pax_global_header00006660000000000000000000000064146255262060014522gustar00rootroot0000000000000052 comment=8fa3c948c14a8ff6668d92fa7cb05364679efc8f q2-sample-classifier-2024.5.0/000077500000000000000000000000001462552620600156775ustar00rootroot00000000000000q2-sample-classifier-2024.5.0/.coveragerc000066400000000000000000000003301462552620600200140ustar00rootroot00000000000000[run] branch = True omit = */tests* */__init__.py q2_sample_classifier/_version.py versioneer.py [report] omit = */tests* */__init__.py q2_sample_classifier/_version.py versioneer.py q2-sample-classifier-2024.5.0/.gitattributes000066400000000000000000000000561462552620600205730ustar00rootroot00000000000000q2_sample_classifier/_version.py export-subst q2-sample-classifier-2024.5.0/.github/000077500000000000000000000000001462552620600172375ustar00rootroot00000000000000q2-sample-classifier-2024.5.0/.github/CONTRIBUTING.md000066400000000000000000000015131462552620600214700ustar00rootroot00000000000000# Contributing to this project Thanks for thinking of us :heart: :tada: - we would love a helping hand! ## I just have a question > Note: Please don't file an issue to ask a question. You'll get faster results > by using the resources below. ### QIIME 2 Users Check out the [User Docs](https://docs.qiime2.org) - there are many tutorials, walkthroughs, and guides available. If you still need help, please visit us at the [QIIME 2 Forum](https://forum.qiime2.org/c/user-support). ### QIIME 2 Developers Check out the [Developer Docs](https://dev.qiime2.org) - there are many tutorials, walkthroughs, and guides available. If you still need help, please visit us at the [QIIME 2 Forum](https://forum.qiime2.org/c/dev-discussion). This document is based heavily on the following: https://github.com/atom/atom/blob/master/CONTRIBUTING.md q2-sample-classifier-2024.5.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001462552620600214225ustar00rootroot00000000000000q2-sample-classifier-2024.5.0/.github/ISSUE_TEMPLATE/1-user-need-help.md000066400000000000000000000006111462552620600247150ustar00rootroot00000000000000--- name: I am a user and I need help with QIIME 2... about: I am using QIIME 2 and have a question or am experiencing a problem --- Have you had a chance to check out the docs? https://docs.qiime2.org There are many tutorials, walkthroughs, and guides available. If you still need help, please visit: https://forum.qiime2.org/c/user-support Help requests filed here will not be answered. q2-sample-classifier-2024.5.0/.github/ISSUE_TEMPLATE/2-dev-need-help.md000066400000000000000000000005641462552620600245250ustar00rootroot00000000000000--- name: I am a developer and I need help with QIIME 2... about: I am developing a QIIME 2 plugin or interface and have a question or a problem --- Have you had a chance to check out the developer docs? https://dev.qiime2.org There are many tutorials, walkthroughs, and guides available. If you still need help, please visit: https://forum.qiime2.org/c/dev-discussion q2-sample-classifier-2024.5.0/.github/ISSUE_TEMPLATE/3-found-bug.md000066400000000000000000000017421462552620600237760ustar00rootroot00000000000000--- name: I am a developer and I found a bug... about: I am a developer and I found a bug that I can describe --- **Bug Description** A clear and concise description of what the bug is. **Steps to reproduce the behavior** 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Computation Environment** - OS: [e.g. macOS High Sierra] - QIIME 2 Release [e.g. 2018.6] **Questions** 1. An enumerated list with any questions about the problem here. 2. If not applicable, please delete this section. **Comments** 1. An enumerated list with any other context or comments about the problem here. 2. If not applicable, please delete this section. **References** 1. An enumerated list of links to relevant references, including forum posts, stack overflow, etc. 2. If not applicable, please delete this section. q2-sample-classifier-2024.5.0/.github/ISSUE_TEMPLATE/4-make-better.md000066400000000000000000000015321462552620600243060ustar00rootroot00000000000000--- name: I am a developer and I have an idea for an improvement... about: I am a developer and I have an idea for an improvement to existing functionality --- **Improvement Description** A clear and concise description of what the improvement is. **Current Behavior** Please provide a brief description of the current behavior. **Proposed Behavior** Please provide a brief description of the proposed behavior. **Questions** 1. An enumerated list of questions related to the proposal. 2. If not applicable, please delete this section. **Comments** 1. An enumerated list of comments related to the proposal that don't fit anywhere else. 2. If not applicable, please delete this section. **References** 1. An enumerated list of links to relevant references, including forum posts, stack overflow, etc. 2. If not applicable, please delete this section. q2-sample-classifier-2024.5.0/.github/ISSUE_TEMPLATE/5-make-new.md000066400000000000000000000015131462552620600236120ustar00rootroot00000000000000--- name: I am a developer and I have an idea for a new feature... about: I am a developer and I have an idea for new functionality --- **Addition Description** A clear and concise description of what the addition is. **Current Behavior** Please provide a brief description of the current behavior, if applicable. **Proposed Behavior** Please provide a brief description of the proposed behavior. **Questions** 1. An enumerated list of questions related to the proposal. 2. If not applicable, please delete this section. **Comments** 1. An enumerated list of comments related to the proposal that don't fit anywhere else. 2. If not applicable, please delete this section. **References** 1. An enumerated list of links to relevant references, including forum posts, stack overflow, etc. 2. If not applicable, please delete this section. q2-sample-classifier-2024.5.0/.github/ISSUE_TEMPLATE/6-where-to-go.md000066400000000000000000000100111462552620600242350ustar00rootroot00000000000000--- name: I don't know where to file my issue... about: I am a developer and I don't know which repo to file this in --- The repos within the QIIME 2 GitHub Organization are listed below, with a brief description about the repo. Sorted alphabetically by repo name. - The CI automation engine that builds and distributes QIIME 2 https://github.com/qiime2/busywork/issues - A Concourse resource for working with conda https://github.com/qiime2/conda-channel-resource/issues - Web app for vanity URLs for QIIME 2 data assets https://github.com/qiime2/data.qiime2.org/issues - The Developer Documentation https://github.com/qiime2/dev-docs/issues - A discourse plugin for handling queued/unqueued topics https://github.com/qiime2/discourse-unhandled-tagger/issues - The User Documentation https://github.com/qiime2/docs/issues - Rendered QIIME 2 environment files for conda https://github.com/qiime2/environment-files/issues - Google Sheets Add-On for validating tabular data https://github.com/qiime2/Keemei/issues - A docker image for linux-based busywork workers https://github.com/qiime2/linux-worker-docker/issues - Official project logos https://github.com/qiime2/logos/issues - The q2-alignment plugin https://github.com/qiime2/q2-alignment/issues - The q2-composition plugin https://github.com/qiime2/q2-composition/issues - The q2-cutadapt plugin https://github.com/qiime2/q2-cutadapt/issues - The q2-dada2 plugin https://github.com/qiime2/q2-dada2/issues - The q2-deblur plugin https://github.com/qiime2/q2-deblur/issues - The q2-demux plugin https://github.com/qiime2/q2-demux/issues - The q2-diversity plugin https://github.com/qiime2/q2-diversity/issues - The q2-diversity-lib plugin https://github.com/qiime2/q2-diversity-lib/issues - The q2-emperor plugin https://github.com/qiime2/q2-emperor/issues - The q2-feature-classifier plugin https://github.com/qiime2/q2-feature-classifier/issues - The q2-feature-table plugin https://github.com/qiime2/q2-feature-table/issues - The q2-fragment-insertion plugin https://github.com/qiime2/q2-fragment-insertion/issues - The q2-gneiss plugin https://github.com/qiime2/q2-gneiss/issues - The q2-longitudinal plugin https://github.com/qiime2/q2-longitudinal/issues - The q2-metadata plugin https://github.com/qiime2/q2-metadata/issues - The q2-phylogeny plugin https://github.com/qiime2/q2-phylogeny/issues - The q2-quality-control plugin https://github.com/qiime2/q2-quality-control/issues - The q2-quality-filter plugin https://github.com/qiime2/q2-quality-filter/issues - The q2-sample-classifier plugin https://github.com/qiime2/q2-sample-classifier/issues - The q2-shogun plugin https://github.com/qiime2/q2-shogun/issues - The q2-taxa plugin https://github.com/qiime2/q2-taxa/issues - The q2-types plugin https://github.com/qiime2/q2-types/issues - The q2-vsearch plugin https://github.com/qiime2/q2-vsearch/issues - The CLI interface https://github.com/qiime2/q2cli/issues - The prototype CWL interface https://github.com/qiime2/q2cwl/issues - The prototype Galaxy interface https://github.com/qiime2/q2galaxy/issues - An internal tool for ensuring header text and copyrights are present https://github.com/qiime2/q2lint/issues - The prototype GUI interface https://github.com/qiime2/q2studio/issues - A base template for use in official QIIME 2 plugins https://github.com/qiime2/q2templates/issues - The read-only web interface at view.qiime2.org https://github.com/qiime2/q2view/issues - The QIIME 2 homepage at qiime2.org https://github.com/qiime2/qiime2.github.io/issues - The QIIME 2 framework https://github.com/qiime2/qiime2/issues - Centralized templates for repo assets https://github.com/qiime2/template-repo/issues - Scripts for building QIIME 2 VMs https://github.com/qiime2/vm-playbooks/issues - Scripts for building QIIME 2 workshop clusters https://github.com/qiime2/workshop-playbooks/issues - The web app that runs workshops.qiime2.org https://github.com/qiime2/workshops.qiime2.org/issues q2-sample-classifier-2024.5.0/.github/SUPPORT.md000066400000000000000000000122421462552620600207360ustar00rootroot00000000000000# QIIME 2 Users Check out the [User Docs](https://docs.qiime2.org) - there are many tutorials, walkthroughs, and guides available. If you still need help, please visit us at the [QIIME 2 Forum](https://forum.qiime2.org/c/user-support). # QIIME 2 Developers Check out the [Developer Docs](https://dev.qiime2.org) - there are many tutorials, walkthroughs, and guides available. If you still need help, please visit us at the [QIIME 2 Forum](https://forum.qiime2.org/c/dev-discussion). # General Bug/Issue Triage Discussion ![rubric](./rubric.png?raw=true) # Projects/Repositories in the QIIME 2 GitHub Organization Sorted alphabetically by repo name. - [busywork](https://github.com/qiime2/busywork/issues) | The CI automation engine that builds and distributes QIIME 2 - [conda-channel-resource](https://github.com/qiime2/conda-channel-resource/issues) | A Concourse resource for working with conda - [data.qiime2.org](https://github.com/qiime2/data.qiime2.org/issues) | Web app for vanity URLs for QIIME 2 data assets - [dev-docs](https://github.com/qiime2/dev-docs/issues) | The Developer Documentation - [discourse-unhandled-tagger](https://github.com/qiime2/discourse-unhandled-tagger/issues) | A discourse plugin for handling queued/unqueued topics - [docs](https://github.com/qiime2/docs/issues) | The User Documentation - [environment-files](https://github.com/qiime2/environment-files/issues) | Rendered QIIME 2 environment files for conda - [Keemei](https://github.com/qiime2/Keemei/issues) | Google Sheets Add-On for validating tabular data - [linux-worker-docker](https://github.com/qiime2/linux-worker-docker/issues) | A docker image for linux-based busywork workers - [logos](https://github.com/qiime2/logos/issues) | Official project logos - [q2-alignment](https://github.com/qiime2/q2-alignment/issues) | The q2-alignment plugin - [q2-composition](https://github.com/qiime2/q2-composition/issues) | The q2-composition plugin - [q2-cutadapt](https://github.com/qiime2/q2-cutadapt/issues) | The q2-cutadapt plugin - [q2-dada2](https://github.com/qiime2/q2-dada2/issues) | The q2-dada2 plugin - [q2-deblur](https://github.com/qiime2/q2-deblur/issues) | The q2-deblur plugin - [q2-demux](https://github.com/qiime2/q2-demux/issues) | The q2-demux plugin - [q2-diversity](https://github.com/qiime2/q2-diversity/issues) | The q2-diversity plugin - [q2-diversity-lib](https://github.com/qiime2/q2-diversity-lib/issues) | The q2-diversity-lib plugin - [q2-emperor](https://github.com/qiime2/q2-emperor/issues) | The q2-emperor plugin - [q2-feature-classifier](https://github.com/qiime2/q2-feature-classifier/issues) | The q2-feature-classifier plugin - [q2-feature-table](https://github.com/qiime2/q2-feature-table/issues) | The q2-feature-table plugin - [q2-fragment-insertion](https://github.com/qiime2/q2-fragment-insertion/issues) | The q2-fragment-insertion plugin - [q2-gneiss](https://github.com/qiime2/q2-gneiss/issues) | The q2-gneiss plugin - [q2-longitudinal](https://github.com/qiime2/q2-longitudinal/issues) | The q2-longitudinal plugin - [q2-metadata](https://github.com/qiime2/q2-metadata/issues) | The q2-metadata plugin - [q2-phylogeny](https://github.com/qiime2/q2-phylogeny/issues) | The q2-phylogeny plugin - [q2-quality-control](https://github.com/qiime2/q2-quality-control/issues) | The q2-quality-control plugin - [q2-quality-filter](https://github.com/qiime2/q2-quality-filter/issues) | The q2-quality-filter plugin - [q2-sample-classifier](https://github.com/qiime2/q2-sample-classifier/issues) | The q2-sample-classifier plugin - [q2-shogun](https://github.com/qiime2/q2-shogun/issues) | The q2-shogun plugin - [q2-taxa](https://github.com/qiime2/q2-taxa/issues) | The q2-taxa plugin - [q2-types](https://github.com/qiime2/q2-types/issues) | The q2-types plugin - [q2-vsearch](https://github.com/qiime2/q2-vsearch/issues) | The q2-vsearch plugin - [q2cli](https://github.com/qiime2/q2cli/issues) | The CLI interface - [q2cwl](https://github.com/qiime2/q2cwl/issues) | The prototype CWL interface - [q2galaxy](https://github.com/qiime2/q2galaxy/issues) | The prototype Galaxy interface - [q2lint](https://github.com/qiime2/q2lint/issues) | An internal tool for ensuring header text and copyrights are present - [q2studio](https://github.com/qiime2/q2studio/issues) | The prototype GUI interface - [q2templates](https://github.com/qiime2/q2templates/issues) | A base template for use in official QIIME 2 plugins - [q2view](https://github.com/qiime2/q2view/issues) | The read-only web interface at view.qiime2.org - [qiime2.github.io](https://github.com/qiime2/qiime2.github.io/issues) | The QIIME 2 homepage at qiime2.org - [qiime2](https://github.com/qiime2/qiime2/issues) | The QIIME 2 framework - [template-repo](https://github.com/qiime2/template-repo/issues) | Centralized templates for repo assets - [vm-playbooks](https://github.com/qiime2/vm-playbooks/issues) | Scripts for building QIIME 2 VMs - [workshop-playbooks](https://github.com/qiime2/workshop-playbooks/issues) | Scripts for building QIIME 2 workshop clusters - [workshops.qiime2.org](https://github.com/qiime2/workshops.qiime2.org/issues) | The web app that runs workshops.qiime2.org q2-sample-classifier-2024.5.0/.github/pull_request_template.md000066400000000000000000000006121462552620600241770ustar00rootroot00000000000000Brief summary of the Pull Request, including any issues it may fix using the GitHub closing syntax: https://help.github.com/articles/closing-issues-using-keywords/ Also, include any co-authors or contributors using the GitHub coauthor tag: https://help.github.com/articles/creating-a-commit-with-multiple-authors/ --- Include any questions for reviewers, screenshots, sample outputs, etc. q2-sample-classifier-2024.5.0/.github/rubric.png000066400000000000000000007014131462552620600212410ustar00rootroot00000000000000PNG  IHDR,4\sBIT|d pHYs.#.#x?vtEXtSoftwarewww.inkscape.org< IDATxw|g3AޫEEQvgmKhQRD.#g$ G)9IIr~vkxr\7ޯ\b0 R1NE/zQ@G E/z'w:~9 .VhhD?^Kg7o78s7HG^{5]~]v ӧOլYD ^-ZٳgW_TB iٲeںufR)//_lRl߾ݤIs8#8ѣGرcٰakQ ___۷Of (p&I8p@sIO5ydXTRZ~ҦMk7oZpDO<1ӧO(8!?0c2dȠs,fݺu_6 8 2?sI @C ޽{uСfIZj& ilϟ߬EILR^DԬYq]]]`I&Ѿ6vUV5o\TD$&~<н{%6p^DGGk֭˓'O/Sڵkhh#^QF &:t\]/TՕ={ve˖M/[l8cǎ%.aÆI ᅲWڴi#F)+)<<\&MҡC8$^dN>mR7n$Y*Toh?^@\UTщ'4tP.]Z3gͫ-[jӦMZf0=ŋMw!;֭ۗ`^q 7|iĚ3gNrN/p6mq$=iӦD Klc׮]K4(z1P ><Ȟ=j֬`gϞ%Y|֋رc; IMMd4k,$ zSLÇ; Id̘Ѭ#GԈ#e\~)z)׉''$w(z6{_uѣ6ͥ\rʔ)SIQh`7ne˖zyr8bŊY4\:t蠀UN/ N%ɝJ,iXQVR 4l0ruw*g͚k׮m+][-Zӧ;8\ !OddgϮGd|k׮ڵ-j9<{Q۶mu=O,XP+VN4ӧOu1*((Haaazː! (E\rJ>}2g`>}ZgΜӧ+W`0_q\\\%K+WN5kT9$ϘԩS:}N:]qSM0A3fPtt(z{xCpBmڴy`0hڿ6mhTMݻw~zmذAғ'OL%Jyj۶*Tę:K.i͚5ڼy;(ƹB jٲڵkB %q҃b[Ew/FGFFjŚ]t<$???EEEI8>vzRѢEuʕ$Uzu |ڷooҽfS5jO?5ڶdXª6m'o׮]2ev!k_?aÆ=zj׮m\֋}I' @;vɓ'M#Oҷ~kl9z:viӦiѢE*W\#""gIh@s(^x큁:tlbUѶm۴m65o\S\̚/oݺufIү_O>5y̍7ԡCi[bV\_:tf͚e.]d$I|'Ol; Kwv=zƍ?~ϯݻ믿Klٲ7oM ^v1UZU~m̟,[L˗iU7oVٲegƭ^Z~~~6/xܹS-Z0~;w֭[Z˗/5-Q'EӮq#""d/_^=z͛7,֊+;tD[ʕf]|Yyn*___b={L}_|amک`ѣյkW=~8...j֬vء7n(22RW^UlYݻwO5?l-v%kNϞ=x_ՆY'{R7'ojΜ9ѣcך5k4zh3Ʀw~-\P}1.q,W\ʕ+5j%KW^&7ne˦}iҘ1c#Gɓ13G*TP`N:PhhN:G***ʤ8UVUժUU^8m CK.Uv^z/_>uI۷ט1c4mڴD犈PvcլYӤչsgX5ٳgmV ,ŋSddU󹹹QF*U1c(,,L>ԑ#Gt9֑iӪv*VMs1X{, ՛0a&N9TREWV맟~RVL*R :T|MK}G&O&L~I/_N:%`0M6Z~IsΝ['OTk׮ԩSڸq:dϟ_|>C3fnܸϟ'8WZo߾ߵh"]~\,Y]&`0رcF>cmݺլ 2) *\Kn߾QF~0+͛7Ox͛75x߿&M$oooQHFi3gNmٲE+Vx /_^>LouIK.ѾϞ=Sum(UN8!wY~ʖ-4ᅰ-[V'N0{ܫݻ9rmsuuՎ;۷QF&iժɅ/dɒ&رمM6K.hLƌg2eѣչs؝D HtTsxչsg?WZJH.]|rLlx.]TىbJKX6mژK@@/^hyjȐ!&oݳhܫ*, 6,ނ׃ԭ[7 ^4j(s*VTbr+Wȑ#&-Zhҥfy!,,쥂Wٵ~7L+O< {zzjŊ*UE:ɓ't5egbΓ1cd%  ֐!C}xﻱQFrcWX=c^UNO6ͤЀ>}z9v- qx^^^ 矛DZYyy v*lRժU3{ܿjFRIt)=<<4vXs4iEc9~Fڷoϑ /W/{6m(**1ϟ?7-IPʫxfpݛhٳ[nf-o6m2|ʚ5Ѷ˗/kܹ&LjoXBׯ_o1͛77{̿ 2DF֭X///w6k,~&SM74{ܬYnU g}j^`['%@dɢ ?P͚5%Çk&_j]frs{!wfaÆYtҥKM>јH\2sOOO?qӧOWddqyGFFj֭fDZ3w߿uY9r䈷=W\:zƌ*Upz7ճgO=zTY Zn%K=nڴi={y޻woI QuujnGh ѣG͚;gΜfcUvwĈf/IgVLLEc|_~{}c,aB.]#G}'Oj…*S,͑ZtY``֭[gQUVɓ'/=K>:vh| PbŊZ~4qD(Q"c.[,>7n4{^KW6{LttM[Z5ըQ_wEڵ+u&xwRJ/]dq\YfUjK:t`1-wy֮];eɒŢ@ҡ0[5n8;wN>e˖-Ib>}Z.\Hρ̞7$$侏?̙3GYw9Ң(`0y>dȐ%} :Tk׮5;γgt]YAVe5zh;vL~~~f9y݃m@D `*Uh֬Yy6mڤVZæ1lH޽{+cƌʚ5kx{{+s2d={fQ?6ofTxqcڵK&ҥKokv<<<4j(|_xxVXy>}̎ 샢fͪ:wFiAAA]ry ҥrav˗| <˔)zหW*Zhrz^{qv8EoOOOu>(zYlYY'!%JД)SѣG9֤g3f4hvOj…;}{v,Y$8?oKy{{%hWh?cGnݚ`Mj]t)ޝ@I;K,<./WWW 4(-=~pڴi]Ec͕?~ġf_њ:u͛og- ۢ<}P't>K5jΝ;o|_Bw4Yzz-Cյk_sm޼YZ2-_>>۷Oϟ~}%޽;N>}X^DrUw1 ()+V̤~E`NME#F=&""],>ԏ?_>}ڽU@sRiԨQfwzuX" `0ԧH"]MrI8$XQ$)yxx\rȑCٳg7;v@@@GJѼys/^q͋?ĹW]7k7x<9>%gΜ޽LEFFjɒ%qk yQ'ц/㏊C6x"""WNx\\\TJcĉfK6l_ 6H2~a˖-޹UP!̙\8p3fҦMk֘gj˖-駟tΝҦM]2E(z0eWӭ[n:;d;w9JU V%c`ھ}Ec}zMڵ|||7sLi5h rUcu%… ?~!e3(o|SNfꫯwyޢE ȑ;Nä#ƍ_tСDt)Ѽ}YƦŒuQƍS*UtY驁=?,I:y*U}ltګ;ِ!C,Sox IDAT̙?ƍho^ϟ$O*[n޼ia_~~~5c խ[Ws-ZTڵ3{ܫ"E^z쏢8tҙO>QPPPrƍDRرwNYr$M8Ѥ3{l}W/=ԛoi/[nVkYTx!cƌyYӧOe+W.Oy瞽kƍ/=H>HֽիIc@A IBCCѣGIxӧOO>Znŋ>Sg}f~ &˪_5l0_OV>}z͞=[7o8gԮ];-^8N۔)S,*R<~آ<ý{C㚲KU&LPDDDי3gV…͎oJR˖--&M}Q''O?~\M4I̙3-O>QM]|EL4ɢbbb4h E2eʨ哐bŊyO6guyѣg0ԵkW8q챏?{ァiرj֬i,޽{q}9sqձ-AD]6qM6+s?;6m9sZ/^DrmVztMhʔ)EذaC97n?աCM4)ν>|ԩٳgiK.VXaSXټЮ];UL=|P5kԆ Lk׮]q (`)-.&&&G5cҤIo~z#o޼f9poΝ;3k˗Wƍ-ۧO싢8K^\\r5k?nqgϪaÆC_ʕ+-1|+Vq111?~jժk*,,,N(:tHzoN)SXT 2UUzu2fyKNk֬QƌnZmڴѮ]ӧOm65iDjR```>iҤ-:F޽{jժ._lXI5j(G4Gdd>3M>ݢϟ?׻ᆱ 6\}Uƍ4 jٲ[]rEu6lؠ GqܹTbQƌ71 R l:-R^,?~ 8P)h[nСCocǎD_,YRwz'R``jժ[nY< .ܹsMWPPP=6L_qMqFjʬ15jЁl4ib=W*^rȡhݿ_/^LpNWWW-]T:u2)u9׆ lr|g,YԨQ#UREEU TLeϞݢBBBt1ݹsGGѺut59Sҥ?~e͚U+V4il g<)R;̙3t!SjĈ6E/p"ǎ3wb˧ҥK+_|򒋋BBB#ԩSq5lP+WT֬Ym_@@{=]r&{Zh#&&F%KŋMfi&Iٲe!\\\4sL}&?~&MYϢEԣGƮ]Vm۶qF*Tn'O[oeՎhǎ*W޳g֭kRߌ3ڵk=OR&MGɽ^z_~w5>I>>3 6LnnnVBR}ڽ{5EǏg}f.Ç&ϗ/Zld4iDP۶mu…$#IZxڷoqe/.B iKj:uFOon(xq8wz+WNuQ5k,rI&wﮀ9Ҧrȡ]vi5kV^Z ^/tU>>>&8pݓw_˖-'NhĈJ6m(VG+ >\SLnnn۷>dƏhWWW <8II8ƍy/_>-YDGUʕ%S0ڼynݪ5j,~|4~x]pA/Vm61...8p._qY|ϒy{'ّԀ>}zԩSuyS6?שSTR% ˌ9RwVٲe-.]:mV-[6go4n8ɋo iq8ǏB 9pĈرc;sN::qݻgRӫ|]5kʕ+5~ٳgڸq6oެ;vfԭ[7KEM,Mw=(P@ӧ,X`Ǭ'$$D?l٢={$1%JP޽եKw>秥K/5!W\Y4h6m$6mJϝ;w~vE/p2A&LPcwuYƍp߿P`0(}ʘ1ͫH"I~bbbt=zT/^իWu-EEE)44Tʚ5gϮrʩjժz7hgѣw^˗OSb=_|ʙ3gr(IzN>G*((Hׯ_۷0e͚UYfUΜ9UR%UZU JaWҥKzٳ+w)⿣`Pٲeuԩ8mK_e#JmQSXhzw}g9H]R֯IСCq̙S;vLlQû{VX~(OOdE/8s*""gL[`G111u넇kĉX ,jժiƌ<5jҧO;rOĉuM͝;W>bbbԬY3>r~wkq|׺sKϊ-$y~\ j]矪Y"##վ}{-[LiҤIRu֩M6F۲e˦k׮tGŋUB>sqqy$N`>T)IZj5jR1ۼysm_c U6m|ݻw`SPPKvڥƍÇɔUsۗ/_.XÆ uɗ .)S$Y~ p!@[dwo{ ce˖͎YNJҙ3gmwqqQJt%dɒI&HP``*TG%د\rڹsgnRիСCfK6~Wխ[7 )$(u1т$8qB׽{Y[o=&C ڰa/E/$2~x$WWWm۶rww7ɓzwt{ 8P&/^8{/ )E/$pYM2ETL:tH۶mիyx 7OVݺuum{j+VLVR,YQFѣ*Wɉ;,mذ!NfjѢ"""-^vޭܹs#TΝ;Z|ۧ =}T3fT…UNuA>>>ɝ&#^I(*** nݪVZٳgFK,ݻw+gΜI"C`6lM6)]tF/\u͛v u(|X@ аaCmܸ(z,D `^) / Cr')**Jо}}/Yvޭ9s1K@25k,]zլA }xŋkʝ; 3H](z$VZ:w$)cƌݻ7nB Ç:~֭[;v(&&&޹E/dzi޽jժiʕ+ǏרQk׮xkr'؂W͚5{x ^T|yܹSӧOWڴi9w֭۷o'I);,88X ֣GSN)O<&?ԤIݿh;;3b-\P=$kά$UREW 8#^vq,dɒڻwrmEڵkP0;v,kk ,Xmۦ,Ym?wUݻwi;6l`ql=p&VdddVojUDDD7n^zzw+>|X+W*U1 E/; ygϪVZVYvm-_\ڵSLLLv۷k/=WkUl ՝],պuk >>>>Zl\]y=#77޶m}R{Fe5?QƌU\=}T]tQTT󻹹r2 Zn*VV`ACO8v֩S8:~d4iHO>Qn:e͚&1R^v֡Cyh"9RFqEIO?TAAA/p4,gΜٳѶiӦGu{n={V={9rh>`lSjf͚Zzrm>T*Uty)88XYdU);&NoTB-]T111SmVϟ$կ_p*ŋu]zUTP!URE 0kݻkɒ% TF-[*M4qڏ?={T^=rH(z`0hݺu:u8...jԨ&LU4j޽}TfM.]ZO߿_~ӦMYo P0{Ծ}{ouww_A4whhZn]vY^uRHDppj׮mRK4x` 6Lmۦݻ[g2e}v ^)QH@dd7ogϚ=v&ҤIŋk̙ʐ!ٱZh!˗]t)S8z5ydy.]:Ϙ1—$ 4H޽I1J(~I7nTLL83G^8+QR?XK/ܩ@&L5iҤدկ_?_zbbbt1} 2U@-^XoҥKզM+WN^^^ʕ+*W~~S@@6mj 8G^8+˸L0a&N(I{%sVWCՌ3$sڵkU~}}o߾^z%rjȐ!o$W0 ϮKvz'cFQ6mZmڴ)ނ$̙S?&NoQ_l+:d/'C ڲeԩ|II>l٢u&cVwJ>#ծ];1...7n;C /gX8+QRǿto /)y.\[ 7rHٳ{ _@2s a ^@ @ @j/d>s[ `PLL$z3۹sg _@2r ca^@27n\/B @/dΜ9oF4| 0@E$eΜy--|EGGkŊ86yXXl=ٸq_~eʽ1`OB`0h/ϟϟ+M4 jΝ;Kw83fPttO.777]rE|l٢;w*>lyXXlz Y|G/cΐ!nݪ~;?[2M/^TB|x _THɓGRddҤIիWe˖VWUҠ$W ^3gUjd r2*Yܹ`>}hVK/|^pWI;; p2ǏO%I}~7%vǗD 3WUb`GcǎɓcΒ%~W ^Rgx!sQUR%vוeUX1c/^X={`>gX8֫N/N(xH-̠A7xCTHHN8%J=5lP׮]:v=TJQ,ԏ>(zI`0hСq ^i %r2WztAUVMTT)޽[%K4:&((HuֵI+[lN 03WR7+xC   6L3f̈}o@rs2A...qߺuKΝ;gt\"E{n˗ϢoV3 ^q:^;$b/1V\riϞ=*U@ժUK1cbbԷo_ ^u^;$5sgT_Rھ}|}})x`Z^%vz6_kǎ8B&22R-[ԡC,#W\+00;6l/`&G^8֫N/  Yf>[o%cfׯ,X 2h֭z-Ν;W(P@{Q- ~^pWɋ^P8 I&i'OiӦVz״sxw|]rE7+::ZsUxxgz(z6`04x8;vP8 Q&Lx٣Gk\ݻjѢ֭[w8zq^ oXEkٱ^*W@\B_WDD̙3_Uj,q-;:wlٲ}z֬YO*M4+*X_\|YժUݻwg;`>G_8֫`!AiΜ9(xHLppW .HgG`Ǐǎ/` G_8֫; Wڹs'/)yZj .H"ڼy>|7naÆF򎯂 m+*e`0>x;wRJɘ /dÕ9sfըQC5k&Iʔ)6mڔ䅯>s ^aXR.75wgڱc/)31 TڴiEDDEھ}ѱ80} D 3WR7֫^(xHM테т$KN?4ibѣGjРgQSNQlԋ* GHx!Wڴivx:|䉚6mjQ111;v$ ^%XW0 8p͛EbŊɘ ϫB p IDAT @jzz HC @/d?A)$$ĪyҥKM6ŻѣG5yW%?k͚538z^.a04`͟??vڥ2e$cf#1 ֭-[J*iǎjNKw|iܹܹreUr caJ}A @j/d&Me˖I9w}n;c8p@+WѣhrWUN/&BfժUС^}}a_͛7׎;MV5kThh;&IU\9b+*KLLz%K> r2V:uS˗Ν;-[6ܺuK VDDI/^ݻ[p6^pW_LLzR+GHB&((HM4%IǏGʕK:t0o~(xfr `J(z_kҥ(xHLhh4iwJjԩS}z-M>ݪ8q `r *x.]:3LLLڴi3gΨxڲe"##u1-Z[jwTTb b-֨K"1D{KJWc^(*-5(bIٝ.lly>9-3lg&puu)S&[VhQر...zAdk^` Ȧ) ^Dd1laB#F@׮];j֬cǎ-rvv\rXr|988`ӦM(S^m"[WDdXB Bf~zi/"2Wyɓ'hѢݻvz OOOۮS.^B ˗زe ɓ'cҤIf^`> &i =UȈㄌ*c_B)R^wޅ/d;c""Kze!BA^ŋgEDf2ٕ*U*ץ۴i8 ǫWKWPXR^Y/^DDDDdS2?SVxq9rNhMպuk|RfΜ)ܢE 9HdSXR^Y7^DDDDd3x%Lr Ο?-Zٳg9`H,8eÇzDy^DDDDd  6H24RJ(;kQ(p9($$$ ##e˖76mSm_ؾ};jժ]3gbƌȜi߾=߯#1^Iݻw{F+<<ڵBÇQHIdnXlC/""""z ȒXݻw-[HҤzLj#k۹_...ѿ,X׮] pIB ҥK(Sn/FYs2%KoŜ9s0i$x~}͛g`EDDDDVYkIKKԩSpBtfϞ.cs r㣏>\"[dT_#%%|e .xxx9c-Y-B?Yky5ksx@TT={")))cK*'NF:쌍72"Ғ+SIMMxɓ1k,Y9<:tׯ_Fl^DDDDd27JJ(#G0""c2hܸ1nݺ]6??? 22ك\۫]6qqqq֭?kΝ;ѦM^zeJǏǂ 9s&LbpϟG6m >D% nR^&^DDDDdu4^GEʕpdDDYLFFڷoÇsرcao}љ]xYVR'N@…sԩ;w.Jcjժ 6jժڿ0"fʔ?VZiK׻|XbmY+ЋBi&i/"2WH=[W#G 888 ڵkɓ'# @cعs'n݊'*jsD"KzEY1"""""P(,Ld\\\qF#>Rݻwzejl|խ[zRK?QYte^\̍-M-[W6mxUɓ1k,sqq6*V,c$2'WC/""""8۷D'/"2W6! sIKw .>^2G}5k4^5u*3lc$2W C/""""( Ȓ̛7o_|)XU ))I>l-+seR 6u|DyrЋ,Fzz:2ZlY^DdluBt*̙ :t(TEFF>-ze2eԫW~)f̘-[HHH{|J3gDttmr~X"""""3}bҶ'GFD-OȔ+W'N_räIdi  P+Mdl^;P(?3/2 +ҖB 4IKKC>}_Ix 999aƌ8qʱQQQ(S Jv777=zT{\t kݻIdk^Y 6h Kɾ|+WQ`h(ezE=li ;̎NǣYf*>&MU{yyI&INNF6mj#}Gdk^Y3lڴI㒃'OƬYo޼'O2777ٳ銡?GFD5OȌ5 nҸĉ}ʶoF ԩ6l`И""";udP[Dƚ땵ӧ֬YNիW/.]=>cxyy4www۷Z2"m^>xO/""""2;iiiݻ7#mFXX/"2;|||b ѪU+$$$}ؿn/FBd?q8::GڵkmذAc Ϟ=CuٳgѰaC ȴXPҋBZZzꅽ{Jۼq1+W.FDN!`gg'=OHH~^l5j @ضm5j|u~g}FDDuԩL뫌!s\6lÑ???lڴWKd^Y[nr労mٳ'6lWWW@WFt OɁWzQcEDZ'dJ%tI&q@3xA0Jv{,X@˔)mۢt(Rw^\v PdIbŊ:XkѨ[.?~vnݺ\튯9s`ҤIZ+>>-Zݻwxɰ^\zQRx+Waaa XҥK1bxxxhܸ1mۆ}ʲի1|p{f͚ؽ{7} ҂5+k7xÇZU˗s5j9Db2o7֮]gHHH@ٲeQ^= 4ڵQЋLZZz`i/"2W!_ܿh߾=;whDEʕq-Z.XQZ5uۗL撆퓶1""se2BtAkĉhڴGFDze 6m!C`С? "##agg'{_x)^}b۶ms{{{m 63]իW1Oz%"""",-LȬ^Z x 6 ϟG|82뒒!D/#җ-+Kh"ٳCJ˕+g x{/9_ ȔXۥK}vy5aT^]帤$,YfBRRRvѱc< t[H)))ԩJ̒-L( ̜9P^=^QlYݼyǏ70رcѪUM/[W޽{6m@T/ĪUPreٳgF?} ȔXߒ%K{ 6mNxok? .vj ;f! ȨRRRХK>|XږxyyyȈ 3g`޽9s&D 0vxôhCΝ!@jpAGzehٲ%?+VƍqIDGGh@Uw^dJWOE˗(]4.^"Ez^bb"zPbC^DDDDd4 ȒpB ׫ ;v4,Ǔ'OPfM|RP^YKbĈjի1x`|򈈈L|) 888=zooou0`IKKC߾}{nM|qyC""""2d^Dd18!t?w) |L<2ˠT*g^-ZΝ;y42W!""?JvI1Riܺu <L|=|e˖=../_>[m6tM~S/uЋd.X"/"2KQk׮Mׯ_m۶ٖ"`ܹ Sh޼9]fQ5` JC AbbV_x֭3XRSS1h !xI^QF!** ;wFHH<<<>˧s{NNN_ B>5aEDDDD 9"mX"='dryŗ+)) ;vdſӧxGիY+o|Ep^dRWm޽سg͛7޽;n޼ ͛7zoumTV 6mһxO/""""Mrr2:wGJxℌrǗ;ۇ?#3/[,XBz<2tWnݺpv튱cǢ\ry&~/e˖8x d/3"`2oɨZ*>|C\\>}ŋGzz:=̙za߾}ߐUŋ@^DDDD$ MWXXJ,##"Κ'dӱc8q(VڵkΝ;\M&BbÆ jϟ!!!hܸT1ժUѣ 0'CK.Etts .CN:*YkWӧ_|]ٳgcԩ6l/_n!Gؼy_l%Ɲ;wвeKDEE_@:t 40Xk"U ^Y-[O>ԯ_͛7j*( 7nA}yu͛7UkbEDZ'dbbbЬY3/ B޽WXv-s<ܖG۶mqỶ+nXh}B|7M<*"^t IDATY+&O3g`ԨQXlv'''lٲCR4oWWWtIe1zΒ^#kIMMEqm@ձg %%h۶cpfhB~^1Xk"F ݗ|ZJJRUDzeY.]={`ٰw ۶m|YFƍ,7$""""d^ǎe^%JȻV?={ETT--Z`(]t^Hv7 'OָsرcKe˖ԡze*AAAׯ,QN}ڷo/;Q_:u¦M?~iìފDrbr/uk$''v/HDDDD6%)) ;vT j֬HW~p<ӦMS{M9D"„̉'hӦ|+h ݋^z!--M6.]K~~~ h۶-Μ9c⑑1B2w v͛KW˖-~z>}ºu0x`xzzVpp04i'Oh1c`aEzeN9m4QdIqѤI:yHLLB$ڵk% 3xbѧOQn]QH1gϞa l^[% 3,ׯ/vZǦUV2ea͚5EBB6l4}pttosZѣG (O^O|A___[շo_# 1g)J*#4cEDDDDdle3gtؿt% dpTzEʕ1tP}_3fDNٍ7_{Z2MW… z}aoo/ &|-}HcZ!xQ`2_GŊ3Y:tqqqZ[bŊ"**ȿzx|hU/ &J,)֭[p'd&NvB BTf;~RPls V*Ν+>Si[۶mMRΝ;wT&|}}ʕ+T~A*Tze ^w;v^~WϞ=u8>gggq֭\9y$/WkYzojԨ!F!ƌ#>QV-é*UkկW^^B0"""",^111y=4Rpp}gy=" cǎihx IIIK?6=z$˧$… 2NrrZ;OT{׫WĸqT`el^|nݺ&b ,UO< ѣAc}h۶ƿ~x~rr]6/29+u.ŋ`ݾ}[L4Ixxxdɒ޽{Z[eB؃@||<>cKjժÇpy82둔+WbܹqQ ~0JD`ʔ)={ hٲeJ>7n͛7k֬4hm{QHm6l@TT\\\W_iL29rVc+V ձ?3f={ƍ/_>,XÇ8mΝ3ʘI^LׯQZ5߸w_ܹsuԑźut#88B@R o>L۷#::Z۷oŋ`h i|EGGk׮HJJBҥqitQ~~~3g߿ѣGAcO>\Э[7̟?_+",, %KS^nDDDDxݺuK$e'Xzu'2y s!~(^(QEDD___wPD qΝlU^]]tɵgϞ GG ȫ )\\\J{hdzY&@bB>o߾SNjUT~ʕ:ѣG2nR)zowʕ9?ɰ^Ç /^ܰ0Qt?uMJ(Sʹ*U2+21""""qqqqaÆ (>>^TPA\ZJ־21˜~왬gn4ɫ 5kGGG}vxÇxzjtR5;`?߃+K.W=M2E=3F6D|YN /==]dddhe-[S 4ڵÕ$%%:udСl}ʼݽ{WmƍӫѸq͛7kVr6ٴxkgΜծ]K,00wUoųgd+%%E9##6lLk֬A?6QNjɝ9Ocs j ϟ?'f͚믿ƍ7p1,_v۷/ .m oÓ'O>ɋKctըQ~< iiiZ pٖvssCPP<<7d_6.oooO*۞>}S(G$7+'dooʕ+V|sN|jغuk0""""Ih۶-2 渿XbUzu瑑Xpl@ѢE%11Qֶ 9s* UTGrr2\"=vZ!pYxzzt ˗WhQh|޼yq_|ƍ>۷ԩSqq9.\ƍ 55Us˔)|̙]CUU*^O +åcҤI(\0+ٳg/K.!22Πl2:UN_l@׮]:zٜٳҶЫ H ͚5Syf͚ٶ͜9ϟKDEE.:y9!w/OePQQQBH7lؐMvޞry7n0vuoVXj.\(}O?xصkW3FNdd$V\y*ϯ\y4駟l+Plip ]tO?W^!::SLA׮]e n޼)پt8o-\0s6mڔc? ӪU"V^VT\Y(JYٷo_{-KۙN8idmzY1M׫Wzhg ѫW/#GLprrZ}%"tQNiB)S|~Me'k8{ptt*zիWe闲k߾}߹l_@ӧ UOIIReNʒxϟ!V%DRRRgddڵkkvvvbΜ9zqd' |j8wl}sݵkΩSd5ee\xe}x{{˗~e.+@̝;WsF֭[G ł ֭[O$c2_|)ѣG*V/6x\%KD6m n+1""""" ,BM4qRE+%%Eߋ!;;;Փ- 9A bذaFkDD8w]ׯE``С(Z...aÆok7oVJ*%o#Qxqf9z״ >ʕ+'VXq)fmIm-ZT$$$zR'NzE}cƌ믿eʔWPA<~ؠA+u}QN_X&N}Ϟ=+a0' īWDݺuU>6nܘdZM|)J1}t'2NNNbFzdmBwxTV^ĤIĺuDxx,KӮYFyvlBH"Kooox 9QFiGEEGx$^}wïUV~mVj履~ WWW@|z_I-+T*G}$J*|ĈbŊXg+JѲeK@ԨQhK4C/""""+"ZO| !ĕ+WDÆ uV8{^5*k1$ʜl(Zhڴ2d;wصkyf~oV]t%ۄǏM<ݶm[G.X s .,&N(>| i&i"핸Ν3ůXk2w h]n_^ZܹsN;{ݻ<^/>{dtWmժU*>ׁ}5G?Zy5 e%^DDDDu>|.Oծ];ѽ{weKTcǎ 777m;99͛?4$+k7V^WtA3F͛7?CL4IZNIa^*J.;tO uB ݻwgkwذaZogg'|}}E^D߾}EN >FgT^z%\u֕~"44To^ ty?CB={ژ={ίĉ?9֪UK y V+ ~>?_IMMGΙ2e/l !"EGGuָr労q Apd/_bȑ9s&ʗ/HOOǢE0i$( 7o^fdd͛|2ooo4jzW IDAT"uLٳgK-[7m4̜9S>_~%JFn݊ݻ}kƍptt1bIs׮]Xx1bbb4SN~6RcѢE?bp[?RL%,, ֭òemױpBlܸ:]|yЍ7PF ( *T}4*UO>U{%K z;t+9y6mV{Q\9|r>}y3g4+#2+cǎ\>W|m޼{ 4^戡be>v-M,k|ݹsG*UJ\zU~__dluBF%K޽{ ???0^˺tڵks=^PVZxe:~ GGG1a.?kZׯs]YӣB b9} jѦMƪo={L5uT̚5K>GGGT\Yk֬slѣGz*\˗/̙3x𡴟2޽{ѥK̙31e[j o%J+W;w ""BzгgOAcGPP5j ,,̠ϧ)))(_<>} [n_+VĔ)SЯ_?888H۟={___$%%@xNɈ 4hlق~=z@jj*vڅ@=G{|esv܉K.ݻx9 .bŊN:h߾=6m '''C_yԍlWx5mڔWx7oވRJ\a_K.1u[м,~YTC &ӧ+Whu^NKf>˧['O^28qܽ{VxB.]Z+'22Rl޼Y㣣EZ|C/""""3)~2GIl޼Y+SnWnDRRtR-~ M(uB&...-M>]vr u׳gDɒ%xOzO~7u W.ǐIOZL-keoo/n޼)k .ޣ}b̙p:_UT[lf͒M>|(ǰIG\L)k@GRR(^ *v؄/HWȺXELL쯁W$ʖ-u NiK~ ̔Yf ذa4JŊe2|`E`2^...m͘1C6H>*U '''lxerttϚ)xFY"pR9{+%%E,YDx{{~e>&L zw-[=zQ@s_^z뒟x䉡/f؃΋/ЪU+\vM֬Y3߿^rq_DDŒoݺu zln:888e,dLٳgK-[T{ァoXbZ9sLL2E |'رcG}=z4NhҚ+S B~=..}d﫯jl`` bbb#Fݻ?s_K,AttA%U8pʿ7n1B(PBÆ u!!!UwG}Oܶ-bEDDDdf?VZ6^^tAAAFnݺcx1„ݻwq!̘1CcȐ!:MfiۥKЮ];ڵ+uꏴӠA7nĖ-[x@BB3Gӱze LG/z˗/ҧ;Əx5͛NNN4hnܸ͛7zZ4^"C^=l[p|FxB Ç5_nBV_7oD&Md//5#"""y}͛sIC 7dQ︤!.P(TϚ5Kz֭BT*ŋEƍȑ#ׯ/Qzu:dkE_ӧOӦMS=z4{*&M$J*eВ^*=~xC^iZ땩[0G֭ٳg ;11Q+VLZT*Ş={|՘ 3>Xٳgֈ-[,ix_b߾}"==ٻ(m. ҤXbcbA-F5j~1jbѠhL4jƆX5*"X( /ceβpkKvfΜqq3gիW/7o\~X2^f"!!kԨ˂UVMx=c˘ӧxA(2r;uǏ^ߘݝrQ)Be?<ժUXme2msJ*x13ZJhoɒ%z > ^hj̙3ܹsgE ze^d2/^\e;ʡ)Rxyyq||}D LixVZaJC r!$S FEE̘Sfdd()  ;;:ttB'N "eI$WT9lllhǎԣGJHH ???ɳ.22wP;Rک*{ה9իhVU~46;F7vŋjcܸq³V^Z-ZЁٳԹsgu}ʕW?ze~R)yyy\߹sg4TET'NP2eDE2uPة+--] R~}~32pذa񕝝k׮~M/0|r\\+VL܎?׭[}3f ِ!C4^믿* vssSAw[N}5djLP ׫$˹m۶LD'_~ .ӧ?u痿??^B#F0\=z`T&M2}m^=zeƬIII S\+[pW^LHYծ];NOO7u@sb_r7oŊ㤤$u۷oGFUd:uwޞ;5j`GGG4jRRRH222^{~{ T .ԹΞ9sF! Pv\GAW---gϞͯ_γ.==ׯ_իW+СGDDhݗa1o߾ `+++&"H$uVQPʼ bccgv!B/yBB&E /&"6mGFFSd6lؠw^xBhhK$?B \J<ﱲgiӦj4h/_֪/ׯE ZYYիW>e_̕L&{rƍ ڵkgΜX .8p>|8 yd\D j1c"B/xYa۷o3g"b32׬Y DWd 0 lZCuKxxQ~~~ Sk֭k.Gy۶m,նyMgiZӓZ6M6FPꕥq]~v޼y¶}dz0eh߾x]x?ܹm+99SSS0`/ G,ÇyŊܫW/c___8p XoܸUb_ׯ__lTa y r*% qF^ ĉ`n͛\|y([j֬ϟ?+ ʒEGG44JNNf777&k׮tze9BCCUr|EGG+wy]|Yx+/ '?^ӧ]u1!777̏(D0 r93F޽{MMqx(ɸUVJߣ!CQ͛ӧD;6+;ްaƻk-u;w9sL}JJ^L_Zjyꌳ3CСCLD\t<{Πs,lzQ\\0uVұcG^`ҤI{VlY^x1;w\5J+wڥ8ASeWBd "E0OMѺ}MСC˜m۶֗-[T* ںu+)SFaM2^J: ̬YhFr;w\.71ݻGVNJ'N`ڻw/xB$ /4rH322[ntĉ<233iȐ!`RUXʖ-r}Rn$Hhȑ#JOOOF>r)11Qi^x{{ƍ)22ƏOvvvz*۷/zd_PJJ uЁvMŋga^۠A?T~[HHy{{իiŊԠA:~~Ȑ!deeفԩ@A Wq/ r 8p徒S;#GUxϞ=+Qa+O<7ݻw`ݺu7j(YveFv` 5k0ŋ!x֬Y\hQرcZKSED666gQl߾]!⠠ j>}`@^JNN`.S[P^,Ⴈ޽{1mۦԬ666||WA  3Çr45a@WquѨQH.4a6mɉ^|w_e)wN:ENDDTH}мyݻw:M)SL&ӸD"UVѨQTnFDDdccC;v=zܷ?7nз~KǏsu҅ǎkhf)wrOiԨQvM63.\rи8>}z~([ڴiu=dr:!?~hipЌ^eo>^hX>M2%ߏs6m{yy+7i҄.]ʩޗbbb^,?֯_14bf`"bz d^DĥJ2I&1D"ᐐy)_c5h qu^"ҥ ;88xe4_C Q|effWD fz-+ˑ^n]#:%___zZ@@޽SZF)|UZxS>ʕ+GL};w׸8;w(]?yd RM6tY^ ͛7yޞ8@mڴ8/y3ԸqcQL]zer.^+V=xJ,)qH[l ҥKDkt;K[FU1B:////vLaP[z@… BUBڱcy^|I'OTѣG~F9pVTɠVPΜ9C͛7W~͚5 $[v-/>|XiEDN]t'Nr͛ÇNoq^h rY[[S͚5^KIII&z;>|(j^P֭)&&FxW^ mR:u>mڴISRR`kݺmb25jԠ:uPfҥKԷo_a֭[Ӊ'TR-"]'!9tEg777:zhgQxx} FݻwGeT=zmөk׮Muؼys #;;;۸ѣGx9+m^Y ym˖-"1%SuU>0bŊQxx88q><===iƍϗ/_0.h߾}T\<٣r?[[[ڻw//̜9SeVZѲe˔sqqpjذ(ER4A*W_ѱc n?%%_""*Qzjٲ/EL=hтn߾U{_Ν;Ӂ $6 D*wЁ+tυ?_pAN*QLڳgY[[+~eюiժUDDTjU $__tA1%J/_/czUqF/+RЀtn7>>իGDDD'O6?^"___a:"^ٳ4m4w}8::җ_~Is%777{ 5nܘ5nDM4%J==xnܸA YYYѾ}sڝ> 3j(Zf խ[]tzяըQ޽+ܱcG:|hz /_^b())/.1@ 6lm۶Mz1K. Be\^ :\.UԮ];:~m+ R222ϏΝ;GD.2eʈgB/\T^۶mS9 ЬY4NVT)ڰauQv߿OC !Hhʕ4f 2ӧL2TjUx UZ޽{GDDw咽={jߟ9ږ-[zcC?S9==]3Ә1chJӁM6:[jܸ1LԨQ#C J^f۷oM6њ5k0+󖖖FG7o5ժUNۃnݺj^:OԥKm=~zAW^^4hmذA``fﳻ;Ӈ߿oꮁ'NTx4-ּf7o\c|aĿ(l;c|ĉ|;ɓ'ޞ9&&Ơ&O,G:uX.kg̙y~ҥK%k m.N&СCUX>u:uE; ӱcG&"vssM6;&ze޽{sŋ+Vl e+++5jīVDyߋp%[n^!D"˗k},^x1;88|J*qDD1LNEDܬY30/^p>vҸו.]>|hPr?~\h~YXi;;w"2"S+Ntt4(Wݻw甔Sw ߠ^ԩ{W˖-9))I6WXwŋW+믿o H^*11;WWWyvvv_111~1^zrw 6T;͏?6uW|;vL^9KjѣGZRT- j0>^PEFFrٲe>1c{7l0~6AAA*\\\'?ޠ ,c"b[[[>tmr۷o9<<>fW^||} $+󕚚*\$HxʕJ;u+WNK.ƍAZ^[ .x ^P *Oe7n bUч>|X^ZhK+ggϞq`I&ZߙveЮ]zJΝ;^}]H|yNj3 4ҥ0 SwdPӅf޼yj}1רQC+ǵkxܹܽ{wd\2wܙgQ ƃ eLfkkw g},ZHЍd^VZ֯,RM4#˹o߾immͣGXmm߾͛7War%w˸L]@Ç3ч;`/^h yKJJ>GtA;MVZ_`$PDFFR6m(>>^x?͛7 {X|9M8ʗ/Oqqq:Mj۶-|2:DB˖- &U̚5ϟ/looOaaa/?uPzz?@>>>{˖-4p@"";w}222hgK$_>k׎ʖ-Kŋ8ڳg]tʔ)CN"OOOΥMҋ/ʊjԨAo߾*֖KW.S>}T...N 648hm۶t j۶-;v0 +O?7|C\BjDPٵbŊt)OE-%Sn޽{\L;,޽{XbzTz@Y;T-[Gd2]ކ oƌz;gU?|PVԼysu3{*mmmŋ}<˸L]@;Ϟ=UlM޽2u:uJx~wKHHEqժU5!Cpff@W!==L20MXbLDsiҤƟӾp-T-%K1cf|5mW>1u9rDxڷoq/H":hze9UI$yѢEݠޙӣGa5k_߫WK.S{ëWbJC#2ud2nѢ^uƆ |Ҷo޼Ç?W+++:Ŀ;?^6˖-SZo߮L&#0a޺uK &M$i CY5tP^… ɓLN:53g/0:SȜg󌯬,ްa(Q5k 3'TV899Ys.LBzeTQvmNMMU^&oƁrJ~}6A7of"RJqݺuu/9 wMa 8p 駜>aaaloorcǎZcӦM}U 9q{SfM~(&&& w{yyy ak׸W^.t"^n^x[r>v3vݻwÇowѻSLa"L|dz}G͔֩sV\|Y(ȑ#9X^`^Æ Ce޽Ea'''>{,337nܘ_s{gΜ-t=2/"Zj~J#Gd[[[ïF ?+WN;9Aw.\`;;;Xw|5J?g^z|H!!!yi„ Z33]tIɓ'vZq:JPn(##R)U\Yu}xٿt֍Onq@5S+PѣGԨQ#Zv-ry=m޼ᆪwމ/LFÇ,>|8& IDATى~ ^Yw n޼9]pY`N?~n̴f""j׮ e @W˲mݺUt9T߿mkחٵknZ|W |ǵSgٳgA܍s1c+VL;˖- $;;LJo߾̏?z펯L.@//<Z*yFӄ^z?r\+?^>3~hdHNN2eʨ 4/ggg:t(Ϙ1[h!ߋt2ܿӧOϟv܉' /[L}^~sŋ4xsA{gϞI&qff^2jUjU!lۿ|988[ =-P f͚xh ::Z-Z͛7CiWrr2Khwb:@Wƍx stt4O2Expl"( F/v&Mh0buN>^`,5Ǐ7xz m:6lP|U,]Ԡ#S'''u Rh&˅; ?]Ɲ;wV[?۷opG3sBB0p{)^8תUkԨ666 ٹsN@ze-Z_9uHGuq?.\PyCfdܴiSsssS|yatyf^L= cH{#G'OG||^ܼ,ްapdɒWi&+X; ֹ?S+ΥKՕܹ۷oW;u쓒~~~*f͚+P!_^H.ZhZ1a^z5;%\.ZjiCW *24 c&".R/Z߽{!!!,JU~94iׯ/7dDvvv#G>}^ᗝw~}B;s1ܶouQ%K~aֻwo&, }ꢦjժ+3e}Ndz[|ڀJ=իp@Y蝙_|} ʼd2g%ݛ% iF޺uK=<==իWB/0[׮]CU@s=رcy֭_^m5yd}^/e@ɓ'x ;88Dʦ#[`(m 2_^K.rJ *U(A@fe{X933SvmVVV*$M8Qf͚ܷo_LAə2PyڌU107ol1$z x;wN[ ׯ_k|+WD9VVV{zz L *ltٳ':t(Ϻkr"ETֲƍszzAP^͛ YZh/^й=1JJJ^ 0 sU TB+[R)Ӈ###=zB}u ._a!WFFK㸻+YsWŬY41B mרQCzN8VVV:}z1o۶M<(\l۷/Q SxM8-KWL*U׵kpWUa}6 S~ݻw?sů >NNNLN;ooon֬׮][PӐK.+zu҅E>k`.|ʒ|+ʊo޼)1NhB ԫ5g/(ʊ7oެq4_&L~B/0+W PS,ڵks]!*^^SVi a%K5Eadz^ݻwyȑ 2) ۷ogkkkJ77o֧۹uF cccWZŅ;v4A\,ь35koߊrܦM )SF6tz޾}*T:Zp~Zc! Lʕ+'7yd='NL&S&%%9ƍzqTT^|9::rxk : |s9sf -ZPΝ;>ɓ\H*\ڷo) rdeezeY?Ύleeŝ;w_~DcΝE]0`fE8ݠ^ի.zj9;; t>֑#G>S KtVX! XrLMWdJMM`.WNWo߾>˗D[li_`}JDD^^^t *S}Gj@p9^$ˉtRA3gΤ&MUX*WLTzu߅UH$ԴiSx1`@0-Zеk(00PٳgCxx8YYYx͝;f͚t]vv6ߟve10WC@@޽lmm?py{{ɓ'5{:txUPA9P̏T*%///;w,zEDԩS'ڳgʚk:u/ B/0sΑB5e^ѣGŸ_x>IIIxb-Z… ŋݽ{hԣGW8g^` g}F7n{Ul=zN:+nܸADBwܹsiJ!2-+ˑMoߦӱc… 3|=}h*xk׎oNDرt;!^RJ\e )ʁ tf`'''9LbnfϞ-Vyذalggӳ} ۷^`TxƄq_y~}||Lݽ#w=y(md2ݻ7eFP_jj*]u癶988++Kv5=+͛ѣm6ꫯC%F[@2wm۶͘޶mzyyq||ю B/0^ˮ]` zjnٲAˎ;ah0 ^xsJNDdnR(T_r!2W...:}}iu m/uK͚5F@2w2K(U0f D#af&EDD? M:,Yb^!222t TVR*VHO퐐6lVVVqF߿(ǃPӧOo߾t9Сmٲ/vR^4N [boɓ'};vk׎iܸq?|IhҥcxbgLi@CUp-\fΜiPգ!CPvjժLvoVnݢڵke0 Mf8rHEi;++J,pǬi֭ԧOQ ʼEGGS6m(..>L-[$gggJHHzVmUR8@^^^j&j߾=թS7oN;vEjRzB :tprvvpjԨmذ*z𕒒BRٳ'ݻxLz8gϞ3iL-ɻwQF:O#J[n?l;::˔)#v|<3(0DӦMS2M~~~3T}Lu(>+^:[YYo߾ͳyʔ)󓛛ߺuK5MuئMNJJ2i(ze9BCCՕ/^Kxuhvuu3gYw ^ 3g *={ժU*첷篾JgF>|XwٲeF>(0 Uhhhz\xqnݺ1qǎy֬YydܱcG&"P<'Lj?K-[N߾})--~'51cU^ShL/0‡Y(={FDTlYjԨf:uSN2P,X<תUTuy{{Q`` mܸfϞMS5P``N*U ^L򢘘jٲ%>}Z6޼yC{Ǐ&((HeM'ORҥu':WX:|0uԉJ.MO>U233UB9{,SZZ/:z(=z"""(%%ҨhѢ駟P׮]>pXl_ҥK%$$A : Ȁ%bfTJIIUR DժUW^Y駟ÇK~d2SNъ+믿֫ Jcǎ%kkkڲe QժU֭[J.P,ßIC%"-[Pj'++ wxT;!{GAJP@~"x$(Cӣ ( M"R DE@z( ded$3ILk3$3뙽s/_>j@ٺ"h?CpXpñc̋/hrֹ"""L.]̱co߾Fҥ_sL 8p Xb)r%̓O>i-[f\n?mڴTzv$+8 5GMu%44̟?듕QG-N;vj$o73p@J_+Wvy5k֘ Cz\}P2כVZ.TPtl޼٭=W^}hzKhxSy=)y%wf&!!繾;bo1!@ozmܪ5k46lp9Vddd۶i޽;</^4mڴqڮk׮>ޝ QǕ+W@tA;d7UThw_1& :Ԅ`3uT<dmԫ믿2O<۟7on>ӧOOk2ӧMBc M/` 9szj֬Mu_Ǐ7qqqng[nɟ?d:ug Uz\CBB;c_4ޙ3gLJ6G'4 ,0Ν3$?ȑ#ft)9ӧ / W%&&k>s^V5+fLٲe$^p*Zvˣӻ(P|g鎟^3_x4jqR%J^#^ݱ~o̜9ѸtٱcyL*UPTZ5sٿLɒ%Ͱa$%%':oJ2Ok SD kMdd4+W6AAAu .8~Sxq'r̙"_|sIJJ2< /PϪU&O쳱] ?k|ݸWעEK.mZje5jhnwܹsK'ߐ^RJf„ fԨQ)|ӿ z5]n[v- 5{ldiӦMͥK|%KL@TfG|=zԩqaڷooNj~Ws1ᅴ)Sڵk;WJ- Ä 8*,,|)0 IDAT=xy]gϞ)Lrn|vd꣏>&U`3gӿ?OgϞ_ݻk|W?;/Z;wnՖ-[ZG|/^<ŗs_B+p;vΝH2 4pZj"-?Lwr]v)={y衇'Oӯ_?CÄ IRRcٟPߦ.[t]wǏɓE]G?UZzӿ]PP>z.wwQ2;*Qٿ={ qf͚W_O_aaaf͚5>x@hzt]4qcw,c…fӦM~_4Lܹ=+[lI3fʕ+e˖nS^=3asY_}o= ɬZ^jz)+U涇r,ub 7T7/SسgO9uꔹ;-\b"##9++{?qTcPPPG|}w&44HKD;vf͚}QHH>}Okٰa/znw9s[l߾ݱ7GxGzV\-[*..q5`SeMpyeTF Ƿz6nhy{W4c ܽ{~T۵vZ͛7O=Os!{d[lq|ڵti5nX{ŋ>*"""|rrze+::ZdI 6UV~WJr͛PB)nOHHPΝΝ$+V̫#8[Wׯ_O111jԨ.]^1cMm\B2+WUVN A6ʚΟ?SNzѣGzox>}ڣ% թS'͛W۷Wxx׹H3|7&gΜNKX 4XYʱc;c~#GḺt$$$x-[8ѤI>M6x;w>!)),Y4iZ?n6l^yǘ毿rSNի[^2|U^XCvXƌ3+VL\֭͹s<Xb1-ez彸83ydSf4Bxxy_ݺuOJJr۷"EX^0<88ٳǧW_uGÆ }:>&d۷o76{nN;)mcq#<3oK>Ku2]7ovٳ 8]nvn:\| 1oS=X?ܣzSܾg;wN ҪUTD ƽƍ+I*Yqo;wN6mryŋh߾}}Scƌh̛jJ?xKk׮Z~J*e9wΜ9G}T;wtVxq :T111ѣGuEm߾]/rʕK,ѯQ2eʨI&)nߺu_O ,PXXGlʕy/Lx:tݱ]:^:uK.ٖˎozɓ'W'LW^1Ԁ3 _KHH0:tpjݺuGSƚ-[ '|>,\дnڄ{dD…ڵkFdFHJJ2_|T[Gxlذ^yܹsVZ/88ؼ[?Zjiւ?<_~e5m$%%Y}իNuǀB l-\-[֜:uHo߾~ 53fjI{QboLג?4I5rHOLL4Zu|rꫩYvms K.Zi[^yo߾}{==EC GiӦ~m|ݰuVӧOӨQ#SlYd (`*UdZnm>cs H;/^4<˗/YrG?>MRRW^c>&>>q1_~q"""LllqB ld4Ne䃏??ޔ,Y2 {ҷ9&f͚Θ?+ߩ3{lHLL4QQQ.kjb,:w)^x\rYɓ1F5,eCW=z sy5m۶5|Yz_̆ ̒%Kȑ#MTT)RbfΜ~ndƎk1f~k|%&&Zw\b~aWpauVǹpႹ]֝R_~%#%z]vy4q$]Zd$^d^ݱ!C8^H8Yti_nkTHeRĄ o*sZҥKxx\p NsSNNX]~|G&$$ir6zk׮.]8^9s7|Ӝ>}:m_n-Zd6mꘔ NsO?ԩu_'O47h;W޹vѡ 6r)MZ[/9s47'OLsXK/}ٿl@F@6|C[W^u:o;R Æ K$SD 駟:iذdrՇ=VLF{勣Sunݺ^9ttkuPPyG͈#?~s1vZ˧橧"%n>j%,jG5.?ݗ$SNS@sY +$%%g}͛'{W^<^bbi۶m%SO=e&Ol~W~sQb ӷo_> d^dq˖-Kz펕̝;(P\vH.<{5'N4Ǐw>11,_y睎 onń aڴiNGPEEEl *8>^ٽ{wj5k/f+7-[>|1=ܗ'Io߾^eENRRٳ_DzGy?ޫ1\b4h<; dY˗/WTT^*I ȑ#էOe= .t|})4448qmۦnݺtҪP|A5lPe˖?={(88XcǎO<ɑ 0@v\ϕ+.] ژ nz畔nsޤI?~  Ǫ^/_Ʉd+:tbcc%It42_5nԞ'Ojǎ>zc^u92}s~n~/q|^?\C Qxx1[oiܹ :Qhz-[^4c޽:zlLRbbt[ǎguU9rp{P ڱc6mȦ?Ç_~.\gU޼y}2$mV;wT.]<:zPB8q/^,WrUM:UTdI6'Jm۶9~>t/^yF#nXd>cϒz"%DGG+&&F5hۊ+jŊ<d v|oҥNܼy;ݻݑ6mdSP!s ٿ2d^CBBL {g=Y瘀?z. z_7Ιl۷ה,Y2ZÇ .-GvF/:8izDVk֬֨Wqu/WP`o (`$%Kx=6nh^x7o^'w&22̜93ӞpGϺgv˖-S6m5jTlVr1'N)IJKÇkҤI)sw(::ZѺtݫC)w*Qʕ+R2!#n5h IJh>|X֭$uE+V4;*TCjС:|bbb_)_|*RjժE#o}k֬i_7 0@o={ŋׯ}%IaaaV^yˤsͮ_zJgVTT-[qKvڪ]&N{*&&FW\Q|TD ժU˯2J1xo…zꩧtuI42R5d5kj˖-6&r֬Y3-[L!!!ڽ{#L/f̘{έZ,-۷ٳU`AܹSԦM{nJLLtL$vmZ|A̙}?VHHO)SFeʔQڵUV-=>} FG(#l= Ă LhhR+G;Vѷo_e!S]J7/اO,>}Ӓ{y'LZ]H:;wcbŊEB }sι8Stifk奁WQ^=k_tDxbir̙cDDݻKaj9Ps뒆7xoӦ?ᗥ{ؾ\r&wnՕ˛cǺݻMHHM\\(4pO3fݱ[?`J2'O;ŋMXX`'&d_|UZ5qFSP!5~t'ӻ.\،1\z5;F޽P'22'c? >q=qfӦMn|z7|5ouϟߜ9sXv2=z0yo1""|WnƗz@ZWtRnMbb̛7'e˖;'Zjŋz뭷$Ӻuk^'  @͛7/Ekرvʖ/^GPPٺu ȶtR bBvرT'nuaKGs)S1b9y>]fڴixܥK|5M05n׮[G*ܐdkӤI䳿Ðl22?>IP3tP/6o>׏?u>Kٳgwm$'c@@?:tׯK4f IDATNpoÇ\r)noٲ/^\X`ڶm+I;v,+PTոqc>}: 0@t\?r6lHʕ+zK 6T"EtI=zT?,Y;vXʗ#GYrȡUViΝϞ= Z^e WwѣG+$$$Ξ=Yfi̘1ڽ{_͛W?Vco߮h}~ռys_իWK>}ϟ+!!!DŽjيrܶn:EFFҥKڵk_W:u?SGʕ+tR=zRիWOժUӕ+Wxb#7o27W_57˗/OEXvZӮ];}qiذaFOy!b޼yСc ;V=z9'|}O?> N=#I7n7;A pwׯիW+44}?^|F+Wx}uV/_m6}{9M6o?ׯ4i 1O?+xy|-)UR7{W5zhK:xy}JJJxUjƍ PW׬YTϱkر?,Y$A^VZ"EI&YjxIMCjϞ=z#G-R^~@ׄ Tn]۸qcYq^R.]hN/^̙3} z9mVfJ|7.\XÆ kƌںu{1ZVXA M/2shxqN;zϞ=` Llݺu`կ_߶A ҥKkҤIQ-O?v^ΨW˙3-Z뱂ԼysmذA~~aoذ{=y UnZd^VXUVVZ>ETT) 7 ;w~ ݻۜ nݺD>ѻwo}ᇎ7nHK؆zxh|_)&&F.\PrTF ^dB^ǏWnlN?~\w}Ο?cBBB4i$uyhʕ+>kw1!$&&F5Jջwo͠TUwY͘1C˖-Ν;ui\rUV-EEEf͚~I/:ZJ5˾Pׂ Ծ}TW9rh̙j߾}&^d2s3}Ժu4 ƒ%K4h IRկ_?2ȪUիW{d|>}dP*xzw:uzѢEmJz5iFfRhhhILLTǎ5k֬ Ld}4$nmxkԩ1'((HSLQ }ŋu_~iQڵSbb$i*]O du4ğ_|Qw}FӧOMBBf͚jժw4J*e˖)^=&d]UVMVroz\\:tu:"nA1FT^=5nDWC6m_($$$$&&SNZ`A9vZhG#&%7j֬YرAqڜ {nh<ȑ#իzHUTQbŔ+W.]pA֭[W_8z7ߨbŊ|Ƙ۷q~!7|࿿gcuQ۶mS2eo>;rDK.U%IaaaڴiWns*duԫgj߾㋯j)kuEǏ?e˖;.hz`iӦK.JJJD+UΝh"N:ZhJ, `BU]vʙ3֭[%K(11Q ʕ+ugPz}c||Tn]ǗƎ_~'c^e_4$qƊT\\kOʕ+ ^dS^pjxM:U;v92̙3̙3>788X={￯0  5jȭ%ho?~}7Seoԫ#))I/ .>׶mԺuk:tHԳgO9GIרWX`ڷoׯ{ݝwީ5k֨TR~J>^d ^̙3:tƏxǫUƍD*|  u6hx*{9scG}TSLQٲe=#!!A'Oo+WHz1c8-M  7xO?U׮]ix5i$M<~z7լY3-HLpE˿Wُ1FСC%Iѣw *d :Tv풔w;ިW/^hz\5Mgyd,1ڲe/_M6i:~PrTV-=j޼J.mcjdULۼy4h8s/^eocƌkx-I˗Wu=@ʟ?N8C)&&F?rB4uThŽlzL>];wN~x~F V%%%… ו?~!;`B\5dȐ/$iѢEСEUhQ?Q{L+WLq; /s,R 7U`A,X225M6Mq /^֭[kɒ%ʛ7o͑#W~[>c^;ѬY ;YՔ)S/y)ZQpƍkݺujӦۗ:2ed`2dw+eZ%^78 ?p>}: /2wVXQjժi֭j۶˖-K zO|׎ixޡM4ydKN 3f)1!xիzuy^~FԳgO\RŋwިQ#S!;^Ǐ׳>+c /Ghz#5:t`s2H {}~^~F?nݪzH9sOd1v M4Iݺu 0!Δ)STZ5^~B_UV)22(WAk׮4\5fΜۜ RbB@^+IhxȔ(W 2O>Dݺus4BCC5gnd2 @^@đ^x@„ @A(Wy1 / z PP scyC{N sUV6'(W 2? 'Ntjxi1! PP ^cȑѣSkΜ94dJL+z Hȑ#;8«e˖6ט(W  Gz ^ 2 @^@ #F `0! PP &7#FP^4oHo: /2 @^@cyC5|5oT2 @^@d1vNÇכoN @fƄ @AiKqqvM q7劈ɓհn X)1%RN)dk4& Le ]5@璴T @6`4p)2%ȶ F @`@^4 Ȗ zq=<<\ , Sb@^4 kbyCɓ5qDc@Ν;8B ʗ/3gСCXc_(pz-gΜ;FTItI%\`*z?-[ܖ{ܒݻwEY>}_||d*ϟܹs۶mB ٘\ٳףTHk+}[J7;!i=q~9ή]t]w9o߾]ժU1~p\߼yjժec"pz S4HzmSpNT!r BCN+]Μ;@ʙS x?$M[%&J $/#Vi`Ś5Сv[b/_T2v?d*2-7WƌΟ; hPFΞ; h@HM/HҔ)!<ew g۶I&%/{Le i,SݓLV>kWGNhz@zfϖ.;OS87O+S}jN[$$HӦI7ڝV'7);S~; W*U M/pDž ر޽v'ŋ'7)3ѴK҄ Ү]v'EHRXIenN ${:LN; T)Lxi(Y N!ii^}M/ܶmҔ)R|I`ETvpҤIҕ+v'-ZHO=ewlXrvU]J ڝwI}fw XեԸ)5^`ܹW_ٝVEGKUڝ…vU}H5j؝"ۢV%&JSJ?dwX-*ew#͘!I`UtT)%^K ]N+InRٝo/K'JfwXQԯ+I^୓'>; T)񕙜:%!>lwXQԷ)^ J#GJg؝V<+vpvpr)u=N_>Dr$eK驧Nߒ:|$Y3gNm_;Nt7;~O; IjM/ Nj԰;E NxC~Sdy4׌fL>Bo_lYS89SZo_\9Sdi4.]J>۝V,ܤ;߮\I>gܯڝV+EGKy؝$ˢrGv'+&7)2ӧ#CN+ʗ|SYM/ÇNٝVԭ+iw gGJÆI'OڝV9s4~Mcefͤg;ݻ DiDzYSd94 #]+͜)cwXѩcvpOҴiRRI`EǎRӦvRhz@FY RZvpܹvU&թcw,d35kNʕ;?*:ZPYM/HWH|"I`E޼M~G 2? N; YSz-S8OiYM/VƏbcN+ONl>i8~C U6;iӤNl&i5~A $פڵNliSKzS8ki,S~A nf͒_?;Nli2S>G nȝ;?Iv4yeI`ExxTBv'ԩYM/'7)21cN+JN>+3pA;Vڻ$[լ));& .?nwXQ۝Ұaɿ[@@ \y1Nls.\; hHzS8;p@=Z:w$hz@j:t7;M)SkN+ڵZ;[wI_؝_KfٝV!կow g+WJ_|aw +4 =Iwiw gs$7*W;s%KNXF ܤ(X$~=yMN+BCEڝo ԩ?۝L):.\Ǝ; (Q"w*($xQ?^ڽ$hzȺ|L^:~\6L:v$JL}[ IDAT=yR#QhHzS8;p@3F:w$ᇥnNihYnjNjζl&O^; h&l&}gw-4=;+/;-djNX-Ulw gsJK؝VEG'+3;WZ@hz1ֶ mo$$HSJ?lwX*Q$3F1CZ$@hz7JHnRٝo/JK{؝V-*T,.]&Lv; *^*Uɓ؝V}wߩ#GND |aC饗Ncᆪ(o"Ev.^'`4 0j4E}6ł 7XPUTDu0 3{g]a{ hIHcNJN(4XxZtl""""""""""J@~S(u XHJѧ0h֮E'!RQt Eg۷NA5 Et Ex{NAM/""""""""""yxR'{NAʚ1h@t ENA^DDDDDDDDDDRkkIdf[.NB*V"L&': 6TJ>K__t,5@`$ ss5ed$:ID^wNBĦ˛$2XQ|Ɨ:-BCE'!-Ǧ*k+:Py"*JtRFV€%KׯE'!-Ʀ $:;wuQg_N񢓐bӋ(t,:"__[t RȑΟnd2IH EDDDDDDDDDTT݁ DP?oS&MDPtgE """"""""͕gϞ˗x)}HOOG\\tuuaff055ER`eeXYY|򰵵EEXD L<.:L&eat(: ) "RHHΞ=gBd2 $$wT^ݺuÀбcG HD3~~~I7_bĉ]hD@^@Ts$Y<֬/X4 =VNLLD! Ʀi\7n@ODZ%>>'OqYQAAA oJ*aȐ!6lg/_ .#\ll,~7]]t+#:i#:%:I `?H /7czzӐbӋ\D={#G-֯IO>1|k3f'|Ԑ;}={`ݸqd2H;<Ο?F҇Djdxjhժ;;;ёH[˗|Tt,۶ɛ;NBbv\9It@lzQS+ IIIGgϞEffHE֭[4h4hիWM6#ѣʙTʔ<=卯Di䒒uM E!Ml 64 ^DDDTddd 00 ."*RSSqQ8q222DGh׮+,X#(99'Nđ#GeTXQt$6ի̙dy~VMto+VȯE! µ%XYz50b,_/^dË1ydTT ñcǴ/LM6N:سg8DDy:s 6lcǎBڨE `D)=} ,^ z%: i˗aӋHBÇGzdDFF1h ?)))͛7ݻ7VX!: iO? BÇ5@\$)?VbcE'! DG(6VZ֭[όZFF\]]51>Ct E/7NRzw -Mtlz0h޼9\": Q/_d2QHL 8:NaKouN?]D  nݺGt">>+ұIDE[Nc윩S33ibnbVQdʛg}ӵڸQ\ /7i FR{lzSzzzGӦMѬY34k 4@ɒ% U755wޅ/O?iiiΟ'O`С8~8ttttl"ʝڷoVZyhܸqflZn֭[c֬YǦMn:DDDI???]cǎ-:xP0^6oƎ D)0=]]I԰/B:tHt,=&LAFlz)IWWcSw'''tA%6I&hҤ &Ol߾ׯ-x9y$֯_o$"Eԩ:t耎;^mѕ+Wٳݻwc RsСCϢ%*2nn&ŕ+d9z(WNޔgx5u$YN,,#D'bBWt"""6l-[cݺucGݱvZXlzYd+ʔ)q֭[E6md\2e BCCl<"m-Z`Μ9z*^z={`ܸqW6>!CBҥU:ׯ1|A+wwzu) ?.:)][t Ev׬FRkEDDDY&6my0r A6m_`齎;… 8r&L0ѣG*H*U | >sCc300+sΩle˖ *(GJI@L4r%,,GGi 卯ɓ峾Az:ijRtRsEDDDZ xܻw[nڶmED ;w.BCCqy7N^p3F3?|||p)Amʔ)`˖-xۇCjLCvvv8{,O1i&'SJ&:V<ac~ԻwUǢL/"""EDTڴi7774^;v U6'uV,V#*\]]ZOOG C&I>1m4s%5Ҹ10}:`$Y""ŋ~7Qx__I| ,Z$lmE!5U|~""""*\022`llƍCZD)FpvvƋ/T2ƍ7pK%6f K^;88>>>prr6Qt ~-_ZP]ѭ[7zhӦ '''8:: M6/ּ~:.\X鉈T'66VZ""vijk׮գ"&N>zBt Ek 2CEP!f|MlzI0`U777亱L&C@@<==QJi?:t͛o޼QADDDD/^@jjdT"Y-"nޒjҤ %G$_/ۛ j{w)]l dfNBaӋ0sL4hCFFF322q㉉XbjԨ~z Dff&tu9IdJx7"* S=\N*Y-"SId-F%㴿?nɏիQ1e дZ'#3>8o길'-DPt({T@lz'p|(]k׮&_|,"""""UȀ5{S.3CDp=nZ####޽&&&%*6<=n!̓ _Fas6qwDPs'pTlzٳgVFbӋ ((HҚÆ i(L:M6ŵőҲeД3]HțmAyĉxXt16<<33I6P>ETwc*dɒEFFl<"""""dddয়~%$ID'883f̀-Zǘ9s&;;vv& w}036l@jqއJbbˁ'OD'|`ӋBBB Gjjtqqw7ũl,"""""lذ!Ǜ c000&i/_bÆ ޽;j֬  &`޼y*MT,5oL$:Hݻl=I m_,/56 ݻwَ%$$Oec`ĈWjDDDDDRzfϞ-iM##l vJKKãGc+Vѣq)dfflYfa*OTl} 0|;!!hߎEyNNȑS(zX /:Qq t~Sͦ^ *V(iM"NZZ<(Io(DEE!22AAA Ez/edd+V`E:.Q2l p$ 5=cp0zz#ܗ__GN5`F`xPt^D`lllϜ9׫o6m`aa(.HDDDDTXXb5 0m4Ik0p@1Trؽ{7Zl): 8QޤvMtǺc%̌E)8WW * |Yt,ǏE@rr=7~xڵK%a„ ڵ+Zj1 +)) CEZZujժIZctttlx`g':}?}=^e<=ZDP{7g5)6 N:KMMŐ!C0m4ƚ5kN>H^H x5MLLO?IZc4h???o033x167wG Ai':Jɯ)ssI6qVbӋ5jLCƍq"JEDDDD$ޅ C+9sFDD97n޼ۋCT|U"oRZKL*VEP \ <~,: }{ziElٲAQKݦ}s}f͚ݿ=z@1c :::Ep"""#z 000@2ePZ5Ԯ]%K,,wA|۷oqMDFFݻwjԨQp-<޽9,--ѰaC)SP#44111044D2e`cc"Co޼!C)i]{{{L0AҚDD9iڴ)\]]1x`2"I4iL,Z$:I.YVeLX!J$")%)iixHzgw503gį8Ө0c0$Y^_fs$ ɘ>}_4֭ NY5jܽ{7_?wΝ;ZjaԨQ1bT2233ݻwxi544D6mзo_ :TOpp0Ο? ϟǓ'OD(QBqqq߱eܺu 2,[=;;;`ѰWDlٲ;vKrF__-[ķ~CWWfm6ܹΝCzzzCݺu쌾}QC"<<\K,uB /0l04nXt"Խ;|85gʕѤfMԩT ml_*T)jfdfś7OVP?|̹;w0vrl:UhtDE6N%8X\ސ+[VtǦx‡IIIhso߾zΣG0m4̜9{ѣѥK7LrM6axI ___bƌ3f O 2>##wݻw1|o˗/GÆ %FDDD9sĉꫯ>:럈ׯO>={D۶ms=$4xIq$ #:6nu~j 3 [KKZZ©iǃ""p v MΪ)upן|RcڠAfd 7\]{0lzi͛7+|Xf->s*sSSSw^ݻvvv * inݺ#G͛Y[[e˖R J,x}dP;)) 111Ri6sss:u UT)tt?o߾Ir}CD$x{{c~EM"68[9~l\Lѥqc\X '~U+1DDL(6 TKKItItŦW1cƍh׮I:+W˗x +,, fBժU1rHɚ_7oƔ)S5eT>7Osmw^|7y>nݺ8y$^6lXYb> @GqF 85BʕQ^= 0Gݻsl̙3ػw/NwJ.͛7# nnnhѢ*W5kC_Ct5׺W\ӧY={fhXh?q0z͞=7nP:ѿ2220x`ܹsG7ou>&66֭zD$[[C%@*牱ʕ*ɥ͚j1F*o|TDk?+ ^ <|(:VґiؚW׮]ѣGDEE!::Hgf\\\(Ww)))r.]0˖-|icccL<ӦMR5ЪU+*PݻJ]kkŘ4iRk.\񜁁_`۶mZo}ݺuos=_n]<|(]4N86m|nbb"Zl<~)=:9ꫯecy& wPZ5DGGg;׼ys\r%2(00u} LD֭[1bݻwգ/((5jx7$Hƍի%kllW^.C{fffcHFGGO?T H 30s7x0)*gKR)5TBvvY@Ŋ0 7T:N&MpzR~~NSWm>#?s*MiL`̛7Wƞ={ .x"""bU5TbHp/^[n?saÆ4T :4[ 7ixҥKx+P z.-- Xvm7ooPX"_ /(UT!---_>tĉl /Xpa^`jj1cxڵk? o\ /^^ / +*d2ۇcƌHIIHt%IJ~A!^ X`°RW/G֭U:O@;1TcGDP ,_ps:5j֬):Z Akԯ_gAAAAСe SRR ]%ǏÇ6 ^JKK ШQ#.yH$A>}DPlYۤT)3 R8o/'R'nd9MqMZjV*zM6Ç9sJ*MNNƀpԩ|=>11K BWԩS.WXP/ ={~g5kRs=?9rAAAَ4l0}|}}T]"""^.\!y-Z`Œ%"R`` Zj 6v,жNv",5 ? 1n㔿モR'g۷N54ebbkkk1FN|hTT gFpp0N<#Fz}t 4O֭[͛u666_bEz¢355Efr=oggΝ;+~i/%s`zz:NoF^ z~c׮]^ҙԏ.$EٲenL8GVMDZSGt E{GN#F`7QY"88Nh)PV-zJt d(QBt '''899!99'v؁cǎ!99bbb0~x:t(mڴ)s-[,^z~ÇB~_SN\|9s7Vzjժzm} ٳgs}:6oތk׮۷8w~GmV%qA8;;+u3+|yyBU".XxHtltttqd8桵GnMUuYpK"bK pCdjjÇ㈈ҥK tZ*s~~~n:inn^ହ =F^ )L(/Jӧs=sN<o߾Wtt4nݺ///9.DDD1֭$kע&"bddva֬Y8<ñl24iҤH?s ʥ oRWŋgD'ɦtɒ7kJ`/"]^_Sᢓh,6@ ;j'ND`` vؑMǏϵuʕ\'eӫVZ[ =FaLR5Ke?猫S*W7n'"...ϱT'iX>TI 믿VIm"n+V gggڿ?\]]U:V [)^^@q/ +U_J^7*6|ڵƎBQh(t,a4Up4^Ň.Kܻw={^£\W?~8,YP?TD TT) U5w DlHD8;;͛*)S6ч:v#GhSV^͛7t "ҿ?Яn֭#13u+Ws$)L>AS({X+FBD5LQ255EݺuQNQ4£Gϴ͛jٽ133Çѷo_>|8Lkv<444礤H=KK\NjtbF|Ϧm۶ׯJSfff$""/99}.\~-~'&"M&Mp9l߾&L@LLJ7n6m뫤>;Ot,gQ(0#G9=p"ָAKTQ(⯿{bN#^%KDŊW\Y`!!! tuuQF TR+WFʕadd333D7@}- !!HMMEXXr!R~}CݺuQY~mqF,\|*U);vAΘʭٔ "^y}}|)5mۆ*UQ"""v6lΞ=ǪU$"\::::t(ڵk!Cŋ!C'J&ݻdٻWsI|޺5V}x>>>>IyL~Oazzz]4Y!QQo>۷/vD$\Vf IDAT*UWWWYFwE.ym"&^N# l"o|A0|I^wO^)?DN&Tǎh ]n3ϟ//[2 C 6kԨ<0̟?|dKm۶?>BBB0{lY0fIƢ,;=֫W/T\|0yF\*QD猍y7o.>lῳ=T)33#GΝ;UR[nرcgիO?y!$$DDZJ>KKk(Ա#ML$y}Iss5{ӬbLc^5kvUVlcǎիَO0ׯ_G޽U~7!̙ooo7k֭ڵkU:pW@@@>,s+f?pɒʫUB4ʕ|ddd%!"""m%0vXlݺU%۴i(&"RX @ʏ?(y]"fo/oRH`b <\t y6ּFZ_$* X(4V57o.99>|8/_^w2<_±)S܇3N>"1㖖9^P/^(td\UVMq4ǚ^EL&Uv\˖-qq>N^۶mÇ%KڵƎBQh(lY&I<^PD^JZSmjN(<tItbO^ c咍QPnnn C(ʖ-_zӧOVVV9xݺu(Wyܸqc4˗ϳ9~d2b*߰aC;v,ŢEХKIkfdd`…$"}N`:tjSÆ(%,OJZO|嗢S(a+%*mze@Y_N:혋dv)![dxP˖-+sjiӦ9>e˖y֓ȫպuk4Jʳ)xE$%%a""""3fʕ+URv8ydDDJWW[lukΝUD5 Yt E}}gaHIt 6 -Vtid;֭[7+VZ gffbhgz'pȑ";ԩ 0''<7}d^|RJSNڶmwaϞ=EfԨQgϞu5""uUbE_sNIk?݁ DP?o p5u*Ф$mz͛7kܸq vc(fڵ+}(r?E0}ڵkَuc^[[[j*>>>Iq#ڷoy̔IDDD̙3믿vJpiب>}W֭[%GD*V"L&': ׮-i=/@ >ߧ覗 ʖ-HLrؠB WVjjjc/^t'meccCCCc.lpAjՒ$:7ce$]p._>mO YIڟzuSKmC]JHHݻws=M:Cq\RN:3f8֦~<<~i3 b۶m9reN'ka?>OH2e/FD$>3Yk9rDzD6m)4I/A3=-QNz))2-['NAEr۫?$ڵk|.gw$kZ;&N( W⣏>QECСCѣG\i8:u*5jTZO&Bg3gyOdddmjժ3kvލQFiZh T:0 ?ghFӦMOD$'|"kK.ZBݻ% h>4 +gJ%JϞNAZbKKr(?߇Jķ~y+++)?ر#4͛ѶmM%kkk]PK,#?,twoqm۶^:'11NΝ;y>)) ˖-+t]غukB9s&ի5k׮Ev |oz ƍ_lDDDdVX.]4:͛+RH$WWWT\Yz˗/eG uKtֈ@׮Sh:}Xg]VlzgݻNAZ`KKիWqٳg֭[@C'''&* 93gP^=;6rsMt 14ΙbÆ / {Aٲes դ{w76שSww7/ލG}׍ĠA: ;w,p]Z%K`:t( \ ;v쀃Cם;w5ȑ#qͬ{!Ν WWW,Yq[[[ܹeUV/|o>lRDDcǎ͛7eG {(s3SMNi.`6+kӫ-oo?epR<~^~Z֭[s} -/_~@ƍڴs#֒m3'==K.Eѯ_?Z QQQ9Sոw,YmۢaÆ8tPlll}vO܍7ƩSPj碢Ю];;vuΞ==8ުU+5vZL6 uƍz1b-Z `ٲe5jj׮ׯnJJ 6ms4ܹL6 4q/+v,kƱcP||KJJB@@:uKKKTV m۶EfP|yKncc}zI"""2iժBCCeG [ 06ǏtH+^YYH+^(3a&ĉQN <|7o^%j5޽3gɓػw/>7k(y{ԩ׿>={`Ϟ=RJrʰϟ;fӦMvڷ.6Ǖ+WcvSTT:w.] ͚5Cr吙\r;v5T*xxxyrܽ{y?WիoL/>rƎ[^K.۷c֬YZ]f ֬Y{{{ywq% <gϞ}iiixQ&UZ{AÆ Ϻu0rHE>|gnn۷C&"75jԐ^xxHaҥ=Pg1$@24CUIN/)=IIKJScc pZZneڛ/_(UlmmaffkkkXZZK|111ǣG\M4qI$#'''XZZ}/QFARaݺuӧѣ9Kܽ{@cUX>>>=z4LLOlٲرc///zc#Gȑ#ռys,X 0^J%K`9u+(###1sy벉DDDd6mڄ#F(ڳg>Ck飚5kZ/""Bzy@ =SԤ>]tltO`rBKZCRV U&5SM M/-o߾Oӧ ]Νu>fqRPZ5_uZl#GΝ;عs'?أ+7NNNh߾=^zxTa =zl2>|laa={bM4Kzsilٳgjiidd?>|8zj\v@ﵶ<<<иqcmٱcLkb֭lxQRreYfgR6²_g"el L,X :IpOJΦMɓ__I-*c%J޽EG(VV\ :֭ubDxx8BBB/^~(QL899Ut民>} !!Nµk8 Y&5km۾~4mT"#Ch PB Ə#""sBCC4XYY5j@˖-{FH^"""ҽ]vaСSacӧ쵉 ,,,r-mV!=qԡ'P!$@Ϟ@LX4 (UJaz%[-+>o>P v$6yԩ;&:J6mFQh1Ujz:%uSʕADDDz:t(eeMDdlll"I`ر#_NY7P`K DVRZ°arNBy0~Y'Odv! 0622š5k0tPk 333j)ұ]mD mMȰ%nUgϐ)>ӄ @VSP* b̙cI&pssdtORd 6LDD$11QZE&Ć Sgg)4m>,{ِ'OdWM 7P 6dnݺ VӧO5/^ѣG^Dr2bp$ I>Z Z\*kًZϹ|yYP$vDd`ll۷kדR|}}Q1rCRpB;VDD&)) ճ 6U$.NBBd+ymj@56VL%¦Lq!CtL4 cLO^RܹsGDDѣGLb&<D'!m4o.O"#{"RqBeLhk)_ ooo||Jo:q9t /_T?S*RZtҲ#=p>d IaݺÇN)(XHH(R !^IU;#GNA`Kf&&&pi4o\g:99?3t6&)իѣb ^`r7eGzY` 3Stưa@^Sh:^ӵ. /]M2Wt ^ypylٲE旅L[nCDDDDDu5tԟ9s&OHm""CvyYըQCzGm5aЪlYj5uݺPT,־ hFtM/T*… 믿W_rʲԮS[,uHׯsΈS'fϞHm""CVq)YkUm9":i ^]t M7m.\XY[Wz%7P%%EVЪU+미}6.\/ÇǓ'OrgҥQreTT CƍѮ];N'""""*ݻ?2?'ODD͛xlJ*'''JIVƍE²||OOsi$ii@@tOb&{lz4 DbKT*ׯcĈ9gdd˗DDDDD$ѡCDEE)RS6QqEe*k=Sqq?0s&": V*RbTI=,Z̘`7p-Y#9g,ibEDzvvvlx0AAAر#>}H#F`ٲeܗ(X~5۷o/k=c/Ia_-:Ǐ??|d}NB%FRtM/""""""ѡC<~C m}Xb^DD.k_z炂ŋ/D'!mt 2P….?۲=dYtNQEDDDDD$PXXtHE껹aʕ02_򒕕ٳgZڵ&sի IHC}N%`*i7Dcʕifb[^Drs Dz |PE47n"M6ʕ+lԨʔ)#kM2&:ihFt M7kFW׵Y3^;r:c":@I{ի Ǐ/^ôiD$"""""@CE6m GD8xyy^w޲$y3`ot.: i$oIT^WKjh-||X@(I ZGbƍطoaÆnzaΜ9 ?mقWɺcG]7c!矕ѯ)o+:EŦLn߾ኍadd'Ncǎ9ΥsQl|"""""ѽ{wܼyS[Ea~ `۶m^z!55USLc%`*i/*L[.~7n3]4܀'zZq*98s@G HɎM/<}~!bcclٲ8tƍ IDATZ7f͚x"""""*t/_V~Vp*UJDT|ܹsnnnxqJ>>?iii4iFtEprrM͢S f  _ -ر !C:kر(ee5wwC)6HVcĈ٘&&&Xx1<==s=waӦM:CDDDDDKHH@׮]q%E7j;J.H}"*ѵkWɺZ"L7nUV7ox{{Z1m(5JImh=aLe#KeU ] #FNBqqx':mmqQQt"E饥t[1fM4:j믡Ve:{&<<c(NRaʕh׮(T\l 88}NBŘ- W&: bҍ7r=ާO[WT2e .][ʚJ*bbb xDDDDDDDD%J?>Q8֬_[NC^ EG!R*eK7o۷nݺɞL2Wոw$&&&Xb<<|Xڵkc֭8r^leAx{ˋNMfN"J%:^za'M'N(H$6:55syW^}ƖUTQ""""""""'ǴiPF Q,Y[nᣏ>Drt||76+`RIٲ%[ơs&031I68 Kaߜ$wܱcKKspB,áCЬY3ܻw/ʖ- *(̙3AAAuf͚:uꈎ5je˖Ç3f LJCt4KDGN"K п?mߎm3f^Pret<OHЩ(bb ɍM/-n:1ZQFaҤIHIIQl@ݻwG\\[oҤ TKDDDDDDTիW| ܹcҥ EGSSS 8NիW1zhXZZEm[૯DԤD/Z[cPX:a^MvT|޵kjYw4xX<{&WE"-iHMM8V1o}O>>}'OĹsp5EWQBʕѮ];t{F2eDG"C4j ܱcd;u ppNy/]=[Dϖ-_\7>Dpd$?WdT]4>Ϟq#.GM">|xMKHH別ٙ򂗗DDDDNٲeѷo_[nҥKtnܸ;w AOfMvhݺ5ڶmvڡjժcQq1m \&:I;&ŠAJ-ZhNH@pd$B|8/^˗/äI`oo/:@6662T|Ԭ)5)f$[L 0>0cP4TX..R3GtlqqtONCTh\n:+&O,:Q{Sh gD'!mh!'/$DƦ ֭ŋCR@ڼuڵxc)4ݻ5E{wD$S,GKd(ٳgXt)Zh!:QNY`:@@ϞSh/`j #CtcKF3f?(lƗJ_Ę<hDt Mv[NAښ8QZPl":Q%3///lڴ Kذa&NqJ,oojU)4m;&:ipqBCS^ 2d];d&MŋX&""""""""*lm&$ْˁkD'!mX[K$RS+˗E'!z+6cǎahР"cTT ˖-ŋQNE """"""""|HM }!!6Vտ{s`BIŦׯСC8p T۷իѣGȈDDDDDDDDD´hxzN)"D'!m4i"O"#{Id":@IRеkWt8qΟ?/ CJJJ-_<ѤIj ;wFuQwE')@RPa}! ^-:I `"`TZlz阥%z=zhGRRRSSK ,,,D$""""""""3 &8p@tl%5MƍL8|tO':I UD!rzvvvcQQxzJs.\$۾}='6Ə_%:I{jpI4p3(4o<4m /GDDDDDDDDDT*ݏ ~l >,:iUKt M[׬F"e6l؀+W`׮]:u*W/ҧ=RS+˗E'!m^^>.-sOcKK8zhs):nhh(^#˚5kаaC?~\񉈈V$>Xx@tFR3U$$AA`Kk5jt5fE KS###ѥKlٲE DDDDDDDDDTM'N)2<Ѩ0m<|}{H06K.B|_/FFYYY>|8g|?Bt MAA위IH:FN)$DE/: plzA۶m" NBr4Υb^cwo)4]H2<_t M/KƥNB%^E,:ڶm@-[VxLL f͚%(i?hJt Mq3ru0iTUڵkcٲe9/]Q@͚Shڼ8p@t Җ7*:[}DM"AA222vZAHԤ$[z:j!SSpt$[Fz5矢P ĦW1ңG6lZ- P' @P${J$˗ߢP æW1RjBCCqi(WӦNcO O{*"Bt*A*Fs=~'!""""""""|u):_E'!mt|BB .Nt*!*FnݺӧO8 Ր!@߾Sh|XHM1h0p]/E'Mbڵkؾ}{ݻ4DDDDDDDDDT _}m+:ÇMD m|=E:a":>HJJB\xycPݻy.o>@zShںؽ[t ҖShڱؾ]t *&ʃ &L˗/iӦhppp D'ɖ] 9#: iTItlj4II`-ԩgb;1H[I/Iz,] ܻ': ilY27$[Rۢcӫͱe|駢ܹsQfM1(֕$* E'!mԪ%-uOyPIȀU@&&&@.]DG)3gDDDDDDDDD$v퀱cE ̟ĈNBhBSX ^`bb-[raΝ={(DDDDDDDDD$77)4ݼ)-K$: iO`P)4ݽ ,Y"-ITHlz6m=YCժUCݱvZc݁Et~#]Et4nVNBF?:7Yf]ŋѲeK={ȀU.5)IL 0>*: iZ5Kt Mqq?": 6dpelwcǎa޼yE/88qqq9ǣG|r """""""""ֲ%0a__ *JtF_$2R>^E޽{#11@CVi̺uڵkhڴis/^@=\1 &:%K/E'!mt .: `" !AtlzٻضMt ք @VShڿ7)H06`ZQ KƦM`nn?0""""""""""T&:#GD myyիNif)H 6c>|sqq;#k =t̛7Oֱ*x{66dKIV^aeeʈN-- .^aKK@f!לUT;w"y&MJʕ+ Yj|铸8 QSϟlziܹsV}ԬYfff{G)Zjh֬Y㉉8t"ci\KDFӧ67Zt M~~үT饥+W8ɓ￑O˗?ѽ{wE3c]qȀt .: `b IH;#FN)8XPE%^Zxmoo~ FFJMLL dF'ODDDDDDDDDd zBӹs@F$C>}Dtjlzi)..N!C`ii)(&M(l"""""""""-Eд?oS<<6mDt y#lzɤu֢# 111joq"""""""""{@Shڼ8p@t Җ7PlT饥7guUTIPl>ܳgt )#:I4 |Yt҆rp$[z:f p$06dmm:))IPlgϞ7$""""""""\U"5)6*VDД,ZNB bKK*Tx}5AI$7n+W<4DDDDDDDDDdP7LBǀ+wտӧ/!: )M/-U\Y둕%$ZɓJGi u !:``Biww)4@\$6TF wŏ?($95:JCDDDDDDDDDkPO)4]Z%E 0@t M׮ITj$$3 Uƍs9s&2220k,T*3cԩX`[ZyIIF )ӘSDSF%KASaH<}[n… Z7ڴiHDDDDDDDDD%TJ0i$Ef\͚Pa99I/OO +KtɫW%RPj.V/Ec޽{ѻwovZXBgVrr2\uF`mm-0QRRRpׯ6l}Qaac樃;9)4YXUff6^Edn{htΘ| gzAѸq/3(B2eйsgJDڵk#EG "zDD21RR )8IM~O5:z=hԩ#c5.EDd8ӫO?,+++L0Ah:aÆׯ rs_!CQ`""l.^ΝH6jBuE.NV-ww5_!bIQD-ҢjPE[ZFդZrί۴k,.:Lcߗ !BBV ?>SK}q]^N~{|ŏ M/.y ѡCIX>}:>⺞DD C&Mxꩧ,<<5'NE .xADHWW#+/7x]_KJƏ.!g+q~k_}=]vxw3,d2Ig=qtL&Z5<`*djՒ0+(V.B:OqIO)(_<֯_eJQIWt+,. T 89I؟ҥkɞaÜ5!;'"#u\{uؼՁW~t,\wlX C]S@Nt ,^ڸ|K'شiv튓'Ovlܸ͚5k """"""g@`0 ۴k0ctY^zMd{~s дi@rʸ(_L*s__5S8 0POթ#]CC`,uMխ+]Crسg:t r~|7իHGݻÇKWX ;wKH]Q+,ED%ENر^nݒ.!-ڷ&Lt0{q襳+bCaÆؿ?Sl$"""""""+{5h?rXΖ.!- tlZ֓l/HWX:sXHO.!-^z P9-JjZt >P,!=׿uk6T%f9^=.oHDDDDDDDdKvF̛$'K:cJWXzU]SII%E "#Ր"!Ah8Qj@/]B4O҉e@Vt iNRKeI3*^RUFrjy:=}&]a),L-ɚ*]BЋ0]+H1cS_FuըQT#ٷX8Q !]a)4X ϗ.!pEDDDDDDDdL&۷KWV&H[+HS~FeEidOҶml0mPtYn.r%pt i_5jH's.!L&SҚ5޽մi@z֭SO(AVV~G|ӧ|}}888L2TG$j8a2aQ=N.^.!-VU7KRS^Laa%E@@PtYzΝ.!-*TPהtYFڇ)C/+:y$Fjժ^ϟGRR2~ۄ3''o~>EDDDDDDT tSrOxC6_?` KΩeӥKH>}^dMM.!-zxCRxRRKJt4g+HNNv빹>}:z4lر/#g`: j(kW KWV9Á=+,eCᗑ<\ J(zdѢE?|TRXp!K8=`#ѝ;wsθuLj/#ټ[ jTys K|l"]AZM l)]aiV 8XWM% ^: |o~GTPᾯ=z{Ffff88W%fW_"]BZkKWk{JV&PtuөdL&K҆ ?JWzQJJ f'sغu+ڡC0hQZU )KRSE9d{TQ7p?JLz9ҢbEuMJed}O.!-\]5UtYVlptIWEݵkW]KkW0||?#ץKHFiӤ+,%&g%ާyҢn]]SoWH=ݻ3ghÀM2{t:KWXTCҢ];`D KׯfUmڨ$*J KH-վqFrㆺbbK^EvZJg`ĉѣ}ߺu P ttZlO>kIWXpA-iuAϞС.],RRKH=å+,AA;%vC"XftsARW_ݻUDDDDDDDd(F]HWXڳ0`p{w Kz5PP ]BZ~ʕ@nt ikjHo$G˗%vC/nܸÇKgnݺzjj*6n(PDDDDDDDDƌWWW4|oMԮ-]aVPڻW2u+,[tie2^^6lv풮 M5a~8ȑ#ڐ!CpY\z7nħ~)S`„ Xx1;777ݛy~Q Q,]b,Y"SAoM22ԞqOKԊK̲eˀǥKH gguMU,]b9|Ĭ C/.]tkXj֬Y__߇7&L{SjzRRu?٨Fԧލ$!=.!- e#u ;zUWxTr20>pt iFrn8ڵk6~x 6~Ez'lٲZTT#"""""""֮_fR0=<L$]a)* 9.!-ɓ+,ݸ11%Eԩbbԍ%vC/-~_LL+'ʗ/w$GDDDDDDD6o_W+,],ZJzCJWXt XHI.!-zιsG5JRDz03SqQFF[n5k (/^|5#""""""l{w Kz5=mo={JWX:xX ˓.!-^{ Gґ#j_&=/$]aq4ӛPٞ={ҥKc ٔZu+ytii#]a;+Hm+,qti5aоt˗ l^+Wgdd 88_s/n] Kk!!U@Ptۥ (L&aC K6;vHWV&-]A:K?uYxG!>>_\r1ͩTI )\\K22%KӧKH K̲ (ʕSהu˗89ӦUJN8ҨN:x"BCCEZ6oތ/^"""""""4hn(ɭ[ܹի%Ez2^<=>u`U5jkAtF 4{ڱd :O\;V]S{JziTT) ,x\r ZJPt@LJJB%ٳ."""""""0]nub ^Q@%ɤ%f6)GMOIUFz<&П;']B `رp(}6nݺƻ9 IDATd^ХKxzzv<""""""B,N.!-ʗW7*T.1/Wˈ)WN]S+KeT#=>'' @ "7XXO5spPoЫ|}}M:Ǝ+@DDDDDD ;.!-M̟DDHꆲܾ /Kj{W]S.Iժ#̳%z_|ҥKKg>ƻ8*͛㭷ޒx?Jb""""""2Eaä+,')ܑ.!-uFt 0o,]BZt #]a)"B=휔$]BZt/]A̚5 ͚5ΰ0dK:~U@^t i1dлtÇ~L:Nh`ॗ+,?,b嗥+,:,] dfJJWcKe˖Epp0ݥS 6ļy3` wm+,iti5aоt;+Hc+, [']AZ t"]AC/x{{ᅦh;;T\Y/_ti4l(]ai` * hXƍKWVӦMJWX V zJC/m9͚5oooJf&lpt inU$]b;zT(S0\`J!ҢT)uMU.]b|/%մi@zGA݋:t#GDDDDDDdKsҢNuCHn˗KHZwMݽKKHj5(]b ,^ IUkYC/+Y&v܉%K?EP|y| {ŒHnfbcKH-)S+,ݼ7KHf͌7hǸTTt iѨzڙ Ǯ^غu+^{5VZ?OX=z4.]O>5j0a0e8 DDDDDDDsG 9Rҕ+/=;GKWXPO&%I:IWXfKH~[n^IIIԩ 6󈉉1g4ogΜzMHcqk'''t .ĵk0|ڡDDDDDDd/VR{<Wұcj/=KWX:u XTIHu]ٳ%@zt iѷ/vxPNNz#G<{1p@;wXrvv+W^y ñcpDFF"&&YYYHKK*UWWWԫW^^^hѢZjrYH!%on%f;wa%Ÿq)KvVהўn3zBBKQ#]BZ۵K`Cs>r/D^ʬTR񁏏O&lؠn)]BZL?ptƍ[6MP>ȇr!]#Rq PbX mTjN.)nyÂ,X౿V!""""""BV.!-ʔQ/\tC%ERꚪ^]Ch|૯T#N@PtYAzj ԑ(nuEDFF>)Sz1DDDDDDD@Ppt iQRɝ;@xt iQ\@3SSE0COpZx.O5Jԓ..%%ǩS |+WÈAAυуܼ iL )$69.!-6U7$.NOEEIo@̚2 wM0v7JLL|X"v\?ڶmZjlٲ_>|M#""""""?|?_=EK`h Kܹ@Rt iѱ#0ntH`lٞ~[j ]BZ< 0itEewC&M}ݺuyfT\Yو,fz_dɒ{'CDDDDDDTdǎ˗ /]a)`R 3S_]WFrӥKH}W_tZ!z (=֮] ???$&&"//uRJE>V\+V# `Nʰa%Ÿq)KvVF.!-FVTHtYHt i1bzjn55n ]C5lzڹSD'\I\rТE ./Ct~զM+]AZ=$8; * @g$_ |ti5e }dغؼYz]uk^\1*&&F::rr+ÇKH GG5VM,/O]S%Ԫ%]aVP^mpL&N KkF* __İWݺu{-77_rrrEu"""""""s åKHͿR% ,ZIzȖ'"^LK*ӦXQLLF3YҢ|y>UtI`ЇIp9]äDEE!::Z:Ⱥbc365mn(I\DEIF̞ \&]BZ4h`k*1Q]S%Ezig:zUR^^^v>Cff.2ړ^[lN """"""*@Rt iѱ#0ntH`- +,] %3#]a)*J}#.NhZEVewC/h۶_OMMdBÆ  K!i蕒YfIg'ˁ,Ң` KgK%K/KWX:^-u&]BZ "]aE$kJt i av.^}yףQFhԨFe˖!44IXDD}\v }E'"""""f.`: jsg K!!ڵȑ@n ((.!- S # VKH!C@Q:zr!##/7<<X|*U ʕ+J*sn{="">>>p)o߾k׮!77XGDDDDDƖdܾ}?Ґ;wX| *|UUe i xx}J&ګYVT%Ŕ)jʓ'K̶nU%ŻkQV5ӍxyGwtݱˡ^u,[L1n߾۷ok .h>/ѣ$&&~]v FLL nMJPfMԩS>>>A&M*Ur"+Wj_=&|tRPY;Jא&@2uԐhO7ڸ\DǾi#F11@t֮Jڷ/֨R.Vާ\.+v9wy+V@~~t ٰL\xaaa77n >>YYYsp]F*VRJB ]6WOO{lڴ)P]8MDE3gܹs8{,Ξ=ֲ?xڵk^^^ر#yt^^^DHjqc*,";[FIMU{1yx>>5TX* AgB=6`4gp~v;[anܸGȑ#8upڵBœv~+|||O駟FN_lҝ;wp19rGѣGmOIDD"""j*@ݺuѯ_?+h׮d䊋Ӂ:uk7VC?|0@15YZ6TӥKٳ>Փ!"iuߗ.v;O>۶mCbbt L~~>N>ȑ#qFwݻ5kk׮֭^xT^ػȺo>ݻ{ůڵk3g̙:u`=z44i"F%ի9t V @Pc}VZHOՐjUkֶ;g\(`L5Qj//. vN5zj~ʐ.]‚ 0`TV -[ɓuV`ڵx7QvmX~=ӥӈH޽SNEVPF +X`Ο?o?ٳcvG6M/ vYF SKIO{CHWXxQ-ɚjȖt"'gϞOa2Sؾ};mۆK.I'Z^^v؁;vB 8p }% -//۷o޽{g;wD7}iӦ裏п$*IBBԓ^o%]BZ۽_0@Nq6߯3mϰaڹS,4T5~<}~W-HnSJgQ11l0T^;vČ3lrg)))X|95k[,HDr]sř3gJΟ?_~m۶Łs$k`V jy~3NjFٲE"ݶ  "xW"^gaɒ%(St ,//?F5jo߾Xz5nݺ%fغu+ڴi=zIDDh߾=|Mܾ}[:J`j& x) dj5k={$ (Ǝ.ߺuO?IWم3ѣGh۶t ĉxQV-t+V@rrtVڵkZh{l@AA+ Tii-[Ԑbz 0mJG۶M]SK&}.1{2DȦ'E`OUZDDDd0YYY8p VFoѳgOdaoL&SҚ5= H%)ׯ~Y2 +,mtMˎ⋨\tL^^FkJ= )ʕ rKӁ%K>_dXvǥ3OFT#=> @=jYYeJHNNFʕv0͛c?FDDD#Ff͚ڵtlٲ_>֭ڵkzpww2e"%%HLLDBBbccK.!<<Vɓ'{a >.1KLfOՓ?y,]*Q8IIܹ򒮡ª[W L.1}7O]SO>)]CM"WBB>3lٲׯ_zV_K.ui"T*Uʕ+lٲpss  ::QQQst2rrr0p@8p7!BV|}}Ѵi{lРjԨ p|?TpIIIݻ7?77b??=777M6hӦ Zn:u98vZ QPP#F… (sR1G=a~tYXp!0y2Pt X{78 ]x8`lO[%f/kq-[eFzz5* ?:U-CLd'r蕘^z=p<[v믿_]:&9997k~~~ *UN:SNbؼy3֮][O]|XlY ;v?N:E(]t=hݺ5Zn>| f̘ŰHbb">c̝;b4|%f0~"Ttim~!>$l߾'OFV 53''' 4GŦMkѢEyM IWXڶ ؼYuo Urfv`& ղFcati5~<Сt]u+tcwCl^?""B*WcǎYfIDDDWfM;8t"""`兖3rqq|ח_~iyG۷~."RT!C`M6r=3g`ĉpppڹrrr`㓠n] K?,]Qbm޿[??X4]XKm`pM5iJWV&#]a)8XO5 N>]7^#DDDd˗ȑ#h̙3 BllUAT… ѭ[7899IgYUq!-wFnIR0w.Pa&.Xd?zu`6:m`|eҢvmėܹ,Xp_TzH7MI..^.!*JɅ K.믿ij>ڵkh@xWc„ XtV 0WΑ?V;>QIv~Ȯƍc޽V{Zbrrrrl֦ /]a): KJ>!!ye˔Q/ ݸ̚<>d@O=L*]a)&9S][d{|}Hԟ}QQ%Dz>}0zh4nO>$^u޽e~! tGAAaҥ8p_-!""*Ne˖Ÿqp%sVc8,صkW8ܹSA tKԓ))%vNZΝ[c~Eti\"+ S:d{vF̛)Iԩ0vtW9s[K4Wr d!<<k׮Oµk_FIVSfMWZ%:ٗcذaw׮]o?ہM+RȩSXYaFe+; +H+,_/]AZt,]a)$$z=fWZZZz\X^\×Jebɸr OnXC GGGݏ}%8p@Q3<<W^d@&%]aiO*-3g*ozmXU6mR/M&#]a)8X 6}$8غUPnUn^+((… u?,\xQ:j1rHcƌpwwN*v;wɓruYDTrժU ?t?u?&\tYVZqҥn..X;:uM9"]BZ8:!Eժ%fj9V~698?IAz5t cW ?k׮\Fz;w*OAӦMqY,[ 9qƺwݺhر(UJ߿z~%Dݺꆲ$'WHؼcqH[m͝;@P.]BZԨ%f))…MUӦF ,^ t c |hNN^z… hC\c옏3 lٲ1c u?.lGgЫf7n@P*ҳ/²5_ԱJPL 0sũ(xTB0{6pt _Z?|}}ѹsgZ c˗1| """*&}A6mt?}t?&Q^t=^%L9wHؤV!g'',4 Fz""yӄd{:uƎtKH +,EFs AAAz~~>݋{3ϠI&Fj *B \.1336mXYGľ}0yd9} 0@c۷CDD]vxQzk@b"PtuڏiLq8, sHǘ>dqLn(<(]bcy,Y99|hV>8P*ٵ 0ӍxƌQS}~Y]SFIFk知KSԘ1ώ7vb"""")Sus%]GDx'u;^vv6u;ِaC K6֬H?__NcWT#ɤ2``V jTys K[_DdC/?~<ʗ//ADDDdU=zxH^Ddz>Ub+n(W,]b9mTdc""s$ҢC`x KjH ]BZkL(]au5L.!`C/~ ggg""""{蕚 ##Cc)SF!٨A^t8l%]"./?nn;V*td (~{;KO.!-^{MRXZ$t 6lt jI6^Dd )))vpppxd&Lڷk~t͛q{R?*UҩȆ3nti5jz:H֬ KHÁ=+,W"q%bQ^=""""]UPA4u\Sc09F l.]!Rt4ߚ5E:Fz.:ف͛o NUɖ-٦ɓ-+,mݪ#Tb^s'st\2!<<\c=䓺섓0mPtYn.jptI/(YQ%]ߟOuQ~>W/HV@fi{KH+ [WҺuT"!%jBfŋ1f.yHDDD6/33SQvv6"""t;^K}F uCHKKoΞ-1>>^5kTdGRSE9d{TQC ggt׹s%EŊE!|_~%ƍg}+VDFPPLq`ܸqhذ!ʗ/&MUVxgO =6o\,=Dd|z-$$DcUPC/zΝ1c+,EDs窛vo͞"X44 Kȑ"#Ր"!Ah8QYlU6t(`Lb(`$KFVЪU~O^^ݻwcҤI}Ϸ~;Z3բwTTW.BT+VPĮwE &` {Î{DEPDqH&Rso-ֻ8{q'55U9&&&r?6)) J^bŊPb#=zÇx%իWLܸq7nIn:%$HU$/LBÇղ>zDC+\$ÇrONN}wɓ8TMXZۛwO7mߡ~zLN aZA88cjnIr~ [͕̚DEUH:::J.kӫL2jF(]vhݺ5tJ]vaܸq#55U/nnnXjhY\]]dtaL8?|/_^dׯw.R:B:(Y^XLB۷o㉒{[nݘ"n * |w~~f 1[*U aHct%Lz|F^Ν$ǵk90q"; )aÄ>N$͛I.#$6W(JWW˗/'I5Fe˖}8p N>;w`ڵȵv%' ---iSBSj_~"Bp(M\1 ?_KK `h`0\\y :;QԬY@ƼS:rDx"itaC)9~\Z3eF֪iڴ)*TPQ `ڴiƓ'O7600@ƍaccSSS܎;"++ @``{T+WZBrT' 7ƤIG{>DVV,\/^f͚z{ӧOEHgϞ!%%Y5j0E!w!b @yR8ڀpP*{de;w 3)lmyabs8vR5v F%0x'dg ˙NC ̘{;I{1eg;$ 8<?ǏARj*SSՅ!uuaT `Z*. +33T(]&&k6?}oވS_ ;w杄h8jzizQK"7o"::woB2001qD*GѣǷ?~V¦M iԨ/_{{{ޜEԲeKl۟CCCkILW\uf;k^ ;B4\fdS:u#]4i7ZCKK SNeR1K\PF cnԪ;R>}7*UƌaHLMs.(wv$% {ƙuNC dɜ1M=́ x&":^ (a_0 +ssԫRMQLFFӁx뱐 l",ڤ 4DtҼ#<`ԩx)b)ccc\znnn 7rSF _Ǐ/FݻwǍ7ЩS'lxB صkFsfffbʔ)6VZm_CBBrՄ>(RA`B#+ݻǬ^^Р_t#JSG,%?߸:y|U)S`bl(Ԩ!H`J[I"VR^ q=BefeƳgpݶ Əe>oڅn1kx@ZFB>}±7p.?Vu<"cc?A{֬y'!^>>>~&N;KKK:uJeYV^-3c]]ZZZb޽(Vhyx5kε\%lԨZjsGo1GQ>}M%7---k׎Y=BHѵo>{`ѢE"M`$)d}+4)^DU%˗qujto?i(j8:N!{` FO3BCww,+DXc~<4৯_s ',CKGGw/YRI`L!&#$DCQK4nӴiSޑH.Z|6lyƏɓ'k 37 NNNS*W}" !Eff&zk׆%zĉ1b% Z!yߟw YO%%NR(QqqpZ^%u_gO` )dx!,; QDn/N!k`:,' |QffqK߱5F@Iu$ j.ȑTD` v- D3PK ZZZ011GWJ#ݻwԩJƓ> |۰accc$ȑ#ҒX9sϞ=cZsR&8̜97ofZWWW?.!pq|wз/$:q_Ta\nIY˜wGқH3}֝;8vLS11c~9z{ˠA(idN>uK5!q065a= //o?W\AGG>DEi&n~/{yիWs=-C) U-[2I|8r֭˼;Znͼ.!77ʊw=@"61X]^zz쬒6TTw Y{/NAT;{sx /!9˽a=|8V9f⹺֪ 'ӧy ^&88wRWQϥ,۹f͚*NBQW݃ӚCռ Odgg̙3hٲ%~'2?ѣ1{lu T,:ƍ,M۰"#1oԮXQ" )UJSŋN#9Y3#I"&f<[h2q"@CCaLF[JkV#Qk yD_"***c˗WqB:ƴiӘ/!D߿amm D>}i&jլ)\H`J[Iv(9ã^*=`DTTTz5; QDT)֬{y-Z8:b-y*_^zSu@P$DPK!%%w BH>򛍩, !ׯ_gZwިVӚgbhԨ*Us犺 A֭GG)d{X!4$"1%VDvv5 |3BCww "w&M3yxx>NB##3˽S6Um Sye&DN)hٷowTR*LBQGɘ+5 ! HIIA\\|/_ << ‹/š6mݡMgEWD*^:6MX⌳6ǏJ՘ڧgc(u&̰ڽw_63fHk<".]FΝ ֮fJ䝆G@` ZLC CÆ?NS[>\^OO`i-H 54D@@:;!oY$}@$`ɒ%xӚ?#6mʴ&!D.\@Nx!֮]QFBQ&1u*`fLp\Gt5' IDATR5*.#F . .(9;IaLMЌZ3t:u$9nmLx!5>΅ɘأ8PU./¾qS5DiB 1z#'X|9R[˝R4o"0kШvT]BYkalh(1h֌w Yǎ>>SE99-[N!))H2231sl|Vs@QKb̙W޼y;!D#BPRR6"VP>}ЦM5 !D^FFFXbnܸڵkCHWWB)d\n۶'١.ҫ+P ֬FR85N杂OooL۰!@Z Tij$j^j&-- DNPfMxxxEtB{%(bܹxӚ`ZB䡧qט6mthy-"5Jnn@⼓HNGTz[/^`ѣJ0+Q+&L`HM VjσE cJJ{ ޽; #G }\lܺ; Q3R_ܹsQ|y.\P҄6xG cڵΞ=Uv1!DaҤIx6mڄrDHުU.(KITz5>,c2rD.UQ*5VL_1E&kAA.L${`YnQ+'8aL~; Q#/JMMűc???jr"#88!!!D||D (N7$9rT>xhlm6E кn|gm&hbm AC׮aۙ3rŒP`߾˜Ui|=|l,.Vw"a˗رclق(qQ{aĈxYǍaaaDFF"#/\o޼֭['Y.pB͛7}%-7AHo>lذy*U`ŊB?|ӧc]6u놾}y4ۃ3&ݻ8v 07 bZ{@xլ ~bHC99 EIaNBS)Sשy'q:5|8:hW>zn^_3x)el1aq7eh(ƭ\}5a \,rpASGNB$Lw(%%DNPvm,_^Hٿ?ڶm+*Q&Lg"11x glٲVVVԩSqEUAi }0## cǎe^W[[;wD%&ܼxhٲ%*U}w,B T;}癕{?W69;CG.9BӼSE5kN!nW a~{TTijvgeK8Wc QIGNA$fzϱk.l޼_~9sٳhӦ 4hҥKT 111Ell,"""p-ݻQѻwo$%%1=k,iӆy]BGhh(-[?]vŌ3о}{ޱ)cc@B4`w%Ah)9`vhTR5sTL 44aI:ssY3iHa 3Rl.-E?!uꄱ]ajO U,-mLL c<<08XsN߸͛jk cjt -;T*+K坆H5DǏK%Hݻwcݼ0; <ϊ+lx8Fa@@.]uVZUVywpp<Xd :v(V4Bǣk׮M4E%‰'p nK,Avx"*KVV"\m(^~V,VURQ0oj9*ilIrkT?4)".NS@ {ˆΝQHsZkkY.\ aQZq^~N鎩2"^ M4AӦMhޱl߾kiiDž?y߿!7ggg;vy]---l߾UHVQUA4ށPvmlٲwBS ֭bc lYɩJ~\bHraSp0ft^$ӡ ^JyFx]hkv.٘;v6mE;B޾VrDhyC}!A*za``-Ze˖UahhTTÇxΞ=0Fs~ |!6_nܸqG!Z k֬[cegg@JDGGcر8y$v؁"LCQQu ر<Е#R45r]\WG7C)=`VQ/שÇy'!y3w(K㲇:ϝ;/_rׯ#(<˕?$)Qί'O//Y+yRP\\87 5~x,]'33!9KBpt.(Ki3g}s6gDaիpASRݨJܲe52k~ر˜xv7~<$DUHڻw/y!M67a/͛zkkkhiizǺYj,dgB|}}1rHdee1]re8p $D4ocR+>>HMMEdd$m% 39Waz 8uQhUWW`ta)8ؿ_C1nJ$$'+un-Z6mA1$9TE gx'q0zD42©%Kld(c~=Æ<..B㫐[f"^r7֯_/ׯ|rܿB˫"Hڅ 0ddff2maaӧOܜymB_%J@&MTrt~o˗q^%(ѣSy QHӥQZm0Y\IP4%F''j\ 3OMFtТ4s23;1պ54jǬD Y:IJ_I:u @u*< %m; Hw) aeeSË%ڵ /FFPBm[nů;!̭[ЧO<(QΜ9CKB5 v»wS*{IHH@Ϟ=q T \P`Z (Ca_eVO|XPErS˜SBB[B t VŦiD}ҥdn.NIiD`Fij$*'W9iʕ+QN4m^^^_ưvڰ`޼y>޿+W`ԨQЖ.BǏѵkW$$$0mhhǏqkB`…x]>}9.)) z+)-EH^5fBVx8]cWDGZթqݺ)U^=I!%>E3S$"Bx D- CV}YSz H` [I't:֗/_Ɛ!C`eeӧŋcFXh^|ϟŋR X&==dž 0rH$%%D!.] ::ymٳmi BxBKUƗ/_гgOʼnzB5w YAA5ߖ^~,N߹TI==l>ZZ,t;7oի_y'!h8w Yo+WJg9O5fǡW{`ր#+{`*F"􊎎ׯ:`߾},5Ċ ƍk׮˗X`j֬ @X~;m&J4Hvv6h"ڢdɒhҤ &M;v ##wDB[hh(:uO"l2͛7'ڬ5qU4h@~cƌ>!L ;{['ظQr AJ#rg͛I"~IWR0&BX4 Ay^W`왰ԡWq#Wvv60`XZZbx)Xy244qqDDD`ӦMV.wSuԉCBBŋ1vXXYYiӦXp!;!(ӧOûwD鉑#GRBզMܹs3f F Q GGw)9s]]䲆u+Wl.L(Б }x ;VI(%/{N{FI##5 03FfPիΝ@v6$DL+""˗/G5`oo+mmmn6m§O~tzzz>v*JH[QQQXbjժ;;;lٲ?~v;vļyo>ܾ}䘘B.] P;-[)SRB K__8y$J,)9̙0Qjœ׉DpD=slBqqBpDQ..qRrp0j&0{œ9Rrp D4镕sΡo߾PΝ ޱTNx=_qơDr?r6d,]+Wƌ3oʔ)ggg\xŋ1h 4oBHbccǏR3g( !DG ׎3󺄈B__lj; `/DZwoƆA%]]Z4$923I\]rxȑ %!ػ7t^/t Ɣg0 Zt)W.]#x f͚+++jrl"cǎvpssC¿([,֬Y\:t.EHQ3qqqܹ3޽+J}''',ZHڄ‚ _.Cʕ+" ++͍w LYK#!J)SF¶R /y'!07Ɣ>$9=D55E ּHӫT)ὯxqY, $D$NDD;.\mXU !ѧOݻ7?~)SАSBBQNbb"z;wRԨQXr( !+(-ŒjR0㋓Yt(D3UFD(&fM%%ʕH{#k3 (ɩbj\r0޾坄L#^R[PWW;vɓs=^zufqQӋHYFF뇹s"++KѣqasJG!KJJBqU8~l޼ZZZ'֪W___3/]Dz;V姍0A;G˖ *fڶ&oU(I"Z_wB"2wѧukh36[ea"4pwDcid+88w’BCC燥Kf͚1;ݻgj,GGG~{{{{lܸ.BZrr2w˗/R~¶mۘ 'U3֮]˼&!' @5JJ5Wয়}y1$%NBѫ0p =:LLD-(KUAԽ;0t(0,z%,; Fns1 c~ }-[e˖eVVΞ=7~{---xzzҾ]}ҥKҥ G5o<!.<<|'B6,Gs]|ADt 0ǎ~Æ qIRBxpuueZ͛+ӚD2e A#F($˜$GB缓E*%4) y'ɑ$ $V7|aS))}MIlY'kzEGG#::y]o^x9šyH%)xDdg+8FH>gff֭[A!ddd`4g IDAT8z(4h???RBx5z8Owuec#\Pf%_ְaŊڧ8DjeL)%2XxwkkI!%_+WoN"Yf%JD%$'3*U7~V޼ᝄ0qM@jԨݬ.OXx}M-9?/_xzzzͫy-{ܹSR_O !D2331b:tHjٳgajj*J}BIKK #F`Z֭[LR&N!CVBak L;w&Ed$$D-[NNS {Mi(+ssfSR 5cۚ  W֤I;v Shf>zqΎ\DV:|0.] }'HMMŁ |7\kTRyx"222[Qzz: l?zQQQf$%%Ȩu-eбcGBĕ#Gb޽ԯQ.^2eʈRBk׮psscV/ Y-BgaH7)eԩ,ޑݡ/Vy.U kՓѫ02Ϟ KN(pн;;IW 3\D70`V+95Yo~Qxҍ큁uYth\KGG=z@=c_{Abb51c hBĤ(t/_^BBB憿K,prrkײeгgOUTXhh(֯_S[#%%ƕ+W.ϣzGӧѷoBG`` ߿qOOO :NA'I&aݢԯ^:.]_'_>ŤÇmF"DeƏ.(_; >8? ?LUdZ;G /\C cIq+-`v`dD4ՠ~ظq#ñi&/ԟ:u -[D&MU!T9pwwСC!Ǐk׮شi\CvsB-צM|Ϙ1K,ZBBQnoMÇysqq͛R4DNA4ɜ9@ÆS~z1h҄w Y N!9Ɔjed =#Y=΀&8!ЊDD7nƍׯGAFX߿c֬Y8p Qn]&͛7G\\q}8rw^8ph޼9V%KbrC>>hݺ\GQR%̝;"'%D34jǏG~6qy4nݺزeKc6!$/...Xz(˔)sΡjժ')c"V-2!X[KoL}\)BD~UHoL} xzoN" ,^ S lg)TP$L200@~Я_? {w6 |˗/;;;;hF7m8}t :T,rl۱cG|>>>8r߿oǵQR%ԫWvvvݻ7*VoaÆVZXx1.^߮)ڴicǢ[n=?ٳ ]nmLMMq=&,HQyaٲeԶj׮-J}B%K2W7BԎ-0e v-$DSl 89"ХP?_MAKf̜+x',XqJ%0YX1fո10k_9'33'N'PvmL4 K_ω'sssM [###9#Gh7v7oǏ~!=BWWMh3!jk577lllDO!ؘid,EKz ah݁H`>Ir| _̜ 0~o * N;I@`:yR4\dggC^й3%,-(AA59@R9 caas"88GEN 8::|0a=z$s<22ٌ7/???\pϿ"DLLLd211)E!߰xbQj*U gΜA=ڻR1GM/Fx dHK)d;vYYE ;\ݺlʬ*^0hгjY{[Q+:::իΝ;/^`ԩr-ÑM6aÆŁ\Ϫ{{{tۏڄBHQ_U%KĹsh(!@R1U_!D6䝂h3}&oLJw (ggE )d8QdgʾiLhZϙ3S9PKN5kիlذA;1h o߾>&&&I#BHZ 3g?f͚RBMBBzg"9@SMT;}??)\]jxup,*z r2LQϹ <;)5 &LǏqezzz>/11_|ؓ'Od!OOOL6Mŋɓ'ѦMQB:bbG!cb"\P64䝄h~Ɣ^?//CI"r2-@@$*uS-˴ )SS>Mztۼ|PK ڵ޾} /{y"""A!5[l( q kN>}Ĵ"EpAVTޘXxwJ&@P$*üeiɴ^XY 3S$6Xc+#5(W-Zw;++ ]v'>p{)\B!(ڶmƏlǡCСC !D1DM/RdjL;$͛ӧN!`|QƍYxxxB##myԯ/Oԇ\PӋ!=== 0W^ŋ/0uT|}NNN([,6m ˗:'M!I;vرcż>|}}ѵkW !D23ʊi=B$G``)&qp BV` n; QDQS Tl,$|i===Ԑž;cN!`jzVZXz5>|+WZeee! -BڵQ~},XyoƵkXD'B47ƌ#JKOODݙ&Mj_T^i=B$oHK)&[7)dݺddNB1hг'nx' WckkgZSa}N!}a߸TIȿJ*ggg899ܹsXnN<)E'Oɓ'Xx1*V޽{W^hӦ ?ƀDYB4СCɼvލRrG!ʛTJ*3g_T=D++RX^Jl!_ׇ.h&&j1 DF 8~03 ᝄ(QS7oNiaL ; sBCqk5[֮ʹ&M49aLImvcFM/B.]ХK`ƍغu+{xzzƨX"222$ʝB!ݢ:::صk 6!hW2fy"1xۯ7_ xחY Փ,WWa7ox'ɱ?`nNՕ07c-)nTka^Si{缓+ !UTnݺ5s~^B9AƎ;0 ދ^H+YR'~* xyNBad$%y'ɑ*,p0Q!aLIiVvz:};p6$|ĮוL/TҼcqwjzqe``~wƍCCCޱ!si 4kkiiaÆ :t(ڄiôf-#DT*\_ի5[ȯR%鍩` (w++aƗ01ӦreX3L2lgm 7Wx')$4*&M`ӦMǪUPreޑ!pYOHacY---[ƍc^B4ôf#D-5o.,&%>@D$DfN!+, Xwsy#.-5g@vdn]%%{_h($E5$TRprrBpp0Ο?ݻCKKw,B!D-?{FJJ ZZZĉ&M?iM333Hq Bxpp BLxI":wFBV` v0K;;`)dyxzѼ($+;==)7ڶe^ xZDENRdQKaooǏիW3gL-!"q׮]C>}Dix)SRB4ю;35۷om)-kCo"4MaU%*0x0Уnx'!0Ӈw Y Ɖ:ؖۇ/_2[JԮXy]Q3з/?LJ❤Hoj˖-ûwaԖBk׮HLL%K0gQjB&… ׵g^7}ܡ?x{NA5u*ЪN睂(j$M)d;;Es)Jm/m_:N!ES^j&LӧOq!TZw$B!Drnܸ$$$R~6&|>J^B5gy rsjB"Sw Y>>B^ CYkϗGNQPK ikkӧO1vXq!ɸu~Gċo̙31|QjBڷoünϞ=annμ.!H\$$9RS%x'!00.(KitaLݹ; Q0,,x'ɑ!,z$z.s"Z=GvK)[gi;Il`.UIjz1CCCxyy~Bڵh iӦ᯿6!h7obܸq1b(u * $:X杄(|y鍩X`Z 0wKKI%Ã7_L y#N uIoa!L$GBq#9$E541l01!n>|{{{DGGR +V6!D3#U 7?Ç e˖E.]%$EJQ&̙S <<y'!h;w Y?"n]%l MD:*Y uvϟE;GvP\9DZr)V޿睤HXz5LLLx BTǰׯ_E?f\Rڄ kkkxyy!33wѹsgƊR6!K`H)d sDz "ƌB֛70 zh&]j XBB1%r4:̜"żERcêA@4+h%c5ֱ^{0&$73KL,b&F{FEQ"Hc%9٣&(>x+/p8;ך,]a_%^Dr0lADD.^Ν;#>>>_裏wQ6DFFbxk.X`q{CͧW\ya~6t(гtѱcK%C S.P @S59zduSVt 3/G!C0wÅ yѠZ51@_S۹X1Ν.)t8""""p k]vŖ-[xl޼'Zn_8~8233{_s=QFѣÿ{=Bqcݓ̟ܺҭ` ?|Ԙ` *Jtԭy  8wW˝;ԍZ(+ ?ݸak4<>qo+U ;z \\ EԮf,\ugLDDDvڵkuyT IDATp7ʔ)#ALxBBBpqqAӦMѢE h͚5CժUP?G_{ 6lg QAyum*WŋsmHӮZS}$]bቛt T6Iꮽ|`pz)jAmuN'}=8E==Q %]\0=iiILDt|@|?Qti899YYYHKKjݻw8TDo݁QKHDŽ jM}tjM+]B:ƎUCK잃Mɽ{K5Jkuw\5 D$&&Jg䙿xץ3  0szY!EϞ%bQC 3mmZS/$]B:]S[V_^SN1ٳΧNIp\+"@DDDDDD[>>>x3΀!]b ] 9"]B:9Z^^%6YYuj MOK-'GG,<eUJW9#]`8"""""""SpttIJeA:奆frt)pt Tk*gNd 0Pt.-]`˖ä^ŞlY5*YR&#CqEDDDDDD+͛7cҤI)DϮ ?3KHG[SDEoo_ _|Q:żj0)HTݺuc)DԾ=0~tQx8$$H6m@988`R^> *T1ٖT(pEDDDDDDb'NE<0 VRSKHG>AOtQ]2?X6e 9;K؏n݀å+(pEDDDDDDbŊ/~z49 DLk']a l,]AƎ:tx_H b8r%7n,cFP/kzQqqq.^9T\. ]@FAAgIW.__Q# O> V cuÅիֈ($dfTЋ(jժwww S+RF˗/G2e99"]A:,LdeK.??+lV`oKT6Eoo888H+^(&+c̙<+/Y,@C/"""""\۷/nݺ}aN2bŊ^éSn:T\Y: ZZt)pt Tt@r2|9pt psSkX1` yk z5 ۶Eg4U<<7t(m؀%'tRS3tiQprrBǎ"::ĬYP^=4+Vo7n`͚5xHRL 0>%]B:WC 3sGHQLbc /77C~=>.Ŋa@۶;q#5 ^nnY[j=E¡QsttDv . <<˖-CQct2doߎ̛7wMx8$$H6m+""Ԑ".Nt20etjFvFŊ'#htF-v놭b?Ag˖p,KiS`l !ݛNDDDDDT8U^&M¤ISNСCow!))I:Q+zs(^tYh(r%0mbだ gնtӧ%JHPNꥆ%6?Ϝ9(UJr{w8ǣ h Q}P 2d*S5*VDڵѡqcҤ jV$EХo& 7o͛cFHH>'ODJJpUX[FVкuk4iEcʉ`3FtH</޽%qFV.;{jDArj{j_p?\p M1q[ҨX<+_ WG5РZ509wd4tZS.]B^Kg`0dHnS֧GHЋL>>>DDF>} ߻w_ܼy񈏏GBBC$''###Vwޅ+dɒ(Z(QT)B 򂇇<==QbExyy,._YYur5O]TySDZOOm[TdtƍTX2_ԵkZ?5M7mRΝYX,Y@Xt H2eаaC4lP:(w?T֕rs]PNOQWժa$$5.]B:*WVC 3{XrEtTd?Qzح[ ǏܹsdN$""""""7nٟ-9f 11%iSuƗܼ%IG(:ZhѰ!_&$@pfϞYYYO}\%зo_L6 /RV3g%KJPNڸQ%`r5<1vy=]qqu%6aa9sek(:vTkjjWŋ@L[0Ro#g^P\xBTT>| $''۷oGƍ|>|Mk`ƍظq#zTZ5oC@ĉt ȑ=%6!!jMM8:JPN .(tѣ<ɓ>d_Vv.9yR)SEk(Wkjvg^-Z :u iiiے?O;wXf DDDDDDDc:~@1kR?.]bkZSCHi#GKl PC9?'SK٣~O)]B:&LP[4:$]^Ξ=~!G߳n:/߿`ٲeyDDDDDDDd6HW.^]hf`> Ԭ)]a-]A|}:u+l1]3~~@4h"Ϟ˘"""""""SHIVΞ.!J ʥJI<|Zt (QB]P.W.G?-tW#e_Ѣj@.]b Yc)QkBg ^ŋg˗ׯ|||~=+/XV3W\ɳ$"""""",\DDH?3IHpQJה5R~u.t)rR%wO˗KHZSNlٲǍ7L2bg>)SѬ:LnTkmѤ #]aTtt h|`| *JtԯvW.hѢO~q%̚5 %Jxc/^ 5))]4u놑#GSN(Vcٳg~-DDDDDDT\,_ܿ/]B:vF0 -KHGǎ1FWK;o']aLMH.!m'JW<8ʅ={ ==;::bѢEضm*~III k:::Ý;wW_aڵػw/_nݺ=BHn%]B: z0:rXVCg`W/ 'իY_d0 U[>|(]B:U^뱯988`Ŋ6m͛ __P>S4im۶>FDDDDDDΝ@LJ&2mТt_[HW)SV++Hĉ3 6m ]:HWjzitN>x =:[ϱrȑ#1bĈ~x !""""""6IW.YS(0ؽ[tY,@:F[*'??A mۀ> ]@F^Ǿֺuk̛7/[?…%K:w 777ٓ!""""""+V<>(.(+']b|1pt (ZT ݥKl23֙GJ"EԚcl ܣGjߐ T$]Q(qرc`8::fԩSQt?|#7onZhhh^Ȯ$$@xt RE]P6wK+WKHGJ[SIIjMIOO5(bŋ%]*ZT1J˙3g /AfͲ9z*U z_V-wet͛?pt h3G(:?_OÆjHa&oSQQ%AugĨS%N 4>իW655r9ͿlٲcbbDDDDDDDv+, X wOtt ds dOqFԄѶ-0qtQDp!?׫NjL"]Qp̽{"555ۏݺuQ\py͚5sDDDDDDDv-- X 8yRt-.(ϛEed3.!NNjZtͣGjMH.TIj֯.!]f+q襩J*lܺuڵk>|g/9 wŋ+WKHs~~FIIҥ@6L&S0atQr2|9pt pwWEKl<>8^t/.]`8Ժuk{{~g"""in/m׮*Tk>vW/KDDDDDDTP?4j2۷ *Jtx{K<.&X.!u ׯK84i{hѢy!333ۯ1x53|3w*WK;t']aN5`" >^tjL,]at|J(45n~݋M6eK,~e2d"!>>>pvvJ'N K}+NRƥIPaq b"]B:zrxC;^mut QK#FeZFFzEܹs'՚7n\]]H/} _Z*N$""""""*v+Hĉ#n^ or&z%+Hט1@ǎF96Md8ʅ3gTRaƌpwwG:uPJHJJ:;;cƌ4EFpȑǾ'Ndu򜛛t֭_JW.__((صKt4l(]a'JW.I ;ۥ+ ^PBO^ZZ._(CM'L?OԮ]q){geeg_(ϼ_5ѣ%I <=Kl=Rk*$DtY,@J6V+aCT"]aaptQ+N>}UV c_駟ZBZ[oƍ|{EtttHҀtQRt)&]B:*TPVr2|9pt pw|}EKlYL.HrԚrq.IIQgƝ=+]BLo6mB޽s\KƶmPlYGcܹst6XVV>6"""""""mfr6ܼ)]B:40ߚ"#KHGݺ[S%[ $.X.!7z|s+WKO8|mڴ֯_@--; A<<" O:ZI~+ΜQ[H޽+ΟW[>x ]B:z 0tImɚ,]B8cq!|5kիyzzwزe N>&M[Mn@DDDDDDf1i7滽{M+H@F7JW1c+6lrp ȑ@׮F!!ڵ@Vt Qr(ڶmmŝ;wPD =UBԨQ㱯)SbŊ|~TT 5jԅ IDAT@͚5DDDDDDDb,`,mgOajΞ.vw#eZS%6۷滻g,MٹS)H z'''TX+V˗q ''59sGF֬ʗg% _T۶5SQQ%665e){Ԛ.ٴINK7$""""""WR88Hܿ|:쏇,]bb2]}j"]bΌ3]}K5UtÇl.!z?I]3`| 2Rtԭk5 ,X\.]B:ͷEue_[S @xt QqGۘ?>KܻwO:ȼڵ&L0vM]P.!['KW]Tlt h6M 573͚m$* 7D8ʥ˗/{R 9s7ٳѣGxyyҩDDDDDDDԯпtљ3ʕ@jt &550iҤ,#""""""3ǫd~`& 5f +F~ _X%c(K `Z +Kt t.]atf )]BC/M5o̜)]aoK_̑0VKC/M9z|-жm|!""""""* 0:w#=ٟ=C+.^>@mI[7` 0`2=ѹ30ztѕ+jM%%I!4UP![srr€! cW^0[`zj.!F]HWkYY%cp{w #GԚ̔.!C!;^ K.45lߛ}+NRƥI+Oxxxoȑ#޾}PfM=gϞͷՊ{/ߞtQۈɎ@Pt9Smwh&l*]ANU۲@`t4 hFh^`f "z];w{iiiXf 5joooL>}ѣ\vzz:M\?]XU+6m ] PtQ` ][hV5"dKW!=0'{??~uؾ};Oʕ+@@@XbX"ʕ+WWW\rpr5qqq8|0\""""""z-.͜ P:uk 58;;ÛGF?#]B:6fϖ0y?uKt4nlA*֒Z[d'52{*2RQzijРtVF/˖w5J(,Lݝc)g^y;V(<\ݙ(]B:ڵ&L0vM)lI47ADDDDDDDt&]a꜓L1t(гtѱcyp 4G)`*u~ٟ~ԇ+Vs. ;(_<|_ ݃oމKD4-::{8gdLuֱcO瀇0dt :SL+|w7RLKݫ֔n0A7%65ePK^DDDD/_756I(wd^5\oش (_Yt¤KleHc!ŋ%6AAjMFE ϝ. RF*&ooo+VL:T)5(]Z&-Mmvt pqQ]]%#X\w5R9;~~.PT۱~t ppPKlV`z!zFp DDDDDDD4ժ f,Y\*]B:*WV$) X\wQyy5%uWܿ|pt P9;K$'}dРA3ӭ&n:\R:RՑ#GdɒB5DDFEF;Qa/Ξx9Mنߺy1C P!+QQ6nmTQxqߨ\QyrM///s;wٳ]bc ksC\^Ov Hge[hhtѯ:H80TޙCyC) WyqMQ^KKM no z>t=3xW.pd͛7ǔ)S3*117n!C]Ȧ#DDyvx~} #G۷+Ud+Փ0dyQlY'8~\[7kIsmujtԽt ' ơW.ԬYŊCZZSSrei?<ʕ+<<2==111ؿ?..]K.DDOuEkܹhԨ`o^DTxq ѣ95f^U:ODfp*Х гtܼy08p jժ%XVZSI\ t t 30W/]b.7rKz傓ԩ3g<=777,_G"jŲe0m4deek5bQk ㏁ͥk(??bckL`ZhRrUk*&FF֭֭݁kH/k,wZ jMk']C^ԠAdž^%J L<ׯ_& +ZQtҀ #''Uה3P3.=##"~UQ//{*WV9sKl-ԖOd_l=`RjזTfRCL3HN/WC njlo TJ GjMqC#^.=\3fl5k,,\=*&"""6p 0rtK`" Ly kH_fz_Fx Ĥѣ#5j,ʆƍ.Vk7@KÆ{I?*W__ߖ.sǶ^rvmugoH 5Ut 31b@ 3i.!}JW=KI.!zCHW>39Ytt .]at2lpt  jűcǰh"khӦ jժ*U ^^^miӀ-+زEtM j%]ag(]A&Nڶ0 6m ]:HW<l ]AF:w0;`zj.!#FݺIWzsڣG%d8Gʕ+E1c֭[ÇիBbb"bbbpl?ӧ /`ǎXODDDDT|}5+ݻ+Hԩ#]ae}40 >LtIWm|t3xE ;mۤ+H̙@Fv?^ ..'ND:uyxxqJJ 3gΠo߾hݺ5.\gODDDDTJP˕.IOW[?.]B:U/wwL`QZS*Hde!!%x9 ظ8tHtUHWm8 ]A|}ե+6m +QFg̚50 K/>V2LDDDDJuAL.\.!*oMݻΣ .!jM99I$'ss.^.!nnrѢ%6~?/]B:ʕS%KlRSՙqOKRԟ}KKؤV'OJq蕇֭[nݺ֭[YYY{c_OMM믿!C $=j0W$Ӱl&o@Tt _|k*&F.!uo@ ,XDDH5ͷ぀5QIb"d pt ^yd=zt"E`xQmݺݺu󭁈(tc7+W_3:IW %m[`D `B .NtjL"]at|J-ӥ+"#Հ>&Ft4m ̞-]atZSoK q9^{ YYYZQxǾ7_oDDDDDfW/ 'իY_d0 V>.!}ue&gϪ-RRKHG^?3'%{w`p KԖ|}9R(,LmG$]B&áW.bذa(}WGGǾ3fhQ2EL+Hĉ3 V}7NIh&7JWѣΝ+֭x}1U($XxHt !]at(@_'s+-ZBXbҥKuV*""""<`NdV/+HРtѶm]Wg&||t3Gqi&;vUdf50ڵ  ]Ӧ-[JW}et^? G[o͘1+ """"P|Kddw'=*]B:QC OOG5k;>Y,@J6V+~CT"]aq#ptXե+6m ] -]ae {t^&8mڴyn;#PDDDDD*URC 3IJRgI ԅ"&pr:ETѢ%6Ο.!ʩ;SK.IMUgƝ>-]B:JRJ.IKSt pqQkU&=]msxt M_^:%K)]B:Q$6X.!5koM\SZ5TBZS%re󭩻w՛Ӯ\.!aziAx 3'%%a^&""""{֡0ntQxP ]B:ڶ&N0-KHGV)Fׯ5+]B:ZPgIdzGLt hLe&7o5ut h0Vk*:ZqoţG~1ԩ&L[0`Ӷ={|׷oߞ/GDDDDT`0 U[I}պ23g+az0:^mut 6L%%%kW`H 0uwNRt 3FU`b 1Q8Iثcǎ={_VZ?~ڵm[lį9r$O_?{wU{! IDAT`n(\TMKrռ.2d{ݺR.i*Z{(\Pr Qm:̙~xs>z^gf<߇DV:$ln|y`p$ȑj́IWsNBzS{J'1;tHͩ1cGl@7tSvI'1 VsjX׽ R*wNbvڏi8H4dy*(H:YhSkM\Sc63g{m/h޼9ƎkL+W~㉉f\""""r>>@)mۤS^&%Bk&`哑l p5ejMg$۶?O'y^?6H ƍS~d. @: `K؇?I&͚5u$/^FDDDDUbE$f+W;>L@ժ)rrի,c2իK7֪FԪ%Bk:`)B+ عS:e2uJZX)_S:;;?K.mHH~Bۛ`EJKu!}IMU{<#SFjsڋY$G2/Pt4`R)$*RH'1wX8qB: Q:O)#,#C;zT: Q<*,+Kݜ }K/wެY3ԨQC(ؿ}DDDDH4Pj$!=NBzԭ.(IbS4Bvxsu``SZꂲܼ ̛p[ TTRp!%Zxsm5""P>aKt/駟7'nVKDDDDm[`hZ.s i0XUxى-9F̚ d7W{|jNK'!=7V{ɕ+'//ԜtI: tzpW~巌 lxf%RVNuj!&x5ZgΨVwH'!=w Nujɚ":T:Vd$hZQAC`ZQQjٟv퀑#ShEG襓=ϟ?/D˗CFR_d~`Z׈:|-#:T*$8Xͩl$ǠAj$!!j,$G@Ϟ)VP{}[:VXlړ^:i~?{,;&e׮]9sSz|JCDDDD$dRTd&`V哑l l,2hT:VP(8Nc~t kxukZv)H1cTKr#ٻNAyE/<<<zlƌY6n܈}O|#""""S&<(rrի O>>7<[8p@: Ԭ)BسG:e2);S^&Pt UA쓯/Рt mۤSPaK&M<ؾ}0|pdÒ۔L:o&<;ʔ)癈D"E"IRS^LgJ'!=ʖUYTZ3)$GRjN=e{ˁ'%J F| ptңhQuruNbZ>,(THͩJݿڱK'^.]NBz4hVIB:O=p^:9;;W^O|Nhh(|}}Ѻuk.]...Dݺu1}ts]oDʕϢL2h֬???>}ZW֮]zz5Zg_ӑ4H:Vx8xSO.!)"#En%;ѩ0|t (`ϫ#GJЊS+Tm #B+&Fݜvt0j(DGG#""… FBBRRRlM6UM"""""+#FFzO@.ڔ  t,B+8Xs> <M:VH$+K: 1`гt cǀ+^_dzN,[$$ӻWFrꔚS9!eM⥗^DG@DDDD$g Q#Z7OSF79( NAzMx{KڱX^:5~<кt ]ט1j ['9hN:ڵ)X_|'''Tvm3Z՜(Lt 5kS^@͚)={S^&)BkzS^&Pt ᅲNAzK mNAzLt M-[SXRV0h}駟H"1ʮ-T/.,- XTR!SS..I/W-(.()#,=]ͩP$GѢjN+',3S<|X: *VNbvSIH/ ZU:YNjE~t^6`գG1vmH_UgUK]P67yh$TR0>%VML5d`B 2R: Q'YYIH=Sh;| !K:j߸t$G@߾)NT{I'!=^{ _:֙3;I,z٘7BBB흯}_|1_KDDDDdN6Nl(4 Ocat kxU+Z;w)Hc^N{7/5 hN:ڵ)H#Sh:|-;m򀧧'~g|xgXE;#ԩS'OEDDDDP|}5ShI ||Z?J |}}߰{ԯ/B+0ضM:e2^^)6mlNAzM֭)(X#Θ>}:"""0yd1p@:u _|+f񉈈^RHQtwU[0$Gɒ_IUP$3Ϩ9UtL:a$S+J'1_ͩ`$T*,'XF!d2իKZ8p@:^yRJŋ_s(Z5jO>QQQ."""""kxx/Fr&0o-pw7ޜJJժ_F ,ZDFJ'!=*URB, ,Y;'puU7YqRS^LgJ'!=ʔQsxq$fiiSSͱ.]?k.ܺu 1g7ݻwGfаaCxxxM6K/!CGPPp ]?1hL,B%`, >^: Ѥ 0mt +WٳW?.իfT+gpҋV/#WIVtcGZG+VIH7zNu*ĥK'!=Nuj!&x5ZgΨ;IH݁ASh;ZJ'G`ы&OVdv`ׄ @V)vS^c/$Bkn_:5jЮt uS^#F:H:tXɑNBz  t,B+8X ΖNB`ыL&C:V@)H/__NZ6/2ShmܨdL&K:V` ut ktQ#Z7OSMJ R*2#9%?#yڇJ'!=yFͩr夓ef֙GH'!=bE$fYYjNt\Y:YNk!$IZ8p@: Ԭ)BسG:^i5j@b gggxzz^ /񸻫 5F,X?/VM]P6d`B 2R: QSNNIRRŋ^'d*TPNbb:{V: Q%%ǏG #88qqqHcC#::۶mÄ PF <GDDDDTp4iڨˀptңQ#` ZWfEaCy*.N: QTb"0{6+]xsu`\ &F: Q͛@tt^eddØ?>z-4m+VDQV-4l͚5CVбcGtCr 6m ";effbڵhذ!}dee?:w NV$'K'!=ڷ~[:VtPstWѣSh].(?_26mqShƪ9(h8Q:ŋ@tңys`dZ.ؙM^:-[ĉn:?~V޼y:txbQI233GsHJJҝ0p Уt #G+ $ǛozI:~\ٙ>}}Sh< ,[ܽ+x5u2ӧVt>SIxjɚ*2D:Vd$hptE/իgrrr0|pV~t )))6HFDDDDD VSh l ;x%ZwI FRd>_:juz5#6L7``* ]`uN\ #tڵů)Z(J,+WDPP-b=#lSG:V@*~}QI` }t dR|I` ut k lެ~>M 4m*B+(H>Mx{Kڱ7 bK_~ sAL2 [FF># 7|cq gQEeef6GH'!=Q eeE: _+K'1Q+sNBzLt 5kS^@͚)֭SS>)NQ SB0gΜ'>p5j"##gjժ=g͚5͓.ُv?#IN.T{\Y)''$f))js礓* EH'1KMU{1=+([VNb,]"S*R<#w՜ NBz,TI~I gyR ۇ 믿KƴiӰsNbǎ:t( ڵk-Q#H^f._NBz4lhbjB0{6ptң^=ͩk׀9sk FrS11IH㝧nƛSII@TtE/+?yJ#44/_GZtF!<<ХK4iݺuêUyf.\Xٳg[4>BoKЊ,nݒNBz 0zt huM$G6ر)bbT"1Q: Ѫ0at ??UT%Ӣ0yt KԍDIH&MiӤSh]SWH')0X޽{XtCתU {A*U:Ʋe,:fcT~Lo_ƍd oVO?W99IHaÀΝSh9-<M:VHj%0@` #C:cK}=،3ЬY\H+_jԨ hۻwoCDDDDD29Fl.2>_Fl*1CGh$[7K N6Nu+qt k$Ho6lNAzMڲΝ@@t ,^8qB{r0eʔ\x3,( OXEDDD@ZZ._W"..vp-ܺu IIIAJJ rʔ)pqqAQbETT UTAŊQZ5ԩS'W+ĉ|}՞F٧&+Kݝ\;Zt YKܑNܽ!,_xJTsj>J^^eJORdkV-yg穛7(ʕ󔷷tĢN&l׮]_{- dɒ߯_l*nDDTp%''ѣ8vN<ӧO#<<믿_g}mڴA۶m^^^ (6T?L:YBM{%pvvf l'K'!GѢZE1{tK| IDATTJӐ4M ?s$fWfTji +!:-[V%6mڔ>WYv5o< *T@ƍ1qD]Νף?5j+W"/m`N=ݽkoĔʣPkzo)Bi`2՞O]ekW``Zj%EJtңS'`0Hڷ~[:Vt -$E/,zvߏ˗/ù>N.],Wh=Rb=MNNN> O>X"^xL4 }nWw0|p?Dbbt$"zѣW^NonE/ׂɋb8Y#6L]T&!CTH~Uc2"=H/IaK IN6mdѝ]u|X4?ADDdTgFJ &`˖-qt|>pD||>_F|]l<D1C1͛ Lo)ȑL )H T[V"[;V6ݻ-9E/^x{yk؂>+VD֭-kk֬Ecӧ/RRRz߮89BTH{dg~ {%sׯP;3o\&ʽVS=^Ӧ7˗oNAz5j$ WLMMN`X„ zl—_~7nDorQeNOO: 99YjժA_]"-ʈW/_?ZNKt&.^)iSDTu &B+&F:Y}{S#y`hdC,zY7@z<22w~aֆs={9/^<ޥIDDT۷mڴAllt"#W_Nuf ?{H!K t$a۷99)zNA7DDҧ!j*/^ܦΙ3Ώ:''GĉQZ5 8-.\ȂgΜa;'^:͛1㏑"}6 hD:@`t "2 T[V"[;`k=Z"Ǣׯu=HLj#гgOc?3F777x{{cHLLx/^DhhMt:vk׮IG![9yg/Pt??Lt -U""MkKxXptdՓNAdR|]c^u|(SUt .|ٳgcҥr劮qCBBEDDD!22=z@*/l; ૯p$GrK3H'AKCJVKNbv3ߤ/ʖNw#)H"EԍDI'!GS+K'!+e#:uBHHZh{͛QX1'Ξ=k1 2eʠvhڴ)6m:h~ZlM...qr;V:JBI'!=QE AiF`SC.ɍySZQfTj*p!)\Y# T1H$mznݺ ֭[駟O}Mjbȑ(\p|rKDDhQvmXL 0g*,պ50~<`MDLy4 ;W:Y\0k{@JiHZFK'1zUH{@ժiRFlI^=usGI'!X1'''{F\\~={ q-eˢAhժڶmBlp¨^:<<#""rdKFӦMѢE _>իE8Ŋ'<==ѥK?}6b۶mضmmzܧ;v,ZjOO|=.ST IڌrgOu _uS+֬Nb,YL*%@3Gi'ٗD` $fӧ# lrFx祗cŋXCիWǨQgF…>… t(_?*TE;"""{Vn]+xѢE ԩS'On<ɭg}ݺuCnݰd۷/eXJJ a׮]y~,'6IWEݻpFYoJbULݹS:Yp:O Q*`7mQ<$,4X0n S7M#ҫat^vW^쎇:v숗_~ T" *;cǎᅬk";;;O?bԩSͪ}IHiſ\Io0ySG}mۦZ ?95xtc8uA知ޭ԰aIQۧoK'!=~[}ڷO: DDDD6TX1tsŹspy|W0` ^Y&[;Ϗ7mڴVNBzի!NmA}6 "5 UK:j" X2&?HۥS#ٸ;׌U%n/_?7n`׮]8q"ԩ#j^^^駟9 s+$G2o͖0ӊ1kZ(9uAHhaIQdf6FZHWzPA:YVj"Ev6ZHUNAE>6A;vĴiӤ# TR׿w^cʕٳ'JbI0Lعs'fK,ɳIHb"0{6#TE< J/ʕ,9c*嗚5e#u XNB") XNBzT.(jNEDH'!G ,YK'!=ʕSѹߟ9lɓػw?DDDD6駟b…h߾}2:_~AʕdCϓI''یs"0w*&M'1f*JCiS`Z/fIQ\ԕ+IH/:T:VdZI,j5!ٟvQShEG7oJ'!GÛYV ) Lڵk8t """"ݼ~z*dp[ldrrCBp̊ח }N8ӠA@)V1eZ_}ӥ}}H -ݓNB)5Ҥ=zH(0E/Xft""""tS=ŋq9Ku+qt kys/?#+#|l\n$fDeKZ?_/"@kn){6z4+)S#9pj5|8Щt zUZh3ٹO>6w6 dZ`~Ԫe˲ _0Q`Kf2kKZعS:U Pt ;S^>>@)モNAdf`&״i@&)uu7nܐBDDD[ѢE|}|L2wU S..HQE/ g+ El+F&qŋ eH'1PmNBz89󔫫t,`J $D: QS*I'1Vmݕ/rrj^&.@_EfͰzjddX3z 6`}IGt:0g $fW{" //uϤ%$̙tTjN}d6t횚Sァn Vb"0{:Oլ),nN{]$Z;w`5(W5j&Mm۶h߾=J(! `РA6-zegg#22^^^6 9u)#E>e V R_Aͩ+?,XAOv_K'1S%˕NCz%`(bb z$uUt70i0wt777o1k,˗G>}phDDD$5m|`[UIHAfX9pLkI:vLŭ S߾@)I'!=zNujK&→n5ILn) <̽{ehѢ~WHDDD$]v6͛6 n6`Fĉ@˖=< @V';6nкt ]ט1@۶)S^#G*B`H_`j 'G: 1dеtE/;vQncǎEzzt"""РA; `e\f2uJZرC: モNAz?/Bkf`&Hnild/``ɒ%hӦ \"Y:ul:^J5C.ݻ,_8!(QB]P.SWLrxȎ-ji+$GBjNU$,;[,UNa] :$Q`׮NAzL@Z) $gѥKԩS(^H,֭[HII۷qҥKرch׮<*Uqb"""25jt<*n{NC^0w-+yWDjUufd$fokK!KUԔ)ijߜzӐʕS+&O6ξw_}V7R,5mw=ʗ^xA: Yy7YT0p@899Iyׯصklق>7"":uBHHJ,)HM3g#C/fWiBnV+7CK]Pǫ̙tTjN}tOUԭ.(tD`w5Ӑ OW us̙\5djT+Sg̐NRlfޫR ~'[vqQ:uٳ 4k?}4Ǝ HRRl:w2Hm$d%K%ѶCW#ShEG7oJ'!=ڶƌNׯK'!=ZƏN ̞ `dIShũ}BtңiS`Ml25ڦTP!G+>yWFPPP>#""" 6D6PH;(`%%~}Q+PR-B+, XLIHwo5)B(-2={Hw$Gn)ΝS-Y&>u *(PkڵknݺIǰcǎ1{.L:FiLDDDy{pU2&$g`z CBOVaP6qQV޽t kHH֮NAz t$B!o$ǐ!@.)UԾcd wNQ `UTvm:tUV}oQQQXb@*"""Om܆Zj6X@st zT7Ϫ1+@)6nmNAzd&`״i@)nU*OS͛Kڶ  NAzMl)W#\jհi&*y!w9WF Gv,# 4T: =ŋqي=h X%"V*RT(}Վ58X: e2WLNzZCdWNv-t djՒN-2ڵS8S*[^iժFΝnZDD*Qc['S̟DEI'CΗcڵ &MBdddF ,$"ul=z d6lPnݤ83/y+V0vΞQ** e2 5NI'1۴IzNBzL.(8!lV5xm>/F IDATMѣI̶mSsj$ĉ/$D:?*ou#θqjNK'qްx] 9Ei,^lY;..ΝV,xݘ3gMYu9L`JuG)_Ϟ"+lרv颊+(K=3ڜVV+t.ZR^Eի4jnUC57֪FԪ%Bk:`w\Eg`<"ْԭ+!pqss.@\nP"@izjcGAXX5j0p@#66ϟ1zꅚ5k"11NB {lA%$$/xh߾ƣ 9YPPt~~ȶag?899*/Փ'Fiߜ8)_WO: Y5 c$fw\]xYY8㑑r\? \IO$\ @ypP㏟xƃiij8WW+F⢊'s=`r57NCOq?;/xT"/_V籜wr\|F+ uuus<:nv͛[;巢Eg1c?Xr0...=vU$h֬Y۷o?ҥKx>>(T BY̙t6s*~Uc|8d}Gam8nU+7-UiS7}$$rT/͛#FHк|Yͩx$^Xxڧ당[࿧NYUʍ;,0 jk}8 ˒\?T$`>)NNNxwj[o "ʭcԩ6?)b19~\IONp20/u1 ƊSQ1M>=~8yRc[3gTC K0ib=~Y]> lsTKVķOmJ'xXd$h;RS1j\lWZZHGs(usZRR#2.Z=F[-zߗ-[OIVN.lu'zt|"XnlӵkW6 ݻj)}]5 hΪڵ)-[J':t[]P kBh`)jNeoD!!ʕpј) r-4Z8v XBET`Ο?ݻIQ\rAAAO|Çqĉ|JUpnn)֬NA`AHسVHB ;S }azUP%* f̘1ϟpAHLb|%CFFF[]w#&_SA8xwЫW/KdIuA>ҧNH/6l@hdUc 4EjNiTٳIHeU1xq$fiijϸSAAz@S{[ u?!>(SF:YF7\D _+9LιG+??}o\YmRIl,L gN"Q+W`4pg,ǁF 0猋3!"\ 6}*>fφӧu'n,)x_;S9sUG6]fϞ}ߋ+… ̞ B!,,)SШQ#T´iӸqSԩ-) M47ԝڙ30}:\ۯ-^2[9x0r a2YI;Gݺ0lΟW/N"LĂ*uX 0y2\dx.O? GNa-*Jݧt'nfP o\S.>.e6""" a&}+F63n!441p@ZlIrxBᖢٽ{73gΤ[n+W+2j(Թիv>ުG\(V?wy{WXG}DΜ9]U!0c 9;+ƚ5khԨ(UƍS ǎN!$ vt'1t>M}د% JcfN_6)vQdΨQjA!I2|vQb gM_~tȜCϾ}t'ɰmO;pC[Q= 74nY1%K(Zj̙3ڧz'Yd I!ױcG>,^Yj^$,Xv%˘i?8^reA %J8gl{XaS6C2SX[ Vw aR;P 6X\mR%)] 7N!>p/TR^,X@w DGGLժU&~i'bp»Q 4zM~9ƢEM!ըQ;vB``8B BLΗÉ٘-Y,9l*?ZwHJR=՝D#wnuMN-X\stQd:A_$RSŨu'n"_ᙿp玺tQdM/aÆl21lre֮]K=(S ~!l`O:uPx[rԩ~PIжm9?#vJ>!OrJ~W^xqn+e3iYILb0`tnsFUgP|ԕ+0}:DFN"QZP681""t'&uh aL8}SzL`l ӝD?ɓB a, 55}pB:vH 7񤦦ùsx"'OѣX,lԨ9!9s{|ڵ^Kݙ6mCYt)3fpJF!4hah߾=ٳgGIÆ0dZ1HINeqKm_~qhJ%K2U}օR fqL&@B[ծ #Fԩdp&Ow1WX7V@ G ʗy!/~~w_w#);wHLNr|<^\vԴ4k?oLDEeܧ-ȓO ?ԝ$åK>5a{y)ZAy޽C{]o޺EJj*))s>6Wx SS5 6vbb dIل0Bˁ8pNצM g۶mwܷo_r׾Z|9~!9s4<BduJk׮ӇJf5 ̥m[ujZI2; ,9!U޾=yyx\Y >sݜs$̝ F\Ȝ-5|$`=ѝ-xyyQhQjV@ X|bV Hsp<'HsǠ 2@i5 ƌ|L8GӦ>eV;V!(U=K{JX8}"ᄆaniz_g)3g2N+XP[.!e7^{517oe}mʕ[C7ٳS !DVӰaC^z%ZlI5rVy^]-ܩ;I~@0?'7W.^mԈW5b|w/Kmcv@&P5oغUy S{NavuM;[KkJfMivX l\y=p+wߩk7\Bc#pˋQF!g}F\\?<ҥ s~DZc 'Y˗2d+WZj{?~\w4.a {)\JB#sxoSfƞVT͸qPV6שF ʛڵcϴiD]ˢ#h] 5/v8B;~8V>, .$99Yw,afeI2$%^Y!3g]]cdULEʥT^.oaN2~>>ڨ_>׬aƠA4VnP: pp,T9> tN5VBt'p玺!v! @r1cnJ*VT_fr L8Ńs3}@y81""t'(]Z-I|<̜ ONTE `L΄/_Cz1cԮ\gda3!!́0'%NUOi#81̓?НDrVv^|kMgt_?`  2`_HL .LtwF3f63gwޙ~o_ޑxB!2ҥK > *duGfTjxn&)p$Nsuޘ6q&@ax.pIG[xᰚ5ah)EEԩ;fxέZ_x`HZqx*_ީs%M>u Z|ĨSNryrd?Iڵ42 dʕGGӧCXlwgXaWNٞk)յkWl{c/ZȮlB!s^u5j$=ܑW^g?/k~g8yUOzssCc4Q͛(  Sԍ{4o}Na-, fVt#$3/;}`r6LhO?rNcшxevST(>'ii{t6䧟`HIѝD W?N~îF{p# :NaRZMmK}ǹ qi/UÛ78ƑM/˺u뤬IZZ .g}ZjU'Z`ƾ~:QQQ>}'NoqQӝ6ӰaCmF5\:0yB͈)Y,O=;ݾ eɶm=;KF^;.s*I<;_},SSU̠ ][wa^Hco€ 1-M]S B.0nO];b Bƺ{…}M$~v?ۓ&NzþN3өF!#^n(00sw^ʖ-;pSs"̤I(R(P Q^%fϞ=k !ȟ??/2ӧOٳ۷iٲ%NKڵՓfr>ٌ_[țcb}VTlbcaTsWC)o3 <鄙plzҥKf"kq+Vxoݺŵk2Ojjj^ϊ!DE={6ϟgĉ-Zԩs^t_|8в%;S`s7nth ///~ Sst'xxu)ED׮N"lTlYFth|AK5lCNaYuM9gThR. o>p”7G>wNm_مp욘X@@jf׮]3n8sJ>S_mBc̘1>}w}0ӧѣׄSm~IZ$u;5~SW7{y~IJIѝDأsghNw k q­ӣePС^GEϥp?m۪{; tn o :aNT%Y0˲ݐk׮MX"r.???C)^8^^^# cX7oײgNF(S 6ȹs8piYz*ׯ[n6#YIΜ9yݻ7}[Flٲ>f+%1B=]OdشI56g-[94F`޼LߠD⡶nUWvQdΠAҞ=dؾOI rNcC]/vTהN7yuuڹSw ?@O>37X}9~6)#W SԠA UɄIdM/ooo.\H*]vq˗gTT׿Ŝ9s ʦBdR2eعs'3gd6ͬ &ТE z)n,8Xm~jysI觓'~2y H$kjPcӍ"sƍSNԝ$CH^~YwanM5)"PсBBCf;(2gXI;I}CI=FRY}y>S~%ȾJ]S]8rۯ3f̐ /ݿ!5c C6@={6iϞ=4/Bar^^^ 6ܹs>~ZZ$==˕K-(;ᚳ۪|}_e 8KkӹIcBKMUetQd6"-MceGl>ތtA#X`rؽۈфPV'U.0~<)/qT3>3שFeM5jo!6ϟg=M .L- gȑbaņ+y|qB߉h"nLK\fAx$Vr%"##wΜ>ܘ@"`l ӝDأHl2]7n';Af1tL/?Nb$}ʉzm >_έNeOkSe>)3jYV߿?٤ϟos}dϞy֭KʕO>[n>Bx5ksNoIf~<ʨŋ0e DGN&8<·QL'Vhcǝ4iթ`!z50ۦO?ҥ/&^!z{dH<[Vuw$:Kh*$'‹>k`YcTä$G3'ה;Zb=M'dT|ɕ#齃b/cFɄ'a|yb`k"-[+t'p*=z4\.O8_@߸aX`lxmUS'M/!<ԁx <<*U,Kzxbz-J(a؉ͮP;|O:nqܩDtȜ_W;wNa.(X|{nz٣~ h"szT)3߿-S'f#Q\w q#]R^6{pO#FrfiNʊL1zbhիQ+%y&&MA\r塯/iԨ[ly))GƲ`d ݻw[fj#fذa|͛oɞ={25?~#uF||]s!jժexgϞ5t<||`8YНDxtSsj?ם"Ţʙ}$ƵNZeS6PVoѝBX:`kךT(r.Uw?fiժTX@=z4<Ξ=˷~Kxx8'Oȑ#9sŶgAÞ={ȕ+գqtޝeoq.^ݻoIOOx1114nܘuҴiS/NPP5H"VMMM믿ŋ9s/f^n۶mUV<*T"EТE Bᨲe˒={vN?ސqDRZ1S3UbEi'HLyN7+P >ec IJ 5U4H20 Uϸ@QCG\}jHHHНF}[ ;֌%ݺeX k`AnnO6'OdOq%''sn߾]^7ofvex7ocvA Bg" )o(BA?ׯ6b НZDZRQ"#atY!Oz0tΝS!6Vw,-3yz$~]1 .2vj*736 3N9s`hȝ[wa_T-ӝ$CX:ې74!n0l,"")1c ~g&(QK"CjYe5klH!7Չݻu'ɰcGѯ$SڥQtȜ}ՂdسGݧ//i11؛Q7jd @kj~&I2,] C};|fL6B!u'x);Vw k2a;w_z8 7'^B!"&&˛7ac qWЩ֎U%Ēt'aRьrvQdNp:sFw VAм$e-|߿~|B!WN7>u$BB (|=ܺݻ3 i׭SW^ѝDB!o6lz XIIѝFySm,U>%Krɒ.f> Ϗf5k3X2KdU`AQCwaYiݾʇ,<;G/4|zϸ(5U9 4Fx>>0~bcuQ`2uMtX,Lt©M<敞~)n# B!<ƍILL4l\w kÔ);3Ϩtfr"L .Nntǖ}i3y)^|}Ĩ}.NR^q_[?]S/k9IɦB! o5t{x6mkW)?J޼;GVнC=l2y6-Z@^SX S')t'q[o/ZD:eTfЯs;$<f4OEa矇tN;;3L^g>n瞃F` vHdz8IIɦB!׿Ezzc6iȔ}ޭX,{6*d>sGwaݡuk)<1Nv?-[ LԪT)s/ڶ5CU=SUlz !BÇb~~~ԕB1cT'3ٰ֭ӝBkHUKw k7nBÆ~NnN(b]GjԤ ^^^Ð!а9}\S7qc)N؜ʒoߦK6[׭K92д8d.XBw aB%B0`᧼Zlc a`(YRw k+WwN! eNaҴ…B)Y[NRrI}_gax80WYZw ajU)_N1M¯aaN /O:e>_;0B!pS&LlJD֓/ZəSw ɪ,ѣ{Mܹu'p** IDATo{ſ|t'ɐ$n0`t~8r)(W7T`앖˖{d˦…u'ɐFݫ;{orV唱T)Zթoŋ;e^X,N"LD6B!Ж-[4iK/>6+_^-(ɕ+0mj-O2滦` НDأdIl&0{6>;)Y,̚ŲoqctŊ~]]SNN"Qu'ɐɓIko'ӹ3V@uM9m~%%^ǏN"LB6B!́ԩe ^{5|}} Wԭz0y2N"Qe&/k%I=~Z"4(uMEEY}y70zB.k Wڝ;1m6mru*WI R6bb`pAwa*UwM]mz۶ԩDfa/gNdPKVhbc4qlz !´ܹC~8o/C楗^͛-[6x ![CSX{hf+NR$$N"Ѭ;p5K[nz`\Bەb'u #:*_ڴ]NKLԝDh$^B!0.\HJxwb,RSSywر#I6BY>>>{N[a󳺑#Ui:3ٸ֭ӝBk0xXv]֬ѝBk仙lW?[L *?ƌaӁX,t۷x1 㬓?;z{3{P>p 4nl옎ڱVҝBثx\:W۵ ~C.:u ݺѾaCc+_|ի4 ?#>&zDD!W^e͚5YlٲQfM{9֭K:u(i IIIرM6i&b`A *Ă \>h\Q", Q} ѝFتY3ضt$NYԆJ0iTݧ-ҝP 7ovO ŊQD *,I%XO+Fqh89oO[x8lݚ-Zvƍa@u,"#a4Ӡ ~֘Źsjk r7oÇ@%RrRwcE p4畄EFoO˩S8{ѿZթûF?Y ӧ;#ΟW&TpB!GKOO_~UX1ԩCթT+VbŊq"͛7 ѣi !Bx8___V\ɘ1ctG¹jքѣuS'ͷuL .N"QZPn!{lۣ&L 6UZP6X6 "#u'(_|ի0cNhՊ&Q8~=ʔ1穸8uMEDN"@6B!ooajR=E ѥKɦB!?Ahh(M6Eڴѝ/2*)){tNa-4T]SoN"Ѿ)kЀ gtGɼ6mK)?J޼;Gн.^ԝm<6>7%CЫTIdK!ȑ'm64tzLmիu85ҝpON!Q`AM7F5ӝ`N"ѫڨn#@ ɓ\8׽P5aRHM՝DD6B!ŋSXKHPt'(\X-4mb"̛'ON")__NB@~fnծ/gAYQS 9sN!) .Gu'PT@F ~7=5,=%Jd9g|t'ɐ$AY B}|g\|/ݻL5[.} 8ooyQzIPc&.Ґ]UjԘ:ΟםDأR%ܧr 4>^ټhRF&jf DQ36Z w L{-65 ,ΧKBLlߞ}\9rhN|*Ub֐!D]1cPH+YהxpӺȦB!B9h۶-+V 66~cO29s[nT;Ν2sf=M-ZT.?n`7lV ˔D\*lR%tv{mtoB_=NoL0>/穏>N̜cǢmӦh۴) Dzͱ쎏˗WBӢn*uUu$mjl$ӧKA3(ծ]O>$|I@||<֭[7_~ݻ;ŋGӦMѮ];t ]tA"0MQyz$V+ÂE-65X ^]h0P^V;Ú5ҦzJ; zNB&^xAV nFE, GSRp$) RRp"5Gqlz:^8 ,BBBPLX\9 CԊTAԎDuQҡmv/}Qof$˗E?rŊo-7ވ;;C'NDj*8~4RΝ/-U,W!*-+zDjV*V*Q0-g8\))~ *,zQWT)n[}ѣػw/<#G->>O?\jժjժVШQ#4n 6dHCh)FNN#9sNC&1cgΕοӐh9O=a^;ÂҦxr?O}?nviS.i'!X""""""d MS-^ ,]LhFieKv_~)* NF[k[XH;zYSح\ ,\L=4оv UxqZcыBBd!յ8XY^; jNa7ovv 25~Z;7Nax1lv rE/"""""\ҡ!=x`^$d""B:KN␑!kڥL//m\9$.fɔO|ʔp$/KڶM; (YRTJI23e͛PyZU;Cv5X""""""ZFGu IN&OMSIDzҡHRSSC:u]F~Q`PvI:sF; h>\;2i$\2^vsL t额nF` 'G; 0U;ݦMҦ~ݵS +ID>@Ϟ)~U֍|Y; [;Νf*/NSǢ;-Zh3Qp3hR;ݗ_Kh SF[k+OSgS;݊…)3i[ X@;6 Q;ݚ5)<<jNa7o)Tt4Pv  NA(v ~L4hONAbbƍS-^ ,[L͚iSϵSi,zy!%Kj'qȐvNB&åM-Egv$dlY NpLmv2QJ8df~lެLJZU;CvLǺqv2Ԩ뵓Y,zyA='IDTtT`T!$dNkSgӦh'!5k{_Z0s&LT&b-}<}ID*r!QXvtw{Itv!""""" pw .!88uJ; h =Z;ѣ ɓIcj;~4 8qB; h\:ɉr:vL; h$TR|JLNB&5 >$E^DDDDDD _;]l\ML<0pv 8୷w >;if̐Q:|2D;ݡC2$dC`pvSOk'!m#Fh;rDfeHNNREDDDDDA.]Sm̝+P0@_e휬,$d)-[ٳ+WGzNa믲nID^@)v-32=}S#^`ыĘ12X YXX;=Z; $_}|v 25rLHV.NAyhN;ݪU)԰a@ǎ)֬>X;<I;ݺuy8EDDDDDd*&SG;݂k S11@Tv oNAƏ4Na'_k S11@),"=hY3vD^xhB;gɍ^DDDDDDålY$/ʴ<۷k'!eJ NpLImv2QJ8dfԙ[h'!RN␕%m꧟iSիk'q,6zz$d*&UK;ݼyڵ) ="*J$i ;:uM9L)ISIDFצI#GMSI -A<]hۿ9S~ӥ 0hv 8L{/0dv Cdd3ID)6uv2Ѷ-0bv #GHLi.!A Ni')X""""""NaϲIVv2ѿ?Эv -[d+WGzNaY~^޽SmsIG9Wݻwߕ(t&IlLɚaыȟFW_|L yv +ئ3i[ cdj0HX@;2DFu뀹s9B4HF9s$ ^DDDDDDDEi[P:)8EG˺dB)~QpsR#|ŋKSqd=@gr4f вv /s ^DDDDD$$D;Cٲҡ\v˗em۴ҥC9"B;CfLsev2DFj'qʒXI;  TI,KF_Lji7djxn]v,S/X""""""uՁ`tA$dV- $ii#IDҦ邋e}Hy N␞.k1j'!r*]Z;CFݻⴲe8\GHyƢQ~iRQ $ǎ''Nh'!-ZtO SML=L4j$ʁ)yKHNB&6L k'!QQޗ L*QEDDDDDtI\0sҡs!)P^t !KMNB&ڵyF;]|)ئӝw#GjKHbSIDV)6nNX""""""oݺiۼYFdfj'!> 衝 ޽^Sm.=]L)@{7pv 2խ| $2%kzv2)NNX""""""*#Gmh`"djm[T . h SC@evʋAd} ٸ;,$dbkWG,zY",\XL9f:d*&F $K_|L'˘1k[XX;5J;BE/""""`tv2Qt(GDh'qf*, ?Nbliv 2"յ8}v2 Ԭ Nv T N11@Tv Ѷm)DZGu IKfNB&W$IDdP$o9|*U%\Sxe8\(n߮L-+m*<\; ^DDDDDy`D V-Z/q`OfR$IIr:zT; h8 NIJHNB&4f >^; Tj*0mpv2QN)^DDDDD*.NFRi'!:k;xP:jΜNB&:v Naw0utRixv@rv2qȑ)N&Mb VZGkKL}Rv2qn-ȺL|zNam0kpv2ѻ7Ыv e=GNa{7@Fv2ѭпv 3ӵ NaL}v2ѥ 0hv 2ĢQ`"djm[vVL t蠝٦ِ!=h[7O;4Y;݆ ܹei'!J+3@Vv2ѿ)EDDDDT,ZXLi[X\;4Nax1)Tt4мv >>T;;V $Kʹ2a +OS#eZV *,zW4[j'!aaҡ\v,:y&$dX1)V!'#ず5S8X$d*&SG;݂2:SL nBEOixA g35&;'mj~$djUiSIeݜX$dR%iS%Kj'q}W.mlY$/ʚq;vh'!eʅDI._RmNB&J6ĢQar80aKY+|%%'Gj'!^:uJTBv2Ѡ\HRRɓx$d"*J:ԩIDݺצΜONB&j S^DDDDDi5aôS:$IDv3hLb;}V;]B0iLn .1Q.$JJNB&ZƌNaw\qv2Ѣ0nv ^DDDDDѶmו+ID@^)o.]NB&zNak{2=݁~SLLt n~`Ly$dK` vqq2utZv2q!) +el NÇk[X@;:vki SO> tn`\NaYYID@n)l23GzNAnEDDDDT-Z,_L4inb/Shysv}|v 25v,p).,NAFZNaWlSlHMv|#)8m\`ы0ʒ7mNB&EUN␓|I@͚), ?X^; Na7>fv 2 ԫn`*d*&__;…)TL Шv rE/""""9Yb~$djU:4T;Cz:;@lv2Qt(,iS{h'!ҦʔNpcv2Q/e`,Y7OҦ""8dfgt|BH$t 'GƍC9$%IJLNB&6 6 Lk'!7$ʁi`Ta$dn]P$gӧj'!jy*-M.NNB&W6¢QQqtj'!O?.><HINB&xYv RJNNB&ZFNaL z >-[ch;vL.8yR; h7N;ҦNB&6 8ہ.]NB&~G;ݮ]2XFv2ѽ;Яv ~[Ѥӵ+0`v M?Lt ..1CFP^``vӦhB >;Æi?EDDDDTԬ^-Sp:vkk SO> tn`\Naq#0gLu( 衝n6Y7e$dwoW/%Ke˴Shysv~ |v 25v,pm).sC;ݲe)smh`"djm[vVL t蠝cы(>P| ԨddITL Pv 5kS^=v H2~}v +Vh S11@F)//NAbbd/RâQQ.kj'!U%Jh'qpx`$dbE`xL$/ʚq;vh'!y|y$/g4b|J6!3S9ܺU;  "#8dei6i'!!!ҦUNRdEDDDDT%%'IDÆHIx$d⦛M> L6֕bj IMONB&jՒ@r,0cpv2QF൩sM߯LT*BCI,zu@Jv2qjKHL֭QS%&&HO˖W 9vLɓIm/qiSǏk'!͚E=L4nxm`ы]22݁}S#S^Lt D;1hV;ʕE)@)V,NAG;E9X0wСԮn|IH)&WO;}LEGk[XB;6Nah|v 25~<Фv ŋ/NA͵S ,z݅ Ӟ=IDŊQSveZ]r夣\9$.fL)#mbE$WȔt[j'!%JHJ$YY6i'!ŊIVM;CNLI@͚) =z#IM7Ir II6Lԫ'$5:8tH; ];ٳIDצΝ6v2QP$rqZlv2Q%j,zsGH"9Y; hF $ @Rv2qW 9vLɓImZqiSǏk'!͚^+) 88zT; h8pTbv2ѠA]VȰEDDDDD#W^L< )~8^; ~'SH4$dS'``vӧ/ >;Æi;tHFj'!O?.>^.NKINB&xY^DDDDD~ei'!O{?nvY%$dᇁ>}SLt망P I!! [TuꤝLt$${j'qKKYrOkvҹpUwHk,_(<)z*mNr%PTO;=$-[l.ҦxByAR矵8]+mœQ8Pw#S4]DDT[nw؁͛+&""opw""""""r[;E@DDDDDDDDDDDDX""""""""""""ǢPDDD-44իWTZ'"r.$D;QPbыo'NЎADei' """""" Jސ^DDDDDDDDDDDDX""""""""""""5 7-[j "ΝSKRB$IJR67NoHDDDDDDDDDDDDAE/"""""""""""" z,zQcы^DDDDDDDDDDDDX""""""""""""Ǣ^7o)>K,K;  _nۖ-!+gΨ+RSg幱,re)ŕ+=Ϟul "BQٶͿiiunq"#|Y_v @T?k+W+u++^#) XXؽطھV2@˖@vw:xWKO5 ѯ?Qlsp"p̕+u/ɑ8Ko67J{` 23QH/"""""MHv%[nڷ:u:wJNEqHqh0kyR+? 4mz99ԩJ( ,\h(Wr aaw]}uj'*8? ,]jX"?EDDDDD ׵*TF4NC Y``tO;&M#ٷ+_8}Z:"^W g`X3?tcY"?EDDDDDG9y[!X1U+vmvp0p:x5o IDATY? ݻh`N !ǰiWΔ, 4kvLCZ<HIcceJ <42k>ٰh??]>*S8!]];[䟗_D}{X"?EDDDDDykx10c}AqOT/Zv]f,^mX:AתYS^cxbSѣc+~]P6ަ}{`{w <>/_u> GZcܱ,_›JdVW֝;v.Y-S0֮^yE.pE/"^DDDDD'O=$x㣏}?ŋ^\hb鄧).h,z…siS̏o H7z,1?&;Zx}xncl*⡡Cߖi l` `<۱ED`ы))I9}vŋKtic][oy6,Lցjx^y?]Ϣ˒TZ!!qK/I~x1瑩__:Kl,pW^8/J˛QO> ̚Udnp>n.<T vy)x@ٲ̙z̔<(x$rrd7p^*UJ}utv;AQ#GpljyXR.͏L*TDD^`ы˛Nnz xM۝<)W`STFaYRz}(!kp?ǏiIǎu]No_d "աwըcwra'11jQ^DDDDD_tJGy>)p +2m+|t钿BB=jDDժy]dת0a231]QƑE/""""" ~!!)9O/LZrrG 5k _|_ . ] 﨣75ڵM;.Qcы =od ڵe-ğJUOHԙoN-LŊs渞ȑCDx ~}sg`24G{Go" ¢y1`ϢeZ̞z 8w'e\\+Ӧ9/!`wOM bEg!" ,zQq}ޭysgѲzv Vs+Wukws:vG|".pjT"иRS?Q`ы  *v;w G?ŋ@Lm &;/pN.D$-.]NQ5hvǎo" .5jxަNx뵘ܙ:}i:@nǕΝ[o/5H… …AD$X"""""¥re$%v Fof@Xt!cؿ !*ʎZR!,̻ʔDDA">Q*mr`>Μq#Lo-k:YiӀ,Yn!s p,dfv F̘~Zf &7J:u,DEՉ]\PRRy?GA9yx,M&W]cы] ̙hHMPj D!?Qzm€{q.]> XP:*ϟin[ÆI?\$?myΝGVI+w$+%JNSAu4_+5S/Xz6+K1{G M@TTgrt8_IO8r.۾\ܖ-rۺU:rG*z9#=+T5FNuodek>7˖-As^JJ JZ*?Ęw_̝+M<)[nG9_;+Kn?&#Cs/K\?eɱ}ֻ K [F}<4\"9s:;W\tiM) bN`t/{ 4l(ˀ;//y1ŋK9/תLGӦKz^."B>O ~|oj7}j>劏f̐zGx޾V-,Яй}Je x!/""""""|5iZ:S'oӽtZHO^xG'P駁G:Wqm7gؿ_%xWm&#~ܭg<1w.0bw&LmsٹSK<)R^m2``yyZN0{LG'^xAFe)~7k4^"&HqWw|!Рdns}3s옌8{,[A[xۥ潘 yeK#}y5˒"ʸqލvL)sW(QkgJNƏs­+M ^DDDDD_ZE}dOW(%KQd;iBj'dR:p@?k^_xK:-ҀÇ_~qbŀ[Fuڑke4D^DUKggVANޭ6n4+R=[: MRjVF awm/ =k浝3gYѕ+tLH 7:A)Δ//={w7n, oք_)n~d輸8amwuL`,ٗՓ%nv:߬,ߝ[-,kڻײRS-%JL%K,kWϙg9'mzW^of<*]Fs\?vF˪]u-eYVޮWc,;ֲBB{+]ڲ~-dI?[6I%'= '"W{%>52ɓ}>㏖U/^ܲzʲv1YYzeOaY[z>f?#߹ӲV b,k,~w._ߗ28IӊLǸxѲOwzRŲ?~ͲjԸ!!5`eΖ`v3-kYk=_y?eI1hв>Pk;fY/hYJ׿ZVNY9;ҤerۻײRR8zԲ>̲zsmʲ\=ו+u]}Y֫ZVFefZ\g?WU5ye9sRS-k4\YZR2珩Yxa}з-[ukIU/qPd6~ݻ}˒k{]}V=lMk3ҥiI]u#""""BGz}ez>ܹ{diTCWs}fv} Ov\ j_{4+;[F\zZвbc-)JOxZJF+}`L=zh'7QZ}|+9YF-gYrpսee*Vt g9{VTɻ,'OZ։^եeedF42,|W-#W9ڴIzVFxx]27(Zs,kx uݏ??ƫmۑ^չe *Wߞx²yIJuA5kzR<Сd;2RF b@?K&y!#rr,ǝ}ƍېs}Ϝ9{7@?ܷL%yy__>~פIgDDDDDTT++˲|S:p=ϗBL}\9ٖլ۷Ѳ ;n׷"UFNߟ׸qdjt=xPڬvV%W_yy iۿ쏢eYV^cRc-Q|]w_uؤ,qqBɓyuӦ{sVʽU:ǹsuM?&,̲vkYRwVȽM>Ms;} y=X[r`AOvL|mbŤM9f맞p:[1nY#ITQQ_Sڦ,G^1c=Vdӕ_ΞmÇNYrն-`y&3G﫯d:WS? q6ՕOM\0v߯T 2lcIL&Mn?S4תV)BCB't/GM-ޠor(,Ybz03>ի;iiYP__=)932}'>,k&4i)#]ȜFɚt0aT̳Vd A2~}:wvMﳠuzu|MʮvZ[ 3xqۭ\iWA> \ߤW(Yz 1#UT)|;wWYl UL 5,/, h='<Ι3RU˅ bZ'(6yAX1+Ov\]弰4twYgʗ5\6ͻ  kʟGK|0j5k^ٱc=嗝׭pfyBBbW>77+HWNVΕΐ^ƍZÆղSG-H'?{YW UWۼY:]1MWm'O:=[Ώ?eey^\9onKM79&$}Kq͓P;2j܏<իck=ިRhy<47߷}^˛,K˨]w^}U.rhBFT.شIt9'-Za_~VZS&Vҙ yƁƛb Eߞ 7%seȫ]zՒ%}ɑ#z!!Wkp*bVb"z>P:_+;[7ɋs]o{HHp]ݹ}|hSi~iOvъGtFJ2{w}fΦM,zNoHDDDDD̳uaa@F2ާ IDAT2(Ym;'J{< g?|Y%11rPXT)44L]]OQp钌p_~\˛u_I_hq7/ zg)*deA/]ߗs}m?{>z)Nbaы{w]UuB0 DhQDD<%BE}P ڊRUh>dh@ & S@ 㷲2{>{o.|?kE=g}=So&""""ozHR?/~=0iRkX=5r^'6t/ |+0,z8S󟻟ͩnn ȟ?< E ffze`[#*۴q֭y-^l=VMys*37{:J8x]^,] eM3fWoT0xM`~%%˫KIo=~~TsmU+ ED{|f) """"""rRϤaazM7X)66nwo>s.eecD? n w)!rTO? wr$8tȷv68_)Ds?۷޽HII~ ̜_OwCwM/;ŨQ5./X4l(ϣJ;keב#%Á7h ? կo#ysguҸi"""""Ką _{Z`Qx<%818uU  M7l*+v}}sK7J|<^Z&N4TYlqK#o 2୷>}~gjIt.(ۓ'_m/^yyՊ =z7}€%A/""""""Skݻ?|ue믾,F"(Uun$^+&-=s)4iʕ{~%dh]N59mnE7OٳN=]i?iiP)`""""""frWׯaТ~ڽ)t=do.vr11@RRBצ~d׃M͛-$ave.F/~XV[O}ohܪUeǵʨcǀU$_O)I+)5g۶~eN~Ǡ'۷u߻v`B ,, X2GP<h@Ւ>ؿeK$j?ޔ;R#fH[zc_mlw2c}Lڴɝr;]J={ԅ- n헯;oRSݻj?,Yx׿ii/]hYlz".Ngsz_~EA/"""""ʬ.eb8[7e**>L}?bce R79*JJ,=cpz%'{o$ lR鮻̖o/h2CQ@ˬZ>UTX|y=x~ 11{RMYopu Qu;wOLtVny9' ;= ѯKLƏS܆ 2+ML3Ѩh|U =/rs<8z/%k֟GOGد~^ˁck"5U2S7Zq1oW)2X>*ll**wLxiϿrϿ7o| R_"k""""""w>_tA˭|iSzܹ2squIݒ7x1С~Sgw }AyMet}+4n Wӧݓ'ufffe[~(s)/`W1OF3 $(Q)2~u )S̶o*/ny'rUp<:{6;2fgJzݹ8rٺ_}߽;=.nn-[̚%cƸ[6A/"""""rI`;(/8wYQXhɓϽ{|{w;BgL 3|?.J|/ɜYƴ"i뫯Gå]xQW$b <^Aߪ*Х))k>)XLG:6Cgy=<ϗԹS<`um:wf㏁ɓ}o~|69{0GPʯP֭>utJIiǒ%fi`R_Z/oo۰C-W v>:TƴiiB8nz;/[w}Zcy}\Fpk^#@^[SSec}k7Xs..y X9=ON ^?l6z6o7}JtxCt|{ET9E (y(ݬ,z;=v?WU+|`ڝfd(5rdmiw^~AR͚YDRRe9u5ʺ^xAӧ}ի߉s;vҳR.jv6h_ɚ5J<}~{+ӓwߵu׉26.7R[ltR'O:K̚evlJ)j{~QmJ .ٳJmڤT||{}T?ryԼT5Y| w~*թپ&Vj,_nާ)zZ/>zYsaaJf{vmbb:|X^i|7&W+l^BNVYN+DDDDDt+?4kFV yzHiI2?f7JCmJK̔F+a?I Sj6TxCk\^uwoS)uRGJYO<9Ҧ,oQ_^zImZFDG+ηQdd(d}+u= +yR)ըcQ>?~&)r>ٸQ.zIIJkϢ:T3ZHG_;j¬Q/))JkgV3g~mJJPn uРnTZ:UWNfVo%Θ1_CO=ԁJ;'Ad lYs'pY-7WȈWdR?/:_9瘼:w~)rz@KV粊%v]u͛]iiխQ#V_~WJ=R_~=3x,d @V@orNth޼j>}:lu_Ujy̔g>}>U׏YڵfY盯x@y:atF=yR;tȑ=O_)TGQ9rD~> |_k TxfGeKIҽkնe(˵l)nV%)JL |Y#0c<1+}KWwe p-e?_Ni#scΫWۛsgסwoڵ.WR"s:%CIhOI ٱh| x%Igz5m*t5HZ¦M<8wNy9{VR</@k Tӧ (/\R(z2qK.#C-ɹn[Mw  cl_Uwꔜ{ii*jj{Y4Pʹز#T&%eDD5sgaCI{ x4ol&*}2OnY%ArjMΡv\ׯ7?6%`^rv*LJΪU6I:[O+rsÇ%\judnI4c=) *9v:t{gͫi壏$}'J5o3//<\ΙD筸XRR<#5yjX$%E1u4]V=O^ٺv~s_hB%Z3_NK1N,Zdw1C@Rܲo__:kӎG.…ԛ1c$WNI{@f̰==]RrIQܤ pr?={Acn8QӓޗWbb>MխR[,;/<]\e zik5{}lq{K~nsxIKsw;sQjR#FM7IJYVz{U/<謌6m2}{挳}6guIMkB?A +1^zM7ϓW^ 7FUƌ1HIV_,]V^w;ifYa];3iM_11CuG vR{Mlե9QQU2j>d85;&5ĩSJ wANGRp5"""""ڮx} kKH  ]vxL~D2g(r""BFpC}U);{/\6LFsmV5B;%ˁSZ[(C74i"rwF&_1!ٳx1{' ѣ@bp͚I:8`͒[} RXp! bH',L.=oAr ̽40V6zHR오$(kmyӯ0aBggqˈKlI%f\ٌF{XpKAo%ǖizN$7yr"I׶+_:ȿKG˗~jyL,X,] n]f͒FJ'Tge$%N4=& n5 /~$nHJ~|s瞓{ɹߠ/1unHNԽv]Tr;ް8sr[KZ8O6 Ν+iC:uuNk["#_wnZ<._.)jg I8{omD+_w3y ׫s;qUQR)r2~2曒NJttvy)q*3Sow3G""""""),Q[))ȟ/#;7?8JNbbeN '.\[ʨ'aQ#"!A:2DpKE|Ud\x )Kk~i^>҉íFWV=0.8 - fastcluster - qiime2 {{ qiime2_epoch }}.* - q2-types {{ qiime2_epoch }}.* - q2templates {{ qiime2_epoch }}.* - q2-feature-table {{ qiime2_epoch }}.* test: commands: - py.test --pyargs q2_sample_classifier requires: - qiime2 >={{ qiime2 }} - q2-types >={{ q2_types }} - q2templates >={{ q2templates }} - q2-feature-table >={{ q2_feature_table }} - pytest imports: - q2_sample_classifier - qiime2.plugins.sample_classifier about: home: https://qiime2.org license: BSD-3-Clause license_family: BSD q2-sample-classifier-2024.5.0/paper/000077500000000000000000000000001462552620600170065ustar00rootroot00000000000000q2-sample-classifier-2024.5.0/paper/fig1.png000066400000000000000000004105261462552620600203520ustar00rootroot00000000000000PNG  IHDR BaJ pHYs.#.#x?vtEXtSoftwareAdobe ImageReadyqe<IDATx xQ 5ȃbeȁ%ΩkP6FN.V;zDqgA=za7:.\?Ei8;>lD"aj"i,z]֛,IC&irz͝;Ny2iH4qH4qH4qH4qF3͗r,0b#O$bi<bdۇ %*VNp#+))V |>fFfi<1b0"F Hx#t:|"F Ct//ޛ ;s:NVGՌ Ƌ9㝔. ̐ װxCJW\.wj::.^/fi]x1 eϟOp@ PRR".u:펿ZoaT9\^T]̾^^/z0:iG_M`M|>1h0Zm"1 Dx1b &)z0f1h?>L11Z+|'O\@GD//T7TNN qfh/zpqn%$M5)S"ZmGGG{D555iʕ@JKK~$˥bЙLR#34^"u1q\>q\"3f0Z%7-Vt]"p8܎K4Ps =Y2y@ǹpAѨVܺ>Ruuu-^d7 .ƋLO^?z;.Ĝ9H&Lh4Dbq\Z`0 ޣ&0!x1K|>eݙ3oR]-(bKOi< !xixl=i@ 4^y@,1xL{']M555PDL\.1VF(I=NƋ9+sxq6Ot4^ Hid2 SOmܸqڵg׬YLΟ?/_f9b Vёǫ)!JqF>|*"!Niiiyy^WTDHTŬnd( +466>'xކ6B 4'$z [Yug Q^^ĭt:B 4^^>d̂c"i,AM|):G.C'}pUUU9"k}u0ɓ'!Jw ~N\JxbZ 5@9H655t:"@9t萼/(keEvzg͚WYEH  m\.WRl¾3 &<0foǏOsBeϿByQB [J%cHV.+Y Ei<(bĥ5|HrwAJ亜`ȅMCj|Ъ}SJ";f@.2E9PLruuu4H.0Ȉ(jo~^'gi Tr@ѭwu:x#@ = 9TXxqR@2Es"L"gۣM] 쨙G- Ed^c00f䦋g$Ȣ#V5kF,lAVKrD̾dg#F#gT*^'&@riU]]j%2#*QԝNShr$~5k(rf{`JKK~ \.óX,F@YG)^ ya<I4%:;; \#д15L@DkZT*UYY%H`0Hd;{HxSbHe3^?aBxp#75<8AFj-䚘y4fz~޼yHo Q s8PHe9JET!x.2i<@#HTWW,x`y<^/. ,~Ha0Lv[CZP | \p9!)  l6Z vD l9|>3|79|wYh"G5559[=n7L j4^ Pkjl8xlk6mZR6ESMnF!M6I% H1` |1[n#fLx4%!8`1cC&rPу'㉍WTTl62]~1}n<3}_VG'\.hLуӍ+D~?( A)ƈ/i<YA]]ObM4Bܹs77nԩ^8uj~7M \p::t_z挈fF]3kxp U+󇵿SqňYӮҤT>*<`r@uO|wkqYFxv"g~C|bw\{___mRR/q[o]nAWT\+87~#Ă8t׭YKz pl !> ****Z[[G}[H̛V"98x/ ././/)(o&M8iҤl!Q?f67KED =%>*<9A \ꫯl͓ u>޿l2"#|_/Jv%y{<`0H4.y{_q2ʅgKjhh@ L!ƛF]nbQOFzf̘-'p]܉ S1_ eOnl{ >t}u;#kk֬ٸqc{{;9?dolBx hZ&SRRt;>'N4CC(;j~*mO9q؆bbnfYd2ɽIjSZnmm ӧ~KK@:xލ7j~\*J)!':|Gq(`Οol{@GCvڤ8i[ne_>x%CReʬx)@G[Mu!&I KWHMΌahI&r CoHMغud/\bL~uv}c3f@zbWWucnyp+>п}|禛nβJpꭷfuvv0(v{$qhWTjU^3@⚚fs_w$jZ<`P^.&qx9'5+kWshf./lݺxq{WѤ<[nE^?Nfw:kٰ֬aS%M7ݬR]!_ 444ӁjMŖu:]kk"sxBwޫpC/6q% ǵtq"o-.K<'IIyVZ% mܸqڵI=d2uttKB ͓vcYe͌28xN\^(M5s˯L|+jypPPpwmvKWkx:3ƜZX,FQyFIӉ7vf|lJhF Pru 2x〼\=I¾i`ֽ//o_k#:;;n7wfqW$RNZ&L!lj '$SN4rNWgkm|4xE_j.4xW~|uĩk&Kqcj|Dž4GZj͹>}z(i<޾>y*灟rjݎ?URU~ ygy@4V/KbąO"&M$"KiO WUx 3V'_g+_u]ݽ7˷U.;o_\Ro6F3IjJ^F?zg{e ݿ ~2 p  2Hd\W5ҧsKDߴ,.w>6o6X,;3g~/.Y"xjW{"7|Ő~[I˶MغUZ?#`5oݻS=ν/%k 6t˕2Dvw&J#.JC(E!HҥKcd]}mӦVXZqP9p}oƢUQ4۪WsxvcrZ\V;ZvM/C|:"@:50 .'"Q==?-7{ݜel6꾽{w4vst[+c}WԔRX/KF~fT̫WC/Bl\|ƴ}>lR0#s:x&OFG?4*c=ֶ.1eͰGM,t8=c3pSNS0V=>[,[r_٬g̸#/,i#3o-mx OjV)1)Rjus䄢x}7N0\Ӧi>/-twϟȶeҹӯVdBR*C~[y3Cֺ-oUT,GP0x y`Vyn\Ɲ#v"ŭi*٭KjpϜ}䊴 ij ь9Q0{fZE:>LJpƍeiiJ*..7o fi'>vz{rfȹ((H4MUHgggKK |;wF^.cU,Y*oq~#X]Ls9(~S 17^y~0qxgM+ H;+m5?y_}#cūJLJpxu@a]HM"RK}{J3 s4/ZP^v7mVy+"0}4G׮]K24? Ǯ]îoJ*//|Bb,{i{>':%W]!R17^b׭l0;vt'/7l.o+ۻw߾}w92[3gypK{˫to}HZ Q;#<,Ϯ'T1بi4ʐζ6KXF>Qj0ևܺA"ƍwE~>4^jb,iawmGIvvkkkfIUm/wJW-.m}kqYQlB,OM;0U,Y;r*G?܌5}Yiܹs7ߥ <@NO:8 F/8xPdqy 7:RaݚwY{vwuv&NNMӬZf*C[&9GLFluGq32͞Mdgĝ9%,m'ͫV&]}O'[W^\744:tA$]Qw)G}kqYF^ѳ={{X)[+ fH ~_qo˰tZ{s@&;wI`RKhs?-"X5yRXd;ڕk^!̛]\ *,oG/~d^*"u;'?6[777;Θy흝/ *,1sfDK+& DŽF&ϻdo\AkM0k~8B(iԺuɒƟ>sV,{,mE Aqi%qrxyi,k;5П Q-[%ׯ_ ;;;/"=I@|_u˃On~EJv+Ie|[RoyDkME"K9ݢE_zE,>sֶiSA'λĂWW-έ.(YV^;_2!8 h6ot:oxw@n?v5l._]4R{Z^@,-\{=(5?9.ξ{efHpl6L8ζx⩮Y^jhh{'[%D4i"qjtxG_ig4Zz3fO<,?9%o]ӥZ4qtҕ_A4.<.+fAjǟx\aⶕ?Z!֮]/ۻwGo8J1 obC2wvvGLw_,,顝_68!z;GǏ_g űҲ~zFC@xᶶ97~o}Yb_=";҈_[n&Pc6LR]]m^@ޅpcwF/}t/kڹӼji.owuw+:v"]}]NrqYt3gO؎x{׭x'?  r[qߗ_y59G+++cq:T|D["0d_}$}G&(Pj>o`സ,o,6b[,Ml͖:WKo_!6dWߟЍ28 VSSz#ƛu:]jûAx.?oE}4"JRvwFq7}rSYYYmm-q011&`0l޾q(j< ;_>z&`0s1x766We#?D^:;;N'9<@hoo"1nbhv{uu)SfWz9&ri< ;TG{Lh>9˜p*Lf抐:&˕߱ƄNZqy@ <'N7Y{zz&MȾ@(--]|ݻ#Ǽf[["rxHPnXUvkMӟߑ 2nlѭWp8Z`01BV8H? O \c gxpP\N4] (i< TUUA|g,-?7}ݔw~O? M 4ޢV@n! @\r5q⃏d"tRtT2T>Okl!ZVn1{rf'.LBSM T2уRԘ<^iyW_>Rb-ZPZt(@ PRRr^^2;ydSSd|:qfy4e/_=8&I Ǐf{PLj= $]EE\jVnmm^S 4h4 Uug :N20p:6؏ϲe #{{{[ZZL<+ޗ\ǮQ҂0nux&b 5`hmm{iJ3ChӐToB,%RAN޾'+\@>**fkݻwt>𾋳ײkK_|!l҂,2}5##~ ;tIi>׌;wܤIا@. dҘ?VmllL & Q)_ Y<5jMEa$.Hٻ`f˓~5VIG,&m$s^TOOOԩ\ \N,USSz#7"b4]siB {D14Ă1HS0\D1t:t\-8q[VL&h|$5v.))eʐ࠸^rx@h4i{rω&GcA@H߄慾},Q]]=eS&vK?ΙTĉ ͜9} ,lٲA+䇞RXP =fżh4 4 fH.T峻\@b**zNHxIظ#byaeycV<t:h2jhNXy`സvs9@v+// 75 A:NZj\ "Zbpbad9<5$c7qDv1#^UUƍ#NeT*&9PS_7|P i 6mz`֑Wp2:ŋg̘ɾ$PFQ*ūHϛ7֚˯Lr8IyCE>9G4cܠ؋/s0}iԩɓ 8ܹ̒OBY,'عB[G{/i訩륅wyHJ:?̟Μ I EEE ~X{_^>AHZRj&mXMveJ{iyds.lUv4#Hʱlٲ:ot:#V&` J wPGMFɓyDKp%G|f2">XVV;:&BGG9<@fsxMND"NFoJ<Owgĉe wTPJUSS#{nǎ7o[lyGZkƊ\C&lwOwz_O▖F$>Kޑ֚@8wD*v=>ߑ*ϖV*'8{L?}Eݨm/oڍ \:m:uرYfuT<س|͒Nkoo tz]~{p>WqȍaWŋ H: g6r\Ⓨ yshdGć&q9s v4;j ;v zt^7ǼjU/5y[ynT}WmxoJ1|#bDuufkrx g+.1]\SI \ɟ*j/RU\l駟?;jJCnD \XXHGt Q wEfAv<L`d/;R+..HFp7(?uZazW7}v%mٴs 㥑_٬==[8r4W7<^1|#bGo+XxVtJ/K˟{}^xOI FFٳgݯR޾>iRdHcc;uq{R".+<'~hhhl6%z1EV_Ν;'. H9$M5U*C=I4ޱ~$L֭/5ov q>o]V[{Bt?Px6;+c&5?򧀑"555r֚"gϞw{w…{#vuz=1I:yjL &+vB1 p \%)Sgx:hn}]̏ia=ΚWkdS_t:OHUSeeEE>Y]z8Gرc?v VV6N^W0(/jV-d'O^=s{)eZ#h ۻϚKh^mn;M6#;veWO`*++]Lرc?+**͝~ze)sǏ:q8,o_rOS^^NXI TVRʹ@"nz.ԫD>drwwƍc/9rB(ZZku,p>- k}{۷@.GsF꙳<8O*#?W^~Q^^YpTuQ1;kpcj-**/~SGJ/ߺ.)6t\ _;Mdwפ<\.8u^Gx;r6ʻrPCC^<Ouu[A>B$bN~9+^; twww""wINx@SD^SSSYYIpH]9HնVTT' s/N'ɯ¯ &Of94(`>Y[ڼys~ v=7$Hy566J?o4W͸zFsUVɴӳw'z?#ntx$2#tJ#gϞ}ځ7ޘ9cƴif^=sISV:W;vdoΣl^mȍ1jM>On:"wK`Ӎ6Sw2qJ:<ɹseAi< eǎ/G֚3dyժrɵ )KKKD[Ǐ?4y9|8`pIno9hEz}O? ` 4 &OzYxQjp9[994lgj#@RM8݈398Cʙ>2e {5hkk[% 5%QG3m9ƪɓ.lOʵ 4^oKKKG!Y AUUo"byfLѿJOK?LB1\ht8bf Drv qwHV ͦ4[^v|)kH )eQkͮΣz?ti򲲉 ?X^'w|/}W6?\^;bnA6o޼+9\%%sGͫVE|GFxKVpt!~_|v^:\PC{C%SF@Z a24^ j)l6iз0^}IG א@O@(鲢oڵ뭷ż? Oh<m?Ѓt.Y2qg.0y,m-Zh}4oz>%qrxyi,k;5П Ah4ʐ/W)O\9sflNzfs]0o޼P1A')|С+M($޴S&L vJkf2 E tZ6 V oCCZ&\øqkHJܜzgxk퐲tk֬-*i/uo{4[[YY).nѢ/"N9k۴) p{Z^w Xt]y¼үmW4iR[ko%τx&[nM6WZEHk-[|̙3ˉ6j'PyP՝ W@GM@JZ텅SG@!(AUUUqqj,E5yZ͉$W~3sސe˖* *,2U6{K Td"W]=cz4Ub;)geiFLrIK/m!A.z%KJ䅺, OB٥Al6yC \.WH)Uf`G\Lnr i<@ T*4 K^P$>Df~kqYF6q҈Xؾu~'|M7?3A%/)++[x1Rt]ml^Ϝ{ݏl0R]i㿭[Ͽ^ >wUʃ~[0}ƍw_[[[J!<#'r-xv=s^%K1]ZҥKm6o_l햛oYPp'nWbLl'5+|S}{+W>sV~Jci7Y*,,0F @d#t254B#Mp9j%޾)SsD5X2$ Cyc6m,**٦֚z~vM7ݜ]j~|/N.۱n}ҟX#qhT0t:k׮ݲehӭK<~VW^)^Uk1-.t]s#xLģD >sV.'穊o?.!AJև|x 2+F@.s8]ukK(DdIJTV3u>}3ؿ@-v~_B/~eNSgeEųK;|G²w7?g~ٝSD( \1q\yikikzOrwꝢ.Z 2 JɃd2L@՟HBX,FD\xIgrሂxUPP^oߎ՗:¿z9 eX,l0/<x%9GAvRWWW&_ٹێzhcɋJBΖ̐o7o|Cjo(-L$|h◷m#k' [lCghh|ölDku5PP ~\!ZViDV쮻'Nػw/@ 0їt:* ȫ)}^$g [xX,pD܃4Rr}sK=(c9. BmLDądTkf[UW]Nws4H$r9:Z57&, :9ueeevnu5ѓP ㉸L( d2c=)fF›|*>\ۛia' x0%G~CSDqvl:-nmyzs Ďi%zqIu4ސA}^{ܙ'u5G9^F,GTWD-HhM~4 =IΊȚW<^ct:ƃLf36DXuԩ31@Bb%J`0800v'R@,͛k˯m/uCy -Vi5;sѢTe-OﲄÇA} l&r6Mu5QQ(˕Ĺokd8 cL&*NHq3, \YYT'ckz>}zub' nbXVO:5Cx:3;x3S ?7ߤz3R\u>2D0(JV brbG{IX@Ԋx<yZPPw@s!1v@ $:sϬ_rع a<] R2yɏ_苺|oy56s y}fǂ8<2 fiZFu!أ]]O2L.ӈ(^ DW$VdA2[\  1<Hr:`6U&}F BreT#C?XrG$ ՔdhXhEM~ccX,]"n@n(((0VfYĕ$_u:B9Eg sx`0v+;)JV;a'?tx<+nY;~afΜyFiXH!~wӶ!2t֭n@;,))A0/qլDErx{HzYvKc!*4 e挞8QXX snP,ӋbM;~|]hXo )Ep KrOS<O{{{CCC r9pLCV$ eyH UUUUVV̦jf$ @ `X lFOF o̴m9uԌ3OxyV>4 pwvt ~oE'wOÑ6<9yH|/**ʄNIC^d2ԩSrMu5ə (OK<@~F İ+Nȕ l$>/9}[1.Moʄm{\#v{AX<5d116ocFѸ\Xl6\.,Z' uuuK>>رc )miijzmBKB*j@>kkk沲2t)Bs_2rňFXx_K.{ o!|> WӬR}ez{Rqu;_u?W]m^7ƛo9"~ 4<[ZZbrk׮Mg~L&+..h4n'$@aW]v N'466p$. 4rr!FcvDj+K,yu(ٳ ] M`vw7888::666fN0Ғ*o:;|o6 d lB&Ú$eS3KB9c:1R{_&+--%߶BH:\@>.k׮]."CCCMMMG&R ϕ`LgRdmmmhFj retٞ} q !S|>pLZ6:C~7Y87=T~1W#v,:֮SﭪOgΔO0q  #ӏXx"f)9ǭlIVtEwi@>e䃯hvt:#Ȧ&2 -rH#mz{{Gbe c:E~_tسy a<\rh3H$Lph#4⏤y]&U,E8_+/7o>s߾߻@ڜyE5Yo=ݯW6MV1cfb)..NV̇F8OHNfEL>"M4)#4R=c] wBV|0@.HJw2E0.XX|'WO3GQt{LY< %5^ˆ=p=ʟq軺"GcYD"QJ9+N*666\.yDB,--EZnz 9N"nUUUVNoѢſJm,Q=CD\wdJ<ۼyo- f/tw,9 t:~KdZuڵz1C6@.ōMMML&r .i"3ʹ oXW\ymߺ旷Ν[KK]?/Er?"ye'T*%CngΜy9ƙӬ;U,U߰՞ݓ-akXl>M?\bŊիWG,9y_DYYYHXSS#xV>{e!/bV|0@UUUkNPCCCýU"tz/%skdj[h۶%IWZZj'SL9s  'Z Nh9|677GQY,9'Ƕz\g$HdKRtއN# ѹg m9{osaK[xN8Ϫ*FRE 9sf{ p8%(+#y---r"f!'l8~ YR2q4,4.U(mmmf9X9"{#V$?N8A~˾y%v+@>C  `0eK9MHgϞH$ ydh+Bꈷ=~! N^:itY_K~3JH9KgEdppy ̔)S>̻~ނn1 :BT~Gu~2zF]L&r| M{$DT*+\.V(o`` b]vrXCCL& oْ]k~Û2eMjkkKݹJeb1>/mJ 65 7QrGLs8hcnm!{1g߲-#t'XuCDVi՚5\t"Gfx9q;Û>mwܞҗ oŜ98N \xE[naiyɃd׷qؘ/;X,GthC.6mzV9}O:ٵkWbSTj:oѽUǪ0n^G ȁnXO>oLn+_"|yns~J/+)gl!relZO?d#ɌdɅ^E̹jaK]]] Q,VK*J$F 90q4a0.O~\8r* Z{dO2umO<=vdZjgWW~ hۄ\Z|ólJ2Ɋi*o#K+]?du%,G.N~LNRv2*g F#m0@MMMOOOJא\S`r/P}Tx%7/P* dÁ0^n{,~{wE\y,~F|!OG[GF g'; f?+~|dVַ/ ^hll\lYH:8\Al|>ӧMMMHnM#y#޾vZH 㕕є;FE|xyvCޛ5L>Ȑ 2 s&@  V4!.xh4%%%!|>\U=(υ*Mųwvwj+BbxA8}}8\\ KF|/Yome ab%d<09Nm*Ce\xqkitÁҚ0q80+IsVkJx o߾{ -Ŝ^h54@ HW~D"@)-ZW2]vrSDp3)V^φ^G[UՍ_>|CpHg9Wx\r8q-Ӧaә9h%Q0ˍE[@@ 8$ɸPNb'J0θ\.d!/y<Us&K{3,]Zx^D UIYRӧOg'OĎKjr I>쩂 `F}Ya%G_ { yE5rG0d}544򪪪(VD='rD{2::RieeeH7zIfxl&e$%R^Z4I` 8s;}]sݕW^9}ڴ|"ḦCbu/"˦ ВB˔Z?u:t 0NJˍcd2iBrya&Jjf 9&].n+f_{www޽S'7&Df%P\\6x{@(JE;#kN^׋aeا'!oG@FAQMdzpSӄG{vG~?Z/5G^$!lܘd5GGGIEHf̘6m:@\5? GeԙLW y9t8$0 SOON#&C@FA GlZ4G*\փb|t4Utd[6VdTjٸ;fmbXׇw:,1)ґE /hi!&xD:gd^555Oz `u8CnL:n;ihX^-SVм=ӄ "Px22 #PTJ$Q}}}ZWFƍ.%.G\\tT*Uxf577OZҬG H{< aVRfvGĥWɰd"iz?ԇrgiiX-0) 059 "2$ yM!j֩ꐗp/X7 K~?i5[yC.x1t\>^M; t`ll )((wbd4Kd2f!RQF2 vqiR&b&LPQQQE4GCXjrҺ ذaRp>+HMrY1^g3}3ϴۻҼ?X"3fЁI1RT===&) "BF^łR+VLl#;zhx` Yz{{v;V(hd \!Mx Gz4Yb$Nk2yHCQ*%%%# qwTpLjaz3dGVUUIR4\./2,d2ۍxs>]$R;v|e'k2-7r[]] t\9^޶-KCc?Z9Sk˯3m-Z,QEMҶE#555hFjqG t:2xpH$_ӧNaG41c~ҐZWSw= K**(E#o565 ƾ~?rX,O#cj5yM?K 4Gz1mRPPf́YwuuʺF;}a}FbI,..Xk5O6ȇ֬!ƍ,_)GFtGՆW C.@ݖE#@JY,@A6@~T*Ҁ 3N<7cHWьVW TT?D;W4tJFzt9%d$/hHV\0;fZ}9[KKE-_ [;n}3+nK۷#*[@rx9^+[d2I Tz~WaАGW@w-i2=nTjj~YZacg[6wr 9'XreЬ^ ]~xm>L0)Z_?ya9K!;ӹ_yC&طoJE{ugegy7=!3!$q ^D /0Th X|Lզ?"4Q99A}l8b%pr< W =@ +c+HҒ:R TU%,ȇ1+EC>y ?YJ:۷lNiiam:sk5kps_eVgh,b$dȗ!zzOR5oŎ+jRgT[ߤ S 9{I{{;9uqhh#9W)^]YKk}"UX(yx*>þH%0$EB>x0= `Zr-//h0/Doo/Orm"rh@(^Ts=q:^mmddش?v8{ hVk?X,&kB?_{6 /Žg~o^!Ri0(2ƣi7)}(---!c3 9Ln>:E"!<:0+H!#_8^/x,hժUhmȽ ?G8XV:=gl6%ߋj^S4oFzV̺aٝW#?z\!Q%%%ӣYVZ't=)]V {/qŏH rO'9{Gp"ugx!KKJI_X$n4;JCqNƷ ȔtlFiM(wzuFF7=+g<#v$2jU|>5xOo^ZZ*^fyxJHԩS/+b1frˆ|]_9^E*fBb:$:Ν  5: bx `ܷ);;;ixnGK@l+ g]+Vd3g8N~Xd}ď=جܝO#9\> Cbw,d}>dcEyKL{^h4c$ؑdߢw~;&-8t }h1fiF<~}wٺN0!6FR}plX8du*"~ޣg=SLaAsX0x̙E~-ar|0Jex0^t<< '~rbɊK$DBBw|r@OOOyyCqtS`۷oR@ w~;Mf5GFX]-W45d߲GC/"CE}ÂW{vd4cgK/lOGϘhPy#g6-H^kV'e3X,OfK R*k׮u\3'D"NEf"dn7ҭ#~ r8{D@rl9|D w^p -<O[[lz&ιbyJ"oG3@DjB6v],XGaj {S5x<3‘Wy}"iy/asyns~a.bqzӰ&iLG`89bx388G~ $Z&;%wk )"IuluIII]0J9/r'53.. O~@(//8>3g^PfN1!v:9 <^WsmtX*j cx!)wwww^Z*@~@VW}=UlȂ~GdZgݰûS[Q> ULʚm3v\bqcccRN%G,GGGpMbD '$!G>8TC@FlI9լ^zŊH^v:z81'Ng҄o2[@MM -YPP@f<j:_Tb1Z]WTTKHCϘ".Hl~_ :)e<~hmSjJYJ[GF('Y:sS?ӟ l$ƭN&O?xpppll r}L&kll̙)'CԩS^%|~W!aQߏ4|rb hhhr͵~y<}ӧ_>.4STjx.˾( "y/tcji>ClQ?)~x@l6`ZCdUTxR2NfqUd3Q-\8n-GՍj:pzV{}KkuO"\T(8~ddĸ>5I&gX\UUvZT#=^x6/d`*n@f"gә[,gL¸\,H`oR[lymsEt̡F@D*v8}[[}Y'3b]͸*jf5*^;wE/\xNVyv߱6|mlxܵ]0A$m$ UWW Yz G{)<Ou>r``- '^N/ ^OdEo-_<ȟd亵> ˟۷MќGFJq2NHaa!v%@:`IE>P q-GaÖOqnݻwrf{au~@1us$mb1ƠYMJ!7n7> |c&v"șghɋ^={O\o?X4'[h ؔX/ڽ^N$nD  BF=as4߹~jUQ3x6F6n3e`aW I6yrI$/R,..FLE5E\𣝌!ߡC&CK䃔O) hpSFkXs<Ng4 ;Lv;{hd yqUԜ-Np>͘!k9 J^OAN:u~?/oE@,֮]㐓 HQbrE@.!L%ɑdd2+-3+;vlOÂf^~?^ogAŔ\_T*NCx;'Z]͸*jXƦv(\Ӱt+ȣ³ĉ Y YPr F/[r,X71%dYnΝ?lJhDy (//yKdz䬎 Ղ  ۱A㣏> W%A@B(u5㪨):WR6BX7 hꪧ]2 ~aF#KDBqʑI6󅏔J2lhh?vkZ@rح`0H4rWKKKkkku"#phەd EYY/wF7n_JmVx^'D8  -2 xL9Ww}'+n6lX5z㋊1Nݚm ՔJe+..;O@&F*@#'%r`{I*W^br9 ?6JNzDRYYR29ND\wmmm4d2ёfL{9GIÂ\} 9{]e<^v wޒ\{%к T$]skpx;v`CPr`}\rO+^~W񅅳7,pu4{Y'~w$N ED\WO#0fs\mZCCCVo.@zKѐ]P9<5gr166qZX,!#npPp ?!'6~虇%CCC8rVT*y^:@28q0NxX2x_dɒ\*jR UFD\x,Zk'~ 7Na7?Y탑WYC~".bSx?##\Qܯy-ҥ6!Yk2V'qA"hbLrovWWWnUo)bYww`ϗaxA't;xиӴgN,^acSSxy+XBjMN֚IdHh vr\"ٸnFF==b%4@x<1 Vyt:."sX Q}@^QT4 g6%#Ƅ<.4 "kilKl<H&R-O=-NV;N q h41 C  䴩R*++SOhdJ GDgk6YDa?x Ұ 3gΚONgz&)'@MM -I7A3@@E)!axj: xJ,k4N1'.7bx:['n2yQ*m߾ӧ_>~yW.h ^JUZZ9KU?:uwahNL[xqh1L@dhh}/‘?jZ6a<ɓo׭}6#[y]n}h2(gW0xَ\Yaߴ<d> ɦN*x;(y\.8}0bP0-))O KW[ >$߻hF } M%H^F|BrE-[pdiC-X0TnXFFC@նoL;MgnmeL'69UWW'kVcc2t}L?FX&dA6$pnpO,tz>dJ kBe==/6722lZ;ݽNga|8p'^M7{¸|Ѣřd%_޶ G5@(ʃH$jZDd<VLLjvjឞ4d &#JKKm6Lx]ME "h49tYZ7HۺY7?˫#97y^.@a/$6^%`͚|/y&ƺ[U^ڷoJ1:0gi Rw_?"ig?9ujs:~ B&#i^ٹs# Dl/uD7vs׿.y'Ç6oB|tK/]:gmUK3,Hvyᇒk|ƕh?P(hLJFz{{ٔ&LS__%~GDd ͜S7_ǃ`/ՔP\u55ァ a<:~e"s@ /O>1_~!UF36 _E[kԩS5&tsbԽXK3VEɸz_}ni j>뮻-$zB _'#j5Lt$ qbgDL+((q"^2x|U1bJ -ãt\Z6K[LwOLj+j.q)<{g];E8ku߼RfljJ4qծ,7G^g_Z֐X۷x(|e1yYͿ*Yɵr4E`rѰ&_zzz 'Ʋ2Z - ¼^/ EL; L0S*ӨhuٵkWDqWԌe##C,.tӖ+t׆j߲GCF}ڳRbN/h=_D?cnAMM˶"y ɤlrioo ׾1ļs'/ZdH|ުjxc,s,ZmD_-ȹn0=a\/5Y^qu]W՘9Sްy'7Cf;;BtDxQy擟 TCo<1i/ƍ%ӯ}W[KKBd_ؓ w7GQĢd Ɇ0<rHfggg7OU*h9y0Z<\q! 4d r@6ظsh46-dQq+##ÞT; pՆGzߟHZmKXw;_!YNÚm hG ҫTg Od44 Nn-n`NVMIɬgK6}Uő&o~yx,ydd>ܮņo--dUf/Bn'Y@J`]p,Šs]MHk r+⪍i4f3M#3A]MDK]3tw}>_,3;wnF_{)tx=Sn߶fRQsddÛ{ՆKOsӦ;_a՚5 [=h LgBΏuc3ᯪp_IYmrq\N3|L&kh8pN-G_[~.1<y=QE ';u9Bg"^Ñd^ڴAC̙R:Z_ɓGn^W 7D\]yy9s__[裏d# Rع\x?޶&]Nj:_Tb1Z]-xѶs&A|62~4(ŏ:t$+/yV>u!F2Lƴjй:_8??8Y76d;5I&gNjFC o"oz;+3GQD+XX< Ͻ.9N5fԊ*,Ll>&ո9s T7"U(bOEzfyΜ9!Jjkk裏:;;u: x|aq\.bOX4yo[к}fޝsQ-`ΑE?xT,(ZEP=I3,]'3y)kM+`%b4bqĄ<&hK_e$oyՓO6^ꘔ}L&uw}OyU`а忶h flHf(QVVvbj@ nѪP L9smBa4=v@=d2&0p8]e2O={D UQs+;S‹~7~ ~gTu LY~{G YG[mdvI69<?A@HeeeI1''^qP 硷ȏ}k̙RMIsN[QG ?VD:~u:WnNl8ZE 7T*BfYoFeee- .uAӑ  ɧT*'|H $5:::888 d,wnՌ&jnT03Ǎٻh;w Q*w;ڲVJŚm h /))h4!#b1N%˼y0._i^2q}ZUWctb ~y ]r%Nϯ @X,rHQPPP__?[V+|P(9xrj$O!c&ãn!f\5wwws o`n;5o5׭oJl÷oƆ]nMҶtFh+ʆo%עEm/Vw_X|Q ^|n;|PVo}{|{o?ɊᅘC•Y,:l0jjjB:4zh4Ja2.2Zm656r@ hn!"&P>0 ~i_WWTT\Q8+Z]͸*j=z [6n$?ɓ']wɩѲD~@1us$m'nf /HK*bxI7}Ͼ}{=?~}̿xG$Oi0^T(---,,lnnniiKlݺ5qWsH3jLTVR%Z.dب5M}pFVhlZ.'rO^VV{`\bsW^}uYCɹ+sLKt;|#ZvޭWLΊ}+R}n~ַ d2I<\ʅQH ct KKKw9R pݽ :/_༚̨9qUwG+WZږSmop:c¬VZq߹vy{ФcGGGZ.'5kP7;;^53ydy|sWboW25}Ga7y;w%\D%oOʿVIwϭfeM(2ٵge^vO uvE%1rRZfM1^Ğr<Y];'k믿A|S~ia^U&˾pb-[H綵V\2S'RNw)oYٟ /޽[9ICرUoQJg#ߛSu{n54K}2ť쿿A<\WEP;{7(k+x>ċhn)|ُp &Gvzj:OCr̫rjiFM'5%w-+5,Z3$!MRP2o\jxG2Qe==ګٔW d[]|Ц> UH$f]N555ֶ{AvΕW?tݵ _;9}Sgχ꧛(oV>\q̉yWJ{#謨 Qrx@Pn"qJTvSǏid2뻻W2vt4 ZB SIaa?q2vy!*^(m=[JyKKm69v/ZXUx\ :ر M[nѰzU?xEx3gt*ϕV Lh:>&o3gHP6Uh5-YO<j\~+@,e\䓵5OX7;0wͥbI9 ҥUSO몛_E`ŷb{衇-Mm7q݊ӣrIɚ_ӊB!Y+*BuaZ.':[SSUiZŋWW V~fu?#JC#ӿ;,To/9CaV>bDo i͡>_aVCO'GĜN};ߑ6?N&RA^^^ӏFE{P ~j }FMe=lEfͬ *T;fo򰿠nE9ϧ3eܦWy,Ĭˉ:rxrzO!EA0vF<k y X,&+DKR(C'y͡ RJ E 8(oG\T鵶֎;wu S&,Gx6ltj˯tLe\ܻ]={U[˧~ܩ3g-K()q}]*>zJ]ﳿF%1rXf;!^VU/ Eyy F!2G6|Z h ^T_(⬪0y;vaFa޷-SpǠŎ7QJ Ͷ+)1& ZjmرOuw<)@\~R*zSTT$e%snog_/,,$&l6>v{<HfG)577(3 "^_̲%z~ݞ윜~6-/|lv]lMMM4 >K|[nyj O۷oonnNRCdZ7;wΞ/~K@(=˟x&t:r}}=1"tP1 R2O(iu!##CCLы 6|efi)< ;VUU _SSju: %/sFH`?~iiK@%GO&vSA{;w_Iߊ} h4Z,vxG涶6bTp!DϠE{@,33n"c2.]'LzUUUS6o{ lsxLbZ}>40 ?OH~m& L C}?.>} Fhhh H(33StXə4iRfLޚ5k5nO᫯KrK ռ{aN8<gە{~`4 #Ri<@ 'J@\dggH/LA_I`0{---6l^:a„Y.RzHb:}O=ǎ={xgn0mԔGXH⩷ qqwRiidWy)ڿ 5͞=oN%#oDQNNv>@'233-[յuVyM  1mQ43H ^/p!͵[G4=l4 p>I[L_~=ӧO/**:v_Pg :1c6 "|폿Xt0\+V ~222y $Hz7nw㍅DD#yR ڌF...noo'&@PL ۭQ`߾}Vgf)_kK/)p [ZZFŒ Vtsb444Hy$O_C]<5###''Rjtl?~ZC|]HH1 &iΝP< x[[[4j6 2.  P _܎֎SO6:WTTDHVFl6"mi<@ԅ3fooo~~>Jz6g ʼnwp ggg3K3 Boo/AHbMk׭uK(n޼9EEE R. .IfZD#g5/@<̨ H5BzzvKRU+̵]zXQp(;75. effwuui3LpR i<.rjyZQJ)y< M(@Q2[[іÇRhm=sLڞUZN,##fŪ\.=)Zw b@>}Ν;C`FM@j hnn&\__߆ nՐдUl 0=؎xxDпjevMDONNAHAO޷l}u=?ʚXf_p!?\.Woo/ t.G`ҤI1BAx^>L23JJ/-'Μ9sޜj@Ͷ}8<ɩӌCԹ\.ؠΝۼy3q \\___\i<@L4i=xBWW@HG}wn#7&DߕHn|˥ [}9t4@G^/A4x4ɉU:]%噙ï`:bxƪKmkEEÑO+5/`3[HD&LZz_~m1zTRO[&x}̀k 5H nfs[[;n2F#O_=r]]jR98x0& v™W7JW7 <IYbAp8F`?JJ$񔑑4^NNd"@?NZs:ƍkhhH L8nSX+((qjܹs=K {/1~tͥY}Ko̙q"ޞC`v R_&a4 vG\p'Q__CROh4555)A%v*ׄ|< i  /PڜNj"ͺ'Nl6Ţo2N鐼9'I5>|tv={ҒY : f;ǤW^Sy‘KuScgUD&_k;Φ-[_=sL9R~%.)&5W_U46%׊{>O3L)ɓOlhhlyyySI&:u*8r^)=ķ}WWmiiZa*)6(\~*'?+v>ȣ߾zQU圛U+3Tu{f"W9*j09<,*<:qQJDs518($p8&N8Jn744 Q7n8tR;VkF*80ihׇНf3z4 ~.'Bم>)Ri<x^:ѰzUygϪ%o, ;l\dą+š3gj 9Vx6TjG D=F IM8n+Iij&T/bJAAꋚ2#'̊?ANhgzK*oEcDމHGveejMmʩ5CEOtAhta.?˂Fq]IJDH#It4@wXG_ LnڸxozExOs*場2b|LYZs?g\ Ro~Q,==G/,ꫬvjOXnW&;̝x dIմ8)*/עV v@Ѱ}~^A:'NvQ#+ rzIFi<@;vj@W:f|__ݹNPۭLY=c+WJJĶس=={{zFЌ--O)ziFye ~q]e߽.97RƮ7}ܯ 6n>ZNUV씿}`RqYeKdTWWwS.R.lZC^v2QdĹz)qQQ_^^τI_ķ s#mʸKD/艢rrrsr'16j efJ`*ċh(X,F^92cD5B|RGM{.g;G$8aTN9PV̡BS4iq>*G8J ?I/ɀ<йy{W{z-Vmկ_ߦV޵?Y!LE975*:o\Q[u\wUaQÓ: @ W^^>qDݮTpXVqhЏ2/~S\BV}+rZ[lYqqS`ڟ>kTJR/$wM zʈU}" #S |٪^Ѽ<剪[XX;C<*Fd6iA;92ؾA)M&j X巁?nQW:ai< ;;{HiFIY >sl̙*EsxNa/W࠹T4ON=v݋VU-^"lժJmѯ3Y7x<Ґ5T8qv#0.ŧy3hMfZ AY,U,紷+_ti3%!1Wn`K]Jvs*'{pt9չZi DC[zUA~pȨ:+P('+4 wfdd۷XέX}+V\)?ׯ|`G{zbԩ&r&/͟俓j.-mt6ˇlndFIɚ_u#`|>2f2r)=X֠ -ݮMD1b\> T^^fMj*$@<(?*O땩$'inĉKNʼn4Q\>pȗrF)K|ڣh%owHQx3 Ly !{,>,f,iKM Tϋj?KDk&3x$p27Z;;_6`dbJKfVքG-s6m(%S?fd D~SBT__/vʟ0UJٯ6yO{{\lrZʏʳAM\Bj#GFQUS"NW*Q>t.//O┩i1WJĻNUKc-J(䬕@+jhh'Ӈ/ʫ=8CN#ۣ*'ѐ𓟚r@AH&3xXQzXe\ﻇVloihztLYƸV䵶ET8oK6jW2<K*-wI-LT+ki`{{7T9&3L>O5$EyZ?l6+uYmhP.KF*8G>/Vl@=QO3|mj䁔ZdU+ȟKwwr2forOJk4U: No\Q~WQ B-jîTDϾ Cx otwHتV\&h1˜OЇ".É0bHVrh4JSI~C*Qj͹w_ZGGZ' ;sRV^VeiD'NH*s+ŶT%U- 6(JM 'Z89-b;G*ӆ R2R4^4oAo"Ѕ4Ç &gfʙ*v圜>?mhh§G5[f'*J372NʟiG6zPSr#uQ)W7چvi^02h(I5i݋.ͷ:Ԫ)A,6*_> t۶i\zu]f캺700@$(-8)˨Ĵluuu'NHhG$8~~0& QK ^ԱmF'kj~|}jު ue"sydM7ݹ`wgA3v #\⨾|xDIչiv4͗v8@#7RQ hooj8q4M0 1f{h2g uw.X0m+h-5,y@"Ҋ;h3JEi-ׅl3˟}&4 Ó6::y>]~FBt"###pgWWWvvjgoo/48QF?9e6O8QWWj=Q^^^PP#֮[s MhIǶmf'J:t(\=, *褚Bzzji<!9%6My(..֘"ί-_$O;G`FeOԄ3˟ 5[DcMPy5'M300@$($9ӘSp8 Wea-'*++l_hD&4A(vv{qqv*sN&IX! HǸq㴓s}"H|JoUcڴiSƍ:l۶57ozhuww=} T+''H&E޶^:h^^DvjMԠLe4,Fd@#βZvfQY9)=@!HnW^\ 0- k( I&UWWʁfĉNeDQLnjjɣ|>_`&ORSUҫR+0k 38yR )L @֮[PhFe[_y5qWf݋е/TsC8.?fdDI_4j6E<&72aNZvNc%Ϗla>1O7JqIiӦFk׭K#~h TQwСouΠG5FHArA14N9w<2˟]}=XNW3z]FFjϾ} TCO<|->Иr3QuzL8_333U{{{ TSm]9G975 _zugi<=:tP֮[jZߓ55 y5#\==G8^%ǎY4^[xZS)77Ǔ$Pհz7&ݖV: @lKxZDE1&LB&M?00@  @3˟-]6mԄœ55͛5F޹`nFNN6IՕO5/`3WLv(0-\t^?ټFeODv@2 \O%2R i`4^?vJvww>D =t}8p3$==]G^/;;[u4Täz۸q[p J>lfJv65m߹c1}0kfsvUR^>d(vEY7߲eeMkʝ҅2#=xZQ1Kn@ҒYbRHqӵiӦ<Ol 2݋$ `Dpy<@6Ǥ~ZV]Ʈ7c*3J>k{=={{zeLc''b(3"⫈Ɲ Eq:vrVG i<=2^f.+567o k ա}jy0:nyrK1^??_Fuq ˜UE7ޠpuu`SgDԋ}}Lg*ZD۷/>Oј6<Cȿce,YF`$nGE24^B՞Zsᢻ} u'rrrB G{zBk޽o:_#e=? ]Wc)8q\yhцI&߲Uyeh\j1&DƓDƢ"y{뻜ؘk*+kBCcǎNpj|oblLh\r#kGk둞cvэ7 |]ߖ_ܥHq\\\l D/Qj[n]Ƕm @beE| 2YY LZdfj-.jb^8.dlCl_UkR].JQg9Խo Zfܥp8V+qd_ lv-{e4^FS~~*9' O yϸmߺ?[NIp)su#铍j8y-6hjF0cG^^^wwNq:Gl444HAk}}=Awy"jkjmjC-v*zA]N<ٶ?t9i>x%%k^|j#=ׯOћk)|h/KÍ?o<vDCuqn* bfrc\5 BVtݻ;Y,Qpcr$ PƑ,s:{uZQ1T[z}دիT92A=R"3K(ױ;qb4^-oý(嵵<N ftӝ hfвe+K_oo^2x/^|YWGhsZqlGzu&܀W֊ ts(K;Vc3Wo'deq*yyyMMMGee%H%'kj77|*E[_}@Е J ]]],'|93!HMUUVp:GUr%VU#tVi'OFvea;-ϖ|dn3 d>f",&LFeOhض5$j-Vb uK.y)ktD}QRrEO*y}r̠~wn[fZ1)p$hxZӕ ɝ ǐN?tR`Pzr/;;[58J`-jt6Kcgﺪ9.dluY{]ͶAڝu-O<3goʚR___\\NbI9sL'N-}mku:jq?E -y'J26}t:.߶O .E4o}64 rrr{Lx0|EEr~S]ѭU.vExlL5MeqWi3쬨Y/M]?? ^H2v漼<ǣޞdi5N|w';zk(B .ޘ^xa!S?H7;N."6$}93Cns6햜=4F,''HHAUP*2i2guk]{nyeˬ[gɼNԤLn-.Uc~gM:aʻ$PtRvM|9s9smrjmqxSOYY--߾j|df9BO@o*++Ws:C]taaʱc_tJ 3njImC~o>P=̙sѶA[JO֔I&m޼Yyt``733=g)ŕo-:S?#JG{zY˜>Oajg-{a0́;kvH %]@qڣ\*/h "SMgS&k>Kf*UOylMǗh_(St --w-ꫤ=:+jhڸQ$(qT&d4&x2 )I@dLu4mh͵w+gTyi.U%N?nZVloi,^(:ֹ1()ycכO=Y;{~q42B :&&SzzZsU.''OHzGp()OUWY 8fC-N rff@1Lcz =fĹ;v (褚 5ڤIT{z{{KرG?͛$Ťx2 ;^</p4T 33Svǎܛ̺ K/ A5*՚涶6 iS,r^M<^AAp\6lPO8jk^"s L~CϽsnj(+k0(xHMzJyޮ>Loiimoi!N NOܹ3gĢ:Sb棏>8{Vstm)m%i<@۷o_~~mNNVꪩ970tN]U>(q$O4pΟ Ӈ~\xḢ~>} ՟_w>M h>H LUOeҤI7oR^W~ HF/;~W?ر?C:%f=/Nۆd[[Tm;sOOmлiAB7x,]jf@Fg=Zgoo/H8 u? H,333[z ,@ #8HͿouTVVӧ#KI">1tΦ-[_=sL9R6Z~r?+s*Z^۳JKf:2gn"4g4 RǞ6i<g^s (AEK,^&K v[fNV9 eP$hI/[3nVVbUR/P@#p <4 !@\>o/ޗe6EwN od.26h?1%ڈh)-}.jz2TZ\^rzTbrh4pM&Ե722D{T*M.%wwWɶ$JbŊfT ^aEbxL/_Y/ 9==>ã="Nxrn#F9!!/tȹg֯D]Ѫs%۳t6fPE))RɎAH }o{Ggf+𳿺wn?lSh96mF`C s_p5( l> s:L.-{.ON&f$OgS}* $e-G ,a]<&5HڳrLpQ1ա(fL>;{]˗l89Ҵ+~Zf/[ 3cWl6DѸB6mc? =_lPSm*`l9jornM]PKӴx0F@J4]boJI#f}tHrQ<9*oK$ٿy-u?;L>v{,#CL8.$ǏKC;#p%%%f19N:E.T, ݻ"""D"}DSS&rԆ?ǯggڳ}]rGnjT+;No?K ̋xJw㓟B(&HHH(,,y#s 4ri@ rpJ *+,tpڵV[[{qwWY11Kal,-.uhuiFخ~gFcu+F1KKK39ɡ䔜vfkiҜ6Oo\(Ԋn9sMo3ʗH޽WuUX30eʔ1ʕ+m;`pp0*8 Lfa<p2T]tL5mII3=8rLǛ4iҭ[F2}͛YYر -}}r~ߖ;:}'(|>?88؆Hpl/111<<rc8Ϗ$ 2o޼GRan5;1lXLm|}tB&rB[0ӐdJҴ](br9PU4ss08 STT4Z-Ѷ{w˫10<Va0)p "33Ӵ=<<5!sZrRpiؕ9)Yb岓 elz&^GhٲeO'h֮]k8Qg!*6HpAHsm[:! lK$v\mr`H Mx 4MRRri"ph+Ʉ0)Vf x;wHfmmmDDO̙틗.{졷EluCk#jr`H GXX PryffE*x`|iJpd#;;;//oHvtt`n''s;:ɶrYbbbӞ]G5ߨoW$[ṍaZ[k[=L eee#$..3 rL&+))T* 󡢉䠉\.H(&gggݻWV[9,y AḺONI~F}W u6rüHˇ;Vv½w޶&aٲek@JR&YYPP04r9MLLd6*k23I2]\\d<0`Z|~NNNXXhsHI^AoT(%YwӦN1lGF\uӳ`I5P7ٞ"""{||<*j/R>DlBH$'N\v\.g+ ӕ4 9OHG`>L2ʊEj4..bgs3 )pƹ-¦>}9FHf#4{,9 \dHo7d 5IL OBB°E*ڿcxIII}dEdU|r(99\ i& a<p0l6{ǎtF6ަcc/_ILIh\BƌM/Ξ,/<9y)+VH[4gZ30A6޻KmfyȘLk{>aȻxG ۼD"a`|YGT2*((8z(#0"ݳ/?&`ZMRY蟑aM$aߨe\FF3t!MۢZW4@)>Hc sXXH@\inimYa< C*IE0e˖az\.0ij۷ٰ@Ix4yDu2y: ALo)ɨ j|r(994-$Ѽ0`'lVeT*Yzٹsgmm-x0Zm@ @EM:D'e2P(t3(5 D":goJ&1s ?/81 0lU::&Vx`/|QKGG0aR#* nC+W7(NDqd,)HfΜ - #gr3,..J]&ZGC6/! eeeFZaa!fXX<\5VR}0Q0T%))V(̻\X,oL} ӧNwnCI£! T R]]0*c|ޅ͛7/""\lL &>ag"!11Q*23(\.33Z}܋T<mHӴ!0؋v֬YXOmPTTf@?  a 9ww73edw{˘j'rې465jޡ|rHgŋů΍Z okN>{fPP0+:\TL.{cڳFX=_;9X#88ش6""`L#7`^zz $?@-x,cӋFa_'+xLegg꼼Ǐ; T*f6FCaO?4x*|Lz{&dDEG'&.0~"#G"7 T*w=z\ Q |C'V\\fkmm#LYYH>9*")**r㹢 ?;{}O-eǼgFٞ6<1;ح`ZL xyRt޽7557#]>>U3g)b3Ƅ;dEJ 3sNL 8fFP(d~3C&b811\Qի9sf\CAE=..:YZZjgErӠ_W S91;8"'^pk%=b ;!x_}M<ʣ'""bǎl6lZK/93{( 14/r~pLؠ"y~~~`aZpJxBnAx^p>pPF"L8Z!U.0%8hTpJ>9BmnF.#pHIxokJJhHxx[;xKGo_t6fWU7ץ[MMԅlWwcv p3j"=`L.cӋ 71-%%%??={2$31Jsa]bb"iPa9<V&D6fn ) ڵG8Zsߴu5aP:/L¸HOO߼y@6RF'M>}:豇޸XdFB87: /'RvZfbb"'u=/0N*uN]z4ձ˾>Anr8'=neMwww6P7X)S7oNJm+{鿴0ȼH:An0fG1P0l  EiSTWtx<Ν;M%넄TQ  :U}M%)pB rEM78I$/Q{ɻ@RRO6L*+utLȇ2G\x\yj讙1f{4pH7 |G>g.-a,+w?Vv+t?[ff؞쌌 QVVfzTjtuSa Qu5 N S5E"c~D,IE .%7>/1WL7mp\}}:w~t^VkMvg*s̎i2x~~~>> .9~zfG9z4f{ov-77sc_0*GJ{v@#29zT& }}A_ټ/cӋF⢣8ZfY qӦ ByIJJr,\.3WC.S2|Ϊ#Ŕ=?mǯ.i:c:ϼG0΍ u};Pp&=:݊+߸&,_7e==6k:>SH 2%G뭨mX7&::00^Qs]uuJw{zdtm< / %"QPU4soݲz\W,]qt޶6:β5S,Gs]YE[۽`WW-]8a6[Bx܃OK'O17K,R"Z\DA ɘ3ją  _j9c(VFFFssiBZݱc/ڽLBa+7h4 }Pu[^VYmzoݤA9ŋ՜KnΏ>K힞!x]#L(-.#|R-~e0fb6\ySiϮ#86~G\|޾Y_? ϑ7 ˖-[Lj޽XML3IKKBwfڵBz&%%E8**IJZ!b|Litλ_(Ommm&w**")**Қc.;x腍t]27 rz{^D塎! `l{ pnMMM;BQkwt/ON&ۏ/[Qu29윜\ZmtWYYKMM,ٹC@wUW_xej{d;w0]4JFAfřn:IIIRBd҇tKLLk>Cٺ\nFduDww~VmEV\OwOuK.S7Y,ւsαT݃'2xiS##rYS!§sbf8lgjA@L"""555aZPiq1]hUbbr*7uj(y3{DƦ}]Al,mp l6;###//4</!!Ja@[XVRRBzH|̙B+Jِ5#\%T~>uj.nOOO =:]GGUuӲk׮WT~Cg̘meMoo???r2aMW_NX  GFUdŭm-w n3..>|M/d6 (}!Õ˗+ށ}{ Z=kw2^瞣oWU m)V>P'>rpS8$$$hBvҘKiio>0#E/,Y:vL۵. rә'Oע[98H4^p܂4L&z#BYUߩ:5 sƝ3ӳÚ$FEE%]A*$$dѣqۛfBKKmV,)TVg~JYҜ1TœPR3ɰ ׆g3y33zSDB.UVV>9D>>B$A\z8V?Ì LP3E!y(GoΝ0aacSH_-WT*4Ҹ\.i* vݕT&23y.*0:BL`8y^ۥރ'iAϱ}qtTϷ49a8+rV`J2s,z⥋N%S0#!qF򊊊ϩŊ~rerpA QT̃$?r5U!Y7lɎ---uw-͋4I cX|-[L"67`nn.5xΩS' 6w_[d♟}9q&ݧyWI-5:OTrBaff&L&CB:I"MUqqO>nl~YAh644>s^044T?jB5wMcOsHdT͐zs;vM;vV,>>{Xɬi܈TO97=o>c&8&Ln8w;:_BW#{v,aM ToM:BKx\EBBB||i{sssnniLD;~8fQԜaYX{O"y;$Y ֣,pzA;OOQwĜ|rw%y&w"/`X:h K3:7?2r$kbx~whG x`L2z`~ퟥiWSRDozSCIKB{8bYڛiϮ{w˫^ 3;:+%flvNNΫj4/++s3 |PQz|,YZ}z? u2}v\^tM-+))dBy0@Yz`ÇFPIVVvs8vB6\ zwwﮪbb::}rStrf̘='~~x`iVv+F hiiqqii鱲/_e6]QQn[:! 0_"p~$?tSoߺ!-[Lã#yEEE!=U*UNN^(¯O_LHF Jr+uW}qvjVvN~^."y.(<<)rP(#vtʅL&#tOPdffr 5yٗH$dcHQ@J[{GGCB!2fzzt5[psԞϭGwuuy__Rݺ@:;;\]0?rDn-Ν7q{烗lCxmUDD&gFVtyr2,z(l MKK g&%%ܔdFYz|țy'[`lddAywrER{{ 5kg7Ϯ a<Gfi:::03N秧KRӻH5򲳳ɳCSCU8ۼ !N7ԜCB mE$1[킂kRrƻs۞;a{4'9gjh+.A`B!-H1b͙2ePGCeth\mHs;!݋/?::7}}}N2"큁N??_Og!,z4. yzxx-A"gbH DUXX:X*>58r=?hڬ,HDcl/ݹ_+**bccg͜d!+3._0k T4*]ZZX,M߿kڨ0B/]~gЙU::&٣ӝ9S~M^8a/89?ǚz{+^Jp81 zhgqwwDx$G@^4RRR0veAd Kz'X^ZNyϰM7$%Ɏڎ><;s33q<#@&) H BXj^V\۷pwwoh ۏ݋nFm͖AlkoOZd#&:Ji;;-*z9sfG͏񶼗7˛)EϯeF ^)>(#7@ l3￿Z<:'H]YUi!Xs9̻6 W# ͶSA>!'Ix.ŚEJ7nS1<\);x𠗗ãT ѢollJNZ̙&r-**illn-^ĉw;VWvjgӧ2d,c;e<p䕕577oٲ슛0W|^tJjv^6>4Z疐 F>Nmmmnn.ڏ/f[Ny^.ˇ--V]JN>Y{sɒ "7I],TWɀY9tԟe(yajhxt\GIIIRRFs/s(11s0BTyL#?ύR,z[[:,v/1П>#P1<7C^NoP`cܐvtmc %72eJ^O1[{{{Xd&a<Sf?monnFuhׯj-[DDD`b ^Q Ν`ۏo_a9Ytw6~c(vUWQ`i4Ȝb1F. qR$F.7<{Icx/^:Ws^.2rf{xucK!n82USS>p6,IED"0^˯9WYUYQQAGY9onO fyOLasx l_33]gRcaHpnu><<<-- /s{ң1TXP[~U&}BB9e&Ŋ9a꾻t }cy ;qJ}M{zz7|џ~{@Cx|7 JQQ|FF&9$&&cƑhFg[r*yvuuzuӦMϵkO>KWќ3gvH*R%4}}} 9;;;0-/֮`]^O#q;e477ok7ndd0h/++ST999f8߭\umkV 8h-J^֧C[[3卍ؘ͠)SB,O ۾ݤ%p„S&X>Fs7n?2xHT*&E?~|TWչ[lxm%6<JNWVvezp|)*J]]]bxkΟ hΜH c{x0 /bx1Z[[? p„E&rpx7ּy j!iGDD8ٖ> j:++ ~ymj[ӝ-hqEtޠtֶ:444gt /444eE7;p___53Ipa]vk[[h@6/jkkEx7xcإ8 wTJ[[򊆆&Y#SKkii;}^vRtqq>>c< 3S~Gݤ.Z0.~)͛7|j `\Vh4IIIF$/ٗn!#qꐓzt:j4t̉5.8{ҕO…YeU|$^騛##".]Gtww~棏ƍ$<sJ9[… ZVffk8W-[\pa<GDlIKK4Nj $ "X-)STT8y4"g%2QKmh.+*ܹC L, vewuuA}|||}}Ic{{UԂHr`|i#>pn fC.;;pP2YK311ndÚ݅B!OB!H0H]L5rn#fuqqܟLo{{G{{^OwO_~EX,֢GY4w떦~Ⱥͻ#\@6ػ`B**.lFpql6{ʕeeecs1 1CnBP*c˥"gJol]Jfq%gDG5&FUck:רA"O|55o 0aʊZN«9g}}okL;_QKww7˕h3 555Yomm>p>o:JjʕcƋزe bxK.0HWPPP(JJJ 5iiia0`.}jy'=I.0+.QM7=<<̞5o\o˺/^tww'C*+}5[^ FfPPPlL)wvj(K0ػUz\p@j*Q|~XXZգgddwQQ7JAAGda<ǢP(233o Foؽ/o/]V'J,+Z(GUѴ2f1 ⷗kΟnX#Ν3P,//u7\fژÆNjeY!E1! fBL&c_툧lٲ?===%%N r1< djLzdpw$+yXy]Tȁdgg獛BZޱVWWCt#YNkhh>+a;C 8@.c>Rd~)q\.ɨwT2ݙ9z(VsJ3B*7?2šeN }vf___WWӞ>9$ݳ{,']x\yrM*4666<ˋi laԂ{[˰ҕ:jtk~"f6:_0lqqq oٲ1X,p4mMoo/[ww7bƜ*f+FZs2%Ý:}Ν;M6Mnj5vvv644Ra^\|am5S:}I{HF#4aˬQ(c%Wx{ HRH$..#_Rx11QDUrGh K9 }mf/[h\mn-g! ڵIu3f̈S~gY׫ 2޳ Mu q̞e!=03K=ZWxZȑ#jA0^=ģ? FCl%/aЯl<  _& LNja?Y6#vthufO)olln[#Sܻf6?{ԕBp rWAQ {ZAѶQ&3ՙqlϴs uөBؙ gߎMXJPKHB,XF$Y{^{%aKprrHÓz u$+*qXɾ44r9k@%44t֭` 7Ak9v؄$KKK4gOO\i}5͔&\'C*paJ`[n&vP(Dãie-\r$c0||`Jӑ)J4T?VL7Z3GSUWrt:#m{M61 &ǪxVW&Dx[n oTV%<|%Q36FxRD"@S"eeeűu:Ƞ `2 ud-LgW~esKE (c sqqH5c1̾>VI%!V߾?`: W^^ITֶGYEkXgg'f͚6T(x ,q,d<^'*twwAGZn4W__СvR1cƜ9Aq0twwU߹SW_OSNӓSWTTg ߦ1Qޞ={ g&Qsʕ IOOD"A@68L5l*U,;cn&0 2YoɭiZɕ+YW/"S{ycB4<]v | |_MfDD{rrMm7~wtNvp,`pP`LLYz u.^,*:>.s&0H#555++ 6333-qxTGMH`[~aa9\(b=['8gP(-J.ϲX(2g쒒ή.r/E1j5j/,YqP++3nff~$`͐6 OjB#^cdhh7i -dPvHTfM߯$ _>:װJa,ZFh<} |Ɔ>`0st#e~$0̥c]{ R96"Z 1ı8޾k >; ƎnG >}544ಏϺςX^s4:u }Xtj\Eײp=A6oI\\;DEEQ|5M]^+Wg={ jxw=5@9P=ڼՌs~C}_5<|~*`[D"jD"IKKswwGXգ6J&++jx`s%ؓ1$ΗX,&YQI8r8ޏU7:`0 6g۞T5p rE1zN^~(:ژu4<ӲkxOGGG> r,N>g4hh[ўN:ˮ..p9~88>\ܾ}ŋ:iETTæfj;o!1"j!fOis'JH{SugY–Iݝ}7U"5 $''oݺ&s yUG+W.>r,?G\+ Ξ9QpdC&jWaV%%%.+]Pp C):<@\4u 9]!>nXHKuc|Q?06E˅ZP 3C$6ТP(Dԯ (=si|MpELr@ć+uFɽRtibk[ *Wofय़2è Ʋh>u{WT r ;%ˁ*K))5=3gUTTJtES3)Igkxyyo]b֌W\t կ|-jG555|vjscyMϣ~/lXޒZ7V%< }5] :jvuu)ǽwsIk8pPM&S u:|׏/mݹD>D/shxϮKFJxW hh"== ((h ۢж.BP粂`G=fddP5<-0oʒ[;: ޴qú$󳠱RǹMTUVΚ5[&x\}STuw饮鑝p_ߝ?1Lggg> 4mV<Ғ`:;Nc̝CkȟnLóNVC3x-w+'2*Xk>}&𰿃:oBW_==6=S__!xqqqU;wqbE_~%\Xso 6g%żYR;tU$$YK re⥹*!.-mf$/;1HLL6_D= :'O$_tw:TP3rvLyENݎiEeչs'M_3E"gyE-\ps! G֣TlUUU/. 1%c]]5t:uuua}25حWQQA3Ǒx+:;:ZWm޾Glxa<'>tڭ[(s! ۳gUE,_{8 iYy69j^ܦESii;ȮPDq z6҃A~ g_ȑˇo`gffD"}N 쎎'O0i6l :9й]'R|+}_@bF t'+Ё*X`<9ZR3vHD <@zY6t"dqlL%J9sg&'J{w=Xlɨ(x+FBtwWWŋ,+&zQpX<kSFょ'̀J|5{3pر7 ϯ_ jGV>ㆆzt-caCj|^hh(hx 4iwkbI]j~'As^&Μ fn\X$##tp4MOO89Z 4'F㵵 fel7WGh.`6Lqqq~~8]1w5G&'J}5G ȣ:jn&-.yyyE4lcM+:u 3 ޞ8 ,rԔ'CUŌ1Ϗۇonm1=dw@~v =̟V KOOD$,qS8MMIM6KK &!֠TGvZqkk+^tss^Ns9 L1v+%_?xl\^\\gdo։-n&Qs5fX{קpn̞埾{nm?V:??[t Eo&ʚXՎ쒋/b5NvZRRR`';j)לΣn} FĄoL&W>HLLLMM͕JzD!E6cM Ji#&d jZRZiemX#rRDl- ưWZZ^6b懄DE0 e<`SX yyygiׯAujZ/D~鉽w^B]{4,vQԙs:kwHYYo^~&ǜGdebQPu=>lji7Xzrәlzk׮QM2i+Wbj<5up1CƛN AWßgQE/x~BY0NB!ԵRf~}}}, ].0ƍZ\vuqYi6k#P&snhW^H',omj_}T3Q-77mGmmqOK~ûwR~yU"JASwD32^흪ᡱNC5 pBF2e<2tcccaIմQsӓIP_G< ]]VQ!=qIHjї=={u.#0[nlDMhN9h#i?haO򞽿7788FP*UhH] m2o$} fgXY9ϯ_ }5Ϟs5嗈E+r׬ON~ Qde65 >.za VR_a~>zK;o#Ǩ#*cLjKJɎ0h,s'lx?3zBysСx+xfb_Mژ5xB֌Ν;1,xy=ܿ*_ٲ%?D"ɓ';::233t` N V際 _(J,~V0(hv<ݿУnM 5Hƃ ===rxxx$MF9l, ϧꑀ2`]L7%/!>69j~z{.yHU2l5$?ґ-*#y<ު@|>ىdVr3~z]&_'x1Jܒec9j~#q3oӻ]4l?NX: EIy֟hN=Ѿ׌p0+$dyڒ_d(׮]0?FLL .`_M,!DL4wΓ2Q\]"줪LbQQ.Sd[0 B0;;='&&ꬥI$.lzÀtUp:Ҋ}=hC^)6 {zz*2rWWWb9P\7TodT׋oǣL9}@[hLc9jNѾ~\ ";{֢aJ[D)N|iq1(hƪˣı$SvӖ/?~\رcZ ыG΢C$I7FpbbY+  Xx )\2l홴f-l@ZPPP[[c󂃃P s+} 6vuuQtk4OO秾WVIGG]#;ҥ/fh`|>)X4x\4ZM$uX\|O+%>>>--m:)4i湳gG傐::z)[:YY9V_0/HyFEFMH쐧'Wٳ' j klLGM̆7P{ 6;9O{86nJ!#A=\r~dz0Ik֒~?TPW"&Û ̬=ydjj´,JRy`.xQ$7:aYNNYX4'mӃD*jeUUuF(\./Ŋ ys:N:1Ʀfxo<` %>>6m߇z͚> }{k9j>',atuuMq;{ܹs=]'r =tE xɔ4~Wd𬙘ZI*4i&nwŋ](jum.PD?ϯj٩ʪp\C}| h72$ׯnp~WA7;i-,,D0'AY*QrW\7ؒd&^?q(3wĒ[66l6+]t12g /Zu*=:^ss덛%$%NUgBT^,i5ž[-4|ZFͨ80X5T,XմQS*}bǻ;=> h>3L7MH쐧X3mi&EԸ4WKŋ:s`cO7JDD9vyz>g<@ ҕ>͢˗0:N^y盖ANfvNDzv-D;` h4Jef,ZԤJn[=dd҇vڸލ%䷯yQlƁrY,Vuuw n.^& 5jZ䨩;w=ޝnڷ3mv0s+#+֑kh0D044tǎV;r>&א9 45DDDwg4|$ tFH]>!.? `;}Pݾoܠꂑa BMnJX+,,_+ SSSE"L`vyuM-Mhadps6louŤ6x{|kQtL ~Z_bYww8rH}Oae-&zΎl0|@ՍfXX( ؔ<[ƣմQ6d uC#:Q+*qbOO[mmj)qjF2elǘwe̓'(w6[_fR/œ=bΜM 4s$4("2=iitc Z;Ii˭[k%pYT^/bgu^;D U)7+*tTS5r\FØ!qc6hdᪧ^ x{;2>>>m#8hs尰0{Q=Iyb,3 ӜSNdKY5rUuդSm߮cQC``)՛]ɔtw^g+ ^` -b1ɑJkE"Qjj*L]Yd{e>N]Va^m%%Mqfh4BѧP֫׮E???a"r`2 ]nRiN{jJ6`?B#X06RRRڊ(jv5k̛[u69GM̉[ /]L^$za=w,E<ƄE3.>qyTܹs7);d}<:dPxv~ /4IHFisf1lm7P17tHWMzvOOp8Xh4:7Z9ӏ5DE|jGj.pq;>puD&q¨H4]uP{8SD3y`Zv%cj~{\ܺw"p2M՗ux_aS3ީT*Ml? vf4XtߑQYYy!9ga_8Y>JjU_bccaB@(fff[+J~CQ $KOO* Zt .yCN7L'oTV [i4ԹZ76iusKW+K6Ge@&޸y/zyyD/twPb<WESٳ1 &_nۺqS ̃9,_/yLRɣj(D5f:jbR_zoǏNP~~__ 1?3YsZo_߼맿t^I߽˯£p2joVz os5Qzvd\x1;;*h4C~&*ӊ)<< .= ׬Cvڬ=\\_ M{?2j6i5 *V4 2#1}#{رc!ЀqiŃ ;jÄv@ZZvW 8XĂTVۼy'HnnnppplllNN:(((33]gf%_;Sp[j5Ud24`0¨1捥˖T(]]T  /00ߞttd<?%O?"GMLPa_GcQ gxzGbr+.)RC}=?;o?tp͚cLo^i۷;މɨG=;x cAhuB___kp Ko#]b1X'O4N-;;I$FkCZPPP[[k Я1Ý;S_|%Q"vPü{t ~%`X>ޫIploQ45L+Ɉd#+>8Cݚڀ@OO/5%%$/99v?@4DBmVP(@uqqzq FEP1;]'M4sԕ~9>e?}e#K-I?01wdQQMEsTV郇ÖT..W?flj>?qt=-\Nֻx:=|w.^*_EDDQC}ŰT~op5>p~KO7m}q.n8qvyl/~iPJyضm[}}=H'j5 BᙂsΞ=w܅T,vQ0&Xv7ߎu ]cwzF1U/6o&Azr?=!Kŷz@,'*sS,61 飞.mmmٕšOkOfȻrdnu얶[iD39#&lt yL9W]nkoGQDQ*U}}vvujg=Y= (: ʕ*%innqdZ$ى4\GGK_A2Yɮ]+~jr>(n2VRw$:+W.1p_#XGnNֻT w}YWZz{6cf#<ݻxľQyF2QO!rӧN2fӦM))?xL~>(yZXx,رBZ{wm^44z2'.899d2q8ű1>;)H@@񍒺:b-]<{,&6N7Rjx4bJ"lyv*!nٲ8jO?t>n#+P;mC}U#jL)Q}oNȯ\L㟊#AgϜprx$&։ )y`vô4j~A[g֭J`` O5r#MBCCaZ;C,['ͪ&[HMMIpAuuzP6~W,_Z,R\\\jL?V.UͷhZ OѨTjA?ލ%E3$d^TD85 ӁEݚƦ殮P_1v@i_MZHSm']]v͙Ct2l_z99Dãabmn\ZRЎ T{N4]]:g*!NG]KZ=R"*$x< pŋ۵.%ߵk>W_%$$@>/6q^yEeMDR 7g \r`554~&OY@ƛ\>8IYg}ijtqIkRڮ]j+W.Uޞ~[tDxD2?/tDm}qWNLҍmr@ bDn4G=K`avJӸ;vH$iiil;|8$+g@S Ĭ*?578ȢngZ$}E1)7{o+*Rzxju՝ex`Aȏ.E\#wj5>ڮU qX|t:5qD0 6`'|Z9nx~ BL&*-}|n|\nW+꜐a_,*"/n52-mpw `-~sQYYy^{mEEE5>+B0--M,>((ɓh:`T4MP{l&SC*CcS՗\U*8OR|>*t `Tϝ&7fX1.=Xd56_O=ЧP\VL=:uvvLcMP-GS'9*'bc3s$20:===l:m2ho{,9;;ڞ)әsT8xӔ ?#Bl۶,|[yoF L+B!:ck( =`0T*v tGg2F^4~?0@&gكTO4B???g៸L&aRԢcA-g?>4>Bt3g=|H d>>66lt&/u4Ѹa U M)H&M!`t:x h)W.w&raÏ XZg9{%n+ f'Ko}o֎^PR%9J"ШL&ppPLTw%ɩqC77x ƍ8/,t%u'L֋fIgP&x-M `:BS 8ѿ*HPL,Ps7nJQ?\S[| ܹCpS<؄u;>=W&DӀBlIM5a񩬪֩={)c A|)q:!UL&Ӣ#MV(sfssk{{Z$ gc2H,ɨyhCc\\T>*]]c8dN'sWW7Q.kڂ~v +*+~Rn=R3@سgTEMGfFFZj`=R2ϗ,j\бh4F=88fMk@2+*>h_\.בñȈWxw4sS`>>TMH.^L_~7n eRƘ5""{8>u13 ]8OK.wtF,cD3066mVΊKB V~X9sQ5k3M~/P{ˈ2o$q\]-$1n@4UL7iF=S+ԑ,[ E|h ]r:Ԍy؉}?n"/; IBQSXXdN3RJhbB$Z& -0öETd8z\pT*՚`N3K>z *lܠvtHoܼڊ-[]Y,;з91T,&h6̏ 񬚈Hm:mn׏&{$˗ ]^G8pPMC}݇J3=ll4p헦 {ٹ|s:,n}q+-dd111Q$܌ jK쥙Jiii0ֆ9|LOOLgkkJ`lLui/Sw#Sr/JЃ:~I?lx[U <<<@ $''333Mkx@PPPcrssAɉ acNg2*wP?jWRPMOL|7K,{66 Jb=ㅄCod 0u¢ H(Fnnnff鎤RiVV9_453T.WDi4"aLZFt:oppgV;99Uh[ɽ{h-n'YCaaaRRD"1!?&&&© ^999mAضKKkTIQ&6aX...---jL&Z_6iYCXnt:IcTd6y cY,x` /teU'r'ػ{-z֟}V^ۗᇨ_߹3}n*;^yUm$_좨3+dݺuǏO 0JzzzV NMM DC\L06Y=--xVV e¶9=.⸺k oZyPRx<ol`ry Qʁ''د77N|}}!lt2X_aS6hW^HQu8ڤLԦy?hx1siBxd<PFɓ;-:Z0.J333M%IFFPTFۢGxt:dR#4MȼyM?V\v={Ҳ!izKn>xHFz:n \lW|F`ܴO>y.y i{=tn܉$Oݴ0ֆxt8Ȋ`M.lw |lL.777888)))+++''pTjP=ZK4<a"|>O0tB\BJ288)EDGG3wq356.8?,}nXbyݚ뱓'q [K'Ր0??~z'>>r`> 33S$JR̈́Ba1 ?##ꉵi''`ChSnWSk ƢQsfoՃ_J7JFȈֶNϛpa$?7~$UǢFAMMT; K^cr5/3 籓d)cyoѣϭ[0`?~\.[@@L " P<d}pԴ4y&.AAA'O leL;88Hjxl6;,liVJFKEE՝jRWEGEk\GGM :4ug[[;x7_h)za_> 6'WssMMF/^z;'xbb';w5C9"OO`L1x:f"322P_isrr![bbbAA$-B| % a+l+:'?ؑ/Y74x,kųgLXlJ777xɀ1`2^@@N1%z-xR;{a.Y0jE\\\e<__EQXCxտ|aL, ^hoo7POOO:A*|H;jiiu  ޽[{uΜjȝFPQ_}C\4CBEE9l:r9IOMD ^M` حo9Dcc#̀7xXXLVNmm )g!zmWW)_3X\R>ϭ[^7}||MԚ6mۇ !^ ac8xcE߃7Ϲsѕ,aykΟl0DFF&$$466 d2Wa1,e6+qqq:#[>nGy?Vgє\nw=/邜V{FyZ5Ùa<N__zHȃ6&i?A9Bll܎bcxgWeeT><9#33sΝi?`8yyyaҗuL&Svv-gHfˠ?2ʐhlj6*=3/]iܶuK@$v<sH?-J~3ߠmHU 'eDT*hozzzW_L8ۖ-[hq?v 6d=UUu_`VhxLas|jGqqu띝=us`?!.>1?{J%x0I? x f e 8;;WoyN\.rQbvww 8Rq_V˷<`|PVU ^Eృi&-%%etkׯ>t(s<09C3_@[ՙjc5DCzdŋ=^jTTUY4 L6AOMb.-,V{#7ں7|xZ;vl/(H\PQZ:Be)ˇ`JOOg)"""11 ÒLhX`eN"nwoozò Jwv0+澽y<Ғn.\pŝگW(J'%G(Ijx` =$#y׮_:ى(TPO?LHH\c춘ȕF~__v465BR!jӪE?>ܪe)rԝK3Wcf`4\r4XpaJJJbb" 7m۞̒ꆴuvep}N֟|jⅼ|?XʯX&&-t:ݐaٜ_VVk0[WrG2VTI QQq^*DGGuv^[U^q y"ḤPY/44d DKTNws"Gظil>da<|l6ҲF)**C.z^}K#]ق}Q`0~SfQ9Lco_\MX0=k{}艫~\.?S}pdtt:^r) Tņ[,V$-E"QJ0q `&HOOޑ2x0nF1}?p9994tGWEM:2sL9|0z]fscS-G6xs5\|Y9|%iAAA6xڶmDrˎVrl6V#IOykj._ۻ[=x /cKdrB.| 4D ~7F.'5 }|NOT(:OOYmWɘ7df`HIIvf2fݻwsr3e-7|~WreϜ9kTJU+SwSt9Vg}N'?_pX>K_W[WW[ XR)B!ͺ#r__;Tk[ 8ㅚ/hhdc9ko .TfIa歾3`196-iZ~zӤ;:|'ƦLnI.V7zpQQQ) "tʃuwρG_fm5o^ZV 7zN >譼^pů'=Yxcf4\0un={p²eRRRp`b䌾``Geu4MQQy%}/gtHE;w8Rp<%Iy"sD,Q*,U*Uvvv^JR(1&lp /,4d  xc<%-يJca7\r~?$Kh`*&((HV/iFl6w{΄IrT*eaSΘ@n%~) b"0) 0N!!!0[:L&SRRcm``(..f1,d>fsCCԽYFY9mƔ&5=,sȽHc1l6(ݑÇAA7O#JJek[{ss ׻Xj+䤩V,N^il"H*`^@i&})iPHO.pFҷ拋!Zy'0 0NiV=>ŮcpQPP`0hdl6sچoMє"䕜~u#''gL+zґ 7)ސѰ_knwvѪU+Ēԟ}6Ii`rawݥ 1pve<7M2H$͛P(,})z! {im\WߐjEzd^X]KW\+&lpQXtjzPZ!̇0Meee,ǎ(//F!XfL_ᳲڑ~oT*WΜec ._|k̟RW2׌/)-I8\>B3˽ykj.=w.OzJ~_aNRcەJ%mOvnDm떏>:dRҥ_pfbLt xp[hjiy|\ sF>''d4ƞ: ZZZN'd٦뭫o`4UYU=)a$"}BV(w.ONϐ12{P(.n:t8TX,Ԝ4|qq===켤ZPB\4 ]O!ӲM&`(,,LJJ/7}p/ԘNW &+W)x>IRZ&b|XZFcxbxuZ͛H)m6 iT(g?/btww\.ҦZ!D"jRF.  2>;vWh9=ue&p{* /ٜˢw CaejYYNw=.FL&&f 5_qRWTU %$GscʹRB ӄ鬘W;:}~MI*Ibة`ȩeu@0a~[RLXXU]i2TvvdbC \T23|+WP|=Cw곴Һ  qT*D"qGTY,/b쭹p?GW\I BGIPg݈-`}|(iL\.I}2X2F\t(-7~k_peU\\i9deez3tij tܷ9/G#jFS%?W[[OgVT[McxNp6R xU4nw]4%Q[6]il03csK+ݔH$oX'́fwPsѶV\=BZh4%%%CκLt:h4њrܻ,.\ޞ;Ɓ{zX]O$DGbFcxL*Yv?g@EG~q6R.߱tڻLz)i,2a\eYB[[롣Gi9=u%-XW[\= V.++ch[H p10Er-;\.6)d}%mIcxj=S00J'=Qa=rL6G~dlRbtV(RdWvT,`0ޖ-[pfGFF:|oAR-ˢ,c/`ͼ&\ryhh-;7w`56eeU 8ivN'mp̌2L,d ¸ؘS}}@4GT&i-Y0y&_@.$"Xng3|S6͛&yZ3Szzzbb"w>ZP9O>͖v;H .V8SqUᲲԑaKG"MiPP?y<͖v@KRkMLLfKH& 6<DAz~RIFa\jwE -nt\.s.u^Z]_ 3p͛7ZLPEiiMm-oXn}x+ +**pU?\ZZ-5d*,|}xM yK|_V)S &}煩\0E [ ir XfJ%Ο R(rFlzvT&J$dSTZVGzѥm,Y&}u_BV}d4O~RHÑ{HH$L w]|q:'$c`xFՎk}_j\Y.}фsD6>vr_"&-kO?]u=8׷xǎyG-\\'1 #%c@#Fӽ==.dh:]aYE@62EΟr҄󅼠)Ϗ#,0[ 0;:zccX-6ݻGs(;}NXUM MҿzO5we7 VS[\? 7qظdt,7l67fyy: #|UΜ=F𩹥uc\@e_\z22bD"|>f9-} HǏ>>|\iG[< ޼!rK׺kiiyoگv $y"Dm}0BT*U\EZ6__:3kz,VuW:~e` o,dݽY/lƍpJGP1h;v4fuI;'? X`@ V3yyy ' Y,VZůz5_\ hi4U&,O R0GׇmRf#-i֝L&;e)gy<Hĺ8n]xqGggkk⋋'?RV8je]~kWGGG]@NEtpħtt$V}}}+{zcܝk IVܹ-3/0 0;ݿ_|Lhb?l>q _fAԕiiϿ=^c;DN%6n֟\W{J_#OfF&5 6LNE^^7ozOu1 l6gggӲF)((]p2f Og'/Y4 ̦@0Ճtu MBPT{ۇH)s\^W$-NVv8>OB/ޞiio'RW {˗9Zh41 9idy򩭛7 >DN=fNǒ!Ç'r4iVAJ18`؇:h4gee _nnZ- n~- /IIIz~WrRȻT{wJcj3ww!'rq;Jɏr@0 99oLLB na쥮ZЖMᚖVCӔ n٤}#/KI^arajhjS O<ԼiqǶ`~<~#`@6,ηXyp?񫦶ήp<|fj떇iRZ&9j;DR0SGXg1q,gnh4Y{qx!Ct&Ldi4ݻwFVRR@aȋ6y_0,-!&?G)8 =Vm4_l6qx:B9N6%_ccil:]%$ iFC}v4o^͖C-.|!$f!!2"G&>h+WccV KT*m\7:6rFr^Px:y5=r9S_~JM3<Xa<ѣ3d4hCߪ:9tK/NͥA KO;p7$vp&xyI=M4UVg >xL:=&7kO[fl6O&`8;ɅbNe hEB@LVDG sB46-KIf=C78Xm4UBC푚-3t$c#jHɎ JbH$b"M'% c;cca465566HvT"gyd:̽#S"0ӽ?ٶn:a7xKJ63g|l'>S$&&f;k= -[Ȳ,9c>nᰵn/44&Wk~IIftq! ZM[fdɺV24P(]%4@RzCCo'HX|\iY?ϏT]_|QgMMMw߳?s&icXe2D"ސӓ, =H$StΏ}[6_818X,%9&z jNspl}}}(am<ZNnmtԕlvpgϱrlؾ]8S$>nDWn/( ?.sx1\p}hpjFqQ@URvѺ{ֆ˒tJt:*((>^s'>aKߑ20W'Kn;:;i_ddߺ4GML&E"J 髧DGݹ˧'O 9H$"^ܞ^?Б:, d.]nni%2LPq ̏H\Zڋw3"#K|276oz$;N +t:<^}Jԑæo%jxa$id2`p"h~|h\\VqܘM-?·IS.\H#EHNj_ԼR.)JFNnf1zuݺ푤K27/YR݂k~J:!{ф?15i@ '>Bŋu℆x|\߿'e7wݗm_{㍭[ -ؾ}"}7{G {nJLCå!'.?4GTTTYnX`LlLN?a G644s}KJJp`4\IRLFg4wsՎ/-]zu*)H%rD"6Il H$f3m߷}?Iץq*KX0?8X=CC=40,4ty NO 0$Ą׮:s拋Ao_ߡG7dG$A`2ձ1 Yѣmm,DD jw v҆&rTdkzz{=rģrchL.eϠa<:iZ xL&/v`[7oINXRR w(-⢉_tV!F@2̼o{pLݻw"REnn.5ǎPz/'h83gϑMUWB\AAA111_{dkxFb+?{'r9[Q/7%K_:~Ʀ]P4p0 @Iҕޢ_pzż(Gx-,S__ɛo~㙧+(-%O?mI ^=rAx|A8P]w>'x6oz Dg;t+!5W`V s %ѬgT*)q@6}:&jnnijjòsNkxkܟ!E"A#ͺD"iB@‚eU.mvONv ,:˰!Zy3R2a<?IZx[ٺUՕEt7'WEFҟ7db+MX4kf7*tį! CeW?7ֲ-8|yy\g;L .׿/ /aݶj C (ZwO]XVnJL[!>?(V}>_pp!ԐT*e3Mg$ryhh(i, G9k0Y =s'i40ftT$[Y<%թx08֯!24gM~/ލ6m_tC"{IbK[},~SIIP# ȼo]yy%/*+<Ըr\E`r>|d2+wyʕjfsz=E&7&]}åj>?z^V "-sr\T^|еkBCIttn|")'eC^Ybހ6d,>GyKLtTRiRPg-ij 3K[[롣Gև q֯mľW[k@^݇ewvUVVw2"Rs|jOJG2y77oZ`Idg{AXUSWV3gX,%HܒrOo)鎎NRBZy5YD"&%G#o~4#DcxCWp|#,GO C`,* >aCy)))s ggg+fh4"'`jLő)v[[ KW,N켦R\.H};BaX%i/a=tII X-G-],@H߽Q<44dpe]f'i'']K.`R 0Z;AO)\jW^e3:&y93fCCCnn.!ߒΥY\\L?6eeex4_'KQQQAA rJy-&&f런],J7((u'|Ro6;88{x&~_>znI5^[a{̤a6*uՊIڪ3׻Qw._ի]<Cjjcv'O{z{I9,445ue@0B\P\7yza|O4;ѫ{8K{CC^墢cxF)++c3> 02#ãIxt.MZiX<Mn}|HޚAcGwFZ{׮ αxaY=Ssv:|!!`JlL^xGq1. tMRILLEgA8V;I4M^^4C l6-Ҟ#oJ3. ݤ7ST^vKR~;:&b]A;&d b v;$=;)(*',g8`L%Kcc^{5\]l6l333S͊糣ɡar<3Mg]f9;;5MAAy fE) ]᧬yNZjuun J$jwܺrф8G.jX":0\X565[,@npӁ*yӇ2xS"3#s߁]ן9yxGc4'EccNNKOOȘ,Tf|HM^w=9 .zl61Ir t B67&:m\.?|T*dl>L"y䶮}{V227$-^B*x##HJ%8Iˎ0?>EI Ή0* 7\~xS"ɧ۵k}]&effWDSh41%%% tM^?IGY6"s1dr-b?j:$9NKK )ӎ.ZK."?,wݕ^Qqnk4'z^%HT*fgdK.H$\)J4x0f6.Aϛm1ǒx 9//oLyդ=Kn'1Nn] '̿S)q@rR[j:]eX227ژ|G[:!aAkkPt%/K'Hl;jJVMdI$P  ,;.Z10n4^mfȨIc]⎵n%ꝓ3>보_ʏZD"L-GNģ%b} Bw.!7FGE\rE@ !`{wTz_hАe˒4`B֯_Ι9Cbh5,ǺETWŋnJr<..6&:OWPX,H$._IK]yju\.Be/LXhhOo/?ѐ$"&pFDKX@"A`hHIIHOOW*3ml999-++e2;;M3`1LcJcs) pӕUt3**j]齽}=RD .ZHWX,.n`zIዋGx{n#4D"GBZ AVl#""l٢"## cy:Ӕ~t |#`ojj:{TTV-X05%*R([Vx^/)^b{ܼwA*Iczd\v{ sPdddttիWGnT*38s  N0 0WyѨweeeL0 ˗'߱D*M'fLL̅L'$-ykT*zB\.H$b( 0wX,yja<c')w{n$—yƃ.77wpEwan[Y2ɢE bX MJ$I_|ljOO?>VK(* \{aMEпx2AS@ s;zǔӂVp |>_ss+ER{^'is ]FFFޞW `m<}8tRMbxz~⫥ st+IĒ[v2^v-VVJ%Rkw8b1[To:*P5\53flv{OOvˑxs_-ӿz]=}{Ab\@a~72NG觷 e_|yBԔ AX2/\#G^?fXHa;W,?3&::9y)344䫺nBPPժ3v`3yl}}}hxYm}^EG}ˣ;\XX p0LIII4J7B3<==>=>2DPw?@rW}O`9+H^4񘙲'+iq0= @4nIqjG!)[2mx:4uL8V4ĠsžX2>g_}>߾oVۺ?]Xp-=6kvXxëA>LF122wXn>]?uh. 333+skpx0&0T~/W+/t2yԓ_޵J![ģ.ݹt[w+-Y?Sv_/[מS׫Ԝ\.JH%_hGGGӗb1lv NOһ{~ &''zQS?%VC ff`ǟ[nVށʾ}]nxS]߿?lq8p;d{+(j>|nYܳ'OO>[6Rngat]B eë#[*/E2fi=G]?VCߞH/p/Bv|ݛn}f+ Xf%䮻zϽGXKp gffh$۵ZԹ\nrrrxx8l6$!hkx+#ҡxXGǟfx_v؍7~āٝq}J];L l>|p l&|RxT.KOO71lv͇/txtitBvkv~޶dGkǏ?=ÁOL6Bw;ΙV&Q\6ԧ錚1СX,]{x%#f\޿Kۯ)4v-֊I5`W<+?Qt=k^lkvXmw30ʯɒx'Ckz'^1v㍟ SJ'._5z  -i4 /ϗ7nOMMeUtRLKvܙ$FL?G^뵽w~KfC;r˻;;o_2OkݭR繯Ry٧X1q/G,:[MrGWlT ;is(_TȎK1g޿us]s=ǝ.qQ MIs{OǕ9>Cc7ޘ|s:`ifw Zi)NQ(&&&җ@ O|>_4Ao{k;:`ڱ[o9}K'oŮٽ%ۭÇt`>? _}5;g㿕ԡCwǿSu׿V+|oVnΓN I5`p|z~ϽǒŮٽ{#V].?ʾ}lK[-rhϩVz=+|#G~m/+/7%@󓓓\.l7$ՋN:G7NH^ay@%zZ3666+Jry.o+η_}w@wb<`LMMuyj- B>222*wy7z A ;pTV,S*ZUdm<X/wt0>V,Ϟ=-o'</XW\nV3 gVO~̙3k_=eRMX뮻=y׾5UA?zxOeؕz}T*###IzCJހ>%epznӡxb#K Ԕ_&d?3X, d{jjJK@xiPRn[_b<L>l_x \.  :b<# :b<kTejj˻VkU 6b<H%ejZRQ@lL @tL @rbqμC։yyYlSN={ږW_&k;sӧ]ےWll9{zϞ:ڭ[U|;'Oڙcm<# :b<# :b<# :b<#X-kaddds^߹sgGF@ wzë?IZ]Kn']cccjuff@uN.>R.֜lۥRInrb< fsΝ=ņ|)rϐ © ZxhV5<<l`i(x;v,-绔 u5Ż\.W&&&1==vbv{Ւfff; /M!1f1fVT*B!LJw8'mY1^Hh#$'lZb<XGv;rlJڜeѰH@_X5岚dH@fffFFF;wnɨV+Xh^ ^T*b1{]@2}3eܽr1MzhMw:nv,Y|þI݌Z}D^vXMOOϟL,YF.[2lxJv_|(\j"!=[\^ֱB,S(Bm/v -p@ߧ- !{=R'}WxĥlzֻAG0$CCVkDqNѣhW+R2;#żvRtرJѳ-_im .=F@\}$sXhAic!+3==]*JX1evY~+8F㼚#[}{'U' .jqtgKcRj+;cXȜGNp@?-%l͙_fff&[R4?[e{6OK@\ֻ37;XZݲ|vjýgoChSSSI]ܹ3Uh/I_.8 /s3 ҞIkQl*o. ^( {P/Z&ەJ%[yo˟tYٜt\H/\pe@V!R(ґg]帷b8;;h4/N:=spP.ӿ]Hfueб*ڶ/jyQTul:datFGuڜrgggCP~YZKp~l;ln1fb1ZVxl.\.^9v6=Cs#9O6_L$*Jr}'9J:bcǎ}w(Jicz^Fk{>0I@cػ1a=cƲF }o&%}Zٳ2gWpS<ɐlNcep@y!h6 .Jz}]XcPHG2|a|||xxxe;gFnjjݍ|jeWZ>e*GNgg[n* !xݛlb7 1${-t K ZVZYV(k1 %Bٓ/9g w=>>}WGpn;dcp[o@@?.ӥ0%@V.s% %|~yϺn]ʇ2BX?oty7\CC簳lե̫<`ZNo!iwK|+v3Ow,ZtJ44J28n86vgk4[pzɞm[됝-[, >O?z @?t6K[|+v3پdWc6\aMLL}᨝;wɔ_iKjg%%#\^pG\dz.BUtLqK47A\ 1gΓ:`0Zy5m]ο&W; kرciT>_|vYV^xvv{e8ߗ>tղ6E.Ycw&&&]+[ဖ`Z]֤={1;،rɎmYB!Xr[(0==^wQǓ<``Z9ܳW`{*$)Ԝ,ryYSu%iZ= n_records: break _validate_file_not_empty(has_data) BooleanSeriesDirectoryFormat = model.SingleFileDirectoryFormat( 'BooleanSeriesDirectoryFormat', 'outliers.tsv', BooleanSeriesFormat) # This is effectively an internal format - it isn't registered with the # plugin, but rather used as part of a dir fmt. This format also exists # in q2-feature-classifier. class PickleFormat(model.BinaryFileFormat): def _validate_(self, level): if not tarfile.is_tarfile(str(self)): raise ValidationError( "Unable to load pickled file (not a tar file).") # https://github.com/qiime2/q2-types/issues/49 # This is effectively an internal format - it isn't registered with the # plugin, but rather used as part of a dir fmt. This format also exists # in q2-feature-classifier. class JSONFormat(model.TextFileFormat): def _validate_(self, level): with self.open() as fh: try: json.load(fh) except json.JSONDecodeError as e: raise ValidationError(e) class SampleEstimatorDirFmt(model.DirectoryFormat): version_info = model.File('sklearn_version.json', format=JSONFormat) sklearn_pipeline = model.File('sklearn_pipeline.tar', format=PickleFormat) class PredictionsFormat(model.TextFileFormat): def _validate(self, n_records=None): with self.open() as fh: # validate header # for now we will not validate any information in the header, # since the name of the predicted column should be flexible. The # header name written by methods in q2-sample-classifier will be # "predicted-*", but this should also accommodate user-defined # column names. line = fh.readline() # validate body has_data = False for line_number, line in enumerate(fh, start=2): # we want to strip each cell, not the original line # otherwise empty cells are dropped, causing a TypeError cells = [c.strip() for c in line.split('\t')] _validate_record_len(cells, line_number, 2) has_data = True if n_records is not None and (line_number - 1) >= n_records: break _validate_file_not_empty(has_data) def _validate_(self, level): record_count_map = {'min': 5, 'max': None} self._validate(record_count_map[level]) PredictionsDirectoryFormat = model.SingleFileDirectoryFormat( 'PredictionsDirectoryFormat', 'predictions.tsv', PredictionsFormat) class _MultiColumnNumericFormat(model.TextFileFormat): def _validate(self, n_records=None): with self.open() as fh: # validate header # for now we will not validate any information in the header, # since column names, count etc are frequently unique to individual # estimators. Let's keep this flexible. line = fh.readline() # validate body has_data = False for line_number, line in enumerate(fh, start=2): # we want to strip each cell, not the original line # otherwise empty cells are dropped, causing a TypeError cells = [c.strip() for c in line.split('\t')] if len(cells) < 2: raise ValidationError( "Expected data record to be TSV with two or more " "fields. Detected {0} fields at line {1}:\n\n{2!r}" .format(len(cells), line_number, cells)) # all values (except row name) should be numbers try: [float(c) for c in cells[1:]] except ValueError: raise ValidationError( "Columns must contain only numeric values. " "A non-numeric value ({0!r}) was detected at line " "{1}.".format(cells[1], line_number)) has_data = True if n_records is not None and (line_number - 1) >= n_records: break _validate_file_not_empty(has_data) def _validate_(self, level): record_count_map = {'min': 5, 'max': None} self._validate(record_count_map[level]) class ImportanceFormat(_MultiColumnNumericFormat): pass ImportanceDirectoryFormat = model.SingleFileDirectoryFormat( 'ImportanceDirectoryFormat', 'importance.tsv', ImportanceFormat) class ProbabilitiesFormat(_MultiColumnNumericFormat): pass ProbabilitiesDirectoryFormat = model.SingleFileDirectoryFormat( 'ProbabilitiesDirectoryFormat', 'class_probabilities.tsv', ProbabilitiesFormat) TrueTargetsDirectoryFormat = model.SingleFileDirectoryFormat( 'TrueTargetsDirectoryFormat', 'true_targets.tsv', PredictionsFormat) q2-sample-classifier-2024.5.0/q2_sample_classifier/_transformer.py000066400000000000000000000137531462552620600250520ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import os import tarfile import json import pandas as pd import numpy as np import qiime2 import qiime2.plugin.model as model import sklearn import joblib from sklearn.pipeline import Pipeline from .plugin_setup import plugin from ._format import (SampleEstimatorDirFmt, JSONFormat, BooleanSeriesFormat, ImportanceFormat, PredictionsFormat, PickleFormat, ProbabilitiesFormat) def _read_dataframe(fh): # Using `dtype=object` and `set_index` to avoid type casting/inference # of any columns or the index. df = pd.read_csv(fh, sep='\t', header=0, dtype='str') df.set_index(df.columns[0], drop=True, append=False, inplace=True) df.index.name = 'id' return df @plugin.register_transformer def _1(data: pd.Series) -> (BooleanSeriesFormat): ff = BooleanSeriesFormat() with ff.open() as fh: data.to_csv(fh, sep='\t', header=True) return ff @plugin.register_transformer def _2(ff: BooleanSeriesFormat) -> (pd.Series): with ff.open() as fh: df = _read_dataframe(fh) return df.iloc[:, 0] @plugin.register_transformer def _3(ff: BooleanSeriesFormat) -> (qiime2.Metadata): with ff.open() as fh: return qiime2.Metadata(_read_dataframe(fh)) @plugin.register_transformer def _4(data: pd.Series) -> (PredictionsFormat): ff = PredictionsFormat() with ff.open() as fh: data.to_csv(fh, sep='\t', header=True) return ff @plugin.register_transformer def _5(ff: PredictionsFormat) -> (pd.Series): with ff.open() as fh: df = _read_dataframe(fh) return pd.to_numeric(df.iloc[:, 0], errors='ignore') @plugin.register_transformer def _6(ff: PredictionsFormat) -> (qiime2.Metadata): with ff.open() as fh: return qiime2.Metadata(_read_dataframe(fh).apply( lambda x: pd.to_numeric(x, errors='ignore'))) @plugin.register_transformer def _7(data: pd.DataFrame) -> (ImportanceFormat): ff = ImportanceFormat() with ff.open() as fh: data.to_csv(fh, sep='\t', header=True, na_rep=np.nan) return ff @plugin.register_transformer def _8(ff: ImportanceFormat) -> (pd.DataFrame): with ff.open() as fh: return _read_dataframe(fh).apply( lambda x: pd.to_numeric(x, errors='raise')) @plugin.register_transformer def _9(ff: ImportanceFormat) -> (qiime2.Metadata): with ff.open() as fh: return qiime2.Metadata(_read_dataframe(fh).apply( lambda x: pd.to_numeric(x, errors='raise'))) @plugin.register_transformer def _10(data: pd.DataFrame) -> (ProbabilitiesFormat): ff = ProbabilitiesFormat() with ff.open() as fh: data.to_csv(fh, sep='\t', na_rep=np.nan, header=True) return ff @plugin.register_transformer def _11(ff: ProbabilitiesFormat) -> (pd.DataFrame): with ff.open() as fh: return _read_dataframe(fh).apply( lambda x: pd.to_numeric(x, errors='raise')) @plugin.register_transformer def _12(ff: ProbabilitiesFormat) -> (qiime2.Metadata): with ff.open() as fh: return qiime2.Metadata(_read_dataframe(fh).apply( lambda x: pd.to_numeric(x, errors='raise'))) @plugin.register_transformer def _a(dirfmt: SampleEstimatorDirFmt) -> Pipeline: sklearn_version = dirfmt.version_info.view(dict)['sklearn-version'] if sklearn_version != sklearn.__version__: raise ValueError('The scikit-learn version (%s) used to generate this' ' artifact does not match the current version' ' of scikit-learn installed (%s). Please retrain your' ' classifier for your current deployment to prevent' ' data-corruption errors.' % (sklearn_version, sklearn.__version__)) sklearn_pipeline = dirfmt.sklearn_pipeline.view(PickleFormat) with tarfile.open(str(sklearn_pipeline)) as tar: tmpdir = model.DirectoryFormat() dirname = str(tmpdir) def is_within_directory(directory, target): abs_directory = os.path.abspath(directory) abs_target = os.path.abspath(target) prefix = os.path.commonprefix([abs_directory, abs_target]) return prefix == abs_directory def safe_extract(tar, path=".", members=None, *, numeric_owner=False): for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): raise Exception("Attempted Path Traversal in Tar File") tar.extractall(path, members, numeric_owner=numeric_owner) safe_extract(tar, dirname) pipeline = joblib.load(os.path.join(dirname, 'sklearn_pipeline.pkl')) for fn in tar.getnames(): os.unlink(os.path.join(dirname, fn)) return pipeline @plugin.register_transformer def _b(data: Pipeline) -> SampleEstimatorDirFmt: sklearn_pipeline = PickleFormat() with tarfile.open(str(sklearn_pipeline), 'w') as tar: tmpdir = model.DirectoryFormat() pf = os.path.join(str(tmpdir), 'sklearn_pipeline.pkl') for fn in joblib.dump(data, pf): tar.add(fn, os.path.basename(fn)) os.unlink(fn) dirfmt = SampleEstimatorDirFmt() dirfmt.version_info.write_data( {'sklearn-version': sklearn.__version__}, dict) dirfmt.sklearn_pipeline.write_data(sklearn_pipeline, PickleFormat) return dirfmt @plugin.register_transformer def _d(fmt: JSONFormat) -> dict: with fmt.open() as fh: return json.load(fh) @plugin.register_transformer def _e(data: dict) -> JSONFormat: result = JSONFormat() with result.open() as fh: json.dump(data, fh) return result q2-sample-classifier-2024.5.0/q2_sample_classifier/_type.py000066400000000000000000000023701462552620600234620ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- from qiime2.plugin import SemanticType from q2_types.sample_data import SampleData from q2_types.feature_data import FeatureData ClassifierPredictions = SemanticType( 'ClassifierPredictions', variant_of=SampleData.field['type']) RegressorPredictions = SemanticType( 'RegressorPredictions', variant_of=SampleData.field['type']) SampleEstimator = SemanticType('SampleEstimator', field_names='type') Classifier = SemanticType( 'Classifier', variant_of=SampleEstimator.field['type']) Regressor = SemanticType( 'Regressor', variant_of=SampleEstimator.field['type']) BooleanSeries = SemanticType( 'BooleanSeries', variant_of=SampleData.field['type']) Importance = SemanticType( 'Importance', variant_of=FeatureData.field['type']) Probabilities = SemanticType( 'Probabilities', variant_of=SampleData.field['type']) TrueTargets = SemanticType( 'TrueTargets', variant_of=SampleData.field['type']) q2-sample-classifier-2024.5.0/q2_sample_classifier/_version.py000066400000000000000000000441551462552620600241750ustar00rootroot00000000000000 # This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build # directories (produced by setup.py build) will contain a much shorter file # that just contains the computed version number. # This file is released into the public domain. Generated by # versioneer-0.18 (https://github.com/warner/python-versioneer) """Git implementation of _version.py.""" import errno import os import re import subprocess import sys def get_keywords(): """Get the keywords needed to look up the version information.""" # these strings will be replaced by git during git-archive. # setup.py/versioneer.py will grep for the variable names, so they must # each be defined on a line of their own. _version.py will just call # get_keywords(). git_refnames = " (tag: 2024.5.0, Release-2024.5)" git_full = "8fa3c948c14a8ff6668d92fa7cb05364679efc8f" git_date = "2024-05-29 04:18:14 +0000" keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} return keywords class VersioneerConfig: """Container for Versioneer configuration parameters.""" def get_config(): """Create, populate and return the VersioneerConfig() object.""" # these strings are filled in when 'setup.py versioneer' creates # _version.py cfg = VersioneerConfig() cfg.VCS = "git" cfg.style = "pep440" cfg.tag_prefix = "" cfg.parentdir_prefix = "q2-sample-classifier-" cfg.versionfile_source = "q2_sample_classifier/_version.py" cfg.verbose = False return cfg class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" LONG_VERSION_PY = {} HANDLERS = {} def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f return decorate def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None for c in commands: try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git p = subprocess.Popen([c] + args, cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=(subprocess.PIPE if hide_stderr else None)) break except EnvironmentError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue if verbose: print("unable to run %s" % dispcmd) print(e) return None, None else: if verbose: print("unable to find command, tried %s" % (commands,)) return None, None stdout = p.communicate()[0].strip() if sys.version_info[0] >= 3: stdout = stdout.decode() if p.returncode != 0: if verbose: print("unable to run %s (error)" % dispcmd) print("stdout was %s" % stdout) return None, p.returncode return stdout, p.returncode def versions_from_parentdir(parentdir_prefix, root, verbose): """Try to determine the version from the parent directory name. Source tarballs conventionally unpack into a directory that includes both the project name and a version string. We will also support searching up two directory levels for an appropriately named parent directory """ rootdirs = [] for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: print("Tried directories %s but none started with prefix %s" % (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @register_vcs_handler("git", "get_keywords") def git_get_keywords(versionfile_abs): """Extract version information from the given file.""" # the code embedded in _version.py can just fetch the value of these # keywords. When used from setup.py, we don't want to import _version.py, # so we do it with a regexp instead. This function is not used from # _version.py. keywords = {} try: f = open(versionfile_abs, "r") for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["refnames"] = mo.group(1) if line.strip().startswith("git_full ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["full"] = mo.group(1) if line.strip().startswith("git_date ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["date"] = mo.group(1) f.close() except EnvironmentError: pass return keywords @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" if not keywords: raise NotThisMethod("no keywords at all, weird") date = keywords.get("date") if date is not None: # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because # it's been around since git-1.5.3, and it's too difficult to # discover which version we're using, or to work around using an # older one. date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) refnames = keywords["refnames"].strip() if refnames.startswith("$Format"): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") refs = set([r.strip() for r in refnames.strip("()").split(",")]) # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d # expansion behaves like git log --decorate=short and strips out the # refs/heads/ and refs/tags/ prefixes that would let us distinguish # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". tags = set([r for r in refs if re.search(r'\d', r)]) if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: print("likely tags: %s" % ",".join(sorted(tags))) for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] if verbose: print("picking %s" % r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") return {"version": "0+unknown", "full-revisionid": keywords["full"].strip(), "dirty": False, "error": "no suitable tags", "date": None} @register_vcs_handler("git", "pieces_from_vcs") def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* expanded, and _version.py hasn't already been rewritten with a short version string, meaning we're inside a checked out source tree. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) raise NotThisMethod("'git rev-parse --git-dir' returned error") # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%s*" % tag_prefix], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() pieces = {} pieces["long"] = full_out pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out # look for -dirty suffix dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: git_describe = git_describe[:git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%s'" % describe_out) return pieces # tag full_tag = mo.group(1) if not full_tag.startswith(tag_prefix): if verbose: fmt = "tag '%s' doesn't start with prefix '%s'" print(fmt % (full_tag, tag_prefix)) pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" % (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag[len(tag_prefix):] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) # commit: short hex revision ID pieces["short"] = mo.group(3) else: # HEX: no tags pieces["closest-tag"] = None count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces def plus_or_dot(pieces): """Return a + if we don't already have one, else return a .""" if "+" in pieces.get("closest-tag", ""): return "." return "+" def render_pep440(pieces): """Build up version string, with post-release "local version identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty Exceptions: 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += plus_or_dot(pieces) rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" else: # exception #1 rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered def render_pep440_pre(pieces): """TAG[.post.devDISTANCE] -- No -dirty. Exceptions: 1: no tags. 0.post.devDISTANCE """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += ".post.dev%d" % pieces["distance"] else: # exception #1 rendered = "0.post.dev%d" % pieces["distance"] return rendered def render_pep440_post(pieces): """TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that .dev0 sorts backwards (a dirty tree will appear "older" than the corresponding clean one), but you shouldn't be releasing software with -dirty anyways. Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += plus_or_dot(pieces) rendered += "g%s" % pieces["short"] else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += "+g%s" % pieces["short"] return rendered def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. Eexceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" return rendered def render_git_describe(pieces): """TAG[-DISTANCE-gHEX][-dirty]. Like 'git describe --tags --dirty --always'. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render_git_describe_long(pieces): """TAG-DISTANCE-gHEX[-dirty]. Like 'git describe --tags --dirty --always -long'. The distance/hash is unconditional. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: return {"version": "unknown", "full-revisionid": pieces.get("long"), "dirty": None, "error": pieces["error"], "date": None} if not style or style == "default": style = "pep440" # the default if style == "pep440": rendered = render_pep440(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": rendered = render_git_describe(pieces) elif style == "git-describe-long": rendered = render_git_describe_long(pieces) else: raise ValueError("unknown style '%s'" % style) return {"version": rendered, "full-revisionid": pieces["long"], "dirty": pieces["dirty"], "error": None, "date": pieces.get("date")} def get_versions(): """Get version information or return default if unable to do so.""" # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have # __file__, we can work backwards from there to the root. Some # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which # case we can only use expanded keywords. cfg = get_config() verbose = cfg.verbose try: return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, verbose) except NotThisMethod: pass try: root = os.path.realpath(__file__) # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. for i in cfg.versionfile_source.split('/'): root = os.path.dirname(root) except NameError: return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to find root of source tree", "date": None} try: pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) return render(pieces, cfg.style) except NotThisMethod: pass try: if cfg.parentdir_prefix: return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) except NotThisMethod: pass return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to compute version", "date": None} q2-sample-classifier-2024.5.0/q2_sample_classifier/assets/000077500000000000000000000000001462552620600232705ustar00rootroot00000000000000q2-sample-classifier-2024.5.0/q2_sample_classifier/assets/index.html000066400000000000000000000066101462552620600252700ustar00rootroot00000000000000{% extends 'base.html' %} {% block title %}q2-sample-classifier : {{ title }}{% endblock %} {% block fixed %}{% endblock %} {% block content %} {% if warning_msg %} {% endif %}
{% if predictions %}

Model Accuracy

{% endif %}
{% if predictions %}

Download as PDF

{% endif %} {% if predictions %} {% endif %} {% if roc %}

Receiver Operating Characteristic Curves


Download as PDF

Receiver Operating Characteristic (ROC) curves are a graphical representation of the classification accuracy of a machine-learning model. The ROC curve plots the relationship between the true positive rate (TPR, on the y-axis) and the false positive rate (FPR, on the x-axis) at various threshold settings. Thus, the top-left corner of the plot represents the "optimal" performance position, indicating a FPR of zero and a TPR of one. This "optimal" scenario is unlikely to occur in practice, but a greater area under the curve (AUC) indicates better performance. This can be compared to the error rate achieved by random chance, which is represented here as a diagonal line extending from the lower-left to upper-right corners. Additionally, the "steepness" of the curve is important, as a good classifier should maximize the TPR while minimizing the FPR. In addition to showing the ROC curves for each class, average ROCs and AUCs are calculated. "Micro-averaging" calculates metrics globally by averaging across each sample; hence class imbalance impacts this metric. "Macro-averaging" is another average metric, which gives equal weight to the classification of each sample.

{% endif %} {% if optimize_feature_selection %}

Recursive feature extraction

{% endif %} {% if result %}

Model parameters

{{ result }}
{% endif %}
{% endblock %} q2-sample-classifier-2024.5.0/q2_sample_classifier/citations.bib000066400000000000000000000017101462552620600244400ustar00rootroot00000000000000@article {Bokulich306167, author = {Bokulich, Nicholas and Dillon, Matthew and Bolyen, Evan and Kaehler, Benjamin D and Huttley, Gavin A and Caporaso, J Gregory}, title = {{q2-sample-classifier}: machine-learning tools for microbiome classification and regression}, year = {2018}, doi = {10.21105/joss.00934}, journal = {Journal of Open Source Software}, volume={3}, number={30}, pages={934} } @article{pedregosa2011scikit, title={Scikit-learn: Machine learning in Python}, author={Pedregosa, Fabian and Varoquaux, Ga{\"e}l and Gramfort, Alexandre and Michel, Vincent and Thirion, Bertrand and Grisel, Olivier and Blondel, Mathieu and Prettenhofer, Peter and Weiss, Ron and Dubourg, Vincent and Vanderplas, Jake and Passos, Alexandre and Cournapeau, David and Brucher, Matthieu and Perrot, Matthieu and Duchesnay, {\'E}douard}, journal={Journal of machine learning research}, volume={12}, number={Oct}, pages={2825--2830}, year={2011} } q2-sample-classifier-2024.5.0/q2_sample_classifier/classify.py000066400000000000000000000513451462552620600241650ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import numpy as np from sklearn.ensemble import IsolationForest from sklearn.metrics import mean_squared_error, accuracy_score from sklearn.feature_extraction import DictVectorizer from sklearn.model_selection import KFold from sklearn.neighbors import KNeighborsClassifier from sklearn.pipeline import Pipeline import qiime2 from qiime2.plugin import get_available_cores import pandas as pd import biom import skbio from .utilities import (_load_data, _prepare_training_data, nested_cross_validation, _fit_estimator, _extract_features, _plot_accuracy, _summarize_estimator, predict_probabilities, _classifiers) defaults = { 'test_size': 0.2, 'step': 0.05, 'cv': 5, 'n_jobs': 1, 'n_estimators': 100, 'estimator_c': 'RandomForestClassifier', 'estimator_r': 'RandomForestRegressor', 'palette': 'sirocco', 'missing_samples': 'error' } def metatable(ctx, metadata, table=None, missing_samples='ignore', missing_values='error', drop_all_unique=False): # gather numeric metadata metadata = metadata.filter_columns( column_type='numeric', drop_all_unique=drop_all_unique, drop_zero_variance=True, drop_all_missing=True).to_dataframe() if missing_values == 'drop_samples': metadata = metadata.dropna(axis=0) elif missing_values == 'drop_features': metadata = metadata.dropna(axis=1) elif missing_values == 'error' and metadata.isnull().values.any(): raise ValueError('You are attempting to coerce metadata containing ' 'missing values into a feature table! These may ' 'cause fatal errors downstream and must be removed ' 'or converted to 0. See the missing_values parameter ' 'to review your options.') elif missing_values == 'fill': metadata = metadata.fillna(0.) # drop columns with negative values # grab column IDs with all values >= 0 metadata = metadata.loc[:, (metadata >= 0).all(axis=0)] if len(metadata.columns) == 0: raise ValueError('All metadata columns have been filtered.') if len(metadata.index) == 0: raise ValueError('All metadata samples have been filtered.') # only retain IDs that intersect with table if table is not None: tab = table.view(biom.Table) table_ids = set(tab.ids()) metadata_ids = set(metadata.index) sample_ids = table_ids.intersection(metadata_ids) if missing_samples == 'error' and len(sample_ids) != len(table_ids): raise ValueError('Missing samples in metadata: %r' % table_ids.difference(metadata_ids)) else: metadata = metadata.loc[list(sample_ids)] if len(sample_ids) < len(table_ids): tab = tab.filter( ids_to_keep=sample_ids, axis='sample', inplace=False) table = ctx.make_artifact('FeatureTable[Frequency]', tab) # convert to FeatureTable[Frequency] metadata = metadata.T metadata = biom.table.Table( metadata.values, metadata.index, metadata.columns) metatab = ctx.make_artifact('FeatureTable[Frequency]', metadata) # optionally merge with existing feature table if table is not None: merge = ctx.get_action('feature_table', 'merge') metatab, = merge( [table, metatab], overlap_method='error_on_overlapping_feature') return metatab def _fit_predict_knn_cv( x: pd.DataFrame, y: pd.Series, k: int, cv: int, random_state: int, n_jobs: int ) -> (pd.Series, pd.Series): if n_jobs == 0: n_jobs = get_available_cores() kf = KFold(n_splits=cv, shuffle=True, random_state=random_state) # train and test with CV predictions, pred_ids, truth = [], [], [] for train_index, test_index in kf.split(x): x_train, x_test = x.iloc[train_index, train_index], \ x.iloc[test_index, train_index] y_train, y_test = y[train_index], y[test_index] knn = KNeighborsClassifier( n_neighbors=k, metric='precomputed', n_jobs=n_jobs ) knn.fit(x_train, y_train) # gather predictions for the confusion matrix predictions.append(knn.predict(x_test)) pred_ids.extend(x_test.index.tolist()) truth.append(y_test) predictions = pd.Series( np.concatenate(predictions).ravel(), index=pd.Index(pred_ids, name='SampleID') ) truth = pd.concat(truth) truth.index.name = 'SampleID' return predictions, truth def classify_samples_from_dist( ctx, distance_matrix, metadata, k=1, cv=defaults['cv'], random_state=None, n_jobs=defaults['n_jobs'], palette=defaults['palette'] ): """ Trains and evaluates a KNN classifier from a distance matrix using cross-validation.""" distance_matrix = distance_matrix \ .view(skbio.DistanceMatrix) \ .to_data_frame() # reorder (required for splitting into train/test) metadata_ser = metadata.to_series()[distance_matrix.index] predictions, truth = _fit_predict_knn_cv( distance_matrix, metadata_ser, k, cv, random_state, n_jobs ) predictions = qiime2.Artifact.import_data( 'SampleData[ClassifierPredictions]', predictions ) truth = qiime2.CategoricalMetadataColumn(truth) confusion = ctx.get_action('sample_classifier', 'confusion_matrix') accuracy_results, = confusion( predictions, truth, missing_samples='ignore', palette=palette ) return predictions, accuracy_results def classify_samples(ctx, table, metadata, test_size=defaults['test_size'], step=defaults['step'], cv=defaults['cv'], random_state=None, n_jobs=defaults['n_jobs'], n_estimators=defaults['n_estimators'], estimator=defaults['estimator_c'], optimize_feature_selection=False, parameter_tuning=False, palette=defaults['palette'], missing_samples=defaults['missing_samples']): split = ctx.get_action('sample_classifier', 'split_table') fit = ctx.get_action('sample_classifier', 'fit_classifier') predict_test = ctx.get_action( 'sample_classifier', 'predict_classification') summarize_estimator = ctx.get_action('sample_classifier', 'summarize') confusion = ctx.get_action('sample_classifier', 'confusion_matrix') heat = ctx.get_action('sample_classifier', 'heatmap') X_train, X_test, y_train, y_test = split(table, metadata, test_size, random_state, stratify=True, missing_samples=missing_samples) sample_estimator, importance = fit( X_train, metadata, step, cv, random_state, n_jobs, n_estimators, estimator, optimize_feature_selection, parameter_tuning, missing_samples='ignore') predictions, probabilities, = predict_test( X_test, sample_estimator, n_jobs) summary, = summarize_estimator(sample_estimator) accuracy_results, = confusion(predictions, metadata, probabilities, missing_samples='ignore', palette=palette) _heatmap, _ = heat(table, importance, sample_metadata=metadata, group_samples=True, missing_samples=missing_samples) return (sample_estimator, importance, predictions, summary, accuracy_results, probabilities, _heatmap, y_train, y_test) def regress_samples(ctx, table, metadata, test_size=defaults['test_size'], step=defaults['step'], cv=defaults['cv'], random_state=None, n_jobs=defaults['n_jobs'], n_estimators=defaults['n_estimators'], estimator=defaults['estimator_r'], optimize_feature_selection=False, stratify=False, parameter_tuning=False, missing_samples=defaults['missing_samples']): split = ctx.get_action('sample_classifier', 'split_table') fit = ctx.get_action('sample_classifier', 'fit_regressor') predict_test = ctx.get_action('sample_classifier', 'predict_regression') summarize_estimator = ctx.get_action('sample_classifier', 'summarize') scatter = ctx.get_action('sample_classifier', 'scatterplot') X_train, X_test, y_train, y_test = split(table, metadata, test_size, random_state, stratify, missing_samples=missing_samples) sample_estimator, importance = fit( X_train, metadata, step, cv, random_state, n_jobs, n_estimators, estimator, optimize_feature_selection, parameter_tuning, missing_samples='ignore') predictions, = predict_test(X_test, sample_estimator, n_jobs) summary, = summarize_estimator(sample_estimator) accuracy_results, = scatter(predictions, metadata, 'ignore') return (sample_estimator, importance, predictions, summary, accuracy_results) def fit_classifier(table: biom.Table, metadata: qiime2.CategoricalMetadataColumn, step: float = defaults['step'], cv: int = defaults['cv'], random_state: int = None, n_jobs: int = defaults['n_jobs'], n_estimators: int = defaults['n_estimators'], estimator: str = defaults['estimator_c'], optimize_feature_selection: bool = False, parameter_tuning: bool = False, missing_samples: str = defaults['missing_samples'] ) -> (Pipeline, pd.DataFrame): estimator, importance = _fit_estimator( table, metadata, estimator, n_estimators, step, cv, random_state, n_jobs, optimize_feature_selection, parameter_tuning, missing_samples=missing_samples, classification=True) return estimator, importance def fit_regressor(table: biom.Table, metadata: qiime2.CategoricalMetadataColumn, step: float = defaults['step'], cv: int = defaults['cv'], random_state: int = None, n_jobs: int = defaults['n_jobs'], n_estimators: int = defaults['n_estimators'], estimator: str = defaults['estimator_r'], optimize_feature_selection: bool = False, parameter_tuning: bool = False, missing_samples: str = defaults['missing_samples'] ) -> (Pipeline, pd.DataFrame): estimator, importance = _fit_estimator( table, metadata, estimator, n_estimators, step, cv, random_state, n_jobs, optimize_feature_selection, parameter_tuning, missing_samples=missing_samples, classification=False) return estimator, importance def predict_base(table, sample_estimator, n_jobs): if n_jobs == 0: n_jobs = get_available_cores() # extract feature data from biom feature_data = _extract_features(table) index = table.ids() # reset n_jobs if this is a valid parameter for the estimator if 'est__n_jobs' in sample_estimator.get_params().keys(): sample_estimator.set_params(est__n_jobs=n_jobs) # predict values and output as series y_pred = sample_estimator.predict(feature_data) # need to flatten arrays that come out as multidimensional y_pred = y_pred.flatten() y_pred = pd.Series(y_pred, index=index, name='prediction') y_pred.index.name = 'SampleID' # log prediction probabilities (classifiers only) if sample_estimator.named_steps.est.__class__.__name__ in _classifiers: probs = predict_probabilities(sample_estimator, feature_data, index) else: probs = None return y_pred, probs def predict_classification(table: biom.Table, sample_estimator: Pipeline, n_jobs: int = defaults['n_jobs']) -> ( pd.Series, pd.DataFrame): return predict_base(table, sample_estimator, n_jobs) def predict_regression(table: biom.Table, sample_estimator: Pipeline, n_jobs: int = defaults['n_jobs']) -> pd.Series: # we only return the predictions, not the probabilities, which are empty # for regressors. return predict_base(table, sample_estimator, n_jobs)[0] def split_table(table: biom.Table, metadata: qiime2.MetadataColumn, test_size: float = defaults['test_size'], random_state: int = None, stratify: str = True, missing_samples: str = defaults['missing_samples'] ) -> (biom.Table, biom.Table, pd.Series, pd.Series): column = metadata.name X_train, X_test, y_train, y_test = _prepare_training_data( table, metadata, column, test_size, random_state, load_data=True, stratify=stratify, missing_samples=missing_samples) return X_train, X_test, y_train, y_test def regress_samples_ncv( table: biom.Table, metadata: qiime2.NumericMetadataColumn, cv: int = defaults['cv'], random_state: int = None, n_jobs: int = defaults['n_jobs'], n_estimators: int = defaults['n_estimators'], estimator: str = defaults['estimator_r'], stratify: str = False, parameter_tuning: bool = False, missing_samples: str = defaults['missing_samples'] ) -> (pd.Series, pd.DataFrame): y_pred, importances, probabilities = nested_cross_validation( table, metadata, cv, random_state, n_jobs, n_estimators, estimator, stratify, parameter_tuning, classification=False, scoring=mean_squared_error, missing_samples=missing_samples) return y_pred, importances def classify_samples_ncv( table: biom.Table, metadata: qiime2.CategoricalMetadataColumn, cv: int = defaults['cv'], random_state: int = None, n_jobs: int = defaults['n_jobs'], n_estimators: int = defaults['n_estimators'], estimator: str = defaults['estimator_c'], parameter_tuning: bool = False, missing_samples: str = defaults['missing_samples'] ) -> (pd.Series, pd.DataFrame, pd.DataFrame): y_pred, importances, probabilities = nested_cross_validation( table, metadata, cv, random_state, n_jobs, n_estimators, estimator, stratify=True, parameter_tuning=parameter_tuning, classification=False, scoring=accuracy_score, missing_samples=missing_samples) return y_pred, importances, probabilities def scatterplot(output_dir: str, predictions: pd.Series, truth: qiime2.NumericMetadataColumn, missing_samples: str = defaults['missing_samples']) -> None: predictions = pd.to_numeric(predictions) _plot_accuracy(output_dir, predictions, truth, probabilities=None, missing_samples=missing_samples, classification=False, palette=None, plot_title='regression scatterplot') def confusion_matrix(output_dir: str, predictions: pd.Series, truth: qiime2.CategoricalMetadataColumn, probabilities: pd.DataFrame = None, missing_samples: str = defaults['missing_samples'], vmin: int = 'auto', vmax: int = 'auto', palette: str = defaults['palette']) -> None: if vmin == 'auto': vmin = None if vmax == 'auto': vmax = None predictions = predictions.astype(str) _plot_accuracy(output_dir, predictions, truth, probabilities, missing_samples=missing_samples, classification=True, palette=palette, plot_title='confusion matrix', vmin=vmin, vmax=vmax) def summarize(output_dir: str, sample_estimator: Pipeline): _summarize_estimator(output_dir, sample_estimator) def heatmap(ctx, table, importance, sample_metadata=None, feature_metadata=None, feature_count=50, importance_threshold=0, group_samples=False, normalize=True, missing_samples='ignore', metric='braycurtis', method='average', cluster='features', color_scheme='rocket'): filter_features = ctx.get_action('feature_table', 'filter_features') group = ctx.get_action('feature_table', 'group') make_heatmap = ctx.get_action('feature_table', 'heatmap') filter_samples = ctx.get_action('feature_table', 'filter_samples') if group_samples and sample_metadata is None: raise ValueError( 'If group_samples is enabled, sample_metadata are not optional.') if missing_samples == 'ignore' and sample_metadata is None: raise ValueError( 'If missing_samples is ignore, metadata are not optional') clustermap_params = { 'cluster': cluster, 'normalize': normalize, 'metric': metric, 'method': method, 'color_scheme': color_scheme} # load importance data and sum rows (to average importances if there are # multiple scores). importance = importance.view(pd.DataFrame) importance = importance.sum(1) # filter importances by user criteria importance = importance.sort_values(ascending=False) if importance_threshold > 0: importance = importance[importance > importance_threshold] if feature_count > 0: importance = importance[:feature_count] importance.name = 'importance' importance = qiime2.Metadata(importance.to_frame()) # filter features by importance table, = filter_features(table, metadata=importance) if missing_samples == 'ignore': table, = filter_samples( table, metadata=qiime2.Metadata(sample_metadata.to_dataframe())) # optionally group feature table by sample metadata # otherwise annotate heatmap with sample metadata if group_samples: table, = group(table, metadata=sample_metadata, axis='sample', mode='sum') elif sample_metadata is not None: clustermap_params['sample_metadata'] = sample_metadata # label features using feature metadata if feature_metadata is not None: clustermap_params['feature_metadata'] = feature_metadata # make yer heatmap clustermap, = make_heatmap(table, **clustermap_params) return clustermap, table # The following method is experimental and is not registered in the current # release. Any use of the API is at user's own risk. def detect_outliers(table: biom.Table, metadata: qiime2.Metadata, subset_column: str = None, subset_value: str = None, n_estimators: int = defaults['n_estimators'], contamination: float = 0.05, random_state: int = None, n_jobs: int = defaults['n_jobs'], missing_samples: str = 'ignore') -> (pd.Series): features, sample_md = _load_data( table, metadata, missing_samples=missing_samples) # if opting to train on a subset, choose subset that fits criteria if subset_column and subset_value: X_train = \ [f for s, f in zip(sample_md[subset_column] == subset_value, features) if s] # raise error if subset_column or subset_value (but not both) are set elif subset_column is not None or subset_value is not None: raise ValueError(( 'subset_column and subset_value must both be provided with a ' 'valid value to perform model training on a subset of data.')) else: X_train = features # fit isolation tree estimator = Pipeline([('dv', DictVectorizer()), ('est', IsolationForest(n_jobs=n_jobs, n_estimators=n_estimators, contamination=contamination, random_state=random_state, ))]) estimator.fit(X_train) # predict outlier status y_pred = estimator.predict(features) y_pred = pd.Series(y_pred, index=sample_md.index) # predict reports whether sample is an inlier; change to outlier status y_pred[y_pred == -1] = 'True' y_pred[y_pred == 1] = 'False' y_pred.name = "outlier" return y_pred q2-sample-classifier-2024.5.0/q2_sample_classifier/plugin_setup.py000066400000000000000000000742361462552620600250720ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import importlib from qiime2.plugin import ( Int, Str, Float, Range, Bool, Plugin, Metadata, Choices, MetadataColumn, Numeric, Categorical, Citations, Visualization, TypeMatch, Threads) from q2_types.feature_table import ( FeatureTable, Frequency, RelativeFrequency, PresenceAbsence, Balance, PercentileNormalized, Design, Composition) from q2_types.sample_data import SampleData from q2_types.feature_data import FeatureData from q2_types.distance_matrix import DistanceMatrix from q2_feature_table import heatmap_choices from .classify import ( classify_samples, classify_samples_from_dist, regress_samples, regress_samples_ncv, classify_samples_ncv, fit_classifier, fit_regressor, split_table, predict_classification, predict_regression, confusion_matrix, scatterplot, summarize, metatable, heatmap) from .visuals import _custom_palettes from ._format import (SampleEstimatorDirFmt, BooleanSeriesFormat, BooleanSeriesDirectoryFormat, ImportanceFormat, ImportanceDirectoryFormat, PredictionsFormat, PredictionsDirectoryFormat, ProbabilitiesFormat, ProbabilitiesDirectoryFormat, TrueTargetsDirectoryFormat) from ._type import (ClassifierPredictions, RegressorPredictions, SampleEstimator, BooleanSeries, Importance, Classifier, Regressor, Probabilities, TrueTargets) import q2_sample_classifier citations = Citations.load('citations.bib', package='q2_sample_classifier') plugin = Plugin( name='sample-classifier', version=q2_sample_classifier.__version__, website="https://github.com/qiime2/q2-sample-classifier", package='q2_sample_classifier', description=( 'This QIIME 2 plugin supports methods for supervised classification ' 'and regression of sample metadata, and other supervised machine ' 'learning methods.'), short_description=( 'Plugin for machine learning prediction of sample metadata.'), citations=[citations['Bokulich306167'], citations['pedregosa2011scikit']] ) description = ('Predicts a {0} sample metadata column using a {1}. Splits ' 'input data into training and test sets. The training set is ' 'used to train and test the estimator using a stratified ' 'k-fold cross-validation scheme. This includes optional steps ' 'for automated feature extraction and hyperparameter ' 'optimization. The test set validates classification accuracy ' 'of the optimized estimator. Outputs classification results ' 'for test set. For more details on the learning algorithm, ' 'see http://scikit-learn.org/stable/supervised_learning.html') ncv_description = ('Predicts a {0} sample metadata column using a {1}. Uses ' 'nested stratified k-fold cross validation for automated ' 'hyperparameter optimization and sample prediction. ' 'Outputs predicted values for each input sample, and ' 'relative importance of each feature for model accuracy.') cv_description = ('Fit a supervised learning {0}. Outputs the fit estimator ' '(for prediction of test samples and/or unknown samples) ' 'and the relative importance of each feature for model ' 'accuracy. Optionally use k-fold cross-validation for ' 'automatic recursive feature elimination and hyperparameter ' 'tuning.') predict_description = ( 'Use trained estimator to predict target values for new samples. ' 'These will typically be unseen samples, e.g., test data (derived ' 'manually or from split_table) or samples with unknown values, but ' 'can theoretically be any samples present in a feature table that ' 'contain overlapping features with the feature table used to train ' 'the estimator.') inputs = {'table': FeatureTable[ Frequency | RelativeFrequency | PresenceAbsence | Composition]} input_descriptions = {'table': 'Feature table containing all features that ' 'should be used for target prediction.', 'probabilities': 'Predicted class probabilities for ' 'each input sample.'} parameters = { 'base': { 'random_state': Int, 'n_jobs': Threads, 'n_estimators': Int % Range(1, None), 'missing_samples': Str % Choices(['error', 'ignore'])}, 'splitter': { 'test_size': Float % Range(0.0, 1.0, inclusive_end=False, inclusive_start=True)}, 'rfe': { 'step': Float % Range(0.0, 1.0, inclusive_end=False, inclusive_start=False), 'optimize_feature_selection': Bool}, 'cv': { 'cv': Int % Range(1, None), 'parameter_tuning': Bool}, 'modified_metadata': { 'metadata': Metadata, 'column': Str}, 'regressor': {'stratify': Bool} } parameter_descriptions = { 'base': {'random_state': 'Seed used by random number generator.', 'n_jobs': 'Number of jobs to run in parallel.', 'n_estimators': ( 'Number of trees to grow for estimation. More trees will ' 'improve predictive accuracy up to a threshold level, ' 'but will also increase time and memory requirements. This ' 'parameter only affects ensemble estimators, such as Random ' 'Forest, AdaBoost, ExtraTrees, and GradientBoosting.'), 'missing_samples': ( 'How to handle missing samples in metadata. "error" will fail ' 'if missing samples are detected. "ignore" will cause the ' 'feature table and metadata to be filtered, so that only ' 'samples found in both files are retained.')}, 'splitter': { 'test_size': ('Fraction of input samples to exclude from training set ' 'and use for classifier testing.')}, 'rfe': { 'step': ('If optimize_feature_selection is True, step is the ' 'percentage of features to remove at each iteration.'), 'optimize_feature_selection': ('Automatically optimize input feature ' 'selection using recursive feature ' 'elimination.')}, 'cv': { 'cv': 'Number of k-fold cross-validations to perform.', 'parameter_tuning': ('Automatically tune hyperparameters using random ' 'grid search.')}, 'regressor': { 'stratify': ('Evenly stratify training and test data among metadata ' 'categories. If True, all values in column must match ' 'at least two samples.')}, 'estimator': { 'estimator': 'Estimator method to use for sample prediction.'} } classifiers = Str % Choices( ['RandomForestClassifier', 'ExtraTreesClassifier', 'GradientBoostingClassifier', 'AdaBoostClassifier[DecisionTree]', 'AdaBoostClassifier[ExtraTrees]', 'KNeighborsClassifier', 'LinearSVC', 'SVC']) regressors = Str % Choices( ['RandomForestRegressor', 'ExtraTreesRegressor', 'GradientBoostingRegressor', 'AdaBoostRegressor[DecisionTree]', 'AdaBoostRegressor[ExtraTrees]', 'ElasticNet', 'Ridge', 'Lasso', 'KNeighborsRegressor', 'LinearSVR', 'SVR']) output_descriptions = { 'predictions': 'Predicted target values for each input sample.', 'feature_importance': 'Importance of each input feature to model accuracy.' } pipeline_parameters = { **parameters['base'], **parameters['rfe'], **parameters['splitter'], **parameters['cv']} classifier_pipeline_parameters = { **pipeline_parameters, 'metadata': MetadataColumn[Categorical], 'estimator': classifiers, 'palette': Str % Choices(_custom_palettes().keys())} regressor_pipeline_parameters = { **pipeline_parameters, 'metadata': MetadataColumn[Numeric], **parameters['regressor'], 'estimator': regressors} pipeline_parameter_descriptions = { **parameter_descriptions['base'], **parameter_descriptions['rfe'], **parameter_descriptions['splitter'], **parameter_descriptions['estimator'], **parameter_descriptions['cv']} classifier_pipeline_parameter_descriptions = { **pipeline_parameter_descriptions, 'metadata': 'Categorical metadata column to use as prediction target.', 'palette': 'The color palette to use for plotting.'} regressor_pipeline_parameter_descriptions = { **pipeline_parameter_descriptions, **parameter_descriptions['regressor'], 'metadata': 'Numeric metadata column to use as prediction target.'} pipeline_outputs = [ ('model_summary', Visualization), ('accuracy_results', Visualization)] regressor_pipeline_outputs = [ ('sample_estimator', SampleEstimator[Regressor]), ('feature_importance', FeatureData[Importance]), ('predictions', SampleData[RegressorPredictions])] + pipeline_outputs pipeline_output_descriptions = { 'sample_estimator': 'Trained sample estimator.', **output_descriptions, 'model_summary': 'Summarized parameter and (if enabled) feature ' 'selection information for the trained estimator.', 'accuracy_results': 'Accuracy results visualization.'} plugin.pipelines.register_function( function=classify_samples, inputs=inputs, parameters=classifier_pipeline_parameters, outputs=[('sample_estimator', SampleEstimator[Classifier]), ('feature_importance', FeatureData[Importance]), ('predictions', SampleData[ClassifierPredictions]) ] + pipeline_outputs + [ ('probabilities', SampleData[Probabilities]), ('heatmap', Visualization), ('training_targets', SampleData[TrueTargets]), ('test_targets', SampleData[TrueTargets])], input_descriptions={'table': input_descriptions['table']}, parameter_descriptions=classifier_pipeline_parameter_descriptions, output_descriptions={ **pipeline_output_descriptions, 'probabilities': input_descriptions['probabilities'], 'heatmap': 'A heatmap of the top 50 most important features from the ' 'table.', 'training_targets': 'Series containing true target values of ' 'train samples', 'test_targets': 'Series containing true target values ' 'of test samples'}, name='Train and test a cross-validated supervised learning classifier.', description=description.format( 'categorical', 'supervised learning classifier') ) plugin.pipelines.register_function( function=classify_samples_from_dist, inputs={'distance_matrix': DistanceMatrix}, parameters={ 'metadata': MetadataColumn[Categorical], 'k': Int, 'cv': parameters['cv']['cv'], 'random_state': parameters['base']['random_state'], 'n_jobs': parameters['base']['n_jobs'], 'palette': Str % Choices(_custom_palettes().keys()), }, outputs=[ ('predictions', SampleData[ClassifierPredictions]), ('accuracy_results', Visualization), ], input_descriptions={'distance_matrix': 'a distance matrix'}, parameter_descriptions={ 'metadata': 'Categorical metadata column to use as prediction target.', 'k': 'Number of nearest neighbors', 'cv': parameter_descriptions['cv']['cv'], 'random_state': parameter_descriptions['base']['random_state'], 'n_jobs': parameter_descriptions['base']['n_jobs'], 'palette': 'The color palette to use for plotting.', }, output_descriptions={ 'predictions': 'leave one out predictions for each sample', 'accuracy_results': 'Accuracy results visualization.', }, name=('Run k-nearest-neighbors on a labeled distance matrix.'), description=( 'Run k-nearest-neighbors on a labeled distance matrix.' ' Return cross-validated (leave one out) predictions and ' ' accuracy. k = 1 by default' ) ) plugin.pipelines.register_function( function=regress_samples, inputs=inputs, parameters=regressor_pipeline_parameters, outputs=regressor_pipeline_outputs, input_descriptions={'table': input_descriptions['table']}, parameter_descriptions=regressor_pipeline_parameter_descriptions, output_descriptions=pipeline_output_descriptions, name='Train and test a cross-validated supervised learning regressor.', description=description.format( 'continuous', 'supervised learning regressor') ) plugin.methods.register_function( function=regress_samples_ncv, inputs=inputs, parameters={ **parameters['base'], **parameters['cv'], 'metadata': MetadataColumn[Numeric], **parameters['regressor'], 'estimator': regressors}, outputs=[('predictions', SampleData[RegressorPredictions]), ('feature_importance', FeatureData[Importance])], input_descriptions={'table': input_descriptions['table']}, parameter_descriptions={ **parameter_descriptions['base'], **parameter_descriptions['cv'], **parameter_descriptions['regressor'], 'metadata': 'Numeric metadata column to use as prediction target.', **parameter_descriptions['estimator']}, output_descriptions=output_descriptions, name='Nested cross-validated supervised learning regressor.', description=ncv_description.format( 'continuous', 'supervised learning regressor') ) plugin.methods.register_function( function=classify_samples_ncv, inputs=inputs, parameters={ **parameters['base'], **parameters['cv'], 'metadata': MetadataColumn[Categorical], 'estimator': classifiers}, outputs=[('predictions', SampleData[ClassifierPredictions]), ('feature_importance', FeatureData[Importance]), ('probabilities', SampleData[Probabilities])], input_descriptions={'table': input_descriptions['table']}, parameter_descriptions={ **parameter_descriptions['base'], **parameter_descriptions['cv'], 'metadata': 'Categorical metadata column to use as prediction target.', **parameter_descriptions['estimator']}, output_descriptions={**output_descriptions, 'probabilities': input_descriptions['probabilities']}, name='Nested cross-validated supervised learning classifier.', description=ncv_description.format( 'categorical', 'supervised learning classifier') ) plugin.methods.register_function( function=fit_classifier, inputs=inputs, parameters={ **parameters['base'], **parameters['rfe'], **parameters['cv'], 'metadata': MetadataColumn[Categorical], 'estimator': classifiers}, outputs=[('sample_estimator', SampleEstimator[Classifier]), ('feature_importance', FeatureData[Importance])], input_descriptions={'table': input_descriptions['table']}, parameter_descriptions={ **parameter_descriptions['base'], **parameter_descriptions['rfe'], **parameter_descriptions['cv'], 'metadata': 'Numeric metadata column to use as prediction target.', **parameter_descriptions['estimator']}, output_descriptions={ 'feature_importance': output_descriptions['feature_importance'], 'sample_estimator': 'Trained sample classifier.'}, name='Fit a supervised learning classifier.', description=cv_description.format('classifier') ) plugin.methods.register_function( function=fit_regressor, inputs=inputs, parameters={ **parameters['base'], **parameters['rfe'], **parameters['cv'], 'metadata': MetadataColumn[Numeric], 'estimator': regressors}, outputs=[('sample_estimator', SampleEstimator[Regressor]), ('feature_importance', FeatureData[Importance])], input_descriptions={'table': input_descriptions['table']}, parameter_descriptions={ **parameter_descriptions['base'], **parameter_descriptions['rfe'], **parameter_descriptions['cv'], 'metadata': 'Numeric metadata column to use as prediction target.', **parameter_descriptions['estimator']}, output_descriptions={ 'feature_importance': output_descriptions['feature_importance']}, name='Fit a supervised learning regressor.', description=cv_description.format('regressor') ) plugin.methods.register_function( function=predict_classification, inputs={**inputs, 'sample_estimator': SampleEstimator[Classifier]}, parameters={'n_jobs': parameters['base']['n_jobs']}, outputs=[('predictions', SampleData[ClassifierPredictions]), ('probabilities', SampleData[Probabilities])], input_descriptions={ 'table': input_descriptions['table'], 'sample_estimator': 'Sample classifier trained with fit_classifier.'}, parameter_descriptions={ 'n_jobs': parameter_descriptions['base']['n_jobs']}, output_descriptions={ 'predictions': 'Predicted target values for each input sample.', 'probabilities': input_descriptions['probabilities']}, name='Use trained classifier to predict target values for new samples.', description=predict_description ) plugin.methods.register_function( function=predict_regression, inputs={**inputs, 'sample_estimator': SampleEstimator[Regressor]}, parameters={'n_jobs': parameters['base']['n_jobs']}, outputs=[('predictions', SampleData[RegressorPredictions])], input_descriptions={ 'table': input_descriptions['table'], 'sample_estimator': 'Sample regressor trained with fit_regressor.'}, parameter_descriptions={ 'n_jobs': parameter_descriptions['base']['n_jobs']}, output_descriptions={ 'predictions': 'Predicted target values for each input sample.'}, name='Use trained regressor to predict target values for new samples.', description=predict_description ) plugin.visualizers.register_function( function=scatterplot, inputs={'predictions': SampleData[RegressorPredictions]}, parameters={ 'truth': MetadataColumn[Numeric], 'missing_samples': parameters['base']['missing_samples']}, input_descriptions={'predictions': ( 'Predicted values to plot on y axis. Must be predictions of ' 'numeric data produced by a sample regressor.')}, parameter_descriptions={ 'truth': 'Metadata column (true values) to plot on x axis.', 'missing_samples': parameter_descriptions['base']['missing_samples']}, name='Make 2D scatterplot and linear regression of regressor predictions.', description='Make a 2D scatterplot and linear regression of predicted vs. ' 'true values for a set of samples predicted using a sample ' 'regressor.' ) plugin.visualizers.register_function( function=confusion_matrix, inputs={'predictions': SampleData[ClassifierPredictions], 'probabilities': SampleData[Probabilities]}, parameters={ 'truth': MetadataColumn[Categorical], 'missing_samples': parameters['base']['missing_samples'], 'vmin': Float | Str % Choices(['auto']), 'vmax': Float | Str % Choices(['auto']), 'palette': Str % Choices(_custom_palettes().keys())}, input_descriptions={ 'predictions': 'Predicted values to plot on x axis. Should be ' 'predictions of categorical data produced by a sample ' 'classifier.', 'probabilities': input_descriptions['probabilities']}, parameter_descriptions={ 'truth': 'Metadata column (true values) to plot on y axis.', 'missing_samples': parameter_descriptions['base']['missing_samples'], 'vmin': 'The minimum value to use for anchoring the colormap. If ' '"auto", vmin is set to the minimum value in the data.', 'vmax': 'The maximum value to use for anchoring the colormap. If ' '"auto", vmax is set to the maximum value in the data.', 'palette': 'The color palette to use for plotting.'}, name='Make a confusion matrix from sample classifier predictions.', description='Make a confusion matrix and calculate accuracy of predicted ' 'vs. true values for a set of samples classified using a ' 'sample classifier. If per-sample class probabilities are ' 'provided, will also generate Receiver Operating ' 'Characteristic curves and calculate area under the curve for ' 'each class.' ) T = TypeMatch([Frequency, RelativeFrequency, PresenceAbsence, Balance, PercentileNormalized, Design, Composition]) plugin.methods.register_function( function=split_table, inputs={'table': FeatureTable[T]}, parameters={ 'random_state': parameters['base']['random_state'], 'missing_samples': parameters['base']['missing_samples'], **parameters['splitter'], 'metadata': MetadataColumn[Numeric | Categorical], **parameters['regressor']}, outputs=[('training_table', FeatureTable[T]), ('test_table', FeatureTable[T]), ('training_targets', SampleData[TrueTargets]), ('test_targets', SampleData[TrueTargets])], input_descriptions={'table': 'Feature table containing all features that ' 'should be used for target prediction.'}, parameter_descriptions={ 'random_state': parameter_descriptions['base']['random_state'], 'missing_samples': parameter_descriptions['base']['missing_samples'], **parameter_descriptions['splitter'], **parameter_descriptions['regressor'], 'metadata': 'Numeric metadata column to use as prediction target.'}, output_descriptions={ 'training_table': 'Feature table containing training samples', 'test_table': 'Feature table containing test samples', 'training_targets': 'Series containing true target values of ' 'train samples', 'test_targets': 'Series containing true target values of ' 'test samples'}, name='Split a feature table into training and testing sets.', description=( 'Split a feature table into training and testing sets. By default ' 'stratifies training and test sets on a metadata column, such that ' 'values in that column are evenly represented across training and ' 'test sets.') ) plugin.visualizers.register_function( function=summarize, inputs={'sample_estimator': SampleEstimator[Classifier | Regressor]}, parameters={}, input_descriptions={ 'sample_estimator': 'Sample estimator trained with fit_classifier or ' 'fit_regressor.'}, parameter_descriptions={}, name='Summarize parameter and feature extraction information for a ' 'trained estimator.', description='Summarize parameter and feature extraction information for a ' 'trained estimator.' ) plugin.pipelines.register_function( function=metatable, inputs=inputs, parameters={'metadata': Metadata, 'missing_samples': parameters['base']['missing_samples'], 'missing_values': Str % Choices( ['drop_samples', 'drop_features', 'error', 'fill']), 'drop_all_unique': Bool}, outputs=[('converted_table', FeatureTable[Frequency])], input_descriptions={'table': input_descriptions['table']}, parameter_descriptions={ 'metadata': 'Metadata file to convert to feature table.', 'missing_samples': parameter_descriptions['base']['missing_samples'], 'missing_values': ( 'How to handle missing values (nans) in metadata. Either ' '"drop_samples" with missing values, "drop_features" with missing ' 'values, "fill" missing values with zeros, or "error" if ' 'any missing values are found.'), 'drop_all_unique': 'If True, columns that contain a unique value for ' 'every ID will be dropped.' }, output_descriptions={'converted_table': 'Converted feature table'}, name='Convert (and merge) positive numeric metadata (in)to feature table.', description='Convert numeric sample metadata from TSV file into a feature ' 'table. Optionally merge with an existing feature table. Only ' 'numeric metadata will be converted; categorical columns will ' 'be silently dropped. By default, if a table is used as input ' 'only samples found in both the table and metadata ' '(intersection) are merged, and others are silently dropped. ' 'Set missing_samples="error" to raise an error if samples ' 'found in the table are missing from the metadata file. The ' 'metadata file can always contain a superset of samples. Note ' 'that columns will be dropped if they are non-numeric, ' 'contain no unique values (zero ' 'variance), contain only empty cells, or contain negative ' 'values. This method currently only converts ' 'postive numeric metadata into feature data. Tip: convert ' 'categorical columns to dummy variables to include them in ' 'the output feature table.' ) plugin.pipelines.register_function( function=heatmap, inputs={**inputs, 'importance': FeatureData[Importance]}, parameters={'sample_metadata': MetadataColumn[Categorical], 'feature_metadata': MetadataColumn[Categorical], 'feature_count': Int % Range(0, None), 'importance_threshold': Float % Range(0, None), 'group_samples': Bool, 'normalize': Bool, 'missing_samples': parameters['base']['missing_samples'], 'metric': Str % Choices(heatmap_choices['metric']), 'method': Str % Choices(heatmap_choices['method']), 'cluster': Str % Choices(heatmap_choices['cluster']), 'color_scheme': Str % Choices(heatmap_choices['color_scheme']), }, outputs=[('heatmap', Visualization), ('filtered_table', FeatureTable[Frequency])], input_descriptions={'table': input_descriptions['table'], 'importance': 'Feature importances.'}, parameter_descriptions={ 'sample_metadata': 'Sample metadata column to use for sample labeling ' 'or grouping.', 'feature_metadata': 'Feature metadata (e.g., taxonomy) to use for ' 'labeling features in the heatmap.', 'feature_count': 'Filter feature table to include top N most ' 'important features. Set to zero to include all ' 'features.', 'importance_threshold': 'Filter feature table to exclude any features ' 'with an importance score less than this ' 'threshold. Set to zero to include all ' 'features.', 'group_samples': 'Group samples by sample metadata.', 'normalize': 'Normalize the feature table by adding a psuedocount ' 'of 1 and then taking the log10 of the table.', 'missing_samples': parameter_descriptions['base']['missing_samples'], 'metric': 'Metrics exposed by seaborn (see http://seaborn.pydata.org/' 'generated/seaborn.clustermap.html#seaborn.clustermap for ' 'more detail).', 'method': 'Clustering methods exposed by seaborn (see http://seaborn.' 'pydata.org/generated/seaborn.clustermap.html#seaborn.clust' 'ermap for more detail).', 'cluster': 'Specify which axes to cluster.', 'color_scheme': 'Color scheme for heatmap.', }, output_descriptions={ 'heatmap': 'Heatmap of important features.', 'filtered_table': 'Filtered feature table containing data displayed ' 'in heatmap.'}, name='Generate heatmap of important features.', description='Generate a heatmap of important features. Features are ' 'filtered based on importance scores; samples are optionally ' 'grouped by sample metadata; and a heatmap is generated that ' 'displays (normalized) feature abundances per sample.' ) # Registrations plugin.register_semantic_types( SampleEstimator, BooleanSeries, Importance, ClassifierPredictions, RegressorPredictions, Classifier, Regressor, Probabilities, TrueTargets) plugin.register_semantic_type_to_format( SampleEstimator[Classifier], artifact_format=SampleEstimatorDirFmt) plugin.register_semantic_type_to_format( SampleEstimator[Regressor], artifact_format=SampleEstimatorDirFmt) plugin.register_semantic_type_to_format( SampleData[BooleanSeries], artifact_format=BooleanSeriesDirectoryFormat) plugin.register_semantic_type_to_format( SampleData[RegressorPredictions], artifact_format=PredictionsDirectoryFormat) plugin.register_semantic_type_to_format( SampleData[ClassifierPredictions], artifact_format=PredictionsDirectoryFormat) plugin.register_semantic_type_to_format( FeatureData[Importance], artifact_format=ImportanceDirectoryFormat) plugin.register_semantic_type_to_format( SampleData[Probabilities], artifact_format=ProbabilitiesDirectoryFormat) plugin.register_semantic_type_to_format( SampleData[TrueTargets], artifact_format=TrueTargetsDirectoryFormat) plugin.register_formats( SampleEstimatorDirFmt, BooleanSeriesFormat, BooleanSeriesDirectoryFormat, ImportanceFormat, ImportanceDirectoryFormat, PredictionsFormat, PredictionsDirectoryFormat, ProbabilitiesFormat, ProbabilitiesDirectoryFormat, TrueTargetsDirectoryFormat) importlib.import_module('q2_sample_classifier._transformer') q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/000077500000000000000000000000001462552620600231305ustar00rootroot00000000000000q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/__init__.py000066400000000000000000000005351462552620600252440ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/000077500000000000000000000000001462552620600240415ustar00rootroot00000000000000q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/categorical_predictions.tsv000066400000000000000000000001361462552620600314570ustar00rootroot00000000000000SampleID prediction matt peanut sat is bat fake cat news rat fake that news hat is vat peanut q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/chardonnay.map.txt000066400000000000000000000015271462552620600275110ustar00rootroot00000000000000#SampleID Vineyard Region latitude longitude v4.3.618 1 Coombsville 38.306 -122.228 v4.3.642 1 Coombsville 38.306 -122.228 v4.3.687 1 Coombsville 38.306 -122.228 v4.3.412 2 Coombsville 38.306 -122.227 v4.3.637 2 Coombsville 38.306 -122.227 v4.3.643 2 Coombsville 38.306 -122.227 v4.3.350 3 Carneros 38.212 -122.213 v4.3.353 3 Carneros 38.212 -122.213 v4.3.355 3 Carneros 38.212 -122.213 v4.3.415 8 Oakville 38.418 -122.412 v4.3.416 8 Oakville 38.418 -122.412 v4.3.417 8 Oakville 38.418 -122.412 v4.3.692 9 Carneros 38.285 -122.322 v4.3.693 9 Carneros 38.285 -122.322 v4.3.694 9 Carneros 38.285 -122.322 v4.3.600 10 Russian_River 38.424 -122.895 v4.3.657 10 Russian_River 38.424 -122.895 v4.3.659 10 Russian_River 38.424 -122.895 v4.3.587 11 Russian_River 38.455 -122.862 v4.3.588 11 Russian_River 38.455 -122.862 v4.3.589 11 Russian_River 38.455 -122.862 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/chardonnay.table.qza000066400000000000000000002004221462552620600277720ustar00rootroot00000000000000PK~Jxb`20a413086-c347-4b53-b349-4f89f0b76939/metadata.yaml+-LR0H41460M6615I25M265IL3H274*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PK~J' )',0a413086-c347-4b53-b349-4f89f0b76939/VERSION uU0J,J,KR0J+JM-/ʶR020433PK~J6G-u<0a413086-c347-4b53-b349-4f89f0b76939/data/feature-table.biomy\G7 *KTliEٷ$↭ں V!`UD%Rԍ({0 K yb{K|?yGs=gfΜ9wn۱dEoʂk͔qs>hԩ3孜௙}mFn۷*tOݛL{L]ɇrȣGbO ޶QG"Ol^lYV5XfD;9s޾ab^炷ow-oyoqb1|g [cӑGb7ŝ>ٵ_n^/>4К,xΜ9_m璷vFG>(߱/v~[o'S[/x>ߨGNȿU3?_O 7#G"ݜiw32G5ߵ7[r*޵?~&qf|m{V879&OohO{'$;wM1'ND;qrptss0Y32xc^cf7vqq9΢C!..v@ ΐ7™_8nΎf8C\]\:;;Z g89e'WglG8nNg?Yofb8'7Gtwg,C>[~ -檧+Q~$ ^zfgۙu8[1>O,Jߥߕ~~'i=NNzG-qu5pz pܜ!=?p}3 /?㿱2N7''5Mwqp5 &x7tf,l}/W;[En[fѝ!.z: Yml8o㪟x} ~Av?mblv{15~7pl(׷.noa~0Aylnzgpqԇɿη3Qp̒wrqtЏYt>@k?쟍ߎzg=!NN >m~484GAts8ul;dA?z@\ 3s}GD(s77‘Ypt^bR2ҏs,~׻A,+|Ewuqpzg"W?ʹߟ v? ?wL =1_9:d?M;ɏȽǧ>]čH? 3>.R#?6c`1{Ӝܻ>*nH?g61.QwQw1{7Ə1#|K O9xN;?uf}1"yMy;8#gyG͐\w]]gmߟSp_O/a"Rdx쑰#?ȸMSe9u//و߿7;OޜrggڷE7\?we[|(~- ;zSGǞ.n}W!w&n=L{Woqz+ʇ/g},2Gago񾞫ᘮE72#{m&9,ة7_hyι2wVkM{hv}-:%m3+ 3{3w-13y3Y!k0?t$nf~r&29/_!L$jͫ?;$8ϼj!?&Aᷮa&P:_ChC9cÇ jӇżSG>l/0OOOOO;{?>:_%ϽFMȲs{\v!~RSuI7&}RIz U.W#l2-:D5S*@.7<\ Za哰>1UŭP?/k$L R\ c'Ds "ZB}vÛ:GjBa=02߇啿H$IC0q-Zw";h/$y]ʊKWur[ʉ[9Jk*x?`j%T'2u] &ϸ֕PqmZ&|://iJ)oݵWKڠy4U֕v!usa/(O 57Ka֪H(ۼKUۘ):S|1lCl1a lϻ4҄夷kuN8aT+]U pXi_֔8P["~ qWsid#>| #ΦHL<^cuMn Zr{0\tҗ'ɉO&:bԒ%QAZ#b$D75>c v3yjBFU,=602RCTn;=WgR_/2k0^K#=tէM3MCj&&QƂ_Ys 4͜fC*۰*^{Xs !v?dFA\'_a.w՞epI+,7)Yx"dm9V{G|n@&ET~q395CAE\<tJ8>ΫTj"XjC"&4f{)Vr,aU>`ՂJ|#Xҫ&=|a`"Nkߦl79tjyݰ5BO;3ךڶfj5$KӁTR1֍{o7˼׋?i޺/c^5S2y \΋PL2Vd!Ϋ{{ 6Y|OYE;vՑ  tk4& =,(~+#حj51`׃8BCm#.dѿ;SH^ӝF6_󦘥!ЋA{ ,XJ (:^ %z#ևo+OJOѢ>bbeym%KPZ uyI CrA?R(l<'q8xWnj@a˧ۇp-;Ql/,ݕpLyɣ^ڈR~%܀/0t\7O(5BF t8ȨY}q0\<ݯk]O)\ l*D{=1Ww+7O,6v~YZĂ^Ø8DtԻ4wcl 0ZĝsM8 Jq {-J+>I NO'GvY#3sD%rUB!.?pR qN6"iB=`!bMM:G0jNL@9w"nE ؑ*/e3E5Z~G;%*OT2W+ݖ{IB!2idW>/rl<Ը[-'}LPpzHڤr LY-In3jBW>r'H:A|&0Ԗ#ƼhBrVH(Sϥo.ԟ,~mr=7n`Ŗc?޼]"ru_bqId>l>e1{uU\Fnӷ*_L}W]gK loC&/!ae&KIa ?[>jƪ> ~pSl~<&ɝUDcUt 2l*c >Q @I>uWI,G5Tu|UuJ3ZuOv?!$IVCH~LRV:Au 9 )J$6L~X܂qMX j0WrF 9ӃkR/KE]B_*wLfɓ{#A=RN;}Ϛ;}<82dQHJܽEc$ 3sT | iP]/i%lEb iud)*[9\_Q6<xE4(QuW/AeD)D?=5QyyуD]ָA⚒ypT%4R%P]ET)Q50xglT5| 7PAOB{>vvɇ9E-_B2,PQ'0kxr(j#57=3ٲAob%{az >](;+iau))Cʠք.npXVaSIo` CaU;'y~Į4E=˯`z"V BtI -9 _?dn9~?`/c;.`7gzAoGM݌?eιpu&EڡLDGH^!*e@$!V%E$mv6Y'8+jtF#kNw>䂄 GU,".[tfRH1 ^{8iM'sjA5vZTQrkW|@ QU7U|'>'ul6]Q03O'7?pV㷜Gʕ 5'-nx>Ho&O % u?E` ;L_mnjiՉWn9 =WַR_<3^Swg!]4 5Lʋy`a0+jO!'W3jWBC 4"+o*xLW2%u1:(&n~0yS)+_g-fUpq 'E-f|s8ЬIp,GυVə?I3q@7 r6;|X XOFPop4mCjmFYe:O8!@K%,TUKqQU]n6(' ľr߰8<{z;uȦ'F.,5^_庹 }sUc]e ::R(0U.~x"~5|US/Ls m>Y >ADG^Q6WcyЛS/L|4bS0, ުKCؚFC*2H 655q{B 2Ϳ-'IQzY*~Fo/"`~R[l?E_ZG$ )'Wp]WLnbwA7śPk|d! O>j-geC] w[h3M.iz;X(Z 5ќGse Gɸz:X,J7eu2К8FYΝd}I!K95UΤUr9A՚ɩ&0K>NffPg=*2Α*,a ܪ8D(94\;=BR/~,{)OG`u1EGhcqpE*[hn84<_xE8qȑU}P -Z]%o>? g+Y"qHsJcG4l$tMn&%՟yc ΓuP6کLJ_3}e@a/~<%qa˟ ]3>FƓ-T#-)BsiCb,ۍe*NK{$N" ~M/ L=6̛{Sަo0;{M'&yr6X "|[p,%YuDvL?ƊЅT(;4$qh>,!Ėv&Dׄ7f,\gAǬl% ڵ".ArAsNMNNtz`:@"Z6QF1U7T*χm"IaMq^pD`R W@nSQOdцՉvPэ@|稦U><Ҿղ½DIAE٥q4O7t"@PmUf=amE+3Brɰ!_0R-F˃{y}l1µLUDJvk:{=ÍPlxr.kޜ#ɱfve_Zm?uk,V~eE_-`E"FZŵNn|[A;jHeEhJqԷ51\^rvrWf /&)s.vجwEΧez NS SG~+ &Ct8MY}IL]P|B~&iʞϋȪJ 1v 臨yހZ{ͳC~ҮWiqu;(;.4cbq;*ŹLsB'GU;xfKɐvhTuu?|"Qy:|<3jirUJa7& y.2/e_~!k¬1CU ՐO >/`u@)C~ƙ8QkS @6L8UΑf !fJi*#4A`il8`n{ T=o0*/N5^lE #rua7-$X1ACTXs;Dv?z % ȼ}ҤNRu,P1DRm;P,o͑dBi}otWr a2# Hcq |kV{ +=C`r"8a͞J5}UN®5EЃMg'6{LcqK,՘uX1Ddo4Zik?DDg`貲˘>++EVzg8W-t۾I" WoTgIldw ~YX2Uib4/pƽhqGO҇)`,bv@_0Hj!gNw/ӔR5߹4*w0@ad#qs/E3C ] zKI`O$뮕_ا'gΜ6Y-M }dš_&G/פs$.: u[½J%e8Ԙ0Uz7嫰Vi_׫8&9K e_tͳ]3!uL\>þ$(?3fVgM4zɘ*Dz52@/ҳ|sVP8q 7Y27\w3hz-p] fiB!sU=(-W@ךlm7D..M POՅ6.@ Uw=!`PB gbɛ!6Dw n)W-ߏJҋY*H\ 8)1ڗ(&$#I67dmOŬ<[psk(NZQ % h~} =1"[ĩ8H*_Nۙ ȣUkZΜm%;חqkT*y XĤUȮF27j})ň^-1BB W:` qTwW͊]w%d^Lu Ul35#xjpDsvzE>:d?lyBJjN/[ugE/c[^B%6U.ߨunC&xKL0Q$_;u&Wb|]61sLAT?DJB '.ݔHAfU֜M ѣ}6|qU?c@00Gb8q4BwlO4.!ۭ"]Du>&,w5j|d8z~+;l({=8bLʽQ:)i+Zf8ⴠ׏fTP"•%3`LP/cؒ2XwGC&!36`/b샲ƘR&ME{#~Zu֋oWgڛPئ]usk..M%K[ȚWSrdVTpgurD}nHIjV_e;OpC:p{ԗ2e*AE ˆ.dM~̡H8F`³zK6zjg_l/~Sdjԯ=ju?Aeq e5iŶ5R٥ZOyveA:( &i+Ym;-kNCWscwpqa^FOӿ]vNp6^,McNr H7STV 7;;]y>!桧?ܗ#SĴòҀ|YϦ2.mt|Nuz=/yХsߊRz]ʂpC^um=P li"I~dR^b l%KoC(aL`inI`/9_ 9:Gek5Z?:oj%),Bª8d+[X 7a bj$GsJoyգ,svBTyH>=t$TB^tA劒jFp0p_GV"FtPO&} 8-itے Rk~IrVBac X˩t+Q\~')TGJd_c5Ue$I[ٲeJyv:PozFdAejDpl4'q2]YRAšʰ5_ds~ @6rᥖCkdn1n[?9J k\~xڇL/{8jNcBEa&OMaP=|!|MekY=MTS9/zʋdƷPR5|m$JZ{eZ4 #lDmJ]u;W ƛx5d/_p/HdN-UT#+'E^ѕ }-na^( n~Ax z{.z(zfmeoM͛7Od˂UGωߖs Yn}O79W`_6sfBx:]Ω/FF= kف/h7}C_Β;u̳?MUO=o}E<4T-Q,#.θ^C=r!MЉ=B*c1dfcXqVW!}r2K!P4PXD{g-HX|n c aM%kcepu”d=H@AWmS--`i{3-PԔ-m%kRd"JWW=<0<%;q| 8 9"nY^3.^D# 7HHYQ]_ukh6Lv^!+}b ΁,[<ԫ۫=Ɲ.^z~l*1ams"?/]0W5Jry*٪? 5}4HxW%Hfe>m^+"3|  c_hBDK|dRG[! jcrKD ]fZJq]gRZί]ȤpRf!ܠ]uJRc3!CZkK+ZNd@B@6ն;@+AʜܓDz؋|9!>dU"g[naʠ|$/ak[G:RߠsK.=+M$1OiKT{s5>p2쟪Ff(ً!ɨ $~&)lY`JiQPDr@Cr|#sw #ҏ]/H$ZH2JyٯJI؟S,:^pb]ˋrX1tv/D>%Ѓe1`J^B :Ҕ'g^55 YdٔI#!Y^0ďz{plM5B n울2:ʋ靶ewZR:zr⦂O1)mӗJ+H;Dѽǒ_Xj |C5DS5jwe8>1f P#D ሧC'+Sk&A炝NvvˊS\o7#fVw*-~ V8CxZ&'eïpOQ\Cى{S/E]Pfݚͫ d6^(σȃ=4Q[w勖N MV]`W8ykm9 ZX0Lc W:%zq31e@2E…B²yiJˇyL]͕Hbv1JAQ)οD?.]#m#eenra/|hViR zwKF}%\`#)lg3|@ (aQC@Jw~"a# N<ŴRQ}g%hD=?F*SƱp S\  `ُ9ˆ)"xQ50<`+j4MALxDbR.ZOUgɯCI-,l@P{UtCLK:XW'=MֲbLimO w Qa YJorliDϜRtȚf^}@%,oH11[+3 !N] ޯOYkrV|@ {UW7u%EG]aV l^Zqrm\j4fF9(ИAkc^ Z񃙒+|8X7s1?HU3CFFb 㦕)qLG"IKU BlxNMpb$(dvgiuĈJ8*y,}D"asuZE|{d}Ods s,`,/iٱ*zmĒǼэa].ѺbjpCUUQzߗۗXw;ʜt4\UDdLMp*Qu_r[0KZ%at@z-T;󈇥=&{j+J'藝PU'Wob.=$@bc[f'8DGH"/=:beļʕ4 ]c5QEIp$sz/ߋ#'/"MGLƯqdWvXCFG\ROVCŦ7)pUhBA ~07Dܓ)Y~D.g}:V~tĥ5Vɳ2.ݕm)QU6[/g"4'PdX3FV;zt%sg4it['RwI5g"މꦾpӽX4)dLg^)ŭysP^(!`Be#.S 64Q(:sdSEEC?ThPh3L3uvbI㫤AV;֔2obm/,uUh7׈*Zb1ۥqhOGb u[[jDׄ4 [eh%4)V鷙JxkO0!qqU:S[f4b1Z`uhHDxIQA,=mRW0328g艱S5b~Ͱ/,VxEiwLLMݡѫ?9^'lRoIX_ٞ S<l #0aSGz:/ F߈)| 8抎m滃G2@1uܭO~R'WsoViuEv^5d|f=`Ϟ+wNѼϣrFEly9k#yfrG:'tbkL}k\~  !Yфn)K ȸ@jSw*nfJ_Ղ{ F/YE"7⧋q [:|NM * 4E҄,M!FPl7_!.Dgtt=he3&pM%Ϣ0*㠠2Qd り*KT-@ ("** "l"keE=I @l_Ν~ﻖhNUuwuu9>޳}TnKy >~10?:QLya;oK )Yi>ae<)QaMޡ0bu>b*oPQFe% PI^4Zq3 0&5]4Wƨ*<@;7R;6aY`fK9<)f$yz!4Hoe4f8vt_O~T~u {/B-6x1vjmVi_]{stWʆe"D.ҴqsCc KY<{EbWj,y"L\7PҤQǢkft2@udžO& [Ds8Ƽ{Slźx M֥5zJ5_K_NSlj)6+P<"ShK>SfPK..ɗsC2iMF1Nms(=- 2RdQNᶧM#A%i2M{GLBn3?DMhGFiS\+0 {ܱdA#]$p ߒxvڤ81mV`Q}iWqW_5ډPI|x;2}!FME5{ql)#v 'm:-/%OXqQ؎Ac ƢYMcr[DG[?{}^/ V1('.?*p7QN:rC9be艺Ɔ.;jY걚'PR8+>6ES>9ݜOT|7f$4WMHly.DlRoC`!w6#n|҆v^6ShP -~'I{/<Ȁr׫߿NPpL*?rK#򺋷z159Rsltʘ+=ӊ9҇J0-6Yͤ#J`+sH[ƐuaL^'@gGL;o*՞;IiM)ڎ}W6tgt^q{9N4[E7WY.gzqM5f{OּȽV؈m%~7eǹī-[Rj_|qe^v4U&AOW&.\q7ُ_ USzit&.Ah=&H%:(QZZQ[*U=P= #05>y8TxELV~y5=gY3_:Uȭٓ|qK1e 1tːIuT zY+'o=et3j:5 I`%F,>׉Ҿ: '6_ck!Yĺ"wtl*{]i E;iZ {ͬܟ5!LEoQi&ȟAމ9\д뼍k|A4kO&Hqb<iDS Ԍuosڥ:N.TXjzkX1&^|? o t~qb`86jrUM BYՌ`FNa:%;~N<Up*s9 L==2[z`k; I'??׼&{eHpqkr09E$tdL6E[Riٽ8mˆi;BoDK{GTmYR؝Q^+Ue"I|Vg|UNTND%d W![]oWd"RbQ-Q岎3ވs}Tq BOjF$: xF~r+QQȲSVthZ֞+gc7ƒ>HƺTV<5!M&?f1O1]P݀0&VI[1ڲ 8q秩G{>x:i'?hiǗF\nߓռĕu2C3.a=fԻ^uރ(: -ҜHL4Jz_Z3*)# @&ֵrO:%/מ5Ɉi+D3Qk•!B\] 64Cm/-}%P.M40LߨO45xl~s:gk(ߤ2s[w#ڈqGVU_k}` &r6.J,E8_$AInƤݿ^_/3g8ꋭ$ )i E EۧMXXؖ);TfUf>>>Ahſ9spRzP.amF^2l WyjѼܐ~c7RoQPH_;hgrr[K̙5kS!a)PCDY6dߥf}glYYީ]|xԲ-с,qqQ,i|<~/qGŞ){h簷k(VPZܫCkR.P7"O(Mf djs﷌5G!|96HƼ}%;GWFrp77#2Of?<_ےW\w=`:/ >#- S=VxČҩts\V0ܚPT `mO' Э{bpN(#N 7T~ 6쐝0) pe'n쇗Y›:iMl s`g]yV,=sT%6&B1,% fihVCFA-Z3>]g*H0'=nz07|Z60s&T<R^fasʚ* 1$*4?,L ADn-k*95}myFIkZZMv+Zi'Mc>YeͲ@+K !sn,[`D*//q ]b@\wuv.]mT(=MIri#bI>u[ڠٳøRfn 9D,݅2кDp" Ƥ&gC5 1R3޸ׂc{Ru_օW04ʰR>rؙa.EJܰ2( G#hI;&<ҍ.+"lE4vkY{C _ր(liMeG4~]%fyKuRF< xgYcӽ&EN}#i)`FY!oLzb ԙQh_f#{hcUM?<7 I~"m_ UjxPIc~w͂5wy;C :N_8>>'wvdr9je/}T5I1osx+U^Ňr5Vbi7Pś3.PvSؐJ9`ar}i^g瘖jxiEPq}dPQΝ'yXQJWr(ȞIDo'"f1?bF}=ZI_ۿM H$={4LmvOr$nqa>= d;0]ZOYy>=9T|k͉Y+oX~zWiFHIޒ̃4TfQvxA4X|R$ˇ!z//뮪&SCe{Uk.~gÕ}[c֎sz5JmK:%3.gÍ@_}8p2[ 6Eݷgh;w̳̅!f~jfPm/馣HZ|WdN^w[+rf`9$W"j|] '񻐆~NPeMsU3˿H)Rc&˿cuK?xpؗ;=&3UMxKUULZ,0#Q C2wu'E S:7Qtkf[=ںz_ً9XqKDO(2ge0]lj\uIY&vw8w!-gMFoNZp&uU8ٶݚI!o@ddC^N7 A P͛C;)TTqFI!d/ޅW]@u*n ݇6sgた>XQn",('rBe JWҩxul2y9Qxr{ _qdT_b)92Ia36AsCN|9'oJu#X?y|*W}AFUW_sW{=K҇=u'WU;gYN1ǣX^Ql_c]}; Н2+h+.+d y"<*hpRaLϕ9fZ?LͅT/WX8UX; ש/:L$J|}ˑ^@MmJ(_~B6x?!^^!VVAG!gz?z`=@]`@^{bйZR)ȬQ\_GXeWQV9XyA(93g<uYPߩ}B8E4sUlT6R´~Qxw4TCKҾ&x zN˅ 0d뿯:e ~=a>/ʔ9k3ҀfY;/ ky&GLq4w}p}T{kL%z5nOy[ wxr{:>:lVlɴIx/ lJ7Q_D:Nuk̮BOߢM~5kn;/>_7#J +Soi'*r9Ϛo5f MS8<&7xL15ywJ^{-Ph!m%/Wb-koZBzin8Ld@Osr]N&:y^N;_^ْ]V,zV3iWJal-SMIJ7$V>~'ӏU&씷fGYw,PIIyҸ~lϻ[}g[ a,aD$#ۤ^>f0($3hVtD#MxVUSRʺ fzit#; ͋/ {ɏGfscZ媎1مSoZaHDӎxIRmCnkj aƴ&˒g{u2@6IZĐ֨ͬK"q;{λ6罴ձP , {x'\9-Ȓ>ЍzQ\ڧ huXPޡ)L}sKmOKhBoAXel^b9/BFhl^Nb6n ۵W.u5߀bzc _@:QT;[Q BPDf}\Q#k+~WCc /7 "4U9c`^hEzDMu{m% HҕYάTIre5'BJ[]f.ߒAҁmi0ݨfcBez>Rڶ ލ7˞̝GofN7frԞ+ 4 ɽ٥T "'pn4f_3'q-0F3w *r =%gNݹo>5vܗҹ;8a*0tOđ҃]Vvվkop"tg;QռO5B@+G]y̎p+m2:fSF}m2᏶v&G~!7CW8/J cػh4(3wxrZagdroRdEM׹٩Q%#B>sftwMC/0jt>uZFI60!N8YpVv":w7 VeД:6iTD)Awbm>l*~/K{ gfIc%O҉O !H:kgA}Y 4blP__V!rLzbGNGKz3ij\Qf.'PX'ݟ$}#)6J$;>B+ i1cƬ\ ۺ~yKyA9"b,B9WhJp(/K-D60c*",ݨ- ۳EH,u^hh.;~Oo zJH@$N/t Ft\[lFyϴyȨd=^I:%i;[;:G?29:QS] ;4Lи 6vBc % oTKF: (!XLuر.d| i" rh>Ġ6NmUOQ]8r" C7qCF5Ͻ>_[ARNSh{JA'zܠhfXI|Zc$:6w7m*?yHcA0xNGL 4 (INS_AK-(ɽ>@E!$8l% f6ӧ}@y`':,N{,ѿĹ{P&1;>_jœ-T(1g?:--<۪!!(?Yi>Smj|C;4wnz}E}` ʶ4[ {_`cMO*#8=]AN!11v/"Ī0?mY̢pPhsT\bC!9Mّe?3.Q<T>+lP&#Ru@7]!x fXP=d5ju d"Co#M`qִ[N %?mlHţPJ蓏~HX1|{ ;w&>M5UNoNlQBo&6$a aFQA}>Io_y?{}ukVo?:~~?B6|r>s y Cavk5o{`U<_Ѫ;|uoϼ=p΂Φ),*#ϴaT~Iq1w#+^OQS Ie5mAY+Q\[>)z !Ue5e.;TSy&\!VX}h8u#6|5l':ѾFukn\cuѯ?g{"]Lڪ7RvXVMOsibRUjKk %n Ly|Kmsgف )7O]#W\>srGTq5vT)#zaݴL|\8A]~{wj ǞYe}v۬-ާC=r麚G{|4W%dy\F=C;Ht<ү`=ivF3+YB ^ܤf[hCT{]I[F+,wT#1VB vH"4ư 'ZM #k/[*dݝB싡n#|[B;+dvn6١a{&6nVM\#U"xG6'wKpkdN;_}I\^^A?J%"!˒-E]בtV\"fo->73_e\\;p aWZQz6s Y{'-2GYf֙@^<',&n,!B1ڙc_I*+HnBCQ^N#̹Sѱ ̒j@F&r3? W_Ab/n ~NkM.]lfB(Obb*}2fDNfImezeʔfHCx}3 I#FXLH(NMہA|>rBbX7~.lF[Ѝt;v+8d&ؿȂ aĤcTM[ϿpSl$fD/JȄ>19l_u BS+l0O #"+ଚ /xϑ?<R iֆVtdՋBl(g8I}B_`r2}o 9;ŝ5oODt+Gvbpp LG,I_5 b? .?3f4 h Jۜ+.>g?7bl@Ƒ·{bz[_ݱj!WgL u[CK\<6z2Cy>a˨-OV9wpEY,ڷ<=QP j]xZ-Eh߰{*BNj+B[}e{⤞!DWWLd``$q3~}#K|_O1@׿ =X$}#PJjR}_Eo`? V/տ7 H@|X,_^Rao_`}]$S 9~zvꂁ =_%RZ12Sc7X=^W|PJI]z6K/7z @)o.o~~x\MRxP zcdTo (mxpԿ(uo6vH @)!54^o@t!R$za-6$=)M ~#XԞ$N)- 9 7Җԑ_W_<0RRz!zb;$;D<^@I9`=qvI狡^_X_4]b#^]>l B r u͔2F>hhh$8^&F+e9(e&!H,_l|1VV[ {R/ B^Iz]=q] #xpc'x}| 7x}XA  :Trr ~O ou R'$zE:)#OTqxrăW2[H,(S$ HRx==]]8ҸHzb4"p"!oCtŁXc uZBPd9M8  b 9zx+_o!{Ϣ?xE};8Мbkā|8^-sauC ŴB; š@OxxH]_Hqy')G|!Fߗ{x]ôFFϾuKlR/m~/8Tk>}Z߭[Qw??+?Kz})kR _ U'ߥ3Aś_v,x ݔk[˿Խ?_/IݲTFT﫯<_,S[&c~Uޯ/)>/_&Cui|喜_}?XzWԺ-K}hU5_PW&,K9 _Jݥ%?KD_Jޒ\3~)?'bR_|ȗRq>k_Kt;L.]du|)'蒟(Rv.7m'K]K~cM/џ'=t:g.П-zSF+S;C,NvMƣг"CdT;f7&=;0sYF!5FP5Zϒƨq#@9~]s?3ww A~%mp Oλ%dU`1B/]\.v̈́S\r p4%yׅQ0E5$rR}~H䓫o[JD1Ue@U4&z57 M KwrW9+&<X{Ĵg7]v UʼJX0q܄1:+Qӝ3ɴNe7͒bqC{ag'+xE&mV'A͓+*`*lemʭ p l PwQGthAx*+&VvH ;k=G'idaY3MBgX4PĆnxcv(vE:oF7ӑ|C ?g+s.../#}WN(&bb0ZkEZ&݇ en~vra>:67V#G*czK-<-!߳NxY:X?ɷ}~fSSQ#arjT+->ceH{KJp[<#dݭ7?'F%1cs +3eȢZ?aSXwzG/O9 zPu"/ \FǬ6oxUpu1٩yj['ƪrVC6Q3iI"Uv1EB֐1Ƞhg+s<‰c^K}̙3zׯ\wSXUuK}}EB3՟'N22urxn0[hTݬyi:߬29@9ZUa*iv{r0Sh={,Xء|)W$R->hdhGnn+.՘=#~u"y)YyfjBk\ B5Vl\grT^[2am\i o&~> <NE(Ln UZ+C^ g0ȲyJm65G,ʏϹy m4W>QgyRq1<= By7A7P1%qӹa1`O /pXr .(S4:ycN9~eQZ>yQgo'2ogD[mvP8cot2 Ku+s@]bNpMHFmؼn#w# E_9 zpv4!xQˀe&W ?ڝD/y"Nr@=.pa(. W*3eq)kU;nȞ0"_ qmO#t˪)g}1QS֚I[O9r0FO9jD)-0Hok\%Q p)h1ޕ|Fc`,/|9ܤSw` "啬HGc' LU,6t8m(^!~}_*dUH76C a2M mIEד8c2,)  C< G*; a3>!Zff6kkMy[yIMv57,|.5֢-)}V(CR+,ܶ$ʧ* Q/l8޹O|܍dC=* zyxYմ9" l=I8cLf5XngLF"݊/Ʒrې9& }Dm }vP%L8lT/)`0~yk c a?z_L<2W }OYPY-qY:Ӹ^dFQŶ8- BZw|^l2@dfY#W kXhAduyb{ #Ȏz:"Mwxɘd(c"O N>ӆkK6È]TdmS1; H=njϤ#~Z'7eǡΗg1*nL5FśރșZZG'kztNC~ڔ։yEzP2?j0q+z0e`:>vRz*D!s`r-ۤq BFL愇v#1ꚃهiZy`25qmŤA^!m?Yu!8`:tÄ#7F@mg0CλpRY:/ ',FF"dE\{繞p?\]oQQ4wA{V+7 j*oVDDZie BTTDDAڦ%*(ʾMXZYn사YdEHJ~3af>|UUVs:i875oy@B[{(i(|9M+K<]]\b4y}e1wSvEffJvf1T:w &Y:#`Zq6\?)Ň0np<oZ$o?r0A\{sz0l1C u* iR)0N^),3_.&N&Q[S?-{ȁtoȗJ@ރm1%Oy~$S(&kUӢ*9P$ߴQ=5nK. }3oɨ.$,h$*T7ujhtib]C|]n.vCqp7ɻzcTN\0=zWĦ] j #od?fabe#(qʸl7\Nq!x-$(gɫtbg=W5b}|M{ 쎀 wkU6ʢEUJIz}L8B'˘ ^L]$f^nXL,] rK:*rYXdcbOQJR g(lK6CET zq3%/o2D:2aCqs)hL"hIGi&*d{n'Mxܔz{ِ?iHi`XS+\l[~\PYHۢxTxy $֫u?Ç&>>^UժIK&LZ6@jQ#5a,=;Dc8+\Ztgэ9}&7Y5v>F^qkD[.OGfS9q+B)1*RE\O,&?T$3mӪX!E-lu {Fk|V.FkyN@ψIf)x-? 4,˛_ӕ9{AQjIf{]UGX[rq ܷt{b#pbmk!Hs1:- -ĘlldWŹs0i4XV ̋i-/vz/F ;̄7AE%?շRrKsB]q{I0р ۔U.Q!}^1ixc/h`c"rN} |>Ҏnp1!>ؘ#x e4Hܫ1\A*9PBn3 t8(ņ>հ96_i7(&MiiFͅ_ӵ.N@Oa|'$3@qr)S_l<opcR<,6m5i5dI=^9\蒼x@|Nq}i]i nfc)l9`́=]SȒ@5_=q*QnviϜ"XsZ%uMjjQ^L4$?H3֙?T>Ә3łCaJ*\wfjY)V~*%I~ `@9P{ܝԤA v%O[Fb׼hgG΅sgݾIt DMe~W N/ΟQ!uo؛I-R~{4*BL$ԅMuC%DG?X <=d Afʗ:7{F0~*fFyʲPHx4֋"y_RS˲+֌Y2<%wY&P l-2@q[&a9(y!pHAٸ = f%A^LS@+us <0]4_=qabh{|DE( /9^d") \T5w͛?TQ 2e9,9Gz \Di&P|S˔@MF~ƙwW/?͛-GC}fy*Q{jGlZSf߉m- &6CgkK|19yX ޳T8 V 0bXMq/ζT!:+UOqkB 7E,ПYe=zÀ3rHFе(Y$b:EU1Kd!74|~hYFXpHӪPӭ@q mVr|yhG~,yTE"m7Z)E̙puSp'S dQ3jae`V o0{z a3ZBQl+L4GxSJWaB h (L1m-+L8.V2%շdM(u_1UìjO|pa9<G =9]4r` о: z,aYV >/ 7oH| ݠE)a}rD%>})a_.H |&jL RR1X ڎx]Tރo;a59@|%0w@pD49R*8W+fIS b%xX ˮCiPX YֈS{EC 3_lg"Dmw~DE$0:ww!I[k=9CzsoeBթ:[Լ${9,cyvgf,&̧o-V4pAu:\)w{ Њs0WS\]X>ۺ uGO82n-5_ T$gNセ< / z=o{<`8ֻɖ8GLHv:#)eS"pˤ6n8ݞ Nv~_XSN30穢GD\8H9Θd6?ۼ*&K XNWD|d&5a$! )u"`c)#N.|3u} =%ރ"߳g-GS|`u4qK߆}k`vYۈ︈UFW~GHx976W>\iˆ-8|&{t vJگ9v "6 kA Lk9)M,"Ƣذ"ËG8ȶת^;MסǚK.j# ٷ6/,y<&Tb1RHAȣ6dN{[g.w^>W"I$k;@nԺvnc%9ws rddڕd#ͻa &ԊEG5Pˊ3L̬8UO9 }9S2Q i2 /on10K\2& /j.|8`=9CRI @c|LCdL"ˇ3BbLfu(_@nɝ`PRI4N^hus I/dvou 1\`o{{LA.j.$5%azOOÚ<@:m:(g~JltCo.gzq ,? )5R99eu(hWR9Ugjj#Vn[?\8_vU_Emú Na*HRdpFͺFYQGew %d7mFCM6ZzWOn]rCTQ3Rkdz)n~\z1GP_7A(Cx$^5?kp ;ฐk_ Xs9g)bPFc&2XpM)ec^{0{TaVQ)cB^@3Fݮle@$5\ZA 4)PI͆!`8t`e^Rz-^Y+ЄZJo`,!*0Qo= AE9F"v'*LR)ڒS[STY; (jV)+mȯMg:vPw  LOrSZtwNyRbdJ_-9X!LuJNa01 y*H8Va/!abFHǼ{5Xuʁx aV ⠮G.NÙiiueB=xx*}wovZ7եO̝BB7ev#-?dLzZz/w<i,aA?ET׼H" cܰIeBGyKVڎsoiM},ҊȊtydg{|‡xR]@SۍLf5ہR79DX*<.3UT+xbIm~OZbԃgP)3 `>DpOB>Q%S*!iNkJ :t:z z-"Wp%BUeDV3t;+ulSF!!rz,,XS2@XMG4Wu =GZ1a( /q\}8 Չ.wIE[ȯ3TfJɧ޵U|͟Q?ֿ\)f$l:.| O/$6L=h!dJDaԪՎuarZ[(?4x)jN [* "?FZEBo9iM4*HRb>ZaEv#;9:A[F> \MD̜<߅—ymyϤ09O8 @S.z{ ud~ntn1z7V:ݛJ6,`YVYykׯؚ7m>{8#%<>b.hNK\mC'c{-B̾iS M,O~P^K[BD*jkO ٽl{YƱ7E-*wx 0NKQ=0O4ehN *(?17SFs5ajУKo'ov,V}rn´[һC*sJo3*=0tNOlg!\oSZLL3 +͓K'尷 “%i{/9\HWlUR1i-1SC5#I8Jz:Ev7> *Dq8Iq10I]JDS(=b ׽e8%+zU5ܻDQk̞,H/\Izw/ ua  7kaM0FA%KGZA- %}gp-hEXxc^qӱ㚥qB,a8P2q#-MDbSeg])o"Qɇrɝ1cx.&`fE"OYt5I$ƪ9Й;3ȫ!tH[}ԊG՛cYi!p@O8M9I|d .S1rMP t*o<#Dol@p{qj;^Hy>݄=hjXX6kcɧ|xҧ$/!eeg#:G>PICJ`RIuJu |bVS2(-9NGfzj ql030oIC2F| ˦{F=xQLJϯ7 )sDcnJ;e/tTGBCIkΌuj>ZFu\YLxǏ Ri72\#?G5WNN?8m'S45dص{W.P}y _wΟYNjo%dtj/F,DEr'r'Nt3::ew&g!%y pˮ̀׸xWɟuxiVG.̰U:ˢjgIz)kX2!">H `RtAH_60E  SW1g-1˽E{1ر Bh($>%Wk6y@E7dovj{&ЛXqW8BP A)L*s#;"@**Crx*rI(b *RcY xP)&UwsfDoQx׭.Mq@~ڛt qȜIhC.{%V}:a_x 8Tڨ-KobW8Wfj|D0E gz)cDzo j$jK/ &F83Wp2q/ZmxCWlԇ  yѳW9:Ԩ'}+fF0IoQi3.֋!kM*,鼋^#1M"e؍_l[h݁ 93V);_'m7&NRK1UI8G楰br  -tWNמ*2>Lv)2  ԴP}Xy {~ De t/{Hl::tRj{ԽJᔉ^t/_%"~|E׾"AP-F^PkSKt^{YAd6m ²VO,!pB-C@Ro&ԚJEL5jdI6\])a%p?x?͛Ooq #ל?԰y ؟wxןv]O&c"""DQ~x1#+e}"M2{3]o&ȤS>]g5#2^s"&<쫣;eT;T5|pY2㖥 gsLb -c롴vx15|~{O8P\*M}(-k5R?/L +7DpxN^Gv<ݢMj6^j3J­(P{sJG%BɪͼK`k̓_CY~җ+H7_6^)KI+&N"D"o;b֗iW%Xn!t9;K̶TI?ƥ0HVqmLzR .ӳV*!>tT=Bŗ熇-.I߈df.:*ɚ0SB=1y܈[dc*L@Pb8 ĐUo=M]cȕ7c[8W .cѽ6hCͻRQ{BT4@e#L$JB5Zؙx|&k=P/eJ~k9p:78܃(`<[u,E3M**ﯬ( 0rVG1F_mӖ(S\m|t޳щs*ݠa ^_Ƈw})L$֓> c:O栤1 Wg/jh D^/* $Ӯ(8%?j/*]ۢ,ޓ` b~={أQwCH~ptiE'b$FvW?ϷZOͿ/Zmڿ#4s$S[?[ٮ^t?'}W]3}?ҿ̟w7R??o?κ7POac7q_oR^?Wo* Ig(q9̛Y׎ܾyawUǙ vܾ;yM0[\ l]Zs|U_)Ҳ׼$m6c'~;9' 1\zW[no?NG *Lt^>q*z5u{D+/GnȽkM6hWV_m@=W'<-M&f1c;|?[zz[Z7Sjq(2 _dcMFN{yo|.0jk<5뎃K~0-QvEaOGDZ>Nni!"x٨C\|7sn6>[N94lTo'͹Q@KB315/c}]2mJ?otR{90-!ططdl&6:f-_q5G 0<Co|KNse⽛D]"ơ."#!LEx+Cdo1®.!|'cqx5k9rs{B7cu|=glX6lx".|i‡W!mN8YfaTf3]оcWy@xμ/beD=U7ܾQֲAβ[ıBnuEzHo4;Ѵ3o vDnD/17B/FO$!~q1~j9D1gO5F;`ͥi zz#޽N˟qѝէ_+$VWx4oKK Fb "~u*;b΅;>>ED#𿌦o 93>1xX4m?+S c?~p#c'K3-BƏ+C<{lJ]M:D¶ں_(HjJKo|߲\TcQ ߉/?*\A0!_UD$eJs_o6j0ѝÅk$fFu}w[/PLdUB!Ɍx+?j-&ܢ誠ғ`3~~(UuQ^Vٕa I2|m.}؛aqd{!e 7w1\^TRrsǒmUc2xw<"9鼢LwkǠ5D/8X+J- Ni^ٔ4Uwn#-5pz}E=`P fIV32~aő 1G$} yT]$ˣ>~66[:(qlr[8yX3m6ʧ@tO=&xt% )jyKEzc$w2W;S9W iCK5gJzSoPL ">sz';6FOܖ+*G7v{or8^oۛ7M?]:2aG|a[AHަ(zͿV[s0bk+V^ bdSK!G[N୏vgNٗW}En']R]%{Sa6s O" ?-qmF"=Y|s- mW zeXM/#@`'X{a闟# %?I'R U}^^7\tL (pa=2B~SBuR|jDv[}dbn_\iIUݺVKX>f+.{5+Y.e~\1W(#q/׈x_ _Kgl#y)-v5NMK"N^;fiD5m = 6.8ߋzv`0i&`8W7=82Bz1^ZΦ_dߗ9xaB.E좃䯷fTd! m߯W/G7kƞ872n4^z|KH mz=SطG h𯘎zMӼ."DIەnS%zWl§d%w F[I,M@ҩqy?{̳$>B~Ky692$kJx/&˂:51$Pdя5c^t]}:ܥˡ ݞEyl ί _%C lu94%_uQO[e랥tO {Zx1o k{g,̮^{{h!vӲJD_;`NCH+]MV0`(2^ Cn~O쾴޹ͼ_eݷv#rΥmVx&06۲/7D=3߂v2b_ͱ9?El-;aՙf0y-LOpWYڀ($z94BD?I){SV%>pņK1x2v=0^L}̓W|>㞘}-INo5/wxW*J_N֛෣vO^FXPu|x ''5jhε#f"v:b;+׊0@"`n9fvv^VVd-ּ9:jn+_=$Z5fOx_GN WilZ~Iq~L+c`ԅ ;@ߨFbvh Hڂ ~|lNwkTtښdY|tшșsDX`Dۈx -o=}[r7OfJpDb1ߩLZD0uoψ!*l wIz91tf<)wpP\vVo>*o%ok/G)c8\KeEOVQv[Qlw첎}6=4&]*ckPkO-NgG{7'1oKr?GUO(ĝGTG'08C_b;o(ÞN8 oZihG1݌6v!||lZ*_t,QUl+zx pٍl$ऩSAq %xKցȉoI6ē_mIȓT~rn9)xD xQ잘jAbylጯX,5wV[LY/Avuceu6&egVoL-<%Ǯ`5- ZcؽI(raqUxc]F,^Z+Z:}`\g!4ho7CJD`7 Ƣ\v3m]wt R "!BDPTP"қt@ @E$EI,P/<{컳sθc˓s|O޼9} k$R"V= t).? <ؠ"8~zR4Rҥ?_S=<>=z.:_p|j,s͋(MZ+Jl컽v#8?.9]vySx:uj‚XĻS=Z|ׄ?aL5l$PHbj^EezbWŽtpd2 ,#[} Tˋݭ%!9}+p(,AJ { K>7M4SoGe6-RH\fv'I̩¹sԺX4jR[,sHg 0݅+uK{yzrꥂKQhx5 !#{>UUrFL?PS|e,Sv!# e] VH&[Eg`/5i}0x_r_)vQv[YMeS{PQia(maEamE+eӔU*bA'ٷOeK0:Aed7xOSAܢW-_WG ?j-dmO8ZHd64;Eg :܈QƤe6G7?h5__MGh''wշbr0T\NBVzRѹ~#E "|xStϸI/Lӧs]Н-GљxZ8T%R UiIT#KKgy G$ eV5hN,^6c GbM(r x@Lhg2Y͂uɸMüs3pCh0',i|`lV4V$2HI~d2:&V&kÍ6z; H0ʖ#:*ľ+UpŹێ T\t5EaЎeMKѫ2!@'{=iTġ"N;+6Lׯ=)hv \E N^ΆtkM+ |I^Zƹc9XO^,.S Έ:)E_ⱶ1& b`7Na1rl9Kv݊=o\2 eZF}!%вB'ڳXmhy-!]Y >|١^h| ȀY 1;K,mnE}[9ľZzb) *%ws|OΜ6IM)Ur^R#BUk nBRsW?SѿzߙÚŦMEAl 4287wZM}F"]C. /(,cKRJa=냔zr@&:z?_ mϔq#s}aݲ]O/ﮋų h!aP=jm4EűWRM+1PB=_Z :j6Y9{ĬD3 b2:c؝C Jn< Vf@&<.}$-`& }S6Fˈ}1;&R|{ŵ8{K7;_b<3GQLBN=Z5se)J=1)u&IN9Wrb{nHڧjĖ dv2t5ro/q{d~!KثK=0eZ`2=?c*?ׄƒ7ug s F[xb a "qM"l(3R>|{j pr1cv*LxC(u#Bʵ )zEr%FR}l ]м{E͎oB}3CpьXɲ{N@g(L@xWZ0TTH@F^vwIz͏u*"UJVCbšRdl|Mƹy@:ĉh2XC;TVy?~닠O0n($?܀\S> ]ZZZdB$ @9sa ;x_3hMH!"~0!^7X4Ąia.[X-+}Hx&\xy/%}3ȺP*Y3ց*1ǩ /B9ZF=Yȃ/4̵B>+.&WfWڔEaǩu&H&ĭ Lv% { czgz.,jZLMUJF͊&8ApJi $bjG$ԱZKJL5d{]'PG}?\-7'&5Y2:!6#Ig1 #;(P=|J nPN{/ٸ}>? K]cvAtkykKhàRdGpfp=C \xnv|3 t,B wnH_Wx0ûKg0U7[nI֞j&Fi}*olMijQ,yOմγ#sdf vj&v*%ȌyihFD9&bNZ+};hf@AypƴyDBS}7rߝAȑWTʆ;2+dk#"m7,>I~E>p-*wLGxL7 z- PYR%eOAMG>e+*ΐJem};밉`O"&LD܍b06O#g}a/‰H(ю:n8̬d†S>aF8XHyc@4A6:tw[5Yry;}wT'aVuAF2-O _W{ }x̿D f iOO8z)\lԂl,ZdFb 3ݖ &8Qehw+s֎Cc-9`{gAצo}@n]{ji1/0l6X wd( t-ryg˃`MSvYT$-biѽK]˞9,t&OD۽V6<'xZ ruaL:RwbE 8 CRBuBa7sC~ǥ⓺j@S2^OfqEI% cQ|{3'jGn̶~E,\:[j<2yɀ1eיE=] _ܸ -=\N:;p=.6G]Cekm80լѮBYfj_e20ls^PuQ'd!iyҘ 5B_cK3Aݓ8RѽP/C/)ggF7,+]7V-00if ΆG5Knp֧ƃoR-F>r"!23R\dTI&Xw_+IqK}^xbTf^!Ԃrd[9,bȭK(v,Tf=pԸhyB_Am"⮾țqe O*LP7v=lPT r֟v>d~SDS@dTԀx+~K26ծ|TFQs=qg, giZC_ օj,| ƭq]NDVӭam{1hZ)4&%ÉڱjHVLe G(R2=L hdr,p=q*̤kXA~̼ogPD/lv<9q )-jknEoD\aZĊNaKd69ɂiVWZ'x+E1 L: o:B"rÉꈧ u@۩B˜OM.W;!,' XLL4#RS.* [ȍ /R`E7XaȖGC::q̦WA,j.ZZ&jT_}d8e P-z&n6~bɴuG""G, \O5ܨ-  :q9Tjzy+/F`"-Gޫ&]yPְOKZ@7L?(;6+G6DI}$Ȥ5V-'E.0b&ɭd fkwJ~"o$ĸK;?";vrw*+ʇ TNCkLEMJm`2OԩɨoKXgaћ! +v(Q+;[n}ƛ1()_#Jbt_A& [qPD,O?~T[1v _=ݰ0]6|&c0=wb2ȽWэ$'9L,s'<))!4 <T %*[R&Z.+K/ { ; H?, m'=kA7l ͷ (Hµ1j6TG@~_b~3`l!J fk*(U9vOVh:@~t/nmT`%h5$aܐ |  ŧ& W߰ sIPP\Rk=Ad"0"Dn0_U]>ޟ?Ӡyka4:;r:ҿn*_ jׇX p;3&&Ʋ-U=q?֕X+MlT⹿y?Û <~(x*?|Gb}Eʱ"ܮ~z4 2 [}}3~3B9)h8J95li`@C¾rDž輏(~p_EX%ҧ["A.@٨dvU"ڱG(\j!Gg;yE1j`4^3:c;k3vspX6y Gw0 G ܿ=h(ꬁ[KoL\vSo`g/ lDK~A`MTmͷ%M/+Qv~!R7vϒMͨŇ1aeeQ<:w$B̡Wfo^ -e L4}Z^`ӃŋO?VG-2$Jjdj:%Ze{h<>voQ0K\j0oQX|L o#X zY 2x&>}& Uչ+~>>K["Kk &TW'\l9NAseټ'(S-.fB| N{ǵ KFe?&\Qxg1|$_*j[Wt yL8ۛ'B -~jfC$i"2eFgǽ&yUכ1)X}rahFPNZ~+ik/Y%)49FZNG{?dUa!;c{ߘ`HA)i7[\qLY Lه.{,X \yۙ˩Fo(bߡGׂhE · ӔjX.[ ؙvNߚ'3Og>tn:P\RBtkI%G6ލ$Tv H]rV3qIvՁXM6U\.]Z+7= )` ~_LMC]V!6rka!g}|}DN g PYrQ$ ˖jC ˎS WIxg c1 VWBuQ 'bI`oBȘy^ܚT*dUJ[VzMJyc*l|-b@,Ͷ=SjdqbDH w ?RnVdI}3Od (1* aK D3n6מ:Fy% Z[!v_Nu|vUlDҍJf^Jf{wqľ'5^<ucG c9K x(Aw$ AoLq1\p+zְ AOSmpzr f{zRqw{!ҷTLIjpI +rOoUM0a&+76A/gƶD/+/W ts(U,+̹~-ʰ:3lyuǩvrk!ܙMTxDt3x(K^&BX"Msȹ:#hO6,'|ZݗVפv L{H˚l`oy\M bt5s<Ҭ ",tw~~Z$tj:x"~RK<4!V4zBDhgJ$QmKBCo1j!*쓬7Vi[;uc״gG/cyfH4UW0L-)/Zi)E *}خr a?!xF GU6%YD_FvS/dͨ鶹u I쒌v`z󷣪<隲q~ה5rMy_,}w6Oſ~;wDj9 ~t-sG7?O#_?I_$mlcXm)mίx Nn.Z߸Q͍ipף˝Ý˕گ>U^M%U^SM*}ZsA<ĕW>/ an(w=:Gb\ _]4p`}>/R~Hnl<ȃ4 1__HRLlƋ2Slm.{ @mڝӶ? w딫IOyp,ьHR.iv*a]#:)iq>&0KWc9Ve]`.7P4\*}NQ爰̠η2^в3*lut Th<2׵E+j̉~J FB-,Ɔ-NB]/9OLB&Wiy~JZy$kGkފ#?|UyV*2þpEfgd;Ze>޹zsU.T6_ z@\Œ9|1`"7E'+}eQJV<:twD泚=k&/Gx#[oY8;x.xpG7Ɖ~qo k)՞<,o6X|1WQlH \5`3*P&&~ͭ׏ZGdq ࢀ1e" %bӗ`LXߺ' \"kq\3?r+HZ!&_Thp@sƺ$ۻ6|[+"VOC ʹ!;co({Bڹ)w7>n[w pWZwxر\|$Po[~Bpz0z XFm,+K Fp.}CQ!NՁ(lso킖7W S\ePK~J!!+z` J0a413086-c347-4b53-b349-4f89f0b76939/provenance/action/sample_metadata.tsvJ1 s| .mҦY/ʈ 3 uwF&M&vϴ_y>>{uqHhzߞa{t7ua!V b1*M"#L@, $vS?['e5 uF,7\}#P95S:h ,0 c`hbXEcITV 0KJ0P5zSrSA%@] R *u&hMDLM(how|2«&&jdX](m?* AkBe^*ʫ̰TXXVX(5|c1"`9g`%7PK~Jb`l0a413086-c347-4b53-b349-4f89f0b76939/provenance/artifacts/413c391a-557e-49d8-9007-f0ebca904645/metadata.yaml+-LR014N64L555O5Lе400M3HMJN40131*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PK~J' )'f0a413086-c347-4b53-b349-4f89f0b76939/provenance/artifacts/413c391a-557e-49d8-9007-f0ebca904645/VERSION uU0J,J,KR0J+JM-/ʶR020433PK~J> q0a413086-c347-4b53-b349-4f89f0b76939/provenance/artifacts/413c391a-557e-49d8-9007-f0ebca904645/action/action.yamlVmo6_oiHdСl(0 C@Q'D2$XmwT̆^#\ iY@"B¬Ұj I]Ulqu0m2h N0dGrQKJq|^ko.ٽҮ{EA$YJh93HB'h8pր6`PAO^G. TQÉCT1]\>M %eEdeifM2L -1=CIe[<٨0 {xn&~X]pI;F]{𮆆  .Hҽ_?Aa$j!~!(8xG[aQ*֋P籒QSDqJBzn"%\qDsBOXkғ3jW5AցIT^A2Qy; ڂrg핽4ROJ@CswUuQm/I=kMKΰc6Moz5&ħ\بekUSv9*&3(u'_\:#pdvru6" _Hj=EUE Ǘz-FvнUт&.[D znX SA8wҀK_ [a\fӅӦ6ỦBMnW ~Hxxr$1׵\8=ݾبf˒%;+iP8c`,p@ 8B-h$$A2vIbB#D{ffyжl`~a$r # THЃ-'I߆Vm$J3~@G1BM -/[?>!>yb9|ХbOiHZvIɕL1mBqǭ)ԤvCM̵u a:|5b9 hgH*"OC+p̙!;y]ǐ yǀ^vVƅ~k`SVcfL|@SuO@ToYĨ]jS Q .,` gt7a;I-u =Fŕ9gy"̴nL ucq xLǡYp}?(U*8m췆EhbhEfWe?RR9wKˉ-xX;PK~Jxb`20a413086-c347-4b53-b349-4f89f0b76939/metadata.yamlPK~J' )',0a413086-c347-4b53-b349-4f89f0b76939/VERSIONPK~J6G-u<%0a413086-c347-4b53-b349-4f89f0b76939/data/feature-table.biomPK~Jxb`=0a413086-c347-4b53-b349-4f89f0b76939/provenance/metadata.yamlPK~J' )'7i0a413086-c347-4b53-b349-4f89f0b76939/provenance/VERSIONPK~J+bX# B0a413086-c347-4b53-b349-4f89f0b76939/provenance/action/action.yamlPK~J!!+z` Jj0a413086-c347-4b53-b349-4f89f0b76939/provenance/action/sample_metadata.tsvPK~Jb`l`0a413086-c347-4b53-b349-4f89f0b76939/provenance/artifacts/413c391a-557e-49d8-9007-f0ebca904645/metadata.yamlPK~J' )'fL0a413086-c347-4b53-b349-4f89f0b76939/provenance/artifacts/413c391a-557e-49d8-9007-f0ebca904645/VERSIONPK~J> q0a413086-c347-4b53-b349-4f89f0b76939/provenance/artifacts/413c391a-557e-49d8-9007-f0ebca904645/action/action.yamlPK Sq2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/class_probabilities.tsv000066400000000000000000000002761462552620600306210ustar00rootroot00000000000000 classA classB classC s1 0.4446 0.9828 0.3208 s2 0.0776 0.0118 0.4175 s3 0.0657 0.0251 0.7505 s4 0.0617 0.1855 0.8716 s5 0.0281 0.8616 0.0291 s6 0.0261 0.0253 0.9075 s7 0.0252 0.7385 0.4068 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/coordinates.tsv000066400000000000000000000001451462552620600271110ustar00rootroot00000000000000#SampleID Latitude Longitude a 38.306 -122.228 b 38.306 -122.228 c 38.306 -122.228 d 38.306 -122.228 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/ecam-table-maturity.qza000066400000000000000000015562421462552620600304430ustar00rootroot00000000000000PKuzJ ^b`2528ad6ee-9da3-495d-94f7-6b1ee03b221e/metadata.yaml+-LR05HL1KMյLI454Mѵ4I35K2LM50N222L*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PKuzJ' )',528ad6ee-9da3-495d-94f7-6b1ee03b221e/VERSION uU0J,J,KR0J+JM-/ʶR020433PKuzJh<528ad6ee-9da3-495d-94f7-6b1ee03b221e/data/feature-table.biomwXS[7jCDTT@ܺ!AQQPэHX)B)*UPe+H@ AR"E  @B-{sν>IYk5֘Ƙ3wlۮpYcYf-C5=r~dz==N?}s췷V?8-ড়-{'C׫s~%PN ;IG|wtΌEl\;wֲY f#O7=g|_;2uǽQ!'0ԏ_3!gǴrO7N!o<OyA?LxO Srf7]{=)>ӄ@ y31?9y?NS~83_"ou%puM'\/hZ>a??< ?_ԦL3\__yGWN]ۮھϛw;9ۋʙӳI~\πYi&@?+KK1S0LرSjYfMŬe͚$l7p+0 0b>oLPQ D%P$&Q` H>EQ!0h2 A 2r ~ C(0`#$" 4fS8CPDLpL P.C IBPPDAIpD`9F@TB!T@!`` D) a ~ B(2&APL& ~N D2F(`0Rl֞O R h2DCp($ MDC! 3"a0@ÑD(DQgCA2 TB yIDL$."# A!p($I"Ah*N@@!ȥ3哈P8F&#ӐHDp$XE3T x;%$8@p p8y Iۡ( h@PC0 d ~$" C$4 @PA4B^1N"p"ASd awp70NFB`$A!) $&'N:?@ $ @$OBSI`|r9D  fS( 03 0p8$Z9JV#)p4Bp 9 PGS g@h FE  E"?fړ L&+" &h2EFf E@! 8$4d~hB1BE@h pI$(IB h8d?ah DD2 D WA$8JP#y"$LD(0@&DD53 00< R P&G@䣐AT` r !I H'ԟH *d  R $j:ӿ:D "($0R@"CfQ(GhH2 BȀ2p0?H=  C;!)DY?D\SPd2P@7\/H(h(LB"g00 oOn`(S@R)D*q$P~|?@ XBh& րa@i|2#AhC$"DH(@:#Q)@AI "(I3C@p 0dr$N"`($r?P$ T=*2+" J2h=+$$J 'hG0E3e  d: 0L6@ $TS(T* 'Bg' 0J!0(BEP L{?,Lv!$$JC d ~  [4 C- pPJ1Se@Rap$rҭC ! J<DA N O$!, h?H@NQ3D6~ h d*Dl^g RGFAP s" )V3'"P0&S&)@YYz(Zd$ d-@3`С430@蒡($ H*!DpMC &LK$/;s H_ qF1;`&P)I 8` Dv?*L*dy T2*D2S>h S*O(P'Sz iL{RQ$d$+$)H v3NR D&=(Dda`z@X]`g"L~"JN#hKQ(r4@tO3$  72 N!i 5 To ~ $-=$ЅCS@IԄw̔@AId (^@ՁCw@CB4%"!ȓ}hv,ۀ!@RFBI@ӍFp/"&"LZ<*hVȨ3dh1HD"8(i"hC3>*p`ZD`|"v?(0(-A 74d<*]C @ÁN P6P _Ado-K p o ' Bւ:1  dI@ uHRef<-ir "d$\Ef؇ 2R(' (^`p8!"CG@|2 h:h T_Αf33c!f#L]S2}ڗw#'mg͙s?}d?AKG>;owt3{#~|H/e{ެ_uP_ǂ gf3ٳԧtzje?}y.@,Y/``Z5$})@D!?Noh~Ziܹs,>;6^9fYx7y&ihy\HmsJ_8"F~>iLGzM6M+<15ߟ>Z+}"xj~Ss95~+]<53/ҵO̓[JljNm3^NsJx75~+`j_V;iojΝ;J=65WLg~pTbOӵ '~M/LJmn5Ơ_zStOMgb_qSiѿC-{ퟢkO.Jo[NG+:E2|Yt)i~$l~眛OY;w>й}h΅!ܯw!^?=; *IT(ktbƵ5Ǟ]ruIda[|h\ZyC>呻Vo/V\{lɷe8) spɅ?Z7xW X֒Q.EWV+0KO.n`WiKYx{<=|q {3-&G*-aZf.v›*FxK`E:]ڴx\2MKe+sGy+ ?ξvi,Dڨxlk3ݽ Joxݫ߶kw!S߇hN/th|s7g*Y՝EȆ|DãyNWUYΛ" m _dy=a~Oy]}+]>=wU\[P]h^咟 n<0^^^FHzrPkƺgmv^*I)pRYS*4!}],U7g>ȰX{FM)DWn5&l?*_~֪TSrV%l>rx8El!mgBM| cYz8urfTwXŘqBeԟAWGk7vq೨%/.Y/icuvX\[|n݄o{zْ9'NmÕX4#/Wj:aQդޤPP d>)mig=b~)Jϑ= Ǻx~HmS{8y3Y\/m=ow=`H<UͧuRWl-gy/V6ҁFE)(/į*qָ^39A'*5ټsd[EOx OB಄aUP~(c\[7MZ }K;QqP%~8#4=}vT\ef|Tw[yd%{"=8Y`41l-2$h6;舛kIE. KOB 7Lq[BK*Y%,J{9'if\5 c+êڠ^+cQ <33ەUwϓ{%]fMe0J|}OZvA;|OY;E7smGHsEfL %:t5hKkda0/^ZcƛnժR-COs:vK52m}/.@.WL.gLxOԦfķY| 9׭JnNޒ(Qۂ 7FocN-1e>7X rt1ժ3E*_håYa$O*2Q`?ӯ/nsѝoǐшAH [^nLyѶcgVK_f;AJ޺@ 4tCrX+;K3XǛd;])DR{y!TmDCHdi㕘ݵey@Kiu{[:buĤGxuʺ>Ӟ;id>6ds4Ti=Pa]6[YkhsĄvUDo+8,7 T5ޢWTT$KgU F)-Kjjeomrk121yYG8PFtZhA$/ZʓeFnQ)hb)YPƙ]e] -.3{G&I~N6Z"b %//] -]ߤVJ]FOOzjT cfZVKK,fggv[9liwlFGiN9ʷ{;'˥}T;vYf3~]k[VdL!P(&HXGDEc:2߯6O|gW%*){|XUgM玫H Ic5qL'HV}\*OLy1OejgA Y!]L`U,rt ?~nOl~Llx>O0&4yhQ?âZ#Z9Un7^Nkms\ WEzttQa4c~vu9ۛnj4,ՓW|k*<ϰ g: Ja'|Enzq峰 n&}phW%6kԪV{G,WL=ĉ!r~o,P፹9^i;HdZʲ&ī!<6߮ܕ%`ItƗ[ֳ²rvӋ#Gµ[GcW$˲N-ܕZ;/Ǣ]ajq-l6tJ-)A칄vKP\^m;x'<}ջ0дޡPbrXaeq4 q6ֽ >>wh=\ʥwGmVV;vhDu^j}qw-@#`y9 Y&q}o>V5[Xma.7眈zyh ݘ6rԶ¼foApq[|D=ccnK7jXwУм~_y; Q@f {= p"[+gq> z} 6Moso "Vb-ߙl%snj*CaBФ3N^o jIE -yKOYc28|)6E9>胃][}Ymޏq|l=|yTܟOx_8v5Աfh+m>v._-˄^]v\Dk8Ն0jUʮ` (IŵVeQZ$Mֵ^Lz\c}ԣչ 4C@"Aw~&=[O2.)sQ~ 6g\IF ۿőDʻBj ;3劑ͭ]+vkhc1E3vW]3o٬SM~;JOUn1ʤ|-̟Ynz{]~Z^V{funiz_{gx8{j-?h}.j5Q6o/7AQەo<}}|LV]w\gubi1㨾y[Կyqȴs/ z0vSziv2gV*OMX\XVq'bˈԬR2Oee*Ԁh{K'TuV;˷ G(m5S){[rC/M2߫~B Fd74 #2t끢j|WWE#}Y%> h!FnVv>}- ݾW<1*r'x]يY[l]Y.z=MXdݣgmIkPQM,q7eÌk$?®1|>ۇCN C e`QaCnq\U0loEA"*{a6)5#x#K$G2tR?z0҃=V=4[ǦB6Tuqɇ5&,vq7Eۇс d Y=|㱮1M?Q|6cͧFxi$rblqkh*}p:˾r/ ^$ `4xwx,nvF}ֹ@G6/yę@ma s7.+W3z^ߤޚykn^=sfe<`U,,Ɉ%MśƤz pF)YWcŒ:M%j)oƺV0izmkuucvF&#q+fjk'z牉&޳M;וoXKO/ڲLO"% 7gП̪Ь6C.lbڣ® I"|1Σ-1ag*\XcJlW~oeZyVGv4]to;hasѺtx9‚n;XeYԮ3uGWֵ'?on*ka׍g$ۅ^r|/1E3S|jkD(XQ PuXrNfhi[>TXjAY5OV!Z }wX<;i8*/ڥZ1.P%RkR1h _h5w[O-(lf 9eS4]uDjM6۔nm }(NJ%΍| V,;V ;&M[nH0 \v5<(82{#ʰL;+c4y'-wÜMޛw 1x=vX'V=Ռ^8nT5~4lx,LFzǝU8"嗀䎭6heR;Y$G*aԼ /`z1"(l̻Ggtz}UWH>a->^3KnͯV)mO:uٹlI~|?67əb-CUDNdMw54?j"Jp7,eF& 3pC$cǹc)¼F\91P}K5eVWd7=zs|t8sRB<8ei*cfEʿB{gCt wQO7e:!*)myCj>>ѣw3V\e0s:5kh-few a$lHVD F D4(pwn *oњSQ;v DWXc4a|dbo>w,Jp`#<-pWu]}['¿\AD>[APqvHNkby\G6_:$ ck L:ct DCLwXw]\ݗ-rVt[rq^9V_ahUR_87Kڍ2ȃ fEV˥]RUmՁ9 .ah+,2~hpSL,0ڢPҟ9&{%I{Ĩ{ rV8V+r39uFk;V7!կ2"%#2EDCWE5Biv饁в~,wc鿔꬐-)x1)7Q'a&lėWui;SJk#/yF>}U pgtT[gq_H3bMzB7.a) 6Jwᗏ9klׄzmC9,}qjٽQ%/8Y{]l12;zEўG߂֡%1WQm1E38MZ58U)P<[ZlzA鮢'"n%*wNձ~nŇw~|";,YX X5'ZnO}+KpIs 7bԍO g{;BD/ =)zH0 Dž>Z\*֖])f_M)@+av,-l}^* 瘄}٦v5jhshe88:KM`0NϜ\Tei &K፵N/ʙsY)Wҿ6.uPaHJlEt|=:OɀC\}sܷv=IOAxC v=)<}KvK]|/VgQ.?Gkʶye4o}]CUM۾Kñet3!Z&Be nc2|&߳5uyw5A /iI-%l% ([tymʇ~%+_WTke?7_# ༡Xu3a v k4\GΟ08;WYHﴥ﮼:xSYr^#[ʝ,ԯ>-5*Jo$\Ւ=yRAH#6 鎽,f;/-u Aө,K%]-c&*^1xÖC*5YIBe %NVfqrԟѫͩ_MQsc_-I7u7? t')k'd$!{2Gޑ齜xLA r!򫞾wV'fiɫns?$z]X6m~G;3%W?uRN\Zo2E^!#7N7 >6{_*ŘafAQKުO]ǿpǍ_Ulk,t-G8?e^(Cƺ!jfH,jcuBGۍdQnr)u]&%d|YSYMYVrj"\a}8RGS?a'L_GRzm!#ʬ!WP9͠ORno7b8)#ֳ-hOS_v,H^ޭ&ʥ]\aBΚ%7$ U-o,3Kᓩ5 iZW[.O+e;槻F`^DHY&&e1~WwUZ0~Դm{y]N 5ݱܹJa(/g./W>H[.8: ֱX To@0J9 ^I 7caO,?ww7X%ӷ7{~=/+Hې=0^neܓ4KaZ=u>߮&>qISۭO{I[;|&{UvIdZ1fMUAy!^Q~wnL*]&vgop:xUE_׉8x8q(^bSFsEg %T>]t^ѥp/ߚhz{J|+w5iy2+~2g}69fONm[rS oܳ|ZmtF2L& ' (HN ԰on*~^E?xA\Ž.7ܻ3Sz{펐sJR SEI0J>:d<]&njх7ӎpzCF'Q\Z"'՜h1WuGxI`*zc R{! YdrQrY׏|ZdW(=y)cڮ̫0F fy4ҘU b_E{e4Ti1橝}ѹG睮O~KsY=RV= >8:xR]gĖ[&Viۧr)!;C& Om 9W:xGS-bUVAtƧ15^F[8 <TU3OJYv ԫϝnI7*+#MGlǎ~+öYޅjw #;9ƍlO)C|JDޚ#n3:YY;;"ì0qo~WZY.rﱗ| ."MqFGSŁV! hˆ" QʉTXJlqV5&:esgBP ]ܭ)2fTN7K*Mt5άmRTb¦TeJVne2rذ}ޏ~>߯nlO&)*Zh[#[eZax:aU܀N& Rcaۓ[~1C&s\0'~k.P5TJT98L=OBGS] Bma5/yzv֪ z4|[ai%k8tyGRWDpQ͆<7 [8<̎rݨgsukm~g\{Ck8q4\ f jJp7\/!kS/%^n_o#g߉jV0c_';7ivueC3\~Z 6GWc5ckH;pZ.~ ; ӶtH[`QS~`LLF(sKޔ=qCBA42W;`\M7ڲN9©eRN8w BKr_by<cc [SLoOrZD)V~;4twBVFn%KIƧVPW|RJ ʉö4`.!M-zEI Y(Ǔ*wKl0GuoB:{f!-D$xwuRJh} 7d7=d;P܂n~ h 򧙗WMM,9<TX B)#!@-*6)C.>LT&ޤ5W fۚN5}ld2&>^TK/riI~:(ㄗXɅ[<iEe};B{:$RsT+.eBcx7+U0; wkJO g#~$\0m˪\@ j sz7{(O(LX=/[cm[lSryal*0Ri6w[@-D9->!M,M1>?L,-{/a^s8 NrfdǷ.Y^Y :ND(&'(?Oiן</I]+3S+psn6V=z' jLuYmhTlz$=:sQF1PΡmV'p͉v=35ߧDIK°.$ M : HY%3ǹdTKFVf|g5rfŘ }znntiE0ǡ^,.اV-g- kvyz:"U~݃q, k){A]h{Qf9e|GrQ VKEqvŎ {ι-lf6>ZW؋ 'aWUh+_t|S!wIy&l|wZ\hH"O3z?jPJH+ K H"1džEdQ6WP̕)dt}!QKmA 3=g(D%NRW/q3.d'x!~byrIŽ5: Vg;M(Ѭ&|: V\! I{Nɑy=ƿݒg*! ߙ@;wwq=zzŐ FnGNAVp<< |׫^^I]rS҇VT%8DgӒ!e]{*@%͉E[8i&`0@/) OΖLSfQ (C/u{;?1D @,ΟwmXPȿ+;]KCyq6D%%]^ p7Z0X!nc?yTv?q s߫ng.lF?~Pu(`[[[Og)QM^)c_V5T/VW%Yȑ&/ c4,1NZLØ0oj|A2[`Ŀgh\uN?vluF.*MsÛ-'pGSVîT;W䣭^]? [Zo,bQ8 3soy>]잸 Y$Cw9ii ;R .!wumE{i^\sRח^ AYmbx,9ڏFv'󺹓o7UPȐ -/f0Sd3aR4v_) Oݗ/J f3w>ٍw:MUIi?I^RCxYSX`84C𺁢L_!sYibzK[ gw% Lk`Bgo XrJ?;_S] u?PWY {|ZZGɱXFǔĭG@Ma6n5á\Hd@ ׍b7 O\Wq{ #ZvW/ۨZTGbfu~jݸzG}2kNйRTQg]>G~iI|̋$}[F! 54M8yT g:<2%tSKx =ъUylT閱JW<O4yzY,K瀅&v(Xj0w)"3>fh=Kj/C1l\4{2~) ~κ'ӸdW@HQc#Kr{ a#-C~G;%VW Ȑ2sh~0SЎ'rN[zRPT t:%P j\" xvY;9jmO{ aCieH$tONܡQVh]6s<+IڄyK*]= 0Q`Rש<о, UൺVbQS7Bԝ~@,oRf NԂ0p:y)8xSvys2{wL >9b-~RWB.V@ҋPd^\8 u+ՕfΣu : nP̬gRٳa V~[?/XDO 0, JN?(kz` /U&Jռ,uz^!>9 >z9M!F}vzP}2AO> %HiA<7Z3ՑPyA{Yzixԫ܆8d^e LF~7) %xV{Toz w"#exVٗ މ')E$5 cq+i7Bapq!07i.uո6-G/>NBgt CV9y6{MqAߌEiOT'O[,O3ZѸ+q{'hj 54p J~Z0 ;VOU_M_m {8頭n#Cxvޠ(*ϖMpvb5i9W 2d_ùx|1]CJ d{GvPny0)̌]Eo7$vS|nua(ḇrBR]"drP+:e6nf ˞/lk6ik~/wҬܬzJ:i?@>F>qMnP EN.t6va&]s0h [[5)%a|N\[w"PPeI|3AN,qwE V'Eutg-EW9]%<,YI30FzvL sɒc ymRD75FW.pudh^>-͉acIVљwՌ6b 7WّZh u@MFOC vUµ3Kpå,7DɔlBZߡ9hYQFu ]lQwZWfpFO׶UOԩps/'S1chbHo6r낍YSJ,xHar:s(Wմ$@J0g,xSN5o wi,QS]rtb"~h#mf j'-ԘW%𔋖c%,rhe3%{Z:gĈrV`8rrniduUJ`4RTČw)'u!- Jl8j5? /1`=dHhJdrJ4"uYʐF'}wʾe7zFXXcaʾec d9T0&<  %8Թs$TF4k=Bg, Xúf7Izҿ\=, s^j?\Kj>_ WaU>߱eEqx`bچk !_Dii`&cZA|9ԍ#D*s)l_fcID`x)!]ơQ/v:ͱ*J Xhx!xxeѣq٬fq).!)'r` W ] D5~P3 cYGYI=kY'5wIaȊnv `RzB7:Ǵ-ױ}oPw m2S0[Itvvɢ6߅RzCQjW\(I,4BtQh)aboh_S#[وKA"3͔(X\t[ ,U3A2՜U#p,~dE %ns 2o@)DtА^9q=wHK-D;)" V箟t/gh%nSA* 3;FKdSO#c:w@Pљ//*Y4zt*o#`Ä&" tQFI wdĪ dZe~lyߊQT'ߛKuaуuU՟Xs]8tșfx{5Xˋ<;H_3q ȝXSuFJ'45X<0IU9C3 2%_:IJJӻ7JCB]EI/@#6}'<Ȱ}:g#3nMs"+k"6ɬޒt!I}aʀ`v},731tg1} ,eq4,2 'G{tvm@;b*?6Sn\\>Zr$1:D^h sD>p'%劝%ow#Vs u^Ĭ JvE񿸡 ]xY'ӥaMmcP}8!ΑUQC\ /P2 ( qvYFT$Jy蕙TS{9 sMD}^,;;z~gnaΜE)bFu0LzBx4OS1c嬬ɿʰ)D|zݔ\`. E/46)hW{FyyˣQ 9VT:2ze25e|I & i4zBe7obό&K\Qm(E1pd;BEQp r[yEp>0Pq~)tM\U)NTw/<W z\1.N$*7g,'7S?GE;Oq΍"Eh=k]e@Mλ;=4wAWIwZăVVa+0f2SdFF9ȴ2@3-6XD7` ǧ!I˧&4"N1{f3W΃Hg /89RJeYj(fR]jP{|{\^ RXm<~ӯr&k ]I<ll9e,Z^\%kv ͢=WĿ tr7;u!\d7 lP8N0y('GADäyevUNgq 8O6GOLK3C,ʚ10!)}REM*޲'2Ln@Fė+9DSE`MWϨ)(ZG8y'Og>=ǡ5sBmvJX89A.S?RԹ4p1Rvʨ4(R裶M:BSIԹo3>@Kpdߒ$q=[E|EP5?v!9l(\;͑&A/yb3,x~qQALrɈj0 bL;KPF>Vk Z'N fp*K 5AeQ^7BzW@w(8+ , up& ʪS^$C̖\<3y9~yK'?=8.;Izac8 z(*v8rdeA>\Ӂ/. ųxӧ\E#囅]AF@*ӌ"*P9.4NM#-=9WcG좆5<~}fzTݚ8 -? V@R~OtUB3z?ǐvMܿ) 'lqĊ ;ȅ)vcv q)#,hG>>u{uub&ʌkK}Hf9L]NʳXM dC8'qdg\لj];r6%Z%ǶAo`56~ah۝$?tkjȺ|uGߘ4Ĝ4ѠvqvL.ڊB]Gy}v F YpB5OZ. ^i Y۟\^HEhb >05f,`Dac`Z|ALnLK5y"d3-1$q_@W!zK9ƀ-V^&U-sW킬/3wvt`D bƅv5EǼ#jap0:>s7B7>EǬH 5&f46j}PA1W6ٍl{D3tXh4ַj=ld&㔉/j&&".xx.)Y(I@J`rw ˆ3Cfe_L?vω=FiAIu :r\MFEhK)c. {_.?C3 'n0q;C,T5LZ (<R ?Q*"/ u 4LϽ?SvC3}~cb^v@V<e0/±P`]*?S"Oble{RM'5K,cH~ME 3}l̥ۡHPX/e^{Y |yp}jn'nYX .!a$D~=68`PSn˯Mwa?3Ny^u|œ hGq}cd^3X&T?6O|^Avh/hH*.iZ.Ucljз<)jrѵ\MU{w ղJ{h~rː҄k q?q:P@NrM7W[pt'ڴ{#jc=ؔ$ȟ0[e+ߛ%+ybʀCSƞs q7p_ ysGY$3dz{ZD؅ ,t1qug\1/Ĵk{*p$zuO^R3{Tݏ-KfPEN ~3 !v/IRd{_ JrԠf*G$"2}>zjJ։~Lp!ÚeW.;*igpna"X[(0To +k O1>IJY]ߠ#f1Hz@ 0?\ISɭȮRXnufS2 ؈u9ܸS 2wS_k%:Z>\Yz1jejO!b135'u6ē% iU♚P6F(gDb ))4gui9b,zr&u-6[nP#</bcW/:c9#=:lz8"ԗ ^*2;k;aqj9sq#^}!z7l38r)g@ Io텭n6vSGr ~-V8e;q^4#%B2A6o pqQM& PьFE,Ic͎!ADATK91JNJFmg­y/'St7egp2s>!m+镻$&s$gFd99"N_Efw=i.CO&8U\ͼK>oNěV$k:T3R>mA͹߸"$+6 _ˇ\Id3|&mU>#6s }~ӉzdAyֲc^b"9X/N^/X⩬ nېN =(HKyu܋qbxX~2W|ݟRXŬӂyo%@QQ`GVf_)( ]K׾5^0;('qE=X-b{Ŝ J8"$@m w],/W+5{M& H1[W`r_tq>iLe"=I(3naͅ8 ˔bߠWps@"TmNDzA-딘҃opבg%=3?!㴢WĸVᒁn5Yguw$tbn}E.M)9Gͨ}Dl>ȧ5 ߍI8E!˵CUQkt8dYmQ=A)Ft?v;ͲpwPÇWk=>l'c`"5{R#1lt H Jed7|qmP/V!8O(A^ 9=łGxNFQ7 ͔r ;ϸvLX5th,:]T <1fFOwՂ$dDo/^ 6ʚAMvuqؓ'1Ĥg4=nز}(~1TFn&h7>M$؛F,f&? |~ 2{ᝅ?#"fdhQ*ӧ:/ 2‰(ɺȾn*=g"k̟"ս"R3VO2|YIDKGAbq!lb*фOUhRY:!Yn}W)f7!wǯǸa:Vm<&߀w԰[eF(=mD)[Ϣ]* $Nd r7B_Q_bߧ|Hjjtz:Ov~+~ŮcOm+oui%0 hS <laEOji[Ke+dĦ"QbcVo0PV|@_A?y_ {n*(em& {# ǚ/=Qx6Fn]#ŪHo+@rG ?iu #/H^jxvUa=mQw# ZՍ1G,+ҁ |;v mҀJD=Xzk4!!:.x3 /WڎV#Gn#Pɴs?L6]&Xnt>8X_$ŖIfQ%^yO&CZ,OyRgI:9/]tzWa0IPS%+J=;  {!t(xLg3F3t)!L@Qa_&EDDLo-^ZJ{/Bf|1pӬP2eg _!ˀƓ93k5_#Sg%),1XrG3 eh,>`!T> Ȼ* 0Ws^ZL20x0eW0>һ?$ArWHiwV@2Ml x@Gz)|}~FeS-`QFk9*5kuKk>^qϔg}&U@q@ P3tz֯5=pLSM^$(*Ӏ u.kkP}4dj=> biRm!E ;hݝ2VGOք;sS4gO]%ݗnˣuVD+J:{;& @f"U;AOA;ynُ m+Lq6aI ?S`בH!'IM<0ǟ]2MA+Jn%xM4TZ<0it1`J "JFL'LƵ;DBr.i>+E \%"pzyQ"9Pj_; WN8*YEfޓG;刟lO;`60:O> 0 BjuDe#Tn/}xJמ a[89@HLN(l'@\G=Y~pSY+gx|ML|\U[O q$K;'W9>+픸A?q6QӌG#aʒTq<9gplKr 9-߆oSBNKoV&%J ½Kg}+D9}6>y8,R@s?Cb=d*Y ;R/മjdEѦI q6 7%\ݍh:hJY ~'x7DN,vɩ=nʚk>Е ?w9 Nk-B'rhQԑ~r}&/-qi}H;}Y&s6bkPж3*ĉcypw)zT:^_T1<3H߂֊` 4cBS~ag* >xH-IK9fa\"N_f7q!}EhCb),Ffug@rZ]̚4r 4 ɻHf?Iu1* y/I5beєz$W/V֎v2>VN^ b&.(ܼ'рo*FFuB`X ¯nz1euTuG<3uu7i/9 wbd0КCs kLZM?1"qSC?_㪱&fmEie\5 [PY0lHz ,uK*Ȳɂ?\et<(esP?mt EdG&>rS bb|*ȃRMT4iQdVb!3US AJJLd+R?OnmG&WwPB(x!"d-a[ J^1F\-AVOD$16寍w7ڡC Mi4Az~ky OZOܩ|DNdn s]+i@>Y}s?mn+Q1VbYam+|>XYN0 Yp "-%Fι4Q~ջvwXFH4n3ߢ825 q?,~7)(imeWN CD1 `MPy!&0ѡbǔstk9dXgi#iDc{O`1/UM|;ݑQ5[D4?= e*oITUVI۔z*MI*ei Z*T*lۋF*&re66;\s}}y~| fUTU6ĸ<{|_4ԕMT㈝ʘ sV~A_E1t՗n(a0؊jj&m*/I~6,eR iGclP?]lFMwli#.b=bvo a i{x$ 2 "導;3(%< OytӰrp*59|xxRbD =ȟ )vrIoۮuvem<Q~lcXyH5Ug[3g(a}kGF h Y ߖBQP&%Peaot>X],Ŭ|u,Ʉڝ[74b!(3̟NMV]e e,l/r:=a翈ujr>~Jo^k f 2> Q;%ISnt]sovv  _&'l4o{/1/rua;2y#D^y,r/G3՚w|60I6s03o-j?<_d>G=8߳͆Suq$P]?"Ed)| a nH[S-J. apOX=qb^n[:Wu1Yo0<GZ(8dF-ej89H$kv?;{PVu,9e[ה"MѹSE9ts <=aР`-fk01S D{Ko$MGZh4ʠ$Dk0bya$E/06oѥ dzU6zoh0MBj܄^-0]f8K|!l!_;墂"cr`]P(|[@,`xI:G,i05=P=hSد}%[d,2) OS&_& NeC xI)  }]Es+R)x /G|Vϰ vǐ%>9ɾ855 ScLpp%2á7ZxDyFL1/ d0tV W(s**KOKrAI7vm(4t=<˭$V_S>a6c_ELNQ-@&\=&;l:_/ (9pOsIVٱ>^fq`B9uNxhPD5lSr4m+ !dU$z>)|23Wf*ۇ@dSau3lZX-v1:aK|)0|Pr 4j'I!*9+25U3b NKD l1) L0nP?% G67l~b݄}_21$:OQXc߲UҏUlm/?zr$ν_Νu }[l RKdP ث3z\ra-m%m ϫf)|pg-־ϰ7O1H@2>egƈ⵶ϰ?OG-qϴ)q7%PՅHY*BR{USB橴Rb؁$u]+7꿊?93IFByI$fɋ|p"Izf}~X 3B_t TbOlצK~_4ptϯ(^ORT~bHLݟP4bYJN?dbmvl97]B6ip|v/$6,X+҄!aLx&/@׆:#%R0Qe3}6bKb@zMMO*+ A|dpn԰jXƤR|ʓ"ktyK`!Kcۿ[rFA&iـ@@@´U幫?[WKcJZ(^~eƼ2~=!3@e>U\a0[ qeg)2xMEJrcʋp-~ʡ]WWJ3bR6$.![3vBvdu/Lt5qp*wŰLqIА􃈆$oFX4,i-~r?hoXvLQ:WsUAty" )0k)l~Xs gwʣaGr/Exq~8:V [b2#vNVZ m?vC]Ÿ#HY%׼N,)FCq&CsIN|(}\n (8ˉ؇)42'byK7P{ߤfB91mٷ$ƸU^ puZ5 ҵ7R` nM> - ;l?Z @R=>uFX?N3js"}by\Q\j}PcSe} +;= ~I"c62s,5 YqB :ÑF"~&oeURɸ^Ǜ\%Ҭva]Ê8v xuH.>)0vfvy؎\86 GRC7P#GmJٝ /82a6t{.nL0>  ȏ&h1'w^_櫖:cmڲ2-# gxg|'X'4eZ_ϊ1w13f'jp4dEb%^~O[͕NѸa#|crU "+mQ*3daMŮTYh*Ŝ{2&(-;y\TS3/n1⋭:@,[M۽rt~-zBtTc_ s27{wl'p/ ׯ(ֻ(}# !NoX1ѣy}gg nbs-˟=]:5֠gʅ>B;Z3BrI\ #֭~| eTsOj1xFe c4%VvSW(_ܻB4ٍR(CS5^:0ZƙoW! ~JmrobM0 Nr_EƑ6Na5 l*3[0s 5r[[I> -K 2\Ht-S=WP;OFJ҄E&# Z8'3@KGGYRr~PKe -gI>m-k=X@`ϴb{vBGf9VLx9P/Tmdtn?+vI!~һW`_4\2hPcF8C"S.y"KfS !gPy*H>3).vဧ:vA7 +֋98.$U هms{p&4$wUmf$RX癩SnKP+~:8ݥ{X Y 4JuA#-4WZFi ,F s 4U9$ߌ Y-G[ ( R湄.R&:\KΆSj "J$ꗽĽ>чb[mn6"{U}>#%e9#;FD,G?0|r?}&Xޫ\$2pGnJc_ҍNrKt8I%jVi;?0R'[{HBoz7ki.=N uS$˫mT=s_ÿ65# T%h L̈́~Vj( d(_ G㴮`\@E^Txd.S}- 'A'>١wfMS㆝Jl۱&I7=X50'oS&軺|d~*0dkk 읊黩mɗʘjM?C'<Fe9&u2I"Vjll4ͣFr_bzlCfT 6݈%cˏ޲rc(wQ؞RoUF\3}`0{5QixG˧_O\tCjO_uכK*ZUJS|xr 6\v~)+!M)3;M #n(L@.`[Hu qcy=;ߵQOr"KDZpIU4\|f")fGٺ[pR/}4}${Aߩc4zm$ꎂSc].@)(R> S3%aHvZy%}V}meFMKfŶwշÚSӜ7oʻZх:НK]oFҔ{ر`~F$o~؋7q8Uny8b2m L&WW G_.M(|c4 O*#ONa$=hHK (lJ2[Xp\br 3P}QD[1 wnDO^|:'VN| ApC]Xjnj  y]8|a2퍞?PU*ȹ!5v߳/NY3e<%\9 #ۖÛm )S9-Iu!=ǞľZl˘LWM; Qwδq@ތeϪJؗf1hWPgBJ朮]b?W_bi4& ~u'DKm. cMV$(ҞE$|*#aUg-e5[^;=i.hzr r2y&`8RHR6C=o1`FB6(CxmCPGHl,I |/3k^5P g|"nНX L_r ]_6A #h(jF2٥zĝmixՐr˅yY?`^j0nrI%?<0Gz=7q `j Tdon+ !w A}EuLm:DUJWFJ1EڊKlj%2 E98@4 Qt/g^l}΂:Mtsv1-PUsq"&LXœR\enJQI ?3D ~cEғ F:"oa(GO—`cgHZb`#6 `u" IA,#ÓP#G8\BG*-݂bxr5L^Z4[5|>;ebhQ8^cS>W)U8ַ&dڞ: t<* e=(Mfo9|jT',E۩LlcK!#TTȓnա'-(N(#DymP-s$ I?v~=ʶ~yqOU )g؁=W'oZ$yūvi'hi_"zUHsd"ڰ)1;9ٱVn$h3' [ R8Z]YF_MZb<\M4k"f!\j,y%gY gWl4m‰4ڬ4(Mj*3jBOV iFWyfֆԇap@RewL>)Bih١8k\Rgs 3 ۉ|G 0xo%xKxmXAreQd!rU 3"牍1Qq@ jg3v\Lj+LŶl%pr_vFuD%˞b6)*b:r[Մ; Г1VCW-:lR)f1J2kd6]7bL7f8yeb%Iqk@*Ъ)`Ps>bwLa@ ~ 7ظ›nm.+rȯ ϦM)Ӻ.5eFV59JkoUɺb55 UA{]R71*RE)J%z|1c%r{=PŬh/,ɣlGk<ܔo_ƔDP;jG,7鞫|esUz\vr3wh+ 6:Nµ( 76* gHX-!v)jID͉ ൸GIٳ+)92ԄfVsq&z@"dڈzמ{ 5Z ۯa&CA\}hqcY N,` D b D[0[0 ; = py}Q`37(!UtC4>Df)2 t-lXU ؗkHo$EdI&'P.S <3u݋cɔ`)K:MENQ56-Whs1i9U`AwФOIf.Q vsmd 5SGu^h s\>6K/DaCY\|sT ?ad M 쒴!M49!:˞{6)[1`C7`-/h21Ann-`Ǫt6od`8C<4]1LV,\ ḻVsSpg LwqHZqVؚ LzAE0+|>Vҝr2ˎ;MFWd|-8Fjgzi2zibD/B+ƛS-yO84lD\o._g)oBSP_"%)=6ve?+yXw(BEk3a-Mtgw0.G.O c9 $# %`0Q![T%#T3!*cRIڀ1; q7*-q`/a1MiK6(-)]V Bq!G8+]\Ǯ1rr0xUG}0C|@(!z_S:^AKnH^HݩkV^=4 4O'bs3s-͚JE`O&)<`pN$l#tDL){m5'5yB"ŌvC׸g>'.H^Ie;JsqO?ݖQv BW{"Kqw`ZjZ{T0 =L|nT?.sSW3zǸ*(B zEp b t˿Y+(=UOThY7GsjX23 &6tuw dpHY)^g .ҨgpՃڣ?o _~$jFFXnm!GP>[dOsْZ/⡬DE[5Ը+3ni^.,PzX?<ת1'2ʐ2A@jL^Ըu_Gmn;i`_Ʌ0aehlC`WIJS-ݎ!ՌM浗Ȏ%d;g?n9nFP (K㮥$ݠ<; "WK~+⏩UYm+HfGoW^*憯{dG9d@zSP!.Z.XǔL#f)#y=`%adn}'u("X=:|a^EӘm0<5w|)\' ir,el:Sd^8v‚; zZ'(W?޹F5j؄w&}-"@1GeS*lKG|d{ h!v UHV(MJ%y p:/20Dz{3}d"??")ddm O :}iՑ%5!M_o ?;ޡs Ϣ{"/N.^sڑG_^PaRt̡ߋ1?GfWצ'k[S:DM(o0A]`#D#ם Xjl:nޢi;&_Uȍ=5[5R]:$W3-"Rup)+GUR؊p:rβd~}kg4Q]w$(ZNU3$xd#>gyHSo5F v^#F1;򿱫։I{c̠lGYj!/y1q&U@#na%4,{TU%Ő}8CozkAFkk&1}fZg#1ɑՖd&p7 pWT I3eזfUy9[eBҶ~T)0?qeTE橐CK`Wo!>Œ-е=)>&~j^JC}'n>zѐ5~9feR"gA7L6øn:S'&n'챌K:&kB"m0I] R{eHXYCpYf@kAz4 w|gx>Vi4r{Koʐ"ƙOKPUR.-=-(lIUG#MWS|GØDg:eYIknZ}DFР1!A uܲ *fL;hQ*ݗFmUk׉rC2&+[wd„段C- ~鬺b|AQ(,~d.pă39zR6@̐ggRNt!-3f/s{!6g ?JF4J@C<.Od2mܤp'`im_3{"*U;sZ|1Q7A%SNЇlޮa{KJH]x[1xLp/AW8Bpλr#Ŷ"fJʌt)u5~&Fr8HUJ_)k/j{`U='M<|MɗVq\&\U6o3xm_#{UߧfQ=wDi>C{O 95$LNG*n;Q_ЯPYsO~;[u V. S4VvS͎`EG/Gbd#$Y\_=\{!]>0U5;GȪq#UԏVOU6|$H~yW?_ӧ寈G38~+)B xbϔ>mJf*xEEQQcnnA%H"ǒHF Z '8!юtS()ڡU_="7me7*j,l+[5l^)* O xxq')q)Xl㪝x^Z#^ ]ȱط!sl@19|ƣg^n.n'S72WLxx'P/Mek(#TyOt"Iyeo Gox%T BjIY=2G7߬eDr ;}~pdrJ6ېF#]k:ڕ!f9&hXF.,l(^?=q,{%rUȸ>tK>6⏄ ARZ\J؜+T N8~?ml1X-ƱSvLja6<퇶>wq; Ц 99goH}o>zK4{jv7vD5boQwKLpcJ{c1cֺӟG2H- #2QOLh(v&a\9\?-gR@`ΰ?vab˄BP >3o0 (+'Nvyq#9Xq"~;N6;3|9/0X.L 'j7=&I&\ >iUD$~WA I\78;oI'Qa%wE~F]6FU`2׵7[{Ikq  t?{6C~T/ zh-.&дqT j䡮SBІMd".àCǽX*R|~zG'HSu{uo]qUSR4Uz.|ɕ)cR Y٦O,kt(FHN|eސQOO޽4E+` ƙV{čD7h z49;TLxU NiN<!1Od'M 1PF7qX{S8F&FlCH&gFk6!^pwPr 4ti_b:2w?~3oV]\fxs|oqovE'%z+|flV8]rtcvKyWvf#jEz0mQ6t!!M(-Wʋm{Zlis0,ZBՄHC'S =h2mL>aeBWѿːsA4rnhˡ|,'y@@7e6[G*?7 ]7qpM\})W;7pTɒ8S.cOM'zvC[;=}C_Yq"gI] y~v꒵*vIfs#;|Y6(aj1Y\ \_kf$486-1XoٶPͦr8id?%ںn$c}O?oxScCu^(ozsB5MFX=MÝI$vMWQ,Ye ݼ`6& OkRYS>W$$2l[_Rj`aLJ OAKd[$хR'RHQ-wDwR,;޺01ݔ/Cpvg+0,0td>$1pe؄J+f?eN MQsQxhE\DP 4Y7.UiҰf7ܺnd<Ғ-4x._M]n'mnNN,.ė:!)<8s׎8^'/ϧmΐϯnnaH ig2?AOZq-gH?hP#3(y0_Ӿ/4rncv6M5)[=oN 5*jEI ׉%& S @Ue$O" E-nL7D9GqF2Rs2оQ0gi-F^xS !vő1#aMoUCGЮ&/%AOk4v&OCXy#(\ˡ2+]aG/r=cTħԈ 3hC;+ gP>[QQ'^D%T3ۿVt qu'Q5 lV0^alט( SNJg6x{BҍP8 6,Fecx.9\?-Wr$vu jݛLr:MHIƽ"Gg ;XЀbZ)TĮ3\ L,hxEpF)l-2nOǤCL6_5 zB3Jsh3shԟ_ aV@E_xLA[}oPӭ8HTSie5g9H(sոqB)/r0E>~K[Zz5/ ZpqhWQel䮒R>sW8S ¹zj ?f1I-QԫXe>'dgå{wx׬ + 킾%avUo@aE:M?.uвBo}!!tŃ4d ]5`㓖ES嵀ȜI/~NOh8fBvcؚvveC`1NCE)H gStG](Qɳpqƃ試7''UDBԡ?}.Ep5_–6s\qnDg>e>:}M(R׭ :6?A/{RE!3eDI+nˡe:!Yrc+:~hN'߂[դvZ84_Z?Kyfp'2j g xRf|cYAΠ"3GsIU4-Fg֐.R:¢L1rM2A]sM}߄_XaNࢋ-P`{7QZoB+KzH)F2uahuj\*痔xg"BkY=zz'u*P% l?y`8eNQ${<1c wLWt`SôBE1gTa8]ZhU淰ڙ.agj<݁{g #wgQWhpvS3~ڶ$]X- ʆ~I.T>bq;#^(5A-YͿ0[_R?Ẃ@<̌{I0Z˗K׃HG7edچ-Pއ__SEB !ۣjy[B׼B'k 7[TX ݾAKru /}Cx*$\.1]gw->\m ?Hp=.q"8ezgYnVy=-{9ttqTIļvk58Q م(k= l/|b&QCLy9kNd82 :‹^oO;Zef>vNj<<KGư\W2>mwH̖#EO} npօ 6'c{ԅnY ,RkHV! TW F=?tTV+* +3:3@/yzў>,Fo=Mkomr1\,}vHha8kǾT_V.-o"N;<u6Tʽ=5 iU(ӧBEB0pZ=6Q$x(ANOo`X6t CXLѐmʊ|Zh̄нeYթE)O*'A>]"/Gp;_PȂ0u|rw/<+ A!,jv3J1ow|("`G.t=9 \EalxyZ @֨xJ6k|v& (J~1ݸy [Fae&y$gV Pg*-)>>nt2<$` B:d>fT}Qv1xcesUccY4r:_Ԁw#ƐadE>΂~psP|t|~x)9ƛ <l9JXN-n"[ *x~3ck:1d·)'ݕ&'@廗$H=ƏyJ '?k;GnxisuElM&{T25d=XZ{jT!@}wȣey(m,E6e Wk /4lҌFgnWQgU_26W?#Pu Σ)I)g9Ѽ :d0.zʍi7%#SB((Ӝ't fNA= 3a>=ˑ$ ameKtKQ#A?(D3c[iڰ{&}^ q5mik,7Q" F^v9E JJ_޼*m4`D a U/2[ܿJо?) Q!nxT~ʇm^*?c*mLr%}vGosbe@l|N68mWaKS4~ovH;65Hc@|:˞Áw5EmY|*l,̔y:Ov_B'uc؏Sӣ":cP:Ra/xpp bVV&Aܷ"lN4ybBl)qI`npĉi|ŪPkL /9Nn+ 17҈>O;K ''b^|O/:LϬ :X,xHBF.U͢INZEF{>#FЃbn*u$Hj=v(n{gKK=u+َQkV᳛ߣ]#ҭ/\ؚP@A3C檲?R%A O}'{2 uSR]F1>Omz\w>6>Bni Lj:M0(A/Cx@OeeP,D ̖Gw{ZNx˙wLꑵY“bΛTct?7&@߁It2 BIT$__'c. ]|.Mw^%l; r/݊z.RZ=c+Pw30'ʔTQm-ckzp,%%q:s #!wy7ǒtjT/T+a+ Jg{(s[Jk$oZ*Esĵ JyQY.T5 0,KK A.r,b+r\Sf#s̜ ևxHVMW VtEӰ#h;}uX ~xJ5FƔ~zή1 ]ށ kS!uk_7c ֡'AZ0PGS Do|Y|Ai;;On,&_|܀wHa#}~ob7wr{-% K9`) h&q3 7My;>nS+Q ;RFk x"b6hsGÃN6aԄAk+ڻRtqktׯۧH9Q4(x bC5 T yK2`Rt0Nmf!"oFY,z1v(u5Z;9j(IRD4D;tq [̩DG|gˎFeqH'6_V]xoG0/Ezar ͖6̸4QaZ'W9u ,"C^?{SER^l1Mw䶹 !˱ʏ lTnJ,%#A3+aը~x%k6|6};Ri/cU{c NΣj)aI5QN3R(%mTyLXrSCU5ұCFrs̃pv ~?t Hu P8Ձx1$yLƃN?ۏb qv+j&j*qٿH#P :^DJZ (cwD;ԩix81v]HN~pʖf1F '2"ZAF|K܉kXy#>Na-7>.%^D6IkOxR9m~&jND\ DC<jwGIoBd/ o8ÊYC3?~+}cԪlܯ;]@n_ѯHBָlZs[ݜ..?zp! z|ȷ wy~?`%JIÉa=xTAre?̽T/%2F[8>;?C ]\t2iT #YETLT$a%f41>S72DSt\) @%F=SW㌂.&]3ncab;GRĥ[a!cB5ǰ!ZurGǙ Scs!Lc;m;TW#c=3M)oWR q>4Fx$'jjR#zbbjc5ܟr9[^r&@ָfe$N8b \~j=Ll ;Tk7gװ\: SEY`ȿQEe+yIgəEY%?`c˨7s**&~aNSD5'vDw7%<\-i6{Ik鸯yָ$q˰8E LC".랙S]9@}"L XC;AL [M^(Kmzg$8d!$#ۯw<9R;JMD&|ԻTM^>Ku-,{ؤegƹy Fi؂jg.[qxf3?qLӻa%O;9_^Д̌ _p^<~qvD[Ѣ3("\P2kdL`>*b8 Iݯ 5@TjyHOФz]o\-'  aezޟmnfWfvttٍ;8#[//4' |ѺK+zp:$X|Zi{i_95{)Ѿb`=,> ?n 9sæ1vF<@'.~d&Yz:=wnU$U)jU#z})چ\֐-ivU޽R;qnܼ((WF!=|؂3?(P0n(mnGsLk&~KƀfUU7pOF2?C-:AiGy:?lМD̻m%!\֪R\<ЧD\T \Hz4/BGw.PR=qްMV}$&Mjm s 6K/YL6q"N=MG!j/< DCA 𷾁%9R/%LPV:`! =oKmka|p6|׿|DV?$c560;;I 2q+6drmO41z>< e GHhO0rcVNϏȊ,U%MМR&`|FI{M*%a3 hku+Hc~ֿ϶XSED;tJDv[5O&;I-mc+Ek4kِ?"|s m00IgeQUU%W_]vR-N5!keď68x}$I[C'̍w.L^%yY7Z<?;`ի [v3Į>Q]󒝯.}!y&yWNJ/9?2>V<Lςy1noj !'LDIY`ʝgm] 6Y'1FO;M.A)㖪q6QV>X/Crw$b5,1=dV4Pˊ%k_HŔAqTZU{jY(;hA)4f}}yL0)Zmhy V vact8-V=f7瑇N2N2)؏ ڈ]SkpaDFJ\-4= 4Yj{CQoUyi:Qѧ\ig켵^Vi7!7| ;w m5޺{n!L @(AdP8n[M1.rj]S˂ \ZSQjQ_#HwHCZ?jBu1IƧ|AAuuv&^O3k{s}ޘTa q\Hrr*\]6*Q7bӬc~|2s)P̰0[M.+a;ĔRv'!̏/z$ A4OqWB(DPklgyEoF앢<5;S N+y!8mf|Z 3t|4kd8zaT|c.KôَBqr,֧!HMWT`fgdUS`^xCiU*,rT>Zna;Ĵ_s96fR*#D1Yc̅ -N?%w^+\O۸A# [, yxB% kgYSr];Q rJ5H`Vq&A^u!]9{:.'2̗%[䔅"e#x0U.tk2>#$n'ewrsjӶ*K&:A&/46R L8#L_:%{aCWl ^rE7/c/jo!wʥTp ȶnb?IL@^ږ<`mԶ \O9-2*|TQJ怑#aVs̛t;@vreJ,wC Æ>!aX$_M"ɬp[N p}OAO/Zӹ֍Duk/-AIC۷^'/!sd5. Qc'?S.s4j]g,:MiQjP/ȶ*r 0[K@]S-+5W%Vcy~m4m6HϤڳ,Zƶe߂rœ7K`!W&8QIlMpOߑk옐nޙu{yJ37=߹C^V{P0=o GYxCaJd\k.&W/S1,k9}\2XüdP{3l =fÌ^sr֧.ŠL*vf|k]yVeU0?ArBz[]?2敋C>ۮ+!9[yh#;U*kE%ӔfW}}9]R GR7JFuve i-!Mx.y։8'T-KDP~n#o76R{2^Kg$Wڈ''*6W+)) ʭ!9 cacpczjRH^C~5C{Ф޾رXX_2 aʣ_ǦϮ*#z~'0 RV1,W.zGf$L[4p>Z+eڰ)ӞslD2 L2;‰g& Y1o- Y6˖/L? +愆n$:6Lк[6^:U+#J% U*D$g|#1EB"dSl 9b ^$8҉{6ف]nB`lK4u@*I/ȐcѶW_QUm\'64nEM,GqI1$Zj^tY&iSBQG/ b [/a mIz»VƲҪh4\w,{OuO_ 1/DG^vK,pߚZV S˾\pw{~?t,#h+dn99祐c>YKeEIKL[Bu㻛3 sڛޗ>qO:S-4q 8Zڸ 3#qSaJxѢzkmqp".$;&4!m'*Ӿh 2ّyX_^-a)5v#!~SI5k7*$-TEp`{c_g˂1J S 14e[5eW !rb״3;XJ}i E'g|0z媜SU^\vV n . TK'Ck^3.R^\O6 ?v.2.CğNNۮ!ɹw6aۍ6Ը9oTȟYƩ{oѰwn?^ZV*jx쐢jtEKdQlag<f^ȲAD6CB)/'OAj)cgX.jP@ @ұH鰩N?aV5S: ah7M; ?2WDKk IB7?vǛS#xos[F]àpsLux0 ŁJ*zq:̽m@;PA"gӝ !\ VlF'L4!o&:,{kaa(/`jL~n*,!݃+'BWEm_10wVޅ\ i:ka[Hk埄W$:sX_)ϔϘᴒܹMJt]Iޞ|z{>ok"NM]7M VdSէya)؅No-/>x=(PYPўa{tS6xM+A2]J;YU@QTv);;4+O-P)-ʆ 9Vc6'lƛV1vZ$ʶ&ͯ0TӇi-Ej 9˛|0YUq2b u-ʦNєassvK&t)vq s4lp(v+n7"G|FH$0n䩛Ts͈0<E/67ҳEv.uYRB`nJz.[6b:06Hs*R޽Ro PEw@ezM, 7evM|%IURos3Iw 7f<c/$;=eP;I}ە'DL2dݱ18V8B|([*z'̉ $}iX3Y*5Vf*Xc$Sn(58PbB5N :& )Y *( Ⱦ߼\:rz1futrBE(`x| JCY߈%R3gv&]]5j{Nphk/+G); kw5w0߲*6wg"3nT%wt6.=m Ac7ّz K7&.NUv8佁qNHQr\64BDщyNQhf.Oŷup S)g$*н&T ZG M䰾#&\'A^ 7M&r`r"C4LK'}Kn紋l}o5$2&'NLNTҠYXw^ hh~è_|`8tb@Rⰳ(1HO.@pηzE9gMJR Вxhu8bE֎K4ԄGy{% bͧƋƸoщثct~ eIұAwgD1> Sǃ|0{\e Y9Vm)CPaݿ8aODDK\9)!(`BUG~SjZ J{z MBu"ud+Lu@4R-ylNI&J4`r0,cH%iBPD V<4<uä\?C/U!-hV0OJHpڏ5 Թڹ$OL(ڽݦ /Ien.D.Ԣ ! ?9l ěcS,Aܥ wneM]}UdY`dӯ|X`PJ$% Sքގխ?f{$ϙ!) Wl ݒ J2Q˟8EgFaMdʨ3@f}Vz=,d6~"8{ lrvFzQM$`H\fT9k$I_ Gsb5rLv~Hh}¦w! A.x *D)ud}/J{&ehx-3h?vܝvҞ,TT!nuGJ-ӽ Xi㯃C#xƲO٦E| f@kѽu '&#X|z LPH|M~T=Um5 )C1rFqF<kf~ځMdŁ0ZvQ=JQ>}M$.9hr5MmfvAtKebA8¯}3lx5댷_sKTGq*A4o}MĪu鞝`Li=Ԟźp{ vh/pUmxǃI^I`|q$3,9nVNkRʶX}SwEƨ\A)ICfNGo\!,Ԥ%gMT|E*r g#K.p!զ\7%:O5贫 /Sk!oT拉΃G3-/>#UnqxAz}zNYa 977VelH=hm/Dgϊ+ŷ0g`Ir\❐9KN3L5[ Qye{1lQYra0(W#&c2b.Noq !gv5/ x *YWt vJsܐ_?;S "9=!\SR $u.zʇΠGJ oy[x%,Mrqm ıyi8N(ЩwMFh{}=2,aTrC$r za%[r354w(s(lNiہ"w7Z~ s N&S667 b>bBs(M8uuX~>}Ίș} Fzt Gg_spD_sD?`ƜtVuL_bofSZ[\ [ԧa (gcYo蛖K_/i-L /73ܡb:@6aG${RBѹ&7W&/Q  }/)H?NC2[yuaZBq0yM3%{<-1Vӎc' 4_Bj 53!6S&n I;T(8 )٭b2!gQ3|X*;5w~3e zmOMma}'h24g=UG0Np" g/FW>KD׈C=i Pg@Z&X͸A߿3 @|:Ug;:2VgOFDcdK燜dMqi)Ƙ:{^7 w_pמSoN+oF2?ǘb5g=Q3c{hG5|gpYEIK4XuSşΛ}hAEn1[i)3U߃* 93=>Jc{&rD=ҋ=GhO7M.#:͸s@^oys<,\mrpA-̩D{y9nc)NY0PCAU: RCR[uyÖ/Tӄ'ɾDr1WI-(Gn}OxBٔDwfg[HseQ,msX֍_j>lݘ7X&WNJG1͞ĽѼbahXF<V<+@ bm{l+cjEN.ۣ 恴z*T=qu0M3WpڥDZ} 08{*&J& k1:&ȝDS 9lQ9 Zl_+xv['iqRN:uPv0P@DS`.oZsNqA_| w#;v?$`vKa@8n@6 D-(v̓F$:#믃؍s\_-x:8t1kB;$+ X=*vLe5(}0VaܯFԒHRc-F+.]iǮcOqĀṵ!2ҙbgϞ!qN2ߪmˠYorpB,o.62 OI~6v řp6OTbY"E%&'(\LJx\8+9FeQ`f![2,O xb_תJgi ij<2$ܯV2>ɹ]!rdѭ{a3 ]/=0tbOFk+?ڙ/%L B#Ziia pl.ؓE/5z/ =J~S+F`xфPBRK{nZ[(|H7,AќX,tc {6ibW>Z ̘qvIJYDcm"V\~S_Э/y6ÍFY7mP@+LP+|~YLkDu4m1գ!|\zhܷhQi!k> OQ=aa4EhodNuL\aG,8WFR5c6YrSKwЬI͊8>2|^ TCa(Wr= "] ]DMfYM@j 5p9\: j܂[\{d+i>!NO&Gww#k7D%]B "oN3;xZMl9տ] mC%UG H R^"vrUi00=Q6cKGܞV$0hhdL^Zl* \?YY ggn]ua]!&{ 4F>,XʱOd2#i1QWuh}nR{hzQd9 ^&e "5sQ 2J&i{}fgS2A+BueaQ?:&S90rW_<斵zնSҼU~+ oI)N=p^ wz9~Y5_Z# ǾuֲӰ|V"t9>r`H-ZD],Pm 3?ۻzu<0aF\xhOffoQg9_*YGI= h}5BAȯ L/D5׿D#Ͳ<'p/5թ{ P7Ϯ}n2tF5_fٿӞvql F|Dr`Ck,jՉ,"= Yu/郅fo%/om ErCM /n%[裂ٱSO.̷ό$(A5_ǵg äʼnc잦9 Î϶Wz=8˚̺\/ ~zy}@K :̘H\sɄ є3(0",>3PQB4USNj)%KpO* Cՙv5u93 ^+lN:0%zҤ{@󺇱o{*ً1J] _K V|VYx #z* ċX$C lvx4JCj31~ФKrCq gH'aB*E)%MXYX־TVbfJf\'ǵa pqeCMwv.A$Fn#*R xTY?;۟h]m]H QM p]2u%d\7'H&В'^"$/]rd$cVN1.S NftaP%P։#MK-2=ZgX3|iIf)Ƀ)Y4y t$9Ċ*ػKz/3' ecyё#˛ ,wHUTrL1ӆY(?k-iZkg7MĜ [߶05$}@1Xo<{3^z6-aM }98 *$f 6I$c$0@$! S2MdYn=?EU%9`S-S5K)D8 3uAx+ʲ=e.[dȿy@T+M+fH΋PQ;܋W]} Sr/^]lYDl'up 9H6WSԾw]g1a)^6z ]:q$X^f+{r SQ$9EuPnIsɅZ~6+XWM;b jc.B r]m8\PbiznjVl${زb쿺$ꍿpKq%1| m;I! U+S9.$X-Ɋ3aU Z FYˤH2<ٔ#=lތm$IIЎ D׹F=/rjK7T #BVCPI]&XcMOf h6ጚdȧʚ&/t s9Zӟ"-K u!_ G!džaQT%]gv:#\ 0K`'#) zkɖ0OmYaڭ)(\JU<qTG0tv5e7#:'E&'Q"EZis:YGh^i8Ubl &;uL/ha9_ kŮ]Ca"KmShpSӴ=k"^3Ўl Xk7 $r |Q&!ش2ZÁ /A5 4Z=Yc-Cosi՝;wnZOo.hXֺq!rԲs_=eLߺ V\% ʔ6%dswN6y}f4: :Eo4+!άZjyĉChKí_QlFzّ+pww>)M$B?hӗ-X! Qs؅e=tN&bWr.ML5k!_A jv-%J[6FM:dlHɅے4o(="t_h!5>N_-lX Knb3!ϣoDVzmM,xn+lxɥ W;5*'+V7RS!bҳ$C1e vQ׋zY]^mO6d"fCIgJ )VBؐnWD^'B250#-?ES1_3*fDLkAeql<ıT&{HB i@x5ɋ|DYrp/M$hߦ{+p/dhVTDl+17^tC1eWX+8[f&">0|-s50MR*NUڞXor7 5t+$O-挺p4Zo>H@"D`+Ÿ D;ğbbi f8d3V}JTT2$Z;-P߀It&"ɫ|p-gxHPțl/7eCͪt6Z-S[=W䏮ᩋ> -KY@kMK+yWJz EY(Vׇ|$ 2KBj0g%]=gV7 rJ؋'D 7UtmOÚѢĨy%5GzHXeJVـ荳:sTVF+s-5l)՟U8HW[?:S as MӓL[Ο' Ϻ^6l5` p 6Y$CVhMMJv׋Dxc]I=R?d:,r|k+J~;9HX\ фh3FsaOyTHQ/)d"[fN2s"<` VS߃W9Du Y a_\Y'SF^4#5m(B? kbICܰ_PRŞٖܝq /=(x cH6C4DUۧ:aaG]~ y76G&"2jLCS?`ىuhpH GqeKP2UælFTþ}҉ >"ikt'|?v#Sgdj v) qU4c˥ \! ,&zPw,IԤu4p5/[(UD} T<ҖWF)q.\1.~Xۣ"QoXwbyx~)Z䦿w͠RIthU 3g2&[3^!휢^>0dbgYwF*-m@? g?) &[Z=MZ "Fh$m(A&cJD1M[il?AJL$T?jѓIg'8\WB(Pѱۮ8>duˊeM<ta w g3 +pu1uy!q]*ivbǡ'o :v-P~7f)DgHniꙇZ"7 p:8͵Qwgsҹs0v`^=619=UAg/r8ByN/7 4m]z\h :pK8T`8s"-Cӓ՗?tb=^Jvmx,e\(p:?: ))X^Ipqc @EA5v |*ln?uRIrf"~)[jjEQy3FKN m$?J'5M`C9@ڕgܻ9΋FMXK/ fqk"]$xפ/d&q[#bc\#0kV]~b,%i'!EN7n%sl.r৓Ɂ0R_m;-]W @lkBHZXVMސe>kC' 2/LJUtP}׊ruz;ϙ۞᭦[f$~sm2u/`l]ws P)yc$-E:sCK<;+3ElX? rcu *$<)cA|gRȕIV~Ab7kfMgR{y J=!办FlIQ!.l[hX *bJ5B"gSaѣrKY?ϝr, U1$\t4 (X~*ֹh'f~th'-"qqGQ둖j[0WƑPPձk Z+ ɰw:;R">ES/vvi  "ںGm["K }\av$ر4Pū(1]?%|{`sH92]ZcKxh%^s8|G^!KaFU*esε}8Anpy`;.2!CVkgR?#.ed89qm+~=-# :%%)f]TKCrl=@LmU9>hI>> mҜcq^$+ vQ}2WAxEa 9@g^WaS<&ߥcDe%r\J @ rt ow. Ouԁ W(DESOLy ᛴ#B62*yμRUkPۅ#>Z{9G 7[SIMwnU%I4r˰蠛 u˶qV27uh+vO:hC}$԰_)VZt4߭|h _2,}`Z6Pxj"[% ~{'@qpFG'p&݈b,y~zN1{4eW0j8ʲyQ[l yp(B), 9EbW@͊ժ%6Wx>?ñ+=bh&annR-z~&^̳xvV>t҉cXuu/bJ3 ^yC1'TU'?.Fɩ Oa=Y]UkDk5vSL3![!.ph=8--O꭭pJK Pz^GtfjSTҤ{2ʈfeH&g_#&Y누H DaQ N2 >޼_ ^L!l#ij=Uoږq+Z^f?*;z';߹U]L{׽uu[]~G^i+n}F}Nq) &W68{-|_zN[s4͆tg΍ٯ2e7kRS3czuN Dg1F 8`l9M*&l,AOs὜#%KsbuWqBmK'fÚ0]x6C'tIU }xN n6-]Qk@̥b|[+w88@2Sj*2͝}cy}n}chDWY%M~n~4 g!e,`0}vmiwz`&Xlϊ?>yZ-jU7As N]A;ޤi&I 20lN:va]M9+$ O[!MOLf&uļuW{d^1Xg@YwHyz[_Mq@I8xO*\_̭ŽbJߤn-1dw>6%C}w>) I*d|G}TUBi/"BJFBEC^x..,ҫp]-I4C/ƩfVNiTRz*سS`Ffv_u%CIiLHR0cc/`B ,8L( @IisDŽfSб_NwR i˾j.7PX!B_l2I5Huݠ- J^WE88'W+D;,|M5YcOsUIC?#H7:CU$?3gM^zԑ VvlQ빨}V\AzxXWEL6Cx/sϴٚHa*Ny㫽<׵´E&$rԫ/mnbCe%$Z(EϭJ3X"-OHr*=PiG$s;..=M~I;iB+fyw 賓T9hDFR?d#J0۱:I 3JƄQԫ~UUd:@hbAu=̐Cp%ʖ(9j ydkZUbz7_|иY`O6]ݕ=aAQDM}5  B Vv?H̗~@ ]VGMpCW Sp 0揨ÝDD$\$ߔN ;M`qZ/Zl?y~ ŋCyؤK'y 9GRQYzu1%@ab)lX7A:̥D~8 NŶM9;v:OZGfZE/o.M jhd '-^[ (48:(lFf]箶:VO}TV)xiAbӱ|L*a 06\diM$UXɌ~~ 0<; >UE3VjN,i6OcqxR.Ltz4b=Z eqhkQDƵT 9-u#L{eu2}}\_Riʤ*b%gk"lQ'Xڪ6.@C1@aܤ l gʄ1쎧Qx q4bSvqfs"ONy71)Nkqܲʗ_`of\'9v%]5BN }?#IL-({U(m6ǛR=&+?4݊Κ*D o ;xu:Z _~12& $JVM,D L;WK^I3S:OxS/IPC%TW'# 6t-2k\bAѥͮyT11<<vڿ}ӓN2!)IEU:`9>wA_ ,_3tFt_fDIJ U1OG.aU1/ B/1:!Fw?Aޝ{0nl$KFbna#wc9vqZ1X-yevma[14*_3Pc0f{s}c̥_w!םJe0ů`nKM cb:"Xm~!IfN)y k[J)tf8Ds;>50xK KvxEdL"w)Z+AS&ʋsD]ػ p^YoO?3UQ"**%-($"*QPQ)" EEEi$ HIH v3>wdZ̬E­6)v?/&i6BZ۵_K(.sUݓ_4յa$/rwO@⛔h^Y&LŇ#)u:XD[SG=Cާw,DS5>I͎#KsS !x.Zi>2Lk^A\Ly ,OuyvܥkSHL'=KCn-"]`UCvMU=|qJ]qvy=Mh?8?ic ۜDkק6 h TMI^U[=Peыp?0p$‡1pk(6"J78[ _rA yqN;< - ɒ H3!\"X`!{7tm1*}0~:_!&̛Z&w3\J9ty5 FQtE9a!U.j^@STzlhzTN:9^R$HCW|t?p +.I0Io%]HIm%"dpBR,tG,]\'m`DϋF%TPr2U:id)RZ܂(Iy\uD/[,ɻYV.Ұh̷fNH@ngzB[.ZuVtҺ͠Wu(Ef)t R}ˮ(z>9w(P݄TRa%ωSQ*_ƌp v` XPkvUuk;܀Ń@I_~L94hǏPA7 WOu-8aO@esZYSG@R| ^Z>mڌ*/Nݓ 򑵛v=ؑ `ަg`V mv\dKM"J:YJYվR^'`x,T *&K(ny(H/5MmohFXpF.BFC3SF{90[A6Hf"Oǽ{{ y*m lRN= w\S~Lrت8iVf b)Oͣi~׶%_Ͱ<}-"XsrW]"s#>Rsg*]"dVmyv#J\-o| ;7lIw#7+Ie=3{[Ƞqї#ޒQa}]zKfcMJhaA dH I Q'7 ]ѯ;ڕ:kL~1Յ:b+C yO#ΠҠI-K\="0gp!-{0`/ JyXfc.p20mѯIagfNぉn 1?m" /l\9 ˜|㖓C@z /tVx;92n ;؝dBB-ΎSP[#\ Y벝h¦.:ĭ?@,[Q4phHC_ ?iXm1 HZ}=krܥGƵ&v4hD>dZ!7J'f\mN|~SU)(Iu .'"D!}-n䕃`e>9Leq#N˰]d]|Nu0坬Y1D >?Ug# 3w2έ3 MXn6;lrkϬo"4L0kuCFx25X;ګB6 { =HQa$tXY4`֩DXl}}32x8X*ځ] X_^0aX 8>۞pidF~3N ,t,b%G)l_ GXIjek}'>aԈ)$Ű5Hh} =  3)LBsq䖠9)x3<veo`Z$=<4&2+22\EuL!򖆧*gX&Tw vYKQ^h>QZJogT$6t[C 3S^"ѭ|\2 Gc>/l:e/ HRɂc*hNEXV<ޢ|}C5cA(xlG}>^z|;Ր-oxՆ+DNK} s1iO z)ÌzO5e"r-;͡<;5:%90f'@-vK؅=tzZCS@E]- qCd@P y:+S &P=&H4"-ٍoLg i"@[ޒ5:!A:i[zc0<1咈q܄C{}Kɕ! nEE.Acl|\Q4G5@ń~^!|?)HUcsm}6Q9i +peW5M7`Nx)Ґ.{n\WUدJ)t3q{bPlB&-&,W3S2tq#5u r:_]}7~;W4J{qv&*FH@Cs!'_E\;1L!\j<\afQv|dMx9Y].u@f$np>Hk2=UtlJ"[`qOzE2S-`- ^_YL4mT]RZ] ٺ:^LS;P:q~uM9<Ꮹ`zbقi&f,di.VKiCK؅Yy>Fc\.K&%yF`uz\c}.1ݱI͟ iA]ґ1ʅ83p{51Qr}Sr<{D##- Fl6Q|6N[ŗ?+9&IKo.)R[=wVSΗU6a ,9Ab<w̯~JњŲ 뇿yU~TmlxQچu{W)ŦSZmjm|Km)uhX2[ReڜdAJrR$WuD-uX;QzkˠKwg?MGj|c$X; U k35`u qݝ~EYQ[:CF0U{>6S ol_=-y{ )X YÎ0-վ4{Is 6N " B*~x<*ɡtp9\T0Pj)ubkdou<,(0ONAi%}::m6UOZ*fJi(*pjA9P#Rfʃ:- ~!Fn&DB>U/!1ܭcryhj~3nT Bg ƍ""~S1VbDx勇 V}n*|,fx (%-p7ۤRZ l]fQU񟪓yRPyZ #d+th;@Wc7[MMWi qg'&Npʈz ҃Ո_I;PR</SCG@]v BT1dAEi3U%[4ʶDDzD#Km4.%XKAYc1?Ѿ2?B kr:N!tE^l$& c;.؋Ԅ B2j=d}Tö^< Mˆn.̤E M彥=ɏa5fP3v-~h(=d 6YOS1hczђn*~y雞xQɒHc,dnL7ey F692D0 фˡ4fZgqKnaY&Gf.yfܯ"ECݵ#ƝAPb93J)xȲ!+"QDM/L:-9.G`8#I&6&AJ{ ܈L'0^\Q3y d_2$vm3^,tA >ي2Hɜ0dK~k1:$I XSP-KKG׀NH|a0'JV]y}JIu~J(=)*& )i2z2NyINCVoKkҿ#Ub;ZO:G\$mG;KUHq]M Zۮr&㾟["Z`9? u? 'n"d27|3c%%)N JHblgI4]_*fdi򔙯Bg_oKo.D+:1j#g4eIe2tb|1@d+)L=jGxDJU|xpH ʡ6`|i02wؕ gM<#j\yqI Ӯ^o8n}:p!!%UHdŠ\cmaRȑ SB/p-L+qLXBGj Lcz,h4+ ;ε/}δ@ULne}x%[Jo9P~=.grMwM#C7S[ lsI/n" "&9Ⱥ@To'o8)rzUǭƆ}ne juT{*ТvOT _TOIWC* BМȸ#!(<4eYI]ȃ8@AXtG F]E Oyn@Ix3n)='觧kHΘ=4&nhT^dpl7oّagsU:j##0f {x(/ v©nt=Z-!>,kS`zڄxʧU.Mf0L;Y}! ٕ~d:˱7UW:!)g Uf8P.Dߟ*Oݗy8S2_5i;֢FCD{+d[ݘCoݢ8eV,1>>Nu.f w7̃XhW=ƮNߵScO*M-vgMڑlQb f|ZpZ>уJ M%h-k- ,N~UPHo}5Db.)BYZu1d@&VF~#2D?DAZS-?yjc& *c{j5;縻ÄWȟM jXdi"\uږ^ GmV=)\2;% jq_PC3N,SF:&1 ѯ5E4^Ǭgt`l:Ja7E gcpkg|!9 ϑwGzCjQ2 =HSp/L.';lJiI%/`nw* >SI=PxFOvnP)l/ 0<1sWE)Rގ - (MEuVRqh} %nqt$t\;'*hOLחX/^R@Q;e-C*H€/.sei:%{7/#i9&̎nZ %]yW*Y惄a rT]lBq>#} tԘF!P:,BKXrP(Ƨ.ԘC!pM*ê2l YAw.(G`Y\x %lO"[NhBCjs a:q0V&ʙ@Y3$>۫j3!Ϻszv3s"UA͍|PO^4{LR}MbIP3.XjُypvGS;OkP#?mg3+υoL6 z20(ۋ׫/>shi_¯K, D$lZ=,,]zILz)f^p8K)53k:IL/kR4ߏl5 ъ訳jwѸ/.< Y&X-!=QٻA=gPNAQg*5Y>_b톰u `DAu:gvH :"&k+f_E{BcGIs:AIQ@dgϚxq,Nr5Ui1!@ n Cw?9x\7^E_v+ƒ9 ש"v6Ѐ C }H;VW6ZTdpv,Ѽ˒.jkVN@nX^>}{h:X_4بD3=6%ɦRzVœa?kL,b]j(i*Qm%;`k&pcX?4y8NV/` Zt|q`R`NoP/0 7 ԓs (JH$ӁZՖ[v:Dke5m1Ŏ[E#0gGny #GbBDHM°䒥(yu (k}M{)S;Oi] fJ }h̘@tEyF]ti$I%s'^AhzQ -*wMR3p/ujD%?8p1NރkIf_!%vAе1Q޲hIq9)vfl[IߟdЕuFcYߵs!Eq84 EoZǔ/@cR]kK< ;=~@@ F2}9Ao RD8&;x؆yf“| UuKz>%ٟ&uyiCqN2п-^vġ"*Ip-ḽτg<8"5h `IIR$1(}Nrchnn]f2AÔTGH]<9C$}[14-h6AF@SN5/AB-벦JwqHw3VROik|5&W"s8.b!O ]+{k]9]nҩZT22 x)N7Y`Y լc!8FsPYdZq'ؤ4)92&dL|n-PI]6svDM|~z8᜘rpcBrک!3 <@9܎ !'\z?đW5Q+OIA_Qd.ByՐh0rs@wVÙ|6Y] ZHμ1-fdIaR;VLi񳰪y|'RBѺǸwAiQSRwvyW6 +gDfĹ]9LDիEsZOw%41/BGQD^x1ah!ă8}m,ߗA F6R^.f`quc?ݻYـ WzN=o=vA煀G <yG:MncAmrnW(t<5njnsen`-)62BP(G}-|gSRWOwQ2Rx`9@e@$5P+"Bg/ԀS Q|ܟD@) SǍM DlaG~ ԲFTok77bkU~H~xU_p{k\}(9>7WO濬O̿ߜr77g^+c?g wkO;3SXXz;oOdrNaU4{[gTuC5-/zǧ}[:> ?sfs[Μ ?u_Eg{n޳ZpЇs;?5`xmB'ONt^-[׽8sŹ/Κ^s̾k^V9svYSVO{?nͷY:ҕ<阉.yšʙfdEm\='clO6ܞuIfޞ*myr?'܏yO9a]ﻇyn1݀?Beh联1ѽce28^ţĊmOQ1 T\x4e0Q ਰ9+uhGQz[iZnRIk=t֥)wm(US TS夭X6!m՗ԝwRͦHU{)u`ize&4UC X3}<?@lׁ⸟=st's2>}'}qo''ӾQ'}C}Q_;\m%ڀTwJ W(1=趉:G՞a?o.v.gş?~ֺ<\s[k{XXgᏛu~5~x e2~3juKZWj.d#I >P T\!P?P8p6P),PUYYK2pjwl0YvMk.M>6ZIƧlOpO6O G>Q/gsEsbd3ji-=X^bԅPtzav^,_ 9uKkg?~q };7k3[3Q-N:uDc|^ǘrǸDJ&)& &`F1 wO(oc@:j:FMͫ"u#5"#Toz[*>qs|'3Qcc*R|_Jr>Q/6'n~;_'V''-Wg;A^Pq~MrwB) u<7Mn%s~nǘʤm)\MS w|w>I٠+CuUq(+>}W:G)3_&zi zM _(o ?W!ayi*}H4s90Ḃed{JußS_1#¨2Ҹ<.NK'_ BsR EEnqJSLS0MPBR>"cy RFu=s{.sπԝV\t^;#'gb^;֟K)Q0ؙ:yX*Clot6rpcޠ@8aCw3ѻMNW$7?M;D%4m@7h8 1ëu|NF?yPOMeWeyO'R^a˂*ӵduaMpPKӧն'/2|*xadc(/ ]e s!]c#ޘ~z>+ t:c B&ʇ>: <? n;C_ArC̫yAzB>#_2O|q( 5"Ks=q;GR|!g )nKԹ~$߿lcv-dwq6ͬXӹ Bކ.lt;|J){^+L~ /_1,l|{9u_O:xqyfoY߫K; X̪ޑ3 /kWyS<y?7;c9(ډC̃/fUWW^WȚZցC^nnk7<}ay"!&C/KշŪ7 MXx~ u^M^AN=[9&/YM9e*5O9zpMkali`(2ŀh <#&Y<?re+ʽW6jϽ_{r7TRbϤ,+Ǐ-?֨mtTWo@ FOi= \ae= 1liҔ`gMF.77qLqoZ?B=luq5©Ure[z~N\QR)Z^)]Vn W1\[s[{tk-кUKxUE'^ ~o6w vui'ٿ4زĹnX^FCe-FbL?7.h^u79F9ʪ]zX"Y^e_pfafwW:8'u1P*&wn9ksѯ0#s[ۼ=w6:.MyۃJ[xSj-YOuԼ|vyX1]hҌ*ovبaz{Wp$8,CMm쁎&S܊߸lvwصU4߾Ęy?諄ugiƤÀwW̺o]#߮Ԉj*v|; ;3EU"6m~yIh9_=T8&}X)$P~&95דF,hUnXR])p{PI:n!K q;;njO?jSɥi׬۟Zc97ozɍO}S&M]6|h+~qۏl,0I4ꄒqGS<.6 0neAgdQbL{_P53ddLvZlK NcR^0_Md15dD11?*_M_f_l>yr9ѰyCDo7I2yC*?3R#n;k*龍#V1cM`[;*{ic'_o\#9-R\Ny0VlXrqmY٧wNĭ2U`n}M, #IyĴrlj΢ Rܦa;5hu7L7uˮ^%!&E ^iW1-#ZfN~/srPZ&>_Z4jO~ݮD/[qQX/4']{&aHJ d;ɔMNbklt(٘c8M",V&oѴX~:^=2vMN)pgfG6Pk 6=mF_*ow`&GeZ_'u`T`M +wmYmgQ75p|gg'Wњ!);nJ:˟_ɨ=Lȏ ZC}JyI6? +;~ AweQ 9,%wڤlDZ^_]Y^nj˃(S]-StҳCZ[͘!W[˱Csh5~y%Byj16F%*kMd&ɔ&Iڷ/×LNX n$Q*H3>g$ |s&߫G0h#h*I xF^YlsKg`im~wh&]徃6/;|jsHf i+0dn3xC;Ľ= sT~֏l7Ny=>]܀Kv!۠XQ\omjEeQ'W\"a{+b=u~JW2S~}*!u#Ɵ't&u}GNl`ᰓ7BJca\s`c+xfR8e氼mډ`Wwm_A(~`\QZȤfHvpnTƤ_v.ڱOBf~ 1~9k~dǗ=ΞWy+[^I3ۯa}pd7XNJmL=h3_}(f]"<>=^2-K}u7eޓO˰ַ_n>2pbGK'HH>3rH"DntM_~F;U偳9.+ Wu|<.> 5:V[~`}D(=A0`Z4t  o;脊nCɈ2W 5n )^rFH u`x@\d?ɤy/(&cy{pdCJGfm8.G:~Pl(r.^ [HϱO {D\ Nqȫ_iڇl~9}f}+F kz[ƶz[z'!#E(*#fo9dDk_{Yee]ү-|RY 3ir{tOfE$RxKGȃ)?:Me{`]Wٍ߱ӘcY/KR5(Լ!V1 P,$o!.;6wVUkwjZ*bF[Ekj="jEv+)jKbEyzιs|/)cïd7?}+&ߺ)껓s4Mr"?Qa 1z(~sB_-Kyzlt}lG)fmFnIVyʳEUp~=xCHZc[Q+nKk{DIǨoq;G2K.k~,OYM# ʖL˾e-3YԷ]lI}76󣼡L%7%6֫ʔ# .D>.$ >=Xh0oYc-ܴc#_f̿Yː&Y5VkOnרLzLszd{?5bvO,T⍴ex,q7.cm0jcyG񌓳RR ِ2etBe+~ӃgR[*pH:7J8J){)-71T|̅9|c9$zt3}S"l[cѿJuuVH?f 8! ȅڐ;qCrO>:TXS;8+~{.~<4MUzRt R@"\" J<_FLk\b1e1Ÿט sg%JW*Á|_#.O8 Tw%#BKb+q}9~8astըz[=킺͗81 wQnZa(s8ϵay&(r@JuA*}߇j5 REخ$/0m\fV6_{rc-ǣ P +6պW}{5#OaKy7^@MYk87SucʀG[j9@?ςrQg[@3V7((BG}t+ymcH_J]ZƨbUZĈ7gA$+w+CϬ>߳Ya/B\Wn@Q~hwpUF;Ub>"KWr8zE_FV j U#0ьE X? +'5#ޏLSrĎ3{?mg5m~=5y~cuz&15tq(m_&+EQb*T0K2VcÂ%kG*oavvү cpq )G K ۰q)*‰..+Ii8S2<`$Ќ+2e ]v- G;5l;\-7(&#"2^#k8挩:ށ"cxxgZMM_O-~ Mb#Ci J\v׏Zv",e -ìFd wUd hq.FfT[Z5 %Ҷ&NSqcY]6±:∾Hٵ uܽwǹ YzY#7TK,MN+4?jy봈>$x6&»V{dL'| P2 a!pVamtϮșv1諔Qe=XaNY{([&$^[A3pB}2"J|+1{gI7 F.,1QUc)"s+x6U6qut}sPȌMT>Пx=DۙpIR |='ҭNZ \ܶsKn*vx3kNF7`@sՅA# .`9w|fӉ-kyȵ4Ov}6sN_eߣG41$Hk4[J+hoCr1+<F{3!_[yM@QO9iAccSxj=/D]^x1p;((P=VkJ"ȺhDU)t'c^葌AM3'1aqʯtmߛ΄{f!y^L0;f0fs)CҍxJh%dvi ^w1+^oqx͵j7,o$"IcUsW5~|tGgۓA؋iDլ'8Of=eu=σ1O OJ)Z禒+y;9x ?#Z(%4M_Nf+:R\ ZF}wkT1FjJӪl%m8 u:!`^xQz ;^@Pc͖&0SOJvkffX3$IޒkytZRq GAe{i럈RmeZ܆C>-=@1N7uAOO `%~΍,h_Tmx222 BLS/fܞǪ򗨈0^ɤ*[!vE \ѕņǎX5"YE|@񱸡a_{`5H:u}E$pay1;88 D^ۚ-IY'qAR?4@VX}1=ץ?F D}M)yD0;JvKBPlmѣ:8:շqA6Աnp7W~9(ݍw|!7^GNM-L*),w@0-֓cnߗ18j1գ>>ފv}tm%.FesY}/Аd𴅡]l7xbr z(yY[{fFl2F,MݵjZ;S~{o+u`iЬ5)hoHv&tz;%-jrFUNBT/%NJ^ )TUdՔK;]|Y|{<6npeɕdņ$ HzUpo=WrMA40mcB_q9C:mi*4 ôܪ=8XJwX-=eH%5%Q~gFu^t Z&ToDu =곢}Wdzo(fKU?RS5(*׷1QNM `n9!rQ% |%6]_3Ѳr-:EI$ͲkZk~|4tĢaGitK>~uY}R u}+[;zbdEEl[ ||8Eue*FV)M KZO!?Vic?~$ۼ6\7`Jxu7Vg!WydLwpb9+xFU<3=_?I-^Vp.0=u}[8[@:ҏ4^Ʒfyo l pՆT7~e078 (/(nAGXQ}VV7 _[|NX;Nm=\:= ~Lty}S>HGsw2TY4t|Hþjyg V+3΅L 1bpl zFx*/0|q`%6LEY,_;qsw`6ǃ&&RfG•Am'i+<]()A[}\JJK>0N~FEv4ji #+N幷jՎ%!L\vJ h-]|Yd=,|\>oj;W?1{ɳBN>fgyy; Q$\Y>E ;űOCʀczG%)>3_/[v2>DܘXm*W3VYMb'DqaGY !AGAfUfvH fç<ěۗ 2zږOT3v90*@{܊b cL$i&iG X:T~Lz\lLԧZ0KMQTY:ʉ%y-k*4rǼ-%Fv0d/ԈmQu؍g5~cHGQ`v1BWY>!‹yV}c廥uTt Bj2MW5z?8/LSԲT(@, tR0s?1 aX<,^_0gvT">$ F -MYa躾2l{edkUN,uMd(Cs槑nf6S0}$2zYa# M L%y ڇhBGȦv\| k%{R*=뫓b Fa﷭Iﻻ9$ |$Tn7'aD K)T\ 0 eF302NSҊ=uj*Z;ۇyü¿t3!A_W&>J(31$udv{5H=Ĉ`% ^,C;Kv*?\v|4i[e$D p<; E]M A:ƅY>be` +F2 G%LSfrLʊ.o1%ٸLl91-7 gW:\NW7j+c]8|,=, h|rP>rV/D |4XBϐP€7QZ-[7}Kcu hzѽZ0&=>J}ۓD8#^GVeȁG"} ?'#q n2ؽ ũdb,z=ʕ^ @ w@CTwЦ[b~,J7[zt!%e~ >^!wH0'HI/%%"#qY3z~tfst͖(w^t5f$,($RcOG4wzyAr!$4dysc$ÑQ?ʎ@ 1!18|ㇽ"lS0XKTV)U嵀1^PŠ4QQΓVߕצh1@檜Wnhs1ȟ՘}+n4{~]:#p3qӂL~"JGÙ/[ x Eo1˦S^Y8 {|6<ۭj꿨$=BnSRmyޅzH05e3D %M_y!Ow03hZY%M&ޥ{л?V%m7۟9"[ՕE2[6GE.laߓw.YrE֔X/19}M盏y|N";vt4zYߏ=K޶_J[ SΙS35JGvCDπfDJڵjYO j^Ikg^鬟%1Tq+yzlszBџ,ɳ_KGYjmthj͹ P+xsP-At..ۜ.5ڴF֢/rd?-28E}/s ]|YXt`bheWiՉ8/>w۪>))a_ޭ<}Vc^V]>WjXU]$S{~d&` d~p\cc;VgٵY)jxc]3v~ nx󽶄zLLi2S٩X~.s,DIy9o6Yc+u$yͣqa^kHэ.%8d",jE<ΔbAI[ɖugQQtTj^|_W,c{/G:2ȇgCC!iG2 2؝42cwGjMUevP!*(16#df0z< ˢ7_(0ǣq@-Ӛn=7/ ~W֛?T+%A  J0o=B5WF?2ڲJHn0W*2>ƾtuc c{I1ߺ(0z49QS&DfrO'';oi NVf /8ݗ#_F~cQ`9M"=~uE :=QWTx7ɛ*wuOL :RCHh^$|>Őu-=wtqZ-twoع/.EEK{ +]TZc7 N[[\C u+0е!Vkff2dc)2ҫ={A!hh Dˤ|s2ޞvf%8ڧdϚ˯p{[R{]XH)qh|b(]n`*jϰ1wp~ğ`Su8ļOS a X#hy}vZ6$W|;_D~HJeqh\`/4p1.VR_-#=fҾ uŃ?Qלbpq'8rmIf@RJ<؝lQOb)SB8w6,pͬr9ww A'Wk7P{S˝®GCbvT/+Cx̖t 9k<$Ǖ-HnԵMorf]~Fd3')ЪwtA#uUxTY%h2ߍQ}šYs%^9z{lWpH"ۥgԝp'%#lKœ%54E[ә{r*1>\l|_r`_{:?=XEǭ`״ `ˊކ( WtGLbU,f,K&/fZ%D=) ɥ9ƳЌ?}} +W0V^1|J:u?grk*ݹb="alW8fiGs2z>p !yQG|խ ->Ci_NO?s<1vr1'zH;-=8eRqvL=h'ee Cmǘ7mo I0yU/Zjց;giS$~!o&R4&COzK%4؟1w(Lyt8z&ОDf/by4ɹ' /i=:8R52k$䧼Ѥo{['>q #SAm0vO4+/ 9ِ[%g~ͤ[ rFo3I0t\n=^iɎM:)VSyL'3+.}{׉/vJ3=R~lݍu?\ )ڜ̑?!d!rq4Du黅}^cRGPA (wAv s7/}ޠch:7M{F_\RcQ3:37$8$xaQxx{IS~mpAhL=W8iǁ~bFwxbt=JZvՕTor+%5@$툲*GqlG#w\ W H+ba0~=̬δ8jZ`-ge k̇v /JEdwPdy6\K#PQ/>1b]r{) .2{+[;?{:N2"/E1ŒUdLA_%-`&oF8CtC:v/+7̋cVW2& WvmS 9EZ$OӭIX>uD L|̂fQRj d()A_c&hB&I6jF49gtLC/|X󎷝ˁҝA Oذi<"UA xZ^91 k5Vyr& 55ߍD页S?V9tocL4T'W$Huz#42Z726rԊJzdviom8V&řUPw~_5 "`ٔќwsZĶSL-/#rȔb$t0%G=7b'|AjH)%bK AW/qNHJIx~A/C"*{ [isV9_/#n u0y( MeÙ|e7Yf _tCJEqCg] &Lz %cL=Y8֬{/y;Qnz쨺+,{Ȕբ`WhOŋ赤Ot+$y5u>κ#]b$w@}-۷qn.cotiSX*(P^B%Y~N|@p񘂎rg 'B@,H7qbG3WHuo-ψ1)U"Sb)i&&i\`5"Q3Wڶ(64_ bLX/@`zcX2 YWlCIêO~SƓOY7GN : cǃ16ރj$|30V fEs46ZJQY+Ts`nfiouJ=eF"mܣ~6p!qS?Q+wEF)k:-b%:o!7oÊ]ܺ5d/X3>6:DP/ǚЭPGCF3\et{ڒNӗer ~հu>Ęxثo!͝Z Y~?OeiTrBqd3r]A~M]c֥ե٥֥Z/P?5_*S?q:Aa^NO1"v$XS6/C :2;JG@Leapy=uմi*ƥ)ڎCCL WҳLU@lJ.P4.T6*]I0#3r/շj~rǗ; ݻӛ. Z2Q%?xGyzE,{6^/m;M6]8|K7\` T6=+TW7i7Gj⃩ H>w P!ɕꊡsN | 'K̽k~62A1f =\;koȏKb+>Nlj1M{̝0X![zS β$<2xp)5[gY^5aF]EUpv2p^xnyf!7nv/ 6zxW\}`G[/_y䒏.ֿ;Oup…mo>q=3KW$/k͛&Ne뿍0NC:.l3#4 lnIWDi/FG/sgeȶchX}׹C;>X]r9?%?G| -I1/%>qjAʼnIs6bBƫ:yiY_^)Mi8 |mލ"(맀wYÇяW< i$wTfݣ RG٩{8iXg'e+*|C9CB΋42#OIM-طyJ}ۋLDy5hAθ-VFr3F/XVW} DϡC%G"$h[mJ+xmnU P6X@V<m?u¯,< Oҡj 06 @h: Oo^E73MXhͭhþ9vs`;egKV4rZqpl^TJpܥ-HGO2Y<g{a7y>#m:a(8Iwm߆OF).V"ecw<(0矦N%:]rzܮ ̳,Ji=tBAvuaZ^-mޝ43vxu^> ܏79a O=hHD}A\ܧ&b8s.5wgsِƾޮ*5Ao LwwId;vV\1/+D[0vRc+QZ4`{竭oQaWC:x,n86MIXOiH|-~Wt4V^cջgRzf~rf|AAX;~J[(G;B5B95ld$$Nc 24{YH◤[#CUe>i̪ |06dnH\IyRZ&en,ЌyYKF } ?GuRngooJ nɸ Ŕ(O].5Xiy> \Ve#_:L{Gd5 έ,g.ÖF w uE2GMK0FeFF1f CtE̻i*Fq@o GTR3e0L1܄'Ĉ;6Yl ת3G$xzJջS+hl4"R~e=Ċ%Π:wԀAn,JԘ趮"H0ІM w,{nL TyRtdЁz[|=FlRVq9l[W"}q,;LHxS;)CX+Qպ}fr?!xn;~c$aW d)z^ W~OmLzs`%MObyX8ora6%b )t$tEWm˫ IE@5n}|5'pxW_LJƔcG@I{l3qp{~R_i4$p8Φ~Wu}$aPN_M9Ү8&4#/lnZ]&EVw&h cn4I4cymWHULbEj콇 ,9ɍ~zbcTV0K:tK%KK<@$%P54|6Wa[/[no,A\֥25,J ~*+|s9-V龠a:EŖb !JEsLTK3/d;ЎD؂HXԏ/+g|+59(Yrs| P{g۳WWPPQ/ I'&Ja|'dnFWʺR*\-p"Uh9ukO w:\I/q[5ʒE`4`RPhאD_T'ȿJef@Eb-^()c䕐 _7=}/KurqlɼQ@[. U"YOҍM/]ؾMS$;PB\*5~<&X/}xNYۅiZqUA{H!К{¯VPUށhYH(bߘޣ>"TX3`GxʙX3zȈHo \k!*'dMR`ee_F\GEbQxg5ݾ>_->z\P/ܽ(S-q]I|10 U \i,ƽ*!?ş{.%5ms3|Uska#6ܧcCSϓ܏ХP Ɵ%%@7 !j :ء095|މ4!v:N G^erKq-咐ǿ)[.8o6~' a}Jب]7;h&G=XRi KoTZW: 5w{tEK_MVojx}j`ZQ}{$ ,ray 1}ܱS%QLOho}jd%Ǔ 89R(3T Xso+K_PѰ9u`q)jsWoav'F@_tsc3sWSAL"dpj0 F5@p܍PC8cKTSp#l])5^eIȱ#ݺ(݆S'eO粊G(.dB6&+e5uw>},_59NڲrOo`z ;;}S{0/fsA͐oܻadfT!zza>fK-ZkZE ^yp+f5}:b/+ ;ʫ$F( I Ӊ-y>xX f39|lzFHu*=C"yȃт~qf-Kޱ9tFƷώpOkԲS?[2߰?Kw[p0oZ [$g_N??'Ɛӕ'> ᄾ4ƞ-n(;1[hP㯄앐lRT$;c+c˒0'ز&01X~zg:9u΅~ q}y%rGIqJ|ܭ;)[Vn ӚLrzPN[aBor@mN=WJթy~L% K)i vq5ƅֺPꆙ rSvA!_ZR:d鏎W(9v&yғz>|`F_ʎ[MxF }c{$SS8Wڔ2d;tqypnir>1B'Of`ny`9d S@Z*p_ (VA{k1 c]?unΫ]%xvr~1mԁb ;w;8wnrh&y.  @Q>D WoV~C:Fq)ltx /lqKr&W ַ=/UY*i3ze341y:8v|HK1FNݼaU؜/_pTK1VOg4TJgSJW|˒BB@W߼~p7qdx/X"gF&6yH D._Lp:VթlEWNT0"n Wl # q@zjP^U'wRBo@#@K/Uzk,< vԃ}~M?NH5H3'R_R?NGQ(hNdB\uA܎k`T粛SEmSc& y) i͑fގ#?dӁ<F%JlöK5АMs{` - ʙ˿'Loyї Ϸ8L#ltk^ hrmMwX00ť}^Zw>Q[W 7* qEh=엵SCaέ= o8[URP TLД^2O"~Yr?|󴓁ےx&̨̓_T>Q߭ťF7Y GΛ1']P4!<L0>5#eBp~9!O#|M +s/vytr~#*%e=p(`pCK`ڔmq)eTKZح I BU ;Mc*kX/7M| p>"xEj,{-!zz?'т4Pb^g :V@ wA(DdXZ,R|`*3&`}z*F7XXCv/w >TumQ!iu4j9A4ʞ0 fqÍ ۮh8ZA$zTlV&r%rY}J;^r]m ?,iWà66"}GQn A:v}8JFPJ"(dk2;v\vɥH| Ц(PƤ齏59 !5a].rfMӶf>1=K|hFH7ѥk(9":mGԜcZW *3}cւbFvӓs*rg¿bL}x|juuz,UjcHE50"&2cz=lzY}m{ 3jJ1?8&+8+u4H۬]謃;~Vk3LiUi U!^.'oEy $]]]02SxRa=C?(cK/S^@Q <8߃iwf>gWe>rlk}[ sy[Y#AD=ݛD,ǁnؕ*{MjTHvK(Mg8į= Ӥ^܂z~R56Z-~.fNޯ :( oըx? ä_ b )NxE2F=[4|SU`?ْ\JȤw#E6`jNA|HD*iAZ2JECyS8:J`e$ T||ЩO K%RpE>/xpU֑UO_8=Kv4F?RyxK͝pL*,*d{{~hA~/y(5xa +]2ټ"ō2.p?B1ĽZqFs5:u [92c{G`ˋyّOz ܇%7tF'hqB &ߴI Un]($"<*0ㅪ  YzGmnɞ%Y#=l㗖u&T\07դ+_G 7]~fyڌHkHN$"}%b =}x`܌ch-1RwIoet9A!R K_f%$HɖBރs4b hWo%%7r[_ysaZ}w-~O0O.[tg <31Gڹna~z.b^3;V91u1FK+.5hM^V]v`dg,-xMOƅ3!t-rmŢ!n4?wdLq<2veْ" +q'E,]T42eZn& Wβsbk m/{O2th6u ؿDNGY㼖.QB(xԐL$;BAC~%I梔K.yGX+kw_}H.{m Avvu&'{ )05W^ >}kb 3AjB/9M^Tym?[ϳ%rAW?\b ,]Q -9׳=,S`[?t>`dܒq`_*;O FBn#^["uN&mn!uQt>[ު9: v._51{5&6E XE%w P~Ǚx zfP`(+R7{Y|ET0 U.Y+²y:}-b-7G8tL:la\%ɘUn؞܇ǺfUn={e+7FIdN,c{:^ .ԕq ~{M?yˡ.$,k8'Vȷ#9p5@* O> . SC,{̼CblKgU}R%X2%Rh? j"cf|k %Ȥqz.盧{'V0hblE=iQIIi'6OmC>vI۠ %2U4-5U[-jAƞݾ(d! tfoުϧ6T] (QݾHYG[r%K=LGŽ1]-ʰ-NAIL&-aLBX^hLCв!0Sd;Aj "!\AAEWѽ8L?$ XJn/S08YKGj[*`Uy\>n5+P>84 מ2GɁ:oȼaWWM: ;À>+ys#\`_\[/5X\͞B[YF% I/FJ }Yc7M HWob޳1BpzX[/#$C14W5lbo41;O%Iy<,Yy>5UH^0}^z{FQ{EpxзTb#E%:-Q,> GN_C> (^V4kkM/} c~nV@(hX,PG"q F9qS-TrR^p-;yxqÁ)jC:c>M "}uQ>-MfXa_GƲMQtJyN>y|&G/ VԀ\+wVσ~]#l&9`T~|lKfCx\σ`qr( lZ}Cp];}ްbyx"S7Ϻ"eQddɐnʄ-lx=?0̭Kq(z.N"wM<6g(7 xo7gY gO4?n4=o1%'QO ]:dO@YhƶԆ-umpk+'E6#BLqCܝ~}ݾ<耜F/Ӫr6%Rzɐ),\Գ+0Z[pN2:oHZ_Ǵ+JuQ()gy>*֡!#IP>k^ cuZoṵmK cE-OYVՑ.Rr1/hDh]_~XiG]t8Whٽ5+#݌7f~zFө)FOtٚ'IƐ18%zOc)?ͲVLܰ$^@nO#曵À*fu|pe!* 2bI}q=n:ؠdA85eÌ 0{S%*B[*&&}8ς]F[WP/609jPKw. 3-KF `F@Q}{guAO"|b\+8oi{Yq>*z6ZgZSR^gCJO}]T0Hf5l!$d٥g$T"tŤJ.d|9siʋ8(}.PJA.!+h|F܇5e˿%\=X e\ʉRZMSPT Y0G5aP;qO K8 gkoؒ!$MHf h{v}-wyq2Έ`@܏;Q9܉Ƅe;t6Inc';%|# ؿ|ԶA! 7Lgp݃^lg nj$W@Ԯ4ۿxspQe#4&aѱwObHyEzzϨ%3Ս/9q;.%(7j7ّSôuKRm^?|xOTXڱ;ƺsx+cl>|9Ky5ѯr* rŬ56Y [Y̘=:{Ba?>oyakL Ĉ\{$vOjbq~"=|&"X0m,;.TtdG*k9'8ؘJŚi5Tϫh2~+XF{9D֎/Y9rVtfX>mQBYZZa=*f:M~?B1ݍwoZ.*o]e bUҷxZc*ɔcشm%qB) #!q59‰A!Ϙg=oSᩦ2E: 3˜݀r0d=A,`؎霎gt^ɬ_+dBZ^1l 1s'Sͬqby EK ~񑍻]S^_5+Sv-q/19{a'tG8l]Ƒ( 95O=cդ'ɪmKgu9Y0`D;x:[X$Z΂g%Mb`CN+~[HNg^Ho_}O("a*ZJć{C5$qoDu8| }@ PN|͝8ZV ۫It/3O*q4*{|bݟ:gaOϩ}]M1YJ{D mfkRSM '/ _&?^uCWZ]lh/Ԕ훓_[)pL5i387U%Ń~,F CVRL/O`+U'eQ_ qpĴmr?,˟ya\giIz\2l+g#..?OߪF̛F/1@(Kk ꥰCIp6Ӟ \7FVOc`mW@Tj~7PK02?k/b8I}JsqN W%I9`Sr}W0c#%mHB {*^UЛ^ͫp׌Vx˖?i3")JOOǮ-v zOZ` ڞ!'W\і޼C[†ܛo|`,ݩ м1U| 8Z8yr$푴rh H$yZXP@ӪQ-Z#/Z9D[wjٽbP]̽)2_GG .(GYϕIUnpWCwwq!?N SjpJI-k7)QHteImjlU.q"KtuEȏOܛ wAY߈CSjj^ذ譬J'H Ev:z9T PZ\r!W>nb\x^Vla? TqG,ns[blE\=AN`ck\K`/TW ]Ɯ/In4QDy,/q(a ͺnZeʺ|p1ɣt\j~=`u"O^x>s,+iqi¢MKշoJ&QPt'a> w} E|紐@l(5)Osëj; }9a W'ǶSP v#n3xF.mQXEMۑ|ɏ_# $Q+rb8t Rv7  n^>Rs!KLh;mn2Jމ hd=?/q -hi!wr NMcSHt~zTJPHbOEKb4e6}^V`|30N[2,Yzb21 L6N>vC|p9{oetW_#nR穒3\yLpdWYܛR&EgbJ> v@7x#1 @Z$<Zw̞~Li/%v̝OͤtBD=}6Y' )m[[HP-ҬG QT8ƂW- C3%RRe< 3YK2]_DnGOk:u)Od)3Q8GMI )b$~'IQ'Fx $+Ee*E l> W=m# ֪2C)cǒU6sKBXe`<.F([m:M`-B{Иp[ 􉬜i l'B!qmJK*VqFvJ|"_` NwT!6A]1~xa`8/rI>\ϙ7KNQzoÙ9ndmQ}DHAf^B^@Z! p81!Oν3P+B20w4O TjxkO3+I@ T[p`B෍1X NG9k䵔aKq|o꧜P}o/ BITR{F ]-#c*l7+ H'4X7_^K, N6"6b"V|~SL[YD_nZO(5&Z=SSsod.v4,3o9LD_^Ul"@tQ* y05!*5/d]KP'!/-[.%gUֻ| xs]|q.|1uKsƹA{ItQto;k-]I-K3JT#%+^t;j]з ko$-̢/m{ ++q -1ޙe3:s[MZ5 ]\=3ע(-`q;ꕽYd[y1${ 8'Yՙg:'ڛOAnǵ/z+]H.XtQbPgj-)S7Ʊį#V#EXX{6 \wlΐ9E+C\H`=>PBIE3@>a hi6[X >Tm:'ծ&m&vQQo]B2xc38"Ym+B/qtX\H.w`HEe2G`n-Bz[ޞ32}w;Ny)cZ.$}xȅ8T;{+՞ز>=,\9P'qs]|[b-ҝ ^`\xNbv~Te~Yi4 $ki& T!Ёe`4!$1/!ӊY)d2kdѤфsJN=9Oϝ: ^k[$\:kpi\hZ(ر 󴛁Ujd(f/+ӁTGu\8Ft0۬Zc"w{FfztI貭1`JP6y컐i²\F} 'dZi;(#+dK,7fO|RRf Y+{d';z)k^6sn!!g3LnmAdAćO0euÏeJ*essΧ;9]B n%$=]2V?"Iq *GsF/r.j!nu0#e Rq"nNYAZ;VyFO1F>, 1 *{l@(Ҍ%ڂvpq],/ߞvWgǩi.Ss0fhj=ոA l+Z_G@ 1>VMhӶ;ewiʓ '( (ʓ~ƿVםWIK* T%(ƨ1!s9}bn28,O_"9u,!N]_8.% SvO\x2b!K'h@1蠛6 2 [bAs>$Y11H}ç# =É;ZK%?C[x1cw KnU$fY W;#"cAk1ՁvCyu[O8]Z<`_=&7b} ՘aa76cj#V`͛OaPh-A7' Pf[ 31ޓOeauax:I&5+#-+5F굓k?7JRg0>i8Ր7{)U8FjٰK c2rk`>0酑Fg P] K`dm|ir#r8wL#U#hKj>=ҭh~ʪXA hd}"P0JW $ƤOU ZxQdn" ~jP$O^~y Hw5`CǏmrx*v$FIO Ս扱't<%Y6"I8Hf[f>+X PmK.xpjN+Fa% µ퉶u`fsSxWMm_P W,Fy- ̏M{腕;Εnrɋ]TiಅS@[\[PkK\qs2vHhv$`tY~7*TSPc׵vʔ¿3vv,_٭ 2Sr{^ۍ8|z_+}Ylܢs:"RnF-$uf/M 2oWGV,^zͷ }8U7Z3zυ%CA%~^&^iYqur\燀rR'_֔15,dweۤY;ǰ[:l+Z[t^Qsr鵔N>Lx5>myTwv-5T4ԭߗ?ji?(X-;˘6m}K|dN§1] eaYvk-+Js[|X z#۞3'339e])RjL{_qѼ6MU8Nt؃wUu%X,kW~#G~m,V~iF\}NoOjUUk~hNe] fNtCU(G|r`ĺ壆&ЮłF.%Gڰ⢐N10!,#k\ kr is!Ul^-~9oMR<*$zzeJfl>;|a],&0Z;|*m(,c=A{vV4MJH߱6sѧ!w8sR㣤-rvzI?ǿ(˰j;f> vM79>ot5q !J5D!, )dC+zbrc$*w`,eRŇ[ < / x'^HH\߃l$xLJTgrۅg_!*RpО9_I,VnW?LN+zA?q:i C3gjTضĮqIsSgw#̅4tNL0g P y d*g#>B[t*crک(>lș~/$~ޱ%)*|ױ8!Xp={/eK_;%Oxl4q l#.yEtN`zaW*K;AϭJ 9zB߷" [3g% lP\j)cEvE 1$vAA2vgŢ)IeܳqK( C~+]C´ZnL-Yf3 ws|DZըZSݲڻRҮn3]<t#2zYhd+^lKBIQ aafGKs:lBwtx:C(ɇwԣU6Nf~1 @&%kAs8 Rfq~l.6<"g_T%clEs{cC<XHbZ *SIR&Z]w]mcVWN>Խ?a8$o),ɨnkœd[ɽQ2A{B~qhz(Ff20HPvP7nF=HjytsW2xl$GۉqBY0{ﲯqϔm>hri}薡4qFw))5].qxi.ޯФɆ2k%{t|]?(+[U1g> .wX݆QLLH+ rdѼKQ׾tn:fVG%C |.;&l.)ʚM1Ų U R\|Ӹ)5k<|i`mƈ&v,6^yǙ13V`sƴ)Irglt-ݶ6\_G MÜpq{mT_iPhS#.&5*%8QayeoiDAɾK<9#CŅlWW֥t*D ~r3' 1G;pKR+E1}`IM5gώ7]d̥eCK|{N>Ė.덹S}+X }ˌ&&1E)+lJSٻ vCl5r 0DW>"fpJ뫩Z᥋W3ٖO WDkiu̻xb6wYWY5f#"1tr(B]ͭdmvݕ ~D|h r+e I @MUx:7j|7w,B$d_fTBmҔ`e ![QgBfgXgd0f0<9}y{Ͻ 0fԭBҎ/nOUd/w8ȶڠY-DiX` NKlXm:E&lcvbћ%/8[FIw@g>h)RõqQJ@3>cvdaqs0pw=+ 1P''}G/5*hM7.,cM{'!ګqkl<˃%nIxzJ;,Kv&6UP-K-IXe5Ύ3Ż4 ӆ_gUd Y>E;ECpOg/EN$$ZpձX3;K(*\Q&Њu| !07nCÅ M!'4C8 gz'\rꂙ "E᪜E.* ɚ wv!R~ 4&[oV6F2^0wC'sNX #fae1;\qIɍo+jUqDmgZNǾQSc5jxʨBR"e _b-f,\~Lja81Zx^5vOj''oTnN1o'B,?67&<!g&sJK:jҼ3T I. q6^kE'uW㙿/1Z]<-R#8f5HT"M%KE :509ܺ} g2Bw4靠0PJzͬtYUaVX7/h2P(=w8Թ$!W@9 * 1b |XW1K ^0 ,+՛=wc gf09ml5QN'!bհ6x5vBwF޺qG |1߼Te [[foT}) <. ~eǮLdg]Pm% 36ui&9!Lv'$IcO<8qdd/>}%Xcѧsj/:~&fXvo_pC)bJ:H&+I{X:Ǔc-:ħ5\jS:dWmV5#/6]p ~p0:sCt^1}͛"Yqj= VcRV"CcKV;XRh`qo%e9A.v!tȵ񰩨:}s#SAd _ nӹb=&]3>1 ˧ n02=d9f:MQ4tOoO7yFc.9DedV΍9*qӟͦQ/CUК6x;DWMw%H>X ؏I[ApݝjTҏliUpOqT2z) 5U3>cNUEe/}2 oǓ,DU#fc)v5CS3$𷄘X帲HRH\dzUtFdP)kO8)zᨷ|4NXŷCwr=xXD#< l&xh]σ-VQnZ:WӼƝu=V8S "Ǯ-7˱=)L x$ ^64~V&{•о!<6cEeGl/TؚN*r\yޥܺ >c)L9e ~ N ?,~Iw@Qg]|$5A%-c9"ѷu#)sm;+.^qȑ&+5VW|Z%9ѣ&q,(Κ!]vִt+1_i0'3 Xnk7Y{rZsbJ1en Iv4S%2n= 6kBQ(7ASt~jpR3X`4h #黁34Pr&-oğ$u?0T{'1FCN͉тoD̮&VFjN46bHZGO<#H~|:YT,H{-S.U[ YuŹWpne-tl.sRXA\њf80LشS[_s_'km|ߎ{ ʂ&4P0{kaG3&7fnl9Qg^ᵲ[Ƿ=KCC0i)&+d:g㞅\)c, H"B@9[;trjѢܘ.L'tWTC'i|`h~/cPB'J6]n4b  ݙМI6t7\5 P Ru↵;VD)HsfڊBdf^hjќ)ƹMP+Y `.Ny5Bk Ȇ qmSG³@rԡc9'f[_ _i0ZW>O;rGҮlcVehoҀz)Rjݺ`8nܽT]p3;4cV]>4<=n⹗jvp($ah>hhdedb.^+1']#`v\k+Y)r%&fxqLh+$E$M08hbCCfr{:sU`ZHҊCnb`V3%,BUN:P{ iExԝFMJDnJ>{* ;=GFaiYյnpRm53B&;_|'-1aO6N+߿Ѣ0G΅|o~` S:KHM㶊=4 P aXֵpoccj>Mױ%HRxy첌5DNĐ;;4B5LJkV^ޤvWRoKӰ:@(+Wm>U=zā|OUƐ/]vpD~AV/kNmqEV= QC&ô5G|b@Wt=z5c]$5;ߖqOL!} :Il=.4/׼ S6kW{6+96 uۧ8^5ƗJ9{tL˯q\|y E׷d9J䌶{6ةA<.נ\ V & ~=2sy5~K^[Q>&ƁgBȦFCwR934 Vg2m;pmv>lѯVF)WeC`%9, u,.ƅ 0{ތzC1J]@}nGx1%+8Θ ;jX2jR6 01 YAa.18 >ε&Cq4R}ڲxQeT65軳13v]>vFS)h2I~g1at("]xZepV-ZAcHτ>}C 'vh- 9úv3 9:ɕ'꛵z~ڲqnR=,Wm#ax3XiHR&%28?`hw w"OqF\ &ga*g 7|zy\cvJaEwis3Z­}2OT8&D Qt^2GZO& l${X*㴱xf񢈸`~T_;oV lJM#ŊNJD%zؐ&+R:7vbt֓))6߶%DNJJf=HvSt&&+FO/m:eіGU3ʢڔ۾1Aaeִ~esg)b_C/ͭFHi+VVV><# B@_@}oF/Muv7K݄cAr ݋2رĮ򀧍_ڹr#5DqrnBHȱsѷl7t2$$[ m[n7g/m}mQ^mD:ǐ!76kW8XA']И={^oˡC巍onRE$^WYȉB wg-j10d h4%q)hX- /? +EW_2v(P.*եcq=QɇāA޵!!6`p @ &j)}m=w>\ [ Txн *ȵT~Ҋڣ5:zD@' /ДpYuLNG(?lNU݅hsl3h1{ .R:7k A(iB1 ,Ý(RbS|vq^-[\T 4J&F*v!zC\Jfa\Eil<0\ R;?&''.7uq5E$JN7mSqm.,ug EFR9yDm0)bSQL=|j)bǦ@.mx8 _4 x(j 7yE` -kQۍ =)4YpA‰ϩ7]2VHM o6/댥r?fqUc]UlC&3Z^{:?΄W3kyKؽxO~Ox[ll Dib e>,WQaxyi\L\foGpQ)ne.Q ij ƫ # Zm +mFW!!+SzjȑmF{NzswU:*q||?/ݳ>ˇܐCݪN6 7.4/^.h #48' ;vmgf 5W_+F)<L @?-zSG1#RIsA{mO.뾠xoNܙj,v\Avt2+rEDk_eVSaN-LX79tޔO16pF`6ԫnnC\\MɈboAv.2Co?$~tYDa4zJ2ի,_3D#CL`^xrprI>sd?yΔ0F6iCEDh5T˫-gIZ:soGm<n9T>Mqjk8ǿfzG:̬fjC(I:qS1~A?]g /Yx|DE봺=|*HSn*׹T_ݹHnɬe筙KAUY!Ϭ迳fnL,A= ʡ-(`XIKvlWiD2U5DjlAh6Mꂱwˢr-zU(CsÚ5Ol_&\5vCcmKk Ȧ0 h:+I.0͛!˷~%=kTnXL5S=AX@={e1* m'Wpd&J1*gʰp2_zF/,Hֲ,aȉvW7$Ƣ>,ͯDBF_>rKٮAػ{i3 #K6bFm%XAH8US@rGt(zO=䒄반xF|esZ"Wbw\gWF?^ k)<Yk"YW3d3e5A%)0s|DЭ٦ƄFRZZW)f;ut1.sѭ~s@8=^Ǥ ШJ>=)J I?~_#m+u\kEJu?F’ւf<, Qp6B yKl-IRO0hwB|}I[r).ʟ? 474EA=VTдFւ_]Lj+vW#}D%'lq+Mwd{3!4αٔ`ڴ2KM-"c]Q[k uC+))^o|9BsMopW~ g6D액)/b Š'$iXbb,QjCbO'Cʳtg+J@u[\ 1‹6PTsa씯nRiޑ<|8M,jt|>>|1z[>C:1) kxρ{ڳFf`(&r;tᨯ|s@;&7]!b &ȂrsL3֢*)8Xzo? < &c$5 9SVy7Aڴ | aT!,5 nDbb Ԩh(ʨhXɶS)I sdR4ciYqI]5vRцt9ȃM(_Fs+2.kL.Pa!ꝗiS_ j(]IP+fĚyDdy+[uLm  XM4!*x{obe.&*n3ܢSBG+ި%Fgl'"58~/F&cgYrCK3 Swڮ8xkdg3Oˑ}yΊWsS73S;s(N7T($pL4|n&7\AcE#BYvH`ȔdMJwtFJJDrtL=/w{]Sg.]"|')!v!ԭeQ6Q6Ѥ(j⍶6X؞1毑9Vݗq}8gAI!I4iB~㡯9h |M$!XE쩿/\r+CI&bm۩?5=JqNձm w>G"UcE&8j9I:LahD9qUUsS~e+їbz+8<2WQS[yuaZ2eLmn #9AC[&8Wߌ7_Ai>蠨A%dPec9Kw:苓h wVoBS."IZ( ƻRon[c]h̶qQnnYuUg-Ɋ 9ȏ$1F18c 0-\#϶q9E&៦1ns@Fmo;ogBCK_畧\%-98a4DN~7+zoRmz25`yפS_޸GpZ쐭=k1 ]xRg,RzD>Xp鏤T!&}KPVj:'hz1Y3蚟rGp4PIL芺 )_X^K`Jن_A(g|?Meg=v r7I&qT"a5q;cL۱?pm%=Hx$gc!^Tm{ x.Zt2Htb޲]k9,0S%m@_Z=z=|Soٟ,>HK"-*UP"FOFum~n#ֈ 3uַ[')&̼V6+0pyi^hVh(㥆hkqKg)f3I-6%o۳8w"0jAŒ;'7MHASgu@)vB}1:93dO plP7Fr$dh Sf>;ПR 3xnh~yIxOf;{+QuWZ+AˁϢ+V8!(66mxM~duQ"B'sh}(RJ] ĵ Sjix'o#۠1cn+i#Qݔ?>mNiH m34J/~cn"1 0]|g ?]鲻~h7MBuyEnqWtJfc/C om/:'oJ" ߋ[kJn7fUd5вIV]||M2rl?^w>9gK_{V?MIJIԡB bVS(|BwDfv1̆MC\b𜅿a܎R`n&)%+ H$:xP p S^i?̿(̑`C&Do.ű+ s:VrriOlfK Z'62:{2cׯW2һBuW.bk Eo^L% حXr7.MĆ RxDӻa'whY|uI"%< O4|'11!b BKāayEUNNjt%[}[xfĹ t!a=!=ڕIHcb1 i&~ץ~(-{C8MQq$̘ 0B̷0@ dJͺp`*>3_^'?WMΫ.=^*QzTuj_LYa~X\ͪj>KO&u)BT>w*̙etY5.@)qtp{ZXU[_{]箱KTLK?Uѥc`[ꇾN;ڹ}'A!+~<$dT͌Ӻ' h^qWj'_US@͸Q.hv Xr*kPVyh9*?V-s_ ʘwO` :n=|29ՍYsz";zy38r˜[=;+, $x͙lVRd*qFtUK0%28xONaDCqȁMMBM |n;kzY]3}ҀYd m8-4C~:3.lf-KYƽH:^K`fGMhj#MmݶfFn:ꞻ{?ڝ|3ؽ61X ~Inmoo F[` 4$VpE@+u=[2Ji2Oh/PWCGnfwgwn?f闬ӫ(vHY.#FF~-2b^uÑ-E:%vg~~Fqb=AR"K;v};h4^6Ö`/G} 4l(s= yIl]fz`Fw MENJҵ%7QBw1lc{o-  `FZ I.5fJ3WGA(e3JpTޟ݉Je[ZvbI7߫hf1&N a7al#"zHo๚OZpL&]! k1t5] /r]K,NNpc3׋+ÄDK"'#2]?ZWXKMpi*iKJ&;\4-ڪ;%qڣ>"uȉč CznRsz][2(18C'בKc=WN8R+5/ %[E@f#(c-.Y>?ŐfL|EWA+r6W@ Ej}s,?J9ygگ?d!F*,lP0YS؀@}R$PYCx|$a2ÖRV}%dBVR=__nP^h#rZ|=/&)*5c=w6cZ_.Ԟ/H:e_ }3Lk{fg0y6]Xu(+'BoDhW LI͘$U| 7QB0J( R K9.2p<LjQ'Nߕb˴spKH]+I,)M.E4WU"OZj2W,k6(MX-ؘ=;4_ܚT(2:i|z+Fq~z2*(?,:Ρ/@:&@HOPi99UJW$|2~J#ճJ#?4JČV[֟bZ9@cO fv1:'TBl:PަIth|daDVfg@x0dXk?6ܵ\(ǻ"S頛UW-bNۂ\eOe~?^|)#}Bq fi8ZJS#C4D_I/~7I/}I鼖 ʣgKh$SKPDڇC+V>`?H-(Sfv.p78j%È|2p:{GYMo(Ъ')*%[)II 9GASՔT`=۔mӔtΈASƅC^/>~%31f5P^ % S<s1iȖ-,d0,Bж)8 -~7L]-.,ZWrsasAydF0!wWg[ӯSD,؂}Xej| x >3os$U.w.$WeW|4XƠOͽ HQ, @ q#S- ~_Ňڮ[Au-˻{Ų[$}b ǔ!{}l2oTl'sj]cY2.Uκc]6ǽ7ߌ^;}8-P/ ́HCX{[q<4rY! UYN N|@imn,^MWD>J2 *pU=`z"lLW`mVⅦ@clc@)+ ]?m>+,:, /oA 4/ je,c ~qSL^TXɰGid1ټe Phtue9uF0"woSvY2[V~j;0\#K{Įi~d'>h!K穈I$O͌mJ4'8S2vrx[mPc+ItX3ka](Y \6UU L yklY.MH7%'UC(Mow|V@]Z{O+$ow#TU ޫH<^1UMl&Etڹ'2) 8&rREE'p# P q eWI9C?0K7-NVj#6ȅf o80( ;4>2?[/eS$s>47܅ T$ly4`9iJt#mNNn1ڵܿ yuS->1B ׸.g7s0F VjI4ɤeg[-kJJBm-d3l/]wa]nN=QJb{=U3?pP=UT^f\\=풩/#XIB [2兊KN2ϮhvGkw<(afI`7DR1Jg,k".D>8ϛ{lڕ%ni W3N4g6O ('41,)YKfovu_s~ r c\q?ةP<=W]qKbzi  )|'>EhRӨr3Ź 0)Z:jܷM- :o<\.ʖ ȁbÑTת$o]\#zvMY˞Cveɢ5cqGmGQ.= E XVen5U&mO;W!ۂ ?} ?73/8BCbZS%hB\i;_!UҏAwyxд(먁pnA*PﭻN ]g:1Cqj\S1^)Oj$(&(ufkp1_wǿyq{>}+c@]dcQ}9>'?|i߿^<_HmwIϵ\q>}?[3/<=DR/AثY-E+QԚE,! "X*j'DmQ-VVmI{>s9yΑZ|y\kfދsr{xQ-?b7͟o|>:{N[^O/Ϟ+0dӉVl|gL8ǟr^Wv϶?ڽ'޲a35nvx=֖\xYOzpʼ~G>q<~'yA׷xgs'{=x-4nގC} ~jG/+ïy37c&9ϯl{}>wN_A{?W&O~sI[\ ;zӉc#Ɵq={ׅ[~Vpy-z_^xi=M龇͹s^=xGl7{ 6ܮJ+޴\2O;{\o̤wZ =wY󷷞G_S+Gß9l]_;CSox߰uߡ:anjVyk;^[y1.7i߾=㟹C6ѿQ'uɒ_~ٵԹG=?vy>澛g.wllփ_??=wNHC ǯ9nGo=u%:a]u2`g {~w BkG=|o?^zgܗּOXkW-ÆsM>굟.ֿCjsnq'wݦWxwߡ>#v'Ԃ7Nz}^rOopެ.#3g>X*÷ט.|lmg9SwSf}FN`GmO{g2lϳT/{;G ߸/m=^z2|y'G=P傿 KpR>zw9^r =bK|mV:lXu|v^>'x.oŴT:,K<[7pRM8G?fOŐQƞl֔,wfo1L9jɜח~niqE/}ݎG {vO/_~M!U,bO6lfoq[J'/z 3xwF}rY{ Wlsa#Vsv?[=rДL'),C'ysJtqHL;"l+ye_NE-8}8ꃏ+Nj&~[m=g b Uß>.cz[<O3f>W|q9Mz}ǜ䁯o?ો>Yy-ݏY7+3~{^:r崑Gn4SW{eZ:oiЎzNg77yjn~ɃC?y&/\tߙ;YʍaO֭3l>֗ n1?洳osW/a/s5[̴?J{yN}l;>}iff;[fSL>f^_oL9x9s;ȋW{xIߤ}\vɟ%n}矻s6~d/~v~^'|Kw?0ڻѣ/z_>ᝐoXW,337o/9_8j#q6+zv2n7Lg+s<}KN?|#:e $/~ן쬍_~fc?6c}o|Ώ7?ŧ{8y֯l3ޏ_gF=}+zԟsx/`{O{5]6?bqJG7q͒}{l_Ԁ768ZsmĎ<{sw:ngn'#W>gO6g]>-b^sOZ35tn?:G-vd›27!xo~+ԶcW? s 3ﶅ<> U[m^36\^L3dd7;R߰_>s{Ng-iϫ=.{J/|~Yz-Ѧ:e9џC?Up-{Nsз?x3_۲^ zr%[з̸/ƃ#?fO^޸%3x<7mfF?m>s5] FN9.ú8k]3~缾p)y.#2r#G}=׺uܞ;{^J}'t{>{!!o ~}SXqG?uylS&;gВV|o6=m9lǍwgsSv}N?:bi˨+v?:RAun[<VlL`'9sҐF!kk8cf>vɇ,raճp W}b~=7nt:H_ꗼGAYM^iP'=ozƜ1 L3q{|'~c[-˫q2,N]O1Ǐz=vZu^nQ ^;~}y)? lq%]@6>{rN~6lէ֡O&|ݗ1g/q%{ͼa߫5kVt@oV,#EA1՞АWpkI,~ݯ|?;pYY~k??<߿o/_ysNxpMßvjSϜsҰ{OX6lr}-<( }]F_E_пy$~b齞{Μ;qV#`n;料?vۥ{z>ymn7~?\,g/iGʝؐ?=v}mcGn7)>>!o/ SSq3>T8*_`ß4}2{<`E_\xe7o֐/p#yb;G|] /~J#>+6Ϝ?Jy{;WO@l;>\4Jk}k>!o 8{Լ.=/tFᨇW:r s͇vnuO- 36f\ɣysւ55vGtt'GcG}>X_swXoACZ甅~SNx`^L):]ڔ \g?e2 >|hh>Iۃ>>=&oˮ{],_qfnU|S'+]=ϟ1 ww+yiӧ?sfoڃ>׏Hp=G= gf-~~cںqdܿ|ǭȷN.ie]OcNym%S' ǨkK{:9ũ|y悓F,Գ^8i { a'=nz2|+'S$:ڥp(ӯ]b뇕R?~C줮_wcY!swW\tv L[XХy^'u(}Fl.#|]潳|1ptq:&R߆/=za٭&ŵ}%[˖쳠Io 7}ʐCVinmm-E[j{?{GQت;l]\Ο=ϭןE[tKumѭ~oK/N^YW{59E~@7͟o|?;1bpiŘfUj'kRZh{l*-³J>#,>?Ii&Jsך\*VeK5LQWɺȠ:LEq.nW_J[4wBH62ed"3>P\I*^xbmڣjߜj\%VDqiieBhKŵGy%( d,˵Wo缊\sBz} OX%>VuE ~}s2#͒z7 /+T<'[邭 cIaJMRApo-PsN1E[M{ÄI)*03LȫLdWi3~<"c֜9f!irϦ}9R6ƬӺF_!M{pDk!++jMR[s1Y05՛P,&aLxJ\ig"j‚WeU(ɳ L*(__pPa$su27f_2UR$\VP"sk7evrV#wFdD mنz53AcuxB(g-:1LBNwUZLbxٺxf@wB(BTpw;hkw4,X-)E}.pI ğ*}N`Җh I;E s+ۚ\gtCƬO\#-m{tg$/]*BLl1(Ľ|Xa#0[20#Y5NX dg#8k{T(UȄ2M{F萒DB$w2fдGVd0}o_REΗdg Y NJ6jۧ,e)Q DNETa3uPQ̧BȘ=CRe"q= xVf/6M{qW4)dK&m:;,h5=+XeV`7H$*e׹0`B1vdLG`O1mÊSmbJ~i IAg`%dgE|7!蒐%@ kdg$ʈ4N@ys^pRՔH(-p$8 @*@C8+K$jt,(WM{>KP^ۣ9U!nӞ[[V ɭs`( ༀ̴+$*VL )M{9 '`ή!@flv|]`mMPؑ)4$`ف]g@(I``$LEԴ^rp`gJ/FƒU8 x%^ 3%!+#btNVr Cc,YBk ^L0Iд7aj䮈,%B,YlV*"N:z`)+%OM{@FY8hi9Tr(%HJ۾B=Aj~*!x<~k@R7uX^Bh%D6L`ڴ>D8W^YU k˙ iU35xގOkQO9`#<- Ѵa8Gkćv2> $/49B3_viwdHsR6#-,!7G5 l,!ٌ`} RY:t;>pwL)P!mdM9Xe[Յ>_H#V0H k\%8qDhpF?t/v=?d &T:DUxID?i PThi@?ZQQ'Ê!̴@*DE V"L<Yo(!*r+3E>?R;$tUNk_bUBqP=ԃoL 7;+{_d!]1̮3DB/T\51䐷PrbFƷ i*`n <~;Lh$^+YZPD@i!شl_4Y@7$@̦=ŀ@_ 'b&xՎ U$[)р^m<j"|L H7 L$>'HC}TJRxyn>liS]Ɯ8Dx:UG ȵ0#kssraS`=Cw4b\jHpbJ;i_ dI3Ia A&PԶ?1Z`]mU1[Fh!ak)m`1HWzz^t֛!p̬1( +A;<jH 7(ipIZMf4V!Yˊ`+M{sH,&Zff>cTD ,kG cPń"]1Ŵg7v~=txIX."*1z/f! 4=J!,ui#RKD+pXPxPR@)ݴ5)XjPP"!Бa첦}5v!@ |WJ.72.Tw>yC1BIW6 ;RY|u}FD2I'M{{p`BhE&CUYLBʻsx "KnO@28vBbB{O>GHc' XDV{}e',_.g6`Vzp5^QdD_5+"b9rqBW! ior/g*`d1 .ыipF6W.58&Zi;0h` )Ax xސbN keyi@`_c @hRaCo`f36 l p;AA7y HG^]oi}By#lp Dhll,h?O~ǚH]8 X|jRzi1=x9QBg;폲@[<;C< rv|pDt {C@#09<j-12Z|TZPPyM{QW3CUd9OIHW@*i>!m<(bHJT$&t>cR]σD@g1i#2tW WMm 7"*h-A:B(!3@Or ||5)FkbTZ(. !Ui(r o6z`M'Ҏ#m<$!c%Ca!xyZ.w  sJRb^P*rES8ՊĨRԶ3Uh8G!M{1/4 **/m{tV0`)Wh TBDJTFa(؊m{EH(DZ Nqa n7R W k!9Cu`A׺rom9oCͩvJ:oJC)G+kuٴc(ڦRia0`ro\D5糇?TjM{;xCBR A]z?F&$PYUϣhy5t7Ζf^+( &v Oevku/z=0 MՙҡpM NovH2 T1-EWӞ*΀yȴ}aTJi]}_$!^M@wx~VhuKQ8P̠.3UkRvtjfɸ3.iij*bمT4Go;?M tGh;Zo\}s29#by:i`~ ̯ߴgȣÁ? ')-~qHY(VTn^zӯid&~X`/08IWoƿltS%r2!mf= U )F*MK;JCn>pށM@+SB+ ;8ݨ/ZGL5]%.KBjbID#Dvzl[B6፫%Ie2n+)QP@!"oi Zm/'"P-H1JM[<' `+` B!T!fm~uw Zy˒jer6Ȋ8YT2fS5BYd} Rx@,9@M4PB 23l63HD|a# _bk,B@B("#oCTCPAb}~vX`)25б IN%a np~@*$e KáiSݵ`tLA3 z9m_E #儌ܵՆIC"4rrDmԃ6#`f!Mp[|>'Cg5¦2۪B90;^Hd&;: aHfб` ۷G#"kZ%LU!%p)ks%gSvh;ރQ^]oO{ !a],թX sC0;e@". g"8r{#_RᎠ3А^Z&2X}>:DW$WƛM*`KA ZuCo,00yAM[?R! ANTKg Bt: L Q&@ (: g[Xoy $)!d <EFgdb^h9H2`eky+:RtHPzOR\h49 GKj/\ $Qٕ&ԣK "<S! {0G62ФU K D* xTL%ZT WtBTt|`$\ ECAxf^:*a\=o:OUpk#τŎis0zT\$7xףRw* }p00TuLUSJhzl˧BØB"IZ$;mp4-?jWX  𛪒0dq1 T<^X|IC(X0!<hx^(دmHѕ-Ah oweZ}wJ />U؂2q$aP ev@ҝ n3-3 !.' &l毣ö&g6p_KC=Hm@UT'N] `Eh,#BnH 㗵/ް0 % ݜ.~8e<'ksO~T܂W4^VxC*IkL:vyg 5ȩau%$Z$NsƟvhet6iPkĈR =gJwLh4״an:B;h:ymz.ʁ547 6CumJRp:é캆< Dl\z 4|){`k@AşvaL@е2C"BB[~h׃C*];9~9$AdPaL9ojǟ)˃i1'+=}s')HFrҜYQ@4sXv*LӅA; PQ 6`v]p '[da6i >(dѶ:v L@e`6x"du͑CID1R:3'@F:ZxdĨ`z:=@76sdv~+&4G3Tp@eFNݴ 3` ݚCghBEӎ?4^' C @ve E SM8 UۥWJtY%^"\AFJxU[`4: :{b/zELR-ހNB::Fu;>tC R^әj0^V"J 4|qɨ~9:S ea*{I 4EÃ>& ,Hvd+B(H^`7PPcrL;$#]z&@"JINt9 -qI ֠ST}Gx@YAb4 1:c]E8DD"B|"o_3tTN]9 d`R *:'% FX&h]'JtJNv<%Uym{TH%Xt~'-4-"e *bʂygԠ^O$@٫tW;ڝ;2#@%L?498݃ӋNP蛞?04t,13LOҵ\oAlS庇MXP|I5@*݉'D..>JT#&w~d~ӎb2RtEC犐 UXGN߶Iap.wɲI`]'eTMk/vlTDh`h_jG$ /FAGʚ,m~YN!i*B ḡg *N56n X3zJg.H@ǘ#s:G3Хyik-Cf@S]m{Tvcm: Ct*otr~ 6Z|I^h,ع:Ǔ_2y!XEF/(@ 8K@Ooz~3Q5uT [ЎOThKk+l}#=QA&~ Uu8r:K$t%Z\n㨄ƿFRxM8ÌuV>n/@FGQAq´xxx[k8Ku8&;T4]Ɗw?tLk!F`W[;( H8& d=YH"_2Zr_ E/Ѧ.f"i`]S V!Xv<I  ^ e?>Nq+< V]Ħo+.V PS;  .}(N*ǥ(On,tnt@y|m[EzEE 0V~`Ha,Ǒt>N{Z(W/Hy2pI(/=:wP폆-#7C tqA p6>FRHzWU;TnJ+mZLi0gAu. @P[G"}>M>*兇B^*c|]$VMLG: -D>F i,w0dM{hb#* IТzwcp]i!*)$ BI&!%A" NKNRm2"婪j h:ҹ[e<rt*b}-TNW:Yh'9H ٶ5.P΅ttc=TմNdzD%.GF,״CH# IFQU 8҅J.ߴ5 1k 9fTP_< +4 Zsfil1jŦ=>BК#nx%bz^rvQ/]VK8UX@Ҿ Hd 1@DAlsR ,Z gڨ*͓rնnҩT+:+@ :Z^1a|A$eB'IYzӞj^$b{Qi5ҍziy $t- 5Jx''ÊZZk(<ݙpň yM{?&\[+AB?^mSRpTF(e$龡uHh0/m; !?QC@IA3auO\ 9DTGˤ>zY~ë"b7wo;ik: b)1<ݝ`7t05xѝɌAQX ]RT70V!ѕbM{[RF K@5We6+1W1x2x߰OvS*+Gѿ}_ . 5ҫ@+.'/Z1dESJ(e{1 PB DOs@BeN];`~iOBDi*8(JRShl.1k`${SJ:n֎gU,*LGWwZe@Ykjr[x*Kz|8E_cSPnδzZJ.OvD;/B|Xt^GKwV; h9-T w.Zq lyؒ->=]K!;;_1dtx ?Ï @nO+  ,Z/С3|Mus+~FD&`ssVj{xDU]vֵbhU8f ~pE'mD‘T7h,<-`3#l]EGEVV΍WX*#HT7BqH.yJ0*ďxVC*pt9vbx0t3۴ MeѢ2Dm4q~-8!Udk_P;'8yG7ҽKr9tT|G*Nm㍮ [" 4 H!OCWcP9tQ. k18Y^M{xV?cˏ=rJR i:%h{n8%!()%.<}ba KR8/ OU R[8Eۥ ops)t]a8p?EZ3}`]O9:o ]2JnI_#TtLtn2Yy` j@h*tOeu}ӇGt=EߘQ=Wm:0?8}&~ &qd;OPp+!mJMWBr=@} N}̐Ȱ%t4}mi骳̕I I[WEjB̑n9nBwގ?Uۢ5#L4U=3ҶQMr_?G hAgvgL<ڐ @OK}#0s0m3)ֹ2Vҷ>#}œ,O 4-"IOCgE!+/gFyWh!XM%P'o)5"xغ$l(Vv]Y>ZP)]-!XjǓDh`C?`][n0Eށ/alRPN#at4xF@MЛ$:˝+-tTٹNJ0 ji-T4+V $12m @hBs!@ ~L;>%#[Nu?!#xQ?TU B$XMT?^`Eu:%KL gvMLJyq"JJw ^5Q1'AVgخ> P4 ](-t"r#bĿ% t]`?n}rGrC&i }񇦣/fp-s';܁' Pq)@UN }C5kVRPt&#huIӷ`fv~*. m"xJWy R"H,H }՘SFs),i.6z(C?p2.ޥmCDDZ%3 :(bP)g3*P A8ngSt~B`̳gw3!TIFYZ_w9],n 0DR;eQ}g 4$`Mn yA#G5QzfX#R| l"XDacy~E@~>F^JF_?`vAWt-5K8~|j?<2dkf>P"@i-€G08tvi ]DfNo첆@dG*!S\ ?LKh:$O5QZrE-vpD:Q&4| -W̔!^TA}HtNH78xPt'xxs*_/kcc\ D @W"˻/B1ՎTΪh/"U_ѵ #9Ȟ,ӗp$(+c ,]Ӧ,)LWu}8݅gj#J(c dC Jj Jsu[:_hO叒_I]X'hgE׶t =ޡtTX:+xt]WD6%@ A t .8}{4%>_ѕ.#EdN%d /l*%Cpv!@p}s=DzLOZUkUm_ _d&Wrɔ{zd+~չ~h4" g{kO>-gAеηE1R?Vbg·8.UU4?%'_wZq.wNCh*i:b&}–Y8#ym:_ J7֚ъ S/ؗro9Tm)ZJvn97Ͽ%Ipe ABo|PW;kTm tӂ}s'L-ϸ)F8pѸU9n,.{\m,J{³ᇒ*fowJNa^X!F,qο._ZM;fQg߼k0,=|y>u),R䱙Mhb[Ԍ(\:Uk /5hIss/KOHquo&#Gu{.% 0d?tZs#< dԕozBZ K %b8m~n].M"WGް )&VUky`LFpD0! r7>"XW+RN.t&?r ʆTKlz%^ѷlD-DBI݅RB$k9,k;, Kpa9͛Lk)?q~PVzQfǴg% ~wh||O1nSX/U6qkUχ>R%!%vs>я6swvґJŸ:v~N}RQ=s!Ҥ|nsp&+e;ʞ~l\6dGv/Di#{ ,p9 ij9G 0/)99Nc8I$Q-5LȔ[#hE fspEne<` GtZ`5n6ݯWU ׽#áBi/"vJPPH:n[5_(.SA/4Ş077nw!Ч9+&w-a7xE)N6vxy~śGNx‰Ob<ڊJB`Vmjs߲m^k!ڠH}q#y!ԺLkrFGV6FiY?'N:NĀ+ EQsjv֎L S_9֏?<']zځ! NSq@ԃ=p8k^;i 8 |E/t0Ƛ3 4 V*Gޟq?NP2Ǭ("CZcl-nEjٗ㟟󹇖^:k_D sU!1ke,U+; 15v{;?X-j|nTwg=A ,ԲwT{_:kDhQ(9}2Xps\n@PŠe"@U?ӿD&VfDxW~qCFʰs$Tȋ"/fE9[9?oB؟hLUi̿^ F ' ZH~ΟpWqJ_wݣ@%un"B7E"2N+^:tTyۓLdQZ!6U}:l."z;fRʒ~f9eF!\= UXZڅ:;>W&EK8 W/o!f8XҾ$><]c|NFDމ)ձO `Va>ɭ cr}1>^5B}ch Ơl3:^~rxc|d]qKS}1~X((AQPKI%X "DK Kc hjULi5QrS8Ċ,pі{n^ ~!'V.Y)OŬʍq@"5[Q<'ҟ?&C\KZ~(lb,6q@+١A'oIar $Dk=?KY'AаB˓0Ӎ>="U) q䠵uI'H1>lϊs ʉI H9{A0j6|_ȽMt.׊evHubiq=ϴ?@vX"tM(1=#WCxLyz^oVYڧ"p%hn-XY*P>2.g<_<nq}LHS_xEV .' Ɵ|.(lFeO+ZYrb"j"«z9h>,|7UgZR5" t=kr|XElkh1;v9Zl,®<׏AV+ n#hs4*4D,YVIM'|+ Quq<1bcb0*emEz5-uҷiX dczs}W (` ّ3h?!xQK3JZ"3T o[pz[+>^G6(P.FshO2ʛnp 4NG$slƽ , e1%CY;Lt^:ɞBg%ӻP]k%I-Gں}"+(x%ށ8WKE|EZ=mS ٭xX3j"O/sΏp`DܨqH}L/mު2`nym懟y*m-K]S@w_/%wmtnpFP=˟ߕNW@ڴpZ iu 󄽗C?*=⌟j)LEh ^GKd?`&VTKnW;gc@")dە_\]dL?#xs\;*Jii50"}sl<:3S>^뜟(Ӕ`rpDYkurh}&Q,3TBL_1}ӿXq| MȞcҜ-*3ZB0l(aS9TnJ  4U0FXf庋N(ΏX "!at }DTg7:FQt _8 o|;oiٙ:.'0/HMl ':oU)g1S||~"`ŋQOsoq?vU@Ik1f*fRyc Whu*WYڌQ.7Lݑx[7PtN֛I5aԲc^Ad@21y uBD 7; jϡR0XYG'oǢ*o$Soq÷nCBA}f[.Eӎ4zBmJFi:ZaSQ\P2aĘ RT{) :ҤƷ=*9m?0D.Fv7rI`⧭3H[Z^owsF)<H;cUZ\" wIp4GO{]b/\`AM;?^ wO՘xs=ט.abۊ!`L>wU] =\ <9G OQ(h܏` i"rȄz E_ q?yV8pڏۇX gE n3`B.l\4 OfEFp!%>|~є3M:&Y2ram;h Ct 8=^d7D!8τfw[ψ( .$Zc?_cRؔ_PM`+gbjۊ0)OX%1>\ RKǝqK<_U,9/ARVD[>RBBG1P>R=yLzƟ=80q3iH,^Xi\%pD@b,X߸||wO}Uo_6+0?<F~R*A8.rd=du}Pcv^iM+Q1vs~_8 i4giN>/ x'(TFa\v;C%&W8:iH;~, KonN9'zgzslh=zuW->v> cgF!XU{KsaiWdp22M1bLCIM 2(ES}gO9$Ya喝UDfʁH|+ZyND{i׺ױN/L#?1Wۤ$娘nV_q~"*\^\/^Sy棫a(~-TN6SY.qUœ.t=_}=+s׉6h(G<#F\YQXnS"86>/ACsha(޺rXʿ.}/*7ٓP]>QZ%q(hn_x(/-.˾\v3Y&$ xslO5$٨:<lBS%g5aN5'vLԤg/B`>,DUPDRBo_lA!Ce,܇\ _~CmX>DB7D+-eCv8}.(qUv %)W Gϭ8'Ӭ_7vY7t qf-LʱokQ x , sKx/z\hptDsiw;A[4Ḻo7 (Sh"so8WZpe%L%oW^, Eiy#ZVQRŢDI-m|~u']W^3oP=T$Uzߋ޷6D(}r/Bnq Wkjү,>91: +VQEcТ5;3-9(hk[y>y,C.mӵdžl) , 8BɴK rEay> {nW4GIybfÎ2} {oXpge"T%. ]4jS(]Ʈnic lv>)7h^-N<o0J*g>G vgjհ`K6!n^|ҭ t)~UJ*K?,N+V/VN%vB'bAwe( s v+lnN"cCh&@iNWta=Ze̟?Dp 뮅͞<~~^<@=u"ej>,!sUL Մ9 ?}/m֊|MSTܹ gOdHc&CS(X~\eա+ {*bYW_?w[ 7Ņ\ׂ v*vyVpzkF,m?a_ꌢ<'t 9UFH, 45/K&|v" S@E*3\gE `4WB"}n0zM =HA 5k3tz=۝s#Ə*s~;c$cBN0C%Z?۵- Ʊ^3* ~XvI`XgBq9?`t~IK1N\I߬~0ZݸB(|`9X .KhyRZ{9@t#*wM&"a$E9R%߿*t60q8d7Wֲq/:+GAF|_COW\mK4i֦t;߈59у"҇ݑ*V\1HGQ9p\U(=jhpH f! v;/g.G7  ?gUaqNP ^@_݇_U*pG@͖5/[i\Pih(|_ 3i9:}FȺ> {g qT&Lޮ=X|ҀLl}s[!{bv܏չWy "E˚p"Qx=O =[MHA+ zbڷ aHOg>_UZ~D屔|~ PBtbs.h/g4@mgIR NV2z[,j ZqsG띆@R~)Sɉ}ُ2.$}cBvhF8C@h~caիsL1V:vDw܄GA܏sE Aի&]惟qō1`ԃiT~ XTI"NUB_3PePس?|脶Jaa?Z)2Ov>n^PιHc< Mkoа aW~smkAWd+ا<2 qKSQKʉ"_>m [`¦@BWDc%O}Zk=(> "d&S pOsg,mHjg[\] ǹ~:~ +1kUDs[!ʤxOڝps4 65W k^sB% #X#-<ϹX8NlQPE kk&P{{3Q\. Uz1c0}<<;SpX05 Ъcuqs V SxEj*t9UV:,ߡCܕ#3>Xqh1}n8,C[-@D#;s=%gu}&+yN\JD?RQQ li>Ž>'S19 d\L]y^RUE" 6G9#MyYi/a[^/Z5y"Vi>7b_L^\:hɚDh}\rg|7R:Uaf4}__2R/k6\~4}l\⋞Bol@DpQտ؉Q.cÃat'mgIEM;W@>8?N$wCU>Ӱ-W>!cEdcؼ9QOX@ n˟9gb@%UU]^_\QP)8W`189/ىĐWy>fip0ԎJWq)`\ي4ㆍ*ףnkm0DIo|SmA^7 ],fS-_[5$dEaz&l }wyԉ 80#W;h} S%}.^^'8hqƫ|Mѓ@oc1_py/GN)-F`@^|_p<\_[>ʹD}}W_š"4!+(=ZV~ٓpLnޑgfVg| m,ZU!zzM@l>DJ(#Rz~IE 6""XD &]bKxs=7Gyty,9jv3qP'7- k|-^BOZx 7iAqj.Wz7> Qz׊!/55n|ύW:H~cЫtrҴ,]ͭB%8Z!(CF**"F-DoJ+PF**乴E[vO/uPE`TxHO6:"K6tL1M;ٹi䚊a"@A~L"7?#aSrO1&FY@-n Y pĶ@3 z,>[t+zkM;Ut!8Vxk8yQm1Ac[/k}&#B=dн͹_\EYѰ)ԍ~ʬs*gOȕ7¥vohIOWuFV۟aUkI]mpwQPu>u70!a)Uw{sD'{ef5YeԌaD:R{Q)%ENj~wC a{@;:TB+totTSg"S*:n*\ᵨ1aJ7}~!F A~ Jd{Ň8هNmg){@RBQbDE{v<Tk1geb*4?ՉGycipE󱈯 лnBH m}Q[!Eg4NH3>#MiTw,=\A+cD,P T80H 8wmiP@Y]#~ܹD\N6)vm[DR[(^Z_x̰nW We^DKSYVMY}Rt oRڟt4C^k@ś[[Bs3W'bj0t^+->$+CR@\ x?v=(AJR;Gﲮ4>^VabgH~o|p&!>nۅC ?vgb;=#3P?r`Pù[2A6nsNlU"]Mȩxga)8q,\yp 16Na~SL G;|SqR7.BzUS,x~CAU<( EOo QA{^ɔ3K_p~_sBbl#/N&HNt` KѾ["/SQDOhx!xi Z!%[L(gT?g^TܨZDDk+(d])/ὄqeYHYu.ˤ1^}IS}u7;>'SOQcu=_ B4*tů:_{e((\bk^_}7ҊD4œ\dk"Vk]Yzcnm}տ;J >T2Ժpt$9_wYԕ=qb!KWh!rRoڙhq o<%rf 1+!Gt~/JI[BX1 3cEERͷc^\|v Ӄ]˷PW9YŢyı췞|AL 3Mسzv>Q) ׿#֊es;qTkiuNT!`Ų^r(OvN*2PcxwDT ;:h?$XkuG #&z4Eݷx8\b>S‰*.i93:>h\(ڪP #MyTB9P2/Nz5ك6ÎӞ~7|R3RB]S 뵖IicbBF4ТﺭY6A, $hLtI7i^wr ȍ<#$z[V2( X~J, [p0us呧Oz+$F*?q bfURo} ]h1۟7&F$NS\5ԍ-Pׇ`Ľ6?} KKxEG'KQRs= MenE—JD͝~h}EoDBFOlQ¡?wSɱi+VL5)'^ x9Jpɫ/“;acQDv^[h_JR9=Kd ql 2L}7jzRI ?g}+'@kFvN^v~}u"  vPT iD'{BO;f |0-⋨k/qad`E 0B9~uBGB9o Ts~Du2/U!qe!];Exo,%G4- S(_ ' wncs87@=*+G4ѭ wUF ծ\~'eB~|~GbSj\pg8qm^;k,\p8m&rUiO ×|Dc"&" {,X |W!(TE`|QtҚjojE)ET)P7{zZʖ1Wc'ŸcVo",_WNh[ ~5=9a) B_J)uGNx9>J8BAAv{4>Sx,uYq6">LGIo]:>= ȋ4/}. Sy3++3z*on/eV g-S&AȢc)Q*C<+^\?E(""#u̓)2ye.\D-2ɩEiѷ)j!56s5'p +S?$=ҤtWZ24;d ?/)$ ڸTEF8𧂀?(Z W+{8ug KvSVVG&WwIH:Lҿ('d]}0hq~_6KIjSv7nQÞa h&3UeKsRA}rjUZ̰em} Y=D%lsJxhC3Ծ.d=rfLY]\Lb2icvi&<;Kh=$?jͶ/)FU/:F6sE'Tc:0x߸֡\3-bEGѥ8?'ql/D 6<Rn&s D}D6)ގc|VTlC:R Wh{OP\=˹ѯΟ11XMc+z2Q)8fΫms~FIt\]k 9"q[sR(JpԺ`K|cŸ^{-x'<+h\+Op#ኈ'C "hy:5J06ȬlJVO3`7N+jny-zd"~ߓȨ~ńZ>¥ޓ)B&6/U1jjvOv1UN₊Ҕ\W}W@4 }Q=6xc<9MC0y{HNTpJyw>aR^M2zbcATVI%4m zƙUȠQ߮JOszi?ּP4vX@Ti]s9/%_C >9?!®-3z嗛0TGﻍ{_mhry3>oq"blAD_qpw;b!t +!Q23΅A@{!-htQ xUV@VhV ;?mCbTp{P<˹C휫EǒPY۳9bA/BpW\*ўvxMkTrʀ$‘7zanhAX&I9 Tv \)?PMBx3B~LvڴNįAG1 e)|=9K%g. A(2Q?=ǣ$4rb_N-C*o]`~- 0.@/pG:q,PW юPtO<छaho| ⬂8A'sgN %&um妢-vgѪG0qU(&gl\1:gwY-x:R#K៊Ź'v#g<5(#ϨJjy]\x^ &F=:E[9߾ MpcBWB-_TєKp k+BgHǸIY֫pBL }'s9()T3-2k6J1 )4qЋ YAȍkyi^q?O=pZëŎ-ـ2<^[N "XW נ6W8/e6=(ͣV/y[ashbl/uꢖCK18$b™lG{x^Tj২:-/2-Jڞ}EQN$r_#}.<-!P#1M\;I2G..n&E/wlzT~jSw˟AmF RD}W8 Dͽ/[h ) &&7^>mЃIQV,rLGJg<ӓm3EN0)!5Yu@ R@j uh_)\sq+Cƫs N/eLmeW=pmshL[ȁf-W;WsTw.7s qg<\N밈jQ 7>OO蒦vUSmG=A?Sʠ*"݁Lx%bzsC:S@]p>sf+h(N(P؄]O.D!^ MWi\ԟay!sB$x=?_Eb/T&Mj:wٚ4z @0>~a׀ۜo8xZC(1'" %֣DE̶%.vm4R1|c  lW"x-rUvF-Zܸh?9?:(@۫mHbHZ##Dx Q$ѣ)(!sMZQʠm.'9w!˄\7㖻Rħys>RZoT)- p iFtd4Oj+kɏժiWZtJN#ˬ SHQ0ۅӧ澗SS"060ΌTx: B%` ,e{}|y]IQROaqTn;<1࿫ȫ'JpM$O{ㄤŢud[WrbAk?9?yvj~V: 0c1*b*ЩN<WxHS}E;QٶLZ?HepCΚZ e^i9{m֋ƵzΧhx҃%M51^ 3QAsL# nrsh6MW5:FXFx1^^Mؘ),zoOa6{yiҰu#(+[P_ C(v*bݐLs勅 Ǭ3%O@KmJnҦC}4E ,l9҂;W.^ #s={#'-]u6;kZDnEX&'N+d{EiŲ ֣Jh}W8+xk$ ":2KöPmM!h hCܛK8XB .fxͻX.Û+Vԝe^Oxic|kW`B}:Z\".RH}tI,VB "_2 aS4G՞d# _s}#:hZs(\-l4`%N0+ T;k9 [j 퀝_c?*84E9TA a1>Qf/86c\.Vtwz(–j<ڌ1^ɑe^1h=`gh+Dn+-lZ79F,^4Mzw"u a-WU!1ݎHy`l$9#J%{s>jRcҍ]-RBPi|U\Uġ$5-)Wpq'cug*?; ;%w0| YC9G$R+N܁ɮB#~xVGbU[9w'ΧZ"-~vj"~/47N_v b`XiRw'Xh,Nw "PW(r6jnt~1~!kyVڣp<A^c>Z@n"Gj9}1ϵS"/ և󃇍oQ_|iӠe鐴~da?k'}RqϗY֟zqvmĬ>()c8 E1-irWpu{  O4)9jQ9cWCT@:Eϫ Տ9燳ERYfRLNi1G5(Ɗ":ǝoB^>_8piӷ?+r-wחAOm>1$|qayYFn OT1"esHmerRsFK$aVCa>Eu_}|1^10J]y/u1gŞc)+/|V$NGXFP`Q9x@ q(}hĖT>_ n*'& .1\*߳GU{?GCx%L#^)}&N0E4 axJ_x>Ϥa4^ (/:糣ph֪d/ }A_Nˏq:S)ҘV~*D}8'L*V./+i{#5Px(:r6G~tsIߖ$?v1Q~Tf\yxh|h!PaT. j79GWGXBvw5k+[ Qa\Q.;:}G0Iǵ{$،ۂɴ H%$ȳ:~)J]|qrB?{GyS M%-;cP3cJlg3뺔FćQD*HQeQ~_{|NJp,1xgqWL]SVc|e'=Jk"x~-|4kuHCW>.@0S8R^1jWwV Gްѥ#eo0`z_;-)0mL5;rVY~]quAa'88ugi }2Fbwո\3Or2r3P/){)/dU~eE c|TT\*=I ]E8uYZ]f]Ԍu[µ@}QKM5֢X87^)Ϳ=P>&F-WJW{w q+x#/:e$ 7tT%(4FzHZ?LvSN42`$Nϼ?w53`-|Թ!q(SÿQڙ9MdiOE"v =qŹ=st"N_ĉm{aiZs7[Ji\z)dr+m=ʂN'UgKIqOq>OA~=r"T<;h"!}f dJMnwbfv|1MMtuf]q Mow6dh:]OLDY~1B^9<\>+JNVQCG?Su&6ݯD+QKW[>o0SC=Mp1~ƮDwa)Xn".%UcKq'\:ҷC.둕Z&&>SႳ/UB:3(ט}T*g7}s|F_\C;^32Slq{-PMȗGLjyc|WH [6 `'䉌kĥT8CoKiOpYNJɣKiI ښ8i}c|I1_#su⚞%f1@YQ\=a\(/ec)Mr mzЃ{y6X낫>!ۓoQxSxsQuCSȓ㧂e4SF9^ZeEH1N"`8h Ȝq)hMv*j#)2VOu虏>96"‡=T,ڧ>PKkt/%\)_3OsQzſF~0\* R|cVẂ{05S?^y9]R¤c/CJ=>12>\l/Ι?׏WFiA:/jܐ({l1ŽO[A)榏Յlb1<-^74z2lp:{9  {+itX9h悊ִ}&"[8 ->ϗџP04 * g|3ElOmQY<_fynju>9+gxDTΣhE}G }kv[t9ק8iCm̅zOl) = K4a -Ko(ܹ4(Z#7}e_.9W-\`jh!h_3mdtڏ4~rj:DӺ@<p{=[X!HYLgB]NE׎kBs}**nWhRvִ7<&p;.1DShot3Jd[-iuF{ݘ8R,Unk9j F[~#E܏.P씘vA{o=49%c+p 2 |Z4;,*w5 s6W<)TgxP(hz ޅ^#G#^TlH^LE0[7wvN0 Qq{ku,b05*/~Gɩ +P0G?9^!P8JV92["` ^;b@aVowxyAT-VYIC̖p~mMmV,Xxl>d/}r"t =G_\@u,aB[V~s=+eR/b߶5yCQk k^f@DƆ\L։g0tGWtq:|Z@!SY"dke9kq=,5sBg 9Wpuİ;ҰJz]bj_Vy]S8Ghop<=VNIsrUA]pQnP.\asSb4ӟS-Cv|3>_f%9 [:=cmSW+YnjL_[[ NZ5jtv|ĽjB]vIy 50KJHET"gEhc:s :VܔmBzJص{>U6;*9i`c;ys>)׎1حxe*zsDm3hZ;SHgr,7μٹŊMr~u )ٞ7&bQ\v9[A)KI Gri[Ts1YNb[ߓ]tw::ʈm۶m۶m۶m'_Y2[8gs+*:gcR эZo:=qe gKϛlboso{VB̦&gSBmo\hAk+ D3-'ʛ v:( ⨡.`{Z%ո]U1Y&/7`1Zνah`n~0ZȔ]yK[zs=; '9 AiT;Py%*O?S7JʣBچQw[]+ 8 벞C鲮^nxrݹNiaPߌfoDN+:qam=ђ7ψ5[2Oj}lz+9 [pqt *]{JWCRʥ(j\o^^JZCa.M"Yhl#֧58mpI I;'(b5,xq.T _57YU^xؖ~bM²~͠ v-s-Px~ӑν IF,њ4dX5pޮ!:7MatY8O zsoEۉ>n9+ x.>,7R)>8XVHiv/8%.nw>{Wm3 BA֘KGD96ڏ8@]K0.Flߌ_h":bGϣ2H^`J-Jkq-ΙBUBMF'>OF#>keW-zL71+ cm'ZD9z m]Ӗ'>uDFoo/mYwϕHCeLlϋc+)w%K+D{S0Ɗ\FG b;ޢo}~: mV'Y r!)=a5&Ed$BhjMISO<9jZWyZܣR[`H%3צ~J$V ^u4I'.Q<>D,셢 nά<׏ܤT 1H:w1a7GG4}V9WHd*L ?y@ci~-RWdX;}*ߎsxe=zی}޹* %.8p^ts~Z=TUDpUaK nxCݑu5e׬pw+;&-T"~-fPul|T k?Sdg5ylgK~)Kf9 _S21A=*+\|o^!RËlxt;rBY+ ވd+RڊٸPWkQϼ1WK;=r9m9 T!>}%lz▒B<׌V;bZpK1"XUOSaaPdtm_w a8a+ 嘯C2Sf }͛ޢR6%re~>U0VOjya\[rK#2 9CN`\>\.:ZQ^+s Ho9:8A,!s@MhXOMYTٝ"1Nv.MFW8]=-P-EPkݔ¡^Ts7eI8@a\;y˧rIEmT:c.!Ce8ݷxI3P)(|Ϲ~Ztyp-I•s<-S$D8]KtCt )[ [5 Pǖ3.Omw,돜ϋ% rknkؽ?=כ ]5PQ:72~OiɎ;Ra6Kkj9>b "[_O&kz4CIP*ydZ?ywM=>J\!xpTLTA9>}S\~꺺 h?}bϦ]fA@ DdgN'!{^`?{<u\uE"O*VPnϸl m< uTeR.s{,fs4pd$ d,;雘fRԣQ)pm/G8$hPpdjԫ)4لd2GNn̯-8/*>WiA m!R_şFPљV ¶ƍyΰ(\ hQ^o ^/H&+iKo֧`gN(،q :3(o)-dByumt8~ 6EfԮΙ%פ"ܠ eو֛@qoT;4E3QL*whZg()؄x2 lj2&s|j6\ϊ_ܔ+QVs$Vl;ז?:|E/ST/oV|?>+sp5<Xx'4HVWn:Ə^??=BGDAh#P,,(g|7/GBi֟D$~Ul"h;E)_%K?uRZ`_a>už)9uku gFXeE_Fة$}fZ\B.3]`0 ,~jJ[lߝkqOQ@[\1I ()QT°pՋ*y !!%ʌ4X*9⳹`hI"% 9xm}13B^c<<MRv߉2aπrJ*hl{hkO7|Q"~ Y&ȑL bipPhPrcPܿ @Ѫ}E2ϙd*|KUq Jaģ5fa:8A;JW\*S.q~Y J|b6hv!jXy9W7`OҦPz0 :(; @Dc[J;ωc3_%=񼻔-D<O+m_>:;:j&\5sq 1+>>_ĤrGڣ'Ozʭ2QKze,e,Ov&!pD ځPXKO\xL B G@7[Y؁3x~E'2[&\BSY8MKW  #>RSJITUu4}Os:-oMJqF4q2^>H=''zV̸nGwOwoBhv$PAN=?9UKyĄfs%, Z=ES[_Xxϩ֥t$XMSa\oF/[{qu1z3~sBíVx ?rGs:6u^Y"\/N(>B*=\z}9<9>_l (Ӭl-7T3km]M9߇r]{8)%6Z#/tZާxx*6s9o= ü]Y-5ɔ&s9 _jaR U>_qC\V1%Ҏ{Ԏs~/jtѕC6-ThTs T"!fD_ZtPcs!4M댇")co%jtm=ai;#\2 JۛށWT3 x.C IJ97LnWuHGW) .*UcPyY` tٿ<j'IX(pyq%-իcүrrFɞSe`JHS"ؔz=nNϚDG o|(+ό\Ȧ6R+e?_ub(UYB/pfP"gWfmS|LZ֢sIР&6z3yf=85^7|rdXBOPB1w'59c+kp,ND^ʋI{z.jՐsξ6r~o@URҴ+͕G.Mn)p<>m%Lhy= XK3ʌwKEkS{ PqjZ/yY=ox'@1SFΚȗ: ´4^hHL]^/}m* k˨/%zgk /sWKx(;P}[~ĘԲrcAm/w~/W[ӥL[o: Ho[Yr5EGUx¹{F.cHۘ ɼ> _;(gvux{2 EK(^9N,hHMXx+7[-?*+~LY(9RXA!l/o ~Z1DIǫG0Uk޵K\;ploѬMjVlNr ^kQT)4|窝Oo2hm ˤ<ʔon񩫾ֹDN1AI;8b~3^i&&IÀ~SWbD LA\Ѽ*'[aV( 㶈٦c߼>"Uj;qW-l_܏xv0D^.lUU]+Ƈ @X>-qê]81 }*|rot>\h)]v|se77lj@ $ԟm~AL;q$Dý$F#yt #l\։lQL=ء?oB (My;OZmbQv!3H8jMoe-=ƑO\Ӿjin,4DH)&t|FXF3  M{?ѱ{ DC|ou÷TW.xTԲ.7-ַ(d-)iĹ#WPۜߛP[ zLT 1w =U;%:̾/uQSdJ} k3B.Nqt>w8ozjN _M5ekMWI1XSTFxE%%!Q[S6;Np>D"owew9@XԜ7Q Qag2ZA[+)o{j&LlU{~7 {Z䷐+=c T`=%I=x8@AA.kѬڸx{>P+4DStJFKoI>7|M(7jhJz{c 284AQQ"n_޶g< ױ4u&E}Ud8Gk-7%VegLx% w-ý(*ݭ~m:G- ]!| zGA>w&o6JC+(7N"P Ӈg6Ǯ FkWТ9X}؉8±v5;\S+Ŕ^vYr7Gث!ZmqTw0ss*oO1F$ď+{gZUgW SW3&e b!.Lx'T1 1Х4\~_Ox Y⢬ʧV]ZN^(kmhL#ug}p^CEc I6=mZ2gWTFȁyv?\@)U훁Yor@x5 g\hݨ7o?ca[ *jVWKs5np}U̶13Fo{\]ڈV]EI{K+OX,8txh/8H YB5N5p{*"s<5ކ׃"=-F`C/ZXoQ2}jxijR&\@j\umb&5Kx"<,?(֢_z튈MKJYB(|_vzIaqٚ"֕/?xGD땹Ws2ǑfY| -vEr@*K6ί:7Ru+NP׽& pWs0Ņ.UeƗZĖŭ% EמS9rg]Fg`mNE+m2X?_÷U$bm4c}s=LD֫ o<3BXvam%e2"~ ϠKc~ E^kb%B?N[xMO娧 IsZ?QF Zvz9Ҿa@>v-)WT#[F~_ӻR3 b弔m7u~|qF eBmcwU9 ѠAMhwv$B Ъf#m7AZͣO`6Wշ۵''u / $cm1#}7|9;|՟Ąc0e0ZluW#4gaQаr{^N(v 4`.,i\B5zN+CѶWظ.ˡ>R\EPs%P彐Ov)eϨ+܉ "U26Z) f6aCB)9/`zD1J'oȠUWR MSzSH+ e)$9HBTlڒ t`dqmsZfhZa2a"ت-~78k--G/*}!`sBe z]P0krd|/CC1ƽ8N+&( _ v?'ȐDg_ōU@bVp߹ [_[_BUN\ZsiV.рP䣖 ǰQj UѕT߿.%z#.HNAa?8׏ws-CS6!ob1Ŗ~Ud_3gPXuAzl[.|;o[.TYTN Rܒٚ^Ή(ZBeOxhZ@MHj(Ky% uq)zRte霅q/DžjuRhL(B7TqZ8tBx(XՉ;y[[&G\pQ]H5!$QGy1^DIEqUt yЙ> SDmI߾BTtCt K #Y!lRXjr(1k8&hęXdah VmE ѠW|F_8nM+rٜ`(<?wBMr~"~tf/xc'1Eθ4C܏pVN?[4z$4k)Kx')GR~> '?99U?ȷWEik1N(⺶0)ӭ=9Ȕj:J5Vy!)bڽ9_]GJx9+o%4bfh{iS{'mƯN#˥I)1tt^Lx5ЫI镬kЩjaI';'B&9BE΅|c8ܪځdDSq_-Ǥ()]g tSݞ CB#ar+ 79>i(驆+)OsƟw(!7H[ Fۧ=W ŗΕBN= =)<>ʥzj %x Usn\|jEEBg Qbl;iz=m33 7-|.գ :jt~/bQmU;g>B<2[j,~AWZocs Yo$i Y8BL*E}YdRt;-WVd1g?G?.J*.9'u=|X K;{W&TAd/,!G8c(ÎxKl`,Q reexUKt~ !,vB2&/g6iQjﯥQ|e zCA5J#W?B)_`B.UWgH4u`W&|aþ?E.eD b?F)k~&%*JkߋUxk.h)u&fEyRv" uFa=h){4-4OơJ\i',&aͽ=vßڪX2F ; d5ҵ9N1RPUmvoW%&QX Ƌi+=CFM{CAQц["=c0w4P f%3AzfUʏ]:U4(]ƏbGb$FMyáI G*.:# l 'Ya *e4ZxH)FNV\?M;KCV2ٞ N7~gY HE]I`w>uB͢.=t%e͉3)S.mugG*V16XhЂnT$P% 4$۩_CUF\4Fj[t>EK; 4}B[1T6!V,Vnz}vP*ߣ-t]AÚ8oΠ$S>w|>5hjGZ;dSrYӼh>vUeO+BZO`,8.9u }:WfOM* 6}gQ֠魐ZȘt{s77h"^g衡Ͻ EҲh5Ŷzx;ְnSsr{3.cϿjrEvTI'4_p [+G%~kRro"$Eߗ<]׆%yB6@i3UQ9pgO2yfC `^- ۝loœHmFU1zq}4g_q~oTj]*vjGTv{/_y;?MWB\* (5TU7 ֤t> SvOФ$V9|͹>{C1֠p.R+<^ ёTמp6:qSa蹰_w.|qOAGK?)LZ QC 2p?o'Ԇjxn[+Gx zܯ $[?DE}+q@fa-Er2dMo>~vkďg$4/YB]`3dsm[O>`Qa4Vxo;ߔq/F1:0jͷ߫Y/\>Ǚ;\LQZqOS(91$R&g=DoV ^u }muw a3BŶwud䴙 5帪iI`{^ vlU{o f( tɘ*80t˥4u'毥<)I!EU+?p> 7î%h]ブʴU>QO)Т(3NLZ?|b-[tE3-ʓ9#U]2^U,O#k}цjU^£act4L.zn3wV?~~/YD ]]o*ٵJ1u*R p+WTGחRTEhE'Rn(j?^)91 A.p 8~v ؟Z# 1.[*^;gO<|MIozEu?w~Jö7;ō hKo0К&D0p+]V M +'/o 0J_]l`"ĄHVCq&iq /DOG~!RΫ +SqӱG5 JWoPPUBanň,3}ok'^` I+h"U,7&=Ʈ3/N^Diƹ>Ҕ H*qoE]52QpMto!8\'(umX }{δ js!KqVWHnz3{ :APX1b/J$1+F/xM*l~"G"OJކ`KH oO8ՌoԌ`0Tet thq0?"0ЃT4LW'r#m"<\5(X!]"6:v^4ۣh>R\^!Z9F߷һ2RhBn?2_,S 9{CxG?+۸FI#6PqblꃎZQOp̆}y?#~AQ`}rdYy(#?&),G?iRJ2jm MФs<>xq8E+T\qQ|=x>(`,ޏ<{luZQZ^wߋ1M" 8ӉG#X\cϻR^]t-i #9>׃3H9^:PR"CKޢ@0[!jqm >𸽎qo]~[M8ƶSfGſk!GWU;*?ߧIu\b(<%+'8dzQviB8e=ˡA]VCP8DSM&)k:=[ aPTN.ΉH4b"nAJOrALP̽@IAd4S{BdJƩ]4P؟܏htZN(H4Mw$Am}?Ź_@RbvKxKxsu]N+e@H IQ&O}y#7> "SSNAn*vpuy=<9nqFu9/YE'2zw/خx[<ܴ\[aI!8~rDLPwDRM|J;8_@8A;*M6\7궐`}_, wF#i\ܿ%fP庞F :'92S JC_i?>E>""8MpO<cK Gbӑ=}N3R`'q6GMj]K¦UeD߷Vc2mI KڸZO6CO?); $QB1-/ʨ2WZج~yu Zt ,$]3*CVVw;AsQ>xEs8Eb يT>o+\]P4y[{F+RasDZ`o,,).>ڒe?߹ޢ(+)!V6ǝϙFz-SF}})tFiI4Z dZ|Q6ܾ ;WҢTLQYkno9*=ۄ$Z/r Yg(au- 6_/Mx?1C}S@Q8#N9>?F9L"CNC:;9+Xduҹ5o|hJ1W4E!KENuJx`+Sل\RŭͶ79[ ݩp78vW+C,7=nqq.k24OF{FB^H}&[,7^pKT /ɫs}[F&41ڍԓem[ŝJD Ll.h|!'RxD)9 %M6G{mnj'V0Gۅ+(^g,rBVS2zDp-Xب봵Ч#\J[!pqerQvѢ6SgQRI яwC}oG~Oe'5{)<űˢ(\V@|[>ޢ_yʼnE2krR&J3$m!7݇'zΗplhŜVn(BRUZڻWЮũSyv _n&(T6׾>󤷨w{hn6ηDMV]y3Lj$MvNS7}>o,%rsoi "?93 oTBiy L{>o$ '^!ӉAbüߙ uAz9SBt/AJ GhnoHy4'ppJtӞ:9gZ}s[q[t}t/㼺-:Oڋ+%V% T>4$0= VH4\psU;*ܼ llr}>k*9rSRQ\[.Q#ᑼ?hd v:ce*58~tI,4xGυ,B~*Ya-uw%"5Bh6Es>WCc\6k 1 Z o980uƊfLM(..mOOY;`l;+i' TM|A#jzoh~~9_{DKh1S98{ ,J9=xh{h0/64+_ՎwD/½V/q5 ?ק X:8b`7_p>; [L9ߦQ˜zSe""Es'4ٯR*^R规܏7K]-F7m&~ozY\?{k6>!vނMX(QN<>(s\ +,A4Lq/ , %ȗ=W/ܿuxT|="fj]4HEB ݷN B)_}]Bh+N@C3- M0Н='\jz x}nUBs=ht/8ܐ k B|yW pΗ"1#{B,*?P" s!$"MT8W"SrsPV7t)*|܄2Ts!cH6}x4Lq$ġUji ʩ5rmP5q>܏swH)>Ԉӯ}&fjMq4k7|aєh֧]fA(v>ٔKR? Fwi0\?˥1.]LdJgZu(LPJ8Dj&Jp)ݷB=RŠ$d'@Ht='(/lҋb>AsQ? yQN}+@ T,Jˌ1H1j*Ea{1 ci{M*t442^~lM!( J+?}ƇF"E*Y. 3:p -QWZܓϞ+ dW#'J5?wG5nUa*j4hBZ?~/n[XfdAO"( S( U4rc(S(-ҍң/mZn<۶B!un|Py*TQvkH8tG,A- ȝx޶S0r[ojPBҚph/zgV OmM䇨"7q2۩Vd璂Q[fSY)֦i߿qf< #^7Kob{oϟ/"+(Qdk•7J!SK+iOK׍^W&*DXɫ;_-#)ehN/w4D&ir_/8/"1s}Ӓq נUַk?87gLExle-=hr6¸ +G̦!WTx2BUԔ,Ƿ"dVSڔQ 2Q. T )0T~ӿzίm5U+eG@MyD &S(2Ubk~#/sTR)5BW2ySQ@)-7)AǏ|^ɔz&Zs==H>eOT:]<?*nd'z%'9T&{V5yJ\O~Ǒ.2bzq#P}y<|C/TLۗ = 3/9!HTfǏq4Dn) X(\6+&+T :+zY>p[4SUjkrm[NEHpZMBcW%H!iחacOz oz6gOz<.׌̠r<$0/dKH'^OjTeiO~&&݉`g2)筦^+^$sDU4)>广8F 1D7Ezs_BlL`~|<-H(>e.UiWJmOJBޒ:\ ^Z I N{y12NTI%ʼnUd~fG"?"">g8K3tgœheD$,d[s3듐Ŷ* hoZ|w% <.ha"YYVYjw):vA:w<~˭ Yv?*M rWmk}FkIbЬ gt/bch:&FWy3>C}4ʣ4iؘiz͙y̘qujFsEUA30:H -xtO.b1*I:5N"z:dz7O.Rz8J[9ҷ_9&g:*/s7[tODGDp ^}yiSDBӫ˝MAHAK ($?ֲ2yr8 ~H^\&ph5I؜Z1^/\Gtqi,*C9S_RW}M-}p±,r46g Uqd%Dz܆qE~s|sS [\YYڹ1PھLS&N0Dx>&<_d|3}YS8Y +!tK=^A<"ǽ/TRAãexnHw!f"GB(0zthGHS4JR=HaO )MELLDp ݻ3+ G~y|{3#0RtȮ|a+i +NV,LOr?VT%). >SyyoHhal=-(';_ؠbÍC{!''2O~"c^`_7alRt `c7[viEc}l^YX [~yx[GPҨOwVq yӨꜘd˙g=|YuE]KO wۮWHyc/zJcWZhXhŞxsw=sj'g1:m`,|e:τ}}ԛƍpy౧Ymt>pHO`G r0x*+pH9yEӤ-ܳ/Uƶ%˵=Jq. 4 T!K0X]b!A}M&'x|p$'o2QLFMWt.Aj ,Va`MK63+ ZW$sfa>ydäAXY/X,țx}vxN .|@^z\ZH>w!R`mp۞΀5; T'#A˛8>,=@Wxn,&cZ?N &Gˇ |A됇,1d*GBh&#>5q|ઘFj dcR74C'!md- c8s o`0y 008%}F\l,-Yn-%&6 ť Ǔu8 $c0NJb$C0-3!VD4E <oas!0<&C4\L`! $8 %ӂI  ԏ8$,;#B#2>D@>4)i`Q8$^\`l*Ρ198Xs '4dI) @>L.5rB0@r PΑ"Yyt0i\pw /, 1 ă! @J> 9Knrm$wZV*f@N2 vϧf4e񄨎 !ʉO¿qHA/)`MRٸ nʛAbi[)RHYHٴjҐb!_!2 v#d`:`5QM<$] $Sac 42 _lx`s#T>H  ! K85}! Y (pmc,(6 _K`A8q2~29oK*DJ5@'XFFA+;'ryc 3Eǣ4&3|/Y9^nMeB #`# 7TLdH tf|O|^w40!V`Bl ‰k_n &S q0_O'!,Trhdpֶ`&2)x}B0QI@g bbvprx^K*JXI|ށ[saT| ƚ0ZpXA?,6> dxlDx®}ءL!r`zb@'&h$!V&"^SMS6'TMG  8FʝEӀeHfbA$#q|X1Vh<* =V&>:QWwSffb7wl@$Kz}3h[ئ P<Yq46R l p$Yta/򉏯=x?rxl*0ijdcW0L吷BG&>< c)._HI"/&kQ 5a^2ENЧƾ7i ")CI,> <l:gg}Nii$p`1E B Lǣ6!=s q7Ө&RIC^F<\aфD}X0p|*`G>B0 EȣaF8 ɻǓug yiL2AVu0[3, B,Ǟ,,nSyq;&PABIbX̟>@HF؆&6& h&¢: ",.Rl{ Jph;q|칑Fǀ|܏H')84T.-vثM}}g !Ѕ15td!OpY<@|^ P|>XeD!C B9@AQd, N3tK%S;PDÎXtX͂0^9OΌLLƔ *3i>!h&8v2@tÓw*DnKܓϥ"?8s  A h bC.dJ!!3 ># 2DXX-31J`c2!pXKf%sq aiKœdFXl(,"6.80y!JAlɤpa >X !LrƧcC @O0HXTB&GրC}Hb#L1d}g"[~,2 ept<& oEZIE\l/ w4s~+h`m.XN:- cy6A )LK<[Nܑtj}2b^A0"Vrx}b*]9l I9xⳐtKD ` 'C$S|G󁍥! 3fD9\fB>ȥ_&S0 `'{V5ϣаp` y{-14+} $X]Hpga6g Y3왍Mxܗ 0*q C;w2Ǔ5pi6KLO!I|&Y@L@4!:v0 U!C* [XcXb @DȺNF,l< %?@< r%A-+l BlM!HcQ9`Idfa:2"$@7 0\]B9XفL=p|M> q MAB05@v$BEWx9VCr&@TE5~\< ƀ \H3rc0lk^ +o Q>L_G2!!ƞ9wLDhR!FL P4PO> /(CӘɡ0Iw :TqHDmڑhDL'clP<!.PLǮ@TqsB÷)N AĀ  @, `L*plr-AUe!XƊ!6EH% C? ^>Q0O8c}g{ PESxVdytڣ'<-)vFF1L>@c>;h a# ?U: ;MxC&1$"0* lfN 09݄  Ǘ)\@,f *?$2#UFRX.d"M ьbƎT ctD'd0|lN`|YYΐxz d`a t j"bk!UY3}1B&Xs0!$3L20? >ʡ2a<,({̥g* 8v${lfqh}gq~"@$cu>x?l6QlþTdtp`ȭ2iasF,&ab1m}ay%"Kz#W1'6_9<j94}TA^ `Ґ&2  S^ 28Fp37li lN,CJ#C@c ڤCxB #9;O֑઱J$`a<) BƄx.>F_&Y B ;#TqBl`"x6x."1xBNs6}x6!BL")&}! 4YęJЧjUWȆ1Ǟ$l˔8&4;pchW1kČx̏>X q,B2.Ϝx}l'ӄ|\*07О@ kq9n2TW":COqLy}t$dc`wM>KH'9<\A|_bSYX7a-"ڣRlA_@G#H"Ph`z|& I+ sxtta"#!,ng#1;bmb&´,%A%{aXBbа\BI ;-cQypH¦f%rH <*NeE> m>M$LEHb¨=2 1f,ă%M(J&'v.,Ht-86>D|,+",H1 Lw}&P8  `Ƀ=/scL&`-MyqJ0Hx: BSV=J WpNs<+GX`!?AԋDAf.L%"%)`0QS\}M]FF";y.-r2ɅԈNr6șojzLj69مLz CΆSc69=)1v9 ߟN'S)1mr }No}69[Nї-|h,2;x_EN\_Cywq}-yh;4;>F!Scr|r#~|VM?rz|pq!G}'r#SNmr+.Z hO[s&} znߗ?}Ȉ[%/oo;v,#[2}sq_4оWCk裥ylnt'j&SxlMO}5Mn#WN H!EvCԌ|elKZAS_m6&hqV%%ancSQ/ R䪙ڥnҭ!֪O݆K>z\>Q4=sK-rLTMES6ʥcsZ+l(-/bg.#f.J+o 5Ktm_ta֊kWm%r]6k\hh꒴ܑ.;n4goGB#MjK/7nkmX]gu4 smzܸ!׽ٍrm6˝ݖؒ{,;)Qeڲи:#fir(n(Vhx3uf^ , 3,{Yg)- 3ה݌J7V *+QQ}k]81fZڤV\nx6ZR4"s"̤"ѐm eL|Fmoc6YoRd^DdUCЯ5fP=ApW;c)pC;ZEYŨ:ўSe^j6L74~疬jY:\3#X#Uk#tf֒-r,R яo,ϒy:SXITLc Y!6ʘܴh݆N!ABAeC7(JK7WX.?X4~B^.[weK 7ϐQ֐ak] s7wȺmv m?Мk.ɯ&wԺsMڶnʵh~_ޢݳM%ݩ w&7n=,;`־)Y߸ɶydo?(P]g) T *Z6Ҫbon#R˙ Ƨ\EvEc3wML LVȮ3Sme[DcvɎ&lkeDLYȺ~e]}J,Cd[Sd=vʎh'xxvky$W.h=R]e;c wfWjZJV2s<-G7,~V oGZ72~gbVV@+Ѝl 1~ڵ:x[IIft[=+ej_mn~8QR)sR{ktzVqXԆ-QvRoXE6gZM >1xy#AQsISGyĺWZ6vٹCv8wKO\oڻΐmI 6+ҹwCEwVJw|p;M`[6?1KnYԍ|L]%/D^,yfUg=M^gU Z>4Y)^@$S?p4I D^涷 :ɵ@  Q]ֹyU9Zn6OUUE+sZfI! ; }!ۜ*g5(I Q9c ly5ԫoGyUC( A`LQn,_hx2J ocYUhx+1 :x ?]x[߮yh_rF¹/(NK[d9V%wn u{eR SDJ-1+ݒe ]oV r)Q}-rcjF+ڏ *X[iFmy-UmYRЍ\QKJjs,F\"U[͇O]e?Լ848Pfe "!^ٲ2oqoȝΖ2 o_˞Fٖn -+ ٹ$,h:Fn?h"TwW2761!̹nbd0f= &8W!\ hclhcr2U]mwUVoW}ͶCm?q%\;?>Um?&| 0o+"9nLlX ^_h*=04>jCuᖛEuyͪBI0GVP}?" ['To[v x}eIo@.mS_c|yj?x,c,I4C4 D|hjf|hFS`k(`Cfrlk?;LZ4ٿ>so~eeO%& E2_=,Uf.=\rbbgÃʗ~p@ΣOaI/FVN>B0rm-wɝѶ1# \׶>d_Dqn6%w#ݬ 2Zyjĭ7|c_[>[d6o0Cm=l]mqDhTԺ ̨M>D&;2sÿxsg#YS6SfTm g9Wmy5;ƹ]6'68NYN>}0ӎM$KUD7E?Lӳ8ZZG%nqNķkfۗ#v쪋nnNE| Sg *>Ȳ_)0O Sesg'rSn< ;;q]:cěKvHKr+Uv*Y%wUigz3ITJ:zSvqD#z nK8E3TOSI)!JUca,Q;&~gvb|J,Mkcr_p\C΄ǏvSA Fom.ׄHP6<1Zl?2ϻ1G?xٿ?m6ߙNz ]8u^DCIu9rZddi`=Yy->$"t|}2yq?7v!Ƀhߜu].wW>C_~dC+ndxOddcD0;hߢ-`F <|p g,6x]c1PM:+_?Lw\?i`G@7;=~8(/|`'?F) vj?X79xқNKAo; M{So+y\ћrܗ<%wrR+A7_7 ySOsw)d o '^_ w+yҠ\MW{ro7oW)?SJcok{kߔso7ݽ Gޔ7j5S48/bޔ~%?MMWrk=\D}%ePnM}W|^G K)JtPޡ7? ޔ׬6{ϯÌߟW8CzS{70{k|yl?p# ?¦Bq8ίVi8,'/,Y/\Rht4{O6/=s)woip5k.Aݱc5OH3T+ӕ=~gfɊ~O$KUPtr˜=Qt1~Ե LvJv8Ss|nE[YutwvEnJJ0\]rdzS9Q<%xzO*[l?;ACiqbNd]y:v淞y7{ 2.{شfϜ).emagQ?tiB*KNsXiHW<,ӱ9~2Y 'wt/<'}pg͙MEq?D"/:z~=IzA\e-R;w۲kLrr,g;(\R#2rU6{6jJ*.'_4;wG$GM8=L[QxFSܼU{N׾ӥ| jb䵧5_NƧ]aH7%8Yn%';!+XI=ARn*frz3;}}W7:xgsxC&ͪYо԰&^w|[ZQB]o_wX Dv*ʩVF({GtWԟԼ)+HhX[t =|#ѡʰ5cFkz zRډ z;_OwY_8E?<#U:^~-u 6+Y,1TG*j=~+sq@_imG*ڼ>꘥Fu=o9S?~C-ĉl|÷x ='ݚzտ=zm|5.gǞ>Rmϓ;Cۘm:+fQ]$7ʟmVݴaPĸY<+ &>bix-"n&*ڴݴꜾ:o3,U5k5jWX=k3+R,ԍ ֗(S֭s}} }2Q1{[TMޜ_:?6T;^KUr-mۮYQa=OJ5Wt O6ãeoJX@ dJ2ok_uE4yکHUm/YV"?dfnBqe/oJQ0#yr##gsw7)EKsyJwYw7?QÊ]޷~`'F/ꦏEW=қv}N誊4lL稘 5+Onjq?ӜhN9$9C&>B(껺pjgYm'-{FF,-okN+UR>5s#N3:6%sVUI:9-!+ ht'+~:Q1G"X>-~nː}y-)-ƍ1~v&eE&]unC&Ia9<ZmZYO骈* g'S55i^3oʒL}^Vѥ맧ڿ'KG{3t$hg}_4izs7/4u^D7,j~'z2N?-0Ϫ5v=`/ A.!q~KnW7tTvtc~m֖ztp׼ w65'SWΏڣؠJFP74[Z*ֳ3K]g+Omhe>xܽz /tHnpݬoe 51fޱ#cd!ݒ.n:c_*7ƨxM=Ȫ͟f{D1mg[8֡MAmN3\v!.<52GSN6OI׋Rg%vMUp^>sKI-.Ҙz>mCFkhb=3 5l#jÞ[ oti;bq$KVOne8-wIQZ=vuUa=mwIrpwbP|jʹ3%I![f'SZ og+Mջ)%7/Ǻ:aPop.霭o3ÿF+ iTkz`$]˔^]!9s=gs=RO0GN[sj]N";W lFpeR*ȔK~\Z7nVu*8eE8S[nzҧx.$rjJ,ycdT6\nZҶ3gE-Ҹԥ-YOJ3tYzYGkJSCGO_1?SE$yH8bW1QZxY9.2`oꍚXY=)v6_ ǵ p/:մ3G);4>n!F;zdwн2.U4USqpU}c:%.J|ɍd^{^>mlމH*= OҕՆZq}/nH7%Xe{so \z5znqrӈyOf<0kwGרBwgZl؛MǽѬ{-/xYyh$_9Y}\s~#aG녅ׂN5Yge[e-꽞Lr>ˉq/yN$q_RȶGL.Ev\勤ũSg:BsPwplMxr1笵Nfq>Iq n]Uh6!k;gbM@OmT2CO䳹/Q\:uWP0dpY҂3wai͍v"*J|+=/2әB8?\gij^l{dOޗ/$/#69Kx)q'uJ՜{Cnu*iXIF>9}aIy4Y'-=HF{\=/+:pyYы%zsW'ķ5^&t><u$geW]{3>1h2lj nʇ*2MbZ wț_Y}zAo? ~tzPUx'/nmYN/O$lWSR"~w0ԳSMYqO"|zڲ[QI]_71iAU8C Ms O?rېyFU?WoerWٗëZO+yYtEZ'_G޳nQoͪXW}$ayŬjX*ķ.v>Bb;J-(Į+ `z#=myMחNS}niЕ[򺦿QO{l(ʳ^\.Q\v kf:ALZA%wS_O-Zݕ7f%U=Y~{˟Bwxm{>`n\ZP9)VIVo~MSo^wR1}qJq.y䋇=Nн2=55^Q9J\OyZ8y_&xY.rG^YTc*Ӫ!~YghX۬`' 5Akjʽ-#b^X^Ӓ15,Hʒޤ[;<ʕ{ *Nt(9ff⸜Zr{<DYRnyM=mwkVGar?uY\]cZMϮk9ZŸ~[@,U.$lYUt u v}e(0F+gB_?0g3;6M"⸾='ҳ2.Rî{1Hw% 鯞^siny½%$8ٖռ%Aa*]F+{Qp=fy0i ټ蠺㝎kl(<#\Vsv!Ӟ)CnEoߌ>b)R9ktۿ5P/bEN?p*{_Uckܭhw cs\'{uުZ{vY^լbuŸsV5n1IҠMb7oKBǪ}q*{f'gZ$El[p>sLqDzIjOyjJȅN >nl(t=+ pjk$gQ`׭2KY6Ҝa0A_G/&r ut5g,x!N&|Bc^c_\EǬJSs`fJRLy)8YZU/EzhVԜ:1$FivQ㒄3˸m}WdK<6!׵IQoΆ[A7R)gRf>qH_{*^& ]ݞqy=83%OՁv ǫ,/־i۲6ZK3MzKE7MvD.D.sh1Ng4L+ ׻fǔz5+ڥT>O%vjNmC_fd˾ϛϤΒ&A&SSdxR[nߊ錤WN0s˺MqGߗ7{x<و]Y䶓hq`okag޻mESoύXkIYbg/Jm|zoE{pTÎ915GP6wiǻloW#.MP^95,3ɱ)^X̍ c:Cް=Oly;q1 -+˛4M4dt?2{p:>x=vy b ]cNz)k C]=}>HΘ9 i=7M<ý!~L3=YgF<l 7cYQw;?YM=;`_Of}dw峘3-N^Hc9Q˽2aov'dF,Vͭ/i}xu=_zܔfס5׹>g s?2ۭfbToy8o&(丧 )pK ͜$r\b2gwrvqnWtxGf& (OYUNJ 3Z,QQ~QS+"s /OzD-֥Lc"hr'PS~@2|!Ж%[3{|"@`dka3y<+d( g%o ]|X̥a&sz5dM6aIS  RŴuaŧQce&!CV>Vy\%U : YU\a vE}daØ[(Q*Iogj3-:I^5OUIJTgkf8Ō篌_гU@I.ӎ]^;fe](Io@[nL'LTCϟ&9iWCW?cJKxfG[\>%֋Nbn*+sgb >"/g&4s5tȘ9:"4ԳcݐA3cPiCUpFv`@1FŞQ:4I–#/D_)r_z[m@!QDFh􏲮İ[ >@ir2:Ep8:AT?#ҦI}DU9ƨ9;G}I`iFVCzo?OEL. JnHtQ4+L6љ*3 ^HPOl]33zà 9LUgsr0\bF&=o6x%[~)y/ =!fDﻀw` ~غ6avbnVx>*svHyݗG)a$]s, ?_=l&L7n]rCm@Z`7XklW7WFjl m 6~P4l_' )֚>ǸS1'D`nǏ|OL4=^ "I2Q>Ae/l'W]]m/)q Q:# ub/ 4)Kh"Uy\JS)>,'OCTQߜ\nhȽ6z򐥝Z|>Ez+¹$9V۪n$R씎LjW%6W̨ƶ2o{EY𯰶I7KнiO Fk3Z3 <.n"#,:Oɂ Y7rngpYL1>q.ŷ~9 ARj]X7It[r\HIxoo!NӧoiC|<)yۉvl=>I52 @7\7󭤣%Q7Pr=jkӠU)_qPs)m@,*udU.:.Wz|(mJՕ#法k BU6x|]!rX6Bڧ4f/o>/CJHw-q' #Ԑ^R1_o [w6Oo:v⯾giWGtlߣjCQ fe7Rz}zٔIOB*\V|9+@k51J0[N]X 8kC롫p{U1 7O+"7'L=/9-Y_vqP.(-m20.-E͋^\PPҌfKo5aFUL/=ֺ"\_jɃ2Q9U J${rr'4*#.~ @\ Zp[K=DG~Ϊ5,F.6beX&qFHr J'm7ƷU]g۫]v5'.+ 8,xi3P5:KY㴙AH3ƢG3J$Co PyQ<)ŋU;]`ĥӢ/Ol=ereg=6d.c}u?8ExN5P3<`Üd:d9 cՍ@&,M?B[}%˲} ,T(i D]I_A&r/4`Z貖tx ^*&L?&s\=C7`7+ܡ}Վ`)6 pb5E>XV[Re8)_ݭ}HZ"'88n#S=gikuoJT`'sJi15ce5Yo(w9\?A#L-s,'ãv=28+ǧpƂ+%{g' j볋G]6Cwkvҭ0&; Yz82̎O6Z`hTJ`uB2 |@v# $'֡?&9lI" ,}$:9ky:1u{mAK&cԘ9RR0fmw%;=c&Qb:`7wPYPI |EQ jpElL18H2A,񹝞Uo,Oeo%ZR+&ƺw6_m앞uL <ۊzj.P=O` {/X 7N'noCfzAs[[]v2>i΍q6`Ɵ몀z?N2~gܶԈf@@˒TӌGɊ`_\1WF,&aiVx󃽤rEEiUufL%ZՉ 1 ;Qh)Фn;+a_Kp񥙋ݨ/y{TL»VO-ҥoW Edo]dKuקvSeO;bPkG[{W0su&ܰꞅ [cUmE/O3U;qBN׭}o,_=mC]*×3jɒ)7uΒ𢄜L/=*p(tl_>Q#9֌/QOً S΅O.6ܬHn#7,lur!"%OeJKI)*З!-uzeӓn҈eu_`E/XL_٭ Tl/ĕm!#$TEX穨 _`SLg)BOJ=9vs8 Ǩ.;huxmmK$? 5WO۽JƍKgH˲WS7dсTv-0p$r*\> zĝ3-2gr"D79ު>%yZ".n0PuJd!Ӝpb$PaEvJ}sIsJP BƗ g|L]횡L +hWTL IodO(Q+el%7Qik0x>M W8@"8z,:hYxp'q>>?P H=6N#.#?#AWJ5G~$ee4ydzzlϢ!O~Z5C5Nd7>\Ui;j9wp7`eGYe;5lJTj|77g.\"rs#`pCC+p]bQW/GtO&9 @ViYL#"f*\෾v1=/oVeqWn|ٹmi h}ڲ;mmr`Os~CMI)%Uk-o4Ws3\MU?/G6NL G'.ΐZMRyZs@!,0fBdg.#C\)L0,hK4Ͳ1͡V:.SY>U(rx,vybȋ'Xd=\_) ̲:3>NY!&hR3FVl02ӹ[݊[ˋUK -`/C=gVwt$APD/=U5k2O3@TGXY+h 4` a$ՕmG·6Iq2lc|wĊpyyݶoVlXm[3zY~ͅ4#xa+Vy; .55^~{I 6Ӎ!y_,sttL\r0Gr> 4?  S[pճVD5}'͂60ߩ?txnYP=8-E:r EWI6$ڻNWn4x0iF$uFJ6 woDw$6N Ey%u^gMgNyi:Бnn7k-F9募 a;P.>JghS|Gn@-tKf_8$̮*$83Sw.&45`g4 w46 _K +p1Un"%KrG$yO”_7Xdӂמ2k=WcὋU s{ĝ D7TKXA.#NOVń1^jCRb_Ypc` Tڥ+5Ab"o|_׳9!Q<3g mL|D^t[;o)ƣ9},g$JL$cfi  /{߅,p/4T=P|e6"K2f ݿCoriE ?n6jX!՗d^.iNɟ92a t '$d2.i1kJ kΝ9)O;#SN9m]"4)謨ҤÊۣg'._/82 %ׂ1asawjH|A~KPHC% vZOj[,nѷWNq6/k.WWwvXh 3 [ϔEIAWVQKߘ! ѿ0'gC$iqwF4@NUXȗYvG3)r+MhxabugZQF&%i! 2@IԠeÏ cavlXZ;gBO*aL>"nX_]̨X4RJQL5)58YW^h6.@4Ogw\vmDGTڹ9I.&Aדtp+'d]O]=CS H.GcϼD^=C5!y^00Ts%kWPdQۛU٩I59[|w0t$,B5q t`j@Z!5hЏ|Y\h[O==ɖ-bg8߅q͎zXt-Twn`;&MsM7L;horؚU Xj@wt^ӵUC_?}B_M_|WT jDph}6~.!%'GXR[)a r 8IcBo6֒_nY,"܎]~3吃*}C RD[m L"ق:zs7:W ib M9+]Χo|r u8q!%K_8cG=gٿ;(3MUZpLQ[qwuYqɏ)5:BoW'~f*4c#9S掼 7r8ک?jcc1g&̽Fԙ#0Xxue#2Ef aF9gR($?38t֌ch:deHWKR ؠaN'^% q4I3~ 3a~OQUx$-Hve3`=޶~֌=,,AkGį0Mr%ޣ4s4|\,͐.ܱPt..+ecm7:;eCo L}K8Uj$LV _1/(+`1.l~3U#ފw!Odb%iMx􂤶ϸdϷ_UcW{zj2ݼsiM;gmS7( 9si'^?L yrJvğ25@/`ԗvzJKJ2N$ʟL4d=d싊:BAvlްL2):'5ך nDF [O\ Q`C׸{UZ8b4j[:ׄ|=-Dkֺjme%ޛR+HM~Ip*A4U_3?b$SX '"農0wڻ_k03hNyHtq]=mp{ó\pe1QF&jk#bmЏɞX{ǠyIDjGW>$24꽇V ͏m tQUo5\%1rH|#pРL8}0G8T֟c׮efsEu9Y*mfjHq%C⚡ZkNMQWn ]?;fhDZ WA=~}Q 0kn ?7dzk@CWlTE1idG48]3;P 8[m /.0AFrBM9֐?w:fM: P}AQ^b[]#py+8=v+qY Qfx5HZ \ٻ8KmDa|:8lf񤞢L盭&J_X'1"E1ȐBrD+aJ*,ɝpQ~xbiwsvJsX$)٨L^[y0rt:)(r9¨-8Gx%z+sΥqh2{"ƕ%3o wJ, %$3迠Q:'2A%xn%190j5&| D{dMZ7D?P'4CTrb3Tد4 ٍ[M$g5<)ƪ^*Q ulH 8o m߁Ҫ9߈/qDD^ZB@]IV_"?=l=% #E>\@9k5v S jj XĿV|QQW(k2.II |C>}L"CFbK{+ UD2_]v/@ߵӽ_pAATt7k.:؛f#1\T=-muqM#|c>j*دq70ss?lW=ncz\&^ =UfX:m{mz)l_hxm}ȧFӔ\bo; 5AES(šTKFjI譕l?"˄WsURz)czG+Bg%A%{ Kx ɲaqK?8-N3p*eqbXi#_`3PLZzȠ`oSNf.xhnPMٴLV03[*!!Dv3VJMnRFlO6'FPh:23~,}6GҍtՐ$p3*MFnOxQpKPժg3X^?&cJ%V.)~_/.TϒMҭg6 X͡A#kv vd:z9XσUr 歐(Uv*| Y6꣚Zw(!韪D'] ^3foFƁZd9#J_hNV?rg|8|\2F΋]f_cD}µ`o6>yY$ &X:0$ЏNsU$rRM f+ UrPa]s1.Ѡ+NuI&~$gT,j[;S2Sֻ9$u}bD0ʏ]EV_?aLD[zowc*VǨnmç,i];.uaP髯!&?\roUOA^zdF0`lPc|91s FC/XH%gKhat5n}enST C\I[3Ż5fgI_SrTo 1c!⋣*a~iR2~3\TTM}eL3Fz / lOY4 ]!b#,ZiQzM4۰Ɲ]?* %e; IїZS㼞u J?"yodm٪_A=7V+~lmahS'Rbtb *P&s"Y-]IQxrpJ<Fl+Y2zWt^1N9E8p鄱f~z3"t?GdzEږPi26Qa` ]=7򗝲.- 꿂5ao]D|T*j2X)ln!9+\@A;2Kp]g}ԁ2 Xs+׾G3x|aJw vV~bڕ{9Y; ߑ:YSr (`?HPn*owp1+΀#GOi#+ŠE 7ᣏ0cdQu8mb)U@SA2eEo7Ne&ڍ֘?<#giꚨ"?S8P#uV\ hV.Z㞃-ꏖu 'Vˌ.%2c v ռv!{pG# FӞ?OO$c>)0' oX09ݡ8JZPeX+:%Z*3_{/1 疽rI;cT}5a}߄/I*7f=Kn{'!&~Gā`]g b _cVK{^ xUB홳t8jČaʤf_#z:k{{|t@yd(+ nF]=uY]Y3moUe9 {@n Twf yMVN7`Z 68hn՝ɟsG3pxtUP2J`dVݟ'}Kc' !'fT j3<^ZNl8F0vSUM/^Xlދe2Oei3T ;3LfE;jVp|aJڈ?D}5`fٱtb6'񏝴tNw[:ݧ9׉ 9eBIR?` %5ҟM,&a4@%V$^0-B hN0);Eu_Pk@[/D* gh#O(_ k5Uudє]x&#Bbݕ1rJs.֯z~6mO>Ef .cq-41ƿU)y Hzm1en]^q!o];! cr(wT^KL~ª9 r/^Qulj>9L}"߭MA JN4f_b*Ri6|8 'zZ[l H%Xj»79=hԙ_+'rȡٚ0R)aDz!2DȟаJw 7E\:W3CEصz #v\e׋LD̘S}&\9#Sr%~smmy-z]z2GvM?B3E7|ط]4i3S/Sj?iA`a\Qpס$vxp~O+jjw[. zJE0ѦȭLڳEy 4t#3wH?ep _S~ޡ6S#O4\JhMN&2{Cr~fnUb{dRc*CLj^\j] _B)Qo Ӥh@컭t0S#u#FND,B7S`Czۀ iZhHִIޱ?k6pg_ il'LJ4j\\-7Yg؏ԅ$:Ǜ AhG22iuްB+wnP+ `m*MQz >u,HûTv >0u˴pOZ}Ƴ%Qݷ:NJQ?iNN G&o$j + dĸxhbO{r#i)>zߌnꥺ/e KFtOZ/Im{H/cOMct>nj%t$y -<%vm/Hƽ,NL*ԯORp ^?h>'߭]1P$LJ> =$"\ir˵|$oU5R#.ޡ :a/C2eA:HӮ3cʎ!/Sw^XώZ`a*/Omoy۲ςv w v#)Rc *ۺY.F|aVmTSc"1]]o|O:WzkY`m %vVm{: ZdX<*\Ϛ NE,ksK:z<;Toh@55i:ϣmf}a%QMi ʄ;a7?~t?8$7ORYRӔ 5MYSIf)MSNB攙 %,cV.XVn &`n |xys?}0tb {n݅պuŌzsbU/w֟#E4{|0"XGwxLW^l?Ox1>FEtyGA*ph#Q0)SIo |}d7ivH/-CrWd&Sz~Žů 0@.o4jbHfhS4ӕY}Al\@A\ܹ,GqȕA̩u[~{3#I 둊?.n_0~즉.hR%;X;]ϋ'7#]N&(_$~P9;IڍE0 KͯKyy65g!-Cbső/иq$hj:!FMZKSg5H"6}n]wO1nBdK[,~g5r'7z2U6AXi@I*nۋ5R{>Ars}ؿ<]zCw0-@1ul|wc{Eae$0.r331M@f,◹0w/ HFK>WPM@tIf r u#aAzbnޱCBL;jy8YIVec? 5E{-֋]pSYq0,!M fx(khσs7S/ ڴ$x rX%L1 $ׄbn3YyEjz%ט+AwkwbL2=5Nnf*dk_mO*Joգ1^:=jZ~ugk.@27Kێbė8uH8Sa'p|cd=%BwLءX_AcFᏌhz~ T~:;\fM~ldNM|+пX$\(z-k]H:s7~8ӥS>1 y~EbdcJCm# eT~@ޤ rp18Wϡ֙M V]DsW|Hp.aafnޑ1)%;nCiO%$niw%TgNlF~CM[!x2mG˼wkoqfOl܏%y6%44_[hjbYF:QaFLGwмRn TbTӟJz! ܥS6ث%5y^UWWxixL@(+wܾ+ԛ0frx+M5@DA*n gp a>Hb18]{v!E25d w.tP4(wv]cDf',QI'dpy 2G0,Gzc1$G) H&fK۬.h5 oe4^z&&i 5"uI^,Co/n,stȡMw_|f5x͋l=6T#6=ܷ늏ecJS#XCyi 8+2kY :H&Mԝ0 h#aȆx'jUҍ.Mq%}KCa~? 5y0鸁H3Mćd`t'Gij+M:O dBMz^N %2Ik -YBhr+'+m[whpn8Sa/TB#y)EК<ڙWzD4 "d:=,|#'! 2:SJSvLЈў]̵1_cUA#/MW]\ed=['Cfq>!rn G9"\,\ 3tz/v-gufE!݅ Pqfz &eJyGvq̉e3sfc c)qy:e|K'n(Up -`j^_27 I L$\Q.3F],p# h@]fIeC,"LOq4~aӶ4*xp&5Sɉa;٢n'rցuYS#uy0@ ٭H5ˊ=Y%DGTL_UP/Db4|fn)%Nl 笒}{$|?e=H~)k0 =~<ț#Nv ۭsgYb~tz!ZH,m7WMBĕ 9] hFV<̊FWXXZ7؊ʲ?H ]'1BF;H sJtoMseyLSg侌UFU ~ѓ^/ A=ߝ(8ldYNbxoHaEOQ|7*FOdib7صDdńfLEI'\3XIEDc׻Mt9^l&s*@|{,.έ;*BQWpN56OHawW)ֿWJ0*r*Z/'_V 鷳UYwƞ9arlC~&4͆,7lRc 6Vq4t;I 3JcjcsaXax`wTh4tFbz?MNozp&+SJ(Iti2CG {>PN?q89CZ$ tQ5jxN>UP4FYhi 5h]{}+pj]x:"7A^n {)z3}!Clg\@U}F:MZ_w%D^:澩Rx@[4LӥV4*WGEPX!t%SdLO1SĹvNV)A^l]5lˆb6+ ?SFt6o4Jw w5_k8\xx&H.i )"k6_ )V/*( ,Md1cC:f 3fNTig UMҎI̓Ƴ z!gޑgᛊE{`gk''4bX3}aWl:b*1?B֯:y1rWApE~R={a#A' -ɥ02򌩂!'A_Q kDS-#tW?=o9t6ELsׇ\"_\G\|xm'Yl?vh14K7 wSm%_WwD2'yf!.2, ^[]a>wp}: Etm]8җHE#Dlv GgDAm q3 $O`c팆=$4Vu%< Qmko7#s0f:kJ5'&o[~p-O[t_Kʵ"n/NVN~#%A dxvx1B5C&^O?Qnqü3  b9Oh;{lM !460|.ۅAə^BzR]ȚK@O';M|Pc`53Aq́/؉$jV:a#̈g3/-J9oQVyϾ N'\PڤVko Y֐r>d3D7č{(6mizĂH)m(gٛ]|e)p5Aϔp>~ ;:f\_nJ򄎸*8P.P,GZ4WîQf~wL51Ԡ\=ܑft#r:޳6B\Ho|շSN~>y"LlPAY5i;xD;oP÷yMr3.S3z;鞞6~5*eeC@T1Oj@mςUMlhUk#GWBq _{X FB0.٘<ɳxbT&NK5a 5g64%+fh ZYO7Ke2bnnB.o-ц g p(g>,5| f]V7࢈Tu=_v0DK/ T'}cZr_9+W3 3zؽU=>@S$zk8׽K~>~`#R}L]p˼dBpdĎ`8KhV\H8F2-9rX٘숕B%2oO \ czJӀ68pqmK-ϛ¹״ +T7&J~fԇ線9c[lC1ˋ߭*Lcgu (xÏs ֛Otgt)ۃuh[_-dS)3'P?v)3s |9D<.5'̒O2S! Z ;]oȀ6 *\ߧDR3聾ֿ![ C7*_ozo͜/PrT`/yZY+`o%C0DQI7N)Jsm:0'GY.xOnR5!!ƙb]ꑮ{d zӐ+oe;Y TmPț)ڵ-hӴ"єbbbRymc:G~+6f¢[( UBqgΙ>| /rsH ᒄk~Go#Ob.]a*r e=6ΨqP~_|DI* CZ>Q ;`0E9+TȻ[{n-'!Źb݅F~F}A~/Pb(Ei iFxhh0XP,ω a΄/(3O1v~o*G N=3!k[a6,:Zc91Qy'U3UlgnVrs^ӣmw8iUVIt%T"))ݕ4bk|?eW`#SI_7v}q (GgQ[Oݦ,izqn=[Lj>~iR-pu_iSD4 Lxs]-zHs΃_]o7% ?h˟//d(2ClGW6u^YS[R4č-2;v$;jWԱ߱]gÈΉBc*bN o˅WC> cmXMF|ɕG /R3!l4j}/MLdIHf#-X@^'.~Lt$--JKI9cr'4 >_Uo2&UyNN2h"a=F;@ԥࠧ&H(>ٕNwwƺ%˰/nm1Q> wl`^J[6[+|m 4g,'pP⑎~ <֖&Ȫ7)@IB3Fޱw5m,5Z7GnbPe;7fFbtA /-)wq WhQ3$rFl 9vRqKs֨s ~\\^'ځfv p3p[fj|.G.6bR ݣ8Fl1$Xj޷`A˺`3wA~sWfZoiͻ'uF\p,⊱%Ns¯v`ՊMV[~RY;l:KG\4}iU'jB" ;5O 7@/n[#HqV5/HT,PL'B_IнӦom,)`MteRi],"SU[kA~f 4 o.?I$̧ - 5@?$Z[&T~Dx.|oo1a8L=ZW'KcE$o'`}Qj-| 1h?lc.&_{!NQR 5*-kbYTS+l| O>TSD=/\e|3]/;D-eyBبaяݓi)ԱD@tp>.= 8dm,E NiZ5a?;Q'1AiPqr9SJ(qH!U5~>)8RM9r8ى@tnrs%\Bm*ͭO (9Cu#+o  :A Jٴ4AGQ6)uksNoF@SMU'd:_Es!ȩ:0sxQ0x)5o#VW=Z=kT{ԾeL)DOYkCmԕ+lY3j~5jBx-g %wrd֞oIaY(֔2, m<AE rbȌ'5j Ri\2d(y]/pA[9ZrKG$,0SEC.hn3wU,*e5meS+Bwd6N- '$N)1,^=oWG?g9'cvEֽ$ܮoV#Bl⇾e(-\n~l\\ ϯ HmŅڌ=CC;W7L^췑uѭbO-(C b_am 8 Sgii):co/LG| ަg[3!zq:\n[ߢ+G`3ǁ",SՆY]  +{C{P*2_s3k`w"`4 pd]=-[5(b_fZ|u)pOĖ3KXL,(D"c?E;dC:hP3  ~؋(0QbE|$A9X Xm׀|mxM߳j,VBf͗ "kkCS0*!'iAF |Graph#7`EEA*ԧ&wҖ* rVPoS^ȸ/H#=u :ƭޞ!,VJᎲ7כ~2i@{[wAʰ\adܪ=챽K_Y2?"͖ KN,eg^6{3^L`ҕn~ˎGXN+KU/ kae7FV0ibA %5+O*r%*pJ!l\yEDJܹih.]M![LhG?ĨXM1W+{8 RO{ԉ F7ji}"HBlHo=^@$һ;B@Ӷ ?C냥:J%=ۣnrt lC^Qȶ2?z}G:n fԑ^|-{!@F3Zk*4~Uw3? W&^Z{47EE_ճKcE"Ԩ<~p+I378Ӵrx%! 9uT8l*w6(Wp4fX4+&p\dTxa j˿8Z!piqcytrl=bj@ڝ{|3G֡T8?/!'%xbf8X U4Ej5*@ja5=DԖ{ra/s=;y)_2Z3,;^8L*@Hr),;V"M a3vieKƂ_2%hYUBn;W[Pl* W'HՏacspʡD@^&a+zn9[}SIMSu_;J6.);zMgvq< TDŽP qoTm:aPv 5k(Bquo^nRuMb R3phOtoGNĤ"+&bW$}@@^o*k˟=UWҚGzs"Gh(}f{X fgOo䖽4կ5T<+cU6( +f$} E'x!is;CAy"mnQ\=Rg!@j_ G {M# ߈c˶k`_~d|SFnfU6 q-Vtrc'T9ގz{( W1,ƒKLna 1N|$eɤ7y,d1Y~ff1cʵ$)pQ.۹\()%|9OKW2xr>=D$IdK*cF\ #o)Fԋ`Ye>+E$Iny({HtWpǕa4|溽fQ=k*!RKb{/}@mWn,8b|]uّY({VͳV RS#cv\l|g@Go3U|2C$&yuuZZ^P"|>&'*-L䉋>XזTy"@l tH}\.ԯF>$ bGN XJ4V~Ͻ*)PM y@8+ ^|Ec6c'G`C6ԙ,1[: i?ufK!$ A P4ߓCoW!P~ҕt-h:5ױL~$Q/z(О} >nc- 궒UM4$NUPM%poԽ*,?|^ʷ -D.r2AV`'_8P:+E عOZP-oS54on¥bAHr{}~l{U*3ED)ea5rea:d#}QFmoշoڍn8bF{#LrwcC KN2u7̣م)"} U}o=MdY:馽y.B ^5#ZCP$LJU*w0%' ؃wQd&o#sJJ$R֢{75W_%[ۄ+ڔS Mr;$%0R\Lk$Moc ?|8:ɸȈFN|'*1:Q("Qw jmm܆}d-?M/=Y:r aQ#?+Ct u!A9% jWD=[Zn 2S]lST@zTJq^N'3τ"!ME5aůP)ؚXYe,Ac~*_1Haڑ^^>If /!Ԑ*?L/ߊGx:!X[mKfPz0̊+̣͘{t~Yo8 Շ`of!B Ŀze٘2I&iɮIRqಅ$:R<\R Z(hJ17V< $.Sڄ1au.5ͳ /T\Ї1= -C}o>S.xYjBynAHM0tQ&=NK 11]c |+a FFwKٽ!,:gL[W̘Х,^1F٥lt@jq!5sq}%*d-EIcU5j'-Yp9eGXKykl v"jt1-%qRQ5PC#/~L Q&}d2 W?یN2Wri$U ;YF)QOv6ljbXeH.\Cn}p=͕EM|:IrP%\u]kԙG1@Wr0C+L?OG3p~{EqNf@͝NƼCV37mDҡÃ>䌧h0 qtQ צ `*vTЂK]ԷС_L\Kj^,"jn*5؛.4TA-zbwNbR B{6 O<|ȩ0Pܐ%70ÿXj+i@r$pC@D]xDKkjx8 |JǏ+}9ݪ|B=gq xP>ߟF-)9MNDA̭Kwizi6NG"7=@PRmqjOO;Dl dCx]UxWp]lzcqwp;Aqy7QlZI p?W~h):QIH~P:f]0!hA3 Kt2f\E0vZQF+&b?\;$]6Q{drj-40 Z|v K>B0A7Mjb&)r;H&z)/]d0z碝aI\X_O4;HP]mt&8[4MЪDp6hA0X- q{ IAJ*k6O7U Ah^OsPTʴi"vF+&ѯ0 07#%p!pA۠n``lQJ+JQa_옦PfFzL6 +. Ev?]\ 0'k*]!K[ V-1In3*sO5W5bFW۹fb mKX]yqΓ_TH>>a􏃰͈t= }qiS^F I¼h|PF( E W`B) }(@3GDgG%D3%̠|BO? >GuЉ+s&L9e~دR{܄ڇrdЬ6e *4&,L靀c~ll,{ܗhN,ƵBu8Ȇ{ղ;)_l ɵjvl^BKrPWa?T24 -Z?sp[6@ %.te]V=$0pu}O㍟/S^-Æu&/95!ۻia&F(.җnV}}nuWZV1:Ov૎_s;a_^L˗~͛w(E':_ʬb蚱OznUTY/Uaq 9q+)}#*7#xEtߠoijWh%&qf>AlHkzSwfa[~JHړ'|fǂ%üG)?~9,H)^b \)䋪df k_C7T P1y˰l~. lWur[St?EzB]s6~g]s_Wr jTC7ǐetHSP'r{8q1E&gNCjF@mCօOV~YvUҨRӕ#l /t>c1Ųx ykRUAoM yzPRYp~ش8k 6qx%}L([jCn.cL ?ݯ*%+4=8^͖LТ10711`$xfrO~sȮ] {W)+'X  gZ;pswf['e9}U$Mxh2tJ^BM0mjGn]I My2Xd`K3&GmuRd[s?o[)y^O1lR}L~|%v8.X??Y}g?!E M)vQ cj.͜M.|(^$N3FvB+ՇNkS smeZpzľ]zT,ˡʠ_mYgU 34a/~Gn>AUIW$JC0(J7tD-kI]ݡYhd{߾ݒ<3 y'D`(Q|F#Oztu݌>ѡոe;{>t-L>go4 qtJ$?ѻ e9ONJ@B5d $}~,P"Z,ǣyc>Hx/5:(a"(lX>T0L ?iϩLp-Bʀ5dH醵 ΊluhOe / kj$ S(B]#ⲠRۇx'-H=5A HUL='cB& J5/n[ ϰ ZjK΀SzrbcLhˍSWvt&ߦǮoi2wO6^ӧP lwWmye }%p²_ 2nH0d8{U 2R;#1Ȇ=q'ԵY&eYB?8<%j2a\NikH,ݡX3N53ȋ̈h#lʹeFO21"㛕D?IA@iMvV] yσ4KԌ$Px},G 竽̭ l̺.s-y!ZWɔKâ9)@Q?g(l(ll_vHrPāwP1sXhێXwrz"+3j'(bU0v_q@$["dW]Y,֣V] VMXCPRNBGXyRZGiς ?va\!Wxº8]g!u4X~nHRCjpaYGlz  9?g,]Df[ݪe:yO^{,ͻV_b)oNsuRҶ/R=)u*v;jI4IfM"z1۫h.'l[4Կaֳ?v˞+*SgͯofOQWCUvݸNs;}QE)~#YCBouNR !b-_Pe"6evw ϭf^,`MWY<'a_ _ϦМXK5-.dpqȘ|n. *}юȿ4a3cxc)/8iW]\~uuljŸ8G->&Z Y\sm-ybh-^sӬ[%QCˋ 5x5{xlZĶx-]PQw+J]|V\JwnS(,f~ǩ9We>Ո^'`) &*Oe|p ;J 2]F~{eCuP[p| =؛:)YBLzı.ԙP$OBC"8O+F2\kߺ[ G f;$ cZ"}^vTy]9݅=ifx($LaA&!nʦLKǔXՆ(寔AY[`D"=:rطI30Xky9?asRDvPI@yۗbř¹NUd 4l նhL9F m#󡞲}❜qeլTt-8õp凜z.4p PZ,|Ruk.z9>;_5,V做 s_miWB?(Yc) t/L?#|` \H~!<@0x|H~e>K) tH(Ҿ+sbX[nw{uv%KSuQ(kZnu|gCQb@:Z'-)]1]-OzKe 12^#Ѯ~7T*>t%' &8w_CB;Pw 8۠~$+xn={v vFఌ?Gh9xCvvn5 tufc˓@ZglI[:a(ctEx0nw%B$Oۊ*vja]=d=QܞEYrL Wt2&IP ~BHP4Y=9+Ig"E7ܦk=蚨`Ѕ]!/tCnDyg@GmDF+;=:<]"iZvqnqc=@t +10 ԽJ:ـ$SvB, =#rD~TQ3߀[[CFixU\ߌ7~r9~)k,n]Zڢ=!Ro2?ǜ8gВ\l 8O*&߮]ǔ2߂Do0댞a)}jOC1:Ҏc#,ƴG#Tlu(VY~ {&Z Wo⮠{Rv:c#jI?M4-9嵘,yX g*S˜B˘y#,D%eJxͺ:ӍkM0Ղs|w|a&HۼW3UmmQ\&5 9@m_YT= J\HQ b;(HIoot"U°+VRnߣae &9l!7`nAЁFami'\O$.٢eAjQqA'ȁou1%,ըVhJNݙknw{Q{HmJT@~a5E{Țxݹ 2CCT V?UE<./ŞJh5#Ǎ8;-F3wf8 {՟wqU{Tyċػ$'7zc6cgXu:SWISG,xGAe i),jߝf>9s߃k$LX8Gl.(ģ-8u!*STX,|ט c (lL3x,2Őr]n7X;SD[qW\0MXDN>|˩T7]*f^8>Ziq1 MtodwV;c5p޽? k3ߗft9  r%G6ѯ:Z;NB9|_McȮ8e9Hsv (e^\UQ^2DbXb#9>&Y F2~gOeSQW#Co R8V+RѲ&8xY?L9BVBcK_3#; :`b5Az,Y=DZvGyQ{56UX;Hp\Wl&ĵ2 ؗeb ?nk9v% :=?] C.!X+㱕wbnU_MH{bo.IVUD-t.8~>X }OM0y#Lv"3jD+ H6` I ꌦuYW?;rրr2di jd#t-swË[dSߨsי$hθ>K![E<2'֢Tt&V7`!Syb! eWβ8t"9{t?97tX}(rhG$ vt5\T8|N+'\E7d+p 1tV.afBWEm3#ե1o_SDuHX6eri9L0Fx~6vDS$qR))=vٯ_GLȞJ/C9DdI!me<`J"9VݤLQ B¯B$K}a"K 1bdno~Bjc 18:QAל0zsn+#FF6u!\2& - ߫b%4Фp70|_cn*[qՃTk͜  7^!7oѽ>I3%k $]/_Bd)" NDIj &կ":,%M'i),_u{ܨ nFbaó?T#B 2=;QE㖹̾} gY@6l& (?2z)'\XwFh;7r+ޡ$]Dm2ɯM2]I&ų#]c!ۮIEaS[lٶIJ[YbcPHQM3OyFWpťo+Rj쁦>m*?Ҭ-d Vb>[F|~1ΚєǺ5͛n|I#]q2;3̩sA2~F$<-tjĞY.éR$oi60`ۡOf뀄({: ܨ+1e9Su֫&hMW3ʢtvW0G(EbS9䐽wGݪ%Pun~;|P MI!b1ת~\FJ}f$ iIjF3J淙}kag'xX6k2Th2Au%C.KXiם&O% 6qBEcmi @ 䵺Bq&5`mg3dź_B/ZYdLNeE׵_= UX9mD/cL4;`ʜV pӴ"- V9:R_}pi Xk0KEox4=UÊ=Y*7iqg8qv.zߵD똁~wLYpj@M_Dsj*엇%[Vcnd,'&rdtC !CUF,\`{հ0w{Mw\Q_ݭtGz"~c#֝3֜T&Q"IXh᭘fUl`#KHFKi^¥D3M4@EG` ,<|DWcNqlL\86qWnCgCqid*`d Ȏg ~T((oh:!5/g5GjA~Zym?AjIld&nW/o`GǰY| ǂ~xLX[sFe>df38wpm09q\t\WOqR EsK+UyIY)ۦ4b CtaNlbY:r,l]i钖3x@}}[%x-|7L0!rCncTD_;USIRqJD]sˮ5p&۽2Lt6b!V10 o{Ĉ} wo`X8~Rp68 e% dIGsDQKt!;pST6^=_N*񘤔3tbuoAh[? _! +ˤh[}aEGdk7G'&Ԏi9; O}eջ~پ ) xnĶDUq^εؕ%9D4[ ~xMِ8TC>ya=2w ?ӹ 1>g {tSbS̞K""X\U)cfЇVjV*$W3Mi|q)Em:Nhqo.dg. &o]@*Cyi=X_J6*DDPyqH\HDؒy^d&5 7T_괠gz2}u6b z +ceBph_ |IQ8 .gTsͺ.2, wPb,ГJ*O$뫡}B3 Or}UiE=n=T]jW-sk;9VԊؐǶ.Vu&MϻarYwQal@ڎ<6/HkG'q V펤Zު@l" $ ]®(X1w~(XmX|=Ͻ_k,ֈ1{f.ΰ "k? &r] hwT P:>/9vw% }wA#:8A)F7СƔ2E(MuWaC{+cͻg"~w8'VS 6,. |4=%3O !T|dī'n/R\4OW MzzsN-jf2VJ!+~(j=vCfM<}i ]u4i'ՅWZmJ4% 0%  Ѿ1°OLJҫR錨%=h·ܴ7?HP. $vO"z`}}h<&.i";7"~E< #eh{~nue%Zh{ PB gsy'VB:wC 3 2fks{op:|e#C,7 ͣUZXۨ0RwM` ש5a/_WD탎.LZCw?lVDƤ%M~zx$R<,KV>ݱ %U¶",]weԀW 9%/߶~S ƛu5fA\Yuua5_!k@r 0ZԆ K8'`M U,8lPYg5$q+ 7&˟s5'Z>~U^rR"k,`ݎW!l:SVaȠ?zb}w9˲بkw =ZR/?>3OM3 /SCFYUXT^^ ?+WtZ{,Dw5j.4~ꀟD|r "LnTq|L,92.HCؿS`|5=jAIeH2~Q{i8F?%W8Z+P)Eאkz&LML0-MFb} f;ks+;3n\K{ cˣ9OmwNN~+WYuJO e rrzr9I.SS>@EBn3o:ɓdnzA'Ᵹػ[E!a &=\5A8m#Q2r/S  ڸ?-ܒ/t'.WmTNƅoO{?Oȼqɓ#Pw}鴸a\lwN1h9Be5qV!-[ƽ0Y@z9aZ܄leX[Zh @7~ 1a$n<@o6(S}ȈzzuWl1(69mHʛb1wD:, $dM*6$N Qjx! v3Ree2烂(6F8a|2ãJՎ"4V5.p0k~s?SX+mkOʙ MR&s X6x̍M4p׏0_"NUؠl6.OVua9{f\j#v;N?@jܞ8 GQ}өRBz} 28ďZ-wBz* bUҌ qQ/5YRgپHH*؉`Qa1j&,mqz{n2FH.A:Rvp_Bctˑkl#Yuލ6z^V"Dvv?TC`*::k)+f3lO$__2(w;GE`5r2EY`WZ!̽ǝnOR/Ԫ\ 9gةeZ3-'+mnݐd(g8 6u&? :#,1TUovhvP^)J(2bAHXeuh{{gs6\q,SIẕ#H dA$0ڗLR6aR\O4U$}"zm0#o=|z2$ `5*1 d'+(>cyM,ۊf#QQSxM< ´)ԪF[D >cؔ0ru#;[9~>OUQ!έ)rXm;i.Nq6yV 20"#6[NfCqO4ˠMG[VRB:DRum$Pt"V^R+x05u̕E]][ºLV^4s*T>U tjGԐ8&Xů!MchԽRBf؏M^.jsf\:{)?6^ 'KGqhKQ2w߬uV= [uG苸Y54FZa UP@\ ZUm6[  0O e R& p>j7}dG4} yrO}6QöEOCrL14)nU *kIU6MQ?Ey(sTG [Jj7k`Scs7ASͯLhNk3—V[h/ooamќԄhN>`.@~0Yu S"͘XR7‹8zxYd$`^y ZĈb;'g ">G8NB'6Aj՝'{w91RA>IAf1/O{itiB& B̼0Bm\؋D3# <¾\Ҫ2# {J3UJex{6I P'- kؐq Jw_!9 V i/wXHB:of~pq N {kM]V3,X=tUX+0h~,Qvk\q9zv_CGR bǕT[r#dY! G:!\M^rdbyvytzEtϏ["~$q+${mLr|E.dbX3yItA7x=I~w˪'ZkeaQ}@l;돛nEנLQ* Vnu~*MA#UX^rL}>C^jk St mS?šLǨ {#NY ybuY|l :H$G q'%^Cݴހ} c#zXվC2R~<0S9E[y,I5֫P|җ$UA^9^V`i[o=SkWp)'#3z3FtWe.߲FuKWASJӺ k`=wcʫ*l; w`} D{)=m\߅w!N2<ʔhta`JQ]mղgN&ۈ[`J0K{2ue1ZXFg5^?FQHB.><JШïr`ir/5:EqKP[W`q=j?xbuvuV=h[ZR'7g=~#HctST3pTxIT=p;wҾKmWQjJSit9:]t >Dn pGb)3\WO[jSL3"ߌ9Q_"=>V2b'P xh2(UDorlTfR8$: FM6-tPFaʁ[ \#aNe1EQt {.)%7~sTZZ# ;yӪ#;/=ڏrc8]J)X[tٕ^_Lk-#4 (LLmkVDs j_{嗁`^tj~YB#TZb O%LrʥŽ^phBWdJ TǛDTRZTSkt!hǝmG/.9:ьzE437>z\T\v[>:jZBG u7[!/DZ:L3 ?vp W]==eZ/-ܣ1e" nMa[ w$0呿vGrkʢE}X m1a\57,N{cDtzLt=~xO;}@ sMxݴ]he;G}I_GS/M?U`sVD|3YZ!~$|/,$ߎTFi&W\yvZ0z3`&>?7I@r7@1Dn%JNSv#YW ]ƒA{|4ͳ J;Zѥ#ft4.¹M+ g54߸t]T@D_WfVU\y ot;'; % BV(NQsbR<Ǿ(>^TUHYw23KYb}4_[Z~xZ2YȾDZ_p.ur{#%;;@4tV<}c'\ ӊ3X@7d:&G*[80`.&o E;ak7w 4#;.ha9kS`GcH^5JYw̷KxBbxiKU, ?̘mdKEb^a]һi,CU^dj{ K _Z҄wL%7Kzu}U;[h49 OIqV9Za7~f.|gx ,gBTL} ~ #ƒ3*` TX(e% "ucI[WVΆ$)a:0GvQpxglFSM(T k"Jl1VvP0q|E@V_95LôZ&rg{AY"UĿ0LtQRXKz1Y҄/QhSG_P]v^C ٻ IOL*?uoޜ%z`k8nQp?6Y^.VENwSV" xjoBV; e*;0Dov3TK-L]iF6T0 B(ܴϬ,::C^tgZ"MQNM C2m< hѐP9rن)-1i _Eg%ˑo2^vyEF6T|a_X7ZRf rrP0,Z|d\69D햟sGK{ڗڬ~"g5@ !O0Qֿ|c:9w,9dmJI4kQC& PQ˰'-S#uՌXD`Y OO\Xb |U7[Av{Kcc&&rą[o5cRU8C=#o{>]w,ץP߼x+2[j=OIXV1)+ƮfRd|٠_mhqwTGR̻ [Wt"_﹈R%e8ApF[Yq BOa@i Naw$i b@svK~X, #{ #ֵ2sqJQe`OJ" m<6S4p{6\㗗iOwK<>=m15)siX?_%4m^:[o;mǍ7%:VY4nm/}$Vܳn%/~K51tϘD~Sj]9=(2+kOQոW2sh\}rĬSAs5-ka| )9׊馕04ϴI-X=mF7DqlUl*}4CJreLUw|-3oxqT=NjVcWPtI6t-6zM!mڨ@GTdc.e/U+[(?;ft=Hm{/,&iJY2p-Y1>P܃\&ޑGҺ Oϝ>XIae;1{,N#S0Z~ !7W]|+ ) М`R|S*̻ڐ@X 4p`&dd@˫@SIzyL5͡ѳi_J@dMS)eDůof= nxf9I-Wz>UBPvpi.E-v*%޿or,J)f}⑀fW H2NXoip=b!O:xC>v5鎣1--ՙ^tUass}QqoP_DQ r!# %ҡ&]5>@s^9:Yi#g/v#Su,V@ӟӇkbo=}"8lTn oj~P@)ۈ2M).և=/B" H~KfUD!rw6q8Har[ Dɹ"bO#PL]*K/%+T ޻LAYDQ1}MarZ9lj U8$ni]bMq",ؾ~2mer᜼E3ZILS{'&OH6b]W@ /V%ڍny޷jEءz|qEfO Av9x):Rn?4xY t4`kT 7vPc7vSʰ٪xIAm'x{tC=,'K/jVEQ.~ V_yT'* mr^}9!dYet;޲(zN(:j"RKMu|.e^Y IҢQ7@WEI#?%ogU\zSIC Vg 3|E!'sv X3c{f\ p#SٴJ'<$zX7n9-ZvAz.{TÊ8HQ[E'MGi2սs&DZu @ppYURyscK|[=otYS' b*o5̛hQ][:^ :]: 6S'ދy;ȅ{8ӢRG &7XKǾB\HERj' v5\PdԚ|ҜRP"`Q$5$*,;BR4aY6i,5>us?trlLt3%PlɋVxȃ ZffhyrUy_s-)=>etjFT:C7ZgoZ^S<##Jd -\yM/icq.?ez}L.;|H-SdS2.dji­H30 F## (ݠ,O>+ʣw4]ޭ* cڛ+4<+fݰ.rBD,%ρHXMv9a|jZ]AXIk=g[_ )u?Rwf3vɱ=AKc9dj}+&cF1M>{ب߲ckCBp{s"VTWvÊٖ퉡x{w 5Xߴ7 p=08^w'tfam`~SNZO E͙ѯQWMnN6QnvuB.0kDKtęlkWKy 2MBvº1zY]^wyľT$ n1f+[; nN7u+,3HfK'B=¶sX3­(F%? 'Ki, 6=wF͎H=Ww̮/.34qoK&62`Q>i6s&pB,I%%]Se縼p'[uY'oH6 t~a#G+-sI2xOK%PIH|favtQKo5;R5ܐX>k_ҿm;mQgZ~u3ߙ7ȯLj "=.,ՎoSXuf+!őUi˜[6dyh%G{}e5GWBdܫnu絓7"ص}K=fp]:}=z -7XΎw>J@eI'R1>$v-7p0QOñ _dt?@OxYE~)FS$6B`%{ҭ]K\?@m*S0SV['鎿<_n5T>G)`%/Z0ǭh+ۏ ߬ywe4A+ YaDGhy)T X(2c/z{KΜ}9Ӭ^llW||qzu(7/><;/&!$LJ<Mj—5mksd?`-=E2 !J j3H1Řƴ|oC]15`pkmjj]3qì7Tp+ȶ1#'˅A-l7o ^`>6*5/!qU)!^(AJgSVHLtу-U8N9sRlU o5Xu'QUPP+QWK}ޒ2؊҅kv){xkg|z.GQ]P̝u؆Ff}z WBcJa v.'o2@ʊ{ .u؄/p1ʸlsXtn}P0ܱ [*%a;0\KB0Ia[*{3۰pLnU`rR (ޓojsZ8;FbR'L(PfaRQ$nƺ2H|ǴliR>Dk$`>*{z||0:J/4BzuʊҳW5v ~B؞-D؈+n ?@촧:`ve26 `NY,O|qNRɚg@->4P<ȴ7;tf)G'Xm8߭"{OX -]QT>A(J$Hq.#)Wq*2Y, Hӆ^8}0[upNIqQ酻ڣ}3(N=arCNzM[+L%UÍ}  L#ɇMXo{&{aZbuq!55X;-<_OUaNv eFīxKy | =$鄦+k,Eג"fO<-`;df!f ۸`h>qscu~[%ҳk=|,:I%LgpaA$Jr㺼;t'芾!9_F<7fk"V)|o”@CrMk05 Z7 cKG͆'m=81J_j|oDvUu,jE˒puƑ0O ad ۂxU =Z6>!( ꇨׂR}_SZ"_Upiŧ/' !Ç'-N$Wq&Q&™_JjJAU3c}+ 3ٔ[̝j:5D<&-D^a_#kMG,{K匊nI6Τq I(*?Ub[V{aK 49܋(N5PW%%| Q3aw'!'[6_ \'ܩqx];l\*Xlyfgօ ky_ krB\8^o·#%5Yra.Nc* NeP{v7-jl)ŗkř0gB3Զ+mqq",;H"ىJݦcjʁ렎 +M NƯZKt23 o (ko^n6J/RcMQoaeyf;L3>mbm \p<ca>+6+X9/=a86*`WP\VNʒ&&DӮ%9Νp0:KA`~TlԢI1pEyPL9.A%H"vPJuirzJ-jDx;6hP"ay>۲ y%1C5?Gm>\2$7L{w.9R'д:9|a>g4uqHZD}J WCУE~!VvE;;)2 6[o[<'~,QSj58Cs,NzXѷmi-PCY#\f"vsಷ*Ia+6s]8j65pFH8C5eWlf=d(Jw_PM'79UK7CǕ浦i۠Y\|fzVIz-oF #Q@+dXm\WR(-Rjzw*GŶ_ 7=S0M/]5ytf]I+%v\ߩO1àuFҵ- WǗ8~ފe5z&U[ǘہ`T`q&nAmiȖ G|HLYt\>] J!9絓wNʰʢKRUCNiۧa^@@8hyYCfrbKa% @7MOG쟆 ."77q|"+YL'UVDڋᾋ);gΑ?I D@s[$&-$qkċU]#F'ҰT~RlzVQe&˶.G_{ nĹZyGE(h4ו7P搐Gl@09:n x5rz=@(eXB!b|k_,֏64܀{-WBD?ikM#ZbxͰ~LZcI\ r_wmDe鞲gZ%RmXTmZ(l 2ɳ%v$UUNjj7哒4Qo-c: A1P?Cr4S•c<)M/$ϼ|]"M:GĦ>hΊc)x&l2(cm,*X#Q' %hm iWT9/13ʺP֊^ܪI0S')20#7Ufxr(bDu=^Ōнzzˣ|UXK_cZWMxN `Yk.J1 ļIB@:De=nj9i,mGݶ܈sRUU!Z+>!r25J*JYE{+<clʀiKŋ)ꃟL uMzt[..W\y/77-Ӯj,Xh.fo2wUF㤪qB4$\<17S<2ij9$6nz@v|Lq_ ΊPnM+$wsy1flր1_0K_)<#i] I5q~:$o'lHПd(Z7| :'QbC Ct"m3 egZ@3)"YQ P^7ÙW<Fo悎ĺe+`#Mik k@yT~2ǵ~/hI1OlاpG 1 pz#hM8iJ>6n+{1$X8 TFf:-$b5/ Sh4Ù;洄:e7#5iHɨ1ZN$`"4?ruE Q|%X><@-/gUbʺ4q8OT%K}}.-w`z1z=4Kʆ"HfZ")IJ שےZڋ/H9Į0_pΉ v+&9ZXBb^{ [ɟ xMA[bxgxF?G NX M8J!.Kޘ8` KHT83~DӚ$Bjcx DE)E/"{?Vxk *0e`]h̬}_g stmPs:-NVsD;sw,'nL۠s.VɞXO7\"=Ҥu6Y8= Z5Iq7f2h |$btU^i9U`LBkiO|DGײYWBo"Hd``]j .ǓM军G_{ B>1}؛S|dr[{!r:S^4VMw,-S.;Xqݞš!9"ǑV[?EWӍS }`Lp ayJH>8~DսgӑmW05 aE)11{CT <|̋n'PVAۻ/k@rcRO4\w"^co$hPG!&d^*U%ObEkr{ǶrGgZ[ӆ60Lө% K#VQpѡ2)<,]kzn.u]EsJqJ&'o~{NF*LZJZd2#&[(Fa k3 ѡDŽ Stx{0@bngC$f F~ɿK3V Ahi=/VI )/at%K꯸GQsstqMcqo=[0ec8{\3&&\/֞^l^˒5:Rvu nkMyl\4ax[gk3$f:ifdt^@%T4/??nZn3u,ګGɜwX?#۴=nmnꅮbߍtkT.`>ưV3&sFD*><W9f a>q k^yk!mDT5O-+&BT}c XBM:BOʧ # ISXzZG'])zslWՆ^Z߅}U1}P*iUGUnhnJ@Ve^?k@ nPnM9kNk r饣>o \Mg.f{FecXA;\";D,Up}c L| (ʓ}ѴY PL,u[`Ueq/}lLDI>anqCEgv[[;c1m^P_Uq:,r4^x+[|SiY-))R7eTC#(Ee=lM1{θ!u|yge4CEcċxAAR0cy5]Zq:˅Hbe8O>=T¡yjmliֲ%1H$A;oJ(Uy?zN0FlA9ZA>:yӴ>+3бe}X>`@P_ۻRN.cˢՅ?xeW~a?SaC+)V>bљԐl_6H=~%OG|zwD° fwV/iA~E_:o+G_Z1r~LϨhC~3cVe3!jaHq9u x ]'_5Y:. :IAWi|0i i< TSM X9ym(t.~AepC?eo%g˳%Eb?Lfd4 ŰOڋkߩ(4uK*ۺ0G%Tu #! I&>4TDҷ,w޺7"51zצ%SePx!k"E<[OB<%I:<@ENjte9"".D-Lh_1Av5,(Vi $wOl=5^:$դє3c?Nyp59+o&H& !QP^>#mjg 8  w4y^ﶆ)r+KPy|z+Ò'pm:{sK #=e%Gҙ%qVNҮ”SNT!444eee%"[d5dP9Ff憠YK&; yu~8Ah@Ԉ*/e430H^] qCj~uN~?DBO E|c)ڍ< 8ZKg=KdDMLX R{VwכR/_ 88ּ-? 한Q*Cxuf}JqӺk_I{4jCc(eEC樻K-׈: vL+'n9I 3QZ{n۴C߽Z[bv6,+Y+#ÉOXX- j0>pfwx'QDgEx^U X;AJUJ$f+R(bNf}U@nD]T5+i_Xd3W qRoikhSuUw& tO]}h߯zlug}&%r>b__f W}L3Rq0>;dyqf˰:8b2d',-G'Yx6&|{%Au .jaeX!ZY·vF. Y9q] & ygfn %uXVXkӳ>[`1e<$ zґ)tAɠbyHfSp5`gW3y'lxu%,l<8rԒ:%t'_OG4l(Rь ;,L$rNߺ;enuP|jV< Y3}ĉtt -H<꘨)͌1ߺG[sJwD>(%"`aܛ*vzNcTVT^ܟ秴vS ^;n]J e\ s38/dYHN hڟ3{%9hCJD*ފWZ'MӐKN$ϐq-yad7*+ѢE')np&O7@}Ƨv  (89H1) iD+R&:RuEޮU^^? a[d_@&)SmMUkmNѩ!y."4o(+xP=##(7aVQg(@eQ챒%ۈh* SDgG|ۀWB}=CeSm+zz@&sФ+@vde8@߃9=T^}N|nu-Sߛ^#DAY$4&tOW^L 5-K smfӺ_x9%@mdKXoVI~(ސC[v-J} k*c,I2,z .@?`qx}Kui.OOo=|yqr;x4`^'7?+e٪grZL>(/jקWo7#8bbӵQ8ÉLqXBRgлa;|Js&Xh֒ )56/1&CBo.6!' w_]jiw4kpO[܄-ID1И3kTߩ?aە.]eE&^mw}+Nr;7h~Zt6ޞUM@︗ZzC bc8ԕRb܄uf)2?YcgȺ! TzsD|/!欚 tpRըXxŬh8qڞ3Z:cL9YMAG[TJ+yo d =T( N^'>gBlHo"вJ8aydؠL;VwEblyR/;޿-u ŋQQ]Gaݱ*6ilx5**;^`T i׼?|wz?fϟ>Uo';,׿5}SaNY| (xvt#ynk=&-oycg ( QFg YW_$Ɂ ɭ1^je?mɢ$r+ا!p0eSOhnjxFizúŲgçdZ_UE9ƺx@E1/S$53yyBRIf;RͦU_K6n#fJҌ9>n`W\9ާ IlDL\/@ioIBf`ZpA&c(2hҠbl }g68AԶ^~=O[`SRZ0ii~BlCH)8sbcCp묊P=Z:mتȶNLԇSq(Va&K \j(w) tai9&Sfȗ9Y[ 2|>!wV9Q0M%kvii_ PArspIo- B}#7a ~5h5ͮ _|,n qІzȗ/WK3zw멂\#T]_)E %IRYe)Ӕ^3Six%՞~ 9i%SynjJFvo乊W$ 5b]t f]!+_ >Ӈ9 ğ5Wh{)ٮ~'\ȀPb:=QPS8U).h-өf&ۙ^ќQ 72qZ28m0؎j=B 0k7I#[^ρ,r.Pq bWS> 9(5qmX1;¹{P>HbY}W)|jqXwu<_K94GƂm@QUd/z,oEFxfG; ɲ, hӗo>,֢TjMFUF2=u_f {el']1#GølE  Ip?ȊS9S+4 )NנHo/b6͛ryi˞͞ znpDzC[qςEbG?S%8 b {2Ø{د!'pUוld~ f\8 M͝[<pEn|)[n1xC+\듆)2+: _Gt`s>#ëHC|Y>vPs;'a ?U8(c0<íZK!7r{s=B۴i[Bˉb=b|]$] Na#@'%=?O@) -ʣȜFYPɢv^^GS@۫ɎɘuF$2wmX jT!Ӑ]lOUQOC>RW ;۳|EI4j^>;n֙Aۈd8}c7v&7r^A.q c6w1D#yID6aXUB[<*lԴW pHN5BF,OGn8+w&QLsȷV8]T" N'MLժaYHRܝ4e9JCBnAN7ǿ0WxKFH UN$Ǜ7i%Fz?k: #Degw?6I ;_\w߽civ.*\WS"&uO>-*cZ vSCt:NxHzaλ-q4X"R.PaES;?O|ln825#z?FZRgN0~ g?ѕֺuŎƙ6`zmCOWKtz,;2'{|t0Xv"-NÊ])jVQsiGw__܏Qkأ$mtpi(6PaܣHS[2Iv$gK05KV>XJh' ϡ;{aE2}i3hEdb.{l!MhX [cVch.[KzѮ3P}1}VVw&:x3ٿl$IZ='1 3FROKB.%$pTQCgt:0rճ]q`_wC.>mb|Au%f!0tGߟN9{d7o"NƌhNXl\>峐Ȱuncu?<%cO;f-h3=ޢ9Zy|ǀG̡==khِ&ofKQ&QZa~L@$Y, W's[YLV>6@_pcfes)L6Œ$rB2FjnܚapyHӚ; WhtN1 &Z6zEԣ$e7M%⹫g;[|gbHcJT -:h/WaPjY6p ?\RaKJlHEOf`pBFwSCZ++(Q:x;(]>2N:j" W=%4Rw%$a.Y R6羅2jj%S/T- cEfDnߝܭ/k̹!^Or7Ԅ0gڇ}<u! k^I2%q}@:; ?R;y6icPBՁWRbgP~1B 10b&s, Tu73ul20׼>CGM[U?Z bOsrD8z]C:RUZ_k2OMßڔ 9b]FzOrDa4f 0"Ia5kI2\sOAA]OGr.7V.s+3EoDđij<XTa[ JvLƲ,qQ |B I>oA"lU`0Jj(DR@-q˦z&+f~^{29ew=#0Oy׶AaLwhCF`ME| )G9nMs۪/POhb.ǠyEkU 2\26W&ք|빼EV3CF ^/q w h%>jv6R*3sH6|2A\~q0'J:KE6O/!ۀDġ0}MS>:ضq&NAd|g#>l5&?eHg}ORH(nbx {Qe^YSo6SV}Q Z!`ŢW&JbJVc1sKRמ`q5~6F F_b}}wQۇ_X: #|)LqJ( W%tj=qDWF"x: 3Ij OSeqe}x[8bcaG7h1rS(d |dj=ֳk&~D ɎǶ,_VKdqpy@AiY(nu%@oL*VW;ebBKyKPCL!tcTrMOī\"V^15-]z)7GIfQbrXn[Pkv+>`-U2Q96l Xj#P??#m2.yq5B`=1m]QGs% ӿn0W92.|5[rK<4\v;ۮ9tūP EnU hsy̶{%N%\Sv [i0W9nT oNU>HOTbZA~lbr}D1ziC&[{^{Pǎez| 4oE{dCÄp@SF6P1c54 P—eNK"F>`Ȫd&nw7pk 3%ԑ> ^(|);dA˞i|ҾY6::Yű  @x6-+Fq2iD tEf$/o' 1gwHו,j91]%:x>ӟ&51%:VȪKz5SAi9LwA6IW qZp}?_G@0)|ެde!ꚬ?qu9Sl(5 M|L>G[ן_!@K^(W';nj ZKFy*uG9;U'ʭ+xћ)>ngwniG ov0;LU?7>Pcׂq_ )Bk bݦQG9KFX j10ې FNs cČo]$xu;] >.rxÝ̷sDBoW4qxޒ`Ahn^uU;E0qMWmQÚ¦M{x3.UkeWUo9,7g 7YS 54ϕ}8N*Fis뾘D_ȎA[^̣-."o`yŸbZC`LF~O;βK<&]LRbtxX`u~k OŸV/.-Gk`\Xy&{X*/'DJ**;1vFCaS֪<­=w QdVA)w2O9c_RSngFQ#osH/" }.9i:ċh՟,g{Ah"ɳ:4l(}֬,%2[ok+{6rSGoueϵd2AfτIUA8:n>C_,3_ 1IPA]:q N_p* CT&مh2d)p)ޘ^:}>+XtT(7ׯo(Q'8pـb2rC7p1"p<+;a*۟+Pᖃryk\[MU?enVrl&H/L QGܺ/W`:KPP+.;4TQH&yÕ*&i=,6ʭ 'Dp,7ƙ15wpln@7!9l"PW+Ғ,eZkXN™)^9v{De$nkH;(5i L#)ӰOO CveҕY^/d, 05Ie(3VXZXPfY Z1&)Wlnkyuf=C MR_󑙾"Õ=AmB+uKQR.O>*XL8(l,J}3"1o+dMoPub(m%mf9uvVqڪv;I µޛ7&} GtşLrSt㙷*CaX}<mQ|E'Lk"!-3~Lըur U'!8嶁Btwp=-2Ta^Ya~C- } T,_&LF^aw} |rpdEh  "[3v1/-fz94RS.cl' b]ؚ6t Dy|aMGLhz''W4g`/цh?Gߢ.-#kn}Qdy53&iWD={,D\26o}I#+/io'hmk.S K6.lxMhQE20hap"IS-lf]4[P)ܴ^1-4XGtH?.H2ߤ-kU]mNM}.;#!nrlԁn 05Ɋðg֘X+@,n:ݐ?۵kSTTNKֳ%ݚݭkWVh]/>f=0?JEiUi]}(ÖÄ`ٳEs( NޤVCT=cZK m#w}.B^B~$Sj١0MȬ>~ b] tXuBwӥԫ[&dݸ3Fc:[ݡ}:ij7C =}l44L /? WzAl]x;A&(SAıA@0 w F}$]Ú-;iYK-iy@D7>1η\3p7tЯnq#3/ KLwVחŪfᚸhp!qr،˳Zs|{i Fb GoE^2f4E-Ia8"xXE'$KGeYLa;)%Q~!VrEcG8_\ #x#+tv'Ӻ: S= mTမZeXbQK<$غ-%p)8jim\#`87/ A1M31~ %UGhK'XjM}:'l+~(iNc_/S-9j0 yzK/sDN1.%A3,W%VङT+ +^̱~KA8 ?w%apMq"Ls4dV\1sEբ ɏDXq>KDggH_4q~kNx=ܫS i}oQ?mbM"xY;( eWŇ E u%`<1Noϖ&OE1Iiܺ8 ف4bgZJPé)房[<6E-_d^)fz){eX \xs2\#>tR߇\߁u˜˺EWY%p),&w BwFy"m)ޓ4a^#yQK'@x -N\Z͠K`U{ z7;F>͎~Jͬ[ }#]--X&FO恟Fxآ gm icT2)Vh H(Ж?kT%J(&,g?FT)@(mĝXSM0ɕ`dsl:.*>]h_ %ܝI0n `Ql;a~X MK'p 5H~Bd0a-ˣ'u7y.3Mk[x~r@S 1Ku٣n" 0 R&Mb-y[/z%QehEI \ &B=Fo vT~`]Fٍr;S5H8V19$u`?ΓLlqOEHH_y)d$X/ #gwC}_onw1dLjܰs>lz'4W^2nWxrfS@";59 2?B͉?Y]p+1rPV7i7{{5)4ص`^2GxhAonF%\`]0+,1Y@}=wR7O ~ov!*FVLbnע.}zte9:#>; Ⱦi5[{P0Zye$ZT{o>V1ے*//)X[W%nUG^w4l3v=Aب E$" ­^Mx=a+O1{ } 0ޱ#gMc*MF`f[,mnbP?fpQyYq|\|e[e9rJ][>#N4I}3fެ-uC2v^toN4U9V{->3}C6WnA|`:~B,訣seI=Up'#ж,9&c;g-.C&6G?[/zss`զEf2pK&ܱh3_ܖOb1 !F>A[ |2YxT(]2ki(1V`jXf8(QBz)xskݳ/UvpCnK>wFE BLjf_FԁĂMU³QSrw$3ĕݖOQ\ws,IxQnEFCKnGl%?=% c IŪ2S JtQpax71+Gu|Xqz@;YWv^ ')sъUj9ܷ@E1@pma^;`nbEˍ:l.]̤`_9wiKA0 lg>Lەcl`I`R>;-J4UI>Dn 13lHf#ۊHk5lְX>)_a>c.|pr,eOȶ gB-^JOzRGfO$|yh.%9XFD+b]W\ۃE?`~:8gx<{0>1饂"dE& 1cڤQ\^?(ڪ1{AjQVXaG1i) -.sò ["ab?5{׿EdRvȎuG}0DT(-I-'* Eȓz NeUKx:zjv*9xƑ*8}jRix N&sT)ԔܙDRqmXόP "sCǀ3k&~։6`ɛϐ?JM,=O;͜ΐhd*r8,Xk/C_%} `~E. pNsz6T}+{0qV5pSst1K`ҙ6@Og#(v`~jQwrPdS)+ ;eL2v;"]3+%:>Gwm?g&Q]!)F{020AwkSR#K.+>unE)ٌ[g 4W]N7[_ۜ&RYtZ_FcSTnAv9NeŐ\cPa"vl"Ewo5¼[36tʕ,Y&۹p̍{yZKZ<놉аJ%=JgXR!w1߯xYUvX}w7 WsokUv0^*fI3N)q5Or;'S![ |ZB(6E7[JGF1awfmg3(qU4Ja[B@[&P+=:_&6!3#$|e#Dwȸ¥iTՠR3wD!tVLsZp!5Pm"rP$Ujgm<]#thkQaCFV\-~RPO_E(fҘЃrS. G;yLUD*ds9;?3"M?8XVBk+jaoDB7fOUي1.NoCmEӡ,Z[#?f0 ")!¯uLJ03vN Y]oh,g @vGQ ҵ%Wg,lkr+/=sXŰcXsIwb<,+2ٳK9C12 ]e_FD#d f] Z<-:HfB%z}S`w{⠔3 I{BC=5;~|ܬ-7z:SK_ORqO, k: }9D |q5,"7!2(ҎNίkaajwB֠HBhO76*eEzPܺ@5hM'm8G _"3 .MURw =וљ↖53ݚLM@q>7 jZGTIMP07_v_Mr9wgV 9+p {x=5|[_CX BRG**0&b. g VnmX__A3Y/T ȣ|f#EՑVD{W]Y 61qDϕskBg>#V,Bnt}U°Ȩ]X\Z'?%)3Iu#eyl ֔P:5aP}3Zasr7lFcbBP,*5T(VYix̴ˁ/׿пߚ?^ POb |]wv%}xͦN&v*z!=_@ՠ>>-j'W|! ERςL5+DzQAc+w僝3wTYXo"K{=UW*t[.uAe@X's>Fw Q=p4i,Q6 M:ィ2 NelW+uPI*6jE!^uTAGJx$x݆wwZ9MO(C歕0 y,1eoQd1(PAsrcIf,˕k9LG~w(<'!N/B;v&]V$q29!#D G y(bSG9:( 6 X0@:Cכi;F릀 OAcn``G{u3_ڎ1Sź4F<٭ƈs TFtSM NӵFV}'l/:黂TxmlLlo)D7M _Wqe8GuS Mm|f 5,PLatB1Xw,unbOɫ%`?R>L h?غR#ݱ'|D3H:J8OJ XC/'D6!GW`#1 ;m>[v~uL*]3/I4tLe LvK? @7?  =BR3(R/gf옛`lCTNkϖ+f Ml;xVIC$lxc;ɆlknmW kYt(w/HA׉G";@QkކZö ts2kF/3(D7[rE+߉Tce=Qv.бrC_$3/S0#W @ԀCKbXf\r?CT}Y,ڢ9VL\~yX*]&b8xX4fo] nmXML`#d*tf&iH`wf@؟>ZhA7X|JnKfkG܀ScVgY(شGR'_F T4^P;yq# @6K̕V& L6<41b}oc!b5FUv!2 vЛ>oJR#3 afNv7bsAQ䄆@mGdg7zeO㥭#~ʟ%Ym-Z vHx<~:l%t54L;Ѱu H(о|\:Ӕ]QE|y7MHzh$Pg.p;j6^B^[TUXjCa<^/6tߺf2Nz0Kv$'ܟi /IQQnq¾ mVJn{ ~2Kٻ&MZBp\<챎-#x!yOTlO8C;@'mo1C3U;3ē4({sۮF&o.phf;"SuĆ~ڐ%&c/ V+~.=GPEpVTHقLRܚ]Wf(p jQ4֩YVQU@]6[%O[DdW>ooy,H"K#|(vF{X{X̄lteiP5q~kU4L .=~ m|S)uw))DZJWwq7:3MTT 笥D(2cj9o&^\w<AxiexZ Θq[}6akC ŰI WY>o΋>1 yxMI7aNӛc7,w񶚧]V&_$û{6z4J kMC;xB2z$a[%Hu\s ͜\FZ$}; YOwkdUYixMV^ ?NY/$CeC3eԎ(~˪h\WQT=5ieaE⼀آx"tUQ2zXr3[nBА{'K܃1&˷Q9:8c kPTZ×gˤlαGè9u{.Ng!b8tq<-0GtxNvrߥn]>0pX3op8#1c>Тo4(ǻ.E7Ά,:o!jJȐ◺)^]cLl_nwg#3Vl{jX=Y>fxɓW-;&"ژq$?o.~ea^dW1l`"2ocapﳱw .T[]yz8)$R|R=& GQX|D ˬ uB#OL>KaK珖~&.Y%fgqtYˆp?u\2?n_hasߛ>mk&HQC:}sn4yY[hY/NJ^qF8O^Cl=l-zd ބZs>U:Zi7їP^nsXpBhyO5ָڽ 5Vџt-J]f%~ -e{C_5ی ޷U# ɗ] X՚R|ji+{|Gz[xgeVW춉\c}jO]毁iegsl)*ƿ~0K^K{IZU%g]z>oI,hKaBWqDhq:끩H¢ft*l4 _*S8"O:n&86vY7ܶLkvʚ6Oitw ޽^JD^xw{D-Tt=c IQo"u C bzRVqlj#S~MjgޢgGQ5 ,>{<[g8>+_%1YnW4}ߴrОLjv F_>V9!w`Ln쏨~`ݸS?q *NAUy_%gK[I'ԈACEvB.٠9ӍGOZ2N:qKCbJcA7@bw.Ϻeo7-DŽ5}.?zeߊ|E}3 |Ff ya9F)!xV+YmvvL {\Dd)206R4,t;kDZ@/c؏F}2D2i6͔+b* ?;W_98U9u ܫRsaiQԄ3J|É4IՏ_WeB8v%oC&_읓98"AeMLw1?M8ys~uFwzYsGI3oM^;ybϳS{^]M>~ُmXOgybL7J.) GV#(M5A6_WR㡺 R|Gb+Bw(Q/s6FNi:,8922O"HFzsfY>av?P|}Lyzdu/zsDU-O@S4Hzľ`a~yYחD c,Vrdop"p_~c\46'|?SmOW}F3f5K)m+{c^)dD.̒յ# DJ)LR t5W.tE [$n=~ @v5. :\-p[1I0"Yw^Ǯ)=_kRKȦom*ьŏi%k Vidy# `SJ-u|'WVS(;} ir"U{upScQv$QuƾkrWaﰲfI>#M+ip-[U"ϽiIb51Z;'oaR k>% `-%SX4ѨorK&YٸpMgʘg٘8W?N}VWv4Ic3Z 4̤ٚj|ƚe#ZY"MZG@"6bDX4JIXՠRrħ>IMoX4~EA ṫfN0fsNn]cjΌU$qqY?%CW^uQ€ʾGDgpaɏ@w7djQ9xC=DaMwzyN&\Edȡ7>C>9ЇF!:oC̬7,3rho'+pi8,({{<85X z<wvY8yGl4|.dᐢ_\iHخp xO%w!tT;Xz\ӯX!s땫$`pSzpxjcPțE}o gxth8㣒=prkօzˑŰ[mkCaM@睑KF*ZOKtc@h訛s%TOt7Pʄ .uJTxsn޵ɋMe wCұ ʯy}`7Q/kKΛ7|/[>ɨV;n&e;p0p(uoDR[%(ScHUrQC~`ਙ7ّӢU?BsB-!@ئfhu/2ۮʡ#N?>l,akUm9*/lI(V]]M^vdi~B+A̎֠..m+WZ"˦#b6TmTuϐ=|b`nv ƴ.gyJat7K]ԦEsQUш X}l܎[zM'Y6"ܜ>oY/E{;gcglpu.)!8lm)L2ʫg!Y`Uوc]K̒0s7nHݸ* [Wےy_&_wEkx&aKk= |Q FN%dH SGzc A/!H5Pޖjsd18v0WS`A 9JF eW(_Z|1XZoJ߄":\K.ARq'Ӳ!4i~>z劎۪xpWW%*'{lx(pڜ籔lSŸ&+ךmVi!=#M܁8Ϡ[#MXCeCOz6I GATMFJ*0]yV 6};vWcrԒw=]]{!Z\*Ԋ{TAd&8W뗻TBw;ؼB"Ɍr'ʾ0S 6jÑDsv?):QsC){l~ب ܬpJFAe}y'FGuk;jƅ4(ZX @DF1n#CM傀kX{z wzqnn{j]y!Ba}OCsQmnr?>.Z}oEz[N >:'ޖ#ڧS/}^QA:Tjc{4ڛ L 1BǪ{Lj>JRSlo^U Vͼ'͹HI|Uͱ;}>F3o 'iS"so:O}8L} ?~_lbrWצ7GeEWxęi2elDð_ p |09M#i-GAfFy{z4ʍL ɶH7ң7j2K:κ;yn.M/\yRk䇇_ b:`ؙ㣒`萶cq 'T߼XEѕjxJ,zMz[.&` Y.Y6GzFbߵ6Czc~he]+@*`kT#|Ileӛ=*ZlfXj6;+q.vþϣ1n ښQ|(o/ =:)yrO 5صSaG_E8ty$Ekuл/eԫ|=faoe?')n+2(VpSs+.Ϲd{e KκWuuumNSDtDjD̢b+fX{ .牓] rUɍ)o#%D£RՒ '."nNs]iUǥXgd.rnJ463fUJ4 9j2:)i?;c¤Wr DXZOo8V 1bҗ~2 |cWw~J6nZݪ6JU2&{g9k g2ٙ7c8u*φ7(SaC:G8sP:.<{CAT񙱝tzI: ޱU->z!fЎ vf%KVjgIPuIeky‹*Ί9K:KkKɶߏi*Oĵ㒢o ab>CDtҨ{A'U?]rfɳk!R gg* ESBK9֮7<9\[,~-o,5Ǥ_-iRzLL~ߞg=q"amEge?Kzv[S/Rf2(9*~TvgD|23v5 }׊L0E+H45}+fcgTgR^vރ<0=گsO1 Ru͔ѩ3R)ȋŴpV-rUIk+IۀQ3˾c;2L1U q*|̬Z*G:Ҵepp4{,_ͤ-/emt PWYXPsĊ1^F{ͼ$aE..>(ɝQF%;ܬ$y$ P|lhMQFyPj'g$T5VRMҏ[o;$L#s W>B{z Ml2q9 'BD)Tʪ9#z4SRv!-H/ie"L9Vo\CD\reE1wӇBt-fdSk7ZIR\eRgnm.l/3(,bkYTí#-]a4edGse:9Q">"]uYD{ Tk0jPI ?={ClyzƜspnxHޡOF+0eq~ U^F svT<Y9,A^y#vBⳍrŤt94=[R.p!L*)DZGMS9e:ۧ, vg;O<.B%VTus{*UeSI)FD\ ^.yny\j;v})%W*|{R؁wg8ޑE --,]Dv+6xT m)x'H\{OuOCpˢF0ZcJr4)w;&KSt$I\AFJ@;2/ Sę̀7Mc]kJ9nnTAj23n>E1 4N<9̸)@A FA7R9s3< !$jKeN d;"u[ia4 JUP :'!iف۾nrZ `r۽5R b ]U|$m$]|3F{E'*sr;Lɋ.UJJs<3cS Q_;+YOYX6^R?ܣs y}xhRvdobjn'-&YhVi:Rr)Kg hee<(P{QVl?]R}(c:-Qhh !:*:4ŷ;Uu-ޯ1NƘe7zxQՓcǍ;ݤr`jvBʺ@¢Meu?U&(n*mwNF #%mR*30I* ᧃMRdd^MIJՕ=9J9,%jgۅ| zMPy8iwGt݅eqhUpyXZ1J)pn%]5w8[Og򊒜Nmn"Gүdm+m;ڳز`BӃSP|8TɂT'}S*7F OoEUb\5&2|~{:UG{&M=h?EE\= f-f[alu.Ωɱ mH13@I٫j׭% M|D/q4Ѣ`=F˳ ,PT^l D y+C7)uqz89p6!G{~XpasR)t\poނZEZ`eXܑݣ^wy]K'o\To}٘TCIRQӦ{ƌ!J=COX~>%U~T6cEY.[dƐ *|_؞<# ʨeydXѶm2}vΥDw?BtN9kGCzr^2UI]݅fad>u*3QGR1%mekJ8zW!RkDzDg 7y:Qi F֟a/,a0;fxw|Пz_dd0{SVLPS(xFnLreǎΨ1RqחյԽv"V128g# =]G }rD#Ԉy8ڢ?"MP酩LKDןMVK_x}.mlamiH kW]WF ŔuY-pOz >׍|rh鮒f2Q*oe7F'(G+ESc"|In\!|ϒ{%ت1(d_eAw;g!-̠Q C#]A#;o\q@}3M mmK?䥼2>$;xex.~Uz՗)fye>R ȖSRDfEDיnGйtE:kg(7u[k]{6 3'/J?75 5n(j}CG$ 熥#OO s$%%1}hFm..E1\®Dxp%Ce#pdnYynyagLL2W5v!ruP遑Yz=sR<9xQa},9纊[U1mg WFκ%\) 0Q\a~!ǂ1!]_&H`HH1.(%Eb27Ix::j_p[p!$hvS|σr>7=GRDK0xe*v#é [P\D9;-6bf_Ïgi7=?#̧ /:b{>I0"?j7!hT(ͻ^36|l.c݃!G\Kբyx ds,P Rꨍ.o iVuqUn9ڝ;`KVE9F@&>+v7U-8g6a΢(EN+2 q&ϼjߚ%idۺ(0,VpXżE0睵/VUX˛'~}Or%}V 9ˢa о9XOaawXOz mJ\؊$gd*9 ]߽9JVM+: >]Kaڛ?L`£3RJ>lmݧFH O,B[ECk:]PCGI-5as"6wۆӸyj;KTi ޮkZ咯9ד~{m|R2Ya{pqx'7cMx>gAH|a]'{?;6!-P1@Erc?N}r5dT֪zRxsE|הC!jK~g8L<xЂcT& |}7oP۞uh[qqt"h6İCb@E]FPaMyע^Uk:d]ۺcA6-3~5urͤ`+ZųDF6?RmLD<:| V_iՏ.{&Yy/*Zy?Dζɠ'Tםǚ̟iG_Dm}z?erZ8Œ+ 6<)ba U8"6VмUQG+"1qܩ͟f-1Bɍj֥ u"okJ!'wVνc1P݄7 .,RN4_,g4UU%]ZE푪ju*QZJDTժUڣԨZUJbc(AHI}{9s=›#;lvr!ET{UsڎiT:#/)\\V^w׿I(ngG~P"X1{RGy#s8^aa{%x?t ,|7nk8jY.je%{k99q0 (0cwبY1/`~܂p4hW+L.T68!=,B 4SG*ɏnlrP ogِsPB/6zƸ5!a,Sydp.DD84Y+Y37;\XBxLG!?JR=B'C+1i6KfUj' "-Ό]fjwI-wX}Pm@ R/\T}5ɀi *u\] .Z_=(׈MŸBdIȳAb9Oo?ޑ}S#p;Mne,T 8жȮMv_ޙb;>~4QΫpħpt췸Rr32H[$b*rRig Gͽvii( yW|)llyd٦&չlW̅rOU`yo8L&cs~k6]Ȃ!nΊ]k_Nl(M ȡ0{{ǥƬ3q_16Z@!/cW~f sޔ IRqYrw|]}=\;?"Jt0Mb*{oy]{mPPPl,ԓzUQB"ٱ!y7$-W[!c"y֥c!Ezz w,jusO7f{J >BafM0Riظ}w|Q xi|rw cWS*QS8[ϯ338ɐ6=)d^ev"$f")}m>(2^$j r]{4z lZW݃Pg/!29EM%,hJ$BԘ-[)U.RHi[f_ sEoCAHfYCES|yT~Utf77Ep# fTxk}(+g$`{LÛ؞@@tmZ0z~igXrGH#y*b2 p {B(kqP\mKU&ODytf(:6D3!06!7-^16_}eA3 գ&nZg |EkcYtũ^#~{Wb/z2yrusY^] #Ym<M29Up #VM@Ԅv$DXJ˨UB% w xTm~[,v_jC,~y{;"ݾ}jd?[bO'ldHnWrϊBtT|af}PE Mp '~:Yj-dssqו2Տ-{H/`bJRLIEP t3e3,rMw/]AݠW5dMU՘5/ pM~gˇ>"ʸ<%s:nal:?qSScemK"۔k@ˈ4" \'X1eon,\qXsb'CcWVHAk5ƙq8%A}}>WűdevFmHLwwu+c9L/6olzn-dR2RWübc#5SX5>2 "=O̖LQT&zݩ '4AX㊋kJ#J􂭘WU7v-W{yL쫏%]T6mG7,X $?،ivJ]zu}b-.N>G*kI:.]&[}.ڞ);Z1j  įaס=nD-ׇīTJ-x۵}~5])EwWlv)/< |5f.CTC9b,%ƺ Bh$U52KLݜk:(o[ZCϋފCXSYkz+9pb;m/#1|m8.}YXu zTygsG.ZuWBY[ɿul[FRR 's14'D!(׸p}ŢtQ<`Zk82[؅.uW wTuPgh:di)9+_iXtbOij5mIv}ڣّL^L GxF:MЇ yƓ's7Ncc0㞛D4`덌XI&ʵVdIl`嚼 v#rl^͌IbՌ>7'"MgZw$Vt0"o̱IPb!V;g1k._\o5~Woeug6fIx5} G'H '"lzs)@/*?4 HOn@ L"Cu#FUDTWyy8GB'D#g~[-]}8=]`"|u]@DbY-8wrCd]7\AȕH[6mهKQKwI#_08Afkm{L]i!Z焳^`OY ~?@#VsC"%{DOޖ\R|N6ߠbrbB>~'w5p~=<[=\\S>JH }QM]'_p4Ԝ|O s$ Dw=eijW]"¬$tNì]*.T<BiZW+S<8$!ї* uٯ?$}#TQ`5ݖrtՀzm Uc{hQp[Xl2bo6Ao%tXv(0h3-C` R3U g&%q\ݧzc>8$]a/?z  #0]edKGS`zEnV)]yZǰϣ $a] ά':{jzh:d&_n${iҕVY׏3~Au5sU'.O<]|,+S:gaSACC%vgB:8zePv<[3p 4}?6\7NUK k1{H>hLM.8f,K_jqU\%h7G]i9;DRY"/Ldi'2dr=:9S~Y9J Ȏ׹T7}i9(}䘁ix=@Dx iϨ#gH,5_ﲌBnydžAPέXQ]lʤqFC.7W;r^=#so`*]7p|!h0!up>u7p\5eA)\Ր3ӊYCs%l,m-Zosck? h]X$U ='8-{hS8э!k7ws8_'p_Fzڤ䫟i"c[ܬXN*ޗ ;]QDf1(ޫs iV@ ,ԲȻj:*QHes1С0^upJ~8Ysv=Y7ܨ5CJ75ڵ|C*M|@iIMYa^+ȎTm8^!1:g?o)LW0xwv.ఽpZ8~+4-/ Dީ-$uhb-ljwN'J`!+Cܸ{9^IC1"DAyPPfk4y8{?R q'G#Bf5V}zs`/OZ&CCy;d(+ CWܮi_ׅCB,˙ug}{j箬Z1$!@e*EV*9^/̷?PR@5 tz&$ZnN-[1KlR|eVqKUQ $,=oH̕y=Ɣ%ɓmcLgJ5K J/4_hVdN"X`g7NDlSW[B[PeDlKlUl3!q;^ 3->BfIHf^gpEbaBPOxO[K+:B݃2͇kT'R176)ќ?mFYZ+ yqTo9 k buJY ,'wxE%M_gQ3Z+`n1JuSV~ Se(9Z͗WV o Ԗ|b4dO-1ǩɫ-*ڴu7.\3lmIӮd\up⅀f}Vr`܏Vϔ}o)zڡnhUݩh*!HI9i&6?T:ټ^ B?P"iDoIl~W|QCDW٩;eSʣTrՇ) LpKS  脿Hd40rLҺGQgP\Z#Dy*tyuQb_EKflݙIz#Ԃ5/xv.Զo%2#ftxdƷ_}e}lY6]񷂍l06bv9X΂Xn Qc>Fo.4xI+l{!'3Ah(Eݪ5 ȟ9Q:QZ+Ywx?_*}#ݎ՟U{ɭsK*ocb^g$M9]8oV.tL0;WHe{ӅkVD vlfwN95ct{c^C:p^sLI:b#mNw k!0^aqm~sk[Mb4BjD`l4oTVܢ>p"}qՉXxqȱu.9y XqӓpH;00Ɍ$Qou|t( ? ,De>2$ ώǴ2G|KHuK(巚%;H)`5p-̳m[Fyf;6&0U,Իg cIzH!eYt 5<6DV!Jn7JOGMfJ?gm}s!{64 9Lxd_o\ wĄ2a OV7 ~Bt{M;[C8cLVCS &myS$s.64] H | G:g*UbloEcOP+J)GysoL;h=[\z0`ctz=VJ7y 6pfr@@[X< _5]~ 3fMx5:m717 I݇V@< yve~g9\t;pi{ju"UV'&^nAyK5|A(9ន]Gb,lӽU{JPDĵK aLT_m ީCV`eLVjEhox/LZ[1'\Ҵ*ߴ $h_Y6_QW7}` ,4vja2`?dg'=NDlNucnYG"/>aԒRy[5›h\R# Eo?̶ 4KLW3ıоk]ࣝBb$xaSFa *MIIR*-o  R; VS-q5]xS݅*yJr~vxƷ̴t- ;;+`'!U䙺^[A,iwr|)@lRɛ xB'&vwt7x]S}4q2|2"{z4]~}|MM.9;\;V@dcWCA x8kvm>LOh7f؇Nh~UC"a 3qMK0[h6p #->V}CF|қH^`~qQM ޗ͊Ңxt&Ւ٘ [[}E[v]; Ze z/{Y=lWn`O}6BUTKS)< VHo$FW|e&[7ˏlũFo WEV Jg֜,njK792Q. ro;Q¼E<ߵF'IW!"v/G=P]h{EٱxZٲAƦXqҎ B/< zYT#uX:"4Z9 qo밣 ۉ)WEtžCU)NEsTVwQA@mde)AyJ9s> r)LQ.B*~;yzi\@֋ZÏa~ 7!aa b;-vP஬q0^K»{d ;ݐ5~薀T| [ԡtk\^ ::llݹWNojF S=ݷ;32O_ ݣZhڽdKnSRG'fDaF, s.X`:w }歰UZP\j W0wpYJkeE}]Uirg!wmL]ˇ\6䚌57qj4K O# Wݍ3PR#ϵu~sI|7'G/n͵x +m~Ac|܀^%Ɖqn?]HzI$ 8r[5$VRn{=dIR[kuN۪݃Ug,z, K/n]}[x_c׭qCJ@ijPNb+wf^1 ;Wlބ?D[N=ށ.T'/ѓPlu:(Ʒ8^lY{x3Ws0ؓij v٨QzC!'RN3_+MW#@̃$y--l@68Sn!Hf2LgA#.B/6_Zfui82ºaUY'\I_͛H^pS<(-#  I<(^`To3y>4 s|=fz@)ΟtkIekvuxhY!Gf\*@;쐎90^j:/@2z4@iOE-B!pN},ȪW"&P\s[OzRphAj'SH(`E  M؀ԃhס;կd*ο>GuiztKߕVŪ?~_LZA-!)W@RxV|^:[~Jm?pyܫE|mQdpTs;R%QsSɉ?h><~Dq)N^X:fN>,OV[i4k 6Eߞ]+. y|{dxk!?1h0yBvB|[h [~fNE7 N Mn yppKhjz+kZ'tg4qTP__?EPKԣ<,Ƿ& j+{bmf?“i ө::EjI7 :&c|UE_Q)XŲ6ISCS-W?ZϝܦRRNHBӏμ.PKV$j7.hZNLqvhlFM(lSoZjow: sgv\q_/ÇcagӽJh_IB9}UW1$Wrh9BJF#V})ڮ;s!!Eds?VA>SlizX!0SS=؈J< ~=&PjĚm:Pߏ5݊hQ3{=d:6d^t clnul|z>SiO>GԱu׿Xv(3ƎWX> yPQ#| ZDAtS$ta k |u݉貯y4/G\Au0}~WK֖c #,}RG!l߻< r%j]~FdH͸$Wg |wկjv?d*[tc͡(h۟dsCGlsB+%tsocg8Tz^a[nn N؜LVlEYB#!]oG+κzz>ZlqT7|ۦjp"&G!(qe\.K# AmSUP]7(XTLV 7Yu%'n@o nuQb^4c2F:$ӮݕK+|kR5>7 {MjlyTFFVi4☢,,^ֵa{xH;mh#jcBFr XnRx4?_vStXbVm2~ dI,:%%o`I7:s?BW)ѻJ2 ۃLC/l2b>ڍ??-پ@`ͱ,c=|0.'`xEoųƶ,JXHcӏ?x8 %ϥ%8I ;=w Q]oY.]T裭AȲ^/9^tt7M Pc _{UQ7&CRT0aS6ԌJ+;x`T] P OTl#Kӕ=m$z#]]P#_zj] [TN_S\1^񽏸}t8 fl?َ͙ Ͼ%7x{BɰF\Yq!a9mzĮ *^:]^H؄f Oٻls,ג| hOEӺ BЯQG@wjn@mc=ЦQ4@`0tVBr)N=.Zwh>OL\nj`7nˉ]JI*ۏPxp$6pzs˻:/{N}kPE-(9/{G#<+HwZˡ[&L޾MMhq8erzLΜtǬf"-Xӱ G\ Tțh35CTXlܠD:D8JNI: .#/([HteF:n?^]k?Bfw2u&o]OVQg+eΊzQz Py1Ynļϕ7%A V៫ak.ޖ7uLe+OWPb"(S?b >#}p <1tz]g@;X> q[LL;s/=d'8kٹ"=vyc)ߓY5bn"5U^O阈V͞(kL\ZB8&ڻ܁MdWc @gwʔ? L!KOR̨su.Y6Cֳi{هٳ*-k;?kaUWHֿbBl-l8 |8#ٹv9Q.QQQ6.Ȥ=$V x= b~߸`rDy~DvDCEfԕϓ8ŊNIMദ|uп###أƮ%^JZ ++]&6e!6{nBBzJ24,n+H|yCT2RMuO\Q /،" 99vE"Oy*.;M`x 3MJvi<-͖Iغ!#Ǡ(ܛ\1D,lPő>.^ZzlBi_EMչ{LwųVb p-Ϙ9ļVA(tjWz{PLyR% D\fOu.^6 ~ч@Izil\*kQG6(DkzǍ 9\"w>H ^NYW 5y<+ <č,:oh7dž,T7-YSLp_\‘Z:C蜥IySe2s4&5GWcG]XK%M"V9AR'W))=J⇴lbQhKn-Bt[[^ `MmGwQmITo΋< rSڌJ]Ŀ[U)k^8j15!,kv6x2ᙾFjGfdXEs0XsELwUb{q9$O7}Q⎪HD_/a鬿?"R*ҥҰ %Ei5It*($6FÈ`?u}^+&D%} Cm;ccR(P--ͩm 'iSVUA9IHšt '+E5lìFoπnF1I_:{2xG"< }_tؒLGx9t,1 R :]!skfooϋw3Us"$8(TDkI`FP{j%kM}ד׷9 (1L z=}9C>AB1Z ߉PNY-!zkU @\;Lvwf%&ySGF޼R_]Ts'z<m+Xݵφh{<1`oߟic` p>ٿhxOs|R"yu;ܽx `P2K8]!vo,(KIH9f'Mgy;SA" cVmR0߆} |3F D(wa{vބeݓe>I^=s݌Q?L^ 9z^ӀѬn6n]}Tſa~l`w%$X_~X USm!oR.B|S:@%16;rM AN ݕA/)~,^;uװc!F>[E$b,eNp0/e LhiMb#ޘp8>1ӻSPA/ga /c}p[)aq.ILHǺ$Xwc;KJ_ tdugc n 6j 9\i^)tƈPXY,!WN9`%{2>hix/s!I94d3~v||b eT.g?Ha^Q ab.őqq'L](u8O ^2oZ 00SUjuR|_0]惏{^>> 6]˒6W~ F)w{ l4|ޚtm+뾹HLd nhT:ā:س ox)21:U{頽JxSl&@h H4\ KQ1<`Oq ]-1 R (ҡ~K:#'ipT89ű9+QoM8'oykO)v ߎJׅX!)wp| =Rȯ=>W >Bf?9R&πE22FSWhEE:9IwοfĺǿǺ00`FMmcM$N-X]Zm~yWW] ,{+pW/0cIKt>6}U+˞O?6Ufl, 谫b6}k |IU X޻k+y:cjckˣEio÷Ѓ\Wwnh3 FYX6 fD:*ǢG.6}%dPeihyvE -+WT,|LhÀwswf}{ L'Ky|t8Ⴣk8a%J AqD]7b/@vc\L.7@QykuP@{AG.N˘s8i#GBljp3 ̂]r-vn⾡ I"}oEP|w{`mVupbю3BŪmK,&9,u|I7uڙzvZ U<\48MB<9n#yu 3ZSvL#U\lo( (3,<2\I!.Mi.`tbۄ3oS zY|h<1*+(n6E%^6E2h5C';Υ!Wۊ<Z5]'48+l~(Otĭfv^~x?䥻0wA AѠjq6d7/18~>(Ar}=n:#kzu,"Cޡcq* r Y3]Ȉ 7Vt3Y0CtmogEeBCfRbiO-NSIQ0f KQO߄ `!" 6xu_MfY}]7\ j~)|"KF`K|9YQ">D"4 6_BW)=ʧ+k0Z۠d!%a鹷+9D̨NBy)bLn^/` &ͦrbx:5Pā:G.-ȋ[1B\u;Ŷ.hTIfĒ4Q{Xg3U!zfӽ/~?R,н^},44$'(]Ə}> >BWt⵸5 -ayv7G ̅1ix٬Nyr {B6R&zH<=jŽQruVf碐:YbQ<ѪKҿr>D&ư)\gS4("^ G8Enr .L:Nq)x]QQǢV)WQl`[sоiQzkzZG,dqU)S(!;,A^ab 9٬\uǫ~`Z^?i ⫴NK*]˜ EK%ƤPR%ث(S4['b>#DaX)a'%?Sk#kB?pg|.#]`:Jbu^DzȂe>0q >gjBj npv`t@e~ZJ` Bbхr s>XcQ k1* "wq'`MC{#|a7nkaBM$xF5ah :Gj]c}Sj 3t`.|i?YtiCW0ƼfFagy56I%HVN.VŭJuj |bj tͰxk5@C['^!dPfN-ÈI3L*kQ3_7Dnsf|/܊wZڠv&ج<߉mU&UJ\c㫲#Krēj/*汥D&yuWtE s|3+G}%7W5R,C]i[N*>YcK~JneM/V;tIM✖֟߂Kl*l4Y#W*Gi~!:g-SjV3PWlk=lΓtc/)=`|pSwן_r#dՅ>쁈`4-U*a/jO cH#:bإX,{$k\2V~2]qsJ##gGj%mp@M}4k%; xaw(c)&zsݾ#A˃N N(_59d)T] !q_! bQyUo0Q {xqGt 3D)/W6pfKc#J}eƘ@=!ߔ,y4߇dr!Y!JF^gd=Wz;U{:Pz!T}<(\")< gOƕ+"~ 3K_\gS %3Xx8PpJ@ .r>DZF $v[mP$8{z5o[ΨZglOԻܵ\ 2~Õ &dDV+@=R&`8bJn0V88YZ QReo(Uj#I󟔙nJ|0)#^:N)OP$xD"w N\Cqʢb|m ^u:5G >ݕSe즓ddQ햔 6" 'ugUem@]J6D Qq?9%mF?_̫ CA/x]`^3 @]yվGf62W@kuϭ"Zj:*Cx߿=~ta#@}@&~F`qڜJ WģD .񲞯r.N2=$~9ykÔzP[?R;3KFnfE^Vf%cocz7Ψ SѨ˜> >sx}:&R|cuyhMhӄFeGϠ!'I%FM}dRq )d`q ҷ2T_aXۀX9U{%:n[Bj/G,xN bVW|4 Z\JJfG T"vH+;u#rfsh  ]+IJ)F$@PLV-KrM`4!YmFښ\$lP{ j|BzR_!~n U*U*<֤0d16۞>޿ٯb%p #Y~_sQE/iC֠?1!qXU+tmel?pݍ-ELQ5+vx @UGc %8nc)2ou*<I1gZcͼ: jM`av ,GIX_ ٹ*6\4A}刋_|Qp* 5p/V4\ n{$2!Eǟ}ޜ(ݮn[B=oXLffNIV&ME?8x!%a+)3TXj$f~/5ElU[5 {\4S~w:eGm t?Z|~no(1!|`QHfeɶy_ix }O+=w:vYb2/ڿm9*vZM֖y@@8PZ&QuYAs`Fnp1b4}wÂX[:3.w "Һ؝z R]7A꓌])B%Sj?^$kseo`oE76fSy̼&tcPRȜ/ý.]7kS2!|[_Zl-mrRZ`t?[6|G 6`*//JAxY9;M7wC7tm`"uF$ȏ7][~7mos0arRN3(]^ljq|tI<1M鵢5ʯf`=8?cpώQΧQe^x/'iV]XhxZ>qn ~﬍$})gi:=~#Id2~e!Nx"*|L)m Ϻ^f2\W_Fڣ(Ō.cc7{{ӄro=GR/xL9bGzb* nM!.h >W,Ɵ!h6PAH72#]{Ņ(0 u|P`E3:d=3M W"Hm$6Im4݇C|;t B]w28H Ɨ(g$NHasj#{nFލOlʫkts6*(̢isu'tlMVq)bZnvȩ$w'w~I֓O6䜶+ѐ-ok&'W}GkjM๵YF$iv[;>$ŚI+eUITsꆌȨl5DHϧLAMn;9,$ؼ3MNn \0L߇?:elWp-)[H\4y2Ҏݥ^h!䋑sF^wac-d+qC]m0"tN P&>~3B}_ŘSrU\$,L׎-o_pv%m4BR*LԺX J?Dޑ2Ĝ;#W]ӊ-ל)ԽX/JxqjE !"(sV%Kh6K='y#;aUJV#@j bCaAoJgKCB6=.D78%4}CqUg`&j& h?~tY - $ w8K9ڊTE t&lʗ/ aa Ժ$}HvtCk@a췡fk[}ZB''§#4e\np30+ۘC$T3L~#Pcc(=N12q}W3kO\;QtS:ч&t],br~\X'0|Hn*1>~nC,4Jk/gaf45s{M> {zLr#ʄB/-VMhߚ,UzW2b AY-azM= ۞mw84n8߱+r*pg0WgZЩ5QYf>{)aH&&^i6V,/p&+VFBᰔq|:ZWA'v\U*AC6!+pT>JlN[A}ݛNF%:aMf8 7O'fAlBɡgW[PLu'5 # Qh> U7}Y8ad]O/A:FƼ#k|0BL"rt!8pՌONy8ҺoТr.֗D0wcԿ`ʦz-wG,.jJ k&'ENX=\q- +àOݸh6Z_7.FTi|GaZX9=|#6rm~V%T5w\cI-܍:o+ >y;uNn~S G_hN[Le+wh񳈽#}KX| ~> ay=ba~NΆ@=Ź%1Ez T7~/꟮Ni"1~iiFt큾 .&}!Ɯ1y+!Ў]:e-IY_+I=D*V \b!@?gLPz:ǹove~^mX75ܾ%ZW7D:Þ=CXu4xp/v3_چ21%{%Ys'o5ShqO.oh(CoHjw haZ<.GCldIzw';zķմB3p{7E)̏,e OoNJ,g+y[AySR?_dva7D.<4Y[`nRkX^RqzxsenG-:Ϭ3ęeHMwJ_ҙ7bUȐ^p-KcKIsGfRpŸ̸vuu*Gqw%`pft.-DTՒw r39TNyq+3Δ5 b77yVp|wZ]0  tv?*IjMl]$6ABdwL|BOOS#9磔[`']ۨĐwD/>{`eـ,FY &րm(V@ftsfSw kNRW`G軞{J^Wlb$/~gG(Vd>c$kZ0Vk 2}>^bCn Cq5gλ]hpɊ^EM>pR&bcx5Y/egVlc4~hr~5)|IbO^r=ԷVQ}DӃ0 ,$w`l۴酫tfI.rM:=(U3>Ӝ *rS7轻o( q1+|~3'9ı+t6y_MLBjZ--oۛ=__(JX} D+^F)Q-".O iVO4yݏ5z:>ձ e0xWY*O=KƲ7iHu/q?;ɚX IvUk"l"m s\38 |+6j[DRӲl!eo'ɚv 69f)J f*51>Oϲ0#4TjnՙR<搫0K{rEKĕT!r>dAu@y18da&9D04}9D^h-5?Tsm}[+J@nϺj%f9R(η1vEYoOe/0I*nEPWo[wOkȏYDVYWHQ[ HQWv4E kWNfҶDcBFs'acLUv]ڛz\WWk$,^9gnfeM;Kth[(tn<T;cnT2MA"/!2# Աs|!m}$ X3ap3؀r!ۑ}"P5NhwTR*cߞ5ڵwSJGr柧K CgdeUzٽO@EE;R#G#Uv}|>4Sjxfݾкa K{ļqWa"PoyKԌ9`(g5_;X oؼSu4!>0DG Xc6H.@d^mS^z[h^'vf}%vMc]r@l~ߞ:f$Nsu5r漡19R3J?Ⱥ/27 Ҕj 1 /Utzy7WMysSꕮW=5x^MzuQt 'y^>YS}0kUse7Ckw;1;nz 2χ5K:(bȹl-tj2<1_%)MR%/uzEdifSyF-l\q]UmIژQa4[u5ZgÌ3.l8d{݊@_k GFu3̲'y飜491Bx*Cr-]6L~"WV="6(~36AlmuƘyVFJ}67= _?C-G)IIJ6[+eܟ_`KDCNKRE؜|GqyŝʼnҒ~35>1vyg|{OɀUn< xbTyP;o)J*#ձH fjDVlȓ=%Freu߮s;a7 ^)^ aͳY%/B.C<ٓ2LZGoͫgjĮ}py\)&A>qpV0(B٘{#[[ tzV cI']_(&$Wqo;{åƙ.n懻˖]^ @km@'9'I "T{vty;xz'VěI[ŀ|^PaM:,[2]~Z5 >Ng3lK3.jų|mіK\4s#{m [UtY*y+ *P|gޒcmo86Nex ?#B!QC)X'{ (Hc]οc*U}lKow>T<85\ugI?F# ѝoW22(( U(a<E"8Qi{G?[fwi#.v*~뎞ML%GL[ BB5T{=I9ؖ˗˖M BSRLRJddZkri >q֓1gi|M#7\l,2ٚ2qЍ>k,`a(d4l:Ȇ;X[>|R/,"T-AM*|ԃ9M)ɠLB&?1{l?#$$aTϿ.[_$-a̳T6é#!J-ך>?˾:[6hݤ~RЩau$2o1mrQKl`^G{{LZ aD3X!rC23ÖB"zN8M߬ ¼NT gX#$]LoTl81j+@n=4jc5vБ|LHLM's5`0ª 3-@d0DvF2.*S!z5met5MswnpxeɛKແyaL$f.]ĻªN 잷OO/>mmn20ذ.W1]{h6|<%zEqM6i,c]x~ʗ_uM$N&mF`SNG0iRыcsrr 3X걚5Қ3.,eTkU֏ V'h,uCĀ ";AkZxDtk>L/]ϓ˺@eR߷sT>&I2-),wC2%}_OyM>_jypKߥ@QbƮ>LX('憀RDDK[Q]#6m՚?ސ OSUV61Ÿl{RytTDNIx~rX_ǂg:m$= '+#F4Z/!YԌz֊7O.sh  Knх[ lXAl2%wN5N1ՕtCh!-t|k\~&@x?XV~/IІIM=+(AEe8E]lcOSnnyBf0zw![+A;~`tS rRntݶ0ƞ!:>c'sb+c :氥 ] F_Abt sldkt _AYC޲"15gLߟ?l{eCX~YKOku:M,]OcYS'Lr ,+uF3`7"{JFQiuyHB[8V׳rahkt7DuIfhr\[>l]f h=y^xe2nZ8Xț=T'6 W1W!}vN(95`Ghv|~+TNYj@MJWJ'L=>d"Orv1nV]ڎR:] n蓆1l!4tK7.rgp4a÷U=?f|E0 }TfV4)4ui ?XX>s?߼ ~6p6G?}545/ŇK-T"+=~QXނzv8:X ʧ 0|XtU.,͍ ic6T0QDDK,TB,BF DR)%EKP@iKTRAaq{ww}:só3:TuW0av'J-EQ^i[^muQQ&643:V?=}g`ڃ(kxsge1&gifUٵn1Pk7̸趏L7;ЩyOE:caٯKZLXϺo}h˯&VoqNe頬cttXw;noM0mi pDw3xOSz;춙?3gJ <”MF^I0x4et=V[}̇],x+}w=G% 02q4#f_xKwvDZV]buFўy6cw* rs!V %Ck}NyO7ҳe):O~ZĨƧE W犷,R[$n6oodD%s32(?F}P{R5~RIXN WU2M8pakz|cF|;suק usk9))LXXTKLeL[=wӬ;ډ0rNX e̩F#zRco_7v1fUL-K߄&[iK?;ݮe}=Uׁ^vCg~xP~Z/ ׏ng=œ]]>gYtd/*s:;cc7(5H1E# a՜ ׮k~eT G8f"ijAنI c%ָ¨waSZx;;Á"We ":L~Pk_px-@x3&ccyn_fÂݎWݭqGRHtٵ9;'5-ҚE{- ݟ 2.\V yc8_WYzIAoghw@C Ud-&jRjUo:#r.NJ7Nҋ2 |NbON&}ZLM 3A6Q_JJ&1 -`ݵrnR7Z|>GpX"rfKv?d!@R%;ቬW:s9TQ}[lX*ǭurLfWT>lU̕+)OV FF4ANnޢTO?e+>q j?={-e#[+Ix"([*ӲED3C~s8\شՁB,R^yBO\+Suw%͌ jU\.?L _p#L6qUZeK<2l.r`µOc'dF.jO_ʊ}/B_U2CV'KB{+|묏[yi~|a%L6 ;'b`DcV}.G\~MsY,7]bL-N%X-Հ!;,>NQ1(1פ-GiGi~!e A"/wsl.q,&,0*.*(}29ZA[0d^aS#a,}}swEAܭ =6d_T(gHuAgO~sEc)5îm/-g} (9H3Mg,˫Oѫ-|ZWk9<7jzK9>WQTRǜc _pgBq)'/>?bH=hw<-m~ uΙ :Iw7i_`p8^0L,X[d*Hj;‡^M;skr/̠Oi߽bv˅Px޷; C˨̎vu_uF`+]^?YO oOr|/1K[ŕ;^.)|š!JQק'yǯ$xYLk34OWZ8L:&UW" UթTwi'q,sy m]1KfjLb4JuSn^[~L+*-?~SsךF'1 Nt 4K`"4BGxfR[KnCtB^6uS\0~3ίNp[޼0s~_+dp2w^uV2 @ t/6YŌ.dr*+DOVN6vObtuc ݬߟ6 iًLN g̮|St<}t׺4g܊->5gl*}s'gnx65z j)sE)]$b^{3ֵTƝ~ 2lpw[No]ك<~W 7|1E-3 i?C+U{j"w.cEKy]WyRg`T2tfH@LҥI-LfaWiKj*w;qs%p oySkӥĪJS d_fpF\A-dP_}C;%|mj۲%ʎ~?d^_/ΓsQk|7~^xDJxyj߷6lBGldIFԶbe7J9v~c~?5oGovȒDRx1uːu[5=8E5jh&\E0brz9PI"nB@Vߖ*)c;S*,fKS l,2h~Y/gy^҄•7ۻ|UV?;J8\-|J4YwinӎM\I3QQ93SN;/S_1\GҙmNdصzy0p/22OHPVq-ݦ%+TN4:#xʿGi]V-X{gTjjٶ4--P-+]~qATW[Pa wyeiʽw}Yp^yw7m# X<8\E{{rAEwTPDJkaOYOV:v_lKT $HHn+PO4;mtԅCS6pǼ壴*#SS}[$uv,|K[>&:}[SIqɳ*IߺfW d-T^Ol]U!7V+a*¾2UY{Wɷ5s f\oN㚍qGtjB$ptkBKxbWRx0t,$&_4D#,S䷹>3goL/sRs."/7wZv!R^JIn^rבwRY<^[ͨ.k3瓿[>LFxCͺ؉_Iw )[bV+1IB1\Glxe{T~UIø܏03Rily#U y*MjӰjZW`iYao1ar[ƪKJ=NIIgמF(1~tӢH]__䍐 _ rD)l8KG^nϏO(rƿ x%.ge65_{)Qa2a^^IZp^H 'm8VSfjБs&o[j]vyRuHVoAx1JVO+DOz'DzQC15n,ߍq{1  hovw24E5{oy.*+|MpuO8{byG=Ezsac}$]cx޶IFH؇[4hmW!:˒-dbO ',E.PTyoA\|)ݨq>qJ.0eZ?R}2d{߈9'uzURmܯ!煟3,+#QU'J5 CNӟc&MU]R4W:wʿ=&s@pc]}'zCqq6魻 $upus\-o܅;n-Nbfh~OhApJ+6\,AS-]+x3h3T;|]n(|%74܊q441lOjXՅv9b)J)e3P;aJ_xPίHaԑ=Qb^_I;T42tWKegŊX>WuIdgzn{LC!vSawFS׎[WX"o$:+/f+֮jsSjWҥdSVFwqnl^4Cr+L9ƴ*J.}QͧK񆩺sk=xmŔ{AD^,uc>EAeG~2Tr"zYgTvXLwgT-Svh{CNNο9tb7sz#ǯƅJL\}믒_V : J)hn7InRΙfޗJCp[ L%N>z5䃙jLsJ(k&g|jm6߹vd?OARW G/.um b5},ݿZ*H ^:Xf]N]e%ZsёӦ4S?Jqjz8 MN%kEq臸'w=>st63=z""_4ZIGAE{uНc8zfhtqYW&~Wѯ=Jlĭ( 8UwVByG)du˽?/]²IyJvΛןolQq,쎾Bڼ#ItW5f<i3ZjgbSy){$ VOkHq+5CWh~yث,KN宕mB~_t (J^h ଠs}d\*˒:q ;^Xn+ Կ^)PHk }Rv~ON?߂~X~bַTU?7Q _.k*+znPiʹ6fLi3\躜muQ4tQ>?]YZǯRӴS~R}߈|z\#qkGP~3368J!Aa]f,奔!\#-$IC} w͹t C l{D,E`> \UXn߇ՉK IzTmDEF>hO^&|{}uC>IVz"ٳpN:_?.b7G!ծY)ǭ6_rw:Zmݟyk58R-Og?{(AcQ4KΊћP"xig[ؚto(}ujWWduhyĴ~mK֊'T'38[dl1yԋ9mw_EuݹG Dž$:ٳ٪Ļ i>+xS!I u y˂dF;Š{~*U٦)\%XHݎ<'h<Z y ԄbJ*deX{u?G_ӝp]#nS;Yrv->f|ஸ=C>RB_=1*):ײD-|)jky;ǎzuĨ)OEe''+!2/|\Gp '|e|#1%R}N+&}rKmzY:㹴zsםO[;ʃ{^hjMrLsu+<((uïFqNgN|C'Y[4Skۅ3_!ܹ٧Rp`cN,~W}2EGjHKqJR'{ O5K!3C/-36;rT~0u\a8Rw?D]my]tA;;U1^P6OGWEU:F~޻O5"D afmGє:ygSd+]~zbsyO{h8ݥpgCqO璿$zqDB܏y"!Jk+e[tE&C!}yۃ{5Ƴwn8>^y%}иb)gfN̩=`]d.^U'j^v F ^ (3^}O o f0-'Nsv$]za-miE]fy8/]2D˼Awfߒ'߾:s QL]E^d' iʹ6fLi3TN_$]ge**"&.#tJDLBHTs Ⓙ}ĥ;%e~K >~~;5Ai .xZcP;!Gu D~u]h?awCgA|Bb831($>VA}PǠ8!u ńDAvRA q;qоPǠ!;i|:Ňh!P#;좠c8wO Ɵ01(K>^i}]1(IKAFr 0>Nd 8r. ƧFPǠ!gu EU!;)! f5:u`Z@q~KcPV61(k$Icqp}s=A9@t:俯@߅8>r8;/=AyB1G}cP  u I8h?ABzq@ 8O1`$}} qP~(y qP0cPO ַpPǠ" "AE!;i~ECAr?8oA!cP$cP  u *I}u  u * ɥ8J: Ae@?TȆ:2B" >Ƀ:`{u * >PǠ !T.:UbT)E1rTAA@TAꡎAGr?o:A}8h#1&7CjAr?m u PǠ@TK71: qP>cP." Dr?!;0K9G (KƐ] 88?#@vw$ϿSNDpQ?O#;cI㑜俄/ ;}g :Nz7`|m8HNې\S";i~n8T!GbI qPNt8.d'HNۋqP>3ԏIφ!ϯN\N7A mFrFm!ʷ8(s8#A \ w8(.AnNHN~8=d'>A>_{C? qABr?_ 9 q8C0AB  qqCrqq8C$A  qh_,A qP'"/xqЎdv@s}#(AAqHqw_AOA;2 ڑTɂܧr!A*GB7A9yHH;אB|ZO!w |O!> )MB>"E|>.E:_3eHNo;nD>O ʯF^_I5B_>C >  y! FzON[ o6?Cp|;׳_ X;!8ȿ{ ^$'w NOqP "9:q0AX 9~rkA̟1~`8(ͿCoɟ8i?A"9y4A@B975Ο+ qE$'_82W  qP5_GrgB~[s+I q>J$'?#; w@ď4.F'}8|~d88~Lj 8Ere88`@?V$'qP?vq@ԏ?8>ϑ@N*?A 9y|DrAG|A";~ǐ|qPI T+ CO"HN+ q0Đ< q~$sI NO 9,I N HN~qP?%Gpp} ?q @:qyPǠ_ ETAEv1ysPǠ#9.@"1(Ud'O :OH%cP1PǠ.C/-cPHN1(]$s}qy&}cPk˹tI~jq_c@ qkqN:=O6Gʇ<&I t }'+8i_I 'u >vR?7IqP#I/qO'/8iI N_&/@&8h=݇8haH7|qp8?8sA#!qh8$>_$8{ ڑqЎDy `<%C<8 "9:) t_B 8LquLR>l@3⠝y| q74` ;i"}o~"+'8;xBĻ 8w%]ǿT#CwSqZ8Aĩ N!qNG8u ~TFz4A'z4C- q0 3~ d=t⠟CA;@(A;Aę-8h A Ngq~I8hq*qP? IBG $]VfLi3mʹ6fLi3mʹ6fLi3mʹ64]q.i)_t;Ǧ/ g`8"gSyK{cϟz0/?%푰b?mZRњEMM} KR7N:m-͹o9BS?LJX?ZlM@Hq]eKbݡ;sҔjuGųW[sWg3ֳ17d̽P&J;;6}x#³:.,\יkDUuF*%lҬ0Q}O, P(q#ul}{R^ הBf4j';ґ;Wƿ&X5}mĨXjڛ⥖ V7UФ*-ģ򻔂D6mJI.H˂tnsORdT ݻ;1ѓ>$JSJ\LJK\CY}uZ-WmuƗV 6xR=v*`Ce~$e˸m8f̻|b]@mRzn=eg6;1(}8 yU,x'^"ҭN5qJA;k`XCԨp됙ڕŞ!{l+w\JQz4>ke*5g0H]Fuh˅o}3vhJ78b33Z٠43eu:zY^wVjY"bp8qbW9^oJѿu}qr*CŃ=D|#OԂ; BA{Z򇳤9ZBYZeŻSYB. ?)+8S(8xwNPpF1{Npl1sN;"!qvBŖ#gAqilCq}B ]tց3U?m*hb'7rm 9g%+ĻRuxUY?TڝI\|&ێy~v2}OnD]1=S*qeސ1RcwޝPzVv/mo154^}͜.K/8]-F =f6GL.ޚ&' ;Y=X ss bE{ݣb^kqX|vL]Qb&D~R[~F的"psٵbOsÈ-CŚr;U@Бf r RPeTEۿaeQ!yʠtw"1O*_C}҅דV&pvwꙑE lp?|M{K* :6l6 rxC435D2bWWoN0r( td/ΙT7{ԝ}#u8NW^٨m$S{&}9j_EN-K!$M!3C*8[a<5 =ž۔xjJ[Q ㏯sPw xNo0ߟ-K[HPl+`D"R^^TV9AAIzܞtVx%y5<~I䯓BiO*iSL}Bj kPKuzJ ^b`=528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/metadata.yaml+-LR05HL1KMյLI454Mѵ4I35K2LM50N222L*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PKuzJ' )'7528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/VERSION uU0J,J,KR0J+JM-/ʶR020433PKuzJ@9! B528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/action/action.yamlVM6 ϯpOk#m1.PE(L'ؒFgR'g3s HG`a!b6ޒ1ee7iVmkJڜ^]&[K=DYJ8-bRI,!e4hnk.ݖoASkI-3- 0)swGْI6^' m̵={shACliwx 5X3߲6MY/:B\4sȧ|xl5< xC׭6Wd 7ڼk7W×h݅5KLm+uuLKLҤ/'=^6)mAb#aOv|~,}hCg?F_ҷLjdlt?< / U:N*Vp*N3r̭TGĉ%88|ec. pGʼn=7llNwN %^E%(Bw# ;̰J!ɼǣcsÆV#n+$b\0n_axB61)[!@V?NkGnE)TI$ nhfX?\ށg{;ކv |x\D[*4vY0㩓oXz 27!ryඕq{x玙a#|3+P ?ջ5yg@k9iW2w ,-h/JB5=ܴv7mr"<`T\zZ&jm緊0\7vc ^„$jXeŕX>~\7~mgqW]3=W}C!Lg֞(lqkjEK+)nPKuzJJ528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/action/sample_metadata.tsvˎ8g^c &J6ŬmvMpAۏxxPQ8?o#H?_?_?}?~_>|Ǘ߿?_}/'?_/O_o?C,R/YǏ/o^޾xY_=d|ċ?(pqQ_Pwy2:0Є~iɅ0T߹տiXV?״?WԽUxQ&²^U\x'9h52+T ;} |LҢ#Hr7<;RDMz9/ Y/j;ωևgcgcϠrKe~ ,4 CM\ p+z<(o@uLk!Df*Dxi@՞\&։ix$+٥kPn))H;C^xvň^>C1Ғp9!K#n"/{ɑ_)8EԼ DB^DoTD?"di}XgvzREw KF*k֍F4TUe=*|ivO¾@L4-֛ 6#D;]v[^|O@^-hx.'x^gt{y#78^o+pF F:~B^ETu/uTRA5N%k\<+ +|I\1bNX `=?Ń7Jӱ׍٨4S HJ49`?~5xj!$h搓lZ?94FWl\ׅ+ye9;+g3yź~FQhÅAWD.CbQnFu1qd*l`Y4)[;  OYVL'IĺH(iʍM(ouh{q{uF$c@AN #"5d_@lCM@M2Q}@[>Ie4488 #yf*8h2Z`ie ̋K+a3Qa_^_*o.oeR3$[_%FJ0d~[tE: c ᚌOt qDJD,98kd;;{E˜祖k5sH]X!ěEl"m<ƾw*'7)@PM;֞\+qH~ָeu݉)k d1nZG{nTJĉnڕwI ,O\4 c,!)4|N!7~R<)"a ҐNs6%!} + fOM IK))rá ӥV>u&s?UisiV^:N\2nj7ySp>']D@pW;Sp{=E%m5I [{vȍtO cxUpB"+w82},RfLU*)7P I9ޅM,m;矘4_R ¾z=p|pk}euip2^?~4CD#t%BEZ%&,!2{ EW6ֱ!Har[K@q+BkZ G׈H~vQ LY 3vQH{M'7) oG73DӖS󵩬U1ghpbEg\ˤE.SV%2qgBƔy^ݞd,7;9ɻEZHz)ҥxo~_ }P$C#龋hʭBɴW H EH[*M "RХPLi= ;H)R;,&AN]DܦO3t:j#iREdmVH' lH$>q% ݼAj\iX2;.ںMH?]Poqԉ3L iJIL,/bIOKqOٶuc<͂P@vC*b+<DNe%U䬰\R 1n=jD`- "͑ xL26R@`,j-D,ic=scxnZA<@O7Zd}foޠpPv-U뒉ʙ quEE:H*)05 s@GLпy$Lm=+L]CeZa昽pR#P17aL"pV\ 5^<x?l;@0<Žerx=<ӒAֶHᘏNŎX񾟱-cGnyT$ 9f@!H4 DcڨI@3-P ؃[(p^L+d?t]d*grofe+W!(GŅ빫i["%~5#6#/lrD34;]+w]g~"NƓ!mmٴᑾD& Ls"Q-YSzp ~^o鈗W,db{lZvMV+'Dgvŵ<ͱ3n75a g{'qi@ܕtyt@-"-+}5(e{|N9ʳUEigmХ@C mKMwRN8D~UM[6ԢhMҷ.  )oW32=e<Ԗ.dO -٪*_x0w5D=l)t72MvagAk94ҎrkTۓ ]HV56b\>*81>6>KQ5^74kܣSN &O*ԟGdG6&zx.[܌h՟}ֺ ~)F,j&91}QPx$IM,,$]!-p}x$"`O{/ Jɳ syif7?T@:(fxH8[;A!͕^dD9T5s޼ykML!z7@K T_eU='QL}϶MnpJGAltGNkv7"-MjZS9?SK`uk6ӠC&Bqx\BOF[$zl0G'nܑS+iR*1hęJ)7`?EqF8uX蛠&GllK:T!5(PT aPe9U1+lꠎUVy*7&ϩyfX!$G{&Pgc?d7jtiQzp'N=7/u.V3?TII]Ӆ1G-5ULԙޖ\f,XT+ b9%gemȘyjlR:Kȳcvc;%@v ^wnpǭ㉭'+dCDgÜc⻈m#I32Ӷ:mBҖV: 8)gG q ܛH00`1^KP^@$L-mSmZ>qlf 42spi1 #Ȗҡ{vf,z#D2Ey[rt&L#Dw3y`R~Iͱ͠u f&U(K{%58O2.eo! /9A}Ai"2UAl`pFZiHߞȒj*p[rP DHi෶G}s}m[yltR%2; =USc򿝲pU=T!?~}c. dI,9'M0]-m ? >N̸*&=z籠)oV`n[i{)3{R a 2:GNBqen)YfleS_Ll>qWà4RcH\8Ex6?΃4'脮BCOT6OtJjC%RkK?L]nu,+"#F>VztFl+ JIWȜ&`K&w6 ؁N2P%4(U-V@zW4\\S YCw<~~V >KgTu*>e=՝cTV>gV)8-gKaFCst3c_p2"D, qWls8 ;0.WMLh#D%W&9 ZJ!4+ht#sBatgc7l7bŖ LGk߉-/zGzt(vĒJ,k?JWroĪ,͗ӴWA|2wdH]J˄+@<]hu=wA{ 0 OY=K%Ȝ$K^<㡝}Y*Q=M:ȠsFTBGٯ֩ASp Ehg']t톦2Spvg7s0/s }lݤNDzEG`ozfyKDR9NY8I=T]A*]P+ aoJ=E=&??]c&: S>}T-%t:AYy꼘O"pZٝiHVO*:yp`A\[ZٯH2p}ki'S\ wTvZ5v@eg UV:4ci(l)dOb4fѫܠT+݋iSQ_WGܻ2~V ^l{]KxܟE%º|t\B7V+@2o'T{rB;W'Tb/='Nf~FszaY71C2F֒ MO$(? P<EZG<@ 2qF ǝJ[AZz{KHbL2NKfjJ!?=D~Dx~ -) 8FCe=[[ŚI/śΏ13I>(.hL>܅iA38V8W7cvV~q&􏴡:_,[TxPW5>z_W$fTYF2XK1TP|6a E,S dT և8GݥUcA0'! Wo(:J&7~WRgE- JO mC@eTN >De zUXPߐĬAXJlq7vT)5Ac<'%i׾1%m$KqP&&ubc5p9LtA7'|FD$%'<0zj-2d&=˥ȼ@b҂tۡœ0* L~]t]}Wbdž$v9az_=`,> ~uUv*Z{]]q%',R~}]Z\uYT߹NMg] SY= =Do@dF.=lac%A)X9%Z~3ILbeCؙ! y"݈=B"$kI}:(RYi D41?K7](LʇoQiHEڵ_t5LWp2fNF|z:?P`zTW/{n[?gkIPڃ[ăEBL'@+ax{(8}lQi݆&&2 Oz*W8n4&BH٨jBۘZdGb࣫~塤/|}c_*Ip4Ry4vfԩ_LrmL薢 1p9,ȇ`&Mx' =a_o} m=dڦnc:&mfDg<"((}GƓqOj;q" ~ljIՂdWdJ#ИgU"kJ  uWWسjN{}TX'PҔS(aS\azd?=B( Wo@>.UWKyHSV_?$gtO,̸Oi8ZIs}L!|f?0N7}7x*n5M?:܉JJx`jGD\:X^[L:j \ގ=_y]8RAMn=Q[iۉf#O  ߝTMJlnOU#F#,PKszJ^zb`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/0e23f1a9-c330-4e4b-ba34-c5bc525ed6d6/metadata.yaml+-LR0H52N3LM6665I5IMJ46M6MJ652MM1K1*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/0e23f1a9-c330-4e4b-ba34-c5bc525ed6d6/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJjP𺧀 ^^&E}*e%I= Pz=V0tち_$47&rQeMjo'.bЁb|MЏfCg N8?˷&IWE]IE!iUc88wGYY_=9 Wmg8Joz]prOׄS9^HYFњ0<"Mء]햨iQž%<=eTFȾ:,?>O G?+W Nj@qϜtfY;V`}>y_EeVQ__^4H9IxGS7!3q/tFZ~*ˬbo +*80ݎUijwOڧQ5 'Z;Ǫ%amx$AU7JKFX[& W\zbؙ;;A ވO2[Y-; #|ϔy-'iXplb !buȴ0V80YEl`YߌVD%(owS,;wUl~).E uuIϏ=pu:3hc?1ټ M;"ao =C't*Q+mN\Ό$Ar8HWp/]^0."(.AZ`aoVaiX=;,ኵ$7b_,qhW"J"€{pDր$hg؁],` ZQD7i' RUU/jlʅk6@D5kѶJaVLui)~`,xQ ֎^ɇ j6|fdj# <>AdԚ~D_Pߘid^^:;^8jrlM3^)3GކO琮;ў'v'Ǻlּ64-fΩQ.D hxsR4MॷZ ]61 %V#DExJ`8ifk1w 8@g)XC m)1vp~N]ʖH]⥻%]oE3Z,y,0?' 6 wx%MuuXH`.G; v9IBBi,CHL/免; :r93PHZn%; ͎JQŀlTt< VIݪ#|_3n/fQqQc/b-fp%q.3Zkً}=؂'Z0aD.Dz@.pYxNQVOC7a*p ک1iA7L&s٪Ulvzbw)vi/p01JY؅mcXA7\5B%im(^0,|O.S+JjY+?u*(D*o"ytd.=JL{k2ӵ4ȓ,V#uSwϞ`7f ܝҏ?3D+٩3dX_e$'ɝ( y5QT6hsd&C7eiHNI"8p@HI֛Q@ @Z)ICZgoLIс8%sblǙqhv7PdA=J$ E@Kn'`(a8/RhA[a;z䢒qm Zv4J3|ǴZ=QkCl@Д9%6NُӪb_WooF+r#7Mgq _W=Ne/t=(yjJXgn@83??v#ʰh W7.4 ,Ԗth4t#^@'4 %Ўl։˙ÀB2+Xlw考4"+E GBOސ2ryPXCo*F8Qe髱l7\3؃Vx)bO:o[|U+t##LZ-#",Krb+_@PyMn?_H Pq GJ8z #J غ-z> 1vڀ 49%Yȑưn8J`Mdi @1:ð$<7.A _R[60.z}+)E VfUI"g\@]ȱe8@'_F.1[ؙg'eY$uvkPVi2ELe+h =pgql`듍T^~Gj)܎'5e7zL^N093Mp8!v\-`xyJPKszJOxl528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/2d2a5921-4944-4030-8aa0-abd82c53fb70/metadata.yaml%˱0FO 4D`F& qmV(o wrv-ը}1FU*YJbrJP[ @k8pgxKnHh{lv.PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/2d2a5921-4944-4030-8aa0-abd82c53fb70/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJ>f q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/2d2a5921-4944-4030-8aa0-abd82c53fb70/action/action.yamlmUKo8W'@-["}` {Y,E,)Tb;-y|7p6.E@&T$ϛ$O`Вmm6(!3uK,o U"IAqV*مEV(*. 0.ݍu3)r'db2?$' OEC0md狇"BM+P>mȖC^Kk0S$bE~6aS~,|%hԛ+UIWOWD0 KkDiBC~f9O9ւ"a!E^CK׿3o ԚIg̨=7T#c8$HفV-P3)XO-u'KW$ qTS(7= 4L~B?qy/7nⰼRh@1pXx{-Hwsd5Ii|c^ J% lT&g0%+?qٷ|34Zu UQV0i . YB9;꽜$?^kg7Ytf0DvʠyiK]ϩ`8IE)*.nslZ뤀k^N)fGZ dPӨ|aϠf055lŕmybBƮӲoёR F!U@EH#'0ڛRf-lFdK N~ D[LC9AĠKNZ5:PyA4ܑ2c}e8f,Ǭ!Pz9I?89I9?')vl jn~Z>! %uiiP[G +[hE!wA΄ez @{\y%t)uW>gC+>I@**"2S g*>"벌iSu" X/]S8YU8n,'#Xc!)VXrw =)HJ~̊s/o$e H1zwa q ~M MZzy 4NCuA=0ڲ-%)t]-dDUzEsIhM )k뵯LtgIU(]Bkw~c}QSc?؛5s<_;č[oSNwE77|\-=v*|0J K$IR{IŨW<e!: &w5;ڟ6T ^eAA#/?D8Ϣλj%! 5Hrql-mt`YO@v ~p%E”]Aghnztq& `óysXcqx $W8XZ4JF׏$ CzOu|Y}:!=U{KÃ[;jRu%i.e%1^1y}8K1 $h;#]0|@nAf%-gBHL/8 :v93`PHZn%8 ͎JQŀ*ltt< ZK!j"|Z_3n/jUqυQc/nb-Vp%%K-յ0؆g^`{DPXS#k-;0\|~g7+i)FwvjyqMZ UI^Eh[PӚnnE1-)M7FIz=#m kV("$Ms8 R̗ODb=%=|eC^ חX: [h`nvH[{==,å6Q.[ߌIJ61]N{<)bR7z +9]н);cjA4JΚ78I+UFJ鑁JӼ~D/ЮMy=f! o gkе4ĞE=VS] fmOOQۅPKszJܴb`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/393cf00c-952b-4971-a8ae-7fec60044e40/metadata.yaml+-LR04NN30Hֵ45J547MHL5OKM63001I51*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/393cf00c-952b-4971-a8ae-7fec60044e40/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJ7d ; q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/393cf00c-952b-4971-a8ae-7fec60044e40/action/action.yamlmVM8`O>:F}HݽV1 6ӡ?~&L(Wzp6.Ey7 .ZК) uAtCf$RT)W0ʔA"01Ja\q|=^?4InN׃. !iM3%50)j}wG\{(L#kзÁ_ \Iс0崣=P3( ZظKԳ]߂v[\c}**]*,!>,jbz{-.={bh){]7w+S)Ϙ7/ (X]f/UW-9AR|~?؂\EJFXk GD(k,O⑵.SˁhUMJ3R8d +ыգLp5T}kY]%(YF@/BL6.9Q>E:5ty-sqdIKoPM0|OnR2[60>z}RCga# ?Lu*(D*"$;=[sQ浾[i)1]9#OvBRWp  v+&gJ?v',;_Dم?3β}E/6RNZ- $|ᴟ5)%h+d՟ "0tu/OO$oL cOhȯT/^?k^<.iZh43bmy@FtZ||<0M>8Ѫ' ^SX@ % pNLc?r ~/ѝq%;(3/cz/"ӈC"E Jk?0'n`]6Sb)8@H10T͎L{=Pmj^=u{V# v߭%R^{Z-hNv(mℱ]@ɯG. #HqiJPD{go v`fϠ hF=p>[|\/#`#pm^`&CڹGEj<{BR;e',; ZE@:ZvOzG*!=[3 Ԣa|C*&o093,ԠiYW3B 4b7U mܥ =&0o8~Bm:̎ rLGW-7r 02B pWs_mH2?k=-vMih3]> i w\3ߝ4ӕ;שx)ҏ(mB / FovQ0m+$ -}'<ق jAo3 ,֞]޹NSneDI-`4] #{mF@%}TC: GX0 ̳TB{c^+wnv~l7вq,X8齔: 050;OԄsp!.,m;)!vD@A_@ؠmJb0*QMoK zOA(:4| dB3B=(PSezU8 tݪW\Q"a}QVəL&;Fbtj0#:\m 0x^ۂQA ~!&9 `}Urf>I浒j L Hd]5#EB0jmY,J5#D2K@o&ŏ!Q&EA RM®pL{$꒜бuٖt@P)ZԧP5ëێ"HB:,kdcV?2% !nS-_}`TB'#ׅ){^O B@&rBKc1,\!LMG2!m((gږ-#UdKZb ]  W 婉 M7?=bgQՏݼQf㿠XWQd :h6`zNS=tWD KIX՛(Lh& 4b5",-&&"Ŧi 8'7@[jlr1&'K,do8H{{=1 Iv47C Z=Qyԣ2ݔ$xO^$AnDaLbP{?S3s"~8܇-$BC7@͠g-՚7E0 pVܴ`$haTqH:/fgÐ ?/RhAo%7FDꑋJbǵJhfk3)ֵ{4R>LCd@Ќ[JLmpU)rMς~y^ɮ7x3ZɎZ2߀v7qƽ|_%;a.)am!ǭUE]*qFAg%,CyE$:IJʾ:ڑ:v93`PHZnpf[dh@1ZY]UUv9k~ [@'wLV0}5O+b{P /A], jT` jEnd [KpD=uI<ֲXWj9Av^ET/HD3N%oX=ʤJ*µU 5-ZP}b'vi8%Yưn8J`Mdi-lAlaIyo\la\z+)+@oiw*$ʳv.g q2{`/^wc+1[ؙM'#OXIZW`筒d"Leg+h=;wgql`듍^vG*)܎'5e7I|=C*./'&8;vZOuk0Cog}<_ļd=7PKszJ4a`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/478aa06b-bd8a-4b30-9c89-f4d2de77ca3e/metadata.yaml ݯ3Is%ZWz}甲Cq LED@QeMjo%WL^1~f8FG|/c꽂&~Z%_"5ۼvNH9tj;,t̬Gk/ƞuA Wmg8Joz]trOׄS9^HUFњ0="Mڡ-Q-bѣ=31Kxxppэ}u<&LW$A$۳@q/tfY;`Dz^nyEQm(| ߯^Aa\0_P{=ֽ1={8BajKO!2ku{J1ZSCn*`|rBλؿ`ӎ(Γ-@t cՒ0rNx)nZ&LW\zbؙ;;A ވHά2GY-' 3׿gJ il<9XCoX݂(;2_(mpEv" 6yPlk179١z ۡyM~8B{,[@KS*sCF1=cwB~f AO "sFEu6復,CHFO ݱjl3#eFݡ쀬5b:פ2  y(XCUGZ= +#VDϣ<-A0 nb-fp8K}h%ſMAVDNFY}3 ;0Á`W+q& XdA hՋ:[։5tZ"o\h[0+m fz b`,xQn093j-ԠkkYW3B 8b/V =Z[Tt<(vH! ͪ#܍+jQQ 7Z38v2>ARbߎ bU+t'#L{ GD(;Xs,;п\.,(qJ)F(+ypL:n۹JlUBP}k\/02JYp; ̚{fIZk(0%o?_8Û uy!Pj[b+nUvKs=]x,y(.p:iߛ=dۭFZ7Ϟ`7n3N .VrHG'پ"HN R;zv@g N#Y7v\`s ftppxS}!v]- k0`w ^xb~f&/PKszJv9r528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/566c39bb-3a46-4b3f-ba75-8eede2867dc8/action/barcodes.tsveYK#\ȔҟZ@Gy dd 7(I?o}(?Fx<=G۶cnsySژ}n:ߏbSkmn X֔g6=6nc;`q. ĉ'Np[_w_XGc߰Ƶll-]U.gy~T涰pܸOl;engv9L,Go.pv\eW4izp s+عAWҷ΅Ӫ!gVv F!ɕ=3&s#sOτyC$a_Q m tfР;7C~7iܴuY~7o6H$}pհ*YHpBZKix:o3ƙT&ߖf- ) $N`N/v_Q+sU`  FZ6k LD qK> 5xEx9eMCeLܛ$0?\2Faǟ:gM[ңuYESM{U&ݍQ-7ې [X@ 0Y% zFz:U[&ؓƐ@]֛bnJ:SdL hw ^Ct ^ʚqƻ쟊N|:DM;K *L0bJnF:S5GB3t|'d hu&@A+q3ǘj$^B1x1ݴj٬ |[^lYlHR ҍ$kϪ +muN4D(0ckZ7gJ5r(I4DAi,y۝펅pcyfNHd@hD뒩}oXxqmY[O -;hb68&uOob2 bMljܖ꒰ޘZ+}{oVV7a ec< Ѱ[vM]]˥!oźhq"lrzciY_#MRg\̋MrQ_x['ӾݰӇᏀ_:#KK<ȴx+!3E#eP@>4c(ˣl-?e Z+UIWWL0 7HqJ>ğwk[Wq/q ՎYJ "OO%exʐ'$);xuZ59;O6-)Lv(M q; 9(A9:xW+X7q_5Qε翕X܍c*@kQ0GZv?x.\_(ǡJ):0.6iA7T}h&}m¤SC UrWFIF)z1S|/Is+Iڦ9 @la"p)ꖒ޲./ [: [l`i͊4I }=w,ù(~ZߌİuFc6w}YJUloPKszJYYl528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/62e4b1f4-e386-4b09-b8aa-9409a188a3e9/metadata.yamlA znA ZC(+S7Sk\-U-JPhŤy A!^wŴC™(bv<PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/62e4b1f4-e386-4b09-b8aa-9409a188a3e9/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJK q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/62e4b1f4-e386-4b09-b8aa-9409a188a3e9/action/action.yaml}Vn6}W-@$~{[ (F6)ʦޡX-TH^xΜ9tLoX]:a?:p㬮]R 3 4J!t\\SH s2˸0K/ߋ$+ ɔyNǨ ൺ#t)D=z!Lw-|L.s9TԠ(}vd:QCW:YeiaaM()$0 8hN4&iM3R8 Q&iqww -ѦiN)OIyk{ٛ{y(/rvC|5SPCCV?8OD:N: 2 x ON^f~D·ߡv~&z^wsvz ;P уD)0WhKZՒ0݂Ƈb/…UP VVCZnV(v\ L>1>cOBꚇkj [0eSjnj#E[FI/KBoF+# ٍgq WϘ%/t=Hqn_%v@ZGw~l#30h Wjtt^lʲ:4WDb.`-#3eFniCV Nm&aM](l ;I-KWa߰UF8^e˱l_38Fx1b˪}(Y]QAӢu\ӆ*S$AqVFq8r>y<%sA h5uTkpPw^EaTu#;}a/6u-f-翓܋4(@k{rQ/0<{(k1vJlػ8%)fxfMU¥ar>R i)f &0RvoF+C wsƵw&J`/b)QN#9ߦ=dFiC92[סD$܋dfxecD+:iN}Ό[IvG8HRTp6 .s2#(>AZb QXlVnltǝ\Q3cъ\, jTfZ;avc8"BYkA}O@>sZ/ڀ*Ip ݣwk1@T k۹JlUBP}k\/02JYp; ̚{fIZk(0p%o?_8Û uy!Pj[b+?nUvKs=]x,y(.NĴMFk.ws<ͳ'd(؍LSg²Հh5{ l_`닌xG*)=;3qzC*.o093jԠii]WsB8boW<1?qRDmPKszJ&z: (r528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6ba3cae1-ac0c-449f-ae6d-1e659a2b05ca/action/barcodes.tsveZˎ#7 <;3pQ:eLJTU5E=lEjbr_Wߗm}oz6}pY6Y߷pۭ|߰j`fy9W1_ XX~-q ~r^(Ovc.k8V_c~msf|@-o.s d_9pkym'8 贸u)iؠWСaQ@^kOp@&-lUpgp<f5>\C>C eI#(,rE4+ )i{b붫mg4"Fx2 gW:аZW<2 DmܮD Uaү %%H'CirXW>ʣ!tv!dj^A05HUU.pS"b]E5.M XZ̕L=yLS'Pw)WOQ_lV@f6V2?R,? z;R C y| Lߔ)!Ro$츌0F2ߩeK\g |(yI'9K' %a`X)HZ? bf1 Iiq+HyJx%w/ˬ:T:4.\7uoV@2f*ݯ:֓@ۂhCe.'e@S5%\al$P $QE6\~tBdo^Q+lWYw:`NkTj?A-ZuODRx^A <4![ !*MԄ )VjQܾ:-S9/uE*GFI"I⏴]AQ=Ȗ+Yz9'X$)U?) H u+=Oݓ9xXIK_E&Pb{+~oS櫀<-R-8ch0ZO43/Hbxaԇ%p`SxI?Fod>.$O/ [9s}V@{ld#e*:'x1w r#E};E;X-t@Ů.=fRe] )ƞ:~"U7ӪaL&}=ȷ@FBӼrb$&ˬ]E \Fwc!5P}*pA(2zI fZ`9vR?U4 ɰH@M7qSXiQJ| p^zARJ}ᯩS5Uy%m{|Ee"Pµ ҚnҚ"XW2?bhwengXR,=#,-}<5ArV@jM2V-h|H/`CzګJaK%O q pF%p!fdhv]m`>4VAqhvj6p,qP;< fE% r@q$"J6*)p( ch n:("z!cpw#5l Lp'fYZc[ %ojI n >\PBTSϲ-za`ƫLNE 27uʱXZIg(jdD d`#)SzڧM5MVN CㄞW2|\Ӆ(X#T:2+@0 򹛥~ʶK>Iyʶ>(q*  񞯯rR'KFsQHJy6/#{kGr M"FR)H+mdv*x$fNíAO  5{t98v:5v& 0%O Ʊ'_&67W=;|uUq_6܆5I4N?!R3ނ"qE^CBK׿k˷j Ҥ5fせvCđ) [`HEF=P3*XG{NЗH&wj$VWPݍ'#ƴMZ Z)s'q;p/ӀC$UˍFLз6p~xBb)c e #7AT K/ɝH3&^!M`ߌVer!o^jyYhY?Du:f `w\~v,r>΃ ڲM'"^$ =5C'Mk#\ IusfD7J;AqO֖a77A9 6k|wck;Dm劚yTc4HV -RFKu){ߏ |U+t'#L{ GD(k-Ouw.~Pˁ )q{p@%na{Ε| 8&薪am3;W Jhp#/xm]rWFIz#=}'Ysq/,Ikm @q6ð$m?gx./*RFA-ZRüOVeD*A8؅2` ILd27ȓ,W#uUgOP]Ib e@k9kv l_`닌T$Gj)=;3qzCj.o093jԠii]WsB8b+Y)PKszJc r528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/802ea0d5-5a16-4964-bb3b-0dc3f5905988/action/barcodes.tsv]VK+1[9Lvt!A0"$1߇q}ӭ"[^*?=qe%{h ^}gh/Վ݂KT,"kc߉R셯;8ȴDȒKjoEYwpz)vZE`LTH ]qUvnBZy0mXhMJwAtbޭO*n9>P q}ڭۿj_GoN J-DA 2!STNg\2,HD->␇=[}z -ә< >"3 ԴP;qvG` @;5vk }&D FRB9߉*n'Y RneP%jud䐅3h‘I- SUjNbT;x"V$VP-}*eNc{ju0RYˮa'g' vLJ`Ƨ0fwjҝ$Ԥ(oy9B}[H3v!= b*e.Nڸil`׹3V}rP_R+#la$%؞0d-g~CHP~TO/h粧 $3Y\)\Lz޾?)v߉bAd@˱O7 oE G;%8lrg} ұm|L pa' r%(ƟMw_yz\rKg|Lk7wЈj9gXNa}Ϋ>qVyA0p*wGypqpj+a+VYUvLEx#BzPKszJ(a`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/9657f7a8-200e-4281-9dce-a60a118392bd/metadata.yaml ݯ:F -p+=EsrP]Wo@19R*ۑAAUh9 )G`;pߌdhۏ,Bg"?PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/9657f7a8-200e-4281-9dce-a60a118392bd/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJ1 q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/9657f7a8-200e-4281-9dce-a60a118392bd/action/action.yamlmUK8ϯ:ƼEs؇6RU `Ӷ4-COczXW_p)0*'ALYԕ0/i8CPӊarW0a$Aģ?4Ƀ,c,N$ p] Mh(  }L:^*9+CN:0&CGq~QP\Iс0G503( +ZM1:dsx6ur%:ݧdԋYVzhEqŲ}UE9i#KEx̼Շ=(Βx.)9-3T]NZ.w٧׷#b=z7T#?#,qb:Iv4ԏwQC5ZH>3EH:MA x gYFAD>ME<GRA,f@"}/Phnp1Ο4Cᗲ{:smtUx"g.[59/ @j "j(>u/ Lc~v3R貁ab?uⷲ<!/B'RW?W+M|׿ b}-#Nsq94Y!V%?qJ;~.ReK.ݒ^ɮ7x3ZS,y->'  wdѥ%CE:fd!G vϤxPf|m˙h~"ӋpcoiyasP'@UG.g  I˭Dษ숬\ >boFMWPJ\΃`Vq#(|13{.{'p銵X ^, fT׶z MOW"Jal1aecAO\ekف],;~zoVT-HE5S{'Vk҂nzMb*D۪Ulv{.bo)Ni/p01JY؅mcXA7\ 5B%im(^0,|O.SW60.z}NUCga 8ͮ}pБePN7c+hL&#Ojn32WrL{SgwƶՂh`5;soqlW`뫌$#y܉^&]z zC ./5֠ki=Ws{Bbg+xY PKszJF-ZYYl528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/a4ac66f7-4e01-4f0f-a015-e0e38fcf36e8/metadata.yamlK йpY8fA v_e?%}'ɐke eX"]T eÞKF3>0!$~PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/a4ac66f7-4e01-4f0f-a015-e0e38fcf36e8/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJV q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/a4ac66f7-4e01-4f0f-a015-e0e38fcf36e8/action/action.yaml}Vn6}W-@$Zz[ (F6)ʦޡXmTHp9gG`Rw~ңRI'I$~5I@4A|~PeJ/ I)A2 $ <*R9}>u:,&t=(:E8SRww-]/:}~zŶϢy7|_A0tPmLWzJa$P$iCYZ*L"bhNfSy%i^A7qÊ0 ݁ƕS}KZ.ddɼ5??i{o'> ڎ3"X}Ck'q-0 BglZ vQ|8Ȝd0݈H=rQI츶[i@L=qm1cOFڇq t5=7~ T)n"ZΰIY/+7RoF8QQKP&3ظwv'<5%R7a-7??v#ʰh WE7. ,Ėth4t#Z@'[iZ^7B'@;Y.g  I˭`ݡl =:{C+˰ Q.Au\Zb aݯ:¿aDn*^ pZ`JX%>ATrlASUҍ0akP.GZv`|_J-"ΫhrB)hFw8کGwT]uZ]E*5E@OB6d.M3}z#= [ ̞[̖6-P0,<~z Q y"^s|%1t6b`(sL3)1{T+VB.l?_Bn&a&ˣfaO]%PÑ >3Բ PǛ>>p΄FI:MGWóxy1 VX!:=Cež7|x8 UU$ቒ{"3~f'2yˌGz#sNf¶tA$.OF3m8oߍ71 fVQ D<~80^n >f}'ZG9!V0\%-0-^xُөoGZ0-zKR-ъP0ظWW34WE6%RZaG2peAwBZa QVqÝ|1;/{%&pk13hos'5J_^쏃+hj|QvKd=I<ֱX!w8av;EY=P4Y•jMjhǤ0nXųU 50sDw)vi/01J9؅mcXC7\5F%imF $hgd~' R+J (ȡsN VfUQzTE82\zD뛱Ud4ki'EQFZ="Cmx;vOXv9Ԭٹ3dX_eƼ# Ry^&3 OY7zpX̨M;!n]- . uCv xbfe.v/PKszJ7I[Yl528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d77f8e27-36e0-4980-bf1e-428ca9947e78/metadata.yaml+-LRH17OH5256K550MJ3L51HN41O5*,HRJ,N-,MKN-J/M,Rp KIuKq,r-PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d77f8e27-36e0-4980-bf1e-428ca9947e78/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJl q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d77f8e27-36e0-4980-bf1e-428ca9947e78/action/action.yaml}Vn6}W-@$nKot{CXtREA#kIjcePr,1*$/ gΜsp6XduG+B mA:XtgAHڎV0@~,|!84thD5!԰U%_?=>,;Diw'?S;hI~܋ι;!ME%´c4@!`-5F4U0=ڊDaRzVSa[PaP v8qyOIpwapsYj4lҋ*vhD Ӎċ#ŽcPi;a 8Xrx6H]pm #b AؠK7qZb`ؤ"/k6JoF+CQ*[f3ظWWϘIt=hunJT~@[a`~F)á.GƕܸRh3̕uhψt#Y@'[e[Q7"/D;rY>g I+`ݑl5,H3y:{Kkǰ7W}΃\a QXܯ:"adj*^ hZZ:e>IQ\r\ASUҍ0agPw>G:v`|_J2,.hrBJ)ot8کG`T>wJpmU"S5g!&^pa&b {z#=rӭfh"% ma`3 K2??| KQה y&^_r%9ty=Pyݬ5)Yny D*L2kIȓ,W֛kPpVi2Le+={ dپ"gHqGj&5~7 `8s,fTGCܸZ\|;vZMk0`g| jĞ PKszJ@*b`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/f034e290-6739-4b65-8dc7-caf980e34754/metadata.yaml+-LRH306I545375I23յHI6MNL0H56175*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/f034e290-6739-4b65-8dc7-caf980e34754/VERSION uU0J,J,KR0J+JM-/ʶR020433PKszJc! q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/f034e290-6739-4b65-8dc7-caf980e34754/action/action.yamlmVKo8WhOnHۖnE(vX, Y%R&*;- y|73Q3qdu)vaQg~ H/(MiQWf=oͧ40a2KxIǹn0^oo˸((&y$nף$6W/ɼQzS@6pTKzzЭaCHh L |ʚ$O^ \0{{0j5MЏfCg Nva $3?#QEUT~XӤɊ0+v9)" qpGYY_=9댃&b%p D}#z {T# =rn%5azDC][ZĦG {fc%!gaJdA= d(I7iF%syjhJ喇^ٮWWAl͕8LoDv?ޘ yYg0 %YezBF[¡ Lc0d}>9Gr')/X#JNA\8V-  DZ$rFiX_+ukD_/JpE[ag=6"v< 8RPPeA(/4 =Szֵ\f`M98zC0 EّiBaLm$d.RcIɃf /E?h_㈡KP=Nl;7Ul~).M uuI64رE|AJl⥦,CHFO ݱj㊣l3#eFݡ쀬5|:פ2  y(XCUGZ=q+#VDϣ<-A0 nb-fp8K}h%~3lUҝ0a1!5g.'v?!AW+q& XdA hՋ:[5tZ"o\h[0+m fz b`,xQ„^ E>f%0kn"2KZCp0,|O.| a\+V-Xaަw(M|\#`֝#pZ6S'0{#OXUn=#Cs)fܝ2L?z]cOĬ[wg dX_dz8ѳڵI8f݌R1qјQkpu(83+h{_[L'nVm"'PKuzJ ^b`2528ad6ee-9da3-495d-94f7-6b1ee03b221e/metadata.yamlPKuzJ' )',528ad6ee-9da3-495d-94f7-6b1ee03b221e/VERSIONPKuzJh<%528ad6ee-9da3-495d-94f7-6b1ee03b221e/data/feature-table.biomPKuzJ ^b`=528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/metadata.yamlPKuzJ' )'7528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/VERSIONPKuzJ@9! B?528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/action/action.yamlPKuzJJ528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/action/sample_metadata.tsvPKszJ^zb`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/0e23f1a9-c330-4e4b-ba34-c5bc525ed6d6/metadata.yamlPKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/0e23f1a9-c330-4e4b-ba34-c5bc525ed6d6/VERSIONPKszJf qs528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/2d2a5921-4944-4030-8aa0-abd82c53fb70/action/action.yamlPKszJ : )r528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/2d2a5921-4944-4030-8aa0-abd82c53fb70/action/barcodes.tsvPKszJJpb`l 528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/359f6860-e3a0-4a7c-a117-34da78f3dbb2/metadata.yamlPKszJ' )'fz!528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/359f6860-e3a0-4a7c-a117-34da78f3dbb2/VERSIONPKszJ11 q'"528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/359f6860-e3a0-4a7c-a117-34da78f3dbb2/action/action.yamlPKszJܴb`ln'528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/393cf00c-952b-4971-a8ae-7fec60044e40/metadata.yamlPKszJ' )'fZ(528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/393cf00c-952b-4971-a8ae-7fec60044e40/VERSIONPKszJ7d ; q)528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/393cf00c-952b-4971-a8ae-7fec60044e40/action/action.yamlPKszJo(xl\.528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/42062def-567d-4336-b8d8-3bc2ffa405bb/metadata.yamlPKszJ' )'f^/528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/42062def-567d-4336-b8d8-3bc2ffa405bb/VERSIONPKszJp/cZ q 0528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/42062def-567d-4336-b8d8-3bc2ffa405bb/action/action.yamlPKszJX\ri5528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/42062def-567d-4336-b8d8-3bc2ffa405bb/action/barcodes.tsvPKszJsnZYl>528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/46c66bc3-637e-457d-bf5e-741f9f911a2b/metadata.yamlPKszJ' )'f?528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/46c66bc3-637e-457d-bf5e-741f9f911a2b/VERSIONPKszJ: q2@528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/46c66bc3-637e-457d-bf5e-741f9f911a2b/action/action.yamlPKszJ4a`lYE528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/478aa06b-bd8a-4b30-9c89-f4d2de77ca3e/metadata.yamlPKszJ' )'fDF528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/478aa06b-bd8a-4b30-9c89-f4d2de77ca3e/VERSIONPKszJS\ȝ qF528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/478aa06b-bd8a-4b30-9c89-f4d2de77ca3e/action/action.yamlPKszJhwlL528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/566c39bb-3a46-4b3f-ba75-8eede2867dc8/metadata.yamlPKszJ' )'fM528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/566c39bb-3a46-4b3f-ba75-8eede2867dc8/VERSIONPKszJ=c qMN528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/566c39bb-3a46-4b3f-ba75-8eede2867dc8/action/action.yamlPKszJv9rS528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/566c39bb-3a46-4b3f-ba75-8eede2867dc8/action/barcodes.tsvPKszJb`l\528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6005c0d7-978c-4b9d-b372-503beab83d85/metadata.yamlPKszJ' )'f]528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6005c0d7-978c-4b9d-b372-503beab83d85/VERSIONPKszJ$ qm^528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6005c0d7-978c-4b9d-b372-503beab83d85/action/action.yamlPKszJYYl d528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/62e4b1f4-e386-4b09-b8aa-9409a188a3e9/metadata.yamlPKszJ' )'fe528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/62e4b1f4-e386-4b09-b8aa-9409a188a3e9/VERSIONPKszJK qe528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/62e4b1f4-e386-4b09-b8aa-9409a188a3e9/action/action.yamlPKszJ'f+$wlj528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6ba3cae1-ac0c-449f-ae6d-1e659a2b05ca/metadata.yamlPKszJ' )'fk528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6ba3cae1-ac0c-449f-ae6d-1e659a2b05ca/VERSIONPKszJ#f ql528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6ba3cae1-ac0c-449f-ae6d-1e659a2b05ca/action/action.yamlPKszJ&z: (rq528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/6ba3cae1-ac0c-449f-ae6d-1e659a2b05ca/action/barcodes.tsvPKszJ |A8yl}528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/802ea0d5-5a16-4964-bb3b-0dc3f5905988/metadata.yamlPKszJ' )'f~528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/802ea0d5-5a16-4964-bb3b-0dc3f5905988/VERSIONPKszJhe qf528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/802ea0d5-5a16-4964-bb3b-0dc3f5905988/action/action.yamlPKszJc rɄ528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/802ea0d5-5a16-4964-bb3b-0dc3f5905988/action/barcodes.tsvPKszJ(a`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/9657f7a8-200e-4281-9dce-a60a118392bd/metadata.yamlPKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/9657f7a8-200e-4281-9dce-a60a118392bd/VERSIONPKszJ1 qT528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/9657f7a8-200e-4281-9dce-a60a118392bd/action/action.yamlPKszJF-ZYYl528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/a4ac66f7-4e01-4f0f-a015-e0e38fcf36e8/metadata.yamlPKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/a4ac66f7-4e01-4f0f-a015-e0e38fcf36e8/VERSIONPKszJV q,528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/a4ac66f7-4e01-4f0f-a015-e0e38fcf36e8/action/action.yamlPKszJ Oa`lV528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d1ab26d9-cdb6-456a-ae9f-76211c7901b5/metadata.yamlPKszJ' )'fA528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d1ab26d9-cdb6-456a-ae9f-76211c7901b5/VERSIONPKszJZz2 q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d1ab26d9-cdb6-456a-ae9f-76211c7901b5/action/action.yamlPKszJ7I[Yl:528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d77f8e27-36e0-4980-bf1e-428ca9947e78/metadata.yamlPKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d77f8e27-36e0-4980-bf1e-428ca9947e78/VERSIONPKszJl q̞528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/d77f8e27-36e0-4980-bf1e-428ca9947e78/action/action.yamlPKszJgHb`l528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/dbad38af-630f-4c0e-bb9e-3ce4f9a9f166/metadata.yamlPKszJ' )'f528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/dbad38af-630f-4c0e-bb9e-3ce4f9a9f166/VERSIONPKszJ;0ep q528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/dbad38af-630f-4c0e-bb9e-3ce4f9a9f166/action/action.yamlPKszJ@*b`lC528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/f034e290-6739-4b65-8dc7-caf980e34754/metadata.yamlPKszJ' )'f/528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/f034e290-6739-4b65-8dc7-caf980e34754/VERSIONPKszJc! qܬ528ad6ee-9da3-495d-94f7-6b1ee03b221e/provenance/artifacts/f034e290-6739-4b65-8dc7-caf980e34754/action/action.yamlPKHH*q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/ecam_map_maturity.txt000066400000000000000000000247361462552620600303160ustar00rootroot00000000000000#SampleID antiexposedall day_of_life delivery diet diet_3 mom_child month month_of_life sample_summary sex studyid Description 10249.C001.01SS n 0 Vaginal bd eb C 0 0 Vaginal.bd.n.0 Female 1 Vaginal.bd.n.0 10249.C002.01SS n 0 Cesarean bd eb C 0 0 Cesarean.bd.n.1 Male 2 Cesarean.bd.n.1 10249.C002.01SS.r n 0 Cesarean bd eb C 0 0 Cesarean.bd.n.1 Male 2 Cesarean.bd.n.1 10249.C004.01SS n 0 Cesarean bd eb C 0 0 Cesarean.bd.n.1 Male 4 Cesarean.bd.n.1 10249.C017.01SS n 0 Vaginal bd eb C 0 0 Vaginal.bd.n.1 Male 17 Vaginal.bd.n.1 10249.C017.01SS.r n 0 Vaginal bd eb C 0 0 Vaginal.bd.n.1 Male 17 Vaginal.bd.n.1 10249.C055.02SD n 30 Cesarean fd fd C 1 1 Cesarean.fd.n.1 Male 55 Cesarean.fd.n.1 10249.C055.02SS n 30 Cesarean fd fd C 1 1 Cesarean.fd.n.1 Male 55 Cesarean.fd.n.1 10249.C004.02SS n 31 Cesarean bd eb C 1 1 Cesarean.bd.n.1 Male 4 Cesarean.bd.n.1 10249.C008.02SS n 31 Vaginal bd eb C 1 1 Vaginal.bd.n.0 Male 8 Vaginal.bd.n.0 10249.C009.02SS n 31 Vaginal bd eb C 1 1 Vaginal.bd.n.0 Male 9 Vaginal.bd.n.0 10249.C014.02SS n 31 Vaginal bd eb C 1 1 Vaginal.bd.n.1 Male 14 Vaginal.bd.n.1 10249.C016.04SS n 45 Vaginal bd eb C 2 1.5 Vaginal.bd.n.1 Male 16 Vaginal.bd.n.1 10249.C017.05SS y 45 Vaginal bd eb C 2 1.5 Vaginal.bd.y.1 Male 17 Vaginal.bd.y.1 10249.C034.03SS n 45 Cesarean fd fd C 2 1.5 Cesarean.fd.n.1 Female 34 Cesarean.fd.n.1 10249.C053.03SD n 45 Cesarean bd bd C 2 1.5 Cesarean.bd.n.1 Male 53 Cesarean.bd.n.1 10249.C053.03SS n 45 Cesarean bd bd C 2 1.5 Cesarean.bd.n.1 Male 53 Cesarean.bd.n.1 10249.C001.04SS y 49 Vaginal bd eb C 2 1.6 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C002.05SS n 89 Cesarean bd eb C 3 2.9 Cesarean.bd.n.1 Male 2 Cesarean.bd.n.1 10249.C031.05SS n 89 Vaginal bd eb C 3 2.9 Vaginal.bd.n.1 Male 31 Vaginal.bd.n.1 10249.C018.03SS n 90 Vaginal bd eb C 3 3 Vaginal.bd.n.0 Female 18 Vaginal.bd.n.0 10249.C030.05SS n 90 Vaginal bd eb C 3 3 Vaginal.bd.n.0 Male 30 Vaginal.bd.n.0 10249.C034.05SS n 90 Cesarean fd fd C 3 3 Cesarean.fd.n.1 Female 34 Cesarean.fd.n.1 10249.C004.04SS n 91 Cesarean bd eb C 3 3 Cesarean.bd.n.1 Male 4 Cesarean.bd.n.1 10249.C031.06SS n 119 Vaginal bd eb C 4 3.9 Vaginal.bd.n.1 Male 31 Vaginal.bd.n.1 10249.C033.04SS n 119 Vaginal bd eb C 4 3.9 Vaginal.bd.n.0 Female 33 Vaginal.bd.n.0 10249.C034.06SS n 119 Cesarean fd fd C 4 3.9 Cesarean.fd.n.1 Female 34 Cesarean.fd.n.1 10249.C011.04SS n 120 Cesarean fd fd C 4 3.9 Cesarean.fd.n.1 Female 11 Cesarean.fd.n.1 10249.C045.05SD n 120 Vaginal bd eb C 4 3.9 Vaginal.bd.n.0 Male 45 Vaginal.bd.n.0 10249.C055.06SS n 120 Cesarean fd fd C 4 3.9 Cesarean.fd.n.1 Male 55 Cesarean.fd.n.1 10249.C012.07SS y 146 Cesarean bd eb C 5 4.8 Cesarean.bd.y.1 Female 12 Cesarean.bd.y.1 10249.C033.05SS n 147 Vaginal bd eb C 5 4.8 Vaginal.bd.n.0 Female 33 Vaginal.bd.n.0 10249.C024.08SS y 150 Vaginal bd eb C 5 4.9 Vaginal.bd.y.1 Female 24 Vaginal.bd.y.1 10249.C030.07SS n 150 Vaginal bd eb C 5 4.9 Vaginal.bd.n.0 Male 30 Vaginal.bd.n.0 10249.C046.06SD n 151 Cesarean fd fd C 5 5 Cesarean.bd.n.1 Female 46 Cesarean.bd.n.1 10249.C046.06SS n 151 Cesarean fd fd C 5 5 Cesarean.bd.n.1 Female 46 Cesarean.bd.n.1 10249.C042.07SS y 182 Vaginal fd fd C 6 6 Vaginal.fd.n.1 Male 42 Vaginal.fd.n.1 10249.C001.10SS y 183 Vaginal bd eb C 6 6 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C005.08SS n 183 Cesarean fd fd C 6 6 Cesarean.fd.n.1 Female 5 Cesarean.fd.n.1 10249.C007.08SS n 183 Cesarean bd eb C 6 6 Cesarean.bd.n.1 Male 7 Cesarean.bd.n.1 10249.C010.09SS n 183 Vaginal bd eb C 6 6 Vaginal.fd.n.0 Male 10 Vaginal.fd.n.0 10249.C025.08SS n 183 Cesarean bd bd C 6 6 Cesarean.fd.n.1 Male 25 Cesarean.fd.n.1 10249.C037.07SS n 199 Cesarean fd fd C 7 6.5 Cesarean.fd.n.1 Female 37 Cesarean.fd.n.1 10249.C032.09SS y 209 Vaginal bd eb C 7 6.9 Vaginal.bd.y.1 Male 32 Vaginal.bd.y.1 10249.C011.07SS n 210 Cesarean fd fd C 7 6.9 Cesarean.fd.n.1 Female 11 Cesarean.fd.n.1 10249.C031.09SS n 210 Vaginal bd eb C 7 6.9 Vaginal.bd.n.1 Male 31 Vaginal.bd.n.1 10249.C014.08SS n 211 Vaginal bd eb C 7 6.9 Vaginal.bd.n.1 Male 14 Vaginal.bd.n.1 10249.C020.13SS y 211 Cesarean bd eb C 7 6.9 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C025.10SS n 240 Cesarean bd bd C 8 7.9 Cesarean.fd.n.1 Male 25 Cesarean.fd.n.1 10249.C033.10SD y 240 Vaginal bd eb C 8 7.9 Vaginal.bd.y.1 Female 33 Vaginal.bd.y.1 10249.C033.10SS y 240 Vaginal bd eb C 8 7.9 Vaginal.bd.y.1 Female 33 Vaginal.bd.y.1 10249.C016.11SS n 242 Vaginal bd eb C 8 8 Vaginal.bd.n.1 Male 16 Vaginal.bd.n.1 10249.C007.11SS y 243 Cesarean bd eb C 8 8 Cesarean.bd.y.1 Male 7 Cesarean.bd.y.1 10249.C020.14SS y 243 Cesarean bd eb C 8 8 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C004.11SS y 266 Cesarean bd eb C 9 8.7 Cesarean.bd.y.1 Male 4 Cesarean.bd.y.1 10249.C007.13SS y 266 Cesarean bd eb C 9 8.7 Cesarean.bd.y.1 Male 7 Cesarean.bd.y.1 10249.C012.12SS y 272 Cesarean bd eb C 9 8.9 Cesarean.bd.y.1 Female 12 Cesarean.bd.y.1 10249.C016.12SS n 272 Vaginal bd eb C 9 8.9 Vaginal.bd.n.1 Male 16 Vaginal.bd.n.1 10249.C024.12SS y 272 Vaginal bd eb C 9 8.9 Vaginal.bd.y.1 Female 24 Vaginal.bd.y.1 10249.C032.11SD y 272 Vaginal bd eb C 9 8.9 Vaginal.bd.y.1 Male 32 Vaginal.bd.y.1 10249.C001.14SS y 294 Vaginal bd eb C 10 9.7 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C001.15SS y 300 Vaginal bd eb C 10 9.9 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C007.15SS y 303 Cesarean bd eb C 10 10 Cesarean.bd.y.1 Male 7 Cesarean.bd.y.1 10249.C011.10SS n 303 Cesarean fd fd C 10 10 Cesarean.fd.n.1 Female 11 Cesarean.fd.n.1 10249.C016.13SS n 303 Vaginal bd eb C 10 10 Vaginal.bd.n.1 Male 16 Vaginal.bd.n.1 10249.C025.12SS n 303 Cesarean bd bd C 10 10 Cesarean.fd.n.1 Male 25 Cesarean.fd.n.1 10249.C005.13SS n 332 Cesarean fd fd C 11 10.9 Cesarean.fd.n.1 Female 5 Cesarean.fd.n.1 10249.C014.12SS n 333 Vaginal bd eb C 11 10.9 Vaginal.bd.n.1 Male 14 Vaginal.bd.n.1 10249.C016.14SS n 333 Vaginal bd eb C 11 10.9 Vaginal.bd.n.1 Male 16 Vaginal.bd.n.1 10249.C007.16SS y 334 Cesarean bd eb C 11 11 Cesarean.bd.y.1 Male 7 Cesarean.bd.y.1 10249.C020.17SS y 334 Cesarean bd eb C 11 11 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C030.13SS n 334 Vaginal bd eb C 11 11 Vaginal.bd.n.0 Male 30 Vaginal.bd.n.0 10249.C020.18SS y 365 Cesarean bd eb C 12 12 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C025.14SD n 365 Cesarean bd bd C 12 12 Cesarean.fd.n.1 Male 25 Cesarean.fd.n.1 10249.C025.14SS n 365 Cesarean bd bd C 12 12 Cesarean.fd.n.1 Male 25 Cesarean.fd.n.1 10249.C030.14SS n 365 Vaginal bd eb C 12 12 Vaginal.bd.n.0 Male 30 Vaginal.bd.n.0 10249.C031.14SS n 365 Vaginal bd eb C 12 12 Vaginal.bd.n.1 Male 31 Vaginal.bd.n.1 10249.C033.14SS y 365 Vaginal bd eb C 12 12 Vaginal.bd.y.1 Female 33 Vaginal.bd.y.1 10249.C044.15SS n 424 Vaginal bd eb C 14 13.9 Vaginal.bd.n.0 Male 44 Vaginal.bd.n.0 10249.C018.13SS n 425 Vaginal bd eb C 14 14 Vaginal.bd.n.0 Female 18 Vaginal.bd.n.0 10249.C036.13SS n 425 Cesarean fd fd C 14 14 Cesarean.fd.n.1 Male 36 Cesarean.fd.n.1 10249.C012.16SS y 426 Cesarean bd eb C 14 14 Cesarean.bd.y.1 Female 12 Cesarean.bd.y.1 10249.C014.15SS n 426 Vaginal bd eb C 14 14 Vaginal.bd.n.1 Male 14 Vaginal.bd.n.1 10249.C020.19SS y 426 Cesarean bd eb C 14 14 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C034.16SS y 483 Cesarean fd fd C 16 15.9 Cesarean.fd.n.1 Female 34 Cesarean.fd.n.1 10249.C005.16SS n 485 Cesarean fd fd C 16 15.9 Cesarean.fd.n.1 Female 5 Cesarean.fd.n.1 10249.C032.17SS y 485 Vaginal bd eb C 16 15.9 Vaginal.bd.y.1 Male 32 Vaginal.bd.y.1 10249.C033.16SS y 485 Vaginal bd eb C 16 15.9 Vaginal.bd.y.1 Female 33 Vaginal.bd.y.1 10249.C011.14SS y 486 Cesarean fd fd C 16 16 Cesarean.fd.y.1 Female 11 Cesarean.fd.y.1 10249.C014.16SS n 486 Vaginal bd eb C 16 16 Vaginal.bd.n.1 Male 14 Vaginal.bd.n.1 10249.C008.15SS y 552 Vaginal bd eb C 18 18.1 Vaginal.bd.y.1 Male 8 Vaginal.bd.y.1 10249.C011.16SS y 553 Cesarean fd fd C 18 18.2 Cesarean.fd.y.1 Female 11 Cesarean.fd.y.1 10249.C044.17SS n 553 Vaginal bd eb C 18 18.2 Vaginal.bd.n.0 Male 44 Vaginal.bd.n.0 10249.C030.18SS n 554 Vaginal bd eb C 18 18.2 Vaginal.bd.n.0 Male 30 Vaginal.bd.n.0 10249.C037.16SS n 554 Cesarean fd fd C 18 18.2 Cesarean.fd.n.1 Female 37 Cesarean.fd.n.1 10249.C002.16SS n 555 Cesarean bd eb C 18 18.2 Cesarean.bd.n.1 Male 2 Cesarean.bd.n.1 10249.C020.24SS y 599 Cesarean bd eb C 20 19.7 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C020.25SD y 604 Cesarean bd eb C 20 19.9 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C020.25SS y 604 Cesarean bd eb C 20 19.9 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C018.16SS n 606 Vaginal bd eb C 20 19.9 Vaginal.bd.n.0 Female 18 Vaginal.bd.n.0 10249.C030.19SD n 606 Vaginal bd eb C 20 19.9 Vaginal.bd.n.0 Male 30 Vaginal.bd.n.0 10249.C030.19SS n 606 Vaginal bd eb C 20 19.9 Vaginal.bd.n.0 Male 30 Vaginal.bd.n.0 10249.C007.22SS y 669 Cesarean bd eb C 22 22 Cesarean.bd.y.1 Male 7 Cesarean.bd.y.1 10249.C020.26SD y 670 Cesarean bd eb C 22 22 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C020.26SS y 670 Cesarean bd eb C 22 22 Cesarean.bd.y.1 Female 20 Cesarean.bd.y.1 10249.C033.19SS y 670 Vaginal bd eb C 22 22 Vaginal.bd.y.1 Female 33 Vaginal.bd.y.1 10249.C022.18SD n 671 Vaginal fd fd C 22 22.1 Vaginal.fd.n.0 Male 22 Vaginal.fd.n.0 10249.C022.18SS n 671 Vaginal fd fd C 22 22.1 Vaginal.fd.n.0 Male 22 Vaginal.fd.n.0 10249.C002.19SS n 731 Cesarean bd eb C 24 24 Cesarean.bd.n.1 Male 2 Cesarean.bd.n.1 10249.C012.21SD y 732 Cesarean bd eb C 24 24.1 Cesarean.bd.y.1 Female 12 Cesarean.bd.y.1 10249.C012.21SS y 732 Cesarean bd eb C 24 24.1 Cesarean.bd.y.1 Female 12 Cesarean.bd.y.1 10249.C018.17SS y 732 Vaginal bd eb C 24 24.1 Vaginal.bd.n.0 Female 18 Vaginal.bd.n.0 10249.C001.34SD y 733 Vaginal bd eb C 24 24.1 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C001.34SS y 733 Vaginal bd eb C 24 24.1 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C022.20SS n 791 Vaginal fd fd C 26 26 Vaginal.fd.n.0 Male 22 Vaginal.fd.n.0 10249.C001.35SS y 792 Vaginal bd eb C 26 26 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C014.21SS n 792 Vaginal bd eb C 26 26 Vaginal.bd.n.1 Male 14 Vaginal.bd.n.1 10249.C025.21SS y 792 Cesarean bd bd C 26 26 Cesarean.fd.n.1 Male 25 Cesarean.fd.n.1 10249.C005.21SD n 793 Cesarean fd fd C 26 26.1 Cesarean.fd.n.1 Female 5 Cesarean.fd.n.1 10249.C005.21SS n 793 Cesarean fd fd C 26 26.1 Cesarean.fd.n.1 Female 5 Cesarean.fd.n.1 10249.C014.22SS n 854 Vaginal bd eb C 28 28.1 Vaginal.bd.n.1 Male 14 Vaginal.bd.n.1 10249.C001.36SD y 855 Vaginal bd eb C 28 28.1 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C001.36SS y 855 Vaginal bd eb C 28 28.1 Vaginal.bd.y.1 Female 1 Vaginal.bd.y.1 10249.C005.22SS n 855 Cesarean fd fd C 28 28.1 Cesarean.fd.n.1 Female 5 Cesarean.fd.n.1 10249.C002.21SD n 856 Cesarean bd eb C 28 28.1 Cesarean.bd.n.1 Male 2 Cesarean.bd.n.1 10249.C002.21SS n 856 Cesarean bd eb C 28 28.1 Cesarean.bd.n.1 Male 2 Cesarean.bd.n.1 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/empty_file.txt000066400000000000000000000000211462552620600267300ustar00rootroot00000000000000#SampleID Garbageq2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/garbage.txt000066400000000000000000000000411462552620600261650ustar00rootroot00000000000000#SampleID one two buckle my shoe q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/importance.tsv000066400000000000000000001220321462552620600267400ustar00rootroot00000000000000 importance 74ec9fe6ffab4ecff6d5def74298a825 0.44469828320835586 c82032c40c98975f71892e4be561c87a 0.07760118417569697 79280cea51a6fe8a3432b2f266dd34db 0.06570251750505914 f7686a74ca2d3729eb66305e8a26309b 0.061718558716901406 4d04d759f5a6615dac43060726239891 0.028086160290024458 04195686f2b70585790ec75320de0d6f 0.02610253907515516 ea3433f2c148c6fae4cc2e9ae197f5b8 0.025273854068462408 8ce931b0c99ad5ed648c25483c1ca492 0.02029344879308132 370829fece3190f1a8efccf50b7d0921 0.017580266040786597 8720f9ecd2331ce68e2896df1bf2d977 0.017034058634807364 e2c3ff4f647112723741aa72087f1bfa 0.016776104364241963 a650f349bbdffb95b3624519d1ba72b8 0.013283768202156983 2ae8a432208b85a14e86eb821c86ce2b 0.010909411591413926 cae14798faeabb8e1b8840e712839921 0.010685797620545407 5d62137a2d05df0be8d6b7e163a3ef08 0.010020841856182077 596c1c5efe777a8d8aafbca19fe37e1d 0.009651091043216155 48d9883fd871b82d9bbc89cb0447be8c 0.008982921060244274 8937656c16c20701c107e715bad86732 0.008214293017642144 c1b636001e0773f9cca8096d70e8b5de 0.006950690004962161 77ad88eed91eef009bf64f101c96baa6 0.00665688537920522 5ee1da6b8eb2e1149af74254c8c07736 0.006601399203235563 eea6b86c0c75e740670ccc50613b1b23 0.006479475209726379 3128e057b1d4f320961e4da677724613 0.005645919539722557 be17b29b03ed02bed133932284568d16 0.004989948679963887 a66dd8d31584930c2b0f811f572dddcf 0.0048124059283415396 ea2b0e4a93c24c6c3661cbe347f93b74 0.004810025669591898 07bfddb8e62098a85afc8fd68ebc308c 0.004140136921392747 4b548f1f6fc22f32237396b7d4ffee6e 0.0038498233115332368 d75b7080930e7a77ef3de8c6154895b9 0.0033346270477890225 9099a7f671b923c7b07c12508f17270a 0.0033074689234597054 0c70bdd5631104dd3d818561c9166f6c 0.00324330648569082 47ad35356a9bfec68416d32e4f039021 0.0022404365031278746 ee084a976fc8028a3fdc50c9555b2a08 0.0022298514655499533 c162a4f3943238810eba8a25f0563cca 0.0021855014795936893 c4f9ef34bd2919511069f409c25de6f1 0.002166099280415516 94b000e59b7ac160b0416c9ab45ff0bf 0.0021550588496877933 148c7eb0139bbc1b8c87dd31464742e4 0.0021365496990399203 0cc2420a6a4698f8bf664d50b17d26b4 0.0021008032637668066 d56536a97c18adccf18eb08958d93345 0.002021901283310038 25def15fb42bed6855ede4893d27a21d 0.0020017444379080624 c18afe570abfe82d2f746ecc6e291bab 0.001972967397047078 a9387e76477da8688775569cf540191b 0.0018074625819242743 6c83fec6e8d03fad51eabc871853c991 0.0017508229418444995 8a261f382a739bbc5f9494b2c64c2744 0.0017232389271744585 3e93fd55a231bb99b67a666bad8446a8 0.0015688191643981873 d996e8d86e152c0a3c5852a2d8c4c52c 0.0014605617822782211 bae0d49b5eb22b0dfaecbcbf39a52265 0.0014360435703925205 74923f4bbde849e27fc4eda25d757e2a 0.0013332140948707867 aebf2a74a3aa9e5876c479b1db88985f 0.0013164588291310188 8e6e925baa81466352ff781a289e188d 0.001305557690975839 d1b7d3ea1db807e9352522d92e403246 0.0012130802121359668 90c2b51afe404951ec89bd52c7ae1f58 0.0012032892974370578 9d4e16844252e2dfbaf80a4a6fc4d55d 0.0011721920358687048 dafe809740d0545dc25c6939a84a1820 0.0010598552486115634 df6a1dbd34417b068878c043bd7a6bcc 0.0010397960283382362 4311a44a7d56ce4086afad3e75bedd6e 0.000943488403386402 61795ee8e60f4a0f66080ab812573fb8 0.0008962861766715468 a24dae6b87885a55d81df1ea6d1abaf5 0.0008721132528209371 7667b07b46f3d78c76f13781337cd218 0.0007996665724943059 3f1ed51e954b35a8108c12dd882b696b 0.0007869337305015549 29bb5fa7f45e47bbabab8cc1b1b3d18e 0.0007471894961390048 ad52a0f6646c574417ce0b13b84acfa9 0.0007379284165598606 59b17c1cd2e1fa86064869f5bdbea8c4 0.0006810720140934703 2fee36ac3b841b7c63b377f87cd57634 0.0006184580387951528 ad7bc2bb6e1ec90a9bc3c8949bce80d6 0.00061784619277928 d9b76ee51ff2b6961430bf352cc578f2 0.0006143795451714199 877f27b47c85f6b2d3cf8a6aa86def40 0.000579939824065776 1986030e3c5cd5df6d869054bc96e536 0.0005571839389159251 e91f1c5b67ffecb5ca3ca3b393a50f00 0.0005367673621172981 f83bc32e60e9c7bddf53a52937cc7ab6 0.0005354610613922348 059c8f8bb468064b134ea6d3661761ea 0.0005301713126190168 1243750138937650754b619370565800 0.0004890847692921625 9ac5fec396208e598ab2e2d26985d0df 0.0004198438160258734 d43642bb228b6bd084483d2e5b48c3ca 0.0004196113785368746 147e08753c0c32354e69746256220ca8 0.00040094057274993046 b9024a1f377b62508864cfea59b16a31 0.0003872820865898205 3b092a59cd0e2d57483420cc994ec49c 0.0003753321093973754 5e4405e37412f415c47c112a0cbc487a 0.0003630769561779562 6c7fa77831ae630967a6fbfc8ee47901 0.0003620100294304884 e7e74960c5ee1984f2e60f99081a368b 0.00035092992275626917 b75d05e361f46e33b39ef21d05334744 0.0003429082395799726 0d357d84911ef4a089c6ae3c6deb39b9 0.000321837484901028 bca0b81a0b8d59e90c25a323c2f62f31 0.00032148902937567593 ece1af985b63ebccd2833e9b5f0432e3 0.00031620424482054 dff37b3a4d27b9220b9af1459162a48b 0.00031297752477390487 78eecb7cd2176d3a2ed21ce8154ba1b3 0.0002897361736257693 0021d135d4ac12982cc8abdf2b38e23f 0.00028687561969616186 1ad289cd8f44e109fd95de0382c5b252 0.0002614751742022106 b7fe67097e773cb42109cefc45628173 0.0002592864600918602 82585d0d14cc315f9da0257c3a2875a4 0.0002544671856237352 ac5402de1ddf427ab8d2b0a8a0a44f19 0.00020068725358655715 c123ec846a7e3837d1247386a6060ad9 0.0001854681628289824 2a13ecb6c618ddf8154298c69336dd8e 0.0001810963201993466 7ce470a3f833253f6d667fa6830abe07 0.0001808688941675811 588a23811b3e98af68f4f0fb24a0daa8 0.00017377450975371653 447b9d6a5c17543a456c597e65b37139 0.00016726377442023347 82c890da8759fa9477cd991a1f214b3c 0.00016594333445879174 ea3af29626a95b6c7b89d631bf1a739c 0.00015564865018761215 ed5952d1e022067b212146b9b3bc6812 0.0001490369165590016 010f0ac2691bc0be12d0633d4b5d2cc4 0.0001427705331111527 a590ab40dc8a6b5cbffa347e8e32e63d 0.00013477008207658987 86deb5cf8d6f29d383136e0d09863b69 0.00013383226709210312 d0f1985c2b919dcbd0bf4664c844a900 0.00012362381132402674 124c75409b4ecd0bf23a84e28593567d 0.0001205792627783874 a186bb74dfce512f83043f7b366c60c4 0.00011304305885473818 62cb0ed0f2cba6fd1ab5d2a374c15bb1 0.00010757469651420703 1aab913302590e21a7be28b1494a3320 0.00010706581367368249 c8d7e00fbcfbd34e1c85a8040155ecb3 0.00010371458403674598 fcc915000295812eecfa7245a74346e9 0.00010216080211401838 5b6a30b5a900999d91448bc79c5e14d4 9.716320058704939e-05 c5b4c6b372dbc13b6a7f2d466fc7335f 9.489811410385969e-05 c04879d53b5b084096c5f2bdcc38d55a 9.334312563306969e-05 de08a70ee5e3336d2c494d20206e650e 9.043444708379022e-05 7281d8476d29dd24b3e674ce9cd9e3b0 8.785266881993596e-05 9b2d42844c99887e67257a377f7b193b 8.74479052197794e-05 4e1758e81adcb1107024ee52c0113a6f 8.098909104258687e-05 0189d0173c07f11e7586ff20eb33f5ba 7.858913280228686e-05 539ca948741b9a713eb781d4281b23fc 7.821268709252524e-05 b3fef1e26b7b6ac20847ede4da68547a 7.701147547233651e-05 ee02d6d3506da57909d5e603709a295f 7.427114488130107e-05 b45c9784d674879d68d54362419a1d70 7.171890492404162e-05 105d5959bed2c9399522aba4291031fd 6.810720140934897e-05 3baa56d5f42b81f2817aa34412e36439 6.782583531284291e-05 bc4177a5fd330e9c23138dac2d6c69e0 6.723418532137901e-05 de61860db8d93da85692dffb5cf32ab9 6.60098361191445e-05 6a66cd42df39f678f4bb2f3e840b011e 6.028963138919508e-05 b7a041d2927c03859714fcdd60b9dc7e 5.378917869303054e-05 04c8be5a3a6ba2d70446812e99318905 5.134352337296379e-05 328d5b7cdad033d7b3ed419b720ba2d3 5.108040105701027e-05 4c731267e801c2afe253b5cbb58bdd24 5.0241359490998746e-05 b835514e2678e3c7ba13bfe0a0d79bb4 5.0241359490996184e-05 2480f3aa1e7784b461d9b5b83a6bfc81 4.604372766711962e-05 237135dc8b20f922cabee934f7d410a1 4.460367317873236e-05 5cf5895a231b0a52d5859c74c74aada7 4.139914348861156e-05 764bb70efe70ec930379806d178319cb 4.0341884019772904e-05 40c85a458df8d5a935122ba778d4f334 3.7337250253227875e-05 34c133377349d1b57072aaab4f781fd9 3.580564835875417e-05 2364e23d05750415070f8df3ccb0c95b 3.568860455789974e-05 ede423f2b32cfcbc0815db2435994947 3.3617092660689695e-05 424613c7d3d2daf5c715d1356a972381 3.3188666891759055e-05 59196a586276f0be745d0e334fc071c6 3.3188666891756934e-05 954f244280781f0339631a6eee679e1e 3.0255383394620722e-05 30fc8af207d17abc37394fbf3d1793f7 2.5212819495517268e-05 b8315874f4341a59e8e3ed317406ab09 2.4891500168818583e-05 b0574dba26050e54cf5efd672c2f58ee 2.4453423469918827e-05 52b25decd37eb58a3bd46167d1c46354 2.128350044041883e-05 68c83aae1babce28612ba404b1096cc1 2.1077191628870952e-05 c5adecb440a6bac201ab573ccd2d6dda 2.098349859690685e-05 ff5c02a6c8a80d8898f37b7dc71f4c10 1.897042303767303e-05 5a0df24ab3d9c2d78a043cd477a54b4f 1.8243000377503335e-05 df1bc3956db29b2cded9d3925999f6e7 1.6809118341572044e-05 4bdc8766a80671911353b96f2d702ffc 1.344683706427589e-05 22b9160be22106587cc68893686c44c1 1.3446837064275873e-05 f8000a94d405169f38df61e7cf1cd286 1.3427118134532813e-05 df3f8cdac76c62baa98469c33b82d8df 1.2770100264252568e-05 1ba09da532a0f9985b3caf72a47b42e3 1.2376844272339594e-05 cca22a273fa140d50cc3cdce9f539f73 1.1787784859310052e-05 0c17cef318a9e1c8895c0961c5ed2193 1.0706581367368972e-05 3ee072a59b45057a86369a7c80ad90e4 1.0371458403674174e-05 ed1c3370c86ae00e0062a3498ef06cf4 1.0085471004943226e-05 1a389bf765c8ff0f92600f684fbe7ad7 8.9648631155042e-06 276c5b1d00e091a197a9ed8753beebc7 8.951412089688543e-06 ebd14a21e990e0266b2b985be4cb3c44 6.6916133546051555e-06 bc0588863994a8f20e7dbce7a6fb8b96 0.0 b1f2146bef78066448576fceeb6b644b 0.0 bc23d2ee539bf2f52faf789289af7879 0.0 8dccd839cf4868a3343e411c063932a6 0.0 b153e0852342c0738da791930625716f 0.0 bb8cd42775d7feb5b54059f90e5ce9eb 0.0 b148aa1f06e0eea5a72ac72fdf3ac867 0.0 acfd094c6c92700cdcf89371abdd104b 0.0 ad01a1417ca1d8a5a7a768ea78e45673 0.0 8fd6bffb88d374f38c6bf35cc8a4a221 0.0 8f5b5babdbe9847334e115160088b371 0.0 b098aa6c11cba636420401399b83be7c 0.0 adc59da8759a4276a8f218e237e27f12 0.0 ad8991870b8bdd236d97d01487ddadc6 0.0 ae791ca848029549cd27ece21344d8a1 0.0 ae793fc8909a69dde3c7757780299e14 0.0 8f4a3341ccda8d1b45f286cb686a3aec 0.0 b01e64261beff06c591132b8f0cf3099 0.0 b265615da6b98d477507607fc51972f7 0.0 8dcd5864b11c06837480c727198cded4 0.0 af25adac3aa4a6a6f6c97b23b7755273 0.0 aefd4044e43af5915f9a3fac602e9308 0.0 8df5a666d571bcb1b2a44aaf978fab49 0.0 aee0d6f2626271eacf89d2e803440657 0.0 8e1c69dc9a692ce4b7e93c8cb728b7a6 0.0 8f1c11c7b732265cbfc1bb7dbd0241e7 0.0 8b159e3b7ba334383b185c1926d9b9c3 0.0 b29deb0964b5328b6206ea33b9035302 0.0 8dba41073e8e2650e099cda3fd3a0630 0.0 ab2ef9bffd8e25c75290c0a2f6a8f85c 0.0 b460255b8269b55301e0c3c3e3da252c 0.0 b47e328fa7998e8085a30dc2a03506c0 0.0 b47e999a38113e0e4e2b139e8b861fdd 0.0 b48a25941ae901a73b4a2830cc24b382 0.0 b507596e6af67ab90ce421ce6f40b0af 0.0 b55ddaf95d9d2217ea087863a7afbbad 0.0 b6985598d3f4a9b830bbe1c6a665f5fe 0.0 8bd6fae62d450bdf768bfc6464d36d38 0.0 b796b2132a5015f869c8b5ac44a0e2bf 0.0 b955f67a541a149dd3b179dc62d37a72 0.0 8bb5ff097e0707dca3fe5860af20f4a6 0.0 8ad30192adf51cd7b03105a1acdea794 0.0 8b86b84549e5940744c30df2a573b55e 0.0 b8c685d6d691d57d63a05b0eaf5a669b 0.0 b8c6906ea995f21303d44ab7b21655c6 0.0 8b78fe0639a5308fb6f33a8eaafcdfd9 0.0 b9d953d2c367d1b3150ccf062dacfe83 0.0 b9fefd4224e459a6a0d21db63b1c0d03 0.0 ba88d4e4e6a24ecc2a5aab6bdfbb77f5 0.0 b3d06445a910a9a444919e41f5da39c3 0.0 b2ab597a902ff227a5ba76030cd6002e 0.0 bb1c2099a32a335b1a55f44d3ba54484 0.0 8db257dc277d4e84ef974e07dc449820 0.0 b2e3852763d37eff884d326836ccec27 0.0 b36ff490f4df87e30600ed347f23cbdc 0.0 b39a1bb517361c2a87f8fb48d66a49ee 0.0 b3b1ae423dc7f3d8942237d115a5bf86 0.0 8b0fef40cdee88fe61bf6c86ea5b8d41 0.0 b4446b03208372a5dd17608d78f7e3e8 0.0 b3e2d6b8bb4b97afa07c0d048746b712 0.0 b3ea95770cf649371d22e1a1d5aa3c0d 0.0 8aa70d0c06e8da0b4c0ea2eba6308983 0.0 bad4f7c5ada34a1f813946abcfe5c556 0.0 b423592b0ae631882095792b27729b9c 0.0 8d99d70a19898e91e9d7dd54dbd5881c 0.0 8d89ee75fdeac54f5ebb1ef3edf80e73 0.0 965d7a58f59ea6445b32afede05a4012 0.0 a7e74b8756d98ed147f70628144245cc 0.0 ab0b78445a54df766c12448fa0ad6d49 0.0 9dd9cefe38347b087dd318d82962cc03 0.0 932e1f2d3f75eaba13d2b2be2f2f7cb3 0.0 9c25197937d1f54e2634026fbca6b55f 0.0 9c58ab3805d06ed6f1ff2a2de766458d 0.0 9c61dd9fc1208289eefdccd5ad281288 0.0 9caa12440830e96456250882ad25f89b 0.0 9cb1cfaea33aafcffe7c261eb104ca56 0.0 9d2176c908640e85287b95f9cd17bf64 0.0 93029132afec86c495769fbd8dd65ff2 0.0 9d650084364f31c59068a17261e13dc8 0.0 9dc78fd8f2f7cb10e190e77af61c7ecd 0.0 92f000f936d3f349c5e7719a5edc5078 0.0 9394eec407745afeb6370fb2a0ee1a98 0.0 9e033e0a6e420a9d407f908d59aa31eb 0.0 9e644716572f5930cb56186d75a6bb84 0.0 9e8e56f06c0615130e1e2f459bd4052a 0.0 9ecd25659ebff6a840c089b93515c5b7 0.0 92ae272884c88aa3be9a5800f2836740 0.0 926708e33d1ebf1a9da757f78c673190 0.0 9f48f7b79ed6f3dcde8b25e0cf244d5d 0.0 9f4d14b114e7499772a797790d81c1db 0.0 91d7d1256be7c1797cd45c2296095521 0.0 9f74473636e6874853d88dfcbcecff49 0.0 9bbff59b3c1084173c4917e136b496fa 0.0 9bbe5054cf0bc376baf895f0638705f1 0.0 aacaf5f360c110204da1051a50c5ba5f 0.0 992072d045462445dc239b35300af2cc 0.0 959d48a11e3b26c9268f0bd1dae6ec40 0.0 96794c2d601e0082c9b66552dce42e4e 0.0 957a16edeead7722188be53d05fbf001 0.0 97951199cbbcc765ccde49fbcbff09b1 0.0 979578981da3916b394bf24c32bace21 0.0 97cfaa815d9e25d41d6698f790b7ad0a 0.0 95348b8c18227b458056472fc9eeafd3 0.0 9828f58eaf910927264c204ace9caeed 0.0 984ef97167ec7b42d7a3650716d6a2ed 0.0 988b0b7321184cfc2c53e0966dcab560 0.0 94a699e62982fe59b7725f1b7271972a 0.0 9acc238746a1f2aa7745a0b5720c4eac 0.0 94738eca8f0e714dac0390e647565488 0.0 9938c8f22908861f780f8719b75dc0b2 0.0 993ea35e8ad7ff6894e32247dc507e9b 0.0 99dda7b5337bc09a69e9e27bab56fd79 0.0 94650d81f3f14b948edfadca3ca7b166 0.0 94035fd1b8dabc1d79586ff8b52846b3 0.0 9a75764782a384ce3b83e019c8b2dd94 0.0 93a9affe525a4ddda933fce27518d7ce 0.0 9aa7314d56b3b3db2253ec2763414be7 0.0 9394fd89106163be8a11cd4dc46bc8a3 0.0 9f8119029c8b972ae0375c8b968c14e6 0.0 91b88aa295fe09a255b2f321d9d2b12b 0.0 919db619ad90cc6b09b31c83d5719da9 0.0 95f77f9e6df255cf93ec17c1a48bc194 0.0 a607665fc01df970cb3f1c4002a00bab 0.0 a6099802840e60febef8e896967b7747 0.0 904f7b1ae29e6a78ff83eacd9ef9cda7 0.0 a66a33da056496a076f57ec22a435dc9 0.0 904d063813394e9a3cd5a23fef870ec8 0.0 904ad13c7b8512200836d5cd9fb09e1b 0.0 a6bd74dcea0ad6299a4cd2937e192151 0.0 a6fa2de5f4576d1d77b1616786e3dd52 0.0 a75b0438ad19fb4e31f4d58c2d49ea02 0.0 a765441df9f96c9e8a1baf9645528616 0.0 a7fad69a900f747d777bf13f8c1ffd83 0.0 9122e867c908301e783c5ce0c3bf12e0 0.0 a837426344372de1e6d07876dd214a5b 0.0 a898fafd80c4c90cdcde401ca2332e05 0.0 a8aca6d9fcb6ac34f6104cbe28a466c7 0.0 a9566f812a634f1b709810bb0cf50629 0.0 a957f3e1f57e99be7c1c28de7f016780 0.0 a9b72251b244f66d8296965d9435218c 0.0 a9e1acfa6cc2678b1fcc40f49007d4c5 0.0 a9e6fc1854a3fd8873b32c9fbd9ac13a 0.0 902c0a7dd5a911a8fbf9e34e49f72297 0.0 aa738f71de2d14bf826740d8df65e5f2 0.0 906138f305d5b85ac761fc50bbb6ca87 0.0 a5676561cb37d21b8c485040ca3ebe96 0.0 a544abd909afc727c4418e4e19eed417 0.0 a51b62113b7c9d4febf6956e86e5dfd0 0.0 a02c286e5afe7220b1fdf83dadea939f 0.0 a1999b4f10c91d6f8efa3c9d73f77fa4 0.0 90e427df120ab07ffbd57703f11c1a4f 0.0 a1a22b2e460e6454dca7805f1cde48d8 0.0 90dd37137cfac54abcaebc7048fe77c9 0.0 a1f75692d5fc417ae9461aa66e0ed7ef 0.0 a220d7daecd7de9a9560ac2a5a64e2a5 0.0 90b56798a9abd8360a79627ec3c332d3 0.0 a2e0f228d7110587954e13405f98f003 0.0 90a685caa7eac21daa8a8f56df52eb29 0.0 90a0937762431acf0f8f3643e08d3180 0.0 a2e3ac6b18daba602b14d93882f3663a 0.0 a33859e0fe8e20bd783ad918ac192884 0.0 a36d070ba91e6c48d0c79036200d0b20 0.0 a42ad1956d801cce5e0109dc0e987ceb 0.0 90949bb38f58e92949ab8504aff01df1 0.0 a4c61d535793417f6f6ab9eae2463f12 0.0 a4dbf71f32a016e120fe6cf253dfa6c0 0.0 907ceab78e867d765fa360527608efa1 0.0 a4e2a4e1321a599651edf92f6999e78e 0.0 a4ecfb2e708863a17978a0942358ffc3 0.0 bc4ae61d84daab04b0e888d22f7d3f69 0.0 c6959c6d7f3f2806418eddfeeb3f2d22 0.0 bd0f4e14387ee1ac7e5fe586cadbbed4 0.0 ecaa9f4e15a28f212d9bd60f749191ab 0.0 e86212f766f010236a072bfbc04774b4 0.0 e8cff5dd9314935749206c1d83214d77 0.0 e94776066de6ff852fc7a43e7a0626cd 0.0 e9c73fbac5dd73dd5e3ada5664ae95fb 0.0 ea6265476f08a35fdb764ae98206ad5e 0.0 eae4215acb2d651ce76c5e4d10f3d839 0.0 eaea5d7b84c08fdef5d8ab40f707e37e 0.0 ebab7cfc7858bfb00c486bba21d6ca6d 0.0 ebb5ea4b9b617249c40513ded403e30b 0.0 ebfae3fd8d9da7341650be7f4f6c13e1 0.0 ec38f851c5429708e114208c539ae458 0.0 ec6c9ea52e88226c339487585ea02f42 0.0 ecc877a3410d54ea784131356fe5ea73 0.0 e82ab12c51a893c6d7938a16632199a8 0.0 ecff0a63780369ddcdc800ab97fb81f9 0.0 ed1528f4822674c9e1da64b84c778e9f 0.0 ee062262ac3b97896676e558bb08986a 0.0 ee41b2201102d120e0ceff1eb49ba6cf 0.0 ee5c4bf663b722fc809746f322a4f6f4 0.0 ee90bebacf6867cd5b4c487cb587ea9a 0.0 ef4045fe369d078db89c253c9ddbd123 0.0 ef467d766ba05adf651d1fc6a30cba06 0.0 ef7c8af53de2ee3385027bc6b4bf0883 0.0 f05a6141cb84e0c95470be3e92085b93 0.0 f09ca081a69806aca5de24d404ad4c6c 0.0 f10155af1849a17996f302d71b32398c 0.0 e84bea8ae61342674744560dd7de4721 0.0 e80317d0fb0618cf19a96ef454fef9de 0.0 bd8cf9d4f4744a93802336d81b60966e 0.0 e30c40e583572ed45fef99d6a32d3924 0.0 dbf76c1b3ed4745cb94c15374d951beb 0.0 dc92897ae65716d40ff3b2746a2a6527 0.0 dd50bb187bc6f99222e626ddc810909a 0.0 dde2f514908a4fcaa80827346c7b7a19 0.0 de0ad18436d210c9b60044fc7b9caf90 0.0 de478a19bf7c5ab5e75d3dfcb742f4d2 0.0 de6891b6f7a1f35bd9ccbc058b9e1a77 0.0 def8acc0fc88cc9a9cf110370ecc2c37 0.0 e0fdbc7f687a7ea0cf13009c2e501197 0.0 e10c0e74616a50d8956a945d0b6dd531 0.0 e21d9f482315985036cf80d1b20de58b 0.0 e2bf5a8c1878477d542ef764b910e5a2 0.0 e32053e0d7a8b525d0b062beb2ae11ce 0.0 e79e5e4c871bac3c43de566188e10002 0.0 e392de248b88befeab2319aebd7872c3 0.0 e3a4a62adc4e83c274978806164b474a 0.0 e4207d118a1ffe33509edaf320ac2a7c 0.0 e4d8026eb8e261594d51750b1080dbf7 0.0 e56aff2928773e4f9d4646bebe35123c 0.0 e5a43b018c81cedd19e9a5354d32d469 0.0 e6441fdd2f0ec36ec914d7154a64061a 0.0 e644522cf6d7222c9da7f9ecf614cd89 0.0 e6a34eb113dba66df0b8bbec907a8f5d 0.0 e6f747cd89d512cf187e8472cfb250a1 0.0 e7037dc2701d6b9666d2c0dab6110ae7 0.0 e78cb60fcb9cadfa0a32ba3ac4b2e95a 0.0 f12011ad5219b22b6ca790103333a755 0.0 f19fa34c0c987ab3bd8aa42d8a4d21ec 0.0 f1da0f084f3e5b7957d11d01abe7013d 0.0 fc7466fe7b054b641298ab8b5c707d21 0.0 f85dae8239789b16d0f8dcac9e272361 0.0 f8dc4d17a9589b91dc466d20015518e4 0.0 f94eeb84a8ab5049e8e0cbcc078de30c 0.0 f994313e9f7ddae7f7d6806221d6be70 0.0 f9b52205cb2d03153fd394a290212a10 0.0 f9f5f08e8da4cc9740518223846563db 0.0 fa09b814b417561651db81db34860ea5 0.0 fa1d5d724ccb4287e07ea1caa9d35502 0.0 fa71c8409cbcaad5dd98b8d80a46b07b 0.0 fad561b7eab58e57b71a09a8b7f990c8 0.0 fba43f263a40d5a9cc7f37f1551b13f9 0.0 fc613984c6bd68a102eb7daee76a24a7 0.0 fc9717bf86bf07fe748f608b4f2c57c6 0.0 f283cd6d309acf7626b1fbc0079d275d 0.0 fcab01e402145abc9e946d12aad1cde5 0.0 fcfab546634e10be9800b9a4118b8dc9 0.0 fd069fff020b15638483c7e49d2ef9cb 0.0 fd1830279629e35893c2cc7538b028a9 0.0 fd1f139259c53276619476db0cc81913 0.0 fd21badba5eecdf5a284d5db7aa0679b 0.0 fd8cc2ec2e11078f3635cdc7fb477823 0.0 fda9e2638dfa1f4eebff04a14575f763 0.0 fdcd6808ef8269653d25dce4a55a025d 0.0 fea3411c847e6627afb5e78b88e2e9af 0.0 fefc7999a7e316dfa98bb6b63d6cfda9 0.0 ff2b5301608beca5896495311a512610 0.0 f83918824d8dd7875a4b478adf4ee601 0.0 f837443696652157e220ae13e330e0e6 0.0 f80a17436037d706dc728dd265b7c21e 0.0 f7ef98bb6d0061b9368a72b1ff40aad0 0.0 f2b4aaab4b89a51ec6205485018c9419 0.0 f307aa8ff39ee31213f4d9e1bfce6dcb 0.0 f3153e589a8718a2a1109a6e181617f7 0.0 f31aab4ff2dba1e72d9ea251e447844d 0.0 f31ac04c4b89a126b2406e811dff97fa 0.0 f3b9619b167cd0ec5f9c55a7dd6c7ee6 0.0 f3c30aa47b3639f25d168a810ee07fd9 0.0 f3cac486ad34144511deb96b29ded2c5 0.0 f402dfa5da0f4bd53468557a1a6b01e3 0.0 f434ebfe13e3764e53f40e7b99e07a39 0.0 f45b62ab6ec22fb20364a7e05088158f 0.0 f47f8e690205be8c0572db3c32829f43 0.0 f4909ad74d5b44aa7c3694798c21ea87 0.0 f4cd813a1b8a862f7a285466b25c6302 0.0 f5487404313a4fb57bc3489c167e9a37 0.0 f56e589e8377da78834cf577a69b939c 0.0 f5dd3f079f8866010ff9e1ce86dea070 0.0 f5f4ef252850e0b1f378923731257d69 0.0 f65ee26124609d6de91d4bffee014357 0.0 f6c6e7419ddde1e2e1d4a790ec6babfe 0.0 f710c0927080e422094a96ffe13b389c 0.0 f73160a94abee0441ab5a573877744d2 0.0 f7a5b80128b001df0f52bdad023aeb23 0.0 f7ce5d68ad002cdc285273d049516c84 0.0 f7e75337c2baaabcd5c9cbfa83ce5ef1 0.0 db9caf76f81e72dac22fd1a55da6d5ce 0.0 db6e4e3d6bea23bd5c619e4dd4ef5b87 0.0 da5463f9a3163db4528898c49e7fa54c 0.0 c9ccc527189a7a19902fc022a72c3bae 0.0 8a974c19d04562e710612ca049799942 0.0 c7408e951d6050a4ea360aa404050896 0.0 c7ec80af1d984fddec04831296fd65a5 0.0 c7ff7e806765a39b6cdf66a15b63f6bb 0.0 c870a3c711d733d9058cd2274a101381 0.0 c8933e6cd4ce9389f4ad6e2e24dbf5b9 0.0 c8ae16a39fbfa227aadd2e6d5a63da7e 0.0 c8fce068920feb387167d44c01689295 0.0 c936431ab7a77c5828a3da971da51acd 0.0 c942f59feffce9c3ab527135de234101 0.0 c98ea813f96e96f25ba321f74703bf6b 0.0 c99c4c951e6f4745973043285ccf486b 0.0 ca0fb2462b67d4296fdb8de1372d9165 0.0 cd5f131980408e798875e41b3c0d53de 0.0 ca5b38f92987671538ac4f8f5b4ee95d 0.0 cac55aa795998014361e14836ddae2bc 0.0 caf54b4995a78b51266cb0e4aed4deae 0.0 cbb1dee8bf80a6cf676e15d39d9979d1 0.0 cbfaac9f291ac42563f27903d0f684a1 0.0 cc3e4918ee1c089c5bed6cab11dbee83 0.0 cc42ed01e236e8f05d25a7310d47e354 0.0 cc5f74d0b0787e9ca4f97835c2c0f2a2 0.0 cc968157f7691aab95df444e8cd103e2 0.0 ccce7fe8aa849bed027f6898300e0c45 0.0 cce0f21cdf5597d900d303fdac05b33c 0.0 ccfb4c8a7a57ffb8fd5212276ff2b193 0.0 c6178d46f91b123b2c226120a3167a34 0.0 c5e3c5422835403541b0af331a2cc649 0.0 c5b95a83a06195f219b0edd9ab18fb1d 0.0 c59161ae395fd5322d2f192f13cfb31d 0.0 bda6b6e7da7508c68057140e7bd6cd8d 0.0 bdb2c60864ae18c4302c9f144219512e 0.0 be480a1e4a4e71fe774ccd3e4ff22945 0.0 be9eb15986b4bdfad6c474a30e7ce4b9 0.0 bed1b5521bddc2d35732fafc25043f19 0.0 bf8144aac6a30e6695ad6bf8f49131ab 0.0 bfb7bb16ab570748b3a5d099e9426af1 0.0 bfd6e1ccc45f37b290d63de0053c212e 0.0 c07ef20fbf08691cd223cba17009e12f 0.0 c0b31b31a1d47acfa4b2a6b279ee631b 0.0 c12331989624002d4f790eb1d19dad02 0.0 c1365ec008032ee718dcafaf5ac17adb 0.0 c1a5735daf6f1e6157aeafb503b9e564 0.0 c24ac2e6e7002af9827563df39144c55 0.0 c2cd19f77efced924e3eccd8bc6750be 0.0 c2efeb6d250b34f682ae6380682f60b3 0.0 c30a545d14731276f649c2428c0babe7 0.0 c326a5572886b04b8ec92047c9415a00 0.0 c348a7cc121fa43fb14ca92cc4273c2e 0.0 c3937c933413c88df1db4b761e0e3ac7 0.0 c3cb5f0be6d5e3a4761a78606c1e4113 0.0 c4b0455f8d6d59d4caafda4b3aa90622 0.0 c4b11e3e5340bdf421aeb4ba0aff0269 0.0 c4cceb02f4ce674101aa2c0d1317cdf6 0.0 c4e57b91cc2be5a2232b3612abdf4c0c 0.0 cd1fc0b5ef8bb9823eb279222f0d0860 0.0 cdce04d738e587eb6a58f8a79ed36c20 0.0 d9ef9c1fd69f0b398b331c428991204b 0.0 d6bb5703483ac68992e09ce17683c52f 0.0 d34887a684a1acc690b8f3644cb11c12 0.0 d371cae3627eb71177294af103c68940 0.0 d39f37b814ebd81091a949f8bd9d1710 0.0 d3d99580d90cca486a23372a474e9571 0.0 d3f86c6a6fd03654e0848a1fb1ad1385 0.0 d43ad42f3b1625379a2429c10f419eda 0.0 d4e63b08a25162d359541e38c6e484e5 0.0 d4e8fb8d73378ac761ec8eb3faf71804 0.0 d5b4f33a93b1580c123d306690d0ffb9 0.0 d5d727a0e5ba892a10e9c81ef29d02c0 0.0 d666cafbfcffb984b12c4a405df6c7c9 0.0 d6752c4c0b83bb0ba7df8368b3c94d6a 0.0 d6bc69828ae0ef27e99c01c9e7df86b0 0.0 cdfd52e813292000f1bbc5c4d7c95b4b 0.0 d6c46ad81c01997055a3b713c0d5ee1b 0.0 d6e76cfe58d253204f5589d78cc79bd1 0.0 d7130a2536c5b200a01662b82ff93d06 0.0 d73c014c9a033812619aa44e9cae934f 0.0 d7466ab97edf938c5ed46f6bb1649b60 0.0 d780f9d98701c8ab19b4488869bd5be6 0.0 d9294a924ce5ef9df6e464b4ef2f9db2 0.0 d93dfe29130fd71bd30fcdeefea2862b 0.0 d97a97d4f8974683e4a66de090129c1c 0.0 d98796acd66eb71638defd318991adfd 0.0 d9d0120f569d8e15590c6486f4ffed36 0.0 d9e7a2013a2b6863cae05c51be41848b 0.0 d32d7b4a5e805f7e43f7823bf3eb566d 0.0 d32627161d829a1488c2a047669cb29f 0.0 d3211b7a04e5fb36a383450b8f5710e2 0.0 d315a0b30c8e21db4cfe89e65c0b2bf1 0.0 ce33f26f3bd4784cdb63910753fa0792 0.0 ce399235aeab566680d0ad1ac6f9c7a4 0.0 ce9976fb696a210e526fb161c15ed88a 0.0 cea0486054293b47714d155ca349b763 0.0 ceaf720138cf7bdfb66e2dbdae539e38 0.0 cee9ade29a61d7669cc2710549611c53 0.0 ceedb016e7628567e25ad61c46a8be83 0.0 ceefb8fade04925c7bbfad924171a220 0.0 cf54928a038081788aa5939c49ae5340 0.0 cf8eb2fb3d885d1919ba916bc0975347 0.0 d0309ad131312d425619892c703b13ad 0.0 d05c86b5bfc092d8677507fb1eae8d66 0.0 d061a99148d649c4eca4836c5f4b5b68 0.0 d0c34b21c7c96271a1bc5f7fe82df3a0 0.0 d0f02fb55f33f41f45d8b5a6a6a5b018 0.0 d103541d4efc81020afaef43c0f02c02 0.0 d117a20b7daabc35e9d810f3a93d18b5 0.0 d1539f8c2855fe568d1313f20d26710d 0.0 d208cad7c585049e04076ac7df960e7f 0.0 d213f55b066d42f6c6fea9f1d27582c5 0.0 d2589a845c837dbf413021f74e82ce0f 0.0 d28170caeb000a27998d838a8e7d5de8 0.0 d284b92d7518959fe5d52aa45b687394 0.0 d28f5cab517f832750bbf62798e58dc3 0.0 d2aa3a30c8e178110125b88dfc7e6f45 0.0 8a9f7499cdb85b8efa497bb56256cb43 0.0 7ebc04cb539befd9f2e7faa131628c66 0.0 8a83cfd5eb074b5dbc6118eb03ef915e 0.0 33950a5fa4d8ee86e10778182fae6714 0.0 2ea79eaaa0b23b2a7d2cf470cbaf72ea 0.0 2eb7bab7b0af702e4f18358968a8f7ff 0.0 2f3b51e3f7acc3c9f66f1552b67a0209 0.0 2f75b02cd4d3ddebf390d17a120f419a 0.0 2f9d067d5ea9cc1b1289e9de830b326e 0.0 2fad39e365933a7f925040cb3c2a5ef8 0.0 3017f87a3b0f5200ed54eca17eef3cbb 0.0 30207d209491dfb7de83344e77fd6fbd 0.0 306d425d43fecaddb4ea5af1cc34ef98 0.0 3098ee4e595175076514b00a8a20c291 0.0 3127220258419507743dc5f2bba69d86 0.0 31ebb433ebf0b3e83259d826875b4438 0.0 31f493208054aa0fea8a26d72ee670dd 0.0 31fe7997ddfef193110db377890f9520 0.0 320c03afc417b829a51ecad3dea2e065 0.0 320fd62cdcfb66cfcc1438371751c4af 0.0 3233034b11dfc584717d9264882a4fce 0.0 32382a0f5831da5faee464d011b5616c 0.0 3255b196d8b70893d9124239bcd46782 0.0 32a21601ca89d1f2629c1a9fc2de4359 0.0 32afbeb5f76a69e47f6cf6a1870e95d6 0.0 32d9ab84e859d48f487b790c58e98234 0.0 32ebb69544acaf3162b5e828d05a5f84 0.0 330b6fa220b88e87ac7c5ed39ec276dc 0.0 33206a2306ca96922fed904661eff421 0.0 334af877a390268de17839f80e212fd0 0.0 33852dc244bb69590e8e756a83bb2f4c 0.0 2d5957484a1289ca13b12328802dfaec 0.0 2d273dee370721d368ed3534c76100ce 0.0 2cf53730a41137e7ad95ed3680541d80 0.0 2732bd972ea75eaae442f937cb39253e 0.0 228592b44e6a4d192af2d0732ec64a51 0.0 2290e92733707772a839abf72e7981f9 0.0 239b4f4f6c5fc459a1c95c4bf704de3c 0.0 23bf5f7fe3d1ff8167bf3901fdb0685a 0.0 23c05ffd2b0ba1534717ee52a81b589e 0.0 23dece0aa961e717a81e1118455253d1 0.0 23f4c333bc50c5cf2c0f20855d049cc4 0.0 2403a466dd6d1e4f551d80394c2aa994 0.0 24ef07664cfa04a819d7797a89e653b6 0.0 251429848560a80abcb96640ceb102db 0.0 252d0fd6601d9776290e142e5bfd744b 0.0 2594fcf48955bec7b61a5ce4aefa3868 0.0 29568b810d7a4e985424b9037aaeab9e 0.0 2cdea72aa7fe332d3e0a891d49d22c1e 0.0 29784e17460e4faa8e4eb6576e85f22d 0.0 29ccf8b234ac00b114fb2c8e1c44f932 0.0 29e53aaab03b86749d3941da8ea5b59c 0.0 2a8a90cd5770804a5f23f425004de7e5 0.0 2a99ec1157a90661db7ff643b82f1914 0.0 2aa7a8ef7c70b5f684c856e6c21b6635 0.0 2b982979f2401a8bc447d7141879e9b2 0.0 2be34a58b64107daf7b5426302feeff7 0.0 2c0fa4f09b72e538e3c6acead5b987cb 0.0 2c1dcc76478dfbb19fa59690738202c6 0.0 2c61ba77eb8ea89ea85728bd0022ac09 0.0 2cca9e3bd17f06418ac623fb0017c4cc 0.0 33902c26956acf7efa69413cfea6326e 0.0 33b58b0709e9c05ba8404c47e6a7ea2e 0.0 4346c337f6760bd0f8e574277524165e 0.0 340a5698fe78713b785c3bcce89df73b 0.0 3d6469bbfb14a86abdaa602a89753ec9 0.0 3d766867c97f511431bf97e059d6498f 0.0 3dca01142e22e42b989fe5a513e103c7 0.0 3df77157a242066dfb4eb9c19062436a 0.0 3e2716bec0426995af52846a88864c6c 0.0 3e9c062471302ac0ef352264490d1b3f 0.0 3ee56b6c4d038d4b8d26f63fc337cd02 0.0 3f11f9f226ab63cc1ff6bfeee9699b79 0.0 3f2fd56fd1ec26b86eed89795fe014cc 0.0 3f54618710e03bf1e78b57e14ca8775f 0.0 3f55a8ca784ae7190790023a30cd859c 0.0 3f56d7b61bdc82e4d12c6f58617f5103 0.0 3f6c45001fd40e8b6f9d0558539fd820 0.0 3fe55dd5e59267f275e972017302459f 0.0 4060be28072a120ebefbef199c09187f 0.0 40787e473f59ede4ad561b4e4079d97b 0.0 40a6b537d995aeb12b0100e2cb6ad879 0.0 41239266f2952a56a313fc4798f28a1c 0.0 419242e308e14800b26a10a4bf82831f 0.0 41b518f17927240fdfd1465cd351afc4 0.0 41df3b4c55182503ecd97c6dbe47966a 0.0 4261b78dbd18dd66cbbc7a7f0f2a51a8 0.0 426bd7119a31b73ef734771a071a216c 0.0 42ac6d34b293d442987af367e2eb4f51 0.0 42ce63585eaa407ee53b568bdc648be8 0.0 42ef609ea1f85d92d08a416be896e309 0.0 431c53fa5c895a6e6f5951578f6dca8b 0.0 3d52122a218f9c70126d51d42996a1a7 0.0 3cc657dfb41c68faa70508afc63f4222 0.0 3cc53c481fdae6358e4d2d5c9f95a1f0 0.0 38e3b7abf4e08699d7a1d1965f177086 0.0 34cddd9fe152c24d78924ef25927d67c 0.0 35513c8de34a49ef37dde85737e6aef9 0.0 362b97b08074732371b6e76cd1a894e1 0.0 363c1c39d58bce4fc3218659d0944258 0.0 36402f6154239da8ce422da64a0bd247 0.0 36be43c248f8e4a7b60a4739cd8dd932 0.0 3781803fe3eeb8e5bc50a5308f4516a6 0.0 3788b1d514737976689f4ed1dee8b52f 0.0 37bdb470cfb64ad4594c5968cd95e312 0.0 37ff76f02e76dd8fc629cb05575defb1 0.0 387e36ab394fd347fd94d8762016779f 0.0 38c80ed971960fd1e878080f767a4765 0.0 3902e1865aa0a0863687793a7891f8f7 0.0 3cb3514dd7db8d7720477ab5759b970e 0.0 3950fe55c9d109b986e327da3ab3653f 0.0 399bcf0feb12a20ca0731d8d65268dae 0.0 39bb3fb5b2257fd2eacca408dc42c5d1 0.0 3a0e00761e8113458ccd7d13af71b4b0 0.0 3a1461e8439091ad6b93af0ddb3849eb 0.0 3a3e562a61e57ea1ff4f24857a1e79da 0.0 3a8731148bda5325db164e3729754abd 0.0 3ad7da49c52ec79eb228067d25d2f2a7 0.0 3af2ddaf4af4b5ae4100439a9c3d4099 0.0 3bfae16068c7a0b87db6a711c01eadc7 0.0 3bff9ab82e7f2a76cc22e687ac7b72fd 0.0 3c5496fdcfbdd5b2e4f620d44f83414c 0.0 226d7503ab3d1ea0ae84d97fbd804323 0.0 22026223740aa4b6376f724986d7bf12 0.0 21d92a1e71eeadaeec2fd51f41249446 0.0 21ce8465657612a85e2f89e74d285ce1 0.0 091e6e4ffe1252fd657f19e42e04e859 0.0 0a5225695ff3a449ad8ce395d75c3799 0.0 0a99bccbf1bd2e4f728514ba8c4cf6b5 0.0 0ae0be308568d07e0434434b14b8d565 0.0 0b05a2e48cdc5f9e766bb0f4c209d4b4 0.0 0b3c20a64187d28e11a68f342081c17c 0.0 0c336b876b379dc729ffcc2a1340f670 0.0 0c3a02ffb054a07b355c1649433fc699 0.0 0c3f267cef317f7d71015849370f1f6d 0.0 0c4204a0e15fccc22a7456685898cd5c 0.0 0cc26190e976fc496119a5eb4cd0fee7 0.0 0cdc26df2e337ea78808c32c8f52c94b 0.0 0cf86462b45382da531327e4186091da 0.0 0d188e3528ce4d674680de129470f7bc 0.0 0d3b942348cade7e1c41ac52df03e63e 0.0 0d69754929eb3dd1a5b256b43f1c05d7 0.0 0e637c81e25ffbf7b7e68a8fbcc4f2ea 0.0 0e7be154d128e3ce2b9b05e3e64a679e 0.0 0eb15dc6ca644533da15764998436274 0.0 0f0a1f8c92368be6e8d3145bd4e94cd1 0.0 0f0c741eeebdb89289460115e9430f1a 0.0 0f42bfd00e871207c3e2bc92a79f3456 0.0 0f6200a5b77099113b52eea9a8645181 0.0 0f8aa0e4c4ccd80c090db7c72be4d264 0.0 0f92fcc184a951ff8b0914467ad2f8f9 0.0 0f9411ed14b5b3aa1a9655523fa33004 0.0 0fcd8cec2c4190fb7703e87f3c04a0a9 0.0 08be83d0a527ddd1da0861135192e593 0.0 08a62d972f6bf2ca4dd9291bc2cc9f63 0.0 08a1598eb1ea4dca23db1135552cd5a7 0.0 052ad6076dacb9cca0dbb762a466404c 0.0 009a4919860d6d1fddec5d3771d37351 0.0 00bb7a84ce1fa6f7411597672ff1b09d 0.0 00ecdfa98a302087bca221884a535f55 0.0 01241d7b0a1f219f5a68bf78b9f3b294 0.0 0209f9868a22059c659df474a746d8f4 0.0 021899b8a2f4157d54475a024303ad5c 0.0 0233fed56365db96e625e92c4dfb9cd0 0.0 026598f1d03fa900cc03cf9a32dc17d8 0.0 03569e3fd843f501355f7853b0ec9361 0.0 03fdbec0c9b63a05ae79f92c6d3a4cfc 0.0 041d6dba3af0b8c9c1a422ed942ee16c 0.0 04cf55ca51883bf19bca35e8ab225def 0.0 053c4d5b8717b60387f777efae437b40 0.0 0820b82d14921828dfa20b56242a48c3 0.0 0540bf08e9a1eb8691a9b1be2afe577a 0.0 0550a92d2e1e15136084e85881efbdea 0.0 05736395b184324b94bf557984b36834 0.0 0584be58049c7828c032b2171aa00a4b 0.0 0590c29091ff2b3affd966ed57773407 0.0 05992d2befeb4bd87b626698a9694ccc 0.0 0615dc8ff9d74b14531dde03da40bc47 0.0 06c0aa8ad0fa418a4236c6914fb420e1 0.0 07465ac96a07454a7c155d9c674bbd5c 0.0 075eb451ed18cc7fa554e88c2726e7ed 0.0 075f8821bc5c57034fb74afc07233d97 0.0 08091b93dffe421f648aac3eb7e192c5 0.0 10155b2834300619ce0102110a37b057 0.0 10a9a0887483597b71cffa08dcda40de 0.0 10cd502b01abafc87e2ecbad86389286 0.0 1cba52a9db0c46eaa9148953a6983f1d 0.0 1a0bea5ccf9d532d75136168ddb54654 0.0 1a5526b9f7147b6893f1a034a107cc65 0.0 1a962bffebb20d79245326ada6fa9b4a 0.0 1aaeb592fcca5013db99a4f629c55062 0.0 1bb5836797e9a89a2de9b96bbe206524 0.0 1bf05d12bfd387888facafd52c07a37b 0.0 1c4344ff805fe2e4a760b5d01eb57eca 0.0 1c85fe6e01899c1b9575734197172ab7 0.0 1c86153e1b13ab5322c96f2602b73513 0.0 1c94105978b1aa2095e3c0096774f240 0.0 1c9f7427ad9eef9581c32e490d0f3e35 0.0 1caec778d70d2d387717d1d1bc248bb6 0.0 1d1d606cff1c8bab0027fdd1e2ede36d 0.0 192522c9b7c41f7a761f8a2ba792268a 0.0 1ec95834f03c9606f9433e59443e5bf3 0.0 1ef782a559e3e0a4ab42516e0a2c828f 0.0 1ef9d7dc5f8c93a8a43bd84e55f9a08e 0.0 1f4c8ba04bcab2849c9ddfbd7fa3d1ea 0.0 1f982b62b3d278f92eb3007e366fbe14 0.0 1fa555f9a74d47a6ca7a65a347bc885f 0.0 1fc9389433a5ed33af26e3985bdcda26 0.0 200f25968eccba0fac01ab0385952acb 0.0 2086666afdd5de098b04a94247040c11 0.0 218a6324d16b842a38c70f1088a7c8b0 0.0 219d2ac2e47968bb839bfa948559ebcd 0.0 219fca301444ebadab34c1a35847fca8 0.0 19cb3add28813b2bf3e1f40a000d33c2 0.0 185e45802a5c7674f89b5d0dd66d7912 0.0 113ce005a880987438bdbe19ee22add8 0.0 149e7d5e484d157f2ac6140a2111618e 0.0 1141f30eddb626a3a1151a19445eadfe 0.0 1142fa8636688cdac86a8bdcbc8bee05 0.0 114a94e972186d56504069f1bacf505a 0.0 11764b0405507198175fe590debb40b4 0.0 1182d94e2fd82a9b44657970e252736d 0.0 11b21c7f71591dd1570f9717990ea4c7 0.0 1264ac914d010d7c663fadca9c5904f4 0.0 131d3b899e72f19fcae1b0f9f8f3a009 0.0 138daeaeee1211d2a3d8502b8fe23b2a 0.0 1407e963207002430eaebcae4b500708 0.0 1442af5b43d77ad0cd6b73feea01af87 0.0 145ebc1f8ab3b2896eb631008973c0b4 0.0 14ea2e862193001ceb4322087eca9f4d 0.0 180b74e94caf35fac5e1f0f4b7ad9d9f 0.0 1516918080ce0a63f2e1ac6251ba1282 0.0 1527fd8b14037f53b8edb26b111e1f72 0.0 157a9e8a83fb37615cabb48c14d919f5 0.0 15dd83460074717cb57171578115cb49 0.0 161d27a7363501e838efa59628353a65 0.0 16306acecd104a4f12ec62522e1bf751 0.0 1634bc38311d3c868d1077602dc439f2 0.0 1661c49d1dc41645c0bf242b2064f1f3 0.0 16c36bcee25e65305630899e962804ca 0.0 17824e221f06eecf126ea102c3a2c289 0.0 17c24a9e01ee9569cd8f4a4b0e9b1b33 0.0 17dd8d3d133442253a1d51601ca5a192 0.0 433d8ad01fdf6ed57d8f509a7d6bfe2a 0.0 4355c3f086c69fffe013ed0a3fdc8b66 0.0 8a658263f5f46e9b06ce187893565b47 0.0 7a8d29c59b803baaed9cc1f04ce0dc33 0.0 7029eddc845e01d613a3bbc113ebeaba 0.0 704d0070549f26fe1f99eb736cdc4c34 0.0 704e8a1acf77dcc1bc06251a34ba2132 0.0 7069d1ba735fd4d5199050b4c100bea7 0.0 71a713c5aa69a8e46efa23a2437010b8 0.0 71d32936afbf6c7745a6083e7b09dff3 0.0 7201d53bd647437ec3de879774eba498 0.0 7212fe837f6f09bd16ed2c9b2c58e557 0.0 740c97e7b2eddae8044cf27859a86b7b 0.0 7412af58f3daee6101db082fd334144b 0.0 744b8cd51857478bda77a9f3ab5e1d5a 0.0 74b7dc5aa537fcaf4d0046dc7715b9bf 0.0 74f2fa20e0ed1f74fbe4857f249e3a28 0.0 758cd34d30d7af60445b5f0f932d21b9 0.0 75a5999048000b7e178036f0e75e4dd4 0.0 75c5f35120584c258c8ffa734a94ea8b 0.0 76075eede2e2c9cf276a8394c7cca293 0.0 764ce1e6cf32606d676870bd6ab3e21d 0.0 76cee9663ccd2b6160d3dfcc88df3c38 0.0 76f7f30b434c8deb5e2a0fd50baa1496 0.0 7769cac4c6bfbe7e3cddd33636c22519 0.0 77c18841a3a2296268d30a71c26a5cec 0.0 78266846787de98cf89a724cb5586858 0.0 7839f352a2bbf8261351db78a9bf3bd8 0.0 78d8e6cbe439685d63e01561094d1736 0.0 797ebe05936131bb058c0ab04c171a26 0.0 7a1144e3e5689e67eb04e1a00e49c45c 0.0 6fa149c798c4251f1ca8cd356f0568ee 0.0 6ed7152332889b69d2d2f33c53b68934 0.0 6eae8918e5425723c03d19afa8ca0356 0.0 6a129e8ae637c96e7bb56223913911f7 0.0 686d42b9552375c3b61301ae5605e3a2 0.0 68bb0065fa02ba7b52acf3f4d833895b 0.0 68db566a60ba7167b024b4c5032d9400 0.0 690754306aeed53ec9ffe767151681cb 0.0 691656f33e727f8857f5c9ee40ed05b1 0.0 69536042153447ceb692aa53159ce0c2 0.0 6961c6244fb505547380d15bfee162a9 0.0 697b3fb29268cba4b2a9eef0eab2de7e 0.0 698862fbff78c7fc3cd7a9f4958bdadb 0.0 699d4b4de178e2d52195830debfc3b1f 0.0 69d052e452e79d571cba042af265d50c 0.0 69f46a090420a7f596df5d450ef67e66 0.0 6a17479edbe461431433bddb084f731e 0.0 6e8986f8088b452f964e7968bb8bca87 0.0 6a5f9d9d0fbc066a57bb7798f9f371ff 0.0 6a6880faba39965be0e4b7d88966d1c9 0.0 6a6d8054e2a7052fb8fd458dccb2f88b 0.0 6a75fd73efa64af9c36a4435bae0f920 0.0 6a83401c3ea3089bf7d3c3051a709ef9 0.0 6b90b86f5da836f13c0ee2f67132e12a 0.0 6bbaf2d026d54c61f24b5c5483e56842 0.0 6c1f3bf3e2186d0faf5325be92f4c974 0.0 6c4de756c45fa6e7e5adfe196f9f0039 0.0 6c84b0ea6103c2ad5f4c3b7f5dd5e1d2 0.0 6d0013cae9b331ee166821cb124dbca1 0.0 6d34445f3adb296a5642fcb5f81e5219 0.0 7a629c748d0205443ef1e8e26ee09543 0.0 7a9469ff27dc7afffdb7238976da0a6e 0.0 438eb58eedcd45e1eedb5889431ebe2a 0.0 7ae7a28e3e35f8669d62a551beedaf7b 0.0 8183f1e3f9806994e125b1d5c6932498 0.0 81a1e88c8e85192aecbcb517cb0bf1ba 0.0 81f1b22052c8eb3dfb1e6b45ab7c8530 0.0 82168325f126cecd669b2d0e030c9eae 0.0 825e1e1d675a615bb3e6914499939c93 0.0 830932289444e28d4ab0ac9cdabfe977 0.0 832e6210c0410af8e0356bea5ec39c80 0.0 832fd777a62ea50c5c34a8c2efb5c5e2 0.0 83420377ed17df2c16abaf3a72e05633 0.0 846b433f433cbb20d6208bd54067f911 0.0 84853bd31e74a04290e47c542c8d293d 0.0 84d6422c401698d91e646b9b4fe4774e 0.0 8507091bac6b1be88f3d360d6d535d0e 0.0 855e8b78c6f45f9a2e3d5afb75c4f5bb 0.0 85d8ef495cd58b08a300a623a3718ba9 0.0 862f918acd63eeace039314ff2263a39 0.0 86f04c5c81713db61f97bb53835f9189 0.0 8731860c790449910b7955d1bde836f2 0.0 87bb02a4196dc0430e4ad2a975a345c8 0.0 8833ed97ab90d2af80eb7c7f7921f139 0.0 88c180a637696e987712b40ac9089f8c 0.0 890bfce6cfa2575db09fc1ba0909d3bd 0.0 8919944cb4b67e5abb04cc8afad9045d 0.0 894f46d021396ebbbc4041b65e198bd4 0.0 8951cc9103140b71bd50c0932e096502 0.0 89aabf43d24dd5bd0fd0f5aca189d341 0.0 8a20667bca2eaf2a0687995af876a84c 0.0 8139d4cc5e4e5d44bad494a295a3e7d6 0.0 812aac97abf11d6d64a00496e070e266 0.0 80fd14aea177425eb5d6a4b388a08a07 0.0 7df3c653a9ad469d0de18261ee771eac 0.0 7b2ff5940de11da4dc3bb208805dff11 0.0 7b6f8858b481821ad1aae2e8d796fae6 0.0 7b9a7ec76bd5dd38a2964e80934bc632 0.0 7bb3a2f7b1bab185035b2e361b4fa760 0.0 7be9bac1b13acbd8acf0de464d7c20e6 0.0 7bfa7582156c882bb0c1de44aaaf7a3c 0.0 7c99906fc47555e0b2df4cb90c47a3c9 0.0 7cb7753109015ae718a1a0201d081e99 0.0 7cc8273fa6f3c9f55f426c3765741834 0.0 7d2f0f34f2ea4ce7030a589e76c0d06a 0.0 7d4bc1c15b975e6ffe247f13716e5f53 0.0 7db357a4adb452de8504d8ca1ddb3f99 0.0 7dfa96abfa7484bb6c9cfa90dc9b606f 0.0 8042eb376d870b471cadeab735dee5a5 0.0 7e17a5137fd9dab8c02617a186088c4d 0.0 7e3f4a0767fe59521a6db1862056798d 0.0 7e54570d21f03dfcefff07151a8c2d54 0.0 7e57bf1306ddc4beb5aa7a1084d8c845 0.0 7e86e84e054d9c5a6d485c9ef762c5c2 0.0 7e907df30e0739c3bf57f18729659005 0.0 7e9ed2c841e64976eace4b578ff56a26 0.0 7ead39abbaa90f90242247c455393162 0.0 7eb58843a058a3dcc0c051e0762de977 0.0 0064e2a432a2756eabdb6288a368eaef 0.0 7f323d6db23992932ec6e097ae09c4c4 0.0 7fa68c46b87cb8fc334456fc14dfdf23 0.0 67ec5c8d397bcd64b2e336a60eef437c 0.0 67cd78854a06d6e3867c28745e509ad9 0.0 6700772469767941a3992c3e2c65c3bb 0.0 6694ca246e895a4f1d7e1d077cc27f5d 0.0 4eb0fadd9ccb6cd253273f89be164175 0.0 4eb2c50a69efefc9d10540928ce08822 0.0 4f5e90e831377b98f5f6e569d6d8f64f 0.0 4f6f2afb7adf1bb487b6a86b13022445 0.0 4fd1b92e9814b1bc6d1f7b1117daf660 0.0 4fdbeac7d6cea1fef876d607636f189b 0.0 4feb634e0ed63566c64710659b17a2ad 0.0 4fed36b0643aa2ddcecf381c1f487a85 0.0 50f328ff0b5c3003ce220fbd7aaa2ef7 0.0 50f8db74e965cdba7ae86014644a3137 0.0 516549c565407769125e3e8f3ca298cd 0.0 517eed6e97dd2846dae1553b8c7c9464 0.0 51a63d18809e04591820c7e3f3acf0b4 0.0 51c999131379511e8950fed0550134f7 0.0 51e4182fc25b356d52164f3de0d5d4b6 0.0 51e77f4577d36c8bd3627a3d0229dd37 0.0 5226eb5e70712d3425df4b0e57d5a406 0.0 5350db19ba80799a8c5ee886143dd940 0.0 536018032c5d0d65e6d25d3988f87421 0.0 53609d8db4e52b4f03beab3bc44ad5ba 0.0 53668ab088d92c4856914e433447af5a 0.0 539c656b9710b0099a96a678b3023299 0.0 53a3eb7f49d8d6857ba7c50dd5bda866 0.0 53f6fd6e785c7fb9d72f94a6ea343a15 0.0 5406f4862e6c5e04e925b8f0a501958d 0.0 5494f5c56e0875a35b62e234cc67ffa1 0.0 552e00cb506f739acaf08aa5641f9d84 0.0 4e3406627aa545813116167826c24a46 0.0 4db47b583b03cc6706e28a2fe2731080 0.0 4d7f3a8e908cb29809ed118acf40d513 0.0 47c98abffb77eb5999855b75594356cb 0.0 444d635c03299c7b88a3a0c236831bad 0.0 44620cd517e481b3b2b27ff6d6611d53 0.0 446ec4331e4894b14be920825fc962a5 0.0 44a36b6738e227582e14a58b9d92a5f5 0.0 454aceb66125863a02ea9d46c0b23136 0.0 457d3865cf0a4bc602a07d8d5324388f 0.0 467201ebcbdb17a73c8dbe98f8bbdafc 0.0 467fa58ad637f123633ecf3cd389ed36 0.0 4687677f9674fec6aca4275f36063b4d 0.0 470aabeb5aab36d5ddc9d1995b087843 0.0 4786895e195caa90723aa4bcb25b8b03 0.0 4790a2be4d1288d94177213af8380f12 0.0 47d0d6c4ca012181585fabd306fe7026 0.0 4cc94d6f0ba7a2a174fa668ef5966bae 0.0 49a130e2f6d8bdeddd170945a75a6783 0.0 49dd84930ff914f17216bbbef0c6ef0f 0.0 4a86baaa7e5adb00842830155d3c7fd0 0.0 4ab7cc7f5969573696f5cc3b1ea0f4bc 0.0 4acc36d268585bc3834e627756313b21 0.0 4b3f3f0ecac9b4026751b7549559c9c3 0.0 4bec204a5986223b16143ad5db1c8433 0.0 4c1afcf47b47fc2850fae19210e27117 0.0 4c2189b6b5ced3cb80093414e9449de9 0.0 4c855814a58f4f324e8f0cfaab222e1f 0.0 4c954887a7bd1f32382dbbade7b91aaa 0.0 4ca53113aeac7afa697e8cae58f69855 0.0 55993950ca597b6dc821765327bbf3b9 0.0 55af0326535a408ef56415f2952e2896 0.0 55d4d3011e1f3bb8e4e5089b801b61a4 0.0 628a44c637e99429e3ac4c39227c6c9d 0.0 5f1d2db99a41906b5ca2800149e0c385 0.0 5f8c4f83215d666e801e21278b17fb45 0.0 5ff2bac04b0e8ba06ff7e0293588c308 0.0 5ff715b26c5f3632a12da2d4dbd758bd 0.0 6007bf22076e2e3d0030e38442149c54 0.0 602510f333bda9666e551383f7ebaf82 0.0 60746d8928422234eb34fff42f4cca47 0.0 60c57911662a9159dfdd0fc05d975a55 0.0 60ce43bfcf795e997e3c969938262dab 0.0 60e681703dcab859a8e336be27fd6cf0 0.0 61602441fe4b6f2b36be40c311fa9cb3 0.0 6240207fd3edd24bf0799b5f427423a0 0.0 62ada1b9706d5e11072e7d78ecb0a4bb 0.0 5e99c84d99dca9630c51c5fb88000143 0.0 62f043c2aed6f033879b83ca519fde32 0.0 630bffb8b9a197b3a6359f42828b4de3 0.0 639a2c1d7ae3f6700506aba8baeec034 0.0 640f0d7bcadfc07ac9f3a4d0b440d859 0.0 64618afa3a07dcab19ba87629333ab84 0.0 6474f5ab8c91efe951ad41f60fb4218b 0.0 64b3028e870c12fc7d39287219f7af67 0.0 64dc86ad2807b50d91f4938a5bb31a87 0.0 651794369aeb3db83839b81fe49c8b4e 0.0 66127b1730c816b3e022c01fcaf024ea 0.0 6677fe5ca3b81ce606eac5d76b0a0ece 0.0 6689cc067754fa14964e70c77ae9ce0a 0.0 5eb9520307f1836913cc5937f1c9f64d 0.0 5e32dea22765b73ed60b1d78a9d4d574 0.0 56c3d1a8e4dc5c2aa7afbc1563559448 0.0 59d031b8ba709e8da78b4c1f63c74f09 0.0 576c2135e8ddf9d0a3674a5937d2466d 0.0 580e8927be639c5ab7fa8731a72c76d2 0.0 5844d8e76e12fb8526d7fede1c425670 0.0 58464ec27209abed9698e88ab974e84f 0.0 585f01cd625ddb45fa4eebbc072fecd1 0.0 5860dac317300b1fe6094e958240cc7f 0.0 58df89090206b56c52bfffa4b97f4d5d 0.0 59597cd430deea6d8e0908dcd6db7e50 0.0 597966c93921ecc2907ad15121cbcd2c 0.0 599ba6458e91e2527f358f547ea39261 0.0 59c4a678634e50b3fda861310820aadd 0.0 59c6ed04d2faf081cecca31f1eb2e42d 0.0 5a21785c07d7cc123256f09d00deec29 0.0 5e151aa3f416a2fa6f0a1d8985282783 0.0 5aa1c4b839946b713b450ff38e7d5bf8 0.0 5ae365ca527c17c22171f54421e75197 0.0 5b31527f1b28c37035a08b3642d61ece 0.0 5ba339813ae7235641d2f1ff581ff2d7 0.0 5bfef4e7e21aee58609421e4f24b5dc8 0.0 5c3e4422374120cd00d41557946e5c6f 0.0 5c6ba6ec99b516d0d9cba8e4730ea1fe 0.0 5c78e7010bae7392c680c7ee9a1ed076 0.0 5ca5ea401c8d3569e69626d2f81d5578 0.0 5cad0c3ca2db85210a2d320bbe783fbd 0.0 5d141d74c8bd046171ec64835c4864b2 0.0 5d20f93c621d95608e5b8473d56d5b52 0.0 ffaecab289059c048c7494d4595a746c 0.0 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/importance_cv.tsv000066400000000000000000001166311462552620600274400ustar00rootroot00000000000000feature importance 74ec9fe6ffab4ecff6d5def74298a825 0.3428133408142244 c82032c40c98975f71892e4be561c87a 0.27634103114598535 2ae8a432208b85a14e86eb821c86ce2b 0.08828221994710637 4d04d759f5a6615dac43060726239891 0.06823380209336659 bae0d49b5eb22b0dfaecbcbf39a52265 0.0369473194038547 eea6b86c0c75e740670ccc50613b1b23 0.020006535264682004 ea3433f2c148c6fae4cc2e9ae197f5b8 0.016953147830527746 5d62137a2d05df0be8d6b7e163a3ef08 0.013211350936413749 1ad289cd8f44e109fd95de0382c5b252 0.012560366391362142 539ca948741b9a713eb781d4281b23fc 0.011156791684704343 e3a4a62adc4e83c274978806164b474a 0.010308983991542713 588a23811b3e98af68f4f0fb24a0daa8 0.010069329482887605 a650f349bbdffb95b3624519d1ba72b8 0.009871225092780213 04195686f2b70585790ec75320de0d6f 0.00876402102831411 9d4e16844252e2dfbaf80a4a6fc4d55d 0.00630257923568541 3b092a59cd0e2d57483420cc994ec49c 0.005622043494081645 2c1dcc76478dfbb19fa59690738202c6 0.004675382639932856 ece1af985b63ebccd2833e9b5f0432e3 0.004513544151860472 e6a34eb113dba66df0b8bbec907a8f5d 0.004315160855326535 fea3411c847e6627afb5e78b88e2e9af 0.003730624243958615 f1da0f084f3e5b7957d11d01abe7013d 0.003652015129777001 c18afe570abfe82d2f746ecc6e291bab 0.0033049296043843033 8ce931b0c99ad5ed648c25483c1ca492 0.0032228897025259203 74923f4bbde849e27fc4eda25d757e2a 0.003150217256362466 8e6e925baa81466352ff781a289e188d 0.0026718177108241716 3128e057b1d4f320961e4da677724613 0.002664604196836876 a66dd8d31584930c2b0f811f572dddcf 0.0026417565965941056 7667b07b46f3d78c76f13781337cd218 0.0026087247436465213 ee02d6d3506da57909d5e603709a295f 0.0022537226110718044 25def15fb42bed6855ede4893d27a21d 0.0018996856274791142 be17b29b03ed02bed133932284568d16 0.001627510760401745 77ad88eed91eef009bf64f101c96baa6 0.0015835888689348587 d73c014c9a033812619aa44e9cae934f 0.0014153770414606557 d0f1985c2b919dcbd0bf4664c844a900 0.0012848091782786443 370829fece3190f1a8efccf50b7d0921 0.001263760407966557 8f4a3341ccda8d1b45f286cb686a3aec 0.0010168579626972755 bca0b81a0b8d59e90c25a323c2f62f31 0.0007409732185557153 0f92fcc184a951ff8b0914467ad2f8f9 0.0007082879970565094 d996e8d86e152c0a3c5852a2d8c4c52c 0.0006555148868768255 c162a4f3943238810eba8a25f0563cca 0.0005993278965731458 ad7bc2bb6e1ec90a9bc3c8949bce80d6 0.0005790178805975375 8937656c16c20701c107e715bad86732 0.0004707675753228123 2a99ec1157a90661db7ff643b82f1914 0.00045698752113701083 ac5402de1ddf427ab8d2b0a8a0a44f19 0.00041009086561453946 07bfddb8e62098a85afc8fd68ebc308c 0.0004035832014127108 ea3af29626a95b6c7b89d631bf1a739c 0.000367769391078963 9ac5fec396208e598ab2e2d26985d0df 0.00036166905786704954 0f0a1f8c92368be6e8d3145bd4e94cd1 0.0003347680535628769 dafe809740d0545dc25c6939a84a1820 0.00030100173376998625 d9b76ee51ff2b6961430bf352cc578f2 0.0002364961500966159 ed1528f4822674c9e1da64b84c778e9f 0.00020923003347680163 e7e74960c5ee1984f2e60f99081a368b 0.0001972740315638449 0d357d84911ef4a089c6ae3c6deb39b9 0.00019167798083865142 6a5f9d9d0fbc066a57bb7798f9f371ff 0.00018830703012912491 2d273dee370721d368ed3534c76100ce 0.00017979836897195073 6c83fec6e8d03fad51eabc871853c991 0.000167384026781444 691656f33e727f8857f5c9ee40ed05b1 0.000149831974143296 3127220258419507743dc5f2bba69d86 0.00014983197414327685 3e93fd55a231bb99b67a666bad8446a8 0.0001412302725968437 180b74e94caf35fac5e1f0f4b7ad9d9f 0.00012553802008608329 4e1758e81adcb1107024ee52c0113a6f 0.00011566499047711704 ebab7cfc7858bfb00c486bba21d6ca6d 0.00010760401721664332 c1b636001e0773f9cca8096d70e8b5de 0.00010535060681949527 1986030e3c5cd5df6d869054bc96e536 8.428048545559623e-05 48d9883fd871b82d9bbc89cb0447be8c 8.026712900532825e-05 df3f8cdac76c62baa98469c33b82d8df 5.380200860832166e-05 29bb5fa7f45e47bbabab8cc1b1b3d18e 4.184600669535961e-05 68c83aae1babce28612ba404b1096cc1 3.745799353582101e-05 d28f5cab517f832750bbf62798e58dc3 3.745799353582054e-05 a4dbf71f32a016e120fe6cf253dfa6c0 3.745799353582041e-05 9a75764782a384ce3b83e019c8b2dd94 3.138450502152082e-05 aa738f71de2d14bf826740d8df65e5f2 0.0 ab0b78445a54df766c12448fa0ad6d49 0.0 aacaf5f360c110204da1051a50c5ba5f 0.0 a957f3e1f57e99be7c1c28de7f016780 0.0 bc4ae61d84daab04b0e888d22f7d3f69 0.0 a8aca6d9fcb6ac34f6104cbe28a466c7 0.0 a9387e76477da8688775569cf540191b 0.0 a9e1acfa6cc2678b1fcc40f49007d4c5 0.0 a9b72251b244f66d8296965d9435218c 0.0 a9566f812a634f1b709810bb0cf50629 0.0 a9e6fc1854a3fd8873b32c9fbd9ac13a 0.0 b835514e2678e3c7ba13bfe0a0d79bb4 0.0 a898fafd80c4c90cdcde401ca2332e05 0.0 a590ab40dc8a6b5cbffa347e8e32e63d 0.0 a42ad1956d801cce5e0109dc0e987ceb 0.0 be9eb15986b4bdfad6c474a30e7ce4b9 0.0 a4c61d535793417f6f6ab9eae2463f12 0.0 be480a1e4a4e71fe774ccd3e4ff22945 0.0 a4e2a4e1321a599651edf92f6999e78e 0.0 bdb2c60864ae18c4302c9f144219512e 0.0 a4ecfb2e708863a17978a0942358ffc3 0.0 a51b62113b7c9d4febf6956e86e5dfd0 0.0 a544abd909afc727c4418e4e19eed417 0.0 a5676561cb37d21b8c485040ca3ebe96 0.0 a607665fc01df970cb3f1c4002a00bab 0.0 a837426344372de1e6d07876dd214a5b 0.0 bda6b6e7da7508c68057140e7bd6cd8d 0.0 a6099802840e60febef8e896967b7747 0.0 bd8cf9d4f4744a93802336d81b60966e 0.0 a66a33da056496a076f57ec22a435dc9 0.0 bd0f4e14387ee1ac7e5fe586cadbbed4 0.0 a6bd74dcea0ad6299a4cd2937e192151 0.0 a6fa2de5f4576d1d77b1616786e3dd52 0.0 a765441df9f96c9e8a1baf9645528616 0.0 a7e74b8756d98ed147f70628144245cc 0.0 a7fad69a900f747d777bf13f8c1ffd83 0.0 a75b0438ad19fb4e31f4d58c2d49ea02 0.0 bc23d2ee539bf2f52faf789289af7879 0.0 ab2ef9bffd8e25c75290c0a2f6a8f85c 0.0 b460255b8269b55301e0c3c3e3da252c 0.0 b39a1bb517361c2a87f8fb48d66a49ee 0.0 b3b1ae423dc7f3d8942237d115a5bf86 0.0 b3d06445a910a9a444919e41f5da39c3 0.0 b3e2d6b8bb4b97afa07c0d048746b712 0.0 b9fefd4224e459a6a0d21db63b1c0d03 0.0 b9d953d2c367d1b3150ccf062dacfe83 0.0 b3ea95770cf649371d22e1a1d5aa3c0d 0.0 b3fef1e26b7b6ac20847ede4da68547a 0.0 b955f67a541a149dd3b179dc62d37a72 0.0 b423592b0ae631882095792b27729b9c 0.0 b4446b03208372a5dd17608d78f7e3e8 0.0 b45c9784d674879d68d54362419a1d70 0.0 b47e328fa7998e8085a30dc2a03506c0 0.0 acfd094c6c92700cdcf89371abdd104b 0.0 b47e999a38113e0e4e2b139e8b861fdd 0.0 b9024a1f377b62508864cfea59b16a31 0.0 b48a25941ae901a73b4a2830cc24b382 0.0 b507596e6af67ab90ce421ce6f40b0af 0.0 b55ddaf95d9d2217ea087863a7afbbad 0.0 b6985598d3f4a9b830bbe1c6a665f5fe 0.0 b75d05e361f46e33b39ef21d05334744 0.0 b8c6906ea995f21303d44ab7b21655c6 0.0 b796b2132a5015f869c8b5ac44a0e2bf 0.0 b8c685d6d691d57d63a05b0eaf5a669b 0.0 b7a041d2927c03859714fcdd60b9dc7e 0.0 b7fe67097e773cb42109cefc45628173 0.0 ba88d4e4e6a24ecc2a5aab6bdfbb77f5 0.0 b36ff490f4df87e30600ed347f23cbdc 0.0 b2e3852763d37eff884d326836ccec27 0.0 b2ab597a902ff227a5ba76030cd6002e 0.0 ad01a1417ca1d8a5a7a768ea78e45673 0.0 bc4177a5fd330e9c23138dac2d6c69e0 0.0 b8315874f4341a59e8e3ed317406ab09 0.0 ad52a0f6646c574417ce0b13b84acfa9 0.0 ad8991870b8bdd236d97d01487ddadc6 0.0 adc59da8759a4276a8f218e237e27f12 0.0 ae791ca848029549cd27ece21344d8a1 0.0 ae793fc8909a69dde3c7757780299e14 0.0 aebf2a74a3aa9e5876c479b1db88985f 0.0 aee0d6f2626271eacf89d2e803440657 0.0 bc0588863994a8f20e7dbce7a6fb8b96 0.0 aefd4044e43af5915f9a3fac602e9308 0.0 af25adac3aa4a6a6f6c97b23b7755273 0.0 b01e64261beff06c591132b8f0cf3099 0.0 a36d070ba91e6c48d0c79036200d0b20 0.0 b0574dba26050e54cf5efd672c2f58ee 0.0 b098aa6c11cba636420401399b83be7c 0.0 b148aa1f06e0eea5a72ac72fdf3ac867 0.0 b153e0852342c0738da791930625716f 0.0 bb8cd42775d7feb5b54059f90e5ce9eb 0.0 b1f2146bef78066448576fceeb6b644b 0.0 b265615da6b98d477507607fc51972f7 0.0 bb1c2099a32a335b1a55f44d3ba54484 0.0 b29deb0964b5328b6206ea33b9035302 0.0 bad4f7c5ada34a1f813946abcfe5c556 0.0 0021d135d4ac12982cc8abdf2b38e23f 0.0 9e8e56f06c0615130e1e2f459bd4052a 0.0 a33859e0fe8e20bd783ad918ac192884 0.0 902c0a7dd5a911a8fbf9e34e49f72297 0.0 8bb5ff097e0707dca3fe5860af20f4a6 0.0 8bd6fae62d450bdf768bfc6464d36d38 0.0 8d89ee75fdeac54f5ebb1ef3edf80e73 0.0 8d99d70a19898e91e9d7dd54dbd5881c 0.0 8db257dc277d4e84ef974e07dc449820 0.0 8dba41073e8e2650e099cda3fd3a0630 0.0 8dccd839cf4868a3343e411c063932a6 0.0 8dcd5864b11c06837480c727198cded4 0.0 8df5a666d571bcb1b2a44aaf978fab49 0.0 8e1c69dc9a692ce4b7e93c8cb728b7a6 0.0 8f1c11c7b732265cbfc1bb7dbd0241e7 0.0 8f5b5babdbe9847334e115160088b371 0.0 8fd6bffb88d374f38c6bf35cc8a4a221 0.0 904ad13c7b8512200836d5cd9fb09e1b 0.0 91b88aa295fe09a255b2f321d9d2b12b 0.0 904d063813394e9a3cd5a23fef870ec8 0.0 904f7b1ae29e6a78ff83eacd9ef9cda7 0.0 906138f305d5b85ac761fc50bbb6ca87 0.0 907ceab78e867d765fa360527608efa1 0.0 90949bb38f58e92949ab8504aff01df1 0.0 9099a7f671b923c7b07c12508f17270a 0.0 90a0937762431acf0f8f3643e08d3180 0.0 90a685caa7eac21daa8a8f56df52eb29 0.0 90b56798a9abd8360a79627ec3c332d3 0.0 90c2b51afe404951ec89bd52c7ae1f58 0.0 90dd37137cfac54abcaebc7048fe77c9 0.0 90e427df120ab07ffbd57703f11c1a4f 0.0 9122e867c908301e783c5ce0c3bf12e0 0.0 8b86b84549e5940744c30df2a573b55e 0.0 8b78fe0639a5308fb6f33a8eaafcdfd9 0.0 8b159e3b7ba334383b185c1926d9b9c3 0.0 8b0fef40cdee88fe61bf6c86ea5b8d41 0.0 84853bd31e74a04290e47c542c8d293d 0.0 84d6422c401698d91e646b9b4fe4774e 0.0 8507091bac6b1be88f3d360d6d535d0e 0.0 855e8b78c6f45f9a2e3d5afb75c4f5bb 0.0 85d8ef495cd58b08a300a623a3718ba9 0.0 862f918acd63eeace039314ff2263a39 0.0 86deb5cf8d6f29d383136e0d09863b69 0.0 86f04c5c81713db61f97bb53835f9189 0.0 8720f9ecd2331ce68e2896df1bf2d977 0.0 8731860c790449910b7955d1bde836f2 0.0 877f27b47c85f6b2d3cf8a6aa86def40 0.0 87bb02a4196dc0430e4ad2a975a345c8 0.0 8833ed97ab90d2af80eb7c7f7921f139 0.0 88c180a637696e987712b40ac9089f8c 0.0 890bfce6cfa2575db09fc1ba0909d3bd 0.0 8919944cb4b67e5abb04cc8afad9045d 0.0 894f46d021396ebbbc4041b65e198bd4 0.0 8951cc9103140b71bd50c0932e096502 0.0 89aabf43d24dd5bd0fd0f5aca189d341 0.0 8a20667bca2eaf2a0687995af876a84c 0.0 8a261f382a739bbc5f9494b2c64c2744 0.0 8a658263f5f46e9b06ce187893565b47 0.0 8a83cfd5eb074b5dbc6118eb03ef915e 0.0 8a974c19d04562e710612ca049799942 0.0 8a9f7499cdb85b8efa497bb56256cb43 0.0 8aa70d0c06e8da0b4c0ea2eba6308983 0.0 8ad30192adf51cd7b03105a1acdea794 0.0 919db619ad90cc6b09b31c83d5719da9 0.0 91d7d1256be7c1797cd45c2296095521 0.0 a2e3ac6b18daba602b14d93882f3663a 0.0 9e644716572f5930cb56186d75a6bb84 0.0 9b2d42844c99887e67257a377f7b193b 0.0 9bbe5054cf0bc376baf895f0638705f1 0.0 9bbff59b3c1084173c4917e136b496fa 0.0 9c25197937d1f54e2634026fbca6b55f 0.0 9c58ab3805d06ed6f1ff2a2de766458d 0.0 9c61dd9fc1208289eefdccd5ad281288 0.0 9caa12440830e96456250882ad25f89b 0.0 9cb1cfaea33aafcffe7c261eb104ca56 0.0 9d2176c908640e85287b95f9cd17bf64 0.0 9d650084364f31c59068a17261e13dc8 0.0 9dc78fd8f2f7cb10e190e77af61c7ecd 0.0 9dd9cefe38347b087dd318d82962cc03 0.0 9e033e0a6e420a9d407f908d59aa31eb 0.0 bf8144aac6a30e6695ad6bf8f49131ab 0.0 926708e33d1ebf1a9da757f78c673190 0.0 9ecd25659ebff6a840c089b93515c5b7 0.0 9f48f7b79ed6f3dcde8b25e0cf244d5d 0.0 9f4d14b114e7499772a797790d81c1db 0.0 9f74473636e6874853d88dfcbcecff49 0.0 9f8119029c8b972ae0375c8b968c14e6 0.0 a02c286e5afe7220b1fdf83dadea939f 0.0 a186bb74dfce512f83043f7b366c60c4 0.0 a1999b4f10c91d6f8efa3c9d73f77fa4 0.0 a1a22b2e460e6454dca7805f1cde48d8 0.0 a1f75692d5fc417ae9461aa66e0ed7ef 0.0 a220d7daecd7de9a9560ac2a5a64e2a5 0.0 a24dae6b87885a55d81df1ea6d1abaf5 0.0 a2e0f228d7110587954e13405f98f003 0.0 9acc238746a1f2aa7745a0b5720c4eac 0.0 9aa7314d56b3b3db2253ec2763414be7 0.0 99dda7b5337bc09a69e9e27bab56fd79 0.0 993ea35e8ad7ff6894e32247dc507e9b 0.0 92ae272884c88aa3be9a5800f2836740 0.0 92f000f936d3f349c5e7719a5edc5078 0.0 93029132afec86c495769fbd8dd65ff2 0.0 932e1f2d3f75eaba13d2b2be2f2f7cb3 0.0 9394eec407745afeb6370fb2a0ee1a98 0.0 9394fd89106163be8a11cd4dc46bc8a3 0.0 93a9affe525a4ddda933fce27518d7ce 0.0 94035fd1b8dabc1d79586ff8b52846b3 0.0 94650d81f3f14b948edfadca3ca7b166 0.0 94738eca8f0e714dac0390e647565488 0.0 94a699e62982fe59b7725f1b7271972a 0.0 94b000e59b7ac160b0416c9ab45ff0bf 0.0 95348b8c18227b458056472fc9eeafd3 0.0 954f244280781f0339631a6eee679e1e 0.0 957a16edeead7722188be53d05fbf001 0.0 959d48a11e3b26c9268f0bd1dae6ec40 0.0 95f77f9e6df255cf93ec17c1a48bc194 0.0 965d7a58f59ea6445b32afede05a4012 0.0 96794c2d601e0082c9b66552dce42e4e 0.0 97951199cbbcc765ccde49fbcbff09b1 0.0 979578981da3916b394bf24c32bace21 0.0 97cfaa815d9e25d41d6698f790b7ad0a 0.0 9828f58eaf910927264c204ace9caeed 0.0 984ef97167ec7b42d7a3650716d6a2ed 0.0 988b0b7321184cfc2c53e0966dcab560 0.0 992072d045462445dc239b35300af2cc 0.0 9938c8f22908861f780f8719b75dc0b2 0.0 bed1b5521bddc2d35732fafc25043f19 0.0 c4b0455f8d6d59d4caafda4b3aa90622 0.0 bfb7bb16ab570748b3a5d099e9426af1 0.0 ecc877a3410d54ea784131356fe5ea73 0.0 e91f1c5b67ffecb5ca3ca3b393a50f00 0.0 e94776066de6ff852fc7a43e7a0626cd 0.0 e9c73fbac5dd73dd5e3ada5664ae95fb 0.0 ea2b0e4a93c24c6c3661cbe347f93b74 0.0 ea6265476f08a35fdb764ae98206ad5e 0.0 eae4215acb2d651ce76c5e4d10f3d839 0.0 eaea5d7b84c08fdef5d8ab40f707e37e 0.0 ebb5ea4b9b617249c40513ded403e30b 0.0 ebd14a21e990e0266b2b985be4cb3c44 0.0 ebfae3fd8d9da7341650be7f4f6c13e1 0.0 ec38f851c5429708e114208c539ae458 0.0 ec6c9ea52e88226c339487585ea02f42 0.0 ecaa9f4e15a28f212d9bd60f749191ab 0.0 ecff0a63780369ddcdc800ab97fb81f9 0.0 f12011ad5219b22b6ca790103333a755 0.0 ed1c3370c86ae00e0062a3498ef06cf4 0.0 ed5952d1e022067b212146b9b3bc6812 0.0 ede423f2b32cfcbc0815db2435994947 0.0 ee062262ac3b97896676e558bb08986a 0.0 ee084a976fc8028a3fdc50c9555b2a08 0.0 ee41b2201102d120e0ceff1eb49ba6cf 0.0 ee5c4bf663b722fc809746f322a4f6f4 0.0 ee90bebacf6867cd5b4c487cb587ea9a 0.0 ef4045fe369d078db89c253c9ddbd123 0.0 ef467d766ba05adf651d1fc6a30cba06 0.0 ef7c8af53de2ee3385027bc6b4bf0883 0.0 f05a6141cb84e0c95470be3e92085b93 0.0 f09ca081a69806aca5de24d404ad4c6c 0.0 e8cff5dd9314935749206c1d83214d77 0.0 e86212f766f010236a072bfbc04774b4 0.0 e84bea8ae61342674744560dd7de4721 0.0 e82ab12c51a893c6d7938a16632199a8 0.0 de0ad18436d210c9b60044fc7b9caf90 0.0 de478a19bf7c5ab5e75d3dfcb742f4d2 0.0 de61860db8d93da85692dffb5cf32ab9 0.0 de6891b6f7a1f35bd9ccbc058b9e1a77 0.0 def8acc0fc88cc9a9cf110370ecc2c37 0.0 df1bc3956db29b2cded9d3925999f6e7 0.0 df6a1dbd34417b068878c043bd7a6bcc 0.0 dff37b3a4d27b9220b9af1459162a48b 0.0 e0fdbc7f687a7ea0cf13009c2e501197 0.0 e10c0e74616a50d8956a945d0b6dd531 0.0 e21d9f482315985036cf80d1b20de58b 0.0 e2bf5a8c1878477d542ef764b910e5a2 0.0 e2c3ff4f647112723741aa72087f1bfa 0.0 e30c40e583572ed45fef99d6a32d3924 0.0 e32053e0d7a8b525d0b062beb2ae11ce 0.0 e392de248b88befeab2319aebd7872c3 0.0 e4207d118a1ffe33509edaf320ac2a7c 0.0 e4d8026eb8e261594d51750b1080dbf7 0.0 e56aff2928773e4f9d4646bebe35123c 0.0 e5a43b018c81cedd19e9a5354d32d469 0.0 e6441fdd2f0ec36ec914d7154a64061a 0.0 e644522cf6d7222c9da7f9ecf614cd89 0.0 e6f747cd89d512cf187e8472cfb250a1 0.0 e7037dc2701d6b9666d2c0dab6110ae7 0.0 e78cb60fcb9cadfa0a32ba3ac4b2e95a 0.0 e79e5e4c871bac3c43de566188e10002 0.0 e80317d0fb0618cf19a96ef454fef9de 0.0 f10155af1849a17996f302d71b32398c 0.0 f19fa34c0c987ab3bd8aa42d8a4d21ec 0.0 bfd6e1ccc45f37b290d63de0053c212e 0.0 fc7466fe7b054b641298ab8b5c707d21 0.0 f83bc32e60e9c7bddf53a52937cc7ab6 0.0 f85dae8239789b16d0f8dcac9e272361 0.0 f8dc4d17a9589b91dc466d20015518e4 0.0 f94eeb84a8ab5049e8e0cbcc078de30c 0.0 f994313e9f7ddae7f7d6806221d6be70 0.0 f9b52205cb2d03153fd394a290212a10 0.0 f9f5f08e8da4cc9740518223846563db 0.0 fa09b814b417561651db81db34860ea5 0.0 fa1d5d724ccb4287e07ea1caa9d35502 0.0 fa71c8409cbcaad5dd98b8d80a46b07b 0.0 fad561b7eab58e57b71a09a8b7f990c8 0.0 fba43f263a40d5a9cc7f37f1551b13f9 0.0 fc613984c6bd68a102eb7daee76a24a7 0.0 fc9717bf86bf07fe748f608b4f2c57c6 0.0 f283cd6d309acf7626b1fbc0079d275d 0.0 fcab01e402145abc9e946d12aad1cde5 0.0 fcc915000295812eecfa7245a74346e9 0.0 fcfab546634e10be9800b9a4118b8dc9 0.0 fd069fff020b15638483c7e49d2ef9cb 0.0 fd1830279629e35893c2cc7538b028a9 0.0 fd1f139259c53276619476db0cc81913 0.0 fd21badba5eecdf5a284d5db7aa0679b 0.0 fd8cc2ec2e11078f3635cdc7fb477823 0.0 fda9e2638dfa1f4eebff04a14575f763 0.0 fdcd6808ef8269653d25dce4a55a025d 0.0 fefc7999a7e316dfa98bb6b63d6cfda9 0.0 ff2b5301608beca5896495311a512610 0.0 ff5c02a6c8a80d8898f37b7dc71f4c10 0.0 f83918824d8dd7875a4b478adf4ee601 0.0 f837443696652157e220ae13e330e0e6 0.0 f80a17436037d706dc728dd265b7c21e 0.0 f8000a94d405169f38df61e7cf1cd286 0.0 f2b4aaab4b89a51ec6205485018c9419 0.0 f307aa8ff39ee31213f4d9e1bfce6dcb 0.0 f3153e589a8718a2a1109a6e181617f7 0.0 f31aab4ff2dba1e72d9ea251e447844d 0.0 f31ac04c4b89a126b2406e811dff97fa 0.0 f3b9619b167cd0ec5f9c55a7dd6c7ee6 0.0 f3c30aa47b3639f25d168a810ee07fd9 0.0 f3cac486ad34144511deb96b29ded2c5 0.0 f402dfa5da0f4bd53468557a1a6b01e3 0.0 f434ebfe13e3764e53f40e7b99e07a39 0.0 f45b62ab6ec22fb20364a7e05088158f 0.0 f47f8e690205be8c0572db3c32829f43 0.0 f4909ad74d5b44aa7c3694798c21ea87 0.0 f4cd813a1b8a862f7a285466b25c6302 0.0 f5487404313a4fb57bc3489c167e9a37 0.0 f56e589e8377da78834cf577a69b939c 0.0 f5dd3f079f8866010ff9e1ce86dea070 0.0 f5f4ef252850e0b1f378923731257d69 0.0 f65ee26124609d6de91d4bffee014357 0.0 f6c6e7419ddde1e2e1d4a790ec6babfe 0.0 f710c0927080e422094a96ffe13b389c 0.0 f73160a94abee0441ab5a573877744d2 0.0 f7686a74ca2d3729eb66305e8a26309b 0.0 f7a5b80128b001df0f52bdad023aeb23 0.0 f7ce5d68ad002cdc285273d049516c84 0.0 f7e75337c2baaabcd5c9cbfa83ce5ef1 0.0 f7ef98bb6d0061b9368a72b1ff40aad0 0.0 de08a70ee5e3336d2c494d20206e650e 0.0 dde2f514908a4fcaa80827346c7b7a19 0.0 dd50bb187bc6f99222e626ddc810909a 0.0 caf54b4995a78b51266cb0e4aed4deae 0.0 c8933e6cd4ce9389f4ad6e2e24dbf5b9 0.0 c8ae16a39fbfa227aadd2e6d5a63da7e 0.0 c8d7e00fbcfbd34e1c85a8040155ecb3 0.0 c8fce068920feb387167d44c01689295 0.0 c936431ab7a77c5828a3da971da51acd 0.0 c942f59feffce9c3ab527135de234101 0.0 c98ea813f96e96f25ba321f74703bf6b 0.0 c99c4c951e6f4745973043285ccf486b 0.0 c9ccc527189a7a19902fc022a72c3bae 0.0 ca0fb2462b67d4296fdb8de1372d9165 0.0 ca5b38f92987671538ac4f8f5b4ee95d 0.0 cac55aa795998014361e14836ddae2bc 0.0 cae14798faeabb8e1b8840e712839921 0.0 cbb1dee8bf80a6cf676e15d39d9979d1 0.0 dc92897ae65716d40ff3b2746a2a6527 0.0 cbfaac9f291ac42563f27903d0f684a1 0.0 cc3e4918ee1c089c5bed6cab11dbee83 0.0 cc42ed01e236e8f05d25a7310d47e354 0.0 cc5f74d0b0787e9ca4f97835c2c0f2a2 0.0 cc968157f7691aab95df444e8cd103e2 0.0 cca22a273fa140d50cc3cdce9f539f73 0.0 ccce7fe8aa849bed027f6898300e0c45 0.0 cce0f21cdf5597d900d303fdac05b33c 0.0 ccfb4c8a7a57ffb8fd5212276ff2b193 0.0 cd1fc0b5ef8bb9823eb279222f0d0860 0.0 cd5f131980408e798875e41b3c0d53de 0.0 cdce04d738e587eb6a58f8a79ed36c20 0.0 cdfd52e813292000f1bbc5c4d7c95b4b 0.0 c870a3c711d733d9058cd2274a101381 0.0 c7ff7e806765a39b6cdf66a15b63f6bb 0.0 c7ec80af1d984fddec04831296fd65a5 0.0 c7408e951d6050a4ea360aa404050896 0.0 c04879d53b5b084096c5f2bdcc38d55a 0.0 c07ef20fbf08691cd223cba17009e12f 0.0 c0b31b31a1d47acfa4b2a6b279ee631b 0.0 c12331989624002d4f790eb1d19dad02 0.0 c123ec846a7e3837d1247386a6060ad9 0.0 c1365ec008032ee718dcafaf5ac17adb 0.0 c1a5735daf6f1e6157aeafb503b9e564 0.0 c24ac2e6e7002af9827563df39144c55 0.0 c2cd19f77efced924e3eccd8bc6750be 0.0 c2efeb6d250b34f682ae6380682f60b3 0.0 c30a545d14731276f649c2428c0babe7 0.0 c326a5572886b04b8ec92047c9415a00 0.0 c348a7cc121fa43fb14ca92cc4273c2e 0.0 c3937c933413c88df1db4b761e0e3ac7 0.0 c3cb5f0be6d5e3a4761a78606c1e4113 0.0 83420377ed17df2c16abaf3a72e05633 0.0 c4b11e3e5340bdf421aeb4ba0aff0269 0.0 c4cceb02f4ce674101aa2c0d1317cdf6 0.0 c4e57b91cc2be5a2232b3612abdf4c0c 0.0 c4f9ef34bd2919511069f409c25de6f1 0.0 c59161ae395fd5322d2f192f13cfb31d 0.0 c5adecb440a6bac201ab573ccd2d6dda 0.0 c5b4c6b372dbc13b6a7f2d466fc7335f 0.0 c5b95a83a06195f219b0edd9ab18fb1d 0.0 c5e3c5422835403541b0af331a2cc649 0.0 c6178d46f91b123b2c226120a3167a34 0.0 c6959c6d7f3f2806418eddfeeb3f2d22 0.0 ce33f26f3bd4784cdb63910753fa0792 0.0 ce399235aeab566680d0ad1ac6f9c7a4 0.0 ce9976fb696a210e526fb161c15ed88a 0.0 d3f86c6a6fd03654e0848a1fb1ad1385 0.0 d43ad42f3b1625379a2429c10f419eda 0.0 d4e63b08a25162d359541e38c6e484e5 0.0 d4e8fb8d73378ac761ec8eb3faf71804 0.0 d56536a97c18adccf18eb08958d93345 0.0 d5b4f33a93b1580c123d306690d0ffb9 0.0 d5d727a0e5ba892a10e9c81ef29d02c0 0.0 d666cafbfcffb984b12c4a405df6c7c9 0.0 d6752c4c0b83bb0ba7df8368b3c94d6a 0.0 d6bb5703483ac68992e09ce17683c52f 0.0 d6bc69828ae0ef27e99c01c9e7df86b0 0.0 d6c46ad81c01997055a3b713c0d5ee1b 0.0 d6e76cfe58d253204f5589d78cc79bd1 0.0 d7130a2536c5b200a01662b82ff93d06 0.0 d7466ab97edf938c5ed46f6bb1649b60 0.0 d75b7080930e7a77ef3de8c6154895b9 0.0 d780f9d98701c8ab19b4488869bd5be6 0.0 d9294a924ce5ef9df6e464b4ef2f9db2 0.0 d93dfe29130fd71bd30fcdeefea2862b 0.0 d97a97d4f8974683e4a66de090129c1c 0.0 d98796acd66eb71638defd318991adfd 0.0 d9d0120f569d8e15590c6486f4ffed36 0.0 d9e7a2013a2b6863cae05c51be41848b 0.0 d9ef9c1fd69f0b398b331c428991204b 0.0 da5463f9a3163db4528898c49e7fa54c 0.0 db6e4e3d6bea23bd5c619e4dd4ef5b87 0.0 db9caf76f81e72dac22fd1a55da6d5ce 0.0 dbf76c1b3ed4745cb94c15374d951beb 0.0 d43642bb228b6bd084483d2e5b48c3ca 0.0 d3d99580d90cca486a23372a474e9571 0.0 cea0486054293b47714d155ca349b763 0.0 d39f37b814ebd81091a949f8bd9d1710 0.0 ceaf720138cf7bdfb66e2dbdae539e38 0.0 cee9ade29a61d7669cc2710549611c53 0.0 ceedb016e7628567e25ad61c46a8be83 0.0 ceefb8fade04925c7bbfad924171a220 0.0 cf54928a038081788aa5939c49ae5340 0.0 cf8eb2fb3d885d1919ba916bc0975347 0.0 d0309ad131312d425619892c703b13ad 0.0 d05c86b5bfc092d8677507fb1eae8d66 0.0 d061a99148d649c4eca4836c5f4b5b68 0.0 d0c34b21c7c96271a1bc5f7fe82df3a0 0.0 d0f02fb55f33f41f45d8b5a6a6a5b018 0.0 d103541d4efc81020afaef43c0f02c02 0.0 d117a20b7daabc35e9d810f3a93d18b5 0.0 d1539f8c2855fe568d1313f20d26710d 0.0 d1b7d3ea1db807e9352522d92e403246 0.0 d208cad7c585049e04076ac7df960e7f 0.0 d213f55b066d42f6c6fea9f1d27582c5 0.0 d2589a845c837dbf413021f74e82ce0f 0.0 d28170caeb000a27998d838a8e7d5de8 0.0 d284b92d7518959fe5d52aa45b687394 0.0 d2aa3a30c8e178110125b88dfc7e6f45 0.0 d315a0b30c8e21db4cfe89e65c0b2bf1 0.0 d3211b7a04e5fb36a383450b8f5710e2 0.0 d32627161d829a1488c2a047669cb29f 0.0 d32d7b4a5e805f7e43f7823bf3eb566d 0.0 d34887a684a1acc690b8f3644cb11c12 0.0 d371cae3627eb71177294af103c68940 0.0 846b433f433cbb20d6208bd54067f911 0.0 7ebc04cb539befd9f2e7faa131628c66 0.0 832fd777a62ea50c5c34a8c2efb5c5e2 0.0 3017f87a3b0f5200ed54eca17eef3cbb 0.0 2c0fa4f09b72e538e3c6acead5b987cb 0.0 2c61ba77eb8ea89ea85728bd0022ac09 0.0 2cca9e3bd17f06418ac623fb0017c4cc 0.0 2cdea72aa7fe332d3e0a891d49d22c1e 0.0 2cf53730a41137e7ad95ed3680541d80 0.0 2d5957484a1289ca13b12328802dfaec 0.0 2ea79eaaa0b23b2a7d2cf470cbaf72ea 0.0 2eb7bab7b0af702e4f18358968a8f7ff 0.0 2f3b51e3f7acc3c9f66f1552b67a0209 0.0 2f75b02cd4d3ddebf390d17a120f419a 0.0 2f9d067d5ea9cc1b1289e9de830b326e 0.0 2fad39e365933a7f925040cb3c2a5ef8 0.0 2fee36ac3b841b7c63b377f87cd57634 0.0 30207d209491dfb7de83344e77fd6fbd 0.0 2b982979f2401a8bc447d7141879e9b2 0.0 306d425d43fecaddb4ea5af1cc34ef98 0.0 3098ee4e595175076514b00a8a20c291 0.0 30fc8af207d17abc37394fbf3d1793f7 0.0 31ebb433ebf0b3e83259d826875b4438 0.0 31f493208054aa0fea8a26d72ee670dd 0.0 31fe7997ddfef193110db377890f9520 0.0 320c03afc417b829a51ecad3dea2e065 0.0 320fd62cdcfb66cfcc1438371751c4af 0.0 3233034b11dfc584717d9264882a4fce 0.0 32382a0f5831da5faee464d011b5616c 0.0 3255b196d8b70893d9124239bcd46782 0.0 328d5b7cdad033d7b3ed419b720ba2d3 0.0 32a21601ca89d1f2629c1a9fc2de4359 0.0 2be34a58b64107daf7b5426302feeff7 0.0 2aa7a8ef7c70b5f684c856e6c21b6635 0.0 32d9ab84e859d48f487b790c58e98234 0.0 23dece0aa961e717a81e1118455253d1 0.0 219fca301444ebadab34c1a35847fca8 0.0 21ce8465657612a85e2f89e74d285ce1 0.0 21d92a1e71eeadaeec2fd51f41249446 0.0 22026223740aa4b6376f724986d7bf12 0.0 226d7503ab3d1ea0ae84d97fbd804323 0.0 228592b44e6a4d192af2d0732ec64a51 0.0 2290e92733707772a839abf72e7981f9 0.0 22b9160be22106587cc68893686c44c1 0.0 2364e23d05750415070f8df3ccb0c95b 0.0 237135dc8b20f922cabee934f7d410a1 0.0 239b4f4f6c5fc459a1c95c4bf704de3c 0.0 23bf5f7fe3d1ff8167bf3901fdb0685a 0.0 23c05ffd2b0ba1534717ee52a81b589e 0.0 23f4c333bc50c5cf2c0f20855d049cc4 0.0 2a8a90cd5770804a5f23f425004de7e5 0.0 2403a466dd6d1e4f551d80394c2aa994 0.0 2480f3aa1e7784b461d9b5b83a6bfc81 0.0 24ef07664cfa04a819d7797a89e653b6 0.0 251429848560a80abcb96640ceb102db 0.0 252d0fd6601d9776290e142e5bfd744b 0.0 2594fcf48955bec7b61a5ce4aefa3868 0.0 2732bd972ea75eaae442f937cb39253e 0.0 276c5b1d00e091a197a9ed8753beebc7 0.0 29568b810d7a4e985424b9037aaeab9e 0.0 29784e17460e4faa8e4eb6576e85f22d 0.0 29ccf8b234ac00b114fb2c8e1c44f932 0.0 29e53aaab03b86749d3941da8ea5b59c 0.0 2a13ecb6c618ddf8154298c69336dd8e 0.0 32afbeb5f76a69e47f6cf6a1870e95d6 0.0 32ebb69544acaf3162b5e828d05a5f84 0.0 218a6324d16b842a38c70f1088a7c8b0 0.0 3ee072a59b45057a86369a7c80ad90e4 0.0 3bfae16068c7a0b87db6a711c01eadc7 0.0 3bff9ab82e7f2a76cc22e687ac7b72fd 0.0 3c5496fdcfbdd5b2e4f620d44f83414c 0.0 3cb3514dd7db8d7720477ab5759b970e 0.0 3cc53c481fdae6358e4d2d5c9f95a1f0 0.0 3cc657dfb41c68faa70508afc63f4222 0.0 3d52122a218f9c70126d51d42996a1a7 0.0 3d6469bbfb14a86abdaa602a89753ec9 0.0 3d766867c97f511431bf97e059d6498f 0.0 3dca01142e22e42b989fe5a513e103c7 0.0 3df77157a242066dfb4eb9c19062436a 0.0 3e2716bec0426995af52846a88864c6c 0.0 3e9c062471302ac0ef352264490d1b3f 0.0 3ee56b6c4d038d4b8d26f63fc337cd02 0.0 3af2ddaf4af4b5ae4100439a9c3d4099 0.0 3f11f9f226ab63cc1ff6bfeee9699b79 0.0 3f1ed51e954b35a8108c12dd882b696b 0.0 3f2fd56fd1ec26b86eed89795fe014cc 0.0 3f54618710e03bf1e78b57e14ca8775f 0.0 3f55a8ca784ae7190790023a30cd859c 0.0 3f56d7b61bdc82e4d12c6f58617f5103 0.0 3f6c45001fd40e8b6f9d0558539fd820 0.0 3fe55dd5e59267f275e972017302459f 0.0 4060be28072a120ebefbef199c09187f 0.0 40787e473f59ede4ad561b4e4079d97b 0.0 40a6b537d995aeb12b0100e2cb6ad879 0.0 40c85a458df8d5a935122ba778d4f334 0.0 41239266f2952a56a313fc4798f28a1c 0.0 3baa56d5f42b81f2817aa34412e36439 0.0 3ad7da49c52ec79eb228067d25d2f2a7 0.0 330b6fa220b88e87ac7c5ed39ec276dc 0.0 36be43c248f8e4a7b60a4739cd8dd932 0.0 33206a2306ca96922fed904661eff421 0.0 334af877a390268de17839f80e212fd0 0.0 33852dc244bb69590e8e756a83bb2f4c 0.0 33902c26956acf7efa69413cfea6326e 0.0 33950a5fa4d8ee86e10778182fae6714 0.0 33b58b0709e9c05ba8404c47e6a7ea2e 0.0 340a5698fe78713b785c3bcce89df73b 0.0 34c133377349d1b57072aaab4f781fd9 0.0 34cddd9fe152c24d78924ef25927d67c 0.0 35513c8de34a49ef37dde85737e6aef9 0.0 362b97b08074732371b6e76cd1a894e1 0.0 363c1c39d58bce4fc3218659d0944258 0.0 36402f6154239da8ce422da64a0bd247 0.0 3781803fe3eeb8e5bc50a5308f4516a6 0.0 3a8731148bda5325db164e3729754abd 0.0 3788b1d514737976689f4ed1dee8b52f 0.0 37bdb470cfb64ad4594c5968cd95e312 0.0 37ff76f02e76dd8fc629cb05575defb1 0.0 387e36ab394fd347fd94d8762016779f 0.0 38c80ed971960fd1e878080f767a4765 0.0 38e3b7abf4e08699d7a1d1965f177086 0.0 3902e1865aa0a0863687793a7891f8f7 0.0 3950fe55c9d109b986e327da3ab3653f 0.0 399bcf0feb12a20ca0731d8d65268dae 0.0 39bb3fb5b2257fd2eacca408dc42c5d1 0.0 3a0e00761e8113458ccd7d13af71b4b0 0.0 3a1461e8439091ad6b93af0ddb3849eb 0.0 3a3e562a61e57ea1ff4f24857a1e79da 0.0 219d2ac2e47968bb839bfa948559ebcd 0.0 2086666afdd5de098b04a94247040c11 0.0 41b518f17927240fdfd1465cd351afc4 0.0 0c70bdd5631104dd3d818561c9166f6c 0.0 08a62d972f6bf2ca4dd9291bc2cc9f63 0.0 08be83d0a527ddd1da0861135192e593 0.0 091e6e4ffe1252fd657f19e42e04e859 0.0 0a5225695ff3a449ad8ce395d75c3799 0.0 0a99bccbf1bd2e4f728514ba8c4cf6b5 0.0 0ae0be308568d07e0434434b14b8d565 0.0 0b05a2e48cdc5f9e766bb0f4c209d4b4 0.0 0b3c20a64187d28e11a68f342081c17c 0.0 0c17cef318a9e1c8895c0961c5ed2193 0.0 0c336b876b379dc729ffcc2a1340f670 0.0 0c3a02ffb054a07b355c1649433fc699 0.0 0c3f267cef317f7d71015849370f1f6d 0.0 0c4204a0e15fccc22a7456685898cd5c 0.0 0cc2420a6a4698f8bf664d50b17d26b4 0.0 0820b82d14921828dfa20b56242a48c3 0.0 0cc26190e976fc496119a5eb4cd0fee7 0.0 0cdc26df2e337ea78808c32c8f52c94b 0.0 0cf86462b45382da531327e4186091da 0.0 0d188e3528ce4d674680de129470f7bc 0.0 0d3b942348cade7e1c41ac52df03e63e 0.0 0d69754929eb3dd1a5b256b43f1c05d7 0.0 0e637c81e25ffbf7b7e68a8fbcc4f2ea 0.0 0e7be154d128e3ce2b9b05e3e64a679e 0.0 0eb15dc6ca644533da15764998436274 0.0 0f0c741eeebdb89289460115e9430f1a 0.0 0f42bfd00e871207c3e2bc92a79f3456 0.0 0f6200a5b77099113b52eea9a8645181 0.0 0f8aa0e4c4ccd80c090db7c72be4d264 0.0 08a1598eb1ea4dca23db1135552cd5a7 0.0 08091b93dffe421f648aac3eb7e192c5 0.0 0fcd8cec2c4190fb7703e87f3c04a0a9 0.0 04c8be5a3a6ba2d70446812e99318905 0.0 009a4919860d6d1fddec5d3771d37351 0.0 00bb7a84ce1fa6f7411597672ff1b09d 0.0 00ecdfa98a302087bca221884a535f55 0.0 010f0ac2691bc0be12d0633d4b5d2cc4 0.0 01241d7b0a1f219f5a68bf78b9f3b294 0.0 0189d0173c07f11e7586ff20eb33f5ba 0.0 0209f9868a22059c659df474a746d8f4 0.0 021899b8a2f4157d54475a024303ad5c 0.0 0233fed56365db96e625e92c4dfb9cd0 0.0 026598f1d03fa900cc03cf9a32dc17d8 0.0 03569e3fd843f501355f7853b0ec9361 0.0 03fdbec0c9b63a05ae79f92c6d3a4cfc 0.0 041d6dba3af0b8c9c1a422ed942ee16c 0.0 04cf55ca51883bf19bca35e8ab225def 0.0 075f8821bc5c57034fb74afc07233d97 0.0 052ad6076dacb9cca0dbb762a466404c 0.0 053c4d5b8717b60387f777efae437b40 0.0 0540bf08e9a1eb8691a9b1be2afe577a 0.0 0550a92d2e1e15136084e85881efbdea 0.0 05736395b184324b94bf557984b36834 0.0 0584be58049c7828c032b2171aa00a4b 0.0 0590c29091ff2b3affd966ed57773407 0.0 05992d2befeb4bd87b626698a9694ccc 0.0 059c8f8bb468064b134ea6d3661761ea 0.0 0615dc8ff9d74b14531dde03da40bc47 0.0 06c0aa8ad0fa418a4236c6914fb420e1 0.0 07465ac96a07454a7c155d9c674bbd5c 0.0 075eb451ed18cc7fa554e88c2726e7ed 0.0 0f9411ed14b5b3aa1a9655523fa33004 0.0 10155b2834300619ce0102110a37b057 0.0 200f25968eccba0fac01ab0385952acb 0.0 1c4344ff805fe2e4a760b5d01eb57eca 0.0 17dd8d3d133442253a1d51601ca5a192 0.0 185e45802a5c7674f89b5d0dd66d7912 0.0 192522c9b7c41f7a761f8a2ba792268a 0.0 19cb3add28813b2bf3e1f40a000d33c2 0.0 1a0bea5ccf9d532d75136168ddb54654 0.0 1a389bf765c8ff0f92600f684fbe7ad7 0.0 1a5526b9f7147b6893f1a034a107cc65 0.0 1a962bffebb20d79245326ada6fa9b4a 0.0 1aab913302590e21a7be28b1494a3320 0.0 1aaeb592fcca5013db99a4f629c55062 0.0 1ba09da532a0f9985b3caf72a47b42e3 0.0 1bb5836797e9a89a2de9b96bbe206524 0.0 1bf05d12bfd387888facafd52c07a37b 0.0 1c85fe6e01899c1b9575734197172ab7 0.0 17824e221f06eecf126ea102c3a2c289 0.0 1c86153e1b13ab5322c96f2602b73513 0.0 1c94105978b1aa2095e3c0096774f240 0.0 1c9f7427ad9eef9581c32e490d0f3e35 0.0 1caec778d70d2d387717d1d1bc248bb6 0.0 1cba52a9db0c46eaa9148953a6983f1d 0.0 1d1d606cff1c8bab0027fdd1e2ede36d 0.0 1ec95834f03c9606f9433e59443e5bf3 0.0 1ef782a559e3e0a4ab42516e0a2c828f 0.0 1ef9d7dc5f8c93a8a43bd84e55f9a08e 0.0 1f4c8ba04bcab2849c9ddfbd7fa3d1ea 0.0 1f982b62b3d278f92eb3007e366fbe14 0.0 1fa555f9a74d47a6ca7a65a347bc885f 0.0 1fc9389433a5ed33af26e3985bdcda26 0.0 17c24a9e01ee9569cd8f4a4b0e9b1b33 0.0 16c36bcee25e65305630899e962804ca 0.0 105d5959bed2c9399522aba4291031fd 0.0 138daeaeee1211d2a3d8502b8fe23b2a 0.0 10a9a0887483597b71cffa08dcda40de 0.0 10cd502b01abafc87e2ecbad86389286 0.0 113ce005a880987438bdbe19ee22add8 0.0 1141f30eddb626a3a1151a19445eadfe 0.0 1142fa8636688cdac86a8bdcbc8bee05 0.0 114a94e972186d56504069f1bacf505a 0.0 11764b0405507198175fe590debb40b4 0.0 1182d94e2fd82a9b44657970e252736d 0.0 11b21c7f71591dd1570f9717990ea4c7 0.0 1243750138937650754b619370565800 0.0 124c75409b4ecd0bf23a84e28593567d 0.0 1264ac914d010d7c663fadca9c5904f4 0.0 131d3b899e72f19fcae1b0f9f8f3a009 0.0 1407e963207002430eaebcae4b500708 0.0 1661c49d1dc41645c0bf242b2064f1f3 0.0 1442af5b43d77ad0cd6b73feea01af87 0.0 145ebc1f8ab3b2896eb631008973c0b4 0.0 147e08753c0c32354e69746256220ca8 0.0 148c7eb0139bbc1b8c87dd31464742e4 0.0 149e7d5e484d157f2ac6140a2111618e 0.0 14ea2e862193001ceb4322087eca9f4d 0.0 1516918080ce0a63f2e1ac6251ba1282 0.0 1527fd8b14037f53b8edb26b111e1f72 0.0 157a9e8a83fb37615cabb48c14d919f5 0.0 15dd83460074717cb57171578115cb49 0.0 161d27a7363501e838efa59628353a65 0.0 16306acecd104a4f12ec62522e1bf751 0.0 1634bc38311d3c868d1077602dc439f2 0.0 419242e308e14800b26a10a4bf82831f 0.0 41df3b4c55182503ecd97c6dbe47966a 0.0 832e6210c0410af8e0356bea5ec39c80 0.0 6d34445f3adb296a5642fcb5f81e5219 0.0 6a17479edbe461431433bddb084f731e 0.0 6a66cd42df39f678f4bb2f3e840b011e 0.0 6a6880faba39965be0e4b7d88966d1c9 0.0 6a6d8054e2a7052fb8fd458dccb2f88b 0.0 6a75fd73efa64af9c36a4435bae0f920 0.0 6a83401c3ea3089bf7d3c3051a709ef9 0.0 6b90b86f5da836f13c0ee2f67132e12a 0.0 6bbaf2d026d54c61f24b5c5483e56842 0.0 6c1f3bf3e2186d0faf5325be92f4c974 0.0 6c4de756c45fa6e7e5adfe196f9f0039 0.0 6c7fa77831ae630967a6fbfc8ee47901 0.0 6c84b0ea6103c2ad5f4c3b7f5dd5e1d2 0.0 6d0013cae9b331ee166821cb124dbca1 0.0 6e8986f8088b452f964e7968bb8bca87 0.0 69f46a090420a7f596df5d450ef67e66 0.0 6eae8918e5425723c03d19afa8ca0356 0.0 6ed7152332889b69d2d2f33c53b68934 0.0 6fa149c798c4251f1ca8cd356f0568ee 0.0 7029eddc845e01d613a3bbc113ebeaba 0.0 704d0070549f26fe1f99eb736cdc4c34 0.0 704e8a1acf77dcc1bc06251a34ba2132 0.0 7069d1ba735fd4d5199050b4c100bea7 0.0 71a713c5aa69a8e46efa23a2437010b8 0.0 71d32936afbf6c7745a6083e7b09dff3 0.0 7201d53bd647437ec3de879774eba498 0.0 7212fe837f6f09bd16ed2c9b2c58e557 0.0 7281d8476d29dd24b3e674ce9cd9e3b0 0.0 740c97e7b2eddae8044cf27859a86b7b 0.0 6a129e8ae637c96e7bb56223913911f7 0.0 69d052e452e79d571cba042af265d50c 0.0 744b8cd51857478bda77a9f3ab5e1d5a 0.0 66127b1730c816b3e022c01fcaf024ea 0.0 6240207fd3edd24bf0799b5f427423a0 0.0 628a44c637e99429e3ac4c39227c6c9d 0.0 62ada1b9706d5e11072e7d78ecb0a4bb 0.0 62cb0ed0f2cba6fd1ab5d2a374c15bb1 0.0 62f043c2aed6f033879b83ca519fde32 0.0 630bffb8b9a197b3a6359f42828b4de3 0.0 639a2c1d7ae3f6700506aba8baeec034 0.0 640f0d7bcadfc07ac9f3a4d0b440d859 0.0 64618afa3a07dcab19ba87629333ab84 0.0 6474f5ab8c91efe951ad41f60fb4218b 0.0 64b3028e870c12fc7d39287219f7af67 0.0 64dc86ad2807b50d91f4938a5bb31a87 0.0 651794369aeb3db83839b81fe49c8b4e 0.0 6677fe5ca3b81ce606eac5d76b0a0ece 0.0 699d4b4de178e2d52195830debfc3b1f 0.0 6689cc067754fa14964e70c77ae9ce0a 0.0 6694ca246e895a4f1d7e1d077cc27f5d 0.0 6700772469767941a3992c3e2c65c3bb 0.0 67cd78854a06d6e3867c28745e509ad9 0.0 67ec5c8d397bcd64b2e336a60eef437c 0.0 686d42b9552375c3b61301ae5605e3a2 0.0 68bb0065fa02ba7b52acf3f4d833895b 0.0 68db566a60ba7167b024b4c5032d9400 0.0 690754306aeed53ec9ffe767151681cb 0.0 69536042153447ceb692aa53159ce0c2 0.0 6961c6244fb505547380d15bfee162a9 0.0 697b3fb29268cba4b2a9eef0eab2de7e 0.0 698862fbff78c7fc3cd7a9f4958bdadb 0.0 7412af58f3daee6101db082fd334144b 0.0 74b7dc5aa537fcaf4d0046dc7715b9bf 0.0 61602441fe4b6f2b36be40c311fa9cb3 0.0 0064e2a432a2756eabdb6288a368eaef 0.0 7d4bc1c15b975e6ffe247f13716e5f53 0.0 7db357a4adb452de8504d8ca1ddb3f99 0.0 7df3c653a9ad469d0de18261ee771eac 0.0 7dfa96abfa7484bb6c9cfa90dc9b606f 0.0 7e17a5137fd9dab8c02617a186088c4d 0.0 7e3f4a0767fe59521a6db1862056798d 0.0 7e54570d21f03dfcefff07151a8c2d54 0.0 7e57bf1306ddc4beb5aa7a1084d8c845 0.0 7e86e84e054d9c5a6d485c9ef762c5c2 0.0 7e907df30e0739c3bf57f18729659005 0.0 7e9ed2c841e64976eace4b578ff56a26 0.0 7ead39abbaa90f90242247c455393162 0.0 7eb58843a058a3dcc0c051e0762de977 0.0 7f323d6db23992932ec6e097ae09c4c4 0.0 7ce470a3f833253f6d667fa6830abe07 0.0 7fa68c46b87cb8fc334456fc14dfdf23 0.0 8042eb376d870b471cadeab735dee5a5 0.0 80fd14aea177425eb5d6a4b388a08a07 0.0 812aac97abf11d6d64a00496e070e266 0.0 8139d4cc5e4e5d44bad494a295a3e7d6 0.0 8183f1e3f9806994e125b1d5c6932498 0.0 81a1e88c8e85192aecbcb517cb0bf1ba 0.0 81f1b22052c8eb3dfb1e6b45ab7c8530 0.0 82168325f126cecd669b2d0e030c9eae 0.0 82585d0d14cc315f9da0257c3a2875a4 0.0 825e1e1d675a615bb3e6914499939c93 0.0 82c890da8759fa9477cd991a1f214b3c 0.0 830932289444e28d4ab0ac9cdabfe977 0.0 7d2f0f34f2ea4ce7030a589e76c0d06a 0.0 7cc8273fa6f3c9f55f426c3765741834 0.0 74f2fa20e0ed1f74fbe4857f249e3a28 0.0 78eecb7cd2176d3a2ed21ce8154ba1b3 0.0 758cd34d30d7af60445b5f0f932d21b9 0.0 75a5999048000b7e178036f0e75e4dd4 0.0 75c5f35120584c258c8ffa734a94ea8b 0.0 76075eede2e2c9cf276a8394c7cca293 0.0 764bb70efe70ec930379806d178319cb 0.0 764ce1e6cf32606d676870bd6ab3e21d 0.0 76cee9663ccd2b6160d3dfcc88df3c38 0.0 76f7f30b434c8deb5e2a0fd50baa1496 0.0 7769cac4c6bfbe7e3cddd33636c22519 0.0 77c18841a3a2296268d30a71c26a5cec 0.0 78266846787de98cf89a724cb5586858 0.0 7839f352a2bbf8261351db78a9bf3bd8 0.0 78d8e6cbe439685d63e01561094d1736 0.0 79280cea51a6fe8a3432b2f266dd34db 0.0 7cb7753109015ae718a1a0201d081e99 0.0 797ebe05936131bb058c0ab04c171a26 0.0 7a1144e3e5689e67eb04e1a00e49c45c 0.0 7a629c748d0205443ef1e8e26ee09543 0.0 7a8d29c59b803baaed9cc1f04ce0dc33 0.0 7a9469ff27dc7afffdb7238976da0a6e 0.0 7ae7a28e3e35f8669d62a551beedaf7b 0.0 7b2ff5940de11da4dc3bb208805dff11 0.0 7b6f8858b481821ad1aae2e8d796fae6 0.0 7b9a7ec76bd5dd38a2964e80934bc632 0.0 7bb3a2f7b1bab185035b2e361b4fa760 0.0 7be9bac1b13acbd8acf0de464d7c20e6 0.0 7bfa7582156c882bb0c1de44aaaf7a3c 0.0 7c99906fc47555e0b2df4cb90c47a3c9 0.0 61795ee8e60f4a0f66080ab812573fb8 0.0 60e681703dcab859a8e336be27fd6cf0 0.0 424613c7d3d2daf5c715d1356a972381 0.0 4e3406627aa545813116167826c24a46 0.0 4b3f3f0ecac9b4026751b7549559c9c3 0.0 4b548f1f6fc22f32237396b7d4ffee6e 0.0 4bdc8766a80671911353b96f2d702ffc 0.0 4bec204a5986223b16143ad5db1c8433 0.0 4c1afcf47b47fc2850fae19210e27117 0.0 4c2189b6b5ced3cb80093414e9449de9 0.0 4c731267e801c2afe253b5cbb58bdd24 0.0 4c855814a58f4f324e8f0cfaab222e1f 0.0 4c954887a7bd1f32382dbbade7b91aaa 0.0 4ca53113aeac7afa697e8cae58f69855 0.0 4cc94d6f0ba7a2a174fa668ef5966bae 0.0 4d7f3a8e908cb29809ed118acf40d513 0.0 4db47b583b03cc6706e28a2fe2731080 0.0 4eb0fadd9ccb6cd253273f89be164175 0.0 4ab7cc7f5969573696f5cc3b1ea0f4bc 0.0 4eb2c50a69efefc9d10540928ce08822 0.0 4f5e90e831377b98f5f6e569d6d8f64f 0.0 4f6f2afb7adf1bb487b6a86b13022445 0.0 4fd1b92e9814b1bc6d1f7b1117daf660 0.0 4fdbeac7d6cea1fef876d607636f189b 0.0 4feb634e0ed63566c64710659b17a2ad 0.0 4fed36b0643aa2ddcecf381c1f487a85 0.0 50f328ff0b5c3003ce220fbd7aaa2ef7 0.0 50f8db74e965cdba7ae86014644a3137 0.0 516549c565407769125e3e8f3ca298cd 0.0 517eed6e97dd2846dae1553b8c7c9464 0.0 51a63d18809e04591820c7e3f3acf0b4 0.0 51c999131379511e8950fed0550134f7 0.0 4acc36d268585bc3834e627756313b21 0.0 4a86baaa7e5adb00842830155d3c7fd0 0.0 51e77f4577d36c8bd3627a3d0229dd37 0.0 446ec4331e4894b14be920825fc962a5 0.0 4261b78dbd18dd66cbbc7a7f0f2a51a8 0.0 426bd7119a31b73ef734771a071a216c 0.0 42ac6d34b293d442987af367e2eb4f51 0.0 42ce63585eaa407ee53b568bdc648be8 0.0 42ef609ea1f85d92d08a416be896e309 0.0 4311a44a7d56ce4086afad3e75bedd6e 0.0 431c53fa5c895a6e6f5951578f6dca8b 0.0 433d8ad01fdf6ed57d8f509a7d6bfe2a 0.0 4346c337f6760bd0f8e574277524165e 0.0 4355c3f086c69fffe013ed0a3fdc8b66 0.0 438eb58eedcd45e1eedb5889431ebe2a 0.0 444d635c03299c7b88a3a0c236831bad 0.0 44620cd517e481b3b2b27ff6d6611d53 0.0 447b9d6a5c17543a456c597e65b37139 0.0 49dd84930ff914f17216bbbef0c6ef0f 0.0 44a36b6738e227582e14a58b9d92a5f5 0.0 454aceb66125863a02ea9d46c0b23136 0.0 457d3865cf0a4bc602a07d8d5324388f 0.0 467201ebcbdb17a73c8dbe98f8bbdafc 0.0 467fa58ad637f123633ecf3cd389ed36 0.0 4687677f9674fec6aca4275f36063b4d 0.0 470aabeb5aab36d5ddc9d1995b087843 0.0 4786895e195caa90723aa4bcb25b8b03 0.0 4790a2be4d1288d94177213af8380f12 0.0 47ad35356a9bfec68416d32e4f039021 0.0 47c98abffb77eb5999855b75594356cb 0.0 47d0d6c4ca012181585fabd306fe7026 0.0 49a130e2f6d8bdeddd170945a75a6783 0.0 51e4182fc25b356d52164f3de0d5d4b6 0.0 5226eb5e70712d3425df4b0e57d5a406 0.0 60ce43bfcf795e997e3c969938262dab 0.0 5d20f93c621d95608e5b8473d56d5b52 0.0 5aa1c4b839946b713b450ff38e7d5bf8 0.0 5ae365ca527c17c22171f54421e75197 0.0 5b31527f1b28c37035a08b3642d61ece 0.0 5b6a30b5a900999d91448bc79c5e14d4 0.0 5ba339813ae7235641d2f1ff581ff2d7 0.0 5bfef4e7e21aee58609421e4f24b5dc8 0.0 5c3e4422374120cd00d41557946e5c6f 0.0 5c6ba6ec99b516d0d9cba8e4730ea1fe 0.0 5c78e7010bae7392c680c7ee9a1ed076 0.0 5ca5ea401c8d3569e69626d2f81d5578 0.0 5cad0c3ca2db85210a2d320bbe783fbd 0.0 5cf5895a231b0a52d5859c74c74aada7 0.0 5d141d74c8bd046171ec64835c4864b2 0.0 5e151aa3f416a2fa6f0a1d8985282783 0.0 5a0df24ab3d9c2d78a043cd477a54b4f 0.0 5e32dea22765b73ed60b1d78a9d4d574 0.0 5e4405e37412f415c47c112a0cbc487a 0.0 5e99c84d99dca9630c51c5fb88000143 0.0 5eb9520307f1836913cc5937f1c9f64d 0.0 5ee1da6b8eb2e1149af74254c8c07736 0.0 5f1d2db99a41906b5ca2800149e0c385 0.0 5f8c4f83215d666e801e21278b17fb45 0.0 5ff2bac04b0e8ba06ff7e0293588c308 0.0 5ff715b26c5f3632a12da2d4dbd758bd 0.0 6007bf22076e2e3d0030e38442149c54 0.0 602510f333bda9666e551383f7ebaf82 0.0 60746d8928422234eb34fff42f4cca47 0.0 60c57911662a9159dfdd0fc05d975a55 0.0 5a21785c07d7cc123256f09d00deec29 0.0 59d031b8ba709e8da78b4c1f63c74f09 0.0 52b25decd37eb58a3bd46167d1c46354 0.0 56c3d1a8e4dc5c2aa7afbc1563559448 0.0 5350db19ba80799a8c5ee886143dd940 0.0 536018032c5d0d65e6d25d3988f87421 0.0 53609d8db4e52b4f03beab3bc44ad5ba 0.0 53668ab088d92c4856914e433447af5a 0.0 539c656b9710b0099a96a678b3023299 0.0 53a3eb7f49d8d6857ba7c50dd5bda866 0.0 53f6fd6e785c7fb9d72f94a6ea343a15 0.0 5406f4862e6c5e04e925b8f0a501958d 0.0 5494f5c56e0875a35b62e234cc67ffa1 0.0 552e00cb506f739acaf08aa5641f9d84 0.0 55993950ca597b6dc821765327bbf3b9 0.0 55af0326535a408ef56415f2952e2896 0.0 55d4d3011e1f3bb8e4e5089b801b61a4 0.0 576c2135e8ddf9d0a3674a5937d2466d 0.0 59c6ed04d2faf081cecca31f1eb2e42d 0.0 580e8927be639c5ab7fa8731a72c76d2 0.0 5844d8e76e12fb8526d7fede1c425670 0.0 58464ec27209abed9698e88ab974e84f 0.0 585f01cd625ddb45fa4eebbc072fecd1 0.0 5860dac317300b1fe6094e958240cc7f 0.0 58df89090206b56c52bfffa4b97f4d5d 0.0 59196a586276f0be745d0e334fc071c6 0.0 59597cd430deea6d8e0908dcd6db7e50 0.0 596c1c5efe777a8d8aafbca19fe37e1d 0.0 597966c93921ecc2907ad15121cbcd2c 0.0 599ba6458e91e2527f358f547ea39261 0.0 59b17c1cd2e1fa86064869f5bdbea8c4 0.0 59c4a678634e50b3fda861310820aadd 0.0 ffaecab289059c048c7494d4595a746c 0.0 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/outliers.tsv000066400000000000000000000000661462552620600264470ustar00rootroot00000000000000 outlier a True b False c True d False e True f False q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/predictions.tsv000066400000000000000000000050601462552620600271230ustar00rootroot00000000000000SampleID prediction 10249.C001.10SS 4.5 10249.C002.05SS 2.5 10249.C004.01SS 0.5 10249.C004.11SS 4.5 10249.C007.13SS 5.0 10249.C008.02SS 7.0 10249.C014.02SS 6.5 10249.C016.12SS 11.0 10249.C017.01SS.r 7.0 10249.C018.03SS 8.0 10249.C020.14SS 6.5 10249.C033.05SS 4.5 10249.C012.16SS 19.5 10249.C024.12SS 15.0 10249.C025.12SS 13.0 10249.C002.19SS 28.0 10249.C020.25SS 24.0 10249.C030.19SS 18.0 10249.C033.10SD 15.0 10249.C033.14SS 10.0 10249.C001.35SS 8.5 10249.C014.22SS 7.0 10249.C017.01SS 9.5 10249.C025.21SS 14.0 10249.C037.16SS 17.5 10249.C055.06SS 5.5 10249.C005.08SS 1.0 10249.C007.08SS 1.0 10249.C011.04SS 5.5 10249.C011.10SS 12.5 10249.C012.12SS 4.0 10249.C025.08SS 6.0 10249.C030.07SS 3.0 10249.C033.04SS 5.0 10249.C034.05SS 3.0 10249.C034.06SS 3.0 10249.C020.17SS 10.0 10249.C020.18SS 14.0 10249.C002.21SD 15.5 10249.C002.21SS 15.0 10249.C020.24SS 14.0 10249.C020.26SD 7.0 10249.C031.14SS 14.0 10249.C032.11SD 6.0 10249.C044.15SS 24.0 10249.C055.02SD 2.0 10249.C002.01SS 5.0 10249.C031.09SS 6.5 10249.C032.09SS 3.0 10249.C034.16SS 16.0 10249.C036.13SS 11.0 10249.C001.14SS 2.5 10249.C004.02SS 0.0 10249.C007.11SS 1.5 10249.C007.15SS 16.5 10249.C007.16SS 5.0 10249.C010.09SS 8.0 10249.C011.07SS 8.5 10249.C012.07SS 1.5 10249.C016.04SS 4.0 10249.C017.05SS 6.5 10249.C030.05SS 0.5 10249.C034.03SS 4.0 10249.C002.16SS 19.0 10249.C005.16SS 17.0 10249.C014.12SS 9.5 10249.C016.13SS 23.0 10249.C033.10SS 5.5 10249.C005.21SS 26.0 10249.C012.21SS 16.0 10249.C030.19SD 20.0 10249.C053.03SD 3.0 10249.C053.03SS 2.5 10249.C008.15SS 6.5 10249.C030.18SS 23.0 10249.C033.19SS 22.0 10249.C001.15SS 16.5 10249.C002.01SS.r 9.0 10249.C004.04SS 5.5 10249.C005.13SS 13.5 10249.C016.11SS 3.0 10249.C024.08SS 3.0 10249.C031.05SS 7.5 10249.C031.06SS 7.5 10249.C037.07SS 20.0 10249.C042.07SS 9.0 10249.C011.14SS 18.5 10249.C014.15SS 2.5 10249.C018.13SS 14.0 10249.C020.19SS 18.0 10249.C025.14SS 7.0 10249.C001.34SS 27.0 10249.C001.36SS 22.0 10249.C007.22SS 20.0 10249.C012.21SD 24.0 10249.C022.18SD 21.0 10249.C022.18SS 22.0 10249.C030.14SS 19.5 10249.C001.01SS 1.5 10249.C018.16SS 19.0 10249.C044.17SS 28.0 10249.C009.02SS 7.0 10249.C014.08SS 9.0 10249.C020.13SS 4.5 10249.C025.10SS 12.0 10249.C001.04SS 4.5 10249.C030.13SS 16.0 10249.C016.14SS 23.0 10249.C001.34SD 23.0 10249.C001.36SD 25.0 10249.C005.21SD 24.0 10249.C014.16SS 17.0 10249.C020.25SD 17.0 10249.C020.26SS 18.0 10249.C025.14SD 12.0 10249.C032.17SS 22.0 10249.C045.05SD 6.0 10249.C046.06SD 15.0 10249.C046.06SS 15.0 10249.C055.02SS 3.0 10249.C005.22SS 27.0 10249.C011.16SS 18.0 10249.C014.21SS 19.0 10249.C018.17SS 16.0 10249.C022.20SS 14.0 10249.C033.16SS 15.0 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/true_targets.tsv000066400000000000000000000003261462552620600273100ustar00rootroot00000000000000sample-id delivery 10249.C041.08SS Vaginal 10249.C055.08SS Cesarean 10249.C027.07SS Vaginal 10249.C042.07SS Vaginal 10249.C005.08SS Cesarean 10249.C056.09SS Cesarean 10249.C035.07SD Vaginal 10249.C001.10SS Vaginal q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/vaw.qza000066400000000000000000000177321462552620600253650ustar00rootroot00000000000000PK+ICP}[53,861451cc-c250-43fc-818a-ddc2159dbe25/VERSION uU0J,J,KR0J+JM-/ʶR0203436K7NIK23PK+ICPb`2861451cc-c250-43fc-818a-ddc2159dbe25/metadata.yaml+-LR03415LNM62551NKֵ0HMII624LIJ52*,HRpKM,)-J ILIv+J-,MKJ/M,Rp 324p,r-PK+ICP2861451cc-c250-43fc-818a-ddc2159dbe25/checksums.md5J1 F}pFA}&0pgFUn%' gt%" 4y}|{x"T)^KJZѻfk0fN:>hLQ, Z4>/N1YUn:EN)Eb#G|__v?\>@}>m+n_ޮi $_ ^\B DIZLL+9d|u!iR V"Ip՗ >E(PYɡv"Kcv 'Lx`*Igzy{{)؛Utj"XXI'>3tʤDa| 'Ӧw +wF`<^^.}Az9\Ʈ۳dr]ZgK훰Wx[v&cL⾙'ԛ;#>6J$Bh fZXR;tQ]V$!k QȌx tDZjk`hPx 6!{#:Y쬿s5[ 5 .OCs3ksΠ۞QL^ߐ>?y w{HFu7MVߤb>]%   k>!`gAj^>/X3xF+T0.sIf'fQz='Cʴ&"6R{[L}qm¾Lox_z}K'u1 g8 PfW# Ҫk-wq@jZ[b"jtVFƵ'*W]ŲR2U~!9KѹMu=УwBu}O $DAPk~\j}C=ub[/>#do+kBna%gJwW~4& T59J:\Dɑ/TwZK+kfG&7I6y@ڶD8~S[~br]nŶoxB)XnV77?\5x㚽GUdu>ɕ;]Ţ/KvHoܯ=)m m)XYm H~䟍cUK+w%@Aq(UνDAwIO<Pġl4A9- 1O-22;5O0O?! %y Y>QW]ƾDYzDyrDA`Ob<I I1:!-5[<\H*֯t]wRט.oI\ى{md֯Q.ӭ(,~^Q L)^^$ż3ǧg/`/-F45d{3e䣚a|TA:iف.R=GdP>P;O)?|A:O @T:*  O rz9|>ܘw1(M_zC_y|A9'5Kwϓf7fwz:o} Y/[Xj՗R6<|=^^j1w 6VSvhԖuGoH ҕ;₤&GR)];qKY%uGFL3lj+0=*֤ǙSY{fgdwVEgCDolC-`Ē&ɎHzWґ~p1ϐ#צ!Qkk1|C|%yf̉Nmu=v (k$jl~VI1V+*CXKP/oButyBΙPȚ2q>d-&F)!̏xS) o1*}JU' oM9E$sۖ9 =zD}$mT95JU|C;D)E>6D:1:eL^]D&gMG1ZZYSڨ>Ͷ>@8nkdQq[ҼIk1AuTmCaW-~f9D^6(EzWL]q@6?q//ѺaUUi~2H2!mQfl .q~\i aw^ļDlj1ՄEٕGu&Ѭ?|.ȹ53i 0^Yϯc1ܬ_;;xroWq|gF]˳^߫xy8-{绽JZrxvr3Om0O)n\$ss[RO7M̟LWqxqycjg(ߍai&?1Dt¹ΰb;}{?PT.iQ'Jawqôju*Xۙc!/(1Q?EJ0$΅ 4z#"m'e6,S ~ &ё'$DPK+ICPd B861451cc-c250-43fc-818a-ddc2159dbe25/provenance/action/action.yamlY[o~ϯPtte]`E( Jdƒm^l݇Cf\?RA<RM&yK4DO/ò7(NJz1q00p8 a?ax].EtϤˁ!e4ʼr\Ю"< E(k8 V+V:Ra.J:䄶rÇ8β-di 0J U.P喘q-*FUktbD*P>}O@˻<9?a J|qP(%ab|w7~/ڴR΄Ѯŝ9t !=r Wwj(2 ȗ ޽'TGOs+44ؓF!/wUӓIGg^(;MGr |22Y>d-%P me亼W`1&Fgܕo P\q-uewt :׆xz ;Vp8yz%s]]|՗EYi\b4S}&G?/ ep< lv3>/,TWz`䀯rug;,.ښf?'Y:L+aYyb/,q;\?y3,ɘm7p1H30 D~ Z?}$ԏo+dD>q%[y JSh%Ԓ|@ASgZԤʬGc[`7G9 WW`/:Q:9zS># *8ƨi#;`(+<`=\ݖ1<9ױ9aϵaZ#PB'yRH1t!ωqsNI[[}'MC/rZ @G=rf H%Z +0K/m*q̥074ĘWcP?¬NY;*ӓF EXϐ)\+4緷Zt&t-JvsRhi̘m0SEr5 + G&N|[?J#k\%IKe'ddr ^e*L; ᴹ, 0h ]xL@@Pp[$cCN8t/H^pI2K8y>sߐJYEͼ-2`5s!yc+e7P )nN=tGFEyTn#_/T0O݊Td-B\p QfcOj`e'-(3P5&vN?HL.YԌȀ繮%nX %KU&n߇2p 6i}n,LZAeXf'Dp_U*e!gT(v.􄏺NS_7ks7w]C?zHL96zOD$I{l!~-).}/ ]=@QM)^chf/T$]&x @`CSX SbXĽ>(#ƹYP'ع#Ng2t5.u6GJ20'MWQKS o+ ljֶrCK = PK+ICP}[53,861451cc-c250-43fc-818a-ddc2159dbe25/VERSIONPK+ICPb`2861451cc-c250-43fc-818a-ddc2159dbe25/metadata.yamlPK+ICP21861451cc-c250-43fc-818a-ddc2159dbe25/checksums.md5PK+ICPc5<S861451cc-c250-43fc-818a-ddc2159dbe25/data/feature-table.biomPK+ICP}[537861451cc-c250-43fc-818a-ddc2159dbe25/provenance/VERSIONPK+ICPb`=l 861451cc-c250-43fc-818a-ddc2159dbe25/provenance/metadata.yamlPK+ICP+d_l=) 861451cc-c250-43fc-818a-ddc2159dbe25/provenance/citations.bibPK+ICPd B[861451cc-c250-43fc-818a-ddc2159dbe25/provenance/action/action.yamlPK/q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/vaw.txt000066400000000000000000000001151462552620600253740ustar00rootroot00000000000000#SampleID Column Sample1 a Sample2 a Sample3 a Sample4 b Sample5 b Sample6 b q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/data/vaw_importance.tsv000066400000000000000000000002421462552620600276130ustar00rootroot00000000000000 importance GG_OTU_1 0.084698283208355865 GG_OTU_2 0.077601184175696976 GG_OTU_3 0.065702517505059144 GG_OTU_4 0.061718558716901406 GG_OTU_5 0.028086160290024458 q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/test_actions.py000066400000000000000000000200551462552620600262030ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import os import pandas as pd import pandas.testing as pdt import numpy as np import biom import qiime2 from qiime2.plugins import sample_classifier from q2_sample_classifier.tests.test_base_class import \ SampleClassifierTestPluginBase from q2_sample_classifier.tests.test_estimators import SampleEstimatorTestBase from q2_sample_classifier.classify import summarize class NowLetsTestTheActions(SampleClassifierTestPluginBase): def setUp(self): super().setUp() md = pd.Series(['a', 'a', 'b', 'b', 'b'], index=['a', 'b', 'c', 'd', 'e'], name='bugs') md.index.name = 'SampleID' self.md = qiime2.CategoricalMetadataColumn(md) tab = biom.Table( np.array([[3, 6, 7, 3, 6], [3, 4, 5, 6, 2], [8, 6, 4, 1, 0], [8, 6, 4, 1, 0], [8, 6, 4, 1, 0]]), observation_ids=['v', 'w', 'x', 'y', 'z'], sample_ids=['a', 'b', 'c', 'd', 'e']) self.tab = qiime2.Artifact.import_data('FeatureTable[Frequency]', tab) md2 = pd.DataFrame({'trash': ['a', 'a', 'b', 'b', 'b', 'junk'], 'floats': [0.1, 0.1, 1.3, 1.8, 1000.1, 0.1], 'ints': [0, 1, 2, 2, 2, 0], 'nans': [1, 1, 2, 2, np.nan, np.nan], 'negatives': [-7, -3, -1.2, -4, -9, -1]}, index=['a', 'b', 'c', 'd', 'e', 'peanut']) md2.index.name = 'SampleID' self.md2 = qiime2.Metadata(md2) # let's make sure the function runs w/o errors and that the correct # transformers are in place (see issue 114) def test_action_split_table(self): res = sample_classifier.actions.split_table( self.tab, self.md, test_size=0.5) y_train = res.training_targets.view(pd.Series) y_test = res.test_targets.view(pd.Series) # test whether extracted target is correct self.assertEqual(y_train.name, 'bugs') # test if complete target column is covered y_all = pd.concat([y_train, y_test]).sort_index() y_all.index.name = 'SampleID' pdt.assert_series_equal(y_all, self.md._series) def test_metatable(self): exp = biom.Table( np.array([[0.1, 0.1, 1.3, 1.8, 1000.1, 0.1], [0, 1, 2, 2, 2, 0]]), observation_ids=['floats', 'ints'], sample_ids=['a', 'b', 'c', 'd', 'e', 'peanut']) res, = sample_classifier.actions.metatable( self.md2, missing_values='drop_features') report = res.view(biom.Table).descriptive_equality(exp) self.assertIn('Tables appear equal', report, report) def test_metatable_missing_error(self): with self.assertRaisesRegex(ValueError, "missing values"): sample_classifier.actions.metatable( self.md2, missing_values='error') def test_metatable_drop_samples(self): exp = biom.Table( np.array([[3, 6, 7, 3], [3, 4, 5, 6], [8, 6, 4, 1], [8, 6, 4, 1], [8, 6, 4, 1], [0.1, 0.1, 1.3, 1.8], [0, 1, 2, 2], [1, 1, 2, 2]]), observation_ids=['v', 'w', 'x', 'y', 'z', 'floats', 'ints', 'nans'], sample_ids=['a', 'b', 'c', 'd']) res, = sample_classifier.actions.metatable( self.md2, self.tab, missing_values='drop_samples') report = res.view(biom.Table).descriptive_equality(exp) self.assertIn('Tables appear equal', report, report) def test_metatable_fill_na(self): exp = biom.Table( np.array([[3, 6, 7, 3, 6], [3, 4, 5, 6, 2], [8, 6, 4, 1, 0], [8, 6, 4, 1, 0], [8, 6, 4, 1, 0], [0.1, 0.1, 1.3, 1.8, 1000.1], [0, 1, 2, 2, 2], [1., 1., 2., 2., 0.]]), observation_ids=['v', 'w', 'x', 'y', 'z', 'floats', 'ints', 'nans'], sample_ids=['a', 'b', 'c', 'd', 'e']) res, = sample_classifier.actions.metatable( self.md2, self.tab, missing_values='fill') report = res.view(biom.Table).descriptive_equality(exp) self.assertIn('Tables appear equal', report, report) def test_metatable_with_merge(self): exp = biom.Table( np.array([[3, 6, 7, 3, 6], [3, 4, 5, 6, 2], [8, 6, 4, 1, 0], [8, 6, 4, 1, 0], [8, 6, 4, 1, 0], [0.1, 0.1, 1.3, 1.8, 1000.1], [0, 1, 2, 2, 2]]), observation_ids=['v', 'w', 'x', 'y', 'z', 'floats', 'ints'], sample_ids=['a', 'b', 'c', 'd', 'e']) res, = sample_classifier.actions.metatable( self.md2, self.tab, missing_values='drop_features') report = res.view(biom.Table).descriptive_equality(exp) self.assertIn('Tables appear equal', report, report) def test_metatable_with_merge_successful_inner_join(self): exp = biom.Table( np.array([[3, 6, 7, 3], [3, 4, 5, 6], [8, 6, 4, 1], [8, 6, 4, 1], [8, 6, 4, 1], [0.1, 0.1, 1.3, 1.8], [0, 1, 2, 2], [1., 1., 2., 2.]]), observation_ids=['v', 'w', 'x', 'y', 'z', 'floats', 'ints', 'nans'], sample_ids=['a', 'b', 'c', 'd']) res, = sample_classifier.actions.metatable( self.md2.filter_ids(['a', 'b', 'c', 'd']), self.tab, missing_values='error') report = res.view(biom.Table).descriptive_equality(exp) self.assertIn('Tables appear equal', report, report) def test_metatable_with_merge_error_inner_join(self): with self.assertRaisesRegex(ValueError, "Missing samples"): sample_classifier.actions.metatable( self.md2.filter_ids(['a', 'b', 'c', 'd']), self.tab, missing_samples='error', missing_values='drop_samples') def test_metatable_empty_metadata_after_drop_all_unique(self): with self.assertRaisesRegex( ValueError, "All metadata"): # are belong to us sample_classifier.actions.metatable( self.md2.filter_ids(['b', 'c']), self.tab, missing_values='drop_samples', drop_all_unique=True) def test_metatable_no_samples_after_filtering(self): junk_md = pd.DataFrame( {'trash': ['a', 'a', 'b', 'b', 'b', 'junk'], 'floats': [np.nan, np.nan, np.nan, 1.8, 1000.1, 0.1], 'ints': [0, 1, 2, np.nan, 2, 0], 'nans': [1, 1, 2, 2, np.nan, np.nan], 'negatives': [-7, -4, -1.2, -4, -9, -1]}, index=['a', 'b', 'c', 'd', 'e', 'peanut']) junk_md.index.name = 'SampleID' junk_md = qiime2.Metadata(junk_md) with self.assertRaisesRegex(ValueError, "All metadata samples"): sample_classifier.actions.metatable( junk_md, missing_values='drop_samples') # make sure summarize visualizer works and that rfe_scores are stored properly class TestSummarize(SampleEstimatorTestBase): def test_summary_with_rfecv(self): summarize(self.temp_dir.name, self.pipeline) self.assertTrue('rfe_plot.pdf' in os.listdir(self.temp_dir.name)) self.assertTrue('rfe_plot.png' in os.listdir(self.temp_dir.name)) self.assertTrue('rfe_scores.tsv' in os.listdir(self.temp_dir.name)) def test_summary_without_rfecv(self): # nuke the rfe_scores to test the other branch of _summarize_estimator del self.pipeline.rfe_scores summarize(self.temp_dir.name, self.pipeline) self.assertFalse('rfe_plot.pdf' in os.listdir(self.temp_dir.name)) self.assertFalse('rfe_plot.png' in os.listdir(self.temp_dir.name)) self.assertFalse('rfe_scores.tsv' in os.listdir(self.temp_dir.name)) q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/test_base_class.py000066400000000000000000000016231462552620600266420ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import tempfile import pkg_resources from qiime2.plugin.testing import TestPluginBase class SampleClassifierTestPluginBase(TestPluginBase): package = 'q2_sample_classifier.tests' def setUp(self): super().setUp() self.temp_dir = tempfile.TemporaryDirectory( prefix='q2-sample-classifier-test-temp-') def tearDown(self): self.temp_dir.cleanup() def get_data_path(self, filename): return pkg_resources.resource_filename(self.package, 'data/%s' % filename) q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/test_classifier.py000066400000000000000000000250701462552620600266710ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- from warnings import filterwarnings import pandas as pd import numpy as np import skbio from sklearn.ensemble import RandomForestClassifier from sklearn.feature_selection import RFECV import pandas.testing as pdt import biom import qiime2 from qiime2.plugins import sample_classifier from q2_sample_classifier.visuals import ( _custom_palettes, _roc_palette, _roc_per_class, _roc_micro_average, _roc_macro_average, _binarize_labels, _generate_roc_plots) from q2_sample_classifier.utilities import _extract_rfe_scores from q2_sample_classifier.tests.test_base_class import \ SampleClassifierTestPluginBase filterwarnings("ignore", category=UserWarning) filterwarnings("ignore", category=Warning) class TestRFEExtractor(SampleClassifierTestPluginBase): def setUp(self): super().setUp() np.random.seed(0) self.X = np.random.rand(50, 20) self.y = np.random.randint(0, 2, 50) self.exp1 = pd.Series([ 0.4999999999999999, 0.52, 0.52, 0.5399999999999999, 0.44000000000000006, 0.52, 0.4600000000000001, 0.5599999999999998, 0.52, 0.52, 0.5, 0.5399999999999999, 0.54, 0.5599999999999999, 0.47999999999999987, 0.6199999999999999, 0.5399999999999999, 0.5, 0.4999999999999999, 0.45999999999999996], index=pd.Index(range(1, 21)), name='Accuracy') self.exp2 = pd.Series([ 0.5000000000000001, 0.52, 0.48, 0.5599999999999998, 0.5, 0.5799999999999998, 0.54, 0.4600000000000001, 0.6, 0.45999999999999996, 0.45999999999999996], index=pd.Index([1] + [i for i in range(2, 21, 2)]), name='Accuracy') self.exp3 = pd.Series({1: 0.4600000000000001, 20: 0.45999999999999996}, name='Accuracy') def extract_rfe_scores_template(self, steps, expected): selector = RFECV(RandomForestClassifier( random_state=123, n_estimators=2), step=steps, cv=10) selector = selector.fit(self.X, self.y.ravel()) pdt.assert_series_equal( _extract_rfe_scores(selector), expected) def test_extract_rfe_scores_step_int_one(self): self.extract_rfe_scores_template(1, self.exp1) def test_extract_rfe_scores_step_float_one(self): self.extract_rfe_scores_template(0.05, self.exp1) def test_extract_rfe_scores_step_int_two(self): self.extract_rfe_scores_template(2, self.exp2) def test_extract_rfe_scores_step_float_two(self): self.extract_rfe_scores_template(0.1, self.exp2) def test_extract_rfe_scores_step_full_range(self): self.extract_rfe_scores_template(20, self.exp3) def test_extract_rfe_scores_step_out_of_range(self): # should be equal to full_range self.extract_rfe_scores_template(21, self.exp3) # test classifier pipelines succeed on binary data class TestBinaryClassification(SampleClassifierTestPluginBase): def setUp(self): super().setUp() self.md = qiime2.CategoricalMetadataColumn(pd.Series( ['a', 'a', 'a', 'b', 'b', 'b'], index=pd.Index([c for c in 'abcdef'], name='id'), name='foo')) tab = biom.Table(np.array( [[13, 26, 37, 3, 6, 1], [33, 24, 23, 5, 6, 2], [38, 26, 33, 4, 1, 0], [3, 2, 1, 22, 25, 31], [2, 1, 3, 44, 46, 42]]), observation_ids=[c for c in 'vwxyz'], sample_ids=[c for c in 'abcdef']) self.tab = qiime2.Artifact.import_data('FeatureTable[Frequency]', tab) dist = skbio.DistanceMatrix.from_iterable( iterable=[1, 16, 2, 1, 16, 17], metric=lambda x, y: abs(y-x), keys=[c for c in 'abcdef'] ) self.dist = qiime2.Artifact.import_data('DistanceMatrix', dist) # we will make sure predictions are correct, but no need to validate # other outputs, which are tested elsewhere. def test_classify_samples_binary(self): res = sample_classifier.actions.classify_samples( table=self.tab, metadata=self.md, test_size=0.3, cv=1, n_estimators=2, n_jobs=1, random_state=123, parameter_tuning=False, optimize_feature_selection=False) exp = pd.Series(['a', 'b'], name='prediction', index=pd.Index(['c', 'f'], name='id')) pdt.assert_series_equal(exp, res[2].view(pd.Series)) def test_classify_samples_ncv_binary(self): res = sample_classifier.actions.classify_samples_ncv( table=self.tab, metadata=self.md, cv=3, n_estimators=2, n_jobs=1, random_state=123, parameter_tuning=False) exp = pd.Series([c for c in 'ababab'], name='prediction', index=pd.Index([i for i in 'aebdcf'], name='id')) pdt.assert_series_equal(exp, res[0].view(pd.Series)) def test_classify_samples_dist_binary(self): res = sample_classifier.actions.classify_samples_from_dist( distance_matrix=self.dist, metadata=self.md, k=2, cv=3, n_jobs=1, random_state=123) exp = pd.Series([c for c in 'abaaaa'], name='0', index=pd.Index([i for i in 'abcdef'], name='id')) pdt.assert_series_equal( exp.sort_index(), res[0].view(pd.Series).sort_index() ) class TestROC(SampleClassifierTestPluginBase): def setUp(self): super().setUp() self.md = np.array( [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1]]) np.random.seed(0) probs = np.random.rand(20, 3) # probabilities should sum to 1 for each sample self.probs = np.apply_along_axis( lambda x: x / x.sum(), axis=1, arr=probs) self.exp_fpr = {0: [0., 0.07692308, 0.46153846, 0.46153846, 0.76923077, 0.76923077, 0.84615385, 0.84615385, 1., 1.], 1: [0., 0., 0.15384615, 0.15384615, 0.61538462, 0.61538462, 0.69230769, 0.69230769, 1., 1.], 2: [0., 0.07142857, 0.07142857, 0.14285714, 0.14285714, 0.78571429, 0.78571429, 0.92857143, 0.92857143, 1.]} self.exp_tdr = {0: [0., 0., 0., 0.57142857, 0.57142857, 0.71428571, 0.71428571, 0.85714286, 0.85714286, 1.], 1: [0., 0.14285714, 0.14285714, 0.28571429, 0.28571429, 0.57142857, 0.57142857, 0.85714286, 0.85714286, 1.], 2: [0., 0., 0.16666667, 0.16666667, 0.5, 0.5, 0.66666667, 0.66666667, 1., 1.]} self.exp_roc_auc = {0: 0.3626373626373626, 1: 0.4615384615384615, 2: 0.49999999999999994} # this test confirms that all palettes load properly. def test_roc_palette(self): [_roc_palette(p, 3) for p in _custom_palettes().keys()] def test_roc_per_class(self): fpr, tdr, roc_auc = _roc_per_class(self.md, self.probs, [0, 1, 2]) for d, e in zip([fpr, tdr, roc_auc], [self.exp_fpr, self.exp_tdr, self.exp_roc_auc]): for c in [0, 1, 2]: np.testing.assert_array_almost_equal(d[c], e[c]) def test_roc_micro_average(self): fpr, tdr, roc_auc = _roc_micro_average( self.md, self.probs, self.exp_fpr, self.exp_tdr, self.exp_roc_auc) np.testing.assert_array_almost_equal(fpr['micro'], np.array( [0., 0.025, 0.025, 0.075, 0.075, 0.1, 0.1, 0.225, 0.225, 0.275, 0.275, 0.475, 0.475, 0.575, 0.575, 0.6, 0.6, 0.65, 0.65, 0.675, 0.675, 0.725, 0.725, 0.75, 0.75, 0.825, 0.825, 0.925, 0.925, 1., 1.])) np.testing.assert_array_almost_equal(tdr['micro'], np.array( [0., 0., 0.05, 0.05, 0.1, 0.1, 0.15, 0.15, 0.2, 0.2, 0.25, 0.25, 0.35, 0.35, 0.4, 0.4, 0.45, 0.45, 0.5, 0.5, 0.55, 0.55, 0.6, 0.6, 0.75, 0.75, 0.8, 0.8, 0.95, 0.95, 1.])) self.assertAlmostEqual(roc_auc['micro'], 0.41374999999999995) def test_roc_macro_average(self): fpr, tdr, roc_auc = _roc_macro_average( self.exp_fpr, self.exp_tdr, self.exp_roc_auc, [0, 1, 2]) np.testing.assert_array_almost_equal(fpr['macro'], np.array( [0., 0.07142857, 0.07692308, 0.14285714, 0.15384615, 0.46153846, 0.61538462, 0.69230769, 0.76923077, 0.78571429, 0.84615385, 0.92857143, 1.])) np.testing.assert_array_almost_equal(tdr['macro'], np.array( [0.04761905, 0.1031746, 0.1031746, 0.21428571, 0.26190476, 0.45238095, 0.54761905, 0.64285714, 0.69047619, 0.74603175, 0.7936508, 0.90476191, 1.])) self.assertAlmostEqual(roc_auc['macro'], 0.49930228548098726) # Proves that the ROC nuts + bolts work if predictions does not have all # the classes present in probabilities. This will occur if there are many # classes or few samples and the data are not stratified: # https://github.com/qiime2/q2-sample-classifier/issues/171 def test_binarize_and_roc_on_missing_classes(self): # seven samples with only 4 classes (adeh) of 8 possible classes # (abcdefgh) represented md = pd.Series([i for i in 'hedhadd']) # array of 7 samples X 8 classes # the values do not matter, only the labels probs = pd.DataFrame(np.random.rand(7, 8), columns=[i for i in 'abcdefgh']) _generate_roc_plots(md, probs, 'GreenBlue') class TestBinarize(SampleClassifierTestPluginBase): def setUp(self): super().setUp() def test_binarize_labels_binary(self): md = pd.Series([c for c in 'aabbaa']) labels = _binarize_labels(md, ['a', 'b']) exp = np.array([[1, 0], [1, 0], [0, 1], [0, 1], [1, 0], [1, 0]]) np.testing.assert_array_equal(exp, labels) def test_binarize_labels_multiclass(self): md = pd.Series([c for c in 'abcabc']) labels = _binarize_labels(md, ['a', 'b', 'c']) exp = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 0, 1]]) np.testing.assert_array_equal(exp, labels) q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/test_estimators.py000066400000000000000000000715071462552620600267450ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import os import pandas as pd import pandas.testing as pdt import biom import shutil import json import numpy as np from sklearn.metrics import mean_squared_error, accuracy_score from sklearn.ensemble import AdaBoostClassifier from sklearn.tree import DecisionTreeClassifier, ExtraTreeClassifier from sklearn.feature_extraction import DictVectorizer from sklearn.pipeline import Pipeline import skbio import qiime2 from q2_types.feature_table import (FeatureTable, PercentileNormalized) from qiime2.plugins import sample_classifier from q2_sample_classifier.tests.test_base_class import \ SampleClassifierTestPluginBase from q2_sample_classifier.classify import ( regress_samples_ncv, classify_samples_ncv, fit_classifier, fit_regressor, detect_outliers, split_table, predict_classification, predict_regression) from q2_sample_classifier.utilities import ( _set_parameters_and_estimator, _train_adaboost_base_estimator, _match_series_or_die, _extract_features) from q2_sample_classifier import ( SampleEstimatorDirFmt, PickleFormat) class SampleEstimatorTestBase(SampleClassifierTestPluginBase): package = 'q2_sample_classifier.tests' def setUp(self): super().setUp() def _load_biom(table_fp): table_fp = self.get_data_path(table_fp) table = qiime2.Artifact.load(table_fp) table = table.view(biom.Table) return table def _load_cmc(md_fp, column): md_fp = self.get_data_path(md_fp) md = pd.read_csv(md_fp, sep='\t', header=0, index_col=0) md = qiime2.CategoricalMetadataColumn(md[column]) return md table_chard_fp = _load_biom('chardonnay.table.qza') mdc_chard_fp = _load_cmc('chardonnay.map.txt', 'Region') pipeline, importances = fit_classifier( table_chard_fp, mdc_chard_fp, random_state=123, n_estimators=2, n_jobs=1, optimize_feature_selection=True, parameter_tuning=True, missing_samples='ignore') transformer = self.get_transformer( Pipeline, SampleEstimatorDirFmt) self._sklp = transformer(pipeline) sklearn_pipeline = self._sklp.sklearn_pipeline.view(PickleFormat) self.sklearn_pipeline = str(sklearn_pipeline) self.pipeline = pipeline def _custom_setup(self, version): with open(os.path.join(self.temp_dir.name, 'sklearn_version.json'), 'w') as fh: fh.write(json.dumps({'sklearn-version': version})) shutil.copy(self.sklearn_pipeline, self.temp_dir.name) return SampleEstimatorDirFmt( self.temp_dir.name, mode='r') class EstimatorsTests(SampleClassifierTestPluginBase): def setUp(self): super().setUp() def _load_biom(table_fp): table_fp = self.get_data_path(table_fp) table = qiime2.Artifact.load(table_fp) table = table.view(biom.Table) return table def _load_md(md_fp): md_fp = self.get_data_path(md_fp) md = pd.read_csv(md_fp, sep='\t', header=0, index_col=0) md = qiime2.Metadata(md) return md def _load_nmc(md_fp, column): md_fp = self.get_data_path(md_fp) md = pd.read_csv(md_fp, sep='\t', header=0, index_col=0) md = qiime2.NumericMetadataColumn(md[column]) return md def _load_cmc(md_fp, column): md_fp = self.get_data_path(md_fp) md = pd.read_csv(md_fp, sep='\t', header=0, index_col=0) md = qiime2.CategoricalMetadataColumn(md[column]) return md self.table_chard_fp = _load_biom('chardonnay.table.qza') self.md_chard_fp = _load_md('chardonnay.map.txt') self.mdc_chard_fp = _load_cmc('chardonnay.map.txt', 'Region') self.table_ecam_fp = _load_biom('ecam-table-maturity.qza') self.md_ecam_fp = _load_md('ecam_map_maturity.txt') self.mdc_ecam_fp = _load_nmc('ecam_map_maturity.txt', 'month') self.exp_imp = pd.read_csv( self.get_data_path('importance.tsv'), sep='\t', header=0, index_col=0, names=['feature', 'importance']) self.exp_pred = pd.read_csv( self.get_data_path('predictions.tsv'), sep='\t', header=0, index_col=0).squeeze('columns') index = pd.Index(['A', 'B', 'C', 'D'], name='id') self.table_percnorm = qiime2.Artifact.import_data( FeatureTable[PercentileNormalized], pd.DataFrame( [[20.0, 20.0, 50.0, 10.0], [10.0, 10.0, 70.0, 10.0], [90.0, 8.0, 1.0, 1.0], [30.0, 15.0, 20.0, 35.0]], index=index, columns=['feat1', 'feat2', 'feat3', 'feat4'])).view(biom.Table) self.mdc_percnorm = qiime2.CategoricalMetadataColumn( pd.Series(['X', 'X', 'Y', 'Y'], index=index, name='name')) # test feature extraction def test_extract_features(self): table = self.table_ecam_fp dicts = _extract_features(table) dv = DictVectorizer() dv.fit(dicts) features = table.ids('observation') self.assertEqual(set(dv.get_feature_names_out()), set(features)) self.assertEqual(len(dicts), len(table.ids())) for dict_row, (table_row, _, _) in zip(dicts, table.iter()): for feature, count in zip(features, table_row): if count == 0: self.assertTrue(feature not in dict_row) else: self.assertEqual(dict_row[feature], count) def test_classify_samples_from_dist(self): # -- setup -- # # 1,2 are a group, 3,4 are a group sample_ids = ('f1', 'f2', 's1', 's2') distance_matrix = skbio.DistanceMatrix([ [0, 1, 4, 4], [1, 0, 4, 4], [4, 4, 0, 1], [4, 4, 1, 0], ], ids=sample_ids) dm = qiime2.Artifact.import_data('DistanceMatrix', distance_matrix) categories = pd.Series(('skinny', 'skinny', 'fat', 'fat'), index=sample_ids[::-1], name='body_mass') categories.index.name = 'SampleID' metadata = qiime2.CategoricalMetadataColumn(categories) # -- test -- # res = sample_classifier.actions.classify_samples_from_dist( distance_matrix=dm, metadata=metadata, k=1, cv=3, random_state=123 ) pred = res[0].view(pd.Series).sort_values() expected = pd.Series(('fat', 'skinny', 'fat', 'skinny'), index=['f1', 's1', 'f2', 's2']) not_expected = pd.Series(('fat', 'fat', 'fat', 'skinny'), index=sample_ids) # order matters for pd.Series.equals() self.assertTrue(expected.sort_index().equals(pred.sort_index())) self.assertFalse(not_expected.sort_index().equals(pred.sort_index())) def test_classify_samples_from_dist_with_group_of_single_item(self): # -- setup -- # # 1 is a group, 2,3,4 are a group sample_ids = ('f1', 's1', 's2', 's3') distance_matrix = skbio.DistanceMatrix([ [0, 2, 3, 3], [2, 0, 1, 1], [3, 1, 0, 1], [3, 1, 1, 0], ], ids=sample_ids) dm = qiime2.Artifact.import_data('DistanceMatrix', distance_matrix) categories = pd.Series(('fat', 'skinny', 'skinny', 'skinny'), index=sample_ids, name='body_mass') categories.index.name = 'SampleID' metadata = qiime2.CategoricalMetadataColumn(categories) # -- test -- # res = sample_classifier.actions.classify_samples_from_dist( distance_matrix=dm, metadata=metadata, k=1, cv=3, random_state=123 ) pred = res[0].view(pd.Series) expected = pd.Series(('skinny', 'skinny', 'skinny', 'skinny'), index=sample_ids) self.assertTrue(expected.sort_index().equals(pred.sort_index())) def test_2nn(self): # -- setup -- # # 2 nearest neighbors of each sample are # f1: s1, s2 (classified as skinny) # s1: f1, s2 (closer to f1 so fat) # s2: f1, (s1 or s3) (closer to f1 so fat) # s3: s1, s2 (skinny) sample_ids = ('f1', 's1', 's2', 's3') distance_matrix = skbio.DistanceMatrix([ [0, 2, 1, 5], [2, 0, 3, 4], [1, 3, 0, 3], [5, 4, 3, 0], ], ids=sample_ids) dm = qiime2.Artifact.import_data('DistanceMatrix', distance_matrix) categories = pd.Series(('fat', 'skinny', 'skinny', 'skinny'), index=sample_ids, name='body_mass') categories.index.name = 'SampleID' metadata = qiime2.CategoricalMetadataColumn(categories) # -- test -- # res = sample_classifier.actions.classify_samples_from_dist( distance_matrix=dm, metadata=metadata, k=2, cv=3, random_state=123 ) pred = res[0].view(pd.Series) expected = pd.Series(('skinny', 'fat', 'fat', 'skinny'), index=sample_ids) self.assertTrue(expected.sort_index().equals(pred.sort_index())) # test that each classifier works and delivers an expected accuracy result # when a random seed is set. def test_classifiers(self): for classifier in ['RandomForestClassifier', 'ExtraTreesClassifier', 'GradientBoostingClassifier', 'AdaBoostClassifier[DecisionTree]', 'AdaBoostClassifier[ExtraTrees]', 'LinearSVC', 'SVC', 'KNeighborsClassifier']: table_fp = self.get_data_path('chardonnay.table.qza') table = qiime2.Artifact.load(table_fp) res = sample_classifier.actions.classify_samples( table=table, metadata=self.mdc_chard_fp, test_size=0.5, cv=1, n_estimators=10, n_jobs=1, estimator=classifier, random_state=123, parameter_tuning=False, optimize_feature_selection=False, missing_samples='ignore') pred = res[2].view(pd.Series) pred, truth = _match_series_or_die( pred, self.mdc_chard_fp.to_series(), 'ignore') accuracy = accuracy_score(truth, pred) self.assertAlmostEqual( accuracy, seeded_results[classifier], places=4, msg='Accuracy of %s classifier was %f, but expected %f' % ( classifier, accuracy, seeded_results[classifier])) # test if training classifier with pipeline classify_samples raises # warning when test_size = 0.0 def test_classify_samples_w_all_train_set(self): with self.assertWarnsRegex(Warning, "not representative of " "your model's performance"): table_fp = self.get_data_path('chardonnay.table.qza') table = qiime2.Artifact.load(table_fp) sample_classifier.actions.classify_samples( table=table, metadata=self.mdc_chard_fp, test_size=0.0, cv=1, n_estimators=10, n_jobs=1, estimator='RandomForestClassifier', random_state=123, parameter_tuning=False, optimize_feature_selection=False, missing_samples='ignore') # test that the plugin methods/visualizers work def test_regress_samples_ncv(self): y_pred, importances = regress_samples_ncv( self.table_ecam_fp, self.mdc_ecam_fp, random_state=123, n_estimators=2, n_jobs=1, stratify=True, parameter_tuning=True, missing_samples='ignore') def test_classify_samples_ncv(self): y_pred, importances, probabilities = classify_samples_ncv( self.table_chard_fp, self.mdc_chard_fp, random_state=123, n_estimators=2, n_jobs=1, missing_samples='ignore') # test reproducibility of classifier results, probabilities def test_classify_samples_ncv_accuracy(self): dat = biom.Table(np.array( [[4446, 9828, 3208, 776, 118, 4175, 657, 251, 7505, 617], [1855, 8716, 3257, 1251, 3205, 2557, 4251, 7405, 1417, 1215], [6616, 281, 8616, 291, 261, 253, 9075, 252, 7385, 4068]]), observation_ids=['o1', 'o2', 'o3'], sample_ids=['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10']) md = qiime2.CategoricalMetadataColumn(pd.Series( ['red', 'red', 'red', 'red', 'red', 'blue', 'blue', 'blue', 'blue', 'blue'], index=pd.Index(['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10'], name='sample-id'), name='color')) y_pred, importances, probabilities = classify_samples_ncv( dat, md, random_state=123, n_estimators=2, n_jobs=1, missing_samples='ignore') exp_pred = pd.Series( ['blue', 'red', 'red', 'blue', 'blue', 'blue', 'blue', 'red', 'blue', 'blue'], index=pd.Index(['s4', 's6', 's1', 's10', 's5', 's8', 's2', 's9', 's3', 's7'], dtype='object', name='SampleID'), name='prediction') exp_importances = pd.DataFrame( [0.595111111111111, 0.23155555555555551, 0.17333333333333334], index=pd.Index(['o3', 'o1', 'o2'], name='feature'), columns=['importance']) exp_probabilities = pd.DataFrame( [[0.5, 0.5], [0., 1.], [0., 1.], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 0.5], [0., 1.], [1., 0.], [1., 0.]], index=pd.Index(['s4', 's6', 's1', 's10', 's5', 's8', 's2', 's9', 's3', 's7'], name='SampleID'), columns=['blue', 'red']) pdt.assert_series_equal(y_pred, exp_pred) pdt.assert_frame_equal(importances, exp_importances) pdt.assert_frame_equal(probabilities, exp_probabilities) # test ncv a second time with KNeighborsRegressor (no feature importance) def test_regress_samples_ncv_knn(self): y_pred, importances = regress_samples_ncv( self.table_ecam_fp, self.mdc_ecam_fp, random_state=123, n_estimators=2, n_jobs=1, stratify=False, parameter_tuning=False, estimator='KNeighborsRegressor', missing_samples='ignore') # test that ncv gives expected results def test_regress_samples_ncv_accuracy(self): y_pred, importances = regress_samples_ncv( self.table_ecam_fp, self.mdc_ecam_fp, random_state=123, n_estimators=2, n_jobs=1, missing_samples='ignore') pdt.assert_series_equal(y_pred, self.exp_pred) pdt.assert_frame_equal(importances, self.exp_imp) # test that fit_* methods output consistent importance scores def test_fit_regressor(self): pipeline, importances = fit_regressor( self.table_ecam_fp, self.mdc_ecam_fp, random_state=123, n_estimators=2, n_jobs=1, missing_samples='ignore') exp_imp = pd.read_csv( self.get_data_path('importance_cv.tsv'), sep='\t', header=0, index_col=0) pdt.assert_frame_equal(importances, exp_imp) # just make sure this method runs. Uses the same internal function as # fit_regressor, so importance score consistency is covered by the above # test. def test_fit_classifier(self): pipeline, importances = fit_classifier( self.table_ecam_fp, self.mdc_ecam_fp, random_state=123, n_estimators=2, n_jobs=1, optimize_feature_selection=True, parameter_tuning=True, missing_samples='ignore') # test that each regressor works and delivers an expected accuracy result # when a random seed is set. def test_regressors(self): for regressor in ['RandomForestRegressor', 'ExtraTreesRegressor', 'GradientBoostingRegressor', 'AdaBoostRegressor[DecisionTree]', 'AdaBoostRegressor[ExtraTrees]', 'Lasso', 'Ridge', 'ElasticNet', 'KNeighborsRegressor', 'LinearSVR', 'SVR']: table_fp = self.get_data_path('ecam-table-maturity.qza') table = qiime2.Artifact.load(table_fp) res = sample_classifier.actions.regress_samples( table=table, metadata=self.mdc_ecam_fp, test_size=0.5, cv=1, n_estimators=10, n_jobs=1, estimator=regressor, random_state=123, parameter_tuning=False, optimize_feature_selection=False, missing_samples='ignore', stratify=True) pred = res[2].view(pd.Series) pred, truth = _match_series_or_die( pred, self.mdc_ecam_fp.to_series(), 'ignore') accuracy = mean_squared_error(truth, pred) # TODO: Remove this conditional when # https://github.com/qiime2/q2-sample-classifier/issues/193 is # closed if regressor == 'Ridge': self.assertAlmostEqual( accuracy, seeded_results[regressor], places=0, msg='Accuracy of %s regressor was %f, but expected %f' % ( regressor, accuracy, seeded_results[regressor])) else: self.assertAlmostEqual( accuracy, seeded_results[regressor], places=4, msg='Accuracy of %s regressor was %f, but expected %f' % ( regressor, accuracy, seeded_results[regressor])) # test adaboost base estimator trainer def test_train_adaboost_decision_tree(self): abe = _train_adaboost_base_estimator( self.table_chard_fp, self.mdc_chard_fp, 'Region', n_estimators=10, n_jobs=1, cv=3, random_state=None, parameter_tuning=True, classification=True, missing_samples='ignore', base_estimator="DecisionTree") self.assertEqual(type(abe.named_steps.est), AdaBoostClassifier) self.assertEqual(type(abe.named_steps.est.estimator), DecisionTreeClassifier) def test_train_adaboost_extra_trees(self): abe = _train_adaboost_base_estimator( self.table_chard_fp, self.mdc_chard_fp, 'Region', n_estimators=10, n_jobs=1, cv=3, random_state=None, parameter_tuning=True, classification=True, missing_samples='ignore', base_estimator="ExtraTrees") self.assertEqual(type(abe.named_steps.est), AdaBoostClassifier) self.assertEqual(type(abe.named_steps.est.estimator), ExtraTreeClassifier) # test some invalid inputs/edge cases def test_invalids(self): estimator, pad, pt = _set_parameters_and_estimator( 'RandomForestClassifier', self.table_chard_fp, self.md_chard_fp, 'Region', n_estimators=10, n_jobs=1, cv=1, random_state=123, parameter_tuning=False, classification=True, missing_samples='ignore') regressor, pad, pt = _set_parameters_and_estimator( 'RandomForestRegressor', self.table_chard_fp, self.md_chard_fp, 'Region', n_estimators=10, n_jobs=1, cv=1, random_state=123, parameter_tuning=False, classification=True, missing_samples='ignore') def test_split_table_no_rounding_error(self): X_train, X_test, y_train, y_test = split_table( self.table_chard_fp, self.mdc_chard_fp, test_size=0.5, random_state=123, stratify=True, missing_samples='ignore') self.assertEqual(len(X_train.ids()) + len(X_test.ids()), 21) self.assertEqual(y_train.shape[0] + y_test.shape[0], 21) def test_split_table_no_split(self): X_train, X_test, y_train, y_test = split_table( self.table_chard_fp, self.mdc_chard_fp, test_size=0.0, random_state=123, stratify=True, missing_samples='ignore') self.assertEqual(len(X_train.ids()), 21) self.assertEqual(y_train.shape[0], 21) def test_split_table_invalid_test_size(self): with self.assertRaisesRegex(ValueError, "at least two samples"): X_train, X_test, y_train, y_test = split_table( self.table_chard_fp, self.mdc_chard_fp, test_size=1.0, random_state=123, stratify=True, missing_samples='ignore') def test_split_table_percnorm(self): X_train, X_test, y_train, y_test = split_table( self.table_percnorm, self.mdc_percnorm, test_size=0.5, random_state=123, stratify=True, missing_samples='ignore') self.assertEqual(len(X_train.ids()) + len(X_test.ids()), 4) self.assertEqual(y_train.shape[0] + y_test.shape[0], 4) # test experimental functions def test_detect_outliers(self): detect_outliers(self.table_chard_fp, self.md_chard_fp, random_state=123, n_jobs=1, contamination=0.05) def test_detect_outliers_with_subsets(self): detect_outliers(self.table_chard_fp, self.md_chard_fp, random_state=123, n_jobs=1, contamination=0.05, subset_column='Vineyard', subset_value=1) def test_detect_outliers_raise_error_on_missing_subset_data(self): with self.assertRaisesRegex(ValueError, "must both be provided"): detect_outliers(self.table_chard_fp, self.md_chard_fp, random_state=123, n_jobs=1, contamination=0.05, subset_column='Vineyard', subset_value=None) with self.assertRaisesRegex(ValueError, "must both be provided"): detect_outliers(self.table_chard_fp, self.md_chard_fp, random_state=123, n_jobs=1, contamination=0.05, subset_column=None, subset_value=1) # just test that this works by making sure a classifier trained on samples # x, y, and z predicts the correct metadata values for those same samples. def test_predict_classifications(self): for classifier in ['RandomForestClassifier', 'ExtraTreesClassifier', 'GradientBoostingClassifier', 'AdaBoostClassifier[DecisionTree]', 'AdaBoostClassifier[ExtraTrees]', 'LinearSVC', 'SVC', 'KNeighborsClassifier']: estimator, importances = fit_classifier( self.table_chard_fp, self.mdc_chard_fp, random_state=123, n_estimators=2, estimator=classifier, n_jobs=1, missing_samples='ignore') pred, prob = predict_classification(self.table_chard_fp, estimator) exp = self.mdc_chard_fp.to_series().reindex(pred.index).dropna() # reindex both pred and exp because not all samples present in pred # are present in the metadata! (hence missing_samples='ignore') sample_ids = pred.index.intersection(exp.index) pred = pred.loc[sample_ids] exp = exp.loc[sample_ids] # verify predictions: # test that expected number of correct results is achieved (these # are mostly quite high as we would expect (total n=21)) correct_results = np.sum(pred == exp) self.assertEqual( correct_results, seeded_predict_results[classifier], msg='Accuracy of %s classifier was %f, but expected %f' % ( classifier, correct_results, seeded_predict_results[classifier])) # verify probabilities # test whether all are in correct range (0 to 1) ls_pred_classes = prob.columns.tolist() ls_correct_range = [col for col in ls_pred_classes if prob[col].between( 0, 1, inclusive="both").all()] self.assertEqual(len(ls_correct_range), prob.shape[1], msg='Predicted probabilities of class {}' 'are not in range [0,1]'.format( [col for col in ls_pred_classes if col not in ls_correct_range])) def test_predict_regressions(self): for regressor in ['RandomForestRegressor', 'ExtraTreesRegressor', 'GradientBoostingRegressor', 'AdaBoostRegressor[DecisionTree]', 'AdaBoostRegressor[ExtraTrees]', 'Lasso', 'Ridge', 'ElasticNet', 'KNeighborsRegressor', 'SVR', 'LinearSVR']: estimator, importances = fit_regressor( self.table_ecam_fp, self.mdc_ecam_fp, random_state=123, n_estimators=2, estimator=regressor, n_jobs=1, missing_samples='ignore') pred = predict_regression(self.table_ecam_fp, estimator) exp = self.mdc_ecam_fp.to_series() # reindex both pred and exp because not all samples present in pred # are present in the metadata! (hence missing_samples='ignore') sample_ids = pred.index.intersection(exp.index) pred = pred.loc[sample_ids] exp = exp.loc[sample_ids] # test that expected MSE is achieved (these are mostly quite high # as we would expect) mse = mean_squared_error(exp, pred) # TODO: Remove this conditional when # https://github.com/qiime2/q2-sample-classifier/issues/193 is # closed if regressor == 'Ridge': self.assertAlmostEqual( mse, seeded_predict_results[regressor], places=4, msg='Accuracy of %s regressor was %f, but expected %f' % ( regressor, mse, seeded_predict_results[regressor])) else: self.assertAlmostEqual( mse, seeded_predict_results[regressor], msg='Accuracy of %s regressor was %f, but expected %f' % ( regressor, mse, seeded_predict_results[regressor])) # make sure predict still works when features are given in a different # order from training set. def test_predict_feature_order_aint_no_thing(self): table = self.table_ecam_fp estimator, importances = fit_regressor( table, self.mdc_ecam_fp, random_state=123, n_estimators=2, n_jobs=1, missing_samples='ignore') # randomly shuffle and reorder features in biom table. feature_ids = table.ids(axis='observation') # look ma no seed! we should get the same result no matter the order. np.random.shuffle(feature_ids) shuffled_table = table.sort_order(feature_ids, axis='observation') # now predict values on shuffled data pred = predict_regression(shuffled_table, estimator) exp = self.mdc_ecam_fp.to_series() # reindex both pred and exp because not all samples present in pred # are present in the metadata! (hence missing_samples='ignore') sample_ids = pred.index.intersection(exp.index) pred = pred.loc[sample_ids] exp = exp.loc[sample_ids] # test that expected MSE is achieved (these are mostly quite high # as we would expect) mse = mean_squared_error(exp, pred) self.assertAlmostEqual( mse, seeded_predict_results['RandomForestRegressor']) seeded_results = { 'RandomForestClassifier': 0.63636363636363635, 'ExtraTreesClassifier': 0.454545454545, 'GradientBoostingClassifier': 0.272727272727, 'AdaBoostClassifier[DecisionTree]': 0.272727272727, 'AdaBoostClassifier[ExtraTrees]': 0.272727272727, 'LinearSVC': 0.818182, 'SVC': 0.36363636363636365, 'KNeighborsClassifier': 0.363636363636, 'RandomForestRegressor': 23.226508, 'ExtraTreesRegressor': 19.725397, 'GradientBoostingRegressor': 34.157100, 'AdaBoostRegressor[DecisionTree]': 30.920635, 'AdaBoostRegressor[ExtraTrees]': 21.746031, 'Lasso': 722.827623, 'Ridge': 521.195194222418, 'ElasticNet': 618.532273, 'KNeighborsRegressor': 44.7847619048, 'LinearSVR': 511.816385601, 'SVR': 51.325146} seeded_predict_results = { 'RandomForestClassifier': 18, 'ExtraTreesClassifier': 21, 'GradientBoostingClassifier': 21, 'AdaBoostClassifier[DecisionTree]': 21, 'AdaBoostClassifier[ExtraTrees]': 21, 'LinearSVC': 21, 'SVC': 12, 'KNeighborsClassifier': 14, 'RandomForestRegressor': 7.4246031746, 'ExtraTreesRegressor': 0., 'GradientBoostingRegressor': 50.1955883469, 'AdaBoostRegressor[DecisionTree]': 9.7857142857142865, 'AdaBoostRegressor[ExtraTrees]': 33.95238095238095, 'Lasso': 0.173138653701, 'Ridge': 2.694020055323081e-05, 'ElasticNet': 0.0614243397637, 'KNeighborsRegressor': 26.8625396825, 'SVR': 37.86704865859832, 'LinearSVR': 0.0099912565770459132} q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/test_types_formats_transformers.py000066400000000000000000000500151462552620600322460ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import os import pandas as pd import pandas.testing as pdt import numpy as np import shutil import tempfile import tarfile import joblib import sklearn from sklearn.pipeline import Pipeline import qiime2 from q2_types.feature_data import FeatureData from qiime2.plugin import ValidationError from q2_types.sample_data import SampleData from q2_sample_classifier import ( BooleanSeriesFormat, BooleanSeriesDirectoryFormat, BooleanSeries, PredictionsFormat, PredictionsDirectoryFormat, ClassifierPredictions, RegressorPredictions, ImportanceFormat, ImportanceDirectoryFormat, Importance, PickleFormat, ProbabilitiesFormat, ProbabilitiesDirectoryFormat, Probabilities, Classifier, Regressor, SampleEstimator, SampleEstimatorDirFmt, TrueTargetsDirectoryFormat, TrueTargets) from q2_sample_classifier.visuals import ( _custom_palettes, _plot_heatmap_from_confusion_matrix,) from q2_sample_classifier._format import JSONFormat from q2_sample_classifier.tests.test_base_class import \ SampleClassifierTestPluginBase from q2_sample_classifier.tests.test_estimators import SampleEstimatorTestBase class TestSemanticTypes(SampleClassifierTestPluginBase): def test_boolean_series_format_validate_positive(self): filepath = self.get_data_path('outliers.tsv') format = BooleanSeriesFormat(filepath, mode='r') # These should both just succeed format.validate('min') format.validate('max') def test_boolean_series_format_validate_negative_col_count(self): filepath = self.get_data_path('coordinates.tsv') format = BooleanSeriesFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'BooleanSeriesFormat'): format.validate() def test_boolean_series_format_validate_negative_cell_values(self): filepath = self.get_data_path('predictions.tsv') format = BooleanSeriesFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'BooleanSeriesFormat'): format.validate() def test_boolean_series_format_validate_negative_empty(self): filepath = self.get_data_path('empty_file.txt') format = BooleanSeriesFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'one data record'): format.validate() def test_boolean_series_dir_fmt_validate_positive(self): filepath = self.get_data_path('outliers.tsv') shutil.copy(filepath, self.temp_dir.name) format = BooleanSeriesDirectoryFormat(self.temp_dir.name, mode='r') format.validate() def test_boolean_series_semantic_type_registration(self): self.assertRegisteredSemanticType(BooleanSeries) def test_sample_data_boolean_series_to_boolean_dir_fmt_registration(self): self.assertSemanticTypeRegisteredToFormat( SampleData[BooleanSeries], BooleanSeriesDirectoryFormat) def test_pd_series_to_boolean_format(self): transformer = self.get_transformer(pd.Series, BooleanSeriesFormat) exp_index = pd.Index(['a', 'b', 'c', 'd', 'e', 'f'], dtype=object) exp = pd.Series([True, False, True, False, True, False], name='outlier', index=exp_index) obs = transformer(exp) obs = pd.read_csv(str(obs), sep='\t', header=0, index_col=0, ).squeeze('columns') self.assertEqual(sorted(exp), sorted(obs)) def test_boolean_format_to_pd_series(self): _, obs = self.transform_format( BooleanSeriesFormat, pd.Series, 'outliers.tsv') exp_index = pd.Index(['a', 'b', 'c', 'd', 'e', 'f'], dtype=object) exp = pd.Series(['True', 'False', 'True', 'False', 'True', 'False'], name='outlier', index=exp_index) self.assertEqual(sorted(exp), sorted(obs)) def test_boolean_format_to_metadata(self): _, obs = self.transform_format( BooleanSeriesFormat, qiime2.Metadata, 'outliers.tsv') exp_index = pd.Index(['a', 'b', 'c', 'd', 'e', 'f'], name='id') exp = pd.DataFrame([['True'], ['False'], ['True'], ['False'], ['True'], ['False']], columns=['outlier'], index=exp_index, dtype='str') exp = qiime2.Metadata(exp) self.assertEqual(obs, exp) # test predictions format def test_Predictions_format_validate_positive_numeric_predictions(self): filepath = self.get_data_path('predictions.tsv') format = PredictionsFormat(filepath, mode='r') format.validate(level='min') format.validate() def test_Predictions_format_validate_positive_nonnumeric_predictions(self): filepath = self.get_data_path('categorical_predictions.tsv') format = PredictionsFormat(filepath, mode='r') format.validate(level='min') format.validate() def test_Predictions_format_validate_negative(self): filepath = self.get_data_path('coordinates.tsv') format = PredictionsFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'PredictionsFormat'): format.validate() def test_Predictions_dir_fmt_validate_positive(self): filepath = self.get_data_path('predictions.tsv') shutil.copy(filepath, self.temp_dir.name) format = PredictionsDirectoryFormat(self.temp_dir.name, mode='r') format.validate() def test_RegressorPredictions_semantic_type_registration(self): self.assertRegisteredSemanticType(RegressorPredictions) def test_ClassifierPredictions_semantic_type_registration(self): self.assertRegisteredSemanticType(ClassifierPredictions) def test_RegressorPredictions_to_Predictions_dir_fmt_registration(self): self.assertSemanticTypeRegisteredToFormat( SampleData[RegressorPredictions], PredictionsDirectoryFormat) def test_ClassifierPredictions_to_Predictions_dir_fmt_registration(self): self.assertSemanticTypeRegisteredToFormat( SampleData[ClassifierPredictions], PredictionsDirectoryFormat) def test_pd_series_to_Predictions_format(self): transformer = self.get_transformer(pd.Series, PredictionsFormat) exp = pd.Series([1, 2, 3, 4], name='prediction', index=['a', 'b', 'c', 'd']) obs = transformer(exp) obs = pd.read_csv(str(obs), sep='\t', header=0, index_col=0, ).squeeze('columns') pdt.assert_series_equal(obs, exp) def test_pd_series_to_Predictions_format_allow_nans(self): transformer = self.get_transformer(pd.Series, PredictionsFormat) exp = pd.Series([1, np.nan, 3, np.nan], name='prediction', index=['a', 'b', 'c', 'd']) obs = transformer(exp) obs = pd.read_csv(str(obs), sep='\t', header=0, index_col=0, ).squeeze('columns') pdt.assert_series_equal(obs, exp) def test_Predictions_format_to_pd_series(self): _, obs = self.transform_format( PredictionsFormat, pd.Series, 'predictions.tsv') exp_index = pd.Index(['10249.C001.10SS', '10249.C002.05SS', '10249.C004.01SS', '10249.C004.11SS'], name='id', dtype=object) exp = pd.Series([4.5, 2.5, 0.5, 4.5], name='prediction', index=exp_index) pdt.assert_series_equal(obs[:4], exp) def test_Predictions_format_to_metadata(self): _, obs = self.transform_format( PredictionsFormat, qiime2.Metadata, 'predictions.tsv') exp_index = pd.Index(['10249.C001.10SS', '10249.C002.05SS', '10249.C004.01SS', '10249.C004.11SS'], name='id') exp = pd.DataFrame([4.5, 2.5, 0.5, 4.5], columns=['prediction'], index=exp_index) pdt.assert_frame_equal(obs.to_dataframe()[:4], exp) # test Importance format def test_Importance_format_validate_positive(self): filepath = self.get_data_path('importance.tsv') format = ImportanceFormat(filepath, mode='r') format.validate(level='min') format.validate() def test_Importance_format_validate_negative_nonnumeric(self): filepath = self.get_data_path('chardonnay.map.txt') format = ImportanceFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'numeric values'): format.validate() def test_Importance_format_validate_negative_empty(self): filepath = self.get_data_path('empty_file.txt') format = ImportanceFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'one data record'): format.validate() def test_Importance_format_validate_negative(self): filepath = self.get_data_path('garbage.txt') format = ImportanceFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'two or more fields'): format.validate() def test_Importance_dir_fmt_validate_positive(self): filepath = self.get_data_path('importance.tsv') shutil.copy(filepath, self.temp_dir.name) format = ImportanceDirectoryFormat(self.temp_dir.name, mode='r') format.validate() def test_Importance_semantic_type_registration(self): self.assertRegisteredSemanticType(Importance) def test_sample_data_Importance_to_Importance_dir_fmt_registration(self): self.assertSemanticTypeRegisteredToFormat( FeatureData[Importance], ImportanceDirectoryFormat) def test_pd_dataframe_to_Importance_format(self): transformer = self.get_transformer(pd.DataFrame, ImportanceFormat) exp = pd.DataFrame([1, 2, 3, 4], columns=['importance'], index=['a', 'b', 'c', 'd']) obs = transformer(exp) obs = pd.read_csv(str(obs), sep='\t', header=0, index_col=0) pdt.assert_frame_equal(exp, obs) def test_Importance_format_to_pd_dataframe(self): _, obs = self.transform_format( ImportanceFormat, pd.DataFrame, 'importance.tsv') exp_index = pd.Index(['74ec9fe6ffab4ecff6d5def74298a825', 'c82032c40c98975f71892e4be561c87a', '79280cea51a6fe8a3432b2f266dd34db', 'f7686a74ca2d3729eb66305e8a26309b'], name='id') exp = pd.DataFrame([0.44469828320835586, 0.07760118417569697, 0.06570251750505914, 0.061718558716901406], columns=['importance'], index=exp_index) pdt.assert_frame_equal(exp, obs[:4]) def test_Importance_format_to_metadata(self): _, obs = self.transform_format( ImportanceFormat, qiime2.Metadata, 'importance.tsv') exp_index = pd.Index(['74ec9fe6ffab4ecff6d5def74298a825', 'c82032c40c98975f71892e4be561c87a', '79280cea51a6fe8a3432b2f266dd34db', 'f7686a74ca2d3729eb66305e8a26309b'], name='id') exp = pd.DataFrame([0.44469828320835586, 0.07760118417569697, 0.06570251750505914, 0.061718558716901406], columns=['importance'], index=exp_index) pdt.assert_frame_equal(obs.to_dataframe()[:4], exp) # test Probabilities format def test_Probabilities_format_validate_positive(self): filepath = self.get_data_path('class_probabilities.tsv') format = ProbabilitiesFormat(filepath, mode='r') format.validate(level='min') format.validate() def test_Probabilities_format_validate_negative_nonnumeric(self): filepath = self.get_data_path('chardonnay.map.txt') format = ProbabilitiesFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'numeric values'): format.validate() def test_Probabilities_format_validate_negative_empty(self): filepath = self.get_data_path('empty_file.txt') format = ProbabilitiesFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'one data record'): format.validate() def test_Probabilities_format_validate_negative(self): filepath = self.get_data_path('garbage.txt') format = ProbabilitiesFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'two or more fields'): format.validate() def test_Probabilities_dir_fmt_validate_positive(self): filepath = self.get_data_path('class_probabilities.tsv') shutil.copy(filepath, self.temp_dir.name) format = ProbabilitiesDirectoryFormat(self.temp_dir.name, mode='r') format.validate() def test_Probabilities_semantic_type_registration(self): self.assertRegisteredSemanticType(Probabilities) def test_sample_data_Probabilities_to_Probs_dir_fmt_registration(self): self.assertSemanticTypeRegisteredToFormat( SampleData[Probabilities], ProbabilitiesDirectoryFormat) def test_pd_dataframe_to_Probabilities_format(self): transformer = self.get_transformer(pd.DataFrame, ProbabilitiesFormat) exp = pd.DataFrame([[0.1, 0.77], [0.8, 0.4], [0.7, 0.1], [0.44, 0.73]], columns=['classA', 'classB'], index=['a', 'b', 'c', 'd']) obs = transformer(exp) obs = pd.read_csv(str(obs), sep='\t', header=0, index_col=0, parse_dates=True) pdt.assert_frame_equal(exp, obs) def test_Probabilities_format_to_pd_dataframe(self): _, obs = self.transform_format( ProbabilitiesFormat, pd.DataFrame, 'class_probabilities.tsv') exp_index = pd.Index(['s1', 's2', 's3', 's4', 's5', 's6', 's7'], name='id') exp = pd.DataFrame([[0.4446, 0.9828, 0.3208], [0.0776, 0.0118, 0.4175], [0.0657, 0.0251, 0.7505], [0.0617, 0.1855, 0.8716], [0.0281, 0.8616, 0.0291], [0.0261, 0.0253, 0.9075], [0.0252, 0.7385, 0.4068]], columns=['classA', 'classB', 'classC'], index=exp_index) pdt.assert_frame_equal(exp, obs) def test_Probabilities_format_to_metadata(self): _, obs = self.transform_format( ProbabilitiesFormat, qiime2.Metadata, 'class_probabilities.tsv') exp_index = pd.Index(['s1', 's2', 's3', 's4', 's5', 's6', 's7'], name='id') exp = pd.DataFrame([[0.4446, 0.9828, 0.3208], [0.0776, 0.0118, 0.4175], [0.0657, 0.0251, 0.7505], [0.0617, 0.1855, 0.8716], [0.0281, 0.8616, 0.0291], [0.0261, 0.0253, 0.9075], [0.0252, 0.7385, 0.4068]], columns=['classA', 'classB', 'classC'], index=exp_index) pdt.assert_frame_equal(obs.to_dataframe(), exp) # test utility formats def test_pickle_format_validate_negative(self): filepath = self.get_data_path('coordinates.tsv') format = PickleFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'pickled file'): format.validate() def test_json_format_validate_negative(self): filepath = self.get_data_path('coordinates.tsv') format = JSONFormat(filepath, mode='r') with self.assertRaisesRegex(ValidationError, 'Expecting value'): format.validate() # this just checks that palette names are valid input def test_custom_palettes(self): confused = np.array([[1, 0], [0, 1]]) for palette in _custom_palettes().keys(): _plot_heatmap_from_confusion_matrix(confused, palette) # test TrueTarget def test_TrueTargets_semantic_type_registration(self): self.assertRegisteredSemanticType(TrueTargets) # test TrueTargetDirectoryFormats def test_TrueTargets_dir_fmt_validate_positive(self): filepath = self.get_data_path('true_targets.tsv') shutil.copy(filepath, self.temp_dir.name) format = TrueTargetsDirectoryFormat(self.temp_dir.name, mode='r') format.validate() def test_TrueTarget_to_TrueTargets_dir_fmt_registration(self): self.assertSemanticTypeRegisteredToFormat( SampleData[TrueTargets], TrueTargetsDirectoryFormat) class TestTypes(SampleClassifierTestPluginBase): def test_sample_estimator_semantic_type_registration(self): self.assertRegisteredSemanticType(SampleEstimator) def test_classifier_semantic_type_registration(self): self.assertRegisteredSemanticType(Classifier) def test_regressor_semantic_type_registration(self): self.assertRegisteredSemanticType(Regressor) def test_sample_classifier_semantic_type_to_format_registration(self): self.assertSemanticTypeRegisteredToFormat( SampleEstimator[Classifier], SampleEstimatorDirFmt) def test_sample_regressor_semantic_type_to_format_registration(self): self.assertSemanticTypeRegisteredToFormat( SampleEstimator[Regressor], SampleEstimatorDirFmt) class TestFormats(SampleEstimatorTestBase): def test_sample_classifier_dir_fmt(self): format = self._custom_setup(sklearn.__version__) # Should not error format.validate() class TestTransformers(SampleEstimatorTestBase): def test_old_sklearn_version(self): transformer = self.get_transformer( SampleEstimatorDirFmt, Pipeline) input = self._custom_setup('a very old version') with self.assertRaises(ValueError): transformer(input) def test_taxo_class_dir_fmt_to_taxo_class_result(self): input = self._custom_setup(sklearn.__version__) transformer = self.get_transformer( SampleEstimatorDirFmt, Pipeline) obs = transformer(input) self.assertTrue(obs) def test_taxo_class_result_to_taxo_class_dir_fmt(self): def read_pipeline(pipeline_filepath): with tarfile.open(pipeline_filepath) as tar: dirname = tempfile.mkdtemp() def is_within_directory(directory, target): abs_directory = os.path.abspath(directory) abs_target = os.path.abspath(target) prefix = os.path.commonprefix([abs_directory, abs_target]) return prefix == abs_directory def safe_extract(tar, path=".", members=None, *, numeric_owner=False): for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): raise Exception("Attempted Path Traversal in Tar" "File") tar.extractall(path, members, numeric_owner=numeric_owner) safe_extract(tar, dirname) pipeline = joblib.load(os.path.join(dirname, 'sklearn_pipeline.pkl')) for fn in tar.getnames(): os.unlink(os.path.join(dirname, fn)) os.rmdir(dirname) return pipeline exp = read_pipeline(self.sklearn_pipeline) transformer = self.get_transformer( Pipeline, SampleEstimatorDirFmt) obs = transformer(exp) sklearn_pipeline = obs.sklearn_pipeline.view(PickleFormat) obs_pipeline = read_pipeline(str(sklearn_pipeline)) obs = obs_pipeline self.assertTrue(obs) q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/test_utilities.py000066400000000000000000000157521462552620600265660ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import pandas as pd import biom import numpy as np from sklearn.svm import LinearSVC from sklearn.feature_extraction import DictVectorizer from sklearn.pipeline import Pipeline from sklearn.ensemble import RandomForestClassifier import pandas.testing as pdt import qiime2 from q2_sample_classifier.utilities import ( _load_data, _calculate_feature_importances, _extract_important_features, _disable_feature_selection, _mean_feature_importance, _null_feature_importance, _extract_features) from q2_sample_classifier.tests.test_base_class import \ SampleClassifierTestPluginBase class UtilitiesTests(SampleClassifierTestPluginBase): def setUp(self): super().setUp() exp_rf = pd.DataFrame( {'importance': [0.1, 0.2, 0.3]}, index=['a', 'b', 'c']) exp_rf.index.name = 'feature' self.exp_rf = exp_rf exp_svm = pd.DataFrame( {'importance0': [0.1, 0.2, 0.3], 'importance1': [0.4, 0.5, 0.6]}, index=['a', 'b', 'c']) exp_svm.index.name = 'feature' self.exp_svm = exp_svm exp_lsvm = pd.DataFrame( {'importance0': [-0.048794, -0.048794, -0.048794]}, index=['a', 'b', 'c']) exp_lsvm.index.name = 'feature' self.exp_lsvm = exp_lsvm self.features = biom.Table(np.array([[1]*5]*3), ['a', 'b', 'c'], list(map(str, range(5)))) self.targets = pd.Series(['a', 'a', 'b', 'b', 'a'], name='bullseye') def test_extract_important_features_1d_array(self): importances = _extract_important_features( self.features.ids('observation'), np.ndarray((3,), buffer=np.array([0.1, 0.2, 0.3]))) self.assertEqual(sorted(self.exp_rf), sorted(importances)) def test_extract_important_features_2d_array(self): importances = _extract_important_features( self.features.ids('observation'), np.ndarray( (2, 3), buffer=np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6]))) self.assertEqual(sorted(self.exp_svm), sorted(importances)) # test feature importance calculation with main classifier types def test_calculate_feature_importances_ensemble(self): estimator = Pipeline( [('dv', DictVectorizer()), ('est', RandomForestClassifier(n_estimators=10))]) estimator.fit(_extract_features(self.features), self.targets.values.ravel()) fi = _calculate_feature_importances(estimator) self.assertEqual(sorted(self.exp_rf), sorted(fi)) def test_calculate_feature_importances_svm(self): estimator = Pipeline( [('dv', DictVectorizer()), ('est', LinearSVC())]) estimator.fit(_extract_features(self.features), self.targets.values.ravel()) fi = _calculate_feature_importances(estimator) self.assertEqual(sorted(self.exp_lsvm), sorted(fi)) # confirm that feature selection incompatibility warnings work def test_disable_feature_selection_unsupported(self): with self.assertWarnsRegex(UserWarning, "does not support recursive"): _disable_feature_selection('KNeighborsClassifier', False) def test_mean_feature_importance_1d_arrays(self): exp = pd.DataFrame([10., 9., 8., 7.], columns=["importance0"], index=[3, 2, 1, 0]) imps = [pd.DataFrame([1, 2, 3, 4], columns=["importance0"]), pd.DataFrame([5, 6, 7, 8], columns=["importance0"]), pd.DataFrame([9, 10, 11, 12], columns=["importance0"]), pd.DataFrame([13, 14, 15, 16], columns=["importance0"])] pdt.assert_frame_equal(_mean_feature_importance(imps), exp) def test_mean_feature_importance_different_column_names(self): exp = pd.DataFrame([[6., 5., 4., 3.], [14., 13., 12., 11.]], index=["importance0", "importance1"], columns=[3, 2, 1, 0]).T imps = [pd.DataFrame([1, 2, 3, 4], columns=["importance0"]), pd.DataFrame([5, 6, 7, 8], columns=["importance0"]), pd.DataFrame([9, 10, 11, 12], columns=["importance1"]), pd.DataFrame([13, 14, 15, 16], columns=["importance1"])] pdt.assert_frame_equal(_mean_feature_importance(imps), exp) def test_mean_feature_importance_2d_arrays(self): exp = pd.DataFrame([[3.5] * 4, [9.5] * 4], index=["importance0", "importance1"], columns=[0, 1, 2, 3]).T imps = [pd.DataFrame([[6, 5, 4, 3], [14, 13, 12, 11]], index=["importance0", "importance1"], columns=[0, 1, 2, 3]).T, pd.DataFrame([[1, 2, 3, 4], [5, 6, 7, 8]], index=["importance0", "importance1"], columns=[0, 1, 2, 3]).T] pdt.assert_frame_equal(_mean_feature_importance(imps), exp) # and this should not occur now, but theoretically should just concat and # sort but not collapse if all column names are unique def test_mean_feature_importance_do_not_collapse(self): imps = [pd.DataFrame([4.0, 3.0, 2.0, 1.0], columns=["importance0"]), pd.DataFrame([16.0, 15.0, 14.0, 13.0], columns=["importance1"])] exp = pd.concat(imps, axis=1) pdt.assert_frame_equal(_mean_feature_importance(imps), exp) def test_null_feature_importance(self): exp = pd.DataFrame( [1, 1, 1], index=['o1', 'o2', 'o3'], columns=['importance']) exp.index.name = 'feature' tab = biom.Table(np.array([[1., 2., 3.], [3., 2., 1.], [7., 6., 9.]]), ['o1', 'o2', 'o3'], ['s1', 's2', 's3']) tab = _extract_features(tab) pdt.assert_frame_equal(_null_feature_importance(tab), exp) def test_load_data(self): # phony feature table id_map = {'0': 'peanut', '1': 'bugs', '2': 'qiime2', '3': 'matt', '4': 'pandas'} a = self.features.update_ids(id_map, axis='sample') # phony metadata, convert to qiime2.Metadata b = self.targets b.index = ['pandas', 'peanut', 'qiime1', 'flapjacks', 'bugs'] b.index.name = '#SampleID' b = qiime2.Metadata(b.to_frame()) # test that merge of tables is inner merge intersection = set(('peanut', 'bugs', 'pandas')) feature_data, targets = _load_data(a, b, missing_samples='ignore') exp = [{'c': 1.0, 'a': 1.0, 'b': 1.0}, {'c': 1.0, 'a': 1.0, 'b': 1.0}, {'c': 1.0, 'a': 1.0, 'b': 1.0}] np.testing.assert_array_equal(feature_data, exp) self.assertEqual(set(targets.index), intersection) q2-sample-classifier-2024.5.0/q2_sample_classifier/tests/test_visualization.py000066400000000000000000000251411462552620600274450ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import pandas as pd import pandas.testing as pdt from os import mkdir, listdir from os.path import join import biom import qiime2 from qiime2.plugins import sample_classifier from q2_sample_classifier.visuals import ( _linear_regress, _calculate_baseline_accuracy, _add_sample_size_to_xtick_labels) from q2_sample_classifier.classify import ( scatterplot, confusion_matrix) from q2_sample_classifier.utilities import ( _match_series_or_die, _predict_and_plot) from q2_sample_classifier.tests.test_base_class import \ SampleClassifierTestPluginBase class TestVisuals(SampleClassifierTestPluginBase): md = pd.DataFrame([(1, 'a', 0.11), (1, 'a', 0.12), (1, 'a', 0.13), (2, 'a', 0.19), (2, 'a', 0.18), (2, 'a', 0.21), (1, 'b', 0.14), (1, 'b', 0.13), (1, 'b', 0.14), (2, 'b', 0.26), (2, 'b', 0.27), (2, 'b', 0.29)], columns=['Time', 'Group', 'Value']) def test_linear_regress(self): res = _linear_regress(self.md['Value'], self. md['Time']) self.assertAlmostEqual(res.iloc[0]['Mean squared error'], 1.9413916666) self.assertAlmostEqual(res.iloc[0]['r-value'], 0.86414956372460128) self.assertAlmostEqual(res.iloc[0]['r-squared'], 0.74675446848541871) self.assertAlmostEqual(res.iloc[0]['P-value'], 0.00028880275858705694) def test_calculate_baseline_accuracy(self): accuracy = 0.9 y_test = pd.Series(['a', 'a', 'a', 'b', 'b', 'b'], name="class") classifier_accuracy = _calculate_baseline_accuracy(y_test, accuracy) expected_results = (6, 3, 0.5, 1.8) for i in zip(classifier_accuracy, expected_results): self.assertEqual(i[0], i[1]) class TestHeatmap(SampleClassifierTestPluginBase): def setUp(self): super().setUp() md_vaw = self.get_data_path('vaw.txt') md_vaw = qiime2.Metadata.load(md_vaw) self.md_vaw = md_vaw.get_column('Column') table_vaw = self.get_data_path('vaw.qza') self.table_vaw = qiime2.Artifact.load(table_vaw) imp = pd.read_csv( self.get_data_path('vaw_importance.tsv'), sep='\t', header=0, index_col=0) self.imp = qiime2.Artifact.import_data('FeatureData[Importance]', imp) def test_heatmap_default_feature_count_zero(self): heatmap, table, = sample_classifier.actions.heatmap( self.table_vaw, self.imp, self.md_vaw, group_samples=True, feature_count=0) self.assertEqual(table.view(biom.Table).shape, (5, 2)) def test_heatmap_importance_threshold(self): heatmap, table, = sample_classifier.actions.heatmap( self.table_vaw, self.imp, self.md_vaw, importance_threshold=0.062, group_samples=False, feature_count=0) self.assertEqual(table.view(biom.Table).shape, (3, 6)) def test_heatmap_feature_count(self): heatmap, table, = sample_classifier.actions.heatmap( self.table_vaw, self.imp, self.md_vaw, group_samples=True, feature_count=2) self.assertEqual(table.view(biom.Table).shape, (2, 2)) def test_heatmap_must_group_or_die(self): with self.assertRaisesRegex(ValueError, "metadata are not optional"): heatmap, table, = sample_classifier.actions.heatmap( self.table_vaw, self.imp, sample_metadata=None, group_samples=True) # This class really just checks that these visualizers run without error. Yay. # Also test some internal nuts/bolts but there's not much else we can do. class TestPlottingVisualizers(SampleClassifierTestPluginBase): def setUp(self): super().setUp() self.tmpd = join(self.temp_dir.name, 'viz') mkdir(self.tmpd) self.a = pd.Series(['a', 'a', 'b', 'b', 'c', 'c'], name='site', index=['a1', 'a2', 'b1', 'b2', 'c1', 'c2']) self.a.index.name = 'SampleID' self.bogus = pd.Series(['a', 'a', 'b', 'b', 'c', 'c'], name='site', index=['a1', 'e3', 'f5', 'b2', 'z1', 'c2']) self.bogus.index.name = 'SampleID' self.c = pd.Series( [0, 1, 2, 3], index=['a', 'b', 'c', 'd'], name='peanuts') self.c.index.name = 'SampleID' def test_confusion_matrix(self): b = qiime2.CategoricalMetadataColumn(self.a) confusion_matrix(self.tmpd, self.a, b) def test_confusion_matrix_class_overlap_error(self): b = pd.Series([1, 2, 3, 4, 5, 6], name='site', index=['a1', 'a2', 'b1', 'b2', 'c1', 'c2']) b.index.name = 'id' b = qiime2.NumericMetadataColumn(b) with self.assertRaisesRegex(ValueError, "do not overlap"): confusion_matrix(self.tmpd, self.a, b) def test_confusion_matrix_vmin_too_high(self): b = qiime2.CategoricalMetadataColumn(self.a) with self.assertRaisesRegex(ValueError, r'vmin must be less than.*\s\s' r'0\.5.*greater.*0\.0'): confusion_matrix(self.tmpd, self.a, b, vmin=.5, vmax=None) def test_confusion_matrix_vmax_too_low(self): b = qiime2.CategoricalMetadataColumn(self.a) with self.assertRaisesRegex(ValueError, r'vmax must be greater than.*' r'\s\s0\.5.*less.*1\.0'): confusion_matrix(self.tmpd, self.a, b, vmin=None, vmax=.5) def test_confusion_matrix_vmin_too_high_and_vmax_too_low(self): b = qiime2.CategoricalMetadataColumn(self.a) with self.assertRaisesRegex(ValueError, r'vmin must be less than.*\s' r'\s0\.5.*greater.*0\.0\s.*vmax must be ' r'greater than.*\s\s0\.5.*less.*1\.0'): confusion_matrix(self.tmpd, self.a, b, vmin=.5, vmax=.5) def test_confusion_matrix_dtype_coercion(self): predictions = pd.Series([1, 1, 1, 2, 2, 2], index=pd.Index(['a', 'b', 'c', 'd', 'e', 'f'], name='sample_id'), name='features') # NOTE: the targets are numbers but represented as str truth = qiime2.CategoricalMetadataColumn(pd.Series( ['1', '2', '1', '2', '1', '2'], index=pd.Index(['a', 'b', 'c', 'd', 'e', 'f'], name='sample-id'), name='target')) confusion_matrix(self.tmpd, predictions, truth) self.assertTrue('index.html' in listdir(self.tmpd)) # test confusion matrix plotting independently to see how it handles # partially overlapping classes when true labels are superset def test_predict_and_plot_true_labels_are_superset(self): b = pd.Series(['a', 'a', 'b', 'b', 'b', 'b'], name='site', index=['a1', 'a2', 'b1', 'b2', 'c1', 'c2']) exp = pd.DataFrame( [[1., 0., 0., ''], [0., 1., 0., ''], [0., 1., 0., ''], ['', '', '', 0.666666666], ['', '', '', 0.3333333333], ['', '', '', 2.]], columns=['a', 'b', 'c', 'Overall Accuracy'], index=['a', 'b', 'c', 'Overall Accuracy', 'Baseline Accuracy', 'Accuracy Ratio']) predictions, confusion = _predict_and_plot(self.tmpd, self.a, b) pdt.assert_frame_equal(exp, predictions) # test confusion matrix plotting independently to see how it handles # partially overlapping classes when true labels are superset def test_predict_and_plot_true_labels_are_subset(self): b = pd.Series(['a', 'a', 'b', 'b', 'c', 'd'], name='site', index=['a1', 'a2', 'b1', 'b2', 'c1', 'c2']) exp = pd.DataFrame( [[1., 0., 0., 0., ''], [0., 1., 0., 0., ''], [0., 0., 0.5, 0.5, ''], [0., 0., 0., 0., ''], ['', '', '', '', 0.8333333333], ['', '', '', '', 0.3333333333], ['', '', '', '', 2.5]], columns=['a', 'b', 'c', 'd', 'Overall Accuracy'], index=['a', 'b', 'c', 'd', 'Overall Accuracy', 'Baseline Accuracy', 'Accuracy Ratio']) predictions, confusion = _predict_and_plot(self.tmpd, self.a, b) pdt.assert_frame_equal(exp, predictions) # test confusion matrix plotting independently to see how it handles # partially overlapping classes when true labels are mutually exclusive def test_predict_and_plot_true_labels_are_mutually_exclusive(self): b = pd.Series(['a', 'a', 'e', 'e', 'd', 'd'], name='site', index=['a1', 'a2', 'b1', 'b2', 'c1', 'c2']) exp = pd.DataFrame( [[1., 0., 0., 0., 0., ''], [0., 0., 0., 0., 1., ''], [0., 0., 0., 1., 0., ''], [0., 0., 0., 0., 0., ''], [0., 0., 0., 0., 0., ''], ['', '', '', '', '', 0.3333333333], ['', '', '', '', '', 0.3333333333], ['', '', '', '', '', 1.]], columns=['a', 'b', 'c', 'd', 'e', 'Overall Accuracy'], index=['a', 'b', 'c', 'd', 'e', 'Overall Accuracy', 'Baseline Accuracy', 'Accuracy Ratio']) predictions, confusion = _predict_and_plot(self.tmpd, self.a, b) pdt.assert_frame_equal(exp, predictions) def test_scatterplot(self): b = qiime2.NumericMetadataColumn(self.c) scatterplot(self.tmpd, self.c, b) def test_add_sample_size_to_xtick_labels(self): labels = _add_sample_size_to_xtick_labels(self.a, ['a', 'b', 'c']) exp = ['a (n=2)', 'b (n=2)', 'c (n=2)'] self.assertListEqual(labels, exp) # now test performance when extra classes are present def test_add_sample_size_to_xtick_labels_extra_classes(self): labels = _add_sample_size_to_xtick_labels( self.a, [0, 'a', 'b', 'bb', 'c']) exp = ['0 (n=0)', 'a (n=2)', 'b (n=2)', 'bb (n=0)', 'c (n=2)'] self.assertListEqual(labels, exp) def test_match_series_or_die(self): exp = pd.Series(['a', 'b', 'c'], name='site', index=['a1', 'b2', 'c2']) exp.index.name = 'SampleID' a, b = _match_series_or_die(self.a, self.bogus, 'ignore') pdt.assert_series_equal(exp, a) pdt.assert_series_equal(exp, b) def test_match_series_or_die_missing_samples(self): with self.assertRaisesRegex(ValueError, "Missing samples"): a, b = _match_series_or_die(self.a, self.bogus, 'error') q2-sample-classifier-2024.5.0/q2_sample_classifier/utilities.py000066400000000000000000001041441462552620600243570ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- import warnings from os.path import join from sklearn.model_selection import ( train_test_split, RandomizedSearchCV, KFold, StratifiedKFold) from sklearn.metrics import accuracy_score from sklearn.feature_selection import RFECV from sklearn.feature_extraction import DictVectorizer from sklearn.ensemble import (RandomForestRegressor, RandomForestClassifier, ExtraTreesClassifier, ExtraTreesRegressor, AdaBoostClassifier, GradientBoostingClassifier, AdaBoostRegressor, GradientBoostingRegressor) from sklearn.svm import SVR, SVC from sklearn.linear_model import Ridge, Lasso, ElasticNet from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor from sklearn.tree import ( DecisionTreeClassifier, DecisionTreeRegressor, ExtraTreeClassifier, ExtraTreeRegressor ) from sklearn.pipeline import Pipeline from qiime2.plugin import get_available_cores import q2templates import pandas as pd import numpy as np import matplotlib.pyplot as plt import pkg_resources from scipy.sparse import issparse from scipy.stats import randint import biom import re from .visuals import (_linear_regress, _plot_confusion_matrix, _plot_RFE, _regplot_from_dataframe, _generate_roc_plots) _classifiers = ['RandomForestClassifier', 'ExtraTreesClassifier', 'GradientBoostingClassifier', 'AdaBoostClassifier', 'KNeighborsClassifier', 'LinearSVC', 'SVC'] parameters = { 'ensemble': {"max_depth": [4, 8, 16, None], "max_features": [None, 'sqrt', 'log2', 0.1], "min_samples_split": [0.001, 0.01, 0.1], "min_weight_fraction_leaf": [0.0001, 0.001, 0.01]}, 'bootstrap': {"bootstrap": [True, False]}, 'criterion': {"criterion": ["gini", "entropy"]}, 'svm': {"C": [1, 0.5, 0.1, 0.9, 0.8], "tol": [0.00001, 0.0001, 0.001, 0.01], "shrinking": [True, False]}, 'kneighbors': {"n_neighbors": randint(2, 15), "weights": ['uniform', 'distance'], "leaf_size": randint(15, 100)}, 'linear': {"alpha": [0.0001, 0.01, 1.0, 10.0, 1000.0], "tol": [0.00001, 0.0001, 0.001, 0.01]} } TEMPLATES = pkg_resources.resource_filename('q2_sample_classifier', 'assets') def _extract_features(feature_data): ids = feature_data.ids('observation') features = np.empty(feature_data.shape[1], dtype=dict) for i, row in enumerate(feature_data.matrix_data.T): features[i] = {ids[ix]: d for ix, d in zip(row.indices, row.data)} return features def _load_data(feature_data, targets_metadata, missing_samples, extract=True): '''Load data and generate training and test sets. feature_data: pd.DataFrame feature X sample values. targets_metadata: qiime2.Metadata target (columns) X sample (rows) values. ''' # Load metadata, attempt to convert to numeric targets = targets_metadata.to_dataframe() if missing_samples == 'error': _validate_metadata_is_superset(targets, feature_data) # filter features and targest so samples match index = set(targets.index) index = [ix for ix in feature_data.ids() if ix in index] targets = targets.loc[index] feature_data = feature_data.filter(index, inplace=False) if extract: feature_data = _extract_features(feature_data) return feature_data, targets def _validate_metadata_is_superset(metadata, table): metadata_ids = set(metadata.index.tolist()) table_ids = set(table.ids()) missing_ids = table_ids.difference(metadata_ids) if len(missing_ids) > 0: raise ValueError('Missing samples in metadata: %r' % missing_ids) def _extract_important_features(index, top): '''Find top features, match names to indices, sort. index: ndarray Feature names top: array Feature importance scores, coef_ scores, or ranking of scores. ''' # is top a 1-d or multi-d array? # coef_ is a multidimensional array of shape = [n_class-1, n_features] if any(isinstance(i, list) for i in top) or top.ndim > 1: if issparse(top): top = top.todense() imp = pd.DataFrame( top, index=["importance{0}".format(n) for n in range(len(top))]).T # ensemble estimators and RFECV return 1-d arrays else: imp = pd.DataFrame(top, columns=["importance"]) imp.index = index imp.index.name = 'feature' imp = sort_importances(imp, ascending=False) return imp def _split_training_data(feature_data, targets, column, test_size=0.2, stratify=None, random_state=None, drop_na=True): '''Split data sets into training and test sets. feature_data: biom.Table feature X sample values. targets: pandas.DataFrame target (columns) X sample (rows) values. column: str Target column contained in targets. test_size: float Fraction of data to be reserved as test data. stratify: array-like Stratify data using this as class labels. E.g., set to df column by setting stratify=df[column] random_state: int or None Int to use for seeding random state. Random if None. ''' # Define target / predictor data targets = targets[column] if drop_na: targets = targets.dropna() if test_size > 0.0: try: y_train, y_test = train_test_split( targets, test_size=test_size, stratify=stratify, random_state=random_state) except ValueError: _stratification_error() else: warning_msg = _warn_zero_test_split() warnings.warn(warning_msg, UserWarning) X_train, X_test, y_train, y_test = ( feature_data, feature_data, targets, targets) tri = y_train.index # filter and sort biom tables to match split/filtered metadata ids # skip filtering if no splitting/dropna was performed # if test_size > 0.0 is implicit, so don't need to worry about initializing # X_train and X_test in an else statement. if list(tri) != list(feature_data.ids()): tei = y_test.index X_train = feature_data.filter(tri, inplace=False).sort_order(tri) X_test = feature_data.filter(tei, inplace=False).sort_order(tei) return X_train, X_test, y_train, y_test def _stratification_error(): raise ValueError(( 'You have chosen to predict a metadata column that contains ' 'one or more values that match only one sample. For proper ' 'stratification of data into training and test sets, each ' 'class (value) must contain at least two samples. This is a ' 'requirement for classification problems, but stratification ' 'can be disabled for regression by setting stratify=False. ' 'Alternatively, remove all samples that bear a unique class ' 'label for your chosen metadata column. Note that disabling ' 'stratification can negatively impact predictive accuracy for ' 'small data sets.')) def _rfecv_feature_selection(feature_data, targets, estimator, cv=5, step=1, scoring=None, n_jobs=1): '''Optimize feature depth by testing model accuracy at multiple feature depths with cross-validated recursive feature elimination. __________ Parameters __________ feature_data: list of dicts Training set feature data x samples. targets: pandas.DataFrame Training set target value data x samples. cv: int Number of k-fold cross-validations to perform. step: float or int If float, reduce this fraction of features at each step. If int, reduce this number of features at each step. estimator: sklearn classifier estimator to use, with parameters set. If none, default to random forests. n_jobs: int Number of parallel jobs to run. For other params, see sklearn.ensemble.RandomForestRegressor. __________ Returns __________ rfecv: sklearn estimator Can be used to predict target values for test data. importance: pandas.DataFrame List of top features. ''' rfecv = Pipeline( [('dv', estimator.named_steps.dv), ('est', RFECV(estimator=estimator.named_steps.est, step=step, cv=cv, scoring=scoring, n_jobs=n_jobs))]) rfecv.fit(feature_data, targets.values.ravel()) # Describe top features n_opt = rfecv.named_steps.est.n_features_ importance = _extract_important_features( rfecv.named_steps.dv.get_feature_names_out(), rfecv.named_steps.est.ranking_) importance = sort_importances(importance, ascending=True)[:n_opt] rfe_scores = _extract_rfe_scores(rfecv.named_steps.est) return importance, rfe_scores def _extract_rfe_scores(rfecv): grid_scores_ = rfecv.cv_results_['mean_test_score'] n_features = len(rfecv.ranking_) # If using fractional step, step = integer of fraction * n_features if rfecv.step < 1: rfecv.step = int(rfecv.step * n_features) # Need to manually calculate x-axis, grid_scores_ is a 1-d array x = [n_features - (n * rfecv.step) for n in range(len(grid_scores_)-1, -1, -1)] if x[0] < 1: x[0] = 1 return pd.Series(grid_scores_, index=x, name='Accuracy') def nested_cross_validation(table, metadata, cv, random_state, n_jobs, n_estimators, estimator, stratify, parameter_tuning, classification, scoring, missing_samples='error'): if n_jobs == 0: n_jobs = get_available_cores() # extract column name from NumericMetadataColumn column = metadata.name # load feature data, metadata targets X_train, y_train = _load_data( table, metadata, missing_samples=missing_samples) # disable feature selection for unsupported estimators optimize_feature_selection, calc_feature_importance = \ _disable_feature_selection(estimator, False) # specify parameters and distributions to sample from for parameter tuning estimator, param_dist, parameter_tuning = _set_parameters_and_estimator( estimator, table, y_train[column], column, n_estimators, n_jobs, cv, random_state, parameter_tuning, classification) # predict values for all samples via (nested) CV scores, predictions, importances, tops, probabilities = \ _fit_and_predict_cv( X_train, y_train[column], estimator, param_dist, n_jobs, scoring, random_state, cv, stratify, calc_feature_importance, parameter_tuning) # Print accuracy score to stdout print("Estimator Accuracy: {0} ± {1}".format( np.mean(scores), np.std(scores))) # TODO: save down estimator with tops parameters (currently the estimator # would be untrained, and tops parameters are not reported) return predictions['prediction'], importances, probabilities def _fit_estimator(features, targets, estimator, n_estimators=100, step=0.05, cv=5, random_state=None, n_jobs=1, optimize_feature_selection=False, parameter_tuning=False, missing_samples='error', classification=True): if n_jobs == 0: n_jobs = get_available_cores() # extract column name from CategoricalMetadataColumn column = targets.to_series().name # load data X_train, y_train = _load_data( features, targets, missing_samples=missing_samples) # disable feature selection for unsupported estimators optimize_feature_selection, calc_feature_importance = \ _disable_feature_selection(estimator, optimize_feature_selection) # specify parameters and distributions to sample from for parameter tuning estimator, param_dist, parameter_tuning = _set_parameters_and_estimator( estimator, features, targets, column, n_estimators, n_jobs, cv, random_state, parameter_tuning, classification=classification) # optimize training feature count if optimize_feature_selection: X_train, importances, rfe_scores = _optimize_feature_selection( X_train=X_train, y_train=y_train, estimator=estimator, cv=cv, step=step, n_jobs=n_jobs) else: importances = None # optimize tuning parameters on your training set if parameter_tuning: # tune parameters estimator = _tune_parameters( X_train, y_train, estimator, param_dist, n_iter_search=20, n_jobs=n_jobs, cv=cv, random_state=random_state).best_estimator_ # fit estimator estimator.fit(X_train, y_train.values.ravel()) importances = _attempt_to_calculate_feature_importances( estimator, calc_feature_importance, optimize_feature_selection, importances) if optimize_feature_selection: estimator.rfe_scores = rfe_scores # TODO: drop this when we get around to supporting optional outputs # methods cannot output an empty importances artifact; only KNN has no # feature importance, but just warn and output all features as # importance = 1 if importances is None: _warn_feature_selection() importances = pd.DataFrame(index=features.ids('observation')) importances["importance"] = np.nan importances.index.name = 'feature' return estimator, importances def _attempt_to_calculate_feature_importances( estimator, calc_feature_importance, optimize_feature_selection, importances=None): # calculate feature importances, if appropriate for the estimator if calc_feature_importance: importances = _calculate_feature_importances(estimator) # otherwise, if optimizing feature selection, just return ranking from RFE elif optimize_feature_selection: pass # otherwise, we have no weights nor selection, so features==n_features else: importances = None return importances def _prepare_training_data(features, targets, column, test_size, random_state, load_data=True, stratify=True, missing_samples='error'): # load data if load_data: features, targets = _load_data( features, targets, missing_samples=missing_samples, extract=False) # split into training and test sets if stratify: strata = targets[column] else: strata = None X_train, X_test, y_train, y_test = _split_training_data( features, targets, column, test_size, strata, random_state) return X_train, X_test, y_train, y_test def _optimize_feature_selection(X_train, y_train, estimator, cv, step, n_jobs): importance, rfe_scores = _rfecv_feature_selection( X_train, y_train, estimator=estimator, cv=cv, step=step, n_jobs=n_jobs) index = set(importance.index) X_train = [{k: r[k] for k in r.keys() & index} for r in X_train] return X_train, importance, rfe_scores def _calculate_feature_importances(estimator): # only set calc_feature_importance=True if estimator has attributes # feature_importances_ or coef_ to report feature importance/weights try: importances = _extract_important_features( estimator.named_steps.dv.get_feature_names_out(), estimator.named_steps.est.feature_importances_) # is there a better way to determine whether estimator has coef_ ? except AttributeError: importances = _extract_important_features( estimator.named_steps.dv.get_feature_names_out(), estimator.named_steps.est.coef_) return importances def _predict_and_plot(output_dir, y_test, y_pred, vmin=None, vmax=None, classification=True, palette='sirocco'): if classification: x_classes = set(y_test.unique()) y_classes = set(y_pred.unique()) # validate: if classes are exclusive, accuracy is zero; user probably # input the wrong data! if len(x_classes.intersection(y_classes)) < 1: raise _class_overlap_error() else: classes = sorted(list(x_classes.union(y_classes))) predictions, predict_plot = _plot_confusion_matrix( y_test, y_pred, classes, normalize=True, palette=palette, vmin=vmin, vmax=vmax) else: predictions = _linear_regress(y_test, y_pred) predict_plot = _regplot_from_dataframe(y_test, y_pred) if output_dir is not None: predict_plot.get_figure().savefig( join(output_dir, 'predictions.png'), bbox_inches='tight') predict_plot.get_figure().savefig( join(output_dir, 'predictions.pdf'), bbox_inches='tight') plt.close('all') return predictions, predict_plot def _class_overlap_error(): raise ValueError( 'Predicted and true metadata values do not overlap. Check your ' 'inputs to ensure that you are using the correct data. Is the ' 'correct metadata column being compared to these predictions? Was ' 'your model trained on the correct type of data? Prediction ' 'sample classes (metadata values) should match or be a subset of ' 'training sample classes. If you are attempting to calculate ' 'accuracy scores on predictions from a sample regressor, use ' 'scatterplot instead.') def _match_series_or_die(predictions, truth, missing_samples='error'): # validate input metadata and predictions, output intersection. # truth must be a superset of predictions truth_ids = set(truth.index) predictions_ids = set(predictions.index) missing_ids = predictions_ids - truth_ids if missing_samples == 'error' and len(missing_ids) > 0: raise ValueError('Missing samples in metadata: %r' % missing_ids) # match metadata / prediction IDs predictions, truth = predictions.align(truth, axis=0, join='inner') return predictions, truth def _plot_accuracy(output_dir, predictions, truth, probabilities, missing_samples, classification, palette, plot_title, vmin=None, vmax=None): '''Plot accuracy results and send to visualizer on either categorical or numeric data inside two pd.Series ''' truth = truth.to_series() # check if test_size == 0.0 and all predictions are complete dataset if (missing_samples == 'ignore') & ( predictions.shape[0] == truth.shape[0]): warning_msg = _warn_zero_test_split() else: warning_msg = None predictions, truth = _match_series_or_die( predictions, truth, missing_samples) # calculate prediction accuracy and plot results predictions, predict_plot = _predict_and_plot( output_dir, truth, predictions, vmin=vmin, vmax=vmax, classification=classification, palette=palette) # optionally generate ROC curves for classification results if probabilities is not None: probabilities, truth = _match_series_or_die( probabilities, truth, missing_samples) roc = _generate_roc_plots(truth, probabilities, palette) roc.savefig(join(output_dir, 'roc_plot.png'), bbox_inches='tight') roc.savefig(join(output_dir, 'roc_plot.pdf'), bbox_inches='tight') # output to viz _visualize(output_dir=output_dir, estimator=None, cm=predictions, roc=probabilities, optimize_feature_selection=False, title=plot_title, warning_msg=warning_msg) def sort_importances(importances, ascending=False): return importances.sort_values( by=importances.columns[0], ascending=ascending) def _extract_estimator_parameters(estimator): # summarize model accuracy and params # (drop pipeline params and individual base estimators) estimator_params = {k: v for k, v in estimator.get_params().items() if k.startswith('est__') and k != 'est__base_estimator'} return pd.Series(estimator_params, name='Parameter setting') def _summarize_estimator(output_dir, sample_estimator): try: rfep = _plot_RFE( x=sample_estimator.rfe_scores.index, y=sample_estimator.rfe_scores) rfep.savefig(join(output_dir, 'rfe_plot.png')) rfep.savefig(join(output_dir, 'rfe_plot.pdf')) plt.close('all') optimize_feature_selection = True # generate rfe scores file df = pd.DataFrame(data={'rfe_score': sample_estimator.rfe_scores}, index=sample_estimator.rfe_scores.index) df.index.name = 'feature_count' df.to_csv(join(output_dir, 'rfe_scores.tsv'), sep='\t', index=True) # if the rfe_scores attribute does not exist, do nothing except AttributeError: optimize_feature_selection = False _visualize(output_dir=output_dir, estimator=sample_estimator, cm=None, roc=None, optimize_feature_selection=optimize_feature_selection, title='Estimator Summary') def _visualize(output_dir, estimator, cm, roc, optimize_feature_selection=True, title='results', warning_msg=None): pd.set_option('display.max_colwidth', None) # summarize model accuracy and params if estimator is not None: result = _extract_estimator_parameters(estimator) result = q2templates.df_to_html(result.to_frame()) else: result = False if cm is not None: cm.to_csv(join( output_dir, 'predictive_accuracy.tsv'), sep='\t', index=True) cm = q2templates.df_to_html(cm) if roc is not None: roc = True index = join(TEMPLATES, 'index.html') q2templates.render(index, output_dir, context={ 'title': title, 'result': result, 'predictions': cm, 'roc': roc, 'optimize_feature_selection': optimize_feature_selection, 'warning_msg': warning_msg}) def _visualize_knn(output_dir, params: pd.Series): result = q2templates.df_to_html(params.to_frame()) index = join(TEMPLATES, 'index.html') q2templates.render(index, output_dir, context={ 'title': 'Estimator Summary', 'result': result, 'predictions': None, 'importances': None, 'classification': True, 'optimize_feature_selection': False}) def _map_params_to_pipeline(param_dist): return {'est__' + param: dist for param, dist in param_dist.items()} def _tune_parameters(X_train, y_train, estimator, param_dist, n_iter_search=20, n_jobs=1, cv=None, random_state=None): # run randomized search random_search = RandomizedSearchCV( estimator, param_distributions=param_dist, n_iter=n_iter_search, n_jobs=n_jobs, cv=cv, random_state=random_state) random_search.fit(X_train, y_train.values.ravel()) return random_search def _fit_and_predict_cv(table, metadata, estimator, param_dist, n_jobs, scoring=accuracy_score, random_state=None, cv=10, stratify=True, calc_feature_importance=False, parameter_tuning=False): '''train and test estimators via cross-validation. scoring: str use accuracy_score for classification, mean_squared_error for regression. ''' # Set CV method if stratify: _cv = StratifiedKFold( n_splits=cv, shuffle=True, random_state=random_state) else: _cv = KFold(n_splits=cv, shuffle=True, random_state=random_state) predictions = pd.DataFrame() probabilities = pd.DataFrame() scores = [] top_params = [] importances = [] if isinstance(table, biom.Table): features = _extract_features(table) else: features = table for train_index, test_index in _cv.split(features, metadata): X_train = features[train_index] y_train = metadata.iloc[train_index] # perform parameter tuning in inner loop if parameter_tuning: estimator = _tune_parameters( X_train, y_train, estimator, param_dist, n_iter_search=20, n_jobs=n_jobs, cv=cv, random_state=random_state).best_estimator_ else: # fit estimator on inner outer training set estimator.fit(X_train, y_train.values.ravel()) # predict values for outer loop test set test_set = features[test_index] index = metadata.iloc[test_index] pred = pd.DataFrame(estimator.predict(test_set), index=index.index) # log predictions results predictions = pd.concat([predictions, pred]) # log prediction probabilities (classifiers only) if estimator.named_steps.est.__class__.__name__ in _classifiers: probs = predict_probabilities(estimator, test_set, index.index) probabilities = pd.concat([probabilities, probs]) # log accuracy on that fold scores += [scoring(pred, index)] # log feature importances if calc_feature_importance: imp = _calculate_feature_importances(estimator) importances += [imp] # log top parameters # for now we will cast as a str (instead of dict) so that we can count # frequency of unique elements below top_params += [str(estimator.named_steps.est.get_params())] # Report most frequent best params # convert top_params to a set, order by count (hence str conversion above) # max will be the most frequent... then we convert back to a dict via eval # which should be safe since this is always a dict of param values reported # by sklearn. tops = max(set(top_params), key=top_params.count) tops = eval(tops) # calculate mean feature importances if calc_feature_importance: importances = _mean_feature_importance(importances) else: importances = _null_feature_importance(table) predictions.columns = ['prediction'] predictions.index.name = 'SampleID' probabilities.index.name = 'SampleID' return scores, predictions, importances, tops, probabilities def predict_probabilities(estimator, test_set, index): ''' Predict class probabilities for a set of test samples. estimator: sklearn trained classifier test_set: array-like of y_values (features) for test set samples that will have their class probabilities predicted. index: array-like of sample names ''' # all used classifiers have a predict_proba attribute # (approximated for SVCs) probs = pd.DataFrame(estimator.predict_proba(test_set), index=index, columns=estimator.classes_) return probs def _mean_feature_importance(importances): '''Calculate mean feature importance across a list of pd.dataframes containing importance scores of the same features from multiple models (e.g., CV importance scores). ''' imp = pd.concat(importances, axis=1, sort=True) # groupby column name instead of taking column mean to support 2d arrays imp = imp.groupby(imp.columns, axis=1).mean() return imp.sort_values(imp.columns[0], ascending=False) def _null_feature_importance(table): feature_extractor = DictVectorizer() feature_extractor.fit(table) imp = pd.DataFrame(index=feature_extractor.get_feature_names_out()) imp.index.name = "feature" imp["importance"] = 1 return imp def _select_estimator(estimator, n_jobs, n_estimators, random_state=None): '''Select estimator and parameters from argument name.''' # Regressors if estimator == 'RandomForestRegressor': param_dist = {**parameters['ensemble'], **parameters['bootstrap']} estimator = RandomForestRegressor( n_jobs=n_jobs, n_estimators=n_estimators, random_state=random_state) elif estimator == 'ExtraTreesRegressor': param_dist = {**parameters['ensemble'], **parameters['bootstrap']} estimator = ExtraTreesRegressor( n_jobs=n_jobs, n_estimators=n_estimators, random_state=random_state) elif estimator == 'GradientBoostingRegressor': param_dist = parameters['ensemble'] estimator = GradientBoostingRegressor( n_estimators=n_estimators, random_state=random_state) elif estimator == 'SVR': param_dist = {**parameters['svm'], 'epsilon': [0.0, 0.1]} estimator = SVR(kernel='rbf', gamma='scale') elif estimator == 'LinearSVR': param_dist = {**parameters['svm'], 'epsilon': [0.0, 0.1]} estimator = SVR(kernel='linear') elif estimator == 'Ridge': param_dist = parameters['linear'] estimator = Ridge(solver='auto', random_state=random_state) elif estimator == 'Lasso': param_dist = parameters['linear'] estimator = Lasso(random_state=random_state) elif estimator == 'ElasticNet': param_dist = parameters['linear'] estimator = ElasticNet(random_state=random_state) elif estimator == 'KNeighborsRegressor': param_dist = parameters['kneighbors'] estimator = KNeighborsRegressor(algorithm='auto') # Classifiers elif estimator == 'RandomForestClassifier': param_dist = {**parameters['ensemble'], **parameters['bootstrap'], **parameters['criterion']} estimator = RandomForestClassifier( n_jobs=n_jobs, n_estimators=n_estimators, random_state=random_state) elif estimator == 'ExtraTreesClassifier': param_dist = {**parameters['ensemble'], **parameters['bootstrap'], **parameters['criterion']} estimator = ExtraTreesClassifier( n_jobs=n_jobs, n_estimators=n_estimators, random_state=random_state) elif estimator == 'GradientBoostingClassifier': param_dist = parameters['ensemble'] estimator = GradientBoostingClassifier( n_estimators=n_estimators, random_state=random_state) elif estimator == 'LinearSVC': param_dist = parameters['svm'] estimator = SVC(kernel='linear', random_state=random_state, gamma='scale', probability=True) elif estimator == 'SVC': param_dist = parameters['svm'] estimator = SVC(kernel='rbf', random_state=random_state, gamma='scale', probability=True) elif estimator == 'KNeighborsClassifier': param_dist = parameters['kneighbors'] estimator = KNeighborsClassifier(algorithm='auto') return param_dist, estimator def _train_adaboost_base_estimator(table, metadata, column, base_estimator, n_estimators, n_jobs, cv, random_state=None, parameter_tuning=False, classification=True, missing_samples='error'): param_dist = parameters['ensemble'] if classification: base_est = { 'DecisionTree': DecisionTreeClassifier(), 'ExtraTrees': ExtraTreeClassifier() } pipe_base_estimator = base_est[base_estimator] adaboost_estimator = AdaBoostClassifier else: base_est = { 'DecisionTree': DecisionTreeRegressor(), 'ExtraTrees': ExtraTreeRegressor() } pipe_base_estimator = base_est[base_estimator] adaboost_estimator = AdaBoostRegressor estimator = Pipeline( [('dv', DictVectorizer()), ('est', pipe_base_estimator)]) if parameter_tuning: features, targets = _load_data( table, metadata, missing_samples=missing_samples) param_dist = _map_params_to_pipeline(param_dist) base_estimator = _tune_parameters( features, targets[column], estimator, param_dist, n_jobs=n_jobs, cv=cv, random_state=random_state).best_estimator_ return Pipeline( [('dv', estimator.named_steps.dv), ('est', adaboost_estimator(estimator=estimator.named_steps.est, n_estimators=n_estimators, random_state=random_state))]) def _disable_feature_selection(estimator, optimize_feature_selection): '''disable feature selection for unsupported classifiers.''' unsupported = ['KNeighborsClassifier', 'SVC', 'KNeighborsRegressor', 'SVR'] if estimator in unsupported: optimize_feature_selection = False calc_feature_importance = False _warn_feature_selection() else: calc_feature_importance = True return optimize_feature_selection, calc_feature_importance def _set_parameters_and_estimator(estimator, table, metadata, column, n_estimators, n_jobs, cv, random_state, parameter_tuning, classification=True, missing_samples='error'): # specify parameters and distributions to sample from for parameter tuning if estimator.startswith("AdaBoost"): base_estimator = re.search(r"\[([A-Za-z]+)\]", estimator).group(1) estimator = _train_adaboost_base_estimator( table, metadata, column, base_estimator, n_estimators, n_jobs, cv, random_state, parameter_tuning, classification=classification, missing_samples=missing_samples) parameter_tuning = False param_dist = None else: param_dist, estimator = _select_estimator( estimator, n_jobs, n_estimators, random_state) estimator = Pipeline([('dv', DictVectorizer()), ('est', estimator)]) param_dist = _map_params_to_pipeline(param_dist) return estimator, param_dist, parameter_tuning def _warn_feature_selection(): warning = ( ('This estimator does not support recursive feature extraction with ' 'the parameter settings requested. See documentation or try a ' 'different estimator model.')) warnings.warn(warning, UserWarning) def _warn_zero_test_split(): return 'Using test_size = 0.0, you are using your complete dataset for ' \ 'fitting the estimator. Hence, any returned model evaluations are ' \ 'based on that same training dataset and are not representative of ' \ 'your model\'s performance on a previously unseen dataset. Please ' \ 'consider evaluating this model on a separate dataset.' q2-sample-classifier-2024.5.0/q2_sample_classifier/visuals.py000066400000000000000000000355501462552620600240360ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- from sklearn.metrics import ( mean_squared_error, confusion_matrix, accuracy_score, roc_curve, auc) from sklearn.preprocessing import label_binarize from itertools import cycle from numpy import interp import pandas as pd import numpy as np import seaborn as sns from scipy.stats import linregress import matplotlib.pyplot as plt def _custom_palettes(): return { 'YellowOrangeBrown': 'YlOrBr', 'YellowOrangeRed': 'YlOrRd', 'OrangeRed': 'OrRd', 'PurpleRed': 'PuRd', 'RedPurple': 'RdPu', 'BluePurple': 'BuPu', 'GreenBlue': 'GnBu', 'PurpleBlue': 'PuBu', 'YellowGreen': 'YlGn', 'summer': 'summer_r', 'copper': 'copper_r', 'viridis': 'viridis_r', 'cividis': 'cividis_r', 'plasma': 'plasma_r', 'inferno': 'inferno_r', 'magma': 'magma_r', 'sirocco': sns.cubehelix_palette( dark=0.15, light=0.95, as_cmap=True), 'drifting': sns.cubehelix_palette( start=5, rot=0.4, hue=0.8, as_cmap=True), 'melancholy': sns.cubehelix_palette( start=25, rot=0.4, hue=0.8, as_cmap=True), 'enigma': sns.cubehelix_palette( start=2, rot=0.6, gamma=2.0, hue=0.7, dark=0.45, as_cmap=True), 'eros': sns.cubehelix_palette(start=0, rot=0.4, gamma=2.0, hue=2, light=0.95, dark=0.5, as_cmap=True), 'spectre': sns.cubehelix_palette( start=1.2, rot=0.4, gamma=2.0, hue=1, dark=0.4, as_cmap=True), 'ambition': sns.cubehelix_palette(start=2, rot=0.9, gamma=3.0, hue=2, light=0.9, dark=0.5, as_cmap=True), 'mysteriousstains': sns.light_palette( 'baby shit green', input='xkcd', as_cmap=True), 'daydream': sns.blend_palette( ['egg shell', 'dandelion'], input='xkcd', as_cmap=True), 'solano': sns.blend_palette( ['pale gold', 'burnt umber'], input='xkcd', as_cmap=True), 'navarro': sns.blend_palette( ['pale gold', 'sienna', 'pine green'], input='xkcd', as_cmap=True), 'dandelions': sns.blend_palette( ['sage', 'dandelion'], input='xkcd', as_cmap=True), 'deepblue': sns.blend_palette( ['really light blue', 'petrol'], input='xkcd', as_cmap=True), 'verve': sns.cubehelix_palette( start=1.4, rot=0.8, gamma=2.0, hue=1.5, dark=0.4, as_cmap=True), 'greyscale': sns.blend_palette( ['light grey', 'dark grey'], input='xkcd', as_cmap=True)} def _regplot_from_dataframe(x, y, plot_style="whitegrid", arb=True, color="grey"): '''Seaborn regplot with true 1:1 ratio set by arb (bool).''' sns.set_style(plot_style) reg = sns.regplot(x=x, y=y, color=color) plt.xlabel('True value') plt.ylabel('Predicted value') if arb is True: x0, x1 = reg.axes.get_xlim() y0, y1 = reg.axes.get_ylim() lims = [min(x0, y0), max(x1, y1)] reg.axes.plot(lims, lims, ':k') return reg def _linear_regress(actual, pred): '''Calculate linear regression on predicted versus expected values. actual: pandas.DataFrame Actual y-values for test samples. pred: pandas.DataFrame Predicted y-values for test samples. ''' slope, intercept, r_value, p_value, std_err = linregress(actual, pred) mse = mean_squared_error(actual, pred) return pd.DataFrame( [(mse, r_value, r_value**2, p_value, std_err, slope, intercept)], columns=["Mean squared error", "r-value", "r-squared", "P-value", "Std Error", "Slope", "Intercept"], index=[actual.name]) def _plot_heatmap_from_confusion_matrix(cm, palette, vmin=None, vmax=None): palette = _custom_palettes()[palette] plt.figure() scaler, labelsize, dpi, cbar_min = 20, 8, 100, .15 sns.set(rc={'xtick.labelsize': labelsize, 'ytick.labelsize': labelsize, 'figure.dpi': dpi}) fig, (ax, cax) = plt.subplots(ncols=2, constrained_layout=True) heatmap = sns.heatmap(cm, vmin=vmin, vmax=vmax, cmap=palette, ax=ax, cbar_ax=cax, cbar_kws={'label': 'Proportion'}, square=True, xticklabels=True, yticklabels=True) # Resize the plot dynamically based on number of classes hm_pos = ax.get_position() scale = len(cm) / scaler # prevent cbar from getting unreadably small cbar_height = max(cbar_min, scale) ax.set_position([hm_pos.x0, hm_pos.y0, scale, scale]) cax.set_position([hm_pos.x0 + scale * .95, hm_pos.y0, scale / len(cm), cbar_height]) # Make the heatmap subplot (not the colorbar) the active axis object so # labels apply correctly on return plt.sca(ax) return heatmap def _add_sample_size_to_xtick_labels(ser, classes): '''ser is a pandas series.''' labels = ['{0} (n={1})'.format(c, ser[ser == c].count()) for c in classes] return labels def _plot_confusion_matrix(y_test, y_pred, classes, normalize, palette, vmin=None, vmax=None): accuracy = accuracy_score(y_test, pd.DataFrame(y_pred)) cm = confusion_matrix(y_test, y_pred) # normalize if normalize: cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis] # fill na values (e.g., true values that were not predicted) otherwise # these will appear as whitespace in plots and results table. cm = np.nan_to_num(cm) _check_vmin_and_vmax(cm, vmin, vmax) confusion = _plot_heatmap_from_confusion_matrix(cm, palette, vmin=vmin, vmax=vmax) x_tick_labels = _add_sample_size_to_xtick_labels(y_pred, classes) y_tick_labels = _add_sample_size_to_xtick_labels(y_test, classes) plt.ylabel('True label') plt.xlabel('Predicted label') confusion.set_xticklabels(x_tick_labels, rotation=90, ha='center') confusion.set_yticklabels(y_tick_labels, rotation=0, ha='right') # generate confusion matrix as pd.DataFrame for viewing predictions = pd.DataFrame(cm, index=classes, columns=classes) # add empty row/column to show overall accuracy in bottom right cell # baseline error = error rate for a classifier that always guesses the # most common class n_samples, n_samples_largest_class, basline_accuracy, accuracy_ratio = \ _calculate_baseline_accuracy(y_test, accuracy) predictions["Overall Accuracy"] = "" predictions.loc["Overall Accuracy"] = "" predictions.loc["Baseline Accuracy"] = "" predictions.loc["Accuracy Ratio"] = "" predictions.loc["Overall Accuracy", "Overall Accuracy"] = accuracy predictions.loc["Baseline Accuracy", "Overall Accuracy"] = basline_accuracy predictions.loc["Accuracy Ratio", "Overall Accuracy"] = accuracy_ratio return predictions, confusion def _check_vmin_and_vmax(cm, vmin, vmax): lowest_frequency = np.amin(cm) highest_frequency = np.amax(cm) error = '' if vmin is not None: if vmin > lowest_frequency: error += ('vmin must be less than or equal to the lowest ' 'predicted class frequency:\n' f'\t{vmin!r} is greater than {lowest_frequency!r}') if vmax is not None: if vmax < highest_frequency: if error: error += '\n' error += ('vmax must be greater than or equal to the highest ' 'predicted class frequency:\n' f'\t{vmax!r} is less than {highest_frequency!r}') if error: raise ValueError(error) def _calculate_baseline_accuracy(y_test, accuracy): n_samples = len(y_test) n_samples_largest_class = y_test.value_counts().iloc[0] basline_accuracy = n_samples_largest_class / n_samples accuracy_ratio = accuracy / basline_accuracy return n_samples, n_samples_largest_class, basline_accuracy, accuracy_ratio def _plot_RFE(x, y): rfe = plt.figure() plt.xlabel("Feature Count") plt.ylabel("Accuracy") plt.plot(x, y, 'grey') return rfe def _binarize_labels(metadata, classes): binarized_targets = label_binarize(metadata, classes=classes) # to generalize downstream steps, we need to coerce binary data into an # array of shape [n_samples, n_classes] if len(classes) == 2: binarized_targets = np.hstack(( 1 - binarized_targets, binarized_targets)) return binarized_targets def _generate_roc_plots(metadata, probabilities, palette): ''' metadata: pd.Series of target values. probabilities: pd.DataFrame of class probabilities. palette: str specifying sample-classifier colormap name. Returns a pretty Receiver Operating Characteristic plot with AUC scores. ''' classes = probabilities.columns probabilities = probabilities.values # only accepts binary inputs, so binarize the target data binarized_targets = _binarize_labels(metadata, classes) # Compute ROC curve and ROC area for each class fpr, tpr, roc_auc = _roc_per_class( binarized_targets, probabilities, classes) # Compute micro-average ROC curve and ROC area under curve fpr, tpr, roc_auc = _roc_micro_average( binarized_targets, probabilities, fpr, tpr, roc_auc) # Compute macro-average ROC curve and ROC area fpr, tpr, roc_auc = _roc_macro_average(fpr, tpr, roc_auc, classes) # generate ROC plot colors = _roc_palette(palette, len(classes)) return _roc_plot(fpr, tpr, roc_auc, classes, colors) def _roc_palette(palette, n_classes): ''' palette: str specifying sample-classifier colormap name. n_classes: int specifying number of classes (== n of colors to select). Returns an iterator of colors. ''' palette = _custom_palettes()[palette] # specify color palette. Use different specification for str palette name # vs. ListedColormap. try: colors = cycle(sns.color_palette(palette, n_colors=n_classes)) except TypeError: # if using a continuous ListedColormap, select from normalized # colorspace. We use linspace start=0.1 to avoid light colors at start # of some colormaps. palette = palette(np.linspace(0.1, 1, n_classes)) colors = cycle(palette) return colors # adapted from scikit-learn examples # https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html def _roc_per_class(binarized_targets, probabilities, classes): ''' binarized_targets: array of binarized class labels of dimensions [n, c], where n = number of samples, c = number of classes. probabilities: array of class probabilities of dimensions [n, c], where n = number of samples, c = number of classes. classes: list of classes. Returns dicts of False Positive Rate (fpr), True Detection Rate (tdr), and ROC Area Under Curve (roc_auc) for each class. ''' fpr = dict() tpr = dict() roc_auc = dict() for i, c in zip(range(len(classes)), classes): fpr[c], tpr[c], _ = roc_curve( binarized_targets[:, i], probabilities[:, i]) roc_auc[c] = auc(fpr[c], tpr[c]) return fpr, tpr, roc_auc # adapted from scikit-learn examples # https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html def _roc_micro_average(binarized_targets, probabilities, fpr, tpr, roc_auc): ''' binarized_targets: array of binarized class labels of dimensions [n, c], where n = number of samples, c = number of classes. probabilities: array of class probabilities of dimensions [n, c], where n = number of samples, c = number of classes. fpr: dict of false-positive rates for each class. tdr: dict of true-detection rates for each class. roc_auc: dict of auc scores for each class. Returns fpr, tdr, roc_auc with micro average scores added. ''' fpr["micro"], tpr["micro"], _ = roc_curve( binarized_targets.ravel(), probabilities.ravel()) roc_auc["micro"] = auc(fpr["micro"], tpr["micro"]) return fpr, tpr, roc_auc # adapted from scikit-learn examples # https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html def _roc_macro_average(fpr, tpr, roc_auc, classes): ''' fpr: dict of false-positive rates for each class. tdr: dict of true-detection rates for each class. roc_auc: dict of auc scores for each class. classes: list of classes. Returns fpr, tdr, roc_auc with micro average scores added. ''' # Aggregate all false positive rates for computing average all_fpr = np.unique(np.concatenate([fpr[c] for c in classes])) # Then interpolate all ROC curves at this point mean_tpr = np.zeros_like(all_fpr) for c in classes: mean_tpr += interp(all_fpr, fpr[c], tpr[c]) # Finally average it and compute AUC mean_tpr /= len(classes) fpr["macro"] = all_fpr tpr["macro"] = mean_tpr roc_auc["macro"] = auc(fpr["macro"], tpr["macro"]) return fpr, tpr, roc_auc # inspired by scikit-learn examples for multi-class ROC plots # https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html def _roc_plot(fpr, tpr, roc_auc, classes, colors): ''' fpr: dict of false-positive rates for each class. tdr: dict of true-detection rates for each class. roc_auc: dict of auc scores for each class. classes: list of classes. colors: list of colors. ''' fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 4), sharey=True) lw = 3 # plot averages in each panel for i in [0, 1]: axes[i].plot(fpr['micro'], tpr['micro'], color='navy', linestyle=':', lw=lw, label='micro-average (AUC = %0.2f)' % roc_auc['micro']) axes[i].plot(fpr['macro'], tpr['macro'], color='lightblue', linestyle=':', lw=lw, label='macro-average (AUC = %0.2f)' % roc_auc['macro']) # plot 1:1 ratio line axes[i].plot([0, 1], [0, 1], color='grey', lw=lw, linestyle='--', label='Chance') axes[i].set_xlim([0.0, 1.0]) axes[i].set_ylim([0.0, 1.05]) axes[i].set_xlabel('False Positive Rate') # left panel: averages only axes[0].set_ylabel('True Positive Rate') axes[0].set_title('Receiver Operating Characteristic Average Scores') axes[0].legend(loc="lower right") # right panel: averages and per-class ROCs axes[1].set_title('Per-Class Receiver Operating Characteristics') for c, color in zip(classes, colors): plt.plot(fpr[c], tpr[c], color=color, lw=lw, label='{0} (AUC = {1:0.2f})'.format(c, roc_auc[c])) axes[1].legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) return fig q2-sample-classifier-2024.5.0/setup.cfg000066400000000000000000000003041462552620600175150ustar00rootroot00000000000000[versioneer] VCS=git style=pep440 versionfile_source = q2_sample_classifier/_version.py versionfile_build = q2_sample_classifier/_version.py tag_prefix = parentdir_prefix = q2-sample-classifier- q2-sample-classifier-2024.5.0/setup.py000066400000000000000000000020461462552620600174130ustar00rootroot00000000000000# ---------------------------------------------------------------------------- # Copyright (c) 2017-2023, QIIME 2 development team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file LICENSE, distributed with this software. # ---------------------------------------------------------------------------- from setuptools import find_packages, setup import versioneer setup( name='q2-sample-classifier', version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), license='BSD-3-Clause', packages=find_packages(), author="Nicholas Bokulich", author_email="nbokulich@gmail.com", description="Machine learning classification and regression tools.", url="https://qiime2.org/", entry_points={ 'qiime2.plugins': ['q2-sample-classifier=q2_sample_classifier.plugin_setup:plugin'] }, package_data={ 'q2_sample_classifier.tests': ['data/*'], 'q2_sample_classifier': ['assets/index.html', 'citations.bib'] }, zip_safe=False, ) q2-sample-classifier-2024.5.0/versioneer.py000066400000000000000000002060221462552620600204340ustar00rootroot00000000000000 # Version: 0.18 # flake8: noqa """The Versioneer - like a rocketeer, but for versions. The Versioneer ============== * like a rocketeer, but for versions! * https://github.com/warner/python-versioneer * Brian Warner * License: Public Domain * Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy * [![Latest Version] (https://pypip.in/version/versioneer/badge.svg?style=flat) ](https://pypi.python.org/pypi/versioneer/) * [![Build Status] (https://travis-ci.org/warner/python-versioneer.png?branch=master) ](https://travis-ci.org/warner/python-versioneer) This is a tool for managing a recorded version number in distutils-based python projects. The goal is to remove the tedious and error-prone "update the embedded version string" step from your release process. Making a new release should be as easy as recording a new tag in your version-control system, and maybe making new tarballs. ## Quick Install * `pip install versioneer` to somewhere to your $PATH * add a `[versioneer]` section to your setup.cfg (see below) * run `versioneer install` in your source tree, commit the results ## Version Identifiers Source trees come from a variety of places: * a version-control system checkout (mostly used by developers) * a nightly tarball, produced by build automation * a snapshot tarball, produced by a web-based VCS browser, like github's "tarball from tag" feature * a release tarball, produced by "setup.py sdist", distributed through PyPI Within each source tree, the version identifier (either a string or a number, this tool is format-agnostic) can come from a variety of places: * ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows about recent "tags" and an absolute revision-id * the name of the directory into which the tarball was unpacked * an expanded VCS keyword ($Id$, etc) * a `_version.py` created by some earlier build step For released software, the version identifier is closely related to a VCS tag. Some projects use tag names that include more than just the version string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool needs to strip the tag prefix to extract the version identifier. For unreleased software (between tags), the version identifier should provide enough information to help developers recreate the same tree, while also giving them an idea of roughly how old the tree is (after version 1.2, before version 1.3). Many VCS systems can report a description that captures this, for example `git describe --tags --dirty --always` reports things like "0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the 0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has uncommitted changes. The version identifier is used for multiple purposes: * to allow the module to self-identify its version: `myproject.__version__` * to choose a name and prefix for a 'setup.py sdist' tarball ## Theory of Operation Versioneer works by adding a special `_version.py` file into your source tree, where your `__init__.py` can import it. This `_version.py` knows how to dynamically ask the VCS tool for version information at import time. `_version.py` also contains `$Revision$` markers, and the installation process marks `_version.py` to have this marker rewritten with a tag name during the `git archive` command. As a result, generated tarballs will contain enough information to get the proper version. To allow `setup.py` to compute a version too, a `versioneer.py` is added to the top level of your source tree, next to `setup.py` and the `setup.cfg` that configures it. This overrides several distutils/setuptools commands to compute the version when invoked, and changes `setup.py build` and `setup.py sdist` to replace `_version.py` with a small static file that contains just the generated version data. ## Installation See [INSTALL.md](./INSTALL.md) for detailed installation instructions. ## Version-String Flavors Code which uses Versioneer can learn about its version string at runtime by importing `_version` from your main `__init__.py` file and running the `get_versions()` function. From the "outside" (e.g. in `setup.py`), you can import the top-level `versioneer.py` and run `get_versions()`. Both functions return a dictionary with different flavors of version information: * `['version']`: A condensed version string, rendered using the selected style. This is the most commonly used value for the project's version string. The default "pep440" style yields strings like `0.11`, `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section below for alternative styles. * `['full-revisionid']`: detailed revision identifier. For Git, this is the full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". * `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the commit date in ISO 8601 format. This will be None if the date is not available. * `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that this is only accurate if run in a VCS checkout, otherwise it is likely to be False or None * `['error']`: if the version string could not be computed, this will be set to a string describing the problem, otherwise it will be None. It may be useful to throw an exception in setup.py if this is set, to avoid e.g. creating tarballs with a version string of "unknown". Some variants are more useful than others. Including `full-revisionid` in a bug report should allow developers to reconstruct the exact code being tested (or indicate the presence of local changes that should be shared with the developers). `version` is suitable for display in an "about" box or a CLI `--version` output: it can be easily compared against release notes and lists of bugs fixed in various releases. The installer adds the following text to your `__init__.py` to place a basic version in `YOURPROJECT.__version__`: from ._version import get_versions __version__ = get_versions()['version'] del get_versions ## Styles The setup.cfg `style=` configuration controls how the VCS information is rendered into a version string. The default style, "pep440", produces a PEP440-compliant string, equal to the un-prefixed tag name for actual releases, and containing an additional "local version" section with more detail for in-between builds. For Git, this is TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags --dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and that this commit is two revisions ("+2") beyond the "0.11" tag. For released software (exactly equal to a known tag), the identifier will only contain the stripped tag, e.g. "0.11". Other styles are available. See [details.md](details.md) in the Versioneer source tree for descriptions. ## Debugging Versioneer tries to avoid fatal errors: if something goes wrong, it will tend to return a version of "0+unknown". To investigate the problem, run `setup.py version`, which will run the version-lookup code in a verbose mode, and will display the full contents of `get_versions()` (including the `error` string, which may help identify what went wrong). ## Known Limitations Some situations are known to cause problems for Versioneer. This details the most significant ones. More can be found on Github [issues page](https://github.com/warner/python-versioneer/issues). ### Subprojects Versioneer has limited support for source trees in which `setup.py` is not in the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are two common reasons why `setup.py` might not be in the root: * Source trees which contain multiple subprojects, such as [Buildbot](https://github.com/buildbot/buildbot), which contains both "master" and "slave" subprojects, each with their own `setup.py`, `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI distributions (and upload multiple independently-installable tarballs). * Source trees whose main purpose is to contain a C library, but which also provide bindings to Python (and perhaps other langauges) in subdirectories. Versioneer will look for `.git` in parent directories, and most operations should get the right version string. However `pip` and `setuptools` have bugs and implementation details which frequently cause `pip install .` from a subproject directory to fail to find a correct version string (so it usually defaults to `0+unknown`). `pip install --editable .` should work correctly. `setup.py install` might work too. Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in some later version. [Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking this issue. The discussion in [PR #61](https://github.com/warner/python-versioneer/pull/61) describes the issue from the Versioneer side in more detail. [pip PR#3176](https://github.com/pypa/pip/pull/3176) and [pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve pip to let Versioneer work correctly. Versioneer-0.16 and earlier only looked for a `.git` directory next to the `setup.cfg`, so subprojects were completely unsupported with those releases. ### Editable installs with setuptools <= 18.5 `setup.py develop` and `pip install --editable .` allow you to install a project into a virtualenv once, then continue editing the source code (and test) without re-installing after every change. "Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a convenient way to specify executable scripts that should be installed along with the python package. These both work as expected when using modern setuptools. When using setuptools-18.5 or earlier, however, certain operations will cause `pkg_resources.DistributionNotFound` errors when running the entrypoint script, which must be resolved by re-installing the package. This happens when the install happens with one version, then the egg_info data is regenerated while a different version is checked out. Many setup.py commands cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into a different virtualenv), so this can be surprising. [Bug #83](https://github.com/warner/python-versioneer/issues/83) describes this one, but upgrading to a newer version of setuptools should probably resolve it. ### Unicode version strings While Versioneer works (and is continually tested) with both Python 2 and Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. Newer releases probably generate unicode version strings on py2. It's not clear that this is wrong, but it may be surprising for applications when then write these strings to a network connection or include them in bytes-oriented APIs like cryptographic checksums. [Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates this question. ## Updating Versioneer To upgrade your project to a new release of Versioneer, do the following: * install the new Versioneer (`pip install -U versioneer` or equivalent) * edit `setup.cfg`, if necessary, to include any new configuration settings indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. * re-run `versioneer install` in your source tree, to replace `SRC/_version.py` * commit any changed files ## Future Directions This tool is designed to make it easily extended to other version-control systems: all VCS-specific components are in separate directories like src/git/ . The top-level `versioneer.py` script is assembled from these components by running make-versioneer.py . In the future, make-versioneer.py will take a VCS name as an argument, and will construct a version of `versioneer.py` that is specific to the given VCS. It might also take the configuration arguments that are currently provided manually during installation by editing setup.py . Alternatively, it might go the other direction and include code from all supported VCS systems, reducing the number of intermediate scripts. ## License To make Versioneer easier to embed, all its code is dedicated to the public domain. The `_version.py` that it creates is also in the public domain. Specifically, both are released under the Creative Commons "Public Domain Dedication" license (CC0-1.0), as described in https://creativecommons.org/publicdomain/zero/1.0/ . """ from __future__ import print_function try: import configparser except ImportError: import ConfigParser as configparser import errno import json import os import re import subprocess import sys class VersioneerConfig: """Container for Versioneer configuration parameters.""" def get_root(): """Get the project root directory. We require that all commands are run from the project root, i.e. the directory that contains setup.py, setup.cfg, and versioneer.py . """ root = os.path.realpath(os.path.abspath(os.getcwd())) setup_py = os.path.join(root, "setup.py") versioneer_py = os.path.join(root, "versioneer.py") if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): # allow 'python path/to/setup.py COMMAND' root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) setup_py = os.path.join(root, "setup.py") versioneer_py = os.path.join(root, "versioneer.py") if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): err = ("Versioneer was unable to run the project root directory. " "Versioneer requires setup.py to be executed from " "its immediate directory (like 'python setup.py COMMAND'), " "or in a way that lets it use sys.argv[0] to find the root " "(like 'python path/to/setup.py COMMAND').") raise VersioneerBadRootError(err) try: # Certain runtime workflows (setup.py install/develop in a setuptools # tree) execute all dependencies in a single python process, so # "versioneer" may be imported multiple times, and python's shared # module-import table will cache the first one. So we can't use # os.path.dirname(__file__), as that will find whichever # versioneer.py was first imported, even in later projects. me = os.path.realpath(os.path.abspath(__file__)) me_dir = os.path.normcase(os.path.splitext(me)[0]) vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) if me_dir != vsr_dir: print("Warning: build in %s is using versioneer.py from %s" % (os.path.dirname(me), versioneer_py)) except NameError: pass return root def get_config_from_root(root): """Read the project setup.cfg file to determine Versioneer config.""" # This might raise EnvironmentError (if setup.cfg is missing), or # configparser.NoSectionError (if it lacks a [versioneer] section), or # configparser.NoOptionError (if it lacks "VCS="). See the docstring at # the top of versioneer.py for instructions on writing your setup.cfg . setup_cfg = os.path.join(root, "setup.cfg") parser = configparser.SafeConfigParser() with open(setup_cfg, "r") as f: parser.readfp(f) VCS = parser.get("versioneer", "VCS") # mandatory def get(parser, name): if parser.has_option("versioneer", name): return parser.get("versioneer", name) return None cfg = VersioneerConfig() cfg.VCS = VCS cfg.style = get(parser, "style") or "" cfg.versionfile_source = get(parser, "versionfile_source") cfg.versionfile_build = get(parser, "versionfile_build") cfg.tag_prefix = get(parser, "tag_prefix") if cfg.tag_prefix in ("''", '""'): cfg.tag_prefix = "" cfg.parentdir_prefix = get(parser, "parentdir_prefix") cfg.verbose = get(parser, "verbose") return cfg class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" # these dictionaries contain VCS-specific tools LONG_VERSION_PY = {} HANDLERS = {} def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f return decorate def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None for c in commands: try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git p = subprocess.Popen([c] + args, cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=(subprocess.PIPE if hide_stderr else None)) break except EnvironmentError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue if verbose: print("unable to run %s" % dispcmd) print(e) return None, None else: if verbose: print("unable to find command, tried %s" % (commands,)) return None, None stdout = p.communicate()[0].strip() if sys.version_info[0] >= 3: stdout = stdout.decode() if p.returncode != 0: if verbose: print("unable to run %s (error)" % dispcmd) print("stdout was %s" % stdout) return None, p.returncode return stdout, p.returncode LONG_VERSION_PY['git'] = ''' # This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build # directories (produced by setup.py build) will contain a much shorter file # that just contains the computed version number. # This file is released into the public domain. Generated by # versioneer-0.18 (https://github.com/warner/python-versioneer) """Git implementation of _version.py.""" import errno import os import re import subprocess import sys def get_keywords(): """Get the keywords needed to look up the version information.""" # these strings will be replaced by git during git-archive. # setup.py/versioneer.py will grep for the variable names, so they must # each be defined on a line of their own. _version.py will just call # get_keywords(). git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} return keywords class VersioneerConfig: """Container for Versioneer configuration parameters.""" def get_config(): """Create, populate and return the VersioneerConfig() object.""" # these strings are filled in when 'setup.py versioneer' creates # _version.py cfg = VersioneerConfig() cfg.VCS = "git" cfg.style = "%(STYLE)s" cfg.tag_prefix = "%(TAG_PREFIX)s" cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" cfg.verbose = False return cfg class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" LONG_VERSION_PY = {} HANDLERS = {} def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f return decorate def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None for c in commands: try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git p = subprocess.Popen([c] + args, cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=(subprocess.PIPE if hide_stderr else None)) break except EnvironmentError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue if verbose: print("unable to run %%s" %% dispcmd) print(e) return None, None else: if verbose: print("unable to find command, tried %%s" %% (commands,)) return None, None stdout = p.communicate()[0].strip() if sys.version_info[0] >= 3: stdout = stdout.decode() if p.returncode != 0: if verbose: print("unable to run %%s (error)" %% dispcmd) print("stdout was %%s" %% stdout) return None, p.returncode return stdout, p.returncode def versions_from_parentdir(parentdir_prefix, root, verbose): """Try to determine the version from the parent directory name. Source tarballs conventionally unpack into a directory that includes both the project name and a version string. We will also support searching up two directory levels for an appropriately named parent directory """ rootdirs = [] for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: print("Tried directories %%s but none started with prefix %%s" %% (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @register_vcs_handler("git", "get_keywords") def git_get_keywords(versionfile_abs): """Extract version information from the given file.""" # the code embedded in _version.py can just fetch the value of these # keywords. When used from setup.py, we don't want to import _version.py, # so we do it with a regexp instead. This function is not used from # _version.py. keywords = {} try: f = open(versionfile_abs, "r") for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["refnames"] = mo.group(1) if line.strip().startswith("git_full ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["full"] = mo.group(1) if line.strip().startswith("git_date ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["date"] = mo.group(1) f.close() except EnvironmentError: pass return keywords @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" if not keywords: raise NotThisMethod("no keywords at all, weird") date = keywords.get("date") if date is not None: # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because # it's been around since git-1.5.3, and it's too difficult to # discover which version we're using, or to work around using an # older one. date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) refnames = keywords["refnames"].strip() if refnames.startswith("$Format"): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") refs = set([r.strip() for r in refnames.strip("()").split(",")]) # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %%d # expansion behaves like git log --decorate=short and strips out the # refs/heads/ and refs/tags/ prefixes that would let us distinguish # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". tags = set([r for r in refs if re.search(r'\d', r)]) if verbose: print("discarding '%%s', no digits" %% ",".join(refs - tags)) if verbose: print("likely tags: %%s" %% ",".join(sorted(tags))) for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] if verbose: print("picking %%s" %% r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") return {"version": "0+unknown", "full-revisionid": keywords["full"].strip(), "dirty": False, "error": "no suitable tags", "date": None} @register_vcs_handler("git", "pieces_from_vcs") def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* expanded, and _version.py hasn't already been rewritten with a short version string, meaning we're inside a checked out source tree. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %%s not under git control" %% root) raise NotThisMethod("'git rev-parse --git-dir' returned error") # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%%s*" %% tag_prefix], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() pieces = {} pieces["long"] = full_out pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out # look for -dirty suffix dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: git_describe = git_describe[:git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%%s'" %% describe_out) return pieces # tag full_tag = mo.group(1) if not full_tag.startswith(tag_prefix): if verbose: fmt = "tag '%%s' doesn't start with prefix '%%s'" print(fmt %% (full_tag, tag_prefix)) pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" %% (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag[len(tag_prefix):] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) # commit: short hex revision ID pieces["short"] = mo.group(3) else: # HEX: no tags pieces["closest-tag"] = None count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces def plus_or_dot(pieces): """Return a + if we don't already have one, else return a .""" if "+" in pieces.get("closest-tag", ""): return "." return "+" def render_pep440(pieces): """Build up version string, with post-release "local version identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty Exceptions: 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += plus_or_dot(pieces) rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" else: # exception #1 rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered def render_pep440_pre(pieces): """TAG[.post.devDISTANCE] -- No -dirty. Exceptions: 1: no tags. 0.post.devDISTANCE """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += ".post.dev%%d" %% pieces["distance"] else: # exception #1 rendered = "0.post.dev%%d" %% pieces["distance"] return rendered def render_pep440_post(pieces): """TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that .dev0 sorts backwards (a dirty tree will appear "older" than the corresponding clean one), but you shouldn't be releasing software with -dirty anyways. Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += plus_or_dot(pieces) rendered += "g%%s" %% pieces["short"] else: # exception #1 rendered = "0.post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += "+g%%s" %% pieces["short"] return rendered def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. Eexceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" else: # exception #1 rendered = "0.post%%d" %% pieces["distance"] if pieces["dirty"]: rendered += ".dev0" return rendered def render_git_describe(pieces): """TAG[-DISTANCE-gHEX][-dirty]. Like 'git describe --tags --dirty --always'. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render_git_describe_long(pieces): """TAG-DISTANCE-gHEX[-dirty]. Like 'git describe --tags --dirty --always -long'. The distance/hash is unconditional. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: return {"version": "unknown", "full-revisionid": pieces.get("long"), "dirty": None, "error": pieces["error"], "date": None} if not style or style == "default": style = "pep440" # the default if style == "pep440": rendered = render_pep440(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": rendered = render_git_describe(pieces) elif style == "git-describe-long": rendered = render_git_describe_long(pieces) else: raise ValueError("unknown style '%%s'" %% style) return {"version": rendered, "full-revisionid": pieces["long"], "dirty": pieces["dirty"], "error": None, "date": pieces.get("date")} def get_versions(): """Get version information or return default if unable to do so.""" # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have # __file__, we can work backwards from there to the root. Some # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which # case we can only use expanded keywords. cfg = get_config() verbose = cfg.verbose try: return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, verbose) except NotThisMethod: pass try: root = os.path.realpath(__file__) # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. for i in cfg.versionfile_source.split('/'): root = os.path.dirname(root) except NameError: return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to find root of source tree", "date": None} try: pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) return render(pieces, cfg.style) except NotThisMethod: pass try: if cfg.parentdir_prefix: return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) except NotThisMethod: pass return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to compute version", "date": None} ''' @register_vcs_handler("git", "get_keywords") def git_get_keywords(versionfile_abs): """Extract version information from the given file.""" # the code embedded in _version.py can just fetch the value of these # keywords. When used from setup.py, we don't want to import _version.py, # so we do it with a regexp instead. This function is not used from # _version.py. keywords = {} try: f = open(versionfile_abs, "r") for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["refnames"] = mo.group(1) if line.strip().startswith("git_full ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["full"] = mo.group(1) if line.strip().startswith("git_date ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["date"] = mo.group(1) f.close() except EnvironmentError: pass return keywords @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" if not keywords: raise NotThisMethod("no keywords at all, weird") date = keywords.get("date") if date is not None: # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because # it's been around since git-1.5.3, and it's too difficult to # discover which version we're using, or to work around using an # older one. date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) refnames = keywords["refnames"].strip() if refnames.startswith("$Format"): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") refs = set([r.strip() for r in refnames.strip("()").split(",")]) # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d # expansion behaves like git log --decorate=short and strips out the # refs/heads/ and refs/tags/ prefixes that would let us distinguish # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". tags = set([r for r in refs if re.search(r'\d', r)]) if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: print("likely tags: %s" % ",".join(sorted(tags))) for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] if verbose: print("picking %s" % r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") return {"version": "0+unknown", "full-revisionid": keywords["full"].strip(), "dirty": False, "error": "no suitable tags", "date": None} @register_vcs_handler("git", "pieces_from_vcs") def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* expanded, and _version.py hasn't already been rewritten with a short version string, meaning we're inside a checked out source tree. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) raise NotThisMethod("'git rev-parse --git-dir' returned error") # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%s*" % tag_prefix], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() pieces = {} pieces["long"] = full_out pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out # look for -dirty suffix dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: git_describe = git_describe[:git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%s'" % describe_out) return pieces # tag full_tag = mo.group(1) if not full_tag.startswith(tag_prefix): if verbose: fmt = "tag '%s' doesn't start with prefix '%s'" print(fmt % (full_tag, tag_prefix)) pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" % (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag[len(tag_prefix):] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) # commit: short hex revision ID pieces["short"] = mo.group(3) else: # HEX: no tags pieces["closest-tag"] = None count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces def do_vcs_install(manifest_in, versionfile_source, ipy): """Git-specific installation logic for Versioneer. For Git, this means creating/changing .gitattributes to mark _version.py for export-subst keyword substitution. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] files = [manifest_in, versionfile_source] if ipy: files.append(ipy) try: me = __file__ if me.endswith(".pyc") or me.endswith(".pyo"): me = os.path.splitext(me)[0] + ".py" versioneer_file = os.path.relpath(me) except NameError: versioneer_file = "versioneer.py" files.append(versioneer_file) present = False try: f = open(".gitattributes", "r") for line in f.readlines(): if line.strip().startswith(versionfile_source): if "export-subst" in line.strip().split()[1:]: present = True f.close() except EnvironmentError: pass if not present: f = open(".gitattributes", "a+") f.write("%s export-subst\n" % versionfile_source) f.close() files.append(".gitattributes") run_command(GITS, ["add", "--"] + files) def versions_from_parentdir(parentdir_prefix, root, verbose): """Try to determine the version from the parent directory name. Source tarballs conventionally unpack into a directory that includes both the project name and a version string. We will also support searching up two directory levels for an appropriately named parent directory """ rootdirs = [] for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: print("Tried directories %s but none started with prefix %s" % (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") SHORT_VERSION_PY = """ # This file was generated by 'versioneer.py' (0.18) from # revision-control system data, or from the parent directory name of an # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. import json version_json = ''' %s ''' # END VERSION_JSON def get_versions(): return json.loads(version_json) """ def versions_from_file(filename): """Try to determine the version from _version.py if present.""" try: with open(filename) as f: contents = f.read() except EnvironmentError: raise NotThisMethod("unable to read _version.py") mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: raise NotThisMethod("no version_json in _version.py") return json.loads(mo.group(1)) def write_to_version_file(filename, versions): """Write the given version number to the given _version.py file.""" os.unlink(filename) contents = json.dumps(versions, sort_keys=True, indent=1, separators=(",", ": ")) with open(filename, "w") as f: f.write(SHORT_VERSION_PY % contents) print("set %s to '%s'" % (filename, versions["version"])) def plus_or_dot(pieces): """Return a + if we don't already have one, else return a .""" if "+" in pieces.get("closest-tag", ""): return "." return "+" def render_pep440(pieces): """Build up version string, with post-release "local version identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty Exceptions: 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += plus_or_dot(pieces) rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" else: # exception #1 rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered def render_pep440_pre(pieces): """TAG[.post.devDISTANCE] -- No -dirty. Exceptions: 1: no tags. 0.post.devDISTANCE """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += ".post.dev%d" % pieces["distance"] else: # exception #1 rendered = "0.post.dev%d" % pieces["distance"] return rendered def render_pep440_post(pieces): """TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that .dev0 sorts backwards (a dirty tree will appear "older" than the corresponding clean one), but you shouldn't be releasing software with -dirty anyways. Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += plus_or_dot(pieces) rendered += "g%s" % pieces["short"] else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += "+g%s" % pieces["short"] return rendered def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. Eexceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" return rendered def render_git_describe(pieces): """TAG[-DISTANCE-gHEX][-dirty]. Like 'git describe --tags --dirty --always'. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render_git_describe_long(pieces): """TAG-DISTANCE-gHEX[-dirty]. Like 'git describe --tags --dirty --always -long'. The distance/hash is unconditional. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: return {"version": "unknown", "full-revisionid": pieces.get("long"), "dirty": None, "error": pieces["error"], "date": None} if not style or style == "default": style = "pep440" # the default if style == "pep440": rendered = render_pep440(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": rendered = render_git_describe(pieces) elif style == "git-describe-long": rendered = render_git_describe_long(pieces) else: raise ValueError("unknown style '%s'" % style) return {"version": rendered, "full-revisionid": pieces["long"], "dirty": pieces["dirty"], "error": None, "date": pieces.get("date")} class VersioneerBadRootError(Exception): """The project root directory is unknown or missing key files.""" def get_versions(verbose=False): """Get the project version from whatever source is available. Returns dict with two keys: 'version' and 'full'. """ if "versioneer" in sys.modules: # see the discussion in cmdclass.py:get_cmdclass() del sys.modules["versioneer"] root = get_root() cfg = get_config_from_root(root) assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" handlers = HANDLERS.get(cfg.VCS) assert handlers, "unrecognized VCS '%s'" % cfg.VCS verbose = verbose or cfg.verbose assert cfg.versionfile_source is not None, \ "please set versioneer.versionfile_source" assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" versionfile_abs = os.path.join(root, cfg.versionfile_source) # extract version from first of: _version.py, VCS command (e.g. 'git # describe'), parentdir. This is meant to work for developers using a # source checkout, for users of a tarball created by 'setup.py sdist', # and for users of a tarball/zipball created by 'git archive' or github's # download-from-tag feature or the equivalent in other VCSes. get_keywords_f = handlers.get("get_keywords") from_keywords_f = handlers.get("keywords") if get_keywords_f and from_keywords_f: try: keywords = get_keywords_f(versionfile_abs) ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) if verbose: print("got version from expanded keyword %s" % ver) return ver except NotThisMethod: pass try: ver = versions_from_file(versionfile_abs) if verbose: print("got version from file %s %s" % (versionfile_abs, ver)) return ver except NotThisMethod: pass from_vcs_f = handlers.get("pieces_from_vcs") if from_vcs_f: try: pieces = from_vcs_f(cfg.tag_prefix, root, verbose) ver = render(pieces, cfg.style) if verbose: print("got version from VCS %s" % ver) return ver except NotThisMethod: pass try: if cfg.parentdir_prefix: ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) if verbose: print("got version from parentdir %s" % ver) return ver except NotThisMethod: pass if verbose: print("unable to compute version") return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to compute version", "date": None} def get_version(): """Get the short version string for this project.""" return get_versions()["version"] def get_cmdclass(): """Get the custom setuptools/distutils subclasses used by Versioneer.""" if "versioneer" in sys.modules: del sys.modules["versioneer"] # this fixes the "python setup.py develop" case (also 'install' and # 'easy_install .'), in which subdependencies of the main project are # built (using setup.py bdist_egg) in the same python process. Assume # a main project A and a dependency B, which use different versions # of Versioneer. A's setup.py imports A's Versioneer, leaving it in # sys.modules by the time B's setup.py is executed, causing B to run # with the wrong versioneer. Setuptools wraps the sub-dep builds in a # sandbox that restores sys.modules to it's pre-build state, so the # parent is protected against the child's "import versioneer". By # removing ourselves from sys.modules here, before the child build # happens, we protect the child from the parent's versioneer too. # Also see https://github.com/warner/python-versioneer/issues/52 cmds = {} # we add "version" to both distutils and setuptools from distutils.core import Command class cmd_version(Command): description = "report generated version string" user_options = [] boolean_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): vers = get_versions(verbose=True) print("Version: %s" % vers["version"]) print(" full-revisionid: %s" % vers.get("full-revisionid")) print(" dirty: %s" % vers.get("dirty")) print(" date: %s" % vers.get("date")) if vers["error"]: print(" error: %s" % vers["error"]) cmds["version"] = cmd_version # we override "build_py" in both distutils and setuptools # # most invocation pathways end up running build_py: # distutils/build -> build_py # distutils/install -> distutils/build ->.. # setuptools/bdist_wheel -> distutils/install ->.. # setuptools/bdist_egg -> distutils/install_lib -> build_py # setuptools/install -> bdist_egg ->.. # setuptools/develop -> ? # pip install: # copies source tree to a tempdir before running egg_info/etc # if .git isn't copied too, 'git describe' will fail # then does setup.py bdist_wheel, or sometimes setup.py install # setup.py egg_info -> ? # we override different "build_py" commands for both environments if "setuptools" in sys.modules: from setuptools.command.build_py import build_py as _build_py else: from distutils.command.build_py import build_py as _build_py class cmd_build_py(_build_py): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() _build_py.run(self) # now locate _version.py in the new build/ directory and replace # it with an updated value if cfg.versionfile_build: target_versionfile = os.path.join(self.build_lib, cfg.versionfile_build) print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) cmds["build_py"] = cmd_build_py if "cx_Freeze" in sys.modules: # cx_freeze enabled? from cx_Freeze.dist import build_exe as _build_exe # nczeczulin reports that py2exe won't like the pep440-style string # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. # setup(console=[{ # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION # "product_version": versioneer.get_version(), # ... class cmd_build_exe(_build_exe): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() target_versionfile = cfg.versionfile_source print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) _build_exe.run(self) os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) cmds["build_exe"] = cmd_build_exe del cmds["build_py"] if 'py2exe' in sys.modules: # py2exe enabled? try: from py2exe.distutils_buildexe import py2exe as _py2exe # py3 except ImportError: from py2exe.build_exe import py2exe as _py2exe # py2 class cmd_py2exe(_py2exe): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() target_versionfile = cfg.versionfile_source print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) _py2exe.run(self) os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) cmds["py2exe"] = cmd_py2exe # we override different "sdist" commands for both environments if "setuptools" in sys.modules: from setuptools.command.sdist import sdist as _sdist else: from distutils.command.sdist import sdist as _sdist class cmd_sdist(_sdist): def run(self): versions = get_versions() self._versioneer_generated_versions = versions # unless we update this, the command will keep using the old # version self.distribution.metadata.version = versions["version"] return _sdist.run(self) def make_release_tree(self, base_dir, files): root = get_root() cfg = get_config_from_root(root) _sdist.make_release_tree(self, base_dir, files) # now locate _version.py in the new base_dir directory # (remembering that it may be a hardlink) and replace it with an # updated value target_versionfile = os.path.join(base_dir, cfg.versionfile_source) print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, self._versioneer_generated_versions) cmds["sdist"] = cmd_sdist return cmds CONFIG_ERROR = """ setup.cfg is missing the necessary Versioneer configuration. You need a section like: [versioneer] VCS = git style = pep440 versionfile_source = src/myproject/_version.py versionfile_build = myproject/_version.py tag_prefix = parentdir_prefix = myproject- You will also need to edit your setup.py to use the results: import versioneer setup(version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), ...) Please read the docstring in ./versioneer.py for configuration instructions, edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. """ SAMPLE_CONFIG = """ # See the docstring in versioneer.py for instructions. Note that you must # re-run 'versioneer.py setup' after changing this section, and commit the # resulting files. [versioneer] #VCS = git #style = pep440 #versionfile_source = #versionfile_build = #tag_prefix = #parentdir_prefix = """ INIT_PY_SNIPPET = """ from ._version import get_versions __version__ = get_versions()['version'] del get_versions """ def do_setup(): """Main VCS-independent setup function for installing Versioneer.""" root = get_root() try: cfg = get_config_from_root(root) except (EnvironmentError, configparser.NoSectionError, configparser.NoOptionError) as e: if isinstance(e, (EnvironmentError, configparser.NoSectionError)): print("Adding sample versioneer config to setup.cfg", file=sys.stderr) with open(os.path.join(root, "setup.cfg"), "a") as f: f.write(SAMPLE_CONFIG) print(CONFIG_ERROR, file=sys.stderr) return 1 print(" creating %s" % cfg.versionfile_source) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) ipy = os.path.join(os.path.dirname(cfg.versionfile_source), "__init__.py") if os.path.exists(ipy): try: with open(ipy, "r") as f: old = f.read() except EnvironmentError: old = "" if INIT_PY_SNIPPET not in old: print(" appending to %s" % ipy) with open(ipy, "a") as f: f.write(INIT_PY_SNIPPET) else: print(" %s unmodified" % ipy) else: print(" %s doesn't exist, ok" % ipy) ipy = None # Make sure both the top-level "versioneer.py" and versionfile_source # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so # they'll be copied into source distributions. Pip won't be able to # install the package without this. manifest_in = os.path.join(root, "MANIFEST.in") simple_includes = set() try: with open(manifest_in, "r") as f: for line in f: if line.startswith("include "): for include in line.split()[1:]: simple_includes.add(include) except EnvironmentError: pass # That doesn't cover everything MANIFEST.in can do # (http://docs.python.org/2/distutils/sourcedist.html#commands), so # it might give some false negatives. Appending redundant 'include' # lines is safe, though. if "versioneer.py" not in simple_includes: print(" appending 'versioneer.py' to MANIFEST.in") with open(manifest_in, "a") as f: f.write("include versioneer.py\n") else: print(" 'versioneer.py' already in MANIFEST.in") if cfg.versionfile_source not in simple_includes: print(" appending versionfile_source ('%s') to MANIFEST.in" % cfg.versionfile_source) with open(manifest_in, "a") as f: f.write("include %s\n" % cfg.versionfile_source) else: print(" versionfile_source already in MANIFEST.in") # Make VCS-specific changes. For git, this means creating/changing # .gitattributes to mark _version.py for export-subst keyword # substitution. do_vcs_install(manifest_in, cfg.versionfile_source, ipy) return 0 def scan_setup_py(): """Validate the contents of setup.py against Versioneer's expectations.""" found = set() setters = False errors = 0 with open("setup.py", "r") as f: for line in f.readlines(): if "import versioneer" in line: found.add("import") if "versioneer.get_cmdclass()" in line: found.add("cmdclass") if "versioneer.get_version()" in line: found.add("get_version") if "versioneer.VCS" in line: setters = True if "versioneer.versionfile_source" in line: setters = True if len(found) != 3: print("") print("Your setup.py appears to be missing some important items") print("(but I might be wrong). Please make sure it has something") print("roughly like the following:") print("") print(" import versioneer") print(" setup( version=versioneer.get_version(),") print(" cmdclass=versioneer.get_cmdclass(), ...)") print("") errors += 1 if setters: print("You should remove lines like 'versioneer.VCS = ' and") print("'versioneer.versionfile_source = ' . This configuration") print("now lives in setup.cfg, and should be removed from setup.py") print("") errors += 1 return errors if __name__ == "__main__": cmd = sys.argv[1] if cmd == "setup": errors = do_setup() errors += scan_setup_py() if errors: sys.exit(1)