pax_global_header00006660000000000000000000000064141562611240014514gustar00rootroot0000000000000052 comment=a2cbdd17a2246429976ae0f0b04b84c8b0252049 bcbio-nextgen-1.2.9/000077500000000000000000000000001415626112400142515ustar00rootroot00000000000000bcbio-nextgen-1.2.9/.github/000077500000000000000000000000001415626112400156115ustar00rootroot00000000000000bcbio-nextgen-1.2.9/.github/ISSUE_TEMPLATE/000077500000000000000000000000001415626112400177745ustar00rootroot00000000000000bcbio-nextgen-1.2.9/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000006761415626112400224770ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Version info** - bcbio version (`bcbio_nextgen.py --version`): - OS name and version (`lsb_release -ds`): **To Reproduce** Exact bcbio command you have used: ``` ``` Your yaml configuration file: ``` ``` **Log files (could be found in work/log)** Please attach (10MB max): `bcbio-nextgen-commands.log`, and `bcbio-nextgen-debug.log`. bcbio-nextgen-1.2.9/.gitignore000066400000000000000000000013231415626112400162400ustar00rootroot00000000000000*.pyc *.idx *.swo *.swp **/bcbiotx/ bcbio/pipeline/version.py bcbio_nextgen.egg-info/ build/ docs/_build dist/ tests/data/test_srnaseq/ tests/unit/bcbio-nextgen-test-data/ tests/data/100326* tests/data/110106* tests/data/110221* tests/data/110907* tests/data/genomes* tests/data/reference_material/7_100326_FC6107FAAXX-grade.vcf.gz* tests/data/tcga_benchmark tests/data/automated/config/ tests/data/automated/galaxy/ tests/data/automated/gemini_data/ tests/data/automated/genomes/ tests/data/automated/liftOver/ tests/data/automated/*-sorted.bed tests/data/variants/S1_S2-combined* tests/data/test_bcbio_cwl-master/ cwl/*-workflow .DS_Store .#* .ropeproject .env *~ \#* .idea/ __pycache__ .coverage .pytest_cache .vagrant/ bcbio-nextgen-1.2.9/.readthedocs.yml000066400000000000000000000004451415626112400173420ustar00rootroot00000000000000# .readthedocs.yml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 python: version: 3.6 install: - requirements: docs/requirements.txt sphinx: configuration: docs/conf.py fail_on_warning: true bcbio-nextgen-1.2.9/.travis.yml000066400000000000000000000102461415626112400163650ustar00rootroot00000000000000os: linux dist: bionic language: generic addons: apt: update: true env: global: - secure: "VJSdyR3BUpDGf7ot0I+GvSVR77TaMgxgscW1pFgxeitr3XvZ9la+PMuSqKH1B1TR/8Gq+l507FnQb1I/zjzUOvomX2gnsL6CcbTml8DKUz12kmQ0ixGT5IxZjDuBDvJwOJlRg1JLgJkcxMHa9EEmDZTh7Feyu7jJC9qeGKSyjFw=" matrix: - BCBIO_DOCKER_PRIVILEGED=True ARVADOS_API_HOST=qr1hi.arvadosapi.com before_install: # exit the build if it only includes Markdown files - | if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(.md)' then echo "Not running CI since only docs were changed" exit fi # Get and install anaconda for custom Python installation - wget --progress=dot:giga https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.2-Linux-x86_64.sh - bash Miniconda3-py37_4.8.2-Linux-x86_64.sh -b -p ~/install/bcbio-vm/anaconda install: # Install bcbio-nextgen and bcbio-nextgen-vm - df -h - export PATH=~/install/bcbio-vm/anaconda/bin:$PATH - conda install --yes nomkl - conda install --yes -c conda-forge -c bioconda bcbio-nextgen python=3 - conda install --yes -c conda-forge -c bioconda bcbio-nextgen-vm python=3 # Clean up space with external tools we don't need for tests - conda clean --yes --tarballs --index-cache - rm -rf ~/install/bcbio-vm/anaconda/pkgs/qt-* - du -sch ~/install/bcbio-vm/anaconda/pkgs/* | sort -h - df -h # Update to latest bcbio-nextgen code externally - rm -rf ~/install/bcbio-vm/anaconda/lib/python*/site-packages/bcbio - rm -rf ~/install/bcbio-vm/anaconda/lib/python*/site-packages/bcbio_nextgen-* - ~/install/bcbio-vm/anaconda/bin/python setup.py install jobs: include: - stage: test name: "Variant standard" script: # -- Prepare variant docker image - docker pull quay.io/bcbio/bcbio-vc - docker images - df -h # Update to latest bcbio-nextgen code within the container - bcbio_vm.py devel setup_install -i quay.io/bcbio/bcbio-vc # -- Standard bcbio variant tests - docker run -v `pwd`:`pwd` quay.io/bcbio/bcbio-vc bash -c "cd `pwd` && /usr/local/share/bcbio-nextgen/anaconda/bin/py.test -p no:cacheprovider -p no:stepwise tests/unit --cov=bcbio" - py.test -p no:cacheprovider -p no:stepwise tests/bcbio_vm -v -m docker_multicore # XXX Arvados tests failing with 404 when contacting from Travis # - sudo mkdir -p /etc/pki/tls/certs && sudo ln -s /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt # - py.test -p no:cacheprovider -p no:stepwise tests/bcbio_vm -v -s -m cwl_arvados - stage: test name: "Variant CWL" script: - docker pull quay.io/bcbio/bcbio-vc - docker images - df -h # Update to latest bcbio-nextgen code within the container - bcbio_vm.py devel setup_install -i quay.io/bcbio/bcbio-vc # XXX Currently commented out joint test, taking too long and causing Travis timeouts # - py.test -p no:cacheprovider -p no:stepwise tests/bcbio_vm -v -s -m cwl_docker_joint - py.test -p no:cacheprovider -p no:stepwise tests/bcbio_vm -v -s -m cwl_docker_somatic # -- Cleanup variant docker image - docker ps -a -q | xargs --no-run-if-empty docker rm - docker rmi -f quay.io/bcbio/bcbio-vc - docker images | grep '' | awk '{print $3}' | xargs --no-run-if-empty docker rmi - docker images - stage: test name: "RNA-seq CWL" script: - docker pull quay.io/bcbio/bcbio-rnaseq - docker images - df -h - bcbio_vm.py devel setup_install -i quay.io/bcbio/bcbio-rnaseq - py.test -p no:cacheprovider -p no:stepwise tests/bcbio_vm -v -s -m cwl_docker_rnaseq # -- Cleanup RNA-seq docker image - docker ps -a -q | xargs --no-run-if-empty docker rm - docker rmi -f quay.io/bcbio/bcbio-rnaseq - docker images | grep '' | awk '{print $3}' | xargs --no-run-if-empty docker rmi - docker images after_failure: - df -h notifications: email: false slack: secure: iMn3Iih7cVmWci7A/Rpozc9Fn5IDKr3o6Y7XAWHEBiOEFlBwkC3oHFZxTC1+wZQiDNR87yVF9z3+FhYTYizpUeCPMddfNLMzdcO0EGtpckZOzX7aaFjqQCWhtucDnDQYaHhZIPKATrWvpPSYm7bpyp/p9cqgE/a9uvFLRMrIyzM= bcbio-nextgen-1.2.9/CODE_OF_CONDUCT.md000066400000000000000000000064311415626112400170540ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at chapmanb@fastmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq bcbio-nextgen-1.2.9/HISTORY.md000066400000000000000000003074431415626112400157470ustar00rootroot00000000000000## 1.3.0 (in progress ~ Q2 2022) ## 1.2.9 (14 December 2021) - Fix vcf header bug: T/N SAMPLE lines are back - needed for import to SolveBio - add strandedness: auto for -l A option in salmon - report 10x more peaks in CHIP/ATAC-seq - use 0.05 qvalue - fix misleading RNA-seq duplicated reads statistics: thanks @sib-bcf - reorganize conda environments - snpEff 5.0 - strandedness: auto - document WGBS pipeline steps - make --local an option, not default in bismark alignment - too slow - bcbioRNASeq update to 0.3.44 - pureCN update to 2.0.1 - octopus update to 0.7.4 ## 1.2.8 (14 April 2021) - Set ENCODE library complexity flags properly for ChIP-seq. Thanks to @mistrm82. - Fix greylisted peaks not being propagated to the output directory. Thanks to @mistrm82. - Better error message when no sample barcodes are found for single-cell RNA-seq. - Better trimming for 2 wgbs kits - enable setting parameters for deduplicate_bismark - custom threading for bismark via yaml - reproducible WGBS user story with the data from Encode - While consensus peak calling, keep the highest scoring peak instead of calling the summit for the highest scoring peak and expanding the peak to 250 bases. - Enable consensus peak calling for broad peaks. Thanks to @mistrm82 and @yoonsquared for pointing out this was missing. - Re-enable ATAC-seq tests, they work now. - svprioritize for mm10 - purecn_Dx.R - mutational signatures - still requires a manual update of deconstructsigs or release of it - make sure purecn uses sv_regions bed to call variants - fix misleading disambiguation fastqc read statistics (total, hg38, mm10) - wgbs: nebemseq kit: add --maxins 1000 and --local to bismark align - WGBS: sorted indexed deduplicated bam for ready.bam - print error message when aligner: false and hla typing is on - make sure that mark_duplicates is false with collapsed UMI input ## 1.2.7 (22 February 2021) - RNASeq: Add gene body coverage plots to multiqc report. - Restore ability to opt out of contamination checking via tools_off. - Properly invoke threading for `verifybamid2`. - Fix circular import issue when using bcbio functions outside of the main bcbio script. - Enable setting custom PureCN options via YAML file. ## 1.2.6 (04 February 2021) - RNASeq: Fail more gracefully if SummarizedExperiment object cannot be created. - Fixes to handle DRAGEN BAM files from the first stage of UMI processing. - Fix issue with double-annotating with dbSNP. Separating out somatic variant annotation into it's own vcfanno configuration. ## 1.2.5 (01 January 2021) - Joint calling for RNA-seq variant calling requires setting `jointcaller` to bring it in line with the configuration options for variant calling. - Allow pre-aligned BAMs and gVCFs for RNA-seq joint variant calling. Thanks to @WimSpree for the feature. - Allow `CollectSequencingArtifacts` to be turned off via `tools_off: [collectsequencingartifacts]`. - Fix getiterator -> iter deprecation in ElementTree. Thanks to @smoe. - Add SummarizedExperiment object from RNA-seq runs, a simplified version of the bcbioRNASeq object. - Add `umi_type: dragen`. This enables bcbio to run with first-pass, pre-consensus called UMI BAM files from DRAGEN. - Turn off inferential replicate loading when creating the gene x sample RNA-seq count matrix. This allows loading of thousands of RNA-seq samples. - Only make isoform to gene file from express if we have run express. - Allow "no consensus peaks found" as a valid endpoint of a ChIP-seq analysis. - Allow `BCBIO_TEST_DIR` environment variable to control where tests end up. - Collect OxoG and other sequencing artifacts due to damage. - Round tximport estimated counts. - Turn off consensus peak calling for broad peaks. Thanks to @lbeltrame and @LMannarino for diagnosing the broad-peaks-run-forever bug. ## 1.2.4 (21 September 2020) - Remove deprecated `--genomicsdb-use-vcf-codec` option as this is now the default. - Add bismark output to MultiQC. - Fix PS genotype field from octopus to have the correct type. - Edit VarDict headers to report VCFv4.2, since htsjdk does not fully support VCFv4.3 yet. - Attempt to speed up bismark by implementing the parallelization strategy suggested here: https://github.com/FelixKrueger/Bismark/issues/96 - Add `--enumerate` option to OptiType to report the top 10 calls and scores, to make it easier to decide how confident we are in a HLA call. - Performance improvements when HLA calling during panel sequencing. This skips running bwa-kit during the initial mapping for consensus UMI detection, greatly speeding up panel sequencing runs. - Allow custom options to be passed to `featureCounts`. - Fix race condition when running tests. - Add [TOPMed](https://www.nhlbiwgs.org) as a `datatarget`. - Add predicted transcript and peptide output to arriba. - Add mm10 as a supported genome for arriba. - Skip `bcbioRNASeq` for more than 100 samples. - Add `rRNA_pseudogene` as a rRNA biotype. - Add `--genomicsdb-use-vcf-codec` when running GenotypeGVCF. See https://gatk.broadinstitute.org/hc/en-us/articles/360040509751- GenotypeGVCFs#--genomicsdb-use-vcf-codec for a discussion. Thanks to @amizeranschi for finding the issue and posting the solution. - update VEP to v100 - Add consensus peak calling using https://bedops.readthedocs.io/en/latest/content/usage-examples/master-list.html to collapse overlapping peaks. - Pre-filter consensus peaks by removing peaks with FDR > 0.05 before performing consensus peak calling. - Add support for Qiagen's Qiaseq UPX 3' transcriptome kit for DGE. Support for 96 and 384 well configurations by specifying `umi_type: qiagen-upx-96` or `umi_type: qiagen-upx-384`. - Add consensus peak counting using featureCounts. - Skip using autosomal-reference when calling ataqv for mouse/human, as this has a problem with ataqv (see https://github.com/ParkerLab/ataqv/issues/10) for discussion and followup. - Add pre-generated ataqv HTML report to upload directory. - Support single-end reads for ATAC-seq. - Move featureCount output files to **featureCounts** directory in project directory. - Remove RNA and reads in peak stats from MultiQC table when they are not calculated for a pipeline. - Only show somatic variant counts in the general stats table, if germline variants are calculated. - Add `kit` parameter for setting options for pipelines via just listing the kit. Currently only implemented for WGBS. ## 1.2.3 (7 April 2020) - Hotfix for not being able to upgrade from stable distribution. ## 1.2.2 (5 April 2020) - Fix for not properly looking up R environment variables in the base environment. - Remove --use-new-qual-calculator which was eliminated in GATK 4.1.5.0. - Ensure header is not written for a Series. In pandas 0.24.0 the default for header was changed from False to True so we have to set it explictly now. - Remove unused Dockerfile. Thanks to @matthdsm. - ATAC-seq: Skip peak-calling on fractions with < 1000 reads. ## 1.2.1 (25 March 2020) - Update ChIP and ATAC bowtie2 runs to use `--very-sensitive`. - Properly pad TSS BED file for ataqv TSS enrichment metrics. - Skip bcbioRNASeq if there are less than three samples. - Run joint-calling with single cores to save resources. - Re-support PureCN. - Skip segments with no informative SNPs when creating the LOH VCF file from PureCN output. - Fix for duplicated output for mosdepth in quality control report. - Fix for missing rRNA statistics. ## 1.2.0 (7 February 2020) - Fix for bismark not being a supported aligner. - Run ataqv (https://github.com/ParkerLab/ataqv) to calculate additional ATAQ-seq quality control metrics. - Workaround for some bcbioRNASeq plots failing with many samples when `interesting_groups` is not set. - Add `known_fusions` parameter for passing in known fusions to arriba. - Fix for tx2gene not working properly on some GTF files. - Sort MACS2 output with UNIX sort to avoid memory issues. - Run RiP on full peak file for ATAC-seq. - Run ataqv on unfiltered BAM file with the full peak file. - Run peddy on the population variant file, not the individual sample level file if joint calling was done. - Add STAR to MultiQC metrics. - Throw an error if STAR is run on a genome with alts. - Don't run bcbioRNASeq if there is only one sample. Thanks to @kmendler for the suggestion. - Improve arriba sensitivity by setting `--peOverlapNbasesMin 10` and `--alignSplicedMateMapLminOverLmate 0.5` when running STAR (see https://github.com/suhrig/arriba/issues/41). - Make TPM and counts files from tximport automatically. - Use --keepDuplicates when making the Salmon index. This keeps transcripts that are identical in the index instead of randomly choosing one. This helps when comparing to other ways of quantifying the transcripts, ensuring all of the transcripts are represented. - Remove unnecessary "quant" subdirectory for Salmon runs. This allows MultiQC to properly name the samples. - Ensure STAR log file is propagated to the upload directory. - Fix issue with memory not being specified properly when running `bcbio_prepare_samples.py`. - Run tximport automatically and store TPM in `project/date/tpm` and counts in `project/date/counts`. - Calculate ENCODE quality flags for ATAC-seq. See https://www.encodeproject.org/data-standards/terms/#library for a description of what the metrics mean. - Fix for command line being too long while joint genotyping thousands of samples. - Fix for command line being too long when running the CWL workflow with cromwell. ## 1.1.9 (5 December 2019) - Fix for get VEP cache. - Support Picard's new syntax for ReorderSam (REFERENCE -> SEQUENCE_DICTIONARY). - Remove mitochondrial reads from ChIP/ATAC-seq calling. - Add documentation describing ATAC-seq outputs. - Add ENCODE library complexity metrics for ATAC/ChIP-seq to MultiQC report (see https://www.encodeproject.org/data-standards/terms/#library for a description of the metrics) - Add STAR sample-specific 2-pass. This helps assign a moderate number of reads per genes. Thanks to @naumenko-sa for the intial implementation and push to get this going. - Index transcriptomes only once for pseudo/quasi aligner tools. This fixes race conditions that can happen. - Add --buildversion option, for tracking which version of a gene build was used. This is used during `bcbio_setup_genome.py`. Suggested formats are source_version, so Ensembl_94, EnsemblMetazoa_25, FlyBase_26, etc. - Sort MACS2 bedgraph files before compressing. Thanks to @LMannarino for the suggestion. - Check for the reserved field `sample` in RNA-seq metadata and quit with a useful error message. Thanks to @marypiper for suggesting this. - Split ATAC-seq BAM files into nucleosome-free and mono/di/tri nucleosome files, so we can call peaks on them separately. - Call peaks on NF/MN/DN/TN regions separately for each caller during ATAC-seq. - Allow viral contamination to be assasyed on non tumor/normal samples. - Ensure EBV coverage is calculated when run on genomes with it included as a contig. ## 1.1.8 (28 October 2019) - Add `antibody` configuration option. Setting a specific antibody for ChIP-seq will use appropriate settings for that antibody. See the documentation for supported antibodies. - Add `use_lowfreq_filter` for forcing vardict to report variants with low allelic frequency, useful for calling somatic variants in panels with high coverage. - Fix for checking for pre-existing inputs with python3. - Add `keep_duplicates` option for ChIP/ATAC-seq which does not remove duplicates before peak calling. Defaults to False. - Add `keep_multimappers` for ChIP/ATAC-seq which does not remove multimappers before peak calling. Defaults to False. - Remove ethnicity as a required column in PED files. ## 1.1.7 (10 October 2019) ======= - hot fix for dataclasses not being supported in 3.6. Use namedtuple instead. ## 1.1.6 (10 October 2019) - GATK ApplyBQSRSpark: avoid StreamClosed issue with GATK 4.1+ - RNA-seq: fixes for cufflinks preparation due to python3 transition. - RNA-seq: output count tables from tximport for genes and transcripts. These are in `bcbioRNASeq/results/date/genes/counts` and `bcbioRNASeq/results/data/transcripts/counts`. - qualimap (RNA-seq): disable stranded mode for qualimap, as it gives incorrect results with the hisat2 aligner and for RNA-seq just setting it to unstranded - Add `quantify_genome_alignments` option to use genome alignments to quantify with Salmon. - Add `--validateMappings` flag to Salmon read quantification mode. - VEP cache is not installing anymore from bcbio run - Add support for Salmon SA method when STAR alignments are not available (for hg38). - Add support for the new read model for filtering in Mutect2. This is experimental, and a little flaky, so it can optionally be turned on via: `tools_on: mutect2_readmodel`. Thanks to @lbeltrame for implementing this feature and doing a ton of work debugging. - Swap pandas `from_csv` call to `read_csv`. - Make STAR respect the `transcriptome_gtf` option. - Prefix regular expression with r. Thanks to @smoe for finding all of these. - Add informative logging messages at beginning of bcbio run. Includes the version and the configuration files being used. - Swap samtools mpileup to use bcftools mpileup as samtools mpileup is being deprecated (https://github.com/samtools/samtools/releases/tag/1.9). - Ensure locale is set to one supporting UTF-8 bcbio-wide. This may need to get reverted if it introduces issues. - Added hg38 support for STAR. We did this by taking hg38 and removing the alts, decoys and HLA sequences. - Added support for the arriba fusion caller. - Added back missing programs from the version provenance file. Fixed formatting problems introduced by switch to python3. - Added initial support for whole genome bisulfite sequencing using bismark. Thanks to @hackdna for implementing this and @jnhutchinson for drafting the initial pipeline. This is a work in progress in collaboration with @gcampanella, who has a similar implementation with some extra features that we will be merging in soon. - qualimap for RNA-seq runs on the downsampled BAM files by default. Set `tools_on: [qualimap_full]` to run on the full BAM files. - Add STAR junction files to the files captured at the end of a run. ## 1.1.5 (12 April 2019) - Fixes for Python3 incompatibilities on distributed IPython runs. - Numerous smaller Python3 incompatibilities with strings/unicode and types. Thanks to the community for reporting these. - GATK HaplotypeCaller: correctly apply skipping of marked duplicates only for amplicon runs. Thanks to Ben Liesfeld. - Fix format detection for bzip2 fastq inputs. - Support latest GATK4 MuTect2 (4.1.1.0) with changes to ploidy and reference parameters. - Support changes to GATK4 for VQSR --resource specification in 4.1.1.0. Thanks to Timothee Cezard. - Support latest bedtools (2.28.0) which expects SAM heads for bgzipped BED inputs. ## 1.1.4 (3 April 2019) - Move to Python 3.6. A python2 environment in the install runs non python3 compatible programs. The codebase is still compatible with python 2.7 but will only get run and tested on python 3 for future releases. - RNA-seq: fix for race condition when creating the pizzly cache - RNA-seq: Add Salmon to multiqc report. - RNA-seq single-cell/DGE: Properly strip transcript versions from GENCODE GTFs. - RNA-seq: Faster and more flexible rRNA biotype lookup. - Move to R3.5.1, including updates to all CRAN and Bioconductor packages. - tumor-only germline prioritization: provide more useful germline filtering based on prioritization INFO tag (EPR) rather than filter field. - Install: do not require fabric for tool and data installs, making full codebase compatible with python 3. - variant: Filter out variants with missing ALT alleles output by GATK4. - GATK: enable specification of spark specific parameters with `gatk-spark` resources. - RNA-seq single-cell/DGE: added `demultiplexed` option. If set to True, treat the data as if it has already been demultiplexed into cells/wells. - Multiple orders of magnitude faster templating with thousands of input files. ## 1.1.3 (29 January 2019) - CNV: support background inputs for CNVkit, GATK4 CNV and seq2c. Allows pre-computed panel of normals for tumor-only or single sample CNV calling. - variant: avoid race condition on processing input BED files for variant calling when no pre-specific variant_regions available. - structural variation upload: avoid uploading multiple batched calls into sample directories. For lumpy will now have a single output per batch in a sample folder. - install: respect pre-specified bioconda and conda-forge in condarc configuration. Allows use of custom package mirrors. - seq2c: move specialized pre-call calculation upstream to coverage estimation. Allows use of seq2c in CWL runs. - MultiQC upload: fix bug where results from parallel run not moved to final directory. - GATK4 CNV: fix for standardize VCF output, correcting number of columns. - RNA-seq variation: fix for over-filtering variants near splice junctions with STAR. - Structural variant gene annotation: simplify and handle issues with multidirectional comparisons. Handle issues with out of order start/end from CNVkit. - Catch and report unicode characters in templating or YAML descriptions. ## 1.1.2 (12 December 2018) - VarDict low frequency somatic filters: generalize strand and mismatch based filter based on cross-validation to avoid over filtering on high depth panels. - strelka2 joint calling: switch to improved gvcfgenotyper approach for calling from gVCFs. - Heterogeneity: initial support for PureCN and TitanCNA heterogeneity analysis including reporting on LOH in HLA for human samples. Work in progress validations: https://github.com/bcbio/bcbio_validations/tree/master/TCGA-heterogeneity - CNV: initial support for GATK4 CNV calling as alternative to CNVkit for tumor normal analyses - VarDict RNA-seq variant calling: avoid structural variants with recent vardict-java. - RNA-seq variation: filter RNA-seq variants close to splice junctions, supporting STAR and hisat2. - RNA-seq variation: add snpEff effects to output variant calls. Thanks to Manasa Surakala. - RNA-seq: gzip/bgzip FASTQ files in `work/fastq` instead of the original directory. - use biobambam2 BAM to FASTQ conversion instead of Picard in all cases. - Trimming: add built-in support for adapters from the SMARTer Universal Low Input RNA Kit (truseq2) and the Illumina NEXTera DNA prep kit from NEB (nextera2). - ChIP/ATAC-seq: allow skipping duplicate marking. - joint calling: ensure correct upload to final directory when no annotations present - Logging: fix logging in parallel runs with new joblib loky backend. Thanks to Ben Liesfeld and Roland Ewald. ## 1.1.1 (6 November 2018) - single-cell RNA-seq: add built-in support for 10x_v2. - Fix UMI support for small RNA. Compatible with Qiagen UMI small RNA protocol. - Ignore .Renviron when running Rscript to head-off PATH conflicts. - Support SRR ids to download samples with bcbio_prepare_samples script. - tumor-only prioritization: do not apply LowPriority filter by default, instead annotate with external databases. Use `tumoronly_germline_filter` to re-enable previous behavior. - UMIs: apply default filtering based on de-duplicated read depth. Uses `--min-reads 2` with raw de-duplicated coverage of 800 or more or `--min-reads 1` otherwise. Allows error correction with UMIs for higher depth samples. - gemini: databases no longer created by default. Use `tools_on: [gemini]` or `tools_on: [gemini_orig]` to create a database. We now use a reduced database for build 37 to match build 38 and make this forward compatible with CWL. - vcfanno: run gemini and somatic annotations by default, producing annotated VCFs with external information. - alignment preparation: support a list of split files from multiple sequencing lanes, merging into a single fastq - variant: support octopus variant caller for germline and somatic samples. - peddy: fix bug where not all files uploaded on first pipeline run - peddy: For somatic analyses use separate germline calls for tumor/normal, if available, or extracted germline calls from supported callers, instead of somatic variants. - GATK: support ploidy specification during joint calling. - GATK BQSR: bin qualities into static groups (10, 20, 30) to match GATK4 recommendations. Thanks to Severine Catreux. - GATK: support 4.0.10.0 which does not use UCSC 2bit references for Spark tools - variant calling: support bcftools 1.9 which is more strict about duplicated key names in INFO and FORMAT. - seq2c: Upload global calls, coverage and read_mapping files to project directory. - RNA-seq variant calling: Apply annotations after joint calling for GATK to avoid import errors with GenomicsDB. Thanks to Komal Rathi. - CWL: add `--cwl` target to bcbio_nextgen.py upgrade to add and maintain bcbio-vm. - CWL: use standard null instead of string "null" for representing None values. - CWL: support for heterogeneity and structural variant callers that make use of variant inputs. - CWL: support ensemble calling for combining multiple variant callers. - ensemble: remove no-ALT ref calls that contribute to incorrect ensemble outputs - RNA-seq: output a matrix of un-deduped UMI counts when doing single-cell/DGE for quality control purposes. This is called `tagcounts-dupes.mtx` in the final directory. - single-cell RNA-seq: allow pre-transformed FASTQ files as input to DGE/single-cell pipeline. - single-cell RNA-seq: only create one index per specified genome instead of per sample - fgbio: back compatibility for older quality setting `--min-consensus-base-quality` - RNA-seq: fix for `fusion_caller` getting interpreted as a path, leading to memoization/upload issues. - RNA-seq: memoize rRNA quality calculations, speeding up reruns. - RNA-seq: prefix `description` with an X if it starts with a number, for R compatibility. Thanks to Avinash Reddy and Dan Stetson at AstraZeneca. - single-cell RNA-seq: respect `--positional` flag with the new tag counting. Thanks to Babak Alaei at AstraZeneca. - RNA-seq: turn on `--seqBias` flag by default for Salmon as early-version overfitting issues have been fixed. - RNA-seq: report insert size from Salmon fragment distribution, not samtools stats. - RNA-seq: when processing explant samples, produce a combined tx2gene.csv file from all organisms processed. ## 1.1.0 (11 July 2018) - Germline calls: rename outputs to `samplename-germline` to provide easier to understand outputs in final directory. - Add bcbioRNASeq object creation and automatic quality report generation with `tools_on: [bcbiornaseq]` - CWL: Support germline/somatic calling for tumor samples. - CNVkit: improve whole genome runs. Better speed in normalize_sv_coverage through parallelization and avoiding logging. Avoid memory errors in segmentation. - UMI: upload prepared UMI bam file (pre-consensus) to final output directory - Add support for bbmap as an aligner - RNA-seq variant calling: parallelize GATK HaplotypeCaller over regions to avoid memory and timeout issues. - Support joint calling with GATK using pre-prepared gVCF inputs. - RNA-seq variant calling: allow annotation of output variants with vcfanno - Support hg38 builds with peddy QC - QC: support VerifyBamID2 for contamination detection - CWL: adjust defaults for align_split_size and nomap_split_targets to match different parallelization and overhead for these runs - CWL: support for Cromwell runner - custom genomes: Unzip GTF file prior to installation. - Avoid making variant_regions required during processing (by filling with coverage) to differentiate targeted and non analyses downstream. - Avoid attempts to download pre-installed S3 genomes, providing better errors with missing genome installs. - Trimming: add explicit `polyg` option for removing 3' G stretches in NovaSeq and NextSeq data. Now defaults to no polyG trimming unless turned on. - Chip-seq: Add RiP calculation for chip-seq data. - DeepVariant and Strelka2 support for customized targeted/genome calling models per region to handle heterogeneous inputs. - STAR: enable passing custom options for alignment. - Add `tools_off: [coverage_qc]` option to skip calculating coverage stats (samtools-stats and picard). - Adding BAM file for each sample in small-RNAseq pipeline, samtools and qualimap qc metrics to multiqc report. - Allow arbitrary genomes for ChIP-seq. Thanks to @evchambers for pointing out the issue. ## 1.0.9 (10 April 2018) - Use smoove for lumpy variant calling and genotyping, replacing custom lumpyexpress implementation: [validation](https://github.com/bcbio/bcbio_validations/tree/master/NA24385_sv#smoove-validation) - Generalize exclusion of regions during variant calling with new `exclude_regions` target. Includes previously available LCR and high depth regions, in addition to removal of polyX and alternative contigs. - Normalize allele frequency calculation and filtering for Strelka2 and MuTect2. Thanks to Vlad Saveliev. - CNVkit: enable specification of pre-built reference background cnn with `background: cnv_reference`. - CNVkit: handle projects with mixed CNVkit and non-CNVkit usage. Thanks to Luca Beltrame. - Improved Atropos trimming: better use of multicore parallelization in variant and RNA-seq pipelines. - Add support for polyG and polyX trimming to variant calling for NovaSeq 3' end cleanup and generally avoiding low complexity reads. - Structural variant: use SURVIVOR for validation comparisons. - RNA-seq variant calling: use multiple cores for VarDict. - Support miRge2.0 for alternative small RNA annotation. Users should install the tool manually until compatible with bioconda. - Add bamCoverage to chip-seq pipeline to calculate bigwig files. - GATK4: Correctly use GATK4 GatherVcfs when tools_off: [gatk4] specified for variant calling. Thanks to Luca Beltrame. - variant: Default to `mark_duplicates: false` if alignment turned off (`aligner: false`). - variant: Fix race condition when preparing BED files for coverage and sv_regions. Thanks to Tristan Lubinski. - Fix `noalt_calling` to correctly avoid parallelizing on non-standard chromosomes without a variant regions file. - Fix broken `kraken` command. Thanks to @choosehappy. ## 1.0.8 (5 February 2018) - GATK4 is the new default GATK release used in bcbio when running HaplotypeCaller or Base Quality Score Recalibration. Use `tools_off: [gatk4]` to use older GATK 3.x versions. - GATK4: Support 4.0 release with changed command line parameters. Re-enable multicore calling for CWL runs. - GATK4: remove older GATK3 based gatk-framework in favor of equivalent GATK4 commands. - install: move to using recent IPython parallel to avoid dependency issues - install: fix resolution issues due to conda 4.4.x (old ipython-cluster-helper, missing libquadmath.so with numpy due to libgcc update) - RNA-seq variant calling: improve joint calling and parallelization with move to use GATK4 HaplotypeCaller. - QC: improve read counting speed by moving to hts-nim-tools, replacing custom samtools view counting - Add `noalt_calling` to avoid variant calling on non standard chromosomes. Thanks to Vlad Saveliev and Oliver Hofmann. - variant alignment: improve core allocations for non-split alignments to avoid memory issues on 4Gb/core machines with whole genome samples. - Add Total number of reads and adapter found to metrics in small RNA-seq pipeline. - Add mirtop to the tools used in small RNA-seq pipeline for miRNA annotation. - delly: Support 0.7.8 release which calls all variant types together. - gVCF: fix basic filtering for GATK and sentieon when running without joint calling. Thanks to Tom Morris. ## 1.0.7 (6 January 2018) - Automatically include bcbio anaconda PATH when running tools. Also allow custom BCBIOPATH specification to help with modules integration. Thanks to Gabriel Berriz. - vcfanno: only correct VCF headers to use Number=1 when decomposition takes place. Avoids incorrect headers for non-decomposed inputs. - ensemble: normalize and decompose variants prior to incorporating into ensemble calls, handling MNPs called differently across callers. Thanks to Vlad Saveliev. - Avoid bgzipping and grabix indexing fastq inputs when not doing alignment splitting to save processing. - Initial support for minimap2 aligner in variant calling workflows. Still needs validation and benchmarking in comparison to bwa. - Standardize dbSNP annotation to use vcfanno for all variant callers. Remove GATK custom annotations for non-GATK callers, which are not present in GATK4. - CNVkit: drop low coverage contaminating regions in tumor calls. Thanks to Eric Talevich. - Expand `remove_extracontigs` for `bam_clean` to more consistently handle compatible pre-aligned BAMs with different extra contigs in reference genome. - Fix problem collapsing samples for QC when using RNA-seq variant calling with gatk-haplotype. Thanks to Neill Gibson. - Integrate ericscript RNA-seq fusion caller. Thanks to Tetiana Khotiainsteva and Vang Le. - Remove read backed phasing (`phasing: gatk`) for GATK runs in favor of HaplotypeCaller internal phasing. - disambiguation: ensure BAM index present for non-split alignments - Use only end of reads to detect 3' adapters in small RNA-seq pipeline. - Fix BCBIO_JAVA_HOME to correctly pass custom Java to GATK and Picard runs. - ChIP-seq: add generation of greylist regions defined as regions of high depth in the input file on a per sample pair basis. - RNA-seq: STAR now outputs a MAPQ of 60 for uniquely mapped reads instead of 255. - RNA-seq: Ensure BAM files fed into Cufflinks have 255 as the uniquely mapped MAPQ instead of 60 as output by hisat2/STAR/etc. - RNA-seq: omit duplicate files from stringtie assembly merging. Thanks to @mmoisse for the bug report. - Add support for peddy (https://github.com/brentp/peddy) for PED file correspondence/ancestry checking. - ChIP-seq: pass through encode filtered BAMs to upload directory. - seq2c: pass through mapping_reads.txt file to directory. ## 1.0.6 (5 November 2017) - Use mosdepth for callability calculations, replacing goleft depth. Centralize coverage and QC depth calculations around single mosdepth runs. - Improve representation of germline and somatic calls in MultiQC report and output directory, avoiding confusing "-germline" extension. Thanks to Vlad Saveliev. - Structural variants: return combined tumor/normal calls instead of single sample tumor for somatic calls in delly, lumpy, manta, and WHAM. - VarDict: remove `-v 50` as required option for deep targeted panels (>5000x average coverage). Recommend adding if needed by a `var2vcf` resource options. - Templating: avoid automatically setting flowcell date to maintain consistency between runs. - Add `fusion_caller` as an optional algorithm field to turn on/off fusion callers. Currently supports oncofuse and pizzly. - RNA-seq: better appropriate kmer size estimation for reads < 60 bp for Salmon/Rapmap/Sailfish index creation. - RNA-seq variant calling: require gatk-haplotype instead of gatk as the caller. - RNA-seq variant calling: support GATK4 - UMIs: move fgbio consensus calling to use filtering, adds `--max-reads` for high depth regions and swaps `--min-consensus-base-quality` for `--min-base-quality` - Correctly re-bgzip fastq inputs even if not using `align_split_size`. - Fix bug when running with `lumpy_usecnv` that resulted in skipping CNVkit. - GATK gVCF joint calling: avoid running through bcftools for header fixes, using Picard instead. Avoids integer/double conversion incompatibilities. - CWL: run variantcalling with multiple cores, reducing total jobs and enabling mulicore supporting callers. - CWL: support structural variant calling as part of variant pipelines. - Add pizzly (http://www.biorxiv.org/content/early/2017/07/20/166322) as a fusion caller when fusion mode is enabled. - VEP: output an effect call per allele for multiallelic positions. - Define separators for paired fastq files during bcbio_prepare_samples.py - RNA-seq single-cell/DGE: add `transcriptome_gtf` as an option which will collapse single-cell/DGE counts down to the gene level. This is recommended for single-cell and DGE experiments. - ChIP-seq: preliminary support for bwa for ChIP-seq alignment. Compared to bowtie2 on a test dataset this results in a superset of the bowtie2 peaks, with 95% of the common peaks within 50 bases of each other. It calls about 50% more peaks though using the bwa alignments, use with care. ## 1.0.5 (11 Sept 2017) - Add optional downsampling whole genome BAM files to a high maximum coverage (200 times the average coverage) to avoid slow runtimes in collapsed repeats and poly-ATGC regions. Downsampling happens in parallel with post alignment sorting. Currently turned off by default pending runtime improvements. Configure using `maxcov_downsample`. - Separate post alignment recalibration and realignment. Recalibration now occurs multicore to support GATK4 implementation. We generally recommend skipping realignment. - Provide multicore read trimming and streaming bgzip fastq output with atropos, replacing cutadapt as the default trimmer. - hg38 runs do not run bwakit's bwa-postproc.js cleanup scripts unless HLA calling needed. Avoids slowdowns using this postprocessing script when running bwa with multiple cores. - Tumor-only prioritization uses vcfanno output instead of GEMINI, allowing use without needing to build a full GEMINI database. - Use samtools multicore indexing, replacing sambamba multicore index. - Replace components of pipeline using single core sambamba view -c with parallel samtools equivalents. - Replace sambamba depth coverage calculations with mosdepth to improve speed and parallelization. - Multicore base quality score recalibration with GATK4 and Sentieon. - GATK4: add support for gVCF based joint calling. - GATK4: fix option usage for gVCF creation with HaplotypeCaller - Allow overriding Java used in bcbio with `BCBIO_JAVA_HOME` - Do not split individual sample VCFs during pooled batch calling. This previously happened only for small batches with less than 5 samples, now we avoid it entirely and let users do downstream sample extraction. - Update OptiType HLA calling to use multicore CBC solver, also avoiding GLPK issues. - Additional approach to retrieving cluster IP addresses for IPython and logging, using the fully qualified domain name. - Add `archive: [cram-lossless]` to do CRAM archiving of outputs without quality score compression. Thanks to Alison Meynert. - Add `tools_off: [lumpy-genotype]` option to skip Lumpy genotyping. - CWL/WDL: use single file tarballs for complex collections of files like aligner, RTG and snpEff indices. - GC bias correction is now the default for Salmon read-based quantification. See https://github.com/salmonteam/SalmonBlogResponse/blob/master/SalmonBlogResponse.md for the reasoning behind this change. - Add kallisto support for non single-cell RNA-seq experiments. - Salmon can now be run alongside other RNA-seq quantifiers. - Cufflinks and Stringtie can be run alongside each other as RNA-seq quantifiers. - Check BED input files for coordinates off the ends of contigs. ## 1.0.4 (9 July 2017) - Initial support for GATK4 variant calling with HaplotypeCaller and MuTect2. Requires `tools_on: [gatk4]` https://github.com/bcbio/bcbio_validations/tree/master/gatk4 - Enable adapter trimming for variant calling pipeline. - Provide `trim_ends` command to quickly do defined end trimming as part of variant calling fastq preparation. - Support duplex UMIs, present as embedded barcodes on read 1 and read 2. - Sort region based analyses like variant calling by interval size. Ensures longest intervals run first avoiding delay at end of sample processing. - Ensure FreeBayes dbSNP and GATK annotations passed into final file. Thanks to @semal. - Use new Ensembl vep (variant effect predictor) with updated annotations. Thanks to Matthias De Smet. - Accept files from HTTP/FTP as input - CWL: use json input files for passing inputs instead of flattened command line arguments. Improves compatibility with multiple runners. - Allow subsetting a pre-aligned BAM to only standard chromosomes, removing non chr1-22,X,Y for human. This allows runs of pre-aligned data with different extra chromosomes than the bcbio reference builds. Thanks to Oliver Hofmann. - Improved support for pre-aligned BAMs by using contigs in BAM file for coverage calculations. - Avoid grabix race conditions with multiple identical input files. Thanks to Andrey Tovchigrechko. - Remove usage of lxml for qsignature and qualimap to avoid icu library errors. - CNVkit: merge adjacent calls with identical copy numbers - Add support for triple-barcoded cellular barcodes. - Add support for Illumina's SureCell single-cell RNA-seq. ## 1.0.3 (7 May 2017) - Allow installs to pull a specific git hash or tag revision of bcbio codebase. - Fix FreeBayes somatic and multi-sample calling order to be consistent between chromosome region runs. Thanks to Ho Danliang. - Fix structural variant output upload for complex batching cases. Correctly handle shared normals and other multi-batch by naming outputs using batches. Thanks to Sven-Eric Schelhorn. - Move to samtools/bcftools/htslib 1.4. Provides parallel bgzip, removing need for pbgzip and improved concatenation speed for region split VCF files. - Improve Lumpy prioritization speeds by adjusting location of breakend genotyping. - UMI consensus: reduce runtimes to ~2/3 of previous avoiding unnecessary compression and file IO. - UMI consensus: pass along metrics about consensus read generation as BAM tags in final file (cD = depth, cE = error rate) - Support DNApi for de novo adapter detection in small RNA pipeline - Several updates to the VarScan support: honor options specified in the resource config section; honor min_allele_frac option and set --strand-filter flag in the single-sample case; general cleanups. Thanks to Christian Brueffer. - Update validation plots to support matplotlib 2.0. - Enable mixed list/string inputs to germline calling. Thanks to Luca Beltrame. - Fix qsignature outfile parsing. Thanks to Oliver Hofmann. - Allow structural variant validations with VCF truth sets. Enables more flexible comparisons without size and event binning. - Provide seq2c VCF output and enable validation of calls. - Allow specification of seq2c options through resources. Thanks to Sally Luke and Marisa Cunha. - Avoid using R_LIBS settings for R runs to limit incompatibilities with externally installed R packages. - Provide absolute paths for relative paths to files in algorithm list inputs. Thanks to Matthias De Smet. - Switch to Salmon from Sailfish as default alignment-free RNA-seq quantification algorithm. - Add `sailfish` as a valid option for `expression_caller`. - Fix chimeric alignment output option for STAR. - Remove deprecated tidy counts for Sailfish/Salmon. - Allow more possible empty/skip inputs in `variantcaller` and `svcaller`: None, null and empty lists - Move DEXSeq to be an opt-in expression caller by default. - Speed up combination of counts/RPKM/FPKM/TPM of samples into a single table by 10x. ## 1.0.2 (7 March 2017) - Fix FreeBayes paired somatic calling by generalizing support for finding non-ordered tumor/normal placement in VCF. - Re-add checks for pre-bgzipped fastq inputs to alignment preparation thanks to a fix for grabix to handle Illumina bgzip outputs. - Provide DNA damage annotation for low frequency sequencing errors in somatic samples. Use `tools_on: [damage_filter]` - Add viral detection for variant calling DNA-seq cancer samples. Uses virus sequences from TCGA GDC distribution and provides simple counts of unmapped reads against viral sequences in MultiQC report. - Improve lumpy structural variant runs from pre-aligned BAM files, using extract_sv_reads to avoid need to resort input files. Thanks to Neill Gibson. - Move VCF files from SV prioritization to final upload directory. Thanks to Miika Ahdesmaki. - Provide whole genome coverage plots with goleft indexcov. Thanks to Brent Pedersen. - Speed up post-alignment callability calculations by using default parameters to goleft depth. Thanks to Brent Pedersen. - Allow custom vcfanno configuration files for variant annotation and GEMINI database creation, using `vcfanno` configuration parameter. Optionally allows use of `vcfanno` without GEMINI database creation. - Always use specified cores for analysis re-runs in local multicore mode. Avoids confusing core behavior with checkpoints on re-starts of analysis in a previous work directory. - Upload of pipeline results to iRODS. Thanks to Matthias De Smet. - Add duplicate removal to post-FreeBayes processing. Thanks to Neill Gibson. - Support latest svtyper (0.1.1) for lumpy to provide speed improvements. Will default to 0.1.1 at next release. (use `bcbio_conda install -c bioconda svtyper=0.1.1` to test in development) - Work towards supporting a Python 3 compatible bcbio codebase. Thanks to Michael Crusoe. - Reduce VarDict maximum BED region sizes for better memory usage. Thanks to Nikolai Karulin, Oliver Hofmann, Miika Ahdesmaki and Zhongwu Lai. - Require `tools_on: [lumpy_usecnv]` to pre-run CNVkit as input to Lumpy, allowing Lumpy and CNVkit to run in parallel otherwise. - Avoid issues with CNVkit bin size estimates for normal associated with multiple tumors. Thanks to Ho Danliang. - Fix double uploading of fast RNA-seq quantification. - Output single-cell RNA-seq counts in annotated MatrixMarket format. ## 1.0.1 (17 January 2017) - Fix bug in 1.0.0 release with parallel calculations on whole genome samples. The release version only parallelizes by chromosome instead of callable regions, resulting in less parallelism. Thanks to Sven-Eric Schelhorn and Neill Gibson. - Generalize use of working directories to support runs on S3 mounted filesystems. Ensures all work takes place inside transactional directories. Thanks to Tetiana Khotiainsteva and Sven-Eric Schelhorn. - Provide separate germline calling for somatic tumor/normal pairs. Supplements somatic calls with standard germline calls on normal samples, including ensemble and SV calling. - Support creating GEMINI databases with new generic mechanism using vcfanno/vcf2db. This allows creation of GEMINI output for any organism. Adds support for hg38 with annotations from dbSNP, Clinvar, ExAC and ESP. - Support FreeBayes 1.1.0 for improved memory usage and 3-4x speedup. Will default to 1.1.0 at next release. Validation work: https://github.com/bcbio/bcbio.github.io/blob/master/_posts/2016-11-21-giab-hg38-freebayes.md - Rework quality control for speed and output directory consistency. Avoid re-duplicating calculations and put all output in qc directory to make re-runs easier. Thanks to Vlad Saveliev. - Fixes for Seq2C concurrency problems when preparing BED files. Thanks to Vlad Saveliev. - Update WHAM structural variant caller to support the latest release. - Update delly structural variant caller to support the latest release. - Improve dbSNP annotation speeds for adding rs IDs to VarDict output. Thanks to Ben Liesfeld. - Support for VEP 87 with additional plugins and generalization of fields. Thanks to Matthias De Smet. - Deprecate `clinical_reporting` parameter and introduce new `effects_transcripts` parameter than enables more control over variant effects prediction. Enable HGVS by default for human projects and separates from transcript selection. - For lumpy runs that use samblaster, use samtools sort instead of sambamba sort. Avoids segfault issues with samblaster. Thanks to Oliver Hofmann. - Pre-install capture region BED files and enable short hand specification in sample configuration. - Use vt normalize as part of GEMINI decomposition to clean up complex multiallelic variants. Thanks to Sergey Naumenko. - Testing suite cleanup. Move to py.test and separate integration and unit tests. Thanks to Tetiana Khotiainsteva. - Fix issue with cutadapt hanging on gzipped input. Thanks to Stephen Turner. - Updated cutadapt to use single-pass trimming for paired-end files, improving performance and hitting the disk less. - Added support for cellular barcode error correction with single-cell RNA-seq via the `cellular_barcode_correction` parameter. This corrects edit distances up to the set value, defaults to 1. - Add support for sample-based demultiplexing of single-cell RNA-seq runs. - Move single-cell RNA-seq results to the upload directory. - Make positional UMI default to off for single-cell RNA-seq. - Add support for the Klein lab v3 version of the inDrop protocol. ## 1.0.0 (20 November 2016) - Default to no calling if `variantcaller` not specified, instead of old GATK UnifiedGenotyper default. - Use samtools depth instead of bedtools genomecov for depth calculations, and calculate high depth regions during initial depth calculations. Improves speed by more than 6x. Thanks to Brent Pedersen. - Adjust de-duplication strategy to use bamsormadup from biobambam2 for most cases and samblaster when split and discordant reads needed for SV calling with lumpy. - Fix handling of fresh installs with GATK 3.6 only included. Correctly handles versioning from bioconda and lack of specifically defined jar directory. - Unset JAVA_HOME when running gatk-framework and GATK > 3.6, forcing use of bcbio installed Java 8. Thanks to Brad Wubbenhorst. - Fix bug when running realignment without recalibration in GATK 3.6. Thanks to Pär Larsson. - Get from GEO server, GSM FASTQ samples using bcbio_prepare_samples.py script - Add seqcluster stats to QC folder - Allow manual specification of total memory and core usage for machines in `resources`. Thanks to Juan Caballero. - Allow PED based gender specifications (1=male, 2=female). Thanks to Brent Pedersen. - Annotate validation variants with genome context from GA4GH and other sources for interpreting true/false positives/negatives. - Limit GATK cores used for GenotypeGVCFs to avoid excessive memory usage. - VQSR: allow forcing GATK to try VQSR with tools_on. Generate VQSR plots. Thanks to Zhengqiu Cai. - Support ATAC-seq for chipseq pipeline. - Remove duplicates after alignment for chipseq pipeline. - Support for bzip2 input files during variant calling. Thanks to Paulo Silva. - Allow non-positional UMI Rapmap quantified single-cell RNA-seq. - Re-enable save_diskspace option to reduce disk usage during alignment preparation and split alignments. - Offload fixing the unmapped Tophat file to tophat-recondition. Thanks to Christian Brueffer. - Add support for vcfanno (https://github.com/brentp/vcfanno) to annotate VCFs with other VCFs/BED files. - Mark possible RNA-edits for GRCh37/hg19 using RADAR coordinates. Thanks to Sergey Naumenko for the suggestion. - Add `local_controller` option to run the controller alongside the main bcbio process. Thanks to Brent Pederson and Sven-Eric Schelhorn. ## 0.9.9 (18 July 2016) - Change defaults for recalibration and realignment to False. These have been the recommended settings (http://bit.ly/bcbio-minimal) and no realignment now matches Broad recommendations. - Use conda installed Java instead of requiring external installation for most tools. - Support GATK 3.6 with Java 8 installed as part of anaconda. Older GATK versions for calling and recalibration/realignment require external Java 7. - Re-organization of variants stats using bcftools and cleaning gemini queries to get individual samples metrics. - Quality control back end revamped to support better parallelization and pluggability of new QC metrics. - Support CNV calling with Seq2C for exome, targeted or amplicon experiments. Thanks to Vlad Saveliev. - Add `fixrg` target to `bam_clean` to accept BAM inputs with correct sorting and reads but that need an updated read group. - More robust file transactions across network filesystems, avoiding failures from partially transferred files. Thanks to Sven-Eric Schelhorn. - Improved checking of BAM files during merge steps. Thanks to Sven-Eric Schelhorn. - Add SAMPLE and PEDIGREE tags to tumor/normal VCF outputs to enable easier post-analysis parsing of results. - Add single point for annotation following variant calling to improve pluggability of new annotation types. - Add support for running germline and somatic calling with Sentieon callers (https://peerj.com/preprints/1672/). Requires license from Sentieon. - Fix fusion calling using Tophat2. Thanks to @csardas for raising the issue. - Add support for kallisto quantification of single-cell RNA-seq data. - Add `transcriptome_fasta` option to single-cell RNA-seq. This allows the user to provide a transcriptome FASTA file to quantitate against rather than use the `bcbio` provided annotation. - Fix naming of vardict RNA-seq variant calls. Thanks to @csardas. ## 0.9.8 (20 May 2016) - Correctly install all datatargets on new installation. Previously we'd skipped installing default additional data unless specified. - Use yamllint to find wrong syntaxes in the YAML file that are ignored by pyyaml package and can affect the analysis. - Improve choosing split regions for batch analysis to use the unionized intersection of non-callable regions. This enables better use of batches with different callable regions. Thanks to Neill Gibson. - Fix HLA typing issues and handle HLA typing on split alignments. Thanks to Miika Ahdesmaki. - Set `align_split_size` automatically based on input file sizes, trying to provide reasonable splits and avoid too many splits for large files. - Fix high depth identification for whole genome runs, correctly calculating it when also inferring coverage estimations. Thanks to Neill Gibson. - Do not remove duplicates for GATK variant calling when mark_duplicates is False or running amplicon sequencing. - Fix installation of mutect jar via toolplus when mutect not previously present in configuration. - Platypus: revert filtering back to defaults after additional cross-validation: http://i.imgur.com/szSo5M6.png - Enable gVCF output with tools_on: [gvcf] for users who need gVCF output for downstream analyses. - Avoid downscaling memory when recalibrating/realigning with GATK, since we should not longer need to work around Java issues. Thanks to Luca Beltrame. - Do not use samblaster on genomes with greater than 32768 contigs, the samblaster maximum. Thanks to morten (@mattingsdal). - Move to samtools for output CRAM support, using bamUtils for 8-bin compression of read quality scores. - Remove `merge_bamprep` option and always merge realigned BAM files if run. - Correctly clean up additional problem characters in sample descriptions that can confuse shell commands. ## 0.9.7 (29 March 2016) - Use MultiQC (github.com/ewels/MultiQC) as main package to process all QC metrics. - New install procedure for data: `--datatarget` allows installation of sub-sets of supplemental data for smaller installs for small RNA only analysis. Also provides a consistent framework for installing larger data types. - VEP data no longer installed by default. Requires `--datatarget vep` - During install, `--toolplus` only used for third party tools like GATK and MuTect and not data installation, which moved to `--datatarget` - Provide `data_versions.csv` in output folder that has versions of reference data used in the analysis. - Use sample description for BAM read group IDs, instead of lane index. This allows remixing of samples after processing without potential collisions. Thanks to Neill Gibson. - Use sample description for file names instead of lane/flowcall information. Makes re-runs more stable when using template and files easier to interpret. Back compatible with re-runs of old work directories. - Finalize support for MuTect2 with validation against the DREAM synthetic 4 dataset (http://imgur.com/CLqJlNF). Thanks to Alessandro (@apastore). - Do not bgzip inputs when they are already gzipped and do not require parallelization or format conversion. Thanks to Miika Ahdesmaki. - Use new snpEff annotations (ANN) instead of older approach (EFF). The new annotations are more interoperable and supported by GEMINI. - Lazy import of matplotlib libraries to avoid slow startup times. - Only apply ploidyfix to all female batches to remove Y chromosome. Avoids confusion with file produced in other cases without any changes. - Improvement to bcbio CWL integration: support parallel alignment and variant calling. - Support for Salmon and RapMap added. - FastRNA-seq pipeline implemented that does nothing but run Salmon with no QC. - Singlecell RNA-seq pipeline implemented that uses https://github.com/vals/umis to handle the UMI and cellular barcode, aligns with RapMap and quantitates by counting, scaling ambiguous reads by the number of transcripts they could have come from. - Migrate bowtie and bowtie2 to handle split input alignments, bgzipped inputs, and produce sorted, de-duplicated BAM files. This allows use in additional standard pipelines. Thanks to Luca Beltrame. - Switch final upload directories for salmon and sailfish results to be of the form samplename/salmon instead of samplename/salmon/samplename. ## 0.9.6 (12 February 2016) - Installation uses conda packages from bioconda for Python dependencies and third party tools. - Add macs2 to chipseq pipeline. - Add germline output files for somatic calling pipelines. The standard variant calls identify somatic mutations different from a normal, while the germline has pre-existing mutations which might contribute to cancer development. - Use parallel bgzip for preparation of input fastq files for parallelization and alignment. Thanks to Guillermo Carrasco. - Avoid extacting individual sample calls from pooled variant call runs for samples with more than 5 individuals in a batch. Avoids slow extraction run times. Thanks to Neill Gibson. - Add explicit check for BED file mismatches with reference genome. - During validation, report truth counts relative to initial truth set representation and pick best metric for plotting ROC scores. - Remove `--sudo` flag from installer. bcbio requires install into a directory structure with user permissions. - Add ability to tweak fastq preparation for alignment splitting so we can explore alternative approaches to bgzip and grabix index. - Re-enable `stringtie` as an expression caller. - Allow `stringtie` as a transcript assembler. - Replace the `assemble_transcriptome` option with `transcript_assembler`, which accepts a list of assemblers to run. The output of all the assemblers is merged at the end with Cuffmerge. - Move Picard to use conda installed `picard` single executable instead of custom installed java directory of jars. - Add library type option to Cufflinks assembly. Thanks to Konstantin (@dezzan). - Tag variants decomposed with vcfallelicprimitives. Thanks to Neill Gibson. - Fix Platypus problem where we weren't correctly specifying BED regions since latest update skips over files not ending with".txt" or ".bed". ## 0.9.5 (12 December 2015) - Add miRDeep2 to small RNA-seq analysis and quantify the novel miRNAs for all samples. - Enable calling of HLA alleles with human build 38 (hg38). Turn on with the `hlacaller` option. - Structural variant prioritization with BED files of known biologically important regions. Extracts SV calls in these regions and produces a tab delimited high level summary. Use the `svprioritize` option to enable. - Add tRNA count and figures by tdrmapper for srna-seq pipeline. - Avoid running callability checks on smaller chromosomes less than 1 million basepairs. Saves computation and disk IO on alt and support regions we don't split on. - Enable nested batch specifications, allowing samples in partially overlapping batches. - Speed improvements for Lumpy genotyping. Move to latest svtyper and avoid genotyping breakends. - Allow use of VEP annotations on non-human analyses. - Filter VarDict calls with poor mapping quality support (-Q 10) which trigger low frequency false positives. - Remove ENCODE blacklist regions when calling with VarDict and FreeBayes on whole genomes. Avoids long run times due to collapsed repeats near centromeres. - Update VarScan to 2.4.0 and rework support to allow piping between mpileup and VarScan to avoid filesystem IO. - Annotate ensemble calls with information about supporting callers. Thanks to Pär Larsson and Son Pham. - Move eXpress to expression_caller instead of being run by default. - rRNA calculation uses the count file instead of using counts from GATK. - Merge STAR fusion calls back into the BAM file. Thanks to Miika Ahdesmaki. - Added preliminary support for the hisat2 aligner. - Swapped STAR indexing to use on the fly splice junction indexing. - Slightly inceased default DEXseq memory requirements in bcbio_system.yaml. - Add support for RNA-seq for hg38 and hg38-noalt - Make Sailfish the default for non-count based expression estimation. Produces isoform-level (combined.isoform.sf.tpm) and gene-level (combined.gene.sf.tpm) TPM expression estimation. - Move Cufflinks to be off by default for expression estimation (turn on via expression_callers if needed). - Add STAR fusion gene parameters suggested by @felixschlesinger. - Add disambiguation to Sailfish by creating a master FASTA file of all transcripts from all organisms, quantitating each and separating out the organism-specific transcripts after. - Add VarDict support for RNA-seq variant calling. Thanks to Miika Ahdesmaki and Sven-Eric Schelhorn. ## 0.9.4 (14 October 2015) - Ensure genome data sort order is identical to BED files when annotating structural variant calls. Thanks To Miika Ahdesmaki. - Improve low frequency calling for VarDict using vaidation against DREAM synthetic dataset 4. - Install truth sets for germline and cancer calling automatically as part of bcbio and make it easy to include them in the configuration files for validation. - Avoid need to set LD_LIBRARY_PATH and PERL5LIB on installations. - Update Scalpel to latest version (0.5.1) and improve sensitivity for low frequency indels: http://imgur.com/a/7Dzd3 - Drop `coverage_depth_max` for downsampling, which no longer works in GATK 3.4. The option wasn't supported by other callers so was more confusing than useful. - Fix missing BAM index when running with `align: false`. Thanks to Stephan Pabinger and Severine Catreux. - Annotate structural variant files with snpEff. Initial steps towards summarized structural variant reporting. - Add ability to specify platform unit (PU) and library (LB) in BAM header. Thanks to Brad Wubbenhorst. - Update gatk-framework to 3.4-46 to avoid errors dealing with new gVCF output. - Set java.io.tmpdir to avoid filling up global temporary space with snpEff. Thanks to Oliver Hofmann. - Speed up transcriptome-only processing. Thanks to Sven-Eric Schelhorn. - Add bamtools output to RNA-seq quality metrics. Thanks to Sven-Eric Schelhorn. - Expand input quality format detection to detect full range of possible Sanger values. ## 0.9.3 (27 September 2015) - Fix bug when using tumors with multiple normals and no CNV calling. Additional tumor sample would get lost due to lack of early (CNV-based) calling. Thanks to Miika Ahdesmaki. - Include R and Rscript in the installation with conda packages and use for installing and running R-based tools. Avoids issues with alternative R versions and need for a separate installation. - Fix bug when using CNVkit on disambiguated inputs. Thanks to Miika Ahdesmaki. - Re-work structural variant infrastructure to provide plug-in parallel ensemble calling, removing the previous overlap-based ensemble calls. Currently supports MetaSV for ensemble calls. Also re-works validation to not rely on ensemble-overlap calls. - Default to using Real Time Genomics vcfeval (https://github.com/RealTimeGenomics/rtg-tools) for validation instead of bcbio.variation. Improves speed and resolution of closely spaced variants. The old funtionality is still available with `validate_method: bcbio.variation`. - Correctly apply BQSR when using recalibration with PrintReads by using GATK full instead of the open source GATK framework which silently ignores BQSR option. Thanks to Severine Catreux. - Require larger blocks (250bp, moved from 100bp) to find regions for splitting analysis to avoid too tight splitting around small homozygous deletions. - Adjust mapping quality (MQ) filter for GATK SNP hard filters to improve sensitivity http://imgur.com/a/oHRVB - Ensure memory specification passed to sambamba and samtools sort during disambiguation and RNA-seq. Thanks to Sven-Eric Schelhorn. - Fix compatbility with bedtools groupby in v2.25.0, which needs short parameters instead of long parameter names. - Allow turning off variant quality score recalibration with `tools_off: [vqsr]` - Generalize group size for batching gVCFs prior to joint calling with `joint_group_size`. Thanks to Severine Catreux. - Support GEMINI 0.17.0, which does not have a --no-bcolz option since that is the default. - Remove test_run parameter since it was poorly supported and not used much. - Fix issue with featureCounts sorting not working in parallel by pre-sorting and filtering the BAM file. - Unified stock coverage and experimental coverage reporting. - Deprecated `report` and `coverage_experimental` as algorithm keys. ## 0.9.2 (1 September 2015) - Support IPython 4.0 with ipyparallel - Fix bug in writing BAM and VCF indexes to final directory. Correctly add indexes as bam.bai and vcf.gz.tbi. - Fix bug in queryname sorting on split files for feeding into diambiguation. Ensure proper sorting with explicity sambamba sort. Thanks to Sven-Eric Schelhorn. - Ensure extra FreeBayes alleles get removed prior to vcfallelicprimatives, avoiding leaving incorrect genotype allele fields. Thanks to Michael Schroeder. - Split CNVkit processing into individual components, enabling better parallelization and control over parameters. - Genotype Lumpy structural variant calls with SVtyper. - Initial support for small RNA pipeline. Thanks to Lorena Pantano. - Support for MetaSV to prepare combined structural variant calls. - Add smallRNA-seq pipeline - Test automatic report for variants calling and standard pipeline. - Allow Cufflinks to be turned off via tools_off. ## 0.9.1 (6 August 2015) - Fix novoalign to work with parallel split alignments. Thanks to Tyler Funnell. - Move lumpy-sv to latest version which uses lumpyexpress instead of speedseq. - Support the manta SV caller from Illumina. Validations: http://imgur.com/a/Gajsg - Remove high depth regions from structural variant calling exclusion file to avoid false positives with lumpy. Thanks to Miika Ahdesmaki. - Move some structural variant calling, like CNV detection, prior to variant calling. Allows use of CNV calls as inputs for variant detection tools. - Generalize support for interaction with blob storage and graphing to support alternative cloud providers. Initial support for interacting with Azure. Thanks to Alexandru Coman. - Remove VarDict call lines where reference and alternative allele are identical. - Fix assignment issues during prioritization with new GEMINI and sqlite. - Support updated versions of sambamba, which provide headers for window depth commands. ## 0.9.0 (20 June 2015) - GATK 3.4: support HaplotypeCaller by avoiding setting downsampling (-dcov) option by default. - Single sample structural variant calling: corectly handle multiple variant callers. Thanks to Sven-Eric Schelhorn. - Make VarDictJava the default caller when `vardict` specified. `vardict-perl` is now required to specifically use the Perl version. - VarDict and VarDictJava: limit regions to 1Mb with overlaps to avoid memory errors. Ignore regions without BED reads which can lead to large genomic sections and memory errors. - VarDict and VarDictJava: annotate outputs with dbSNP. - Add `tools_on` configuration with `svplots` option. This turns off structural variant plotting by default, which can be time consuming compared to calling. - Add a `--only-metadata` argument to template preparation that will only include BAM or fastq files in sample YAML if they are present in the metadata CSV file. - samblaster: support -M flag in 0.1.22 release - Fix VEP/GEMINI incompatibility where empty fields are included in VCF output. - VarDict: restrict maximum region size within a BED file to 2Mb to avoid high memory usage and failures for longer regions. - Include snpEff effects summary file in output directory when used for effects prediction. ## 0.8.9 (10 May 2015) - Upgrade variant effect predictor (VEP) to the latest Ensembl version (79) with support for hg38. The latest VEP has better support for multiple versions but incompatible database naming. This requires an update of tools and data in a two step process. First `bcbio_nextgen.py upgrade -u stable --tools` (or `-u development`) then `bcbio_nextgen.py upgrade --data`. - Improve de-duplication for split alignments. Do not sort/merge during splits, and instead perform a global merge sort and de-duplication of the final set of reads. - Initial support for new human genome build (hg38/GRCh38) including alternative alleles. Usage is in place but still requires validation and additional testing. - Remove alternative alleles from downstream variant calling after using in alignment to avoid issues with chromosome names like `HLA*`. - Enable installation of external conda-managed tools. Adds in builds for heterogeneity analysis. - Clean up preparation process for multi-allelic inputs to GEMINI to avoid needing to split/merge. Thanks to Sven-Eric Schelhorn. ## 0.8.8 (29 April 2015) - Automatically calculate `coverage_interval` based on coverage calculations, avoiding need to set this directly in input configuration. - Update vt decompose to handle additional multi-allelic adjustments including all format attributes, providing full support for new GEMINI changes. Thanks to Brent Pedersen and Adrian Tan. - Add `default` configuration target to `bcbio_system.yaml` reducing the need to set program specific arguments for everything. - Ensure `resources` specified in input YAML get passed to global system configuration for making parallelization decisions. Thanks to Miika Ahdesmaki. - Run upload process on distributed machines, allowing upload to S3 on AWS to take advantage of machines with multiple cores. Thanks to Lorena Pantano. - Re-write interactions with external object stores like S3 to be more general and incorporate multiple regions and future support for non-S3 storage. - Scale local jobs by total memory usage when memory constrains resource usage jinstead of cores. Thanks to Sven-Eric Schelhorn and Lorena Pantano. - Disambiguation: improve parallelization by disambiguating on split alignment parts prior to merging. Thanks to Sven-Eric Schelhorn. - Disambiguation: ensure ambiguous and other organism reads are sorted, merged and passed to final upload directory. Thanks to Sven-Eric Schelhorn. - Fix problem with sambamba name sorting not being compatible with samtools. Thanks to Sven-Eric Schelhorn. - FreeBayes: update to latest version (0.9.21-7) with validation (http://imgur.com/a/ancGz). - Allow bz2 files in bcbio_prepare_sample.py script. - Ensure GEMINI statistics run for project summary file. Thanks to Luca Beltrame. - Better error checking for booleans in input configuration. Thanks to Daryl Waggott. - Implement qualimap for RNAseq QC metrics, but not active yet. - collect statistics graphing capabilities moved from bcbio-nextgen-vm, enabling plotting of resource usage during runs. Thanks to John Morrissey and Lorena Pantano. ## 0.8.7 (12 March 2015) - Run snpEff 4.1 in back-compatibility mode to work with GEMINI database loading. Fixes snpEff 4.1/GEMINI effects loading. - Add PED file to GEMINI database load, containing family, gender and phenotype information from bcbio metadata. Thanks to Luca Beltrame and Roy Ronen. - Enable specification of input PED files into template creation, extracting family, gender and phenotype information. Any sample rows from PED files get used when creating the GEMINI database. - Fix preparation of multi-allelic inputs to GEMINI by implementing custom merge of bi-allelic and split multi-allelic. Previous implementation using GATK CombineVariants re-merged some split multi-allelic, losing effects annotations. - Skip contig order naming checking with bedtools 2.23.0+ to avoid potential issues with complex naming schemes. - Installation and upgrade: Set pip SSL certificates to point at installed conda SSL package if present. Avoids SSL errors when pip can't find system certificates. Thanks to Andrew Oler. - Enable support for PBSPro schedulers through ipython-cluster-helper. ## 0.8.6 (23 February 2015) - Calculate high depth regions with more than 20x median coverage as targets for filtering in structural variants. Attempts to detect and avoid spurious calls in repetitive regions. - Support snpEff 4.1, including re-download of snpEff databases on demand if out of sync with older versions. - Split multi-allelic variants into bi-allelic calls prior to loading into GEMINI, since it only handles bi-allelic inputs. Thanks to Pär Larsson. - Pass ploidy to GATK HaplotypeCaller, supporting multiple ploidies and correct calling of X/Y/MT chromosomes. Requires GATK 3.3. - Remove extra 'none' sample when calling tumor-only samples using MuTect. Harmonizes headers with other tumor-only callers and enables tumor-only ensemble calling. Thanks to Miika Ahdesmaki. - Perform variant prioritization as part of tumor-only calling, using population based frequencies like 1000 genomes and ExAC and presence in known disease causing databases like COSMIC and Clinvar. - Switch to samtools sort from sambamba sort during alignment streaming. Saves steps in processing and conversions on single sample no deduplication inputs. - On AWS, download inputs for S3 instead of streaming into fastq preparation to avoid issues with converting BAM to fasta. Thanks to Roy Ronen. - Provide better defaults for mincores that packs together multiple single IPython processes on a single cluster request -- use core specification from input configuration. Thanks to Miika Ahdesmaki. ## 0.8.5 (11 January 2015) - No longer keep INFO fields with `vcfallelicprimitves` in FreeBayes, Platypus and Scalpel calling to prevent introduction of problematic fields for multi-allelic MNPs. - Fix batching problem when using `coverage` and multiple shared batches like a global normal in cancer calling. Thanks to Luca Beltrame. - Use `mincores` specification to ipython-cluster-helper to combine single core jobs into a single submission job for better memory shared on resource constrained systems. - Move disambiguation split work inside parallel framework so download and preparation occurs on worker nodes or inside Docker containers. Enables on demand download of disambiguation genomes. - Ensure population databases created when some inputs do not have variant calls. - Switch to seaborn as matplotlib wrapper, from prettplotlib. - Fixes for ensemble structural variant calling on single samples. - Fixes for mixing joint and pooled calling in a single configuration file. - Support for qSNP for tumor-normal calling. - Add eXpress to RNA-seq pipeline. - Add transcriptome-only mapping with STAR, bowtie2 or bwa. - Change logging time stamps to be UTC and set explicitly as ISO 8601 compliant output. Improves benchmarking analysis and comparability across runs. - Add support for RNA-seq variant calling with HaplotypeCaller - Fix parallelization of DEXSeq. ## 0.8.4 (29 November 2014) - Improvements in VarDict calling on somatic samples. - Fix compatibility issue with bedtools 2.22.0 when calculating genome coverage. - Fix joint calling upload to avoid redundant inclusion of full VCF file in individual sample directories. - Fixes for inclusion of GATK jars inside Docker contains when running distributed jobs. - Enable generation of STAR indexes on demand to handle running STAR on AWS instances. - Re-organize code to prepare samples and reference genomes so it runs inside distributed processing components. This isolates process to Docker containers on AWS and also enables complex operations like preparing reference genomes on demand. ## 0.8.3 (19 November 2014) - Improve tumor/normal calling with FreeBayes, MuTect, VarDict and VarScan by validating against DREAM synthetic 3 data. - Validate ensemble based calling for somatic analysis using multiple callers. - Improve ability to run on Amazon AWS, including up to date interaction with files originally stored in S3 and transfer to S3 on completion with encryption. - Avoid race conditions during `bedprep` work on samples with shared input BED files. These are now processed sequentially on a single machine to avoid conflicts. Thanks to Justin Johnson. - Add data checks and improved flexibility when specifying joint callers. Thanks to Luca Beltrame. - Default to a reduced number of split regions (`nomap_split_targets` defaults to 200 instead of 2000) to avoid controller memory issues with large sample sizes. - Avoid re-calculating depth metrics when running post variant calling annotation with GATK to provide accurate metrics on high depth samples. Thanks to Miika Ahdesmaki. - Consistently keep annotations and genotype information for split MNPs from vcfallelicprimitives. Thanks to Pär Larsson. - Enable VQSR for large batches of exome samples (50 or more together) to coincide with joint calling availability for large populations. - Support retrieval of GATK and MuTect jars from S3 to enable integration with bcbio inside Docker. - Bump pybedtools version to avoid potential open file handle issues. Thanks to Ryan Dale. - Move to bgzipped and indexes human_ancestor.fa for LOFTEE to support access with new samtools that no longer uses razip. ## 0.8.2 (September 17, 2014) - Fix bug in creating shared regions for analysis when using a single sample in multiple batches: for instance, when using a single normal sample for multiple tumors. Thanks to Miika Ahdesmaki. - Unify approach to creating temporary directories. Allows specification of a global temporary directory in `resources: tmp:` used for all transactions. This enables full use of local temporary space during processing, with results transferred to the shared filesystem on completion. - Fix issues with concatenating files that fail to work with GATK's CatVariants. Fall back to bcftools concat which correctly handles problem headers and overlapping segments. - Enable flexible specification of `indelcaller` for `variantcaller` targets that do not have integrated indel methods. Thanks to Miika Ahdesmaki. - Move to samtools 1.0 release. Update samtools variant calling to support new multiallelic approach. - Improve Platypus integration: correctly pass multiple BAM files, make use of assembler, split MNPs, and correctly restrict to variant regions. - Be more aggressive with system memory usage to try and make better use of available resources. The hope is to take advantage of Java memory fixes that previously forced us to be conservative. ## 0.8.1 (August 29, 2014) - Support joint recalling with GATK HapolotypeCaller, FreeBayes and Platypus. The `jointcaller` configuration variable enables calling concurrently in large populations by independently calling on samples them combining into a final combined callset with no-call/reference calls at any position called independently. - Add qsignature tool to standard and variant analyses, which helps identify sample swaps. Add `mixup_check` configuration variant to enable. - Fix issue with merging GATK produced VCF files with vcfcat by swapping to GATK's CatVariants. Thanks to Matt De Both. - Initial support for ensemble calling on cancer tumor/normal calling. Now available for initial validation work. Thanks to Miika Ahdesmaki. - Enable structural variant analyses on shared batches (two tumors with same normal). Thanks to Miika Ahdesmaki. - Avoid Java out of memory errors for large numbers of running processes by avoiding Parallel GC collction. Thanks to Justin Johnson and Miika Ahdesmaki. - Enable streaming S3 input to RNA-seq and variant processing. BAM and fastq inputs can stream directly into alignment and trimming steps. - Speed improvements for re-running samples with large numbers of samples or regions. - Improved cluster cleanup by providing better error handling and removal of controllers and engines in additional failure cases. - Support variant calling for organisms without dbSNP files. Thanks to Mark Rose. - Support the SNAP aligner, which provides improved speed on systems with larger amount of memory (64Gb for human genome alignment). - Support the Platypus haplotype based variant caller for germline samples with both batched and joint calling. - Fix GATK version detection when `_JAVA_OPTIONS` specified. Thanks to Miika Ahdesmaki. - Use msgpack for ipython serialization to reduce message sizes and IPython controller memory instead of homemade json/zlib approach. ## 0.8.0 (July 28, 2014) - Change defaults for installation: do not use sudo default and require `--sudo` flag for installing system packages. No longer includes default genomes or aligners to enable more minimal installations. Users install genomes by specifically enumerating them on the command line. - Add support for Ensembl variant effects predictor (VEP). Enables annotation of variants with dbNSFP and LOFTEE. Thanks to Daniel MacArthur for VEP suggestion. - Support CADD annotations through new GEMINI database creation support. - Rework parallelization during variant calling to enable additional multicore parallelization for effects prediction with VEP and backfilling/squaring off with bcbio-variation-recall. - Rework calculation of callable regions to use bedtools/pybedtools thanks to groupby tricks from Aaron Quinlan. Improves speed and memory usage for coverage calculations. Use local temporary directories for pybedtools to avoid filling global temporary space. - Improve parallel region generation to avoid large numbers of segments on organisms with many chromosomes. - Initial support for tumor normal calling with VarDict. Thanks to Miika Ahdesmaki and Zhongwu Lai. - Provide optional support for compressing messages on large IPython jobs to reduce memory usage. Enable by adding `compress_msg` to `alogrithm` section of `bcbio_system.yaml`. There will be additional testing in future releases before making the default, and this may be replaced by new methods like transit (https://github.com/cognitect/transit-python). - Add de-duplication support back for pre-aligned input files. Thanks to Severine Catreux. - Generalize SGE support to handle additional system setups. Thanks to Karl Gutwin. - Add reference guided transcriptome assembly with Cufflinks along with functions to classify novel transcripts as protein coding or not as well as generally clean the Cufflinks assembly of low quality transcripts. - Developer: provide datadict.py with encapsulation functions for looking up and setting items in the data dictionary. - Unit tests fixed. Unit test data moved to external repository: https://github.com/roryk/bcbio-nextgen-test-data - Add exon-level counting with DEXseq. - Bugfix: Fix for Tophat setting the PI flag as inner-distance-size and not insert size. - Added kraken support for contamination detection (@lpatano): http://ccb.jhu.edu/software/kraken/ - Isoform-level FPKM combined output file generated (@klrl262) - Use shared conda repository for tricky to install Python packages: https://github.com/chapmanb/bcbio-conda - Added initial chanjo integration for coverage calculation (@kern3020): https://github.com/robinandeer/chanjo - Initial support for automated evaluation of structural variant calling. - Bugfix: set library-type properly for Cufflinks runs. - Added `genome_setup.py` a script to prepare your own genome and rnaseq files. ## 0.7.9 (May 19, 2014) - Redo Illumina sequencer integration to be up to date with current code base. Uses external bcl2fastq demultiplexing and new bcbio integrated analysis server. Provide documentation on setting up automated infrastructure. - Perform de-duplication of BAM files as part of streaming alignment process using samblaster or biobambam's bammarkduplicates. Removes need for secondary split of files and BAM preparation unless recalibration and realignment needed. Enables pre-processing of input files for structural variant detection. - Rework batched regional analysis in variant calling to remove custom cases and simplify structure. Filtering now happens explicitly on the combined batch file. This is functionally equivalent to previous filters but now the workflow is clearer. Avoids special cases for tumor/normal inputs. - Perform regional splitting of samples grouped by batch instead of globally, enabling multiple organisms and experiments within a single input sample YAML. - Add temporary directory usage to enable use of local high speed scratch disk on setups with large enough global temporary storage. - Update FreeBayes to latest version and provide improved filtering for high depth artifacts. - Update VQSR support for GATK to be up to date with latest best practices. Re-organize GATK and filtering to be more modular to help with transition to GATK 3.x gVCF approaches. - Support CRAM files as input to pipeline, including retrieval of reads from defined sequence regions. - Support export of alignment data as CRAM instead of BAM for space storage and long term archiving. - Provide configuration option, `remove_lcr`, to filter out variants in low complexity regions. - Improve Galaxy upload for LIMS supports: enable upload of FastQC as PDF reports with wkhtmltopdf installed. Provide tabular summaries of mapped reads. - Improve checks for pre-aligned BAMs: ensure correct sample names and provide more context on errors around mismatching reference genomes. - GATK HaplotypeCaller: ensure genotype depth annotation with DepthPerSampleHC annotation. Enable GATK 3.1 hardware specific optimizations. - Use bgzipped VCFs for dbSNP, Cosmic and other resources to save disk space. Upgrade to Cosmic v68. - Avoid VCF concatenation errors when first input file is empty. Thanks to Jiantao Shi. - Added preliminary support for oncofuse for calling gene fusion events. Thanks to @tanglingfung. ## 0.7.8 (March 21, 2014) - Add a check for mis-specified FASTQ format in the sample YAML file. Thanks to Alla Bushoy. - Updated RNA-seq integration tests to have more specific tags (singleend, Tophat, STAR, explant). - Fix contig ordering after Tophat alignment which was preventing GATK-based tools from running. - Allow calculation of RPKM on more deeply sampled genes by setting `--max-bundle-frags` to 2,000,000. Thanks to Miika Ahdesmaki. - Provide cleaner installation process for non-distributable tools like GATK. The `--tooplus` argument now handles jars from the GATK site or Appistry and correctly updates manifest version information. - Use bgzipped/tabix indexed variant files throughout pipeline instead of raw uncompressed VCFs. Reduces space requirements and enables parallelization on non-shared filesystems or temporary space by avoiding transferring uncompressed outputs. - Reduce memory usage during post-alignment BAM preparation steps (PrintReads downsampling, deduplication and realignment prep) to avoid reaching memory cap on limited systems like SLURM. Do not include for IndelRealigner which needs memory in high depth regions. - Provide explicit targets for coverage depth (`coverage_depth_max` and `coverage_depth_min`) instead of `coverage_depth` enumeration. Provide downsampling of reads to max depth during post-alignment preparation to avoid repetitive centromere regions with high depth. - Ensure read group information correctly supplied with bwa aln. Thanks to Miika Ahdesmaki. - Fix bug in retrieval of snpEff databases on install. Thanks to Matan Hofree. - Fix bug in normal BAM preparation for tumor/normal variant calling. Thanks to Miika Ahdesmaki. - General removal of GATK for variant manipulation functionality to help focus on support for upcoming GATK 3.0. Use bcftools for splitting of variants into SNPs and indels instead of GATK. Use vcflib's vcfintersection to combine SNPs and indels instead of GATK. Use bcftools for sample selection from multi-sample VCFs. Use pysam for calculation of sample coverage. - Use GATK 3.0 MIT licensed framework for remaining BAM and variant manipulation code (PrintReads, CombineVariants) to provide one consistent up to date set of functionality for GATK variant manipulation. - Normalize input variant_regions BED files to avoid overlapping segments. Avoids out of order errors with FreeBayes caller which will call in each region without flattening the input BED. ## 0.7.7 (February 27, 2014) - For cancer tumor/normal calling, attach final call information of both to the tumor sample. This provides a single downstream file for processing and analysis. - Enable batch specification in metadata to be a list, allowing a single normal BAM file to serve as a control for multiple tumor files. - Re-organization of parallel framework code to enable alternative approaches. Document plugging in new parallel frameworks. Does not expose changes to users but makes the code cleaner for developers. - Default to 1Gb/core memory usage when not specified in any programs. Do not use default baseline if supplied in input file. Thanks to James Porter. - Integrate plotting of variant evaluation results using prettyplotlib. - Add `globals` option to configuration to avoid needing to specify the same shared file multiple times in a samples configuration. - Remove deprecated Celery distributed messaging, replaced in favor of IPython. - Remove algorithm/custom_algorithm from bcbio_system.yaml, preferring to set these directly in the sample YAML files. - Remove outdated and unused custom B-run trimming. - Remove ability to guess fastq files from directories with no specification in sample YAML. Prefer using generalized template functionality with explicit specification of files in sample YAML file. - Remove deprecated multiplex support, which is outdated and not maintained. Prefer approaches in external tools upstream of bcbio-nextgen. - Add `--tag` argument which labels job names on a cluster to help distinguish when multiple bcbio jobs run concurrently. Thanks to Jason Corneveaux. - Connect min_read_length parameter with read_through trimming in RNA-seq. Thanks to James Porter. - Map `variant` calling specification to `variant2` since original approach no longer supported. - Fix issues with trying to upload directories to Galaxy. Thanks to Jim Peden. - Made inner distance calculation for Tophat more accurate. - Added gffutils GFF database to the RNA-seq indices. - Add gene name annotation from the GFF file instead of from mygene. ## 0.7.6 (January 15, 2014) - Expand template functionality to provide additional ability to add metadata to samples with input CSV. Includes customization of algorithm section and better matching of samples using input file names. Improve ability to distinguish fastq pairs. - Generalize snpEff database preparation to use individual databases located with each genome. Enables better multi-organism support. - Enable tumor/normal paired called with FreeBayes. Contributed by Luca Beltrame. - Provide additional parallelization of bgzip preparation, performing grabix indexing in parallel for paired ends. - Fix downsampling with GATK-lite 2.3.9 releases by moving to sambamba based downsampling. Thanks to Przemek Lyszkiewicz. - Handle Illumina format input files for bwa-mem alignment, and cleanly convert these when preparing bgzipped inputs for parallel alignment. Thanks to Miika Ahdesmaki. - Provide better algorithm for distinguishing bwa-mem and bwa-aln usage. Now does random sampling of first 2 million reads instead of taking the first set of reads which may be non-generalizable. Also lowers requirement to use bwa-mem to 75% of reads being smaller than 70bp. Thanks to Paul Tang. - Enable specification of a GATK key file in the bcbio_system resources `keyfile` parameter. Disables callbacks to GATK tracking. Thanks to Severine Catreux for keyfile to debug with. - Correctly handle preparation of pre-aligned BAM files when sorting and coordinate specification needed. Thanks to Severine Catreux. - Fix incorrect quality flag being passed to Tophat. Thanks to Miika Ahdesmaki. - Fix Tophat not respecting the existing --transcriptome-index. Thanks to Miika Ahdesmaki. - Keep original gzipped fastq files. Thanks again to Miika Ahdesmaki. - Fixed incompatibility with complexity calculation and IPython. - Added strand-specific RNA-seq support via the strandedness option. - Added Cufflinks support. - Set stranded flag properly in htseq-count. Thanks to Miika Ahdesmaki. - Fix to ensure Tophat receives a minimum of 8 gb of memory, regardless of number of cores. - Remove `hybrid_bait` and `hybrid_target` which were no longer used with new lightweight QC framework. Prefer better coverage framework moving forward. - Added extra summary information to the project-summary.yaml file so downstream tools can locate what genome resources were used. - Added ``test_run`` option to the sample configuration file. Set it to True to run a small subset of your data through the pipeline to make sure everything is working okay. - Fusion support added by setting ``fusion_mode: True`` in the algorithim section. Not officially documented for now until we can come up with best practices for it. - STAR support re-enabled. - Fixed issue with the complexity calculation throwing an exception when there were not enough reads. - Add disambiguation stats to final project-summary.yaml file. Thanks to Miika Ahdesmaki. - Remove `Estimated Library Size` and `Complexity` from RNA-seq QC summary information as they were confusing and unnecessarily alarming, respectively. Thanks to Miika Ahdesmaki and Sara Dempster. - Several memory allocation errors resulting in jobs getting killed in cluster environments for overusing their memory limit fixed. - Added JVM options by default to Picard to allocate enough memory for large BAM->FastQ conversion. ## 0.7.5 (November 29, 2013) - Update overall project metrics summary to move to a flexible YAML format that handles multiple analysis types. Re-include target, duplication and variant metrics. - Support disambiguation of mixed samples for RNA-seq pipelines. Handles alignment to two genomes, running disambiguation and continuation of disambiguated samples through the pipeline. Contributed by Miika Ahdesmaki and AstraZenenca. - Handle specification of sex in metadata and correctly call X,Y and mitochondrial chromosomes. - Fix issues with open file handles for large population runs. Ensure ZeroMQ contexts are closed and enable extension of ulimit soft file and user process limits within user available hard limits. - Avoid calling in regions with excessively deep coverage. Reduces variant calling bottlenecks in repetitive regions with 25,000 or more reads. - Improve `bcbio_nextgen.py upgrade` function to be more consistent on handling of code, tools and data. Now each require an implicit specification, while other options are remembered. Thanks to Jakub Nowacki. - Generalize retrieval of RNA-seq resources (GTF files, transcriptome indexes) to use genome-resources.yaml. Updates all genome resources files. Contributed by James Porter. - Use sambamba for indexing, which allows multicore indexing to speed up index creation on large BAM processing. Falls back to samtools index if not available. - Remove custom Picard metrics runs and pdf generation. Eliminates dependencies on pdflatex and R for QC metrics. - Improve memory handling by providing fallbacks during common memory intensive steps. Better handle memory on SLURM by explicitly allowing system memory in addition to that required for processing. - Update fastqc runs to use a BAM files downsampled to 10 million reads to avoid excessive run times. Part of general speed up of QC step. - Add Qualimap to generate plots and metrics for BAM alignments. Off by default due to speed issues. - Improve handling of GATK version detection, including support for Appistry versions. - Allow interruption of read_through trimming with Ctrl-C. - Improve test suite: use system configuration instead of requiring test specific setup. Install and use a local version of nose using the installer provided Python. - Fix for crash with single-end reads in read_through trimming. - Added a library complexity calculation for RNA-seq libraries as a QC metric - Added sorting via sambamba. Internally bcbio-nextgen now inspects the headers of SAM/BAM files to find their sorting status, so make sure tools set it correctly. ## 0.7.4 (October 20, 2013) - Framework for indexing input reads using parallel bgzip and grabix, to handle distributed alignment. Enables further distribution of alignment step beyond multicore nodes. - Rework of ensemble calling approach to generalize to population level ensemble calls. Provide improved defaults for handle 3 caller consolidation. - Support for Mouse (mm10) variant calling and RNA-seq. - For recent versions of Gemini (0.6.3+) do not load filtered variants into database, only including passed variants. - Improve specification of resource parameters, using multiple `-r` flags instead of single semi-colon separated input. Allow specification of pename resource parameter for selecting correct SGE environment when not automatically found. - Support biobambam's bammarkduplicates2 for duplicate removal. - Clean up logging handling code to be more resilient to interrupt messages. - Speed improvements for selecting unanalyzed and unmapped reads to address bottlenecks during BAM prep phase. - Bug fix for algorithm options incorrectly expanded to paths on re-runs. Thanks to Brent Pedersen for report. - Fix for Tophat 2.0.9 support: remove reads with empty read names. - Save installation and upgrade details to enable cleaner upgrades without needing to respecify genomes, tool directory and other options from installation. ## 0.7.3 (September 22, 2013) - Move specification of supporting genome files for variation (dbSNP, training files) and RNA-seq (transcript GTF files) analyses into an organism specific resources file. Improves ability to support additional organisms and genome builds. - Provide paired tumor/normal variant calling with VarScan. Thanks to Luca Beltrame. - Require bash shell and use of pipefail for piped commands. Ensures rapid detection of failures during piped steps like alignment. - Use samtools cat for post-BAM merging to avoid issues with bamtools requirement for open file handles. - Add installation/upgrade options to enable commercially restricted and data intensive third party tools. - Support for GATK 2.7 - Fixes for TopHat 2.0.9 support: remove extra non-mate match paired end reads from alignment output. - Pull `description` sample names from BAM files if not present in input configuration file. Thanks to Paul Tang for suggestion. - Bug fixes for non-paired RNA-seq analysis. - Add custom filtration of FreeBayes samples using bcbio.variation. - Default to phred33 format for Tophat alignment if none specified. ## 0.7.2 (August 30, 2013) - Report memory usage for processes to cluster schedulers and use predicted memory usage to schedule cores per machine. Gets core and memory information for machines and uses to ensure submitted jobs can schedule with available resources. - Provide error checking of input YAML configuration at run start. Avoids accidental typos or incorrect settings that won't error out until later in the process. - Drop requirement for fc_name and fc_date in input YAML file. Individual sample names are instead used and required to be unique within a processing run. - Remove original `variant` pipeline, replacing with the all around better `variant2` analysis method. Plan for the next version is to automatically redirect to `variant2`. - Improve parallelization of BAM preparation and gemini database creation by moving to multicore versions. - Move variant annotation to work on called sub-regions, to avoid bottlenecks when annotating a full whole genome VCF. - Remove sequencer-specific integration functionality which is poorly maintained and better done with third party tools: demultiplexing and statistics from Illumina directories. - Bug fix to re-enable template generation functionality. - Improve BAM merging on large files using samtools for output sort. - Uploading results works with the RNA-seq pipeline. - Rework internals to provide a consistent dictionary of sample attributes up front, avoiding lane/sample dichotomy which provided confusing internal code. - Drop calling htseq-count from the command line in favor of an internal implementation. ## 0.7.1 (August 12, 2013) - Remove requirement for bcbio_system.yaml passed in on command line, defaulting to default file prepared by installer unless specified. - Bug fixes for new approach to parsing *.loc files: handle Galaxy *.loc files with mixed tabs and spaces correctly and fall back to previous approaches when aligner specific *.loc files are missing. - Bug fixes for preparing merged BAM files using bamtools: correctly sort after merging and avoid duplication of reads in noanalysis files. - Bug fix for concatenating files when first file in empty. - Recover from ZeroMQ logging errors, avoiding loss of logging output. ## 0.7.0 (July 30, 2013) - RNA-seq pipeline updated: deprecate Tophat 1 in favor of Tophat 2. Perform automatic adapter trimming of common adapter sequences. STAR aligner support. RNA-SeQC support for RNA-seq specific quality control. Transcript quantitation with htseq-count. - Updated installation and upgrade procedures, to make it easier to build an initial analysis pipeline and upgrade bcbio-nextgen and third-parts tools and data in place. - Add support for MuTect tumor/normal variant caller, contributed by Luca Beltrame. - Generalize variant calling to support alternative callers like cancer-specific calling: provide additional associated files to variant calls and pass along sample specific metadata. Document implementation of new variant callers. - Improve algorithms around post-variant calling preparation. Avoid unnecessary tries for VQSR on low coverage whole genome reads, and concatenate VCF files to avoid locking penalties. - Fix logging and memory usage for multicore jobs run within ipython clusters. - Improve logging for IPython cluster issues, including moving IPython logs inside project logging directory for better access. - Options for improved cluster resiliency: minimize number of clusters started during processing with more extensive reuse, flexible timeouts for waiting on cluster start up, and expose options to allow job retries. Thanks to Zhengqiu Cai for suggestions and testing. ## 0.6.5 (June 07, 2013) - Improve logging: Detailed debugging logs collect all process standard out and error and command lines across distributed systems. - Piping improvements: provide fully piped analysis with GATK recalibration and gkno realignment. Handle smaller reads with novoalign piped analysis. - Improve collapsing analysis regions into evenly sized blocks to better handle large numbers of samples analyzed together. - Provide template functionality to ease generation of input sample.yaml files from lists of BAM of fastq files. Thanks to Brent Pedersen and Paul Tang. - Updated program support: Improved novoalign support based on evaluation with reference genomes. Support GATK 2.5-2. Support VarScan 2.3.5. - Fix naming of read group information (ID and SM) to be more robust. Identifies issues with duplicated read groups up front to avoid downstream errors during variant calling. Thanks to Zhengqiu Cai. - Improve quality control metrics: Cleanup into custom qc directory and ensure correct selection of duplicate and other metrics for split post-alignment prep, even without merging. - Fix IPython parallel usage for larger clusters, providing improved resiliency for long running jobs. - Clean up handling of missing programs and input files with better error messages. From Brent Pedersen. ## 0.6.4 (May 06, 2013) - Integrate fully with bcbio.variation to provide automated validation of variant calls against reference materials. - Provide full list of all third party software versions used in analysis. - Create GEMINI database as part of output process, allowing immediate queries of variants with associated population and annotation data. - Collapse analysis regions into evenly sized blocks separated by non-callable regions. Provides better parallelism. - Documentation and examples for NA12878 exome and whole genome pipelines. bcbio-nextgen-1.2.9/LICENSE.txt000066400000000000000000000020631415626112400160750ustar00rootroot00000000000000Copyright (c) 2013-2021 bcbio-nextgen contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. bcbio-nextgen-1.2.9/MANIFEST.in000066400000000000000000000006441415626112400160130ustar00rootroot00000000000000include *.txt include *.md include bcbio/data/umis/*.txt.gz include bcbio/data/umis/*.json include config/*.yaml include config/*.ini include tests/*.py include tests/data/*.csv include tests/data/automated/*.yaml include tests/data/automated/*.ini include tests/data/automated/tool-data/*.loc include tests/data/variants/*.vcf include tests/data/variants/*.tbi include bcbio/scripts/R/*.R include bcbio/scripts/R/*.Rmd bcbio-nextgen-1.2.9/README.md000066400000000000000000000161201415626112400155300ustar00rootroot00000000000000![bcbio banner](https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/docs/contents/images/banner.png) Validated, scalable, community developed variant calling, RNA-seq and small RNA analysis. You write a high level configuration file specifying your inputs and analysis parameters. This input drives a parallel run that handles distributed execution, idempotent processing restarts and safe transactional steps. bcbio provides a shared community resource that handles the data processing component of sequencing analysis, providing researchers with more time to focus on the downstream biology. [![Build Status](https://travis-ci.org/bcbio/bcbio-nextgen.svg?branch=master)](https://travis-ci.org/bcbio/bcbio-nextgen) [![Documentation status](https://readthedocs.org/projects/bcbio-nextgen/badge/?version=latest)](https://bcbio-nextgen.readthedocs.io/en/latest/?badge=latest) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3564938.svg)](https://doi.org/10.5281/zenodo.3564938) ## Features * Community developed: We welcome contributors with the goal of overcoming the biological, algorithmic and computational challenges that face individual developers working on complex pipelines in quickly changing research areas. See our [users page](https://bcbio-nextgen.readthedocs.io/en/latest/contents/users.html) for examples of bcbio-nextgen deployments, and the [developer documentation](https://bcbio-nextgen.readthedocs.io/en/latest/contents/development.html) for tips on contributing. * Installation: [A single installer script](https://bcbio-nextgen.readthedocs.io/en/latest/contents/installation.html#automated) prepares all third party software, data libraries and system configuration files. * [Automated validation](https://bcb.io/2014/05/12/wgs-trio-variant-evaluation/): Compare variant calls against common reference materials or sample specific SNP arrays to ensure call correctness. Incorporation of multiple approaches for alignment, preparation and variant calling enable unbiased comparisons of algorithms. * Distributed: Focus on [parallel analysis and scaling](https://bcb.io/2013/05/22/scaling-variant-detection-pipelines-for-whole-genome-sequencing-analysis/) to handle large population studies and whole genome analysis. Runs on single multicore computers, in compute clusters using [IPython parallel](https://ipyparallel.readthedocs.io/en/latest/), or on the Amazon cloud. See the [parallel documentation](https://bcbio-nextgen.readthedocs.org/en/latest/contents/parallel.html) for full details. * Multiple analysis algorithms: bcbio-nextgen provides configurable [variant calling (small and copy number), RNA-seq, ATAC-seq, , BS-Seq, SC RNA-seq, and small RNA pipelines](https://bcbio-nextgen.readthedocs.io/en/latest/). ## Quick start 1. [Install](https://bcbio-nextgen.readthedocs.io/en/latest/contents/installation.html#automated) `bcbio-nextgen` with all tool dependencies and data files: ```shell script wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/scripts/bcbio_nextgen_install.py python bcbio_nextgen_install.py /usr/local/share/bcbio --tooldir=/usr/local \ --genomes hg38 --aligners bwa --aligners bowtie2 ``` producing an editable [system configuration file](https://github.com/bcbio/bcbio-nextgen/blob/master/config/bcbio_system.yaml) referencing the installed software, data and system information. 1. [Automatically create a processing description](https://bcbio-nextgen.readthedocs.io/en/latest/contents/configuration.html#automated-sample-configuration) of sample FASTQ and BAM files from your project, and a CSV file of sample metadata: ```shell script bcbio_nextgen.py -w template freebayes-variant project1.csv sample1.bam sample2_1.fq sample2_2.fq ``` This produces a [sample description file](https://github.com/bcbio/bcbio-nextgen/blob/master/config/bcbio_sample.yaml) containing pipeline [configuration options](https://bcbio-nextgen.readthedocs.io/en/latest/contents/configuration.html). 1. Run analysis, distributed across 8 local cores: ```shell script cd project1/work bcbio_nextgen.py ../config/project1.yaml -n 8 ``` ## Documentation See the [full documentation](https://bcbio-nextgen.readthedocs.io/en/latest/) and [longer analysis-based articles](https://bcb.io). We welcome enhancements or problem reports using [GitHub](https://github.com/bcbio/bcbio-nextgen/issues) and discussion on the [biovalidation mailing list](https://groups.google.com/d/forum/biovalidation). ## Contributors * [Miika Ahdesmaki](https://github.com/mjafin), AstraZeneca * [Luca Beltrame](https://github.com/lbeltrame), IRCCS "Mario Negri" Institute for Pharmacological Research, Milan, Italy * [Christian Brueffer](https://github.com/cbrueffer), Lund University, Lund, Sweden * [Alla Bushoy](https://github.com/abushoy), AstraZeneca * [Guillermo Carrasco](https://github.com/guillermo-carrasco), Science for Life Laboratory, Stockholm * [Nick Carriero](https://www.simonsfoundation.org/team/nick-carriero/), Simons Foundation * [Brad Chapman](https://github.com/chapmanb), Harvard Chan Bioinformatics Core * [Saket Choudhary](https://github.com/saketkc), University Of Southern California * [Peter Cock](https://github.com/peterjc), The James Hutton Institute * [Matthias De Smet](https://github.com/matthdsm), Center for Medical Genetics, Ghent University Hospital, Belgium * [Matt Edwards](https://github.com/matted), MIT * [Mario Giovacchini](https://github.com/mariogiov), Science for Life Laboratory, Stockholm * [Karl Gutwin](https://twitter.com/kgutwin), Biogen * [Jeff Hammerbacher](https://github.com/hammer), Icahn School of Medicine at Mount Sinai * [Oliver Hofmann](https://umccr.github.io/), University of Melbourne Centre for Cancer Research * [John Kern](https://github.com/kern3020) * [Rory Kirchner](https://github.com/roryk), Harvard Chan Bioinformatics Core * [Tetiana Khotiainsteva](https://github.com/tetianakh), Ardigen * [Kerrin Mendler](https://github.com/kmendler), AstraZeneca * [Sergey Naumenko](https://github.com/naumenko-sa), Harvard Chan Bioinformatics Core * [Jakub Nowacki](https://github.com/jsnowacki), AstraZeneca * [John Morrissey](https://github.com/jwm), Harvard Chan Bioinformatics Core * [Lorena Pantano](https://github.com/lpantano), Harvard Chan Bioinformatics Core * [Brent Pedersen](https://github.com/brentp), University of Colorado Denver * [James Porter](https://github.com/porterjamesj), The University of Chicago * [Vlad Saveliev](https://github.com/vladsaveliev), Center for Algorithmic Biotechnology, St. Petersburg University * [Valentine Svensson](https://github.com/vals), Science for Life Laboratory, Stockholm * [Paul Tang](https://github.com/tanglingfung), UCSF * [Stephen Turner](https://github.com/stephenturner), University of Virginia * [Roman Valls](https://github.com/brainstorm), Science for Life Laboratory, Stockholm * [Kevin Ying](https://github.com/kevyin), Garvan Institute of Medical Research, Sydney, Australia * [Steffen Möller](https://github.com/smoe), University of Rostock, Germany * [WimSpee](https://github.com/wimspee) ## License The code is freely available under the [MIT license](https://opensource.org/licenses/mit-license.html). bcbio-nextgen-1.2.9/Vagrantfile000066400000000000000000000013521415626112400164370ustar00rootroot00000000000000# -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.hostname = "bcbio" config.vm.provider :virtualbox do |vb| vb.memory = 4096 vb.cpus = 2 end # to make any additional data on the host available inside the VM # (for example: reference genomes, pipeline inputs, etc) # set BCBIO_DATA_DIR environment variable on the host to a directory that contains the data if ENV["BCBIO_DATA_DIR"] config.vm.synced_folder ENV["BCBIO_DATA_DIR"], "/data" end config.vm.provision :shell, :path => "scripts/vagrant.sh" end bcbio-nextgen-1.2.9/artwork/000077500000000000000000000000001415626112400157425ustar00rootroot00000000000000bcbio-nextgen-1.2.9/artwork/bcbio-nextgen.sketch000066400000000000000000007200001415626112400216700ustar00rootroot00000000000000SQLite format 3 @  - mmFetablepayloadpayloadCREATE TABLE payload (name text, value blob)IgtablemetadatametadataCREATE TABLE metadata (name text, value blob) HGEvariant streamtyped@NSStringNSObject+APPSTOREMversion streamtyped@NSNumberNSValueNSObject*q7Mbuild streamtyped@NSNumberNSValueNSObject*q.S$app streamtyped@NSStringNSObject+com.bohemiancoding.sketch3[0fonts streamtyped@NSArrayNSObjectiNSString+ Roboto-MediumPlength streamtyped@NSNumberNSValueNSObject*qMd@commit streamtyped@NSStringNSObject+(a4be2586610959109f5c934980f53be1a6a00efc !UZ]_bdkltw{ #$*23;<DEKLXYcw|,1469;BCDHKQejmort{ '(.15:=AGJNafiknpw{~ #%,03=FGHIQRST\]^_ghijkst +0358:AEH&/012:;<=EFGHPQRS[\]^fghiqrst|}~  "#$%-./089:;CDEFNOPQYZ[\defgopqrz{|}       ! " * + , - 5 6 7 8 @ A B C K L M N V W X Y a b c d l m n o w x y z            ' ( ) * 2 3 4 5 = > ? @ H I J K S T U V ^ _ ` a i j k l t u v w              $ % & ' / 0 1 2 : ; < = E F G H P Q R S [ \ ] ^ f g h i q r s t | } ~       ! $ ( . 1 5 F K N P S U \ ` c             % & ' ( ) * + , - 5 = @ C E O R V u z }   "*+0789<FY^acfhot{|} %&/09:CDEFZ_bdgipw~!(-4569?SX[]`bipwxy| ")0789<@FGJNTW[nsvx{} %*-/24;?BLTUVW_`abjklmuvwxyz&+.035<@C!)*+,4567?@ABJKLMUVWX`abcklmnvwxy&'()1234<=>?GHIJRSTU]^_`hijkstuv~ #$%&./019:;<DEFGOPQRZ[\]efghpqrs{|}~     !"#+,-.6789ABCDLMNOWXYZbcdemnopxyz{   ()*+3456>?@AIJKLTUVW_`abjklmuvwx #&*;@CEHJQUXx !<ADFIKSTUY]ghoswz{ "#$)*238;?EHL_dgilnvw| ).1368?CFPX`hpqr 27:<?AHLOUinqsvx"$+148=@DJMQdilnqsz~!$&-14>FGHIQRST\]^_ghijkl      ! # * . 1!!!!!!"!#!$!%!-!.!/!0!8!9!:!;!C!D!E!F!N!O!P!Q!Y!Z![!\!d!e!f!g!o!p!q!r!z!{!|!}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""" " " " """""" "!"""*"+","-"5"6"7"8"@"A"B"C"K"L"M"N"V"W"X"Y"a"b"c"d"l"m"n"o"w"x"y"z""""""""""""""""""""""""""""""""""""""""""""""""#### #########'#(#)#*#2#3#4#5#=#>#?#@#H#I#J#K#S#T#U#V#^#_#`#a#i#j#k#l#t#u#v#w################################################$$$$$$$$$$$$$$$%$&$'$/$0$1$2$:$;$<$=$E$F$G$H$P$Q$R$S$[$\$]$^$f$g$h$i$q$r$s$t$|$}$~$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%%%%% % % %%%%%%!%"%#%$%,%-%.%/%7%8%9%:%B%C%D%E%M%N%O%P%X%Y%Z%[%c%d%e%f%n%o%p%q%y%z%{%|%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&&&& &&&&'&,&/&1&4&6&=&A&D&d&l&m&n&o&w&x&y&z&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'''' ' ' ' '''''' '"'#'='B'E'G'J'L'T'U'V'['^'b'h'k'q'''''''''''''''''''''''(((( ( (((( (%(((,(2(5(9(L(Q(T(V(Y([(b(f(i(s({((((((((((((((((((((((()))))))))')/)7)?)@)A)B)U)Z)])_)b)d)k)o)r)x)))))))))))))))))))))))))** ***"*#*$*8*=*@*B*E*G*N*T*W*[*`*c*g*m*p*t************************+++ + +++++"+%+)+:+?+B+D+G+I+P+T+W+a+i+j+k+l+t+u+v+w+++++++++++++++++++++++++++++++,, ,,,,,,",&,7,<,?,A,D,F,M,Q,T-2-:-;-<-=-E-F-G-H-P-Q-R-S-[-\-]-^-f-g-h-i-q-r-s-t-|-}-~---------------------------------------------..... . . ......!.".#.$.,.-.../.7.8.9.:.B.C.D.E.M.N.O.P.X.Y.Z.[.c.d.e.f.n.o.p.q.y.z.{.|.............................................../// / / /////// /!/)/*/+/,/4/5/6/7/?/@/A/B/J/K/L/M/U/V/W/X/`/a/b/c/k/l/m/n/v/w/x/y////////////////////////////////////////////////0000000000000&0'0(0)010203040<0=0>0?0G0H0I0J0R0S0T0U0]0^0_0`0h0i0j0k0s0t0u0v0~0000000000000000000000000000000000000000000000011111 11111111#1$1%1&1.1/1011191:1;1<1D1E1F1G1O1P1Q1R1Z1[1\1]1e1f1g1h1p1q1r1s1{1|1}1~111111111111111111111111111111111111111111222 2 22222$2%2(2,2225292J2O2R2T2W2Y2`2d2g22222222222222222222222222222222222222222222333 3 3 3333333 3!3)3*3+3,3-3.3/3D3I3L3N3Q3S3[3\3]3a3dx3o3s3t3w3|333333333333333333333U$null Vassets_currentPageIndex[layerStylesUpages[do_objectID_enableSliceInteractionV$class_layerTextStyles_enableLayerInteraction\layerSymbolsT 7 8P  !"#$%&YgradientsVcolors_imageCollectionVimages ()*Xarray_do,./01Z$classnameX$classes^NSMutableArray023WNSArrayXNSObject./56WMSArray573]MSModelObject(9*,!>? A ./CD_NSMutableDictionaryCE3\NSDictionary./GH_MSImageCollectionIJK3_MSImageCollection__MSImageCollection]MSModelObject(M*,./RS_MSAssetCollectionTUV3_MSAssetCollection__MSAssetCollection]MSModelObjectXYZWobjects(\*,./ab_MSSharedLayerStyleContainercdefg3_MSSharedLayerStyleContainer__MSSharedLayerStyleContainer_MSSharedObjectContainer__MSSharedObjectContainer]MSModelObjectXijO(l*o,q[NS.object.0st uvwxyzYinstancesUvalueTnameLN(|*,[NS.object.1[NS.object.0_$18E54ECB-62C2-44F3-A4C4-60A5EE1B31B9_$CEB9C525-6DEA-4E67-897E-1D43819128B3Tlogo uxy_shouldBreakMaskChainUstyleXrotationVlayers]exportOptionsUframe_isFlippedVerticalYisVisible_originalObjectID_hasClickThrough^sharedObjectID_isFlippedHorizontalXisLocked_layerListExpandedType[nameIsFixedXuserInfo&#+$ L MUsizes_includedLayerIds\layerOptionsZshouldTrim!#(* ,(*",./_MSExportOptions3_MSExportOptions__MSExportOptions]MSModelObjectQy_constrainProportionsUwidthVheightQx#%#@`#@Y#./VMSRect3W_MSRect]MSModelObject_startDecorationType_endDecorationTypeTblurYtextStyleZmiterLimit*' Vradius[motionAngleYisEnabledTtypeVcenter#@>Ā)#(Z{0.5, 0.5}./[MSStyleBlur3[MSStyleBlur\_MSStyleBlur[MSStylePart\_MSStylePart]MSModelObject./WMSStyle3X_MSStyle]MSModelObject(*,,[NS.object.1[NS.object.0[NS.object.3[NS.object.2-  u    6#7.3 5 41/#(*0,($*2,),-.#@=qq%#@<#@D#Tpipe_$6111096D-FFEE-4D95-AC02-D053B5F88598*(6*89:;,=[NS.object.1[NS.object.0j9? @AuDEFHIJMP[windingRule_clippingMaskMode_hasClippingMaskA#?:hiO @VW=;#([*<,(`*>,ehij#%#@$#@D#[Rectangle 1mnorWbordersUfillsB*I(uvCHx,z[NS.object.0D|}~YthicknessXfillTypeXpositionUcolor#?GESredUalphaTblueUgreenF#?l#?#?l#?l./WMSColor3X_MSColor]MSModelObject./]MSStyleBorder3]MSStyleBorder^_MSStyleBorder_MSStyleBasicFill__MSStyleBasicFill[MSStylePart\_MSStylePart]MSModelObject./_MSBorderStyleCollection53_MSBorderStyleCollection_MSStylePartCollection]MSModelObject(JN,[NS.object.0K}_patternTileScale^noiseIntensity_patternFillTypeZnoiseIndexML#?# F#?p#?#?ssssss#?./[MSStyleFill3[MSStyleFill\_MSStyleFill_MSStyleBasicFill__MSStyleBasicFill[MSStylePart\_MSStylePart]MSModelObject./_MSFillStyleCollection53_MSFillStyleCollection_MSStylePartCollection]MSModelObject(*P,[NS.object.0Q u_hasConvertedToNewRoundCornersVeditedTpath[fixedRadius_booleanOperation #WfRgYX #@US#(*T,(*V,#%#@$#@D#TPathVpointsXisClosedZ e(*[   ,[NS.object.1[NS.object.0[NS.object.3[NS.object.2_\ca \hasCurveFromYcurveModeUpointYcurveFrom\cornerRadiusWcurveToZhasCurveTo^]]#@]V{0, 0}./%&\MSCurvePoint'()3\MSCurvePoint]_MSCurvePoint]MSModelObject--/-^``#@`V{1, 0}6686^bb#@bV{1, 1}??A?^dd#@dV{0, 1}./FG[MSShapePathHIJ3[MSShapePath\_MSShapePath]MSModelObject_$6209FEC6-2AEB-4275-A1C8-7A1340C52B65./MN_MSRectangleShapeOPQRSTUVW3_MSRectangleShape__MSRectangleShape_MSCustomShapeLayer__MSCustomShapeLayer_MSShapePathLayer__MSShapePathLayerWMSLayerX_MSLayer]MSModelObject_$F8770DD6-2EE6-4813-AF32-DDE472239EB4./Z[\MSShapeGroup\]^_`aUVb3\MSShapeGroup]_MSShapeGroup\MSLayerGroup]_MSLayerGroup]MSStyledLayer^_MSStyledLayer]MSModelObject? @AufghjkJorr#pkiy qxynl#(}*m,(*o,#@%#@7#@>#@[Rectangle 2mn߀s*v(vtH,[NS.object.0u|}~#?GE(wN,[NS.object.0x}ML#?# (*z,[NS.object.0{ u #|gX #}#(*~,(*,#%#@7#@># e(*,[NS.object.1[NS.object.0[NS.object.3[NS.object.2^]]#]---^``#`666^bb#b?? ?^dd#d_$BBA11151-7DA0-4F94-A8A2-26747FBAFD41_$82FDB437-4B37-4F41-8B12-18B39EB19059_$FD8DD8AD-9E9D-4270-86A6-6F8BD5462A6D./\MSLayerGroupUV3\MSLayerGroup]_MSLayerGroup]MSStyledLayer^_MSStyledLayer]MSModelObject u")*#   ڀ-.#(2*,(7*,<?@A#@=%#@<#@D#@Z\pipe-flipped_$639AE563-C6A2-4C99-9D97-80356F357D33*(I*LMN,P[NS.object.1[NS.object.0? @AuTUVXYJ]P#i @fg#(k*,(p*,uxyz#%#@$#@D#mn|߀*(vH,[NS.object.0|}~#?GE(N,[NS.object.0}ML#?# (*,[NS.object.0 u #gX #@#(*,(*,#%#@$#@D# e(*,[NS.object.1[NS.object.0[NS.object.3[NS.object.2^]]#@]---^``#@`666^bb#@b???^dd#@d_$3AA5726E-3B48-48AE-B209-7E1A721794E5_$39D16AF1-84C7-4ACF-95A7-27057BBDB5B9? @AuJ  #ـi #(*,(*,!$%&#@%#@7#@>#@[Rectangle 2mn),߀€*ŀ(/vÀH2,4[NS.object.0|}~6#?GE(;ƀN>,@[NS.object.0}DEML#?# (H*ɀK,M[NS.object.0 uRSTUX` #Ѐ؀gX #bc΀̀#(g*̀,(l*π,qtuv#%#@7#@>#x e(|*Ӏ,[NS.object.1[NS.object.0[NS.object.3[NS.object.2ՀԀ׀^]]#]---^``#`666^bb#b???^dd#d_$EBDB9697-50FD-4902-8FA5-3907EB290589_$CF73F61F-B7E2-4393-AE7C-1575AF73D1EA_$E71CC1E4-816B-420A-BE78-D1F729262C9F? @AuJ#܁ i ߀݀#(*ހ,(*,#% #@Y#@X#@0VOval 3_$F45470EE-9918-4113-A156-F926F2A15A1Fmn߀*#@>Ā)#Z{0.5, 0.5}(vH,[NS.object.0|}~#?`qPGE(N,[NS.object.0}ML#?# (*,[NS.object.0 u #   X#(*,(!*,&)*+#%#@Y#@X#- e(1*4567,9:;<[NS.object.1[NS.object.0[NS.object.3[NS.object.2?ABCD ^# _{0.77614237490000004, 1}_{0.22385762510000001, 1}X{0.5, 1}?LMNO ^# _{1, 0.22385762510000001}_{1, 0.77614237490000004}X{1, 0.5}?WXYZ ^# _{0.22385762510000001, 0}_{0.77614237490000004, 0}X{0.5, 0}?bcde ^# _{0, 0.77614237490000004}_{0, 0.22385762510000001}X{0, 0.5}_$A936FD17-DD98-4684-8466-556686BA3F03./lm[MSOvalShapenopqUVr3[MSOvalShape\_MSOvalShape_MSShapePathLayer__MSShapePathLayer]MSModelObject_$880772A4-E0DA-4B7A-A8AA-F3908586AE61 uvwxyz}?#  K#(*,(*,#@%% #@S#@S#@:\icon_15733 3_$39A2FC56-EA50-4E07-AB5F-D6422CA06A89n߀*#@>Ā)#Z{0.5, 0.5}(N,[NS.object.0}M#?# F##?##(*,[NS.object.1[NS.object.0? @AuJ&#$i- %" #(*!,(*#,#?o%#@S@.#@S>F8F#?B=nhUShapen߀*)'#@>Ā)#(Z{0.5, 0.5}(*N,[NS.object.0+}   M,#?# F#?#?#?#?(*.,[NS.object.0/ u#%(#05 6X,-31#(1*2,(6*4,;>?@#=dЀ%#@S@.#@S>F8F#B7 e(F*8oIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ,    !"#$%\NS.object.10\NS.object.76\NS.object.57\NS.object.80]NS.object.106\NS.object.38\NS.object.61\NS.object.42\NS.object.19\NS.object.23\NS.object.89[NS.object.0\NS.object.93\NS.object.74\NS.object.55]NS.object.105\NS.object.36\NS.object.17\NS.object.40\NS.object.21[NS.object.7\NS.object.87\NS.object.68\NS.object.91\NS.object.49\NS.object.72\NS.object.53\NS.object.34]NS.object.104\NS.object.15[NS.object.3\NS.object.85\NS.object.66\NS.object.70\NS.object.47\NS.object.28\NS.object.51\NS.object.32\NS.object.98]NS.object.103\NS.object.13\NS.object.79\NS.object.83\NS.object.64\NS.object.45\NS.object.26\NS.object.30\NS.object.96[NS.object.6\NS.object.11\NS.object.77]NS.object.102\NS.object.81\NS.object.58\NS.object.39\NS.object.62\NS.object.43\NS.object.24[NS.object.2\NS.object.94]NS.object.101\NS.object.75\NS.object.56\NS.object.60\NS.object.37\NS.object.41\NS.object.18\NS.object.22\NS.object.88[NS.object.9\NS.object.69\NS.object.92\NS.object.73]NS.object.100\NS.object.54\NS.object.35\NS.object.16]NS.object.109\NS.object.20[NS.object.5\NS.object.86\NS.object.67\NS.object.90\NS.object.71\NS.object.48\NS.object.52\NS.object.29\NS.object.33\NS.object.99\NS.object.14[NS.object.1]NS.object.108\NS.object.84\NS.object.65\NS.object.46\NS.object.27\NS.object.50\NS.object.31\NS.object.97\NS.object.12\NS.object.78[NS.object.8\NS.object.82\NS.object.59]NS.object.107\NS.object.63\NS.object.44\NS.object.25[NS.object.4\NS.object.95aiyс-9a݁Ɂ}فUIY فuEAQՁmu9Qemс}!Ձ1Áe)́݁]M]ɁŁyMEU Łq==iqY%5I(*+,- ^<:#;_,{0.46512118623704479, 0.0021930824800647517}_-{0.47645077257030227, 0.00028026898572660388}_-{0.47645077257030227, 0.00028026898572660388}(5678 ^@>#? _+{0.45321162108001956, 0.023955091502037198}_+{0.45609151592907349, 0.010845809491102096}_+{0.45373160209443203, 0.022082336929046459}(@ABC^DB#C _+{0.45278163677963995, 0.027770703760376596}_*{0.45290163239835052, 0.02585789026603845}_+{0.45278163677963995, 0.027770703760376596}(KLMN ^HF#G_){0.4168529486107132, 0.12264024424134541}_*{0.42722256999428598, 0.12068737182565989}_*{0.42722256999428598, 0.12068737182565989}?VWXY ^LJ#K _*{0.38378415602105526, 0.13062198431981392}_*{0.40613334000590118, 0.12461314611770462}_*{0.39598371058996445, 0.12732713803899065}(abcd^PN#O _*{0.36095498956136701, 0.13965527108365156}_*{0.37253456676693819, 0.13536896649948027}_*{0.36095498956136701, 0.13965527108365156}(lmno ^TR#S_+{0.27355818060049319, 0.061490300804546587}_+{0.28238785821061352, 0.069492070343688775}_+{0.28238785821061352, 0.069492070343688775}(wxyz ^XV#W _+{0.21795021096303097, 0.083983385141109007}_+{0.26062865268442797, 0.059968061793345559}_+{0.25019903349149986, 0.065706502276359935} ^\Z#[ _*{0.15225260971898727, 0.13835335613986119}_*{0.18810130080877369, 0.10583552673611314}_*{0.16121228258271075, 0.13018133618499256}(^`^#_ _){0.15458252464895109, 0.1624187531393089}_*{0.14956270793289175, 0.15138252030810151}_){0.15458252464895109, 0.1624187531393089}( ^db#c_*{0.18464142713595191, 0.27468388021538409}_*{0.19908089992079192, 0.25722820523825657}_*{0.19908089992079192, 0.25722820523825657}(^hf#g _*{0.16027231690281118, 0.31317048889989407}_){0.17154190542671335, 0.2934214406756282}_*{0.16027231690281118, 0.31317048889989407}( ^lj#k_+{0.041906638679714552, 0.30893425796740703}_+{0.054246188137119421, 0.30937490610222834}_+{0.054246188137119421, 0.30937490610222834}( ^pn#o _*{0.01398765805971919, 0.36252307999988498}_+{0.030757045774522988, 0.31665561505711742}_+{0.026787190722181248, 0.32834280536021992} ^tr#s _-{-0.0014617778492682625, 0.44682707997547827}_*{0.00539797168702001, 0.39799525485300347}_-{0.00027815862203517188, 0.43452899112182791}(^xv#w _+{0.016367571164145729, 0.46392222466047917}_+{0.0050879830053510182, 0.4587946827280126}_+{0.016367571164145729, 0.46392222466047917}( ^|z#{_*{0.11037413878899416, 0.52992931231064966}_*{0.11009414901200282, 0.50752636054711886}_*{0.11009414901200282, 0.50752636054711886}(^~# _*{0.11672390694576247, 0.57484537787141665}_*{0.11245406284664426, 0.55238233772586476}_*{0.11672390694576247, 0.57484537787141665}( ^#_+{0.023857297698664546, 0.64853376368995008}_+{0.033416948655940908, 0.64121299581371372}_+{0.033416948655940908, 0.64121299581371372}( ^# _+{0.036416839123705469, 0.70778090836274765}_+{0.020067436074388649, 0.66112227972336912}_+{0.023947294412697485, 0.67249901338602935}   ^# _+{0.078615298370260128, 0.78037768857456469}_){0.0531862268385093, 0.73969785394628496}_*{0.07222553167392165, 0.77015264890064217}(^# _*{0.10252442539834362, 0.78248078194530302}_+{0.090814852939169327, 0.78532496536096796}_*{0.10252442539834362, 0.78248078194530302}( ^#_*{0.21755022556732906, 0.77299683231630711}_*{0.20287076154506786, 0.75593173182231677}_*{0.20287076154506786, 0.75593173182231677}(()*+^# _*{0.25115899844118456, 0.80239006585495842}_){0.2340096246004639, 0.78827931081033853}_*{0.25115899844118456, 0.80239006585495842}(3456 ^#_*{0.22714987506417564, 0.91925195415564731}_){0.22937979364521394, 0.9076348669649027}_){0.22937979364521394, 0.9076348669649027}>?@A ^# _*{0.27405816234512065, 0.95555535162672423}_){0.23245968119211888, 0.9310392917621183}_*{0.24263930951273327, 0.93702810050355401}IJKL ^# _*{0.35455522323013605, 0.98624048537882902}_*{0.30795692463086005, 0.97115830149153459}_*{0.34298564565945749, 0.98253503515419494}(TUVW^# _*{0.37422450506377897, 0.97210970087353532}_){0.3671847620994248, 0.98200425444634198}_*{0.37422450506377897, 0.97210970087353532}(_`ab ^#_*{0.45620151191289149, 0.89048964862821733}_*{0.43385232792804562, 0.88675415421257286}_*{0.43385232792804562, 0.88675415421257286}(jklm^# _*{0.50200983935565624, 0.89150113639223905}_*{0.47897068056322445, 0.89173147518998652}_*{0.50200983935565624, 0.89150113639223905}(uvwx ^#_){0.5569578330902103, 0.99591471488422478}_*{0.55121804266188745, 0.98535918910918607}_*{0.55121804266188745, 0.98535918910918607}? ^# _*{0.59601640698050462, 0.99694623210892019}_({0.5687674018983101, 1.0016531553672392}_*{0.58057697070640979, 0.99958010618751147}? ^# _*{0.64719453836056784, 0.98468820217661734}_){0.6113058487312113, 0.99431235803032902}_*{0.62696527697294224, 0.99010617128885248}( ^# _*{0.69731270844202098, 0.96581043549165724}_*{0.66677382348017777, 0.97783812662621272}_*{0.68565313415730944, 0.97019688737919707}(^ā# _){0.7036424773290042, 0.94175505322254638}_({0.704642440818259, 0.95419334830091274}_){0.7036424773290042, 0.94175505322254638}( ^ȁ#_*{0.69191290560004481, 0.80779802023685665}_){0.6932228577709687, 0.82323071968594064}_){0.6932228577709687, 0.82323071968594064}? ^́# _){0.6475145266771295, 0.79893498388874562}_*{0.67837339995553414, 0.79632113927082804}_*{0.66293396368143931, 0.79763306894495523}(^Ё# _*{0.63736489726119272, 0.82796768713527025}_*{0.63606494472516151, 0.81250494349517566}_*{0.63736489726119272, 0.82796768713527025}^ԁ#_*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}( ^؁#_){0.63488498780784086, 0.9285856828295902}_*{0.64589458582453674, 0.92466992326788244}_*{0.64589458582453674, 0.92466992326788244}? ^܁# _){0.60553605939821098, 0.9379995293462281}_*{0.62417537883792129, 0.93299216417780373}_*{0.61276579542552356, 0.93604665693054268}(^# _*{0.59098659062955294, 0.94079363911020886}_*{0.59817632811729526, 0.93924135590799751}_*{0.59098659062955294, 0.94079363911020886}( ^#_*{0.53833851292028501, 0.84219861894393233}_*{0.54365831868312076, 0.85167255384259133}_*{0.54365831868312076, 0.85167255384259133}(     ^# _*{0.48612041951139673, 0.83932439133725667}_*{0.52800889007628238, 0.83662041414630772}_*{0.51714928658297477, 0.83745163676426615}(     ^# _*{0.41509301286962469, 0.82725664128135401}_({0.455771527612512, 0.83639007534856002}_*{0.42629260394927904, 0.82987048589927148}(    ^# _*{0.39694367553964921, 0.84124721956193171}_*{0.40345343785469823, 0.83176326993293592}_*{0.39694367553964921, 0.84124721956193171}( % & ' ( ^#_*{0.32320636784199652, 0.91409436803217003}_*{0.34109571466476579, 0.92088435520055345}_*{0.34109571466476579, 0.92088435520055345}( 0 1 2 3^# _*{0.28902761577926578, 0.89718950322356927}_({0.3059169991127802, 0.9062227899874068}_*{0.28902761577926578, 0.89718950322356927}( ; < = > ^#_*{0.31090681692416189, 0.78913056288897054}_*{0.30890688994565219, 0.79953586770895657}_*{0.30890688994565219, 0.79953586770895657}( F G H I ^# _*{0.27392816709151752, 0.75378857953023104}_*{0.30687696406246484, 0.77849491927123715}_){0.2984972700225092, 0.77203541820396959}( Q R S T ^# _*{0.22617991047959846, 0.69879769525059432}_*{0.25194896959769592, 0.73194645266556391}_*{0.23317965490438239, 0.70756058429533708}( \ ] ^ _^# _*{0.20383072649475251, 0.69808664939667808}_*{0.21463033217870492, 0.69506220083494974}_*{0.20383072649475251, 0.69808664939667808}( g h i j ^  # _){0.10153446154398135, 0.7060283305537991}_*{0.11106411359658007, 0.72273290075566288}_*{0.11106411359658007, 0.72273290075566288}( r s t u^# _+{0.085505046811226088, 0.67058619989169121}_+{0.092854778457249237, 0.68872287653172448}_+{0.085505046811226088, 0.67058619989169121}( } ~  ^#_*{0.17152190615692828, 0.60211548857865582}_){0.1631322124820801, 0.60896556412906044}_){0.1631322124820801, 0.60896556412906044}  ^# _*{0.16528213398397804, 0.54964831634390499}_*{0.17520177179738616, 0.59103919682610107}_*{0.17260186672532354, 0.58052372997240986}(  ^# _*{0.16323220883100562, 0.47856376041295212}_*{0.16188225812051155, 0.51931369815358996}_){0.1631322124820801, 0.48950986067112789}( ^ # _*{0.14704279993996952, 0.46391220993014226}_*{0.15693243884870001, 0.46855904480644012}_*{0.14704279993996952, 0.46391220993014226}( ^$"##_+{0.063505850047619355, 0.40319289989782797}_*{0.05995597966076463, 0.42219084334683016}_*{0.05995597966076463, 0.42219084334683016}( ^(&#' _+{0.075105426522975624, 0.36625857441552956}_+{0.069155643761909275, 0.38451542781960496}_+{0.075105426522975624, 0.36625857441552956}( ^,*#+_*{0.18428144027982019, 0.36938317028062634}_*{0.17356183167500819, 0.36910275783119462}_*{0.17356183167500819, 0.36910275783119462}  ^0.#/ _*{0.21276040045379835, 0.32676047796699781}_*{0.19421107772812082, 0.36348449411222244}_*{0.19912089846036218, 0.35393044137086865}  ^42#3 _){0.25865872461059597, 0.2698067065413387}_*{0.23038975676936133, 0.30093248842826481}_){0.25118899734586225, 0.2780788737995758}( ^86#7 _*{0.25591882465003768, 0.24774425560926078}_*{0.26051865670060997, 0.25789919217082546}_*{0.25591882465003768, 0.24774425560926078}( ^<:#;_*{0.23020976334129548, 0.14808767402727824}_*{0.21521031100247273, 0.16051595437530761}_*{0.21521031100247273, 0.16051595437530761}( ^@>#? _*{0.26253858294890481, 0.12638575338732685}_*{0.24582919304345627, 0.13686116131967074}_*{0.26253858294890481, 0.12638575338732685}(     ^DB#C_*{0.34369561973682838, 0.19930300496992306}_){0.33543592131558331, 0.1918019719476233}_){0.33543592131558331, 0.1918019719476233}(   ^HF#G _*{0.38040427942737393, 0.19026971820608543}_*{0.35558518562406854, 0.20116574481257696}_*{0.36573481504000532, 0.19654895412728962}?     ^LJ#K _*{0.42540263644384219, 0.17757104013896113}_*{0.39508374344963509, 0.18570300117248234}_*{0.41117315599174564, 0.18137663766696369}( " # $ % ^PN#O _*{0.46458120595284724, 0.17029033118407205}_*{0.43992210630782264, 0.17374541315028488}_*{0.45377160063400229, 0.17189268803796787}( - . / 0^TR#S _*{0.47649077110987254, 0.15198340412831243}_*{0.47346088173743028, 0.16249887098200369}_*{0.47649077110987254, 0.15198340412831243}( 8 9 : ; ^XV#W_+{0.52113914090510149, 0.058435808051807668}_*{0.5020498378952265, 0.058125351411365364}_*{0.5020498378952265, 0.058125351411365364}( C D E F^\Z#[ _+{0.55883776445000943, 0.061910919478694218}_+{0.53992845486820018, 0.059166883366397631}_+{0.55883776445000943, 0.061910919478694218}( N O P Q ^`^#__*{0.57466718648491366, 0.17135189259977804}_*{0.57303724599742834, 0.16051595437530761}_*{0.57303724599742834, 0.16051595437530761}( Y Z [ \ ^db#c _){0.6221754518594117, 0.19207236966671823}_*{0.58243690279642391, 0.18024497313889978}_*{0.59291652016381469, 0.18326942170062813}( d e f g ^hf#g _*{0.68568313306198725, 0.22758460344118409}_*{0.65030442481215067, 0.20474100354283198}_){0.6762234784536364, 0.22119520548627458}( o p q r^lj#k _*{0.70746233785795787, 0.22119520548627458}_*{0.69802268251939215, 0.22758460344118409}_*{0.70746233785795787, 0.22119520548627458} ( z { | } ^pn#o_*{0.80087892702414609, 0.17785145258839288}_*{0.78602946920871142, 0.16526293655497395}_*{0.78602946920871142, 0.16526293655497395}( ^tr#s _*{0.82767794853617593, 0.20603290375628544}_*{0.81463842463629266, 0.19164173626223371}_*{0.82767794853617593, 0.20603290375628544}( ^xv#w_*{0.77062003183929417, 0.29870921829348435}_*{0.77656981460036056, 0.28946562219257294}_*{0.77656981460036056, 0.28946562219257294}  ^|z#{ _*{0.79306921217306559, 0.34493721352837847}_*{0.77062003183929417, 0.31057667374265019}_*{0.77656981460036056, 0.31981025511322481}(  ^~# _*{0.81951824646385651, 0.41310748293130828}_*{0.80679871088053479, 0.37232750099965994}_*{0.81632836293313338, 0.40229157416751155}( ^# _){0.8399974987237957, 0.42220085807716701}_*{0.82884790581860424, 0.42093900205472407}_){0.8399974987237957, 0.42220085807716701}( ^#_*{0.93883389000174511, 0.44913046795295342}_){0.9356140075663445, 0.42978200894216151}_){0.9356140075663445, 0.42978200894216151}( ^# _*{0.94223376586521168, 0.48761707663746345}_*{0.94156379032741078, 0.46844888277273483}_*{0.94223376586521168, 0.48761707663746345}( ^#_'{0.838107567729104, 0.5224082498276762}_({0.84851718765224693, 0.518913108940116}_({0.84851718765224693, 0.518913108940116}(  ^# _*{0.82600800950912034, 0.57333315359055237}_*{0.83071783754351058, 0.53167187538926142}_){0.8295778791657602, 0.54260796091710028}(  ^# _*{0.80183889197383063, 0.64227455722941962}_){0.81750831985045402, 0.6036477423201938}_*{0.80591874300999045, 0.63172904618471781}( ^# _*{0.81253850130885763, 0.66206366437503283}_){0.80443879704589327, 0.6542421599819539}_*{0.81253850130885763, 0.66206366437503283}(  ^#_*{0.90780502293016707, 0.75747400029419154}_*{0.89679542491347108, 0.74644778219332097}_*{0.89679542491347108, 0.74644778219332097}?  ^# _*{0.94757357089783245, 0.73545160828346101}_*{0.92558437376911828, 0.75747400029419154}_*{0.93656397288113657, 0.74644778219332097}(    ^# _*{0.93656397288113657, 0.70661919964367337}_*{0.94757357089783245, 0.71764541774454382}_*{0.93656397288113657, 0.70661919964367337}(  ! " ^#_*{0.87035639025757294, 0.61216026310651528}_*{0.86271666919966594, 0.63362183021838225}_*{0.86271666919966594, 0.63362183021838225}( * + , -^# _*{0.87975604705656851, 0.56725421227608519}_*{0.87597618506718522, 0.58991754702837407}_*{0.87975604705656851, 0.56725421227608519}( 5 6 7 8 ^#_){0.99153196588547565, 0.5306303434342291}_*{0.98010238320329268, 0.53407541067010511}_*{0.98010238320329268, 0.53407541067010511}( @ A B C ^# _){1.0003016456862406, 0.47238467179511651}_*{0.99948167562505175, 0.52038527429963277}_*{0.99998165736967914, 0.50846774519878279} K L M N ^# _*{0.98601216742478903, 0.38665858011169063}_*{0.99643178698282442, 0.43506978656001777}_*{0.98862207213174413, 0.39849599136984598}( V W X Y^# _*{0.96400297102628962, 0.37669392342652608}_){0.9760725303415958, 0.37784561741526368}_*{0.96400297102628962, 0.37669392342652608}( a b c d ^ā#_({0.8526970350373323, 0.3457183624946526}_*{0.86077674003051141, 0.36719995906719333}_*{0.86077674003051141, 0.36719995906719333}( l m n o^ȁ# _*{0.83142781162088153, 0.30652070795622638}_*{0.84279739649370922, 0.32577903439398664}_*{0.83142781162088153, 0.30652070795622638}( w x y z ^́#_*{0.89355554320828534, 0.20545204939674822}_){0.8872857721306574, 0.21550683865494444}_){0.8872857721306574, 0.21550683865494444}(  ^Ё# _*{0.86182670169422892, 0.15470741077993533}_*{0.89278557132155911, 0.19254306199255011}_){0.8853958411359657, 0.18326942170062813}  ^ԁ# _+{0.79622909679911069, 0.099886776916024933}_*{0.83450769916778633, 0.12973067331983434}_*{0.80587874447042007, 0.10742786885967209}( ^؁# _){0.7727499540714069, 0.10649649893834515}_+{0.78279958713841813, 0.099496202432887815}_){0.7727499540714069, 0.10649649893834515}( ^܁#_*{0.66822377053959747, 0.15527825040913573}_*{0.68754306515200103, 0.16621433593697463}_*{0.68754306515200103, 0.16621433593697463}( ^# _*{0.62695527733804968, 0.13777250178032399}_*{0.64802450805664935, 0.14535365264531852}_*{0.62695527733804968, 0.13777250178032399}( ^#_+{0.61014589108367567, 0.020550083187508675}_*{0.6118058304758387, 0.032537715400716691}_*{0.6118058304758387, 0.032537715400716691}  ^# _,{0.55382794736884255, 0.0022832150530963944}_*{0.60097622588720867, 0.01098601571581808}_,{0.58908665999996856, 0.0088328486933955518}(  ^# _-{0.47834070356499392, 0.00024021006437923085}_,{0.51666930410813228, -0.001061704879411069}_+{0.479290668879786, 0.00030029844640039717}( ^# _-{0.47645077257030227, 0.00028026898572660388}_-{0.47740073788509435, 0.00024021006437923085}_-{0.47645077257030227, 0.00028026898572660388}_$AEA7C999-A4E4-4E79-BC1C-D9451F9B5503./ _MSShapePathLayer UV 3_MSShapePathLayer__MSShapePathLayer]MSModelObject_$442353C1-7D04-4A4B-B808-157AA349ACC4? @Au  J #Ji % #( *,( *,    #@9v$%#@Ā)#Z{0.5, 0.5}( "N %, '[NS.object.0} + ,M,#?# ( /* 2, 4[NS.object.0 u 7 8 9 >% C#   IX G H#( L*,( Q*, V Y Z [##? _){0.9988913633583224, 0.63125981004408149}_*{0.91927717248297547, 0.77631021125535704}_*{0.93956888622995349, 0.73992722607510353}     ^DB#C _){0.92928917900193286, 0.1708812865389466}_){1.0171485517164216, 0.49872943608601095}_*{0.98264193031819602, 0.37015838698579134}( ! " #^HF#G _,{0.56703657949783115, 0.0054457127487348746}_+{0.76010233087409362, 0.032599190658997634}_,{0.56703657949783115, 0.0054457127487348746}_$CB387502-20BA-497E-8450-07E57631F0C5_$C550036B-A9ED-4539-80B5-ADB394041D84_$7835DE9E-B005-40C4-93BE-7990C4ABD6E5_$EDF1C5EA-91A4-4910-B20D-D82E21CA18A9_$6F2F6F69-5A19-4C3E-AB17-A9420F8100AA./ . /]MSSharedLayer 0 1 2 3 43]MSSharedLayer^_MSSharedLayer^MSSharedObject__MSSharedObject]MSModelObject./ 6 7_MSSharedLayerContainer 8 9 : ; <3_MSSharedLayerContainer__MSSharedLayerContainer_MSSharedObjectContainer__MSSharedObjectContainer]MSModelObjectX > ?QS( A*R,./ F G_MSSharedLayerTextStyleContainer H I J K L M N3_MSSharedLayerTextStyleContainer_ _MSSharedLayerTextStyleContainer_MSSharedLayerStyleContainer__MSSharedLayerStyleContainer_MSSharedObjectContainer__MSSharedObjectContainer]MSModelObject( P*U S, U[NS.object.0V W X  Yu Z [ \ _ ` a c d e f g h k l q_horizontalRulerDataYzoomValue_verticalRulerDataTgrid\scrollOriginVlayout^#\ .W#?4& 5 6 2]_  1 v wZX#( {*Y,( *[, #%#@r#@r#VPage 1*( *` , [NS.object.1[NS.object.0[NS.object.2ҁa  W  Yu Z \    _hasBackgroundColor_backgroundColor_includeBackgroundColorInExportn#k bɁЁ,с ms   ec#( *d,( *f , [NS.object.0g u  Uscale_visibleScaleTypeVformat#?jihSpngP./ \MSExportSize 3\MSExportSize]_MSExportSize]MSModelObject %#@il#@#@#@_$5980F01E-1538-4E5D-842D-5DAFD1CB3939Vgithubn ߀*o( pN , [NS.object.0q }  M,r#?#_$4EFEC55E-6DC9-47FA-B36B-519FB1EC954F( *t  , [NS.object.1[NS.object.0u uy}#v{  yw#(*x,(*z, $%&()%#@c|#@8#@i#@Z@_$E6E90292-576E-4474-9B48-63BB996AD2FC.߀*~ 1345#@'n)#Z{0.5, 0.5}_$26433145-B5E7-44CA-9102-BECE00F95945(:*=>?@,BCDE[NS.object.1[NS.object.0[NS.object.3[NS.object.2݁g7 uHIJKLV# 5 ܀4Z[#(_*,(d*,ilmn#@F#Eg%#@E6Md6#@O(\*#r߀* uwxy#@.Md6N)#Z{0.5, 0.5}_$C3C3E1A2-E7B3-4444-BB01-2B9F2CF334F9(~*,[NS.object.1[NS.object.0? @AuJP#i @#(*,(*,#%#@.Md6N#@O(\*#mn߁* #@.Md6N)#Z{0.5, 0.5}_$5ECC50AE-32D6-405B-81DF-28D6DB9C9AF3(vH,[NS.object.0~ |}GE#?>>_$AC20EECA-0721-4DBF-A880-7CA8A47F3454(N,[NS.object.0}ML#?# (*,[NS.object.0 u #gX #@>>#(*,(*,  #%#@.Md6N#@O(\*#  e(*,S.object.1[NS.object.0[NS.object.3[NS.object.2 "]]^#@>>]_$E231732D-B745-4FF0-A8A6-9D52C3B5B9DE (--,-``^#@>>`_$1FB3E770-47E6-4CD5-8189-45B7388DFEE7 26666bb^#@>>b_$2A2DF133-2D6A-4DD8-A293-9B327869CE75 <??@?dd^#@>>d_$49B82564-2DF8-4F09-8C47-E3B31BFD5D76_$010705AD-2DAD-4AFE-B454-C10606C534FE_$279F5B88-6CCC-482A-BD33-DE09069AA81D? @AuIJKMNJRr#ۀi q[\#(`*,(e*,jmno#@"=p >%#@Al&ɲm#@F#@Md6Nmnqtu߁À*ǁ xz{|#@.Md6N)#Z{0.5, 0.5}_$24E81070-D605-4CC8-98AF-5137112DF783(vĀH,[NS.object.0~ |}GƀE#?>>_$E6F33C6D-FA48-42E1-9F13-E63C7EEFE550(ȀN,[NS.object.0}ML#?# (*ˀ,[NS.object.0 u #ҁځgX #Ё΀#(*π,(*р,#%#@Al&ɲm#@F# e(*Հ,[NS.object.1[NS.object.0[NS.object.3[NS.object.2ׁցف^]]#]---^``#`666^bb#b???^dd#d_$99AF5513-96F6-4C1C-9FE8-FE58 A5E5D590_$A6C8451F-E003-4DCD-BD07-E6B034C4B35A_$7D9702E0-CD66-4BAA-B936-60AE564BF0A6 u"*#ށ   6߀#(*,(*,"%&'#@FkQ%#@E6Md6#@O(\*#@cl&ɲ+߀* .012#@.Md6N)#Z{0.5, 0.5}_$7825528A-8A03-4E18-A3B4-1B1919A4C233(7*:;<,>[NS.object.1[NS.object.0? @AuBCDFGJKP#i @TU#(Y*,(^*,cfgh#%#@.Md6N#@O(\*#mnjmn߁* qstu#@.Md6N)#Z{0.5, 0.5}_$7AB7BE49-5A68-4254-9DDD-B2390968FA12(zvH},[NS.object.0~ |}GE#?>>_$62D99C54-74EA-4BC1-9CBF-F3F542D4849C(N,[NS.object.0}ML#?# (*,[NS.object.0 u #gX #@>>#(*,(*,#%#@.Md6N#@O(\*# e(*,[NS.object.1[NS.object.0[NS.object.3[NS.object.2    ]]^#@>>]_$3370B5DB-1E1B-4C4B-A33C-D006F41875C1 --- ``^#@>>`_$6E9F04E5-72AA-4815-A0F5-764BAB9E4EC8 666 bb^#@>>b_$BB72DEB8-B89D-4A46-8800-87DA3C14F168 ???dd^#@>>d_$8222B535-379D-4152-9C44-AF3154784877_$DCAFABA9-96E5-4CBE-81B1-23418CA04638_$BA477052-21B4-4EFC-A62B-8B102CD13893? @AuJ  #5i$ #(*,(*,#&'(#@"=p >%#@Al&ɲm#@F#@Md6Nmn*-.߁*! 1345#@.Md6N)#Z{0.5, 0.5}_$5F1C6CC3-FFA9-4028-9835-729C1DF362F2(:vH=,?[NS.object.0~ |}BDG E#?>>_$E8378C10-8462-437B-9B41-DA9DC7488784(H"NK,M[NS.object.0#}QRML#?# (U*%X,Z[NS.object.0& u_`abem #,4'g-X #op*(#(t*),(y*+,~#%#@Al&ɲm#@F#. e(*/,[NS.object.1[NS.object.0[NS.object.3[NS.object.21032^]]#]---^``#`666^bb#b???^dd#d_$C5B3D51F-1E01-47BD-8AB5-CDF5520D17E1_$51C6B58A-4997-40A7-83B2-78A595A71283_$6794B697-2372-4F69-94F2-F691FCAC73FF? @AuJ>#=8fiI ;9#(*:,(*<,#% #@b|#@c#@8>>mn߁B*F? #@'n)A@#Z{0.5, 0.5}_$8A185DAA-C26A-4630-BEE8-07E5C7881C37(vCH,[NS.object.0D~ |}GEE#?"FTW_$F876F4F1-4D09-413B-8190-7671546066DA(GN,[NS.object.0H}  ML#?# (*J,[NS.object.0K u"#LQ R eX&'OM#(+*N,(0*P,589:#%#@b|#@c#<S e(@*TCDEF,HIJK[NS.object.1[NS.object.0[NS.object.3[NS.object.2YUa]?OPQR ^XV#W _{0.77614237490000004, 1}_{0.22385762510000001, 1}X{0.5, 1}?Z[\] ^\Z#[ _{1, 0.22385762510000001}_{1, 0.77614237490000004}X{1, 0.5}?efgh ^`^#_ _{0.22385762510000001, 0}_{0.77614237490000004, 0}X{0.5, 0}?pqrs ^db#c _{0, 0.77614237490000004}_{0, 0.22385762510000001}X{0, 0.5}_$6CC1E849-E2AD-4786-B863-B0B5C525CC07_$FE17A171-D4BB-450D-AA0F-6E19E3BB2CFC u|}~}?n#uhm ki#(*j,(*l,#@/Q% #@].#@] =p#@Dd6Mn߀*ro #@'n)qp#Z{0.5, 0.5}_$12A365F7-48DE-4C68-B208-67315850EF14(sN,[NS.object.0t}M#?# (*v,[NS.object.1[NS.object.0Kw? @AuJ~#}xJi %{y#(*z,(*|,#?L`t̀%#@]*uRNT#@]?ک5#?MX<^Nn߀* #@'n)#Z{0.5, 0.5}_$841C9CBD-40CF-4B2B-AB5E-BC85E66292A3(N,[NS.object.0}   M,#?# (*,[NS.object.0 u%## IX'(#(,*,(1*,69:;#=V7u%#@]*uRNT#@]?ک5#= e(A*oDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~,      \NS.object.10\NS.object.76\NS.object.57\NS.object.80]NS.object.106\NS.object.38\NS.object.61\NS.object.42\NS.object.19\NS.object.23\NS.object.89[NS.object.0\NS.object.93\NS.object.74\NS.object.55]NS.object.105\NS.object.36\NS.object.17\NS.object.40\NS.object.21[NS.object.7\NS.object.87\NS.object.68\NS.object.91\NS.object.49\NS.object.72\NS.object.53\NS.object.34]NS.object.104\NS.object.15[NS.object.3\NS.object.85\NS.object.66\NS.object.70\NS.object.47\NS.object.28\NS.object.51\NS.object.32\NS.object.98]NS.object.103\NS.object.13\NS.object.79\NS.object.83\NS.object.64\NS.object.45\NS.object.26\NS.object.30\NS.object.96[NS.object.6\NS.object.11\NS.object.77]NS.object.102\NS.object.81\NS.object.58\NS.object.39\NS.object.62\NS.object.43\NS.object.24[NS.object.2\NS.object.94]NS.object.101\NS.object.75\NS.object.56\NS.object.60\NS.object.37\NS.object.41\NS.object.18\NS.object.22\NS.object.88[NS.object.9\NS.object.69\NS.object.92\NS.object.73]NS.object.100\NS.object.54\NS.object.35\NS.object.16]NS.object.109\NS.object.20[NS.object.5\NS.object.86\NS.object.67\NS.object.90\NS.object.71\NS.object.48\NS.object.52\NS.object.29\NS.object.33\NS.object.99\NS.object.14[NS.object.1]NS.object.108\NS.object.84\NS.object.65\NS.object.46\NS.object.27\NS.obje ct.50\NS.object.31\NS.object.97\NS.object.12\NS.object.78[NS.object.8\NS.object.82\NS.object.59]NS.object.107\NS.object.63\NS.object.44\NS.object.25[NS.object.4\NS.object.95uс9)9݁m5!Ձ1Ue1́M]-Ł́݁E Ł)Ձy-= %q%5ف!iсEQaɁAIY Ɂف}=A ($%&' ^#_,{0.46512118623704479, 0.0021930824800647517}_-{0.47645077257030227, 0.00028026898572660388}_-{0.47645077257030227, 0.00028026898572660388}(/012 ^# _+{0.45321162108001956, 0.023955091502037198}_+{0.45609151592907349, 0.010845809491102096}_+{0.45373160209443203, 0.022082336929046459}(:;<=^# _+{0.45278163677963995, 0.027770703760376596}_*{0.45290163239835052, 0.02585789026603845}_+{0.45278163677963995, 0.027770703760376596}(EFGH ^#_){0.4168529486107132, 0.12264024424134541}_*{0.42722256999428598, 0.12068737182565989}_*{0.42722256999428598, 0.12068737182565989}?PQRS ^# _*{0.38378415602105526, 0.13062198431981392}_*{0.40613334000590118, 0.12461314611770462}_*{0.39598371058996445, 0.12732713803899065}([\]^^# _*{0.36095498956136701, 0.13965527108365156}_*{0.37253456676693819, 0.13536896649948027}_*{0.36095498956136701, 0.13965527108365156}(fghi ^#_+{0.27355818060049319, 0.061490300804546587}_+{0.28238785821061352, 0.069492070343688775}_+{0.28238785821061352, 0.069492070343688775}(qrst ^# _+{0.21795021096303097, 0.083983385141109007}_+{0.26062865268442797, 0.059968061793345559}_+{0.25019903349149986, 0.065706502276359935}|}~ ^# _*{0.15225260971898727, 0.13835335613986119}_*{0.18810130080877369, 0.10583552673611314}_*{0.16121228258271075, 0.13018133618499256}(^# _){0.15458252464895109, 0.1624187531393089}_*{0.14956270793289175, 0.15138252030810151}_){0.15458252464895109, 0.1624187531393089}( ^#_*{0.18464142713595191, 0.27468388021538409}_*{0.19908089992079192, 0.25722820523825657}_*{0.19908089992079192, 0.25722820523825657}(^# _*{0.16027231690281118, 0.31317048889989407}_){0.17154190542671335, 0.2934214406756282}_*{0.16027231690281118, 0.31317048889989407}( ^ā#_+{0.041906638679714552, 0.30893425796740703}_+{0.054246188137119421, 0.30937490610222834}_+{0.054246188137119421, 0.30937490610222834}( ^ȁ# _*{0.01398765805971919, 0.36252307999988498}_+{0.030757045774522988, 0.31665561505711742}_+{0.026787190722181248, 0.32834280536021992} ^́# _-{-0.0014617778492682625, 0.44682707997547827}_*{0.00539797168702001, 0.39799525485300347}_-{0.00027815862203517188, 0.43452899112182791}(^Ё# _+{0.016367571164145729, 0.46392222466047917}_+{0.0050879830053510182, 0.4587946827280126}_+{0.016367571164145729, 0.46392222466047917}( ^ԁ#_*{0.11037413878899416, 0.52992931231064966}_*{0.11009414901200282, 0.50752636054711886}_*{0.11009414901200282, 0.50752636054711886}(^؁# _*{0.11672390694576247, 0.57484537787141665}_*{0.11245406284664426, 0.55238233772586476}_*{0.11672390694576247, 0.57484537787141665}( ^܁#_+{0.023857297698664546, 0.64853376368995008}_+{0.033416948655940908, 0.64121299581371372}_+{0.033416948655940908, 0.64121299581371372}( ^# _+{0.036416839123705469, 0.70778090836274765}_+{0.020067436074388649, 0.66112227972336912}_+{0.023947294412697485, 0.67249901338602935} ^# _+{0.078615298370260128, 0.78037768857456469}_){0.0531862268385093, 0.73969785394628496}_*{0.07222553167392165, 0.77015264890064217}(   ^# _*{0.10252442539834362, 0.78248078194530302}_+{0.090814852939169327, 0.78532496536096796}_*{0.10252442539834362, 0.78248078194530302}( ^#_*{0.21755022556732906, 0.77299683231630711}_*{0.20287076154506786, 0.75593173182231677}_*{0.20287076154506786, 0.75593173182231677}(!"#$^# _*{0.25115899844118456, 0.80239006585495842}_){0.2340096246004639, 0.78827931081033853}_*{0.25115899844118456, 0.80239006585495842}(,-./ ^#_*{0.22714987506417564, 0.91925195415564731}_){0.22937979364521394, 0.9076348669649027}_){0.22937979364521394, 0.9076348669649027}789: ^# _*{0.27405816234512065, 0.95555535162672423}_){0.23245968119211888, 0.9310392917621183}_*{0.24263930951273327, 0.93702810050355401}BCDE ^# _*{0.35455522323013605, 0.98624048537882902}_*{0.30795692463086005, 0.97115830149153459}_*{0.34298564565945749, 0.98253503515419494}(MNOP^# _*{0.37422450506377897, 0.97210970087353532}_){0.3671847620994248, 0.98200425444634198}_*{0.37422450506377897, 0.97210970087353532}(XYZ[ ^#_*{0.45620151191289149, 0.89048964862821733}_*{0.43385232792804562, 0.88675415421257286}_*{0.43385232792804562, 0.88675415421257286}(cdef^# _*{0.50200983935565624, 0.89150113639223905}_*{0.47897068056322445, 0.89173147518998652}_*{0.50200983935565624, 0.89150113639223905}(nopq ^  # _){0.5569578330902103, 0.99591471488422478}_*{0.55121804266188745, 0.98535918910918607}_*{0.55121804266188745, 0.98535918910918607}?yz{| ^# _*{0.59601640698050462, 0.99694623210892019}_({0.5687674018983101, 1.0016531553672392}_*{0.58057697070640979, 0.99958010618751147}? ^# _*{0.64719453836056784, 0.98468820217661734}_){0.6113058487312113, 0.99431235803032902}_*{0.62696527697294224, 0.99010617128885248}( ^# _*{0.69731270844202098, 0.96581043549165724}_*{0.66677382348017777, 0.97783812662621272}_*{0.68565313415730944, 0.97019688737919707}(^# _){0.7036424773290042, 0.94175505322254638}_({0.704642440818259, 0.95419334830091274}_){0.7036424773290042, 0.94175505322254638}( ^ #_*{0.69191290560004481, 0.80779802023685665}_){0.6932228577709687, 0.82323071968594064}_){0.6932228577709687, 0.82323071968594064}? ^$"## _){0.6475145266771295, 0.79893498388874562}_*{0.67837339995553414, 0.79632113927082804}_*{0.66293396368143931, 0.79763306894495523}(^(&#' _*{0.63736489726119272, 0.82796768713527025}_*{0.63606494472516151, 0.81250494349517566}_*{0.63736489726119272, 0.82796768713527025}^,*#+_*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}( ^0.#/_){0.63488498780784086, 0.9285856828295902}_*{0.64589458582453674, 0.92466992326788244}_*{0.64589458582453674, 0.92466992326788244}? ^42#3 _){0.605 53605939821098, 0.9379995293462281}_*{0.62417537883792129, 0.93299216417780373}_*{0.61276579542552356, 0.93604665693054268}(^86#7 _*{0.59098659062955294, 0.94079363911020886}_*{0.59817632811729526, 0.93924135590799751}_*{0.59098659062955294, 0.94079363911020886}( ^<:#;_*{0.53833851292028501, 0.84219861894393233}_*{0.54365831868312076, 0.85167255384259133}_*{0.54365831868312076, 0.85167255384259133}( ^@>#? _*{0.48612041951139673, 0.83932439133725667}_*{0.52800889007628238, 0.83662041414630772}_*{0.51714928658297477, 0.83745163676426615}(    ^DB#C _*{0.41509301286962469, 0.82725664128135401}_({0.455771527612512, 0.83639007534856002}_*{0.42629260394927904, 0.82987048589927148}(^HF#G _*{0.39694367553964921, 0.84124721956193171}_*{0.40345343785469823, 0.83176326993293592}_*{0.39694367553964921, 0.84124721956193171}( ! ^LJ#K_*{0.32320636784199652, 0.91409436803217003}_*{0.34109571466476579, 0.92088435520055345}_*{0.34109571466476579, 0.92088435520055345}()*+,^PN#O _*{0.28902761577926578, 0.89718950322356927}_({0.3059169991127802, 0.9062227899874068}_*{0.28902761577926578, 0.89718950322356927}(4567 ^TR#S_*{0.31090681692416189, 0.78913056288897054}_*{0.30890688994565219, 0.79953586770895657}_*{0.30890688994565219, 0.79953586770895657}(?@AB ^XV#W _*{0.27392816709151752, 0.75378857953023104}_*{0.30687696406246484, 0.77849491927123715}_){0.2984972700225092, 0.77203541820396959}(JKLM ^\Z#[ _*{0.22617991047959846, 0.69879769525059432}_*{0.25194896959769592, 0.73194645266556391}_*{0.23317965490438239, 0.70756058429533708}(UVWX^`^#_ _*{0.20383072649475251, 0.69808664939667808}_*{0.21463033217870492, 0.69506220083494974}_*{0.20383072649475251, 0.69808664939667808}(`abc ^db#c_){0.10153446154398135, 0.7060283305537991}_*{0.11106411359658007, 0.72273290075566288}_*{0.11106411359658007, 0.72273290075566288}(klmn^hf#g _+{0.085505046811226088, 0.67058619989169121}_+{0.092854778457249237, 0.68872287653172448}_+{0.085505046811226088, 0.67058619989169121}(vwxy ^lj#k_*{0.17152190615692828, 0.60211548857865582}_){0.1631322124820801, 0.60896556412906044}_){0.1631322124820801, 0.60896556412906044} ^pn#o _*{0.16528213398397804, 0.54964831634390499}_*{0.17520177179738616, 0.59103919682610107}_*{0.17260186672532354, 0.58052372997240986}( ^tr#s _*{0.16323220883100562, 0.47856376041295212}_*{0.16188225812051155, 0.51931369815358996}_){0.1631322124820801, 0.48950986067112789}(^xv#w _*{0.14704279993996952, 0.46391220993014226}_*{0.15693243884870001, 0.46855904480644012}_*{0.14704279993996952, 0.46391220993014226}( ^|z#{_+{0.063505850047619355, 0.40319289989782797}_*{0.05995597966076463, 0.42219084334683016}_*{0.05995597966076463, 0.42219084334683016}(^~# _+{0.075105426522975624, 0.36625857441552956}_+{0.069155643761909275, 0.38451542781960496}_+{0.075105426522975624, 0.36625857441552956}( ^#_*{0.18428144027982019, 0.36938317028062634}_*{0.17356183167500819, 0.36910275783119462}_*{0.17356183167500819, 0.36910275783119462} ^# _*{0.21276040045379835, 0.32676047796699781}_*{0.19421107772812082, 0.36348449411222244}_*{0.19912089846036218, 0.35393044137086865} ^# _){0.25865872461059597, 0.2698067065413387}_*{0.23038975676936133, 0.30093248842826481}_){0.25118899734586225, 0.2780788737995758}(^# _*{0.25591882465003768, 0.24774425560926078}_*{0.26051865670060997, 0.25789919217082546}_*{0.25591882465003768, 0.24774425560926078}( ^#_*{0.23020976334129548, 0.14808767402727824}_*{0.21521031100247273, 0.16051595437530761}_*{0.21521031100247273, 0.16051595437530761}(^# _*{0.26253858294890481, 0.12638575338732685}_*{0.24582919304345627, 0.13686116131967074}_*{0.26253858294890481, 0.12638575338732685}( ^#_*{0.34369561973682838, 0.19930300496992306}_){0.33543592131558331, 0.1918019719476233}_){0.33543592131558331, 0.1918019719476233}( ^# _*{0.38040427942737393, 0.19026971820608543}_*{0.35558518562406854, 0.20116574481257696}_*{0.36573481504000532, 0.19654895412728962}? ^# _*{0.42540263644384219, 0.17757104013896113}_*{0.39508374344963509, 0.18570300117248234}_*{0.41117315599174564, 0.18137663766696369}( ^# _*{0.46458120595284724, 0.17029033118407205}_*{0.43992210630782264, 0.17374541315028488}_*{0.45377160063400229, 0.17189268803796787}(&'()^# _*{0.47649077110987254, 0.15198340412831243}_*{0.47346088173743028, 0.16249887098200369}_*{0.47649077110987254, 0.15198340412831243}(1234 ^#_+{0.52113914090510149, 0.058435808051807668}_*{0.5020498378952265, 0.058125351411365364}_*{0.5020498378952265, 0.058125351411365364}(<=>?^# _+{0.55883776445000943, 0.061910919478694218}_+{0.53992845486820018, 0.059166883366397631}_+{0.55883776445000943, 0.061910919478694218}(GHIJ ^#_*{0.57466718648491366, 0.17135189259977804}_*{0.57303724599742834, 0.16051595437530761}_*{0.57303724599742834, 0.16051595437530761}(RSTU ^# _){0.6221754518594117, 0.19207236966671823}_*{0.58243690279642391, 0.18024497313889978}_*{0.59291652016381469, 0.18326942170062813}(]^_` ^# _*{0.68568313306198725, 0.22758460344118409}_*{0.65030442481215067, 0.20474100354283198}_){0.6762234784536364, 0.22119520548627458}(hijk^ā# _*{0.70746233785795787, 0.22119520548627458}_*{0.69802268251939215, 0.22758460344118409}_*{0.70746233785795787, 0.22119520548627458}(stuv ^ȁ#_*{0.80087892702414609, 0.17785145258839288}_*{0.78602946920871142, 0.16526293655497395}_*{0.78602946920871142, 0.16526293655497395}(~^́# _*{0.82767794853617593, 0.20603290375628544}_*{0.81463842463629266, 0.19164173626223371}_*{0.82767794853617593, 0.20603290375628544}( ^Ё#_*{0.77062003183929417, 0.29870921829348435}_*{0.77656981460036056, 0.28946562219257294}_*{0.77656981460036056, 0.28946562219257294} ^ԁ# _*{0.79306921217306559, 0.34493721352837847}_*{0.77062003183929417, 0.31057667374265019}_*{0.77656981460036056, 0.31981025511322481}( ^؁# _*{0.81951824646385651, 0.41310748293130828}_*{0.80679871088053479, 0.37232750099965994}_*{0.81632836293313338, 0.40229157416751155}(^܁# _){0.8399974987237957, 0.42220085807716701}_*{0.82884790581860424, 0.42093900205472407}_){0.8399974987237957, 0.42220085807716701}( ^#_*{0.93883389000174511, 0.44913046795295342}_){0.9356140075663445, 0.42978200894216151}_){0.9356140075663445, 0.42978200894216151}(^# _*{0.94223376586521168, 0.48761707663746345}_*{0.94156379032741078, 0.46844888277273483}_*{0.94223376586521168, 0.48761707663746345}( ^#_'{0.838107567729104, 0.5224082498276762}_({0.84851718765224693, 0.518913108940116}_({0.84851718765224693, 0.518913108940116}( ^# _*{0.82600800950912034, 0.57333315359055237}_*{0.83071783754351058, 0.53167187538926142}_){0.8295778791657602, 0.54260796091710028}( ^# _*{0.80183889197383063, 0.64227455722941962}_){0.81750831985045402, 0.6036477423201938}_*{0.80591874300999045, 0.63172904618471781}(^# _*{0.81253850130885763, 0.66206366437503283}_){0.80443879704589327, 0.6542421599819539}_*{0.81253850130885763, 0.66206366437503283}( ^#_*{0.90780502293016707, 0.75747400029419154}_*{0.89679542491347108, 0.74644778219332097}_*{0.89679542491347108, 0.74644778219332097}? ^# _*{0.94757357089783245, 0.73545160828346101}_*{0.92558437376911828, 0.75747400029419154}_*{0.93656397288113657, 0.74644778219332097}( ^# _*{0.93656397288113657, 0.70661919964367337}_*{0.94757357089783245, 0.71764541774454382}_*{0.93656397288113657, 0.70661919964367337}( ^#_*{0.87035639025757294, 0.61216026310651528}_*{0.86271666919966594, 0.63362183021838225}_*{0.86271666919966594, 0.63362183021838225}(#$%&^# _*{0.87975604705656851, 0.56725421227608519}_*{0.87597618506718522, 0.58991754702837407}_*{0.87975604705656851, 0.56725421227608519}(./01 ^  # _){0.99153196588547565, 0.5306303434342291}_*{0.98010238320329268, 0.53407541067010511}_*{0.98010238320329268, 0.53407541067010511}(9:;< ^# _){1.0003016456862406, 0.47238467179511651}_*{0.99948167562505175, 0.52038527429963277}_*{0.99998165736967914, 0.50846774519878279}DEFG ^# _*{0.98601216742478903, 0.38665858011169063}_*{0.99643178698282442, 0.43506978656001777}_*{0.98862207213174413, 0.39849599136984598}(OPQR^# _*{0.96400297102628962, 0.37669392342652608}_){0.9760725303415958, 0.37784561741526368}_*{0.96400297102628962, 0.37669392342652608}(Z[\] ^#_({0.8526970350373323, 0.3457183624946526}_*{0.86077674003051141, 0.36719995906719333}_*{0.86077674003051141, 0.36719995906719333}(efgh^ # _*{0.83142781162088153, 0.30652070795622638}_*{0.84279739649370922, 0.32577903439398664}_*{0.83142781162088153, 0.30652070795622638}(pqrs ^$"##_*{0.89355554320828534, 0.20545204939674822}_){0.8872857721306574, 0.21550683865494444}_){0.8872857721306574, 0.21550683865494444}({|}~ ^(&#' _*{0.86182670169422892, 0.15470741077993533}_*{0.89278557132155911, 0.19254306199255011}_){0.8853958411359657, 0.18326942170062813} ^,*#+ _+{0.79622909679911069, 0.099886776916024933}_*{0.83450769916778633, 0.12973067331983434}_*{0.80587874447042007, 0.10742786885967209}(^0.#/ _){0.7727499540714069, 0.10649649893834515}_+{0.78279958713841813, 0.099496202432887815}_){0.7727499540714069, 0.10649649893834515}( ^42#3_*{0.66822377053959747, 0.15527825040913573}_*{0.68754306515200103, 0.16621433593697463}_*{0.68754306515200103, 0.16621433593697463}(^86#7 _*{0.62695527733804968, 0.13777250178032399}_*{0.64802450805664935, 0.14535365264531852}_*{0.62695527733804968, 0.13777250178032399}( ^<:#;_+{0.61014589108367567, 0.020550083187508675}_*{0.6118058304758387, 0.032537715400716691}_*{0.6118058304758387, 0.032537715400716691} ^@>#? _,{0.55382794736884255, 0.0022832150530963944}_*{0.60097622588720867, 0.01098601571581808}_,{0.58908665999996856, 0.0088328486933955518}( ^DB#C _-{0.47834070356499392, 0.00024021006437923085}_,{0.51666930410813228, -0.001061704879411069}_+{0.479290668879786, 0.00030029844640039717}(^HF#G _-{0.47645077257030227, 0.00028026898572660388}_-{0.47740073788509435, 0.00024021006437923085}_-{0.47645077257030227, 0.00028026898572660388}_$392F406F-BC08-4C8C-A70A-9087346B70BF_$C48DD06B-BDF1-4B23-A533-21B74B9985B0? @AuJR#QLiY %OM#(*N,(*P,#@C7x0%#@E^u#@E>e#@B^)n  ߀*VS #@'n)UT#Z{0.5, 0.5}_$1A54B544-0FB4-4CB0-A1AC-78C819FC383B(WN,[NS.object.0X}  !M,#?# ($*Z',)[NS.object.0[ u,-.3%8#\a bX<=_]#(A*^,(F*`,KNOP#=V7u%#@E^u#@E>e#Rc e(V*dYZ[\]^_`abcdefghijklmnop,rstuvw[NS.object.6[NS.object.7[NS.object.8[NS.object.9\NS.object.10\NS.object.11[NS.object.0\NS.object.12[NS.object.1[NS.object.2\NS.object.13[NS.object.3\NS.object.14[NS.object.4[NS.object.5}eimquy({|}~ ^hf#g_-{0.50273486918088972, -0.0035697769613720694}_,{0.56703657949783115, 0.0054457127487348746}_,{0.56703657949783115, 0.0054457127487348746} ^lj#k _+{0.10348603168427635, 0.086825889894566702}_-{0.43586323205694311, -0.0021786628221270796}_+{0.36939314599659101, 0.015584794648232002}? ^pn#o _*{0.08836094162221475, 0.89426063894634056}_,{-0.054136145812039849, 0.36280153336478399}_+{0.017125782940540596, 0.62847758176559132}( ^tr#s _){0.6682542175945656, 0.97451722390278217}_){0.36200460642645116, 1.0542922693494852}_*{0.62785818059695331, 0.98305117410315057}? ^xv#w _*{0.67711511106455202, 0.85410559427313437}_*{0.69414087616096132, 0.93492397532427107}_*{0.68565476368366296, 0.89455491309118096}( ^|z#{ _*{0.59458298246041774, 0.83735872021222357}_*{0.63733478569778479, 0.82831647830713118}_*{0.59696551877107873, 0.83679692411752848}( ^~# _*{0.40221325292771942, 0.88893695214422996}_*{0.59220044614975675, 0.83797402069688964}_*{0.58981790983909577, 0.83869632996149768}? ^# _*{0.11127612231801071, 0.40309033901291774}_*{0.21182450864208749, 0.77796884734445682}_*{0.16157708555095543, 0.59048946488620901}? ^# _*{0.59758123040192368, 0.10972576880213808}_){0.2222916063664522, 0.21020701316760299}_*{0.40992303334873481, 0.15993963878988507} ^# _*{0.86257816230342399, 0.49883644486595274}_){0.7879699746875557, 0.22069387360191137}_){0.8381906277077813, 0.40814650386517359} ^# _*{0.78748811341124214, 0.70287543602021296}_){0.84943405748842893, 0.5900079253764704}_*{0.80777982715822039, 0.66646569864497385}? ^# _*{0.87333973080775806, 0.78931177801830066}_*{0.80055190801351839, 0.74878220261529749}_*{0.83690566430427893, 0.76906036641429176} ^# _){0.9988913633583224, 0.63125981004408149}_*{0.91927717248297547, 0.77631021125535704}_*{0.93956888622995349, 0.73992722607510353}     ^# _){0.92928917900193286, 0.1708812865389466}_){1.0171485517164216, 0.49872943608601095}_*{0.98264193031819602, 0.37015838698579134}(^# _,{0.56703657949783115, 0.0054457127487348746}_+{0.76010233087409362, 0.032599190658997634}_,{0.56703657949783115, 0.0054457127487348746}_$7645375A-1225-475E-B596-B1E985804214_$35BF06BB-982F-4BD4-A809-68E3C6BA5C22_$DEFAC19D-B2C6-4226-86CD-19C6426E2070_$697E11FB-9EAD-4069-9C2E-8AB1284C3A9B"#$%& u'*+,./236_usesNewLineSpacingBehaviourWstorage]textBehaviour_dontSynchroniseWithSymbol_heightIsClipped_!automaticallyDrawOnUnderlyingPath#ǁ =>#(B*,(G*, MNOQR%#@Z@#@H#@k#@y(_$06FA93FD-F16F-42E6-8681-52A5B89B59D3UbcbioX*Z[\Zattributes^_`abcdefXNS.key.1[NS.object.1XNS.key.0[NS.object.0WNSColorijklmnUNSRGB\NSColorSpace_NSCustomColorSpaceF1 1 1pqrTNSID./tu\NSColorSpacev3\NSColorSpace./xyWNSColorx3VNSFont|}~VNSSizeXNSfFlagsVNSName#@d ZDiscoNight./VNSFont3./EE3./[MSTextStyle3[MSTextStyle\_MSTextStyle]MSModelObject XNSStringZNSDelegate\NSAttributesXNS.bytesEbcbio./_NSMutableString3XNSString^`fbd[NS.object.2XNS.key.2[NS.object.1[NS.object.0āijkmnO)0.003921568627 0.3411764706 0.6078431373_NSParagraphStyle(ZNSTabStops[NSAlignment./_NSParagraphStyle3_NSParagraphStyle|}~#@VŁ]Roboto-Medium./]NSTextStorage3]NSTextStorage_NSMutableAttributedString_NSAttributedString_$6AB237DB-8FD0-4FA6-AC76-765CF5DA4736./[MSTextLayerUV3[MSTextLayer\_MSTextLayer]MSStyledLayer^_MSStyledLayer]MSModelObjectTbaseVguidesʁ(*ˀ,./[MSRulerData3[MSRulerData\_MSRulerData]MSModelObjectс΁(*π,_$04D6D56F-5E06-4E9D-98AD-2CC5DD16E49F./_MSArtboardGroupUV3_MSArtboardGroup__MSArtboardGroup\MSLayerGroup]_MSLayerGroup]MSStyledLayer^_MSStyledLayer]MSModelObject W  Yu Z \ ? y#  с     ցԀ#(*Հ,(*׀,[NS.object.1[NS.object.0ۀ u   !#@jځSpngP u %  (#?jځSsvg ,-.01%#@Y#@h#@`#@_$4DAEC7EF-8A47-4B3C-8AA3-22E7BBFF78C9n6߀*(9N<,>[NS.object.0} BCM,#?#(F*I,K[NS.object.0 uNOPQRxy# L `a#(e*,(j*, pqrtu%#@Y##@`#_$1608F572-216F-4C8F-9D0B-D43E3F954331z߀*}#@>Ā)#Z{0.5, 0.5}(*,S.object.1[NS.object.0[NS.object.3[NS.object.2= u# 5 <4#(*,(*,#@=qq%#@<#@D#*(*,S.object.1[NS.object.0? @AuJP#i @#(*,(*,#%#@$#@D#mn߁*(vH,S.object.0|}~#?GE(N,[NS.object.0 }  ML#?# (* ,[NS.object.0  u ( # gX #@*+#(/*,(4*,9<=>#%#@$#@D#@ e(D*GHIJ,LMNO[NS.object.1[NS.object.0[NS.object.3[NS.object.2U^]]#@]--]-^``#@`66e6^bb#@b??m?^dd#@d_$8950733D-CB35-416D-AEE3-44A3AFF6E2B1_$6A197363-A75C-4D82-8080-459C8F2D63F2? @AuuvwyzJ~r##";i* q #(*,(*!,#@%#@7#@>#@mn߁$*'(v%H,[NS.object.0&|}~#?GE((N,[NS.object.0)}ML#?# (*+,[NS.object.0, u #2:-g3X #0.#(*/,(*1,#%#@7#@>#4 e(*5,[NS.object.1[NS.object.0[NS.object.3[NS.object.27698^]]#]-- -^``#`666^bb#b???^dd#d_$63E06324-2E84-4266-BF78-6EEBE4D6E1CB_$34EAAFF6-AD0C-45BC-97B4-9825B5A7E751_$56DF2CF2-0577-473B-8AF5-6E6F11ED342D u!"#$%"/*D#E>C   34A?#(8*@,(=*B,BEFG#@=%#@<#@D#@Z*(M*FPQR,T[NS.object.1[NS.object.0gG? @AuXYZ\]JaPN#MHfiU @jkKI#(o*J,(t*L,y|}~#%#@$#@D#mn߁O*R(vPH,[NS.object.0Q|}~#?GE(SN,[NS.object.0T}ML#?# (*V,[NS.object.0W u #]eXg^X #@[Y#(*Z,(*\,#%#@$#@D#_ e(*`,[NS.object.1[NS.object.0[NS.object.3[NS.object.2badc^]]#@]---^``#@`666^bb#@b???^dd#@d_$2F5BBD32-1BAD-437A-BC8B-497FE8E78B10_$A8BCA065-015F-4CB4-95C0-A50021A40389? @Au J  n#mhiu ki#(*j,( *l,%()*#@%#@7#@>#@mn,/߁o*r(2vpH5,7[NS.object.0q|}~9#?GE(>sNA,C[NS.object.0t}GHML#?# (K*vN,P[NS.object.0w uUVWX[c #}xg~X #ef{y#(j*z,(o*|,twxy#%#@7#@>#{ e(*,[NS.object.1[NS.object.0[NS.object.3[NS.object.2^]]#]---^``#`666^bb#b???^dd#d_$4C96068D-8B1E-4516-A856-CD6C36315BF0_$882073B2-240A-413E-9A42-EC85CEC3EDB7_$5AE6FE4D-58C1-449B-AB52-F4ADC185C67A? @AuJ#i #(*,(*,#% #@Y#@X#@0mn߁*#@>Ā)#Z{0.5, 0.5}(vH,[NS.object.0|}~#?`qPGE(N,[NS.object.0}ML#?# (*,[NS.object.0 u  #  X#(*,("*,'*+,#%#@Y#@X#. e(2*5678,:;<=[NS.object.1[NS.object.0[NS.object.3[NS.object.2?ABCD ^# _{0.77614237490000004, 1}_{0.22385762510000001, 1}X{0.5, 1}?LMNO ^# _{1, 0.22385762510000001}_{1, 0.77614237490000004}X{1, 0.5}?WXYZ ^# _{0.22385762510000001, 0}_{0.77614237490000004, 0}X{0.5, 0}?bcde ^# _{0, 0.77614237490000004}_{0, 0.22385762510000001}X{0, 0.5}_$A2BB1D11-0AFC-4ED0-AAD7-28CDE2BFD223_$1D552FFD-FD5E-427C-B236-C9931E804B55 unopqr}?|#Á  #(*,(*,#@%% #@S#@S#@:n߀*#@>Ā)#Z{0.5, 0.5}(N,[NS.object.0}M#?# (*Ā,[NS.object.1[NS.object.0 ? @AuJ#Ɓ i %Ɂǀ#(*Ȁ,(*ʀ,#?o%#@S@.#@S>F8F#?B=nhn߀*ρ̀#@>Ā)#Z{0.5, 0.5}(ЀN,[NS.object.0} M,#?# (*Ӏ , [NS.object.0 u    % #Ձ  X  ؁ր#( *׀,( *ـ, $ ' ( )#=dЀ%#@S@.#@S>F8F# + e( /*݀o 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~   , !!!!!!!!!! ! ! ! ! !\NS.object.10\NS.object.76\NS.object.57\NS.object.80]NS.object.106\NS.object.38\NS.object.61\NS.object.42\NS.object.19\NS.object.23\NS.object.89[NS.object.0\NS.object.93\NS.object.74\NS.object.55]NS.object.105\NS.object.36\NS.object.17\NS.object.40\NS.object.21[NS.object.7\NS.object.87\NS.object.68\NS.object.91\NS.object.49\NS.object.72\NS.object.53\NS.object.34]NS.object.104\NS.object.15[NS.object.3\NS.object.85\NS.object.66\NS.object.70\NS.object.47\NS.object.28\NS.object.51\NS.object.32\NS.object.98]NS.object.103\NS.object.13\NS.object.79\NS.object.83\NS.object.64\NS.object.45\NS.object.26\NS.object.30\NS.object.96[NS.object.6\NS.object.11\NS.object.77]NS.object.102\NS.object.81\NS.object.58\NS.object.39\NS.object.62\NS.object.43\NS.object.24[NS.object.2\NS.object.94]NS.object.101\NS.object.75\NS.object.56\NS.object.60\NS.object.37\NS.object.41\NS.object.18\NS.object.22\NS.object.88[NS.object.9\NS.object.69\NS.object.92\NS.object.73]NS.object.100\NS.object.54\NS.object.35\NS.object.16]NS.object.109\NS.object.20[NS.object.5\NS.object.86\NS.object.67\NS.object.90\NS.object.71\NS.object.48\NS.object.52\NS.object.29\NS.object.33\NS.object.99\NS.object.14[NS.object.1]NS.object.108\NS.object.84\NS.object.65\NS.object.46\NS.object.27\NS.object.50\NS.object.31\NS.object.97\NS.object.12\NS.object.78[NS.object.8\NS.object.82\NS.object.59]NS.object.107\NS.object.63\NS.object.44\NS.object.25[NS.object.4\NS.object.95   vҁ*: Bށ R  n"~2 : Jf ~ 2N^ f z  *ށFV ^  v "Ɓzց> V r ΁r&6 > N  nj . 6 FRb j .JZ b  &ʁ ځB Z(!!!! ^#_,{0.46512118623704479, 0.0021930824800647517}_-{0.47645077257030227, 0.00028026898572660388}_-{0.47645077257030227, 0.00028026898572660388}(!!!!  ^# _+{0.45321162108001956, 0.023955091502037198}_+{0.45609151592907349, 0.010845809491102096}_+{0.45373160209443203, 0.022082336929046459}(!(!)!*!+^# _+{0.45278163677963995, 0.027770703760376596}_*{0.45290163239835052, 0.02585789026603845}_+{0.45278163677963995, 0.027770703760376596}(!3!4!5!6 ^#_){0.4168529486107132, 0.12264024424134541}_*{0.42722256999428598, 0.12068737182565989}_*{0.42722256999428598, 0.12068737182565989}?!>!?!@!A ^# _*{0.38378415602105526, 0.13062198431981392}_*{0.40613334000590118, 0.12461314611770462}_*{0.39598371058996445, 0.12732713803899065}(!I!J!K!L^# _*{0.36095498956136701, 0.13965527108365156}_*{0.37253456676693819, 0.13536896649948027}_*{0.36095498956136701, 0.13965527108365156}(!T!U!V!W ^#_+{0.27355818060049319, 0.061490300804546587}_+{0.28238785821061352, 0.069492070343688775}_+{0.28238785821061352, 0.069492070343688775}(!_!`!a!b ^# _+{0.21795021096303097, 0.083983385141109007}_+{0.26062865268442797, 0.059968061793345559}_+{0.25019903349149986, 0.065706502276359935}!j!k!l!m ^# _*{0.15225260971898727, 0.13835335613986119}_*{0.18810130080877369, 0.10583552673611314}_*{0.16121228258271075, 0.13018133618499256}(!u!v!w!x^# _){0.15458252464895109, 0.1624187531393089}_*{0.14956270793289175, 0.15138252030810151}_){0.15458252464895109, 0.1624187531393089}(!!!! ^ #_*{0.18464142713595191, 0.27468388021538409}_*{0.19908089992079192, 0.25722820523825657}_*{0.19908089992079192, 0.25722820523825657}(!!!!^  # _*{0.16027231690281118, 0.31317048889989407}_){0.17154190542671335, 0.2934214406756282}_*{0.16027231690281118, 0.31317048889989407}(!!!! ^#_+{0.041906638679714552, 0.30893425796740703}_+{0.054246188137119421, 0.30937490610222834}_+{0.054246188137119421, 0.30937490610222834}(!!!! ^# _*{0.01398765805971919, 0.36252307999988498}_+{0.030757045774522988, 0.31665561505711742}_+{0.026787190722181248, 0.32834280536021992}!!!! ^# _-{-0.0014617778492682625, 0.44682707997547827}_*{0.00539797168702001, 0.39799525485300347}_-{0.00027815862203517188, 0.43452899112182791}(!!!!^# _+{0.016367571164145729, 0.46392222466047917}_+{0.0050879830053510182, 0.4587946827280126}_+{0.016367571164145729, 0.46392222466047917}(!!!! ^!# _*{0.11037413878899416, 0.52992931231064966}_*{0.11009414901200282, 0.50752636054711886}_*{0.11009414901200282, 0.50752636054711886}(!!!!^%##$ _*{0.11672390694576247, 0.57484537787141665}_*{0.11245406284664426, 0.55238233772586476}_*{0.11672390694576247, 0.57484537787141665}(!!!! ^)'#(_+{0.023857297698664546, 0.64853376368995008}_+{0.033416948655940908, 0.64121299581371372}_+{0.033416948655940908, 0.64121299581371372}(!!!! ^-+#, _+{0.036416839123705469, 0.70778090836274765}_+{0.020067436074388649, 0.66112227972336912}_+{0.023947294412697485, 0.67249901338602935}!!!! ^1/#0 _+{0.078615298370260128, 0.78037768857456469}_){0.0531862268385093, 0.73969785394628496}_*{0.07222553167392165, 0.77015264890064217}(!!!!^53#4 _*{0.10252442539834362, 0.78248078194530302}_+{0.090814852939169327, 0.78532496536096796}_*{0.10252442539834362, 0.78248078194530302}("""" ^97#8_*{0.21755022556732906, 0.77299683231630711}_*{0.20287076154506786, 0.75593173182231677}_*{0.20287076154506786, 0.75593173182231677}(""""^=;#< _*{0.25115899844118456, 0.80239006585495842}_){0.2340096246004639, 0.78827931081033853}_*{0.25115899844118456, 0.80239006585495842}("""" ^A?#@_*{0.22714987506417564, 0.91925195415564731}_){0.22937979364521394, 0.9076348669649027}_){0.22937979364521394, 0.9076348669649027}"%"&"'"( ^EC#D _*{0.27405816234512065, 0.95555535162672423}_){0.23245968119211888, 0.9310392917621183}_*{0.24263930951273327, 0.93702810050355401}"0"1"2"3 ^IG#H _*{0.35455522323013605, 0.98624048537882902}_*{0.30795692463086005, 0.97115830149153459}_*{0.34298564565945749, 0.98253503515419494}(";"<"=">^MK#L _*{0.37422450506377897, 0.97210970087353532}_){0.3671847620994248, 0.98200425444634198}_*{0.37422450506377897, 0.97210970087353532}("F"G"H"I ^QO#P_*{0.45620151191289149, 0.89048964862821733}_*{0.43385232792804562, 0.88675415421257286}_*{0.43385232792804562, 0.88675415421257286}("Q"R"S"T^US#T _*{0.50200983935565624, 0.89150113639223905}_*{0.47897068056322445, 0.89173147518998652}_*{0.50200983935565624, 0.89150113639223905}("\"]"^"_ ^YW#X_){0.5569578330902103, 0.99591471488422478}_*{0.55121804266188745, 0.98535918910918607}_*{0.55121804266188745, 0.98535918910918607}?"g"h"i"j ^][#\ _*{0.59601640698050462, 0.99694623210892019}_({0.5687674018983101, 1.0016531553672392}_*{0.58057697070640979, 0.99958010618751147}?"r"s"t"u ^a_#` _*{0.64719453836056784, 0.98468820217661734}_){0.6113058487312113, 0.99431235803032902}_*{0.62696527697294224, 0.99010617128885248}("}"~"" ^ec#d _*{0.69731270844202098, 0.96581043549165724}_*{0.66677382348017777, 0.97783812662621272}_*{0.68565313415730944, 0.97019688737919707}(""""^ig#h _){0.7036424773290042, 0.94175505322254638}_({0.704642440818259, 0.95419334830091274}_){0.7036424773290042, 0.94175505322254638}("""" ^mk#l_*{0.69191290560004481, 0.80779802023685665}_){0.6932228577709687, 0.82323071968594064}_){0.6932228577709687, 0.82323071968594064}?"""" ^qo#p _){0.6475145266771295, 0.79893498388874562}_*{0.67837339995553414, 0.79632113927082804}_*{0.66293396368143931, 0.79763306894495523}(""""^us#t _*{0.63736489726119272, 0.82796768713527025}_*{0.63606494472516151, 0.81250494349517566}_*{0.63736489726119272, 0.82796768713527025}""""^yw#x_*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}("""" ^}{#|_){0.63488498780784086, 0.9285856828295902}_*{0.64589458582453674, 0.92466992326788244}_*{0.64589458582453674, 0.92466992326788244}?"""" ^# _){0.60553605939821098, 0.9379995293462281}_*{0.62417537883792129, 0.93299216417780373}_*{0.61276579542552356, 0.93604665693054268}(""""^# _*{0.59098659062955294, 0.94079363911020886}_*{0.59817632811729526, 0.93924135590799751}_*{0.59098659062955294, 0.94079363911020886}("""" ^#_*{0.53833851292028501, 0.84219861894393233}_*{0.54365831868312076, 0.85167255384259133}_*{0.54365831868312076, 0.85167255384259133}("""" ^# _*{0.48612041951139673, 0.83932439133725667}_*{0.52800889007628238, 0.83662041414630772}_*{0.51714928658297477, 0.83745163676426615}("""" ^# _*{0.41509301286962469, 0.82725664128135401}_({0.455771527612512, 0.83639007534856002}_*{0.42629260394927904, 0.82987048589927148}(####^# _*{0.39694367553964921, 0.84124721956193171}_*{0.40345343785469823, 0.83176326993293592}_*{0.39694367553964921, 0.84124721956193171}(# # ## ^#_*{0.32320636784199652, 0.91409436803217003}_*{0.34109571466476579, 0.92088435520055345}_*{0.34109571466476579, 0.92088435520055345}(####^# _*{0.28902761577926578, 0.89718950322356927}_({0.3059169991127802, 0.9062227899874068}_*{0.28902761577926578, 0.89718950322356927}(#"###$#% ^#_*{0.31090681692416189, 0.78913056288897054}_*{0.30890688994565219, 0.79953586770895657}_*{0.30890688994565219, 0.79953586770895657}(#-#.#/#0 ^# _*{0.27392816709151752, 0.75378857953023104}_*{0.30687696406246484, 0.77849491927123715}_){0.2984972700225092, 0.77203541820396959}(#8#9#:#; ^# _*{0.22617991047959846, 0.69879769525059432}_*{0.25194896959769592, 0.73194645266556391}_*{0.23317965490438239, 0.70756058429533708}(#C#D#E#F^# _*{0.20383072649475251, 0.69808664939667808}_*{0.21463033217870492, 0.69506220083494974}_*{0.20383072649475251, 0.69808664939667808}(#N#O#P#Q ^#_){0.10153446154398135, 0.7060283305537991}_*{0.11106411359658007, 0.72273290075566288}_*{0.11106411359658007, 0.72273290075566288}(#Y#Z#[#\^# _+{0.085505046811226088, 0.67058619989169121}_+{0.092854778457249237, 0.68872287653172448}_+{0.085505046811226088, 0.67058619989169121}(#d#e#f#g ^#_*{0.17152190615692828, 0.60211548857865582}_){0.1631322124820801, 0.60896556412906044}_){0.1631322124820801, 0.60896556412906044}#o#p#q#r ^# _*{0.16528213398397804, 0.54964831634390499}_*{0.17520177179738616, 0.59103919682610107}_*{0.17260186672532354, 0.58052372997240986}(#z#{#|#} ^# _*{0.16323220883100562, 0.47856376041295212}_*{0.16188225812051155, 0.51931369815358996}_){0.1631322124820801, 0.48950986067112789}(####^Ł# _*{0.14704279993996952, 0.46391220993014226}_*{0.15693243884870001, 0.46855904480644012}_*{0.14704279993996952, 0.46391220993014226}(#### ^Ɂ#_+{0.063505850047619355, 0.40319289989782797}_*{0.05995597966076463, 0.42219084334683016}_*{0.05995597966076463, 0.42219084334683016}(####^́# _+{0.075105426522975624, 0.36625857441552956}_+{0.069155643761909275, 0.38451542781960496}_+{0.075105426522975624, 0.36625857441552956}(#### ^с#_*{0.18428144027982019, 0.36938317028062634}_*{0.17356183167500819, 0.36910275783119462}_*{0.17356183167500819, 0.36910275783119462}#### ^Ձ# _*{0.21276040045379835, 0.32676047796699781}_*{0.19421107772812082, 0.36348449411222244}_*{0.19912089846036218, 0.35393044137086865}#### ^ف# _){0.25865872461059597, 0.2698067065413387}_*{0.23038975676936133, 0.30093248842826481}_){0.25118899734586225, 0.2780788737995758}(####^݁# _*{0.25591882465003768, 0.24774425560926078}_*{0.26051865670060997, 0.25789919217082546}_*{0.25591882465003768, 0.24774425560926078}(#### ^#_*{0.23020976334129548, 0.14808767402727824}_*{0.21521031100247273, 0.16051595437530761}_*{0.21521031100247273, 0.16051595437530761}(####^# _*{0.26253858294890481, 0.12638575338732685}_*{0.24582919304345627, 0.13686116131967074}_*{0.26253858294890481, 0.12638575338732685}(#### ^#_*{0.34369561973682838, 0.19930300496992306}_){0.33543592131558331, 0.1918019719476233}_){0.33543592131558331, 0.1918019719476233}(#### ^# _*{0.38040427942737393, 0.19026971820608543}_*{0.35558518562406854, 0.20116574481257696}_*{0.36573481504000532, 0.19654895412728962}?##$$ ^# _*{0.42540263644384219, 0.17757104013896113}_*{0.39508374344963509, 0.18570300117248234}_*{0.41117315599174564, 0.18137663766696369}($ $ $ $  ^# _*{0.46458120595284724, 0.17029033118407205}_*{0.43992210630782264, 0.17374541315028488}_*{0.45377160063400229, 0.17189268803796787}($$$$^# _*{0.47649077110987254, 0.15198340412831243}_*{0.47346088173743028, 0.16249887098200369}_*{0.47649077110987254, 0.15198340412831243}($$ $!$" ^#_+{0.52113914090510149, 0.058435808051807668}_*{0.5020498378952265, 0.058125351411365364}_*{0.5020498378952265, 0.058125351411365364}($*$+$,$-^ # _+{0.55883776445000943, 0.061910919478694218}_+{0.53992845486820018, 0.059166883366397631}_+{0.55883776445000943, 0.061910919478694218}($5$6$7$8 ^  # _*{0.57466718648491366, 0.17135189259977804}_*{0.57303724599742834, 0.16051595437530761}_*{0.57303724599742834, 0.16051595437530761}($@$A$B$C ^ #  _){0.6221754518594117, 0.19207236966671823}_*{0.58243690279642391, 0.18024497313889978}_*{0.59291652016381469, 0.18326942170062813}($K$L$M$N ^ # _*{0.68568313306198725, 0.22758460344118409}_*{0.65030442481215067, 0.20474100354283198}_){0.6762234784536364, 0.22119520548627458}($V$W$X$Y^  #  _*{0.70746233785795787, 0.22119520548627458}_*{0.69802268251939215, 0.22758460344118409}_*{0.70746233785795787, 0.22119520548627458}($a$b$c$d ^  # _*{0.80087892702414609, 0.17785145258839288}_*{0.78602946920871142, 0.16526293655497395}_*{0.78602946920871142, 0.16526293655497395}($l$m$n$o^  #  _*{0.82767794853617593, 0.20603290375628544}_*{0.81463842463629266, 0.19164173626223371}_*{0.82767794853617593, 0.20603290375628544}($w$x$y$z ^  # _*{0.77062003183929417, 0.29870921829348435}_*{0.77656981460036056, 0.28946562219257294}_*{0.77656981460036056, 0.28946562219257294}$$$$ ^ ! # _*{0.79306921217306559, 0.34493721352837847}_*{0.77062003183929417, 0.31057667374265019}_*{0.77656981460036056, 0.31981025511322481}($$$$ ^ % ## $ _*{0.81951824646385651, 0.41310748293130828}_*{0.80679871088053479, 0.37232750099965994}_*{0.81632836293313338, 0.40229157416751155}($$$$^ ) '# ( _){0.8399974987237957, 0.42220085807716701}_*{0.82884790581860424, 0.42093900205472407}_){0.8399974987237957, 0.42220085807716701}($$$$ ^ - +# ,_*{0.93883389000174511, 0.44913046795295342}_){0.9356140075663445, 0.42978200894216151}_){0.9356140075663445, 0.42978200894216151}($$$$^ 1 /# 0 _*{0.94223376586521168, 0.48761707663746345}_*{0.94156379032741078, 0.46844888277273483}_*{0.94223376586521168, 0.48761707663746345}($$$$ ^ 5 3# 4_'{0.838107567729104, 0.5224082498276762}_({0.84851718765224693, 0.518913108940116}_({0.84851718765224693, 0.518913108940116}($$$$ ^ 9 7# 8 _*{0.82600800950912034, 0.57333315359055237}_*{0.83071783754351058, 0.53167187538926142}_){0.8295778791657602, 0.54260796091710028}($$$$ ^ = ;# < _*{0.80183889197383063, 0.64227455722941962}_){0.81750831985045402, 0.6036477423201938}_*{0.80591874300999045, 0.63172904618471781}($$$$^ A ?# @ _*{0.81253850130885763, 0.66206366437503283}_){0.80443879704589327, 0.6542421599819539}_*{0.81253850130885763, 0.66206366437503283}($$$$ ^ E C# D_*{0.90780502293016707, 0.75747400029419154}_*{0.89679542491347108, 0.74644778219332097}_*{0.89679542491347108, 0.74644778219332097}?$$$$ ^ I G# H _*{0.94757357089783245, 0.73545160828346101}_*{0.92558437376911828, 0.75747400029419154}_*{0.93656397288113657, 0.74644778219332097}($$$$^ M K# L _*{0.93656397288113657, 0.70661919964367337}_*{0.94757357089783245, 0.71764541774454382}_*{0.93656397288113657, 0.70661919964367337}(%%%% ^ Q O# P_*{0.87035639025757294, 0.61216026310651528}_*{0.86271666919966594, 0.63362183021838225}_*{0.86271666919966594, 0.63362183021838225}(%%%%^ U S# T _*{0.87975604705656851, 0.56725421227608519}_*{0.87597618506718522, 0.58991754702837407}_*{0.87975604705656851, 0.56725421227608519}(%%%% ^ Y W# X_){0.99153196588547565, 0.5306303434342291}_*{0.98010238320329268, 0.53407541067010511}_*{0.98010238320329268, 0.53407541067010511}(%'%(%)%* ^ ] [# \ _){1.0003016456862406, 0.47238467179511651}_*{0.99948167562505175, 0.52038527429963277}_*{0.99998165736967914, 0.50846774519878279}%2%3%4%5 ^ a _# ` _*{0.98601216742478903, 0.38665858011169063}_*{0.99643178698282442, 0.43506978656001777}_*{0.98862207213174413, 0.39849599136984598}(%=%>%?%@^ e c# d _*{0.96400297102628962, 0.37669392342652608}_){0.9760725303415958, 0.37784561741526368}_*{0.96400297102628962, 0.37669392342652608}(%H%I%J%K ^ i g# h_({0.8526970350373323, 0.3457183624946526}_*{0.86077674003051141, 0.36719995906719333}_*{0.86077674003051141, 0.36719995906719333}(%S%T%U%V^ m k# l _*{0.83142781162088153, 0.30652070795622638}_*{0.84279739649370922, 0.32577903439398664}_*{0.83142781162088153, 0.30652070795622638}(%^%_%`%a ^ q o# p_*{0.89355554320828534, 0.20545204939674822}_){0.8872857721306574, 0.21550683865494444}_){0.8872857721306574, 0.21550683865494444}(%i%j%k%l ^ u s# t _*{0.86182670169422892, 0.15470741077993533}_*{0.89278557132155911, 0.19254306199255011}_){0.8853958411359657, 0.18326942170062813}%t%u%v%w ^ y w# x _+{0.79622909679911069, 0.099886776916024933}_*{0.83450769916778633, 0.12973067331983434}_*{0.80587874447042007, 0.10742786885967209}(%%%%^ } {# | _){0.7727499540714069, 0.10649649893834515}_+{0.78279958713841813, 0.099496202432887815}_){0.7727499540714069, 0.10649649893834515}(%%%% ^ # _*{0.66822377053959747, 0.15527825040913573}_*{0.68754306515200103, 0.16621433593697463}_*{0.68754306515200103, 0.16621433593697463}(%%%%^ # _*{0.62695527733804968, 0.13777250178032399}_*{0.64802450805664935, 0.14535365264531852}_*{0.62695527733804968, 0.13777250178032399}(%%%% ^ # _+{0.61014589108367567, 0.020550083187508675}_*{0.6118058304758387, 0.032537715400716691}_*{0.6118058304758387, 0.032537715400716691}%%%% ^ # _,{0.55382794736884255, 0.0022832150530963944}_*{0.60097622588720867, 0.01098601571581808}_,{0.58908665999996856, 0.0088328486933955518}(%%%% ^ # _-{0.47834070356499392, 0.00024021006437923085}_,{0.51666930410813228, -0.001061704879411069}_+{0.479290668879786, 0.00030029844640039717}(%%%%^ # _-{0.47645077257030227, 0.00028026898572660388}_-{0.47740073788509435, 0.00024021006437923085}_-{0.47645077257030227, 0.00028026898572660388}_$B244B151-2430-4894-B60F-1C95720F0C47_$E6C6921A-8133-4BF6-830B-591B281F9616? @Au%%%%%J% #  i %%% #(%* ,(%* ,%%%%#@9v$%#@Ā)# Z{0.5, 0.5}(& N&,&[NS.object.0 } & & M,#?# (&* &,&[NS.object.0  u&&&&%&$#   X&(&) #(&-* ,(&2* ,&7&:&;&<# e(&B* &E&F&G&H&I&J&K&L&M&N&O&P&Q&R&S&T&U&V&W&X&Y&Z&[&\,&^&_&`&a&b&c[NS.object.6[NS.object.7[NS.object.8[NS.object.9\NS.object.10\NS.object.11[NS.object.0\NS.object.12[NS.object.1[NS.object.2\NS.object.13[NS.object.3\NS.object.14[NS.object.4[NS.object.5 Ɂ ́ с Ձ ف ݁  (&g&h&i&j ^ # _-{0.50273486918088972, -0.0035697769613720694}_,{0.56703657949783115, 0.0054457127487348746}_,{0.56703657949783115, 0.0054457127487348746}&r&s&t&u ^ # _+{0.10348603168427635, 0.086825889894566702}_-{0.43586323205694311, -0.0021786628221270796}_+{0.36939314599659101, 0.015584794648232002}?&}&~&& ^ # _*{0.08836094162221475, 0.89426063894634056}_,{-0.054136145812039849, 0.36280153336478399}_+{0.017125782940540596, 0.62847758176559132}(&&&& ^ # _){0.6682542175945656, 0.97451722390278217}_){0.36200460642645116, 1.0542922693494852}_*{0.62785818059695331, 0.98305117410315057}?&&&& ^ ā # _*{0.67711511106455202, 0.85410559427313437}_*{0.69414087616096132, 0.93492397532427107}_*{0.68565476368366296, 0.89455491309118096}(&&&& ^ ȁ # _*{0.59458298246041774, 0.83735872021222357}_*{0.63733478569778479, 0.82831647830713118}_*{0.59696551877107873, 0.83679692411752848}(&&&& ^ ́ # _*{0.40221325292771942, 0.88893695214422996}_*{0.59220044614975675, 0.83797402069688964}_*{0.58981790983909577, 0.83869632996149768}?&&&& ^ Ё # _*{0.11127612231801071, 0.40309033901291774}_*{0.21182450864208749, 0.77796884734445682}_*{0.16157708555095543, 0.59048946488620901}?&&&& ^ ԁ # _*{0.59758123040192368, 0.10972576880213808}_){0.2222916063664522, 0.21020701316760299}_*{0.40992303334873481, 0.15993963878988507}&&&& ^ ؁ # _*{0.86257816230342399, 0.49883644486595274}_){0.7879699746875557, 0.22069387360191137}_){0.8381906277077813, 0.40814650386517359}&&&& ^ ܁ # _*{0.78748811341124214, 0.70287543602021296}_){0.84943405748842893, 0.5900079253764704}_*{0.80777982715822039, 0.66646569864497385}?&&&& ^ # _*{0.87333973080775806, 0.78931177801830066}_*{0.80055190801351839, 0.74878220261529749}_*{0.83690566430427893, 0.76906036641429176}&&&& ^ # _){0.9988913633583224, 0.63125981004408149}_*{0.91927717248297547, 0.77631021125535704}_*{0.93956888622995349, 0.73992722607510353}&&&& ^ # _){0.92928917900193286, 0.1708812865389466}_){1.0171485517164216, 0.49872943608601095}_*{0.98264193031819602, 0.37015838698579134}(''''^ # _,{0.56703657949783115, 0.0054457127487348746}_+{0.76010233087409362, 0.032599190658997634}_,{0.56703657949783115, 0.0054457127487348746}_$45489D93-8DBE-4634-B4A0-A900D516B411_$CFFE4C70-2EFC-4F8C-8559-4765BE092FC8_$DBE34D81-CE29-461F-9176-4DFF5E31EA92''''F#?y"v#?#?y"v#?y"v'с ('* ,'с ('* ,_$FC587D3B-EF21-46B3-B84D-3BC7B62E635B W  Yu Z \ '&'''(?'*','- '0'3'4 #  ' - с *  '>'? #('C* ,('H* , 'N'O'P'R'S%#@c` #@#@`#@_$450B396B-782B-41E8-83C6-2311EA2DAC93]logo-wordmarkn'Y߀* ('\ N'_,'a[NS.object.0 } 'e'fM,#?#('i* 'l'm'n,'p[NS.object.1[NS.object.0   u's't'u'v'wxy #    L '' #('* ,('* ,''''#%#@`#@Y#'߀* '''#@>Ā)# Z{0.5, 0.5}('* '''',''''[NS.object.1[NS.object.0[NS.object.3[NS.object.2 ^  ׁ  u'''''' #    5 ]4''  #('* ,('* ,''''#@=qq%#@<#@D#*('* ''','[NS.object.1[NS.object.0 = ? @Au'''''J'P $# #  (?(@(C(K # 3 ; .g 4X #@(M(N 1 /#((R* 0,((W* 2,(\(_(`(a#%#@$#@D#(c 5 e((g* 6(j(k(l(m,(o(p(q(r[NS.object.1[NS.object.0[NS.object.3[NS.object.2 8 7 : 9(x^]]#@]--(-^``#@`66(6^bb#@b??(?^dd#@d_$C675AC45-337D-4E84-AECF-DA92F210CE1D_$EDE00841-67B1-401B-81F1-ADAE6DABDF1C? @Au(((((J(r D# C > \i K q(( A ?#((* @,((* B,((((#@%#@7#@>#@mn((߁ E* H((v FH(,([NS.object.0 G|}~(#?GE(( IN(,([NS.object.0 J}((ML#?# ((* L(,([NS.object.0 M u(((((( # S [ Ng TX #(( Q O#((* P,()* R,)) ) ) #%#@7#@>#) U e()* V)))),))))[NS.object.1[NS.object.0[NS.object.3[NS.object.2 X W Z Y)$^]]#]--),-^``#`66)46^bb#b??)<?^dd#d_$96D36843-5055-48FC-BD12-C756DC107030_$42DD89E3-C5C0-4A4F-A046-AB6AD61CAE1F_$65AEE671-0F71-4079-8D7A-B697CC6F0A49 u)D)E)F)G)H")R* e# f _ d   )V)W b `#()[* a,()`* c,)e)h)i)j#@=%#@<#@D#@Z*()p* g)s)t)u,)w[NS.object.1[NS.object.0  h? @Au){)|)}))J)P o# n i i v @)) l j#()* k,()* m,))))#%#@$#@D#mn))߁ p* s()v qH),)[NS.object.0 r|}~)#?GE() tN),)[NS.object.0 u}))ML#?# ()* w),)[NS.object.0 x u)))))) # ~ yg X #@)) | z#()* {,()* },))))#%#@$#@D#) e()* )))),))**[NS.object.1[NS.object.0[NS.object.3[NS.object.2 *^]]#@]--*-^``#@`66*6^bb#@b??*?^dd#@d_$EDA6A4ED-C3F2-4642-B1B6-589B415DB3D8_$2D74F65A-0F53-4869-92EA-95C9E91D27E9? @Au*'*(*)*+*,J*0  #  i *9*: #(*>* ,(*C* ,*H*K*L*M#@%#@7#@>#@mn*O*R߁ * (*Uv H*X,*Z[NS.object.0 |}~*\#?GE(*a N*d,*f[NS.object.0 }*j*kML#?# (*n* *q,*s[NS.object.0  u*x*y*z*{*~* # g X #** #(** ,(** ,****#%#@7#@>#* e(** ****,****[NS.object.1[NS.object.0[NS.object.3[NS.object.2 *^]]#]--*-^``#`66*6^bb#b??*?^dd#d_$A85DDEB6-4E1C-4AD7-A211-B91B165AD220_$FBDBB86A-9FBC-4CCA-B4FC-77ADE08C4050_$5D460778-55DB-4E5F-8549-B8228F45E9F4? @Au*****J* #  րi ** #(** ,(** ,****#% #@Y#@X#@0mn**+߁ * +++#@>Ā)# Z{0.5, 0.5}(+ v H+ ,+[NS.object.0 |}~+#?`qPGE(+ N+,+S.object.0 }++ ML#?# (+#* +&,+([NS.object.0  u+++,+-+2+7#     ՀX+;+< #(+@* ,(+E* ,+J+M+N+O#%#@Y#@X#+Q e(+U* Ā+X+Y+Z+[,+]+^+_+`[NS.object.1[NS.object.0[NS.object.3[NS.object.2 Ɂ Ł с ?+d+e+f+g ^ ȁ # _{0.77614237490000004, 1}_{0.22385762510000001, 1}X{0.5, 1}?+o+p+q+r ^ ́ # _{1, 0.22385762510000001}_{1, 0.77614237490000004}X{1, 0.5}?+z+{+|+} ^ Ё # _{0.22385762510000001, 0}_{0.77614237490000004, 0}X{0.5, 0}?++++ ^ ԁ # _{0, 0.77614237490000004}_{0, 0.22385762510000001}X{0, 0.5}_$1C20A32A-5130-4D79-A57D-36E7831EC3ED_$B9AD386A-8049-417A-8C07-17F88BAE05D4 u+++++}?+ # ؁   ++ ہ ـ#(+* ڀ,(+* ܀,++++#@%% #@S#@S#@:n++߀* ߀+++#@>Ā)# Z{0.5, 0.5}(+ N+,+[NS.object.0 }++M#?# (+* +++,+[NS.object.1[NS.object.0  ? @Au+++++J+ #  i %++ #(+* ,(+* ,+,,,#?o%#@S@.#@S>F8F#?B=nhn,, ߀* , ,,#@>Ā)# Z{0.5, 0.5}(, N,,,[NS.object.0 } ,,M,#?# (, * ,#,,%[NS.object.0  u,(,),*,/%,4#   X,8,9 #(,=* ,(,B* ,,G,J,K,L#=dЀ%#@S@.#@S>F8F#,N e(,R* o,U,V,W,X,Y,Z,[,\,],^,_,`,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,{,|,},~,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---------- - - - - --------,---------- -!-"-#-$-%-&-'-(-)-*-+-,---.-/-0-1\NS.object.10\NS.object.76\NS.object.57\NS.object.80]NS.object.106\NS.object.38\NS.object.61\NS.object.42\NS.object.19\NS.object.23\NS.object.89[NS.object.0\NS.object.93\NS.object.74\NS.object.55]NS.object.105\NS.object.36\NS.object.17\NS.object.40\NS.object.21[NS.object.7\NS.object.87\NS.object.68\NS.object.91\NS.object.49\NS.object.72\NS.object.53\NS.object.34]NS.object.104\NS.object.15[NS.object.3\NS.object.85\NS.object.66\NS.object.70\NS.object.47\NS.object.28\NS.object.51\NS.object.32\NS.object.98]NS.object.103\NS.object.13\NS.object.79\NS.object.83\NS.object.64\NS.object.45\NS.object.26\NS.object.30\NS.object.96[NS.object.6\NS.object.11\NS.object.77]NS.object.102\NS.object.81\NS.object.58\NS.object.39\NS.object.62\NS.object.43\NS.object.24[NS.object.2\NS.object.94]NS.object.101\NS.object.75\NS.object.56\NS.object.60\NS.object.37\NS.object.41\NS.object.18\NS.object.22\NS.object.88[NS.object.9\NS.object.69\NS.object.92\NS.object.73]NS.object.100\NS.object.54\NS.object.35\NS.object.16]NS.object.109\NS.object.20[NS.object.5\NS.object.86\NS.object.67\NS.object.90\NS.object.71\NS.object.48\NS.object.52\NS.object.29\NS.object.33\NS.object.99\NS.object.14[NS.object.1]NS.object.108\NS.object.84\NS.object.65\NS.object.46\NS.object.27\NS.object.50\NS.object.31\NS.object.97\NS.object.12\NS.object.78[NS.object.8\NS.object.82\NS.object.59]NS.object.107\NS.object.63\NS.object.44\NS.object.25[NS.object.4\NS.object.95 ' / ? K [ c s ' ہ C S  [  k Á  Ӂ ; S   o ˁ  3 ; K g w   + 3 C _  w + ߁ G W _ #  o # ׁ ? O  W g  ρ s 7  O  k ǁ { / 7  G c  {(-5-6-7-8 ^  # _,{0.46512118623704479, 0.0021930824800647517}_-{0.47645077257030227, 0.00028026898572660388}_-{0.47645077257030227, 0.00028026898572660388}(-@-A-B-C ^  #  _+{0.45321162108001956, 0.023955091502037198}_+{0.45609151592907349, 0.010845809491102096}_+{0.45373160209443203, 0.022082336929046459}(-K-L-M-N^ # _+{0.45278163677963995, 0.027770703760376596}_*{0.45290163239835052, 0.02585789026603845}_+{0.45278163677963995, 0.027770703760376596}(-V-W-X-Y ^  # _){0.4168529486107132, 0.12264024424134541}_*{0.42722256999428598, 0.12068737182565989}_*{0.42722256999428598, 0.12068737182565989}?-a-b-c-d ^  #  _*{0.38378415602105526, 0.13062198431981392}_*{0.40613334000590118, 0.12461314611770462}_*{0.39598371058996445, 0.12732713803899065}(-l-m-n-o^  #  _*{0.36095498956136701, 0.13965527108365156}_*{0.37253456676693819, 0.13536896649948027}_*{0.36095498956136701, 0.13965527108365156}(-w-x-y-z ^  # _+{0.27355818060049319, 0.061490300804546587}_+{0.28238785821061352, 0.069492070343688775}_+{0.28238785821061352, 0.069492070343688775}(---- ^  #  _+{0.21795021096303097, 0.083983385141109007}_+{0.26062865268442797, 0.059968061793345559}_+{0.25019903349149986, 0.065706502276359935}---- ^ " # ! _*{0.15225260971898727, 0.13835335613986119}_*{0.18810130080877369, 0.10583552673611314}_*{0.16121228258271075, 0.13018133618499256}(----^ & $# % _){0.15458252464895109, 0.1624187531393089}_*{0.14956270793289175, 0.15138252030810151}_){0.15458252464895109, 0.1624187531393089}(---- ^ * (# )_*{0.18464142713595191, 0.27468388021538409}_*{0.19908089992079192, 0.25722820523825657}_*{0.19908089992079192, 0.25722820523825657}(----^ . ,# - _*{0.16027231690281118, 0.31317048889989407}_){0.17154190542671335, 0.2934214406756282}_*{0.16027231690281118, 0.31317048889989407}(---- ^ 2 0# 1_+{0.041906638679714552, 0.30893425796740703}_+{0.054246188137119421, 0.30937490610222834}_+{0.054246188137119421, 0.30937490610222834}(---- ^ 6 4# 5 _*{0.01398765805971919, 0.36252307999988498}_+{0.030757045774522988, 0.31665561505711742}_+{0.026787190722181248, 0.32834280536021992}---- ^ : 8# 9 _-{-0.0014617778492682625, 0.44682707997547827}_*{0.00539797168702001, 0.39799525485300347}_-{0.00027815862203517188, 0.43452899112182791}(----^ > <# = _+{0.016367571164145729, 0.46392222466047917}_+{0.0050879830053510182, 0.4587946827280126}_+{0.016367571164145729, 0.46392222466047917}(---- ^ B @# A_*{0.11037413878899416, 0.52992931231064966}_*{0.11009414901200282, 0.50752636054711886}_*{0.11009414901200282, 0.50752636054711886}(----^ F D# E _*{0.11672390694576247, 0.57484537787141665}_*{0.11245406284664426, 0.55238233772586476}_*{0.11672390694576247, 0.57484537787141665}(---- ^ J H# I_+{0.023857297698664546, 0.64853376368995008}_+{0.033416948655940908, 0.64121299581371372}_+{0.033416948655940908, 0.64121299581371372}(....  ^ N L# M _+{0.036416839123705469, 0.70778090836274765}_+{0.020067436074388649, 0.66112227972336912}_+{0.023947294412697485, 0.67249901338602935}.... ^ R P# Q _+{0.078615298370260128, 0.78037768857456469}_){0.0531862268385093, 0.73969785394628496}_*{0.07222553167392165, 0.77015264890064217}(....^ V T# U _*{0.10252442539834362, 0.78248078194530302}_+{0.090814852939169327, 0.78532496536096796}_*{0.10252442539834362, 0.78248078194530302}(.'.(.).* ^ Z X# Y_*{0.21755022556732906, 0.77299683231630711}_*{0.20287076154506786, 0.75593173182231677}_*{0.20287076154506786, 0.75593173182231677}(.2.3.4.5^ ^ \# ] _*{0.25115899844118456, 0.80239006585495842}_){0.2340096246004639, 0.78827931081033853}_*{0.25115899844118456, 0.80239006585495842}(.=.>.?.@ ^ b `# a_*{0.22714987506417564, 0.91925195415564731}_){0.22937979364521394, 0.9076348669649027}_){0.22937979364521394, 0.9076348669649027}.H.I.J.K ^ f d# e _*{0.27405816234512065, 0.95555535162672423}_){0.23245968119211888, 0.9310392917621183}_*{0.24263930951273327, 0.93702810050355401}.S.T.U.V ^ j h# i _*{0.35455522323013605, 0.98624048537882902}_*{0.30795692463086005, 0.97115830149153459}_*{0.34298564565945749, 0.98253503515419494}(.^._.`.a^ n l# m _*{0.37422450506377897, 0.97210970087353532}_){0.3671847620994248, 0.98200425444634198}_*{0.37422450506377897, 0.97210970087353532}(.i.j.k.l ^ r p# q_*{0.45620151191289149, 0.89048964862821733}_*{0.43385232792804562, 0.88675415421257286}_*{0.43385232792804562, 0.88675415421257286}(.t.u.v.w^ v t# u _*{0.50200983935565624, 0.89150113639223905}_*{0.47897068056322445, 0.89173147518998652}_*{0.50200983935565624, 0.89150113639223905}(.... ^ z x# y_){0.5569578330902103, 0.99591471488422478}_*{0.55121804266188745, 0.98535918910918607}_*{0.55121804266188745, 0.98535918910918607}?.... ^ ~ |# } _*{0.59601640698050462, 0.99694623210892019}_({0.5687674018983101, 1.0016531553672392}_*{0.58057697070640979, 0.99958010618751147}?.... ^ # _*{0.64719453836056784, 0.98468820217661734}_){0.6113058487312113, 0.99431235803032902}_*{0.62696527697294224, 0.99010617128885248}(.... ^ # _*{0.69731270844202098, 0.96581043549165724}_*{0.66677382348017777, 0.97783812662621272}_*{0.68565313415730944, 0.97019688737919707}(....^ # _){0.7036424773290042, 0.94175505322254638}_({0.704642440818259, 0.95419334830091274}_){0.7036424773290042, 0.94175505322254638}(.... ^ # _*{0.69191290560004481, 0.80779802023685665}_){0.6932228577709687, 0.82323071968594064}_){0.6932228577709687, 0.82323071968594064}?.... ^ # _){0.6475145266771295, 0.79893498388874562}_*{0.67837339995553414, 0.79632113927082804}_*{0.66293396368143931, 0.79763306894495523}(....^ # _*{0.63736489726119272, 0.82796768713527025}_*{0.63606494472516151, 0.81250494349517566}_*{0.63736489726119272, 0.82796768713527025}....^ # _*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}_*{0.63736489726119272, 0.82796768713527025}(.... ^ # _){0.63488498780784086, 0.9285856828295902}_*{0.64589458582453674, 0.92466992326788244}_*{0.64589458582453674, 0.92466992326788244}?.... ^ # _){0.60553605939821098, 0.9379995293462281}_*{0.62417537883792129, 0.93299216417780373}_*{0.61276579542552356, 0.93604665693054268}(....^ # _*{0.59098659062955294, 0.94079363911020886}_*{0.59817632811729526, 0.93924135590799751}_*{0.59098659062955294, 0.94079363911020886}(//// ^ # _*{0.53833851292028501, 0.84219861894393233}_*{0.54365831868312076, 0.85167255384259133}_*{0.54365831868312076, 0.85167255384259133}(//// ^ # _*{0.48612041951139673, 0.83932439133725667}_*{0.52800889007628238, 0.83662041414630772}_*{0.51714928658297477, 0.83745163676426615}(//// ^ # _*{0.41509301286962469, 0.82725664128135401}_({0.455771527612512, 0.83639007534856002}_*{0.42629260394927904, 0.82987048589927148}(/$/%/&/'^ # _*{0.39694367553964921, 0.84124721956193171}_*{0.40345343785469823, 0.83176326993293592}_*{0.39694367553964921, 0.84124721956193171}(///0/1/2 ^ # _*{0.32320636784199652, 0.91409436803217003}_*{0.34109571466476579, 0.92088435520055345}_*{0.34109571466476579, 0.92088435520055345}(/:/;/ <# =_*{0.77062003183929417, 0.29870921829348435}_*{0.77656981460036056, 0.28946562219257294}_*{0.77656981460036056, 0.28946562219257294}0000 ^ B @# A _*{0.79306921217306559, 0.34493721352837847}_*{0.77062003183929417, 0.31057667374265019}_*{0.77656981460036056, 0.31981025511322481}(0000 ^ F D# E _*{0.81951824646385651, 0.41310748293130828}_*{0.80679871088053479, 0.37232750099965994}_*{0.81632836293313338, 0.40229157416751155}(0000^ J H# I _){0.8399974987237957, 0.42220085807716701}_*{0.82884790581860424, 0.42093900205472407}_){0.8399974987237957, 0.42220085807716701}(0000 ^ N L# M_*{0.93883389000174511, 0.44913046795295342}_){0.9356140075663445, 0.42978200894216151}_){0.9356140075663445, 0.42978200894216151}(0000^ R P# Q _*{0.94223376586521168, 0.48761707663746345}_*{0.94156379032741078, 0.46844888277273483}_*{0.94223376586521168, 0.48761707663746345}(0000 ^ V T# U_'{0.838107567729104, 0.5224082498276762}_({0.84851718765224693, 0.518913108940116}_({0.84851718765224693, 0.518913108940116}(0000 ^ Z X# Y _*{0.82600800950912034, 0.57333315359055237}_*{0.83071783754351058, 0.53167187538926142}_){0.8295778791657602, 0.54260796091710028}(0000 ^ ^ \# ] _*{0.80183889197383063, 0.64227455722941962}_){0.81750831985045402, 0.6036477423201938}_*{0.80591874300999045, 0.63172904618471781}(0001^ b `# a _*{0.81253850130885763, 0.66206366437503283}_){0.80443879704589327, 0.6542421599819539}_*{0.81253850130885763, 0.66206366437503283}(11 1 1 ^ f d# e_*{0.90780502293016707, 0.75747400029419154}_*{0.89679542491347108, 0.74644778219332097}_*{0.89679542491347108, 0.74644778219332097}?1111 ^ j h# i _*{0.94757357089783245, 0.73545160828346101}_*{0.92558437376911828, 0.75747400029419154}_*{0.93656397288113657, 0.74644778219332097}(111 1!^ n l# m _*{0.93656397288113657, 0.70661919964367337}_*{0.94757357089783245, 0.71764541774454382}_*{0.93656397288113657, 0.70661919964367337}(1)1*1+1, ^ r p# q_*{0.87035639025757294, 0.61216026310651528}_*{0.86271666919966594, 0.63362183021838225}_*{0.86271666919966594, 0.63362183021838225}(14151617^ v t# u _*{0.87975604705656851, 0.56725421227608519}_*{0.87597618506718522, 0.58991754702837407}_*{0.87975604705656851, 0.56725421227608519}(1?1@1A1B ^ z x# y_){0.99153196588547565, 0.5306303434342291}_*{0.98010238320329268, 0.53407541067010511}_*{0.98010238320329268, 0.53407541067010511}(1J1K1L1M ^ ~ |# } _){1.0003016456862406, 0.47238467179511651}_*{0.99948167562505175, 0.52038527429963277}_*{0.99998165736967914, 0.50846774519878279}1U1V1W1X ^ # _*{0.98601216742478903, 0.38665858011169063}_*{0.99643178698282442, 0.43506978656001777}_*{0.98862207213174413, 0.39849599136984598}(1`1a1b1c^ # _*{0.96400297102628962, 0.37669392342652608}_){0.9760725303415958, 0.37784561741526368}_*{0.96400297102628962, 0.37669392342652608}(1k1l1m1n ^ # _({0.8526970350373323, 0.3457183624946526}_*{0.86077674003051141, 0.36719995906719333}_*{0.86077674003051141, 0.36719995906719333}(1v1w1x1y^ # _*{0.83142781162088153, 0.30652070795622638}_*{0.84279739649370922, 0.32577903439398664}_*{0.83142781162088153, 0.30652070795622638}(1111 ^ # _*{0.89355554320828534, 0.20545204939674822}_){0.8872857721306574, 0.21550683865494444}_){0.8872857721306574, 0.21550683865494444}(1111 ^ # _*{0.86182670169422892, 0.15470741077993533}_*{0.89278557132155911, 0.19254306199255011}_){0.8853958411359657, 0.18326942170062813}1111 ^ # _+{0.79622909679911069, 0.099886776916024933}_*{0.83450769916778633, 0.12973067331983434}_*{0.80587874447042007, 0.10742786885967209}(1111^ # _){0.7727499540714069, 0.10649649893834515}_+{0.78279958713841813, 0.099496202432887815}_){0.7727499540714069, 0.10649649893834515}(1111 ^ # _*{0.66822377053959747, 0.15527825040913573}_*{0.68754306515200103, 0.16621433593697463}_*{0.68754306515200103, 0.16621433593697463}(1111^ # _*{0.62695527733804968, 0.13777250178032399}_*{0.64802450805664935, 0.14535365264531852}_*{0.62695527733804968, 0.13777250178032399}(1111 ^ # _+{0.61014589108367567, 0.020550083187508675}_*{0.6118058304758387, 0.032537715400716691}_*{0.6118058304758387, 0.032537715400716691}1111 ^ # _,{0.55382794736884255, 0.0022832150530963944}_*{0.60097622588720867, 0.01098601571581808}_,{0.58908665999996856, 0.0088328486933955518}(1111 ^ # _-{0.47834070356499392, 0.00024021006437923085}_,{0.51666930410813228, -0.001061704879411069}_+{0.479290668879786, 0.00030029844640039717}(1111^ # _-{0.47645077257030227, 0.00028026898572660388}_-{0.47740073788509435, 0.00024021006437923085}_-{0.47645077257030227, 0.00028026898572660388}_$8F749B3A-AFEE-4B70-B532-2D17E36AF56D_$33F1829C-2001-4010-8A3D-3C7BD39D27B2? @Au11111J1 #  i %22 #(2* ,(2 * ,2222#@9v$%#@Ā)# Z{0.5, 0.5}(2& ĀN2),2+[NS.object.0 } 2/20M,#?# (23* ǀ26,28[NS.object.0  u2;2<2=2B%2G# Ɂ   X2K2L ́ ʀ#(2P* ˀ,(2U* ̀,2Z2]2^2_# #  "  &  3E3F  #(3J* ,(3O* , 3U3V3W3Y3Z%#@O #@Z@#@`#_$30676E28-992D-4476-BAB5-B7AE8A2DB3D2Zbcbio copy3`* Z3b\ 3e^3f`3gf3j3k3l3m3n[NS.object.2[NS.object.1[NS.object.0ā !   ijk3pmnO)0.003921568627 0.3411764706 0.6078431373_NSParagraphStyle(3x'n3z #  $3~Ebcbio3^3`33fbd[NS.object.2[NS.object.1[NS.object.0 %|}~3#@JŁ_$D4F32D3D-9DD4-426A-9F94-AC02694FE9FE3с ((3* ),3с +(3* ,,_$2ADD5351-DC21-4986-AA79-7448687E4CB83с /(3* 0,^{-2317, -1057}3с 3(3* 4,_$9B2C71C5-C356-41D3-9EB5-74D3B4F46DEC./33VMSPage333333UV33W_MSPage\MSLayerGroup]_MSLayerGroup]MSStyledLayer^_MSStyledLayer]MSModelObject_$450D9862-8CDD-4BDB-8754-F4BFF40F8521./33^MSDocumentData3333^MSDocumentData__MSDocumentData]MSModelObjectZMSArchiver33Troot"+5:? 5<Ngtvxz} #+4=ELZceglnwy{$&/CL`u7R`iknwy{)PU   ( 7 M V n z !!!! ! !!!!! !)!;!D!V!i!w!!!!!!!!!!!!!!!"""+"A"U"Z"d"o"q"s"u"w"y"""""""""""""""# ##$#1#?#H#P#Y#b#p#y#{#}##########$$$$($*$,$.$/$0$2$3$5$7$8$9$:$<$>$@$U$W$Y$[$\$e$g$i$n$p$y${$}$$$$$$$$$$$% % % %%%%%)%5%A%C%E%G%%%%%%%%%%%%%%%%%%%%%%%& &&&&&&&!&&&(&1&3&5&:&<&U&^&`&a&j&s&|&&&&&&&&&&&&&&&&'' '''"'+'-'.'0'E'I'O'T'Z'\'e'n'w'''''''''''( (()(6(D(M(g(r((((((((((() ))-)8):)<)E)N)O)d)f)o)x))))))))))* ** *8*C*[*s*********++!+&+2+E+G+H+I+R+T+V+X+Y+[+]+^+_+a+b+d+e+f+o+x++++++++++++++++++++++,,,,, ,!,#,,,.,0,E,Q,],i,u,w,y,{,},,,,,,,,,,,,,,,,-- -- ---;-I-j-k-m-o-q-z-|-}-------------------....$.1.?.f.o.......///!///V/_/l////////0=0?0@0B0K0M0N0P0R0T0U0V0X0Y0Z0\0^0_0`0b0w0y0{0}0~0000000000000000001111111&1(1*131?1A1C1\1e1g1h1j1s1u1w111111111111111112A2C2D2E2N2P2R2T2U2W2Y2Z2[2]2^2`2a2b2k222222222222222222222222233 3 33#3/3;3G3S3U3W3Y3[3]3~3333333333333333333333344444!4*4,4-4T4{4444444555^5_5a5j5l5n5p5q5r5t5u5w5y5z5{5|5~55555555555555555555555666:6S6U6W6Y6b6d6f6s66666666666667777777 7 7 7777&7(7*7,7-76787:7?7A7J7L7N7S7U7n7w7y7z7777777777777777788 8 8 8888#8/81838T8V8X8a8j8k8t8v8x888888888888888889999999#9%9'9)9*9395979<9>9G9I9K9P9R9k9t9v9w9999999999999999999::!:":$:&:(:1:3:4:U:V:X:Z:\:e:g:h:::::::::::::::::;;y;{;|;~;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<<<<"<.> >>>>">+>8>:>;>=>F>H>J>_>k>w>>>>>>>>>>>>>>>>>>>>>???"?#?%?'?)?2?4?5?V?W?Y?[?]?f?h?i???@9@;@<@>@G@I@J@L@O@Q@R@S@U@V@W@Y@[@\@]@_@t@v@x@z@{@@@@@@@@@@@@@@@@@@AA6A8A:A<A>A@ABA[AdAfAoApArA}AAAAAAAAAAAAAAAAAAABBBBB'B(B1B3B5B>BJBLBNBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCC!C#C$C-C6C?CLCNCOCQCZC\C^CsCCCCCCCCCCCCCCCCCCDDD$DEDFDHDKDMDVDXDYDtDDDDDDDDDDDEEE/E0E2E5E8EAEDEEE`E{EEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGGGG!G*G,G-G6G?GHGUG|GGGGGGGGGGGGGGGGGHH H H.H0H3H<HEHFH[H]HfHoHxHHHHHHHHHHIIIII&I)I*I-I0I2I3I4I7I8I9I<I>I?I@IBIWIZI]I_I`IiIlInIsIuI~IIIIIIIIIIIIIIIIIIJJJ!J*J+J.J9JBJEJGJPJ\J^JaJJJJJJJJJJJJJJJJJJJKHKIKRKUKXKYKZK\K]K`KaKdKeKfKiKkKmKKKKKKKKKKKKKKKKKKKKKKLLLLLLLMMMMN NN$N1N>NKNXNeNqN~NNNNNNNNNOO OO'O4OAOOO\OhOuOOOOOOOOOOPPPP,P9PFPRP_PlPzPPPPPPPPPPQ QQ#Q0Q=QJQWQcQpQ}QQQQQQQQQRR RR'R4RARNR[RhRtRRRRRRRRRRSSSS+S8SESRS^SkSnSqStSwSzS}SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTT T TTTTTTT"T%T(T+T.T1T4T7T:T=T@TCTFTITLTOTRTUTXT[T^TaTdTfTiTlToTrTuTxT{T~TTTTTTTTTTTTTTTTTTTTTTTTTTTTUUOUUUUUUUUUUVV@VaVbVdVgVjVsVvVwVVWW!W"W$W'W*W3W6W7WcWWWWWWWWWWX!XNX{XXXXXXXXXY Y9YZY[Y]Y`YcYlYoYpYYYZZZZ!Z$Z-Z0Z1Z_ZZZZZZZZZZZ[![N[{[[[[[[[[[\ \7\X\Y\[\^\a\j\m\n\\\]]]]]](]+],]Y]]]]]]]]]]^^E^s^^^^^^^^^__3_T_U_W_Z_]_f_i_j___`````!`*`-`.`\``````````aaIavaaaaaaaaabb4bUbVbXb[b^bgbjbkbbbcccccc(c+c,cZccccccccccddGdtdddddddddee3eTeUeWeZe]efeiejeeeffffff$f'f(fUffffffffffgg>gjggggggggggh'hHhIhKhNhQhZh]h^hhhiii i iiiiiIiuiiiiiiiiijj3j`jjjjjjjjjjkk?k@kBkEkHkQkTkUkkkkkkllllll?ljllllllllllm'mTmumvmxm{m~mmmmmnn3n4n6n9n<nEnHnInunnnnnnnnooo0o\ooooooooooppEpfpgpiplpopxp{p|ppqq$q%q'q*q-q6q9q:qgqqqqqqqqqqr$rQr~rrrrrrrrrss;s\s]s_sbsesnsqsrssstttt t#t,t/t0t]ttttttttttuuHuuuuuuuuuuuvv1vRvSvUvXv[vdvgvhvvvwwwwww"w%w&wSwwwwwwwwwwxx<xixxxxxxxxxxy'yHyIyKyNyQyZy]y^yyyzzzz zzzzzHzuzzzzzzzzz{{3{`{{{{{{{{{{||>|?|A|D|G|P|S|T||||}}}}}}}}B}n}}}}}}}}}}~+~X~y~z~|~~~~~~~679<?HKLy 8e%Stuwz}2358;DGHu2_Ijkmps|()+.1:=>k)U?`acfiruv!$'034aLy 8YZ\_bkno #,/0]Gt1RSUX[dgh"%&S>k)JKMPS\_` Kx5a>?ADGPST<g#Opqsvy -.036?BCp-ZEfgilox{|$%'*-69:g%R<]^`cfors #,/0]Gt0QRTWZcfg!$%R~;g&GHJMPY\] Gt2_?@BEHQTU Gv ;krtux %FHJMPRktvbclorstvwz{~ "+.0s ,/258;>ADGILORUX[|} ABDGJSVW Gv3`?@BEHQTU@m+Xyz|679<?HKLy5aLmnpsv *+-03<?@l+Y$KTbo}7R`ilox{}#B\w*4HMZacdgpstwz !*1JLNPY\^o{ 0QSTW`cdghknqtwxy|$'*-12;HQ^lz !#,8:=bdgjs|}./2;>ADEFHIKMNOPSUWlortu~ *,.13PY[^ajkvMNQZ]`cdeghjlmnortv"$AJLOR[\gŽ—šœ©µ$&'*367:=?@ADEFHJKLNcfikluxzÁÊÍÏÔÖïøúû '0258ABMt}ĀĂċėęĜĹĻľ:<>GPQZ]_htvy!$&+-69;@B[dfgpyƂƏƒƓƕƞơƣƸ!#%.01X}~ǁǃDžLJǐǒǓǺABEGIKTVW~ȥ')*-69:=@BCDGHIKMNOQfilnox{}ɂɄɍɐɒɗəɲɻɽɾ *358;DEPwʀʃʅʎʚʜʟʼʾ =?AJST]`bkwy|$').09<>CE^gijs|̡̖̘̤̦̻̅̒̕!*,-NOQSU^`a͇͉͔͕͂̓͒ͅͶͷ͹ͻͽ>΍ΎΑΚΝΠΣΤΥΧΨΪάέήίβδζ "#,5>[]_bdρϊόϏϒϛϜϧ dfgjsvwz}ЀЁЄЅІЈЊЋЌЎУЦЩЫЬеикп ;>@BEHJgpruxстэѴѽ 1:=?HTVYz|~҇ҐґҚҝҟҨҴҶҹ "#%()*,-/01:ORUWXadfkmvy{ӀӂӛӤӦӧӰӹ(*-036[\_acenpqԘԽԾ #%')245\ՁՂՅՇՉՋՔՖ՗վ gijmvyz}րւփքևֈ։֋֍֎֏ָֻֽ֑֦֮֩֬֯>ACEHKMjsux{ׅׄא׷ 4=@BKWY\}؁؊ؓؔ؝ؠآثطعؼ"%&(+,-/0234=RUXZ[dginpy|~كمٞ٧٩٪ٳټ+-0369Z[]_ajlmڎڏڑړڕڞڠڡ 0W~ !*-/46?BDIKdmopy܂܋ܷܰܳܵܺܽܿ)257@LNQnpsu~ݦݯݲݴݽ)+.yzރކމފދލގޑޒޕޖޗޚޜޞ޳޶޹޻޼ &3679BEG\ht߀ߌߎߑߔߗߚ߻߼߾1247:CFGb} #&/23Nir"%&'*+-/01258:ORUWXadfkmvy{ &'2Ybegp|~PRSV_bcfiklmpqruwxy{$&(+.0MVX[^ghs  #nox{~ (+,.7:<"/=JWdq~ &3@MZgu+8ER_lx"/<IVcp} &3@MZgt)6CQ^kx !$'*-0369<?BEHKNQTWZ]`cfilorux{~Cs6d$EFHKNWZ[ Er0]~?@BEHQTU Cp-Yz{}89;>AJMN{ 9g'Uvwy|:;=@CLOP~ >k)Vwxz}89;>AJMN| =i(Uvwy|457:=FIJw4`Ijkmps|()+.1:=>k(U@abdgjsvw!$'034aIv  4 U V X [ ^ g j k         ! $ % R ~           : g           % F G I L O X [ \            F s         0]~<=?BENQR =j&Stuwz}2358;DGHu3^Ijkmps|'(*-09<=j(U?`acfiruv!"$'*367d Mz 7XY[^ajmn(+,ZGu3TUWZ]fij$'(T>k ) J K M P S \ _ `   !! ! !!!!!!K!w!!!!!!!!!""4"a""""""""""##@#A#C#F#I#R#U#V#####$$$$$$$A$n$$$$$$$$$%%-%Z%{%|%~%%%%%%%&&<&=&?&B&E&N&Q&R&&&&&&''' '''<'i''''''''''('(S(t(u(w(z(}((((())2)3)5)8);)D)G)H)u)))))))****3*`**********++K+l+m+o+r+u+~++++, ,*,+,-,0,3,<,?,@,m,,,,,,,,,,-*-W----------..?.`.a.c.f.i.r.u.v...///!/$/'/0/3/4/^//////////00E0q00000000011.1O1P1R1U1X1a1d1e1112 2 22222!2"2O2|2222222223 3:3g33333333334%4F4G4I4L4O4X4[4\4445555 5 5555G5t5555555556616^666666666677<7=7?7B7E7N7Q7R777777888 888=8i88888888889%9R9s9t9v9y9|99999::1:2:4:7:::C:F:G:t::::::::;;;0;];;;;;;;;;;<'>T>>>>>>>>>>??@?a?b?d?g?j?s?v?w??@@#@$@&@)@,@5@8@9@i@@@@@@@@@@A-A]AAAB6B8B9B<BEBHBIBLBOBQBRBSBVBWBXB[B]B^B_BaBvByB|B~BBBBBBBBBBBBBBBBBBC C CCCCC3C<C>CACDCMCNCYCCCCCCCCCCCCCCCCCCDDD DTDUD^DaDdDeDfDhDiDlDmDpDqDrDuDwDyDDDDDDDDDDDDDDDDDDDDDEEEEEEE E"EeEqE}EEEEEEEEEEFFFF!F$F'F*F-F0F3F6F9F;F>FAFDFGFJFMFnFoFqFtFwFFFFFGG3G4G6G9G<GEGHGIGwGGGGGGGHH H H9HhHHHHHHHHHHI%IRIsItIvIyI|IIIIIJJ1J2J4J7J:JCJFJGJtJJJJJJJKKKK2K_KKKKKKKKKKLLJLkLlLnLqLtL}LLLLMM(M)M+M.M1M:M=M>MkMMMMMMMMMMN'NSNNNNNNNNNNOO>O_O`ObOeOhOqOtOuOOOPPPP"P%P.P1P2P^PPPPPPPPPPQQKQzQQQRRqRRRRRRRRRSS S S SSSSSSSSSS S!S"S#S8S;S>S@SASJSMSOSTSVS_SbSdSiSkSSSSSSSSSSSSSSTTTTT.T7TCTLTXT[T^TaTdTgToTTTTTTTTTTTTTTTTUUU UU%U.U5U>U@UCUFUQUZUaUfUoUtU}UUUUUUUUUUUUUVV V VVV-V4V=VZVfVoV{VVVVVVVVVVVVVVW WWWW$W7W<WOW`WiWlWoW}WWWWWWXX XX)X5XBXPX_XmXzXXXXXXXXXXXXXXXXXXYYYY YY5Y>YPYeYwYYYYYYZ;Z=Z>ZAZJZMZNZQZRZUZXZ[Z^ZaZbZcZeZhZiZkZmZnZpZqZsZtZZZZZZZZZZZZZZZZZZZZ[[[[ [ [[#[,[/[2[5[9[V[X[a[d[m[n[w[[[[[[[[[[[[[[\\\\$\-\.\7\:\<\E\Q\S\V\\\\\\\\\\\\\\\\\\\\\\\\\\\\]] ] ]]]]3]5]>]A]J]K]T]]]]]]]]]]]]]]]]]]^ ^^!^-^9^;^>^A^D^G^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^____ _)_+_,_5_>_G_`_b_d_f_o_r_t_________`` ``````````` `"`#`$`&`;`>`A`C`D`M`P`R`W`Y`b`e`g`l`n``````````````````aaaa%a'a(a*a3a6a8aAaMaOaRasauawaaaaaaaaaabbbb bbbbbbb!b"b#b%b&b(b)b*b3bHbKbNbPbQbZb]b_bdbfbobrbtbyb{bbbbbbbbbbbbbbbbc cc!c#c&c)c,c/cPcQcScUcWc`cbccccccccccccccccccccccccccd&dMddddddddddddddddddddddddddddeeeeeeee3e<e>e?eHeQeZe{e~eeeeeeeeeeeeeeeeeeeeeeeff!f#f,f5f6f?fBfDfMfYf[f^ffffffffffffffffffffffffgg g ggggg g%g'g@gIgKgLgUg^gggtgwgxgzgggggggggggggggghhh hhh0h1h3h5h7h@hBhChdhehghihkhthvhwhhhhhhhhhhi ioipisi|iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjj j9j;j=j?jHjKjMjZjfjrjujwjzjjjjjjjjjjjjjjjjjjjjkkkkkk&k)k+k0k2k;k>k@kEkGk`kikkklkuk~kkkkkkkkkkkkkkkkllll llll&l(l+lLlNlPlYlblclllolqlzllllllllllllllllllmmmm m!m$m'm)m*m3m6m8m=m?mHmKmMmRmTmmmvmxmymmmmmmmmmmmmmmmmmnnnn)n*n,n.n0n9n;n<n]n^n`nbndnmnonpnnnnnnnnnnnnnnnnno&ooooooooooooooooooooooooooooooooooop pppp!p*p3pTpWpYp[p^p`piplpnpwppppppppppppppppppqqqqqqq&q2q4q7qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrr"r$r%r.r7r@rMrPrQrSr\r_rarvrrrrrrrrrrrrrrrrrs s s ssssss=s>s@sBsDsMsOsPsqsrstsvsxsssssstTtVtWtZtctftgtjtmtotptqtttutvtxtzt{t|t~tttttttttttttttttttttuu+u.u0u2u5u8u:uSu\u^uguhukuvuuuuuuuuuuuuuuuuuuuvvvvv$v%v.v1v3v<vHvJvMvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvwwww'w)w*w3w<wEwRwUwVwXwawdwfw{wwwwwwwwwwwwwwwwwx x&x/xPxQxSxVxYxbxexfxxxxxxxxxxxxyyy<y=y?yByEyNyQyRymyyyyz.z/z2z;z>zAzDzEzFzIzJzLzNzOzPzQzTzWzYznzqztzvzwzzzzzzzzzzzzzzzzz{{{{ { {{'{0{2{;{<{?{J{S{V{X{a{m{o{r{{{{{{{{{{{{{{{|A|C|D|G|P|S|T|W|Z|\|]|^|a|b|c|f|h|i|j|l||||||||||||||||||||||}}}}}}!}:}C}E}N}O}R}]}f}i}k}t}}}}}}}}}}}}}}}}~1~2~;~>~A~B~C~E~F~I~J~M~N~O~R~T~V~k~n~q~s~t~}~~~~~~~~~~~~~~~~~~~~~~~ '4ANZgt*8EQ^kx"/;HUcp} &3@LYfs*7DQ]kx!.;GTWZ]`cfilorux{~  #&),/258;>ADGJMORUX[^adgjmpsvy|6f'HIKNQZ]^  Jw5b ABDGJSVW Ft3`=>@CFORS >j*Xyz|9:<?BKNOAo.[|}:;=@CLOP~ ?m,Yz{}9:<?BKNO|   :f#Opqsvy -.036?BCp.ZEfgilox{|$%'*-69:f$O| 9Z[]`clop!*-.ZAm*KLNQT]`a   Ly 6c ABDGJSVWBo-Z{|~78:=@ILMz  8e!Noprux -.036?BCp-ZEfgilox{|#$&),589g'S=^_adgpst!$-01^Jw 8YZ\_bkno ),-ZDp.OPRUXade "#P}:f$EFHKNWZ[  Fs1^>?ADGPSTBo,Yz{}78:=@ILMz  8e#Pqrtwzƒ†‡´/0258ADErß0]ĊīĬĮıĴĽFghjmpy|}Ū#$&),589fƓ!LwǘǙǛǞǡǪǭǮ4UVX[^gjkȘ$'(UɁɮ?lʍʎʐʓʖʟʢʣ*KLNQT]`aˎ˻   Ly̦ 7d͈͎͚͆͋͗͛ͅ!BCEHKTWX΄αBoϜϽϾ,Yz{}ЀЃЌЏАл679<?HKLyѦ  7cҏҰұҳҶҹ LmnpsvӂӃӱ ,-/25>ABnԜ,YՆէըժխհչռսDefhknwz{֩$%'*-69:iז,[؉تثحذسؼؿ Pwٞ   !"$9<?ABKNPUW`cejlڅڎڐڑښڣڬ !#,8:=^`cluvۂۄۍۙۛ۞  #&)+,58:?AJMOTVoxz{܄܍ܖܣܦܧܩܷܲܵ*7DP]iu݂ݎݛݧݳݶݹݼݿ  Ixާ <jߋߌߎߑߔߝߠߡ+LMORU^ab  Kx 6c!BCEHKTWX Co,Xyz|679<?HKLy  6cLmnpsv6] 6 !#@BKNWXaj%&/24AMY\^a  !:CEFOXa~ !$stw $=?ACLOQ^jvy{~ !*-/46?BDIKdmopy*,/PRT]fgpsu~%(+-.7:<ACLOQVXqz|}  -.024=?@abdfhqst*%.7X[]_bdmpr{ !*68;&()2;DQTUW`cez  ABDFHQSTuvxz|LMPY\_bcdfgiklmnqsu%(*7CORTW "$=FHIR[d)+-6?@ILNWceh%(*/1JSUV_hq~   :;=?AJLMnoqsu~^`admpqtwyz{~1468;=FIKT`be~gijktwz}~ *-.09<>S_kw!*,-NOQSU^`a1347@CDGJLMNQRSUWXY[psvxy  09;DEHS\_ajvx{ %'*uv"/235>ACXdp| -.036?BC^y     " + . / J e n         ! " # & ' ) + , - . 1 4 6 K N Q S T ] ` b g i r u w | ~                    ' 0 3 5 > J L O p r u ~              ! $ - 0 1 4 7 9 : ; > ? @ C E F G I ^ a d f g p s u z |                     " + , / : C F H Q ] _ b              "#&'*+,/13HKNPQZ]_dforty{+7DQ^ly".;HUbo| %2@MZgt)6CP^kx!.:HUbo| $147:=@CFILORUX[^adgjmpsvy|  !$'*,/258;>ADGJMPSVY\_behknqtwz}Cdegjmvyz%&(+.7:;i'T?`acfiruv!$'034b#Q=^_adgpst #,/0]  G t         !!5!V!W!Y!\!_!h!k!l!!!""""""("+","\""""""""""##L#z#########$ $8$Y$Z$\$_$b$k$n$o$$$%%%%% %)%,%-%[%%%%%%%%%%&&J&x&&&&&&&&&' '6'W'X'Z']'`'i'l'm'''((((((((+(,(Y(((((((((())C)p)))))))))**,*M*N*P*S*V*_*b*c***+ + + +++++ +M+z+++++++++, ,7,d,,,,,,,,,,-"-C-D-F-I-L-U-X-Y---..... ....C.p.........//,/Y/z/{/}///////007080:0=0@0I0L0M0z000000011 1 171b111111111122J2k2l2n2q2t2}222233(3)3+3.313:3=3>3k33333333334)4V444444444455@5a5b5d5g5j5s5v5w555666!6$6'6063646a666666666677L7y7777777778 878X8Y8[8^8a8j8m8n888999999&9)9*9W9999999999::B:o::::::::::;+;L;M;O;R;U;^;a;b;;;< < < <<<<< ">C>D>F>I>L>U>X>Y>>>????? ????D?r?????????@@0@\@}@~@@@@@@@@AA;A<A>AAADAMAPAQA~AAAAAABB B BB;BhBBBBBBBBBBC'CTCuCvCxC{C~CCCCCDD6D7D9D<D?DHDKDLDyDDDDDDDEE E E7EdEEEEEEEEEEF!FMFnFoFqFtFwFFFFFG G,G-G/G2G5G>GAGBGoGGGGGGGGGHH-HZHHHHHHHHHHIICIdIeIgIjImIvIyIzIIJJ"J#J%J(J+J4J7J8JeJJJJJJJJJJK#KPK}KKKKKKKKKLL;L\L]L_LbLeLnLqLrLLLMMMM!M$M-M0M1M_MMMMMMMMMMNNLNyNNNNNNNNNO O6OWOXOZO]O`OiOlOmOOOPPPPPP&P)P*PWPPPPPPPPPPQQBQoQQQQQQQQQRR-RNRORQRTRWR`RcRdRRRS S SSSSS!S"SOS|SSSSSSSSST T:TgTTTTTTTTTTU#UDUEUGUJUMUVUYUZUUUVVVVV VVVVCVpVVVVVVVVVVW)WTWuWvWxW{W~WWWWWXX2X3X5X8X;XDXGXHXuXXXXXXXYYYY2Y^YYYYYYYYYYZZIZjZkZmZpZsZ|ZZZZ[[([)[+[.[1[:[=[>[k[[[[[[[[[[\)\V\\\\\\\\\\]]A]b]c]e]h]k]t]w]x]]]^^ ^"^%^(^1^4^5^a^^^^^^^^^^__L_y_________` `6`W`X`Z`]```i`l`m```aaaaaa%a(a)aVaaaaaaaaaabb@blbbbbbbbbbbc)cJcKcMcPcSc\c_c`cccd d d ddddddKdyddddddddde e6eceeeeeeeeeef!fBfCfEfHfKfTfWfXfffggggg ggggFgsgggggggggh h8hfhhhhhhhhhhi-iTi{iiiiiiiiiiiiiiiiiiijjjjjjj(j+j-j2j4j=j@jBjGjIjbjkjmjnjwjjjjjjjjjjjjjjjjjkk kkkk;k=k@kIkRkSk\k_kakjkvkxk{kkkkkkkkkkkkkkkkklllll llllll'l*l,l1l3lLlUlWlXlaljlslllllllllllmmm!m-m:mFmRm_mkmxmmmmmmmmmmmmmmmmmmmmmmmmmmn&nUnnnnnnnnnnooGohoiokonoqozo}o~oopp)p*p,p/p2p;p>p?pkppppppppppq(qUqqqqqqqqqqrr@rarbrdrgrjrsrvrwrrrss s"s%s(s1s4s5sbsssssssssst tLtytttttttttu u5uVuWuYu\u_uhukuluuuvvvvvv%v(v)vVvvvvvvvvvvww@wmwwwwwwwwwwx)xJxKxMxPxSx\x_x`xxxyy:yayyyyyyyyyyyyyyyyyyyyyyzzzzzzzzzz$z'z)z.z0zMzOzXz[zdzeznzwzzzzzzzzzz{{ {{{{"{%{({+{.{?{k{n{q{{{{{{{{{{{{{{{|| | ||||||,|5|8|;|b|o|r|u|~||||||||||||||||||||}}}} }#},}/}1}6}8}_}h}o}}}}}}}}~~~~)~;~I~T~Y~^3~`bcbio-nextgen-1.2.9/artwork/logo.png000066400000000000000000000424721415626112400174210ustar00rootroot00000000000000PNG  IHDR&U pHYs.#.#x?v IDATx_ՙ5lᅁ䦛YŻ HmX,H\F6JD]L ^` Al(h vf:JRbѮb,tK*tKhf>)wUHIsq ofk_ktc/L5ю_;ힱ~%g(EjGY^^p$`D#|LtĿ+.eď`Dlc2 ^"L !ݯ+ "a["c|_*TYG0jdG 57ʐRA[ ",ae]Pa`xhv02L23Bb&0h&;*#TEҶQIbV&:$"ٺQI!C  ```y2 #CRq=`n[A C=)\Ha2 C*# (縺&#G] aU(k&Ȟkd=Ju5[pYd`,I] w!Q/iäYd`\̃,LHNE1w뗀L47{#HĂ (DA&H# Y$@P @ A(HQsMZ$P\Ԯ3d3 .`SA&vb kxAm p`R+ЗW=@D` AQ Xn4}$ ۂ5-,JsZv?c@p (fk;l ݒ\^R#-ۨrg\ ;sͭmjUOhE& U HTOP+ jAԆ`JQ%B#2TI(Q=AcJ4-UI^'g r1HLrj1|bodQ Y^t?ۀTL`3n,p #偬0XʁWޝ',OC??杠/l %l΄$/~ '[VdW>(V|gKT4dp `Km~<J6*{Źma6E0\(g>IFo\[>󩨞**{*J bW6ԱP_7P"#jv ;v zrog %yQk̴{ܿ{Y 6B0AFuԅdD7%=̼Hu5 &A*5$Fc#F_)\G0u %To4ogL'D0A_B2׀>Np k $)=NF0EZ2NIa !`3B JlM7CL2E(A+&Dp1I%R|N!d`B w_3?Rep!IF%%~1DpI&%eg?`NlN $#7~r"eOjiіrGNWg (#$`lA7ѩ]ey\o+3 A,7Wuz=VRW.ޮ?࿂p6I$dkޞ7i=jƿ)_*?b5Lku?}o7 B9}i$QfkwQ|؄>g(YOO?ɵZK!d7ǖdsqH$AfKч.ٮC7x88+gˀur2ΠT5ҫI{ۼ{Cb&i4[;#>Z|ޡ>Mt>XX/X-e8izsyH=&Qd,m$XiEC3>jo?2o0G [7XI}utV2>X_]^zlX Ɯ21f`FuY%7RX85ӏ5ypU8\ƱESZ2l,L@$`-Tס*I/Z2P8ӹ6CIa)8 9IM$(oX^Zb"Ja-Yaq&s؁F UI-fMk9Q,[r 'ԉ$n4:+jE0NT uɾqzb;zͯ7I crV d)p2qMj FtF|SePUz#!DlM"7 O>  e։_BCߋl=8*7<8OdN{]4/DlDck4N=NB`oa9-;#n-wW()\UH!XndLyA뼚v[(QЯgyWIu2Q YomzM5r!Dĭѻk&3jY'u}c z'ɼ0S`WD6NI\&ȽDoԺ[XpS([.CߋՖ#,okeJz[({E&Ƚdm=~(gTN >Ӗ"8ם@OI&`WNrSYc3PuD7ﶡwII[-.C2fn5Hx}'{[nq樓$p`,(h 65khVU/)nnZ*Y\XQ{;uMU ^9U:8[#IM%iTrZkGID\>4dqZ JEAZjT⋫ӓ];I \s=>XojR ")hIMU£YR[/m|.O64-dz{} ^z U4:(.^^I"ׇPS*I?=WU}wjUdauv]:#TlԇMV͂uݨu'}8TMB*R:(oj|W2sDx V 'zdphuv:"Tl-g{tX૓2n^sH\BHگIF&+ӣ]IlO>nn_=dp.iAR;AmzԔWc''`)ŽTL*@d8.}l$ĵq}=v`ri**Vǿvom<4gߝCjR*&8A(k~UNt;JkW9^UIˉT'זBE^&G~zӑz 2(hBB >*#=L#aى؄fkk^G<hVu=#xTOBi&0GR_P,dw%:hY,8E/_$kC֥hVK赦]Sj*/~B͡:LGϨ="xvp2!}:F&J[[NຸAןUԁE=̇Mxx@0%XJӖQ`3*\+oEUASj0#x.ϗ{F56jT@K`ڥ~9`z#ּa'bF7-?4͠4@ϖ*\SCh ؾF\k|R"uS=^s6ضc*"'ldLJ:ꨇ_J66*ܯ7N5ňv0qdޅPs_SL>V!5YWCmh85׼Uf:zѼ7hhn tX΍(ך몉u ,w̒^a_DcC %㺎 W yx$K:tg@U1^g1nUTLDdBu 5e򻈈±>Ocمӗ12ш =IЍE@y6X|R_%H5/{Ab=4ˀЗrXƩ}!?{L~kxꔤ̏tY|C2Ql&ã&GokoQVf {&Ë(9zS)3i6b%LY7g{&Cpg 4.gB(<|Pz >+#ހLËm=Hp> g !L䆾MEGL{~]]D )[Ybj*BB0b>) gB9" 'EoGS0!}^pd.(AR!}^|q`ɀ&DW!_8C/.t=CĽbPp|PF(A,4gJpO471K8k}{>c,`?Js:5u8[␾Jq*cHX.pH_g`708sARWj 3s1+5ΰ䒯J2ǵMl tj弆U&{F9AzwIjǎ~q_J fQ)hdKh=غ[/q@jS_4LؑSEn_6n_%tl.&[ V{Fxׇ{ JlhdzhǙ;*&Q?[ٟsf ǎ^?;]ߏGnyXl F|?jSf|C(nGn+Fom=l#>_ßڳ3V|,7]/XV:~eNI& /6Oj~e>QZR4JJ O>dZݢjL2[Ͽ'ZSrFڧbe¦c4K!apb! Bo5*듵n`1T_h*?SRvL2>\WiZBՇPu3O -si sM IⴌKoIGF3bl3g&WZֲ zP5A&i'jFFm}PPģ"Q/.IrYQ$Ǚ%DX0ҲE9.1ч $a,h=jIY%IdX=9YD61`\ޠ\ʮZ@U(z[#eUԌ`>I7ڟsQ$ϩd &?H6K;U- ԅ`(!VL\by4o_*fPPMֲjB,D@~+:i['vBN%t]U` Շ^\H~~nsd)O._i3|#˄)I4`S'G͈Wae\V:+-%J]W%7BI=%vr8Ѷ:I2V=n Bziz6ᙌ8Bj(٪߹gd!pI ="BSNd#$z0ǡWO=B!702kAAy7"6\I=DJͫz[rD0ITݘx#ntsSR9S@ٷg=!)]gܦ6\QnD@& 9wy1Bot#;7^eu/ SHU|20FT*xHsL-s.XƩLyMDD@l{M Ϋ_,ߊwsN0SVgELc_쇐:pe:I(eq";#@Rk@Dk9QD0IAfNub)C )- &TQM.Og11fLcY1aZJ@{ !Чyx׼/hjjGϽv&`r WC}UcD-=7~UR^.\i $!auT)W^X$MVwIjK:/ltF0IQ$}.-ݼTT0񹴣6[\5 m0lLbJĿ'j* )5=7_D& V*`W)ŭ $Wק=݌R+h9ޮcZ-OLbCR_JJ>oڥc=NVڑZXꍞO"`JJ>Ij#~Bqw!%rNz8+'?*e7ƔLZSz*(C]6 -)Dv`F=dzvu];>6z>$囆%M"/MնCwZj4FRCBuC!2 T& IDATl;oy-}SKa!ǚ9:#-DXYO (Q-kY^Z6+D5ߛ^wצO|MrCI" ϟ~},JUQ-!(h'MK3UƍjLc)g#e@y{c}HJ:7o;ඖ|d1d-= L_:etc~mvd#GC=6C0IJ}] kui;6vl҆6=Q,-`øP^h (3ؠC're.(Ѵ^ع?q5$so.3rZo &55`م5 w]tiLB0InTm>@hnؚ[,LuGEd.X.hՒS/slYHk*-hhᤤANErz NX2sհbRG0I>M+^ ()w[~XYre+w*F& R8vɿzG}P@Ѱ O>d'시25Yf_7si!$L5KE'!7,5ɦc|09ksFffY0ڙ@ԃ`rÝ϶hMo.:'O%3ʡ3L%v@l2(:p1lcg8gR1c[:&Ҳ@PʩVwŽ*&ó3رlM%+)<+ŗy%b}o•*[e?&hӧI{}!<)˭rViO@&޼˝< (u#?ĆrᩢȲzc8򕻋]閼 l^K++Z)9s4$MaDCwc#Fգ*lɣIwGtFbX~l;J^a"`[ʓZK ~=ȱ|boc bsufs~VR@0AߴGԠS9 ݔR+## Oϼ(ZXy`>L0v@ooR0$|Ffʝ<dԬ -0!,w~]뀺VaO:&%5\T)eE$`g+I2f:pgNgXepH j`}(y&`sWc>aز0X jBI u豙K]#n;up- w(`H=&Vg_hōp:`XKb /X,|X̸#1hvM %-zLlX+b;| #sW_BLE@c%-󃴅SׂO ke,YFF0Abd3Gz&\/ 9FP" m/#ފԾF &CPFݡ}z! 759wdډb%`Kl`/NT^7"X+i9ARѸu+1ȩkl7ϽXxxC07VoZSjR&ڑm|]Bŵ4aL8a-xu9jX H50f l`/Vou:;u]ؗ|&ޒؗq} n|}㴒BDoZ_3? ULA&0溷} )αiO $4T͊$c  ,5 LhO?|ehke:ŒN7k>+8 C;5xk]5A7U] O1g4.jzm,WYAU&~.F|_/>&4ahQ-iDZ*LЗ*I:i'@jg8ƚ?2cƔk!S ~n^\z<ZpFPg[ҿ3D?zjpA#`KUʛCf}"'G@{&iz}-;'a#/aO7{rl"Tz~Twx i7?<<ީ3zj)8ϵ_5j>暣TtSc3OQ>uՒF썜Vt;O^\I\_XxLR7˪IYA>~N$vt3QJ8%7P?/4͚CkZOmv ij`@ƎNTL2~n L7]nVg=-+]^n,.8vcڧݮeF6lkd2輠T/#\ Yymn8ZIY +R `U]Fo]gi h=pG]$zSc@SP‰…nz]bK 5 P~L2JI$z3rpfxnްy`vNP%_3e}M܊I|槄 'Mp7oLڽ=Qh!MvN\^2%  !q%4+4.z=O])ʗ5%Y' |#d$U_tMҍGKdo>!a9?`໲F8O Zn̟FD}'-`kk E0PuCjU8qѲ"dǛSOrgtS~:V@Lzk l'$>>~p( zm))b0Ĉ`9Yo=SDQTw<< b;'og>eۊg/.u=,5$+W`_}X1WK_4ӿ+ o&-E0ʕLUM ePP7?q pXL2OXޜvy[qEv~ŝw|ɂSA! (vM>Ƈ)F%8UE3[}ho{D8Avx]^:>ފ]=wh1q+9tlfTC1}?E/N%F?&95}j%ap WAEtyiv N"Ift >鐪&z&\>x3eXrBHx '1%A0Ѕ'2?I _3כz)UNtا"`3zMw=Z-@1; '6`coKQ/tQc]&`:;=hMֲ k7:Li/#L| C< h(_Lٚ? #3c] Bo:;]C]FLzj|}F?+@0̹NږAޫOw{_o_*D*N/Dɩ[OADoHĤ%%7*%䒂ɤ9 %U_KŠWOE_{sG%԰*o?h;tiu #-VE8XdpcKj<;} ҒN'XQuFG NUNFp=.N/y`g^}MGg}?ׄ` }iXr `2& `zNBd$بplW8ItrK@0&DUM|Љq '|wo&K"k# 9p2w9 Q-dHs)4)<5؜U8[W~xV=C Hb& F867l8Ћot=9& Hx'TMJ`sÄX^F$8 ۯ}t_u=+ ~ÉG-ޒf}/u.6"iԉ"TՄy( C؀N||v= %E$u=;vj4W9rʕK6iu5:o5/oauvzb/T7 ]JFchl?N󐽭>ya|{^O(V8ڸ>!shuv:y:R[Ʉ`RySUo2cՀO}ѧy 2 :-X ':?Zlϵ靱]FuB?ǂ߷׃B'[wI8=/otƵץ !UTN[/e/Cuɚ>P+[_m!nuTF?։}/tR/Di;8x][cA zw߯:; tn`G^nw"2 pB -m>ȷW{?6;O,UN4ˁpdΘ+"xZդ"r͕ V}2ԅYF'Ԟ䞑n#V}*9r yn'L5UXd c '`@"?8X~­b98-tjRN.IVgU0YZ1b:SSGu"OU0dZ28b:m>8Bc"VD`87$C_I<9:/*uAj#Dp2`tNJI{kp}%UUmLbQI$Ql!6`yJ: Mp*˖|wqwn뵪ҜIJB0H͖M~-{niWJ|Pg vB7kjRN+=&dp/^}Mw=ߗ*NPդQEO B_I&dI,_^&E7`5}*hŲƾ,_o< C[$^H5I鏏^kYW26UM1D}%q#DluvzQܯv>L@5UՋC/O A+D57X2pԽ7"RȭNS=U[xȺ tWQ8c!fV۾Gno{5;1IVg &PcO?RLnj9+[n{TMO]!J #C&K_Xi^~-U_] |يuD0,jftLA3ִ+Q욦0RVQ|Mw=ɶCU>&FhFYʩ ͮ!$duvZ'rki_Be>86 ӿO׬ג0v~Ӧ*7Ib\7ܯFR?{Ec3҂qH:5ucRñz{~ҁv߻!vइ` ו~,ЋvN+zk9LrMU[$sc|̠'M;>ܯA͖~hrӲ'PhkU~˥+5ٮS./M5A.m&#l<&Z.yW}&ZP’*11~;k;xPIg^ 'aL2h;u h,W >jpk"ZS" 7@04Iw”XxFSS{M‰*!eွZ]s$s_l{TA O>w3Y \ vbTEՓ}{FAX0 K!2b;0F0A\89͎)("``fDQǹ9:;}Q`& M:䊡5{pkUJ0 'ܚ2̰VXʁF@6N +sNTҡBTI`soTң݄@^]7'XOxv1-ڒ L^LPFOYG@tάNۆ*LPF5'4[qUyW ͯ{<3PJQ1AmAJZQ1AmJQ1AJ`LF'9:;}ˍPLF5'|wo\dKLFu(LLizs\VW˽qzr`B?K 0m /At&?9A@zZqdLFSM| ZcON_z FDH d3wq $H! 36H r K!(̹m,} C a0@0RDLք (}k(]b&g0ΠB5%. 9<`TUS_BGU4@&@TT*Ȣ ","q3SvwzTl-uE*"@X&@\UE!e,B p Rl--]ˮL*' WaJ{qer  !Dz=+x0F 2l\LQ nIENDB`bcbio-nextgen-1.2.9/artwork/logo.svg000066400000000000000000000205001415626112400174200ustar00rootroot00000000000000 logo Created with Sketch. bcbio-nextgen-1.2.9/bcbio/000077500000000000000000000000001415626112400153275ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/__init__.py000066400000000000000000000000571415626112400174420ustar00rootroot00000000000000"""Blue collar bioinformatics main module. """ bcbio-nextgen-1.2.9/bcbio/bam/000077500000000000000000000000001415626112400160665ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/bam/__init__.py000066400000000000000000000645051415626112400202110ustar00rootroot00000000000000"""Functionality to query and extract information from aligned BAM files. """ from __future__ import print_function import collections import os import signal import subprocess import numpy import pybedtools import pysam import toolz as tz from six.moves import zip_longest from bcbio import broad, utils from bcbio.bam import ref from bcbio.distributed import objectstore from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import config_utils import bcbio.pipeline.datadict as dd from bcbio.provenance import do def is_empty(bam_file): """Determine if a BAM file is empty """ bam_file = objectstore.cl_input(bam_file) cmd = ("set -o pipefail; " "samtools view {bam_file} | head -1 | wc -l") p = subprocess.Popen(cmd.format(**locals()), shell=True, executable=do.find_bash(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)) stdout, stderr = p.communicate() stdout = stdout.decode() stderr = stderr.decode() if ((p.returncode == 0 or p.returncode == 141) and (stderr == "" or (stderr.startswith("gof3r") and stderr.endswith("broken pipe")))): return int(stdout) == 0 else: raise ValueError("Failed to check empty status of BAM file: %s" % str(stderr)) def is_paired(bam_file): """Determine if a BAM file has paired reads. Works around issues with head closing the samtools pipe using signal trick from: http://stackoverflow.com/a/12451083/252589 """ bam_file = objectstore.cl_input(bam_file) cmd = ("set -o pipefail; " "samtools view -h {bam_file} | head -300000 | " "samtools view -S -f 1 /dev/stdin | head -1 | wc -l") p = subprocess.Popen(cmd.format(**locals()), shell=True, executable=do.find_bash(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)) stdout, stderr = p.communicate() stdout = stdout.decode() stderr = stderr.decode() stderr = stderr.strip() if ((p.returncode == 0 or p.returncode == 141) and (stderr == "" or (stderr.startswith("gof3r") and stderr.endswith("broken pipe")))): return int(stdout) > 0 else: raise ValueError("Failed to check paired status of BAM file: %s" % str(stderr)) def fake_index(in_bam, data): """Create a fake index file for namesorted BAMs. bais require by CWL for consistency. """ index_file = "%s.bai" % in_bam if not utils.file_exists(index_file): with file_transaction(data, index_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: out_handle.write("name sorted -- no index") return index_file def index(in_bam, config, check_timestamp=True): """Index a BAM file, skipping if index present. Centralizes BAM indexing providing ability to switch indexing approaches. """ assert is_bam(in_bam), "%s in not a BAM file" % in_bam index_file = "%s.bai" % in_bam alt_index_file = "%s.bai" % os.path.splitext(in_bam)[0] if check_timestamp: bai_exists = utils.file_uptodate(index_file, in_bam) or utils.file_uptodate(alt_index_file, in_bam) else: bai_exists = utils.file_exists(index_file) or utils.file_exists(alt_index_file) if not bai_exists: # Remove old index files and re-run to prevent linking into tx directory for fname in [index_file, alt_index_file]: utils.remove_safe(fname) samtools = config_utils.get_program("samtools", config) num_cores = config["algorithm"].get("num_cores", 1) with file_transaction(config, index_file) as tx_index_file: cmd = "{samtools} index -@ {num_cores} {in_bam} {tx_index_file}" do.run(cmd.format(**locals()), "Index BAM file: %s" % os.path.basename(in_bam)) return index_file if utils.file_exists(index_file) else alt_index_file def remove(in_bam): """ remove bam file and the index if exists """ if utils.file_exists(in_bam): utils.remove_safe(in_bam) if utils.file_exists(in_bam + ".bai"): utils.remove_safe(in_bam + ".bai") def idxstats(in_bam, data): """Return BAM index stats for the given file, using samtools idxstats. """ index(in_bam, data["config"], check_timestamp=False) AlignInfo = collections.namedtuple("AlignInfo", ["contig", "length", "aligned", "unaligned"]) samtools = config_utils.get_program("samtools", data["config"]) idxstats_out = subprocess.check_output([samtools, "idxstats", in_bam]).decode() out = [] for line in idxstats_out.split("\n"): if line.strip(): contig, length, aligned, unaligned = line.split("\t") out.append(AlignInfo(contig, int(length), int(aligned), int(unaligned))) return out def fai_from_bam(ref_file, bam_file, out_file, data): """Create a fai index with only contigs in the input BAM file. """ contigs = set([x.contig for x in idxstats(bam_file, data)]) if not utils.file_uptodate(out_file, bam_file): with open(ref.fasta_idx(ref_file, data["config"])) as in_handle: with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for line in (l for l in in_handle if l.strip()): if line.split()[0] in contigs: out_handle.write(line) return out_file def ref_file_from_bam(bam_file, data): """Subset a fasta input file to only a fraction of input contigs. """ new_ref = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "inputs", "ref")), "%s-subset.fa" % dd.get_genome_build(data)) if not utils.file_exists(new_ref): with file_transaction(data, new_ref) as tx_out_file: contig_file = "%s-contigs.txt" % utils.splitext_plus(new_ref)[0] with open(contig_file, "w") as out_handle: for contig in [x.contig for x in idxstats(bam_file, data) if x.contig != "*"]: out_handle.write("%s\n" % contig) cmd = "seqtk subseq -l 100 %s %s > %s" % (dd.get_ref_file(data), contig_file, tx_out_file) do.run(cmd, "Subset %s to BAM file contigs" % dd.get_genome_build(data)) ref.fasta_idx(new_ref, data["config"]) runner = broad.runner_from_path("picard", data["config"]) runner.run_fn("picard_index_ref", new_ref) return {"base": new_ref} def get_downsample_pct(in_bam, target_counts, data): """Retrieve percentage of file to downsample to get to target counts. Avoids minimal downsample which is not especially useful for improving QC times; 90& or more of reads. """ total = sum(x.aligned for x in idxstats(in_bam, data)) with pysam.Samfile(in_bam, "rb") as work_bam: n_rgs = max(1, len(work_bam.header.get("RG", []))) rg_target = n_rgs * target_counts if total > rg_target: pct = float(rg_target) / float(total) if pct < 0.9: return pct def get_aligned_reads(in_bam, data): index(in_bam, data["config"], check_timestamp=False) bam_stats = idxstats(in_bam, data) align = sum(x.aligned for x in bam_stats) unaligned = sum(x.unaligned for x in bam_stats) total = float(align + unaligned) return 1.0 * align / total def downsample(in_bam, data, target_counts, work_dir=None): """Downsample a BAM file to the specified number of target counts.""" index(in_bam, data["config"], check_timestamp=False) ds_pct = get_downsample_pct(in_bam, target_counts, data) if ds_pct: out_file = "%s-downsample%s" % os.path.splitext(in_bam) if work_dir: out_file = os.path.join(work_dir, os.path.basename(out_file)) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: samtools = config_utils.get_program("samtools", data["config"]) num_cores = dd.get_num_cores(data) ds_pct = "42." + "{ds_pct:.3}".format(ds_pct=ds_pct).replace("0.", "") cmd = ("{samtools} view -O BAM -@ {num_cores} -o {tx_out_file} " "-s {ds_pct} {in_bam}") do.run(cmd.format(**locals()), "Downsample BAM file: %s" % os.path.basename(in_bam)) return out_file def get_maxcov_downsample_cl(data, in_pipe=None): """Retrieve command line for max coverage downsampling, fitting into bamsormadup output. """ max_cov = _get_maxcov_downsample(data) if dd.get_aligner(data) not in ["snap"] else None if max_cov: if in_pipe == "bamsormadup": prefix = "level=0" elif in_pipe == "samtools": prefix = "-l 0" else: prefix = "" # Swap over to multiple cores until after testing #core_arg = "-t %s" % dd.get_num_cores(data) core_arg = "" return ("%s | variant - -b %s --mark-as-qc-fail --max-coverage %s" % (prefix, core_arg, max_cov)) else: if in_pipe == "bamsormadup": prefix = "indexfilename={tx_out_file}.bai" else: prefix = "" return prefix def _get_maxcov_downsample(data): """Calculate maximum coverage downsampling for whole genome samples. Returns None if we're not doing downsampling. """ from bcbio.bam import ref from bcbio.ngsalign import alignprep, bwa from bcbio.variation import coverage fastq_file = data["files"][0] params = alignprep.get_downsample_params(data) if params: num_reads = alignprep.total_reads_from_grabix(fastq_file) if num_reads: vrs = dd.get_variant_regions_merged(data) total_size = sum([c.size for c in ref.file_contigs(dd.get_ref_file(data), data["config"])]) if vrs: callable_size = pybedtools.BedTool(vrs).total_coverage() genome_cov_pct = callable_size / float(total_size) else: callable_size = total_size genome_cov_pct = 1.0 if (genome_cov_pct > coverage.GENOME_COV_THRESH and dd.get_coverage_interval(data) in ["genome", None, False]): total_counts, total_sizes = 0, 0 for count, size in bwa.fastq_size_output(fastq_file, 5000): total_counts += int(count) total_sizes += (int(size) * int(count)) read_size = float(total_sizes) / float(total_counts) avg_cov = float(num_reads * read_size) / callable_size if avg_cov >= params["min_coverage_for_downsampling"]: return int(avg_cov * params["maxcov_downsample_multiplier"]) return None def check_header(in_bam, rgnames, ref_file, config): """Ensure passed in BAM header matches reference file and read groups names. """ _check_bam_contigs(in_bam, ref_file, config) _check_sample(in_bam, rgnames) def has_tags(in_bam, tags): """ Checks the first 10,000 records in a BAM file for a set of tags. Returns True if all the tags are seen at least once and False otherwise. """ assert isinstance(tags, set), f"{tags} is not a set." assert is_bam(in_bam), f"{in_bam} is not a BAM file." MAX_ALIGNMENTS = 10000 with pysam.Samfile(in_bam, "rb") as bamfile: alignments = 0 for read in bamfile.fetch(until_eof=True): alignments += 1 if alignments > MAX_ALIGNMENTS: return False if not tags: return True tags_left = tags.copy() for tag in tags_left: if read.has_tag(tag): tags.remove(tag) return False def _check_sample(in_bam, rgnames): """Ensure input sample name matches expected run group names. """ with pysam.Samfile(in_bam, "rb") as bamfile: rg = bamfile.header.get("RG", [{}]) msgs = [] warnings = [] if len(rg) > 1: warnings.append("Multiple read groups found in input BAM. Expect single RG per BAM.") if len(rg) == 0: msgs.append("No read groups found in input BAM. Expect single RG per BAM.") if len(rg) > 0 and any(x.get("SM") != rgnames["sample"] for x in rg): msgs.append("Read group sample name (SM) does not match configuration `description`: %s vs %s" % (rg[0].get("SM"), rgnames["sample"])) if len(msgs) > 0: raise ValueError("Problems with pre-aligned input BAM file: %s\n" % (in_bam) + "\n".join(msgs) + "\nSetting `bam_clean: fixrg`\n" "in the configuration can often fix this issue.") if warnings: print("*** Potential problems in input BAM compared to reference:\n%s\n" % "\n".join(warnings)) def _check_bam_contigs(in_bam, ref_file, config): """Ensure a pre-aligned BAM file matches the expected reference genome. """ # GATK allows chromosome M to be in multiple locations, skip checking it allowed_outoforder = ["chrM", "MT"] ref_contigs = [c.name for c in ref.file_contigs(ref_file, config)] with pysam.Samfile(in_bam, "rb") as bamfile: bam_contigs = [c["SN"] for c in bamfile.header["SQ"]] extra_bcs = [x for x in bam_contigs if x not in ref_contigs] extra_rcs = [x for x in ref_contigs if x not in bam_contigs] problems = [] warnings = [] for bc, rc in zip_longest([x for x in bam_contigs if (x not in extra_bcs and x not in allowed_outoforder)], [x for x in ref_contigs if (x not in extra_rcs and x not in allowed_outoforder)]): if bc != rc: if bc and rc: problems.append("Reference mismatch. BAM: %s Reference: %s" % (bc, rc)) elif bc: warnings.append("Extra BAM chromosomes: %s" % bc) elif rc: warnings.append("Extra reference chromosomes: %s" % rc) for bc in extra_bcs: warnings.append("Extra BAM chromosomes: %s" % bc) for rc in extra_rcs: warnings.append("Extra reference chromosomes: %s" % rc) if problems: raise ValueError("Unexpected order, name or contig mismatches between input BAM and reference file:\n%s\n" "Setting `bam_clean: remove_extracontigs` in the configuration can often fix this issue." % "\n".join(problems)) if warnings: print("*** Potential problems in input BAM compared to reference:\n%s\n" % "\n".join(warnings)) def open_samfile(in_file): if is_bam(in_file): return pysam.Samfile(in_file, "rb") elif is_sam(in_file): return pysam.Samfile(in_file, "r") else: raise IOError("in_file must be either a BAM file or SAM file. Is the " "extension .sam or .bam?") def is_bam(in_file): _, ext = os.path.splitext(in_file) if ext == ".bam": return True else: return False def is_sam(in_file): _, ext = os.path.splitext(in_file) if ext == ".sam": return True else: return False def sam_to_bam(in_sam, config): if is_bam(in_sam): return in_sam assert is_sam(in_sam), "%s is not a SAM file" % in_sam out_file = os.path.splitext(in_sam)[0] + ".bam" if utils.file_exists(out_file): return out_file samtools = config_utils.get_program("samtools", config) num_cores = config["algorithm"].get("num_cores", 1) with file_transaction(config, out_file) as tx_out_file: cmd = "{samtools} view -@ {num_cores} -h -S -b {in_sam} -o {tx_out_file}" do.run(cmd.format(**locals()), ("Convert SAM to BAM (%s cores): %s to %s" % (str(num_cores), in_sam, out_file))) return out_file def bam_to_sam(in_file, config): if is_sam(in_file): return in_file assert is_bam(in_file), "%s is not a BAM file" % in_file out_file = os.path.splitext(in_file)[0] + ".sam" if utils.file_exists(out_file): return out_file samtools = config_utils.get_program("samtools", config) num_cores = config["algorithm"].get("num_cores", 1) with file_transaction(config, out_file) as tx_out_file: cmd = "{samtools} view -@ {num_cores} -h {in_file} -o {tx_out_file}" do.run(cmd.format(**locals()), ("Convert BAM to SAM (%s cores): %s to %s" % (str(num_cores), in_file, out_file))) return out_file def reheader(header, bam_file, config): samtools = config_utils.get_program("samtools", config) base, ext = os.path.splitext(bam_file) out_file = base + ".reheadered" + ext cmd = "{samtools} reheader {header} {bam_file} > {out_file}" do.run(cmd.format(**locals()), "Reheadering %s." % bam_file) return out_file def merge(bamfiles, out_bam, config): assert all(map(is_bam, bamfiles)), ("Not all of the files to merge are not BAM " "files: %s " % (bamfiles)) assert all(map(utils.file_exists, bamfiles)), ("Not all of the files to merge " "exist: %s" % (bamfiles)) if len(bamfiles) == 1: return bamfiles[0] if os.path.exists(out_bam): return out_bam samtools = config_utils.get_program("samtools", config) bamtools = config_utils.get_program("bamtools", config) num_cores = config["algorithm"].get("num_cores", 1) with file_transaction(config, out_bam) as tx_out_bam: cmd = "{samtools} merge -@ {num_cores} {tx_out_bam} " + " ".join(bamfiles) do.run(cmd.format(**locals()), "Merge %s into %s." % (bamfiles, out_bam)) index(out_bam, config) return out_bam def sort(in_bam, config, order="coordinate", out_dir=None, force=False): """Sort a BAM file, skipping if already present. """ assert is_bam(in_bam), "%s in not a BAM file" % in_bam if not force and bam_already_sorted(in_bam, config, order): return in_bam sort_stem = _get_sort_stem(in_bam, order, out_dir) sort_file = sort_stem + ".bam" if not utils.file_exists(sort_file): samtools = config_utils.get_program("samtools", config) cores = config["algorithm"].get("num_cores", 1) with file_transaction(config, sort_file) as tx_sort_file: tx_sort_stem = os.path.splitext(tx_sort_file)[0] tx_dir = utils.safe_makedir(os.path.dirname(tx_sort_file)) order_flag = "-n" if order == "queryname" else "" resources = config_utils.get_resources("samtools", config) # Slightly decrease memory and allow more accurate representation # in Mb to ensure fits within systems like SLURM mem = config_utils.adjust_memory(resources.get("memory", "2G"), 1.25, "decrease", out_modifier="M").upper() cmd = ("{samtools} sort -@ {cores} -m {mem} -O BAM {order_flag} " "-T {tx_sort_stem}-sort -o {tx_sort_file} {in_bam}") do.run(cmd.format(**locals()), "Sort BAM file %s: %s to %s" % (order, os.path.basename(in_bam), os.path.basename(sort_file))) return sort_file def bam_already_sorted(in_bam, config, order): return order == _get_sort_order(in_bam, config) def _get_sort_order(in_bam, config): for line in pysam.view("-H", in_bam).split("\r\n"): if line.startswith("@HD"): for keyval in line.split()[1:]: key, val = keyval.split(":") if key == "SO": return val def _get_sort_stem(in_bam, order, out_dir): SUFFIXES = {"coordinate": ".sorted", "queryname": ".nsorted"} sort_base = os.path.splitext(in_bam)[0] if out_dir: sort_base = os.path.join(out_dir, os.path.basename(sort_base)) for suffix in SUFFIXES: sort_base = sort_base.split(suffix)[0] return sort_base + SUFFIXES[order] def aligner_from_header(in_bam): """Identify aligner from the BAM header; handling pre-aligned inputs. """ from bcbio.pipeline.alignment import TOOLS with pysam.Samfile(in_bam, "rb") as bamfile: for pg in bamfile.header.get("PG", []): for ka in TOOLS.keys(): if pg.get("PN", "").lower().find(ka) >= 0: return ka def sample_name(in_bam): """Get sample name from BAM file. """ with pysam.AlignmentFile(in_bam, "rb", check_sq=False) as in_pysam: try: if "RG" in in_pysam.header: return in_pysam.header["RG"][0]["SM"] except ValueError: return None def estimate_read_length(bam_file, nreads=1000): """ estimate median read length of a SAM/BAM file """ with open_samfile(bam_file) as bam_handle: reads = tz.itertoolz.take(nreads, bam_handle) lengths = [len(x.seq) for x in reads] return int(numpy.median(lengths)) def estimate_fragment_size(bam_file, nreads=5000): """ estimate median fragment size of a SAM/BAM file """ with open_samfile(bam_file) as bam_handle: reads = tz.itertoolz.take(nreads, bam_handle) # it would be good to skip spliced paired reads. lengths = [x.template_length for x in reads if x.template_length > 0] if not lengths: return 0 return int(numpy.median(lengths)) def filter_primary(bam_file, data): """Filter reads to primary only BAM. Removes: - not primary alignment (0x100) 256 - supplementary alignment (0x800) 2048 """ stem, ext = os.path.splitext(bam_file) out_file = stem + ".primary" + ext if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cores = dd.get_num_cores(data) cmd = ("samtools view -@ {cores} -F 2304 -b {bam_file} > {tx_out_file}") do.run(cmd.format(**locals()), ("Filtering primary alignments in %s." % os.path.basename(bam_file))) return out_file def estimate_max_mapq(in_bam, nreads=1e6): """Guess maximum MAPQ in a BAM file of reads with alignments """ with pysam.Samfile(in_bam, "rb") as work_bam: reads = tz.take(int(nreads), work_bam) return max([x.mapq for x in reads if not x.is_unmapped]) def convert_cufflinks_mapq(in_bam, out_bam=None): """Cufflinks expects the not-valid 255 MAPQ for uniquely mapped reads. This detects the maximum mapping quality in a BAM file and sets reads with that quality to be 255 """ CUFFLINKSMAPQ = 255 if not out_bam: out_bam = os.path.splitext(in_bam)[0] + "-cufflinks.bam" if utils.file_exists(out_bam): return out_bam maxmapq = estimate_max_mapq(in_bam) if maxmapq == CUFFLINKSMAPQ: return in_bam logger.info("Converting MAPQ scores in %s to be Cufflinks compatible." % in_bam) with pysam.Samfile(in_bam, "rb") as in_bam_fh: with pysam.Samfile(out_bam, "wb", template=in_bam_fh) as out_bam_fh: for read in in_bam_fh: if read.mapq == maxmapq and not read.is_unmapped: read.mapq = CUFFLINKSMAPQ out_bam_fh.write(read) return out_bam def convert_invalid_mapq(in_bam, out_bam=None): """Some aligners output 255 to denote a uniquely mapped read which is an invalid MAPQ value according to the SAM spec. This detects that and changes it to be 60. """ INVALIDMAPQ = 255 VALIDMAPQ = 60 if not out_bam: out_bam = os.path.splitext(in_bam)[0] + "-MAPQfixed.bam" if utils.file_exists(out_bam): return out_bam maxmapq = estimate_max_mapq(in_bam) if maxmapq != INVALIDMAPQ: return in_bam logger.info("Converting 255 MAPQ scores in %s to 60." % in_bam) with pysam.Samfile(in_bam, "rb") as in_bam_fh: with pysam.Samfile(out_bam, "wb", template=in_bam_fh) as out_bam_fh: for read in in_bam_fh: if read.mapq == INVALIDMAPQ and not read.is_unmapped: read.mapq = VALIDMAPQ out_bam_fh.write(read) return out_bam def remove_duplicates(in_bam, data): """ remove duplicates from a duplicate marked BAM file """ base, ext = os.path.splitext(in_bam) out_bam = base + "-noduplicates" + ext if utils.file_exists(out_bam): return out_bam num_cores = dd.get_num_cores(data) sambamba = config_utils.get_program("sambamba", data) with file_transaction(out_bam) as tx_out_bam: cmd = (f'{sambamba} view -h --nthreads {num_cores} -f bam -F "not duplicate" ' f'{in_bam} > {tx_out_bam}') message = f"Removing duplicates from {in_bam}, saving as {out_bam}." do.run(cmd, message) index(out_bam, dd.get_config(data)) return out_bam def count_alignments(in_bam, data, filter=None): """ count alignments in a BAM file passing a given filter. valid filter strings are available in the sambamba documentation: https://github.com/biod/sambamba/wiki/%5Bsambamba-view%5D-Filter-expression-syntax """ sambamba = config_utils.get_program("sambamba", dd.get_config(data)) num_cores = dd.get_num_cores(data) if not filter: filter_string = "" message = f"Counting alignments in {in_bam}." else: filter_string = "--filter {filter}" message = f"Counting alignments in {in_bam} matching {filter}." cmd = f"{sambamba} view -c --nthreads {num_cores} -f bam {filter_string} {in_bam}" logger.info(message) result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return int(result.stdout.decode().strip()) def has_nalignments(in_bam, n, data, filter=None): """ does a BAM file has at least n alignments? """ sambamba = config_utils.get_program("sambamba", dd.get_config(data)) num_cores = dd.get_num_cores(data) if not filter: filter_string = "" message = f"Counting alignments in {in_bam}." else: filter_string = "--filter {filter}" message = f"Counting alignments in {in_bam} matching {filter}." cmd = f"{sambamba} view -f sam {filter_string} {in_bam} | head -{n} | wc -l" logger.info(message) result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return int(result.stdout.decode().strip()) >= n bcbio-nextgen-1.2.9/bcbio/bam/callable.py000066400000000000000000000450571415626112400202120ustar00rootroot00000000000000"""Examine callable regions following genome mapping of short reads. Identifies callable analysis regions surrounded by larger regions lacking aligned bases. This allows parallelization of smaller chromosome chunks through post-processing and variant calling, with each sub-section mapping handled separately. Regions are split to try to maintain relative uniformity across the genome and avoid extremes of large blocks or large numbers of small blocks. """ import collections from functools import reduce import os import numpy import pybedtools import pysam import toolz as tz from bcbio import broad, utils from bcbio.cwl import cwlutils from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import shared from bcbio.pipeline import datadict as dd from bcbio.variation import coverage from bcbio.variation import multi as vmulti from bcbio.structural import regions def sample_callable_bed(bam_file, ref_file, data): """Retrieve callable regions for a sample subset by defined analysis regions. """ from bcbio.heterogeneity import chromhacks CovInfo = collections.namedtuple("CovInfo", "callable, raw_callable, depth_files") noalt_calling = "noalt_calling" in dd.get_tools_on(data) or "altcontigs" in dd.get_exclude_regions(data) def callable_chrom_filter(r): """Filter to callable region, potentially limiting by chromosomes. """ return r.name == "CALLABLE" and (not noalt_calling or chromhacks.is_nonalt(r.chrom)) out_file = "%s-callable_sample.bed" % os.path.splitext(bam_file)[0] with shared.bedtools_tmpdir(data): sv_bed = regions.get_sv_bed(data) callable_bed, depth_files = coverage.calculate(bam_file, data, sv_bed) input_regions_bed = dd.get_variant_regions(data) if not utils.file_uptodate(out_file, callable_bed): with file_transaction(data, out_file) as tx_out_file: callable_regions = pybedtools.BedTool(callable_bed) filter_regions = callable_regions.filter(callable_chrom_filter) if input_regions_bed: if not utils.file_uptodate(out_file, input_regions_bed): input_regions = pybedtools.BedTool(input_regions_bed) filter_regions.intersect(input_regions, nonamecheck=True).saveas(tx_out_file) else: filter_regions.saveas(tx_out_file) return CovInfo(out_file, callable_bed, depth_files) def get_ref_bedtool(ref_file, config, chrom=None): """Retrieve a pybedtool BedTool object with reference sizes from input reference. """ broad_runner = broad.runner_from_path("picard", config) ref_dict = broad_runner.run_fn("picard_index_ref", ref_file) ref_lines = [] with pysam.Samfile(ref_dict, "r") as ref_sam: for sq in ref_sam.header["SQ"]: if not chrom or sq["SN"] == chrom: ref_lines.append("%s\t%s\t%s" % (sq["SN"], 0, sq["LN"])) return pybedtools.BedTool("\n".join(ref_lines), from_string=True) def _get_nblock_regions(in_file, min_n_size, ref_regions): """Retrieve coordinates of regions in reference genome with no mapping. These are potential breakpoints for parallelizing analysis. """ out_lines = [] called_contigs = set([]) with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: contig, start, end, ctype = line.rstrip().split() called_contigs.add(contig) if (ctype in ["REF_N", "NO_COVERAGE", "EXCESSIVE_COVERAGE", "LOW_COVERAGE"] and int(end) - int(start) > min_n_size): out_lines.append("%s\t%s\t%s\n" % (contig, start, end)) for refr in ref_regions: if refr.chrom not in called_contigs: out_lines.append("%s\t%s\t%s\n" % (refr.chrom, 0, refr.stop)) return pybedtools.BedTool("\n".join(out_lines), from_string=True) def _combine_regions(all_regions, ref_regions): """Combine multiple BEDtools regions of regions into sorted final BEDtool. """ chrom_order = {} for i, x in enumerate(ref_regions): chrom_order[x.chrom] = i def wchrom_key(x): chrom, start, end = x return (chrom_order[chrom], start, end) all_intervals = [] for region_group in all_regions: for region in region_group: all_intervals.append((region.chrom, int(region.start), int(region.stop))) all_intervals.sort(key=wchrom_key) bed_lines = ["%s\t%s\t%s" % (c, s, e) for (c, s, e) in all_intervals] return pybedtools.BedTool("\n".join(bed_lines), from_string=True) def _add_config_regions(nblock_regions, ref_regions, data): """Add additional nblock regions based on configured regions to call. Identifies user defined regions which we should not be analyzing. """ input_regions_bed = dd.get_variant_regions(data) if input_regions_bed: input_regions = pybedtools.BedTool(input_regions_bed) # work around problem with single region not subtracted correctly. if len(input_regions) == 1: str_regions = str(input_regions[0]).strip() input_regions = pybedtools.BedTool("%s\n%s" % (str_regions, str_regions), from_string=True) input_nblock = ref_regions.subtract(input_regions, nonamecheck=True) if input_nblock == ref_regions: raise ValueError("Input variant_region file (%s) " "excludes all genomic regions. Do the chromosome names " "in the BED file match your genome (chr1 vs 1)?" % input_regions_bed) all_intervals = _combine_regions([input_nblock, nblock_regions], ref_regions) else: all_intervals = nblock_regions if "noalt_calling" in dd.get_tools_on(data) or "altcontigs" in dd.get_exclude_regions(data): from bcbio.heterogeneity import chromhacks remove_intervals = ref_regions.filter(lambda r: not chromhacks.is_nonalt(r.chrom)) all_intervals = _combine_regions([all_intervals, remove_intervals], ref_regions) return all_intervals.merge() class NBlockRegionPicker: """Choose nblock regions reasonably spaced across chromosomes. This avoids excessively large blocks and also large numbers of tiny blocks by splitting to a defined number of blocks. Assumes to be iterating over an ordered input file and needs re-initiation with each new file processed as it keeps track of previous blocks to maintain the splitting. """ def __init__(self, ref_regions, config, min_n_size): self._end_buffer = 250 if min_n_size > 50 else 0 self._chr_last_blocks = {} target_blocks = int(config["algorithm"].get("nomap_split_targets", 200)) self._target_size = self._get_target_size(target_blocks, ref_regions) self._ref_sizes = {x.chrom: x.stop for x in ref_regions} def _get_target_size(self, target_blocks, ref_regions): size = 0 for x in ref_regions: size += (x.end - x.start) return size // target_blocks def include_block(self, x): """Check for inclusion of block based on distance from previous. """ last_pos = self._chr_last_blocks.get(x.chrom, 0) # Region excludes an entire chromosome, typically decoy/haplotypes if last_pos <= self._end_buffer and x.stop >= self._ref_sizes.get(x.chrom, 0) - self._end_buffer: return True # Do not split on smaller decoy and haplotype chromosomes elif self._ref_sizes.get(x.chrom, 0) <= self._target_size: return False elif (x.start - last_pos) > self._target_size: self._chr_last_blocks[x.chrom] = x.stop return True else: return False def expand_block(self, feat): """Expand any blocks which are near the start or end of a contig. """ chrom_end = self._ref_sizes.get(feat.chrom) if chrom_end: if feat.start < self._end_buffer: feat.start = 0 if feat.stop >= chrom_end - self._end_buffer: feat.stop = chrom_end return feat def block_regions(callable_bed, in_bam, ref_file, data): """Find blocks of regions for analysis from mapped input BAM file. Identifies islands of callable regions, surrounding by regions with no read support, that can be analyzed independently. """ min_n_size = int(data["config"]["algorithm"].get("nomap_split_size", 250)) with shared.bedtools_tmpdir(data): nblock_bed = "%s-nblocks.bed" % utils.splitext_plus(callable_bed)[0] callblock_bed = "%s-callableblocks.bed" % utils.splitext_plus(callable_bed)[0] if not utils.file_uptodate(nblock_bed, callable_bed): ref_regions = get_ref_bedtool(ref_file, data["config"]) nblock_regions = _get_nblock_regions(callable_bed, min_n_size, ref_regions) nblock_regions = _add_config_regions(nblock_regions, ref_regions, data) with file_transaction(data, nblock_bed, callblock_bed) as (tx_nblock_bed, tx_callblock_bed): nblock_regions.filter(lambda r: len(r) > min_n_size).saveas(tx_nblock_bed) if len(ref_regions.subtract(nblock_regions, nonamecheck=True)) > 0: ref_regions.subtract(tx_nblock_bed, nonamecheck=True).merge(d=min_n_size).saveas(tx_callblock_bed) else: raise ValueError("No callable regions found in %s from BAM file %s. Some causes:\n " " - Alignment regions do not overlap with regions found " "in your `variant_regions` BED: %s\n" " - There are no aligned reads in your BAM file that pass sanity checks " " (mapping score > 1, non-duplicates, both ends of paired reads mapped)" % (dd.get_sample_name(data), in_bam, dd.get_variant_regions(data))) return callblock_bed, nblock_bed def _write_bed_regions(data, final_regions, out_file, out_file_ref): ref_file = tz.get_in(["reference", "fasta", "base"], data) ref_regions = get_ref_bedtool(ref_file, data["config"]) noanalysis_regions = ref_regions.subtract(final_regions, nonamecheck=True) final_regions.saveas(out_file) noanalysis_regions.saveas(out_file_ref) def _analysis_block_stats(regions, samples): """Provide statistics on sizes and number of analysis blocks. """ prev = None between_sizes = [] region_sizes = [] for region in regions: if prev and prev.chrom == region.chrom: between_sizes.append(region.start - prev.end) region_sizes.append(region.end - region.start) prev = region def descriptive_stats(xs): if len(xs) < 2: return xs parts = ["min: %s" % min(xs), "5%%: %s" % numpy.percentile(xs, 5), "25%%: %s" % numpy.percentile(xs, 25), "median: %s" % numpy.percentile(xs, 50), "75%%: %s" % numpy.percentile(xs, 75), "95%%: %s" % numpy.percentile(xs, 95), "99%%: %s" % numpy.percentile(xs, 99), "max: %s" % max(xs)] return "\n".join([" " + x for x in parts]) logger.info("Identified %s parallel analysis blocks\n" % len(region_sizes) + "Block sizes:\n%s\n" % descriptive_stats(region_sizes) + "Between block sizes:\n%s\n" % descriptive_stats(between_sizes)) if len(region_sizes) == 0: raise ValueError("No callable regions found in: %s" % (", ".join([dd.get_sample_name(x) for x in samples]))) def _needs_region_update(out_file, samples): """Check if we need to update BED file of regions, supporting back compatibility. """ nblock_files = [x["regions"]["nblock"] for x in samples if "regions" in x] # For older approaches and do not create a new set of analysis # regions, since the new algorithm will re-do all BAM and variant # steps with new regions for nblock_file in nblock_files: test_old = nblock_file.replace("-nblocks", "-analysisblocks") if os.path.exists(test_old): return False # Check if any of the local files have changed so we need to refresh for noblock_file in nblock_files: if not utils.file_uptodate(out_file, noblock_file): return True return False def combine_sample_regions(*samples): """Create batch-level sets of callable regions for multi-sample calling. Intersects all non-callable (nblock) regions from all samples in a batch, producing a global set of callable regions. """ samples = utils.unpack_worlds(samples) samples = cwlutils.unpack_tarballs(samples, samples[0]) # back compatibility -- global file for entire sample set global_analysis_file = os.path.join(samples[0]["dirs"]["work"], "analysis_blocks.bed") if utils.file_exists(global_analysis_file) and not _needs_region_update(global_analysis_file, samples): global_no_analysis_file = os.path.join(os.path.dirname(global_analysis_file), "noanalysis_blocks.bed") else: global_analysis_file = None out = [] analysis_files = [] batches = [] with shared.bedtools_tmpdir(samples[0]): for batch, items in vmulti.group_by_batch(samples, require_bam=False).items(): batches.append(items) if global_analysis_file: analysis_file, no_analysis_file = global_analysis_file, global_no_analysis_file else: analysis_file, no_analysis_file = _combine_sample_regions_batch(batch, items) for data in items: vr_file = dd.get_variant_regions(data) if analysis_file: analysis_files.append(analysis_file) data["config"]["algorithm"]["callable_regions"] = analysis_file data["config"]["algorithm"]["non_callable_regions"] = no_analysis_file data["config"]["algorithm"]["callable_count"] = pybedtools.BedTool(analysis_file).count() elif vr_file: data["config"]["algorithm"]["callable_count"] = pybedtools.BedTool(vr_file).count() # attach a representative sample for calculating callable region if not data.get("work_bam"): for x in items: if x.get("work_bam"): data["work_bam_callable"] = x["work_bam"] out.append([data]) # Ensure output order matches input order, consistency for CWL-based runs assert len(out) == len(samples) sample_indexes = {dd.get_sample_name(d): i for i, d in enumerate(samples)} def by_input_index(xs): return sample_indexes[dd.get_sample_name(xs[0])] out.sort(key=by_input_index) if len(analysis_files) > 0: final_regions = pybedtools.BedTool(analysis_files[0]) _analysis_block_stats(final_regions, batches[0]) return out def _combine_sample_regions_batch(batch, items): """Combine sample regions within a group of batched samples. """ config = items[0]["config"] work_dir = utils.safe_makedir(os.path.join(items[0]["dirs"]["work"], "regions")) analysis_file = os.path.join(work_dir, "%s-analysis_blocks.bed" % batch) no_analysis_file = os.path.join(work_dir, "%s-noanalysis_blocks.bed" % batch) if not utils.file_exists(analysis_file) or _needs_region_update(analysis_file, items): # Combine all nblocks into a final set of intersecting regions # without callable bases. HT @brentp for intersection approach # https://groups.google.com/forum/?fromgroups#!topic/bedtools-discuss/qA9wK4zN8do bed_regions = [pybedtools.BedTool(x["regions"]["nblock"]) for x in items if "regions" in x and x["regions"]["nblock"]] if len(bed_regions) == 0: analysis_file, no_analysis_file = None, None else: with file_transaction(items[0], analysis_file, no_analysis_file) as (tx_afile, tx_noafile): def intersect_two(a, b): return a.intersect(b, nonamecheck=True).saveas() nblock_regions = reduce(intersect_two, bed_regions).saveas( "%s-nblock%s" % utils.splitext_plus(tx_afile)) ref_file = tz.get_in(["reference", "fasta", "base"], items[0]) ref_regions = get_ref_bedtool(ref_file, config) min_n_size = int(config["algorithm"].get("nomap_split_size", 250)) block_filter = NBlockRegionPicker(ref_regions, config, min_n_size) final_nblock_regions = nblock_regions.filter( block_filter.include_block).saveas().each(block_filter.expand_block).saveas( "%s-nblockfinal%s" % utils.splitext_plus(tx_afile)) final_regions = ref_regions.subtract(final_nblock_regions, nonamecheck=True).\ saveas().merge(d=min_n_size) _write_bed_regions(items[0], final_regions, tx_afile, tx_noafile) if analysis_file and utils.file_exists(analysis_file): return analysis_file, no_analysis_file else: return None, None def get_split_regions(bed_file, data): """Retrieve a set of split regions using the input BED for callable regions. Provides a less inclusive hook for parallelizing over multiple regions. """ out_file = "%s-analysis_blocks.bed" % utils.splitext_plus(bed_file)[0] with shared.bedtools_tmpdir(data): if not utils.file_uptodate(out_file, bed_file): ref_regions = get_ref_bedtool(dd.get_ref_file(data), data["config"]) nblock_regions = ref_regions.subtract(pybedtools.BedTool(bed_file)).saveas() min_n_size = int(tz.get_in(["config", "algorithm", "nomap_split_size"], data, 250)) block_filter = NBlockRegionPicker(ref_regions, data["config"], min_n_size) final_nblock_regions = nblock_regions.filter( block_filter.include_block).saveas().each(block_filter.expand_block).saveas() with file_transaction(data, out_file) as tx_out_file: final_regions = ref_regions.subtract(final_nblock_regions, nonamecheck=True).\ saveas().merge(d=min_n_size).saveas(tx_out_file) chroms = set([]) with shared.bedtools_tmpdir(data): for r in pybedtools.BedTool(bed_file): chroms.add(r.chrom) out = [] for r in pybedtools.BedTool(out_file): if r.chrom in chroms: out.append((r.chrom, r.start, r.stop)) return out bcbio-nextgen-1.2.9/bcbio/bam/counts.py000066400000000000000000000042431415626112400177560ustar00rootroot00000000000000"""Utilities to examine BAM counts in defined regions. These are useful for plotting comparisons between BAM files to look at differences in defined or random regions. """ from __future__ import print_function import random import collections import pysam class NormalizedBam: """Prepare and query an alignment BAM file for normalized read counts. """ def __init__(self, name, fname, picard, quick=False): self.name = name self._bam = pysam.Samfile(fname, "rb") picard.run_fn("picard_index", fname) if quick: self._total = 1e6 else: self._total = sum(1 for r in self._bam.fetch() if not r.is_unmapped) print(name, self._total) def all_regions(self): """Get a tuple of all chromosome, start and end regions. """ regions = [] for sq in self._bam.header["SQ"]: regions.append((sq["SN"], 1, int(sq["LN"]))) return regions def read_count(self, space, start, end): """Retrieve the normalized read count in the provided region. """ read_counts = 0 for read in self._bam.fetch(space, start, end): read_counts += 1 return self._normalize(read_counts, self._total) def coverage_pileup(self, space, start, end): """Retrieve pileup coverage across a specified region. """ return ((col.pos, self._normalize(col.n, self._total)) for col in self._bam.pileup(space, start, end)) def _normalize(self, count, total): """Normalize to reads per million. """ return float(count) / float(total) * 1e6 def random_regions(base, n, size): """Generate n random regions of 'size' in the provided base spread. """ spread = size // 2 base_info = collections.defaultdict(list) for space, start, end in base: base_info[space].append(start + spread) base_info[space].append(end - spread) regions = [] for _ in range(n): space = random.choice(base_info.keys()) pos = random.randint(min(base_info[space]), max(base_info[space])) regions.append([space, pos-spread, pos+spread]) return regions bcbio-nextgen-1.2.9/bcbio/bam/coverage.py000066400000000000000000000142511415626112400202360ustar00rootroot00000000000000""" calculate coverage across a list of regions """ import os import six import pandas as pd import pybedtools from bcbio import utils from bcbio.utils import rbind, file_exists from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction import bcbio.pipeline.datadict as dd from bcbio.pipeline import config_utils from collections import defaultdict from itertools import repeat mpl = utils.LazyImport("matplotlib") plt = utils.LazyImport("matplotlib.pyplot") pylab = utils.LazyImport("pylab") backend_pdf = utils.LazyImport("matplotlib.backends.backend_pdf") sns = utils.LazyImport("seaborn") def _calc_regional_coverage(in_bam, chrom, start, end, samplename, work_dir, data): """ given a BAM and a region, calculate the coverage for each base in that region. returns a pandas dataframe of the format: chrom position coverage name where the samplename column is the coverage at chrom:position """ region_bt = pybedtools.BedTool("%s\t%s\t%s\n" % (chrom, start, end), from_string=True).saveas() region_file = region_bt.fn coords = "%s:%s-%s" % (chrom, start, end) tx_tmp_file = os.path.join(work_dir, "coverage-%s-%s.txt" % (samplename, coords.replace(":", "_"))) samtools = config_utils.get_program("samtools", data) bedtools = config_utils.get_program("bedtools", data) cmd = ("{samtools} view -b {in_bam} {coords} | " "{bedtools} coverage -a {region_file} -b - -d > {tx_tmp_file}") do.run(cmd.format(**locals()), "Plotting coverage for %s %s" % (samplename, coords)) names = ["chom", "start", "end", "offset", "coverage"] df = pd.io.parsers.read_csv(tx_tmp_file, sep="\t", header=None, names=names).dropna() os.remove(tx_tmp_file) df["sample"] = samplename df["chrom"] = chrom df["position"] = df["start"] + df["offset"] - 1 return df[["chrom", "position", "coverage", "sample"]] def _combine_regional_coverage(in_bams, samplenames, chrom, start, end, work_dir, data): """ given a list of bam files, sample names and a region, calculate the coverage in the region for each of the samples and return a tidy pandas dataframe of the format: chrom position coverage name """ dfs = [_calc_regional_coverage(bam, chrom, start, end, sample, work_dir, data) for bam, sample in zip(in_bams, samplenames)] return rbind(dfs) def _get_caller_colormap(callers): colors = mpl.colors.ColorConverter.colors.keys() return {caller: colors[index] for index, caller in enumerate(callers)} def _get_caller_heights(callers, plot): max_y = plot.get_ylim()[1] * 0.2 spacing = max_y / len(callers) return {caller: spacing + spacing * index for index, caller in enumerate(callers)} def _get_stems_by_callers(intervals): stems = defaultdict(list) for interval in intervals: pos = interval.start caller = interval.fields[3] stems[caller].append(pos) return stems def _add_stems_to_plot(interval, stem_bed, samples, plot): stems = _get_stems_by_callers(stem_bed.tabix_intervals(interval)) callers = sorted(stems.keys()) caller_colormap = _get_caller_colormap(callers) caller_heights = _get_caller_heights(callers, plot) for caller in callers: stem_color = caller_colormap[caller] caller_stems = stems[caller] stem_heights = list(repeat(caller_heights[caller], len(caller_stems))) markerline, _, baseline = pylab.stem(caller_stems, stem_heights, '-.', label=caller) pylab.setp(markerline, 'markerfacecolor', stem_color) pylab.setp(baseline, 'color', 'r', 'linewidth', 0) plt.legend() def _split_regions(chrom, start, end): """Split regions longer than 100kb into smaller sections. """ window_size = 1e5 if end - start < window_size * 5: return [(chrom, start, end)] else: out = [] for r in pybedtools.BedTool().window_maker(w=window_size, b=pybedtools.BedTool("%s\t%s\t%s" % (chrom, start, end), from_string=True)): out.append((r.chrom, r.start, r.end)) return out def plot_multiple_regions_coverage(samples, out_file, data, region_bed=None, stem_bed=None): """ given a list of bcbio samples and a bed file or BedTool of regions, makes a plot of the coverage in the regions for the set of samples if given a bed file or BedTool of locations in stem_bed with a label, plots lollipops at those locations """ mpl.use('Agg', force=True) PAD = 100 if file_exists(out_file): return out_file in_bams = [dd.get_align_bam(x) for x in samples] samplenames = [dd.get_sample_name(x) for x in samples] if isinstance(region_bed, six.string_types): region_bed = pybedtools.BedTool(region_bed) if isinstance(stem_bed, six.string_types): stem_bed = pybedtools.BedTool(stem_bed) if stem_bed is not None: # tabix indexed bedtools eval to false stem_bed = stem_bed.tabix() plt.clf() plt.cla() with file_transaction(out_file) as tx_out_file: with backend_pdf.PdfPages(tx_out_file) as pdf_out: sns.despine() for line in region_bed: for chrom, start, end in _split_regions(line.chrom, max(line.start - PAD, 0), line.end + PAD): df = _combine_regional_coverage(in_bams, samplenames, chrom, start, end, os.path.dirname(tx_out_file), data) plot = sns.tsplot(df, time="position", unit="chrom", value="coverage", condition="sample") if stem_bed is not None: # tabix indexed bedtools eval to false interval = pybedtools.Interval(chrom, start, end) _add_stems_to_plot(interval, stem_bed, samples, plot) plt.title("{chrom}:{start}-{end}".format(**locals())) pdf_out.savefig(plot.get_figure()) plt.close() return out_file bcbio-nextgen-1.2.9/bcbio/bam/cram.py000066400000000000000000000047541415626112400173740ustar00rootroot00000000000000"""Handle conversions to/from CRAM reference based compression. """ import os import subprocess from bcbio import bam, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd, config_utils from bcbio.provenance import do def compress(in_bam, data): """Compress a BAM file to CRAM, providing indexed CRAM file. Does 8 bin compression of quality score and read name removal using Staden io_lib if `cram` specified: https://github.com/jkbonfield/io_lib Otherwise does `cram-lossless` which only converts to CRAM. """ out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "archive")) out_file = os.path.join(out_dir, "%s.cram" % os.path.splitext(os.path.basename(in_bam))[0]) cores = dd.get_num_cores(data) ref_file = dd.get_ref_file(data) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: compress_type = dd.get_archive(data) scramble = config_utils.get_program("scramble", data["config"]) cmd = [scramble, "-I", "bam", "-O", "cram", "-9", "-r", ref_file, "-V", "3.0", "-t", cores, in_bam, tx_out_file] compressed = False if "cram" in compress_type: try: cmd.extend(["-B", "-n"]) do.run(cmd, "Compress BAM to CRAM: quality score binning") compressed = True except subprocess.CalledProcessError: pass if not compressed: do.run(cmd, "Compress BAM to CRAM: lossless") index(out_file, data["config"]) return out_file def index(in_cram, config): """Ensure CRAM file has a .crai index file. """ out_file = in_cram + ".crai" if not utils.file_uptodate(out_file, in_cram): with file_transaction(config, in_cram + ".crai") as tx_out_file: tx_in_file = os.path.splitext(tx_out_file)[0] utils.symlink_plus(in_cram, tx_in_file) cmd = ["cram_index", tx_in_file] do.run(cmd, "Index CRAM file") return out_file def to_bam(in_file, out_file, data): """Convert CRAM file into BAM. """ if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: cmd = ["samtools", "view", "-O", "BAM", "-o", tx_out_file, in_file] do.run(cmd, "Convert CRAM to BAM") bam.index(out_file, data["config"]) return out_file bcbio-nextgen-1.2.9/bcbio/bam/fasta.py000066400000000000000000000025741415626112400175460ustar00rootroot00000000000000from Bio import SeqIO from bcbio.utils import file_exists from bcbio.distributed.transaction import file_transaction def sequence_length(fasta): """ return a dict of the lengths of sequences in a fasta file """ sequences = SeqIO.parse(fasta, "fasta") records = {record.id: len(record) for record in sequences} return records def sequence_names(fasta): """ return a list of the sequence IDs in a FASTA file """ sequences = SeqIO.parse(fasta, "fasta") records = [record.id for record in sequences] return records def total_sequence_length(fasta): """ return the total length of all sequences in a FASTA file """ return sum([x for x in sequence_length(fasta).values()]) def strip_transcript_versions(fasta, out_file): """ strip transcript versions from a FASTA file. these appear like this: >ENST00000434970.2 cdna chromosome:GRCh38:14:22439007:22439015:1 etc """ if file_exists(out_file): return out_file with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: with open(fasta) as in_handle: for line in in_handle: if line.startswith(">"): out_handle.write(line.split(" ")[0].split(".")[0] + "\n") else: out_handle.write(line) return out_file bcbio-nextgen-1.2.9/bcbio/bam/fastq.py000066400000000000000000000303521415626112400175610ustar00rootroot00000000000000"""Utilities for working with fastq files. """ import six from six.moves import zip from itertools import product import os import random import sys import toolz as tz from collections import defaultdict from Bio import SeqIO from bcbio.distributed import objectstore from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio import utils from bcbio.utils import open_possible_gzip, sort_filenames from bcbio.pipeline import config_utils from bcbio.provenance import do @utils.memoize_outfile(stem=".groom") def groom(in_file, data, in_qual="illumina", out_dir=None, out_file=None): """ Grooms a FASTQ file from Illumina 1.3/1.5 quality scores into sanger format, if it is not already in that format. """ if not out_file.endswith("gz"): out_file = "%s.gz" % out_file seqtk = config_utils.get_program("seqtk", data["config"]) if in_qual == "fastq-sanger": logger.info("%s is already in Sanger format." % in_file) return out_file with file_transaction(out_file) as tmp_out_file: cmd = "{seqtk} seq -Q64 {in_file} | gzip > {tmp_out_file}".format(**locals()) do.run(cmd, "Converting %s to Sanger format." % in_file) return out_file @utils.memoize_outfile(stem=".fixed") def filter_single_reads_by_length(in_file, quality_format, min_length=20, out_file=None): """ removes reads from a fastq file which are shorter than a minimum length """ logger.info("Removing reads in %s thare are less than %d bases." % (in_file, min_length)) in_iterator = SeqIO.parse(in_file, quality_format) out_iterator = (record for record in in_iterator if len(record.seq) > min_length) with file_transaction(out_file) as tmp_out_file: with open(tmp_out_file, "w") as out_handle: SeqIO.write(out_iterator, out_handle, quality_format) return out_file def filter_reads_by_length(fq1, fq2, quality_format, min_length=20): """ removes reads from a pair of fastq files that are shorter than a minimum length. removes both ends of a read if one end falls below the threshold while maintaining the order of the reads """ logger.info("Removing reads in %s and %s that " "are less than %d bases." % (fq1, fq2, min_length)) fq1_out = utils.append_stem(fq1, ".fixed") fq2_out = utils.append_stem(fq2, ".fixed") fq1_single = utils.append_stem(fq1, ".singles") fq2_single = utils.append_stem(fq2, ".singles") if all(map(utils.file_exists, [fq1_out, fq2_out, fq2_single, fq2_single])): return [fq1_out, fq2_out] fq1_in = SeqIO.parse(fq1, quality_format) fq2_in = SeqIO.parse(fq2, quality_format) out_files = [fq1_out, fq2_out, fq1_single, fq2_single] with file_transaction(out_files) as tmp_out_files: fq1_out_handle = open(tmp_out_files[0], "w") fq2_out_handle = open(tmp_out_files[1], "w") fq1_single_handle = open(tmp_out_files[2], "w") fq2_single_handle = open(tmp_out_files[3], "w") for fq1_record, fq2_record in zip(fq1_in, fq2_in): if len(fq1_record.seq) >= min_length and len(fq2_record.seq) >= min_length: fq1_out_handle.write(fq1_record.format(quality_format)) fq2_out_handle.write(fq2_record.format(quality_format)) else: if len(fq1_record.seq) > min_length: fq1_single_handle.write(fq1_record.format(quality_format)) if len(fq2_record.seq) > min_length: fq2_single_handle.write(fq2_record.format(quality_format)) fq1_out_handle.close() fq2_out_handle.close() fq1_single_handle.close() fq2_single_handle.close() return [fq1_out, fq2_out] def rstrip_extra(fname): """Strip extraneous, non-discriminative filename info from the end of a file. """ to_strip = ("_R", ".R", "-R", "_", "fastq", ".", "-") while fname.endswith(to_strip): for x in to_strip: if fname.endswith(x): fname = fname[:len(fname) - len(x)] break return fname def combine_pairs(input_files, force_single=False, full_name=False, separators=None): """ calls files pairs if they are completely the same except for one has _1 and the other has _2 returns a list of tuples of pairs or singles. From bipy.utils (https://github.com/roryk/bipy/blob/master/bipy/utils.py) Adjusted to allow different input paths or extensions for matching files. """ PAIR_FILE_IDENTIFIERS = set(["1", "2", "3", "4"]) if len(input_files) > 1000: return fast_combine_pairs(input_files, force_single, full_name, separators) pairs = [] used = set([]) used_separators = set([]) separators = separators if separators else ("R", "_", "-", ".") for in_file in input_files: matches = set([]) if in_file in used: continue if not force_single: for comp_file in input_files: if comp_file in used or comp_file == in_file: continue if full_name: in_file_name = in_file comp_file_name = comp_file else: in_file_name = os.path.basename(in_file) comp_file_name = os.path.basename(comp_file) a = rstrip_extra(utils.splitext_plus(in_file_name)[0]) b = rstrip_extra(utils.splitext_plus(comp_file_name)[0]) if len(a) != len(b): continue s = dif(a,b) # no differences, then its the same file stem if len(s) == 0: logger.error("%s and %s have the same stem, so we don't know " "how to assign it to the sample data in the CSV. To " "get around this you can rename one of the files. " "If they are meant to be the same sample run in two " "lanes, combine them first with the " "bcbio_prepare_samples.py script." "(http://bcbio-nextgen.readthedocs.io/en/latest/contents/configuration.html#multiple-files-per-sample)" % (in_file, comp_file)) # continue sys.exit(1) if len(s) > 1: continue #there is more than 1 difference if (a[s[0]] in PAIR_FILE_IDENTIFIERS and b[s[0]] in PAIR_FILE_IDENTIFIERS): # if the 1/2 isn't the last digit before a separator, skip # this skips stuff like 2P 2A, often denoting replicates, not # read pairings if len(b) > (s[0] + 1): if (b[s[0]+1] not in ("_", "-", ".")): continue # if the 1/2 is not a separator or prefaced with R, skip if b[s[0] - 1] in separators: used_separators.add(b[s[0] - 1]) if len(used_separators) > 1: logger.warning("To split into paired reads multiple separators were used: %s" % used_separators) logger.warning("This can lead to wrong assignation.") logger.warning("Use --separator option in bcbio_prepare_samples.py to specify only one.") logger.warning("For instance, --separator R.") matches.update([in_file, comp_file]) used.update([in_file, comp_file]) if matches: pairs.append(sort_filenames(list(matches))) if in_file not in used: pairs.append([in_file]) used.add(in_file) return pairs def fast_combine_pairs(files, force_single, full_name, separators): """ assume files that need to be paired are within 10 entries of each other, once the list is sorted """ files = sort_filenames(files) chunks = tz.sliding_window(10, files) pairs = [combine_pairs(chunk, force_single, full_name, separators) for chunk in chunks] pairs = [y for x in pairs for y in x] longest = defaultdict(list) # for each file, save the longest pair it is in for pair in pairs: for file in pair: if len(longest[file]) < len(pair): longest[file] = pair # keep only unique pairs longest = {tuple(sort_filenames(x)) for x in longest.values()} # ensure filenames are R1 followed by R2 return [sort_filenames(list(x)) for x in longest] def dif(a, b): """ copy from http://stackoverflow.com/a/8545526 """ return [i for i in range(len(a)) if a[i] != b[i]] def is_fastq(in_file, bzip=True): fastq_ends = [".txt", ".fq", ".fastq"] zip_ends = [".gzip", ".gz"] if bzip: zip_ends += [".bz2", ".bzip2"] base, first_ext = os.path.splitext(in_file) second_ext = os.path.splitext(base)[1] if first_ext in fastq_ends: return True elif (second_ext, first_ext) in product(fastq_ends, zip_ends): return True else: return False def downsample(f1, f2, N, quick=False): """Get N random headers from a fastq file without reading the whole thing into memory modified from: http://www.biostars.org/p/6544/ quick=True will just grab the first N reads rather than do a true downsampling """ if quick: rand_records = range(N) else: records = int(sum(1 for _ in open_possible_gzip(f1)) / 4) N = records if N > records else N rand_records = sorted(random.sample(range(records), N)) fh1 = open_possible_gzip(f1) fh2 = open_possible_gzip(f2) if f2 else None outf1 = os.path.splitext(f1)[0] + ".subset" + os.path.splitext(f1)[1] outf2 = os.path.splitext(f2)[0] + ".subset" + os.path.splitext(f2)[1] if f2 else None if utils.file_exists(outf1): if not outf2: return outf1, outf2 elif utils.file_exists(outf2): return outf1, outf2 out_files = (outf1, outf2) if outf2 else (outf1) with file_transaction(out_files) as tx_out_files: if isinstance(tx_out_files, six.string_types): tx_out_f1 = tx_out_files else: tx_out_f1, tx_out_f2 = tx_out_files sub1 = open_possible_gzip(tx_out_f1, "w") sub2 = open_possible_gzip(tx_out_f2, "w") if outf2 else None rec_no = - 1 for rr in rand_records: while rec_no < rr: rec_no += 1 for i in range(4): fh1.readline() if fh2: for i in range(4): fh2.readline() for i in range(4): sub1.write(fh1.readline()) if sub2: sub2.write(fh2.readline()) rec_no += 1 fh1.close() sub1.close() if f2: fh2.close() sub2.close() return outf1, outf2 def estimate_read_length(fastq_file, quality_format="fastq-sanger", nreads=1000): """ estimate average read length of a fastq file """ average = 0 with open_fastq(fastq_file) as fastq_handle: record_iterator = SeqIO.parse(fastq_handle, quality_format) read = next(record_iterator) average = len(read.seq) for _ in range(nreads): try: average = (average + len(next(record_iterator).seq)) / 2 except StopIteration: break return average def estimate_maximum_read_length(fastq_file, quality_format="fastq-sanger", nreads=1000): """ estimate maximum read length of a fastq file """ lengths = [] with open_fastq(fastq_file) as fastq_handle: record_iterator = SeqIO.parse(fastq_handle, quality_format) for _ in range(nreads): try: lengths.append(len(next(record_iterator).seq)) except StopIteration: break return max(lengths) def open_fastq(in_file): """ open a fastq file, using gzip if it is gzipped """ if objectstore.is_remote(in_file): return objectstore.open_file(in_file) else: return utils.open_gzipsafe(in_file) bcbio-nextgen-1.2.9/bcbio/bam/readstats.py000066400000000000000000000117361415626112400204420ustar00rootroot00000000000000"""Calculation of mapped reads by BAM counting, currently implemented with samtools. """ import contextlib import json import os import time import toolz as tz from bcbio import bam, utils from bcbio.bam import ref from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction pybedtools = utils.LazyImport("pybedtools") def _backcompatible_cache_file(query_flags, bed_file, target_name, data): """Back-compatible: retrieve cache file from previous location. """ cmd_id = "num_" + " and ".join(query_flags).replace(" ", "_") if bed_file is not None: target_name = target_name or os.path.basename(bed_file) cmd_id += "_on_" + target_name work_dir = os.path.join(dd.get_work_dir(data), "coverage", dd.get_sample_name(data), "sambamba") output_file = os.path.join(work_dir, cmd_id) if utils.file_exists(output_file): return output_file def get_cache_file(data): cache_file = tz.get_in(["regions", "mapped_stats"], data) if cache_file: return cache_file else: return os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "coverage")), "mapped_stats.txt") def number_of_mapped_reads(data, bam_file, keep_dups=True, bed_file=None, target_name=None): """Count mapped reads, allow adjustment for duplicates and BED regions. Since samtools view does not use indexes for BED files (https://github.com/samtools/samtools/issues/88) we loop over regions in a BED file and add the counts together. Uses a global cache file to store counts, making it possible to pass this single file for CWL runs. For parallel processes it can have concurrent append writes, so we have a simple file locking mechanism to avoid this. """ # Flag explainer https://broadinstitute.github.io/picard/explain-flags.html callable_flags = ["not unmapped", "not mate_is_unmapped", "not secondary_alignment", "not failed_quality_control"] if keep_dups: query_flags = callable_flags flag = 780 # not (read unmapped or mate unmapped or fails QC or secondary alignment) else: query_flags = callable_flags + ["not duplicate"] flag = 1804 # as above plus not duplicate # Back compatible cache oldcache_file = _backcompatible_cache_file(query_flags, bed_file, target_name, data) if oldcache_file: with open(oldcache_file) as f: return int(f.read().strip()) # New cache key = json.dumps({"flags": sorted(query_flags), "region": os.path.basename(bed_file) if bed_file else "", "sample": dd.get_sample_name(data)}, separators=(",", ":"), sort_keys=True) cache_file = get_cache_file(data) if utils.file_exists(cache_file): with open(cache_file) as in_handle: for cur_key, cur_val in (l.strip().split("\t") for l in in_handle): if cur_key == key: return int(cur_val) # Calculate stats count_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "coverage", dd.get_sample_name(data), "counts")) if not bed_file: bed_file = os.path.join(count_dir, "fullgenome.bed") if not utils.file_exists(bed_file): with file_transaction(data, bed_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for c in ref.file_contigs(dd.get_ref_file(data), data["config"]): out_handle.write("%s\t%s\t%s\n" % (c.name, 0, c.size)) count_file = os.path.join(count_dir, "%s-%s-counts.txt" % (os.path.splitext(os.path.basename(bed_file))[0], flag)) if not utils.file_exists(count_file): bam.index(bam_file, data["config"], check_timestamp=False) num_cores = dd.get_num_cores(data) with file_transaction(data, count_file) as tx_out_file: cmd = ("hts_nim_tools count-reads -t {num_cores} -F {flag} {bed_file} {bam_file} > {tx_out_file}") do.run(cmd.format(**locals()), "Count mapped reads: %s" % (dd.get_sample_name(data))) count = 0 with open(count_file) as in_handle: for line in in_handle: count += int(line.rstrip().split()[-1]) with _simple_lock(cache_file): with open(cache_file, "a") as out_handle: out_handle.write("%s\t%s\n" % (key, count)) return count @contextlib.contextmanager def _simple_lock(f): """Simple file lock, times out after 20 second assuming lock is stale """ lock_file = f + ".lock" timeout = 20 curtime = 0 interval = 2 while os.path.exists(lock_file): time.sleep(interval) curtime += interval if curtime > timeout: os.remove(lock_file) with open(lock_file, "w") as out_handle: out_handle.write("locked") yield if os.path.exists(lock_file): os.remove(lock_file) bcbio-nextgen-1.2.9/bcbio/bam/ref.py000066400000000000000000000016701415626112400172200ustar00rootroot00000000000000"""Manipulation functionality to deal with reference files. """ import collections from bcbio import utils from bcbio.pipeline import config_utils from bcbio.provenance import do def fasta_idx(in_file, config=None): """Retrieve samtools style fasta index. """ fasta_index = in_file + ".fai" if not utils.file_exists(fasta_index): samtools = config_utils.get_program("samtools", config) if config else "samtools" cmd = "{samtools} faidx {in_file}" do.run(cmd.format(**locals()), "samtools faidx") return fasta_index def file_contigs(ref_file, config=None): """Iterator of reference contigs and lengths from a reference file. """ ContigInfo = collections.namedtuple("ContigInfo", "name size") with open(fasta_idx(ref_file, config)) as in_handle: for line in (l for l in in_handle if l.strip()): name, size = line.split()[:2] yield ContigInfo(name, int(size)) bcbio-nextgen-1.2.9/bcbio/bam/skewer.py000066400000000000000000000061421415626112400177430ustar00rootroot00000000000000import os import shutil import bcbio.pipeline.datadict as dd from bcbio.pipeline import config_utils from bcbio.distributed.transaction import tx_tmpdir from bcbio.provenance import do from bcbio.utils import safe_makedir, file_exists, flatten FW_ADAPTERS = {"truseq": ["AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC"]} RV_ADAPTERS = {"truseq": ["AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGTA"]} def trim_adapters(data): fq1, fq2 = dd.get_input_sequence_files(data) skewer = config_utils.get_program("skewer", data, default="skewer") nthreads = dd.get_num_cores(data) samplename = dd.get_sample_name(data) out_dir = safe_makedir(os.path.join(dd.get_work_dir(data), "trimmed", samplename)) of1 = os.path.join(out_dir, samplename + "-trimmed-pair1.fastq.gz") of2 = os.path.join(out_dir, samplename + "-trimmed-pair2.fastq.gz") of2 = of2 if fq2 else None if fq1 and fq2: if file_exists(of1) and file_exists(of2): return of1, of2 else: if file_exists(of1): return of1, None safe_makedir(out_dir) file_string = "{fq1} {fq2} " if fq2 else "{fq1} " mode = "tail" if not fq2 else "pe" cmd = ("{skewer} --min 25 --threads {nthreads} " "{fw_cmd} " "{rv_cmd} " "-m {mode} " "--compress --output {out_stem} ") + file_string with tx_tmpdir(data, out_dir) as tx_out_dir: safe_makedir(tx_out_dir) out_stem = os.path.join(tx_out_dir, samplename) fw_cmd = _fw_command(data, tx_out_dir) rv_cmd = _rv_command(data, tx_out_dir) message = "Trimming {fq1}, {fq2} with skewer.".format(**locals()) do.run(cmd.format(**locals()), message) shutil.move(os.path.join(tx_out_dir, os.path.basename(of1)), out_dir) shutil.move(os.path.join(tx_out_dir, os.path.basename(of2)), out_dir) shutil.move(out_stem + "-trimmed.log", out_dir) return of1, of2 def _fw_command(data, tx_out_dir): fw = _get_fw_adapters(data) if not fw: return "" else: fw_file = _write_fasta_file(fw, "forward", tx_out_dir) return "-x %s" % fw_file def _rv_command(data, tx_out_dir): rv = _get_rv_adapters(data) if not rv: return "" else: rv_file = _write_fasta_file(rv, "reverse", tx_out_dir) return "-y %s" % rv_file def _write_fasta_file(adapters, ext, tx_out_dir): tfile = os.path.join(tx_out_dir, "adapters-%s.fa" % ext) with open(tfile, "w") as out_handle: for i, adapter in enumerate(adapters): if file_exists(adapter): with open(adapter) as in_handle: for line in in_handle: out_handle.write(line) else: out_handle.write(">%d\n" % i) out_handle.write(adapter + "\n") return tfile def _get_fw_adapters(data): builtin = [FW_ADAPTERS[x] for x in dd.get_adapters(data) if x in FW_ADAPTERS] return flatten(builtin + dd.get_custom_trim(data)) def _get_rv_adapters(data): builtin = [RV_ADAPTERS[x] for x in dd.get_adapters(data) if x in FW_ADAPTERS] return flatten(builtin + dd.get_custom_trim(data)) bcbio-nextgen-1.2.9/bcbio/bam/trim.py000066400000000000000000000315051415626112400174170ustar00rootroot00000000000000"""atropos cutadapt-like multicore trimming of input reads from Fastq or BAM files. """ import os import sys from Bio.Seq import Seq from bcbio import utils from bcbio.bam.fastq import is_fastq from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.distributed import objectstore from bcbio.pipeline import config_utils from bcbio.provenance import do import bcbio.pipeline.datadict as dd SUPPORTED_ADAPTERS = { "illumina": ["AACACTCTTTCCCT", "AGATCGGAAGAGCG"], "truseq": ["AGATCGGAAGAG"], "polya": ["AAAAAAAAAAAAA"], "nextera": ["AATGATACGGCGA", "CAAGCAGAAGACG"], "truseq2": ["GATCGGAAGAGCACACGTCTGAACTCCAGTCAC", "GATCGGAAGAGCGTCGTGTAGGGAAAGAGTGTAGATCTCGGTGGTCGCCGTATCATT"], # 3'only: first read, second read "nextera2": ["CTGTCTCTTATACACATCT", "AGATGTGTATAAGAGACAG"] # Second read in pair 3', 5 } def trim_adapters(data): to_trim = [x for x in data["files"] if x is not None and is_fastq(x)] if not to_trim: return data["files"] logger.info("Trimming low quality ends and read through adapter " "sequence from %s." % (", ".join(to_trim))) out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "trimmed")) return _trim_adapters(to_trim, out_dir, data) def _trim_adapters(fastq_files, out_dir, data): """ for small insert sizes, the read length can be longer than the insert resulting in the reverse complement of the 3' adapter being sequenced. this takes adapter sequences and trims the only the reverse complement of the adapter MYSEQUENCEAAAARETPADA -> MYSEQUENCEAAAA (no polyA trim) """ to_trim = _get_sequences_to_trim(data["config"], SUPPORTED_ADAPTERS) if dd.get_trim_reads(data) == "fastp": out_files, report_file = _fastp_trim(fastq_files, to_trim, out_dir, data) else: out_files, report_file = _atropos_trim(fastq_files, to_trim, out_dir, data) # quality_format = _get_quality_format(data["config"]) # out_files = replace_directory(append_stem(fastq_files, "_%s.trimmed" % name), out_dir) # log_file = "%s_log_cutadapt.txt" % splitext_plus(out_files[0])[0] # out_files = _cutadapt_trim(fastq_files, quality_format, to_trim, out_files, log_file, data) # if file_exists(log_file): # content = open(log_file).read().replace(fastq_files[0], name) # if len(fastq_files) > 1: # content = content.replace(fastq_files[1], name) # open(log_file, 'w').write(content) return out_files # ## Atropos trimming def _atropos_trim(fastq_files, adapters, out_dir, data): """Perform multicore trimming with atropos. """ report_file = os.path.join(out_dir, "%s-report.json" % utils.splitext_plus(os.path.basename(fastq_files[0]))[0]) out_files = [os.path.join(out_dir, "%s-trimmed.fq.gz" % utils.splitext_plus(os.path.basename(x))[0]) for x in fastq_files] if not utils.file_exists(out_files[0]): with file_transaction(data, *[report_file] + out_files) as tx_out: tx_report_file, tx_out1 = tx_out[:2] if len(tx_out) > 2: tx_out2 = tx_out[2] # polyX trimming, anchored to the 3' ends of reads if "polyx" in dd.get_adapters(data): adapters += ["A{200}", "C{200}", "G{200}", "T{200}"] adapters_args = " ".join(["-a '%s'" % a for a in adapters]) adapters_args += " --overlap 8" # Avoid very short internal matches (default is 3) adapters_args += " --no-default-adapters --no-cache-adapters" # Prevent GitHub queries and saving pickles aligner_args = "--aligner adapter" if len(fastq_files) == 1: cores = dd.get_num_cores(data) input_args = "-se %s" % objectstore.cl_input(fastq_files[0]) output_args = "-o >(bgzip --threads {cores} -c > {tx_out1})".format(**locals()) else: assert len(fastq_files) == 2, fastq_files cores = max(1, dd.get_num_cores(data) // 2) adapters_args = adapters_args + " " + " ".join(["-A '%s'" % a for a in adapters]) input_args = "-pe1 %s -pe2 %s" % tuple([objectstore.cl_input(x) for x in fastq_files]) output_args = ("-o >(bgzip --threads {cores} -c > {tx_out1}) " "-p >(bgzip --threads {cores} -c > {tx_out2})").format(**locals()) quality_base = "64" if dd.get_quality_format(data).lower() == "illumina" else "33" sample_name = dd.get_sample_name(data) report_args = "--report-file %s --report-formats json --sample-id %s" % (tx_report_file, dd.get_sample_name(data)) ropts = " ".join(str(x) for x in config_utils.get_resources("atropos", data["config"]).get("options", [])) extra_opts = [] for k, alt_ks, v, want in [("--quality-cutoff", ["-q "], "5", True), ("--minimum-length", ["-m "], str(dd.get_min_read_length(data)), True), ("--nextseq-trim", [], "25", ("polyx" in dd.get_adapters(data) or "polyg" in dd.get_adapters(data)))]: if k not in ropts and not any(alt_k in ropts for alt_k in alt_ks): if want: extra_opts.append("%s=%s" % (k, v)) extra_opts = " ".join(extra_opts) thread_args = ("--threads %s" % cores if cores > 1 else "") cmd = ("atropos trim {ropts} {thread_args} --quality-base {quality_base} --format fastq " "{adapters_args} {input_args} {output_args} {report_args} {extra_opts}") do.run(cmd.format(**locals()), "Trimming with atropos: %s" % dd.get_sample_name(data)) return out_files, report_file # ## fastp trimming def _fastp_trim(fastq_files, adapters, out_dir, data): """Perform multicore trimming with fastp (https://github.com/OpenGene/fastp) """ report_file = os.path.join(out_dir, "%s-report.json" % utils.splitext_plus(os.path.basename(fastq_files[0]))[0]) out_files = [os.path.join(out_dir, "%s-trimmed.fq.gz" % utils.splitext_plus(os.path.basename(x))[0]) for x in fastq_files] if not utils.file_exists(out_files[0]): with file_transaction(data, *[report_file] + out_files) as tx_out: tx_report = tx_out[0] tx_out_files = tx_out[1:] cmd = ["fastp", "--thread", dd.get_num_cores(data)] if dd.get_quality_format(data).lower() == "illumina": cmd += ["--phred64"] for i, (inf, outf) in enumerate(zip(fastq_files, tx_out_files)): if i == 0: cmd += ["-i", inf, "-o", outf] else: cmd += ["-I", inf, "-O", outf] cmd += ["--cut_by_quality3", "--cut_mean_quality", "5", "--length_required", str(dd.get_min_read_length(data)), "--disable_quality_filtering"] if "polyx" in dd.get_adapters(data): cmd += ["--trim_poly_x", "--poly_x_min_len", "8"] if "polyx" in dd.get_adapters(data) or "polyg" in dd.get_adapters(data): cmd += ["--trim_poly_g", "--poly_g_min_len", "8"] for a in adapters: cmd += ["--adapter_sequence", a] if not adapters: cmd += ["--disable_adapter_trimming"] cmd += ["--json", report_file, "--report_title", dd.get_sample_name(data)] do.run(cmd, "Trimming with fastp: %s" % dd.get_sample_name(data)) return out_files, report_file def _get_sequences_to_trim(config, builtin): builtin_adapters = _get_builtin_adapters(config, builtin) polya = builtin_adapters.get("polya", [None])[0] # allow for trimming of custom sequences for advanced users custom_trim = config["algorithm"].get("custom_trim", []) builtin_adapters = {k: v for k, v in builtin_adapters.items() if k != "polya"} trim_sequences = custom_trim # for unstranded RNA-seq, libraries, both polyA and polyT can appear # at the 3' end as well if polya: trim_sequences += [polya, str(Seq(polya).reverse_complement())] # also trim the reverse complement of the adapters for _, v in builtin_adapters.items(): trim_sequences += [str(Seq(sequence)) for sequence in v] trim_sequences += [str(Seq(sequence).reverse_complement()) for sequence in v] out = [] for trim in trim_sequences: if utils.file_exists(trim): out.append("file:%s" % trim) else: out.append(trim) return out def _get_quality_format(config): SUPPORTED_FORMATS = ["illumina", "standard"] quality_format = dd.get_quality_format(data).lower() if quality_format not in SUPPORTED_FORMATS: logger.error("quality_format is set to an unsupported format. " "Supported formats are %s." % (", ".join(SUPPORTED_FORMATS))) exit(1) return quality_format def _get_builtin_adapters(config, builtin): chemistries = config["algorithm"].get("adapters", []) adapters = {chemistry: builtin[chemistry] for chemistry in chemistries if chemistry in builtin} return adapters # Older cutadapt approach, to remove after review def _cutadapt_trim(fastq_files, quality_format, adapters, out_files, log_file, data): """Trimming with cutadapt. """ if all([utils.file_exists(x) for x in out_files]): return out_files cmd = _cutadapt_trim_cmd(fastq_files, quality_format, adapters, out_files, data) if len(fastq_files) == 1: of = [out_files[0], log_file] message = "Trimming %s in single end mode with cutadapt." % (fastq_files[0]) with file_transaction(data, of) as of_tx: of1_tx, log_tx = of_tx do.run(cmd.format(**locals()), message) else: of = out_files + [log_file] with file_transaction(data, of) as tx_out_files: of1_tx, of2_tx, log_tx = tx_out_files tmp_fq1 = utils.append_stem(of1_tx, ".tmp") tmp_fq2 = utils.append_stem(of2_tx, ".tmp") singles_file = of1_tx + ".single" message = "Trimming %s and %s in paired end mode with cutadapt." % (fastq_files[0], fastq_files[1]) do.run(cmd.format(**locals()), message) return out_files def _cutadapt_trim_cmd(fastq_files, quality_format, adapters, out_files, data): """Trimming with cutadapt, using version installed with bcbio-nextgen. """ if all([utils.file_exists(x) for x in out_files]): return out_files if quality_format == "illumina": quality_base = "64" else: quality_base = "33" # --times=2 tries twice remove adapters which will allow things like: # realsequenceAAAAAAadapter to remove both the poly-A and the adapter # this behavior might not be what we want; we could also do two or # more passes of cutadapt cutadapt = os.path.join(os.path.dirname(sys.executable), "cutadapt") adapter_cmd = " ".join(map(lambda x: "-a " + x, adapters)) ropts = " ".join(str(x) for x in config_utils.get_resources("cutadapt", data["config"]).get("options", [])) base_cmd = ("{cutadapt} {ropts} --times=2 --quality-base={quality_base} " "--quality-cutoff=5 --format=fastq " "{adapter_cmd} ").format(**locals()) if len(fastq_files) == 2: # support for the single-command paired trimming introduced in # cutadapt 1.8 adapter_cmd = adapter_cmd.replace("-a ", "-A ") base_cmd += "{adapter_cmd} ".format(adapter_cmd=adapter_cmd) return _cutadapt_pe_cmd(fastq_files, out_files, quality_format, base_cmd, data) else: return _cutadapt_se_cmd(fastq_files, out_files, base_cmd, data) def _cutadapt_se_cmd(fastq_files, out_files, base_cmd, data): """ this has to use the -o option, not redirect to stdout in order for gzipping to be supported """ min_length = dd.get_min_read_length(data) cmd = base_cmd + " --minimum-length={min_length} ".format(**locals()) fq1 = objectstore.cl_input(fastq_files[0]) of1 = out_files[0] cmd += " -o {of1_tx} " + str(fq1) cmd = "%s | tee > {log_tx}" % cmd return cmd def _cutadapt_pe_cmd(fastq_files, out_files, quality_format, base_cmd, data): """ run cutadapt in paired end mode """ fq1, fq2 = [objectstore.cl_input(x) for x in fastq_files] of1, of2 = out_files base_cmd += " --minimum-length={min_length} ".format(min_length=dd.get_min_read_length(data)) first_cmd = base_cmd + " -o {of1_tx} -p {of2_tx} " + fq1 + " " + fq2 return first_cmd + "| tee > {log_tx};" bcbio-nextgen-1.2.9/bcbio/bed/000077500000000000000000000000001415626112400160615ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/bed/__init__.py000066400000000000000000000040201415626112400201660ustar00rootroot00000000000000import pybedtools as bt from bcbio.utils import file_exists from bcbio import utils def decomment(bed_file, out_file): """ clean a BED file """ if file_exists(out_file): return out_file with utils.open_gzipsafe(bed_file) as in_handle, open(out_file, "w") as out_handle: for line in in_handle: if line.startswith("#") or line.startswith("browser") or line.startswith("track"): continue else: out_handle.write(line) return out_file def concat(bed_files, catted=None): """ recursively concat a set of BED files, returning a sorted bedtools object of the result """ bed_files = [x for x in bed_files if x] if len(bed_files) == 0: if catted: # move to a .bed extension for downstream tools if not already sorted_bed = catted.sort() if not sorted_bed.fn.endswith(".bed"): return sorted_bed.moveto(sorted_bed.fn + ".bed") else: return sorted_bed else: return catted if not catted: bed_files = list(bed_files) catted = bt.BedTool(bed_files.pop()) else: catted = catted.cat(bed_files.pop(), postmerge=False, force_truncate=False) return concat(bed_files, catted) def merge(bedfiles): """ given a BED file or list of BED files merge them an return a bedtools object """ if isinstance(bedfiles, list): catted = concat(bedfiles) else: catted = concat([bedfiles]) if catted: return concat(bedfiles).sort().merge() else: return catted def minimize(bed_file): """ strip a BED file down to its three necessary columns: chrom start end """ if not bed_file: return bed_file else: sorted_bed = bt.BedTool(bed_file).cut(range(3)).sort() if not sorted_bed.fn.endswith(".bed"): return sorted_bed.moveto(sorted_bed.fn + ".bed") else: return sorted_bed bcbio-nextgen-1.2.9/bcbio/broad/000077500000000000000000000000001415626112400164165ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/broad/__init__.py000066400000000000000000000631221415626112400205330ustar00rootroot00000000000000"""Work with Broad's Java libraries from Python. Picard -- BAM manipulation and analysis library. GATK -- Next-generation sequence processing. """ from contextlib import closing from distutils.version import LooseVersion import getpass import re import sys import os import subprocess import toolz as tz from bcbio import setpath, utils from bcbio.broad import picardrun from bcbio.distributed.transaction import tx_tmpdir from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do, programs def get_default_jvm_opts(tmp_dir=None, parallel_gc=False): """Retrieve default JVM tuning options Avoids issues with multiple spun up Java processes running into out of memory errors. Parallel GC can use a lot of cores on big machines and primarily helps reduce task latency and responsiveness which are not needed for batch jobs. https://github.com/bcbio/bcbio-nextgen/issues/532#issuecomment-50989027 https://wiki.csiro.au/pages/viewpage.action?pageId=545034311 http://stackoverflow.com/questions/9738911/javas-serial-garbage-collector-performing-far-better-than-other-garbage-collect However, serial GC causes issues with Spark local runs so we use parallel for those cases: https://github.com/broadinstitute/gatk/issues/3605#issuecomment-332370070 """ opts = ["-XX:+UseSerialGC"] if not parallel_gc else [] if tmp_dir: opts.append("-Djava.io.tmpdir=%s" % tmp_dir) return opts def _get_gatk_opts(config, names, tmp_dir=None, memscale=None, include_gatk=True, parallel_gc=False): """Retrieve GATK memory specifications, moving down a list of potential specifications. """ if include_gatk and "gatk4" in dd.get_tools_off({"config": config}): opts = ["-U", "LENIENT_VCF_PROCESSING", "--read_filter", "BadCigar", "--read_filter", "NotPrimaryAlignment"] else: opts = [] jvm_opts = ["-Xms750m", "-Xmx2g"] for n in names: resources = config_utils.get_resources(n, config) if resources and resources.get("jvm_opts"): jvm_opts = resources.get("jvm_opts") break if memscale: jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": memscale}}) jvm_opts += get_default_jvm_opts(tmp_dir, parallel_gc=parallel_gc) return jvm_opts + opts def get_gatk_opts(config, tmp_dir=None, memscale=None, include_gatk=True, parallel_gc=False): return _get_gatk_opts(config, ["gatk"], tmp_dir, memscale, include_gatk=include_gatk, parallel_gc=parallel_gc) def get_gatk_vqsr_opts(config, tmp_dir=None, memscale=None): return _get_gatk_opts(config, ["gatk-vqsr", "gatk"], tmp_dir, memscale) def get_picard_opts(config, memscale=None): return _get_gatk_opts(config, ["picard", "gatk"], memscale=memscale, include_gatk=False) def _clean_java_out(version_str): """Remove extra environmental information reported in java when querying for versions. Java will report information like _JAVA_OPTIONS environmental variables in the output. """ out = [] for line in version_str.split("\n"): if line.startswith("Picked up"): pass if line.find("setlocale") > 0: pass else: out.append(line) return "\n".join(out) def _check_for_bad_version(version, program): if version.find("bad major version") >= 0 or version.find("UnsupportedClassVersionError") >= 0: raise ValueError("Problem getting version for %s. " "This often indicates you're not running the correct Java version:\n%s" % (program, version)) def get_gatk_version(gatk_jar=None, config=None): if gatk_jar: cl = " ".join(["java", "-Xms128m", "-Xmx256m"] + get_default_jvm_opts() + ["-jar", gatk_jar, "-version"]) else: cl = gatk_cmd("gatk", ["-Xms128m", "-Xmx256m"] + get_default_jvm_opts(), ["-version"], config=config) with closing(subprocess.Popen(cl, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True).stdout) as stdout: stdout = stdout.read().decode().strip() out = _clean_java_out(stdout) # Historical GATK version (2.4) and newer versions (4.1.0.0) # have a flag in front of output version version = out flag = "The Genome Analysis Toolkit (GATK)" for line in out.split("\n"): if line.startswith(flag): version = line.split(flag)[-1].split(",")[0].strip() if version.startswith("v"): version = version[1:] _check_for_bad_version(version, "GATK") return version def get_mutect_version(mutect_jar): """Retrieves version from input jar name since there is not an easy way to get MuTect version. Check mutect jar for SomaticIndelDetector, which is an Appistry feature """ cl = ["java", "-Xms128m", "-Xmx256m"] + get_default_jvm_opts() + ["-jar", mutect_jar, "-h"] with closing(subprocess.Popen(cl, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout) as stdout: stdout = stdout.read().decode().strip() if "SomaticIndelDetector" in stdout: mutect_type = "-appistry" else: mutect_type = "" version = os.path.basename(mutect_jar).lower() for to_remove in [".jar", "-standalone", "mutect"]: version = version.replace(to_remove, "") if version.startswith(("-", ".")): version = version[1:] if not version: raise ValueError("Unable to determine MuTect version from jar file. " "Need to have version contained in jar (ie. muTect-1.1.5.jar): %s" % mutect_jar) _check_for_bad_version(version, "MuTect") return version + mutect_type def fix_missing_spark_user(cl, prog, params): """Adjust /etc/passwd and GATK parameters if current username missing. Set Spark user to avoid lookup errors on environments like Docker where we run as a user id that is not present in /etc/passwd https://stackoverflow.com/questions/45198252/apache-spark-standalone-for-anonymous-uid-without-user-name/45361221#45361221 https://github.com/jaceklaskowski/mastering-apache-spark-book/blob/master/spark-sparkcontext-creating-instance-internals.adoc#-utilsgetcurrentusername https://blog.openshift.com/jupyter-on-openshift-part-6-running-as-an-assigned-user-id/ """ if prog.find("Spark") >= 0 or "--spark-master" in params: user = None try: user = getpass.getuser() except KeyError: if os.access("/etc/passwd", os.W_OK): with open("/etc/passwd", "a") as out_handle: out_handle.write("sparkanon:x:{uid}:{uid}:sparkanon:/nonexistent:/usr/sbin/nologin\n" .format(uid=os.getuid())) try: user = getpass.getuser() except KeyError: pass if user: cl = "export SPARK_USER=%s && " % (user) + cl return cl class BroadRunner: """Simplify running Broad commandline tools. """ def __init__(self, picard_ref, gatk_dir, config): resources = config_utils.get_resources("gatk", config) self._jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx2g"]) self._picard_ref = config_utils.expand_path(picard_ref) self._gatk_dir = config_utils.expand_path(gatk_dir) or config_utils.expand_path(picard_ref) self._config = config self._gatk_version, self._gatk4_version, self._picard_version, self._mutect_version = ( None, None, None, None) self._gatk_resources = resources def _set_default_versions(self, config): """Retrieve pre-computed version information for expensive to retrieve versions. Starting up GATK takes a lot of resources so we do it once at start of analysis. """ out = [] for name in ["gatk", "gatk4", "picard", "mutect"]: v = tz.get_in(["resources", name, "version"], config) if not v: try: v = programs.get_version(name, config=config) except KeyError: v = None out.append(v) self._gatk_version, self._gatk4_version, self._picard_version, self._mutect_version = out def new_resources(self, program): """Set new resource usage for the given program. This allows customization of memory usage for particular sub-programs of GATK like HaplotypeCaller. """ resources = config_utils.get_resources(program, self._config) if resources.get("jvm_opts"): self._jvm_opts = resources.get("jvm_opts") def run_fn(self, name, *args, **kwds): """Run pre-built functionality that used Broad tools by name. See the gatkrun, picardrun module for available functions. """ fn = None to_check = [picardrun] for ns in to_check: try: fn = getattr(ns, name) break except AttributeError: pass assert fn is not None, "Could not find function %s in %s" % (name, to_check) return fn(self, *args, **kwds) def cl_picard(self, command, options, memscale=None): """Prepare a Picard commandline. """ options = ["%s=%s" % (x, y) for x, y in options] options.append("VALIDATION_STRINGENCY=SILENT") return self._get_picard_cmd(command, memscale=memscale) + options def run(self, command, options, pipe=False, get_stdout=False, memscale=None): """Run a Picard command with the provided option pairs. """ cl = self.cl_picard(command, options, memscale=memscale) if pipe: subprocess.Popen(cl) elif get_stdout: p = subprocess.Popen(cl, stdout=subprocess.PIPE) stdout = p.stdout.read() p.wait() p.stdout.close() return stdout else: do.run(cl, "Picard {0}".format(command), None) def get_picard_version(self, command): if self._picard_version is None: self._set_default_versions(self._config) if self._picard_version: return self._picard_version if os.path.isdir(self._picard_ref): picard_jar = self._get_jar(command) cl = ["java", "-Xms64m", "-Xmx128m"] + get_default_jvm_opts() + ["-jar", picard_jar] else: cl = [self._picard_ref, command] cl += ["--version"] p = subprocess.Popen(cl, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # fix for issue #494 pat = re.compile(r'([\d|\.]*)(\(\d*\)$)') # matches '1.96(1510)' m = pat.search(p.stdout.read()) version = m.group(1) self._picard_version = version p.wait() p.stdout.close() return version def _has_gatk_conda_wrapper(self): cmd = gatk_cmd("gatk", [], ["--version"], config=self._config) if cmd: if "gatk4" not in dd.get_tools_off({"config": self._config}): return True else: try: stdout = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True, encoding="UTF-8") return stdout.find("GATK jar file not found") == -1 except subprocess.CalledProcessError: return False def has_gatk(self): if self._has_gatk_conda_wrapper(): return True else: jar = self._get_jar("GenomeAnalysisTK", ["GenomeAnalysisTKLite"], allow_missing=True) return jar is not None def cl_gatk(self, params, tmp_dir, memscale=None, parallel_gc=False): support_nt = set() support_nct = set(["BaseRecalibrator"]) if self._has_gatk_conda_wrapper(): gatk_jar = None else: gatk_jar = self._get_jar("GenomeAnalysisTK", ["GenomeAnalysisTKLite"], allow_missing=True) if not gatk_jar: raise ValueError("GATK processing requested but gatk or older jar install not found: " "http://bcbio-nextgen.readthedocs.io/en/latest/contents/" "installation.html#gatk-and-mutect-mutect2") is_gatk4 = "gatk4" not in dd.get_tools_off({"config": self._config}) cores = self._config["algorithm"].get("num_cores", 1) config = self._config atype_index = params.index("-T") if params.count("-T") > 0 \ else params.index("--analysis_type") prog = params[atype_index + 1] # For GATK4 specify command first, so swap params to accomplish if is_gatk4: params = params[:] del params[atype_index + 1] del params[atype_index] params = [prog] + params if cores and int(cores) > 1: if prog in support_nt: params.extend(["-nt", str(cores)]) elif prog in support_nct: params.extend(["-nct", str(cores)]) memscale = config["algorithm"]["memory_adjust"] = {"direction": "increase", "magnitude": max(1, int(cores) // 2)} # Filters and unsafe specifications not in GATK4 if LooseVersion(self.gatk_major_version()) > LooseVersion("1.9") and not is_gatk4: if len([x for x in params if x.startswith(("-U", "--unsafe"))]) == 0: params.extend(["-U", "LENIENT_VCF_PROCESSING"]) params.extend(["--read_filter", "BadCigar", "--read_filter", "NotPrimaryAlignment"]) if memscale: jvm_opts = get_gatk_opts(config, tmp_dir=tmp_dir, memscale=memscale, include_gatk=False, parallel_gc=parallel_gc) else: # Decrease memory slightly from configuration to avoid memory allocation errors jvm_opts = config_utils.adjust_opts(self._jvm_opts, {"algorithm": {"memory_adjust": {"magnitude": 1.1, "direction": "decrease"}}}) jvm_opts += get_default_jvm_opts(tmp_dir, parallel_gc=parallel_gc) if "keyfile" in self._gatk_resources: params = ["-et", "NO_ET", "-K", self._gatk_resources["keyfile"]] + params if gatk_jar: return " ".join(["java"] + jvm_opts + ["-jar", gatk_jar] + [str(x) for x in params]) else: cmd = gatk_cmd("gatk", jvm_opts, params, config=self._config) if cmd: return cmd else: raise ValueError("GATK processing requested but gatk or older jar install not found: " "http://bcbio-nextgen.readthedocs.io/en/latest/contents/" "installation.html#gatk-and-mutect-mutect2") def cl_mutect(self, params, tmp_dir): """Define parameters to run the mutect paired algorithm. """ gatk_jar = self._get_jar("muTect", ["mutect"]) # Decrease memory slightly from configuration to avoid memory allocation errors jvm_opts = config_utils.adjust_opts(self._jvm_opts, {"algorithm": {"memory_adjust": {"magnitude": 1.1, "direction": "decrease"}}}) return ["java"] + jvm_opts + get_default_jvm_opts(tmp_dir) + \ ["-jar", gatk_jar] + [str(x) for x in params] def run_gatk(self, params, tmp_dir=None, log_error=True, data=None, region=None, memscale=None, parallel_gc=False, ld_preload=False): """Top level interface to running a GATK command. ld_preload injects required libraries for Java JNI calls: https://gatkforums.broadinstitute.org/gatk/discussion/8810/something-about-create-pon-workflow """ needs_java7 = LooseVersion(self.get_gatk_version()) < LooseVersion("3.6") # For old Java requirements use global java 7 if needs_java7: setpath.remove_bcbiopath() with tx_tmpdir(self._config) as local_tmp_dir: if tmp_dir is None: tmp_dir = local_tmp_dir cl = self.cl_gatk(params, tmp_dir, memscale=memscale, parallel_gc=parallel_gc) atype_index = params.index("-T") if params.count("-T") > 0 \ else params.index("--analysis_type") prog = params[atype_index + 1] cl = fix_missing_spark_user(cl, prog, params) if ld_preload: cl = "export LD_PRELOAD=%s/lib/libopenblas.so && %s" % (os.path.dirname(utils.get_bcbio_bin()), cl) do.run(cl, "GATK: {0}".format(prog), data, region=region, log_error=log_error) if needs_java7: setpath.prepend_bcbiopath() def run_mutect(self, params, tmp_dir=None): with setpath.orig_paths(): with tx_tmpdir(self._config) as local_tmp_dir: if tmp_dir is None: tmp_dir = local_tmp_dir cl = self.cl_mutect(params, tmp_dir) prog = "MuTect" do.run(cl, "MuTect: {0}".format(prog), None) def get_gatk_version(self): """Retrieve GATK version, handling locally and config cached versions. Calling version can be expensive due to all the startup and shutdown of JVMs, so we prefer cached version information. """ if self._gatk_version is None: self._set_default_versions(self._config) if "gatk4" not in dd.get_tools_off({"config": self._config}): # In cases where we don't have manifest versions. Not possible to get # version from commandline with GATK4 alpha version if self._gatk4_version is None: self._gatk4_version = "4.0" return self._gatk4_version elif self._gatk_version is not None: return self._gatk_version else: if self._has_gatk_conda_wrapper(): gatk_jar = None else: gatk_jar = self._get_jar("GenomeAnalysisTK", ["GenomeAnalysisTKLite"], allow_missing=True) self._gatk_version = get_gatk_version(gatk_jar, config=self._config) return self._gatk_version def get_mutect_version(self): """Retrieve the Mutect version. """ if self._mutect_version is None: mutect_jar = self._get_jar("muTect", ["mutect"]) self._mutect_version = get_mutect_version(mutect_jar) return self._mutect_version def gatk_type(self): """Retrieve type of GATK jar, allowing support for older GATK lite. Returns either `lite` (targeting GATK-lite 2.3.9) or `restricted`, the latest 2.4+ restricted version of GATK. """ if LooseVersion(self.gatk_major_version()) > LooseVersion("3.9"): return "gatk4" elif LooseVersion(self.gatk_major_version()) > LooseVersion("2.3"): return "restricted" else: return "lite" def gatk_major_version(self): """Retrieve the GATK major version, handling multiple GATK distributions. Has special cases for GATK nightly builds, Appistry releases and GATK prior to 2.3. """ full_version = self.get_gatk_version() # Working with a recent version if using nightlies if full_version.startswith("nightly-"): return "3.6" parts = full_version.split("-") if len(parts) == 4: appistry_release, version, subversion, githash = parts elif len(parts) == 3: version, subversion, githash = parts elif len(parts) == 2: version, subversion = parts elif len(parts) == 1: version = parts[0] # version was not properly implemented in earlier GATKs else: version = "2.3" if version.startswith("v"): version = version[1:] return version def _get_picard_cmd(self, command, memscale=None): """Retrieve the base Picard command, handling both shell scripts and directory of jars. """ resources = config_utils.get_resources("picard", self._config) if memscale: jvm_opts = get_picard_opts(self._config, memscale=memscale) elif resources.get("jvm_opts"): jvm_opts = resources.get("jvm_opts") else: jvm_opts = self._jvm_opts if os.path.isdir(self._picard_ref): dist_file = self._get_jar(command) return ["java"] + jvm_opts + get_default_jvm_opts() + ["-jar", dist_file] else: # XXX Cannot currently set JVM opts with picard-tools script return [self._picard_ref, command] def _get_jar(self, command, alts=None, allow_missing=False): """Retrieve the jar for running the specified command. """ dirs = [] for bdir in [self._gatk_dir, self._picard_ref]: dirs.extend([bdir, os.path.join(bdir, os.pardir, "gatk")]) if alts is None: alts = [] for check_cmd in [command] + alts: for dir_check in dirs: try: check_file = config_utils.get_jar(check_cmd, dir_check) return check_file except ValueError as msg: if str(msg).find("multiple") > 0: raise else: pass if allow_missing: return None else: raise ValueError("Could not find jar %s in %s:%s" % (command, self._picard_ref, self._gatk_dir)) def _get_picard_ref(config): """Handle retrieval of Picard for running, handling multiple cases: - A directory of jar files corresponding to individual commands. - The ubuntu/debian picard-tools commandline, which provides a shell wrapper around a shared jar. For a directory, configure resources with: picard: dir: /path/to/jars For the debian commandline, configure with: picard: cmd: picard-tools """ try: picard = config_utils.get_program("picard", config, default="notfound") except config_utils.CmdNotFound: picard = "notfound" if picard == "notfound" or os.path.isdir(picard): picard = config_utils.get_program("picard", config, "dir") return picard def runner_from_config(config, program="gatk"): # Try to retrieve old style GATK try: pdir = config_utils.get_program(program, config, "dir") # otherwise use new-style bioconda except ValueError: pdir = None return BroadRunner(_get_picard_ref(config), pdir, config) def runner_from_config_safe(config): """Retrieve a runner, returning None if GATK is not available. """ try: return runner_from_config(config) except ValueError as msg: if str(msg).find("Could not find directory in config for gatk") >= 0: return None else: raise def gatk_cmd(name, jvm_opts, params, config=None): """Retrieve PATH to gatk using locally installed java. """ if name == "gatk": if isinstance(config, dict) and "config" not in config: data = {"config": config} else: data = config if not data or "gatk4" not in dd.get_tools_off(data): return _gatk4_cmd(jvm_opts, params, data) else: name = "gatk3" gatk_cmd = utils.which(os.path.join(os.path.dirname(os.path.realpath(sys.executable)), name)) # if we can't find via the local executable, fallback to being in the path if not gatk_cmd: gatk_cmd = utils.which(name) if gatk_cmd: return "%s && export PATH=%s:\"$PATH\" && %s %s %s" % \ (utils.clear_java_home(), utils.get_java_binpath(gatk_cmd), gatk_cmd, " ".join(jvm_opts), " ".join([str(x) for x in params])) def _gatk4_cmd(jvm_opts, params, data): """Retrieve unified command for GATK4, using 'gatk'. GATK3 is 'gatk3'. """ gatk_cmd = utils.which(os.path.join(os.path.dirname(os.path.realpath(sys.executable)), "gatk")) return "%s && export PATH=%s:\"$PATH\" && gatk --java-options '%s' %s" % \ (utils.clear_java_home(), utils.get_java_binpath(gatk_cmd), " ".join(jvm_opts), " ".join([str(x) for x in params])) class PicardCmdRunner: def __init__(self, cmd, config): self._cmd = cmd self._config = config def run(self, subcmd, opts, memscale=None): jvm_opts = get_picard_opts(self._config, memscale=memscale) cmd = ["export", "PATH=%s:\"$PATH\"" % utils.get_java_binpath(), "&&"] + \ [self._cmd] + jvm_opts + [subcmd] + ["%s %s" % (x, y) for x, y in opts] + \ ["--VALIDATION_STRINGENCY SILENT"] do.run(utils.clear_java_home() + " && " + " ".join(cmd), "Picard: %s" % subcmd) def run_fn(self, name, *args, **kwds): """Run pre-built functionality that used Broad tools by name. See the picardrun module for available functions. """ fn = None to_check = [picardrun] for ns in to_check: try: fn = getattr(ns, name) break except AttributeError: pass assert fn is not None, "Could not find function %s in %s" % (name, to_check) return fn(self, *args, **kwds) def runner_from_path(cmd, config): """Simple command line runner that expects a bash cmd in the PATH. This makes Picard tools back compatible with new approach of a single jar + bash script. """ if cmd.endswith("picard"): return PicardCmdRunner(cmd, config) else: raise ValueError("Do not support PATH running for %s" % cmd) bcbio-nextgen-1.2.9/bcbio/broad/metrics.py000066400000000000000000000525461415626112400204520ustar00rootroot00000000000000"""Handle running, parsing and manipulating metrics available through Picard. """ import contextlib import glob import json import os import subprocess from bcbio.utils import tmpfile, file_exists from bcbio.distributed.transaction import file_transaction from bcbio.broad.picardrun import picard_rnaseq_metrics import pysam class PicardMetricsParser(object): """Read metrics files produced by Picard analyses. Metrics info: http://picard.sourceforge.net/picard-metric-definitions.shtml """ def __init__(self): pass def get_summary_metrics(self, align_metrics, dup_metrics, insert_metrics=None, hybrid_metrics=None, vrn_vals=None, rnaseq_metrics=None): """Retrieve a high level summary of interesting metrics. """ with open(align_metrics) as in_handle: align_vals = self._parse_align_metrics(in_handle) if dup_metrics: with open(dup_metrics) as in_handle: dup_vals = self._parse_dup_metrics(in_handle) else: dup_vals = {} (insert_vals, hybrid_vals, rnaseq_vals) = (None, None, None) if insert_metrics and file_exists(insert_metrics): with open(insert_metrics) as in_handle: insert_vals = self._parse_insert_metrics(in_handle) if hybrid_metrics and file_exists(hybrid_metrics): with open(hybrid_metrics) as in_handle: hybrid_vals = self._parse_hybrid_metrics(in_handle) if rnaseq_metrics and file_exists(rnaseq_metrics): with open(rnaseq_metrics) as in_handle: rnaseq_vals = self._parse_rnaseq_metrics(in_handle) return self._tabularize_metrics(align_vals, dup_vals, insert_vals, hybrid_vals, vrn_vals, rnaseq_vals) def extract_metrics(self, metrics_files): """Return summary information for a lane of metrics files. """ extension_maps = dict( align_metrics=(self._parse_align_metrics, "AL"), dup_metrics=(self._parse_dup_metrics, "DUP"), hs_metrics=(self._parse_hybrid_metrics, "HS"), insert_metrics=(self._parse_insert_metrics, "INS"), rnaseq_metrics=(self._parse_rnaseq_metrics, "RNA")) all_metrics = dict() for fname in metrics_files: ext = os.path.splitext(fname)[-1][1:] try: parse_fn, prefix = extension_maps[ext] except KeyError: parse_fn = None if parse_fn: with open(fname) as in_handle: for key, val in parse_fn(in_handle).items(): if not key.startswith(prefix): key = "%s_%s" % (prefix, key) all_metrics[key] = val return all_metrics def _tabularize_metrics(self, align_vals, dup_vals, insert_vals, hybrid_vals, vrn_vals, rnaseq_vals): out = [] # handle high level alignment for paired values paired = insert_vals is not None total = align_vals["TOTAL_READS"] align_total = int(align_vals["PF_READS_ALIGNED"]) out.append(("Total", _add_commas(str(total)), ("paired" if paired else ""))) out.append(self._count_percent("Aligned", align_vals["PF_READS_ALIGNED"], total)) if paired: out.append(self._count_percent("Pairs aligned", align_vals["READS_ALIGNED_IN_PAIRS"], total)) align_total = int(align_vals["READS_ALIGNED_IN_PAIRS"]) dup_total = dup_vals.get("READ_PAIR_DUPLICATES") if dup_total is not None: out.append(self._count_percent("Pair duplicates", dup_vals["READ_PAIR_DUPLICATES"], align_total)) std = insert_vals.get("STANDARD_DEVIATION", "?") std_dev = "+/- %.1f" % float(std.replace(",", ".")) if (std and std != "?") else "" out.append(("Insert size", "%.1f" % float(insert_vals["MEAN_INSERT_SIZE"].replace(",", ".")), std_dev)) if hybrid_vals: out.append((None, None, None)) out.extend(self._tabularize_hybrid(hybrid_vals)) if vrn_vals: out.append((None, None, None)) out.extend(self._tabularize_variant(vrn_vals)) if rnaseq_vals: out.append((None, None, None)) out.extend(self._tabularize_rnaseq(rnaseq_vals)) return out def _tabularize_variant(self, vrn_vals): out = [] out.append(("Total variations", vrn_vals["total"], "")) out.append(("In dbSNP", "%.1f\%%" % vrn_vals["dbsnp_pct"], "")) out.append(("Transition/Transversion (all)", "%.2f" % vrn_vals["titv_all"], "")) out.append(("Transition/Transversion (dbSNP)", "%.2f" % vrn_vals["titv_dbsnp"], "")) out.append(("Transition/Transversion (novel)", "%.2f" % vrn_vals["titv_novel"], "")) return out def _tabularize_rnaseq(self, rnaseq_vals): out = [] out.append(("5' to 3' bias", rnaseq_vals["MEDIAN_5PRIME_TO_3PRIME_BIAS"], "")) out.append(("Percent of bases in coding regions", rnaseq_vals["PCT_CODING_BASES"], "")) out.append(("Percent of bases in intergenic regions", rnaseq_vals["PCT_INTERGENIC_BASES"], "")) out.append(("Percent of bases in introns", rnaseq_vals["PCT_INTRONIC_BASES"], "")) out.append(("Percent of bases in mRNA", rnaseq_vals["PCT_MRNA_BASES"], "")) out.append(("Percent of bases in rRNA", rnaseq_vals["PCT_RIBOSOMAL_BASES"], "")) out.append(("Percent of bases in UTRs", rnaseq_vals["PCT_UTR_BASES"], "")) return out def _tabularize_hybrid(self, hybrid_vals): out = [] def try_float_format(in_string, float_format, multiplier=1.): in_string = in_string.replace(",", ".") try: out_string = float_format % (float(in_string) * multiplier) except ValueError: out_string = in_string return out_string total = hybrid_vals["PF_UQ_BASES_ALIGNED"] out.append(self._count_percent("On bait bases", hybrid_vals["ON_BAIT_BASES"], total)) out.append(self._count_percent("Near bait bases", hybrid_vals["NEAR_BAIT_BASES"], total)) out.append(self._count_percent("Off bait bases", hybrid_vals["OFF_BAIT_BASES"], total)) out.append(("Mean bait coverage", "%s" % try_float_format(hybrid_vals["MEAN_BAIT_COVERAGE"], "%.1f"), "")) out.append(self._count_percent("On target bases", hybrid_vals["ON_TARGET_BASES"], total)) out.append(("Mean target coverage", "%sx" % try_float_format(hybrid_vals["MEAN_TARGET_COVERAGE"], "%d"), "")) out.append(("10x coverage targets", "%s\%%" % try_float_format(hybrid_vals["PCT_TARGET_BASES_10X"], "%.1f", 100.0), "")) out.append(("Zero coverage targets", "%s\%%" % try_float_format(hybrid_vals["ZERO_CVG_TARGETS_PCT"], "%.1f", 100.0), "")) out.append(("Fold enrichment", "%sx" % try_float_format(hybrid_vals["FOLD_ENRICHMENT"], "%d"), "")) return out def _count_percent(self, text, count, total): if float(total) > 0: percent = "(%.1f\%%)" % (float(count) / float(total) * 100.0) else: percent = "" return (text, _add_commas(str(count)), percent) def _parse_hybrid_metrics(self, in_handle): want_stats = ["PF_UQ_BASES_ALIGNED", "ON_BAIT_BASES", "NEAR_BAIT_BASES", "OFF_BAIT_BASES", "ON_TARGET_BASES", "MEAN_BAIT_COVERAGE", "MEAN_TARGET_COVERAGE", "FOLD_ENRICHMENT", "ZERO_CVG_TARGETS_PCT", "BAIT_SET", "GENOME_SIZE", "HS_LIBRARY_SIZE", "BAIT_TERRITORY", "TARGET_TERRITORY", "PCT_SELECTED_BASES", "FOLD_80_BASE_PENALTY", "PCT_TARGET_BASES_2X", "PCT_TARGET_BASES_10X", "PCT_TARGET_BASES_20X", "HS_PENALTY_20X" ] header = self._read_off_header(in_handle) info = in_handle.readline().rstrip("\n").split("\t") vals = self._read_vals_of_interest(want_stats, header, info) return vals def _parse_align_metrics(self, in_handle): half_stats = ["TOTAL_READS", "PF_READS_ALIGNED", "READS_ALIGNED_IN_PAIRS"] std_stats = ["PF_HQ_ALIGNED_Q20_BASES", "PCT_READS_ALIGNED_IN_PAIRS", "MEAN_READ_LENGTH"] want_stats = half_stats + std_stats header = self._read_off_header(in_handle) while 1: info = in_handle.readline().rstrip("\n").split("\t") if len(info) <= 1: break vals = self._read_vals_of_interest(want_stats, header, info) if info[0].lower() == "pair": new_vals = dict() for item, val in vals.items(): if item in half_stats: new_vals[item] = str(int(val) // 2) else: new_vals[item] = val vals = new_vals return vals def _parse_dup_metrics(self, in_handle): if in_handle.readline().find("picard.metrics") > 0: want_stats = ["READ_PAIRS_EXAMINED", "READ_PAIR_DUPLICATES", "PERCENT_DUPLICATION", "ESTIMATED_LIBRARY_SIZE"] header = self._read_off_header(in_handle) info = in_handle.readline().rstrip("\n").split("\t") vals = self._read_vals_of_interest(want_stats, header, info) return vals else: vals = {} for line in in_handle: metric, val = line.rstrip().split("\t") vals[metric] = val return vals def _parse_insert_metrics(self, in_handle): want_stats = ["MEDIAN_INSERT_SIZE", "MIN_INSERT_SIZE", "MAX_INSERT_SIZE", "MEAN_INSERT_SIZE", "STANDARD_DEVIATION"] header = self._read_off_header(in_handle) info = in_handle.readline().rstrip("\n").split("\t") vals = self._read_vals_of_interest(want_stats, header, info) return vals def _parse_rnaseq_metrics(self, in_handle): want_stats = ["PCT_RIBOSOMAL_BASES", "PCT_CODING_BASES", "PCT_UTR_BASES", "PCT_INTRONIC_BASES", "PCT_INTERGENIC_BASES", "PCT_MRNA_BASES", "PCT_USABLE_BASES", "MEDIAN_5PRIME_BIAS", "MEDIAN_3PRIME_BIAS", "MEDIAN_5PRIME_TO_3PRIME_BIAS"] header = self._read_off_header(in_handle) info = in_handle.readline().rstrip("\n").split("\t") vals = self._read_vals_of_interest(want_stats, header, info) return vals def _read_vals_of_interest(self, want, header, info): want_indexes = [header.index(w) for w in want] vals = dict() for i in want_indexes: vals[header[i]] = info[i] return vals def _read_off_header(self, in_handle): while 1: line = in_handle.readline() if line.startswith("## METRICS"): break return in_handle.readline().rstrip("\n").split("\t") class PicardMetrics(object): """Run reports using Picard, returning parsed metrics and files. """ def __init__(self, picard, tmp_dir): self._picard = picard self._tmp_dir = tmp_dir self._parser = PicardMetricsParser() def report(self, align_bam, ref_file, is_paired, bait_file, target_file, variant_region_file, config): """Produce report metrics using Picard with sorted aligned BAM file. """ dup_metrics = self._get_current_dup_metrics(align_bam) align_metrics = self._collect_align_metrics(align_bam, ref_file) # Prefer the GC metrics in FastQC instead of Picard # gc_graph, gc_metrics = self._gc_bias(align_bam, ref_file) gc_graph = None insert_graph, insert_metrics, hybrid_metrics = (None, None, None) if is_paired: insert_graph, insert_metrics = self._insert_sizes(align_bam) if bait_file and target_file: assert os.path.exists(bait_file), (bait_file, "does not exist!") assert os.path.exists(target_file), (target_file, "does not exist!") hybrid_metrics = self._hybrid_select_metrics(align_bam, bait_file, target_file) elif (variant_region_file and config["algorithm"].get("coverage_interval", "").lower() in ["exome"]): assert os.path.exists(variant_region_file), (variant_region_file, "does not exist") hybrid_metrics = self._hybrid_select_metrics( align_bam, variant_region_file, variant_region_file) vrn_vals = self._variant_eval_metrics(align_bam) summary_info = self._parser.get_summary_metrics(align_metrics, dup_metrics, insert_metrics, hybrid_metrics, vrn_vals) graphs = [] if gc_graph and os.path.exists(gc_graph): graphs.append((gc_graph, "Distribution of GC content across reads")) if insert_graph and os.path.exists(insert_graph): graphs.append((insert_graph, "Distribution of paired end insert sizes")) return summary_info, graphs def _get_current_dup_metrics(self, align_bam): """Retrieve duplicate information from input BAM file. """ metrics_file = "%s.dup_metrics" % os.path.splitext(align_bam)[0] if not file_exists(metrics_file): dups = 0 with pysam.Samfile(align_bam, "rb") as bam_handle: for read in bam_handle: if (read.is_paired and read.is_read1) or not read.is_paired: if read.is_duplicate: dups += 1 with open(metrics_file, "w") as out_handle: out_handle.write("# custom bcbio-nextgen metrics\n") out_handle.write("READ_PAIR_DUPLICATES\t%s\n" % dups) return metrics_file def _check_metrics_file(self, bam_name, metrics_ext): """Check for an existing metrics file for the given BAM. """ base, _ = os.path.splitext(bam_name) try: int(base[-1]) can_glob = False except ValueError: can_glob = True check_fname = "{base}{maybe_glob}.{ext}".format( base=base, maybe_glob="*" if can_glob else "", ext=metrics_ext) glob_fnames = glob.glob(check_fname) if len(glob_fnames) > 0: return glob_fnames[0] else: return "{base}.{ext}".format(base=base, ext=metrics_ext) def _hybrid_select_metrics(self, dup_bam, bait_file, target_file): """Generate metrics for hybrid selection efficiency. """ metrics = self._check_metrics_file(dup_bam, "hs_metrics") if not file_exists(metrics): with bed_to_interval(bait_file, dup_bam) as ready_bait: with bed_to_interval(target_file, dup_bam) as ready_target: with file_transaction(metrics) as tx_metrics: opts = [("--BAIT_INTERVALS", ready_bait), ("--TARGET_INTERVALS", ready_target), ("--INPUT", dup_bam), ("--OUTPUT", tx_metrics)] try: self._picard.run("CollectHsMetrics", opts) # HsMetrics fails regularly with memory errors # so we catch and skip instead of aborting the # full process except subprocess.CalledProcessError: return None return metrics def _variant_eval_metrics(self, dup_bam): """Find metrics for evaluating variant effectiveness. """ base, ext = os.path.splitext(dup_bam) end_strip = "-dup" base = base[:-len(end_strip)] if base.endswith(end_strip) else base mfiles = glob.glob("%s*eval_metrics" % base) if len(mfiles) > 0: with open(mfiles[0]) as in_handle: # pull the metrics as JSON from the last line in the file for line in in_handle: pass metrics = json.loads(line) return metrics else: return None def _gc_bias(self, dup_bam, ref_file): gc_metrics = self._check_metrics_file(dup_bam, "gc_metrics") gc_graph = "%s-gc.pdf" % os.path.splitext(gc_metrics)[0] if not file_exists(gc_metrics): with file_transaction(gc_graph, gc_metrics) as \ (tx_graph, tx_metrics): opts = [("--INPUT", dup_bam), ("--OUTPUT", tx_metrics), ("--CHART_OUTPUT", tx_graph), ("--REFERENCE_SEQUENCE", ref_file)] self._picard.run("CollectGcBiasMetrics", opts) return gc_graph, gc_metrics def _insert_sizes(self, dup_bam): insert_metrics = self._check_metrics_file(dup_bam, "insert_metrics") insert_graph = "%s-insert.pdf" % os.path.splitext(insert_metrics)[0] if not file_exists(insert_metrics): with file_transaction(insert_graph, insert_metrics) as \ (tx_graph, tx_metrics): opts = [("--INPUT", dup_bam), ("--OUTPUT", tx_metrics), ("--Histogram_FILE", tx_graph)] self._picard.run("CollectInsertSizeMetrics", opts) return insert_graph, insert_metrics def _collect_align_metrics(self, dup_bam, ref_file): align_metrics = self._check_metrics_file(dup_bam, "align_metrics") if not file_exists(align_metrics): with file_transaction(align_metrics) as tx_metrics: opts = [("--INPUT", dup_bam), ("--OUTPUT", tx_metrics), ("--REFERENCE_SEQUENCE", ref_file)] self._picard.run("CollectAlignmentSummaryMetrics", opts) return align_metrics def _add_commas(s, sep=','): """Add commas to output counts. From: http://code.activestate.com/recipes/498181 """ if len(s) <= 3: return s return _add_commas(s[:-3], sep) + sep + s[-3:] @contextlib.contextmanager def bed_to_interval(orig_bed, bam_file): """Add header and format BED bait and target files for Picard if necessary. """ with open(orig_bed) as in_handle: line = in_handle.readline() if line.startswith("@"): yield orig_bed else: with pysam.Samfile(bam_file, "rb") as bam_handle: header = bam_handle.text with tmpfile(dir=os.path.dirname(orig_bed), prefix="picardbed") as tmp_bed: with open(tmp_bed, "w") as out_handle: out_handle.write(header) with open(orig_bed) as in_handle: for i, line in enumerate(in_handle): parts = line.rstrip().split("\t") if len(parts) == 4: chrom, start, end, name = parts strand = "+" elif len(parts) >= 3: chrom, start, end = parts[:3] strand = "+" name = "r%s" % i out = [chrom, start, end, strand, name] out_handle.write("\t".join(out) + "\n") yield tmp_bed class RNASeqPicardMetrics(PicardMetrics): def report(self, align_bam, ref_file, gtf_file, is_paired=False, rrna_file="null"): """Produce report metrics for a RNASeq experiment using Picard with a sorted aligned BAM file. """ # collect duplication metrics dup_metrics = self._get_current_dup_metrics(align_bam) align_metrics = self._collect_align_metrics(align_bam, ref_file) insert_graph, insert_metrics = (None, None) if is_paired: insert_graph, insert_metrics = self._insert_sizes(align_bam) rnaseq_metrics = self._rnaseq_metrics(align_bam, gtf_file, rrna_file) summary_info = self._parser.get_summary_metrics(align_metrics, dup_metrics, insert_metrics=insert_metrics, rnaseq_metrics=rnaseq_metrics) graphs = [] if insert_graph and file_exists(insert_graph): graphs.append((insert_graph, "Distribution of paired end insert sizes")) return summary_info, graphs def _rnaseq_metrics(self, align_bam, gtf_file, rrna_file): metrics = self._check_metrics_file(align_bam, "rnaseq_metrics") if not file_exists(metrics): with file_transaction(metrics) as tx_metrics: picard_rnaseq_metrics(self._picard, align_bam, gtf_file, rrna_file, tx_metrics) return metrics bcbio-nextgen-1.2.9/bcbio/broad/picardrun.py000066400000000000000000000327141415626112400207660ustar00rootroot00000000000000"""Convenience functions for running common Picard utilities. """ import os import collections from bcbio.utils import file_exists from bcbio.distributed.transaction import file_transaction, tx_tmpdir def picard_rnaseq_metrics(picard, align_bam, ref, ribo="null", out_file=None): """ Collect RNASeq metrics for a bam file """ base, ext = os.path.splitext(align_bam) if out_file is None: out_file = "%s.metrics" % (base) if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: opts = [("--INPUT", align_bam), ("--OUTPUT", tx_out_file), ("--TMP_DIR", tmp_dir), ("--REF_FLAT", ref), ("--STRAND_SPECIFICITY", "NONE"), ("--ASSUME_SORTED", "True"), ("--RIBOSOMAL_INTERVALS", ribo)] picard.run("CollectRnaSeqMetrics", opts) return out_file def picard_insert_metrics(picard, align_bam, out_file=None): """ Collect insert size metrics for a bam file """ base, ext = os.path.splitext(align_bam) if out_file is None: out_file = "%s-insert-metrics.txt" % (base) histogram = "%s-insert-histogram.pdf" % (base) if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: opts = [("--INPUT", align_bam), ("--OUTPUT", tx_out_file), ("--Histogram_FILE", histogram), ("--TMP_DIR", tmp_dir)] picard.run("CollectInsertSizeMetrics", opts) return out_file def picard_sort(picard, align_bam, sort_order="coordinate", out_file=None, compression_level=None, pipe=False): """Sort a BAM file by coordinates. """ base, ext = os.path.splitext(align_bam) if out_file is None: out_file = "%s-sort%s" % (base, ext) if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: opts = [("--INPUT", align_bam), ("--OUTPUT", out_file if pipe else tx_out_file), ("--TMP_DIR", tmp_dir), ("--SORT_ORDER", sort_order)] if compression_level: opts.append(("--COMPRESSION_LEVEL", compression_level)) picard.run("SortSam", opts, pipe=pipe) return out_file def picard_merge(picard, in_files, out_file=None, merge_seq_dicts=False): """Merge multiple BAM files together with Picard. """ if out_file is None: out_file = "%smerge.bam" % os.path.commonprefix(in_files) if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: opts = [("--OUTPUT", tx_out_file), ("--SORT_ORDER", "coordinate"), ("--MERGE_SEQUENCE_DICTIONARIES", "true" if merge_seq_dicts else "false"), ("--USE_THREADING", "true"), ("--TMP_DIR", tmp_dir)] for in_file in in_files: opts.append(("--INPUT", in_file)) picard.run("MergeSamFiles", opts) return out_file def picard_index(picard, in_bam): index_file = "%s.bai" % in_bam alt_index_file = "%s.bai" % os.path.splitext(in_bam)[0] if not file_exists(index_file) and not file_exists(alt_index_file): with file_transaction(picard._config, index_file) as tx_index_file: opts = [("INPUT", in_bam), ("OUTPUT", tx_index_file)] picard.run("BuildBamIndex", opts) return index_file if file_exists(index_file) else alt_index_file def picard_reorder(picard, in_bam, ref_file, out_file): """Reorder BAM file to match reference file ordering. """ if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: dict_file = "%s.dict" % os.path.splitext(ref_file)[0] opts = [("--INPUT", in_bam), ("--OUTPUT", tx_out_file), ("--SEQUENCE_DICTIONARY", dict_file), ("--ALLOW_INCOMPLETE_DICT_CONCORDANCE", "true"), ("--TMP_DIR", tmp_dir)] picard.run("ReorderSam", opts) return out_file def picard_fix_rgs(picard, in_bam, names): """Add read group information to BAM files and coordinate sort. """ out_file = "%s-fixrgs.bam" % os.path.splitext(in_bam)[0] if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: opts = [("--INPUT", in_bam), ("--OUTPUT", tx_out_file), ("--SORT_ORDER", "coordinate"), ("--RGID", names["rg"]), ("--RGLB", names.get("lb", "unknown")), ("--RGPL", names["pl"]), ("--RGPU", names["pu"]), ("--RGSM", names["sample"]), ("--TMP_DIR", tmp_dir)] picard.run("AddOrReplaceReadGroups", opts) return out_file def picard_downsample(picard, in_bam, ds_pct, random_seed=None): out_file = "%s-downsample%s" % os.path.splitext(in_bam) if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: opts = [("--INPUT", in_bam), ("--OUTPUT", tx_out_file), ("--PROBABILITY", "%.3f" % ds_pct), ("--TMP_DIR", tmp_dir)] if random_seed: opts += [("--RANDOM_SEED", str(random_seed))] picard.run("DownsampleSam", opts) return out_file def picard_index_ref(picard, ref_file): """Provide a Picard style dict index file for a reference genome. """ dict_file = "%s.dict" % os.path.splitext(ref_file)[0] if not file_exists(dict_file): with file_transaction(picard._config, dict_file) as tx_dict_file: opts = [("--REFERENCE", ref_file), ("--OUTPUT", tx_dict_file)] picard.run("CreateSequenceDictionary", opts) return dict_file def picard_fastq_to_bam(picard, fastq_one, fastq_two, out_dir, names, order="queryname"): """Convert fastq file(s) to BAM, adding sample, run group and platform information. """ out_bam = os.path.join(out_dir, "%s-fastq.bam" % os.path.splitext(os.path.basename(fastq_one))[0]) if not file_exists(out_bam): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_bam) as tx_out_bam: opts = [("--FASTQ", fastq_one), ("--READ_GROUP_NAME", names["rg"]), ("--SAMPLE_NAME", names["sample"]), ("--PLATFORM_UNIT", names["pu"]), ("--PLATFORM", names["pl"]), ("--TMP_DIR", tmp_dir), ("--OUTPUT", tx_out_bam), ("--SORT_ORDER", order)] if fastq_two: opts.append(("--FASTQ2", fastq_two)) picard.run("FastqToSam", opts) return out_bam def picard_bam_to_fastq(picard, in_bam, fastq_one, fastq_two=None): """Convert BAM file to fastq. """ if not file_exists(fastq_one): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, fastq_one) as tx_out1: opts = [("--INPUT", in_bam), ("--FASTQ", tx_out1), ("--TMP_DIR", tmp_dir)] if fastq_two is not None: opts += [("--SECOND_END_FASTQ", fastq_two)] picard.run("SamToFastq", opts) return (fastq_one, fastq_two) def picard_sam_to_bam(picard, align_sam, fastq_bam, ref_file, is_paired=False): """Convert SAM to BAM, including unmapped reads from fastq BAM file. """ to_retain = ["XS", "XG", "XM", "XN", "XO", "YT"] if align_sam.endswith(".sam"): out_bam = "%s.bam" % os.path.splitext(align_sam)[0] elif align_sam.endswith("-align.bam"): out_bam = "%s.bam" % align_sam.replace("-align.bam", "") else: raise NotImplementedError("Input format not recognized") if not file_exists(out_bam): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_bam) as tx_out_bam: opts = [("--UNMAPPED", fastq_bam), ("--ALIGNED", align_sam), ("--OUTPUT", tx_out_bam), ("--REFERENCE_SEQUENCE", ref_file), ("--TMP_DIR", tmp_dir), ("--PAIRED_RUN", ("true" if is_paired else "false")), ] opts += [("--ATTRIBUTES_TO_RETAIN", x) for x in to_retain] picard.run("MergeBamAlignment", opts) return out_bam def picard_formatconverter(picard, align_sam): """Convert aligned SAM file to BAM format. """ out_bam = "%s.bam" % os.path.splitext(align_sam)[0] if not file_exists(out_bam): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_bam) as tx_out_bam: opts = [("--INPUT", align_sam), ("--OUTPUT", tx_out_bam), ("--TMP_DIR", tmp_dir)] picard.run("SamFormatConverter", opts) return out_bam def picard_mark_duplicates(picard, align_bam, remove_dups=False): base, ext = os.path.splitext(align_bam) base = base.replace(".", "-") dup_bam = "%s-dup%s" % (base, ext) dup_metrics = "%s-dup.dup_metrics" % base if not file_exists(dup_bam): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, dup_bam, dup_metrics) as (tx_dup_bam, tx_dup_metrics): opts = [("--INPUT", align_bam), ("--OUTPUT", tx_dup_bam), ("--TMP_DIR", tmp_dir), ("--REMOVE_DUPLICATES", "true" if remove_dups else "false"), ("--METRICS_FILE", tx_dup_metrics)] if picard.get_picard_version("MarkDuplicates") >= 1.82: opts += [("--PROGRAM_RECORD_ID", "null")] picard.run("MarkDuplicates", opts, memscale={"direction": "decrease", "magnitude": 2}) return dup_bam, dup_metrics def picard_fixmate(picard, align_bam): """Run Picard's FixMateInformation generating an aligned output file. """ base, ext = os.path.splitext(align_bam) out_file = "%s-sort%s" % (base, ext) if not file_exists(out_file): with tx_tmpdir(picard._config) as tmp_dir: with file_transaction(picard._config, out_file) as tx_out_file: opts = [("--INPUT", align_bam), ("--OUTPUT", tx_out_file), ("--TMP_DIR", tmp_dir), ("--SORT_ORDER", "coordinate")] picard.run("FixMateInformation", opts) return out_file def picard_idxstats(picard, align_bam): """Retrieve alignment stats from picard using BamIndexStats. """ opts = [("INPUT", align_bam)] stdout = picard.run("BamIndexStats", opts, get_stdout=True) out = [] AlignInfo = collections.namedtuple("AlignInfo", ["contig", "length", "aligned", "unaligned"]) for line in stdout.split("\n"): if line: parts = line.split() if len(parts) == 2: _, unaligned = parts out.append(AlignInfo("nocontig", 0, 0, int(unaligned))) elif len(parts) == 7: contig, _, length, _, aligned, _, unaligned = parts out.append(AlignInfo(contig, int(length), int(aligned), int(unaligned))) else: raise ValueError("Unexpected output from BamIndexStats: %s" % line) return out def bed2interval(align_file, bed, out_file=None): """Converts a bed file to an interval file for use with some of the Picard tools by grabbing the header from the alignment file, reording the bed file columns and gluing them together. align_file can be in BAM or SAM format. bed needs to be in bed12 format: http://genome.ucsc.edu/FAQ/FAQformat.html#format1.5 """ import pysam base, ext = os.path.splitext(align_file) if out_file is None: out_file = base + ".interval" with pysam.Samfile(align_file, "r" if ext.endswith(".sam") else "rb") as in_bam: header = in_bam.text def reorder_line(line): splitline = line.strip().split("\t") reordered = "\t".join([splitline[0], str(int(splitline[1]) + 1), splitline[2], splitline[5], splitline[3]]) return reordered + "\n" with file_transaction(out_file) as tx_out_file: with open(bed) as bed_handle: with open(tx_out_file, "w") as out_handle: out_handle.write(header) for line in bed_handle: out_handle.write(reorder_line(line)) return out_file bcbio-nextgen-1.2.9/bcbio/chipseq/000077500000000000000000000000001415626112400167635ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/chipseq/__init__.py000066400000000000000000000221561415626112400211020ustar00rootroot00000000000000import os import shutil import subprocess import sys import toolz as tz from bcbio import utils from bcbio import bam from bcbio.pipeline import config_utils import bcbio.pipeline.datadict as dd from bcbio.ngsalign import bowtie2, bwa from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.log import logger from bcbio.heterogeneity.chromhacks import (get_mitochondrial_chroms, get_nonmitochondrial_chroms) from bcbio.chipseq import atac def clean_chipseq_alignment(data): # lcr_bed = utils.get_in(data, ("genome_resources", "variation", "lcr")) method = dd.get_chip_method(data) if method == "atac": data = shift_ATAC(data) work_bam = dd.get_work_bam(data) work_bam = bam.sort(work_bam, dd.get_config(data)) bam.index(work_bam, dd.get_config(data)) # an unfiltered BAM file is useful for calculating some metrics later data = tz.assoc_in(data, ['chipseq', 'align', "unfiltered"], work_bam) clean_bam = remove_nonassembled_chrom(work_bam, data) clean_bam = remove_mitochondrial_reads(clean_bam, data) data = atac.calculate_complexity_metrics(clean_bam, data) if not dd.get_keep_multimapped(data): clean_bam = remove_multimappers(clean_bam, data) if not dd.get_keep_duplicates(data): clean_bam = bam.remove_duplicates(clean_bam, data) data["work_bam"] = clean_bam # for ATAC-seq, brewak alignments into NF, mono/di/tri nucleosome BAM files if method == "atac": data = atac.split_ATAC(data) encode_bed = tz.get_in(["genome_resources", "variation", "encode_blacklist"], data) if encode_bed: data["work_bam"] = remove_blacklist_regions(dd.get_work_bam(data), encode_bed, data['config']) bam.index(data["work_bam"], data['config']) try: data["bigwig"] = _normalized_bam_coverage(dd.get_sample_name(data), dd.get_work_bam(data), data) except subprocess.CalledProcessError: logger.warning(f"{dd.get_work_bam(data)} was too sparse to normalize, " f" falling back to non-normalized coverage.") data["bigwig"] = _bam_coverage(dd.get_sample_name(data), dd.get_work_bam(data), data) return [[data]] def remove_mitochondrial_reads(bam_file, data): mito = get_mitochondrial_chroms(data) if not mito: logger.info(f"Mitochondrial chromosome not identified, skipping removal of " "mitochondrial reads from {bam_file}.") return bam_file nonmito = get_nonmitochondrial_chroms(data) mito_bam = os.path.splitext(bam_file)[0] + "-noMito.bam" if utils.file_exists(mito_bam): return mito_bam samtools = config_utils.get_program("samtools", dd.get_config(data)) nonmito_flag = " ".join(nonmito) num_cores = dd.get_num_cores(data) with file_transaction(mito_bam) as tx_out_bam: cmd = (f"{samtools} view -bh -@ {num_cores} {bam_file} {nonmito_flag} " f"> {tx_out_bam}") message = f"Removing mitochondrial reads on {','.join(mito)} from {bam_file}." do.run(cmd, message) return mito_bam def remove_multimappers(bam_file, data): aligner = dd.get_aligner(data) if aligner: if aligner == "bowtie2": filterer = bowtie2.filter_multimappers elif aligner == "bwa": filterer = bwa.filter_multimappers else: logger.error("ChIP-seq only supported for bowtie2 and bwa.") sys.exit(-1) unique_bam = filterer(bam_file, data) else: unique_bam = bam_file logger.warn("When a BAM file is given as input, bcbio skips removal of " "multimappers.") return unique_bam def remove_nonassembled_chrom(bam_file, data): """Remove non-assembled contigs from the BAM file""" ref_file = dd.get_ref_file(data) config = dd.get_config(data) bam.index(bam_file, config) fai = "%s.fai" % ref_file chrom = [] with open(fai) as inh: for line in inh: c = line.split("\t")[0] if c.find("_") < 0: chrom.append(c) chroms = " ".join(chrom) out_file = utils.append_stem(bam_file, '_chrom') samtools = config_utils.get_program("samtools", config) if not utils.file_exists(out_file): with file_transaction(out_file) as tx_out: cmd = "{samtools} view -b {bam_file} {chroms} > {tx_out}" do.run(cmd.format(**locals()), "Remove contigs from %s" % bam_file) bam.index(out_file, config) return out_file def remove_blacklist_regions(bam_file, bed_file, config): """Remove blacklist regions from a BAM file""" if not bam_file or not bed_file: return bam_file out_file = utils.append_stem(bam_file, '_filter') bedtools = config_utils.get_program("bedtools", config) if not utils.file_exists(out_file): with file_transaction(out_file) as tx_out: cmd = "{bedtools} subtract -nonamecheck -A -a {bam_file} -b {bed_file} > {tx_out}" do.run(cmd.format(**locals()), "Remove blacklist regions from %s" % bam_file) return out_file def _bam_coverage(name, bam_input, data): """Run bamCoverage from deeptools""" cmd = ("{bam_coverage} --bam {bam_input} --outFileName {bw_output} " "--binSize 20 --effectiveGenomeSize {size} " "--smoothLength 60 --extendReads 150 --centerReads -p {cores} ") size = bam.fasta.total_sequence_length(dd.get_ref_file(data)) cores = dd.get_num_cores(data) try: bam_coverage = config_utils.get_program("bamCoverage", data) except config_utils.CmdNotFound: logger.info("No bamCoverage found, skipping bamCoverage.") return None resources = config_utils.get_resources("bamCoverage", data["config"]) if resources: options = resources.get("options") if options: cmd += " %s" % " ".join([str(x) for x in options]) bw_output = os.path.join(os.path.dirname(bam_input), "%s.bw" % name) if utils.file_exists(bw_output): return bw_output with file_transaction(bw_output) as out_tx: do.run(cmd.format(**locals()), "Run bamCoverage in %s" % name) return bw_output def _normalized_bam_coverage(name, bam_input, data): """Run bamCoverage from deeptools but produce normalized bigWig files""" cmd = ("{bam_coverage} --bam {bam_input} --outFileName {bw_output} " "--binSize 20 --effectiveGenomeSize {size} " "--smoothLength 60 --extendReads 150 --centerReads -p {cores} ") size = bam.fasta.total_sequence_length(dd.get_ref_file(data)) cores = dd.get_num_cores(data) try: bam_coverage = config_utils.get_program("bamCoverage", data) except config_utils.CmdNotFound: logger.info("No bamCoverage found, skipping bamCoverage.") return None method = dd.get_chip_method(data) cmd += "--normalizeUsing CPM " toignore = get_mitochondrial_chroms(data) if toignore: ignorenormflag = f"--ignoreForNormalization {' '.join(toignore)} " cmd += ignorenormflag resources = config_utils.get_resources("bamCoverage", data["config"]) if resources: options = resources.get("options") if options: cmd += " %s" % " ".join([str(x) for x in options]) bw_output = os.path.join(os.path.dirname(bam_input), "%s.bw" % name) if utils.file_exists(bw_output): return bw_output with file_transaction(bw_output) as out_tx: do.run(cmd.format(**locals()), "Run bamCoverage in %s" % name) return bw_output def shift_ATAC(data): """ shift the ATAC-seq alignments """ MAX_FRAG_LENGTH = 100 sieve = config_utils.get_program("alignmentSieve", data) work_bam = dd.get_work_bam(data) num_cores = dd.get_num_cores(data) out_file = os.path.splitext(work_bam)[0] + "-shifted.bam" log_file = os.path.splitext(work_bam)[0] + "-shifted.log" if utils.file_exists(out_file): data["work_bam"] = out_file return data unsorted_bam = os.path.splitext(out_file)[0] + ".unsorted.bam" # shifting removes all reads if the BAM file is not paired shiftflag = "--ATACshift" if bam.is_paired(work_bam) else "" if not utils.file_exists(out_file): with file_transaction(out_file) as tx_out_file, \ file_transaction(log_file) as tx_log_file: tx_unsorted_file = os.path.splitext(tx_out_file)[0] + ".tmp.bam" cmd = ( f"{sieve} --verbose --bam {work_bam} --outFile {tx_unsorted_file} " f"{shiftflag} " f"--numberOfProcessors {num_cores} --maxFragmentLength 0 " f"--minFragmentLength 0 " f"--minMappingQuality 10 " f"--filterMetrics {tx_log_file} ") do.run(cmd, f"Shifting ATAC-seq alignments in {work_bam} to {tx_unsorted_file}.") # shifting can cause the file to become unsorted sorted_file = bam.sort(tx_unsorted_file, dd.get_config(data), force=True) shutil.move(sorted_file, tx_out_file) bam.index(out_file, dd.get_config(data)) data["work_bam"] = out_file return data bcbio-nextgen-1.2.9/bcbio/chipseq/antibodies.py000066400000000000000000000025461415626112400214650ustar00rootroot00000000000000#from dataclasses import dataclass from collections import namedtuple VALID_PEAKTYPES = ["narrow", "broad"] # @dataclass # class Antibody: # """ # ChIP-seq antibody # """ # name: str # # call narrow or broad peaks # peaktype: str # # remove duplicates? # rmdup: bool = True # def __post_init__(self): # if self.peaktype not in VALID_PEAKTYPES: # raise TypeError(f"peaktype {self.peatktype} is not one of {VALID_PEAKTYPES}") Antibody = namedtuple('Antibody', 'name peaktype rmdup') _ANTIBODIES = [ Antibody("h3f3a", "broad", True), Antibody("h3k27me3", "broad", True), Antibody("h3k36me3", "broad", True), Antibody("h3k4me1", "broad", True), Antibody("h3k79me2", "broad", True), Antibody("h3k79me3", "broad", True), Antibody("h3k9me1", "broad", True), Antibody("h3k9me2", "broad", True), Antibody("h4k20me1", "broad", True), Antibody("h2afz", "narrow", True), Antibody("h3ac", "narrow", True), Antibody("h3k27ac", "narrow", True), Antibody("h3k4me2", "narrow", True), Antibody("h3k4me3", "narrow", True), Antibody("h3k9ac", "narrow", True), Antibody("h3k9me3", "broad", False), Antibody("broad", "broad", False), Antibody("narrow", "narrow", True) ] ANTIBODIES = {x.name: x for x in _ANTIBODIES} SUPPORTED_ANTIBODIES = {x.name for x in _ANTIBODIES} bcbio-nextgen-1.2.9/bcbio/chipseq/atac.py000066400000000000000000000272521415626112400202550ustar00rootroot00000000000000import os import toolz as tz from collections import namedtuple from bcbio import utils from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio import bam from bcbio.rnaseq import gtf from bcbio.heterogeneity import chromhacks # ranges taken from Buenrostro, Nat. Methods 10, 1213–1218 (2013). ATACRange = namedtuple('ATACRange', ['label', 'min', 'max']) ATACRanges = {"NF": ATACRange("NF", 0, 100), "MN": ATACRange("MN", 180, 247), "DN": ATACRange("DN", 315, 473), "TN": ATACRange("TN", 558, 615)} def calculate_complexity_metrics(work_bam, data): """ the work_bam should have duplicates marked but not removed mitochondrial reads should be removed """ bedtools = config_utils.get_program("bedtools", dd.get_config(data)) work_dir = dd.get_work_dir(data) metrics_dir = os.path.join(work_dir, "metrics", "atac") utils.safe_makedir(metrics_dir) metrics_file = os.path.join(metrics_dir, f"{dd.get_sample_name(data)}-atac-metrics.csv") if utils.file_exists(metrics_file): data = tz.assoc_in(data, ['atac', 'complexity_metrics_file'], metrics_file) return data # BAM file must be sorted by read name work_bam = bam.sort(work_bam, dd.get_config(data), order="queryname") with file_transaction(metrics_file) as tx_metrics_file: with open(tx_metrics_file, "w") as out_handle: out_handle.write("mt,m0,m1,m2\n") if bam.is_paired(work_bam): cmd = (f"{bedtools} bamtobed -bedpe -i {work_bam} | " "awk 'BEGIN{OFS=\"\\t\"}{print $1,$2,$4,$6,$9,$10}' | " "sort | " "uniq -c | " "awk 'BEGIN{mt=0;m0=0;m1=0;m2=0}($1==1){m1=m1+1} ($1==2){m2=m2+1}{m0=m0+1}{mt=mt+$1} END{printf \"%d,%d,%d,%d\\n\", mt,m0,m1,m2}' >> " f"{tx_metrics_file}") else: cmd = (f"{bedtools} bamtobed -i {work_bam} | " "awk 'BEGIN{OFS=\"\\t\"}{print $1,$2,$3,$6}' | " "sort | " "uniq -c | " "awk 'BEGIN{mt=0;m0=0;m1=0;m2=0} ($1==1){m1=m1+1} ($1==2){m2=m2+1}{m0=m0+1}{mt=mt+$1} END{printf \"%d,%d,%d,%d\\n\", mt,m0,m1,m2}' >> " f"{tx_metrics_file}") message = f"Calculating ATAC-seq complexity metrics on {work_bam}, saving as {metrics_file}." do.run(cmd, message) data = tz.assoc_in(data, ['atac', 'complexity_metrics_file'], metrics_file) return data def calculate_encode_complexity_metrics(data): metrics_file = tz.get_in(['atac', 'complexity_metrics_file'], data, None) if not metrics_file: return {} else: with open(metrics_file) as in_handle: header = next(in_handle).strip().split(",") values = next(in_handle).strip().split(",") raw_metrics = {h: int(v) for h, v in zip(header, values)} metrics = {"PBC1": raw_metrics["m1"] / raw_metrics["m0"], "NRF": raw_metrics["m0"] / raw_metrics["mt"]} if raw_metrics["m2"] == 0: PBC2 = 0 else: PBC2 = raw_metrics["m1"] / raw_metrics["m2"] metrics["PBC2"] = PBC2 if dd.get_chip_method(data) == "atac": metrics["bottlenecking"] = get_atac_bottlenecking_flag(metrics["PBC1"], metrics["PBC2"]) metrics["complexity"] = get_atac_complexity_flag(metrics["NRF"]) else: metrics["bottlenecking"] = get_chip_bottlenecking_flag(metrics["PBC1"], metrics["PBC2"]) metrics["complexity"] = get_chip_complexity_flag(metrics["NRF"]) return(metrics) def get_chip_bottlenecking_flag(PBC1, PBC2): """ flags from: https://www.encodeproject.org/data-standards/terms/ under Library Complexity """ if PBC1 < 0.5 or PBC2 < 1: return "severe" elif PBC1 <= 0.8 or PBC2 <= 3: return "moderate" elif PBC1 <= 0.9 or PBC2 <= 10: return "mild" else: return "none" def get_chip_complexity_flag(NRF): """ flags from: https://www.encodeproject.org/data-standards/terms/ under Library Complexity """ if NRF < 0.5: return "concerning" elif NRF < 0.8: return "acceptable" elif NRF < 0.9: return "compliant" else: return "ideal" def get_atac_bottlenecking_flag(PBC1, PBC2): """ flags from: https://www.encodeproject.org/data-standards/terms/ under Library Complexity """ if PBC1 < 0.7 or PBC2 < 1: return "severe" elif PBC1 <= 0.9 or PBC2 <= 3: return "moderate" else: return "none" def get_atac_complexity_flag(NRF): """ flags from: https://www.encodeproject.org/data-standards/terms/ under Library Complexity """ if NRF < 0.7: return "concerning" elif NRF < 0.9: return "acceptable" else: return "ideal" def split_ATAC(data, bam_file=None): """ splits a BAM into nucleosome-free (NF) and mono/di/tri nucleosome BAMs based on the estimated insert sizes uses the current working BAM file if no BAM file is supplied """ sambamba = config_utils.get_program("sambamba", data) num_cores = dd.get_num_cores(data) base_cmd = f'{sambamba} view --format bam --nthreads {num_cores} ' bam_file = bam_file if bam_file else dd.get_work_bam(data) out_stem = os.path.splitext(bam_file)[0] split_files = {} # we can only split these fractions from paired runs if not bam.is_paired(bam_file): split_files["full"] = bam_file data = tz.assoc_in(data, ['atac', 'align'], split_files) return data # reads on the negative strand have a negative template_length value for arange in ATACRanges.values(): out_file = f"{out_stem}-{arange.label}.bam" if not utils.file_exists(out_file): with file_transaction(out_file) as tx_out_file: cmd = base_cmd +\ f'-F "(template_length > {arange.min} and template_length < {arange.max}) or ' +\ f'(template_length) < {-arange.min} and template_length > {-arange.max})" ' +\ f'{bam_file} > {tx_out_file}' message = f'Splitting {arange.label} regions from {bam_file}.' do.run(cmd, message) bam.index(out_file, dd.get_config(data)) split_files[arange.label] = out_file split_files["full"] = bam_file data = tz.assoc_in(data, ['atac', 'align'], split_files) return data def run_ataqv(data): if not dd.get_chip_method(data) == "atac": return None work_dir = dd.get_work_dir(data) sample_name = dd.get_sample_name(data) out_dir = os.path.join(work_dir, "qc", sample_name, "ataqv") peak_file = get_full_peaks(data) bam_file = get_unfiltered_bam(data) out_file = os.path.join(out_dir, sample_name + ".ataqv.json.gz") if not peak_file: logger.info(f"Full peak file for {sample_name} not found, skipping ataqv") return None if not bam_file: logger.info(f"Unfiltered BAM file for {sample_name} not found, skipping ataqv") return None if utils.file_exists(out_file): return out_file tss_bed_file = os.path.join(out_dir, "TSS.bed") tss_bed_file = gtf.get_tss_bed(dd.get_gtf_file(data), tss_bed_file, data, padding=0) if chromhacks.is_human(data): organism = "human" autosomal_reference_flag = "" elif chromhacks.is_mouse(data): organism = "mouse" autosomal_reference_flag = "" else: autosomal_reference = os.path.join(out_dir, "autosomal.txt") autosomal_reference = _make_autosomal_reference_file(autosomal_reference, data) organism = "None" autosomal_reference_flag = f"--autosomal-reference-file {autosomal_reference} " ataqv = config_utils.get_program("ataqv", data) mitoname = chromhacks.get_mitochondrial_chroms(data)[0] if not ataqv: logger.info(f"ataqv executable not found, skipping running ataqv.") return None with file_transaction(out_file) as tx_out_file: cmd = (f"{ataqv} --peak-file {peak_file} --name {sample_name} --metrics-file {tx_out_file} " f"--tss-file {tss_bed_file} {autosomal_reference_flag} " f"--ignore-read-groups --mitochondrial-reference-name {mitoname} " f"--tss-extension 1000 " f"{organism} {bam_file}") message = f"Running ataqv on {sample_name}." do.run(cmd, message) return out_file def _make_autosomal_reference_file(out_file, data): """ for many organisms we don't know in bcbio what chromosomes are what, for now include everything non-mitochondrial """ if utils.file_exists(out_file): return out_file nonmito = chromhacks.get_nonmitochondrial_chroms(data) with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for chrom in nonmito: print(f"{chrom}", file=out_handle) return out_file def get_NF_bam(data): """ get the nucleosome free BAM file for ATAC-seq if it exists """ return tz.get_in(("atac", "align", "NF"), data, None) def get_NF_peaks(data): """ get the nucleosome free peak file for ATAC-seq if it exists """ peak_files = tz.get_in(("peaks_files", "NF", "macs2"), data, []) for f in peak_files: if f.endswith("narrowPeak") or f.endswith("broadPeak"): return f return None def get_unfiltered_bam(data): """ get the nucleosome free BAM file for ATAC-seq if it exists """ return tz.get_in(("chipseq", "align", "unfiltered"), data, None) def get_full_peaks(data): """ get the nucleosome free peak file for ATAC-seq if it exists """ peak_files = tz.get_in(("peaks_files", "full", "macs2"), data, []) for f in peak_files: if f.endswith("narrowPeak") or f.endswith("broadPeak"): return f return None def create_ataqv_report(samples): """ make the ataqv report from a set of ATAC-seq samples """ data = samples[0][0] new_samples = [] reportdir = os.path.join(dd.get_work_dir(data), "qc", "ataqv") sentinel = os.path.join(reportdir, "index.html") if utils.file_exists(sentinel): ataqv_output = {"base": sentinel, "secondary": get_ataqv_report_files(reportdir)} new_data = [] for data in dd.sample_data_iterator(samples): data = tz.assoc_in(data, ["ataqv_report"], ataqv_output) new_data.append(data) return dd.get_samples_from_datalist(new_data) mkarv = config_utils.get_program("mkarv", dd.get_config(data)) ataqv_files = [] for data in dd.sample_data_iterator(samples): qc = dd.get_summary_qc(data) ataqv_file = tz.get_in(("ataqv", "base"), qc, None) if ataqv_file and utils.file_exists(ataqv_file): ataqv_files.append(ataqv_file) if not ataqv_files: return samples ataqv_json_file_string = " ".join(ataqv_files) with file_transaction(reportdir) as txreportdir: cmd = f"{mkarv} {txreportdir} {ataqv_json_file_string}" message = f"Creating ataqv report from {ataqv_json_file_string}." do.run(cmd, message) new_data = [] ataqv_output = {"base": sentinel, "secondary": get_ataqv_report_files(reportdir)} for data in dd.sample_data_iterator(samples): data = tz.assoc_in(data, ["ataqv_report"], ataqv_output) new_data.append(data) return dd.get_samples_from_datalist(new_data) def get_ataqv_report_files(reportdir): files = [] for r, d, f in os.walk(reportdir): for file in f: f = os.path.join(r, file) if utils.file_exists(f): files.append(f) return files bcbio-nextgen-1.2.9/bcbio/chipseq/macs2.py000066400000000000000000000114271415626112400203470ustar00rootroot00000000000000import os import glob import subprocess import sys from bcbio import utils from bcbio.provenance import do from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio import bam from bcbio.chipseq import antibodies from bcbio.log import logger from bcbio.distributed.transaction import file_transaction def run(name, chip_bam, input_bam, genome_build, out_dir, method, resources, data): """ Run macs2 for chip and input samples avoiding errors due to samples. """ # output file name need to have the caller name config = dd.get_config(data) out_file = os.path.join(out_dir, name + "_peaks_macs2.xls") macs2_file = os.path.join(out_dir, name + "_peaks.xls") if utils.file_exists(out_file): _compress_and_sort_bdg_files(out_dir, data) return _get_output_files(out_dir) macs2 = config_utils.get_program("macs2", config) antibody = dd.get_antibody(data) if antibody: antibody = antibody.lower() if antibody not in antibodies.SUPPORTED_ANTIBODIES: logger.error(f"{antibody} specified, but not listed as a supported antibody. Valid antibodies are {antibodies.SUPPORTED_ANTIBODIES}. If you know your antibody " f"should be called with narrow or broad peaks, supply 'narrow' or 'broad' as the antibody." f"It will run 'narrow' if the antibody is not supported.") antibody = 'narrow' antibody = antibodies.ANTIBODIES[antibody] logger.info(f"{antibody.name} specified, using {antibody.peaktype} peak settings.") peaksettings = select_peak_parameters(antibody) elif method == "atac": logger.info(f"ATAC-seq specified, using narrow peak settings.") peaksettings = " " else: peaksettings = " " options = " ".join(resources.get("macs2", {}).get("options", "")) genome_size = bam.fasta.total_sequence_length(dd.get_ref_file(data)) genome_size = "" if options.find("-g") > -1 else "-g %s" % genome_size paired = "-f BAMPE" if bam.is_paired(chip_bam) else "" chip_reads = sum([x.aligned for x in bam.idxstats(chip_bam, data)]) if chip_reads == 0: logger.error(f"{chip_bam} has 0 reads. Please remove the sample and re-run") raise RuntimeWarning(f"macs2 terminated - no reads in {chip_bam}. Please remove the sample and re-run") with utils.chdir(out_dir): cmd = _macs2_cmd(data) cmd += peaksettings try: do.run(cmd.format(**locals()), "macs2 for %s" % name) utils.move_safe(macs2_file, out_file) except subprocess.CalledProcessError: raise RuntimeWarning("macs2 terminated with an error. " "Please, check the message and report " "error if it is related to bcbio. " "You can add specific options for the sample " "setting resources as explained in docs: " "https://bcbio-nextgen.readthedocs.org/en/latest/contents/configuration.html#sample-specific-resources") _compress_and_sort_bdg_files(out_dir, data) return _get_output_files(out_dir) def _get_output_files(out_dir): fns = [os.path.abspath(fn) for fn in glob.glob(os.path.join(out_dir, "*"))] peaks = None for fn in fns: if fn.endswith("narrowPeak"): peaks = fn break elif fn.endswith("broadPeak"): peaks = fn break return {"main": peaks, "macs2": fns} def _compress_and_sort_bdg_files(out_dir, data): for fn in glob.glob(os.path.join(out_dir, "*bdg")): out_file = fn + ".gz" if utils.file_exists(out_file): continue bedtools = config_utils.get_program("bedtools", data) with file_transaction(out_file) as tx_out_file: cmd = f"sort -k1,1 -k2,2n {fn} | bgzip -c > {tx_out_file}" message = f"Compressing and sorting {fn}." do.run(cmd, message) def _macs2_cmd(data): """Main command for macs2 tool.""" method = dd.get_chip_method(data) if method.lower() == "chip": cmd = ("{macs2} callpeak -t {chip_bam} -c {input_bam} {paired} " "{genome_size} -n {name} --bdg {options} ") elif method.lower() == "atac": cmd = ("{macs2} callpeak -t {chip_bam} --nomodel " " {paired} {genome_size} -n {name} --bdg {options}" " --nolambda --keep-dup all") else: raise ValueError("chip_method should be chip or atac.") return cmd def select_peak_parameters(antibody): if antibody.peaktype == "broad": return " --broad --broad-cutoff 0.05" elif antibody.peaktype == "narrow": return "" else: raise ValueError(f"{antibody.peaktype} not recognized.") bcbio-nextgen-1.2.9/bcbio/chipseq/peaks.py000066400000000000000000000374501415626112400204510ustar00rootroot00000000000000"""High level parallel chip-seq analysis """ import os import copy import toolz as tz import subprocess import shutil import math from tempfile import NamedTemporaryFile import pandas as pd import sys import bcbio.bam as bam from bcbio.log import logger from bcbio import utils from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction from bcbio.rnaseq import count from bcbio.chipseq.atac import ATACRanges def get_callers(): """Get functions related to each caller""" from bcbio.chipseq import macs2 return {"macs2": macs2.run} def peakcall_prepare(data, run_parallel): """Entry point for doing peak calling""" caller_fns = get_callers() to_process = [] for sample in data: mimic = copy.copy(sample[0]) callers = dd.get_peakcaller(sample[0]) if not isinstance(callers, list): callers = [callers] for caller in callers: if caller in caller_fns: mimic["peak_fn"] = caller name = dd.get_sample_name(mimic) mimic = _check(mimic, data) if mimic: to_process.append(mimic) else: logger.info("Skipping peak calling. No input sample for %s" % name) if to_process: after_process = run_parallel("peakcalling", to_process) data = _sync(data, after_process) return data def calling(data): """Main function to parallelize peak calling.""" method = dd.get_chip_method(data) caller_fn = get_callers()[data["peak_fn"]] if method == "chip": chip_bam = data.get("work_bam") input_bam = data.get("work_bam_input", None) name = dd.get_sample_name(data) out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), data["peak_fn"], name)) out_files = caller_fn(name, chip_bam, input_bam, dd.get_genome_build(data), out_dir, dd.get_chip_method(data), data["resources"], data) greylistdir = greylisting(data) data.update({"peaks_files": out_files}) if greylistdir: data["greylist"] = greylistdir if method == "atac": fractions = list(ATACRanges.keys()) + ["full"] for fraction in fractions: MIN_READS_TO_CALL = 1000 chip_bam = tz.get_in(("atac", "align", fraction), data) if not bam.has_nalignments(chip_bam, MIN_READS_TO_CALL, data): logger.warn(f"{chip_bam} has less than {MIN_READS_TO_CALL}, peak calling will fail so skip this fraction.") continue logger.info(f"Running peak calling with {data['peak_fn']} on the {fraction} fraction of {chip_bam}.") name = dd.get_sample_name(data) + f"-{fraction}" out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), data["peak_fn"], name)) out_files = caller_fn(name, chip_bam, None, dd.get_genome_build(data), out_dir, dd.get_chip_method(data), data["resources"], data) data = tz.assoc_in(data, ("peaks_files", fraction), out_files) return [[data]] def _sync(original, processed): """ Add output to data if run sucessfully. For now only macs2 is available, so no need to consider multiple callers. """ for original_sample in original: original_sample[0]["peaks_files"] = {} for process_sample in processed: if dd.get_sample_name(original_sample[0]) == dd.get_sample_name(process_sample[0]): for key in ["peaks_files", "greylist"]: if process_sample[0].get(key): original_sample[0][key] = process_sample[0][key] return original def _check(sample, data): """Get input sample for each chip bam file.""" if dd.get_chip_method(sample).lower() == "atac": return [sample] if dd.get_phenotype(sample) == "input": return None for origin in data: if dd.get_batch(sample) in (dd.get_batches(origin[0]) or []) and dd.get_phenotype(origin[0]) == "input": sample["work_bam_input"] = origin[0].get("work_bam") return [sample] return [sample] def _get_multiplier(samples): """Get multiplier to get jobs only for samples that have input """ to_process = 1.0 to_skip = 0 for sample in samples: if dd.get_phenotype(sample[0]) == "chip": to_process += 1.0 elif dd.get_chip_method(sample[0]).lower() == "atac": to_process += 1.0 else: to_skip += 1.0 mult = (to_process - to_skip) / len(samples) if mult <= 0: mult = 1 / len(samples) return max(mult, 1) def greylisting(data): """ Run ChIP-seq greylisting """ input_bam = data.get("work_bam_input", None) if not input_bam: logger.info("No input control BAM file detected, skipping greylisting.") return None try: greylister = config_utils.get_program("chipseq-greylist", data) except config_utils.CmdNotFound: logger.info("No greylister found, skipping greylisting.") return None greylistdir = os.path.join(os.path.dirname(input_bam), "greylist") if os.path.exists(greylistdir): return greylistdir cmd = "{greylister} --outdir {txgreylistdir} {input_bam}" message = "Running greylisting on %s." % input_bam with file_transaction(greylistdir) as txgreylistdir: utils.safe_makedir(txgreylistdir) try: do.run(cmd.format(**locals()), message) except subprocess.CalledProcessError as msg: if str(msg).find("Cannot take a larger sample than population when 'replace=False'") >= 0: logger.info("Skipping chipseq greylisting because of small sample size: %s" % dd.get_sample_name(data)) return None return greylistdir def consensus(peakfiles, consensusfile, data): """call consensus peaks from a set of narrow/broad peakfiles we use this method: https://bedops.readthedocs.io/en/latest/content/usage-examples/master-list.html """ if utils.file_exists(consensusfile): return consensusfile try: bedops = config_utils.get_program("bedops", data) except config_utils.CmdNotFound: logger.info("bedops not found, skipping consensus peak calling. do a " "--tools update to install bedops.") return None try: sortbed = config_utils.get_program("sort-bed", data) except config_utils.CmdNotFound: logger.info("sort-bed not found, skipping consensus peak calling. do " "--tools update to install sort-bed.") return None try: bedmap = config_utils.get_program("bedmap", data) except config_utils.CmdNotFound: logger.info("bedmap not found, skipping consensus peak calling. do a " "--tools update to install bedmap.") return None logger.info(f"Calling consensus peaks on {','.join(peakfiles)}") logger.info(f"Removing low quality peaks from {','.join(peakfiles)}") filteredpeaks = [] for fn in peakfiles: filteredpeak = NamedTemporaryFile(suffix=".bed", delete=False).name df = remove_low_quality_peaks(fn, qval=0.05) df.to_csv(filteredpeak, index=False, header=False, sep="\t") filteredpeaks.append(filteredpeak) peakfiles = filteredpeaks with file_transaction(consensusfile) as tx_consensus_file: with utils.tmpfile(suffix=".bed") as tmpbed: message = f"Move all peaks in {' '.join(peakfiles)} to a single file." mergepeakscmd = f"{bedops} -u {' '.join(peakfiles)} > {tmpbed}" do.run(mergepeakscmd, message) iteration = 0 while os.path.getsize(tmpbed): iteration = iteration + 1 iterationbed = NamedTemporaryFile(suffix=".bed", delete=False).name with utils.tmpfile(suffix="bed") as mergedbed, \ utils.tmpfile(suffix="bed") as intermediatebed, \ utils.tmpfile(suffix="bed") as leftoverbed, \ utils.tmpfile(suffix="bed") as tmpsolutionbed: mergecmd = (f"{bedops} -m --range 0:-1 {tmpbed} | " f"{bedops} -u --range 0:1 - > " f"{mergedbed}") message = f"Merging non-overlapping peaks, iteration {iteration}." do.run(mergecmd, message) nitems = len(open(mergedbed).readlines()) message = f"Considering {nitems} peaks, choosing the highest score for overlapping peaks." highscorecmd = (f"{bedmap} --max-element {mergedbed} {tmpbed} |" f"{sortbed} - > " f"{iterationbed}") do.run(highscorecmd, message) message = f"Checking if there are peaks left to merge." anyleftcmd = (f"{bedops} -n 1 {tmpbed} {iterationbed} > {intermediatebed}") do.run(anyleftcmd, message) shutil.move(intermediatebed, tmpbed) nitems = len(open(iterationbed).readlines()) message = f"Adding {nitems} peaks to consensus peaks." if utils.file_exists(tx_consensus_file): consensuscmd = (f"{bedops} -u {tx_consensus_file} {iterationbed} > {tmpsolutionbed}") do.run(consensuscmd, message) shutil.move(tmpsolutionbed, tx_consensus_file) else: shutil.move(iterationbed, tx_consensus_file) return consensusfile def call_consensus(samples): """ call consensus peaks on the narrowPeak files from a set of ChiP/ATAC samples """ data = samples[0][0] new_samples = [] consensusdir = os.path.join(dd.get_work_dir(data), "consensus") utils.safe_makedir(consensusdir) peakfiles = [] for data in dd.sample_data_iterator(samples): if dd.get_chip_method(data) == "chip": for fn in tz.get_in(("peaks_files", "macs2"), data, []): if "narrowPeak" in fn: peakfiles.append(fn) elif "broadPeak" in fn: peakfiles.append(fn) elif dd.get_chip_method(data) == "atac": if bam.is_paired(dd.get_work_bam(data)): for fn in tz.get_in(("peaks_files", "NF", "macs2") , data, []): if "narrowPeak" in fn: peakfiles.append(fn) else: logger.info(f"Using peaks from full fraction since {dd.get_work_bam(data)} is single-ended.") for fn in tz.get_in(("peaks_files", "full", "macs2") , data, []): if "narrowPeak" in fn: peakfiles.append(fn) consensusfile = os.path.join(consensusdir, "consensus.bed") if not peakfiles: logger.info("No suitable peak files found, skipping consensus peak calling.") return samples consensusfile = consensus(peakfiles, consensusfile, data) if not utils.file_exists(consensusfile): logger.warning("No consensus peaks found.") return samples saffile = consensus_to_saf(consensusfile, os.path.splitext(consensusfile)[0] + ".saf") for data in dd.sample_data_iterator(samples): data = tz.assoc_in(data, ("peaks_files", "consensus"), {"main": consensusfile}) new_samples.append([data]) return new_samples def read_peakfile(fn): """read a narrow/broad peakFile see http://genome.ucsc.edu/FAQ/FAQformat.html#format12 for a description of the formats """ if "narrowPeak" in fn: return read_narrowpeakfile(fn) elif "broadPeak" in fn: return read_broadpeakfile(fn) def read_narrowpeakfile(fn): """ read a narrowPeak file """ PEAK_HEADER = ["chrom", "chromStart", "chromEnd", "name", "score", "strand", "signalValue", "pValue", "qValue", "peak"] return pd.read_csv(fn, sep="\t", names=PEAK_HEADER) def read_broadpeakfile(fn): """ read a broadPeak file """ PEAK_HEADER = ["chrom", "chromStart", "chromEnd", "name", "score", "strand", "signalValue", "pValue", "qValue"] return pd.read_csv(fn, sep="\t", names=PEAK_HEADER) def remove_low_quality_peaks(peakfile, qval=0.05): """remove low quality peaks from a narrow/broad peakfile we define low quality peaks as peaks with a FDR (qval) higher than a cutoff, defaulting to 0.05 """ # qvals are NOT encoded in phred-style format ! phredval = - math.log10(qval) peaks = read_peakfile(peakfile) return peaks[peaks["qValue"] > phredval] def peakfile_to_summitfile(fn, out_file=None): """convert a narrow/broad peakfile to a file of summits """ if not out_file: out_file = NamedTemporaryFile(suffix=".bed", delete=False).name df = read_peakfile(fn) df["summitStart"] = df["chromStart"] + df["peak"] df["summitEnd"] = df["summitStart"] + 1 summits = df[["chrom", "summitStart", "summitEnd", "name", "qValue"]] summits.to_csv(out_file, index=False, header=False, sep="\t") return out_file def consensus_to_saf(consensusfile, saffile): """ consensus format: chrom, chromStart, chromEnd, name, qValue SAF: peakID, chrom, chromStart, chromEnd, strand """ BROAD_CONSENSUS_HEADER = ["chrom", "chromStart", "chromEnd", "name", "score", "strand", "signalValue", "pValue", "qValue"] NARROW_CONSENSUS_HEADER = ["chrom", "chromStart", "chromEnd", "name", "score", "strand", "signalValue", "pValue", "qValue", "peak"] SAF_HEADER = ["GeneID", "Chr", "Start", "End", "Strand"] if utils.file_exists(saffile): return saffile df = pd.read_csv(consensusfile, sep="\t") if len(df.columns) == 9: df.columns = BROAD_CONSENSUS_HEADER elif len(df.columns) == 10: df.columns = NARROW_CONSENSUS_HEADER else: logger.error("Could not determine if consensus peak file was from broad or narrow peaks, aborting.") sys.exit(1) df["GeneID"] = (df["chrom"].astype(str) + ":" + df["chromStart"].astype(str) + "-" + df["chromEnd"].astype(str)) df["Chr"] = df["chrom"] df["Start"] = df["chromStart"] df["End"] = df["chromEnd"] df["Strand"] = "." saf = df[SAF_HEADER] saf.to_csv(saffile, index=False, header=True, sep="\t") return saffile def create_peaktable(samples): """create a table of peak counts per sample to use with differential peak calling """ data = dd.get_data_from_sample(samples[0]) peakcounts = [] out_dir = os.path.join(dd.get_work_dir(data), "consensus") out_file = os.path.join(out_dir, "consensus-counts.tsv") if dd.get_chip_method(data) == "chip": for data in dd.sample_data_iterator(samples): peakcounts.append(tz.get_in(("peak_counts"), data)) elif dd.get_chip_method(data) == "atac": for data in dd.sample_data_iterator(samples): if bam.is_paired(dd.get_work_bam(data)): peakcounts.append(tz.get_in(("peak_counts", "NF"), data)) else: logger.info(f"Creating peak table from full BAM file because " f"{dd.get_work_bam(data)} is single-ended.") peakcounts.append(tz.get_in(("peak_counts", "full"), data)) combined_peaks = count.combine_count_files(peakcounts, out_file, ext=".counts") new_data = [] for data in dd.sample_data_iterator(samples): data = tz.assoc_in(data, ("peak_counts", "peaktable"), combined_peaks) new_data.append(data) new_samples = dd.get_samples_from_datalist(new_data) return new_samples bcbio-nextgen-1.2.9/bcbio/cwl/000077500000000000000000000000001415626112400161145ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/cwl/__init__.py000066400000000000000000000001121415626112400202170ustar00rootroot00000000000000"""Manage export of workflows for the Common Workflow Language (CWL). """ bcbio-nextgen-1.2.9/bcbio/cwl/create.py000066400000000000000000001171071415626112400177400ustar00rootroot00000000000000"""Create Common Workflow Language (CWL) runnable files and tools from a world object. """ from __future__ import print_function import collections import copy import dateutil import functools import json import math import operator import os import tarfile import requests import six import toolz as tz import yaml from bcbio import utils from bcbio.cwl import defs, workflow from bcbio.distributed import objectstore, resources from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import alignment from functools import reduce INTEGRATION_MAP = {"keep:": "arvados", "s3:": "s3", "sbg:": "sbgenomics", "dx:": "dnanexus", "gs:": "gs"} def from_world(world, run_info_file, integrations=None, add_container_tag=None): base = utils.splitext_plus(os.path.basename(run_info_file))[0] out_dir = utils.safe_makedir("%s-workflow" % (base)) out_file = os.path.join(out_dir, "main-%s.cwl" % (base)) samples = [xs[0] for xs in world] # unpack world data objects analyses = list(set([x["analysis"] for x in samples])) assert len(analyses) == 1, "Only support writing CWL for a single analysis type: %s" % analyses try: workflow_fn = defs.workflows[analyses[0].lower()] except KeyError: raise NotImplementedError("Unsupported CWL analysis type: %s" % analyses[0]) prep_cwl(samples, workflow_fn, out_dir, out_file, integrations, add_container_tag=add_container_tag) def _cwl_workflow_template(inputs, top_level=False): """Retrieve CWL inputs shared amongst different workflows. """ ready_inputs = [] for inp in inputs: cur_inp = copy.deepcopy(inp) for attr in ["source", "valueFrom", "wf_duplicate"]: cur_inp.pop(attr, None) if top_level: cur_inp = workflow._flatten_nested_input(cur_inp) cur_inp = _clean_record(cur_inp) ready_inputs.append(cur_inp) return {"class": "Workflow", "cwlVersion": "v1.0", "hints": [], "requirements": [{"class": "EnvVarRequirement", "envDef": [{"envName": "MPLCONFIGDIR", "envValue": "."}]}, {"class": "ScatterFeatureRequirement"}, {"class": "SubworkflowFeatureRequirement"}], "inputs": ready_inputs, "outputs": [], "steps": []} def _get_disk_estimates(name, parallel, inputs, file_estimates, samples, disk, cur_remotes, no_files): """Retrieve disk usage estimates as CWL ResourceRequirement and hint. Disk specification for temporary files and outputs. Also optionally includes disk input estimates as a custom hint for platforms which need to stage these and don't pre-estimate these when allocating machine sizes. """ tmp_disk, out_disk, in_disk = 0, 0, 0 if file_estimates: if disk: for key, multiplier in disk.items(): if key in file_estimates: out_disk += int(multiplier * file_estimates[key]) for inp in inputs: scale = 2.0 if inp.get("type") == "array" else 1.0 # Allocating all samples, could remove for `to_rec` when we ensure we # don't have to stage. Currently dnanexus stages everything so need to consider if parallel in ["multi-combined", "multi-batch"] and "dnanexus" in cur_remotes: scale *= (len(samples)) if workflow.is_cwl_record(inp): for f in _get_record_fields(inp): if f["name"] in file_estimates: in_disk += file_estimates[f["name"]] * scale elif inp["id"] in file_estimates: in_disk += file_estimates[inp["id"]] * scale # Round total estimates to integer, assign extra half to temp space # It's not entirely clear how different runners interpret this tmp_disk = int(math.ceil(out_disk * 0.5)) out_disk = int(math.ceil(out_disk)) bcbio_docker_disk = (10 if cur_remotes else 1) * 1024 # Minimum requirements for bcbio Docker image disk_hint = {"outdirMin": bcbio_docker_disk + out_disk, "tmpdirMin": tmp_disk} # Skip input disk for steps which require only transformation (and thus no staging) if no_files: in_disk = 0 # Avoid accidentally flagging as no staging if we don't know sizes of expected inputs elif in_disk == 0: in_disk = 1 input_hint = {"class": "dx:InputResourceRequirement", "indirMin": int(math.ceil(in_disk))} return disk_hint, input_hint def _add_current_quay_tag(repo, container_tags): """Lookup the current quay tag for the repository, adding to repo string. Enables generation of CWL explicitly tied to revisions. """ if ':' in repo: return repo, container_tags try: latest_tag = container_tags[repo] except KeyError: repo_id = repo[repo.find('/') + 1:] tags = requests.request("GET", "https://quay.io/api/v1/repository/" + repo_id).json()["tags"] latest_tag = None latest_modified = None for tag, info in tags.items(): if latest_tag: if (dateutil.parser.parse(info['last_modified']) > dateutil.parser.parse(latest_modified) and tag != 'latest'): latest_modified = info['last_modified'] latest_tag = tag else: latest_modified = info['last_modified'] latest_tag = tag container_tags[repo] = str(latest_tag) latest_pull = repo + ':' + str(latest_tag) return latest_pull, container_tags def _write_tool(step_dir, name, inputs, outputs, parallel, image, programs, file_estimates, disk, step_cores, samples, cur_remotes, no_files, container_tags=None): out_file = os.path.join(step_dir, "%s.cwl" % name) resource_cores, mem_gb_per_core = resources.cpu_and_memory((programs or []) + ["default"], samples) cores = min([step_cores, resource_cores]) if step_cores else resource_cores mem_mb_total = int(mem_gb_per_core * cores * 1024) cwl_res = {"class": "ResourceRequirement", "coresMin": cores, "ramMin": mem_mb_total} disk_hint, input_hint = _get_disk_estimates(name, parallel, inputs, file_estimates, samples, disk, cur_remotes, no_files) cwl_res.update(disk_hint) docker_image = "bcbio/bcbio" if image == "bcbio" else "quay.io/bcbio/%s" % image if container_tags is not None: docker_image, container_tags = _add_current_quay_tag(docker_image, container_tags) docker = {"class": "DockerRequirement", "dockerPull": docker_image, "dockerImageId": docker_image} out = {"class": "CommandLineTool", "cwlVersion": "v1.0", "baseCommand": ["bcbio_nextgen.py", "runfn", name, "cwl"], "requirements": [], "hints": [docker, cwl_res, input_hint], "arguments": [], "inputs": [], "outputs": []} if programs: def resolve_package(p): out = {} parts = p.split("=") if len(parts) == 2: out["package"] = parts[0] out["version"] = [parts[1]] else: out["package"] = p out["specs"] = ["https://anaconda.org/bioconda/%s" % out["package"]] return out out["hints"].append({"class": "SoftwareRequirement", "packages": [resolve_package(p) for p in programs]}) # GATK requires networking for setting up log4j logging, use arvados extension if any(p.startswith(("gatk", "sentieon")) for p in programs): out["hints"] += [{"class": "arv:APIRequirement"}] # Multi-process methods that read heavily from BAM files need extra keep cache for Arvados if name in ["pipeline_summary", "variantcall_batch_region", "detect_sv"]: out["hints"] += [{"class": "arv:RuntimeConstraints", "keep_cache": 4096}] def add_to_namespaces(k, v, out): if "$namespaces" not in out: out["$namespaces"] = {} out["$namespaces"][k] = v return out if any(h.get("class", "").startswith("arv:") for h in out["hints"]): out = add_to_namespaces("arv", "http://arvados.org/cwl#", out) if any(h.get("class", "").startswith("dx") for h in out["hints"]): out = add_to_namespaces("dx", "https://www.dnanexus.com/cwl#", out) # Use JSON for inputs, rather than command line arguments # Correctly handles multiple values and batching across CWL runners use_commandline_args = False out["requirements"] += [{"class": "InlineJavascriptRequirement"}, {"class": "InitialWorkDirRequirement", "listing": [{"entryname": "cwl.inputs.json", "entry": "$(JSON.stringify(inputs))"}]}] out["arguments"] += [{"position": 0, "valueFrom": "sentinel_runtime=cores,$(runtime['cores']),ram,$(runtime['ram'])"}, "sentinel_parallel=%s" % parallel, "sentinel_outputs=%s" % ",".join([_get_sentinel_val(v) for v in outputs]), "sentinel_inputs=%s" % ",".join(["%s:%s" % (workflow.get_base_id(v["id"]), "record" if workflow.is_cwl_record(v) else "var") for v in inputs]), "run_number=0"] out = _add_inputs_to_tool(inputs, out, parallel, use_commandline_args) out = _add_outputs_to_tool(outputs, out) _tool_to_file(out, out_file) return os.path.join("steps", os.path.basename(out_file)) def _write_expressiontool(step_dir, name, inputs, outputs, expression, parallel): """Create an ExpressionTool output for the given inputs """ out_file = os.path.join(step_dir, "%s.cwl" % name) out = {"class": "ExpressionTool", "cwlVersion": "v1.0", "requirements": [{"class": "InlineJavascriptRequirement"}], "inputs": [], "outputs": [], "expression": expression} out = _add_inputs_to_tool(inputs, out, parallel) out = _add_outputs_to_tool(outputs, out) _tool_to_file(out, out_file) return os.path.join("steps", os.path.basename(out_file)) def _add_outputs_to_tool(outputs, tool): for outp in outputs: outp_tool = copy.deepcopy(outp) outp_tool = _clean_record(outp_tool) outp_tool["id"] = workflow.get_base_id(outp["id"]) tool["outputs"].append(outp_tool) return tool def _add_inputs_to_tool(inputs, tool, parallel, use_commandline_args=False): for i, inp in enumerate(inputs): base_id = workflow.get_base_id(inp["id"]) inp_tool = copy.deepcopy(inp) inp_tool["id"] = base_id if inp.get("wf_duplicate"): inp_tool["id"] += "_toolinput" for attr in ["source", "valueFrom", "wf_duplicate"]: inp_tool.pop(attr, None) # Ensure records and workflow inputs get scattered if (_is_scatter_parallel(parallel) and _do_scatter_var(inp, parallel) and (workflow.is_cwl_record(inp) or inp["wf_duplicate"])): inp_tool = workflow._flatten_nested_input(inp_tool) if use_commandline_args: inp_binding = {"prefix": "%s=" % base_id, "separate": False, "itemSeparator": ";;", "position": i} inp_tool = _place_input_binding(inp_tool, inp_binding, parallel) else: inp_binding = None inp_tool = _place_secondary_files(inp_tool, inp_binding) inp_tool = _clean_record(inp_tool) tool["inputs"].append(inp_tool) return tool def _tool_to_file(tool, out_file): with open(out_file, "w") as out_handle: def str_presenter(dumper, data): if len(data.splitlines()) > 1: # check for multiline string return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') return dumper.represent_scalar('tag:yaml.org,2002:str', data) yaml.add_representer(str, str_presenter) yaml.dump(tool, out_handle, default_flow_style=False, allow_unicode=False) return out_file def _clean_record(rec): """Remove secondary files from record fields, which are currently not supported. To be removed later when secondaryFiles added to records. """ if workflow.is_cwl_record(rec): def _clean_fields(d): if isinstance(d, dict): if "fields" in d: out = [] for f in d["fields"]: f = utils.deepish_copy(f) f.pop("secondaryFiles", None) out.append(f) d["fields"] = out return d else: out = {} for k, v in d.items(): out[k] = _clean_fields(v) return out else: return d return _clean_fields(rec) else: return rec def _get_record_fields(d): """Get field names from a potentially nested record. """ if isinstance(d, dict): if "fields" in d: return d["fields"] else: for v in d.values(): fields = _get_record_fields(v) if fields: return fields def _get_sentinel_val(v): """Retrieve expected sentinel value for an output, expanding records. """ out = workflow.get_base_id(v["id"]) if workflow.is_cwl_record(v): out += ":%s" % ";".join([x["name"] for x in _get_record_fields(v)]) return out def _place_input_binding(inp_tool, inp_binding, parallel): """Check nesting of variables to determine where to place the input binding. We want to allow having multiple files together (like fasta_indices), combined with the itemSeparator, but also support having multiple samples where we pass things independently. """ if (parallel in ["multi-combined", "multi-batch", "batch-split", "batch-parallel", "batch-merge", "batch-single"] and tz.get_in(["type", "type"], inp_tool) == "array"): inp_tool["type"]["inputBinding"] = inp_binding else: inp_tool["inputBinding"] = inp_binding return inp_tool def _place_secondary_files(inp_tool, inp_binding=None): """Put secondaryFiles at the level of the File item to ensure indexes get passed. """ def _is_file(val): return (val == "File" or (isinstance(val, (list, tuple)) and ("File" in val or any(isinstance(x, dict) and _is_file(val)) for x in val))) secondary_files = inp_tool.pop("secondaryFiles", None) if secondary_files: key = [] while (not _is_file(tz.get_in(key + ["type"], inp_tool)) and not _is_file(tz.get_in(key + ["items"], inp_tool)) and not _is_file(tz.get_in(key + ["items", "items"], inp_tool))): key.append("type") if tz.get_in(key, inp_tool): inp_tool["secondaryFiles"] = secondary_files elif inp_binding: nested_inp_binding = copy.deepcopy(inp_binding) nested_inp_binding["prefix"] = "ignore=" nested_inp_binding["secondaryFiles"] = secondary_files inp_tool = tz.update_in(inp_tool, key, lambda x: nested_inp_binding) return inp_tool def _is_scatter_parallel(parallel): return parallel.endswith("-parallel") def _do_scatter_var(v, parallel): """Logic for scattering a variable. """ # For batches, scatter records only at the top level (double nested) if parallel.startswith("batch") and workflow.is_cwl_record(v): return (tz.get_in(["type", "type"], v) == "array" and tz.get_in(["type", "type", "type"], v) == "array") # Otherwise, scatter arrays else: return (tz.get_in(["type", "type"], v) == "array") def _step_template(name, run_file, inputs, outputs, parallel, step_parallelism, scatter=None): """Templating function for writing a step to avoid repeating namespaces. """ scatter_inputs = [] sinputs = [] for inp in inputs: step_inp = {"id": workflow.get_base_id(inp["id"]), "source": inp["id"]} if inp.get("wf_duplicate"): step_inp["id"] += "_toolinput" for attr in ["source", "valueFrom"]: if attr in inp: step_inp[attr] = inp[attr] sinputs.append(step_inp) # An initial parallel scatter and multiple chained parallel sample scatters if (parallel == "multi-parallel" and (not step_parallelism or step_parallelism.get(workflow.get_step_prefix(inp["id"])) == "multi-parallel")): scatter_inputs.append(step_inp["id"]) # scatter on inputs from previous processes that have been arrayed elif (_is_scatter_parallel(parallel) and (_do_scatter_var(inp, parallel) or (scatter and inp["id"] in scatter))): scatter_inputs.append(step_inp["id"]) out = {"run": run_file, "id": name, "in": sinputs, "out": [{"id": workflow.get_base_id(output["id"])} for output in outputs]} if _is_scatter_parallel(parallel): assert scatter_inputs, "Did not find items to scatter on: %s" % name out.update({"scatterMethod": "dotproduct", "scatter": scatter_inputs}) return out def _get_cur_remotes(path): """Retrieve remote references defined in the CWL. """ cur_remotes = set([]) if isinstance(path, (list, tuple)): for v in path: cur_remotes |= _get_cur_remotes(v) elif isinstance(path, dict): for v in path.values(): cur_remotes |= _get_cur_remotes(v) elif path and isinstance(path, six.string_types): if path.startswith(tuple(INTEGRATION_MAP.keys())): cur_remotes.add(INTEGRATION_MAP.get(path.split(":")[0] + ":")) return cur_remotes def prep_cwl(samples, workflow_fn, out_dir, out_file, integrations=None, add_container_tag=None): """Output a CWL description with sub-workflows and steps. """ if add_container_tag is None: container_tags = None elif add_container_tag.lower() == "quay_lookup": container_tags = {} else: container_tags = collections.defaultdict(lambda: add_container_tag) step_dir = utils.safe_makedir(os.path.join(out_dir, "steps")) get_retriever = GetRetriever(integrations, samples) variables, keyvals = _flatten_samples(samples, out_file, get_retriever) cur_remotes = _get_cur_remotes(keyvals) file_estimates = _calc_input_estimates(keyvals, get_retriever) out = _cwl_workflow_template(variables) parent_wfs = [] step_parallelism = {} steps, wfoutputs = workflow_fn(samples) used_inputs = set([]) for cur in workflow.generate(variables, steps, wfoutputs): if cur[0] == "step": _, name, parallel, inputs, outputs, image, programs, disk, cores, no_files = cur step_file = _write_tool(step_dir, name, inputs, outputs, parallel, image, programs, file_estimates, disk, cores, samples, cur_remotes, no_files, container_tags) out["steps"].append(_step_template(name, step_file, inputs, outputs, parallel, step_parallelism)) used_inputs |= set(x["id"] for x in inputs) elif cur[0] == "expressiontool": _, name, inputs, outputs, expression, parallel = cur step_file = _write_expressiontool(step_dir, name, inputs, outputs, expression, parallel) out["steps"].append(_step_template(name, step_file, inputs, outputs, parallel, step_parallelism)) used_inputs |= set(x["id"] for x in inputs) elif cur[0] == "upload": for output in cur[1]: wf_output = copy.deepcopy(output) if "outputSource" not in wf_output: wf_output["outputSource"] = wf_output.pop("source") wf_output = _clean_record(wf_output) # Avoid input/output naming clashes if wf_output["id"] in used_inputs: wf_output["id"] = "%s_out" % wf_output["id"] out["outputs"].append(wf_output) elif cur[0] == "wf_start": parent_wfs.append(out) out = _cwl_workflow_template(cur[1]) elif cur[0] == "wf_finish": _, name, parallel, inputs, outputs, scatter = cur wf_out_file = "wf-%s.cwl" % name with open(os.path.join(out_dir, wf_out_file), "w") as out_handle: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) out = parent_wfs.pop(-1) out["steps"].append(_step_template(name, wf_out_file, inputs, outputs, parallel, step_parallelism, scatter)) used_inputs |= set(x["id"] for x in inputs) else: raise ValueError("Unexpected workflow value %s" % str(cur)) step_parallelism[name] = parallel with open(out_file, "w") as out_handle: out["inputs"] = [x for x in out["inputs"] if x["id"] in used_inputs] yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) sample_json = "%s-samples.json" % utils.splitext_plus(out_file)[0] out_clean = _clean_final_outputs(copy.deepcopy({k: v for k, v in keyvals.items() if k in used_inputs}), get_retriever) with open(sample_json, "w") as out_handle: json.dump(out_clean, out_handle, sort_keys=True, indent=4, separators=(',', ': ')) return out_file, sample_json def _flatten_samples(samples, base_file, get_retriever): """Create a flattened JSON representation of data from the bcbio world map. """ flat_data = [] for data in samples: data["reference"] = _indexes_to_secondary_files(data["reference"], data["genome_build"]) cur_flat = {} for key_path in [["analysis"], ["description"], ["rgnames"], ["config", "algorithm"], ["metadata"], ["genome_build"], ["resources"], ["files"], ["reference"], ["genome_resources"], ["vrn_file"]]: cur_key = "__".join(key_path) for flat_key, flat_val in _to_cwldata(cur_key, tz.get_in(key_path, data), get_retriever): cur_flat[flat_key] = flat_val flat_data.append(cur_flat) out = {} for key in sorted(list(set(reduce(operator.add, [list(d.keys()) for d in flat_data])))): # Periods in keys cause issues with WDL and some CWL implementations clean_key = key.replace(".", "_") out[clean_key] = [] for cur_flat in flat_data: out[clean_key].append(cur_flat.get(key)) # special case for back-compatibility with fasta specifications -- yuck if "reference__fasta__base" not in out and "reference__fasta" in out: out["reference__fasta__base"] = out["reference__fasta"] del out["reference__fasta"] return _samplejson_to_inputs(out), out def _indexes_to_secondary_files(gresources, genome_build): """Convert a list of genome indexes into a single file plus secondary files. This ensures that all indices are staged together in a single directory. """ out = {} for refname, val in gresources.items(): if isinstance(val, dict) and "indexes" in val: # list of indexes -- aligners if len(val.keys()) == 1: indexes = sorted(val["indexes"]) if len(indexes) == 0: if refname not in alignment.allow_noindices(): raise ValueError("Did not find indexes for %s: %s" % (refname, val)) elif len(indexes) == 1: val = {"indexes": indexes[0]} else: val = {"indexes": {"base": indexes[0], "indexes": indexes[1:]}} # directory plus indexes -- snpEff elif "base" in val and os.path.isdir(val["base"]) and len(val["indexes"]) > 0: indexes = val["indexes"] val = {"base": indexes[0], "indexes": indexes[1:]} elif isinstance(val, dict) and genome_build in val: val = _indexes_to_secondary_files(val, genome_build) out[refname] = val return out def _add_suppl_info(inp, val): """Add supplementary information to inputs from file values. """ inp["type"] = _get_avro_type(val) secondary = _get_secondary_files(val) if secondary: inp["secondaryFiles"] = secondary return inp def _get_secondary_files(val): """Retrieve associated secondary files. Normalizes input values into definitions of available secondary files. Requires indices to be present in all files, since declared CWL secondary files are not optional. So if we have a mix of BAM (bai) and fastq (gbi) we ignore the existing indices and will have to regenerate during processing. """ out = [] if isinstance(val, (tuple, list)): s_counts = collections.defaultdict(int) for x in val: for s in _get_secondary_files(x): s_counts[s] += 1 for s, count in s_counts.items(): if s and s not in out and count == len([x for x in val if x]): out.append(s) elif isinstance(val, dict) and (val.get("class") == "File" or "File" in val.get("class")): if "secondaryFiles" in val: for sf in [x["path"] for x in val["secondaryFiles"]]: rext = _get_relative_ext(val["path"], sf) if rext and rext not in out: out.append(rext) return out def _get_relative_ext(of, sf): """Retrieve relative extension given the original and secondary files. """ def half_finished_trim(orig, prefix): return (os.path.basename(prefix).count(".") > 0 and os.path.basename(orig).count(".") == os.path.basename(prefix).count(".")) # Handle remote files if of.find(":") > 0: of = os.path.basename(of.split(":")[-1]) if sf.find(":") > 0: sf = os.path.basename(sf.split(":")[-1]) prefix = os.path.commonprefix([sf, of]) while prefix.endswith(".") or (half_finished_trim(sf, prefix) and half_finished_trim(of, prefix)): prefix = prefix[:-1] exts_to_remove = of.replace(prefix, "") ext_to_add = sf.replace(prefix, "") # Return extensions relative to original if not exts_to_remove or exts_to_remove.startswith("."): return str("^" * exts_to_remove.count(".") + ext_to_add) else: raise ValueError("No cross platform way to reference complex extension: %s %s" % (sf, of)) def _get_avro_type(val): """Infer avro type for the current input. """ if isinstance(val, dict): assert val.get("class") == "File" or "File" in val.get("class") return "File" elif isinstance(val, (tuple, list)): types = [] for ctype in [_get_avro_type(v) for v in val]: if isinstance(ctype, dict): nested_types = [x["items"] for x in types if isinstance(x, dict)] if ctype["items"] not in nested_types: if isinstance(ctype["items"], (list, tuple)): for t in ctype["items"]: if t not in types: types.append(t) else: if ctype not in types: types.append(ctype) elif isinstance(ctype, (list, tuple)): for x in ctype: if x not in types: types.append(x) elif ctype not in types: types.append(ctype) # handle empty types, allow null if len(types) == 0: types = ["null"] # empty lists if isinstance(val, (list, tuple)) and len(val) == 0: types.append({"type": "array", "items": ["null"]}) types = _avoid_duplicate_arrays(types) # Avoid empty null only arrays which confuse some runners if len(types) == 1 and types[0] == "null": types.append("string") return {"type": "array", "items": (types[0] if len(types) == 1 else types)} elif val is None: return ["null"] # encode booleans as string True/False and unencode on other side elif isinstance(val, bool) or isinstance(val, six.string_types) and val.lower() in ["true", "false", "none"]: return ["string", "null", "boolean"] elif isinstance(val, int): return "long" elif isinstance(val, float): return "double" else: return "string" def _avoid_duplicate_arrays(types): """Collapse arrays when we have multiple types. """ arrays = [t for t in types if isinstance(t, dict) and t["type"] == "array"] others = [t for t in types if not (isinstance(t, dict) and t["type"] == "array")] if arrays: items = set([]) for t in arrays: if isinstance(t["items"], (list, tuple)): items |= set(t["items"]) else: items.add(t["items"]) if len(items) == 1: items = items.pop() else: items = sorted(list(items)) arrays = [{"type": "array", "items": items}] return others + arrays def _samplejson_to_inputs(svals): """Convert sample output into inputs for CWL configuration files, with types. """ out = [] for key, val in svals.items(): out.append(_add_suppl_info({"id": "%s" % key}, val)) return out def _to_cwldata(key, val, get_retriever): """Convert nested dictionary into CWL data, flatening and marking up files. Moves file objects to the top level, enabling insertion in CWL inputs/outputs. """ out = [] if isinstance(val, dict): if len(val) == 2 and "base" in val and "indexes" in val: if len(val["indexes"]) > 0 and val["base"] == val["indexes"][0]: out.append(("%s__indexes" % key, _item_to_cwldata(val["base"], get_retriever))) else: out.append((key, _to_cwlfile_with_indexes(val, get_retriever))) # Dump shared nested keys like resources as a JSON string elif key in workflow.ALWAYS_AVAILABLE or key in workflow.STRING_DICT: out.append((key, _item_to_cwldata(json.dumps(val), get_retriever))) elif key in workflow.FLAT_DICT: flat = [] for k, vs in val.items(): if not isinstance(vs, (list, tuple)): vs = [vs] for v in vs: flat.append("%s:%s" % (k, v)) out.append((key, _item_to_cwldata(flat, get_retriever))) else: remain_val = {} for nkey, nval in val.items(): cur_nkey = "%s__%s" % (key, nkey) cwl_nval = _item_to_cwldata(nval, get_retriever) if isinstance(cwl_nval, dict): out.extend(_to_cwldata(cur_nkey, nval, get_retriever)) elif key in workflow.ALWAYS_AVAILABLE: remain_val[nkey] = nval else: out.append((cur_nkey, cwl_nval)) if remain_val: out.append((key, json.dumps(remain_val, sort_keys=True, separators=(',', ':')))) else: out.append((key, _item_to_cwldata(val, get_retriever))) return out def _remove_remote_prefix(f): """Remove any remote references to allow object lookups by file paths. """ return f.split(":")[-1].split("/", 1)[1] if objectstore.is_remote(f) else f def _index_blacklist(xs): blacklist = ["-resources.yaml"] return [x for x in xs if not any([x.find(b) >=0 for b in blacklist])] def _to_cwlfile_with_indexes(val, get_retriever): """Convert reads with ready to go indexes into the right CWL object. Identifies the top level directory and creates a tarball, avoiding trying to handle complex secondary setups which are not cross platform. Skips doing this for reference files and standard setups like bwa, which take up too much time and space to unpack multiple times. """ val["indexes"] = _index_blacklist(val["indexes"]) tval = {"base": _remove_remote_prefix(val["base"]), "indexes": [_remove_remote_prefix(f) for f in val["indexes"]]} # Standard named set of indices, like bwa # Do not include snpEff, which we need to isolate inside a nested directory # hisat2 indices do also not localize cleanly due to compilicated naming cp_dir, cp_base = os.path.split(os.path.commonprefix([tval["base"]] + tval["indexes"])) if (cp_base and cp_dir == os.path.dirname(tval["base"]) and not ("/snpeff/" in cp_dir or "/hisat2" in cp_dir)): return _item_to_cwldata(val["base"], get_retriever, val["indexes"]) else: dirname = os.path.dirname(tval["base"]) assert all([x.startswith(dirname) for x in tval["indexes"]]) return {"class": "File", "path": directory_tarball(dirname)} def _add_secondary_if_exists(secondary, out, get_retriever): """Add secondary files only if present locally or remotely. """ secondary = [_file_local_or_remote(y, get_retriever) for y in secondary] secondary = [z for z in secondary if z] if secondary: out["secondaryFiles"] = [{"class": "File", "path": f} for f in secondary] return out def _item_to_cwldata(x, get_retriever, indexes=None): """"Markup an item with CWL specific metadata. """ if isinstance(x, (list, tuple)): return [_item_to_cwldata(subx, get_retriever) for subx in x] elif (x and isinstance(x, six.string_types) and (((os.path.isfile(x) or os.path.isdir(x)) and os.path.exists(x)) or objectstore.is_remote(x))): if _file_local_or_remote(x, get_retriever): out = {"class": "File", "path": x} if indexes: out = _add_secondary_if_exists(indexes, out, get_retriever) elif x.endswith(".bam"): out = _add_secondary_if_exists([x + ".bai"], out, get_retriever) elif x.endswith(".cram"): out = _add_secondary_if_exists([x + ".crai"], out, get_retriever) elif x.endswith((".vcf.gz", ".bed.gz")): out = _add_secondary_if_exists([x + ".tbi"], out, get_retriever) elif x.endswith(".fa"): out = _add_secondary_if_exists([x + ".fai", os.path.splitext(x)[0] + ".dict", os.path.splitext(x)[0] + "-resources.yaml"], out, get_retriever) elif x.endswith(".fa.gz"): out = _add_secondary_if_exists([x + ".fai", x + ".gzi", x.replace(".fa.gz", "") + ".dict"], out, get_retriever) elif x.endswith(".fq.gz") or x.endswith(".fastq.gz"): out = _add_secondary_if_exists([x + ".gbi"], out, get_retriever) elif x.endswith(".gtf"): out = _add_secondary_if_exists([x + ".db"], out, get_retriever) else: out = {"class": "File", "path": directory_tarball(x)} return out elif isinstance(x, bool): return str(x) else: return x def _file_local_or_remote(f, get_retriever): """Check for presence of a local or remote file. """ if os.path.exists(f): return f integration, config = get_retriever.integration_and_config(f) if integration: return integration.file_exists(f, config) def directory_tarball(dirname): """Create a tarball of a complex directory, avoiding complex secondaryFiles. Complex secondary files do not work on multiple platforms and are not portable to WDL, so for now we create a tarball that workers will unpack. """ assert os.path.isdir(dirname), dirname base_dir, tarball_dir = os.path.split(dirname) while not os.path.exists(os.path.join(base_dir, "seq")) and base_dir and base_dir != "/": base_dir, extra_tarball = os.path.split(base_dir) tarball_dir = os.path.join(extra_tarball, tarball_dir) if base_dir == "/" and not os.path.exists(os.path.join(base_dir, "seq")): raise ValueError("Did not find relative directory to create tarball for %s" % dirname) tarball = os.path.join(base_dir, "%s-wf.tar.gz" % (tarball_dir.replace(os.path.sep, "--"))) if not utils.file_exists(tarball): print("Preparing CWL input tarball: %s" % tarball) with file_transaction({}, tarball) as tx_tarball: with utils.chdir(base_dir): with tarfile.open(tx_tarball, "w:gz") as tar: tar.add(tarball_dir) return tarball def _clean_final_outputs(keyvals, get_retriever): def clean_path(get_retriever, x): integration, config = get_retriever.integration_and_config(x) if integration: return integration.clean_file(x, config) else: return x keyvals = _adjust_files(keyvals, functools.partial(clean_path, get_retriever)) return keyvals def _adjust_items(xs, adjust_fn): if isinstance(xs, (list, tuple)): return [_adjust_items(x, adjust_fn) for x in xs] elif isinstance(xs, dict): out = {} for k, v in xs.items(): out[k] = _adjust_items(v, adjust_fn) return out else: return adjust_fn(xs) def _adjust_files(xs, adjust_fn): """Walk over key/value, tuples applying adjust_fn to files. """ if isinstance(xs, dict): if "path" in xs: out = {} out["path"] = adjust_fn(xs["path"]) for k, vs in xs.items(): if k != "path": out[k] = _adjust_files(vs, adjust_fn) return out else: out = {} for k, vs in xs.items(): out[k] = _adjust_files(vs, adjust_fn) return out elif isinstance(xs, (list, tuple)): return [_adjust_files(x, adjust_fn) for x in xs] else: return xs def _calc_input_estimates(keyvals, get_retriever): """Calculate estimations of input file sizes for disk usage approximation. These are current dominated by fastq/BAM sizes, so estimate based on that. """ out = {} for key, val in keyvals.items(): size = _calc_file_size(val, 0, get_retriever) if size: out[key] = size return out def _calc_file_size(val, depth, get_retriever): if isinstance(val, (list, tuple)): sizes = [_calc_file_size(x, depth + 1, get_retriever) for x in val] sizes = [x for x in sizes if x] if sizes: # Top level, biggest item, otherwise all files together return max(sizes) if depth == 0 else sum(sizes) elif isinstance(val, dict) and "path" in val: return _get_file_size(val["path"], get_retriever) return None class GetRetriever: def __init__(self, integrations, samples): self._integrations = integrations self._samples = samples def integration_and_config(self, path): """Get a retriever and configuration for the given file path. """ if path.startswith(tuple(INTEGRATION_MAP.keys())): key = INTEGRATION_MAP[path.split(":")[0] + ":"] integration = self._integrations.get(key) config = {} for sample in self._samples: config = tz.get_in(["config", key], sample) if config: break return integration, config return None, None def _get_file_size(path, get_retriever): """Return file size in megabytes, including querying remote integrations """ integration, config = get_retriever.integration_and_config(path) if integration: return integration.file_size(path, config) elif os.path.exists(path): return os.path.getsize(path) / (1024.0 * 1024.0) bcbio-nextgen-1.2.9/bcbio/cwl/cwlutils.py000066400000000000000000000246541415626112400203470ustar00rootroot00000000000000"""Useful utilities for handling CWL inputs and outputs. This is shared functionality abstracted across multiple approaches, currently mostly handling CWL records. This needs some generalization to apply across non-variant calling workflows. """ import collections import glob import os import pprint import tarfile import six import toolz as tz from bcbio import bam, utils from bcbio.pipeline import datadict as dd from bcbio.variation import vcfutils def to_rec(samples, default_keys=None): """Convert inputs into CWL records, useful for single item parallelization. """ recs = samples_to_records([normalize_missing(utils.to_single_data(x)) for x in samples], default_keys) return [[x] for x in recs] def to_rec_single(samples, default_keys=None): """Convert output into a list of single CWL records. """ out = [] for data in samples: recs = samples_to_records([normalize_missing(utils.to_single_data(data))], default_keys) assert len(recs) == 1 out.append(recs[0]) return out def is_cwl_run(data): return data.get("is_cwl") or data.get("cwl_keys") or data.get("output_cwl_keys") def handle_combined_input(args): """Check for cases where we have a combined input nested list. In these cases the CWL will be double nested: [[[rec_a], [rec_b]]] and we remove the outer nesting. """ cur_args = args[:] while len(cur_args) == 1 and isinstance(cur_args[0], (list, tuple)): cur_args = cur_args[0] return cur_args def normalize_missing(xs): """Normalize missing values to avoid string 'None' inputs. """ if isinstance(xs, dict): for k, v in xs.items(): xs[k] = normalize_missing(v) elif isinstance(xs, (list, tuple)): xs = [normalize_missing(x) for x in xs] elif isinstance(xs, six.string_types): if xs.lower() in ["none", "null"]: xs = None elif xs.lower() == "true": xs = True elif xs.lower() == "false": xs = False return xs # aligner and database indices where we list the entire directory as secondary files DIR_TARGETS = ("mainIndex", ".alt", ".amb", ".ann", ".bwt", ".pac", ".sa", ".ebwt", ".bt2", "Genome", "GenomeIndex", "GenomeIndexHash", "OverflowTable", ".fa") # indices where we take the basename if the file is found BASENAME_TARGETS = (".exons") def unpack_tarballs(xs, data, use_subdir=True): """Unpack workflow tarballs into ready to use directories. """ if isinstance(xs, dict): for k, v in xs.items(): xs[k] = unpack_tarballs(v, data, use_subdir) elif isinstance(xs, (list, tuple)): xs = [unpack_tarballs(x, data, use_subdir) for x in xs] elif isinstance(xs, six.string_types): if os.path.isfile(xs.encode("utf-8", "ignore")) and xs.endswith("-wf.tar.gz"): if use_subdir: tarball_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "wf-inputs")) else: tarball_dir = dd.get_work_dir(data) out_dir = os.path.join(tarball_dir, os.path.basename(xs).replace("-wf.tar.gz", "").replace("--", os.path.sep)) if not os.path.exists(out_dir): with utils.chdir(tarball_dir): with tarfile.open(xs, "r:gz") as tar: tar.extractall() assert os.path.exists(out_dir), out_dir # Default to representing output directory xs = out_dir # Look for aligner indices for fname in os.listdir(out_dir): if fname.endswith(DIR_TARGETS): xs = os.path.join(out_dir, fname) break elif fname.endswith(BASENAME_TARGETS): base = os.path.join(out_dir, utils.splitext_plus(os.path.basename(fname))[0]) xs = glob.glob("%s*" % base) break return xs def _get_all_cwlkeys(items, default_keys=None): """Retrieve cwlkeys from inputs, handling defaults which can be null. When inputs are null in some and present in others, this creates unequal keys in each sample, confusing decision making about which are primary and extras. """ if default_keys: default_keys = set(default_keys) else: default_keys = set(["metadata__batch", "config__algorithm__validate", "config__algorithm__validate_regions", "config__algorithm__validate_regions_merged", "config__algorithm__variant_regions", "validate__summary", "validate__tp", "validate__fp", "validate__fn", "config__algorithm__coverage", "config__algorithm__coverage_merged", "genome_resources__variation__cosmic", "genome_resources__variation__dbsnp", "genome_resources__variation__clinvar" ]) all_keys = set([]) for data in items: all_keys.update(set(data["cwl_keys"])) all_keys.update(default_keys) return all_keys def split_data_cwl_items(items, default_keys=None): """Split a set of CWL output dictionaries into data samples and CWL items. Handles cases where we're arrayed on multiple things, like a set of regional VCF calls and data objects. """ key_lens = set([]) for data in items: key_lens.add(len(_get_all_cwlkeys([data], default_keys))) extra_key_len = min(list(key_lens)) if len(key_lens) > 1 else None data_out = [] extra_out = [] for data in items: if extra_key_len and len(_get_all_cwlkeys([data], default_keys)) == extra_key_len: extra_out.append(data) else: data_out.append(data) if len(extra_out) == 0: return data_out, {} else: cwl_keys = extra_out[0]["cwl_keys"] for extra in extra_out[1:]: cur_cwl_keys = extra["cwl_keys"] assert cur_cwl_keys == cwl_keys, pprint.pformat(extra_out) cwl_extras = collections.defaultdict(list) for data in items: for key in cwl_keys: cwl_extras[key].append(data[key]) data_final = [] for data in data_out: for key in cwl_keys: data.pop(key) data_final.append(data) return data_final, dict(cwl_extras) def samples_to_records(samples, default_keys=None): """Convert samples into output CWL records. """ from bcbio.pipeline import run_info RECORD_CONVERT_TO_LIST = set(["config__algorithm__tools_on", "config__algorithm__tools_off", "reference__genome_context"]) all_keys = _get_all_cwlkeys(samples, default_keys) out = [] for data in samples: for raw_key in sorted(list(all_keys)): key = raw_key.split("__") if tz.get_in(key, data) is None: data = tz.update_in(data, key, lambda x: None) if raw_key not in data["cwl_keys"]: data["cwl_keys"].append(raw_key) if raw_key in RECORD_CONVERT_TO_LIST: val = tz.get_in(key, data) if not val: val = [] elif not isinstance(val, (list, tuple)): val = [val] data = tz.update_in(data, key, lambda x: val) # Booleans are problematic for CWL serialization, convert into string representation if isinstance(tz.get_in(key, data), bool): data = tz.update_in(data, key, lambda x: str(tz.get_in(key, data))) data["metadata"] = run_info.add_metadata_defaults(data.get("metadata", {})) out.append(data) return out def assign_complex_to_samples(items): """Assign complex inputs like variants and align outputs to samples. Handles list inputs to record conversion where we have inputs from multiple locations and need to ensure they are properly assigned to samples in many environments. The unpleasant approach here is to use standard file naming to match with samples so this can work in environments where we don't download/stream the input files (for space/time savings). """ extract_fns = {("variants", "samples"): _get_vcf_samples, ("align_bam",): _get_bam_samples} complex = {k: {} for k in extract_fns.keys()} for data in items: for k in complex: v = tz.get_in(k, data) if v is not None: for s in extract_fns[k](v, items): if s: complex[k][s] = v out = [] for data in items: for k in complex: newv = tz.get_in([k, dd.get_sample_name(data)], complex) if newv: data = tz.update_in(data, k, lambda x: newv) out.append(data) return out def _get_vcf_samples(calls, items): have_full_file = False all_samples = set([]) sample_matches = False for f in utils.flatten(calls): if have_full_file: cur = set(vcfutils.get_samples(f)) if cur: if not all_samples: all_samples = cur else: all_samples &= set(cur) else: for data in items: for i, test_name in enumerate([dd.get_sample_name(data)] + dd.get_batches(data)): # For tumor/normal batches, want to attach germline VCFs to normals # Standard somatics go to tumors if dd.get_phenotype(data) == "normal": test_name += "-germline" if os.path.basename(f).startswith(("%s-" % test_name, "%s." % test_name)): # Prefer matches to single samples (gVCF) over joint batches if i == 0: sample_matches = True if sample_matches and i > 0: continue else: all_samples.add(dd.get_sample_name(data)) return list(all_samples) def _get_bam_samples(f, items): have_full_file = False if have_full_file: return [bam.sample_name(f)] else: for data in items: if os.path.basename(f).startswith(("%s-" % dd.get_sample_name(data), "%s." % dd.get_sample_name(data))): return [dd.get_sample_name(data)] return [] bcbio-nextgen-1.2.9/bcbio/cwl/defs.py000066400000000000000000001153531415626112400174170ustar00rootroot00000000000000"""Definitions of workflows for translation into common workflow language. This organizes the metadata and other information about workflows, providing the necessary information to translate into CWL. The goal is to eventually replace pipeline/main.py workflows with generalized versions of this code. Ideally we could translate the specification of these workflows into a YAML-based DSL (some sort of CWL-lite), instead of writing them in Python code. The variable 'workflows' provides a dictionary to retrieve the steps and outputs for each of the defined workflows. """ import collections from bcbio.pipeline import datadict as dd def s(name, parallel, inputs, outputs, image, programs=None, disk=None, cores=None, unlist=None, no_files=False): """Represent a step in a workflow. name -- The run function name, which must match a definition in distributed/multitasks inputs -- List of input keys required for the function. Each key is of the type: ["toplevel", "sublevel"] -- an argument you could pass to toolz.get_in. outputs -- List of outputs with information about file type. Use cwlout functions programs -- Required programs for this step, used to define resource usage. disk -- Information about disk usage requirements, specified as multipliers of input files. Ensures enough disk present when that is a limiting factor when selecting cloud node resources. cores -- Maximum cores necessary for this step, for non-multicore processes. unlist -- Variables being unlisted by this process. Useful for parallelization splitting and batching from multiple variables, like variant calling. no_files -- This step does not require file access. parallel -- Parallelization approach. There are three different levels of parallelization, each with subcomponents: 1. multi -- Multiple samples, parallelizing at the sample level. Used in top-level workflow. - multi-parallel -- Run individual samples in parallel. - multi-combined -- Run all samples together. - multi-batch -- Run all samples together, converting into batches of grouped samples. 2. single -- A single sample, used in sub-workflows. - single-split -- Split a sample into sub-components (by read sections). - single-parallel -- Run sub-components of a sample in parallel. - single-merge -- Merge multiple sub-components into a single sample. - single-single -- Single sample, single item, nothing fancy. 3. batch -- Several related samples (tumor/normal, or populations). Used in sub-workflows. - batch-split -- Split a batch of samples into sub-components (by genomic region). - batch-parallel -- Run sub-components of a batch in parallel. - batch-merge -- Merge sub-components back into a single batch. - batch-single -- Run on a single batch. """ Step = collections.namedtuple("Step", "name parallel inputs outputs image programs disk cores unlist no_files") if programs is None: programs = [] if unlist is None: unlist = [] return Step(name, parallel, inputs, outputs, image, programs, disk, cores, unlist, no_files) def w(name, parallel, workflow, internal): """A workflow, allowing specification of sub-workflows for nested parallelization. name and parallel are documented under the Step (s) function. workflow -- a list of Step tuples defining the sub-workflow internal -- variables used in the sub-workflow but not exposed to subsequent steps """ Workflow = collections.namedtuple("Workflow", "name parallel workflow internal") return Workflow(name, parallel, workflow, internal) def et(name, parallel, inputs, outputs, expression): """Represent an ExpressionTool that reorders inputs using javascript. """ ExpressionTool = collections.namedtuple("ExpressionTool", "name inputs outputs expression parallel") return ExpressionTool(name, inputs, outputs, expression, parallel) def cwlout(key, valtype=None, extensions=None, fields=None, exclude=None): """Definition of an output variable, defining the type and associated secondary files. """ out = {"id": key} if valtype: out["type"] = valtype if fields: out["fields"] = fields if extensions: out["secondaryFiles"] = extensions if exclude: out["exclude"] = exclude return out def _alignment(checkpoints): process_alignment_out = [cwlout(["work_bam"], ["File", "null"], [".bai"]), cwlout(["align_bam"], ["File", "null"], [".bai"]), cwlout(["hla", "fastq"], ["null", {"type": "array", "items": "File"}]), cwlout(["work_bam_plus", "disc"], ["File", "null"], [".bai"]), cwlout(["work_bam_plus", "sr"], ["File", "null"], [".bai"])] if checkpoints["umi"]: process_alignment_out.append(cwlout(["config", "algorithm", "rawumi_avg_cov"], ["int", "null"])) process_alignment_out.append(cwlout(["umi_bam"], ["File", "null"], [".bai"])) align = [s("prep_align_inputs", "single-split" if checkpoints["align_split"] else "single-single", [["alignment_rec"]], [cwlout("process_alignment_rec", "record", fields=[cwlout(["files"], ["null", {"type": "array", "items": "File"}], [".gbi"]), cwlout(["config", "algorithm", "quality_format"], ["string", "null"]), cwlout(["align_split"], ["string", "null"])])], "bcbio-vc", ["grabix", "htslib", "biobambam", "atropos;env=python3", "optitype;env=python2", "razers3=3.5.0", "coincbc"], # HLA deps for general docker inclusion disk={"files": 1.5}), s("process_alignment", "single-parallel" if checkpoints["align_split"] else "single-single", [["alignment_rec"], ["process_alignment_rec"]], process_alignment_out, "bcbio-vc", ["bwa", "bwakit", "grabix", "minimap2", "novoalign", "snap-aligner=1.0dev.97", "sentieon;env=python2", "samtools", "pysam>=0.13.0", "sambamba", "fgbio", "umis;env=python2", "biobambam", "seqtk", "samblaster", "variantbam"], disk={"files": 2})] if checkpoints["align_split"]: inp = [["alignment_rec"], ["work_bam"], ["align_bam"], ["work_bam_plus", "disc"], ["work_bam_plus", "sr"], ["hla", "fastq"]] outp = [cwlout(["align_bam"], ["File", "null"], [".bai"]), cwlout(["work_bam_plus", "disc"], ["File", "null"], [".bai"]), cwlout(["work_bam_plus", "sr"], ["File", "null"], [".bai"]), cwlout(["hla", "fastq"], ["null", {"type": "array", "items": "File"}])] if checkpoints["umi"]: inp.append(["umi_bam"]) inp.append(["config", "algorithm", "rawumi_avg_cov"]) outp.append(cwlout(["umi_bam"], ["File", "null"], [".bai"])) outp.append(cwlout(["config", "algorithm", "rawumi_avg_cov"], ["int", "null"])) align += [s("merge_split_alignments", "single-merge", inp, outp, "bcbio-vc", ["biobambam", "samtools", "variantbam"], disk={"files": 3.5})] return align def _variant_hla(checkpoints): """Add hla analysis to workflow, if configured. """ if not checkpoints.get("hla"): return [], [] hla = [s("hla_to_rec", "multi-batch", [["hla", "fastq"], ["config", "algorithm", "hlacaller"]], [cwlout("hla_rec", "record")], "bcbio-vc", cores=1, no_files=True), s("call_hla", "multi-parallel", [["hla_rec"]], [cwlout(["hla", "hlacaller"], ["string", "null"]), cwlout(["hla", "call_file"], ["File", "null"])], "bcbio-vc", ["optitype;env=python2", "razers3=3.5.0", "coincbc"])] return hla, [["hla", "call_file"]] def _variant_vc(checkpoints): """Add variant calling to workflow, if configured. """ if not checkpoints.get("vc"): return [], [] vc_wf = [s("get_parallel_regions", "batch-split", [["batch_rec"]], [cwlout(["region_block"], {"type": "array", "items": "string"})], "bcbio-vc", disk={"files": 2.0}, cores=1), s("variantcall_batch_region", "batch-parallel", [["batch_rec"], ["region_block"]], [cwlout(["vrn_file_region"], ["File", "null"], [".tbi"]), cwlout(["region_block"], {"type": "array", "items": "string"})], "bcbio-vc", ["bcftools", "bedtools", "freebayes=1.1.0.46", "gatk4", "vqsr_cnn", "deepvariant;env=dv", "sentieon;env=python2", "htslib", "octopus", "picard", "platypus-variant;env=python2", "pythonpy", "samtools", "pysam>=0.13.0", "strelka;env=python2", "vardict", "vardict-java", "varscan", "moreutils", "vcfanno", "vcflib", "vt", "r=3.5.1", "r-base", "perl"], disk={"files": 2.0}), s("concat_batch_variantcalls", "batch-merge", [["batch_rec"], ["region_block"], ["vrn_file_region"]], [cwlout(["vrn_file"], "File", [".tbi"])], "bcbio-vc", ["bcftools", "htslib", "gatk4"], disk={"files": 1.5}, cores=1)] if not checkpoints.get("jointvc"): vc_wf += [s("postprocess_variants", "batch-single", [["batch_rec"], ["vrn_file"]], [cwlout(["vrn_file"], "File", [".tbi"])], "bcbio-vc", ["snpeff=4.3.1t"], disk={"files": 0.5})] vc_rec_exclude = [["align_bam"]] if not checkpoints.get("jointvc"): vc_rec_exclude.append(["genome_resources", "variation"]) vc_wf += [s("compare_to_rm", "batch-single", [["batch_rec"], ["vrn_file"]], [cwlout("vc_rec", "record", fields=[cwlout(["batch_samples"], ["null", {"type": "array", "items": "string"}]), cwlout(["validate", "summary"], ["File", "null"]), cwlout(["validate", "tp"], ["File", "null"], [".tbi"]), cwlout(["validate", "fp"], ["File", "null"], [".tbi"]), cwlout(["validate", "fn"], ["File", "null"], [".tbi"]), cwlout("inherit", exclude=vc_rec_exclude)])], "bcbio-vc", ["bcftools", "bedtools", "pythonpy", "gvcf-regions;env=python2", "htslib", "rtg-tools", "vcfanno"], disk={"files": 1.5})] batch_in = [["analysis"], ["genome_build"], ["align_bam"], ["vrn_file"], ["metadata", "batch"], ["metadata", "phenotype"], ["config", "algorithm", "callable_regions"], ["regions", "sample_callable"], ["config", "algorithm", "variantcaller"], ["config", "algorithm", "ensemble"], ["config", "algorithm", "vcfanno"], ["config", "algorithm", "coverage_interval"], ["config", "algorithm", "effects"], ["config", "algorithm", "min_allele_fraction"], ["config", "algorithm", "exclude_regions"], ["config", "algorithm", "variant_regions"], ["config", "algorithm", "variant_regions_merged"], ["config", "algorithm", "validate"], ["config", "algorithm", "validate_regions"], ["config", "algorithm", "tools_on"], ["config", "algorithm", "tools_off"], ["reference", "fasta", "base"], ["reference", "rtg"], ["reference", "genome_context"], ["genome_resources", "variation", "clinvar"], ["genome_resources", "variation", "cosmic"], ["genome_resources", "variation", "dbsnp"], ["genome_resources", "variation", "esp"], ["genome_resources", "variation", "exac"], ["genome_resources", "variation", "gnomad_exome"], ["genome_resources", "variation", "1000g"], ["genome_resources", "variation", "lcr"], ["genome_resources", "variation", "polyx"], ["genome_resources", "variation", "encode_blacklist"], ["genome_resources", "aliases", "ensembl"], ["genome_resources", "aliases", "human"], ["genome_resources", "aliases", "snpeff"], ["reference", "snpeff", "genome_build"]] if checkpoints.get("umi"): batch_in.append(["config", "algorithm", "umi_type"]) if checkpoints.get("rnaseq"): batch_in += [["genome_resources", "variation", "editing"]] else: batch_in += [["genome_resources", "variation", "train_hapmap"], ["genome_resources", "variation", "train_indels"]] vc = [s("batch_for_variantcall", "multi-batch", batch_in, [cwlout("batch_rec", "record", fields=[cwlout(["config", "algorithm", "variantcaller_order"], "int"), cwlout("inherit")])], "bcbio-vc", disk={"files": 2.0}, cores=1, unlist=[["config", "algorithm", "variantcaller"]], no_files=True), w("variantcall", "multi-parallel", vc_wf, [["region"], ["region_block"], ["vrn_file_region"], ["vrn_file"], ["validate", "summary"]])] if checkpoints.get("jointvc"): vc += _variant_jointvc() if checkpoints.get("ensemble"): vc += _variant_ensemble(checkpoints) summarize_in = [["jointvc_rec" if checkpoints.get("jointvc") else "vc_rec"]] if checkpoints.get("ensemble"): summarize_in += [["ensemble_rec"]] vc += [s("summarize_vc", "multi-combined", summarize_in, [cwlout(["variants", "calls"], {"type": "array", "items": ["File", "null"]}), cwlout(["variants", "gvcf"], ["null", {"type": "array", "items": ["File", "null"]}]), cwlout(["variants", "samples"], {"type": "array", "items": {"type": "array", "items": ["File", "null"]}}), cwlout(["validate", "grading_summary"], ["File", "null"]), cwlout(["validate", "grading_plots"], {"type": "array", "items": ["File", "null"]})], "bcbio-vc", disk={"files": 2.0}, cores=1)] return vc, [["validate", "grading_summary"], ["variants", "calls"], ["variants", "gvcf"]] def _variant_ensemble(checkpoints): out = [s("batch_for_ensemble", "multi-combined", [["jointvc_rec" if checkpoints.get("jointvc") else "vc_rec"]], [cwlout("ensemble_prep_rec", "record", fields=[cwlout(["batch_id"], "string"), cwlout(["variants", "calls"], {"type": "array", "items": "File"}), cwlout(["variants", "variantcallers"], {"type": "array", "items": "string"}), cwlout("inherit")])], "bcbio-vc", cores=1, no_files=True), s("combine_calls", "multi-parallel", ["ensemble_prep_rec"], [cwlout("ensemble_rec", "record", fields=[cwlout(["ensemble", "vrn_file"], ["File", "null"]), cwlout(["ensemble", "validate", "summary"], ["File", "null"]), cwlout(["ensemble", "batch_samples"], {"type": "array", "items": "string"}), cwlout(["ensemble", "batch_id"], "string")])], "bcbio-vc", ["bcbio-variation-recall"])] return out def _variant_jointvc(): wf = [s("get_parallel_regions_jointvc", "batch-split", [["jointvc_batch_rec"]], [cwlout(["region"], "string")], "bcbio-vc", disk={"files": 1.5}, cores=1), s("run_jointvc", "batch-parallel", [["jointvc_batch_rec"], ["region"]], [cwlout(["vrn_file_region"], ["File", "null"], [".tbi"]), cwlout(["region"], "string")], "bcbio-vc", ["gatk4", "gvcfgenotyper", "sentieon;env=python2"], disk={"files": 1.5}, cores=1), s("concat_batch_variantcalls_jointvc", "batch-merge", [["jointvc_batch_rec"], ["region"], ["vrn_file_region"]], [cwlout(["vrn_file_joint"], "File", [".tbi"])], "bcbio-vc", ["bcftools", "htslib", "gatk4"], disk={"files": 1.5}, cores=1), s("postprocess_variants", "batch-single", [["jointvc_batch_rec"], ["vrn_file_joint"]], [cwlout(["vrn_file_joint"], "File", [".tbi"])], "bcbio-vc", ["snpeff=4.3.1t"], disk={"files": 1.5}), s("finalize_jointvc", "batch-single", [["jointvc_batch_rec"], ["vrn_file_joint"]], [cwlout("jointvc_rec", "record")], "bcbio-vc", disk={"files": 1.5}, cores=1)] out = [s("batch_for_jointvc", "multi-batch", ["vc_rec"], [cwlout("jointvc_batch_rec", "record")], "bcbio-vc", disk={"files": 1.5}, cores=1, no_files=True), w("jointcall", "multi-parallel", wf, [["region"], ["vrn_file_region"], ["vrn_file"]])] return out def _variant_checkpoints(samples): """Check sample configuration to identify required steps in analysis. """ checkpoints = {} checkpoints["vc"] = any([dd.get_variantcaller(d) or d.get("vrn_file") for d in samples]) checkpoints["sv"] = any([dd.get_svcaller(d) for d in samples]) checkpoints["jointvc"] = any([(dd.get_jointcaller(d) or "gvcf" in dd.get_tools_on(d)) for d in samples]) checkpoints["hla"] = any([dd.get_hlacaller(d) for d in samples]) checkpoints["align"] = any([(dd.get_aligner(d) or dd.get_bam_clean(d)) for d in samples]) checkpoints["align_split"] = not all([(dd.get_align_split_size(d) is False or not dd.get_aligner(d)) for d in samples]) checkpoints["archive"] = any([dd.get_archive(d) for d in samples]) checkpoints["umi"] = any([dd.get_umi_consensus(d) for d in samples]) checkpoints["ensemble"] = any([dd.get_ensemble(d) for d in samples]) checkpoints["cancer"] = any(dd.get_phenotype(d) in ["tumor"] for d in samples) return checkpoints def _postprocess_alignment(checkpoints): wf = [s("prep_samples_to_rec", "multi-combined", [["config", "algorithm", "coverage"], ["rgnames", "sample"], ["config", "algorithm", "background", "cnv_reference"], ["config", "algorithm", "svcaller"], ["config", "algorithm", "sv_regions"], ["config", "algorithm", "variant_regions"], ["reference", "fasta", "base"]], [cwlout("prep_samples_rec", "record")], "bcbio-vc", disk={"files": 0.5}, cores=1, no_files=True), s("prep_samples", "multi-parallel", ["prep_samples_rec"], [cwlout(["rgnames", "sample"], "string"), cwlout(["config", "algorithm", "variant_regions"], ["File", "null"]), cwlout(["config", "algorithm", "variant_regions_merged"], ["File", "null"]), cwlout(["config", "algorithm", "variant_regions_orig"], ["File", "null"]), cwlout(["config", "algorithm", "coverage"], ["File", "null"]), cwlout(["config", "algorithm", "coverage_merged"], ["File", "null"]), cwlout(["config", "algorithm", "coverage_orig"], ["File", "null"]), cwlout(["config", "algorithm", "seq2c_bed_ready"], ["File", "null"])], "bcbio-vc", ["htslib", "bedtools", "pythonpy"], disk={"files": 0.5}, cores=1), s("postprocess_alignment_to_rec", "multi-combined", [["align_bam"], ["config", "algorithm", "archive"], ["config", "algorithm", "coverage_interval"], ["config", "algorithm", "exclude_regions"], ["config", "algorithm", "variant_regions"], ["config", "algorithm", "variant_regions_merged"], ["config", "algorithm", "variant_regions_orig"], ["config", "algorithm", "coverage"], ["config", "algorithm", "coverage_merged"], ["config", "algorithm", "coverage_orig"], ["config", "algorithm", "seq2c_bed_ready"], ["config", "algorithm", "recalibrate"], ["config", "algorithm", "tools_on"], ["genome_resources", "rnaseq", "gene_bed"], ["genome_resources", "variation", "dbsnp"], ["genome_resources", "variation", "lcr"], ["genome_resources", "variation", "polyx"], ["genome_resources", "variation", "encode_blacklist"], ["reference", "fasta", "base"]], [cwlout("postprocess_alignment_rec", "record")], "bcbio-vc", disk={"files": 1.5}, cores=1, no_files=True), s("postprocess_alignment", "multi-parallel", [["postprocess_alignment_rec"]], [cwlout(["config", "algorithm", "coverage_interval"], ["string", "null"]), cwlout(["config", "algorithm", "variant_regions"], ["File", "null"]), cwlout(["config", "algorithm", "variant_regions_merged"], ["File", "null"]), cwlout(["config", "algorithm", "variant_regions_orig"], ["File", "null"]), cwlout(["config", "algorithm", "coverage"], ["File", "null"]), cwlout(["config", "algorithm", "coverage_merged"], ["File", "null"]), cwlout(["config", "algorithm", "coverage_orig"], ["File", "null"]), cwlout(["config", "algorithm", "seq2c_bed_ready"], ["File", "null"]), cwlout(["regions", "callable"], ["File", "null"]), cwlout(["regions", "sample_callable"], ["File", "null"]), cwlout(["regions", "nblock"], ["File", "null"]), cwlout(["depth", "samtools", "stats"], ["File", "null"]), cwlout(["depth", "samtools", "idxstats"], ["File", "null"]), cwlout(["depth", "variant_regions", "regions"], ["File", "null"]), cwlout(["depth", "variant_regions", "dist"], ["File", "null"]), cwlout(["depth", "sv_regions", "regions"], ["File", "null"]), cwlout(["depth", "sv_regions", "dist"], ["File", "null"]), cwlout(["depth", "coverage", "regions"], ["File", "null"]), cwlout(["depth", "coverage", "dist"], ["File", "null"]), cwlout(["depth", "coverage", "thresholds"], ["File", "null"]), cwlout(["align_bam"], ["File", "null"])], "bcbio-vc", ["sambamba", "goleft", "bedtools", "htslib", "gatk4", "mosdepth", "sentieon;env=python2"], disk={"files": 3.0}), s("combine_sample_regions", "multi-combined", [["regions", "callable"], ["regions", "nblock"], ["metadata", "batch"], ["config", "algorithm", "nomap_split_size"], ["config", "algorithm", "nomap_split_targets"], ["reference", "fasta", "base"]], [cwlout(["config", "algorithm", "callable_regions"], "File"), cwlout(["config", "algorithm", "non_callable_regions"], "File"), cwlout(["config", "algorithm", "callable_count"], "int")], "bcbio-vc", ["bedtools", "htslib", "gatk4"], disk={"files": 0.5}, cores=1)] out = [["regions", "sample_callable"]] if checkpoints.get("archive"): wf += [s("archive_to_cram", "multi-parallel", [["postprocess_alignment_rec"]], [cwlout(["archive_bam"], ["File", "null"], [".crai"])], "bcbio-vc", ["samtools"], disk={"files": 3.0})] out += [["archive_bam"]] return wf, out def variant(samples): """Variant calling workflow definition for CWL generation. """ checkpoints = _variant_checkpoints(samples) if checkpoints["align"]: align_wf = _alignment(checkpoints) alignin = [["files"], ["analysis"], ["config", "algorithm", "align_split_size"], ["reference", "fasta", "base"], ["rgnames", "pl"], ["rgnames", "sample"], ["rgnames", "pu"], ["rgnames", "lane"], ["rgnames", "rg"], ["rgnames", "lb"], ["reference", "aligner", "indexes"], ["config", "algorithm", "aligner"], ["config", "algorithm", "trim_reads"], ["config", "algorithm", "adapters"], ["config", "algorithm", "bam_clean"], ["config", "algorithm", "variant_regions"], ["config", "algorithm", "mark_duplicates"]] if checkpoints["hla"]: alignin.append(["config", "algorithm", "hlacaller"]) if checkpoints["umi"]: alignin.append(["config", "algorithm", "umi_type"]) align = [s("alignment_to_rec", "multi-combined", alignin, [cwlout("alignment_rec", "record")], "bcbio-vc", disk={"files": 1.5}, cores=1, no_files=True), w("alignment", "multi-parallel", align_wf, [["align_split"], ["process_alignment_rec"], ["work_bam"], ["config", "algorithm", "quality_format"]])] else: align = [s("organize_noalign", "multi-parallel", ["files"], [cwlout(["align_bam"], ["File", "null"], [".bai"]), cwlout(["work_bam_plus", "disc"], ["File", "null"]), cwlout(["work_bam_plus", "sr"], ["File", "null"]), cwlout(["hla", "fastq"], ["File", "null"])], "bcbio-vc", cores=1)] align_out = [["rgnames", "sample"], ["align_bam"]] pp_align, pp_align_out = _postprocess_alignment(checkpoints) if checkpoints["umi"]: align_out += [["umi_bam"]] vc, vc_out = _variant_vc(checkpoints) sv, sv_out = _variant_sv(checkpoints) hla, hla_out = _variant_hla(checkpoints) qc, qc_out = _qc_workflow(checkpoints) steps = align + pp_align + hla + vc + sv + qc final_outputs = align_out + pp_align_out + vc_out + hla_out + sv_out + qc_out return steps, final_outputs def _qc_workflow(checkpoints): qc_inputs = \ [["align_bam"], ["analysis"], ["reference", "fasta", "base"], ["reference", "versions"], ["config", "algorithm", "tools_on"], ["config", "algorithm", "tools_off"], ["genome_build"], ["config", "algorithm", "qc"], ["metadata", "batch"], ["metadata", "phenotype"], ["config", "algorithm", "coverage_interval"], ["depth", "variant_regions", "regions"], ["depth", "variant_regions", "dist"], ["depth", "samtools", "stats"], ["depth", "samtools", "idxstats"], ["depth", "sv_regions", "regions"], ["depth", "sv_regions", "dist"], ["depth", "coverage", "regions"], ["depth", "coverage", "dist"], ["depth", "coverage", "thresholds"], ["config", "algorithm", "variant_regions"], ["config", "algorithm", "variant_regions_merged"], ["config", "algorithm", "coverage"], ["config", "algorithm", "coverage_merged"]] if checkpoints.get("vc"): qc_inputs += [["variants", "samples"]] if checkpoints.get("umi"): qc_inputs += [["config", "algorithm", "umi_type"], ["config", "algorithm", "rawumi_avg_cov"], ["umi_bam"]] if checkpoints.get("cancer"): qc_inputs += [["reference", "viral"]] qc = [s("qc_to_rec", "multi-combined", qc_inputs, [cwlout("qc_rec", "record")], "bcbio-vc", disk={"files": 1.5}, cores=1, no_files=True), s("pipeline_summary", "multi-parallel", ["qc_rec"], [cwlout("qcout_rec", "record", fields=[cwlout(["summary", "qc"], ["File", "null"]), cwlout(["summary", "metrics"], ["string", "null"]), cwlout(["genome_build"]), cwlout(["description"]), cwlout(["reference", "versions"]), cwlout(["config", "algorithm", "tools_off"]), cwlout(["config", "algorithm", "tools_on"]), cwlout(["config", "algorithm", "qc"])])], "bcbio-vc", ["bcftools", "bedtools", "fastqc=0.11.7=5", "goleft", "hts-nim-tools", "mosdepth", "picard", "pythonpy", "qsignature", "qualimap", "sambamba", "samtools", "preseq", "peddy;env=python2", "verifybamid2"], disk={"files": 2.0}), s("multiqc_summary", "multi-combined", [["qcout_rec"]], [cwlout(["summary", "multiqc"], ["File", "null"]), cwlout(["versions", "tools"], ["File", "null"]), cwlout(["versions", "data"], ["File", "null"])], "bcbio-vc", ["multiqc", "multiqc-bcbio"], disk={"files": 2.0}, cores=1)] qc_out = [cwlout(["summary", "multiqc"], {"type": "array", "items": ["File", "null"]}), ["versions", "tools"], ["versions", "data"]] return qc, qc_out def _variant_sv(checkpoints): """Structural variant workflow. """ if not checkpoints.get("sv"): return [], [] sv = [s("detect_sv", "batch-single", [["sv_batch_rec"]], [cwlout("sv_rec", "record", fields=[cwlout(["sv", "variantcaller"], ["string", "null"]), cwlout(["sv", "vrn_file"], ["File", "null"], [".tbi"]), cwlout(["sv", "supplemental"], {"type": "array", "items": ["File"]}), cwlout(["svvalidate", "summary"], ["File", "null"]), cwlout("inherit", exclude=[["align_bam"], ["work_bam_plus"], ["reference", "snpeff"]])])], "bcbio-vc", ["bedtools", "cnvkit", "delly", "duphold", "extract-sv-reads", "gsort", "lumpy-sv;env=python2", "manta;env=python2", "break-point-inspector", "mosdepth", "samtools", "smoove;env=python2", "pysam>=0.13.0", "seq2c", "simple_sv_annotation;env=python2", "survivor", "svtools;env=python2", "svtyper;env=python2", "r=3.5.1", "r-base", "xorg-libxt", "vawk;env=python2"], disk={"files": 2.0})] sv_batch_inputs = [["analysis"], ["genome_build"], ["work_bam_plus", "disc"], ["work_bam_plus", "sr"], ["config", "algorithm", "background", "cnv_reference"], ["config", "algorithm", "tools_on"], ["config", "algorithm", "tools_off"], ["config", "algorithm", "svprioritize"], ["config", "algorithm", "svvalidate"], ["regions", "sample_callable"], ["genome_resources", "variation", "gc_profile"], ["genome_resources", "variation", "germline_het_pon"], ["genome_resources", "aliases", "snpeff"], ["reference", "snpeff", "genome_build"], ["sv_coverage_rec"]] if checkpoints.get("vc"): sv_batch_inputs.append(["variants", "samples"]) steps = [s("calculate_sv_bins", "multi-combined", [["align_bam"], ["reference", "fasta", "base"], ["metadata", "batch"], ["metadata", "phenotype"], ["config", "algorithm", "background", "cnv_reference"], ["config", "algorithm", "callable_regions"], ["config", "algorithm", "coverage_interval"], ["config", "algorithm", "exclude_regions"], ["config", "algorithm", "sv_regions"], ["config", "algorithm", "variant_regions"], ["config", "algorithm", "variant_regions_merged"], ["config", "algorithm", "seq2c_bed_ready"], ["config", "algorithm", "svcaller"], ["depth", "variant_regions", "regions"], ["genome_resources", "variation", "lcr"], ["genome_resources", "variation", "polyx"], ["genome_resources", "variation", "encode_blacklist"], ["genome_resources", "rnaseq", "gene_bed"]], [cwlout("sv_bin_rec", "record", fields=[cwlout(["regions", "bins", "target"], ["File", "null"]), cwlout(["regions", "bins", "antitarget"], ["File", "null"]), cwlout(["regions", "bins", "gcannotated"], ["File", "null"]), cwlout(["regions", "bins", "group"], ["string", "null"]), cwlout("inherit")])], "bcbio-vc", ["bedtools", "cnvkit"], disk={"files": 1.5}, cores=1), s("calculate_sv_coverage", "multi-parallel", [["sv_bin_rec"]], [cwlout("sv_rawcoverage_rec", "record", fields=[cwlout(["depth", "bins", "target"], ["File", "null"]), cwlout(["depth", "bins", "antitarget"], ["File", "null"]), cwlout(["depth", "bins", "seq2c"], ["File", "null"]), cwlout("inherit")])], "bcbio-vc", ["mosdepth", "cnvkit", "seq2c"], disk={"files": 1.5}), s("normalize_sv_coverage", "multi-combined", [["sv_rawcoverage_rec"]], [cwlout("sv_coverage_rec", "record", fields=[cwlout(["depth", "bins", "normalized"], ["File", "null"]), cwlout(["depth", "bins", "background"], ["File", "null"]), cwlout("inherit")])], "bcbio-vc", ["cnvkit"], disk={"files": 1.5}), s("batch_for_sv", "multi-batch", sv_batch_inputs, [cwlout("sv_batch_rec", "record")], "bcbio-vc", unlist=[["config", "algorithm", "svcaller"]]), w("svcall", "multi-parallel", sv, []), s("summarize_sv", "multi-combined", [["sv_rec"]], [cwlout(["sv", "calls"], {"type": "array", "items": ["File", "null"]}), cwlout(["sv", "supplemental"], {"type": "array", "items": ["File"]}), cwlout(["sv", "prioritize", "tsv"], {"type": "array", "items": ["File", "null"]}), cwlout(["sv", "prioritize", "raw"], {"type": "array", "items": ["File", "null"]}), cwlout(["svvalidate", "grading_summary"], ["File", "null"]), cwlout(["svvalidate", "grading_plots"], {"type": "array", "items": ["File", "null"]})], "bcbio-vc", ["bcbio-prioritize"], disk={"files": 1.0}, cores=1)] final_outputs = [["sv", "calls"], ["svvalidate", "grading_summary"], ["sv", "prioritize", "tsv"], ["sv", "prioritize", "raw"], ["sv", "supplemental"]] return steps, final_outputs def rnaseq(samples): checkpoints = _rnaseq_checkpoints(samples) prep = [s("prepare_sample", "multi-parallel", [["files"], dd.get_keys("sample_name"), dd.get_keys("ref_file"), dd.get_keys("genome_build"), dd.get_keys("gtf_file"), ["analysis"], ["rgnames", "pl"], ["rgnames", "pu"], ["rgnames", "lane"], ["rgnames", "rg"], ["rgnames", "lb"], ["reference", "aligner", "indexes"], ["config", "algorithm", "aligner"], ["config", "algorithm", "expression_caller"], ["config", "algorithm", "fusion_caller"], ["config", "algorithm", "quality_format"]], [cwlout("prep_rec", "record")], "bcbio-rnaseq", programs=["picard", "samtools", "pysam>=0.13.0"]), s("trim_sample", "multi-parallel", [["prep_rec"]], [cwlout("trim_rec", "record")], "bcbio-rnaseq", programs=["atropos;env=python3"])] align = [s("process_alignment", "multi-parallel", [["trim_rec"]], [cwlout(["align_bam"], "File", [".bai"])], "bcbio-rnaseq", ["star", "hisat2", "tophat;env=python2", "samtools", "sambamba", "seqtk"], {"files": 1.5})] if checkpoints.get("vc"): pp_align, pp_align_out = _postprocess_alignment(checkpoints) else: pp_align, pp_align_out = [], [] quantitate = [s("rnaseq_quantitate", "multi-parallel", [["trim_rec"], ["align_bam"]], [cwlout(dd.get_keys("count_file"), "File"), cwlout(["quant", "tsv"], "File"), cwlout(["quant", "hdf5"], "File"), cwlout(["quant", "fusion"], "File")], "bcbio-rnaseq", programs=["sailfish", "salmon", "kallisto>=0.43.1", "subread", "gffread", "r=3.5.1", "r-base", "xorg-libxt", "r-wasabi"], disk={"files": 0.5})] qc = [s("qc_to_rec", "multi-combined", [["align_bam"], ["analysis"], ["reference", "fasta", "base"], dd.get_keys("gtf_file"), ["genome_build"], ["config", "algorithm", "coverage_interval"], ["config", "algorithm", "tools_on"], ["config", "algorithm", "tools_off"], ["config", "algorithm", "qc"]], [cwlout("qc_rec", "record")], "bcbio-rnaseq", disk={"files": 1.5}, cores=1, no_files=True), s("pipeline_summary", "multi-parallel", [["qc_rec"]], [cwlout("qcout_rec", "record", fields=[cwlout(["summary", "qc"], ["File", "null"]), cwlout(["summary", "metrics"], ["string", "null"]), cwlout("inherit")])], "bcbio-rnaseq", ["bedtools", "fastqc=0.11.7=5", "goleft", "hts-nim-tools", "mosdepth", "picard", "pythonpy", "qsignature", "qualimap", "sambamba", "samtools"]), s("multiqc_summary", "multi-combined", [["qcout_rec"]], [cwlout(["summary", "multiqc"], ["File", "null"])], "bcbio-rnaseq", ["multiqc", "multiqc-bcbio"])] vc, vc_out = _variant_vc(checkpoints) fusion = [s("detect_fusions", "multi-parallel", [["quant", "fusion"], ["quant", "hdf5"], ["trim_rec"]], [cwlout(["fusion", "fasta"], "File"), cwlout(["fusion", "json"], "File")], "bcbio-rnaseq", ["pizzly"])] steps = prep + align + pp_align + quantitate + qc + vc + fusion final_outputs = [["rgnames", "sample"], dd.get_keys("align_bam"), ["quant", "tsv"], ["summary", "multiqc"]] + \ vc_out + pp_align_out return steps, final_outputs def _rnaseq_checkpoints(samples): """Check sample configuration to identify required steps in analysis. """ checkpoints = {} checkpoints["rnaseq"] = True checkpoints["vc"] = any([dd.get_variantcaller(d) for d in samples]) return checkpoints workflows = \ {"variant": variant, "variant2": variant, "rna-seq": rnaseq} bcbio-nextgen-1.2.9/bcbio/cwl/hpc.py000066400000000000000000000417431415626112400172510ustar00rootroot00000000000000"""Setup configurations for running on HPC clusters with CWL. Contains support for setting up configuration inputs for Cromwell. """ import json import os def create_cromwell_config(args, work_dir, sample_file): """Prepare a cromwell configuration within the current working directory. """ docker_attrs = ["String? docker", "String? docker_user"] cwl_attrs = ["Int? cpuMin", "Int? cpuMax", "Int? memoryMin", "Int? memoryMax", "String? outDirMin", "String? outDirMax", "String? tmpDirMin", "String? tmpDirMax"] out_file = os.path.join(work_dir, "bcbio-cromwell.conf") run_config = _load_custom_config(args.runconfig) if args.runconfig else {} # Avoid overscheduling jobs for local runs by limiting concurrent jobs # Longer term would like to keep these within defined core window joblimit = args.joblimit if joblimit == 0 and not args.scheduler: joblimit = 1 file_types = _get_filesystem_types(args, sample_file) std_args = {"docker_attrs": "" if args.no_container else "\n ".join(docker_attrs), "submit_docker": 'submit-docker: ""' if args.no_container else "", "joblimit": "concurrent-job-limit = %s" % (joblimit) if joblimit > 0 else "", "cwl_attrs": "\n ".join(cwl_attrs), "filesystem": _get_filesystem_config(file_types), "database": run_config.get("database", DATABASE_CONFIG % {"work_dir": work_dir})} cl_args, conf_args, scheduler, cloud_type = _args_to_cromwell(args) std_args["engine"] = _get_engine_filesystem_config(file_types, args, conf_args) conf_args.update(std_args) main_config = {"hpc": (HPC_CONFIGS[scheduler] % conf_args) if scheduler else "", "cloud": (CLOUD_CONFIGS[cloud_type] % conf_args) if cloud_type else "", "work_dir": work_dir} main_config.update(std_args) # Local run always seems to need docker set because of submit-docker in default configuration # Can we unset submit-docker based on configuration so it doesn't inherit? # main_config["docker_attrs"] = "\n ".join(docker_attrs) with open(out_file, "w") as out_handle: out_handle.write(CROMWELL_CONFIG % main_config) return out_file def _get_file_paths(cur): """Retrieve a list of file paths, recursively traversing the """ out = [] if isinstance(cur, (list, tuple)): for x in cur: new = _get_file_paths(x) if new: out.extend(new) elif isinstance(cur, dict): if "class" in cur: out.append(cur["path"]) else: for k, v in cur.items(): new = _get_file_paths(v) if new: out.extend(new) return out def _load_custom_config(run_config): """Load custom configuration input HOCON file for cromwell. """ from pyhocon import ConfigFactory, HOCONConverter, ConfigTree conf = ConfigFactory.parse_file(run_config) out = {} if "database" in conf: out["database"] = HOCONConverter.to_hocon(ConfigTree({"database": conf.get_config("database")})) return out def args_to_cromwell_cl(args): """Convert input bcbio arguments into cromwell command line arguments. """ cl_args, conf_args, scheduler, cloud = _args_to_cromwell(args) return cl_args def _args_to_cromwell(args): """Convert input arguments into cromwell inputs for config and command line. """ default_config = {"slurm": {"timelimit": "1-00:00", "account": ""}, "sge": {"memtype": "mem_free", "pename": "smp"}, "lsf": {"walltime": "24:00", "account": ""}, "htcondor": {}, "torque": {"walltime": "24:00:00", "account": ""}, "pbspro": {"walltime": "24:00:00", "account": "", "cpu_and_mem": "-l select=1:ncpus=${cpu}:mem=${memory_mb}mb"}} prefixes = {("account", "slurm"): "-A ", ("account", "pbspro"): "-A "} custom = {("noselect", "pbspro"): ("cpu_and_mem", "-l ncpus=${cpu} -l mem=${memory_mb}mb")} cl = [] config = {} # HPC scheduling if args.scheduler: if args.scheduler not in default_config: raise ValueError("Scheduler not yet supported by Cromwell: %s" % args.scheduler) if not args.queue and args.scheduler not in ["htcondor"]: raise ValueError("Need to set queue (-q) for running with an HPC scheduler") config = default_config[args.scheduler] cl.append("-Dbackend.default=%s" % args.scheduler.upper()) config["queue"] = args.queue for rs in args.resources: for r in rs.split(";"): parts = r.split("=") if len(parts) == 2: key, val = parts config[key] = prefixes.get((key, args.scheduler), "") + val elif len(parts) == 1 and (parts[0], args.scheduler) in custom: key, val = custom[(parts[0], args.scheduler)] config[key] = val cloud_type = None if args.cloud_project: if args.cloud_root and args.cloud_root.startswith("gs:"): cloud_type = "PAPI" cloud_root = args.cloud_root cloud_region = None elif ((args.cloud_root and args.cloud_root.startswith("s3:")) or (args.cloud_project and args.cloud_project.startswith("arn:"))): cloud_type = "AWSBATCH" cloud_root = args.cloud_root if not cloud_root.startswith("s3://"): cloud_root = "s3://%s" % cloud_root # split region from input Amazon Resource Name, ie arn:aws:batch:us-east-1: cloud_region = args.cloud_project.split(":")[3] else: raise ValueError("Unexpected inputs for Cromwell Cloud support: %s %s" % (args.cloud_project, args.cloud_root)) config = {"cloud_project": args.cloud_project, "cloud_root": cloud_root, "cloud_region": cloud_region} cl.append("-Dbackend.default=%s" % cloud_type) return cl, config, args.scheduler, cloud_type def _get_filesystem_types(args, sample_file): """Retrieve the types of inputs and staging based on sample JSON and arguments. """ out = set([]) ext = "" if args.no_container else "_container" with open(sample_file) as in_handle: for f in _get_file_paths(json.load(in_handle)): if f.startswith("gs:"): out.add("gcp%s" % ext) elif f.startswith("s3:"): out.add("s3%s" % ext) elif f.startswith(("https:", "http:")): out.add("http%s" % ext) else: out.add("local%s" % ext) return out def _get_filesystem_config(file_types): """Retrieve filesystem configuration, including support for specified file types. """ out = " filesystems {\n" for file_type in sorted(list(file_types)): if file_type in _FILESYSTEM_CONFIG: out += _FILESYSTEM_CONFIG[file_type] out += " }\n" return out _FILESYSTEM_CONFIG = { "gcp": """ gcs { auth = "gcp-auth" caching { duplication-strategy = "reference" } } """, "gcp_container": """ gcs { auth = "gcp-auth" caching { duplication-strategy = "copy" } } """, "http": """ http { } """, "http_container": """ http { } """, "local": """ local { localization: ["soft-link"] caching { duplication-strategy: ["soft-link"] hashing-strategy: "path" } } """, "local_container": """ local { localization: ["hard-link", "copy"] caching { duplication-strategy: ["hard-link", "copy"] hashing-strategy: "file" } } """ } DATABASE_CONFIG = """ database { profile = "slick.jdbc.HsqldbProfile$" db { driver = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:file:%(work_dir)s/persist/metadata;shutdown=false;hsqldb.tx=mvcc" connectionTimeout = 200000 } } """ def _get_engine_filesystem_config(file_types, args, conf_args): """Retriever authorization and engine filesystem configuration. """ file_types = [x.replace("_container", "") for x in list(file_types)] out = "" if "gcp" in file_types: out += _AUTH_CONFIG_GOOGLE if "s3" in file_types: out += _AUTH_CONFIG_AWS % conf_args["cloud_region"] if "gcp" in file_types or "http" in file_types or "s3" in file_types: out += "engine {\n" out += " filesystems {\n" if "gcp" in file_types: out += ' gcs {\n' out += ' auth = "gcp-auth"\n' if args.cloud_project: out += ' project = "%s"\n' % args.cloud_project out += ' }\n' if "http" in file_types: out += ' http {}\n' if "s3" in file_types: out += ' s3 { auth = "default" }' out += " }\n" out += "}\n" return out _AUTH_CONFIG_AWS = """ aws { application-name = "cromwell" auths = [{ name = "default" scheme = "default" }] region = "%s" } """ _AUTH_CONFIG_GOOGLE = """ google { application-name = "cromwell" auths = [ { name = "gcp-auth" scheme = "service_account" json-file = ${?GOOGLE_APPLICATION_CREDENTIALS} } ] } """ CROMWELL_CONFIG = """ include required(classpath("application")) system { workflow-restart = true } call-caching { enabled = true } load-control { # Avoid watching memory, since the load-controller stops jobs on local runs memory-threshold-in-mb = 1 } cwltool-runner { # Use external cwltool to avoid slow runtimes with java embedded pre-processing class = "cwl.CwltoolProcess" } %(database)s %(engine)s backend { providers { Local { config { %(joblimit)s runtime-attributes = \"\"\" Int? cpu Int? memory_mb %(docker_attrs)s %(cwl_attrs)s \"\"\" %(submit_docker)s %(filesystem)s } } %(hpc)s %(cloud)s } } """ HPC_CONFIGS = { "slurm": """ SLURM { actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory" config { %(joblimit)s runtime-attributes = \"\"\" Int cpu = 1 Int memory_mb = 2048 String queue = "%(queue)s" String timelimit = "%(timelimit)s" String account = "%(account)s" %(docker_attrs)s %(cwl_attrs)s \"\"\" submit = \"\"\" sbatch -J ${job_name} -D ${cwd} -o ${out} -e ${err} -t ${timelimit} -p ${queue} \ ${"--cpus-per-task=" + cpu} --mem=${memory_mb} ${account} \ --wrap "/usr/bin/env bash ${script}" \"\"\" kill = "scancel ${job_id}" check-alive = "squeue -j ${job_id}" job-id-regex = "Submitted batch job (\\\\d+).*" %(filesystem)s } } """, "sge": """ SGE { actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory" config { %(joblimit)s runtime-attributes = \"\"\" Int cpu = 1 Int memory_mb = 2048 String queue = "%(queue)s" String pename = "%(pename)s" String memtype = "%(memtype)s" %(docker_attrs)s %(cwl_attrs)s \"\"\" submit = \"\"\" qsub -V -w w -j y -N ${job_name} -wd ${cwd} \ -o ${out} -e ${err} -q ${queue} \ -pe ${pename} ${cpu} -l ${memtype}=${memory_mb}m \ ${script} \"\"\" kill = "qdel ${job_id}" check-alive = "qstat -j ${job_id}" job-id-regex = "(\\\\d+)" %(filesystem)s } } """, "lsf": """ LSF { actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory" config { %(joblimit)s runtime-attributes = \"\"\" Int cpu = 1 Int memory_gb = 2 String queue = "%(queue)s" String account = "%(account)s" String walltime = "%(walltime)s" %(docker_attrs)s %(cwl_attrs)s \"\"\" submit = \"\"\" bsub -J ${job_name} -cwd ${cwd} -o ${out} -e ${err} -q ${queue} -W ${walltime} \ -R rusage[mem=${memory_gb}] -n ${cpu} \ /usr/bin/env bash ${script} \"\"\" kill = "bkill ${job_id}" check-alive = "bjobs ${job_id}" job-id-regex = "Job <(\\\\d+)>.*" %(filesystem)s } } """, "pbspro": """ PBSPRO { actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory" config { %(joblimit)s runtime-attributes = \"\"\" Int cpu = 1 Int memory_mb = 2048 String queue = "%(queue)s" String account = "%(account)s" String walltime = "%(walltime)s" %(docker_attrs)s %(cwl_attrs)s \"\"\" submit = \"\"\" qsub -V -l wd -N ${job_name} -o ${out} -e ${err} -q ${queue} -l walltime=${walltime} \ %(cpu_and_mem)s \ -- /usr/bin/env bash ${script} \"\"\" kill = "qdel ${job_id}" check-alive = "qstat -j ${job_id}" job-id-regex = "(\\\\d+).*" %(filesystem)s } } """, "torque": """ TORQUE { actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory" config { %(joblimit)s runtime-attributes = \"\"\" Int cpu = 1 Int memory_mb = 2048 String queue = "%(queue)s" String account = "%(account)s" String walltime = "%(walltime)s" %(docker_attrs)s %(cwl_attrs)s \"\"\" submit = \"\"\" cd ${cwd} && \ qsub -V -N ${job_name} -o ${out} -e ${err} -q ${queue} \ -l nodes=1:ppn=${cpu} -l mem=${memory_mb}mb -l walltime=${walltime} \ ${script} \"\"\" kill = "qdel ${job_id}" check-alive = "qstat ${job_id}" job-id-regex = "(\\\\d+).*" %(filesystem)s } } """, "htcondor": """ HTCONDOR { actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory" config { %(joblimit)s runtime-attributes = \"\"\" Int cpu = 1 Float memory_mb = 512.0 Float disk_kb = 256000.0 String? nativeSpecs %(docker_attrs)s %(cwl_attrs)s \"\"\" submit = \"\"\" chmod 755 ${script} cat > ${cwd}/execution/submitFile < ${cwd}/execution/dockerScript < ${cwd}/execution/submitFile <= 0] assert len(main_cwl) == 1, "Did not find main CWL in %s" % directory main_json = glob.glob(os.path.join(directory, "main-*-samples.json")) assert len(main_json) == 1, "Did not find main json in %s" % directory project_name = os.path.basename(directory).split("-workflow")[0] return main_cwl[0], main_json[0], project_name def _run_tool(cmd, use_container=True, work_dir=None, log_file=None): """Run with injection of bcbio path. Place at end for runs without containers to avoid overriding other bcbio installations. """ if isinstance(cmd, (list, tuple)): cmd = " ".join([str(x) for x in cmd]) cmd = utils.local_path_export(at_start=use_container) + cmd if log_file: cmd += " 2>&1 | tee -a %s" % log_file try: print("Running: %s" % cmd) subprocess.check_call(cmd, shell=True) finally: if use_container and work_dir: _chown_workdir(work_dir) def _pack_cwl(unpacked_cwl): """Pack CWL into a single document for submission. """ out_file = "%s-pack%s" % os.path.splitext(unpacked_cwl) cmd = "cwltool --pack {unpacked_cwl} > {out_file}" _run_tool(cmd.format(**locals())) return out_file def _chown_workdir(work_dir): """Ensure work directory files owned by original user. Docker runs can leave root owned files making cleanup difficult. Skips this if it fails, avoiding errors where we run remotely and don't have docker locally. """ cmd = ("""docker run --rm -v %s:%s quay.io/bcbio/bcbio-base /bin/bash -c 'chown -R %s %s'""" % (work_dir, work_dir, os.getuid(), work_dir)) try: subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError: pass def _remove_bcbiovm_path(): """Avoid referencing minimal bcbio_nextgen in bcbio_vm installation. """ cur_path = os.path.dirname(os.path.realpath(sys.executable)) paths = os.environ["PATH"].split(":") if cur_path in paths: paths.remove(cur_path) os.environ["PATH"] = ":".join(paths) def _run_cwltool(args): """Run with cwltool -- reference implementation. """ main_file, json_file, project_name = _get_main_and_json(args.directory) work_dir = utils.safe_makedir(os.path.join(os.getcwd(), "cwltool_work")) tmp_dir = utils.safe_makedir(os.path.join(work_dir, "tmpcwl")) log_file = os.path.join(work_dir, "%s-cwltool.log" % project_name) os.environ["TMPDIR"] = tmp_dir flags = ["--tmpdir-prefix", tmp_dir, "--tmp-outdir-prefix", tmp_dir] if args.no_container: _remove_bcbiovm_path() flags += ["--no-container", "--preserve-environment", "PATH", "--preserve-environment", "HOME"] cmd = ["cwltool"] + flags + args.toolargs + ["--", main_file, json_file] with utils.chdir(work_dir): _run_tool(cmd, not args.no_container, work_dir, log_file=log_file) def _run_arvados(args): """Run CWL on Arvados. """ assert not args.no_container, "Arvados runs require containers" assert "ARVADOS_API_TOKEN" in os.environ and "ARVADOS_API_HOST" in os.environ, \ "Need to set ARVADOS_API_TOKEN and ARVADOS_API_HOST in environment to run" main_file, json_file, project_name = _get_main_and_json(args.directory) flags = ["--enable-reuse", "--api", "containers", "--submit", "--no-wait"] cmd = ["arvados-cwl-runner"] + flags + args.toolargs + [main_file, json_file] _run_tool(cmd) def _run_toil(args): """Run CWL with Toil. """ main_file, json_file, project_name = _get_main_and_json(args.directory) work_dir = utils.safe_makedir(os.path.join(os.getcwd(), "toil_work")) tmp_dir = utils.safe_makedir(os.path.join(work_dir, "tmpdir")) os.environ["TMPDIR"] = tmp_dir log_file = os.path.join(work_dir, "%s-toil.log" % project_name) jobstore = os.path.join(work_dir, "cwltoil_jobstore") flags = ["--jobStore", jobstore, "--logFile", log_file, "--workDir", tmp_dir, "--linkImports"] if os.path.exists(jobstore): flags += ["--restart"] # caching causes issues for batch systems if "--batchSystem" in args.toolargs: flags += ["--disableCaching"] flags += args.toolargs if args.no_container: _remove_bcbiovm_path() flags += ["--no-container", "--preserve-environment", "PATH", "HOME"] cmd = ["cwltoil"] + flags + ["--", main_file, json_file] with utils.chdir(work_dir): _run_tool(cmd, not args.no_container, work_dir) for tmpdir in (glob.glob(os.path.join(work_dir, "out_tmpdir*")) + glob.glob(os.path.join(work_dir, "tmp*"))): if os.path.isdir(tmpdir): shutil.rmtree(tmpdir) def _run_bunny(args): """Run CWL with rabix bunny. """ main_file, json_file, project_name = _get_main_and_json(args.directory) work_dir = utils.safe_makedir(os.path.join(os.getcwd(), "bunny_work")) flags = ["-b", work_dir] log_file = os.path.join(work_dir, "%s-bunny.log" % project_name) if os.path.exists(work_dir): caches = [os.path.join(work_dir, d) for d in os.listdir(work_dir) if os.path.isdir(os.path.join(work_dir, d))] if caches: flags += ["--cache-dir", max(caches, key=os.path.getmtime)] if args.no_container: _remove_bcbiovm_path() flags += ["--no-container"] cmd = ["rabix"] + flags + [main_file, json_file] with utils.chdir(work_dir): _run_tool(cmd, not args.no_container, work_dir, log_file) def _run_wes(args): """Run CWL using a Workflow Execution Service (WES) endpoint """ main_file, json_file, project_name = _get_main_and_json(args.directory) main_file = _pack_cwl(main_file) if args.host and "stratus" in args.host: _run_wes_stratus(args, main_file, json_file) else: opts = ["--no-wait"] if args.host: opts += ["--host", args.host] if args.auth: opts += ["--auth", args.auth] cmd = ["wes-client"] + opts + [main_file, json_file] _run_tool(cmd) def _run_wes_stratus(args, main_file, json_file): """Run WES on Illumina stratus endpoint server, which wes-client doesn't support. https://stratus-docs.readme.io/docs/quick-start-4 """ import requests base_url = args.host if not base_url.startswith("http"): base_url = "https://%s" % base_url with open(main_file) as in_handle: r = requests.post("%s/v1/workflows" % base_url, headers={"Content-Type": "application/json", "Authorization": "Bearer %s" % args.auth}, data=in_handle.read()) print(r.status_code) print(r.text) def _estimate_runner_memory(json_file): """Estimate Java memory requirements based on number of samples. A rough approach to selecting correct allocated memory for Cromwell. """ with open(json_file) as in_handle: sinfo = json.load(in_handle) num_parallel = 1 for key in ["config__algorithm__variantcaller", "description"]: item_counts = [] n = 0 for val in (sinfo.get(key) or []): n += 1 if val: if isinstance(val, (list, tuple)): item_counts.append(len(val)) else: item_counts.append(1) print(key, n, item_counts) if n and item_counts: num_parallel = n * max(item_counts) break if num_parallel < 25: return "3g" if num_parallel < 150: return "6g" elif num_parallel < 500: return "12g" else: return "24g" def _run_cromwell(args): """Run CWL with Cromwell. """ main_file, json_file, project_name = _get_main_and_json(args.directory) work_dir = utils.safe_makedir(os.path.join(os.getcwd(), "cromwell_work")) final_dir = utils.safe_makedir(os.path.join(work_dir, "final")) if args.no_container: _remove_bcbiovm_path() log_file = os.path.join(work_dir, "%s-cromwell.log" % project_name) metadata_file = os.path.join(work_dir, "%s-metadata.json" % project_name) option_file = os.path.join(work_dir, "%s-options.json" % project_name) cromwell_opts = {"final_workflow_outputs_dir": final_dir, "default_runtime_attributes": {"bootDiskSizeGb": 20}} with open(option_file, "w") as out_handle: json.dump(cromwell_opts, out_handle) cmd = ["cromwell", "-Xms1g", "-Xmx%s" % _estimate_runner_memory(json_file), "run", "--type", "CWL", "-Dconfig.file=%s" % hpc.create_cromwell_config(args, work_dir, json_file)] cmd += hpc.args_to_cromwell_cl(args) cmd += ["--metadata-output", metadata_file, "--options", option_file, "--inputs", json_file, main_file] with utils.chdir(work_dir): _run_tool(cmd, not args.no_container, work_dir, log_file) if metadata_file and utils.file_exists(metadata_file): with open(metadata_file) as in_handle: metadata = json.load(in_handle) if metadata["status"] == "Failed": _cromwell_debug(metadata) sys.exit(1) else: _cromwell_move_outputs(metadata, final_dir) def _cromwell_debug(metadata): """Format Cromwell failures to make debugging easier. """ def get_failed_calls(cur, key=None): if key is None: key = [] out = [] if isinstance(cur, dict) and "failures" in cur and "callRoot" in cur: out.append((key, cur)) elif isinstance(cur, dict): for k, v in cur.items(): out.extend(get_failed_calls(v, key + [k])) elif isinstance(cur, (list, tuple)): for i, v in enumerate(cur): out.extend(get_failed_calls(v, key + [i])) return out print("Failed bcbio Cromwell run") print("-------------------------") for fail_k, fail_call in get_failed_calls(metadata["calls"]): root_dir = os.path.join("cromwell_work", os.path.relpath(fail_call["callRoot"])) print("Failure in step: %s" % ".".join([str(x) for x in fail_k])) print(" bcbio log file : %s" % os.path.join(root_dir, "execution", "log", "bcbio-nextgen-debug.log")) print(" bcbio commands file: %s" % os.path.join(root_dir, "execution", "log", "bcbio-nextgen-commands.log")) print(" Cromwell directory : %s" % root_dir) print() def _cromwell_move_outputs(metadata, final_dir): """Move Cromwell outputs to the final upload directory. """ sample_key = [k for k in metadata["outputs"].keys() if k.endswith(("rgnames__sample", "rgnames__sample_out"))][0] project_dir = utils.safe_makedir(os.path.join(final_dir, "project")) samples = metadata["outputs"][sample_key] def _copy_with_secondary(f, dirname): if len(f["secondaryFiles"]) > 1: dirname = utils.safe_makedir(os.path.join(dirname, os.path.basename(os.path.dirname(f["location"])))) if not objectstore.is_remote(f["location"]): finalf = os.path.join(dirname, os.path.basename(f["location"])) if not utils.file_uptodate(finalf, f["location"]): shutil.copy(f["location"], dirname) [_copy_with_secondary(sf, dirname) for sf in f["secondaryFiles"]] def _write_to_dir(val, dirname): if isinstance(val, (list, tuple)): [_write_to_dir(v, dirname) for v in val] else: _copy_with_secondary(val, dirname) for k, vals in metadata["outputs"].items(): if k != sample_key: if k.endswith(("summary__multiqc")): vs = [v for v in vals if v] assert len(vs) == 1 _write_to_dir(vs[0], project_dir) elif len(vals) == len(samples): for s, v in zip(samples, vals): if v: _write_to_dir(v, utils.safe_makedir(os.path.join(final_dir, s))) elif len(vals) == 1: _write_to_dir(vals[0], project_dir) elif len(vals) > 0: raise ValueError("Unexpected sample and outputs: %s %s %s" % (k, samples, vals)) def _run_sbgenomics(args): """Run CWL on SevenBridges platform and Cancer Genomics Cloud. """ assert not args.no_container, "Seven Bridges runs require containers" main_file, json_file, project_name = _get_main_and_json(args.directory) flags = [] cmd = ["sbg-cwl-runner"] + flags + args.toolargs + [main_file, json_file] _run_tool(cmd) def _run_funnel(args): """Run funnel TES server with rabix bunny for CWL. """ host = "localhost" port = "8088" main_file, json_file, project_name = _get_main_and_json(args.directory) work_dir = utils.safe_makedir(os.path.join(os.getcwd(), "funnel_work")) log_file = os.path.join(work_dir, "%s-funnel.log" % project_name) # Create bunny configuration directory with TES backend orig_config_dir = os.path.join(os.path.dirname(os.path.realpath(utils.which("rabix"))), "config") work_config_dir = utils.safe_makedir(os.path.join(work_dir, "rabix_config")) for fname in os.listdir(orig_config_dir): if fname == "core.properties": with open(os.path.join(orig_config_dir, fname)) as in_handle: with open(os.path.join(work_config_dir, fname), "w") as out_handle: for line in in_handle: if line.startswith("backend.embedded.types"): line = "backend.embedded.types=TES\n" out_handle.write(line) else: shutil.copy(os.path.join(orig_config_dir, fname), os.path.join(work_config_dir, fname)) flags = ["-c", work_config_dir, "-tes-url=http://%s:%s" % (host, port), "-tes-storage=%s" % work_dir] if args.no_container: _remove_bcbiovm_path() flags += ["--no-container"] cmd = ["rabix"] + flags + [main_file, json_file] funnelp = subprocess.Popen(["funnel", "server", "run", "--Server.HostName", host, "--Server.HTTPPort", port, "--LocalStorage.AllowedDirs", work_dir, "--Worker.WorkDir", os.path.join(work_dir, "funnel-work")]) try: with utils.chdir(work_dir): _run_tool(cmd, not args.no_container, work_dir, log_file) finally: funnelp.kill() _TOOLS = {"cwltool": _run_cwltool, "cromwell": _run_cromwell, "arvados": _run_arvados, "sbg": _run_sbgenomics, "toil": _run_toil, "bunny": _run_bunny, "funnel": _run_funnel, "wes": _run_wes} def run(args): _TOOLS[args.tool](args) bcbio-nextgen-1.2.9/bcbio/cwl/workflow.py000066400000000000000000000510351415626112400203440ustar00rootroot00000000000000"""Prepare bcbio workflows from input YAML files. """ import copy import pprint import six import toolz as tz from bcbio.pipeline import alignment ALWAYS_AVAILABLE = ["description", "resources"] STRING_DICT = ["config__algorithm__ensemble"] FLAT_DICT = ["config__algorithm__variantcaller"] def generate(variables, steps, final_outputs): """Generate all of the components of a CWL workflow from input steps. file_vs and std_vs are the list of world variables, split into those that reference files (and need declaration at each step) and those that don't and can be safely passed to each step. This function keeps track of these as they're added and updated by steps, passing this information on to creation of the CWL files. """ file_vs, std_vs = _split_variables([_flatten_nested_input(v) for v in variables]) parallel_ids = [] for step in steps: if hasattr(step, "workflow"): wf_inputs = [] wf_outputs = [] wf_steps = [] for i, wf_step in enumerate(step.workflow): inputs, parallel_ids, nested_inputs = _get_step_inputs(wf_step, file_vs, std_vs, parallel_ids, step) # flatten inputs that are scattered on entering a sub-workflow if step.parallel.endswith("-parallel"): if i == 0: inputs = [_flatten_nested_input(v) for v in inputs] wf_scatter = [get_base_id(v["id"]) for v in inputs] else: inputs = [_flatten_nested_input(v) if get_base_id(v["id"]) in wf_scatter else v for v in inputs] wf_inputs, inputs = _merge_wf_inputs(inputs, wf_inputs, wf_outputs, step.internal, wf_step.parallel, nested_inputs) outputs, file_vs, std_vs = _get_step_outputs(wf_step, wf_step.outputs, file_vs, std_vs) wf_steps.append(("step", wf_step.name, wf_step.parallel, inputs, outputs, wf_step.image, wf_step.programs, wf_step.disk, wf_step.cores, wf_step.no_files)) parallel_ids = _find_split_vs(outputs, wf_step.parallel) wf_outputs = _merge_wf_outputs(outputs, wf_outputs, wf_step.parallel) yield "wf_start", wf_inputs for wf_step in wf_steps: yield wf_step wf_outputs = [v for v in wf_outputs if v["id"] not in set(["%s" % _get_string_vid(x) for x in step.internal])] yield "upload", wf_outputs wf_outputs, file_vs, std_vs = _get_step_outputs(step, wf_outputs, file_vs, std_vs) yield "wf_finish", step.name, step.parallel, wf_inputs, wf_outputs, wf_scatter file_vs = _extract_from_subworkflow(file_vs, step) std_vs = _extract_from_subworkflow(std_vs, step) elif hasattr(step, "expression"): inputs, parallel_ids, nested_inputs = _get_step_inputs(step, file_vs, std_vs, parallel_ids) outputs, file_vs, std_vs = _get_step_outputs(step, step.outputs, file_vs, std_vs) parallel_ids = _find_split_vs(outputs, step.parallel) yield ("expressiontool", step.name, inputs, outputs, step.expression, step.parallel) else: inputs, parallel_ids, nested_inputs = _get_step_inputs(step, file_vs, std_vs, parallel_ids) outputs, file_vs, std_vs = _get_step_outputs(step, step.outputs, file_vs, std_vs) parallel_ids = _find_split_vs(outputs, step.parallel) yield ("step", step.name, step.parallel, inputs, outputs, step.image, step.programs, step.disk, step.cores, step.no_files) yield "upload", [_get_upload_output(x, file_vs) for x in final_outputs] def _merge_wf_inputs(new, out, wf_outputs, to_ignore, parallel, nested_inputs): """Merge inputs for a sub-workflow, adding any not present inputs in out. Skips inputs that are internally generated or generated and ignored, keeping only as inputs those that we do not generate internally. """ internal_generated_ids = [] for vignore in to_ignore: vignore_id = _get_string_vid(vignore) # ignore anything we generate internally, but not those we need to pull in # from the external process if vignore_id not in [v["id"] for v in wf_outputs]: internal_generated_ids.append(vignore_id) ignore_ids = set(internal_generated_ids + [v["id"] for v in wf_outputs]) cur_ids = set([v["id"] for v in out]) remapped_new = [] for v in new: remapped_v = copy.deepcopy(v) outv = copy.deepcopy(v) outv["id"] = get_base_id(v["id"]) outv["source"] = v["id"] if outv["id"] not in cur_ids and outv["id"] not in ignore_ids: if nested_inputs and v["id"] in nested_inputs: outv = _flatten_nested_input(outv) out.append(outv) if remapped_v["id"] in set([v["source"] for v in out]): remapped_v["source"] = get_base_id(remapped_v["id"]) remapped_new.append(remapped_v) return out, remapped_new def _merge_wf_outputs(new, cur, parallel): """Merge outputs for a sub-workflow, replacing variables changed in later steps. ignore_ids are those used internally in a sub-workflow but not exposed to subsequent steps """ new_ids = set([]) out = [] for v in new: outv = {} outv["source"] = v["id"] outv["id"] = "%s" % get_base_id(v["id"]) outv["type"] = v["type"] if "secondaryFiles" in v: outv["secondaryFiles"] = v["secondaryFiles"] if tz.get_in(["outputBinding", "secondaryFiles"], v): outv["secondaryFiles"] = tz.get_in(["outputBinding", "secondaryFiles"], v) new_ids.add(outv["id"]) out.append(outv) for outv in cur: if outv["id"] not in new_ids: out.append(outv) return out def _extract_from_subworkflow(vs, step): """Remove internal variable names when moving from sub-workflow to main. """ substep_ids = set([x.name for x in step.workflow]) out = [] for var in vs: internal = False parts = var["id"].split("/") if len(parts) > 1: if parts[0] in substep_ids: internal = True if not internal: var.pop("source", None) out.append(var) return out def _find_split_vs(out_vs, parallel): """Find variables created by splitting samples. """ # split parallel job if parallel in ["single-parallel", "batch-parallel"]: return [v["id"] for v in out_vs] else: return [] def is_cwl_record(d): """Check if an input is a CWL record, from any level of nesting. """ if isinstance(d, dict): if d.get("type") == "record": return d else: recs = list(filter(lambda x: x is not None, [is_cwl_record(v) for v in d.values()])) return recs[0] if recs else None else: return None def _get_step_inputs(step, file_vs, std_vs, parallel_ids, wf=None): """Retrieve inputs for a step from existing variables. Potentially nests inputs to deal with merging split variables. If we split previously and are merging now, then we only nest those coming from the split process. """ inputs = [] skip_inputs = set([]) for orig_input in [_get_variable(x, file_vs) for x in _handle_special_inputs(step.inputs, file_vs)]: inputs.append(orig_input) # Only add description and other information for non-record inputs, otherwise batched with records if not any(is_cwl_record(x) for x in inputs): inputs += [v for v in std_vs if get_base_id(v["id"]) not in skip_inputs] nested_inputs = [] if step.parallel in ["single-merge", "batch-merge"]: if parallel_ids: inputs = [_nest_variable(x) if x["id"] in parallel_ids else x for x in inputs] nested_inputs = parallel_ids[:] parallel_ids = [] elif step.parallel in ["multi-combined"]: assert len(parallel_ids) == 0 nested_inputs = [x["id"] for x in inputs] inputs = [_nest_variable(x) for x in inputs] elif step.parallel in ["multi-batch"]: assert len(parallel_ids) == 0 nested_inputs = [x["id"] for x in inputs] # If we're batching,with mixed records/inputs avoid double nesting records inputs = [_nest_variable(x, check_records=(len(inputs) > 1)) for x in inputs] # avoid inputs/outputs with the same name outputs = [_get_string_vid(x["id"]) for x in step.outputs] final_inputs = [] for input in inputs: input["wf_duplicate"] = get_base_id(input["id"]) in outputs final_inputs.append(input) return inputs, parallel_ids, nested_inputs def _get_step_outputs(step, outputs, file_vs, std_vs): if len(outputs) == 1 and is_cwl_record(outputs[0]): # For workflows, no need to create -- inherit from previous step if hasattr(step, "workflow"): out_rec = copy.deepcopy(outputs[0]) out_rec["id"] = "%s/%s" % (step.name, out_rec["id"]) file_output = [out_rec] else: file_output = [_create_record(outputs[0]["id"], outputs[0].get("fields", []), step.name, step.inputs, step.unlist, file_vs, std_vs, step.parallel)] std_output = [] else: file_output, std_output = _split_variables([_create_variable(x, step, file_vs) for x in outputs]) if step.parallel in ["single-split", "batch-split", "multi-combined", "multi-batch"]: file_output = [_nest_variable(x) for x in file_output] std_output = [_nest_variable(x) for x in std_output] # For combined output, ensure at the same level (not nested) as main samples if step.parallel in ["multi-combined"]: file_vs = _merge_variables([_clean_output(_flatten_nested_input(v) if not is_cwl_record(v) else v) for v in file_output], file_vs) else: file_vs = _merge_variables([_clean_output(v) for v in file_output], file_vs) std_vs = _merge_variables([_clean_output(v) for v in std_output], std_vs) return file_output + std_output, file_vs, std_vs def _flatten_nested_input(v): """Flatten a parallel scatter input -- we only get one of them to tools. """ v = copy.deepcopy(v) if isinstance(v["type"], dict) and v["type"]["type"] == "array": v["type"] = v["type"]["items"] else: assert isinstance(v["type"], (list, tuple)), v new_type = None want_null = False for x in v["type"]: if isinstance(x, dict) and x["type"] == "array": new_type = x["items"] elif isinstance(x, six.string_types) and x == "null": want_null = True else: new_type = x if want_null: if not isinstance(new_type, (list, tuple)): new_type = [new_type] if new_type is not None else [] for toadd in ["null", "string"]: if toadd not in new_type: new_type.append(toadd) assert new_type, v v["type"] = new_type return v def _nest_variable(v, check_records=False): """Nest a variable when moving from scattered back to consolidated. check_records -- avoid re-nesting a record input if it comes from a previous step and is already nested, don't need to re-array. """ if (check_records and is_cwl_record(v) and len(v["id"].split("/")) > 1 and v.get("type", {}).get("type") == "array"): return v else: v = copy.deepcopy(v) v["type"] = {"type": "array", "items": v["type"]} return v def _clean_output(v): """Remove output specific variables to allow variables to be inputs to next steps. """ out = copy.deepcopy(v) outb = out.pop("outputBinding", {}) if "secondaryFiles" in outb: out["secondaryFiles"] = outb["secondaryFiles"] return out def _get_string_vid(vid): if isinstance(vid, six.string_types): return vid assert isinstance(vid, (list, tuple)), vid return "__".join(vid) def _get_variable(vid, variables): """Retrieve an input variable from our existing pool of options. """ if isinstance(vid, six.string_types): vid = get_base_id(vid) else: vid = _get_string_vid(vid) for v in variables: if vid == get_base_id(v["id"]): return copy.deepcopy(v) raise ValueError("Did not find variable %s in \n%s" % (vid, pprint.pformat(variables))) def _handle_special_inputs(inputs, variables): """Adjust input variables based on special cases. This case handles inputs where we are optional or can have flexible choices. XXX Need to better expose this at a top level definition. """ from bcbio import structural optional = [["config", "algorithm", "coverage"], ["config", "algorithm", "variant_regions"], ["config", "algorithm", "sv_regions"], ["config", "algorithm", "validate"], ["config", "algorithm", "validate_regions"]] all_vs = set([get_base_id(v["id"]) for v in variables]) out = [] for input in inputs: if input == ["reference", "aligner", "indexes"]: for v in variables: vid = get_base_id(v["id"]).split("__") if vid[0] == "reference" and vid[1] in alignment.TOOLS: out.append(vid) elif input == ["reference", "snpeff", "genome_build"]: found_indexes = False for v in variables: vid = get_base_id(v["id"]).split("__") if vid[0] == "reference" and vid[1] == "snpeff": out.append(vid) found_indexes = True assert found_indexes, "Found no snpEff indexes in %s" % [v["id"] for v in variables] elif input == ["config", "algorithm", "background", "cnv_reference"]: for v in variables: vid = get_base_id(v["id"]).split("__") if (vid[:4] == ["config", "algorithm", "background", "cnv_reference"] and structural.supports_cnv_reference(vid[4])): out.append(vid) elif input in optional: if _get_string_vid(input) in all_vs: out.append(input) else: out.append(input) return out def _get_upload_output(vid, variables): if isinstance(vid, dict) and "id" in vid: parent_v = _get_variable(vid["id"], variables) v = copy.deepcopy(vid) v["id"] = _get_string_vid(vid["id"]) v["outputSource"] = parent_v["id"] else: v = _nest_variable(_get_variable(vid, variables)) v["outputSource"] = v["id"] v["id"] = get_base_id(v["id"]) v.pop("secondaryFiles", None) v["type"].pop("secondaryFiles", None) return v def _create_record(name, field_defs, step_name, inputs, unlist, file_vs, std_vs, parallel): """Create an output record by rearranging inputs. Batching processes create records that reformat the inputs for parallelization. """ if field_defs: fields = [] inherit = [] inherit_all = False inherit_exclude = [] for fdef in field_defs: if not fdef.get("type"): if fdef["id"] == "inherit": inherit_all = True inherit_exclude = fdef.get("exclude", []) else: inherit.append(fdef["id"]) else: cur = {"name": _get_string_vid(fdef["id"]), "type": fdef["type"]} fields.append(_add_secondary_to_rec_field(fdef, cur)) if inherit_all: fields.extend(_infer_record_outputs(inputs, unlist, file_vs, std_vs, parallel, exclude=inherit_exclude)) elif inherit: fields.extend(_infer_record_outputs(inputs, unlist, file_vs, std_vs, parallel, inherit)) else: fields = _infer_record_outputs(inputs, unlist, file_vs, std_vs, parallel) out = {"id": "%s/%s" % (step_name, name), "type": {"name": name, "type": "record", "fields": fields}} if parallel in ["batch-single", "multi-batch"]: out = _nest_variable(out) return out def _add_secondary_to_rec_field(orig, cur): # CWL does not currently support secondaryFiles in fields if orig.get("secondaryFiles"): cur["secondaryFiles"] = orig.get("secondaryFiles") return cur def _infer_record_outputs(inputs, unlist, file_vs, std_vs, parallel, to_include=None, exclude=None): """Infer the outputs of a record from the original inputs """ fields = [] unlist = set([_get_string_vid(x) for x in unlist]) input_vids = set([_get_string_vid(v) for v in _handle_special_inputs(inputs, file_vs)]) to_include = set([_get_string_vid(x) for x in to_include]) if to_include else None to_exclude = tuple(set([_get_string_vid(x) for x in exclude])) if exclude else None added = set([]) for raw_v in std_vs + [v for v in file_vs if get_base_id(v["id"]) in input_vids]: # unpack record inside this record and un-nested inputs to avoid double nested cur_record = is_cwl_record(raw_v) if cur_record: # unlist = unlist | set([field["name"] for field in cur_record["fields"]]) nested_vs = [{"id": field["name"], "type": field["type"]} for field in cur_record["fields"]] else: nested_vs = [raw_v] for orig_v in nested_vs: if (get_base_id(orig_v["id"]) not in added and (not to_include or get_base_id(orig_v["id"]) in to_include)): if to_exclude is None or not get_base_id(orig_v["id"]).startswith(to_exclude): cur_v = {} cur_v["name"] = get_base_id(orig_v["id"]) cur_v["type"] = orig_v["type"] if cur_v["name"] in unlist: cur_v = _flatten_nested_input(cur_v) fields.append(_add_secondary_to_rec_field(orig_v, cur_v)) added.add(get_base_id(orig_v["id"])) return fields def _create_variable(orig_v, step, variables): """Create a new output variable, potentially over-writing existing or creating new. """ # get current variable, and convert to be the output of our process step try: v = _get_variable(orig_v["id"], variables) except ValueError: v = copy.deepcopy(orig_v) if not isinstance(v["id"], six.string_types): v["id"] = _get_string_vid(v["id"]) for key, val in orig_v.items(): if key not in ["id", "type"]: v[key] = val if orig_v.get("type") != "null": v["type"] = orig_v["type"] v["id"] = "%s/%s" % (step.name, get_base_id(v["id"])) return v def _merge_variables(new, cur): """Add any new variables to the world representation in cur. Replaces any variables adjusted by previous steps. """ new_added = set([]) out = [] for cur_var in cur: updated = False for new_var in new: if get_base_id(new_var["id"]) == get_base_id(cur_var["id"]): out.append(new_var) new_added.add(new_var["id"]) updated = True break if not updated: out.append(cur_var) for new_var in new: if new_var["id"] not in new_added: out.append(new_var) return out def get_base_id(vid): """Retrieve the base id for a variant, ignoring workflow/step prefixes. """ return vid.split("/")[-1] def get_step_prefix(vid): parts = vid.split("/") if len(parts) > 1: return parts[0] def _split_variables(variables): """Split variables into always passed (std) and specified (file). We always pass some variables to each step but need to explicitly define file and algorithm variables so they can be linked in as needed. """ file_vs = [] std_vs = [] for v in variables: cur_type = v["type"] while isinstance(cur_type, dict): if "items" in cur_type: cur_type = cur_type["items"] else: cur_type = cur_type["type"] if (cur_type in ["File", "null", "record"] or (isinstance(cur_type, (list, tuple)) and ("File" in cur_type or {'items': 'File', 'type': 'array'} in cur_type))): file_vs.append(v) elif v["id"] in ALWAYS_AVAILABLE: std_vs.append(v) else: file_vs.append(v) return file_vs, std_vs bcbio-nextgen-1.2.9/bcbio/data/000077500000000000000000000000001415626112400162405ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/data/umis/000077500000000000000000000000001415626112400172155ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/data/umis/10x_v2-cb1.txt.gz000066400000000000000000104217621415626112400220740ustar00rootroot00000000000000vy[10x_v2-cb1.txtdYe)kW}|kx 2eBbXkUYK*ߟ(FrE4rQ)F"˹Q~q_%`%jpKS! T$אRòY:T|)WV(+2넌 Q%I8⯸`_>`X(_eW$kEP_ Q(lRQ8#/r_WQ r}QRah@] ?V?eh_E?ѵP0U1?Cb:WEJf~fDd4OD>Hzr( dvJipKA-Di]itt{fph,(C8>97h"b9 AN݅i):AUpfbm"-Dj(rLWWߚCg_/VЯۮGr=BilL~S`Fm `!6i"ʡo5 @1h{`i!8^~ ?:ك ۻ?:%{R9{0u/ElP&9~HCTNgƶ˲u'=>&*!8E 0 ;ݞő- xO&@" +L׶"*- tO~\m4N Z)͠{ w7d觭il}p\ P8uR4f6m@% 2(a-Xh8C) " M70A5[GsͿM3{UY"ʯ Ѣm_Qe(fJ\"QqKŲV8oQ8m)>WV ADølmWo_^D[4hs_Qc M Œm5hm # q+,?~J { 2 ׄnKRe(Fn;v4CX6{O~"ʖz]6P%굕q|6t\14J-j1cڱx;BETi趙̶m0snh0t ;HC\A-~sC#ҫAe?6X6~ԦŨ-l(&d$gEiԜo=Nixvc M]e""SR16g OɊ ҀͱCh)3Vg,е{q>j]CcHozX{VKp 530W EpAW^έ薮u2P0D4`geً +ڥ ?M |h9Qei-m˘ 0H!`&j/A$Z) Y/jWrEK 1W ۉQ5v Xc{@nr%lpE vYXsCu` WQ!ۙQ,(Φ+d4,;YD6U|;giP&W SHD + VTaB$)PZw4:ͷdLp-$QclV=#,Vl龮$>腆wt[`aV~[l="jLt׷'@e3Q=\B4ص̬ۖ[QZ۽``}W,ڶ-k O_+Ș )̇ T=0QGD4vRQ8ml&`i[&C=eP !DQmLl.W(fw؞F0TU(! Bif>(& cn/ Wk09iaPsD:fZp;4c 3g7D?DB2=;I`(^t@^!ض7i݃Q|}Y Uc/8z{!*Mb)3.pܚS3J{^ X8e%r}K 44(BpkTϷ!!f[Za˩V$ n*X6D9w@On"`% [y`iQ -7%nM{,o 8 UE)Uf(F1sPYoifKPHgP^{+~k0j ԓ HcN8 F`"s ̌AA;QT`h}Cq`4fS by@,lml+m*(iLy6w0DMx~%~BWEs,~:A%ӅB3h_ldEKW6VTY{>`@US| !7/l"9iIozh6ȇ(^ 8*ϠHB h:VRA+jQL8u02ۡ_ZvЃ`l Q5PmrWI[p/,sՋj9nD0cX7™}Ug&Jyb(m-@}%A#|8 ؃ACn2 )Um'S%8FCXp0} :pH B~`=TP pDi^eW+cO8R/_1mX@}lOb"ʱ*@UX)QaKSWiKN8}?SX0Q(.Ꙓi($lEC'P:ؕQbDғ *ن0#}~v+ֳmapML>}!2*P1 )ʂ}m ^TҰ" ,"g7@N{V*߀*tKUǺ7AQ T `DBsfpA\c3G%g 74Zn F@TDsBVaaY`(>zEn- QMY8lAFQTBHt</xrث >[Qc܉_gQ ;Z<95`/.:|ŵ f;FpV0j[/6?k:qHmT߆mhD]%Q, 5\.!\Z!}f>q8aQYs%s A?DpqD3 (ǹB0O{l gGS`8m(!o +i~|P>G(C`:i  .}ENbA[ `F1priɢ>f}(Q DEsEkP6ұKQ#rdL%ݞL"^j2W\w#-t)-lmj7ilFߠP gC1ckӧlfZ\?-8up"f]B\Q&fۆSB\@'dSc+t "7(6B:Eh u & C DLQ]t}!jWL TFx*HCQX]E@ F,%"}&_LE,@_egY7 J,{R dj˷61`!?E.GC(CAԶ\L#pETϻE ~g?"w{4ԍb}gLj"E \6 A6/=I,$NU78B_ iIo`kCczs( K6<,֛ *HI @Q{DJmi=#" u9sɆgQPYCr>gP8e0\Akg@|[Y|NO?`DykQy!Ķ`%{W(]\Er;ED Yc*> .6]P,WdU>pW~ N-|_W@1(Bzx&]%r T D$~2D7f3\;#rmAs s#/ztk&`ˍX} ++x)!Z/3J1&/"yl(bccXh*y`V_Fi48+@P;/>{nٻPλ YNRc f_`wܻ~Њϊ|F׮z|*|DjEvU<Qz7]Xt++BPfHC%oS/VX%]_qt)=f?ec}2e`F>!C/6^caubC9 "P 8CD@E]ʢrWl/> +@0.@YB(i=IYәiƦ֝>m(K̺9# B`hMQ c GƦ })1 x>^!OU!O59@Tz/0Ni`/ur`3(ħ t)Sz.ލ\`\J)X]6)lR uVp*Cfl%>ƎRj [46KL4cn+HVN۰9Cxdk1ZsH#D~EipQ(qT rD[bYvZ/ V>[Ҳ2u˳ooZ٢px_X] TM0cm $'`MXry# FF%~(ǖIȘ&(B(T}pES>gfYX, j!amHC`:9 t>4J.!ѷ]QA|m_tڮQ>S1`HvZo0t˳ŷHC\,~sC#ҫAe?i1j [$uvup}#AQs;fL7Gu+?z}`PlW(kb՗!=LyZOVl#Rfmο,\Ytuwn~VSv%Gl}r/`/q?P+҈v{ (c S@mo!0L.r坎@0!ߣPAU !$g+rmSf)^%D/Ȭz_eђ`Ղi"{r !k*֘~ "wȱ▀Ķ"B. +bn-LCU1{!kv|^{n pf"gr;tb<EB&2jL!{8/(}*.>4:@AZd֘ĉҲA)ǻSukኀ S1@J 6׊D+C/+B'y!b}]/0cnn"okP@. a&Jݲ B"PB>P%CۗBQZ۽՚C+BPqu\mGz7\y: 2&CJmB?UL-+>mL'꽲Xc66zm?Pt`CVD)j"`3]DK: PJmka*y+j! BI6V|]( z[?]{li}k `%1N+VM?'=Y?29}eQrz.U%0|}pBmF ݋>Tvir0VGhxJz\r9MLܚS3J}0 dQQ6P!Xuz~n%Q} j]F3 7XJ rn/B2,ͭ<(XGߥ޷oCLa |hƞ|̩C! FJvE<@!2 2QZ/Ǎ)Q @=4`F,1Ej w@1 FS`1ް)VОaR(iLy6w0DMxxsoPh4q )ϮT2]X *>ֻNVa1zz5`ckE!uP4P{0 (1}Z !AC1n^^vAE>1*k۳ACӌL^g rA$ <u_@d>fr/A;@+B`n}>zV½8 / _)N'muIJ`U/ ;L_.p%`ưֹ!Zuf{) tn$ ipNz\uJN4*|/`mqu`>Ǹ8nLc~f("Qxy_>( L]EP%T+bW4Zc>PpTDO*t, BҀ%@ԩ+Fpc7a:jE`vQϔLC! e(j78Հ#Qn mapML>}!2*P1 )"v\!T4H 5P.r;*PT[B<ֽ B TA.48_EPh)>C}>=h/%$/A"8@\H%Znp4È ".+t܀#'y/˸_ei(' `uR-YA%.YDiy @> o#JWvaNQZxͅ_>[_.(-_.0e]![/*C8 թO$@mͩX =,\ (N2*BPh!(aZ/F8_9j `:50o :jY¡-(>j)c-=uXXG[!2UEKo:nD^.!G[Z`dהH1lf"QXWjǑƬ ;@ 1>GBisv2ҘkrXo!_` -T@h*%SJ,KE Wl(fٲД#jFdEy.4DʳM{!'H 5Ɲl[_>0ww`F1+hCk&ʂ >{ ԀPJ/QɃZ¨vP~lsVRsomTox@w6P> > \|xe_+#!  49µ0L4j:}β$`N|7.nh`| Z(f?KVГ _>@[8%m4p,x4R;S\s%rϕ!0xE0I{W0W >D,x~v+(fN.m?YGL{%?9|(E}< (FT_ý%HO]xEΕ5٠FZR\،AN{?*n φb+ -O(=0뵸~Q- z~J[p4`*/f]B\_>yv {1f_W:4ГQ( 8*. M\: WԂ%)l ] Ҙg`۠} \ VH#4g@wkTD*t(h2|I]lZQXkl>a D9Y"]V~uӏ |$2y"*]!?Lo($mb*gB ~ "rlR " Qr2QQ=Y)jPloPP7ξ{2gy_1d1}ѽ$RŒ(m^Q{"(XH6@J1n&0b"(V++ȜoGMPl|0 +:OTLz6:r/UQA@!*mSL6OCҍ_> ֡]Nm;qۀ0Ӹ+ ib>nC=pF[| >Y83> v\ SP*/(.H>Yol(+2v*X{YQ=mm ![& 5\i9~ @F^`v]Qf\hG 6]s9m]` [s6[SP`j킐뮐mk^xصP0k@fRワ˻@^3O{6H8@Y\2E9@ړ/e@1c;D+da;qK-!?Q|;.V|VT/]XJ»Z;h_o^ypB ׻0¢;!(*(y{5ǜz*Kw{2>0#֡Cz@Yr(}݅!"P!8^Zv)^]v `{\mpW "Ga6=hPҺ~ IYәiƦ֝>m^Q|us׮C]z 3{6,iݔvAzpD6M~.HB@d[&!c⚰/$c!PR> |)3,Vd,m506$Lz| t>4.vATc>/,}bdR2`go9Y,vG%k A jbH CD!<;Cc`6\E,9CW[w( 2޶!Pc ]#ht~AqUwqATлZ ["%EMҲA)4\Q. z7N:[H Q;+)\+m|=P+F6 t_ת,DLk`@_ ]nܕ5(u.DC %OZ!Bb}@D1DC+BPqu\mǻjz pT&o[QpHì{V Y=n{Aӝ_S Z:"`3]Q6=?a{C@8J10P %X]l14_]mi~}k `%1{AVM?'=Y?iзPc㚯Bݺrid>s>o8{{ 6@H#E*y;BVBe9H^#Dq4r~W<)uN'L4R9L)+Y} i7E.V[alw CD%y[u-NjEak_ rv2"vEJ+|*8/E|F5 b [xZ/Ќ=̩C! FJvEBj[~=oh#!nA/Z k0j ԓ HcN8 F`"s ̌AA;QTw@1 FS`1ް)VОaR(iLy6w0DMx{97({gf츅ݔg *.fbAv`]'+0^je 'vώ̺\Y}=|Z"d> ȇiIkOzCӀ@CӌL^gh *2 gD4@ŬSCy<5vkҠE!0n>Q =xp qQq Dp ^bY+Po C{Wf +`}Ug&Jyb(m8YDfN{0AE}m SpT>V!/`~|1 .i|n.Nvf{l=6@TӀ=r,0wA_tΤOQ_Y6h="CNDQ=бS6J– QS1.n8uՊiqYPvO\ ((1zI|mзo lgi5@ 9մ;lbR" /ilF+xjQ=oÕ :n+Rj"2tcݛ @NP`DBs\hP 3ĻA{ل(!a/pnX6I@2gS A6h9}ԇ m v`.ձ#'y/Nj{1q)zjH_.`uҹ-H4bx_ ]"V@n^D}LW(~QR(jEY^+o$*v4vY}/ {AepP"rZ: 9+D/ wVIFQE*3%LH+{1GQ 0ԭ03l!* [O,@wPp5nՖ@VXXr' Xx储 ut򁢥{@ 7`a/ /!G[֫#c$4fD6`bi=9LT%]Ƃ׵84m UXڴA󳅛J-WXE7bw?{*"ѹyn0oM"`Cq7ϖ]ȇ,DQ[6 (*sy@$:Wme+{!'H 5Ɲl[_.;0w!G{Jsj^(Ljv~uLjN4ЊFcgMGxvmנ2P|svC+8QoW @ԩ(BoM!׹5-ikp#>X FMgY)Q-\QV!T9`|eR}tSLDz<9gB)BO.^Ngy9J J p0w__`"xӀ/ݥ n7ɥ'h @uz8D/cc- 3r{F:6v "bDYQwtۓ)CD?KM+ҠFZRz<}B~T$+ Ũ!dr`MOͱGzpZ iU_.f]B\_.<ۆSB\@'dSc+t 2`q7t<: WԂdۀݡ" C]t}!jWL Td):=REi(С%vi%{e\Yh@ >̯l`&ɢ}Ŭ~P{%UQAF a|@!iCP8 UxP?s-W(-enřφ -M/u+ g{b7.+Y!rL_t)e" n"ړAB1nop0bӂWV9ߺ6lJ/ZX/,<,n@.jP?RakHB}G*d~r_gr7i/FeS @1}xF Ͼmi4A1.FW\Y/BXJ|Wz@BzNQ|"g,e>KMiR\?Q >`l@1(B[@dbL&Zbw?@vrA1cϨQ3O1zM¹xc +֜M;?pU !Z@uWuW6oDS?xCQB]4y!˯dC)~j,>p 0n/`#4]Dz˕ OZ(~Di=WnP!5^"o'Cp~3/0ʻxww]hgEikk9@UVk Zs5>Qz7]XttpE  J^1^J Rz d"| Bl[6^mgņrD>(k,>@1^~`@E]ʢrWl/> +@0.@YB(i=hjiֻشBc;AdzmĿ"f/fQBS 06} jBBjr_>a:9\m4uTԺk9B]!~Z-[wu&(B~lEa3f lP'`% 2(aV*Zα5"p`S-VD\%&Њ1x$n+'m؜!H=G Lk8BWT }9UEKXs|VKߜ(h{*Cqs+p~fwwlzxEyrA9@Ԙi3غ>X]E/$(X ? 58|87}^Bm )Pxʏ&(B(T}pES>gfYX, j!amH/`:9 t>b;@\i%$|@Tc>m[Z}bj9̶m0snh0t ;HC\Z Ĝ/ 1C۪D>EkH|`M"wȱ▀Ķ"B. +bn-LCU1{!kv|^{n pf"gr;tb<EB&2jL!{8/(}*.>4:`o4!`%+|L|įd|\mAS~ j0͵" !ˊI^Gst_ת,Dzۚbg{_RTp a&Jݲ B"PB>P%CۗBQZ۽՚C+BPq 0y?:!-V@ZB:_.<\!pT&V6^wV Y;nb_;,J"JQ\!QQ|"Q(R|JsPE`0ʖ QscKk-} 8\v1cpP1ӊCݡI'g]/(ؼ=$0|}pBmF ݋>Tvir0VGhxJz\r9MLܚS3J0SzrAT((Mio(\P=?dd-PNL4 ` +֕"QNW|]f/(XGߥ޷oCLa |hƞ|̩C! FJvE<@!bc.78y?nLywL55`hIlp1'0B``fƠ(HTSwh0!m03MֻNVa1zz5`cӭ2ѹP4P{0 (1}Z !AC1n^^vAE>1*k; in`& WJ3p D_@ T:O/N 2 3mkױ~@+B`(T;0E{q"@&_RNxe^Tqv\JasCD)OR ݿ ɢ/ 0sK **kmk`@҇Ӡ2 )5|wЗ PQ NcutZoq8>ZhETU$ /OeW|?/@SQ_Y6h="CNDQ=8gkqD4$`N]Q~7b|NqLT+ zd ol(@Pfp]%FT/= ݶ'"@r(;(|Z е;CdNU bRE{cD0] W<GW,/'\ISAh-@I{W0Weݥ/[ `F1priɢ>f}(Q}l&`5.3݀_f~>?pdL%HO]xEΕ5٠FZRjC7ilFߠP gC1:NӧlfZ\?ɑ|cuQ q1g/'6Ŝ}]Bp! *}68Rf}m?.`۔vA^gT]E.:}$^IcQF;p? (W˹@@LNhq܎_.(fU8CwF>)F8BP8?PQ8#/ztk&`m(Wu@Y\w\wo@4KcK/3J1&/"Ը/h(2.9 B'P5xJ{Ab| ,[D~"@k Je@1c;D+da;qK-!?yQ;>p=@+>+N]XJ·ZkZ @7/CjWI`;|]XttpE  J^1?UGs]`o#P>'Sfc"`:rh)!bTa~ A1^3D$*~mTxk إ,*W{vn{R9]Y0.@Y!c(pN4DEtfjl?l[xE]byGkNgqd} ~$S aTswEoS+*/J|L's2@E#A!>.5p6} T+w#/p >Ii@ A[CPB0^b^-g6b@i]b1 / 3D)z;b~imG*@~ *ȱx|ۢTS`m!e>j-7# MsY XK!Fc`mPEXgWW 9xD5mǛjqy]~nPo0cm 6v @6(6!ۜYcj\:#[_oj ^33{ (c S7PD۶$"0LFu2P0D4` Qx[UB=m `CDZSABJm0fmZDid֋rHhI0j@=O]p|֐5@k̅P@@&pE vYXsCoa@٣D_ XM/"scv7(9ޡ[w( 2ƶ!Pc ]#ht~AqUw񁨠qZ b%+|L|įd|\mASED)\g A؞lVi6^VNj=BĘV_`` :V?Eջ[g]nޕP.DC %o@Ym_fEi> p&TEuLǏ`Ƞy O/DdH<`>\!:eGMDe.g{-¯xW8Lgaa:u.`-8bd_.`0ȡ$+  th݁1~Nzz6eb73ЃLw*F8g{ź=py`< |t~!+rڝ9@1j@|4c_>`ԡ|D%NVeb`h <7<ޢm0j ԓ HcN8 F`"s ̌AA;QT`h}Cq`4fSx"60R1KDR`4l=?Zr3 evnJ YgЀ '# sCCD?m?\Ypg}4:i5(Ƹya{Nƨ_;xȇ(^ 8*@x D;QAP8 "qBŒ_.`;_6h~hEۭGB:\C\W 8k 䎯:^bYfAs܀/0cXGc:3QӽCi B81tFp{жV)}8 *`R 0_pa jp0㮛D|3i=TP pDi4,0xhJ\S1+fP`s}݉8*w(U+? J– QS1> 8q &E=S2 76mh$WJ2J^zD%m7ODQO v63Qk vȜ@4( ѷ%xES_Ұ" ," @բzކ+tVqUw aVa ,(\hp`*}d@KbA{ل(!a/9> lE+@\H%Znp4C3]hr̥:?pz4E"x|+,< Ae2LDw0:$E1n99_.0e]!qo ^XDN+T>5"`%W.xp!*;(Aebi|e#戢?f-"D>k`HV"i`VpjK O+,)R{VȱȺWd,VHKc=sj D9ua/܀0\6/A߳CdWA FxMy̶m`&Z+5~f}Ii r믋Nmzs$$n9g'# G0o! [6So`~pSI bv%ܼЀUXXV7ʷϦ^g.CTCS~"-EQ< +6 ޷셜,>#-*4Vw"n9qŬQp^U( N/#3PB9FT fܠNQc'zY$ހ]p5 ! m!]%Q}"7@|QA h=VG9B@j@hskaiteIBn\"Lq(b4(*_(Gw8%m4p,xs[%R;S\s%rϕ!0xE0I{W0Weݥ/[ `F1priɢ>f}݋D=%?9|g6W@EaϏ!E>pEIg+pSc^se_6軑65@w46oPޏDq[5DDCS63Jkz-_g ۛC: X 8YiI++ȜoGME |8,ak7 AGWt~5r(tA0g$BTDӾ#`N2p?/I77}No 42Da(Fn|\g64oP>VyO`F̃!].+6Pz >jE{₊D GYʬ ^KMigT[E_:$>p$o(ofqx5\P,Oy@@L?qy1fQf8 6]s9"xѽA[s6[nKfFT!Z ++x)]F CT(!|/|@fRワ˻@^3O{6H8@Y%Ƞm(~ QkO@U!,~O ,jOw8Ԋ|w~@+>+N }%V]Z @힃 ]]% vat]`cK1/lj XAo@|ѥtvߛ!ɔEضmxϊ P7|PC.D _o[!8^h[:{LNw'^EN{W:ަPp9~HCT~Pcۀe![3(S(K̺9# B`hMQ c GƦayHf> +*/ -2JrAE#A!>.5p6} T+e<ySȏ@(lR  =T%XAh9jDMXIX!"s}e{[v PB9$aG3e36$Lz|z+ĕV]BwQAxڶ/?pCJ|z[-F߶Ĝދ 1Y۠6-FmaDή0s"4js}rL=xtsTױӆg{B!mٞ򴎟" 3F 1M&0cwsfkg5Uj[rT-{5[5W`.mv@Q8@n"ݾۈ'@0!wQ{ު JK̇_30ZBJm0{~6gW| "42E^Jm`U)EZJ|֐5h+d&z7<9 |" ҙ\17TW*rU8Bxvzw= 5_{?, oQ(r/.(\P.drm(CRG#"nw8J~<{\@i9y jsR&Lp-$Qcl} C/+ʲ'-W1Guz һAt~00w @5&2(u.DC %o@Ym_fEiήo! EAyQjZi2H -U!/@_ɐRy|OC*ut˷-uPa=i,L1,b_;,xx傊DK: PJmka*y+j! BI6V|z=( z{[/4?>5JsQƌAUL+u&}ޟMvy4[ Pqj n]@U 429+֕+xe!?/}Y #0mg VI+T: Г[s `&BfJ_JzeC) E5f]v0DTs(W;U`axW+Dݻ']f/(߱+K`o 8 <bc;VB@:=>Զ.{_F`1w UwL55`hIlp1'0B``fƠ(HTSwh0!m03M4 DjQ}Q6Zc>PpTDO*t, BҀ%@ԩ+%'>v)VfL4P>IveQ$Jw6ODQO v63Qk vȜ@4(qՆlS_Ұ"_FP?'rE W(踭3J-G5PTXQ/p| >2C@E n zP_@ 3p4I2W9"(ܟC`S}b`R_*A X=qX"ip{j. vC LT&pt;I (҈i3tZx1]M/mD PJQw8Je{a-/0fYB\ 2W8! Aui'TaŠr;+ [v"ث8lAFQTBHt</xrث >[Qc= vswfN?DyVi,*Jsj^(Ljj;5;/` Zw(AaX; (?^l9tD97`6q *C7WRTPn x@eL']WrExEYpwi1-U (fN.m?YGL{%@E33o#8 (FT_ýLG4W\Y}7"@vbvL`3:HW5?|5_.ӧlf*z z~J[p4`*䇶h#PWp/_>x۰sjuU /}iQ=D/P:_D+j빽[E nr17p1DJQ|T;X\G" E:4$v|ZQXҠ@Zp_`~e3QN`!JQ*f#7+ _p 25zW IY H, -W(~\(w@,5(~6DNiiz7ݲw 0 OcDX c{J+p4Bm٨R /ĸUJvFX. s=]6-Plxak7 AGWt~5r(tA0g$BTDӾ#`N2p?/I >%,t ~<3PP\Uee31 vv4@r5"PArw⁊D?Yw.mJX|gTyଢ8~N[hQbQx38n{ bG}8e[mh9Ƌd>eqb8ief"|T9t)?..)>P0w2C  _:xAHol(y`"4PDz˕ OZ(~ݝDi?{B]Z(flh,l'Cp~w3.'`]hgEթ]@U>Z @힃 ]]% va:AAytWIW]Jn{2>0#֡CM r/oPE1^q DCů-z/w-6Ej.?_8i"@ {-2&9~HCT Ʀ 59Ĭ~;"fNٶ`~hFBcS>۔||ZoW9}V av{b^(Q*jݵ! w SZ-[wV 2+ ꃜF uQ8kO8!D os{M!ؔ|Ԋ }""1Y&n+x6l;`#&@{@6pȯ2 n3 %ؓ**"i e1½_>Pm{e92-66e+=yejrY4h;1r1fu+dn@_HQ6@~X&87l~>pD6M~z/HyB(?/pM1( )n`>\є3v,Vd,m506$LdF&}NDC1WZ}t ~ r,/жye3#u/0C<[|44ͥ}]g17;b,T,^`mP[D](՚/H<'wD4<wiC= _u:cU_e{:~"4`s14}0 W?]n;6?ZWؒ er|W^ؚ @H#^33 s|`P7PDzEyÔ2y SCi tрmoQ PAU i3*9-g?j-N/3JfmZcH Rjb\k7,60j@=O]p|֐uy5h+d&or%`ȇ+P(BJx rU}$Bxvw U  E, KQ(rα CW[w( 2 !Pc ]#ht~AqރtEヒ5_&d} 2S/N+D5uDꭵ(kEBڡeZ}1辮U 1Xz7NFf5Al PLePEj},KH/3Xg׷{5}݇W,Vw*J Pd3{eȘ )̇ T=0QGж 0lEp~eL1,b_;,~{e{偊Devy±]%@)u.tP Qs{Tѵz `%0(9u]aTu̴"Pwh9Al}k 5֕TL#Qb]?8h ŒUH@CmV,^#Dq4BFU  ib֜PrEGِFhJ{CQbu -֘[D 2DTrZ{L4 ` +U*N&  ,V}e'PrQߥ޷2t_=!DqzuJ޾%aJ/Bƾ oh#52Zޘ2+zKC3POb+#94-wc503FQECP 1mєiLcΧucZaR(iLـk{[Z*j `kgߥDlx M}r80^rxvώ̺\Y}.!,`CḊXcܼW$:77P1'=b%c{eQE>4 DjQ} ASh *2 %NV7 hr <0hjr ֪3]7D|[}٨msK©*{}GY`/}ehJ \S1ކ5@k!*~_w"ʞ XE@AUp:uEN8}?SX0Q(.Ꙓi($lEC}7\g%J2J^zD%wзo Li§]O3DT*!EYĎ6d@2i`Qi95} *,O}#B ,(\h8_.EPh)>C(cQ*=J\4ۧM .$lm-G1g@}K76ޓ#Pciku{j vC݆ 2qR^ 8WA =CW1-LQkpk2Fů>Ük>n9߾_0bk,is! i* *?AN} *hkNEJ .,\ (N2t4lQ´^DJ FQ 0ݷ2"DSAo}St< Q]m DiE G e>D0>[^ض|~u17So`~pSI1J-vJD²PwE%AL;D>Wa[KN 'ŕ< +6 ޷셜,>#-*4Vw"nyy`8bV(8/*M|x%`/w f;F<6ЊFyE6?k:Ԝk!x9 1Ɖ2-" (BoM!{(rz~r>38 0Ө9˒9 "E\QV!Tu@ <@[8%m4p, (EBO.^Ngy9J J 8Nڻ`/ y@Q]V|Q̮-\~D_#JrAEsEkP6ұyADQ,ݠ(lE~j`i@p9FZRZݡo(،AN{?*n φbt+ -O(|Fzprn0$r8upC8 OA9ϳ@cƙ i)+$ PAK:bb$LƒXz u W60d>wYbM?r(𽿒"2@TѻB~.PH2q,g ]1ͳȡ~ j[P&|yQQ=Y)jPloPP7ξ{2gy_1d1}ѽ$M*X8C:U`!}U__ ⋠X. s=^6e[@YxXl gϮ.jҧi&P?RakHB}G*drp?:$}o b22Da(Fn|\g64oP>VyO`F̃!ZX`%}O(=pDr5"PAu@}肊D GYʬ ^KMiF U聨{KG6 _P6 `ǭ\L.T DIHz#/*QoFcx!P.wDcj[=h pDT!Z ++x)]F hW(!|/|@fR[W^#>@m{CƽqHXodPIůs('_ t˪t{fpn+&E_ۉ_m atr/qwⳢ4ZPbDjEuwU Qz7]Xtt|&R "^Jz R[G?ZXLYAmVZi '= P|x9Bhmgp/o-Ej.?ӽ_.6] +@0[aECP[?'oiشBcSNQ׶(K̺9# B`hMQT׶3M"GSD6Q /WBQ\a:i`/T6RgݧO[8AgxWN!?9 "Ha3h pT+C V3m t3o 8yn ᷓz;b~imG*@=J>U"Qq%wKX,9ߎ_.nr@ gkQZXnyMP+>[~\^ =E"`յ_i>w/Qc X ŒZ6a] Gj} (yrׄ}!RQcw(mGÎf92{|v x^/h"D =qG.vATc>O f|97|)jMsi_sz/V|25y`\P(&d$gEiԜ䎙{樮c%gY ,49}!V}3udEi1b-%`ݭokg5Uj[rToz{5o?"{41D"/DS< F|if_7Q5dEn@nH3r|%Zΰ|m[TE ~6gW| "42En$`Ys`kܧ8>kHz\Psa4@$j 99WQ(-b%W ՕJ\G߇W-WDxx/ݻ4"g{b<EB&=2jL!{8/({RQB&k> -VB_7@J)4>Y@(!a Q;+)\+m|=PI^Gst_ת,Dݐ¬&ޗ!0?*CRTB>P%CۗBQZ۽``}݇W⼋([.m8?xX Z{"c2v0.S Dm~ ji5vj m/(uxT+5`&{;MpP+j! BI6V|z=( z{[/4?>5JsQƌAUL+u&}ޟMvy4{Bk>P U#J*F8g l4B<^#d%@N+Tsj@}(AJQZ^?l9ՊD+wW+Dݻ']f/(߱+K`o 8 <4c_.0sP@Q]Q?Veb`~&p%aYk75`hxGsi0Z# Ƙk`f D5uC;b)0ӘGo+hcbG`kc_i@Ta/@9Lcϳ!j/yA/80_f-_ |7 D;QAP8 *f'_@ ${_y@+B`n}>zݔ 4 "M gq/,sՋj9nS\ 1uc "Q-0U[D=Ub<uJN4*x/8FC5}8 w8nLc~f(K GY`/{hJ+bT kkhP`ۓrPDa:}!`TiA G.cn8uՊ좞)\X (-EC'P:ؕQbDғ *s9.ă:Fa? 74Dj'"sRӐ,GߖQ(O@HÊ4n(t9Xpn~b-U[p x@Gf!±χ({ل(!a/pnX6IpN7TlG}(0"lC,FTg.Vx HZ/Vebĥ.# I (҈ibZz5 @> |(_) XNGi5|E}r@1 s<`%E˺*CpzAP0TDZVN} *jEN+*D/ wVIFQE*3%LH+{1GQ 0ݷ2̝]GU2Bfu "`zc-=uXXGnzT/D9-^ {al4 }^>ڒ5#c$4fD6`bi=9LT%]Ƃ׵84m coŧlᦒBV ((ϞHtn^h*,, gSPe!*) {?GԖ"( \hΕg`[BN{g+j;Z`|\0ww`F1+hCk&ʂ >{1_0070k1 "Qc^ѵyFϚ({k!_SQ\ߚCs{D-{d2#!  49µ0L4j:X S( ![$i@>%`B>Q~ZP/FvUت)icY|>=B)BO.^Ngy9J J p0w__`"gr,٭0][8dQm3N}G({}}#@aF.zHn/ADQ(ˑ19nPt{2e{^se_H]J6oPޏDq[5DDCS63J#^\=-8upC 8@Mƙ,.#U  _h6P¼_`̕E/3f,g.+?[̺GnWPe dj˷61`!?[슱o܎G3+B{GYD_gqA!rzGHKKAA8 ,Ai|v(+Y!rL_t)e" n"ړAB1nop0bӂWV9ߺ6l>0d./_ B8I @Q{DJmi=#" u9sɆ5uHw ׂ!NY.:(We/?_`V|Q^%?pefk@Qz+/BO}*W(BT)T$lpۀ?P٧\v)b"cϨ򁻊]unI F!qK L>p T D$~xbƞQ1>tgC-hvyd.p$EOكnlsWu@Y\{G#hJ%E RjJ6b~1٠6x "?Dz˕ OZ(~Di=B+/n{p۫S{K-!?yQ;>p=@+>+N5~ZPbZbm"z*(Pj va}!(/((y{5ǜz*K9.07(C@)31mJ3 'ʡo/]" ƶ*BpR t +@0.@YB(/)'Vhlj݉ ٶo9>LE5FaS=X1Bc" IK +!OҖ`/Sysx9<_>PQfPϾKMMwB?ՊnٺF 0_.p%@c{,. 6)lg:+ [h9jDM9X=ipmgh B+V軭[Ҳ2u˳ooZ٢px_z 5%\=k" p;߆D xrVBC A[!}>X_>@|!ٶ_>0//9}+^Pb/ A_xb]]a(\EiԜ䎙{Q]JϾ^6>۳ZǭC0Xoz @AQ30c5} •@[gxg5Uj[rT-w±"lb.92EpDS/Qjj(_>0 _>`uUxTPoUym m `CD/ڶeLQZ0glxzϗ \(Y/v#ˢ%^E>u٩LoT2 }.+n Ml+(J@+J%@٣C3%X U\t/½.簈BS%G>ޡ[w( 2ƶ!Pc ]#ht~AqU*LqZ b%+|L|įd|\mAS~ j0͵" !ˊI^Gst_ת,Dzۚbg{_RTp a&Jݲ B"PB>P%CۗBQZ۽՚C+BPqu\mǸzl. zm?Pt`CVD)j ?Ll06=_a{C@8J10P %Xi\v& cnli@tW6v1视VM?'=Y?2jl^u@-Ta߷(uO?`(+|!?/}Y #`{1tN5@Jɭ90 3/D%r!ДŪs(AJ֢qnz D` n]y ^~we+yK+rU<_q]x;}kAH1h1|f̜:>bdWԩRe`h <7<;&Fk04yr#94-wc503FQECP 1mєiL7l1p#ů RC`15} yA `츅ݔg *7U} wHbzj֊ =;B0Zsei>`@iPLcQ T|xEsqEsړ4`\4c70׫G%\A8nyw/pADx*f'P\5v lP "#J.M@L8k 䎯:^bYfAs܀/0cXGc:3QӽCikq/ " iTT5 ؃5NiPX6`~Q`mq{>Ǹ8nLc~f("Qxy)Q~ջ?/@Se3 khP`ۓrPDa:}!`TiA uw#8@0NaDp0gJ{  <Nr5t+Ĉ'ATv_.@r(;h"е;CdNU bR" /iX \jz]w8`U¹ 8BTny{ ,(\h/.>2C@E }>lF&D 3iet A8D>fpAޅ qŃpz4E"x|+,< Ae2;Nj%+{Ի3<!Wx偌]& \x(_) XNGi5>n9,KuT(zo ^XDN+T>5"`%W..,g@}0@]D z1GET uLsg1Ao}St< Q]m DiE %g 74Zn F@TDsBVaaY`(>zEn- QMY8lAFQTBHt</xrث >[Qc܉_gQ ;Z<r!` Zw(AaԘWtmn^h9;Q#چ;Aet^NoC %n*:Ⳏ runop_@ˍ_6r>38 0Ө9˒9 "E\QV!T5iЪzrq(` e}/Pjg Г|Y^N"vCm %Eh b~Q(r7 l( .m ffk ',m&oP\Z>ftlloQ#/g VƮ "lw#-t)_.@wxlFߠP gC1ckӧlfG>#~Q- z~J[p4`*/f]B\pUlobN; q!t<i'{'֋Q(OϵoPAtoPlJt\: WԂ/ۀݡ"yȟAp.H~ +Ey&*h2`q"4UPd@ش3$$xe^-h}g D9Y"]V~uӏ |$2y"*]!?Lo($mb*gB ~ "x+`Lg#CAԶPVyLQgCnxq@ؓ >ώ`%+D=%l@Ua٨R /qX55[A ]^ XA|{<l>W%v19 $S.U8ӯހMiKUT6E(aw̩B&'|~!/r7xee. P ܶFmiܕ4@18r}#ʭ >,BԵ>JPz >jE{₊D GYʬ ^KMiF U聨S:G6 _P6 `ǭ\L.T DIZF(7#1<(ۂlAG1^t tk&`˽|[]rr-D)]F hW(!|/|@fRワ˻@(_T0n/`#4~ ,[D~"@~ J{ݲwi w@8 F ( |w~@+>+N{4"}gh- V+bB ׻0¢;!(ێ*(y"`UG]f?ec}2e`F>!C/6^oabC9 "P 8CDⷝ*BpR t ~'N^)_@۔ʢBI.Ѻ&Af]TNgƦZw"#^QmCߎ٣5FaS]X1BcS>۔|MiDWSU=㠴%*- tO~ZӸ9 _.ur`3(gߥ&ΦOjEuq~&(B~lEa3f lP'`%:A/ !J-Xh8C)" MA6P=6l~;.`#&@{3R_Qe(fJ>U"Qq%wKX,9ߎ_.nr@ gkQZXnyMP+>[~\0Q;lOruxE@9@Ԙi36C9-V80cm $'`MXpnm9H|xl4  %_x\5a_H4B(T}pES^gfYX, jr{|v x^/-2n#: s>^X_.mkXl`m_.sC_./4|1b*CQz CD!<;Cc`6\EX{wQ(r.(\P.drm(CRG#"ʽ₨w8JVؒ/PZw4: ݈Q. z a Q;+)\+m|=P+F6 t_ת,Dzۚbg{_RTp a&Jݲ B"PB>P%CۗBQZ۽``}݇W,Vow7<yZDdH<`>\!:@:\G(0kxô}&`iu^Pt`CVD)j?Llfwx0ݽ %WԘC(l.{Q 14_]mi~}k `%1N+VM?'=Y?i|}[GRU3Gq g/t@^!/i1y߽#@%oGJV, c؋y(_.Uj&: Г[s `&B&`ᔕ|TbP!XuzE CD%y[u-NjEak_ rv2"vEJ~ +|*8/E|F5 b?(˻BZ/Ќ=̩C! FJvEBj[~=}'(w 6p5 `Xi hX$6c1(h0* b9no\0֯Z>X2;na7uJ YgЀ zɊ4!F^llݳ#5Wjc4OA10D4|5 xEsqEsړ4`}<4c70׫G%hAf$ z _.P1p?i2!a/m4ZvЃBʼnD||^ gq/,sՋj9nS\ 1ucV(^8D=‡Ӏ=**kmk`@҇Ӡ2 )7&Kmq(f뿻n.(6C_@E1|8 w8nLCF% H^A}Q~ջ?/@S\S1Г}@}̡u'"쉞UX)QaKSWԩpc7a:jE`vQϔLC! e(j78Հ#ʞ{YtnZ`0{-7~ni§]O3DT*!EY-+P2i`QG(-Å!}>lF&D 3p4Isąd@Q G38 Q`.ձ#'y/Nj=5T|ΆP&N*8s[ix4{e1- QkpkFů>Ükr>n9y9ߎ_0e]!qo ^*c9P@T֜^x"xⳜJbQ\}+v%LH+7ET uLD?UT y-?VXXr' X޻O.N 8_>Pv{L4셿_Vg(2-YC-n02vksgem3Z(+5HHcV[]Ltj F s#!4p9;iLU5y`,x]K ޯN0Q|J n*i \a@R݁쩈D²P}6 >[v"qDm( υ\y _5`/diWA|Ƹ vKanA0w! ΋Je=x^ u/xVv~uLjN4ЊFyE6?k:Ԝk!_2JN-GYr}k hKz !GH3}p- 0z, S( ![$i@>%`B>Q~ZZ @O.n| ت)icY|>=B)BO.^Ngy9J J s>Qp2+ЀWP_.Pw6ڊo3ٵT8\ބ x۰sju/ =T< =a@&(:|6X_.PWg<9 nr17p1 P| @cƙ,.#U  _h-P¼_`̕E/3f,g.+?[̺GnWPe dj˷61`!?[0&ȡ~ j[P&QQ=Y)jPloPP7ξiP|# JV{J+p4Bۼ8$EPrA[Ūq!̯`$odη!̦czs( K6b0 +:t{uOv'I*PnK`N2aӖ3yr7vo 42Da(Fn|\g64oP>VyO`F̃!ZX`%}O(=pDr5"PAu=EqAE{,e|Agۥ]*@ԩ?#qx/(Fy0C| >k2X|]*7`^of5<oFcx!P.wDcj[=+֜M{;/T!Z ++x)]F Z`F 9{2C:/ _~2󂐮 z0#֡Cz@Yߟb| D2޶*BpRzg@Nw'^E/mJ{eѻ (pN4DEtfjlZu'kW%fݜ!0{&(tkz=fb}ThlzӰ)킨 y yDwrxoqsſ\PQfPϾKMMwB?ՊnL\ P8 f @ ٠NJu^PB0o+*Zα5"p`S-VD\%&Њ1x$zo+6l~;.`#&@{@6pȯ2 n3 %n*ANU~%,Ŝo/ 79m೵(-]as̕Zl_eS$\]kq3 s*@Ԙi3غX= TM0cm $'`MXpnm9H|ڸA3 R.P{ʏ\ZrV!PR> |)3,Vd,m506$Lz| t>4.vATc>|ٶ5` 5`|@\ZĜދ 1G_/T$uvup}#AQs;f g.6>۳M` KߐA&<'+H6Ch)3v7?`:{nm~ֿ`jݑߺj ~ jE1y 5 ڶ7pR&|1=a CD_.0Ꮺުṫ_35@hۖ1`FiBMY>_H2@1zQז[ X-)\-(B'ׂVⳆԮU1F^!3{ȱ▀Ķ"B. +bn-LC}V2Bk%WDV8_."Z,ܽ;LI (r/.(\9aL-zeԘBj4p$_P@UD]\GX ;yxe+Y0WCД 8软(.3 D`sHBH;,to1{,Dzۚbg{_RTp a&Jݲ B"PB>P%CۗBQZ(\iK\i jI\t_7y X=i 0yt@dLÅ~R[Vh[}N{eY0LgaVžNw~OY6BQ`/l. 6=?a{C@8J'WXA)u.tP QsoKѵߖǼ' V^ǠD:fZp;4c dl{/jl\=$0|}pBm2F݋>T9PY X5b! hBHs=5f!\a{偨dQQ6P!XB5fQ mֵ8k400Xp5[WD9_vEJ~ +*\[n"J^;}kAH1_.{rSB@}KLÔ0_".{`8o6A=y`Xi hX$6c1(h0* b9n  H>iLVb>`hk6Df4椵'iy in`& WJ3|wH3 "\b~|eA悐0ضƎ_{qRAǃ `Z! D"L>/|8?"˂=W6+0y Ac:3QӽCikq:748{{PUTP` :AecRj`mq{>ǻt{RzPAm&©*{{GY`/Lm+95(B9TD= >e04 l u:N8(q &?Yg%Ɋ ҝע+ (*zd o8mPOkqX}}D#߻myo a?m4L]O3ET*!E]GߖP@ÊPsoml5L!T9;݁s!mh> ^h \{k_9}Bg>9ʵ0Lbvm'h @u7p<_>P\Z>f}yA<Q}9CVnPt"G?5~7+iw#-t)/;@-LR/( Ũ4>e3)\}3 )(-P¦NVB~cuQ q1\yۆXRB\=g %5sm..H~ Ǹ}?&o)3PAqt ޑ*CфM^.6-F m,4%"}&o̔EY~ |WPe_p25zWs˷oSP8 UȽȡ~ j[P&\਋Z)jP|miio0}`d1ld1ۧ$ނ-}Ur8tU`!rA[Ū_o ՛"(6+Ȝoώ.?e.<,am@.jҽh=~"ô;#0w,B&Oe!^ @nzk )|v 2/0S< 0P䀧|@@M5v@`èr=f!@4w2pdEqLWӭ9_nzT(S X 1-.k^qH?|$E"Լ/˼@~TzA5|6cxAY%Ƞm~ Q[bj *$ݞۻ:E#Sp~ssvNcx%~hkE _0؄cAk1mD̃#f8LtG J^ͱ^lJ@ѥ46>`V;(S@)31:rh5VPVP|(x9CLerM *Rp̵إ,*W{;݌rs;pW "G3a4>hކ(pNfb{ThlMy,pJ; ZB^|e0Sfu1qr@E#?B|]jlVtK-F`Fr w,]6)lR :c*y/Xh8SSN "M3A8>0s6g OO} {{@6pȷ2TJ>U"Sq%XsEhCjYi0ys0W~_cؓ?D`\~qf-b`V(t,a@Ha-NNXpnh1>?xxl4 %/_/$c!PR}]7@2bEbb 3|oC"/_T|v"`yk 2bD9rm[#kmo[r_bIŊL1G1/9"S "\13w09X qiC= ouu EouɊ ;cdr 6?`V?]{6.ksVr `/Ԋ >RSC)9`"_0Ur]UB=Zi- G1·mS#-RX3 <[zϗ 2_.(E/p\-(R'[Rfb.Bf| NJ.ĶxB[F*f )<;ͻ> (Φ-Gba/P Kq+ l-n(SR#it~AqU0@Z b#+,|\ %js>oe#oF[{2|m_ eiP+2m 77pEsܾq,,Df5A׶_RTpT03n)ơj@Ym_f Emή{5B``U#52X}R_>y/ɐR{pTfV62Nlηl X[:PEHT倊Lt@^FJV,  -Z7\aBRɭ903 3gD#r!ДCQbfsdE SD#kQ87pzSfWAeܺrAd 7x*mYlV^;VqAQq)azۏS؂Z(H4[b)T2`h D )Ĩ\b f #y r)Hl0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0E=b _*Z~ev܂7:A#s ل3h_lu"sqK]Z@gG ]k,{h.),lr !6L]Q k;| ʡin`f]3|p s2D/rADrt42Art42Ar@qn0 {O}r#tvp qQ+d^Hg/ o)N'muĺfAs܀f`_D>֪336(aCmX6I؜nq ė㶏P8>È "W pz4E"xPxCP&N.8uҹ-H%k 74\a@|%LB6a; ǩWPfqerW8~薅\hΕg`ݷ셜,>#-|k+Zl[/LGڞ~xZWB9FT۩ s#J8y@+R-] mcp\ ̣f}+KDC]$y@vo(|5lЪzrbȮ {0ڀC ~JsMq 0g6ū(S`: ]f(rE]pwi-U G̮-\roP +:w8/ *+XGŒ\ܽ߀2xA<Q}9CVnPt"G?5~7+ku_ m._}B?*2n ׆bt+2ݿ§l Xփ(-P¦NVB~]۬W 932Ώ/ '6Œ}]B \LQ+R Zox#U  $v|ZQXkf 06o̔EY~ |WPeA )Lm @LAeD[Qb879@mʄgu"_3E  -] ~?[4 ># FVs/}J-زiW9+cHQ /ĸU5[-bS1= _Њ] K06 AGWt~5P?Ra띑HQu;rT!'\:$݌r>k/Pa.(>}QO3w AC} GF#Pfe/gؠl_xBW )8Eq@E{.et>CK F*hqKm9:z@(|0bV yZT L$@v@`èr=f!@4w2pdEq^Ol~9e }"rT92OR6:r`R<0 9qd)5@|(2/i!] _>q[}AQ&gY]DE@vؓe{i X]v@7qKM F篹H'x~hkEթOF׮_( jmb9Хz$Rka]Yt.++RP#%oXR/6\%} Rv0)ɔEmx9v g{~qt(ˡמ_DLerM *Rp̵إ,*W{;N^)/@tJBIk@C+VCT~Pc Nö+n)0{>ö}TYv@z<$>" y`0;̼b^G#Z w SFy> _>J) 'A6)lm#;Yi7Aŗs{M))צ}v T`wN۰9Sxz2V{GLs´#EEyrPPz=٭(R/`.|/ /Ըe2u7AxmQ8nooW}_g9ph1fu+}X}@_H`m $'`O'87[~p rSu`xoGh1>߷!`v !^Ф/P0qGp; ȱxGhBm_sC1S44|@,X)F(/Tduvur}#AQs;f6Gu+_;z0m(}g-ζb՗mٞ>YD9~gbL`sʕkO|?`jݑ__[ZG ff@rL\r@|[r^%tKWa(a CD1f_7_.@ @Ӿg4_+-UӤVBN/9>7;),^KVAJȢz_un^E >uZCj׌r@[̅ѰWtoX%VP(\17Na}@a)Ʊ`65|h-VnLIU0"T)KrCW\9a{nP&t@-EL sG}Dkhq4HL|rlS!ldpq~)2|m_ eiP+2m 77pEsܾq,,D0w j-("2)u.HLC %o.!ھb]Wkuz^}]g}j8%[zl>y/FDz-+>mL'*s9ke(o66m(un) 5=/`("b/xRj[XS`> R(i\|0AoPs{TѵKz `#0(9u`, vw 2q̙/;r@pWZhB[WPU3,Gqu{:ExE90!^(irjoh#5_.ן7\r F5/p1'`"s ̂AA;"SMݡ(yL6X9lml-HMm/@9c5/1~U: `ouFV =Ս^'+0X9:?wckE)XtPi=hrcCD,bt^+2 yIkOzs;()vpT@ L=@3a0/ LPX&_( {Zvȴ\}>X BʼnD|tVG<@ |zQm64 aj+ ڂ)Zuf{) tn$ yp=AU@5|=h[+ڔ{8 *`R}0TG`mq[b4`9]7Dۮ ̃K cAm[TNU)vy/8RC6~@M@UzSX ݲ/|DPU8AuE _ / BQ#3TZ #}% Esl4It ė1g@ЌvfOvx HZ/*"!L\&pt;^p>G  _"ro#еjls:Xj$9Ex `]kWT얈b|/0bk,(ivPګp'TlgRYIL ־E*RPh)(aZ/F{% #Q 0ݷ2LϮ# b j y[G 0O @m@(W,VHKztܭkq7Oq_>@梥{@ 7`a/4l/|<\F%k Fxm3Z)-5Hc6[]tj F v32sLU҅/ ^`¶- P OɿM% /WXE7@t^h&l`|8 >.LQQ*P1lA>h υ\y _}k^3WAr8|lGp^U N/x%`/cD_0070[1Zk!ЊFyEצBq GϚGjN ص);g;r1Ɖ2pE!׷&=Zr='?P3r>3q8VaQs,K!v$!. <|%`B>f Z @O.:@< ت)icYpU>B\4 0ׄgV/EVRTP7"_>wWx_>+D .5\n7ٵ{2}L0^s㑨Ҡ|(6c@x6 =pEIg+pSwHrH]J34436mTd+ :WdZN>PmaS+W!?.mE+_`GobI;>G3t4|XKTP~Q2cOߥS{EQwtA{'q G)qwg2@z&\-U1;q;\P,3< >hCl < xc+֜M/9:]LBBBy >K~c~M^ 3EH-^/n` "wgvdP_s'@%bvVa /5\x0Sy'>p;>p=@+^+N3}%6[5h- 힃 ]J"; 0ʢ;})(gcI@ctAѥ6.0ؘ)ɔEmx9v g{~qt?PC/x=LCů@E ]ʢrE2;{R9_.@pJu >@C+VCT~Ʀ 5x$JwE7=Z#tgۺk3=*46Uc<)TT#;|t9\mLc n+'m؜)<<>V{GLs´#EEyrP{[E%P`8_b]vp3Kz<֢lXny&- G/{Y>`vzW]/WZk@nE@֭Pbu,a@Ha-NNXn9}^xڸE+G (?FpMGm`9\)ff]({\-0#}&`"5i;t\J.!.h #h۲|`~B̹Si.-@,X\0}!*2:P> 93w6Gu+_kk=m(}g-ζb՗mٞ>YD9~gbL`sfе|j]Ň-9P;] ~{ak6"{< rL\^弮K薮hu2Qra CD!̾wȻF4P<VZf9xK|9Q۶),^K/Ȣz_uyn`Ղi"{r x!k@[̅ѰWorNl+G(zBFx 󸧰.PElqw\XMgxh-Vv93_ \-e Bj}82/(}*y]| h\uG ;\oy@|K)|6Xx0 QoVRVdZ!-oE]I+RĘ+v`` :]{Czۚbk/)R`*8?*SR4@P(ҡL}ZT:[VǸzl.<_.ɐR{pTfV6 y-j\a{&`m~׹_g,?5Lev+ E(@)mc\v1L^6@t|XOlf1NU381~Nz?z# -6:֕*G8g{ź=p͢ ^f w^(irj@3(H4[b)T2 2SZݕ ?nLyU__.-`hr#94_# Ƙk` |Dj w@1 ƧԊSKA8zV(Gh^J r X/~_.paV̎[lPhdna50Sh_lÑ9ĸ%ǮW~lhݳ#5W= G_ PSn0CD,bt^+2 yIkOzs;rACӌ^ 8*g p ~@4Ј*gD/NBL|`h _2AilP#ZvH\C\ Y'd [I[p/.ڀC*LS#,Vڂ)Zuf{) tn$ yp=AU@\m=yUH/3P06=wA =,Ǹ鶫RWgy P+2薪LӀ=h.036~@<2WTʲ5(R9TD= >e04 l m6p؍`ZQ9]3%PH~álŇu"EQ Tr9/ 4b!"R|P>6(afp> l9B#h#.4s{r#ԥXorZ]㞚TEC@8LvtiΕۇ"a\n"y RLK|1]M-p!~QRnOGmk.=n9\PÜog ̺ JZ:{*T03: h9yD"#fBU@I>T&Z/f J֋^IĈڿ|}+:-0o uCW[Q|ZabSPȱ(W,VH-0| a_(Zzpfزi%UnmjqQާl0d1~o̴Vd k|K80 _3xb)HH32sLU5\0m[(GAT󵅛J_n >R݁#ЀMXXV7ʷSДnT-E(sy@d:WmevrUhh1z"n9|`zw`>b6#8/*M||1NM/Qt'l)M6Ÿ5Ԝkq *SoCTt^N!eEZ(r"S_jyBg>9ʵ0L# FVs/}J-زiW9+cHQ /qX5zHa%Ė/bS1=zÒ `_>B8Χ@Ѧ{D JmiwF"E#XRL0i˙_._>pP8u0m`9Q 3/(} >k\,||/RԳ^FW(]\E 9@EG]l>~zNi{FU>Ѧ >`8 p~L![<3|j9[Ał=#Нp 9ʶ9si9Ƌ 2 nrsWu@E\w\wo@|JwH/c~M^ 3EH-^/n` "wg# 5@M+4;D{<^Q}XtsH٣5>Nz X1ۣBcS>nJf9S+*FDwry`_Tk9R3(gߥ&ΦOjE9V&Zȃk Lc Fp܆͙Ólw=G Lk8R[T* J>U"Sq%Xs_>@+܌Ҡm൵(-]as̕Gp~fwwr <[TL֭Pbu,a@Ha-NNXn9}^xڸŽ0.HG (?FpMhQ[@QHQm^`ŊfoC"<\r@n!6߱ĕV]B]@ŻGжeC-/sC!+9@\ZrXw)F(`BTduvur}#AQs;fm6V֊zPl[(km1Ī/}C۲=i}"<`s14= ʕk޹ZMպz[r4 /`/y@kfq\s dBķmSB Gjj(/B}؏*y Ԯ*!O !_+-Ur%a(m[THmV%L_ydыrz+9,.^E Z?{+ZCj׈* a;pX%VP(y sCu` W챁#gqwbZQl:|@kr 0%/ș_x>Pr\n(SR#it~AqU0@㚯8FVL|3[Ma>6SE p}E,XZivheE]I+RĘ+v`` :]GYmMPk1E)0)L[pAwhTB{KH/3Xg՚z0 D 0V 4oRat Wx=0SGж 0}eY 0L{q:;\!QQ_>P)G(50<-JWo" aޠ8Kk Ǽ' 6l1(3*=Ah@@e?'=y3GǵBk&uJ`(+یG3Eyo(irvGU?ÈKVI+T.r&&@On)i%W)=\,>ʆ`ԡ|{WEG]Ѧ}hԶۢ|^&vAfJk2Ǎ)Ĩ\b f /8N0R``fGT`h}Sq`|<<:;l 1r[ *P^J rǹ)j7_>0?\ì~MyNj`6! [{c*W/r׫?V4ّEך+ ڣ(G) ?f9@0D4r-F "SWcn60F%/D94 LՀ~B 8 2 ~@4Ј*gD/NBL| $̈rӐr#tvp qQ+d^Hg/ o)N'muĺfAs4Or ATc:3SӽCmkq4<8{{PU4Phmk`@rAecRjˌrc4s(&=wA =,Ǹ鶫Rz@SUd]A#u1,Lmxd:mx6]P1v)*~_w"ʞ ؄E@A Up6uE݈N8}?6T+*zd o8mP;(GbDғ ن0Јrߖ>~`ibOv`g,JTCWm&<Ո򀐇y`@ Ӵ+JX758Y-G5PTXQgp_EPh)>S(cUz03hmX6I؜nq ė㶏P8>È "W ]{r#ԥX"ip{j>PxC6_eFDw0|tn "6G"Ŵ _Gk\%@-EDpB(C3t^h&,, ǩWPfqerW8lA>h υ\y _}k^3WA|lGp^U N/x%`/cD_0070[1Zk!ЊFyEצBq GϚGjN ص);g;r1Ɖ2pE!y}k4fzN~F)H}f>cp\ ̣f}+KZ;mEfP ZG~Z#KVГFPDz/ӈ L!kB#x-/'"/(L'r93uݥFڭ01priE{ :w8/T1W\~#n({G7(J:[^xE Ε灾iKiA#pFߠЦ폊Lq[_'LCS6G>#ʑ^?-l4`*Fpxl._!.fpF_>?=q׹l}}fRE j{2ky_U cE/{[e" sV')#b*Vg|KތA ]^ @|{vt )t?ua]/[CFDwQÒg746VHQu;rT!0m9v=< =cve]LP| o;QG@|<ǷxL}ZO`<5eVec@HQu6r}_8Bi}jE rw⁊L? ~.9 PW33tk&9QP`j큐뮐mOR6:?UH1M 3EH{_˽@}nՍ2mlwgvdP_sxgO~@%bvVa /u]x'0S|OnJf9>կS@Tz_8L_ KHT@E#?B|]jlVtK}[|7r SAN#lR :G8ow)D o/Xh8SS^ "hp,A>2w[h{AJ__/$c!PR}pŧ6c0bEbb s ߷!`~_ t\߱ 5_= Xy`۲ֈ5<0_F 4ͥ5 XqԈ2509X ӆg{B!۲=ib9`s<‹)s\Yu@+i<)j y]] >{}Vy9vP׈@|[r^0LetB1 5<`uc?F @ JK,o/g?jy@BJm0iBM{ebY\k7.s`kHܧ8^kH_b0 ~+ۊr ޲@+><\G"a)c`6}_"Zww^(r^ CW\9a{nP&u@-b82/(}*x ^uG  @|K)|}68{BB-fz͵"S6YQnW"kՍ2 KGYmMPk1EETUTHL[pA UdjV(y{u eP>"gq"m>cKhW//R{pTfV6o0= >0m 0{,?~2ӀyyQ=JWo"ȖLQs{TѵKc=a{ǜ:n0 Tu̴"Pwh9Ajl~9/Z]uA-4a߷GJU <9i1,5<@߽#@#{+~ P t3c؋y(/*{R41zrkNLC(LehdQQ6v(\n3s(AF֢qn{4 [~.Ad 7x*mYlevoY@kM<.EF}kA b)l/E)U/fIwQh佷0unuڀs _ bxh RhE Gk׈2FŷQ[ {Ln PÜo_̺ JQlv L^hnPEBu @[s*60Doʅ;߻|D)L^0#ӽUL=Y̰eR~0o up!>Nzwak鉢{E:jto`IMUy a}_.(Zz(겵Kdزi%UnmZ>e! }f"SX[jǑl ;@L1>GBy#|deu-/ F/lB9jE\6So`pSIV Gj;P7pd: Cq?|\vUp;bDm(|D@ "ӹl,;_kF^3WA8|lGp^U N/x%`/cD_0070[1Zk!ЊF;x (?^l9t."LᨋBoM!{(2zN~n )H}f>cp\ ̣fY,)Q-ﳹlB֍򁂩#HadNI0MG i~>B ZG8oro+)R`*(#8eL'#B/(ꂻK=Ln7ٵK{,ڣm&׹{HT|(6c@x6 =p[ 3S\"ڀ+RpiKA7pFߠЦZ%(5}ۭ׆bt`w2j9}f>Rcx `HsiU/pxl._!.^8#//`Om؋%5zY8g|@HQn >}|BՍ{₊L G]l|AkK]zqt}M-{sf qx5\P*#*7@yXkT@|f\hG 6- **rdE{^Ol~9|:=L!}<rdҥ|mt=x@=7 ؃y6 ,vdP_~=מ|kP!zk>+wuc7q٢ `0:2!;.VVT^`th- 힃>5^T+epE 傂Ws,譒8f3?@)31:rhV(^+~(z73r(q LCů=@E {]ʢrW.?ӽ/pJPyF)E6(~N:-{شBc;Aǵm}+mh{# R`hMөm}Ts{ESTt8޲ F2)y@^0\PHϠ}8>~RwF0/r >Iy@ A['N2(a+*c5kELO\<6K4sz6l}f} {{@6pȷ2TJ>UnAHbη#/Z-E/wLPj~i.b*SQ3C׌rAEXgW7*9xDgM1.u_{z]0m(}g-)b-@6()aTӆREreuZQt>bZutG~}]oܫ`/|ԊRSCiQ5 jW}hVf9xK|9Q3·RjH= X3 <[zϗ 2 E/uxcZL(R'[Ne6A[l/"{ȱK@;(+P:@+F%@cG _t@_XξY Bڡu&y)bqV/`n!YmMPk1E)0)L[pA UdjV(y{u ePZ; EHAyWԴ6q~%[zHyrc@CQahV6l=iY=n{As;NY~6P_`(/TdJm c9L%OrEݳP(ƊO"ȖLQsϥϥWǜ:n0 Tu̴"Pwh9Ajl~_ -6U|m$0r}pBm@#t~7BVBe9H^#Eq4VsR&&@On)i%W)<,>ʆIxm4%@Tb{ОuW_.(hJ#\S1v+:߀}̡u'"쉞MX)QaKhSWpc7a:jE`vQϔC!)j@`W>#6^P;N7PjO`g,JTCWm&<Ջ2y`@ T-m2@Am:jq>ں7A*:"ʅ6ij9@i[XN #{لGBŒ/p> lUAVܟC`Sn4r< rMȃpz4E"xy\PQAe2LDw0|tn "/K/D Hxtc[_@ۈu{8ju{a-GyY}/L2zalPEBu @[s*6DŠr;+ DqwRE *3%L+ۏ#Q 0ԭ03l)* };(il5nՖ@VXbH@Dѽ`aBZ70\ C_>Pv{4셱e=;xhKz `)ϝ#603xR=$#-|k+ZL'n)Kx *@X4Q%̋rWB9FT۩ s#J8y@+R-f5zYHIנ2P}ct^N!8Q"(:/p/G{_ԋ2#)  |skayܬo`%`IbGM""\Q6!TO9`2@`N} ԛ)BO.^Nm%ro+)R`*ū(S`:6"]Z_.Pw6R|d#<1xG/*+XGŒ\ܽo#?67G#/g V视^se/ nE.t/36mTd+UE9՚^ )H-j= )(-P¦NVB~CCompF֋r;1L=a/AG/}<̮(#O#rE-xl_.P\*.H~ Ǹ})j[8ZPA덐w P4CAώ@1C8jKb/ z u [603d{Ţ %UeGh Sw0|@!iSP8 U[c8鞥Du%rET@|-5(6DN{{4w7>RE j{2ky_Q6Bo6l@UaqT)/1nƳM`%VoF؄.l s=;^/.<,am@.jҽh=~"ô;#0w,B&Oe!^ ./(St]8f#i9ny[Y\Mq?G` ka}\7Pz >jE =EqAE{.esWxߥS{EQo}@%#qxy)q{drA& >-U1o@`ר2=l[TT4ƋuكnrsOuz@E BBŔi|JZ}~h)BJr_:|{P/`V_Fy:@Y%ȠڃPמ|kP!zk>+wuc7q٢ `0:2!;.VVT^`tc-( jbjEu*Gz7]Yt] \~Kz-.aYGL}O, Doˡ[X=xQr(/_7iܢHbKYTevRN^)/9=݆ 8[E"شBcSN׶pH٣5>NX1ۣBcS>Z\ϩ]NiDWSU=㠶%*- T`ŊxoC"<L X/ж5hOŽ3淭97Ԍr}5|@\Z3bI]@e?jy`_.CRSCiQ5 jW}hvGr%a )|O,^KVAJȢzVr'`U)E E!-=X%VP(y sCu` W챁#gwwbZQl:\E/ g,ȩ/^yʅL=2ZL!> F ԊGRq_`#/^ (-GMa>6SE ph1@ԛl} C/+Mj=RĘuz_`` :V?0w j-("2)u.HLC %o.!ھb]Wkg)8V>!nzRaE_+( )7XzH`nYm[G(0[xTw"<׹UiŇj3+5rAEK: 0T$W=l.{l1\/\`}@q̹cAUL+D&wy_b㚯QI3,Gq g/t@^!F) `Z! D"L>{^xKq:i#~E >W6H:`kՙRj,z^"tF#x=h[+ڔ{8 *`RKOxusA3k*Ӏxw\N ں7A*:"ʅ6ij9@i[XN (A{لGBŒ/p> lUALGGqG}(.|R۟X=qX"ip{j.x( χ 2qr ;N:@G _"V@ x1]M-p/mD P|ˍYrV+"^y#S[/0.!.^P+Ae ؠ:(i'Tlཅ,vV⢵fѥT&Z/f J֋)W1G`[af2)RD?UT7@wP:jY¡-(>j)% Zz^QZ!-XRSU_.M/(ZzpfزьrAr%kj0 vHm֊La %k 74\a@|%LB6aaY`(>N"7.ST OeEy.4LʳM[BN -FOV6-)oA01h{k&ꢢy_.J^(Ljj;5;``n`cD 'hE Ō[/6?k:97`6To 9P'|\DQ\h7r/Kz_p#}r- 0 ,iCH B]$y@>+J&j}1i/L_G #*q hLwWx4wiE"g@Q]@,;lKU|R+:w8/cc- 3rqt< Q!+{G7(J:[^xE Ε4軑^|ڴQ)pk 6DƧԋr>e3EͱGz#~j[iU/pxl._!.6P 1L=a/AG/W/h e{_B2|6X/(Jjnq$`?cܾ-Ey-F `q;REy(СKg!%^ZЂ-r=w]b}Pۿ*ˈ2#E4ѻB~[ )L *ୀ1StR "Q27t}.z_kqA!r#K*RPݓ ^Lj"܋nx l@UaqT)/1nƳM`%VoF؄.l s=;^/.<,am@c}E pz~VHQu;rT!'׈2_t/w ɶw1(S\u\Au >7 <wX.#?Pfe/\Bz | >\=H!4P/S`?K1܀?Pڧ\R)b`Ϩ򁻊 ݒx'q G)qwg2@z&\-U1;q;\P,3< >h=HAʹxӶ>p^Ol~9:]LBBBy >KcW-/c]LRjܗsA|(2.9 B؃j6@YluY>PQDm=Bl/- ȴB&Sp~9[4F_#&"wUF>rכ5>PCnLztpE %oXR/6X%]oqt) o?e c}2e`F>!~[6^mkP7rPC/x=LCů@E ]ʢrW.?Ӎ/~шr:Sm8@QlcuZ!*3Pc M;D{<^Q}K>y7"f;ٶ.` @l Mjq=zWt>^!OU!O5 *- T xL!JJ|@ŗs{M))צ}v T;/ 3E)z;b|ޞ# )-%n*AIU~q%b]vp3K{ ^[Ҳ]cۛ'?/|{Hr/pP) y^GyO?09X wӆg{B!{A9HZJ= ʕkέ=jZu7G̯-wZG ff@Q9@.@|v!0L.@|䝎@0!f_7 _@ @Ӿg4_M rr·RjH glxz/Ad+)ȵkvV8/"Ѝ7G(rfޡ\{(*2[h1.4pd(5JsQ ƂaVM?'=YM2T EAߎL! sǻJ`(+یG3Eyo(ir0VGhZ%=PR&&@On)i%W)=\,>ʆ@3(H4[b)T2 0 m/SxoQ @_.p1'`"s ̂AA;"SMݡ(yL6X9lml-HM@9c5/~_.paV̎[<^'hdna50~ NVa1zɱՀ{~ڛse@{flP#ZvH\C\ Y'd [I[p/.E@7`W +`蘂}UgfJybmop y% T/AXЦiPX_.2 nsirn>N P{‰Дf\Xi7'{E39TD= >e04 l m6p؍`ZQ9]3%PH~álŇxj@`W>#n 4\冏6qgj'ؙ"KR.oKG(O5< aEXx7p#PUj-6r{8`U¹ 8-ֽ B TAT.4s3xVT>G(-c kCI!||D%UH:+p9\Hl*rQ ghs /\c3GgmZ>3R|d~f"SX[jǑl ;@L1>GBysv2򘪤k`,x]K PZфצ -T@rUtZǧ"2 ؄eu|8 >.LQQMYDQ[6 Q4Bt</5`/di ^[bDher8|lGp^U N/4K{# f;FpV0Zk@bY㑚xvmc;Ae C %n{DZG9:\3r#KG 9R@j@8+07X XR( !. <|%`B>F3a0<Fv!,#']8gx$Ro=x94_ Ho(#8`I-0\+DΌE]pwv+G̮-\dm3G#}}#@aF.޷#՗3`pEIg+pSwHF nE.t/>@ (5PLCS6Z{/30$maS+W!?4|cuQ q1|3v쉷 {f_W:_.`+#ڷh U4`5<`O܈r`/P\ϵ0 6(`Y|Z<4g@w"<MPd%bbt̐ƒX#ZЂ-r=w]b}Pۿ*ˌ#E4ѻB~[ )L *`W}lxP?s-W(_>਋Z)jP|miioPP7_ԍ=ർ/x(Y!r̽)`˦Dp_!G"(XH6@/Vߢ?Ro ՛"(6+Ȝoώ.?-3 K6b9  HEMwmO0w,B&O!F܁cŽk)N].:G?}Xg@|s,>p xO?`<<+ 0 ,J|Wz@Bhz_x(>P~Q2cOߥS{EQwtA%O6(>20SVdbL&Zbw?@vXgTy@|3O1zMos92"xѻAWӭ9_nxN(Sc뮐mOR6:X)~?`>r+)BJr._:xAHp{P/`V_Fy<8DT}o jZ]mӠB|Vn~o0痳ELat>R+J;>p=@+^+N3}%6[5h- 힃yxJw`*ؕEw+RP/:^QR/6X%]oqt) ۘ=ɈXLYA֡C@ZC9 2@1^~n|0PkE?Pe.`\;t#8z(r4\vqP[?'oyֻ6`]d֌(WT%ݜ{# R`hMөm}TswE)TT#;|t9\m`vzW]/WZȃ1{Y.(3m[BчPBxk!䇵8׾yj}ゔP(ycׄ}!R,+>ی{?D9$>p;߆D xq.Bl c{+>L X/mk蝑0m!P) _4\ ]xAe? _.b]`\EyԜ䎙{s}g>0m(}g-)b-@6(6)bL`sfе|j\Uwx;] ~{@#ro1D"m۹Ô2J!!f_7 _@ @Ӿg4_+-Ur%ܞ=B3`>Rç,^K/ȢzVrY\1W ?ߋ>Cj׈* a;pX%VP(y sCu` W챁#gqwbZQl:|@7 g,ș_x>Pr\n(SR#it8}@xdhqZ b#+r&-٦2{!=z1 ph1@ԛl҄Bڡu&y)bqV/`n.#¬&K Of-{ ;4Z=P%CۗBQ[^jMPTwHM+m} X]i 0\y:\"z+C*3ut mxӉ\Zop X[(uno@Uar③0E!QQ_>P)G({C@8Jh10P %.#[62Eq D.L{b{m:efؠcC> BOemGZl^u@-4ǭ+PU3,Gq g/t@^!f@ьg%u(UQhdWR*~q6ZgǍ)Ĩ\b f /8N0R``fGT`h}Sq`|<<:;l 1r[ *P^J rǹ)j7_>0?\ì~MyNj`6! [{bc׫?V4ّEך+ c=y=r !6L]Q k۞mQM3v3Sz5ਤqȴ 4<!Ӏ,/.BL|87̽jy`eH\C\ Y'd [I[p/.E@yMT#,V rfkՙRj,z^"tE#=h[+ڔ{8 *`R3_faC1 j4`9]7N'SUd]A#uwiRGS-bMP`s}݉8*{'`:})`TiA mw#8@0NaLr0gJ桐CxdJv#1zIlCho a?m4L]O3ET*!E]GߖPjy@Êں7A*:"ʅ8|3Ќr@(}d@KB!||d/HH/9}`$ɜM8r¶P8>C3]h9R۟X=qX"ip{j>PxCP&N.ԹAtI (1lH)8{/}LW` \rFŷQ[ {Ln9\PÜog ̺ JZ:{*T 3kBuzJښSG =\`V.DK.f,Tʄ[fcJ F`[af2)RD?UT7@wP:jY¡+/, zc-=Qt(iBZ70| a_(Zzpfز| }^9ڒ^5;}C LkEl# #@nu1ө7-vbZ}0-#>G T%]3cZ_^ضrԊ&,6mէ|mᦒ—+bw?>t^h&,, ǩWPfqerh'ڲQ<Ds&Xv~a{!'H _ڊ'B+#\RyVi.8GPvjv~luLjڢ kŌ[/6?k:97`6To 9PW @i u4C@oF jyBg>9ʵ0L>0#߯c@xD1rݠ(lE~jxn)8WֈFZR_.@wЈr7(i"S\@|m(F "r|5PmaS+W!?4|cuQ q1|3v쉻e{AG#luz_Z1F#h n_>@Q<L.H~ Ǹ})j[8Z}8St^HAhB&c/ɟ#gQ-+g,z 4 }&o̔EYn#7TYf)Lm @La(gB "c<鞥D e#u"_3E 2bFT*RPݓ ^}r FVs/}+߂-}Ur8vT)dh-#[-bSz:o~h)BJr_:|{P/`V_Fyܻ<8˕ zPמ|-KKł;2_`0:2O\yw\x:/]XJl»Z;ZQt]j( `WAןW_.((y{5ǒ O_ RN`V1S+S@)31:rhV(^+~& /_.unp.Vz_> *##^0\PHϠ}8>~kdz@&WTN!?~r"Ha3h T%s%@ŗs{M))צ}v |T;/p܆͙ό[1~oUyC]@ۧJPRUd*_bη#/Z-{@\^ wD/WZ|WA["(3mf(#j#,X ?  햃<GF R.PNjrׄ}!R,+>݌}{?D9$ >;߆D xy]@> 2bDm#pH޲*m/o[3sn)jfĒދL1G/ A_3b]`\EyԜ䎙{QJ޳^X.9` ď3 G /' v0+Et:{nmVS@ǖM(n={A#e߁rL\3m۹Ô2fGc"j3Fa4 yk $Y9_ΰԌrmk`>RϧmV%LoydыrHhI0j@=O]p֐\Psa423V+ۊr ޲@+><\G"a)0/x27G(rFCW\{(*2[h1.4pd_P@Uʆz0E{q"@&/8?" 8۬0PpTDO&)ZUp6uEވq'>v)VTfJoY! j pX9W>#6^P;N{Z е;SdIU bR~m ^^< x6\BG W8BT[&9k q3ЈP 3B8^6ᑐ0#\4ǶO,$sU 鞃Ȋmv 0)}#0 ҼIŊн@,=-e^ ;<Jul/K/D Hxtc[_@ۈu{8ju{a-GyY}/L2zalPEBu @[s*6D_ʅ;߻|D)L^0#Sl?bP\Xaf2)RD?n)BQ]m DiE~OA Zz^QnrHP*/D9#ua/܀0l4\gmZ>3R|d~f"SX[jǑl ;@L `[Fc偱u-/ F/lB9jE\6So`pSIV Gj;Pt:/4` +~(z32EE94eaqDm(|D@ "ӹl,;րgBxmE vq@X4Q^#J^(Lj%3q8VaQs,Kw~ࢋD3(gsE ؄P#f?倂3HadNI0s[HL!zrro+i|[ISA P_>_tһ+x <<<g uݥ_k|ɥO6ܽox$||(6c Q(Q09nPt{2e{^se/ nE.t/36mTd+ Ũ4>e3EͱGzpZmaS+W!?\ͺ~_.<\?|{m^,U!.ă_`+#ڷh n{ay 3uT/ 36\q$`?cܾ-E):U|m"w P4CAtK(a^X9seKE-L0߲)'޳}}ו-Gn+ /8RD+䇹 IY"<}P "Qr2G]DLQkCLؼQ-3}`d]~{9^Ѧ/VȠ6/=I,$~_.qX5G -!~0y啀 dη]~J/ZXGPlň06 AGWt~5P?Ra띑HQu;rT!'׈2_t/g [ȋ22Ůa&(>r߷܀0Vi~b95@ GF~8pWG@@Lhq/ U&qΌ|cx @o Ƌ>myE?ݚ Gu@EBBBy >K v+T#!]49!˷R/9.5p6} R1F0/r w,]6)lR :ًBZsQ\W *c5kELOy]&<6K4cn+N۰9S`#&9aZ"ߢc&=樮c%g^LJY EsJj0bc 2i}"4`s10csfе߹ YMպz-9Pf|46@MYs|`P7PD۶s)e6bG 4:ahq7@FaTP<660!W Ƕ1̩{Z!6Q>MY{42E^[n%`Ys`k\ go%>kH F>PQvDk.h+Y!`/`{L ~%jsR&w7u\H QoVRQOm( 7ɫc׵23K(¬&s"jL@tﮬ D[pATB{,KH/3XgQZӖ^.Դ6@8XMZ/qyC2<`>\!:eGMD+5ô,L1,b_v~l݅_`3]/:=a{C@8V 0P %X^6& c4?]4>5JsQƌaVM?'=YMv{|]G?{' 429{7=py`{L {et~7BVBe9H/6}e4W )>MLܚS3J0S2@T((Mi;E.V[D 2DTs(sf&WA|ueHpo+T.X XZyECkMD"~ y4c_0sP@Q]Q^Veb`h |Lֿ7Lp F5Ɯp;Eb1v"QMݡ(h4by@,|6k v7y!P0Ә8w0D=lsoPh4q ޔ-fϠ;AɊ4!]/9v`觽0W=  H{ZӘ{Z !AC1:/l"s1*/ր2@CӌL^ 8*g h *2 gD4y@ŬcI PB_`P"#J\C\@q !n;RNxeU/ ;L_p%`\ņWD[j`3Jip^lUEAXPiPXz rc4s(&=wA =ǽtZo^`1Mփ j3AnK ; ++_(Д/+bW4yE>PpTDO*t, BҀ%@i\J28q &cY0 Q-Ilj@`WFKOnto 6qgj'"sRӐ,oK(L aEXx7pEE W(踭3Js?@<ֽ B TA.4/Gf!±χ({ل(!a/@ |\` $s6U(rQ G38 y@h{!,Hܣ,pz4E"xNzwak鉬{E:z G痩*_ rXG/-^ {alh@|%k FxMy̶m`&Z+5~f}Ii r믋Nmzs$$n9g'#JXm UQ|J n*i \a@R݁TDyn0o^ДOe2<Ds&Xv~a{!'H _ي'B+wfX4Q^h 3PB9FT#` Zw(AaԘWtm:/zkq *C7v@wb(q۫ O:*Gj(r2#!  49µ0L4jn70PDC]$i@K XP`}S/Dy)icY\`N}P'/'x0 8Nzw_/ y@Q]V|Q̮-\r}L0^s#JrAE334`5.3݀_KQ#/g F>视^se_軑/tL>@ (5PxEӧlfZ{/30$n;" l4`*/pxl._!./T+sP oqOm؋95*ąxX>j\-p_tx : WԂ/Jz @ac OA97Ԋ@8St^HAB&c/M1C8JKb_%"}&_LEYn#7TY/8BD+䇹 IzP[Q슱og eenřφio.u@ؓ >Lj"܋n l@UaqT)b*VgJތA ]^ XA|{vt ؔ^_&@YxXl ۀ!]]Ԥ{ @Q{DJmiwF"DE0w̩B&OC_Y> qra(F׶0({|[Y|NO?`DykQ\?Գ^JM+.Dr"PA9@EGYʬ>K= =*w肨wKm0?P20CVdbL&Zbw?@wEo7f3\;#zv (8?PQ8#/rdxE?ݚ r[F3U.P`j!]!]!]H4;BD !Tfc~M^ 3DHq_Pe\st 7m<6( j\~B3,Vn\T}o J^ypwۻ:E!8l&>9zpH|QjENw]hgEikk9@UVk ZsKVI`;|]Xt="}m}s  +.awYG }O, Duh)!bTa~ A1^3D$*~ *BpRzg@N7u'^EN,t PJZo_?BlN4DE@]jl,2}kF%rwY7=Z`v:ճm]X*vSb6>^!OU!O59@Tz/0`.x`^(Q*jݵ! w S觭i.<Sȏ_'\f @ 6ɜE!9Q´\ԶzM!ؔHk>Dc / 3'X} =G Lk8BWT J\/'UTEbη 7iPﶂٽb=nnse-6xq/Pj r4hr1fu+d}X]E/$(X ?V v6xl4 J\@1ׄ}!Ṙ+m^`Ŋf<>p;߆D xr(f?u}h!htk!ĕV]B]QA|m_$l/sCLWxwLm1b *CQx! |"Q+ "\1}w~`nsTױ ,|"!C7d-@'+H6CLsο,\Yp=[{Tؒ ej [{4 pL@Em-u]@tE @0!o0PA JK̇_30Z j`FfmZ%D/ȬzVrY\1W {8>kH|5oyA$7\9Vt h'pE ޲@+J%@٣z߇׸;1DGq6|Xww/ș]}r(\n(CR#ht~AqUe7 @Tи-i(-7u q9MJvqq~)\Dž j0f%kEBڡe&y!bqV_`` :V?Eջ57uP@[ a&Jݲ B"PB{,KH/3Xg՚}W,n_z_h[  XP%^/P\)7zH`nYmo`:Q^+^޳0Kǰ}uv'_.`(_>P yEJ)P+j! BI.ۅC^6@t|XOf1N+U381~Nz?2jl^u@-Tǭ+PU3Gqu{:ExE>0_.c?D`*9PYN70VGhxJz\r41z DC(~]( *Y[1)mŪ. Cfo0DT)D20cm#`_>0\L,~M٠Pj`Vр '# sqK]llݳ#5W= G_ PSn0CḊXct^+ iIkOzs;xȇ(vpT@x D;QAP8 "4 r /./` i٠/hEۭGiڀNo2 e^Hg/ _)N'muIJj60;L_.p%`ư >֪3 {8 ؃Fp{жV)pT>V!/`~ nsi|n>Nm9Ng- H< ؃/pwb\M/+bW4yE>PpTDO*t, BҀ%@ԩ+Fpc7a:XLCTzc td';!P:ؕQbDғ *m/maS;3Qi5@ 9U)iHQѫ# /iX \j`]p @sp<[j 'p9_>hr@(}d@KB!|،WP_>Esl4I2W9Jpm-m> {1B0m qŃ:#Pciku{j>PQ 2qRڕ 0JN|tAxx1]M-p P6(~(`ݞ(jEY^+o$*v4vrY[cAN+T'{@X^fc T>5"`%W.xp!\p?V3RE*nW&ӾpVLOվM4`VpjK O+,S]X Zz"^1:j2x)sj D9ua/܀0l_>1G[Z`dה ,<Ư׶ DkEԬ# #YAnu1ѩ75vbZ}0-#>G e>D0>.F/lB>jE=@󳅛J-WXE7bwoHt:/4` +6|\v"퀊e2<Ds&Xv~a{!'H _ي'B+ `F1+h{! ΋Je<rS f;FB!M6Ÿ5QjN ص!;g;r1Uuj9ʢ[QD-xe<!GH3}p- 0>gY0PDC]$i@>+J*j}/ "JadNI0 293D ԛ)BO.^Nm%ro+)B`*(xE0I+0WM/R٭0][8ɢ>f} Q*q;q7m&E1pwt⾮i8W\Y R.Q 7i8oPGE­PxE)5˹ Ӏ|cuQ q1g/`Ou.`_W:4'diQ]ڷ noPlJt\: WԂ/ۀAVt] {~ ۠}V|(>nj3E;X\ɢPAtŦHƙ"e,m,5٠@@3c}g D9YE뻬l1>r(_I@e#DTѻB~[ ! e,XVA{Cbe~u)J+GYD_gqA!r#KAA8~P7d1d1ۧ$RŒ(zۼ8$EPxUٿ&0b[A ]^ XA|{vmؔ^_@YxXlgϮ7CP3)#R D"ض-9Un L[|Jz ocL; @1J N0(;Mq[{ 8w1DJAOZ(~}Di=y[~p?7qK}.f_\<1@{w w>UF>r.h- vA.[%_ vathll)81+[%M_qt) 46&jec}2e`F>!0OzgP >h/Zlv)^]v `ݕEe @QlcuZ!*Zivt'cz+n!0{&(t{Gַ'(L=FX)1 8NiDWSUS}P|SANH#lR :(;Y\h9jDMXD\n`&s{eN۰9C`#&@0m_Qe(?o(qT rD?-`,|{V9Qj0}*C 0W>"`c ߽,ݡDui>^ L֭j(}!YDa@HL[sC 9# >h(2\dL#BJ0(F`YX#@ԘC|L߷!`L}偊c!htk!ĕV]B]l 2m[?VS`m!6sC[n0EF jz\K!F`8T$u zD5L=8 <95nPo0cm 6v['Ja8Ժ|VH fZ4a7#%H Rjb\k7,ZRZ05P`OSW5v} Psa42=&+lpE R 0b!6V8_"scv(9Ρ-^y…L-@5ED s{3QB&k؎&d-)j{eJˢ@S!h}68{BB5f]kQZ׊D+C/+Mj=BĘu`` :]{Czۚbg/)B`*8?*CRH4@P(ҡ (-y/p&n_!81mywjM6@_&ɐR{pT&V6l֘Imc3Kǰ}uv>O_&`(_H{IDJm c>L%OrE9R(ƊOE`0ʖ QsKѵ? Vr_iPs.t˜1lP1ӊCݡI' ./[ P{P}:id>s>o8{{ v2:^w *˹GX5b!/* ib֜PJ)+Y[1)mŪs(AJ֢qnN&WA| Vd{_vEJ`iQ -7%.EF}kA b)lh1 @3}e3{Bju(W*eJ/B._F@k}ݘp F5z[i hX$6c1(h0* b9nڒ^5;53R2۶hH`;_YGF6Cuj0j1ĴZ `[FHcm[BX%[Y F/lB>jE\6So`~pSIvW7%DBVaaY`(Jn<D>DQ[6 (*sy@$:Wmevr5FOV6-_Q ڞ~bDYpz+{#Y%f} Q/To׸tN|՛6@Q}9CnPt" G?5~7= (_>w#-t)!@w47(i"Q\@l(F "r͌^s%!qZ QQ 8̯l`&ɢ,@_egY7@oJŻ QAF utۮ"`!?[슱og e,z/8SԠ9%ޠn{2gy_QVB{S_M*X8C:*EP{eUٿ&0b7EPBWV9ߞ]6e,<,E B8I.N^D(azSL6\~!_xα !|v Q?+׶0( fceQߩ|QF%̃.5>P,WdlUx>N-(|@1t ![ ~il!#r>J &&Z36*Q7#4e[2d>H4ƋE^+֜M2Qef}"|T9t)?.CTfcM~@fRDC)yN}nm<ѯ'( 2qgvdP_sQaO>@{pVBb/5]x/0C"FO;xw6Њό8{J±Z۠h=ToDv~#T ypE zr@A۫9ԋ4WI8Ɔo?ecՇ 0#ضsuP^1*0^{PC.D _-/s-v)^]v `ݕEZ(KoȘb" Q@mEo(DN.1GkNgqd} ~$S aTӰv@z<$F+y`x{ LK%?9]͠}8>~RcA=`/p%@C} 62 'N2(aZMPr|3rX]iGcy߇bq mp܆ӓz;b~oUyzC@%dJqZbY@+`۶++`}EƮy/fwqr5xEyr1fu+d}X}@_HQ6@~mXGj}(<| B2E!zGW4،Y+26sH6$LxXEѭwWZ}t wwr@_r|`H/e 44ͥ_> t\_H C EiԜo=NYg9<86M)4"SR16-@'+H6:gbL`Ɔs•kO?`jݑ-wPVR{4ށD" +Z\nn@RSCi tрm뇟ue\p*]UB=Yi+rTP ԮR(5}z`&s"42En$`Y0j@=O]p|֐595hvЪcE "B[(VrP]U1{Txvw}@ 1U|Jyh-nLIx`:r@\-eԘBj}8/(εp3QB&㚯фxWNa>6)"sS AԘa vEi]+m( 7ɫc׵jr3K(¬&K Of-{ * 5P+ʲth2C(Juv} \}yE*uEm>룊rzWr:<`>\!:eGMDe.g{-¯xW8L{,m(un) P/`(*^Rj[ØSɓ`O62R(sCwbpb˦=]?>+@q̹ cưAUL+u&}&`_~ 5kB}RJ`(^t@gh9:0cP *f&}V@ Q ^(Jz^Hs=5f!\a|Qɢ\lH#4P!Xc@aJ֢qnyL4 W~M  ,V|voY@kMDK?#5 1`r@QJyUF`t@Q^0%bc>oh#5\֟7\p F5_>HcN8 F`"s ̌AA;QT`h}Cq`4fShM[[VTa/@9Lc5VZ,1RřYvgǥDlx NVa1zɱՀ{v`ֵBbYP  2byaHt:7P1'=b%ýa%4c70ŮWJ|p @T|nK : 42A|)sa{~ja9{#ʴ\}>X `zS6(L޿CLͱĊ(=1X\ڬ h|V:k `kՙRJ[3PIip=AUQA{a r{8 *`Rx_Kh(v`~`=Ǽt!({l=msK©*.O+chJx+b*F}eL+:Wt:c{cQm@UX `TiA uN5 a:jE`vQϔLC!  5nig%J2J^zD%m@ma;NL{Z е;CdNU bREjC6/iX \j`]Ga:n ݲ/|D? p98(*-gpa3J_@ _9}`$9"(ҹ?iߋy@h{!,H\(ԥX"ip{j( OC@8LvtiΕ2|61肄|lE(еjl|o#JW(VE셽Fb/(aηxfYB\l9!q^T@/47"rZ: 9+pپ4,vV⢵f5J_Q(aZ/F{% #̙p{ ̰eR~0o up!>Nzwak鉬 u iX9 *a/ p'KnD^[6/\F%k FxM`czmLV$ZSԬ# #YAnu1ѩ75vbZ}0-#>G e>D0>.F/lB>jE\6So`~pSI1J-vJDBVaaY`(߻ D`*lkޠq 'ŕ< +6 o 9Y|FZ*4V=Z`0;0=ZWB9FT۩ s#aԘWtm:/p鈲"`6T߆C %qE!eQ 8z;E[nR[ Xj9B@j@hskaiܬ9˒9 ""L\QV!T5٠`h\t8yf ت)icYpm:;B ZBO$> o(8`L'|,Beݥ/[ `F1priE} :w8D/ *+XGŒ\ܽo#D`7pdLn1DHO oOJK7#!c(`w47(i"Q\@l(F "r͌Rcx `HsiUȏcuQ q__`/ '6Ŝ}}fY zRVHo@M^hcp6Ě@/3f,z"]V~us$|le1#DTѻB~[ ! e,Xn : BP?s-W((w@,5(~6DN{{4w7(ǯƞLY|v EM4:'BPj;L{3!*P#`N2~KYr߈e,b'Fn0+4b>FC} (x,̃B԰~\P}<EjҠ:"a=Q2cP١|R){EƆQ倷>} tܒ+q p>e: _`ǭƁEB}(O*-P$:v#xF (Л8e[2d>H4Ƌuك^b>Z(Ou2>Wk\zD>FS5/CD <}_~QBy\4!BJm_ɆR/{!((5݀`0nkwDU;,.W" }"@kz J;ݲPλ Y؛8 f\$^(wZYQu4Ӑѵ/XcAk1ѶZu " 5^T ypE ߏHC%oS/V\%} Rv0ؘ!ɔEضsuP}ғ PfbA1^z" [!8^ZRzg@N799 +@a^e @QlcuZ!*3Pc M;D} V(K̺9F@њөmد(b}ThlMipJ; jB^|e0Co1sPQfPOiQnO[jlq6Ulq/p%@C} 62 'N2(a+qU Rj .VD\%&p:P}ar'm؜!<=`#&@0m_Qe(7}9@bηxZKO㶂 Z-E>UJq~i&jvS$\ k^c| j̴l Y.V*Y㦁0cm $'`O'87[~pD6M~ڵ@(?/pM1( )> |)f̲XX#@ԘC>߷!`/4"D 8@\i%$: r,msvj9_>0T ݲF/s*WQ|C9"Q+ D "\1ws.u?;z0m(}g+ζb՗!=LyZg"*vyWZJ +@מ ƹ YMպz-9Pfkx5WpP+҈L@1)m=_> F> tQ|Q_.@ @Ӿg4?̇_3_ڶVH f>0glx?h]L#^}FEK 1W }*㳆ԮU D@]6|" RoYXsCoa@٣D_!Ʊ`6h>  7*'DN(\{( 2[1.4p$_Pkf*L5_ +Y!`?Xc'RHˢ@S!h}68{BB5f]kQZ׊D+C/+Mj=BĘu\һAtf5A϶_RTpT0n!ThZ=P%CۗBQZ^jMܾC+BPql/X[%@z/p@Jc4FaDi56j|Tw"|8n{@s;NY6jES`&T((R|JsPE``AqMkO} 8\v1cؠcC> BOVg]/W};3+(r?{' 429{7=py`/i_>ο+*yoir0VGhhBFUj&: Г[s `&B&`ᔕ,>ʆ4BSEU Q qu-NL4 W`UhN& 7x*mY,";VqA|Qq)aݷ _@369鞁8D%N 2d Ɣ ^cbC3i hX$6c1(h0* b9n%q)Q;3h_lu" sqK]llݳ#5W=  H{ZӘ{Z !AC1:/lNg4椵'Ud7) in`&]3A$ \mD]~9 $|l[_|737@+B`n}>zޔ 4 kMRNjgcd E >W6+05+3}t >֪3%@+EDpV+"^y#Q[/0e]!ޮ! cl,"SH ښSQ(V|YIL ־Y*i ~E.i|esDq?f-"DSAo}St<-sb{ 9Yp@ҽ95Ur@T:_N&a/܀0l_A߳Cd )ϝbٶ DkE5J80Ҙ_xQc!HH3 2rNFStTm[G‚kQ|J n*i \_2C F@|*"Qe²P/!3m!|h'ڲQEQA "ѹl,;րgBlE vӻ3YAQp^U( N/x%`/cD?v~uLjN4ЊFyEצBq GϚ({kq *C7v@wb(q۫ O:*!//?P !}f>q8aQs,Kw(~ࢋD3 (gsE XP`|ezrxQ(` em!VeN}P'/'gy9!0 A4p2]WЀ29"Q( .m ffk '>YGLs#JҠ|(6ұyADQ! {G7(J:[^Lߞ軑/@w|7(i"Q\@l(F}l Q"r͌RcE(-P¦NB~]۬W rgdr;?i=a/Az>j򴽀A)Ad`I+r lv.iV OA97p1DJQ|  3E;~?雀UPd%vi1:fHGicIih~>}GH3QNg.+?[̺ |Wb>p x u'0J5~(pUP*/@H Y }lzNi{FXwYQ >`8 e8 ?`ǭށL>p T D$~ǭA {F(Нxlz[(ˑh9Ƌ 2 ^b>ZG:] BBŔh4^2Dt;R@`F 9!}9DC)q(5܀?T 0nkwDU " br%Ƞ'-QgO-KKŌ;_j>`0:|FyO|@ku=@+>+N[ c2Xoc| U@D va>[s`cNXActA|ѥ,v#P>'Sfc"`:rh5V(>+6C= A1^3D$*jaxk إ,*WwiU.pO?Gp^E/l2&9~HCT~Ʀѝ>m(K̺9F@њөmfWf>*46Uc4l9} jBBgNe0CܽL]@E#A!>.5p6} T+&` \ P8uRcdP|6lmdN۝,@eQ W*Zα5"p`S" MA8.`w|6l}fX} =G Lk8BWT J>U"Qq%wKX,9_>@+|A=Eiٮ AMP+>[|K0Q;ԻZ\=kq3 sU1faD@%k!䇵8{8a}sC y# >hqA( De2& B2E!zGW4ی,n;v4CX6{Cbc<>p;߆D xrVBC A[!}b r,/mk6r \0T nYx# Msi Ĝ/ 1G /Dή07!#a5>c&@-٥gYXhJaYsJj0bce{|x#CLsο,wt:{j\:#[_[w5"Ƚp\s d/mS/Q c" |2V|E.VpJK̇_3_> mR(5|z?MY0~E5_(Y/v#,.^E>uYCjxU D@]6|" RoYXsCoa<+X U\t/iEY`w^B-l;tb˵Wp!P@)D sy3*L|e+Y!`Kk"eA)4\Q. o07?gX,jE0l,$?]"?prEn"okZ!=`***$f-{ * 5P+ʲth2C(Juv} \}yEcl/q}h@_.ɐR{pT&V6 i5j\a{&`i~ׅ:;ePÓ`{?$*T$" Զ1'@)dcŧqe#Cpi@t|X@J+ cEnW3 :fZp;4c d6e/(ؼZ¾oQJU 429{7=py`< a {@%9PY=ƪQ |VsR&&@On)h>sSV((Mi;E.V-778zܩ mw('W|]fWXZyE{R aݷ <-FЌ==!DqzyD%NVeb`h <7<p F5<Ɯp;Eb1v"QMݡ(h4by@,|6k RC`1q`?Z*j~5u)jOJ`V! [{Hbc׫[+*hk͕zOE#Ĕ"d>^t6nHcNZ{[J{/D>^(vpT@xqH4y'+N/` )r /( !S}l~&Z W>Q =VBYɵ& _)N'12"^Tqv\JasCD)OR m`NR" 3tFp{жV)pT>V! _zDh(v`ܞNCﮛDH.}|6*ypDӀ=hGY`U{A_. qDqWLŨ,ixEN}̡u'"쉞US04 l u:p؍`ZQ8]3%PH~álECm8Հ#Qn 4o dbŲ{Z еSe;(< aEXx7pE}v@NkͽXl db}'t˾!j E q@BQ#3TZ fJf.cۧM*#؊} saml}_>0A\8A,{8^8`4`Gw0|tn " <y BhE(еjl \%@+EDpV+"^y#Q[_.(aη ̲{Y@epܮ! cl,"SH ښS+@-,g@}0U@]D z1#*s&ܞ,03l!vBԶ/<-}(@ȏ>.I9Yp}Q+{c=sj D9p'a/܀0l_>g/mjq^S;#(m֊Dk q$a1+ȭ.&:CLϑfe䜝4*\0m[G‚kQ|J n*i \_2C F@|*"ЀUXXV7we D`*?GԖ"( \hΕg`ݷ셜,>#-|g+jl[_>0;0=Ear%x^ Qm&` Zw(AaԘWtm:/pRsoml5 ! Qx9?J\DC8ʢ뼾5@q4Лxe<!GH3}p- 0>gY0PDC]$i@>+J*oExATa@D)>C)iBbU4߷!JL!kBYro+)B`*MZPz2]WЀ2ENba[Q̮-\dQm3(Q}}#@aF.޷ "bD X8;AQɔ!^Lߞ p]AANjAk Qqh 5˹ Ӏ|cuQ q1g/`Om؋95*ąx=qㄌByږk+|ӎ|LQ<96] 0c nr1n_obZ<Tz#d@wPAtڥ_0X8seKE-L0('޳}}-f<#$|\djo($mb*gB ~v\lxP?s-W(-enM  -] ƞ~#5=}cDX cEOI|[6 0`p 8ABb*VgJތA ]^ XA|{vt ؔ^_@YxXlۀ!]]Ԥ{ @Q{DJmiwF"DE0w̩B&OCҍ_> d eytQ>A۶0(]Y\Mq#0J3^(y!D] \ SP*/o]P^(K܀/?`uJ{X|5\/:$>p$Qb(<B>pM&k2rP%&hqܾ_(fU8CߌCl ]Dcj[=h pDT!Z /D> ҥltV|E_fcM> 3DHw_P]/zn{CFpHXd4/Di=[yw$Z! {!8-f_`_w]ЊϊS= }%V]Z @Vd]׫bB t0?`AןW\PPj9bUGjw@XLYAmˡ[X=P|x9Bhmgp/o-ؽH&`{\9] +@0[aE (~N:-Ҹ `ƶ"CkƦum[ĬfP{债mbd>*46Uc4l:]^!OU!OO9V 5~\m4u *jݵ! w SZ-u8? L\ P8P$4f ͠ x !JJs{M!ؔjHk>Dc>/p܆ϓz;b~oϳJ>UXs\@+x债 ֢lXny&- G_.~7Lri>w/Qc`Vsz@dݛ`@HLPA`gu4h aQ+B(?/pM1( )> |)ffYX, j!amH/`:@}h!htk!ĕV]B]삨 }rm[mkrjr}5/9+>Pb<0}_.H CjAQs;fZӽ4<=uٞP::cU_ 2i}"4aTӆRf:?`?]~[Tؒ e> jE1i|b92Ep_.mS< F:El[_,PA nH3r|%Zΰ|mk`F{~6g%HrFf(׫,ZRj1E\ go%>;]XcbeA$j 9Vt ` *P(\17! >+!XɵV8_."Z,ܽ;LI{(9Urr(\zn(CR#ht~Aq>L( 5_؎&Na>6)"sS AԘa J > Bڡ}{1Zwt[`aV~[Z Ql%EL'@e3Q=\BJeYB:IEiή{5mK!8 0y w O/DdHy|c@CQahV6_0= m/(un) ]!xm0r7g5PE`0aޠ8KѵKc}_+4(mbO :fZp;4c d6 56Ul$0|}pBm2F݋>TY #`{1JSR41zrkNDC(LQɢ\lH#4P!Xuzn!["*YV6pz=h`a'z/>Lpo+T.XXZyEXG賂o 8A 1-xr-F v/(%*u{| m]&&hwc11 `Xi hX$6c1(h0* b9n lUG&JV um9LӀT!:nҼISsAWDYxIeGw;N:@F K_Z7" tc1mD PJQ=QՊWHTiz _0e]!% *CXDN+T>5"`%W[XYbg%1(.Z`feb$GVLOU2BQ]m DiE vԻ +XKOd^uVHKzT/DЦ/(Zzp&ز|=;xhKP)FmLV$ kJ80Ҙ_xQc!HH3 U|7.503G0o! MD)70?[rUt1J-vJSN²P}zE7.CTCS?GԖ"( \hΕg`ݷ셜,>#-|g+jL'n`zw`F1+h{! ΋JeQQ¼_.J^(LjY%`N}P'/'gy9!0T{DC G(C`:9{!{M(ʂKYwtm7ɥO6ܽo||(6ұyADQ! {G7(J:[^Lߞ}7"@{t_>(i"Q\@*!ZNQjQs^\4Ӏz\!6 8#_.`|{m^̩U!.ă /6}z1 -*[R!/d`m" C.H~ Ǹ}oV|(>@Mƙ zRVHo@M^hcp6z4%"}&_LEYn#7TY/8BD+䇹 IY Ƚȡ~ j[P&Z8""?3E  -] + '|`%+D^F}Up8tU`!{Uٿ&0b7EPBWV9ߞ]6-Plxam@=P3)#R D" u;rT!'xe~!/ܛ뭁.Pa.(Fyl忶Fn0[Y1W_`D|3dfg;)W(BTY lNi(+26*UoQ\{i(F!qq0P,䀧|@@LM 8n/(flU.8CoFn0 !(48(ˑh9Ƌ 2풴nl9|S> !]!bJH4ҥltk0)/0h2C| J1 txAHt>=/~KƯDj ߍ@E@vؓe{i w@7q٢ `0:?Q_ϻ/C+>+N{4dtc-( jmbmD̃Dj( `AßWo;&Bs W]Jcf2L7pDa:rh5VP|Vl(zAb |_w!gH4TnTxkKYT;|w'^E/@ {-7dLEsih Ʀѝ>mW8F@њөmXQBk7%a3)퀨 y yg9-560x[<0q,x倊Zw-G6B|]jlVtK-F`/p%@cX]6)lR :+ًBZsQLW-Xh8C)Fq4l#,A8>09oEWwhޞ# !+L:O HT\xbηxZ}@|e2u7AlQ8zrafwqr5xEyr1fu+d}X}@_HQ6@~X-i 8P&`?@(?/x(B(To(ኦ0bEbQc EU@J+i:nZdZGqGp; *ȱx/ж_yzr|`H/e 44ͥ_> t\_H C9Vt h'pE ޲@+>4)("Vr-yvw}@ Q+QM^Zw}SRS3Eζ1Ŗk<EB&t@5ED s(㾋T6+Y!`K@iYhu q9M}NM:.$Qc7+)'@i6^V{1Z53uv "okZ!m a&Jݲ B"PB{,KH/3Xg^0W,n_7y y -U! O"c2慄zH`nYmulHìqVgaVž:;ePӓjxEr@EK: PJmka*y+j! BI6V|Џ uJDٲ!cn4]{4}k `%1N+U381~Nz?2_(Ԙ1 id>s>o8{{ _.|߽#@%9PY=ƪQ @9L)uN'L4R9L)+Y} ixEἢ,b}E CD%kQ87pzS& ` +֕ "QN˯Pn"`%_.`iQޱ +o)D#5 1`r-FxfNwQ1JT+`Զ=/&@rZޘr+~{L55`h2#94-wc503FQECP 1ǭfShM[5r+()> v|97(~U: `wޔ-fϠ;AɊ4!]/9v V`\Y4P}]4@9BLY1!AC1:/lNg4椵'Ud7lPQUCӌLSe? c@1 /D_.@ i@| /LMX&P CL̯l}>z0E{q"@&/|8?"^Tqv| X>:`kՙRJ,zDfN{0AE !( Z/ RX6`~Q`mq{{8 y8V$p|6*ypDӀ=hr,0?/TUa +:W1A9ErEVa,* 8[DN=n8NqLT+ zd o8mhqOj@`WFKOqnP0 ily&=}!2*P1 )"vQ(O5@HÊ4n(P4 V*߀X |UXp #93i!}>lF(a\4ǶO,$sU;G@:Ô> 0A<=qX"ip{j( OC@8LvtI (҈1_.Z7" tc1mD PJQ=QՊkr%@1 s/0e]!k/ ^Tgc9P@T֜<_DŠr;+ Dqw3RE*3%LH+ۏ#Q 0ԭ03l! RGy[G 0QB|Za" 9YFgZG̩*~zH#̔}f&ز9 }^>ڒ5#c$4fD;@ 1>GBisv2Ҙ |`,x]K ZQצ -T@h*%DBVaaY`(>N"`Cћe!*_'ڲQEQA "ѹl,;րgBlE vӻ3YA* ZB1-:|e#` Zw(AaԘWtm:/k5QjN ص!;g;r1Ɖ2pE!y} P f8-7_.p#>X Fz, S( !. 4|%`B>Q~Z "JadNI0 2i`N}P'/'gy9!0T{DCNzw_@|r,@̺;lKU3tG>!x~c}݋Dm[D8H`Zep޴Dňp^m4AV视ӷ|eO Х4/ ~+!m"?ѹuH4>e3Ԣ#~97^\p96upC8Z`1F PA79| uȩ˻U]tyEi?V|(>Y zRVHo@M^hcp6Ě@/`A;Br=wYb}PUAYgf' 25zWs˷61`!?[0&1@mu,gioӵ Ch%(~6DN{{4w7(ǯƞLY|lNiF U>Q=9 _P0CVbuM&|Zb$-Ō]bG}蛑?rmAsuyh]mm|(2Vk\w\}h4Ko rd)y J1 t>!] z~DWSUS_>p fM u,66T6RgݧO[nq~&(B~rDa3fAFT%s%@E9V&Zlb5@i]b1 8yn tkݫVD*OG Kn@bηg#V8]{[l_.qbazh/p~;"`յ_i>w/Qc`Vsz@dݛ`@HLPA`gKNP&`?}\@ & ɘFm`>\єw3,Vd,m50_.P%uq"C;B+>DQAxڶ/[_.m[ P 4ͥ5y@X|!krAEXgWW 9xD5>c&z`nsTױӆg{B\l!V}3uɊ Ҁ;cZJ]•k}[Tؒ e> jE1i|b92Ep_.mS< F:El]?,PA nH3r|%Zΰ|my:q@P\7%H2@1zQWo%`Ys`k71*S5*֘ ڑ@@]ډmE>\B,P䊹0 a WчH"gߛ)bZl:@kp0%_.|`-[ \-zeԘBj}8/(}*.. Rq`Aq= k?Vr_iPsDTu̴"Pwh9Ajl{/jl\ZB[W.PU3Gq g/t@^!nv%Pv/P{#d%@N+Tsj#5 1_.{rSB@:=>Զ.{_F@kxe1eWk0j 4`F,1Ej w@1 FS`1v+hcb#ů\#7*(iLy;x{97({gfmbxST*Av`kiC^rz5`ckE!uPi>`@:jPGₛ\T|xEٸ"9iIo+ z<4c70TYpTϠH^ 3DP8 ҀD}G'2A悐0ضZZvЃ.!.j,܋2x+餭8yX\ڬ h+3}t >A$Jyb(m-@FgiT'  :N4*x/8FC5p0ﮛ iqz4[*P8B0Ի,0?/@S\S1+f^鼢6 l'zVcЧlF-AN]Q7b\ 8q &E=S2 76P4n p]%FT/= ݶ yo 6qg(B 9U)iHQѷ%xE=BVwWD'i{8`U¹ 8BTny{ ,(\h 8_>b!"R|P>6e\Esl4I2W8@Al-mp4È "W yq.Vx HZ/ *"P&N*8uҹ-H4bx_2@ЊȽQk|"4sZjEY^+o$*v^(-4y,KuT(z^T@/ VN} *hkNEJ~<fBU@$"֋b$GVLOվM4`VpjK O+,S]X Zz"? u iXx储 ut򁢥{@ 7`a/-_.A߳Cd )ϝbٶ DkEԬ# #YAnu1ѩ75vbZ}0-#d1UIx偱u-/ F/lB>jE\6So`~G13V%DBVaaY`(>N"`Cћe!*) ۟#jFdE_DʳM[BN 5FOV6-/L(fmO?DyVi,8Gpo+_0070k1 "Qc^ѵOY#JIנ2P|ct^NpeG;EC(C8ʢ뼾`5:6P$j/ 2#!  49µ0L4jneIBn\th`l(bzP0Ux2@D)>C)icY|3D ԛ)BO.^Nm%ro+)B`*((/`:9{!{M|o~Tj; `F1priE}} Q^zg0J-v\2 8UoL0oϏ!>pEIg+pSw/ nE.z|Q(pk ~6>(^hh9}fFEͱGzpZ{6J[iU_.f]B\_.<쉷 {1f_W:4'޾ГQ(ڷ noPlJt<: WԂ/ Co4 { x~ Ǹ}!`P݀L Td):!-e.Tbbt̐ƒXZЂ+rp&n#7BqUЫ7|օE<ATѻB~[ !L *`W}lxP?s@+~yLQgC䴷GHKsxq n}cDX cEOI|[6 0`p 8AB1nƳM`~%VoFX. s=;lJ/ZX/,<,ۀ!]{ g7`S[G**h"DE0w̩B&OCҽ_.M@傯Q 3/(5\*<+ 0\Bz XJ|Wz@B_a*}68Rf} 7T|]9]P,WdU>pW@D[/$n(b(Bzx&g2r.P%HF~0zF >tgC-hvy28m}A[F/1c-v#U.P`j!]!]!ۼMR~6:X ~r d)5˹ J1 t\q"wg-g1@E>/P%ҺxW4t5ۻ:Eߛ8 l0CԊ>ܻ~Њϊ|F>rm͋(PzS.,?\Ws̩+h.8ކf2>0#֡C@Yc/?7h5ܢ2bKYT;x{R9\Z(KoȘb" Q8Vhlj݉ ٶo=Z`v:ճm]X[OiG-LZ\_ yϜ~+y`0;̸1w,{Zlt)VH 4ލ\`\J)ޱ@(lR uV9%p%>^-g6pz ڴ.1Áv8yn ^1J-Wш8BWT O HT\xbη 7iPﶂZ9~[L:L-6x_wD9ж5(r \0T nYx# Msi Ĝ/ 1G /Dή0s"4js}rL=Q]JϾ^6>۳M` KߐA&|½.4E|wŖk<EB&p~@5ED s(ヒDk؎&d-)jlJˢ@S!hJ@ܽ`n q!!3 DYIZhvheEYI^GsܾU1Xz7NFf5A϶_RTpT0n!ThN]m̺:՚%T<>:!-V@ZB:_.<\!B?UL-+>mL'*s9k~+a{&`i~׹_g,jw!(j ?Ll0/0ݽ %WԘC(<7tw], 7((å1ׂ`YLc3sQƌaVM?'=YMvT EAߎ 1 C(I3Gq g/t@^!/i1߽#@%{+~ Uc/8<W\)uN'L4R9L)+Y} i"@T-"*D2"io̕zO4Vb>`hk xEٸ"9iIo+ j`E4c70ŮWJ\A8nyw/pADx*fO/N 2 3mkx lP "#J\C\ Y'd WI[p/,EYA7`L+3p(6D)OR H {8 ؃Fp{жV)pT>V!/`~ nsi|n>N 4zPAm&  GY`U{A_.0xW|TݰN+CNDQ=бS6J– QS1> 8q &cY0 Q-I@`WFKOw\QOc83Qi5@ 9U)iHQѷ%xES@HÊ4n(PUy Pq[gB0ny{ ,(\hpb!"R|P>6e|ied $87iTbk涏P8aD؆B+wP<G jA\cFůl_ï8Je{a-/0fYB\x-\xK\T@/tal,"SH ښS+@{rY}gPl;(Aebi*!#Q 0ԭ03l!* };(il5nՖ@VXbH@D\u iX|QA|倢{@ 7`a/-!ˇkr) YZ֊Da <_YGFbSo0j1Ĵ `[F|@0T%] Ƃ5`BoZQצ -T@h*%Gyn0o^ДnT-EQ< cZ[BNc 5FO n98bVC x11;``n`ֺcD 'hEƼky=fqHml5 !9;݁DS O:*G f8-71yBg`Z&`57}β$`N|7.H40Ӏ}6WUF1i_ x偈R}tSLDz_>io=CJB V,/'"_Q 0  X|ș|@Q]j?Z+ɥO6ܽoP\Z>f}< (FT_ý%HO oOJ}7"@xt_S}@Pj%%5DDCS63J-j= C6upCpxl._!./<;|쉷 {1f_W:\Z`1FPA7|LQ<96X(rjp]]tqzԊ@8Stqa]CZ ] K:bbt̐ƒX z u W60d{Ŭ %UQAF an6Bm`*gB ~ "c<79P e8""?3E  -] + '|`%+D>%l41R /qX5k+!z3Z*ty%`%`Sz:yea]__optEwQ].E!(Qޑ0 ll?/I7:w 2)_y ^>|<gfoe;_Pk >UyW>`F ,+.Dr"PA9@EGYʬ>K= =*w肨wKm0?P20CVdbL&Zbw?@vrA1cϨQ3!@4`< xc ` c.pD̺+rrb[є.g3J1&/"Ը/h(2.9 B؃jrCX"4]Dj=ߍ -Di Ұ-KKŌ;_M3/0J:_>`tc-( jAk1Ѷ{"0t*{(T OW|s  +.awYG }O, Duh)!bTa~ A1^3D$*~ *BpRzg@N7u'^E/l2&9~HCT~ƶ"CзfQ"^Q|us٣5FaS=XQT<8S+*/s6gO{{@6pȯ2 ^ϻ#2Qe1h4w[l-JKWw-&J{a~fwwlzxEyrA9@Ԙi3غ>\."Ef nE;nV~}^Bm aBpM?Fm`>\єo3,Vd̊=.sH}&2P>=`J.!. }ڶ/ |`m̹+rbNŊTC@EXgWW 9xD5>c&樮c%g ,|"!C7d-@'+H6CLsο,\Yp=[{Tؒ ej [i@kfq\s d/.[ D c" |~TPAYi+rRjO3 Psa4@$7\99}.B[(Vr[=u+b%͔(CԊ|+G½.4E|wŖk<EB&p~@5ED s(ヒDk؎&d\oS!hVXwQc7+)\+m( 7ɫc׵j3K(¬&K Of-{ * 5P+ʲth2C(Jkad "gq"@j8_X=Z/q:|Hy|OC*ut mxӉ\Z_p XZ(un) ;C8@E24apP+j! BI.ۅC^6@t|XOf1N+U381~Nz?2jl^u@-Tǭ+PU3Gqu{:ExE>0_.%@N+TUc/8<W\)uN'L4+̔\,>ʆ4BSEU ]nad-PNw`hk xEٸ"9iIo+ TE4c70ŮWJ\ASh *h gD_>0_2AxESx,_>0/xq2-Wp©bŁ| "M gq/,ڀC* S \ 1CmRJ[3й,@#pUE{m S4L}BJ_.291 .Ӏw| :sF%o[Nl /%7ȯ8ӯ<@_.49_1l+:W1ם'zVcЧlF-AN]Q~7b|NqLT+ zd o8mh_w@=+P:ؕQbDғ *m/maS;3Qi5@ 9U)iHQѫ# /iX \ų]4 V*߀X ݲ/|DPU8AuE q@BQ#3TZ fJf.cۧM*AAlI1bSn4`Q`.݀xOB]JG5@WDYxIeGw;NpTc n"roEt5_.@ۈu{8Je{a-/0fYB\l9P=Qc^{UU~P@T֜<^" …;bIFQE*3%LHt$bDq?f-"DSAo}St<- @D\u ieRT/ rXG/-^ {al| }Wcd ) Yx_m֊Da <_YGFbSo0j1Ĵ `[F|@0T%] Ƃ׵84m UXpm OɿM% +Qj;P7p$: Cq >. QMYv@ňڲQEQA "ѹl,;րgBlE vwfX4Q^#J^(Ljj;5;``n`ֺcDӝV0j+6xΎk8 tD97`6To Wphh(+rE!׷&=Zl5yBg`Z&`573ʱ$P~yfEk }yAf):!-ݛyT4CA+c/|2/dmcI\#Z5 }&o̔EY׊E7@oJ,3@Fo0|@!iSY_+A[1ͳ{CAb#+ /pԥ/kq9%@P7_ԍ=ർ/xT6r1ۧ$ނ-}Ur8tUD XH<| mŪ[G -!U"J2۳kCOE Ò `_HъogO3AE)(GvK`I+dr t_t#@.F.t@| o;e(s[Ypd#<8@!> ld}_8Bi}jL?lⵟ1>{E>g %q\G qK >b3GQgFS&p`oE,G1^1^A[F/b9Zl#Gu2~Wk\B[!ۼҪ|mt;we)u^%?Txd{@  /`n?Uwg1wc 6T_sxgO~-t{fpVncoLx-P@_&#ZQϻ/V:/]XTlob9Хz$RS,C}tU1n {[] 46fd"| Bw5GCIO~& C."2 _-zE ]Ej]v `_8~p(rf+ZKoȘb""Pjl.e֌(WT*ݜ{# R`hMӕ>,X+>mMf90iՍ2@%i/ss~Z+e|7r JUȏꃜG fA> (z?P0וŗs{M))צ T;/pͿH _ RzC=@ۧJPRdZ\xKXs}_@=բlXny&Њ׊7_|ey_Nȃ1{YD6[j(}!Y<‚õ8:a=r9j㮰(=|{AJ__b#BJO`9v >B劂Ƌ‹R2&cQ\i%d= X/жlm5<0/Lѧ傚R/K]82_^#LV7*9xD\13|`ns۸x ,"x9%5Cln rx#SL,?Y9t:{wnmj\iݑ_u r:siffx~`/ķmSd/P4<0 _0e4P<6|m*0Qė3_(|[RGt}z`&l߰ 2L Ez+9Y 1^Z?{+ZCjy@bY {L @.ĶV=-VU\/p/@JB?R[*>mL'վbY0L{m}m:uvC]O/TQQ|_Pd#RrJ^-Bl:jGld q]k_6r_i 9:n0 TBow*9A.7_Zm@ M_|D%%0rs>o8{{ LP#et~7BV)Uc/B _U  ib֜PLeh\l+*u1@T-"s(W;U&`ap{[[W&L9/B2|LږWlE;>xAvELl̔e|{c/hC3(/8N0R``fGJiMݡSq[Ni36ЊS 7Dj+e>`;'/yoy߶ M@hdna50~ 4d6W9vc׊=;RʢzOEȑb V0D4r[ xEٸAEs*ǾXve(GM3v38*gP#= L;gheT0Ԉt,jy`hֈr 5< !Ar#B:; Y'Ug/ o:^źfAs܀F7V +:1X̔TK-@ !a{ /AhS4P>R/_^ A06=wA =,ǽt8ߪq8^mn PCP_Tyooq?n)/XS1+f^鼢yEۓ)ʱ-T<&QaKheBq̴VTfꙒy` td''P:GbDғ ن0eT-7|4<3ŞVt>YR(1Knxn y",X>M@UA 7,gyxf*NP"ʅ<T 3EpaJyieӮ ėOp|y`rMȃpz4E"xbHV"il5¡-(>]a݅r' +{c=Kj /@rh^ i c˦FB-YC-n0 v#603ՊLa @|*"ЀM(, ǩrW8l,|<Ds&Xv[BN ⵊ'B+7ӻyVi.8РXR@ 1NM_0070[1 'ԊFyEצBq GϚG8$`6(So 9P'|\DQ q4Л|/8R# `Z&` \ XR( !EfPJ%`B>T7SG ad,/|zGB(f A'|[I󵼜J Tr"xI-2_!r^*o1)VkN.}hD_2|$ywFhnOi37G*FT_b#o 2uE~jxn)8W9FZRu P7Z<&F :WdZNhQs._΍=\NMB~ԍ6 q< -s x۰KjRAG/+Ux#h n{y 3uTNԂ_ `@EI^-`W nr1Њ8ZPA덐^H hϞ{Iش3$$^-h^!w03d{b}PSb9,,N djVs˷61`!(Vbg##mYLyQz߿řkC䴷GHKsxA8~P7d1R"܋nx l@UaqT`!@[7t|t+lds47x%`%4*m0]@]Ò `x_._op[Ԥ{ M^D #azX ll?Y/|C/|2_LuytG>Am`9Qkfweq7? ~\x6yO`>(е>F֍r'8O"Et|@^਋xn(^{]tF U>Ѧ=9 _ >0Sm& 5\i93&}_ VQe#oFcxC[- x)x{ /(p"3FL1M&`9rru|ֿ`ִH_[j j\ڀyw 恨c Sk W|9%`tv##f !B3f_74 jW}hj([/VH #z>glxzϗ 2_Ȣr]un`iנ"{Pk -fa4) @.Z㚯P(Ib#+u` K1{}<;aShE9tE^+w{S҈rEΈ ~99a{nP&EP-V!ELgq3GB&k>Pj+&e[Ma>VC)Hpq~) Z0m` 6kE !劺p|+RĘG/|_ȱmf@k1K Oe 3S=\j`P(ҡLQQ[y/pVܾ``U#?m8?xX VWq:\><)7X zH`nж 0lEx iY{s;_g,?󤾀GEK: 0T`OV@)sCwwFb qek?z `#0ǜEn7 *3mp;4c jl~_ |}@ M#!^t@ghjGw>B_X0t| PRrIS ~W<)uN'4fJ/D#zeC)mH!L92@!["s(W;U`ap{[+D{ovEF~_`m%T#Q{)0ݷ X-xG ̒)u([m{|R%~w6ZGߍ)Ĩ\b fP_p1'`"s ̂AA;"ӚC yL6 1b#ŷr@9 {)E0fS|oc1Ŝ_yY}W<^'hdna50Sh/:Y9ĸU]صvώ,z@{urc!Abt^+2 *֞Mv(GM3v3Sz5ਤA8*~ ~@4a9'NI˄Ц B¼/ <[]/"i|lPC!AkAsq#=1A.E@7`ы򀕀 ڂ)Zuf_j`R[D=$4`A#hS4P>R#_F8F`mq{{8 Xw鶫z@1EG]`-/y҈+b*F}e+:Wt:c{#E9ErG؄EF-AM{P:8 j8u3٥zdj@!.NQ$Fw6T-7|4<3ŞVt>YR(1KV O+»@ Ӵ+J.(ILݲ/|D Q v"ʅ8\h@(}d@KB8H_@ 3\Esl4\ b90O~}/B aA:֙ur,{8^=5(RC@8LvtiΕe:mieHQ+Rp ^<]&x/mD EnOGmkE]Wȴ-{=@Üo5\@q5'#W8n e Bsl, թO$@_ 0 ⵜJbh;Y[% o.E z12+IQ2gɂG* [&Eվ;T:jY}|NQ 9Euҽ%5Uh utfʾ33 {alԌrAnmjqQާl0d1~oT+2l-q$a1ȭ.f:(s#!2UIky`,xm[(V4ڴATM% _nwubwot:/4` C!3xT5rWa[K'bN+sy@d:Wme/5`/di ^h1z"n\0;01h{k& >>x^ 1NM_0070[1Zk!)M6Ÿ5qHml5P(T Qx9?J\DS8R!׷&=*2u˽/ HQg(|skayhn7p%`I|7]$y@>+M>bS/ɢ3 em!t} ԛ)sMxYhuD٪ũ@o(/Q/`:_`+DΈrAE]pwgڭ01v'h @u7p<>fEk }yA<=p+pSwHR/KiKՋC/3B?*2n :WdZNhQs._΍=\NMB~]۬+ňrķ঒R,{m^,h_`Wig@rÈ@fꨜ/ 3%5s{yD OA97B+"h@7BVtx#%ȣ  Z{Iش3$$A/3|f,z"]WV,zyF (_Irle1#E4[!?-PH2q,n `ge2G]y"(g  -] u@ؓ ^H`#Ws/}J-زiW9+'sDI@ mŪ_o ؄W69ߞ]~Jԅ%Hf?u8dAt~4T?Ra띑Hx:L9KZ!-gyջ2EaFnyܕ4X8r}| >Y8g|BY7Pz >jҍ}E{.2_x?wuJ{@WU.V|@D[8(|sLQu<|L._drP}=מ|A[*+rZQ9,_\x0S_o8O\yw\rԊU'= >//؄wv@k1mDGz7]YttX~@PKz-.Uw?2>0#[i `QP}ғʡ̃b\^HL="[=.rW.?ӽ/|~p(rySKJ?jjyZ U߆DAߚQ<%[Ţ~oD  vjwAlH=[)vSb6q.VWK#4eB/L͚_>eB/sa{~zC?R`jAltvp7eb@>[Cn;"N'muuU/;^,Vuc V)^ PB8Nt@@`@@r21KmqG̯@ } irn.NW'+)2.OG]`-/y҈+b*Fj7)$Gr]eT<&)ZUp6M}oĸNq̴VTfꙒyTH~áluoNr5tĈ'A4 aзߖ>~`ibOv`g,iGUԥqc2C@ELQ!||_.9}`ٴ"#h#S}(a)]ԋK ҼISs-: L\&pt;T綠"#NjҠgh"tH-_@ۈ@|(`ݞ(֊{ai[/yY}/P zAL^Tgc%UN} hkN"`#%[XZbg%1AQ\,z"֋bdG03l) 1v+H4`VwՖ@NQ 9Euҽ%5Uh uth^ i c˦f B-Y5PQާ.L(|ڟ#j"G*sy@d:Wme/5`/di ^h1z"n\0;01h{k& >>x^ 1NM_0070[1 'ԊFyE6xΎk8 t3@cp\ Cs,Kw~`EﳹR ؄P#f?Ջr`h,:@< XiqJڀyXb{JBPV|-/'"6ūTtһ+x </P/Tw6(*ٵ '>YGLs㑨E334`5.3݀zfoT!+F>视^s^}7"@;}CYMg 6mTd+_ѹu4>e3yEx `Hsi)GEͺB\/pF_.`_>=a/Ń_`Wig@rÈ@fꨜ/ 3%5s{yD_.H~ Ǹ}ZQ|G *h;)DM`/|cp64^-h^!6o̔EY׊E7@oJ,#@Fo0|@!iSP8 k%ୀ1Sge2G]y"(g  -] u@ؓ ^H`#Ws/}J-زiW9+cHQE/1n' j[ѭ|$o dηgGrK6aq6\P+Rv1|  HъoQ].6'RPj;L{3)P#`I+dd/I\ dMLuytG>Am`9Qkfweq7? ~\x6yO`>(е>FMO(=pDr5@EB=Eq"kQ܀/P@WU.V|@D[8(|sLQu<|L._drIP7rPˡuEL="[=.rW.?!>}.P"@2&G[""P^w5 X2}kFH+on)0{&GJ׶ >fPhlMy,uJ Z9 LWJrs9 /(ZZ R+ΦO֊nYwF0/X P Q} AU :G8t= @^-g ~b5@i]b1\7"E/z;b|ޞ#(Lk8R[J* u%n*AIKiqU/b]vV倾{ ^WVLA-`}E\nt{_NZ|Wa3sUh1fu+X=E/$GX6@~\' 87[~86M~.HB//^lrԶBTH,n>`{?D9$U }o\PJի9cQ\i%dz.r,m-+j`~[/̹A3Si@Msf%+>L1f׌r"S y^<'wL݃muW`Pl[(7SR16(~lOy@,l8Rx14]k?sk5U jMu>E^XCJBb\](۶s)e6bG Ҡa CD~[_.@ VRxK|98h/ BJm0齀E?c~*T Ez_un`iנ"{r x!\ 2 2]ډmE9xB, @ld[w 끊vxrAݻ$Eζk<ʅLs2ZBj> F/(}*]\ v4!`#WL|#ŷd|6S"sSXDž Z0f%"SvhrE]IV#E9n_k;k/ÎN>Rջjk/)R`*8?)L[pARdj`P(ҡLQQ[y/pVܾC+RPq.n_l/|V=dKVWq:\><)7X zH`nж 0lEx iYcX&CwC=O /TQQ_.PdJm c9L%ʊsJWoQ>e#Sc4_]4?>5JqYv`2Cow*9A.grbnZhB/sC3,8g l#[[|K| {)E0J}Z  3/so |})Z~61) [X &Av~AɊ0PnK\Y;0 m 8/0>2C@ELQ!||_.9}`Te z@[Tsrۧ^BW yq.Vx HZ/ o)!l7[us[PT2@)8{/}LW` !TC%-u{8j[+R^7#b|;<`%E˺)q^(SXDISHښ/ { +^Y$&(־ER2z1SP´^Lq9Cf-"Eӽ~#n)BQCW[Q|";Eջ +XKO+ QWHKzTB h ut Ţ{@ 7`a/-Q A߳CWd (S;#oT+25E=$BINർJ T9GpAe L'ˋrEΈrAE]-R#m|څK{,ڣm&׽L{q#W3{F:~lo`d/66 SW视ׯ'Rp`>w#-t3}CYMg 6mTd+_ѹu4>e3Ѣ#]\/ {.: X9mEb3r;=a/s4AG/+Ux3h n{ay 3uTNԂG傊빽["?۠}+j)-<Tz#d@wpq;R"<*СK|cpv@h@ #$)'޳}}וn#7U\ 83;A4[!?-PHT&΂Z "x+`g##mYLQ&;]0EkC䴷GHKsxA8~P7d1R"܋nx l@UaQ{",$~_.q[j<[BlftMrvȜoώ.?qPizblyam@Vt~trT?Ra띑Hx:L9KZ!-g!~o_g 4Ae]L >r߷_`,8b95@ GF~8pcBu6/4@r5AEBrwE G]du~@OESb`Q偳~ mݒ8@K\GGf⸭{-gRbg2XϨ2AG{ԙ/p rmAs~AfG1^Ӷ0{Wӭ9_nh>rT*Sw@u+亿MƧ*_..o?GBhr2S b~\={n0n*㻋qȃؑKAڃ_QϞ@[J!~OL㵜;| Q+^[T^^%؄jķEϫbx;<]Yt.+1A]C+J-.U߆fAe c}2e`F>!~[6.6Pkq9)"Puݢ'PxkإY<tm8~p(rSKoȘb"/f jl.eZl[xEby7"f;]m @=[)vSb69=u\PTz_8L_ >{/rh1fu+X Phnk!j0hm ת_9Q<@m6^o(?n& ɘG )>]7us !,!1q ߷!`v !^[k]@]P\i%d= X R-*FՈ4<0EF jK5 P,wh`z/(2:[`\Eyhs}r{͡nJ~g6>۳`C07}5<'Awƈ)jUs\u;6_[SVocW9̯_^"{ F/(}* ^uA-F_`/PZ/D|;:UN@ܽ`n 븐Dެ`룞!ڸ\QnHcZwt[#Y&ZL!"@̔e(E %o.!ھ:[Wk EHAyWhZiq%[eHyrx-@C)Jo*@dZ::"o0= }@) u= fEr<`v< "pžP(,ǽl>b7ui~ ui}k `#.fؠ1C> BO&wi|< ػ=;I`}pB y݃Pv/{#d%@I*˹G`ڤ )|VI+T: Г[s `fB 3or!ДCQb-LmkqzSef|'[$Xڇr ^we-xPrDK`)5 1*lv,{Hc;V|| P|$ي6@THmeb`h e|{c11*`X_y r)Ti`5ZLk wbS`1v,6О"FVTR`<<L'ހ_Syhu츂7:A#s ل3h/:Y9ĸU][|0EZŢך+= G_ G) ?f9X"d9-F "lܠ"9iIo4`ǽ_r4c703ŮWJkqd&@h r*gD4Pߑ L8mzoy $Lhokx7lu/Ԋ[Gtvp qp/N ^"N'muuU/;n,Vuc V)^ZԖg"`MZh }`R-vķec )u>旞*wgK({8 X{jqB~k-*WRd{|.0_q M kt^ l{aP|~AQ=бS6HJ– ѦViKN8}?SX0ZQ9]gJQ! *>w8ՀV>#ݶԍ2ߖ>~`ibOv`g,󨊺;n!n y",X>M@UA 7,gy@ "NP"ʅ< >2C@ELQ!||y_9}`Te z@[Tsrۧ/BW yq.Vx HZ/o7qNe2;wy9<|L)jE Gkotȱ6pIsDP*{Ԋ{ai[z69ߚ)u q.e pܮ腱Au6QR'$6^ཅ,vVEk̢W)RPh)(aZ/F8_~Q܏j 3ÖI"iAo}4`VwՖ@[DB~qIȱ(W,,*xhαYG)4셱e JZ!{vі7;}sgdmjEhǑl ;bZ}0([pR`pL}s~i0zaʡM(6mէ|pSI—V h;Pt:/4` Cq-~(e)倯BqDmXHEy.4LʳMݷ셜,>#-|k-V'ny<0;01h{k&R_J^Xh%`/Q jE żky츽!v(So 9P'|\DQ q4Л|Ѝ2#E9R@jq8Va桹Y%1Ďd D"\lB`h,:@< yXb9oGB(IЂ7(dro+i|[ISA.PzAe L'ˍE΋@E]pwiba[]priE{ :w8{qS+;nzfoT!+{G7%]^xE ΕGnE.U7u\g 6mTd+_[rWku<@-OG9H)([¦NVN!?j6`yny{m^,K!.= VX֋PkJeQ9Q ~_. #%5s{yD OA97 (>Y\\"&t(hŦ!%q[%"}&o̔EY׊E7@oJ,{ H djVs˷61`!(V 3H, (j[V(_pԥ/kq9%@e{ 0O1R"g#E2Dp_!G/ĸX5k-!z3&Sz d.Òno [_ߠ<ߢ&ݻ\mOvzg$R({GVdcz_&ky 佢])|v Go0,k<,xr+/0|^.0yRhXX?FֈrJ\]P@_S(26un(^;h8}@WlUx>M-VQ(|8nkxh0L&/=O@)A177&Lnf| ڣތ`(F8RP<@Q9ˑif~5gM,\r}"rHLSZ?x j[JGBy\42S| >T2/9˂t>=H30nDgv*Ƞ'߂?@vؓ(t*`L7q f k./#j-VEIӧkK#*6Xmgu c G?`Wݡ `E z9@Pj%bU-cfAe c}2e`F>!~[6.6@kʡoCE1q LCt@e>.fq@|^$/ Tk@uM,r[تu'hajշE7=Z#ta >fPhlMy,pJ; Z]!OK!O7'(*r)4V9\/(ZZ s14LVt[ ƍ\/r 'A6upd)f7P|9jDrX]ypmgi @vN۰9S3R_Hoy]@60S%(i)2-_%\9"!}@VҲ]cۛ`/) oO h/a->+}L֭P.V(4'a@HZ=n9CDq>h=} %/_/$c!P*ToTÊO96c?`ev|l, >v 0|Wi:nZd ZGJ.!.v@4c/ж/mr/RJ[_.0i.|X]e?/^r"S y^<'wL݃muWv:`Pl[(7SR16(~-אXpbZ0+'=]gԊy?)jMMk0{=@+򈁼@T1)/&!m;pR&_>P|d@l=.-ߥ]UB=?f9rCr@ۊy:q@c*t  Ez_ucN )ؓUk -fa423>9&ۊrXRoYȊ0w o)6;+q18V̦X/Zu#9Xk<ʅL%LJqwh ?4:PxD+] 4jeB"0!ŷd|;:UF8{q!!3 DYIqm\}@lg7f X0Xz7N>RջjkO> j f-{ E)2 5V(y{u e-Z+n_)8umM=$J *^u<`9< N V:lqVUN5 TV|I}5XGE9@)G(50*+Z! *RXռ|dFti> tiX@F+ 1]4Ac-D\M2g5_ ЄPR3,8g lrA!?Eyo(Be9H^#8ڽ*y ib֜Pr+WEGِGhJۡ(Rp[T-"8zީr3  ` - L9/B2<\t5׹-K?S}kA bU؂ZT#{oyfK(c>oh#5_.ן7\r F5A_>cN8 Ɨ;HEs ̂Պr? 1 Ƨz0ąV½8"L>{^x8֪^źfUA|5^A_.`sSL)OR m`NY^:Lh h`R-v{8 y)TkU_z# v`J({8 Xw/Ǯ}6yr%E*/*7ȷ8o_njhJQ_Y6Nΰg= yF-AMhS1n8u3٥zdp(۠C}$WJ[H^zD#mfm#?ٹXmيGl)#%1\W ^T(ķ/0K*GmkE]Wȴ-b|/0e]\]/) cl, թO$@mIlָLfBU$)E *3%L+ۏ#Q 0x^1Eڭ8"E:jY݅CW[Q|nղ"G$k鉢{E: iX 䰎"K۽ 0ӰƖM1!{vі7;}sgdmjEhǑl ;bZ}0-#d1UI _>0`¶-C+Ppm OɿZᦒ/'bw?>t^h& [P7.S(_'ڲ\hΕg` o gBxr8|lGjq4/_J^X VwɃ"b^ѵsv\QIv(So 9P'|\DQ ,9@ f8_nČr#E9R@jq8Va桹Ys%K AT?D"\lBj@0U_.GGw8%m0|I-0|կ9r@E]pwv+G̮]8ɢ=f} Dg>fEk }yA̷l`fɢ,@_ukŢ %U"譐o($mb *gBP|l7FG3P۲Br.E_3E ׆io.q n-|p ru'0yk\z z_>pUHQh6NNQ|@~QkqSb`Ϩ򁻊 ݒx'q})ށbL>p J ImF~0 =8G9ʶ9sirz742z1b8)XZ@u+&LSZ?xԊ<GB]4yA)BJr.U1 tp{F 0n*@Y% 6T'-KĂ;2Ua /g&3|D+J{Eiѵ@&|ķs5>PCQ#`*ؕEwO+RP/cI@ctAѥm]`V;T02 `pfc"uhma'= Qq9)"P5ܢPxk إ,>t#8zE95\v-ԥ7dLEsiNj.e֌(nw0( _ٶ.`  X)1xNiVWR_x [3a]7x9`v^DZȃ1{Y.D6[(}!Y<‚c.<"q 𵿿>lP(ycׄ}!R!zۧV|ʷ{YW,m-0#^Tg`::nZd ZGJ.!.h }m[3qu\0傡[ _0i.\P,iXz _.CrB(2:[`\Eyhs}r̴t\ug:}g>0m(}g-Zg[` 1o(z['<'Awƈ)9_`VN?]{έ=T[|U&,;] ~{Vy=sAT1)/o=B hj(BLCf_7/U i3Zf9rC·ѿt&@9@\7UG]scN )ؓVⵆ>G$ѠvcK@;(P(y @ldܠnT d)f )<;aShE9tAʽ.4|"g9+r!5ܢLڢ@G sG|Mvߌ@-٦0Nթw7:.$b7+)'@i6.Wԅj=RĘFXt<`ixdZ@2/z"Z̻03n)ޡP ڵB: Ã0k%4DpB+RPqU#[.q1nzur<`9< L 7  2hulPbgaֶq}:;e'j0ʣ5\2|DXeE9AP*+]G .=\/`}8涱F?56t̴EФsГ ]F <|@hyZhfYq g/t@^!f y1\^FJ*Tsjф"3)>sSh7̭Y cD361) [X &Av~AɊ hJ3VTnXxENg` ʞ ؄E@A Up6Mn'>v)i\-j@!.IQ$F~wnP#~[nilyf=})/J̣*RՆl=h9 >2C@ELQ!||_>Esl4\tmx$}38PP;hBt܀#'y/˸8t'2qr CfÜ+u/E@)8{/}LW` TD-9oqԶVԥ {Lr@Üog ̺{Y2W8n e ؠ:(Bu @[syD"#fBU$)E *3%L+ۏ#Q 0]af2)RD?0oݡBQ.s!?$XKO+ QWHKzTfD93{@ 7`a/-B!+G[Z`)ϝGm`fxߢGFbSo0Zbi=9T%傱oZфkQ}J nOHQr*A ǧ"2 ؄²P}zGU(|ڟ#j"G*y 2+6vrUhU=Z`_>0;01h{Z #0#-:Z f;FTAZh1t^h9;(Y$ހ]) 7v@wb(qe>."LK\֌ifF 4 V+ 6*UoѦ\t>@|d: _`( bkLxZJ I6Td:v#0;̼fQ-h2d>4K9Kdzٵnr<)XZ; rcLSZ?x !?|$E(3EH)WL'PCnjR>g\`ܪ/`#<]D zTÞ|@[Vewd_4]x/0S_.#wE _0؄cAk1mD`RjCοrL5"= (y{5ǒz*Ga2>0#CCopQ@;b\^Ÿ<.`kE_H2b`p8 >w `_x~p(rj:LM.B(bPh] >\`V}}kFH+on[0R`>NW`cPlVaf9S yZ yZ3Kҋ/p"Kau@1G#V#?C S觵[0n&`9 "Wִup./ j@Q´@^-g ~buAi]b1]1\fw_ 3'l#\4"4TnJ\@iqrAfb]__6иVҲ]cۛ@+^+ G/p~;h\~9 k^cgg@-f nO@  pю86M~:/H9B3(?f& ɘG )[\&n.W,[zVh1>οM(L!L2&}NćpyWZ}t ww9-i=M-G!/#R1%+~@b1lur}#A93ȴ6+_;z0m(}g-Zg[` 1o(z['<'Awƈ)l8\t=jy?)jM5?^ؚ Vy;p;Zbzŗz.[ZeBBz")~[D]5 U i3Zf9rCr@ۊy:q@c*t@#.v#2,>1^}*㵆>G$ѰWtoX+a#JeQb#+><)TxX0"^+7$9"_CW_**2Y-h -4pd8xdwq@4мA-- iX&>lSwG괷}w7:.$b7+)ج*C+Mr)bZ_.`` :V?ȴ:\|uAE Xq \Oe 3S=\+vBDmZq=HAŹ}mk81o_PG@Jn-V6j_lqVgaֶqľ|PӓZ*h!]f0?a{ {0J幡bp18IѵKz `#06v181~Nzr6ˌ_Z |5Bz޺r@I <Jt6&rP@}hdo/JPYN70VG q4x9VI+T>)uN'4fJ/F.>ʆ)avD?L6Z|ycehC3(#y r)Ti`P#tpC;@L1m)06OZbj}ucgB9 {)E0fS|6`F?0ן_>ì̎+xS6[X &T7 mil!]rz5Ǯ {v`k͕Eڣ#Ŕ"CD,G輰Wd:T1'=35 LՀ~/ Qd_.@ H1i /LbX&0/.:|V|<2-Wpьb@>[Cn;"N'muuo)60;L/Ja-}UgfJybgs#YȃG4`_#!@BJ!0 Kh 0n]Pp19 :]-ηsF#o[TTEG]`-#b_>M _XS1+f^鼢6 u'EQ=бS6HJ– ѦVǍpc7a:֊xqQ-I@`+KOhqԌT-7|4)k vȒ/GUԥq :\B`@ Ӵ+JXpn~b}'t˾)B ,.\hrg ib!"R|}>l>WP \4ǶO,UAb+ܟC`Sn4r< Â-t܀#',GkSS V\2f;Np,i3y還r)8{/}LW` ~Qo>ÒQZQb/72-vK9"̺ JP=b ifc T> 5'g@{Y}g ~;GJDLA z12+IQ܏j 3ÖI"iAo}4`VwՖ@NQ 9Eu;  䰎"K۽ 0ӰƖM1HV2-YC-n0 v ,<ƯmjEhǑl ;bZ}0-#>G T%-XZK PhBi>%kJnP|D݁#ЀM(, ǩH(|Q[6A>R@ "ӹl,;a{!'H _ZE vq@h_>@ 3h%`/QNؠV0Z+6xΎk8 t<97`neBx9?J\DS8R!]rwfZħH}f>>X fY,)QD3(gs ZG~eTa Fv!,3Ks[HL!(dro+i|[IS Pf8`][`_!r倊R3|V|]priE{ :w8/ }̊>@6c@xbD+G{ DIgW视^sf ؊.!`w7ڴQ)pkP|m(F "rj?=5x 0*¦NVN!?j9cuQ}@8##{m^,K!./`Wi4/P: 2SGD-_k90lU.H~ Ǹ}0m%̷l`fɢ,@_ukŢ %U"譐o($mb C8 k%`+ƾy6ro[![$HAWoOilhm Gޑ2-_>@I7 >1 P0|r\^7m >,|3>PHka}O(=pDr5@EB=Eq"kQ|WxE)^QkT[E_=mzoI|H#Qx3Eqn^bL.J ~ "ӻya/D{7#1p)^`>rLRj|K~'Y0/i=7 ؃64{_Gk|tm[`cPlV }ڿ,uJ Z]!OK!O@Q_.0_>pN9 /(ZZ R+ΦO֊nٺF0/X P Q} AU :G8owE \?r|3?s t3s[G 8ynLt[1~o|F)-|Oȴ~*p.|;\@+܈rmZ-ZZQ8߽,AjtxE Z̴l E.V@   58hj} (<@\5a_H`{?D9$ >;߆D xy]@43AqG_,><Jm5\0/Lѧ5ͥ_(^2_^3LV7*9xD\13ݚ"Pq%kY ,"Xl! Eo:d"<`s14iY40+'\g?pϭ T[|U&,n={Vyw 恨c Sk m;pR&kyiЌrЌ{hvUyks^,G9_ΰhmm< a8 P1 gaAdz Ez+9r,S)Z?{+کLoHl1 a=Nl+a#JgY17YcG ίwwZQq6_."X{wF (rFCW_**2Y-zh -4pd8xdhwjq4lQLC/`_(%ѩ:p"sSXDž Z0f%[!劺p\Gsܾҋ2 K0wZ)׶_RTp(SR4Z=P%CۗXg^j%Tw~,CջHRH(XRjoi LRmo`: g50= u^ un])D vyr"S%PJmka*yUV=RXջ>b7si si~}k `#.fؠ1C> BO&wy_@hqk{$GCy WeB/}h #`{1hr~W<)uN'4fJ/D#zeC)mHŪs(AF8k400l=x˽ueȔpo-T./my#߱-K`)5 E0#/?c5?| >RD#[Ѧ?P!]~=oh#5p_ݘ2~{L5-`hGsi0F ,1,H)2;4Zb9nOy?a@{#(V>[[|Y}SjY@9c{ _ @/<츂7:A#olB4`[{b*ǮW~>yB~Xf:W{h={Z r(.u2E+2 *֞Mv(GM3v3Sz5ਤA/pd@heT0ԌrAES/M 2y_5֪33\ (l#1zIlCԋߖ>~`i*SPL%-U󨊺;n!^ y",X<@IÁoYSeuoPK8Au *c p*-~!B8H)JZ!aF hmX6U9" ėOp|a`^ xq.Vx HZ/ o)!L\&pt;TmdשK`/V@ x1]Mqq9~Qo>ÒQZQb/72-v1s_0e]\ZlD ؠ:(Bu @[sEx"/fBUU\yR0#Sl?b(G5PwaˤH ڷUt y[G 0pjK OWXbzwak鉢{E: iXˆrA4m֌۽ 022lj }^9ڒ5`Oy,>2m3S80 _3xbSLϑfx n\j` Γ`/ F/lB9 צ n*iPr*A-vJSNlBaY`(>NEEo]P Oec# < 2+6vrUhU=Z`,K)XUGڞ~xZ(a^ ֽs#pAHaWtm:/38$`6(So 9P'|\DQ q4Л|^)ʑR|}r- 0+K*c6A`EﳹR ؄P#f?Ջr`2@<"]yXg|zGB(f A'|[I󵼜J  G<@6c@xbD X9;(<+RpԋҠFZR

Y\\"&t(he%bt̐ƒ^ZЂ-r=w]Z>r(_I@e"譐o($mb *gBP|l7FgGQ:KQ=_LQ!r#KV' F9^t[e" sVǐ _ bV5[]bZ^ @|{vt )ha_@]xXl#ۀ!5h=~"vwGޑ2~FZ{_.Yk*S\uG?}X]-kfoe;_ } >kȬkBzY/P}) wL lkqSb`Ϩ򁻊 ݒx'q G Gq[dL&ZL$~6Tdv#?`vqugãe[9\4K=mf~5g \,X} r 1-Vkn/[GB]4yA)BJr.U1 tp{F 0nD."b[bE9^ PJ}n ]`Sp~x-lNo5Zڢ4|ZbZbz"j( `Wݡ? ~b#^QR/6X%]oqtzv)ɔEmڸڸꂊ?C= A1./}8SDkE?H2bK\;t#T8zE95\S)ԥm8@QlcuZQTNgV+4j݉ ٶo=Z#tgۺk3b{(4Rc\]usJ@BBֈr@Qm. b:XV#?C S觵[s6g O5R?Ho)e#}%-E׳Z_Xs_>@+܌@ﶂZ-Jve oox(=|ǽ,0)*~G" Z̴l E.VM`m $p-Nn9}^xxl4 J_._>5a_H|EmQr/ )%`Blur}#A93w6+_z}`Pl[('` 1o(z @쓉 ;c* g\v=_޹ښzфe~zr/`/Њ 6bnP7*_ )l:|ba`J_>@3]}@rPQnT@UHmG#ŹT#D8/G b#(-g Ma>a#[@ܽ`n 븐Dެ`룞!ڸ\QnHcZ_`` :V?HaV~ SmHP03n)JiB{KH/3EEm> j%Twm  *^Ͼ1zAHyrXC*3utKWlSlPbgaֶq}:;evB Q_.`"w_>`v| "pY (ƊE`8Kk 6r_i 9:n0 T:f"Pwh9A.#Z- v,gB2w/()GCy WB/}h #`{1hZ%=PR&&@On)i%+̔_.F.>ʆRLk wbS`1v,6О"FVTO`<<L'ހ__Y}W<^'h-M?`kyC^jSD?M@{0"lCCBW yq.Vx HZ/㞚(RC@8LvtשmAEPG e/DZ7t51mD E`K*GmkE]Wȴ-g #-|k-V'n9|`zw`>b6#8/*MԥCHbI15`/w VwɃ"b^ѵsv㐀]؎kLQsv/'C@^%Ѧ}"7@@Nky_n1+M>bS/gTay F.{NI02|҅|zGB(f A'|[I󵼜J T2F 0́HQ.#(rfTw_k|څK{,ڣm&׹{HT9@Ǭc-Yܽo#?67G*FT_ýήO "J/H]F j9@s)Ц폊Lq[kKQjFPS6-j=  Ρ: X9%?x n@[pSIC)=a/ŃF }zs[4/t_.L`/(kõ0 6(`Y|TǶDqtx#%ȣ  Z{Iش3$$e^-h}g L9YE뻮|Xts$2}m/`9Q7y[YW_`<2g< Gy5;)WT(4FL G]dt>@ڡ|E)b`èr[E>m:nImLG q[Ca29@~ O@)A177&LnfaT@GP.p`yr#//5ninrs:}2>Wk\(4>Us`R<@GBy\42S| >T2/9˂t>=H30nD ,5|7>>F rP9>]`b /[rVN0(ջAxmQu=Zbf_׼0(z j(q vej`E z9@Pj%bU-cfAe c}2e`F>!~[6.6@kʡoC."2 _-E {LN7 8uEN/@ԥVZc_kdG 6`]#QRpH٣5>NW`cPlV }ݔr HQE8L:}ǸV9@rg}Zp6} Vt[ ƍ\/rcXT fP6NF9|@QLW/Xh8SSN "M3A8>0s6g>3"z;b|ޞ#xF )-ϳ#}%T`p bηrpA=բlXny&Њ׊3_Aj?WA,D6[5\>E/$GX6@~'`O'87[P-v8Q@m6t^rgP~/pM1(R}*aŧ02e@;>CX6{Cbc;߆D _>+4-2n#EqGp; ȱxGhB6kj9b )%-/y4_>P,X_>0EXg "yO6|8uٞPo0cmPmٞX_D vҴ* g\tmP+9$5;k0{=@+ܛ@rL,6 m۹Ô2Y#ZHzx} R+R]U i3Zf9rCr@ۊy:q@c*tȢr]unS){CD/\l1Kl L@.ĶVGld qMkO} l@sLT:f"Pwh9A.3x9@h1\@ Myyd99{7=py`C y/@w/{#d%@I*˹GX5b)Z%ϩfHs=5f!0Sz@4rQQ6?(ǖkC :Gf^ECQb}E SD#CLN i򉞬*'3| ,6rk+x 0[BoCLa Fh1BďX#KP@D#M=6PHmeb7/S.xoQ @F8N0RlQG0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0~_,֥W605| X>:`kՙRj,zDfI{0AEՈFb)-L|8̃}BJU 0TG`mq{{8 XnNcF#o[TNUi K ; -+#1|4p[LŨ,yxENg` ʞ ؄Ը٧Nr5t+KOhqhߖ>~-[՞->"Et9@By!+»+اiW=*P,O}#R ,\hrg ib!"R|P>6(a.cۧM*#؊} sam_W yq.Vx HZ/*"!L\&ptÐ W/~@G <\)"ro#еjl_>%@-E氤娭VE셽FbD0[Y}/L2zalPEBu @[s*6ཅ,vV⢵fѥT&Z/f J֋)W1G`ڽXc觝![qDuCW[Q|o% Zz^QZ!-XRSU@QiPv{4셱e#9 }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfx n\j` Γ`/ F/lB9jE\6So`pSIV Gj;Pt:/4` +~7.ST OeEy.4LʳM[BN -&ؓ[`_ =GÌJ<P+;``n`cD 'hE żky츆gM#5'CPBsv/'C@k(qa G]rh7r3˞&f )H}f>cp\ ̣fY,)QEfP ZG~Z3Sx0 e/ io=#!z3@ Zro+)R`*(jPz2js *Re9"_Pw6R|ɥO6ܽox$?4cc- 3rqt< Q!+{G7(J:[^xE Ε5hf$_}B?*246_r5/Pтrzj= s%46urC3*?x _`GobI; q!t4|X֋Pkn9_>:*WԂlf%5s{yc nr1n_ob TǶDF .Bpx*h2wi1:fHGmcIz u [603d{Ţ %U"]!?-PHT&΂@|mDV)FG3P:@Q[9"E g_"=@ZԍW@ucO&xp_Q6Bo6_>W9+cHQ /ĸU5[-bSzŠ/.<, iƿ$%"U8s_?u^(RT0SVbuM&|Zb$mPdzw#/0;̻h}3b4#s92m]` [s6SP`j킐뮐m1%pdry":[}`]|$ELRݗ@|(.t=7 ؃yv!,D ,.W" }"@y? n^Z(li,MRυw3GȽxwⵢיCF>r}'E  vet.pE o䡂Ws,譒 )o?e c}2e`F>!~[6^mkP7rPC.DL_-z/o-Ej]v `{_.(uv]@t=Pސ1 8[E"u/ Aֵm}+mhw0^ڶ` @l MX)1NiDWSU=㠶%*##1{rAE#?B|1&ݐ)jEL#B~rDa3fA> xL!JJ/<>R[HG ~b5@i]b1/w/b`V(B#? B`uvA{Axxl4>_(?^ & ɘGm`9\)ff],D3e7$f9^6$L#X/-2n#.vA4c>\@ֈ5\0m/̹f Қ_K_ *SQ3C׌rAEXgW7*9xD5>cf6-m6V`Pl[(7SR16?kHyڠXpb -%`jY40+W?\g?E~*ZGw${A#^33@Q9@CaJ\3#tB1 5\0=jVE]U i3- G/߶3:yu~X"LkP#^}FEK 1W }*㵆Ԯ*^D|cEvb[QWP..z|}`*6B-\@iYhm TZ"sS Aa J 6׊La *G~v~ln_תe mzۚbkO> P̔ePEj@Y_@Q[GZT:[VǻjzHyrOC*3ut mxӉ\ZopJNX[zm ҊsS6((Mi;E .V[D 2E4?յ8ݩ23 m{)'[|]f_X[y#߱-K`vprb [r-F#4c/%u(} DG]Ѧ?ھ_.|\&@fJk21eWk0Z Gsi0F ,1, GT`h}Sq`|<by@|6k ԶRC`1q` rxęY2;n -fϠ;AɊz0E{q"@&/8@k)X\l ' e +`蘂}UgfJybmop y% T7AXЦiPX6`~8FC5pw\N M@U 7,gy@ "@NP`DBs_. 4| >2C@EL: lUAVܟC`Sn4r< rMȃpz4E"xy\PQAe2; _'ۂD#Nj/B+Rp ^<]&fP6((`ՊWT#2m3Z)-5Hc6[]tj F s#!#-|k+Zl[/LGڞ~xDy+{J/QɃZh1t^h9;(YHIנ2P}ct^N!8Q"(:/p/G{_ԋ2#)  |skayܬ9˒% ""0}6WM>bz_(*< Fv!B;9gx$Ro=x94_+\Nm%E L)A+>hLwWx4wy_.)4V6X]@,;lKUk '>YGLs㑨>>0#wHǏ ňrwty8W\Y/K=\fc(`wЋ8oPhGEkC1R_C4dr`ܟcx 0*M\Ћr6b3r;쉷 {f_W:<'޾ГEy*-=!)[L;#rE-xl z @aX)q$`?cܾ0m%7 <wX.#?p̓k@HQz^\t'>p)wz(G]l>~zNiR} M-|p@(Bzx&g2r.P%3F~0 =tgb#**rdEw̱خ[s6U.P`j!]!]!ۼry":X.@?`>r+)BJr._:xAHp{P/`n?%@Y]DE j+W~ XS7qK F_#\ܻ~Њ׊ӌkk9@MVk Zo k|  ve>pMcK1zEI@ctAѥ6.0)ɔEmx9 ?C= A1^cqs{_-/c-vEj]v `_>p> +@t Pސ1 8[E".5 X5x$JwE7}!<A=,XQBk7%a)TT#;|t9Y.x9 Rj HO9\<6K4pa'm؜)H5R?HoQe#}%UEϻ/`.|;|VREiٮLAMP+^[_>^a_}"/pCX6{CbcoC"<\r@Ňj!6߱ĕV]B]@ڶf:G(SrR/ ݲ#Msi!bIu/V2/ A_Lήn0Ts"0m([(7SR16?v['EXwwfP/CW(~PT.dr )b ]h4:8A⑪x$dhBFV/[LW iYhm TZ"sS Aa vEm]+2m 7ɫHc׵jywt[#¬&K Of-{ *2 5P+ʺt8b]Wkuz^ioAX]i 0\y:\!B?U-+>mL'*s9k+a{&`m~׹_g,?5X "`(/{I#RrJ{g5.PE`-8Kk 6r_iPs.tX0lP1ӊCݡI' ]F <|bj =n]yd9s>o8{{ 6< njr:^wh*˹GX5b)#hBHs=5f!aVNȢ\l#4P)Xuz~n%} Z]ӫǝ*00l=YUw)'[|]fGX[y#XGߥo 8A 1-x-F3ďX/ԊLӫ]ohS(_z>/ 35py_ܘ~{L5-`hr#94_# Ƙk` |Dj w@1 ƧW605\JasSL)OkEtg*4`m hS4̃}BJ/`~_pa j4`9]7N'SUd]A#uW\!ȑSB-ҪojAONΰg= yF-AM{P:8 }?SX0S.Ꙓy($PC}Iv#1zIm9\冏6qgj'ؙ"KR.bnF< xj`]PҭV[X ݲ/|DPU8AuE qgP 3B8H_@ \4ǶO,$sU;G@:Ô> |`R_&A X=qX"ip{j>PQAe2; _'ۂD#LjG"V@ xDG?B<Fŷ>ÒZQr\`%E˺*S[}K\T@/ VN} XҊFQ.rY}gP{w"ķ((aZ/F8_~Q܏jnaˤHt_![qDuCW[Q|nRLK@Dѽ`aBZ70| a_(Zzpfز| }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfxyLU5\0m[(Gh‚kQ}J n*a=V Gj;Pt:/4` ~l6yA OeEy.4LʳM[BN -&ؓ[`_>0;01h{k&@,)fz<~Vv~`%<7-] mFSx0wpJڀyXs[HL!zrro+i|[ISA PFpr][`WbI .5# FVѦ#}Ur8tU`!m:| Z ̷h啀 dηgGҋԅ%v1ƿ$S.U8s_?u^(RTr>r<kf+ib9އF5~Gy!E= lz_>pUP^)TdZG]l>~zNi{FXwYѦ >`8 p~L![<3|j9ImPdÌ_.Нp 9ʶ9si9Ƌ 2 nr[F:]LBBBy >^2Et;R@?`>r+)BJr._:xAHp{P/`n?%@Yݸ2Iկ9|Aٓ? t˽Bp+wuc/wSp~z)?fb{Thl=:@au>^!OU!O5 *38Lg1/#QZ w SZ-8w&.Yr >Iy@ A['N2(aZMPG )t.VDѰ4pa'm؜)<<>V{GLsH#EEyrPz=٭(R/`.|;|VA kkQZk,SP<~{ԊGp~fwwr rS ̺XQX#@CŒmHS`::nZd ZG qGs@4c>|Eg{j9/ )Ur- _04\ ]xAe? _.b]`\EyԜ䎙{s}g>0m(}g-ζb՗mٞ>YD9~gbL`sfе|xk5U->|lф2j ?jE1y1D"my]-]eB}B5 U i3*Y9_ΰ|@m< a8 cAdPhyЄ|@U <9+֕lM%1\^(irj#{oyfKx_>@L̔|qc11*`X3<`|X$6cY0(hUd;4Zs63æ@{#+-(yLy;x~soP#0]4/` @qn0 }:]-,go|<2-W0E{q"@&/8?"^T qv_.p%`Y[0X̔t/PZKȃG4`SP/MӠ2 )5\e91 .Ӏw| :pH}!?J0[hrLӀ=h.0?9t)a-Xi7'{ENg` ʞ ؄EF-AM]Ѧ~7b|N5 a:jE`vQϔC! s(GbDғ mF P;N{Z е;SdIU bREjC6F< xj`]Pp @sp<[HQT.,\h38/ i;Ի&B8H_@ \4> lUAVܟC`Sn4y@h{!,H\GKɱ4E"x|-,<eGw;NpA e/D Hx)/mD P|KQ9,i9ju{a-g yz !f]B\l%P=b^{UU~P@4֜<\r!*$QE?bdW1ʜ ' QLOվM4`V3 iE vԻ +XKO+ Q+{c=Kj 3倢{@ 7`a/-!Bw3xhKP>e! }f"SX[jǑl `bi=9#St/kq~i0zaQ+ڴAT󵅛J_n >R݁#Suh²P}zEEo](|Q[6 Q4Bt</5`/di ^[bDher8|l كbD]pz+{_0070[1Zk!ЊFyEצBq GϚGjN ص)!*/'C@k(qa G]r}k@/7lP#r>3q8VaQs,Kw~ࢋD3/%`B>FSx0 e_0 P' ro+)R`*(ʈr"_.tһ+x </ SMFpwv+G;}L0^s㑨r@EsEkPmbD%_`pEIg+pSwHF nE.t/}B?*2n ׆bt+2 -OGjQs^\/ {.: X ۬Wg/`Om؋%5ȃ@o_lҢ<1BǮ(O_.L+jV6] 0c nr1n_ob TǶDF `q;REy(СK:Ŧ!%F z u [603d{Ţ %UGh Sw0|@!iSY"<79@m@Q[9"E g_"=@ZԍW@ucO&x- ># FVs/}J-{6 +sDI`!me9bx ̷VEPlBW69ߞ]~J/ZXgPlŌr@8dAtr™ ) շ(RT5_]>p;Go0,0~@|pXY1>\xd44ƋE nrs:}@EBBBy >^2Etk0)/0 9!˷R/{!G kT30n/`#<]DŎ\" >F@ֵǸf I[XS_M3>R+J:;xw6Њ׊`tc-( jmb9/Gz7]Yt \bN%bGذYLL}O, Doˡ\X}@ZC9󾙘yP xy]LCů}AE Ej]v `_x~pJPh:SPp>Esih Ʀѝ=mWT%ݜ{# R`hMөm,XQBk7%a)h y y"`X> 1s_hurgPϾKMMwB?Պn`L]"p%@r76)l9ow)D 3]T|Q@!ȃk>LcN;/p܆͙ӓz;b|ޞ#xF )-|Otxbηrp▥3{@:L-~a~;ԸZr5xEyrh1fu+}X}@_H`m $'`O'87[~pYD9~gbL`sʕkk5.k5U->|lф2uT ?"4o| */ķmSbP_bG1KqhvUyk `Cė3/߶3:yu~X"LG ydыrz+92,>1W ɵVⵆԮ*"qcEvb[QWloDEQLt@/S.xoQ @F8N0R``fGT`h}Sq`|<by@|6k ԶRC`1q`{ gߠg80_f-xS42M?^'+0wj {v`ѵBʑbYP,  bya嘛 Q}Z} ʡin`f]3|p s2D/rADrt42Art42Ar@qn0 ~ "B:;p/N$@:^b]szUf`X7ʙ}UgfJybm-@Ֆg"`AXЦiPXB`~AѰϡ5piq>Ixm4%@Tb{Ќr.0K!i#-xUa +:a݀*~_w"ʞ ؄E@A Up6uEz܈q'>v)VTfL<p(@{V"+GbDғ ن0ЌT-7|4<3ŞVt>YRu;ڐMy!+»+اiW=*P,O}#R ,\hrg ib!"R|P>6(a4|p.2W9BlI1Ե0O~}/B+wЄ.jrx HZ/*oНeGwhWjÜ+e:_.Z7t5/@ۈsXrV+"^y#S["y-|K۽ ZBuj03{+Th9yFDg Ņ Y40.U2Vr{% #Q 0ԭ03l)* };(il5nՖ@VXbH@Dѽ`ut~6C:e r@4:/ ua/܀0l/!+G[Z`) Yx_603xR=$9ʵ0Lf 3HadW=@e_|zGB(f Г|[I󵼜J J24Q30 3X})4`iK/[ `>bvm'h @u7p<՟_T1W\~#՗3`pEIg+pSwHf߿nE._}B?*2n ׆bt+2 -OGjQs^HAA/n6urC3۬W 932Ώ/ ':B\@߀z(Ocбk+AS*fd`I+J lv.yV OA97p1 P|ʸn*h?Ȯ9x#U  $v|ZQXkm~>}GH3SNg+_[, |WPeA )Lm @LAe,XVA{9c{Jyږ+~yř׆qjypZf*lK)}>W`#+Do)aFr'i@Q=hS)ƭbx ̷h啀 dηgGҋVua] K06 AGWtr™ )#R Do,B&O.uHo Mz#2Ea(> o;Q]Y\Mq?G` ka}\7Pz >jE =EqAE`/pԥxnTuJ{X}(5\Pbe D[8(|A(pM&k2rP%3&l"ӻyat*D{蛑?p)(t8/ˑi9Ƌ 2xE?ݚ 2Vk\w\wo@|ʽe! cM> 3EHw_˻@^ҿ?Px|JD."br%Ƞ'-TQ[bj*$]o`N`&Sp~;#|^wE7=Z#t{GkE*vSb6q.Vz_> *##1{rAE#?B|]jlVtK-<4J.!.vA462!-+XM-gm ) r)04nPZ"L1Cuո"SQ> 9f 6Gu+_{z]0m([(7SR16?v['hB__[j ?"4'@ rL\3m۹Ô2fGc"j`{Ԍ{hvUyk `Cė35\ |Z!6Z0GT1 ga 2_(E/v#r,^E >uZCj׋r7=@"L NJ.ĶxB,Pl䊹0XLqU>"gq"q~n^& OG`2<`9\!:eGMDe.g{-·L:-fVž:;e'`G?$*TdJm c91h10P %ynX.h?8KѵKcf1NU381~Nz?iзb㚯Bݺryd9s>o8{{ 6 Lj:{GFV*^#Eq4VI+T: Г[s `fB&`唍,>ʆL5uC;bS`1vhcb#ŷ\#7U"3)>sSg_ ߠ_y/) [X &Ä dE㮗^ vώ,\Y4}]4@9RLY1!ACl1:/lNg<椵'Uld7y ʡin`f]3ЌAfdz_@ f Ӏf`颩X&h87grHZpy@̣8@Ao)N'muĺj60;L/`X7ʙ}UgfJybkNR"tF#x=h[+ڔ{8 *`R#_F8FC5pﮛ iq>Ixm4%@Tb{Ћr.0?^.%l/#bT5@k)*~_w"ʞ ؄~`ibOv`g,JTCw=#z_",}v@IÁoYn>"E*:"ʅ8\h@(}d@KB!||_.9}"sU;GrQ ghs /+t܀#'y/˻悊8t'2qr ;N:@G A RhE Gk׌Fŷ_jE]^+od*vb|;<`%/F+T'{@Xfb@4֜<r!*$QE *3%L׈HQ܏jnaˤHt_![qDuCW[Q|Za" 9Eut~6C:e #@򁢥{@ 7`a/-/!+mC";}Cn0m3Z)-5Hc6s`N F jk)n@T%k a<%[.V4ai>%k 74\a@|%Gyn0o^Cћe)*_*FԖ"G < 2ur[}k^H PbDp /LGڞ~x.w(a^ ^xA%c 1\ ̣fY,)QEfP ZG~Z/Sg;6`84߷JB V|-/'"<|`w]e L'3Bo]e|ɥO6ܽox$|nzfo(FT_ý%O "z_H]J-w2Mg mW5_ѹu4>e3yE˹ j-\Ћr6b3r;쉷 {f_W:<'sP[cVTHQ|. 6] 0c nr1n_ob T7qaTd):w P4CAtM1C8jKb/ z u [603d{Ţ %UeGh Sw: T&΂@|mD+ƾy6ro`v{:3!@4wdpdExE?ݚ 嶌#Gu@Ewgp\w\wo@|J)W|GBhr)BJr_:xAHu~=h)؎~=AQ8b ,.W" }"@zu-]m I[XS_N`0:2.xxwr[}{"0t*0`WA?HAAhurgPϾKMMwB?m@㻑kL/B~ |mCa3fA> xL!JT|9jDXMyGcy߇bq  3'lw=G Lk8R[T*%ؓ**"bη'R {mKڽb }onse-~/<`v_>k^c P-f n_d B` +_}xxl4  %/#E& ɘGm`9\)̺XQX#@CmH_z}_.-2n#Ks{ ȱx_mi19<0m/̹FMsi/%.V25 0}/Tduvur}#AQsvef=nc%k^LJZg[` ďݖ OAc3FL1M&`sfе߹ [ZutG~}}r|W^xq{M{ebY\k7.s`kHܧ8^kH_b0 ~+ۊr ޲@+><\G"a)c`6}_"Zww^(r^ ~kp_kEB&u@-EL sG.|] -6B/`{_&ߒm q97߲?(v7.b]/RԊL+C/+M \" o(rt[#¬&K Of-{ *2 5P+ʺth2S(juv} \}yE *uEo<b5Z2<`9\!:eGMDe.g{-·x[8L{m(un) u= !QQ|_{I#RrJ! BI- 7((l*7XOlf1NU381~Nz?97{|]P M{J`(^t@gh(f ?{*E[KV,^#Eq4yVI+T: Г[s `fBfJ/D#r!Д~ b.VbE SD#y[hY&4 [[W&L9/B2|L-KpmGߥo 8A 1-y_̒:>#fKPc7LoLU=&Fk04ǜp/wc50 >L5uC;bS`1vhcb#ŷ\#7U"3)>sSo<0 ì~MyNj`6р dE㮗^ vώ,\Y4}]4@9RLY1!ACl1:/lNg<椵'CӀ ʡin`f]35G6 ئRANg5GL8mzoy $̍2@+R`n}>kwl DptVG<@ |zQm64 a Xgmc:3SӽCmkq:7<8{Nh=0eЋ2ڔ{8 *`R/_^ `mq{{8 X{鶫Rz@SUd]A7+/Lmx)/-bT5Wt:t^*~~AQ=бF-AM]ѦnxN5 a:XCTz[X (%=y aOL#ݶo a?m4L]O3ETsO[["<Ս2y`@ Ӵ+JX758Y-G(jAT.4@/(*-g paJyied z爠 bHsrۧ^B aK՚=ٱ?qX"ip{jx( χ 2qr{1OR1 5"`#(@\ (~;GTDLA z12+IQe΄g>03l)* };(il5>\>AO+,S]X Zz^QZ!-XRSUx_rXG_ ua/܀0l4<1+G[Z`) Yx_603xR=$b6#8/*M||1NM/QhE żky츆gM#5'v\BNdj;r1Ɖ2pE!׷&=Zr7uLH!G H3`Z&`57}β$`I|7.H40}6WM>bӺ_>P0Ux )>C)icY_.0 P&2^ Ho(/(G0 / < .2_#fN.}hD_}#Q}W_P\Z>f}yA<wty8W\Y7}7"@R%@w47(i"S\@|m(F "r|5˹ Ӏ_f]TB\/pF~_`_.x۰Kj9yG(Oc_&@q #/rE-6X/(Jjnq$`?cܾ-Ey-F `q;REy(СK:Ŧ!%nz u [603d{ŢgTYe8RD+䇹 IP&΂@| ~ j[P&|<਋Z)jP|mߟ)8ԍW@ucO&x- eIO3M^DGޑ ll?or^(n#]N'?p,5> ?`qW|rF3^G>Bu\ SPnSTdzm8Rf{<7 *^{]:=PWU.V|@D[8(|A(pM&k2rP%3&hqܾ/ v*8CߌCl \xc s @,[=xSP`j킐뮐mOR6:r{H/xcM> 3EH-^/znՋCX"<]DŎ\" >F~ j{ݲP,. Y؛8Ll0SԊ^ ~?Ukk9@MxWkhQ!waQt]j( `WAןW_.((y{5ǒz*xK;YLL}|< Doˡ[X=xQr(/_7iF {]ʢrUF\hwu/49z_@ {-ԥ7dLEsih .Ʀѝ=m^Q}XtsH٣5>NX1ۣBcS>nJf9STT/96L5~\m~RwF0/r >Iy@ A['N2(a+*c5kELO\<6K4sz6l~L0mHoQe7}%UEK/`.|G~nV0^[Ҳ]cۛV(\^ PjZ/yv֭h3#Z\oxk!j0Aю~86M~.HB//\d#BJw3.D3e xoC"<# z{.D~.} l8\v`ؠcC> BOVg/ \Phqj uB۽#@#%PY=ƪHQ ~_.U  ib֜Pr/Ȣ\l#4P)Xuz?&Z?^TGo r ^weW< va!7!/b4\@3rYRB@|$m'&PHmeb`h _7 r F5<z0E{q"@&/8@k)X\l hԋ+ }tL>֪33QH>P ʞ ؄E@A Up6uEވq'>v)VTfL<p(@>Iv#1zIlCyr|4<3ŞVt>YRu;ڐMye!+»+اiW=H-G(jATNфm 8/EPh)>S(cUz0#\4ǶO,$lN7H|9n38 y@H}7b rZSTPǡ;`Gw0|tn "/K/D Hxtc[_@ۈsXr {Ln<T&Z/f J֋)W1GT3d#v/֘" j/;(il5nՖ@VXbH@Dѽ`aBZ70\ 䰎/(ZzpfزьrAr%k Fx)>2m3Z)-5Hc6[]tj F s#!R݁TDyn0o^Cћe)*_'ڲQ<Ds&Xv~a{!'H _ڊ'B+/ӻyVi.8GPvjv~luLjN4ЊFyEצBq GϚGjN ص)!*/'C@k(qa G]rF 5 /4eG 9R@j@8+0YJ1Ďd DpEﳹl|Ъzr3(,/ߧg (z3` = ~ g WxyI-C_.Pwz݊ok '>YGLs㑨je:Ŏk\f'M pA<Q}9CVnPt{2e视^se/ pgҋ^}B?*2%!_ѹu4>e3)\}3 )(-P¦NVB~cuQ q1\yۆXRB\] <(>8!<1z -p/P:/dz@QRs=w0 6(`.o)h@7BVt ޑ*CфM^?;>-F m,4%"}&o̔EY~ |WPeًRGh Sw0|@!iSP8 [p4g#ݳTCԶ\LQQ=/JP|mia¶OTLZ|v,G=-k0+ } 1>\xd4eV\r3~@HQ6r/<+xBՈ`8"a=Q2cPڡ|ߥS o}@%Wn{;A(|B kLxZT L$@v@`èr=f!@4w2pde{G^v[s6ܖ|NP`j퀐뮐mOR6:\5Њ GBy\4)BJr>J1 txAHt>=f`V_Fy/<8˕ zP{Bl/- ȴB&Sp~{rOPzw6Њ׊`tc-( jmbjE5*.Gz7]Yt \_((y{5ǒ'2VI8T{d"| Bmx;3E=8:D9(ˡb<.`﹃xkKYTʊ݋dvw'^Efh:}u 5buZ!*Z 7cضxE]by7"f;jض>Mkq=Wt5NiDWSUS/ D_0Eo|$?PHϠ}8>~RcB~rDa3fA> X^Қ_α5"pড়.VD\%fp:P}a96lL0mHoQe7^bOvKX9"!5n+EiٮLAMP+^[_y/fw;E"a->?`aޢ -f PGV Bkqt:sC #` O)P(ynjrׄ}!R,+>،Y+ 6sH|}&`GI_<=.`J.!.v@4c/ж/WS)R/e1Fb%+~2/倊Lήn0Ts"9Vt h'p#Je!b#W }ySXPElywxbqM/iE]`w8fE4(~PT.drh1.4pd_P@U<28 h^@AZldE`C ķd|\ma#8{nw24Vv˛@Qno1}^8|"ǎN>"okZ)mHLafJݲ R"PB{KH/3Xg՚}݇W0&qq"qcbuZ}3Z( )7XzH`nYmo`:@b0L{q}uvCMO"?L.3fwN0ݽ {0P %ynX.h?8kOAFaPs.tX0lPm]x;1~Nz?e/Z |5&uU%0rlXWY4W 3| o*E[KvgPLa{1Z%=P9MLܚS3J0Sz@4((Mi;E .VbOSj? YpzSf ` -֕ "SN˷Pn"`#/?1G -7HT\vaL#{: @@36`ԡ|F{KÔ0_"{^&L|}Cr1W}_>0Z d#94_# Ƙk`L+ʡ*Md;4Zs63lnlP+RLo.Y {)E0fS|6`F?0?|Y2;nAlBOu;AOG㮗^ vώ,\Y4}]4@9RLYjP,  byat:7P1'=3ffjQI?18{*2D/rADrt42Art42Ar_]tV|S(cUz0rͱ&\AAl>90O~}/B[>,H\G6u,7`9b |(' `:mR1.I9Eu ieRTh u_-^3 {alو_Grȶd (S6޷m`fZ+25f{Iyr믋Nmhzs$$n9G*Bkq~i0zaQ+ڴAT󵅛J_n >R݁#ЀMXXV7ʷS倯#jF#\hΕg`ݷ셜,>#-|k+Zl[/LGڞ~xZWB9FT۩ s#J "b^ѵsv\Q㑚xvmc;Ae m 9P'|\DQ\ߚCPdj/ZW3H}f>cp\ ̣fY,)QEfP nc*ŒrARcx `HsiU/pxl._!.Ȉr;?4x۰KjuU luz^|\ -p3Q/ `5(鶻V OA97p1ExKQ|G 1,JKY!aK4{I໴f3WZЂ-r=w]b3R@oJ,r#E4ѻB~[ ) e,Xn `g e3y#@!r#KAAo'`#+D>%l41R gb*Vg|K-o_&ty%`ٵ!_.@]xXl v h87P {Xrm6L{3)*{G*dr L[|n9 ]L\P| ^r 7yo@C} GF#̃2/0SVCa29X} O*hq/(lU.qތ1<(ۂ.ALc1^4n+֜M/7=x)XZ; ++xS?xz)2/0 9qd)u^%?b~ q<!] _>q[}A1b ,.W" }"@kz j;ݲP,. Y؛8L f #|d\L@;@X/o[r_G^j_>Pbb A_r@EXgW7*9xD5>cfEm|8uO)>`NI  Ed:dEy1b -%`s]{6.k5U->|lф2~?^8qy@kf| */ķmSbq:a(92F4 yk $Y9_ΰ |Z!6=E?cի| "bY\k7.ZRZ05P`OSW5v/T\ {L7|rALp#Je!b#W }y*f>D)<;ͻ> *>_"Zܸ;i0]Pr\n(SR#it~AqUȸhyW-- iX&>@|K)|}68{nw24Vv˛@Q+F6cspE!5A )bx}?*SR4@P̮A+Tߨ-y/"XܾC+R}]g}j81o^_PG@JÅ~R[@dhullqVgaVž:;eT+Ź|cD2`vQrE9R(ƊO"AqMkO} l8<3{AUL+u&}&w_Z |5&uU%0r}pB _.0:{GF!+JZ{$Uc/摢8<@*: Г[s `fBfJ/FzeC)mHŪs+ Z"YǯCUNT+2 mq)'`,6rk+x 0[BoCLa Fh1BhF̒:>#ȮhS R*~y0 m B{@s⿜+jThC3<`|X$6cY0(hUdu8PL1m)0G;l 1r[ *P^J rǹ)j7ן_~ן_>ì~MyNj`6! [{bc׫?V4ّEך+ c=yAP,  byat:7P1'=3ffjQI?18 2 ~@4Ќr*gD/X2ŖL0]4/ LP CfNW [>z0E/ l DptVG<@VEmVa v_>JasSL)OR H {8 ؃jD#{жV)pT>V!_c4 0n]Pp19 :vU`_J0[P9UEi4 L20&#KWTʲWt:t^*~_w"ʞ ؄E@A Up6uEz܈q'>v)VTN C?8Հ|$FT/= m/@rGOc83Si5@L%մ;lbR~m ^f <6#x~բzކ+tVHg1U薪-uov`DBsD8!KP 3B8^6ᑐ0rͱ&\Hl*Tl/mp|aD`Kulb biދEbh^F L\2R3 _'ۂD#nj4\)"ro#еjl_>%@-EDpV+"^y#S["y-|KuT zAP06"JZ: h9yFDg wVůw'*RPh)(aZ/F8_~Q{#VLO y[G 0[8t%ŧ+=k鉢{E:jto`IMU_rXGLv{4셱e#9 }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfe䜝<*Bkq~i0zaQ+ڴAT󵅛J_n >R݁TDyn0o^Cћe)*ʡ) ۟#jF#\hΕg`ݷ셜,>#-|k+Zl[/LGڞ~xDa%̌rWB9FTG/QɃZh1t^h9;(YHIנ2P6D@whCC'yDZ(r ._nE_.p#}r- 0>gYPDC]$y@>+J&o#f? Lf ;6`8ei`N} ԛ)sMhVRTP7"_>wWx_>E]pwv+G̮-\dm3G3K>>0#wHǏ_xD1,Gh;AQɔ)&SxE Ε5@ߍХ4|A3K8oPhGE­PLCZ{/EA/n6urC3۬W 932Ώ/ '6Œ}]BpUP^)Tdlpԥnx?.wvA^QgT]E]mnI  G׀sL>PW˹@@Nhq܎/ *8CwF>1<(ۂ.AG1^/z74~5g \e }>rrb[)]F !\GB]4y!˷R/9F jZBl/- ȴB&Sp~9[4F_#ϻⵢ4|ZPbZb9Gz7]Yt="򁂒Ws,h.8T{d"| Bmx׊ʡoY(ύfZ{`m/V|[_c"nu'^EF a4.@]4nùb"Qz}VhlGw"x.漿')0{>϶u >fb{ThlMy,sJ@z)8,.A#w[8ynLz;b|ޞ# )-%n*AIU~KX9/niPﶂZ9zrZ#8x;ԻZ~z\f-bŪ6C9.V8a@Ha-NNXܰ_>/p@ʏ\ZrV!PR}pŧ|u`xoGh1.`ې0/`::nZd ZG qGs@4c>||sG] _.R傡[<`i.-@,X\0}!*2:P> 93ӭ)m6VٞP::cU_e{:dEy1bi29{+@[{ݿsVzr/`/y@v{ 您c S| m;pR&\ >RSC)4D|2F4P<6|Trr·RjH glxz/Adb7(å1 '1u 4AUL+u&}&w_6Bk&uJ`(+یG3Eyo(irvGU?~4W\)>MLܚS3J0Sz Y} y"[hL Cfo0E4W;U`ap{[ޭ+D?+B2<<+1T#Qw)0GA b)l3h1_>@3(H4[b)T2 0 mJ} a3K} @_.p1'`"s ̂AA;"SMݡ(yL6X9lml-HMm/@9c5/~_.paV̎[<^'hdna50~ NVa1zɱՀ[+hHk͕zOE#ŔX"d9^+aEsړܡi;\4c703ŮWJ_. 7) `Z! D"L>{^xKq:i#~E >W6> ~K,V rfkՙRj[3P!@,؃E#=h[+ڔ{8 *`R3_fv 0n]Pp1@t<8`=4ж%@Tb{ЈG]`a:<4WTݰN+CNDQ=бS6HJ– ѦhS1> @0NaLr0gJ桐Cn/0opRhw_.@rGOc83Si5@L%U)yHQ _" ksD]4 VMMb}'t˾)vsAT.4fBQT͔-g paJfͱ&\tmx$}ԇFmh< $Qyz4E"x|-: L\&ptv&<̹RK\0H)8{/}LW` \rFŷQ[ {Ln9\PÜog ̺ JZ:{*T 3kBuzJښSG =\`V.DK.f,Tʄ[f$@2gɂGf-"ESAz_@wPSsfGB|Za" 9Es@H9:LUa@4::Pv{4셱e#@r%k Fxm3Z)-5Hc6[]TCuj0Z1Ŵ `[F|@Jf Ƃ׵84m MXpm OɿM% /WXE7@|*"ЀM؎Cq?|\vUh"T#\hΕg`ݷ셜,>#-|k+Zl[/pIGR=H8/*M||1NM X#J8y@+R-] m9ʵ0LPW˹@@N#ł=#Нp 9ʶ9+*g /rdxE?ݚ t2>Vk 1-.k4;#댒$Ya$x6LqYf 5K@BGB]4y!NPOcqz؃j6@Y%Ƞm~ Ϟ[V3r{W0{zd /]S8[$>GjEIw]hkEiѵ&|ķs5>_ ve>%ǖb/xEI@z -.awYGL}O, DoˡXX]xQr(wg4TnTxk إ,*Wet#8z(r4\vqP[?'oyֻشBc;AdzmwE7=Z#tgۺk3=*46Uca}^xxl4 J_._>5a_H dq>|eKY|` /Msi!bIŊT! _>P) y^GyO?09X wӆg{B\l!V}ޖ OAwƈ)9_`V?]sk𵚪u>1 y^Gp~VY{ *\P| m;pR&\ >RSC)4D|{7k@ @Ӿg4_+-Ur%a(mk`>Rç,^K/ȢzVrY\1W ɵVⵆԮUl1F^!3wȱK@;(+P:@+F%@cG _ t(XwwfP/CW(~XQ5ܢP@)vG#aTf ;\oy@|K)|Js@ܽ`n _Wu_Vv˛@QnWFs8zrEn|DջS_~ISq P̔ex&>` dP(ҡL-y/p^(LQLj|}tC[.Tt_.<_.ɐR{pTf^iM-L'(0[ոô,L@s;NY~Ij3b/xRj[XS>@)dcŧq|0AoPsåѵKc}_4(9u`,6iEФsГ.#_>PhyЄ|@U <9{7=py`_c߽#@#%PY= *aBH)ib֜Pr#Ȣ\l#4P)be- Cfo0E4s(W;U`ap{[ޭ+D{ovEF_`mc["^rBFHst/{YRB@|$y-1S~*~q6ZgǍ)Ĩ\b f /8N0R``fGT`h}Sq`|<by@|6k ԶRC`1q`{ m1Ŝ~U: `ouFV gЀ dE㮗^ vώ,\Y4}]4@9RLY1!ACl1:/ls1*/րw ʡin`f]3\A8ny{FP9 "teESr BÐ>6?3-[G =V½8 ^RNxumVa v_.p%`\,}L)OR  q[AU@\m=yUH0TGaC1 j4`9]7N]L:[ZiETUd]A#uW_>0&/-bT5Wt:t^*~_w"ʞ ؄E@A Up6uEn8 r0gJ桐Cn9's#1zI=dqa%Ա;N{Z е;SdIU bREjC6F< xj`]Pp @ Yn>"EQ Tr9/ 4b!"R|P>6(aful4I2WsDP[s9LӀ_/텰 qٓ#'y/˸o7qNe2; _ 8Wu LjG"V@ x1]M-p!~QRnOGm.b/72rA1s_.0e])q^T@/ VN?hkNEFK>Bx-g1W (~;GTDLA z12#*s&ܞ,xDaf2)RD?UT7@wP:jY¡-(>Nzwak鉢{E:E?!2U@r@۽ 0ӰƖ!{vі7;}sg LkEl# #@nu1ө7-vbZ}0-#d1UI׌rA_^ضrԊ&,6mէ|mᦒ—+bw?>t^h&,, ǩWPfqerW8lA>h υ\y _}k^3WAq@X4Q^#J^(Ljk%` Vw(AHaWtm:/px$ހ]؎kPB~;r1Ɖ2pE!-G9:\3r#[5]j@g>9ʵ0LB{0ڀCʜ7#!o0ׄuZ`"p/'h98 A|(^=@I-h2|"g.XtGwV|][8*ߠƋWu7p<_cc- 3rq~/er@xD1,Gh;AQي<+Rp]J#_36mTd+ :Wdjj9}f>Rc(G zq ԶӀ}g6bg3obI; q!t4\VWEy*c4<3rE-x9U "CJ1 6(`.o)O@Mmt `q;REy(СKg!%F3,~}2Ff,z"]WXPۿ*ˌ#E4ѻB~[ )LB~<h5A]*mBG]DLQkC䴷GHKsx5<(>Lj"܋nx l@UaqT)#b*Vg|K&O &J2[ ?-3 K6b9  HEMwmOvzg$RTm ʬ?Y8+6r/|B#.)^ ^~NiF U>Ѧ=9 _P|9 `ǭ\>i9~8n_FGoFcx!P]Lc1^to9+֜M/9|:=L!׷^QZGSx/GB^4!˷R/cxAHs=^0n/`#<Є<8˕ zPzDm=[ewd;·}%psvNw8O\yw\x:{&Zo CꭒHί{L]VW_.((y{5ǒz*xKn=`V;(S0x3r:=o70?W=8:P4TznTxykإ,*W{;N^)/9=hPҺbP :-{ N׶K,9F@њaS],XQBk7%a)h y y^o|$\PHϠ}8>~RwF0/r w,]6)lR :G8ow)D o/Xh8SS>"hp,A#Sb]s6g ?O ^{|pȷ2TJ\/'UTE %,ŜoG h_{[xm-Jve ooZڢp: qooW=/WZ|WA#(3m[BџPBxk!䇵89a]r|>hwAJ~_x_./$c!PR}pŧu`xoGh1y`zn`j&}Nćuy+>L@rm[#3֌rj`_>i.b*SQ3C׌rAEXgW7*9xD5>cfz`nsTӆg{B\l!V}ޖ OAwƈ):?`V?]~[Z;z}^ {ǽVyw 恨c S׌rA|[r^K薮hu2Q3B1 5\`uc?f@ JK,o/g?j@BJm0{~6gWDUR#4%PYN70VGhhB>B*@J͸x֜Pr/Ȣ\l+*u1[hL"J)@8ݩ23 m 2| ,62k, µ&K`vprb [W#4c۱P@D#%aJ/Bŏ.{_F@k21eWk0Z Gsi0F ,1,*2 b9nOy?aSl=Rp RC`1q`{ _ ߠgpmxlBOu;AɊX BʼnD|tVG<@ |zQm64 ay Xgmc:3SӽCmkq:7<8{Nh=0eP_UЦiPX{DJ< îTc :vU`_J0[hrLӀ=Q2؈rG ҈mbWP ʞ ؄EF-AM]Ѧ7b\ @0S.Ꙓy($PCݛ}>g%JQ$Fw6Ћߖ>~`ibOv`g,JTCWm&<Ջ2y`@ Ӵ+JX758Y-G(jAT.4@#BQ#3TZ #}%̈rͱ&\AAl>90O~}/B aAu&G>B]Jy/˻悊|(' `:mR1<^~_Z7t59r̫X} A-EDpV+"^y#S[/0.!.ƂVNnh i*{PG}'Tl`׽Lr!*$QE *3%Lt$bD9nO<03l)* };(il50Jڇ'iE vԻ +XKO+ Q+{c=Kj 4P[ut EKo:nL^[6_.A-YC-n0 v ,<Ưm֊La 3q8VaQs,Kw~ࢋD3(gsE ؄P#f?倂3HadNI0s[Hs,\zVRTP7g(g0 / 3\WTj;_01priE{xLs㑨>>0#wHǏ `7pL%O "z_H]J/z_>g mW5_ѹu4>e3EͱGzprn0$rl4`*^ 86&}>6'RPj;L{3)*{G*dԴ/P!w68뮁P8u0nwxF >7 <wX.#?p̓k@HQz^\t'>p)w>u)=*^ ]9]PWU>pW@D|p@(Bzx&g2r.P%3Z#ł=#Нp 9ʶ9si9ߞ)nr~,X} ++xS?xCGB]4y!NPO7gί_ A5\q[}Ab| ,.W" }"@kx_}ݲP,. Y؛8L f /ww]hkEiѵ&Yb9Хz$RaS,?\~@A۫9ԋ 4VI[]Jo?ZXLYA֡CopQ@x9rQ4TnTxk إ,*W{;{R9_.@pJu >@C+VCT~Ʀѝ=(WT%ݜ{# R`hMөm}TYh y yQ_>a:`.x`^G/*Zݵ)RgݧO[mqnr+*ꃜ2}e>E!mND o/Xh8SS"M3AhŘ?ԫXs܆͙Ól#\hDuz"ߢ5a_H1 [] ~{@#^33{ 您c S| W|9+ZݰL\ tQQ/U i3*Y9_nϞSA!BJm0mV%L_ydыrH<7 0j@=O]p֐5|-h+df7\9Vt h'p#Je!b#W }ySX("6;xbw̦3+SҌw/^yʅL2ZL!> F>P.> 4:@AZld_.7< %Tf/@o#F#8{nwv2P+2m 77pEs>[(;:]GYmMPk1E)0)L[pA UdjV(y{u ePZT:[VǸz3R{pTfV6l-gaV}uvC OP_.`(/{I#RrJsPһ>b7(l*å0=cEn7 { vw 2q0G_:Bk&uJ`(^t@gh(f储|}hdo/JZn`{1Jz\r9MLܚS3J0Sz ݩqWhJۡ(Rp>@"J)@8zܩ3 mw)'[|]fGX۽eI-7HT]x;րuq,{{YR>:@|$m'&PHmeb`s @kMs،?rhC3g y r)Hl0\`P#TSwh0)m0>fShM 8GjE`vQϔC! s(GbDӗEa/m#짱 v)k vȒ@M@UzSX ݲ/|DPU8AuE qgP 3B8H_@ 3|ied z爠 bHsrۧ_B aA7b biދE2@[DYx>`Gw0|6\#LjG"V@ x1]M- rM5\"P^F.ZQr9/u q5BurDUN{U`f8V Bu @[s*6pM k9h;Yt"֋bdW1C 3ÖI" ڷ)BQ]7ħ)ڀF7+ -=Qt(XXG,[_ӼySrua/܀ܲ|Grȶd (S6޷m`fZ+25f{Iyr믋Nmhzs$$n9G*_. ^`¶-V4ai>%k 74\a@|%Gyn0o^Cћe)*_*FԖ"G < 2+6 o 9Y|FZ*4V=Z`_>0;01h{k& >>x^ Qm&` Vw(y6ЊFyEצBq GϚGjN ص);g;r1Ɖ2pE!-G9z;E\Ԉ#)  |skayܬ9˒% ""\Q6!TOkiP0U_G #pJڀyXs[HL!kB#x-/'"/(L'r93uݥFڭ01 }L0^s㑨r@EsEkPml8 &G{ V视^siKiA#pFߠЦ폊Lq[_'LCS6Z{/KC .'NVB~h6bg3obI;>G3t4\VWEy*c4<3r{N% ֈEILaؽ(k]tqzSԊqqt ޑ*CфM^.6-F{fdm, az u [603d{ŢgTYf)Lm @La(gB "c<79@mʄG8{akJP|miioPP7_<(>Lj"܋nx l@Ua *6u@/Vk-!U|啀 dη)OE kVԅ%vaܞ T8dAt~5i&P?Ra0XRL0i˱p xO?`<<+ 0 ,J|Wz@Bhz_x(>P~Q2cOߥS{EQwtA{'q G)qwg2@z&\-U1Sc4XgTy@|3O1zMos92"x ~5g \e }>rrb[)]F !T#!.@fR[[C)旟f k=F 0n/`#<]DJAOZ~ <6 *$]o`N`&Sp~3|]<{ZZQu_>`tc-( jAk1mDp̓#PzS,?\~oƙ+J -.awY}1@)31:rh5V(^+~(zAbXf(ύf*~ *RpRzwN^)/h8]hPzbbuZ!*ZPc N϶uWT%ݜ{# R`hMYEM>fb{ThlMy,sJ@z rS ̺XQX#@CŒmHBW;4i;t\J~;r,=|݀Bo[97|`B4ͥ/%}+^PbB /@EXgW7*9xD5=QJ׾^6_a-)b-@6(6)bL`sfе|j\:#~/`/y@kfq\s dBķmSB G c" _>`uc?4P<{FR0![B߶VH #5|z?Mkk2}_(E/v#,.^E >uZCj׈* a;pX%`(+P- bn-º@ap#Sc`6_>EXwwfP/CW(~PT.dr )b ]h4:8ך7}⑐ Y!`g 0/o6OFw7g_ `sȴBH;.$)bqp"ǎNgaV~[ZLQ|m%E L'@e 3S=\BJe]B:}):>>"gq"q1nz^ur<`9\!:eGMD+-j\a{&`m~׹_g,?5Lt@f6X9lml-HMm/@9c~soP# 8GjE`vQϔC! sP:ؕĈ'A4wL#~[nilyf=})*P1)"vPjy@ÊS(cUz03hmX6I檠w b+t!0)}< $xq.Vx HZ/㞚TEC|-_>uR-@uR{f=<)"ro#еjZǘC%@-EDpV+"^y#S[/0.!.]@e p% *S?=( @[s*6pDG ʅ;߻|D)L^0#_#"cDq?f-"Eӽ~#n)BQ]m DiE vԻ +XKO+ Q+{c=Kj 3倢{@ 7`a/-QR!+k`) YZ֊La %k 7۰#(82 ؄eu|&h6yA ?|qymqey.4L]bvrUhh1z"l vӻy B/% ԀPvjv~`Z V0Z+6\3款A|v\Bx9| Nm0U MDnxp@ozN~F)H}f>cp\ ̣fY,)QEfP ZG~Z#Kˆ@ .5<׺J`>bvm'h @u7p<_cc- 3rqt<  vGh;AQي<+RpܿiKiA#0yJMv+_'LCS6Z{/KC .'NVB~h6bg3obI;>G3t4\VWEy*c4<3rE-x96X#%5s{yc nr1n_obZ<Tz#d@w"<MPd%bbt̐ƒ-dh@ >̷l`fɢ,@_ukEo?H+ /8RD+䇹 ۋ B8:=@Abg##\Lx.Mv;a ׆io.u@ؓ ^Lj"܋nx l@Uaʕ9$EPx@[Ū_o ՛"(6+Ȝoώ.?-3 K6b9 /ˁCFDwQÒg746VHQu;rT!-G@ֹPea|[e'_{܀'08+zX&rx4me!H'RԱNFMJl7@+WBjusbL vG]l xc~:NiR/>Ѧ Ľs( `ǭ΁dbuL&3*iOhq~_&(UGp 9ʶ9qi9Ƌ 2xE?ݚ 嶌#:ML3BBBy >KJUH1&'"w_w^Elg|0Mqqb<8m8_P%ں8W\P!zk>+wuc7q٢ `0:GjEIw}ZZQu_0؄gv. b)@N: X1ۣBc"+*䩾/J2yx)/Tk9R3(gߥ&ΦOjE|`o \ P9P$^ L֭Pt Fֹi` nE;nV}Nxxl4wAJL@k¾y@QHQlN`2A1AC|&`ې0/`z<:E sl_wp  X2m[6Tz_߶^P/SՋ_Z LPbz_&^*2:P> 93ss=g6>۳M` KPA&uZCj6A[̅p)*X%VP(\17! 䪘=I{3%V8/xh-V/`J_ȹ_8(~PT.drh1.4pd_P@UmL'*s9k+a{&`m[t ) ZHQ_&`3|_0< E(@)ml>b7(9_ Ǹ޻09yaPs.tX0lP1ӊCݡI' ]lbk{$G8g>-{ vyqL^FJV,n`{1/JBeHs=5f!\aehdQQ6v(\P=?dhd-PN4 [`UhNf 7x*mYl/ k, µ&{z4`vprb [2-F74c/%u(} DG]Ѧ}hԶLlL|}CnLxoQ @_&p1'`"s ̂AA;"SMݡ PL1m)0G;l 1r[ *P^J rǹ)j7 0Y2;n -fϠ;AɊ"io̕u؃y`ObsOA0D4r-F "l@ǜ7wh~_&rhb׫G% LASi /Xtl?@~7 2@+R`n}>) `(5Pmr[I[xuU/;L/EJa *gV)^8D=b{PU4P tMӠ2 )uLy1 . pXLփj3ATNU)vy}_p_?/@S_p[LŨ,yxEN}̡u'"(a:})`TiA m*J28q fE=S276P|'Iv#1zIlC2ilyf=})*P1)?xtϥy`@ T-m2@Am:zw@‹0B TATNфm 8/b!"R|P>6&<ied $s6H|9n38 y@H}7b `wOoeP&N.8uҹ-H%kE\a@|dg0%LB6aaY`(>N"7.STCS?GԖ"G < 2+6gBxmE v/ӻyVi.8GP fܠNb^ѵsv\9t ^h \{98RȑR|>X Gz, XR( ![-3(gsE ؄P#f?/S_x0 ey3<B7S\J.'"<~_&tһ+x <L+D΍2./ _#fN.}hD_2|$ynzf~{~L(4n07B1G?5~7+72 &D1-}޲̕gohBo56>Gv'ӧl#9H/_g Ρ: X /۬We77{m^,).i~Wt)ؽԓQG(Oϵo@2Í2Af\Q _ /6\q$`?}7`~_o)3PAqt ޑ*CфM^.6-F m,B6@/3|f,z"]WXts_ p25zWs˷61`!_[슱og e_u"_3E  -@A8~P7d1ld1ۧ$ނ-}Ur8tU`!eUٿ&0b7EPlBW69ߞ]~J/ZXoe y  HEMwmOvzg$RTBȽi SPMSTdzm8Rf{<7 *^{]:=POԻoh{KG(|A]G=k2X}]*7@yXkT@|f8e[:<4ƋEz]=xSP`j킐뮐mOR6:[}R0 9{2Sz<J1 t>!] -`;Ao.(4a=3br%Ƞ'-T'_ t@`L+dao0z.)? Gh-Զ~?Uϋ7%6]Z @|=ToD v~#`*ؕEw)(G J^mA@o@ѥt70)ɔEmx9v g{~qtrPC.DL_-z/o-Ej]v `C|:] +@WSwJBBI]@",h .ƶ"CзfDI.Gk|Num[`c GƦ }ݔr\ +*^Jrkuz@KHT]ˑA!>.5p6} T+\`_p%@cX(lR u6i7Aŗs{M))צ}v |T;Vp'm؜)<.`#&9aZ"ߢ

"~_.w/fw{ruxE@9@i3غb,a|÷PX-y\P&`?}\@ʏ B2E!zGXW|ʻY+ 6sH|v [`j&}Nćuylj] X/ж5l=\0m/̹f Қ_Kz/V|25<0}/Tduvur}#AQs;f 6Gu+_{z]0m(}g-'*b՗mٞ>YD9~gbL`sfе蚶sbjݑ_u > jE1{;@T1)zŗ\@tE @0!Qx⻴ @Ӿg4_+-Ur%ܞ=Z#K6w0GT1 ga 2_(E/v#r,^E >uZCjKUl1F^!3{ȱK@;(+P- bn-;-b#.p#Sc`6_."ZVvoP/.(~PT.drh1it~AqUȽhw8FVL|#[MeBz6b4M:.$b7+)\+2g\# }]`n.#¬&Z"R`***$T03n)TiN]m,:x5q=HAYܾm|`{[@cFty A O#SV"ZTfV6o0= [-b_ @Uar③;-{:ExE9vI/}hdo/JZn`{1Z%PyR&&@On)i%W)<|Tbv(\P=?dh?Z^T6Xx˽ueȔpo-T./޲$ זx$/E|F}kA b)lv,{{YR>:@|$m{| m?LL|}C#Ɣ^cbThC3Gy r)Hl0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0E=/soP/ {v`ѵBʑbYP,  byat:7P1'=/QF`f]3Ќ~O@heT0h`: h _.._>ef sa{ ̷l}>kwl DptVG<@ |zQm64 az(W +`SL)OR H {8 ؃F#x=h[+ڔ{8 *`R#_F8FC5p} :sF#o[TNU)vy/8ӯ<\P/ДF-bt$^鼢6 l'z6cЧlF-AM]Ѧ7b\ 8q fE=S276P|{D@`W>#ʞ,:7-0Cyo a? S{bO"KR.bU O:\!+»+اiW=*P,O}#R ,\h#FGf)±χG*=J.cۧM*#H|9ag1g@ЋK՚=ٱ?qX"ip{j.x }(' `:mGG _"V@ x1]M- rM59Ex `].b/72@1s_0bk,(ivPګp'Tl`/ wVůw'*RPh)(aZ/F{% #Q 0ԭ03TaP[A!Ocfu ~ @m@(W,VHKzޭyf(\vPek4斍f Bw3xhKP>e! }f"SX[jǑl ;@L1>GBy#|d>D0>.F/lB9jE\6So`pSIV Gj;P7pd: Cq?|\vUp;bDm(|D@ "ӹl,;_kF^3WAr8|lGp^U N/x%`/ԽZ s#J "b^ѵsv\Q㑚xvmc;Ae C %qE)uQ 8z;E\ԋ2#)  |skayܬ9˒% ""0}6WM>bz_(*< Fv!B_>`N} ԛ)BO.^Nm%ro+)R`*(3p3NzwogX}_.Pwz݊okkX} K/X/cc- 3rqt< Qݠ(KD^xE ΕGnE.צ}C&36*AnE 6sPS6Z{/KC .'NVB~cuQ q1\yۆXRB\=̷l`fɢ,@_ukE7@oJ,#@F an6B 0`!_[슱og e/^6A)EkC䴷GHKsxq n}cD cEOI[6 0`p 89m\[Bly"(6+ȜoϮ ?-OZPlۅyXҭ7-a++:4(tHA0Hx:L9K&0m9v{ΊG= 7|@0F^7Y8g|@HQn >}|BՍ{₊L G]l|AkK]zqtw>Ѧt=9 _P|DQx38nu<|L.(V_drr/@kx:/]XJl»Z;gL@]׫bxJa~S,?HAA?\PPj%bUa7"YLL}O, Doˡ[X=xQr(}݅)"PEP`j_{ؽH&`C|:] X"G/0zNi.Z!?Z$ȢoLAM+46Dqm[Ģ_=LE5>NX1ۣBcS>nJf9STT/D{pnɷ -ǽaV]ˑA!>.5p6} T+\`_p%@C} 6N۝,@e QBۧJPRUd*_bη#/Z-E/~\`v\jյ_y>w/b`V(B#? BkqsºsC kVZ R>>lP(yk¾y@QHQn>`@;>CX6ϡ^6$Ln!Dի:E {l|u ȱxrm[6Tښ_.߶f P3SՌMsi/%+>Pb_f *2:P> 93{sg.6>۳ ` ďR@6(6)BK XYt:(:lS1\:#~ܫ`/|ԊrO= t'z=uъ(K<{F,o/g?j@BJm0{~6g%G(ڍcL{ )ؓUk ]/Ul1F^!3{ȱK@;(+P- bn-;-b#.p#Sc`6_."ZVvoP/.(~PT.d.9>aRǑit~AqUȽhw"`#+&e-٦0WC)"sS Aa J 6׊L+C? F6csV/`n!YmMPk1E'LZED>̔ePEj@Ym_f Em> jMܾC+RPq`< X=i "SU =#ڛ,ݲPzDV<g50= m/(ua;NY~I}5m0ˋr7sPګYw|dF(|AtX@F+ cniScVM?'=YMbs=Bk>G_{' <9{7=py`_cy߽#@#%PY=ƪHQ ~_.*@Jɭ903 3_EGِGhJۡ(Rp>@"J)@8ݩ23 m{)'[|]f_X[y#߱-K`vprb [r-F#4c/%u(} DG]Ѧ?}. @NPZmP^{~{L5-`h#94_#uc50 M"SMݡ(yL6X9lml-HMm/@9c~-1R3evҊjOJ`6! [{bR+[ vώ,\Y4}]4@9RLY1!ACl1yat:7P1'=b#k/D9^)vpT@3i 3 "_.N_>ef f``2tZX0߲xЃ.!.j,܋2x-餭ĺfAs܀^\ X0uc V)^ ɢ_*@aT4Ph;Lij8̃}BJ/`~_>pﺹ*=,]7D|k-*ȴ,cʷ8ӯ<\P/ДF-bT5Wt:t^*~_w"ʞ ؄Խ8Հ|$FT/= m/m#?ٹi.Vt->"EKbREړ<Ջ2y`@ Ӵ+JXpn~b}'t˾)B TAT.4ų9@i[XN #}%̈rͱ&\AAl>90O~}/B+wЄ<G T(o) X' ZQry9ߎ/u q.\]/*SXDI+T> 5"`#(@y\ (~;GTDLA z12#~T ^+8Q ݊#R<-}(@ȏ>.I9Eu iXˆrA4m#ua/܀0lDIgmjqQާR݁TDyn0o^C|\vUh"-E(sy@d:Wme#sUhh1z"n8|lG8^(a^ 1NM/QɃZh1t^h9;ngqH?);g;r1Ɖ2pE!y}k8p\ԋ2#)  |skayܬ9˒% ""0}6WM>bz_(*< Fv!B_>`N} ԛ)BO.^Nm% |[ISALC/`:_`"g@Q]ev+G̮-\dm3G/*+XGŒ\ܽo#?67G#/g V视^s=\fc(`wЋ8oPhGEZbr5/Pтrzj= s%46urC/۬W3^ [&`Om؋%5*ąx3luz^|\ -p/P:/dz@QRs=w0 6(`.o)h@7BVtvqPAtM1C8jKⶐ KE-L0߲)'޳}}ו-Gn+ /8RD+䇹 IYv7FG3Pr2G]DLQkC䴷GHKsxq n ># FVs/}J-زiW9+cHQ /ĸU5[-bSz: d.F B8zIHAWoOٛZ@)*{G*d_k dc(S|u0yտFn0+  1>\xd4q"qgvdP_sQaO>@%bvVa /5]x/0S_.#wZZQuB}%6XmZ @|\j( `WAßWG J^ͱ^lJ@ѥ46>`V;(S@)31:rh1*0^{PC.DL_-/s-v݋dv:;ħ{R9_>ԥ7dL`3["QPwfjl.2VhlZö+n;ByC]3{h,V4aQBk7%a)h y y`/SVo_hurgPϾKMMwB?Պn`LWTN!?9 "Ha3h T%L *c5kELO9].<6K4tmp܆͙ӓz;b|ޞ# )-:7jѥg%b]__6q[xm-Jve ooZڢpr{Y0)\ k^c| Z̴l E.VY㦁`m $p[ &(q {Axxl4 %/_/$c!PR}pŧ0bEbb 3|oC"BXڡI_<=.`|p; ȱxGhBm_sC1S44|@,X)F(/Tduvur}#AQs;fZlyy٫]v:`Pl[(O6U1Ī/}Cѷ\C :dEy1b -%`sʕkk5.k5U->|lф2\q5 ?"{<ށD"^弞K薮hu2Qb̾nG\jW}hv@- G1·RjHMX3 <[zϗ 2_.(E/v#%^E >uZCj׌r@[̅PHU NJ.ĶxB,Pl䊹0w <;XL1U|)EXqw0%!9`:+@Q5ݢ/P@)vG#q@EaBd_>_.ߒm q9r, o07븐Dެ`sȴBH;.$V#E9n_v :za :]GYmMPk1E)0)L[pA UdjV(y{u p%:x5q=HAYܾn2X}RaE_+(^OidڠOC*3ut mKeEcEf+a{&`m5PίSjzR@ _> f"w_0tz E(@)4.`^>b7(l*ӥc=a{6v1*=Ah@ s9A{Ϝy8:S/Z |5أ fYlM /ʷ{GFV*fƪHQ _U @Jɭ903 3gD#r!ДCQb}E SD#kQ87pzSf ` -֕ "SN˷Pn"`#/{˒*\[n⑨0[BoCLa cy߻&GhG̒:o#Ȯh>4Bj,Zq2SZ|yc11*`XȈGsi0F ,1,o6Q>L5uC;bS`1vhcb#ŷ\#7U"3)>sSo?0?|Y2;nxlBOu;AɊL烵 qQ+d^Hg/ o)N'muĺfAs܀f`X-}UgfJybm-@FgiT T#؃5MӠ2 )// `mq{{8 Xy8nc~ mn P9UEi^u)C!1|4ئ+*F}e+:Wt:c;GeOlB"O * 8[DM=n8Nq􏾍!3Պ좞)Be(>Ը٧(GbDӗEa/@rGOc83Si5@L%U)yHQ _.",}v@IÁoYn>"E*:"ʅx`pϊ hh i)nam`H:)cUz0rͱ&\AAl>90O~}/B aAu&G>B]Jy/˼怊|(' `:mrPD1 cm!-T2uъWT얈b|/0bk,(iv[ܠg T> 5"`#(r!*$QE *3%Lt$bDq?f-"ESAo}St<GB|o% Zz^QZ!-Xq~_Ir'>v2{@ 7`a/4l/|<\F%k Fxm3Z)-5Hc6[]TCuj0Z1Ŵ `[F|@JcZ_^ضrԊ&,6mէ|mᦒ—+bwot:/4` +~(z32EE9v@ňڲQ<Ds&Xv~-?c -FOV6-)oA01ÒX4Q^#J^(Ljj;5;``n`cDB)M6@|v\Bx9?J\DS8ꢐ[pwL-~G 9R@j@8+0Ys%K AT?Dp E`l(|5lP0U_.G #pJڀyX9gx$Ro=V|[ISoJgwЊū/tһ+x </`"_Pw_.k|d#_6} K/X/ *+XGŒ\ܽo#?67G#j/*+{G7(J:[^xE Ε|FZR_>7(i"S\@|m(Fk&؝ ZNԢ#~97^\p96urC3۬W>T8L=a/{p t4|X֋Pkn9_>:*WԂlf%5s{yc nr1n_obZ<Tz#d@w"<MPЎ?M1C8jKⶐ KE-L0߲)'޳}}ו-Gn+ @F an6B 0`!_[슱ogenre N~'L9%ޠn{2ky_Q6B{SoM*X2GԞ /ĸU5[*MJ2۳kCOE kVԅ%vaܞ T8dAt~5i&P?Ra띑HQu;rT!-`YH@>7⭻z@傯7 <wX.#?p̓k@HQz^\t'>p)w>u)=*^ ]9]P֋K_>p.6q/$n(#Q38n<L&(V_d\J fz'8nG {FG;#rmAs~ s#/ztk&,X} ++xS?xVGB]4y!˷R/{!G k=F 0n/`#<]DJAOZ~ Ϟ[ewdZ! {)8p}Lat>.x:/0ܕכ5>PCnLztpE %oXҽp -.awYLL}O, DoˡXX]xڛ4@b |_w!g4TnTxk إ,*W{;{R9_.@pJu >@C+VCTNgƶ"C~=mK,9F@њaS=,X1.@i-TS+*FDwry`_Tk9R3(ħv7dZ-8x7r] xSAN#l1<8#qD 3\rռ(3?pz t3Áv >s6g O0mHoQe7(qT JL?_b]vp3Kz<֢lXny&- G/q/wD/WZȃ1{Y.(3m[BчB#4p BkqpvA#ȿ? JJ_._>5%GmE!zGXW|ʷ{Y+ fE3e `oC"BXڡIۡ]@~ukw/mˆJ[m _>0BLWO^j _.L1G!C|"S "\13}w~`nsTVӆg{B\}!V}R@'+6S{+@;[{T[w$;] ~{@#^33{ 您c S| m;pR&\ >N] tQQ/U 鯇|OTWr%a(mk`>Rç,^K/Ȣz_uђ`Ղi"{r x!k@[̅ѰWorNl+G(zBFx rU}$Rxvw] x*.l:|@kr 0%/ș_x>Pr\n(SR#it~AqUȻ@&4G ;\oy@|K)|}68 ~@X߁ ` 6׊L+C/+Mj=RĘu_`` :]{Czۚbk/)R`*8?*SRTTB{KH/3'@<՚}݇W,n_z_>=-VK\/P_.ڛ, T=0SGжJmy-j\a*;.`m~׹_g,?'jo6E{I#RrJsPګYq|0AoPsåѵKc}_4(9u`,6.Fm\ s@' ]l<|bj =n]yd9s>o8{{ 6< njr:{GF!+Jڝ9@1j6@(Uؿ 0mȔ@!^4mr F5<\cN8 Ɨ;HEb1& GT`h}Sq`|<by@|6k ԶRC`1q` 97(|gfouFV gЀ dE㮗ZgZ@gG ]k,{h=(1CD,bt^+2 yIkOzs;n:QM3v3Sz5 /pd@hT0_>bѱ$ym:n@H~[_̄xHqxЃ.!.j,܋2x-PĺfAs܀F \ X0uc V)^kc*cKK *^4 ؃5MӠ2 )5\e91 .Ӏw| :ۭyLLSUd]A#uW_>P%4Q_Y6N+CNDQ=8kaTiA mw#8@0NaLr0gJ桐C?8Հ|$FT/= m/m#짱 vgj'ؙ"KR.b՞<F< x6\BG WHLX&5PTXQgp_EPh)>S(\#{لGBhͿ00C]d $s6H|9n38 0 |#|-,<eGw;N:@G #B+Rp ^<]&T(o) X' ZQr9/u q.\]/*SXDI+T> 5"`#(@{\ (~;GTDLA z12#~T u+ [&E觿#n)BQ]m DA~OA Zz^QZ!- ^ Œh ut9h^ i c˦AT!{vі7;}sg LkEl# #@nu1ө7-vbZ}0-#d1UI׌rXo MD)70_[ #(OEd*.MXXV7ʷSДOeEy.4LʳMZӊ^3WAq@X4Q^#J^(Ljs#J8y@+R-] m ^h \{ky_jyBg>9ʵ0L+J&j}1i/ #HadNI02`N} ԛ)BO.^Nm%ro+)R`*MZ񡄣F 0 #B/Pw_k|ɥO6ܽox$?P\Z>f}yA<Q}9CVnPt"G?KM+2HߍХ4\8oPhGE­PM;>e3EͱGzpZmaS+W!?4|cuQ q1|3v쉷 {f_W:_.`+# -p#(4\:*WԂ]lF(Jj$)24hwAmP> \LQ+Rg&Lx  ]lZQXl^-͂u [603d{Ţ %UGh lC@fZYv7FG3Pr2yř׆io.u@ؓ ^Lj"܋nx l@UaqT)d6㵱j|KތA ]^ @|{vt )ha_@]xXl3am@c}E P?Ra띑HQmtT!'׌_t#|$GbPAm`9Q 3(~\x6yO`>RԵ>FO(=pDr5"@u|"kQ2_Pګ-U1oǭAFGoFcx!P]Lcj[=+֜M/r+)BJr_:|{P/`V_Fyܻ<8˕ zPzDm=[ewdZ! {)8sLate>r/ZZQu_.0؄wv@k1my|j( `WAןW_.((y{5ǒz*xKm)o?e c}2e`F>!~[6^mkP7rPC.DLnwE7}!<债X1ۣBcS>nJf9STT/Dwty`o *Zݵ)RgݧObF0y=J)ǯB#3a3h T%s%@ŗs{M))צ |T;/p܆͙ϓz;b|ޞ# )-󆺀OT\x%,ŜoG h_{[xm-Jve ooZڢpr{Y.0)\]k^c~5%GmE!zGXW|ʻY+ 6sH|v V#BCLA[H^w ڶFmk` 5\0E_/4֌X{)F!k"S "\13b˳>٥kxu?@9}!V}3uɊ ;cZJ]A]~[T[w${46@v@Q9@CaJ\3#tB1 5\`^0Ȋb<6|601Mj5<@YȩfBJm0{~6gWD7h-V/^yʅL=2ZL!> F>P..z|}@aBdvy߈2lS!rE#{.E{l[{_Dž Z0f%kEB÷(b~v~ln_תe mLk`@_ H7:ݸ+k3S=\BJٵb}@5J cVM?'=YM4rA5_&uU%0rKV>Jm@#t~7BVBe9H^#Eq4VI+T: Г[s `fBfJ/D#r!Д\^Qs>@ Cfo0E4l_N"0Xko rv{@On"`# <Gc[տ">#5 1ZF h_.0KP@D#M}~@!Ƕh==~&p[ @_p1'`"s ̂AA;"ӭ b9nOy?aSl=RpTTR`<<LQsOr3ev܂7:A#s ل3h_lu"sqKl3I-hݳ#5W=  {Zrb9`h[ xEٸ"9iIo4`}_rhb׫G% 4Q_Y6N+CNDQ=бS6HJ– ѦhS1.n8u3+޲Be(>$WJ=52E^zD#߻myo a?m4L]O3ETyHQѷ%x#z_،kI$.E W(踭BU.(S@<ֽ j E q3ЈP 3B8^6ᑐ0#\4ǶO,$sU GP} }ԇFmhG`.ձ#'y/Nj{X0q)zZH/Dw؋yΕ 1<^~_Z7t55<%@-EDpV+"^y#S[/0.!.^P+Ae ؠ:(i'Tl`/ wVůw'*RPh)(aZ/F8_~Q/̰eR~0n=A!Ocfu "`zc-=Qt(XXG,*/D9#ua/܀0l4\gmjqQާ.LQQMYDQ[6 Q4Bt<[WBN -FOV6-_ w#fmO?<ry@,)fr_0070[1 "b^ѵsv\Q㑚xvmc;Ae BwhCC'yDZ(p"S_iP/r>3q8VaQs,Kw~B\Q6!TO9`2@k\,||/RԳ^FW(]\E 9@EG]l>~zNiR} M}u >`8 p~L![<3|j9I-bQG{8e[9\4Ƌeo^Ol~9:]LBBBy >K~_#!.@fR[[C)#5܀?T#D."bG.@Um#@kx_}\]A)a /g&3|Vyw|{_Tf]XJlBo- 힃yxJw`*ؕEw+RP/((y{5ǒz*xKm]`V;(S@)31:rh5V(^+~(zAb |_w!g4TnTxkCoA|^$Ӎ/~шr:Sm8@QlcuZ!*ZPc N϶uWTpWC[HNz X1ۣBcS>Z\ϩ/9} ZBBj9@Tzgp/ -ǻV@EP.gPϾKMMwB?ՊnyL3B~ |@ 6NF(a+_α5"pRD\%fЊ1xdn+'m؜)<<>V{GLs´#EEyrPS%(*2/^bp u1/>t1a&@hXny&- G/q/Pj Y?y>q/bwmr<2\p<‚c)q_>/p@ʏ\ZrV!PR}pŧ|u`xoGh>p;߆D xq"S wlmB ) ȱx_>@֌bQB *`薅/yhK _.K.V2/ A_L=Gvur}#AQs;fZlqy]ٞPWlcU_e{:dEy1bi29{+@sk𵚪u>hB__[w5"Ƚp\s dBķmSB Gjj(/B}؏*y Ԯ*!O !_+-Ur%a(mk`>Rç,^K/Ȣzmuyn`U)E Z?{+ZCj׈* a;pX%VP(y sCu` W챁#gqwbZQl:|@kr 0%/ș_x>Pr\n(SR#it~AqU0@㚯8(D!`g 0/o6O}NM:.$b7+)'@i6^Ve%pEsܾU#,,DP̋P@[P!we=`fJݲ R"PB:VpE:B+RPqU#52H -U!f Og `2<`9\!:eDcEf` X[(un) fVf ؃ :fZp;4c d6ˈGZl^u@-4ǭ+PU3,Gq g/t@^!f {v`ѵB؃y`ObZP,  byat:7P1'=#QM3v3Sz5ਤqȴ 4<!Ӏ,/.BL|87Li-,go|]#'Ep-=uX쎞'B:{[pĝu_#BȦ!{v;YC-n02vkfdٶ H"RT4HˆcV[]tj FP 1w}0(E*xq1O~[}s~i0za-C+P0m OɿRIB O(MED: eu| >& lڞ#j"O**sy@D:WϚr6i` U-Z`,KX V>0\@ 3|+{a9FTSuLj*8~"D#D9B@j: 0'%f*{lPouV>/4@r5AEBrwEȬk"O(m[/.Փ49 G%'Px3Dqwom V1_FH3PBjvҷ536fPhlJ-&ZWRӺ_.(*-aZ}6M~zHyB\d#Jc |@ùrHÎf>`א0?/`\h6"`wAqe'h1c#m=/hy`ܠ)4\PsTŜ~+ 1"R}^<7wHkNYxvw끹w{R::c}C{g{Ss2Ds1290 ']-߽ lMZ}ćƮrTa_^{"{8!Bh6!0L2@M Es#Bf_7Σ4L jSh&[xa3H%Z@mBJm0?ѵ}Y?cge1̺(GXb"{J$kHm]/H1 awa1$VÊO(μ VbnPW*_!"lSl/X0%=/P+VU\scROTF mk4X8::"ƾ` X> u뜔`C. QEEy@)ΒO(na*yUVԘCT ؂@sפפy~Oc΢N+6mp;49Al_/5`*&g' 82✽^?8B=/߽#@%9U, '}V@ !6/'ܕ}BeHs=5f!ئ2@TrQU66(kv9W@JE 鵏^V>ѓ?)'>e*T{_f XO wn((0ӷ< X^wX?/B*@}8L %B10n2Z(+~[L55`heGsi0Z# Ƙk`f  1 FS`16,VОSL#_@i$3)>qCh7`:b97Z_Z,̎+XST2U;`kqC^8j'[eseQ}؃qL1y@6"d>5F "ilܠ"9iIo4`ǽ_|n`FS3e _&@ _(18~ei s 5,k9@"\C\h,܋*s@Twp/bY`sՋj9ne+3p}UgFJyb(g=#g"`y#=h*g8 q)i,/=Uﭛf T qߺy :]-η{dK+"Ut˒"R4` /`< ehJVb*Fj3yE>P"쉞UX-J– QViKN8}?[X0ZQ8lTϔBeT4ՀV~#Q۶2;74<#řVtR(1(KVod@2A!Wāw+>XZTKkoY2tݽ B ,.(\h &g]@iGX*c"y8ieS*#Al9Psacl}_A\8A,{8^;5(R51Ne2; [:AE1<|L!jE>Ok .fߛ(TDDpV {H@Üo̲wY2W8{q@uS7$V^}r;+ ⢵f?/Sli~esD<+LO+6Tշ P!Ofu.]m D8)>]X Zz"^ut`NMUy *6k@^022ljy }^>z'k FxMyތ,~2۶VDf}Iq r믋Nm!ϕfH/.503o`/ F/콿|hE MD)70^*iPh9aݠ%HBVn0o"`Cњd!BqDmXIEy.4Hʳ` o 9Y|Uh*j8ĬmOp_U(Ky+{a9FTS6Q jEƼkx7q !q@P|t>N ׸Qc"Tu>_cO,Z3_2#D9B@j: 0/02ؑlM$q@>+U~bӶ [ ГEcg~B{ 0\ڀCL2 I% Z,>N%d8w!0- WTtҧ+H .9eۥ YwtSڅK,L(rYZ>3xzߛtll^oT~! wG7%]VxEΕ_跑T]/;r@ӶGEx­A1R䣸Zj9}f~EͱGAA_<?up Q[pxp #gvbN;^ qQezzb8̮]!PĦp\=X/T\1$`?x|o@+R1!+ >AQQ$1:ېƒz s f*r3wYu$LdjVȷb*gBPLV #H, (j[V(_pwA1Y)j &"=@Z~p߲ŧ^ ׿"" sא_/ĸX5k3[}]bZ^ XA|{Nt ؔ^a}_&@YxY. b B8Z-j}PQ{DJ!P#`N+dqd=/0Y_z2)_y@ ^>|j9}fq]Y|Nx u'0>y<`~r/(aW(]\ꁊ -("}{pEf} 3(\v3J@,Wdm|஢?pρ.:}$^I\ Of⸭w့ee\PJPN_.36U(~⨏3Qw d.pD 2 ^|OtAef}>r}"|HH)d]'!!{9DCU/ 5̀?m P}88D=EkX_}v,>~0sD at~EZw|{@H:i~m =@|B ׻0¢;t^AA?|@Pj9bUK;,6# aDgCm{qozq9xY4T| !8^Zv)zg@N7|}pW@S0[a"@Y@P[?'oqZҲVhlGw"x{[~Z+e#ދ\`_.p"'A{Ugл6' Q0ÔE9V&Zlab@i]b18yÒu/D (Lk8Bd*%n*ANKiqUp,|;|pK @z_>=oH9"`c,/@_?(.`+9#D{[BևPA B}'0gyj}ごP(ycׄ R!ا0V4;,+250^Tϧ`::n_Zdb];KPzpH>*m/sS _]*_.^EXg+ "yo?09u\ w{R::c}C{g{Ss2Ds129{@{k0ٚ]2[i ="{8 pL,@mpR& _.(~_>07"/0q%yԦ*!OLf>ʑJ!@mBJm0?Ѱ~6gU)'#.uQrY\1!ؓpV"YCjk XcFD~cI@ȇP(y @dܠT d)f !<;Zq6=xZ,{;LI669׺'x> \[T.dY!PcR[h4:Aq UnЄ\!` 0M/S:z;MFCa1c+)'@i6.Wj=BĘ񵖆1SwhO z[MBL"c@Œe(E}ڽ̬Xg^jz!8- ж5l/`}HU\N/P_.ڇ̇~Z=0RGTh[}NJr"L+R03 ~@<9) ]!D vE8K: >ڻȧUYQcaP)ƊC`c zq D&{ ~@su]atiCݡI BO&` /xPc`sC3̇8g l8B_.@w/P d%@N*yGX5b!O\)un'4۔_.J.ʆ8p^QskT+"*(fFӶ#T$* '#Lw,VK[^ɽV@({v[BoCb/xwp{SB*@}8%bc./p7py?^Ly-&Fk04r#94-wc503~RHk wb)0Gl+hcF`kc@Ta/@9ccgM(A˂c1Y71) *GX *Av~AɊ8!Srz5`cӭ2ҹ>@}8pujnc70#TYpTΠ _@ u?<:/| $rְ/@"\C\h,܋*s@Twp/bY`sՋj9nVuޣc "RӽCi8wD=b=H Fp{ T)p(`SH~ת0TO[7/\PQ3xjqU$p$HvH6(/*7Teoy? )M/XͰN؃m+ /8*{'`:}!Ҁ%@ԩu"8@0naHkER=S2 omPPep$FT/= ۶r;74<#řVtR(1(KVod@(8n`'PKd:9m  J7gR薥-bPKAu @(*-g 'i_>Es4\4m$Z>՗ MPP;B^t܀#'y/xT` u @8Lvt֩kAEPG e/DZgj\~@~(m(Kr9N/e q.epܦq@uS7$VpD,\ [NR2z1CP´^Hq9xC [&E[@wqt tŎ@U.c-=uX쎺BZ00| *6 _wz~A d\읬7;5y3lfZ)v`*q$a1+ȭ.F:(>WBqsw2☪5\0`[ȇVT`ڴA3cj㽫+fL%HBVn0o"`Cњd!BqDmXIE=/Ds[ӷ셜,MZ*4d5FKV6-LO ږ~Z W}DTuLj*X ~91Ďd Dh"9\Bji lU_O-=@e_0~ P:5$ @m U`I X_.`+D򁊲xE*R#_0?1v>'3O>fEk }oұyA|R1q,@tvE~jXn!8Wj٠FZR5\P0F@ӶGEx­A1PxE-5#} G¡NN!?jEbg8=Ŝ}xrkb_r1AEf׮(Ħp<=X*rjnc  c c'ק*CtY8fȮ>-b 3q#0>|^0?(a}O(=pDr5@EB:#(.PDz`/pEf}<3 ^Qb"cwSo}w@}%#qxp/)^ '!||!{9DCU/xAH͟ z >%[l}qX\dP׳~ J{/(t˶*1c;Hq f/u^GHvcrUxWkm o{pJw`*؅EwX~@Pj9bUK={,6# }lDYlmVT$[l(zAb\^Ÿ%# _,zE{]Ej.?=/|~p(ryQ(KJIPbuZQTj.V+4;D}ܽxEby"f ;] 36fPhl=:@a3A3J^oqsſ_.PԺ! R+ΦO֊nYE0/X P Q} =3A~ xP(JgJE9V&Zlgb5@!/Ę,۷oEktk}ZKDu"S)e(5}9-Eݵ~ #u,|;\]~{ բlXny&ЊdE/~\`vݧ`˵ Ws2F 3 n?d 3 58$+ m8OFR.Pr+(R}*aES̲"cxQc EUarA)VBK MK aoks啥T7RG71q.bk27{Cm[Du?s"84繾cFz`s0{낹w{R`NI ۠ؽ=i1s<‹!5,\36Zo0WkZGw$`׵W =ZG ff vrAmpR&kyɽ@_.0qeTPoXE^/qdEn$`Ysj1EP=o]p$kH>&XcF^!3{1$VÊO(ȢJV }qG_"'.*l:\E, ιY|B3|^@l(\d=*C*h#itQAlCVkry 4) o0uLHƌ >`VDm\( {1k-=/0c :V?IaV~ "j0#n!Ji{&ve,3(-Z+_!8`,ƶ;C2><`>,!:B+&tR2a*}fau t >) zP_`8\gI'R{70*+jxBlF?*)ɖ !g|AtgX@J' 1gQƌJg8 Zl[;:E Ԙ{c=l$0|so8{{ 6 P#t~BVTw$Uc/B ~_.த*@Jɭ90# d6r!ДAQbu -֘WD 2DTr-PN46\Rr^Be+-V1@(B0ӷ< X^r(۱_>w_O0%Qbc/p7p^L-&Fk04Ilp1'0B``fƠOJiMݡCq`4fShbyX8lml14r^J rǸ!7l97ZyY|Wd/ q9 CP /Ny@BJ /`~_>pߺ@lp @E1p0ﭛ |IH6*y%@JHqӀ=Ql <MiQ?Y6T`sj'zV!oqdҀ%@ԩu"pڍ`pv)G7 6hp$FT/= ۶ "@{熟11g8j7"sZs;-Y/Z Pq`Om9m  J7genK\͗pr̬B}@BQ+3TZ±O _.9}`TAqQCOxS})ͰFh|ۥu ҼISs",< Ae2; [:AE1<=C+@!87Okw[#kyMb*u[8J[+R셽Fn9< aηfYB\ @+2zaPET: 9<p!*@l}:OJD A z1"ʶ#yT uWl3l! ?1v+4`VwՖ@Ӆr'QWHKzT xi;bpFqdS!{v;YUP^S7#̶m`Fb7YGFbSo0jb{s%$ 2J(10za-C+P0m OɿRIB O(MED: eu| >& lڞ#j"O**sy@D:W_8}k^ۤBHVQc@[>/LO ږ~Z(a cD>5;aYUyРV0j+Wȏ`n:>ќkq ! 7N@w b(qe>&" (K\r8hpZi8B# }p- 0z, S( !EfPJ%`B>TVadNI0\s_$-7@|;J P|zNt,~_.( .2݊okn.s3O}̸Ѐħ>'#g_ d8԰+BpҠFZRrݡ_( `PmH[bGqVm @-oOz^#`ֵ~9/^=XO/T\1$`?x|Z(>>Y\\"*t(he%vct!%q=/ @ZWȠ f*r3wYu$2 djVȷb*gBPLVb췎1@m en"(&;E dC䴵GHKxA8vP7dd^ ׿"y" sא?/ĸX5k3[}]badηDM%4?eeػ_>} HъoQS.:'BPj;d$B(>gGVd_`I\ 佅U}!,3'?pvn>PL?`Qo@m\V,|BwVr|B#.*B*H- = eY EWxb"cwSo}w@}%#qxS`!Cp~9G4F_'u?3AH: /][_.P jbmDmPCnLW+BPЫ*_/V 8To?~S`Fl[6.6z"bC9 "ggb\}g="[=.նؽH&`{_. .P"@g2&9~봈Twfjl,e֌ȩW*f,?qOPݽ1(ևBc+>fJf>QQ yZ yZJo vpV5O`.x`9XE[P!>-liu8?p_z뿟GTŞAUT6' Q0ϔ{UR[HG63 ڴ.1πvN{csdsimGLqp~PP?-bYvp@$WV =G[\@\P_eO=-+߻,=[!( Y|Œ!{`q7V&{>p|Bm/6=r(? &G )>)afY\XG10\@|E[Q\i%Dz. ڛL!a '_.m97h`>M/]bNÊ(C!5\lup}#Aġ93C]Ǖ޻^=۳ E9!Clbc:d"81ber3v0 'Lg?p dk#>4v lr"`/|hE1s}s|`P7(D۶q)eĎZ 3~4(tc#vu>0*MUB;l} (G*rT54 )DϦfmZWDbuQ,9-l5sR[k̟hFl+a'Jg+Y17+YcGίvZq6_."Xv (rKW-Vy g=@eXm8"_PBU| *=Z U\!``;Mm\( {1k-=/0c :V?IaV~ Cɶ]RTp(CR4Z3P%C/3DEigZB+BPqE' жl`}HU\C"><`>,!:B+&tR2a*^ iYkXb_qIY6ԳGE8K: >:b±ʊsJT6V|{ă{&D~&Y [{b{c΢N+6mp;49Al {{T0>;I`Ƒ}pBmGE*yȩBe9#ƪ Ʈ*@Jyۣ.[s `FB&`*+(*MiE.VR- \Qc0-* R6p2*߽/X,my' ;7Iߋݲ- enB /phfNw_OS}/ _Fe{1eWk0j 8`F,1I)";4Zb9nh9BLY1|`#AXc "R+1Ab q"5ԫG% jy 3"tP8cC @M/2 fM/2 Ĺ5oP+B`n}>>z90Ej "ܑ8#.~EP, l6Pm`򀕀 Ac:3RӽCi8wD=b=H CP /Ny@BJ /`~_>pߺ@l~b4`>[7DV}lTsK•┧{Оe?n hJz_>`E*b6+:Wt:c__pTDO*t, B`SaKS+E 8@0naHkER=S2 ɿ QP{V"(ObDғ *m۠P޹'q v)δk vȜ*@qTEY`G;+>CTǾ6?(a hcX6U*s6ت^{ہ}&xM/@LEnKGikEYWވ-8vy,K m5#zaPET:mh%@mI`?/ gŅz" TfcJ Fϣ`baˤbC_}4`VwՖ@Ӆr'3wGg9C9:rAT/mq{@nHc0lj }^>z'k FxM`³ڶVDf}Iq r믋Nm!ϕfxe ?-" ^B> Ӧ  /4(nPD݁TDxPXV7ʷQohc|ԔmOec'< "+ނe/5`/dmVA$1Z"nY'fmK?|bDYp{+{a9FTY+;aYUyРV0j+6zzkq ! 7N@w b(q۪ od4orK=/8B# }p- 0̩!v$!EfPJ%`B>TVadK!`PƁkY_>`N> ԇ),>N%d8w!0-0 RX #4xLv+O̮]ɢ>z :O8>?/P1+XGaFʼn ؼ >Q8Cn J:"G?5~7+4跑T-65@wjo iۣ"R<֠l(F "rDctx~J+4` 8<.%g^*ـeĭz)EgPO~"kW)+@F(/lv>.q*1$`?x|Z(>xn*hVx}"%  ZgIct!%q=/ z jfL0SEYdŬ }%UeG SB~G CP8 bD 9gGQ۲BhG(KQ=/bS@L6De=hiاA vO&H<\!r̳hcLEy,ʠ>6GԞ?/ĸX5k3[}]bZ^ XA|{Nt ؔ^a_@YxY._p @^C]O^%@fc/ !vX/`%J|Wz"DzkwwHu`?(fP$ .zFiMXXQ >` @d ?`(zx[&_oW˹q;\ fm`0:?yO|Zw|{@H:M/Vx9UVk ZsgJw`*؅EwgO+BPó!JP"`UK;,6# }o,gCm(!bTa>@1./b\~f|0P5̢Pxk إ t8zE95\S(VZ\?jjq @5$֌BXŬ? >LE5~NWz{[0cmcPV }͔|<D+i)i /0ݿqF@`"+jZl ogݧOkEwy{LVB~:)z 3='ˋBs{M!ؔꁈkӾHc p3%X }]Ai rz8?ֿQc֭abu~,>azõ8{a}sC gyj}ごP(ycׄ R!ا0V4;,+250&2?&}nDC{<8+Hۚ_~ł̶|` L'9vbNÊ(C!`zb0s"84繾cF4v lzr/`/,OuTffBQ8@| +Z%H82\g7,9-l5ܷ85 ,Bf~cI@ȇP(Ez 㸷.HXX@3dapݖ[fT@UHmF#Ź/T'kDgPPj_Ub*Y>Vo)-+PXDŽ j J 6kE !劲\Gs<3 mf@k1l%EL'2i=\ik^"0bzu_z^s&s`Ƞ[|088Rj0i HRmo`:)^0Hô,Lֻn8_,jXRrGHDXeE9AP*]ƒ&DSA0X=1gQƌJg8 jl56:`*&g' 82Jt&|xa ?^ȩBe9 X5b!R61zrkNHC(,\e%z_eC)mZ1S=?dZ? ^=Ty ` ")'>e*T{_fXڟ' ;7I=x;L!7!V<|;F=|̩C !IT>[b!Jl6N/Nj)◧ F5Ayǜp;Eb1v?)E5uC;@ 1mєqL<|@+BX8N&4~(qLـ097ZY|Wl T2Un4`[b<*ǩW6v` / "ܑ8#.~EP, lzQmV4 azXVf +:k `kՙRJH g8 ؃ =o@@ 21_.2 n[=NGQ{- WRDSA{J"p[V"r4% /XͰN+CN'zVcзl* 8[DZQ~/b|N_qV}/LP+ mꙒqTHdڛYV~#Qm j~~`hLv`giGUq7 Ou8\ j`ߦ]Ӷp {p<[j` 7pDBs,}@Żs260$]UǾ6?(ap> lES@\Th9{ac|`^V xѱOKciދE2ީ",< Ae2; [ 8WaA e/DZgj\&J1Q-Qe)^y#b^0%0bk,ȩBurD#^hPET: 9<\p!*@l}:OJD A z1"+IQlwz~4 Ȧ!|NPgm3R080_#xQcCs+!8ʈ~Rf`%f"BZNXE7(~@4^h* **78`Q [*FԖETTBt<{ pրŷI [he^Z- Je<QOM_`n`ֺcDBP+B5] yΎo = ص'g;q1ƍ2pBoM!{TDQ}f>Bcp,\ C.Kw(~`DsR XP'f?mUay >Fv_!,4߯J}BPQL|GIS O_.tҧ+H X #4`9o_`[ `~bvͥ}N{&yzIe>fEk }oұyA|R1OX8;(8԰+BpAХjݡ`PmH[b_'HC[6-j=y pӀSȏ_>ᱷuQ|(5 8#RI粡 xa/ŋ \''kбkWbSVH傌Q8Q _lv>.q*~ P> ,ЊTDy -A ODqTTɈgI]lmHGicI\ZЂ3 H9YE뻬LV̺y |WPe"*譐o($2q,d%`+ƾy7r|< O !4vX?JrJ\]PPA;Eq"ұ{,2cHv`h}@,WdllVsDW?p%n/'P3DqxerX[&<-H$ޠ1cev> ã(jq(4K myE?ݚ rr:}2>Wk\B{~i4UltKʰ $C(3DH2le/A_>q~ o1^qpk" sRҎ ݲ @λ R,Ci{r?O;xo6Nrѵn9U8Vkm[+^êP`ݡ=V%O[/VPU"Gq`?20# !CC\X}"bC9 "r(E8CDkE_2b`j[{h^$M/(a)qE9V&ZlibuAi]b18yӒz;b~ !2RƁyZC@۷JRDZ\x%\,9! e΄x$Ei٦ AMɊ_)a̲"cxQc 3|_C" /_ρtk!+HQA{ q8$LYDrl[sn|PC_tT@bn|@blup}#Aġ93C]ǕɎ^=۳ E9!CL3:d"81bZ0 '=Mg{k0ٚ]2[\4 S~h<77xb>s d`ѶmCaJ,@q;Im=,>e(\ jSh&@(G*rBj`~i{~6g| "1̺(ٍ,KsZkP=o]p$kHmM/H1 a1$VÊO(ȢJV }qG_"_Ckl /xZ,x;iB8ɺp!5͢/ ڢ@G s_O{DghZ  //S:z;MYVT 桰 AԘAԇl֊HBڡe!Z}1x|f ;DkkH¬Vh-mP0#n!JiBg,KH_fbzu_z^s&s` bHRH->JQbɴ\siV-V_6j[qW}fauľ|lҊOD _>7̊2`viDG%$AP*+}[cn4]{4}k `%iSJg8 jl^ 0PcxULNqd>9{7=py`|BBt'T݋>T>Y Srޑ0VGq4x9 y*.T"~pրMHt9;Fr3/T'QVԩRe`/)(\Qc fP8Nr!Hl0\3cP'`h}!m03f`@8:@ci5󡢸(ȇWD:T1'="5ԫG% zQ8 2 N *936Dz0@d 3|mp62H=`DAZ! ⤊2x!q:]G\[7Dvfsw&•┧{Оe8L iUbE*b6+:Wt:c;)ʞ XE@߲Al4 l ujEzq'v-i(]gJQ!!*j7ՠX8+?KOd sOO3RB 9-U㨊wW|ByZ8\ j`iQ=+:n+D踥Ye)t˳7A%ܠ:E q q.ž2C@E Q!~d/IH98ieS*2g=+zmsا[P;B^t܀#'y/|E*EYxĉeGwhSjÜ+˰u/YrA!8/>}&xPD " X% ,^+oDZ얽 aηuʢ(.] !z^(C9XDNSH ښX  =|,\>(.fևSl(W1Gϣ`baˤbC_}4`VwՖ@Ӆr'3wGg9C9:KE/ ĝu_#8)9 }^>z'k FxMyތ,~2۶VDf}Iq r믋Nm!ϕfxeܝ8*iƂZ_^{ Њ*L6So`&+TҠr*A-vJcSNBaY`(>FE5.C(QS=GԖETTBt<{ pրŷI [he^Z- Je<QuLj*wY0PDC& 8|ÕJ*j}?1id 0 e_|zOB(a A'|GI3Y>N%ELj hU0=R(K]jn7ٵ 79YGD_}'Q YZ>3r'IňpxwtQq8aW\e`];uO5(&Q_['^ih9}f~EͱG~)- (pӀSȏ_ۺ(B\KxdvI8c{ŋ o@=y_^<# ĦQ8Q ؃m"C \to(`ChE*,ŝ\\"*t(he%vct!%qM/f 0o0#dg2Y19r(m_I@e/VT!L a6B@ Ae,XJV}n>xPpd~zUv>]۝0Db!r#yJn{2A|/XTVr1Ϣۦ$RM~*X8\C:*"vH<bxί TBlatUhy%`9%`Szq_.@YxY.Al1 AG+:EMO*tA듑:L9sZ!' _.`I7 o-5!,3'k)@1k]Y\M JXɷqd]/|B#.*B*H- = eY EWxkX|T[E_=uz_I|H'Px3ķx9n\ @)A1o@-1cwSe'oFcxC4`XQ8ir/tk&`Z_NT`j킐Vu+xooDSZF KHI1߇&(3DH^P{@^zfyVAqb ,&WE"@, ݲ @λ R,Cg;>{ ~D vzk3b}(4Rcm8l]`תE8Ld*oſ_.PԺ! R+ΦO֊nYE0/X P O,.{UgP{@E!]ri7^-g63 Gބe1< gtk1Z J)@.*~9r #u,|;\] @Zmf:{@~_..fw}Zn^ j3غL"'Xo@~'`?# 87Yv8>6M~HB\d#Jc |XєV'}샜"cxQc <߯!`_u@}i!;BWZ}u ^s aokx` ܠ)4|v9+> 1r"R}^<7wHۃcuW&{z]0PnB*ZX` 1ozlOysN&{#[&0c8prum>p d_sutG~]kܧ`/|hE1@1)5\m- niE;_(tc#Bf_7Σ4 jSh&[f>ʑJBj`~g{~6g| "e1̺(ٍ,5xcN [{ *B'd 5fa42#MڈmE>B, @d[w 끊TO\ qUp/]] -(̢ ڢ@G s_O{D8mVrUUrh 4oe%oFTpzcBB5fla%"RvhrEYxHV#D9_kNO z[MBL"c@Œe(E %o,!z!*Ju>֊}yE*<9:!+V@ZnZWqz΍8R',|XC*#utKUrE耊8w503 u^0`IY6ԳGE8K: >ڻȧQ ? aP)@wb18IѵIc=a{c΢N+6mp;49Al |}`*&g' 82Jt&|xa_ʷ{GJV t3chŮؕ{BHpܚS3J{^ XJ.-ДAQbu -֘WD 2DTr-PN~o HccʯDP}EJ~_`i%T޹OQa؏ _.nc/9u(}!?JgKÔ0_"D{_Fe{1eWk0j 8`F,1I)";4Zb9neBM/L͚_>eBM/sAqd\}6X Z! ⤊2x!q:]G\R_8F,6qY,p0ﭛ . [gp%E8i^eoU<MIHTfXxEN}̡ ʞ XE* 8[DZQ/b\ G`pv)G7 6hD@`lW?Qm< ?a?cc4Hq]o3DTJ*R Pq`Om9m  J7ge?? p9+wE7P i)1[±O)=JCcX6U>9"Vy?9XDN 9<p!*@l}:OJD A z1"+IQ2gmɂO*LO+6Tշ P!OfutŎ@U.c-=uX쎺BZ00\lwz~4 Ȧ Bw5x蝬7;5e! kfZ)v`*q$a1+ȭ.FZCuj0jb{s%$^O*i /84U(6mŧLVxAUt'Z Nb}z Ek]P nTjIEy.4Hʳ` o 9Y|Uh*jl[|+YA%Je<QOM_`n`ֺcDBP+B5] yΎo = صFTt>N ׸Qc"T 8z;H]l!R|>X a]E,H40XV!TO lUx >Fv_!,O/0 I% Z 8od80-0 RX 3\PQ]e&'ƋWu7p|_>cVŒ,o@,^oTS?J:"G?5~?RK~iKC=/1B=*"n Ɇbt+"5e3?Ѣ#]r/ : X8+E_A\e\6B `xa/{p ^tkb_r1AEf׮(bSVH偌Q8Q _>`;qAU1 P> ,ЊTDy -A ODqTTCA+, (m,iKE-L0SEYdŬ }%UeG SB~G CʄD[ıE.G. ʢgenPQrwA1Y)j &"=@Z-[4 >#\!r̳)Tpd" sNړCs~M`b[/ - s=6lJ//,,{bώ>/54T?R۱'#B u>;rB&O{IͽJ7.[]P+n@ m/`>f0+41>p'Y|?Yx뼢PX_xBW *B*HKqEcGYd4>@?>v0JX|T9ୢx@:$~J\w?uA >!ƅc<-H$q;|@T> ãe9e|ir/ltk&`M\r nM i4Ult~x $C(3DH2le/A_>q~ o1^qp;r2H{״@Zc| P[?'oqZ NQcoW*fݜ B`hMӕ1(ևBc+>fJf>QQ yZ yZK /pKs9\/(jZl ogݧOkl2}xVB~T_$8bϠ* zwpd!f7Pc5kE &VD\%FpP}a9؜!<-`#&@AaZ"S)e(5}9-EW[Ų-]8qHۆÊ=Gϗ[>ρ{9,Ai4v8?25fl Y&V"'Xo@~'`O#87Yvp|Bm/6t>rP~L/pM1(R}*aESeqEbf:;D _>+4m"D נKtXۂQ|`薢 8jn_>PxX_>0EXg+ "yo:Lv:`ݞT(αbGߐٞTL;F 1L`Ɔqkװk0]d1\iݑ_Z: #^33w!Q8@m=ɢ?PD/̍f_7ΣD/T i33^R|SgRO4mz`&u/AD:\ ƑY(92,>1!ؓpV"YCjk9@bY {H@&mĶ"V|Bt-sR 0=6po}B+!ΦrA>) _ȁb1r 2Y, -4pD8d7 @TP|\!`b*Y>Vo)Hp~y(cBB5fla%iBvhrEYxHV#D9_kiN0wZ!d.)B`*8?!H[pAqiBg,KH_fbz"W⼋O4wimk8%[ԺW9C_>)Ud@C*#utKUrE耊8w5>ag&`ik\=@<9) PTQQ,Rj1WӂBlj>~blAo i|@ti1ka`Yc3qYv1c8٦-u&}6?'=>2lI: jGfq g/t@^!B݋>T>Y SrNGUa9]I'T>)mOhn)i%+)=| *(*M򊲘-Xcz~^%Qɵ@8zr# UA"aWm8)'>e*T{_f XO wn(x0}GA bU1 /9u(}!?JZÔ0_"D=&~rZr+~[L55`he#94-wc503~RHk wb)0Gl+hcF`kc/U"3)>qCh7`O/yqŗqkcuJV agЀ_lmu"sԫ^ }t+t,4P\4!d1y@6"d>5F "R+1Ab qD>jnc70#ũWJ|p s"t P8cCi4P˄fK,_熾Ԋ[OtNp qp/N YRueU/ XE^A_.`ưn3XΌt/PZ-@Ꝇg"`4|=h*g8 q)| 4o 60Ncus@tZo8 F%=(\I)NyM/8ʂ߽>^)K+R1#^鼢yEsIpTDO*t, B`SaKS+E8_?[X0ZQ8ll@7PHI&{~"Þ"FT/= m_> ?a?cc4Hq]o3DTJ*R5\Pq`Om9m  J7ge?pA.4G934Eq63Dpa~J_> :}`Te `6p|-cKh&h(yATqq<=qX"ipwjPkcНĉeGwhSjÜ+˰u/YrA!8/>}&xPD " X% ,^+oDZ1se q5T:{@/s*T9<|"QAEqa5f֫!Lx0 W1xC [&E[@wqtIOWIQ 9Y̩*QAY@^0/#BwZ`dה ,<_mjE 0`[ȇVT`ڴA3YᥒV h;Pt/4`a0P}z Ek]P mO%w(~RQA "ҹ-Xv[BN&-lD%B+VUJf*k&ʂ >6x^ 1zuLj*W9,xr݊oilـ6&/^yzIicVŒ,'#g DIgW视^smE.Ujic :m{TD' :WDZN߲hQs.9BP@iC,B~rE_ /KٙSB\/:_>ZXW\LPٵ+  6etd‰Z04倊빽["?{C97B+R1!+ >AQQ$1:ېƒZЂ3 H9YE뻬LV̺y |WPe !L a6B@ Ae,XJV}nnn3P2t7(m9RTϻ,5 cjeo0}:ъ`dd^SX"y<`~r/(aW(]\ꁊ rEEoȬaEOgvX|T]E]u^IP'P3Dqֻp2Xz[&ZH$~@-1coS';#!(q~@Q8ir}=CxE?ݚ rrWu2>Vkn\B@4Ult~?wI`~r RjsA4T29 BZ A_.U?Fq88U@9P| o?nVZ flB!Cp~0} at~@{@H:M/0-P gߏ5@dU 5^T PϞV_> (y{5ǜz*Hѥ,6# }o,gCm5VT$[l(zAb\^Ÿ`>(BpR.*W{vn5'Zj(rjQ(KJ޹ :-(*~V+4;D}V1Gk.` X X)1xFiZWR_(*8L=|@Qr`3T~K8>~Z+e#ދ\`_.p"'A{Ugл6' Q0ÔE9V&Zlab@i]b18ysimGLqpP[%i)"-_.Ŝopnio@Zm-Z(=|ǻ,0zv?qp̭= T0cAHZ=>rdz h@(<\@1|k~q@R}S+^`eA;a&0.`א0O/`::n_ZdnŕL} *ȱx_>Žɯ_.RJr-/q.\P{Xe?/ A/"Rϑ0s"84繾cFoXE>/qdEn$`YsZkP=o]p$kHm /XcF^!3߯cI@ȇP(Ez 㸷.HXX!޵ 0N/"XZQ;s"g9]rp! P5V! 4:Aq U{QA?X-Xv@1SlCДn8xz<1!!36Z)6¹,<$W" H"YG/4vz7N~Rջjb'LDx})u.QHC J>eYB:2CTl} \$^L%ʊsJT6V|5l&=L/`X8,t˜1p;49Ale/jl>uULNqd>9{7=py`_(aE*yȩBe9H^#8<|O\)un'4۔_.J.ʆ8BSE-Xczl>JEmMilp Ry<r^Be+yy-^x Rq=x;L!7!6YiXO/'ƞ_>`ԡ| P$*y-1S~%6xLL|7A8<ַ6G~"5`hGsi0Z# Ƙk`f  1 FS`16,VОYA8; C+RC`11` [?\,̎ۛJB%Y3h/:YT] "W6vf9lD4|k xEظAEsړ+ 5\gif8jQI; 8 2 N *hy36D _>0 _2B /m 4\P+B`n}>>z90ąV½8"L>g^HENz^ŲfAs܀FVf +:1XΌt/P>d/ q9 Fp{ T)p(`SH/ﭛ X4`>ut8ncnTsK•┧{GYdȱb_.4e3t^鼢9T~8*{'`L* 8[DZQ~/b|N_q|öKL8*$aPAEC}MQe0A /sOOs1R,3[|DiGUqkO q",X M m@UA 7,wy@"nP"…8|3r@(# IW±O)=J\4DZO,UAb+΁꼟C`S4` T7(#'y/ H( OC@8Lvt֩kAEPG e/DZgj\&J1Q-Qe)^y#b_.0,!.] @0"rP@T֜DJ^.rY}g >'Aebi~esD< R(@uDv=/<OB|_% Zz"^ut`N G ^,9@^0/4l _>g/5#c$8fHkN FP 1w}0+#d1UIk`,x腽Bi(>%fK% -'?bw?64^h* c[l(Z32"Uh{"- ? υ\y,;{!'o "YE vӺ~08 (ax%`/,Lj}jvs#pAaԘWtm/9;nD38$`6(Co P7|LDQ h06U@ /hy! PhskaqheIBn,H40}W*еX|W|bS / 0 G=64߯J}BPm QRTjECNtr_!rTo_`[ `~2͑ / xmc} D}̊>@ޤccBbD X8;(dO "J /23V_>@-hQs._΋=\NC,B~+p&{؋958xrkbZ/~Byz} p{NP+r=X*rjnc  cbxί TBlatUhy%`9%`Szquyeeػ_Ϳ>$hE編I)@E!([{8B(>ݖVdi/3\@I7| }ǫ=vTe;'G_Ƿ);@1 x3oe5-'0>*= !J#hQ&Q }_.nQ<ۃ}Qq̀P$] +2mZl'Gu2~Wk\B[!{{ ҪL6:]]P+RJ]c]"}/gh>sA_Eq|o1Nqp;r2H{o J'?PRH=38 SB!8#Y EXw&Bs "Gjw20# !CC]X Plq9~!"P{!8^Zlv)zg@Nw

1 8[EEE6`YL3sŷY77Bqz]/з53i~RV }͔||FiD+i)i]/| fܷn(=0y@Qr`3T~K8>~Z+e}GhɊpLVB~T_$8bϠ* zwpd!_h9jDMyM&86K45y؜!|-`#&@AaZ"S)e(5}9-E/Ųw{`$Ei٦ AM6wY0>)*\xE}e9@Ԙgu+dX E`'Xo@~w &q{C``OFRP2ׄ R!ا0?pDbg$f>5$LX>/(MXA]P\imd?sm=/hy`ܠ)4\PsTŜ~+ 1"RiAġ93Zx]&z`ݞT(αbGߐٞTL;F 1L`>kg wwom&[SV񡱫UXfg-w4#^33s|`Pky ڶ{8L)5 PDSC܈׍( /T@h&[J|#h9cC )DצfmZ*2Gf],gf1ƜZLT`O+#YCjy@bY jC Z 9&l %cXɊA]R8Bxv~ݷ(Њ|A}o )y"trmPQɺfT@UHmF#pd7 @TuAN +B>/`{_&(ucvrߍO7:&$Qcڴ!>@YxHV#D9_kNO z[MBL"c@ŒeHC J>eYB:{Ibz"W⼋O/m]X P*^8ԟ aV-^iNqtt@Ef}w503 ]}@<߀>bZ>GE8K: >ڻȧUYQc](ƊC`c zq]k_Vr?i 9:ݮ0f T:۴EФ'Wg]|< {-TaO~z3̇8g l8Bx_@BVTw$Uc/B _த*@Jɭ90# d6r!ДAQb}+62!kQpopz}SeFO.)R^] "Lw,V2K[\TEpր ~_@Q3{BqzE/ NR%6}LlL|7ALbm11 `Xq hX$6c1(hRDZSwh0s6My?`XA{#(6[UK)!P0w0x ,̎+XST2U;`kqC^8jƮ{v`k͕E꣟#Ĕm@6"d>5F "ilܠ"9iIo4`ǭY"5ԫG% j 3"t P-qh4PX&4Ѭ,jy@~N f*[OtNp qP[(dx!q:gX\ڬ hJa\=:`kՙRj" iqppӀ=H `S4P>R_ Amq{ނg8 jqU$p$p%E8it<( ~b S5V]ZГyE3` ʞ XE@߲Al4 l u#aWC8/S`pv)G7 6he p$FT/= mewn iyF3}!2 PbUQbǭ&9" DاR87`^~rUȋpz4E"xO?zq(@LEbs*GikEYWވ-8,K~u(Cp6 P@/s*TŜ**z"fBUṭT*ۥ(aZ/F_vQ`DQ[6A~RQA "ҹ-Xv[BN&-lD+'ny<0;0?1+h[k&R +{a9FTS6Q jEƼkx7q Co7hN ص'g;q1ƍ2pBy@ f8-weGr>3@u8aơyX9TDC& 8|ÕJ*j}?1[_&O- ey3|BSH|GIS P_.U/`: /"y,xLv+O̮]ɢ>z :O8>_/(}#0#IIňpxwtQq8aW\~iK2C]/}N dKj-5#}V8i)G]/pxp #湁TRI粡 xa/ŋ_`Wi PA<C]/d‰Zr`=Oّ028~ C]/|,u2Wsuo/`>f0㨷VA1>p'Y'o{;`%k9 \wS.Q / HȬi|"١|a^r[E΁>u:^ILCOf⸭q29@,~-RbooPvrAG}ԛ8G9As0#//5^e׊~5g<,x*C0sv@u/|HH)d^qI0? 9A!BJr> U1txAHk" UAYM2IE^ypZbv*d^.i{r?O;xo6U'MAp6h- vA.G%`*؅EwaOw!(A4WIT]Ɓo?f"|6ضm\m"F_jq9xY0㻀i}"\}]Ej.?M/=Z'tflo1b}(4Rcm8lc{AiUTzSi`.x`^Dn-G6C S觵[8l L5>`%@*GEN# bϠw '򢐮i9|@Q´@r|3rX]qpmwi i@vN{csd:simGLqpPPz{[E%qZŲ-]8@㵂 e2uc7^88 #5z`˵ Ws2F 3 nO@f7 ?\Y$ɪ+ѱa ҝ-/wWO!@ NFXpnh1>?Bm/6t>rP~L/pM1( )> |)a̲XXG1>߯!`ȌBM0i+DQA;-iZN*-_.0.-*CQ!_H CjAQs;f1Gu+?;z0PnW(kc1Ī}C{g{:dEi_/[&0c8fеQ Vd{S1\Uwӈb\4 [i@kf.| E/DzEy= -MQjj(E/̍̾nG\ jSh~VZf>JQrжBJm0Դ=Y?c֫| "*H>`\g7,sb@=o]p|֐5PHtoX$@E >@+J%@.k1ĸV̦rbaTMu8Ǹtu@*@Q5͢/P@)vF#pARQB&㙯Z b%+,|\ ~%!hVC:&$QcQVRy\?> C/+Cj=BĘu_.`ưӻAt~00w j-(~"c2(u.DC %o,!z!:>"g"@j81_^_P@Jc\4 [Vh[}NTr"W|ô,Lj\=yhiI}5X"`(7c0JPvA1M]{4}' Vr3sQƌဪ68 d}6eO/j |5*|u߿id>sW+9,+_>7o%@N+TUc/8<]sR&&@On)h%WlSz@T(*MiE.VbyE CD%kQ8/pz|S&O* ' ޗY'Pz&Dǣ`Np܄4O@c/p̩C ! FJgKLÔ0_"=&~rZr+ /5`h2|Ɯp;Eb1v"QMݡ(h4"DR0TTR`4l~[9` _4q ֔ #fz M}s80O8j֊ =;B0Zse>@}s1eLA1؈hk xEظ"9iIo4`xmf8jQI;8w*DM/pƆi4 iei)ie`ld؍7Њ[(sjN85|@L8@A;RNz?" 8{[!aj+3`V(^8g8iTT؃n`@ AecR]jSF1[us@58i|̷nN'Q{- H< ؃e֯ /"GFi24pWK~=+:Wt:c;GeOB"o 6Up:uEzq'v-V.Ꙓi($aP> D@`WFKOh;7~`jy&3}!2*P1 )"v\F6䩦 4H 5oӮi[8`U½ 8]-G5PTXQ@ ž2C@E }?lF(a4Es4I2W}rDP[q~9LyӀyAhˇ+^tԙK XkSs@W` uIeGw;NpaA |tAxي}Qa^|MůQZ( {Dn /(aη,!.ƂVNn i*ή: ~<|"xag9h;u"į(E0#ѽVl3l!*6T7@wP8:jY¥-(>" 9Yr̩*QAQiP^0/#% 읬7;5e! kf"QԬ# #YAnu1ѩ75vb\ `HT%]*94Q+`ڴA󳅗J-WXE7bwoHt/4` c+6|Lv"UpbDm( υ\y,;pրŷI [ي[`_Q ږ~bDYT0$hB9FTS  Zw(y6ЊFyEצBon:Ԝkq *C7N@w b(qe>&" (BoM!{(r89B@j@hskai<˒9 "h"L9\QV!T5lPت0\Q #pJڀiZ9gBS\|;JQRTP5P|z2>]W`Ѐ2@/(ʂKYwtSbvm>'=7(iۣ"Q<@*!4@-o(9H/_΋=\NC,\r 0<7 /KbN; q!^t4|XKTh#p_>: WԂ`M/(r] +?{C97p1DJQ|C w@wEi)+$ O7&,#w6p6Ě_~@Zp?`~e3QN}f.+?[̺y |WPe !L;rT!&0rt@>o)Fe. P ܶfi[Y\Mq#0JQuwX`%r'8O@B_>poQ\P݃Q2_P٫-U1o7*QoFcx!P]Dcj[=+֜M2Q>ef. ;D)}OE/xЊ0k@fR[W^#t=3 ؃y6H UgLX\2Io J{/e[i w@qK=F_`u[ЊϊS= }vJ»Z;h[ȺUJw`*؅Ewе!( J^1?UG={,OccV>7Sf!Duh(!bTa~ A1^3D$*~=*BpRzg@N\] +@t=PJZ\Z!ZE"uۙ >.1GkN{[0cmc {@炨Z\ϩ]FiDWSU=㠴%*LK%\PQfPOiQ~RE0Y=J)"'A{R pi7AE9V&Zlgb5@f1< gtk1ZimG*@.{[E%P`8-`,|;\]债 ֢lXny& 6r痶afw'E"`-+߻,D{[B֟B%43gu6AGj}Q( De2& A2E!GW4=},{osH|v~ @bUQIۡMXA> bD9_v_.m[sn)jviM/9ҫF!k"Q+ "\1o^09X {낹w{B\!V9YDs1kYtg:{om~VS>CcK*[Op5ZF ff߅pL\Ѷ^r^I薮ucgclDr׍_@ @~g4?G0!W_.ڶVH fz60glxz/A$Z)'L#^F'`^EuYCjrAkl/"{ȱI@ȇ+P(\17z@a"ZM  w{SR6hʽkŖk<EB&3@5ED("}₨8JVL|WN}\a%8xz<cBB5;-`~|Ai6^V{1Z awtm okZ!m a&Jݲ B"PBg,KH_fEiήz5/=AY+VK\/p/@JÅ~R[Vh[}NԶXc}Vž~`}hEC=K LHT՟HTfwxFpP}T(! BI.ۅC^6@tgXOf1N+Ũ0ϝ BOVg]~_.(xP~\fJt&|xa_ʷ{GJV ݙC^#Dq4V3ԹMLܚS3J~_`ᔕ,ʆ4BSEU Q E MhlX8k_ r^~w,V$?XڟfC띛ſ">#5 i73\nc/9u(}!D(QɮSPHm10 m _@SxŗF5<(HTSwh0!m03󹻱A1 ̲cg|Ԋ*(iLـ0rZ*jvev܂5eB%YFv`S4!S/9Nvώ̺\Y4P\4@9BLY^46nHcNZ{қ'4 quz 򡹍L^ 8*ig D;QA(!i4X&h`hj _._V|D;Wp©1@>GC[Jq:]G\<@, l6Pm`Wf +omc:3QӽCi VYp i9TA{7NyӠ2 )UOJDqng%J2J^zD%z_@{QOLm4Dq]o3DT*YWD<2i`Qm9m  T7ge?p rg(*-gpV~JF\4> lUAV鼟C`S4``^aAu&GF.%|#z\PQ 2qR+e:mie!8/@>[W\(~o(~yi9Je{a-iY[cAN+T'y@X^ gW~P@T֜<ⳜJbQ\̺TD A z1+IQP^0/#M/j ;YC-n02vkCͯ׶ DkE <_YGFbSo0j1=L\`JƂ׵84Q+`ڴA󳅗J-WXE7bwoHTbY*n0o^hc#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`|_.Q ږ~bDYp{+{# f;F< hEƼkx7q Co7QjN ص!'g;q1ƍ2pE!׷&=ZlA=/8BR|Bcp,\ La])QEf9\QV!TPت2@D)쾺C)ikY_>`NP''g8w!0tvh(>=@I+hvy_._.Po6s,Q̮-\dQg} Q*+XGŒ\c uHO5?O")\@-o(9H/_΋=\NC,\rE+rgv8=Ŝ}]Bֺb/-Su3_>PQA>{y I" z@ӽ `X)1$`?x|!jWZ}̸Stz+ PTCAqt掑;E}}-fe _`ǭƅcb5LxZT D$@vc366U.8CoFnrla G1^4tk&`Mef} 1[єD <_vQBy<4!BJm_ɆR/{!(^5̀`D- " bmr%Ƞ>'-(O>@m%bvV>a/5Mx/0C_.`Ϻo:F>%VXmZ @Vd]ê₈B ׻0¢;hr@A۫9ԋ4WI8Ԗ,OccV>7Sf!Duhk.>P|x9~Bh!8^ZRzg@N7 tM,Z!ƹ?BlN4DEtfjl,2Vhl0^Q|us׮C]5>X| +*䩦 /pKs9\/TԺk9BSZq2DS薻> _>J)"'A{R pd*Cf7h9jDM9M.46L44r'Ͻ9CxZ2ZwGL9aZ"4P8Ok(qV rD?-`,| /p_6Zl-J6enop `cO/p~|;"jip]D{P(Gf7 ?~R m4QFQ( De2& A2E!GW48Y+2505$!T zMXA+DQA;-_m[r_G^j_>Pb A_r@EXgWW 9xD5繾c&EuuNyeE0cU? 2is"41b-%`Ɔq ӷ еlqo~VS>CcK*[O0{=Vyƻ(c Sm=E/q:Qr׍ PAV *9-g mR(5mz`&3_HtFf(ٍ,^`^EuYCjr@k̅ѰWLZr+(J}d!b%W }ix#gvZ0^Zo}S@/ ƥ-Vy…Li}2jL!6 F QjEQAZ ["L|rSlWo)"P AԘAԇl׏!byv66kr3 ӵ5$0w j-(~"c2(u.DC %OZ!Bb]!"g"@j81_^_P@JÅ~R[NDEf0ƛ`i5P^AJV, c؋y(O/pW @Jɭ90 NYɢ\lH#4mP!Xu_znFf0DTl-ZhlX8k_\rv[@O}EJKij*\D(x0[BoCL /p_66`ԡ|D%N=6PHm1`~?8 arQ @8ҘNr!Hl0\3cP`U$ w@1 FS`16+hcb`#ůL#/U"3)>qC<o֟_~BO/pa̎[֪3PLÜofYB\ 2W8n q@u թo$@mͩX  =|,\ (>dU2z1CP´^Dq9xC݊m-"DSņK4`VpjK ` c-=uXZ!-SSUrAv hƑ=;x蝬7;5y3R2۶hH+5HHcV[]Ltj F >WBisw2Ҙ _>0腽ZQӦ -T@h*%D% C1 >& QMYDQ[6 (*sy@$:W/5`/dmVA|hr8bVжC-0^ Q;uLjn4ЊFyEצBon:Ԝkq *C7N@w荆 n*:eQ 8:\rZnY_.p#>X Fz, S( !& 44sB0Ok龂 0 e_|z(!0@ Y>N%EL%XC_*Nt_,BRV|Q̮-\dQg} QK>>0#O{ݛE1,G;AQɔ!&CxEΕ5@Х4|AKoPӶGEx­PxEhar7=5T9-4`*䇦8<._!.r;?4xa/EGX(Ok PA<7@/D+j)`M/(rjz0 P> \ Q+Rg&Nx}"U  .E@ 3\™+^-hg D9YE뻬l19r(m_I@_.p 25zWȷb*gB ~ "c߼9@mʄenŝφik)uXLOy(r̳)ȦD2͋#jORO/ĸUy#[0yZ8$odηS6wX%`__ptEwQS.E!([{}2!*P#`N28~rCM/܁!NY.:(Wm^ ~_`V|Q^%n~(w{!D X| >\=!TP=/[H~Q2cOR(b"coSw)U{%O6(F!q$L>P,ޖs*ݢf36U8CwF>)F8BPq~p.G1^/z/4~5gt2>Vk 1[є~?xK(!@fR[Weef`"g6dP߂?@'@m%bvV>a/5Lx0CyQZ(mݷ~ЊϊkrYߟk<ȺUJw`*؅Ewг+BPO/((y{5ǜz*Km!o?ec}3e`F>Bl[6^mgņrD>(ˡs"pDC}2bKYT;kNZj(r4\avʢBI띋}Vih>@M+4;D}.1漿'!0{&(tu36fb}ThlLi3J@z.`א$P%u9 tܾtk!ĕV_]B\QAmM/MZNCJ\0t˂44K _.sSDPb /@EXgWW 9xD5繾c&5EyQ]JϾ^Д)Ϲ` O=!bn= =ӷеZu}OsVM#zr/`/i@v{!(c S| ڶ{8L) _.q؈(׍PAV0JK̇_3? _> mR(5lz?MYa }_(Y/~v#,.}*㳆ԮU1F^!3OȱI@ȇ+P(\17qoa]X"ZMxh-N+ʂ}snQ(rޥ[ o(2jL! H4:0>VDy]| *h`~m|{,<$V#D9_תf ;DzۚbgO: x}(u.DE5P+}ʲtePZ$._9z_h[  XP"<_.ɐRpT&V_6lػqiYջnb_ 5,?@ vC @E8K: PJi"p\QcaJxFٲ!cn4 0i}k `%1N+UmZp;4i' ._>PP|@U 429{7=py`_0t~BVBe9H^#Dq4xw%=PR&&@On)h%WlSz *Y} i " @b(62݇cQZ?^=Tyc('>W|"`% < MDG/`Np|b1_>mfNw_Q1JT+ m{<&v&~hbm11 `X4`F,1Ej w@1 FS`16+hcb`#ůL#/U"3)>qC8lsoPhgf츽DPda50v NVa1zqՀ{v`ֵB}b¶YP6"d>^46nHcNZ{[Jy*eQE>Y(NpT~Pf@QA(!"4eDSr ]|5\!0n>Q =V½8 YRNz@k)X\ڬ hr+3{t >֪3PД\S1'f^鼢yEs܉8*{'`,6Up:uEN8}?[X0Q(]3%PH~àlEC&WJ2J^zD%m7r;7~"i5@#BdNU bREړPjy@HÊ4n(P6 V*ܛ߀X ݲ|DPUAuE qgP 3B8_>EpyE@2gS Qx죾fpl" Br@m'GF1Ա4߀̘*"P&N*8uRo[`뤶̬{y BhE>(е8\&JWm(VE셽Fb_.(aηfYB\ 2W8n q@u թo$@mͩX _.0 O'E!L^0#Qܯl;b(G5PY X'`Hm9 i5nՖ@[CSPȱȺWd,vG[!2UQANo:/܀~a_>g/5#c%g /4Zn F@l*"Qe²P}zE5.CTCS=GԖ"( \hΕgo o 9Y|Uh1Z"n9|`Zw`F1+h[!Gr%rާ&`6Q̓Z¨14^sv\PMGxvm8Ae|A %n[DYG*?[ E[n٠!}f>u8aQ.Kw(~ࢉD3 M(Z,Q~ZKV偈R}uSLC r93D ԇ)BO.>N% |GISoJgwЊ 0  ,BL/Po_gbvm>'=uOvlH"nK`N28~rM/I7|Ƚ%7 eytQ>A۶0wS 3(6G`D|=x' 0|ۃ!>JO(=pDr5"PA;EqAEwGYʬg|AgۥQ{E*)U}%#qx 3DH^P=/zfCX"4[DJA}NZ(~ Q/ҸOP!h> OucqK=F_`u[Њϊrѵn9@UxWkm C꣒ί{Lt"rAA۫9ԋ]+.z0!͔Elmx96 g{~qt_ ( x DC}bKYT;rgw'^Ea@Y@P[?'oi}jl,21 ^/usWLCz_36fb}Thl=:@a3 jBB/p/0x[<0 /e(rAE~#A!>-5p6} T+\`_p%@ 4b`f= $sd*C-Xh8C)צ |T;# !+L󳆺׽HT\DZ,9/pn9ku\=oRsE~_.wY.0>)[n^ey j3غL"# 3] !Gj} ( De2& A2E!GW4=},{osH|v~ VBK MB\i%$z. ڛLH!a `5\0۶ PSҚ_szV|25<0}M/T$uvup}#AQs;fZx<uC= _uu~ Y O뜓A=C-kYtg:{om~VS>CcK*rO?^q/i@߅pL\Ѷ^r^I薮ucgclDr׍_@ @~g4?+-U3r|%Zmk`Fg{~6gWD42En$`Ys@=o]p|֐ڵ Xc.ߟHZrhFl+(J}d!b%W }i|P|Evb1ĽVfZo=)i"gtuA*@Q̢P@)vF#pD]\GH4&e+Y>AS~Y. o0또DD}XI{m|{,<$V#D9_תef ;Dzۚbg.)B`*8?*CRH4O]2u+Juv} \}yE*uEճq~^^uC}yRj0.S DݲB+&t2W+}faVž~`}hEC=K /HT՟HgIDJ)P+j! BI.ۅC^6@tgka`YLc3sQƌဪ68 d}6iBg>P UJ`(^t@hȇf(>γsY %@N+TUc/8\]I'T: Г[s `&B۔~_Jz_eC)mŪ.>nad-n N~o D+T8k_ r^~w,V`sK, c'%E|F8}kA(s@ %B10 m _@SxoQ @_p1'0B``fƠ(HTSwh0!m03XAcm` Q+RC`11`g soPhgfkcuJV =ՍV'+0O8j֊ =;B0Zse>@}s1ea,( 2bxaHt7P1'=mf8jQI;M/pT$ z_@ M/LM/2ADSLrAqn062`7@+B`n}>̝ 8Fq !-w|8#.~E 6Wp C^& AcD{) t^$ ip3AUQAu<w+g8 *`R_8FCacy j4`>[7D|[}٨vH6NWe֯<\PFj; \S1'f^鼢yEs܉8*{'`:}!Ҁ%@ԩ+E 8@0naDpvQϔLC!  ,X8WFKOm=/s(q v(δk vȜ@4( {'xES@HÊ4n(P6 V*ܛ߀X ݲ|DPUAuE q3P 3B8_.9}`$ɜM[R umy煱3]KԚ=ٱ?qX"ipwj.( OC@8LvtiΕ2l642@Њ}Qk p7QRnKGi,b/7@1 s_0lT mzAP<:i7T`?/ wVߧT&Z/fJ֋!#Q 0ԭf2)BD?UlZ yGG 0[t%ŧ;qR>]X Zz"^ݢrt~rATcwt@q{@nDc0l4\1ˇky`dה ,t- DkE <_YGFbSo0j1=L\`JƂ׵84[.VTai(>%gkBV ((8 Xeu| Ek]ȇ,tbDm( υh-v~{!' MZ*4V-&cӺ3YAQp_mr!+{#J_`n`ֺcDB!M0FN C zkq *C7N@w+QPVԩ(BoM!{(rKz_p#>X Fz, S( !& 4|%`B>Q~L\ O/D;6`4߯!J>L!zrq(i~|GISA P_>_tҧ+ ,<<+Dr,xkfk 79YGD_}G(>>0#O{ "bD%_`EIg+pSw6"@}B=*n φbt+ -o(9H/_΋=\NC,\rE+rgv8=Ŝ}]Bֺb/-SPA<r@&(\Q >M=XO/(rj$)r@  c<+E):S,`q'REi(С8K:bslC8JKb=/ z 43}&_LEYn#7TY!Lu:^ILC %cb5LxZT D$@v@1ccS1>f!@;hv2p$EC:A^Olܴ>NP`] _>r$MR~6:\Ka|%C"yl(!] _>q[AQ*gYMDEu-1٠B|n~0痚&!/0xxgq{Pui{ѵn9@U8VkmYװ  va4pE z9s X%} Rv0ؘ!͔Elmx9 (>+6C= A1^3D$*~M *Bp̵إ<,E2;r3;pW "Ga4>hPR?$ @C(rVhlj݉ cm5Ĭ~D 0 ;jm}k3>*4  ҰZ4| t8(mJ/a / Lc# !+ϲ(5}9@bηrwe\֢tŞDøla~E_w Du->+,(3 nO $'`O#87Y(-~vQ@m/6t>rP~L/pM1( )> |)c?`Ŋ⽷?D9$t>v~ 0|Wi:DqmKHt78={[rS!_>0tˢ 44K_> t<|`*:P Ҩ93󘣺w{(}g+αbՏ!=LyZ眬"r#Rfl,\Y4m0]jG|hlQ2[_ZxZF dyno.| E/D۶q)er(vDFQ6UygH3r|%Z(9@hZ!6QjMYg*@1zQ X #}*SsMP >9V4 h#pE >@+憾4\ƥ-Vy…Li}2jL!6 F QjEQAZ b%+,|\ ~%!h|Jvq~y(\DŽ j J 6vheEYxH^Gs)"Q *jGG(0kliYոn{@8XZPQ,|co2`v+PJ_T$WԘC(l4[4i> 4ika`YLc3ۛ]L4q@UgVMl~Nz>2+ BAw6f✽^?8BB݋>T>Y U+v%=\w%۔ɭ90 mJO/Jz_eC)mŪ.>nad-PNL46,5WW.D9/Be+y45RW"~f 27!aƆ̜:bdWԩ m{>&L|Bw|1Wk0j d#94-wc503FQECP 1mєiL 6 X8lml+HK(m/@9Lcc5ߠUQ;X2;nXH`V! [[Hb<ԫ[+*ho#D=δ(1ϴQ!!"^+1Ab qD>4ԫG% D/ /\D;QA(!"9@ŬIrt s@Hl[_5|@+B`n}>z90E{q"@&/|8#.~E 6Wp CWfUl(XeGRJ[3y,@#pUEFXP 11g(B 9U)iHQN(_.Ұ" ," @բzW(踭3Jg1Ӂ-p #_Wf!±({ل(!aCcX6I@2g5#J}ԗ M yAHEm\ҼIeSs@WDYxIeGw;N:@F <\!"rEgj_>&JWm(VE셽Fbe q5Buw'*T mbr} *hkNEJ^>g9BU@$"֋b$mGVl3l!*6T7@wP8:jY¥-(>" 9Y tT倨 (4(v hƑ=;x蝬7;5e! kf"QԬ# #YAnu1ѩ75vb\ `WFHc.@_^{ UX0m OɿK% +Qj;PHt/4` c+6|Lv"8lAFQTBHt<{ _8}k^ۤBlE viqŬm(/*M|l1?v~aY%u8aQ.Kw(~ࢉD3 (>%`B>Q~63󳅭 0 e_|z(!0@ L/qKSA PDC W(C`:9{!rEN eۥ Ĭ;bvm撫xmc} QK>>0#O7L.^oQ#g V视^seM/?o#-t)M/@wQ(pk ~6(^-5!q8iP W!?4ᱷuQ q/pF{{1f_W/:4x&޶ГU(ٷ oPlJtd`i " CJ1 P> \ Q+R4 ;E;X\TD*t(h2Β@1:ېƒXKuC 7Br3wYbsP۾* \djo($T&\LtEUb9@mD ?GYD_gqA!r#yJAA8vP7dc1d1Ϣۦ$#Tpt UCU9&0bEPBWV9ߞ]6wX%`__ptE)*yހMiA!*mSL6\r?tg =S,t 6e?`,8|| 5@ (_%?p8p3+Է:+>/4@r5"PAE@EY ~l(+2mxc{A^Ol\ief VDq$MR~6:]]]R|02C  _:xAH5~=0n`#4~ ,vdP6(k1iTH>S"Crh!L("u ⳢיLCF>%VZ@k1Ѷ{"0t>*0`A=AAWs>@|ѥ `(C@)3"`:rhm1*~#ggb|dH4TfTxkإ,*W{vy= +@et]Pp9~HCTƶ"CзfQ"^Qy"fNm X85Bk3%a3QQTt8(mJrix)D?/TԺk9BRgݧO[;{kL(B~:)Dg ŞA2 '`yQHZ? J/\r|3XMipmwh k@5'Ͻ9CZ2=ZwGL9aZ"4P8_k(qĞVQ !?-`,|<]V0>[{/ ρyE]L=7[" 2@9@Ԙgu+dX E$(Xo@~X,i|v8P&`?<@eʏ A2E!GW4w;Y+250&eQI_P=&`J.!\쁨Ʉ4J[mky` 5<0E_ /hn2a*CQC@EXgWW 9xD5繾c&=<樮c%g^=۳ZX` Gߐٞ9YDs1290 W}Mg/MjG|hlQ2[_+i@ vh[h9/qR&2Rs#̾nG2*MUB;Yi+rG /m[+3J]3 uGX [ReA)CДP A؞l{ !*C/+Cj=BĘu_&`ưӻAt~00w j-(~"c2P.]xjV(y e (-Y/p^(xE*λhRsstCWTtx_<}_ɐRpT&V_6_03 >P<ίsR u- !QQ|_HTfwFpX!pF aJ}lF17(9cxBj[ƾ _h#n2Z2+ 0j eGsi0Z# Ƙk`f D5uC;b)0ӘpDqӀ=yQl;24_.pWLŨ kt^鼢9T~DEV]Yl4 l u:"pڍ`ZQ8lgJAڛY@,+Ĉ'AT_@{QO3Qi5@ 9U)iHQnLjBye! +»+@ ۴+rXpo~b}'aVa ,(\h LEPh)>C(cQ)=J.اMh%b #J}ԗ M ~rU6.j biދErߩy+: LT&pt6&4̹RJ\0e!8/@>[W\(~o(~(`ݖ(jEY^y9>/e q5BurDUNm  iE+*hkNEJ^v} `.DK.f̺TʄWf$@(G5Pbaˤt_eZwqtKW[Q|Z#'EӅr'3wGg9_<}_.(v hƑBwZ`dה ,<_m֊DxR>$4fD6`b{s%$^(23o`/ F/콿|Ԋ*,6mŧlᥒBV (5uޔTGxn0o^hcBqDm( υ\y,;pրŷI [ي%B+.)Ŭm(/*M|l1䩰6`6 %~v* MX FV洌!v$!& 4|%`B>Q~Z [_&(]`sW%R=8w4? k(A !0  lEYvi10][ɢ>z >`(rAEsEk0zm ؼ (FT?û%HO "ʺ_跑t\c uHO5?yuH4e3Ԣ#^<?-4`*䇮8<._!.8#?/?/xc{EG/}iQ=L (2QGZr`=<ȩ˻UjsAS(rAJQ|xn*h?Ȯ9x}"U >{%نp6ĺ_%"}&_LEYn#73̇ e Sw0|@! 2q,g Dq7=K%4DmʄenŝφqjpZ&*G!{>O`%+Dy~_M~*X8\CrAa1ny& JiV>YiᐼWV9ߞ]6wX Pd]- 3(6G`D|Aſ `FBa}\Pz >jEEqAEwGYʬg|AgۥQ{Em\/΁:$>p$Pbg(<B>pL.(_wOy@@L?qef. 1[є.g*W/(!||@fR|{@^̀/`"g6dP_r(O@m%bvV>a/Lx0CQ||o~@+>+NF>%V]Z @힃 ]J";0¢;]%oӟW*K=`(C@)3"`:rhm1*0?/_.5_,z/o-Ej.?!>یpW "G0zFi,Z!?BlN4DE@>w5 X߿>.1GkN{[0cmc {@炨Z\ϩ]FiDWSUS=/o᥌ſ_.ur`3(g&ΦOn2= q_z+ ӈ=) zwQ8ˋBZrQ´^-g63 ڴ.1πv .76g?K X }eYB:2C(Juv} \}yE*uEճq~^^uC}yRj0.S DݲB+&t2W+}faVž:'ePϒj傊Dqt@DڻȧQ 0P zx=(1M]4?>+@q̹ c~1Bos*gsГ9pt\9?/jl0 /DM۽#@%{+~ !Uc/8\]I'T: Г[s `&B۔~_Jz_eC),bu -֘WD 2DT(W7U``A|徺2@$ x*߽/X,>$ ;7%E|F8}kA'-! cyߧ&((fNʷ|1JT+ˌ)Ul6 ^L-&Fk04yyƜp;Eb1v"QMݡ(h4by@,l6i RC`11`\0_pa̎[/D>4ԫG% 4 f@KOd+2VHKzt8͛87Nf]^0/4lDN1Gd ) Yx6^60b7~f}Ii r믋NmMk70+#>W e偱u-/ F/콿|Ԋ*,6mŧlᥒBV ((8 Xeu| Ek]lQ[6 (*sy@$:W/5`/dmVA|hr8bVжCk&ʂ >6x^ QTX  ZwZ"Qc^ѵiЛ츆𷛎(5'q\B񍓳8?J\FC8ʢ[pwD-nz_p#>X Fz, S( !& 4|%`B>Q~Z O/D;6`4߯!J>L!zr,'"<|W<c uHO5?yuH4e3Ԣ#~9/^*HCQ@1:ېƒw%"}&_LEYn#7TY!LA۶0wS 3(6G`D|=x' 0|ۃ!>JO(=pDr5"PAu|ޢ"ѻ{,e3WxR(b"cwSo}w@ԩ?#qx 3DH+Pe/ BATxykإ,*W{vkw'^Ea@YB(is hji6`Yd{[Ĭ~D 0 ;m=X Nkq=Ot}]^!OU!O|@Tz 8L -}a]͠Ңݐ!jE=}L(B~ b`ogл x !JgJs3X ipmh g@kp3%~wh># !+L󳆺o HT\xbη܅_Zl-J6enop `c?/p~{;"_ip]=m(@gb5# 3gu6AGj}]KJ~_x_.$c!PR}pES̲XXG1y`א0Vvhvn!Vﵽ+DQAŻ eCٶ5\0熚_.hnSi,jy`_ *:P Ҩ93󘣺w.Д)Ϲ` Gߐ-9YDs1;kYk636?ZW[w$`Z}> {ǽVyw!(c SrAmpR&ގ{@0FDM/}8eT|/ٟf>JQB )RϦfmZ>%Did֋rH~`^EuYCjrAk̅ѰWLZrhFl+(J}d!b%W }ix#gvb{̦^Zo=)i"gtuA*@Q̢P@)vF#{@!Jr߻ *=-ivy2SlWo)Jvq0y(\DŽ j0 BH;}Z}1x|]1n!YmMPk1Dm!0!D[pAU$*Z3P%C/3Xgg՚x|ݗW0&q"@8?xX Z/q:\><)zH`nYmo`:Q`ݻ`JMXZ: kI}5X"`f"`H,逈B)wØSɓ\QcaJ{6{Q- c4_]4?>5IsQƌjb/sS&`\Pc㙯Brid>so8{{ 6 "ʷ{GJ!+rڝ9@1j;pրS/phfNw_Q1JT+oMVcb`s @!^-&Fk04yyƜp;Eb1ӊ|~Ej w@1 FS`16+hcb`#ůL#/U"3)>qC8l97(3 ev܂5:A%Y3h_lmu" sKSllݳ#5W3  HgZӘgZ FḊXc4^+ iIkOz;n:mf8jQ r(Ph储erYP Bz90E{q"@&/|8#.~E 6W6+0[7D|3{zPAMSU$SA`W_.(^@S_>Q?Y6N+CNDQ=8gҀ%@ԩ+E 8@0naDpvQϔLC!  xj@`WFKOd@(~0 imęVtSe;(z_Ұ" ," @բzW(踭3Jg1Ӂ-p rg(*-gp܇KMF\4 e*T!hGh9/{AT!/:n|#0c( OC@8LvtI (҈asx BhE>(е8ߛ(_) X% ZQry9/e q.\M/*C9XDN+T5"`%?/@y,\ (>dU2z1CP´^Dq9xC݊m-"D?(Զ<-\sb{ 9Yr̩* /D9vGwz~L4 ȦAT!{v;YC-n02vkfem3Z(vWjǑƬ ;@ 1w}0+#d1UIXB>jEL6So`~RI bZǦ"X*,, ǨWl(Z32DE>4eaqDm( υ\y,;pրŷI [ي%B+Ӻ3YAQp_U( n/x%`/cDs#Jy@+B5] yΎk Rsom5 !89;݁3!mӾ > \yk-s !GH3}p- 0>wY0PDCM$i@>+J* Y1Ta0 ey9gBS\|;JQRT_tҧ+ ,<<+Dr,xV|Q̮-\dQg} Q*+XGŒ\c uHO5?+ -o(9H/_w ơH: X Wp&{؋95*ąxuz_^ByV PA<r2QGZ 95sy9 Or1_obZ<4w@wEi6&`:4gI]z,%"X?`~e3QN}f.+?[̺y |WPe_p ‘oD`G d!L ٚ&Ep4w##mBr,z/(~6DN[{4O7('BƞLY|,F9Yt۔Wpd" sאJvH6@q|6VJ>A ]^ XA|{Nt ؔ^a_@YxY._p4 (BP3E_A!*mSL6\C=/܁M/(C\uQ?۔@3L,>p x u'0JQBz;J|Wz@Bz_x(>Pۃ,e0@gqۥQ{Eަ*肨Jm0 ?P2 0CVom|j9I-}0;ަQ3O1zM?EL[s6[nXN(C0c뮐㽽Mw*cwV|?`F 9!{9DC)^5̀?TD-" bmr%Ƞ>'-(O-JKŌ;}_j>`0:'>PںoUF>we?x0u=" 5^T gOW_>PPj9W_ R[G@XLYφ֡C@Yښ4@b |?w!gH4Tgp/c-vEj.? /~v}"G0Fi,Z!޹hji{6`Yd֌"J+n}!0{&(tu36fb}t>uZ(QTT;|t9\m4s*jݵ! ~Z-8x/r] X:WN!?~rl2(>{;(9YTc5&Zlab@f18yk1ZimG*@<>@۷JSU$*_n e1܅_Zm-{@_>]a-Wo^/pD6`df %A@e2& -9J( )> |)afYvDbg$f> 5$!T z_/-27ZGqW3@Tc>|{[zSrR/# ҂ ĜT! _>P(}^Fyo?09X Y+>빇w{B!ؽ=ib>x#C-gYta:{Vd{S1\:#[_Z4"}p/\s dD۶q)erbw;/0qU*MUBzJK̇_3? _> mR(5lz?MYa }_(Y/~v#,.}*㳆ԮU1F^!3ѭ@MڈmE>\B,P䊹0{ WJo}Q,x*.l:|@kpZQ;sB3.]}rm(\~E!Pc w VGŹ/TE3_lYEJVL|WN}\+*$o`!^D`sH?DB!# ]I'T.: Г[s `&B,EWِFhJ۠(Bp@| DD%kQpopzxS&Wޫ+D_1dp,"ʽV@|Q(0[BoCL<|;F=|̩C ! FJvE]<@!bc[=]r7py?^Ly-&Fk04yƜp;Eb1v"QMݡ(h4by@,l6i RC`11`?|` ?\L,~7 #fΠ;AɊ4!S/9Nvώ̺\Y4P\4@9BLY1FḊXc4^+ iIkOzX0orA"O!p~ujl _> Z_>4<"LX&_>0M4/` t/hEۭGB:'p/N$s@@ l`~Vk)X\ڬ ' f +`}Ug&Jyb(mp i9TA{7NyӠ2 )5\e91  0n[P iqz={=SU$SAe֯<|? )M/+bO4yE>PpTDO*-Yl4 l u:{pڍ`ZQ8lgJAڛ&WJ2J^zD%m7r;7~"i5@#BdNU b7.By! +»+xKߦ]Ӷp @{p<[j 7p9N/ 4b_!"R|PGiE(ap,4I2W}rDP[qA}ԗ M ߿&vޟX=qXo|Z]㝚T|E!LT&pt;aZi_6@Њ}Qk p.Můz'k FxMyތ̶m`&Z+nJ80Ҙ_xQc!ϕfxeܝ4*_. ^`[G‚iQ|J ^*i \a@R݁TDRQeu| Ek]lڞ#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`_>0;0-EafWB9FTS  Zw(AaԘWtm/9;a(#JIqנ2P|t>N ׸Qc"(:/pM/(Z3_6G9B@j@hskai<˒9 "h"LCS>+J*j} 0 r9gBS\|;J'"ߔ ŧ /`:| X|ș_>( .5f}oұyADQ~! wG7(J:[&CxEΕ5l̘x%!4c uHT r][d|5 /M{/KrJ[8iU /ۺ(~_>y;r{{1f_W/:_.`+Ң<鞐#p( 2QGZo{(rjn1$`?x|!jWZPA냐ݡM(-w  .6w6$$A/~3f,"]V~u$2<#63| Q+BP8 U}ȡ~ j[P&<|QQ=Y)jPliioPP7]ԍ={bDX cEMI|G6 0`p Aab*Vk+!0Z*ty%`9%`Szquyeeػ_Ϳ>$&ݧ\:'BPj;d$BTDgG*dq_gnla5,|b+xm6e/?̀/0x+ib>^C](?p?pef=xz_>pUP*-T$`?(K1̀?P٧\vgvA^򁻊*x'q C Cջp2@z[&Zbw?@v EPTy@=Aw¹xc +֜MX} ++xooDS?xhW]fc~M^ 3DH)+xU1lP A5\q"g6dP_r(k1 ݲPλ Y؇8 fO/0{x׺Ⳣ4|g,>`h=" 5^T gOW_>PPj9K]`(C@)3"`:rh5V(>+6T[|P3{_,/c-vEj.? /~r:Q(KȘb" Qz}, A40^Q|usWLC_ۺk3>::f>Q+*䩆Dwri`TԺk9BSZq2DSzG.<\J)>@( f ?k pd*CfPrռ*3rX=ipmh _)N{cs;#ZwGL9aZ"4P8kPT/[bYvw{JU|+=^nse-6/|Hlz4?.Qc֭abu~,0cAH5`66AGjV(34(Ξ9ǖIȘ&(B(G/H빇RB!ؽ=ib>x#C-gYta:{?Zo [w$`Yp~VYWD ^D۶q)erbw;/0qU*MUB=T|h9cB )Ræ?@42En$`Ys@=o]p|֐5|5h6ЪcE "BG(Vr[ƽu+b%>(Ck`6_>EXvPL/KW(\[( 2Y1.4p$_Pk͗>P%d|mhBJVL|WN}\]@P AX ` 6׊D+C/+Cj=BĘ3k3 mQYmMPk1Dm!0!D[pAU$@Y^@QZ^jM0Kwž:'ePÒ` ?$*T$" c>L%J%R(@wbb&=L/`s-l9iaPs.t˜1Pm]lM L7?'=YmMv_6Bg*xuJ`(+F JACmvgP a{1ܕxBHs=5f!\M储dQU66(\/P=?dd-PNoxBj[ƶ{> nZ+~[L55`hr#94-wc503FQECP 1mєiL 6 X8lml+HK(m/@9Lcc;[ZY2;nXyBOu;AɊ4!S/9Nvώ̺\Y4P\4@9BLY1FḊXc4^+ iIkOzX0orACs(NpT v 8 2 @T %NV/` 4es_ҙ_.Њ[(sjN85\ Q?\ f t~?"z-hX|/Ƞ_`ưn3XLt/P>d/ 0sK **7 ؃n`@ AecRjrc46v`ܞNcutZoq8>pDqӀ=h,rѥct1b*FdL+:Wt:c;GeOB<ŦJ– QS1> 8q &özd omh* ΕQbDғ *mr;7~`jy&3}!2*P1 )"vmQ(O5< aEXx7pE}v@NWXl db}'t~!B TA.4BQ+3TZ f~Jfq&\AAl9r傑^S6ZjEhǑƬ ;bZ}0+#>W erXZK B> MD)70?+Tozh;P7p$:/4` CvMPm"0Ubzŕ< PZրYYE$n9|`8bV>(/AȱbN15`/,Ljj)J_00ȘcDn  9o㐀]؎k Q(sv'8_ :u9R!3%+W Bcp,\ LCs.Kw(~`D3 (gs Z(f?@0U_(;6`e93D ԛ),>Nm%qo+)B`*P4\E0\wW0\WeۥYkfkn.}D_}G(rYZ>3{F:66/7(#X9n J:" G?5Nn!8Wj٠FZR5\PZ@0\: 'j `5|"zn/0qAmP> ,ЊⳌOSt rQZ+$ w7V^hcp65lKE-L0('޳}}n#7+ L/8BDXZ0|B+BP8 g%`+ƾy7ronC=pF[| >Y83>Pka}O(=pDr5@EBEq"kQ_?`J{@,WdU.V|@Dq8wP1;(<8n^x5\ Oy7򀘱kTQp rmAs= #//3Wӭ9-e4|!u+ n\By ҪltxQB>4@!BJm_Ɇ_~2;|{0n9U}qH=dP;9@ZLÅn٧ @λ Q,Mrh!? (Z{ԊUkk9UhD9Хz$B׽]Xt."rs]%=_qtv߇*C@)31mڸx g{~qt|PˡsE w,zE{]Ej.?=/|.P:LCi,!c(pN4@6`YEȩW*fݜ{# B`hMQJ׶3gqNCߡ oU%\uk9B*gVMwB?ݲϊN ^6lX^N_P0-&Pc5kE |G46L4;;D xy(Ԥ/h(0J˾;|D9m /#L/̶r4\0E4jyhy`zM/( C>G/HCs;f 6+?zPnW(ζbGߐlOyO&H6CL=Y8twtlMZŇƮrTa_e3i [Њ4b 53.<s d`M/DzEy}G@ ˄ 0Dh~PA}T 䩫?VR3Jܞ=M/ BJm0齀Y?c{2Ff],=fƜL{ *B'R[kh8)j)x$ȇQ(zˢJV }i|JQ\ qUp/]] \(\dcT@UHm@G s_( 3_PXvy2@+Ye FJ8{ Q|/]5֖SY+Ui6.Wj=BĘ1Xz7NF)o5b}.)B`*8(CRH4Z=P%Cۗ.szu_z^sqZg}mq~^uC}yRjo0i DRmo`:>+5vj[Cn;5Y\CTǾ6Sz0\4ǶO,UA9V hGh¶1g@0n@m'GF.UGSs+EYxIeGw;g6\#K?/DZ7" tc[5<%QO8J[+R셽Fn9< aηfYB\l9UN=Qc ifc T5' <`.DYw'!L^0#ѽ03l! RGy[G 0pjtE@Dֽ"cau2xUN8DKo:nD^@vEYz!\F%k FxM`czmLT+5~E>$4fD6`zs%$^(SƂZ_^ض|hE G6So`~VxAUtb-vJDBaY`(>z >GvBB\/7ŕ< +6vr8 >1Dhe`8bV>(/*M|x%`/,Ljj;5;uLj* jEƼkBqŸ5Q4'v\eB񍝳814+(K\ߚCHŖ{_! PhskaihneIBn,h`lTV!Tz_L_(sNI0 \sW%Roz84? @P_>_tһ+ Nxyů9eۥ_gbv?gL0^s#JYZ>3{F:66/7(#j/ûήHO/CxEΕz_H]o iGEx­A_'DC[635x `Hi)G=/pxl. `Om؋95z񢣧=\@yZeT=\@0<: MO/ 9vWC?qAmP> ,Њ(1N.. f K#2@شq'KKz_hX?`~e3QNg.+?+fGnWPe_p 25z+䇹 IP&΂Y "؊oލge2GYy?;E φ -] u+ '|#\!r̽>S_M~*X8\C:UD XH\b-#[*~Uhy%`ٵ!`Sz: d.[Vt~>4uOv6pPD)nK`N+dr-gyr/k!~e`w1J N0(;Afge1@O8 5FSypf6NPcaeJl7@+W! Ԧ -ȬcΡ {EƎQe^E@Du Ľ;(<;( `(:8&1 ZD{e1cǨP⨏(@4`28R tk&`}'hiZ r 1-hJ?`F 9e)u^~%b~ qDw x }_&U?Fi" bG.@NO= ݲOiw@ Y؛8 l0C`91Q+>[T}*VY]Z @힃 ]J";+`*؅Ewsn+BP_/J^1^o4A|ѥlM`1QW>7Sfc"`:q9q} *>[l(zAb\(gH4T|}Ǣ!8^R.*W{v2*'^">/w(mp&9~H: @m AߚQD/us٣5Fa+X1(ևBc+>VZ\ϕ]CiD+i)i}_(*4A1 uk9B*gVMwB?ݲE 0_/X P Q} AU :(qE %~@r|3;bipmh 8y~IX =GP6pȯ2 n3 %n*ANKhqUp,|{ @+rkeeZYQ82 `v^DZ4ι Q¢p )P(2e/Vr9J[!P*ToTÊ<eqEbQc 5$LX^/>"D C3WZ@ wo٠}_mieٶz_s@Ms 9=+N 1 2"Q}^<7wDۃmuW~ݞPkm1ԏ!mٞTgLl#&1=fе{klMZŇƮrTaߺ^Q8G/i@kfaޏ'`P ڶpR&ESC24D`{y< *!O !?[J|+rCm3JfmZWDTH0̺([XZU0b"{J|v*:kh+d&z7L9& Cl+aE 3oԕJ,챁#gvZq6_"XZQξYDȹ_8[OT.dc!PcR[<#ht"njq4yf eL| @+Y0Nթw7:GH QoVRUOm\( 7{1k-}_1Xz7Nק! z[MBlK f-{ D) 5pik-cYwEiwzPTwEJo`n6`}|Xu^ 2Vڛ̇~Z=0QGTh[}N`` X:m:uv @ 2"Q%Q(50*+j! *RXmC?*h?@ !Hѵ#{ ~@su]a6t̴EФs߿Ŷ~_>B{-TWW()FC} WFE*yoȩBe9H^#8VIOL)un'L4fJ_&J.ʆ4BS" @T+"*Dz DO+'D9/B2`i+*\[n"JߋݲU o 8A [2-FvB !%*ي:L %B.Z|Di _>/Q ͠|LHcN8 F`""03F)E5uC;@ 1mєiLl+hc"~(iLyw0xe97Z23 2;p:A%w6pΠ; Ɋ4!]rz5`c׊ =;B0ʢzObsO7P|xEq4椵'CӀ2A䣦(vpTA=/p~/ @T3 " 0 0h !ArG\C\h,܋*@I[p/bYpfAs܀E`%`ưCD)OR 448{{$y1JȠu=4Rc4-Ӏ޺ :]-η{F%o[H< ؃D( Le|_&t<`WLH} kt^? @;)ʞ XE@߲AUp:N-Q:*bGe 6LVfꙒiTHd p#Q6A}_&@r(짱 v3@e=}!2 PbUQbǭ6d@(4n`EՇ }oYl-{X \QKF߀3Ph\- IW±({ل(!ahmX6U3 .p#J}/Fmh(yAT!/:nҼI{fW4`Gw0:y-*҈?/bZz(е[L%Q9̩Ůy=/TG[^/i2Y.P }@06"rP@T֜DJLfBU*v)J֋(W9b(G5PwO+ [@wu tE vwVȱȺWd,̩*\/D9{@ 7`a/-z_A߳Cd )ϛ(mjEhǑƬ ;bZ}0(WR3cG0o!}^` '-"DUtbLE$:/4` C9[l(f9|B'ڲ2JEy.4DʳMݷ셜,>#-*4*j'Z`,9-X(f~bDYJ0cD``n`ֺcDn4!cgMGI@P|ct>N@ %qC8R!|u f8->/}f>Bcp,\ LCs+s*c6A`D3 (gs Z(f?VГ~_=0 \%Roz84? @P~_U?/`:QJ.P\/Tog2#+m&׹{%y@Ǭc-Yܽo#DՏ3`XhD]~7+@Х2C}_a :HO5(~6^hh9}fF>#}q Vi)G}_f]_!.:za)c{m^̩K!.LZXW-5F?/ n uNԂ`2@EN^-`۠}X Y\\"*t(he%bt̐ƒ>/+wfѰf,z"]V~V̺ |$r8BDm @ Ae,X H, (j[G^Te)EP,5?"O{4w7>ъ`dsb+DgJ+زiO9 kH砊 ?/ĸX5k+!z3*)d#G@YxYlam@Vt~trT?Ra띑B9uI䭙O/T8e0Q?̇sAfoe;_ 5\*2{yr̓BYX/`%J|Wz"Dڴ;EEGYd8gqۥb^]'itA{%O׺ZbqP3DqֻdL&7ůnPۍa/D}ԝp }+BPp#/=+֜M'?pU *C0cVu+x)F Kw.3J1&/(3DH^Px@/ic`rƭ6H@Y\dP89|Aٓ?P}JČ;Ua/Gx0CyQ;>|ԊUF>rmyB ׻0¢;;O+BPO/cNXActA|ѥm]`# }o, Duhrh *>[l(zAb\^Ÿ=DC8"X].rWlp(rjơ PZ!j}Ph] ^TNgV+4j݉ ٶx_>by7"fl[0c} X XSb6} j]!OK!Ok9`iVosx_>p8B*gVMwB?ݲE 0O/X P Q} AU :(qE 3h9jDM9X=ipmwh qv</B~1^BwGL9´#D~ipQ(qV rZDbpe1M/ r+{hp~xfw;EEӳ+Ҡ}L֭qB%k!kq8 },is8P&`?|BX(m@RS+m^`{?D9$UTϧ`::n_ZdZGߏmM/%M-GrR n)yHTrA1a !F\0DVW 9xD\1}o~`ns ,|"x9%5Clbco |x#CԪ̘Epr=T75;띖;+ <"{4!B,@m!0L\Pn]P0!BQPA}T i3&f>h9!@mBJm0H!`&u/A$< Yz?eUcN !ؓUg }.H1 apx$ȇQ(zˢJV }iG_"_ !޵ 0N/"voQ(rޥ-ק* 2YX!PcR[<#ht"{QA%N| ;\oyS4) o07uDެ`V$m\( 7{1k- /0cnnRջjg\RTpP0n!JhN]m~#^j}ݗW\ܾn-uWgC"<`>,!:B+ )HìwW ޳0K[ľ|lҊ(;\ fEv_>`vqDXeE9AP*+mG8BsHk#{ ~@su]a6t̴EФsSO>Mv_آI! =ހfq g/t@^!ئ i1\^FJ*Tj@9u(}!D%%aJ/]_h#5py?^LyOL55`hGsi0Z# Ƙk`f7TF)E5uC;@ 1mєiLl+hc"~(iLyw0x97ZY|W8MyNB3h/>u" sq׫ZB3M-ݳ#^k,4P{0 i 1!AXc{^8?"(gzQmV4 azXVf +:1XLt/Pd/ i9 Fp{ж*{8 i)rh 0n[Pp1޺@tZo^`1Mփ j3AH< ؃ ,0cr_1~l8߀}̡s'EQ=б[6J– QVԩߋnøu٥zd8PAEC7P:(1zI޶ݠ P0 ilCL{Z е;CdNK4,8GߖQ(O\pEXx7" Ңzކ+:n+"tE-uoPKAu 㹂 xW|PZ flB0hmX6U3 .p#J}/v.j9:?pz4E"x|@,< Ae2;Nu^ *4bx /xy BԊ7@Fl\%QO8J[+R셽Fn9\ aηfYB\ @+ eؠ:ȩBu PA[s+yx"fBU{wQJD A z1>G03l!VTշ P!Ocfu.]m D~E Ǟ@Dֽ"cauto`NMUa@T:: Zzp&ز)@|%k j02vkfd1lfZ(+q$a1+ȭ.&:(s+!4ȹ;iLUҚ_. ^kq~i0zaU(m Oɿ}"BZNXE7(FىLTDBVn0oCEi# GMY8l,RQA "ѹl,;bՊ^3Bx vtfI?D}Vi,s+{a9FTG_0070k1 7ԊF;x (?^l9tDќkq ! 7v@wPӾ > \ky-7lGr>3@u8aYs%s A?Dp E`lTV!T_ E}uSLײ /|z(!z3Г Y>Nm%EL)aB\E0\wW0\Weۥ٭0]psiE} :w8D}̊>@6ұyADQ8C΋&Hi8qwR6"@t_a :HO5(~6ڊN@-o(Z{ ;áH: X8۬+'6Ŝ}xrkbZ/F<=Ͼ@q JLQ8Q _ 򁊜6\c$`?cܾb(>@;E;)DUPK:bbt̐ƒ @ZW !D9YE뻬us>_I@ey"*譐o($mb*gBPl7FG3P۲BGYy?;E φ -] u+ '|#\!r̽>S_M~*X8\C:UD XH<| mŪ__ ՛E V啀dηgGME ˒ `__op47AWoM-m (az ll?YC /r!,3m;q?{?`qW|b>nC=pF[| >Y83>Pka}O(=pDr5@EBiw{E{,2@٫pM&ůk2r(%(&Mq< fU(FqG}3clu8/Pr$ 2xE?ݚ r[F3ʧ:=PY B[!׭m*?->.QB>4@!BJr_:W;|{0nD-" bG.@-Di=BBX#?g9gw 'E+rzOw\|ԊUkk9UxWkm Cꭒ_  vaꞧ3A?Ʈ!|+r z+.UwAec}3e`F>![i `Ql({~qt|PˡsE w,zE{]Ej.?=/|.P:LCi,^yip既Y/*~Pcۀe)CзfQ"*fݜ{# B`hMQJ׶3gJ1%a3PQ yZ yZJrsſ_.PԺ! R+ΦO֊nYwE0/X P w,.6TP'`%{QH;9|g_^-g6;b5@i]b1 8yn M3^#&@AaZ"R4P8PP~ѥ**AEwKXs_.D͙@|V9Zl/~\`vSTl9]k^c~< 3m[Bd BZa] {Gj} (<@\5a?H4BTH(ΕCQc EUarA)V GXA>M{\삨 }vm97h`>M/i.@1a!F_.P$uP М掙}{͡J޻^LJY EsJj0n:d"4`s14@~Gg?P+^y.?!jMl>nPhroCl+ۅ"XѶ^r^ߑ-05M/LC ̾nGiGUB;٪U `_3_.(VH f30glxֺzϗ _Ȭr][n%`Y10`kP=Y go%>kHsu @bY {D #}mE>Bt-sR 0=6pzo=P g {F w{SrE{T@EB&2jBjo H4:Aq Ue7 @T{8>\s&eWNa>VCДipq~)s j0f%[_!劲p\Gsܾ23K(Y&Z !~t!0f-{ Ľ4qm ݶE`f:ZB+BPqEc- ж8?xX ZWq:\><)7 zH`nж 0lE iY{uvI /N4` BO>Mvy_@1c-Ta(*)FC+2@!?݋>TY Srޑ6bq4BFU  mb֜PL偨\lH#4}(BH1r PaJE Mhܧ+Օ"QN˯Pn"`%?/{˒*\[n"JHv[BoC<\@rfNw_(QVԩTHm10 m/ߋ)Q ͠</D>^(vpTAM/p(D=/pA 桁_>eBM/#5|˄_.ÐY}m~&+[(B:;4eb@>[Cn;"N'mue^Tqv^& {t >֪3mn P"Q4`z_.pr?) /+b>5Wt:t^$(E9Er(B"o * 8[DZQ=.8@0naDkE`v)F7mPPe&WJ[%FT/= ۶ yo w1Qi5@#BdNK4,Ŏ[m&CTǾ6Sz0\4ǶO,UAb+꼟C`Sn4``^~rUȋpz4E"xy\ NC LT&pt;q֩kAEPF "Dx1]M-_@ۈ@(`'Qe)Bv1 s_0e]\ḏ^(CXDNSH ښX{({ +>Y$&(־YR2z1CP´^DqsDq?+ [&E~;T:jY݅KW[Q|";Eջ +XKOd+2QWHKzT {@EYvD^[65\g/mjq^S7#Qf60ՊDa <_Ѭ# #YAnu1ѩ75v@1Ĵ\ `WFHcD0o!ZQѦ '-"DUtbLE$:/4` C9[l(f9|B'ڲ2JEy.4DʳM{!'H ⳊIV6- (f~bDYp{ WrS Z kƼkBqŸ5Q8$`6(Co !5naGY*:/ z_p(GH3\`Z&` \ SCH BZfPJ%`B>Q~T=Y<qNQ(`LBIA'|[I|J T8 A4hPI+8Ѐ\@3\PQ]ڠuGwؖfkn.}D_2_>cVԛ6BR1q,@t# OSxEΕz_H]o i-~ :dr͌EͱGAA_?6up ovpxl. x {1xi񢣧XEyZeT=\@0<: 'j`rAEN^-`짿8WV|EY;eBpxC(c/ɟ `QXҠ@Zp?`~e3QNg.+?+fGn[*2#DT[!?-PHT&΂Y "x+`Lw#ݳTHmYLQz_NQ!rGHKsx}jiP|#\!r̽>S_M~*X8\C:UD07u@>/D5[]bZ^ XA|{vt ؔE rAA06 AG+:EMw*tA0HPD{GVdc_g c~_& 2@w (G_̇3@14g@P\U2=2(gaG( Т\MPPAmڝE",2~@OPb BTOghZ~~@RA q[߅ >bV -gRbg2Ϩ2A1>|lmq>(H4K9K}/|}NT`j큐[]ACr$MiU~6:]]]R|@(!=49@!BJr_:|~=H" UAY\dP=9<@ZL{ I[X/Ua/Gx'0C_w8|O[Tt>`tmU>3zO b)@D0`ݡ `E A۫9ԋtWIW *B߇*C@)31mڸڸjʡo?qK&* !8^Zlv),E2;9'Zծ(rPZ!j}bhE"fjlBc;Agۺ+on!0{&(t϶53%L=XSb6J{ j]!OK!O7'(*ib^Qn-G6C S觭?+NVB~T_$4fP62 '},2DQx+Ȋs{M!ؔצ}w `w_ 3Dk1Z Rm`F*dJP.Ŝoh{_>og(-:L-66e+=yseirxE19@Ԙi3غ^dk!j0w },i?xx_l4}  %_/P~\/pM1(R}*aES~ee ސ`א0?/`\:n_ZdZGJ.!QAm[_m97hy`> /4ja!F2_P$uP߄D544繾c&=R] ,|"x9%5Clbce{b>`s<‹!f;?Y8t{tZu>'1\iݑ_i `/q{4!Bh۽7Ô2Y( f뉌Rl['ԊTKUygV)r|%Zΰhyж633 < N V:Hìga}6UjEQ}_`L%ʊsJT.ۅ!1w4?]i}Z09ia mbO *3mp;4c l_/5@ U#JJ`lXW l4Bx_@2c п Sfƪ!>^(J>2ԹMLܚS3JV)} \} iE.VbyE CD%"ju pr&W$X ' ,V2K[^PrQߣvprbZh~_0sg W=x佷4L %B10 m>/)Q ͠ HcN8 F`آ`fƠ(H`h}!m03byX8W/U"3)>qso s2;jgk_3%+YFv~AiC^jƮ{v`k͕E꣟#Ĕ}>f9"d>5 xEq4椵'%V272@cb׫G%2 @T2 %NV r 5<0hr 5< !ArG\C\h,Ec q:gcd EP, \ڬ h2V pfkՙRJ,zE" 3t@QA Z0/p(`SH~ת0T( v`J({8 ޺y :]-η?O|6*yp%E*/*7ȯ8oy@F_.+bO4yE3l} ʞ Xy? J– QVԩ1nøuŵFQ-}$=y VFKOmo dbbYe+P#BdN?/FUqkOByZ(4n`E}v@N^A 2ge?pA.4@(*-g f~JyieS*#Al>PsOp4È E0/U?*E X=qX"ipwjP|( OC@8L!A=8@E1<|L!jE(еjl2FWD/0rV {D@LÜo̲>r!q P@/47"rP@T֜DJ^0 ߻2JR.E z1U"B8F`^1DNڭ8"D:jY݅KW[Q|_% Zz"^BZ70<䰎>/M_.{L4셱eS!{va=/LT+l+q$a1+ȭ.&:(s+!4ʈF 02w!ZQѦ ^*iPh~dE݁#yxPXV7we%J8ͰjEE>pVqy~ \hZ(\_}k^H ⳊIDy3YA쓟!Ǯ9 ԀJ_0070k1 7ԊFyE0FN>tDќkeB񍝳81ƍ2#" (K\8xr !R|>X f])QfPJ%`B>Q~E}uSLr9gB<4 PVlqo+)B`*P4 pNzw_ /"y,xV3ٵ 7>YGLs#J@Ǭc-Yܽo#DՏ3`+pS^sp+ݡ p}N<*imPl(FMS F{ %4 : X8mEy3;rۆSB\/:z^WPgJeLQ8Q ~_. 95s{yD nr1n_o`1Y;eBpx*he%vi1:fHGicI\ZЂ+r=wYY1>r(}@x_ 25z+䇹 wE*gBPl7FG3P۲B,EۿŝgCi.q@ؓ >[x/ cE l@Sa9"BƳM`~%VoFXWV9ߞ]6-( /K6  H±KT}lJcȽTEmQPD{GVdcz_&gy2)_y@rm`>Qg1 4w@k >UyW>`F !,| >\=PPAz_@P$lpEf}Ow(^gT]E]u^I AQAq[dL&ZD$~6T$v#?`vQugãe[\H4K9KdxE?ݚ r[F3U. [ Vu+b[єVg)WԊsQB=4yA!BJr._:xAHk{ 0nGD-" b} zT( _n٧ @λ Q,Mq3=<{jgkk9UVk ZsK XQ<!JPj9bUGawY}21903]uhrh'T|P|PL4T|c(BpR.*W{vn=N^EN /8v2&9~Hz},֝>m(U̺9WL0kY׊*&FF)ևBc" =u<-<倢;|t9\m4*D(jfZp6} Rbg.<\`%@*GENH#lUa3h p(C%L -Xh8C)" q48} \_gVN۰9Cxdk1Z Rm`Fui/G.d.Ŝo 74{|V @=|ǻ,0)*^c\ 3m[B dk!j0hm # h@(<\@1|k~i@RS+m^`{?D9$p>p;D xq"C;BWZ}u b r,ާж5O-GrR n)yHTrA1a !F\0DVW 5;^<7wDkNYxvwӆw{BuuS?e{S}2D9~wbL` k{kjMlzxO_^8~@+҈L^ DzEy#[ZQeBrA̾nG _@Qh~j&5 /h`F8fmZWDbuQ Xw9-T`O[W5H1 a0w1Hl" RoYXɊ0{ 낊+y+]{Z{o])iErt}r 2YX!PcR[<#ht(kDgѰE! ;\oyS4) o07uDެ`V$m\( 7{1k- /0cnnRջjg\RTpP0n!JhB{,KHs^Xg;Zq/=AŹ}ж58_X=ZWq:|C}Rjo0i DRmo`:)^+^޳0K[ľ|lq` ?(N/P$" Զ1WBT u.h?@ !l@tq1kD,8涱F?56t̴EФsГg] <|@ZBWW>PR3̇8g{ź=p͢ "^ ^ȩBe9 X5b!Jzo_>0B/80/ )ϩT2Un4`[:Y9ĸU]lZQAgGf\YTi>h9BLYc!AXc{^8?"(gzQmV4 a4\`%`ưn3(^Z΋d" Ӏ=H CPM/N@BJM/`~_p5p0㭛D+\賂*~mn Pd{,0cRV|TɲWt:t^*Z 쉞UXsҀ%@ԩu"8QLײ`EWj@!G2 ؓ(1zI޶ݠ P0 ilCL{Z е;CdNK4,Ŏ[m&CTǾ6Sz0hmX6U9"Vy?`nyas_Z';VG$4fD6`Jϕfxe LUҚ_. ^k`BoBhQ|J /4(nP@<ЀU(, Pox.C( Q[6AF υZݷ셜,|8 >1DpAD_>0Ow`F1+hCs_>#s#Z¨1<`M/ = صHԅ WplourBoMW Bcp,\ LCs.Kw(~`D3 (gs Z(f?@0U_(;6`e93D ԛ)V||[IS /*L'BL/( .5@6ұyAD vGQxwtQi8qwR6"@t_a :HO5(~6^hh9}fFѢ#]\/ {: X8۬+'6Ŝ}4xrkb_(O /nrA&(O/k@EN^-`۠}X _9h@7BVtx#%H  Z{I]lZQXA/~3f,z"]V~V̺ |$2<djVs˷oCf B8:= ~ ʄ8RTϻY)j ~6Dϊ] u+ '||ҲiZtg(>7:_.9$E XH<| mŪ__ XWV9ߞ]6-( /K6b9 ?%-jҧi&=~"ô;#B:L9sZ!Jo x뭁. \ Fyh a@47@h\~eT} t+q8(|e Q5.=H0nD- " b} zT(DiB.t>Ubv*dao0#!/0xxwoZ٢/]XT±Z۠hZ*.(PzS.,CtX_cNXAsKذYD]XLYAm5VlyL4(Əeb\.`k@e>.rWlA8zE95|桴,B(U?$ @ViFQ8[تu'ajŷY7=Z`vҰm}3fPhl=:@6haҪ񕐧54(*r)40x[<0,rl Yv7d觭/r}0|JUȏꋜF fAFP(Jy^-g6 3m[B*K`@HL q Q ]KJ_>@15(R}*aESeqE\?hlK!L`א0z㺏<5( r,ڶ\ZCJ_>SF5ͥsZ5^!b0s"44繾c&:<`ns ,|"Xl!~ YdS}2D9~wV%`@מGg{k5UkQe~r `/qЊ4b 53xb>s d`Ѷ}Ô2Ybq;c"D/}؏\ *!O=gZ|+rCr@mBJm0h=Y?c{rFf]FVU9-T`O[W5$֘ȱ]̩"VDP-+Y17QR}$BxvQ\ 1U|)4Xv0%9`\:@l>PQɚǢ/ DPQ{DghZ  //u w#E ~x\; j0f%"QvhrEYIV#D9n_kiwt}0wZ! a&Jݲ B"Pk@Ym_fu_z^sqZg}mkqcbuj]+/ڛ̇~Z=0QGTh[}N`0o"|qs;_g,"ހ6ۥv0<DXeE9AP* ]☛G=4}Z09ia 9:ݮ0f T:f"Pwh9A .KEAЃo%%0|so8{{ /_>^ȩBeqw3c؋yGh|BR61zrkNDC(Ya\lH#4}(Bp@"J!kQ8/pz=h`:-l5WW.D9/(R<\ҖWD3@|Q(a o 8A [0@@36`ԡ| PlE *Kl6Z|1W>11 `X4`F,1 1 FS`1>Y= 3[4 RC`19{ so gfev\49uJV =Ս`S'+0wʱՀ]+*hך+=  H{Zi=b>`h(/l *Ҙ֞Mvܞu"5 DՀ _>A8_w P8 R PBL/`'_z3Ԋ[(B:;@gk@mrW60?x˂3W6+0_>`%`ưn3(^Z΋d" Ӏ=H Fm T)p(`SH)i ay j4`>[7Dvf{l=6@  ; +[ѫ^K?bWLŨ,ixEN}̡s'EQ=б[6J– QVԩNjpk7a:ZLV iWECWe(leQ$JޖjߖFa?mshbOv`giFUq 5\PHi`(RZTpeAmQ[ZJ[B<ֽ B ,.(\hrg ib_!"R|{s Q QBrͿ00CY\Ti6pDOp4È E:?pz4E"xJQ 2qRY:AE1<-} "Dx1]M-mD ~E(֊{ah[4_>`%ą 2zAu6S7$V`O/0 ߻RT&Z/fJ֋_Q܏j 3ÖI"iA_}4`VwՖ@?T)(XKOd+2QWHKzT倨 u_ua/܀0l_A߳C _>02vkCZsC3QH80Ҙ_xQcCLϕfxe LU҂/[.C+P8ڴAK% -'h;P7p$ZŲ(PXV7ʷϡ"`C4ϑ]P䣦,t@ňڲ2JEy.4Dִ|oPl(s1Bx}}l9`8bV>(/>r!D SxZcDs#pAaԘWtm^9o㐀]؎k Q(sv'8_ o:*W .H~ Ǹ}ZQ|  Zw@wpq;R"4*СtŦ!%qM/d!D9YE뻬us>_I@_.p 25z+䇹 A!L ADc߼79 VBr,EۿŝgCi.q@ؓ >ω J9^t)`˦Dp?,!*",$NiUWBlftUhy%`%`Sz /,, iƿ$hE7s_g>*tA0HPD)nK`N+ddCM/|!,3m;q?{?`qW|b>nC=pF[| >Y8Ŋ(] d]/|B#.*B*H- ^Ȭw gEPb"cרrz QAqK uM&|ZDI8n^~@5 P⨏f8G9ʶ9yhr/{b>ZGOuz2nE3>#9sm*?->p/)^ fc]"{/h=}cyVAqb ,vdjwr(n)?iEp7b/ 9;.@lQu_.0Xwv@k1Ѷ{"̃DS.,CtIƮws z+.UwAec}3e`F>![i `QlIrD>(P"pDC;="[=.rWl ~p(ryޡPz<EsiFQu[؎Dqm[[Ŭ~oD 0 ;]ڶ`ƴϘCT|haҪJz_>PTz 8L -}a@Qr`3T~K8>~ )A1 -\tVB~:)12T|6lmdN8Ye*9u]7ùrHÎffoH|<kHz_>h>"D J.!{\삨 }Efzgd̶r4\0E4jyhy`zM/(:[]a(^<7wDۃ1g:ug=m(}g+Zg[` 1oz['Д:d"4`s14@~Gg?p T[|h*GuO}> {;{46@vBQ8@rAm!0L@1ir׍(M/ (O !?[J|+rC )wfmZWDbuQ,sZ05R[kh+d&z7<9& P"VDP JV J%@b³kWB+!Φ+j-b<…L;=@eX4p$8k.PD <@-J_:XmAS[V 榰1@>ZZ+Ui6.Wj=BĘ1Xz7NF)o5b}.)B`*8(CRTk@Ym_fbWk EAyQ~m[uWR{OT& mxI\Z_p Xںm/:uvI ?(V@((R|J^5Bl=& 14_]i~}Z09ia 9:ݮ0f T:f"Pwh9A .K?/56[GL#!+2@!?{@%9U,nk *0a{BH)mb֜PL偨\lH#4}(B~q naZ? ^T}* r_]  ,Vr(,myEZG!7!Va _.hf3{Bqzݠ%*ي:> ExLLe{1eW>11 `Xi hX$6c1(h0J);4Zb9nu" sq׫^ صvώz@}sr,CDGxxaHԊ|MƨXvGM3v3Qz59_ |/ D;QA(ܖ8XA<4PLyD`P`2BrG\yA1 q ͱQ8{#c/bYpfAs܀FVf Ι4åHTf !@C"`t< :Nec )uKO  0n[Pp޺ :]-η{F%o[nvWe<\ hJa +:W=1JQQQXE@߲AUp:K@鰫!ŗ)،[X0Q\:ij@!G2 ؓ\ (leQ$Jo6-7~`<ŞVtR(1(KV O+»Qm9 &ytܾ2t~!B ,.(\hWf!*cQ)=J?'(c <0WsD  Z>՗ #64 TТ6ޓ#P*ҼISs+8 ut'2qRY:AE1<~_"roEt5kyo#J+uDpV {Dry@LÜo̲ r\ḏ^(CXDN] PA_TQ{(,g1+DYw'en4(~]b$}#Q 0]af2)BD?0oݡBQ.\)]X Zz"^BZ700\䰎/`&`a/-_.A߳Cd ) Yx_mjE~E>$4fD6`zs%$^9w'#JZ_^ض|hE G6So`~VxAE݁DBaY`(}.!3 jY>Oecd \hΕg` o 9Y|FZUhUO"n\0Ow`F1+hCk&ʂ >gcD``n`ֺcDn4! m=Р2]Wp"g,xA1-U (f.\haxE_}G(E|fdq~dBR1q,@tvE~j+BpҠFZR`;vAHU1qAmP> ,Њ!+ ޑAQQ$v|ZQXҠ@Zp?`~e3QNg.+?+fGnWh1?\!L an6B 2E~4$_G.&Y*AQԶP&\(KQ=/gq9}#Kv>54(>ω J9^t)`˦Dp?,!*",$~_.q[j<WBlftUhy%`%`S6g"mۀ!5=~"ô;#B:L9sZ!'kuH;{.F,|1}r.(~L,>p |Q^%@fc/Qru俀W(]\ꁊ r"g,2cOw(^gT]E]u^I$;(18(8n]x8L> o0r.(%(&z'jq/{FQQwF>)F8BPp#//^itk&`ˍ!Z@`Nb75DєVgr RjsA4T29`_{`f3h,>p 0nDpHX*Ƞ'qr('- ZGN+ {FX$>(~[ԊU'30|@*|h<zSD׻|]Xt+!(J^1^J 6a# }o, Duhrh *>[l(zAb\~QPL4T|c(BpR~,>݋dv8zW>@S05] T}GCiȬ?/! NQ϶uW*fݜ{# B`hMQ骏 0c(PhlӰw(Q yZ ygVEwri`(jZl ogݧO[!%(%~V (\Ii͠*lmdN8YeGPc5kE G46KL48@uN۰9C{{0m_'.@5a?H4BTḢM{Y.?hlp>p;D xq"C;BWZ}u b r,ާж5;# `m!z|z[#r#~.fz;b"PC&~ԦŨ-l(G~2nМ掙{{sC]Ǖ}w>0m(}g+)b-@6!E;x+dr3_`N]{=[{Zo0WkZGw$`;-w{q\ڀyƽsA1)/=ɂ Q45~mw(/ @Qh~j(W m3JfmZ "?@L#.~v#Y\1^}*㳆5WD~c⑀ "VDP-+Y17+YCC5]y59`ύXξYDȑʑwb<…L9GCdX4p$8k͗>2y>u>hBJ_:XmAS"sSX AԘa J 6kE !G~v664<һAt~0JaV~ "jOP!oe=`&Jݲ B"Pk@Ym_fbWk""@8|C?2<`>lDRmo`:)^+؉F/Mz`C;\QEEq"Q%Q(50*+j! *RXxFٲ!174 8|X@J' 1]L4Ac-u&}\}>2lЯ@Z~oQto?`}pBmyFE*yoȩBe9HF+ӰJ~ 3yTFᢹ5f!0Sz *(*Mi(\n3(AJE Mh\k_`U3Lpo+T.X,myE{Q azۏO/h̜:RQ0%Qbc./8</<'&Fk04Ilp1'0B" i3cP`R$ZSwhPkCq`4fS Ap8#ůG#_@i{)E0fS| yRԺp_f0{Q;8gЀ_l}dEW9vkE!ZseQ1eaY b^ Q}ffjQs/pd@0|`(9 _>fmk/kB qUz0ąV½8"L>{^8XEYA7`rĆ© RJ,zE" 3t@QAz.` L}L!Ԇ~/=U"c4{(&BQܳ+괶Ô:48D%o[Htg=h,0cr_1~l{c;)ʞ Xy? J– QVԩߋnøuŵFQ-}$=ٸՀVFKO{Z,sf;(k vȜ>/(1(Kc i" ,Xj`ߦ]>@PQWcTn>"D%ܠ:EBa}@(*-g f~JfZǶO,UAb+꼟C`Sn4` TТ6ޓ#P*^tc/N_)P&N*ԹAtSׂ"=C+@!8{/@> ^rFWD>(m(Kr9N/e q.epG/! cl," @T֜DJ^.V|߻RT&Z/fJ֋(W9b(G5P# Pc{(n!BQ.\)]X Zz"^BZ700| *a_-^ {al| }^>ڒ^5;5y3em3QH80Ҙ_xQcCLϕfxeܝ4*sK$94m Њ*6mŧRIB (ZLE$:/4` C9[l(4ϑ]Pg<GԖEQ**sy@$:Wme/5`/dipVA|VQc<y3YAX4Q^9G#s#pAaԘWtm^h9;qP#$ހ](Co !5naGY*:/@ /}f>Bcp,\ LCs.Kw(~`D3 (>%`B>Q~`0<QWw8%m4p-r9gB<4 PNbŜⳅPo4hPI+8Ѐ2|"g@EYviba[Q̮]dgL0^ LfD}̸ЀxtN|M pADQ8Cn07B1 G?5Nn!8Wj`?CJ?7 st-C(Q\j9}fFyYx `Hi)G /f]_!.pF_>?=a/DW@'W-5F n_>@0\: 'j_] 0lUs\tqz!+<-F wDiTTCA+c/M1C8JK_%"}&_LEYϊY7@TY!L an6B 2a2iHb79@m ee)EP,5?"O{<' u+ '|#\!r̽>S_M~*X8\C:UD XH<| mŪ__ ՛E V啀dηgGMZ06 AV/ *BP3)#R DB:L9sZ!'kyuH@>o.F]N@ ܶFo]Y\M Qn%_/df+|t-{Jw\ PPA_>poQ\H`/pEf}@٫p$u _ Fy0Cm & 5\i9&}_3v*8ꣾQ-hvp#/u tk&`m(@ef.n\sBDq$MiU~6:[}V| r R꽗@4T1 ؃HlO Gg>rUAO*_QkO-Vyw$_`0:2܇'.PZ}o~V|:ZbD֊=U1@DWT P<V_.cN_+.UwAec}3e`F>!CCC r/q9~!"PEbK tA 8zE9{0u/@YzCP[?'oi\/! 7ڶ>ŷY7=Z`vҵm=3b}t.:zt=vAԺBBV'(*Lë2J@Qr`3T~K8>~ )A1"(\Ii͠*lmdNE!]E oE9V&ZlwjHkӾDcT;4v l>p5i.mL@1)m弾#[ZQeb4(t?"Jm}O=e_h> nH3JaZ Z!6Q^MY=_Hr Yz?eUcN !ؓUg 5x$ȇQ(zˢJV }i|JaXZM 0XZQξYD6^@l>PQɪ{q -hH4:Aq UwqAT{8+B/`_(~%c9MJ8{9BB5֖SY+Ui6~? F6}ef mQ z[MBlK f-{ D) 5V(y{e e(-N/pVܾK+BPq.n_l/m3>+VU\/p/@JnJk mxI\Z_p Xڭ @) z'/;< fEvy_.0; "pF aP)sCwbp18Iѵߑz `%0fO Qy?'=|6i3_BrAI 42Jt6&|xa_ʷ{GJV ݙ!Uc/B ~_.Ur/Qht&&@Ob>h%+̔~_J.-ДŪ(AJE Mh\k_ r ^~we+iF1TD(}v[2}0 /Ќ=\`ԡ| PlE^@v{_F@k2Z2+~yy`Xi hyXGVi"њC h4MӺVZfYꙐ^J r  @h})j `ev\4eBOu; تoGW9vkE!ZseQ1esO"d>5 xEq4椵'CӀy QӌL^ 8*yΠ8wwP8 R@M/2 ͚_>eBM/L+~M/ LpzQ( ⤊2x+tVG\&0@tZo?'>mn P"QvWe`@ДXS1'f^鼢yEsIpTDO*kQaKS+E 8@0naDq-QTzc t$`OoBtQbDғ *m۠P0 ilUgj7"sz\PbUQbǭ=y0 i=/pEXx7" M }oYn>"D%ܠ:E q3P 3Dpa3J?@ 3\Esl4\ b90O^ B[>Ls{rdRXo|Z;5(R!LT&pt>JMiܧH#V@ ]&xM/mD ~E(֊{ah[/iY[cANx@ԘBuk/X'թo$@mIཅ,vVŅ,YR2>D~ONW1Cf-"DOD;@wu t" K@Dֽ"curUSSU_. rXGua/܀0lj }Wcd ) Yx_mjEhǑƬ ;bZ}0+#>W e>`,x}m Њ*6mŧRIB (Z  X²P}J8sd!YT- TTBHt<_}k^3Bx v*Ŭ}Qp_U( n/#J^XvjvYU[k!! m81ƍ2#" (K\ߚ";P-42#D9B@j: 0ܬ˒9 "X<"L\B0O *< QWw8%m4p-i_=CJBPV,'"Ch(>=Р2]Wp"g,xA1y?b+څK{,m&׹{%|@Ǭc-o0 exADQ{ɧ,@tvE~j+BpҠFZRwt 7ϣ"Q<֠P!+ -o(Z{ %!q`S \ͺ(B\ /pF_.`_>=q<^ qQzz_^Byz}  (2QGD-xl_.鶻*9.H~ Ǹ}ZQ|>f):^(-PA+c/MQw܏y$A/~3f,z"]V~V̺ |$2 djVs˷61L ADV(FGu [6>̬WEiQz_NQ!rGHKsxA8 n{H`%Ws/ϔWe" sאA?/ĸX5k+!U"J 2۳kCuee] />[!?AEpz6eojDoQPD{GVn L[%r70z#@e. Fn|\ciܕ4P>VyO`F̃BZX`%Jw\ PPA_>poQ\H`/pEf}@٫p$bwPx3Dqֽk2@,~]@)A1o@-1cר2@1>ꛑ?(ۂl+ g9RRnl-S !׭V6oDSZ\}V| r RjJ6T!w  =/`ܪ`#4[DU@>P|Di=BSZ flB&Cp~;;r;qjgrѵ@*ZsK [}Y`cݎ@Pj9bUGaYD]Hׁ{CLP^1*0ދq9~!"PEbK\;ev{"z_@w(VZw_BlN4@܀eٺAǵm}+on!0{&(tkz3fPhlӰ{(킨u<-<EwtixUF_/(jZl ogݧO[!%(q_z9 "T͠ x' Q0-&Pc5kE |G4X}1DIJ6l~'.`{iE{: _)e(i (q=٭T`8-bYvV g(-h,CP<&Њϊ_eZl9]k^c~< 3m[Bdk!j0hm Ϫ?{Q\@m/6=rQ\dL#Jm |Xєw3,X, j!a/`:| tܽdѭw(. r,އ h_vN/̶r4\0E4jyhy`zM/(:[]a(\Eihs}sL=xPq%g] ,|"Xl!~ Yo:d"4`s14@~Gg?p ՚ [Opǽ`Kp 53.<YgdK#y 7_Ki@^>-]efc"j~T/U i3*YiRBN54RjH= X3 <[zϗ 2_(E/v#r,^E >uZCj׋rA[̅ѰWoxrNl+G(zBFx Na=x \XMG >h-V/WA؞[ܢP@)vG#{@hq4H#Fķd|\mg#Mvk QoVRVdZ!xYQno1}^<@cGkoHaV~[ZLQ|m%E L'@e 3S=\BJe]B:}):>>"gq"q~n^uC}yRjo.S LݲB#&t g50= m/(un) 4%PYN70VGhr~W<)uN'4+̔~_F@,WT+b.VbE SD#kQ87pzSef ` -֕"SN˷Pn"`#/{˒*\[n⑨va!7!/b4\@3rYRB@|$m{| m?LL|}C#Ɣ^cbThC3Gy r)Hl0\`P#TSwh0)m0>fShM[[|K5rh^J rǹ)j7_.~_paVxS42Mn4`/:Y9ĸ%ǮW~lhݳ#5W= G_ PSrb9`h[ xEٸ"9iIo4`}_rhz, 8*g L=@/aьrtЌ,4\0]45|+okxkiP/Zvȴ\}>X BʼnD|tVG<@ |zQm64 ay Xgmc:3SӽCmkq:7<8{Nh=0eЈ2ڔ{8 *`R#_F8FC5pﮛ mWihmsKʩ*2.OG]`G 6~@P ʞ ؄E@04 l m6N8(q fcY0Q-na5nL}'DJ=52E^zD#z_@rGOc83Si5@L%U)}Ӣ,S/yX \>M@UzSX ݲ/|Dv`DBs_. 4| >2C@EL}>l>WPŒ/p> lUAVܟC`Sn4r< ]ٓ#'y/˻悊|(' ЗpA _"V@ x1]M-p/n[ਭVE셽Fb_(aη#f]B\l%P=b^{U/؏N$@mͩ/ ~_0+_NU2z1SP´^LJ FT3̰eR~0o up!>Nzwak鉢{E:jto`IMUa a_>Pv{4셱e݌^9ڒ5`O`cz߶iq$a1ȭ.f:Sx(>GBy#|d偱u/^ضrԊ&,6mէ|mᦒ—+bwot:/4` +~(z32EE9v@ňڲQn"ӹl,;րgBxmE vq@X4Q^#J^J/QhE żky츆gM#5'v\BC 9P'|\DQ\ߚ"Pdj˽/ Bg>9ʵ0LC)icY_>`N} ԛ)sMe|[ISA P_>_tһ+x <<<+DΈr.^S){|ɥOm3G/*+XGŒ\ܽo#?67G`Q09nPt"G?5~7+iw#-t)/;7(i"S\@|m(F "r|5˹ Ӏz_.f]TB\/pF_.`_>=a/s4AG/}iQ= g (F2SGZ`=\(˻U]tqzSԊq!+^HAhBe|cp6z_h@ >̷l`f}+_[,/Z}]H! z׺_25zWs˷61L -r8̳?CAԶ\LQQ=/8SԠ9.S-HKsxq n}lϽ M_ 0`Q{"(XH\Vj<[Bly"(6f@|{vm)ha_@]xXl#g! IO3M^DGޑ ll?i_{_._w 2ũ_yo}ny4AC]G^#?pe#PW˹@@N#ł=#Нp 9ʶ9si9Ƌ 2 nrsWu@E\w\wo@|J!T#!.@fR[[C)旽#^5܀?T#D."bG.@Um#@kx_}ݲ*$ݞۻ:E#Sp~x- ">R+J;>p=@+^+N3}%6[5h- 힃yxJw`*ؕEw5A_Ws,h.8ކf3X03r9]oˡXX]xQr(wg4TnTxZˢrUV|^$Ӎ/~шr:Sm8@QlcuZ!*ZPc N϶wE7=Z#tgۺk3=*46UcIy@ A['N2(a+_α5"ptVhp,A#Sb]s6g OsG|*@<>@ۧJPRUd*_b]vp3Kz<֢lXny&- G/q/Pj +}^ ŞUmr<2\p<‚m5h+_>/p5a_HhB__[NuT ?^33{ 您c S| m;pR&\ >RSC)4D|x]]UB=Zi&B ( 9x\!6~6gWD/>Y@ܽ`n q!!3 DYIG=BH('-W1Z5<һAtf5A׶_RTpT03n)TiZ=P%CۗBQ[^0Dz)8V q33Q0Rjo.S L*Z[G(0[ոô,L@s;NY~Ij3b/xRj[XS`@PE`Aq D.} l8\v`ؠcC> BOVg/x@5_BzܺU%0rKVu{ 6< njr:{GF!+JZ{$M8ڽ*qR41zrkNLC(LhdQQ6+[L"J)@8zܩ3 //n]y 22"vEF_`mc["^#5 1/?c5?wQhdW˔0_"{\&v&b9B{ V#11*`X3<`|X$6cY0(hUd;4Zs63æ@{#+-A4a/@9c5:b97(|huq ޔ-fϠ;AɊ旞*c4 0n]Pp1@t:@ B~`=4ж%@Tb{ЈG]`gLjr4WTݰN+Ců/8*{'`:})`TiA mNqDz`һVnLd$WJ=52E^zD#_.@rGOc83Si5@L%U)yHQ _"/P?'rE W(踭B)[H;wT;g r9/ 4b!"R|P>6(afp> lUAVܟC`Sn4y@H}7b biދE2@[ u@8Lvt4s _'`#B+Rp ^<]&T(o) X' ZQr9/u q.\]/*SXDI+T> 5"`#%[XZbg%1(.Z`]HAebi|esD9~1ԭ03l)* };(䩹uCW[Q|Za" 9Eu iXŒh ut9h^ i cF=;xhKP>3R|d~f"SX[jǑl ;@L `桊ƥf<`¶-V4ai>%k 74\a@|%LB6aaY`(>N"7.ST OeEy.4LʳM[BN -&ؓ[`_>0;01h{k&ꢢ_>Pvjv^QɃZh1t^h9;(YHIנ2PGt+:'Ɖ2pE!y}k@q4Л|E.N|5\ G H3`Z&`57X X2ؑl.H40}6WM>b_L Г#|8`8mGB(՞p\JVRTP7x@e L'ˈba[][8ɢ=f} DG*+XGŒ\ܽo#?qA<Q}9CVnPt"G?5~7+k٠FZR_.@wЈr7(i"S\@|*!4|ZNԢ#ʑ^?-l4`*䇶h#Ж `yny;rۆXRB\/}iQ/nÌrAf\Q _ ֈEI^ޭ"?۠}V(>Y,.zG"E:4{I3$$ֈm~>}GH3SNg#EӫXts$2Yﲗ Gyp!E}yZ=p )/)*2l8Rf{\7*^6@^QϨYE?p6nI%Gf q;pg2yX}17*8CgF1<(ۂ.LcӶ0{Wӭ9_z?pT)XZ{ V׋ SH|JD\]oQ`>rELRޗ3@|(r/й BAu q[}AQ&gY]DEݲP,. Y؛8L f ]$NG'8~/Њ׊S]]y&Vkh- V]W5^T+epE 偂Ws,讒8T{d"| Bmx݅׊ʡo/_.4T38@E ]ʢrW.?/G8z(rt 6BI{Vi @M+46Dٶ.Ģ~oD  v:gk3=*46] "VϫQ}_0}_.0x[<0: X/Z )- "Vt'n2+*ꃜG upd*S_P^-g ~JjOjE Ę,|U"Sq%Xs}_@}L֢lXny& ~m[>{eQE4^YpP+򈁼b\](ky m;pR&׈2w:n_0U#h +KkZ_,o/g?jy@BJm0~6gWDUR#"okZ)mHLafJݲ R"PB{KH/3Xg՚}݇W0&qq"qQEiZ2<`9\!:eGMDe.g{-·x[8LNX[}m(unC+>j#E V{?L.REK: 0T$WC(lt/& c4?]4>5JsQ ƂaVM?'=YMr+˙BAw/*G8g l/B-|}h*˹GX5b) W )uN'4+̔_FzeC)mHZl1S=i)~+zuf ` -U*'3| ,6$)^HCkM<.EF}kA b)l//Ќ<`ԡ|F{KÔ0_"^&6&e|{c11*`X/<`|X$6cY0(xDj w@1 Ƨ2C@EL{s e .aa\Hl*rQ gpA4!:nҼIŊн@,=-en;N:@G /D Hxtc[_@ۈu{8ju{a-_y2Y}/L2zalPEBu @[s*60DLlr!*$QE *3%L+ۏ#Q 0ԭ03l)* et<-sb{ 9Eu iX‹@4:\Pv{4셱e=;xhKP>3R|d~f"SX[jǑl ;@L1>GBysv2򘪤`,x]K PZфצ -T@rUtZǧ"2X&,, ǩWPfqerh'ڲQ<Ds&Xv~a{!'H _ڊ'B+7ӻyVi.8GP f;FpV0Z+6xΎk8 t ^h \{_9n )H}f>cp\ ̣fY,)QEf\Q6X߿LP, /#Gw8%m \LQ+Rg&Lx#U  ]E@ sLʙ+^-͂u [603d{Ţ %UeGh Sw0|@!iSP8 5]6h0FG3Pr2G]D9%ޠn/SPݓ ^Lj"܋nx l@UaqT)dVj<[BlfMJ2۳KOE 2Ò `x_._op4(RP=EO׆iwF"E#XRL6\/|C/|S׷@0F^7Y8g|@HQn >}|Biw{₊L G]l|AkK]]*)2U%#qxy)qK buM&|Zb$-[݃ v*8CߌCl \xc sWӭ9_sOuz@E BBn>4>Kox |$XkW2Sz<J1 t>!] z_ w1ypk+@>i-Dm=[ewdZ! {)8sLate>r/ZZQu_.0؄wv@k1mD`RB vet.pE 傂Ws,譒8T{d"| Bmx;3E=8:P 8SDⷝ*RpXm:c"spW "G/0zNi.Z!?.ȢoLAM+4;D{\n J,_&0P׋r@],XQ9,y,uJ ZBBOp'0x[<0/#Q傊Vw-G ~t)S薻+*N ~׆͠|v' PB0-&r|3?c5'"Gcy߇bq mp܆͙ϓz;b|ޞ# )-󆺀׽T\DZ9ߎ/ 7Pں_.0W>"~_.w/fw(QE4^{xE@9@u:`<`m $Hm?' 87l~~| ,}x0P+kI(& ɘGm`9\)ff](X, Z!a^6$L#X/-2n#K] X/ж5"/o[3sn)jfĒދL1G/ A_3b]`\EyԜ䎙O Sm6V`Pl[(km1Ī/}C۲=i}"<`s14]ʕk?sk𵚪u>hB__[j ?\ڀ71D"f zŗ\@tE_:m}=k@ @Ӿg4_+-Ur%a )|O,^K/Ȣz_un`Ղi"{r x!%* a*X+G(zBFx Na=x \XMG >h-V/^yʅL=2ZL!> F>P..z|}@aBdvy߈2lS!sS Aa J 6׊L+C# }]^X0Xz7N>2}e\|5"ZL'@e 3S=\B+Yt+juv} T:[Vǻjza uAHyrx-@CQJoVT::@bgaVž:;e'Z\yW5b/xRj[XSɓ\baJm]~@1EqeSD~.AFaPsLTu̴"Pwh9Ajl~_ -6@-4߭+*G8g{ź=p͢ ^F^(irj6=>7X,C(݂4/-IFF5<ef f``2B-[GZŁ| "MxKq:i#~E E+"60;L/EJa` V)^8D=b{Ћr 4 6-4̃}BJ/`~_> nsirn.N'SUdZW1[uW_.(hJ#\S1+f^鼢yEs}݉8*{'`:})`TiA m{#p؍`ZQ9-Jola5nL}'DJQ$Fw6Ћߖ>~`ibOv`g,yHQ j.fX{0K]Pp @sp<[Hj 'r964GvqGf)±χG*=J.cۧM*#؊} sam_.‚:L|K^$-wOoeP&N.8alys _ bx/ )"ro#еjlkyo#J[ਭVE셽Fb_(aη#f]B\l%P=b^{UU~P@4֜<r!*$QE *3%Lt$bDq?f-"ESAu뉥 y\Z8t%ŧ)R.c-=Qt(XXG,*/D9#ua/܀0l4\1+G[Z`) Yx_603xR=$R݁#ЀMXXV7ʷSzPԊ倯#jF#\hΕg`ݷ셜,>#-|k+Zl[/8|lG8^(a^ 1NM X#HaWtm:/px$ހ]*S7v@wBsk@k(qa G]r}k@15֋2#)  |skayܬ9˒% ""\Q6!TOgf`2@r(_I@e"]!?-PH2q,k ]1ͳ{CAԶ\LQQ=/8SԠ9%ޠn{2kE˦yjs!AEhSa˦D2hVǐJ,$~_.qX5k-!U|啀 dηg׆ҋeԅ%v1| v %"U8s_?u^AV|:L9KkuHo ee P|ve_{݀0+ ib9zGn#_/d#y!E] l_.G])W(R Ԧ ) *26 u)=_Pګh}3C-hrdpdEWۺA^Ol~9|:=L!]!]!ۼwWoPh)BJmo_BxAHs=^0n/`#<]DJAOZ~=מ|-KKł;2_`0:2O\yw\_!4\`tc-( jb.<8@!~[6^mkP7rPC.DL_-z/o-Ԟ=c"spW "G/0zNi.Z!?BlN xL!JJ/Xh8SS:V}R+Rp48} V齭N۰9Sy2]V{GLs´#EEyr~PPT/źrp#uo+EiٮLAMP+^[~_.w/fw;E"k-+}^L֭PbȺ7 <Z.ܰ_WG:y#Jc$L\ZrV!PR}pŧu`V;>CX6ϡ^6$)T z_>:E {lk@rm[#Ԍr5\0熚_.fhKky@,4^5<0G/ A_3b]`\EyԜ䎙6Gu+_kk=m(}g-'*b՗[!i}"<`s1`9reu|j]Ň-9P{A#^33@Q9@CaJ\3#tB1 5\`uc?f@v0![_.mRG^M{2@1,zQ X-)\-(R'R^ b.Bf|cmb6xB,Pl䊹0a WчH"gwwb{̦#^Zw=)i"g=tuA˵Wr!ELSH@GŹT# 5_hآ_7 %js>>Y@ܽ#.3 DYIZivheE]I^GsܾU/,,DkoHaV~[ZLQ|m%E L'@e 3S=\BJe]B:})\gp&n_)8 0y}tC[Ttoi׊ &CJÅ~R[Vh[}NԾbҽVž:;eT+)j#Ek*2^Զ'@)dcŧw|0AoPsϥϥW6v1U38-~z?iBk>G_{' <9{7=py`_cy߽#@#%PY=ƪHQ ~_.U  ib֜P2+ldQQ6v(\P=?dhd-PN4 [+D{o1dK\mFem|*8/E|F}kA b)l#/Ќ=\`ԡ|FvEBj,Zebd/SxoQ @_p1'`"s ̂iE94ZL5uC;bS`1vhcb#ŷ\#7U"3)>sSo\0<ì~MyNj`6! [{bc׫?LTK,9#ĺT4aaY`(>N"7.STCS?GԖ"G < 2+6 o 9Y|FZ*4V=Z`||lGp^U N/x%`/cD%X Gz, XR( !. <4ﳹlB|mTex0 ey9gx$Ro=x94_ H7;hŇ"xyI-9#R/[ `>bvm'h @u7p<_>P\Z>f}yA<Q}9CVnPt"G?KM+iw#-t)/;7(i"S\@|m(FڊLCS6Z{/3mPM\Ћr6 2~.za;!0S`Om؋%5*ąx3luz_{So@rÈ@f\Q g %5sm..H~ Ǹ})j[L Td):w P4CAtM1C8jKb/ z u [603d{Ţ %UeGh Sw0|@!iSP8 UȽȡ~ j[P&\਋Z)jP|miioPP7_ԍ=ർ/x(Y!r̽)`˦Dp_!G"(XH\Vj|KތA ]^ @|{vt )ha_@]xXl#ۀ! ˡh=~"ô;#0w,B&Oe!^ ] 4 Luyt|r\kfweq7?P,P>m >,|3> ka}\7Pz >jE =EqAE{.esWxߥS{EQo}*ޒ-U1oO0ӻyat*D{蛑?rmAs~ #/f~5g= >e . 1-.k-/xcM> 3EH)+ߏ"%eA=7 ؃y68@Y]DE n^Z(li,MRυw3GȽxϻhkEiZ,.0Z @|[(W5^T+Ow+RPЏ/cI.-.F @XLYA֡Cz@ZC9 P 8SDⷝ*RpRzwspW "G/0zNi.Z!?BlNNX1ۣBcsX YvAz`.x`:X傊Vw-G ~uLT+e0p%@cX(lך6NF@0ϕ_α<))צ (Ër'm؜)<.`#&9aZ"ߢw/b xX xk!䇵89a]r|q+,{ %A@e & -9j( )rS̺XQX[v|lZ < G߆D xyEѭwWZ}t ^w ڶFHX5_RfnY3FҚ_K*W/Q3C׌rAEXgW7*9xD5>cfz`nsTV: >`NI  Ed:dEy1b -%`sfu|j]Ňݺ#> jE1{;@T@\3m۹Ô2fGc"j~T/.VmCHnHr%a )|O,^K/Ȣz_uђ`Ղi"{r x!-h+dfj 9 r ޲@+><\G"a)0/xh-V/^yʅL=2ZL!> F>P..z|}@AZld_7 %js>\. m`n q!!3 DYIZivh{ubd Z һAt~aV~[ZLQ|m%E L'@e 3S=\BLJe]B:}):>C}yE *uEob5Zr<`9\!:s~ Zt g50= m/(un) ZHQ_`3/9=?a{C@8Jh10P %X]1Lsi si~}k `#1NU389Ajl~_ -6@-4߭+*G8g l#B/}h*˹GX5b)/J]9MLܚS3J0Sy Y} y"@Tϭ0dv SD#kQFNT+2 m{)'`,6sk+x;V1@Q{)0[BoCLa _.hf(H4+R*~lqgPh_~r F5<L烵 qQ/l Dp ^b]sՋj9nS/,V:1X̔t/PZ΍d"Ӏ=*n4؃5MӠ2 )5e04 l m6N8}?SX0S.Ꙓy($PC<Nr5t+KOh{m/m#짱 {Z е;SdIU bR~jxT/BV䁅wW<]Ty Pq[#ZT[B<ֽ B TAT.4@#BQ#3TZ #{لGBŒ/p> lUdΦA6r.| GKɱ4߀刵,*"!L\&pt;Jul/)Ӌ2@ЊȽ@> T(o) X' ZQry9ߎ/u q.\]/*SXDI+T> 5"`#(@y\ (~;GTDLA z12#~T u+ [&E u uCW[Q|{bSPȱ(W,VHw)Kj #@򁢥{@ 7`a/-/XHVNsٖ7;}sg LkEl# #@nu1ө7-vbZ}0-#d1UI׈Xo MD)70_[ #(OEd: Cq?|\v8lA>h υ\y _}k^3WAr8|lGp^U N/x%`/cD%9ʵ0LC)icY_>`N} ԛ)BO.^Nm%ro+)R<|G<j-[_.t_L+j `rz E OA97p1ExKQ|  3E;X\ɢf K#4{I໴3WZЂ-r=w]b}Pۿ*ˈ2#E4w>R!?-2SԊT&΂@|mD+ƾy6roLj"܋nx l@[!zۼ8$EP ƭbո)̷&yl suSz: d.F B8I.M^DGޑ ll?FZ{_.8/(S f#jAm'`9>k?7<gXC r}㑯8,|Rga\_PEG@Bh\x".eu~ⵟ1K}Ni*UghhZ~: ?P|: O`m/'L&drP%3=Z7ł}F G3#_rmAs~AfG1^/nWӭ9_z?pT)XZ{ ++xSx|GBhr)BJY1ī"%^u݀`e ". "bG.@Um#@zu-a[ewdZ! {)8-f /ZQϻs>C@yZPb~vA.[% ve=/%oXR/6]% oqt)}vF mx{'?C= A1P?7 iQ&u"] .eQګw~э2:Sm8LAC+VCT 0VhlGw"l[xE]by7"f;m *vSb69=^!OU!Ou\ *//o]0y]ˑA!>.5p6} T+e|7r SȏcHa3!z#^@0ו/Xh8SS^ "M703A5*ŜP¢p)P(ykBK*BJff](X, Z!anT zC>Csy+>L?wڶ^ jy`~_sC/LW#_K]8@e?j`_CRSCiQ5LjWۆ*Y9_ΰԈmk`>RקmV%L/ȢzVrscL{ )ؓkak ]7Ul1F^!3|cEvb[QWmL'j_l1{[8L{:P}_`(/TdJm c9L%O=J$+>݋# z☻.D׾.yOl=-FcPfO :fZp;4c d6ˍro -֕T#Qy We!?^݋>4Y P  7,iX%}PR}=5f!\a2@4((yE]Zl1S=?dhd-PNwLL#|Lr ^weWB3y/B@|$y-1S~*~{6Z_ )Ĩ\b f /8N0R``fGT`h}Sq`|<by@|6kф"3)>sSo<0 ìMLouFV gЀ dE㮗^ vώ,9#E#ŔX"d9^+17Ab qoff*KJh 32D/rAD#i@#X&hy`hj+o׻xz/hE ۭ#tvp qQ+d^Hg/ o)N'muĺfAs4"p%`n3X̔t/PZ- "gET T_4؃5MӠ2 ) 1jW5pmW-*< ؃nuw2Aw{V"t0 /m#짱 v)k vȒ@M@UzSX ݲ/|DPU8AuE y3ЋrA(}d@KB!||y_9}`$9" ė㶏P8>È "‚=Gh\y _}k^3WAK `>b6#8/*M||-:ŵ f;FpV0Z+6xΎk8 t3q8VaQs%-c6AࢋD3(gsE ؄P#f?mڂ#HadW=@ey3<B7S#x-/'"<\_tһ+x << +D΋.^S){|ɥOm3G7}}#@aF.'~lo(FT_ý%O "ʺ_軑nt\g mW5_ѹu4>e3EͱGz#~j[iU/pxl._!.^8#//`Ou.`_W:zXKT<e4=<@ :*WԂ_ `򀢤zn/V`wAmP> \LQ+R Zox#U  ڱwi1:fHGmhSseKE-L0߲)' n뻮|mgE /Wzk]X/D+䇹 IYv7F͡~ j[P&|<਋Z)jP|moNHKsx/U'\9^W[6 0`p R ob*Vg|KތA ]^ @|{vt )hazÒ `0Kf%l}} .jҽh=~"ô;#0w,B&Oe!c1z@傯\x5ʬWp T L$Ϛq;\P,3< >hCl 𻸢r.G1^/z74~5g \e }>rrb[)]FSx?Ph)BJr._:xAHp{P/`V_Fy<8DT}կ9|Aٓ? t˪t{fpVn~OL㵜w 'xH(_!4|ZPbZb9GίwLztcm}K -.awYGL}O, DoˡXX]xQr(wg4TnTxk إ,*W{;N^)/h8]h܆s?BlN^!OU!O5 *38Lg]AEP.gPϾKMMwB?m@u&WTN!?9 "Ha3h TVW|9jDrX=ypmgi @uu1'm؜)<<>V;>|F_)-%n*AIU~KX9)h2gB׻e2Y #8x;ԻZ~zxE/rh1fu+}X]E/$GX6@~mXyj}ゔP(ycׄ}!R,Pw8G ²#ۄ -zݿ|mŇj!6߱ĕV]B]@ڶf-mzgdo[97|`B4ͥ/%}+^PbB /@EXgW7*9xD5>cfnc%kYLJYx EpC0Xo(z['mL'*s9k+a{&`m~׹_g,?5Lt@Gx=hrcCD,bt^+2uE9&hcTr_;rACӌ^ 8*gk$JA8ny{ aiY,@d>X&45<xz/hE ۭ#tvp qQ+d^Hg/ o)N'muĺfAs܀F \ X0WC+Kr"SӽCmkq4<8{{PU4Phmk`@rAecR|,/=UhPLq{{8 Xqiq>Ixm4%@Tb{ЈG]`gLjr4WTݰN+CNDQ=бS6HJ– Ѧhp؍0eYRu;ڐMy!+»+اiW=*P,O}#R ,\h38/Gf)±χG*=Jj> lUAVܟC`Sn4y@H}Em'G>B]Jy/˸o7qNe2; _'ۂD#LjG"V@ x1]M-vNkS }0o"VE셽Fb`"+f]B\ 2W8n 腱Au6Q  P6@mͩ{G(, wVůw'*RPh)(aZ/F8_~Q܏jnaˤHTaP[A!Oc먁QRՖ@VXbH@Dѽ`aBZ7`/N)N!l#0S i cF=;xhKP>3R|d~f"SX[jǑl ;@L1>GBysv2򘪤k`/ F/lB9jE\6So`pSIV Gj;Pt:/4` !3xT5rW8lA>h υ\y _}k^3WAq@X4Q^#J^(Ljj;5;``n`cD 'hE żky츆gM#5'v\Bx9?J\DS8ꢐ뼾W8p܈VM'_.#}r- 0 ,C\th`۽lB|mT=3=@em!VeNJUЂ7zrrZ^Nsviq*(jPz2][ЀeEΌE]pwi-U G̮-\roP +:w8{qVݕ 3rq~2xA<Q}9CVnPt"G?5~7+k/x6@҈rFAM kC1:NZNԢ#ʑ^?-l4`*GEͺ~_>y;rۆXRB\/}iQ/nÌrAf\Q _p;vAR.H~ Ǹ})j[8ZPA덐w P4CA;.6-F $L/3|f,z"]WXts$ʲJ)Lm @LAeD[Qb8鞥D e#u"_3E  -] ~?[4 ># FVs/}J-زiW9+cHQ /qX5k-!z3Z&t9; dηgGҋV.<,pz +:tr(tHA0Hx:L9KkyuH:;xXboo 42Ea(> o;Q]Y\Mq?G`pOQ\P^K܀/x?w@^QkT[E_=mzoI|HGf qx5\P*#*7@yXkT@|f8e[:<4ƋE^b9Z#2Vk\zD9Ƨt)_W=x5^T+epE OWԋ VI[]Jw6fc2"02 `fu{֡o`!~>IP7rPCF4r/0PEP`\;t{\G 8z(r<ZKoȘb"Qк]`HK؎Dqm[Ģ~oD  v:յm=*vSb6q.VUkNe0Sb:Xmhu6RgݧOuLy<hwAJ~_x_./$c!PR}pŧu`xoGh1y`z,X2׆v"`K] X/ж5@/o[3sn)jfĒދL1G/ A_3b]`\EyԜ䎙{QJ޳^LJYx EpC0Xo(z['RSCiQ5 jW}hVZf9If( 9ԌҠVH #|z/`&l߰DVAJȢzVrY<1W ɵVⵆԮ* a=X%VP(y sCu` W챁#gwwbZQlzn"Zܽ;LIU0"l@suOc_ \-ze Bj}82/(}* ]hBFVL|#[Ma>6SE ph1@ԛl} C/+Mj=RĘuvKC;p<"okZ)mHLafJݲ RCP %o.!ھb]Wk"W⼫G\&q~QEiZr<`9\!:eGMDe.g{-·x[8L{q }uvC=O /HTG *2^Զ|APҽw|0AoPsϥϥWm:efؠcC> BO{q_~_.(ظЄyd9s>o8{{ wBt#T݋>4Y P #`{1|VI+Tڛqͭ903 3_EGِWT+b.VbE SD#kQ87pzSefWAeL9/B2 +U oqT^;րS؂X X)<ʷwU@|$m{| m?LL|}C#Ɣ^cbThC3Gy r)Hl0\`P#TSwh0)m0>f6X9lml-m&(yLy;枸 `n?b]`?=#807:A#s ل3h_lu"sqK]Z@gG }ᑊʑbYP,  byat:7P1'=/QM3v3SOG% zQ8 2 ~@4a93 " @t89>ehw!a,y@+R`n}>) `Z! D"L>{^xKq:i#~E >W60M@U 7,gy@ "@NP`DBs_. 4| >2C@EL}>l>WPŒ/p> lUALGGqG}(aD؆B+wЄ<G."LᨋB_ 9ʵ0LY :w8o)*+XGŒ\ܽo#?67G#/g V视^se/ nE.t/36mTd+ :WdZNԢ#ʑ^?-l4`*^ 8̷l`f[H⪠Wox 0)Lm @La(gB "c<鞥D e/yř׆64w7>RE j{2ky_U cE/{[e" sVǐ܎*EP ƭbx ̷hpl s=;^>i@]xXlaI̷Ϯ.jvX}֑{HQu;rT!'׈2_t/@n^he P|v>- 3(~\x6eV^2g|@HQn >}|BՍ{₊L G]l|AkK]]*ohS:GkO.)q{drA& >-U1o@`ר2=p 9ʶ9uyi9ߞ)^b9Z#2Vk\w\wo@|J}C|~h)BJr_:|{P/`n?%8@Y%Ƞm~=מ|-KKł;2_M3GH(>C@iZPbڬ~k1mDGz7]Yt] \~Kz-.aYLL}|<|uh-PVP|(x9rQ4TznTxykإ,*W{;݋rw'^E^a~P (j{`EE@^w56؎Dqm[Ģ~oD  v:յm=*vSb6q.Vz_>;y`0;L -ǽaVPgPOiQnO[nq~&WTN!?9 "Ha3h T%s%@ŗs{M))צ}v |T;/p܆͙ϓ^{|pȷ2TJ>U"Sq%Xs_.bL躷 ֢lXny&- G/p~;ԽZ~ "A9@i3غ\"#,؞okqsºsC j,Q|B//\ZrV!PR}pŧu`V;>-v<οM(LQGz_>:E {lJ˾;bBc>\@ֈ=߶f P3SՌMsi/%ҫfF!k"Sϑ]`\EyԜ䎙{QJZZOJYx EpC0Xo(z['6SE ,<{h1@ԛl} C/+Mj=RĘuz_`` :V?0w j-(V{ })u.HqM\@5P+ʺth2S(jkad EHAyWlLob5Zr<`9\!:eGMDe.g{-·x[8L{'q }]ίSyR_@ vyC8\P)G(50<-J$+># z{.D~.} l8\v`ؠcԊ6ujl~_ -6@-4#{oyfKPc[~1yKZGmFhQ @_p1'`"s ̂AA;"SMݡ(yL6X a {)E0fS|'ހ_` _yY2;nxlB4`/:Y9ĸ%ǮW~lhݳ#}HE{uH1ea,(Y輰Wd:(֞Mv(N;\QI?/pd@heT0h`: h _.._>ef sa{~ja9{|B:;p/N$@@ l`?"^T  ;L/`XGc:3SӽCmkq4<8{{PU4Оp2hm=yUH/#`mq{{8 Xw8V$p6yrLӀ=Q~bx_4|o1j7yE3lAGeOlB"O * 8[DM}oĸNqT+*zd o8mPf$WJQeѹiy@/~[nVhZźTS(G*=J.cۧM*#H|9n38 \c3G3R|d~f"SX[jǑl ;@L1>GBysv2򘪤ky`,x]K PZфצ -T@rUtZǧ"2 ؄eu|8 >.LQQ*?GԖ"G < 2+6 o 9Y|FZ*4V=Z`|_. =΋Ju<rS f;FpV0Z+6xΎk8 tƿ$&ݻ\6'RPj;L{8RTp;Go0,G=-k<7X>p#(㲗 GyBk9 \wS.PF .5>PWlUx>Mt\t>.)qqg_>xi9P%3}x-ł # !@4w2pdEC:A^Ol~9|S>L!]!]!ۼҥ|mtK|H1&? 3EHy_C)yN/nՌ "qgvdP_sQaO>@%bvVa /5]x/0S_.#w>C@ _0f[oE  ve4pE z9K[]jf2>0#C/6^sakP7rPC/xy]LCo;TxkKYTevw'^Efh:}u 5buZ!*3Pc M;D{ VK,9F@њaS X1ۣBcS>nJf9STT3KQE8Ly.`G*Zφ~uLT+gq#0#\ P9P$0s6g OO} {{@6pȷ2TJ>U"Sq%XsEhC jVp^[Ҳ]cۛV(= /`vS$~"A9@i36C9.V8a@Ha-NNXpnh1>?xڸ`?mB3(?f&䨭B(To(O96c?`ŊY? Y- >v 0|Wi:nZd ZG qLoh _m _b-9` /LWZ /L1G1/9"Sϑ]`\EyԜ䎙{QJZ_/@9}!V}3uɊ ;cZJ okOZQt>bZutG~} o㧰r^8qy@kf| */ķmSbq:a(9~T1h +m `Cė3/߶VH #5}z`&l=_tG(ڍ͠\-(R'Rfb.Bf[%+ۊr ޲@+><\G"aScl/xh-VnLIrE4(~PT.drM )b ]h4:8xdwq@4м櫁G /ć/o6OF`pDެ`sȴBH;X1݀׵jwt[#¬&K Of-{ *2@P(ҡL:>C}yE *uEoǼzW9C_>)7XzH`n9ݢ?y-6j|ô,Lj=׹_g,?j#E _> f"w_0PJi"p\baJӼ|0AoPsӥӥc}_4(9u`,6iEФ (d6ˌb}bA-4+*G8g lrGt~7BVBe9H^#Eq4x9VI+T>)uN'4+̔_>,>ʆ)avD ?EL?8R-@s,k7-`h2|ǜp/wc50 >L5uC;bS`1vhcb~@9jER`<<LQsOrgfouFV gЀ dE㮗^ vώ,9#4c703ŮWJ@yȴ 4\1*Ob Ц 3|W3"B:;p/N$@@ l`?"^T qv_>JasSL)OR H {8 ؃jD#{жV)pT>V!_c4 0n]Pp19 :ۭyLLSUd]A3+#1|4p[LŨ,yxEN}̡u'"쉞MX)QaKhSWǍpc7a:jE`vQϔC! j p]H({ܴ< a~[nilmĞVt>YRu1<Ռry`x~բzކ+tVHg1U薪-uoPU8AuE _ / BQ#3TZ #{لGB \4ǶO,$sU GO.1E|9n38 \c3GA!Ocfu  zW~r^QZ!- ^ < _-^3 {ي C\F%k Fx)>2m3Z)-5Hc6[]tj F s#!%k 74\a@|%LB6aaY`(>N"7.STCS?GԖ"G < 2+6 o 9Y|FZ*4V=Z`_ =΋Ju<r_0070[1 "b^ѵsv\Q㑚xvmc;Ae mhD'댒+Yq 6"?Z/@'o(@!UmrԥBoM!/7"/8R# `Z&`>gYPDC. <|͕J&j}1i 3\_,3Ks[HL!(dro+i|[IS Pf8`][`_!r倊R3|V|]W,+:w8/ }̊>@6c Q.GwtQɔ)?+RpԌ}7"@543B?*2n Ũ4>e3Ѣ#]\}q Vi)G/pxl.rgd9_`Om؋%5z=q3cf @7@/Lælf*JjpȌA nr1n_o`1VEgVƙ\\"&t(he%erJV\Yh,X_`e3SNg+_+Gn+ @.V!?-evcFl7FG3P۲Br.E_3E ׆io.q \̃Ӽ/xT6r1ۧ$ނ-Am.=I/ĸX5Ha%&O6x%`{׆ҋVua] K06 AG+:q_:QѦ{D Jmi}@Ho,iL6,uHo ѻ*St]8fO~Xk}]Y\M#0|g| )t-u\ SHQh /(.Pdzm8"=^~]{EQo}@?#qxr/>C@iZbķEU1@Ër'm؜)<.`#&9´#Eyr~PP/^.ŜoG h_н`VҲ]cۛ@+^+ G/p~;읢"ӵ_y@VqwLs BuvA#]aQ{8  (<@\5(R}*aŧuqEbb <߷!`_u@n!6ﱽWZnm>^ X݀/o97h`>/i.Ռ@b)FЌ_.PduP> М䎙{͡nJ׺{q.9` 1o(z @쓉 ;c* v0+Et:{nmjnݑ_> "Ƚy *_.o=ɚ_(>rO=P0!B3f__k@⻸BnBv@&5/Pr*Ќ@+= X3 <[]K/ydEn$`]jUӂiAE >uZCj@bY {L]K Dvb[Q+P-Y17QR}$Rxv~(*l:\EPkr0%/P/.\{TT.d[)bR[h4:AqUȽhwjq4T-6r_7 P|K)js>eYȞK븐Dެ`Vdҿ_|KE]\1݀Zz_`` :](o5b )0f-{ E)2 5V(y{u e- \ܾC+RPq.n_l/|z>=-VU\/p/@JB?R[~F*0[xô,L=n{׹SQ_`"wy_.0sz~t@8` APګYw|0Ao |AtX@F+ 6AF?56t̴EФsГ9pt\9/-6֕ JJ`帗| ֕+ۈ2@!?F݋>4Y PRr0VG q4VI+T: Г[s `fB 3_r!Д,Xuz Cfo0E4r-[_"0 ro] 22"vEF~_`m+U oqT^;La!7!Va _.hf}t>@hd+*K.Z|;XE_8 ^cbThC3(/8N0R``fGJiMݡSq`|<<:;lhcG`kco\#o@m{)E0fS|o\0_paV_f) [X &Av~AɊP"쉞MX)QaKhS+F 8@0NaLkE`vـJ\! *>$WJ=52E^zD#<冏6qgj'ؙ"KZ%Qu}[Wsi۟X=qX"ipb4t/#(=-ed/Dwys Zzpfزi%=;xhKP>3 L"SX[4Hc6[]tj FPL `[FcֈXZK PhBi>%kJnP|D݁TDyPXV7ʷSoCћe)) ۟#j"G*sy@d:Wme/5`/di ^h1z"n\0;01h{k& >>x^ 1;luLjjV0Z+6xΎk8 t<97`6(So2^%Ѧ.G]*rG9/8R# `Z&`>gYPDC. <|͕J&j}1i /#;6`84߷JBPV|-/'"<|G<fEk }KT(`h;(dOR)" #}7"@tz_>g 6mTd+_Q[#^ih9}f>EͱG~)- ӀSȏz_.f]T_!.F 8#//x۰KjRAG/+#ڷh n{ay 3uTNԂG傊6\c nr1n_o`1VEg="^H hBV^.m"2+g,z u [603d{b}Pۿ*ˈ2#E4[!?-PH2q,n `>oX "e2G]v/ tC8S@|mT{2¶O"5=ർ/xͳ@cEom< "ړ`!rAۊUop0b w`{׆ҋeԅ%v1| vlp[Ԥݟf6'RPj;L{3)P#`I+d(P!^ @>6>{-Aeuu-oKrQv0{ ' G' ,$0AB ܛ6[(D["HQh6NЧ(&Pd6 u xk[wiX@:LMD}8 O >r qK M&կ6LRb{`*2 SmT Q-h2LccT Wӭ9_xOU',YMr SG)Foi>8k튠!˷䇪_7&GЉq  "brUAO*T_s j ۻX#}MK`0:l ] U/F>rWkvA.[%3]Yt.+6AcW;_lj @goqtz'0ؘ+S@)@+~۳"0(~>IP7rP Ÿz%3 _-@إ >v/ N {":_a8.B(U_$ @ViGQjvt'hm 64)0{&G,kE@=[)vSb6NiD+i)i//_̣s `;V߆[~ wgݧO[!%(7r`X P w,]*lUa3 qP'`# @(a+/Xh8SS:V}R+Rp48} ViV0'm؜)̈} {{0mHo)e7}%"KXsL@+Lh>)hsse-~e/>L`v^Dm-+}^9@i3غ~\d B`87[hO#]aQ{8 炔 (|P~/pMR}*˱noGÎސ86$L_^/(>TifJ.!v ȱx2m[6Tۿm0snh0t ;ȣt-sbEe? n!b"SP> М紻i=8Pq%kӆB!Ace{b9`s<‹)LsϢY9t:;@[#kk՚ [`/<hE1{b\](uL߶{VtK+ZݰL(teQ_@t,G9_ΰm? .6~è"n8"S Rw$G]}F֥VU9-T`OSW59 2 2 cK@;(P(h>HnT d)fg׹; B+!Φ_ u#9_k<ʅLq&Lڢ@G sG:| MBP|K)js>es@ܽ`n 븐Dެ`룞!ڸ(nk-/,,D)o5b )0f-{ E)2 5V(y{u e-Z+n_)8- mKi8X7@~_`eHyrXC*3utKGMW6[DgpeL1,s;_g,?񤞀eEK: 0Th10J{6q.#[628KѵZ+n!L{[cPfO *3mp;4c jl~vP~o 0b5_h u<<✽^?8B}_ y@w/{#d%@I*˹GX5b)eZ%ϩfHs=5f!0SF.>ʆ@w@fJk2ύ)11*`XTOb+#94_# Ƙk` | 1 Ƨф"3)>sSgO @' 32;MyNj`6!  NVa1zc׫?vhݳ#}=h9RLY1r Ql1:/lNgyIkOzKld7S"A)vpTϠns 2D_An @/`P7EnLeqn0 gZX0ߢUz℣o<ā|&wENx^T qv/V +:1X̔TK-@jKCȃ=AR4GB}_Цĩ}L!/_/8F`mq{{8 XsjqU$p6yr{?0 L/b8_)}_-bW#6A~R~[nilyf=}) PbUQbni/<\ xj`]Pp sp<[Hj` 'pDBsL2@(}d@KB8H_@ i ԥ9 ėOp|6g@(BXŃpz4E"x9LxKQAe2LDw0|͖l :U{̢ bZz!Gko#J-u{8j]_&hbyKu(Spv P@/ ~{ $( 0 ⵜJbh;Y*E *3%L+ۏ#Q 0ݷ2LϮ# b{G ݊#R<]8t%ŧ+,ST@Dѽ`a=Wlt(Goq9@_ 䰎~_-^3 {al4Vr%kj0 v#603ՊLa l)S`8e}B7S =YJVRT7ov%LwWx`+DeR/|V|]priE{ :w8/(7Mk\f'>8 Q}9CVn J:"G?5~7+7H]Z; e57ڴQ)pkP|m(F "r|D{^#`ѵ~97^\p9b EN 8̃(а~kE;)WT(4FL G]dt>@ڡ|E)b`èr[E>m:nI~꨿<2/0S< {03}5vXaT= ãe[e8|ir7ltk&<)XZ; r 1-Vk^qH0 9qLRjޗP˼@>A[$O֓.Ao#qg# GP}MDm<6($ݞۻ:"_~Z VtxwmP+^;<3/ FTl±Z۠{"x j( `Wݡ `E z9@Pj%bU-.UcfAe c}2e`F>!~۹Һ̣'?C= A1Pw\0SQ&kE_H2b`rQګw~f{"]Y05> (~N:-(*~Pcۀu)CзfDIVGk|n($S aJYv@tJE_0Eo1s_P)*gߥVMwB?ݲgq#0#\>Iy͠*lm#;Ye _α5"pড়.VD\%fp:P}a96lLAaZ"RSuqEbb 3|oC"/_ۇFߑKt X#m _NYۊ_s)/ jK/(t\e?/^r"S y^<ݍL݃muWv:`P[(ζb?v['<'A#&Xrru8v_;5;k0{=@+򈁼@T1)۶s)eٛf|doB1  m=<>u(\jW}hj([ũ@ _zF )|Dkq@c*t@#.uVreY|cN )ؓVⵆ֌r0ԎrLt h' 3oԍJ,챁#g׼;ZQq6Ej-VnLIrE4=(5ݢ/Lڢ@G sG|5gр\!`[Ma>VC)Hpq~)BB-fzm[B!ڸ\QnHcZ_.`` :V?HaV~ SmHP03n)ơ %o.!ھ:[Wk EHAyWlLo }DiZ]&@"`eHyrXC*3utKGMd.g{-·Lmc3kǰMzPETQQDb/xRj[XSɫ=Ymd`P*+}& 17]=]?>f-<0ǜEn7 *3mp;4c jl~eKpW-4a߷GTR3,8g lrA!?Eyo(Be9#ƪa% *pܚS3JV)=| ((Mi;E .VbE SD#עqny4 n)avD?L6Z|yc11*`X<`|X$6cY0(hRdZSwh0s63f[Cn;"N'muuU/XG^A_.`n3X̔t/P[-@jKCȃYlI@> 6Nec )// AR(Ӏw[9Nk-*WRd]A3Njt 4%i`[LH55T`ۓ)ʱv PбS6H0aKhS+F8Q̴VTfꙒyTH~ál5nZ( p  <=nߖ>~`ibOv`g,iGUԥq 5\Py`Gi%m J87g>e_nK\Y;0 m 8!KP 3EpaJ_> :}u)lN7 ėOp|a`rMG(.,f,z" 2%$@(G5PwO+ }[@wup!>]a݅r'3,* @(4-^3 {algmjqQާl0d1~oT+25E=$/P(ퟑГ Z^Nm%E L*xC_h-fUI-0|կ9r@E]pwv+G̮]8ɢ=f} Dg>M8~c@xbD X9;(<+RpԌFZRݡo( Ц폊Lq[kC1:Nӧl#G>#]r/nH)G/pxl.rgd9_`O:B\:_>VXW-1F3h n_t@dʉZ04 ֌r@EI^-`wAmP> ,Њ8ZPA덐^H hBV^?;>-F m,k^-h}g L9YE뻮|Xts$ʂ/8RDVX])"`!(Vb췎1@m e33LQ!r,S-6oALݲŧy_U"܋v_ʷ`˦Dp_!UD XH<bx ̷"J2۳KO K6_OPG+:EMw*tHA0HP\x5dV]5^PHgaW(]\ꁊҋr;EEG]dpOE)^QgT]E]mnI Gf⸭w]>r J IZ#bQ#;#(ۂ.VTrd㥞yE?ݚ r LRjܗsA|e\s>؃4\q xw1>ypk" }RDm=n^Z lB&Sp~p}Lat>.Zڢ4|{@&|ķE`RU)aS,C3%oXR/6X%]oqtzv)/!~[6.6r/q(;.in(RpR.*W{;݈N^EN/pJuBZ!ZEEEtfjlBc֝=mU,9F@њa۳8M>fPhlMy,sJ@BBֈr@Q_>a:`.x`^D_(ZZ R+ΦO֊nYow#g \>Iy͠*lm#;Ye*6_α5"p.VDhp,A>2`uc?J]UB=m `o/g?/(|[RGrE?c{G]}F֥VU9-T`OSW5F}"w1%VÊG(zˢFV }yG"_ )ޱ 0/"XwwfP/CW[\QnT@UHmG#ŹT#ヒDkgр\!`g 0/ߒm OFMvkXb]F"SvhrE]I)bq;`nn|0wZ)׶_RTp(SR4Z=P%CۗXgpVܾC+RPq.n_7y 4orM6@/DʐR{OTf mxI\Zon' 0L{m:uvCV<"j3`V.#0/0ݽAUVCT q|0Ao 9#cF]CxObx u 4Ac-u&}\M2⿸آor( s[yd99+֕+ی@!?f ݋>4Y PRr0VG q4xW\)uN'4fJ/D#zeC)mHZl1S=?dhZ? ^5i\koپo"SN˷Pn"`#/{˒*\[n⑨v[BoC<|4c/0KP@H(>)avD?LL|}C3Ɣ^cbThC3(/8N0R``fGJiMݡSq`|<Ar[*P^J rǹ)4/~/80/ ޔ-fϠ; dE֣?L7bG{P?)ǶHNPб؀B%@mw#8@0Nawsr0Tϔ̣BeT|'IQ$F~wnP#~[nilyf=}) 0mui,zy#5Esl4R؜nqQGGqۧP8>È E0U_&A X=qX"ip{j>xKQAe2; _:AE1 ^rF[DDp/hb_.0.!.^L@06"J@4֜DFQ.rY}g ~;GJDLA z12#~T uLӳXAo}4`VwՖ@NQ 9Euҽ%5U@rh^ i c˦!{vі7;}sgdmjEhǑl :`z?Sn`[Fcm[lBX%[Y F/lB9vm"D)70_+TҠUt#v%+#ЀM(, ǩrԔOec# < 2+6vrOxq@X4Q^#J^X f@Nb^ѵsv\9t<97`6(So 9PW @i u4Cӽ__6Ј#E9R@jg> 1X fY,)QD3(gs ZG~<=20 e_ߧJB0ׄFZ^Nm%E L*xC_ZtGL'r_!rfTw_k|څK{,ڣm&׽LHT9@Ƕiv\2 87m&(QhmO p+pSwHR#}7"@t_3B?*2n Ũ4>e3>!q9yh-PTN!?j6 q1|3v=a/4@?-t4\VX֋PknÌrAfꨜ/k@EI\E O;rVEgVƙ\\"&t(he%bbt̐ƒF z u [603d{b3R@NO尰_.25(m2ShE *gBP|l7FG3P۲BG]y"(g  -] u@ؓ ^H`#Ws/}J-زiW9+cHQE#bV5[]ba dηgGLPd.fQp[Ԥ{ M^D #azX ll?Y3|Cҍ/o*St]8fO~Xk}]Y\M#0|g| )t-u\ SHQh /(.Pdzm8"=^~]{EU.V|@D[8(|sLQu<|@uM&|ZLI8n_Ă]GQߌ HAVwE,G1^1^ sWӭ9_nKf>NT`j킐Vu+xSZx/cM>PfRワCU/xAHD2>O{V}Aqb ,.WE"@[^{n^Z lB&Sp~sLate>r/wjkӈrѵ@&BwaQ^#PzS,C] HAA?\ (y{5ǒz*xݰ"YGPp9fdA֡ˡ-xmC9 z (73 _-zE {]Ej]v `{_..\{"z_@R+R/vZ!ZEEEֽjl.e֌(WT*ݜ{# R`hMYE׊&l3b{(4Rc)hs̕_ 8rt{_NZ|WA߽,L֭P-OEE/$GX6@~'`?' 87[~86M~.HB//\d#Jm rX)ff],D3e7$f9^6$L#X/-2n#6k@rm[#l0m!6sC[n0EF5ͥh6e?6-!j\lP> М紻{͡nJ޳^LP_sJj0UmٞXpbi29@~kk՚ z}^ {ǽ@+ܛ߁rL{o>)efq:aЌr׍(/U i3Zf9rC3oRjZglxoXE/ydEn$`]sZ05Hܧ8^kHm/}"{1%VÊG(zˢFV }y|xKaX)0/x17G(rFCW_**2z)bR[h4:AqUȽhw B/`_(%c9hdMah1@ԛl֊LBڡܾҋ2 KG z[MB|m%E L'2)u.HQLC Je]B:})*juWk>""b5Z}3Z#Q2<`9,!:B#&tR2[ۉF|˯}kQ&ľ|Pϓj#ϝ./fwxNp *+Z! *RXջ>e#Sc4_]4?>5JqYv`ؠ1C> BO&wy_Zl\-4߭+#!_b mG#Eyo(Be9H^#8\@*@Jɭ903 d/EGِGhJۡ(Rp>@"J)kQ87pzSef[+D{ovEF~_`m+U oqT^;La!7!Va _.hfT#VTHmeb`h _7 r F5A$8N0R``fGJiMݡA@L1m)0G;lhcG`kco\#o@m{)E0fS|/y_y՗qۨD 42M?`kyC^>C踵vώ,z@{urc!Abt^E9&hcTr_;@)vpTϠf8{{^P9 R3ifY$ sAH~[f:sZt?P+R`jAl8y8 䎷I[~!A.E@7`ы򀕀 }tL>֪33 a jK,Gݻn.NW'+)2.OG]`-/y҈+b*F}ẹ5)*Z 쉞MSZQ- ئVm{#p؍`r0Tϔ̣BeT|{p|$FT/= ݶ OT9;N{Z е;SdIK<.Ŏz_("t>2t˾)B ,.\E p_>b!"R|}>l>WPŒ/p> *#Al>Psam_.A\8A0E@,<e:7`:չ-*4Z"EHxtc[5<%Q=Qu)^y#b_0.!.^L@06"J@4֜DF~QY}g ~;GJDLA z12#~T ^[pH=-/|Đڭ8"E:jY݅CW[Q|";Eջ +XKO+ QWHKzTF {@ 7`a/-_.A߳CWd@ FxY|d~fZ)-q$a1h]P;bZݿ+n9g'#Jeo alg%m Њ&\6So`VA G(OEd: eu|8?|\vBQ*?GԖET4Bt<ךrZ,G@'B+/ӻyVi.8G0gQm&`/Q jE zcgM#xvmc;2EC %qE)u뼾_.G{_l=+#E9R@jg> 1\ Cs,Kw~B\lB9@0Ux Fv!,/0 PBO/'kk͝o+)R`*P3v%LwWxxyկ9#uݥ_k|څK{,ڣm&׹{HTm}epSoL ⑊՗3`p+pSwHR/K=\f.!`w`[B M)(ZNFkqrn0$r=9r Q/۬+ňrgvobI;^ qWtU{~P1z -p/P:/dʉZ`=\PQRs=wK]tqz)-<Tz#d@wpq;R"<*СtM1C8jKz_h@ >̷l`fɢ,@_ukŢ %UeGh S @ݶ+3V2q,JV}lxP?s-+ /8RTA8S@|miy< u@ؓ ^H`#Ws/}J-زiW9+cHQE/1n+Vg|Kތ. -l s=;}L`d.F*\op[Ԥ{ M^D #azX ll?Y#|Cҽ/|o tAe.'o{1(?yoX>p#x,|?PH+ׂ \wS.HQh / )l|CSo8Լ倷hqKu7SGm(|8nkxhc㑧|}3Ă GQoFn0 )(jlq4K9Kd6~5gM,\r no@|J8x |$E(3EHy_CU/^S`"y 60( zSy/<8D>Fkz j9-KĂ;2Ua /g&rъ] jk`tc-P jmb9/Gz7]YttX_cI@sxKذYGPXLYA֡ˡk.>PrD9(Əeb\n|0P5ݢ/PxkK\;t3N^E^La+ )SPސ1 8[EEEָjl.e֌(WT*ݜ `Q5la >fPhlMy,pJ; Z]!OK!OkiPTzSi`.x`: XE[ˑB|]jt)/7r}0|JUȏꃜG fA> xP(JJ@^-g ~buAi]b1f8ynLgFV{GLsimG|K)@<S%(i)2-_%\9"![.f բys0W>"Ǟ_y/fwиZr"P 4jPsϢB"0!ŷd|6S"sSXDž Z0f%۶4!BH;qQ1݀Z_.`` :V?ȴn%_]P-V߀ ʺ̔e&X+iHO讨-#\U/"]5>iշ` bHRH)| Vڛ,~Z=0SGTh[}NJr"|Wô,LnVb_vNY~I}@f\y.3fwN0ݽAUVCT yȖL!|@t1kD,汇8<3{Ac-u&}\M2lI&"pW-4+#!+\P#:{GF!+JPYjg_.`I*y ܧ Г[s `fB 3gD#zeC)mHŪs(AFE N i^yq)'[|]fg XG -7HT\v# 1*lr-Fr؈rYRB*@hd+` ?L6Z|yc11*`XTOb+#94_# Ƙk` |n`h})m0>fShbyX9lml-kdMm/@9c{ g@3y՗qouFV gЀ_lu"sq׫ZgZ@gG \YTi=h9RLY1r Ql1:/lZQ k;| Qӌ^ 8*gPyȴ 4\b@1K,_./ L(9@ CfN)0nJ6@ZpM٠8 䎷I[p/b]j[C*LV +Q9L)OR 38Y]"t@@> 6Nec )// aC1 j4`9$0@tZo8 F6\I)vy/8^/xd:mP+b*Fj7ZcP}̡u'EQ=бS6HҐmjEZѦ7b 8q fyPAŇ7|}aQ$Fw;Pm#짱 v)k vȒִ;lPbUQbǭ6d@֌rA!qw6ߥOӮ(i{8`UP¹ 8Y-G5Tr9"A(}d@KB8H_@ /j> *#H|9nT ghs_hK ҼIeSs-: L\&sSۂ"3˞v'THQ+Rp ^<]&x1P6" X' .^+odZ얈1sEu q5T:{SZA~w hkN"`#(r!pEUT&0+W1Cf-"E jV*il5¡-(>]a݅r'3,* @(4-^3 {algmZ>e! }fZ)-q$a1hn0T(Yy *d[VyV PhBi>%kJnP|D݁TDyPXV7ʷSoCћe)倯BqDmXHEy.4LʳM}{!'H r] l1z"n9`U01h{ ،bI15`/,Ljj;5;luLj*Vqʵ0L<472ؑln!<|͕J&j}1f SxDRyX9gx$Rozx94_ H@o(3Ku *S`:f"_ .5\n7ٵ '>YGLs㑨@Ƕiv\2 8:!?67G*FT_ýήO "J/nE.U}Fݡo( Ц폊Lq[kC1:N;Z0BOOͱGHAA_?ɑSȏ_f]T_!.Ȉr;?4u.`_/(t4|^ޯZcf @7@/L`i倊빽["?۠}XLoq!+ ޑAQф$v|ZQX׌=,~}2Ff,z"]WV, |WPeA )L~+, utۮZY_+A[1ͳY*AQԶP&<KQ=_LQ!r,S-6oAL >Ҋ`d 5B{^l41$ gbV5[]bZ^ @|{vt )haE Pl4U$hE編I.@E)(Gޑ2~!f@>']=P傯< >r>rj9_܀/0x+iC]G^#@fe/\z z_>pUHQh /SPdlpEf{ 7(^ ].R=I} M-|pp~LQ<k2Xz&\-RbwϚq;\ U(>h3O1zx)xwL[s6U.LB[!׭mOiU6:ru;0 9A)BJr.U1 tp{F 0nD."bG.@-Dm=n7r{WG==2?k9gw 'Ȟ_.>ܻ~-N3}*6[5h- 힃yxJw`*ؕEwOk{1%oXR/6X%]oqtzv)ɔEmڸڸꂊ?C= A18Ÿ`kE?H2bK\;t#8zE95\S)ԥm8@QlcuZQTj >@VhlGw"xOU,9Ẉ0kigۺk3b{(4RcIy͠*lm#;Ye(c5kELO9\<6K4pa'm؜)̈} {{0mHo)e7(qT JZLoźZfHEѮLAM~_/pp;߆D xŇj!6߱+>Lm/m{gdo+/Or@MsbIŊ(S!`z!bn0Ts"<49nlfZm:.:K׾^6 ` -@6^L1M&`9rruwnj՚#ׯ-WuT ?"{< rL,@|v!0L\P|doB1 B}؏<jW}hj([! V+ glxzϗ 2}_Ȣr]uyn`̩AE d5FHl1 a;pNl+a#JgY17YcG ίqwZQq6݀oy>ԍ7G(rfޡ_**2Y-h -4pd8N 4:E6r_.7>) o07u\H QoVRQOm\ 7{1k-/`nn|0wZ)׶_RTp(SR4Z=P%CۗXg^jz)8M+}tCոHRH(XRjoi LRmo`:)^-^޳0k[ľ *].V+50"`8|@)G(50*+ZոBlj\vٲ)17\?]{4_>5JqYv`ؠ1C> BO&w_65_h =n]@I <✽^?8B/c߽#@#%U, i>+ GCZ%=PR&&@On)i%+̔_.F.>ʆ[[|Y}SjK)!P08w0x~_G[L1חgp/ ޔ-fϠ; dEW9vc׊=;RʢzOEȑbY Ybyat:7cNZ{қ;4 q]kuA)vpTϠqȴ 4<BLBL(t,9˄Bsa{~4<0ߢUz℣b@>[Cn;"N'muuU/;F ,Vuc V)^{&4'^+@a(H/AhS4P>Rc`~8F`mq{{8 Xq|>Ixm4%@JLӀ=h.0g*DNtJ+/XXiojAONg87`s}IpTDO&t, RhqD4$`ZѦViKN8}?SX0A.3%CsNr5tĈ'A4۶Z,.?Xnilyf=}) PbUQbǭ6d@ֈ@!W䁅w+اiW=*(,O}#RX \Qgp_EPh)>ST>6(ajͱ@K9"Vչ?iP;hBt܀#'y/˸8t'2qr ;Nun *2m3S80 \g7SbSL^UNEEo]P Oec# < 2+6vrZ,G@+ؓ[`_>0;01h{k&R)\L^&`/,Ljj;5;luLj*T#KT=20( 8$s߀PoPV|-/'"6ūTtһ+x </ș_>PQ]ڠXtGwؖ#f.\dm3G#>M87m&HňrwtQy8W\eiKՈrC/}M זZ/ӧl#Z{ @-P۞ X9-8r(_I@ey"¢PGL)L ADV)FgGQ۲BG]y"(g  -] ~hlAi|Ucw@xKIHȱ֮LRjܗsA|e\s؃4\q Є<8U@>PϞBl/ T! {)8h>`0:">.ZڢkK/Tl߯*Gz7]Yt.+)(gJ^ͱ{7Aѥv#L}O, Do5VTڛ4@b\cqqKf*~@e.`rQګw~F\Gp(rjSKJ޾ :-(*3Pcۀu)CDIVGk|n(V4ac\hS-JS*(*38Lg]|@rg}Zp6} Vtz[.\;+*W!?rDa3 A['N@(a+/Xh8SS"M3A8.`w_>s6g>3"z;b|ޞ#(Lk8R[J* J>U"ū?_źZf/VҲ]cۛ`/) oy ׏'E/g-WA#D6o3b  -y< P&`?|B##& ɘG )>S ̺`xoGh>p;߆D xq"S;RWZG2D93hۚ_ zgdo+/Or@MsbIŊ(S!`z!zlur}#A9iwc3w6+_z}OYiP`NI ۠{Xpb{`9rt:{;_[S`ִHߺj ?"{< rL,@|v!0L\P|䝎a Cf_7/\]Z,G9_nϞSŽ )|Dç,%L%Hޑ`YtQ XZU0`kP=O]p֐_>0M"L]K Dvb[Q+P-Y17QR}$Rxv~.(x*.lzn"voPcCW\{TT.d[)bR[h4:AqUȻ@㚯jY4`#WL|3ŷd ۈw7:.$b}&)ج*C+F6csZK#,,D)o5b )0f-{ E)2 5V(y{u e- \ܾC+RPq.n_l/|>=<bv| "p R(_.#[628Kk 6r_i 9:n0 T[6T&sГ ]F <|@hyZhB[W>PR3,8g l3fShbyX9u@9 {)E0fS|/~K38՗qouFV gЀ_lu"sq׫^ kE)XZseQ؃y`O1@,  ^t6nPǜ7whgA)vpTϠqȴ 4<BXtl?<6;0#![xZV d G#<ā|&wj`8yA.E@7`шr }tL>֪33#ʞ,unZ`0T-7|4<3ŞVt>YR(1 _("t,V ݲڲ`6B ,.\h38/Gf)*ce S#hmB]\TiAm >ՇڜAF q7b biދEнXR5| T綠"#LjG"EHxtc[/mD EnOGmkE]Wȴ-g t^h& [Pfqe E9j'ڲ\hΕg` o 9Y|FZ-ⵊ'B+#w#fmO?% ҷ=pۓ)SD?O"J/H]F j9mW5(6>G"r|DctpRZ-P۞ X9۬+Ō3g'6Œ}xшcF@7|ҡF 2SG尩c96X#*J ShwAmP> ,ЊL >f):^H hBV^.[&_`̕E/3|f,z"]WV, |WPe_p25(m2ShE *gBP|l7FG3P۲BG]y"(g  -] uŧy_l cEOI[6 ]!z\Q{",$MGDo)̷&yl sLa~J/ZXgPlŌr6 AG+:EMw*tHA0O(-%&0m93t#@ޢ=k'L2@w GQvk?7<g@,h>GN`>r̃R賰F#hQ&HQh }_.NQ<>਋n(^sJ@W3r'0Sm}.1< V>G/q{ 3LP|uf ãe[sir_P-@w-6㑣: PEB[!׭mOiU6:]]R|@GBhr2S:/ߒb~h B '_Ey|w1Nyp;r2H} jٓ(t*`L7q٢ `0:2ъ~~/-N/F>r[}{"0t*aS,C}tXy@Pj%bUGon2>0#CC]X PrD9(ugP˟4T|] )8^Zlv)zwy8= +ȩetk.!c(pN<@m![3G^Q}XtsH٣5>Ngq]+H=[)vSb69=u\`#ofw PaVխHP!>.limq^%V_\;.6T8CLQ0וŗs{M))צ}v tŘ <2n+x6l}fDlw=GP6pȷ2TJ>U"ū?_źp/~s:ѢafT,0W>"Ǿ_{/fwwrxE2 Z̴l E.V@    햃<>PwEq3 RP2ǍׄrԶBTH,ی+ 6sH|`v 2V/Eѭw(o-,޽>v<@֋AQ1??`}y4nbnؠҫ2LV7*5;^<ݍLb];hPo0cmPmٞTgLl bL`>k_ sk5Uk>v [O] >{}@+ܛ BCaJe#:aЈ׍(/U !$kV)Yr%aЈ@j`>a8 P1 3RL/ydEJ|n`iנ"{8^kHm/Hl1 awa1%`(P(y @ldܠnT d)f )<;aShE9y`ύX:y_.]= ~\d] *S*#itn{@Hwф\!`_0/ߒm OY&w7:.$bHZQOm\ 7{1k-/`nn|0w?"Z&03n)CP Je]B:})*ju>֪^ Eo[yǽjl<}_!aV-V6j_lgaֶ}:;e'`_?(/(2^ԶWeE9AP*+ G ☻.D׾.} l@su`,6t̴EФsГ ]n-@ M#!+ۋ2A!?^{@#%U, c؋yGohBeHs=5f!0S ((Mi;E .V[D 2E4r-PNwLL#|Lr ^we-xPrDK`)5 1*l//Ќ<`t@H!NEߢhS/.cķ"SZ_ m^ cbThC3VGsi0F ,1,H)2;4Zb9nOy?a@{#(V>[[|/C+RC`1q` =7so |egf5u)~">?`kyC^j]+hHך+= G_ G) ?f9X"d9-F E`(17Ab qo5 LՀ~5 Axo{n P-q4P#X&ԈtѬ,jy@ CfWHq+z℣eb@7^x8h12"(>W60_`X׹)Zuf{)jqR[D=b=H`m T)p(`SHe// v`ܞNu@tZo8 F6\I)vy/8oy@7Д^ xݰh=@E 1םGeOlB"O -AMhS7b< 8q fZ+*KL<*$PAŇn'P:GbDғ P;N{Z е;SdIK<.Ŏ[m&<eB V<5OӮ(oZª`K p<[Hj` 'pDBs|_ \b!"R|7<=y_9}u)lN7#h#S}(aD؆"‚-t܀#'y/˽[ u@8LvtשlSx9,z )F t5ko#J-sXR9j]_hb|_0e.!.^L@06"J@4֜DFQ2Y}g ~;GVI[*KQ´^Lq9C}+*RD?0oݡBQ.)]X Zz\:zP_< 䰎/z?3+3 {alԈ@r%k FxY|d~fZ`;ol# #@uv:5-v@1ŴԵysv2d[VyV }~M(6mէ|pSI—]G(OEd: eu|_ Bfj倯BqDmXHEy.4LʳMݷ셜,>#-ZE vq@X4Q^#3PrS VwɃ"b N@bYI@P}ct^N!8Q"Tu^_`/ /_r+R#z(|lZkayhn7p%`Ie #&,H40}6W*|짺_>'"@O> l)q ,Њ8ZPA덐!-PA+c/ɟcp6uKE-L0߲)'޳}}ו~ |Wh/@F:mWf HAe,X H, (j[V(_pԥ/kq9%`nK+RPݓ ^H`#Ws/}J-زiW9+cHQE71n+Vg|Kތ. -l s=;}L`d.^ 'r(ߢ&ݻ\mOvzg$R({GVdcz_&kydA]=P傯< >r>rj9_܀/0x+iC]G^#@fe/\g6^\t'>p*RH/L lkqSb`Ϩ򁻊 ݒx'q G Gq[&կg2r.(%(fz'jq܎/{F8ڣ|Sp`E,G1^1^ `P,X]xNT`j!׭V6oħ*_,x? #!.!}9ć_:xAH~Ci,>p 0n"<]D zTQgO@[Vewd_4\x0Sy'>p;>p=V:/0؄o֠{"j( `Wݡ?HAA?|@Pj%bUGawYGPXLYA֡ˡk,.xmC9 Pύf*[/c-v^@N7|:}pW@S#0[a"@]zCP[?'oyZPcѝ=mU,9F@њa۳8Mm>RlV }ݔr<D+i)i/`v.ӳ+}L֭Pbu,a@HZ=>r>hqA~:\@1|k¾y@RSX+>ی+ 6sH|v rV3Eѭw(2}br,gж5h ` n}y4nbns"P n!j|@)xDv763}w~@yxvwӆB!Ace{b9`s<‹)9_`VN?]{έ=T75;;] ~{Vy=sAT1)/o=B q:a|~4P<{FU,G9_ΰ_>PZ!68~6gØ/ydEn$`]sZ05Hܧ8^kHm/TD|cK^Q+P-Y17qOa]Pb#>`#.x*.l:|`ύX:ș_x> ~\d *S*#it5o⑐ B/`_(%c9rw7:.$bhSY+2Ui6.Wԅj=RĘFX0Xz7N>Rջjk/)R`*8?)L[pARdj`P(ҡLQQ[y/pVܾC+RPq.n_l/|>=-Vnt Vڛ,~Z=0SGTh[}NJr"|t;(o66~@) 5@*@Jɭ903 d#EGِGhJۡ(Rp[T-"s(W;U`apaAݺ@d 7x*mYlֶ{xR a o 8A [ZfЌ=|,鞁B^mQߋEѦ~.c.78sSgGyG yԵۧ$^.E@.  NVa1zc׫?vhݳ#^k,4}]4),lb9`h(6Lq<椵'ߟ#QffjQI?B 8 2 ~@4Ј*%N6 _2E, _> !ArЃ'/BZ{A\gcd EP |zQm64 a4\`%`sSL)OR ? ɢ_ 0KK  m T)p(`SH/3 v`ܞNcut8ߪq8^mn P"S4`_> Lb_.4`[LŨ,y"CN'z6!OqjUp6Mn'>v)i.3%CsNr5tĈ'A4vP;N{Z е;SdIK<.Ŏ_( 䰎/NB^3 {al| }^9ڒ^5;}sgdmjEE=$V-g`38yhneIBn,H40}6W*|_ #0 e_0 PBO/'ky9)0 e9`w]NzwoVB/ .5YGLs㑨rm}epSoL ⑊՗3`p+pSwӀa٠FZRrݡo( Ц폊Lq[kC1:Nӧl#=Z\/ {.@k1r Q#8KQ=_LQ!r#Kn{2ky_l cEOI[6 0`p 8@x@ۊUٿ&0b7@lB+Ȝoώ.?e.<,Qm@Vt~trT?Ra띑Hx:L9KZ!'kyuHo {2Wsg,0~3w X>p#x,|?PHaaׂ \wS.HQh / L G]dt>@ڡ|E)b`èr[E>m:nIH GGf⸭q? GRbooPvXaT=G9Q-h2d>4K9Kd{[s6ܖ|NL!׭V6oħ*_.CHH1&?PfRć_: Q4݀`"y _O ǸȃX\dP@vؓ(t*`L7q f #|d\_P)*gߥVMwB?ݲg=`FX P Q} AU :G8owE oŗs{M))8>DDcL0n+86lLAaZ"R]>E/$GX6@~v6|j}~:|c9k¾y@RSX+>،YW,m-036$L^A}h)htk)+>L@; ضO-G!/#R1%+~@b1lurȴ Мo=MYg9<|86>eaA--Cln:d"<`s9cdr 6?`VN?]{6.ksutG~r eE t^33w Q9@nP"o_\nnDP|d@}ZG]5 U i3Zf9rCkq*B)|DӧmV1/2_.ȢrH 7`iנ"{r x!5 ,#@-]6rXRoYȊ0w o)6;+q18V̦rAʍ>) _A◓ce[)bR[h4:Aq`( klG6rE`C o6Xmg#E 榰 Aa R֢֊LBڡu&Z}1} mf@k1K Oe 3S=\X+ʺth2STl} \T:[߶lrW9C_>)7X zH`nж 0lEx iYcX&CwCMO"?("Lt@/,B:>(Be9 X5b)Z%=P9MLܚS3JV)=| ((Mi;E .VbE SD#עqny4 .l5>]Ȕpo-T.3޲$ זx$?.E;La!7!Va FD)|fl9,鞁B^0%HQǞ}_F@k \?oLU=&Fk042|ǜp/wc50 >RLk wbS`1v,6ОrhER`<<L'ހ_9` ?|Y}M]}JRw1<Ս`kyC^j]+hHך+= G_ G) ?f9X"d9-F "lܠ"9iIw@)vpTϠ= L=@3ܖ8@t(ieB1E /sa{~鴰=`eȴ\}>X `zS6(!B[DK=1A.E@7`ь+ pSL)OR tn$ yp=AR4Оp2_.@r21B`~A v`,{8 Xy WC-*WRd]A3[F1|4-bW'1>Rc[$'xMX `TiA Ԋ6N8j8u3٥zdp(۠C}YV>#n~[nilyf=}) PbUQbǭ6d@֌rA!W䁅w+اiW6)[H!/AT.4G934EPh)>ST>6(a.cۧMU檠w@u!0)}< $ncɑP*ҼIeSs-EYx>`Gw0|6\Y1 ^T(ķmK%|@Üof]B\l%+2zAu6QR'$6`/0+įw'*iP|Kw)J֋^IĈ9nO%kJ\_2CP|D݁#ЀM(, {7_4r."LK\ߚC/7hkf# ``38yhneIBn,H40}6W*|짚_6Lf adNI0240 H% ZNർJ T24Q30 3X /Tw_.k|څK{,ڣm&׹{HTicVŒ,޷#n(X903uE~jxn0}{P:/roFB]BL7pF@hGE­A_'LCS6-j=˹ ӀSȏ_f]T_!.Ȉr;?4x۰Kj9yl>@yZ djVs˷61L A[p41@m e3EP|-5_"=@Z+ ' F9^t[e" sVNړ`!r@ۊUٿ&0b[/ -l s=6A  K6_[[oQ>f6'RPj;L{3)P#`I+dԿZ_xXq_]>p;#O7ce?P|pXYW_`<2g< Gy5;)WT(4FzE{.2cx?>^QaT9ୢx@6$~J\w/-(|0a bV yZJ Iǚq;|@,0\P|fQ-h2d>4K9Kd62z1bp=H30nUǸȃؑKAmbj rZQ9,Mrh)Ώ/(8۠V:!FזFTl±Z۠{"x j( `Wݡ `E z9@Pj%bU-.Ucf3ue c}2e`F>!~[6.6@kʡ̃b @1q LE}"\}]Ej]v `_x~p(rj:VصPސ1 8[EEEָjlBc;Aǰm5[Ţ~oD  vҰm}2)Bc+>nJf9S yZ yZ3KaNy`x{ c\p?huk9R3TϾK8>~Z+e-0|JUȏꃜG fA> xP(JJ@^-g ~buAi]b1f8ynLt[1~o )-:Oȴ~*p.|/ /nYi06Gϛ[>?r{Y0zӰ00PoQ3m[Bѧd BuvAGF Rʏ B2BJO`9c3f]\QX#@C`ې0#zE]@WZ}t ww9-qu|`H)1n)ȣTbIŊPC!/(2:[`xD\13w<<|8uٞPkm1ԗmٞTgLl#&Xrru8v_;5;9z=@+򈁼@T1)/ķmSd1hj(b!Br׍(1hvUykV)Yr%aPZ!6hMa/ydEJ 7`iנ"{8^kHm/Hl1 a81%`(P(y @ldܠnT*f )<;a(Њr)EPkr`JB(r8tu@}Ae X}82_Pp3GB&㚯ф\!`[Ma>VC)Hpq~)g; Z0m` miB vhrE]I)bq/ȱӵ7$@aV~ SmHP03n)ơ %o.!ھ:[Wk Ei jI|WhZi2X}rW9C_>)7X zH`nж 0T`0= 5 unPETQQDb/xRj[XSɫ=Ymd`P*+}& 17]=]?>ksCI o6AF?56t̴EФsГ ]f-Ig5_ Є}:QI <✽^?8B![[|Y}SjK)!P08w0x~97gf5u)׎KVAv~AɊ 6Nec )// AR(Ӏwn*0/*~ mn P"S4`_p߽>^3)!K+b*Fj7yE>P"쉞MX)QaKhS+F8Q̴VTfꙒyTH~ál5nZ( p  lCԌT-7|4<3ŞVt>YR(1KV Ok+»@ Ӵ+J@U@&,gy@ "NP"ʅ/pB(*-g #}% |ul4\tmx$}38PP;hB\8A,{8^=5(oНeGwhWjÜ+u/ErA)8{/}LW` ~QoQZQb/72-vK9"̺ JPv) ZL:Ld 5'g@{Y}VQ\X͢Y[% o.E cJ F`̰eR~ZaP[*C<݇' @U.c-=QqBZ7/D9G)4셱eSr@r%k Fxm3STShǑl ;bZ}0-#>G T%-XZK PhBi>%kJ&(>@|*"ЀM؎Cn 6r."LK\ z3/7f )ʑR|}rZ<472ZM"Xth`lT6!TO5l */#ȖBDz/ io=#!z3` /ർJ T24Q30 3X /Tw_.k|څK{,ڣm&׹{HTicVŒ,~loT!+{G7%]^Lߞ3WߍХjC/ Ц폊Lq[kC1:Nӧl#Z{ @-P[aS+5ͺB\ v~i=q\^ qQ-F m,k^-h}g L9YE뻮|XPۿ@尰@Dm @LAe,X 9@m e33LQ!r,S-6oAL >Ҋ`d`\+DoM*X9Cr;@x9 mŪ_o ՛E 6啀 dηgGҋVua] K06 AG+:EMw*tHA0HP$<r>rj9_܀/0x+iC]G^#@fe/\z z_>pUHQh /(2}68"=}.zNi=*whwKm0? >20Sm<3|j938nG Ă=GQwF>1%}wP+^[Tf]XTl·ZkZ @|=\5^T+PϟV_> (y{5ǒz*xK۰v#L}O, Do5VTQq9xYs{"X].rW.?Ӎ/~PԈr:VصPސ1 8[EEEֻjvt'hg:+{8F@њa+=,H=[)z:9} Z]!OK!Ok9/`#owsx9^Aj /p"3FL1M&`9rruwnjǮr4a_j ?"{< rL,@|v!0L\P|DSC|`"/0%y Ԯ*!O|m*0Qė3BVH #>`&lcAd< Ez+9,.S)'㵆ֈ-fa423}.]6rXҙFV F%@b³kvA1VCMgxZܻ;LI3(rfޡ_n-\d *S*#it8}V֪33 8q &٥zd/C}IQ$F~wnP#~[nilyf=}) PbUQbǭ6d@ֈ@!W䁅w+XZTpep `K p>euoPK8Au *c p*-~!B8^6ᑐ0U_<^3檠w#h#S}(aD؆"A\8A,{8^=5P( χ 2qrSۂ"#_"ro#UG[V P6" X' .^+odZ3b|;\`%E˺)k/Buj03X=( @[syD"#fBU$[% o.E z12#~T uWLO+ }[@wu tE vwVȱ(BZ70| a_~fʾ33 {al| }^9ڒ5`Oy,>2m3STShǑl ;bZ}0([2JZ3ck-/ F/lB9 & 74(|MP|D݁TDyPXV7we D`Q*?GԖET4Bt<_}k^3WAVbDheݲ/զ`U01h{k&R @3PrS VwɃ"b^ѵsv\QI@P}ct^N!8Q"Tu^_`/G_WF ʑR|}r- 0,!v$!EfPJ%`B>T#KTay F.{NIfEk }yAͺB\lm%(R($0ۆXRB\:_.`q01F#h n_>@߂=q#PHf`5|zn/0 6(`Y|x(>Y zҲ\!aK2h1:fHGmcI\#ZЂ-r=w]Z>r(_IrXX/Dm @LAe,X H, (j[憮#pԥ/kq9%`nK+RPݓ ^H`#Ws/}J-زiW9+cHQEdh޿&0b7@lB+Ȝoώ.?-3 K6b9  HъoQ].6'RPj;L{3)P#`I+dd/I7| d_o tAe.'VzZn0+4C} GF# 㲗 Gy5;)WT(4FzE{.2cx?>^QaT9ୢx@6$~JsH@|d: _`( bkLxZJ IA-bQ#7#7l58PTrd 2풴nrs:}2>Wk\B[!ۼҪ|mtk0)/0 9A)BJr>b~4t>=H30nGD. "bZwAm~ QaO>-KĂ;2Ua /g&rъXZڢ/]XTl±Z۠{"x j( `Wݡ?VG%oXҽ[]Ɔo?d"| Bm\m\sa?T{rPˡˢ4T|M )8^ZR.*W{;݌rs;pW@S3a®E (~N:-(*՝K5x$JշE7=Z#ta e>Rl_hS-J㊮)hu<-<0e0So1s_P)*gߥVMwB?ݲg-|LVTB~T$U"ū?_ź-@+lwk(-5)[ ~r|c/p~;h\~9 k^cgg@-f nO@   햃<P&`?@3^lrԶBTH,rl~+ 6sH/ rs9GI_<=.`ŕV]B]h _m _yzij9b )%-/y4_>P,X_>0EXg Ӛ/Cs;fg:g6>۳ ` -@6^L1M&`9fеk5.kk՚ kx59za "{<)TZ5@1G`6Ej-VnLIrE4\{TT.d[)bR[h4:Aq`( klG6rE`C o6Xmg#E 榰 AX߁ ` > Bڡu&Z}1}ڡ.¬Vh-_~ISq LafZ~(E %o.!ھ:[Wk{{^sqZg}qcbuZ]7P>H@)7X zH`nжJm*0[liYqs;_g,?>lo"t PJmka*yUVCT +cٲ)17]=]?>5JqYv`ؠx;P8 BO&w_~3B h =o]9fYq g/t@^!B {@#%ƪH!/*y ib֜PLEGِWT+b.VbE SD#עqny4 .l5[W.L9/B2<\ږW0J}Z w,O!ן_~/paV&&7elB4`ӐـC^j]+hHך+= G_ G) 7{Z r Ql1:/lNgyIb qk\k(GM3v3SO@ ch1Eb2__.@ @1K,_./ L(9@ CfN-[Gtvp qP[(dx-t%Z8yA.E@7`ь+ p蘂}UgfJybmo++Y^:Lh h`@@r21B`~A v`ܞNcus@tZo8 F6\I)vyG]`-#b FGXS1+f^鼢yEs}IpT {kaTiA Ԋ6N8}?SX0ZQ9]gJQ! *>Ը٧Nr5tĈ'A4v~[nilyf=}) PbUQbni/pEXx7}v@I^A 2g>0PpAT.4s3Ph- IW±χG*=Jp> lUS@\Tr>0"G+wЄ<G aη.!.^L^{SZAHښ3  =|\ ޝ#sA-ߥ(aZ/F8_~Q܏j 3ÖI"^Cj!Ocfu]m D @U.c-=Qmtuҽ%5U9 aEA 7`a/-bB-YC-n0 v#603ՊL5|f{Iyr믋Nmh)HH32rNFe Γ`/ F/lB9 צ n*iPr} A-vJSNlBaY`(Fn<D9DQ[6A>R@ "ӹl,;a{!'H _ZE vq@X4Q^hP,)fQm&`/Q jE żky츆gM#xvmc;2EC %qE)u뼾B@of݌r#E9R@jq8Va桹Ys%K AT?D"\lBj@0U_.GGw8%mwWx_>W9.ᅠXtGwؖ#f.\dm3Ee=HTߋ\(b5.3݀zfoT!+FFd<`4t_D]f;Ԍ@ gBRӷA_'LCS6-j=˹ ӀSȏ_f]T_!.Ȉr;?4obI;^ qQr>r<>7 <w@,P|r\Y5^PHgaW(]\ꁊjL lkqSb`Ϩ򁻊 ݒx'q G Gq[dL&ZL$~@-`evqugã٭.AG1^i[0{Ж XU.LB[!׭mOiU6:XR?`>r LRjܗsA|e\s؃4\q= xw1>ypb}(| j(t*`L7q٢ `0:ъ>xEiѵ@&|ķE`RU)aS,C=X~K -.Uo2>0#CCopQ@(Ÿ |_wQin(RpR.*W{;݈N^EN/l]u @QlcuZQTNgƶR,VsT,9F@њa+=,Gz*tf9hu<-<gNe0Sܽë66(Z}n *gߥVMwB?ݲZk xJUȏꃜG fA> (kx(a RԶzM))צ}v T;/ 3'} {{0mHo)e7(qKUT/b]ld qK k|6oL>"_>^a^c\ 3m[BчFw,X ?V D;nV}^xxl4 J_._>5a_Hp;߆D xq"S;R]@ڶfEIS\0傡[ _0i.\P,Xe?/ A/"S iA93wg:}g>0m(}g-M 07g OuDy1bZ{@sk5Uk>v xW_^U#{< rL,@|ۖDB q:a|~4P<{F,G9_ΰ_>PZ!6h~E?cØ?G]{Gb%`]jUӂiAE 佉R[o0ԎrLt V:mX=VWq:|C}Rjoi LRmo`:)^-^޳0k[ľ|P !/lY/0pzt@8VYbaP)ƊE`8bd#\{&rh=-F1(381~Nzr6ˈb˙blЄ|fYqu{ wG=^{#d%@I*˹GX5b)Jz\r9MLܚS3JV)=\\} y"@T-"s(sffh6Xx˻uȔpo-T.#޲$GAT]x;La!7!Va _>@ьg%3Rӫ-{Q(R%~q6ZgǍ)Ĩ\b fP_.p1'`"s ̂AA;"ӚC yL6 1b#ŷ7U"3)>sSh7_>0_.paV_Snx3h/:Y9ĸihSD?Mػ{0 i 1!Abt^+2 *֞po@QR)vpTϠH^pGi 0m D$OehqBŒ/ <[]#"\C\h,E7^x8h12"(>W60?AZ< }tL>AdJybgs#YȃG4`\ 6Nec )5\e91nsirn>ۭyLL+XH6(/*7ȷ8oy?F )/XS1+f^鼢yEs}IpT >e04 l mjE݈N8}?SX0ZQ9]gJQ! *>$WJ[H^zD#m7T-7|4<3ŞVt>YR(1 =<\ xj`iQ=oÕ^A 2gڻX j` 'pDBs_>h9T 3Epal#!afp> l2WUp=nh䊡^@`Sn4y@4!:nҼIeS[|(' `:չ-*19<)jE Gk/o#J-u{8j[+R^/-{=@Üo㔅/{Y2W8n e ؠ:(Bu @[syD"#fBU$[% o.E z12#~T uWLO+ }[@wu tE vwVȱ(BZ70| a_L/pfز)@r%k FxY|d~fZ`;ol# #@nu1ө7-v@1Ŵ `[Fc֌rXZK PhBi>%/^F—KfSt:/4` Cn 6ry;rx۰K A:_.`q01F#h n_>@0\:*'j3_>PQRs=׆k`wAS?!*jPh[Dy&*he):!-N]lZQX׈A/3|f,z"]WV, pz*],E<A4[!?-PHT&΂Z "؊ogYLx.E_3E ׆io.q n}c+D>%l41"B1n+Vg|Kތ. -l s=;^/.a]/ B8Z-jҽPѦ{D JmiwF"0w,iL6!F뭁.L\ >}1(vc,xr+/0|3d#m:nI-#Q3Eq8p3 V䀧|⸝_> lU.(>hz3r(@4w2pd 2lX}S>PEB[!׭mOiU6:\5cM~!}9U1 txAHkݣ"qgv*Ƞ'߂?@vؓ(t*`L7q f #|d\rp6h- 힃 ]J";#T+Pß+RP#Ws,h>oqtv0*S@)31:q9v g{~qtrPˡuEL}"\}]Ej]v `C|z8 +ȩ0[a"@]zC6ShE""Pk\w5 X2}kFH+on)0{&GJöl#Phl=:@aZj@%i/ 9l-560x[<0G#V߆[~ wgݧOkE@K|8#\;.6T8(kzP0-&P|9jDrX]ypmgi @v  3'lw=GP6pȷ2TJ\bOv)?Ηp.|/ /hVp^EiٮLAMg8xr4f-b`V(t,a@HZ=n9c}~>hyAJ_>@15a_HF1(381~Nz3gks=pW-4+#!^t@gh(f @TTSH%U,^#8<@*: Г[s `fB 3gD#zeC)mHŪs(AFE N M ` -֕ "SN˷Pn"`#/{˒@Qq)a o 8A [޽6A>B31Kg W[G!ޢhS *K2`h tW&1Wk0Z ʈGsi0F ,1,H)2;4Zb9nOy?a@{#(V>[[|Y}SjK)!P08w0x~97gf5u)׎KVT7 NVa1zc׫?vhݳ#}=h9RLY1r Ql1:/lNgyIkOzKld7lK)Qӌ^ 8*gP@hTnKl : 42Y˄bĹ0d=N-[GZ Y-2Y n q:gcd EP |zQm64 aE`%`` "SӽCm8D=b{ AhS4P>R/1nsir̻nNW'+XH6(/*7ȷ8o_njhJQ_Y6N+CN'z6cЧlF-AMhS1n8u3٥zdp(۠C}YV>#ʞ,unZ`s9["@rGOc83Si5@L%-U󨊺;n!Z Py`Gi%՚{ *,O}#RX \Q@ >2C@ELQ!||AhmX6U9"Vչ?iy@h{!,HA:#.Uy/˼[|2 Gw0|6\}("_."ro#еjls:Xj$9"x `]jE]Wȴ-b|/0bk,(Buڥ(h1^ 3ñOSHښ3  =|\ ޝ#sA-ߥ(aZ/F{% #Q 0]af2)RD?0oݡBQ.)ڀF7WZzhuto`IӼysN8}dݸi [4M(if і7;}C L"SMvߢGFbSo0Zbi=9#Sck-/ F/lB9 צ n*iPr} A-vJLB6n0|m"0GU(|tqDmXHEy.4LʳMݷ셜,>#-|k-FOV6-gw#fmO?bv^ nܽox$?4P1+XGaFwHǏ ⑊| DIgW视ӷHߍХjC/ Ц폊Lq[kC1:Nӧl#Z{ s%!q`S+5ͺB\ v~i=a/Ńf8i4/P: 2SGD-_k9zn/0 6(`Sh[Dy-F `\X ] K|cp6m!@Zp_`e3SNg+_+Gn+ X @4[!?-PH2q,JV}lxP?s e3^6A)j%_"=@Z+ ' F9^t[e" sVǐ gbV5[*~Mhy%`ٵ!Iua]%z3ߢPG+:EM| *tHA0HPo]`/pEf{<7 .Ni]*ohS:G/y)\bL.J ~jqܾ/F8ڣQ-hrdpdeo[F/b9Z#@e .n\By >Uo{H0 9{e)u^%?Txd{@  /`jw"<]D zTQkO-t{fpVN+*ڛ8LEυw3GȽxϻ Ukk9MxWkvA.[%0ʢ;3A?]CWԋ VI[]f3ue c `fd:=oVZy?W=8:r(}E8SDEHbK\;tvO_G 8zE9<v-ԥ7dLEsiGQu/[؎Dqm[[Ţ~oD  vҵm=| B~Z+e-G\>Iy͠*lm#;Ye*9RԶzM))8>DDcn+Vp'm؜)<.`#&9´#Eyr~PPz{[E%Hqu1ZFto+բlXny&Њ׊/_eW=/k-3?`aޢ -f n?d BuvA#` O)yk¾y@RSXuPwp`xoGh1y`ې0VvhޞHP0J.!.vA4cڶl_.V3snЌr}_>P\bIŊ(S!5\lur_TkNlМ䎙{ <|=uٞPkm1ԗmٞTgLl#&XY9t:{nmz_0WkZGw$ׯ-{5#^33@Q9@֌rA|[r^KFG45/LCf ̾nGi Ԯ*!O|m*0Qė3_.(|[RG|z/`&lu/Adz Ez_un`iנ"{r x!\ ,Bf|cKl %鞱@ldܠnT*fg痖xrAݻ4\@3|@rr Ls2ZBj> F/(Zf L|}GCb#WL|#ŷd|6S"sS= wAa l֊LBڡu&V1^<@cGkoH¬Vh-_~ISq LafJݲ RCP Je]B:})*ju>֊}yE *λj|d$b5Z]r<`9,!:B#&tR+-vj ?LL|;Ah tW&1eWk0Z #<`|X$6cY0(hRdZSwh0s63fR#_F8F`mq{{8 Xw鶫z@1EG]`-/y҈+b*F}e+:Wt:c{#E9ErG؄EF-AM{P:8 j8u3٥zdj@!.NQ$F! yo a?m4L]O3ETJ̣*RՆlz_(e_XE q3ЈP 3EpaJfieS*#Al>Psam_.‚-t39RX"ip{j.P( χ 2qr+Eøܤf"EHxtc[5<%Q=Qu)^y#b_0.!.Ƃ~E pܮXDISHEF~QY}g ~;GVI[*KQ´^LJ F̙p{ 3ÖI"iAo}4`Vw. ħ+,ST@Dѽ`auto`IMUa a_>#-|k-FOV6-_ w#fmO?g 6mTd+_ѹu4>e3Ѣ#]\/ {.: X9mEb@[pSIC)=a/s4AG/+Ux3h n{ay 3uTNԂG傊빽["?۠}XLoq!+ ޑAQф]lZQXl^-h}g L9YE뻮|XPۿ@尰_25z+䇹 IP&΂-r8̳{CAԶP&\KQ=_LQ!r#Kn{2ky_l cEOI[6 0`d=I/ĸX5k-!U"J2۳kCOiT`d.F[CFD編IO3AE)(Gޑ2~KjrF(^ @~2Ws ƷF_;܀?`1Vib9ƇF>xg@!ld/<+x) :@਋n(^;h8}@WlUx>M-GGf⸭q"{=j㑧|⸝_> lU.(>hz3r(@4w2pd㥆uك<P,\}S>PEB[!׭mOiU6:\K|H1&?PfR[[CU/{!GQ4݀`Ҍ[lǸȃdh߂?@vؓ(tK)$ݞӊ)dmrVN0(8۠V:!F>rp6h- m(z j( `Wݡ?~b3K(h>oqtv0ؘ+S@)31Εf'= yL<(Pqin(Rp̵إ\Tevw'^"ftJR6@QlcuZQTNgV+4j݉ cضxEby7"f;]iض>i xO&@)>nJf9S yZ yZ3Kҋ/p"Ks9\/(ZZ jQnOkE@K|8#\>Iy͠*lm#;Yego9V&Zȃk>LcN;/p܆͙ӓz;b|ޞ#(Lk8R[J* u%n*AIKiqU/b]__z\jQZk,SP<~{3_]>Ph7 |k!kqt:sC #` O(<|c9k¾y@RSXuPwp`xoGh1>߷!`F`/ ]@WZ}t ww9-9Gm#Rb RrGMsŒV_>0EXg B{^<'wL݃~O٥kY ,"Xl! EdS}2D9~gV%`skO|mMZŇ]h2~ ojN"{<ށD"Xr@|v!0L|"9`"/}؏\jW}h',G9_ΰ_(|[RG4}z`&lu/Ad:\ Ez+9dsZ05HUk -fa423>9&hᚯ(PFV F%@?U_ShE9_"Xqw0%!9`:@rPQɚnT@UHmG#{@xdhyWZ U\!`[Ma>VC)Hpq~)BB-f60[!劺p\GsܾҌr K0wZ)׶_RTp(SRTk@Ym_fb{+RPqU#'mM=-VU\"HyrXC*3utKGMW6[liոm}PUZvB Q#m0+~*EK: 0Th10JecW"8KѵK6r_i 9:n0 T:f"Pwh9A.3KEAߎLQA掷倒yd99{7=py`C y/@7BVT{$Uc/B _U @Jɭ903 d3r!ДCQb}E SD#עqnz L#[W.L9/B2<\t5׹-K?S}kA bU؂Z{B qzE/ E *K2`h D )Ĩ\b fPF8N0R``fGJiMݡSq`|<Ar[~PhB(yLy;BsOr_32;MyNj`6!  NVa1zc׫?vhݳ#^k,4{0 i 1!Abt^+2 *֞Mvܞu5 LՀ~/ 7\L=@3ܖ8@t(9KbB/5<_z3~ jE ۭ#B:;ӛA1q ͱpuU/;fX X0Gc:3SS/0i%<8{Hi$EiD#{ж*ڔ{8 y)| 4p5p|3i=4P r{?0 Le9@%/ xe3t^鼢IXxMX)QaKheBq̴VTfꙒy` td''P:GbDғ ن0~[nilyf=}) PbUQbǭ6d@֌rA!W䁅w+XZTpep `K p-uoPK8Au *#_Gf)*\#{لGBԌrͿ00C]\TiA8/mC #64< T}7b biދE29@,<eGw;Nun *2JR]bdG03l)VTַ P!Ocfu]m DUb{ 9Euҽ%5U9 aEޏb6#8/*MK{a9FTG_0070[1 'ԊFyEצBq GϚG8$`6(So 9PW @i u4CӽB fЌr#E9R@jq8Va桹Y% "Xth`lT6!TO5l */#?6`8ei`N} ԛ),^Nm%ro+)R`*PʌG/tһ+x </`+DPQ]j݊okN.}hD_}#QYZ>3{F:~loT!+{G7%]^xE Ε_~FZR5|ݡfZ<&F}ɆPLCS6-j=  Ρ: X9mE_TPwqOm؋%5z)El>ji{'@q ܌rC/LZQR`/T\ULev$`?cܾ7Oo@qtx#%ȣ  Z{Iش3$$|h~}2Ff,z"]WV, |Whh SB~[ )L ADc<79@m e3EP|-5_"=@Z+ ' F9^t[e" sVǐ hmkcx ̷"J2۳KOiT`d.Az ߸}~h=~"ô;#BHo,iL6,uH;潋2ũ_y@| ޷}xF }ny4X.#?p̓kBzY/P}) EG]dpOE)^QgT]E]m^IQ#Q3Eq;p3|@~=sA)A1;PA Ă=GQwF>1` (c.pܻ~}1|@&)Zo[+^ϫxJw`*ؕEwX~K -.^fAe c}2e`F>!~۱ẓ'?C= A1.]3Ed*~@e.`rQګw~F\Gp(rjSKJ޾"iGQ8[تu'hg:+on)0{&GJ϶u %L=X)1xNiVNi0Uq@Q_>a:`.x`:XV#?C S觵[<@K|8JUȏ_'\?Ff׆͠|v' LQ0Õŗs{M))צ}v T;/ 3'} {{0mHo)e7(qT JZLbp bη3h_V^EiٮLAM#8x;읢"ӳ+}^ b xdX=xk!kqpvA#` O)P+kI(XqM1(R}*aŧ|uqEbb/K|v rV3Eѭw(dr,g~LVm/sS _i.\P,Xe?/ A/"Sϑn0T _ М䎙{xvw.|.9` 1o(z @쓉 ;c* /0+\@sk5Uk>v xW_^8q?y@v{ 您c S _>߶{8L)/P/!̾nG _@⻸B=m `o/g?/(|[RG4|z?M=_y@#.uVr֥VU9-T`Oޛ x!5|@bY {L]K DyG(zˢFV F%@b8"_ )l:|ba`J_>@3]}@rPQnT@UHmG#Yk #!5_hZl ;\oylS|4 8{q!!3 DjZԶzvh{uq~v~ln_k;kаnn|0wZ)׶_RTp(SR4Z=P%CۗXg^0DpqzHAŹ}m[U\/P_.ڛ,~Z=0SGnDc耊<{g5.0= ~`ڤ`NY~݅B`{F`V.{a8=_a{ h10JecW" a@såѵKc}_4ǜEn7 &s:vw 2q\M2lBkB}xD%%0rs>o8{{ 6sSh7_>0_.paV_f) [X &Av~AɊl>Mx$$̌.cۧMU檠ʜMZl/mC #64\Zg.Vx HZ/ +.EOpY#;Nun * ^rF[DDpԶVԥ {Lr@Üog ̺{Y2W8n e ؠ:(Bu @[syD"#fBU$[% o.E z12#~T uWLO+ t y[G 0pjK OWX\)(XKO+ QWHKzݭ^8/3; _E]\+2 {dWԥg\ed[Z`)ϝGm`fj 80 _3xbSLϑfe䜝<*i/84m Њ&\6So`VA%3G(OEd: eu|_ BfۺC) ۟#j"G*sy@d:Wme/5`/di ^h1z"n9|`zw`>b6#8/*M||cDs#pAHaWtm:/pxdCvmc;2EmhD?hS.r}kNky_n@#H}f>>X fY,)QD3(gs ZG~`0<#pJڀyXs߀P_>Iro+)R`*Pʈr"_.tһ+x </"g@E]pwv+G̮+x~-ܽox$?cVŒ,޷l8 VnOL{>+5lw#-t_.@w8o i"S\֠PLCS6-j=KiQ@mMB~ԈmEbg3obI;>G3t4\VX֋PknÌrAfԊk@EI\E OA97B+"3PA+L..zGJGE:2w29%̈+g,z u [603d{b}Pۿ@尰_.25z+䇹 IY_+A[1[GAge2EP|-5_"=@Z+ p1O1R"܋nx l@B8$E XH<| mŪq78Ro  ֽkCOiT`d.fۀ!5h=~"ô>IBx:tB&O{IM[Όr%݈o f2EaFnyܕ4X8r}| >Y8BY7Pz >jҍ}E{.2_x?wuJ{@WU.V|@Dq8(|sL/0a]bV J ~jqܾ/F8ڣW1YLcc<rG>,[]r no@|J`>rLRj|K~eAz_U_Fyܻ<8U@>P}=מ|A[aVTN! 7q f /{w]-N#Fזn Tl»Z;{"̃#f{L]V~b/^lJz Ru70*S@)31:q9q-~(zAb\oqv3Ed*d=)8^Zv)zwspW@S/0@]jPu.Њ<8[EEEֽjlBc;Aǵm}+on)0{&G,kEj xO&@)>nJf9S yZ yZ/Jrs9 /(ZZ R+ΦO֊nYw{ߥfP6u6t= >x_α5"p|.VD\%fcn+Vp'm؜)̈} {{0mHo)e7}%-EWu1ZFZZ-Jve oV~_.w/fwнZ~9]kq3sUh1fu+X=E/$GX6@~'`?' 87[~86 gx\@ʏ ]m@RSXuȬ+ 6sH|v V#]@>P\iwoh }+;# `~[/̹A3Si@Msf%+>L1f׌r"S iA9iwc3{ZóK޳^LWXx EZ 0ŏݖ OG /&XY9t:{nmz_0WkZGw$ׯ-{5#ro|b92Ef ۶s)efS%fm}=k@ @mCHVRxK|9· )|DϧmVcN ?AJm Ez_un`iנ"{r x!\ ,Bf|cK^Q+P FV F%bPxv~(*l:\EPkr0%/P/.=(ܢLڢ@G ָ#!5_؎&l ;Rջjk/)R`*8?)L[pA{hB{KH/3EEmZq=HAyWhZi2hbhuW##R{OTf mxIl=iY{s;_g,?󤾀GEK: 0T`OV@)ƊE`-BsϥϥWc΢N81~Nzr6ˋ/Bk>&JJ`}pBmG#{ݽFJ*Tsj U  Qͭ903 d/EGِGhJۡ(Rp[T-"s(W;U`ap{[$Xڇr ^we-x;V1@Q{)0GA bU؂G h1_.{,鞁B^7(>)avD?LL|*25p_ߦ9lk0Z #<`|X$6cY0(hRdZSwh0s63fW60z_`Ur"SS/0N !a{ m T)p(`SH/#a5ƭb4`9]7Dۮ ̃M yr{?0 L/@S_>`[LŨ,yxEN}̡u'EQ=8kaTiA ڴG.cF?SX0ZQ9]gJ-Ilj@`opUh{표/~[nilyf=}) PbUQbni/pEXx7}v@I=*,O}#RX \QG 8/EPh)>ST>6(aF ~?&(c/0WsD s9LӀ_7BXGYb biދE@,<eGw;NfK6|f )jE GkZǘC%Q=Qu)^y#b_0.!.^L^{SZAb`%@i$`#(@y\ ޝ#sA-ߥ(aZ/F8_~Q܏j 3ÖI"^Cj!Ocfu B|";Eջ +XKO+ s@Hrt2Uh ut#0So0ӰƖM/!+G[Z`)ϝGm`fj 80 _3xbSLϑfe䜝<*i/84m Њ&\6So`VAn#Zǧ"2 ؄L0`#AU Uh"- h υ\y րgBxr8|lGp^U N/4(3PrS >7 Qfzżky츆gM#xvmc;2E'ʎvWLK\!ްAE.~^)ʑR|}r- 0,A,H40W%`B>T/30wpJڀyXg|zGB(f \z_T7g(g0 /"g.3|V|]pr}L0^s㑨E|fdq~d@xbD X9;(<+RpԋҠFZR

#\!r̽)`˦Dp_!G/ĸX5k-!z3&Sz: d.F B8Z-jҽPѦ{D JmiwF"0w,iL6e!^ @mPbe0Am'`9t܀0Vi~߇#_#? e/Xȱ|@u6ro4@r5AEBrz@g}Qq݀P?w6X}(gTyଢ8@D~$Q(<8n;pg2y@~}&3@)A13_P@,gT=8G}v(|@Q9ˑirnWӭ9_z?pT*Sw@u+bܒ#Vk!?|$䘿&(3EH{_*{^Һnm<6@e]DŴ>ߍ GP}]b6PH=38+S½]L v-'#ZQϻsEyZb~ԢB{aQ*&Gz7]Yt"K-߆)o?d"| Bm\m\wa5@kʡo?m3in(RpܵR.*W{;ݍq{p(r~[uJu @QlcuZQTj}=@m֥ AߚQ<%[Ţ~oD  vg&F>RlSD6ˡIn-!O/p/ -wE[ˑB|]jt)VH yl}29 "T͠|v' LQ0וŗs{M))צ}v T;/p܆͙דz;b|ޞ#(Lk8R[J* %n*AIKiqU/b]yVn+++q[1S0o8]7>k^cgg@-f nb5,a@HL q GF RP2Ǎׄ}!R!zۧV|o3v.߽,D3e7$f9n6$L/X/ۇFߑbP𵟻@m[/_V#snЈ}_.?Z _PC#Cky@)Cf? М䎙wsCƕz=0m(}g-M 07-@쓉 ;cdr 9`VN?]^[ZMXׯ[j ?\ڀy9vP7(ķmSmĎVl:ahonKxKwiW}hj([mcS֋rVH #>glxzϗ 2L E庶J|n`iנ"{J֐ں_bFqcKl 3oԍJ,챁#gn>b (8/xZ 0%/P/|\{TT.drR*S*#itn{@Hw8B/`{_&(%c9rw7:.$b7+)ض )Bڡܾҍ2 KG z[Ms@E Xq |*$ﮬ L[pATk@Ym_fb}@<^0W⼫G4 nҲ Vڛ,~Z=0SGTh[}NJr"|Wô,L-t ) u= Qir<`v< "p R(_݋# zq]k_Ǭf☳cAc-u&}\Mr5_h }o]yfYq g/t@^!^ y ^FJ*T;`3/aBeH)ib֜PLeh\l#4P)XB-fQL\ǹӫ*00-߭+D{ovEF_&`m+1T#QRazۏ/b<@3YRB*@h佷RLk jb9nOy?a@{#(V>[[|Y}Sju`<<L'ހ_y`  ì̎F%lB4`[{bVjEǭ {v`k͕Eڣ#Ŕ@,  ^嘛 Q}7QffjQI?_ 7LL=@7a4P#8 tLa *gV)^ZD=b=H`m T)p(`SHe//ǡ 0n]PԊ^X8ԀÔ:<8`=4ж%@JLӀ=yQ~xq/#)mXS1Ra +:W1םGeOlB"O * 8[DZѦnxNqDz`E7PHK&{"|$FT/= meT9;N{Z е;SdIK<.Ŏ[m&<eB V<5OӮ(i{8#B*S@ "NP"U4gP 3EpaJyieS*#H|9nT gp+wЄuA{p{jPPǡ;Ю9WT%^0eHQ+Rp ^<]&?9֦.`*BE`/#XZQb/72-ve1s}_0bk,(BurD)T 3؃P^$60Doʅsįw'H)RP~+SPXzDZ ڷUt y[G 0pjK OWXbzwak鉢{EL+{c=Kj /@rh^ i c˦FB-YC-n0 v ,<ƯmjEhǑl ;bZ}0-#>G T%}N Xm Њ&l{>%kJnP|D݁TDyPXV7ʷSoCћe)倯BqDmXHEy.4LʳM}{!'H _ZE v*@X4Q^hP,)fQm&`/Q jE żky츆gM#xvmc;2EC %qE)u뼾z_G_Ѝ2#E9R@jq8Va桹Y%1Ďd Dp E`lT6!TOu|@0Ux F.{NIfghk\f'_'Hňrwt⾮y8W\=\f.!`w`[~2`< :dr|Dctȑ~j+l4`n8VE Zo..zGJGE:2h1:fHGmcI\7ZЂ-r=w]Z>r(_I@"譐o($mb *gBP|l7FgGQ۲B.E_3E ׆ȱLؼQ-3-lK+RPݓ ^}r F9^W[6 0`p "BƳM`%VoF؄W69ߞ]~J/ZX_ PlŋrAz ߢ&ݻ\mOvzg$R({GVdcz_&ky_bLqram`9t x,>p ru'0yY\ۊ ؈r=#!@ =@QoVr\t'>p! w=8Rf} 3T$ ..(Хz@DW/$ˋ008n.<|Z=/8>Zbw?_.(fm< ~1<({.(i=mf~5gt2>Vk 1[є.e/kI1&/"x/h(29 B؃HOP5@ qpbɾT*A'@m%bvV>a/&VYw|{V$+N}vJ·ZkZ @"ۃ'PzS.,=\~@A۫9ԋ4VID*.w`wYmG }o,gCmˡXX]HVl(zAb |(όF*~ *BpRzg@N7|}pW "g(E5 (~N:-iƦ֝>^Q|us٣5~Nz{[0cmc GƦ }͔|<DWSUS /Jsx9Zl_ P&`?|B&Gc`>\є0,Vd, j!a 5$LXN/ۗn#0g. }RM-! _.eFۥ/9}+^Pb /@EXgWW 9xD5繾cF<樮c%`JYH"fSC7d]K'uɊ wLj!{+@{k0YMպ-9PfYp~VyǽsA1)m۸Ô2yobG 4:рmgqwAE+RQK%Hqd֋rG,c(B'9[d ]Xc.Bf~cE6b[W|BG(Vr[0d`%גgvbZl:|@kpZQ;s"g9]@*@Q֋(CRh#it~Aq U{QA㙯8JVL|b*Y>ASE p1c+)'@i6^~@lg7`cV /0c :V?0w j-(&vIS1 PŒePEj@Yb}@|՚%T<9:!+V@ZB:L/@N/DdH}x|OC*#ut mxӉ\ZxE*}fav+P<ίsR B5a&; 8Lwo(G5J$+>.'17L?]{4_>5IsQƌဪ68 d}6eQ EA߆ ! ĻJ`Ƒ(@^!ئ8B_.@w/P d%@N+Tje*T{_fXZy'ZQ aӷ< b/xwp{SB@$*y-1S~*6xLL|BwŔ^bbC3 q hX$6cG~H5uC;b)0Gl1pb*HK(mm-`8< QL[/B/80_f-XST2U;V'+0OojD!uPi>`@8:^46ncNZ{қ'4 q " HqՀv 8 2 N *hy36D/P18~<:/| $rְlPZvI\C\@q ! uIJfAs܀ \ 1uޣcV)^8D= {PUTP=o :N8*rh(l6=oA 3GNvfsz < ؃8ʂ_y@ /@S_pE*bO8yE>PpTDO*t, B`SaKSWԩߋnø pvQϔC!  xj@`W~#Qm 4\ ?a?cc4Hq]o3DT*!EY`G;+><q`@ T-qe =?)tc![ݽ B TA.4BQ+3TZ '{لOBL/9}`$ɜM%6p|-cp4cao4`^R?*E X=qX"ipwj>P( OC@8LvtI (1l!8/>}&8`#}1PE+"^y#R[N/0,!.]P+BUNm Q 9+yx"fBU@$?QE*3%Lň+ێ#Q 0ԭf2)BD?Ulo qtKW[Q|_c-=uXZ!-SSU_>_(v iƑ!{v;YC-n02vkflf"RTjǑǬ ;@ 1w}0+#d1UI[" ^B>jEL6So`&[xrUtZǦ"" Xeu| Ek]ȇ,l{"-E(*sy@D:W] ۤBHhiqYAX4Q^h 3PB9FT#`6Q̓Z¨14^sv>fqHm5 !89;݁3!mӾ uTCӼ5<_6G9B@j@hskaq<˒9 ""0}WU~b_* /'Ww8%m8p-r9g$R=8w4QRT 0 R_!r(ʂK /0٭0?1psiE} @u7p|_cc- 3r7ؼ >Q~! wG7(J:[VxEΕ5lo#-t)-65@w4A-L R'Ɇb-I-j= CupC8<._!.pF_>?3^̩U!.ċ Xj y-*GP:L/d_>ȩ"?{C97ԊTL Td):O PTCAqtنp6_6%"}&l`Fɢ,@_eeŬ }%UG Sw0|@! 2q,bU}ȡ~ j[P&<|QQ=,5(&"=@ZԍcW@ucO&H`%+Dy6% l@Sa1T)ĸU5J>A ]^ XA|{Nt ؔ^a_@YxY.b B8 !™ ؔ}7"D'aSL6\L!܁|]= qra(~rm`>ަb 3/(5\U,|n^ z+\t'>p! w=8Rf} 3T$ ..(Х/@DW/$na('P38n.<L>P,ޖs*_.(fm< ~=Aw¹xc +֜MX} ++xooDSF vv{h!BJr.R/ k= 0n`#8[DŶXg*|@ J-JKŌ;"}_M3I}HVT]Xo֠h=j( `AϞAA?|s  "G;,6#P>7Sf!Duhk,.P$+6C= A1~vf(όF*~ *BpRzg@N7|}pW "G0Fi,\Esih>@mEo(>zE]by_FH3akiPoofmT㰙g y yQ_>a:`.x`9XZlt)oq.<\J)>@( 3b(5,? JaJ|@E9V&Zlab@i]b18yk1ZimGLEqpP[%ȩ*"/^bpŲM/ H+=^nse-6/|Hlz8?.Qc֭abu~,>azc>٭ rdz h@(<\@1|k~q@QH>QMc/0bEbf8_C"<\r@}i!;B-L} *ȱx_> r _.R傡[<`ġ]Zr!F(`TDuvup}#AQsݍHX<LC Po0cm 6vlOyڠ9sf_`]{=d5U j zr/`/ۥgN^ XQ8@.@mpR&\ ~n] tc#f_7Σ _@ @~g4*9R3? _> mROj~Y?cØDP# +bn-º@XɵkvV8N/0ba`J_>@3.]}rm(\f(CRh#it~Aq5_@'!3_lCVBN/`_S:qv7߲]@<` 1!!36MkQZ׊H+C/+Cj=BĘu_`ưӻAt~e>|"j̷0#n!TiZi] ̺:}`AY+VK\N/P_.ڇ̇ T=0RGж 0lEWag&`i~y_,jXR@+YA)O; 8Lwo(G5J$]ƒ!cn4 0i}̵E,Ʊ@qgp{q@UgVMl~Nz>2l|P UT#Q} W!? 9PY X5b!+R61zrkNHC(bQɢ\l#4mP!Xu_z~^%QZ? ^=Tyc{u偈p2*߽/X,C띛$EF8}kA b)ph93BWESS(Ul6N/Nj)(\Qc f O/8Nr!Hl0\3cP'tpC;b)0Gl1pb*HK(mC`11` [ZY2;nXyBOu;AɊ8!S/fZQAgGf]k,g~.!,l|`#AC1/lNc8椵'Ud7k 򡹍^ 8*ig p "tP-qh4 9,/( F>S_t=`Ѓ .!.j,܋2x!t&xeъTġ^ 05\Ja gV)^} ɢ_*@a洗TTP=o :N8*rh(l6=oA 3x8V$p$pHqӀ=h,rѥ\e3t^鼢9T~D= y&M-AN]Q~/b|N_qtqJoa5nL&DJQ$J~o40\ ?a?cc4Hq]o3DTsa㐢,bf 婆8a` 0ۥoӮ-LYn>"D*ܠ:"…8|3r@(}e@KB!~_>Es4I2W}rDP[q~0g zkq *C7N@w0(`Dp@kr5<!GH3}p- 0>wY0PDCZfP ZO~ZKV0 e_0~ P''f|;J J2 0 R_!r(ʂK /0YZ O̮-\dQg} D*+XGŒ\ ~"<T d@w"8UPd%vct!% z s f*r3wYl19r(m_I@ey"*]!?#PHVT&΂@L "c߼9P eenNQb!r#yJAA8vP7ddň"Zl/~\`vO=[|W1wY(3 n?d 3] !0kj} (<@\5a?H8B(T(ኦe"cxQc <߯!`_u@}i! qW'2JoA GVSٶ5\0熚_.hn!F!k"R+ "\1#bdz>٥`s,B\!V;@9'+{#[&0c8petLVS>CcK*rO?^q/q@kf]y 5\m=5< ~RSC傹Qf_7ΣjԦ*!OLVf>H%Zmk`~RϦfmZ>%Hqd֋r(9r,?(j=J$kHz_.b0!V+ۊ| 3o+bnT 䪘=6p+X Q+QM  w{SrE{b˵Up!E SH@GŹ/T'a3_hآ_7 u4Y@<` 1!!36͵" !ˊZ}1x|]1nnDջCm aFJݲ B"PBg,KH_fEiήz//!8񓚻 1Rj0.S HݲB+&t2a*^ iYսn{A8IY6BQ`?$*,Rj1'](dcŧ؂ޠ8IѵIc-=g18\v1c8M+u&}6?'=YmMvy_Pc㙯~b}v#Q} We!?݋>T>Y Uc/8\]I'T: Г[s `FB۔~_Jz_eC)mŪ(AJ֢q^z Hc`+ɪT+DP}EJ~_`i|*Tſ">#5 1{1_.۱_>w_QdWԩlKqbc/p7p^L-&Fk04yyǜp;Eb1v?QECP 1mєqL 6 X8lml1i "3)>qC<o_.~B?/80_f-XST2U;V'+0O8j'[ese>@}8pu@1yՠlD4|5F "il@ǜ7Oh>/D>4ԫG% 47@DJyb(m-@{FZ "gETTA{7NyӠ2 )5㱏R87D0/A\8A,{8^;5T"P&N,8uy-H8bxXrAT/mj@q{@nHedh }^>z'k FxM`³ڶi0q$a1+ȭ.F:Cs+!8T ^\j`f ƓV_^{ UX0m _^*i \a@%HBVaaY`(>F"`Cњd!*['ڲQ<Ds[[BN&-lD5FKV6-{ .)YAX4Q%rWB9FTS  Zw(AaԘWtm/9;nD38$`6To P7|LDQ\h5hA=/8BR|Bcp,\ cO`%`NbGM"h"9\QV!TO9Ue0wpJj ākY_>`N> ԇ)BO.>N%d8w!0T[DC W<T~2@Pj[Ɇbt+" -oOjQs^AA/upC{[ů[EvN^ lL3^̩U!.ċ_`+ꗋ q][!P MpE-x`=\ȩ˻U\to(`Y|Z/"P d@w"8UPd%نp6z_h@ >T60#dg2bsP۾*2#DTѻB~G CP8 1*`W}n{Jqږy#enNQb!r#yJP?R;jGOّ0 l?C=/܇뭁.Pa.(~9m{QO0XY1W_`|2*2?{m~@Qc_xBW ! -*"{8Rf}L3*U)"uab"ccS倷>} t+q%Pd _`ǭƅcb5LxZT H$@v@1ccSG} bt#s9""xxAMVӭ9-7-x!Z; ++xooDSF .cM~@fRDC)N/f"gZvA5-?<]{ IGX}S}_M3~Yw|hE/]XcAk1Ѷ{"xۃ'PzS.,=AA/cNXAsHѥ4>`(C@)3"`:rh5VP$+6C= A1^\aw# Y!8^ZRzg@N7 tM,|b"QPwfjlZ݉ cm5_xxy"f ;jm}k3>*4  Ⱉo y y`/SQo1s_qKfP~KMMwB?Պnq`LWN!?9 "3bϠw 'mN2(a)qs{M!ؔꂈkӾHcN;L/pͿ s´#D8P8Ok(qV rH?-`,| /p_6 _H9"`cO/p~|;xZlxE;'cQc֭ib( Y|Œ!䇵8dljLv}~ h@J_>@1J R}̇+r~,{osH/ rs9@Wi:n_Zd<5WZ}u 3JoA GVS-9`msn(9`ۥE/s:V@e?_>0}b]]a(\EqԜx{yQ]Jd]JYH"x9%5Cl{g{|`G/[&0c8fе5l{k0YMzZutG\(N{jE1qCl+ۅ"h6!0L.ɸE/}8*Ԧ*!OLVx3r-g mROjMYa "_.(ƑY/,0\-l5P`OsR{ˬ1W\ ? +ۊ| >@+憾8w%#+<;>LO,(Φrba/PKqb˵Up!kE_ SH@GŹ/T'㽋Td` TN}\w#C:&$QcQVRUOm( ɫc׵j3u6 DջCm aFJݲ B"P>MvXf֭(-Y/p-q "g&s0|>+VK\scuEH}x|OC*#ut mk4X8::@Yc0L,u}uNvB /`(,Rj1'@)dcŷ7QANOld☛&Dמ&`X@q̹ cp@UgVMl~Nz>2 5`*&=7$0|}pB _._>^AJV, c؋y(O/pW @Jɭ90# mJO/Jz_eC^Q8(XB5fQ E <Vԩp R\r^Be+yW|U\8;pրS1 /9u(}!DO㘖LE/{>&L|Bw|1Wk0j d#94-wc503~H5uC;b[}'8by@,l6J4rW!Pi-S|osoPh8i `MyNP !6HqEsړ*V26(*򡹍SeXfQ P8cCDrY|A怐0ضſūA3'tNp qQ+d^H, uIJfAs܀2:`ưy!6H)OR c`N}R"3TT؃n`@ AecR _>_8FCacy j4`>[7D|[}lTvH6Nd*`Wc4%iTLŨ,qxEN}̡s'"(>a dҀ%@ԩ+E8@0naHpvQϔC!  5^i\ (ObDғ *ymm;74<#řVtSe;6{O(O\qX \ @բzZXpo~b? |UXp 㹂 H+*~q!}?l~*$ Es4I2W}rDP[q~9LyӀyAH7b biދE2ߩ9"Q 2qbkA"PcO/Dx tu5A-C&Jb*EDpV+"BvK@1se q.\jW@/sVN} *hkNEJ^>fBU@$?QE*3%Lň+ێ#Q 0ԭf2)BD?~bHV"i5nՖ@VItak鉬{Ebw i>XO;ڽq6e? #pjq^S7#Of60#b7R>$8fH6`b{s%$^9w'#JcZ_^{ UX0m Oɿ7Bh*Ɏ`JcSN²P}zE5.CT mOeEy.4Hʳ`ӷ셜,MZ*4d+jl[N/LO ږ~ZB1#:  Zw(AaԘWtm/9;לտt|Rsom5 !89;݁TphheGYr좆\yH-_.p#>X ~JBn\4h`(5lPت0\Fv_!,KsWI>L!zrq(i&  J`>]A*0|W9@QHTj' O̮-\dQg}݋D{(>;m&ňp^iHO "ʚ_D`]J44TBAnE &yu4e3?EͱGzp;CCnupC{[ůrgd9_ RRSuz_r1"k+ PlJtd`i=X빽[E Or1(CԊTZPA냐O PTCAqtنp6Ě_~@ZW !H9YE뻬Lux/qUЫ7$"QAF a6B@ Ae,Xd ]1ͻCAJP&<(w@Lw  -S Ʊ+ '$ň"`~r/Ba\P}B #}(>Pۃ,e0@EOR(b"coSw{tA{%OMg('P38n.<L>P,ޖs*_.(fm< ~=Aw¹xc +֜M2\ef}>r*Gє.ewI.c~M^ 3DH^Pea:`.x`[ Zw-G6B|[jlVtK#ދ\`_.p%@C} =) zwpd*CfPr|3rX=qpmwi a@uN{cs;#ZwGL9aZ"S]pP{EwKX,9ߞ yҠdkQZi,CPrGi1gDj}ごP(ycׄ R}̇+^`rA;!v6@bc8_C"<\r@}i!;B+HXO/R_S)`H nYvibNÊT! _>P)}^Gyo?09X w{R`NI @lٞA1UG;j􄽔{+@hEֱy.?CZ;xO_^8q?P+∁̌^ /mS O D~"QHE.m du0!G*rGRjI 0glx>oX"H82E^}eyf`U)EZ8?g+!|5pX$VP(\17! +!XɵaJ|b1DGq6_>EX8( ιY|BS%G>"@*@Q;h(@)#3_lYEJ_.` /_.:qvrߍ, o0또DD}XIW=BH;bd<׵jyNOYmMPk1D1B"x`FJݲ B"P>MvXf֭(-Y/pL!8 0y 1Rj0ZB+SC *jGG(0kոô,L]@ uN%N/HTTDJ|J{w5.PC`-8Ik Vr?iPs{F?5lӊCݡI BOVg] <|Pc`}v#Q} W}] 8BO|}} *yGX5b!+yn5@Jɭ90# mJ/D%r!ДAQb}yE CD%kQ8/pz=h`Od=/`Wm8)'>e*T{_fXZy'ZQ aӷ< b/xwXO/B@$*uw}Զ=_Fx1Wk0j Gsi0Z#uc503~H5uC;b)0Gl1pb*HK(`8< !`/~BWE `츥jگMJ`V! [[b<ԫonΕL8Vb> !6HqEsړ*V25\gif8jQI;^#qTz- 26D@   軒< N 2 3\5,xz /hEۭ'tNp qQ+d^H, u@<@, lzQmV4 az(Wf +`}UgFJyb(mp q9TASZ6p|RX'S%>yo| NCﭛD|DQ}; ,r4Wb*Fdٌ+:Wt:c;GeOB lUAV鼟C`S4` ~rUȋpz4E"x|"Q 2qb{zE1< <<!"r'е .fߛ(QZ( {Hn8ּN)E˺*Cp^_0"rZ: 9+yx"xaEJbQ\̺TD A z1"ʶ#yT  R(@uDn!BQ.]m D~E G_$k鉬{Ebw i>X ^P^0/#BwZ`dהHٶ HkE <Ԭ# #YAnu1ҩ75vb\ `ơTR3c0`[G‚iQ|J d /4Zn ~R݁TDxn0o^ >& Q*=GԖ"O< "+ނeNr6i` 1a? vӺ>h_._>Ps#Jy@+B5] yΎo = ص2P|t>N ׸Qc"(:/pM/(Z3_6G9B@j@hskaq<˒9 "h"9\QV!TOkiPت0<Fv_!BsWI>L!zrq(i&+;m&bD X8;AQي8԰+Bpe=\f/Q '@NjAk QqM{/KrJ[8iU /PF*'g8=Ŝ}]BhX֋PgxnrAF(\Q _빽[E Or1_o'1!+CPZ S 8K:bslC8JKb /h@ >T60#dg2bsP۾*^8BD+y Io1`! #}ȡ~ j[P&<|QQ=,5(&"=@ZԍcW@ucO&HVx/X(+Y!r7BD/@Sa1T)ĸU5J>A ]^ XA|{Nt ؔ^a_@YxY.b B8zIAp8|5,|'Wm^ &̀/0]Y|NO?`|*w{W>`~r/Ba\P}B}*"}{pgdqۥQ{Eަ*肨J*(~g(Bzx[&(_oW˹@@Nhq/36U?qԇ|cx!P]Hc1^^ie1b8>X} +z8"t)?xhE*v{h!BJr.R/ k= 0nAQ*gYZ.@Eװ J? t˶@1c;H+da0sD at~Ap;>p=@+U60-( jAk1Ѷ{"ۃ'PJ  va> J^1^J Rqt) o?ec}3e`F>Bl[6^mEbC9 "P 8CD0~"X].նؽH&`_>p > +@te(9*- !mL3swYD}@kN.` @ MX)1xFiZ{Ai-5`.x`9XZlt)SzG.<\J)"'A{R ?T%0%>^-g60z ڴ.1Àv< az;b~*@<>@۷JSUD*_n e1ZԜ ]﵂l-J6enoZlQ8z痶afw(QE4}8?.Qc֭abu~,>a|T(rܻq{C``:dܥx qG/'J_._>5a?H8B(T(ኦ|e"cxQc 3\߯!`_.u9 tܾtk!ĕV_]B\QAmM/{퓑0۶sn(}/hn\ =xAe? _.b]]a(\EqԜt4Bg-w{aZG ffBQ8@.@mpR&\ ~RSC)܈(׍PAm du0!G*rGRjI 0glx>oX"H-Wqd֋r(9,.ɵpV"YCj*^D~cE6b[W|Bt-b%W ՕJ\a!jE>/½.TM (r.]}rm(\f(CRit~Aq UnX ;\oy@L%!h}78xz<cBB5fla%[_!ˊZ}1x|]1nnDջC՞."B"x`FJݲ B"PBg,KHc/ (-Y/pL!8- ж6>+VK\~Ab/@Js߲PDZ8{w5.03 zm?Pq~laIj,Rj1'@)dcŧ؂ޠ8Ik Vr?iPs{F?5lӊCݡI BOVg] <|Pc`}v#Q} W!? ݋>T>Y #`{1P: mb֜Pr6 EWGhJ۠(Bp@"J!@8z# UA^]y "Lw,VK+^x Rq=x;pրSO/ncO/0sPBD%N}/ @_Fx1Wk0j Gsi0Z#M0\3cP'TSwh0!m03XA{# ->QV!P0w0D3lsoPhuq ֔#fΠ;AɊ8!S/9N V`\Y4P\4@9BLY1FḊXc^46ncNZ{қ'4 q ",^ 8*ig p "tP8cCDi4 9,/( FfNW f*[O =V½8 YR)N'xeU/ ;L /0cXGc:3RӽCikq3Jqp8-}O7 ؃J0N8*Tuc`~n>Pl~b 1޺@t:-η8 F%=("~q(Sq[b_.4TLŨ kt^=ض l'zVcзl* 8[DN^'v-V.Ꙓq($^2>&WJQ$J~onwn VhZŲ~T|Bg9AbRElS /qX \ M m@U 7,wy@"@nP`DBsdCseam`H:)cSz0hcX6I檠O!h'r}&qq6sPD PL(`ՊWވT8v,K~uT gPc^T`9P@T֜<\"Ybg%1(.Z`f]Aebi~esD< O;(i5nՖ@VItak鉬{Ebw i>X ^P^(.iƑ!{v;YC-n02vkflf"RTjǑǬ ;@ 1w}0+#d1UIrXB>jEL6So`&[xrUtZǦ"" Xeu| Uf1e|V8lA~ υ\y,;pրŷI [lEw`>jZw`~bVж'/*M9 ԀPs#Jy@+B5] yΎo = ص2P|t>N ׸Qc"(:/pM/A /8BR|Bcp,\ a}+sZ;mEfP ZO~ZKV0wpJj 2~ P''f|;J -@eL'}T`Ѐ9eۥ Ĭ;ީJ`~bvm>'=f}oұyA|Q8CnPt# O "_6跑 4d k" :WDZN߲Ԣ#^<?-4`*䇆pxm]B\5|e{{1f_W/:_.`+ꗋ q][!PR! 2RGZr` /P\*c.H~7z,>AH(>>YRVHo@MY}|AmHGicIe^-hgf,"]V&[zyF(m_I@ey"*]!?#PHz!L lDV)FgmBGYD_bSԠliio0}:QEj{2A|/X(+Y!r̳)Tpd" sאJ:_>f*!0Z*ty%`9%`Szquyeeػ_Ϳ>$%"U8\8:r/UQA{(BT|Bώ9Ud5rrb)]d]'!@fR㽜 x@/3Wɻ6@YZ.@Eװ J? t˶@1c;H+da0sD at~b>"YQu_>`t[PbZbmDpOz7]Xt={"򁂒Ws̩+h.T]J@xQ! ֡C@P|x9rQ4TfTxk إ t8z(r4\avʢP[?'oq3Pc NQoo(K̺9A@њ?aS 0cmc GƦ }͔|<DWSUS /Jo 0U5O`.x`9XZlt)SzG.<\J)"'A{R ?T%0%>^-g60z ( Hc pͿ,>ZwGL9aZ"SQe(5(qV rH?-`,|;|pK~{ Ei٦ AMP+- G/.Pi rv?qp윌D{[BևPA Bkq06AdFR>@ʏ^d9J( )> |)afYX,{#@ԘCxQU_>@|*VE[!"}b r,ާpokZ+KߩYo0TZo0tc[`ġ],&#Ae?C c;l)p}#AQs;fc:V&z}`ݞT(7SR16w'H%Z(ж-c*E ~6g%yGf(׫,Zk\ l%5v /b0 @MڈmE>\ RYXsC_oaTJ%_ "t,w8f Ertb˵Up!kE? SH@GŹ/T'kD8M/vJ)CДndp~y(\DŽ j J Bڡe!y!bV /0c :V?0w @5VGTHH[pAUDjk^"0nEiήz}`AY~!R֎;l"(Ԙ{c'f✽^?8BM/q1\^AJV, c؋y(/த*@Jɭ90# mJ/D%r!ДAQbu -֘WD 2DT(W7U``A^]y "Lw,VK+^x RqK!v!7! _>ƞ_>`ԡ|?JgKÔ0_"=_Fx1Wk0j ԓ cN8 F`"s ̌AA;"RMݡ(h8by@,l6J4RRJk3)>qCoߠ8q ֔#fΠ;AɊ8!S/9N V`\Y4P\4@9BLY1FḊXc4^+" qIkOzX0orACs)NpT@rxADD /pƆh@r LMX&_>P~#m- Ѓ .!.j,܋2x!tһyX\ڬ hr+3{t >֪3#<q`@ ۴+rXpo~b}'t~!B TA.4s3xWT:B8I?@ 3|8iez?B!h'rg/^5;5y3Rdm3Z)v`*5HˆcV[]sJH32rNFS% 10za-VTai(>%fJ-WXE7?@l*"iЀUXXV7ʷQPf1e|V8lA~ υ\y,;pրŷI [lE vK^K `~bVA}Vi,@)frާ&`6Q̓Z¨1^!?^l9$ހ]8kPB(qrv'gC@k(1aGYrG@ /Z!}f>u8aQ.Kw(~ࢉD3(pE XP'f?Aa@|R}uSײ /|zOB(a Г|GI3Y>N%ELP|zr>]A*0\+DEYv&'+L(r@E334`53݀_ >Q~! ̃s}O "_6跑Z; e'R_l(F "r5f/KC.'NB~hE+E_A\e\6B `xa/EGuz_r1"k+bS*rAF(\Q _빽[E Or1_o'1!+^HAġB&, (m,5lZЂBm0SEYdY7ϑ@oJ,QAF a6B@ Ae,Xd ]1ͻCAԶ]rVydqA19m<%ޠn{2A|/X(+Y!r̳)Tpd" sאJvH<| ƭbxί TBlaUYV9ߞ]6l%`b9 6 +:tr(tA듑Q u>;rT!'uHo x뭁.Pa.(~}Ѷ0cSb fceq?Ph\~ɨO^`~? Vr<+xB`ܢ8"ұ{,e4>"١|{EƦo};@x%Wa(|@i(|Bt OU177⸝_>PT@Qz3rؖ\Mixж0{Wӭ9-7-x!Z; ++xooDSF <} OBy<4!BJr> _: kEl|0Cq1b ,Vkn|2/c?[ywDZ! !8#fd ;ɜ "YQu}vJ±Z۠h[ȺU 5^T aOw+BP%oS/V\%} Rqt)~S`F.mx9 (ʡo/]"" Y!8^ZR;r3;pW "OW:QP>1 8[E"p:35 X>V(K̺9A@њ?aS0cmc GƦ }͔;ρ{9,a-Wcc| j3غ>M> T6=O $pLP 8>6J@3t-P(yrׄUc`>\є0fYȘÎf>/P=T zE[!"bD9r\ZN*_N_.0.-Si,_>0G/9"R+ "\1#o09X zݞT(kc16g O뜓Aā=Ch)36?`]Y.`u[rTװk"`/Ԋ8b 530W EpAmpR&M05B16"mw0YGY3 T 鯇L'+9R3?j-NUROjMYgrA1zQW%`Ys@=%#YCjr@k̅PmHU NJ&mĶ"B,P䊹0a ]J%_!jE>)EXv0%9`\:rm(\f(CRh#it~Aq Ux
 '>+Y!`1SlWo)"x\; j J B&P{1Z5\awt['¬&l%EL'@e3R=\BJ>eYB:2C(JOZӖ^x|9G0d^*|_>!~̇ T=0RGж 0lìqWx,m_(u9) ]! ?.RE8K: >ڻȧI10P %X~T((i|@ti~Oǜ:ݮ0f TuiEФ' .KEA߆ ! ĻU%0|}pB _._>^AJV, c؋y(O/pW @Jɭ90# mJO/Jz_eC)mŪ(AJ֢q^z Hc1XHerAD xhKuTrK+] RqߋRU 8yA 1^0#9rSB@$*uq}Bj[L_h#n \֟/\p F5 /p1'0B``fƠOT`h}Cq`4fShM4ԫG% D/ /\H;|&{Ŭ)x$9`h_` 987:]-,gl}>>)s `>(s4072x!tһyX\ڬ hWf +`}UgFJyb(m-@Eg8iT' P[7D. G [gP8UE8i4( ~e9?zKM _"S1'f^鼢yEsGeOB"o 6Up:uEzq'v-V.Ꙓq($aPvO\ (ObDғ *ym_> ?a?cc4Hq]o3DT*!EYĎ&&|F\4aa\Hl*h9/{A`Tg<=qX"ipwjHE!LX&pt;aZq__.ZgjZg3MTm(VE셽Fb0[Y. ^{~e8:i7T_>`.DY[NU2z1CP´^Hq9$O(.f2)BD?Ulo qtI`R{ 9Y}95U9 *6E/ ;bpFqd#9 }^>z'k FxMyތ?mVDJ80_#P;@ 1w}0+#d1UI[" ^B>jEL6So`&[xrUtZǦ""X*,, ǨWl(Z32DE>4eaqDm(DQA "ҹ-Xv~{!'o "ي%B+ӺTfJebN15`/cD?v~aY%u8aQ.Kw(~ࢉD3(pE XP'f?eV0 e_|zOB(a Г|GI3Y>N%ELPU0 R,BRLv+O9ewۘ`xE_}'QAEsEkPIbD X8;AQي8t/5+BpmE.ӦB&TBAُldC1kk+" -oOjQs^\m8pӀ_ۺ(~8#g⽇SB\M/`+'m#p_>: WԂ%)`M/(rj$)2l{C97ԊTL Tԛ,.D"E:4gI]lmHGicI44[OL~#$)'>}}n#7TYG Sw0|@! 2q,b[p4w##m,enNQb!r#yJAA8vP7dd^QVBgmSȦDp?,!C"(l:[H6Vޢ?Bh啀dηDMVeeػǀ!]יE!([{}2!*>v0 l?&t@>1}@0?n|Mdfweq7?Pm\V,|@QwVr]/|B#.! = e)>^K]M U9Q= _P `ǭ- 2rP%#&hq^~2>p 9As5yi9Ƌ 2xE?ݚ rrOuz@Y BBB@4Kltxg!] z_~ o1qpum7 =ůu- >] IGX}S}_M3gq"YQu_.0-Vo- vA 5^T kOw+BP/cNXAo@Rvf"|6ضmxdņrD>(ˡs"pHCůg=@EO&:o Dc"3pW "G0zFi,z<Esih.Ʀѝ>~D v:zk3>*46Uc>kvAz`.x`9X傊Zw-G6B|[jlVtK#9+WN!?~r]=߯H6 3 x !JgJsW!ؔ[jWk Hc> 8yϒz;b~*@.[%ȩ*"/^bp`,|;\]债 dkQZi,CPy&V8>azZ,`Ds&{>p|bvŎ>A3R.PU}kBK*BJ0h{Y+250&^ۗB k{WZ}u ) *ȱx_.ݼOFlۚ_.sCM/LW4Kky@}X5\P)}^Gyo޷/uL֊d=PnB*αbՏ!뽳=is"81ber3v0 W?݋ j]}ćƖU(u>p^P+∁܇߅pL\ѶmCaJ\'55_.5\`u<PAmt!$`R0!G*rGM/m[+z60glxz/ADz P#^GXkf\"P`O֯Ԯ*֘ aX$VP(y XsCu` W챁#gvbZl:\EXv (rKW[ \,zeԘBjm8" ?P+> 7ASj$N7uLHƌ >`뫞!xYQ!bV=/0c :V?0w j-(&vIS1 PŒePEJ>eYB:2C(Juv} > EAyܥAzX=i 0<y:<!B?U-̗ jGG(0kxô,L^yU}dk'E `CN"R%PJi"p\QcaJ{~blAoPsϤϤ~Oǜ:ݮ0f TuiEФ՛&``@8:^46ncNZ{қ'4 q" HqՀR3{AfDD=/pƆ р`iX&h`kiPZvI\C\ Y'd9 B*wp/,EYA7`Wf +`}UgFJyb(m-@{FZ "gETTA{7NyӠ2 )5}&qq6sPD PL(`ݖ(jEY^+oD*vb|;<`%E˺*Cp^ թc`؃<5"`%?/@y,\ (>'Aebi~esD< [&E觊 ~MtO!zpjK O+vH}@Dֽ"c;j2x)sj QAŝu_#8rA|NP)~2۶i0q$a1+ȭ.F:Cs+!8T ^\j`f ƓV_^{ UX0m OɿlᥒBV Oj;Pt/4` c+6|Lv"8lA~ υ\y,;pրŷI [lE vK^K `~bVж'/*MEE \P1 "Qc^ѵiЛ츆𷛎OjN ص!'g;X!95mӾ uTCӼ5 {_2#!  4µ0L8j70e #&\4h`(Pت2@|RU!`PƁkY_>`N> ԇ)BO.>N%d8w!0` L'}T`_!r eۥ_`[ `~bvm>'=v0 l?C=/|y?Fee. Pm;Q5~,. J^0?Ba}\Pz >jEEqAEwGYʬg|AEWxR(b"cwSo}w@}%#qx?y!q{wbuL.T HIZŌMOoFcx!P]Hc1^t_9` p|N(C0ovAuWuWt)x/0? 92Cz< _:g|{P=/`n;%8@Yֵx2j_Z?ݲPλ Y؇8 0CԊ^ HVT }vJ»Z;h=|ۃ'PzS.,=AA?\PPj9@Rvf"|6ضmxdņjkr(/_3i̢bKYT;rgw'^Ea^e@QlcuZ!* @mEo(>zE]by"f ;m=XDzNu5J jBBNe0C|g0x[<0,rAE#A!>-5p6} T+\`_p%@C} = 3dC *C^-g6c5Af1<?ϒz;b~*@.[%ȩ*"/^bpŲrwV0Ei٦ AM\] Piruw/8?vN=[!( Y|Œ!䇵8a]P/5h1kDqh@J~_x_.b%QZ@QH>QMyc0bEb ^@|@@'Ԥ/h(_sK]X/poksrlۚ_.sCM/LW4Kky@}X5\P)}^Gyo޷/uL`ݞT(kc1Ī}C{g{:dEq`csf?`][LVS>CcH׵WR3yHۥ 8qCl+ۅ" m۸Ô2Ojj(5\07"jyTM/T i3JK̇D5\ m˘ 0?iBMYa "_(ƑY/,5xc(B'9[d ]U1F^!3{ȱI@ȇ+>P:@+J%@cG_?Et@kp0% /P /.(\[( 2Y1.4pD_PBU| *HʼnoyTN}\w#C:&$Qc&)'@i6^V{1Z awt['¬&l%EL'@e3R=\^j ص{/cYXgg>^0W⼋O\&@8?xX Z}^+Ș )zH`nYmGG(0kxô,L^y_,YR_@ vyC8\P0ݽ %WԘC(l/Tq~@1Dq= k?Vr?iPs.t˜1P~6T&7@mK?/j)B{T#Q} We!?݋>T>Y !Uc/8\]I'T: Г[s `FB۔~_Jz_eC)mZ1S=?dd-PN~o HcmGWWH9/S2 +>U 8n{₪< b/x;F_.0sPBD%%aJ/B~=_h#n2Z2+#5`h#94-w1AA;"RMݡ(h8 jEm` - UX{R!P03֊ [` <,~`M٠P !6HqEsҒ\;@Cs)NpT@i "_.F_>e ``ld;?t=`Ѓ .!.j,܋2x!tһyX\ڬ h+3{t >֪3#V!0 /pn$8fH6`b{s%$^9w'#ܸ`[G۫A3K% +bw?64^h*,, ǨWl(Z32DE>`DQ[6 ?QTBt<{ _8}k^ۤBHhr8ĬmOp_U( n/4s{# f;FpV0j+Wȏ`n:>97`6To P7|LDQ\傹_@=/ Bg\`Z&`5X 2ؑl.H40}WU~bz_hU=h cqZP&2QRTP5*0 RX|_.Pozn7ٵK,L(>>0#O{ ňp^iHO "z_H]Jz_>P >k" :WDZN߲>P(mP W!?\ᱷuQ q1\y{{1f_W/:zyXKTeT=\@0<: WԂ`빽[E6$`?x|oVR Zx}"U >{%نp6z_~"Xf*)'>}}v |WPe_p 25zWȷb*gB &[슱oލtR "Qr2GYD_bSԠliio0}:QEj{2A|/X(+Y!r̳)Tpd" sאJvH\g n哕lN!y s='l-( /K6c@.j}=~"ckOF"D'aSL6\L! @>ku@(C\u\Ao>|r.}fq4A1.'?Pfc/⓻Ѡz_>pUP*-TD`?(K1̀?P?.`A^򁻊= x'q C?!qw့ebL>p T H$~rA1c2;x储G 6#T4ƋE^OlܖN(C0c뮐㽽MR&,x?p0? 92C\ _:xAH0{P /`V?Fq88z@U_m#@kX_}e[i w@q9 `0:?9}b>"gJ·ZkZ @힃 ]J"; 0¢;t^\~@A۫9'?[%]8ށf2_TrC/6~z""Yv)@b DA%~e4TfTxk إ,*W{vn5'^E a4.@Y4^ùb"Qz}, AߚQ|9Ĭ~D v:ۺk3>_$sD(Q(F*o$|]͠8>~R" \ P8'hŞ{R ?,/ i -Xh8C)Gq48} \_gVN{csdk1ZimGLEqpP{[E%P`8-`,|;|pKz/p|Bm/6t< %/P~ /$c!PR}pES:cԊ⽷?D9$UTϧ`::n_ZdnJ.!g.Ʉ8J[ٶ/sC+9@s1a *CQr/ C>G/<7wHۃuLC= P::cU?uɊ wLj!3ο,\Y0=[{>khlQ2[_Z(n`<770W Epm弮I薮'vB16" _>`u<TPAS[V6mP:&$Qc` 6׊H+C/+Cj=BĘu_`ưӻAt~aV~[Z QL"c2)u.HC %o,!z!:> "g"@۶BQEijH}x|OC*#ut mxӉ\ZxE*}faVt >) ;\!QQ_>P)ΒO(na*y}TOB(<tw], ((l*ä0X=cEnW3߯܁ d}6e 5P|@U 829+֕M 4\7o%@N3(0VؕsO\).[s `FB۔_.Jz_eC)mZ1S=?dd-PNo0M4/` @qn062s hEۭ'sjN85\ Qh`nd6B*wp/,ڀC4 aj\-}UgFJyb(m*kN}R"3tAS4}BJM/`~_prCPQ3xKfsWgy P+"薪HqӀ=h,r4召sKdŁ0}|kNDβcoTLŨ,qxEN}̡W= q`04 l u:{pQT+ zd o(@PeD ΕĈ'AT{v /m'짱 v3Ri5@ 9U)qHQc 婆8 j`ߦ]>@U 7,wy@nQp_EPh)>C(cSz0 :}`$9"(y?iyAhBX=ٱ?qX"ipwj>P( OC@8Lvt+eu "V@ 1]MP sP6(R(jEY^+oD*vb|;\`%X } jBuk 3ñO 9+yx"fBU@$?QE*3%Lňt$bD9,Daf2)BD?~bHV"il5\>AO+,S]X Zz"^n rH9:LUa@T::Pv{4셱e#@/mjq^S6^60#xSYGFbSo0j1Ĵ\ `ƁWF|@J Ƃ׵84m UX8ڴA3K% +bwot^h*,, PP3: 0㨹Ys%s A?DpD3(>%`B>S0 e_0 I*hpq J8 e9W /`: X|ș_>( .5AH(>eol`Fɢ,@_eeŬ J,QAF an6B 0 W(o $(KP?s-W(_>(w@Lw ӧ=@ZԍsƞL, >'F9^t)Te" s')b*VgL%/<2++ȜoϮ ҋ%v1?;l}.jҧi&P?Ra띑Q u;rT!-gn}>Z,t|m;e`,8|| 5@ OJ~8pW|r:+>/4@r5"PAmڝE@E GYʬ{ d?cK}(+2U8>Q+=(@{Px38n]x3X1Bc"I^!OU!Ou\ *o=0ַᖀ͠Ңݐ!jElqE0?/p w,. 6)lm'q!D s_Pr|3 ڴ.1Pk <@H>"`c_/p~};"?q>.Qc`V=b5P^k!䇵8zsCA߹PJfZP2ׄUm`>\єffYȘÎf2u>0;D qGXA] "=X?/жlPmky` 5<0E_ /hKk@̩4^5 0G / A_b]]a(\EqԜsZ ,B\l!V3uɊ cZJ}0 W}^[j[|hlQ2[_i `/qq@kfal_=5 ~ݎ@0!̾nG2*VcHQ@kpa`Jz_y_.dQ<pp!@53 FP|]<t@A5P>/`{_&S:ԾI ~ @Ԙa J Bڡe&y!bqV]/0cnOCzۚbb}.)B`*8T0#n!TiN]m̺? "gq"@q%[zeHy|OC*#ut mxӉlwWc S{aVu}uvvBS`&v0=< E(@)dcŧ0AoPsHѵZۅg`"CI `AF?56iEФsГ ._({ZBWWPU3Gq g/t@^!ؼ"^BO|} *yGX5b!J>2ތOhn)i%W)} ,ʆ8BS" @T+"*YyyF3#SaARBd{~'E[ XZy'Zߣo 8A 1-y̜:'QɮӾ4Bj[_F@k2Z2+~k0j eGsi0Z# Ƙk`f Dj w@1 FS`1>)VОS)TTR`8<;xZY2;n49uJV qΠ;AqC^rz5`ckE!uPi>`@:jP  2b^/-^# {alhy }^>ڒ5#c$8fH6`bi=T%]cZ_^ض|Ԋ*,m Oɿ﯈cjm-fLED*,UXXV7PTr8u ) <GԖ"O< "+6 o 9Y|FZUhVO"ny<0Ow`~bV>Op_U( n/#J^(Ljs#Jy@+B5]xΎk$ހ]؎kPB(sv'8FNP{%(:/E ("ruL!GH3}p- 0>wY0PDCH40}6WU~bӺ_>P0Ux >)쾺C)iƁkY_.0~ P''f|J J8 \E2]A*8e_!reۥ_&`[ `~bvm'h @u7p|<;#b53݀_* ^ ‘19nPt"G?KM+9FZR_@wroP>H[1P>HC[6Z{/EAN@i : X mE+gv쉷 {1f_W/:zX֋P) n{yApE-XҊEN;E_> OA97p1DH(>@MƝ,.zG"E:4{I]lZQX9@@3cgf,z"]V&[̺ |$-"*]!?-PHT&΂@L "c߼79P eydqA19}#KAA8 nsbDX cEH[6 0`p T)d6#X5zab7EPB#g)ha}_&@YxYlam@{}̇N^DOĶm̩B&Oe&to +[] \P m/`>Qb87PrQ<O^`~̃B԰~\O(}ru"PAEq@E{,e<|@ECۥơF*JuWSGmyP38n{ <0P,13] F&qk*ǭE36*8CoFnrmAs8 G1^//ltk&`͓<\rrb[є.ex;|Iȱ֮d)5@4b~4y _>q[A1b ,vdP6Di]qX}JKŌ;"_M3~R+r:Nwm3Tkk9@U8Vkm g > va4r}zmԋ4WIT]JcfmdD}o, Duhk.>HVl(zAbXf(4TǢ/2b`\;evwN^)M/@<E5@QlcuZ!*Zivt'aj8n!0{&OTöfϘQT|$Z_J/a / cJ)ǯB#3"ٰupT%a@Ha-Nr8'ƭ(=4| %kGВ Ṙ+rl~,{?D9$t>v~ 0|Wi:+^qW8.v@Tc/ж/>sGY_>0TnYrbNÊ 1G/9"R+ "\1#o09X zPnB*ζbՏ!mٞ>YD9~wbL`+@מGg{k0YMպz-9' YOp=V7ޅD"h>CaJ\JQr׍ PA}T !$`R0!G*rmk`~RL^K/ȬzVre\-(B'[d ]ko85htoXH@b[W|Bt-b%W ՕJ\j1DGq6 7$9"_]:r}*@Q5E_ SHH s_OvDghq4h<\s,|\ u q9MoY. o07!!3 DYI-MQ!xYQnW"kr3Kr|"okZ! PŒe&4ص̬ۖ[QZ;՚z!8V W>i /<D|~R[Vh[}NTr"L+R0= m(un) '0E!QQT'P)O(50<5J!Aq#DjmqԂ`Yc3^ǠHTu̴"Pwh9A{Ϝq8:%r@WZBWWPU3Gq g/t@^!ؼ"^BO|} *0V iX%=P61zrkNHC(LQɢ\l#4}(Bp@"J!@8zr#>GWW.H9/SvEJ+>Q!7!4cfNʷwQ@$*uq}Bj[ƶh=cbHi Ŕ ^(\Qc f q hX$6c1(hUD;4Zs6MyGby@,lml1HK(m/@9cs!j7`O/yA80_f-u"sqK]llݳ#ᓊb>"d> "RWcn60F%N/|hb׫G%kqd.@@Ta93 " XAơ'X&:/fvӐ:]-,gl}>>) `Z! D"L>{^H8?"˂3W6+AxA?*3p(6H)OR  q[AUQA5|=h[+{8 *`R/1=`ܞNcus@t:-η8 F%o[Nl /%7TewrA|2mHQ1yE>PpTDO*t, BҀ%@ԩ+E8@0naHp0gJơƁ  Y$FT/= =:o ?a?mshbOv`g̩JTCWm&KhaD0/AOKɱ4E"xP NC LX&pt߿):$E1<==M/Dx tc[mD PL(`'QՊWވT}b|k^@q5BurP|L9P^T_>`.DK.f̺Tʄw A cJ F`[af2)BD?UT7@wP:jY¥-(>Nzwak鉬{ELҽ95U9 *aEKo:nH^[6B-YC-n02vkCkf"RX`*5HˆcV[]tj F s+!8ʈ~2UI|`,x]K ZQMD)70qLmŌ<ـ݁H² D`ƁU "88lA~ υ\y _}k^3BHx vĬ}X4Q^9GPvjv~uLjj@+B5]xΎk$ހ]؎kPB(sv'8FNP{%(:/E nGO3_~ !}f>u8aQs9-c6AfP ZO~w**L/'] 8p-3|B7S\|Jqo+)B`*(4"_>wW N_>+D( .5\dͥO6ܽo$|(ll^o(FT?û%OSxEΕ5귑;hiϣ"R<@L6^ih9}f~Rc(G T-l4`*䇦8ZWEy*^c4\ J@F(\Q _P\*s\tqzCԊT!+^HAġB&c/ɟcp6Ě_g'`4 `Fɢ,@_eeŬ J,2Y!Lm @ a(gB &[슱oލtR "v@Q}L%t!,5(&"5|%`nt`dd^SX cE{e*زiO9 kH*EPx9 ƭbx TBlfUyV9ߞ]6-r˒ `asIB8Ia3)#R D0w̩B&O.:$r7.Fe. Pm;Q=]Y\Mq#0>|Aſ `~BԵ>JO(=pDr5"PAH- *"6 e)>1 *l(+2v*| }N+{;(|AwPx38nu/<|L.(_drk 0? 92Cz< _:w z_~ o1qp#W" }"@~ JZ>ms@,)a/`0:2?O\{>C@iZPbDz"̃'PzS.,y \~s z"Gݰ{,OccV>7Sfc"`:rhV(ʡo?=7# ޱ*BpRzg@N\pW "G0z@YB(buZ!*3Pc M;D}\.1Gknz>c GSD6Q "z_> *>0;Zlt)VH 8\`_p%@C} 6N8YyG?Pr|3 ڴ.1 Z9~[:L-6rwY.0)[1EP5f n#V'X ?V vkpnc9| h@J~_x_.$c!PR}pES̲XX#@ԘC<kHz_>:+~=.vATc>\@Grlۚ_.sCM/LW4ͥ5< >@e?jy`_. C>G/`s<‹!0 W~[jZ;uO}> {;{A#^33BQ8@h>CaJ\'vB1 5\`uc?PA}T i3nH3r-g?j@hZ!6;{~6gWD82En$`Ys`kܷ85v{ႹozD @!p'Je!b%W }q*fD!<;LO,*l:\>/,;}"g>Pl>(\zǢP@)v@GŹ/T' 3_ܳhJVL|b*Y0WCДndpq~)\ AԘa J 6׊H+C/+Mj=BĘuz_`` :V?0w j-(&"s'@e3R=\B4ص̬ۖ[QZOZT<>:!+V@ZB: /@/DdHy|OC*#ut mxӉ\ZxE*gaVž:;eP5m07sPvF14_]i~}̵`"s 8\v1cؠcC> BOV&`TLŨ,qxE37`s܉8*{'`:}!jqD4$`N]Q/b\ 8q KZc8<e(j7JQ$Jޖ<冟694H]o3DT*!EYp-+>Nzwak鉬{E:jto`NMUa *a_>Pv{4셱e=;xmH#cl0dm֊Ha <Ԭ# #YAuv:55vbZ?k)^8*'s~i0z]GѦ ^*i \a@%GBVaaY`(>zEi# QMY>eEy.4H3Ch-v~a{!' #-@-C"يIDyI?|b#w(a 1?v~uLjn4ЊF;x (?^l9o㐀]؎kPB(sv'8FS od]vf8-4eG9B@jW|Bc#aQs.Kw(~fP ZO~w]5ֵ P}uSײ<|3|B7S\|Jqo+)B`*(4K wW NxyWEYv'fn.}D_}'Q DEZcp޴@EaߞC82&G} VƩ "z_H]Jz_>ϣ"R<@L6O"r5!qp(⨵pC۬W'6Ŝ}]BֺbZ/~Byz}  (2RGZ`=\ȩku`۠}VRg&Nx#U  .6-F (m,4%"}&l`Fɢ,@_eeŬ J,{R dj"`!v7FG3+Br,z/1Y)jPL6DNiioPP7ι{2A|/QVB{}$RM~*X8\C:U`!rA[Ū_h啀dηgGME 2˒ `_>PTz +:tr(tA0H:L9sk:$r{Eݻ!|v P,WdlUx>N+VOA ոРb5L&<-booq;|aT@Qz3r]Ay@E\Hc1^4^inlyr:}@YwE3BBBy ҥL6:\5x/0? 9d)5@4b~eAH<|{PM/~ o1^qpb_P%ҺOp{W0{!8-fVt8@+U'9ZPbf_`uS'PzS.,y\_((y{5ǜz*ذ@,>G }o, Duhk.>HVl(zAbXf(4TǢ/2b`\;evwNZj9_>y((k89~봈CT~Pcۀe![3O"^Q|us٣5~NgqdVTa1Bc"IK"_J/a / c@0(qs{M!ؔצ}w >0s6g3R~whޞ# !2UƁy:o T\xbηrpm)Ei H>"`cO/p~|;xZl"rP~L/pM1( )> |)f̲wY>ÎffoH|L`א0zEѭw&Lv; *ȱxhۂ6r_>0TnYrbNÊ 1G/9"R+ "ܶ-3sɎ^LJVXH"x9%5Cl۲=ib>`s<‹!flYtytVdV\ 1WkH8-`< yZG lxb>s domۇ{8L)_> ~2n}@0!QE/ @~g4*9R3E/m[+gz`&߰D/Ȭze,>1W ɵV"YCjr@k̅#">9V<ЇVP(\17na}@XɵfJ|b1DGq6y>X8( g,>ȁŖSy…L^@5b8"/(}*>]4je+Y!`1S!h|Jvqq~)\ AԘa J 6׊Ha G~v66kr3KOYmMPk1D1B"x`FJݲ B"PB{,KH/3XgpL!8uVX P"<DdHy|OC*#ut mxӉ\ZxE*gaVž.l) ' /`N4`L/az E(@)乡b]~@1Dq#DמG?>Z09qaPs.t˜1lP1ӊCݡI'g]r@WZBWWPU3Gq g/t@^!!?E*[KV,n`{1Z%=PԹMLܚS3J0Sz@T(*Mi(\/P=?dd-PNo\H+TkWW.H9/SvEJ_.`izwHQ(aݷ  /b/Ќ /9u(}!DO]Q(Ul0 mhb}bbC38`F,1*" b9n^)vpT i4\Ѐ MK,D/Ð:]-,gl}>>) `Z! D"L>{^H8@k)XEYA7`V pf "4޺9 :ۭqL- 'XH6vd*+1|RKWb*Fdٌ+:Wt:c;GeOB<¨Ҁ%@ԩ+E8@0naHq-!*ՀBd'7!P:ؕĈ'ATx4|o ?a?Heko!2*P1)"v\ɃPj@Ê8nOm9Xpo~b}'t~!B TA.4G934EPh)>C(cSz0rͱ&\AAl>9sG})0"lC!;B^t܀#'y/|怊TDYxĉeGw;gt^ "x BhEOk_ā0$9EH^F,ZQ_>PÜofYB\x9[!? ^- ؃b?5"`%O/p!*{w"֋bDDp(G5P Y@ڭ8"D:jY¥-(>ݯc-=uXXG̩*QA(4(ZzpFزg/.) YZ֊Ha <Ԭ# #YAnu1ҩ75vbZ}0+#>W T%]uF/ UX8ڴA3K% +bwot^h*,, PP)쾺C)iơn / i_='!z3@ 8!0tvh(>=`]A*8`9r,xruͥO6ܽo$?4cc- 3rqtll^o(FT?û%OSxEΕ5.3cKC;hiP !hwɆb~hhcx 0*M,\r6_ /K쉷 {1f_W/:_>ZWUO(OϳoPA7@/H+j6X빽[E nr1n_okZJQ|Tz#d@w#Bpx*h2@ش3$$ZЂ3 H9YE뻬Lus>_I@_.p 25zWs˷oCP8 1*`W}nxP?s@+ O/8""ŝdCi.u+ '$+|N(+Y!r̽>S`˦Dp?,!*EPx9 ƭbx TBlfUJ 2۳K_.@YxYl  HEMwuOvzg$BT|B9Udc/0Y_z;|5,|'We/}ǀ/0x+ib>^C]O^%?pe'?Գ^JW(]\E9ݢ@EGYʬq >KCiR} N+|N_uOAջp3|X|=s*_.(fU?qԇ|cx!P.Hc1^^ie1b8>̺+ 1-hJ2cwUI1&/"x/h(29 B1rm!@Y%Ƞm(~Di xO4t{fpVB֞8 V}HVT]XJ·ZkZ @힃yzW/T wێ*(y{5ǜz*Hѥ6.0(C@)31mx9 Ɋ P7|PC.D _X!8^Zv)^]v `_>p}pW "G0[aE (~N:-mf+n7BqC]Kz ߿'b}Thl=:@a30ii R ygNe0Cܽ=|ַᖀ͠8>~ )Gb xSEN#lR :O8d*C\Hex$V&ZlqꁈkӾHcT; / 3I{{@6pTT q}9UEKXs_>@+Ҡk Z{[ afBDE_XO/mk}vr _.R傡[<`ġi.-@{X\0}*":PZEqԜtmۇ{8L) _.?|`" _>`uc?TPU(~g4*9R3/ڶVH '5~Y?c4D>/ȬzVrcL{ !ؓka#YCj*֘ GD7\9V<WP(U;V(VrP]U1{lkO,(Φy SwŖSy…Lq,eԘBj4pD_Pk͗>PI +Y!` 0M/d|\mASE p#$Qch-JZivheEYI^GsܾU,D?f5Ad\RTp aFJݲ BKJeYB:b] EAy XP%^pO/@JÅ~R[Vh[}NTr"L+R0= zm?PίS 5NRrDEq@EK: >0T$WԘC(l4& cni@tq1ׂ`Yc3sQƌaVM?'=Y}>2l|P URU3Gq g/t@^!ئ8B_.@7BVBeqw3ca3 /0axBH)mb֜PrQɢ\l#4}(Bp@"J!@8z#>GWWH9/SvEJ_`ikD*G/`m?BoCLa _>@93B O]Q~PHm1 0 mN/Nj)Q @_.p1'0B``fƠOT`h}Cq`4fSby@,lml1_ G^J rpCo_>0_.pa̎[8MyNB3h_l}dE㮗^ ZQAgGf]k,{~.!,1!AC1^+"uE>&hcTr_;rACӌ^ 8*y@rxADD /p[`Ѐ,/G4/` @qn0 :]-,gl}>>) `Z! k e@&1^H8*@, \ڬ hr+3*6Ne3i̇U)iZ- "{*~bz.` :N8*rhPLq{ނ{8 iqIH6*yp{?@_Jyo8ӯ<|? )M/"S1>5Wt:t OaP|~AQ=б[6J– Q=r (v1e 6ײ` (H&{q]I^zD%m7rߖ~~`<#ŞVtSe;ڐMy!+»+>طiW7\߿:n_ ݲ|DPUAuE qgP 3B8I?@ 3|2r*#yh9n/Fmh ~rU6ޓ#?.%ҼIeSTpNe2;N:@G e/Dx tc[ P6(RbsZjEY^+oD*vb|;\`%X թߝ P|L9PJ 0<\p!*{w̭b*v%Lň+1G`[af2)BD?UT7@wP:jY¥-(>Nzwak鉬{E:jto`NMUa@T::Ea00ҰƖ!{vі7;5e! m3ZiMvSYGFbSo0j1Ĵ\ `ƁWFɈc傱uM/^ض|Ԋ*,m OɿlᥒBnZLED:/4` 2Xm"0UDQ[6 ?QTBt</5`/dipVA$[Qc<yI?|bDYp{ WB9FT۩ s#Jy@+B5]xΎk$ހ]؎kPB(sv'8FNP{%(:/E ("rK G9B@j@hskaqܬo`%`N?Q# 8|oBҠ`0<FvUت)iƁkYi_='!z3` / Y>N`SA /*L'Tpr9eۥV|][*w1xO}}#@aF.o@\ >Q~! wG7(J:[~7+k٠FZR_.@wroP>H[1PxEӷl'9H/rK5 P¦NB~h6b@SK%ˆXx{m^̩U!.ċ X(OkPA7|a #uO/Jz @aX)9.H~ Ǹ}!jE*EyZPA덐w PTCAώ@1C8JKb /-[h@ >T60#d{2bg+ j1., Lm @ AeqTAbw#ݳT]KEi(w@Lw ӧ=@ZmNTL, >'F9^t)Te" sאA"(XH<| ƭbx TBlfUJ 2۳Kuyee]L/ B8I.N^DOޑ0 ll?C /ybP8e0?׶0u d1 8wP|rW(ﱗO\ɵg]+\t'>p! 债>e)>1T$ .]P,WdU>pW@DW/$9I 8(Bzx&g2r.P%#ZŌ='Нxlz[(i9Ƌ 2 nlqrWu@Y\w\i4Klt;]R@`~r d)5˹ J1tƟ 5xJD-"b}JAOZ(~Di=B+/V1c;H+d^.RfO/~"YQu_>`tc-( j| wJ]aS.,y"򁂒Ws̩+h.Tކf?ec}3e`F>!C/6^cau"Yr(ۈJ;# Ʊ*BpR~,>݋dv8kW "G0.@YB(q(356؎Dl[xE]by7"f ; 3MD B8l&- /D*!O5 *8L=|ַᖀ͠8>~ )70O/p Iq@ A[ '},@eQŒTc5kE G86K48@uN۰9C`#&@0mܓ]p>@۷JSUD*_n e1M/ Hee"٢p/|ֻ-WZ3FP5f n@?H0cm $p[ &x> bFR>@ʏ\d#BJ0hʷ{Y.?hlp>p;D xq"C;B+HqD9hۚ_x응0۶Re>j-r#Msi?,ގXK!FOp A jbpf? 936Gu+}w>0m(}g! ` n G/&w8peLVS`jݑwZ4<jE1q 1D"Ѷ}Ô2J~mw(/ *!OLVZf>H%Zΰ|@hۖ1`~"Y?c~ADP- +bnT 䪘=}<;LO,x*.l:|9`ύXξY|B3.]}r}*@Q;h] SHH s2*> <:`4!`%+r&1S!h}78{s j0f%kEBڡW# ܾU,D?f5(BVf-{ *" 5P+ʲth2C(Juv}ZT:[mqxz@N/D4KU>2vP6`nYmo`:Q^0yFL/[HEI7Plq` ?$**"^ Զ1'@)dcŧdF(qѵǑ Vr?iPs_3U381~Nz|6e٠_ 0@3_BzU%0|}pBmy@#t~7BVBe9H^#Dq4xO\)ML|3J0Sz *Y[1)E-Xcz~^%QZ? ^=TyVԩ Ry<r ^B2<<+>*T"^#5 1M/{SB@$*y-1S~*6xLL|Bhb}bbC3POb+#94-w@603~H5uZ+@1 FS`1>)VОS)TTR`8<;bC_>0_.pa̎'QDlAv`S'+0wj֊ =;B0Zse@}s1eaYP  2b^0 _!a ض+g~hEZP%\C\ Y'd B*餭^bYpfAs܀ \ 1uޣc "RӽCi{EoTi- /'!P'qUH/P06=oA 4`>޺@t:-η8 F%o[Nl /%7Tew@|2mHQ?Y6h="CNDQ=8`04 l u:{pڍ`uj@!G2 ؓ\ (ObDғ *m3Yo9g~~`<#ŞVt*!EYĎ='_",}v@N?)tܾ@e?p 6BQ+3TZ '%.cۧM*#؊} saml}?/O yq.Vx@! apwj>P( OC@8LSN:@G e+@ЊȽ@> .o#Jb*E>(VE셽Fb_.(aηfYB\ 2W8! cl,"SH X _.0 o0Yf̺Tʄ(i?i8W9b(G5P Y@~'t y[G 0[t%ŧ)R.c-=uȘiBZ700| *a_(ZzpFز| }^>ڒ^5;5y3Rdm3Z)0q$a1+ȭ.F:CLϕfxeܝ8*sK@cs?m[GѦ ^*i \a@%9S Xeu|p.CTg<GԖ"O< "+6 o 9Y|FZUhVO"n9|%0?1+h'/*M|x%`/cD_0070k1 "Qc^ѵyxAϚOjN ص]b@(sv'8FNP{%(:/E]@ /Z!}f>u8aQs.Kw(~fP ZO~ZK@|R}uSײ /|zOB(f Г|[I3Ym%EL%2 0 R ,BL/Po_`[ `~bvm'h @u7p|_cucp޴'Տ3`s#\pS^se /23&_CLC*!\yт\k"jM-Ikz-_΋=\NM,\mE+':B\] 8,-ST /t_.H+j_>ȩ˻U 6(`.9h@7BVt ޑ*CQM^hcp6_%"}&l`Fɢ,@_eeŬ J,QAF an6B 2q,bUȽȡ–Qf֥(enNQb!rGHsnsP7dd^91d1LI-TptAB1nƳM`b7EPBWV9ߞ]6e_G@YxYlam@{X.Epz6u^(BT|B9Udc5j>"١|RP o}@x%WqP'fqj\xYd/ԇ8>yZT H$@op"ұya/Л8e[¹xж0{Wӭ9-7OT(C0sv@uWuW6oDS_?xz)S/0? 9d)5@4b~4y -`;Ao#g>r%Ƞ'-Di=[)-3B&Cp~y3~28@kmɊ`tc-( jmbm"*.Oz7]Xtt"o8TPj9bU"GذY}@XLYAmˡ\X}@P|x9~Bi5E_Pe>.eQګwt{R9{0u/> (~N:-әmZi V(K̺9F@њ?aS >c GSD6Q D*!O54^9_ -x9ַᖀ͠{ w7d觭q> _>J)"'A6)lm'q!D 37h99yB:B) "M#A8P}a96l'`#&@0m24}9UEtXsh:b}2usnoZlQ8z9,a-WZ|WA,(3m[B5X}@d3X ?V v6L8DqhӮ% ~!Fnk~q@QHQM96c?`Ŋf:;D 1*V tܾ4J.!q\쀨 _m _U۩|`H ݲ#MsiĜJcU?_>0}b]]a(\EqԜx{Q]Jd] ,B\l!=LyZg";F 8pelqo&ZWo%Gl}r `/qq@kf.|  TѶ}Ô2y SCi tрmqQHE.}T i3Du0!G*rTP _Z)3 Ķ"B,P䊹0a WїH"gߛ)Z0\!:eWMDe.g{-T"Siv+PίS ZIQހ)m0Ecaz E(@)dcŧaޠ8k#`X@q̹ cưAUL+u&}>Mv_, >XB2w_PU3Gq g/t@^!!?E*yoirޑ0VGhrO|R&&@Ob>iۥ)+Y[1)EU Q qY&ɝiE ` ")'e*T.Xɒ8{!O޵ "Gǣ`vprb [0@@36`ԡ|?JvEz\l_} #5_.@S.xp F5 /p1'0B``fƠOT`h}Cq`4fSby@,lml1HK(m/@9cs!j7`O/yA80_f-u"sqK]llݳ#5W=  {Z{Z !AC1^+"(☓֞Mvܞu"ffjQspd.@@Tr gDD/ul?_.@d 3|mϻxzM/Њ[O =wl DpܑJq:i#.~E gzQmV4 aj+3{t >ADJyb(m-@EgiTT؃5NӠ2 )// `mq{ނ{8 N 8zPAm&  [7Tewo~' #Ci(RqE*bO8yE>PpTDO*t, BҀ%@ԩ+E8@0naHq-!*ՀBd'7P:ؕĈ'ATx4|o ?a?mshbOv`g̩JTCWm& .aa\Hl* h'rQ_ G38 yAH7b biދE2ߩ9"Q 2qb(5AaΕ2:Of=\!"ro'еjl_>%@1uDpV+"^y#R[q-|,K~uT(z ^Tgc9P@T֜<|"…s…,Y*BPpe"`?' '>GVLO~M4`VpjK ϭZ!B~)(XKOd+2fZG̩*QA(4(ZzpFزg/mjq^S7#Of60#xSYGFbSo0j1Ĵ\ `ƁWFɈc>D0>G^ض|Ԋ*,m OɿlᥒBV Oj;P3IJTTaaY`(>zEi# QMY8lA~ υ\y _}k^3BHx v_O ' Je3x^ Q;``n`ֺcD 7hEƼkBqŸ5Ԝkq *C7v@w0(;)jDQ\!yaE[n_.p#>X Gz, S( !G$qh*gsE XP'f?erA|R}uSײL/ i_='!z3@ ,'"NC_*Nzw,B^)ʂKM/0٭0?1psiE} :w8>O/ *+XGŒ7 erBD1q,ݠ(lE~j+BpmE.K/iFߠP} b5|ӷl'9H/_T 6upC۬W 932/ ':B\@߀zj iN ŦTHM/H+jV6] 0c$`?cܾ"<4w@w"8UPd%vi1:fHGicI44[wL~#$)'޳}}n#7+ QAF an6B 2q,bU_0+ [6>GYrETϻE &;E Ɇ -] 9W@ucO&H# JVs/ϔD*%Ȟ_ m"ړABTqX5k3[-b)ha P^l4_optEr™ ֑ؔ{ Qض-9Udc/0Y_r+b]N'?pveǀ0+ ib>nC=p'/̃|p<Vr]/|B#.! gQ2"٫(-./c|0P!8^Zv)^]v `{_.] +@t߿(_e2EmcO̺h.Ʀѝ>m^Q|us٣5~NgqdVTa1Bc"IKJS=/e0C|{0x[<0,rAEo-A!>-5p6} T+ew:WN!?~rɆ͠>N2(aQTc5kE |G86K4;@r'm؜!H{{@6pTT wJܾU"Rq%wKX,9/h1Rs&>i@Gc97AH(\] PiruxE@9@Ԙi36C9>yGp|ŒP中r=j} ( De2& A2E!zGW4݌},{?D9$s>;D xyEѭwWZ}u bD9m /?Pmk` 5\0E_M/4!F!k"R+ "\nlFz`nsTױ0{_< ` n G/&{8po&Zo0WkH=-4<"Ƚ]y 5\mۇ{8L)ky@ގ{@0! ̾nG2**i3JK̇D_.ڶVH '^MYa̵^/Ȭz?e,^Eu!5hGȱ]̩"B,P䊹0TJ~o]O,*l:\EXv (rKW[O( 2ޱ!Pc -+#\k vA'!3_.VB56EJ Q0WCДrE%8{s j0UEi]+"g(e&y!bqV=/0cnnDջCUC@;R4@P(ҡ (-^jMܾK+B}]g}m8?xX Z/q:\><)7zH`nYmo`:Q^0Hô,L^ׅ:;eP$`{?$*d*"^ Զ1'@)dcŧdF(wHc^+4(9u]a6iEФsГ .K?/jlP!Xu_zn!{!opz{SeFZQ6XH徺2@D 7x ,VpV^wbHQ(0[BoCLa _.hf3{Bju(`*u{} m=&&~e{1eW>11 `X8`F,1*" b9n`hk6Ha8椵'Udo@cb׫G%hy 3"tP-qxh@Lr<X&h87Li-,gl}>>) `z_>P?\ x!t&xe^Tqvz_p%`ưy!6H)OR m`NR"3/ m S4}BJ /`~_> ni|n.N'#٨msK  ,0OAPpTDO*-,* 8[DN}_ĸN_qT+ zd o(@P;nr5t+?KOm=/m'짿#-EjGȜ@8(qTBVāwW|5oӮ-LYn>"D*ܠ:"…8\h@(}e@KB!~_.9}`$9"(y?ir ~rUȋpz4E"x!*Rei(' `uy-H8bx& {UVN} *hkNEJ~^Y}gPl;OTD A z1">GVLORۺ_>4`VpjK O+,S]X Zz" hBZ700\䰎/(Zz(ea/-M/!G[Z`dהHٶ HkETjǑǬ ;@ 1>WBqsw2☪ky`,x]K ZQMD)70-Tozbw?g*"yxn0>JnNT5|B'ڲQ<Ds&Xv~a{!'H "يIV6- O ' JebN15`/cD_00ȘcD 7FyE6?k:>97`6To `*QvS4^2, vQCxH-Ҡ!}f>u8aQs.Kw(~fP [O9`2@|R}uSC r9g$Ro=84VRTPi(O/UO/`:_`"ҀRO/0٭0?1psiE} :w8>?/cc- 3rqtll^o(FT?û%ݞL"qwyҠFZRz_@wZ<_l(F "r5y ӀK *z_.0[& gvobN; q!^t<qpO:!?<1BǮ(ŦTH偌Q| 6] 0c$`?cܾ"<-F пBpx*h2@3WZЂ3 H9YE뻬Lus>_I@e"*]!?-PHT&΂@L摢 8̻{CAJP&Z8""Vb!rGHKsx>W@ucO&H# JVs/ϔD*زiO9 kHJMPQM`b7EPBWV9ߞ]6-( /K6b@z +:tr(tA0H:L9sk:$rg-eS @+mg@L,>p x u'0>yk\Bz X| >\=!TP=/[`?(K1"٧\vw(b"cϨ򁻊 x'q(~wP38n{ <3|X|=s*_.(fU?qԇ|cx!P.Hc1^^ie1b8>X} ++x)]dc~M^ 3DH^PeqpKAOZ(~Di=BSZ(fli,Mrh!?@mEo(>zE]by7"f ;ٶ.`X[OqGCiZ`T;|t9\m8DT6RgݧO[8A3y`_.p%@C} 6N8Yi7AE9V&ZlJjojE/Ę, >s6gL`#&@0m24(qTD*_\"H-Ŝo 74ZHee"٢p/|ֻ-g"\єo3,Vd,m50&^BK A[!"}>XO/(ض:S)`H nY1a *CQr/ C>G/<7wHۃuLݞT(km1Ī}C۲=i}"8`s14+@GgЊy.?CZ;Np@#^33{!(c S| +Z xnX& _.:a(׍PA}T i3JK̇Dm[+gz?MY{@1zQWo%`Y1 0"{rߺ H֐5|5h>HU v3P(\17qoa]HE1O,x*.l:|@kp 0%M/ș_x>Plr >@\X1.h4:8w񁨠Z b%/ƆPZN/D|\mASE p#$Qc7+)\+"m|{,{"pEsܾU,D?f5Ad\RTp aFJݲ B"PB{,KH/3Xgwzu_z^}]g}me_GW8ԧ B?U-DZ ֱut"] 0L{,uLt ) '?@ vC8|"R%PJmka*yFVP %ynXlnP Qs{TѵǑ z `%0(9u]a6iEФsГ ._>PP|@U 829+֕lM 4\7o%@N+TUc/8<|VI'T.: Г[s `FBfJ/D%r!ДZ1S=- E}xӫǛ*0Ҋ:'R5],VK, C8 EF}kA b)lRʫPBD%%aJ/B]_h#PZߪOL55`hr#94-wc503~H5uC;b)0G+hcbpF`kcF_@i{)E0fS| QsO[ZY2;n49uJV =Ս֧NVa1zɱՀ{v`ֵBb>"d> "yظ"9iIo4`_.|hb׫G%_. TDD /pADyh@r #L|87~T>Lwk⢆l DpܑJq:i#.~E gzQmV4 aj Xgmc#+QzPA,$K ; 2GY`r4Wb*Fdٌ+:Wt:cZ 쉞UXsҀ%@ԩ+Ep©F?[X0R(.Ꙓq($qlEC}س]I^zD%m7rߖ~~`<#ŞVtSe;ڐMy!+O8ύjQ=oÕ :n+qjle#B p9N/ 4b_!"R|PǾ6?(ap> lUAV鼟C`Sn4` O!,H\OKɱ4E"x|"Q 2qbY 8W8A e/Dx tc[ P6(R(jEY^+oD*vb|;\`%X } jBuk 3ñOSH ښS =\`.DY[NU2z1CP´^HJ FT3>ɂOf-"DSAz_@wPSsfu B|Za" 9Yu iX ut9h^ i cF]^>ڒ5#cl0d1~m`FZ+"5R>$8fH6`bi=8R3c8<`¶-VTahQ|J d /4Zn ~R݁#yxn0oC"`C4ϑ]*bDm(DQA "ҹl,;րgYlEn9|`8Ĭ}X4Q%rSuLjj@+B5]xΎk$ހ]؎kPB(~;X!955nmuj9ʢ[pwH-A /8BR|Bcp,\ f])Q# 8|%`B>S0 e_0 I*hpqo+)B`*(4\E0\wW N_.`"g,x݊ok 7>YGLs(r@EsEkPmcc'nȘwGbZ~7+k٠FZR_.@wroP>H[1YUC\ie3?EͱGzpr^0$yrl4`*䇆pxhKG0RkpF_>?=a/}h X(OkPA7|a #uO/k"zn/V`۠}VRY,.zG"E:4{I]lZQXk٠@Zp?`)'޳`ᓢU̺ |$2<djo($mbC8 1-r8ZGAg(Vr2ydqA19}#KAA8 nsbDX ca/ϔD*زil ڀEqAB1nƳM`b[A ]^ XA|{vmؔ^N/,,0$!]]ԤOL=~"ô;#0w̩B&O{IM[r%;geS @+xmɾcq,>p x u'0>yk\Bz X| >\=!TP=/[`?(K1"٧\vw(b"cϨ򁻊 x'q(~2 ?`m/'x&&\-U1;q;\P3< ~Cl ] xӶ>p^Ol89:] BBm^4ҥL6:X0? 9!T^/ǀ?TD-"b}JAOZ(~Di=BSZ(fli,MRfO/ܷ~ЊdEiѵXo֠h[Ⱥީj(rLWW_>PPj9bUKm]`1R+C@)31mx9 Ɋ PebA1^\;.i5E?Pe.`ڳA4v/ ܃~r:ơ PJ$hJ@f}0CPc M;D}<^Q|m!0 ;ٶ.`X[Oq̓jarATۂ8L[ -{@Eo-A!>-5p6} T+e.q:WN!?9 "Ha3h ? !Jqs{M!ؔ|Ԋ }_""1xD^+'m؜!-Ϲ jEE_6nE `~Bʏ\ZrV!PR}pES ̲X]^G3e\ `8_C"<\r@#B k{+HqD9hۚ_tN-M-! _.iF҂ Ĝ/ 1GC|"R+ "\1#}o~`nsTױ0 1m(}g!Zg[` GߐA&]/½.4|"g9]@Tp!k~@53 FP.>4:@AZd_.7< u q9MFw75eDެ`sBH;,$V#D9n_תf iHaV~[Z QL%ELOf-{ *" 5P+ʲth2C(JcOZT:[mqǖl P%^Uu@-Tǫ+PU3Gq g/t@^!ئ8B_.@w/P{#d%@N+Tj11 `X8`F,1*" b9n:($ ZQr\`%E˺*Ck^T@/ VN} *hkNEJ^.rY}gPl;OTBb*v%Lň+1G`[af2)BD?UT7@wP:jY¥-(>X)(XKOd+2Q+{c=sj 倢{@ 7`a/-B-YC-n02vkflf"RX`*5HˆcV[]tj F s+!8ȹ;qLU5\0m[GѦ ^*i \a@%9S Xeu||2DE>4ea'ڲQ<Ds&Xv~a{!'H "يIV6-R>Ĭ}X4Q^9GP f;FpV0j+6/8(YIIנ2P|ct>NpSJ!eQu>_r6PDXr>3: 0㨹Ys%s A?DpD3(gsE XP'f?ATay >)쾺C)iƁkYi_='!z3@ ,'"NC_UN=U EN/eۥV|][ɢ>f} D*+XGŒ\ܽo#'Տ3`EIg+pӽd mE.t /0:O5 Ũ4e3?EͱGzp–ӳP¦NB~h6B<7K%ˆXx{m^̩U!.ċ Yl'ٷ noPlJt؀pE-x96] 01 OA97p1DH(>@MƝ,.zG"E:4{I]lZQXk٠@Zp?`)'޳}}n#7+ L/8BD+䇹 IYVAbw##\L#pETϻE &;E Ɇ -] 9W@ucO&H# JVs/ϔD*زiO9 kHJ,$|(ƭb-#JތA ]^ XA|{vt ؔ^N/,,06 AGWtr,CQ{DJmiwF"D'azSL6\L!| PA۶0(=]Y\Mq#0>|g|u-Jw\ !TP]/(.`/pxǀ/H]J{X|5\/:$>p$OA%drA& >-U1o@1cר2>p 9ʶ9yi9Ƌ 2xE?ݚ r2Vk\w\wo@4Kltxw.xc=y R꽗@4b~y| B1 ؃y68@Y%Ƞm(~Di]qX}JKŌ;"_M3I=q~}rѵ*Zsg > vat]mDcNXAo@Rv߇!͔EضmxdņrD>(Əeb| HCůw,z/o-TE2;E*{R9z_@;ʢ6CP :-ugƦѝ>m^QmCGkNum[0c} @ B8l&-=/D*!O|@Tz[閟L\m8s_Zw-G6B|[jli+bE0{SȏcvQ Ha38 X^z'/%;Js{M!ؔצ}w |`w}N۰9Cds´#D8P8PPT#ܒk q 6>ZѠ,̵=94obpe1=#p^Lh @ZVw#@߽,Ajr "ey@5f n?d 3B`ю^PwEq)P({ ](m@RS+n>`{?D9${|v [`1q"C;BWZ}t ^w m_U,ٶ\0_.O4j@1b!F|!5@) C۳ E!CL}ޖ OuDq1bi29@~`5UkQe~]oܫ`/|hE1{;@1)5 ڶ{8L)5yf_74Ԯ*!O !Zf>ʑJa|Bj`~{~6g| "buQ,9-T`O[d khoxrLt h' 3oԕJ,챁#g׮~bȇ8_."X{w/P_>-^y =@eX}8"_P@U| *]Z U\!`+`] PL%c9MoYw7:.$Qc7+)ض !Bڡe&Z}1}n{ 1Xz7N~Rջjb!0f-{ =4qZ=P%CۗXg^jz!8M+}tC[,t⃩ .PSx|bHy|XC*#utKGMd.g{-T"޳0K[b_vNY6󤾀loxEK: >0T򪬨10JecW"a@sϥ{*>f-80ǜEnW3 *3mp;4c jl{/56֕ JJ`Ƒ}pB  q݃Pv/P{#d%@N*0VliX%PyR}=5f!ar!ДCQb}E CD%עqnwTQG[WH9/SvEJ~ ҖW|"G賂!7!Va cyo/Zfl;VrP@H(~lE@sYHi  7 p F5Ay#94-wc503~RHk wb)0G;l+hcG`kc7U"3)>sCh7`_.~/80/ ޔ-fϠ; dEW9vkE!sOEbY byaԊ|MƨXvܺZ=in`F]35G |7 H; r gD 'X&:}7\X&4`"\C\h,܋*@T餭8yA,EYA 2H1D>ADJyb(g !@,؃ `@@r21(.,fz" TfcJ F`̰eR~ZaP[*C<FN tE vwVȱȺWd̴BZ70`/N)Κ<@{?3e_0ljrA|%k FxM`czmT+"5YGFbSo0jbi=9'S/5y`¶-C+Ppm OɿpSIB O(OED: eu/Jn<D>DQ[6A~RQA "ҹl,;a{!'H _e_[= ΋Je<Qm&`/Q jEƼky츆gM'xvmc;2DeG;EC(C8R!y}o|bq4Л{/8B# }p- 0̩!v$!EfPJ%`B>t7L #[ {0|4߷JBPVL|[IS P|G<yI xx_!r/Twz2݊okN.}D_}'Q|/sje:?3,N|NIňpwtQq8W\KiK{tz|uW5(&ѹu4>e3?Ѣ#]rC5 PZaS cuQ|C5L 06`o=q\^ qQ<~բ<-c|eT=ҡ/B[p<l\PSs=wK]tqz!"Q|G *h;)DUPЎ?Ŧ!@h@ >T60#d{2Y1>r(_I@[&WG SB~[ !L A1Y "؊otR "x\y PQG`vLgɆ64w7>hEj{2A/* cE/{e*زiW9 cHnG P {L%VoFX.g)hazÒ `_3Y B8Z-jҽPQ{DJmiwF"0wiL6L!cր/T8e0\Ak]-b 3/O?`|*2.{y/(г^J{W(]\ꁊ {wH ȬEOvX|3|஢?p.:}$^IQ'Q3Dq;p3|@,~=sA)A1;PvrgTy>8G9ʶ9ŊYHccԻAWӭ9-7{@!zk> wuDߛ8 l0C?ъ>ܻ~N]XT·ZkZ @힃yJw`*؅EwO+BP_>pu~}6r  "GawY|1@)31mڸڸꂊd P7|Pˡˢ4T| !8^Zv)zg@NWKHpW@S aj8]Ը (pN8@w NQ϶uWGkl[0ccPSD6I/D*!Okr@Q|trq`@QpKf}Zp6} Vtz[.<JUȏꃜG fA~ xP(JJ|^-g6pz ڴ.1Áv >s6gO{{0m2}9-EW[ŲmV8/s&m Y-JveooHV|ǽ,0z8hs_r1fu+d}X]E/$O6@~v6L}^xl4 J\@1ׄ}!R!zۧ0V4ی,+26sH}&`"굕q$:cb~1J.!=eD9ж5QQ `/q4 \PXe?_.^xHVW 9xD\1#}w~`ns0wӆg{R::c/}C۲=>"3F 1M&0c{ k޹lMZŇƮrTO@8p~@+∁̌ /mSd hj(/}؏yԮ*!OLj(G*rCx )Dç%H/qdEJ<7 0b"{J$kHm_> ,H Dvb[+>P:XɊA]R8Bxv~ '.Њ||^ S|9"rPQnT@UHmG#ŹT'a5_hZ(-/D|6)Hpq~)BB5fzzvhrEYIV#D9n_k^f r|Rջjb!0f-{ D)" 5V(y{e e(-Z; EAyhZi2-V@ZB:_.<\۫ @C*#utKGMd.g{-T"޳0K[ľ|l6P\QEEqEK: >0T򪬨wV z9[G a@såѵKc}_+4:eFؠ1C> BO{q/x5_h =n]@I 82✽^?8By\@!?{*E*yoȩBe9H^#8<W\)uN'o14fJ_.J.-ДCQbu -֘[D 2DTr-PNTQ%E*֕"RNT|]f/cD*K/`)5 1*lv,{IscPG?J{KÔ0_"D=._F@k|1Wk0j q hX$6c1(hRDZSwh0s6MyGobyX8lml15 RC`1q`=l@h8츂7:A%w6gЀ_lu"sq׫^ صvώ9'؃q`O1@̇ₛ\(CD>"lܠ"9iIo4`\in`F]35G 7=B+d^T@&/"N'mueU/ ;/X 1GcD{)jqR[D=b=H {m T)p(`SH_/8F`mq{{8 q|>IH6*yp =hOINjt@|26HŊTLH5Wt:t^*~_wR= >e04 l ujE݈N8}?SX0A(.3%㨐{  n9'P:ObDғ *s9["@rOOc83@e=}!2 PbUQbǭ6d@xB V|5 =?:niq>Z j` 'pDBs,a}@ųs260$]U>6?&|f.cۧMU檠w#h'r>fp+wP<G cm!戠"*{Ԋ{ai[z69ߚ)e q.epܮ腱Au6S'$Vx`_.0 *s0^Ae;U(W1G`̰eR~ZaP[*C<]8t%ŧ+,ST@Dֽ"c7ATC:*>v2{?熾3# {al@|%k FxMy,~2۶VD kLE>$8fH6`zs$$G)RK ̌y3m[ȇVTڴA3YᦒV h;Pt:/4` Cq-6|\vB*?GԖETTBt<_}k^3WA$1z"nY'fmO?|bDYJ0x%`/,Ljj;5;uLjjV0j+6xΎk8 t|97`6(Co `*[(6^2,r좆\@or|qxr>3@q8aơY91Ďd D"\B?L`0y >F8`8er9g$Rozx94VRT78`r9!Ҋ.E|eݥ/0٭0?/ x~c} DƂ>fEk Ȳ87m&IňpwtQq8W\}7"@59uW5(&ѹu4>e3?Ѣ#]rC5 PZaS 56 qXi K#j1f_/(t4^ޯZc/nJp<96XT\q$`?cܾbHE Zo..zGJGE:cvi1:fHGicI\ z u f*r=wYus$ʲ+QAFo0|@!iCY H, ‷?y PQG`v;aZ dC䴷GHKsxӉV'$H`%Ws/}J"l41"BbV5Jތ. - s=;lJ/ZX{TPlۅyXҭ73ȇB8Z-jvX}lJcȽTEmQP|B95y:$x=իTeaOZ?p򑠘q,i~1&rT2.{0?⓶\caܛ6-&آoV*B*H)Ȭ xEG6X|1 ЫzhsK[^9  ~9 !΁duL&3A)A1Ҟq2cT(~⨏(@4`XQ8ir:7\tk&`}4Aef[ HV!׭m*-8c>MNPfR}9DCU/:xAHs=h)ԓ0wB3,vdhsx('P薿?X8&`0wS,Hso(_Vxw w>3T/]XT³Zh=ToDv:G'T Pǟno6vU qbVзJ Rqt:vilԕ!ɔEضm\m\jd P7|P[ u7>F*>hEo-6^]v `@pW@ӻ+> PnÙb""Pݙ NQǶW8F@њ?a۳8?0Tht  Ⱉ-LZ2A_(*-aZ'p|Bm6 e %L@2ׄ}!R!zۧ0?pD²3mH/`zy@P{1n#DqGq *ȱx @}/̶{e972}z

ʑJaTk3Z!6Y?c{);#.uVrVU9-T`O[d $֘ѰWȌorLt h' =P}ԑM]R8Bxv~ '.Њ|L(>Pkp 0%_ȹh -4pD8d7 @TP}eVrLPL%c9MFMa1@ԛl} C+Mr!bqZK/,D?)o5!Pc-p}?!H[pAshbB{,KH/3DEiZB+BPqE'VZ} XMiY S)ޯ-XRjo0i HRm[GTa֘"޳0Kǰľ|lϓzj ?(_PDJm c>L%ʊsJT6V|]6?1Lcsi <X@J+ 1gQƌaJL[M?'=? ؽ-T[W()GCy W @!?/} #=(ݓ4PR}=5f!0S{e\9 Mi;E/v\E CD%עqnNFWA">po2*mYCkM|b,sU# 1*lh1 @3}e3T'Q{oqfK(&7x@7(\Qc fPLcN8 F`"s ̌AA;"ҚC h8 Apb*kdM(m/@9c{ yR: `ev\xB4`[{b*ǮW6vݳ#}>h9BLY1| Q1:/lZ k2A䣦)vpTϠ/p~7 N *{3 "`: {,2tѬX&{eqn0 }:TJ6@ZpM٠8 T餭8yA,EYA7`Vf ^Y]. "IH6*yp{?0 Sq}e|LM kt^鼢9T8*{'`:}!8ZN4BDn8u#űpxeT4Թj@`+?KOd _&@rOOc83Ri5@ 9-U㨊;n!_ q",X >M @UA 7,gy@ "NP"…x`p*-~!B8I_@ s'&(c_0WsD s9LӀ#P;BxOT9HZ/=5(R7qNe2; _:AE1<_>Q+Bp ^|]&x_&@ۈ@LEnOGikEYWވ-/q}e,!.^ @06"rtK:$ȩP~T$Y wVbI~RT&Z/fJ֋)W1G`̰eR~ZaP[*C<]8t%ŧ+,ST@Dֽ"cauto`NMU2@T:zy@&{4셱eSB-YC-n02vksgdٶ H"RX`*q$a1+hn0T(v32rNFSlb*:J0zaU"OɿpSIB O(OED: eu|8 >. |ڟ#j"O**sy@D:Wme/5`/di5FOV6-_= ΋Je<Qm&`/Q jEƼky츆gM'xvmc;2DC %qE!e뼾WX f8-}8B#z(4V-gZ&` \ "Xth`{J*j}?1idSESȖB;UƁcYpI4? $A ޠГ @ljh(^=Р2]A*hv"2@EYpwiba[]pro} D_Poħ޴'#/g DIgW视^s_>w#-tmC; e57Q)pkPL6s^)5#}q VZ!SȏcuQ| 1Tl(»'6Ŝ}x XEyZ< *[~ @p #uNԂ/X] 0lU.H~ Ǹ}Z(>Y\\"*t(he%bt̐ƒ_>KE-L0SEYdŬ %U #DToEnەB+BPuSCub8鞥DEm e/8RTϻ,5  -] ~hlAi|Q=9 _ ~0CmıMO>-Rb$ZČ]OQߌ AVwE,G1^1^ sy xk|!Z VEFSZF CHI1ߋ&(3DHw_P˻@(znm<zr@z\ Tgv*Ƞ'9@ړ/(t˟aX8(Bjo0=F^ 1/ AHVW E^q/Њ8b 530W EpAm;pR&o#vԺa!gihde( jW}h&[J|#h98h_h`~{~6g1@#.v#r,ӂiAE>u!@bY {H D "V|B$3VԕJ,!zw=P qU< EPkp0%I0"l@suOp]] \{T.d[!PcR[h4:Aq7]$dф\!`/` PL%c9MFMa1@vEi*C+Mr!bqZK1SwhO z[MBL"@Œe&.X+ʲth2CTl} \TwEm>CurxHy|XC*#utKGMd.g{-T"޳0KǰMz`C=O _`8@)O(50*+j! *RXmC?*)ɖ !|AtX@J+ 1gQƌaJL[M?'=?iB h kD%%0|s>o8{{ 6G{@%9U, c؋yGCZ%PyRjo'\44fJ_J.>ʆ8p^QskT-"*s(W;U`ap{D* "RNT|]f/|*TRր_./93BO㘞L\ 6LL|}CƔ^cbC3(_p1'0B``fƠOJiMݡCq[Ni3fW6+0z<`%`ưsCH)O[j`R[D=$4`A}iN@BJVEJ| aTc :]-ηsd- c ; 2GY`-_.{hJXe3t^鼢I *>a daTiA G.cn8u#٥zdj@!.IQ$Jw6(~[n ilyF=}!2 0muizy'+»@ Ӵ+r6! j(|융3PF߀3xGf!*cUz0 hmX6U9"Vչ?iߋy@T!:nҼISs",< Ae2; _:AE1 ^P6SQZQb/\n9y@Üo/e q.epܮ腱Au6S'~1J~<l0 ߻dn4(R.E z1"#~T uWLORGy[G 0pjK OWXbzwak鉬{E: iXx储 ut'熾3# {al|=;xhKPYdm3RTST4HˆcV[]tj FP 1>GBqsv2☪)" ^o!ZQkQ|J dJZ"(~@|*"ЀU(, 2Xm"0GU|ڟ#j"O**sy@D:Wme/5`/di U=Z`|\0;0?1+h{k&ʂ >>x^ RVvYU8yРV0j+6xΎk8 t|!@P|ct^N!8Q"Tu^_`_.G@˽_2#D9B@j8 0ܬoJBn,H40}6W*z *< >FVZ6`8i~~BI7@J T|8NzwX 3,^Ԉ; `~bvɥO6^T&m$ywFhvBԛ6@bD X8/V6 RW视^s/ nE.U}Fݡo( P폊Hq[b_'HCS6-j=˹ ӀSȏz\ͺ(B\_. n*\6bݻ {8*i/+UxPA|Jp<l\PSs=wK]tyEi?B+Rq!+ ޑAQQ.6-F (m,Ҡ@ZW !H9YE뻬LV̺ WqUЫ7$kapfv SB~[ !L A1Y "؊: BP?s-+ _.pwA1Y)j &"=@Z+ '$H`%Ws/}J"l41"B1n+VgL%VoFX{`%`S6,a]_>ƿ$hE編I.@E!(Oޑ02~/0Y{\p>'7y2)_y@ ^>|<dfoe;_ 5\UyW>`~r̓BYX/`%+.Dr@EBr"g,2c@?.`9] +2*} N-|pp~ Q<L&Jr.(%(Fz'.>Pۍa/D}ԝxl8?(4K9Kd'@1c-v㓫:]PY\B[!ۼM׼ ,x? '!.!}9DCU/Q4܀?ݣ"wgv*Ƞ'9|Aٓ?PRH=38 *d&Cp~p} at]5a_H8BTHO;#?hlx|v |^/(]XA~("}b r,/mkRmr_.RJx傡[ <`Q\*rA1\0b07!#Ra|0yO?8<LٞT(7SR16(6v['șĖk<…L^*@eXitO$d-XVUQcPZ Na>S_ ' o07u\H q@+"g(\# ܾxf mf@k1쉇SA-Q!@Œex&>@5V(y{e e(-Z+n_!8M+}tC[.-2<`>,!:B#&tR2a*^ iջq}6U 5@|4c_>`t@!NsQVԩ*/|^&vAFJk|1Wk0j q hX$6c1(hRDZSwh0s6My?aXA{#(>[Ep(qLy;bC|` \,̎F%B4`[{b*ǮW6vݳ#^k,4P}]4!,lb>`h(6Hq8椵'%V2krA #"wujCpd@@Ta9'+NI˄P\5<xֺ/Ԋ[Otvp qP[(dx!q:gcd EP, |zQmVPYOVucV)vK-@jKC=ARTОp2h{8 q)|/A06BQ=Gn>ۭqL- c ]7d*[,_.Vb*F}eٌ+:Wt:^_pTDO*),* 8[D%tp,؍`p0Tϔ[X (%=8ՀV~#Qn jrߖ~~eٖj"sZ%yY//pEXx7}v@N=*,O}#BX \Q/ 49 >2C@E Q!I_@ 3ͱ˦*sU;G؊}:Ô> ~|`rUȃpz4E"x|@JQ 2qbSۂ" <y BԊȽ@> ^x(TD0rV {Hݲ׳8pE ̲{Y2XzA ^Tgc9UN} *s \`.DYw'*iPL]bDG$k #0v+4`VwՖ@[,% Zz"^BZ700@T::9'3e_0l | }^>ڒ5#cDQ[6A~RQA "ҹl,;a{!'H _xӻ>0f.xVvYU8yРV0j+6xΎk8 t|97`6(Co 9P'|\DQ @or 4y! Phskaqhn7p%`N|7]$q@>+U~bS_ adK!`)iQ rr9g$Rozx94-\Nm%EL)ݡV40I x\WpwLv+O̮]8ɢ>f} D8Έ-v\2 87m&IňpwtQq8W\{̌]B PP폊Hkv Ũ "rjctprnFPZaS 56 q1T/vobN;^ qQbx TBlftUhy%`%`Sz:yea]__op @Wo4KUT6E'az ll?YCҍ_>p!NY.:'We/(&܀/0x+i1.'?p̓kBz+Y\t'>p*B*Ht(nP$ .zNi=T,ܻႨwK૎~@d8 ?`(zx&ůg2r.(%(Fz' "ҷÌ_.;#(ۂl s#//nie(c.p|rU *C0cVu+x)!"I1&/(3DHq_P˸@/i 7irƭv(@Y% 6_s('-t{fpBjO rVNZlQu|ZbZbmDp̓'PzS.,C=\l쭥"D J^1^J Rqtzv!H03.`: 8 '= P|Ÿ |_wQin(BpR.*W{vnN^EN_.@ 2&9~봈z},e9[Ŭ~!8 C/ l[0c 4?)ևBc+>nJf>S/u Vtz[0_.p 'A6upd!UbE9V&Zlb@!Ę,xe1'm؜!<<>Z&@{Fg~"S)e('}9-EW[Ų|_VբlXny&ЊdE8x;읢"`Y?q>q/r1fu+d}X]E/$O6@~v6L}^xl4i-P(yrx\d#Jm |@9rHÎffoH|.`z>@)V .B c{WZ}t >wD9ж5v]ZCJ \0tK8jK_.(j,_.Cx!_>lupZEqhs}rnjt\ug:ɾ^6>۳ E!CL}ޖ OuDq1bi29{@sk0ٚz]2[j ?"{8 pL,hv!0L"i׍(PA Ӿg4Zf>ʑJa@mBJm0?~6g1@#.uVrY\1^ZoH֐|@bY jG {1%`ȇP(IJV J%@b³kvA1VCM/"Xww/ș]}@l(\d *C*#itOvDk؎& (-EQ0!h}6R@ܽ`n zEl} C+M c׿^8"ǎN~Rջjb!0f-{ ;4B{,KH/ PQZy/pVPTwO0-m  XP*^/P\)7 zH`nж 0lEWa{&`i׹S 5@3|fN j:^0Eh9BLY1| Q1:/lNgqIkOzs;xGM3v3ROG% \A8nyv:QAP-q4Px, |`h9+Ŷ5< l"\C\h,E7^HENx^Tqv_.0cX׹!Zuf-0- "pIQA{aʠS4P>R 0_p5p0㮛Dۮ cAm[nvd*[,_.Vb*Fj7yE3lAGeOB"`& J– Q=r (v12q FZ+ KL8ՀB]2 ؓ\ (l'1zIݠ/m'짱 v)k vȜ*}ֹ0PxB V|5OӮo Zª`K p<[j` 'pDBs|3|P 3DpaJf.cۧMU檠w#h'r>fp+wP<G ^x"CLE=0GikEYWވ-/q|,!.^ @06"rP@TK \`.DYw'*iPL]bDG03l!VTַ P!Ocfu]m DUb}\r' +{c=sj D9~"0S i c˦B-YC-n02vksgdٶ H"RMvSѬ# #YAnu1ҩ75v@1Ĵ `Ɓ[FɈc|傱o!ZQkQ|J dJZnwu?bw?>t^h* ~6qA Oec'y "+6vrUh*jl[_>0;0?1+h{k&ʂ >>x^ RVvYU8yРV0j+6xΎk8 t|97`6(Co 9P'|\DQ @or 4y! Phskaqhn7p%`N5QD3(gs ZO~KTa@|"l)8%m8p,xs[IL!kB,/'"_Q 0 R,~o09+R1qxkN.}o @u7p|cVŒ,޷ Ⓤ՗3`p+pSwR nE.U jr7Q)pkPL6s^ih9}f~EͱGAA_?6up Qpxl.HL7~.JD=]x=qx:v 2ؔarAF(_ Co8 [c nr1n_o`1V"h@7BVtx#%  Z_@ش3$$ZЂ3 H9YxwYcE/( zd-,/Dm @ Ae,XJV}l{Jq-+~n"(&3E dC䴷GHKsxӉV'$H`%Ws/}J"l41"BbV5Jތ. 0 2۳KuÒ `ƿ$hE編I.@E!(Oޑ02~/0Y|}oxe]N@m;Oyu~,.|܆zOn%_ O>Xɺ\ SQ _>o]`/pEf}<7 ^Sb"cרrz ޒ-Rb$ZČ]OQߌ A&E,G1^1^ sWӭ9-[)vSb6q.ZWRz|`iVoqsſ\uk9B*gߥVMwB?ݲA x9 "T͠v' Y%@*Vc5kE |.VD\%F9P=6l}fD'\4": 2J>U"ū?-bYvrpHVҲ]cۛ@+/p~;^[NZ|WA#D6[!u]"'X ?\-qNP&`?}\@ & G )>]7 us ސx<οM( !Lz|@P"D =J.!.vATc>hrl[_.s/LѧjK5y{h\lupZEqhs}rnj=xPq%`ӆg{R`NI ۠mٞ򴁘pbi29@~Y~C՚ u>p^q@kfy \m=ɚ|#h9 )DϧfmZ "buQ,9-T`O[d kh+dFz7<9&l0O({sR 0=6pzw=P g^ W+7O(r/.[* 2y UPcRit5n@Iq"`%W/S:XmAS"sSXDž j0f%[!G~v66wt['Y&Z !&{!TPKTH;RTk@Ym_fb{`AyhZim8?xX ZWq yZ^}Rjo0vN'SCBH+j[GTa=iY{uv'`/TQQ\{I'R|J^5Bl]?ٲ!1\/\`X}8涱F?56t̴EФsГ .~\ ظ{T0;I`Ƒ}pBm2@!?/} #`{1h{傂PBHs=5f!0S@TrQQ6v(\n3s(AJE Ni^yʽuepo2*mY,my'߱"G賂vprb_.{rSB*@佷8L %B20 m_@SxoQ ͠<yǜp;Es ̌AA;"ҚC h8 Apb*kQ?V!P08w0` <,̎ZlM)Y *Av~AɊ8!]rz5`cӭ2ҹ@}urc!AXc "lܠ"9iIo z<{ifjQI?eB_..5 5@ CfN3'B:; Y'Ug/ I[j"(>W6+0z<`%`ưsCH)O[j`3JqpӀ=r? 4u*4P>R0_>pﺹ@l>p @EQi|Խt8~@~lT%@~ Aa~+Ge*[\ Д/"S1+f^鼢yEsj'zV!OqdaTiA G.cn8u#٥zdj@!.IQ$Jw6(~[n Ov.F*]VHmd%Qe)vړ?<8\ j`]p sp<[j` 'pDBsdCs,-~!B8I_@ 3ieS*#Al>Psaml}_.A\8A,{8^=5(R)P&N,8alqܫ#{/DZ7t51mD " X' ,^+oDZ8vY}/P gPc^Tgc9UN} *HZSE%W{p!*@l;OJD A z1"#~T -8Q ݊#B<]8t%ŧQ}\r' +{c=sj xh/-^# {al|=;xhKPYdm3Rf}Iq r믋Nm!HH32rNFS/84m Њ*\6So`&+TҠr*A-vJSNBaY`(>NE|\vB*?GԖETTBt<_}k^3WA$1z"nqYAhx<@ +{a9FT۩ f;FTAZ¨1t^h9;nD38$`neB񍝳x9?J\DC8R!y}5@ f8-i}f>Bcp,\ Cs+s A?D"\Br`|eD;8%m8j[_>`N}> ԛ),^Nm%d |[IS~" ū<yI xx_!r/Twz2݊okN.}D_}'Q}̊>@6ұyA|R1r,@tvE~jxn!8W`K!_He PPjjw"(&Q5DxEԂr7=5x 0*¦NN!?r6 qq~HL7~.J. {1f_/(t|zz^\-p_.t<: 'j95s{yD OA97hE*<Tz#d@whwJr.TK:bbt̐ƒ/ z u f*r=wYus$2"*譐o($mb*gBPLVbg##mYLr,EۿLQ19%@P7_ԍ= }c+D>% l@UaqT`!{ƳM`b7@B++Ȝoώ.ҋ( K6b06 AV/ *BP3)#R DB u;rB&Oxe&t ӫ!,3'?pve(&{݀0+ i18r}[| >Y8g|B+Y >}|! ) ^Ȭ]7 ^Sb"cרrz ޒ-Rb$ZČ]OQߌ(@4`\x)x{^OlS !׭V6oDSZF ԊT_'!|/|!\1{AzlmDcNXA+@Ru70*C@)31mڸڸꁊd P7|P Ÿ|`EbK=@4w `{\9] +ȩ0@YzCP[?'oq @m A40^Q|us=Z'tkzk3b}(4  Ⱉ-LZy R yZ0j\m8u n-G6C S觵[8L(\;h Az ċBUrk~^-g6s ڴ.1s.;_. 3'whޞ#(Lk8Bd*󆺀O ~*wKXs\@+x @ZVw#@߽,a[NZ|WA߽,L֭b,>a@HL q 0ٽ p|Bm6]r/P~_./$c!P*{??n.Wd,[zV1y<߷!` М6+g.6>۳ E!CL}ޖ OuDq1bi29@~`5Uk1u>p^q@.O߁p`_.mSd_(~hr4Dhr׍(_@ (OLj(G*rC mRjO%H/qdEJ\70`kP=Y go%5/H1 AHPK o^+>P JV J%@b³kW?q1VcHr}?Pkp0%_.|@l(\d=*C*#it0QAhآ֪^.?ѴG0dиHRH->JQ~mDʐR{OTF mxIl=iY{s;_g,yR_@ vGHt@|B)U-V {0JecW"a@sϥϥ1kD,Ʊ8涱F?56t̴EФsГ .~\ ظZB[W.()GCy W8B<^FJ*T;` ӰJ]41zrkNHC(Ya{偨\l#4P!Xuz~n%Qɵ@8ݩ2#Ui{D*֕"RNT|]f/zwHQ{)0[( ,i734c_.0sP@H(~lE@sYHi  7 p F5Ay#94-wc503~RHk wb)0G;l+hcG`kc7U"3)>sCh7`_.~/80/ ޔ-fϠ; dEW9vkE!ZseQ1ea,CDG輰WDjE>&hcTr_;{GM3v3Rz5ਤA_ |7 H;(ai/2/L͚|˄\ !7oAqdZ`-C\q !AI[p/bYszUFV pf "ќkq ! 7v@w0(;)urBtoؠ"R[@!R|>X f}WTSn,H40}6W*z *< >FVZ6`8io='!z3Г ,/'"<"x]A*|B_.( .|e&'f.\dQm3O(}#0#lloT(#c;(8+Bp{AߍХC_>g :mTD+ :WDZNhQs.9BP(ӀSȏz\ͺ(B\Q !'nK!.=y^ޯZc /P:_H`|傊빽["?۠}X Ⳍ 6lqq;R"8*Сώ@1C8JKz4%"}&l`Fɢ,@_eeb}Pۿ*xeG SB~[ !L A1Y "؊otR "x\y PQrwA1Y)j &"2bFӉV'$}r J9^W-}Up8vT`!{ƳM`b ֽkCu2Ò `|  HъoQ].:'BPj;L{3!P#`N+dd_`I䣬ox,|+%m]-b 3/O?`|*2+ 0? !,J|Wz"D9"g,2c@?.`9] +2*} N-|pp~ QL> W˹q;@3C@ikk9UVk ZYU@|B E{(T Pϟ}*xȩ+h.T]ކfmdD}O, Duhrh *-6C= A1./}8CDkE?2bKY| t\Gp(rjr:L PZ!/Q)fjlBc֝>m(U̺9F@њ?a+=XCT|haҪJPTz/0`.x`:X l wgݧOkElqw#/X P w,.6T͠v' q kE .VD\%Fcn+VN۰9Cxx2}simGLzv]yxC}O ~*wKXs|VK @Z-Z(={Y>`vrzxE/9@Ԙi3غ>\.(Tr.`@Hznv6LVs>hqA(<c B2BJO`>v ~B劌f<>p;߆D xrV C("}b r,/mk4 `/q4 \PXe?_.^xHVW 9xD\1#}w~`ns0wӆg{R::c/}C{TgLl#U Y8t:{;ZU* `hE1q1D"XxѶCaJ,rAM Ex!Q/U i3nH3H%Zΰ|жZ!6h~Y?c{{1̺(ڍ,KsZ05ܧ85/XcFD|cK@;ȇP(IJV J%@bPxv~iY!ޱ 0_>EPkp 0%_>@39rPQnT@UHmG#ŹT'R|2Y㚯jq4T-Vr\o@1S4eYQw7:.$Qc7+)ج*C+Mr!bqZK1Xz7NgIaV~ Cɶ_RTp(CR %o,!ھ:[Wk>"]4~iշ`Ƞy O/D|~Z=0RGTh[}N}eY 0L{,m:uvJ+>5`Vl0/0ݽAUVԘCT z5]O .=\/`X}F1(381~Nz3g;56:@ UqJJ`Ƒ}pBm@!?/} #`{1hxJz\r9ML|3JV)= *(׷bNCSE-Xcz~n%Qɵ@8k40REWAn]y "Lwe+yK[^=V@(v[BoC<-FЌ=S>:IT[b!Jlq6Z/Ǎ)(\Qc fP\cN8 F`"s ̌AA;"ҚC h8<:;l+hcG`kc7U"3)>sCh7`_>0B_.pa_f) *yfϠ; dEW9vkE!sObsO7P|xEٸAEsړܡi; Qӌ^ 8*gPxq </(1~*t 0 ض_c3R-,gl}>>z0ąV½8"L>{^HENx^Tqv_.0cX׹!6H)O[j`R[D=%~b )*H5 ؃5PPi}L!/`~ a j4`>]7NW 8zPAm&q,00<L *R"S1+f^鼢yEs}IpTDO*t, BҀ%@i\J28q &٥zdj@!.IQ$J\ֹP;NTе;CdNK8,oKO(Ok@!Wāw+>XZTpeAm8B,ny{X \Q/ 49 >2C@E Q!|d/IHhmX6U*s6#h'r>fp텰 q7b biދE2",< Ae2;~1u6[T%^0V@ 1]M-/mD " X' ,^+oDZ 8vrY}/Pk]/! cl," թO$@I+r \`.DUnh`frA1v)J|esDq?+ [&Eվ;T:jY݅CW[Q|";Eջ +XKOd+2fZG]!-SSU| *a ZzpFز)=;xhKPYdm3Rf}Iq r믋Nm!HH32rNFS/84m Њ*\6So`&+TҠr*A-vJSNBaY`(>NE7.C(QS?GԖETTBt<_}k^3WA$1z"n9UĬOp^U( N/x%`/,Ljs#Z¨1t^h9;(Y$ހ]؎k Q(sv/'8DNP{%Tu^_rG@ˍ_6xGr>3@q8aơY9 "Xth`lTV!TO)%*_O-UwDz_0 PBO/'fJ T29G_.tr<J.P7 K_`[ `~bvɥO6ܽo$?9@Ǭc-Od@bD X8;(8+BpxeiKxtg :mTD+ Ũ4>e3?Ѣ#]\ : X88p;|u<@e]L ~r_N||F~nq|+4?h>WGN`~r̃B賰JM#hQ&Q }\x@g}Qq݀P$]9 +2U8>Q-u~@: O`(<\L_䁣 PJPL⸽ f3LPQuf ã>;lmq>(4K9K}7|+֜Mi]=r}"|HH)d!$䘿&(3DH{_P˽@/i]7؃HM=9L og# GP|]b6PH=38 wuD==2p$97JO"w ~}{kk9U>Z @힃 ]J";}GT P?=%oS/V]% 8T}vilԕ!ɔEضm\m\wa5@EņrD>(Əeb\&`EOrbK\;evN^EN,tNi,uob""PjlBc;Agۺ+mh{# B`hMYY߂@{*4:LOq̇&=0O 2+y`0;̽fbu/(jZl wgݧO[!%(5&VB~ K͠*lUa38d/ 麞%u%@r|3XMqpmgi @5}N۰9Cz2=Z{GL9´#DR8P8_o(qT rZHbpe1½_>ﶂ bw#@O `?q>{/r1fu+dX E/$O6@~v6L >h{AJ @qyk¾q@RSuPw8G  a }&X_.P4c A[Q\i%D=X_m/̶x97h}\S{@bnxee?4`z_PDuP> М紻wsC]Ǖ~g6VXH"Xl! Yo:d"8`s9cdr39`N]^[T[|h*Gy]] >{}`Kp f;9v](m۹Ô2yZ 3~7Al[wDYk&@ (OLj(G*rSZͬk`~~6g| " 82\Wo%`Y>70`kP=Y go%5/H1 awa1%VÊO(C%QG6u` K1{l+B+!Φ0GZS{ߡĖk<…Lu2jBj> F/(}*> tEVrUU}JKA)js7߲- o07u\H QoVRmKB(C+Mr!bqZK 1Xz7N~RջjM*BƊ[(CRߡ %o,!ھ:[Wk EAyhZi2b5e){e2<`>,!:B#&tR2a*^ iYcXb_vNY6~{e**b/Rj[ØSɫ R(_݋' zq]k_Ǭf☳ cưAc-u&}\MvBk.B޺@I 82✽^?8B_&({et~7BVT_M hݰ*{Rɭ90# '蕀\9 Mi;E2s(AJE N i^yw)'e*T.X XO -7Iqv# 1*lh1z<@3{3T'QVԩTHm20 m_&@S&xoQ ͠ǜp;Eb1v?)E5uC;@ 1mєqL61b#T*P^J rǹ!4/97Z232;MyNPj`V!  NVa1zc׫VTY>GDQ}]4!,lb>`h(6Hm`J5`ǽ in`F]3 it3 "5y`: x,jtѬX&xqn0 {O}ia9{LE d G ޔ ql "MHENx^Tͱ> t Ac:3RSZԖgb=H AS4P>R0_.p}.Ӏw<[9NGQ1E,00LL *R"S1Ra +:W1םGeOB"O GTKC鯛Fp؍`8uXáln`JQ$J! 2ߖ~~`ibOv`giGUq u+»@ Ӵ+rXpn~b}'t˾!B ,.(\h8_.EPh)>CT>6?(a/p> *#I}Fmh(y@TEm'G~B]K^$-{OT u@8LJMqseN^3L!jEOk(~Q(m(K{e1s} `%XSvSNfk"h@l VTQgU,g `fJʄw A p{% #Q 0]af2)BD?0oݡBQ.)]X Zz"^1: iX{偨 urh^ i c˦/!G[Z`dה ,<Ư׶ H"RX`*q$a1+hn0T(v32AeSlb*:J0zaU] ŧLVAUt'Zǧ"" X²P}z Eo]P Oec'< "+6vrZG@'B+'fmO?|bDYpz+{a9FT۩ f;FTAZ¨1t^h9;(Y$ހ]؎k Q(sv/'C@k(qaGY*:/'G@_}eGrV| 1,\ Cs+s|7]$q@>+U~b ɧ-UwDz6io='!z3Г ,/'"<@k1RNzwX y, V|]priE} :w8>_.Po׸tN|NIňpwtQq8W\}7"@v 1CPV}N dC1:Nӧl'Z{ @-PZi-PN!?.mETpS 'nK!.=^ޯZcL /P:_Hz@EN^-`wAmP> ,ЊTDy-F wDqTTCA+c/ɟcp6u9@Zp_`)'޳}}ɊY7@oJ, !L~+, utۮZY H, (j[V(<(KQ=/b8S@L6De=hiaۧA vO&H\\!r̽heL[6 0`p "B1n+VgL%VoFXWV9ߞ]6- Pl ?AC!5=~"ô;#B u;rB&O{e&t@>:2)_y@ CW˹s,>p |J^0? !,5P}! >eY dqE)^gT]E]unI Of⸭w_@{8>ZH$~@-bƞQ';#(ۂl+ g9"RR^OlܖNT`j!׷.ȇ4ҪL6:ru;0? 9we)5˹ b~؃HL@U{όݸ2H} J(t˟awۻ:"F~Wp$9[S8[$>O"ϻjEEikk9UVk ZsKVI`wL>pMb_lj XActAR6.0*C@)31mڸx;3D=8:D>(Pۍin(BpR.*W{vn{"]Y05.@Yj܆s?jjqZPcۀe)CзfDNV1Gkn$S aJ㰙u<$~R@ X[3a]7$֭f}Zp6} Vtz[.<JUȏꃜG fA~ xPV-Xh8C)צ}v T;VN۰9Cxx2}simGLqpP*dJPe1h4л$WV A-`}E|<{ewl9=k" j̴l Y.V@ f n +}~8>6M~:.H/P~_>5a_H8BTHO;#?~?D9$x|v [`j&}NDC{<8+>Hhۚᅯ{{j9/ )%r-_0i.w\0b0s"84mǛjqy]&z}`P[a!`C07d-@쓉 QCLsο,\p=[{T[|h*G[Op~@+∁̌  JѶ^r^%tK+j}/Ҡa CDQwvUy`UG9R۳'T5@+ 0glxֺzϗ "}< ƑYz+9,.ӂiAEd-H֐|@bY {H Dvb[+>PԕJ,챁#g׸;bEt|Xww/ș]}@l(\d *C*#it@TиZ U\!`/` "]4~iշ`Ƞy O/D~ȤJD HRmo`:)^0Hô,L1,s;_g,jxR|**("^ Զ1WeE9APwXq0Ao l@t|XOfs}t˜1lP~6T&sГN}9_> ؼ-Tǭ+()GCb]?8f^/@ ^iwbi>+ GCZ%=PR&&@On)i%+̔\TŸv(k4Xz~n%Qɵ@8zܩ# + Ry<r ^B2<y[PrDߥvprb`;{mf ~bԡ|(~)avD{\&v&hqc11 `X/8Nr!Hl0\3cP'`h}!m03fv)nVfꙒq` td'{JQes0A_.@rOOc83Ri5@ 9-U㨊;v{O(Ok@!Wāw+>اiW=*(,O}#BX \Q/ 49 >2C@E Q!||ieS*#Al>Psaml!‚-t39RX"ip{j>H( OC@8LvtiΕqlV@ 1]Mqq9(~Q(m(K|1s\`%XSvSN{03:  iEN,\" …;$?)E*3%Lňt$bDq?+ [&E{O ݊#B<]8toOWXbh\ah鉬{E: iXZS_.`۽qrJH^hn#ܒ+Ka 6>Z/′m;rS!|NPgm3QH+q$a1+ȭ.&:(>WBi+2UI[E0>&F/콿|hE MD)70?+TҠr*A1%GxPXV7ʷQohc|Vmecd \hΕgoNr6i` >1Z"n9|`Zw`F1+h[! JeŜbj^X f;FTy6!M&" (K\ߚCHŖ9 /8B# }p- 0 )QD3 (p Z(f?@تh,@<3 8%m4p-k1ɜ3D ԇ),>N%q()B`*Pr"_.tҧ+ , /"g@EYv~v+(f׮b6&/^yz%?cVŒ,&D| DIgW视^s3JХjCPVha@PPj"(~6^hh9}fFѢ#]\/ {: X878<.$~/y.j$bN;^ qQh^ޯZkPA<7|a uNԂk@EN+!`msAӽ}f +<>f):^H ҨBVYh;Fe)r?ƒ@Zp?`~e3QN}f.+?+f#\!r̳)ȦDp?,!C;$_>bxί ̯V@B++Ȝoϩ ҋ;}N( /K6~cVG+:EM4uOvlHPDgGVn ̽;{Ί(Q!NY.:b+xm6e/(~_`Vb>^C](?p?pef=xA!d=/BO}*WT(TPoNnQ|@ۃ,2c@٧\v3J@,Wdm|஢?pρ.:q/$O_uba(8n]x8m|@,~-\-Rbw?r@1>8G9As3hrك^|(Wu2>VkuD>$GєVg?r RjJ6T{؃4\qVD-" bG.@Di~ R Ig`0GrFߢQ E+r;>p=V|:M/0-P jAk1Ѷ{"ۃDj( `ݡ=lb^S/VX%]_qtzvilLԕ!D\lmxo0bCMO6C= A1.]3D$*Y/c-v^]v `C|}pW@S0[a"@Y@P[?'oiZr AߚQD>/P1GkNWz{[0cmcPSD6 j]!O,Q he0CfusA1,E[6C S觵[;ZҊ(Zh}/qGJ)@<>@۷JR$Z\x%\,9N/.@﵂Y=/bah1o?c2{Zn" yr j3غ>L."Ef7 ?\87Yxv8P&`?|B&ɘF )>]7{osH|v~aLn!Dի'B(Q\i%$>X{l̶|` L'9vbNÊ(C!`zb0s"44繾c&m=ɂ Q45Ff_7Σ/T@h~j(W mRjEæVDbuQ,9-l5s5ֻ5fa4@$7\9&ۊ|XBIzw> VbnPW*_ZVDq1VCMʳQ@3.]}@l(\d *C*h#ht"nЄ\!` 0M/ucvrߍO7:&$QcQVRUOm\( {1k- /0cuQ z[MBl%EL'2(u..M|jާ {̺+Ju>֪^.lLa|cbj]H}x|XC*utKWMV6kոô,Lֻn8_,jXRrGDqt@DڻȧUYQcaP)mc<v[cn4 0i}k `%☳ cp@M[Ml~Nzr}6_> |-Ta@L#!+@!? ݋>T>Y Srޑ{:yGC2 w%=PR&&@On)h%+)=\\} ixEἢ,FqeQ \yӫǛ*0QEUA|彺@$ x*߽/X,myE{Q a o 8yA 1_>mfNw_(QVԩ*Klop7v%6xoQ ͠<\HcN8 F`"s ̌AA;QJhMݡCq`4fShbyX8lml+UK)!P0Әw0x}(h9BLY1|`#AXc4^+ *Ҙ֞ MvGmf*KJ\A8^ywP8cCh, _>0M4 _{m 4\P+B`n}>=B+d^T@&/|ENz?"(6W6+0Ja\=:` [=Ng[nNWeoy? )M/XS1Ra +:V_pTDO*t, B`SaKQ|͸uöKL4pՀBM2 ؓ\ (leQ$J\yP޹a8;FLgZ е;CdNK4,Ŏ[My?+»Qm9m  J7ge?pA.4BQ+3TZ±(%.اMU檠O!hGh9T_ G386FC BO yq.Vx HZ/㝚(kcНIeGw;Nu^ *4bx_"rEgj\~@~_l),^+o$Zb|;\`%E˺!q^(C9XDNSH VTQUYbg%1AQ\z"֋b$mGf2)BD?PW*C<]t%ŧ+v⤨tak鉬{Ebw}95UQAq{@nDc0lDN+}^>z'k FxMyތ,FmLT+nf}Ii r믋Nm!ϕfxeܝ4*iM/84U(6mŧw13iـ݁TDxPXV7ʷQohc|V8l,RQA\y,;{!'o Ⳋ%B+ufX4Q^#J^k%`/l070k1 7ԊFyEצBon:hN ص'g;q(;)jDQ vQCӼaD]l#D9B@j: 0Q~U=Y48yf XiqJڀiZb9gBSP٪ũ@k(`I+0\We񊯘Jxnybvͥ}Ng} Q>fEk }oұyADQ8Cn J:" G?5~7+7QmE.U5c :m{T$'?yuH4e3hQs.9BP(pӀSȏ~co q1|@WRI粡 xa/ŋ XEyZhy#p( 2QGD-x9{T\1$`?x|ZQ|C *h};)DUPjybslC8JK!@Zp?`~e3QN"8]V~V"BWzg"*譐o($T&΂Y "؊oލtR " X-GYy?;E φik)ا?ZLY|,F*+BgmS_M~*X8\C:*"vH<| mŪ__ ՇE V啀dηDM%Hf?ul1 AG+:EMO*tA듑Bώ95<:$o k;2Da|ЧJr'8O"D~[({8">^Qb"cwSo}w@}%#qxQfos2@,>*aOy7򀘱2@1>ꛑ?({.@G1^1^ sWӭ9-k9|:=PY Bou]ɑh4Uo{I0}h2Cz< U1t><Az_U?Fiܷ48U@9P|=w?B+/n`0rw1=F[$( > ~?P+>{-3.1|@*ZsKQI`{LW+BP/J^1^Jz Ru0*C@0#CC?=ņrD>(P"pDEg="[=.rWl >C 8zE9<S(V$ :-(*~Pcѝ>V1GkNW{[0cmcPSD6[YDV&z*>PTz 8L -We(r֭fZp6} Vt˺G/r= xyJUȏꋜFTŞA2 'mN@(aZMh9jDML4X%"s}e76g?K X{}(Zh}/qiGJ)@.*dJPe1 /V0>Ei٦ af]øllIluܧ`_ip윌=[!( YDazõ8a]rƵ|x_l4{  %?/P~PsTŜއPCCk@( C>G/HCs;f 1+?{z]0PnW(αbGߐٞTL;F 1L`Ʈqfеk\iݑ_Zi =ZF ff߅pLh[h9$`tK+jؙ@_.0qeTPVo)Hp~y(cBB5fla%"QvhrEYxHV#D9_kN(Y&Z !~"c@Le(E}ڽ̬Xg^jx|ݗW\<9z_hV>$J P*^ 8ԇ aVL-V_6_03 u^ u뜔`C=K /TQQ_.P$" c>L% MVP @}srcFDGhW$jE>!hcT\;@6v3Qz5ਤAM/p(D=/pƆHM/L_>eBM/L͚_>eBM/sia9{#ܹl!.BId9 Wwp/bY`sՋj9n"0cPʪORJ$48{N )*p2hu34Rjyhf9n?0NusAt%Pa[H< ؃ eoy@ДXS1'f^鼢yEsj'zVcp,&J– QViKN8jøuöKL4*$aPAECݗ}>g%JcsPJo6wn4<řVtR(1(KVod@Vp i" ,Xj`ߦ]Ӷp {p<[! rg(*-g f~J@CcX6U>9"Vy?z'k FxM`³ڶV$80Ҙ_xQcCs+!4ʈF5<0`[ȇVT`ڴAK% -'h;P7p$: D1-6|LvB* P1zd \hΕgoNr6i` >1Z"n\0;0-Z Wrާ&`/l070k1Zk!!M]W`B /Toz݊o3ٵ 7,Z/^yz%|@Ǭc-Y<߀2Y `vGQxwQi8ayEΕz_H]7Q(pkPl(F "-! Mٛ&`օU#PZP fEb3r;bN;6G3 ^tkb_(O=  (2QGD-x " CV?{C97B+"ch@BVtx}"%H  ZgI]lmHGicI\K^-hg D9YE뻬u$2 djVȷbCB~4~5( $(b9ږʄ e)EP,5?"=@Ze[ 0 Oc1RX"p3QJ#hQ&QڝE"oGYd5~@O(m^oS偳~ u8@K\C(Px3DqwoQ3@)A13_P6U&(FqG(@;hv dp$㥾d>tk&`~NT`j큐[]ACr$M׼ ...)> fc!˯dCU/{!(^ҺfVA! ipk" sRDi ݲ @λ Q,Ck; {xcyZ٢L-}_P ZsKQI` va:V;F J^1^J R `1QW>7Sf!Duhrhm1*0Cߛ(佰hf(BpܵR.*W{vy= +ȩetFi,B(Q+VH{[؎Dm]y@Ŭ~!4 Ck3b}(4Rcm4l3J{ j]!O,Q e0Cu3@1 (QZ#B|V- "iq^5&e+ W!?/rDgP{;(9Yei7ERj &VD\%&P ṗM`{osH|`v~ !J z}_.m"D wmJ.!\쁨 y{[Kٶ_srAR /sZ5^_CCky@( C>G/HCs;fX <w끹w{BuuS?:d"4$vVsf3,\5໷6?[SV񡱫UXfg-w4]ڀy9v](5<m-U_(Fn P0F̾nGiԦ*!Ol*0QD_(VH f]3 (sC_oa,їH"g};lbZM%EcQbᾷ$aAGS.]= \[T.dY!PcR[hH4:Aq U{⁨8(D!`U5v<@i)Z4:z;MFCa1c+)ج*C+Cr!bZKvz7N֐Y&Z !~"c@Le(E: af:[Wk""@۶B%[ԺeH}x|l]L-V_6j[Uߛ]}@<9)  `VPG}(YRj1WeE9AP*]ƒ&D׾&AJa 9 dPlzD\mMv_Pc PT9U,^#8ڼQ+M(ܦ܇q֜P; XJ.ʆ4BSE-Xcz~^%Q} j}Ͽ9 ` +vچr^~w,VrUq4~Ȓ*\D((0ӷ< X^w<`ԡ| Pϖ)avD= r7_L-&Fk042#94-wc503F)E&Zb9njnc70ũWJ2 @T2 gl4,jy`hr 5< FfN+[(sZr8 {_ue_)Vav^& ڂ!Zuf{)jq:/48{N )*H7؃nNy@BJ7 0T( l6BQ3}t8ߪq8>p%E8it<( ~E ehJ+b*FdL+:Wt:c;)ʞ XE@߲Al4 l ujE{N8}?[X0ZQZ/.*qՀBM2 ؓ(leQ$J! Fa?cc4Dq]o3D%0Q(Ou4t.}v@NoYn>"D%ܠ:E y3rA(}e@KB8VA%cX6U>9"Vy?jY K@Dֽ"c; i>X@Tcw@^0/#_AwZ`dה ,<_mjE <_Ѭ# #YAnu1ѩ75v@1=L\`JZ_^{ Њ*L6So`~v[ZDB (Z V,* c[l(Z32"UpbDmX<Ds[ӷ셜,MZ*4*jl[^/L(fmK?Dp @ s<#  ZwZjEƼkx7q Co7Q4'q\eB񍓳8?J\FC8R!׷&=*utLQg(4µ0L44}$`N|7M$iTJ%`B>Q~63VEdXQ(`՝* 8$sW%Rz8w4? @k @Nt_@Eeۥ YwtSbvͥ}N{&yz%\cVŒ,&D| DIgW视^smE.Uu\c :m{T$'?yuH4Z؄MOͱG~9/^MPZP fEy3;r{{1f_/(^t<iLm'W-5Vص+݀ uNԂ"؃m" CV?{C97B+"ch@BVtx}"%H  ZgI]lmHGicI\ZЂ+r3wYY19r(m_I@"*譐o($2q,J[c9@m e,EۿŝgC䴵GHKxA8vP7d ĝMgBRQTpt UD y mŪ__ XWV9ߞS6wX P^lcVG+:OTslJȽTE Bώ9L:$Ȼ*C\u(Wm^P3L,>p |Q^%n~(w{B Xz_>pUQڝݢ"D4(fP|].{*Ppﱆ N+|0e ?`(ۭ~ ѷeL>p J I˄T$N#?`vz*D}ԝp rlg s#/=+֜MU. B !9k^?x_yvQB=4yA!BJm_Ɇ_BQ 5̀?[l*gYM2IEkX_}(t˶*1c;Dq fO/0{x׺~}SA`t[bZbmyTDv=`*؅EwgO+BPfH%oS/VX%]_qtzvilLԕ!͔Elmڸx3D=8:(P"pDC0~@e.`rQګwt8zE95\S(VZ\?jjiәUDA_+4Zoo(U̺9E 0 ;]m]@>[)6Sb6>{AiUTzpN/ -We(E[P!>u VtzG.<\`%@*GENH# bϠ* (kX(adE *M9L46KL40a'Ͻ9CxX2}simGJ)@<>@.VQ *B[ŲM/ ^+xբlXny&Њϊ K0Q;쓢"`+ǻ,=[!B%{if7 ?\87Yxv8P&`?mB@d[&!c5a?H4BTH>̇Mc/0⊌⽷?D9$p>p;D x(Ԥq&B k{\QAmM/%M-GrR n)yHvbNKr |@( C>G/HCs;f[S:w{B٤c}C{TL3@J= k޽ٚ]2[i {4 pL,@mK"Sd(vclD_>`uPh[R(6`&u/A$*AJȬrH3h1!ؓUg kl/"w1$VÊ(J}dQb%+憾4 Y٣/DίvZMxZ,{;LI6p4ʑwb˵U@EB&kE?P5V!EDPQ{ |PaB$VUQc(-7ucvrߍO7:&$QcQVRY+Ui6.Wj=BĘ񵖆1n! z[MBl%EL'2h=\X+}ʲte(-D֊}yE*<9:!+V@ZB:L/@N/DʐRx*.R25>(THqtt@Ef` Xzm? u뜔`CVD5aVlfw(R{ 10JecW! ؂@s^1 xާ"(6ޓct e&8٦-u&}6?'=>2آor( [{3̇8g{ź=py`_(r:{GJ!+rPY;ƪ!/L)un'L4R9LUVrQU66(\/ۥb#["*-Dz Dcc('>W|"`%Ly`i^x ({v[BoCb/xwp{SB*@1JTuw} =]r7py?^Ly<\0j 4`F,1 1 FS`11 ̲±|% {)E0fS|6`z??|` L,̎+XS6*GX *Av~AU4!S?z5`coO`,z>`@8:@Lci5󁍈bxaHt7HcNZQtNp qp/N Y"N'x^Tqv /X 1Gc:3QӽCi8D= {S4P>R~/=U"c4 0n[P 1޺@tZo^`1~^* p%E8i4|QlV[@ДvXS1'f^鼢yEsIpTQXE@߲Al4 l ujEN8}?[X0ZQ8lTϔLBeT4n p#Q6A /s(q v(δk vȜ*@iTEY`G;+P@! Ww+@ ,-qeAmQ[Zjb>*T%ܠ:E qgSQ+3TZ±({ل(!ap> lES@\T#J}/P;B^t܀#'y/xei(' `:y-*҈19<!jE>(е8/MWDDpV 4-v1 _wz~L4 Ȧ!{v;YC-n02vkfd1lfZ(vW4HHcV[]Ltj FP 1w}0+#dQf`%gJZNXE7(FԵ{S8 X²P}z Ek]P䣦,l{"- TTBHt<{ pրŷI [YE vӺ3YAQp_U( n/x%`/,Lj fc kƼkx7q#$ހ]8k Q(qrv'gC@V%Q}#7@|QANE(!R|>X a])QD3 (p Z(f?mYa@DFv_!,4߯!J>L!(dq(i~|GIS PDC"4 OWX4` /_ؠ,xA1P[ `F1v>'=^T&܃Q>fEk0zmO}h3A€WC3?pdήHO "J /H] j9uHO5(~6(^hh9}fFѢ#]\Ty0$n" 4`pxm]_!.pF_>?y&{؋9Ń O@<o[lb[T7B:L/d‰Zyl6`w!`bW zEw UP(>@;E;)DU, (m,k٠@f+r3wYY19r(^0t1djVȷb*gBP0&CAԶP&Z8RTϻY)j ~6DN[{4O7ԍcW@ucO&, >#\!r̳)0#{eP#jORĸ4|t+dstᐼWV9ߞ]6wXPd]L/_p @@}%#qxQf⸭{wuL.J ~jq>/+l(oFcxC~3{yp#//u_9+W1kQ>[]rɑh4^2DtxQB>4@!BJr_:3=H" UgLX\dPo J{/(t˶*1c;Dq f/0}xϺԊU'm="rUxWkm C꣒_  va]`E 90D J_Jz Ru0*C:0x3| `: 4 r/q9~!"P̢Pxykإ\T;rgw'^"a= T랋]@ViFQu,e֌"J+on}!0{&(t36fPhlLi5J j]!OK!OҪ/p/0x[<0 (QE[P!>-liu8?p_zN ^{UgP{;(ˋBz P0-&Pc5kE |&VDhp,A2Xs3%u/r\M?[!+L󳆺׫ؓ**AE.Ŝo 7Ze2uc7V|V~_.v7LO=-+߻,=[!( YDazõ8a]rƵ|x_l4{  %?/P~ 1r"Q}^<7wDۃcuW~`ݞPkc1ԏ!뽳=9"ߟ‹!5,\36?{/5;Z}> {ayp a;w!(c Sk +Z3 ҊZ7v&4kHm=/H D D6b[+P(Ez na=Pb%." ĖceY!PcR[hH4:Aq UwqAT{8+B*jRhucv7߲i#@Wpz2WԘAԇl֊DBڡe!V1p;:V?0wZ!϶]RTp(C!JhBg,KH_fbzu_z^sZ}m8?xX ZWq:\><){h(0QGTh[}NJr"W|ô,Lֽn{ysR ,/;R?إ8e nPGeOB"XMM-ANS1.F?[X0ZQ8lTϔLBeT4`J2J^zD%߷m;7~`hLv`giFUq7 O+»Qm9m  58]-Gj.(\hWf!*cQ)=J.اMh**6pD cyAh[!,HE:#P*ҼISs+!LT&pt;a2l642@!8/@>[WP| Q-Qe)^y#b_0,!.Ƃ*T'y@ԘBuk/"`@T֜DJ~^GXYbg%1AQ\z"֋b$W1d΄ےQ*LO+6Tշ P!Ofu B|bG NOVȱȺWd,vG]!-SSU_. r/wz~L4 Ȧ Bw5x蝬7;5e! kfZ(vW4HHcV[]Ltj FP 1w}0+#>W ̌x#K {o!ZQiQ|J /4(nP@4^h* c[l(Z32"UpbDmX"ѹ-Xv[BN&-lg5FKV6- ufX4Q^#J^Z+;aYZ AaԘWtm/9;a(#$ހ]8k Q(~oD@w b(qe>&" (K\ߚCHŖ{_! PhskaiheIBn,H40Ӏ}W*bS=/[_(;6`4߯!J>L!kBO/|;J T O4 OWX4`O Ė_bZ^ XA|{Nmؔ^a_@YxY.{}6.mߢ&}f:'BPj;d$B(P#`N+dq_{_.yߓ_ qra\Ak){A 3/O?`Dy=+ 0 !vX/`%J|Wz"DnQ|@ۃ,2c@٧\v3J@,Wdm|஢?pρ.:}$^IPba(8n]x8m|@,~-\-Rbw?r0RbG}ԝxl(6//^itk&` \X} 亟 "#hJwI`F 9e)u^~%b~ qD0{ 0nDϞg6*Ƞ>'a9|A'-JČ;U>a/&!?<(Z([ԊU' \+Xocuc>YgU@D va}%O[/VX%]_yvT0ؘ+C@)3"`:q9q-6C=Ÿ ,q=DC0~@e.`rQګwt8^" aj] T띋}G[""P=jlBc;A:+on}!0{&(tu36fPhlLiÃQt8(Jsx9@۷J-0*B[ŲM/ e2uc7V|V_>nֻ-[Hc\ 3 n3@?HQ $p-NFXf9H}^Bm\E]j3 (?pMR}*aES ̲wY.aG32p>p;Baa_.u9 t\+ŕV_]B\QAmM/՛Z!/TFRŜ(C!`zb0s"44繾c&'1\iݑ_Z4)?${4 pL,@mpR& _.(Fy.(tc#BQPAmtKl*0QDV+3M3 ƞ_>`ԡ| PlE *Kllwcbd _@SxoQ ͠<\HcN8 F`"s ̌AA;QJhMݡCq`4fShbyX8lml+iQ"3)>qC8lso +0/PP((@T gl|` eBfX&|@~N W>QtNp qp/N Y5Zx^TTyxAiy {t >֪3 8q &Z+ mꙒiTH~àlz/\ (leQ$J! jFa?DŲϴko!2 PbzyE_(4n`Ev۴+rXpo~b}'t~!B ,.(\h8M/Wf!*cՊOPL/9}`Te @[qA}/{\:{b bik|@XCOC@8Lvt֩kAEPF e/DZ" tu5 _.@{%3rV {Dr@LÜo ̲wY2W8n e8:ȩBu PA[s+yx"xag9Eqw3UT&Z/fJ֋(W1Gϣ`l X'`HV"i5¥-(>b}]r'QWHK̩*L/ rN/;bp&qdS=;x蝬7;5y3em3QH+q$a1+ȭ.&:(>WBisw2Ҙ5\ 腽Bi(>%gJZNXE7(Fbw?64^h* c[l(Z32"Uh{"- TTBHt<{ pրŷI [YE vӺ3YAQjq4 /P /J^X f;FTAZ¨14^sv\PMGIq@P|t>N ׸Qc"Tu>_`M/G@ /hy! PhskaiheIBn,H40Ӏ}W*bS / E}uSLi_=CJ}BPQlq()B`*M@Nt_@eۥ YwtSbvͥ}N{&yz%?cVŒ,&DՏ3`+pӽdR{̌Ͼݡ`PmDkABjP˩M{ %T9up Q8<.8#O/`_xa/ŋ XEyZ(OT PA<7|a uNԂk@EN^-`sAӽ}X _1!+CPZ~EUP8K:bslC8JK_6%"}&_LEYϊY7ϑ@oJ,QA8m 1ȷA!"`!(~V }ȡ~ j[V(_>(KQ=/gq9m<%@P7]ԍ=೅H`%W,mJ+8iO9 kHPEĸX5ϯ ̯"J 2sK˒ w1} HъoQS.:'BPj;d$B(P#`N+dqdM/I7|s,|1}x?̀/0x+i1.FWۃ3BoV\t'>p*B*H=8">}l= {Eަ*肨Jm0 ? F!ޅޖ2r.(%(&z'jq/{*8|Sp`wE,G1^1^ +֜M!Z@u?/D>$GєVg+.3J1&/(3DH^Px@/i 3iv!"4$Ta=3 bmrUA}N*_r( ݲ @λ Q,Ca}Z٢akEpm =@D va}Wԋ4VIW]ށfms0# !CCXX]PbC9 "ggb\~f|0P5̢Pxk إ\T;kN^EN /0Je@QlcuZQTj>@m A40^Q|usޯ~#$Fa@oofmJӰgu<-<3J;|t9\m4sn-G6CZq2DZ-q^r9 "3!(^5,?P0ÔE9V&Zlab@f18ysimGJ)@<>@۷J-0*B[ŲM/ ZY-JK+=^nse-6/mwDO-[Hc\ 3 n d B87Yxv8PwŎ>A3; (?pM*Gi+Jc |Xє0,X,{#@ԘC kH z_m"D w@qW3@Tc>|{[_.RJr-/i.\Pi݇/PCr(:[]a(\EihsLt(sC_oa_)Vx;VDq1ĻVqf^ SM:Mx> \[T.dY!PcR[hH4:Aq֚/}@%d|mhBJ_:-@+PXDŽ j R֢֊DBڡe!Z}1x|f ;DRջjg.)B`*8?!D[pAR$j`P(KTl} \T:Gm[xԺRx*.R25>(THqtt@Ef` Xzm? u뜔`C KP_.`8|@(Β(R{7D R({xFٲ!17L?]{4_>f-l9ia0u6hSJg8 i8:56:@ Um42✽^?8BM/cXPɿh Sfƪ!/L)un'L4۔_.J~o|b MiE.VWD 2DTr-PNoW|"`%/Q wn"J=x;L!7!V<|;F=|鞁B^mQNP!]bc{> nZ+~[L55`hGsi0Z# Ƙk`f RDk wb)0mY= -~E0~(iLy;b!`/~_Y|Wh9BLY1|`#AXc4^+ *Ҙ֞X0o(Gmf8jQI; 8 2 @T %NV _2D, _> FfN+[(B:' Y'UZ0oOY\R?إ8e[7Ag8 |IlTsK•┧{GY[_> K /XS1зl"CN'zV!oqbSaKS+Epk7a:֊aۥzd0(۠>,#Qɿ#c5\ 11g8j7"sZ%Qe)vmQ(Oky+»Qm9*.O#BX \Qp_EPh)>CTǾ6Sz0hcX6U>9"Vm-W8fpl"썆"A\8A,{8^;5P|PǠ;`Gw0lTi_6@!8/@>[WhA\7Q_QZQb/7-v1 s_.0l(Cp-qM ^,8j*hkN"`%/@#,g(.Z`fJD A z1U"B8Fϣ`baˤt_Őڭ8"D8:jY݅KW!>jY K@Dֽ"c; i>X r۽ 7`_G6/A߳Ck`dה ,fZ(vW4HHcV[]Ltj FP 1w}0+#>W erD0z߅|hE MD)70?+Tzh;P7p$: eu|&"0ӀEUl~qy޽ \hZ(\_8}k^bsVA|VQcDؠ-L(fmK?D} B /s{a9FTS6}od1~ ?Y?Wtm/X款A4CCvm82D|~76*Q}#7@|QAeh5he /8B# }p- 0 z, S( !EfPJ%`B>Q~Uay #pJڀiZsW%Rz8w4? @k @Nt_@eۥ YwtSbvͥ}N{&yz%?cVŒ,&DՏ3`+pSwR6"@t_Y}kEPl(F "r͌EͱG~9/^#\!r̳)ȦDp?,!C;$_>bxί ̯"J 2sK˒ w1'Vt~;yz6qt^QPDgGVn ̽Jg |=/Te;b#/v۔ x3oe5-'0|| (g{pB};yZ=p *B*H [(`pEf}\3.6U89Q+5~@r '0Cm}.L_ߖG/q{ fTQuf >hG 8Pr$>myE?ݚ rr: PYV1%p$MiU~6:]]k @(!=49@!BJr_:xAH͟ 7CXEiH>{fŶXg OuD߇8 0CQ"u^Gggݲh}}_P ZE`R}T!<]Xt+!(%oS/V]% _qt0ؘ+C@ۿQ/*$8mڸڸjʡoC." _,zE]Ej.?]/C8zE9u S(mdLEsiFQ8,KVhl V1GkNWm.H@>[Oi̇&_<3JZl/mwDO-oHc 3 n_ M# 3] >#87Y>pD6M~zHyB^rBTH>̇M`{osH/ TϟJ z}_.m"D wm_wp~3{ *ȱx_ WS1`H>2`W`QsT 9V@bcY{Cm[$uP М掙C]Ǖz=0PnW(7SR16(6v @6=!V%`>k_ {k5U jMl֭'9z}@+҈Lb;_._mSd /|(tc#Bf_7Σ4L jSh~vo0QD_(VH f]3 L(.U y`ύX;sBwؘb˵U@EB&EOP5V!EDPQ. |]Pj+2&eWN}AS"PXDŽ j J 6kE !劲\Gs<23 mQ z[Mu!Pc# 5(u.QDC vXf]QZ(\T 0ystCWyCRj0i DRmo`:)^+^>0K[ut >) *"j{ì.fwFp *+j! *RX~TЯS"ʖ !k@tk<5O$Hsu]atiCݡI L=-rͯ$dxkyfq g/t@^!؞ i ^AJ*Tw70VGq4yV3ԹMLܚS3JVlS *(*MiE.VWD 2DTr-PNL46\8k_D9/Be+-bpsQ[ Np|b{RF6SB*@1JTuR%6}LlL|Bw Ŕ ^bbC38ҘNr!Hl0\3cP`R$ZSwh0s6My?`XA{#(6[[`YRJK)!P0Әw0x/E_f) *GX *Av~AɊ4!Srz5`coO`,4P{0 ߟ 1ϴFDGh/E>!hcT\;2@6v3Qz5ਤA /pd&@e_&@d s 5,k9EP+B`n}>=B+d^T@&/|ENz?"(6W6+0_0cX7™}Ug&Jyb(mp4̜aE !( Z L}L!_zDh6v`J(Nu@tZo^`1~^* p%E8it<( ~b_\`WLHm5_"CW=  Yl4 l ujE{N8}?[X0ZQ8lTϔLBeT4n p#Q6A~R(~0 iy&3}!2 0>R(uLPHi`(PKyo\@q[ggڧ[ݽ B ŗ6`f pz_.EPh)>Cܗ}My8ieS~E A8DاR8a ]Zg\8A,{8^;5(R!LT&pt;aT絠"H#r@ !jE 2 tnkx /@(`ݖ(֊{ah[>/i2Y[cANS;A5P>&Q 9| ⳜJbh;ůTKQ´^Dq9xC [&E[@wqt tŎ@U.c-=uX쎺BZ0<}_.wz~L4 ȦBw֫#cl0dzmLT+nf}Ii r믋Nm!ϕfxeܝ4*i=/84U(6mŧRIB (ZǦ" X²P}z Ek]P䣦,l{"- TTBHt<{ pրŷI [YE viqŬm(/*M|l Ԁ#6Q jEZP~lsVvEsom5P(89;݁3!mӾ > \yL_U!R|>X a])QD3 (p Z(f?aE}uSLײ<\`NF $A ' Y>N%EL*XCB\EhPI+hv_y_( .mP:NϱJ`F1v>'=}}n#7TY !L a6B@ Ae,X Deȱ=K%4ږʄe)EP,5?"=@ZƱ+ '| J9Yt۔Wpd" sא_/ĸX5k+!0*,+Ȝoω.ҋ;( /K6rAl1 AG+:EMO*tA듑Bώ9L:$u@T8e0Q?۔g|[Y|Nx u'0JQ{_.+YP}! wDeY >˞+MU9Q >SWe ?`(zx[&Jj98n ČMQQwF>1<%W`wE,G1^1^ Ӡ1b8\X} r 1[єVg]fc~M^PfR㽜 *^{g6WɻV xo1>ip;r2H}o J?PmUbv*da0sD atFъ>x12=Xo֠h=" 5^T y"A۫9ԋ4VIW]ށfAe#џ΍xQضm|3bCMO6C= A1.]3D$*Y/c-v^]v `_>p > +ȩtk,} c(pN4@ iRo(DNV1GkNWz{[0cfb}(4Rcm4l} j}=DUo;V av{֭fZp6} VtzG] xJUȏ}bv3=38=(C%0%>@r|3rX=iKD1:76g0sz(^a#D~ipP[%i)-_.Ŝopniog(-4![ Ⳣp/|zO]-W1wY.D{[BևPAŒ!kq06AGj}ごP(ycׄ R!ا0V4;,+250^TP=_>PJr@}i!;BWZ}u >sD9E玲u̹-Hvi?Y }1^ !F8k A7~HlupZEihs}sL=-٥g]=۳ ` ;@꜓ wLj!3ο,\0=[{ZU*,YnPhvi>l0W EѶmCaJ,ESC|`nD_>`u@5V(y e QQZY/pVPTwe"@۶B!QZnZWq:|C}Rj0i DRmo`:)^+^>0K[t >) ;\QEEq"Q%Q(na*yUVԘCT   0i@ta|X@J' 1gQƌJg8 jl{@1ZBid>9{7=py`_(r:^w} #`{1hJz~? ݲ|DP7@% Y1BQ+3TZ±(%.اMU檠O!hGh9T_ G386FC BO yq.Vx HZ/㝚(kcНIeGw;Nu^ *4bx / V@]l]M# P|/qIWD=+֊{ah[N/irY.P mzA ^T`9UN} *hkN"`%/@{,\ [N2<*iPJe%LH+ێ#Q 0]ͰeR~ZگUt yGG 0pjK OWIQ 9Ypw}95UQA_GM`&`_G6/A߳Cjq^S7#Qf60ՊD5f}Ii r믋Nm!ϕfxeܝ4*iM/84U(6mŧRIBnb-vJcSNBaY`(mJ !3 XT5|V8l,RQA\y,;{!'o Ⳋ%B+ufX4Q^#J^k%`/l070k1 7ԊFyEצBon:hN ص'g;q1ƍ2pBk8hpZniA !R|>X a}WT;mD3 (p Z(f?@ت0<Q-=@e_0 %-N|;J T2 0  ,~ș_>PQuGw;U (f.\dQ/^yz%?cVŒ,&DՏ3`+pSwR6"@t_1B=*n :W$ZN߲Q9H!(G¡NN!?jEbg8=Ŝ}xrkP1_@JLQ8Q _95s{yD Or1_o`1V|E Zƃu}iY0<%ހ Z /]lmHGicI\K˖ZЂ+rb^Q\ _. 25z+y Io1`!(~Vb췎1@m ee)EP,5?"=@Z[ܷlAi|,F*+BgmS_M~*X8\C:*"vH<| mŪ__ ՇE VfXA|{Nt ؔ^a_@YxY.b B8Z-j}PQ{DJm^DE0}viL6~!g 뭁. \ Fyh =-3ioPr#ʨda/&!/0xxgq{A84_P jmbmD/(PzS.,CmA]Cli9bU+.UfAe#Q,mfņꛞl(zAb\sqvŸ% _,E^]v `_x~p(rj:VصP>1 8[EEExCZ NQcoW*fݜ B`hMQ,kE-FF)ևBc+>fJLf>QQ(&:*^9_ -x9@Qr`3T~K8>~Z+e#[  /p"'A{Ugл xPx+Vc5kE &VDhp,A2,8y-MimGJ)@<[%i)-_.Ŝo{Je2uc7V|V_.fwxZl9" 19@Ԙgu+d}X}@?HQ $p-NFXpnh1>?Bm/6t>rP~L/pM1(R}*n1 us ;} 11|[ !L^DqmAqW0; *ȱx-rD/RJ[_.0Ҩ]*@1a(C!b07!#=C/HCsf1+?;z0P[a+)bw') _ȁb˵U@EB&kE_P5V!EDg- v"Jd<`+,|\PJ)!h}7R@<` 또DDZBH;q,<$W"4\CpD)o5bm!0f-{ ĸ4qZ3P%C/3DEigZ/=AyQ~im[(-7@z8ROT& mxI\Z_p Xm{ 0,jZR@ _>QEE_P$" c>L%ʊsJT6V|5l☛&Dמ&`X8,t˜1PlC>\mMv_~BᙯZQTR3̇8g lrA!?{ݽAJ*TjqC8l97Z3 `MyNPCTǾ6Sz0rq˦*sU'G؊s:Ô> _A\8A,{8^;5(R!LT&pt;aT絠"H#_."rEgj-w_QZQb/7-vK9̲wY2W8{SNm=(Σ PA?**yzD wVbIF)E*3%LH+ێ#Q 0]ͰeR~/bHV"i5¥-(>]#'Eէ +XKOd+2̩*QAQi v hƑM!{v;YC-n02vkfd1lfZ(vW4HHcV[]Ltj FP 1w}0+#d1UI _>0`[ȇVT`ڴAK%'*A1%DBVn0`%,D>`DQ[6AFHt<{ pրŷI [YE viqŬm(/*Ms{>W#cUyo'0j+6z0veCvm82D|~7ʎv+QpB]Ԑ4oؠ"Q[nM/8B# }p- 0 )QD3 (p Z(f?Ua #{= e_BIl9,'"L/ pL'}Be񊯘Jxnbvͥ}Ng} QKE|fd7ؼ T~! wG7%]VxEΕ_0x%541kEPl(F "r͌EͱG~9/^M@8UOM/`WiTM/P:2QGD-_`r@EN^-`sAӽ}X _1!+ >AQQ .6w6$$z s W60dU뻬uBWzg-,QAFo0|@! 2q,JVQ"JV(_pwAS@liio ǮƞLY|,F*+BgmS_M~*X8\C:*"vH<bxί ̯"p s='lJ%`__p[Ԥ Nڎ>(a l?Yr?tw }2)_y@rm`>ަ>3 4w@k >U,|r/(aW(]\ꁊ rEEoȬagqE(^򁻊= x'q CQf⸭w့eQsA)A1;Pv@TyQugãe9\H4K9KdxE?*o-v#U. B[!׭㽽MiU~6:X.)~@(!!{9DCU/~fD0{ 0n*H@YLn\"@5,/Ҿ^ypT< OuD!8H3e\ܷ~}1|@*|D93@D va:V_> (y{5ǜz*K;,6# }L~ .,? ضm\mDʡoC." _,E]Ej.? /~Pr:L P>1 8[EEE{6`YEȩW*fݜ B`hMQJoofmz*tHf>t>>`Ϫ•;|t9\LG`(jZl ogݧOkEwyM (\IiĞAU pd!f_i )j[&Zlab@! Dc p3%X{}(Zh}/qGJ)@<>@UɻhqU%\,9N/.@﵂Y-J6eno(=|ǻ,0zv?ip] Qc֭abu~,0cAH5@ }v8P&`?|Br( A2BJO`>hw{YWd, j!a  CrVE[Q\i%$>XO/:S\0傡[ _0Ҩ]*_.^EXg+ " yo?09u\ ws,|"X!~ Y OuDi`csf_`N?]-lMZ}ćƮrTa_Z4ZF ffBQ8@| +ZEPkr 0%/ș_x> ~99a{nP&kE?P-V!EL>PHHy8B/`_(%c9rw7:.$b7+)ج*C+Mr)bqZK#,,D)o5b )0f-{ E)2 5V(y{u e-Z+n_)8`< X]iZ]H0aV-V*0[ոô,L;nin;e'/TQQ_>{I#RrJ^j#(RynX.h?@L!9#cF]CxObx1gQ ƂaJL[M?'=?e#|G_{' <JmyG3E[K*TUc/B _>@*@Jɭ903 d#EGِGhJۡ(Rp[T-"s(W;U`apaAgȔpo-T.#޲$ זx$.Eր/g%u(} F{KÔ0_"E{\&v&|qc11*`Xg y r)Hl0\`P#ȴ`h})m0>fShbyX9lml-kф"3)>sSh9XG4d.#<츂7:A#s لFv~AɊyB~Xf:W{=ڣ#Ŕ@,  ^t6nPǜ7wh/D9jb׫G% _. Qd_@ H!@!X&|`heB!Ĺ0d=?tZX0߲xdZ>` {qRE|q:i#~EP |zQm64 a4\`%`` V)^ZKȃG4`A3hS4P>R3_fA06BQ=,Ǹ WC-*WRd]A#u<|@#Дfxe3t^鼢9Toʱ-T<&t,6kaTiA Ԋ6p(q fZ+*KL<*$PAŇz7g%J[H^zD#m7T-7|4<3ŞVt>YR(1KV Oky+»@ Ӵ+JXpn~b}'a6 ? r9/ 4wM` #}%̌.cۧMU檠w@u!0)}< $ncɑP*ҼIeS[|(' `:m _ bx/xy RԊȽ@> ^rF[DDpԶVԥ ^[/yrY[cAI۽ ZloG Bsl, թO$@mIl`/ wV߻|)L^0#ӽ%s&ܞ,x̰eR~ZaP[*C<GB|";Eջ +XKO+ QWHKzTfDo 6ua/܀0l _>1+G[Z`) Yx_603ՊLa >xȴB/K{a9FT۩ f@Nb^ѵsv\9t<97`6(S߆C %qE)u[pwF 4e3Ѣ#]\/ {.: X9۬+Ō3g~ SŃF ꛋ *0v@_> ~ 0\:*'j3_>PQRs=wK]+zj;oq!+ ޑAQф]lZQX׈A/3|f,z"]WV, WqUX h SB~[ ) e,X"u~ j[-G]y"(g  -] u@ؓ ^H`#Ws/}J-زiW9+'sDI@x@ۊUٿ&0b[/ 0 2۳kCOE blŌr@k5i&h=~"ô;#Bu;rB&O{IM[Όr%݈;&k*S\uG}xF }ny4X.#?p̓kBzY/P}) wL lkqSb`FU>Ѧ >sH몣)ށbV ZL$~@-`Ϩ@G{ԝxl8?4K9KdxE?ݚ fPhlMy,sJ@pJ{>Js:mV+bEP.g}Zp6} Vtz[.<\`%@*GAN#lUa3h (S%̶ ͷX^-g ~b@!Ę <2}|oE'z;b|ޞ#(Lk8R[J* J\bOv)?_ź׳8V8/s&t=բlXny&Њ׊#8x;]w^c\ 3m[BчPBxk!kqpvA#` O)PrLj/6r9j[!P*ToTÊO6c/0⊂ƋI@~7>PJի:E wlJ.!.h }`ۚ_%B̹A)/4 _.(]x2B |@)C`uc?J]UB=ڪU `o/g?/(|[RG4|z?M{aAd< Ez_uyn`iנ"{r x!5|@bY {L Dvb[Q+P-Y17qOa]Pb#>`#.x*.l:|ba`J_>@3B8uEB&kE?P-V!EL>P.> .(v4!`#WL|3ŷd|6S"sSXDž Z0f%"SvhrE]IV#E9n_k^ڡ.¬Vh-_~ISq LafJݲ R"Pk@Ym_fb{uz^sqZg}۶B%[3R{OTf mk4ئ::"#0= ~`ڤ`NY~Ij3UTg(2^ԶWeE9AP*+mG:%ٲ)17\?]ۋ]y桹ԀWc΢N81~Nzr6ˈG-6xL&u%%0rsW+W6+T(Gw>B۽#@#%U, c؋yGG*qR41zrkNLC(YarA4rQQ6󊺘U QL\ǹӫǝ*00 3Ad 7x*mYlֶ{x[ vprb J)/#4c۱+2W9xhd+ڴOMP!]]oh#5py_ܘ~{L5-`hGsi0F ,1,H)2;4Zb9n) `1v,6О"FnMK)!PZo,O!_>0_.paV7'xlB4`[{b*ǮW~Z@gG }E{urc!Abt^+2 *֞po@QRRV7 8{v@AT04`i M 2 c, <[]#"\C\h,܋*@I[p/b]sՋj9n+ p蘂}UgfJybmop<̒aE )(fЦĩ}L!f 0/8F`mq+{8 Xq|>Ixm4%@JLӀ=h.0gcҌro1l+:W1c[$'xM؃7_ J– ѦVߍn8u3٥zdp(۠C}IQ$F! jo a?m4L]O3ET=-Ei/pEXx7}v@IÁoYb9&TWslBa}@3Gf)*cUz03hmX6U9"Vչ?iP;hBt܀#'y/˸eP&N.8us[PTc#V@ x1]M-vNkS f·mKz/`tyyY}/P zAL^Tgc%UN} hkN"`#(@{\ ޝ#HAebi|esDq?+ [&E{G ݊#R<FI tE vwVȱ(W,,*l^@EKo:nL^[6/A߳CWd (S;#oT+25E=$>X fY,)QD3(gs ZG~>3󵂩ˆ@<">C)icYFi~>BIl' Z^Nm%E L*xC_Q#NzwoVB/WTjĝw##f.\dm3EeBVG^zgDŒ,޷##/gy"G?5~7+5lw#-t_.@w8o i"S\֠PxE)5x `Hsi)G/f]T_!.fpF_>?'6Œ}xшr[b_(O/nÌrAfꨜ/k@EI^-`wAmP>` x(>Y\\"&t(hŦ!ݿ az { r̔EY׊E7@* zZXlH djVs˷61`!(Vb췎1@m e#u)Z)j 6DN{{4w7ԍW@ucO&x- >#\!r̽)`˦Dp_!G/q[j<[BlftMY69ߞ]~J/ZXm%vq^5Az ߢ&ݻ\mOvzg$R({GVdcɚ_kh]).3'?p,5>P|u~,.rF3^G>Ⱥ_.G])WT(4nS(26 u kSb`רrz ޒhf8G9ʶ9uyir7tk&2|)XZ r 1-Vk! >GB^4@)BJrU1 t>!|{^0n*8@YLn<>Fy?Wt5ۻ:"Mrh)? G׻/g6}>][JP jb9Хz$R=]Yt.+)(G %oXҟ[[]fAe c `fd:=o廰zD9(WqKf*d=)8^Zv)zw |{"z_@2&9~ȣԺ]@z$o(zEby7"f;]ڶ` _#ѦZ\U_h1uJ Z9 LWJrs|$ V#?C S觵[L#VTB~T$Lc>|o+6l~LAaZ"RhwAJ~_x_./$c!P*ToTÊOy7c0⊂xoC"Be>BM1(2bD9#mk/o97h`>/i.Ռ@b)FЌ_.PduP> М䎙{͡nJ޳^LJYx E!CL}ޖ OuDy1bi29@~ksutG~rW?^ؚ Vyw 恨c Sk W|9%`tK+Zq:aЌr׍(/U i3Zf9rC3oRjO,%Lo<\Wo%`]sZ05H5^ $ѠvcK@;(P(Ex Na=Pb#kg׻;b"l:\EPkr0%/P/|+*2Y-zh -4pd8xwqA4л8B/`_(%c9]*ނ{hZBH;q.$W"m/ KG z[MB|m%E L'2)u.HQLC Je]B:})*ju> ""m>CuC}yRjoi LRmo`:)^-^޳0k[&CwC=O /TQQ_.PdZfwxNp *#! *RynX.h?@L!l@t`"8r(?tX0lP6T&sГ ]^~_.Zl\-4߭+#!^t@gh(f ?{*E[Kvg 0VG q4VI+T: Г[s `fB 3_r!ДCQbu -[D 2E4r-PN~w L6XxBp2SN˷Pn"`#/?1G -7HT^;Laaab`;{m|f >bԡ| P|$y-1S~%~w6ZGߍ)GF5Ayyǜp/wc50 >RLk wbS`1m:֍ "60"VτrhEj}W<0fS|6`F\0_paV_f)-fz V}r80wʱՀV4ّE>GxD}]4),`i5CD,G輰Wd:T1'=/QffjQI?^#qTz-@h r*gD4pVs|˄Ц B˄V׋@HqxdZ6b@>[CӐ o:^źju-h?Y}/ /`Xk `kՙRj+xemɢ_ 0KK  ' _@r21_2|1n[)irn.NW'+)2.OG]`-/yR/xe3t^鼢9T|~AQ=pWF-AMhS1.F?SX0ZQ9]gJQ! *>Խ& @`opUh{mz_@rGOcibOv`g,iGUԥqc`Gw0|6\Y1<^~_"ro#еj-c!@ۈ@|(`ݞ(֊{ai[z69ߚ)u qr)&P@/ܿ{PG}'$6D_ʅ;I>RT&Z/f J֋1Cf-"Eӽ~#n)BQtE vwVȱ(W,[ B{i ac'-^3 {alԌrAnֈ(S6ZjEhǑl ;bZ}0-#>G T%偱z߅rhE MD)70_+TҠUt#Z Nl_b}z >.L(|Q[6A>R@ "S o 9Yl`}*4*Zr8|lGp^lc/Œbj^Xvjv$#< GHaWtm:/X#sVFhN ص;g;r1Ɖ2pԥBoM!{Td{_) P8+0ܬ9˒%1Ďd D"\lB|`2@<">C)icY_>`NJ`/pVRT7g(g0 /"g.3|VkN.}hD_}#Q YZ>3{F:~loTSVn J:"G?5~7+4軑T/;ԋ-L JMv[׆bt+2 -OG9H)([¦NVN!?cuQ}_.<\?|{m^,K!.=g *J OA975VEnj3E;+eBpx*he%bbTƙ"em,iKE-L0߲)'޳}}וn#7TYbE"譐o($͸2qtzA[1[GAge2G]y"(g  -] ~n^̃Ӽ/xT6r1ۧ$ނ-}Ur8tUD XH\bx ̷V@lB+ȜoϮ ?-O K6<,֛k5i&h=~"ô;#Bu;rB&w/Pҽ/܁.F.|+xCW˹|[Y|NxO?`<2+ 0 ),| >\=P@z_x(>`?਋nP9] V+ *} M-|pp~Lq 0a=>r J IZ#bQ#;#)(mq~@Q9ˑirz74~5g \, n\By >U~?|$E"yP^/i 7iV}Ab| ,|7. Rm#@5 (y{5ǒz*xKm)46fd"| Bm\m\cauAkʡoCE1q LE0~rR.*W4&,Ӎ/~\EN/pJuBZ!ZEEEֻ6`]Dl[xEby7"f;]ٶ.`  X)1xNiVNi0Uq@Q_>a:`.x`:XV#?C SLx7r] xJUȏꃜG fA> xP(JJ|9V&Zȃk Lc Fp܆͙ό_ RyxC}Oȴ~*p.|;|VA=բqs+{hc/q/wrzxEZtam3m6#h#a@HZ=>r>hqA(<\@1|k¾y@RSX+>یv? aP.> 4:`*6r_.7>) o07u\H QoVRY+2g+Mr)bqZK#,,DkoH¬Vh-_{!TPKTH;R4Z=P%CۗXg^j}W0&"m>C-(XRjoi LRmo`:٠"Y 0L{m6SjxRrGLt@@*@Jɭ903 d#EGِGhJW\n31hZ?^=Tym Vd{ovEF_`m+*8.Eր/g%u(} Fe)avD?LL|}C3Ɣ^cbThC3(/8N0R``fGJiMݡSq`|<Ar[*P^J rǹ)3#@#M@UA 7,gy@ BT7@E qgP 3EpaJfͱ˦*sU;G؊}:Ô> |`rMȃpz4E"x)o)!L\&pt;C_ _j/rYt/DZ7t5 _.@ۈ@|(`ݞ(֊{ai[/yrY[cAIS;A-P?& b@4֜DFQ.rY}g ~;GJDLA z12#戒9~aڂChڮ倐up!>ݷc-=Qt(XXG]!-XRSU_> 䰎/ua/܀0l _>gmjqQާl0d1~oT+25E=$gY2ؑl]$y@>+MZ+1Fˆ@<">C)iQ r97#!Г VRTjŇF 0 #>_>PQ]jy݊okN.}hD_}#QE|fdqt< Q}9CVn J=2ESwHR#{̂]BLP#pF@hGE kL(GqV#-j= G ӀSȏ_>ͺB\/<|9{m^,K!./+#ڷh n_>@0\:*'j3_>PQRs=wK]tqz)-<Tz#d@wpq;R"<*СtK(aFX9seKE-L0߲)'޳}}וn#7TYf)L an6B 2q,n : RP?s-+ /pԥ/kG!r,S-6oAL >Ҋ`d e<EArDp_!~ 6u@/Vk-!z3&Sz: o;ˡOy]Y\M#0|^0̃RZX`#Jw\ P@_>pOQ\`/pEf{<7 .Ni]*oh{KG/y)\bV J ~jqܾ/F8ڣQ-hrdpd㥮uكnrsOuz2Vk\Bn>4>Uj[_#!|/|!}9ć_:s=H/aAqb ,.WE"@<^{n^Z lB&Sp~sLate>r/3#n Tl»Z;u*G0ʢ;tYHAA?\ (y{5ǒz*xK;YGP7A֡y?T$rD9(PeQw\0P/o-{LNgupW@S/0@]zC6SPh] ~ `0KVhlm^Q}Xtsޯ#$Ga׋rm}JYvAsJ0F[3a]79 /(ZZ R+ΦO֊nYwF0/X P Q} AU :G8owE \?r|3?s ڴ.1ρv[^s6g ?O ^Z=Wp#Ez|Oȴ~*p.|;\@+܈rmZ-ZZQ8߽,a(~9]k^cn@-f n? \X6@~v6| ~| ,}x0PNjrׄ}!R!zۧV|ʻYW,m-0/^TbR^Ф/P0J.!.vA4c>\`_.V3snЌr}_>P\bIŊ(S!5\lur}#A93Zlӽ<<|=uٞPkm1ԗ=LyO&6SԪ,u\s=6_[SVocW9̯_[j ?ZG ff߁rLCaJ#tD>RwD]5 U i3&f9rC3o+nLs"n8"e1,(ڍKsZ05Hܧ8^; m-fa4)j)Nl+a#JeQb#+>< Y٣D ίwwXMG j-Vk<ʅLs2ZBj> F/(}*]\ @-- iL|#ŷd|;:UN@ܽ`n 븐Dެ`Vdm|{.$W"Hⵎ^#G)o5b )0f-{ E)2 5V(y{u p%*ju>֊}yE *kEo }ǖl *^G 8G aV-V6o0= u^0m 0{,?Ti#;< fE\`v "p R(_# zq= k?6r_i mbOUz݁1~Nzr6ˋ/Bk>&u傒yd99{7=py`_(Lj:{GF!+JPY=ƪH!/*wR41zrkNLC(Ya@4rQQ6.bu --Lmkqz=h`apaAEU}8)'[|]f_XGc[տ">S}kA bU؂X~QJNGhƶc5| P|$y-1S~%~w6ZGߍ)Ĩ\b fP_p1'`"s ̂AA;"ӚC yL6 1b#ŷDR`<<L'ހ_` <ìMLouF"9ل3h/:YT_ 2W~Z@gG n(c!9RLY1r(.u2E+2 *֞Mv(GM3v3SOG% jy 32D/rAf J,:jmn $̞֋^jE ۭ#B:; Y'Ug/ o:^źfAs܀F/V +:1X̔t/P[-@Fgi$EF#x=h[m=<Rjyˈh 0nPc :]-η[/0cA *WRd]A/Ȑc*Xz7Nj4%/ئ+*F}e+:Wt:^_pTDO&t, RҀ%@m{#p؍[p.3%Cj p|$FT/= ݶ yo a?m4L5 е;SdIK<.oKG(O+»@ ,=*(J[B<ֽ B ՗v`f p_>b!"R|}>l>Mx$$̈rͱ˦*sUP֑mS}(aD؆"A\8A,{8^=5(RC@8LvtשmAEPG _"EHxtc[9%V"S|(`?͒QZQb/72-v1\oA)Y}/P[]/) cl, թO$@mIl`/ wV߻|)L^0#Sl?b(G5PwaˤH _@wu(iՖ@NQ 9Euҽ%5U{quXG@],Zzpfز=;xhKP>3 L"SX[4Hc6[]tj FPL1>GBysv2򘪤5<0`¶-C+Ppm OɿZᦒ/'bw?>t^h& [Pfqe E9j'ڲ2&@d:Wme/5`/di ^h1z"n\0;01h{k& >>x^ bs#pAHaWtm:/pxDsoml5P(T9;݁s!mh> ^h \{5 /4Ћ2#E9R@jq8Va桹Ys%K AT?D"\lB9@0Ux Fv!,/0 H% Zg 8oro+)R`*P3p3N@)RˋrExӀgx[LFy2ٵ '>Y :w8/P1+XGaFwHǏ `7p{G7%]^xE Εz_H]^7ڴQ)pkP|m(F}l xE)5([¦NVN!?cuQ}_.<\?|{m^,h /6}zs[47?et_L6`w!`Ap/۠}XLgVƙ\\"&t(hŦ!M͕E/3|f,܇ b}^HQ\ _25z+䇹 IY_+A[1[GAge2Qz߿řkC䴷GHKsxA8~P7d1R"܋nx l@UaQ{",$~_.q[j<[BlftMhy%`%Ն K6<,=6 AG+:OT}@)P#`I+dԴ/P!{ryd5)N].:#W,3^P|s,>p ru'0ykXȵ4г^F֋+.Dr@EB9"g.2c@ڧ\vX}(3|஢?p.6}$^IQ#Q3Eq;p3|@*#W˹YS9nG Ă=GQwF>1Ucw;0 9we)5˹ >T2.9w?Jmyn`҈rƭ6@Y% 6T_s'-t{fpVncGx-lNoъ>ܻ~}1|@&|ķs5> 0ʢ;tYmD=L%bUGawYԕ)ɔEmڸڸꂊ?C= A1.]3Ed*[/c-v^@Ngs'^"F aj8]Ը (pN<@w N϶uWT8F@њa+=,XCBk7%a) y{I|0f [3a]7x9Lc , s6g Ospȷ2TnJ>U"ū?_źZfz\."#,X ?\87[x~86M~:.HG (?FpM1(R}*˱n!A;>CX6{CbcPBBW;4/~v"`;K} ȱx_>`Bo+/Or@MsbIŊ(S!`z!bn0Ts"<4>cfPq%kYLJYx E!CL}ޖ OuDy1bi29{@sk5Uk>v Xw5ZG lb.92Em۹Ô2YrAM Ei|~4P<{FU,G9_ΰ_>PZ!6h~E?c{G]scN )ؓVⵆֈ-fa423}.]ډmE9xB[b#+u` K1{lH5B+!Φ-GZ{w])iEΌr;t˵W@EB&kE?P-V!EL>P 4:GCb#WXUE/=D|6S>I 榰 Aa J > Bڡu&Z}1}@uBһAt:[G z[MB|m%E L'2)u.HM|j`P(ҡLQQ[y/pVPTwV>:!-V@ZnVWq:|C}Rjoi LRmo`:)^-^޳0k[ľ|PÓ`g ?(/PdJm c9L%ʊsJT"" a@såѵKc}_4ǜEn7 vw 2q̙/xbЄ|fYq g/t@^!f y1\^FJ*Ts *ZѺaU ~={#\44R9LU6rQQ6v([4# T2{)-@zaLv `ap{[$Xڇr ^weyy-xx v# 1*lv,{v=ʷwU*@hd+ڴOMP!]]oh#5py_ܘ~{L5-`hGsi0F ,1,H)2;4Zb9nOyGobyX9lml-kф"3)>sSh7uso |}%H<ì̎+xS42M?`kyL Sz5Ǯ {v`k͕Eڣ#Ŕ@,  ^嘛 Q}#QffjQI?B 8 2 ~@4Ј*gD _>0 _2r02`2L=`eЃ.!.BId [餭8yA.E@7`шr6ATc:3SӽCm8- "gE$EE#=h[m=<R|,/=UhPLq+{8 Xq|>Ixm4%@JLӀ=h.j`cF kt^鼢9T8*{'`:})`TiA Ԋ6q 8G֊R=S2 o8mP>$WJ[H^zD#5\冏6qgj'ؙ"KZ%Qu)vjC6i/pEXx7}v@IÁoYn>"EWslBa}@3(*-g #}%̌CmX6U9"Vչ?iP;hBxO|T9HZ/㞚(oНeGw;Nun * cm!戠-T2uu)^y#b_.0.!.^L@06"JP~e4֜DF\|"ע,eSEk̢W)RPh)(aZ/F8_~Q܏j 3ÖI"iAo}4`VwՖ@NQ 9Euҽ%5U@4:NfwGa 00ӰƖM!B-YC-n0 v#603ՊLa >X f}Wt ]$y@voT6!TO54L ГE -=@em!&|$-x+7ky9A٪ũ@o C)0 .#(rfTw6(*ٵ ',Z/^׹{HT9@Ǭc-Yܽ߀2Y<  vGwtQy8W\eiKՈrC/}M ׆bt+2ݿ &`хU-P[aS+}g6 q1|3v쉷 {f_o:_.`Wi4/t_.LKݡ D OA97B+"h@7BVtx#%ȣ  ڱwi1:fHGmcI\#ZЂ-r=w]Z>r(_I@ey"譐o($mb CB~<$_G.fY*AQԶP&<|Qz߿řkC䴷GHKsx/-kyP| F9^t[e" sVNړ`!ƳM`%VoF؄W69ߞ]~J/ZX{TPl aEhE編Ia3S[GDoQP2/0Sm {<-Lm qPbQ#7#7l58PTrd 2-Vӭ9_nzTT`j퀐[]ACrdҪ|mtk0) #!<.@)BJr>b~eAHk " M{̃X\dP@vؓ(t*`L7q f k./#j-V3j#*6Xm11DkxU\PCQ#T+e"=s(h>ovT0oc8&#c}2e`F>!~[6.6@kʡoCF4^XD4T|M )8^ZRnE2;݌rs;pq_>S)KJƾ?j:E_.0SPcѝ=mWT*ݜ{# R`hMӕm,XCBk7%a)hu<$>R@6Lavyy.`Gn-G ~ wgݧOkE`L+*W!?rDa3 A['N@(a+qŗs{M))צ}v T`w_ 3E[1~o )-ϳ7}%-EWu1[9V8٠jQZk,SP<~{hkEucؓ?e\~9 k^cgg@-f np,a@Hn -y_;(6M~:/H9B3(?f& ɘG )>Su| !,!11|oC"/_)htۀyWZ}t ww97Ti/o+9` b㿜i.|Xq)F|`z1LV7*9xD\13w09m\ qiC= o`NI ۠۲=i9Hdr 6?`VN?]{6E~S՚ kx5Wpy@kf| *bo߶{8L)/(>2N}a#oqKxKwiW}hj([1oRjO,VDT@1,(ڍpƜL{ *R'R[3[h+df:7|rLt h' ޲(sCoa*RlywV>) o07u\H QoVRY+2Ui6? F6csZہ$^腆wtf@k1ړZBR>̔e(E %o.!ھ:[Wk>""m>cKhuWr:|RjovN5SDTh[}NJr"|Wô,L8n{I7PPӓj**r"S%PJmka*yUVCT m0/ٲ)17]=]?>5Jq~F?mW Ou&}̙/?pW-4+#!+\P#:{GF!+JPY=ƪH!v/#Jz^HpѼ&03 d3r}K 44P)XB-fQL\ǹӫ*00 ">̔po-T.3my#XGǥ`)5 1*lr( 1f|{WF{KÔ0_"E{^&L|}Cr1Wk0Z ʈGsi0F-Ƙk` | 1 Ƨ<ãf%+ل3h/:YT_ 2W~Z@gG \YTi=h9RLY1r Ql1:/lNgyIkOzKld7׌(K#03ŮWJ|p s2D/rA4P˄b!af~32t:-,go|<" ` {qRE|q:i#@U uU/;fX X0Gc:3SӽCm{Eo(@a(H#؃TF0Nec )Z旞*c4R(N]7DcF#o[TTEG]4M{}8Lg 锶A[ Q_Y6N+CN'z6!Oq¨Ҁ%@mq#p؍m i.3%Cj'P:GbDғ ن0~[nOv.f*֥]{H%_(1K֞<i/pEXx7}v@IÁoYn>"EWslBa}@ >2C@ELQ!||AhmX6U9"Vչ?iy@4!:nҼIeSs-EYx> W/~"3x RԊȽ@> ^T(ķmK%|@Üof]B\ @+2zalPET: h9,\q/MP,vVŅ,ER2ve"`?+ '#~T ^[pH=-RGy[G 0pjK O-!?$XKO+ fZG]!-XRSU@Qi Zzpfز)9 }^9ڒ5`Oy,>2m3S80 _3xbSLϑfe䜝<*i!ƂZ_^ضrhE MD)70_+TҠUt#Zǧ"2 ؄²P}zJfqe E9DQ[6A>R@ "ӹl,;a{!'H _ZE v*@h_>@ 3#s#Zh1t^h9;(Y$ހ]{#LQsv/'C@k(qa G]*:/q4Л|eO3H}f>>X fY,)QD3(gs ZG~eT=Yt8y#┴icۀCL2 H% Zxmro+)R`*PʌG/tһ+x </`+DPQ]j݊okN.}hD_}#QYZ>3r#l8 VήO "J/Ex6@543B?*2^[d E9_S F9H/KiT96ur wvpxl.rgd9_`O:̃/`WQG(Oϵo@7@/L`i倊빽["?۠}XLoq!+CPZ+$ w7V^.6-F m,k^-h}g L9YE뻮|Xts$ʂ/8RDm @La(gBP|lo)b j[V(_pԥ/kq9%@P7_ԍ=൅H`#Ws/}J-زiW9+'sDI@x9 mŪ_o ՛E 6啀 dηgGҋVua] K0ask-jvX}@)P#`I+dԴ (f@n)߻*S\uG?}Xg|[Y|NxO?`<<+ 0 ),| >\=P@z_x(>`?਋sOE)^QgT]E]mnI Gf⸭wg2XUGsA)A1Sc4@,3rU *ScVu+xSZ\P+0 9we)5˹ >T2.9 BZ A_.~"wgv*Ƞ'9|Aٓ?PUbv*dao0 F_#\ܻ~}1|@&|ķsK X tYHAA?|7L%bUGawY}1@_ 0#~[6.6~z"AkʡoC."2 _-E ]Ej]v `_>p> +ȩtNi.!c(pN<@wml݉ ٶ[Ţ~!< CFXth1(Bc+>nJf9SՇST4\F2)#s|$|@rg}Zp6} bF 0/X P Q} AU :G8owE oŗs{M))8>DDcLn+'m؜)<<>V{GLsimG|K)@<>@^(2-_\"L]9/niw[xe2u7VV_>^a^<dw9[̴l E.V@  n +_WGF R>@ʏ\d#Jm rX)ff]\QX#@CŒmHg z_׽A;w@qGs@4cJ+B̹A)/4 _.(]x2B |@)C"3FL1M&`9rruwny`ִH_[w5ZG ff@Q9@| W|9nX&/:a|~4P<{FU,4 _.,T @+ glxzϗ 2}_ȢrH<7 0`kP=O]p֐_> ,#@-]ډmE9xB, @ld[=uA[</Z{w])iEΌr;t1s 2Y-h -4pd8xwhq8(D!`g 0/ߒm OFMah1@ԛl֊LBڡu&Z}1}@uBһAt:[G z[MB|m%E L'2)u.HQLC Je]B:Ib{uz^sqZg}۶B%[3R{OTf mxI\Zop Xzm?0m 0{,?5**3b/xRj[XSɫBif9E`8IѵKc=a{cni߄4%U,^#8<|VI+T.: Г[s `fB 3G r}K 44-bz~n%ȵ@8zܩ3  ` -O 2| ,6k, µ&K/`)5 1*l3D)|ffIʷ|#fK(c.7L|qc11*`Xg y r)Hl0\`P#ȴ`h})m0>f6 1b#ŷ7U"3)>sSh7_>0_.paV_f) [X &T7 NVa19:?wc׊=;RʢzOEȑbY Ybyat:7cNZ{қ;4 qG 5 LՀ~/p(2D/rAi, _>  3\okxlZvȴ\}>X Z! ⤊2x-tVGkXz7Ljr4g#bWPGeOlB"xMJ– ѦVߍF?~"ŅkE`vـJՀB]2 ؓg%J=52E^zD#5\冏6qgj'ؙ"KZ%Qu)vjC6i/pEXx7}v@IÁoYn>"nk$ʅ8|3Ќr@(}d@KB8H_@ 3|ieS*#Al>Psam~_>0m/[]a݅r' +{c=Kj 3۽ 0ӰƖM(if і7;}C L"SX[4Hc6[]tj FPL=AM]n9G*i/84m Њ&\6So`VA G(82 ؄²P}z >.L(|Q[6A>R@ "ӹl,;a{!'H _ZE vӻyVi.8G#s#Zh1t^h9;(Y$ހ]؎kLQoډL]C %qE)u[pwzN~@#H}f>>X fY,)QD3(gs ZG~`0<#pJڀyXs߀PRۏ =& Z^Nm%E L*xC_Q#NzwoVB/ .5YGLs㑨rYZ>3{F:~lo`h;(<+Rp㑾iKՈrC/}M ׆bt+2 -OG9H/KC .'NVN!?j6 q1|3v쉷 {f_o:_.`Wi4/t_.L`/(˻%.H~ Ǹ}ZQ|G *h;)DMPK:Ŧ!%q[%"}&o̔EY׊E7@oJ,3@Fo0|@!iSY_E.GC(HCAԶP&<|Q&;|-5_"cE N|.q n}lϽ MG 0`d=I/q[j<[BlyE 6啀 dηg׆ҋԅ%v1?;l}n :EM| *tHA0HP҂mXcMNPfR[[CU/{!G /aAqb<8U@>P}}Dm=yBl/ T! {)8s0S#j-V}E҉2MxVkԢB˜-#PT veV_cI@*ixKٰOccL}O, Do))bTa|CE1q LC H&`q >v/ / S_ a®E (~N:-8_jvt'hcz@Ţ~oD  vұmM@=[Oy,y'`#ofW#QeEo-?C S觵[|5&e+*W!?rDa3 A['N@(aZMr|3?bypmgi ρjv/۳`C07-@쓉 ;cdr g\:9T[|U&,{\ >{;Vy9vP W|90L֋2AM E/ⷵ̾nG@ @Ӿg4_[Jr- ^ ߶eGZglxoXE/bYtQ XZU0`kP=O]p֐Z|[hL Dvb[Q+P-Y17QR}$RxvB+!Φ7^+W+7G(rnΡ/^y KUkcZ(?8#its@5_lG6r_&wߒm OFMah1@ԛl֊LBڡܾwt Pջjk/)R`*8?)L[pARdj`n["0b{uz^sqZg}<cKh Vڛ,ݲ4FD*0[Dgp>v-׹S2GeEK: 0Th10J{6]61Lcn/]si}' 6r3qmc3~jlPiCݡI'Wg\2bЄn]fYq6ĈW,f^Q/@7Q}Sv/ފ_Tn`{1heZ%]29MLܚS3JV) ((Mi;E .V[D 2E4r-PNT`6-l5H*'3| ,6[(x4{[n^ݷ X-eo̒:>RD#[Ѧ}h ?w6Zݕ ݘr F5Aǜp/wB@60 >RLk jb9nOy?a@{#(V>[[|Y}SjK)!P08w0x~/so |/%+لFv~AɊ"E%:EhBa}@7(*-g #}%̍2ͱ˦*lN7#h#? hyvfOvxBu"x@,<eGw0 "s,i&DZ7t5o#J-u{8j"@/72-ve1s_&0bk,(BurD)TRU~P@4֜DFL/fBU$)E *3%Lt$bDq?~-8Q0oݡBQ.)]X Zzhuto`IMU a_-^3 {al4VnmjqQާl0d1~oT+25E=$+K\ߚC/s8R# `Z&`>gYPDC. <|͕J&j}11eZ @O @Tey~~_PBO/'k~_(v}>(_ 0 /"./ _#f.\dm3G_}̊>@6c@xbD%rwtQy8i@GpcS;8o i"]kC1:Nӧl#G>#]\/ {.: X9/۬+ō2gev쉷 {f_/+*E i_4 @pL:*'j7zn/0 6(`Sh[Dy-F `\X ] tM1C8jKⶐ KE-L0߲)'޳}}וn#7TYnGh SB~[ ) e,X Ƚȡ~ ʄ/8RTA8S@|miy< u@ؓ ^H`#Ws/}J-زiW9+cHQE_bV5[*~Mhy%`ٵ!czԅ%vq<? c)™ )#R DBu;rB&O֍:$e;}<.|+xe/(3/>\x5yW>`>r̓RYX/`# J|Wz"E:z;EEG]d}.zNi=*whwKm{;p~LQL> VW˹q;\ U(>h3Qs[-(*g92RR[F/b9Z#Wu2>Vkn\i|JwH`>r LRӉ+?S._6p{Sm DaЛ@Y]2IEkx_}e{iX]v@ Y؛8LEÅ3gȻxj{>C@iѵ@&|h\(z=j(C9]Ytzt"A۫9ԋ 4VI[ކ)46fd"| Bm\m™"F_kr(}E8SDkE?H2bKY| >w `_>p> ;{0[a"@]zCP[?'oy/)U߆DAߚQ<%[Ţ~oD  vҳm]@=[Oy,SFJs|$|@rg}Zp6} Vt'x7r] xJUȏꃜ+^k :G8t %L _α5"p.VD\%fcevwD93hۚ_{Z!/ R/vAb )F\0LV7*9xD\13}w~`ns۸ ,"Xl! Eo:d"<`s14= k޹ښz1 y5#^33{ 您sъnP"o_"E?c{G]}FY\1^}*㵆ֈ-fa423}.ksSxE9xB, @ld[=uA[</ZeLI3(rfޡ_**2ya*#itw5_hZl ;\oylS|6 榰 Aa J 6kE !G1k-/`n! z[Ms@E Xq \Oe 3S=\X+ʺth2STl} \T:[߶lqh_|KQ/DʐR{[6R25(Tȴ]N}eY 0L{Cb_vNY~Ij3UTg(2-; 8LwocoB<7tw[,~n ^6 pi}' 6r3qmc3~jlPiCݡI'Wg/xbЄ|fYq6ĈW,f^Q/@3Q}Sv/ފ_Tn`{1hZ%=PR&&@On)i%+̔_.F.>ʆ@ьg%u(} FMP!]]oh#5py_ܘ~y`Xg y r)Ti`P#ȴР yLcΧucH1 ̺±3Zф"3)>`m#_>0_.paV_fGޥVT7 pa1zc׫?vhݳ#}=h9RLYj Ybyat:7cNZ{қ;4 qG 5 LՀ~/p(2D/rAiZ~*@H~[e/Ԋ[GjN8uG\Cgk@mr[餭V%"(>WpY)a4\`%`L>֪33M@PLݲ/|DPK8Au *Wф6fBQ#3TZ±χG*=J\4ǶO,UAb+ܟC`Sn4ߋy@hˇ[<GxKQAe2;9WA {還)8{/}LW` T(ķmKr9/u q5T:{^{) *?AN} hkN"`#(@{\ ޝ#HAebi$@(G5P# bվ;T:jY݅CW[Q|";Eջ +XKO+ QWHK<+Kj 3۽ 0ӰƖM!\HV2-YC-n0 v ,<ƯmjEhǑl ;bZ}0-#>G T%}N Xm Њ&l{>%kJnP|D݁#ЀM(, ǩo]P nT- h υ\y րgBxq@X4Q^#J^XvjvU jE żky츆gM#xvv!P(T9;݁s!5N0.rh \qP_n@#H}f>>X fY,)QD3(gs ZG~>3󵂩ˆ@<">C)icYFio=#!z3Г VRT7E0\wWx_.`+DΌ򁊺R#|V|]priE{ :w8/(q;qԛ6@xbD+G{ F>视^sF RxH׍-!\y&z_]rWk5|ZNhQs._΍=\NMB~ԈmEbg3obI;^ qWtU{'W-1F#h n_>@0\:*'j3_>PQ/0lU.H~ Ǹ}ZQ|G b3\ ] tMQgܗy$e^-h}g L9YE뻮|Xts$2[![$HAWoOilhm Gޑ2-gn7w1TPfR[[CU/?͂|_Elg|Q]~sЄ<8U@>P}=מ|A[Vewd_\x0S܋'.P[}w~Vzf\crMxWkvA.Z TP`Wݡ `E A۫9ԋ VI[]f3ue c}2e`F>!~۷̣bTa|.C."2 _-zE {]ؽH&`C|:] +٫;l!uJ{uBG= 7f jlBc;Aǵm}+on)0{&GJ׶ >fPhlMy,uJ Z9 LoUHT@rg}Zp6} Vt'7r= xyJUȏꃜG fA> xP(J(c5kELO\<64+V齭N۰9Sy2]V{GLsimG|* u%W'UTKXs_.L͙к Sws+{hc/p~;^ȃ1{YD6[u]"#,؞ouvA^' F R.PNjrׄ}!R!zۧV|ʻYW,m-0/}&`"M"D=J.!.vA4c>\`_.V3snЌr}_>P\bIŊ(S!5\lur}#A93{sCƕg.6>۳`C07-@쓉 ;cdr v0+'\g?P+^y?)jM[Op^y@kfy * Jmy}.[Zeb4(t'{ R+R]U i3Zf9rCkmBJm0齀E?c{2G]}FY<1^}*㵆֋r0 @.ĶVPj+&e[Ma>VC)Hpq~)BB-fzZBH;qQ1݀$ZG/4,Dx0wZ)֞."ZBR>̔e(E %o.!ھ:[Wk>""m>cKhuW##R{[6(t:Jo*@dZ::"o0= [I7PPϓj#UTG b/xRj[XSɫ R(սw|0Ao l@tXOlf.f]'(j@@e?'=y3G}_@hqЄ}:QI <Jt6&f /}hdo/JPYN70VG q4VI+T: Г[s `fB 3_r!ДCQb}E SD#עqnw4 .l5H*'3| ,62k, µ&K`)5 EB]޽6A>B31KPGFMR%~w6ZGߍ)Ĩ\b fP_p1'`آ`fGJiMݡSq`|<Ar[MK)!P08w0x~9732;MyNj`6р_lu"\d]صvώ,z@{urc!Abt^+2 *֞Mv(K#03ŮWJԌ~ ~@4Ћ2*gDj`: Ԍ,j@X&Ԍr87̾N [>L烵7eb@>[Cn;"N'muuU/;^,VuL>֪33Ixm4%@JLU_TyooqE_.Nj4t@Ũ,yxEN}lOb|(ǶHNPбS6HJ– ѦVpc7ѷ1`r0Tϔ̣BeT|{D@`+eO_:7-0Cԋߖ>~Z+L]{H%_.(1KV O+»@ Ӵ+JXpn~b}'t˾)B vDBs_. 4| >2C@ELQ!||_.9}`Te z@[Tsrۧ^B aA:֙ur,{8^=5(RC@8L!AaΕۇ"42@)8{/}LW` !TCP}0Go"KK򀘇9ߎ/u q5zAL^hnPg T> 5'_ <`V.DY_NR2z1SP´^LJ F`̰eR~ZaP[*C<]8t%ŧ+,Sn0Dѽ`auto`Ixq7Oq֌EKo:lܲ݌^9ڒ5`O`cz߶Vd k|f{Iyr믋Nmh)HH32sLU@ PhBi>%kJnP|D݁#ЀM(, ǩo]P nT- h υ\y րgBxr8|lGp^U N/x%`/,Ljj;5;luLjjV0Z+6xΎk8 tXe쮴u)eۥ_gbv^ x(Q}}#@aF.&DnȘwG7(J:짆^sgF鷑L; eT_PxE-5y pӀz_.ۺ(~_.<\?|g⽇SL=# JV,mJ+8iO9 WړwrAz__ ⋠X. s=6lJ%`¼,-ٱ֮I@Q{DJm^D(aSL6{9vlQ>|.]= qra(F׶0oS 3/(5\*w{W>`Fۃ!^JW(]hEw] TP=/[H~Q2cKqDy)={3JX|T]E]u^IP(z!qw့ebQ \-U1Qc4H]Q3!@;hvy28"x3Wӭ9-7,?pU !Z@uWuC FS?xKvQB=4y!˯dC)旽G}f`"g# 5,/ҺxO4t}4ۧ:E߇8 0CyQjENZw|{V|VT]@UVk Zs| PC)+`*؅Ew"ߏ "^J Rzvŷ1{-#c}3e`F>Bl[6^mgņrD>( xK&*~ *BpR~fE2;{R9_.@0Jex (9*356؎DĬ~D 0 ;m]X*6Sb6>^!OU!O5 *8LL=|]͠8>~R" \ P8P_$4b@=dNۜ,@eQ S*Zα5"p`S" MA8 .`w{< az;b~ku a JܾU"Qq%wKX,9N/bLz<֢tŞ-`sE_>]ݡzn_`a> 5fl Y&V@" 3~"Z=>rFiψb O)Pr A2E!GW4;,{osH|v~ [`j&m6"`];@\i%$>X{l/m[97|`4K _.sV2/ A_Dή0s"4js}sL=yQ]JϾ^{(}g+αbՏ!뽳=is"41ber3/0 W=LgЊ~! Mպ-9' YO_^8q?P+҈L^ /mS (55̍}8*yԦ*!OT|h9cB )Ræ^}K>/ȬzQrY\1W [{ !ؓk|g ]Xc.Bf~cE6b[WDP:@+J%@cG_ "tba`J_>@3.]}rm(\f(CRvD s_(a3_hq4Hįdbz;MFO7m.bYjEBڡe!c?9^NGaV~[Z Qt!0h3Q=\]@P(ҡBQZ^jMPD 01J] 4_Rat 2Wxn2U%{H`nYmo`:Q`` XZ(u8IY6԰5Dqt@DڻȧI10P z](17L?]{4_>=a$Ά2~ڦx;P8̙\y@3_B{RJ`(+FE*yirNGU?6sO\)m(\4L4+)=\,ʆ4BSEU Q E Mhl+UUhN& x*߽/X,"MDG/`c?BoCL<|;F=|̩C.Q]Q}hԶ=MP ?^Ly-&Fk04yƜp;Es ̌AA;QT`h}Cq`4f 6 X8lml+HK(m/@9Lcc5yA i/) *GX *Av`kiLإ Qz5`ckE!uPi>hrc󁍈hW$|CƨXv>K#0ũWJ_. /g^Jq:]G\<@, lzQmV4G}A$\ 1D>֪307!;Lia3iUH/Ѱ*Ncut~^*h%@T0p (K߽ͭ>^em޺bTm5Wt:t^*~?w"ʞ XE@߲Al4 l u:{pڍk V.Ꙓi($aP>Z((1zIlChFa? SL"s|@4(q_Ұ" ," M m@UPX ݲ|DPUAuE qgP 3B8_>Es4I2W}rD0 A8DG})D "O ]{rdRr,{8^;5 Aw(' /s ['ׂDH#!8/@>[W\rߛ(_) X% ZQr9N/e q5BurDUNm  iE+*hkNEJ^.rY}.Q\E3RE*_eJ W1xC݊m-"DSņj yGG 0[t%ŧ;qR>]X Zz"^1sw i>X r@q{,[D_G6 " A߳Cjq^S6l~m`&Z+nJ80Ҙ_xQc!ϕfxe LU5\0腽ZQӦ -T@h*%DBVaaY`(>F"`C|Lv"Uh{"-EQ< +ނeNr6i` >[QcDherK `F1+h[! Je<rާ&`6QhEƼkx7q Co7QjN صQTB(qrv'gC@k(1aGYr?ZjyBg\`Z&`5X 2ؑl.H40Ӏ}WUF1i / ["JadW=@!VeNP' q()B`*(r"_.tҧ+ , / 3|@Q]jy݊o3ٵK,L#J9|(ll^oQ#crݠ(GDVxEΕ(6"@r`ANJPj[ :W$ZN߲QjQs^AA/upC8<._!.pF_>?3qyl}mfhXKThy#p( 2QGZr` /P\*c.H~7zCԊ1!+CPZ S 8K س (m,{l^-hg D9YE뻬l1m!}%UG Sw0|@! 0`!?[슱oލtR " Qr2yNQgCL -S OTLYkVBg^4+sDI;t@z__ Շ"(V++Ȝoω.ҋ;( /K6r@lٱg]Ԥ3) QBώ9Ud̽J@22Da(Fn|ԧ< ~?`qW||܆z(/((B;Jw\ !TP]/(.H^(K8MДu5J{X@I;z k 0}h!BJrR/xAH3=0n`#4[DJA}NZ(~=w?[yw$Z! !83 ateFO\PV|VT }vJ»Z;gL@d]תbB t0?`AמW_.((y{5ǜz*=@,OccV>7Sf!Duh-P|Vl(zAb |(׌o&*~=*BpRfDc"3z(r<gʢBI랋]@C(2Vhlj݉ m}+n}!0{&(t36fb}ThlLi5J jBB/p/0x[<0,rk=#A!>-5p6} T+\`_p%@C} ҈=) zwQ8os!D L?Pr|3X ipmwh g@r'Ͻ9C`#&@0m_,@.[%ȩ*/^bpŲrwl-J6enoZ٢prwY.0E[|W1EP5fl Y5z@Gf7 ?  m4JFP&`?}\@ʏ A2E!GW4=},}NC( 5$LX/m"D /gQArٶ5\0熚_.hn!F!k"Q+ "\1o^09X {낹w{B![!ib>x#Ch)3v0 WLg?YT 1WkH׵}g{AH#^33BQ8@h6!0L1ʽa(bZ=eъ(ڥMUB;ٽ̇_3?j@hZ!6Q^MYg2@1zQ X-)\-l5P`O[W5v=/T\ {D NJ&mĶ"BG(Vr[0bK$³{;1ĽVf/}_`Yp" E{b˵Up!wPo SH@GŹ/TEQAhq4Hįdbz;MFO7uLHƌ >`sHBH;bd<׵N(¬~C?vIS1 PLePEj@Yb}@DjM&`@}4pu@1yՠlD4|5F "il@Ɯ7Oh>/D>4ԫG% 4PpTDO*t, B`SaKSWԩpk7arZQ8lgJA <nr5t+Ĉ'AT a93 iy&3}!2*!EY`G;+P@HÊ4n(PUyo\B(>]$Pnyv&5PTXQ8E7 4| ž2C@E }?lF&D 3\Es4I2W9J0m-cp4Cog@l#'PnX/ *"P&N*`skA"Pie!8/@>[W\(~o(~(`ݖ(jEY^+o$*vb|;<`%E˺*Cp6 ^T`9P@T֜<p!*tQTD A z1ʶ#yT  R(@)6T7@wP8:jY¥-(>ݯSPȱȺWd,vG̩* /D9vGwz~L4 F!{v;YUP^S7#(m֊DxR>$4fD6`b{s%$^9w'#JƂ׵84Q+`ڴA󳅗J-WXE7bw?64^h*,, ǨWl5.CTCS=GԖ"( \hΕgo~TBN&-lg+jl[>/L(fmK?D}Vi,cGP  Zw(AaԘq׀c(5'mCPB(qrv'gC@V%Q}#7@|QAN2ZiPr>3: 0ӨyXs%s A?Dp E`(bz_(lUx Fv_!,O/0~ QB(a Г|GIQRT %\E>]W`_!r eۥ_gbvm>'=P\Z>f}oұyADQ~! wG7(J:[VxEΕ4efLc uHT rWl(FڊN@-o(9H/_w ơH: X Wp&{؋95*E?ѥHC⳯2 i][!P MpE-x`=\ȩ"?{C97p1DJQ|  ;E;X\TD*t(h2Β@1:ېƒXK^-hg D9YE뻬l19r(m_I@e"*]!?#PHz!L *`W}n>xP?s-W(~_.pETϻE ~w?"=@Z q n{bDX cEMI|G6 0`p Aa1ns~M`~%VFX. s='lJ//,,{b B8zIA^C](?p?pef=xz_>pUP*-T$`?(KQ }lzFiRs N+|N_u(P38n.<L>P,ޖs*_.(fm< Fqԇ|cx!P]Dci[0{Ж @X]rU !Z@uWuC FS?x p0{h!BJr.R/ k= 0nkwD-" bG.@E}v IGXZQ Y؇8 0CyQ~h-[hgEiѵn9@UVk ZՊYU<Q 0¢;}!(cNXActA|ѥ.0!͔Elmx9 ʡo/]" Y!8^Zv)?3Dc"n5'^E a^e@QlcuZ<`ƶ"Ckƶs} B`hMQToofE Mjq=zOt>^!OU!O5/`%osx9ϖ?(>@m/6t< %/P~ /$c!PR}pES ̲XXG1.`א0O/`::n_Zd U-f,޾4J[ٶ/sC+9@s1a *CQr/H CjAQs;fb]~C= _`NI @l-9YDs10c8petwo~VS>CcK*zr/`/i@v{!(c S| ڶ{8L) _.P _>07" _>`u<TP/ȬzQrEK 1W [{ !ؓk|㳆ԮU1F^!3wȱIS/lPB[J+*f !<;.CԊ|g^Zӊ`ߡ{# Ertb˵Up!KϬeԘBjm8/(ε`2y>u64!`%+r&+Y>ASj$P AԘATmZUOm(>\)}PT U:PaػqiYջnb_q~l݅N/ 3]a=_a{C@8J10P %Xi<v[0i@ta|X@J' cnov1UmZp;49Ajljl>uUl$0|}pBmy@H#t^P d%@N+TjKh&h ~rUȋpz4E"x|+: LT&ptc#A^@F e/DxٺG PD PJQ9i9Je{a- irY. 2zaPEBu PA[s*VpD …;bIFQE*3%LH+ێ#Q 0ԭf2)BD?Ulo qtKW[Q|_% Zz"^BZ00| *6/z?҈m~3qd#@|NP)FmLV$ZSԬ# #YAnu1ѩ75vb\ `WFHc傱u-/ F/콿|Ԋ*,6mŧlᥒBn1J-vJcSN²P.\Zl5"DE>`DQ[6 (*sy@$:W/5`/dmVA|hiqŬm(/*M|l1z_`n`ֺcD 7hEƼkx7q !vTo P7|LDQ\@krK G9B@j@hskai iCH BM$i@>+J*j} 0BLײ /|z(!0` /|;J $ %\E0\OWX_.`"g,x?fk 79YGD_}G(r@EsEkPIE1q,ݠ(lE~jXn!8WAХ4\oPӶGEx­PMӷlfZ{@9BPЋGC,\WO/LsjuU ֺbZ/F<=Ͼ@}\ /@!_빽[E Or1_obZ<T d@w"4UPd%نp6_Z%"}&_LEYv |Wb>\XL/D+y Io1`!?[슱oލtR " Qr2yNQgC䴵GHKxyU'|`%+Dy6%45cR/qX5k+!0Z*ty%`9%`Szquyeeػ_Ϳ>$%"U8\QBώ9Ud5<:$7la5_Y>p;(O7m{QOa38M(c4\2*2?{? Vr /<+xBҠ:"ѱ{,eG 3*>;]j}X|T9ୢx@:$~J (P38n5.<4[&err>J &&Z*Q7#7lGTH4Ƌuكnli9|S> !]!=A?H4ҥltk_J]3J1&? 3DH^|@tM3؃jmlxHX\2Iůi9(O>@薿XZŌ;qKM F e<+Nrѵn9@U8VkmYװ PC)+T aOwۂ[!64z*G8YmG }o,gCmˡ\X}@Y񚋳(Ì&*~M *Bp̵إ<,E2;r3;pW "Ga4>hPbP4J; >\`ƦZw"{[ .1GkNgqdVTbd>*46Ucj<`^!OU!O54^9_ -x9]͠8>~R㈳70\ P8P_$4b@=dNۜ,@eQLS-Xh8C)צ}w T`w_76g3R~wh># !+ϲ(5}9UEkZ Xs /)UZm-E/`v/-6^A9@Ԙgu+d}X}@mzQ $'f9HaDqh@J_>@15a?H4B(T(nb!A;!v6@bc:;D _>+4h6"`y\k ;|< *ȱx/W(S!_>0tˢ 44K_> t<|`*:PZEiԜjwc3󘣺w{([a+)bB@6({8Bx10c8fеlqo~VS`jݑa-`< i{@H#^33w!Q8@.9 ڶ{8L)_> F7(l=QĶ@e!5b\fS9@kp`J(rtu@*@Q5͢/P@)vF#\ /P%d2j MXXcSlWo)"P AԘA)\+m( ɫc׵jN(¬&ٶK Of-{ * 5P+}ʲtePZTw.mX P%^u><`><-@Cـ:eWMDe.g{-¯xW8L,u}uN%`{Ll;LpP+jll4l17M=M?>5Iۛ]L4q@UgVMl~Nz>2 5gQI3Gq g/t@^!!?{ݽAJV, c؋y(O/pW @Jɭ90 mJO/Jz_eC)mZ1S=?dd-PNL46򉞬xuHp+T{_f XZyEwQo 8yA 1^0#9@llj_ԊDӫ]_S R*6|L6hbm11 `XGsi0Z#D)@603<~j& b9nJaCD)Ok" t:IHGpM/x1J uZ8iPX`~㭛(p0iqإF%=("NWe֯ /hJ_1~l+:W1ϝ'zV!oqbSaKeB_qLT+ mL40(@PeՀ#Qm-9s(q v(δk vȜ/e;(_.Ұ" ," M [+ 2gzwoPUAuE _ / BQ+3TZ flB0rq&\AAl990O!;B^t܀#'y/|怊4`ld64ӋPcO/Dxٺ!@{%@+EDpV+"^y#Q[i-|,K~uT gPcj͝fp-8n$@sZQ  =|,\ (>dU2z1CP´^Dq9xC݊m-"DS-j;(i5nՖ@WDB~uIȱȺWd,vG̩*QA)iP^0/#!{v;YC-n02vkfem3Z(vWjǑƬ ;@ 1w}0PWR3c0`[G‚iQ|J ^*w`=V ((ME$: Cn Vri ԊBqDm( υ\y,;pրŷI [ي[`_Q ږ~bDY4 B9 ԀP9FpLO`ԘWtm/9;nD38$`nB񍓳8 n W (B]Ԑ4o@Ŗ_~ !}f>u8aQ󰾁9 "h"L9\QV!T5lPت0\Q #{= e_|z(!0@ Y>N%EL@40|I+0|W9@Q]j݊o3ٵK,L#JiP\Z>f}oұyADQ~! wG7(J:[VxEΕ5H6|KC;hi+B=*n Ϫ"jMr͌Rcx `H8iUM/pxp +xs*~/y.b-bN; q!^t4|X֋Q(OϳoPA<7@/D+j{95s{yc  c<+Ey -A `q'REi(С8K:bslC8JKbM/?KE-L0('>}}-fZD" u>;rT!'\:$r7[_PY8|@QwVr]/|B#.! = e)>_P٫-U1oeDify<oFcx!P]\Q8#/f~5g2Vk\w\=}h4OxЊl.%C R꽗@4b~y| BA'-Qڻ|- ,>)] { `0:2S_ϺhgEig*ZՊZU Q0¢;]" cNXAo@|ѥt0!͔Elmx9z ʡo/]" Y!8^Zv)_3 {LN\] +@t=P>1 8[Efjl,2VhlZwo^Q|usWLCz_36fb}Thl=:@a30iy TDwti` *jݵ! )- "b-N(B~/rDg ŞA2 'mN2(a)*ZnPH-#X ipmwh g@r'Ͻ9CY2]ZwGL9aZ"Yv=YC]@۷JSU$zK/`pŲrwV0>[ҲMcۛV|(\] K-\ " @9@Ԙgu+dX= TK0cAH1Aq7V~ipĎb_6^(J~_x_.$c!PR}pES̲XXG1y`א0/`:| tܾtk!ĕV_]B\삨 }{[mk` 5\0E_M/.1Xz5<0}M/T$uvup}#AQs;fZx<uC= _uu~ Yd:dEi`cZJ]•k?{k𳚪u[rT׵}g{.mL@1)k ڶ{8L)ky@RSC傹Qf_7ΣjԦ*!OOTW3r|%Zmk`Fg{~6gWD42E^}eђ`^EuYCjrAk̟X$VQ(BJ+*fsοS"ZM >{h-Ŗk<EB&3@5ED s_(U%dxZ ["Xc'RHˢ@SlWo)"P AԘAԇlVi6^V{1Z awt[`aV~[Z Ql%EL'@e3Q=\BJٵ"0nEiήz5/=AY+VK\/p/@Js߲45@t mxӉ\Z_pJMXZ:뜔`CVDٓ%YA)OT(Β(R{70<5J$+>`c z{&D~&{ ~8~mo&8M+u&}6?'=YmMvy_Pc㙯Brid>so8{{ 6 :{GJ!+rZw$Uc/8\]I'T: ГO`&B/ۥ)+Y[1)mŪ(AJֽ{A`s ` +Օ"QN}˯P}EJ~_`iQkWſ">#5 1{1_.6rSB@:>rwcbd _@SxoQ @_p1'0B" i3cP`U$u8P 1mєiL 6 X8lml+HK(m/@9Lcc5 ߠ4q ֔#fΠ;AɊ4!S/9Nvώ̺\Y4P{0 iPLCFḊXc4^+ iIkOz;n:mf8jQI;M/pd@erYP BPpTDO*t, B`SaKSWԩpk7a:~%`GX ($=ٸՀ#Qmz_@{QO3Qi5@ 9_.P1 )"v\F6䩞4a` 0Eƕ :n+R踪YL*t˳7A*ܠ:"…8\h@(}e@KB!erͿ00CYd $s6`%Z>Kh&h ~rUȋpz4E"xy\PQ 2qRڔ 0JNj+q9̺"V@]l]M#pM/u[8Je{a-iY. Q6 ^T`9P@T֜<p!\p5f֥T&ܦL_vQWBisw2Ҙky`,x]B>jEL6So`~RI bZǦ"X*,, ǨWl/ww"8lAFQTBHt<{ _8}k^ۤBlE vߏf~!Qn/x%`/cDs#Jy@+B5] yΎk Rso=`*C7N@w b(q۪ o:*Wj(rKz_p#>X Fz, S( !& 4|%`B>Q~Z O/D;6`4߯!J>L!zrq(i~|GISA P_>_tҧ+ ,<<+DNHQ]e~v+(fn.s3(Q}}#@aFB\ (FT?û%HO "z_H]Jz_>c uHO5?Q_[CH4-lB#~Q- zpӀz_.ۺ(~_.<\?|g*ąx3 '֋Q(O 8*GR!<: WԂ%)`?v>.iV Or1_obZ<4w@w"4UPd%vct!%l>}2Ff,"]V~u$2 djo($T&΂@lD 9抡mBhG(w@,5(~6DN[{4O7(ǮƞLYc1d1Ϣۦ$RŒʠ>6/=IvH6@q|6VJ>A ]^ XA|{Nt ؔ^a_@YxY._pr(BP3)#R7"DEmw[:skuH;Žk!NY.:(Wm^ ~_`V|Q^%n~(w{!D X| >\=!TP=/[He)>OR(b"coS%肨Jm0 ?P2 0CVom|j9I-[36U8CwF>1<({.(6/rdxE?ݚ rrWu@Y\w\;h4"Dt;]R ~r+!BJr.R/ k= 0n`#4[DŎ\" Fװ J? t˶@1c;D+da0sD atF9kZYQu_>`t[PbZbmDp(PS.,=\~k Ws̩+h.8ށf20# !C/6^caubC9 "P 8CD0~"X].gfh^$ /~r:Q(k8@QlcuZ<`Ʀѝ>^Q|G>y]/.` @ M`H>^!OU!O5 *8LL=|]͠8>~rx/r] X:WN!?~rl2(>{;(9YTc5kE &VD\%&pP]0|؜!<,>ZwGL9aZ"r-.@<>@۷JSU$*_r Xs_>]哥 3G2uc7AlQ8zwY>`vzO][Hc\P5fl Y&V@" 3+?8PbG `FPU}kBK*BJ0hw{Y+28!v6@bc8_C"<\r@}i! wKHtOQAmM/1e)`H rZ򀑆vibNÊT! _>P(}^Fyo_󘣺JY EpsC0XozlOyZ眬" 9~wbn= •k޽YMպ-9PfYp~V pL\h6!0L.@RSC)܈(׍PAmYi+rGRjM3 |"jL<'@e3Q=\BJu, u+JDB+BPqEc2H -U! O "c2><`><-@CQJVHTQ8::@Yc}faV}uNz@+YA)O Z?P(Β(R{70<5j\@$+>.`c z&=L/`X@q.&8M+u&}6?'=YmMv_6Bg*xuJ`(+FE*yirޑ0VGhJzW~?&Ezq4W>Q+G/`Np|b1_> 6c5?w_Q1JT+ m'&~hbm11 `X4`FRDW(-kCI!~،MF0Es4I2W}rD0 A8DG})D "ۥ:{b biދE2ީ@WDYxIeGw062D\cB+Bp ^D" yRrߛ(_) X% ZQr9N/e q.\M/*C9XDN+T5"`%/@{,\ (>dUeb$mGVl3l!*6T7@wP8:jY¥-(>bSPȱȺWd,vG̩*L/ rN/wz~L4 F=;x蝬7;5y3R2۶hH+5HHcV[]Ltj F >WBi+R1UIrXB>jEL6So`~RI bZǦ" Xeu| 1JQ*=GԖ"( \hΕgo o 9Y|Uh1Z"nGM(fmK?DhBz:O21z_`n`ֺcD 7hEƼkx7q Co7QjN ص2P|t>N ׸Qc"(:/pM/(Z3_ԫʼn }f>u8aQ󰾁9-c6AࢉD3 (pE XP`ҠUay FvUciZsW%R=8w4? k(`I+0\+DN/ERV|Q9mL0^#J9|(ޤccBQ8CnPt" G?KM+k٠FZR_.@wr7(iۣ"Q<@l(F "r c(G zpӀ_>ᱷuQ qXi@腪PH&8=Ŝ}]BxuBF<1BǮ(ŦTH \ZdԂۀݡ DbsAӽ}V|(>>Y,.D" E:4gIct!% z s W60dgŬ }%UG Sw0|@! 2q,g ]1ͻY*A!j[恮#pETϻE ~w?"=@Zc"5={bDX cEMI|G6 0`p Aad>&0bEPBWV9ߞ]6wXP^lc@^(BẊNڎ>Qّ0 l?Y_>r@+n s棞 fceq?Ph\~eTeO^`FyۃBa+P}<Eji0nQP؃=Q2룆.5>P,WdllVsDW?p%Qfq~0ѱer@[&<-booq;|rQz3r]Aqy@E\Dc1^4^itk&`Mef} qGє.g^qI?r+!BJY1XPCa _>q[A1b ,&W" s"@kZ J;e[i w@qKM F e<j\m4sZlt)S薻> lp IiXYsϠw(5-%4%nPr|3rX]ipmwh B+Ɯ67"DW~wh># !+ϲ(5}9UEKXs /Zm-E/`vO}-WcHcd j3غ>M>E$(Xo@~Bau6A'# q+va>rP~L/x(B(1sQ;XVd,[z*@ԘCxQU2P><=.`J.!a.v@Tc/po __m[r_viĜ?Pb A_r@EXgWW 9xD5繾c&D59X cw{B!ؽ=ib>x#C-apep ƽ YMzZutG\(S~ԧp 530W EpѶmCaJ\1ʸl=QĶ@e\B,P䊹0w <;Q,*>_"Z,x;i0.]PlP.drM !Pc ]hH4:82޻8 *Hʼn_>JVX&>@J)CДndp~y(\DŽ j J 6׊D+C/+Cj=BĘ3kr3fmPe:<|u"j୬ DpAU$jV(yZf *oZT:Gmi|zsn H@)}P6`nYm7" ]` XZ:뜔`CMK$Ԃ]DRj1'@)dc'l17M=M?>5Iۛ]L4q@UgVMl~Nz>2 5ՕTL#Q} W6@H#:{GJ!+rZw$Uc/8<]I'T>)un'L4+)=| *Y} ixEXB5fQ E M hlX8k_\r^~w,VrK+U\_qK!v!7! c/p_0sPBQӘLE/{/p7_.@S.xo_ @8ҘNr!J򴁙1(h0*:(VIi3 6!ַYp`FnUK)!Pi-S|ޱTZ0/pT>V!_c46v`ܞNcus@t:-η8 J{n P8UE%/%7ȯ8ʂ__()DNo:(⊯Q?Y6N+CNDQ;PDa bSaKSWԩNjpk7a:jE8^,*qՀBM2 ؓ\ ((1zI<޶ݍ6|Fa?cc4Dq]o3Dt+*!EYĎ# 婦 4ac5oӮi[8`U½ 8]^̇Yj 7p9+Ļ@iGXN f~Jf%E.اMh% Qx c_My9`^V WG[W\7QRnKGi,b/_`0[Y. 2zaPEBu PA[s*V`O/0 O'E!L^0#Qܯl;b(G5Pbaˤt_Őڭ8"D8:jY¥-(>" 9Y}95U9 *ȱ; / ;bp&qd#9 }^>z'k FxMyތ̶m`&Z+nJ80Ҙ_xQc!ϕfxeܝ4df ƓV_^{ UX0m OɿK% +Qj;PHt/4` c+6T!*['ڲQEQA "ѹ-Xv~{!'o 5FKV6-ufhq4H!DŽ >6x^ QOM/l070k1 "Qc^ѵiЛ츆𷛎(5'mCPB(qrv'gC@k(1aGYrrTCӼ/r#!  4µ0L4jeIBn\4h`(bӚ_6(lU_.(Ww8%m4p-3D ԇ)BO.>N%q()B`*(WL/tҧ+ ,L/`"_P+b*5CZ (fn.s3Ee=%yOF*b53݀_ (F3vË7Mi8aW\Y˞H,CKi0FߠPmD[_'DC&nzj= %T9-4`*䇦8<._!.r;?4<=Ŝ}]Bhk]ޗxr*G(4| uK_P\*} P>+Ey -A `q'REi(pd.6w6$$ZЂB `&ɢ,@_egY7ϑ@Wzg]X *]!?#PHz!L *`W}n>xP?s-W(_pETϻE ~w?"=@ZԍcW@`1 > @Φyk3!AETpt UCt9 jϯ ̯VEPBOXA|>!`Szq_.@Y˒ w/ b B8zIA|M >3 4wP|r#ʫ\Yn^ z+\t'>p! w=8Rf}3@gqۥQ{Eަ*肨S_O6(F!qLm|X|-\-U1;q;\P̘3^ CwF>)F8BPq~p.G1^/|{~5g嶌f:] BB^H4ҥlt;]R@`F 92C:/ _,sx /0{P /`n;%H@YMDEװ J? t˶@1c;D+da0&!?<(h-vLE@iѵn9@U;C}ƃ1YU<Q0¢;}!(cNXActA|ѥ,6#P>7Sf!Duhk,.P|Vl(z^~V{/]" "X].gfh^$ /~v}"G0Fi,} c(pN46`Yd֌"J+n5!0{׹tu36fb}ThlLi3J@z[ҲMcۛV|(=|ǻ,0C.`-W1wY.(3 ~`nQ~? Bȏ,06AL;}x0P(ycׄ R}̇+^`eA;a%0.`א0O/`::n_ZdnJk~} *ȱx_>Ž_S)`H nY򀑆vibNÊT! _>PȮ0s"4js}sL'q1Gu+?z}BS <"SR16w'/Ȭz?eyf`^EuYCj*֘ ڐ@@MڈmE>\B,P䊹0{ WJo}Q,x*.l:|@kpZQ-LI(r"@*@Q;h(@)oB#"{QA㙯"`%+r&+Y>ASE p1c+)\+m|{,<$V#D9_תf ;D_ C?{!TUTHD[pAU$jV(yZf *C`dk%4Dx|ݗW0&q"@j8_X=Z/q:|C}Rj0 NW U:PaػqiYջnb_뜔`C Kh0+H05\v_>`va| E(@)dcŧe#C0i@ta|X@J' cnov1UmZp;49Ajljl>u@-Tǫ+PU3Gq g/t@^!W|"`%/(ZGߣo 8yA J~ p{SB@:>xBj[]&(w6æo_ @_.p1'0BlQG0\3cP`U$u8P 1mєiL 6 X8e)c|Ԋ*(iLy;b!`/~B/80_f-z۔fΠ;AɊ4!S/9Nvώ̺\Y4P\4@9BLY1FḊXc4^+ iIkOzX0orAcԫG% zQ8 2 @T!r gl4`h@ߕ L8u:^@Hak@+B`n}>z90E{q"@&/|8#R/,Zq Cr+3{t >֪3>pDK_J8yo_q[b_.4Q?Y6N+CNDQ=8gҀ%@ԩ+Epk7a:jE/*qՀBM2 ؓ\ ((1iˢ0 P޹aӟ\LXL"s|@4(q'F[W\rߛ(_) X% ZQݲ׳iyR~uT mzAP0"rZ: 9+yx"fBU@$"֋b$mG;>+Q BQ.]m D~E G_$k鉬{Ebw i>XQANo:/܀~yd#@|NP)FmLV$q$a1+ȭ.&:Cs+!4ȹ;iLU5\0腽ZQӦ -T@h*%DBVaaY`(>F"`C~1 XT5|V8lAFQTBHt<{ _8}k^ۤBlE vӺ3YAQ8 (ax%`/cD>5;uLjn4ЊFyEצBon:ԜkAe|A %qD!eQu>_c(.cSA /8BR|Bcp,\ La])QEfP [m33?[ت0<QrNI0 -tsW%R=8w4?+ \ Q+R Zx}"U  .[&_`̕E/~3f,"]V~u$ʲ+QAF a6B@ Ae,X4)ڀ9@mʄ8""?<?"=݁ԍ=Fj{2g?9Yt۔Wpd" sאJvH<| ƭbxί ̯h啀dηDM%`b9 6 cTg-6qt^QBƻ-9Ud5<:$3{A,t 6e?`,8|| 5@ (_%?p8p3@Qa/uMx'0CQ'8~/NF>%VZ@k1Ѷ޼ ]8T ]XT># k(<{c" J^1^J RmN`(C@)3"`:rhuV(>+6C= A1^wqx3㛀 P`\;evRN^)]/ (~N:-әmZi}{[xE}!4t{GkEX*6Sb6=^!OU!Ou\ *o=0y]͠8>~Rߋ\`~_p%@C} ҈=) zwQ8os!D sM/h9jDMyM&46KL45y؜!Hx@6pȯ2 JܾU"QqZZ,9>/p೵(-4![ jg_|eyHl/1W1wY(3 n_Jަ B87YثGj}(| @q<5a?H4B(T(nb!A;!v6@b:_C" rAEC+f&ug?sm=/l_sC /LWۥ5 {Xq25k `/Ԋ4b 530W Ep /D۶q)er /Q~?b.yjmn(6UygH3r|%Zmk`Fk~6gWD id֋rHhI0"{rߺ T&oT\ ՆZrhFl+(J{#[u` WQ}C6V1f/}o )y"t@*@Qu͢'P@)vF#"JUD \ 4,XcQ>ASE p1c+)\+m|{,<$V#D9_תef ;Dzۚbg.)B`*8?*CRH4@P(ҡBQZ(\}yE*/ܥmյqq_^yCRj0.S DݲB+&t2W+}faVu}uNT+5ea&7j @$+>݇`-8IѵIc^+4(DTuiEФ' ._({=>;I`(+2FE*yirޑ0VGhw%}PR&&@On)h%WlS *Y} i " @TϭJ֢^3hll=YUՕ "QN}˯P}EJ_&`iQ wn"J{qv!7! ~_؎rA(}!D(QɮS/PHm10n2Zߋ)(\Qc f ?/8ҘNr!Hl0\3cP`U$;4Zs6My?`S=R0TTR`4< QL[y`  L,~`MyNP[$0v NVa1zqՀCD?CPi>`@8:qe =:jq>Mj 7p9>/pz_.EPh)>C(cQ QB e*T!hGh9/z;څ jA7b biދErߩy+,< Ae2:7`:$E1<|L!"rEgjkMůQZ( {Dn PLÜo̲wY@epܦ! ,"GMPAU+rZQ _0 _ W"J֋(W1Gϣ`[ͰeR~Pu_ qtKW[Q|Z#'EӅr'Q+`=sj QANo:/܀~ahy }^>z'k j02vkfem3Z(vWjǑƬ :P;@ 1wg-0PWR3c0`[G‚iQ|J ^*i \a@R݁TDxn0o^hcДmOe2<Ds[[BN&-@-C5&'ny<0;0-Zhx%`/cDs#Jy@+B5f5z#JIqנ2P|t>N JNFnr n+!r@]/8BRz{_aZ&`5X S( !& 4|%`B>Q~63󳅭 /DȮ [ݩ0 \r9gBS\|;JQRTP5 v%PtR0-< +D,xV|Q̮-\dQg} Q}l&`53݀_* ^ ‘19nPt" G?5~7+9FZR_@wr7(iۣ"Q<@*!t<@-o(9H/_w ơHbU]/pxp +xs*~/y.b-bN; q!^t2k]WPgxJeLQ\=X/(rjz0 P> \ Q+Rg&Nx}"U  .6w6$$r@/~3f,"]V~u$Ldj[aPGޕV2q,g ]1ͻCAԶPVyNQgC䴵GHKxq n{bDX ׿"" sאJvH|<Vj<WBlaUJ 2sK2˒ w\PT +:tr(tA듑Q:L9suHo G /(CtY8fbOݔ}@5~LCoP>V,m> + >}|B{₊DY ^K]M U9Q= _P 0CV2X|- >-U1oeDifTy Cߌ A{yAE\Dc1^t_9+֜M{|[]rrb)!% 3J1߇&"{/h(t=3 ؃y6H8@YMDErP;Ⳣ4\`t[PbD9 PCnLt"}I1ĞxENXAo@|ѥt0!͔Elmx9z ʡo/]" Y!8^ZvE2;r7'^Ea@YB(is hji3Pcۀe![3(S(CP1V=9{C]u` @ MX)1 FiDWSUS=/a>j\m4sZlt)S薺G/r= xySȏ_'\b@=) 3 X^zERj |&VD\%&P=\7"DW~wh># !+L󳆺o Ht`pŲrwޖ೵(-4![ jg.fwlxE{r1s`V3z@?HQ $'`?# 87YҸv8P&`?}\@ʏ/VUc`>\є0,Vd, j!a* /P=_.P% էKH]X/pokў9dd̶97r}5|@sĜއ 1GM/ A_b]]a(\EiԜ>T{@1Gu+?{z]0PjW(7SR16w';_Xcb| +ۊ|" RYXsCu` WQ}C^xrba`J_._>p/]]PlP.dr=!Pc ]hH4:8RQB&{Єe ``ldDka9{#J\C\ Y'd9 WI:^bY`sՋj9nSV:1XLt/P> W! ͇^:LPQAu<w+g8 *`R_8FCacy j4`>[7D|[}٨SU$SA{J"p[j"(hJ|_1~l+:W1ϝrw*ŦJ– QS1.nøuՊaE=S2 K@P4ԯ; nr5t+Ĉ'AT}۶P޹a8;FLTE}!2*P1 ); ^TBVwWDطiW-*P.O/ì 5PTXQU8F߀3PgMEPh)>C(cQ)=J.اMh% Qx죾fpl"T!/:nҼISsAWDYxIeGw;N:@F "V@]l]M#pM/u[8Je{r@1 F"`Cњd!*) ۞#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`|bVжCk&ʂ >6x^ QOM/l070k1 "Qc^ѵiЛ츆𷛎(5'q\B񍓳8?Jܶ*:Ⳏ ru7rKz_p#>X Fz, S( !& 4|%`B>Q~Z O/D;6`4߯!J>L!zrq(i~|GISA P_>_tRb+DNO/JM?{V3ٵK,L{QsF{q듑 (qL7W}h3.7(Տ3`X{ZVxEΕ4跑|Q(pk ~6^hh9}fFEͱGzpr^0$yr4`*䇞 8<._!.Txs*Tlx&{؋95*ąx3ņ,-Sc+t 2\PlJt_D+jۀݡ Db Or1(_)ch@BVt >*HCQm=Β@1:ېƒXK^-͌y rLEYn#7% zϺ83;ATѻB~G CP8 U~_.0؞Du%?&0tmwZ  -S Ʊ+ '|`%+Dy6%f}x(ؼ8$EP!rA!4|t+ds4x%`9%`Szque1.K6c@=P3)#R7"DEmw[:skuH;뮁P8e0\A+۔@3L,>p x u'0JQBz;J|Wz@Bz_x(>Ph=8Rf} 3T|]]P,Wdm|½.:}$^IP(P38n.<L>P,ޖs*_.(fLf1>tgC"/ 6#TH4ƋE^OlܖьrU !Z@uWuWk^?xK(!@fR㽜 x@/f`mDi48ɕ PDi~nVZ(flh,CRÄ3=+N^PbZbmD`R}T!0_`AϞAA5PAɫ-+h.8ށf20# !C/6F r/gr(܅!"PkE?Pe.`j[{h^$!> > +@t P>1?BlN4DE@ݙmEȩWS+TZ`v:ۺk3>*46Ucm4l} jBBj9@Tz[閟ix)Df@E#A!>-5p6} T+E 0O/p IiĞ{;(E!a9Q´^-g60z ڴ.1Àv >solL`#&@0m_Qe(5(qĞVQ !?NKX,9ߞ yҠk೵(-4![ jg8x;{Z\xE60PQ3 n d B}Xgy# h@(<\@1|k~i@QH>QMc/0bEbf8_C"BXڡI_P}i+Dd۲|`mP) _.-@{X\0}*:P Ҩ931Gu+?z}`ݞP::cU?uɊ wLj!X3fеj]}ćƖU([= ~{Vl6@kfq/\s dDzEy]-]QDB16" _>`u<TPeYB:2C(Juv} \}yE*uEհq1^z^G%YHpm>btD<ܮc>$ $!U%SU =#ڛ, T=0SGж 0lEx iY;nb_v~PÓ`g ?$*3*2^ԶAC(R`\v1L^6@t|XOlfsAF?56iEФsГ֎ks=|P MqT#Qb]?8f^QOz!Q}Sv/ފ_Be9 X5b)#qR41zrkNLC(EGِGhJۡ(Rp>@"J)@8zܩ3 mw)'[|]fGX۽eI-7HT]x;րS؂X C}t>H4+ T 0 m+_ܘ~{L5-`hr#94_# Ƙk` |Dj w@1 Ƨ6Ng%JQ%F! 4\冏6qgG vȒ@M@U 7,gy@ "@NP`DBsTa}@YQ- I'paJfͱ&\tmx$H> |`^ W<39Rr,{8^=5x( χ Z.#eGw;NpE1<<<)"ro#еjloPcm!-T2uъWT얽 PÜo ̺ JZ:{*T03: h9yD"#fBU@뗸>3w%Lt$bDq?f-"ESAo}St<-VXbhݬ0Dѽ`aBZ7[\i<Ź'>v2{@ 7`a/4lDI1+G[Z`) Yx_603xR=$R݁#ЀMXXV7ʷS倯#jF#\hΕg`ݷ셜,>#-|k+Zl[ R>ނ `>b6#8/*M||1NM/Qt'l)M6Ÿ5Ԝkq *S7v@wb(qe>."LᨋBoM!{(2vcjG 9R@j@8+0Ys%K AT?DpEﳹlBֈҠ`0<Fv!,#4߷JB V|-/'"/(L'@UK)4`9w_k|+x~c} Dl?|(6c@xD1rwty8W\|FZR_.@wЈr7(i"S\@|m(F "r|5˹ Ӏ_>ͺ~P6 8#pSICobI; q!t<ypO8!<1BǮ(3R!f 2SGZrl z @aؽ(k]tqzSԊqqt ޑ*CфM^.6-F2mm,Bh@ >̷l`fɢ,@_ukE7@oJ,{R H djo($mb C8 UȽȡ~ j[G^(j}̷NB+A!r#KAA8~P7d1ld1ۧ$ނ-}Ur8tU`!Uٿ&0b[A ]^ @|{vm)ha} d.Òno []!]]Ԥϧ@Ѧ{D JmiwF"E#azXRL0i˱<8>wo 42Ea(> o;qnyܕ4@C=p#/̃|p<6r/|B#.)^ ^~NiF U>Ѧt=9 _P|9 `ǭ\L.T LIZ/ł]#7#1<(ۂ.AG1^/كnrsOuz@E BBBy >Ko{H/xcM> 3EH-^/znՋmlǽqȃؑKAGPzDmp.e{i X]v@7q٢ `0:2%|w~@+^+N#F>rh- 힃>5^T+Ow+RPЏ/cI@o@ѥt70ؘ)o0#mx׊ʡo?u_-z/o-TE2;];M +@t=Pp9~CTԝVhlGw"xE ~oD  v:յm=*vSb6q.Vz_> *- tO\mU"Sq%Xs#?R wuo+Ei -`}E\^ PjZ/Pb_f *2:P> 93{sg.6>۳Zg[` KPlOyZg"3FL1M&`c6tm]_sk𵚪u>hB_u > ^33@Q9@CaJ\3#55_._.0U3hvUyk `Cė35\ |Z!6齀E?cի| "ebY\J\70j@=Jv*u b.Bf|cEvb[QW\{(*2[h1.4pd_P@U.{ 35]Ɣ^cbThC3Gy r)Hl0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0E=/soP/P ʞ ؄E|-* 8[DM}oĸNqDz` (%=y |$FT/= m/m#짱 vi=})*P1)"v\!T/BV䁅wW<5OӮ(i{8`U¹ 8Y-G5PTXQL@YQ mZ!-- I'paJfied z`:6p<_>C #64`R_&tQɑPciދE-: L\&ptv&<̹rPD12UI׈XFF/lB9jE\6So`pSIV Gj;Pt:/4` !3xT5rW8lA>h υ\y _}k^3WA/-#f$k& >>x^ Qm&` Vw(AHaWtm:/px$ހ]؎kPBsv/'C@k(qa G]rF @/8RȑR|>X GV!v$!. <|%`B>^ /#]8`84߷JB V|-/'"<|G<<w(rF uݥ_k|d#{9>&/^׹{HTߋ\2b5.3݀߯c@xD1rݠ(lE~jxn)8Wn0黑^|ڴQ)pk 6s^ih9}f>Rc(G zq ԶӀz_.f]TB\Q LZ,U!.ă_`+Ң<1z -p/P:/dz@QRs=w0 6(`.o)h@7BVt ޑ*CфM^?;>-F m,B6@/3|f,z"]WXts$-"]!?-PHT&΂@|mD+ƾy6=K%\x5ʬk@HQz^\t'>p)w>u)=*^ ]9]PWU>pW@D[/$n(#Q38n<L&(V_d\J fz'8nG {FG;#)(8?PQ9_m1^/z74~5g \e }>rrb[)]FSx?Ph)BJr._:xAHp{P/`V_Fy<8˕ zPDm=Bl/- ȴB&Sp~3|]<ֽx:/0؄o5.@]ϫxJw`*ؕEw+RP/((y{5ǒz*x۰{@¬v#P>V~ .\~v:rh5V(^+~(zAb |(ύf*~ *RpRr@N7|;/h8]hPzbbuZ!*ZPc N϶uWT8F@њaS=,XQBk7%q7xNiV_3osxVw-G ~c MZ?@Sz[.<\J) 'A6)lm#;YT|9jDrX=ypmgi @uÈN۰9S`#&9aZ"ߢr߿ld#J_._>5%GmE!zGXW|ʷ{Yw/? a Y|v rV3EѭwWZ}t >wD93hۚ_FZN!CJ\WB<4ͥ/%5 L1G!C|"S "\13}w~`nsTVӆg{B!۲=ib9`s<‹)yL;kEa<)j xW_^8q?P+򈁼 */o=Ʌ/q0D|{7h[ߥ]UBnI*Y9_ΰ|@BJm0mV K@1,zQ Xfq\-(R'Ne.b.Bf|cEvb[QWG,x*.l:|@krZQξYo8{{ qBt#T݋>4Y P #`{1Jz\r9MLܚS3J_`唍,>ʆ#{oyfKPc[.Li _7<r F5<\cN8 Ɨ;HEb1vQECPL1m)0G;l 1r[ *P^J rǹ)3#ߠG y/Qȥh ~ NVa1zɱՀ[+hHk͕zOE#ŔX"r-F "l@ǜ y/D9~0){^_Ц1Ad2 "rANg5GL8m:n@H~[㿁g׈rV|S(Uz03hmX6I檠w b+6/mp|aD`KulҼIeS󁊷|(' `:$E1b6A_dc#bI15`/cD_0070[1 "b^ѵsv\Q㑚xvmc;Ae m 9P'|\DQ\@oF jyBg>9ʵ0Lr>r<kfoe;_P,P|r\Y5^ ga\/P}BՋr;EL  }..(V+ *} M-|p@(Bzx&g2r.P%3Z#ł=#Нxlz[ܞ-b1^nitk&,X} ++xS?xh[_#!.@fR㾜 C)q^5܀?T#a xw1>ypk+@>i5`0:yO|zw|{VVTf]XJl·ZkZ @|=\5^T+OW_>5Wԋ 4VI[]Jo6fc2">'Sfc"uhk,.PVP|(P4TnTxk إ,*W{;݈RN^)/h8] (~N:-wmM3K64;ByC]#Kz X1ۣBcS>nJf9S+*FDwry`_Tk9R3(ħv7dZ-8x7r] xSAN#lR :G8ow)D 3\r|3?pz ڴ.1Ávq/b`V(p@_H`m $p[ &_sC yjVX>(<\@1|kBK*BJo3.V,m-0#}&^gBuifqGs@4c>|r _.R傡[<`i.-@,ŊT! _>P) y^Gyv763bֻ<.u_kk=m([(7SR16?v['߶{8L) _.y.:a(׍B@tR0![B߶VH #5|z?Ma̵/Ȣz_uyn`Ղi"{r xT&vb-hvЪcE xB,Pl䊹0{ [Fw}XLU\tba`J_>@3]}+@Q5ܢP@)vG#\}.> lG6B/`_ߒm q9r, o07븐DjZֵ" !ˊpZ}1}]ہ$^腆wtv9f5A׶_RTpT03n)TiZ=P%PZT:[VǸz3R*O#SV"ZTfږNTrVe΄wV ޳0kwž:;e'/HTgTdJm c9L%OrE9R(]`\vٲ)cn4 pi}̵`"s 8\v`c g<w# -6:֕*G8g l3B/V4| P Uc/摢8<|VI+T.: Г[s `fBfJ/D#r!ДCQb}E SD#kQ87pzSf ` -֕"SN˷Pn"`#/G -7HT]x;րS؂gb4|ffI .ޣoh>4Bj[ŏmz>/ 35py_ܘ~{L5-`hr#94_# Ƙk` |Dj w@1 Ƨ<ãæ@{#+-(yLy;b?C?|` _Y2;nxKFv`kyL Sz5֊=;RZse@{uH1ea,(byat:7P1'=b#ýA^#QM3v3Sz5ਤqȴ 4PftG "B:;p/N$Zpo8yX\l hԈr+ pZuf{)60'~Y^:LP@\m=yUH/3P06=wA =,Ǹ8V$p6yrLӀ=h.5Mb_.0Ԉr6]P1+f^鼢yEs}݉8*{'`|-* 8[DMn'>v}CfE=S276P|w& @`W>#ȿ`_.@rGOc83R#T{;SdIU bRE1<Ո򀐇y`@ Ӵ+J5"`K p<[Hj 'r9/ 4*!}>l>WP/9}`$9"( }ԇFmh< rMȃ biދE2@[DYx>`Gw0|tn "#_Z7t5A-c!@ۈu{8ju{a-g yrY.g 2W8) ?=( @[s*6pDG ʅ;bѥT&Z/f J֋1C 3ÖI"^Cj!Ocf=[Sc-=Qt(XXG,*/rXGgua/܀0l/A߳CW׌r(S6е87403xR=$R݁#ЀMXXV7ʷ{mFn<D9/'W6Bԅi-v~a{!' ̱O_ڊ'b_>0;01%y B/% ԀPvjv~`Z V0Z+6\3款A|v\Bx9|8QAi u4"t9p܈A/8RȑR|>X Gz, XR( !. <|%`B>FSx0 e_0 P' ro+)R`*(ʈr"_.tRmPE /ș_> .5<׺J`>2ݑ/ x~c} DG*+XGŒ\ܽo#?67G#/g V视^se/H]J#_S}@Pj[ :WdZNԢ#~97^\p96urC#8r(_I@ey"]!?-PH^2qtzv7FG3%rET@|-5(6DN{{4w7(ǯƞLZ|pd#<8> l3eqb89,+>+++xS5/SD CT#!]49!}9ćR/ ?T7". "bG.@Um#@zu-]m I[XZQ Y؛8Ll0SԊ~~/Њ׊Ӌѵ&Vkh- 힃 ]J";#`*ؕEwO+RP~D*(y{5ǒz*ixK۰OccV>'Sfc"uh.PVP|(x9Biuݢ'HrbKYTevRN^)/?PJ?Ps=U"]5 X5x$J64)0{>mk[Oy,G-LZ_<Սrl-0<&`/Tk9R3(ħv7dZ-mq^P J) 'A6)lm#;YT|QuBJm!))צ}v T;/p܆͙דz;b|ޞ# )-zO.}%,Ŝo_9 &kkQZn1um=Ƈ?{Y0C}W /Wȃ1{Y(3m[BѯPBx BLPA`k?P&`?շo(?n& ɘGm`9\)̺XQX#@CmH_z}_."Dj ĕV]B@m[/5<0m/̹FMsi/%ҫFFe!ky"S 5;^GyO~w>Pyxvӆg{B\l!V}ޖ OAwƈ)Ere|.?𵚪u>hB__^jE1yCl+ Ep/ķmS_Ԉ4DԈ׍_&@ @Ӿg4_+-Ur%a )|O,%2A1,zQWo%`]>70j@=8^kH_b0#V+lp#Jg(6rPݨU1{lHk7V8/xh-V;lLI/9/ߡ_ \-ze Bjo 4:8W&#Dm J [R؍eA)|}68{BB-f]kQ[׊La *gE]I^GsܾU7,,Df5A? ?*SRߡj@Ym_f Emή{5B+RPqU#l{hW//R{pTf^iMut"ž`Jߝ>Pv~Pדj/偊Lt@sS6((Mi;E .V[D 2E4SDkqzSefWAueȔpo-T.7CkM<.EF}kA b)l//Ќ<`t@HQ^ο|KE R_h= LoLU=&Fk04ǜp/wc50 >L5uC;bS`1vhcb#ŷr@9jER`<<LQsO235u)=]3h_lu"sqK]Z@gG ]k,{h.),lr !6LqEsړ*62u bSW1cT@# i 'N_.2A#ES#X&hy87̷̾l}>) `Z! k e@&ׂx/8*@ |zQm6S7,V rfkՙRj[3P!@,؃F0{жV)pT>V!^0/8FC5piq>Ixm4%@Tb{Ѝ.0?n)Սr+b*FnXxENg` ʞ ؄E@A Up6uEN8}?SX0S.Ꙓy($PC}7\\ (GbDғ ن0Ѝ2ߖ>~i.?W՞->"ET*EW eT(o) }0%-Gm.b/722@1\oe.!.ƂVN}AX1`fp-؏N$@mͩ7 _0+_NU@|bdGVLOվM4`VpjK ϭZ)B~qIȱ(wZ!-XRSUx_rXG_ ~y/LL^[6_A߳CWd (S6޷m`fZ+2)[jǑl ;@L1>GBysv2򘪤`,x]K PZфצ -T@r@|%LB6aaY`(Fn<D9DQ[6 Q4Bt</5`/di ^[bDhey`zw`>b6#8/*M||1NM/QɃZh1t^h9;(YHIנ2P}ct^N!8Q"(:/p/G_eG 9R@j@8+0YJ1Ďd DpEﳹlB֍򁂩#HadW=@oJB qU|zGB(f Г|[I󵼜J Jr"xI-29ś<\K=Ln7ٵK{,ڣm&׹{HT|(6c@xD1rݠ(KD^Lߞ7}7"@ҍ2n AMߊLq[_'LCS6Z{@9RPЋ[M\Ѝ6y3;rۆXRB\@o_lҢ<1BǮ(/O/rE-6] 0c nr1n_obZ<Tz#d@whwJK ؄M^?;> `QX9@Zp_`e3SNg+_[,zyF (_IPpa  djo($mb *gB "7۳TCԶ\L#pET@|-5(6DN{{4w7>RE j{2ky_Q6B{So)aFePoGԞhh޿&0b7EPlBW69ߞ]~J/ZX_ PlŋrAz +:OT}֑{HQu;rT!'׋2_t7o O@n:ݷn0+ } 1>\xd4eV\r3~@HQ6r/<+Њ<@547y.et>CK FJܸѦ\t>.)qq0P䀧|@@M (2fhcx!P]xch ˮtk&>NP`j퀐뮐mO׼L.CT#!<.!}9_: kT30nkwD. "br%Ƞ'-TÞ|-KKł;2_j^`0:?\G<] ⵢ/@0-&rӣBJm!))צ}v T`w_ 3'lw=G Lk8R[T*%ؓ**"bηr35gB׸e2u7AxmQ8z9,ݡza->+}D6[PBx Bc-NNXpnh1>?xxl4J_>@15a_H j@|(w Kt X#m!K;r_>0T1nYrbI*/倊Lήn0TxD5>cf:<`nsTӆg{B\l!V}ޖ OAwƈ)l8\Yt=jk>bZutG~} ojfP+򈁼@T1)_o_\nn@|da CD1sߣF4P<{FR0![bo[F?`>RӧmV%LG ydыrH 7`Ղi"{r x!k9-otoX%@#Je!b#W }ySXPElywxbqM/ʍ>) _A/^yʅL}2ZL!`pd_P ]ȸhyW-ihJˢ@hSwGa#8{BB-fz͵"Ss˛@QnW"kՌr KGYmMPk1EETUTH6LafJݲ R"PB{KH/3Xg՚}݇W,n_z_>`{[.@zE8R{pTfV6o0Ɲ`m5Pݷ*H+>>,|C/Td*;LpPUGB(<7tw[,~nPLQs{TѵKz `#0(9u`,6iEPhГ.3x9bA-4+*G8g{ź=p͢ $?E[KV,^#Eq4x9VI+T>)uN'4R9L)Y} y"[hL"J)Z^=T6Xx˸uȔpo-T.3OLCkM<"~F}kA(i7X#(H4[b)Fh=ebLi D )ˈb f #y r)Hl0\`P#TSwh0)m0>fSئiؠV(r[ *P^J r X/yA/paV̎[lPhdna50Sh_lÑ9ĸ%ǮW~lhݳ#5W= G_ PSn0CD,bt^+2 yIkOzs;(3"w)~bpTd_.@ 4 ie)ie`2s hE ۭ#r'_> Qgk 䎷:^b]szUf`Xk `kՙRj[3й,@#pUEՈFm hS4̃}BJ!0 Kh(v`ܞNcus@t:-η8 F6"S4`_p_WpnjhJ54p[LŨ kt^ TpTDO&t, RҀ%@+F8@0NaLr0gJ桐C5nig%JQ$Fwfm#Z}j#Si5@#RdIU b#,S/yX \>M@U 7,gy@ "@NP`DBsD8!KP 3B8xAhmX6I檠w#h# c3]his{r#ԥXorku{jx 2qr+e:mc9/'/X7t5/@ۈsXrV+"^y#S["yz 1̺ JZ:{*T03: h9yFDg wVůw'*RPh)(aZ/F{% #Q 0ԭ03l)* };(il5nՖ@[Sc-=Qt(XXG[/`IMU_rXGA۽@Q]"ӰƖx$+lKP>e! }f"SX[jǑl ;@L1>GBy#|d.Xo MD)70_[ #(82 ؄eu|8 >.LQQ*P1lA>h υ\y _}k^3WAr8|lGp^U N/x%`/ԸZ s#J "b^ѵsv\Q㑚xvmc;Ae C %qE)uQ 8z;E܌,N|5|@g>9ʵ0L>0#wHǏ ňK θDW\Y3K?Х4|A3K8oPhS"S\@|m(F "r|5˹ Ӏ_f]TB\ v~i=a/Az(Ocбk+ P /L+j6 `X)q$`?cܾ0n@y->f):ݡ](-ex6`:4{IWR5_.`̕E/3|f,z"]WXts$ʂ/8RD+䇹 IP&΂@|mDg 9gmBhG਋Z)jP|miioPP7_ԍ=ർ/x(Y!r̽)0#{92͋#jORsSr@z_o ⋠؄.l s=6^" K6_[]!]{ g74KU46EGޑ aӖ/_x}-[]L\P| ^r 7yo@C} GF#̃CK FJܸѦ\t>f qjxYd/F8yZT L$Wd*Ec7_>7#7p 9ʶ9p#/f~5gMe } 1-{_/[_#!<.!˷R/{!G kT30n/`#<]DJAOZ~MDm=[ewdZ! {)8tLat~'x~hkE _0؄cAk1m^#PzS,?HAAyK[]jHaV1S+S@)31:rh5VPVP|(x9Bi{`m8^ZRN(t3N^)/@tJBIk@C+âشBcSNö+n)0{>ö}TYv@zB3\d#BJc3f](X, Z!afmHX"Kq.Bl c{ ĕV]B]h _m _b-9` /LWZ /L1G1/9"S "\13w09X q뀟|@9}!V}3uɊ ;cZJ ۃ"tmE?j]Ň-9Pozq5 ?"{<ށD"CaJ\q:B1 /}}B&(\ 0V!O|_f9xK|9Qrmk`>RӧmV%LG ydыrHhI0j@=O]p֐5P@d^ȱK@;(+P- bn-CU1{!Hk18V̦rba/P Kqk<EB&t@-b82/(}*] 4j -6B-6@iYhm q9r, o07]+bĺ/ jE0l.Vlg78z;:]{CzۚbkH@k2)u.HLC %o.!ھb]!>"gq"qcbuZ+/ڛ, T=0SG*Z[G(0[l4Dkqb_Rx"?$*r@EK: 0T$WC(l4/1Lti> tiX@F+ cEn7 :fZp5 (d6ˌb}bA-4+*G8g lrGt~7BVBe9H^#Eq4x9VI+T>)uN'4R9L)Y} y"@Tϭ0dv SD#kZ^˩Vd ` -֕ "SNn/#mYlV^;VqAQq)aݷ /b/Ќ/%u(} DG]Ѧ(Gh=ebL&p%arQ @F8N0R``fGT`h}Sq`|<by@|6k ԶRC`1q`{ gߠg80_f-xS42M?^'+0wj {v`ѵB؃y`ObsOA0D4r-F "l@ǜ7wh/r_fjQI?18 2 ~@4Ќr*gD/X2/LM1K,/Ðr#tvp qQ+d^Hg/ o)N'muĺfS3\ X0uc V)^8D=b{PU4Ph` 6N<*| 4pa j4`9]7DLփj3ATNU)vy/8ӯ+6~@<2txo1j7yE>PpTDO&t, RҀ%@+F8@0NaLr0gJ桐C?8Հ|$FT/= m/@rGOB޿GjGȒ@0"lC,>s\8A,{8^8`|(' `:$E1P[_>`%E˺*S[]/*SXDI+T> 5"`#(r!*$QE *3%L+ۏ#jG(.03l)* ֈrBQ]m DA)R.c-=Qt(XXG,* @(⿜iul0l/!+G[Z`)ϝ#603xR=$3q8VaQs,Kw~ࢋD3(gsE ؄P#f? Lf ;6`H!*s[HL!zrro+i|[ISA Pf8`][`Cfuݥf ڭ01priE{ :w8/ *+XGŒ\ܽo#?v ň=pEI'S~L)8W֌}7"@Ҍt/ AMߊLq[5<ӧl#9H/_T^?-l4`*f8p xO?`<<+ 0 ,J|Wz@Bhz_x(>P'(G]l>~zNi{FX9} M-|p@]0SVdbL&Zbw?@wEo7f3\;#rmAs~ s#/ztk&U.P`j!]!]!ۼry":Xoy~h)BJmo_wt 7ՈrmlǻȃX\2Iկ9|Aٓ? t@`L+dao0.)?rV+U@a:`.?72|]ˑA!>E!SD?ՊnyL3B~ |@ 6NF(aZMPG )t.VDѰ4cn+VN۰9Sxx2}_imG|*@<>@%.bη3h_Իe2u7AxmQ8z{Y>`vS$~zxEyrA9@i3غ>\.Y女 X6@~X87[x~86ȿ {#J_._>51.PWHQm^`ŊfoC"<\r@}h)htk)ĕV]B]@ڶf\0T!C,yC\ZrXRi, _.! _>P) y^GyO?09X wӆg{B\l!V}R@'+6Sh) /0+W8@+9TL1WkH-wZG lb.92Ep!zŗ.[ D!B1 /0U]UBnBv `Cė3/mRGj~E?cի| "bY\k7.ZRZ05P`OSW5v/b[^ @]ډmE9\RoYsCoa<+/ʽ.4|"g9@˕cer )b ]h4:8xwh '"`#+lIb#(- Ma>6S[6vmPu\H QoVRVdZ!xYQnW"kՈ KGYmMPk1E)0)L[pA UdjV(y{u ePZT<>:!-V@ZB:/@/DdH0B?U-+-ř 0}eY 0Lw'q:;\!QQ_>P)G(50< j#(<7tw[,~nPLQs{TѵKc=a{ǜ:n0 Tu̴"Pok(A4Pjl~e/(ؼ=;I`(^t@gh(f储|}hdo/JZn`{1Jz\r9MLܚS3J}0+ldQQ6v(\n3s(AF;hu-Nw֪33 @0NaLr0gJ桐Cn9`Jv#1zI@#~[nilyf=})*P1]^F< xj`]Pp @sp<[HQT.,\h38/ iAwwM`pVJfͱ&\AAl>90O~}/‚:L|K^$-qO*"!L\&pt;JN_6@ЊȽ@> .o#J[ਭVE셽Fb_.(-/u q5BurD-H^hnPEBu @[s*6pDG ʅ;߻|D)L^0#ӽUL=Y̰eR~0o uHϭZ)B~qIȱ(W,VHKzTfD=EKo:nL^[6Bf і7;}C LkEl# #@nu1S թhzs$$n9G*_. ^`¶-V4ai>%k 74\a@|%Gyn0o^Cћe)*_*FԖ"G < 2+6 o 9Y|FZ*4V=Z`_>0;01He X4Q^#J^(Ljj;5;``n`cDB)M6@|v\B݁s!5N0. 5\q_6G 9R@j@8+0Ys%K AT?DpEﳹlBֈҠ`0<Fv!,#4߷JB [Z^Nm%E L)A+>0\wWx_.`"xӀ]jy݊olinܽox$?P\Z>f}yA<Q{WX9;AQي<+RpeiKiA#pFߠЦ폊Lq[!+2 -OGjQs^\/ {.: X ۬Wg/`Om؋%5ȃ@o_l#\y@q |THQ<lv.yV OA97p1ExKQ|G *h;X\TD&t(h2wi1:fHGmcIe^-h}g L9YE뻮|m>r(_I@ey"]!?-PH2q,kh0FG3P27t7PVyř׆io.u@ؓ ^Lj"܋nxK 3GPypD GĸU5[*MJ2۳kCOE Ò `_>6S.U8s_?eojDoQx:L9K^RӖ3\@I7| c}k )|v pEO@Bh_STdP,0\ >hcx!P]xж0{Wӭ9_nzT(Ssv@uWuW6oħk^?x -/cM~@fR[[C)旽#^5݀`D. "bG.@E@ֵǸf I[XS_M3>ywmU'9ZPbķՊkxU\PCnLt"G䡂Ws,px-.a?ZXLYA֡CjoQc/7 i5ݢ/H2b`\;t3N^)/@tJy(~N:-q6`]dߟhajwE7=Z#ta >fb{Ԩ }ݔr +*fҋ/p"Ks9\/Tk9R3(ħv7dZ-58> _>J)ޱwQ Ha3h T%t%nPGUB:RSN "M3A8>0s6g OO} {{@6pȷ2TJ>U"]zKX9"![.f>9z̕g8xrNjXL@Ȅ<J[r/̹şo9bI*/倊Lήn0Ts"6S[6M:.$b}&)ض )*C/+Mj=RĘu_.`` :]{Czۚbk/)R`*8?*SRTB{KH/3Xg՚z)8V [>i / tikD,汇@q̹cAu1j@ s9Ajl~eKBᚯЄfY✽^?8B!B ݋>4Y P)U?~4W|R}=5f!aVNȢ\l#4P)Xuz~n%|Vn4 n/S.xoQ @F8N0R``fODCPL1m)0G;l 1r[ *P^J rǹ)33soP3y/) [X &Av`kyC^rz5֊=;RZse@{uH1ea,(Y輰WdrMƨ/rhb׫G% / 7\L=@3a0/ L0]4/ LP CoxHqxЃ.!.j,܋2x-餭8yX\mf`,V rfkՙRj[R/WȃYlUEՈFm hS4̃}BJ!0 KhPLq{{8 Xy8nc~7F6"S4`_pһA/T3KWTݰN+CNDQ=8kaTiA mq#p؍`ZQ9]3%PH~álŇ7|}ab\H^zD#_>冏6qgj'ؙ"KR_.`Pj@Êe_p *#_Gf)QZу*=J$4Tied z`:6p<_>C #64`R_&tQc54E"xPxCP&N.8CRD(1i RhE Gk|o#J[ਭVE셽FbD0[Y[cAI+T'{@X1`fp- WN[/Z @[s*6`/0+% nh`]HAeLA cJ F`[af2)RD?Gw y[G 0[8t%V-!?$XKO+ fZGg9_/D9Ҡh^ i cFr@r%k Fxm3Z)-5Hc6[]tj F s#!2UI|`,x]K PZфצ -T@rUtZǧ"2 ؄eu|8 >.LQQ*?GԖ"G < 2+6 o 9Y|FZ*4V=Z`_ͰGڞ~xZWB9F<%."LᨋBP f8_n_.p#}r- 0 ,iCH B]$y@>+J&j}1i/Lf Ȯ {0240 P'/'ky9)0tvPzL'V_!r7 _R3|V|][8ɢ=f} Dg}}#@aF.'_'bD X9;AQي<+RpFZR_>7(i"S\@|m(Fk&LCS6Z{@9RPЋ[M\Ќr6_/#K쉻e{A7,-SiQJp9 - R!rE-_ۀݡ DbwAmP> \LQ+R2.ۀ dW ޑ*CфM^?;>-F m,5x6_wL#$)'޳}}ו-Gn+ @F an6B 2q,k =`ȱ=K%m ʬe<6r/|B#.)(G]l|AkK]]%V^@%#qxy)q{drA& >-U1oeLnfy<oFcx!P]lA4Ƌu7tk&2|,[]rrb[))*WحPk@fRワC)w _T/D."br%Ƞ'-TQkO@%bvVa /\x0S܋'.;.VVTF }%6]Z @|_o^.[%_ vet.pE yKz-.aYGL}|<|uhCyŨ@b |(׍of*~=*RpRzwspW "G/0zNi.Z!?BlNNX1ۣBcS>nJf9STT/Dwt? /Tk9R3(ħv7dZ-u8?pozp\ P9;. 6)lm#;YT|QB:RS>"hFXf9P=\s6g ?O } {{@6pȷ2TJ?Rn@%,ŜoG h_{[xm-Jve ooZڢpr{Y.0)\]k^cn Z̴l E.V{,X ?  햃<GF@ʏ B2E!zGXW|ʻY+ 6sH|v V#BCLA[H^w ڶFmk` 5\0E_/4֌XRi,jy`_f *2:P> 93{sg.6>۳M` KPA& @]ډmE9\RoYsCoa@٣D _XMG +w{S҈rEΈ{k<EB&s@-EL sG}D8՞oY!`?b3,z46O)W4M:.$b7+)\+2m 7ɫHc׵wt[#¬&K Of-{ *2 5P+ʺth2S(juWkuz^}G0dиHKUH( )cÅ~R[Vh[{NTrVe΄{V ޳0k{b_v~P5_6SkyE{I#RrJsPE`Aqy~_`6zZ̡$`AF?56iEФsГ./K/Zl\=;I`(^t@^!FL5uC;bS`1vhcb#ŷ\#7U"3)>sSo\0<ì~MyNj`6! [{bz4w4)?\Y]h=(1CD,bt^+2 yIkOzs;TQUCӌ^ 8*g L=@/aьrEfЦ B¼/_ԋV|:`kՙRj[3й,@#pUE )(FЦiPX_2|1 .Ӏxw\N PRm@б؀QaKhSWpc7awsZQ9]3%PH~álŇxj@`W>#nz_@rGOc83Si5@L%U)yHQѷ%x#z_",E W(踭BU-bڻX +@NP`DBs_. 4|TU!-- I'pal#!a\Esl4I2W9Jpmx$}ԇFmh< rMȃ biދE-,<eGw;N:@G L/B+Rp ^<"#qJ/mD P|KQ=QՊryЌY}/LQlv L^Tgc%P@4֜<r!*$QEO.i|esDq?f-"ESAo}St<GB|nRLcOA Zz^QZ!-XRSU_.rXGG-^3 {alh }^9ڒ5`Oy߶iq$a1ȭ.fE0Z1Ŵ `[Fc偱u-/ F/lB9jE\6So`pSIV GjmTGyn0o^Cћe)*ʡ) ۟#jF#\hΕg`ݷ셜,>#-|k+Zl[/LGR%gYPDC]$y@>+J&j}1i/L_G #pJڀyXg|zGB(f Г|[I󵼜J JE][V_!r~?K*E]pwgڭ0Ȟ_} ƋWu/*x$||(6c@xD1rݠ(lE~jxn)8W֋ҠFZRz_@wЋ8oPhGE­PLCS6Z{/3mPM\Ћr6b3r;=a/4@?:<'޾ГQG(Oϵo@ߠ)A/rE-xl z @ac O;R@xKQ|  3E;X\TD&t(h2wi1:fHGmcIA/3|f,z"]WXtsx/TX#@F an6B 2q,k \`ȱ=K%Am`9Q 3(~\x6yO`>RԵ>FO(=pDr5"@u|"l8Rf{<7 *^{]:=PW̟Q+w/kx ޒV \v:rhV(^+~(zAbXf(׍of*~=*RpRzwspW "G/0zNi.Z!?BlN *##KHT]ˑA!>.5p6} T+\`+*??G Ha3 xL!J/\GRj HO\<6K4sz6l}f} {{@6pȷ2TJ\/'UTE Xs_.n9`O ֢t0W>"~_.{Y.0Cݫk-+}^L֭Pb,a@Ha-N~NXpnhq>pL@Ȅ<J[3֌rj`_>i.b*SQ3C׌rAEXgW7*9xD5=xnc%kY WXx EsJj0n G /&XYtm]_sk𵚪2>hB__[j ?"4_Js d_.opR&׌=a CD/}؏e4P<{FR0![_.mRG^Ma̵/Ȣz_un`Ղi"{r x!-oxrWP(\17z@a)0/xh-V/^yʅL=2ZL!> FZf * .{ 35p_ݘ2~{L5-`h#94_# Ƙk` |Dj w@1 Ƨef f``2oV|M[+ 2g>e_p *rg(*-g paJF/\4b_0W9@lI1ԵsG}(aD؆B+wЄ<GPv{4셱e=;xp/>e! ]sC3Z)-5Hc6[]tj F s#!2UI׈Xz߅rԊ&,6mէ|m`@|%GRфeu|&h6yACSrAd\hP9/5`/d9 ^[bD@/ӻy B % ԀPR_00(cD 'FyEצk`gqHml5L!T9;݁D+QpE!y}ju7l{_ԋ2#)  |skayܬ9˒% ""CS>+J&j}1i/L_G #pJڀyXg|zGB(f Г|[I󵼜J JE][V_!r7 x.2_Z+ٵK{,ڣm&׹{HT@EsEkPmbD X9;AQي<+RpAߍХ<0yJMv+_'LCS6Z{/KC .'NVB~cuQ q1\yۆXRB\@o_lҢ<1BǮ(Oz_L+jV6] 0c nr1n_obZqa*Sg@w"<MPd%bbt̐ƒX/K^-͂u [603d{:R?r.#K*pxc .+-fA۶0wS1k]Y\Mq#0>|=x' 0?Ba}\Pz >jEEqAE^(K̀/H]=P,Wdn\Pbc DW8g(|Ag(<B>pL.(_wOy@@?op"{yat7U7#*F8BPq^PQ8#/rd~5g2fp\w\w-hʽeo{I?$C R꽗@4b~y| BzofSvK}qXkdP_r(k1pT0!8#f/ZkqɊrѵn9@UxWkm o{pJw`*؅Ewе!(K!|+r z"G={,6#P>7Sf!Duh-P$+6C= A1^3DD*~=*BpRzg@Ng5pW "G0zFi,} c!hjq}jl,2}kFI+n}!0{&OXۘQT|¤H%䩞Jrs9 _/TԺk9BRgݧO[q~V1<R[HG63 ڴ.1πv .Z2]ZwGL9aZ"SQe(5}9UE׺wKX,9/pn9dkQZbqbah ] Piruw/8?.Qc֭gb~,>azýk05ºsC kj} ( De2%FV!PR}pES̲XXG1-?@ܾ7.P%M5q+HQAr]yOFlCJC<&Fۥ\b8b-T>M0P;Fb] 9xD5繾cFz`sTױ0{낹w{R`NI @lٞA1s<‹!5,\Y36T7ZGw$`K6sg{A#^33s|`PrAmpR&ɽa_.0qU6Uy`R0!G*r{D ji2OZ0glx>oX"Hqd֋r(9r,}*#YCjrAk̟X$VP(\17z@X}c X qU+Vd@dLڇ̇ T=0RGж 0lE7iYսn{A8IY6ԳDEQ @E8K: > E(@)dcŷ7QANOld{&D~&80(9u]alӊCݡI ~mkG}_ 5Օ T#Q} We!?݋>T>Y Uc/8\]I'T: Г[s `FB&`ᔕ,ʆ8BSEU ]Q {u-N~o Hc1XH徺2@D x ޗYdV^wbHQ-aӷ< b/cdOmjB ! ~:>rwcbd _@SxoQ @=8`F,1*" b9nqCosoPhgfkcuJV agЀ dE㩗^ ZQAgGf]*꣟(G) >f9@1؈hk xEظ"9iIo+ z_|hnc70#ũWJhy 3"tP8cCDh@Lr4,4\P}@?B`ւ*=V½8 YR)N'xeU/ ;L=/0cX7™}UgFJyb(mp q9TA{7NyӠ2 )5 lRg@\H0m$ZN8Q_ G3څ`Tg\8A,{8^;5T"P&N,8uy-H8bx$8fH6`b{s%$^9w'#JXQ+`ڴA3K% +bw?64^h*,, ǨWl(Z32DE>4eaqDm(DQA "ҹ-Xv~{!'o "ي%B+Ӻ>}Vi,cGPs#Jy@+B5]+֋ 0go7Ԝkq *C7N@w b(q۪ odl5ZlAϯBg\`Z&`5}$`N|7.H40}WU~bz_(lUx >)쾺C)iƁkY_>`N> ԇ)BO.>N%d8w!0` L'}T`_!r/ x.2݊ok 79YGD_}'Q}̸ЀxtN|Շ6BD1q,0B1G?5~7+io#-t)!@w47(iۣ"R<@L6^ih9}f~^%!qP W!?\ᱷuQ q1\y{{1f_W/:8x&޶ГEy*^cl][!P MpE-<@6`;qA\to(`.1qt >*CQMYh;F2diSseZ Le3RN}f.+-fA ]^ XA|{Nt ؔ[LP^l [of*/ S.U8\8:r/UQA{(BT|"nK`N2as/gy1'ض[@be0?9m'`>Md?38gh>W,l ouVr4@r5"PAE@Eu`pfT$]zX|ط@k {%q?!qߖ2yh9I-ebƾM O3#_ے+BP;|p.G1^i[=+֜M2ief tGє{H $䘿&"}/gh(rй BA[$Ov'( >G[DJA}NZ(~]~Bl+-3B!Cp~k;{xcOLɊѵn9@U>Z @Vd]U 5wyLpE 90 J^mAXAw4@R0!͔Elmx96 g{~qtV{PC.D _,z/w-6TDc"N^)>]Y0Fi,} c(pN8fjl,2VhlZ^Q|`yShMө1BcS>fJf>>+*䩮 D{pnTG`?/TԺk9BRgݧO[;{kL(B~/rDg ŞANֵ~@0^b^-g65 ڴ.1׀jv/p@=Cp0W9"`c_/p~};"`շ[W1wY(3 n_Jަ 3] !0b]ZR.žlP(yk~q@QH>QM`Ŋ⽷?D9$U;}>C c!" r,ޟlPmky` 5<0E_ /hn2a*CQC@EXgWW 9xD5繾cF=<樮c%`]JYH"9!Cl{9YDs10cqfе߽ j]}ćƖU(['E^/l6@kfal*h[h9/qR&Mucgb4:ض,|(L jSh&@#h9cTP9VH 'umz`&3_2A1zQ X-)\-l5P`O[WNe6Ak̅PmHU NJ&mĶ"B,P䊹0a WїH"gvbZM 6Ŗk<EB&5@5EH s_O. |] -VB2&>S1SlWo)"P AԘAԇlVi6^V{1ZmNOYmMPk1D1ٶK OfB{ *" 5P+}ʲtePZT<9:!+V@ZB:lTDyĐRpTFV_6ST8L,m_(u9) R>/ 3]p0ݽ %WԘC(ld5'1#}}j-9Đ l(3UmZp;49Ajlr 5{T0>;I`Ƒ(^t@^!؞ 8Bx_@w/P d%@N+Tj;4RRJK)!P03al97(23ev܂5eB%oB4`/6b<ĩW6 b؃qLbLKG HqEsĹXveȇ6v3Rz5ਤ8w:v:QA(!' /N 21 _( FfNW f*[O =O Dpo#tһyX\ڬ h2+3{t >֪3#/[>/e q.Zo q@u թo$@mͩX _0 O'*BPh!(aZ/F_vQWBqsw2␙1O~[}s~i0za-VTai(>%fJ-WXE7?k8" Xeu| Ek]ȇ,l{"-E(*sy@D:W/5`/dmVA$[QcDheRT>}Vi,cGP fcANQc^ѵiЛ^sVvIIqנ2P|t>N JNFnHQAN2Z9 !}f>u8aQ.Kw(~ࢉD3(pE XP'f? /'Ww8%m8p-4߯J}B QL|GISA?@4pN*Bi~BS|ixLv+O̮-\dQg}݋D{(rAEsEk0zmf~g~ /nPt"G?5~7+9FZRZ0mj/ioPӶGEx­l(F}m xE-I-j= բ@i : X W ^܀3 /y.b-bN HSgm =y_^<# MpE-{  @aس!8@ zEw0LV@i jE*Ey&*h2`q'REq('Yh;FgQX9@Zp?`)'>}}n#7% ~" *]!?#PHz!L lD+ƾy7rp'xۃ!qq29X|-U17rN/(fLf~cx!PEqy@E\Hc1^4^+O"k8>y!Z; ++xooDSF .c] Rjh(2i!] _>q[A1b ,vdP_(~ Qڱ|-JKŌ;"}_M3~A;xo6ЊdE _xVXch=TDv~+T aOw+BP>&B4WIT]Jf20# !C/6F r/awx9~Bi5͢/2b`j[{h^$M/azZ[CD&;>?x_l4| %O/_$c!PR}pESe"cxQc 3|_C" / 5s !"S@Tc/po _tsGY_>0TnYrviĜ?Pb A_r@EXgWW 9xD5繾cF:<`sTױ0q뀹w{Ruu~ Y O뜓Aā=C-apetvTؒ eu }.| E/DzEy薮05FDf_7Σ_.@ @~g4*9R3?_ڶVH '5mz`&3_tGf(׫,sb@=d ]U1F^!3qcE6b[W|Bt-b%W ՕJ\aCԊ|gS9@kp`J(rtu@*@Q5͢/P@)vF#pAd7 @T|櫁GX M_)J)CД4 8xz<cBB5fla%[_!ˊZ}1x|] 1nnDջCm aF* B"PBg,KH_fEiήzPTwI]  -U!`*)j0E!QQ*"8Lwo(G56j|BI6V|}[ǜWcr7_.@S.xŗ @8Nr!Hl0\3cP'TSwh0!m03r@Qb`# Li~(qLـkņ?0֟_>,~`M٠PV!_c46v`ܞNcus@t:-η8 F%=("R4`S,U[A 'B@S+R.dt^鼢9T~D'B"o 6Up:uEzq'v-V.Ꙓq($^2>:}av'1zI<޶a;74<#řVtSe;z#TBVāwW|5Pƕ :n+qUض^̇Yj 7p9pg |PZB8^6ᓐ0RQuU4!40W}rD0 A8>㱏R8 / B'wPG:(~o(RnKGi,b/_`0[Y. 2zaPEBu PA[s*V`O/0 O'*BHLE.i~esD< [&E觊 ~M4`VpjK O+vH}@Dֽ"c;jt`NMU_ rKNo:/܀~aو_A߳Cjq^S7#Of60#b7R>$8fH6`b{s%$*R2G0B>jEL6So`&[xrUt񓚺voJ*#iЀUXXV7ʷQPf1e|V8lA~ υ\y,;pրŷI [lE vK^ZPO ږ~Z(a~9 ԀPsֱܠd14^sv\PM'5'q\B񍓳8?J\FC8ʢ|/G@M/*_j!  4µ0L8j70e #&\4h`(5lPت0\FvUcqZ9g$R=8w4QRTP5"_>OW ,L/`"_Po_.`[ `~2͑M/+>'QAEsEk0zmf\o(FT?û%O "ʚ_~FZR_>7(iۣ"R<@L6^ih9}f~Rc(G zpӀ_ۺ(~ ,s B!<{{1xxֺb/-STM/P:lTp&ni=X빽[E6$`?_ԊTZPA냐O PTagO.6w6$$j3ҧO&hpEYdY7ϑ@W^QAF a6B@ Ae,Xd ]1ͻY*A!j[恮#pETϻE &;E Ɇik)اU'$ň"$&ݧ\:'BPj;d$BT|Bώ9Ud/0Y_re0 eyt|m`>rfqܕ4@18r}[Y'B;Jw\ !TP]/(.^(K̀/H]=P,Wdl o}w@}%#qx?y!q{wbuL.T HIZŌ0>p 9(t8/(i9Ƌ 2'@ǯϡ|-/T!Z ++xooDSF KT'!Z""{/h(t=3 ؃y68@YMDEu-q9B|VB!Cp~g;>p\PbD9Х$B^a~S.,=AA?\PPj E D*.{`YmG }|<| `:rh'(ʡo?;3k7# Y!8^Zv)^]v `{_. .:Q(V%{.vAcuZ!* @M+4;D}ܽxE]by"f ;m=*L=FX)1FiDWSUS=/a'S1x[<0/'Q傊Zw-G6B|[jlVtK#)+ 3b@='E!g9|(aZMPr|3X qGcyߗbu kp3%~wh># !2UƁYC]@%dJqZbYvpu_+֢r+h 8r>[nf#Qc֭gb~,>azZ.f9}>x_l4{  %?/P~ |)afYX,{#@ԘC<kHz_>:n_ZdnJ.!k.vATdB GVSٶ5\0熚_.hn!F!k"R+ 5;^Gyo޷/8<L`ݞT(kc1Ī}C{g{:dEq`csf?`?][LVS>CcK*rO?^U#ZG dyno]y 5\m- n;5< tc# ̾nG2*MUB;T|ȑJQB )M^}K^/Ȭz?ef`^Eu!5h+dFz7<9V4 5z >@+憾8[X(R+v+>^xrba`J_._>p/]]Plr ¶Lg=2jL!6 FZe *> <GX ;eYB:2C(Juv} \}yE*uEճq~^^p)<>1><`>\!:eWSì{W >0K{b_q~lgI}5>)rAE8K: >ڻaǾ&B5J$]ƒ!cn/ 3i~}l^f1N+UmZp;49Ajl|}Օ T#Qb]?8a^/@Q|Sb*jBe9 X5b!ܕ{BHs=5f!\M偨dQU66(\n3(AJ֢q^46,5T+DP}EJ~_`i%T޹OQaӷ1{1_.6r!ӫ]Tԩ(vxL쁌hbm11 `X8`F,1*" b9n^46ncNZ{қ'4 quz 򡹍^ 8*igN@@T2 %NV4|M/LMM/2AŹxqd\m 8h kAsb\I^zD%߷my~~`hLv`g̩JTCWMye!+»+>طiW<+hU@&,wy@MXQL@]Q\# I'pa~Jf%'\4DZO,$sU'Gh90v =/viZ';VG[W\(~o(RnKGi,b/7"@1s_0lT mzAP<:i7T`?/ wVߧd4SQ(aZ/FJDLj*s&ܖ,DͰeR~PWA!Ofu B|Z#'EӅr'-YA G痩* /D9vGM&M/ iƑ Bw5xp /Źi`;Ԭ# #YAnu1ҩ75vb\ `ƁWF|@JƂ׵84[.VTai(>%fJ-׏bwot/4` /*78`Q [cZRŎ[Y#1*sy@DB;pր&-lD5FK "r8ĬmOp_mr!Fxĵ85`/cDɵ  ZwZ"Qc^ѵi_.k@Iqנ2Pވ P7|LDQ\ߚCPDj !GH3}p- 0>wY0PDCM$q@>+J*j}?1i=/*< Fv_!,O/0~ P&2QRTP5*0 RX|_.PozɺJ`~bvm>'=M3Nڎ>P#`N28~Kj /P=//⭷@+n F^|M3qo@1>p'xۃyZT H$@v@1ccSG} Cw2 d>4Ƌuكnli9|S> \!]!]!{{ ҥL6:\Le_`~r RjL%J18>񂐮i|{PM/~ o1^qp5l7>T}o JZciE5@QlcuZ!*3Pc M;D}^Q|us٣5~N{[`#?BcS>fJf>QQTTKQ8Lq.`*jݵ! )- "VtK#[  /p%@cX]{RHgл6' PB0ӔAE9V&ZlibuAi]b18yӒz;b~*@<[%ȩ*"/^bpŲ-]8cVpEi=Gϗ[>ρ{9,a-Wcc| j3غ>M> TK`zZ=f9c}~ hӮ% %O/_$c!PR}pESe"cxQc 3|_C" /_6"`y\k "bDM&1NgS)RE/eFۥE/s*WF(E/TDuvupf? 93󘣺Ɏ^=۳ EpsC0Xoz @9'+{#Rfl,\Y4m0]d5U#>4Ba-`< i{@#<77xb>s dm۸Ô2'vclD`u<TPH%Z(9@hZ!6Դ=Y?c֫| "b\>J\-l5P`O?+#YCjr@k̅ѰWȌtoX$@'J}d!b%W }qJFVr-yvo}@ Q+QM/>) _ȁŖk<EB&4@5EHOj'㽋3_ 8JVX&>@L%!hGp~y(\DŽ j J Bڡe!y!bVM/0c :][Czۚbbm!0!H[pAUDjV(y e (-Y/p-q "g"@j81_^_P@JÅ~R[Vh[}NԶXc0L&XZ:7 h݅j0EgI'R{7D@)yb]x~@1DqMkOoƱ@q̹ cp@UgVMl~Nz>2t_YmXB2O_PU3Gq g/t@^!!?E*[KV,n`{1Jz>Hs=5f!\MQɢ\l#4mP!Xu_z~^%QZ? ^3ilX8kWW.H9/S2<\jy"Gǣ`Np܄4O@c/p_0sPBD%N m{>&L|Bw|1Wk0j d#94-wc503~H5uC;b)0Gl1pb*HK(m(qLy;xrZ3ev܂5:A%YFv`kqC^rz5`ckE!uPi>`@8:^46ncNZ{қ'4 q{!|hnc70#ũWJ_>A8_v:QA(!"LY|A怐0ضſ3a7@+B`n}>>)s `Z! D"L>g^H8#.~E 6W'z-h';LM/p%`ưn3XΌt/PZ΋d"qӀ=**7 :N8*| 4pnqE*bTm5Wt:t^*~?w"ʞ XE@߲Al4 l u:xN8}?[X0R(]3%PH~àlECWe¹Q$J;h;74<#řVtSe;z#TBVāwW|5Pƕ :n+q?Pnyv&5PTXQ@ ž2C@E p e> .00CYd $s6s0*Y1Ե汏R87D0/A\8A,{8^;5TkcНĉeGw;N:@G eK!8/>}&qq6sPD PL(`ݖ(jEY^+oD*vK@1se qmr*Cp-qMPЅsVN} *hkNEJ^>fBU@$?QE*3%LňWQ0w! MD)70-T@h*I-vJH% C1 >& QMY6@ňڲQ<D.Nk o 9Yl`}*4d+jr9`Zw`~bVж'/n/4s1;uLjn4ЊFyEצ _ _Ԝkq *C7N@w b(q۪ od4ophjBg\`Z&`5}$`N|7.H40}WU~bӚ_6(lU_.O #pJڀqZ9g$R=8w4QRTP5"_>OW ,L/`"_Po_.`][ɢ>z :O8>O/ *+XGŒ\: WԂ%)`M/(rj$)2l{C975AH(>e}2Ff,"]V&[̺y |WPe !LA ]^ XA|{Nt ؔ^a P^l i} Hx}P?R۱'#mw[:s _.`I7pr}dP8e0?׶0oS1g|[Y|NO?`|*w{W>`~OGz;J|Wz@Bڝݢ@EoY >K= MU9Q >` 0~ ![ -e\J Fz'8n.J_PTy@Q3!@;hvy28""x{AWӭ9-g9:] |9㽽MR&,x?Pk@fR㽜 x@/f`"gZvȠm(~ Qڟ86 *$ݞۧ:E-hPp$9yԊ>ܷ~ЊdEi"8@UVk ZsKQI`׻|]Xt={"`cK1d"^ UK]`(C@)3"`:rhm1*0~V{/]"" Y!8^Zv)^]v `_>p > +@t PJ$hjq{شBc;A:@Y7>=Z'tu36fb}Thl=:@a3@z@%dJqZbYvw^+x9~[:W$[_>]ݡz+ǻ,D{[BևPA Bkq06A'b O)P'kIȘ&Gc`>Pw8W G/<7wHۃuLC= P::cU?uɊ wLj!3ο,\Y0=[{jG|hlQ2[_Z4"p^ /&[֍ clD|yT6Uy`R0!G*rGRjI 0glxz/ADPzw>P䊹R 0b>!g|b1DGq6_>paZ,{;LI(rޥ[ \,eԘBjm8"/(}*> 4:@APN/`_S:qv7߲]@<` 1!!36͵" !ˊZ}1x|]1nnDջCm aFJݲ BKik^"0nEiήz5zAyܥA -U! O "c2><`>\!:eWMDe.g{-T">0Kwž:'ePÒ`?$*d*"Y c>510P %yXlP Qs{TѵIc=a{ǜ:ݮ0f TuiEФ' ._>PP|@U 829+֕M 4\7o%@N+TUay9]I'T.r&&@On)i%WlSz *Y} q " @T+"*YyӫǛ*0Ҋ:mƞ_>`ԡ|?JvE]<@!bc./p7py?^Ly-&Fk04yǜp;Eb1v?QECP 1mєqL 6 X8lml1i RC`11`g ߠ8q ֔#fz NVa1zqՀ{v`ֵB}b¶YP6"d>^+1Ab q " HqՀv 8w:v:QA(!"4eDSr c#7nV||2w6SbŁ| "ܑJq:]G\<@, l6Pm`L+3*6i"R-0U488{9كy#=hV)pT>V! 0L/8FþbNm=NGQ{- c,r4Wb*FfXxEN}̡s'"쉞UX-J– Q=r (v1e 6T+ mL8pՀBM2 ؓ¹Q$J~onwn iyF3}!2*P1)"v\F6Z aEXx7p'P6 V*ܛ߀X ݲ|DPUAuE qgP 3B8I?@ 3|> lUALCOx?.46fOvx HZ/㝚Tk(} Ae2; [ 8Wʰu "V@ٺG PD PL(`ݖ(jEY^+oD*vb|;\`%X m5V:W6ٕ T/ PAU+rZQ _.0 O'*BPh!(aZ/F{% #Q 0ԭf2)BD?Ulo qtKW[Q|Z#'EӅr'-YA G痩*L/ rN/wz~4 F]^>z'k FxM`³ڶi0q$a1+ȭ.F:Cs+!8ʈ~2UIrXB>jEL6So`&[kn5Zn ~R݁#iЀUXXV7ʷQPf1e|VmeEy.4Hʳ`ӷ셜,MZ*4d+jl[/- Je<r(Vv~aYZ V0j+6z0vIIqנ2P|t>NpSS :*!{("r5<!GH3}p- 0 )QEfP7RV!TO)Uay >)՝*,4߯J}B |r /*L'}T``WRLv+O̮-\rmL0^(r@EsEkPP&/7O#j/* wG7(J:[VxEΕ5lo#-t) /;h9Q)pk &yur5y pӀ_>ᱷuQ q1|॒>eCU,3^̩U!.ċ X(OkPA<7|a #uO/J @aX)1$`?x|!jE*E) ɸSt^HAġB&, (m,5lKE-L0SEYdY7ϑ@oJ,QAF a6B@ a(_AoGD+ƾy7r{w<2)_y}x>3 8wP|rWۃW|r?Ez+\t'>p! u-TD`?(K1̀?P?.`3JX|T]E]u^I>|?!qK ޖ2r.P%#ZŌMO;#rlg s#/rdl|Ot2>Vk 1*Gє.e%T'!@fR[e*Pe/t 3rCX"8[DŎ\" Fװ J? t˽Bp Ouc/wCp~GCyԊ>ܷ~NJ·ZkZ @힃 5^T gOW_>PPj E [%]8ށf#2 0#l[6P}ӓ P7|PC.D _,/c-vEj./v{R9_.@ {-dLEsih>`HK؎DĬ~D v:ۺk3>*4  ⰙZ4\@`g ŞANۜ,@eQ S*Zα5"p`S"hp,A#RbYsolL`{ՊOjN8Bd*%n*ANU~%,ŜopniP﵂l-J6enoZlQ8zwY>`vzO][c\P5fl Y&V@f7 ? ,q< P&`?|B&Gc`>\є0,Vd, j!a O/P%u9 t\+J.!g.Ʉ8J[ٶ/sC+9@s1a *CQr/ C>G/<7wHۃuLC= P::cU?uɊ wLj!3ο,\Y0=[{jG|hlQ2[_Z4"ȿ?XQ8@.@mpR&\ ~RSC)܈(׍PAm d `CTm[+6`&}ްD>/ȬzQrY\1W [{ !ؓk|DԮU1F^!3wȱI@ȇ+>P:@+J%@cG_\"tba`J_>@3.]}rm(\f(CRh#it~Aq UnЄTN}\ԾI p1c+)'@i6^V{1Z5 EAylLհq1^z^ur><`>\!:eWMDm+5j\ag&`i~y_,jXRrDEq@E8K: >ڻaǾ&B5J$+>.'17L?]{4_>5IsQƌဪ68 d}6e 56:RU3{dXW lBL/}} *yGX5b!+Rɭ90# mJ/D%r!(W\/P=?dd-PNo*T"^#5 ܓCSO/ncO/0sPBD%NVcb`8</<p F5<\cN8 F`"s ̌AA;"RMݡ(h8by@,l6JoDR`8< QL\ 0d,?=#80 kcuJV agЀ dE㩗^ ZQAgGf}ᓊb¶YP6"d>^46ncNZ{қ'4 q " H=U3\A8^yv:QA(!"4eDSrWd݋mkX _6qЃ .!.j,܋2x!tһyX\m* SV:1XΌt/PZwD=b=**hO8 A4<:N8*rh(l6=oA 3x8V$p$pHqӀ=h,r4Wb*FfXxENgO/8*{'`:0Yl4 l u:{pڍ`ZQ8ll@7PHI&{qX8W~#Q6 P޹'q v)δk vȜ`}Ӣ̺S /qX \ M m@U 7,wy@"@nP`DBs_>h9 ž2C@E }?l~OPL/9}`$>9" DG})D "O yq.Vx HZ/㝚TkcНĉeGw;1+e:3_Zgj _.@? ?l)LQZ( {Hn9\PÜo ̲wY@epܦ! ,"SH ښS =\`.DY[NU2z1CP´^Hq9xC݊m-"DSņj yGG 0[t%ŧ;qR>]X Zz"^ݢrt~ r@q{@nHc0l/A߳Cjq^S7#Of60#b7R>$8fH6`bJH32rNFStM/kq~i0za-VTai(>%fJ-WXE7?@l*"iЀUXXV7ʷQPf1e|V8lA~偈t<{ _8}k^ۤBHhiqYAX4Q^#J^萊k%`6Q̓Z¨14^sv\PM'5'q\B񍓳8?J\FC8ʢ|Vxn("r5<!GH3}p- 0 iCH BM$q@>+J*j}?1id [Ȯ { 0\2`N> ԇ)sMhyq()B`*(r"_.tҧ+H X|ș_>(Wb*5œw'fn.s=f}oұyA|Q8CnPt"G?5~7+k٠FZR_.@wr7(iۣ"R<@L6^ih9}f~Rc(G zpӀ_>ᱷuQ q1|3vbN; q!^t4\ZWEy*^c4< pE-x9{(rjn1$`?x|!jE*E) ~s BX\TD*t(h_@1:ېƒXZЂ3 H9YxwYl1NJ^! zd]XL/D+y Io1`!v7FgmBGYD_bSԠl/ e±O'A vO&H<9YW#Tp6T)ĸU5J>A 0 2sK˒ w1} HEMOuOvlH:L9sky:$o oK]N'?pv>-1k]Y\Mq#0>|Aſ `~m> + >}|B{₊HY dۥQ{E*聨JG /(~ 0CVn\i9~8n*8CߌC4`\xն.0{Wӭ9-,/T!Z ++xooDSFU>\OB>4!{9DC) _TD-"bG.@E׳~ J{/t*$]`N`!Cp~9G4F_'u[ЊdEi"rAUxWkmY׵ > vat.pE 傂W[/V[%=8#BׁC/6^oa"Yr(/_3i!8^Zv)^]v `{_. .:Q(k8@QlcuZ!*Z iƦ֝>~D v:zk3>*46Uc>kvAz`.x`9X傊Zw-G6B|[jlVtK#<@( f ='9Yyh9j;r`S>"M70#A `wx_.76g?K X{}O g4#D8P8?k (qV rH?-`,|;\]债 dkQZi,CPQMyc0bEb9xo0Da_u@}i! qW2m /Z:湣,5<0TM/ ݲ84Kky@}X5\P)}^Gyo޷/uLBS <"SR1Ī}Cַ\C:dEq`cZJ]]ӷеj]}ćnݑk-4ZG ff߅pL\ѶmCaJ\'55_.5\`u<PAV3@`{ $9R3?j@hZ!6Գ齀Y?c֫| "eb\>JhI0"{r-H֐\Psa42#V+ۊ| 3o+bnT 䪘=6p{@ Q+QM  w{SrE{b˵Up!E SH@GŹ/T'a3_h+y5\@i9<u4=M㘇uLHƌ >`뫞!>@YxH^Gs'1L/L`X@q̹ cp@UgVMZVԩCOVg]~_.(x{T0>;I`Ƒ(+2E7oBVBe9H^#Dq4~O<)un'4+)<,ʆ8BSE-XcznFVJ֢z Hc`+ɪT+DP}EJ~_`i|*Tſ">#5 1{1_.۱_>w_Q}8L #{_Fe{1eWk0j Gsi0Z# Ƙk`fL+y*MD;4Zs6My?`S=S)FnUK)!P0w0D3l97(3ev܂5:A%Y3h_lmu"sKSl->"Q"\Y4P{0 iPci5( 2bxat7P1'=mf8jQujlj@(rAT2 glh` h _.&_>e s6?#3'tNp qQ+d^H, uIJfAs܀\ 1uޣcV)^8U488{{PUTОp2hu3qUH/[7/\PQ3{tZo^`1~^*h%@T┧{Оe֯<\PД"S16+:Wt:cZ 쉞UX-J– QS1.nøu#ՊaE=S2K@P4}Հ$FT/= ۶ < ?a?c X8j7"sR㐢,bUod@@Ê8nO޸2@Am:jq6zwoPUAuE Qc 8wEs260$±O _.9}`$>9" DG})D "O yq.Vx 0V߀SE*[xp)zjH=/Dw0lt^ "K?/Dx tu55<&Jb*EDpV+"^y#R[/0,!.]P+Ae8:i7T`?/ wVߧD!L^0#Rܯl;b(G5PbaˤTj]/;(i5nՖ@WDB~uIȱȺWd,vG[/`NMUa *65|۽ 7`_G6_.A߳Cjq^S7#Of60#b7R>$8fH6`b{s%$*RK ̌x#K {o! MD)70-T@h*I-vJcSN²P}zE5.CT mOeEy.4Hʳ`ӷ셜,MZ*4d+jl[ R>ւ `~bVж'/*MEE \Ps#Jy@+B5] yΎo = ص!'g;q1ƍ2pE!|k8hpZiPr>3: 0yXJ1Ďd DpDsBk?LP̺ [_O #*1 8p-i_='!0@ ,'"ߔ ŧ<}}n#7TY!pbo!jE*gB &[Ӥhn{Jqږy#enPL6DN[{4O7>"nc1d1Ϣۦ$RM~*X8\C:*EP!rA[Ū_h啀dηDMe%`b@l1 AGð"U>ZlݷllH:L9sk:$r} ߧ!NY.:O?G]-1g|[Y|NO?`|*eW>`~r/Ba\P}BrEHe)>*}lzFi{*s N+|0@a(Bzx[&(_oW˹@@Nhq/36U?qԇ|Sp`;@E\Hc1^^itk&` \ef}>rrb)]dZʳ ~$C Rʊ'^!(-sx /͟ 5xJD-"bmr%Ƞ>'-Qڷ[ywDZ! !80} at~ɊkEpm =@|B ׻0¢;}!(ڂ~*Hѥ\f20# !C/6^cau"Yr(/?3i!8^Zv)^]v `_>p > +@t PJZ\?BlN8DE@ݙ_C"o(>zE]by"f ;\k3>*46Ucm8l} jBBj9@Tz[閟L\m8s*jݵ! o SZ-8x/r] xSEN_Y=2?AeQ S*Zα^-g60z t3 Sv</Bx=Kx@6pTT a JܾU"Rq%wKX,9N/.ҠdkQZi,CPJ j@4C\i%D>XO/WS1`H>2`ķCsYLsCG%' jsǨw"RC>G/<7wHۃuLC= Po0cm 6vlOyڠ9sf_`?][wo&Zo0WkH׳;+ ${8!B\h6!0L.@ݎ@0FD̾nG< jSh&+-U3r-g|@hۖ1`~"Y?cyADP# +bn-º@X!޵ 0N/"sc,>ș_x>PlP.dr !Pc ]h4:8w 'VBN/`_S:qvrߍ, ~y(\DŽ j J 6׊H+C( ɫc8Uvz7N~"okP@VfB{ *"OLeb,!z!:>"g"@j8_X=Z}^+Ș )zH`nYmGEf` XZ(u9) ;\!QQ_>P0/0ݽ %WԘC(lOTЯS-8Ik Vr?iPs.t˜1P٦Cu:|ضvte@BzU%0|}pBmy@#t~BVBe9H^#Dq4xw%=PR&&@On)i%WlSz *Y} q "[hL(AJ֢646,5Tޫ+DP}EJ_`ikD*o)D#5 1{c4|̜:'Qlq{<&v&~hbi~k04$8Nr!Hl0\3cP'TSwh0!)0 6!J,lr0i RC`1gfߠ8q ֔ #fΠ;AoG㩗^ ZQAgGf]k,g~.!,`i5( 2bxat7P1'-9/D>4ԫG`g p "tP8cCDi4 9,/( FfNTABʼnD|Jq:]G\<@, lzQmV4 aj X=:`kՙRJb*csK **7 ؃n`@ AecRjrc46v`ܞNcutZoq8J{n P8UE8i^e֯<|? )M/"S16`/@}̡s'"쉞U[0Yl4 l u:{pڍ`ZQ8lgJơAz/\ (ObDғ *mA~"wn i)δk vȜ@8(qc|By!+»+>طiW-*P.O#B ,(\h &g |PZB8I?@ 3|8ie.ZB!h'r<3B@rK76ޓ#?.%|#|"XCm.#5| aJN_6DA~]!p.MTm(VE셽Fb_.(aηfYB\ 2W8n q@u թo$@mͩX _.0 O'*BPh!(aZ/F_vQ%fJ-WXE7?@l*"iЀUXXV7ʷQPf1e|V8lA~ υ\y,;pրŷI [lE vӺ>}Vi,cGPs#Jy@+B5]+֋ 0go7Ԝkq *C7N@w b(qe>&" (BfJV"PDj z~r>3: 0yXs%s A?DpDsBҠUay >)쾺C)iƁkYi_='!0@ ,'" /*L'}T``WRLv+O̮-\dQg} D*q;m&bD~3cr0B1G?5~7+k٠FZRjC/ioPӶGEx­l(F "r5f/KC.'NB~hE+p&{؋95*ąxrk]ޗx*GP:L/d_>ȩ˻UjsAӽ}VR Zx(-e)7$qtنp6_6^-h^!6l`Fɢ,@_eeŬ }%UG o!jE*gB &[슱oލg eenNQb!r#yJAA8v4 ># JV,mJ"45cR/q3QZMGJ6'O󐼁WV9ߺOmؔ[LP^lc@.j}=~"ckOF"D'aSL6\L!\Me,'OПk )1a3VAb>FC} OF%x=!D \wS.P*=e)>l޼ (+266Ux9N+a(|@i(|B-29i9P%#}x-Ō0D}G9򍀂MSpp.G1^//tZOlܖNP`j퀐뮐㽽MR&Cj0.)Pxh2Cb:WEJ~5i|{Sc  x񂈃X\2Iůi9(O>@m%bvV>a/5Mx/0C_.'u?3V$+Nr"h0PbD9Х$Bk\a]Xt {\_((y"`i>8Ɓo?ecށ0#ضmdņrD>(ˡs"pHCůi}AEEj.7;r3;pW "OW:QP>1 8[E"5;,7pjwY7>=Z'tfmT㰙av@z _>J)>@~1_qf= ċBZrQ´yU6g64 (^V _)r'Ͻ9CxZ2ZwGL9aZ"SQe(5^bOv%,Ŝo@$WV =Gϗ[>ρ{9,ݡz`->+,(3 nO@f7 ?ܻq{C``OFRPʏ A2E!6`w PeEb񾥧D9$U99J+4/-27ZGqW0; *_|`H ݲ#Ң9+~2E/倊Hή0s"8js}snjt=x<樮c%`g 4ps.,9%5Cl{g{:dEq`csfl,\Y4m0]d2uG1BYQ8G/ܪRvi/V(0֊"z&[֍ @0FD&(xFTPHEvbqM/>) _ȁŖ+ l-f(CRh#it~Aq Ux
W-i_>_.S:qv7߲o0또DD}XIZivheEYxH^Gsu_.`ưӻAt~aV~[Z QL"c2)u.HP(ҡBQZ^jM<`>\!:eWMDm+56j|ô,L5,b_q~liI}5XDE_gI'R{7D@)yb]x~@1DqeSDמ&` 8\v1c8M+u&-+ԡ' .x9PcO4*|uU%0|lXWsX4W 3| o*E*[KV,^#Dq4x9O|R&&@On)i%WlSz@T(*M,bu -֘WD 2DT(W7U.``A2^] "Lw,VrK, M|b[{Ho 8/! c/p_0sPBD%OJ/Bƞ}_F@?_L-&Fk04_>cN8 F`"s ̌AA;"RMݡ(h8by@,l6J4RRJK)!P0w0D3l97(gfkcuJV =ՍV'+0O8j֊ =;B0Zse>@}s1ea,( 2bxat7P1'=" HqՀR3|pSi4\"р  sÞpGjV||2w6GbŁ| "ܑJq:]G\<@, l6Pm`V:k `kՙRJ[3y,@#pUE !()pT>V!_c46v`ܞNcus@t:ᒀYԊH+"R4`_p[2P)KWb*FfXxEN}̡W= c176Up:uEzq'jøu#Պae[9" Dg3]hiڸ#'G5ߩ9"XCk(' +e:mcNtAx/[gj_>&Jb*EDpV+"^y#R[q-|,K ۼ jBuk m+?AN} *hkNEJ^>fBU@$?QE*3%Lňt$bD9baˤTگ)BQbG Nԧ +XKOd+2+!2U9 *ȱ; / ;bpFqd#9Opjq^S6l~m`FZ+"nLf}Iq r믋NmJϕfxe ?- {o! MD)70-T@h*I-vJHBVaaY`(>F"`Cњd!*[*FԖ"O< "+ނeNr6i` 1Z"n90;0?1+h[k&ʂ >6x^ Qrs#aԘWtm/9;a(㓚xvm8Aei'"8?J\FC8ʢ뿙=Zl89B@j@hskaq<˒9 "h"9\QV!TOk٠Ua >)쾺C)iƁkY4߯J}B [,'"L/ pL'}T``9r,xr݊ok 79YGD_}'QAEsEkPI `7pdL%O "ʚ_} &}bv~L}B=*"n dC1:Nӷl'9H/_΋=\NC,\rE+_`8=Ŝ}mfhk]ޗxr*G(pE-_`r"zn/V`sAӽ}VR2ۀ '+D,JKY!axJ4gI]lmHGicIz s f*r3wYl19r(m_I@_.p X a6V0`!"1@mʄenNQb!r~?VgoPP7]8(>w>iZtg(>Ϣ7:_>O9 WړAa1ns~M`b C^ XA|>!`Szq_.@YxY.Alٱg/:i uOvlH:L9s?s/_>@I7 䶺_PA۶0wS1k]Y\Mq#0>|=x' 0?Ba}\Pz >jEEqAEwGYʬg|AEWxR(b"cwSo}w@}%#qx?y!q{wbuL.T HIZŌMOoFUp`=⼠p.G1^//tk&`Z_N(C0ovAuWuWt)\}^R0? 92C:/SɆR/M!] z_~ o1qpk+@9i, nVZ(fli,CRτw3}x"YQu_.>p\Pb{0ȺU 5^T kOw+BP/ڂ~*H a1R+C@)3"`:rhm1*0V{PC/x HCůg=@E{]ʢrWl~pֺW.:Q(V%{.v["Qк]@M+4;D}ȑS(K̺9A@њ?aSݽ1BcS>fJf>QQTTDwtqx)?_/TԺk9BRgݧO[q~&WN!?Eg7l ?T%XAh9jDML864;Vp'Ͻ9C`#&@0m2JOt)Jn e1 /l-J6enoZlQ8߻,ݡz_qp]=[!&V@f7 ?  m8OFR.Prׄ R}̇+>`@AԘC<kHBW;4i;t\+j&{. r,އ 5@M/̶97r}5|@sĜއ 1GM/ A_b]]a(\EqԜ}{yQ]Jd] JYH"x9%5Cl{g{|`G/[&0c8petZu}OsVl֭'O?^q/q@kf]y 5\m- nZ7v&jy@0FDM/}8eTP\ RYXsC_oa-X qUe+Y!`0 /djnWo)Jvq~y(\DŽ j J 6׊HAߏll_jvz7N֐¬&쉇SVQ!O0#n!TiZ3P%C/3Xgp&_!8uV{jf O"c2><`>\!:eWMDm+5fHô,L^ׅ:'ePϒjNr7sPC`-8bd?/O E 6ޓR1z eF8M+u&}6?'=YmMvy_Pc㙯Brqd>s'{ 6 :unYlC[&"@9] P/P d%@N+Tj^46nHcNZ{[JyeQE>Y(NpT@;wP8cCDh@Lr4,4\PLh-,g_|D)s `Z! D"L>g^Jq:]G^bY`sՋj9nSV:1XLt/P>d/ 0sK **7؃n`@ AecRjyh(l6=oA 3̇[7D|3 9>pDqӀ=Ql<Mi+b*FMP`s܉8*w(B/. B`SaKSWԩpk7a:jE)Be(j@`WFKOd@(~0 Ov.&Z,x]{9U)iHQjOBye! +»+@ ۴+rXpo~b}'aVa ,(\hb_!"R|PǾ6Sz0\4DZO,$sU'G#Jp죾fpl" B aA7b biދEީ+: LT&pt;a޶dIm%.Y2@Њ}Qk pAAV }1_",VE^4vy,K~uT mzAP0i7T`?/ wVߧT&Z/fJ֋(Wn#Q 0w|V0H=5 RGyGG ~4؃@Dֽ"c;گl G痩*| rny۽ 7`_G6_.A߳Cjq^S7#(m֊DxR>$4fD6`b{s%$^9w'#JƂ׵84Q+`ڴA󳅗J-WXE7Ե{SR N²P}zE5.CT mOe2<Ds[ZbiE/dmVA|hr8bVжC-Jrާ&`6Q̓Z¨14^sv\PMGxvm8Ae|A %qD!eQu>__.(Z3{_2#!  4µ0L4jeIBnBhi@>+J*j} [_(Ww8%m4-|z(!0@ Yq()B`*MZP|zNt_X|_.Poz݊o3ٵK,L{QsF?/cc-] 8UL "bD X8;AQي4԰+Bp.3cٗ(`woPӶGEZ? ~6#3DN@-G 9H/_΋sSpӀz_.ۺ(~_.<\?|LsjuU 񢣧Xj<#pO/P: /d؃r"Sc.H~ǼjWZ}̸StCPZ S CYh;F2m(uj,z s W60dgŬ 2 djo($T&΂@lD+ƾy7rP?R۱'#" u>;rT!&0r(~߁ܒO1(C\uQ?۔@3L,>p x u'0JQBz;J|Wz@Bz_x(>Pۃ,e0@gqۥQA]j{tA{%O6(F!qw့ebL>p T D$~rA1coS1>tgCw d.p$EOكnl-N(C0c뮐㽽MR~6:ru%?r d)5˹ J1ta_.vK{HX\2Iůa9|A'@m%bvV>a/5Lx0CyQoU׊%V[5h- V+gU@D va>Wԋ4VIW] ۘ=Joc}3e`F>Bl[6^mgņrD>(ˡs"pDCsK.xk إ,*WeEc"gN^) /h] (~N:-әml݉ CzE]by_FH3 akiPoofmTӰg y yQ_>a:`.x`^(QZlt)SM 4ދ\`_.p%@C} ҈=) zwQ8os!D %V+Zα5"p`S" MA8 .`w{< az;b~UyXC}׽HT\xbη 74Zl-J6enoZ٢p/|Hlz4?.Qc极6 0z B}Xgy# h@(<\@1|k~i@QH>QMc/0bEbf8_C"BXڡIۡMXA~WZ}u >sD95Uٶ/sC+9@s1a *CQr/H C>G/H<7wDX< M)>`NI ~ Yd:dEi`cZJ= A]{=jG|hlQWf= ~{@H#^33{!(c S| v0L.@n] tc#f_?g@Y.V~g4?@[j/Pr*(^`FafmZ>%Did֋rHhI0jak"{rߺ !k@k̅PmHU NJ&mĶ"BG(Vr[0bK$³x;1ĻVqf^Z{o])iErtb˵Up!kE? SH@GŹ/TE3_hq4lQDCN/`_u*==6+8cBB5fla%kEB_QŊll_jvz7NYmMPk1Dm!0!D[pAU$jV(y e p%:>C}yE*uEհq1^z^ur><`>\!:HTQ8::@Ycp XZ(u9) RR` ?.0/0ݽ 5,?@)k0Q- cn4 0i}k `%Ά2~jP٦C>˶/x@3_BzU%0|GVu{ 6< r:{GJ!+rZw$Uc/8<|O\)un'L4+)=\TŸ+4%W\/P=b#["*YV6pzǖSH46,5WWD9'"`%/(ZGߣo 8yA 1^>6AF6>(F1sPWQ]Q~PHm1 0 m?8 aK'jC3 i hX$6c1(h0* b9nQ =V½8 YRNz?"^Tqv_.p%`ưy!Zuf{) t^$ ip3AUQA\w+g8 *`R_5p0㭛D. G [gP8UE8i4|Qlcr+b*FMP`s܉8*{'`:}!Ҁ%@ԩ+Epk7a:jE޲Be(j7ՀaO #Q6 P޹a8;FLgZ е;CdNU bRv" 婆4H .E7 Pq[gBU-b-U[ݽ j E qgP 3B8e/%$.اM*T!>-'/{A`Tg\8A,{8^ ČKS#\Fʎ`Gw+0Jo_Z" tu57(ȱު!/+T2eъWHT4v,K~uT mzAP06`(T`/ wVߧT&Z/fJ֋(WQ_FbaˤTj=/;(i5nҕV1ħ;V{ 9Y}95U* h_;Ywq{@nDc0l/A߳Cjq^S7#(m֊DxR>$4fD6`bJH3 2rNFStM/kq~i0za-VTai(>%g /4Zn F@l*"iЀUXXV7ʷQPf1e|h¶'ڲQEQA "ѹ-Xv~{!'o 5FKV6-L(fmK?D}Vi,cGP  ZwSam`ԘWtm/9;a(#JIqנ2PߟHW!(:' eEZ(r.Z3_6G9B@j@hskai<˒9 "h"L9\QV!T54(lU_(Ww8%m4p-r9gBS\|;JQRTP5\E0\OWX_.`yEYv~v+(fn.s3(Q倊>>0#O{ݛE1,G;AQɔ!&CxEΕ5lo#-t) /;h9Q(pk ~6(^hh9}fFEͱGzpZ(mP W!?4|cobg8=Ŝ}]BhX֋Q(OϳoPA<7|a uO/`ENEaC \to(`._)3}wȱ"4UPd%v/J\Yh@ >̯l`&ɢ,@_egY7ϑ@oJ,QAF a6B@ a(gB ~v\n}C%4Dmʄ8""?;E 㽹<%ޠniP||rgPgD/@[!ؼ8$EP!U>op0b&O w`0dirZ%`¼,֛++:i&P?R۱'#" u>;rT!&0r (܁|#2)_y ^>|M >3 4wP|r#ʫ\Yn^ z+\t'>p! w=8Rf} 3T|]]P,Wdm|஢?pρ.:q/$C ?P2 0CVom|j9I-}o|36U8CwF>1<({.@G1^=+֜MX} ++xooDS~ :ruV|?`F 92C:/ _~2󂐮a_.~ xo1>ipk+@9i5,/ҾݲPλ Y؇8 fO/0{x׺Ⳣ4|Z|*Ybm"zVDj( `AϞAA?|4VIW]J?ZXLYφ֡C@Yr(܅!"PkE?Pe.`\;ev{R9_.@0Je >@C+VHCTNgƦZw"#^Q|us٣5FaS 1BcS>fJLf>Q+*䩆Dwri`TԺk9BSZq2DSzG.<\J)>@( 3b(5,? JaJ|@E9V&Zlab@i]b1 .`w_>solL`#&@0m_Qe(5(qV rD?-`,|;|pKz<֢lXny&- G/.OD[Hc\P5fl Y&VXo@~X87Yxv8Pu0V4C{ 2 ׄUc`>\є0,Vd̊aG3QcK|v~ @bU^Bu ۚ_tN-! _.iFۥ/9ҫ? _.z C>G/H<7wDۃuC= _uu~ Yd:dEi`cZJ= •k޽YMպ-9Pfn={aZF >lb.92Epm۸Ô21ʻwa}8*yԦ*!O=g+r{D _ԪGH f6`&3_HyFf(ٍ,c(B'RT\ {D NJ&mĶ"BG(Vr[0bK$³x;1ĻVqf^Z{o])iErtb˵Up!kE? SH@GŹ/TE3_hq4Hįd셴cĨdO7cF 1c+)\+m( ɫc׵jyN(¬&ٶK Of-{ * 5P+}ʲtePV՚x|ݗW,_9z_h[  XP%^pO/@JÅ~R[Vh[}NԶXc{V}uNT+5X"`f"`H,逈B)wØ}M j! BI6V|](17L?]{4_>5IsQƌဪ68 d}6e9}eQзa9C=<.id>so8{{ 6< r:{GJ!+rZw$Uc/8<|O\)un'L4+)=\TŸ+4mP!Xu_z~^%QZ? ^3hlX8k_y<r^~7O .TG%KhB\kW"^#5 1~?P~ p{SB@:>xBj[}L|mIE:p F5<\HcN8 F`"s ̌AA;QT`h}Cq`4fShMh9 ž2C@E p Q QBhͿ00CYd $s6`%ZN8Q_ G386F~?&vޟX=qX"ipwj>PXCP&N*8uRo[~F e/DxٺG PD PJQ-QՊWHT4v,K~uT mzAP0i7T`/ wVߧT&Z/fJ֋(Wn#Q 0ԭf2)BD?Ulo qtKW_`R{ 9Yyb CO_xq_> g9۽ 7`_Áï(}^>z'k FxMyތ̶m`&Z+nJ80Ҙ_xQc!ϕfxeܝ4*_. ^`[G‚iQ|J ^*i \a@R݁TDRQeu| Ek]ȇ,l{"-EQ< +ނeNr6i` >[QcDher8bVжCk&ʂ >6x^ Q;uLjn4ЊFyEצBon:Ԝkq *C7N@w b(q-J!eQu>__>P Ʀhe_p#>X Fz, S( !& 44sB0OkiPت0<QrNI0 \2`NP''g8w!0` e9W /`:| X|ș_>( .5@y*^c4< _.Dá_>)_.?{C97p1DJQ| @cƝ,.D" E:4gI]l홑{_`̕E/f+r3wYbsP۾*#DTѻB~G CP8 U}ȡ~ j[P&<|QQ=Y)jPliioPP7]ԍ=|/X(+Y!r̳)ȦDp?,!C"(l:b*Vޢ?B_ Շ"(V++Ȝoω.ҋ;( /K6r@l1 AGWt~>uCQ{DJmQĶm̩B&w;L`L/P /M_{ܟPeaQZ?p8=fi=OPi \0JhY`F uvX'`%2@ +Eyܢ"ѳ;,eg<@g1ۥQ{EΦ@Duq'PxbP ![ -2 T D{@VŌM1>3!@;hv928"xقu~5g|,hief[ rrb)]FxKTfc] R{/gh(=t}fe"#@YMDEg9^Q|us٣5FaS 1BcS>fJLf>QQTTDy\m4QZlt)S:G&:lWN!?~rl2(>{;(9Yi7AE9V&Zl (/Ę, ,`#&@0m_Qe(?k(qĞVQ !?NKX,9^/pkl-J6enoZ٢pe/e%gn^2A9@Ԙgu+d3@?HQ $'`FXpnhq>'pD6nŎ>A3| @d (?LBƶ*BJ0hs;Y+250_C"BXڡI_P.nJ>'bBG6c;am]/ `m=/̹z_&szV2L0}=/T$uvup}#AQs;f1Gu+?kg=PnW(kc1Ī}C{g{:dEi`csfEpeڟ?ZW%Gl֭'9zg;@H#rCl+ۅ"maJ\bJ=/̍z_0qU *MUB=T|h9cmSf)^}KVAJȬz?eђ`^EuYCje*֘ a0X$VQ(BJz rU}$Bxv@ Q+QM e97(9Ŗk<EB&g SH@GŹ/TEQA3_hq4H+Y>AS[VC6gX,jEBڡe!c?[(;:](¬&ٶK Of-{ * 5Pص{/cYXgg՚x|ݗW,_9z_h[}6>WPu^ 2Wxn2U%{H`nYmo`:Q^+}faVž:'eP%`?$*T$" c>L%OrE9R(<v"`c z˦4O>+@q̹ c~Bos*gs/$bq?/eB{ZB fJt&|xa_&ʷ{GJV *fƪQ ]IOL)un'L4+) *Y} i " @T+"*Yyӫ7UhlX8k_9D_2,#KpsQ^{k[BoCLU1juQQ̜:obdWi@!bc[=wߘ"Dxmn]/ bbC3 i hX$6c1(h0* b9n/0cX-}Ug&Jyb(m-@Eg8iT' _P/s(q v(δk vȜ`}Ӣ̺" >/BVwWDطiW-*Pjp<[j 7p9^/p_EPh)>C(cQ)=Je.اM  Qx v.mSkdj biދES3@WDYxIeGw;NpeF sٶd#6N.bN(BE`/#X7@/72A1 s_&0bk,i6Pګ`OSH ښS?/@2Y}gPl}:(Aebi$@(G5Pw0-(@)6T7@wP8:jY¥-(> E-=uXZ!-^[z_&`sq{@nDc<2@/5#cl0dzmLV$q$a1+ȭ.&:Cs+!4ʈF`,x]K {o!mN0Q|J ^*i \a@R݁#iЀUXXV7ʷQPf1e|Vme2<Ds[[BN&-lg+jl[~_Q ږ~bDYp{+{# f;FTk-Z¨1^!?^l9Rsom5 !89;݁3!5n0, 5\qHb@}_!}f>u8aQ.Kw(~ࢉD3 (pE XP`VГ~_Z6`=0J>L!kB?/,'"<~_&tҧ+ ,L+D2,x ?fke3(Q}}#@aF.&DnȘJV视^sgF鷑>/;7(iۣ"Q<@l(F "r͌Rxg/KC.'NB~2E+2gevbN;6G3 ^t2k]ޗx *G~_t_&D+j eEN^ޭ"?{C97p1DJQ|C *h};X\TD*t(hg?نp6ĽC6/k̯_&ɢ,@_egYo;+ \/QAF a6B@ a(gB ~ "c߼9@mʄ?/8ʲ{NB+A!r#yJAA8vP7dc1d1Ϣۦ$#Tpe=IvH ƭbxί ̯VEP=)d#,,{emE% I@Q{DJm^D(aSL6{9vlQ>|y]x5,|b+xm6e/?̀/0x+ib>^C](?p?pef=xz_>pUP*/@H~Q2cO(+26U>pW@D|૎~eջp2@z[&Zbw?@vQ3-"* r$EϷg-N(C0c뮐㽽MR~6:X.)~?`F 92C:/ _BQ k= 0nAb| ,vdP6Qڷ[yw$Z! !8#fO/0JUF>%V[5h- vAw{B ׻0¢;}!(cNXActA|ѥ.0ؘ!~`*# ֡C@Yr(܅!"PkE?Pe.`\;ev:;ħ8z(r4\ei(A~N f]T~Ʀѝ>^Q|us٣5FaS 1BcS>fJLf>Q+*䩆v `%osx9sD9_>-*mf|` /҂ Ĝ/ 1GC|"Q+ "\1}o~`sTױJY Epucm 6vlOyڠ9sf_`?]{+$?Zo0WkH׳;+ @h}a^33 s|`P| ڶ{8L) _.P _>07" _>`u<TP\B[J+*f !<;.CԊ|g^_`Yp" Ertb˵Up!kE? SHc8/(}* |ȋįdbz;MFO7uLHƌ >`뫞!xYQW"k3 ӵ5$0w j-(~V{ x}(u..M|jk^"0nEi> p^(xE*λh2VxzRpT&V_6lػqiYջnb_뜔`C KP_.`,w]a=_a{C@8J10P z00ʖ QsäѵIc^+4(9u]alӊCݡI L=YmMvB5A-Ta(f✽^?8BM/i1\^AJV, c؋y(/த*@Jɭ90 mJ/D%r!ДAQb}yE CD%kQ8/pzxS&n<{uHp+T{_fXZyE{;pրSO/ncO/0sPBQ]Q}hԶ=MPvm11 `X4`F,1Ej w@1 FS`16+hcb`#ů@Ta/@9Lcc5yA i/) *GX *Av`kiC^je 7vώ̺\Y4P\4@9BLY1FḊXc4^+ iIkOz;rAcԫG% /pd@|` _2Ai)9s#J\C\ Y'd9 WI:^bY`sՋj9nSV:1XLt/P>d i9' _@ AecRjrc46v`ܞNcutZoq8>pDqӀ=h,r4W|TͰNg7`sGeOB"`~* 8[DN^'v-V.Ꙓi($aP>&WJ2J^zD%_.@{QOB*OE=[|D̩Jާ;- +Pjy@HÊ4n(P6 V*ܛ߀X ݲ|DPUAuE qgP 3B8_>Es4IAq!#J}ԗ Fh_vޟX=qX"ipwj>PXCP&N*8uy-H4bx_Zy(еG PD PJQ9i9Je{a- irY. 2zaPEBu PA[s*VpD …;bIFQE*3%LH+ێ#Q 0ԭfp Tگ)BQ.]m DiŎ@OVȱȺWd,vG̩*L/ rN/wz(ʲK$qd r=;x蝬*)ϛbٶ DkE <_YGFbSo0j1=LT%]cZ_^{ UX0m OɿK% +Qj;PHt/4` c+6|Lv"Uh{"-EQ< +ނeg 9Y|Uh1Z"n9|`Zw`F1+h[! Je<rާ&`6Q̓Z¨1֋ 0go7QjN ص!'g;q1ƍ2pE!|ksM/zN~!}f>u8aQ󰾁9-c6ABL9\QV!T54(lU_(]`?!-^gW%R=8w4? k(`I+0\+DEYv~v+(fn.s3(Q倊>>0#O{ "bD X8/V4AxDaW\ُ9(6"@r`ANJPj[ :dr͌Rc(G zpӀ_>ᱷuQ q1|3vbN; q!^t4\ZWEy*^c4< pE-x9{(rjn1$`?x|!jWZPA냐ݡM(-e)Td%نp6ĽC6h@ ~#$('>}}-f<#$2<djo($T&΂@lD+ƾy7=K%4Dmʄ8""?;E  -S OTLY|,F9Yt۔Wpd" sאJCPJ>A 0 2sK˒ w1} HEMOuOvlHBώ9Ud5<:$;ϋx뮁P8e0\AkZgfoe;_Pk >U,{3@QoVr\t'>p! w=8Rf} 3T|]v'P,֋K$ pρ.:}$^IP(;'`ǭޅޖ2r.P%ZŌM(Нp m!(8?PQ8_m1^=+֜MX} ++xooDS?xZ(!@fR㽜 x@/f`"y sl>AQx*gYMDEװ J? t˶@1c;D+da0&!?<(\~NUF>%V[5h- V+gU@D va> J^1^J Rzv~?0~`FmˡXX]P|x9rQL4TfTxk إ,*W{vn5'^EN,t PJZ\?BlN4DEtfjlZu'uW%fݜ B`hMQToofm4 4(QTT;|t9\m4s*jݵ! )- "Vt'x/r] xSENH# 3AFT%0%>^-g60z (/Ę, >7"oxE#&@0m_Qe(5(qV rD?-`,|;|pK~{ >WV =G[.\@=|ǻ,0>)[n" 1r1s`V0@mzQ $'`#pnh>/pD6е@ʏ^d9J( )> |)afYȘÎf>0|U^BK MB\i%$>XO/svj9/ )Ur_N _0x>p.s*W\0}*:P Ҩ931Gu+?kg=PnW(7SR16g O뜓A=Ch)3/0 W=LgЊc\~*ZGw$`Y{Ԋ4b 530W EpAmpR&Mucgb4:рm뇟u=*MUBzDu0!W0Z[)Ræ^}K>/Ȭz?eђ`^EuYCj*֘ apXo1WQ(BJz rU}$Bxvo] x*.l:|@kp 0%M/ș_x>PlP.dr !Pc ]hH4:8޻@Tx-ivSlWo)"x-~2P+m( ɫc׵jyN(¬&ys"jL<'@e3Q=\Bڽ̬[Q'@DjMf✽^?8BM/i1\^AJV, c؋y(/த*@Jɭ90 mJ/D%r!ДAQbu -֘WD 2DT(f&Wޫ+D_=x+yyWD*8nwU 8yA 1^M/63/(%*y-1 S~*66N/Nj)(\Qc f O/8ҘNr!Hl0\3cP`U$;4Zs6My?`S=R0TTR`4< QL[ZY2;nXyB4`/:Y9x%ǩW6VTYך+ c3i3|`#AC1/lNc4椵'yBӀgȇ6v3Qz5ਤH4<"u? _@d>fmkX _܇o!0n>Q =O Dpo+PIJfAs܀ \ 1uޣcV(^8D= {PUTОp2hyu3iUH/Pmq{ނg8 iqz={=&©*)O`W_>P%4Q?Y6N+Ců/8*{'`:TiA u"8@0naDpvQϔLC!  xj@`WFKO_.@{QO3Qi5@ 9U)yEuyES /iX \ų]Tyo\B(ZT[B<{ ,(\h8M/Wf!q.!^6!JH /f(Kg@\H0m-cp4cao4wl#'y/x_ei(' `:$E1< <<!"v5B\rߛ(_) X% ZQr9N/e q.\M/*C9XDN+T5"`%/@{,\ (>dU2z1CP´^Dq9xC݊m-"DSņj yGG 0[t%)=k鉬{Ebw i>X r@q{@nDc0l/A߳Cjq^S7#(m֊DxR>$4fD6`b{s%$^9w'#JXQ+-T@h*%D% C1 >& QMYDQ[6 (*sy@$:W/5`/dmVA|hiqŬm(/*M|l1?v~aY%N%q()B`*(r"_.tҧ+ , / 3|@Q]jy݊o3ٵK,L#J9nf~g~ Ș!&CxEΕ5lo#-t/Q /ioPӶGEx­PxE-5jQЋGC,\WO/LsjuU ֺbZ/F@LQ,iENk"zN"K6$`?x|!jWL Td):O PTCAqtنp6_|k A7Br3wYbsP۾*#DTѻB~G CP8 U}ȡ~ j[P&<|QQ=Y)jPliioPP7]ԍ=|/X(+Y!r̳)ȦDp?,!C"(l:[lE0bEP=):uOvlH"nK`N28~rM/I7|ȽO> eytQ>A۶0wS 3(6G`D|=x' 0|ۃ!>JCO(=pDr5"PAu|ޢ"ѻ{,e3Wx{E*聨JG /(Fy!qK n\i9~8nu/J?PT@}3c[rE 6# * r$Eb8|[]rrb)]F KTfc] R꽗@4b~y|aFzfm<96( 4[DŎ\" F׳~ J{/eUH=38 W+ W! {zd/]}R8]$("׺ゟ̙@+>+NF>%V]Z @힃" 5^T kOw[!'|W鋀VIW]J@Hׁힳ*P}ӓ P7|PC.D _,z/o-Ej.?=/|~pJP"@Q%@Y@P[?'oi}CZjvt'(K̺9A@њөد(b}ThlLi5J jBBNe0CK4sZlt)S薭;NPMp%@I!&3⳱gл x J^-g63 (/Ę,؜!,.`_UaZ"4P8?k (qV rD?-`,|;\]债 Cp0W9"`c?/p~{;}Z\ " @9@Ԙgu+dX=E$(Xo@~X,i\Q[p  (kUGВ R}Q;+?h/ Tχ T z_>PPm"D qW5 *ȱx_.Rfdd̶97r}5|@sĜއ 1GM/ A_b]]a(^Fyo޷/KZY=۳ZX` Gߐٞ9YDs129+@~g5U#>4Bk-}J^q/i@vs|`P7PD۶q)eĎZ@SCi tc#v?(}FaTP<{ Yi+rGũҠVH fz60glxsE42E^}ef`^EZ8o!5h+d&z7<9V4 +(Jg(VrP]U1{lV8nba`J_._>p/]]PlP.dr=!Pc ]hH4:8/]P%dxЄįdbz;M}OC:&$QcQi-JW=BH;,<$V#D9_תefڠ.#0w j-(~"c2(u.q/M\@5P+}ʲtePZS/"]4F]h[=XP%^ 8ԇ B?UL-+mL'*s9k~+ag&`i@8IY6ԳlDEQDqt@DڻȧI10P %X~T((g|AtgX@J' cEnW3:۴"PwhgsГl 5j kRJ`(+2F{ݽAJV, '}V@ Q m^(ܕ{BHs=5f!\M偨dQU6!`+ (62!@82 UA|徺2@$ x*߽/Xɂ),"wb^얺(.JA b) c4\m3{Bju(W*R*6(wŔ^bbC3i hX$6c1(h0* b9n@}s1ea,( 2bxaHt7P1'=b%üA^mfpT@h *'+F_>e L5,54qRA}P?ܳ.CRNjg@, lzQmV4 ay X=:`kՙRJ[3PNCHYlUE !(jV)pT>V!Nc`~Q5p0ﭛ iqIlTsK©*)OGY+/4Ua +:W=1(T6" б؀ŦJ– Qpڍ`ZQ8lgJAڛ&WJ2J^zD%߷myFa?cc4Dq]o3DTsS`Q(O aEXx7pE}v@N!ytܾ@e?p rg(*-gpa3J?@ 3\Es4I2W}rDP[qA}ԗ M yAH7b biދEީ+: LT&pt;aZix_ BhE>(е8ﶻ!(~(`ݖ(jEY^+o$*vb|;<`%E˺*Cp6 ^T`9P@T֜8BⳜJbQ\̺QI+v%LH+ێ#Q 0ԭf2)BD?Ulo qtKW[Q|Z#'EӅr'pw i>XrATcwt#ئ00/#M/!Gd )ϛbٶ DkE5J80Ҙ_xQc!ϕfxeܝ4*sK@Us~i0za-VTai(>%g /4ZnwuQj;PHt/4` v"0ӀEUlڞ#jFdE]/Ds[[BN&-lg+jl[>/L(fmK?D}Vi,cGp+_`n`ֺcD 7hEƼkx7q Co7Q8$`6To P7|LDQ\h5hA=/8BR|Bcp,\ La}+sZ;mEfP Z(f?VEı3PLײ6uv %R \|;JQRTP5P|z2>]W`Ѐ\@3\("{*ͥ}N} Q*+XGŒ\3^̩U!.ċ_`u0SPA<r@&(\Q _>=XO/(rjn1$`?x|!jWZPA냐x!-e)T vct!%ZЂ+rŬ B\ bG Sw0|@! 2q,g Dːc{Jiږ+ ?/8""?;E  -S ~oVL|/X(+Y!r̳)ȦDp?,!C"( ƭbxί ̯hp s='lJrVc@.j}=~"ckOF"DE0}v̩B&Oe~! @x?{2WsA1q-G=-g4߭|QF%Pfc/Q5vX?J'>pEO@B_@T$:`pfT|v`0J@^r[E΁>u:^I-(P38n5.<iL(0r>J &&Z*Q7#7p 9As0#/rd6ؒvk8xCDL/ *7{0b)]F U%C"|/Pe>aFfCFpHX\2Iůi9(O>@m%bvV>a/5Mx/0C"FO;xo6N5mz0^x( jmbmD`R}T!50S.,C!(倂Ws̩+h>_qt)F >< >uhi r/awx9rQW`4"\}]ʢrWl~pJPh:Vk,} c!hjixCZjvt'+n}!0{&(tflo12X[OiG=+*jXU4`%ofR1 /e(r@E[6B|[jlVtK#l> _>J)"'A{R pd*C-Xh8C)Fq48} \_gXs3%uo!m{@6pȯ2 J\/'UTEbηrwe\֢lXny&- ǶW~׏%ijip윌D{[B֧d Bkq4:sC aGj}(<|c9k~i@QH>QM9c?`Ŋ⽷?D9$t>v~/q*Vvh@4LC\i%$: r,m]rlۢPr}E/ 4K_> t<|`*:P߄D ksiԜ掙x{yQ]Jώ^=۳ZX` Gߐٞ9YDs1290 W=Mg{k𳚪u[rTװk0{=Vyƻ(c Sm-L.@f7E F> tc#QE/T i3*9-g mR(5mz`&}ްDVAJȬz?ef}*㳆Ԯ*֘ "qcE "BG(Vr[ƻWJo(Cklz^"Z,x;PGS(\[( 2Y1.4p$_Pke*L3_ +Y!`+Y>ASE p1c+)\+m( ɫc׵l/3fmPEջC?vIS1 PLePEj@Yb]Wku_z^x|]}m5m?^_P@JÅ~R[Vh[}NTr"W|ô,Lj\=y_,jZR@ _>!QQ*YRj1'@)4`>F17(l*Ӥc=a{c:L4q@UgVMl~Nz>3g;3_ j id>sW+9,+_>7o%@N+TUc/8ڼQ+ mb֜Pr6D%r! (W\n3(AJ֢q^LNcm  ޗYvY` ?E;pրS۱kdncb3}u>%*y-1 S~*6|L6hbm11 `XGsi0Z# Ƙk`f D5uC;b)0ӘGl1pW DR`4< QL[9` _N;XsXST2Un4`/:Y9x%ǩW6VTY6GRQ\4@9BLY1FḊXc4^+ iIkOzX0oؠ,ȇ6v3QOG% D/ ߩH4\"р Wd݋mkX_^q2w>`Z! D"L>g^Jq:]G\<@, lzQmV4 aj+3ڂ!6D)OR H g8 ؃AhW@ AecRߵ旞*1  0nBQ3|tZoq8>pR{,b_>M _+bO4yE>P ʞ XE@TiA u"pڍ`ZQ8lgJA/4س]%F=mYt^Z`s9P޹a8;FLgZ е;CdNU 0>uiQf]^TBVwWDطiW-*P.O#B ,(\hrg ib_!"R|PǾ6Sz0rq&\AAl990Om qŋ:#PciދE2ߩ9+,< Ae2; [ 8WnH#肄/[" tu58r̫X| A+EDpV+"^y#Q[i-|,K ۼ jBuk EQ 9+yzDk<&p!*tQTD A z1+IQN%EL%XC_*Nt_,B~-1wQ̮+xmc} QK>>0#O{ "bD%_`EIg+pSwrFZR_>7(iۣ"Q<@l(F "r͌Rcx `H8iUM/pxm]B\v~i3^̩U!.ċ:xr*G(pE-_`r"zn/V`sAӽ}V|(>>YRVHo@@1:ېƒw%"}&_LR7]V~uB^.,QAF a6B@ a(gB ~ "c߼9P e^6Aӵ Ch%(~6DN[{4O7(ǮƞLY|,F9Yt۔Wpd" sאJvH<Vj<WBly"(VfXA|{Nmؔ^as d]%z3R+Q!]]ԤOL=~"ckOF"DE0}v̩B&O> :$b|aaS,|b+xm6e/?̀/0x+ib>^C](?p?pef=xz_>pUP*-T$`?(K1̀?P٧\vgvA^򁻊= Wǽ Qfq]x8m|X|-\-U1;q;\PTy@=A&¹xcb c.pD*v_h Vt)?,x?PQB=4y!˯dC)旽Gf`mDi48ɕ PDi~nۧX}SqK FVFyO|Zw|{Pu_>`t[PbZbmDp(PzS.,=ll)rWԋ4VIW]J?ZHρힳ*P}ӓ P7|PX}b`0~"X].eQګwtvO?CpJPhf+P>1 8[E"!-Bc;A:+n}!0{&(t{GkEX[OiG-LZ{WBYhe0CK4s*jݵ! o SZ-8x/r] xSENH# 3AFT+m!@mDM9L4KD1Dd sol}gX^"J-UyXC}o HT\xbη 74S೵(-4![ jg±m𕷟|D=w[n" yrA9@Ԙgu+d}X]E$(Xo@~X87Yxv8P&`?|B&ɘFc`>v PB"cxQc 3\?0VvhޖQP~0 qW3@Tc۲|`mP) _.-@{X\0}*:P Ҩ9fc:V~C _`NI @lٞA1s<‹!3ο,\Y0=[{T7ZGw$`Yp~VyƽsA1) _>m=/Q~!撧~Q6Uyg `CD/ڶVH f6`&0z>/Ȭz?eyf`^EuYCj*֘ apX$`ȇ+P(U;V(VrP]U1{Txv(Ck`6݀_)/½.4|"g9]@*@Q5̢P@)vF#\k (!3_lCVBN/`_u4Y@<` 1!!36MkQZ׊D+C/+Cj=BĘu_`Lݡ 8zۚbg.)B`*8?*CRj@Yb]Wku_z^."@j8_X=Z/q:|C}Rj0.S DݲB+&t {w5.03 zm?P<ίsR 5,?@ vC8|"Q%Q(na*y+j! Bif>C`0ʖ QsäѵIc^+4(9u]alӊCݡI BOVg]l|P UTL#Q} W!? {@%9PY;sO8ڼQ+R61zrkNDC(bQɢ\lH+ e5B[z~^%QZ? ^=Ty* ^]y  ޗYV^^x ({v!7! _>ƞ_>`t@Q^οJE]<@!bc.~{ x1Wk0j Gsi0Z# Ƙk`f D5uC;b)0ӘGl1pW~)  {)E0fS|q?!ߠ4~XyB4`/:Y9x%ǩW6VTY6GRQ\4@9BLY1FḊXc4^+ iIkOzX0orACsw3\A8^ywP-qh4 9= ضſZwxqRABʼnD\ _)N'[?gq/,EYA7`Wf +`}Ug&JyZfID=pӀ=**hO8 A4<:N4*rh(l6=oA 3x8V$p|6*y%@y 0p ( ~1\Mi9_1~l+:W=1(T6" 8gҀ%@i\J28q &özd8j@!&MveQ$J! 4\ 11g8j7"sRN0(_Ұ" ," M [+ 2ge?p @(*-gpa3J?@ 3|8ied 䈠 Hsا[!;B^t܀#'y/x_ei(' `:$E1]X Zz"^BZ00| *ȱ;:P^0/#S!Gd )ϛbٶ DkE <_YGFbSo0j1=LT%]cZ_^{ UX0m OɿK%'*%DBVaaY`(mJ !3 XT5|V8lAFQT@$:W/5`/dmVA|hiqŬm(/*M9 Ԁp+_`ѿ1Ljn M_r (r='?Pr>3: 0ӨyXJBn\4h`(bݸS&WazrXQ(`;UkYpm:;]z(!0@ Y>N%EL%XC_UNt__!r(_1ɻ3ٵK,{ :O8D*+XGŒ\] ~*^t4\ZWEy*^c4< pE-x9{(rjn1$`?x|!jWZPA냐O PTCAنp6ĽC6@/~3f,Ep뻬l19r/Wzg"*]!?#PHz!L *`W}n>xP?s@+ /pETϻE ~w?"=@ZԍcW@ucO&, ># JV,mJ+8iO9 kHP ;$_>Vj<WBlaUYV9ߞ]6qQiiz˒ ~c@.j}=~"ckOF"DE0}v̩B&O~!܁[gP8e0\Ak){g|[Y|NO?`Dy=+ 0 vX/`%+.Dr"PAnQ|"ѷGYʬa>K= MU9Q >` e ?`ǭޅޖ2r.P%ZŌM(Нp 9As3h9Ƌ 2 nla9bh倊fi-hJwIU%C RjsA4b~gj= 0nAb| ,vdP6QZbin S"_~Yٽ`GoԊ>ܷ~ЊϊkEpm =@D va> J^mAXAWK]`(C903r]uhi 7= P|ٙ/?3h5̢2bKYT;kN^) /h] (~N:- i"CзfQ"^Q|us٣5FaS 1Bc" IkO0J>KbaM/ f_4s*jݵ! o SZ-8kw&WN!?Eg Ş{;(9YTc5kE &VDX%"s}ebYsolL`{Պ(^M=fw"4P׌B۷JSU$*_n e1܅_{|{@0W9"`c,|'_~,Q&xO][Hc\P5fl Y&V@" 3] !Gj}ごP(ycׄ R}̇+^`Ŋ⽷?D9$p>p;XN/ۗn#KH} *ho2! #+|`mP) _.-@{X\0}*:P Ҩ931Gu+?z}`ݞP::cU?uɊ wLj!3ο,\Y0=[{Tؒ ei =jE1sA1) _>m=/Qjj(//0qU*MUB;Yi+rG-LsAEsp"b\>J<3 0jak"{r-!k@k̅p )*X$VQ(μP䊹R 0b³׮FV8nba`J_>@3.]}rm(\f(CRh#ht~Aq Ue7 @Tx-ivSlNoTC:&$QcQVR&m( ɫc׵jyBNFf5A϶]RTpT0n!ޥP %o,!z!:> EAyQjw`Ƞ1Rj0.S DݲB+&t2W+}faV}uN%N/HTT$" Z@8Q 0P %Xi<v[0i@ta|k65`%I _1z e&8M+u&}6?'=YmMv_6Bg*tJ`(+FE*yirNGU?60r4v%=PR}=5f!\M储dQU6,b}yE CD%}[uDcmG_y<r^~w,VK+bpsQQ aPA(sxBj[]_h#nZ+~[L55`hr#94-wc503FQECP 1mєiL 6 X8lml+ {)E0fS|y&ހ߶soPhgf?`MyNP4z, 8*ig p D /pƆh@r LM^u/m?JY5\!0n>Q =V½8 YRNz?" 8{[!aj Ac:3QӽCikqiip8-=0eg8 *`R_aC1y j4`>[7N'Q{- H< ؃8ʂN1\Mi9_1j3yE3`7__pTDO*t,6gҀ%@ԩ+Epk7a:jE)Be(sZ¹2J^zD%m /s(q v(δk vȜ`}Ӣ̺" 婆4H 5oӮi[8`U½ 8]-G5PTXQp_EPh)>C(cQ)=JJhq&\4m-cp4cao4`^R?*tQc54E"x|+: LT&pt6&4̹RJ\0!8/@>[W\r [JQ_~QZ( {Dn9\PLÜo ̲ rZ:{*T E iE+*hkNEJ.W e傱u-/ F/콿|Ԋ*,6mŧlᥒBV ((ME$: C1 >& Q*=GԖ"( z_Dʳ`ӷ셜,MZ*4V-Z`_>Q ږ~bDYp{+{>W\+;uLjn4ЊFyEצBon:Ԝkq *C7N@w b(qe>&" (Bh5he_p#>X FV洌!v$!& 4|%`B>Q~ZKVE"όB{ 0 \ڀCl3D ԇ)BO.>N%q()B`*(r"_.tҧ+ , / 3|@QO /Q̮-\dQ{&yz%?P\Z>frquB66/7(Տ3`EIg+pSw mE.t /}B=*n φbt+ -o(9H/r@i : X ovpxm]B\L/<|9g*ąxrk]ޗx*GP:L/d_>ȩ˻U\to(`.2ۀ dW >*HCQMh;FgQXk٠@Zp?`~e3QNKwYbs^! zϺ_. 25zWȷb*gB ~ "c߼鞥D eenŝφqjpZ&*G!{>O`%+Dy~_M~*X8\CrAab*VJ>A 0 2sK˒ w1} HEMOuOvlHBώ9Ud5<:$o 7|#2Da(Fn|ԧ< ~?`qW||܆z(/((B;Jw\ !TP]/(.H^(K̀/?`5J{X|T[E_=uz_I|H(Px38nu/<|n\P,*7`o(@ԇ!@;hvqE\Dcj[=+ߵ(2Vk\w\w-hJ} PQB>4!{9DC) _TD-" bmr%Ƞ>'-Qڻ|-JKŌ;}_`0:2܇'.;.V|VT }vJ»Z;h\.G%_  vat.pE 傂Ws̩+譒8f2u`f5{mˡgņr(/_3h̢bKYT;rgw'^Ea@YB(is IYIA7m}+n}!0{&(t36fb}t.:>kvAz`.x`^(Q傊Zw-G6B|[jlVtK#<@( 3bϠw(UB0^b^-g63 (/Ę,xbN{csdwr\MI=#D~EipQ(qѥ**"i e1 /}`|e2uc7AlQ8߻,a-WwHcn j3غL*Y $'`?# 87YҸv8P&`?}\@ʏ A2E!GW4=},{osH|v xy@fj@4LbD9_v_.m[sn)jviM/9+>Pb_ *:P Ҩ93󘣺w.{(}g+7*bՏ!B@9'+H{#]•k?{k𳚪u[rT׵}ljE1i|b92EpM/DS_q؈Q5 jSh~vo0!W_.ڶVH fz60glxz/A$z PL#^FEK 1W [{ !ؓUg ]U1F^!3{ȱI@ȇ+P(\17z@a"ZM  w{SrE{b˵Up!E SH@GŹ/TEQAhq4Hįdbz;MP A؞lVi6^V{1Z awt[`aV~[Z Ql%EL'@e3Q=\BJ>eYB:2C(Ju5/=AY+VK\/p/@JÅ~R[Vh[}NTr"W|ô,L^y_,YR_@ vyco\`vg EG%@)yb]x~@1Dq]4?>+@q̹ cp@u1jm@ sgsГl 56@-T߫+*F8gb  lB /}do/rڝ9@1j;pրP&yz:rw =\`ԡ|D%%aJ/B~=_h#n2Z2+<<0j Gsi0Z# Ƙk`f7("QMݡ(h4"60Rѫ@Z@9LcX ߠ4q ֔ #fz mHb^46nHcNZ{қ'4 q" DqՀv_ ߩH "_.F_>e `傹A=/hEۭGs'z_(s4P厯uIJjVavz_p%`ư >֪3~^:LPQA{aʠe)pT>V!0 /pn9"(8y?$4fD6`b{s%$^(St /kq~i0za-VTai(>%g /4Zn Fk8 Xeu| Ek]lQ[6 (*sy@$:Wί%VBN&-lg+jl[>/L(fmK?D}Vi,cGPsֱܠNQc^ѵiЛ츆𷛎(5'q\B񍓳8?J\FC8ʢ[pwD-Ҡ!}f>u8aQ.Kw(~BL9\QV!TPت2@D)쾺C)ikY_>`NP''g8w!0tvh(>=L'},B /(ʂK= n7ͥ}N{&׽L~8DT1Wxzߛtll^oQ#j/* wG7(J:[VxEΕ4跑|Q(pk ~6#3DN@-o(9H/_΋=\NC,\rE+rgvg⽇S<TֺbZ/F<=Ͼ@pE-x`=\w0c ~8W@JQ|C w@wEi)+$ O7M9,#w܏y$Ҡ@Zp?`~e3QN}f.+?[̺y |%2 djo($2q,g ]1ͻCAԶ\LQQ=Y)jPliioPP7]ԍ=|/X(+Y!r̳)ȦDp?,!C"( ƭbxί unI,݉{vWںoTBly"(VfXA|{Nmؔ^a_@YcϮa}Epz6ejD Q u>;rT!&0r( @>ku@(C\u\Ao>|M dfoe;_Pk >ɫ\Y@QoVr=/BO}*W(BT*"}{pfH]]P,!t9Q >` 0~ ![ -e\J Fz'8n {*8CwF>1<({.@G1^/z/4~%o-v㓫:] BBB@4Klt;`]?$C RjL%J18>񂐮a_.~ xo1>qpk+@9i5,/ҾݲPλ Y؇8 fO/u[hE/g*|D9oJw`*؅Ew"򁂒Ws̩+h.T]J?  0#l[6^mDEbC9 "P 8CD0~"X].eQګwt8z(r4\avʢBI띋}Vih>@mEo(>zE]by"f ;m]X*6Sb6>>`ϪQ_>a:`.x`__>PQfP~KMMwB?Պnwy{L(B~/rDg ŞANۜ,@eQx䊖s{M!ؔꁈ8} V{< az;b~*@<>@%k}AFj,|;|pKzQMc/0bEbf8_C"<\r@n!VߵĕV_]B\QAR{j9/ )Ur- _0.-@{X\0}*":P 931Gu+}w>0PnB*αbՏ!뽳=is"81ber3/0 W=Lgx`ZsVl֭'xO_^8q?P+∁̌^ /&[֍ clD|yT6Uy` #h9cB )M3 @i9\u4Y@<` 1!!36͵" !ˊZ}1x|]1n!YmMPk1D1ٶK Of-{ *" 5P+}ʲtePZT) ;\!QQ_>P)ΒO(na*y7XA)yb]x~@1Dqy_.`1zj̡$T8\v1c8M+u&}6?'=YmMv_6Bgأ I3Gqu{ 6< r:{GJV *fƪQ _>]I'T.: Г[s `FB۔_.Jz_eC)mZ1S=?dd-PNohrc󁍈hWD:(☓֞ Mvȇ6v3Rz5ਤN@@T gl_>0/` 4eŹw~ja9{Leܹl!.j,܋2x!tһyX\ڬ hr+3ڂ!Zuf{) t^$ qp3AUQA{aʠ)pT>V! 0L/8FCacbqӀo| :pIm!?J={=SUDSAe֯<|? )M/"S1'f^鼢yEscG'B"`&M-AN]Q~/b|N5 a:jE)Be(s(ObDғ *ن0r;74<#řVtS̽OwZYW|By!+»+>طiW-*P.O/ì=$@_(\h8M/_q!}?l~OPL/9}`$>9"(8y?n9\PÜo ̲ rZ:{@/4"rZ: 9+yx"fBU@$?QE*3%Lňt$bD9nK|f2)BD?Ulo qtr!>" 9Y}95UQA'ޏ8bLHc0l/AwZ`dה ,<_m֊HxSYGFbSo0j1=qťf`=`I X_.`"g,x݊ok 79YGD_2$?P\Z>f}oұyA|= ۖ&QfV视^se /H]J_1:m{TD'ɪ"jM-I-j= %!qP W!?4|C[:* ^܀3v/D3>] ~*^t4\ZW/(0BL/(6B:L/d_>ȩ˻U\+azJ;P+R)ch@BVt >*CQMYh;FgQXk٠@Zp?`)'>}}n#7% ~"` *]!?#PHz! e,Xdhh!b9ږ+ /pETϻE &;E Ɇik)u@ؓ {bDX ׿"t" s')ĸU5J-o_*,+Ȝoϩ ҋ;(qY.bώ>v EM4:'BPj;d$BT|Bώ9Udi/3\@I7|~O1(C\u\Ak){3Cwe;_Pk >ɫ\Y@QoVr=/BO}*W(BT*"}{pfH]]P,WdwSw{tA{%O6(~2 0CVokr.P%#ZŌMO;#!(8?PQ8#/rdxE?^o-v㓫:] BBB@4Klt;]R@`~r d)u^ _BxAH0{P /`V?Fq88ɕ PDi~nVZ(fli,CRÄ3{xZ Z:M/0^x+3zc>Y׳x > va:AA?|s\}Hѥ\f#2s`pf3mˡ~bTa~?"PE1^} Pe.`\;evծPhF(E+;["Qz}, AߚQ|9Ĭ~D v:ۺk3>::=u3J@zbċBZr+-X8!ؔꁈ8{Y18yk1ZimGLEqpP{[E%P`pŲM/ He2uc7AH(=|ǻ,0C.`-W1wY.(3 ~`nA%f7 ? ,q< P&`?|B&Gc`>\є0,bZutGi =jE1q 1D"Ѷ^r^$tKWԺ3Qra}8*ydE #hLVZf>H%Z(жBJm0?afmZ K@1zQ Xgfq\-l5P`O[WRT\ {H@MڈmE>\ RYXsC_oaTJo}X U\tbᴢ,w8f Ertb˵Up!P@)1XFP.>4:`*VBN/`_S:qvrߍ,:&$Qc{gSVD pV{1Z5dKZ׌rAdLڇ̇ T=0RGж 0me] 0L,up_,jXRrDEq@E8K: >ڻȧI10P %Xi<v?ٲ!c+Fr԰Pcm'1c_9ԷC%PwhҲNz>2l|P UT#Qb]?8BM/qr:{GJ!+rڝ9@1je*T{_fX}dIwn({v!7! _>ƞ_>`ԡ|?JvE R*6xLL|BwŔ^bbC3 q hX$6c1(hUD;4Zs6My?`S=S)F_@i{)E0fS|yA q/AyB4`/:Y9xр{v`ֵbG}s1ea,( 2bxat7P1'=b%üa",^ 8*Pf@162/ _@ р,/&L|` _6qЃ .!.j,܋2x!tһZK IJfAs܀ \ 1uޣcV)^} ɢ_*@a洗TTОp2hyu3qUH/Pmq[b4`>޺@t:-η[/0[gpHqӀ=h,r4Wb*Fdٌ+:Wt:crlOX^\J– QS1> 8q Fözd omhՀ$FT/= m /sOOs1bY3[|D̩Jg(qTBVāwW|5oӮi[8`U½ 8]^̇Yj 7p9N/ 4`*}e@KB!~_>Es4I2W}rDP[q~9LyӀT!/:n|#0cHE!LX&pt;aZq_6@Њ}@>[W\rߛ(QZ( [N/0,!.]P+Ae8:i7T`/ wVߧD!L^0#Rܯl;b(G5P Y XG`Hm9 i5nՖ@WDB~uIȱȺWd,vG[/`NMUa@Tcwt9۽ 7`_G6!Gd )ϛ'm֊HxSYGFbSo0j1=T%]cZ_^{ UX0m OɿlᥒBV Ojڽ)HBVaaY`(>F"`Cњd!*['ڲQ<Ds[[BN&-lD5FKV6-LO ږ~DafWB9FTS  ZsV0j+6z0vIIqנ2P|t>N ׸Qc"(:/pM/(Z3_6G9B@j@hskaq<˒9 "h"9\QVX|+>1i / [;6`Z4߯J}B QLVx;J ~S:V40\OW , / 3|@Q]jyn7ٵK,L{Q8?}}#@aF.&'Տ3`EI'S~jXn!8W.3cٗ(`wr7(iۣ"R-um=!*!4|ZԢ#~9/^?y&{؋9Ń Oŋ Xj y-*GP:L/d_>ȩ˻U\+azJ;P+R)ch@BVt p|rT!Z{ ++xooDSF ".xc@fR}@/f2Cq|o1Nqp;r2j_rx(k1iTH>ՊU>a/&Vx{V$+NF>%VZ@k1Ѷ{"0t>*0`A=AA~R'eWN!?9 "3!O(u-%XAh9jDMyM&8645y؜!|-`#&@0m2J\"Rq%wKX,9>/p@}LdkQZB}e̕}_|eyHlv8?vN=[!j(8>azýk0Aq7V&}x_l4} b?__$c!PR}pES~e"cxQc s ߯!`~_ tܾtk!ĕV_]BQA jy`m /̹_s=8@e?j`_ CjAQs;fZx]&z`ݞT(kc1Ī}C{g{:dEq`csf3,\Y5໷6ZGw$`볖{|k@#^33s|`P@>aJ\'55_5<`u< PAm d `CT_ڶVH 'umz`&a/"LP#^GXbZk\ RXc.jC 9V4 +O(μP䊹R m[1{l6V8>/xh-{;lLI9ߥ-WAؖ[u͢'P@)vF#\ @'!3_lCVB>/`{_&S:qvrߍ, o0또DDզ(kEBڡs{1ZuLawt['¬&l%EL'@e3R=\4@P(K(Juv} \^.?ж6>+VK\>/p?/@JÅ~R[Vh[}NTr"L+R03 >P<ίsR u- !QQ|_gI'R{70< ՛ Jn4`/:Y9x%ǩW6VTYך+ ꣟(G) >f9@1؈hk xEظ"9iI 򡹍^ 8*igeN@@T2 %NV4\e L@qn062tZX0S||RAB"L3^H8*g1X\ڬ h2+3p(Zuf{) T q[AUQA{aʠe)pT>V!0[7D|[}lTsK©*")OGY+?/2ѥ \Ua +:V_pTDO*t, B`SaKSWԩ1S`ZQ8lgJơA^We(a P m{P޹'q v)δk vȜ@8(q_&",}v@NI-G5PTXQ8=/Wf!±O)=J.اM*#iI}ԗ M yAH7b biދErߩy"XCP&N,8uy-H8bx\/ BhE>Ok pe7QS) }19-Gi,b/7"2@1s}_0lT mzAP<:i7T``_/ wVߧd4SQ(aZ/FJDLjyT u+LOet<ݗ'iŎ@OVȱBZ0<}_.~۔fFqd=;xp=/Źi`;Ԭ# #YAnu1ҩ75vb\ `ƁWF|@JƂ׵84p; XӦok&[xr@%Gx /*78`Q [߿p~Ey.4H](bNr٤BHh6AD_- M"DQ\/x%`/cD>5;uLjn4ЊFyEצy`傚xvm8Ae|A %qD!eQu>_z_(Z3_eG9B@j@hs=GV洌!V-&\4h`(u|Ue0Bײ<\`N> ԇ)sMe$ k(/*0 RX|y_PozɺJ`~bvm>'=f}oұyA|Q8CnPt"G?5~7= (mE.et]/}B=*"n dC1:Nӷl'9H/r@i : X W8=Ŝ}]Bez_<1z#p/P: \ Q+R)ch@BVt>PAqo;FgQX9@Zp?`)'>}}v |Wb>\XP?R۱'#0}v̩B&Oe&tw S,|'W森s3,>p x u'0>y2{yn^ z+\t'>p! 债=8Rf} 3T$ ..(+26U>pW@DW/$$|(~2 0C Pom|j9I-bަ'НxlzG(i9Ƌ 2 ^b>Z'Wu@Y xdrrb)]d]'!@fR㽜 x@/3WɻvK{񁈃L}"T 86 *$]`~V>a/&VYw|{V$+N}vJ·ZkEƃ1YU<PCnLztpE %oS/VX%]!o?ec}3e`F>Bl[6^mEbC9 "+x=H2Y!8^Zv)^]v `_>p > X{R9_.@ {-dLEsih>@M+4;D}.1GkNm.H*D MX)1xFiZ_osx_>PQfP~KMMwB?Պnwy70O/p IqĞ{;O8os!D 3Lh9jDM9L86K40a'Ͻ9C`#&@0m2}9UEKXs_>]A=֢tŞ-`sE_>]ݡz+9#(3 nX]E$O $'`#pnh>/p|Bm/6t< %/P~ /$c!PR}pES ̲wY.aG3fH| kH z_/-27ZG>sD95'# `m!|z[r#~.f1Y }*CQ&~oaHή Wkv"\1#}o~`sTױ0ws,B!ؽ=ib>x#C-gYta:{}ZGw$`Yp~VyǽsA1) _>m=/q؈(׍PAm d `CTm2OZ0glx>oX"Hqd֋rJ<3 0jak"{r-H֐5|5h+dF7\9V4 +O(BJz 㸷.P"Vr-yvo] (Φe97O(rޥ[-(P@)vF#\k OB&g؆&d_.7< u4Y@<` 1!!36͵" !ƫߏll_תf ;D?f5(Bꈀ |+3R=\BJ>eYB:2C(Ju Wkx^x|]}m5l/`}W@kFt 2&CJÅ~R[Vh[}NTr"Le9(EckQ&`:뜔`C KP_.`,w]a=_a{C@8JOd`PvA17L?]{4_>Z"s 8\v1c8M+u&}6?'=YmMv_6W PP|@U 829{7=py`_c߽#@%{+~ Uc/8<|O\)un'4+)=\,ʆ8BSE-Xcz~^%QZ? ^=Tyc{u偈p2*߽/X,C띛$EF8}kA b)ph9u(}!DO0%bc./p7py?^Ly-&Fk04$8Nr!Hl0\3cP'TSwhCq`4fShM4ԫG% /pd@@T gl_>0/hqxI0l[_k\4ЊJ6@:'p/N$s@TI:$"^Tqv_.p%`ưn3XΌt/P>d/ 0sK **7 ؃n`@ AecRjrc46v`ܞp0zo| :{d[NU)Ny /p[b_.0r+R1~l{E1ϝ'zV!oqdҀ%@ԩ+Ep©F?[X0R(]3%PH~àlEC}UYJcsX|D%m7#}&X-OO3Ri5@ 9U)qHQnTBVāwW|5oӮi[8hB![j 7p*,oh9 ž2C@E }?l~OPL/9}`$>9"(8y?`/z;څ]g.Vx@! apwj>P( OC@8L ;N:@G e+@Њ}@>[W9[5\Ŝ"PBE`/#X( {Hn9\PÜo ̲69[!Qc/z&`@T֜<\p!*t"֋bDDPl3l! ?1v+4`Vw_. ħ;qR>]X Zz"^BZ00| *ȱ;:P^0/#B`D02vkC7^60#b7R>$8fH6`b{s%$^O*sK@cc`BoZQӦ ^*i \a@%Gx c+6|Lv"UpbDm(DQA "R Y3BN_sVA$[QcD@u'fmK?|b_.s{# f;FpV0j+6\_97`6To P7|LDQ\@kr=VG9B@j@hskaq<˒9-c6AB9\QV!TOkiPت0<Fv_!,4߯J}B QLVk$~GISA Ppr>]A*0\+DEYv&Z+ٵK,L(r@E334`53݀_ >Q~! wG7!VxEΕ5l̘x%!6scHe_ +>Є\k"jM-Ikzax~J[8iU /ۺ(~_>y;r{{1f_W'q @=YZ5F _>@0\: WԂk"zn/V`sAӽ}~NP+R)ch@BVt >*CQMYh;FgQXk^@Zp?`)'>}}n#7TY!LP?R۱'#0}v̩B&O&t@>뮁P8e0?;ʿmQW˹@LVw~[Y|NO?`|*e=@QoVr\t'>p! w=8Rf} 3T$ ..(Хv''肨Ju?!AebL>p T H$~rA1coSG}<G 6#T4ƋE^OlܰU.P`] 뮐㽽MR&,x?P{h!BJr.R/ k=h)αEaЇ@Yֳݸ2j_r(xO4t}4ۧ:E߇8 0CyԊ>d>C@iѵn9@UVk Zs| > va> J^1^J Rqt) o?ec}3e`F>Bl[6^mEbC9 "+x=H2Y!8^Zv)^]v `C|}pW "g(dL`3["Qz}, AߚQ|9Ĭ~D v:ۺk3>*4  ⰙZ4\Zl_H%Z>ei-mROj~Y?cyAD "g"@j8_X=Z׌rAdLڇ̇ T=0RGж 0lEWag&`i[ž:'ePÒ` ?$**"Y c>L%O~r&+(<tw],˯S-8Ik \ [{b{ǜ:ݮ0f TuiEФ' ._>P1P|@U 829{7=py`_c߽#@%{+~ Uc/8<|O\)un'4+)=\,ʆ8p^QskT+"*YyӫǛ*0Ҋ:D*Օ"RN}T|"`%/O~?D*o)D#5 1{-_-Mnc۱r@(}!DO0%bc./p7py?^Ly-&Fk04yǜp;Eb1v?QECP 1ǭfShMf9@1؈hk xEظ"9iIo+ TEn`FꩲXf@162/ _@ р,/&L|87:]-,gl}>>)s `>(s4PTI:^bY`sՋj9nSV pf "PF_pE*bO8yE>PpT {`TiA u"8T-V.Ꙓq($aP>,9~J۶h~~`hLv`g̩JTCw='_",}v@NoYb>*PUAuE qgSQ+3TZ '%.اM*#؊s s汏R87D0/A\8A,{8^;5HE!LX&pt;aZq_6@Њ}@>[W!zKgTm(VE^- qrY&g 2W8n 9XDN+T5"`%/@{,\ (>'Aebi_1xC݊m-"Dӽ~'n!BQ#}|VItak鉬{Ebw i>X–[eqq{@nHc0l/A߳Cr) YZ֊HxSYGFbSo0j1=\'S% 10z]G‚iQ|J d /4Zn ~R݁#iЀU؆C1 >& Q* P1lA~ υZ_8}k^g "ي%}l8ĬmOp_mr!fW}DT\+;uLjn4ЊFyEצk7fqHm5 !89;݁Tplou7rD ru7Zl_p#>X Gz, 2ؑl.H40}WU~bݸS&Wa@|R}uSײ /|zOB(a Г|GI3Y>N%EL%XC_UNtr9eTLxnyͥ}N{&׽L?{q`sExzߛtll^o(FT?b%MDjE~jXn!8WAХwt 2Mc uO5 :WDZN߲Ԣ#/$@i : X {[ů8#O/`_<=Ŝ}]BhXKThy#p( 2RGZr` /P\*c.H~7yEi0DH(>>Y,.D"E:bslC8J@h@ ~#$)'>}}n#7% zd]X *]!?#PH7YVAbw##\Lx,z/1Y)jPL6DN[{4O7>"5= Y|,F9Yt۔D*8iO9 kHP ;$_>Vj<f*!0Z*49;dηDMV,eػ8IM} HEMOuOvlH:L9sky:$0e22Da(~ ܶOy@L?`qW||܆zOn%_Pfc/o〺;Jw\ !TP]/(.^(K̀/H]=P,Wdn\/΁:$>p$P'Px3ķx'?pL.(_wOy@@?q!] z_vK}qX\2Iůg9@ֵ} IGX}S}_`0:2?O\Yw\| ANMFqh- כKQI`׽]Xt++BP/cNXAo@RvׁC/6 r/kwx9rQ""-zfTxykإ,*W{v7>C 8z(r<g2&9~봈CTNgƶ"CkƦu>wY7>=Z't36fb}Thl=:@a3]`ת;\a:|\m8Df@E#A!>-5p6} T+\`_p%@C} =) zwpd*CKXh8C)Gq48} \_gVp'Ͻ9CY2]ZwGL9aZ"SQe(5Х**"%,ŜoAw̙u_+֢tŞHøl/~\`v}R$\ "1r1s`V3z@dݗ`zýk0Aq7V&{>p|Bm/6=r(? &Gc`>\є.N9"cxQc <߯!`v !^[GE[dQArAaok_.m[sn)jviM/9+>Pb_ *":P 93󘣺޻^=۳ Epͦ 0Xoz @9'+{#Rf?`?]~[^k j rO?^q/q@kf]y 5\mےÔ2OclDr׍_@ @~g4[ |ȑJQB )M^}K^/Ȭz?eђ`^Eu!5h6ЪcE6b[W|BG(Vr[0bK$³Ôb{̦^Zo=)i"g6[(\9a[nP&3@5EH s_O{Dg> -VB/`_S:qvrߍ, o0또DD}XIZivheEYxH^Gs >jM<`>\!:eWMDe.g{-T">0K{'COT+>)j{Ll;<8Lwo(G ՛ J{~blAoPs^1k?\+yObHcEnW3:۴"PwhgsГl 56ULNqd>sW+W6'T?^AJV,n`]+e4v%PyR.[s `FB۔~_Jz_eC)mZ1S=?dd-PN46,5T~?DP}EJ~_`i%T޹OQa؏S۱k'O̜:'QlqfKPcb`8 / p F5<`@Pci5( 2bxa Qsmf8jQI;^#qTz-N@@T!r gl4`h@ߕ L8u^ $Lh5,xz=/hEۭ'tNp qQ+d^H, uIJfAs܀\ 1Y(Zuf{) t^$ qp3AUQA{aʠe)pT>V!0 /prU(NusAt:-η[/0[gP8UE8i\( ~bx_4|Q?Y6N+CK9Er'B"`&M-AN]Q/b\ @0naHpvQϔC!  xj@`lopRm=/sOO3Ri5@ 9U)yEuy'z_",E7 Pq['ZŴOx1fVU\Y0 p_>`*}e@KB!~d/IHCcX6I@2gSKh&h ~rUX8A,{8^;5T"P&N,8uy-H8bx&\= 9+yx"fBU@$?QE*3%Lň+ێ#Q 0ԭf2)BD?Ulo qtr!>" 9Y}95U* h_;Ywq{@nHc0l4\g/5#cl0dzmVDJ80_#xQc!ϕfxeܝ8*_ ^`[G‚iQ|J d /4Zn ~RSMI%pD: _D1 >& QMYDQEy.4Hʳ`ӷ셜,MZ*4d+jl[>/LO ږ~Z WB9FTG/l070k JLv* MX Gz, E\4h`qBLUe0 ey9oOB(UA r' ,'<|W<HM-oOjQs^AA/upC{[ů xbN HS񢣧Xj y-*G_.t_H+j\}\ 0 O;R&@ɸSt^HAġBvv]lmHGicIA/~3Le3RN}f.+-fATѻB~G CPp2qTAb(KP?s-W(~_.pETϻE &;E Ɇik)-jqP|`%+Dy6% l@Sa1T) b*VL%VFX{`9%`SzqI+b\l [of*/ &ݧ\:'BPj;d$BT|Bώ9Ud5 dȿ1O(CtY8f'mdfweq7?Pm\Ve>2+>?+ >}|B{₊HY dۥQ{Em\/΁:$>p$P'Px3ķx9uL.(Oy@@?q4!{9DC) lz >%"g6dP߂?@'_ t˶@1c;H+da0z&!? O~|o~@+UkW]/Xwvz\Y׵ >RWT ypE 傂Ws̩+譒Tf2C/6^oa"Yr(iQ&3"[=.kfqA4v/ >C 8kݫ]PyF(E+=Qe35 X5$rwY7>=Z'tjsAfmT㰙kvAz`.x`^OZlߟ l VtK#<@( 3bCPB0^b^-g63 ڴ.1πvN{cs;#ZwGL9aZ"S,@.{[E%P`pŲrwHe2uc7AH(\] Piruw/8?vN=[!&V@f7 ?kku6Adb O)P(yk~q@QH>QMyc0rey ;} 1<߯!`_u@}i!;B+HQAr8_^YNz!|z[r#~.f1Y }*Cq,"~oaHή 9xD5繾cFz`sTױ0{낹w{R`NI @lٞA1s<‹!5,\Y36Z;u>p^P+∁܇߅pL\Ѷl>)erM/qmw0YGY6Uy`R0!G*rGM/m2OZ0glx>oX"Hqd֋rH\30jak"{rߺ H֐\Psa42#+ۊ| >@+憾8[X(R+v+>^xr,w8f E{b~1Y+ 2(2jL!6 FP.. z|}`vy2J)CДrE%oFE*8cBB5fla%kEBڡW# L%O~r&+(l{l1L/L`X@q~F?5lӊCݡI BOVg]j 56@-T߫+*G8g{oXz`_cy߽#@%9PY;ƪQ ~_.த*@JQ:?yf!\M偨dQo Ĝ "[hL"J!@82# ` "** '#Lw,V2K+V1@(}v!7! _.r ̜:'QlqfKPcb`8 / p F5z[q h򴁙1(hUD;4Z!m03XA{# -R0TTR`8< !`?/yAq/&(T2U;V'+0O8j֊ =;B0Zse>@}s1ea,( 2bxa!*1Ab q" HqՀv_ TDD=/pƆ рY$ sAHm?JY}_ZTABʼnD|Jq:]GxHE 6W6+0P ʞ XyŦJ– QS1.S`ZQ8lgJơA/|7P: *m`;o9g~~`hLv`grqHQnTBVāwW|5oӮi[8hB![j 7p*,oh@(}e@KB!~_.9}`$>9"(8y?}&PD PL(`ݖ(jEY^+oD*vb|;<`%E˺*Cp6 ^T`9P@T֜<p!_&,Y*BPp2~esD< GL4`Vw_. ħ;qR>]X Zz"^1sw i>XrATcwt@q{@nHc0l4\g/^5;5y3Rdm3Z)v`*5HˆcV[]tj F >WBqsw2☪- {o! MD)70-T@h*I-vJcSN6 &ʷQPk]lڞ#jF' \hΕgo o 9Y|UhV-Z`|_.pIO ږ~Z 1z_`n`ֺcD 7hEcOjN ص]bcdqrv'gC@k(1aGYr =VG9B@j@hskaq<˒9-c6AࢉD3(pE XP'f?V;6`4߯J}B QLVk$~GISA P_>_tҧ+H_`"g@Q]e&'fn.s3O*q;m&bD X8;<q?8԰+Bp.3crRz?]Wkz_.ӷl'=0U(mP W!?\ᱷuQ q1\y]=uU~Ku,-SPA<r@F(\Q _>=XO/(rjn1$`?x|!jE*Ey -A `q'REq(С8K:bslC8JKb=/ z s f*r3wYl19r(m_I@e"*]!?#PHz!L lD+ƾy7r"5= Y|,F9Yt۔D*8iO9 kHP ;$~_.qX5k3[}-b)4?eeػ_>} HqEA"١|R({EƦo};@x%Wa(|@i(|m ver@[&<-booq;|r>f!@;hvqE\Hchh[=+֜M<\rrH)]d^T]'!<!{9R/^{g6COCX"8[DJA}NZ(~ Qڱ|-JKŌ;"}_j^`0:?\OoHVTkrp6h- V+aUqA|B 40S.,=AA/cNXAsHѥ4>`(C@)3"`:rh5VP$+6C= A1^\aw#-fTxkKyY݋dvgw'^E^La+ !QP>1 8[Efjl,2VhlZcoW%fݜ B`hMө1BcS>fJf>QQTTKQ8Lq.`*jݵ! pwC~R㈳x(B~/rDg ŞANۜ,@eQLS-Xh8C)צ}w T`w_76gOKX }G/<7wHۃc:V&;z0PnB*αbB@9'+{#Rfl,\Y4m0]dsVM5?^8qq@kf.|  TѶmCaJ7֍ @0ضwEaTPH%Z8ԂV=BJm0?i{~6gWD82En$`Y~`^Eu!k95h6ЪcE6b[W|BG(Vr[08Bxvo}@ 1U|)E, ιY|B/ ƥ-d(\0k@5EHOj'㽋3_ 8JVX&>@L%!h}78xz<cBB5fla%BH;bd<׵jNOYmMPk1D1ٶK Of-{ *" 5P+}ʲtePZT:Gmi|zW9C_>)}P6`nYmo`:Q^0HTo"| l: ZIQ>)a&T)ΒO(na*y7aJ|؂ޠ8IѵIVr?iPsfO:۴"PwhgsГlʢorzy]rqd>so8{{ /q/@w/P d%@N+Tj`@8:^46ncNZ{қ'4 q{!|hnc70#ũWJ_>A8_v:QA(!"LY|A怐0ض+g~hEۭ'tNp qѧZŁ| "ܑJq:]G\<@, lzQmV4 aj+3{t >֪3#_8FCacy j4`>&0@t:-η?lTro@T0p Sq[{}8L ?QMGE*HTɲGk!*~?w"ʞ XE@߲Al4 l u:xN8(q Fözd omh&WJcsX|D%m`xSg熟11g8j7"s:bRElSM/qX \ @բzW(踭BU-bڧ[ݽ B TA.4G934EPh)>C(>\'{لOBh9{,2W9J0m$Z>Kh&h ~rUȋpz4E"xP( OC@8LmJMq?# BhE>Ok p.ߛ(QZ( {Hn /(aη,!.]P+Ae8:i7T_>`.DK.f̺Tʄ۔4+ێ#Q 0ԭf2)BD?Ulo qtr!>j)c-=uȘ;jt`NMU_ rKNo:/܀~aو_A߳Cjq^S7#Of60#b7R>$8fH6`b{s%$^9w'#JXQ+`ڴA3K% +bw?6IJTTa ǨWl5.CTCS=GԖ"O< "+ނeNr6i` 1Z"n9- Je<r_`n`ֺcD 7hEƼkx7q Co7ԜkNit>N JNFnHQAN\_~ !GH3}p- 0>wY0e #&\4h`(5lPت0\Fv_!,KsWI>L!zrq(i& A+J`>]A*0|W9@Q]jn7ٵK,L(Ҡ|(ȿm&дk(FT?û%O "ʚ_~FZRZ0mj/ioPӶGEx­l(F߅O"r5P(mP W!?4ᱷuQ q/pF]=uU uz_^򴭀xn9A2RGZEN;E \to(`.@ɸSt^HAġB&, (m,5f 0o0#dg2bsP۾* \djo($T&΂@L "c߼ -W(_pETϻE &;E Ɇik)اU'$ň"|b 3/(5\U,{=xz_>pUP*-TD`?(KQ >K= MU9Q >` 0~ q7?p[&(_oFʳt{@N.>F~0z*D}8e9s9"m}A^OlܰU.P`j!]!]!{{ #BD Kʳ ~$XkW2C\ _:xAH0{P /`V?Fq88ɕ Po?Bl+-3B!Cp~a= va>? J^1^J Rqt) o?ec}3e`F>Bl[6^mEbC9 "PE1^~f|0ҢLa@E]ʢrWl\CpJPhF(E+;["Q8Vhlj݉ mwY7>=Z'tu36fb}ThlLq3J@zsolL`#&@0m2}9UEϺXs_>]A @(-4![ =|ǻ,0>)[n"1r1s`V0@d.`zzfq{C``dF郟P( 5r$dL\d#BJ0hw{Y+250&^BK M3@Tc>|{[zGSrR/ ݲ#҂ ĜJcUr/ A_Hή0s"8js}snj=yQ]Jd]=۳ Epͦ 0XokyZ眬"9~wBK gYta:{}ZGw$`Yp~V pL\h6!0L.@ݎ@0FD̾nG< jSh&0!G*rGRjI 0glxz/ADP# +bn-CU1{%kv]/½.4|"g9]@~La2jL!6 FP.>4:@AZd-)j(- N}\+*y6(R}1c+)\+"m( ɫc׵jyNOYmMPk1D1ٶK Of-{ *" 5P+}ʲteP"g&s`Ƞ1M{}576(S HݲB+&t2a*^ Dջnb_q~l(ՊOlDEQ @E8K: >ڻȧIOd`PC`c z&=L/`X@q̹ cp@UgVJz>2آorzy]U%0|}pBmy@#t~BVBe9H^#Dq4xw%=PR&&@Ob>iw%`ᔕ,-ДAQbu -֘WD 2DT-Dkqz=h``A^]y "Lw,Vr`ikD*G/`Np|b1_>mfNw_Q}8L %Bfmϻxz /hEۭ'tNp qQ+d^H, uIJfIg <dP /0cXGc:3RӽCikq:/88{Nz.`ڻu3qUH/Pmq{ނg8 iqz={=&©*")O`w@|RД'pE*bO8yE>PpTDO*t, B`SaKSWԩߋS`ZQ8lgJơA <nr5t0678@)@T{v /sOO3Ri5@ 9U)q}̺S /qX \ @բzW(踭BU-bڧ[ݽ B TA.4BQ+3TZ (A{لOBL/9}`$ɜM%6p|-cp4cao4`^R?*E X=qX"ipwj>P( OC@8LmJMq/PcB+Bp ^|]l]M#p(~o(RnKGi,b/7"rA1s_.0e]!ަ! ,"SH ښS =\`.DK.fr]D ~pܯl;b(G5PbaˤTگ)BQtc-=uȘ;jt`NMUa@Tcwt9۽ 7`_G6!Gd )ϛ'm֊HxSYGFbSo0j1=T%]cZ_^{ UX0m OɿlᥒBV Oj;Pt/4`a0P}zE5.CTCS=GԖ"O< "+ނeNr6i` 1Z"n9|3YAX4Q^#J^(Lj f;FpV0j+6zzkq *C7N@w b(q۪ od4opM/ jyBg\`Z&`5}$`NbGM"h"9\QV!TOkiPت0<Fv_!,4߯J}B QL|GISoJgwЊ"_.tҧ+H X|)4`9o_`[ `~bvm>'=fL|Շ6( x5;cG;AQي8԰+Bpe~iKiA0FߠPmH[1P!|ӷl'9H/r@i : X {[ů8#O/`_< q!^t<qL|K=Y{S <xA)a #uO/`C8 {6hsAӽ}VRg&Nx}"U  .6w6$$A/~3Le3RN}f.+-f !]!]!{{ r`s@+Rvxh2C| J1t kT0n`#8[DJA}NZ(~ Qڱ|-JKŌ;"}_j^`0:?\Oh-[ "YQu}vJ±Z59 aUqA|B ׻0¢;h7PA۫9ԋ4WITƁf20# !C/6^saEbC9 "PE1^f|0ҢLi}AEEj.?M/CT+g"0\ P8'hŞ{RuV *Z{N@!libuAi]b18yk1ZimGLEqpPPT?-`,| /p_6 Zm-"٢prwY0>)[n^A9@Ԙgu+d]PA Bky6FXpnh1>?x_l4> R?\#LB5a?H8B(T(ኦ02e@;!v6@bc:;D 1*V tܾtk!ĕV_]B\쀨 _&M-CJ|`E/qhn|@.Ae?_>0}b]]a(\EqԜx{yQ]Jd]JYH"x9%5Cl{g{|`G/[&0c8fеl:>bZutG\4 ="}.| E/!!۶{8L)_> ~2n}@0FDf_7Σ_.@ @~g4*9R3?_ڶVH '5mz`&}ްD/Ȭz?ef}*#YCjr@kȱI@ȇ+>P# +bn-"a!Ƶ`6 e97O(rtu@~ o(2jL! 4:8dwq@T|Ud-)jl9Ҳh !hJi#"1!!36͵"Rllbd<׵jNOYmMPk1D1B"x`FJݲ B"PBg,KH_fEiήz5/=AYӴ>}d>\!:eWMDe.g{-T"SiVž.9) PHTTDJ|JMVP %Xi>~e#C4i> 4iX@J' cEnW3:۴"PPГl<P1<ՠՕT#Q} W6@#:{GJ!+rZw$Uc/8<]I'T>)un'o14/ۥD%J@ihJ۠(BpkT+"*YQZ^=Tcxu傈p2*߽/XiV^ɻVqA(x0[BoCL /p_66`ԡ|?JgKÔ0_"rw2Rhbm11 `XGsi0Z# Ƙk`f Dj w@1 FS`16+hcb`#T *P^J rǸ!7lvXOq/AyB4`/:Y9x%ǩW6VTYך+ ꣟(G) >f9@1؈hk xEظ"9iIo+ _>EHbz~ADB QA(!"9` _` 9`h_` 987k3ZX0S||RABʼnD|Jq:]G^bY`sՋj$ϳ 2 1uޣcV)^} ɢ_*@a洗TTP o`ڻu3qUH)i -xӀxtZo^`1~^*h%@T┧{r,a:\4ߟHQ?Y6N+CNDQ=8`TiA u"pQT+ mL80(@PeՀV?Qmwn Ov.FZ,x]{9U)quy'_.",}v@NoYn>"D*ܠ:"…/p(*-gpV~J_YOk p.ߛ(QZ( {Hn /(aη,!.]PXmzAP0"rZ: 9+yzD Ņ Y40.U26e"`?' 'ʶ#yT  R(@uDӺt<ݗ'UK1Dȏ.I9YVHKzT倨 (4(v iƑ=;x蝬7;5y3Rdm3Z)v`*5HˆcV[]tj F >WBqsw2☪ _>0腽ZQӦ ^*i \a@%H% 0`(>F"`Cњd!*['ڲQ<Ds[[BN&-lD5FKV6-~?-GJrާ&`6Q̓Z¨14^sv\PM'5'q\B񍓳8?J\FC8ʢ|/G@M/{_.p#>X Gz, 2ؑl.H40T ZO~Z IadNI0-tKi`N> ԇ)BO.>N%d 7;hEC0 R,B_04ۥ V|][ɢ>z :O8>O/ *+XGŒf\o(FT?û%O "ʚ_EX6@tM/ `ANjAk Qqj9Z؄MOͱGz#x~J[8iUM/pxm]B\v~i3qyl}]BxԓEy*-=!)*G} (pE-o{  @aX)1$`?x|!jE*Ey -A &joVCAqtنp6Ě_~@Zp?`)'>}}n#7TYG Sw0|@! 2q,bU_0+{ e,z/1Y)jPL6DN[{4O7>"5= Yc1d1Ϣۦ$R)aFrePGԞ ;$_qX5k3[}-b) /,,{ 6 +:tr(tA듑Q u>;rT!'\dn9seS @+xmH &̀/0x+ib>^C]O^%^0?ۃ!^JW(]\E9ݢ@Eq,e0@EOR(b"coS%=pA{%OTUG?Pd ?`0ޖ2r.P%#Z[,bަ'Нp 9lW4ƋE[F/1c-v㓫:] BBB@4F":X<OB=4y!{9DC)^5̀?Ta xo1>qp;r2j_r(O-JKŌ;"}_M3I}HVT]Xo֠h=j( `AϞAA5PAɫ-+h.T]J@ˆρφ֡vozr(/?3iQ&0~"X].eQګwt8z(r4\Z(KȘb"Qz},21 zE]by_FH3akiPoofmT㰙g y y倷~+y`0;x1,Zw-G6B|J:nwC~R" \ P8P_$8b@='E!7CfPr|3rX=qpmwi a@uN{csdkݫV||N8Bd*%n*ANU~%,ŜopniP﵂l-J6enoZlQ8zwY>`v}R$\xE;'cQc֭abu~,>azýk0Aq7V&>/p|Bm/6TJ"Cp2 ׄ R}̇+^`Ŋ⽷?D9$p>p;2?1CK MB\i%D>XO/usGY _.R傡[<`ġ]ZrSi, _.! _>P)}^GyojNYxvw{Ruu~ Y O뜓Aā=C-gYta:{}ZGw$`YPKp 53b.92Epm۸Ô2JFD̾nG< jSh&+-U3r-g|@hZ!6԰~6g%yGf(׫,Zk\ l%5v /b0 )*X$VP(y XsCu` W챁#gvbZl:|@kp 0%M/ș_x>Pl XQ5̢P@)vF#0QA㙯 +Y!`K_>@iYhu4Y@<` 1!!36zvheEYxH^GsڻaW10P %Xi<v?17(aä~Oǜ:ݮ0f TuiEФ' ._>PP>)U%0|}pBmy@#t~BVBe9H^#Dq4xw%=PR&&@Ob>i%WlSn)+Y[1^Q8(XB5fQ E Mil")'>e*T{_fSXZy'ZQ aӷ< b/xwp{SB@$*y-1iTbc./p7py?^Ly__.5`hr#94-wc503~H5uC;b)0<|V(p4 RC`1gf97(r3{obXS6(T2U;l!S/9Nvώ̺?(ɒUGk Q6)!I A!\Y4}]4@9RLYjP,  byat:7P1'-9/D94 L=U3\A8ny{FP9 "teESrW݋߶w%l_.Њ[G =V½8 ^RNxuU/;L/`XGc:3SӽCmkq4<8{{PU4Phmk`@rAecRjˌrc4 0n]Pp1@t:-η8 F6"S4`_> L{}8LG⑂ q<⊷Q^鼢6 l'z6cЧlF-AM]Ѧ~7b|N5 a:jE`vQϔC! sNr5t0 mF P;N{Z е;SdIU bREjC6F< xj`]Pp @sp<[Hj 'r9/ 4b!"R|P>6(afp> lU+@\Hpmx$}ԇF< rMȃpz4E"x|-: L\&ptv&<̹RK\0H)8{/}LW` \r"O-Es ⨭VE셽Fb_.(aη3f]B\ 2W8n 腱Au6Q թO$@mͩ# _.0+% nh`]HAeLA |esDq?f-"ESAo}St<݇'UK1Eȏ>.I9EQ+{c=Kj 3倢{@ 7`a/-!B-YC-n0 vHm֊La %k 74\a@|%LB6a; ǩWPfqerW8Ŏ[8Y,lt</5`/di ^[bDherK `>b6#8/*M||_0070[1 "b^ѵsv\Q㑚xvmc;Ae C %qE)uQu^__>0|e_p#}r- 0 ,iCH B]$y@>+J&j}1i/ #HadW=@e_0 P&4e3EͱGz#~j[iU/f]TB\/<|9{s*ąx=q|T<:׾@q |THQ|. 6] 0c۠}_SԊq!+^HAhϞ+k!aZQXk٠@Zp_`e3SN"8]WXϊ^H! z׺_.25zWs˷61`!_[슱o.li6r2QQ=/8SԠ9%`nK)}cD cEOI[6 0`p 8AB1n' jV>in7J2۳KOE Ò `__optEwQ].E)(P#`I2~r/I7| [Xo t2WsA'o{qvAfceq?P,PrYq#<!E 5;)W(R T#Kq L G]l|@k~Ni(V+ 6*UoѦ\t>tL Pdr@&U177⸝_>P,OUG{ bt#~+ˑi9Ƌ 2m]Ol~9|S>L!]!]!ۼҥ|mtk0)Ph2S| >b~4|{P/ w1^ypk+@>i5=?u-1)$]o`N`&Sp~{rO;xw6Њ׊`tc-( jmb9/Gz7]Yt \_((y"`Aѥ46>`V;(S@)31:rh5VPVP|(îw3-nTxkKYTevw'^Efh:}u 5buZ!*Zivt'hajwE7=Z#t{GkE*vSb61V_J/a/ c\p?PHϠ}8>~RcB~ |@ 6N>6QLW_α5"pড়.VD\%fp:P}a96l}f{}GƹhDu"ߢ rSu`xoGh1>οM(LQX"Kq"S;R+>L@Ȅ<J[E/9` /LW@\ZbTCP) y^Gyv763w09X qiCB!۲=ib9`s<‹)l8\Ytm0έ]od|lф2\q5 )?SI8ip */ķmSbq:a(9~T1hvUyk `Cė3/߶VH #5}z`&la̵/Ȣz_un^E >uZCj׌r@[̅ѰWtoX%`(+P- bn--b#ϻp#Scl/xh-VnLIrE4(~bEB&t@-EL s- v@#!qWhBFVX&>@|K)|y6(ނ:.$bhSVdZ!xYQnW"kՌr KGYmMPk1E)0)L[pA UdjV(y{u ePZT:[VlyhWr:|Rjo.S LݲB#&t2[-gaVž:;e'`E9"S%PJmk˱"sPn)cn4]{4}̵`"s 8\v`ؠcC> BOVg/?BᚯЄfY✽^?8B!B ?+>(ifƪHQ _U @J['03 3gD#r})mHZl1S=?dhd-PNw\L`aAeܺrAd 7x*mYlV^µ&K?#5 7!#!4c#fI .{QT m?L6Z|yc11*`XȈGsi0F ,1,*2 b9nOy?aSl=Rp RC`1q` rgfouFV =Ս^'+0wj {v`ѵBʑbYP,  byat:7P1'=b#ýA^3ffjQI?18 2 ~@4Ќr*%N64 9'1!af^3"B:;p/N$Zpo8yX\8kAs{AՌr pZuf{)60'~Y^:LP@5|=h[+ڔ{8 *`R/1 .ӀwNm9Nk-*< ؃fu`ݠ?f]jiQ^鼢yEs}݉8*{'`|-* 8[DM=n8N5 a:jE`vQϔC! jd8Jݶ[r/@rGOc83Si5@L%U)yHQnxT3BV䁅wW<5OӮ(-LYn>"E*:"ʅ/pB(*-g paJ_9}`$9" ė㶏P8>È "W yq.Vx HZ/*oНeGwhWjÜ+e:_.Z7t5A-c!@ۈu{8ju{a-<_>`%ąL5Ae "`@4֜<|"3ʅs…,E*RPؿ)%7*kDp(G5P̰eR~/|dzwup!>Nzwak鉢{ELl tTh u_-^3 {alو_A߳CW|`) YZ֊La b6#8/AȱbI15`/cD%` >7 Q3=b^ѵB款A|v\Bx9| Nm ~e G]r쪆\{L-~jBg>9ʵ0LC)icYf4߷JB V|-/'"/ pL'V_!rE]pwֵVk '>YGLs㑨Ҡ|(ȿ?jbD X9;AQي<+RpR_>A-LRӷ݊@|m(F "r|5P}&j[iU/pxl._!.Ȉr;?4\ q!t4|XKTFP&<਋Z)jP|miio0}`d1ld1ۧ$ނ-}Ur8tU`!r@[Ū_o ՛"(6+Ȝoώ.?-rÒ `@am@.jҽh=~"ô;#0w,B&O.uHo ee P|vcG 3(~\x6eV^2g|@HQ7m>}|BSTdzm8Rf{<7 *^{]:=PWU.V|@D[8(|A(<3 ^`B]L.T LIZ/ł]#7#1e rrb[)]FU>p)^Ph)BJr_:|{Sm  7őǽqȃXdP_sk1{r{W0{)8-f /ZQq ⵢ4\`tc-( jb9Хz$Ra~S,?HAA?\PPj%bUGݰ{v#P>T~[6^m|V(^+~(zAb |(׍ofZܢHbKYTevN^)]Y0zNi.!c(pN xL!JT|9jDX yGcy߇bq mpͿHt[1~oUyC]@%dJHqźrp#uo+++qbazhc/p~;ԽZ~ "~-XҰ6g6[(}!Y<‚m5hm ^P&`?}\@ʏ/6uxC]!zGXW|ʻY+ 6sH/ #TG T z_>:nZd ZG qGu ȱx_.mk3ˌr5\0熚_.fcj|nk%+>Pb_f *2:P> 93{sg.6>۳Zg[` KPlOyZg"3FL1M&`9reu|ֿ`jݑ__[_> ^33srwn"o_s nX&6J}ZG]5 U i3*YiR a69_|8z>glxz/Adz P#^[Xf\-(R'R b.HU NJ.ĶxB,Pl䊹0'\XMG >h-V/WA؞[ܢP@)vG#{@hq4^\s&e-٦0WC)- ph1@ԛlVi6^Vԅ{1Z һAt~aV~[9@-&n2)u.HLC vmXfѭ-y/p&n_)8ulwhW##R{pTfV6o0= } ׹_g,?󤾀DEq"S%PJmka*yz0P %ynX.F1M]4?>@q̹cAUL+u&}z?iB]ZhB[W.PU3,Gqu{:ExE90/DM۽#@#{+~ P t3c؋y(/*wR41zrkNLC(LhdQo Ē-bz~n%Z? ^T6Xx˽ueȔpo-T./޲$ זx$nM{x-vprb [r-F#4c/%u(} DGY.aJ/Bŏ.{_F@k21eWk0Z Gsi0F ,1,*2 b9nOy?aSl=RpTTR`<<LQsOr3ev܂7:A#s لFv`kyC^rz5֊=;RZse@{uH1ea,(Y輰Wd:(֞Mv()vpT@3={^P9 4X&h`hj _.( {HqxdZ>`(5Pmr[I[p/.E@7`e\ X0uL>֪33]5R` \3~QRnOGm.b/72@1s_0bk,(ivPګp'Tl`/ wVůw'*RPh)(aZ/F{% #Q 0ԭ03l)* };(il5>\>AO+,S]X Zz^QZ!-XRSU_.rXGG-^3 {alh }7cWd (S6޷m`fZ+25f{Iyr믋NmhJϑfe) PZф}է|—+bwot:/4`c0P}zEEo](|Q[6 Q4Bt</5`/di ^[bDhe`zw`>b6#8/*M||1NM/QhE żk{zYHIנ2P}ct^N!8Q"(r"S_iP/r>3q8VaQs,K!v$!. <|%`B>}fk /#Gw8%mbvm'h @u7p<_>Pnj qL7ķ`pA<Q{WX/Rxnc~jxn)8W֋ҠFZR.QL7i8oPhGE­PxE)H-j= )(-P¦NVB~cuQ q1\yۆXRB\= \LQ+R Zox#U  ]lZQXiZЂB `fɢ,@_ukE7@oJ,#@F an6B 0`!_[슱og e/yř׆qjypZf*lK)}>W`#+DoM*X9Cr;ABUٿ&0b[A 0 2۳kCOE 2Ò `_>?;l}vptEwQ>fE)(P#`I2~r/I\r+뭁.Pa.(>Yo{QO38M(c|\~hʬ,|? aa7mP}<E ڴ;8Eq@E{.et>C˞+F*hqKp>tL <-C#<-booq;|XaT@|z3r؞\Mcʹxж0{Wӭ9_nzT(Ssv@uWuM82OR6:rU_/[_#!<.!˷R/{!G kElg|0y&gY]DE@vؓe{i X]v@7qKM FG ȸxqOL3Tkk9@M8VkV+UqA`V1S+Sz0fpCCP}ғʡo/_.p㻀erM *Rp̵إ<,݋dvw'^EN,tM.Z!ƾ?Z$Ȣ/) iZw"^Q}XtsH٣5>N`c GƦ }ݔr +*fҋ/p"KK 1s_hurgPϾKMMwB?02}@cLWTN!?9 "Ha3h T%t%nP^-g ~buAQ }""1xdU9ynLt[ݫV<2@#wv#Eyv}|OT\x%,ŜoZe\Sys0W>"Ǟ_y/fw_ȃ_.4츻b`V(t7 |k!䇵8{:arGiÉj}(<|c9k¾y@QHQrl~{?D9$Ǒ{Q=GT zE]@+>L@;@|`Hb ݲ#Msi1Ē?Pbb A_r@EXgW7*9xD5>cf:<`nsTӆg{B\l!V}3uɊ ;cZJ +@מ ƹ \:#\X{=Vy9vP7PķmSmĎV7,L aGoD]5 U i3&f9ImrzǗmy:q@P\7%tG(ڍcL{ )ؓUk2Qg-h+df:7|rNl+G(zBFx rU}$Rxvw}@L1U|)EXqw0%!9`:1s 2[h1.4pd_P@U<28 h^@AZldE`C ķd|;:U8{BB-fz͵" !ˊpZ}1}]f X/ptf5A׶_RTpT03n)TiZ=P%CۗBQ[^jMܾC+RPql/|[M=-VK\"HyrOC*3ut mxӉW6[liYcXž:;eT+)jm0ˌr8Lwo(GMB(l č)cn4]{4}k `#1]4AUL+u&}&w_J߭(U. j =o]9@U <9{7=py`C #ȿ,L?Vc>oh#5_.ן7\r F5/p1'`"s ̂AA;"SMݡ(yL6X9lml- {)E0fS|'ހ_9` _3?MyN[$0~ NVa1zɱՀ[+hHo#~`i*v`g,JS`Pj@Ê ."o-E,i9ju{a-ht</5`/di ^[bDher9`zw`>b6#8/*M||-:ŵ f;FpV0Z+6xΎk8 t ^h \{ۋ"R_n_.p#}r- 0>gYe #&\th`l(|33_[0U_.G #pJڀyX9gx$Ro=x94_ Ho(3KE0|PE /Po04JMq݌rٵK{,f} Dg}}#@aF.޷#՗3`pEIg+pSwHf軑\; eڴQ)pk 6>G"r|5PmaS+W!?4ͺ~@8##{m^,U!.ă /6}zs[47(~Jt@d`ilv.y?tqzS@jρ cq;REy(СiŦ!%fͯ߻O&hp̔P7]WXtsR^.,@F an6B 2q,k ]1ͳ?CAԶ\L#pET@|-5(6DT{2Saۧ_HA vO&x- 5Y!r̽he| l@UaQ /ĸU5[-ba dηgGҋVua] K06 AGWtr™ )#R D0w,B&O.uH;u<eS @+xs|[Y|N>\x5ʬk@HQz^\t'>p)w>u)=*^ ]9]PWU>pW@D[/$n(#Q35 ~z&g2r.P%3F~0zF =tgC-hd.pdEwL[s6t2>Vk 1-.k)WCGB]4y!}9ćR/ k=F 0n/`#<]DJAOZ~ Ϟ[ewdZ! {)8p}Lat>.x:/0؄o֠{"0t*zG/T+OWo;&RK -.awYGL}\.uhoaurD9(ˡb`E\-/c-vEÏ݋dv{R9_.@pJu >@uM,h >@M}}kFH+mh{# R`hMөm}T<DWSUS/JsR>_>PHϠ}8>~gd@u&WTN!?~r]mdP6lR $s> JT|9jDrX=ypmgi @uÈN۰9Sxx2}w|+^H#EEyrPz=٭(R/`.|;|VA kkQZk,SP<~{ԊGǽ,0C.g-WAدEKvl1fu+}X]E/$GX6@~X87[x~86nE `>Bʏ\#BJo3.V̊=.sH|vmBa<\ j@|(?wK} ȱx_>@֌"|` /Msi!bIŊT! _>P) y^GyO?09X Z+^iC= ouu EouɊ ;cdr /0+W=\gxkj xW_^ؚ @#^33{ 您c S| W|9+ZݰL\ tQ`]5 U 䩥R0![B߶VH #5|z?M{@1,zQ Xfq\-(R'RFT\ {L NJ.ĶxB,Pl䊹0{ [Fw}XLU\tba`J_>@3]}1/L2ZL!> F>P.> 4:@AZld-)Zl[Ma>6Sa#8{G} Z0f%kEBߢ 7ɫHc׵jywt[#¬&K Of-{ *2 5P+ʺth2S(jkad>"gq"q1nz^ur<`9\!:eGMdEf` X[(un) 5@)乡bpb˦=\/` 8\v`ؠcC> BOVg/x@5_BzܺU%0rlXWY4W 3ЌrATЋ>4%PYN70VGhZ%=PR&&@On)i>sS6((Mu1[h~3-Lmյ8zܩ3 mw)'[ =EV`=<41ToQw)0[=i1E 1-x-F3hƞ_>`ԡ|Fe)avD ?EL̔|qcrhC3g y r)Hl0\`P#TSwh0)m0>fSئiؠVZf] ±ճB9jER`0/` teӊ/٠F "B:;p/N$@:^b]szUF \ X0SL)OR H {8 ؃A3hS4̃}BJ/`~_pa j4`9]7N'P_7_-@ȴ[*2.O .b_.T#xUa +:W1__pTDO&t, RҀ%@+Fp©F?SX0S.P-na5Ȟ(1zI@#~[nil)k vȒ@< nF< xi%m T87g>e_E5P"ʅ8|3Ќr@(}d@KB!||_>Esl4I2W9Jpmx$}{as /\A';VG 5"`#(@{\ (~;GTDLA z12+IQP\Xaf2)RD?UT7@wP:jY}|VXXr' r,*/rXGgua/܀0l/A-YC-n0 v ,<Ưm֊La %k 74\a@|%Gy +~(z32EE94e#jF#\hΕg`ݷ셜,>#-|k+Zl[/ =΋Ju<rS f;F< hE żky츆gM#5'v\BD@!95CYѦ. 5\q_6G 9R@j@8+0Ys%KZ;mEfP ZG~Z#Kˆ@_> .5Rc(G zq ԶӀ_>ͺ~_>y;rۆXRB\/}iQ/nÌrAf\Q _ ֈEI]tqzSԊqT"o0n0[XK:ŦHƙ"em,5lKEY3|f,z"]WXts$2Y}Y81 :/4@r5"@;E@E G]l@k?c~(V+ U8>Ѧ-u~uL![}.L&drP%3=Z7ł}F G3#_rmAs~AfG1^/n @,] xN(Sw@uWuW6oħt)_ CT#!]49!˷R/{!G g~(y`n?%㻋qȃؑKAGPDm?{Bl/- ȴB&Sp~9[4F_&#w ⵢ<`tc-( Խ0(> j( `WA?HAAy`0;̽f1: X/Z w SZ-mq^5&eWTN!?9 "Ha3h T%u%9V&Zjȃk Lc^n8ynL[1~oUzC=@ۧJPRUd*_bη/½/ﶂ Z-E/<`v_>k^cn Z̴~17lGV BkquzsC s#ƭ(=|{AJ__В R,+>;Y²y p ߷!`~_ t\߱ ĕV]B@m[/˫KEo0ToVo0t[`i.b_#ҫAe?gZCoگY*2:P> 936Gu+_kk?hM39` KPlOyZg"3FL1M&`sf~&@׾|&k5U->|lф2~|W^xqy@kfaޏ'wCaJ\##55_Eon#Ȋr|Zi- G/߶eLH!`&l߰D~_&(E/f1\-(R'[Rnb.Bf֪cEvb[QW2l{h}h@/DdHyrOC*3ut mx<j a{&`m}׹_g,?~2DEy"S%PJmka*y+Z! BI6V| G 1w]}]`}@q̹cAUL+u&}&w_[ PhwЄ}:)U%0r}pB@?^݋>4Y P #`{1Z%}PR&&@On)i%W)} ,>ʆф"3)>sSo<0 ì~JFV gЀ dE㮗^ vώ,\Y4}]4@9RLY1!ACl1:/lp.s1*/ր ʡin`f]3Ј2Afd_&@ FӀF ЦB/_ "Њ[G =V½8 ^RN@ |zQm64 a X>:`kՙRj[3P!@,؃F0{жV)pT>V!^0/8FC5wC+Qz@SUd]A7+/Ǎ24WTݰh="CNDQ=бS6HJ– ѦhS7b< 8q fE=S276P|m'P:ؕĈ'A4 aG|r|4<3ŞVt>YRu;ڐMye!+»+اiW=H-G(jATNфm 8/Gf)±χG*=J.cۧM6@\Hpmx$}ԇFmh< rMȃpz a刵zx Cw(' `:$E1 5"`#(@\ (~;GTDLA z12#*s&ܞ,x^kLTaP/;(il5nՖ@VXbH@Dѽ`aBZ7< 䰎/-^3 {alhy }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfe䜝<*z_ ^`¶- P OɿM% /WXE7@|*"ЀMXXV7ʷS倯BqDm(|D@ "ӹl,;րgBxmE vq@X4Q^#3PB9FT۩ s#J8y@+R-֛[/6?k:97`6T߆C %qE)uQu^_z_?׋2܍r@ϯBg>9ʵ0L=<@ԛ)sMeע腂Q#bwЊū< wWxx!V/(ꂻK=Ln7ٵK{,ڣm&׹{HT|(6c@xD1rݠ(dO "ʺ_eL[R7-}1s}u-STC\yZNF @A/n6urC7۬W//obI; qWt)Т|T<e4=<@ :*WԂ_ `򀢤zn/V`wAmP> \LQ+R Zox#U  $v|ZQX9@Zp_`e3SNg+_[,zyF (_I@"]!?-PHT&΂@| H, -W(_pET@|_"=@Z_d*lK)}cD cEOI[6 0`p 8ABUٿ&0b7EPlBW69ߞ]~>0]@]xXl/am@.jҽh=~"ô;#0w,B&Oe!n@>o t2WsA'uo/`9i9_xXY;UX>p#(㲗 GyBm F'>pEO@Bh_STd:l8Rf{L7*^;pJ@^QaT9ୢx@6$~J vo'(>2/0SVCa29X} O*hq/(lU.qތ`(F8RPilqPQ=[xޑ(A]+֜M/e4y)XZ; ++xS?x !cM~@fRćR/^3?COmlǸȃX\2Iկ9' t@`L+dao0痚.)Ώ/qBm@+^+Nrѵ& ~׼0(W5^T+Ow+RP#%oXҟ[*Gjw@XLYA֡CopQ@(x9rQ4Tk\}]ʢrUFhw!>=^)/@tJBIk@C+VCT~PcSO#QRK,9F@њaS X1c^s@i-T㊮)h y y"\m0s6g>3Rlw=G Lk8R[T* u%ؓ**"bηrpA=EiٮLAMP+^[_y/fwqjX j@|(w Kt X#m!K;rL(zsC[r#Msi_Z *Sq<"~ԦŨ-l) y^GyOm|8uO)>`NI @mٞA9Hdr 6?`Vgt:{ԂE~*ZGw$k0{ak6"{<ށD"^弞K薮hu2Qb̾>!h +t=@k `Cė3/߶VH #-RX3 <[zϗ 2_.(E/v#2,>1W }*㵆Ԯ* a*X%VP(\17Na}@a)Ʊ`6Eu#9`:+@Q}׋(SR#it~AqUȸhyW-i_>_.ߒm q9 ph͵" !ny(Mj=RĘu_.`` :V?0w j-("2)u.HLC %o.!ھb]Wkuz^˜:[Vlyh}h@"`2<`9\!:eGMdEf0= m(un) 5=/`("7coJ$ ߅S^6@t0=cEn7 Qow*9Ajl~Z |5&uU%0rloCL`~%,+_>7o%@I3(0VGhrW|R&&@On)i%W)=| Y} y"[hLO"Yyӫ*00Xko\r ^weyi>bpmGRo 8e!aZ(H4[b)T2`h D )]^ F5z[y r)Hl0\`P#TSwhSq`|m=yUH)i nsNC㮛 Nzwak鉢{E:j2x)Kj r@4:/ ua/܀0l/W#Y9ed[k`O`cz߶iq$a1ȭ.f:SLϑfe _>0m[(Gh‚kQ}J n*i |*H-vJLB6aaY`(>N"7.ST nT-E(sy@d:WmevrUhh1z"n90;01h{k& >>x^ Qm&` Vw(y6ЊF;x (?^l9tX Gz, XR( !. <|%`|5lP0U_.G #pJڀyX9gx$Ro=x94_+\Nm%E L%xC_(Nzwo>_Pw_.k|ɥO6ܽox$?4cc- 3rqt< Qݠ(dO "ʚ_zght)/@wЌڴQz_]Wk_ӧl#9H/_΍=\NM\Ќr6_/#K쉷 {f_W+yhQ|qB>By*c4\J@f\Q F_Pt] +?۠}V(>O0%ހ ]E@ 3\ʙ+^-h}g L9YE뻮|m>r(_I@_.p25zWs˷61L -r8̳{CAԶ\Lx9QQ=/JP|mie¶OTLZ|\x5yW>`>r̓)YX/`#׋+.Dr"@mڝ@EG]l>~zNi{FU>Ѧ >@QGf qx8L>PW˹@@Nhq܎/ *8CwF>1<(ۂ.AG1^/z74~5gmGt2>Vk 1-.ko/[_#!.@fR[[C)旽#^5܀?T#D."br%Ƞ'-TQgO-KKł;2_j>`0:yO|@ku=@+^+N3}%6[5h- 7/CꭒHίwLztpE %oXR/6X%]oqt-#YLL}O, DoˡS8SĨx/(ˡu"pLCsk@]֡E媬ؽH&`_>p> +@t PJZo_?BlN_>PHϠ}8>~Row#g \ P9P$"_>^a_^c\P-f PGIU`m $Bj{8a}sC yj}ゔP(ycׄ}!R,+>ی{?D9$>p;߆D xq.Bl c{]@ڶfESrR/ ݲ#Msi!bIŊT! _>P) y^GyOjMYxvw>s,9%5Clc 2i}"<`s1`9r?k޹ZMպz[r4̯ߺj ?jE1y1D"m[pR&\ >N] tQOZw 'h|60![B߶VH #5|z?M{@1,zQ X-)\-(R'R]b0 Z@]ډmE9\RoYsCoa@٣D _ XMgxh-VN+`j/p@˵Wr!P@)vG#w5_hq4lQLC/`_ߒm q9r, o07븐Dެ`sȴBH[pZ}1}]FX0Xz7Nސ PW(R- N7z̔ePE~VvmZi;<F\ZBC}yE c`<s˷cbZ}3Z3Q0Rjo.S LݲB#&t"Y 0L{q:RxZ3`&~fwNpP+Z! BI6V|]G 1#{}kxObx iScVM?'=YM2⿸آorz_{' <9+֕+ی򀐇/}h*˹GX5b)#hBHs=5f!\arA4((Mi;E .V-?nahd-U8k400Xkoy<r ^weyy[PrDߥo 8A 1-x-F3hƞ_>`ԡ|FvE<@!]oh#5py_ܘ~{L5-`hr#94_# Ƙk` |Dn`h}Sq`|<by@|6k ԶRC`1q`{ GyA/80_f-xS42M?^'+0w= `觽0W{=c=yh9@0D4r-F "l@ǜ7wh/D94 LՀ~B 8{*2D/rAD^2 BLM!X&_>P CfNW [>z0E{q"@&/8?")8۬0L+ }tL>֪33 8q fxiPC<Nr5t+KOhd@#~[nilyf=})v TC-+2C@EL}>l>Mx$$̌.cۧM*T#h#>0"lC!;hBt܀#'y/Nj{X0q)zZH/`:$E1n9\PÜog ̺{Y@e pܮ) cl,SHښSG =\`V.DYޝ#HAebi|esD`[af2)RD?UT;(il5nՖ@VXbH@Dѽ`aBZ70| a_(Zzpfز| }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfe䜝<*_. ^`¶-V4ai>%kE\a@|dg0%LB6aaY`(>N"7.STCS?GԖ"G < 2+6 o 9Y|FZ*4V=Z`_>0;01h{-J^ Q;``n`: J|"b^ѵsv\9t9ʵ0LYGL{Q}>_cc-Y 8UoL0oϏ)۞& nOL+RpeiKiA#pFߠЦ폊Lq[5<-`#9H/_g Ρ: X ۬Wg/x {xшr[]G<=׾@q ܈JQ<6\q$`?KPZ<41^HAhB&c/|6PŒ/rʢ@Zp_`e3SNg+_[, pz*], h Sw0|@!iSP8 [p4g##mBG]DZ+A!r#KAAp@ؿxp_Q6B{SoM*X9C:*EPx@[Ū_o ՛"(6+Ȝoώ.?-3qXl3am@.jҽh=~"ô;#0w,B&O!F@(S|u0y( fce~Vb9ƇF>xW<U`#׈rJ\]H!4Pv'(t`pԥnTvwb`~F*hqKmpoLG 8`L(V_drr>J f&Ϛq;|XaT@|z3rCl  82#QqLWӭ9_nKf>T(Ssv@uWuW6oħt)_.CT#!<.!}9_: kT30n/`#<]DŎ\" >FnYn ]")8ssvNcx%~hkE _0؄cAk1mD`RU)50S,?_~mD cI@sxK;YGL}O, Doˡ\X}@ZC9 P 8SD﹃xkKYTʊ݋dvw'^Efh:}uѼ P[?'oyָjl.zD{ +n;ByC]35l[` @l MX)1NiDWSUS/ D_0Eo|$?PHϠ}8>~5ǸB~ |@ 6NF>Y%/[\^-g ~buAi]b1f8ynLt[1~oUyzC@^Td*_bηrpR-K3mfve :̙g8xrj\~"@|K)|Js@ܽ`n q!!3 DYIG=BH[pZ}1}]f X0Xz7N>2[ @W(R-T03n)ơ: tEXg՚z)I|WԴַ` bHKUH)| &CJÅ~R[Vh[}N6Pa8 ޳0kqb_v~Pӓf/TdJm c9L%OrE9R(ƊO"AqMkO} l8<3{AUL+u&}&w_~35_ j =o]9@U <9+֕+\ at~7BVBe9H~'{U @JO'4+̔_>,>ʆ#ȮhS R*~y0 m"Ɣ ^cbThC3<`|X$6cY0(hUdu8PL1m)0G;l 1r[ *P^J rǹ)j7usoPU38/) [X &Av`kyC^rz5֊=;RZse@{uH1ea,(Y輰WdrMƨXvQM3v3Sz5ਤ={f P9 "9`: _` 9`h_` 987Li-,go|e_E5P"ʅ/pB(*-g paJ_0Tied z爠 bHsrۧG!;hB٦y/Nj{X0q)zZH/Dw0|tn "3x RhE Gk|o#J[ਭVE셽FbD0[Y}/L2zalPEBu @[s*6^?rs;߻|D)L^0#Sl?b2gɂGf-"ESA BQ]m DiE vԻ +XKO+ Q+{c=Kj r@4:/ ua/܀0l/!+G[Z`)ϝ#603xR=$B{0ڀCʜ7#!o ർTP7x@e L'ˌrE .m *ٵK jaxE_}#QAEsEkP ňrwtۓ)SD?5~7+ku_ m._}B?*2n ׆bt+25m;EͱGz#~j[iUȏcuQ q/pFFۆXRB\/`+Ң<1_.@q ܌r| 3uT#KW)Co< +?۠}V(>Y,.zG"E:4{I3$$֌ҳ'`4 `fɢ,@_ukE7@oJ,r#E4ѻB~[ )LB~<h5A]*mBr.z_k9%@ ># FVs/}J-زiW9+cHQ /ĸU5[-bSzŠ/.<, iƿ$&ݻ\6'RPj;L{3)*{G*dB Z_reӽ@0Oy@|u~,.#0|Aտ `>G>u-Jw\ H!4P/(.`/pԥxnTuJ{X}(5\/6$>p$Q#Qx38nu<|L.(VOy@@?qh}3b4#۳@9Ƌ 2xE?ݚ 2Vk\zD9Ƨt)_->p)^Ph)BJr_:|{P/`V_FyT {ypk+@>i<^{Bl/- ȴB&Sp~;{w^,Vv٣h2rAMxWkvAypxJw`*ؕEw"rAA۫9ԋ VI[] o?e c0~[6^mkP7rPCF4r/0P̓8^u\t/{R9z_@sJ{u u.buZ!*Z ivt'hkWT%ݜw0^ڶ` @l MX)1NiD?/p/0x[<0{rAE#?B|]jlVtK-<Bʏ/6Um`9\)ff](X, Z!a*/P=_.P%u@}h)htk)ĕV]B]h }`_~f 淭97Ԍr}5|@\Z3bIŊTf傊Lήn0Ts"۳ ` ďݖ O^L1M&`9reu|j\:#r^q/y@kfa].5\߶{8L)ky@|䞎{@0!f ̾>!k@ @Ӿg4_+-Ur%a )|O,"*Hޑ`Y\k7.j1EHܧ8^kHz_.b0 Z@]ډmE9\RoYsCoa)ov+x5@kr0%UPǧ,9q]]Pr\zn(SR#it~AqUȽhw y-\@i9<m q9r, o07븐Dެ`sȴBH[I)bqV/`uzۚbk/)R`*8?*SR4@P(ҡL-y/"XܾC+RPql/|l*J %^G 8G B?U-EV<g50= m/6SyR_@ vyC8\P)G(50<-J$+mG:%ٲ)c4_]4?>5JsQ ƂaVM?'=YM4rA j n]@U <9{7=py`_cy߽#@#%PY=ƪHQ ^GhBHpܚS3J0Sy Y} yxE弢.bu -[aF֢vw4 _U[~ "SNn/#mYleV^wbx[ o 8A 1-x(*?c5?| >#{oyLO_.(~w6p[@ljGcbThC3Gy r)Hl0\`P#TSwh0)շSc)6ОG`kco)FnMK)!Pi-S|g_ ߠgp;<^'hdna50~ NVa1zɱՀ[+hHk͕zOE#ŔX"d9^t6ncNZ{[F{uK>in`fꩲ1T3@1 _.z_@ f Ӏf`颩X&h87̷̾l}>) `Z! D"L>{^xKq:i#~E >W60~`ibOv`g,JAE1<Ջ2y#Dz>R}462a6 ?`DBs_. 4|T 3B8H_@ 3\Esl4I2WsDP[s9LӀ_74!:nҼISsA[DYx>`Gw0|tn "/K/D Hxtc[_@ۈu{8ju{׍r@1s_0e])q^T@/ VN} hkNEF~Qv0+_NU2z1SP´^Lq9ʜ ' QLORGyjn5nՖ@VXbH@Dѽ`aBZ70\ 䰎/(ZzpfزьrAr%k Fx)>2m3Z)-5Hc6[]tj F s#!<<*_ ^`¶-V4ai>%k 74\a@|%LB6aaY`(>N"7.ST OeEy.4LʳM[BN --_ w#fmO?'7r>r<kf+ib9އF5~Gy!E= lz_>pUP^)Tdlpԥnx?.wvA^QgT]E]mnI  G;p3|X-r.P%3˄(2}0;̸h=HA ƋE^Ol~-U.P`j!]!]!ۼry":X)~0 9w2S\J1 t_.~KǻȃX\2Iկ9|Aٓ? t@`L+dao0.)?V~ .\~v:rh5V(^+~(z^~^{/]"2 [)8^E2;݈NZh(r4\v2&9~CTԝjhg:+"КaS=,XQBk7%a)TT#ۂ8L[ -66Tk9R3(chjE Rj HOXIHX!"s}ew[8ynLgF _imG|*@<>@%dJHbηg#V8]Z-E_ X/mkQkj9/ )Ur- _04\ t׀2/ A_Lήn0Ts"۳ ` ďݖ O^L1M&`9reu(:lS1\:#j ?jE1y1D"m۹Ô2w:B}}B&Њ(K<{FR0![B߶VH #5|z?M{a 2}_(E/v#,.^E >uZCj׈*;pX%VP(\17qOa]x)ޱ 0/"ZVvoP/lEk<EB&]/ LSHm1XF>P.> 4:`*6Bֈr&RHˢ@hS!ldpq~)\Dž Z0f%kE0lbds??6kՈ KGYmMPk1E'LZED>̔ePEj@Ym_f Emή{uz^}]g}j8_-SU uAHyrOC*3ut_ձut"Y 0Lw'q_g,?5Lt@B۽#@#%PY=ƪHQ _> %+T.: Г[s `fB&`唍,>ʆ$WJQ$F~wnT-7|';3-EjGȒ@<^Xty#_" k>@ Ӵ+JXpn~b}'t˾)vsAT.4G7 G +b!"R|PGiE(afp> lUAVܟC`Sn4y@H}7b biދE2@[DYx>`Gw0|tn "#_Z7t5/mD P|KQ=QՊWT얽 P[_.0e])ޮ) cl,SHښSG =\`V.DYޝ#HAebi|esD9nO<03l)vFn)Bp1W]m DUK1Eȏ>.I9Eu iXŒh ut9h^ i cF=;xhKP>3R|d~f"SX[jǑl ;@L1>GBysv2򘪤k`,x]K PZфצ -T@rUtZǧ"2 ؄eu|8 >.LQQ*?GԖ"G < 2+6 o 9Y|FZ*4V=Z`||lG8F (aFx%`/cDf;FpV0Z+6xΎk8 t9ʵ0Lbvm'h @u7p<<;#b5.3݀_8 Q!+{G7(J:[^xE Ε5l,_36mTd2EE9՚FPтrzj= s%46urC#8# FVs/}J-%VAr8tU`!Uٿ&0b7EPlBW69ߞ]~J/ZXgPlŌr@z +:OT}֑{BY,0w,B&O!F܁@(S\u\A({|[Y|N>\x5yW>`>r̓)YX/`#׋+.Dr"@NQ|"u)=*^ ]9]PWU>Pbe D[/$n(#Q38n<L&(V_d\J fz'8nG {FG;#rmAs~ s#/rdxE?ݚ 嶌#Wu@E\w\wo@|ʽecwV?`>r d)etbz#5܀?T#a xw1>ypk+@>i5{n^Z(li,MRÅ3gȻx׻ⵢ4|Z3JՁGn 0dEqƀA!PMVk Zo CꭒHίwLztpE RB%oXR/6X%]oqt) o?e c}2e`F>!~[6^m™"F_kP 8SDp~"Nj֡מ=c{v{R9_.@pJu @QlcuZ!* @mEw5AdzmwE7}!<A=,XQBk7%a)TT#ۂ8L[ -Vw-G ~uLT+F 0/r >IyXZfA> X^%L *c5kELOXIH`qy߇bYfw_>s6g O0mHoQe7(qkLˑKźZfn+xEiٮLAMP+^[_>^a_^c\P-\l3b nE;U6kG(a|B##& ɘGڀ-f.]7@ -0#}&P>C{<<ĕV]B]@ڶf^M-! _.e!FB ĒJcUr/ A_Lήn0Ts"۳Zg[` KPlOyZg"3FL1M&`9re/έ=j[|z.;] ~{ak6"{< rG+Z}@|[r^%tKWa(@0!f_o 5 U i3*Y9_ΰ|@BJm0mV%L_ydыrH<7 0j@=O]p֐5|-hvЪcEvb[QWG,x*.l:|@kr 0%/ș_x>Pr\n(SR#it~AqUȻ@*N|g) [R؈Jˢ@hS!. o07븐Dެ`sȴBH[X1Fsu_`` :V?0w j-("2)u.HLC %o.!$Xg``q=HAYܾm5|/`{[@z=R*O#SV"ZTf Zt(0[ոô,L@s;NY~Ij3±JHPn)cn/ pi}' 6r3sQ ƂaVM?'=YM2l?ZhB[W>fYJt6&rxa_.ʷ{GFV*fƪHQ _>@*@Jɭ903 grFzeC)mHŪs(AF֢qnq4 [ޭ+DWweyyi>bpmGR aݷ2}03h1_>@3(H4+ m?LL|}Cr8R-@s،⽂Zn0Z Gsi0F ,1,*2 b9nOy?|Z76)ַYplPZф"3)>`m#_>0?\ì~M٠j`6р '#sqK]Z@gG ]k,{h.),`i5(Y輰Wd:(֞Mv()vpT@r~O@hT0_>0/` teӊ/٠F "B:;p/N$@:^b]szUF \ X0SL)OR H {8 ؃E#=h[+ڔ{8 *`R3_f`mq{{8 Xq PpTDO&t, RҀ%@+Fpc7a:jE`vQϔC! s(GbDғ mF PS;3Si5@L%U)yHQ _" k>@ Ӵ+JXpn~b}'t˾)vsAT.4s3xVBQT]@!||_>Esl4I2WsDP[s9LӀ_/-$xq/Rr,7`9bqO*"!L\&pt;JN_.H/X7t5/mD P|KQ=QՊWT3.I9Eu i靧0| a_(Zzpfز|Grȶd (S6޷m`fZ+25f{Iyr믋jN F s#!2UI׌rXo MD)70_[ #(82 ؄eu|8 >.LQQ*P1lA>h υ\y _}k^3WA/-#f$k& >>x^ Qm&`-e0@(y6ЊFyEצBq GϚGjN ص)!*r_J\DS8ꢐ떣r"S_n٠F)H}f>cp\ ̣fY,)QEfP ZG~Z#Kˆ@e3EͱGzprn0$rl4`*Fpxl.{ނ<7|M`o=a/A}Sc+t 2|)a 3uT/ۀ'SV OA97p1ExKQ|G 1,JKY!aK4{Iش͐ƒX#ZЂ-r=)j^Ţ %UGh Sw0|@!iSY"<79@mu,gm娋Z)jP|miioPP7_<(>Lj"܋nx l@QNk!G"(XH<| ƭbx ̷VEPlBW69z C.gԅ%v1?;l}vptEwQ>fE)(P#`I2-gn7[bPAm`9Q 3(~\x6yO`>RԵ>FO(=pDr5"@u|"kQ2_Pګ ~?Ukk9@MxWkvA.[%_ vet.pE 傂Ws,Hw@ѥt70ؘ)o0#m׊ʡo/]"2 [)8^Zv)?v/ ^ >G 8z(r<BI]@C+VCT~Pc N׶K,9F@њaS],XQBk7%m|:]^!OU!O|@TzG 8LG -rAE#?B|]jl1{#G\ P9\G Ha36i7Aŗs{M)) "hp,>Ps[G 8ynLt[1~oUyC]@%dJHqźrp#uo+EiٮLAMP+^[~_.{Y.0Cݫk-+}^L֭Pb,a@Ha-N~NXpn؀~86nE `>Bʏ BJw3.V̊q=sH|v V#Bu|}@\i%dz.F&0e0Uښ_.߶f P3SՌMsi/%+>Pb_f *2:P> 93{sⵞ6>۳Zg[` KPlOyZg"3FL1M&`9reڽ8[T%G߫͢`/|Ԋ<)7XzH`nYm[G(0[xô,L׹_g,?󤾀DEq"S%PJi"p?|$R(sCwwF1M]4?>@q̹cAUL+u&}&wy_b㚯Bݺryd9sW+,+hy  Ћ>4%PYN70VGhr~W<)uN'4+̔~_FzeC)@\n)nahd-PN~w L`aA޺2@d 7xCOE6X/{˒*\GRaݷSS؂G h1_.{,C! >P~*~lq)#Ɣ^cbThC3Gy r)Hl0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0E=/soP/) `Z! D"L>{^xKq:i#~E >WpY)ay Xgmc:3SӽCmkq:7<8{Nh=0eЈ2ڔ{8 *`R#_F8FC5pﮛ G T%]#cZ_^ضrԊ&,6mէ|mᦒ—+bwot:/4` +~(z32EE94e#jF#\hΕg`ݷ셜,>#-|k+Zl[/LGڞ~xZWB9F\+;``n`cDB)M6Ÿ5Ԝkq *SM; 9P rE!׷&=Zr/Kz_p#}r- 0>gYPDC]$y@>+J&j}1i/L_G #pJڀyXg|zGB(f Гoky9)0 8L'3>z@Q]ev+G̮-\dm3G/*+XGŒ\ܽo#?67G`Q09nPt"G?KM+iw#-t)/;7(i"S\@|m(F "r|5˹ Ӏz_.f]TB\/pF_.`_>=a/s4AG/}iQ= g (F2SGZ`=\(p3.H~ Ǹ})j[SƅuL2+D^HAhB&c/|cp6z_hhL0߲)'޳}}ו-Gn+ /8RD+䇹 IP&΂@| ~ j[P&\਋Z)jP|m?+Rp3w7(ǯƞLZI˦yjqs/zh*X2GԞ /ĸUE0bWLL6x%`ٵ!uua]/>@Ѧ{D JmiwF"E#XRL6~Jo ?Ɉ22Ea(> o;qnyܕ4@C=p#/̃|p<6r/|B#.)^ ^~NiF U>Ѧ=9 _P|9 `ǭ\L.T LIZ/ł]#7#1<(ۂ.AG1^/7tk&SP`j킐뮐mOR6:kOCT#!|/|@fRVL'ַ/znՋmlǽqȃX\2Iկ9@ړ/e{i X]v@7qK=F_# > ~?Ukk9~k1mD`RU)u0?`WAןW_.((y{5ǒz*xKn=`V1S+S@+`F._mx9 ?C= A1^\73 [)8^,*Wet/{R9z_@sJ{u u.buZ!*Z ivt'hkWT%ݜ{# R`hMөm}TYvAz`.?KHT]ˑA!>.5p6} T+\`_p%@I!׷9y~96m@#{QHy_ JT|9j^}ұ ({Y1?6l~L0mHoQe7^bOvKX9ߎ/ 7PZ-E/~\`vW=/WZ|WA߽,D]s Bkqsºs||Ž.HB//\Zur`9\)ff](X,޷Th1y`ې0/`:| t\ĕV]B]h }j`~ۚ_.sC/LW34ͥ5< ^@e?jy`_.C F>P..Rq_`#+&e-٦0WC)-B9{BB-fz͵" !ny(b6c׵wt okZ)mHLafJݲ R"_P(ҡL-y/"XܾC+RPql/|[=%^G 8G ~, T=0SGTl{V ޳0k{b_v~Pϓj#傊Lt@ nsirn.N'h_AȏLփ6"S4`z_.p_y?^)/p[LŨ,yxEN}̡W= 17* 8[DM}oĸN5 a:jE`vQϔC! j'س]H^zD#z_@rGOcL4L]O3ET*!E]Ď6d@@Ê<,=Dn<5OӮ(i{8`U¹ 8Y-G؝;ϝQG 8/EQrcpaJfied z爠 bhr? hz_>s{r#ԥXorZ] *"!L\&pt;JNx_ RhE Gk׌FŷQ[ {Ln9T&Z/f J֋^IĈ*s&ܞ,xDaf2)RD?UT7@wPSsf=VXbH@Dѽ`aBZz,*/D9#ua/܀0l4\`#Y9ed[Z`) Yx_603xR=$b6AyVi.8GPvjv~Yb[Ĉj@+R-] m."LᨋB~r"S_iP/r>3q8VaQs,Kw~ࢋD3(gsE ؄P#f?倂3HadNI0s[HL!zrx-/'"<|G<# FVs/}J-زi'im')/1nƳM`%Ė/bֽkCOE 2Ò `_>?;l}6mEM| mOvzg$RTp xO?`<<+ 0 ,J|Wz@Bhz_x(>P~Q2cOߥS{EQwtA%OҺ G;p3|X}=s*_.(Uq|Sp`@ElEwL[s6U.P`j!]!]!ۼҥ|mt;R@`>r d)et,t 7ՈrmlǻȃX\2Iկ9|Aٓ? t@`L+dao0.)?0#C/6^caur}31/_.s{_-/c-vE媬N^)/h8]hPzbbuZ!*ZPc N^Q}XtsH٣5>Nz X1ۣBcS>nJf9S+*FDwry`_Tk9R3(gߥ&ΦOjEU"Sq%Xs_>@+܌Ҡ֢lXny&- G/q/Pj Y?y@E Z̴l E.V@   #` O)PrLj/6Ur`9\)ff](X,޷Th1pP=`j&mv"`;@\i%d> X [VS-/sC!+9@\ZrXw)F(`BTduvur}#AQs;fm6VٞPo0cm ~lOyڠXpbi29{+@|j\:#~xEp~Vy9vP| m;pR&\ >N] tQO@ JK,o/gO䁩eZ!6~6g%yG(ڍscL{ )ؓUk ]#b.Bf|cEvb[QWG,x*.l:|@kr 0%/ș_x>Pr\n(SR#it~AqUȻ@ꂒnG6B/`_ߒmL`N}-\pq~)\Dž Z0f%kEB&Pԅ{1GЎ^aGkoHaV~[ZLQ|m%E L'@e 3S=\BJe]B:}):>>"gq"q1nz^ur<`9\!:eWlS <cô,L@s;NY~Ij3b/xRj[XSɓ\baJ(uԀl17\?]{4_>5JsQ ƂaVM?'=YM_>Ph1cZhB[W>fY✽^?8B/y1\^FJV, c؋y(/U ib֜Pr#NP{ .b}E SD#kQ87pzSf ` -֕"SN˷Pn"`#/G-o)D#5 1hKxfl;V_(H4+ڴOMVc.7h; ^cbThC3g y r)Hl0\`P#TSwh0)շSc)6ОG`kco)FnMK)!Pi-S|gGyA/80mxlB4`/:Y9ĸ%ǮW~lhݳ#倊ʑbYP,  byat:7P1'=b#ýa%4c703TY a |@(!ShT0_>0/` teŹ0d=?t=`eH\C\ Y'd [I[p/.E@7`W +`蘂}UgfJybmop y% T/AXЦiPX_.2 nsirn>N8$оnSUd]A#uW_>P#Дf\S1+f^鼢yEs}݉8*wG؄=x04 l m6p؍`ZQ9]3%PH~álŇz7\ (GbDғ ن0Јrߖ>~`ibOv`g,JTCw=#_",}v@IÁoYb9&9k qgSQ#3TZ #}%̌.cۧM*#؊} sam~_>0m/+t܀#'y/˸oe6_e?+e:mødtAxV@ x1]M- rM5\o RnOGm.b/z_>n9\PÜog ̺{Y@e pܮ) cJVN} hkNEFQ.rY}gP{w"֋bdĈ*s&t@af2)RD?>bHV"il50J*"`R{ 9Eu iX–[H 䰎nyh^ i c˦AT!{vі7;}sg LkEl# #@nu1ө7-vbZ}0-#d1UI׌rXo MD)70_[ #(OEd: Cq?|\vUh"-E(sy@d:WmevrUhh1z"n9|`zw`>b6#8/*M||-:ŵ f;FpV0Z+6xΎk8 tYGL{Q}><;#ԼRݘmbDYmO hLO " #}7"@҈rFAM kC1:Nӧl#9H/_΍=\NM\ЈmE+Ō3g<ۆXRB\/}iQ/nÌrAf\Q _ ֈEI{Q׶ 6(`aZ<bkct ޑ*CфM^.6-F2/dmH^-h^!w03d{Ţ {^.,N djo($mb *gB v\lxP?s-W(_>1A)_"=@ZԍW@`1O1ld1ۧ$ނ-}Ur8tU`!Uٿ&0b[A =]`0dr>Z8, ۀ!]]Ԥ{ @Ѧ{D JmiwF"E#azXRL0iـuH[|icve]LP| o;e_`,8r|j|1>pd#<8> lG@@Lhq/ U&qΌ|cx!P]>xcA^Ol~-QP`j큐뮐mOR6:]]R|0 9d)u^%?b~h BAu q". "br%Ƞ'-TQϞ-KKł;2_N`0:2.xxw,XQBk7%aSTT7~Rߍ\`~_p%@C} 6N۝,@e Q´9V&Zjȣ8>DDcn+N?H[1~oUzC=@%dJHqźnw[xm-Jve ooZڢp{Y0C}W /Wȃ1{Y(3m[BѯPBxk!j0Aю>p rS~u`xoGh1#kzn7P%Mc!2r,{)Lۖ F淭97Ԉ}5\i.eŊTF偊Lήn0Ts"۳Zg[` KPlOyZg"3FL1M&`sfе߹ [ZutG~֭'9z}Vy9vP׈@|[r^0LetB1 5<`uc?F @ JK,o/g?jy@-c*|E ~6gWD_ ydыrH|n`Ղi"{r x!y-hv8+ۊr ޲@+><\G"a)c`6}_"Zww^(r^ "@˕cer] )b ]h4:8xh{Z b#+2&e-٦0WC)"sSeھ"@KUMP+2m 77pEsܾG/`` :V?0w j-("2)u.HLC ԍv2Yt+juv} \}yE *uEo<b5Zl<}_ɐR{pTfV6lEa{&`m}׹_g,?~2DEy"S%PJmka*yF6P zآP|0AoPs{TѵKc=a{ǜ:n0A݁1~NL]vtvP~7ZhB[WPU3,Gqu{:ExE90y݃Pv/ފ_Be9 X5b)7J^29MLܚS3J0S Y} y"[hL"J)@8ީ23 m֕ "SN˷Pn"`#/{˒*\[n⑨6}kA b)l-_@*ێռ _ju([*ڴOMVc7{AƔ ^cbThC3_y r)Hl0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0E=7soP7V!^0/8FC5pmW-*< ؃nu)C/Lmx)/ll )*~~AQ=б8sҀ%@+ߍp©F?6T+*zd o8mP>Y|$FT/= mЍ2ߖ>~`ibOv`g,JTCWm&<Ս2y`@ Ӵ+JX758Y-G(jAT.4@/(*-g paJyieڞAq!r? hK՚=ٱ?qX"ip{jx( χ 2qr+e:mødtAy`Zzv|vkx;CK>SP {Ln<\>AO+,S]X Zz^QZ!-XRSUr )xsN8[^..Zzpfزi%UnmjqQާl0d1~o̴Vd k|K80 _3xb)HH32sLU 0m[(GAT󵅛J_n >R݁#ЀMXXV7ʷS倯#jF#\hΕg`ݷ셜,>#-|k+Zl[/LGڞ~xZWB9FT۩ s#HaWtm[/6?k:97`6T߆C %qE)uQ 8z;E\ԍ2#)  |skayܬ9˒% ""\Q6!TO@E/PV}_&`8=JB0ׄ_&ky9)0 E2][eV_!r^uݥ_&k|ɥO6ܽox$ *+XGŒ\ܽo#?67G`Q09Ël%O " #}7"@ҍ2n AM kC1:Nӧl#|Fzprn0$rl4`*n8fE)(P#`I2~Kjr^( eS @+xe/_܀/0x+ib9އF5~Gy!E= lz_>pUP^)Tdlpԥnx?.wiA^QgT]E]mnI  G;P"{=\xj9I-bQG{8lz[ˑi=mf~5g \e }>r/Q*G)]F -/c~M^ 3EH-^ߏH 7ՈrmlGgvdP_s'@%bvVa /5\x0Sy'>p;>rhkEթO}%6[5h- V]ϫxJaS,?\~@A۫9ԋ 4VI[]Jo?Z/AvfꓞPo&fPE1^~n|0PkE?Pe.`s@|^$!>> +@t PJZo_?4>E_0SR+46Dl[xE]by7"f;ٶ.` @l MX)1xNiV{AmKTzgp/ -ǻV@E#?B|]jlVtK-ލ\`_.p%@C} 6N۝,@e Q W*c5kELO9\<6K4pa@ s܆͙ÓluZ;W<|pȷ\Ϯ P9oPt E Xs_>@+܌Ҡm൵(-5)[ jk#8 35GrhqA(<\@1|k¾y@QHQm^`ŊƋk?@~7>Jի:E wlqGs@4c>|r _.R傡[<`i.-@,X\0}!*2:P> 93w6Gu+_z}`Pl[(km1Ī/}C{>YDU0㮬h) /0+W=\gxk5U->|lф2^Q9H:-06@kfa]./o=Ʌ/qf|D~wD]5 U i3&f9xK|9Q )|E ~6gWD/WydыrHhI0j@=O]pv*u b{@ @]ډmE9\RoYsCoa@٣D _ XMgxh-Vv=#9Ur@˵Wr!kE?LSH@GŹT#ヒDkhY!`g 0/o6OFw7u\H QoVRVdZ!xYQnW"k;kaGkoHaV~[ZLQ|m%E L'@e 3S=\BJe]B:}):>>"gq"q1nz^ur<`9ޱ uTgDV<Wô,L@s;NY~(ՊGr6e7sP6~@1Eq D.} l8涱F?mW Bow*9Ajl~e/(U.B,>R4fY✽^?8B/y1\^FJV, c؋y(/Uj&: Г[s `fBfJ/D#r!W\P=?dhd-PN4 [ޭ+D{ovEF_`mc[b;E UmiЌmj#|FvE R*~q6ZgǍ)Ĩ\b f /8N0R``fGT`h}Sq`|<by@|66DR`<<LQsO97(|hMLouF"9ل3h_lu"\d]Z@gG ]/~`i*v`g,JTC-+<Ո򀐇y`@ T-m2@Am:jqSn X&5PTXQgp_EPh)>S(ce 3|ied ԋq: }ԇFmh< rMȃpz4E"x|-,<eGw;N:@G e/D Hxtc[9,.rEx o<u{a-g yz T ̺{Y@ebAe ؠ:(i'Tlཅ,vV⢵f_ ķ((aZ/F8_~Q܏jnaˤHTaP[A!Oc먁QRՖ@VXbH@Dѽ`aBZ7RxE9[^..Zzpfز| }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfe䜝<*_."K PZфצ -T@rUtZǧ"2 ؄eu|8 >.LQQMYDQ[6 Q4Ж1"ӹl,;րgBxmE vӻyVi.8Gpo-_0070[1 "b^ѵsv\Q= ص);g;r1Um'rk top/ˍ/Ԉ#)  |skayܬ9˒% ""\Q6!TOkiP0U_G #pJڀyXs[HL!zrx-/'"6%EhLx"]FPo@Qxw϶J`>bvm'D_}#Q倊>>0#wHǏ `7pL%O "_6軑F 4g mW5_Q[#^ih9}f>RcE(-P¦NVB~h6bg3obI;>G3t<ypO}'֋PkAS*ÌrAf\Q _ Co< { OA97p1ExKQ|  3E;X\TD&t(hŦ!M͕E/3|˹}}ו-Gn⪠Wox+8RD+䇹 IY 3Ƚȡ~ j[P&Z8"E g_"=@ZԍW@ucO&x- ># FVs/}J-زiW9+WړAB1nƳM`%VoF؄.l s=;A%ua]%'U$S.U8s_?uA6EGޑ ll?%5m93tvޱ`_P8u0m`9Q 3/(} >k\,||/RԳ^FW(]\E 9@EG]l>~zNi{FU>Ѧ >`8 p~L![<3|j9I-bQG{<G ^7TT4ƋE^Ol~9?\e }>rr-LS?xCGB]4y!}9ćR/~fPۺwUd2؄o5.@]ϫxJw`*ؕEw+RPз)3Wԋ 4VI[ކf2>0#C/6NLr/r(}݅)"PkE?Pe.`\;tvO?GpzG>@t PJZo_?BlNa:`.x`^G/*Zݵ)s14akO[mqnr+*{Ea3f 8()(arŗs{M))צ}v T;ثXs܆͙ό[};W<|pȷ2T^bOv/`.|;|VA=EiٮLAM#8 35C.g-WAǽ,D6[z.V@   햃<GFmq~B##& ɘGm`9\)ff]޽,D -0#ۄ -zC>C{<<ĕV]B]@ڶfSrR/ ݲ#Msi!bIw *SQr/C`&l߰D9G(ڍscL{ )ؓUk ]#b{@ @]ډmE9\RoYsCoa<+/iE]`w8fEζ_ w(2ZL!`pd8NP+y]| h\uUld-)ZleA)|J]@ܽ`n q!!3 DYIw!xQ1݀׵Hⵎ^hXz7N>"okZ)=`***$f-{ *2 5P+ʺth2S(juv} \}yE *uEo|cbZ}3Z3Q0Rjo.S LݲB#&t2[-һV}]oV|Ij3b/xRj[XSɓ\baJӸ>e#SǜW1n!Lrh=-FcPfOUz/z[C BOVg/x@5_Bz_{' <9+֕+یG3Eyo(ir0VGhZ%ϩfHs=5f!aVNȢ\l#4P)Xuz~n%Z? ^=Ty6Xx˻uȔpo-T.#޲$ זx$.EF}kA b)lv,-&Gh%u(} DG]Ѧ}hԶ{\&v&|qc11*`X3<`|X$6cY0(hUd;4Zs63æ@{#+-A4a/@9c~soPU38/Qj`6! [{c*W/r׫?V4ّE׋r@E{uH1ea,(Y輰Wd:(򘓖x+v(/f:EppS8F% /pTd_@ i@r B1 BÐ>6?3-[G =V½8 ^RN@ |zQm6yxAՈ }tL>֪33N 0B TAT.4fLEPh)>S(Uz03hmX6I檠w b+t!0)}< rMȃpz4E"x|-,<eGw;N:@G e/D Hxtc[9֦.`N(BE`/#X ^[/0.!.^P+Ae ؠ:(i'Tlཅ,vV⢵fѥT&Z/f J֋)W1G`Z!Xg`HV"il50J*sb}\r' ҽ%5U@hEw۽ 0ӰƖ!{vі7;}sg LkEl# #@nu1ө7-vbZ}0-#d1UI׌rXo MD)70_[ #5u6J*#ЀMXXV7ʷS倯BqDm(|D@ "ӹl,;րgBxmE vӻh_._>Pvjv~luLjN4ЊFyEצBq GϚGjN ص);g;r1Ɖ2pE!y}k@q4Л|e_p#}r- 0>gYPDC]$y@>+J&j}1i/ #HadNI0Ms[HL!zrxp9)0tvPz2][ЀeEΌE]pwi-U G̮-\dm3Ee=HT9|g6Wi37G`Qi2ݠ(lE~jxn)8Wֈ.`KS;h9ڴQ亶Wk_>@-G F9H/_΍Өrj[iU/f]TB\/<|9sOm؋%5z਋Z)jP|miioPP7_ԍ=}cD cEOI[6 0`Q{"(XH<| ƭbx ̷h啀 dηgGҋV.a]%'U$&ݻ\6'RPj;L{3)*{G*dԴ/P~-r˒ee P|ve_{݀0+ ib9zGn#_/d#y!E] l_.G])W(R T7) *26 u)=.u(V+ +o}@%#qxy)> 5\POy@@?qh}3C-hrdpdE{^OrlQ,#2Vk\w\wo@|J}h[_#!|/|@fRワC)w _T/a w1ypk+@>i-Dm=[ewdZ! {)8sLate>r/ZZQu_.0؄wv@k1mD`RU)u0?`4(s~{kHg ^lJz Rvշ1{ `fu{֡C?=@iqt_ (ˡb|`E\-z/o-Ej]v `C|:] +@t=Pސ1 8[E"u/֝=m^Q}XtsWCz_kzk3=*46Uc`ŊxoC"BXڡIۡ]@> 2bD9#m/Ճzrjy`H_e/yhKky@,4^5<0G/ A_3b]`\EyԜ䎙].u_{z]0m(}g-ζb՗mٞ>YD9~gbL`sfе\:#> jE1y|b92Ep/ķ/ nV7,5< tQ3f_7j Ԯ*!O|TrLZ/Pr*ARG^M{2@1,zQ Xf\-(R'R^ b.jG 9Vt h'p#Je!b#W }y|PElwwxb{̦#^Zw=)i"g=tuA˕cer=)b ]h4:8xwqA4лZ ["#Fķd|\mg#M:.$b7+)\+2m 7ɫHc׵Hⵎ^hXz7Nzۚbk/)R`*8?*SR4@P(K(juv} \}yE *uEob5Zr<`9\!:eGMDe.g{-·x[8L{q }uvC=O /HTG *2^Զ|APҽw|0AoPs{TѵKc=a{ǜ:n0 vw 2q̙/ \Phqj n]@U <4֕lM 4<7o%@I+TUc/摢8\@*@Jɭ903 3_EGِGhJ?u1qT-"Yǹӫߝ*00Xko r ^we[PrD賂o 8A 1-؎}^ {?1KPGD#0_"]&&e|wc11*`X#<`|X$6cY0(hUd;4Zs63by@|6k ԶRC`1q`{ _ ߠ_y/) [X &T7qӐـC^ vώ,\Y4}]4@9RLY1!ACl1:/lNg<椵'CӀy ʡin`f]3Ќ~O@heT0h`: h _.( c,4\P<)0n>L烵 qQ+d^Hg/ o)N'muĺfAs܀^\ X0uL>֪332C@EL}>l>WPŒ/p> lUAVܟC`Sn4r< $xQgr#ԥX"ip{j.x( χ 2qrÜ+e:mieH)8{/}LW` !TC%q)[eu{a-GyY[cAI+T'{@X^fc T> 5"`#(@y\ (~;GTDLA z12+IQe΄|Daf2)RD?UT7@wP:jY}|[Sc-=Qt(XXG$@H9:LU ac'.ZzpfزьrAnmjqQާl0d1~o̴Vd k|K80 _3xb)~'Եy#|d偱u-/ F/lB9jE\6So`pSIV Gj;P7pd: 1`(>N"7.ST nT-E(sy@d:WmevrUhh1z"n\0;01h{k& >>x^ Qm&` VwZ"b^ѵsv\Q㑚xvmc;Ae Udj;r1Ɖ2pe@@/4eG 9R@j@8+0Ys%KZ;mEfP ZG~Z/Sg;6`84߷JB [Z^Nm%E L%xCy"xyI-9#R/[ `>bvm'h @u7p<_>P\Z>f}yA<wty8W\Y/KiKyA/AM kC1:Nӧl#9H/r@m : X mE+ňrgvobI;>G3t[]ޗx3h n{ay 3uT/ 3빽[E OA97p1ExKQ|G *h;X\TD&t(hŦ!%^ZЂ-r=w]b}Pۿ*ˈ2#E4ѻB~[ ) e,Xn `CAԶ\LQQ=/8SԠ9Vgo0}`d]NZ6Sn ^Ѧ/}Ure=I,$~_.qX5k-!U|啀 dηg׆ҋ' K6<, g!_t~5i&P?Ra띑HQu;rT!-gy^Luyt|rԧ< ?`qW|rF|u-Jw\ H!4P/(.`/pԥxnTuJ{X}(5\/6>p$Q#Qx38nu<|L.(V_drK! c]LRj|K~(x BAIy@ A['N2(aZMP^-g ~b5@Q Lc>^ 8ynLt[1~oUyC]@%dJHqźrp#uo+EiٮLAMP+^[~_.w/fw{ruxE/rh1fu+X=E/$GX6@~X-y\P¢}x0PNjrׄuxC]!zGXW|ʻY+ v؍r >;߆D xy]@> {xA4c>\@ֈ5\0m/̹f Қ_Kz/V|25<0}/Td9 "\13w^09X 6>۳Zg[` KPlOyZg"3FL1M&`9reںpk5U->|lф2> jE1y|b92Ep/ķ/ nV7,5< tQ3f_7j Ԯ*!O-?*Y9_ΰԌrmk`>RϧmV%LoydыrH\70j@=O]p֐\Psa423+ۊr ޲@+>"gq"q~n^uC}yR',rOC*3ut mK{qfL'j_l{V ޳0k{b_v~Pϓjg8HTG *2^Զ'\md`Pn)cn/ si~}' 6r3sQ Ƃ9x;P8 BOVg/ \Phqj n]@U <9+֕lM 4<7o%@I+TUc/摢8\@*@Jɭ903 3_EGِGhJۡ(Rp[T-"Yǹӫߝ*00Xko r ^kqQd /޲$ gAT^;ր{Xޏ/#4c/%u(} DG0%HM[8 o6@{L5-`h#94_# Ƙk` |Dj w@1 ƧkV½8 ^5Z<@ |zQm64 ay Xgmc:3SӽCmkq:7<8{Nh=0eЈ2ڔ{8 *`R#_F8FC5pﮛ W-*< ؃^ u)C/"]6]~sCyEN}̡W= 17* 8[DM}oĸN5 oZQ9]3%PH~álŇ7|`Jv#1ˢs0^P;N{Z е;SdIU bREjC6^< xi%m T87g>e_E5P"ʅ8\h@(t(cUz0z_.9}`$9"( }09څ^\ڮɎҼISsA[DYx>`Gw0|6\}("/K/D Hx)5<%@-EDpV+"^y#S[/0.!.ƂVNnh i* *?AN} hkNEF~QY}gP{w"@~Q´^LJ FԞŅf-"ESAo}St<GB|ZabSPȱ(W,VHKzޭN8#ua/܀p C\F%k Fxm3Z)-5Hc6[]TCuj0Z1Ŵ `[F|@JFƂ׵84m MXpm OɿM% /WXE7@t^h&,, ǩWPfqerW퀊eEy.4LʳM[BN -FOV6-_ w#feIq^U N/x%`/cD_0070[1Zk!ЊFyEצBq GϚGjN ص)!*/'C@k(qa G]r}k@/4eG 9R@j@8+0Ys%K AT?DpEﳹlB֋r@Tex0 ey9gx$Ro=V|[ISA P_>_tһ+x <<<+DΈr.3|V|Lwd/+:w8/cc- 3rqt< Qݠ(lE~j+>ÍËҠFZRz_@wЋ8oPhGE­PxE)H-j= s%!q`S+W!?\ͺ~_.<\?|{m^,@<b/-Sg@r^2SG z@QRs=w0 6(`.o)h@7BVt ޑ*CфM^.6-F m,4%"}&o̔EYn#7TYF)Lm @La(gB v\lxP?s-sCwEm娋Z)jP|miioPP7_ԍ=ർ/x(Y!r̽)`˦Dp_'LB Z ̷VEPlBW69ߞ]~J/ZXGPlň0aqh.jLh=~"ô#E#a ll?%5m9#t/@w-@0F^7Y8g|@HQn >}|BՍ{₊L G]l|AkK]]*ohS:G/(>0SVbuM&|Zb$-bQeG{l}Cl \xն.0{Wӭ9_y_N(SovAuWuMƧt)_->o~k@fR[[C)旽#^܀/` "{gvdP_s'_ t@`L+dao0z.)? G||w~@+^+N#F>rf[oE RGT+Ow+RPЏ/cI@o@ѥt70ؘ)ɔEmx9z ?C=x9rQ4TznTx:t6 E2;݋rw'^E^a@]B(i} 9]E)iƦ֝=m^Q}X_D{@k|Num[`c GƦ }ݔr\ +*^Jo 0Uo5O`.x`:X傊Vw-G ~t)S薺[7r= KVB~rDa3fA> xL!JJ/Xh8SS:V}R+Rp48} V齭N۰9Sy2]V{GLs´#EEyr~PPT/źrp#uo+EiٮLAMP+^[~_.w/fw_f-b xX xk!䇵89a]aDqŽ.HB//\ZrV!PR}pŧu`xoGh1y`ې0/`:| t\ĕ 4xA4cڶ5\0m/̹f Қ_Kz/V|25<0}/Td9 "\13w^09X ciC= ouu Ed:dEy1b -%`sfеu}>pϭ j[|ؒ e~}]oܫ`/|ԊrO= t'z=u( jWۆ&f9xK|9Q3·RjH= X3 <[zϗ 2_(E/v#%^E >uکL&b0 @]ډmE9\RoYsCoa@٣D _XMG +w{S҈rEΈ{k<EB&s@-EL sG}Dm J -6B/`_ߒm q9r, o07븐Dެ`sȴBH;.Vlg7umx ӵ7$0w j-("2)u.HLC %o.!ھb]!>"gq"q~n^U%SU uAHyrOC*3ut@:Pa=iY=n{As;NY~(ՊGlo6e;<8Lwo(G-JWo"aޠ8KѵKc}_4(mbOUz݁1~Nz?z/|}֕ T#Qy We!?F݋>4Y P #`{1A(]9MLܚS3J0Sy Y} y"@T-"YǹoS4 [+D^FГ./XG賂o 8A w@>B3rYRB@|$m'&PHf]Q0yK_W!^411*`X#<`|X$6cY0(hUd;4Zs63æ@{#+g.x0PZф"3)>sSo\0<ì~MyN[$0~ NV1㗂LՀ[+hHk͕zOC #64`R_&A X=qX"ip{j.x( χ Z/Dw0|tn "~_Z7t55<%@-EDpV+"^y#S[/_0e])ޮ) cl,SHښS_ <`V.DYޝ#HAebi|esDq?f-"ESAo}StPv{4M(B-YC-n0 vHm֊La Byz} O}"Lu()l z @ac OA97p1ExKQ|  3E;X\TD&t(h2wi1:fHGmcIz u [603d{,E7@oJ,#@F an6B 2q,k ]1ͳ{CAԶ\L#pe N~'L9%ޠn{2ky_Q6B{SoM`+dܯADeM_ շ[BlfMJ2۳KOE 2Ò `_>ƿ$S.U8s_?uA2Ȋ`Q*dԴa2߲F=0G-FY `+ 4P,G(\'0F`'ز|dV6rol}l@Bh6NЧ(&ȴm8;'Sfc"uh,?C= A1gq L2[4AE `ڳA|^$ӝ/lG 8^ E+DNt4E+"IZ!ZE"شBc;AG۶o=Z#tjwA}TYvJ ZBB@Tz[閟|yu~]ˑA!>.5p6} R1 SȏcHa3fp {!L!JJ<@ŗs{M))>)8>DDcLзLs6g O } {{@6pȷ2TjJ>UnAHbη_ h rSf,Y !,!1qmH/X~_-2n#rłһlN h:08_^]L(z!z|z[r#Msi_Z 1^ *Sq<"~ԦŨ-l) y^GyO݃m6VzM0m(}g-ζb՗mٞ>YD9~gbL`jY40+W}\gsk|m{O0WkHߺ}58{ǝV7!߅"n ۶s)er/#55_&&u}؏ Ԯ*!O|60![_&m˘ 0iBM{iTH0,zQWo%`]s`kH\ go%^kHst -h+df NJ.ĶxB[F*f )<;2.;}x"2@1s 2zQe Bj}82/(}* \5G [R؉2eA)||Fޮ`eھ"@ˉ2@ȴBH;bds??6 O;:V?0w @-&n2)u.HLC %o.!ھb]Wk"45$GjZiG0dw*|(O{VQ0Rjo.S LݲB#&t t;Q8k|l-,b_v~PǓzj_eLt@o .lչi^y*Xڇr ^weYp9W`s @k){Ĩ\b fVGsi0F ,1,*2hs63æ@{#+-(yLy;x~e97(|Y2;n -fϠ;AɊ; X&87̽zC?R`n}>) `Z! D"L>{^xKq:i#R/.E@yM\"p%`n3X̔t/PZ- "gET T5 ؃5MӠ2 )1jW5Z(lWވT얟b|0bk,i>5V:fp- WN[/Z PA[s*Vrc4r;+ Dqk ̬K!Lx0?n$bDC}dG;(i`Vw_. ħ;a)R[VȱȺWdBZ SSUL P^0/ MȩBwZ`dה ,<_m֊HxSYGFbSo0j1=\'St}_Ƃ׵84 P OɿlᥒBV Oj;P3<ЀU sWl(f9Y>OU.vݣ<Ds[{!'ogD5Ɠl[ |N *YA>}Vi,s`@ QOM/l070k1 "Qcm'z㓚xvmנ2P|rv'w ׸QsD!eQu>_L07\\Z!}f>u8aQXJ1Ďd DpD3(ǸB@_&=0\2}B)sMjPؔ2L'm]A*8WR_/Lv+O̮-\v3N}'Qe>>0#'Տ3`EIg+pS^s=\fƴ(-֢ƐO̕_l(F "r5f` z~J[04`*䇎 8<._!.R B*B/CHc{D -ϾNO(Ok_PA4: WԂ?/`빽[E  c4_obZJQ|T;X\E"E:bslC8JK!@Zp?`)'YdYs |$!p 25zW Io1`!v7FP?s-W(.)J>n&;E ɆqjpZF*}:QEj{2A|/)d1m^ L6 0`p }P ;$>_&qX55J6FX. s=]6e_G@YxY.>/_ B8I @Q{DJm^[F"D'av̩B&':$b-sk5,|'W森s3/(5\U,{=xb`% >\=!TP=/[~Q2c@EORP{Eަ*tA{%O6ؽ8(Bzx[&(_oW˹@@Nhq/36U?qԇ|Sp`3q~p.G1^/z/4~5g\ef}>rrb)]d)WKOB=4y!{9DC)^{g6Cwml{񁈃XdPIůqr(O-ywDZ! ۈ_j} at~7}HVT]Xog| wJw`*؅Ew;OW_>PPj9bUKw20# !C/6^cau"Yr(/c|0P{*BpRzg@N7|'`JPt@8vʢBI>@C+V봈CT~Ʀѝ>^Q|usoC@њ?aS$`XƁ"x>^!OU!O5 *8L=|]͠8>~ݲu ދ\`_.p%@C} =) zwpT%8J|@E9V&ZlqꁈkӾHcT; /76g3R~wh6*@5a?H8B(T}pES>cfYvDbg 3&^BK MB\i%D} *ȱx_>Ž_S;# jCE, ,>ș_x>PlmA*V.dr1;+#3_lYEJVL|b*Y>ASED(\ AԘAJ 6׊HA7,4W"׵jyNOYmMu1TUTHDf-{ *" 5P+meYB:2C(Juv}Z}yEcuLmqxf O "c260.S HݲB+&t2a*^ i,LR`,j5HaK: >ڻȧI10P %Xi<v?ٲ!cni@tq~Oǜ:ݮ0f :۴"PwhgsГ .j 56:Օ*G8g lB1\^!d%@N+TjPpTDO*-,6Up:uEN8}?[X^@+ mL88P>&WJQ$J~onGLvr';#-Ei5@#BdNU bREړ?<q`@ ۴+r'I-G5PTXQ8Ep_EPh)>C(cSz0hO,$sUЖ# ;90٧[/F!;B^t܀#'P`>b!*Rei(' `uy-H8bx / ]"V@n^|]l]M7QS) XIGi,b/7"rA1s_.0e]!q ^cXDN+T5"`%/@{,\ (NU2z1CP´^HqsDC}dG:"Cj[!OtKW[Q|_% Zz"^BZ SSU_>_(v iF=;x蝬7;5y3Rdm3Z)v`*5HˆcV[]tj F >WBqsw2☪-ϑB>jE{(>%fJ-WXE7?@TDBVaaY`(>zEi# QUDQ[6 ?QTBt<{ _5`/dmBHx vt'f~Daf1z_`n`ֺcD 7hEN@bYM'5'چ9Aet>N@ %qC8ʢ|5|8xAϯBg\`Z&`5>wY0PDCH40}+J*o'f?Aa@|R}uSC r93|B)BO.>Nf))B`*MZP|zr 0\+DEYv&'fn.m;YGD_(r@E334`53݀_f\o(FT?ûLC>Ʃ "_6efL}bv f*Z8AN<*"Ղ\"jMh Ikz-_΋=\NNB~hE+`=Ŝ}]⢟Rı{'֋Pgh7|a #uO/`EN^ޭ"? Or17p1DH(>A *hmY,."U  [h"_`̕E/~3Le3RNm}}nڑ@TY!L46B@ Ae,Xdk)ڀ g een&dCiAHO'A vO&HVx/QVB䘶>Sd" sאA"(x@[Ūد TBl1Z*ty%`):nC=p'//d'B/FO(=pDr5"PAu|ޢ"һ{,e;|AEWxRP{E*@}%#q=(|AwPx38nHn\i9~8n*8CߌC4`28""x}A-{ɧ:= !]!]!{{ ҥL6:[}@+R0? 92Cz< _:ޛ?z>Dqܷ88DT}ůwr(k1MXm)60c `0:2?9;.V$+NF>%V]E'Y=U1@|B ׻0¢;螧!( J^1^Jz Rqt>N`#P>7Sf!Duh-P$+6C= A1~vf(4Tgp/o-Ej.?=/|. E+D@t"@Y c(pN8DE@>w5 X zE]byO+B`hMөX1Bc"IKJS=/ fs9 _/TԺk9BRgݧO[!%/r= xySEN# 3A~ x' PB0(*Zα5"p`S#VD\%Fz؜!N2]ZwGLo0m24}9UEKXs_..r@ @{es)u-6rwY.0ö-Wwc~ d `CTZSAA˘ 0?iBMYްD^/Ȭz)9rY<1W [{ !ؓkl+!5hHU NJGۊ| 3o+bnT 䪘=6p'CԊ|g<eñ'9 -ק o(2jL!g8"/(}*> >hBJVL|b*Y>ASED(\ AԘAJ ӄBڡoB#y!b|]1nnDջCsIS92)u.q/M\@5P+meYB:b] EAyܥώ`Ƞ1RjzH`nYmo`:Q^0y줎p֢Ln`:u,eP$`?$*–t@|B)wØSɓ\QcaJ{~blAoPsHѵߑ\ [{b{ǜ:ݮ0f :۴"PwhgsГ .K~5|}Օ T#Q} We!?݋>T6ir#ƪ9]I'Tr&&@On)i%WlSy *Y} qE.Vo Bh E}xӫߛ*0Ҋ:Sy}uepx ޗYeV^ɯwTſ">f?B7! _.r ̜:'QɮSPHm10 m _@Sxp F5z[q hX$6c1(hUD;4Z!m03Mhr,( 2b^+1 QIXvȇ6v3RXpT򜁦8 2 N *36D4\0 h2A󈦦``ld;?tmЏ?Ѓm(c(rG*wxe^TQ߉  AcD{) T q[AUQAu<w+6qUH/aC1y j8Ly󀈃K [gpRA( ~xq>/'PT\U5c;GeOB"o 6Up:uEq'v-)e8D7LX (H&{~"]I^zD%߷m>/~0C6}!2*P1)"v\F6䩞8 j`ߦ]>@O Pn>"D*ܠ:")`F߀3P 3B8I?@ 3\Es}`$8B=8>G})D "O ]{r'ԥċaEީ":@8L} 0Jgԧ3=CW!8ۀ@>[W7QS) XIGiO^y#R[/0,!.ƂVN=QcS m*BN+T9+yx"fBWI~T&SeJ W1hj?@# Pc UA!OtKW[Q|Z#"uak鉬.mXrATcwt@q{@nHc0L6_.A߳Cjq^S6l~m`FZ+"nLf}Iq r믋NmsJH32sLU疀Ƃ {o!}^` ^*i \a@%9S Xeu||2DE>pVqDm(DQA "ҹ-Xv~րŷI "يIV6- \RI?|bDYp{ WB9FTS  Zw(AaԘWtm^sv\𷛎OjN ص s\B |eG;EC(C8ʢ|`5:7lb=/ z~r>3: 0io`%`NbGM"xDc\QV!TO9UO/P@ey}zB)BO.>Nf_¦  ŧ<<餭+H'<<+Dr,xLv+O̮-\v3N}'Q}}#@aF.'_'dcBD1q,ݠ(lE~j`i@4efL /Q LC*?C0W~Vb_'HC[6G>#/$@i F,\rE+rgvc{D &SPA4{ay #u/ 95s{yc$`?h"<-!d@w0ۀRVHZ7&Öo;FgQXiKE-L0SE,@_eeŬvP|%UeG Sw0M CP8 1*`W}n{Jq˕QQ=,5(&"e=h`D!`\"ǴE{e*045$A"( ƭbxf*!-bXt ؔ}M`?eeػ_>m$&V.E!([{mPiۑ0 l\L! @Ǧ׺k!NY.:O?G]-1Yfoe;_Pk >ɫY'w{!D X| >\=!TP=/[~Q2c@EORP{Eަ*tA{%Oֹu?0CVom|j9I-bަ'Нxlz&T4ƋE[F/1c-v㓫:] BBB@4Klt~?wIUI1&/"x/h(29`_{1r>Dq88+@P'/ҾݲOi w@8 F_'h-BhEd8{L/a:`.x`9XZlt)Sz&ދ\`_.p%@C} =) zwpT%8J|@E9V&Zlqꁈ8DDcL^+'_/p|Bm/6t< %/P~ /b%QZ@QH6(ኦ| ̲wY.aG3f$f>~t0T z_/-27ZGqW;. }@aok=Ͷ̶- _>0E_ۥ/9}+^Pb /@EXgWW 9xD5繾cF4sTױ0ws,B!ؽ=ib>x#C-w8peLVS`jݑwZ(v`^33s|`P| ڶpR&\ ~n] tc#f_7Q/ @~g4*9R3? _> m˘ 0?iBMYްD>/Ȭz?ey,.}*#YCj*֘ apXH@b[W|B& +bn-º@X!޵ 0N/"Z,VnPL/KW(\P.dr1.h4:8w񁨠 +Y!` 0M/dbz;MFLp#$QcQ+)\+"m(ٴg7`c|]1Swuzۚbb}.)B`*8T0#n!TiZm(ҡBQZ;՚hK+BPquLm }G}h@N/DdHm<`>\!:eWMDe.g{-T~côm&`i~`I7PoKY68Ij–t@|B)wØSɓ\QcaJ_'[62Dq̍#=4_>5IsQƌ@UgVMl~Nz|6e 5Ыܐ#Q} W!? ݋>T6irޑ0VGhJz`ԡ|?J޶%1O2|1 0 m _@Sxp F5<\cN8 F`"s ̌AA;"RMݡ P 1ǭ>Ki3Mhr,( 2b^طiWO8hB! + P*rY3LEPh)>C(cSz0hO,$@\H8I>Kh&h ~rUȋpz a eSTDYxĉeGw;gt^ "_Z x tu5L PD PL(`'Q\^- qrY. Ae0P"rZ: 9+yx"fBU@u"֋bD}#$+H=5/Đڭ8"D05nՖ@VHm]X Zz"^BZ SSU_>_(v iF=;x蝬7;5y3Rdm3Z)v`*5HˆcV[]tj F >WBqsw2☪k`,x]K {o!}^` ^*i \a@%9S Xeu||2DE>pVqDm(DQA "ҹ-Xv~րŷI "يIV6-Ok&ʂ >gnRqs#Jy@+B5]z8(= ص s\B |߁J\FpE!|k@q44he_p#>X GMc])Q# 8| ZO~ZKVГ /Z6`e9> /Pl' z)kL'm]A*8`WxE*RS_0?1psiɢ>z {$y-#b8Um&bD X8/V4AVƩ "_6efL /Q FߠP}Ɇbt+" -oO Ox `H04`*䇆pxm]B\L/<|9&{؋95*E?ѥC_>@y*^c4< J傌Q<=X95s{yc$`?Ǽ? Q+R)s ZBVt HAġB&Ötنp6_6%" T60#d6wYl1x/qUЫ7$"QAF a|@! 2q,bU D 3Pr2ydqA19}#9PP7ι{2A|/QVB䘶>Sd" sאA"(x@[Ūد TBl1Z*,+ȜoEMPd]L/_ B8I @Q{DJm^[F"D'av̩B&'uHw {r,|'Wm^ &x,>p x u'0>y=+ 0?ۃ!^JW(]\E9ݢ@EoY*}lz.(+26U>pWv N+|OAջp2@TOs*]&|@F~0 >tgb#s9""x{AWӭ9-e4?X} ++xooDS5/CD %T'!@fR㽜 x@}ǀ?TAb| ,GDv"@k J? t>%bvV60Gx0Cy'>PߌZ:M/0v**|?x0uS'PzS.,C!(#cNXActA v(B߇! 0#Womx9 Ɋ P(ˡs"pHCůq,/c-vEj.? /> V /hJei (~NqdEE@=jl,2}kFI+nm=Z'tu3gT1%a3P+*䩆Dwru@KIo6TԺk9BS SZ-L.<\J)"'A{R ? !Jq'PH-#rz ڴ.18yk1ZswGLEqpPz=٭(B[bY2 K~{ EiGc97AH(=|ǻ,0C.`-W1wY.(3 n_EE$O $pLa}sCAOF8?@ʏ\d#BJGW43^`rA;!v6 11\߯!`_.u9 tܾtk!ĕV_]Bۚ_ԛff|` /҂ ĜT! _>P)}^Gyo?0uLC= "x9%5Cl{g{|`G/[&0cpfе"mۇ{8L) _.?y.:Qi(9@+RQKUy`R0!G*rGmS'-R3 P=oyAD7\9V<ЇVP(BJz 㸷.P"Vx;bw̦ eñ'9"@Tp!P@)1XFP.>4:`*VB56|ҲxA)wGLp#$QcQ+)\+"Q~? F6 4_תf ;D?f5AdO< !H[pAUDjV(yʲtePN/p&TEu"@jqQEij}_3Z1RjzH`nYmo`:Q^0y줎pջnb_ @UAZP$N/HTTD [ c>L%OrE9R(ƊO! ɖ QsHk#{ ~8\v1c0P٦zD>Mv_6Bg*I*G8g lO< Gw~B۽#@%oCJV, c؋y(/த*@Jɭ90# wpJz_eC)EU Q  j]ӫǛ*0`kTaWp2RNme*T{_fXZy'ZQ a[B7! _>ƞ_>`ԡ|?JvE]<@!|1 2RN/Nj)Q @_.p1'0B``fƠOT@k(h86 X8b**P^J rpCoߠ8q{SP4a50 [:Y9hՀ{v`ֵBm@}s1eaYP6"d> "yظ"9iIo+5\EHn W1^_Pfh 26D@  w%yeB /m x/Ƞ_`ưy!Zuf{)ҶE_*@a洗TTОp2hyuJN8*rh(l6 E1l8 n>N 8A=("RXy /p[SEPДj9Q?Y6{E1__pTDO*-,6Up:uEN8}?[X0R(]3%PH~@z/\ (ObDғ *m P-OOs1bYV|Bg9U)q:D)70-T@h*I-vJs"" C9+6O3e|B'ڲQ<Ds[{!'ogD5Ɠl[/;0?1+h'Z 0=Z f;FpV0j+6/9;qPM'5'چ9Aet>N@ %qC8ʢ|5|8xA /8BR|Bcp,\ .Kw(~fPqE XP'f?APV-NI0-t4|B)BO.>NfW` /*L'm]A*8`WKv&'fn.m;YGD_(繶T~RxtN|F pA|Q8CnPt"G?5Nn!8WA.t /0:t$ H ^ih9Z؄M az/KrJ[04`*䇆pxm]B\L/<|96^̩U!.~M56`+Ң<鞐DswJ傌Q<=m.q;E 0qAӽ} \ UG(hmY; XM- (m,5lKE-L0SE,@_eeŬvP|%UX)p 25zW Io1`!CY*A!j[P&Z8""ŝdCi@A8 n # JVgJ"fd/ jypDIC1nc&0S h啀dηǢKkz( /K6r@l +:OTLz6a:r/UQA{(BT|BmG*da~rM/0Y_> dZhe. Pm;q7eշx,. J|ۃ!>JO(=pDr5"PAu|ޢ"e)>1 *l(+2v7U.(pN+{OAսerA[&|Zb$Z#/0;{偨}3b4#¹xն.0{Wӭ9-N_N(C0ovAuWuWk^xص $C R꽗@4b~y| B1 ؃yvCX"8[DŶXg*q\J|MXm)60c `0:2?UBi{Z: /]Xwv=.Ⱥj( `A<AAZ*Bs z"k@,>G }o,gCmˡ[X=HVl(zAb |?w!g4TzǢbKYT;rwNZj9z_@;@QlcuZ!*3Pcۀe!BcӺ{[{7BqC]u`X*1zNu=vAz`.x`9X傊Zw-G6B|1*ݐ!jE5q~&WN!?9 "3bϠw '},@eQ¼h9jDMX qpmwi wvN{cs;#ZwGLo0m2nJܾU"Rq%wKX,9/pn9dkQZXnyMP+- G?/p~{;lKruw/8?.Qc֭-O@/'Xo@~w &.r=j}짭P(yk~q@QH6(ኦ̲wYaG3f$f>5$LX//-2XA>d"c0m*mM/̶97r}5|@sĜ0T傊Hή0s"8js}snjTug:޻^=۳ EsJj0bc 2ib>x#Ch)3v?`?]6T7ZGw$`랖}wZG ff߅pL\Ѷ}Ô2OclDr {TM/ @~g4[ |ȑJQB )E ~6gW| "eb\-,ZRZk\ c[d ]U1FCA 9V<ЇVP(BJz rߕZ{@ Q+QM eñ'9 -ק o(2jL!g8"/(}*>]\G4lIQc N}\w# Q1cl} C~? F6 4_תef ;D?fQZ QL%ELOf-{ *" 5P+meYB:b}@|՚%TEuLǎ`Ƞ1RjzH`nYmo`:Q^0Hôm&`iu^P4ױ`C.E vyco\`vwQrE9R(ƊO!ɖ QsHѵߑVr?iPs.t˜1lӊCݡI BOV&`u"s%ի{~FP4P{0 ش(1mZ FḊXc<2q`@ T-sW#yt_zwoPUAuESTag(*-gpaUT!a hO,$sU D죾f hz_>R?pz a SsAE*,< Ae2:7`uy-H8bxP^0Rq&M/!GdWA FxMyތ?mVDJ80_#xQc!ϕfxeܝ8*_ ^`[GѦ ^*i \a@%9S Xeu||2DE>4ea'ڲQ<Ds[{!'ogD5Ɠl[>/Ok&ʂ Ĝbj^(Lj f;FpV0j̰5z㓚xvmנ2P|rv'w ODr\hA=/8BR|Bcp,\ cO`%`N|7.h`WU~bz_(lUx >)쾺C)iƁkY_>`N> ''LI3Yqϔ!0T"xyI[W NxyWK_>K= dͥm'=7p|_>P\Z>f7ؼ >Q~! wG7(J:[~7+i̘h?z_>P !\yAr}Qc5|ӷl'9H/_vg`H PڂQ W!?\ᱷuQ q1\yl⽇SB\] 8(>:!?<1BǮ(ŦTH偌Q<|{ \ 0  c4_o'@ɸSt^[ PTCAaK:bslC8JKb=/ z s f*rhE뻬Luӎ |$2 djɷb*gB &[슱oލ܆G3Pr2QQ=,5(&"O{<' 9W@ucO&H# JVgJ"l@Sa9R?/ĸUL%VEPBWV9.ҋ;( /K6k3 AGWt~5r(tA5#D'av̩B&'2uHo #m eyt|m`>bfweq7?Pm\V,|@QwVrm>}|B= e)>1 *l(+2v7U.V|vN+]Ѻ/(~ `ǭ- 2rP%#&hq>/3v7U?qԇW1MyAE\Hcj[=+֜M{'/T!Z ++xooDSF ZOB>4!{9DC) =h)؎|0*l3,:;FT@ J{/e@1c;H+daq10C@k2V$+NF>%V]Eރ1D[,Oz7]Xtt"rAA۫9ԋVID*`7"Y}@XLYφ֡Cz@P|x9~BiEP`\;evծ (r~?[~J{e ubP :-әmZm^/usoC@њ?aSݽ>c GƦ }LS'>p]^!OU!O|@Tz 8L -}a]͠8>~R"\ P8 b@=) uV D ^-g6;b5@i]b1 8y_x =1Zs´#D8P8PPT/[bYvp@$WV =G[\vE~_..fwؖ"_qp]=[!G*0cAHa-N!r=j} (<@\J RmQMye<Îf6H|xQU_.z>\Jq"Cpӭwu`D9_~ frj`_>I[{@}X5\P)}^Gyo޷/f:V&{z]0PnB*)b3 ^ =YtwtLVS`jݑ{Z?.wZG 6Cl+ۅ"mp)eĎZ7v&6J ض'hE*v*!OLvo0!G*rcSAARO齀Y?c֫m2@1zQoJhI0jak"{6bTG>WXc.Bf~c#}mE>\ R,P䊹0a WїH"gvbZl:\E, ,>_>p/]]Pl>(\~E!Pc ]<#it~Aq U}₨8tvy2J)CД4 8h`!!36XIW=BH;bdӞ݀Muz_`ưӻAt~aV~[4Mn5)u.HC 4ص{/cYXgp&7TEuLǎ0M XP"<_ɐRx|OC*#ut mxӉ\ZxE*m0KT=m) ]!07sPG'(wHc^+4(9u]a TuiEФ>Mvy_PcYf˙ lNqd>so8{{ 6 :{GJކ9PY;ƪQ ~_.த*@Jɭ90# mJ?/D%r!ДŪ(AJ֢q^z HcAr_] "^Be+W|] RqK!vր b) c4\m3/(IT+R*6{LL|BwŔ^(\Qc f /8Nr!Hl0\3cP'TSwhCq`4fSby@,lml1HK(m/@9cs!j ߠ8q{SP4a50 [:Y9hՀCD?m?\Ym=lZ6|`#AC1^+"(☓֞;@Cs)^ 8*y@i "_.P10?iu^ $8A=/hEۭ't,h@q @A;R)N' IJU/ ;L/EJaCH)OR m30'6Ti/&`ڻuJN8*Pmq{ނ@4`>~D|3{zPAMSUD +OGY+/4HTɲWt:1ϝ'zVcзl* 8[DN}_ĸN_qT+ mL88PvO\ (ObDғ *m@(s'a;)lZ е;CdNU bR{'x'{.8 jjQ=+tVIg1m@gwoPUAuESTag(*-gpal'!a hO,6p|-GR8aB]g.Vx@! apwj.HE!LX&pt;qI (42@Њ'е&pM/JQO8Je{a-qY. Ae0P"rZ: 9+yx"fBU@u"֋bD}#$+H=5PWA!OtKW[Q|Z#"uak鉬{Ebw i6`NMUa *ȱ;:|۽ 7`_&M/!GdWA FxMyތ?mVDJ80_#xQc!ϕfxeܝ8*sK@cs?腽ZQ} Oɿ>i!+H?g*"yxn0oC"`C4ϑ]ȇ,DQ[6 ?QTBt<{ _5`/dmBHx vyI?|bDYp{ WB9FTG/l070k1 "Qc֋ 0go7Ԝk!81} od<_@=/ Bg\`Z&`5>wY0PDCH40}+J*j}?1i=/*< Fv_!,O/0~ Pjc Г|8gJ J8 L'm]A*8_!r eۥ_`[ `~bvmҶE} @uZ8>?/cucp6L0Qрs}OSxEΕ4efL}bv f*Rʳ  Ũ4e3?EͱGzp`H>8`iU=/pxm]B\ /pF_.`_>xa/D @=y_^<D (2RGZz@Ss=E  c4_obZJQ|  ;E;X\E"E:4.6w6$${ { rE,@_eeŬvP|%UeG Sw0M CP8 1*`W}n6m$&V.E!([{mPiۑ0 l\L! @AV,|'Wm^ &"0x+ib>^C]O^%n~OBz;hpUP*v'x(>Pۃ,e8dqۥ7/MU肨JmwPOAջp2@z[&Zbw?@v>tgb#s9""x{AWӭ9-7NN(C0c뮐㽽MR&,x?P{h!BJr.R/ l \%"g>r%Ƞ߂?@'@}JKŌ;"ma/5>`0:?yO|/OLɊkrhQ!`"-'PzS.,y"򁂒Ws̩+h.T]O߇!͔Elmx9 Ɋ P7|PC.D  Pe.`\;ev8k]?q(E+ֳ}Vih>@mEo(>zE]by GkN}\3fb}Thl8lJ@z]ݡz+ǻ,D{6'Z\o Bkq8 },qs8>6M~:H (?pM1( )f`>\є{Yv?hl̇UTϧ`::n_ZdnJ.!w\QAmM/{CaJ7֍ @0FD߉ ,(**Ȋv|?0Yi#h9cc1̩A˘ 0?iBMYްD>/Ȭz?ey,.}*#YCjKU1F^!3RkUȱbȇ+>Pj\17qoa]HEv\ZMx,w8vD9-ק o(2jL!g8"/(}*>y]| *hhBJVL|b*Y>AS~is j jc%kEBڡoB#y!b|]1nnDջ[gSGTH[YR4O]2u+Juv}Z}yEcuLmqxf O "c260.S HݲB+&t2a*ICLU{ 0R 5NRrDEq@E%PJ0T$WԘC(lF?*!cni@tq~Oǜ:ݮ0f :۴"PwhgsГ .-"B7<&*xuJ`Ƒ(+L/}mY #`{1ܕxBHs=5f!\M储dQU6>P!Xu_z"QZ?܇78z# f{u偈px ޗYV^ɽV@(B0!SO/ncO/0sPBD%NVcb`8</<'&Fk04$8Nr!Hl0\3cP'TSwhCq`4fSby@,lml1HK(m/@9cs!7lsoPhgf츽DPdUs Obzaj֊ =;B0Zsei>hr,( 2b^V! 0L/8FCacy jӀ*~Nm=NGQ{- VAe֯<|? )M/"S1'fP`s܉8*{'`L* 8[DN^'v-V.Ꙓq($qlEC}Mv'1zI޶`P?a;)lZ е;CdNU bREc|ByqX \ M }@:n_ ݲ|DPUAuESTagP 3B8I?@ 3|04I2Wm9"(鼟C`S}b`^R?*E X=q0|ZCT"P&N,`sY'ׂD#A BhE6'е0 _.@{%@1uDpV+"^y#R[N/0,!.]P+ a:EBu PA[s*VpD …;bo$?QE*3%Lň+1GQ 0HV8zDjl_!倐a:jY¥-(>Kں@Dֽ"c;jt00| *ȱ;:P^0/ !{v;YUP^S7#Of60#b7R>$8fH6`b{s%$^9w'#JX0za-VTaSo`&[xrUtZLED:/4` sWl(f9Y>OeEy.4Hʳ`[BN&-*4d+j'Z`_>0Ow`~bV>Op_U( n/#J^(Lj}jv~aY%X GMc])Q|H40}+J*[OkiPت0<Fv_!,4߯JmL!zrqϔ4՚ϔ!0pr"_.t X|ș_>( .5Sd" sאA"(x@[Ūد TBl1Z*ty%`)Zl'Gu@YBBB@4Klt໤@`~rC R꾗3@4b~\!]A[$Ov?g# uOe@1c_@8 h!LOjEN~/ЊdEyg*Vkh- vA.զοrL=%oS/V]% 8Tz'0(C@)3"`:rhuV(ʡo/]"" "] .eQګwt{R9{0u/~, (j{`EE@{jl,2}kFI+8! B`hMө_QBS 0J{ jBB`wV avbs*jݵ! o SZ-[wV1 J)"'A{R ? !J{s{M!ؔצ}w `w_76gߓL\є1v,Vd, j!a5$LX>/ۗB>43KtOQA_mky` 5<0E_ /hn2a*CQC@EXgWW Wkv"\1#|R0s,B\u@lٞ򴎝"9~wbnմY40 W}^`u-9Pf;-w4<"{8!B@Emۇ{8L)&vzJ ضN eъTGUB;T|ȑJQkq*P40?{fmZ"82E^mJ|,Sɵ`oHv*kvW D[%+ +O(μP䊹R 0b³};l1DGq6}_"Z,VKP/DbxwtN,\pz4 9BB5flUEi'@i6( {1Gu_&`ưӻAt~aV~[Z QLvpTuWf-{ *" 5P+meYB:2C(Juv}Z; EAyܥώ` WTtx_<}_ɐRx|OC*#ut mxӉ\ZxE*m0K(T֊O2DEy"RؒO(na*y+j컫1lt[=@t{y~Oǜ:ݮ0f :۴"PwhgsГ ._({ZBWWPU3Gq g/t@^!؞ 8Bx_@ !+rZw$Uc/8|<]I'T: Г[s `FB۔_Jz_eC)EU Z+CD%C <V>ѓU|Lrn/S2|L+>1T޹OߣַoCL<Ziqz:^0:w}Զ}_Fe}1eW>11 `X8`F,1*" b9nq6xe^Tqv_p%`ưy!Zuf{) T q[AUQAy#=hV)m8 *`R_ 5m8 Nm=NGQ{- VA{J"p[@\/@Sz_.pE*bT} kt^=>AGeOB"o 6Up:uE{N8}?[X0R(]3%PHdEC}/\\ (ObDғ *{]/sOO?#-'*>ڳGȜ@8(q_&",*d:9}-LYl-ջ{ ,(\h*7 $U?J0am`H:)ce> z'k FxMyތ?mVDZSTjǑǬ ;@ 1w}0PE*xq1`[GѦ ^*i &?@TDBVaaY`(}.Bf8Q }#jF' \hΕgo ַ셜,MZUhVO"n)9-'f~Z(a{Z f;FpV0j+6/9;qPM'5'چ9Aet>N@ %qC8ʢ|u8aQXJ1Ďd DpD3(ǸBV Ȯ {`Z4߯JmL!zrqϔ4))B`*(4 pNTBlVt(reۥ_&`[ `~2#{Ϙ`xE_(rAEsEkPޤccBD1q,ݠ(GD~7g{P:\/H]J G; e7(ԩV JMv+1PxE-I-j= !(E(mӀ_ۺ(~ ,s BU($g`{{1f_W/:z x =<@ : WԂ EN^ޭ"? Or17p19h@ !+CqV ɰ%نp6ĺ_%"}&l`Fɢm2bM;r(}" *]!?Lo($T&΂@L "c߼鞥Du%rETϻE &;E Ɇ -M+Ӊ*BPݓ {Ĉ"ǴEH&Tpt4:_Zo5J6FX. s=]6wX P^lk3 AGWt~5r(tAkH:Lێ9Udz_&`IwpVqBr@He)>1T$ .]P,֋K$ p@DW/$֭EPDfq]xwm(Sy'# wQbަ'Нp 9As; s#/ze1b8>X} ++xooDSF K;I1&/"x/h(29 B1rm!@Ylu&v>PDi~n٧PX!i,l#Cp~9&fO/Zw"YQu_>`t[PbZbm| > va}!(cNXActARz f"|6ضmxdņrD>(ˡb=HCůq,/c-vEj.? /(r:? (j{`EEtfjlZu'uWpoC@њ?aS OT1%a3P+*䩆v `%65`.x`9XZlt)Sz&j-N(B~/rDg ŞAN8YGh9jDM9X=qpmwi qv< q~wh6*@60?[%ȩ*"/^bpŲ-Fj΄ZHee"٢p/|R$\xE;1r1s`V8buPz/ \PX!pnc9 h@(<\@1|k~q@QH6(ኦ| ̲XXG1.`א0O/`::n_Zdnɾb r,ާpokQ(r _.R傡[<`ġ]Zr!F(`TDuvupf? 93ɾ^{(}g!M` Gߐ-򴎝"9~wBK 6fе+$TM|hlQ2[_i yԊ8b 53b.92Epmp)er'vB16" _>`uU*2)u.HC %o@Yb}@|՚%TEuLǎ`Ƞ[|0QV1RjzH`nYmq5j\a6 zm?P9,jw!(j{Llfw/0ݽ %WԘC(l4[8Hc^+4(9u]a TuiEФ'g][}!ԏbm;I`Ƒ(+GE*yBVBe9H^#Dq4xw%=PR&&@On)i%WlSz *Y} qE.VbyE CD%kQ8/pz=h`` Ry<rn/S2<<+>*T"^#XpҾA 1^M/63/(IT-1S~*6xLL|BwŔ^(\Qc f O/8Nr!Hl0\3cD*" b9nSUs Obz-4C =;B0Zsei>`@iPcڴ󁍈xxat6ncNZ{[Jb_.|l[)^ 8*y@rxADD /pƆ*f'B /m j@+B`n}>>)c0E{q"@&[R)N'xe^Tqv_.p%`ưy!Zuf{) t^$ qpNz.`ڻuJN8*rh(l6=oA @NcutZo^`1~^* pHai^e֯<|? )M/"S1'f^鼢yEs܉8*{'`:}!Ҁ%@ԩ+Epk7a:jE)B6P4n p]I^zD%m7r;7c1bYDVt->"DT*!EYpwW|By!+»+>ZT{z~R踿(C@<{ ,(\h &g |PZ kCI!~d/IH\4٧M*pF%+9LiiyAH7b biދE2ީ@E*,< Ae2;N:@G e/Dٺq<9EH^F,ZQr9N/e q.\jBu1ZAan$@mͩX _.0 D!L^0#RܯsQG5PbaˤTگ)Bfu t" cOA Zz"pw i6`NMUa@Tcwt9۽@Q]"/ !{v;YC-n02vkflf"RTjǑǬ ;@ 1w}0+#d1UIrXB>jE6mŧLRI '(ϙt^h*,, PPN@ %n*:"YG9:7r5<!GH3}p- 0z, S( ![-3(ǸBҠUay >)쾺C)iơn9`N> ''LI3Y>N"ߔ %\E0\餭+H' / 3|@Q]jyn7ٵKN{&io$?P\Z>f7ؼ >Q~! wG7(J:Ʃ ٞ6"@rjaT_ -<@L6#mEN@-oOjQs^\}8qӀ_>ᱷuQ q1|3v{{1f_W/:_.`~-~By;7fVŦTH傌Q<=X95sq] P>FY|ZJQ|  ;E;wJKY!ah%ހ [hI*<$A/~3Le3RNm}}nڑ@TY!L46B@ Ae,Xd ]1ͻȡ~ j[P&<|QQ=,5(&"O{4ԍsƞL, >'F9-ϔD*045sPQ-#J6FX. s=]6wXP^lk3 AG`}Ep]ZQ{(BT|BmG*da~rM/0Y_> ZߵǓ]N'?pvn> &{?`qW||܆zOn%_m^OuwX`%JwV  - *"{8Rf}cT${.u=P,֋K_.@DW8wP'0CVn\i9~8n*8Cߌ݇yMyAE\Hc1^t_9` p|N(C0ovAuWuWt)x}0? 92Cz< _:Ww w Z 8@YZ.@U_m#@[ nV,ܶm@‘,jK-'"t[ЊdEig*ZsK$B^a~S.,y -R :1+譒T]J`Y}@XLYφ0+F_"gP1iEP`\;ev{R9m]Y0ZP(e(G f]T~Pcۀe![3O"%fݜ!0{&O,oOP{*4:*>8lJ jBB/p/0x[<0/'Q傊Zw-G6B|[jlVtK]\`_p%@c[,.=) 38 X^z'/v%@*h9jDMX qpmwi wvN{cs;tk1Zs´#D8P8PPz=٭(BXs_.bL5|R3r+_eR$\ "@9@Ԙgu+dz@?H0c{a*9w },qs8>6M~HB\d#BJGu?pD=sH|v~ V*|}@\i%Dz]X/pok_.m[sn)jvA-&*CQCrAEXgWW 9xD5،=x4sTױ0{낹RRu:cU?udEq`ϱ#[&0cpfеhE5>/?CZ;uO}> {;{.mvBQ8@n" nZ7v&"\FD,PA}T i3JK̇D0_ )ޙ 3 Xv (rKW[O( 2ޱ!Pc w VGŹ/T'a3_дY4`%+&e1SlWo)-+D(\ AԘAJ 6׊HAΊH^Gs4_תef ;D?f5AM1^!H[pA{i{&ve,3VN/p&7Twɖh[3>+VK\/p/@JmB?U-+mL'*s9kp,m_(u_R NR_@ vyC8\P)lI'R{70<5J$Ovb˦4?>+@q̹ c`M+u&}6?'=Y}>4rA3_*I*G8g{ź=pc8_xGE*[KV,^#Dq4~O<)un'4+)<,ʆ8BS" @T+"*Yyӫߛ*0p#T+DT|"`%?/dIwn(}vր b) c4\m3/(IT+R*6{LL|BwŔ^(\Qc f /8Nr!Hl0\3cP'TSwh0!m03Mhr,( 2b^ {1B0/S W39Rr,{8^;5T"P&N,88Jg642@ЊmOk `ߛ($ ZQry9/e q5DAeB@u _汤PAU+rZQ ~_0 D!L^0#ҽE{T u+LO;(i`VpjK O+vR.c-=uXZ!-݆̩* /D9vGwz(ʲKDarA/5#cl0dzmVDJ80\g7SQc!^L]^@T%{go +:J0za-VTnsSo`&OZD '(8" C9+6O3e|ଂ*FԖ"O< "+ނeo 9Y|~5Ɠl[>/Ok&ʂ >g1z_`n`ֺcDB! yΎkvچ9Aet>N@ %qC8ʢ[pwH-Ҡ!]=]+p- 0Vw(~fPqE XP'f?333VȮ [ݩ0-t4߯JmL!zrqϔ4))B`*(4Z2 9RO/0٭0?1psiɢ>z : DToxtN|F pA|Q{WX8;AQ6`?5Nn!8WҠFZR{_ݡ_(8ANJPj[Ɇbt+" -oOjQs^\/ {bU=/pxm]B\ /T1T\6T[bN; q!^tk]ޗx =\@0<: WԂ`빽[E  c4_obZJQ|T;wJKY!ah%ހ [hI*<$Ҡ@Zp?`)'YdY7 J,QAF ut]!F~"oGD+ƾy7r9@mʄ enNQb!rGHKJAA8 nsbDX cڢLIM~*X8\C:U`u@>/DL%Ė/bXmؔE P^lEΎ>B8I@Q{DJm^[F"D'av̩B&'2uH;ϋx(C\u\Ak){;|[Y|NO?`|*w{W>`~r/BaEpVqB*"}{pǀ?P?.`;vA^򁻊]u^I A?;(B`pbL>p T H$~rA1coSG}8e9i=mf~5g\ef}>rrb)]dZ;I1&/"yJ6b~ q|=P؃Hֻ{@Qx*l3,GDv"@k J? t˽BU< :E!88=<{~}XL]|*|DjENU<PCnLWW_>PPj9bUK.0!͔ElmJ3'ʡo/]"" Ʊ*BpR;{{R9m]Y0.@YB(i=hS.*3Pc M;D}.1߆٣5~Ngqd} ~$S aT1%qCiZ`T;|t9\m8s*jݵ! )- "VtK=E 0O/p IqĞ{;O8d*Cf%>^-g68b@i]b1 p3I5d[$Ddž'Kw"ݕ<Uc`>\є0,Vd̊aG32p>p;D xq&B k{+Dr _.R<`]ZrSi, _.! _>P(}^FynMx<.u?kg=PjW(kc1Ī}C{9YDssLj!{+@hE5>[qp1\:#[_Z4"{4 pL@Em={;jؙ`j( clD4`Y]ey(< jS?Q]|h9cOߋжBJm0԰~6gWD42En$`Ys@=o]p|֐5|5h+d&7\9V4 h#pE >@+J%@٣܇x;1ĻVqf^Z{o])iErtb˵Up!kE? SHc8/(}*TE8JVL|WN}\w#wQcQVRV$ pV{1Z5L%OrE9R(ƊO! ؂ޠ8Ik Vr?iPs.t˜1P٦C>&` /(۰!dx|@U 429{7=py`_c߽#@%9PY;ƪQ _>]I'T.: Г[s `&B۔_.Jz_eC)mŪ(AJ֢q^z Dc1XJvچr^~wqQ:*yyWD*8EF8}kA b)WencO/0sPBQ]Q~PHmؿ`8</<p F5<\HcN8 F`"s ̌AA;QT`h}Cq`4fShMf9@1؈hk xEظ"9iIo4`Y DqՀv 8 2 @T gl_>b[<~|`h _2A`ld;?t=`~eЃ .l Qh {_)N'xeU/ ;L /0cXGc:3QӽCikq/ " qӀ=**7 ؃n`@ AecRjrc46v``3xKm+QA6ANU(Ny /p[bU/4W|TɲWt:t^$(kS(B"o 6Up:uEN8}?[X0Q(]3%PH~àlEC7P:ؕQbDғ *ن0r;7~b8jGȜ@4(q_Ұ" ,"g޸2@AmQ W-E5p"…8|3r@(}e@KB!e.aa\Hl*#J}ԗ M ]g.Vx HZ/㝚T|E!LT&pt;aZi_6@Њ}Qk p.MůQZ( {Dn9\PLÜo ̲wY@epܦ! ,"SH ښS =\`.DY[N2*BPh!(aZ/F_vQ{c +LO;(i5nՖ@?Xr'Q+`=sj ŝul~a_>g/5#c%g /4Zn F@l*"Qe²P}zE5.CTCS=GԖ"( \hΕgo o 9Y|Uh1Z"n9|`Zw`F1+h[! Je<r_`n`ֺcD 7hEƼkx7q Co7Q8$`6TQ8?J o:*!iජb /#!  4µ0L4jeIBn\4h`(bӶ-lU_(Ww8%m4-i~F T-N|;J J2 0  ,>/_>( .5f}oұyADQ~! wG7(J:{^se /H]J M 2Mc uUR( Ũ!W$ZN߲QjQs^\x~J[8iU /ۺ(~_>y;r{{1f_W/:_.`+bӶN _.D+jV{(rj$)24hsAӽ}V|(>@MݡM(-7PTCAqtx1O(m,544[OL~#$('>}}-f$o羿|(tA듑QElݖ*dq_gn7[E_P{.u(+2v7U.V|@DW8g(|A1fq^x2X}T(*7@VŌM(7#1<({.@G1^//tk&`Z_N(C0ovAuWuWt)?->p/)^PQBvE 3DH^P=}zfml}qHX\2Iůg9@'_ t˶@1c;D+da0z&!? ( > ~?Uϊ%V]Z @힃 ]J";0¢;t^\~VIW]J@XLYφ֡CopQ@ڻb |?w!gH4TzfTxykإ t_{R9z_@3J{e u."̺;356kHEȩWS+TZ`v:zk3>*46Ucm4l]^!OU!O|@Tz[_Nix)D *jݵ! o SZ-u8?p_zu(B~:)dP|6 zwQ8ˋBZrQ´^-g63 ڴ.1πvN{csds´#D~EipQ(qĞVQ !?NKX,9/h1Qs&t gkQZi,CP[n^ey j3غL"Efl7 E8a]rƵ|ڸL@JֵxoppM )> |)afYX,{#@ԘC<kHdF&}nDCil!bD9_~k`mM/̹ ۥ5< >@e?jy`_.H C>G/H<7wDۃc:V~֊zݞP::cU?uɊ wLj!X3fе"{S1\:#[_Zi [i@kf]y 5\m- nZ7v&jy@0FDM/s_>pQԦ*!OB~VZf>JQBѿt&@9†"n8K2@1zQ Xkf\-l5P`O[WDm*֘ aX$VQ(BJz na=X \b{̦^Zo=)i"gtuA*@Q̢P@)1XFPQ{Dg> -VB/`_uѩ:X. o0또DD}XIZ(6YQW"k23 mQYmMPk1DET|!D[pAU$jV(y e (-Y/p&_!8uVGW*Qb#!B?UL-+mL'*s9k~+ag&`iu^Pݷ*S.~VD)j}SEg*7c0JPvA1M]4?>+@q̹ cp@UgVMl~Nz>4rA3_*TL#Qb]?8a^E*[KV,^#Dq4@J~O<)un'L4+)<,ʆ4BSEU Q %ZL46,5TaWm8('>W|"`% <?1( ;7%E|F8}kA(sw76!J,l6i RC`1gfsoPhgfkJ.Elx M}s80O8j֊ =;B0Zse>@}s1eLA1%ߟȇXcDqEsړ֪3W(-kCI!~،OP /p> lUALC(r[W\(~o(~(`ՊWHT4vy,K ۼ jBuk m+?AN} *hkNEJ~^Y}gPlW~_lQ´^DJ Fϣ`[ͰeR~PWA!Ofu bG Nԧ +XKOd+2VH-00\_>P^(.hƑ Bw5x蝬7;5e! kf"QԬ# #YAnu1ѩ75vb\ `WF|@0T%]cZ_^{ UX0m OɿK% +Qj;P7p$: C1 >& Q* P1lAFQTBHt<{ _8}k^ۤBlE vK^ZP(fmK?D}Vi,cGP j%`6Q4'l!Mu8aQ.Kw(~ࢉD3 (pE XP`r@a0 sW%R=8w4? k(O/UO/`:PE]F_.Poz݊o3ٵK,L#J@EsEkPIE1pxwt3m~jXn!8WҠFZRz_@woPS~VgC1:NӷlfZ{/KC.'NB~coB<7vI8=Ŝ}]Bֺb/-SPA<r@&(\Q _>=XO/(r] +?{C97p16T7<b3&Bx*h2Β@OR5y_`̕E/~3f,"]V~u$2 djo($2q,g ]1ͻCAԶPVyNQgC䴵GHKxq n{bDX cEMI|G6 0`p <9u\WBly"(V++Ȝoϩ ҋ;( /K6cϮ.jҧi&P?R۱'#" u>;rT!&0r( @w]#2)_y ^>|M >3 4wP|r#ʫ\Yn^ z+\t'>itPAnQ|"ѷGYʬa>K= MU9Q >` EP38n.<L>P,ޖs*?frAԇ|cx!P]Dc1^^itk&`YN(C0c뮐㽽M׼ ,x?PQBvE 3DH+Pe/ B؃j6H@YMDEװ J? t˶@1c;D+da0&!?<(\ܷ~Њϊkrm C꣒ίwLztpE bz*K]`1Q+C@+?`F.? ضmϊ P7|PC.D _,/c-vTDc"no +@t PJZ\?~?VYugƦѝ>^Qy"fN.` @ MX)1 xFiZ_a'v.RF?/ur`3(g&ΦOjE;D͙^+xEi٦ AMP+>[_>]ݡz+ǻ,D{[BևPAŒ_ȱ'`#pnh>/pD6M~:H (?pM1( )> |)afYX,{#@ԘC kH z_m"D j ĕV_]B\QAmM/:S)`H nY򀑆vibNÊT! _>P(}^Fyo?09X ws,|"9!C7dw'eYB:2C(Juv} \}yE*uEհq1^z^p)<R',|OC*ut mK^ӉV6kոô,L]@wOZL!QQ_>P(Β(R{70< ՛ JsW+9,+s@c߽#@%{+~ t3c؋y(/த*@Jɭ90 wpJz_eC)mZ1S=?d!ֵ8z ` +Օ"QN}˯P}EJ_`i%T޹(Q(0[BoCL<|;F=|̩C ! FJgKLÔ0_"Ķ|LLhbm11 `X4`F,1Ej w@1 FS`16+hcb`#ůL#/U"3)>qC<o_>0_.pa̎[ !6DqEsړV! 0L/8FCacy j4`>[7N'\h[Aȏ~^*h%@T┧{P_xp[j"()Dr+]ZK-^鼢{mAGeOB"XMM-AN]Q~/b|N5 a:jE)Be(s((1zIlChFa? SL"sRӐ,bUod@jy@HÊ4n(P6 V*ܛ߀X ݲ|D6`DBsւ `F1+He X4Q^#J^j%`6QhEƼkx7q Co7QjN ص!FTt>N ׸Qc"(r"Q-7lPr>3: 0ӨyXs%s A?DpDsB0OkiPت0<Q #pJڀih_0~ QB(a Гog8w!0` e9W /`:| X|Y̩eۥ٭0LsdKwۘ`xE_}G(r@EsEkPIE1pxwt3m~jXn!8WAХ4\oPc!Q<@l(F "r͌Rcx `H8iU /ۺ(~K5L}^FH8=Ŝ}} -6diQ[cV|bS*J)uO/`C4 +?{C97p16T׶DA &Bx*h2Β@OR<4% z s W60dgŬ }%UG Sw0|@! 0`!?E.Gy7r# JV,mJ+{6 +sDI`:_>WBly"(V++Ȝoϩ ҋ;( /K6r@lٱg{ g7`SGGD Q:L9s^Rs/gnmӧ!NY.:(Wm^ ~_`V|Q^%n~(w{!D X| >H w݃,e0@gqۥQ{EަJ,{ႨJm0 ?Pg(Bzx[&(_oW˹@@LNlHtÌ_.Нp 9As3h9Ƌ 2 nla9:] BBB@4^2Dt;]R ~r+!BJm_ɆR/{!(^5̀?TD-" bG.@U_m#@kX_}v IGX}S}_M3VYw|{V|VT\+Xo֠h=" 5^T gOWߚC4VIW]J?ZXLYφ֡C@YyL4(ˡb`0~"_~6t E2;kN^) /h]hsEmcO̺h>@M+4;D}x}~D 0 ;m]X*1zN:} jBBj9@TzpN/] 4s*jݵ! o SZ-8x/r] sV(B~/rDgCL3r_wQ(5,? JaJ|@E9Vll-+@f18yÒ~wh># !+LB۷JSU$*_n e1ZLԜ ]﵂Zm-E_p;D xq&B k{+DXO/bQ *`/ihn\ =xAe? _.b]]a(\EiԜ掙{{󘣺}w>0PnW(kc1Ī}C{g{:dEi`csf_`?][ȺT 1WkH׳;= ~{@H#^33{!(c S| ڶ{8L) _.P _>07" _>0= _x(< jSh~VZf>JQm}:q@P\7%HyFf(׫,j1E\ l%>kH_>Psa42}.+ۊ|" ҙ\17TW*rU8Bxvo] (Φ SwŖk<EB&0~@5{`p$_PBUD w]S-iS,Z4:Tjߍ, ~y(\DŽ j J Bڡe"D9_תf ;DkkHaV~[Z Qt!0h *CRHTTBg,KH_fEiήzg!81J] 1Rj0.S DrE_i5j\ag&`i~׻oPUا\lR`?$**YRj1AԘC(l4Q- cn4 0i}k `%1N+UmZp;4iYQ=YmMv_6Bg*xuJ`(+FE*yirޑ0VGhJz`@8:^46nHcNZ{қ'4 q۲ DqՀR3\A8^ywP8cCDi4 9,/( FfNW W>Q =V½8 YRNz?"^Tqv_.p%`ưy!Zuf{) T q[AUQA\w+g8 *`R_5p0㭛D|[}٨SU$SA{J"p[j"(=DhJ5Q^鼢{mAGeOB"o 6Up:uEN8}?[X0Q(]3%PH~($=ٸՀ#Q6 P޹aS>(δko!2*P1 )"v\F6䩆4HڣoF*X2V*ܛ߀ض-ջ{ ,(\h*8wEWf!±({ل(!aYRD9}`$>9" Qx죾fpl" B'wPGdU2z1CP´^Dq9xC݊m-"DSņj y\Zt%ŧ;qR>]X Zz"^BZn95UQANo:EYvDc0l/A߳Cjq^S7#(m֊DxR>$4fD6`b{s%$*G0B>jEL6So`~RI bZǦ" Xeu| Ek]lڞ#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`|bVжCk&ʢuWB?P+;1#:W. JTX5] yΎk Rsom5 !89; Ή%qD!eQu>__>P f8-7t!}f>u8aQ󰾁9-c6AࢉD3 (pE XP`ҠUay FvUcih[N/|z(!0@ Y>N%EL%XC_UNt__!r/ _ۥ٭0][ɢ>z :O8D*+XGŒ\ \ (>>YRVHo@MYhI0,&i3|OL~#$('>`!JQ*fA ]^ XA|{Nt ؔ^a_@YxY.b B8I)Nڎ>Qّ0 l?Y_>r@+n s棞 fceq?Ph\~eTeJ &&Ht\@1ccS1>fC1M¹xch &I+֜M<\rrb)]F U%C"|/Pe> BA5|6HcxAYMDE״@v' t˶@1c;D+da0痚&!/0xxgqU'9Y4_( jmbmD/(PzS.,=AA/ڂ~*G8YmG }o,gCmˡ\X}@Yr(/3 h5͢/2b`\;ev:;ħ{R9_>iE+8;NJ42"شBc;Aԇ9Ĭ~D 0 ;jm}k3>*46Ucm4lc^!OU!O54a'2v> 1s_ur`3(g&ΦOjE8l0^&`+ ꋜF]f/ iMD 3MTc5kE t746L44kpͿk1ZimG*@60PT/[bY_bL~{ >[ҲMcۛV|(=]Pijip윌D{[B֧d Bc-NFXpnpwiP(<|c9,GiE!GW48Y+250Wv?߯!`v !^Ф/h(s KHtXۂf0熢+i]Z1aTCP(}^FyouuC= _`NI @lٞA1s<‹!0Ytm [Zuͽsbjݑߺ^Q8G/Ԋ4b 530W EpѶmCaJ\1ʸE/s PAm JK̇_۳'TPW_.u};:Uw#C:&$QcQVRV$ pV{1ZmMH(¬&Yu: !D[pAU$jV(y e (-Y/p&_!8uVWC}OŐRpT&^iNqtt" #03 m(T)?[+5XDE_HgIDJ|k"QcaJ_D-8IѵIVr?iPs.t˜1P٦C>&`L/?B7<&*|uU%0|}pB _._>^AJV, c؋y(O/pW @Jɭ90 mJO/Jo@1n7-Xcz~^%Qɿ_bu-No\Dc1XxuHp+T{_f XZyEw[ o 8yA 1^pWphKӈml;V_B@ϖ)avD{>&L|Bw|1Wk0j d#94-wc503FQECP 1ǭfShMKh&h ~rUȋpz4E"xPXCP&N*8uy-H4bxL/?!8/@>[W|A=~(`i9Je{r%|9̲wY@epܦ! J}VN} *hkNEJ^>fBU@$"֋b$ĈyT u+ܿ RGyGG ~4؃@Dֽ"c;jt`NMUa- rny۽@Q]"/#!{v;YC-n02vkfem3Z(vWjǑƬ ;@ 1w}0+#d1UI|`,x]K {o! MD)70?[xrUt1J-vJcSN²P}zE5.CT mOe2<Ds[[BN&-lg+jl[N/L(fmK?D}Vi,cGp+_`n`ֺcD 7hEƼkx7q Co7QjN ص!'g;q1ƍ2pE!| _(Z3_vrr>3: 0ӨyXs%s A?DpDsB0Ok٠Ua Fv_!B4߯!J>L!zrq(i~|GISA P`>]W``9r,^S)_.0][ɢ>z >`(>RI^vcF.&Dňp^iDhSw=nХ4|AKoPS~VgC1:NӷlfZ{/KC.'NB~h9co_ /K3^̩U!.ċ}iQM/xn9_>: WԂ`M/(r;E`sAӽ}+J!1qt6qPAqtx%r g,z { rLEYn#7% zϺ83;ATѻB~G CP8 U}ȡ~ j[P&<(w@,5(~6DN[{4O7(ǮƞLY|,F9Yt۔Wpd" sאJCPQ}~M`~%VFX&g)jŸ,{S_ptEwQS.E!([{}2!*P#`N2as/_>@I[ eytQ>A۶0wS 3(6G`D|=x' 0|ۃ!>JO(=pDZ7*[T$z`/pxfT|]=P,Wdn\/΁:$>p$Pb]CսerA[&|Zb$_a(@1cwSe1>p 9As5yh9Ƌ 2l|(2Vk\w\w-hJ]fcM> 3DH^P=/zfCX"4[DŎ\" F׳~ J{/e[i w@q9 `0:2Ԋ^ : /]Xwv@k1Ѷ{"(PzS.,=AA?\PPj9bUG={,6#P>$pDa:rhV(>+6C=/_ (ˡs"pDCůg=@E{]ʢrWlz3pW "G0Z(E+@Q 8T}jl,2}kF%rwY7>=Z`v:zk3>*46Ucm4l]^!OU!O|`wV 5~\m4Q{]͠8>~RE0/p IiĞ{;(9Yyh9jDML4KD1: 8yE?K X }[ҲMcۛV|(\] Piruw/600PQ3 n?d B5+?{>pD6M~HB^d9J( )> |)afYX,{#@ԘC qTBVq"CpӭwWZ}u ^s m /{_.m[sn)jviM/9+>Pb_ *:P Ҩ93󘣺w.{(}g+αbՏ!뽳=is"41ber3v0 WLg?+$?ZW%Gl֭'Ajy&_viff vh6!0L1JM FDM/}8eTPoX"Did֋r(9r,ɵpVⳆԮ*֘ ڐrhFl+(Jg(VrP]U1{lV8/xh-lrm(\zf(CR{D s_(a3_ EJVL|WN}\w#C6gX,mV5AH?D( 7pEs<G/EP(¬&Y"B`***$f-{ Ľ4q@=/k^"0nEiήz5B`n5$([.ml`}W@}Ș )zH`nYmo`:Q^+}faVž.9) zP_`(/T$" c>L%OrE9R(Ɗoo!c4_]4?>5IsQƌဪ68`(iB=Z~oQJU 429{7=py`{Be!?{0 oBVBe9H^#Dq4~O<)un'L4+)<,ʆ4BSEU Q E Mhl+Օ"QN}˯P}EJ~_`iQkWbԽEqAUBoCLU1juQQ̜:bdWԩ(Ul6/ߋ)(\Qc f /8ҘNr!Hl0\3cP`U$;4Zs6My?`S=>Q"3)>qC<o_.~B?/80_f-XST2U;V'+0O8j֊ =;B0Zse>@}s1ea,( 2bxaHt7P1'=}F`&S35G |/ D;QAƆ(!ҀD}W'2{A悐02ְoY<!0n>Q =V½8 YRNz?"^Tqvz_p%`ưy!Zuf{) T q[AUQA{aʠe)pT>V!0 /pn^` -T@h*%DBVaaY`(>F"`Cњd!*['ڲQEQA "ѹ-Xv~{!'o 5FKV6- ufX4Q^#J^(Lj}jv~aY%N%q()B`*(pNt_X|_.Poz݊o3ٵK,L#Jߋ\2Qjnf\oQ#gy # O "z_H]Jz_>c uURӯ݊@l(F "r͌Rxg@9BPЋGC,\rE+rgv8=Ŝ}]Bֺb/-SPA<r@&(\Q _>=XO/(rjn1$`?x|!jWZPA냐ݡM(-e)TN$mHGicI_|+@+_3QN}f.+?[zyF(m_I@e/VJ!Li9?;̀?`1Vi|QF%Pfc/Q5vX?J'>pEZ@*=e)>.{ P,WdllVsDW?p%Pbո`lP,ƖO*hqN/(fll\ Fqԇތ`(F8BPiqPQ8#/rdzvE?ݚ rr:}@YBBB@4Ks`\R<0xh2C| J1txAH4>=`n;%HcxAYMDE״@v' t˶@1c;D+da0痚&!/0xxgqU'9g* Zs PCnLt"=PPj9bU+.q`@HÁ0#W+l[6P}ӓ P7|P\@1^f|0PkE_Pe>.eQګwtN^)M/@Fi@Y6(@Q 8TxCZjvt'+n}!0{&(t{GkEX*6Sb61Z_AJ2!b9 X倊Zw-G6B|[jlVtK#E`p IiĞ{;(9Y *Zα5"p`SN "hp,A2W,76g0szW2MO[ !+L:o HT\xbηr5g­!JK6enoZ٢prwY0C>[|Ws2FP5fl Y&V"Efl7 E8{arư# h@J_>@15a?H4B(T(ኦ0bEbƋ@_P%_ۗn#KHtXۂsbj9E/RC,HCsbNÊ 1G/9"Q+ "\nl&:<`sTױsv+,|"x9%5Cl{g{|`G/[&0c8fеl]!YMzZutG\(N{jE1iCl+ۅ"h6!0L.e܎a̾nG\ jSh~VZf>JQrжBJm0H!`&an_.(Y/~v#2,>1W [{ !ؓUg ]U1F^!3qcE "BG(Vr[ƻWJo(Ckl /xh-nLIrE4(\[( 2Y1;+#\ /P%d2jȋL|rSlWo)"P~?3660kE gEYxH+BĘ8z;:V?EջC?NSVQ!O0n!ThZ3P%C/3Xgg՚x|ݗW,_9z_h[M>+VK\H}x|OC*ut mxӉ\Z_p XZp_,jZR@ _>!QQ*YRj1'@)dcŷ7QA&`L/?B7<&*|uU%0|}pB _._>ο+*yirޑ0VGhrw%=PԹMLܚS3JئdQU6󊲘-Xcz~^%QZ? ^=Tc('>W|"`%O/(ZG"`Np|b`9;Fr3{Bju(W*`Զ=&~rZr+~[L55`h2|Ɯp;Eb1v"QMݡ(h4by@,l6iQ"3)>qC8l97(gf `MyNPd/ 0sK **hO8 A/NyӠ2 )// 5p0~E_[NU(NyM/8ʂ__e_1~l+:W1__pTDO*-Yl4 l u:xN8}?[X0Q(]3%PH~àlEC}&WJ2J^zD%m_> dbŲgZ еCdNU 0>uiQf]^TBVwWDطiWtkpEU@&,wy@"@nP`DBs8KP 3B8hcX6I檠O b+΁t!0)}=0/A\8A,{8^;5T|E!LT&pt;aZi_~B+Bp ^D}&q{**^EDpV+"^y#Q[i-|,K~uT gPcS"`@T֜<|"…;bIFQE*3%LH+ێ#Q 0ԭf2)BD?F1v+4`VpjK O+vH}@DBZ0/D9vGAq{,[D_G6BwZ`dהH1lf"QԬ# #YAnu1ѩ75vb\ `WFHc.XB>jEL6So`~R n F@l*"iЀUXXV7we{CLU "Uh{"-EQ4\Εgo o 9Y|Uh1Z"n90;0-ZB1#:|ŵ >72Q3=Qc^ѵiЛ츆𷛎(5'q\B񍓳8 n W (B]Ԑ4o@Ŗ_~ !}f>u8aQ.Kw(~ࢉD3 (pE XP`AarAD)쾺C)iuv~ QB(a Г|GI|;J J24U0  X|ȁe]baT%0][ɢ>~0^#JiP\Z>f}oұyADQ~! wG7(J:짆^seM/0M: WԂ`M/(rjn1$`?x|!jWZPA냐ݡM(-e)T4\v1y̓i8JKbM/?KE-`~e3QNKwYb^! zϺD+y Io1`!?[슱oލg(Vr2GYD_gqA!r#yJAA8vP7dc1d1Ϣۦ$#Tpt U`:_Zk+!0Z*,+Ȝoω.ҋ;r˒ w/ b B8I)Nڎ>Qّ0 l?~!@k!NY.:(Wm^ ~_`V|Q^%n~(w{!D X| >H w=8Rf} 3T|]]P,Wdm|஢?pρ.:}$^IP(;'`ǭޅ}r#r.P%ZŌM(Нp 9As3h=mf2zk Qt2>Vk wz#hJʳ ~r d)5˹ J1ta_.vK{HX\" s"@kX_}e[i w@q9 `0:Ԋֵ}:M/0-( jAk1ѶZu=" 5һ|]Xt={"򁂒Ws̩+h.8ށf2s`pf3mˡXX]P|x9~Bh5̢bE:tC݋dv{R9_.@zFi, (j0CPcۀe]_Ĭ TZ`v:ۺk3>*4  ҰZ4\_ yQm^ L=|]͠8>~Ro`_.p%@C} ҈=) zwQ8os!D 3Lh9jDMXMX%"s}ebYsolL`B{7D͙^+xEi٦ AMP+>[_>]a#\ 4GTƞU 2LpDa|ïPw &(ZŹa~gD;ごP(ycׄ R}̇+^`Ŋ⽷?D9$p>p;Ba<\r@}i!;B+Dۚ_tSrR/ ݲ# ҂ Ĝ/ 1GC|"Q+ "\1}o~`s:JY EpsC0Xoz @9'+H{#Rf_`?]{Y?j]}ćƖU(xO_^8q?P+҈L^ /mS (vBz"m뇟u=*MUB;ٽ̇_3? _> mR(5lz?MYg@1zQW%`Ys@=o]p|v*uη Xc.cHM9V4 h#pE >@+憾4\G_"D!޵ 0N/"Z,{;LI(rޥ[ \,eԘBjht~Aq Uw񁨠Z b%+r&+Y>ASE p[=5XZ(6YQ+F6ϳy|^8\@cGzۚbg@m2(u.DC %o,!z!:>C}yE*uEհq1^z^U%SU uEH}x|OC*utHTQ8::@Yc}faV}]8ίsR ZN/ 3]a=_a{C@8J10P %Xi<v[0i@ta|X@J' cnov1UmZp;49Ajljl>u@-Tǫ+PU3Gq g/t@^!ئ4B_.@w/P d%@N+Tj`@8:Kh&h ~rUȋpz4E"x|+,< Ae2; ['ׂDH#"V@]l]M#p(~o(~(`ݖ(jEY^+o$*vbxBrY. Q6 ^T`9P@T֜<\p!*tQTD A z1ʶ#*G5PbaˤTگ)Bp1W.]m DiŎ@OVȱȺWd,vG̩*L/ rN/wz(ʲK$qd#@|NP)FmLV$q$a1+ȭ.&:Cs+!4ȹ;iLU5\0腽ZQӦ -T@h*%DBVaaY`(>F"`Cњd!*) ۞#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`|bVжCk&ʂ >6x^ Q;/` Zw(AaԘWtm/9;a(#JIqנ2Pވ `\׀JNFnr A /8BR|Bcp,\ La])QEfP Z(f?Aa@D)쾺C)iuv~ QB(a Г|GI|;J J2 0=U"Ҁ]jy݊o3ٵK,L#J9|(ޤcc[Ea`\‘19nPt# O "_6跑 4c uU$' Ũ!W$ZN߲QjQs^\x~J[8iU /ۺ(~P5 8#RI粡*xa/Ezj<# MpE-x9{  @aس!8@  c<+Ey&*hMm@i)+$ O7&,$UJҧO&hpLEY}/L }%UG Sw0|@! 2q,gh0FG3Pr2QQ=Y)jPliioPP7]ԍ=|/X(+Y!r̳)ȦD2hאJCPַWBlaUJ 2sK˒ w1} H\pz6qt^AV4Eώ9Ud5<:$3{#,t 6e?`,8|| 5@ (_%?p8p3@Q]3JX|طYE?p΁:^I%(;'`ǭ |[&o䁣 J &z& 8n6U&8CgFS&p`w@ElEكnlk9QP`j큐뮐㽽MR~6:]].@`F 9d)u J1t.k{P]/`V?Fi|o1Nipbv֋T ~Bl+-3HB!Cp~9G4F_&`_h-[hgEyg*Vk3zO ϪbB ׻0¢;賧{!({!TPj9bUnE@XLYφ֡C@Yr(܅!"PEOP`ڳA4v/ +@et]Pp9~HCTԝVhlj݉ ۺ+8A@њө1BcS>Z\ϩ'.Z_.a'b.x`s*jݵ! o SZ-q^5&eWN!?Eg Ş{@E!k9(a)-Xh8C)Ԯצ}w T;\/p3D)z;b~UZC=@۷JSU$*_n e1=/೵(-4![ jg_|eyHlv4?.Qc֭u}&V(Xo@~Xpkpw9?}Bm/6>(?&ɘFc`>\єafYwYaG3fH|\kHz}_./-2XA]~ c0}d0U_m[sn)j@sĜ~+Pb_*:P Ҩ931Gu+?z`ݞPo0cm 6kyڠ9ZJ}+@׾hEֱy.?CZ;Y]= >{}V!B\ѶmCaJ\bvB16"jyyT /T i3[ |h9cRjM"42E&`Ys@=J|֐u@+憾4w%#+<;ݷCԊ|g/iEYp" Erwb˵Up!P@)1XFPQ. |]e+Y!`K_,Z4:qvR&O7uLHƌ >`뫞!xQ1y݀ZuLawt[`aV~[Z QISwjf-{ * 5P+}ʲteP" Wk+BPq`< zX i ">AdLڇ̇ T=0QGж 0lE iYwb_뜔`C.E cor<`vk< E(@)dcŧe#C5i~ 5i}k `%1N+UmZp;49Ajlr 5`*~Nid>so8{{ L 2:{GJ!+rZw$Uc/8|<]I'T: Г[s `&B&`ᔕ,ʆ4BSEU Q E 鵏^cՕ "QN}˯P}EJ_&`iQ wn"J{qv!7! ~_̜:bdWԩ(v{LlLhbm11 `X4`F,1o6QFQECP 1mєiL 6 X8lml+HK(m_C`11`<Ų`XTDqa̎ۛJJV agЀ dE㩗ZB3{v`ֵB}؃iLbLA1؈hk xEظ"9iIo+Y DqՀv_ /LD;QA(!' /N]~ $2ְr@]/hEۭGB:'p/N$s@u@<@, lzQmV4 a X=:`kՙRJ,DfN{0AE`XP <0/A\8A,{8^;5T|E!LT&pt;aZi_2AЊ}Qk ~a4<%q_)Weˢe{a-i2Y. ^{jEzaPEBu PA[s*V0D…;bIFQE*3%LH+ێ#Q 0w|V0H=5 RGyGG 0[t%ŧQ}]r'Q+`=sj QANo:/܀8@|NP)FmLV$q$a1+ȭ.&:Cs+!4ȹ;iLU 0腽ZQӦ -T@h*%DBVaaY`(>F"`Cњd!*['ڲQEQA "ѹ-Xv~-~(s6i` >[QcDheRQ ږ~p @ su8a_'0PDCZfP Z(f? /D;6`Z4߯!J>L!zrq(i~Vx;J ~S:V4pNt_X|y_Poz݊o3ٵK,L#J|(ޤccBQ8CnPt" G?5~7+9`1|KC;&OBA"? v'M{/3*C,\E+E_A\e\6B `xa/EG/}z1 y-*H$z_poQ\P݃Q2_P٫-U1o@1cwSe1>lGTH4Ƌuكnlg9|:= !]!]!{{ ҥltU%C R꽗@4b~y| BATxykإ,*W{v3ֽuEa@Y@P[?'oi}jl,2VhlZwo^Q|usWLCz_36fb}ThlT9}(킨 y y;\a:|\m4sZlt)S薺G/r= xySENH# 6`c@2'mN2(a)*Zαih9C)צ |T;)[n^ey j3aDJDf7 ?ܻ\# 87YҸv8P&`?}\@ʏ A2E!GW4=},n;v4Cls>;D xyE[!wxATc>\N,ٶ5\0熚_.hn!F!k"Q+ "\1bdz>٥g] ,4ps.,9%5Cl\C|`G/Rf?` Lg?YT 1Wk4k-4ZF ff߅pL\ѶmCaJ\b{;5\`u<PAV3@gH3r|%Zmk`Fg{~6g%HFf(׫,'\-l5P`OއYCjrAk̅PmHU NJ&mĶ"BG(Vr[08Bxvzo= (Φ^Zӊ`᜛EŖk<EB&[/ SHc8ο!Jr߻ *=-X ;+V5Ey:<!B?UL-+mL'<{W >0K{b_ ,/;<7Dvy_.0Q({C@8J10P %X=l1L/L`X@q̹ cp@UgVMZVԩCOVg]~_.(xP~\f✽^?8B /i}DqO"0cairޑ0VGhrw%PyR&&@On)h%WlSy *Y} i " @b(62݇cQZ?~pz=h``A|徺2@$ x*߽/X,y: (}v!7! _.r ̜:bdWԩ(Ul6/ߋ)(\Qc f /8ҘNr!Hl0\3cZODQECP 1mєiL 6 X8lml+HK(m/@9Lcc;[@eL,~7 #fΠ;AɊ4!S/9Nvώ̺\Y4P{0 iPLci5( 2bxaHt7P1'=b%k>/D>Y(NpTNPM/_. z_@ M/LM/2ADSLrҠ"#J\C\ Y'd9 WI:h-%"^Tqvz_p%`ưy!Zuf{)10'>~^:LPQAu<w+g8 *`R_8FCacy j4`>tߺ :ۭi̭߳׃ {n P8UE8i\( ~bx_4|_1~l+:W1ϝ'zV!oqbSaKSWԩpk7a:jE)Be(7P:ؕQbDғ *m@(~0 Ov.&Z,x]{9U)iHQ+P@HÊ4n(P6 V*ܛ߀X R7A*ܠ:"…8\h@(}e@KB!~،Mf8ied $s6`%Z>Kh&h ~rUȋpz4߀̘*"P&N*8uy-H4bx%g /4Zn F@l*"iЀUXXV7ʷQPf1e|h¶'ڲQEQA "ѹ-Xv~{0Y|Uh1Z"n\0;0-Ey+{# f;FpV0j+6z0v$ހ]8kPB(qrv'gC@V%Q}#7@|QAV@Ŗ{_2#!  4µ0L4jeIBn\4h`(Z,?bz_(lUx Fv_!B_>`NP''g 7;hECO/`:|_`"g@Q]e~v+(fn.s3(Q}}#@aF.&Dňpxwtۓ)CD?5~7+i̘x%!|Q亶Wkz_.-`gZ{/KC.'NB~cob3r;bN; q!^tk]WPgxJLQ<|{_.P\IS6$`?x|!jWZPA냐O0<%ހ .E@ ™+^-͌s W60dgŬ }%UeG Ay@fZYiRGy7r+|,F9Yt۔Wpd" sאJvH\Vj<WBlaUJ 2sK2˒ w1| 6 aX@*\a-6llH"nK`N28~r /I\ ^0/(CtY8fbOݔ}@5~L,. Qn%_m^(PwVr]/|B#.! = e)>lFi*| sN+{3 `ǭ- 2rP%&hq>/3v7U8CߌC4`\xն.0{Wӭ9-,/T!Z 亯"UD)]F hW]fcM> 3DH^P=/zfCX"4P}48ɕ Pw?[yw$Z! !83 ateFO\Yw\:ճg*ZՊZU Qί{Lt"rAA۫9t8|Gr=Bf"|6ضmxϊ ֤"P 8CD>Txykإ|,.E2;rgw'^Ea@Y@P[?'oi\/!mQwo^Q|usWLCz_36fb}t.:>kvAz[ҲMcz^8 8E_wݫ#\ " @9@Ԙgu+dX= TK0cAH5+?C]ZR>;}x0P(yk~i@QH>QM0,Vd, j!a5$LX//-27ZGqW5 *ho2! #+rlۚ_.sCM/LW4Kky@}X5\P(}^FyojNRs,|"9!C7d}B:dEiܖ1wf?`?]~[Tح;u>p^P+҈, 1D" m۸Ô2(vBz"mkq@>0*MUB;ٽ̇_3?j@hZ!6Q^MYg*@1zQ X-)\-l5P`O[WDm*"QkUȱI@ȇ+P(\17! 䪘=I{@ qUT>Y !U+v% w%+)ݷ Г[s `&B۔~_Jz_eC)mŪs+62!le#f&W+D_2 +|*8E|f 27!a c4\m3/(%*u{} m=&&~hbm11 `X4`F,1̘VCUHTSwh0!m03XA{# -~`~(iLy;b!`?/yA vev܂5:A%oB4`/:Y9x%ǩW6VTYך+ c3i3|(.xu@eȇW$|CƨXvȇ6v3Qz5ਤ8 2 @T2 glh@ŬI!aضſ<!0n>Q =V½8 YRNz?" 8{[!ays VY RJ[ڀETHi/&`ڻu3iUH~/=U"c4{(&=oA 3{tZo^`1~u"ъnH< ؃ e֯*yR=/pWLŨ,ixEN}̡s'"쉞U[TiA u"pڍ`ZQ8lgJA <nr5 (1zI|߶mwn4<-UDv`g̩JTLCwWD<2i`Q޸2@AmQ W8BTUXp rg(*-gpa3^6!JHCcX6I@2g=C]{ہ.LQQMYDQ[6 Q4Bt</5`/di ^[bDhe`zw`>b6#8/*M||1?v~luLjN4ЊFyEצBq GϚGjN ص);g;r1Um'rk top/˽/ Bg>9ʵ0L'Z{#2Ůa&(>r߷܀0Vi~b95@ GF~8pWѦ-u~uL![}.L&drP%3=Z7ł}F G3#_rmAs~AfG1^/nWӭ9_nh>rT)XZ{ +oFX#.kZ/xc.@fRC){^u݀`e "wJypn T}կ9<@ֵw*$]o`N`&Sp~9[4F_&#w ⵢיCF>r[}{"0t*0`WA?HAAvLPA۫9'?}}xK۰v#P>'Sfc"uh))bTa~ A1~,3f)"PEOP`\;t7N^)/: ކ3 8[E"]56IAߚQ<%o}!<ٶ` @l?GMkq=w.sJ{ ZBB-Q}_0}_.0x[<0/#Q/Z w S觿_#n2+*{Ea3f 8(u=%L *c5kELOy]&<6K4uy6lL0mHoQe75 @E%b]yVV0^[6Gߛ[\@y˶.fjvS$~xE2@9@i3غ~]"#,X ?aᑢ +_}xxl4  %/P~/pM1( )> rS~u`xoGh1`ې0/|9ʟC\i%d= X/жlP#ֈjy`_.4ֈ2Xb*SQ#C׈@EXgW7*9xD5>cf6g]٥k^LJYx EpC0Xo(z['PίSzR?l ֋2ˍ7coJ$ ߅S^6@t<kDpP nġDmL' ]n|#@ %Reb`h |_&׿7L//k04ǜp/wc50 >LG0)m0>fSئiؠVZf] ±ճB9jE:W 0fS|6`F<0_N?X2;nAlBOu;AOG㮗^ vώ,\Y4}]4@9RLYCD,bt^+2 yIkOzs;2@Cӌ^ 8*ge L=@7aшtЈr _._.2A#ӊ债_Њ[GjN8u Qgk`2x-餭8yXx8kAsTe  [[0X̔t/PۂW,zDfI{0AE`m hS4̃}BJU 0TG`mq{{8 X{8V$p6yrLӀ=yQ~^EP7F_.p[LŨ kt^鼢9TD= qkaTiA mF8@0NaLCTzc td';!P:ؕĈ'A4w_@rGOcL4L]O3ETyHQnxT7Ba`6ߥOӮ(i{8`U¹ 8Y-G5PTXQ_8/Gf)±χG*=J.cۧM*#؊} s/c vK76ޓ#.%|#bHV"il5nՖ@VXbH@Dѽ`aBZn%5Uh uh^ i cF#!r^FxŹiq$a1ȭ.f:SLϑfe`,x]/z߅rԊ&,6mէ|mᦒ—+bwot:/4` +~(z32EE9v@ňڲQ<D.TNk o 9Yl`}*4V=68|lG~?B/% ԀPvjv~o%Ow)M׋]/5'v\Bx9?J\DS8ꢐ[QL-~债_&p#}r- 0>gYPDC]$y@>+J&j}1i/(*bvm'h @u7p<տ_.cc- 3rqt< Qݠ(lE~jxn)8W֍r@ߍХt Z<oPxEh?=5˹`U@m : X mE+ŋgv쉷 {f_W:zXKT<e4=<@ :*WԂ_ `򀢤 `X)q$`?cܾkZ<b3`q'RVHo@M^.6-F2/dmcI^-h}g L9YE뻮|m>r(_I@"]!?-PH Lq'e0f{CAԶ\LyQQ=/8SԠ9%ޠn{2kLj"܋nx l@UaqT)71nƳM`%Ė/bSzLd.^ Q &}>6'RPj;L{3)*{G*dr L[΋2%ݍ=~}@傯7 <wX.#?p̓k@HQz^\t'>p)j*2}68Rf{ 7TsJX}(3|஢?p.6}$^IQGf qx8L>PW˹@@Nhq܎/ *8CwF>1<(ۂ.ˑi9Ƌ 2 nr[F:]L3BBm^4>Kcw;?|$ELRj|K~(x B؃j6@Yݸ2h_s Bl/- ȴB&Sp~9[4F_#u;>p=@+^+N3}%6[5h- 힃 ]jGbTʢ(@чێ*(y{5ǒz*xKm]`V1S+S@)31:rh1*0ދr(}݅)"PkE?Pe.`s@|^$Ӎ/~шr:SV%/NiȢ/)m#Q%ݜw0Fl[`c GƦ }ݔr<DWSUS/JsR>_>PHϠ}8>~e>b1w#g \ P9P$Bʏ\d#BJo3.V,m-0#}&^gB@f ZG qGs@4c>||`~B̹Si.-@,X\0}!*2:P> 93S-<.u_z}`Pl[(km1Ī/}C۲=i}"<`s14= ʕk޹ZMպz[r4̯ߺj ?^33{ 您c S| W|9+ZݰL\ t߿m<.k@ @Ӿg4_+-Ur%a(mk`>Rç,^K/ȢzVrY\1W {8^kHst -h+df7\9Vt h'p#Je!b#W }ySX("6LYxbZQl:|XwwfP/CW(~PT.dr )b ]h4:8xwhqZ ["3fķd|\mg#M:.$b7+)\+2m 7ɫHc׵jywt 0[ @_=Hs P̔ePE: hEXg՚}W,n_z_>=-VK\/P_.ڛ,ݲ45@t mxӉW6[ոô,L@s;NY~If @ьg%u(} DG]Ѧ~PHmeb`h _7<r F5<\cN8 Ɨ;HQG OvQE[#Zs63æ@{#+-(yLy;x~soP#V!f 0/8FC5p㮛D|[}hmsKʩ*2-a~)aAQ~xq/#)m[\S1+f^鼢yEs}݉8*{'`:})`TiA mw#8@0NaL?0Q-I@`W>#6F P;N{Z е;SdI_u;ڐMyy.t]4 V*߀X ݲ/|DPU8AuE qgP 3B8H_@ 3|ied z爠 bHsrۧ_B aK՚=ٱ?qX"ip{j>PQAe2;+5AaΕ2|61lH)8{/}LW` \rFŷQ[ {Ln9\PÜog ̺ JZ:{*T03: h9yD"#fBDqm ̢K)L]OJ J F`[af2)RD?UT7@wP:jY¡-(>Nzwak鉢{ELҽ%5U@r@۽ 0ӰƖ!r%k Fxm3Z)-5Hc6[]tj F s#!2UI׌rXf F/lB9jE\6So`v{ZD V Gj;P7pd: Cq?T ZUp;bDm(|D@ "ӹl,;րgBxmE v.)@~"S_.K{#Z V0Z+6xΎk8 tX Gz, XR( !. <|%`B>}fk #HadNI02`N} ԛ)BO.^Nm%ro+)R`*(ʈr"_.tһ+x </ 3|@Q]jy݊ok '>YGLs㑨r@EsEkPL.o(F^UVnPt"G?5~7+k٠FZR_.@wЈr7(i"S\@|m(F "r`ܟcx 0*M\ЈmE+Ō3g':B\/}iQ/nÌrAf\Q _ ֈEI^ޭ"?۠}V(>Y,.zG"E:4{Iش3$$ֈA/3|f,z"]WXts$2̃R԰~\#O(}ru"@mڝ`8"a=Q2ۣ]j8}X}(0V}D[?p%Q#Q38nԮ^h/p<IbQG{ C-hʹxж0{Wӭ9_nzT(Ssv@uWuM82OR6:\K|H1&? 3EH-^/nՌ "qgvdP_sQaO>@%bvVa /5]x/0S_.#w>C@ _0؄cAk1m^#Pj ve4pE z9K[]Jcf32>0#C/6^sakP7rPC.DL_-/s-v݋dvN^)/@tJBIk@C),'Vhlj݉ cضxE?BŒZ" v:հm}k3=*46Ucc)q 6dz^ ,}x0Pʏ B2E!zGXW|ʱ.V,m-036$L^A{LA[H!2bD9rm[R*9`~bPr}/uT_)F(/Tduvur}#AQs;f?L59X qiC= ouu Ed:dEy1b -%`jY40+W=]gsk𵚪u>hB__[i.m@T1)_o=/> tGoq˸F4P<{F,o/g?_mRGjM{rA1,zQ X-)\-(R'~M07Psa423>9Vt h'p#Je!b#W }y*f>D)<;ͻ> *>_x0 +7$9"_CW\{(*2[h1.4pd_P@U<28 h^@aBd_>_.ߒm q9r, o07븐Dެ`sȴBH;.$V#E9n_ת ӵ7$:\|u"ZL'@e 3S=\BJٵ-VZT:[VlyhW(PW$ ڛ, T=0SGж 0}eY` X[:RxdOf <.3fwN0ݽ %WC(l4/1Lti> tiX@F+ cLTu̴"Pwh9Ajl~`BᚯЄfY✽^?8B!B ݋>4Y P #`{1A(y^Hs=yf!\ahdQo Ē"@T-"YǹF33 mq)'[|]fg X[y#XGǥ`vprb [0@@36`ԡ|FvEzl}. @_F@k \?oLU=&Fk04_>cN8 Ɨ;HEb1vQE[#Zs63æ@{#+-(yLy;x~97(|e04 l m6N8}?SX0CTzc td''P:ؕĈ'A4 a~[nilyfZxD})v TC-+<ՌrǸ;X{M"wQ-m2@Am:jqSn X&5PTXQwkCsXP 3B8^6ᑐ0rͱ&\Hl*rQ gpA4!:nҼIeSs@[DYx>Ю9WuR{f=\)"ro#еjl_>%@-EDpV+"^y#S["y-|KuT(z^T@/ VN} hkNEFQ>fBDqY̢/ߢ.q_i8W1G`[af2)RD?UT7@wP:jY¡-(>Nzwak鉢{EhBtTh u_-^3 {alو_A߳CWd (S;#Gm`fZ+25f{Iyr믋Nmhzs$$n9g'#JcB^ضrԊ&,6mէ|mᦒ—+bw?>t^h&,, ǩWPfqerh'ڲQ<Ds&Xv~a{!'H _ڊ'B+얂 ='2UȱbI15`/cD%C)icYf4߷JB V|-/'"/ pL'@UEN3K]j݊ok '>YGLs㑨Ҡ|(}P&7G#/g V视^se/?w#-t)/@wЌڴQ)pk 6>G"r`ܟcE(-P¦NVB~h9cuQ qHL ULZ,U!.ă o@=y^|\ - wJ@f\Q F6`w!`Apv$`?cܾ-Ey&*h2`q;REy(СK:Ŧ!%fͯ߻O&hp̔EYn#7TYGh Sw0|@!iSP8 UȽȡmBhG਋Z)jP|miioPP7_ԍ=}cD cEOI[6 0`p 8ABUٿ&0b7EPlBW69ߞ]~J/ZXԅ%v/ ۀ!]]Ԥ{ @Ѧ{D JmiwF"E#azXRL6\r_t3o &zk )|v xgl_xBW )8Eq@E{.et>CK F*hqK=:z@(|B kLxZT L$@v@`èr=fC1Mcʹxch .I+֜M/7=x)XZ; ++xS?x !cM~@fRćR/^5݀`D. "br%Ƞ'-TÞ|-KKł;2_j^`0:?\G<Xx:!F>rp6h- 힃yxJw`*ؕEw;)(ێ*(y/K[]Jcf2>0#C/6^sakP7rPC.DL_-/s-v݋dv pW "G3a4>hPbP :-ugƦ 5x$J5SpWC_6a >fb{ThlMy,pJ; ZBBji *- tO\m]>E/$GX6@~# 햃<P&`?@3^ld9j( )> rSu`xoGh1񢪀/P=GT d>bSۇFߑB\i%d:r,ڶūm_sC1S44|@,X)F(/Tduvur}#AQs;fZlnc%kY ,"x9%5Clce{rx#SL,X=fеlqnVS`jݑ__[WT )?SI8{b\](_o=/> tQr׍b @ JK,o/g?_mRGjM{a 2_.(E/v#2,>1W }*㵆Ԯ* a8ȱK@;(+P- bn--b#ϻp#s+|)a|ba/P Kqk<EB&t@-EL sG}DklG6B-6@iYhm q9Rhdw7u\H QoVRVdZ!xYQnW"kՌr fPȴ:\|u"Z஬ LpA UdjV(yZf?̢[Q[^jMܾC+RPql/|[M=-VK\}c=#_zpTfV6o0= m(un) 5= `6S _>2`vQrE9R(ƊOQ>e#Sti> tiX@F+ c>Tu̴"Pwh9Ajl~<Ph1cZhB[WPU3,Gq g/t@^!!?Eyo(ir0VGhrW|R&&@Ob>i%W)7`唍,-XRW\P=?dhd-PNw\L`aAeܺrAd 7x*mYlV^;VqAQ-aݷ /b/Ќ/%u(} DG]Ѧ(v} 35_.ן7\ҿi~k04_>cN8 Ɨ;HEb1vQE[#Zs) `1"Exo)FnMK)!Pi-S|ޱ<~_9` _361)[X &Av``2pqK]Z@gG ]k,{h.),@!ACl1:/lNg<%ǾXvQM3v3SO@lu*9@(!Sr@4Ќr*gD/L1K,/LM1K,/Ð>6?3-[G =V½8 ^RNxuъC*LS3\ X0uc V)^ VB8NtjD#{жV)pT>V!_c4 0n]Pp19 :sF#o[TNU)vyG]`a:\L oq[LŨ kt^鼢9TD#lZUp6uEz܈q'>v)g!*ՀB]2 ؓ\ (GbDғ ym?ڌT-7|4<3ŞVt>YRM*!E]ĎS/y>$`~>M@U 7,gyxfV*:"ʅx`pϊelam`H:)cUz0rͱ˦]ąGGqG}(aDG!;hBt܀#'y/˼怊8t'2qrڕ 0JNj/q9,g "V@ x1]M-p1P6((`ݞ(jE]^5n/(aη.!.^P+Ae ؠ:(i'Tl_>`V.DK.f,Tʄ[OT+ۏ#Q 0ԭ03l) ;(il5nՖ@VXbH@Dѽ`u iX 䰎"K{@ 7`a/-1!{vі7;}sg LkEl# #@nu1ө7-vbZ}0-#d!`pL}s~i0zaQ+ڴAT󵅛J_n >R݁TDyn0o^Cћe)*_'ڲQ<Ds&Xv~a{!'H _ڊ'B+얂 ='2UȱbI15`/cD_0070[1 "b^ѵsv\Q㑚xvmc;Ae C %qE)uQu^_B /;G 9R@j@8+0Ys%K AT?DpEﳹlB֌ATa )>C)icYf4߷JB V|-/'"/ pL'V_!rE]-R_#fN.}hD_2|$ywF*Ŏk\f'M pA<Q}9CVsAQي<+RpeO Х4|A3K8oPhGE­PxEh?=5˹`U@m : X mE+EA e@L':B\/`+Ң<1_.@q ܌r| 3uT#K`/(Jjnƾ]tyEmV(>Y,.zG"EK:Ŧ!%f%"2}GH3SNg+_[, *^"@F an6B 2q,k ]1ͳ{C=Pr2G]DLQkC䴷GHKsxq n ># FVs/}J-زiW9+cHQ /ĸx[d#I+Ȝoώ.?-rbl4_optEwQ].E)(P#`I2~r!|C/܁?ь2ũ_yo}ny4AC]G^#?pe#PW˹@@Nhq܎/ &Ì_.Нp 9(8?PQ9#/ztk&2\e }>rrb[)]FS|{)0 9w2S\J1 t_.~KǻȃX\2Iկ9|Aٓ? t@`L+dao0.)?PPj%bUG۰v#P>V~ .\~v:rh㿿P^1*0~^{/]"2 [)8^Zv)^@N7|:}pW "G#0Ni.!c(pNIy@ A['`yQHkx@0^b9V&Zȣ8>DDcLn+'m؜)<<>V{GLs´#EEyrPAr/`.|{62hۥA kkQZk,SP<~{ԊGp~fw;E"g-WAǽ,D6[nk!>9,@ʏ\d#BJo3.V,m-0#}&^gBCLA[H>wD93hۚ_ZN!CJ\0tB<4ͥ/%}+^PbB /@EXgW7*9xD5>cf6g٥kYLJYx Epɦ 0Xo(z @'+6Sh) /0+W=\gxk5U->|lф2j j\ڀy=sAT1) _>߶%)er!#tB1 /0U]UB=m `c _.,TPARGj~E?cի| "bY\k7.ZRZ05P`OSW5v/b0 @]ډmE9\RoYsCoa@٣D _ XMg\+SҌPr\n(SR#it~AqUȻ@㚯8(D!`g 0/o6OFw7u\H QoVRVdZ!xYQnW"kՈ KG5A̋P@[nޕ)u.HLC %OڿnEm> jMܾC+RPq`< X]i 0\y:\!B?U-+>mL'*s9k+a{&`m~׹_g,?j#8ך_.`3/0pzt"p`@PE`Aqy=\/`}@qgp{AUL+u&}&w_BlQзc9S=.yd9%+ĺ=py`B!?{*Eyo(ir0VGhZ%=PR&&@On)i%W)=\,-XД~D]Ūs(AF֢qnz L`aAݺ@d 7x*mYlvoY@kM<"^#5 1/{YRB@|$mw|Զ{\&v&|qc11*`X3<`|X$6cY0(hUdu8PL1m)0G;l 1r[ *P^J rǹ)j7_>0?\ì~MyNj`6! [{bz4w4)?\Y]h=(r !6LqEsړܡi;\4c703ŮWJkqTd2 "rAN$OehqBŒ/ <[F "B:;p/N$@:^b]-Po SԈr+ }tL>֪33P#Дf\S1v+:Wt:crlG؄E|-* 8[DMn'>v)g!*ՀB]2 ؓ\ (1zI@#~[nilyf=})v S`Pjy@vjH]Ty Pq[#ZŴwxfV*:"ʅ8|3Ќr(*-g pal#!afp> lUdΦA8/mp|aD0A\8A,{8^=5x( χ 2qr{1ORK\0H)8{/}LW` \rFŷQ[ ^[z6@1s5S _>@q.\]/*SXDI+T> 5"`#(@{\ (~;GTDLA z12#~T u+ [&E j y[G 0[8t%ŧ)R.c-=Qt(XXG,*/rXGgua/܀0l/A߳CWd (S;#Gm`fZ+25f{Iyr믋NmhJϑfe䜝<*_. ^׌rm[(Gh‚kQ}J n*i |*HM]Jt:/4` +~(z32EE94eaqDm(|D@ "ӹl,;րgBxmE vӻ?B/% ԀP fܠNb^ѵsv\9t ^h E_6G 9R@j@8+0Ys%K AT?DpEﳹlBֈҠ`0<Fv!,#4߷JB V|-/'"/(L'r93uݥFڭ01priE{ 7{q띑 GjnTEaߞS8 =M&%O "_6軑F 4g mW5_Q[#^ih9Z0BOOͱGzp>0*M\ЈmE+Ō3g<ۆXR\TRE j{2k}r FVs/}+߂-}Ur8vT)#b*Vg|KތA 0 2۳KOE blŌr@z +:tr(tHA0Hx:L9KkyuH@>x^;2Ea(> o;qnyܕ4@C=p#/̃|p<6r/|B#.)^ ^~NigT[E_=mzoI|HGf qx5\POy@@?qh}3b4#s92"xѽA[s6ܖ|SP`j킐뮐mOR6:r{H?|$ELRݗ@|(.6Pow=q[}Aqb ,.W" }"@[^{Bl/- ȴB&Sp~;#|^fb{ThlzD6q.Vz_> *##KHT]ˑOl Vtc\`_p%@cX(lR u6p*SKl W|9jDX ypmgi @Ër'm؜)H0mHoQe75 @EK/`.|;\@+܈r@=EiٮLAMP+^[~_.w/fw{ruxE@9@i3a<ŵGX6@~d-y\P&`?}\@ʏ B2E!zGXW|ʻY²/}&^GۇFߑB\i%dz.r,G h_~yu3 - ny\|<4ͥ}]k17vZ"L1,^`mPEXgW"\13Dm|=uOhZsJj0n G /&XY6s=6_Zo0WkH-{5ZG l<s d_.opR&׌=a CD/}؏e49^R0![_.m˘ 0iBM{a 2_(E/v#r,^E >uZCj׋rA[̅ѰWZrALp#Je!b#W }y|PElwwxb{̦#^{n haJ_._>p]]Pr\E)b ]h4:8xwqA4лф#Fķd|\m+ ph1@ԛlVi6=PnW"kՋ2 KG5AP@qWf-{ *2 5P+<-kkt nkή{5q=HaLuEob5Z}3Z#Q0Rjo.S LݲB#&t2[I_ckQ&`:zh0Hp5<\`v E(@)dcŧw|dF(|AtX@F+ c>؃ :fZp;4c d6ˋҠo 0@5_&uU%0rloCL`~%We!S_@w/{#d%@I+Tsj[C&w8'xuъC*LS/,V:1X̔t/Pd/ 0KK *hO8LA4 6N<*ԈP06=wA )C iq>Ixm4%@Tb{Ћr.0#<Mi+b*F}ẹ5cZ 쉞MS04 l m6N8}?SX0SNjE7PHK&{q]H^zD#߻m󵿿s#짱 v)k vȒj6P1)"vP@c3=~?\>M@G Pn>"E*:")`p_>b!"R|P>6(aF hmX6I檠w b+t!0)}`R_&A X=q0rZSTEC@8LS _'ۂD#NjҠg )"ro#еjlkyo#J[ਭVE셽Fb_(aη#f]B\ 2W8n 腱Au6Q թO$@mͩ/ ~_0+_NU2z1SP´^Lq9C}? GR{t<- @wVȱ(W,VHKzTF EKo:nL^[6_.A߳CWd@ Fx)>2m3Z)-5Hc6[]tj F s#!#-|k+Zl[/LGڞ~xDy`@ Qm&` Vw(AHaXoP~lsVx$ހ]؎kPBsv/'C@k(qa G]rF ˽/ z~r>3q8VaQs,Kw~ࢋD3(gsE ؄^ /#Gw8%mbvm'h @u7p<_>Pnj qL7Wi37G#/g F>视^se/ p]an oʳ74!Z(ZӋr%yE˹ Ӏz_.f]TB\/pF_.`_>=a/}E @=YZ1F/JQ<|6X/(Jjnq$`?cܾ-Ey-F `q;REy(СK:ߥ_0/%"}&o̔EYn#7TYF)Lm @LAe,Xt)ڀ<79@mʄ_ u"_k׆iod*lK) ># FVs/}J-زiW9+cHQ /ĸU5[-bS1=zÒ `_>ƿ$&ݻ\6'RPj;L{3)*{G*d_k o5_]>p;Go0,0~@|fceq?P,Pr<O^`>̃Rl\6ro<+xBՈ`8"a=Q2cPڡ|ߥS o}@%W(|@(|Bka29X} O*hq/(lU.qތ1<(ۂ.ALclHt Wӭ9_nzT(Ssv@uWuW6oħt)_.Re_`>rLRjޗPe^ Bzg;)y~KǸȃX\2Io j;ݲP,. Y؛8L f #|d\CnO[0n&`+*ꃜG upd*Sf7r|3?t ڴ.1Ӂ3-{@=^wD/WZ|WA,(3mf(#Z\oxk!O@j{:arj}JJ_>@15a_H+4-2n#Kt X#m!9j;>S1^g`ŷC\,sCoGWi1j [duvur}#AQs;fTsg)]sg)b{5|lф2\q5 ?"{<ށD" m;pR&o#va`j( c"zx} @V|{Du0![ZSA-i#>glxz/Ad:\P#^}FoZ05P`OSW5v/T\ ՎZrALp#Je!b#W }y#gywX0"^{n haJB(r8tu@˵Wr!P@)vG#{@ZȸhyW-- iX&>@|K)|}68{BB-fz!@]I^GsܾU3,,Df5A׶_RTpT03n)TiZi][+Vp07GZ$.n_z_>`{[.@cF_>!B?U-+>mL'*s9k+a*;>n}ЊZ,=鳁W2OE_{I#RrJsPE`# z☛.Dמ.`}@qyg cVM?'=YM2t_YXB2w_PU3,Gq g/t@^!!ߏE7o7BVBe9H^#Eq4x9VI+T>)uN'4+̔_>,>ʆoh#5_.ן7\r F5z[y r)Hl0\`ZQ߿xDn`h}Sq`|<by@|6k ԶRC`1q`{ gߠg80_f-xS42M?^'+0wj {v`ѵB؃y`Obr !6LqEsړܡi۳ACӌ^ 8*g Ad_.@ s+Ob ЦB/5#n#}V<ٞ}@hibOv`g,a.bU O5\ xjjQ=oÕ :n+|qU@Ǻ7A*:"ʅ/pB(*-g pܛKxd/HH/pp3E@2gS ė㶏P8>È "W yq.Vx HZ/Vebĥi.#5uҹ-H 5"`#(r!*$QE *3%L+ۏ#Q 0ԭ03l)* bBjouCW[Q|nRLcOA Zz^QZ!-XRSU@QiPv{4셱e#9 }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfe䜝<*sJ@c`¶-V4ai>%k 74\a@|%L%֥ Cq?|\v8lA>h υ\y _}k^3WAr8|lG8)FĽM^(Ljs#J8y@+R-] mgYPDC]$y@>+J&abmLU0U_.G #pJڀyX9gx$Ro=x94_ H7;hŇ"_>wWx_>+D .5\n7ٵK{,ڣm&׹{HTiP\Z>f}yA<Q}9CVnPt{2e视^se/?w#-t)-65@w47(i"S\@|m(F#^ih99H/_g Ρ: X mE+_`GobI; q!t4|X֋Pp4/P:h@f\Q vB_P\I8Sd٠ OA97p1ExKQ|  3E;X\TD&t(h2wi%̌r+g,z 4 }&o̔EYn#7TYGh Sw0|@!iSP8 5]6h0FG3Pr2G]D~(6DN{{4w7(HA vO&xp_Q6B{SoM*X9C:*EPl6ݦq6Vg|KތA ]^ @|{vt )haE Pl4_op4(RP=EODoQxD[:K _.kn9lw1(S\u\A({|[Y|N>\x5yW>`>r̓)YX/`#׋+.Dr"@NQ|"g.ep@kqK= =*whwKĭsH몣(>20S㶇dbL&Zbw?@Vł=#Нxlz[ˑi9Ƌ 2 nrsWu@E\w\wo@|Jx ~|$XkW2S\J1 t_. xw1>ypk+@>i-Dm=Bl/- ȴB&Sp~3|]</C+^+N3}%6[5h- 힃yxJw`*ؕEw+RP/((y{5ǒz*xK;YGL}Sf :rh5V(^+~(zAb |_w!g4T38@E +CoA|^$Ӎ/~шr:SV%/Z!ZE".56؎Dl[xE]by_#f u/ ٶ.` @l Maf9S+*FDwry`_Tk9R3(gߥ&ΦOjE=u&.Yr 뤐 xm :G8ow)D 3\r|3?c5'"G}""1Y&x|oE} {{@6pȷ2T}%UEK/`.|;|VA=EiٮLAM#8x;"ճ+}^ ŞUmr<2\p<‚' =>a}^x b6^G( DGb#Q[@QHQm^`ŊƋŒ3T z_-2n#K} ȱx_>@֌R^/߶sn(}/hK _.K.V2/ A_Lήn0Ts"Rç,"bY\k7.Z05P`OSW5v/b0 Z@9)xB,Pl䊹0{ [Fw}XLU\tba`J_>@3]}+@Q5ܢP@)vG#wTf ;\oy@|K)|J]@ܽ`n q!!3 DYIZivh{ubds??6kՈ fPȴ:yh:"B2z̔ePEjevmZ~Dmή{uz^}]g}j8_X=V/q:|C}R, T=0SGnDcEf` X[(un) 54Y P #`{1Jz\r9MLܚS3J0Sz Y} yxE^p>@ Cfo0E4W;U`a n]y 2Pn"`# <G-o)D#5 1/{YRB@|$mw|Զ{\&v&b9B9li~k04yǜp/wc50 >LG0)շSc)6ОG`kco)FnMK)!Pi-S|gGyA/80;<^'hdna50~ NVa1zɱՀ[+hHk͕zOE#ŔX"d9^t6ncNZ{[F{uQE94 L=U}[0 _> Ð)@4Ј*gD/NBL|`h _2A`2g=`eH\C\Ԉr@q !n;RNxuъC*LS#,V:1X̔t/Pd/ 0KK *hO8LA4<6N<*Ԍrh(v`ܞNcutZoq8^mn P9UEi4|Q~1\Mi9o1l+:W1C9Er#lZUp6uE݈N8}?SX0SNjE7PHK&{q]H^zD#m/m#짱 v)k vȒj6P1)"vPjy@c3=~?\>M@U 7,gyxfV*:"ʅ8|3Ќr(BZ[XN #}%̌.cۧM*#؊} sam~_>0A<=qX"ip{j>PQAe2; _'ۂD#LjG"V@ x1]M-p!~QRnOGm.b/t`_.(aη3f]B\ 2W8n 腱Au6Q թO$@mͩ# _.0+_NU2z1SP´^Lq9C 3ÖI"^Cj!OͭGB|Za" 9Eu iXŒh ut9h^ i cF=;xhKP>3R|d~f"SX[jǑl hzs$$n9g'#Jf Ƃ׵84m MXpm OɿM% /WXE7@|*"ЀMXXV7ʷS倯BqDm(|D@ "ӹl,;րgBxmE vӻTfB/% Ԁpo-f;FpV0Z+6xΎk8 tP f8_n٠F)H}f>cp\ ̣fY,)QEfP ZG~Z#Kˆ@@0\:*WԂg`5|@QRs=w0 6(`0ExKQ|G *h;X\TD&t(h2wi1:fHGmcIe^-h^!w03d{,݇T ʼn⪠Wox 3D+䇹 IYv7FG3P27tYG`%twZ  -] + 'V/x(Y!r̽)`˦Dn(5 ǐJ,$_>Vj<[BlfMY69ߞ]~J/ZXgPd.fۀ!]]Ԥ{ @Ѧ{D JmiwF"E#azXRL6\3|Cҍ/1.Fe P|ve_{݀0+ ib9zGn#_/d#y!E] l_.G])W(R T7) *26 u)=.u(V+ v*| }M-{ssL!ߐfdrA& >-U1o@`ר2=p 9ʶ9uyi]myE?ݚ 嶌#2Vk\w\wo@|J>GB^4!}9ćR/xAHs=^0nAqb ,:_@E9n T <6THޚ]"Mrh)? GjEIw^,'Ukk9@MxWkכg  vet.pE OWԋ VI[]Jw6fc2">V \v:rhV(^+~(z^^{P x LCů=@E {]ʢrW.?ӽ/|~pJPyF)ԥ7dLEsi @mE Mڶ>wE7}= T׶ >fb{ThlMy,uJ ZBB/p/0x[<0/#Qmlhu6RgݧO[poz+*ꃜG upd*S9V&Z|Ԋ }""1Y&\s6g ?O } {{@6pȷ2TJmJL?_b]ld e΄{[xm-JKWnnyse-~/~\`vS$~ "ey Z̴l E.V{,X ?aᑢ +_{>pYD9~gBK XYtm]_sk𵚪u>hŸp^ {ǽVyw 恨c S׌rA|v!0L{:_.0U3hvUyk $Y9_ΰԌrmk`>RϧmV%LoydыrJhI0j@=J֐\Psa4T;RhUȱK@;(+P- bn-C}V2Rkɳ׻;1E(Gq6_."Zܽ;LI#9#"@˵Wr!ELSH@GŹT# TF ;6zH`nYm[G(0[xô,L׹_g,?BHsm0ˋr7sPҽw|0AoPsϥϥ1ׂ`Yc3^ǠLTu̴"Pwh9A{Ϝy8:/|}`*Nyd9s>o8{{ wBt#T݋>4%PY X5b)/J]9MLܚS3J0Sy Y} y"@T-"Yǹko:3 m{)'[|]f_X[y# זx$/E|F}kA b)l#/Ќ=\`ԡ|FvEBj[ŏ.{_F@k21eWk0Z Gsi0F ,1,*2:(yxtvhcb#ŷ\#7U3)>sSo\0<ì~MyNj`6р dE㮗^ `觽0W=  {Zrb9`h[ xEٸ"9iIo4`}_rhb׫G% zQ8 2 ~@4a93 " @tw$y,@a0/VHqxЃ.!.j,܋2x-餭8yXx8kAs܀^\ X0D>֪33P ʞ ؄E@A Up6uEވq'>v)VTnK*ՀB]2 ؓv#1zI1 T-7|4<3ŞVt>YRM*!E]GߖP@jH]Ty Pq[#[ai X&5PTXQG 8/EPh)>S(ce 3\Esl4I2W9Jpmx$}ԇFmh< rMȃpz4E"xy\PQAe2; _'ۂD#Nj/B+Rp ^<]&qq9~QRnOGm.b/72eg0[8f (.]@e p% *SAu6Q թO$@mͩ/ ~_0+_NU2z1SP´^LVLOվM4`VpjK O+,S]X Zz^QZ!-XRSU_.rXGG-^3 {alh }^9\#`O`B̴Vd k|K80 _3xb)HH32sLU5<0w MD)70_[ #(82 ؄eu|8 >.LQQMYv@ňڲQ<D.TNk o 9Yl`}*4V=6r8|lG8^(a^ 1?v~luLjj@+R-] 9FԜkq *S7v@wb(q۫ ڴO:!h7r//r>3q8VaQs,Kw~ࢋD3(gsE ؄P#f?mڂ3HadNI0r P'/'ky9)0 8L'3B/(ꂻK= ׺J`>bvm'h @u7p< RT1W{F:~lo(FT_ý%O "z_H]J/z_>P !K6JkC1ckx+2 -G F9H/_vg0*M\Ћr6b3r;쉷 {f_W:zyX֋PkJQ<|6X/(Jjp]]tqzߏ j[L Td):w P4CAtM1C8jKb/ z u [603d{Ţ %UX)p25zWs˷oS~M "c<79@mʄ_ u"_3E  -] + 'vBeP{SoM*X9C:*EP ƭbx ̷h啀 dηgGҋeԅ%v1| EMKހ:r/U@@)*{G*d_kr}q@W v(>҂mXc@|q,i~b9·`uyp#m@HQ:NZ(ME\(R T'=.u&(V+ v**z ܒ8|91 Pdr&P%3I-/ł =3!@4w9282"xѹA[s6ܖ|U )XtW|WuWuW6oħt)_[=p)Phr)BJ}LJ1|<!'6ypu|7& >Fu-qB|Vn~o0痳ELatԊ~}Ӎ2ѵ&< Zo CꭒHίsyL:t"2@A۫9ԋ &8Άf32 Bm׊ʡooq6x0PsH&`\;t_oN^)}_&@6BI @C+VCT~Pcۀu![3G^Q}XtsWC[HN赢 @l Mjq=b6@zoe#oF[{2|m_ @ȴBH;.$)bq2En|Dջ_Hs P̔ePEj@Ym_f Emή{5qzi jI\ܾm8On@׹fe( )7XzH`nYmo`:Q^-F|˶9n;@s;NY~݅/HTo*2^Զ'\md`Pn)cn/ <XOlf1NU381~Nz?5|=P M֕T#Qb]?8f^Q/@7Q}Sv/ފ_Be9 X5b)_hwR41zrkNLC(L/Ȣ\l#4P)XB-fQLE \6Xx˹u 2| ,6[PrD-i[BoCLa _fe(H4[b)Teb`h _S^cbThC3POb+#94_# Ƙk` |Dj w@1 Ƨ`Z! D"L>{^xKq:i#~E >W60 Xgmc:3SӽCmkq:7<8{Nh=0eЍ6N<*ԍ2h(v`ܞNftUyp~){l=h ՊL+"S4` L2G ҍ+b*F}ẹ5cZ 쉞MX & l m6ucP`ZQ9]3%PH~álŇ:7\>AO+,S]X Zz^QZ!-XRSU_rXGoua/܀زы2@nmjqQާl0d1~o̴Vd k|K80 \g7Sb)|lcm[lBX%[Y F/lB9vm"D)70_[ #(82 ؄eu|8 >.LQQ*P1lA>h υ\y _}k^3Oh1z"n`zw`>b6#8/*M|| ԀPvjv~luLjj@+R-֛[/6?k:97`6T߆C %qE)uQ 8z;EY7RȑRz>v+07X XR( !. <|%`B>}fk)Gw8%mbvm'h @u7p<6'RPjwG HQu;rT!-2goa5.|#W,3^ _`Vru'0yk\BS6r{{P}BՋr;EL  USֻ vA^QgT]E]mnI  G;p@]3|j9I-bQG{<G 6-TT4ƋE^Ol~9:]LBBBy >Kcw;?|$ELRj|K~(x B Wɻ6@Y]DE jյTHޚ]"MRÅ3gȻx׻ⵢ4|ZPbZb9Gz7]Yt="򁂒Ws,h.8ކf32>j%p@C+VCT~Ʀѝ=m%^Gk|EM>fb{ThlT9ջh y yQ_>a:`.x`:XZ w S觭y.<\J) 'A6)lm#;YT|9jDrX=ypmgi @uÈN۰9S`#&9aZ"ߢ rS ̺XQX#@CŒmHg z_"D;wKTw@ڶf#S`~:/0C`<1k17lp/V2jM0ԁ[1@Y<G_"_ !޵ 0N/a½.4|"g9]r}*p!5E?P5V!3 F/(Ze(L|+r&WNa>VCДn8{9BB5f60"QvhrEYIV#D9n_kiywt}0w:T@#Boe=`&Jݲ B"Pk@Ym_fbWk""@8|cbj]Hy|XC*utKWMlػqiYkXb_vNY6TiEQ_.`8|@((R|J^5B<7tw], 7Ccni@tq1kD,8,t˜1lPiCݡI'W&` /jl>uՕL#!+@!? 9U,n`{1hZ%=PR&&@On)h%+̔_.J.ʆ4BS" @T+"*(f&Wޫ+D{_vEJ_`i+*\[n"J=x;La!7!Va _>@93Bӫ-{Q(oMP!]bc./8</<'&Fk04Ilp1'0B``fƠ(H`h}!m03byX8W/U"3)>q@hgfev\49uJV  OHb*ǮW6vݳ#^k,4P{0 i 1!AXcjb׫G%\A8^ywP-qxh, _>0heBĹ0d;?tZX0Uz℣Ӕ i pL"N'[?gq/bYpfAs܀FVf +Q<(^{&4'~QHi/&PT7 ؃5PPiL}L! 0L/8F`mq{ނ{8 |IlTriEnYR$]Ae<|@F_+bO4ZcP}̡s'EQ=8g8ZNS+Epk7a:ZLcIa(۠>,#Qے@~R(~[n4Ρy&=}!2 PbUQb# i /pEXx7" ?6@N' 2g ݲں7A%ܠ:E qgP 3Dpa3/BL/9}e)sU;G؊}:mKha`^~rUȋpz4E"x|@,< Ae2;Nu^ *4bx / V@ ]&Ђ8(į}QZQb/7-v1 s_.01Pv. jL:~=( PA[s+yx"fBU{wQJD A z1U"B8F`̰eR~/bHV"il5¥-(>]a݅r' +{c=sj ۽ 022l _>g/?mH#cl0dmjEhǑƬ :P;bZLlPT%'W B> CD)70?+Tozh;P7p$:/4` CvMPm"09Pg~qymqey.4D-nkPl~,"9K1Dؠ-Q '696\P)fQm&`/}od1 7FyEk7fqHml5P(9;݁FS o:*W Bck߂a_'p%`N|7H40Ӏ}6W*bS / S偈"쾺C)ikYi_=CJBPV,'"NC_ZLT2]Wpr_!rTo_gQ̮]ɢ>f} Q>Ŏk.R1q,@tvE~j+BpAХ]B /ZA *h;)DUPK:bbt̐ƒ z s W60d{b}P|%UG SB~B> @e,X Ƚȡ~ ʄ8RTϻY)j ~6DNiio \ԍ=|/ cE l@Sa9"B1n+VgJތ. - s=;lJ/ZXP^lr6 AG+:EMw*tA5#" u;rB&O?tlٻ*CtY8f1'?pve(~~L,.|܆z(/̃|p3g|B+WJw\ PPA[(6 eY֧p$bwPx3Dqֽ_@(@)A1o@-1cר2@1>ꛑ?p!(nq^(H4K9Kd2zb8|!u+ n\By ҪltxQB>4@!BJr_:;|{S' DaOqb ,un<"@N?*kt5ӊ)dao0痳E ateFъdEiZbD93Qz7]Xt."rs z+.UwAec}3e`F>!CC=PbC9 "r(E8CD@`rQګwtA 8zE9a®E (~N:-(*~Pcۀe)CзfQ"#^p٣5Fa+]Qz*tHf>~ \s-ki`  l ogݧOkE-<<`%@*GENH#lUa3h p(C%;JE9V&ZlwjHkӾDcT;:n_Zdb^@qWh}D9m /[L/̶r4\0E4jyhy`zM/(:[]a(xDܶM{<]~`P[a+)b-@6^ 1M&0cpfе{k5U jMl>E^^i@kfal%h>CaJܛǬu2P:ah=q@>0*f-40ǜEnW3 *3mp;4c l s<&BrAI 42✽^?8B /cyWTY Sfƪ!?/*R61zrkNDC(Ya@TrQU6󊲘U Q \yyF3UiaA|徺2@$ 7x*mYe"wb[ vprbZ h_.0sg W[_QԩTHm10 m/ߋ)Q ͠<8l97ZyYm)ϩT2Us ֧NVa1zc׫VTY5W{=Ә{Z | Q1^+T1'=-qaEYJff*K}k0rAQ̚_. z_@ ⡁_>eBM/#5|˄_.Ðia9{#Ѓ.!.zW @ȿߐZ8& _-q8F^ŲU/ ;'dNua w M2J^zD%߷mߖFa?mshbOv`giFUqLjBy+»QZdW-LYeeBX \Q 8 /0ž2C@E Q!~،RVH.cۧMU檠w@u!0)}b`^~rUȋpz4E"xy\JQ 2qRY:AE1<~_"roEt5kyo#J+uDpV -4vy,K թߝ SN}>& {U*T5' <`.DYw'!L^0#QܯsQ܏j 3ÖI"^0![qDu tE vwVȱ6:: iXrAT::|o2nDK+@ dn@2-YC-n02vkCkfZ`;_Ѭ# #YAnu1ѩ75v@1Ĵ\ `WFHc>`,x}m Њ*6mŧwgwGfQv"S3<ЀU(, e D`s *y"- TTBHt<_}k^3Bx vy3YAX4Q^9Gpo+J_0070k1 7ԊFyE6?k:hN ص;g;q(;)jDQ vQCxrK=/8B# }p- 0"?+s A?DxDﳹR XP`9@0Ux #pJڀiZ|z(!z3Г Y>Nm%EL*\E]Wp,~_.(>BP̺;lKU3ٵ 7>YGL{Q}F{q`-v\1 87m&(Qj&x" G?5Nn04tx_H].CPV0ByT$'?yuH4e3hQs._J-PZaS \ͺ(B\ /pF_.`_>'6Ŝ}x@yZeTHv\O/+z"zn/0qAmP>`(>A *h;~?eBpx*he%vi1:fHGicI\K^-h^!o0d{b}Pཊ^gf' 25z+䇹 IY?+A[1ͻ{CAb%+ ?/8RTϻY)j ~6DNiio \ԍ=|/ cE l@Sa9"BƳM`~%VoFXG`%`Sz: %v1|  HъoQ].:'BPjwG B95 :$r-{#@eS  ^>|<Ͼci4P|r#ʫ\,|r̓BYX/`%J|Wz"D~(}68">1(>0EPb"cϨ򁻊 x'q! g2Xz&\-Rbw?rgTyQugãe[\H4K9Kdlk QtAef}>r no@4U~r RjsA4T29 BZ؃4\q= xo1>ip#WE"@5N_}\]B|N+ _4>`0:'>pOw|-N}*V[5h- vA.[% 0¢;;O+BPO/cNXActA|ѥm]`# }L~ .,vmڸ-6C= A1./b\~`L8"X].rWl܃~Pr:VصPސ1 8[EEE{6`YDl[xE}=Z`vҳm]*ЌRSD6[YD+i)i /o Z#B|[jt)zF iZ (\Ii͠*lmdN8Yei7^-g68b@!/Ę, >s6gL`#&@AaZ"R4P8P*dJPe1۳@+. ^+xբ죱 Aۛ@+>+ G/.l9=kq3 smQc`V8bu~,0cm $p[ &mXwGj}ごP(ycׄ R!zۧ0V4ی,+26sH|v~ rVE(Vߵ+Dn>~ *ȱx_>@҃zij9 \0tKF5ͥ 9}+^ 1!/P$uP8"44繾c&R ,|"Xl!~ Yo:d"4`s14@Ggxgi՚ NpVyƽsA1)/-q:a|~TPUygV)iR\@Yȩ@VH f3`&u/A$< Yz?ey,.ӂiAEuYCj60) #j]Ê(JeQb%+憾4 Y٣/Dο7S"!޵ 0N/"XvPL/cb1eƱ*C*xF#Yk Ejq4T-Vr_.72lBgBzid>9+֕lM GwF/̘B:jTn`{1hZ%=PR&&@On)h%+̔_.J.ʆ4BS(XB5fQ \yyF3  ` +Օ"QN˯Pn"`%/{˒*\[n"J=x;La!7!Va _>@93BnbI@ %B1 0 mN/Nj)Q ͠<\HcN8 F`"s ̌AA;QJhMݡCq`4fS Ap8#ůG#_@i{)E0fS| 'ހ?|` _.pa_fNSS'dna50Sh/>u" sq׫^ صvώz@}4uj b^48`=TPiEnYR$]Ae<|@Дe3 t^鼢9T|~AQ=б8'&QaKS+EpQ-h(.PPHL&DJ=52D^zD%m7-7~`<ŞVtR(1(KV Ou4\ 5c@{ *X)tRֽ D5@A.4BQ+3TZ±(i_>Esl4\ b90O B‚-^t392 ur,{8^;5P|( OC@8Lvt'\YY bx /xy BԊȽQk/o#J+uDpV {Dݲ׳4ּNY i^{) *?AN} *hkN"`%/@{,\ [N2J)BPh!(aZ/F{% #JL?f 3ÖI"iA_}4`Vw_. ħ+,ST@Dֽ"cauto`NMUa@T::7 _{L-j і7;5e! m3QHTShǑƬ ;CL\`JZck-/ F/lB> MD)70?+TҠr A1%GBVa &6iC( Z:ORo vQ**sy@$:Wme/5`/dipVA|VQc<y3YAX4Q^9G#s#Z¨1Nm%EL*2 0  X 3|,x?fkn.}D_}G(ߓ(}#0#mccB>+pS^s mE.U5uQ(pkPl(F "r͌EͱGAA_?6up Q8 6et_.D` /ȩ˻%s\tqz!+<-F wDiTTCA+c/M1C8JK_6%"}&_LEYϊYs |$b>,,9L an6B 0`!(~v\nP?s-+ /pwAS@lߏ!8mhEj{2g^'-g/"܋ t" sNړ`!ƳM`~%Ė_bZ^ XA|{vmؔ^N/,,0aqhߢ&}f:'BPjwG B9?Ӗ3\@I7|P0Q>A۶0ǀ0Ӹ+ i18r}#ʭ dߟ,(е>Jr'8O"Dt|@@^(xǀ/P|Ħ} Pb"cרrz QAq[uM&|ZDI8nČ](oFUp`yp#//u_9+֜M{'/T*C0ovAu+b[єVg*W/3J1߇&(3DH+P^#1 ؃rh- vAypB ׻0¢;=Owg~]CWԋVIW]f?@)31mڸڸꁊʡLb\oqvŸ| DC;="[=.rWl ~p(ryޡPz<EsiFQu[؎Dqm[{!0{&(tìkEn#CB+-JCiD+i)i=/(*L>0\uk9B*gVMwB?ݲA xyJUȏꋜF fAFP(Jws{M!ؔצ}w |`wx_. 3Dk1Z Ro H~V2Qbη /)Z}4![s{hgE/~\`vݧ`H1E 3m[Bdk!kqn >4QFR.Prׄ R!zۧ0Pwp"cxoG1y`א0/`:|@P}D{mŕV_]B?PzpH޲* fj` _.OjK5 {;{Vyw!(c Sk ڶpR&ky'b.y4<=q@>0*kHm=/H1 ax$`6PDP JV J%@b³@1VCM j-b<…L;=@eX4p$8k.PD <>hBJ~_`=/PZ/D|6)Hpq~)s j0m` Bڡe&Z}1}ef iH¬Vh-?"s'2(u.QDC JeYB:}!*Ju \Ֆ^.hZi'ڶXP*^ 8ԇ aVL-V_6곲Xcgau ľ|l݅B`?(/(^Rj[ØSɫ](ƊC`0ʖ !wHc^+4ǜEnW3 *3mp;4c l |}`*~Nid>9{7=py`_(:^w #`{1hr~O<)un'L4fJ?/D%z_eC)E-Xcz~^%Qɵ@8g400l=}ueHpo+T.X,myEZGvprbZ X/ЊDu(Wu7&.cb`h _@Sxp F5AyyƜp;Eb1v"њC h461bpF`kc_FVTX@9Lcs!vreBM/saw~鴰=`~eEAgZ! ⤊2Y x+t~?"(gzQmV4 a<`%`ưCD)O[j`:$@CN )*HAS4P>R_ܷn.ab4`>[7DV}٨ҊDݲH< ؃ e<\ hJe3 t^鼢9T~8*{'`,* 8[D%tp,ڍ`p0TϔLB6hp#Q6A=/ma;(k vȜ*@iTEYw{( PHi`(PKyi-VDU@&,2tjpA.4@BQ+3TZ±(i_.9}`Te z@[Tsrۧ[P;B^t܀#'y/{W4`Gw0:y-*҈42@!8{/@> .1o#J+uDpV {Dry@LÜo̲wY2W8{! cl," թo$@s`?/ wVbIF)E*3%LH+1G`̰eR~/bHV"il5¥-(>]a݅r' +{c=sj QAYDKo:nDز=;xhKPY2۶V$ kf}Ii r믋Nm!JH3R|/.503Ó`/ F/lB> MDɿY`ݠE݁DBaY`(}.!3ߘcE>pVqDmX<Ds&Xv[BNgg5V'n\0Ow`F1+hCk&R@HbN15`/,Ljj;5;uLj* UL'X 3\PQ]e~v+(f.\dQm3(Q>fEk }ؼ T~! wG7%]~7+4跑T=/;P} ϖ"Z=/P[635ew6up Q%\? ^@WRI粡 x۰sjREGO/+/Tav 2\ 6et_Dz"zn/0qAmP> ~ZQ|Tz#d@wpq;R"4*СtŦ!%q=/ z s W60d{b}P|%UeG SB~[ !L ADc߼79 VBr,EۿŝgCi.q@ؓ >ω J9{!N 0`p T`!rAۊUٿ&0b7@B++Ȝoώ.ҋe%v1|  HъoQ].:'BPjwG B95 :$rg}[T8e0Qo>|<Ͼci]Y|Nx u'0J5~(p*B*H>eY-)=J@,WdU>pW@DW/$%~@2 ?`(zx&ůg2r.(%(&z'jq/{FQQwF>)F8BPp#//^itk&`ˍ!Z@u+b[єVgr RjsA4T29 BZ؃4\q!"4[DŴٍ P|Di=Wnt{fpnc/wCp~g9giE"{^GlQu_>`tc-P jAk1Ѷ{"" 5^T P<AA?|@Pj9W_ R6.0T>7Sfc"`:q9q-6T& C." _X/c-v^]v `C|'^" ajJe  AViFQ5 X2}kF%r}{# B`hMQJ϶u3gCu¤U񕐧5PTzpN/ -{֭fZp6} Vtz[h'+ W!?/rDa3 A[>N@(aQ-Xh8C)" MA8P]Z8y_`#&@AaZ"R4P8P[%i)-_.Ŝo 74Z}4![s{hgE_!0?!D[pAR$j`P(ҡ QQZ^j T:[m[uW8ԧ aVL-V_6_0= ~@) !N/TQQ_>H{IDJm c>L%ʊsJT6V|Џ uJDٲ!174 8|X@J' 1gQƌa3>@@e?'=|6es<&Bzid>9{7=py`_(r:{GJ!+rڝ9X5b!Jz`/97ZYm)ϩT2Us ֧NVa1zc׫VTYE}4uj b^4<ul?<:/| $L(87~N W>Qtvp qp/N ^"N'mue^Tqv /X 1Gc:3QӽCi{Eo(@a洗(*HAS4P>R_A06=oA =xjqU$p|6*"QE,).O[_> hJV|TɲWt:t^*~?wREVa,* 8[DZQ~/b|N_qLVfꙒiTH~@ ^97P:(1zI޶ݠ P0 ilCL{Z е;CdNK4,Ŏ=F_(4n`EE+O8`UP½ 8 |UPKAu @Wf!*cQJ 3|ieS*#Al>Psaml}?/A\8A,{8^;5P|( OC@8LvtSׂ"_"roEt51mD ~E(֊{v1 s_.0e]\jL:03X=(H ښX _.0 ߻RT&Z/fJ֋(Wn#Q 0]af2)BD?F1v+49-\*"`Xr' +{c=sj [n!WT:b۽ 022l _>g/mjq^S7#Qf60ՊDa <_Ѭ# #YAnu1ѩ75v@1Ĵ\ `WFHcrXZK BhQ|J /4(nP@TDBVn0oCEi# *y"- TTBHt<_}k^3Bx vtfI?D}Vi,РS@  Zw̓"Qc^ѵyxAϚ(xvmc;2D|߁J\FpBk8x /8B# }p- 0"?+s A?DxDﳹR XP`ji * /DadNI0 \2`NPBO'g8!0pr"_.tһ+ N_.`+D򁊲xWLFy7<`F1v'h @u/*(Q|/s3L/1#mccBR1q,+yM+pS^s mE.U5ɳ!@AnPxE-Ectp;CCn : X8۬+<ۆSB\/:_.`WpkWbSVHLQ8Q _ 򁊜Ns\tyEi?B+"snj;E;)DUPK:bbTƝ"c,E KE-+df,z"]V~V̺ T 3Dm @ Ae,X Ƚȡ~ j[V(_>(KQ=/gq9}#KnsP7dsb+DgJ+زiO9 kH砊 ĸX5k+!z3*A۶0(@fweq7? 6G`D|gQ>Xɺ_.G])WT(TPv'(.P$zm8">1 Ox{(^kT[E_=uz_I|HA (f⸭{drX& >-Rb$ZbƮQebG}7#*F8BP@Q8ˑhr/e(pDT*C0ovAu+b[єVg% r R꽗@4T1 ؃@!zk> wuDߛ8 l0CQ"t^GlQu_.0Xwv@k1Ѷ{"̃Dj( `ݡy AA?\ (y{5ǜz*Kݰ{,>GPHׁAm4 urz ({o&*ޱ!8^Zv)zg@N>{"z_@ 2&9~HԺ]`H X2}kF%r 8F@њUgz*tHf>~D+i)i=/X[3a[75 Z߆[6C S觵[}LVB~T_$4fP62 '},2DQ¼Pc5kE |G46KL4;@C%8yn wFZҊ(Zh}/шwiGJ)@NC]@Un"%\,9ߞ Zv9`OrmߊR}E~_..fw}ZH1wYD6[!PAŒm5`6>4QFR.Prׄ R!zۧ0V4݌},+26sH|v~/{ˢVq"C++D| *ȱx_.mkrl[M/̹ASi@Ms9+> 1r"Q}^<ݍDۃmuW~`P[a+)b-@6^ 1M&0cpfе{k5U jMl֭'O?^^i@kf]y _.=ɚ_(F(tQ_@Qh~j(W mRjEL\[;2Ff],=fƜL{ *B'M p|֐Z~khPc⑀ "VDP-+Y17QR}$BxvQ\ g/Zo=)i"g> \(\dcT@UHm@G xE㙯& ;<)7 zH`nж 0lE iY{s;_g,jw!5**Dt@D0T򪬨10JecW!eF;|Atw~Oc΢N+81~NzrlBg>*{u傒id>9{7=py`ۻJPH#B{WTY Srޑ0VGq4VI'T: Г[s `&B 3r! (W\/P=?dZ? ^3N ` +Օ"QN˯Pn"`%?/QkWſ">S}kA bU؂X 2 {Abt@!NES.cb`h _@Sxp F5AyyƜp;Eb1v"њC h461bpF`kc_FnUK)!P0Ә`\0B?/80m49uJV qΠ; Ɋ4!]rz5`c׊ =;B0ʢzObsO"d>5 xEq4椵'%V27@䣦Ҁ zQ8 2 @Ta9'+껒< N 2˳l[Z@q" ` {qREc q: ?x˂3W6+0Ja\=:` M2J^zD%߷mߖFa?mshbOv`giFUqLjBy+»QZ-LY*C@B!B ,.(\hWf!*cQJ 3\Esl4\ b90O 'wPGWBisw2Ҙ5<0`¶-C+P8ڴA?"UW̘LE$:/4` Cs6i? "88l,RQA[DʳMݷ셜,>#-*4*j'Z`|_.;0O! JeŜbj^k%`/}od1 7FyE6?k:hN ص;g;q(;)jDQ vQCxrK=/8B# }p- 0"?+s A?DxDﳹR XP`9@0Ux #pJڀiZ|z(!z3Г Y>Nm%EL*\E]Wp,~_.("(f*څK{, +:w8D8Έ0;ԛ6Z"JňpxwtQi8qwRK~iKC=/Y}kEPl(F "r͌EͱG~ٝ!!q7@iM,^jPCn<7<\?|{m^̩K!.= *rjnc$`?cܾb(>A *h;~?eBpx*hbbt̐ƒZЂ+rp_&ϊY7x!DqUЫ7|"`G SB~[ !L ADc߼79 VBr,EۿŝgCi.q@ؓ >ω J9^t)`˦Dp?,!*",$~_.q[j<WBlftUhy%`%`Sz d.˒n_ъ|(ߢ&ݻ\uOB:L9sZ!'kuH;,|1}xF }ǀ/0x+i1.FW\Y/(г^J+.Dr@EBz}(>H`?(ǀ?lM@Pb"cϨ򁻊 x'q!ޅbL>p J IZbƞQbG}ԝp rmAs; s#//^ie(c.pD!Z@u+b[єVgr RjsA4T29 BZ؃4\q!"4[DŴٍ zT( Ϟk7PHޚ]`&Cp~9[4F_`;Eiѵ@*|D9Хz$BS.,Ct"A۫9ԋ4VIW]O߇*C@)31mڸx g{~qtS{C."  2bK\;ev8zE95\v-7dLEsiFQ5 X2}kF%r|>k0B` _ٶ.`@>[Oi̇&_.<倢;|t9\m4|w`(j}n R+ΦO֊n{ Yq_.p"'A6uQ8d!s{M!ؔצ}w .`w_>s6gL`hD8#D~ip>@^(-_\"D],9N/niZ(uZl_G/HCs;f?Dkns\h.Ϲ` 1oz['<'AwLj!fο,;8:{?[SVo񡱫UXf;-w{qZF ffBQ8@| +Z{@ ˄B1 }؏< rECUG9-g?/(VH f3`&u/A$< Yz+9Y\1^}*㳆z> ,D]K v3(JeQb%+憾4 Y٣/Dο7S"!޵ 0N/aXvPL/KW[OT.dƱ*C*xF#Ź/TE3_hآ_.7@*@Jɭ90 dQEWِFhJ@Qb}+ 2DTr-^3N ` +Օ"QN˯Pn"`%/{˒@? Q a o 8A [ZЌ=|̩C !%*ي:>x@v=_F@kZ+~k0j 4`F,1n`h}!m03byX8WDR`4<;BsO[?\L,̎+ ^rFWD>(m(Kr9N/e q5T:D)TRU~P@T֜DJ^.rY}g ޝdR2z1CP´^DJ F`̰eR~ZaPݡBQ.\)]X Zz"^BZ700| *a_-^@MQȶd ) Yx_mjEhǑƬ ;bZ}0+#>W erXZK BhQ|J jMsXB (Z  X²P}|2"8>ecd \hΕg` o 9Y|FZUhUO"n9|`8bV>(8 (ax%`/,Ljj;5;uLjjV0j+6/8(YEsoml5P(9;݁FNPS,r}k"Q[n@}f>Bcp,\ LcOJBn,h`lTVkbݸS&K0U_(;6`e93D ԛ),>Nm%qo+)B`*P4\E0\wW0\Weۥ٭0]psiE} :w8D}̊>@6ұyADQ{ɧ,@t{2eƩ "J /H] j97ϣ"Q<֠PxE35(PZaS 5|cuQ|_>y;rۆSB\/:_.`WpkWӎky_($_>PSs=wK 6(`ChWDyZPA덐^H ҨBV^h6P /pʢ@Zp?`~e3QNg.+?+fGnWPe_p 25z+䇹 IP&΂Y#Ep4w##JV(_>(KQ=/g]+9}#Kn@ؓ >?'-g/"܋3%l45sPEbV5[*~Uhy%`ٵ!`Sz:r+뭁. \ Fy, ^^| ǀ?`1Vib>FC} (x,̃(а~'>pEO"D:`ܢ8@(ǀP|Ħx 8^aT9ୢx@:$~J^QA q$:L&ůa29i9(%(&&8nF QQoFn(ۂlq@Dcж0{Wӭ9-7OTT`j퀐VuM8*?.R~e r"yle/ BZA_>q~ o1^ip#WE"@5O J;<]{,~o0#!/0xxwo_!/]XT±Z۠hZ*.(PrL5`E z9@Pj9bU+.է 46&f"| Bl[6.6@g P7|PˡsE vPx̓lm E2;r;w'^"<V$LE5Fa+ >cPSD6IWBҠ`iVo1s_P6*gVMwB?ݲu Ƌ\ /p"'A6uQ8d!f%nh9jDMD\%&pr'm؜! ,}x0P(yrׄ R!zۧ0V4،YWd,m505$L^A#B k{ +Dm>Xm94|`薢 4jKE/(t<e?D/^r"Q}^<7wD09u\ qiC= _::c}C{TgLl#U q8fеlMZŇƮrTa_\4 y"{4ޅD"Xr@m!0L|e܎@l=QmqQ> nH3JaPh[R(gz`&u/A$:\ Yz?eUcN !ؓUg2M ,D]K v3|XB, @d[Fa K1{%fJDq1ĸV̦rA>) _ȁb<…L<}AeX4p$82޻8 *h>ՠGH4,|\PJ)jsrߍw7:GH QoVRY+Ui6=PWlg7`csZK,DӐY&Z !~%ELOe3Q=\X+ʲth2CTl} \ܾK+BPq.n_l/m3`}W.@zbR{OT&Xֱut@Ef0= 5 un`CVD5X6e98Lwoc5Blj>F1Lcni> <~OcnhScJL[M?'=|6e+3D;ޢJJ`}pB _.(|߽#@%9U, c؋yG B @Jɭ90 dr!ДŪsW2{!kQFNy-WZN ` +Օ "т\w2"vEJ_.`i+kW"~ր4cfNw_(QVԩR>_h#u B{@s蜘k0j Gsi0Z# Ƙk`f RDk wb)0ӘG,VО-~E8YRJK)!P0Ә`=l97Z3 2;p:A%oB3h/>u" sq׫^ صvώ>s(؃i`O1@̇`8@" *Ҙ֞MvffjQsE/ /\D;QA(a)9ĬcԩǥBL/`'_T:̯l}>=BKq !A_:^ŲU/ ;X 1Gcw$Jyb(g"YHG4`4|=h[u=4R _>_8F`mq{ނ{8 jqz4[*"QE,XH6(/?FWeT1|V|TɲWt:t^*~?wR= e04 l ujEzq'v-h(.3%Ө vO\ (leQ$J\n :Fa?mshQ ]o3DTJL*ʂsm ^ i" }#7@ ,-祵X}oYe)t-"nP"…ۍ q`BQ+3TZ±(ihmX6U*s6A(rfp'wPG$4fD6`zs%$^9w'#JZo!ZQѦ ^*iPh9aݠE݁DBaY`(>z >GvBqDmX<Ds&Xv[BNgg5Ɠl[KfI?D}Vi,s+{a9FT#`,YUyРV0j+6/8(YEsoml5P(9;r_J>Uu7rg<ްAEȇQ}f>Bcp,\ L'0PDCG$i@>+UF1n)%*L/DadNI0 \240~ QB(f A'|[I|J T8 ei`:9'J.fK]j݊o3ٵ 7>YGLs#JicVŒ,޷rbͥoϏ!+G} DIgWƩ "JM/?o#-t_>PKF@>D[gC1kkӷlf-j=KiQ?VVi)GM/pxl.%g^*\6b]obN;^ qQxxņZ/F<=Ͼ@m!Da݀_>: 'j6] 01 OA97B+"3PA+N..zGJFE:2@ش3$$El}2Ff,z" QDK̺ |$/8BDm @ Ae,X Ƚȡ~ D ?GYy?;E φ -] u+ '|#\!r̽>S_M`WȠ X8\C:UD XH<bx ̯"J 2۳K_.@YxYl  HъS.U8s_:r/UQA?B9/I7ro2Ws ce?P838M1W_`D|3dfg@!d /<+x! Eq"a=Q1lM@lq(b"cèr[E>u:^ISG̃!㶗 bkLxZJ IA-bƆQbG}ԛ G [( g9RR>nlyr:}2>Wk\B[!ۼMiU~6:\53J1&?PfRN\PCaA_>q~ o1^ip#WE"@5O J;<]{,~o0#!/0xxw/V|:F>rp6h- vAPbC9 "r(E8CDk@e>.ghl@N7 +ȩ05}eB!IBlN4@ugV}kF%r64!0{&(ta3gz*tHf>0iJӚ_0_1x[<0,rַᖀP!>-li薭;N0^&`{Ra3YAQ(k>(aQs{M!ؔ[j+@i]b1]1\oZ</B?{{0m_)e(i(qV rZDbpe1[9V8٠jQZXnyM8xr4[NZ|WA,D6[!dk!kqn  q(b O)P(yr+(Rj֘Lpwb.Wd,[zV1/P=J ʌBM8q(x@Tc/ж/^fۊ_s)D/ jKE/(t<e?D/^r"Q}^<7wDۃmuW~v:`PnW(7SR16(6v['7!B,9 ڶpR&_>P2n}a CQ PA}T i3Zf>h9!9жZ!6Q4MY{aA$:\ Yz?e,>1^}*㳆r0~ >93|XB, @d[Fa K1{%fJDq1ĸV̦rA>) _ȁb<…L<}AeX4p$82޻8 *h>`4!`%WXUEM/PZ'D|6)ˊJ8{9BB5fzZBH;q,$W"Ɯ}f@]G¬Vh-?"s'2h=\X+ʲth2CTl}Z+n_!8uڶ>+VU\}c=GCJB?R[*mL'ge]` Xm:uvJ+,|"Ht Q(50*+j! *RXuԀQldq#DמG?>5IqYv1cؠ1C> BO>Mv_~B h =_]9fq g/t@^!B݋>TY Srޑ0VGq4x9VI'T>)un'L4R9LUVrQU6_b}yE CD%עq^[DuZk_\r ^~we+y-U\_qK!v[B1*lr-FrrSB*@1JTuq}A{Y1dhbM`X4`F,1 10ӘZbj}ehQ">`;'qso gfmbl T2Us 4d6W9vkE!ZseQ؃i`O1@  2 "yظAEs*ǾXvff*X1倢@1 E/DM/pA P 3|mk/kpnAq2-W` M/ ā|&w|ENx˂3W6+0_>`%`ưCmRJ)c!PT7mkN@BJ0Kh 0n[Pp1ߺ9 :]-η{F%V$ ,c_qS"hJ_XS1R+:Wt:c;)݁" o~F-ANS1nøu٥zd8PAEC}&WJ[%FT/= ۶Ѧma;(k vȜ*@iTEYw{(5\PHi`(PKyi-Vrp {p+nYm0PpA.4s3Ph\- IW±(ihmX6 .p#J}{aÈP_)[G]a݅r' +{c=sj r@T: / DKo:nD1eS(\ed[Z`dהbٶ D"QXW4HHcV[]Ltj FP 1>WBisw2(3c8<`¶-C+P8ڴAK% -'h;P3<ЀU(, Pox.C( }#j"(< +6vr8 >1Dheݲp^`0O! Je3x^ 1NM_0070k1 7ԊFyE6?k:hN ص;g;q(;)jn (K\w9*!yaD]le'7\Qg(4µ0L4)QfPJ%`B>Q~eTa #pJڀiZ9gB7S =Y|JVRTi(K\E0|I+8`_!r倊xWL=cbvͥO6^T&z߃Q^zgDExtN|M J1#cjG>XhD]~7+5tdht_>PKF@>D[gC1:Nӷlf-j=KiQ?VVi)GM/pxl.}!ps R3x۰sjREGX*\>7`v /MY!p / `5PSs=wK OA9W!+<-F wDiTTH{I]lZQXZЂB `&ɢ,@_egŬ {Wzg-,NdjVs˷61`!(~Vbw##JV(_pwAS@l>%@P7ιӠ4 >'F*+B{}$-Tpt@x9 -Dik|t+ds47x%`{׆ME +\%v/ ۀ!5=~"vw(az ll?Yr?tg oM=g' 2@w (G_gf3 kZO`D*c| (<8@!> ޴8Bi}j :-~6eY~l}*UghZ~~@r O`(^OL_䁣 PJPLL⸽_3Vf QgF1< @VYDccnl-NT`j큐Vu+x)F KH%䘿&(3DH+PlGvCXEi|o1Nip#WE"@uO7 }X#}M{w3 {xsた̙V|:=/]XTobmD`RU!P`ݡtlb:1+讒8T}v߇*C@)31mڸx g{~qt]=@1.&`@`rQګwt{"]Y0u (~N:-(*ƶRo(DNby7"fn$S az*tHf>~++u<-<傢"D wmJ.!bB?H!az `Zm ) r)0=bnؠҫ2~ Aߕ"&jEXg+ " yN~o>09u\ ӆ _::c}C۲=>" u14}0 '?}^[ZU*,;-w4[5W`.mLb;_. JѶ^r^aJnX&6Њsɳ4D4`;q7@{FaTPUygV)r|%ZΰR(gz`&u/A$@L#.~v#cN-*B'R $֘ѰWL0x$ȇQ(C%UG6u` K1{}<;v0!k`6}_"scvoQ(r ET@EB&2jBjg8_PBUD"J5,XcQ0!h}7R@ܽ`n !!3 DYIfHT!ڸ\QncZ_&`` :V?0w!Pc-p}(CRH4m ݶE`f:[֊}yE*FѴG0dPW,tx_<}_!aVL-V_6곲Xc]0L{,m_:uvI>/TQQ|_P$" Զ1WeE}w5P* ]&D׾G` @su]a6t̴EФsГg]5@ U%%0|sW+,++B۽#@%{+~ Srj2ԹMLܚS3JV)} \} iE.VWD 2DTr-PNL4 [DO.)2A$ 7x*mYevoY@kMD"S}kA bU؂h1z_(6c5\w_(QVԩTHm10 m>/)Q ͠z[i hX$6c1(h0J);4Zb9n&hcTr_;2@䣦(vpTA8*(Pxt[mT`2 " XA<4Pߕ L8uz_y $28~jE[- Ѓ'YQ( ⤊2x+tVG\D&D !'-"DUtb-vJDBaY`(>z >GvBUp@ňڲ2JEy.4DʳMݷ셜,>#-o1 V6-(f~bDYj9G0gQm&`/QԊF&8֋ 0gϚ(xvmc;2D|߁J\FpBoM!{T$b]/l= #D9B@jg>Bck߂aY9 "X<"L\B0O`2ADFVݩ0 \r9gB7S =Y|JVRTi(/h-&UI+8eBYGLs#Jk,c[4;ԛ6BR1OX8;(48W\~iKmݡ_( p}N<*n -E>r͌y ,B~G 0<7Tl(»'6Ŝ}x~բ<-^c2*[_tx_D`=nC=pF[| >Y83>Pk J"G])WT(TPv'(.P$zm8">1 lCi]*o聨JG _ Fy0C| AXůk2r(%(&Mq< fU(FqG}3b4#[- x)x^Ol;9|:=PY B[!׭m*?WxQB>4@!BJm_Ɇ_BQ :Aow=q~ Ҹo1ip#WE"@N? rP8`0rw1#!? ( d>C ;{ѵ@*Zsg PCnLW+BP/J^1^Jz Ru70ؘgy8mڸڸꁊʡoCE1q DEw,zE{]Ej.?=/|.P"@w(VZw_BlN4@jvt'kW*fݜ{# B`hMQ,oO L=XSb6q] D琢oqsſ_.PԺ! R+ΦO52=PL&+ W!?/rDa3 A[>N@(aQ(Zα5"p`S#VDhp,A#Z</B?{{0m_)e(i (qV rZDk~ u,|;\@+rmU|v6G[\@\] l>i>Ŝw9k̴l YG"Ef  XҸ>pD6M~HB^rBTḢMy7c0⊌ƋrR^>"D J.!{\삨 }@m /?l[̹-7# Y V(Cǂ۠6-FmaDVW 9xDܶM{<]~`P[a+)b-@6^ 1M&0cpfе{ksutG~r"`/|q/Њ4b 530W EpAm!0LFu2P:ahݿYGY3  @~g4?[J|LrCҺжZ!6Q^MY{aA$z Yz?e,S)}*㳆r0 @Gۊ|XB, @dܠT d)fg{;b{̦^{n p" E{}r 2YX!PcR[<#ht"QB&g>XcQ0!h}7R@ܽ`n !!3 DYIfHT!ڸ\QncZz_`LݡpD)o5b}.)B`*8(CRH4Z=P%CۗXg;Zq/=AŹ}жe_ևDij]r<`>,!:B+&tR}V6kxô,L5,in;eP$`?(/(^Rj[ØSɫwBl딈e#Cci ;X@J' 1gQƌaJL[M?'=|6i656xL*{u傒id>9{7=py`_(:{GJ!+rPY;ƪ!?/*R61zrkNDC(Ya@TrQU6󊲘-Xcz~^%Qɵ@82 V>ѓK.A$ 7x*mYe"wb[ vprbQJy)۱_>w_(Qɿ$Ә'~Bj~=_h#5p^LOL55`hՓ HcN8 F`"s ̌AA;QJhMݡCq[Ni3byX8WDR`)>8l97ZyYݡ'is-fAv~AiC^jƮ{v`#DQG? G) |r10D4|k6DaiIkOzKdo@QR䣦RZ75\P(! P8 R@M/2 ͚_>eBM/sC~7EP+B`n}>=wā|&w|ENx˂3W6+0z_0cXy!Zuf{)60'~QHi/&PTОp2hu=4Rjyh 0nPc޺ :]-η{F%o[H< ؃ e<\ hJe3T`sc[$'*QaKS+E 8QLVf V >Ilj@鰧FKOd _?)-7~`<ŞVtR:Tf" i=/pEXx7" M }oYb>*TW%fVgWf!*cQ)=J.cۧMU檠w@u!0)}b`^~rUȋpz4E"xy\JQ 2qRh 2:U/YZ"Dx1]M-_@ۈ@(`'Qe)Bv1 s_0e]\ḏ^(CXDNSH ښX ~_0 ߻RT&Z/fJ֋(W9b(G5Pwaˤt_Őڭ8"D:jY}|NQ 9Yuҽ95U储 uth^ h c˦ B-YC-n02vkfd1lfZ(+q$a1+ȭ.&:(Pz}04R3c8<`¶-C+P8ڴAK% -'h;P3<ЀU#BUϡ"`C4ϑ]Pg<GԖEQ**sy@$:Wme/5`/dipVA|VQc/b|_.;0O! Je)QNm%qo+)B`*P4*0 _`+DrAEY+R#{bvͥO6^T&m"QAF a6B@ Ae,XVAb췎1@mʄ enŝφq]/@Ze[ 0 O`\"g#DDp?,! UCU9&0bEPdηDMeŸ,{b B8I)Nڎ>Qّ0 l?Y{_.8#=/(C fb#/v棎3 x3 gh>,f=8XyZ=p ! -*`pfT|?`g6@^oS偳~ u8@K\CQ O`ǭ |[&G@@LLhq^/3mL FqԇΌ|MA¹xc{A^OlܖьrT!Z{ +亿CFSO໤@`F 9d)u J1t.Wk{P]/`n;%H{qHX\2Iůk9<@O~@薿X}*ۧ:E_!85 ateFxXw<|hgEyիd[}h=Tiq*us Px6C+r +.n@Xs`0fg`7&0j4 P˟ugPW`5"] .նؽH&`_8~pJPF(me2ip既Y", AߚQDzE]b?>LE5Fa۳8^+mTӰ(큨 y yQm^ LK%7*jݵ! o SZ-q^5&eWN!?9 "3bϠw6' PB0הs{M!ؔjHkӾDc^8yk1ZimG*@|{[E%P`pŲ9bL5Di@Ѧ AMP+>[_.fwir?ip̭D{[B֯PAŒ_qL[sC g?#FRP2ׄ R}Q;+?h|`v~ 2V &B .WZ}u ~bD9z_6ٶ5<0_ 4Kk@!Fe!ky"Q+ "\nl&=<樮c%g^=ڭ ` O=!bn}+@׾hE5>7sVl}}r|O^xqi@kfal_mS_Ca(bgeQԦ*!OT|h9cRjMsہD?/Ȭz?e,}*㳆Ԯ*֘ ڐ@@M6|" Rwb%W ՕJ\GgvbZM 6mPlP.dr] !Pc :/(ε`TD 7+Y!`0=/_:qvrߍ, o0또DDY" !ˊZ}1x|] 1nn"okZ!UC@'RH4@P(ҡBQZ^jM5Iۛ]L4q@UgVMl~Nz>rBg.*e0|}pB 4B(T{@%9PY;ƪQ _*@Jɭ90 mJ_/D%r!ДAQbu -֘WD 2DT(W7U&`#TaWm8('>W|"`%_/( ;7%=8;pրS?/pyfN } *y-1 S~*6}LlL|Bw Ŕ ^bbC3i h[1Ej w@1 FS`16+hcb`#ůR@>jER`4< ߠ4q ֔#fΠ;AɊ4!S/9Nvώ̺\Y4P\4@9BLY1FḊXc^46nHcNZ{[Jy",L^ 8*igk$JAx_w P-qh4JX&:/<mkX7_Њ[(tNp5e1@ZY 15^+pxeU/ ;L]/0cXGc:3Q-0N Q3A^2uZ8iPXz_\ U(p0iqIlTsKa~'˘+`W~_(ehJe3 t^鼢IQD9֦QXy?M-AN{P:8 }?[X0Q(]3%V 6$`O6nr5t+Ĉ'AT_@{QOs1bY3[|DOӐ,bfTBVwWDطiWtkpEU@&,wy@"@nP`DBsφ(U?J8tRǾ6Sz0\4DZO,$sU'G@:Ô> <0/A\8A,{8^;5T|E!LT&ptc#AaΕ2lVru_/Dxٺ!@{%@+EDpV+"^y#Q[z6@1 s5Sjye]!k/X1ZAqH 洢 } `.DY[N2*BPh!(aZ/F_vQ%g /;bZǦ" Xeu|]+`ͰAQ*=GԖ"( \hΕgo o 9Y|Uh1Z"n;$Q ږ~bDYp{S@ QOM/l0ȘcD 7FyEצBon:qH?!'g;q(;)jDQ\!iް"ѽ`LuL!GH3}p- 0 )QEfP Z(f? /Dy)in\`NP''g8w!0` \E2>]W`e_!reۥ_&gbvm>'=}}-f# JV,mJ+8iO9 kHP~@^/D5[}-b)JLP^lc@^(BP3)#R7"DE0}v̩B&Oe~!@Aާ!NY.:(Wm^ ~_`V|Q^%n~(w{!D X| >\=!TP=/[H~Q2cKqDy)={3JX|T]E]u^Iǒ EP38n.<L>P,ޖs*_.(fm< Fqԇ|Sp`;@E\Dci[0{Wӭ9-7,?pU !Z@uWuC FS?x PQB=4y!{9DC)*{g6CwCX"4[DŶXgߎ*BkX_}^ypT< Ouc/wCp~z!?<("?}:M/0-( jL@d]Ϫ⁈B 0_`AϞAA?|s  +E@XLYφ֡C@Yr(܅!"PkE?Pe.`j[{h^$ /~v}"G0Fi, (~N:-0CPcۀe!Bcz{[xE]b֟Q"Кө 1Bc" IK񕐧_a>j\m4s*jݵ! o SZ-8Ulq_.p%@C} ҈=) zwQ8os!D 3Lh9jDM9L46KL40a'Ͻ9C`#&@0m_Qe(5(qV rD?-`,|;|pK~{ >[ҲMcۛV|(=|ǻ,0-Wo^ |)afY޻,Dbg$f> 5$LXN/ۗn#gۚ_x쓑0۶R}d>j-o9vi?Y }*CQ&~oaDή"\1}o~`sTױJY EsJj0bco ^ 3ο,\Y0=@+sbjݑg-w{aZF ffBQ8@.@mpR&\ F| ض~wDY~ITTPkH_>Psa4C 9V4 h#pE >@+J%@٣܇Ôb1ĻVqf^{n `᜛EwŖk<EB&vQ2jL!6 FPQ"JЄįdbz;MFO7uLHƌ >`sHBH;bd<׵jyN(¬&:{EX[P!O0n!ThZ3P%C/3XgQZT:Gma|cbj*"><`><-@CQJVHTQ8::@Yc}faV}uN%N/ 3]a=_a{C@8J10P %Xi<vl17L?]{4_>5Iۛ]L4q@UgVMl~Nz>2lЯPcj uD)U%0|}pBmy@H#t~BVBe9H^#Dq4x ƞ_>`ԡ|D%N}/ @_Fx1Wk0j ԓ HcN8 F`(Ef~("QMݡ P 1mєiL 6 X8lml+HK(m/@9Lcc;[ZY2;?ⳚmSU;V'+0OA+:VTYך+ ꣟(G) >f9@1؈hkL0^+ iIkOzXZmf8jQI;h *hy36D/F8֪3V! 0L/8FCacy j iqݿfs[NU<{Оe֯<|? )M/+bO4Zc>PpTDO*-Yl4 l u:{pڍ`ZQ8lgJ{ z/\ ((1zI޶`Yo9gFa?cc4Dq]o3D'iHQjOBy! +»+@ ۴+rZR}562t~!B TANQc 8wEs260$±(%.اM*#؊s sacl}?/O yq.Vx@! apwj>PQ 2qR[Dw0lt^ "=CW!8/@>[W\rߛ(_) X% ZQr9N/e q.\M/*C9XDN+T5"`%/@{,\ (>dU2z1CP´^Dq9xC}Gg# PcZ>7@wP8:jY¥-(>ݯc-=uXZ!-SSU_>_(v hƑ!{v;YUP^S7#(m֊DxR>$4fD6`b{s%$^9w'#JXQ+`ڴA󳅗J-WXE7bw?64^h*,, ǨWl5.CT mOe2<Ds[ ^ۤBlE v_!9bVжCk&ʂ >6x^ QOM/l070k1 "Qc^ѵiЛ츆𷛎(5'mCPB(qrv'gC@k(1aGYrG@ /Z!}f>u8aQ.Kw(~BL9\QV!T54(lU_(Ww8%m4p-r9gBS\|;J՚'QRTewЊ 0  ,BL/Po_gbvm>'=Dňpxwty~i8aW\Y{̌g_a~n _ʳ4!?gC1R?C4dr͌^%!qP W!?4|coB<7-p&{؋95*E?ѥHckb[T /t_.D+j؃5|@Ss=w0 P> \ Q+R Zx}"U  .6w6$$ҽ|/~3f,"]V~u$2<djo($T&΂@lD+ƾy7rA ]^ XA|{Nt ؔ}M`d]L/_pl@*yހMهZQ{(BTDgG*dq_gn7 !,3@1'?pvn> ~V3(6G`D|=x' 0|ۃ!>JCO(=pDr5"PAu|ޢ"ѻ{,eG]3 *>{.u(Х/|@DW8]C Qfq^x2X|- >-U1o@1cwSe1>p 9As5yh9Ƌ 2l|(2Vk\w\w-hJ|vQB>4!{9DC) _ElՓEaЇH8@Y%Ƞm(~=w?O>B|n~0sD ateF9 m~?Ukrh- vAJw`*؅Ewе!( J^1^Jz Rvf"|6ضmxϊ P7|P[]@1^f|0PEP`j[{h^$=/pW "g(dLEsi;35 X59=4sjE}@kNaַ'(L=Fjq=Ot}]^!OU!O|n?J2! -}a]͠8>~RE0/p IiĞ{;(9Yyh9jDML46KL43z؜!,.`#&@0m_Qe(5}9UEKXs_..roNGZܘ6! -`sE~_..fw'E"`-+߻,D{[Bַ<-( YDazýk0Aq7V~kDqh@J~_x_.$c!PR}pES̲XXG1y`א0/`:| tܾbJ.!QbB?H!a @#JM/̶97r}5|@sĜއ 1GM/ A_b]]a(\EiԜjwc3󘣺w.{([a+αb;@9'+H{u129yf,\Y36?ZW%Gl}]kܧ`/|Ԋ4b 53.<s d*h6!0LZ@?clD4`Z=eъ(ڥMUB;Yi+rGũҠVH fZ4?,D42E^}ef`^EZ8?g+٩L]9D @MڈmE>\B[J+*f !<;CԊ|g/iEYp" E{b˵Up!K׬qeԘBjm8/(}* z|}`vy2SlWo)"P AԘAԇl} C~? F6ϳy|]1nn"okZ!m a&Jݲ BKP %o,!z!:> EAyQ\&@8?xX ZDyH@)zH`nYmo`:Q^+Ac3K(u9) ]!DEq"Q%Q(na*y+j! BI6V|z=(1L/L`X@q.&8M+u&}6?'=YmMvy_Pc㙯B{RJ`(+2FE*yirޑ0VGhr PyR&&@On)h%WlSy *Y} i " @T+"*YyyF3 UA|徺2@$ x*߽/X,"wbQaӷ< b/x;F_.0sPBQ]Q?}/ @_Fe{1eWk0j Gsi0Z# Ƙk`f D5uC;b)0ӘGl1pWz RC`11`g soPhgfkcuJ"9Y3h_lmu" sKSllݳ#5W3  HgZӘgZ (Q\T|xEظ"9iIo4`}_|hnc70ũWJhy 3D=/pƆ T:4 :}/\ymkXkiPZ(T 1*F,܋2x+wp/,EYA7`Wf +`}Ug&Jyb(m-@; " gETTA{7NyӠ2 )5`DQ[6 (*sy@$:W/5`/dm_lE vK^ZP(fmK?D}Vi,cGPs#Jy@+B5] yΎk Rsom5 !89;݁3!5n0, \s5 {_2#! g>kX V洌!v$!& 4|%`B>Q~Z{zeȮ { 0 \}zBS,'"<|b!0l_lX|_.Poz݊o3ٵK,L#J@E qL7W}h3€WC3?pdL%HO "z_H]J M 2Mc uHO5?yuH4e3>P(mO,\rE+ą ynY-p&{؋95*ąxuz_sO/][!P MpE-x`=\ȩ˻U\to(`._)ch@BVt >*HCQMY}|mHGicIA/~3f,"]V~P۾*2#DTo@{WfZYv7Fgmy (enŝφik)ا?A vO&, ># JV,mJ+8iO9 kHP ;$~_.qX5k+!0Z*ty%`9%`S5=iz˒ w1|`D>*+:tr(tA5#DE0}v̩B&Oe~! @>o t2WsA1:ݷ0f0+ } 1W_`D|@\`FyۃBa+P}<Eji0nQP؃=Q2cPY QM*wJ` P2 /0CVCz[&err>J &&Z*Q7#7p 9As0#/rdzٵnl-NP`j퀐뮐㽽MR~6:\5xvQBy<4!BJr> _: kT0n`#4[Dj ۍ@U_m#@kZ J;xpT0!8#fR+r:;xo6Њϊ`t[PbD9Х$Bk\a]Xt {\_((y{5ǜ'2VI8Ɓo?ec}3e`F>Bl[6^m"F_"PE1^f|0PkE_Pe>.նؽH&`_''^Eh}e| P[?'oi3PcSOEȩWS+TZ`v:36fb}~QNkq=Ot5FiDWSUSM/ D{p'0x[<0 S X倊Zw-G6B|[jlVtK#E`p IiĞ{;(E!i9|(aZMPr|3rX]ipmwh i@vN{csd:s´#D~EipPPz=٭(BXs /x|e2uc7AlQ8z9,ݡz`->+9#(3 nO@" 3>;N4/gQFRPʏ A2E!GW48Y+2505$LQI_P}i+D c r,mKr_>0TnYrviĜ?Pb A_r@EXgWW 9xD5繽7՞P?g:w{([a+αbՏ!뽳=is"4XC-g •kO٣:>[qp1\:#[_Zx셭Ԋ4b 53xb>s dmtKW^!ʸE/}8*Ԧ*!OT|h9cmk`FiBMYgrA1zQW%`Y0jak"{r-T&oT\ {D@MڈmE>\B,P䊹0 a ]J%_!~"l /xh-nLIrE4(\[( 2Y1.4p$_PBUD]4j -VB0WN}\Jvq~y(\DŽ jwZLZhvheEYxH^Gs+VK\DyH@)zH`nYmo`:Q^+^>0Kqb_q~lE _>!QQ*8Lwo(>*aJ$]ƒ!cn/ 4iXOf1N+9Ajl_(jP UJ`(^t@hȇz^iwƪQ _*: Г[s `&B۔_>,ʆ4BSE-Xcz~^%QZ? ^3hlX8k_\r^~w,VrKӌbpsQQo 8enB 1 /9u(}!D(QlifKPcb/p7_.@S.xŗ @8ҘNr!Hl0\3cP`U$;4Zs6My?ؠVZfY ±ճB>jE^J r #`O/yA80_f-XS6(T*T7pa1zqՀ{v`ֵB}؃iLbLA1% a#Ht7P1'=" DqՀvpT$ _.@ *fO PBL/`/:|@+B`n}>̝ 81@>GCs#RNz?" 8kAs܀0cXk `kՙRJ[ڀETHi/&>w+g8 *`R/1  0n[P 1ߺ9 :{F%V$Z-U┧{Оe֯ /hJ_1~l+:W1ϝ'zV^#,6Up:uEzq'v-V.Ꙓi($^2> D@`WFKOh;7~`jy&ZBo3DT*!EYĎ# 婦 4H 5P : q?seݽ B TA.4G7 $U?J8tRǾ6" /p> lUAV鼟C`S4`{9`^aAu&GF.%|#PQ 2qR+e:mc9]0_n"rEgjZg3MůQZ( {Dn /(aη,!.ƂVNn i*ή: 9+yzD wV/qW"J֋^IĈyT u+LOQ ݊#B<-\ӊ8)R.c-=uXZ!- ^ ŝu_qd#b>d45#cl0dzmLV$q$a1+ȭ.&:Cs+!4ʈF _>0腽ZQӦ -T@h*%Gxn0o^hc#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`z+fX4Q^h 3PB9FTS &Q4'l!Mu8a"0PDCM$i@>+J*j} [ "JadNI0 \240~ QB(a Г|GI|;J J24U0lBl(rEYv~v+(fn.s3(QAEsEkPIE1pxwti8aW\YK߰ m._䩾@ (5ڭφbt+ -o(9H/_vg`H P¡NB~h9coB<7vI8=Ŝ}]Bhk]ޗprٵ_(6B:2QGZ04EN+!`\to(`Y|Z<b3`q'RVHo@MYh;F2dicIz s W60dgŬ }%U"*]!?#PHz! e,XVAbw##my (enŝφik)u@ؓ >ň" qra(F׶0oS 3/(5\*w{W>`Fۃ!^JW(]\E9ݢ@EoY }lzFi{*s N+|0@10~ ![ -e\J &z'8n {*Q;#!(8?PQ8#/rdxE?ݚ rrWu@Y\w\w-hJwIU%C RjJ6b~ qDU.~ xo1>ipl7. Fװ J? t߿,\.`N`z !]}R8A-}:M/0-( jAk1Ѷ{"ۃDj( `AϞw 6Cl9+r  +.w`wYDf"|6ضmxϊ P7|PX}b`0~"X].նؽH&`_>ON^) /h]hPzbbuZ!* @mEo(DN{ @ŜZQ"КYYU6fb}ThlT9{g y yQm^ L=|]͠8>~R" \ P8P_$4b@=dNۜ,@eQ S*Zα5"p`S" M70A8 .`w_>sol}gX }`u<TPJ<3 0"{>ĨNe.$HorhFl+(J_Tr_u$`T 䪘=}<;.CԊ|g^{n `᜛EwŖk<EB&0~@5ED s_(a3_lCVrklrA)CДndp~y(\DŽ j J Bڡe!y!bV /0c :][Czۚbg.)B`*8?*CRH4@P(ҡBQZ^jM<+BPq?RsstCibu*(OU1  B?UL-+mL'j[wW >0Kwž:'ePÒ` ?$**YRj1'] (dcŧe#C0i@ta|X@J' cEnW3:۴"PwhgsГle~5|P UTL#Q} W!? ݋>T>Y #`{1PxBHs=5f!\M储dQU66(\/P=?dd-PNL46򉞬{uHp+T{_fXZyE{Q aӷ< b/xwXO/B@:>xBj,UL|BwŔ^bbC3POb+#94-wc503FQECP 1mєiL 6 X8lml+HK(m/@9Lcc;[ZY2;nXKQ;3h_lmu" sKSllݳ#5W3  HgZӘgZ (Q\T|xEظ"9iIo+ _.|hnc70ũWJ_. /g^Jq:]G\<@, lzQmV4 aj X=:`kՙRnEz!@٣ g8 ؃y#=hV)pT>V! 0L/8FCacy j4`>[7N'Q{- H< ؃D( ~1\Mi9_1~l{E1ϝ'zV!oqjiH:ݛAX&@0naDpvQϔLC!! ^97P:ؕQbDғ *ن0OD 11gjO`g̩JTLCw=FS /iX \j`ߦ]Ӷp @{p<[w&5PTXQU8F߀3xWT>W(-kCI!~،MfqӠP>9"(8y?ւ `F1+h[! Je4#J^(Lj}jv~aY%N%EL%XC_]@Iv 0\+DEYv~v+(fn.s3(Q倊>Mnf\oQ#g V视^se /H]J-w2Mc uHO5?|5 /ӷlfZ\/ {bU /PWU ^*\6T[<=Ŝ}]BhXKThy#p( 2QGZr` /P\*c.H~7zCԊ1!+^HAB&, (m,5lKE-L0('>}}-fxP?s#/,z/SԠ9m<%ޠn{2g^QVBo:l@Sa1T)ĸU5[}-b)4?eeػ_(p} HEMOuOvlHBώ9Ud5<:$;]{>2)_y ^>|M >3 4tW|Q^%n~(w{!D Xɿ\W(]\Ezkww=8Rf} 3T|]]P,Wdm|஢?pρ.:}$^IP(P38n.<Hj9I-bަbG}8e9\H4ƋE^OlܖьrU !Z@uWuC FS?xK(!@fR㽜 x@/f`"y _OP}(4[DJA}NZ(~ o?B+/pT0rw1&!?<(\ܷ~Њϊkrm C:zW/T gOW_>PPj9bUG;,6#P>7Sf!Duh(!bTa>@1^3D$*~ *BpRmk݋dv?8z(rteh] (~N:-fjl,2}kF%r|Ĭ? >LE@݀;ݞő- xO&@Q>fJLf>Q+*䩆D T}ZwGL9aZ"4P8kP4#2џPopni++(_/\ρ{wY>`vzO][Hc\P5fl Y&V@" 3+?eܥx Q+B&ɘFc`>\є0,Vd, j!a 5$LXN/ۗn#KH} *ȱx_>elۂhz+9@s1a *CQr ix|` C>G/HpaZ,{;LI(rޥ[ \,eԘBjm8/(}*TE5:@aB$vSlWo)"P AԘAԇlVi6^V{1Z5&` /x@3_BzU%0|lXWsX4Ws}E*[KV,^#Dq4x qC<o_>0_.pa̎["il@Ɯ7Oh/D>4ԫG% /pT$ _@ р,/&L|87:]-,g_|D;W 0Ej9(rWI:^bY+Pm`e\ 1u >֪3pDK_~A*We֯<|? )M/+bO4yE>PpTDO*t, B`SaKSWԩߋnøuՊiqXTztd'7!P:ؕQbDғ *m P޹a8;FLTjO`g@4(qj.{;=NMҷiW-*P.O#B ,(\h Q+*~q!}?lF(ap> lUAV鼟C`S4` $xQgrdRr,{8^;5( OC@8LFfHÜ+e:mcB+Bp ^D}&7QRnKGi,b/7rA1 s_.0bk,i6Pګ`OSH ښS =\`.DY[ į(E0#ѽVl3l!*6T7@wP8:jY¥-(>" 9Y}95UQANo:/܀~a_>1Gd ) Yx6^60b7~f}Ii r믋NmsJH3 2sQ*sK@cc`[G‚iQ|J nK!\a@R݁#iЀUXXV7ʷQP=(jE|Vme2<Ds[[BN&-lg+jl[/8bVжC-J^ QOM/l070k1Zk!ЊFyEצBon:ԜkAe|A %qD!eQ 8z;E{kyBg\`Z&`5}$`N|7.H40Ӏ}WUF1i* /D;6`e93D ԇ)BO.>N%q()B`*(r"_.tRb+DEYv~v+(fn.s3(Q倊>>0#O{ "bD%_`EIg+pSw mE.ӦB&1:m{T$' :W$Z6!wSs^\/(mP W!?4|cobN W<P *xa/EGuz_Z5F _>@0\: WԂk"zn/V`sAӽ}V|(>>Y,.D" E:4gI]lmHGicIe^-hg D9YE뻬l19r(m_I@ey"*]!?#PHz! e,XVAbw##my (enŝφik)u@ؓ >NP4o-~&$"u*45cR/qX5k+!U|啀dηԆM%`b9 6+cTslJȽTE Q:L9skyuH@9^he. P ܶfiܕ4@18r}#ʭ >Y8|@QwVr]/|B#.! - *{8Rf}5WxR(b"cwSo}w@}%#qx 3DH+Pe/ BA*46Ucm4l]^!OU!O|@Tz[ysRF_/TԺk9BRgݧO[q~&WN!?9 "3b@=߿d/ i= D o{UPH-#X ipmwh g@kp3%~wh># !+L󳆺׽H'CXs_..r@ gkQZi,CPp^P+҈L@1)k +Z3 nLa_.0qU6Uyg `CD5 0ҠVH fz60glxz/A$z PL#^FY<1W [{ !ؓUg ]U1D~cE6b[WDP# +bn-L㻅+b%.pE!0/xh-Ŗk<EB&3@5ED s_( 3_hآL|?"Z7: iLjQ. o0또DD}XIZhvheEYxH^GseYB:2C(Juv} \}yE*uEճq~^^U}n H@)zH`nYmo`:Q`+ag&`iu^P<ίsR ,/;+/ \Pj ^]@U 429+֕M 4<yv?UHo/rZn`{1A(=ԹMLܚS3J}0 dQU66(\/Jֽ{AԺW7U``A|徺2@$ x*߽/Xɂ),>$ ;7%E|F8}kA b)X 2 C1S:@:>{Y6/ߋ)(\Qc f /8ҘNr!Hl0\3cP`U$;4Zs6My?`S=R0TTR`4< QL[` e srGs`-C\ Y'd9 WI:^bY`sՋj9nSV:k `kՙRJ[3y,@#pUEF{ S4L}BJ /`~_> -xӀxo\Nm=Ng[NU(Ny)Ql?)_FqWLŨ,ixEN}̡s'"쉞UX-J– QS1.nøuՊaE=S2 K@P4ԯ; ʞ((1KlCyFa?cc4Dq]o3DT*!EYĎ&<2i`Qm9m  T7ge?p  pڣ EPh)>C(cQ)=J.?[Σ,2W9J0m-'u8aQ.Kw(~ࢉD3 M(bӶ-lUx Fv_!,O/0~ QB(a Г|GI|;J J\E>]W`_!r/ x.2?fkkX} ƋWu7pD?/cc- 3r7ؼ (F^UnPt" G?5~7+7QmE.t=/1:m{T$' :W$ZN߲QjQs^\/ {: X W ^܀3 /y.j$bN; q!^t<iLm'KT B /R!2QGZ9lv>.i/1$`?x|!jWZ}̸St^HAB&,#w܏y$ KE~3f,"]V~u$2 djo($2q,g \`ȱ=K%4DmD ?GYv/ !?"=@ZԍcW@ucO&, ># JV,mJ+%`PypDICU9&0b[A ]^ XA|{Nmؔ^as d]%z3{}vptE)*yހMiA!*mSLv˱c{笈3b@be0A׶0ߦg?34gh>GN`FqEvX`%#hQ&P*>/|(HY ~l(+2ma/uMx'0CQ'8x1Z2JobmD`R}T!]aS.,C!(*(y{5ǜz*iK;,OccV>S8mx9 ʡo/_.!"ѢLk=AE]m{LNgg'^Eat@YB(i}bP :-ugƦѝ> .1GkN` @ MX)1 ZFi0ϪQm^ L{a@E#A!>-5p6} T+#  J)"'A{R pd*C_Pr|3XMiGބe1^+xoE_x@6pȯ2 JܾU"Qq%wKX,9>/p@=Ei٦ afBq/_|ey=7[" 1r1s`V5@?HQ $'`_#87Y>pD6M~zHyB@dQ~lm,C/)> |)]XrjEbƋB߹/XڡI8MXA]  r,}09X s,|"x9%5Cl{g{|`G/[&0cqfе][Z;[+ ZF ff vh6!0Le1w;n5<`u< PAm JK̇_3?jy@hZ!6Q>MYa LPL#^F3c(B'RXc.Bf NJ&mĶ"BG(Vr[0bK$³};l1wb̦^ZSErwb˕cer] !Pc ]hH4:8w@T_6+Y!`K_,Z4:qvrߍ, o0또DD}XIZhvheEYxH^GseYB:2C(Juv} \}yE*uEm>룊rzsn H@)f>\!:eqtt" ƾ` XZ}m{ 0,ZR?@ C @E8K: PJ0T$'Wo2R(̇qtԀQld☻&D׾&{ ~8\v1c8M+u&}6?'=YmMv_/j̽1A-T+*F8g lB2(\4L4R9L)+Y} ixEἢ,bu -֘WD 2DT(W7U&``A|  ޗYdV^Pz&D"`c?BoCL!hcT\;2@Csʢ?֍P /@T2 glhy` h /LM /``ld;?t=`~eЃ .!.j,܋2x+wp/,EYA7`eWfsqCD)OR c`N}R" 3tAS4L}BJ=/`~y_.prU(Nu@t:-η8 J{n P8UE8i^e֯*R/_1~l+:W1rl(Yl4 l u:"pQLT+ mL40(@P{wj@`lopRd@(~0 iy&3}!2*P1 )"vmQ(OuL aEXx7pE}v@NoYb>*P7@񫸚6`f7 $UoN+xcQ)=JCcX6I檠O b+΁t!0)}y`^R?*';VG" 9Y}95U偨 rAq{@nDc0lDNg/5#c%g /4Zn F@l*"iЀU!*ǨWl(Z32DE>`DQdEy.4Dʳ`ӷ셜,MZ*4V-Z`|bVA}Vi,cGp+_`n`ֺcD 7hEƼkx7q Co7QjN ص!'g;q1ƍ2pE!|y8hpZBg\`Z&`5}$`N-(~ࢉD3 (>%`B>Q~Z [_&(Ww8%m4p-4PN| Jr"xI+29ŗ<\_1ɻ (xS +{"QAF a6B@ AeD[Q슱?CAԶ ݶ}WbNB+A!r#yJ? m54(>ň"A 0 2sK2b\lc@.j}=~"ckOF"DE0}v̩B&Oe~!@Ŀk!NY.:(W森sg|[Y|NO?`Dy2+ 0"hPoVr=/BO}*W(BT*}{pf?.`3JX|T]E]u^I Qfq]x8m|X}T(W˹@@LNhq/36U8CwF>1<({.@G1^/z/4~5g嶌f:] BBBH4ҥlt~?wIU%C Rʊʆz5̀?Ta xo1>ipk+@9i5,/ҾݲPλ Y؇8 fO/0{x׺^̇V|VT]z PbZbmD`R}T!0_`ݡ  J^1^J RzvρC/6^~ ʡo/_. er *BpR;kN^) /h] (~N:-ml݉ mwY7>=Z`v:ۺk3>*46Ucm4l} jBBj9@TzpN/ -2Jo6TԺk9BRgݧO6.x/r] xSENHÊϚ{;(E!a9Q´^-g60z ڴ.1V98yÒ~wh># !+L%ؓ**"i e1s]8]{|e2uc7AlQ8zwY>`vzO][Hc]i:g{[BևPAŒ!{`>nox_l4x J_._>5a?H4B(1sQ, 50&QI_P~0 qW3@Tc>|{[`SrR/ ݲ# ҂ Ĝ/ 1GC|"Q+ "\1}o~`sTױJY EpsC0XozlOyZ眬" 9~wbn= •k=dZutGi [i@kfq/\{&x>ZѢ0Wm弮I薮ucg/0ey(< jSh~VZf>JQmk`FafmZ>%Did֋rH<3 0jak"{rߺ !k@k̅PmHU NJ&mĶ"BG(Vr[ƽu+b%>(Ck`6_>EXvPL/lEb˕c \,eԘBjm8/(}*.>7\JVL|WN}\Jvq~y(\DŽ j J 6׊D+tN( ɫc8Uvz7NFf5A϶]RTpT0n!ThZ3P%C/3Xgg՚x|ݗW,_9z_h[  XUK\N/P_. 3.S DݲB-L'(0kոô,L]@8IY6԰5Deva| EG%@)yb]x~@1DqeSD&AJaPs.t˜1P٦C>&` /x@3_BzU%0|lXWsX4W 3W=ʷ{GJV *fƪQ _>]I'T.ڇq֜Pr6 EWِFhJ2 Z1S=?dd-PNomfNw_Q1JT/4L %B1 0 m _@Sxŗ F5<\HcN8 F`"s ̌AA;QT`h}Cq`4fS[swcZbj}e)V UK)!P0Ә3alsoPhgfkJV =Ս9iC^rz5`ckE!uPi>hrpyՠlD4|5F "il@Ɯ7Oh/D>4ԫG% zQ8w*D"pƆHV]I˄P_.` Es4I2W}rDP[q~9LyӀЖ W踁 Ox 0Vx_ei(' +e:mc> a(е8\&JWm(VE셽Fblb|k^|bk,i6Pګ`OSH ښS =\`.DY[N2*BPh!(aZ/F{% #̙p baˤTگ)BQ{cVItak鉬{Ebw i靦00| *ȱ;:P^0/#\FNPgm3Z(vWjǑƬ `bJH3 2sQ*_. ^`[G‚iQ|J ^*i \a@R݁#iЀU؆C1 >& Q* P1lAFQTBHt<{ _8}k^ۤBlE vӺ3YA* Z WB9FTS  Zw(y6ЊFyEצBon:Ԝkq *CF r_J\FC8ʢ떣r"Q-7lPr>3: 0ӨyXs%sZ;mEfP Z(f?Aa@D)쾺C)ikYi_=CJ}B Q,'" /*L'}r9eۥ٭0LsdKwۘ`xE_}G(ߓT1Wxzߛtll^oQ#rdL%HO "_7,CKiA0FߠPmD[_'DC[63J-j= !(#P¡NB~hE+p&{؋95*ąxrk]ޗx*GP:L/d_>! +?{C97p1DJQ|C ~Q|W ̯l`&ɢ,@_egY7ϑ@oJ,{R djo($2q,gh0F@ 3P2t7Pv_},5(~6DT{2Qا?A vO&, Φykq,z~*X8\C#*u@/Zk+!U|啀dη!ək4?eeػ_?; &}fE!([{}2!*P#`N2as/gn7[}@0|m`>r?{̀0Ӹ+ ib>nC=pF[Y|p3ʷ=_.G])W(BT- *{8Rf}<3 *>{.u(+2v7U.V|@DW8g(|A13 ![ [&er4!˯dC)旟fƼ _TD-" b[w肊|\/Di~}@,>)>a/&R+rz;.V|VT }vJ»Z;h_o^Jw`*؅Ewе!( J^1^Jz RvilLf"|6ضmxϊ P7|PC/x DCůg=@E/?:YTʊE2;rgw'^Ea@Y^yb" Q8Vhlj݉ m}+ 8A@њөXۘQBS-T\ +*䩞JrsӸ9 _/TԺk9BRgݧO[q~&WN!?9 "3bϠw6' PB0ϔ-Xh8C)Ԯצ bm .76g?K X }bvŎb_6^(J~_x_.$c!PR}pES̲XXG1y`א0/`:| t\+~/2JoA GVSٶ5\0熚_.hn!F!k"Q+ "\1o^09X {낹w{B\}!V3uɊ wLj!+@Ŭ{k𳚪u[rToz4ZF ff߅pL\ѶmCaJ\b{;5\`}(PAm -f>JQB )RϦfmZ>%Did֋rJhI0jak"{r-!5h+d&z7<9V4 h#pE >@+憾4w%#+XpE!jE>rba`J_._>p/]]PlP.dr=!Pc ]hH4:8r߻ *Hʼnoyįdbz;MFO7uLHƌ >`뫞!,oEY;I`(+2FE*yirޑ0VGhrw%PyR&&@On)h%WlSy *Y} i "[hL"J!@8~rc =}W|"`%?/(ߵ+G`Np|b /p{̩C ! FJgKLÔ0_"{_FkP^{p;lk0j Gsi0Z# Ƙk`f D5uC;b)0ӘGl1pW *P@9Lcc5 ߠ4q ֔#fΠ;AɊ4!S/9N`}0W3  HgZӘgZ FḊXc4^+ iIkOz;@Cs(NpT@h *36D4\bkN8_@ $ְҠ"#J\C\ Y'd9 WI:^bY`sՋj9nSV:1XLt/PZ΋d" qӀ=**7؃n`@ AecRjyh(l6=oA 3{t%(aT+薪DqӀ=Ql<Mi+b*FdL+:Wt:c;GeOB"o 6Up:uEq'v-V.Ꙓi($aPvO\ ((1zIlCyFa?cc4Dq]o3DT*!EY`G;+P@HÊ4,=FnDZTUkoY R7+ϓQ 8 /EQrKB!~،*$rq&\Hl*#J}ԗ M yAh[!,H\<=qX"ipwj.( OC@8LvtIm J\0e!8/@>[WԂ89(~o(~(`ݖ(jEY^+o$*vb|;<`%E˺*Cp^ թc`؃<5"`%?/@y,\ (>dU2z1CP´^Dq9 Q 0ԭf2)BD?Ulo Q{cVItak鉬{Ebw i>XrATcwt@q{@nDedh }^>z'k FxMyތ̶m`&Z+nJ80Ҙ_P;@ 1w}0+#d1UIXB>jEL6So`~RI bZǦ" Xeu| Ek]ȇ,l{"-EQ< +ނeNr6i` >[QcDhe`Zw`F1+He X4Q^h 3PB9FTf;FpV0j+6zzkq *CVuN| (q۪ o:*!i_@=/ Bg\`Z&`E~+s A?DpDsB0O9UeR}uSLײ<|3D ԇ)BO.>N%q()B`*(pNt_X|_.Poz݊o3ٵK,L#J@EsEkPI޿"(Տ3`EIg+pSw6"@䩾@ (5PxE-5  J[8iU=/pxm]B\ /pF_.`_>3^̩U!.ċ_`+b[T**H23qO/@!_>=XO/(rjz0 P> ~+Ey&*hMx}"U  .6w6$$Ҡ@Zp?`~e3QN}fBU̺y |WPe_p 25zWȷb*gB ~v\n>xP?s-@},z/SԠ9m<%ޠn{2g^QVBgmS_M]=Nk!C"( ƭbxί ̯h啀dηDMe%`b@l1 AGWt~5>P?R;jG(aSL6\C=/W}@+n m/`>Ʀ3io@1>pFQ,? Vr /<+xB`ܢ8"ѱ{,e4>CۥQM*wJMa(|@14 ![  ƖklIbƦbG} bt#۳@9Ƌ 2-Vӭ9-7-x!Z; +!FS?x %3J1&? 3DH^|@L. BA5|6HcxAYְdP6(O>@m%bvV>a/&rԊ~Pzo6Њϊ`t[Pbf_`u " 5ҸLt"=PPj9bU+E@XLYφ֡CbC9 "P 8CD4"Njm/@4v/ ծ(r4|F((V%q.vM2[@0CPcۀe[ cm5Ĭ0Aԇ&(tfmTsDWav@z+,(&Vhqnhed Bkq޲- #Q+B(?&ɘFc`>\є0fYƻ,aG3fH|L`א0zE[!;|< *ȱx/_S)RE/eFۥE/s:V@e?_>0}b]]a(\EiԜ掙x{yQ]Jώ^=۳ ` O=!bn +@ŬkEֱy.?CZ;5?^8qi@vw!Q8@. ٶmCaJ\1ʸl=QĶ@E+h6Uyg `CDE/m[+3JM3 kH_b0 +ۊ|" RYXsC_oa@٣/D_!jE>)EX8( ιYDȁŖk<EB&45ڿ `8/(}*. Rq_>_.u4=M o0또DD}XIW=BHYX1y݀Z5\awt[`aV~[Z QISVQ!O0n!ThZ3P%C/3Xgg``zAYJD DG$uHìqW}faVždQ$!Ӈ_Dȼt uvCMO"E9"S%PJmka*y+Z! BI6V|]Gld☛.Dמ.} l8涱F?56iEФsГ.3x9bA-4+*G8g l!?t~7BVBe9H^#Eq4x9@JW\)uN'4+̔_.FzeC)mHŪs(AF֢qnjsf ` -֕D=}[|]fgGޱ["^#5 1`9#9fl9,C! >68>@!LL|}Cr8R-@s⿴o_ @F y r)#cY0(hUd;4Zs63æ@{#+-(yLy;b?C?cuxT<ì~ⵚSM?^'+0wj {v`ѵB؃y`ObsOA0D4r-&8/lNg<椵'Uld7k ʱLՀ~b 8 2@ha0/ L0]4/ LP C̴̷l}>) `Z! D"L>{^xKq:i#R/.E@7`W +`蘂}UgfJybmop y% T#ASZbAecR _./ `mq{{8 XnN'h_AȏO6yrLK_2|.0ʈr@/@SBxe3t^鼢9TD= yF-AM]Ѧ7b 8q fE=S2䷊B]2 ؓ\ (GbDғ ym_.@rGOs1b]=[|D,/yHQjO|T3<ڣO#P4 V*߀X Rmݛ`w>wDBsߍg vq iR|P>6&<_9}`$9"(ҹ?iy@H}7ҼIeSs@[DYx>`2D y_~3"V@ x1]M-p1~QRnOGm.b/72%\PÜo.!.^P+Ae ؠ:(i'Tl`/ wVůw'*RPh)(aZ/F8_~Qe΄ۓ( [&E觝![qD{*\LHO-!?$XKO+ Q+{c=Kj r@4:/ ua/܀0l/!+G[Z`)ϝ#603xR=$.LQQ*?GԖ"G < 2+6 o 9Y\#-|k+Zl[?|dzw`>b6A}@ȱ1NM X#J8y@+R-] mgYPDC]$y@>+J&j}1i/Lf#Gw8%m<-9gx$Ro=x9J.'[ISA Pf8`I-0\+D .5|݊ok '>YGLs㑨Ҡ|(6c#՗3`pEIg+pSwHfތ`]A3K8oPhGEZz STC\i9ZSs^\/QԶӀ_f]TB\8#k9eۆXRB\/}zs[4/P: rE-_k9@QRs=w0 6(`.o)h@7BVtvqPAtM1C8jKb/?KE-L0߲)'޳`ᑢU, |WPeA8RD+䇹 IY"<79@mu,gm娋Z)jP|miioPP7_ԍ=}cD cEOI[6 wD98Y8tU`!r@[Ū_o ՛"(6+Ȝoώ.?-ԅ%v/ ۀ![$P g74KU42Ȋ`Q#`I2~r!Z_x(Sܺ\uynw1ny既ru'?`<2g<<B 5;)WPF5܀x?.wvA^QaT9ୢx@D[/$n(|@(38n5<iL&a29i9IrA`èG{ C-h2d.pdEq^Ol~-S.P`j퀐뮐mOR6:\5Њ h)BJr._: kT3a w1~ ,.W" }"@kz_n^Z(li,MRӅf #ȸxq뷁VVTkk9@M8VkvA.UZ Fe\D]c~mD_+J -.awYGL}O, DoˡS8SĨxx@1^3Ed*~MTx:tڳA|^$!>=ьr:SKoȘf Z!ZE"6`]VD{ VK,9 `! u/XZфc GƦ }ݔr +*fۂ8L[ Iy@ A['N2(aZMP^-g ~JjOjE T;xVp'm؜)<=`#&9aZ"ߢAaQ+g (?f& ɘGm`9\)ff](X, Z!af 6$Ln!Dի9C\i%d:r,ڶ.9`~bPr}/ 4ͥ/%+^Pbb /9"S "\13b˳^Rӆg{B\l!V}ޖ OA=cdr 6/0+WŢskk5U->|lф2\q5ZG ff@Q9@.9 W|9tKWa(@0!OU i3*Y9_ΰ |Z!6=E?cի| " F>P.a]8(D!`L|-٦0WC)"sS Aa J 6׊L+tM# }]ہ$^腆wt300w j-("2)u.HLC %o.!$Xg^}yE *uEo|cbz׳o >H@)42Uo%{H`n0SN|N6Pa-gaVž:;e'`"P)G(50<-Jq" aޠ8kO z `#0(mbOUz݁1~Nz3g;35_ jxfYJt6&rxaB ^(irjL`aAeܺȔϊPn"`#/`m%T#Qq)0[BoCLa cy߻&GhG̒:o#Ȯh>4Bj[ŏ=/_F`g4!Yn0Z dǜp/wc50 >L5uC;bS`1vhcb#ŷ\#7U"3)>sSo?0?\ì~MyNj`6р dES:~)Ȕ^ [ese@{uH1ea,(Y輰Wd:(֞Mv()vpT@r~O@ha0/ LPX&_( !A-[G =V½8 ^RNxuU/;L/`X-}UgfJybm-@FgiT T#AXЦiPX_L`vE_us@3%,{8 XyC+Qz@SUd]A}Q2P3Д6]P1+f^鼢yEs}݉8*{'`:})`TiA mq#p؍m VTfL<p(@> D@`W>#ʞ,:7-0Cho a?m4L]O3ET*!E]Ď6d@jyXX{xj`]Pp @sp<[H;wT;g r9#ijř*z| }>l>WP \4ǶO,$sU;G@:Ô> =0m/+tԙu)9HZ/*"!L\&pt;Cy_/]0_|)8{/}LW` !TC%q)[eu{a-b|/u q5BurDUN{U`f8V Bu @[s*6pDg ʅ;߻|D)L^0#ӽUL=Y̰eR~0o Q{#!>N4Yah鉢{E:jto`I-N)N1l.ZzpfBsF+㑬2-YC-n0 v ,<Ưm֊La R݁#ЀMXXV7ʷS倯#jF#\hΕg`ݷ셜, -FOV6-)oA01%yVi.8GPvjv^QhE żky츆㑚xvmc;Ae m `\׀8Q"(r"S_j#)  |skayܬ9˒% ""\Q6!TOk٠`0| )>C)icYf4߷JB [Z^Np"/ pr][`W9@Q]j_#f<1xG3K>>0#wHǏmo(F^UVnPt"G?5~7+?iKiA3K8oPhGE­PxE)H-j= s%!q`S+W!?4ͺ~C5HL^NHobI;AG3luz_Z1F3@7@/d`iEI^ޭ"?۠}V(>Y,.zG"E:cbbt̐ƒ-dh@ >̷l`fɢ,Xx}zn#7TY@F an6B 0`!_E.Gy6roXQ&;]0VkC䴷GHKsxq n}cD cEOI[6 Ar5(J,$_qX5k-!U|啀 dηg׆ҋ' K6<,=aqh.jLh=~"ô;#0w,B&O{IM[hY[=Lqa(> ޷}xF}n0x+ ir+0y|g|)YX?FO(} >E 9"gQ2c_Pڧ|ߥS=*oѦt\`8 _P|d8 ?`ǭށbL&|ZT LI-[(UqCl <82"x3Wӭ9_sOu2>Vk\w\wo@|J] UH1&? 3EH-^/nՈ "wgvdP_sQgO@%bvVa /5\x0Sy'.;.=@+^+N3F>rvA.[%_0ʢ;]3%oXR/6X%} Rzv0ؘ)ɔEmx9v g{~qt? (ˡu"pLCů@E EtvO?G 8z(r4|F)V%/v["Qz]@M}}kFH+n)0{>϶}T6xNiDWSUS/Jrryx)/Tk9R3(gߥ&ΦOjE<L3\ P9P$w[q/L֭Pb(}!Y<‚Z=.ܰ_>?xڸE+*>@e & "C]!zGXW|ʷ.V̊=>-0#6$)T d>BM"D;wK] X{-*m!\0B +9@\ZbTC\P) y^GyO/m|ٞP::cU_e{:dEyx14=+@b߹ZMպz[r4̯-w셭ԊRçmV%L_ydыrH<7`Ղi"{r x!k-h+df7|rNl+G(zBFx Na}@a)ޱ`6_."Zܻ;f (rfޡ _ \-e Bj}82/(}*y]\ 7|30/o6O; wAa J 6׊L+tM 7ɫHc׵jywt okZ)mHLafJݲ R"PB{KH/3F^jMܾC+RPql/|[ =-VK\/p/Ry=0SGж)Pa; ޳0kwb_v~PÓj3?$*Td*;H^vo(G-JWo"AqeSD.` 8\v`ؠcC> BOVg\ybj =n]@U <9+֕lM 4| o}hdo/JZn`{1Z%=P9MLܚS3J0Sz@4((Mi;E .V0dv SD#kQ87pzSf ` -֕"SN˷z%.nLmoqT]vaL#{:̌r-F34c/%u(} DG]Ѧ}hԶۢ|^&̔@weSx՗gk04y#94_# Ƙk` |Dj w@1 ƧԊSKA8zV(Gh^J r X/yA/paV̎[lPhdna50Sh_lÑ9ĸ%ǮW~lhݳ#5W= G_ PSn0CD,bt^+2 yIkOzs;()vpT@ L=@#a\0/` `h _2Ar _6ZvH\C\ Y'd [I[p/.ڀC*LS#\ X0ڂ)Zuf{) tn$ yp=AU@|=h[+ڔ{8 *`R30/8FC5p㮛 Mi9o1l+:W1ם'z6cЧlF-AM]Ѧ~7b\ 8q fE=S276P|_w#{V"t+KOhd@#PS;3Si5@L%U)yHQ _",ҧiW=*P,O}#R@ @ *rgPU!-?0[ #}%̌rͿ1G]d $s6H|9nyas /\u)9V׸悊|(' `:mrPD1fBU@I>T&Z/f J֋^IĈړ̰eR~0o uHO+,[FC)(XKO+ Q+KXRSU_.rXGgua/܀0lDI1+G[Z`) Yx_603xR=$+J&j}1i/ #HadNI02`N} ԛ)BO.^Npky9J J2F`:F 3\ .5p)/)Td`?K܀?POxߥ>}FUTѦ-{s@(P>*ud~XϨ2=tg >hG 6}[ܞ-b1^ sWӭ9_yN(So뮐mOR6:[]R@`>rELRj|K~(x B؃y6㻋qȃX\2Iկ9@'@薿Xwxۻ:E_{)8sLate>]<{ZZQu_>`tc-( ķs5_0ʢ;?C+Jz-.od"| Bmx׊ʡo8d4TznTxykإ,*W{;݋N^)/9=hP>@C+VCT >@M+4;D{| .Gk|n(zh1ۣBcS>nJf9>DWSUS/Jss|]ˑA!>.5p6} T+- <"M703A`wx_>s6g>3Rlw=G Lk8R[T* J>U"Sq%Xs_>@+܈rREiٮLaB- G/w/Pzg-WA߽,D6[(}!Y<‚Z>rjVX>û JUǖI(&zAHQcwG;XV,m-0/}&^G *>Tۻ@\i%d} ȱx_>@ֈҕ蝑0m/sC/f 4ͥ5< XԌ5|"S "\nlf=QJZZOJ ` ďݖ O^L1M&`sfеU[T7ZGw$ozj ?jE1y1D"fķmS_7K_q@Fa4P<6|Trrf߶VH #|z?MØkk2 P#^}FsxcL{ )ؓUk ]/b.Bf NJ.xE9\RwF*f}_߱0/"ZwwFP/|>Pr\zn(SR#it~Aq5n@#!5_lG6B/`_ߒm q9r, o07븐DjZֵ" !ˊpZ}1}]ہ$^腆wtv9f5A׶_RTpT03n)CJe]B:}):Wkuz^i`Ƞq##Q:TV!:e83lwV ޳0k}uvC=OP_`(_P)G(50<-J"E`-8Kk?6r_iPs.tXk݁1~Nz3g4Bk.&uJ`(+ۈ2G#{ݽFJV, c% *@JO'4+̔~_FzeC)mHŪs(AF֢qnw4 n@шG%3R G]Ѧ}hԶۢ|\&@fJk21eWk0Z Gsi0F ,1,*2 b9nOyGoM[[|K5R}SjK)!P08w0~_3ev܂7:A#s ل3h_lu"\d]Z@gG ]k,{h.),lr !6L]Q k<4c703ŮWJhy 32D/r[`i@3X&h@9@H~[_3Kz_Њ[G =V½8 kMRN~^b]sՋj9nS/,{\ȔZN' ypNh<m=yUH/#Ѱϡ5pﮛD|[}hmsKa~)aAQ_y@/@S_.ئ+*F}e+:Wt:c;GeOlB"E*:"ʅ8|3ЈrA(B8H_@ 3|c=\AAl>>0"lC!;hBu)9HZ/TEC@8LvtI (42@ЊȽ@> jA\cFŷQ[ {Ln9%k 7nXOUtZǧ"2 ؄eu|_ Bfj倯BqDm(|D@ "ӹl,;ր5WAq@_,)΋JubI15`/cD_00(cDB)M6ךGjN ص);g;r=ϣC(S8ꢐ뼾`W5] f8_iP/r>3q8VaQs% ""^J&j}1i/L_G #{= ey3<B7S~~+^ <<o(/(g0 / 3|@Q]ev+G;gx~c} D_ *+XGŒ\ܽ߀2xA<Q}9CVnPt"G?5~7+iw#-t)/;&OBAnE 6s^)H-j= s%!q`S+W!?|cuQ q1|oM%UۆXR \LQ+R Zox#U  ]lZQXiKE-L0߲)'޳}}ו-Gn+ /8RD+䇹 IP&~uEUȽȡ~ b#sC}.z_kqA!r#KAA8~P7d1ld1ۧ$ނ-}Ure=I,$~_>Vj<[BlfMJ2۳KOE 2Ò `_.HEMKހ: Z}"E#azXRL6J@A޻)N]>p;G>A( foeq7X>p#/̃|W6r/|BW])W(R T/> >.>PWU.V|@6~JI/(>20SVdrAz& >-b$~bQG{蛑xlz[TT4Ƌeo^Ol~9|:}@E BBBʑi|JwH?|$E"Ը/˸@/mOCX"<]Dj=ߍ@>i5]"_f /ZQqwZZQu_.0؄3\Ex  ve.pE 傂Ws,h>oqtz'0ؘ)ɔEmx9 (^+~(zAb |_w!g4T38@E Ej]v `_..v]@0Ni@]zCP[?'oyֻjl.2}kFH+n)0{&G,XQTr¤񖐧_sx9یY |}&X/v"`;@\im>w ڶf={gdo`H2`ŷC\,sCoG%Coڴ-2A1W }*㵆Ԯ* 8RhUȱK@;(+P- bnnT 䪘=}<;LG,x*>t`ύXξY"okP@yWf-{ *2 5P+ʺth2S(juv]>"1u"<_>!TFDz-+-y-j|ô,L׹_g,?𤾀rAEK: 0T$WC(l4.ٲ)cn4_]{4}k `#1N+s:vw 2q&w_6[ PhyЄ\fY✽^?8B/ynjt~7BVBe9H^#Eq4xVI+T>)>MLܚS3J0Sz@4((Mi;E .VBkehd-n NwfShM֪33e91 .=,]7D|[}hmsKʩ*2.OG]ʐc31|Ҍr6]P1+fP`s}݉8*{'`|-* 8[DMnĸNq􏾍!3Պ좞)Be(>Իj@`W>#ʞ,:7-0C>_X-GOc83Si5@L%U)yHQnxT#BV䁅wW<5OӮ(i{8hB)[Hj 'r&,loh9 EUHKq kCI!||_.9}`$9"(ҹ?iy@H}7(kLQQAe2LDw0|tn "#=CWH)8{/}LW` \T(o) X' ZQr@1s_>`%E˺*Spv L^Tgc%P@4֜<|"#ʅ;߻|D)L^0#Sl?b(G5PൂCh~#Զ^BQ{#!>N4Yah鉢{E:jto`I Gh ut9h^ i -!!{vі(S;#Gm`fZ+25f{Iyr믋jN F s#!X Gz, XR( !. <|%`V>b_LF;6`8e93<B7S~~+^5wVRTP7E0|I-0|WE]pwv+G;}L0^ L}#}8Ѐ׸tN|՛6@xD1r`nc~jxn)8Wֈ.`KS;l0׍-!\y&z_]Wk_.ӧl#=赸~97^\p96urC#۬W33obI; ¹F#ԓEy*c4<Jr{N% ֈrzn/V`wAmP> \LQ+R Zox#U  ]L@ 3<ʙ+^-h}g L9YE뻮|m>r(_I@ey"]!?-PHT&΂@|mM 8̳{CAԶ ]rVyVkC䴷GH߿T*RPݓ ^Lj"܋nx l@Ua~ʄMЦ#M`%VoF؄.l s=;}L`d.fۀ!]]Ԥ{ @Ѧ{D JmioGGxK`I2~KjrfPҍ/@Vnqe_]&H η`9Qvfge1@Oq>[F̓,0iB: ȽiBi-h @Bh:_8(`pԥnTqJX}(1 Ыzhh=G0B:8&1 Zb=?q{LP,18C=#?rmAs~ 3#/r=SxE?ݚ :ML!]!]!ۼҥ|mt{R0 9s2SLJ1 tƟ.h%o퇰Dy"bG.@E j{ݲP,. Y؛8Ll0SG~~]hkE2ѵ&<hQ!{aQt xJw`*ؕEw)(/cI@w4Aѥv#P>'Sfc"uh.&PVP|(x9Bimgp/w-6Ej]v `_hG8k]P0Ni.!c(pN3Rlw=G Lk8R[T* 5%n*AIU~KX9~_{ ^WVLA-`}E} ^P:ڋhX 93ss=g6>۳ ` ďݖ O^L1M&`5,+@{[k5U j u8WO^xqy@kfa]. Tm۹Ô2yP0D4u}؏߯ jW}hV`Cė3Z_ j`>RקwmV%L zGydыrz+9%SɵVⵆԮe* ڑ@@]ډmE9\ҙ\17T7*rU8RxvwM (Φ_ g,sSo 0Lì~JFV gЀ dE㮗^ V`\Y4{0 iPci5(Y輰A_6AE9&hcT b qo ffjQI?/pdi @ ^Ӏ^~* 3@He~[_/_ZvH\C\@q !n;RN ĺfIg <dP/,V:1X̔t/Pd y% TGB}_ЦiPXLc4 0n]PCkqXLփ6"S4`S.0_WTݰh="CNDQ=бS6HJ– ѦhSWQ:&b Gl)VTfL</B>$WJQ$F! _T9;N{Z е;SdIU b' .xT7 y`@ T-m2@Am:jq>ں7A*:")g |PZ z^6ᑐ0_hmX6I檠w#h#> h_Tg.Vx@! ap{jx( χ 2qr ;N:@G 傞+@ЊȽ@> eT(o) X' ZQ2A1sL`%E˺*Spv L^Tgc%P@4֜|Ler!*$QE *3%L+ۏ#Q 0xzDZLaP![qDuCW[Q|nRLK@Dѽ`aBZ7 6%k 74\a@|%LB6aaY`(>N"7.ST OeEy.4LʳM[BNH _ڊ'B+얂 =΋JuQQ/{#%9ʵ0LY,.zG"E:4{Iv|ZQX@Zp_`e3SNg+_[, |WPe8RD+䇹 IYv7Fgm>QQ=/8SԠ9x@m~"5=ർ/x(Y!r̽)`˦Dp_!G"(XH| Vj<[BlfMJ2۳KOE ua]|__optEwQ].E)(P#`I2~r}_Z_rLqa(> ݷi9_Oy4b9އF^0̃Rl\6r/|BW])W(R T/> >.>PWU.V|@6}$~J#Gf qx3\PO*7q;|XgTy@|fC-hd>4ƋE^Ol~9? >,X]rrb[)]F ! c~M~@fR㾜ćR/ g~S>q[}Ab| ,.W" }"@kx jݲP,. Y؛8L f /w{VVTf }%6[5ТBR˜ z^#PzS,?HAA?\PPj%bU-oE @XLYA֡CopQ@ڻb |(ύf*~ *Rpإ,*W{;NPZ!r4|F)V%/v["QPwfjlZ݉ ٶĢ~oD  v:ճm}k3=*46UcJ) 'A6)lm#;Yi7Aŗs{M))צ}v T`wN۰9S`#&9aZ"ߢ<[TL֭P-O@_H`m $'`' 87[x~pC{<<ĕV]B]h }sեT~)974q-04u1cՠ2dzx-!AmZb]`\EyԜ䎙{QJ׾^LJYx EsJj0nuɊ 1bi29{0+W w;_ZWocK&xWp^P+򈁼;󁨜c S\++ZݰL|@0!Q/U i3*Y9_ΰ\ |ۖ1`>"E?cի| "bY\k7.s`kHܧ8^kH_.b0 +ۊr ޲@+>>Y@ܽ`n _Wu_Vi6^}@lg7+v`` :]GYmMPk1E)0)L[pA UdjV(y{u eP \}yE *uEoǸ>f O{VQ:TV!:eWlSll1O:-Z-M3jxR_@ vDEq"S%PJmka*y+Z! BI""AqeSD.` 8\v`?c g<w٠o 0@5_Bzܺryd9s!07g^(irjX BʼnD|tVG^b]sՋj$ϳ'DJa` V)^8D=b{PU4Ph` 6N<*Ԍ/3P06=wA лtUyp~){l=hmsKʩ*2.O>Krl`j#)M_ئ+*F}ẹ5c;GeOlB"O * 8[DMnĸNq􏾍!3Պ좞)Be(>Ի=+P:ؕĈ/M {׊?u,7|4<3ŞVt>YRNj.xT#BV䁅wW<5OӮ(i{8hB)[Hj 'r&,loH<+*~!ҊWP/p> l9B#h#煱.4siZ';VGfBU@I>T&Z/f J֋^IĈ~T ^+8QST7@wP:jY¡-(>j)% Zz^QZ!-Xw~/N)N!(\v{4斍݌^9ڒ5`O`cz߶iq$a1ȭ.f:SLϑfekXoN0Q}J n*i |*H-vJLB6aaY`(>N"7.ST nT-E(sy@d:WmevrFZ*4V=Z`_. =΋Ju<rS f;FTk-Zh1t^h9;(|x$ހ]؎kPBsv/'u!5N0. 5\q9_+#)  |skayܬ9˒% ""\Q6!TOkiЪzrˆrl┴,#4\@ԛ)sMhy@/F W_>wWx_>+DΌr.Ԉ_#f<1x1 3 X/T1W{F:~lo`rݠ(lE~jxn)8W#{̂KiFAM :WdZN>˹ Ӏ_.f]TB\/pF_.`_x۰Kj9yh5_.,-S4/P:/L+j3_.P\*.H~ Ǹ})j[8ZPA덐w P4CA;.6-F m,B6@/3|f,z"]WXPۿ*ˌ#E4ѻB~[ ) e,XVAbg##mBr.Mv;a ׆ion{2ky_Q6B{SoM*X2GԞ /ĸU5[*MJ2۳kCO K6<,=~8dAt~5i&P?Ra띑HQu;rT!-`YHܻk}k)N]>p;G>A(0x+ ir+0y|g|)YX?FMO(} >E ڴ;;EqAE{.epOK={F U>MGf qx8L.(V_dr|@@_>P,3< >h}3O1zMoʹxc+֜M/7.OvLUkk9@MVk Ը0(z5^T+Ow+RP/cI@cx۰{@¬OccV>'Sfc"uhk,>xQr(}݅)"PkE?Pe>.eQګw~~~p^EﯦE+Vih .Ʀѝ=mn)0{&G,XQBk7%a)h y yQ_.0_0x[<0wrAE#?B|1&l VtK-ލ\<|SAN#lR :G8ow)D 3\r|3?pz ڴ.1Á~\7"d_imG|*@<.S%(*2/^bp u1Zf}@v6G[>?r{Y.0C>/WZ|WAǽ,(3m[Bѷ<-(}!Y<‚Z=.n9}~>hS- (<|c,GmE!zGXW|ʷ.^D3e B>/XڡIۡ]@~WZ}t >w w/жeC=_^]L(z!z|z[r#/mbI?EPb􏺂`mPEXgW"\13}w^09X wiC= o`NI @mٞA9Hdr ?`V?]{έ=jZ;y"`/Ԋt`ύXξY!B?U-+>mL'j_lwVX)&C]C55JsQ ƂaVm %A.~[;:DPh1cZhB[W.PU3,Gq g/t@^!f^FJV, c؋y(/*q ib֜P+ldQQ6v(\P=?dhd-PNw#Ȯh>4Bj[ŏ=.&>9lWk0Z ԓ cN8 Ɨ;HEb1vQECbS`1vhcb#ŷ\#7U"3)>sSgG ߠG80_fmAlB4`/:Y9ĸ%ǮW~lhݳ#5W= G_ PSrb9`h[ xEٸ"9iIo _>4c703ŮWJ_>A8ny{FP9 "`: _傐0#m !{Y 7#m- Ѓ.!.zW 8@Ao)N'mu^b]sՋj$ϳ 2h/* }tL>֪33e91 .=,GtZoq8^mn P9UEi4\ LrA/4Q_Y6KP`s}݉8*{'`|-* 8[DMnĸNqT+*zd o8mPfp]H^zD#{j-t9;N{Z е;SdIU b/,>1 Oy?@ÊR}462t˾)B TATNфm 8/Gf)QZу*=J.cۧMj{ąGGqG}(a)]h9R۟X=q0E2-,<eGw;N:@G ãg )"tH-p!P6(YrV+"^y#S[/(aη3̺{Y@e pܮ) cl,SHښSG@{Y}gP{w"֋bdGVpH=-/|Đڭ8"E:jY¡-(>j)% Zz^QZ!-XRSU_.rXGgua/܀0lDIgmZ>3R|d~f"SX[jǑl ;@L1>GBysv2򘪤) PZф}է|—+L?>t^h&,, ǩWPfqerW8lA>h υ\y _}k^i ^[bDher`zw`>b6#8/*M||1NM/QɃZh1^!?^l9_k:97`6To |b(qe>."LᨋB׌rAq4Л|8RȑR|>X Gz, XR( !. <|%`B>FSx0 e_0 P'/'[IZs'n%E L%xC_Q#0 #X}ș_.Pw_k|ɥO6ܽox$?Pnj qL7Wi37G#/g?s#}]pSwH/s2 &D1-}޲~OW2EE9ڶ3r|5/KC .'NVB~hcuQ q1\y9{m^,U!.~?sF 'KT# FVs/}J-زiW9+cHQ /ĸU5[-bSnF0]@]xXl3am@.jҽh=~"ô;#0w,B&O!F @v(St]8f#W_}X(ZfwXC=p#_#?pe#<> l޴B#>p)j)Td`?K܀?POxߥ{E>*wh=@sL![}.L&(V_Wy@@Nhqܾ/ Uq| HAos92Oك^b9Z#Wuz@E\w\wo@|JJUH1M> 3EHw_˻@/zn`"y a0Mq8@Y]DE~ jٓ? t@`L+dao0z.)? G'>P۽2VVTF]XJlov@k1my\5^T+ϟHAA?|Kz-.o@XLYA֡Cz@ZC9 g/n|0PEP`\;t/8z(r*`[_H9=lP&p既EәmZi} .Gk|n(IBèBk7%aS+*^ v `#owss|]ˑA!>CnO[໑L#B~rDa3fA> xL!JJ|Aŗs{M))צ}v |T;/ 36!̒UeԊGsiG|*@>@ۧJPRUd*_bη#9n} ൵(-5)[ jk/8;"g-WA߽,D6[\`{[(rV n9|>h=} %/P~//$c!PR}pŧ6c0bEbb EUaX/ۇFߑ> X/mk٣`5|` 5|`_.4֌XRAe?jy`_>P) y^Gyv763nc%k^6%[(7SR1ĺ[c 2ib9`s<‹)0+W\g/ T7ZGw$-wO~Vy9vP7PķmSfoaؠVK !?.ZwiW}hOUr%a8_ )|OX3 <[}7,D_ydыrHhI0j@=O]p֐7=@"L @]ډmE9\RoYsCoa@٣D _߱0/"Ѝ27G(rF CW(~PT.drh1it~AqUw5__ld_7 %js>>Y@ܽ`n q!!3 DYIZ)?D(nZ һAt~aV~[ZLQ|t)0h}gLafJݲ R"P&v2Yt+juWkuz^}G0dиHKUH( )7XzH`nYmo`:Q^-^Sv+Pv~P5Lt@o8{{ 6 Lj:{GF!+JZ{$Uc/摢8|VI+T: Г[s `fB/EGِGhJۡ(Rp>@"J)@8k400Xkon] 2| ,62k+x B0[BoCLa _>@шG%u(} DG]Ѧ^Vc78 nLU=&Fk04yyǜp/wc50 >L5uC;bS`1vhcb#ŷ\#7U"3)>sSo|` _yYvk5ۧd%0~ NVa1zɱՀ{~ڛse@{e5* 8[DM݈N8}?SX0S.Ꙓy($PC<Nr5t+KOhnz_@rGO_fZ]{H%U)y|_`PuBV䁅wW<5p۩fwhÕ :n+|qU'7Pny{ ,\h#8/Gf)=h/HH\4ǶOB]d $87i4bkam{1B0A\8A,{8^=5x( χ 2qr ;N:@G _"V@ x1]M-p/mD P|娭VE셽Fb_(aη#f]B\ 2W8n 腱Au6QRG @[s*6D_ʅ;߻|D)L^0#Sl?b(G5P̰eR~0o uCW[Q|nRLcOA Zz\u iXˆh uth^.i cF3B-Y5PQާR݁TDyn0o^Cћe)*ʡ) ۟#jF#\hΕg`ݷ셜,ˡ bDhe8|lGp^U N/x%`/cD s#J8y@+R-f5z~x$ހ]؎kPBsv/'u!mh> ^h \{k_iP/rԮr- 0>gYPDC]$y@>+J&j}1i/L_G #pJڀyh[/|zGB(f ГܭZ^Np"<\.2][V_!rF(ꂻK= n7ٵK{,ڣm&׹{HTm}ep޴@EawϏ)=pEIg\"ڀ`4tx_H]J M 2Mg mW5_Q[#^ih9}f>RcE}਋Z)jP|miioPP7_ԍ=ർ/x(Y!r̽)`˦Dp_!G":M_Do)̷h啀 dηgGҋeԅ%v1\PTz +:tr(tHA0Hx:L9KkuHo ubPu0(>}m?r kfceq/(c| ><O~|/R԰^F'.DZ@ T#Kq L G]l|@kqK o} tܒx'qh5(>(38n5<4g29X} O˹@@M 8ng F8CoFn08RPilqPQ9#/rdZ"[s6>N(Ssv@uWuW6oħt)_.C<h)BJr._:grY5݀`퇰Dy?ypb*1Jn^Z(li,Mrh)Ώ/#ûwox:!F>rp63zO UxJw`*ؕEw;)(倂Ws,h. (Rd"| Bmxͅ׊ʡo/]"2 [*Rp̵Rzwn99 Xk:"G30LEQ[?'S.*Zm#QRK,9F@њa۳8^+}TYv@z@0ӕAŗs{M))"M3A8.`w_ 3E)z;b|ޞ# )-:OT\x%,Ŝo-fj΄[_#h>)hs̕g8xrj\w\ k^c\P-f nkX]E/$GX=-9uvA#` O58Prnjrׄ}!R,+>،˸v|l, >p;߆D _._ۇFߑbP]h _m _~흑0m1sn(9`bb ĒW\0}1b]`\EyԜo=MY <|8u o`NI @mٞA9Hdr 6/0+W=]g jZ;kx5W_^8qy@vw 您c S߶{8L)_..:a(9~T1@ JK,o/g?_mRGjM{a 2_>P#^oeY\1W ɵVⵆԮ* a8pX%VP(\17Na]xȵkvV8"^Zӊpi0]Pr\E)b -+#q@Y!`L|-٦0WC)ipq~)\Dž Z0f%[C? F6csV/`` :V?0w j-(C@;R4@P(ҡL-#\xE *uEo|cb>f O( )7XzH`nYmo`:Q^-^Si܉pkqb_PE ?ϝ.3s/xRj[XSɓ\baJӼ>e#Sti> ti}k `#1NU38J z?e35_ j =o]9@U <9{7=py`Cy/}h*˹GX5b)3Jz^r9MLܚS3J_>)Y} y"@T-"Yǹӫ*`a 2n]@d 7x*mYlwGǥo 8A 1-___0KP@D#M=6PHmeb`h DS>r F5/8N0R``fGT`h}Sq`|<by@|6k ԶֻR!P08w0~_xęYvk5ۧd%0~ NVa1z-|mX@gG ]k,{h.),lr !6LqEsړ*625\dSW1vwM cQ@r@4ЌT0_NbX&_.bX&_( !S}l~fZ [>z0E{q"@&/8@k)X\lf \ X0uc V)^ ɢ_*@aT4Phmk`@rAecR _./ `mq{{8 XnNvf{l=hmsKʩ*2.OG]`b_./ \S1+f^鼢yEs}݉8*{'`|-* 8[DM=n8NqT+*zd o8mPf8Հ|$FT/= ݶ?T-7|w1b]=[|D,JTc.xT3< xj`]Pp @sp<[Hj 'r9"A(}d@KB!?؃*=J9ied z爠 bHsrۧG!;hBt܀#'y/˼怊|(' `:$E1j)% ZzhBZ7/D9Ҡh^.i cFr@r%k Fx)>2m3Z)-5Hc6[]tj F s#!R݁TDyn0o^Cћe)*_'ڲQ<Ds&Xv~aBNH _ڊ'B+3ӻh_._J^(Ljj;5;``n`cD 'hE żky츆㑚xvmc;Ae !8Q"(:/p!@of=M/p#}r- 0>gYPDCZfP ZG~Z3SHadNI0-tKi`N} ԛ)BO.^Npk VRTC3NzwoV_!rE]pw|V|][8ɢ=f} Dg}}#@aF.޷#՗3`pEIg\"ڀ`4t_z3M?vb v/ jaT !!`w2j9Z0BOOͱGzprnFP¦NVB~h9cuQ q/pFFۆXRB\/?<鞐 -p3rAf\Q F_P\*.H~ Ǹ}oV(>YRj6CAtq%eQXk^-h}g L9YE뻮|m>r(_I@_>H djo($mb *gB "c<79@mʄgu"_3E  -] + 'V/x(Y!r̽)`˦Dp_!G":Mg{|KތA ]^ @|{vt )haE.<, iƿ$&ݻ\6'RPj;L{3)*{G*dBI7ϱPu0(>ce/_;܀/0+ S Oxd4wVBՈ`8"a=Q2cPڡ\R)b^]jr tܒx'q[Gh8 L![G>kLxZbooq;\P,0|@|z3rCl   xch @,\]xN(Ssv@uWuW6oħt)_. Ph)BJr._: kT3a w1~ ,V- 5=/{Bl/- ȴB&Sp~9[4FGZQqPuB}%6XmZ @|=ToD v~#`*ؕEw;)(倂Ws,h.8Ɔf2>0#C/6NLr/wx9Bi5ݢ?Pe.`\;tvOG8z(r4\. lbkO,h ƶ"C7,WT%ݜw0Rөm}z*tf99^!OU!O54ؿ[3kl`.x`^G#  )- "VtK-F 0#B~rDa3fA> xL!JT|9jDrX} ڴ.1Ӂv  3'lw=G Lk8R[T* u%{MP~9r 3XsE9mkkQZk,SP<~{Ԋg8xrNjX،{?D9$ >p;߆D -zC>Cy{|y+>L@;@/o[r_Xz\0G1CP) y^GyOjMYgrvqiC= ouu EouɊ 1bi29+@מ vk5U->|lф2\q5ZG ff@Q9@.9 W|9tKWa(@0!Q/@ @Ӿg4_+-Ur%a(9@BJm0{~6g%t@1,zQWo%`]s`kH71*㵆Ԯ* ڑ@@]ډmE9\RoYsCoa7S+V8"^Zw]) _A/^yʅLe Bjo 4:8xdwq@4м"`#+,\_> %js>>Y@ܽ`n q!!3 DYIZ)?D嬨 7ɫHc׵m/ Kr<"okZ)՞."B"x`fJݲ R"PB{KH/ -uZ7T:[VǼhWr:\)7XzH`nYmo`:Q^-^Si܉pkqb_PE ?$*r@EK: 0T$WC(E`̋.# z˦=]/` `n1(3U38J z3g;35_ j =o]9@U <9+֕lM /DM۽#@#{+~ P t3c؋y(/*yR41zrkNLC(y+ldQQ6v(\P=?dhd-PNw|V 2n]@d 7x*mYl޲$( AT\x;րS؂X C}t>H4+`Զ{^&v&@111*`XȈr#94_# Ƙk` |Dj w@1 ƧX BʼnD|tVG<@ |zQm6 S3,V:k ` 2Ը٧(GbDӗE1:o a?]̴XqO"KR_>+<Ռ!+»+اiW=*P,O}#R ,\hrg ib!"R|PJ_9}`$9"(ҹ?iy@h{!,H\GKɱ4E"xPQAe2; _ 8Wn#nj~ cm!Dp)[eu{a-b|/u q5BurDUN{U`f8V Bu @[s*6pDg ʅ;߻|D)L^0#ӽVLOվM4`VpjK ϭZ)B~qIȱ(ZG,[i<)EKo:E]vL^hnو_||<\F%k Fxm3Z)-5Hc6[]tj F s#!2UI\0m[(Gh‚kQ}J n*i |*H-vJLB6aaY`(>N"7.ST nT-E(sy@d:WmevrFZ*4V=Z`_ =΋Ju<rS f;FTk-Zh1t^h9;(|x$ހ]؎kPBsv/'8oCYѦ. 5\q9_>H!G H3`Z&`57}β$`I|7.H40}6WM>bqLŒx0 %40 P'/'[I󵼜n%E L%xC_(L'r9r.Ԍv+G̮+x~c} Dg}}#@aF.޷#|ý%qhSwӀ|FZR_.@wЌTki+ :WdZNԢ#~97^\p96urC3۬W 932Ώ/ '6Œ}]Br(_I@_>H djo($mb C8 UȽȡ~ b#W(_pe N~'L9%ޠn{2ky_Q6B{SoM*X9C:*E07u@/D5[*MJ? ɖ{ߊТ.P?C4(k"q!@oϮ ?-OZPlۅyXҭ7-EM| mOvzg$RTp xO?`<<+ 0 ,J|Z@ T/*2}68Rf{ 7TsJX}(3|஢?p.6q/$n(#z)qwg2@z&\-U1;q;\P,3< >hCl < xcb c.p'Sfc"uhk,.PVP|(P4TnTxk إ,*W{;{R9_.@zNi. (j{`EE@]jlZ݉ ٶĢ~oD  v:ճm][Oy,G-LZ_.<Ոr/0_xV "_>^ݡzճ+}^ L֭Pbu,a|÷PX87[x~86M~ %/P~//$c!PR}pŧ|u`xoGh1.`ې0Vvhvn!6߱ĕV]B]@Ȅ<J[m _>0BLWrXz\0G!C|"S "\13}w~`nsT ,"!C7-@'+6SL,sο\Yp=@+i<)d|lф2j ?jE1ip */o=Ʌ/P _>0 //k@ @Ӿg4_+-Ur%a(my:q@P\7%yG(׫.Z05P`O5v/b0 @]ډmE9\ҙ\17T7*rU8RxvwwbZQl:|@kr 0%/ș_x>Pr\n(SR{[ VGŹT#DkhY!`g 0/o6xwtN. o07븐Dެ`ۖ&gu&y)bqV/`n!YmMPk1EETUTH6LafJݲ RCJe]B:}):> EHAyWԴַ`Ƞy33Q0Rjo.S LݲB#&t {g5.0ޝzm?Pݷ*H+>5Lt@PhyЄ|@U <9{7=py`_c߽#@#%PYj0@"J))Յm:[83 + n]y 2| ,6k+xPrDߥlPܽo ű_.Ghƞ_>`ԡ|FvE<@!]}'(7<r F5<\cN8 Ɨ;HEb1vQECPL1m)0G;l 1r[ *P^J rǹ)j7_>0?\ì~MyNj`6! [{bc׫?V4ّE>Gx=hrcCD,bt^+2uE9&hcTqG ?UL3\A8ny{FP9 "teESr BÐk7@+R`n}>) `Z! D"L>{^xKq:i#~E >WpY)aj ATc:3SӽCmkq4<8{{PU4Phmk`@rAecRjˌrc4s(&=wA =,Ǹ8V$p6yrLӀ=h.0wb_.4Q^鼢6 u'"쉞MX)QaKhSWߍn8u3Պ좞)Be(>Իs#1zIlCho a? S{bO"KRx_`Pjy@Êe_p *@3(*-g pJful4I2WsD0A8/mp|aD0A˱?qX"ip{j>PxCP&N.8CRD\}("6G"V@ x1]M-p!~Q\`ՊWT32UI׌rXo MD)70_[ #(OEd: Cq?|\vUh"-E(sy@d:WmevrUhh1z"n9|%01h{k& >>x^ .x@%."LᨋB_ 3q8VaQs%-c6AࢋD3(gsE ؄P#f?mڂˆ@YGLs㑨r@EsEkPʼn yA<Q}9CVnPt% O " #}7"@҈rFAM^p[_'LCS6Z{@9RPЋ[M\ЈmE+Ō3g':B\/}iQ/nÌrAf\Q _ ֈEI^ޭ"?۠} (>e\XdWvqڀMPd%b\Iu͐ƒ-dh@ >̷l`fɢ,@_ukE7@oJ,3@F an6B 2q,k ]1ͳY*A!j[P&<|QQ=/8SԠ9.S-6oALm~"5=ർ/*ld1ݗ-زiW9+cHnG":MGD5[-bSz:Bu\ SPnSTdzm8Rf{<7 *^{]:=PWU.V|@D[8(|A]G=k2X}]*7Wd*Ew7ü_7#*F8RPnq^PQ9#/f~5g= >e . 1-.k*WЊ\GB^4!}9ćR/xAH~C[])y`V_Fyܻ<8˕ zPzDm=O>B|Vn~o0z.)? G||w~@+^+N#F>rh- V]׫bxJw`*ؕEw)(G J^ͱ^lJz Rvd"| Bmx׊ʡo8b|`s"[=.eQګw~^ >G 8z(r<BI]@uM,h .ƦZw"xE]u=Z#ts`c GƦ }LS+>p.Vz_> *##^0\PHϠҢݐ)jEL#B~ |@ 6N۝,@e Q)hs̕_ 8rNZ/xxl4>_(?^ & ɘGm`9\)ff](X, Z!a^6$L#X/-2@> 2շxA4c>\@ֈ;# `~CJm0C`<4ͥk17*Sq7?p]5.*9xD5=xnc%kY WXx EsJj0r ) O^L,u\YsV j\:#> jE1y|b92Ep/ķmS_:aQ5 jW}hv,o/g?j@BJm0a8 cAdz P#^}FEK 1W }*㵆Ԯ傹ozD @]ډmE9\RoYsCoa@٣D _XMG u#9# _ \-ze Bj}82/(}*]\ v4!`#+&e-٦0WC)Fvqq~)\Dž Z0f%kEBڡu&y)bqV/`nn|DջS_~ISq P̔ePEj@Ym_f Emή{5q=HAYܾn2hb*È@Lڛ, T=0SGж 0lEvTfVž:;eT+)j#傊Lt@5JsQ ƂaVm % =YM4[ Phqk{$G8g l#B/}h*˹GX5b)/J]9MLܚS3J~_`唍,>ʆfShM[[|K5R}SjK)!P08w0~_` _yY2;nxlB4`/:Y9ĸ%ǮW~->"XtPi=`@:jP,  byat:7P1'=b#k/D94 LՀ~_ |7 L=@/aьrEfЦ B¼/_/Hq۳)O,C\ Y'd [I[p/.E@YOT/,V:1X̔t/P,zDfI{0AEՍF{жV)pT>V!F0/w\P }b4`9]7D|3i=4jERU)vy/8ӯ<\P/ДF-bT5@k)*~_w"ʞ ؄لj 'r9/p_>b!"R|PGiEBIfiPUAVܟC`Sn4r< rMȃpz4E"xy\PQAe2LDw0|tn "/K+@ЊȽ@> T(o_0KZjE]^+od*vb|;<`%E˺*Spv L^Tgc%~w hkNEF~QY}gP{w"֋bdGVLO}o uCW[Q|nRLK@Dѽ`aBZ70\ C_>Pv{T\FƖf B-Y5PQާR݁TDyn0o^Cћe)*_'ڲQ<Ds&Xv~a{!'H Pl1z"n\0;01h{k& >>x^ Qm&` Vw(AHaWtm:/38$`6To 9P'|\DQ\h7r/KjrԮ]+r- 0}#?% ""\Q6!TO9`2@YGLs㑨>Mnzf~{~L({G7(J:[^xE Ε4軑Z; eڴQ)pk 6#5DxE)Hk,z-_T^?ɑz_.f]TB\/pF_.`_>=a/AG/"i츞_['($#`rzn/V`wAmP> \LQ+R Zox#U  ]lZQXiKE-L0߲)'޳}}ו-Gn+ /8RDVX*m2SԊT&΂@|mD+ƾy6ro# FVs/}J-زiW9+cHQ /ĸU5[-bS1=zÒ `_>PTz X@*ހ7շ(RTY8g|@HQׂJw\ H!4P/(.`/pԥxnTuJ{X}(5\/6$>p$Q#Qx38nu<|ǍOy@@?qh}3C-hrdpdE{^Ol~-ȧ:=L!]!]!ۼҥ|mtV`>rd)etb出[s=h)؎~=AQ8w1ypk+@>i<^{Bl/- ȴB&Sp~;#|^'Sfc"uh))bTa|./]"2 [)8^Zv)^@NgupW "wW:SKoȘf Z!ZE"u/ AߚQ<%Ģv F #t{Gѷ'?.ۣBcsX YvAz`.x`)X傊Vw-G ~uLT+1F0/r >IyXoG(xxl4>_(?^ & ɘGr`9\)ff](X,gh1y`ې0Vvh@|(_wKT@rm[#Ԍr5\0熚_.fhKky@,4^5<0G/ A_3b]`\EyԜo=MYRӆR+,"!Clce{:dEyXSL,u\Ys=6_ZWocS{_u > jE1y|b](zŗ\@tE @0!Q{hvUyk `Cė۳'TPkiP+z>glxz/Adz P#^}FY<1W }*㵆Ԯ* ڑ@@9)xB,Pl䊹0a WчH"gwwb{̦#^Zw=)i"g=tuA˵Wr!ELSH@GŹT# 5_hآ_7 %Tf/@o#F#8{BB-fz͵" !ˊpZ}1~n(rtv9f5A׶_RTpT03n)TiZi][+VpQ[^jMܾC+RPql/|[=%^G 8G B?U-+>mL'j_l1{[8L{'m(un) b7(l*ϥ0=6z23~jlP1ӊC@'q_~_.(ظЄ~\fYJt6&rxa_ʷ{GFV*fƪHQ ~_.U  ib֜P2+l{ДCQb}E SD#kQ87pz=h`a ro] 2| ,62k, µ&K`vprg0v,{{YR>:@|$m{| m?LL|}C#Ɣ^cbThC3Gy r)Hl0\`P# w@1 Ƨef f``2tZX0߲xdZ>`(5Pmr[I[p/.ZqY)ay Xgmc:3SӽCmkq:7<8{Nh` 6N<*ԈP06=wA =,ǻtZoq8^mn P9UEi\ LrA/@S_>Q_Y6N+CNDQ=бS6HJ– ѦhS1.n8u3Պi]3%PH~álŇ7|`Jv#1ˢs0^P;N{Z е;SdI5Ǎ2.xT/Bؿ+اiW=*P,Ojp *rg(*-g pVl#!aF hmX6I檠w b+t!0)}< $xq.Vx HZ/ *"!L\&pt;E1<^~_Z7t57(ȱ6pIs@*{hE]^+od*vb|;<`%XP -V:WX'թO$@mͩ/ ~_0+_NU2z1SP´^LJ F`[af2)RD?UT7@wP:jY¡?!>j)% Zz^QZ!-X{_ӼyS3l.ZzpfBsF3V<\F%k Fxm3Z)-5Hc6[]tj F s#!2UIS" ^o MD)70_[ #(82 ؄eu|8 >.LQQ*P1lA>h υ\y _}k^3WAr8|lG8^(a^ 1NM/Qt'l)M6Ÿ5Ԝkq *S7v@wb(qe>."LᨋB[rwL-~eG 9R@j@8+0Ys%K AT?DpEﳹlB֋r@Tex0 ey9gx$Ro=x94_ Ho(/Q/`:_`"g@Q]ev+G̮b>&/^׹{HT@EsEkPmbDYwty8W\|FZRZpmj7i8oPhGE­PxEh?=5˹`U@m : X mE+ňrgvobI; q!t[]ޗx3h n{ay 3uT/ 3~3!`mwAmP> \LQ+R@cƙ,.zG"E:4{Iش8S̓%$L/3|f,z"]WXts$2 H djo($mb C8 UȽȡ~ j[P&\eNB+A!r#KAA8~(Z6S *RD/@UaqT)/1nƳM`%Ė/b[2)ha} d.Òno []!]]Ԥϧ@Ѧ{D JmiwF"E#azXRL0i˱p xO?`<<+ 0 ,J|Wz@Bhz_x(>P~Q2cOߥS{EQwtA{'q}(>20S73|X}=s*_.(Uq|cx!P]Lc1^dmrGt2>Vk 1-.k_#!.@fR[[C)旟f k=F 0nAb| ,vdP6TQgO-KKł;2_M3gH(_Tf]XJl·ZkZ @|=\5^T+OW_>PPj%bUG۰OccV02 `pfc"uhmaꓞP|(x9Bi5ܢH2bKYTev:;ħ8z(r4\ZKoȘf Z!ZE".!-Bc;AdzmwE7}=5>Nz X1ۣBcS>nJf9S+*F96Lavqb:XkCA!>E!SD?Պn{ L3B~rDa3fA> xL!JJ|@ŗs{M))צ}v bmzbN۰9Sxx2}U+y >@#UyxC}OT\x%,Ŝog 74w[xm-Jve ooZڢp/|ֻ_^c\P-f n d Bȏ}rXxhm > P&`?G (?FpM1( )> rS ̺XQX#@CŒ{Q=`j&mv"`;@\i%d> X R-*m!- _>0E_!B ĒJcUr/ A_Lήn0Ts"Rç,"bY\J<7 0j@=J֐5|-h+df7\9Vt h'p#Jg(6rPݨU1{lHkvV8/"Zܻ;LI3(rfޡ\{(*2[h1.4pd_P@U6SE ph1@ԛl} C/+Mj=RĘuvKC;p<"okZ)mHLafJݲ RCJu< Yt+juv} \^rVǸz3R{pTfV6l-һV}uvC Oh0Hp5\2|QrE9R(,Ǹ>b7(åWǜ}Tu̴"Pok(A4Pjl~vP~# -6:RU3,Gq g/t@^!fф"3)>sS7̭Y cgfmbxS42M?^'+0wj {v`x=hrcCD,bt^+2 yIkOzs;rACӌSeiQI?!i hy3 "BL!X&_>0]4/xEѽm !5\)0n>z0E{q"@&/8?"ozUF \ X0uc V)^8U[D=b=*^4 ؃5MӠ2 )5\e91 .Ӏw| :sF#o[TNU)vy/p_y@/@S_p[LŨ kt^ l{aP|~AQ=бS6HJ– ѦhS1> 8q fJola5nLd$WJQ$F! 4\冏6qgj'ؙ"Kiw@<^Xty#_xw]$`~>M@U 7,gy@ "@NP`DBs_>h9 >2C@EL~Jfͱ&\tmx$}ԇFmh< $xq.Vx HZ/㞚TPǡ;`Gw0|fK6|^rYt/D Hxtc[9UDG-/fIQ[ {Ln9\PÜog ̺{Y@e pܮ) cl,SHښSG =\`V.DYޝ#HAebi|esDq?f-"ESAo}St<FICW[Q|nRLK@Dѽ`aBZ7`/N[#̔}ffزi%Ur%k Fx)>2m3Z)-5Hc6[]tj F s#!}F*4@wK-q?p(>r'0SV߁ >3;lnˑi9Ƌd>tk&9QP`j큐뮐mOR6:]]R|0 9!}9ćR/ ?ElAo(4a=3br%Ƞ'-TQϞ-KKł;2_N`0:2.xxw0#C/6NLr/k񺋳(˟4TnTxkإ,*W{;ӟ{R9at@]B(i}bP :-ivt'h϶uWT%ݜw0R~0ThtUcB >+*n Dy\m+xF__ )-z׽T\DZ9߾/ | &kS{s+{hc/p~;wrYhS}[P(yk¾y@QHQی{?D9$ >0;60Eav !^Ф/P=&`J.!SbB?!az `5<0m/̹FZ 5 Pb_F*2:P> 9fZl{y]; ouu EouɊ ͱ#&X9reu|j]Ň-9P-ww5ZG ff B@E+nV7,Ԋsɳ4D4q7@Fa4P<{FR0![Qo[+>glxz/AdG(ڍf1\-(R'RnAdorNl+G(zBFx rU}$Rxvw U y@kra`Jz_y_.]=Pr\n(SR#it~AqUw@ 4,ߋ2lS!ldpq~)\Dž Z0f%kEBڡu&y)bqV%`` :]GYmMPsSE ^Of-{ *2 5P+ʺth2S(juv} \}yE *uEo<b5Z2<`9\!:eGMDe.g{-·x[8L{m(un) ZHQހ)@EK: 0T$WC(>p/& cn/ ui}' 6r3^ǠLTu̴"Pwh9A{Ϝy8:ro -֕T#Qb]?8f^Q/@/Q}Sv/ފ_Be9 X5b)7J^29MLܚS3J0S Y} y"[hL"J)@8k400Xkon] 2| ,62k, µ&"#5 1`;{m|fP|,Cv >)avD ?LlL|}C/Ɣ ^cbThC3_y r)Hl0\`P#TSwh0)m0>fShM[[|K5rh^J rǹ)j7׿_~׿_paV̎[<^'hdna50еVv`kyC^rz5֊=;RT {Z{Z !ACl1:/lNg<椵'CӀ뢊rhb׫G% 4 ASi 3 "_P~҈2 @Hc`2tZX0R dZN-xS6(5Pmr[I[p/.E@7`eW +`SL)OR H {8 ؃F0{жV)pT>V!^0/8FC5piq>Ixm4jERU)vy/8ӯS(c@IF7\4ǶOB]d z爠 bHsrۧ^B aAu&G>B]Jy/˽恊|(' `:mrPD1>x^ Qm&` VwZ"b^ѵsv\Q㑚xvmc;Ae C %qE)uQ 8z;E\ԍ2#) g>c 1\ cO`%`I|7.H40}6WM>b-*RcE->=9rC7۬W//obI; q!t2[]ޗp#fV;G { ɋrl_P\*.H~ Ǹ})j[8ZPA덐w P4CA;.6-F m,B6@/3|f,z"]WXts$LH dj[aPGL1̍@|mD+ƾy6ro6'RPjwG HQu;rT!'EAk1pO^he P|ve_{݀0+ ib9zGn#_/d#y!E] l_ .O(=pDr5"@mڝ"kQ2_Pګ.5p6} T+\`{SAN#lR :G8ow)D o/Xh8SS>"M3A`wN۰9Sy2]V{GLs´#Ez󆺀׽T\DZ9ߎ/ 7Pڽb nnyse-~/wLPj+}^L֭Pb,a@HO mXoA+)b6^G(<@\5a_HPb_f *2:P> 9m;T{@˳>٥kY WXx EpC0Xo(z['hB__[j ?\ڀyw 恨c S7Pķ/ nV7,L aGoq@^0]UB=Zi- G/kk )|O,^K>Y@ܽ`n q!!3 DYIZivheE]I^GsܾU/,,DkoHi u()bx}?*SR4_^ص? ~?̢[Q[^jMܾC+RPql/|[=%^G 8G qU< Eej(QX"SEcEfݳ` X>PίSyR_l ֈT)G(50<-vj<@Wo"aޠ8k?z `#0(mbO :fZp;4c d6_ -6@-4߭+ `(^t@gh(f偨|}hdo/JZn`{1Z%ϩfHs=5f!\a@4((Mi;E .V[D 2E4s(sff|'yVd{ovEF~_`m%T#Q{)0[BoCLa _.h@؎P@D#M}~@!~=}'(7 r F5<ef sa{~ja9{|i|!.zW 8@Ao)N'muĺh[ġf`e\ X0uL>֪33V! _z#P06=wA =,ǻtZoq8^mn P9UE%/%7ȷ8ӯ<\P{‰ДF-ҪojAON+CNDQ=бS6HJ– ѦhS1.n8u3ՊiqXTzc td';!P:ؕĈ'A4 aT-7|4<3ŞVt>Y.bU O:\!{wX{0K]Pp @sp<[{ ,\h#FGf)±χG ыrͱ&\AAl>90O~!‚:L|K^$-wOoeP&N.8alysNzwak鉢{E:jto`IMUa a_>Pv{4셱e J݌^9ڒ5`O`cz߶iq$a1ȭ.f:SLϑfxyLU甀`¶-V4ai>%kE\a@|%Gyn0o^C)*_*FԖ"G < 2+6 o 9Y|FZ*4V`One`zw`>b6#Z Rȱ_R${#Z V0Z+6xΎk8 t3q8VaQs,Kw~ࢋD3(gsE ؄P#f?mڂ3HadNI0s[HL!zrro+i|[ISA Pć )0 ./9#ba[][8ɢ=f} D_T1W{F:~lo(F^UVnPt"G?5~7+7H]J M 2Mg mW5_r5?6-!#~97^LmaS+W!?\!hnyۆXRB\=g %5s{yc nr1n_obZ<Tz#d@w"<MPd%bbt̐ƒ-dh@ >̷l`fɢ,@_ukE7@oJ,#@F an6B 0`!_[0f{CAԶ\LQQ=/8SԠ9%ޠn{2kE˦yjs!AEh*X9C:*EPl6}_.Vk-!U|啀 dηg׆ҋeԅ%v1| v %"U8s_?u^(RTBu\ SPMSTdzm8Rf{uWxߥS{EQo}@%#qxuL!ۭ~ k2X}]*7@yXkT@|f8e[:<4ƋE{[s62Vk\w\o)#.k! c]LRj|K~(x BAfb{ThlMy,uJ ZBB-Qm^ KHT]ˑA!>.5p6} T+\`{SAN#lR :G8ow)D o/Xh8SS>"hp,A#{[lP(yk¾y@QHQn>`ŊxoC"<۳Zg[` KPlOyZg"3FL1M&`9reuZQoq/ZGw${A#^33@Q9@^>-]efD>"~>|.@ JK,o/g?j@BJm0{~6gWD/WydыrH\70j@=O]p֐\PoxrNl+G(zBFx Na=x \XMG +w{SRp|ʒ/WA؞[ܢP@)lbŹT# 5_hآ_7 %js>>Y@ܽ`n _Wuy_>P+2m 77pEsܾG/|_1l9 zۚbkH@;R4@P(ҡL-y/p&n_)8ulwhWߐR{[6:]JoVT::@bgaVž.l) L5uC;bS`1vhcb#ŷ\#7U"3)>sSo\0_N?X2;nxlBOu;AɊV! _z#P06=wA =,ǻtRz@SUdZW1[uW_.HAS_>J=+:Wt:cZ 쉞MX `TiA m{#pQT+*zd ɿLPfY|$FT/= m/m#Z}j#Si5@#RdIu;ڐMye!+»+اiW=*Pojp<[HQT.,\h9gEs260$±χG*=JG 5"`#(@-x-g@}0.Uw%Lt$bD9nO<03l)* };(il5>\>AO+,S]X Zz^QZ!-XRSU_.rXGG-u%2 {alh }7cWd (S6޷m`fZ+25f{Iyr믋Nmhzs$$n9G*_ ^`¶-V4ai>%k 74\a@|%Gyn0o^C|\vUp;bDm(|D@ "ӹl,;րgBxmE v,GMGڞ~xZWB9FT۩ s#HaWtm:/px$ހ]*SoCTt^N!8Q"(r"mG0z_p#}r- 0>gYPDC]$y@>+J&j}1iL_G #pJڀyb[N׷JB [Z^Nm%E L%xC#8@I-h9#ba[][8ɢ=f} D_T1W{F:~lo`rݠ(KD^xE Ε4軑^|ToPxE)H-j= s%!q`S+W!?\ͺ~P6 8#eۆXR̃=%l4+sDIWrAz_o ⋠؄.l s=6^/.<,ag]Ԥϧ@Ѧ{D JmiwF"E#azXRL6J;}<eS @+xe/_܀/0x+ib9އF5~Gy!E= lz_>pUP^)TdlpԥR<.=9]PWU>pW@D[/$n(#$`ǭށL>p T L$~rA`Ϩ=tgC-hd.pdEwL[s6t2>Vk 1-.kc]LRʊ'^)(wt 7ՈrmlǻȃX\2Iկ9|Aٓ? t@`L+dao0.)?PPj E -.awYLL}O, DoˡS8SĨy}b |(ύf*~ *RpRkۻ?Ӎ/~шr:SV%/Z!ZE"Է!@зfDI.ahShMөm}TYh y yQm^[~-o|$|]ˑA!>.5p6} T+F 0kx]J) 'A/͠G(5@%dJHqźZfn+xEiٮLAMP+^[_>^ݡzճ+}^ L֭Pbu,a@Ha-NNXn9ȣ|xl4 J_._>5a_H|WS)`HB nY򀑇b *SQr/C F>P.> 4:@AZld_.7< %js>$o07븐Dެ`sȴBH;.$V#E9cV/`n!YmMPk1E)0)L[pA UdGB{KH/3Xg՚}݇W,n_z_>=-VK\DyxĐR{pTfV6l;qiY;nb_v~PÓ`7`C8|"Sa8=_a{C@8V  aJm]~@1EqeSD.AFaPsLTu̴"PwhҲMz?e# -6:֕*G8g{ź=p͢ ^f ^(irj@ьg%u(} DG]Ѧ}hsY6ZgǍ)3 @_.p1'`"s ̂AA;"SMݡ(yLcΧucZG`kco)Fo@m{)E0fS|6`F?|` _Y2;nAlBOu;AOG㮗^ vώ,\Y4}]4@9RLYjP,  b?Wd:(֞Mv\k.rhb׫Gg p ~@4Ј*gD/NBL|`h _2A_^#Zvȴ\m F <l DptVG<@ |6Po SԈr+ ` V)^8D=b{PU4Phmk`@rAecRjˌrc4 0n]Pp1@t:-η8 F6"S4`?uW_>PRi:3x ZГyE>PpTDO&t, RҀ%@+Fpc7a:jE`vQϔC!)s(GbDғ ن0Јrߖ>~`jyf=})*P1)"v\!T#BV䁅wW<5OӮ(i{8`U¹ 8Y-G5PTXQUF߀3xVT>G(-c kCI!||*xSmX6I檠w#h#? h_tj=9Rr,7`9bqO*"!L\&pt;JN_.H/X7)A0S _.@ۈu{8ju{a-g yrY[cAI+T'{@X^fc T> 5"`#(@{\ (~;GTB[E0#ӽVLOվM4`VpjK O+,S]X Zz^QZ!-TTfD93EKo:nL^[6BXHVNsٖ7;}C LkEl# #@nu1ө7-vbZ}0-#>G T%]3cZ_^ضrԊ&,6mէ|mᦒ—+bwot:/4` +~(z32EE9v@ňڲQ<Ds&Xv~a{!'H _ڊ'B+얂 =΋Ju<rS f;F< hE żky츆gM#5'v\Bx9?J\DS8ꢐ =n;15ֈ#)  |skayܬ9˒% ""\Q6!TOkiP0U_G #pJڀyXs[HL!zrro+i|[ISA PFpr][`WR#|V|][8ɢ=f} DG*+XGŒ\ܽo#?67G#rL%O "_7 \LQ+R@cƙ,.dQZ ] K:ŦHƙ %F z u [603d{Ţ %UGh o)jE C8 UȽȡ~ j[P&<|QQ=/8SԠ9%ޠnyP|`#+D>%l41R /Uٿ&0b[A ]^ @|- bfLPlŌr@EM| mOvzg$RT o;qnyܕ4@C=p#/̃|p<6r/|B#.)^ ^~NiF U>Ѧ=9 _P|9 ` PdrA& >-U1o@`ר2=l[TT4ƋEnrsOuz@E BBn>4>Ko{H?|$XkW2S:/ߒJ1d4 !] z_ w1ypk+@>i<^{Bl/- ȴB&Sp~;#|^'Sfc"uh-PVP|(x9rQ̴(EP`j_{ؽH&`{_..uv]@t=PJZw_zNidѷ`Ʀѝ=m^Q}XtsH٣5>NX1ۣBcS>nJf9STT/D{pnɷ -ǽaV]ˑA!>.5p6} T+\`+*ꃜG zcypF./ i= D \?P^-g ~b5@f1F6l}f} {{@6pȷ2TJ>U"SqKźrp#}@e2u7AxmQ8߽,ݡzյ_y>vvL֭Pt]d By~:a]rGiE+mo Ӱ(a|B//\d#BJw3.^²/}&^G4J.!.vA4c>\@ֈ5\0m/̹f Қ_Kz/V|25<0}/Tduvur}#AQs;f 6Gu+_{z]0m(}g-)b-@6(6)bL`sfеu}>E~*ZGw$oz{5ZG ff߁rL\3m۹Ô2fG% Qx⻴ @Ӿg4_+-Ur%a )|O,"ebY\k7.Z05P`OSW5v/T\ {L NJ.ĶxB,Pl䊹0XLqU5J23~jlP1ӊCݡI' ]^~_.(ظЄ~\fY✽^?8B/y1<^FJV, c؋y(/*wR41z4+̔~_F@,ihJۡ(Rp[T-"Yǹӫߝ*00Xko r ^weW< va!7!/b4\@3rYRB@|$y-1S~*~w6ZGߍ)Ĩ\b f /8N0RlQG0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0~_` _yY2;nik5ۧd%0~ NVa1zɱՀ[+hHk͕zOE#ŔX"d9^t6ncNZ{[F{| {/^ 8*gwȴ /L/2A3ES3LЌrAqn0 }:]-,go|eS)*~_w"ʞ ؄e_p *9 H<+6M+4l ±χG*=J.cۧM*#؊} sam_.‚:n #'y/˻悊|(' ݡ] "{N"*x32EE9DQ[6 Q4Bt</5`/di ^[bDheݲopIGR=o9&^#J^(Ljj;5;``n`cD 'hE żky츆gM#5'Qe C %qE)uQu^__.(z3/4eG 9R@j@8+0Ys%KZ;mEfP ZG~Z/Sg;6`Z#io=#!z3@ Zro+)R`*(3p3NzwogX}_.Pwz݊ow`xE_}#Q}}#@aFWi37G#/g V视^se/ p7ԋ2|7(i"S-um=)*!\@-G F9H/r@m : X mE+EA e@L=q6;KjuU g>j-[_.t؀og/ 3빽[E OA97p1ExKQ|G *h;;0%ހ ]lZQXiKE-L0߲)'޳}}ו-Gn+ /8RD+䇹 IYv7FGu@m@Q[9"E g_"=@Zm~"5=}cD cEOI[6 0`p 8AB Z ̷h啀 dηgGҋeԅ%v1|  HqEHAWoOilhm P#`I2~r/I\p']=Lqra(>r>rlH _`Vru'0y2.{y|/RԳ^FW(]\E 9@EG]lznx?.wvA^QgT]E]mnI  G;p3|X}=s*_.(Uq|cx!P]\Q9_m1^/z74~5gmGt2>Vk 1-.kZHȱ֮d)5˹ >b~!] A5\q"wgvdP_s'@%bvVa /5\x0Sy'>p;>p=@+^+N3}%6[5h- 힃 ]8T ()(gcI@ctAѥ6.0)ɔEmx9v g{~qt?PC/x=LCů@E ]ʢrŏ݋dv{R9_.@pJu @QlcuZ!*ZPcۀu]_l[xE]by_}GH3akiP϶u >fb{ThlMy̓S+*FDwryx)/hurgPϾKMMwB?ՊnyL]"p%@C} 6)l9ˋBZsi7Aŗs{M))צ}v T;/ 3'} {{@6pȷ2T5 @E%b]vp3Kz<֢lXny&- G/{Y>`vS$~zxE1rh1fu+}X]E/$GX6@~mXڽ pC{<<ĕV]B]@ڶf^M-! _.+i!FB Ē/L1G!C|"S "\13b˳R!ӆg{B\l!V}ޖ OAwƈ)9_`V?]έ=j[|ؒ e~}=ofP+򈁼 */o_uZCj׈* ڑ@@]ډmE9\RoYsCoa<+/ʽ.4|"g9@˵Wr!kE?LSH@GŹT#ヒD8/vߌlS!ldw7|0 QoVRVdZ!-oE]I^GsܾU#,,Df5A׶_RTpT03n)TiZ=P%PVx5q=HAYܾm5|/`{[@z_>>\)42Uo%{H`nYmlSllwV ޳0kwž:;e'`!QQ_>P y#Rڽ %WC(<7tw[,~nPLQs{TѵKc=a{6v1U381~Nz?e# -6:֕*G8g{ź=p͢ ^f #@#{+~ P t3c؋y(/U ib֜Pr#Ȣ\% Mi;E .Vb~ Cfo0E4s(W;U`a n]y 2|o@\Yak|PxR aݷ2}03h1_>@3(H4[b)Tؿo_F@k1W}y`X3<`|X$6cY0(hUd;4Zs63lnlP+RLo.Y {)E0fS|6`F?|` _Y2;nAlBOu;AOG㮗^ vώ,\Y4}]4@9RLYjP,  byat:7P1'=zZ]4c703ŮWJ_. ȴ 4<!Ӏ,/.BL|`Z/ԈrV| 8q fE=S276P|_w#{V"t+KOhw_.@rGOcL4L]O3ET*!E]Gv{G(O5< aEXx7p#ߥOӮ(i{8`U¹ 8Y-G(jAT.4fBQT@n)>S(cUz0_>Esl4I2W9Jpmx$}^ǜAB#0n@m'G>B]J,G5@[DYx>`Gw0|6\cy還[Hx)/mD P|KQ=QՊWT3G T%]3cZ_^ضrԊ&,6mէ|mᦒ—+bwot:/4` +~(z32EE94e#jF#\hΕg`ݷ셜,>#-|k+Zl[/ 2{p^U N/x%`/cD_0070[1N@+R-] mmj9ꢐ[pwL-~e_p#}r- 0>gYPDC]$y@>+J&j}1i/ #HadNI02`N} ԛ)BO.^Nm%ro+)R`*(ʈr"_.tһ+x </ 3|@Q]jy݊olinܽox$?P\Z>f}yA<Q{WX9;AQي<t/5+RpE=3F 4g mW5_ѹu4>e3EͱGzprn0$rl4`*Fpxl._!.fpF_>?=a/AG#luz_Z1F#h n_>@Q<n+!`Ϗ]tqzSԊqX;X\m{ƭf K#4{Iش8S̓%F z 4 }&o̔EYn#7TYf)Lm @La(gB v\lxP?s-sC}.z_kqA!r#KAA8~P7d1ld1ۧ$ނ-}Ur8tU`!m:| Z}Ha%Ė/bSz:د@be09Nr|F~ny|+4?@߇#_#?p̃Y81 :7mPEG@Bh\x".eu~ⵟ1K}Ni*UghhZ~: ?P|: O`ǭ|&g2yh9I-}n| U&qΌ|cx @o Ƌ>myE?ݚ Gu@EBBBy >]Z/xc]LRj|K~(x BA[$Ov'( ],XQ:,Oy,@zp0;߆D 1*V/]@] 2r,_hz_6mky` 5<0E_/ bneԈ2509X c R9}!V}3uɊ ;cZJ}~е{q>wnmVSǖM(n=w5ZG ffx~*CaJeb4:ahonVE].VmCHK,o/g?aN^j`>RקmV%L/Ȣz_uђ`Ղi"{r x!y-h+dfj 9 r ޲@+><\G"a)c`6}_"Z`Jz_y_.]=Pr\E)b ]h4:8xh 'e6B/`{_&ߒm q9r, o07븐Dެ`sȴBH;X1݀׵wt ok:(R-T03n)TiZ=P%CۗBQ[^0D}݇W,n_z_>=-V1Ey !B?U-͗ Z[G(0[;17wE EI7PW{CV0 m B{@s؋A{L5-`h2#94_# Ƙk` |Dj Vb9nOy?aSl=RpTTR`<<LQsO23ev6*[X &Av`kyC^rz5֊=;RZse@{z0Ej(6-PZJE >W6H:`kՙRj[3й,@#pUE`m hS4̃}BJ/`~y_.pa ja eT(o `ՊWT/<KuT zAP06"JZ: h9F"7fBU@I>T&Z/f J֋)W1G`Z! j}_&@wP:jY¡-(>=>Ԟ@Dѽ`aBZ7< 䰎/-^3 {alhy }^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfe䜝<*sJ@c`¶-V4a{D)70_[ #(OEd*.MXXV7ʷSДOeEy.4LʳM[BN -FOV6-ow#fmO?+J&j}1i/(*YGLs㑨rAE334`5.3݀_* ҷwt⾮y8^j2W\Y7{̂.QL[1e 9QkC1ckx+2 -OGjQs^\~j[iU/pxl._!.^8#//`Om؋%5*[8Ң<1z -p/P: 3uTEI\c nr1n_obZ<4g@w"<MPd%/JeV\Yh@ >̷l`fɢ,@_ukE7@oJ,/@F an6B 2q,k ]1ͳ{CAԶ\LyQQ=/8SԠ9x@ԍW@`1O1ld1ۧ$ނ-VȠ6/=I,$MUop0b&O ֽkCOE 2Ò `x_._optEwQ].E)(P#`I2~r/Iw\x5yW>`>r̓)YX/`# J|Wz@Bhz_x(>P~Q2cOߥS{EQw)2U%O6s@=G%dbL&Zbw?@3}FG;#rmAs~ s#/rdxE?ݚ r d)u^%?b~(5܀?Elg|0q M{̃X\2Iկ9|Aٓ? t@`L+dao0.)?όp_x_>PbZb9Хz$RS,C)(gcI@ctAѥ6.0)_ 0#cbTa>@1^3Ed*~ *RpRzwnu'^E^La+ )SV%/Z!TֻشBc;AdzmwE7=Z#tgۺk3=*46UcDDcn+VN۰9Sxx2}_imG|*@<>@%dJHqź-fj΄w[x^Y1m7\?/|ֻ_^c\P-f nX]E/$GX=-9 햃<Gmd4D]j %A@e & qBJo3.V,m-0#}X/ۇFߑB\i%d> X/(ضf:S)`HB nY򀑇Xz\0G!C|"S "\13}w~`nsT ,"!C7-@'+6SL,sο\Yp=@+i<)j xW_^8q?P+ܛ@Q9@n"o_|.ZwiWۆ*Y9_ΰZ j/ )|OX3 <[zϗ 2}_(E/v#,.^E >uZCj׈* a;pX%VP(\17qOa]x)ޱ 0/"ZVvoP/CW(~r L^@-b82/(}*y]| h\uG ;\oy@|K)||Fޮ` Aa J 6׊La *G~v~ln_ת mzۚbkH@;R4@P(ҡL-y/p&n_)8um+U1Ey:\!B?U-+>mL'j_lwV S݉pk6j~Ij3Ek*2^Զ'\md`Pn)cn/ pi}' 6r3sQ ƂaVm % =YM2l|P MRU3,Gqu{:E?f ݋>4%PYN70VGhZ%=PR&&@On)i%/rFzeC)mHZl1S=?dhd-PNw֪33#n 4\冏jY{Z еYRO`Pjy@Êe_E5pT%ʅ8|3Ќr@(}d@KB!A}%̌.mX6I檠w b+t!0)}< $xQgr#ԥX"ip{j>PQAe2; _ 8Wu LjG"V@ x1]M-p!~Q\`ՊWT3 5"`#(@{\ (~;GTDLA z12+IQe΄ۓ( [&E j y[G 0Osb}\r' ҽ%5U@r@۽@Q]"ӰƖ!r%k Fxm3Z)-5Hc6[]tj F s#!2UIS" ^o MD)70_[ #(82X&,, ǩWPfqerW퀊eEy.4LʳM[BN -FOV6-GLGڞ~xZWB9FT۩ s#HaWtm:/pxdCvmc;Ae m 9P'|\DQ\ߚCPdjˍ/Ԉ#)  |skayܬ9˒% ""CS>+J&j}1i/ #HadNI0Ms߀Pl' Z^Nm%E L%xC_Q#NzwoV_!rf(ꂻK/[ `>bvm'h @u7p<_cc- 3rqt<  vGh;6`?5~7+k٠FZRZpmj7i8oPhS\@|m(F "r|5˹ Ӏ_>ͺ~_>y;rۆXR̃/}iQ/nÌrAf\Q % ֈEI^ޭ"?۠}V(>YRM&t(h2w1̓y8jKb/h@ >̷l`fɢ,@_ukE7@oJ,3@F an6B 0`!_E.GC(HCAԶ\Lx.z_kqA!r#KAA8~P7d1ld1ۧ$ނ-}Ure=IMЦR[Ū_o ⋠؄.l s=6A  K6b9 v5@t~5i&P?Ra띑HQu;rT!-gn=~}@傯7 <wX.#?p̓k@HQz^\t'>p)j*2}68Rf{ 7TsJX}(3|஢? E6}$^IQG0SVdbV Zbw?@3}0;̸hCl < xӶ>` [s6t2>Vk 1-~?x Ph)BJmo_B|p{P/`V_Fy<8˕ zPDm=Bl/- ȴB&Sp~3|]<{ZZQu_>`t%6[5h- wToD v~#`*ؕEw"򁂒Ws,h.8ކf32>0#C/6NLr/r(q LCů@E ]ʢrW.?Ӎ/~шr:SV%/Z!ZE".56ԺAdzm|ĢfP׈Ҡm}TYh y yQ_>a:`.x`^G/*Zݵ)SZq2ESz[.<\J) 'A6)lm#;Yi7Aŗs{M))צ}v T;/ 3'} {{@6pȷ2TQ.VQ )?ΗXs_>@+܌Ҡm|6G[.\@{{Y>`vS$~zxEyrA9@i3غ>\.Y女 X6@~#E;nV}^xxl4>R_\#LB5a_H0BLWrXz\0G!C|"S "\13b˳R ,"dSC7}5`uc?4P<{F𵿿*Y9_ΰ|@BJm0mV%L_ydыrHhI0j@=O]p֐@[̅ѰWorNl+G(zBFx 󸧰.PElqw\XMg\+SҌw/^yʅL2ZL!> F>P.> 4:@aBdvߌlS!ldpq~)\Dž Z0f%kEBڡu&y)bqV/`n!YmMPk1E)0)L[pA Udjcڿ ~Eߗr`dk%4D}݇W,n_z_>=dKV/q:|C}Rjo.S LݲB#&t {g5.0ޝzm?PίSjxR@+@+O \"S%PJmka*y+Z! BI- 7((l*å0=c> ؃ :fZp5 (d6ˈGZl^u@-4a߷GJU <9i1,+h o*E[KV,^#Eq4xW\)uN'4GX9e#r!ДCQb}E SD#kQ87pzSf ` -U*'3| ,6$_޲$ זx$.EF}kA b)l3h1_>@3(H4+ڴOMVc.78C=;RZse@{uH1ea,(Y輰Wd:(֞Mv()vpT@r~O@hT0_>0/` teŹ0d=?t=`eȴ\}>X 5Pgk 䎷:^b]-Po S2Q,V:k `kՙRj[3й,@#pUEՋFp{жV)pT>V!f 0/8FC*irn>Nm/SUd]A#uW_>P#Дf\S1+f^鼢yEs}݉8*{'`:})`TiA mw#8@0NaLrZ/j@!.Nv#1zIlCho a?m4L]O3ETy?G(O:\!wwX{0K]Pp @sp<[Hj 'r9/ 4b!"R|PGiE(afp,n4I2WsDP[s9LӀ_/텰 qŃ:#.%ҼIeS󁊷|(' `:mR12UI׌rXo MD)70_=-" #(82X&,, ǩWPfqerW퀊eEy.4LʳM ^3WAq@hq4/PŒ/J^(Ljj;5;``n`cDB)M6Ÿ5Ԝkq *S7v@wb(qe>."LᨋBoM!{(2F jyBg>9ʵ0L?=a/AG#luz_ZҢ<nÌrAf\Q 0`/P\*.H~ Ǹ})j[8ZPA덐w P4CAtM1C8jKb/h@ >̷l`fɢ,@_ukE7@oJ,3@F an6B 0`!_[슱og e#u"_3E  -] + 'h4O-~.$"Hm:\W9+cHQ /qX5k-!U|啀 dηg׆ҋԅ%v1?;l}vp4(RP3S@6EGޑ ll?fZ_>pr_׻)N].:G?}Xg@|s,>p xO?`<<+ 0 ,J|Wz@Bh6NNQ|"g.ep@kqK= zqtqTѦ >`8 p~L!LL>p T L$~k *8CwF>)F8RPmq~r.G1^/z74~5g \e }>rrb[)vE?,}0 9w2S:/ߒJ18񂐮_. xw1>ypk+@>i5{n^Z(li,MRÅ3gȻxZ {>C@iѵ&|f_qaz^#PzS,?\~@A۫9ԋ 4VI[] 46fje c}2e`F>!~[6^mkP7rPC.DLvH2bKYTevѮPhF)E+["Qz}VhlGw"x.漯݂C} T϶u >fb{ThlD6>^!OU!O5 *38Lg]|]ˑA!>CT+1F 0/r >Iy@ A['N2(a+_α5"p.VD\%fp8P]0|6l}f} {{@6pȷ2T}%UEK/`.|;|VA=EiٮLAMP+^[_>^a_^c\P-f ~`nA# ?Y 햃<GF郏P(L5r$L\d#BJo3.D3e `oC"Bq.Bl c{+>Lm/n#M-! _.e!FB ĒW\0}!*2:P> 93Ts}g>`S <"SR16?v['bZutG~}=oԊuZCj׈* a'X+G(zBFx 󸧰.PElqw\XMgxh-VN+ꢅ)iEΌr;tk<EB&]/ LSHm1XF>P.> 4:`*6B/`_ߒm q9r, o07븐Dެ`s rVԅ{1Z5<һAtf5Aמ|0hq3S=\BJٵB:h Z^jMܾC+R}]g}j8_X=VnjrALڛ, T=0SGж 0}eY 0Lw'q_g,?VW|~ @EK: 0T$WC(l4.l17\?]{4_>5J cVm % =YM2l|P MqT#Qy W!S_.@w/{#d%@I+Tsj`ԡ|FvE<@!]oh#5py_ܘ~{L5-`hr#94_# Ƙk` |D2(yL6X9lml-HMm/@9c~soP# 8q fxV v$`O6Nr5t+KOhd@#~[nOv.fZ]{H%մ;lb?EW"E*:"ʅ8|3Ќr@(}d@KB!=_>E&\AAl>90O~}/W yq.Vx HZ/[0E[DYx>`Gw0|tn "#_Z7t5/mD P|ˋrYrV+"^y#S[/0.!.^P+Ae ؠ:(i'Tl`/ wVůw'*RPh)(aZ/F8_~Q܏jk# b!7@wP:jY¡-(>j)% Zz^QZ!-XRSU_> 䰎/-^3 {al_>gmjqQާR݁TDRфeu|8 >.LQQ*?GԖ"G < 2+6 o 9Y|FZ*4V=Z`_>0;01h{-J^ Qm&` Vw(AHaWtm:/px$ހ]؎kPBsv/'C@k(qa G]rjG_6G 9R@j@8+0Ys%K AT?DpE}6WMh-VߊG~>3Sx0 r9gx$Ro=x94_+\Nm%E L)A+>0\wWx_.`"g.Ԉ_#fN.}hD_}#Q倊>>0#wHǏ ňrwtۓ)SD?5~7+k`Y0q%)4g mT r][dr5/PZ{/KoԶӀ_>ͺ~_>y;rۆXRB\/}iQJt*[FP:/dQR`/P\*.H~ Ǹ})j[8ZPA덐w P4CAtK(aFX9seKE-L0߲)'޳}}ו-Gn+ /8RD+䇹 IYRGy6ro# FVs/}J-زiW9+cHQ /qX5k-!z3Z&ty%`%uyua]/ B8I.M^DGޑ ll?fZ_> `@0F^7Y8g|@HQn >}|BՍ{₊L G]l|AkK]]*)2U%#qxy)q42& 5\i9~8nYł]#7#1<(ۂ.AG1^/7{o-Ouz@E BBBy >Zb~y| BAi<^{Bl/- ȴB&Sp~;#|^xxl4J}"Sp2 ׄ}!R,+>݌}{?D9$ >;߆D 1*V#BCL!6ﱽ+>Lm>^ X/ж5@/o[3sn)jfĒJcU3Ԍ5\P) ՚/ȣ<'wLPyxv{iC= ouu EouɊ ;cdr v0+W?\g?pϭ ^o j u>p^P+򈁼;@T1)k W|9r=a CD/}؏e4P<{FR0![_.mRG^M{2@1,zQ Xf\-(R'R^ b.jG |cEZ㚯*P- bn-CU1{!Hxrba`J_._>p]]Pr@\-ze Bj}82/(ε`T<2y\-- iL|#[Ma>6SE {h1@)\+2m|{.$)bq/PGYmMPk1E)0)L[pA UdjV(y{u ePZT:[VǻjzHyrOC*3ut mxӉ\Zop X[:RxjoDEQLt@ BOVg/ \Phqj n]@U <9+֕lM 4<7_a*CmV,^#Eq4VI+T: Г[s `fBfJ/D#r!ДCQbu -[aF֢vz L`aA޺2@d 7x*mYldvoY@kM<տ">#5 1ZF h_.0Kg (NvQߋM}~@!~=oh#5p_ݘ2~{L5-`h#94_# Ƙk` |Dj w@1 ƧkVBYɵ& o)N'12"^T qvz_p%`Y[0X̔t/PZ΍d"Ӏ=*hO8LA4 6N<*ԈP06=wA =,ǻtUyp~){l=h ՊL+"S4`z_.p_y?))/p[`UԂ+:W1__pTDO&t,04 l m6N8(q fE=S276P|{D@`W>#nz_@rGOc83Si5@L%U)yHQ z_",E\u/`4`*tKUjE5P"ʅ8\h@(}d@KB!||D%UH/p,n4I2WsDP[s9LӀ_7BXAGɑPciދE-,<eGw;NpA _"V@ xDG?㔚_@ۈu{8ju{a-GyY[cAI+T] DUN{U`f8V Bu @[s*6D_ʅ;߻|D)$E]D z12+IQe΄ۓ( [&E u up!>j)% Zz^QZ!-XRSU_.rXGGN&/{T\FƖf Bw3xhKP>e! }f"Ӛf{Iyr믋Nmhzs$$n9G*_ ^`¶-V4ai>%k 74\_2C >R݁#Suh²PwE#A7昢UIAN+sy@d:WmevrUhh1z"n\0;01h{k& >>x^ Qm&` VwZ"b^ѵsv\Q㑚xvmc;Ae m 9P'|\DQ\ߚCPdj˽/ Bg>9ʵ0L<Vw~ࢋD3ߟ() d >bz_(*< Fv!,/0 P&2^ Ho(/Q/`:_`"g@Q]ev+G̮-\dm3G/*+XGŒ\ܽo#?67G`Q09nPt"G?5~7+iw#-t)/;7(i"S\@|m(F "r|5 [6} q7@m : X mE+ňrgvobI;>G3t[]ޗp3fV;g{y % 3빽[E OA97p1ExKQ|G *h;X\TD&t(h2wi1:fHGmcIA/3|f,z"]WXPۿ"`y ]!?-PH2q,kh0FG3Pr2G]DLQkC䴷GHKsxq n}cD cEOI[6 0`Q{"(XH6@b9bx ̷VEPlBW69ߞ]~J/ZXGPlň0aqh.jLh=~"vwP#`I2~KjrF(^ @>Vܷ@n ƷFn0+4b9ƇF>xgl_xBW )At@E{.et>*~6Ni(V+ 6*URdhqKu7SGm(|B kLxZT L$cM8(bQG{ C-h2d>4ƋE nrs:}@EBBBy >Ǯ8x |$XkW2S:/ߒJ18񂐮|{P/ w1^yp;r2h_sQ[bj *$]o`jE*dao0痳ELat~Ԋ] ⵢ/]XJl±Z۠{"x j( `WAßWG J^ͱ^lJ@ѥ46>`V1S+S@)31:rh5VPVPo&f2@1^n|0PkE_Pe>.eQګw~f{R9_>E6@QlcuZ!*Zivt'haj)0{>öl[Oy,G-LZ_>o y"\m<J[r/̹şo9bIŊL1G1/9"S 5;^GyOm|8uٞP::cU_e{:dEy1bi290+W?=]gsk𵚪u>hB__[:*ZG ff@rL\r@|v!0L.HM i(9~T1hvUyk `Cė3/߶VH #5}z`&l=_tG(׫.s`kH\{ZCj׌r@[̅72>9Vt 6E9\ҙ\17T7*rU8Rxv?|bZQl/<Zw}S@/ ơ_ \-e Bj}82/(εp3L5_ 8FVX&>@|K)|}68{BB-fzm[BH;.$V#E9n_ת ӵ7$0w j-("2)u.H1M@5P+ʺth2S(juv} \^ioAS@Lڛ, T=0SGж 0}eY` X[:])LHTկ{I#RrJsPE`# z☛.Dמ.`s-<0(9u`,6iEФsГ.3˖35_ j =o]9@U <9{7=py`C @"J)@8k40ӊ6m6@(U2`h D )Ĩ\b f #y r)Hl0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0E=3soP3y/) [X &Av`kyC^rz5֊=;RZse@{) `Z! D"L>{^xKq:i#~E >W6> j ATn\wAdJybm-@Ֆg"`AXЦiPXB`~AѰϡ5piq>Ixm4jERl /%7ȷ8^/|D!r锶-x PS6@}̡u'"쉞MX)QaKhSWǍpc7a:XCTzc td';!P:ؕĈ'A4rVm#짱 v)k vȒ@2C@EL}>l>*$fOBC}`$9" ė㶏P8>È "W ]{r#ԥX"ip{jx Cw(' ݡ] "s̢{ RhE Gxe! }f"SX[jǑl ;@L1>GBy#|d.Xo MD)70_[ #(OEd*.MXXV7ʷS倯BqDm(|D@ "ӹl,;րgBxmE v|lGp^U N/x%`/cD_0070[1 "b^ѵsv\Q㑚xvmc;Ae 'ʎvWLᨋB]Րto@/7@/8RȑR|>X ǾJ1Ďd DpEOn 2j}1i/Lf Ȯ {0240 P'/'ky9)0 eif`:f /(ꂻK/[ `>bvm'h @u7p<՟_T1W6c@xD1rݠ(lE~jxn)8W֌FZR_>7(i"S\@|m(F "r|5P*l6urC3۬W 932Ώ/ ':B\/`+_0B/2׌r߂=q3HZQR`/(Jjnq$`?cܾ-Ey-F `q;REy(СKg!%ff 0w03d{Ţ %U"]!?-PHT&΂@|mD+ƾy6=K%<fѥu"_3E 2bFT*RPݓ ^}r FVs/}+߂-}Ur8vT)d/#Vg|KތA ]^ @|{vt )haE Pl4_optEwQ].E)(px:L9K _.kn9=fG).3@O~X^7r+)BJr_:|{P/`V_Fyܻ<8˕ zPzDm=[ewdZ! {)8sLate>r/ZZQu_.0؄wv@k1m^#PzS,?HAA?\PPj%b鮒8T{d"| Bmx׊ʡo/_.un"M3A`wx_. 3'lw=G Lk8R[T* u%n*AIU~KX9ߎ/ 7PZ-Ea~;"յ_y>ֿLs B` +_{>pLm>^ L!az `5\0m/̹f Қ_Kz/V|25<0}/Tduvur}#AQs;f 6Gu+_{z]`S <"SR1Ī/}C{>YD9~gBK XY=(k?sk𵚪u>hB__[j ?"y|b92Ep/ķmS_:a@V|+i3&f9xK|9Q3·RjH= X3 <[zϗ 2_(E/v#i3h1W }*㵆Ԯ* a*X%VP(\17! 䪘=I{3%xrba`J_._>p]]Pr\zn(SR#it~AqUȽhw8FVL|#[Ma>6So}h1@ԛlVߢ# }]^X0Xz7N>"okZ)mHLafJݲ R"PB{KH/3Xg``q=HAYܾm|`{[@z_.P_ڛ, T=0SG*Z[G(0[xô,L׹_g,?j#E 7`cDJ$xRJ7e9R(ƊO"aޠ8KѵKc}_4(9u`,6iEФsГ./K/Zl\ZhB[W.PU3,Gq g/t@^!FYRu;ڐMye!+»+.E W(踭BU-b-U[E5P"ʅ8\h@(}d@KB!||d/HH/pp\Hlؒbkam_.vKulb biދEbh^F L\2R/bs:@ _"V@ x1]M-p/mD P|KQ=QՊWT#T&Z/f J֋)W1GP\Xaf2)RD?UTet<- QPn=`wW,[ҡ'T #@򁢥{@ 7`a/-/!+G[Z`)ϝ#603xR=$R݁TDRфeu|8 >.LQQMYDQ[6 Q4Bt</5`/di ^[bDhe`zw`>b6#8/*M||1?v~luLjN4ЊFyEצBq GϚGjN ص)~"S ݡ (Umj9ꢐ[pu7F^ H!G H3`Z&`57}β$`I|7.H40T ZG~Z/Sg;6`84߷JB V|-/'"<|G<g mW5_Q[#^ih9}f>RcE(-P¦NVB~cuQ q1\yۆXRB\=e\Xʔ-s BX\TD&t(h2wi%̋2+g,z 4 }&o̔EYn#7TYF)Lm @LAe,Xn `>omBr.z_kqA!r\Zl(܃ >RE j{2ky_.'-g/"܋ y" E')dVj [Bl؄.l suSz: d.F B8ϯ6'RPj;L{3)**d_kv].|#W,3^ _`Vru'0yk\Bz | >\=H!4P/S`?K1܀?Pڧ\R)b`Ϩ򁻊*Wǽ  G;p3|X}=s*;(}A`Ϩ=tgC-hd.pdEg [s6U.P`j!]!]!ۼoW!\GB]4y!˷R/?͂yAHp{P/`V_Fy<8DT}կ9|Aٓ?pur{W0{)8-f /ZQ{ZZQu_>`tc-( mV{"j( `WAϟHAA?|K -.awYGL}O, DoˡXX]xQr(}݅)"PkE?P/_:c"nu'^EF a4.@]4nùb"Qz}VhlGw"^Q}K>y7"f;ٶ.` @l Mjq=zWt>^!OU!O5 *38Lg]|]ˑA!>.5p6} T+F 0/r 뤐R Ha3fe#{QHkx@0Õ/Xh8SSn]"M3AhŘ <2}|6lL`#&9aZ"ߢø J󪸀В R,+>ی{?D/ F 6$)T z_-2@~WZ@-,^;3hۚ_;RrR/ ݲ#Msi!bIŊT! _>PȮn0Ts"۳Zg[` KPlOyZg"3FL1M&`9reuwnVSǖM(K6p~V7e rL\CaJ\rHM QQ/U !$k `Cė۳'TPARGj~E?cի| "bY\J<7 0"{r-x!k@[̅ѰWorNl+G(μPl䊹Q 0b³׸;1E(Gq6_>EXwwfP/CW(~PT.dr )b ]h4:8xdhqZ b#/FPZ/Dmhdw7u\H QoVRQOm)bqV/`nn|DջS_~ISq P̔ePEj@Ym_f Emή{g)8V q33Q0Rjo.S Lݲ| ձut"Y 0L{q:j3+55b/xRJ7sPE`Aq D.} l8\v`ؠcC> BOVg/x@5_BzܺU%0r}pBmy@#t~7BVBe9H^#Eq4xW\)uN'4+̔_.FzeC)mHŪ]nahd-PNy_nzm=YUw)'`,6sk+xx va!7!E]|D؎r@(} DG]Ѧ~PHmeb`J} 꿟Wk0Z Gsi0F ,1,*2 b9nOy?aSl=Yp<~(Gh^J rǹ)j7_>0?\ì~MyNj`6! [{bc׫?V4ّEך+ c=y=r !6LqEsړܡi;\4c703ŮWJ_. 7 8q fE=S2䷦Cx'P:ؕĈ?ݶho a?m4L]O3ET*!E]Ď6d@jy@Ê<,=Dn<5Pz>R踪Yltf jp * pϊng*}d@KB!||d/HH\4 ru*T#h#mp|aD0m/+t܀#'y/˸oeP&N.8uR-@uR{f=<)"ro#еjl _.@ۈu{8ju{a-g yrY}/L2zalP7Q թO$@mͩ# _.0+_NU2z1SP´^LqrQ܏jnaˤHTaP[A!OTB- @m@۞OA^Q+B:oi~'倢{@ 7`a/4l/A߳CWd (S;#Gm`fZ+25f{Iyr믋Nmhzs$$*ނg#K PZфצ -T@rUtZǧ"2X&,, ǩWPfqerh'ڲQ<Ds&Xv~a{!'H _ڊ'B+얂 =΋JuQQŒ/J^(Ljj;5;/` Vw(AHaWtm:/px$ހ]؎kPBsvr_J*6ⵎru7fF.#)  |skayܬo`%`IbGM""CS>+J&j}1i/ #\_>)=`e_0 P'/'ky9)0 e9G/`:F X}ș_> .5f} ňrwty8W\Y#}7"@҈rFAM kC1:Nӧl#9H/r@m : X ۬WM$B/TBr`Om؋%5xш1F#h n_>@0\:*M#_>()_.?۠}V(>nj3E;X\TD&t(h2h1?,؋+y@@`}g L9YE Ob}Pۿ*ˌ#E4ѻB~[ )L *`W}l{Jyږ#u"_3E  -] OTLZ|G@@Lhq;(=@`QeG{l5cx!P]>xѧm=` [s6~N(Sw@uWuW6oħt)_..Њ|~w2S J1 t.{P/`V_Fy|w1Nypk+@>iu=~n^Z(li,MRׅw3_ wǻs>C@yZPb~fbjEyULPCnLpE 偂Ws,讒8T{d"| Bmx݅׊ʡo/_.73  P`\;t7N^)/: hPbuZ!*3PcS߆DAgۺ+n)0{>mk}TY)h y yQm^ aV+Vw-G ~t)S8/n2+*ꃜG Ha36T|9jDұZCD18mp܆͙דz;b|ޞ# )-zOT\x%,Ŝo> &kkQZk,SP<~{Ԋo^wD/Wȃ3FP-f PGGX6@~X75h` O)P(L5r$L\d#BJff](X, Z|`v 2GI_{L<ĕ֑LX0E9/m/Ԉ5<0_F 4ͥ5 XqԈ25|lф2dS~Z^33srwCaJ\##c"jy~T/.VӾg4_M rrFo[+>glxz/AdG(ڍ͠\-(R'Rnb.Bf֪cEvb[QW F>P|]< FVeL|/[Ma>6SE ph1@ԛlVi6=P+F6csV/`nn|DջS_~ISq PT~PEj@Ym_f Emή{uz^}]g}8XMV/qz8  B?U-[::@bY0L{:Rx/l]n#Rڽ %WC(lt/& c4?]ۋ]yQ &9l1(3U381~Nz?97{|]P M{J`(+*y߽݃#@#%PY=ƪHQ _U  ib֜Pr7Ȣ\l#4P)XB-ݷ!["YV6pz/Zi,l5|Lrv{@On"`# <G -7HTqva!7!w&p,__̒:>#{oyfKPc3C(݂4/>/Xn0Z eGsi0F ,1,*2 b9nOy?Zbj}u)G% {)E0fS|6`F<0 ì~M٠j`6! pa1zɱՀ[+hHo#R踪YL*tcݛ @NP`DBsÈ _̥:?pz4E"xb4t/# &.EOpmA"P97B+Rp ^<]&FP6((`ݞ(jE]^+od*vK>A1s5Sjye])q^T@/ VN} hkNEFQ2Y}gP{w"֋bdGVLOU y[G 0[8t%ŧ+=k鉢{E:jto`I?iy΋rA۽ 0Ӱ@.=D4mjqQާb-*e3EͱGzpZmaS+W!?t<ͺ~x_<\=a/AG/ {yT<e4=<@ :*M/EI3E_>۠}V(>@Mƙ,.zG"EnY8g|@HQn >}|BՍ{₊L G]l|AkK]]*ohS:G/(>0SVbuM&|Zb$-bdvqW1Mwʹxն.0{Wӭ9_y_N(SovAuWuW6oħt)_->[ 0 9{2S:/ߒJ1Xx_s=^0n/`#<]DJAOZ~=מ|-KKł;2_`0:2O\PPu_.0|+ ~f_waQt]j( `WAןW_.((y{5ǒz*xKm)o?e c}2e`F>!~[6^mkP7rPC.DLvHbKYTevNZh9z_@sJ{u u.buZ!*3Pc M;D{\.Gk|Num[`c GƦ }ݔr\ +*^Jrs9 {[\HϠ}8>~RwF0/r 뤐R ~kf @2'`yQHy_ JJ/X~#-g ~b5@f1F6l}f} {{@6pȷ2TJ>U"Sq%Xs h۶H֢lXny&- G/߽,a_ȃ1{Y(3m  xk!䇵89a]r|q+,{]r_(?^ &tXum`9\)ff]#agfoHrmHGz_>:nZd ZG_wp] X/ж5@/o[3sn)jfĒދL1G/ A_3b]`\EyԜ䎙{QJ޳^X.9` ď3 G /R:?`V \g?pϭ jZ;z}^ {RϧmV%LoydыrHh `Ղi"{r x!-h+dfj 9Vt h'p#Je!b#W }y*f>D)<;Sc`6_."evoP/dQ8ݞ[}׋(SR#it~AqUȽhw8FVL|#[Ma>6S` Aa J 6׊L+C 7ɫHc׵wt[#¬~S_~ISq P̔ePEJe]B:}):x5q=HaLuLgA -U!F OG`2<`9\!:eGMD+-vje#Ssi si~}k `#1NU38hS&wy_b㚯QI3,Gq g/t@^!P@?{}h*˹GX5b)/J]9MLܚS3J0Sy Y} y"@wQ2OF֢PF33 m{)'[|]f_X[y#߱-K`vprb [r-F#4c/%u(} DG]Ѧ?Vcķ"SZGmFcbThC3Gy r)Hl0\`P#TSwhSq`|<by@|6k ԶRC`1q`{ _ ߠ_y/Qj`6! [{bc׫?L7B؃y`ObsOA0D4r-F "l@ǜ7wh/D94 LՀr1Si 0l : ؕk B¼/ <[^"B:;p/N$@:;X\l hԋ+ }tL>֪33 nsNC iqz4[P9UEi\ LrA/@S_>Q_Y6Ng87`s}݉8*{'`:})`TiA m{#p؍`ZQ9]3%PH~álŇxj@`W>#nz_@3a?m Xj'ؙ"KR.+<Ջ2y`@ T-m2@Am:jqX&5PTXQ9E7 4| >2C@EL}>l>Mx$$̈rͱ&\Hl*rQ ghsE0ɭ٦-AV߀S[DYx>0unuR-@uR{f )"ro#еjlkyo#J[ਭVE셽Fblb|kԌrE˺*Spv L^Tgc%P@4֜<r!*$QE *3%L+ۏ#Q 0xzDZLaPu uCW[Q|Za" 9Eu\A/SU_.rXGG-^3 {alh }^9ڒ^5;}sg LkEl# #@nu1ө7-vbZ}0-#d1UI׈Xo MD)70_[ #(OEd: Cq?|\v8lA>h υ\y _}k^3WAr8|lGp^U N/x%`/cD%cp\ ̣fY,)QEfP T>b-*< Fv!,/0 P'/'k Ho(/Q/`:_`"g@Q]ev+G̮-\dm3G[cA>>0#wHǏ ňrwtۓ)SD?5~7+i,z_>g mT r}5<ӧl#9H/_g Ρ: X mE+ňrgvobI; qWt)Т|T<e4=\@0<:*WԂGEI3E_hwAmP> \LQ+Rg&Lx(-e.Td%/JeV\YhhL0߲)'޳}}ו-Gn+ J)#E4|!Cm 3EHAe,Xt)ڀ<79@mʄ_ u"_k׆iof*lK)ucO&x- ># FVs/}J-زiW9+cHQ /ĸU5[-bSz: d.F B8ϯ6'RPj;L{3)**d_k:w 2ũ_yo<wX.#?p̓k@HQz^\t'>p)w>u)=*^ ]9]PWU>pW@D[/$n=G)qwg2@z&\-U1;q;\P,3< >hCl < xc s]+֜M/e4,X} ++xS?xCGB]4y!}9ćR/ k=F 0n/`#<]DJAOZ~ QgO-KKł;2_j>`0:yO|@ku=@+^+N3/Jl·ZkZ @|=ToD v~#`*ؕEw+RP/((y"`UGr=Rd"| Bmx;3E=8:D9(ˡu"pLCo;Tx:t6 E2;݈N^)/h8]hPzbbuZ!* @mEo(zE]bo u/ ٶ.` @l MX)1xNiV_a[KHT@E#?B|]jlVtK-ލ\`_.p%@I!ץ׆@ dN(aZMPy5"pt7<64pa'm؜)H0mHoQe7(qĞVQ )?ΗXs_>@+܌Ҡ֢lXny&- G/{Y>`vzW]/WZȃ1{Y.({.V 6*  #fwPX `>Bʏ\d#BJo3.V,m-0#}&P>C{<<ĕV]B]@ڶf _>0m!P) _4\ ]xAe? _.b]`\EyԜ䎙{s}g>0m(}g-)b-@'+6SL,sο\Yp=[{T%Gzr/`/lVy=sAT1) _>+u xnX& _.:a(׍B@ JK,o/g? _> |Z!6~6gWD/Psa423V+ۊr ޲@+><) oyWʆbpmGR aݷ2}03h1_>@3(H4+ e2 0 mJ} a3Oy`X3<`|X$6cY0(hUd;4Zs63lnlP+RX9lml-HMm/@9c,XGyA/80_f-xS6(42Mn4`/6bc׫?V4ّEך+ ڣ(G) 7{Z !ACl<"l@ǜ7wh/D94 LՀR3\ASi hy3 "BL!X&_>0]4/` k@+R`n}> 8ԈrGq !n;RNxumVa v_.p%`L>֪33 8q fE=S2䷦CxdJv#1zI@#~[nil)k vȒ@< nF<ڣO#P4 V*߀X ݲ/|DPU8AuE Qm/g P 3B8H_@ 3|ied $s6H|9n{as /\u)9V׸oeP&N.8uڀs _ bx/u^ a<-V@ x1]M-p!~QRnOGm.b/72rA1s_.0bk,(ivPګp'Tl`/ wVůw'*RPh)(aZ/F{% #Q 0ԭ03l)* ֋Bp1W]m DiE vԻ +XKO+ Q+KXRSU_> 䰎/-^3 {al_>1+G[Z`) Yx_603xR=$R݁#ЀMXXV7ʷSДnT-E(sy@d:WmevrUhh1z"n)Kx *@X4Q^#J^(Ljj;5;h-bDӝV0Z+6xΎk8 tcp\ ̣fY,)QEfP ZG~Z#Kˆ@f} ňK V视^se/7 \LQ+R@cƙ,.dQZ ] K:ŦHmp6_6%",X_`e3SNg#EӫXts$2# FVs/}J-زil ڀ1R GĸU5[*MJ2۳kCOE Ò `_>B8Χ@Ѧ{D JmiwF"E#XRL0i˙_._>pd_w 2ũ_yV({|[Y|N>\x5yW>`>r̓)YX/`#׋+.Dr"@NQ|"g.ep@kqK= =*whwK9u)qwg2@z&\-U1;q;\P,3< >h=HAʹxc +֜M/7`0:yO|zw|Њ׊ӌkk9]Y|~k1mDp̓#PzS,?\~@A۫9ԋ 4VI[]Jo?ZXLYA֡C@ZC9 P 8SDp~"X].gN^)/h8]hPzbbuZ!* @M+4;D{QRK,9F@њaS=,XQBk7%a)TT#ۂ8L[]|]ˑA!>.5p6} T+F 0/r >Iya36D 3\rռ(3?c5Af1 ~|oE} {{@6pȷ2T}%UEK/`.|;|VA=EiٮLAMP+^[_> /|ֻ_^c\P-f n d Bkqp yj}ゔP(ycY*BJo3.V,GƋI@~7>Jի:E wlqGs@4c>|^/߶sn(}/hK _.K.V2/ A_Lήn0Ts"۳ ` ďݖ O^L1M&`9reuwnVS`jݑ__YtԊ`uc?4P<{FR0![y`*(٠VH #5|z?M{a 2}_(E/v#,.^E >uZCj׈* a;pX%VP(\17qOa]x)ޱ 0/"Zܻ;LI3(rfޡ\{(*2[h1.4pd_P@U<@4иhBFVL|3[M5|}68 ph1@ԛlVi6^Vԅ{1 腿vtf5A׶_RTpT03n)T/<Je]B:}):>>"gq"q1nz^p)<1<`9\!:eGMD+-iY;nb_v~PÓ`g ?$*3*2^vo(G-J$+mG:%ٲ)cn4 pi}k `#1NU38hS&w_6B BzܺU%0r}pBmy@#t~7BVBe9H^#Eq4xW\)uN'4+̔_.FzeC^Q9Xu-LE Ni,l5[WL9/B2<<+*8;րS؂[ -MX{9 >#ȮhS(v|^&vAfJk1Wk0Z Gsi0F ,1,*2 b9n0G;l 1r[ DR`}Z ~soP# 4<!Ӏ,/.BL|`Z/ԈrV|<2-W0E{q"@&/8?"^T qv_.p%`ֹ)Zuf{)60'~Y^:LP@\m=yUH/3P06=wA =,Ǹ8V$p6yrLӀ=8ӯ<|?F )/-blГyE>PpT {kaTiA mw#8@0NaLr0gJ桐Cx'P:ؕĈ'A4 aT-7|4N{Z е;SdIU bR~jxT#BV䁅wW<5OӮ(i{8`U¹ 8Y^,لj 'r9#ij9@i[XN #}%̌.cۧM*P/ bKGam~_>0tj=9Rr,7`9bqO*"!L\&pt;\)ic#B+Rp ^<]&9֦.̈́o) X' ZQz/`_.(aη3f]B\ 2W8n 腱AXDI+T> 5"`#(@{\ (~;GTDLA z12 bDq?f-"Eӽ~#n)BQ¡+/, zc-=Qt(XXG[/`IMUa-rXG@]\v{4셱e#@r%k Fx)>2m3Z)-5Hc6[]tj F s#!gYPDC]$y@>+J&j}1i/ #HadNI02`N} ԛ)BO.^Nm%ro+)R`*(ʈr"_.tһ+x </ 3|@Qxwލ/][8ɢ=f}݋D{𑨾|2ƌ\ܽo#?67G#rl{LFFdjE~jxn)8WֈAߍХ4\8oPhGE­PxE)H-j= s%!q`S+W!?4|cuQ qчjGz?)<ۆXRB\/}iQ/nÌrAf\Q _ ֈEI.H~ ǼV(>nj3E;X\ɢPAtM3E# FVs/}J-زiW9+cHQ /qX5k-!U|69z C.gCE0]@]Ò `8  H߸}~P?Ra띑HQmtT!;L`rf (~oqcL; @o rkfge1@Oq>[F̓,0iB: u Bi-h @Bh:_8(`pԥ܀x?&w6A^QcTW>Ѧ Ľs( `ǭ΁dbuL&3*iOhq~_&(Lf^-C1<(`r.G1^/:7\tk&242 1-.k !c>MN 3EH-˞"t}ne퇰Dy"br%Ƞ'-T> Ǟ<-KKł;2_s0S#ڻc/C+^+N7F>r.h- 힃 ]J"; 0ʢ; 7%Oԋ &8Άf2>0#C/6NLr/7x9BiETxbKYTev6{R9L)mԥ7dLEsih ƶ"CзfDI.Gk|Nul[`c GƦ }ݔr+*䩾/J2:M |$ Z w @OjE|5&eWTN!?9 "ɆypFv 4>D o/Xh8SS~.Vצ }v E L0mHoQe#^bOvKX9ߞ ZrA Z-E/_2JTG{k^ce Z̴l E\&"#,X ?V v6|>h(2y2um`9\)ff](X, Z!aoC"B2&}Nćr;R+>L@2m[7Kz_߶^P/SՋ򀦹^ Ē'L1G/ A_/b]`\EyԜ䎙{pQJמ^LJYx EpC0Xo(z['<\G"&SԊrge/iE]`w8fE΍v[(~PT.dr}nh1.4pd_P@U/wЄn]@U <9+֕lM%݃Pv/ފ_Be9 X5b)_hwR41zrkNLC(L/Ȣ\l#4P)Xuz~n%} Z]ӫ;Ui,l5,? 2| ,6i>bpmG^2W{%L#{:LWb:{?1KP@D#M])Teb`h _S^?n0Z eGsi0F ,gÂAA;"SMݡ(yLiؠV(r%`Fo@m{)E0fS|6`F` _23ev܂7eB#s لFv`SWpY)a2+ ` V)^8D=b{PU4P tMӠ2 )uLy1 .Ӏ :sF#o[TNU)vy}_p_?/@S_p[LŨ kt^}݉8*{'`:})`TiA m*JDL~8u3Պ좞)Be(>6Ng%JQ$F! o a?m0<3ŞVt>YRu;ڐMy/ y`@ Ӵ+JXpn~b}'t˾)B TAT.4e@7(*-g paJie/ ėƾF.v̥PɑPciku} PxCAe2; _ 8Wu Di=`~ [9֦.`N(BE`/#X7@/72eg0[8e.!.ƂVNnh i* *?AN} hkNEFL/fBU@I>T&Z/f J֋^IĈ~T uLHTaP[A!Ocfu ";E݅r' r,*VD9}dEKo:nL^[6z_A-YC-n0 v ,<Ưm֊La 94m hu17So`pSIV Gj;P7pd: Cq?|\vUp;bDm(|D@ "ӹl,;րgBxmE v/ӻyVi.8GPvjv~luLj;aHaWtm[/6?k:97`6To 9P'|\DQ\ߚCPdj}_>P_G 9R@j@8+0Ys%K AT?DpEﳹlBVГ~_Z6`8=JB V|-/'"<~_&tһ+x <L+D΍2./ _#fN.}hD_}#Q}/s3RH-v\2 8UoL ňK yy8W\Y_H]J_ yڴQ)pk 6s^ih9}f>Rg/KC .'NVB~2632;ۆXRB\LVWEy*c_(n 2SGZl~_Pt] +W nr1n_ob T7<b3`q'RVHo@M^.6-F2mm,oٿ`_ [603d{Ţ %UX)p25zWs˷61L *`W}lxP?s-W( ਋Z)jP|miioPP7_ԍ=ർ/x(Y!r̽)`˦Dp_!G"(XH -Dm"[*MJ2۳kCO%t?ua]%z3>B8IO3M^DGޑ aӖsL@I do t2WsA'o{1_;܀?`1Vir+/0|3d#<!E 5;)W(R T#Kq L G]l|@k~6^F*hqK`: P|d: _`ǭƁEB{h㑧|@@M @؍<0D{ #s92m` [s6>NP`j퀐뮐mOR6:\| |$E"yPe/tM7؃jmlǸȃX\2Iկ9' t@`L+dao0痚.)Ώ/qϻ/C+^+Nrѵ& ZoE  ve4pE z9K[]jHaV1S+S@)31:rh5VPVP|(x9Bi{`m8^ZRc"n99 +@0Ni@]B(i}IEәoC" MkضxE]by7"f;jض>*vSb61V_J/a/ c\p?PHϠ}8>~RcB~rDa3fA> XT%t%nP^-g ~buAf1f8y~ӓz;b|ޞ# )-s(qT JL?_b]__6q[xm-Jve ooZڢpr{Y0)\ k83sUh1fmr<2].p<‚Z=n9c}~>hyAJ_>@1F R,+>،Y+ 6sHxcr*GIۡ]@+>L@;@X/o[r_G^j_>Pbb A_r@EXgW7*9xD5>cf:<`nsT|8uO)>`NI  Ed:dEy1b -%`sA]{6.k5U->|lф2~xEP̥ 8yC ](_o=/> tQr'dqh + nHr%a(9@-c*|E ~6gWD#@|K)|}68{nw24Vv˛@Q+F6cspE!YmMPk1E)0)LpA Udjfص̢ۖ[Q[^0D}݇W,n_z_>`{[.@׸( )7XzH`n72U:Pa8 ޳0kqb_v~P5X6e97sP dlPLQsӥӥc}_4(9u`,6iEФs_okGǝ_Z*ЄfY✽^?8B!B ݋>4Y P #`{1Z%=P9MLܚS3J0Sz@4((Mi;E .Vo%} Z]?~9ՊL`aAeܺrAd eD=2<\+y*.8nq‪ /b/Ќ/%u(} DG]Ѧ(U2`~?8 09Wը\b f #y r)Hl0\`P#TSwh0)m0>fSahZbj}u)G% {)E0fS|6`F?0?|Y2;nAlB4`/6bc׫?V4ّEך+ c=y=r !6LqEsҒc_;()vpT@yȴ 4\1*L'1ES1Ź0d=?t=`eH\C\ Y'd [I[p/.E@7`,V:1X̔t/PZ΍d"Ӏ=*F4mk`@rAecR _>_8FC5pmWLSUd]A3+#S? Ni24p[LŨ kkh/P`s}݉8*{'`:})`TiA mq#p؍`ZQ9]3%PH~álŇxj@`W>#6fm#짱 v)k vȒ@< S/yX \wQ;@IÁ&g1U薪-uov`DBsD8!KP 3B8^6ᑐ0rͱ˦]ąGP} }ԇF.44Tg.Vx HZ/Vebĥi.#5uҹ-HX)(XKO+ Q+{c=Kj r@4:/g{@ 7`a/-1!{vі7;}sg LkEl# #@nu1ө7-vbZ}0-#d!`G0oN0Q}J n*i |*H-vJSNl²P}zEEo](,l"-E(sy@d:WmevrUhh1z"n90;01h{k& >>x^ Q;``n`cD 'hE żk{zYHIנ2P6D@whCC'yDZ(r ._nE_.p#}r- 0>gYPDC]$y@>+J&j}1i/Wh–;6`8eiv>B7SЌr^ Ho(3KE0|I-0|!V3R3|V|][8ɢ=f} Dg}}#@aF.޷bD: &G{xZ&SxE Ε5@ߍХ4|A3K8oPhGE­PLCS6G>#~Q- zq ԶӀ_f]TB\ v~i=a/AG3>j-[f(rE-_k9@QRs=׆"W nr1n_obZ<41^HAh-wi%̌r+g,~xWo%oٿf,z"]WXPۿ* \H djo($mb *gB v\lxP?s-W(_pET@|-5(6DN{{4w7(ǯb}cD cEOI[6 Am^Q{"(XH<7E Gm5w&a dη]~- K6_ B8I.M^DGޑ ll?!fG).3@O~Xk}@|u~,.#0|g|u-Jw\ H!4P/(.`/pԥxnTX}(5\/6$>p$Q#Qx38nu<|L.(V_drh}3#۳@9Ƌ 2xE?ݚ 2Vk\w\wo@|JUH1ߋ&"yP2NjҠABۧJPRUd*_bη#/Z-E/~\`vW=/WZ|WA߽,D6[(}!Y<‚Z.n9}>xڸŽ.HB//^ld9j( )> rS̺XQX#@Cxo{Q=_.P%5s >C\i%dz.r,G h__.߶f P3SՌMsi/%+>Pb_f *2:P> 93{sg.6>۳ ` ďݖ O^L1M&`9reu|j\:#r^(OQJBܛ B\3m۹Ô2fGc"j~T/U !$k `Cė35\ |6w0GT!V K2@1,zQ Xf\-(R'R^ b.Bf|cEvb[QWe#Ssi si~}k `#1NU381~Nz?iB Bݺryd9s>o8{{rw $?F݋>4Y P #`{1Z%PyR&&@On)i%W)<,>ʆ<~-Xuz~n%} Z]ӫߝ*00Xko r ^weW< B0[BoCLa _.hf(H4+R*~w6ZGߍ)o_ @_p̏}c50 >L5uC;b[};<pڠV(ro- {)E0fS|g_ ߠ_y߶ M٠j`6! ӐـC^rz5֊=;RZse@{uH1esOA0D4r-F "l@ǜk<4c703TYnC5\ ÐheT0h`: h _.._>E5<54HqxЃ.!.j,܋2x-餭8yX\l hԋ+ }tL>֪33\ (GbDғ m@/~[nilyf=})*P1)"vP@Ê0B TAT.4@#LEL}>l>WPŒ/p> lU+@\Hpmx$}ԇF`^ W<G%k 74\a@|%LB6aaY`(>N"7.ST OeE/Ds&Xv~a{!'H _ڊ'B+/ӻyVi.8G_0070[1 "b^ѵsv\Q㑚xvmc;Ae C %qE)uQu^__.(z3/4eG 9R@j@8+0Ys%K AT?DpEﳹlB֋r@Tex0 ey9gx$Ro=x94_ Ho(/Q/`:_`"g@Qxln7ٵK{,f}݋D{𑨾|;q7m&bD X9/66 S+pSwH^}7"@ҋ^}B?*2n ׆bt+2 -OGjQs^\/ {.: X mE+ňrgv{m^,U!.ă_`+Ң<1z -p/P:/dz@QRs=w0۠}+j)`P݀8ZPA덐w P4agOu%l41R _ brOAVѭ|$o dηgGҋe8,am@.jҽh=~"ô;#0w,B&Oe!^ @>u@(S\u\A({|[Y\JP,P|r\Y+,J|Wz@Bhz_x(>P~Q2cOߥS{EQwtA%O6(>20S\Ag2@z&\-U1;r܎/ 8CwF>1<(**rdEwL[s6ܖ|ī"W|Z@uWuW6oħt)_,x?Ph)BJr._:xAHp{P/`n?%@Y%Ƞm~ Ϟ[V3r{W0{zd /]S8[$>GjEIwXx:/0؄o֠{"aS,?~R (h.8ކf2_ 0#Cos?i"?C=/?PC/}8SDE\-/c-vEj]v `_>p> +@t Pސ1 8[E".!-7`]d֌(WT%ݜ{# R`hMөm}TYh y yQ_>a:`.x`^GPHϠ}8>~Row#g \ P9P$B%dJHbηg#V8]Իe2Y #8x;ԻZ~zxE1rh1fu+}X]E/$GX6@~mXyj}ゔP(ycׄ}!R,Y+ 6sH|v~/3T d>BMWZ}t >wD93hۚ_靑0m!P) _4\ ]xAe? _.b]`\EyԜ䎙{s}g>0m(}g-ζb՗mٞ>YD9~gbL`sfе|\:#?먜S~Z^33{ 您c S| m;pR&\ >RSC)4D|~T!hvUyk `Cė3/mRGj~E?cի| "bY\J<7 0j@=J֐5|-hv.+ۊr 3obnnT 䪘=6p5@LQ+QM7[Z{w])iEΌrv[(~r L2ZL!> F>P 4:@AZld_.7< %js>>Y@ܽ`n _-fzzvheE]I+RĘ8zrEn|DջS_~ISq PT~x&>@5P+ʺth2S(juv} \^ioA -U!f Og `2<`9\!:eGMDe.g{-·x[8L{q:;\!QQ_>PԶ'\md`PE`Aq D.} l8\v`ؠcC> BOVg/x@5_BzܺU%0r}pB MLܚS3J0Sz Y} yxE弢.L"J)-@ Vv `ap{[ޭ+D{ovEF_`mc["^~ <|4c/0KP@D#%1= _>P2 0 m/Sx՗g F5<\cN8 Ɨ;HEb1vQECPL1m)0<|VZf] qA4a/@9c,X+6b _*Z~61)[X &Abc׫?V4ّEך+ ڣ(G) 7{Z !ACl1:/ls1*/րw ʡin`fꩲ4ਤ<\A8ny{ aiӀ#`pt 0#VHqxЃ.!.j,܋2x-餭8yX\l hԈr+ *~(xe\.@dJybm-@Ֆg"`m hS4̃}BJEJ< +Lq{{8 XqmW-*< ؃F8ӯ<|`j#Mi9o1j7yE>PpTDO&t, RҀ%@+ڴ%'j8u3Պ좞)Be(>Իj@`78@)@4ŅxSrGOc83Si5@L%U)yHQ _",}v@IÁ&g>e_p *@3(*-g paJfZǶO,vJyH|9n38y@H}8G@q.\]/*SXDI+T@ 5"`#%x-g1W (~;GTDLA z12#~T u+ [&E j y[G 0O @wVȱ(W,VHKzTfD93EKo:nL^[6B!+G[Z`)ϝ#603xR=$X GVtC\th`۽lBֈҠ`h\tp{䙏PDz62 HsM^g &WrKSA Pć )0 .#(rf(o1 ڭ01prU}GH3SNCw]b^H! zd8RD+䇹 Iʄ+ȣ "בLq6ro\xd4eV\r+y jXX?F'>pEO@Bh_STd:l8Rf{L7*^;pJ@^QaT9ୢx@6$~JܖQ#Q38n5<iL&Jr>J f&Z3YG7#7p 9/Eq@E\Lc1^4n+֜M/9|W1E|Agp\zD9Ƨt)_.CT#!<.!}9_: kT30n/`#<Є<8˕ zP{Bl/- ȴB&Sp~{5qϻwox:=U#%6XmZ @|=ToD v~#T+epE z9K[]Jcf2G`F>!~[6!~({~qt(ˡb/0PkE_Pe>.eQګw~~pJPh:SPJZc_Z!ZE"5.;ې [3G^Q}XtsH٣5>N`c GƦ }ݔr +*jxU4^9_ -r@E#?B|]jlVtK-F`Fr >Iy@ A['`yQH?_α5"pড়.VD\%fp:P}^ź6lLսj#\4"x:]HoQe7^bOvKX9"!5n+EiٮLAMP+^[[a9=[[za->+򰙇9z*@i3غ>]>E/$GX6@~X-y 86M~:/H9B3(?f& ɘGm`9\)f̺XQX#@C`zn|9!2bD9= i۲0m1sn(9`bb%+~2/倊Lήn0Ts"uZCj׌r@[̅ѰWtoX%VP(\17Na}@a⑹V}QMϭ^Zw}SRp|ʒ/_+*2[h1.4pd_P@U<28 h^@AZldE`C ķd|\mg#Mvk QoVRVdZ!xYQno1}^"ȱxDջS_~ISq PT~PEj@Ym_f Emή{5q=HAYܾm5}?ؒ-Z+/ڛ, T=0SGж 0lEx iY8n{@s;NY~I}5XDE_gxRj[XSɓ\baJ{61/1L^6@t0=cEn7 { vw 2q̙zO0x9bA-4+*G8g{ź=p͢ ^Q}Sv/ފ_Be9 X5b) W|Rjo#\44+̔_>,>ʆ)avD ?L6Zݕ ?oLU_Fk04_>cN8 Ɨ;HEb1vQECPL1m)0/ԊSKA8n0]#7&(yLـk{r~U: `mbxS6(42Mn4`/YT^ vώ,\Y4}]4@9RLYjP,  byat:7P1'-9/rhz, 8*g ~O@hT0_NbX&_( ubmk_>)0n>L烵 qQ+d^Hg/ o)N'muĺfAs܀f`X-}UgfJybm-@FgiT T#؃5MӠ2 )ZKOx1 ]}(Ncus@t<8`=4ж%@Tb{Ќr._ 6~@<2diMWTʲWt:t^*~_w"ʞ ؄E@A Up6uEz܈q'>v}CfE=S276P|qO=+P:ؕĈ/M _>冏6qgj'ؙ"KR.bU O5\ aEXx7p#P4 VMMb}'t˾)B TAT.4G934EPh)>S(cUz0rͱ˦]ąGGqg c_#<0m/+tԙu)9HZ/*"!l7[uڀs94m MXpm OɿM% /WXE7@t^h&,, ǩWPfqerW퀊eEm 2+6 o 9Y|FZ*4V=Z`_ =΋Ju<셿X[J/QhE żky츆gM#5'v\Bx9?J\DS8ꢐ[pwL-~FkBg>9ʵ0LAm`9Q 3(~\x6yO`>RԵ>FO(=pDr5"@u|"kQ2_Pګe . 1-.k! c]LRj|K~(x BA}.ы:Sm8@QlcuZ!*Z oC"o(zE]by7"f;ڶ` @l MX)1NiDWSUS/o|$\PHϠ}8>~RwF0y=J) 'A6)lm#E!m'%@r|3?s ڴ.1ρv6Kp܆͙ϓ^{|pȷ2TJ\/'UTE Xs_.n9m൵(-5)[ |@\^ Pj+}^L֭Pb,a@Ha-N~NXpnhq>phB__[j  {<1D"f zŗ\@tE Ԍr4DԌr׍_@ @Ӿg4_+-Ur%a )|O,^K/ȢzVrY<1W-)ؓkp֐\Psa423+ۊr 3obnnT 䪘=6p{@LQ+QM7[+w{S҈rEΈ{k<EB&s@-EL?ԊGz|}@AZld_7 %js>>Y@ܽ`n q!!3 DYIG=BH;.$V#E9n_תe ӵ7$0w j-("2P.HLC %o.!ھb]Wk"W⼫GjZiG0d-V@ZB:/@/DdHyrOC*3ut mxӉW6[xô,L׹U֊GLHTG *27g5PګYw|0AoPs^1_Ǹ^mF9l1(3U381~Nz?z/|}֕ T#Qb]?8B/y1<^FJV, i>+ (v/#J]9MLܚS3J0Sy Y} y"E[4# ( Z? ^T`+ɿ{)'[|]f_X'T#Q{)0[BoCLa _.h@>bԡ|FvE R*~wwh; @ljGb f /8N0R``fGT`h}Sq`|:`kՙRj[3P!@,؃F#x=h[+ڔ{8 *`Rc`~8FC5pﮛ iq>Ixm4%@Tb{Ћr.0#!ȑS<|oV}S zWt:t^*~_w"݁6cЧlF-AM]Ѧ=.8@0NaLr0gJ桐CuoNr5t+KOhd@/~[nilyf=})*P1)"v\!T/BV䁅wW<5OӮ(i{8`U¹ 8Y^,لj 'r9/p_>`*}d@KB!||ыrͱ˦]ąGGqG}(aDo !;hBt܀#'y/˻悊8t'2qrmA"P2@ЊȽHyR3~QRnOGm.b/_.`_(aη#f]B\ 2W8n 腱Au6Q թO$@mͩ{G(VYIL ־E*RH|bdGVLOվM4`VpjK O+,S]X Zz^QZ!-XRSU_.rXGG-^3 {al4*}^9ڒ5`Oy߶iq$a1ȭ.f:SLϑfxy,'?S_^ضrԊ&,6mէ|mᦒ—+Ե(LB6aaY`(>N"7.ST OeEy.4LʳM[BN -&ؓ[`|_. =΋JuQQ Qm&` VA kżky츆gM#5'v\Bx9?J\DS8ꢐ뼾5\P f8_Bg>9ʵ0L-F m,B6@/3|f,z"]WXtsx/qU*ˈ2#E4ѻB~[ )L *ୀ1StR "Qr2G]DLQkC䴷GHKsx5<(>Lj"g#EDp_!G"(XH6@/D5[-bSz: %v1|  HEMwmOvzg$RTP~Q2cOߥS{E} M-|p@(Bzx&&\-U1;q;\P,3n CwF>)F8RPmq~r.G1^/z74~%:]LBouULS?xCGBvE 3EHq_˸@/n` "*4a=3br%Ƞ'-Tk1wM I[XS_j>`0:E|]<{ZZQukW/( jAk1mD`RU)0_`Wݡ 3 J^ͱCoqt) o?e c}2e`F>!~[6^m™"Fa~D9(Əebz%3 [)8^Zv)^@N7|:}pW "G#0Ni.Z!޾hjyֻ6`]d֌(WT%ݜ{# R`hMYEM>fb{ t>mZ9ջh y yz^JsR>_>PHϠ}8>~Row#5.p%@cX(lR upD %6+c5kELO9\<6K4pa'm؜)H0mHoQe7(qĞVQ )?_b]vp3K=*^[6G[.\@{gO}xLֻ_^cgg Z̴l E.V@   햃<GF R>@ʏ\d#BJo3.V,m-0#}&P>C{<<ĕV]B]@Ȅ<J[m _>0BLWrb *SQr/C`uc?4P<{FR0![B߶VH #5|z?MØkk2ڠG(ڍscL{ )ؓUk ]#b.Bf|cE xB,Pl䊹0{ [Fw}̭;Xlzn"Zܻ;LIU0"T)KrCW(~PT.dr )b ]h4:8ך7}⑐ Y!`g 0/o6Oa#8{BB-gy0kEBڡu&y)bqV/`nn|DջS_~ISq PT~PEj@Ym_f Emή{5q=HAYܾm5|/`{TQZnV/q:|C}Rjo.S LݲB#&t2[-gaV}uvC OP "`(/TfwNpPUGB(<7tw[,~nPLQs^1G Ǹ޻09yaPs.tX0lPm]l#T&sГ.#_>PhyЄ|@U <9+֕+یG3j;sb c؋y(v/#Jz\r9MLܚS3J0Sz Y} y"[hL"J)@8zܩ3 m*Xڇr ^weyyG -7HT]x;րPܽof-F3hƞ_>`t@HQ^0%H]oh#5py_ܘ<\0Z Gsi0F ,1,*2 b9nOy?"60Rj? V4a/@9c,XGyAWEV̎[lPhdna50Sh_lÑ9ĸW~lhݳ#5W=E#Ŕ=r !6LqEs`_;޵VD94 LՀ~B 8{*2D/r[`i@r BLM!X&_>P C?7Њ[G =V½8 kMRN~^b]sPͱT#,V rfkՙRjbve*@aT4Phmk`@rAecR旞*c4 0nBQ=,Ǹ8V$p6yrLӀ=h.03C FG[\S1+f^鼢yEs}݉8*wG؄GF-AM]Ѧ~7b|NqT+*zd o8mPf~M@+KOhwmO#~[nilyf=})*P1)"vPjy@Ê`Gw0|tn "#_Z7t5A-c!@ۈu{8ju{׋vb|;\`%ąL5Ae "`@4֜<\z]`V.DYޝ#HAebi)#Q 0ԭ03l) 1v+H4`VpjK O+,S]X Zz^QnrH9:LUa@4::Pv{4셱e#@rf FxŹiq$a1ȭ.f:SLϑfeY08O\K B9jE\6So`pS n >RS`JLB6aaY`(  Bfj倯/(v\w[\@ "S*ݷ셜,60>}k+Zr8|lGp^lcbI15`/cD%` >7 ?@+R-] sV >CCvmc;Ae '6?^2. vUCӽaE܈A/8RȑR|>X Gz, XR( !. <|%`B>FSx0 e_0 P:=x94_ Ho(#8`I-0\+DΌE]pwֵVk '>YGL{Q}>_cc-Y 8UoL ňrwty8W\Y#}7"@҈rFjaT VkC1:Nӧl#9H/_΍=\NM\ЈmE+Ō3g<ۆXR\T# FVs/}J-زiW9+cHQ  Ц#{|KތA ]^ @|{vt )ha_@]Ò `__optEwQ].E)(P#`I2~r/I7|#.Fe P|ve_{݀0+ ib9zGn#_/d#y!E] l_.G])W(R T7) *26 u)=.u(V+ Ϩrz ޒy)q{JdrA& >-U1o@`2;̻h}3C"/ 6- **rdE{^Orp0#C/6NLr/Qr(}݅)"PEP`\;tNr\G 8z(r<2&Vih .ƶu'hkWT%ݜ{# R`hMөm}z*tf9sJ ZBB/p/0x[<0/#Q@E#?B|]jli+b-N#B~ |mCa3fA> X^z_α5"p|.VD\%f9P={[C\i%dz.r,G h_~f 淭97Ԍr}5|@\Z3bIŊTf傊Lήn0Ts"pPQI8y|b92Ep/ķ/ nV7,5< tQ3f_7j Ԯ*!O|TrLZ/Pr*ARG^M{2@1,zQWo%`]s`kHܧ8^kHz_.b0#V+ۊr ޲@+><)7XzH`nYmo`:Q^-^޳0k{b_v~Pϓj#傊Lev E|APҽw|0AoPs{Tѵz `#0(9u`, vw 2q̙/ \Phqj n]@U <ĺ=p͢ ^BG|}hdo/JZn`{1Z%PyR&&@On)i%W)<,>ʆkV½8 ^RNxuU/;L/`X-}UgfJybm-@FgiT T7AXЦiPX_2|1 .Ӏxw\Nm9Nk-*< ؃^ u)C/Nj4_S(cUz0#\4ǶO,vJA8/m?/}9r< ]ٓ#'y/˻悊|(' +EieH)8{/}LW` !TC%q)[eu{a-@b|kl`%XP -V:WX'թO$@mͩ/ ~_0+_NU2z1SP´^LJ F`[af2)RD?UT7@wP:jY¡-(>N4Yah鉢{E:jto`Ixq7OqjyEKo:nL^hnh }7cWd (S6޷m`fZ+25f{Iyr믋Nmh?&Եy#|Df<`¶-V4ai>%k 74\a@|%Gynh6yA nT-E(sy@d:WmevrUhh1z"n\0;01h{k& >>x^ Qm&` VwZ"b^ѵsv\Q㑚xvmc;Ae C %qE)uQ 8z;E\ԋ2#)  |skayܬ9˒% ""\Q6!TO9`2@w#-t)/;7(i"S\@|m(F "r|5˹ Ӏz_.f]TB\/pF_.`_>=a/s4AG/}iQ= g (F2SGZ`=\(˻UjwAmP> \LQ+R Zox#U LFK:Ŧ!%q[%"}&o̔EYn#7TYe8RD+䇹 IP&΂@|mD+ƾy6D e/^6AkqA!r~H%ޠn{2ky_U cE/{[e" sV')/1n' j&⋠؄.gSzua]ɔZ[CFDwQ>fE)(P#`I2~іcyx$w α(S\u\A({|[Y|N>\x5yW>`>r̓)YX/`#׋+.Dr"@NQ|"g.ep@kqK= =*whS_O6(>20SVdbL&[b?&_.(Lf\;#ryQmq~r.G1^/{{~5gyN(Sc뮐mOR6:ru;|$ELRj|K~(x B؃j6@Y]DE je{i X]v@7qK F_#\ܻ~N3}%6[5h- 힃 ]J"; 0ʢ;})(g\(h.8ކfmdD}\.uhOO$PVP|(x9Bi5ܢH2bKYTevv~шr:SV%/Z!ZE".56mH#QRK,9F@њaS=,XQBk7%a)TT#;|t9\mq/b`V(p@_H`m $p[ &(q #` O)PrLj B2E!zGXW|ʷ{Y+ 6sH|v [|:E wlqGs@4cmPi _>0m!P) _4\ ]xAe? _.b]`\EyԜ䎙{s}g>0m(}g-ζb՗mٞ>YD9~gbL`sfе|\:#j )?j~{^33{ 您c S| W|9+ZݰL\ tQQ/U i3*YiR+SA!BJm0mV%L_ydыrH<7 0j@=O]p֐5|-hvЪcEvb[QWGVZ̦3+SҌ[ZxZQ5ܢP@)vG#w5_hq4H3fķd|\mg#M:.$b7+)\+2m 7ɫHc׵jywtv9f5A׶_RTpT03)TiZ=P%CۗBQ[^jMܾC+RPql/|[  %^gp/@JÅ~R[Vh[}NԾbgaV}uvC OP_.`(/TfwNpPaJ{61.& cn/ Ԁ}' 6r3^ǠLTu̴"Pwh9A{Ϝy8:GZl^u@-4ǭ+PU3,Gqu{:ExE90y݃Pv/ފ_Be9 X5b)#hBHs=5f!\arA4((M.bu -[D 2E4s(W;U`a n]y 2| ,6k|PrDߥo 8A 1-x-F3hƞ_>`ԡ|F (avD ?LL|;Ah tW&1W}y`X3<`|X$6cY0(hUd;4Zs63//)ַYpY RC`1ga#ߠG y/)[X &T7pa1zɱՀ[+hHo#L烵 qQ+d^Hg/ o)N'muĺfAs܀F \ X0uL>֪33PQAe2;<̹rPD1A1s5S _>@q5BurDUN{U`f8V Bu @[s*6pDG ʅ;߻|D)L^0#ӽULGf-"ESAo}St<݇'iE vԻ +XKO+ Q+{c=Kj 3倢{@ 7`a/-QRf і7;}C LkEl# #@nu1ө7-vC9#2 G0o MD)70_[ #(82 ؄eu/E#AU Up;bDm(|D@ "ӹl,;րgBxmE vӻyVi.8GPvjv~luLjj@+R-] mgYPDC]$y@>+J&j}1iLF;6`8e93<B7S~~+^ Ho(#8`I-0\+DΌE]pwv+G̮-\dm3Gcc- 3rqt<  vGh;AQي<+Rp`>w#-t)/;h9ڴQ)pk 6s^ih9}f>Rcx `HsiU/f]TB\/<|9{m^,hF (OcF@7|a 3uT/kzn/V` OA97p1ExKQ|G *h;X\TD&2y`/|cp6m!@Zp_`e3SNg+_[, |WPe H djo($mb C8 [p4g# mBG]DLQkCYKAA8~P7d]NZ6Sn ^Ѧ#}Ure=I,$_>{ {?i[*MrvȜoϮ ?-3 K6b9 vl2EM| mOvzg$RTr߷܀0Vi~b95@ GF~8pc@HQu6r}_8Bi}jE rw⁊L? ~.9 PW3tk&2ie  1-.kS.)>Pw2S:/ߒJ18񂐮{P/`V_Fy|w1Nypk+@>iu=ں@)a /u]x'0S|O\yKx R60ؘ)ɔEmx9v g{~qtrP xs㛀_-z/w-6Ej]v `_8~pJPF)mE+ַ/["Q.{z$o(zE]by7"f;ݞQZфc ǽ@hZ\ϩ/sJ{ ZBB@Tz_8L_ KHT+Vw-G ~t)S8/n2+*{Ea3f ͠|(u=%L *c5kELOy]&<6K4uy6l}f} {{@6pȷ2TJ\/'UTE %,Ŝo>y3#_+l7 ?{Y0C}W /Wȃ1{Y(3m[BѯPBxk!䇵8:a=r9j}(| @q<5a_HL?w y8$LoYLF淭97Ԉ}5\i.eŊTF偊Lήn0Ts"{ak6"4!߅"Fzŗ)er/|:aQ5LjW}hVZf9xK|9Q#·RjH]X3 <[zϗ 2LP#^}FscL{ )ؓUk ]7s 27 9Vt h'p#Je!b#W }y*f>D)<;ݻS|*l=-VK\/p/@JÅ~R[Vh[}NԾbY0L{:P}_`(/Td*;\8Lwo(9Y\۪+T☈rܽl<)5J$]ƒ!cn/ 5i}̵E_0x+6as:6w 2q6?'=YmMv_@3_Bid>sW+9,++B۽#@%{+~ !Uc/8|<]I'T: Г[s `&B۔_Jz_eC)mŪ(AJ֢q^L46,5|Lr^~w,V2KӌbpsQߣo 8enB jER`4l~[y`  L,~`M٠P¹2J^zD%t 1hLv`g̩JTLCw=FS]/iX \j`ߦ]Ӷp @{p<[j 7p9>/pz_.EPh)>C(cQ)=J.اA,2W}rDP[q~v<0;0-&w(a1䩰6`6Q4'l!3NP~lsVw=/Ԝkq *C7N@w b(qe>&" (BoM!{(ruL!GH@h+µ0L4jeIBn\4h`(bӶ-lUx Fv_!,/|z(!0@ Y>N%EL%XCy`w]eL'},B \ Q+R2s?eNx(-e)Td%vc$N1O6ĺ_%"}&_LEYn#7TYb"*]!?~o!~3Ee슱oލg eyNQgC䴵GHKxq n{bDX cEMI|G6 0`p Aa1ns~M`~%Ė/b)Ld]ZG:] \!]!]!{{ ҥlt;]R@?`F 92C:/ _BQ ?P5xJ"g6dP_r(k1M IGXZQ Y؇8 fO/0{x׺Ⳣ4|g*|D9n>Qz7]Xt={"򁂒Ws̩+ _qt) 46&jec}3e`F>Bl[6^mgņrD>( x=DCůa@E]ʢrWl\CpJPhf+P>1 8[E"5 X59Ĭ~D 0 ;ݞőZQf>*46Ucm4l} jBBj9m_J2!Yosx_>PQfP~KMMwB?Պnwy@gr+ 3؛l pd*CfPr|3rX=ipmh a@uN{cs;#ZwGL9aZ"4P8kPT/[bYvw9Qjqc?~~yr>Zl_\є0,Vd, j!a 5$LXN/6"`];@\i%$>7CTilCJm0C`44K7bns-T n!j|"Q(\"4js{{g:}w>0PjW(7SR16w']I'T.: Г[s `&B۔_.Jz_eC)mŪ(AJ֢q^L46,5WWD9/Be+yyWD1T޹(Q(0[B}0c4|̜!ӫ]_S(Ul6N/Nj)(\Qc fVGsi0Z# Ƙk`f D5uC;b)0ӘGl1pW *P^J rǸ!v97(r3 5u)ϾG?Z+;AɊ4!S/9Nvώ̺\Y4P\4@9BLY1FḊXc4^+ iIkOzX0orACs(NpT@rxA$ _@ р,/&L|87_krЃj-N85\ Qȿ_ɵ`& _)N'd E 6Wp Cr+3p(Zuf{)d/ 0sK **7 ؃n`@ AecRjrc46v`ܞNcutZoq8>pDqӀ=h,rѥ\S1'fP`s܉8*{'`lM-AN]Q~/b|N_qLT+ mL40(@Pe~U@,+Ĉ'AT|_?;7~`hLv`g̩JTLCw=FS /iX \j`ߦ]ZV[X ݲ|DPUAuE qgP 3B8_>Es4(E檠O b+΁t!>Kh vZE X=qX"ipwj>PQ 2qR[Dw0lt^ "=CW!8/@>[W\rߛ(_) X% ZQr9N/e qٿ+AeB,"]X Zz"pwt~VC:e xIr@nDc0l/A߳C|) Ylf"њ~f}Ii ` թs0^@T%Ɠ Ƃ/s! Mg4?[xr %Gxn0]}Qɽ!D`*~>/(v\ެ@QA "Q 5Z-׏(c 5FK "iqŬm(/6E 3|+{#J_`n`ֺcD 7hEƼkx5|`倚xvm8Ae|A %qD!eQu>__>P f8-7lPmB3صBo? 0ӨyXs%s A?DpDsB0OkiPت0<Q #pJڀiZsW%R=8w4? k((C`:| X|ș_>( .5<ϺJ`F1psiE} @u7pD/T`Zcp>Dňpxwti8ai@0lo#-t)!@w47(iۣ"Q<@l(F "r͌^%!qZ QQ {[ů8#O/`_xa/EG@y*^c4< pE-x9{(rjn1$`?x|!jWSƃuLY):x!-e)Td%vct!% z s W60dgŬ }%A-ÅErATѻB~BG*gB ~ "c߼9@mʄ8""?;E  -S Ʊ+ '|`%+Dy6%45cR/qX5k+!0Z*ty%`9%`S5=iz˒ w1PT +:tr(tA듑Q:L9skyuHo x뭁.Pa.(Fyh ) fceq?Ph\~eTo{' /0!j~E;)W(BTKz耊DY lFi(+266Ux9N+CQfqj\xYd/ԇ8<-booL8@8<0D} Cw2 d>H4Ƌuك^b>Z(Ou2\w\w-hʽes+.3J1&? 3DH^|@tM3؃HxHX\2Iůi9(k1pHB!Cp~i{r'x~hgE _0-( jmbm"VDj( `AÞW4TPj9bZ+.q`@XLYφ֡CbC9 "ggb<.`4"\}]ʢrWl{R9}a^e@QlcuZ!*3Pcۀe!Bc{[ .1GkNgqd} ~$S aTӰav@z 1s_ur`3(ħ4L$lVtK#-NWN!?Eg Ş{;(9Y *ZnZT5PH-#rX]ipmwh i@vN{csd:soG*@60PT?-`,| /p_zXƌʊ!r0W9"`cO/p~|;"jip]D{[B֧Jަ B}XaGj}]KJ_>@15a?H4B(T(ኦ0bEbf:;D _>+4/-27ZGqW0; *ho2! #+0۶970E_˧Y E/ 1G/9"Q+ 5;^FynM|+VK\H}x|OC*ut mxӉ\Z_pJM} y_,J"JQ>)a&T(Β(R{70>*aJ$]ƒ!cn4]{4}̵E,@q̹ cp@UgVMl~Nz>2t_YmXB2O_PU3Gq g/t@^!!?XtؿWBeqw3c؋y(O/pW @Jɭ90 wpJz_eC)mŪ(AJQZ^3hlX8k_\r^~w,VrK+bpsQQo 8enB 1 /93BWERQ({>r7_.@S.xoQ @8ҘNr!Hl0\3cP`U$;4Zs6My?`S=R0TTR`4< QL[9` ?|Y2;nXyBOu;AɊ4!S/9Nvώ̺\Y4P{0 iPLci5( 2bxaHt7P1'==D>4ԫG% D/ /\D;QA(ܖ8XA4倐0ضſ3a7@+B`n}>z90Ejr@Aׂq:U=&c/,ڀCU0cX7™}Ug&Jyb(m-@Eg8iTT؃n`@ AecR _>_8FCacy j4`>[7D|3VtKUE8i4( ~VEP%0(e3 t^= s'"쉞UX-J– QS1nøuՊaE=S2 7 6P4n ~U@,+Ĉ'ATx4|Fa?cc4Dq]o3DT*!EYĎ&fBU@$̣W"J֋1xC݊m-"DSņj yGG 0[t%V-!?r'-YA G痩*QAQi7D/ bp&qd#9 }^>\򁑱^S6е8740l+5HHcV[]Ltj F >WBi+2UI[" ^z߅|Ԋ*,6mŧlᥒB#3bZ J,KE F%!|hb < upZ_8}k^g 5FK "r8bVжCsE&q-@ 5xOWX_>+DNHQ]jubvm>'=FH3QN}f.+?[̺y |Wb>\XL# JV,mJ+%Ȟ_ c"ړAadgcxί ̯h啀dηDMVeeػǀ!]{ g7`SGG**hoE(btT!'\:$r}eS @1?|M >3 4wP|r#ʫ\Yn^ z+\t'>p! 债݃,e0@gqۥQ{EަJ,{ႨJm0 ?P2 0CVom|j9IHF~0z*D}8e9\H4ƋE^Olt2fp\w\w-hʽecwr+!BJr.R/ k= 0n`#4[DJA}NZ(~ {ڦA, Y؇8 fO/0{x׺~}krm C꣒ίwLztpE 90 J^1^_+@|ѥ.0!͔Elmx96 g{~qt?P3{_,/c-vEj.?!> > +@t PJ$IYivt'uW%fݜ B`hMQTooflo12X[OiG]DWSUS /JsRF?/A!>-5p6} T+-Nap 뤐g@3AFT%L *Zα5"p`S" MA8 .`w{< az;b~Um`F{[E%P`8-`,|;|pKz<֢tŞD9"`c/.Pi rv?iL@}D j3غ>L."Ef7 ? ,i< QFR>@O 2-1qM1( )> |)afYX,{#@ԘC kHBW;4s !}b ڛLH!a `/m[97|`4K _.sV2/ A_Dή0xD5繾c&<樮c%g]=۳ZX` Gߐٞ9YDs129{+@{k𳚪u[rT׳;= ~{@H#<77b.92Epm弮I薮ucg/0qU*MUB;Yi+rGRjM3 )3,逈B)wØSF aJ{61Q- cn/ 0i}̵E,PP|@U 429+֕M 4\7o%@N+TUc/8<|O\)un'L4R9L)+Y} i " @T+"*DkqzxS&ZQ1X{uHp+T{_fSX}dIP{>(Q(0[B}0v,̩Cv_ FJ>x%bc./p7]hbm11 `X4`F,1Ej w@1 FS`16+r 1 ̲@>jER`4< QL[ZY2;nXyBOu;AɊ4!S/9Nvώ9Bb¶YP6"d>^46nHcNZ{қ'4 q " DqՀv 8w*D /pƆh@r LMX&_>P/؍7Њ[(sjN85\ Qh {_)N'xe꽭05\Ja g "QӽCikq:/48{Nz.`ڻu3iUH/Pmq{ނg8 iqIlTsK ;$K ' +`Wm\1\`t)]@ Q?Y6N+CNDQ=б[6M-AN]Q~/b|N_qLT+ mL40(@P{w_ (1iˢ0 P޹a8;FLgZ е;CdNU bRElS /iX \j`ߦ]Ӷp @{p<[j 7p9N/ 4b_!"R|PǾ6Sz0hcX6I檠O b+΁t!0)}|`^V W392 u)9HZ/㝚T|E!l~ȶ7Wuڀs嶡4bx<<!"rEgjq:XopIs@9-Gi,b/7rA1 s_.0lT mzAP<ҷ+?AN} *hkNEJ^.rY}gPl}:(AebibD< [&E觊 ~M4`VpjK O+vhnYY tӼysN8}dfŝu_BȦAT!| FxM`BLV$q$a1+ȭ.&:Cs+!4ʈFk`,x]K B>jEL6So`~RI bZ N²P}zE5.CT nT-EQ< 9bNr٤BlEm>6|`Zw`F1+h[! M"DQ /J^(Ljk%`6QhEƼkx5|`D38$`6To WplSQ\ߚCP$jv;#!  4µ0L4jeIBn\4h`(bݸS&Wa@D)쾺C)ikYi_=CJ}B Q,'" /*L'}r9ŗ /Rkfkewۘ`xE_}G(r@EsEkPIE1pxwti8aW\o#-t) /;h9Q(pk ~6^hh9}fFEͱGzpr^0$yr4`*䇆pxm]B\L/<|9g⽇SB\@<N(5Vصe@)a uO/`C4 +?{C97p1DJQ|x)?;E;X\TD*t(hg?نp6ĽC6@/~3f,"]V~u$2<djo($ q'e슱oލg(Vr2Q&};aφik)u@ؓ >ň"*+:i uOvlHBώ9UdgQPYC:ܠe22Da(Fn|M^34oP>V,(uwX`%r'8O@B_>poQ\P݃Q2_P٫p/)^PQB>4!˯dC)旽G/zfml}qHX\2Iůg9@ֵ} IGX}S}_`0:2܇'.;.^`th- vAWT ypE 傂Ws̩+HA|ѥt0ؘ!͔Elmx9z ʡo?P#BDE\,z/o-Ej.?!>} .:Q(V%C?BlN4DE@>w56؎Dq>wY7>=Z`v=#뵢 @ B4l&-=/WB/p/0x[<0,rAE#A!>-5p6} T+\`_p%@cX]{RHgл x !JgJs{M!ؔjHkӾDc>|_+؜!Hx@6pȯ2 JܾU"Qq%wKX,9/pn9`O ֢tŞDøl/~\`vO=[|Ws2FP5fl Y&V@" 3gu6AGj} (<@\5a?H4B(T(ኦtau>ȩ{osH|v~ [`j&l6"`^KH]7CTik`mM/̹ ۥ5< >@e?jy`_.H C>G/H{ jE1~(A1)k ڶ{8L)ky@ro= tc# ̾nG2*MUB;Yi+rGM/m[+3J= 3 AS[V6mP|uLHƌ jZֵ" !ˊZ}1x|]1n!YmMPk1Dm!0!D[pAU$jV(y e (-Y/p&_!8uڶ*J P%^ 8ԇ B?UL-+mL'j[{W >0K{'CO%`?$*,逈B)wØSF aJ{6{Qld{&D~&40(9u]alӊCݡI BOVg]l\Pj ^]@U 429{7=py`_cyXPɿh U+v% Ʈ*@J~EskNDC(bQɢ\lH#4mP!XB5fQ E MhlX8k_®Bp2QN}˯P}EJ~_`iQ wn"J>;LEA(oCL<\PR^Q=\`t@Q^7D%%aJ/B~=&(w݅ / p F5<!hcT\;@Cs(NpT@h *'+F_>e ``ld؍7Њ[(tNp qQ+d^Hɵ`& _)N'[?gq/,ڀC4 ay\5™}Ug&Jyb(mp i9TA{7NyӠ2 )5PpTDO*-Yl4 l u:}N8(q &özd omh~U@,678@)@T|@(~0 iy&3}!2*P1 )"vmQ(O aEXx7pE}v@NWXl db}'t~!B ůj>NڀUX8F߀3P 3B8_.0T8ied 䈠 Hy죾fpl" B'wPpz4E"xy\PQ 2qRkA"P2@Њ}Qk jA\7QRnKGi,b/7@1 s_0lT [⚠2z؃\:yH ښS <`.DY[N2*BPh!(aZ/FJDLjyT u+LOQ ݊#B<ݗ'iŎ@OVȱȺWd,vGg9#@Tcwt@q{@nDc0lDNg/偑^S6е8740b7~f}Ii r믋NmsJH3 2sQ*_ ^`BoZQӦ -TzQj;P7p$: #\E&"0ӀEUl~q 7; υ Z[BNc 5FK n\0;0-69< 3PB9F\+;#c%<75] 9o㐀]8kPB(qrv'8_ Ć+QpE!|.ju7lHb@=/8BR|Bcp,\ La]YA?DpDo Z(f?ݍ;er*< Q #pJڀiZB Z 8oqO/`*(pNt_X|_.Pozubvm撫xZ/^yz%||(2xADQ~! wG7(J:[VxEΕ(6"@䩾@ (5ڭφbt+5e3Ԣ#/$@i : X Wp&{؋95*ąxuz_Z5FO/xJLQ<|U " CJ1 P> \ Q+R2s?eNx}"U  .6w6$$z s W60dgŬ }%UeG Sw0|@!q[qPp2iTAb,CAJP&\(w@,5(~6DN[{4O7}˶`{bDX cEMI|G6 0`p Aa1ns~M`~%VFX. s='lJ//,,{b B8I)Nڎ>Qّ0 l?Y{_.t,5]Nm;Qk]Y\Mq#0J^0"ʷq@Xu\ SP*[T$z`/pxfT|]=P,Wdn\/΁:$>p$Pbg(<B>pL.(0ʧS"Crh!? ("׺hgEiU%V]Z @힃 ]J";0¢;t^\b"^ UG={,6#P>7Sf!Duh(!bTa|./7QP{a!"PEP`\;evN^)=/= (~N:-6`Yd֌"J+n}!0{&(t36fb}Thl=:@a3]^!OU!O|@Tz 8L -2J]͠8>~R-N(B~:)Dg Ş{9ˋBZrQ´\ԶzM!ؔjHkӾDc> 8yϒz;b~UYC]@%dJqZbYvpu_+Ei=oRsE~_.wY.0Cݧ`-+9#(3 n?d B}Xk# h@J"Cp2 ׄ R}̇+>`Ŋ⽷?D9$s>;D 1*(f?u}i!;B+DQA{ i8$LYL frj`_>]ZbNÊT傊Dή0s"4js}sL=x<樮c%g] JY EpsC0XozlOyZ眬" 9~wbn]•k?{k𳚪u[rT׵}ljE1w!(c SrAWg0+jؙ5\`u<PAm JK̇_3?j@hZ!6Q^MYg2@1zQW%`Ys@=o]p|֐\Pgo@$z7<9V4 h#pE >@+憾4[X("VrpE!0/xh-Ŗk<EB&3@5ED s_( 3_h+Y!`K{_.@J)CДdO7uLHƌ >`sHBH;,<$V#D9_תef ;Dzۚbg.)B`*8?*CRH4@P(ҡBQZ^jM[b! {>{ n2Z2+<<0j Gsi0Z# Ƙk`f D5uC;b)0Ә:ԊS,KA8zVG^J r #`?/yAi/)*GX *T7pa1zqՀ{v`ֵB}b Vb> !6DqEsړ̝ 8Fq !-w|8#.~E 6Wp C+3ڂ!Zuf{) t^$ ip3AUQAu<w+g8 *`R_8FCacmU(qӀxo\Nm=Ng[NU(Ny=/8ʂkq>/Div~1+b*FdL+:Wt:c;GeOB"o 6Up:uEq'v-V.Ꙓi($aP~QD ΕQbDғ *m@(~0 i(δk vȜ@4(qz_Ұ" ," M m@U 7,wy@"@nP`DBs_. 4| ž2C@E }?lF(a h re*bKDsا[Ж W392 u)90V{悊4Ц9Wʰu B+Bp ^D}&PD PJQ-QՊWHT4vy,K ۼ jBuk m+?AN} *hkNEJ~^Y}.Q\E3RE*nS&~pVl3l!*6T7@wP8:jY¥-(>" 9Y[A/SU_. r/(v hƑ Bw5x蝬7;5e! kf"QԬ# #YAnu1ѩ75vb\ `WF|@0T%]cZ_^{ UX0m OɿK% +Qj;P7p$*,UXXV7ʷQPf1e|hB*FԖ"( \hΕgo o 9Y|Uh1Z"n\3Ŭm(/*M|l1Z f;FB!MX Fz, S( !& 44sB0O9UeR}uSLײ<|3D ԇ)BO.>N%q()B`*(pNt_X|)4xV|Q̮-\dQg} Q*+XGŒ72xADQ,ݠ(lE~jXn!8WҠFZRz_@woPӶGEx­PxE-5y pӀz_.ۺ(~_.<\?|g*ąx3 'KT:Ͼ@|bS*@&(\Q "؃mg 01@  c<+E):S,`q'RmM*t(h2Β@1q'KKb=/ z 43}&_LEYn#7TY!Lň"'-Qڷ[yw$Z! !80} atFyO|Zw|Њϊkrm =@D va>[s`9b魒.8ށf20# !C/6^caubC9 "P 8CD0~"X].eQګwt8z(r4\avʢBI띋}Vih>@M}kF%rwY7>=Z`v: 36fb}ThlLi3J@z/pD6M~:HR?\#LBƶ*BJ0hw{Y+250^TP=_>J 3O:>2CpӭwWZ}u >sDM&0}d0Us啥T7RG71-0.b?#Ae?C c;l(p}#AQs;fc:V~C= _`NI @lٞA1s<‹!3ο,\Y0=[{T7ؒ e~xEP>Y P(c S| ڶ{8L) _.q؈(׍PAm JK̇_3? _> m˘ 0H!`&}ްD>/Ȭz?eyf`^EuYCj*֘ apX$VQ(BJz Ӹ.P|Ev\e՚_.l:|`ύX;sB3.]}rm(\f(CRh#ht~Aq Uw񁨠Є%E /,Z4:qvRdO7uLHƌ >`sHBH;,<$V#D9_תf ;DkkHaV~[l="j̷0!Th_>{̺:>"g"@j8_X=Z1M{GÅ~R[Vh[}NԶXc}faV}uN%N/HT՟HTfwFpP}T(! BI6V|'*)eF(aä~Oǜ:UmZp;49um-"B7<&*xuJ`(+FE*yirޑ0VGhJzmfNw_Q1JT+ m{<&v&~hbi~k04$8ҘNr!Hl0\3cP`U$;4ZsєiLCԊ%6W9i RC`1gfߠ4q ֔ #fΠ;AoG㩗^ ZQAgGf]k,g~.!,`i5( 2bxaHt7P1'-9/D>4ԫG% /pd@|` _2Ai)9s6?q[ ds `Z! D"L>g^Jq:]G\<@, l6Pm`Wf +`}Ug&Jyb(mq^:LPQA\w+g8 *`R_5p0㭛D|[}٨SU$SAevz7(hJGW|TͰKP`s܉8*{'`,6Up:uEN8}?[X0Q(]3%PH~àlEC pX8WFKOd _?;7~`hLv`g̩JTLCw=FS /iX \j`ߦ]Ӷp @{p<[j 7p9N/ 4b_!"R|PǾ6Sz0hcX6 .*Y1Է@D1~_>0/A\8A,{8^;5 Aw(' ݡM " sa뤶̬ ]"V@ @F _.@{%@+EDpV+"^y#Q[N/0,!.]P+Ae8:i7T`/ Ņ Y40.U2U~esD< [&E{(Ӻt<-\ӊ8)R.c-=uȘ;E?+!2UQANo:/܀~a_>g/^5;5y3R2۶hH+5HHcV[]Ltj F >WBisw2Ґ=[ {o! MD)70?[xrUt1J-vJcSN²P}zE5.CT mOe2<Ds[[BN&-lg+jl[/pI(fmK?D}Vi,cGP%J/l070k1 "Qc^ѵB~lsVv$ހ]8kPB(qrv'gC@k(1aGYrG@ /Z!}f>u8aQ.Kw(~ࢉD3 (pE XP`ҠUay Fv_!,4߯!J>L!zrq(i~|GISA Ppr>]W``WKv~v+(fn.s3(Q倊>f\ghkᱷuQ q1|3vc{E}2 xu} ŦTHLQ| {  @aX)ƾ\to(`bZ`Td):O PTagO.6w6$$h@ f,"]V~u$2<djo($T&΂@lD+ƾy7rYiᐼWV9ߞ]6l%`b9 6 +:tr(tA듑Q:L9skyuH@H}]Nm;q7e?{̀0Ӹ+ ib>nC=pF[|ۃ|p3ʷ=>G])W(BT- *{8Rf}<3 *>{.yAP,Wdn\/΁:$>p$Pbg(<@[&er 3DH^P=/zfm<96( Piܷ48ɕ PzDi~Bl+-3HB!Cp~g;r's&Њϊrѵn9@UxWkm C꣒ί{Lt"rAAɫ-+Hw@|ѥt0!͔Elmx96 g{~qt_ (ˡb|`E\,z/o-Ej.?=/|~pJP"@3J{e@QlcuZ!*Z md{[Ĭ~D 0 ;m=X*6Sb6q.Zz_> *LK%\PQfP~KMMwB?dz@L&WN!?e4b@=dNֳ@0-&h9jDML46KL43z؜!,.`#&@0m_Qe(5^bOv%,Ŝo 7ogʊ!r+h 8r>[n^~s7k3غL"Ef7 ?ܻq{C`g(b O)P(yk~i@QH>QMyc0bEbƋrUQ~q"CpӭwWZ}u ^s &pH>*mM/̶97r}5|@sĜއ 1GM/ A_b]]a(\EiԜ掙}{yQ]J޻^=۳ZX` O뜓A=C-kYtg:{om~Z_ %Gl}]kĺ [i@*_92EpAWg0+jؙ`j( clD4`Z=e( jSh~VZf>JQkq*54RjM^}K^/Ȭz?ef`^EuYCjrAk̅PmHU NJ&mĶ"BG(Vr[w W撧{ Q,*l:\EXv (rKW[nW(\zf(CRh#ht~Aq UwqAT{Z b%+&e+Y>AS~!8` 1!!36͵" !ˊZ}1x|]1nn"okZ!m a&Jݲ B"PBg,KH_fEiήz5/=AY+VK\/p/@JÅ~R[Vh[}NTr"W|ô,L5,b_q~lgI}5rAE23z~t"D9R(@wbb˦L` 8\v1c8M+u&}6?'=YmMvy_Pc~O|Օ TL#Qb]?8a^/@Q|Sv/Pފ_Be9 X5b!ܕ{BHs=yf!\M偨dQihJ.(XݿYcz~^%QZ? ^Tc('>W|"`%?/?1( ;7%ni!b) c4\m3/(%*b!Tl6/ߋ) @_p1'0B``fƠ(HTSwh0!m03󹻱AQb`#ůL#/U"3)>0cF_.~B?/80_f-XS6(T2Un4`/6Hb<ԫ[+*hk͕LE#Ĕ3|`#AC1/lNc4椵'yBӀy 򡹍L^ 8*ig D;QA(!i4X&h`hj _.( {q2w6GBY'd9 WI:^bY`szo0;L=/0cX-}Ug&Jyb(m-@Eg8iTTA{7NyӠ2 )5`6@ňڲQEQA "ѹ-Xv~{!'o 5FKV6- \R3YAQp_U( n/x%`/cDɵ  Zw(m@+B5] yΎk Rsom5 !89;݁3!5n0, 5\qHb=/ Bg\`Z&`5}$`NbGM"h"L9\QV!TPت2@D)쾺C)ikY_>`NP''g8w!0` L'},B /(ʂK= n7ͥ}N{&yz%||(ȿ_~ "bD%_`EIg+pSw6"@҂iSt~L}B=*n φbt+ -o(9H/r@i : X Wp&:B\=vEM4:'BPj;d$BTDgG*dr^%r]y}@傯|$?̀/0x+ib>^C](?Pf}ef=xz_>pUP*-T$`?(K1̀?P٧\vgvA^򁻊= x'q C CջoPz_.pDZb?)2rA1coS1>tgCw¹xӶ>` [s6[nXN(C0c뮐~8t)?O:@+0{h!BJm_ɆR/{!(^5̀?TD-" bmr%Ƞ>'-Qڷ[yw$Z! !80} atFyO|Zw|{V|VT]Xo֠h[ȺUJ]aS.,=\~ "^ UG;,٣.>7Sf!Duhk,.P|Vl(zAb |(ό&*~ *BpR~fE2;kN^) /h]hPzbaVhlj݉ mwY7>=Z`v:ۺk3>*46Ucm4l} jBBj9@TzpN/ -{@E#A!>-5p6} To1" \ P8'h_L# 3AFT%0%>^-g60z t3Àv< az;b~ku a JܾU"Qq%wKX,9N/.Ҡk೵(-4![ jg8x;"`-W1EP5fl Y&VXo@~X>noli]ZRžlQ(<\@1|k~i@QH>QMc/0bEbf8_C"<\r@n0 qW3@TdB '*mf|` /҂ Ĝ/ 1GC|"Q+ "\1}o~`sTױJY EpsC0Xoz @9'+H{#Rf_`]{=jG|hlQl4p~V /mS (vB "Q6UygH3r|%Z(жBJm0԰~6gWD42En$`Ys@=o]p|֐5|5h+d&7\9V4 h#pE >@+憾4\G_"a!޵ 0N/"Z,{;LI(rޥ[-g \,eԘBjm8/(}*.>4:@AZd_.7< ~%!hJ==6+8cBB5fla%kEBڡe!y!bI| "okZ!m a&Jݲ B"PBg,KH_fEiήz5/=AY+VK\N/P_.ڇ̇ T=0QGж 0me] 0L,u:뜔`CVD)j{LlfwFpP}T(! BI!! ؂ޠ8Ik Vr?iPs7~mL BOgLq <|Pcj =^]id>so8{{ 6< r:{GJ!+rZw$Uc/8<|O\)un'o1L4+)=\,-Д\^QskT+"*YyyF3 ` +Օ"QN}˯P}EJ_`iQ+G/`NpI!b)ph9u((Qɮ̘Bj[]_h#nZ+~[L55`hr#94-wc503FQECP 1mєixt6+hcb`#ůL#/U"3)>qC<o_>0_.pa̎["il@Ɯ7Oh/D>4ԫG% /pd@|@ŬIt 0l/ṑ6?+[(tNp qQ+d^H, _)N'xe꽭05\JaCD)OR H g8 ؃y#=hV)pT>V! 0L/8FCacy j4`>[7Nvfsw&©*)OnPДj9`@Ũ kt^鼢9T~D= eTiA u"8@"ŅpvـJoa5nLd&¹2J^zD%_.@{QO3REk vȜ@4( {'xES /iX \jjQ=+tVqU*tKUgwoPUAuE qgP 3B8e/%$.اM*tdPv 0)}|`^R?*E X=qX"ipwj>PQ 2qR~-8WʰuR[f=<!"rEgj _.@{%@+EDpV+"^y#Q[N/0,!.]PXmzAP0"rZ: 9+yx"fBDqk ̬?/_Q(ab$mGVl3l!*6T7@wP8:jY¥-(>" 9Y[A/SU_>_(v hƑ!{v;YC-n02vkfem3Z(vWjǑƬ ;@ sM]^9w'#J Ƃ׵84Q+`ڴA󳅗J-WXE7bw?64^h*,, ǨWl(Z32DE>4eaqDm( υ\y,;pրŷI [ي%B+\R3YAQp_U( n/x%`/cD?v~aYZ V0j+6z0v$ހ]8kPB(qrv'gC@V%Q}#7@|QAnG@ /#!  4µ0L4jeIBn\4h`(b_* /D;6`e93D ԇ)BOn;QRTP5\E0\X".(r/ _ۥ٭0][ɢ>z :O8D*+XGŒ72xADQxwti8aW\Y6"@r`AN gC1kkӷlfZ{/EA/upC8<._!.pF_>?3qyl}mfxԓU(ٷ oPlJt_.D+j؃m" C \to(`._)O֝Y):O PTCAqtنp6_d{ s W60dgŬ }%UG Sw0|@! 0`!?[슱oލomBhG(w@,5(~6DS Ʊ+ '|<9YW~G6 0`Q{"(x@[Ū__ Շ"(V++Ȝoω.ҋ;( /K6r@lٱgQd?uQc';rT!Os/gnmree]LPr_N||̀0Vi~b>F8ۃY8l ouVr}_8Bi}jErw⁊D=e)>. P,WdTyଢ8@D~$Pbk(<B.<\m)[" 2@9@ԘgaDF%~;0cAHa-NFXpnh}Bm/6k B\dL#BJ0h0v, 3&e^ B@fnJ.!\쁨 y{[5<0۶PSrvi /9/2509X R89}!=Lyڠ9ZJ}L&@׾|&g5U jFY]= >{}V!B\ѶmCaJ\bvB16"jyyT /hk?Du0!W_ڶVH f60glxz/A$Ff(ٍ,^`^EuYCj@k̅ѰWLZrhFl+(J}d!b%W }ix#gvbZM e97(9ߥ-Vy…L^@5ED("QA 8JVmJLįdbz;M)WT:&$QcQVR~@i6^@lg7`cV]/0c :V?EջC?vIS1 PLePEJ>eYB:2C(Juv} \}yEc/}h@>/DdH}x|OC*ut mxӉ{gwWc =+B+žt ueJ"JQ>)a&T(Β(R{70>*aJ$+>݇`-8IѵIc^+4(9u]alӊCݡIˊ:ujlr 5ՕTL#Q} We! Sx_@w/P d%@N+Tj4ԫGk06C5< Zhy *36D4Q =V½8 YRNzG/,EYA7`eWf +`}Ug&Jyb(mp i9T7؃n`@ AecRrc46v`ܞp0޺y :ۭi̭߳׃ m("Q4`_p[j"(^@S8+bTm5Wt:CNDQ=б[6M-AN]Q^xN_qLT+ mL40(@P'M.}dQ$J! t o9gFa?c X8j7"sRӐ,bUod@@HÊ4n(PUyo\B(ZŴO@<{ ,( pz_.EPh)>C(>\BlB0_p3E@2gS Qx죾f `^R?*E X=q0|Z}fL_ei(' չAtI (҈qe!8/@>[W\(~o(~(`ݖ(jEY^+o$*veb| `%E˺*Cp6 ^T`9P@T֜| ep!*tQTD A z1ʶ#yT  R(@)6T yGG 0[t%V-!?r'Q+KSSUx_ r>/wz~L4 F!{v;YUP^S7#(m֊DxR>$4fD6`b{s%$^9w'#JƂ׵84Q+`ڴA󳅗J-WXE7bw?6IJTTaaY`(>F"`Cњd!*) ۞#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`_Q ږ~bDYp{+{#  Zw(AaԘq׀c(5'q\B񍓳8?Jܶ*:Ⳏ ru7 ruL!GH3}p- 0>wY0PDCM$i@>+J*Uu|UeR}uSLײ<\`NP''g k(/*0  / <( .2?fk 79YGD_}G(rAEsEkPIE1q,ݠ(dO "ʺ_efLjEEqAEwGYʬg|AgۥQ{E*聨JGk(|A13 ![ [&erp 9As5yh9Ƌ 2xE?ݚ rrOuz@Y BBB@4Ko{I.x3Jȱ֮d)y J1t>!] z_~ Ҹo1ipum7 =ůu- >]DH>S"Crh!? (Z hgEig[Y\`h=|ۃDj( `AמW_.((y{5ǜz*Km!o?ec}3e`F>Bl[6^mgņrD>(ˡs"pDC} {LN\] +@t=Pp9~HCT~Pc NQwo^Q|x]y"fNu` @ Mjq=Ot}]^!OU!O|@Tz 8L -}a]͠8>~RE0Y=J)ǯBMfgcϠw6' PB0ϔ-Xk3rK ipmh g@r'Ͻ9C`#&@0m_Qe(5}9UEKXs_..r@=Ei٦ AM\] Piruw/4?.Qcꀽ T Bkq޲'G;(v `FP'kIȘ&ɘFc`>\є0,Vd, j!a5$LX//-2XA> DB?H!a `5\0۶ PSҚ_szV|25<0}M/T$uvup}#AQs;f 1Gu+?{z]0PnW(7SR16w'JQB )RϦfmZ>%Did֋r(9r,SɵpVⳆԮ*֘ a*X$VQ(μP䊹R 0b³{;1DGq6_."Z,V,P /.(\[( 2zQeԘBjm8/(}* z|}@AZd_7 ~%!hJ{@P AԘAԇl} C6ll_תef ;Dzۚbg.)B`*8?*CRHTTBg,KH_fEiήz+BPqEc 1Rj0.S DE?i5vj)3,逈B)wØSɓ\QcaJ{F17(g|AtgX@J' cEnW3:۴"Pwh BOVg]~_.(x{T}vL#Q} We!?݋>T>Y #`{1J=ԹMLܚS3Jئ@T(*MiE.V- Em-Zhl+Nj+Օ"QNn+#ɽ/Xɂ),"wbQaӷ< b/x;Fbc;VB ! FJvE^Bj[~=_h#9C(ۂboUFiQ @_p1'0B``fƠ(HTSwh0!m03XA{# -~`~Z@9Lcc5 ߠ4q ֔#fΠ;AɊ4!S/9N V`\Y4P{0 iPLci5( 2bxaHt7P1'=mf8jQ)hy 3D=/pƆ T:4 :}AHaA=/hEۭGB:'p/N$s@uIJfAs܀\ 1uޣcV(^8i%48{{PUTP]o :N4* Џ PQ3̇[7D|[}٨dՊD+"Q4`S, yW|TͰN+CNDQ=б[6M-AN]Q/b\ 8q &özd otd'7P:ؕQbDғ *m@(~0 i(δk vȜ@4(qz_Ұ" kQsZp @{ cKzwoPUAuE Qc 8wEBQ+3TZ fUT!a hcX6I檠O!hGh9/{AT!/:n|#z\PQ 2qRkA"Pie!8/@>[WԂ89(~o(~(`ݖ(jEY^+o$*vb|;<`%E˺*Cp^+B9XDN+T5"`%?/@y,\ (>dU2z1CP´^Dq9xC݊m-"DSņu {*\ իKW[Q|Z#'EӅr'Q+KSSU_. MM/(v #M/!Gd )ϛbٶ DkE <_YGFbSo0j1=LC_K ̌x#K {o! MD)70?[xrUt1J-vJcSN²P}zE5.CT mOe2<Ds[[BN&-lg+jl[ R\R3YAQp_U(+{# _Zw(AaԘWtm/9;nD38$`6To`\׀׸Qc"(:/p /G@=/ Bg\`Z&`E~+sZ;mEfP Z(f?V"Jad0Hײ<|3D ԇ)BO.>N%q()B`*"xyI+9RO/[ `F1psiE} @u7pD?/cc- 3r7Dňpxwti8aW\YK~iKyA~񕟌!~VgC1:NӷlfZ{@9BPЋGC,\rE+V`QB!9LsjuU 񢣧XbEfVbS*@&(\Q _>=XO/(rjsK%Ց ӇO?:iurۺ@ZE Or1_o'_)ch@BVt QQ=Y)jPliio0}'|`%+Dy6%4f1T) b*VJ>A ]^ XA|{Nt ؔ^a_@YxY._ptEwQS.E!(pBώ9Ud5 :$r}Ⱦe,b'Qk zZ3io@1>pFQYf=!Dk9 \wS.P*v'(Ht(K1̀M *UQ\{.i=ubi(|B-29i9P%}x-ŌM (Л G 6#* r$EL$[s6[nZT(C0sv@uWuWt)?.KTfcM~@fRDC)N/f"gZvA5-?<]{ IGX}S}_M3F8Њϊ`t[Vo- vAo{B ׻0¢;hr@A۫9ԋ4WI8Ɓo?ec}3e`F>Bl[6^mϊ P7|PC/xy]DCůi}AE~6t E2;r3;pW "Ga4>hPR?$ @C+VHCTԝVhlGw"{[ #^p٣5FaS0cmc GSD6K^!OU!O54a>j\m4s7n o SZ-58> _>J)"'A{}048#uŋBZrQLS-Xͫ8C)Ԯצ T`w_+z;b~UyZC@۷JSU$*_n e1[9pA=9~[LԘ+h8xrj<\" 1rabކrD&V80cAHa-N[ŹR?;(0bG/f %O/_b%QZ@QH>QM9c?`Ŋ⽷?D9$U99J+4/-2XA+D r,mWm_sCS4.-*CQ!_H C>G/H<7wDۃc:V~v:`ݞPo0cm 6vlOyڠ9sfl,\Y-\qo~VS`jݑa-+ ZF ff v.9 ڶ{8L)_> F> tc#QE/T i3*9-g mR(5mz`&}ްD/ȬzQreY|c(B'C !sk̅ȱI@ȇ+P(\17! 䪘=I0%X Q+QM/>) _ȁŖk<EB&4@5ED s_(㽋Td` įdbz;MFpz<cBB5fla%[_!ˊX1y݀Z5\CpDf5A϶]RTpT0n!T}ڽ̬[QZ^0Dx|W,_9z_h[M>+VK\scuEH}x|OC*utiuHìqW}faVž:'eP !DQHT倊Dqt@DڻȧI10P %X~TЯS"ʖ QsӤӤc^+4(9u]alӊCݡIˊ:ujl_(Ԙ{cZBWWPU3Gq g/t@^!!?E*yirޑ0VGhrw%=PԹMLܚS3JئdQU6󊲘-Xcz~^%QZ? ^rVԩp 2^] 2"2<\+kWRF8}kA b)Ɔ̜:b}4%Sƞ}_F9C(ۂi~k04_>HcN8 F`"s ̌AA;QT`h}Cq4?`S=R0 RCZ7'qsoPh4i `MyNP !6DqEsړ*V26(*򡹍LSebDbld_ _.@ *fO P{z! 3|mkX_tZX0RABʼnD|tһyX\ڬ h 1uޣc "QӽCiETHi-UEFXPYj 7p9+Ļ?Wf!±(ȩB\4DZO,$sU'G@:Ô> _O yq.Vx 0V|怊4`Gw0lt^ "x BhE>(е8|MůQZ( -4_>`%E˺*Cp6 ^T`9P@T֜<|"…;bIFQE*3%LH+ێ#Q 0ԭf2)BD?F1v+<:jY¥-(>" 9Yr̩*QAQiP^0<| 읬7;5y3R2۶hH+5HHcV[]Ltj F >WBisw2Ҙ _>0腽ZQӦ &B-WXE7D?64^h*,, ǨWl(Z32DE>`DQ[6 (*sy@$:W/5`/dmVA|hr8bVжCk&ʂ >6x^ Z Y%ň"p x u'0JQBz;J|Wz@B_a*}{pf?.`3JX|T]E]u^I Qfq]x8m|X|-\-U1;L"wm\;#rlg s#/rdxE?ݚ r[F3U.P`j!]!]!{{ ry":X.)~0{h!BJr.R/ k= 0nAb| ,&W" s"@kX_}e[i w@qK F_`u:M/0-+o- vA.G%_  va>%_z*K]`(C@)3"`:rhm1*0~V{/]" Y!8^h[[ؽH&`_>p > +@t P>1 8[E"6`Yd֌"J+ewrv.` @ B4l㷲"Z_a>j\m4Q{]͠8>~R" \ P8P_$4b`f= $sD oU(MXoipmh a@uN{csdk1ZimG*@<>@%dJqZbYdpm^+xEi٦ AMP+>[_> /|ֻ-Wo^/pD1bG/f %/P~ /$c!PR}pES ̲XXG1.`א0O/ȌBM3xi+Du?XO/6ث\0TC,yHCs1a *CQr/H C>G/H<7wDۃuw{B\!V;@9'+H{#[&0c8petwo~VS>CcK*zr/`/lVyƽsA1) _>m-uM@tE;/؈(׍PAm JK̇_3? _> mR(5lz?MYg@1zQ Xgfq\-l5P`O[W5voT|-/D NJ&mĶ"BG(Vr[0bK$³Ôb1ĻVqf^Z{o])iEr6[(\[( 2Y1.4p$_PBUDy]| *h+VK\DyH@)zH`n9̢/Z4{w5.03 zm?P<ίsR 5,?@ vC8|"QA(Rڽ %WԘC(<tw], ((l*ä0X=cEnW3:۴"PwhҲNz>2l|P UTL#Qb]?8a^/@^t`}do/rZn`{1PxBHs=5f!aNYɢ\lH#4mP!Xu_E- wQZ^-XDc1X{uHʈzr,VKӌbpsQQ aӷ27!aph9u(}!D(QɮS(6p~[a? O/k04yƜp;Eb1v"QMݡ(h4"60RQ+RC`1gfߠ4q ֔ #fz M}s80O8j֊ =;B0Zse>@}4pu@1yՠlD4|5&/lNc4椵'yBӀw 򡹍L^ 8*;^#qTz- D;QAƆ(!ҀD}W'2ԩߥ_.` > ~_>0/ۥPɑQKɱ4߀;5( OC@8LvtiΕ2l61|tAxV@]l]M#p(~o(~(`ݖ(jEY^+o$*v^(-/e q5BurDUN{Upv'թo$@mͩX _.0 O'E!L^0#ѽVl3l!*6T7@wP=.¥-(>" 9Yr̩*L/ rN/wz~L4 F]^>z'k FxM`³ڶhH+5HHcV[]Ltj F >WBi+2UIrXB>jEL6So`~RI bZ N²P}zE5.CTCS P1lAFQTBHt<{ _8}k^ۤBlE vK^ZP(fmK?D}Vi,cGPƶ %OsZ¨14^sv\PMGxvm8AeVuN| (q۪ rE!׷&=~!6_p#>X Fz, S( !& 4|%`B>Q~ZKV偈R}uSLײ /|z(!0@ Y>N%EL%XC_UNt__!r/ _ۥ٭0][ɢ>z :O8Dl?|(ޤccDňK V视^se / Х4\oPӶGEx­PxE-5y pӀ_>ᱷuQ qkpFVᥒ>eCm3^̩U!.ċ -6diQ[cVŦTHLQ<="{\to(`._)ch 1Nx(-e)Td%vcކp6_6%"X?`~e3QN}fBU̺y |WPeًRGB~G d! e,XVA{!, -W(-enŝφik)u@ؓ >ň"B8 @p x u'0JQBz;J|Wz@Bz_x(>Ph=8Rf} 3T|]]P,Wdm|½.:}$^IP(P38n.<L>P,ޖs*u$.J_PTy@C4`< xc +֜MX} ++xooDS5/CD %\(!@fR[W^#t 3rml{HؑKAWPDi]imTH>S"Crh!?<("ϺⳢ4|g,>`h=" 5^T gOWߚCxENXActA|ѥ.0oc8[Ff"|6ضmxϊ P7|P3{_,/VC-h^$ /~r:Q(k8@QlcuZ!* @M+4;D}.1GkNz{[0cmc GƦ }͔|<DWSUS /Jo 0U5O`.x`9XZlt)SzG.<\J)"'A{0挼%P^%0%>yU6g6c5Ai`18yÒ~wh># !+L%n*ANU~%,ŜopniP﵂Zsx̕}8x;{Z\xExrgb`oC9 Q $'`#pn؀}v8AؗW3 (?pM1( )> |)afYX,{#@ԘC kH z_m"D wKH} *ȱx_>eOFlۂ̹S]Zr!F(`T$uvup}#AQs;fc:V~C= _uu~ Y O뜓A=C-gYtm=[޽YMպݺ#[u {Ԋ4b 53Ӹb.92Epm۸Ô21JM s#f_7Σ _@ @~g4?+-U3r|%Z(жBJm0԰~6gWD42E^}eyf`^EZ8?g+YCj*֘ apX$VQ(μP䊹R 0b³x;1DGq6_>EXvPL/KW(\[( 2Y1.4p$_PBUD ˲hq4H%E /,Z4:qvrߍ, ~y(\DŽ j J ӄBڡe1ɫc׵ HⳎ^hnΞzۚbg.)B`*8?*CRj@Yb]! EAyQjw`Ƞ[|+L%OrE9R(=`<v[0i@ta|ka`YLc3sQƌ6. S̙/x@3_BzU%0|}pBmy@H#t~BVBe9#ƪay9]I'T.r&&@On)hsSV(*MiE.VWD 2DT(W7U`#WWD9 ޗYV^Pz&Dߣ!7! _>ƞ_>`ԡ|{E(QɮӾ4Bj[]_h#P^{p;l>w]n0j Gsi0Z# Ƙk`f D5uC;b)0m)VОF`kc_)F_@i{)E0fS|y&ހ?|` ?\L,~`MyNP"D*ܠ:"…x`p?TU!-#!±(%.اM*#i%Z>Kh&h ~rU6ޓ#Pcikuwj>PXCɧ!LT&pt߿)lt^ "_Z" tu5/u[8Je{a- irY[cAN+T'y@X1ZAP^T`/ Ņ Y40.U2Up{% #Q 0ԭf2)BD?Ulo Q{cVItak鉬{EQ+KSSU_>_(v hƑ!{v;YC-n02vkCͯ׶ DkE <_YGFbSQc!ϕfxe LU5\0腽ZQӦ -T@h*%DBVaaY`(>F"`Cњd!*['ڲQEQA "ѹ-Xv~{!'o 5FKV6-{)kA0˜X4Q^#J^(Lj}jv~YQcxGu\٩60j+6z0v$ހ]8kPB(qrvr_J\FC8ʢ|5|8hpZn٠!}f>u8aQ󰾁9-c6AࢉD3 (pE XP`ҠUay FvUciZsW%R=V||GISA Ppr>]W``WKv~v+(fn.s3(Q倊>>0#߯ "bD X8;AQي4԰+Bpe귑 4c uHO5?yuH4e3Ԣ#^<?-4`*䇆pxm]B\U ^FH8w3f_߃iHg> T BL/(6B:L/d6`w95s{yc  c<+Ey -A `q'RVHo@MY}|mHGicIe^-hg D9YE QڧW19r(m_I@ey"*G޳A ]^ XA|{Nt ؔ^a_@YxY.bώ>6&mNyހMimn ,0}v̩B&O?`L/P /22Da(Fn|ԧ< ~?`qW||܆z(/((B;Jw\ !TP]/(.H^(K̀/?`5J{X|T[E_=uz_I|H(Px38nu/<|n\P,*7@VŌM(7#1<({.(?m/rd~5g2Vk\w\w-hJS *W/0}h!BJrR/xAH3=0n`#4[DŎ\" F׳~ JZLBl+-3HB!Cp~9G4F_`ZkqⳢ4\`t[,.0Z @힃" 5^T kOw+BP/cNXAWK=`1Q+C@)3"`:rhV(>+6C= A1~vf(׌o&*~=*BpRzg@N\] +@t=Pp9~HCT~Pc NQwo^Q|us٣5FaSݽ1BcS>fJL;<5J jBB/p/0x[<0,rAE#A!>-5p6} T+\`_p%@/H# 6`c@2'mN2(a)*ZαW_e#p`S:VD\n`&P=\sol~Lx@6pȯ2 JܾU"Qq%wKX,9/pn9k೵(-]r+h ] Piruw/4?ֿ=[!( YDazZ.ܰ?{>pD6nŎeBd](?LB5%GiE!GW4=}, 3X/m"D qW5 *ho2! #+rlۚ_.sCM/LW4Kky@}X5\P(}^Fyo޷/uC= _uu~ Y O뜓A=C-kYtm][{k𳚪u[rT׵}g{AH#<77.<s d_.mS_Pj`nDr׍_@ @SKg `CD5\ mR(lz/`&3_HFf(׫,Zk\ l%>kHz_.b0 @MڈmE>\B[J+*f !<;CԊ|g/ݷ4\@3|^rm(\zf(CRh#ht~Aq Ue7 @TuAN8JVL|WN}\ͷdpz(.36m4!DvheEYxH^Gsso8{{ 6 :{GJ!+rZc Ʈ*@Jo'L4+)<,ʆ4BSE-Xc!}QZ? ^T* r_] '[Ȋ=-B\H^P68E|f 27!a c4\m3/(%*y-1 S~*6(wŔ^bbC3i hX$6c1(h0* b9n^+1Ab q" DqՀR3{Af$ z_@ M/LM/2ADSLrҠ"#J\C\ Y'd9 W60?xe꽭02 c-=uȘ;E?+!fT ;bp&qd=;x蝬7;5e! kf"QԬ# #YAnu1ѩ75vb\ `WF|@0T%]cZ_^{ UX0m OɿK% +Qj;PHTbY*n0o^hcДmOe2<Ds[[BN&-lg+jl[>/fX4Q^#J^(Ljk%`6Q̓Z¨14^sv\PMGxvm8Ae|A %@i uTCӼ5 {_2#!  4µ0L4j70e #&\4h`|%`B>Q~Z O/DȮ { 0 \sW%R=8w4? k(O/UO/`:|_`"g@Q]e~v+(fn.s3(Q}}#@aF.'_'dcBQ8CnPt" G?KM+io#-t)=/;7(iۣ"Q<@l(F "r͌Rc(G zpӀz_.ۺ(~_.<\?|g*ąxuz_Z5FO/xJLQ,iENEN;E_hsAӽ}V|(>eA۶0i9fiܕ4@18r}#ʭ ,?Y8|@QwVr]/|B#.! = e)>lFi*| HTQ= _P 0CVn\i9~8nu/J?PT@}3Cw¹xն.0{Wӭ9-,/T!Z +!D)]FU>_vQB>4!N~?!(-sx'-Qڻ|-JKŌ;}_`0:2܇'.;.V|VT }vf[ՊZU Q0¢;]%oS[|G={,6#P>7Sf!Duh-P|Vl(zAb |(׌o&*~=*BpXѶ;rgw'^Ea@YB(is ]Y!iƦ֝>.1뿿&0Nu` @ MX)1 FiDWSUS=/a>j\m4sZlt)S薺G/r= xySȏ_'\z} Tyh9j^}MXoipmh `wx_.76g?K X } {ǽVyw!(5;" m۸Ô2(vBz"mkq@>0*MUB= `CD5\ mR(lz/`&3_HFf(ٍ,c(B'Ne6Ak̅ѰWLoxrhFl+(J}d!b%W }i*fD!<;Ck`6_."Z,};LI9 -Vy…Lg=2jL!6 FPQ{Dg> -VB/`_u4\Q. ~y(\DŽ j J 6׊D+C/+b6γZ awt[`aV~[Z Ql%EL'@e3Q=\B@Yb]!"g"@8?xX Z/q*"><`>\!:3~ jt w503 m/(u9) RR`?.fwxFpP+j! BI6V|z=(1L/L`X@q.&8M+u& d}6iBg>P UJ`(+2FE*yirޑ0VGhr PyR&&@On)h%WlSy *Y} i "[hL"J!@8AjE`A|徺2@$ meD=e+Y09WDU _q>;pրS/phfNw_Q1JT>[b!Tll/o p;l9C3i hX$6c1(h0* b9n@}4pu@1yՠŅq@eȇW$:(Ҙ֞ Mvȇ6v3Qz5 4P^0/#M/!Gd )ϛbٶ DkE <_YGFbSo0j1=LT%]cZ_^{ UX0m OɿK% +Qj;PHt/4` c+6|Lv"8lAFQTBHt<{ _8}k^ۤBlE vK^ZP(fmK?D}Vi,cGPˊ2 FpV0j+6z0v$ހ]8kPB(qrvr_Jܶ*:eQVCӼ5 {_2#!  4µ0L4jeIBn\4h`(bz_(lUx Fv_!,O/0~ QB(a Г|GI|;J J\Ecb5P_]e~v+(fn.s3(Q}}#@aF.&* wQxwti8aW\YK~iKyA`AN gC1kkӷlfZ{/EA/upC{[ů*gd^*\6T[<=Ŝ}]BxxbCOWPgxA)ay u&lv/&jz0 P> \ Q+Rg&Nx(-e)Td%vct!%ZЂ+r3ObsP۾*2#DT׌R!?#2CԊT&΂@lD+ƾy7rAk){g|[Y|NO?`Dy=}3@QoVr=/BO}*W(BT*}{pf?.`3JX|T]E]u^I Qfq]x8m|X|-\-U1;q;\PTy@C4`< xӶ>` [s6[rWu@Y\w\w-hJϷ+.3J1&/"O*BP k= 0n`#4[DJA}NZ(~ o?Bl+-3HB!Cp~a}:M/0-+o- כKQI`׻|]Xt={"}c" J^1^J Rzvf"|6ضmx3D=8:(ˡs"pDCůa@E]jgN^) /h]hPzbbuZ!*3Pc M;D}ȑS(CGkNz{[0cmc GƦ }͔|<DWSUS /Jo 0_1x[<0 /e(Zw-G6B|[jlVtK#ދ\`_.p%@cX]{{3b۬wFְ(a rE9VllJj~Hk Dc*L^+'Ͻ9CxX2}s´#D~EipP.VQ !?-`,|;|pKz<֢lXny&- G/.OD[Hc\P5fl Y&VXo@~X87l> QFR>@ʏ\dL#BJ0hw{Y+2 j!a 5$Ln!Dի gugۚ_;J5 *`/ihn\ =xAe? _.b]]a(\EiԜ掙{{󘣺}w>0PnW(o6U1Ī}C{9YDs10c8petwo~VS>CcHoz4"}p/\{&x ( _>mےÔ21ʻwa}8*yԦ*!O `CDi`*(٠VH f6`&3_HyFf(ٍ,c(B'RT\ {D NJ&mĶ"BG(Vr[0bK$³x;1ĻVqf^Z{o])iErtb˵Up!kE? SH@GŹ/TE3_hq4H%E /,Z4:>ASN7uLHƌ >`sHBH;,<$V#D1 mQYmMPk1Dm!0!D[pAU$(3P%C/3XgQZT<9:!+V@ZB:lkE!B?UL-+mL'j[1{W8L,u:뜔`CVD)j{LlfwFpP+j! BI6V|](1#{}}j-9PfO:۴"PwhҲNz>2آorzy]U%0|lXW lBL/}} *yGX5b!+R61zrkNDC(,ߛ*w " @T+"*Yyk: ` +Օ"QN}˯P}EJ_`i%T޹(Q(0[BoCLl^1Wence_/(%*uw}{Y=]r7py?^Ly-&Fk04yƜp;Eb1v"QMݡ(h4by@,l6i RC`11`g ߠ4q ֔#fΠ;AɊ4!SGl->"i~LPQ{0 iPLci5( 2bxaHt7P1'=mf8jQ)_. ߩH4<"u? _@]@Hc lPZve\}6X BʼnD|tһyX\ڬ hr+3{t >֪3n9\PLÜo ̲wY@epܦ! J}VN} *hkNEJ^.rY}gPl}:(Aebi~1xC݊m-"DSņj yGG ~4؃@Dֽ"c;j2x)sj 4o\@No:/܀~a_>g/5#c%g /4Zn Fk8 Xeu| Ek]ȇ,l{"-EQ< +ނeNr6i` >[QcDheRT3YAQp_U( n/x%`/cDs#Jy@+B5] yΎ5go7QjN ص!'g;q1mUuj9ʢ뿙4opM/ jyBg\`Z&`5}$`N|7.H40Ӏ}WUF1i / ["JadNI0 \2`NP''g8w!0` e9W /`:| X|ș_>( .5f):O0<%w%vc$N1O֎:5WZЂ+r3wYbsP`Sb>\XL/DY,m0| Q+BP8 U}ȡ~ j[P&<|QQ=Y)jPliioPP7]4(>ň"(Kq̀ v(mb"c>*UhZ~ ?Pr '0CV߅ -׷erP%=ZŌ}*Q3#_)F8BP;|p.G1^/^Wӭ9-%3ief 1[є.g%3J1M 3DH+P ?TD[DŎ\" =o J'? t˶@1c;D+da0sD ateFCp;b>Ⳣ<`t[Pb~m X Qz7]Xt}t"@A۫9ԋtWIW]J߁f20# !C/6^wa5bC9 "P 8CD5"] .eQګwtvO~pJPF(mE5lbuZ!*Z~Pcۀe![3(S(K̺9A@њө1BcS>Z\ϩ'.Z_.s:m@E#A!>-5p6} T+#  J)>@( f ?{@E!k9(a rE9V&Zlkb5Af1FkpͿzP;b~UZC=@%LT\xbη܅{_>ogkQZi,CPG/H<7wDuw끹w{B!ؽ=ib>x#C-8petj\:#[u p^xqi@vs|`P@>aJ\bJ /̍_0qU6Uygu&0!W40r@R(umz`&3_H2A1zQW%`Y>30"{r-!y5h+d&orhFl+(Jg(VrP]U1{l6V8>/xh-{;lLI9ߥ-Vy…Lk=2jL!6 FPQvDg.h+5v<@i u}\ԾI p1c+)'@i6^V{1ZmN(¬&ٶK Of-{ * 5Pڽ̬[QZ^j,"]4FK[_c2H -U! O"c2><`>\!:eWMDm+5iYwb_q~lf !QQ|_HgIDJ|Jj @$+я E!c4?]4>5IsQƌဪ68ԓl_/jl7l9ĻTL#Qb]?8B=/i ^AJV, c؋y(_/pW  mb֜Pr67Uw " @T+"*YyyF3 |'*2A$ x*߽/X,"MDo)D#5 1{-_#{UF۱rA(}!D(QɮS/PHm10 m |_&@S&xoQ @~_p1'0B``fƠ(HTSwh0!m03XA{# -~`~(iLy;xZY2;nXyB4`/:Y9x%ǩW6vQ =V½8 YRNz?"^Tqv_p%`ưy!Zuf{)10'^WHi/& w+g8 *`R_ 5p0iqIlTsK©*)O=%8ʂ_y?)=/+bkZ }˦(B9T~D= eTiA uE8@0naDpvQϔLC!! snr5t+Ĉ'AT_@{QO3Qi5@ 9U)iHQ7 OuL aEXx7pEE7 Pq[gydbۦ3C@TMj 7p9pg |PZB8e/%$q&~ąC(r±R8aB.3G`DQ[6 (*sy@$:W/5`/dmVA|h`/c-fX4Q%WB9FTS  Zw(AaԘq׀c(5'q\B񍓳8?J\FC8ʢ|3: 0ӨyXJ1Ďd DpDsB0O@a0BLײ<\`NP''g8w!0T[DC/`:|_`"y@Q]e~v+(~Qg} Q}}#@aF.&Dňp^iDHO "ʺ_跑t\c uHO5?yuH4e3Ԣ#^<?-4`*䇮8<._!.:P g⽇SB\= ZW/(0Bf):O PTCAqo;F2T ™+ %"2FH3QN}f.+?[̺y |WPey_&p 25zWȷb*gB ~ "c߼鞥De?GYD_gqA!r#yJ<*BPݓ >ň"A ]^ XA|{Nt ؔ^aaz˒ wa^tJ *HI)Nڎ>Qّ0 0 @Ig> qra(F׶0u >3 4wP|r#ʫYf=xz_>pUP*-T$`?(K1̀?P٧\v b"coSw{tA{%O6(F!qw့ebL>p T D$~rA1coS1>tgc[rE 6#TH4Ƌm|(Wu@Y\w\w-hJn/W]fc~M^ 3DH^Pe > +@t"@Y@6CP :-ә iZw"#^Q|us٣5FaS 1BcS>fJLf>Q+*䩆v-0㭛 4s*jݵ! o SZ-8x/r] xSENH# 3AFT%0%>^-g60z ڴ.1Àv{bN{cs[3^yՊ(^a#D~EipP[%ȩ*/^bpŲM/ l-J6enoZ٢p/|Hlz4?vN=[!yDazZ=>rƳx_l4x J_._>5a?H4B(T(ኦ|e"cxQc EU~ǵznP%M3xi\QAmM/;J5 *`/ihn\ =xAe? _.b]]a(\EiԜ掙{{󘣺}w>0PnW(7SR16g O뜓A=Ch)3/0 Wg w?ZW%Gl֭'9z@H#^33 s|`P| ڶ{8L) _.q؈(׍PAm -f>Jܞ= j`FafmZ"b\-,ZRZk\ l%>kH_>Psa42}.+ۊ|" RYXsC_oa@\[,""tba`J_>@3.]}rm(\f(CRh#ht~Aq Uw 'VBN/`_u}\w#C:&$QcQVRUOm( ɫc׵l/3fmPEջC?vIS1 PLePEj@Yb}@DjM[xE*uLA -U!WDy"ɐRpT&^iNqtt" _03 zm?P<ίsR B5a&; 8Lwo(G5J$+я A17L?]{4_>5IsQƌဪ68 d}6eb b|id>so8{{ 6< r:{GJ!+rZw$Uc/8<|O\)un'L4+)=\TŸy& b.VbyE CD%kQ8/pz=h``A|彺@$ x*߽/X,"ʽV@|Q|/vK[JA b)[ ;F[Fnc۱r@(}!D(QlifKPcb`8</<p F5<\HcN8 F`"s ̌AA;QT`h}Cq`4fShMbq$yu:^@H=mkX _6qRABʼnD|tһyX\ڬ hr+3{t >֪3Es4I2W8@Al-'/{AT!/:nҼIeS󁊯4`Gw0lt^ "_Z" tu5A- /4@v7ůQZ( {Dn9\PLÜo ̲wY@ep 5V:}L/8ҹ5"`%/@{,\ (>dU2z1CP´^DqrQjEL6So`~RI bZǦ" Xeu| Ek]ȇ,l{"-EQeLHt<{ _8}k^ۤBlE vӺ3YAQp_U( n/4s{>Ws#Jy@+B5] yΎo = ص!'g;q1mUu7rg4opM/r>3: 0ӨyXs%s A?DpDsB0Ok9["JadNI0 \2|҅|z(!0@ Y>N%EL%XC_UNt__!r(Ĭͥ}N.)_.?{C97Ԋ@>f):x!-e)TΏh;F2diSseKE-L0(' n뻬l19r/NOpa0\djo($T&΂@lD+ƾy7r# JV,mJ+8iO9 kHP ;$_>Vj<WBlaUJ 2sK P^l [oWb_PAEMOuOvlHBώ9Un ~?*?tͥ ܆]Nm;q7e?{̀0Ӹ+ ib>nC=pF[|ۃ|p3ʷ=_.G])W(BT- *{8Rf}<3 *>{.u(+2v7U.V|@DW8g(|A13 ![ [&erS"Crh!? ("׺ Ukrh- vA.G%_  vat.pE OWԋVIW]J6feD}o,gCmˡQ8CĨ@bPL4TzfTxykإ,*W{vkw'^Ea^e AC+VHCT~Pcۀe![3(S(K̺9A@њөXۘQT|gvAz`.x`^(Q傊Z? o SZ-u8?p_z+ 3b@=cNJ{ND os{M!ؔjHkӾDc>U,9yϒ^1J-WqiG*@.{[E%P`8-`,|;\]债 ֢tŞD9"`c?/p~{;}Z\ " @9@Ԙgu+dX=E$(Xo@~X,i\QFR.Prׄ R}̇+>`Ŋ⽷?D9$s>;BaBXڡIۡMXA> bD9_~ frj`_>]ZbNÊT傊Dή0s"4js}sL=x<樮c%g] JY EpsC0XozlOyZ眬" 9~wbn]•k?{k𳚪u[rT0i ="}]y 5\m- nZ7v&jy@0FDM/}8eTPG(Vr[w WJއ) Q,(Φ^Zo=)i"gtuA*@Q̢P@)vF#"}₨8JVL|WNeBZ1bTC:&$QcQVRV$Z!xYQW"k^f ;DEջC?vIS1 PLePEj@Yb]Wk^x|]}ml`}W@z_.P_ڇ̇ T=0QGж 0lE iYսn{A8IY6ԳDEq"Q%Q(na*y+j! BI!C`0AqeSD~&40u6hS〪68 !|}Օ TL#Qb]?8a^/@Q|Sv/Pފ_Be9 X5b!ܕ{BHs=5f!\M偨ДAQb}yE CD%kQ8/pz{Se&ZQ1X}ueHp+T{_fX}dIPO(}v!7! cyߧ&((fNʷ|1JT(avD=&&~hbm11 `X4`F,1Ej w@1 FS``S_160RUK)!P0Әw0D3l97(3 ev܂5:A%YFv`kiC^rz5`ckE!ms(E#ĔmlD4|5F "il@Ɯ7Oh>/D>4ԫG% 4̝kV½8 YRNz?"^Tqvz_p%`ưn3(^8D= {PUTP]o :N4*Pmq{ނg8 8V$p|6*y%@ GY+/ѥ+bO4yE>PpTDO*t, B`SaKSWԩpk7a:jE)Be(_t+Ĉ-K Lz_@{QO3Qi5@ 9U)iHQ7 O aEXx7pE}v@NoYn>"D*ܠ:"…8\h@(}e@KB!~،OP /p> lUAV鼟C`S4``^V W392 u)9HZ/ *"P&N*8uڀs(҈42@Њ}Qk pAAV }1_",VE셽Fb_(aηfYB\x-\M/*CTYP@T֜<p!*tQTD A z1?bD< [&E觊 ~M4`VpB|Z#'Ep͊ ȺWd,vG}[/N-NM/P۽ 7`_hh }Wc) YZ֊DxR>$4fD6`b{s%$^(St /kq~i0z]G‚iQ|J ^*i \a@R݁#iЀUXXV7ʷQPf1e|Vme2<D_h-v~{!' MZ*4V-&cӺ3YAQp_mr!+{# f;F٩60j+6\sV !qנ2P|t>NpeLSQ\ߚCP$jzN~!}f>u8aQ.Kw(~ࢉD3 (pE XP`Ɲ2 [_(Ww8%m4p-i_=CJ}B Q,'"<|W<P\Z>f}oұyADQ,ݠ(lE~jXn!8Wn0H]Jz_>c uHO5?yuH4e3Ԣ#~9/^*HCQMYh;F2dicI0ZЂ+r3wYbsP۾*2#DTѻB~G xo0L ]1ͻCAJP&\(e>]۝0VgC䴵GHKxq n{bDX cEMI|G6 0`p Aa1ns~M`~%Ė/b)eeػ0/Kf~VB8I@Q{DJm^D(aSLv˱c{笈;obP8e0\Ak){g|[Y|NO?`Dy=+ 0 vX/`%+.Dr"PAnQ|"ѷGYʬa>K= MU9Q:=w蟡Qfq]x8m|X|-\-U1Qc4HTDi3^ CwF>1<({.(ˑh=mf~5gt2fp\w\w-h!Zg%C RjJ6b~ qD񂐮a_.~ xo1>ipk+@9i5,/ҺxO4t}4ۧ:E߇8 fO/0{x׺~}krmY׳x PCnLztpE ixENXActA|ѥ.0oc8[Ff"|6ضmxϊ P7|PC.D _,/c-vEj.?!>?pJPhF(E+!IZ!ZE"p:356ԺAԇ9Ĭ~D 0 ;m]X[OiG-LZ_.ZwGL9aZ"4P8kPT>[bYvw^+xEi=oRsE_>]a-Wo^L.*Y論 $}Xgy# hӮ% ~!Fnk~i@QH>QMc/0bEbf8_C"BW;4i;t\1tۀi+Dw/ޖ m _>0熂LWO^j _. 1GC|"Q+ "\1}o~`sTױJY EpsC0Xoz @9'+H{#Rf_`?]{=jG|hlQ/`/i@kfq/\s dD۶q)erbw;/0qU*MUB;ٟf>J\_SSAZ)Ræ^}K>/Ȭz?eђ`^EuYCj*֘pX$VQ(BJz rU}$Bxv}Q,x*.l:|@kp 0%M/ș_x>PlP.dr !Pc ]hH4:8޻@Tx-iXc'RHˢ@S}P AԘAԇlVi6^V{1Z5C`0Aq D&40u6hS〪68 z 56:Օ*F8g lBL/}} *^#Dq4xw%=PR&&@Ob>hKISV{SДAQb}yE CD%@Ժf&Wޫ+D_2,A qrU<_q=x;pրSO/ncO/0sPWQ]Q~PHm?/|LL@SxoQ @_.p1'0B``fƠ(HTSwh0!m03 by@,l6i RC`11`g ߠ4q ֔#fΠ;AɊ4!S/9Nvώ9B؃iLbLA1؈hk xEظ"9iIo4`Y 򡹍L^ 8*ig p D /pƆ*fOP_.`~0 ld;?t=`~eЃ .!.j,܋2x+wp/,EYA7`Wf +Q8D)OR H g8 ؃y#=hV)pT>V! 0L/8FCacy j4`>[7Nvfr|6* pDqӀ=h,a_E!ri+e3 t^鼢9T~D= eTiA u"8@0naDpvQϔLC!  xj@`WFKOd@(~0 iy&3}!2*P1 )"v\F6䩆4H 5Pƕ :n+R踪YL*t˳7A*ܠ:"…8|3r@(}e@KB!e.aa\Hl*#Jp죾fpl" B'wPG[W\rߛ(_) X% ZQr9N/e q5Buw'*T mb(T`/ Ņ Y40.U26e"`?' ' bD< [&E觊 ~M4`VpJG#=H)(XKOd+2fZ!-SSU_>_(v hƑMȩBwZ`dה $FmLV$q$a1+ȭ.&:Cs+!4ȹ;iLU5\0腽ZQӦ -T@h*%D% C1 >& QMYDQ[6 (*sy@$:W/5`/dmVA|h߯fX4Q^#J^(Lj f;FNQc^ѵiЛ츆𷛎(5'q\B񍓳8?Jܶ*:Ⳏ ru8hpZjyBg\`Z&`5}$`N|7.H40T Z(f?mV偈R}uSLײ /|z(!0@ Y>N%EL%XC_UNt__!rj/ERV|Q̮-\dQg} Q}}#@aFB\ (FT?û%HO " f~iKiA0FߠPmD[5DDC[63J-j= բ@i : X {[ů8#O/`_< q!^t<iL|bӶN ŦTH /d`I+r=}\ 0c  c<+Ey&w@w"4UPd%vc$N1O6IJ%"X?`~e3QN}f.+?[̺y |WPe_p 25zWȷbC8 U_>`1W ul|ԏ"0.Ei(w@,5(~6DN[{4O7(ǮƞLY|,F9Yt۔WJ=|2͋#jOR PR[Ū__ Շ"(V++Ȝoω.ҋ;( /K6r@lٱgWGWt~)*yހMiA!*mSLv˙_._>prW^bP8e0\Ak){g|[Y|NO?`Dy=+ 0 vX/`%+.Dr"PAnQ|"Ѻ{pf?.`3JX|T@{5\u^I Qf+-C(W˹@@LF: }/(fm< Fqԇ|cx!P]\Q8#/ztk&` \ef}>rrGє=DSЊ<(!Z""x/h(29 B؃j6H@YMDEװ J? t˶@1c;D+da0&!?<(\ܷ~ЊϊkrmY׳x PC)+`*؅Ewг+BPó!tu"^J Rzvŷ1{-#c}3e`F>Bl[6^mgņrD>(ˡb`E\,/c-v{LN7|}pW "G0Fi,Z!޹h} <`ƦZw"#^Q|us٣5FaS 1BcS>fJLf>Q+*䩆Dwri`TԺk9BRgݧO6.x/r] X:WN!?~rl2(>{;(9YTc5kE &VD\%&pP]0|؜!<,>ZwGL9aZ"r-.@<>@۷JSU$*_n e1܅_{|e2uc7AlQ8zwY>`vrv?ipg1=[!^ ByP --~Q|x_l4x J"Cp2 ׄ R}̇+^`Ŋ⽷?D9$p>p;D xqCpm!}b r,ާpokZZNCJ\0t˂44K _.sV2/ A_Dή0s"4js}sL=yQ]JϾ^{(}g+αbՏ!=LyZ眬" 9~wBK gYta:{??0WkHoz4"}p/\s dD۶q)erbw;`D}Q6UygH3sKBN/͐R(5lz?MYg@1zQ X-)\-l5P`O[W5v /b0 @MڈmE>\B,P䊹0 a WїH"gvbw̦ Sw?YdK#M?:'@Ӻ+϶u)Ėn-ft@uH" "{QA㙯zq4t/Vr1)PZ- N[셴1bT p1aȇlVi6^( {1Z5+V֫z_>>\)i{H`nYm0tYE ,Dnb_q~lQ`co5e07c 0J3](17L?]{4_>X~`PfO:۴MФ'~m_>PP|id>so8{<pi`_hr:#@%9PY;ªыy( /த*@J[' m XJn-ДTZQqSQ=?d^? ^3hlq f_y<r/B209mrU<_Q=x;L̀ _>ƞ_> T|W4D%]LC0_"D{<&v&>Fx1W|[L3Ak@Ɯp F "`91cP`H`0!5MyFfV! 0L/(FCac5p |1V|6*PDqc4|@Ql0_(Ml=*"*F~lN+:V1N=P-%@ԩ*TEp)-h(]6GX6$`OnrP:@(/= %_.@s(q vhuEF vȜvu.ewWDX r@q׽ 7`_G6 /A!ˇwZl02vkfd3l[1Z(vWjǑƬ Y]LtjhPzu+#d1UIrX ZQӦ -Tbh*ڠ%DІC1m6tLv"=e8llQA "ѹ,;̀ŷI [lEUw1XAQp_*MtlbD?vXTX ӊMo n:Ԝ ص8 'g;q}1*:YE)T f8-7lP}f>Fcp,aQ^.K洄!v$!&bPJ'`B>Q~ZAaB@D)l_!,4W%S=8w4? PpArc!2|"Ҁ]*y݊o1ص79YԇL@%?PT, 3/&_'dcBADQ~! wG7(J:# E?~7Њ+ko#-t_.@woPSۣ"Q.il`sAӽ}V|(>c\D"*T(h-%vc %q/.^-h~3b,|f.+?[̺xlTY!D^C<5B `!h~ "Xc_ppdPR2aG(KS=w7ASdPl/ {2Ʊ?LYkVrϢ^@0`p I6T)ĸX5k+!|*Ti%`9%`SjquyeeI]L/{}RpTEWQb'O;RC&&r (|Y~lڧ:C,3@1'?pvcGgbweq7?Pm\@r+{@m>QwVr]/|B#.:B4*[T$z`/PxfT|]=P,Vdn\/΁:$>p$Pbg(<9n^x2X[&|Z] ~MЋy2@3>?p!(q^PQ8"//}_9@+֜E{|!Z **ĸ)Uί\}^R}hCz< 1t>!] z_-?Fiܷ48 |NZ(~=w?FV3HB!83@ !teFO\Yw\|6UkrjV]`- vA׻0¢;@!(轏Њj*K={@,٣n<}Sf Qض mxm6B= A1^ Tk7 Y!8^Zv)5zg@N\] t~Fi,B(bPb:-h*~Pcѝ>@+8 B`&(t]wof6fغBӐkvAz< yJrqӸ9 _/TԺj)B:ħRkΦOdz}L(\'ho2t|6 :+YBM L?PrռD@ML4A%"s2}N!_>#hLk(BW2 NJ\*AN"E?P,|;\]=EiiXny&- G=/p~{;}Z\ " iHYc֭gb?HQ1o@~'`=# 87,i\QbO)P(y@܊v)c|)abYԑX{#@ԘBhQU_.z>\Еj1L%$z. R,\- *mM/̶97r}5|viM/4szV|25<0}M/T$uvP8EiԜ|sGL=x<(q'g] ,|"x9%!A=A1s<@B!5@,\tg:{om~j\:#[ߺZQ8E/|Ԋ4b @b;_.5\mkS_hFhta# ľ.G2*Ȧ*!Oh~{u1jySAM/BJm0Գ齀Y?c@yjHFf(FY<1W [{!ؓ}*ⳂԮ*֘ aX$Fl+(J>hb%W 4[Xt|Y TEZM z-ŖU@GB&33jCjm Fo(ξPQ{Dg> MXƞ (-Q!N؇؈ AԘAJ 6ՊD+B/ue=BĘuz_`DuQmMPk1DK Ob-=\+ 5W(y e e(-Y/p<!87/m?XP\/p/@JC~R[Vh[-L']rk~E+a3 }^P<ίsR ,/;so8{<pi`_h:#@%9PY;ªыy(=/pWR  mbdkNDC( z%`:+r˜jEYZ1Q=?d^? ^T`('`+T/X,mkEZE"`ip|b{1_.6rS-_Ќ:ս>.6{LL|~B(i+-&F F ͠5\4@)BLYh|`# Ѭ1/lNcc4椵'Ud7lPQGml1QMhֺM"ldrAT2 'lr4X&r4X&rAqnX=/[(tNpqQ+d^t@&-|8x?"h6W^Tqvz_P%`ưCYuf{)_*@!K **hO8 A4 :AecRjyh(l`ܞ޺ :]/η{F%=(\WE81`z_.P[m"(hJ|@_}dN+:V1C9Er(B,6U 8-ANUQ/b\ nCuöTzˀB&M.J=52D(/= %~_@s(q v(δ е}!2]`}y0Q(O:@Q6 .ܛ߀b>*Pp5A.4@DEWfXf?@ 3\Es`- |rDP[qqǀyA7b biE"xy\P,< A \FrAt" ql֩m% 0e+Bp /@>[WP|o(~(`eKEi{EYPry8/e qwY@epd q@{PG@l ښS < .DY[N2JW2a!(a#Qܯ Fϣ 0ձͰeR~/"Hm+4 0qG#=c)(䘥'QuHK`=s* QAŝ^:/܀~aDN;g/j)ϛ(m DkE <_YGFdu1ѩ;BCչ@LT%UcZ_ F/B>jEL6So ~RA hfZǦ" ²`(:FM5.CT 'ڲ 2JGi.4D[7BN&-l 5FK+Ӻ1XAQp_*Mtl#:|E76 ZWW PcZѵisv\PMGpgPQ|t>N WQc"tu>__.(Z3@=/(B"}p Fz, S(QE 1 (p Z(b?V"Jad ei83D FO.>N%q()B`*5*0t_X3\QO5 Fv>' @u-**%d**#@aF.{ cDq,+Y*J:# E?~7Њ+7Q6"@t~_>c uj{T$' :V$Zo(9z/KA.' W!?cob3r;3qa/T]!.5ur J9Y+#`?,!Ɇ*EP!rAێU9&bˇMPoV8ߞ]6wXPᲤ.{}RpTEWQb'O;RC&&r2Fhς5Ageub-p0ޔh~fb^YLyb>P?N Dq%O'ز@!;dl}l加#D;oQLP`'P8fT|ۥlP,֋K_&@Q~%'q8Ca1Dsz j`ķ@HvY,GAe?eZC cHrp@ Ҩ9掘`s5CݞP::c}C=LyZ眬"*vV:3V@,\tc:;=Uۺ#[ߺZQ8H:+.5@kf!l_&q)er]/(55_&uL u<TMUB _?Ѷ1`FH!`&Ь/A$k PL#^~v#ҫ;\-lt`ONe6Akl/"Qo+؈mE>TBG P䊹[Fc WK$By; V8~_&"sc,P޵GmPl9[t.drh]0P$8BUD{DgнXBJ)!h}78xz<cBB5&lW=BH+Q1ymu:_1nnҘokkg2(uKDC evme,1(-Y/p<!87/m X+z% @d)_҅: uБXca3 P<ίsR յ"JQ &`/=pPݪ10J{6Ea0Aq kkqضRt\(?ѷC4zx]6:F8gV6-2wF-/P d%@N+Tjb!Aܕ< mbdkNDC(bR @TrS*MiE.V @T+"*m{qz=h`1A|e('`+T/X SX֊( 睛blqU!7!ֱ;F @̩BЌ: :ep{L n\hb +-&F F ͠=4c0Z!cvtE=uP 1ǭh4afyY8lml+*R`4< QL܀L0}BWE `KkcuJ"9X30`/6[HCb/^vЃ .4hQh 厯:ZͲʋj9nS *3p}̪3'1Fi1*T,|!bAh u:k7 !:aۥ=S2/mP'M.J2J(/= %~(wn4<ھӮ4,N(}4PGXx" ]XtźB Mj`nP&…3eP}e !}?lF&D 81Aq CPEh9/{ ;B^t܀#'IS3AW4 Ewli8</4F5AhE͌yYKעou X {[ů 8#_&` 3qa/T]!.@<-6}z1 y-*GC:|_2QEZe; @!س!8 Or1_obZ<'REitTBA;;.w6$$.h?Ѱb,|f.+?[̺xlTYb:"DTѫB~GPHT&΂*ୀ1Q܍g e@QzogqȠ9i)oPP7]ԍ=|/XtVrϢmS_D SאJvHtLcxί įatP$ηDM%AaqWe1 AGUt~OTsu6pt$/UQA{(BTD#`N;dp I'ߚ!\Nm;q7eh~? qW||܆z(//dbo{F/\Pz >j = e)>lo^R sN+{3  h۾>pL.(@Wf$^ŌMQߌؖ\S)Wۺ@AZO,ܳS !U!׽cJH4Row1J1݇&h1DH^P{@*{g6Cm6HN " b6j _r(O-mŌ+>a/LxCQ'!6Ud-t[P*~f_`VDj(^T מU>&BtA۫9TVIW!o?|3e`F>Bl[6^ mꁎ6Jo/.@" Y!8^Zv)5zg@N\] ׽uEN?/3J{eB=G[iFSu[ںAVpA@aMQ̘mQu>f3%!1(킨 yt8(m5oqsſ_.vP`3tOMwB?ݲ\`_P%@:>@ttǞAwuVp*C4%3%@E)V^-e63 wh g@r'ZגֺZsimEJWYC]@[%iW$\h5jEo 7೵(-m-E/abw'EM[|V1wY( noyZJ" 3 Bgu k" q_l{  %=/P~@L BtEr2(F^jy|K+BPqn_9z_h~6>+V5Ey:<kAJC~R[Vh[-L']rk~E+a3 }^P:'ePϒj{ì .bwxFpPݪ10J-aŷ7QAC3i 3i~}5@q̩ cp@Ug 8@ԓl@"(1[Ώ#J>;I (S@Z!؆i1W|{_fX֊(ߵ+07BoCc/x;F_.sP}!4D%Nu~Cj{_h#n2Z2+-&F F ͠=4c0Z!c`H`0!5My?l٬=4 -~`~R`4<  ~? _N;X;7 #, ag`_l:Y8xV {cD!^se>@}hR1KFAYc4^@+iIkOzXɽq",@L^3H z_@ _.F=|˄_.&=|˄_.( FfLvЃ . .j,܋ns@:MZͲʋj9nSV}ޣc1Lt/PZpK4Ĝz0AEF{ ST>V!_?ۼgQOs1bYgZ[|DiWbQf=y0 i?/4PGXx" @ߦ]S[8`UЅ{p]-#B؅T p9/p_>P!:(~Jf81Aq CPEh9/v.K #'ISsAW4 Ewlix_ $4fbS75v@3=׹@LT%UcZ_ F/B>jEL6So ~RA hfZǦ" ²`(:FM5.CT 'ڲ 2JGi.4D[*{ac6i``1Z"X`|_.Q ږ~ҋy@+{a+F b+FTA!Ԙpg@bYMGpgPQ|t>N WQc"tu>__.(Z3{_ 3@u80ӨyXs%s "Bhi@>+UFi=/*4 Q #Ww8%m4z[qgBɇ)\|;Jm' @u(DT1U1GŒ\<& "JLj X8-V4AHCO "z_ pk}bv~_>c uj{T$ rPM;^؄MO#~9/^MP¡ W!?cob3r;{{1b_ qѼzz_^Byz}  (2QEZj#zn/V`sAӽ}V|(>46qluHo@.w6$$@{ k  &gŬPm_I@e@"*HU!?#_($b*gBlDV(FG3PR2EYۿ ŝ"gC#xJAA8vP7d6 >#!rijh۔Wpdc5cR=/ĸX5k+!|*Ti%`9%`SjqueeI] /?p :BP ؔ>ZD" u)s!'2?tw ױĿk:C\uQ?۔g|[Y|NO? Dy=+  !^JW(]\ꁎ w=(Rb} 3T|]yAP,֋K_>pρ.:}$^I\a(ba(9n]x8m|X~[&Z] I^ŌMQwF>@1<%W`w©xixYv[s[nhF!Z@uUuUqooDS:?,}{hC\ 1tЂa_.v "g1\5dIůa9|A'-mŌ+>a/5LxCyQb>zgkEpjV[XsoB va}@!(ڂ~*K;@,6# }7Sf!DUhm1*0zV{/.@" Y!8^Zv)Dc{LN7|}+@0=.@Y| #( 8""6`YZ֌"JT+jf,_!*m] Y[Wc6Sb>^!OBr@S`/_x[<0,ZW-E6C[j t)^-q^r* !?9 "3=2 '֢a9y2rX=ipmKL40a'/Z})j\hExR1q`V0$(̘7 ?] 87,i< QbO)Pr-VeR>PES IJ#cxG1Ѣ0|-F&}nDC{<4+-_]B\QAmM/eZNCJ\0t˂4zn\{X\0}*:\a(s"4js#&ڋu::@KϾ^{(۳ d0|`E-[&0c8pеlOzZutG~?kp^hVy8v]( _>m-uM@TE ;/4:Q Q/lg/< _? _>hZ!6Qj~Y?c@g@1zQٍ,3c :B'Ug]Xc*!@ 9V4 ۊ|" ,Xs0{ 낎4+yUDQ3ĻVqfZ}<`᜛EwŖU@GB&0~3jCjm Fo(ξPQ{ |ЋaB$v@+Y>.o)X* o0또D D>`SHBH+RGYxH^V#D9_תf ;D4fuۚbgm!0!D[z DW$j`/`^"b]Wkk_z^s9Gd|Hˮ[|+MyC}(ڇ̇ =0QEж|[N"V|g"`i]@8IY6԰5n**m; 8Lwo(G0JNԚ. Q 8k U 429[+֕t&Њ|ha_.ʷ#@%k+~ t3aW|{_fXڟfAMDo)D8}3 lqR<73|;F=|@̩BЌ:ջ>x@,BwŔ^- {mQcC3hM/(ҘhX$1g f  w@1)Ә:_ ApW *PZ/@9@LcOfals7(r2 %v܂5Aye Va_lÑ8xՊS/6onΕELJb 晖A1؈0|4kl4"illБƜ7Oh q "= DqeQI; 8w*wP8aCh,_>0M4_2ŹA57!0n>QpjFq !;RNh4 8Խ05\Ja-}̪3p]ǀ=(ʂb_.4Q ktBs'MQ鉞UX B`Sŀ Tu"8ڍ`pviϔLC% Ct4{=+P:HQbDyI޶ݠ P|0 i(δ е}!2]itGYMy4ԑ5зiWXt|'tK?vj(\h]8F߀3Ph\# If?@ 3|81Aq CPEh9ya h= {rdRXo|Z;5JS 2qR@+[u R FKlE 2 tm5Bߛ(_) X@Q^Qf/6rA1 q_.bk,i$D#^(PEBu 9+yx"XbBU@$tE*֋z1+IQ<2PW6ÖI"idž_}4 0qjK OuIQtaDֵ"c;ie̩*L/ ~ ;u_8i@zWcdWA#c4l~5b7~f}Ii D6n0jf{s%$^ѹ(STM/jq~1{ UX0m OɿK%+ Qj;P( ²`(:FM5.CT *FԖMQ:*Hsy@$:Wނeor6i``1Z"X`lKX v1XAQp_*MtlbDyl ֺbD9A!Ԙpg@bYMGpgPQ|t>N WQc"t (@G{@ky@! hs0L4jeIB6.Hi@>+UFi / 0}uSLײ/Ӽ_=CJ>L!hQ,'"?@4\ħ+ ,/"g@GYv~v+(bn\dQ3{E(r@ESE|({oұy t,+Y*J:# E?~7Њ+k)߰ 5@t_1:=*nφbt@+ -ǷlfZ= % qPǀ=|co yn[&L{؋9zWEG~b4Į!PC:L/d _>Бӽ \to(`*_)chc\൚Ҳ!axJΒ@H1jNƒ @ZV b,|f.+?[̺xlTY!D^C<5B `!h~ "Xc_9@mKʄ(TM,?" -S Ʊ+ '|J9YmJ+81Sa 1T)ĸX5k+!U&(VJ++Hoϩ R;( /K`b9 6**:i :tAHBgG vd^r%;mS!NY.:(Wm^3@L,>p x u'JQvX/`%+.Dr@GFrEDe)>*> .޼ (_+26U>pW@DW/$0@10~@ .<L>P,~-\-炮D$~@/bަ(;#ے+BP;@ETDcb{A@+֜E!Z@uUuUqooDS:?,x?p{hC:/ 18hAH0{P /`ܖ`#4[DŎ\" =ůa9|A'GX}S>a/&BCp;>|6UB>webmDp(P `ݡ=T~@A۫9t8\}K;@,Occ }7Sf!DUhk,.llM A1^ ]42D$*~ *Bp{K ۋdv^)_.@av5 (Z?'طN4@3PcۀeiA[3(S(#^Úu 1ۘ47Dz=u3J@z< yMׂ8LWL=|UK!>Zp6} Wt~G.<\JuȏENH# |048#ˌE!rM 3Lh9j}@Mv46@L40a'̩VA~wDh}4 !+] a J\*AN"E?P,|;|p,]L66enoZ٢p/|@ֻ-WoZ4e jXm(@ab" 3 Be?N4g(bwQe@BʏZVCtH)tCMc/ˢF`::l"D һw@sKHtOQAmM/c;RrR/ ݲ!ۥ/4sV2/ A_D.W "o?09u wsw{B ۠ٞԠ9sf_ 0=[{Zo0WkHַn=VN =jE1iClDڸÔ2fJFDľ.G< @S3^]|+rGm[+3J 0glhz̗ }_(Y/QrY\1WS!ؓk|g]Xc*Bf~cEȇ*P(y XsCR 0b@Bx;f-`6_>E, ιYDș_x>Pl9[t.dr :C:vF@ht Ue7 @Tx^ ݋<\_>@i9\uvrߍ,P AԘzVh㥎c׵jyNl ИokZ!]RTpTn]hS XbQZ^DY(hE*λhRsstAxHˮ[|+My& B?mLT-YQ8::# ] 0L}f!u:뜔`CyrG7,逈B)wØQVE)APj +я B-8Ik ^+Oǜ:ݮ0f T[6&T&Zu:|ضRte /(nrw*F8gVFL/ˋ>T>Y Swªыy( /த*@J֜PR6 rWِFhJ۠(Bp*_z~^%Qɽ@8A-zrWWޫ+De+#ޗY"ʽV@|EQ-ao< X^M/h6b5?ʷ/tfdUԩ:1 065Jk/foUF(1 i `B, Ƙ33FD{C;b[єiL ApW *PZ/@9@Lcc;[ ?\LC,~`MyNP<2vfiC^82`c =;B0ʢ}؃iLbLˠlDd>5F "illБƜ7Oh q "= DqeQٰ3hp wP8aCh,_>0M4_2se_.!0n>Q =V½8&L>gZJq:#.~E, l+05\Ja=:`D)OR 10' +@!K **7 ؃n`@ Ǡ2 )5\e9@1 -xc|n>=Ng["Q)@Qlr4U|ETfXhE *;iJOB<Ŧ%@ԩ*TEp@naD{EҞ)FWM2 ؓ\ReQ^zD%K=\{QOm4Dqe 9]L;1P@# u7r# EW(Vqgmә![w&5 7PDBs13PP}e !}?lF&D 3|81Aq CPEh9/]gO\8A,7`>b㝚T|) OC@8LRt֩kAMБF e /D^y]m8o&JWVDPW Fn9\PLCo IJ 2W8Ae8:i PA[s*VpD …;bIFT&3%b$#y:LOQm!Bp1Wj\S;qR>]X ,=uX쎪CZn:s* ŝ^:/܀~a4| g/Z FxMyތlFmk &Z+nJ80Ҙ$믋Nm`s\JH1 ^\23gKU-/zo! MD)7?[xĠrUA3J-vJcSNVaaYm0o&`CњAd!*[qDm4Ds-Xv{!'o ي% vˆ`-ŬDY(ah%`/lň>5;A!Ԙpg@bYMGpgPQ|tuuN|2PCh5hř_PhEH34\`, 0i CH BM$ 4|ÕN*j}V偈RU!`PkYiޯ!J%4zrq(i~|GISA5/*L'>]W` 9:ʂK/[ Fv>' @u(D**#@aF.{-\7(#ʏ3`X{# E?~7Њ+ko#-t_.@woPSۣ"QYϑ ۾*"DT|m!&V2q,VAbw#Y*AԶ]G(KS=w7ASdPl[{O7>hG'|J9YmJ+81ദ5cR /q۱j<WBl0 UJ sK˒ػ_?pTEWQ)@G!([{>QH,?Y_>pٞ~_& 2;(G_G-gg?34g\@U%{e1Xy,8!T [T$>(Kq̀ vAZoS偳~ u8%(Px1Dswob2yh9t%h&z& zq^/3mLЌ>3b4"[GTNH4K+K/|`Z|ܵ(Gu3~Wk\W\w:"hJUg%1J1}MbR:Zù`eݣ "- " b6j _rx(@[JyW$Z! }_N :2|O3H&`_8~p]z"a^e(Z?'طN4 ,K ޚQDjEUͬ"fkNm *PҬ +1)1 Z]!ONe0Cu3@39 XZlS觽[wyAg2* !?9 "3.3s Д0הS&ZlJj~Hk Dc^8ybo!̜j0wn"4L@B[%iW$\h5jEo |ogkQZ4![ jgQ_tey@=7[" 1R1q`Vz&V@d!zq5zsR@/~3xڸ/6>(?&dL#JO`>TєabYwY!E3Φ$f>]_@W^ BEছwh|u ~bD)z_6ٶ5<0_ zn2@3ÊT偊D.W Wkv"o~o>Pihvsw{B ۠ٞԠ9sf3@,\tl.Zo0WkHZ(^{jE1iCl+ۅ"mmCaJ\(f뉌l[}wDYzW:Ŧ*!Oh~{uъD 5/`{_&h~%ǻSu>dO7uLHƄ i-JZhVhbd<ۀZuL[EƬ~[Z QISABAe1Q.+}ʲt2CtZk_Tuڶj^Ϲ1z"><`>4- D  uБXc]0L}f!6U}֊(E @E8K: PJ0CTUQc a)ZŠoox~@1Dq]k_^+ObO:۴MФ' ._(Ԙ1A-T+tU1Gq g/ l4Bx_@BVBe9HF/8t<]I'T: Г9 mJ]/D%7庯!_S.(XB5&Q f^^uT`Օ "QN>W|{_f X֊( 睛RqfA bu?/pybN U*{QTԩtHm{LlLhb35f042"9;@EsbƠ(]hO`h}Cqk01`YA{#h6[4rB/@9@Lcc;[y`ֿ_P!ML+>~6%+X30`/6[HCb5F "illБƜ ֺ_|41QMŀv= Ax_;QA(ܖ8XA4,zy`hrVd]m+Xr@]/[(tNpqQ+damɵ`&nZl2"h6W^Tqv_P%`ưCYuf{)_*@!K **>oU/vꅉ/p *`R_ kq{ނg8Go<ȏ'>p]Vc~ɻA~EQlr*"*F~lN+:k+ O Xy?MBKSUԩ1k7 !:aۥ=S2/mP>&T%FQ۶2Fa?De;[j"sT.eivޓP2A# u*@ m95 *H|'tK?vj(\h &g]ֹ@iGX;(~Jy81[\䈠 90屏[_;B^t܀#'IS@W4 ldDӋt9@W@^D}&x/S_) sZ4{WH-i2X~uT G6 ^T`9P| *hkNEJ^2X}gPl}:(ĠviJH+mG( ݋5~m!Bёfu5.]m D)" % ,=ꐖzTTx bp&qd!=;xNP FxMyތlFmk &Z+)WjǑƬ Y]Ltjh:WBisw2Ҙ`,xU[G‚iQ|J ^*1h!hF@l*"i`*,, m VrbC6!*[qDm>/Ds-Xv{!'o ي% viqEm(8(a#:|E76 ZW^B14^9;`(#JI܀]?!N@w b(qe:&" (K\h5h债_&PhEH34\`, 0:wY0P !&bPJ'`B>Q~Z [_&(;6`- iޯ!J%4zrq(i~8w!0TJeL'>]W`eCcS]C" *HU!?#_($b*gBlD*ƾx7rU,|@r/hz+\t'>p:B4*T$`?(KQ }lzFi{*s N+|` e ? h~x[&(ߖsAWfw?`ot$N#? vQ}gãe)\H4K?mbڢv41b(hCD /T4***ĸ)U?x<(!!{9DCu/ k= 0nkw&4[Dj=ۍ WPDi~VZ Pλ YCrh!?<("u;>p=W|:M/-+ŷm+Ϫ⁈B va}@!(cN/(!o?Bz .|6ض m=LPI5ix)x?whgP/c-v^]v `_>p > t"@Y| #( 8""p:3 -7`YZ?Њ⫚Y!4Cz{[0c{Q%s]Q+iW_x fÌn.hsx_>PQ몥f~K8>~+e#j?[ T PѾIiĞgd_wQ(STb5iR`S" M7A8 .`w_>solL`k iZoEJWm F+m_Cn 5"η 7{|McۛV|(5|ƻ,>)j\hExR1q@{JeX=ŒyC5 ݫEj(@(4\@1|kB?H4BtH)tCMc/ˢf8_XN/K M7\i}b R,ާpokHX5 *`/i.-!F(`T$uvPZEiԜ|sGLtFS6NyeE0$1ʏ!A&4uG~?k{Ԋ4b 53Ӹb.)2EpmmCaJ\rA3ʻwA/pU*HywF{ $V|%ZN(@mk`FafmZ "b\/%`Yzu=ɵpVⳂԮU1FCِW+lPE %Y4@+_oa컒\5;.h?0N/"XvPL/KW(: 2Y!PcRh#`H4:CqރtE3_lCVr_.7ƞ_> T|BHhFJVE]qC8ls7(r2 {obXST2 *;AdEW+N ؽvώzhi>`@8:<2(fxaHtt1'=b%ü "= D5UʆA4< " /bqTB /mBq^vЃ . .j,܋ns@@ 4?h4+/ ;L /0cXy!Ǭ:3QӽCi VYkc*c|9a XP<1L}BJM/`~_PƮy j0㭛DvbsMH<Aeok@ /@S_PWDO4iEӊ>PIpTz'`,6U 8-ANUQz/b|(p &+ mL4:$`PAGC7 ((1$J~on(wn46`YL]7"sFwvmLjBy4ԑ.]7Pq3Js?ݛ .ܠ:@M qgP}e !}?lF&D 3|81[\ud@}ڗ MjFvi?pz4߀XW|) OC@8LRt֩kAMБF y_"" tu5A- -4|Kb"U% ,^7mvb|;\ %ąe]!k/XdZAqH ښS 5\ .DY[N2JW2a!(a#Qܯ1Gϣ 0ձͰeR~Զ!OTǎ:@Yz"뿟J쎪CZn:s* ŝ^:/܀~a4| g/j)ϛ(m DkE <_YGFdu1ѩ;b\ WFHc傱U-/zo! MD)7?[xĠrUA3J-vJcSNVaaYm0o&`CњAd!*Sڞ#j&(<Ε`o셜,MZ*g+jV6-L(bmK?D}14Q^0h3{>W f#qWjL+6yΎ+ Rs7` *C4/ n*:U+!׷&4oPM/ jy@! hs0L4jeIB6.Hi@>+UFi / 0}uSLײ/Ӽ_=CJ>L!hQ,'"jXC _UN|@r!rts4wbk7n.skD_齁"J9Y>f7%(#J! wG7(J=2Dӽd 6"@t_ɳ}G6 E+ -ǷlfZ= ơH:,\{[ů8#O/`_s*͋ X@yڼ(y#p( 2QEZr`/ȩu`sAӽ}f jWL TZSt`!-[f K#_@xfyW^-h~3b,KwYbsd-|_. RC<5h1DAe,XVFG3PR24s4?;EφȱGHKxq LS|/XtVrϢmS_D:d͋#jOR /q۱j WBl!VV8ʧ6lJ-N/,,i1 AGUt~5irt?R[瓑Q:ώ9jyUH@:C,3@1'?pvn>5~@L,. Qn%_m^(uwX`%r'8O#D;EqAEwEYJg|AgۥQkE*聨JG /(Fy!- er<Е7@1cwSefE}7#@1bR[W:wA(K&PDCůg=@E{]JMj.?=/|~pz(ryf+PȈs}H] H X59fy5Fa{[0c1hG͔|\ ֟QLZU|/p/x[<0 (Q|*j]! o5gݧO{E{"T PO,.{{3=cNJ֢{NoS&Zlgb5@Q }cn>r'Ͻ9CY2]ZתQ g4"D~+@.jdYE%qZ@ͲqpzoPٺ_.-`9"`c?/p~{;}Z\ " @)@Ԙgu+dX=EEf X 6AEjQg8h@Jz_x_.P} 1PR>̇*> EŻ?D)$s>;W1Da_u@踾t͕.!k.vATb>\P_~ frj`_>s9+>Pb_ *:\a(s"4js#&z`ssw{B\!V~ YuɊ wLj!5@,\tg:{om~j]>Cc[w$`}g{.5@a;w!(b SrAVg0*j]ؙF6"j@yTM/lt!$gWW1JQRjM^>%Did֋r|ef`֞AG}QPSa42+؈mE>TBG P䊹[w 끎4+y,UDQ3DGq6_."Xv (rgap?…Lg=@gX.(P}*.. z|}GC߇k._7 J)!h|JVq~y(\DŽ jL a%jEBZ:C!bV=/0c`(Y&Y%EL'@e1Q.ik{/cYWGiήzZs"@Z^r><`>T!*e+"tҶ w50Xھm/{>) zP_`覢8\P(Β(R{7nUԘBt 5F "illБƜ7Oh q"= DOJxQ傦@T+*HK!إ VjQL8u^ $V7Ьz_!0n>QgqQ Dt]G\<@Y\yQ-V4 aLlUf +>k `D)OR H g8AUQA{aʠe)p *`R_(FCac*81`>[7D|@٨H<A`5\PД+b'fZ鴢iEۿ)ǶHNUX-&%@ԩ*TE 8ڍ`pviϔLC et4}{V"t*Ĉғ *mk(wn4<řo3D洫̽>tf}kKm.@# u*@ m9V]7g1 >"D3(\h+3T,ga3_.9} lW>9"(8~8Lycr $ncɑQKbiE"xy\P,< Ae2;H[ 8W`A @W@^D}&xO/ A+E+[(J+^y#f^(!η?@,K 6"`2zx@u 7T`=/ wVߧ!LX/fJHt$bD<C] [&E~;t8:2ƥ-(>ձ#'EӅrY׊:|9U储 N{@nDc0lz 1ˇwZl02vkJ! k[1Z(vWjǑƬ Y]Ltjh:WBi+2UIX ZQӦ ݖrUA3J-vJ~ExUXXVhtT74`Qelecd _D[7BN&-l 5FK+Ӻ1XAQp_*Mtl#:|E76 ZW(k-"PcZѵisv\PMG= ص8 'g;q}12PCoM@!=:Uz_PhEH34\`, 0:wY0P !&bPJ'`B>Q~jV"Jad ei8o(!k,'"jXCi"hyӉOWXhy9eъJM]bk7n.s=<7PD[VMPT, 3rޛtll^7(#j/* wG7(J:# E?~7Њ+1H]7(ԩQ(p3h~6Zhh9e3Ԣ^\/{:,\Wp&=Ŝ}+E󢣦XEyڼƨeT5\@0<* WԂ`V9s{yc  c<@+Ey - d@wPs"4:P2EنP6x +rŬZ\xϪ@"*HU!?#_($bA8 g U1 D 3PR2EYۿ ŝ"gC#xJAA8vP7dc1X"G.5>P,VdllVsDW?p%Qbxer@QD$nЋv@1ccSfE} bt"MS)Ҋ$[s[nZU 2Wk\W\W@4`\R<xh-)u^~%c~ qDQjT0nD- " b6j _rQڱ|@[JyW$Z! }_j^ :?\(uZǯt t*U8VkXs PCz7]Xt@!(倂Ws̩+h>_Qtvؘ:Cj80f Qض{Ϊb͆MO6B= A1^ ]42D$*~M *Bp̵إT;SN^ENO/@iW^\BlYEMExAZ NQco@+jf]}!0{X`vf6fغBӐav@4J /pi.`+uR`3tOMwB?ݲx(\h_$4bϠ; ;(9YM 3M *ZNh(C)צDcN;hk]VD &LӴ:׷JӮH~j%,8! %΄Z6enoZ٢prwYC>[|V1wY>P 5&l Y&V"" 3 Biu aEj(@J_>@1JnEi;JO`>Tє0bYԑX{#@ԘBhQU8K] zBBǕMXA +-_]B\쀨 _*mm_sCS.-@3aTCP( C|#AQs1\ǝw{(۳ d0|`E-[&0c8bJkOYqo~j\:#[VN ="{4!B\r@{8L)_>Ќ2n}aľ.G\ @S3^]|+rGRjMVD42Eg7,sg=ٷ(>+H_b0 +؈mE>TBG P䊹[ƻ4+yv*b\fS9@ba/P&: 2Y!PcRh#`H4:Cq2޻8 *h>e MX_>D)-Q>.o)"P AԘAJ 6ՊD+B/ue=BĘum>th5A.)B`*8?*CRpAH4^3P%XggZڗWdKZ_P@JC~R[Vh[-L'm[=0L}f!u枴O%`T倊Dqt@Dڻȧu S(G:%l17M=M?>X~8Tv1c%B6ns*gsГl4P1ycZߏ(U 429{7P?8Bi>rA#?=ʷ#@%9PY;ªыy(M/pWR @J֜PR6D%7庯! (VE\WD 2DTr/PNo\Dc@c0JvlD9_}EJ_.`i[+kWRqfA bu[6@QJiUF6y {ѽ"*߃JVER[]l06hb35f04|@VD}D1 ČAA;Q"ў(㶿bSf[Wc(lwCPJQʖ(4{r׳ix@,K ˺*Cp#^T@/sVN5"`%O/p!*tQ" A c~9xem-"Dӽ~aAj[qDqtd qjK OuIQtaDֵ"c;i)`NEUa-Њ Rny^0/#B{vᝬٌ2@LV$q$a1+H_ڸ!Εbxeܝ4*jq~1{ UX0m OɿK%+ Qj;PHt/ j|6 :& Q*؞#j&(eLHt<8}3`/dmV >[QcDn90;-ŬDYp{A@+{>WT+;c@uňj<0!ӊMo n:qH-Th_89;݁3!n阈0,rj r"D+B@j: gai<׹˒9m\40Ӏ}W:"S*D/DNI0 \B ZN|;J a %1U0t_,~ȁ:ʢ_ɻ1ص79Yԇ @u-*>`(9TFݘޤccBADmK X{# E?~7Њ+keTO/@wHO4?yuH4߲QjQsH/_΋=\NCB~rE+_`3qa/T9i~Y\D"*T(hg?EنPvC %"2H~#$(' m.+?[̺xlUWo 3D*xk@ Ae,XVط1@mKʄein&h~w ck)u@ؓ >H`%w,6%@0`JQ{"(h9 mǪ__ &(V q='lJE,i bǀ!UUԤ}Q{DJm֞OF"DE0>;RC& O{Iͽ%+rw|v. P ܶ4?{̀Ӹ+ ib>nC=pB[|ۃ|p1ʷ=@#DXu\ SѨ oNpoQ\P݃@Q_P٫?({M.@E1^Z1^ sVӭ9-e4hCDhE!U!U!ƽM׼ ->p/)^PQB>4@!BJr_:uAa/LxCQ|h1Mi@U2@5m AQI`{L+*BP J^1ZJz R}:C:0x3"`*qo0fCiŨZ]@1^ ]42D$*~=*BpRj*W{v|^)~_@g@Q~Noi4^ i҂fQ"[fyFH1P债{[0c1hG͔|\ +iW~_>Tz 8L~h%7*j]! H\tE?ݲ\`_P%@:G"'A{ݱgAFThJ *ZYT}CJm!!ؔjHkS]b1ޖ76g=K XZ"ʽWpAuozEJWm Fĕ4^ ?NKYq=܅{债 r^nysρ޻,ݡz_ipL]J=[!(~,0c $7QXk" q_li# (<@\5$c!P:}:󡊦eQGbQc <ίE|Y4Ct%8>:/-27ݬ#DsKH]X/pok}k`mM/̹ =Kky?jy`_.Hrp@ Ҩ9掘h/{<]~`nW(kc1ʏ!ٞ9YDs129+Lg?p TG|hnE}>p^0K 8i|b)2EpM/DjEi}&[օ_hta# ľ.G2*Ȧ*!Oh~{uъD 5\h1wN0GT1 a5A$z PL#^~v#r,=ɾu@YAjKU1}D~cEȇ*P(Ȣ\17z na=f%.PE5Ck`6_.a>kp0% /P /fŖU@GB&33jCjm Fo(ξPQ{Dg>ЋaB$ƞ (-Q>+ o0또D D>`SHBH+RGYxH^V#D9_ײ^fi(:V?1C?k !&J!"P{`tb]Wkk_z^s"@q~%[z5WRPT&ږxIZ_ъpv7`i^y_,YR_+XA SZl;<8Lwo(nUԘBt ̝k⢞9(`o+ĻyA,+͡m`2 T 1-}̪3V!0 /PƮmU(qc|n.N׋m'Q{- U(Ny ؃ eo*yR=/PWDO4iE`mAi=P-%@ԩ*TE 8ڍ`p8^TzˀB&MReQ^zD%߷m y 11g82@ vȜwؠi\/0Q(O:\F85`oӮȩ-*½ 8.O~!B Q 8 /EWfX±(a hc,UO b+΁C Su\0/m+ۼgrdRX{8^;5T|) OC@8LRtiΕ-:m12@!8}Qk pnt1b? ?_) 1(m(KzD4] IJ rZ:=Qc^{U-8n$@mͩX z_ O'+BP^0֋^IĈy:LO;6T[@w萧qtdY]KW[Q|nղ"䇯K@Yz"ZU0`+ R̺;u_8/j) ,<_m DkE <_YGFdu1ѩ;b\ WFt@0T%UcZ_ F/B>jEL6So ~v[ZDFV(( NVaaYm0o&`CњAd!*[#j&(eLHt<8}3`/dmV >[QcDn\0;-G%rV}DVvXeWjL+6yΎ+ Rs7` *C4/ P 7tLDBQ5\HT͖{_ @! hs0L4jeIB6.Hi@>+UFmfg [_(;6`4W%S=8w4? P_>_t|_`;DNM/ЊJM]bk7n.s=<7PDo!**#@aF.{ cD%_`EI'u观Zse=/~iKC?/1:=*nφbt@+ -6!wSsH/_΋sSpcUȏ~_.ۺ(~_.<\?|g^̩׻B\4/:4x&n[luFI:\@-mHG=]$!@Ң<1BǮ(#ӎÈ@f\Q _>lv.yV OA97p1 c[ "Pz#d@w"<MPЎ?M1C8jKb/ z u [603d>M}}ו-Gn⪠Wox )Lm @La(gB "/۳TCԶ\L#pET@|-5(6DN{{4w7(ǯƞLwe<"EDp_!G"(XH\Vj<[Bly"(6+ȜoϮ ?-OZPlۅyXҭ7-a++:OT}֑{HQu;rT!'׈2_t/o o t2WsA'o{1_;܀?`1Vir+/0|3d#<!E 5;)W(R Ԧ )*2ݝ Q2cPڡ|ߥS %Vn\hqKU7SGm(|B[@dr@&U17XS9nEP,0\ >hcx!P]xch Wӭ9_nzML!]!]!ۼry":\5x~k@fR[[C)旽#^5݀`D. "bG.@Um#@kz j;ݲP,. Y؛8Ll0S_.#ûwo_!/]XJl±Z︨Լ0(W5^T+Ow+RPfC%oXR/6\%} Rv0ؘ)L=|31:60CIO~(zAb |_w!g4TnTxkKYTevw'^Efh:}uѼ P[?'oyָCZjvt'haj{_Gk|N5l[` @l Mڿ,pJ; ZBBji *r)4 1s_hurgPOiHt)S[ ƍ\WTN!?9 "Ha3h T%t%nPGUB:RSN "M3A8>0s6g OO^qRg"ߢ

-E/`vW}_ȃ1{Y>P-f nO@  ^;v4/kP&`?0T1nYrbI*/倊Lήn0Ts"۳Zg[` KPlOyZg"3FL1M&`9fеlqnVSǖM(kxx^GpP+򈁼@T1)_o=/0 /}؏* Ԯ*!O|Trrѿt&@9†"n8KrA1,zQWo%`]0"{rKk ]3Ul1?D| NJ.ĶxB[F*f )<;ͻ> (Φrba/P Kqk<EB&t@-EL sG|5hآĉҲ ѩ:pE ph1@ԛl} C/+Mj=RĘu_.`~?ӵ7$0w j-("2)u.HLC %o.!ھb]Wkg)8V y -U!( )7XzH`nYmo`:Q`0= m(un) fVj0E!QQT"S%PJmka*y+Zll4/1Lti> tiX@F+ cEn7 :fZp;4c d6ˌ_(jP MyJ`(+\ |߽#@#%PY=ƪHQ _U @Jɭ903 grFzeC b.V[D 2E4rVz LOdU[ƭ+D{ovEF\y`mc["~F}kA b)lr-FryiwQhdW Zq2SZ|yc11*`XȈGsi0F ,1,*2 b9nOy?aSl=Rp RC`1q`{ gߠg80mxlB4`/:Y9ĸ%ǮW~lhݳ#}HE{A8o{f P9 "9`: _` 9`h_xEѽm 1M3"B:;p/N$@:^b]sՋj9nS3\ X0uc V)^8U[D=b=*F4mk`@rAecR _>_8FC5piq>Ixm4%@Tb{ОuW\'HM'⊷J=+:Wt:^_pTDO&t, RҀ%@+F8@0NaLr0gJ桐{ 5n kt+KOhd@3P;N{Z е;SdIU bREjC6f < xj L@U 7,}:3tKuoPU8AuE Qm 8ʅGf)±χG *x1G]d z`:6p<_>C #64`R_&A X=qX"ip{jx( χ 2qrmA"Pc/D Hx)/@? ?o) 娭VE셽FbDbu q.Vo 腱Au6Q թO$@mͩ3  =|\ (~;GTB[E0#Sl?b(G5P̰eR~0o uCW[Q|nRLK@Dѽ`aBZ7/D9Ҡh^ i cFr@r%k Fx)>2m3Z)-5Hc6[]tj F s#!0m[(Gh‚kQ}J n*i |*H-vJSJKE +~(z32EE9DQ[6 Q4ЈrAd:WmevrUhh1z"n)Kx *@X4Q%O-:ŵ f;FpV0Z+6xΎk8 t \L Zox#U  f ]lZQXkQһO&hp̔P7]WXtsR^.,@F an6B 2q,k =`ȱ=K%# FVs/}J-{6 1R h#Vg|KތA ]^ @|{vt )haE Pl4_optE)*ހ:r/U@@)*{G*dB Z_x7[]L\P| ,G=-k<7X>p#(㲗 GyBk9 \wS.PFֳK1݀x?>R){EQ+7.k@%WCZO=tL![ b5L&<-booML=FèhP.p`u@E\Lc1^4nitk&~(Ssv@uWuW6oħk^?x !c]LRjޗPe^ BA5|6cxAY]DE@vؓe{i X]v@7qKM FG ȸxqˡU'9ZPbķs3^PCnLt"}I1zEI@sxKil}v#P02` Do<'= Qr(/7 i5ݢ/H2b`\;t3N^)/@tJBIk@uM,;3!-շ!@зfDI.Gk|N5l[` @l MX)1NiDWSUS/ D{p' 1s_hurgPϾKMMwB?Պn`LDJJ) 'A6)lR $sf QLW_nzT5PH-#?t ڴ.1Ӂ3</RVs<#Um`>BۧJPRUd:K`p u1[9V8٠֢lXny&- G/,ݡza->+}D6[PBxk!䇵8{:arj}( De %FV!PR}pŧ0bEbb qd^TUP>Cy{\<ĕV]B]h _m __߶970E_1KMsi1Ē?Pbb A_r@EXgW7*9xD5>cf:<`nsTӆg{B!۲=ib9`s<‹)l8\Y/\qnVS`jݑ__[WT )?SI8yCl+ Ep1m۹Ô2#tc"_0Ur]UB=Zi- G1·-nLsAEl߰D/Ȣz_un^E >uZCj׌r@[8ȱK@;(+P- bn--b#ϻp#s+|)EXqw0%!9`:+@Q5ݢ/P@)vG#q@*N|ld-)ZmlSwG괷}. o07븐Dެ`sȴBH;.$V#E9n_תy8:V?0w j-("2P.HLC %o.!ھb]Wkuz^}]g}j81o^p@JÅ~R[Vh[{6<g5>a{&`m5PίSjzR@ 7`C~ @EOxRJ7sP|dF(|@tWǜ:n0 Tu̴"Pwh9Ajl~<Ph1cZhB[WPU3,Gq g/t@^!!?Eyo(ir0VGhrW|R&&@On)i>sS6((\Qs[lܷ-Lmյ8zީr3 mq)'[|]fWX[y#XG"`vprb [0@@36`ԡ|F{Kcz2P2`h D )o_ @F8G>HEb1vQECPL1ǭfS8 mP+RLo.t RC`1ggߠg80mAlB4`/ !wj {v`ѵBʑb Vb9`h[ xEٸ"9iɱ/րWZD94 L=UbP1@1 bf P9 "9`: _` 9`h_xEѽm 1WNW [>z0E{q"@&/8?"^T qv_>JasSL)OR m`r1p}% T#؃5MӠ2 )// `mq{{8 Xy8V$p6yrLӀ=8ӯ+C FG[\S1+f^鼢6   {kaTiA mq#p؍`ZQ9]3%PH~álŇu<\ (GbDғ ym?ڌT-7|4<3ŞVt>YRu}[W .Q|KQ~%-Gm.b/t`Dbu q.Vo 腱Au6Q թO$@mͩ3  =|\ (~;GTDLA z12#~T u+ [&E{G ݊#R<- @wVȱ(W,VHKzTh u_-^3 {alو_A߳CWd (S;#Gm`fZ+25f{Iyr믋Nmhzs$$n9g'#g#K PZфצ -T@rUtZǧ"2 ؄eu|8 >.LQQMYDQ[6 Q4ЈrAd:WmevrUhh1z"n90;01h{k& >>x^ u%R׸tN|՛6@xD1ryMy8W\Y3˞HXR_>7(i"S\@|m(F "r|5˹ Ӏ_f]TB\ v~i'6Œ}]BAm`9Q 3(~\x6yO`>RԵ>FO(=pDr5"@mڝ"l8Rf{<7 *^{]:=PWU.(rM-{ssL/0buM&|Zb$mPdzw#/0;8CߌC^^2Et=xA?`>rd)y >b~y| BA+wuc7qK=F_# > Xx:/]XJl»Z;{"0t*GT+Ow+RPó)TPj%bUGݰ{v#P02 `fc"uhmaQ@ڻbg/_7iQ&s"[=.eQګw~^ >G 8z(r<2&9~CT~rEo(n5Ģ~oD  v:յm=[Oy,^!OU!O|@TzG 8LG -66TogPϾKMMwB?Պn{#G\ P9P$B%dJHqźnV0^[79~[̔:L-~/~\`vW=/WZ|WA#(3m[BџPBxk!j0Aю~86M~.HB//\d#BJw3.V,m-0/^TG T z_>:nZd ZG qGu ȱx_.mkk`~ۚ_.sC/LW34ͥ5< ^@e?jy`_.CѠ{q%E/PZ=D|\mg#Mvk QoVRVdZ!xYQno1}^<@cGf5A׶_RTpT03n)TiN]m,:>>"gq"q~n^uC}yRjo.S LݲB#&t2[-gaVž:;e'`G?$*#b/xRj[XSɓ`O62R(sCwwF1M]4?>=a{ǜ:n0 Tu̴"Pwh9Ajl~_ -6@-4߭+*G8g{ź=p͢ ^BG|}hdo/JZn`{1Z%PyR&&@On)i>sS6((yE]Zl1S=?dh>o :9V ro] 2| ,62k, Ciտ">#5 1ZF h_.0KP@D#%1=jeb`h _7 r F5<L烵 qQ/l DptVG<@ |zQm64 aj/EJa *g "SӽCmkq:7<8{Nh` 6N<*ԈP06=wA =,ǻtUyp~){l=hmsK  G]`U{G~oq[LŨ,yxEN}̡u'"쉞MX)QaKhSWp©F?SX0S.Ꙓy($PCm& @`78@)@4۶^P;N{Z е;SdIU bREjC6Z aEXx7p#P4 VMMb}'t˾)B TAT.4@#BQ#3TZ #}%̈rͱ&\AAl>9sg c3]ƎG`.mWkdj biދE-,<eGw;NpA _"V@ x1]M-p/n[ਭVE셽Fblb|+ ̺v9[)q^T@/47"JZ: h9Ex"/fBU@I>T&Z/f J֋/R8F`[af2)RD?UT7@wP:jY}|VXbH@Dѽ`aBZ70\ 䰎/(ZzpfزьrAnQާl0dkqnh`fZ+25f{Iyr믋Nmhzs$$n9G*_ ^`BoPZфצ 5a /WXE7@t^h&l`|8 >.LQQ*P1lA>hec/5`/dcBxmE킈>\0;01h{sEy_.J^J/QhE żky=QRQx = ص);g;r(`DZ(r"S_iP/r>3q8VaQs,K!v$!. <|%`B>t3erL_G #pJڀyXg|zGB(f \zVRTP7g(g0 / Si3-RSy2ٵK{,f} DƂ}}#@aF.޷#|ý%O "z_H]J/z_>g mW5_ѹu4>e3EͱGz#}I6urC/۬W##'6Œ}]BBy*cl][!PF R!F2SGZ`;vAR.H~ Ǹ})j[8ZPA덐w P4CAӋ2M1C8jKb/ z u [603d>M}}ו- B qUЫ7օE@F an6Bm`ߌ;A(G(`W}lxP?s@+~yř׆io.sۧ_HA vO&x- ># FVs/}J-زiW9+cHQ /ĸU5[*MJ2۳kCOE 2Ò `_>ƿrTGWt~5i&P?Ra띑HQu;rT!'׈2_t/o o t2WsA'o{QO38M(c|\~hʬ,|? aaFP}<E j=u8Eq@E{.et>CK F*hqKU7SGm(|0b5L&<-boױr/(lU.qތ1<(ۂ.ˑi9Ƌ 2xE?ݚ ^]f6?+++xS?x !_#!<.!˷R/{!G kT30n/`#<]DŎ\" >F@ֵǸڦ_r{W0{)8-f #|Vtxwm3Tkk9@M8VkE  ve4pE z9K[]Jcf32G`F>!~[6!~>IP7rPC/xy]L2[)8^ZRzwn9pW "G3a4>hކ(pN~RcB~rDa3fA> xL!JJܠ9V&Zȃk>LcN;/p܆͙ӓWxWшt#EEyrPPT/ź-@+Yi0m1S0g8xrj\~"A9@i3غ>]>E/$GX6@~XͳAю~p rSu`xoGh1>E_P%_b0qG2w9-qu)R/e1Fb%+~2/倊Lήn0Ts"glxz/Ad:\P#^[Xfj1EH\ go%^kH_b0 +ۊr 3obnnT 䪘=6pUXLQ+QM/ʍ>) _A/ZQ5ݢ/P@)vG#a5_ 8F_>_DD|\mg#Mvk QoVRVdZ!xYQno1}^8|"gGYmMPk1E)0)L[pA UdjV(y{u ePZ; EHAyWԴַ` [>i / tiAFޓނm:efؠcC> BOVg/?BᚯЄfY✽^?8B!B ݋>4Y P Uc/摢8<@*: ГO`fBfJ/F@,WT+b.VbE SD#kQ87pz=h`a'z-֕ "SN˷Pn"`#/Gޱ -K?#5 1`9#9@؎<4(H4[bӓR*~y0 m"Ɣ ^cbThC3<`|X$6cY0(hUd;4Zs63æ@{#+-A4a/@9c5/yA/paV&&7:A#w1g/mـC^rz5֊=;RT {Z{Z ih[ xEٸ"9iIo4`ǝ_>4c703TYpT@yȴ 4\1i@1ES+op }:]-,go|m=yUH)i nsir̻nN]Lփ6"S4`S.00_.G 4p[LŨ kt^鼢9TD= >e04 l m6N8(q fE=S2K@P|qN_X+aV_6fm#짱 vo2՞>YRu;ڐMy!+»+ZTpe =)t\,}:3tKuoPU8AuE Qm 8gEs26柭P8^6ᑐ0rͱ&\tmx$}ԇFmh< rMȃpz4E"xPQAe2;+5AaΕ2|^rYt/D Hxtc[bn[ਭVE셽FbD0[Y[cAI+Tw ZBuj^AHښSg@{Y}.Q\WRE *oe J|esDq?f-"ESAo}St<݇'iE vԻ +XKO+ D:_/D9Ҡh^ i cFr@r%k Fxm3Z)-5Hc6[]tj F s#!t^h&l`|8 >.LQQ*?GTq 'ŕ 4\Εg`ݷ셜,>#-|k+Zl[ R>ނ `>b6#8/*MEE 3po-_0070[1 "b^ѵsv\Q㑚xvmc;Ae C %qE)uQu^_㫁G<n/H!~W_/#}r- 0 ,iCH B]$y@>+J&j}1iLf Ȯ {0240 P&4\ro+)R`*(ʌG/tRmPE 񻴢 @/(o1λlـ>&/^׹{HTiP\Z>fgbD X9;AQي<+RpnE._}B?*2n ׆bt+2 -OGjQs^HAA/n6urC3۬WM$B/TBr`O|Œ}]B djo($mb *gB "c<79]زl䖗QQ=/8SԠ9%`nK)}cD cEOI[6 0`p 8ABUٿ&0b7EPlBW69ߞ]~J/ZXԅ%v/ ۀ!]]Ԥ{ @Ѧ{D JmiwF"E#azXRL6\r_t3w ]=Lqra(>r>rJG8_`Vru'0y2.{y|/RԳ^FW(]\E 9@EG]l>~zNi{FU>Ѧ >W@(Bzx&g2r.P%3Z#ł=#Нp 9ʶ9+*rdEwL[s6W1E|倊 1-.k_#!.@fR㾜 C)q^5܀?T#a xw1>yp;r2h_s'@%bvVa /g&3|Vyw|{VVTf]XJl·ZkZ @|=\5^T+OW_>PPj%bUG۰v#P02 `pfc"uhmaꓞP|(x9rQ4TnTxk إ,*W{;88z(r4\ZKoȘf Z!ZE" N϶uWT8F@њaS=,XQBk7%a)TT#Ϝ~fw\ sx_>PHϠ}8>~Row#g \ P9P$^ݡzճ+}D6[(}!Y<‚Z=>r>hqA(<\@1|k¾y@b|S ̺XQX#@CŒ{Q=`j&}NćC\i%d> X/mk:./B nY򀑇b *SQr/C |Z!6~6g%yG(׫.Z05P`O5v/b0 @]ډmE9\ҙ\17T7*rU8Rxvw] (Φ3+SҌw/_+*2[h1.4pd_P@U>Y@ܽ`n _-fzzvheE]I+RĘu?ZG/A{GYmMPk1E)0)L[pAwhTB{KH/3Xg՚z)8- m5|/`{[@z=R{pTf^iMut"o0= zm?PίSjxRrDEq@EK: 0T$WC(l4.& cn4 pi}k `#1N+s:vw 2q&w_6Bk&H*G8g l3B/}h*˹GX5b)#hBHs=5f!\arA4(׷bIr^Qsz~n%Z? ^=TyGoy<r ^weyyW h=]80?\ìMLouFV gЀ dES:~)Ȕ^ vώ,^*ڣ(G) ?f9@0D4r-F "l@ǜ7wh/D94 L=U3\A8ny{FP9 "te!aD$~[_A/hE ۭ#tvp qQ+d^Hg/ o)N'muĺfAs܀F \ X0uc V)^8U[D=b=*^4 ؃5MӠ2 )5\e91 .Ӏw| :vU`_J0[hrLӀ=8R_>0&/lj7yE3lAGeOlB"O * 8[DMn'>v}CfE=S276P|w8Հ|$FT/= ݶho a?m4L]O3ET*!E]Ď6d@jy@ÊC #64`R_&A X=qX"ip{j>PxCP&N.8uҹ-HgmjqQާR݁TDyn0o^Cћe)*_'ڲQ\y _}k^3WAq@X4Q^#J^J/QɃZh1t^h9;(YHIנ2P}ct^N!8Q"(:/p/?׌܈A/8RȑR|>X GV!v$!. <|%`B>FSx0BDz/|zGB(f \_ky9)0 e9G/`:F X}ș_>WTj;FG̮-\d6ܽox$?P\Z>f}yA<wty8W\Y#}7"@҈rFAM kC1:Nӧl#9H/r@m : X ۬Wg/`Om؋%5z਋Z)jP|miio0}`d1ld1ۧ$ނ-}Ure=I,$_>Vj<[L՛"(6+Ȝoώ.?-8ua]%'U$&ݻ\6'RPj;L{3)*{G*dԴ/P!{Dzk )|v P,0\ >hcx!P]xc+֜M/9|W1E|3BBBy >Ks`R<0 9qd)etb8i5=?n^Z(li,MRӅ3>2.8ywmU'9ZPbڬ~k1mD`RU)50S,?HAA/cI@sxKil}v#P02` Do<r/wx9rQ4TnTxkKYTev:;ħ{R9_>E+;Vih 06$֌(WT%ݜ{# R`hMөm,XQBk7%a)h y y"\m?xxl4 %/_/$c!PRjؖrl~ -6l0|ߋ޲S|9!{|< ȱxGhBvث|`Hb ݲ#Msi1Ē?Pbb A_r@E#P> 93qsg6>۳Zg[` KPlOyZg"3FL1M&`9fеQ Vsbjݑ__[셭Ԋs dbzŗz.[ D1c"_0Ur]UB=Zi- G1·RjHMX3 <[zϗ 2_.(E/v#2,>1W }*㵆Ԯ* a8ȱK@;(+P- bn--b#ϻp#Scl/xh-VnLIrE4(~PT.drM )b ]h4:8xdwq@4м櫁G /ć/o6OsSeZh1@ԛlVi6^Vԅ"E9cp+E@cGf5A׶_RTpT03n)TiZ=P%CۗBQ[^jMܾC+RPql/|[M=-VK\"HyrOC*3ut mxӉW6[^޳0kqb_v~Pӓj"PO6&G(50*#! BI- 7((l*ӥc=a{ǜ:n0A݁1~Nz?e/Z |5&uU%0rlXWY4W 3| o*E[KV,^#Eq4x9VI+T>)uN'4+̔_>,>ʆbpmGRo 8e!aX C(H4[bӓǞ}NPZ|}0+ @F8N0R``fGT`h}Sq`| Qgk 䎷:^b]szUf`Xk `kՙRj[3й,@#pUEՈFm hS4̃}BJ!0 Kh(v`ܞNcus@t<8`YԊL+"S4`_pԥ 9/Lmxd:Ɉ`e3t^鼢9TD= >e04 l m6N8}?6T+*zd o8mPf{V"t+eO_! 4|o a?m0<3ŞVt>YRu;ڐMy!+»+اiW=*Pojp<[Hj 'r9"A(}d@KB!||AhmX6I檠w b+t!0)}{9`aA7b biku{jzX0q)zZ7[uڀsfBU@I>T&Z/f J֋^IĈ~T u+ [&E j y[G 0[8t%ŧ)ڀF7ChBZz,[e4nNf]v{4斍x$+lKP>e! }f"SX[jǑl ;@L1>GBy#|d.Xo MD)70_[ #(82 ؄eu|8 >.LQQ*P1lA>h-cDs&Xv~a{!'H _ڊ'B+3ӻyVi.8Gpo-_0070[1N@+R-] mC)icYf4߷JB0ׄf Z^Nm%E L%xC_(NzwoB x[Ln|?<1xG3K>>0#wHǏ `7pL%O "ʚ_zght)/@wЌڴQ)pk 6s^ih9}f>Rcx `HsiU/pxl._!.Ȉr;?4x۰Kj9yluz_Z1F3h n_t@d:V6X30!`]tqzSԊqqt %l4 :Mg{|K-o_&ty%`0d Szua]%'U8;l}6mEM| mOv6px:tT!;L`rt3g ee]LP| o;e_`,8r|j|1>pd#<8> lhG ^7TT4ƋW.+֜M/s: L!]!]!ۼҥ|mt;@?`>rELRj|K~(,دÌG?T7D]DJAOZ~]=[axVn~MRׅw3_ wǻsZZQuz_0؄jķsKVI`wyL8&b7^QR/6]% oqt)}vild"| Bw5bTay=@1^wqxs㛀_-z/w-6Ej]v `_8~pJPF)mE+ַ/[{`EE@jlZ݉ m]wE7=Z#t{GkE*vSb69=^!OU!Ou\ *//o|$y]ˑA!>.5p6} T+-  J) 'A6)lm#;Y_α5"pৼ.VD\n`fЊ1xd'KN۰9S`<@#UzC=@.VQ )?_b]y@3HKve ooZڢp{Y0C}W /Wȃ1{Y(3m[BѯPBx Bc-NNXpnh}xxl4  %/P~/pM1( )> ruˊP0/`\PE ۄr,_hz_6mky` 5<0E_/hKk@,w)Fe!ky"S "\nlf=nc%k^LJ ` ďݖ O^L1M&`sfеZQtMS`jݑ_u `/Ԋ70j@=O]p֐u })u.HxjV(y{u eP>"]5>LVyǽjzeHyrOC*3ut mxӉW6[;1iYwb_P}_`RJ`(ٿ+ۋ2G/{ݽFJV, c؋y(/*{R41zrkNLC(LehdQQ6v(\P=?dhd-PNwLL#|Lr ^we[PrDK`vprb [-F/4c/%3RWERѦ}hԶ^&6&>/4/Ĩ\b f /8N0R``fGT`h}Sq`|<by@|6_(G j3)>sSgoߠoy/) [X &Av`kyC^[Z@gG ]k,{G_ PSrb9`h[ xEٸ"9iIo TE{ifjQI?/pTd_&@ ӀF LЈtԈr _( !A-[G =LobŁ{bj V<٣~E >W60u JasSL)OkEtg*4`/AXЦiPXz_\ nsirܻnN'1R{|.0/q Mo1l+:W=Qm@Ћ>e04 l m#Lc7a:jE`vQϔ[X (%=8Հ|$FT/= m/m#?ٹi.Vt->"ET*!E]ĎS/yX \>M[+ 2g>0B TAT.4@/Gf)±χG*=J.cۧM*#؊} sam<0m/+t܀#'y/˽恊|(' `:͖l :_&Z7t5O o#J[ਭVE^_-_y2Y}/L^{*T 3k~w XҊFQ2Y}gP{w"֋bdGVLORGy[G 0[8t%ŧ)R.c-=Qt(XXG,*/D9/EKo:E]vL^[6_A߳CWd (S;#Gm`fZ+25f{Iyr믋Nmhzs$$n9g'#J^Ƃ׵84m MXpm OɿM%6'*HM]Jt:/4` ~l6yA OeEy.4LʳM}{!'H _ڊ'B+7ӻyVi.8@,)frS fٟB)M6Ÿ5qHml5L!T9;݁DNJ)uQu^_r (2nBg>9ʵ0LYGL{Q}>տ_.cc-Y 8UoL ňrwt3.m~jxn)8W֍r@ߍХt Z<JMv+_'؝ ZNԢ#~97^\p96urC7۬W*7~.?T[obIq!HSG(Oc_&@q #/rE-6X/(Jjnq$`?r1rAxKQ|G *h;;0%?d%b\Is'p6ĺ_%"}&o̔EYn#7!>*ˋ2#E4ѻB~[ )L *`W}lxP?s@+ /8"E g_"=@ZԍW@ucO&x- ># FVs/}J-زiW9+cHQhh޿&0b7EPlBW69ߞ]~Je   HEMwmOvzg$RTk\,||/RԳ^FW(]\E 9@EG]l>~zNi'R]jtA%O6(>(Bzx&g2r.P%3Z#ł=#Нp 9ʶ9si=mf~%o-v㑫:]LBBBy >KcwUH1&/"Ը/Pe\s>@ 7ՈrCX"<]DŶXkx_>K}rP+ۻ:E)8T=wF_#{zw|{VVTf]XJl·ZkZ @|\#PzS,?\~@A۫9ԋ 4VI[]Jo@X03r9]oˡHxQr(}݅)"PkE?Pe.`\;t#8z(r4\vAb"Qz} AֳmwE7=Z#tgۺk3=*4  YNiV_3o<~# S/*Zݵ)RgݧO[mqP'L3B~rDa3fA> xL!Jo7Aŗs{M))Gq4l#,3A8.`w_>s6g O0mHoQe7(q?ХgKKX9/niPﶂZ-E_q/b`V(p@hd.`@HLPA`kGF R>@ʏ\d#BJo3.V,m-0#}&^gBCLA[H>wD93hۚ_tSrR/ ݲ#Msi!bIŊT! _>P) y^GyO?09X wӆg{B\}!V}R@'+6Sh) /0+W? wVsbjݑ__[w5"{< rL\WSB Gjj(/B}؏*y Ԯ*!O|60![B߶VH #5|z?M{@1,zQuђ`Ղi"{r x!k@[̅p)*X%VP(\17T7*rU>o#Sc`6_>EXwwfP/CW(~r L2ZL!> F>PT#!5_hq4H3fķd|\mg#M:.$b7+)\+2m 7ɫHc׵jywt[#¬&K Of-{ *2 5P+ʺth2S(juWkuz^}G0dмHKUH( )f9\!:eձut"Y 0L{q:;\ f"w_>`v| E(\md`Pn)cD.AFaPs.tX0lP1ӊCݡI' ]F <|bk{$G8g~`  l3B/}hdo/JZn`{1Jz\r9MLܚS3J0Sz Y} y"[hL"J)@8zܩ3 mw)'[|]fGX۽eI-7HT]x;րS؂gb4|ffIwQh佷 Lb_.4Q_Y6N+Cfȱ-(a:cnUp6uE݈N8(q fE=S276P|w{V"t+KOhw_.@rGOc83Si5@L%U)yHQ _",}v@IÁoYb9&9k qg-(-? l}>l>WP/9}`$9"(ҹ?iBXAGɑPciދE2@[DYx>`Gw0|6\)i#_Z7t5/mD P|KQ=QՊrA1s_.0bk,(iv[ܠ:(i'Tl`/ wVůw'*RPh)(aZ/F{% #̙p{aˤHTaP[A!Ocf=[DB~qIȱ(W,VHKzTfDyq™_(Zzpfز| }7cWd (S6޷m`fZ+25f{Iyr믋jN F s#!2UI׌rXo MD)70_[ #5u6J*#ЀMXXV7ʷS倯#jF#\hΕg`/ c -FOV6-GLGR%b_LF;6`8e93<B7S~~+^ H7;hŇF 0 #B/Pw_k|d#_k*r@EsEk0zmzfo(F^UVnPt"G?5~7+k٠FZR_.@wЈr7(i"S\@|m(Fk&؝ ZNԢ#~97^\p96urC#8r( ey"]!?-PH2q,kh0FG3P27t7PVyř׆io.u@ؓ ^Lj"܋nx l@Uaʕ9$EPx@[Ū_o ⋠؄.l s=6^/.0aqh.jLh=~"ô;#0w,B&O{IM[Όr%݈o F).3@O~Xk}@|u~,.#0|g|u-Jw\ H!4P/(.`/pԥxnTuJ{X8BIz ޒ[ 0 9{2S:/ߒJ18񂐮|{P/`V_FyT {ypk+@>i<^{Bl/- ȴB&Sp~;#|^rh- V]׫bxJw`*ؕEw)(D*(y{5ǒz*xKn=`V1>0#C/6NLr/wx9rQ4TznTxykإ,*W{;݋rw'^E^a@]B(i} hjyشBcSN׶K,9F@њaS],XQBk7%a)h y ygԶDwty~f V]ˑA!>E!SD?Պn{#G\ P9P$^c~L@rm[#Ԍr5\0熚_.fhKky@,4^5<0G/ A_3b]`\EyԜ䎙{QJ޳^LJYx EpC0Xo(z @'+ȣF5m(=a/%`sfеu}>pϭ j[|ؒ e~}]oܫ`/|Ԋ4Y P #`{1Z%ϩfHs=5f!aVNȢ\l#4P)Xuz~n%Ⱥ|/Vz LOd/>̔po-T./޲$ זx$/E|F}kA b)l#/۱_>wQhdWi@!}\@L̔e|wc11*`X#<`|X$6cY0(hUd;4Zs63æ@{#+-(yLy;x~97(|;gfouFV gЀ dE֣?L7bG{v)VTfL<p(@'P:ؕĈ'A4 aT-7|4<3ŞVt>YRu;ڐMye!+»+ZTpe =)t\, RMj 'r9/p_>PZB8%j)c-=Qt(XXG,*/D~:ڽy/LL^[6_.A߳CWd (S;#Gm`fZ+25f{Iyr믋Nmhzs$$*"eSt/Tm[(Gh‚kQ}J n*i |*HM]JTb]*n0o^Cћe)*ʡ) ۟#jF#\hΕg`ݷ셜,>#-|k+ZL'n\0;01h{k&ꢢ.&q-@ Q;``n`: J|TX-] mbz_(*< Fv!,/0 P'/'ky9)0T{ć"4Ptһ+x </P^)ꂻKEwtm7ٵK{,ڣm&׽L/cc-Y 8UoL0oϏ)۞& V视^se/ nE.t/36mTd+UE9՚^ )H-j= բ@m : X `yny'2N.@?:<'޾ГQG(O 8[?B:y 3uTKZQR`;vAR.H~pY=}_>P+Rg&Lx#U  ]lZQXC 0w03d{Ţ {ߏrx޺r#E4ѻB~[ )L *ୀ1Sg e.z_kqA!r#KAA8~P7d1ldHm<W9+cHQ  Ц4ƪ_o ՛"(6+Ȝoώ.?-#qXl#ۀ!]{ g74KU46EGo ll?FZ{_.^j@0F^7<,.#0|g|u-Jw\ H!4Pv'(.ȴ> ^~NigT6$>p$Q#Qx38nu<|L.(V_dr^2Et=xA?`>r+)BJr_:|{P/`V_FyT {ypk+@>i-Dm=[ewdZ! {)8sLate>r/ZZQuJѵ&Zo CꭒHί{Lt"B%oXR/6[%=oqt) o?e c}2e`F>!~[6^m™"Fkr(}݅)"PEP`\;t/{R9z_@sJ{u HVih .Ʀѝ=m7%^pH٣5>NX1ۣBc"+*qPoտ_.hm%gPϾKMMwB?Պn{#p%@I!׏@ڰupd*SKlkELO\<6K4sz6l~L0mHoQe7^bOvKX9ߎ/ 7Pں_.qbazhc/p~ifjvW=/WZ|WA߽,D6[(}!Y<‚Z[ksC j} ( De & B2E!zGXW|ʻY+ 6sH|v V#BCL!6ﱽ+>Lm>^ X/ж5@/o[3sn)jfĒދL1G/ A_3b]`\EyԜ䎙{QJ޳^LJYx EpC0Xo(z['RϧmV%L zGydыrH\70j@=O]p֐ڵ b{@ @]ډmE9\RoYsCoa@.nHfJeQ{k<EB&s@-EL?{@hq4^\s$N| [Ma>6S[6M:.$b7+)|_Bڡu&y)bqV/`nn|DջS_~ISq P̔ePEn;Mve,VZT:[VǻjzHyrOC*3ut mxӉ\Zop X[:J③SEk*2^Զ'@)乡bpb<>m5@m'1u 4AUL+u&}&wy_b㚯Bݺryd9sW+We!?F݋>4%PYN70VGhrT39MLܚS3J}0+ldQQ6v(\P=?dhd-PN̴Mm{)'[|]fWX۽eIPOva!7!/b4\@3rYRB@|$m{| m?LL|}C#Ɣ^cbThC3Gy r)Hl0\`P#TSwh0)m0>fShM[[|K5R}SjK)!P08w0E=/soPU38/) [X &T7[{bz4w4֊=;RZsewݣ=`@:jP,  byat:7P1'= ʡin`f]3Ќ~O@heT0h@ŢcI3hw!a^m / y@+R`n}>k^(6-餭8yX\l h^& XgmcD{) tn$ yp=AU@u<m=yUHjC?旞*c4 0n]Pp :sF#VdZ- R{|.0?HMxoV}S zWt:t^*~_w"݁6cЧlF-AM]Ѧ7b\ 8q fE=S276P|m`Jv#1zI|mT-7|4<3ŞVt>YRu;ڐMyyX \@բzZXpn~bڻX +@NP`DBs_. 4|T 3B8*J0z_.9}`$9"(ҹ?iy@h{!,H\GKɱ4E"xy\PQAe2; _ 8Wu Nj/B+Rp ^<"#qJ/mD P|KQ=QՊ[H#S[/0.!.ƂVNnh i* *?AN} hkNEF~Q[XZbg%1(.Z`)$E]D z12+IQ܏jnaˤHTaP[A!Ocfu ";E݅r' ҽ%5Uh ut@۽ 0 2l4<\F%k Fxm3Z)-5Hc6[]tj F s#!2UI׈Xo MD)70_[{@rUt񑚺v%t^h&,, ǩWPfqerW퀊eEy.4LʳM[BN -FOV6-_ w#fmO?<"E]pwi-U G̮-\dm3Ee=HT@EsEk0zmzfMbD%_`pEIg+pSwH^}7"@ҋ^}B?*2n ׆bt+2 -OGjQs^\<wԶӀz_.f]TB\/pF_.`_>'6ŒBA}Sc+t n@Q<|6] 0c zEwZ ھ/o)h@7BVt ޑ*CфM^.6-F m,4%"}&o̔EYn#7% K \X/D+䇹 IP&΂@|mDV)FG3BhG਋Z)jP|miioPP7_ԍ=ർ/x(Y!r̽)`˦Dp_!G"(XH6@/D5[*MJ2۳kCOE 2blň0$!]]Ԥϧ@Ѧ{D J)*{G*d_k}Tj@0F^7Y8g|@HQn >}|BSTdzm8Rf{<7 *^{]:=PWl o}@%#qxy)qK buM&|Zb$-bQeG{蛑?rmAs~ #/rd~gE/&\N(SovAuWuW6oħt)_->p)^Pk@fR[[C)旽#^܀/` "{gvdP߂?@ړ/e{i X]v@7qK=F_# > ~?3TF }ķsKVI`C9]Yt] \~K|Gݰ{OccV>'Sfc"uh))bTzrPC.DL_-z/o-Ej]v `{_..ы:SV%E?BlNPSTT/Dwtyx)/Tk9R3(gߥ&ΦOjELzar >Iy`=l9ˋBZsQx RԶG))צ |T;/p܆͙ϓz;b|ޞ# )-󆺀Kn@| u1ZFV0^[Ҳ]cۛ`/_ ^ PjZ/p 2շxA4c>\@ֈ;Œr5\0熚_.fhKky@,XԌ5\P) y^GyO޻/m|o1ŴٞP::cU_e{:dEy1bi29+@~k5U->|lф2fP+򈁼;@T1)k W|9%`tKWa_.0U3hvUyji|Trrf o[+z>glxz/Adz P#^}FY<1W }*㵆Ԯ* a=X%VP(\17! 䪘=I{3%xrba`J_._>p]]Pr\zn(SR#it~AqUȽhw8FVL|#[Ma>6Sa#8 ,<{h=3)\+2m 7ɫHc׵wt okZ)mHLafJݲ R"SQ %o.!ھZ{5q=HAYܾm|`{[@z_.P_ڛ, T=0SGж 0}eY0L{q }uvC=O LHTG *2$xRJ7sPn)c+FYgdY} .?KG  the72zrlBg>*{u傒id>9+֕+2@!?݋>T9@ a{1hr~O<)un'L4fJ?/D%z_eC)EU bT2{!kQ8/pz=h`apaA|徺2@$ 7xCOvEiF1T3(}v[2}0 /Ќ=\`ԡ| PlE^@v|<&@&Jk2Z2+~yy`Xi hX$6c1(h0J);4Zb9nhEm`E Њ*(iLـk{[` _pa_fNS6*[X *T7 pa1zm=z;kE!}QbsO"d>5 xEq4椵'CӀOD>jb׫GeAM/p(D=/pA 桁_>eBM/#5|˄_.V_yV|D 8y8 䎯@ l`~?"(g6Po CyJa-}Ug&Jyb(p*kN^:L ]omkN@BJ /`~_> ay j4`>[7DV}٨msK•b{r,0 'Mi_1~l+:W1ϝG@UK+? J– QVԩpk7a:֊R=S2 o(۠~QD@`+Ĉ'AT aP(~[n43Qi5@ 9-UӨ}LjByZ4\ .}v@NV%ܛ߀X |UPKAu rgWf!*cQ QBrͱ˦*sUPeΦU8%Z>^ǜA\T90VNei(' `uڀseoK?/DZ7" tc[5<%QO8J[+R^b|;<`%XS>5PK`f8V Bu PA[s+yx"fBU{wQJD A z1+IQ܏j 3ÖI"^0![qDu tE@Dֽ"cau2xUT {@ 7`a/-_.A-YC-n02vkCkfZ(+q$a1+ȭ.&:(s+!4ʈF5<0`¶-C+P8ڴAK% -'hmDBaY`(>z >GvB}#j"(< +6vr8 >1Dhe`8bV>(/*M|x%`/,Ljj;5;u٩60j+6/8(YEsoml5P(9;݁;C@rEe[pwrK=/8B# }p- 0 z, S( !# 4|͕J*j} O/DadNI0 \sW%Roz84? @P_>_tһ+ Nxyů9eۥ_gbvͥO6^T&z߃Q}̊>`ڀzf\oQ*F^) wG7%]&CxEΕz_H]o iGEx­A_'DC[635x `Hi)G=/pxl. x {1xi񢣧XEyZeT=\@Pp<|6XO/Tt] {~  O;GV@ihWDyZqtx__FE:2@شq'KKz_hX?`~e3QNg.+?+fGn pz*]̇E@T^ o2ChEC8 g%`+ƾy7ro4uOvzg$B(v02aӖ3<@I\pEu@T8e0Q?3^P;|[Y|Nx u'0J5~(p*B*H>eY}lCiU>pW@D|8(18(8n]x8L> W˹q;\ fU(FqG(@4`28ROكzNT`j!׭V6oDSZ?xԊsQB=4yA!BJm_Ɇ_BQ 5=H"g>rUAO*_QgO@[)3HT! {!8h} atFyO|}Z٢4|Zb,~k1Ѷ"NU<Qz7]Xtz>`E WsO|孒.8T 46&f"| Bl[6.6އ"F_f4(P"pDC8"X].rWl܃~Pr:LCi,B(zbQ+VH @m A_9[Ŭ~oD 0 ;]ٶ.`@>::z:J@ԺBBr@Q_>a:`.x`^Qn-G6CZq2DZ-mq^r9 "l`%P^5N(adE9V&ZlqHk DcT; / 3I{{0m_)e(iPz{[E%n bηh_V>EiGc97V|V_>]a[NZH1wY.D6[!JX ?\!pnc9H+е@ʏ\A 8+ToTÊ|eqE\?q ƞ&^Bu"`];r_ r,ާж5\Z!/TFMsbNKr |@VW 9xD\1}o~`ns ,|"Xl!~ YdS}2D9~w;Y8tqtwo~jCcHoz4<"{4 pL,@W=nX&/:a|~TPUya? `_k`*UR(gz?MY=_Hy@L#.~v#R*ƜL{ *B'R[$֘ѰWLorL<ЇVÊ(JeQb%+憾4 Y٣/DίvZMxZ,{;LI(rޥ-ק* 2YX!PcR[<#ht"{QA㙯jq4T-Vr_.7P!Xu_z~^%Qɵ@8g400 ^]y EіvoY@ ({v[BoCeq, 2 ̜:RQSTHmؿ 0y%h}uNL55`hGsi0Z# Ƙk`f RDk wb)0ӘG,VОQxa ZQ"3)>q@hgfev\49uJV qΠ; Ɋ4!]GOsG6vݳ#^k,{ H{Zi=b>`h(/l *Ҙ֞Mvܞu"5 DՀ _. Q$ _@ HJ: _@d>fmk/qofxZvEAgZ! ⤊2x+Pe^Tqv /X 1Gc:3QӽCiSY}SCi/&PT7 ؃5PPiL}L! 0L/8F`mq{ނ{8 |3r|6*P"Q4`_>( LbU/4+b*FdL+:Wt:c;)݁" V~F-ANS1> 8q &Z+ KL4*$ql <nr5tQbD,K! jo 694D]o3DTJL*RcD#-*4*j'Z`_>0Ow`F1+hCk&ʂ >gcD?vY007PSam`ԘWtm^h9;qP#$ހ]؎k Q(sv'w DYG9:7Xhe /8B# }p- 0 z, S( !# 4|͕J*j}TKTay 6`e93D ԛ),>Nm%qo+)B`*P4\E0\wW0\Weۥ٭0]!x}+`(rYZ>̻^pSoLP0oϏ!'M&ήHOW\e~iKrC /0ByT$'?Q_[CH4e3hQs._J~J+l4`pxl.8#O/`_obN HEGjO'@q J_.Dæ` /)_.? O;GV@i+<@w@wpq;R"4*СtŦhό g,z jfL0('޳}}n#7c8=."` *譐o($mb*gBPl7FG3P۲BGYy?;E φ -] u+ '|#\!r̽>S_M~*X8\C:UD XH6@n8>Fo!̯"J 2۳Kuye1.K6b9  Hъo羿|T?RaBض-9Jg *C f1|m;e(~;<ƷxLjQJ~8p31P:+YPEG"DE",2~@OPb"c>F*4@ԩ;@K܃QA q[߅ >b3Quf ãe[htk&`m(Gu2~Wk\B[!ۼMiU~6:]]P+ r+2C  U1t.={0nD[DŴ@-Di4\}JČ;Ua/g&9Nw7Sfc"`:q9q݅-6C= A1~,3wo&* !8^Zlv)zg@Nw[)>4l;@ԺBBrAQ}_0}_.0x[<0 (QߟZ#B|V- "i+4\tVB~:)12T|6lmdN8Ye*V-Xh8C) " MAxP pk^c 3m[B \K0cm $p[ &mX(fZPr}kBW9J[!P*ToTÊ6c0⊌:_C" rA}i!htk!+-EhQAm[_m97hy`> /4jӪ2_^DVW 9xD\1|`ns ,|"Xl!~ YdS}2D9~wV%`ƾ@׾Gg/MT[|h*G[O= >{=46@vs|`Pky v0L2@1w;nB1 _0eTPUym ٟV3Ja@mBJm0}Y?c{e1̺([X #ӂiAES5$֘ѰWL0x$ȇQ(zˢJV }irߕdm`EChE>ybᾷ<@\ }r 2YX!PcR[<#ht=;"J8+B>/`{_&(~%c9MoYw7:GH QoVRom\( 7{1k-]/0cnnRջjg\RTpP0n!JhB{,KH/3DEiwz+BPq.n_l/m3>+VU\>/p?/@JB?R[*mL'%s9k~+aZ0K[uľ *Th݅B`koc̊RH{IDJm c>L%ʊsJT.ۅ!1w4?]{OǬf☳ cưAc-u&}\}>r3_h }_]yfqu{ 4B(T݋>T9U,n`{1hO )un'L4fJ_/D%z_eC)EU Q \yyF3  ` +߫+D{_vEJ3XښGu^pߣvprbZh~_0sPBH(FJN]Bjgz`"QZ 6a}bbC3(?/8ҘNr!Hl0\3cP`R$ZSwh0s6My?fR_ A06=oA =}t8nLc~f(\I(vy]/8oy@%0(V|TɲWt:t^*~?wR= e04 l ujE{N8}?[X0Q\:ij@!G2 ؓ(leQ$J޶=P0 ilCL{Z е;CdNK4,Ŏ[m&jY cOA Zz"^BZ70<䰎>/ua/܀0ljy }^>e^S6ZjEhǑƬ ;bZ}0+#>W e2XZz߅|hE G6So`~VxAUtb-vJDXE ^!3m!|ԔQ[6AF υZݷ셜,60>*4*j'6(vy3YArp{A1{a9FT#`/Q jEƼk<0gu@soml5P(9;݁;C@ۧJNFnrer !R|>X f])QfPJ%`B>Q~E}uSLײ<\`NPBO'g8!0peL'X  OA975V|EgVƝ\\"*t(he%vi1:fHGicI\Z53}&_LEYϊY7@TYerp 25z+䇹 A!L ADc߼79@m en"(~w ӧ=@Z9W@ucO&, >'F*+B{}$-Tpt@l:ݦq|6VgJތ. = 2۳Kee]|<Ͼci4P|r#ʫ\,|r̓BYX/`%J|Wz"DnQ|@~Q1@٧\v;vX|3|஢?p.:}$^I(fk@9L> ^;@1;PE Č=(;#!(mq~@Q8ˑhrz/4~5g\̺`\B[!ۼMiU~6:ru0k튠!{9DCU/ 5=H"g1wv 6( n٧ @λ Q,Mrh!?<(Zwjgkk9UVk Zs5>Qz7]Xtz>`E Ws̩+h.8T !͔Eضm\m\cauAg P7|P(w&*dc(BpR.*W{vn=N^EN /8vR+R/BlN4@ NQ϶uW*fݜ{# B`hMQ,kE3b}(4Rc}Li;u<-<倢;|t9\m4sOE[P!>-li+4ދ\`q:+ W!?~r*>62 '},2DQŒ(Zα5"p`S#VD\%&pa'm؜!ΈX =GP6pȯ2 4(qV rZDbpe1!hxۥR+>Eii 0W>"`c/.l9=k" Qc`V8bu~,0cm $p[ &ح wGj}ごP( 5r$d&ɘF )>)ffY\X#@ԘC kH z_/-2n#DqW;. }m[_.RJr-/i4 _.(=x2 |@( C>G/HCsfmuW~hW(7SR16(6v['IMre!KW )q\[;Ff],;fqƜL{ *B'M p|֐_> ,Bf~c⑀ "VDP-+Y17qoa]Pb%͔`EChE>tA½.4|"g9'>eƱ*C*xF#Yk EAVr_.7PR3̇8g lO@93Bӫ-{Q(R%6xLL|Bhb}bbC3(O/8ҘNr!Hl0\3cP`R$ZSwh0s6My?ff9"d>5 xEq4椵'%V27rA䣦(vpTA8*xA$ 2 "p[`Y1 N 2 3\5N7u /Ԋ[(B:; Y'UZ8& _yA,8sՋj9n+3p(Zuf{)60'~QHi/&PT7 ؃5PPiL}L! 0L/8F`mq{ނ{8 |IlT%@JDӀ=h,0cRmWLŨ,ixEN}̡s'EQ=8gaTiA Ԋ:{p(q &kY0 (H&{~"Þ"FT/= ۶= /ma;(k vȜ*@iTEYw{(5%^0Q+Bp ^D}LWhA\cFWD>(m(K b|k^,Ņ 52z؃b?5' =\`.DYw'!L^0#_%"cDq?+ [&E{(n!BQtE vwVȱȺWd,̩*L/ rXGDKo:nD^[6/A߳Ck`dה ,fZ(+q$a1+ȭ.&:(Pz}0+#>W erXZz߅|hE G6So`~Vx߆XE7(FbwoHt^h*^!3 jYڲ2JEy.4D-b/5`/d9yVA|VQcX f]̩!v$!# 4|͕J*j}TKTay #pJڀiZsW%Roz84? @Ppr]Wpr_!rTo_gQ̮]ɢ>f} Q^~?Ǭc-Yܽo#DՏ3`+pS^s mE.U5ɳ!@AnPxE-Ect/$@iM,B~mEbgobN;^ qQh^ޯZkPA7|a uNԂ`5|"zn/0qAmP> ,Њ!+ ޑAQQ.6-F (m,k٠@Zp?`~e3QNg.+?+fGnWPeEQAFo0|@!q2q,JV}nG 3P&<|Qz_NQ!rHKsxA vO&, y5+B{^l45$A/q[j<WBlftUyV9ߞ]6-( /K6b9  HъoQ].:'BPj;L{3!Qޑ02~Y_> ~|2Da|m`>i9?{?`qW|b>nC=pF[,}e3g|B+YPz >j {E{,2@٫p$bwPx3Dqֽk2@,~]^=6@1o@-1cר2@1>ꛑ?(ۂl{@G1^1^ sWӭ9-N_NT`֭h6`Nb[єVg*W/3J1߇&(3DH^P{@=H*H8@Y% 6_QZk1 Ig`0{zd/r^#HQ"t[-NF>rh- vAypB ׻0¢;=Owg~]CWԋVIW]f?f"| Bl[6.6zņrD>(PۍhzǢPxqEo(ؽH&`{_.] +ȩtz@YzCP[?'oiZ m![3(S(U̺9F@њӕmfϘCT|ha t&zOU|/p/0x[<0,o(jZl ogݧOkElq-tUeB~T_$4fP62 '},2DQ¼Pc5kE tVhp,A2}N۰9CdsimGJ)@NC]@۷JR$Z\x]e1=#p~oZ6oDI z WA["D#Vl3 ;b5# 3B`юa~|žlQ(<@\5a?H4BTH(ΕCv4CX6{Cb9x_C"<<EC!VﵽWZ}u bD9m /?ٶ_.s RM/szV|@bM/ AEXg+ " yo޷/:uݞPkm1ԏ!mٞTgLl#&{8prٚz]2[iܧ`/|q/Њ4b 53.<s d`M/DSdM/hj(_.M/}؏2*eD=2 ҖWDU _q>;La!7!Va _.h؎PBH(FJ$0_"D{_Fb>B(Vo>11 `Xi hX$6c1(h0J);4Zb9nh9BLYc!AXcQtvp q@>[Cn;"N'mue^Tqv=/X 1D>֪3mn P"Q4`z_.pr?) /+b>5Wt:t^*~?wR= e04 l ujEnøu٥zd8PAECݗ}>\ (leQ$Jo6-7~`<ŞVtR(1(KV O+Xj`ߦ]>@UA 7,wy@"nP"…8\h@(}e@KB8_.9}`Te z@[Tsrۧ[P;B^t܀#'y/{WpNe2;Nu^ *4bx(m(K{@LÜo ̲ rP 1cOSH ښXɿQ(V|YILP}0^Aebi~e#~T uWLO+ [@wQ.\)]X Zz"^BZ700\䰎/-^ {alrA|%k FxM`czmLT+5~E>$4fD6`zs%$F)G0o!ZQѦ ^*iPh9aݠE݁DBaY D`U "88l,RQA "ѹl,;a{!'H Ⳋ+ؓ[`|_.;0O! Je^Ŝbj^Xvjv^Q jEƼkBqŸ5Q4'v\eB񍝳\!955naGY*:/ z_p(GH3\`Z&` \ SCH BG$i@>+UF1SEd9gF=0 \ڀCL2 %-xBO'g8!0pjh(>=Р2]Wp"g,xA1-U (f.\dQm3(Q|/sje:h87m&bD X8;(48W\AХyݡ0ByT$'?MZ=/~&`օU-PZaS  8-F (m,iKE-L0('޳BQn#7+ x djVs˷61`!(~V H, (j[V(~_.pwAS@l>% v>54(>ω J9!N ]!6`p T`!rAۊUٿ&0b7@B#g)ha_@YxYD`S B8Z-jҽPQ{DJmiwF"" u;rB&O2?t@>Ib eyt(m}Zci (4P>V2{(е>Jr'8O"Dt|ޢ@^(xǀ/P|]t= +2v*| }N+{;(| QL._L&x+DI8nČ](oFcxCl ]x)x^Ol;9|:=PY Bou]ɑh4Uo{I0}h2Cz< U1t>==H" U{LؑKAm(מ|A[J!,~O Y "qFъ|o~g:U2UxWkm <8@D va: 6vU ^S/V[%=_qtv߇*C:0x31mfņꛞl(zAb\^H w,zE{]Ej.?:%q] +ȩtz@Y꽆?jjiZ iY+4;D}\V1GkNW>cPV })1 .ZW =U;\a:|\m4s^}+#B|[jt)Z-[w&+ W!?/rDa3 A[>N@JXr|3ұZKD1:{ 3I X^Z+FN8BWJ wJܾU"ū?-bYZ/˜ ZeeZYQ8*|ړ@_?'Q&O=ӵ_i>vvQc`V;b~,0cm $p-N~.ܰ?{}>Bm/6=r(? &ɘF )>]7ùrHÎffoH|<~! -zC>|{ 4+Dq ڶYm5\0M/Lѧ5ͥ_(>2_^DVW 9xD\1o^09u\ {iC= _::c}C۲=>" ;F 1M&0cpfе{k5UkQe~rO?^^i@kf]y _.=ɚ_(FP4\0 _.0eTPUygV)r|%ZΰhжZ!6Q^MY=_HT Yz+9rY<1^Z?{+YCj@bY {D #}mE>Bt-sR 0=6pzo=P g {F w{S#9Z^,(\dcT@UHm@G s_(a3_PXvy2@+Y0!h}7R@ܽ`n !!3 DYIW=BH;q,$W"^f@]G¬Vh-?"s'2(u.QDC JeYB:}!*Ju \U/"]4Frm[rԺHy|XC*utKWMd.g{-¯xW8L{,m}:;eP$`?(/(^Rj[ØSɫ R(_`8ޑ k{q 4`"(6ޓmt2~jlPiCݡI'W&`Qtvp qp/N ^"N'mue^Tqv=/X 1Gc:3QӽCi8- " gE$Ez#x=h[u=4R4旞*1n[)i|n.NW'Q+).OGY`-/y+b*FcXxEN}lObRc}T6@EVcзlF-ANpڍ`p0TϔLB6hp#Qm"D%ܠ:E q3P 3Dpa3J?@ 3\Esl4\ b90O 'wPG(m(K{@LÜo ̲wY2W8腱Au6S7$V^0 EŠr;+ ⢵f֫!L^0#QܯsQ܏j 3ÖI"iA_}49-\)]X Zz"^BZ70`/N[(H#̔f&ز=;xhKPY2۶V$ kf}Ii r믋Nm!JH3 2rNFS$94m Њ*6mŧRIB (ZLE$:/4` ^!3 jY>Oecd 2&@$:Wme/5`/dipVA|VQc<rQAFo0|@!iCP8 g%ୀ1Q܍tR "e2GYy?;E φ -] ~hSL|/ cE l@Sa9"BƳM`~%VoFXG`%`S6gkԊ]lipz ߢ&ݻ\uOvzg$B(P#`N+dd /Ig>uTea(-8m | =ǀ'08+z@i \0J@fc/f6NPcaeJl7@+W! sbE;,2;Q Ľ;(<;( `(:8&Fi-gRb=?P2cT(FqGcxCl ] x)x^OlwrxV& Bou]ɑh4UsIq0yhr2C˙ b~yaF}ǀ`e[l*gY\dPwrx(y,~o0}GxF׷H`J~_!LFVT³Zcu} Ys PCQ+`*؅EwX@Pj9b} +.UgnAec}3e`F>!CC׷ņrD>(Əeb\X4"˷]ؽH&`ۋS|Pjȩ0JeBG AVhlGw"8V1GkNgqd]+ϘCBcJLf>Ρz|{ az{xE19@Ԙi3غdk!kqwk },i?+Zi=@X `FPeʏ\dL#Jm |Xєg3v,]  a ۄBX2φۗFKH *ȱx_mieٶz_s@Ms 9=+N 1 2"Q}^L%ʊsJT.ۅ!1i wy1kD,8涱F?56t̴EФsГg]>/e3_h I3̇8g lP(GwF^ȩBeqw3c؋yGC/dZ%=2ԹMLܚS3JV) *(*Mi(\n3(AJUG1Dz-NT`apaA|EUp2QN˯Pn"`%_X( ז?"NS}kA bU؂=2-F3 v B*@1JT[b!Jl1 0 m^/hW>11 `X i h[1 1 FS`1>Y= 3[4r^J rpC8lso s2;jgk_3%+YOv~AiC^jƮ{v`#DQG? G) |r10D4|k6DaiIkOzKdo(F`&]RU`~QA06BQp0it8~@~٨msK•0 ( Le|_&0+b*FdL+:WtVs'EQ=8g& l ujEZtp,ڍ`p0TϔLB6h?P:(1zI|޶@}_&@r(?ٹXmي(T{eӨ;nɃQ(OPHi`(P6  J7ge?pA.4e@(*-g f~Ji 9 A8DqۧR8aD؆"A\8A,{8^wjP|( OC@8L!AaΕeu>%^0 @f^D}LW` CK⾘#P {Dݲ׳4ּN,KrP{fsQ 9y"RU|YILP}0^Aebi*!#Q 0w|v/"i'`HV"il5¥-(>ݯc-=uXXG]!-SSUSZ rXG̺EKo:nD^[6 g/_ۆD02vkCn0۶V$ kf}Ii :x5v@1Ĵ~Եi *ӘO6 `BoGC}(>%gJZNXE7(FbwoHt^h* sPi# *bDmX<D Wkvr1OUO" }_;0O!J-0cD``n`ֺcDn4! 2խIv!P(9;݁;C@k(9"Tu>_sVQ,f8->/ b\kp- 0 z, S( !# 4|͕J*j}?=20 F-t2yhГ }pZwg /;F@>DwN Ũ "rj~AH/KiT9ɑSȏ ͺ(B\\/pF_`_x۰sjREG?/+b[T @pL: 'j"zn/0qAmP> ,A}m+A Zo}Ҳ\!aKcvi1:fHGicI\h@ >̯l`&ɢ,@_egŬ J,{ djVȏR?xY?+A[1ͻ{CAԶP&Qz_NQ!rGHKsxA8 n-|NTVr1LI|[6 0`p T`!eƳM`~%VoFXWV9ߞ]6e_G@YxYleI̯_PAoQ].:'BPj;L{3!Qޑ02~~!>/܁R~z2)_y@rm`>Qg1 4w@k >UyW>`F !,BO}*WT(T-(}68">@٧\v;vX|3|஢?p.:}$^I(f⸭w]3|j9Pۍa/D}ԝp zv (mq~@Q8ˑhrz/4~5g嶌f:]PYVu+x)FS_y0{h2C\ U1t8-`HC)4[DU@>P|Di}W8(t>Ubv*dao0#!?<(oP+>[T]XT·ZkZ @힃 ]J8Fzwd}QWs̩+h.8T !ρ!CC?=ņrD>(Əeb\~`k~@e.`rQګwtAp(rzwe8v2&9~Hz},֝>m(U̺9WL0kY߂@{*4:L)>4lJ@ԺBBr@Q_>a:`.x`^Qn-G6C S觭x/r] xJUȏꋜF fAFP(J(Zα5"p`S#VDhp,A2{X]E$(X ?V D;nV~v>QFR>@ʏ\dL#Jm |Xєo3,X, j!a 5$LXN/ۗFKH@Tc>|g{j9 \0tKFY !F\0DVW 9xDݱx]~hW(ζbGߐlOyO&H6G;F 1M&0cpfе޽wZsutG~r/`/q?0ͥ 8i 1D"A +Z xҊZ7,VKs"mw𳎲g@Qh~j& 'eR(ZEspVDbuQ Xw9-T`O[W5}"w1H@b[+P(Ez Ӹ.Ja"!޵ 0N/aXvPL/KW[NA'(5E?P5V!3 F/(}*.>4:EVr_.7>\)7 zH`nж 0lE iYkXb_vNY68IjUT(^Rj[ØSɫq! *RynXln ^6 8|`"s @sDT:f"Pwh9A ._> |-Tǫ+()FCb]?8f^/@Q|Sv/Pފ_Tn`{1hZ%=PR&&@On)h%+̔_.J.ʆ4BS(XB5fQ m[g@-ׇ Xm('W|]fXڽeI-7%EրO/h̜:RQ'%Qbc./8</<'&Fk04r#94-wc503F)E5uC;@ 1mєiLl+r 1 ̲@> {)E0fS| 'ހ?|` _.pa_fNSS'dna50gv~AiC^jƮ{v`k͕E꣟#Ĕ}>f9"d>5 xEq4椵'CӀw QӌL^ 8*yΠ@0|`(9˄#/`PqnȘ jE[- Ѓ'-lPLCgk@mrW餭yA,8sՋj9n+3p(Zuf{)jq:/48{N )*hO8 A4<:Nec )5\e91ni|n>pI B~`=Tж%@JDӀ=h,0cRV|TɲWt:t^*Z 쉞UXshqD4$`ZQVԩߋF?[X0Q\:iX@ ^9gJ=52D^zD%m7-7~`<ŞVtR(1(KV Oky+»Qm9Xpo~b}'t~!D5@A.4BQ+3TZ±(%.cۧP2WsD ~? h56ޓ#P*ҼIeSW4`Gw؋yΕeu "Dx1]M- P6" XIGikEYWH- 4v,KVN=Qc {9 b@T֜DJ^.rY}g ޝdR2z1CP´^D%s&3Jaˤ گUt y[G 0/O)]X Zz"^BZ700| *a_-^ {al| }Wc߯mC";5e! 7mLT+5~E>$4fm0 `JWM]^٠2J_p`,xJ0z]ȇVTb(>%gJZNXE7(FbwoHt^h* sPf} Q>2;~ " l82VήHOSxEΕ_6跑ԶK!7ϣ"Q<֠PxE-Ectpr^0$yr)G /f]_!.pF_>?=a/}h XEyZhy-p( 2QGD-x96X*rjnc$`?cܾb(>A *h;)DUPK:bbt̐ƒ z s W60d{b}P|%UG SB~R?x7N *GDc߼1@m ee)EP,5?"cEN|.q@ؓ >w>i4o-3{D/@SaQ{",$_>bx ̯V@B++ȜoϮ ҋ%v1 p?%54T?Ra띑B9₩-gn7Gz#@e. Fn|\ciܕ4P>VyO`F̃BZX`%jp|B#.*B*H- ^Ȭw gEPb"cרrz QAq[~i\/8|ZDI8nČ](oFUp`yp#/u e(pDT*C0V4r no@4Uv-H%C"yle/ BZA[$O.L8@Y\dP;9@ZL>msB|N+ _`0:2܇'.Nw\Z٢4\`tc-P jbmy|" 5^T P<V_.cNXAo@|ѥn=`1QW>7Sfc"`:q9q-6C=PL4T|c(BpR.*W{v;w'^"wW:VصPސ1 8[EEEtfjlBc֝>m^Q|us٣5Fa۳8?0ThtRc}Li=vAԺBBkNe0C|{0x[<0,r֭fZp6} Vt˺[?+NVB~T_$4fP62 '},2DQ¼Pc5kE |G46KL4;@r'm؜!ΈX =GP6pȯ2 4}9-EW[Ųrp_jQZr+{h 8rNQtxE j̴l YG(T>zQ6@~r=# h@J~_x_.$c!P*ToTÊeqEbQc <߯!`_u@#B k{ugq ڶ= fj` _.OjK5`s<‹!jUf,\;:{om~j\iݑ_hE1i|b92EpAm!0L6{ Zb.y6l[wDY3  @~g4?M |+rCkq*_h`F;{~6g1O$z Yz?eUcN !ؓUg 傹oz@A$z7<9& ` Q(zˢJV }iG_"_!0/xev(9 ĖSy w,z -hH4:Aq/]2y<}Є\!`0 /u w#E 榰1@>ZZ+Ui6.Wj=BĘ1Xz7Nק! z[MBlK f-{ D) 5V(y{e e(-D֊}yE*<>:!+V@ZB: /@/DʐR{OT& mxIY{W ޳0Kװľ|lҊ(;< fEvy_.0; "p R(vFbq̽#D~G`L{b{c΢N+81~NzrlBg>G?{' 42✽^?8B /cyJ9U,n`{1hr~O<)un'L4fJ?/D%z_eC)EU Q \yyF3  ` +Օ"QN˯Pn"`%?/Q -7%E|ր/b4\@3r=!8ڢοNR%6{LL|Bhb}bbC3(/8ҘNr!Hl0\3cP`R$ZSwh0s6My?f{E j}gZ+; Ɋ4!]rz5`coO{`,4P{0 i 1!AXczA ^hnPEQ 9<p!*@l;(sA+R0#_%"cDq?+ [&E~;T:jY݅KW[Q|";Eջ +XKOd>u̩* /D9&SM/{L4셱eS!{v/^S6pٶ D"QMvYGF6Cuj0jbi=+L`WF6Lc?Ó Ƃw94-C+P8ڴE)/K% -׏h;P7p$:/4` C!3m!|Ԕ_b **sy@$jp;a{!' #-Q Xc<>>\0Ow`F1+hCsy_.J^X f;FTAZ¨1c֋ 0guk$ހ]؎k Q(sv'w ODYG9:7Xh!R[={p- 0 z, S( !# 4|͕J*j}TE}uSLײ<|3D ԛ),>Nm%qo+)B`*P4KPI+8B /TozJ`F1v'h @u7pD?/P`-v\1 87m&(Qj>+pSlOJAХjhSt~&a :HO5(~6(^hh9}fFѢ#]\Ty0$nEZ!Sȏz_.f]_!. 8#//x۰sjREGO/:iPAr@&(/ 95sm9.H~ Ǹ}ZQ|  Zw@w0~Hr.TK:bbt̐ƒZЂ+r=wYY1>r(}@_ 25z+@ZY?+A[1ͻ{CAԶP&\(KQ=/gq9}#KnsP7dsb+DgJ+زiO9 kH砊 bV5[]bZ^ XA|{vt ؔ^/,, ۀ!5=~"ô;#B:L9sZ!'kuH;{.F,|1}xF }ǀ/0x+i1.FW\Y/(г^J+.Dr@EB9@w}@~Q1@٧\v;vX|3|஢?p.:}$^Ise~ Q.<k2Xz&\-Rbw?rgTyQugb#[-( g9RR[F/b>ZG:]PY!B[!6A/p$MiU~6:X.)~@(!!{9DCU/ " U.Ei48" }R-Di46 p?B&Cp~87}Z٢4|ZbZZTH4@dީ" 5ջ|]Xtz>`E Ws̩+h. *B߇*C@)31mڸڸꂊʡo?q{q,E]{LN7|'Zj(rjf+Z(KoȘb"35 X2}kF%rŷY7=Z`v=#ZQ 4CBcJLf>ޡD+i)i /tA1,E[P!>-li8?+NVB~ K͠*lUa38 X{!P(JqE9V&ZlqHkӾDcT; / 3Dk1ZG=u o H~*wKXs_>@+`۶*>EiCPB}E_>]Ai rzxEyr j̴l Yw( YDa@HZ=a}sCAϾC6M~:H (?pM1(R}*aES ̲wY.aG3e7$f> 5$LXN/ۗFKH@Tc>|eYm )[ r)0Ҩi.@k27۠6-FmaDVӚ/HCsv:g٥g]Lv+,|"x9%5Clbce{b>`s<‹!fο,\8:{?[S`ִH֯wZ4<"Ƚp/\s d`mp)ebw;Bz"Q_ *!Ol*0QD m2Ff)ƜRj1̺(ٍ,;fqƜL{ *B'R[$֘ѰWLorL<WÊ(JeQb%+憾4- *Rvbw̦eݡ{# ErtT@EB&vQ2jBjg8_P ]w񁨠 +BN/`_(~%ѩ:p"sSX AԘa REi*CW# ܾ3K(Y&:{>uD@d(u.QDC JeYB:}!*Ju \T:[m[Ey:\+CJnJPzP"ъZi5j\a{&`i]׹S 5NRrGDt@D0T򪬨10J幡b]~BsHk#Y &=g1=1]L4Ac-u&}\}>2lЯ@ZBWW>PR3̇8g l4B_.@)C9U,n`{1hZ%=PR&&@On)h%+̔_.J.ʆ4BS" @T+"*DL4 .l5WWD9/B2<<ҖWD1TD({v[BoC<|4cO/0sg W[_Qԩ*Kl6ZŔ^(\Qc fP=4`FUD֪3[=Ng- WR$3O4|Q~1\`t+b*FdL5!*~?wR= y~F-ANS1> 8q &Z+ KL4*$qlz/2J^zD%m7#}~b3694D]o3D@iTEYw{(5 l2WsD ~fhs_\8A0E2ީ+EYxIe:7`uZPTc٠gh"roEt5 _.@ۈ@(`T֊{ah[N/irYG2W8XDNSH ښX _.0 ߻2JR.E z1U"B{B_TLOQ ݊#B<]t%ŧ+,ST@Dֽ"cauto`NMUa@T::7 _{L4셱eS=;xLnkfZ`;_Ѭ# #YAnu1ѩ75v@1Ĵ\ `WF|@0T%}n X0z]ȇVTpi(>%gJZ!(FbwoHt^h* u"`C /*~=/;.ooPQA "Q o 9YipVA|VQc<>>6|`8bV>(/>r!D 3|+{a?``n`ֺcDn4! 9[xv>C Q(sv'w ׸QsD!e|_> f8-7l8B# }pwYs%s A?DxDﳹR XP`ji * /DadNI0 \2`NPBO'gk+OO|pr"_.tһ+ N_.`+D򁊲RV3ٵ 7>YGLs#J9@nj qL7ħ޴DՏ3`s#\pS^s p+;̯scʾ@0W O2"Z /ӷlfu-_΋=\NM,B~mEbgobN;^ qOtUzrբ<-^c4< p<95s{yD nr1n_o`1/s Zo..zGJFE:2@ش3$${^-hg D9YE뻬us>_I|XXL/DmNJT&΂Y "؊oލge2n"(~w ӧ=@Zq@ؓ >ω J9^t)`˦Dp?,!*",$_>bx ̯"J 2۳Kkz( /K6b9  H±KT}lJcȽTEmQPD{GVdcɚ_gn7[ eyt(mk}iܕ4P>VyO`F̃BZX`% '8O"Dt|@@^(=|Wx{(^kT[E_=uz_I|H@ `(ۺ>pM&ůk2r(%(&M&Dnfy<Qߌ(@4`28RWۺA^Ol;9|:=PYVu+x)F Z`F 9e)y b~y| BZA[$Ov'L8@Ylu~v"QZk1 I[X@ Y؛8 l0CQ"?{EiZbDz"̃Dj( `ݡy AA?\ (y{5ǜz*KwAec}3e`F>!CC=PbC9 "2@1.c|0P/o-^]v `{_.] +٫;l!R2 8[EEEtfjl,eZպxEbyv Fkz&FF)ևBcw`yHf> oqsſ_.PԺ! R+ΦO֊n{ ku*2 W!?/rDa3 A[>N@(aQ(Zα5"p`S#VD\%&z6l~'.`#&@AaZ"R4P (}9-EW[Ųrp@|v6G[\@\] w-k-+Ҡ}]Qc R(X ?~RXثGj} (<@\5a?H4BTḢMy7c0⊌9x_C"<vWZ,\(K-LI9 ĖSy  D=HWD]\@-- hL|ůd|6)Hpq~)s j0f%"Qvh{eq~v66 һAt~0ʴ~@_ P5Vߠ[YRH4Z2vBb}@D1DpmK!8uڶXP*^ 8ԇ aVL-ֱ߱ut@Efݻ` Xڭ @) ]!`q_`"`4rPc㙯h ^]fq g/t@^!؆ i1<^ȩBeqw3c؋yG h{BHs=5f!0Sy *(*Mi(\/P=/Qkeo ^["0 r_] >eD=2 ҖWD1TD(}v[BoC<\@rfNw_(QVԩTHm10 m_8R-@sR<Q ͠<o_.~iŗqӔ *[X *T7 OHbV }S *hך+=  H{Zi CDGxxaHt6nPƜ7wh>/D>jb׫G%{Af$ z_@ HM/ul?2!aضƉ_yV|Dz0Ejl LCf/|j`yA,+šqv=/X 1D>֪3`WLŨ,ixEN}̡s'EQ=б[6J– QVԩpk7a:֊xiql <P:(1zI|߶mP(~[n4Ρy&=}!25FU" i=/،kO+xKiQ=oÕzF:o1![pA.4@BQ+3TZ±({ل(!a hmX6U*s6Ad@}/Fmh(\Zg.Vx HZ/ +.EOpYNu^ *4bxr!B Tgc9UN} *hkN"`%?/@y,\ [N2J)BPh!(aZ/FJDLj~T uWLO+ [OT@wu tE@Dֽ"cauto`NMUa *a_> Zzp&ز=;xFxM`Bkqnh`&xYGFbSo0jbi=L\`J(9`BoBhQ|J /4(nP@<ЀU(, Pox.C(QSbDmX<D WkZb=FEYYE$n\0Ow`F1+hCZ 0^ 1;uLj*X f])Q-ﳹR XP`9@0Ux #pJڀiZ|z(!z3Г Y>Nm%EL*\E]Wp,~_.( .2?kbvͥO6ܽo_>cVŒ,޷_R1\>ۓ)CD?KM+4跑T-mj/Z=a/ŋ_`WU(ٷ n{ay uNԂ傊6\c$`?cܾZQ|  Zw@wpq;R"4*Сtڥ_0,%"}&_LEYϊY7@TY!L an6Bm`*gBPl-IUWcC;Z^vϮN[B@9@m en"(~w  -S ug y(r̳)ȦD+dP#jOR bVy#[0ypH++Ȝoݧ6lJ//,,{b B8Z-j}PQ{DJm^DE0}viL6e~! @s>P傯< F׶0oSgfoe;_ 5\*w{W>`FۃB^J+.Dr@EB9ݢ"ѷGYd0OgvX@|]u^I (P3Dqn-ůe\PJPLN_.36U(FqG=AVYDcc{AWӭ9-7,?pU *C0V4r n-hJwI.3J1&/(3DH+P?h(wƭ6H@YLn\=EkX_յ($]`0!8#fO/0}Z٢4|g@*|D9n>Qz7]Xtzt"A۫9ԋ4VIW]ށfAec}3e`F>Bl[6.6ņrD>( Ÿ`kE?2bK\;ev{"_.@avR5 (~N:-(*~V+4;D}x}WњE@>[)j3(Q yZ yZEwri`(jZl ogݧOkElq" (\'h=3=cNJ2DQ S-Xh8C)צ}w tŘ <}|؜!ΈX }> QbGq)Pr ](m@R}S+^`{osH|v~ rVE(Vߵ+DK #+lCJm0C`4jnnbns"P n!j|@((\EihsLtkC]Ǖ}w>0P[a+)bw'`uBG Vbn-L0d`%kgx;bȇ8N/"sc,PL/KW[* 2Y, -4p$8޻@TxmhBJ_:z;MY'O7:&$QcQVRY+Ui6.Wj=BĘ񵖆1nnRջjg.)B`*8?!D[pAR$j`P(ҡXg^j%T 0ystCW.,t_.<_.!aVL-V_6j[wW >0K[ľ|l݅B` ?(N/P$" c>L%ʊsJT.ۅ!17L?]{4_>f-l9ia 9:ݮ0f T:۴EФ'Wg] 56:`*~Nid>9{7=py`_(r:{GJV Uc/B _>]I'T.: Г[s `&BɊmJ/D%z_eC)mŪ(AJE < ` +Օ"QN}˯P}EJ_`i+*\D({v[BoCb/xwp{SB*@1JTuw} {<&v&~hbm11 `XTOb+#94-wc503F)E5uC;@ 1mєiL 61b`#ů/UG!P0Әw0ĎC_>0B/80/ ֔#fZk`[[Hb<*ǩW6v Q1/lNciIkOzKd7rA6v3Qz5ਤAh *hy36D _>PbqTt 0l[E=׬N+=1Ѓc,C\h,܋*s@I:^ŲfAs܀FVf +Q<(^8YDfN{0\wu34Rjr{b3#T 1޺@tZo8 J.HT-KDqӀ=h,-O/rѥe3T`sIpTDO*-Y-S+Ԋ:{pڍ`pv)F7 6h* @`+Ĉ'AT{v~P޹a8;FLgZ е;CdNK4,Ŏ# i /pEXx7" _ m@UA 7,![VMj` 7pDBs_>h9 ž2C@E Q!~،90hcBY\ 9اR83]r$n\8A,{8^;5P|( OC@8L ;Nۖ :U[̬ V@]l]Mqq6sPD ~EnKGikEYWH- 4v,K_ȶBurD~dBoLQ 9<\p!*@l}:(Aebi*!#Q 0]ͰeR~/bHV"i5¥-(>]#'Eէ +XKOd+2-e xiq{@nD8)@|C";5e! 7mLT+nf}Ii ` թ!Sa3 2AeSO6 ^ F/ Њ*L6So`~VxAUtb-vJDBVn0o"`Cњd!#j"(< P@0(/-v{h)vӺ3YAQp_lcŜbj^X f;FTAZ¨14^Yݚ_Мkq ! 7N@w b(qe>&" (K\q4Кھ!#D9B@jg>Bck߂a_'p%`N|7M$i@>+UF1V偈"쾺C)ikYi_=CJ}BPQ,'"?@4Ԗ" OWX_.`+D򁊲RV3ٵ 79YGD_}G(rhnO}h3 T~! wG7%]VxEΕ_6跑T!@wj/|e_ ((5m?yuH4e3Fkq;CCnH)G /ۺ(B\L/<|9g⽇SB\/:_.`W_.&Heؔa uNԂk@EN^-`sAӽ}~O_1!+ >AQQ.6w6$$e^-hg D9YE뻬u$2<djVȏ:PH7Y?+A[1ͻCAԶP&<|Qz_NQ!r#yJn{2g^ cEMI|G6 0`p @!s~M`~%VFXWV9ߞ]6e_,,{ ǀ!5>=~"vw(a l?YC /x[2Ws m/`>Ʀf0+41>pFQ,?PVJ\]PPA_[({8">l M*wJuWSGLC os48<-D$ޠ1ccSbG}ԛ8G9As0#//5^+֜M<!u+ n\B@4Us`\R<_`F 9 Rjhe> BZ -`;0Cq1b ,5l7>=EkZ Jk-1pTG}_M3FٿuE _0-P jmi- vAo{B ׻0¢;԰;rs W]Ɓo?f"|6ضm\m\saʡoY(aweY/s-v)zg@N7 P"@idLEsiFQ5;,K59[Ŭ~D 0 ;ݞő- IBÔB+-J㉮(퀨u<-#(Lk8BWJ i u%n*ANKhqUp,| /p_6{[++-\@=]rxE;'cr1s`V4~,0cAH5@ vpD6M~:H9B(?&ɘF )>)a̲"cxQc 3|_C" /_ۗn#DqWw9{[c;"R RrFR9+~@bHlup}#A9}:g5RsEBuu۠ؽ=9" 91ber36?`N?]-\qo~v 0WkZGw$`װ󱼎9z=@+҈L]@1)m۸Ô2yobG~1Ҡal[DY3 T i3gpr|%ZZ gR(60glxֺ̗ _.Ȭr]}ef^Z8?g+YCjk9@bY jC Z 9&ۊ|XB[b%+u` K1{l5@1VCM/Zo}S@/ ƥĖceY!PcR[hH4:Aq Ue7 @TP|\!`WN}AS"PXDŽ j J 6kE !劲\Gs+VU\H&Z!:B*qtt@Ef03 } @<9) PTQQ,逈B)wØSɫ~zB<tw], Ccn4]{4}Z"s @su]atiCݡI BO&`L/[N/5g_l$0|so8{{ /_>^ȩBeqw3c0\Ʈ*r&&@On)h%+)=| *(*MiE.VbyE CD%עq^z DcmG_\r^~w,VrK[^Pz&Dǣ`c?BoCb/_ml9̩C !%*y-1 S~%6|L6hbm11 `X4`F,1 1 FS`16,VО"FVT~C`11`3l97Z3 2;`MyNP!hcT\;Gmf8jQI;pd.@)9` 42iY˄Ĺw~鴰=`~eEA} s4 rWwp/bY`sՋj9nVf +Q8D)OR g q[ART7@@ 2 1`~㭛f9n[P 1ߺ9 :]-η{F%=(\I(NyM/8ʂ߽>^{/b*Fj3yE>P"쉞UX-J– QVԩNjpQ-h(]gJQ! *jP:78*@Txv(~0 iy&3}!2 PbUQbǭ& l2W}rD0 A8DاR87`^~rUh\tܠ Ox HZ/_51Ne2;)5AaΕe:U[̬{ BԊ}Qk .fߛ(įm(m(K%|@LÜofYB\x-ep% ! -PET:mh%@mI_>`.DU^h`fJʄWf*!#Q 0]ͰeR~ZگUt yGG 0QB|bG NOVȱȺWdut`NMU_ ͢No:/܀~ag/|`dה ,fZ(vW4HHcV[]L`sJH3 2sQ*sKƂ?w!ZQiQ|J /4(nP@4^h*l`| >& lQqwb \hZ(\_8}k^bsVA|VQcDrUbVPAb_>P)fQOM_`n`ֺcDn4!M _/ 4'q\eB񍓳8?J\FC8R!|/ r#D9B@j: 0@eqacBR1q,@tvE~jXn!8Wj귑T-65@wj/|'c JMv[φbt+ -o(Z{ @#PZP 5ᱷuQ|8#gcvŋ+/Tav /MY!p / k9"zn/0 P> ~'ЊZPA냐^H ҨBVY}|mHGicI\h@ >̯l`&ɢ,@_egŬ }%U"*譐o($ Ae,X ge~Qz_NQ!r,S-6_AD >ъ`d`\+Dy~_M~*X8\Cr@!r@ۊU9&0b@B++Ȝoω.ҋ;r˒ w/ b B8Z-j}PQ{DJm^DE0}viL6,uH;},|1}r.(~_`Vb>^C](? ﱗ(w{B Xz_>pUQڝݢ"ѷGYd0OgvX|T]E]u^I (P3Dqֻp2Xz[&ZD$~@-1coSbG}ԝp rl+ g9RR^OltAef݊fB[!׭㽽MiU~6:ruk%C"x/heipz@i~-Di46 pTG}_M3WE׺jgkrm C꣒_  va}%oS/VX%]_qtzv!͔Elmڸx3D=8:( Pό&*Y/c-v^]v `_>p > +ȩtFi,5^ùb""P=jlBc;A:Y77Biz / .` X X)1 xFiZWR_(*8LL72|@Qr`3TϪE!CD?ݲE 0O/X P Q} ҈=3AF(C%L -Xh8C)צ}w T; /76gKx0m_)e(5(qkEˑKe1܅_V>sx̕}8x;=w[No^ j3غ>L."Ef7 ?Bq7V~}^Bm/6(<\@1|k~i@R}S+^`{osH|v~ rVE[Q\i%$>XO/2|`sn|`>5K/sZ5^ F\0DVW 9xD\1:g٥g]=۳`sC07dw'<9'A=C-gY8tzp{k5UkQe~=k{{4 pL,@W5 xҊZbw;B16"/0q%yԦ*!Ol*0QDV+3M3 /idE>J<3 0洰נ"{_N! ,Bf~cI@ȇQ(ȢJV }i[XT|XZ5B+!Φ= Swb| a@eXm8? xfPD <:GH4r&WN}AS"PXDŽ j J !Bڡe!Z}1x|f ;Df@k1ٶK Oe3Q=\+uWl} \xE*kEa|cbj]H}x|XC*utKWSPYcUM Xzm? u矿 5,?P+YASߢ8|@(Β(R{70*+j! *RyXl ^6 0i}Z"s @s~\dPlzD\mMv_63_h =^]@I 42Jt&|xa_.ʷ{GJV t3c؋yGpW mb֜P WYEWِFhJ۠(BpkT+"*(W7U`1X{uHp+T{_fX}dIwn"J=x;L!7!V<|;F=|̩C !%*y-1 S~%6xLL|BwŔ^bbC3(O/8ҘNr!Hl0\3cP`R$C;@ 1mєiL 6k9ZfYx0BC`11`3lso r3 2;`MyNP@}srcFDGhW$:T1'= DqՀv/p(D /pƆH@X&|`heBĹw~鴰=`~ee\}6X _9 q:]G\R_Amq{ނg8 |IlTsK•┧{GY[_> K /XS1'f^鼢yEsIpTDO*t, B`SaKS+Epk7aª jEjqV 6$`OoBtQbDғ *mA /s(q v(δk vȜwؠ4(:\B 85`Kߦ]Ӷp {p<[j` 7pDBs_>h9 ž2C@E Q!V~Jfq˦*sU'G؊s:c^g;E /`Mٓ#'y/xei(' `:m [ bx /xy BԊ}Qk .fߛ(įW erXZK B> Ӧ ݖr*A1%GxPXV7ʷQohc|Vmecd \hZ(\_8}k^bsVA|VQcDؠ-L(fmK?D0\@ 3|+{a9FTS6QԊFyEצ{#n:hN ص'g;q1ƍ2pBoM!{T$b /hy! PhskaiheIBn,H40Ӏ}W*bӶ* /DadNI0 \2`NPBO'g8w!0` e9W /`:| X 3|,x?kbvͥ}N{&yz%?cVŒ,&D| DIgW视^s mE.U5ɳ!@AnPxE&nzj=y`n : X8{[WO/LsjREG~բ<-^c4< p<=X*rjnc  c<{(>>Y\\"*t(he%vct!%q /h@ >̯l`&ɢ,@_egŬ }%UG SB~G xo0oƝ "؊oލge2n"(~w  -S u@ؓ >'w6[ I(BD/@Sa1TC1n+VJ-o*):ъoQ>M3AE!([{}2!Qّ028~Y_>r2Ws scl~a38M1W_`D|< (o{;`%k9 \wS.Qڝ`ܢ8@؃=Q1̀P|v`h}@,WdllVsDW?p%(P3Dqn-29i9(%(&&8n*8ތ`(F8BP8<@Q8ˑhr/ȴIҊ~5gOu@ef݊fB[!׭㽽MiU~6:\5xvQBy<42C:/ U18xAHk"g1a 6(xf,>~0sD at~Q"ú/g:F>*VXmZ @힃Jw`*؅EwaOw!(A۫9ԋ4WI8TilLԕ!͔Elmڸڸ-6C= A1~vf(aw _,E^]v `_x~p(rj:LM,5_ 8[EEExjlկ!@зfQ"^Q|us=Z`v36fPhlLi0J; j]!OK!OkiPTzSi`.x`9 XE[P!>u VtG Ƌ\ /p"'A{UgP{U\^5-(JiJ@r|3rX]ipmwh i@vN!?x0m_)e(5}9-EW[Ų-]8٠jQZZr0W9"`cO/wY0z`iip]=[!PAŒ!kq4:sC aGj}58Pʏ/Vr9J[!P*TTÊ0⊌⽷?D9$U99PJPfjvn!VǵŕV_]B\쀨 _x_m+9` 4]*@1V2 A/9@( C>G/HCs;f[S:uC= _`NI ۠ؽ=i1s<‹!0Y8ti:`[Zo0WknQ֯a-+ )?${4!B,9 ڶ{8L)E/(F>P0FQ PAm VR3J!9жZ!6Q4mz`&}ް _.Ȭr]}ef^ɿ `HmM/H1 a1$VÊ(J}dQb%+憾4-T|XZ5@1VCM/Zo}S@/ ƥĖk<…L42jBj6 F矆 "x
WmhBJL|rA+Y>Vo)Hp~y(cBB5fla% !劲\Gsf-l9ia 9:ݮ0f T:۴EФ'Wg]rPc PPR3̇8g lrA!?E*[K*Tw70VGq4x9O|R&&@On)h%+)=| *(*yEYŪ@]*62!kQ8/pz|S&.5WW.D9/Be+yijRWRpր c/p_0sPBH(FJN=6.cb/p7_.@S.xo_ ͠ /p1'0B``fƠ(H`h}!渭4?~ChEm`EL ޓ2>`;'qso gfl T2Un4`s#OqՀ]+*ho#DQG? G) 7gZ |`#AXc4^+ *ҘVmTd7l(K)QsrPuc3倢@A:_>P])9` 42iY˄Ĺw~鴰=`~eEAZ! ⤊2x+tһyA,EYA7`+3p(Zuf{)10@p g8m>ĜaEix#{ T)p(`SH)i n`.DYO'!L^0#_%"cD<+LOQ ݊#B<]t%V-!B~)(XKOd+2̩*QAQi v hƑM!{vaFxM`Bkqnh`&b7~E>$4fD6`sJH3 2sQ'Ekq~i0z]ȇVT`ڴAK% -'h;P7p$: eu| >& GMY6@ňڲ2JEy.4D-b/5`/d9i >1Z"lPӺ3YAQp_lrl@1rާ&`/l070k1 7ԊFyEצ/Y݂xvm82D|A %n[DYG9:VrNn! PhskaiheIBn,H40Ӏ}W*bӶ*L/DadNI0 \240~ QB(a A'|GI|;J T24U0  X /T+J`F1v>'={"#Jߋ\(hnO}h3.7(#gy uE~jXn!8Wjeht_>PK-L JMv[φbt+ -o(Z{ %!qP 5ᱷuQ|8#LsjREGXEyZh#pLQ8Q ؃5PSs=W;E \to(`!+<T d@wpq'R"4*'Yh;FgQXZ532FH3QN}f.+?+fkapfv SB~G xo0`!(~Vbw##mYLx9Qz_NQ!r#yJn{2g^ cEMI|G6 0`p @!r@C8J[ѭ|<$odηDMVe1.K64Ϳ>$hE7s_g>*tA듑RlݖVdɂ Y_w5!,3m;q7e(~?`qW|b>nC=pF[|ۃ|p3ʷ=@!d]/|B#.*B*H- = eY gE(^r;z PfR|* ̀/`CXEiܷ48DFDipTG}_M3E+rz;.b>~}rѵn9UxWkm o{pB ׻0¢;ԵWs̩+譒8To?F |6ضm{FN!P\V{Pq DC3@`rQګwtvO_C 8zE9<v-dL`3Z!ZEEE}CZn![3(S(U̺9A@њӕXۘCT|haҪJz_>p`%ofyo~Z+e#<<`%@*GENH# bϠwpyQH=E L?h9jDML46KL43z^bYsol~Lֽ"ZKDu"R4P8?k (q=٭T`pe1s]8/s&kZV9~+&Jρ߻,AirxE{9@Ԙgu+dX=E$(Xo@~w &q{C`g(b O)P(yk~i@R}S+>`{osH|v~/qA)Vvh@4LKH]X/pokU3\0Vsnr}_>PsTŜއPCCk@( C>G/HCs;f 1+?{z]0PnW(αbGߐٞTL;F 1L`Ʈqfеٚ]2[Zff߅pLh6!0L@1傹Q_@ @~g4?[J|+r mRjEϦfmZ "e1̺(GXkfƜT`O9[R[khPRR1$VÊ(Jg+Y17+YcGί]!bȇ8/xZ,};LI9"rmPQzfT@UHmF#Ź/TE0QAlCVr_7 PJ)!h}7R@<` 또DD}XIfHT!ڸ\QcZm3u6 Rջjg.)B`*8?!D[pA{iBg,KH_fbz"W⼋([.m8?xX ZWq:\><) zH`nж 0lE iY{8_,YR_@ vyr"Q%Q(na*yUVԘCT \mMvy_@PQTR3̇8g l~O PH#B۽#@%{+~ Sfƪ!?/pW  mb֜PbQEWِW+b.VWD 2DTr-PN~o DuVy('>W|"`%?/Q~Wſ">S8}kA bU۱!Qmjކo(}!D%[Q?P!]bc/p7p^L-&Fk04#94-wc503F)E5uC;@ 1mєiL 61b`#ů@Ta/@9LccgM(A˂c1L,ޛ֔#fz V'+0OqՀ]+*ho#DQG? G) >f9lD4|k xEظAEsړ n$4fD6`sJH3 2sQ*i /84[.C+P0m OɿYᥒV Q(8 X²P}z Ek]P nT- TT7@$=@_8}k^g Ⳋ%}`Zw`F1+h[! M"(a #:|Z  Zw̓"Qc^ѵi` /Y}hq\eB񍓳8 nm0U NFnr D]l!R|>X a}WT;mD3 (p Z(f?ݍ;e O/DadK!`PkY_>`NP&2> @k(O/UO/`:|_`+DrAEY+R#{bvͥ}Ng} Q[cAE/aFO{ "JňpxwtQi8aW\AХyݡ}N φbt+ -o(Z{ @}&J+4` 8<. LsjREGO/+Ux {ay uNԂ`95s{yD Or1_o`1V|E Z..DJFE:bslC8JkG+^-hg D9YxwYY1ϊ^Q\ p 25z+y CP8 g%`+ƾy7=K%4`O^Tv_};aZ φik)ا?ZLY|,F*+BgmS_M~*X8\C:*"vH\bxί ̯"J 2sK P^l [oW" hE編I)@E!([{}2!Qّ028~YCeo tAe,1 F^|i9(~vLc,x|QF% 㱗 (o{;`%k9 \wS.Q / -=eY gQ{EƦo};@ԩ+q7Qf⸭qgP5|i9(%(&&8n*8ތ1 U1txAHk"g6*Ƞ>'i9('Olt}4ۧ:"Ci{r'x~ U'9g@*3Cm[+^ê₈B ׻0¢;԰;rs W] o?f"|6ضm\m\saʡo?;30㻀 2b`rQګwtvOC8zE95|QPZ!Q+VH @VhlպAjŷY7>=Z`v36fPhl=:@a3Zj@|%iM/ J/a / Lc-li58> _>`%@*GENH# bϠw6' Q0Ӕ^-g64 ڴ.1Ӏ- solLQN&RyZC@۷JR$Z\x%\,9܅ 4^+բbq[1Q0}_)a̲"cxQc 3|o00Vvh@4L: >X GVS0VrD/L'QW-~s_>0E#[]a(\Eihs}sLt=x4v lrNaEpi@kf.| m۸Ô2Ybq;clD_0q%vq) _ȁb˵U@EB&kE_P5V!EDPQ{DghZ  //ucvrߍO7:&$QcQVRY+Ui6=PWlg7`cZ0c :V?0wZ!϶]RTp(CRH4Z3P%C/3DEig`u_z^sZ}mk81__P@JB?R[ND耊4W|ô,Lָn{ysR UZE`{ì.fwF0ݽAUVԘCT z}Q- 17M=M?>f-l9ia 9:ݮ0f T:۴EФ'Wg]l< j*|u倒id>9{7=py` i/@w/Pފ_Tj6AF6yO/ B !%*y-1 S~%6|Lo!mAnm11 `X4`F,1 1 FS`16,VОYA8; C+RC`11`3l97Z3 2;`MyNP $L(9@~N W>QtNp qp/N Y5Y\`%ąP mzA ^hPET: 9<|"…;$"֋b$ĈyT uWl3l!Vl/@wqt tŎ+=k鉬{Ebw}9i޼Ź'v2nq{@nDce  _>02vkCZsC3QH+q$a1+ȭ.&:(>WBi+2UI _>0`BoBi(>%gJZNXE7(FbwoHt/4` C1-6|LvBmecd \h~PkNr٤Bh6AD_Q ږ~bn!JQ;aYUyРV0j+6,9`D38$`6(Co (`De[pu7*uzN~@}f>Bcp,\ LC.Kw(~`DsR XP`Ɲ2YV傈2+8%m4p-3D ԇ),>N%q()B`*PWL/tҧ+ ,L/`+DPQ]jJ`F1vX} ƋWu7pDO/ }̊>@ޤcc/ADQ.GQxwtQɔ!z'^s3JХjCM/ `PmD[gC1kkӷlf-j=KiQ(pӀSȏ_ۺ(B\v~i3^̩׋M/ _<-^c4\ J@&(uL/ k9"z7E Or1_o`1V|EgVƝ\\"*t(hg?e0$z s W60dgbsP۾* \djVȷ 2q,JV}n>xP?sX e^6Aӵ CJ ~6DN[{4O7ԍcW@b{b+Dy6%4v cspDI@!r@ۊU>op0b&Ox%`ԆM>'U%`¼,֛ȇB8Z-j}PQ{DJm֞& " utB&O>gn9 d`#@e]L F9m'`>M̀0Vi~1_C r}#W,bEBaG( Т\MPPA\3P$>(f(>] +2mߞ!^|ܵ(Gu2ӋuHN*xooDSZx|3J1MPfR[W*9<t̀`2 b ,vdjk9<@ZLÅn)3pZQ8,Ԟ8>97 E+rYw0i2@|%i]/| fܷn(=0y@Qr`3T~K8>~Z+e}Gh'e+ W!?ڥbϠ* b(Z?P0הE9V&Zlkb5Ai]b1]1D 76g_KX }Ei׻b3 #>+ G_/p~};{Zo" 2 j3غ~M"Ef7 ?\,i|v8PwŎ>A3R2ׄrBTH>(\X,{#@ԘC\kHz}_.P4T]ۻҲPz v(_m97hy`> /.2@1Ê(Ce!5B$}w+Y17+@h[챁#g痾(Њ|A}o )y"trmPQɺfT@UHmF#Y "JЄ\!`0=/ucv7߲- o0uLHƌ "i-JkHT!ڸ\QcZ_&`ưӻAt~0JaV~ CmP0n!KP J>eYB:2CTl} \U/"]4Fm8XMZWq< ) zH`nж 0T`}w503 ]}@<9) P}_`C`08IѵIc:G9l(36mp;49Al9_/5@ U#JJ`}pBF{ݽAJ*Tw70Vle4v%}PR}=5f!ئ2@TrQU66(\/P=?dZ? ^}T* 2A$ x*߽/X,myEC띛E8yA =/py鞁B^7(FJN]Bjƾ oXE } e ^bbC3(?/8ҘNr!Hl0\3cP`R$ZSwh0s6My?`XA{#(6[[/C+RC`11`3l97ZY|M]mJߣDlΠ; dEW9NkE!ms(1ea,󁍈bxaHԊ|CƨXveGmf8jQI;_ /LD;QA(ܖ8XA4,jy`hr 5< F>S_tZX0"s ` B `& _-q8eU/ ;̘%6MR$JyR3z!@CN )*H7؃nNy@BJ=/`~y_.p}-xӀo<[=Ng[nNWeoy@Д ͰN؃m+ /8*{'`:}!Ҁ%@i\J]E (Lf:֊aۥzd8j@!&M2J^zD%oP(~0 iy&3}!2 PbUQbǭ&WBisw2Ҙ 0`[ȇVT`ڴAK% - Q(ME$: eu|]+74`Q ['ڲ2JEy.4Dʳ` o 9Y|UhU-Z`_Q ږ~bDYp{+{a9FTS6Q jEƼkx7q Co7Q4'q\eB񍓳8?J\FC8R!|qP-s_&p(GH3\`ᴰgp#\!r̳)ȦDp?,!C;$_q[j<WBlatUhy%`9%`Szqeeػx_.Ϳ>$hE編I)@E!([{}2!Qّ028~ Y_f!,3m;Oyk]Y\M Qn%_ (VD?a}O(=pDr5@EBDȬg|WxkX|T[E_=uz_I|Hbg(<8n^x2@,~- >-Rb$Zb(oFcxC4`\x)x[F/b>ZGOuz2Vk\߿DFSZx/3J1߇&(3DH^P{@Σt_="4$Tg6*Ƞ>'g9@'_P{iyw${ f-`u[-Nz6]Xwv@k1Ѷ{"0t)!`{Lu."rs z+.U20# !CCopQ@ڻb\~o}`EbKY\݋dvN^EN=/l]e@QlcuZq `V+4;D}ܽ\/usޯ~#$Farد(PhlLi5J j]!O,Q hye0Cu@1 (QE[P!>-liu8? LVB~T_$4bϠ* zwQ8osE oE9V&Zlgb5@i]b1< gtk1Z ϲJ\@hqrA&bYvp {~/<ҽp `ck/G8el9 " 19@Ԙgu+dX=E$(Xo@~Å(>no_]ZR>;}x0P(yk~i@R}S+r$0⊌⽷?D9$s>;D xyE[Q\i%$z. r,އ 5,O/̶r4\0E.@1a!F_.P$uP8"44繾c&Zug:w.{(}g+ZX` 1ozlOysN&HCbyoe]0L`Ʈqfеٚ]2[>{ viff߅pLh[h9$`tmv#bM Es#Bf_7Σ4 jSh~j(WM/V+3M>%D?@L#.~v#r,^}*㳆>W$د+A$z7<9&hgPDP#+Y17+YC}C{^xʵQ@ݷ$aAGS.[* 2Y,z -4p$8k.PD <@-- hL|ůdbXw#E 桰 AԘAԇl֊DBڡe!Z}1x|ef ;D_2"jx'2(u.QDC u]̺+Ju>֊}yE*kEgb5j]r><`>~"utKWMd.g{-¯xW8L,m}:'ePϒZ *h /] 0ݽAUVԘCT @}srcFDGhW$jE>!hcT\;@6v3Qz5ਤAM/p(D=/pƆHM/L_>eBM/L͚_>eBM/sia9{#ܹl!.|@h@厯I:^ŲԊzo0;L/J~ gV(^ZKHG4` F{jè& Qi)zKO  0n[P ޺ :]-η{F%=(\I ' +`<\ hJe3 t^鼢9T~8*{'`:}!Ҁ%@ԩuN_qLVNjJoa5nL&DJ[%FT/= ۶ yFa?cc4Dq]o3D4,Ŏ[MyZ(q{@b33E7 踭3qjl-G5Tp9/p_>b_!"R|}?lF(a :}`Te @[qTsا[жBXGYb biދEީ@,< Ae2; " s,iK?/DZ" tu5kyMWDDpV {Dry@LÜo̲ rP=Qc i gW~Po$@mIQ(5ZYbV [N2J)BPh!(aZ/F{% #Q 0]ͰeR~ZگUt yGG 0pjK OWIQ 9Y+`=sj QANo:/܀~arA/5#cl0dzmLT+nf}Ii r믋Nm!ϕfxe LU_`[ȇVT`ڴA"BZNXE7(FbwoHt/4` C1-6T lQ[6AF υ\y,;{!'o Ⳋ%B+Ӻ3YAQjq4Np> `V-N*XCm ŧTtҧ+ ,] (r *ʂK{*څKxmc} Q}̊>@ ( "JňK>`+pSwRK~iKC=/1B=*n :W$%@){̺/KrJ+4`"ۺ(B\ /pF_.`_>3^̩K!.= @aت\to(`ChWDy -A ODiTTCA+, (m,iKE-L0('>}}n#7TY!L a6B@ a(V(oDq7r3.6U89Q+5~@r '0CV?eXL8ZD$~A-e1cߦ(3#_({.Vr$>myE?ݚ rr: PYB9@ɑh4UwwAg<%XkWe)u^~%b~ qD5~=H" UgLؑKAm(~ Qo?Bl+3HT! !8#f.'`ȩu ~}MF>*VZ@k1Ѷ"YULQh va곧{Ws̩+讒8T}vilLԕ!͔ElmڸڸjʡoC." _,zE]ʟؽH&`_8~p(rQ(Kp9~H2[تu'oo(U̺9E 0 ;]k3b}(4Rcf>>ϒ0X[3a[7s﵂ Y-J6eno==|痽ݾ~?\l9}xE}e9@Ԙgu+dX P^ Bgy+?C]ZR.žlQ(| @q<5a?H4BTH>̇M`{osH|`v~ 2Vs 3D]ۻKHtOQAjQ'# `ܠ)4\PsTŜ~+ 1"Q}^<7wD09u\ s,|"X!~ Yr ! OuDi`c*3`N?]^[ZU*,볖{|kVy9v](5<m=_(FP4<07"4<`u/DjKO}Pͯ[*mL'նXc]0L,m}m:70V4ToP}#aVl*E8K: PJ0T򪬨JecW!؂@sפפy~OcL4q@M[Ml~Nzr}69Bg.B@I 42✽^?8B=/߽#@%9U, c؋yGC2 w%۔['0 d6r}K 44mP!Xu_z~^%Qɵ@8g40'zrIՕ "QN}˯P}EJ_&`ikGG`)5 1*c&6&~hbm11 `Xi hyX"њC h4 ApW*P^J rǸ!4ۖ` ֗igp/ ֔#fΠ; dEW9NkE!ms(؃iL1y@6"d>5F "ilܠ"9iIo4`ǭRL^ 8*igP h *36Djy` r 5<0M4k˄_c#ArG\C\h,܋*s@I:^ŲfAs܀FVf +:1XLt/PZ-@Ꝇg"`ڇy#=HaT _4P>R"S%8F5p0|c>>p%E*/dӨ,a_BTM *bWK;e!*~?wR= eTiA Ԋ:"pڍ`pv)FK@he p#Q6A]/s(q v(δk vȜ6AiTEYz# i" ,Xj`iQ=+:n+"t,m:3tݽ B ,.(\hwEeam`H}?lF&D S0Es4\4m-cKh&h(yAT!/:nҼIS+EYxIeGwhSjH{zq4bx\/ BԊ}Q" yPD ~EnKGikEYWH-4,K~u(Cp6 P@/s*T5'0 ⳜJb־YRW*ۥ(a~ mGf2)BD?PW*C<]t%ŧQ}]r'3wG]!-SSUx_ r>/;bp&qdS!{v;YC-n02vkfd1lfZ(vW4HHcV[]Ltj FP 1w}0(W2JZck-/ F/콿|hE MD)70?+TҠr*A1%DBVn0o"`C >& lڞ#j"(< +ނe/5`/dmVA|VQcDhe_U3YAQp_U(K'S@ 1zuLj*8?J\FC8R!|X f8-weGr>3@u8ayX91Ďd Dh"L9\B0Off~Vتh,@<3 1 4p-k1ɜ3D ԇ),>N%q()B`*P+O4 OWX4` @DՏ3`+pSwR6"@et_.1B=*n -Ectx~J+4`coco qXi KM p&>fgN;^ qQezz_^Byz} (6Wp&e($؃@EN^-`sAӽ}X _1!+ >AQQ$1:ېƒz s W60dgbsP۾*2#DT[!?#PHz!L ADV(FgFQ2t},EۿŝgC䴵GHKxyA vO&, >#\!r̳)ȦDp?,!C;$NJ>. - s='lJ/>/,,{ǀ!EP*yހMهZQ{(B(P#`N+dqd=/Iw< ]u5 P0Q>A۶0[>?{̀0Ӹ+ i18r}#ʭ d>2|BwV >}|! DȬ]3 l]{E*聨JG /!g|{0nD-" bmrUA}N*(O-JČ;U>a/z&!? ( > ~?P+>[T }vT»Z;hEmQ0¢;ԵWs̩+譒8To?f"|6ضm\m\oa@g P7|PˡˢL4T|=!8^ZvE2;r''^"a= T랋]@Q#[تu'('CSWԇ&(t36fPhlLi5J j]!OK!O@Qm. L>0\uk9B*gVMwB?ݲ\`>[VB~T_$4bϠ* zwQ8osE L?h9jDML46KL43z؜!,.`#&@AaZ"R4P8?k (qV rZDbpe1 /V0>Ei٦ AMl/~\`v?.n^ j3غL(Trݗ`zu:n_ZdnbD9_~@m5\0M/Lѧ5K5{ "{4 1D"XѶmCaJb{;B Rl[_,PAm -f>h9cC )g{~6g| "e1̺(ٍ,KsZkP=o]p|֐z_.XcF^!3{1$VÊ(J}dQb%+憾4 Y٣/DίvZM j-b˵U@EB&EP5V!EDPQ{D8 /+&eWN}AS"PXDŽ j J 6kE !劲\Gs<23 mQ z[MBl%EL'2(u.QDC J>eYB:2CT" Wk"uLA -K!WC"><`><-@Cـ:B+ )Hì{W >0K[b_qIY6TiEQ "`F13z~t@8VYQcaP)ƊC`08IѵIc^+4ܯDT:۴EФ'Wg]~_.jl<=>;I`}pBmFE*yȩBe9H^#8\PJ~O<)un'o1L4۔~_J.-ДAQbu -֘WD 2DTr-PNL46\8k_ r^~w,V2K[^V1@|Q(0ӷ< X^rw =\`ԡ| Pϖ)avD=&&~hbm11 `Xi hyXGVi"њC h4 ApW*P^J rǸ!4 @hgfev\XH`V!  NVa1zԫ{~ZZseQ}؃iL1y@̇⢰q2D+ *Ҙ֞ Mvܶl#|n`&S3H "5\PbqT!aض+gyV|Dz90ąV½8"L>g^8#.~EP, lzQmV4 a<`%`ưCD)OR t^$ ip3A^2hu*4P>R_8F5p0ﭛ | KJm(\I _=%8ʂ߽>^mJ L *bWLŨ,ixEN}̡s'EQ=б[6M-ANS1.nøuöKL4*$^2DEC7P:(1zI|߶mP(~0 iy&RD)tӨwWDMj` 7pDBsφX+Z>W(-kCUpa3^6!JH}QhcX6U*s6!hGh9T_ G386FC BO yq.Vx HZ/ _)P&N*8CRD*҈42@!8/@>[WPD ~EnKGikEYWH-4vy,K~u(Cp6 P@/s*T5' <`.DU#*E*nS&~pܯl;b(G5Pw6ÖI"iņjV*i5¥-(>ݯSPȱȺWdl$*tHrt2U储 q{@nDc0lj }^>z'k FxMyތ,FmLT+nf}Ii r믋Nm!ϕfxeܝ4*i /84U(6mŧRIB (ZǦ" X²P}z %X32"5eaqDmX<Ds[ӷ셜,MZ*4*jl[e>fX4Q^#J^X6Q jEƼkx7q !Ut|}Y PU @i uTCӼ_@=/ Qg(4µ0L44}$`N|7M$i@>+UF1 O/DadNI0 \sW%Rz8w4? ݡV4T*0J.b+DrAEYv٭0]psiE} @u7pD?/P1+XGaFB,^oQ*FT?ûήHO "J=/ mE.U|uHO5(~6ڊxE-EctpR}m4pӀSȏz_.ۺ(B\3r=/LSB\/:zy^WPgxJ~md‰Zz"z7E Or1_o`1V|EgVƝ\\"*t(he%vct!%q=/ z s W60dgbsP۾*2#DT[!?#PHz!L ADc߼9-"0^-GYy?;E φik)q n{b+Dy6%45c"adrAJ>. - s='lJ//,,{b B8a*BP3)P j}oEE0}viL6e~! @x?{Ae,1q-ؔ@ fceVA1>pFQ,?PVP}<ꂊ `ܢ8@؃=Qa|CE(b"ccS倷>} t+q[C(P3Dqָp29@,~-RbooPvrA1> ãe9ŊYDccxAf[s6[nhFy*C0sv@u+b)F +.3J1&?PfRDCU/^Қfiƭ6HcxAYM2IEe[iw@ Y؇8 Eӄ3FO;xo6-Nrѵn9U8Vkm CR-NE ׻0¢;԰;ri E W]Ɓo?f"|6ضm\m"F_"r(E8CDkE_2b`j[{h^$!>یpW@Saj}eB8;G[""Pݙm![3(S('CSWԇ&(tfmJӰav@ԺBBҠ`閟ixUF/(jZl ogݧOkEq`L+ W!?ڥbϠ* b(kZP0-&Pc5kE &VD\%&pP}㵂8yӒz;b~ !+L:׫ؓ**AE.Ŝo\jQZi,CPnoj.) bG/f %O/_$c!P*TTÊ0⊌⽷?D9$t>v~ [`j&}nDC~BWZ}u sw9{[b_m+9` 4]*@1a(C!b0s"44繾c&:<`ss,|"X!~ Y OuDi`csfL̢Y8ti:`[ZU*,[`< i{VޅD"Xr@W3 ҊZ7v&D/(tc#Br׍(6UygV)r|%ZnϞHS>f`FѴ=Y?cgrFf]FeY|cN [{ *B'R[kh+d&:7|rL4 h#" RYXɊ0w _)V|;+b\fS9ba/PKq*p!5͢/ ڢ@G s_(㽋3_ jq4T-Vr` _:-- o0uLHƌ >`V$m\( {1k6KawtQ z[MBl%EL'2(u.QDC J>eYB:2CTl} \T:Gm[uW<-PSxD1><`>,!:B+&tR2W+}fauľ|liI}5XGE9@(Β(R{7ͷ R(xl؂@s{$Ӥc=a{ct e&8٦-u&}6?'=ya;BᙯZBWW()FCb]?8a^u^ȩBe9 X5b!d[-dž#&KB$ȣ٫HBy ib-PrD%;Uw"@T-"*Yǹӫ*00Xk_\r ^~we+yrK, µ&Dǥ`vprb [޽6AF{?9u((QɮS Re`h /)(\Qc f 8ҘNr!Hl0\3cP`U$;4Zs6My?aS=RpTTR`4< QsO[rZgfouJ.Elx NVa1zɱՀ{v`ֵBbYPGkDqEsړܡi;@CӌL^ 8*g  D;QA P8 "rtieES| /Ð:]-,g_|DkV½8 ^RNxeU/ ;L_>Ja`V(^8D=b{PUTP>u=iUH)/xc4 0n]Pp19 :sF%o[NU(vy)Q~xq_.()mW\S1:qt^鼢9TD= >e04 l u:N8}?SX0Q(.Ꙓi($^2> D@`WF]d@ma;NLTjO`g̩JTLCWm&<|! +»+@ Ӵ+rXpn~b}'t˾!B TA.4G7 $Q?JtR>6Uz0x.cۧM*#%ZN.4isiZ'ɑQKɱ4E"xPQ 2qR9WQc肄|_"roEt57(ȱ6pIs@*{hEY^+o$*vKb|_>`%X 5V:WX'թO$@mͩX@{p!\f֥T&0?Ht$bDq?f-"DSAo}St<-/ħ)ڀF7+ -=u !w8͛8_>@梥{@ 7`a/4l_\F%k FxM`czmLV$ kJ80Ҙ_xQc!HH3 2sQ*/ ^`¶-VTai(>%g 74Zn F@t^h*,, ǩWl(z32DE>v@ňڲQEQA "ѹl,;րgBlE vK_[P(fmO?DyVi,8GPvjv~uLjZ"Qc^ѵsv\Q#JIנ2P|ct^N!8Q"(r"mG0ƚ\!GH3}p- 0>gY0PDC]$i@>+J*j}/L/D;6`8e3D ԛ)BO.^Nm%ro+)B`*(|"|I9@!v_r,|~v+(f^ nܽoş4cc- 3r`E1pwti8W\w#-t)_>K8oPGE­PxE)5˹ Ӏͺ(~P6Y@95*ąx|uz_Z1F PA79| u鶻v/ v$`?cܾ+Ey->f):w PTCAtŦHƙ %H^-h}g D9YE뻬l1>r(_I@\djo($mbC8 UȽȡ–Qf֥(eٽlӵ Ch%(~6DN{{4w7(ǯƞLY|ZGOuz@Y BBBy r_fcM> 3DH+Pe/ BAyv!,D." bG.@Um#@y? n^Z(flh,Mrh!?QjENw]Њϊxkk9@UxWkm <8@D vat.pE is z+.aYD }O, Duh-P|Vl(zAb |_w!gH4TznTxykإ tvϟFpW "Ga~,= %(@Q 8T3Pc NQ׶(~oD 0 ;ڶ` @ MX)1 NiDWSUS_>;+y`?`.x`:XZlu T+\`Dc>|o+6l~L{{@6pȯ2 J>U"џ~Xs\D͙uo+Eiٮ AMP+>[~\^ PjruxE@9@Ԙi3غ\"Efl7 Eu\єw3,Vd,m506$!T zCC@fZGqGu *ȱx{ڶl5`m_.sC_./4|1Xz|?j5"Q+ "\1w^09X {iC= _uu YouɊ Ҁ;cdr3VsϢYt:]!YMպz-9Pfn={AH#^33@Q8@ѶCaJ\(55\0 5~T_@ @Ӿg4?+-U3r|%Zΰ|mk`F{~6g%H2@1zQWo%`Ys`k\ go%>kHz\Po@$z7<9Vt h'pE 3o+bnT 䪘=6p{@ Q+QM/xh-9CW[ \-zeԘBjo H4:8 *]@^d-)jreA)4>Y@ܽ`n q!!3 DYIG=BH;,$V#D9n_ת,DkoHaV~[Z Qt!0T0n! j@Ym_fEiή{5B+BPqEc- жz>>-VK\}c=G/U|OC*ut mxӉW6kxTw"<ׅ:;ePϓj?$*T$" Զ1'@)m]& c4_]4?>5JsQƌaVm % =YMv{Bk>P U#J*F8g l4B<^FJV, c؋y(_.U  ib-PvK,-ДCQb}E CD% j]ӫߝ*00+֕"QN˯Pn"`%KhؿQcWſ">#5 1_.{rSB@:=>sYDi B{@s11 `Xi hX$6c1(h0* b9neSj"sR̺" /iX \j`]p @sp<[j 'p9#haBQ#3TZ EJfrO,$sU;G#J}ԇ #64`R_*A X=qX"ip{j. Cw(' ݡ] " s>F "V@ ]&/mD PJQ9i9Je{a-/0fYB\ 2D2zalPEBu PA[s*V{`_0 % nh`f]Ae A Q8l?b(G5P  ڷ)BQ]m DUK1Dȏ>.I9YQ+{c=sj ul0lDNg/mjq^S;#(m֊Da <_YGFbSo0j1Ĵ `[FHccZ_^ض|Ԋ*,6mŧlᦒBV ((OE$*,UXXV7ʷSPfqe|W8lAFQTBHt</5`/di >[QcDheRT3YAQp^U( N/x%`/cD_0070k1 "Qc^ѵsv\Q#JIנ2P|ct^N!8Q"(:/p_.?xe\{eG9B@j@hskaiܬo`%`NbGM""LCS>+J*j}/L Q #*q 4~?!*s[%Ro=x94? o(_>YRM*t(h2{̐ƒ-dh@ >̯l`&ɢ,@_egYo?+ _p 25zWs˷61`!?[sPwag(3_GYD_gqA!r#K*BPݓ >Lj"܋nJ 3*X8C:*E07u@J1nƳM`~%VoFX. s=;lJ/ZX/,<,ۀ!]]Ԥ{ @Q{DJmiwF"DE0w̩B&OCҽ_.w{#2)_y ^>|lH ~_`V|Q^%^0\Bz XJ|Wz@BzNQ|"D4Q2cOR)b"cϨ .k ݒx'q G8Bzx&g2r.P%˄(}0;Q储=A¹xc +֜MX} ++x)<wHU%E RjܗsA4b~!?j,>p 0n/`#4]DJAOZ(~ Ϟ[yw$Z! {!8p} at.U}%V[5h- vA<@D va>7PA۫9ԋ4VIW]Jo@XLYAmˡXX]P|x9rQL4TnTxk إ,*W{vnN^)_.@pJe >@C+VHCT~Ʀ 59Ĭ~oD 0 ;]k3>*46Uc4l9} jBBjr_>a:9\m4uTԺk9BSZq2DSz[.<SANH#lR H PB0ÕsQ5"p`S" MA8.`w|oEz;b~oUyxC}O Hy~bη 7iwgkQZk,CP<~{Ԋ/{Y>`vzW]g-WA#(3m[BևPBŒzn<'pnh>/pD6M~ !FnmUm`>\єo3,Vd,m50^T/z>*(f?u}h!htk!ĕV]B]QA|m_9g*F )[ ihKbn툵DPb7۠6-FmaDή 9xD5>c&樮c%gYLJY EsJj0bce{|x#CLsο,\Yp=@+9T 1WkH;+ ${4!B\xѶCaJ\x1;wa CD}؏**]UB=Yi+rmSf)"42En$`Ys`kܧ8>kH|5oyA$7\9Vt h'pE ޲@+>4) _+yWD[i/`6|`ύXξYDș]}r(\n(CR#ht~AqUw񁨠qф%E_>@iůd|\mASE p1@ԛlVi6^V{1Z5ywt[`aV~[l="j; H4@_>ݶE`f݊b]Wkuz^}]g}m5|/`}[@׻1MGÅ~R[Vh[}NTr"ô,L@s;NY65Eg*~RJ7sP딈e#Cpi@t|X@J+ cEnW3 :fZp;4cD]l[;:xePcnP|@U 429{7=py`< |t~7BVBe9H^#Dq4xZ%=PR&&@Ob>hl dQo Ĝ"[h}[ Q wQZ^=Ty6XʻuHpo+T.Xɂ+,"=V@|Q-aݷ <-FЌ=SB@)avDh=]8y?nLyo_ @=4`F,1Ej w@1h4CԊS,KA80ZQ"3)>0cm#`_>0\L,~M٠Pj`V! pa1zɱՀ{v`ֵBb Vb>`hk xEٸ"9iɱ/րwrACӌL^ 8*g rA$ <LLt9Ð~Uz0E{q"@&/|8?"^Tqv\JasCD)OR m`p1p}9T5 ؃5NӠ2 )5|h(v`ܞNcutZoq8>mn P8UEi4,00<QS+bW4R!*~_w"ʞ X 8q &E=S2 76P4ԯ; Nr5t+Ĉ'ATvD(~[n4<ŞVt>Se}[WDC(cQ*=JhmX6ąG(rQ G3# _Tg.Vx HZ/㞚T|E!LT&ptv&4̹RK\03tZy]!.rFůQZ( {Dn99_.0e]!ޮ! cl,"SH ښS+@{rY}.Q\pE3RE*nW&Ӿpl?b(G5P̰eR~/2;@wP:jY¡-(>j)@Dֽ"cu iX|QA|倢{@ 7`a/-!G[֫#c$4fD6`bi=9Ľْ`,x}\^ض|Ԋ*,6mŧlᦒBV ((OE$: Cq >. QMYDQ[6 (*sy@$:WmevrUh1z"n9fX4Q^#J^(Ljj;5;``n`ֺcD 'hEƼk{zY$ހ]؎kPB(sv/'C@^%Q}"7@|QA8W@Ŗlkp#>X Fz, S( !. 4|%`B>Q~ZS0 e`N}P'/'gy9!0 er"\wWx\+DNpwV|Q̮-\dQm3(Q}8Ѐ׸tN|՛6@Q}9Cn̍u}LO "lw#-t)!@w47(i"Q\@l(F "r͌^s%!q`S W!?46b_\ q!t<ipO|Ң<1εoPAߠؔ 0 u & Co4 +W nr1n_obZ<Tz#d@w"4U`/M1C8JKb_6^-͌y `~e3QNg.+?[̺ |WPe<djo($mb*gB ~ "rC݅-̬KQZ9""?3E  -] + '|`%+D>%fd_>@E')ĸFGi5'+ٜA۶0(]Y\Mq#0J3^(y!D] ޴G])W(BTST$Z GYʬ|Agۥ{EƮQ w/kx ޒAQ8Ҹw1ip;r2h_s('_ t˪t{fpn~O 㳜w 'Vzw\9hgEirѵ*Zsg PCnLt|&R ~XAo@|ѥt70!DmY Qض{ΪfbCIO6C= A1^3D$*~=*BpRzg@NspW "wW:S(KoȘb" Qк]`H X59Ĭ~oD 0 ;ڶ` @ MX)1 NiDWSUS_> * 8L/0x[<0{,}傊Zw-G6B|]jlVtK-<ySANH#lR :(E!Ur|-Xh8C)צ}v |T;_. 3'uZ+F?_!+L󆺀O HT\xbη hwgʊ!hs̕ 8r^[H1{Y(3m[B֟PBŒm5hm ^QF R.P{ʏ\dL#BJ0(FpD²3^T/P=\J 3O'BT4LC\i%$z. r,/ж5靑0۶/̹/LWhKk{!FC|傊Dή0s"4js}rL=x樮c%gY ,|"!Cl۲=i}"4`s14]•k?sk𳚪u[rTOP̥ 8iCl+ۅ" ڶ{8L);jOL a CDQ{vUyg `CDZSAKZ!6Q^MY{}eb\J\70j@=J|֐5hvЪcEvb[WDP:@+J%@cG_"t~(~@kp0%_.|r(\zn(CR#ht~AqUe7 @TлZ b%+lIQc (- Na>6)"sS AԘa J > Bڡe&y!bqV_`Lݡ8zۚbg/)B`*8?*C TB{,KH/3Xg՚z!81ʖh[=XP%^/p_ڛ̇ T=0QGж 0lE iYcXž:;ePϓj?$* * PJmk3@ԘC(ldl5`Aq= k?Vr_iPs.t˜1lP1ӊCݡI' .~\P1\>P Uw1J*F8g l4B<^FJV, i>+ (v/dZ%PyR&&@Ob>h%W)7`ᔕ,-S(We;nE CD%kQ87pzSe&WA|޺2@$ 7x*mY,"wb^얺(.JA b)l h1\@3x3(%*u{| m]&&hwcxQc f _p1'0B``fƠ(HTSwh0!m03rAQb#qATa/@9LcX+6l_G[ 1JL,MLoJV gЀ 6bc׫[+*hk͕zOE#Ĕ=| !6DqEsҒc_;{ȇw3|wH3 "\04 \0]45%`^"#J\C\@q !n;RNxeU/ ;L_p%`ưֹ!Zuf{) Tmiip8-<u=iUHX_zDh(v`ܞNusAt:-η8 J6("Q4`z\( L{}8L/D锶+Ua +:W=1(U6" бS6J– Qp؍`ZQ8]3%PH~álECm8Հ#Qnz"D*:"…83x(*-gpa3J_@ 3ie.ZB#hGh9nF< rUȃpz4E"xy\PxCP&N*8CRD\)I%.Y{e!8{/@> (u{8Je{a-/0fYB\ 2W8n 腱Au6 թO$@mͩX{({ +>Y$&Ņ Y40.U2U#~T u+ [&E j y[G 0[8t%ŧ)R.c-=uȘiBZ700 *a|h^ h cF B-YC-n02vksgem3Z(+5HHcV[]Ltj F s#!4p9;i'?S_^ض|Ԋ*,6mŧlᦒBV ((OE$: Cq >. Q*?GԖ"( Εg`ݷ셜,>#-|g+jl[_.pI(fmO?DyVi,8GҺVv~uLjN4ЊFyEצBq GϚ({kq *C7v@wb(qe>." (Bxh7hKz !GH3}p- 0 iCH B]$i@>+J*j}/L Г#όB{0 ڀCʜ7`JUЂ7zrro+i~|[ISA PDCNzw_@{Mnee񊯘JV|Q̮-\dQ6ܽo||(Wi37(՗3`pEIg+pSw/ nE.צ}C&3:mT$+ :W$ZNQjQs^AA/n6up"f]B\_.<쉻e{A}2 xu} ŦTHpE-x`;vAHRtqzV|(>Y,.zG" E^Q/M1C8JKb_h@ >̯l`&[n#7BqUЫ7|v+!Lm @ Ae,XVAol{Jiږ+~yLQgC䴷GHKsx54(>Lj"܋n l@UaqT) brOAVѭ|$odηgGMiTڠ8\!h|  HEMwuOvzg$BTD{G*d :${7w1(C|e0e: _`ǭƁdr@{QU177⸝|-Q7#7lRQ8#/rdZ"[s6[s:}@YBou"UD)]F U%E"Լ/Pe^s&!] |6H U{LX\2Iů9(' t@1c;D+dao0痚.!_sx'Z(m~hgEթOF׮Pbf_yau " 5^T ypE zr@Aɫ-+h>_v(Bd"| Bl[6^m"F_kr(q DCů}AEEj.?_x~pG|0Ni@YB(i}hjiָjlې [3(S(K̺9F@њөmXQBk7%a3)퀨 y y^ Da_ -2Jr@E#A!>.5p6} T+gq#0p >Ii@ A[(UB0^b^-g6t ڴ.1Ӂ8yn gF w2@#UyzC@]ʭ(B[bY@+٠֢lXny&- W=eqr5xE1r1fu+d]PBŒn -i 8P&`?@(?/pM1( )> |)f̲{Y>c{| j!a`&(Lx2ԡEѭw&p; *ȱx/ж__S)!|`_.04q*CQ|C9"Q+ "\1w09X qiC= _`NI @llOyڠpbi290 W?=]ghEa1W }*㳆ԮU1F^!3qcEvb[WDP- +bn-L+b%ϻpE(ΦX/iEY`w8f"`:r(\E!Pc -+#"ʸ
yW-X _>\ ~%jsr, o07븐Dެ`sH p}@lg7`csV_.`` :V?EջC?{!TUTHDpAU$jV(y{e eP" Wkuz^}]g}m5}?-SȘT#B?UL-+>mL'*s9k~+a{&`i5Pv~lI}5Xser8Lwo(G5J$+>͋>([62DqyȞ|}kxOb hScVM?'=YMv/j |5**~Nid>s_ d \ :{GJ!+rZ{$Uc/8ڽQhBR41z DC(LE%sv(\n3s(AJ֢qnyL4 W`UhN& 7x*mY,Fy*.8?.E;րS؂h/9u(} D(Q{oifKPeb7_.@S.xŗF5_>HcN8 F`"s ̌AA;QT`h}Cq`4fS窿"DQ~ATa/@9LcXbY`?mZ,~JJV gЀ 64!]4w4`ckE!uq.!,`i5(輰W$:(Ҙx+v"{/L^ 8*g  D;QA P8 "rtieES| /ÐrGB:;p/N$@:h-%"^Tqv| X>:`kՙRJb*csK **k` :N4*Tk%/=U"c4 0nBQ=̇]7D|3i=Tж%@Tb{|GY`a: L _qWLŨ kt^鼢9TDEV}!`TiA uq#p؍`ZQ8]3%PH~álEC}$WJ2J^zD%m@maӟ\LXqO"sRӐ,b՞<T 4H 5OӮi{8`U¹ 8Y^̇Yj 'p98Gf!±χ(}% 9ie.ZB#hGh9nFyr< rUȃpz4E"xPxCP&N*8CRD(҈1_.Z7" tc[/@ۈu{8Je{xvKb|_>`%E˺*Cpv ^Tgc9P@T֜<_Dk\&p!\p6f֥T&0?p8_~Q܏j#ೂCN`zwuCW[Q|o% Zz"^1:jto`NMU䰎EKo:nD^[6/!G[Z`dהH1lf"QXWjǑƬ ;@ 1>GBisv2Ґ18O~>94m UXpm OɿM% +QjmTGyn0o^BqDm( υ\y _Kl9腜,>#-|g+jl[_pI(fmO?Dh|frWB9FT۩ sa`nPg1t^h9;(Y$ހ]؎kPB(sv/'C@k(qaGYr@or=M_.p#>X Fz, S( ![-3 (gsE XP`|e|傈R}tSLC 40 QB(f\J.'"ߔ ū_>wWx|Wr,|~v+(fN.}D_2ş4cc-Y 8UoL "bD X8;AQي4+BpR|ApFߠP폊D @l(Fk&؝ Z9H/_΍ӨrJ[iU_f]B\8#K=q׹l}]BF8,r̃!곰JPEG@B;E@E GYʬ@g?cK}NiAt{ghSw\G wd@L&-gU13_q{12@ԇΌ|cx!PEo¹xѧm=` [s6[nhF9]=rrb[є.gS.صPQBhr!BJrR/ ?T0nA8AY]DE Jٓe{i w@7qK] FL(] UF>r3CmYU1AD va= J^1^J RN`;(C@+ 9 uh.P|Vl(zAb |_w!gH4T38@E]ʢrWl/G8z(rtF)m7dLEsi @meNQm(K̺9 `! -fS}1BcS>nJLf>>+*/J{o᥌ Zw-G6B|]jl>#bߍ\`~ J) 'A6)lmdN~@0^b^-g6u (Ę,|{/Qc r]&pDa@HLPA`g?QF RP}eʏ\dL#BJ0ho3v,Vd,m5}&X_.-2n#: 3Jm_6mkj}5@\ZĜ~+Pb 0}_HsdWW 9xD5>c&:g]٥g^XhJaYsJj0Xoz @'+H6Ch)39`s}]^[Tؒ e>o `/ܪsiff vѶ{o>)er_|:af_7j2*ȊvB=m `cj2e!P+3J]3 4\G"a!c`6} Y+ 2[1.4p$_P@UDx *^uGH4{eL| įd|\mASE p1@ԛlVi6=P+F6}]/0cnn"okZ!m a&Jݲ B"PB{,KH/ (-y/"XܾC+BPql/{W8/@J(S DEi5ô,L;n@s;NY6jEcDv<`v< E@PE`0aޠ8Kѵݦc}_+4(9u]a6iEФsГlsCoֿ<0ֿ L,~MyNPj`V! [{Hbc׫[+*ho#D=(1CḊXct^+ iIkOzs;}eȇ(vpTϠH^sV@(h: 2 "pA+Ng5(X&:w0ضZZvЃ.!.j,܋2x+PIJfAs܀/0cXGc:3QӽCikq:748{N=0e{e)pT>V!/`~y\ nsi|ܻnNvf{l=6@Tb{}GY`/}ehJ \S1v+:Wt:cZ 쉞UXl¨Ҁ%@ԩ+ߍpc7a:jE`vـJola5 xj@鰧FeO_Qݶ2ߖFa?m4D]O3DT ?ByBVwWDlբzކ+tVqU*tKUǺ7A*:"…y3{P 3B8e/%${.cۧM*T#>-mp4È "R۟X=qX"ipX1F}{1OrPD15"`%W}ep!*{wQTD A z1#~T u+ [&E nt<- @Dֽ"caBZ704y{傢{@ 7`a/ÁlEYz!i.#ے5#c$4fD6`bHH3 2rNFSt_ ^`¶-VTai(>%g 74Zn F@|*"ЀUXXV7PTr4u ) ۟#jFdEy.4DʳM[BN 5FOV6-/L(fmO?DyVi,8GP f;FpV0j+6xΎk8 tD97`6ToІ N*:eQ 8:^BluBg`Z&`57}β$`N|7.H40Ӏ}6WUF1iLLQr8%m4p, io=CJB V,/'"<G<I+xe_!r/(ʂK=݊o3ٵ{2}L0^s#Jߋ\TF]0#wHn/ADQ(ˑ19nPt{2e W\YnE.\g uHW5?Q[CH4>e3Ԣ#~Q- zq Ӏ<ͺ(~x<;{쉷 {1f_:z2/P=-p_tx : M_. 95sm..H~ Ǹ}!jWL T~@vȱ"4UPd%v29%}e\Yh@ >̯l`&ɢ,@_egY7@oJ,2Y!Lm @ Ae,XVAbg#*A!j[P&|yQQ=Y)jPl.uXLӼ/*d1ݗ+زil m"ړAB1nƽa~%?L6x%`{׆ME {e%v  HEMwuOv'I*PnK`N2~r_&g7[.Fe. P ܶF^74oP>VyO`F̃!ZX`%}O(=pDr5"PAmڝ"kQ2_P٫~}xkk9@UxWkm <8@D vat.pE %oS/V[%=_qt) o?ecށ0#o¶uh-P|Vl(zAbPL(EP`\;ev{R9z<ʢBI}$[" Qк]@M+4;D}\Pby7"fNum[0cc GSD6%Zz|@Tz/p_>`.x`:X|+jG`3(gߥ&ΦOӸ7r= x+ {Ffgfp X^z^-g6s ڴ.1V#{[</BZ{GL9aZ"4P8?o (qT rD?-`,| VmD>l_.qbazh/p~;ԽZ\]k^c4츻Yc`Vsz@_HQ6@~X-i\Q[aQ{8hwAJ~<@,GiE!zGW4݌},{?D9$UT/`:@}h!htk!ĕ}wx/6/ r,/ж5ٲgrlۚ\0熚\0E__>i.bNŊT/ A_ *:P> Ҩ93{sg.6>۳ ` n G/&Yt:{nm~z_0WkHW ?"Ƚ`l\m=5y@rO= tQ ̾nG|eTP<6T|LZ_,TPBJm0齀Y?c~A$zFf(ڍ,uxcL{ !ؓUg e֘Xc.D NJ.Ķ"B[(Vr[w WJ~w](Cc`6\EX{w/P_>bo1s 2[1.4p$_P@UD]\v4!`%+xL|įd|\mAS[VOM:.$Qc7+)\+m( 7ɫc׵23fPEջC?~ISq PLePEn;Mve,3VZT:[mb5jxRjgEB?UL-+>mL'j_{V ޳0K{b_v~lI}5b/逈B)ȧy0_@)乡b]~Qld{.D~.L{b{ǜ:ݮ0f Tu̴"Pwh9Ajl{/jm֕ TL#Qy W] 4B(T݋>T9PY X5b! hBHs=5f!\a{偨dQQ6󊲘-Xcz~n%QZ? ^TVԩ ro]  ,V{eV^W[ o 8A 1-xr-F h\`ԡ|D%_0_".{vDi  ַii~k04y#94-wc503FQECP 1ǭfShM[5r^J OkSX`!`_.~B_pa&&7:A%s YFv`kiC^rz5`ckE!s(E#Ĕ"d>^t6nHcNZ{[J{eQE>4 D=U}k06 ߩHS 2 "pA+Ng5(X&:}7\oYy@+B`n}>z0E{q"@&/|8?"^Tqv߿Ay3p(6D)OR m`NR" 3T'  :N4*x/8FC5p0ﮛ iq>IlT%@ R{,0 ѥ/pWLŨ,ixEN}̡o3 QX=x04 l u:N8(q &e*ՀB]2 ؓ(1zI|m(~[n4<ŞVt>Se;v{({.4H 5OӮi{8`U¹ 8Y^̇Yj 'p9_. 4(*-gpa3J_@ 3ied z爠 bH>fpABXA X=qX"ip{j.( OC@8Lvt'\}("~ !"roEt55yo#JW(VE^ -{=9ߚ)5lT zAPܠ:i'T ~<`.DY[N2*BPh!(aZ/F?1C 3ÖI"^0![qDup!>Nzwak鉬{E:z G痩*_. rXG/(Zzp&ز|=;xp_;5e! ]sC3Z(+5HHcV[]Ltj F Pz}0-#>G ecZ_^-Q+ڴAD b Nv &ʷSPfqe|W퀊e2<DZ[BN>FZ*4V=.c wf༘.B%{{_qY%38 0ӨYs%sZ;mEfP Z(f?ݍ;erL Q #pJڀiX/0 QB(f Г|[I󳼜J J|8Nzw_/ 3@Qw=bvm'h @u/*(Q|/s_1W{F:667(՗3`XhDHO "z4軑/;8oPGE­PxE)5P}&J[iU_.f]B\_.<=a/AG_`+Ң<1z2*[\@0y u_>/(rjnq$`?c^Q? Q+R Zox#U  .6-F (m,iKE-+df,z"]V~usx/qUЫ7|օE Lm T&΂@lD+ƾy6CAJP&QQ=Y)jPl}HKsxU'|\9^W~[6 0`p R /ĸU5[-bz 2۳Ku2blxam@.jҽ=~"ô;#" u;rT!'xe~!/܁ܻ@傯j9}ni4A1.FW(ﲗ(pUP*o;ED Y }lzNi{FU>Q >`8 e8 ?`PdbL&Zbw?@vrA1cϨQ3O1zMos9"xѻAWӭ9-e4\ef 1-hJ!Tfc~M^ 3DHq_Pe\s6fU.~KƻHX\2Iů9|AֵƻڦA,)a/5\x0C'>p;>|hgEikk9@UVk Zs5>Qz7QAzN Q6ClrWԋ4VIW]Jo@eB# ֡C@:(ˡb`E\-/c-vEj.?Ӎ_>p> +@0Ni,!c(pN4DE@]jl,[w"x.1GkNv$` @ B4l㷲"Z *p_0x[<0 /e(66TԺk9BRgݧOLi.<SANH#lR :(;YTc5kE .VDX!"s}ew[8y_zL`#&@0m_Qe(7(qĞVQ !?-`,|{62hۥA=Ei D>"`c_>^ݡzY?i>c1au3m[BևPBŒ(=>rxl4 J\@1+Y*BJ0hʷ{Y+26sH/ P=|@EѭwWZ}t >wD9ж5Z+KYo0ToZo0t[`i.b?#Ae?Coڴ-:(\EiԜ䎙{s}g>0m(}g+)bݖ O^ 1M&0c9peuwn~y`jݑ-wW ?jE1iCl+ۅ"m۹Ô2bw:/0UxTP<{FR01Mj_.,TPxe1`FiBMY{a }\B,P䊹0{ WJw}Q,x*.l:,;}B39`-[=(kE? SH@GŹTEw5_lGVB_.7y@J)4>Y@ܽ`n q!!3 DYIZhvheEYI^GsܾU1Xz7NFf5(B눀 ɼ+3Q=\B4ص̬ۖ[QZ^jMܾC+BPql/qz7\y: 2&CJÅ~R[Vh[}NTr"ô,L@s;NY65*^Rj[ØS`@P6~Qld.=\/`sݦ=+FcPfO :fZp;4cD]l[;:xePcnP|@U 42h+W] 4B(T݋>TY Uc/8<W\)uN'L4+̔\,>ʆ4BSDYŪE CD%kQ87pzS& ` +֕"QN˯Pn"`%_`iQ+o)D#5 1h1|f̜:>b_ifKPeb`h <7<p F5z[i hX$6c1(h0* b9nfroY뽡_ZTAgBʼnD|tVG<@, |zQmV4 az(Wf +Q8D)OR m`NR" 3tAPiPX\erc4 0n]Pp1@t:-η8 J6("Q4`|Q~cr4e3=TE1__pTDO*)YUp:uE݈N8(q &e*ՀB]2 ؓ\ (1zIݠo?ߖFa?m4D]O3DTsO0(j.i`Qi9m T87g>e_p |/Gf!±χ(}%|\4ǶO,  Q>fFh# ̥:?pz4E"x|+,< Ae2;bs _'`fg !"v5B` \x(_) X' ZQݲ׳iyRxF rZ:QcS؃b?;5"`%W.xp!*{wQTD A z1#~T u+ [&E{(n!BQ";E݅r' [ G痩*_>䰎_(Zzp&ز@|%k j02vkCkf"QXWjǑƬ ;@  `[FHc>D0>.F/lB>jE\6So`~pSI bZǧ" XL0o^BqDm( υ\y _}k^3WA|xӻ3YAQp^U( N/x%`/cD_0070k1 "Qc^ѵB~lsVRsoml5 !9;݁s!5N0,[5 QD-xe_+#!  49µ0L4jneI1Ďd DpEﳹB0OkҠ`0y Fv!,io=CJB V,/'"_Q 0  X|ș|@Q]j?fk '>YGLs#Jߋ\2Qjno2c8 (FT_?s#}]pSw/H]J-w2Mg uHW5?ѹuH4>e3FVPЋ[M,\x۬W8#_>?9{m^̩U!.ă/}iQ_@q x 2QGZ|`_>ȩ˻U]tqzCԊq!+^HAB&c/M1C8JKb_6^-h^!6_LEYn#7TYb"*]!?-PHT&΂@lD+ƾy6CAԶ\LxGYD_gqA!r\Zl(2w7>QEj{2gy_UX cE/{We" sǐ܎*EPxUٿ&0b7EP XA|{vt ؔ[LPl|06 AGWt~5P?Ra띑Q:L9sk?t|Y}TbPVe^23> ka}ܛ6Pz >jE{₊D GYʬ|Ageϕ]*o聨{KG/(Fy!q{drA& >-U1o{bƮQe1>l[TH4Ƌuكnl9|:= !]!]!ۼMR~6:rw3J1ߋ&"Ի/h(.t=7 ؃HlOP)4]DJAOZ(~=מ|-KKŌ;_`0:xeFO\PڭSMUF>r3z c.zU Qz7]Xt] \~rAA۫9ԋVIW] o?ecށ0#l[6^mgņrD>(ˡb|`﹃xykإ,*W{i*~pO_G 8kݣ]Pt@sJ{e @QlcuZ!*Z ml݉ ڶ>wY7=Z`v:յm=X*vSb6q.Zz|@Tz/p_>`.x`:XZlt)S]#bF0_p%@C} 62 'N2(a+*Zα5"p`S>" MA`wx\s6gmB9ݫQ hDu"4P8?o (qT rD?-`,|;V}@|v6G[\@߽,a-WZ|WA["(3mܰA%" 3B`uvAGj} (yrׄ}!Ṙ+n>`eA;!,!1EUarX_>:nZdZG߯]삨 }rm[mkrjr}5/9+>Pb<0}_.H CbZutG~b]ZF ff vn"mSmĎZ7,L a CD~Q]h{?nH3ӤAa84RjO"42En$`Ys`kܧ8>kHz\Psa4T;RhUȱK@;ȇ+P(\17z@a"XM/xh-N+7(9CW[ w(2jL!`p$_P@UD]\UdLePEj@Ym_fEi> p&n_!I\ܾжz>>-V1Ey:y 2&CJÅ~R[Vh[}N6Pa=iY l_g,yR_@ v6QσJ$+mGqb{.D~.} 8\v1cؠcC> BOVg]/ PcnP~\f✽^?8B_DM۽#@%9PY=ƪQ ~\@*@Jɭ90 3/D%r!Д\^QskTMٛcQZ?~?ӫߝ*00Xk_ r ^~we+2K+ (B0[BoCLa \@x/9u(} D(QɮSPHm20 m_@SxoQ @Q =wl DptVG^bYsՋj9nS\ 1ucV(^ ɢ_*@a洗TTОp2h2{8 *`R0_> nsi|lD .}|6*ypDӀ=r,0 4\S1+f^鼢yEsGeOBݷc-=uXXG̩*_. rXG/(Zzp&ز|=;xhKP)FmLV$ kJ80Ҙ_xQc!<^#!4p9;iLU甀Ƃ?m[G‚kQ|J n*i \a@R݁TDyn0o^BqDm( υ\y S 3WA|{qŬ(Vi,8GPvjv~uLjN4ЊFyEצBq GϚ(5'v\BED? N*:Ⳏ QD-{A_p#>X Fz, S( ![-3 (gsE Xb=?[0Ux2@D)>C)in99gB7S\J.'"ߔ ū<yI+|X=@Q]V|Q̮-\dQm3(Q*+XGŒ\ܽo#Dňpwtۓ)CD?5~7+`1q%!6_т3:mT$Wl(Fk&؝ ZQjQs^\/ {.: X ۬W/_>=a/AG_`+bs[T=a@&(\Q |6X_.P\*.H~ Ǹ}!jW8ZPA덐w PTCAtڥ_0X8seKE-L0('޳}}-fGn+ _p 25zWs˷61`!?E.Gy6D e en?"e=h?`d |ҲiZ܀"܋ Dp_,!~De¦QM`~%VoFX. s=;lJ/ZX/,<,ۀ! Tzk)wgô;#" u;rT!'xe~!/܁܃w1(C\uQ?3^ ~_`V|Q^%?pefk@Qz+/BO}*W(BT)T$lpn?.`sJX@|]unIǓ9 e8 ?`ǭށL>p T D$~xbƞQ1>tgb#* "xѻAWӭ9-7cNXActA|ѥ,v#P>'Sfc"`:rh5V(>+6C= A1^3D$*;XZ-L|(m:YTnNZh(r4F)7dLEsih >@meNQ϶uW%fݜw0/ ]k3>*46Uc4)QTTDwosx|]͠{ [~gd@Lu&(B~rDa3fAFT%p%>^-g6pz ڴ.1Áv8yn gF s´#D~EipPS%ȩ*/^bpŲ|_Z-E8x;"Y?i>q/Qc`VȺP6pDa@HL>r,QBpMhQZ@QHQM6c/0˲ێ ސ\߷!`\|q"C;B+>Dhۚ;# `m!z|zr# Msi_Y *CQ&~ԦŨ-l(CPsa4T;RhUȱK@;ȇ+P(\17qOa]X"XM/"scvoQ(r/CW(\{( 2zQeԘBj}8/(}*.>4:`;vr&WNa>6)" AԘa J 6׊D+/~EQnW"kxf mQYmMu:"B2zLePEj@Y_@QZ #x/p&n_!8uVǸ>f O/DdHy|OC*ut mx4{g5.0(7Wt ugjxR||b/逈B)ȧix0 R(ƊO" eF(åWǜ:ݮ0f Tu̴"PZQ=YMvlзPcj =n]id>%+JmF ݋>TY #`{1hBHs=5f!<ySV((Me1@T Bh ENh,l5[WD9/b/(XGߥo 8A 1-xZ/{3(%*uw|Զmz>/ 5pZܘ+~{L55`hIlp1'0B``fƠ(HTSwhCq`4fShM[5R}SJK)!P0Ә8w0ĎC|` ?Y2;n -fϠ;AɊ4!]/9vvώ̺\Y4P}]4@9BLY1!AC1:/lNg4椵'Ud7krACӌL^ 8*g rA$ <L8<$0 ضǿzY 7#m- Ѓ.!.j,܋2x+餭^bYsՋj$ϳscYߍu1ucV(^ ɢ_*@a洗TTP.` :N4*|/`mq{@i|ut!vJ6("Q4`|Q~cr4e3(B9TD= y~F-AN]Q~7b|NqLT+ Tz[X (lw8ՀaO #Qn HZ,sf;NL{Z е;CdNU buyES_Ұ" ,"gi9m-F)t>@e_E5P")g(*-gpVJf.cۧM*#؊} >fhs _Tg.Vx@! ap{j>PQ 2qR ;<J 1+8QF1v+4`VpjK {wԻ +XKOd+2Q+{c=sj D9ua/܀0l_>g/mZ)FmLV$ kJ80Ҙ_xQc!<^#!4p9;iLU甀Ƃ?m[G‚kQ|J n*i \a@R݁TDyn0o^BqDm( υ\y _}k^3WA|xӻ3YAQp^U( N/x%`/cD_0070k1 "Qc^ѵsv\Q#JIנ2P_gY0PDC]$i@>+J*j}/ "JadNI0 293D ԛ)BO.^Nm%j͝o+)B`*(xE0I+0!V(ʂK_gbvm'h @u7pD_cqepuB667(՗3`ps#}]pӽd/23&D1+}@ re|5_>@-O(=0뵸~97^\p96upCpxl._!./<;|쉷 {1f_W5|z(Oc/nJpE-xrl/P\*.H~ Ǹ}!jW8ZPA덐w PTCAtŦ!%/h@ >̯l`&ɢ,@_egY7@oJ,!Lm @ Ae,Xn `>omBxyLQgCLؼQ-}`dOZ6SP{D_.1aO6u@_>WBlfUJ 2۳Kcz%v19  HEMwuOvzg$BTD{G*d<:$x@nM[@0|m`>Qiܕ4@18r}#ʭ >,BԵ>JMO(=pDr5"PAu=EqAE{,esWxR)b"cרrz ޒ: _P0CVbuM&|Zb$}˄  ny CߌCl ]\Q-'bj[=+֜M{|[]rrb[єWV|`F 9{2Cz< _:|{Sm  7őƽqHX\2Iů9@ړ/e{i w@7qK=F ( J[]Њϊxkk9@UxWkmY PCnLt"Hc8Jz Rvŷ1{>0#֡Cz@Yr(}݅!"PEP`\rw'^E^La+ !S(KoȘb" Q8,֝>m^Q|us٣5FaS]XQBk7%a3)킨 y yDwrxoqsſ\PQfP=P2DS]#bF0_p%@C} 62 'N2(a+*Zn(M\46KL4szr'm؜!<.`#&@0m_Qe(7}9UE׻wKX,9ߎ_.nr@=++0W>"`c_.w/fw;E"`յ_i>w/Qc`VȺB%k0cm $p[ &(q GjJfZP{ʏ\ZrV!PR}pES̲XX#@ԘC¼`ې0_uqCWZ}t ^w m_x\0۶/̹/LWhKkSi,j5y`\P(y^FyO޻/uٞP::cm 6v @'+H6Ch)3v0 W?\g?pϭ j[|hlQ?{AH#^33@Q8@n"mSmĎZ7,L a CDQ]U iog& GB )RϧfmZ%D/Ȭz_eђ`Ղi"{r !rAk̟=X%VQ(zBJx rU}$Bxvzw= *l:@kpZQξYD|r(\E!Pc ]hH4:8rﻸ *]-ikLW iYhu q9MFw7u\H QoVRV$Z!xQ1݀$YG/4,DEջC?~ISq PLePEj@Ym_fEiή{5q=AYܾжz>>-V1Ey:y 2WxQ=0QGж 0lE tDx l:`CVD)j0E f"`Hb/逈B)ȧy0_@)t/;]& c4_]4?>5JsQƌmL'=s~\Pqj n]@U 42ĺ=py` xt~7BVBe9H^#Dq4r~W<)uN'o1L4_KISV(׷bNCSryEYŪs(AJ={AԺsf& ` +֕"QN˯Pn"`%_`iQcWſ">#5 1_.{rS>:@:Ō)/z>.{ 5p2Zݘ2+~{L55`hxGsi0Z# Ƙk`f D5uC;b)0)VОG`kc_)Fo@i{)E0fS|'ހ` yY2;nxB4`/:Y9Հ{v`ֵB؃i`ObsOA10D4|5F "l@Ɯ7whC4c70ŮWJhAf$ z _.P1~|eA悐0ض_i{~ja9{#J\C\@q !n;RNxeU/ ;L_p%`ưֹ!Zuf{) tn$ ip=AUQAu_#x=h[+{8 *`R0_> nsi|I`tZo^`1Mփ j3ANU(vy_.pwo~aȑS?bW4yE>PpTDO*t, BҀ%@ԩ+F 8@"Ņp0l@7PHK&{qÞ"FT/= m_@r(짱 v(k vȜ@4(qՆlS_Ұ" ," @բzކ+tVqU*tKUǺ7A*:"…83x(*-gpܛKMF hA"sU G(rQ G38 y@H}7b biދE+,< Ae2;~-8WuR{f BhE(еjlkFůQZ( {Dn9y9ߎ_0e]!ޮ! cl,"SH ښS+@Y}.Q\pE3RE*nW&Ӿpl?b(G5P̰eR~0o uCW[Q|nR cOA Zz"^1:jto`NMUarAT::@۽ 0ѰƖ/!G[Z`dהH1lf"QXWjǑƬ ;@ {M]n9g'#JXm UXpm OɿM% +Qj;PHTbY*n0o^ДOe2<Ds&Xv~a{!'H _ي'B+ ~0=ZWB9FTG/QhEƼky츆gMGxvmc;AeC %n{DYG9] f8-iP!}f>q8aQs,Kw(~ࢋD3 (gsE XP`{倂"JadNI0 |4߷!JL!zr,/'"<"x]W,B^!eݥ n7ɥO6ܽo||(}Q(D`7pdL%HO "z4軑\; eQ(pk ~6>(^hh9}fFEͱGzpZ(maS W!?cuQ q13xv':L@߀z>j򴽀A)A2QGZ9 cw!`]tqzCԊ@Jρ cq;REi(СK:bbt̐ƒXl}2Ff,z"]V~us$2"*]!?-PH2q,g c.lE`f]QQ=Y)jPl+Bp3w7(ǯƞLYskVB{^fd_. m"ړABtX5k+!z3Z*ty%`%`Sz:ea]_>?;l}6iP3) ַ(BTDv0 ll?~L[xJw Ⱥk!NY.:(We/?܀/0x+kY x u'0J5~(r YX/`%{W(]\Er;ED`?(Kun90\Gn 9ȒfBi l0@gqۥQ{EަJ,{ႨJm0 ?P2 0CVom|j9DZz/(fm< Fqԇ|cx!P]\Q8#/rdxE?ݚ rrWu@Y\w\w-h_E~3Jȱ֮d)5˹ J1ta_.~ xo1>ip;r2j_r(O-BX}S==2rή>)-`ZgZYQu_>`t[PbZbmDp(f׻|]Xt={b{g"^J RzveV>7Sf!Duhk,.P|Vl(zAb |?w!gH4TfTxk إ,*W{vn5'^E a4.@Y4^ùb" Qz}VhlGw"x{[xE]by"fN.` @ MX)1 xFiZ_osx_>PQfP~KMMwB?d@Lu&` \ P8uR l pd*C]Wc5kE &VD\%&pP]0|؜!<,>ZwGL9aZ"4P8kPT/[bYvw^+xEi٦ afB9{wY>`vzO][Hfr[Qc֭abu~,0cAHa-NFXf9H}^Bm/6t< ~!Fnk~i@QH>Qcw(ΕCv4Clp>p;D x倊c!WZ}u >sD9_>-*mf|` /҂ Ĝ/ 1GC|"Q+ "\1}o~`sTױJY EpsC0XozlOyZ眬" 9~wbn= •k޽YMպ-9' YO_^8q?P+҈܇BQ8@.@mpR&\ F|`nD|yT6Uyg `cn\@YȩeZ!6Qj~Y?c֫| "b\>J<3 0jak"{r-!k@k̅ѰWLorhFl+(Jg(VrP]U1{lkvV8n< SwŖk<EB&0~@5ED s_(a3_hq4H%E"eA)CД4 8xz<cBB5fla%[_!ˊZ}1x|]ۀ$>NrDf5A϶]RTpT0n!ޥP %o,!z!:> EAyQjw`Ƞ:s(C*ut mxӉ\Z_p XZ(u9) 0E!QQT"Q%Q(na*yaJ{61Q- cn4 0i}k `%1N+mL BOgLqm<|Pcj =^]id>#+ĺ=py`_c߽#@%9PY;Į{Ʈ*@Jo'L4ҞWNYɢ\9 MeqT+"*YyӫǛ*0p[Wޫ+D_2,+kW"^~< b/xwp{S]D%N1Զ=_F@!^-&Fk04yƜp;Eb1v"QMݡ(h4<:l1pW *P^J rǸ!j7`:b97(~$80_f-XST2U;V'+0X9:?Ovώ̺\Y4P\4@9BLY1FḊXc4^+uE>!hcT\;rACs(NpT@rxA$ _@ р,/( 3\5,/rV|D)s `Z! D"L>g^Jq:]G\<@, lzQmV4 ajs VY RJ[3PNCHYlUEFp{ S4L}BJ"S%8FþbNm=Ng[NU(Ny /pe;r4^#'Q^鼢yEs܉8*{'`:}!Ҁ%@ԩ+%'v_+BP\X+ m V 6$`O6nr5tS#CĈ'AT awn4<řVtSe;z#TBVwWDطiW-*P.O#B ,(\h8M/Wf!±(%CcX6I檠O b+΁t!0)}|`^R?*tQɑQKɱ4E"x|+: l~H /s ['`fB+Bp ^D}&7QRnKGi,b/7rA1 s_.0e]!q^T@/sVN?*hkNEJKF,g1W (>dU2z1CP´^Dq9xC݊m-"DSņj yGG 0[t%ŧ;qR>]X Zz"^BZ00| *ȱ;:P^0/#S!Gd )ϛbٶ DkE <_YGFbSo0j1v3 2rNFStM/T腽ZQӦ -T@h*%DBVaaY`(>F"`Cњd!*['ڲQEQA "ѹ-Xv~{!'o 5FKV6-L(fmK?D}Vi,cGPs#aԘWtm/9;a(#JIqנ2P|t>N ׸Qc"(:/pM/(Z39_p#>X FVtC\4h`}B0OkiPتh\4p[Q(`PkYpUBC TI||4]Z J O4Ptҧ+ ,]P_p+, .m fNU3ٵK jaxE_}G(r@EsEkP?{82&G} V视^s;H]J_1:m{T$' :W$jj9}fFEͱGz#x~J[8iUȏ~cobg8=Ŝ}mfxuBF<1BǮ(MpE-x9U " CJ1 P> \ Q+R Zx}"U  $1:ېƒw%"}&_LEYn#7TY!LZu@YVk\zD>FS\=p.)PQB<49!r&R/:xAH͟ -h%o"*Ta=3 bmr%Ƞ>'-> g?y[yw$Z! !8g `0:}DF9O o>Ulz0v2@UxVk}cXUDj( `ݡ %oS/VзJ RmN`1Q+C@)3"`:rh-&P|Vl(zAb DA%" "˷]ʢrWl>/ծ(rFQ(V%s.6[" Q: @M+4;D}.1GkN6$` @ MX)1 8FiDWSUSձx@Tz8LL</TԺk9BRgݧO[q>p^2+ ꋜFHgл x !Jϔs{M!ؔ@i]b1? >/p3D)z;b~Uo HT\xbη܅_.೵(-4![ jgq4Gq~틉ݡDu-+["(3 ~?07l(PŒ!䇵83sC c9# h(2ׄ R}̇+N`eA;!v6@bs>0;D q&B k{-1 *ȱxemPiWS1`H>2`ķHCsY,>XK!F8k A7QEXgWW 9xD5繾c&z`sTױr!ؽ=ib>x#C-g 7tt:>bZutGi ?{jE1iCl+ۅ"m۸Ô2 (55z_$`ۺ̾nG ]>#~VZf>JQB )RM"њ/Ȭz?eђ`^EuYCje*֘ a+ۊ|" RYXsC_oa@٣/D_a!jE>y5` `᜛Es{sjb˵Up!P@)1XFPQ{D}|=e+Y!` 0]/WN}\w#C:&$QcQVRV$ p_( ɫc׵awt[`aV~[l="jL8h3Q=\BJ>eYB:2C(Ju5/=aLuEg<cK}h@^/DdH}x|OC*ut mxӉ\Z_p XZp_,곤2`Ӏ7sPګ! eF(ϤyڟIc^+4(9u]alӊCݡI BOVg]lj>@-TWWPU3Gq g/t@^!خ! S_&@w/P d%@N+Tj(\4L4+) *Y} i "[hLMxJ֢6M&W6Lp+T{_f?/,"MDG'`Np|be]/p̩C ! FJgKLÔ0_"=&6&~C(y+~[L55`hIlp1'0B``fƠ(HTSwhCq`4fShM Qs츟 ",L^ 8*ige$ pƆр~*{Af0 ضſ~hEۭGB:'p/N$s@u^bY`sՋj9nS \ 1uޣcV(^} ɢ_*@a洗TTP G*g8 *`R0T(Pwb4`>Vt:-η[/0Ә[gpDqӀ=2,24W|TɲFk!*~?w"ʞ Xy?M-AN]Qtp,ڍ`ZQ8lgJA:/<\ ((1zIlC(sfӟ\LXL"sRӐ,b՞<T! +»+@ ۴+rZR}562t~!B TANQc 8]/Wf!±(%2q&\AAl990O׼ ~rUȋpz a|ZCT|E!LT&V ['ׂDH#3tZ" tu5L&JWm(VE셽Fb_&(aηfYB\ 2W8n q@u թo$@mͩXɟ ]%g9h;u"֋b$mG;>+Q m-)i5nՖ@WDB~uIȱȺWd,vG̩*\/D9vG;bp&qd r=;x蝬*)ϛbٶ DkE <_YGFbSo0j1=LT%]cZ_^{ UX0m OɿK% +Qj;PHt/4` c+6|Lv"Uh{"-EQ< +ނe[N+z!'o 5FKV6-?/L(fmK?DhL@ `@ QOM/l070k1 "Qc}N@bYMGxvm8Ae|A %qD!eQu>__(Z39_+#!  4µ0L4jeIBnBhi@>+J*b\PتQ #pJڀih[^/|z(!CBO.>N% |GISoJgwЊ~_&tҧ+ ,L+D2,x ?fk 79YGD_}G(偊>>0#O{ "bD X8;AQɔ!VxEΕ({̌g_A`ANjAPM;m;Fx `H8iU}_ۺ(~_| <3^̩U!..@™(O{ r 0q+82@Ss=w0 P> \ Q+R Zx}"U  .E@ c;JK!@Zp?`~e3QN}f.+?[̺y |WPe_!LA ]^ XA|{Nt ؔ^a_P^lc@.j}=~"ckOF"DE0}v̩B&OuH@'?P4!{9DC) " Qa Ҹo1ip;r2j_r(O@m%bvV>a/&R+rz;.V|VT }vJ»Z;h=|ۃDj( `AמW_.((y{5ǜz*K;YmG }o,gCmˡ[X=P|xk7 "[=.eQګwt{R9z_@EY~QJPs=U0"u, A40^Q|usWLCz_36fb}ThlLi5J jBB-;ki` *jݵ! o SZ-u8?p_z+ ꋜFHgл x !JgJs{M!ؔjHkӾDc> 8yk1ZimG*@.[%ȩ*/^bpŲr5g­!J-nls{̕}_eHlxE{r1s{eo*# 3~"ǽk0Aq7V~}>Bm/6=r(? &ɘFc`>\є0,Vd, j!a5$LX//-27ZGqW5 *ȱx_.UQ f9~)974S`]A-~sK!F'kqAEXgWW 9xD5LTug:w.@8iE0cm 6vlOyZ眬" 96ber3v0 wM@~Tؒ e>{ jE1i|b92EpM/D۶q)erM/Qv&:Qf_7Σj^# ~VZf>JQB )Rkq@P\7%HFf(׫,Zk\ l%>kHz_.b0 )*X$VQ(μP䊹R 0b³{;1DGq6_."sc,P /.(\[( 2zQeԘBjht~Aq Ue7 @T{+Y!`0 /_:qvrߍ, o0또DD}XIW=BH;}Z}1x|]1nn"okZ!՞."B"x`&Jݲ BKP %o,!$Xgg՚z!I|Q\&@8?xX Z׌@dLڇ̇ T=0QGж 0lEivRp~eﱙսn{A uN%`?$*,逈B)wØSɓ\QcaJ{F17(g|AtgX@J' cEnW3:۴"PwhgsГlA`Bg>P U#J*F8g lB1<^AJV, c؋y(?/pW  mb֜Pr6EWِFhJ۠(Bp@'nٔ!782 UA|徺2@$ x*߽/X,"wbQaӷ< b/x;F_.0sPBQ]Q?Vcb`8 / p F5z[i hX$6c1(h0* b9nhrc󁍈hW$:(Ҙ֞Va >K#0ũWJhy 3D=/pƆ р`iX&h87:]-,g_"JZpy@L8@A;RNz?"^Tqvz_p%`ưy!Zuf{) T q[AUQAu<w+g8 *`R_8FCacy j4`>tߺ :{F%=("Q4`z_.p[rAQP`s܉8*{'`:}!& l u:}N8}?[X0Q(]3%PH~àlECݗ}>\ ((1zI|߶mЏ%Fa?h,?Wj"sRӐ,bUod@@HÊ4n(P6 V*ܛ߀X ݲ|DPUAuE q3P 3B8_.9}"N7`%Z>Kh&h ~rUȋpz4E"x!*kcНIeGw;N:@F A B̝^M/dgjkyMů쾘Ü85r>n9z'k FxMyތ̶m`&Z+nJ80Ҙ\g7SQc!^L]^9w'#JbbWu`[G71D)70?[xrUt1J-vJcSN²P}zE5.CT mOe2<Ds[[BN&-K1Z"n\0;0-Z WB9FTS  Zw(AaԘWtm/9;a(#JIqנ2P|t>N ׸Qc"(:/p /?2ZiPmB3صBZ,\ La}+sZ;mEfP =U'O'Z((MI!*}zBS\|;JQRTP5ZL2>]W`_!r eۥ_gbvm>'=PǶiv\1 8UL "bD X8;AQɔ!VL۞K~iKyA`ANJPj[ :W$ZN߲Q O(G z'GB~cob3r;bN; q!^tk}`SPA<r@&(\Q _>=XO/(rjn1$`?x|!jWZPA냐a"PAqo@gQXiKE-L0('>}}-f<#$2 dj[aPGޕV2q,gkm`ލtR " Qr2GYD_g9m<%`G!{bDX cEMI|G6 0`p <9u\WBlaUJ 2sKkz%`bK.j}=~"ckOF"DE0}v̩B&Oe~! @ޗ!NY.:(W森sg|[Y|NO?`Dy2{yr/Ba\P}Њ4@z_x(>Pۃ,e0@gqۥQ{Eަ*肨Jm0 ?Psfq]x82r.P%˄(}0;x储C4`< x֑{A @X]rU !Z@uWuWk^?xKvQBvE 3DH^Pe%V[5h- vAw{B ׻0¢;}!(K!'|+r  +.Vf20# !C/6^caubC9 "PE1^~f|0P{*BpRzg@N7|}pW "G0Z(e2EmcO̺h>@M+4;D}x}~D 0 ;m]X*1zN:} jBBj9@TzpN/] 4s*jݵ! o SZ-8x/r] X:WN!?9 "3bϠw6' PB0ÔU(M9L46KL40a'Ͻ9CxX2}s´#D~EipQ(qV rDu?-`,|;|@37fMb9zr>Zl_/pD6M~:H (?pM1( )> |)afYX,{#@ԘC kH z_/-2XA~WZ}u ) *ȱx_>E:湣,/ )Ur- _0.-@{X\0}*:P Ҩ9}:g٥g]~ 4"SR1Ī}C{g{:dEi`ϱ#[&0c8pta:{Vd]sCZ;xO_^8q?P+҈L^ /mS (55̍s3 ~XZ\B[J+*f !<;.CԊ|g^Z{o])iErtb˵Up!kE? SHc8/(}* | -VBeIJ!- N};:U}Jvq~y(\DŽ j J Bڡs{1Z5so8{{ 6< aE*yirޑ0VGhJzW|"`%/(ZGߣo 8yA 1^M/۱_/(%*y-1 S~{> nZ+~[L55`hr#94-wc503FQECP 1mєiL 6 X8lml+HK(m/@9Lcc5yA i/) *GX *Av`kiC^rz5`ckE!uPi>`@8:^46nHcNZ{қ'4 q",L^ 8*ig p D /pƆh@r LMX&_>P~̯l}>z90E{q"@&/|8#.~E 6W6+05\JaCD)OR z!@,؃y#=hV)pT>V! 0L/8FCacy j4`>[7N'Q{- H< ؃D( ~VEP{‰Дj9_.dt^=ض l'zVcзl* 8[DN^'v-V.Ꙓi($^2>&WJ2J^zD%m7r;7~ڧ=řVt->"DT*!EYĎ&<򀐆i`Q`trXpo~bۦ3C@TMj 7p9pg=ZXP 3B8e/%$TTkmA8` `6pD㱏R87D0/A\8A,{8^/( OC@8LvtI (҈1l!8/HüN)Mů쾘ÜZQr\`%E˺*CkM/*C9XDN+T5"`%/@{,\ (>dUeb$mGVl3"bCz_@wP8:jY¥-(>" 9Y}95UQANo:EY~hƑ!{v;YC-n02vkfem3Z(vWjǑƬ ;@ 1w}0PWLc傱u-/ F/콿|Ԋ*,6mŧlᥒBV ((ME$: C1 >& Q*=GԖ"( \hΕgo o 9Y|Uh1Z"n)KX *Ŭm(/*MEE )fz<~Vv~aY%>0#O{ "bD X8;AQɔ!VxEΕ5lo#-t) /;h9t]HO5?yuH4e3Ԣ#^<?-4`*䇆pxm]B\lu9z* 0{{1f_W/:4x&޶ГEy*^cl][!P# M+LQ<=}\ 0c  c<P݀ZPA냐kPZ S 8K س (m,5lKE-L0('>}}-f|r.?̀/0x+ib>^C](?Pfc/QBz;J|Z@T*GYʬa>K= MXXQ >` EP38n.<L>P,ޖs*آ@G1a/D}8e9\H4˶DN 2 nl9?\ef}>rrb)!o/W]fc] RjsA4b~!] A5\q[Ab| ,&W" s"@kX_}e[i w@qK F_`u[hgEiѵn9@UVk ZE`R}T!0_`AϞAA5PA۫9ԋ4VIW] o?ecg`w֡CˆQ@x9rQL4Tgp/c-vEj.? /~r:Q(V%w.Z!TشBcSNQoo(K̺9A@њөXۘQBk3%a3(QTTۂ8LG -2J@E#A!>-5p6} T+E 0-RWN!?9 "3bϠw6' PB0^b^-g60z (/Ę, >solL`#&@0m_Qe(fJ?Rn@bη9k೵(-4![ jg8x;"n_`a> 5fxoC9 Q=+9a m4(b O)Pr A2E!GW4;,{osH|v~ rVE[>sD95wjj9/ )Ur- _0.-@{X\0}*:P Ҩ931Gu+?z}{\YsJj0Xoz @9'+H{#Rf_`=g wVd ihG|hlQ2[_Z4"{4 pL\hۖD/Q clD|yT/V!O `CD/ڶVH f6`&3_HyFf(ٍ,c(B'RT\ {DOȱI@ȇ+P(\17! 䪘=I5@ U\tba`J_>@3.]}rm(\f(CR{D s_(kD8UlS,Z4:qvrߍ, o0\'bIJ /ԊDAΊ|W1p;:V?EջC?=]DLZ!D[pAU$jV(y e (-D"1 0ystCW.Tt_i׊ 2&CJÅ~R[Vh[{:4{w5.03 zm?Pq~l(Պ(E `coJQrE9R(ƊO! ؂ޠ8bd/O 5{Wp^gCF?5lӊCݡI BOVg][mXB2O _>fJmy@H? ݋>T>Y #`{1ܕxBHs=5f!aNYɢ\lH#4mP!XB5fVldZked-U8g40p ^]y  ޗYvY@띛"^#5 1{c4|̜:b}4L %B1 0 m _@SxoQ @_.p1'0B``fƠ(HTSwh0!m03XA{# -~`~(iLy;x97(r3 ev܂5:A%Y3h_lmu" sks{~ڇseOݣ>`@8:^46nHcNZ{қ'4 q۲ DqՀv 8w*D /pƆ*fOP_.` j@+B`n}>z90E{q"@&/|8#.~E 6W6+05\JaCD)OR H g8 ؃AS4L}BJM/`~_pn#RA6ANU(NyGY .QQBQ\S1'f^鼢yEs)ǶHN*t,6gҀ%@ԩ+Epk7a:jE)Be(j7Հ#Qm 4\ j}~Dq]{S̽QN(_Ұ" ," @բzW(踭3J㪰@‹0B TA.4s3xWT>W(-kCI!~،Mf%E.اM*T!hGh9/{AT!/:nҼIe( OC@8LvtI (҈19<!"rEgj _.@{%@+EDpV+"B4v,K~uT mzAP0"rZ: 9+yx"fBU@$"֋b$mGVl3l!*6Tt<-\ӊ8)R.c-=uXZ!-SSU_>_(vPeB_G6!Gd )ϛbٶ DkE <_YGFbSo0j1=LT%]cZ_^{ UX0m OɿK% +Qjڽ)DBVaaY`(>F"`Cњd!*) ۞#jFdEy.4Dʳ`ӷ셜,MZ*4V-Z`_>0;0-Z WB9FTO/l070k J7Qc^ѵiЛ^sVv$ހ]8kPB(qrv'gC@V%Q}#7@|QANZn٠!}f>u8aQ.Kw(~ࢉD3 (pE Xbb_* /D;6`_!-^gW%R=8w4? k(`I+0\+DNx?fk 79YGD_2(Q倊>>0#O{ "bD X8;AQɔ!VxEΕ5lo#-t) /;h9THO5?Q_[CH4e3Ԣ#~Qy0$n" 4`*䇆pxm]B\L/<|9LsA@<N(5VصE<ߠؔ LQ<=}\ 0 O;Rv9V|(>@MƝ~0<%w%v/J\Yh@ >̯l`&ɢ,@_egYo; f8=.ÅErATѻB~G CP8 5M6h0FG3Pr2QQ=Yk%(~6DN[{4O7(n{2g^QVBgmS_M~*X8\C:*E0u@/Zߢ?B_ Շ"(VfXA|{Nt ؔ^a_@Y˒ w1} HEMOuOvlHBώ9Ud5<:$7 z5_Y>p;(Oݷ0cSg47Pr#ʨO^`FyۃBa+P}hEo}@_[T$:`pfT|v`0J@^1M*wJm98 (F9q38n5.<iL(_c䀧|@@LM 8n366U.8CoFnrla G1^u$r:^+Qef} 1[є.g^qI?r Rjh(2i!] _>q[A1b ,&W" s"@[ҎnVZ(flh,CRӄ3FO;xo6Њϊ`t[PbD9Х$Bk\a]Xt {\_((y{5ǜz*Gjw@Xy80f0֡C/ʡo/]" "\}]ʢrWl~pJPh:QPJZ\Z!Txjl,2}kF%rwY7>=Z`v:36fb}ThlLi0J; jBBji *r)40x[<0 /e(r@E#A!>-5p6} T+g"0\ P8'hŞ{RuVi7AE9V&ZlibuAi]b1<^+8؜!<-`#&@0m_Qe(5^bOv%,Ŝo-&j΄Zl-J6enoZ٢prwY0C>[|9*@Ԙg 2M.pDa|ïPX,i 8P&`?@\dL#BJ0hq,Vd, j!akHBW;4s !bD9= eC-9`msn(9`ۥE/s:V@e?_>0}b]]a(\EiԜ掙x{yQ]Jώ^~ >`NI ~ Y O뜓A=C-apti:@+44U#>4Ba-`< i{@H#r 192EpѶ^r^$tKWԺ3QE/}8**i3*9-g mR(5mz`&3_HtFf(ٍ,0\-l5P`O[W5vM/T\ {DOȱI@ȇ+P(\17na}@a"Z0^Zo}S@/ ƥ-Vy…Li}2jL! H4:82޻8 *h>@AZd` įdbz;MoY. o0\'bIJL/ jE gEYxH+BĘ8zV."ǎNg#0w j-(~V{ x}(u.DC %o,!z!:>"1uVWr:|Rj0.S DݲB+&t2W+}faVž.9) PHT倊Dqt@DڻȧI10P z}Q- cn/ 4iXOf1N+6w 2q6?'=y3 Gǵr@WZBWWPU3Gqu{:ExE>0^irj^46nHcNZ{қ'4 qD>Y(NpT@ D;QA(!"9` _` 9 $LP}ja9{#ܹl!.j,܋2x+wp/,EYA7`V:k `kՙRJ[3y,@#pUE !()pT>V!_c46v`ܞNcus@tߏHK [gpDqӀ=h9Q_d;Lm2die3 t^鼢9Tj'zVcзl* 8[DN=^8N_q~!ՊaE=S2 7 6P4x٧((1iˢ0s(Z}j#Qi5@#BdNU bRElSM/iX \j`ߦ]Ӷp @} Yn>"D*ܠ:"…/p(*-gpa3J?@ /p> lUAV鼟C`S4`{9`^V W392Yy/ QQ Y.#_qtiΕۆ"҈>!8/@>[W!z@}1_",VE셽Fb0[Y[cAN+T'y@X^ gW~P@T֜<|"…;bIFQE*3%LHt$bD< [&E觊 UkA!Ofu bG N6ছ-=uXZ!--.4o܀N_;Ywq{,BȦAT!|NPgm3Z(vWjǑƬ ;@ 1w}0+#>W e.XB>jEL6So`~RI bZ N²P}zE5.CT nT-EQ< +ނeNr6i` >[QcDher9`Zw`F1+h[! Je<rާ&`6QhEƼkx7q Co7QjN ص!'g;q1ƍ2pE!׷&=ZlN#5\!GH3}p- 0>wY0PDCM$i@>+J*oEAarAD)쾺C)ipm:;]z(!0@m|;J J24U0  X|ȁeۥ ٭0]W,+:O8D}}#@aF.&DnȘwG7(J=2DSwrFZR_>7(ԩV JMv+_'DC[63J-j= %!qP W!?4ᱷuQ q/pF{{1f_o/:_>ZWEy*^c4\ J@&(\Q ؃5ȩ˻U\to(`._)ch@BVt߯E@i)+$ O7vv]zv6ĽC6@/~3f,"]V~P۾* \djo($2q,gkm`ލg e^6Aӵ Ch%(~6DN[{4O7(n{2g^QVBgmS_M~*X2GԞ倨>&0b[A ]^ XA|{Nmؔ^as d]%%U8;l\2 :i uOvlHBώ9Udi/c8o  /(CtY8fbOݔ}@5~L,. Qn%_m^(B;Jw\ !TP]/(.H^(K̀/?`5J{X|T[E_=u = _Psfq^x2X|- >-U1o@1cwSe1>p 9As5yhmA^OlܳSP`j킐뮐㽽MR~6:[}`(!||@fR[W^#t=3 ؃y6H8@YMDEݲPλ Y؇8 f/0}xϺhgEig*ZXJw`*؅Ewе!( J^1^Jz RmN`1Q+C@)3"`:rhV(>+6C= A1^3D$*~38@E{]ʢrWl~pJPyF(E+=Vih.ƦZw"{[Ĭ~D 0 ;m=X*6Sb6q.Zz_> *L>0\PQfPOiQnO[q~&WN!?9 "3bϠw6' PB0ϔ-Xh8C)צ}w |T;Vp'Ͻ9CY2]ZwGL9aZ"4P8?k (qV rD?-`,|;\]债 ֢lXny& 6rwY.0>)[n^ey j3ކrDy&V80cAHa-N~FXpnhq>pD6M~ڵ@ʏ A2E!GW4=},{osH|v~ [`j&m6"`^\삨 ۲rlۚ_.sCM/LW4Kky@̩4^5<0GM/ A_b]]a(\EiԜ掙}{yQ]J޻^XhJ\YsJj0XoȺ(uɊ wLj!ok?hEֱy.?CZu7(fZ}> {ǽVyw!(c SrAmpR&ގ{@0FDM/}8eT|/ٟf>JQB )RϦfmZ>%Did֋rH}*㳆Ԯ*֘ a+ۊ|" RYXsC_oa@.^xrba`J_._>p/]]PlP.dr=!Pc ]hH4:PR+.. z|}@AZd_7 ~%!h}78xz<cBB5fla% BH;}Z}1x|]1n!YmMPk1Dm!0!D[pAU$jV(y e (-D"EGmgb5jr><`>\!:eWMDm+5vjC`0Aq= k?Vr?iPs.t˜1P٦C>&`\Pc㙯Brid>so8{{ 6 DM۽#@%9PY;ƪQ ~_.த*@Jɭ90 mJ?/D%r!ДAQb}Z"*YGz Dc1X}ueHp+T{_fXZMS:/u8@|Q(0[BoCL<\nc/9u(}!D(QɮӾ4Bj[~=&(wmP^{p;lWk0j Gsi0Z# Ƙk`fl (HTSwh0!m03XA{# -~`~(iLy;xr˂c1RřY2;nXyB4`/:Y9xV }S *hk͕L4Vb> !6DqEsړ$4fD6`b{s%$^9w'#JƂ׵84Q+`ڴA󳅗J-WXE7bw?6IJTTaaY`(>F"`Cњd!*) ۞#jFdEy.4Dʳ`?*{0Y|Uh1Z"n\0;0-Z WB9FTO/l070k1 "Qc^ѵiЛ츆𷛎(5'q\B񍓳8?Jܶ*:Ⳏ ru7r='?Pr>3: 0ӨyXs%s A?Dp E`(Z, Y1Ta0 ey9gBS\|;JQRT_tҧ+ ,<<+Dr,xV|Q̮-\dQg} Q*+XGŒ\c uHO5?w!dr͌RcE}m4pӀz_.ۺ(~_.<\?|g⽇SB\=@M+46Dx_>p>=Z`v:ۺk3>*4  Ұ jBBj9@TzpN/ -od@E[6B|[jlVtK#ދ\`ְSȏ_'\?ƞA2 'mN2(aZMPr|3rX=ipmwh a@uN{csdk1ZimG*@<>@%LT\DZ,9N/.Ҡk|{@=|ǻ,0>)[n" yrA9@Ԙg 2LpDazZ[gsC gy# h@( De2& A2E!GW4;,{osH|v~ rVE+J.!QD95|`mP) _.-@{X\0}*:P Ҩ931Gu+?z}BS <"SR1Ī}Cַ\C:dEi`cZJ= =ӷеj]}ćƖU(xO_^8q?P+҈܇BQ8@.@WnZ7v& _.:QQ/ha?[ |h9cB )Ræ^}K>/Ȭz?eђ`^EuYCjz>Psa4DU NJ&mĶ"BG(Vr[0bK$³Ôb1ĻVqf½.4|"g9]@*@Q5̢P@)vF#"{QA㙯8r&+Y>AS[VC:&$QcQVRV$Z!>@YxH^Gs0Kwž:'ePQl0e07sPvA1M]{4_>+@q̹ cp@UgVMl~Nz>2l|G?g' 429+֕M 4\7o%@N+TUc/8<|O\)un'L4+)=\,ʆ4BSEU VldZked-GNLNc('>W|"`% <Ȓ0<Q(0[BoCL<|;F=|̩C ! FJvE]<@!bc./p7py?^Ly-&Fk04yƜp;Eb1ӊ|h?Jj w@1 FS`16+hcb`#ůL#/U"3)>qC<o_>0_.pa̎["uPi>`@8:^46nHcNZ{қ'4 q " DqՀv 8w*D /pƆ*fOP_.`GZve\}6X 5Ph {_)N'xeU/ ;Le\ 1u >A$Jyb(m-@Eg8iTTA{7NyӠ2 )5\e91  0n[P 1޺@t:-η[/0Ә[gZhEvH6NWe֯<|? )M/+bO4yE>PpTDO*t, B`SaKSWԩߋnøuՊaE=S2 7 6P4`JveQ$J~onwn4<řVtSe;z#TҰ" ," @բzZXpo~b-U[np @(*-gpa3*r0hcX6I檠O b+΁t!0)}|`^V W392Yy/Nj{1q)zjH /`:mR1< <<!"rEgj _.@{%@+EDpV+"^y#Q[N/0,!.ƂVNn}! sVN} *hkNEJ^.rY}gPl}:(Aebi$@(G5PbaˤTj=/;(i5nՖ@WDB~uIȱȺWd,vG̩*L/ @ 6wz~Lt#Q8edd ) Yx6^60b7~f}Ii r믋NmsJH3 2sQ*_. ^`[G‚iQ|J ֚a +Qj;P7p$: C1 >& Q* P1lAFQTBHt<{ _8}k^ۤBlE vӺ3YAQp_U( n/x%`/cD>5;uLjj@+B5] yΎo = ص!'g;q(;)ʊ:eQ 8z;E[n٠!}f>u8a_'0PDCM$i@>+J*ibmLUت0<Q #pJڀiZsW%R=8w4? 7;A 0  ,BL/Po_gbvm>'=y;r{{1f_W/:_.`+b[TH_.B2=X95s{yc  c<+Ey -A `q'REi(С8K:_0,%"}&_LEYn#7TY!Lr+뭁.Pa.(Fy, ^^|Mf0+4b>FC} (xۃ.5>P,WdllVsDW?p%n/(P38n{ <29X|-U177⸝_>PT@cx!P]x֑xAf[s6[nZT(C0sv@u/|T9t)?.3J1&? 3DH+Pe/ BA5|6H UgLX\2Iůi9(O>@m%bvV>a/5Mx/0C_.`ϺoⳢTӦkrp6h- V+aUqADR{(T aOw+BP%oS/V\%} RmN`1ѷc}3e`F>Bl[6^mϊ P7|PC.D  Pe>.afq@4v/ {R9_>iE+!IFidև شBcSNQcoW%fݜ B`hMQTcoXۘQT|¤񕐧_D_0o1s_ur`3(g&ΦOjE8l0^&`+ ꋜFHgл x !JiJܠ^-g64 ڴ.1Ӏ< itk1ZimGʳ i u%n*AN_EwKX,9܅ jVp>[ҲMcۛV|(=n?"`˵ W1wY>P5fxoC9L Q $'f9HaDqh@J_>@15a?H4B(T(ኦ0bEbf:;D _>+4m"D @\i%$wx@Tc/po _r_>0TnYrviĜ?Pb A_r@EXgWW 9xD5繾c&:<`sTױR89}!VB@9'+HF5Pz^J okOj]}ćƖU(5?^8qi@kf.| E/D۶q)er(vDFQ +e{ $9-g mR(5mz`&3_HrFf(ٍ,cZL(B'Ne6Akl/"QkUȱI@ȇ+P(\17! 䪘=I0%X 1U|)EXv0%9,PTɑqb˵Up!kE_ SH@GŹ/TEQAZ b%O/`M/PZN}\w#C:&$QcQVRV$Z!>@YxH^GsW|"`%O/(ZGǣ`Np|b`9;Fr؎<4/(%*uq}Bj[ƞ}_F@?_L-&Fk04_>HcN8 F`"s ̌iE>4ZD5uC;b)0ӘGl1pW *P^J rǸ!j7`O/yA vev܂5:A%oB4`/:Y9x%ǩW6 TK9B؃iLbLA1% rP"Nc4椵'yBӀw@Cs(NpT@H4\"T:D/N 2_>5,E/~̯l}>z90E{q"@&/|8#.~E 6W6+05| X=:`kՙRJ[3y,@#pUEFXPMe3 t^鼢9T~D= eTiA u"pڍ`ZQ8lgJA <nr5t+Ĉ'AT a(~0 iy& !tSe}By! +»+@ T-qe =:jqSn Mj 7p9A(}e@KB!~،M_9}`$ɜM%6pD㱏R87D0/A\8A,{8^ ČKS#\Fj9 aZi_~B+Bp ^D}&(~o(~(`ݖ(jEY^+o$*vK@1 F"`Cњd!*) ۞#jFdEy.4Dʳ`ӷ셜,MZ*4VԘr8bVжCk&ʢ_J^(Lj f;FpV0j+6zzkq *C7N@w b(q۪ o:*!iජbM/?Pr>3: 0ӨyXs%s A?DpDsBk&(fTP 0 e_|z(!0@ Y>N%EL,h(*BeL'r@!v_)4,xuGwV|Q̮-\dQg} QK>>0#O{ "bD X8;AQɔ!VxEΕ5@Х4|AKoPӶGEx­YUC\i9ZN߲QjQs^\x~J[8iUM/pxp +xsr;?4xa/Ezj<# MLQ / ۀݡ D= P> \ Q+Rg&Nx}"U  .E@ 3\™+^-hg D9YE뻬l19r(m_I@_.p 25zWȷb*gB ~I }ȡ~ j[P&Z8""?9m<%ޠn7BPݓ >ň"g#D~*X8\C:*EP!r@[Ū__ Շ"(V++Ȝoω.ҋ;r˒ w/ b B8 !"`S^D(aSL6\r?tw {r,|b+xm6e/?̀/0]Y|NO?`Dy=+ 0 vX/`%+.Dr"PAnQ|"ѷGYʬa>K= MU9Q >` e ?`ǭޅޖ2r.P%Z"(fm< Fqԇ|Sp`;@E\DclH +֜MX} +z8;@t;@+?r d)5˹ J1ta_.~ SHX\2Io J? t˶@1c;D+da0&!?<(h-[hgEi3}vJ·Zkg| gU@D va>*(y{5ǜz*K;YmG }o,gCmˡXX]P|x9~Bh!8^Zv)^]v `_>p > X]E a4.@YB(isP :-iƦ֝>^Qy"fN.` @ MX)1 xFiZ{AiKTzpN/ -{@E#A!>CnO[q^r+ 3b@=cNJְ(a)-Xh8C)צ}w T; /76g3R~wh># !+L%n*ANU~%,ŜopniogkQZi,CPp;D 1*VE[!}b r,ާpokQor _.R傡[<`]Zr]\0}*:P Ҩ931Gu+?z}BS <"SR16{5bZl}=k{Ԋ4b a;sA1) _>m=/Q clD|yT +e~@gQ0!Wm[+3J 0glx>oX"DkPL#^F+\-l5P`O[W5v /beA$u NJ&mĶ"BG(Vr[ƽu+b%>(Ck`6_>EX8( ιYD;lǻtb˵Up!P@)1XF QjE3_lYEJVؒƆPZ-Dbz;M)WTC:&$QcQVR]?@i6=PW"k3 mQYmMPk1D'LZED<>LePEj@Yb]Wku_z^˜:Gma|cbj}_3Z1Rj0.S DݲB+&t2W+{V}]8oևV4԰53,逈B)wØSɓ\QcaJxFٲ!cn4 0i}k `%1N+UmZpn(ATPjljl>u@-Tǫ+PU3Gq g/t@^!ئ4~?AT݋>T>Y #`{1ܕ< mb֜P; X8e%r!ДAQb}Oܲ)p *YGL46,5WWD9/Be+Y{> jy+G/`Np|b1_>mfNw_Q1JT+ m{<&v&~hbm11 `X4`F,1̘V QT`h}Cq`4fShMŲ`XTDqa̎ۛJJV agЀ dE㩗^ ZQAgGf]k,g~.!,l|`#AC1/lNc4椵'Ud-v/&:EppCK |@(| *hy36D/FL|`h _2A`ldDka9{#J\C\ Y'd9 WI:h-%"^T$A|5^A5V!7 0T(Pmq{ނg8 n>N 4A=("Q4`_>( ~VEPДz!(Ua +:W1ϝ'zV!oqbSaKSWԩߋnøuՊaE=S2 7 6P4{j@`WFKO_.@{QOs1bY3[|D̩JTLc +Pjy@HÊ4n(P6 V*ܛ߀X ݲ|DPUAuE qgP 3B8J+zP?@ 3|fاM*#؊s sacl}?/O yq.Vx HZ/[0DWDYxIeGw;N:@F e/DxٺG PD PJQ-QՊWHT4v,K~uT mzAP0"rZ: 9+yx"xag9h;u"֋b$mG;>+Q m=/<-\sb}]r'Q+`=sj ŝu_8| }^>z'k FxMyތ̶m`&Z+nJ80Ҙ_xQc!ϕfxeܝ4*_. ^`[G‚iQ|J ^*i \a@R݁TDRQeu| Ek]lڞ#jFdEy.4Dʳ`ӷdmVA|hiqŬm(Z 01z_`n`ֺcD 7hEƼkx7q Co7QjN ص!'g;q1ƍ2pE!|k@q4КA /8BR|Bcp,\ La])QEf9\QVXOnc*V偈R}uSLC ݲi_=CJ}B Q8w!0tvh(>=@I+hv_>@3|@Q]@̺;읪fk 79YGD_}G(r@EsEkPIE1q,ݠ(dO "_6efL՚P3J-j= %!qP W!?4|cobg8=Ŝ}]BhXKTƌ倊 q /+87\o{(rjn1$`?x|!jWZPA냐O PTCAqtڥ(aX8seKE-L0('>}}-fxP?s-W(_>(w@ggC䴵GHKxq~@ؓ >+|,F9Yt۔Wpd" sאJvH<| ƭbxί ̯h啀dηDM%`b9 6 aX@*\a-6^D(aSL6\C /r__PpoQ\P݃Q2_P٫%V]Z @힃" 5^T kOw+BP/|:"^Jz RmN`q͔Elmx9z ʡo?;3k7 "[=.eQګwt{R9z_@3J{e@QlcuZ!*Z mEȩW%fݜo0RөXۘQBk3%a3(킨 y y;\a:|\m4so6B|J:nwC~RE0/p IiĞ{;(9Yyh9jDML46KL43z؜!,.`#&@0m_Qe(5}9UEKXs_..r@ gkQZb0W9"`c?/p~{;"_iL@}D j3ކrDy&V80cAHgu6AGj}짭P( 5r$dL\dL#BJ0h{Y+250&^6"`^KH]X{[6Tښ_.m[sn)jviM/9ҫF!k"Q+ "\1bdz>٥g] ,4ps.,9%5C7dw'J\30jak"{r-!5h6ЪcE6b[WDP:@+J%@cG_"t@kp0% /P /.(\[( 2Y1.4p$_PBUD GH4&e+Y>ASE p1c+)NBTi6=PW"k23 2w@2@5&g2(u.q/M\@5P+<Zi<FLZBC^˜w.m} X=i 0<y:<۫ T=0QGж 0lE iYսn{A8IY6Գ@+YA)O Z?P(Β(R{70<5JWo3!؂ޠ8IѵIc-=g1=1z e&8M+u&}6?'=y3 GǵrA3_*{uU%0|}pBm@H?݋>T>Y 圎le4v%PyR}=5f!\M偨dQU66(\/P=b#Z+CD%kQpopz{Se&n<}ueHp+T{_fSXZyEC띛ſ">~< b/x;F_.0sPbdWԩ(Ul6 ^L-&Fk04yyƜp;Eb1v"ѭ b9nf9@1؈hk xE<m`J5`}_|hnc70ũWJhy 3D=/pƆ р`iX&h87:]-,g_|D)s `Z! D"L>g^Jq:]G\<Y$ɪ+ѱa ҝ-/ O!,ZqY!a+3p(Zuf{) Tmiip8-<u=iUH_/p}.Ӏxw\Nm9Ng- H< ؃/8^/e:m+b*FnXxEN}̡u'"쉞UX)QaKSWԩpc7a:jEv (%={V"t+Ĉ'AT a(~[n4<ŞVt>SM*!EYĎ6d@2fX{M"fi9m T87g>e_p x@Gf!±χ(}%x.cۧM*#%Z>ChaD0A(f:HZ/Vebĥ.# s[i9< BhE(еjlkFůQZ( {Dn9y9ߎ_0bk,ivP?&  iE+*hkNEJ~<fBDqm ̬K!Lx!(a,^IĈ~T u+ [&E Q uCW[Q|nR K@Dֽ"cu iXx储 ut򁢥{@ 7`a/-S!G[Z`dה ,<Ư׶ DkEԬ# #YAnu1ѩ75vbZ}0-#>G ecZ_^ض|Ԋ*,6mŧlᦒBV ((OE$: Cq >. Q*?GԖ"( \hΕg`ݷ셜,>#-|g+jl[_.pI(fmO?DѴJe<rS f;FTk-Z¨1t^h9;(Y$ހ]؎kPB(sv/'C@k(qaGYrj zN~/8BR|Bcp,\ Lf}+sZ;mEfP [33?[0Ux2@D)(,_>`N}P'/'gy9!0 p0 _`"gr,٭0][8ɢ>f} QT1W\~ "bD X8;AQɔ!^xEΕ軑/;8oPGE­PxEh 5P(maS W!?cuQ q13xv':B\=yXKT< n{rxLQ|. 6X_.P\*.H~ Ǹ}!jW8ZPA덐w PTCAώ@1C8JKⶐ KE-L0('޳}}-fGn+ _p 25zWs˷61L ٚ.Ep4g#ݳTHCԶ\Lr,Mv?"e=hU'|X cE/{We" sǐ܎*EPrA[Ū__ ՛"(V++Ȝoώ.ҋ( K6b0a++:ZlJcȽTEmQB9UdcgQPY{\pr;22.a&(F9m'`>h9܀0Vi~b>F(e/Qyp!D}XJ{(W(BT/|(H>(Kq݀ v)mb"cQ偳~ uݒ8@K\GQfq;pg2yX|}&3*/⸽ PgT@Cl ]\Q8#/r}7|y|ܵ(Gu@YBBBy ҥlt~!3J1M 3DH{_P^s>@]7؃2mlwgvdP_sx(gO~@%bvVa/u]x'0C2|OV03rsm{WZi r/kr(q DCo;TxgCoA4v/ /G8z(rtF)mE+ַ/@HcuZ!*Z~Pc NQm(K̺9 `! -fS}ZIBèBS-ZL9=~&`Wyrix)D_ur`3(gߥ&ΦOjEԷyAg{eWN!?9 "Ha3h pd*C-Xh8C)ԮFq48} \g໭N۰9Cz2=Z{GL9aZ"4P8_o(qkDˑKŲ{Z/ﶂ Z-E_|ey]7[>k^cn js6C9\ Q6@~Xlqn؀>pD1¢؇W3 /P~_/$c!PR}pES~e"cxoG1 ߷!`~ {q.B .WZ}t 3JoA [VSmkj}5@\ZĜ~+Pb 0}_H C~hW6AQs;fZ{y]~;ٞP::cU_e{:dEi1bi290 W}]g/έM~Z;y]] >{}Vy9v](k@Wnn@@0!/}؏vUyg `CD< mR(u}z`&=_H{eb\k7,s`kܧ8>kH(-7@z}<Rjo0.S DEi5ô,L;nI7Pl(Պ(E 2DE@EK: PJmka*yFVP z ( z˦}]` 8\v1cؠcC> BOVg]l|yPc j uD)U%0|lXWY4 kŒUH@CmV,^#Dq4W )uN'L4+̔ ,>ʆ4BSE-Xczn!["*Yy[N"0Xk_5]Hˈzre+2K, µ&DK`vprb [{偢B3{3{B>)avD^&6&{P1eWk0j 4`F,1Ej w@1 FS`1v+hcb#ů" {)E0fS|'ހy` Y2;nxBOu;AɊ4!]/9vvώ9B؃iT9BLY1!AC1:/lNg4椵'CӀ2@CӌL^ 8*g;w/p[`i@ Lx颩X&h@qn0 }:]-,g_|DkLobŁ\5PWIqIJfAs܀/0cX-}Ug&Jyb(m-@FgiT' zL:N4*{e/ `mqX4`>]7D G cAV$Z-Ub{}GY`/}ehJ \S1+f^鼢yEۓrl(B"xMJ– QS7b< @0Na9`(.Ꙓi($P}.س]%FT/= m_@r(짱 v(k vȜ@4(qՆlS_&Ұ" k>QsZ_䣰IW8BTnM;w%…y3{P 3B8E9UH\4ǶO,$sU;G@:Ô> y`^ W<392 u)9HZ/*"P&N*8uڀs _ bxh2AЊȽQkxe(_) X' ZQ2@1 s} `%X!q^T@/47"rZ: 9+0D/ wV߻T&Z/fJ֋^IĈ*s&ܞ,03l!* :jY}|VXbH@Dֽ"caBZ70y *a}\;6`&`22lDN1G[Z`dה ,<Ư׶ DkE5J80Ҙ_xQc!HH3 2sQ*z 0m[G‚kQ|J n*i \_2C F@t^h*,, {W_Tr4~c!*_m-;nd<Ds&Xv~a{!'H _ي'B+wfX4Q^#J^(Ljj;5;/` ZwZ"Qc^ѵsv\Q#v\B Ή%qE!eQ 8z;E[2#!  49µ0L4Vw(~ࢋD3 (gsE XP`lT0 eyr9o(!{' Y^Nm%EL%xCyr"x2]W,B_Pwz2?fk '>YGLs#JrAEsEkPmcc~a'=?pdLn1DHO "軑/;r7(i"Q\@l(F "r͌RcE(-P¦NB~6g '6Ŝ}}f<uz_s_0B_(6B:_D+j `xEN^ޭ"?۠}V|(>Y,.zG" E:4{I]lZQXl^-h}g D9YE QڧW1>r(_IPpa *]!?-PH2q,ghh!b9ږ+ _pETϻE ~g?"=@ZԍW@ucO&, ># JVs/}J+زil ڀEqU`!}Uٿ&0b[A ]^ XA|{vmؔA ( K6rAk.jҧi&P?R;jG(azSL6t}|ve. P ܶF^74oP>VyO`F̃!ZX`%}O(=pDr5"PAu@}肊D GYʬ|AgۥS{EƮQo}@%#qxp)^PQB^4!˯dC)旽G}߿hz >% "{gvdP_s('_ tnXZQ YX{!8s atr/ZYQu\`t%V]Z @힃>Jw`*؅Ew|&R "^Jz RvilLXLYAmˡ[X=Po&fgPW`s"NjmkQoA4v/ /|~pJP:S(V%/v[" Qк]@M+4;D}\.1GkNgqdVT612X*1zNuuJ jBBQ\a:i`/TԺk9B]!~Z-u8?P<ySANH#lR :(;Yyh9jDMXIX!"s[G 8yn gF s´#D~Eip~PPTk~ Xs\@+xߜ(h>!hs̕ 8r^[}" ey jXP(jGf e?[~}>bvEf %_x\5a_H4B(To(nb{?D9${|v x^/hv"`KHTQAxڶ/?p{eͶm0o n# MsY |+>Pb ~r`UりDή ha Ҩ9f 6Gu+?{z]0m([a+)bݖ O^ 1M&0c9peuj\:#[_[j ?"{41D"/D۶s)er_~0\|Q{vUyg `CD\ mR(;iu~X"D/Ȭz_en`U)E>uYCj{*֘ a=X%`ȇ+P(J V]U1{Txvzw= *l:`ύXξYD|r(\zn(CR#ht~Aq5n"Jq +krx偨S!h}68{BB5fz͵" !ˊ_c׵23K@ջk#*$㮬D[pAU$jV(y{e eP ,n_!8ᅩRJ[>:!?(7<y:y 2&CJÅ~R[>ֱut" Y0L{,q }uv'`/HT/T$" Զ1'@)dcŧwe#Csi si~}k `%1N+U381~Nz?iзPc㚯B}눲429{7=py` xt~7BVBe9H^#Dq4r~W<)uN'L4+̔~<,>ʆ4BSEU Q E {hdUW`U 2"vEJ~ +|*8/E|F}kA b)l h1\ 6c5?@(} D(Qɮ>4Bj[~=oh#P^{U=&Fk04$8ҘNr!Hl0\3cP`U$;4Zs6My?aS=RpTTR`4< /yA/80_f-xST2U?^'+0wj֊ =;B0Zse@}4u@1ՠ"d>E`TÊ4椵'Ud7@CӌL^ 8*gh *2 gD4`: h,4`hj,487̾n"m- Ѓj-N8y@L8@A_)N'muIJfAs܀/0cXGc:3Q-0U[D=Ӏ=**kmk`@rAecRj`mq[} i|n.N'QSU$]A eW\P)_>Q_Y6h="CNDQ=8gkqD4$`n8BP:8 }?SX0Q(.Ꙓi($P>IveQ$J! ma;NL{Z е;CdNU bRE1P2i~2 9;@-m2@AmQ PnMj 'p9_. 4@(}d@KsAlB0 hm\AAl>90O/B+wP<G. Q*?GԖ"( \hΕg`ݷ셜,>#-@-b ` V6-/L(fmO?DyVi,!>>xsj^(Ljj;5;/` Zw(AaXoP~lsVRsoml5 !9;C %qE!eQu^_\P f8-ie,rԮƮb| Y FVw(~ࢋD3 (gsE XP`{倂"JadWZ6`8io=CJB V,/'"<Nzw_/ 3@Q]V|Q̮-\dQm3(Q*7Mk\f'M pADQ! {G7(J:[^xEΕiw#-t)!@w47(i"Q\@*!ZNQz^#`kqrn0$rz\!6 Tl'6Ŝ}]B<uz_Z1F_@q (/d`|EN^ޭ"?۠}V|(>Y,.zG" E:4{I]lZQXҠ@Zp_`~e3QNgBU̺ |WPe dj[aPG Q+BP8 UȽȡ~ j[P&QQ=Y)jPliioPP7_ԍ=೼/x(+Y!r>XFD2hǐJ,$~\Vj<WBlfUJ 2۳Kcz%v1@Qm@.jҽ=~"ô;#" u;rT!'xe~!/܁\߱(C\uQ?3^ ~_`/(5\*<+ 0\B_{)+W >\=!TPv'x(>P~Q2cOR)b"cϨ򁻊 ݒx'q G G;p? m2$pDZbw?@vrA1cϨQ3!@4`< xc +֜M2Qt2>Vk"|T9t)?,x?PQB]4y!}9DC)qQb =h)ت'  7őƻHX\2Iů9|Aٓ? t˟ap wuc&Cp~[4VFyO|zw|{V|VT/0Xo֠h=ToDv~#`*؅Ew5A_Ɩb_lj XActA|ѥ6.0!ɔEضmx;3D=8:(ˡu"pDCů@E+ڶ(Dc"nN^)]Y0Ni,!c(pN4DE@]jl,2}kF%r@Y7=Z`v=#[& MSD6DW 8@Tz/0`.x`^(Q*j}n w SZ-8x7r] xr+ ꃜF uQ8ow!D os{M!ؔ|Ԋ }""1Y&x|6lL`#&@0m_Qe(7(qĞVQ !?NKX,9_>@+|m)>WV ADx ׏'j ri>q/QcŪ6C9 Q6@~6g(fwPX `FPxʏ& ɘFm`>v PB9$=.sH}&X_hv"`;@\i%$>X_>@|'V,ٶu_ ` n}ihK7bn툱jPb < i1j [$uvup}#AQsv:g٥gYLJVX EpC0bce{:dEiXCLsο,\Yp=[{Tؒ ej ?jE1i1D" +ZuYCjz>Psa4D NJ.Ķ"BTX}XsCu` WQCbw̦|scvoQ(r/CW(\{( 2[1.4p$_P@UD(!5_hq4]\ /_:g#M:.$Qc7+)\+m(˞\"kxf mQYmMPk1D!0!D[pAU$j`n["0nEiή{uz^.Դַ` [.Tt\y: 2&CJÅ~R[ ֱut" Y 0L{,m(un) ;C8@EK: PJmka*y+j! BI.ۅC^6@t|XOf1N+U381~Nz?2٠o 0@5_BzܺU%0|lXWY4W 3|(|}do/rZn0m\`N*qR41zrkNDC(LQɢ\lH#4P!Xc@aJ֢qnqLNU9ʻuHˈzre+yK, Ci"^#5 1h1|@llj~r@(} D(QɮS(Ulq6p[@j(11 `X'Ɯp;Eb1v"QMݡ(h4by@,|6k RC`1q`{ !ߠ i/) *[X *T7[{Hbc׫[+*hk͕zOE#Ĕ"d>^t6nHcNZ{қ;4 q/D>4 DՀ~/pT$ <LLt9Ð~|Dkwl DptVG<@, |zQmV4 aj/EJa` "Q-0U[D=Ubz\u=iUH_/8FC5p0㮛D|[}٨msK©*.OeW|?/@SQ_Y6h="CNDQ=бS6J– Q=r (˄>v)VfL4p(@PfD@`WFKOw}P0 ily&=}!2*P1 )"v\!TҰ"Qi9m T87g>e_p |/Gf!±χ(}%|\4ǶO,$sU;G@:Ô> {1B0m/+tԙK^$-qO*"P&N*8uڀs _ bx_6Dx1]M-p P6(~(`ݞ(jEY^+o$*v4vrY[cAN+T'{@X^fc T>T"\l_@r;+ Dqw3RE*3%LHt$bDq?f-"DSAo}St<5`VpjK O+,S]X Zz"^Z!-SSU| *aPv{L4셱e#]^>ڒ5#cl0d1~m`&Z+5~f}Ii r믋Nmzs$$*g#K ZQצ 5a +Qj;P7p$: Cq >. Q*P1lAFQTBHt</5`/di >[Qc= vwfX4Q@)frSuLjj@+B5] m(w@,5(~6DN{{4w7(ǯƞLY|rooxe,b'Vk a3]L7Pr#ʨy' /0<5,`%x'>pEO@BZOm0NQP(K1݀?>vb"cèr[E>u:nISG(F!qK b5L&<-booq;@1cèrQz3r]Ay@E\Dc1^4nitk&`Mef}"|T9t)?.CTfcM~@fR[W^#~^M7؃j "qgvdP_sQaO>@{ո,)] f\$^(w^ǯt`t߿PbD9/(PzS.,C!(%oS/V\%} Rv0ؘ7? ~`Fmˡ\X}@Yr(}݅!"PkE_PŊݿ""J4v/ /kH1{Y>P56\6f(@bu# 3Bkqt:s#>lQ(<|/VUm`>\єc3fYX, j!a*X]XA+>DQA;9`/^_m[|979`/ 4ͥ_> t\_H C\B,P䊹R 0b!{3%X 1U|i; ba_/ ơ-^y…L}2jL!> F>PQ"Jd\`;/`_/:g#M:.$Qc7+)\+m(˞\"k|fڡ.#0w j-(~"2(u.DC %o,!ھb]!>"gq"@j˾*J P%^xR{pT&-Q::@Yc0L{,q}uv'`?$*x倊Dt@D0T$WԘC(l딈e#Cti> tiX@J+ cEnW3 :fZp;4c d6eP1cZB[WPU3Gq g/t@^!B} *˹G`ڤ ! VI+T>)uN'L4+̔| *Y} ixEἢ,FqT-"*Yǹӫ*00~p~+ "QNn/#mY,";VqA|Q-aݷ _(J)(bc;VxA(} D(QɮS R*6L6p%X[վQcbC3i hX$6c1(h0* b9n0ӘG;l1pW DR`}Z ;[jn?bY`?=#QizxST2U?^'+0wj֊ =;B0Q*꣯(G) ?f9@10D4|5F "l@Ɯ *ʢ|hz, ֺa 9@(!S|倨(a9`: 42A|)sa{~ja9{#J\C\ Y'd WI[p/,EYA7`\ 1ucV(^ ɢ_*@a洗TTОp2\:N4*1 շ =ǼtZoq8>mn P8UEi49Q~er@_>M 4pWLŨ,ixEN}̡"9" o~F-AN]Q=.8@0NaDp0gJC74IveQ$J! 4ߖFa?m4D]O3DTsO0(\ aE'+@ Ӵ+rXpn~b}'aVa_ռ ;g*,lo40>2C@E }>lF(a\4ǶO,$sU;G@:Ô> 0A\8A,{8^=5T|E!LT&pt;s[i/Dx1]M-pmD PJQ=QՊkr%@1 s/0e]!q^T@/ VN} *hkNEJ.\q/M g9h;u"֋b$GVLOQ ݊#B<5`VpjK O+,S]X Zz"^Z!-SSU/D9xA۽ 0ѰƖ!{vі7;53R2۶hHq$a1+ȭ.&:CLϑf4pR3cpL}s~i0zaQ+ڴA󳅛J-WXE7bw?>t^h*,, ǩWl(z32DE>DQ[6 (*sy@$:WmevrUh-/L(fmO?DyVi,_@)f{_q%0k1 "Qc^ѵsv\Q#JIנ2P|ct+:'Ɖ2pE!y}8pZn\!GH3}p- 0>gY0PDC]$i@>+J*j}}fg EgFTem!t0J*h=x94? o(8`L'|,Be񊯘JMq|3ٵK{,m&׽LԶU0Jߋ\TFŎWi37(՗3`XhDHO "ʚt3/@w|7(i"Q\@Wk 4eMx `HsiUȏ*? n܀3294obN; q!t4k]ޗx|T_t/D+jxl/(rjnq$`?c^Q? Q+R Zox#U  .6-F (m,5^-h^!w0d{,D)jCDqUЫ7|v+!Lm @ Ae,XVAb췎1@mʄ/8""?3E  -] + '|`%+Du:D2hǐJ,$Vj<WBlfUYV9ߞ]6-x8,٠_optEwQ].E!(Qޑ0 ll?C_dۻ!,3@1'?pve?{݀0Qib>nC=pF[| >Y83> ka}\ >}|B}^Y ^K]]*o聨{KG/(Fy!q{drAi9~8n/3v*QoFcx!P.AG1^t tk&`m(2Vk\zD>FSxص`F 9{2Cz< _:|{P_~KƽqH]P_s('_THޚ]"Mrh!_o8Ԋ^ :_.0v**ZE(PzS.,C!(/cNXAo@|ѥt70!`F._ضmxϊ Pkr(}݅!"PEP7I t "{t=Pސ1 8[E"p:35 X^+46kWT̩a* 0 ;ڶ` @ Mjq=Wt}:]^!O7`׫ۂ8L[ -]Xmlur`3(gߥ&ΦOjEL\ P8P$4f ͠ x !JJs{M!ؔ[jWHk>Dc>/p܆ϓz;b~oUyC]@BNU~%,ŜoFp~wPZ-E>Uʵ'?~T Yd:dEi1b-%`jY40 W\g?pϭ j[|hlQ2[_[j ?"{41D"/D۶s)er_q0D|Q5Ԯ*!O60!W G_.ڶVH fz>0glxz/A$zFf(k˭,cL{ !ؓkag2Qg5hvЪcEvb[WDP- +bn-LC}V2Bkɳ׻;1DGq6hO@kp0%_.|`-[ \-zeԘBj}8/(}*.. z|}@AZd:!TQEijիJR{pT&-ulHì{V ޳0K{b_v~l݅_`3]/9=?a{C@8J10P %X]& c4_]4?>5JsQƌaVM?'=YMvy4{Bk>G?{' 429{7=py`Be!?{0 o7BVBe9H^#Dq4{!B  ib֜PrEGِFhJۡ(Bp>@"J!@8AjEa R ^FГ.XXZyEXG賂o 8A 1-xr-F h\`ԡ|D%N}~@!LL|}CNJ} ahQ @[5R}SJ<(iLy;x~yA/80_f-xST*Av`kiC^rz5`coO{`,{=(1Q T|xEٸ"9iIo4`}<4c70ŮWJkqd@ r gD4HX&:=}AHl[㿁g{qRAgBʼnD|tVG<@, |zQmV4 a+3}t >֪3Nzwak鉬{E:jto`NMUarAT::@۽ 0Qq[6\g/mjq^S;#(m֊Da <_YGFbSo0j1Ĵ `[FHccZ_^ض|Ԋ*,6mŧlᦒBV ((OE$: Cq >. QMYDQ[6 (*sy@$:WmevrUh1z"n)K)fX4Q^h 3PB9FTG X#J8y@+B5] mq8aX S( !. 4|%`B>Q~Z EgFZ6`8gB7S\JVRTP7/Q_t0.* 3@Q]V|Q̮-\dQm3(Q|/s3R;q7m&ADQ! {G7(J:[^xEΕiw#-t)_@w{0yJ;dD ~6>(^hh9}fFEͱGzp;CCn6up"f]B\peۆSB\=yX֋Q(OϵoPA =y xzr"z E OA97Ԋ@8St^HAB&c/M1C8JKb_h@ >̯l`&ɢ,XR>Y7@oJ,{R djo($mb*gB ~ "c<79@mKEioӵ Ch%(~6DN{{4w7(ǯƞLY|ƿ$&ݻ\:'BPjwG Q:L9sk2?t @Ŀk!NY.:(We/?܀/0x+ib>^C](?p̓35^ ga\\t'>p! *}68Rf} 7T|]9]P,WdU>pW@D[/$n(b(Bzx&g2r.P%˄(}0;Q储Cl ]Dc1^nitk&`m(Wu@Y\w\wo@4^2Dt;R@`F 9w2C\ _:xAHp{P_. xw1>ip|7. >F}ݲPλ Y؛8 l0CԊ>ܻ~Њϊ|F>rm CꭒίwLztpE b_z*Km]`;(C@)31mx9v g{~qt|PC.D _-/VCoA4v/ / {R9\vʢBI}Vi;35 X59o9>4gۺk3>*46Uc]usJ@z.5p6} T+F 0_.p%@I!ץHa3f @2'`yQHkx@0-&hQuBJm!!ؔ|Ԋ }""1Y&x|6lL`#&@0m_Qe(7(qĞVQ !?NKX,9_>@+|A gkQZk,CP<~{Ԋ/{Y>`vzW]g-WAǽ,D= 2\pDa@Ha-N[Źa~}^bvEf !Fnk¾i@QHQM6c/0bEbQc 3oC"B@fj@4T`J.!QD9ж5\xm |` _>0E_4ͥ_.s.V2_.*:P> Ҩ93w6Gu+?z}`PlW(km1Ī/}C۲=i}"4`s14ܳh`?]{έ=j[|hlQ2[_[w5셭Ԋ4b 53Ӹb.92EpDzEy]-]QeB1 _>`uc?vUyg `CD/ڶVH f>`&=_H@1zQWo%`Ys`k71*㳆ԮXcD|cEvb[WDP- +bn-LCU1{!kvV8_>EXww/ș]}r(\n(CR#ht~AqUw񁨠qZ b%+l_.+ҘuS!h?dw7u\H QoVRV$Z!xYQ+F6}]/0cnn"okZ!m a&Jݲ B"PB{,KH/3Xg``qzAYܾж>>-VK\Dy>H@)7zH`n9ܢ/Z4{g5.0= zm?PίS 5sW+,+hrA}%3V!irjbdWԩR{bUL|}C|8R-@s|E{`X i hX$6c1(h0* b9nԊS,KA8zVG^J r /~B_.pa̎[lPdna50Sh_lÑ9ĸ%ǮW6VTYך+ c=i=| !֘༰W$:(Ҙ֞MvM3v3Qz5ਤ;w/pADxi@x,_>0]4_2Axӊ/A_.Њ[(r'\ Qgk 䎯:^bYszU/0cXk `kՙRJ[3й,@#pUE{m S4L}BJ_.291 .Ӏw| :sF%o[NU(vy)Q~^EP )?⊯Q_Y6N+CNDQ=бS6J– QS1> 8q &E=S2 ߿BP({V"t+Ĉ'ATv_.@r(짱 vgj'"sRӐ,bU O5y@HÊ4,=DnDاiW=*P,Ojp  pڣ EPh)>C(cQ QB_>E_ -QɜM%86pDml}_>0m qŃ:#Pciku{j>PQ 2qR+e:mc n"roEt5_.@ۈu{8Je{a-//e q5BurDUN{U`f8V Bu PA[s*Vx`_.0 w'E!L^0#ѽVLOվMtO!zpjK O+,S]X Zz"^Z!- ^ |QA|倢{@ 7`a/-j і7;5e! m3Z(+5HHcV[]Ltj F s#!4pˈFkrXo! MD)70?[rUt1J-vJD% Cq >. QMYv@ňڲQEQA "ѹl,;րgBlE vK_[P(fmO?DyVi,8GPvjv~YQc[Ĉ;aaԘWtm:/pRsoml5 !9; Ή%n{DZ(r"OsfN|5@g`Z&`57}β$`N|7.H40T Z(f?Kx偈R}tSLDz_0 QB(f Г|[I󳼜J J29G_.tһ+ <_.`"xӀx~v+(fN.}D_}G(x倊>>0#wH67(|ý%HO "│ox6@xt_3:mT$+ :W$ZNQjQs^\/ {.: X 8PlJt\: WԂ%)l dEN]tqzCԊqqt Lj"܋nJ 3;+d,!G"(XH<@[Ū__ ⋠X. s=6lJ/ZX/,<,agWGWtr™ ֑ؔ{ BY (B&ƍ6m9 (/܈eS @1}xF >7 4wP|r#ʫ\,|r̓!YX/`%{W(]\Er;ED`?(K1܀?P٧\vvA^gT@# ݒx'q G G;p3|X|=s*LF~0zF >tgC-hvy28m}A^OlU.P`j!]!]!ۼM׼ ,Њ<(!.@fR[W^#t 7x "wgvdP_s('@%bvVa/5\x0C'>p;>p=@+>+N\//( jAk1ѶZu=" 5^T OWߚC4VIW]Jo?ZXLYAmˡXX]P|x9Bh5ܢbE:t6 Dc"nN^)_.@pJe >@C+VHCTNgƦZw"x.1'Aԇ&(tgۺk3>*46Uc4)QTTD{pnɯ -ƻZw-G6B|J:nwC~Row#/p >Ii`f=l.J(a+-Xͫ8C) " M70A8.`w|6lL`#&@0m_Qe(7(qT rD?-`,|;pn+xEiٮ AMP+>[|ǽ,0)[^c\P5\l3 pzk!䇵8{8a}s е@?(?LB5%GiE!zGW4ی, aDhۚZN *r_N <`i.-rSi, \0G /Dή0s"4js}rL=Q]JZYOJY EpC0Xoz @'+H6Ch)3/0 W=\gxg5U->4vl֭'xW_^8q?P+҈L _>m=Ʌ_.q0D׍/U 鯇OTW3r|%ZΰжBJm0~6gWDid֋rHhI0j@=O]p|֐5@k̅ѰWLorNl+(Je!b%W }i*f>D!<;.Cc`6|@kp 0%_>@39@+@Q5ܢP@)vG#"ʻQA㚯8JV`IzLįd|\mASE$o;aDެ`sHBH;,Vlg7`csV_`` :]{Czۚbg/)B`*8?*CRHTTB{,KH/3Ob`q=AYܾж>>-VK\DybHy|OC*ut}A:Pa;qD;nb_v~l(Պ(E V{?Ll"Q%Q(5D@)dcŧqb7(åWǜ:ݮ0f Tu̴"PwhҿBOVg]/(۱!dxid>s>o8{{ 6y@H#E*yoir0VGhxPBHs=5f!aNYɢ\lH#4P!Xuz~n%QZ? ^ [N"0Xk_y<rv{m+qQ:*}(XGߥo 8A 1-xZ/{3(%*uw|bR%79lbQ @\HcN8 F`"s ̌AA;QT`h}Cq`4fShM[5R}SJK)!P0Ә8w0D=lߠ i/) *[X *Av`kiC^rz5`ckE!uPi>`@:jP  2bL+ iIkOzs;n:M3v3Qz5 _. 7{^ gq/,EYA7`V:1XLt/PZ΍d" Ӏ=**kmk`@rAecRjrP06=wA =Ǹ8nLc~f("Q4`?eW\ѫ^hJGW|TݰN+CNDQ=бS6J– QS1> 8q &E=S2 ䷦C <Nr5t+Ĉ'AT a(~[n4NL{Z е;CdNU bREjC6/iXGȍ(ZTpe =:jqSn X&5PTXQUF߀3xVBQ#3TZ 7e/%$TTcf(UdΦA8DqG}(0"lC~'Tg.Vx 0V׸_ei(' `:$E15"`%W.xp!*{wQTD A z1#~T u+ [&E j y\Z8t%)=k鉬{E:j2x)sj D9ua/܀0l_>g/mjq^S;#(m֊Da <_YGFbSo0j1Ĵ `[FHccZ_^ض|Ԋ*,6mŧlᦒBV ((OE$*,UXXV7ʷSPfqe|h'ڲQEQA "ѹl,;րgBlE vK_[P(fmO?DyVi,8GPˊ=s䒠NQc^ѵsv\Q#JIנ2P|ct+:'/@i uTCӽ5y-7٠/8BR|Bcp,\ LfY)QEfP Z(f?Kx偈R}tSLDz_0 QB(f Г|[I󳼜J J29G_.tһ+ <_.`"|k8ݥ/[ `F1priE} :w8D/T1W{F:6UɥoϏ!>pEIg+pӽd/H]J 49Q(pk ~6>(^hh9}fFEͱGzpZ(maS W!?46B<7M%ˆXx{m^̩U!.ă 'dSc+t "noPlJt؀_ϡE&J-XҊۀAf 0c nr1n_obZ<4g@w i7PTCAtŦ!%/> '`4 `&ɢ,XR>Y7@oJ,!bo!jE*gB ~ "c<79@mD ?GYD_gqA!r#KAA8~P7d1d1ۧ$-VȠ X8C:*EPl:ݦq|6Vޢ?B_ ՛"(V++Ȝoώ.ҋ( K6br@z +:q_:=~"ô;#"ض-9Udc5yuH|& eytQ>A۶0(]Y\Mq#0J3^(y!D] \ SP*/(.H`/pxnT|]:=P,WdU.V|@D[8(|A1s ![& 5\i9~8nuJ?P5 Fqԇ!@4`\xc sWӭ9- *- tO~\m4u *jݵ! w SZ-u8?pozp\ P8uRcdP|6lmdN۝,@e*9⊖s{M!ؔFq4X\k18{ 3'uZ+F?_!+L󆺀O HT\xbη hPZ-E_eu{-WZ|WA߽,D]X ŒZ.ܰ?{>pD1¢p  (UGВ RQ;#?hl{|vߟb<y*]XA> bD9 htm[ P 4ͥ5y@X|!krAEXgWW 9xD5>c&z`nsTױV|ӆg{B\l!V}ޖ OAwƈ!f:?`?][j]Ňnݑ-{5ZF l<s d\m=5y@RSCQ ̾nG|eTP<6T|h9Q RjO^K_(Y/,uxcL{ !ؓkag ] Xc.Bf|cEvb[WDP:@+J%@cG_"t~ w{Sx -^y…L=2jL!> F>PQvD8_`%+xL|įd|\mASj$sS AԘa J > Bڡe16ɫc׵23fPEջC?~ISq PLe&.JeYB:}!:>C^.lLq~n^p)<Ṙ T=0QG|nDcEfݳ` XZ:`C=O LHT՟H{IDJm c>L%OrE9R(ƊO"0AoPsϥϥWǜ:ݮ0f Tu̴"Pwh9Ajl{/jl\Z߿QJU 429{7=py` xt~7BVBe9HLY1Dq4{!*wR41zrkNDC(LQɢ\lH+ e5BG@P2{!@8ݩ2 + ro] W|]fWXZyEXG賂o 8A 1-xr-F h\`ԡ|D%N}~@!bc[D-!nA/[Z{C3/8ҘNr!Hl0\3cP`U$;4Zs6My?aS=^J rǹ!j7`:b97(~U: `?MyNPj`V! [{Hbc׫[+*hk͕zOE#Ĕ"d>^t6nHcNZ{қ;4 q/D>4 Dw#ਤ/pd@(a|4L|颩_Kz<!0n>Q =V½8 ^RNxeU/ ;L_p%`ưֹ!Zuf{) Tmiip8-=0ePmk`@rAecR4旞*1 .Ӏxw\Nm9Ng- H< ؃ ,0 4\S1v+:Wt:c{cQlEVc? J– Qp؍`ZQ8]3%PH~álECm8Հ#QnzfpAT!:n #'y/˻悊8t'2qRmA"P"V@ ]&/nW(VE셽Fb5"`%%P-,g@}0.U2z1CP´^Dq9C 3ÖI" ڷ)B[G 0QB|Za" 9Yu iXx储 ut򁢥{@ 7`a/-_.A߳Cd )ϝbٶ DkEԬ# #YAnu1OQc!HH3 2rNFSt_"K ZQצ -T@h*%DBVaaY`(>N"`Cћe!*_'ڲQEQA"ѹl,;րgBlE vK_[P(f$k&ʂ >>x^ Z {K`ֺcD 'hEƼky츆gMG= ص!;g;X!955N0, \ / 2#!  49µ0L4jn70e #&\th`l(bzP0U4@O.:@<3 q 4p,k-^gۀQB(UA @ Y^Nm%EL%xCm ū(C`:| .}ExEY+RSy?b+ɥOm3(Q*+XGŒ\ܽo#8 (FT_ý%HO "z4軑/;8oPGE­PxE)5P(maS W!?.mE+EAe\vB `x۰sjuU /}iQ=-p_.t<: WԂ/ 95s{yc nr1n_obZ<Tz#d@w"4UPbbt̐ƒXZЂ+r,D)jCu/8pF e2#DTѻB~[ !L *ୀ12؞Den?GYD_gqA!r#K54(>Lj"܋n l@|pZp 8AB1nƳM`~%VoFX{`%`S6(,/hE./_optEwQ].E!(Qޑ0 ll?/Id9}eS @1}\ ~_`V|Q^%^0\Bz XJ|Wz@BzNQ|"g,ep@gqۥS{EƞQwtA%O6(F!qwg2@{Qs*\P3< Fqԇ|cx!P.AG1^/z74~5gp> +@0Ni,Z!޾hjiֻشBc;AdzmwY7=Z`v:ճm]X*vSb6>^!OU!OUϫQ|tr0 /e({Zlt)Sz[.<SANH#lR :(;Yi7AE9V&ZlJjOjE3Áv8yn ^1;W<|pȯ2 ^bOv%,Ŝo/nҠm೵(-5![ jg±}gO}xLֻ-WZH3FP5\l3 pzk!䇵8{8a}s b6^(J\@1ׄ}!Ṙ+m^`Ŋf<>p;60Da\|q"C;B+>Dhۚ│\xm |` _>HC\Zx1b *CQx! |"Q+ "\1}w~`nsTױ ,|"!C7d-@'+H6CLsο,\Yέ=j[|hlQ2[_[w5"{4 pL\xѶ^r^%tKWԺa(ra CD}}B&x(< jW}h~VZf>Ja(mk`FfmZ%D zGidַ0@Ea)\-(B'R/b0 @]ډmE>\B,P䊹0{ WJw}Q,x*.lzn"Z,ܻ;LIN9X-WAXV.dr !Pc ]hH4:8@T|VB_.7y@J)4>Y@ܽ`n q!!3 DYIZhn ebds?׵j3K(¬&K Of-{ * 5P+ʲth2C(Juv} p=AYܾж>>(-7@z|C}rTZ!:D9b:@YcgaV}uv'_.`(_>P((R|J{rBI.ۅC^6@t|XOf1N+U381~Nz?2jl^u@/PU3Gqu{:ExE>0_.ʷ{GJV *fƪQ ^(Jz\r9MLܚS3J0SzrAT((Mi;E.VbE CD%kQ87pzS& ` +-@$ Pn"`%_`i%TD(va!7!_>@|4c_>`ԡ|D%%aJ/B]oh#Ph @\HcN8 F`"s ̌AA;QT`h}Cq`4fShM[5r^J rǹ!j7`_>0֯Z,~MyNPj`Vр dE㮗^ ؂[Rӭ2ѹPi>hrcCḊXct^+ iIkOzs;xȇ(vpT@x D;QAP8 "4 r /./` `2tZX0RAgBʼnD|tVG<@, |zQmV4 ajr+3ڂ!Zuf{) tn$ ip=AUQA{aʠNӠ2 R}[`mqu`{8 q W- H< ؃/p_yb\Mir+b*F}eL+:Wt:cZ 쉞UX `TiA uw#8T)VfL4p(@PfD@`WFKOw\QOc83Qi5@ 9U)iHQ < aE}"7@ Ӵ+rXpn~b}'t˾!vsA.48_EQrP fJf.cۧM*#؊} saml}_>0m/+tԙK^$-qO*"P&N*8uڀs _ bx_6x!8{/@> .rFůQZ( {Dn99_.0bk,ivPګp'T wfBU@$"֋b$W1ʜ ' ( [&E j yjn5%ħ)R.c-=uXXG̩*_>䰎_(Zzp&ز@/mjq^S6^60xR>$4fD5TCLϑfeLU5`,x]K ZQצ -T@h*%Gyn0o^#jFdEy.4DʳM[BN 5FOV6-/Q R=H8/*M||1NM X#aԘWtm:/pRsoml5 ! QVe>." (BoM!{(r j#!,8hskaiܬ9˒9 ""L\QV!T5iP0U<Q #pJڀiX4߷!Js,Гogy9!0 er"\wWx\+D|R٭0][8ɢ>f} Q*+XGŒ\ܽo#8 (F^UnPt" G?5~7+kAߍХ4AAN gC1:NӧlfZ{/KC .'NB~hmE+|/`=a/{p t4XKTY,.zG" E:4{I]lZQXkA/3f,z"(Eӫus$2y"*]!?-PH2q,gh0FG3P27t7PVyLQgC䴷GHKsxq n}cDX cEOI|[6 Ϗ,\-R /qX5k+!U|啀dηg׆ME |%v19 vl2 :i uOvzg$BTD{G*dԴ_.| >c,t ܀0Vi~b>F8,r̃!곰JPEG@B;E@E GYʬ@g?cK}Ni*UghZ~: ?PQx38nx3G@@LLhq_(f3L FqԇΌ|cx!P.Dc1^ [s6[z?pT!Z{ ++x)]F CTfc.@fR[W^#t]7؃2mlwg# u=~n^Z(flh,Mrh!QjEN?]hgEѵ*Vkh- vA.[%_0¢;{!(/cNXAw4@|ѥm `1Q+C@)31mx9 ʡLb |(˟L4TnTxkإ,*W{v@)'^E/: ކ3EmcO̺h}=@M+4;D}| ۆy7"fNٶ` @ Mjq=sJ{ jBBr_0}\Ysy]͠"gݧO[໑kL\ P8P$4f ͠ x !JJ|AE9V&Zl-+@i]b18yn k1ZimG*@60PT/[bYv@}L֢lXny&- G_{/fwjrY4her1fu+dX E/$(؞okqn v4'g?Q|B(?/pMhQZ@QHQMm`Ŋ˄6sH}&X_."D j ĕV]B{ r,/ж٠/̶snSxMsi_s*W_/ A_*:P> Ҩ936Gu+?kg=m(}g+ζb՗!mٞ>YD9~gbL`jY40 W݋ "뚶sbjݑ[j ?"{4!B\m۹Ô2/Qjj(5y`"j5 U JK̇_35y@h6w0GT1 ga Ff(׫,sb@=J|v*u Xc.Bf NJ.Ķ"Bt-b%W ՕJ\a!jE>{/}w )E{Ŗk<EB&u@5b8/(}* VTAZNa>S_ W@ܽB3 DYIG=BH;,$V#D9n_ת,DkoHaV~[Z Qt!0?3'CRH4@P(ҡ (}Z; EAyQjZiG0d-V@ZB:_<} !B?UL-+`bEf}g50;`i}׻oPUV4TY_`(_H{IDJm c>L%OrE9R(ƊO"0AoPsץץyWǜ:ݮ0f Tu̴"PB?Nz?r9 5֕TL#Qy WB_@w/P{#d%@N+TsjbdWi@!bc[Di |Lֿ7Lp F5Ɯp;Eb1v"QMݡ(h4by@,|6k RC`1q`{ ߠi/) *?^'+0wj֊ =;B0Zse@}4u@1ՠ7 DqEsړܡi{ DbǨ/pd&@(ax4X&htx,4y87̯̾l}>z0E{q"@&/|j`8yX\ڬ=`a2+3}t >֪3e04 l u:w#p؍`ZQ8]3%PHdEC}7\\ ((1zIlC2ߖFa? S{*CP#BdNU b/0(L aEXx7pEvQ=*PŶOgnMj 'p9g |PZΝ3B8Mͱ&\tm-mp4È "R۟X=qX"ip{j( OC@8LvtI (҈q9 "V@ ]&/mD PfNQZ( {Dn9߾_0e]!q^T@/ VN} *hkNEJ fBU@K\2eb$GVLOվM4`VpjK  wVȱȺWd,VHKzT/D9 ul0l4y }^>ڒ5#c$4fD6`bi=9LC_K ̌y3m[G‚kQ|J n*i \a@R݁TDyn0o^BqDm( υ\y _}k^3WA|/-fX4Q%}.x|Vv~uLjN4ЊFyEצBq GϚ(5'v\B񍝳x9?J\DC8ʢ뼾y8pZr@_&p#>X FV洌!v$!. 4|%`B>Q~ZLLQ #*q 4-/|z(!z3@ Y^Nm%EL%xCyr"x2js *BҊ.E{EYpw/[ `F|>&/^׹{%|(6ұyADQ! {G7(J:{^se_軑/;r7(ԩ­PxE)5P(maS W!?tycuQ qXi@腪PH`쉷 {1f_W:z2k]ޗx PAxJpE-rl<ȩ˻U]tqzCq!+CPZn7PTCAώ cp6ĺKE-L0('޳}}-fGn+ _&p 25zWs˷61`!?[슱otR " Q:@QZ9""?3E  -] OTLY|JPz >jE{₊D GYʬ|AgۥS{EƮQo}@%#qx: `ǭ\L.T DI Q)@ԇ!@4`\xն.nl9|:= !]!]!ۼ3KdՕ0}|cڈ-O{Tn[Z!DhJ3J1K7/)y J1t>!]All)؞!C/6^oabC9 "PbhEP`\;evRN^)=/J{e{ (pN4DEtfjlZu'kW8F@њөmfϘQBcJL<=vAz0\PQfPOiQnO[nq~&Yp Ii@ A[>N2(aQTc5kE |G46KL4;@r'm؜!N2]ZwGL9aZ"4P (}9UE-2Qe1ZV0>[Ҳ2usnoZ٢prwY.0)[q1WA#(3m[BJ}if w },is8P¢짭P(ykBK*BJ0(FpD²3&^T4T"` ~{\삨 }j`mM/̹ Қ_s*WM/QCrAEXgWW 9xD5繾c&z`nsTױ'ݞPWlcU? 2i}"4`s10c5,+@= :lS1\:#[_Ԋ4b 53.<s d_.=5< Fr4Dr׍_@QnH3r|%ZΰrжBJm0;{~6gWD42E^[n%`Ysb@=%㳆Ԯ*֘ aXH@b[WDPw.(VrP]U1{lV8/xh-ŖSy…Lw,zeԘBj4p$_PBUD 76)"^ j0f%[_!ˊpZ}1}]1Xz7NFf5A PLePEj@Ym_fEi?W՚%TwVWgC]}Rjo0.S DݲB+ )PaؽiYսn{As;NY6BQ`7`cDv*^Rj[ØSɓ\QcJ{F1L;|Atw~Oǜ:ݮ0f Tu̴"Pwh9Al 56Ul$0|}pBm@H#t~7BVBe9H^#Dq4VI'T: Г[s `&BfJ?/D%r!ДZ1S=?d}ؖ!ֵ8g400l=YU('W~'EV` +|*8E|F}kA b)l /X//(%*y-1 S~*6WL|Bhb}bbC3i hX$6c1(h0* b9n{^ gq/,8sՋj9nSV:1XLvK-@{FZ " UiTTAXPiPX_2|1 -Ӏxo\N 4zPAm&©*.O( LrA 'B@S_>~2;eS!*~?w"ʞ XE@߲AUp:K@X&@0naDp0gJƁ  xj@`WFKOm=/ma;(k vȜ@4( ѷ%xES=/iX \ų]Ty Pq[gB0 X&5PTXQL@]Q\- I'pa3^6!JH:T4sU QfpA\c3G(VE셽Fb_(aηfYB\ 2W8{P|L\NYcU eTPՊVTD…;bIFQE_Q(aZ/F_9C 3ÖI" گ)BQ.]m DA~OA Zz"^Z!-SSU_. rXG-^ {alh }^>ڒ5#c$4fD6`bi=LC_2JƂ׵84m UX8ڴA󳅗J-WXE7bw?g*"yxn0oC"`C4ϑ]ȇ,DQ[6 (*sy@$:Wmevr8 >[Qc= vy3YAX4Q! Ĝbj^(Ljs#Jy@+B5]xΎo = ص!;g;qb(qbC(C8ʢ|5\P 3: 0ӨYJBn\<"L\QV!TP0Ux F{NI0 \sW%Ro=84? P_>_tһ+ NxyWEYv٭0][ɢ>f} Q*+XGŒ\ܽo#Dňpxwti8^j2W\YK~iKyAj.E7(iGEx­YUC\ZN߲QjQs^\}8i`S W!?\%5 Tl'6Ŝ}]BֺbZ/F<=Ͼ@q z_D+j`r"z E nr1n_o'_)3PAqt ޑ*HCQM^hcp6z_h@ >̯l`&ɢ,@_egY7@TY!Lm @ Ae,XVAbw##mBr,z/SԠ9}#KAA8 n{Ĉ"g#DDp?,!*EPl:}_.Zߢ?B_ ՛"(V++Ȝoώ.ҋe%v1|  HEMwuOvzg$BTD{G*d_gd¶P8e0\Akg@;|wP|r#ʫ\,|r̓!YX/`%+.Dr"PAnQ|"g,e8>KCi{FU>Q >`@18(Bzx&g2r.P%ZŌ=bG}<G 6-TW@9Ƌ 2 nlqrWu@Y\w\wo@4Kcw?rlb; x/h(29 B1rml{HXwvȠm(~ QgO- ,)] e6Y;Ȟ_.oUF>rm k| PCnLz> J^1^J Rzv߇!͔Eضmxϊ P7|PX}b=DCůq,/c-vTE2;?8z(r4\q(E+[" QPwfjl,2}kF%r64sjE}@kNYUgTsDP+*䩆D{p'0x[<0,Zw-G6B|[jlVtK-ދ\`8v+ {Ha3fp(5N@0(-Xh8C)" MA8P]0|6l}gX =G Lk8BWT q}9UE-2Qe1M/ l-J>-Ϲ jg8x;{Z\=k" [Xx>/pD6nE `FPr -9J( )> |)ffY./²3&^BK !VP@\i%$ }m[\0T~9-yHC\Zr!F(`T$uvup}#AQsݍDۃu'CLJVX EsJj0bce{|x#CLX=fе޽YMzZutGii@v{!(c S| ڶpR&\ FU}؏*yGUBZZ?+-U3r|%Zΰ|@hZ!6Qj~6gcHyFf(׫,s`k71*S؅_5*֘ apXH^WDP- +bnT 䪘=}<;.CԊ|g^Z{o])iErtb<EB&82jL!g8/(՗Ie7 @Tx}Єįd|\mASj$ AԘa >ZUOm( 7ɫc׵jywt[`aV~[Z QlK !D[pAU$jV(y{e ePs(\xE*uE8|cbjիJR{pT&V_6_0= zm?PίS B5X "`(N/H{IDJm c>L%OrE9R(ƊO! eF(qѵǑ Vr?iPs.t˜1lP1ӊCݡI'g] <|Pcj =^]id>so8{{ 6< r:^w *yGX5b!R61zrkNDC(L储dQU6>P!Xu_z~^%QZ? ^3h,l5WWD9/=(V^^x ({va!7!O/h̜!ӫ]_S(vP%/8</<'&Fk04yƜp;Eb1v"QMݡ(h46 X8W G#/U"3)>qߠ4q )ϩT*9֧NVa1zɱՀ{v`ֵB؃i`ObsOA1% q@eȇW$:7P1'=b%x|%D>4 DՀ /pd@nK e,/( !S}m~&Z W>Q =V½8 kx/|j`yXEYA7`Wf +`}Ug&Jyb(mop i9TAXPiPX_.2 ni|n>Nm=NgU+薪DӀ=hOI+O/(=DhJ'CP[6@}̡s'"쉞U[04 l u:{pڍ`ZQ8]3%PHdEC}MveQ$J~on-7~`<-UD7"sRӐ,b# 婆4H .E\+ykpEU@&,Gں7A*ܠ:"…6Ļ@i[XN fUT!a/^S檠w b+6㶏R8aD؆Xs\8A,{8^;5( OC@8Lvt㬓kA"PcB+Bp ^D" G[_>%q_)Weˢe{a- irY. ^{*T>fSؾ5"`%/@{,\ (~+`/_Q(aZ/F_9C 3ÖI"^0![qDuKW[Q|ZabSPȱȺWd,VHKzTD9EKo:nDedl_>g/mjq^S7#(m֊Da <_YGFbSo0j1Ĵ\ `WFHc傱u-/ F/lB>jE6mŧl`@R݁D²P\+ Bf? QUDQ[6 (*sy@$:Wmevr8 >[Qc<p^M%0O! JebN15`/cD_00ȘcD 7FyE6?k:Ԝkq *C7v@w+QvS4^2, vQCxDkyBg\`Z&`[C 0PDCH40Ӏ}6WUF1i / 0 e_0~ QB(f Г|[I|J J8 e9W /`: E%_!r(ʂK /[ `F1psiE} :w8D*+XGŒ\ܽo#Dňpxwti8^j2W\Y6"@rjaT_ ~VgC1:NӷlfZ{/30$(maS W!?4|cuQ qkpFvIobN; q!^t4\ZW%\>7| ؔ +7\`t:iENa5|@Ss=w0qAmP> \ Q+RY,.zG" E:4{I]lZQXk٠@Zp?`~e3QNg.+?[̺ |$2<djo($mb*gB ~ "c߼79P eenŝφ -] 9W@ucO&, >'F9^t)`˦Dp?,!*EPQM`~%VoFX. s=;lJ/ZXP^lr@z +:tr(tA5#DE0w̩B&O~!܁~o5,|b+xm}ǀ/0x+ib>^C](?p̓35^ ga\P}BrED Y*> .]P,WdU>pW@DW/$nqP(fq]x8L>P,W˹@@LNhq/3*Q;#rmAs; s#/ztk&`ˍX} ++x)]F +\fc_R㽜 x@/ǀ?TAb| ,Vݸ2Iůqr('@}JKŌ;_M3V}:M/0Xo֠h[Ⱥީ" 5^T wAA?|s  +.awY}@XLYAmˡXX]P|x9~Bh5E?Pe.`ؽH&`_> r:ơ Pސ1 8[E"p:35 XQ϶uW8F@њөmfϘQT<8&- /WBj9@Tz[zysx9^-g68b@i]b1 p܆$X =G Lk8BWT q}9UE-2Qe1M/ V>[Ҳ2usnoZ٢p/|{HlzxEyrA9@Ԙi3غ>X] TK0cm $p[ &(q ((<\@1|kBK*BJ0hʷ{Y+2 hlp>p;D xq"C;B+Du7?XO/mk;# `mP) _4\ TK F(`T$uvup}#AQs;fm:V~! ,|"!C7dg OAwLj!k peڿ?ZWo%Gl}r/`/q?P+҈L^ /=/Q c" _>`>2{FTPUya?̇_3/ڶVH fgz?MY{@1zQWo%`Ys`kܷ8>kH_>Psa4Zrx$ȇ+P(\17! 䪘=I{3%X U\`%W SwŖSy…Lq,eԘBj4p$_PBUDy]| *Hʼnoįd|\mASE ~ 1@ԛlV>7,$V#D9n_תf mQYmMPk1D}.)B`*8T0n!ThZ=P%CۗBQ'@DjMܾK+BPql/ XP%^Ͼ1"TZ!:eLdEf`JM XZ(un) RR`YA*l.REK: PJmka*y+j! -Xi<v& cni@tq~Oǜ:ݮ0f Tu̴"Pwh9AlW},g;/PU3Gq g/t@^!ئ4B_.@w/P{#d%@N+Tj'ހ?|` ?\L,~p:A%s Y8gЀ Ɋ4!]/9vvώ̺\Y4P{0 iPLci5(xxaHt6nHcNZ{қ;4 q{!|hb׫G%_. /G'1F̰eR~0o u%)+䘷Dֽ"caBZ700| *a_(Zzp&ز| }^>ڒ5#c$4fD5TCLϕfxeܝ4*_. ^`¶-VTahQ|J ^*i \a@R݁D% C9+6O3e|h>Oe2<Ds&Xv~a{!'H 5Ɠl[ |N *Ŭ كbDYp{ WB9FTG/Q̓Z¨1X Fz, S( !G$i@>+J*j}S偈R}uSLײ /|z(!z3@ Y>Nm%EL%2 0gsTBl~ "g,x?fyҀgL0^s#J9|(6ұyADQ~! wG7(J:[&CxEΕ5lo#-t) /;h97(iGEx­PxE-5 [6} qp(NB~h6/ 2~.zaB `x۰sjuU ֺbZ/F@Mmt `q;REi(СK:bbt̐ƒXOC{ 7Br=wYb}P|%UG Sw0|@!iCP8 [p4w##m,enŝφ -] 9W@ucO&, >'F9^t)`˦Dp?,!*EPl:ݦq|6Vޢ?B_ ՛"(V++Ȝoώ.ҋ%v1ƿ$o羿|(tA0H"nK`N2~rM/I7|Ƚ_P1 *>{.u=P,WdU.V|@DW8wPbwPx38nu/<|L.(_dr!]AwY7=Z`v:յm=3>*46Uc}Li|.Zz_> *L>0\PQfP=P2DS薺[/r= sV(B~:)12(>62 '},@eQ¼h9jDMX ipmwh wvN۰9C`#&@0m_Qe(i (qV rD?-`,|;\@+r@=EiGc97AlQ8߻,a-WZ|WA߻,D6[!G*k!䇵8ºsCA(- {` %A@e2& -9J( )> |)ffY,D²3X//-2n#į;8?{]X/ж5@M/̶97r}5|@\ZbN5\P(}^Fyo޷/uo1ĴݞPo0cm 6v @6(6!BK {8peڽ8[T7ZGw$`랖}wZF l.<s d_.=5< F:aQ5 *!O=gP0!W GM/m[+3J30glxz/A$z PL#^FEK 1W }*㳆Ԯ*֘ aXH@b[WDP- +bn-LCU1{%^xr>/,;}B3|^r}*@Q֋(CRxF#"}₨ 'VB/`_u q9M)WTX/Qc7+)\+m(nuz_`` :V?Ebg\RTp a&Jݲ B"PB{,KH/3" Wku_z^}G0dxHKUHȘ )7zH`nYm[G(0kxVž:;ePQloDEQDt@D0T$WԘC(l{Qld{G/4?>5IsQƌaVD?ݿBOV&`u" sqK]l->"io̕zO4Vb>`hk6Da4椵'CӀOD>4 DՀ 4Pv{L4셱e=;xhKz`dהH1lf"QXWjǑƬ ;@ 1>WBisw2Ҙky`,x]K ZQMD)70?[xrUt1J-vJs"X*,, PP#-*4VO"n\0Ow`F1+hCk&ʂ >g1?v~uLjn4ЊF;x (?^l9tD97`6To ! W (BrAq44hA=/8BR|Bcp,\ Lf])Q# 44ﳹB0O9`2@D)쾺C)ikY_>`NP''g P_>_tһ+ NxyWEYv٭0][ɢ>f} Q*+XGŒ\ܽo#Dňpxwti8^j2W\YK=\fc(`wFߠP}jA3jl(F}m Q"r͌RcE}}8i`S W!?\ͺ(~_.<\?|{m^̩U!.~½FO/POBy*(TT`2=qO/Nx2] 01 OA97p1DJQ|  ;E;X\TD*t(h2@ش3$$Ҡ@Zp?`~e3QNg.+?[̺ |$2 djo($mb*gB ~ "c߼79@mʄ enŝφ - q@ؓ >ω`%+DgJ+زiO9 kHJ,$NUWBlfUJ 2۳Kuee] /_optEwQ].E!(Qޑ0 ll?Y{_.Iz@傯Q/3/(5\*<+ 0\Bz X| >\=!TP=/[H`?(K1ORP{EƞQw)U{%O6;(bqP38n.<L&(_d\J &z'8nFϨrAԇ|cx!P.Dc1^^9ˮtk&`m(Wu@Y\w\wo@4߮3J12C\ _:xAH8_.~ xo1>ip#W" }"@[>{n٧Pλ Y؛8 F_`J[Ⳣ4|"8@UVk ZsKVI`׻|]XttpE %_J Rzv߇!͔Eضmx g{~qt|PC.D _X!8^Zv>k݋dv8z(r4\q(E+[" QPwfjl,2}kF%rwY/0Nl[0c} @ MXSbww(QTTۂ8Lix)DTԺk9Bs1TakO[mq^ \ P8;h@ 6s@E!qri7AE9V&ZlqHkӾDcT; / 3D)z;b~oUy%ؓ**"i e1M/ l-J>-Ϲ jg8x;{Z\=k" |̶- _>0E_҂ Ĝ=$\0}*:P Ҩ936Gu+?b 1m(}g+)bݖ OAwLj!fο,\Y8:{?ZWo%Gl}r/`/lVyƽsA1) _>m-uYi+rB )RL3 Ķ"B[(Vr[ƽu+b%>(Ck`6_>EX8( g,PL/KW(\P.dr1.hH4:8޻@Tx-ivS!h?dw7{F1@ԛlVi6^~@lg7`csV /0cnn"okZ!sIS92(u.DC %o,!ھ QZT:[mqxf OU1ŐR{pT&V_6_0= zm?PίS 5NRLHT՟HTfw/0ݽ {QB(<7tw], 7((l*Hc=a{ǜ:ݮ0f Tu̴"Pwh9Ale/(|ZBWW>fJt6&|xa_.ʷ{GJV *fƪQ _> %'T.: Г[s `&BfJ/D%r!ДŪ(AJ֢q^L4 Wޫ+D{_"+l[&1Q F1T8L({vaL#{:ZЌ=|̩C ! FJvE]<@!^*&~x1W|y`X4`F,1Ej w@1 FS`1m:֍ jE 3[h RC`1gfalsoPhgf츅Ӕ -fz M}s80wj֊ =;B0Zse@}s1esOA10D4|50 Ht6nHcNZ{қ;4 q in`&]Lpj@L8@A_,.~E g6Po Cr+3`V(^8D=b{PUTP=omk`@rAecRjrc4 0n[PpiqIlT%@Tb{Pp_y@H!ry(M_pW~!oTE1ϝ'zVcзlF-AN]Q~/b|N_qLT+ zd ɿ h{V"t+Ĉ'AT{v /maSgj7"sRӐ,bU O5< aEXx7pEv۴+r'*P.O#B ,(\h*loH+*~!}?lF(a/^pyE檠wA(r? h_tj=92 u)90Vx_ei(' `uڀsڷ@ G$يȽQa^\%@+E>(VE셽Fb_.(aηfYB\l9P{*T03: 9+yx"fBU@$"į(E0#ѽVLO~M4`VpjK `R{ 9Yu ieRTD9EKo:nD^[6j і7;5e! m3Z(+5HHcV[]Ltj F s+!4ʈFk`,x]K ZQMD)70?[xrUt1J-vJD% C9+6O3e|ଂ*FԖ"( \hΕg`ݷ셜,>#-*4VO"n)9-fI?D}Vi,s+{#Y% "Qc^ѵyxAϚ(5'v\B񍝳81ƍ2#" (BoM!{(vcjG9B@j@hskaiܬ˒9 "xDrn j}S偈R}uSLײ /|z(!z3@ Y>Nm%EL%2 0  X|ș_>( .52 {m^̩U!.ċ X(OkPA7|a~{ N')l(rb۠}V|(>A w@w2/B&c/M;E8JKb /h@ >̯l`&ɢ,@_egY7@TY!Lm @ a(gB ~ "c߼79@mʄ8""?;E ӧ=@ZԍsƞLY|N(+Y!r̽>S_M~*X8\C:U`!u|ĪѽM`~%Ė/b)ha_@YxYlagWGWt~54(tA0HB9Un L[r%o w /(CtY8fbO5> ~~L,. Qn%_/df<Vr]/|B#.! ^Yl(+2v*| HTQ= ![ & 5\i9~8nu/J?P5 Fqԇ!@4`28m]` [s6[2Vk\w\wo@4Ko]KU%E 3DH+Pe/ B1 ؃y6H8@Y\2Iůwr('_ t>%bvVa/`0:2܇'.Nw\: /]XJ»Z;h_o^.[%_  vat]%oS/V[%=_qt) 46&jec}3e`F>!C/6އ"F_P 8CD;=@E{]Dc"{N^)=/J{e u.buZ!*3Pc M;D}ȑS(K̺9F@њөmfϘQBcJL<=vAz[Ҳ2usnoZ٢pr0rNruxE@9@Ԙi3غX= TK0cm $'`CXpnc9H|ڸE+Bɺ*2 ׄ=BJ0hʻY+2fE 9x_C"BXڡIۡ㺏|}. r,އ h_v frj`_>i.1a*CQCrAEXgWW 9xD5繾c&z`nsTױ!ӆw{B\}!V3uɊ ҀcZJ+@~Gg?p j[|hlQ2[_4<"{4 1D" m[pR&ގ{@0! ̾nG2*<~v@+r}MuL54Rjޙ 3 p/]]Pl>(\zǢP@)v@GŹ/TEQAhq4Hįdj!h}78{(.3 DYIZhvheEYI^Gsܾ0cnOCzۚbg\RTp a&Jݲ B"PB{,KH/3" Wku_z^}G0dxHKUH->Q~"c2<`>\!:eWMD}V6k^޳0K{b_v~l(Պ(E 7`cDv{%bv+PJi"p\QcaJ{F1LǜW1n!Lrh=+FcPfO :fZp;4c dl|}`*~Nid>sW+We!?݋>TY #`{1Z%PyR&&@On)h%W)<,ʆ4BS" @b( QZ? ^3h,l5WWD9/bɖ(k(,޲$ A|Q(0[BoCLa cyo/ZUf߿tB ! FJvE^Bj,Zcbd/ߋ)Q @_p1'0B``fƠ(HTSwh0!m03M`hk6Da4椵'CӀOD>4 DՀ 4޲AON+CNDQ;PDa:}!`TiA u"pڍ`ZQ8]3%PH~@ <nr5t+Ĉ'AT a-7~`<ŞVtSe9Bye! +»+xjQ=oÕ :n+2/lYL{w aVa ,(\h &g |PZB8e/%$K(\4ǶO,$sU Qmp4È "R۟X=qX"ipwj.( OC@8Lvt㬓kA"Pie!8{/@> AAK⾘SPE+"Bo!Dn9WBisw2Ҙky`,x]K ZQMD)70?[xrUt1JM]JHt^h*,, PP#-*4VO"n)9-fI?D}Vi,s+{##` Zw(AaԘWtm^h9;ל?k:Ԝkq *C7v@wP~J!eQu>__.(f8-4eG9B@j@hskaiܬ˒9 "xDﳹB0O9`2@D)쾺C)ikY_>`NP''g8!0ppNzw_ O/ 3\( .2?fk 7>YGL{Q}F?/cc-] 8UoL0oϏ!'M&%HOR!"z_H]Jz_>ϣ"Q<@l(F}m Q"r͌RcE}}8i`S W!?\ͺ(~K5L^؇!<ۆSB\=/Do!̯h啀dηgGME ,e]%z3~AiTt~>uCQ{DJmiwF"DEmw[:sJrG[] \P}Ѷ0(4|QF%̃9zpHQjEN[ Ⳣ/]XJ±Z۠h=ToDv~+T q_6Clk#^J@|ѥ46>`ZXLYAmˡ\X}@Yr(܅!"Pk"\}]ʢrWltCi@Y4_ 8[E"5;, AߚQDzE]by7"fN5l[`X*>4Aq(퀨 y y\m4QZlt)S[ Ƌ\ /p%@I!ץHa3f>N2ijJ^^-g6X}@?HQ6@~X!871}~ڸE+B(?&(B(To(nb!A;!,!11|_C"BXڡIhECyi+Dqw9-6US)RE/iFҢ9+~2E/倊Dή0s"4js}sLt=x樮c%g ,|"!C7d-@'+H6CL8pelqo~VSCcK*pf}< yZF lxb>s dm|SQjj(E/LCDf_7_.@QJK̇_۳'TP )RL^K/ȬzVre\-(B'[RXc.Bf~ NJGۊ|" ҙ\17TW*rU8Bxvo}@ Q+QM7WZo}S@/ ƥ-ק \X1.hH4:8 *h>@AZd` įd<ۈQ. o`!e QoVRUOm( 7ɫc׵^f "okZ!sIS92(u.1.M@5P+ʲth2C(Jkad \^.Դַ` bHKUH)| 2FDzL-+mL'*s9k~+a{&`i5PίS 5OR@ _>!QQ*^RJ7sPxl0AoPsHѵ{ ~`n1(3U381~Nzva<P1<ՠՕTL#Qb]?8BB݋>TY #;AX%ݓ4O|R}=5f!\adQU6>P!Xc\@aJ֢q^L4 Sy('W =EV`=\+kW"~8A 1-؎}^ ЌQ̜:o(%*uq}Bj[ƶh=cbDi Ŕ ^(\Qc f i hX$6c1(h0* b9nf9@10D4|5 xEm`J5`ǝ_>4c70ŮWJ3|p @Tr gDD/CX&_G4E/ LP CL̯l}>z0E{q"@&/|j`yXEYA7`̘P8q(^8U[D=b=**7mk`@rAecR4旞*1=`ܞNcus@t:-η8 J6("Q4`_p__(Д+b*Fзl*"CNDQ=б[6J– Qpڍ`ZQ8]3%PH~@uDMveQ$J! 4|o 694D]o3DT*!EYp-+Pj@HÊ4n(ҷiWO8`U½ 8]-G5PTXQ@ ž2C@E }?lF(aCmX6I@2gSjE6mŧlᥒBV ((ϙHt^h*,, PP#-*4VO"n90Ow`F1+hCk&ʂ >g1NM/Qg1gF=0 \ڀCʜ7`JUЂ7zrqY>Nsviq*(4P|z2]Wpe9"_Po6Rbvm撫xZ/^׹{%?4cc- 3rq~?erBQ8CnPt" G?KM+ke_8]J44a uQ(pk ~6^-5P(maS W!?.mE+_`obN; q!^t4|XKTh-pLQ / \] 0qAmP> \ Q+Rnj;E;X\TD*t(h2h1qȟQ- g,z 43}&_LEYn#7+ QAF an6B 0 W(oFD#n{Jiږ+ O/8""?;E ӧ=@Zn٧ŧ^91d1LI|[6 0`p T)1nFo!̯h啀dηgGME kV%va^tJh(Wt~>uCQ{DJmiwF"DEmw[:s%rȽ22.a&(F9m'`>h9`,8|| 5@ (_%?Pf}dfWD9ga\PEG@B\ݢx",e=@g?cK}(+2U8>Q+=(@1=(<B.<\L(o0rP%?ND3U&8CgF1<(ۂlDc1^ [s6[~N(C0w@Aʑh4KwwwI?rC Rʊʆԯ8<~=0n`#4P48DT}ů{rx(k1 ݲOi w@7q٢ `0:ER+rx{Pu{kWJobmD`RU!]aS.,C!(WԋtWIW]J߆fmdD}o, Duh.P|Vl(zAbXf(ƫhuEOP`\;evsN^)]/Je} g(pN4DE@{jlא [3(S(K̺9F@њө>X1BcS>ǔ||ZT-5p6} T+-  J)"'AagMAp(uO? J{s{M!ؔצ}w b* y6l'`#&@0m_Qe(i(qV rD?-`,|Y˜ ]k೵(-]as}e̕۔|׷ï|O ZWA#(3m[Bdk!䇵8zsCA߹Q[aQ{8h@J__-b 8Rj֘Lpw(,+2-= j!a5$L2PIq6T"`wKH;.@Tc<@A /̶97}5\i.e1ÊT偊Dή0s"4js}sL{{Q]JZYOJY EpC0Xoz['{Ķ"Bt-b%W ՕJ\a!jE>y5@kpa`Jzkxa(8'(@53 FPQvDg.h+Y!`0=/_:w#M:GH QoVRmKBTi6^V{1gl_תef "okZ!sIS92P.]xZ=P%CۗBQZ;՚z!81JM+m} zX ij2<`>\!:eWMD}V6k컫1iYwb_v~l{j偊Dev{yQrE9R({!0AoPsHѵZۅg`"s `n1(3U381~Nz3g{Bg.*}uU%0|}pB 4B(T݋>TY lm9 *@JyGe.[s `&BfJ_/D%r!ДZ1S=?dd-PNoLD>G_Up2QN˯Pn"`%_/( זE8A 1-y̜:o(%*y-1 S~*6E{LlLe}1eW|`X4`F,1Ej w@1 FS`Zbj}e)G% {)E0fS|6`Z!`_/yAy̎[8M٠Pj`V!4`/6Hbc׫[+*h3GRQ\4@9BLYjP  2b^+17Ab q"ffjQsa mAx_w (ai 2 l`-n?:/<meiw~ja9{#ʴ\}g!.j,܋2x+餭yXEYA 2 1D>֪3 lE+@\qGh9nyaaD?/ B‚=G/-^ {alhy }^>ڒ5#cl0d1~m`&Z+5~f}Ii r믋Nmzs%$^(23Ó`/ F/lB>jE6mŧlᥒBV ((ϙHt^h*,,x(* Bf8Q }#jFdEy.4DʳM[BNgg+j'Z`_pI(f~bDYp{ WB9FT۩ s#aԘWtm^h9;qP#JIנ2P|ct>N@ %qC8ʢ떣r.f8-wPr>3: 0ӨYJ1Ďd DpD3 (gsE XP`ق0B@ey3D tzrqo+i~|[ISA <\_tһ+ NxWEYv ٭0][ɢ>f} Q/BT1W\~ "bD~1crݠ(lE~j+Bp~iKA8AN<*n φbt+ -o(9H/r@i : X mE+gv쉻c{EG/}iQ=L (2QGZrl_P\*}qAmP> \ Q+RY,.zG" En4ώ@1C8JKb]/h@ >̯l`&ɢ,@_egY7@TYe8BD+䇹 IP&΂@lD+ƾy7=K%4Dmʄenŝφq}_4w7>QEj{2g^SX cE{We" sאU`!@[7 Bly"(V瑳XA|޵!`SzLd. gϮ.jvX}lJcȽTEmQB9UdcL:$7w1(CtY8fbOG}Zg14oP>Veߟ,(BԵ>JO(=pDr5"PAu|ޢ"kQ2WxRP{EƮQo}@}%#qx/(Fy0CVbuM&|Zb$-bdvQf\hG 6- * r$Eg]Ol;9|:= !׷^,FDS\}^R0}h!BJY1XPWziPAm^Q|us٣5Fa۳8^+ϘQBcJLf> +i%10X[3a[7i`+ur`3(g&ΦOjE}L(B~ fYA_wQ(N_Y%W\r|3 ڴ.1V9[H1EP5f n#V@" 3Bkq;u>4QFR.Prׄ Re(F`YXoQc <߯!`_u@EC!Vﵽ+Dq ,.އ h__.m[sn)jĜއ 1GM/ A_b]]a(\EiԜjwc3sw.6ڭ ` n G/&{8peYMz{Miܧ`/O%!@ P(=wEpM/DS_C%OM/m}O=e( *!OT|h9QB )RL?v eb\g7,s`kܷ8>kHz_.b0 @lpE {b%W ՕJ\Ggvb{̦+ w{SrE.(\P.drc(CRxF#\k vAE㙯&d_7 ~%jsRdw7uDꣵ(kEBڡe&y!b׵wt[`aV~[Z QlK !D[pA{ic k@Ym_fEiήWku_z^.Դַ`Ƞ1Rjo0.S DݲB+&t>+5vjhr,(xxaH Q}M3v3Qz59^#qTz-HdD@ ⡁c,@d. <5N뻺@=/hEۭGi9 qQ+d^H{^Jq: ?xe 8kAs܀\ D>֪3"D*ܠ:"…8\h@(}e@KB!~،OP /2sU;G@:Ô> _.)˞X8A,{8^;5T|E!LT&pt;qiΕ2:mie!8{/@> jA\cFů$ ZQݲ׳iyR. ^{*T>fbXgT0\xl_@rs;bIFQE*3%LH+1G`[af2)BD?F1v+4`VpjK O+,S]X Zz"^n rH9:LUa *a_>Pv{L4셱e=;xhKP)FmLV$ kJ80Ҙ_xQc!JH3 2rNFSt /kq~i0zaQ+pi(>%g /۰bZLE$:/4` 2Xm"0UDQ[6 (*sy@$:Wmevr8 >[Qc<rQ~w**'@ #{= em!VeNP''8_TPi(O/UO/`:|'<<+Dr,xV|Q̮-\rϘ`xE_}G(X|( (Dň>EIg+pS^se=/ mE.t=/S}@Pj[ :W$%Дm6^%!q`S W!?.mE+rAJz? UۆSB\=r(}*^8BD+䇹 IįuEUȽȡ~ b%W(~_.pETϻE ~w?"O{4w7(\4(>ω`%+DgJ+زiO9 kHJ,$~_.qX5k+!~?0ye0WV9ߺwmؔ^/,,٠_optEwQ].E!(Qޑ0 ll?Y{_.r0 eytQ>A۶0({ 3(6G`D|gQ\BXu\ SP*[T$zm8Rf}cT|]J{X|5\/:$>p$(fq^x5\P,Oy@@L?q 3DH)++BP[x_;|{P=/`sK}qHX{vȠ'-מ|- ,)]  atzVЊϊrѵ[Y\`h=|" 5^T {W_.((y{5ǜz*Kn=`#P>7Sfc"`:rhV(>+6C= A1^3D$*~cTxykإ,*W{v;w'^Ea= (~N:-6`Yd֌"J+n!0{&(tkz3fb}Thl=:@m|&=+!O{/Q40\PQfP~KMMwB?ՊnZ'WN!?~r] ~?k H,/ i%@E9VllwjHk Dc/vN!`#&@0m_Qe(i (qV rD?-`,|;\@+r@=EiGc97AlQ8n]*zZ/4h{r1fu+dz@?HQ6@~CXpnc9H|ڸE+B^d9J( )k\&nb aٴƋrUQI_P=`J.!{\삨 }E{蝑0۶ PSMsiM/9+>Pb_ *:P Ҩ93sⳞ6۳ ` n G/&{8peYMzZutGixEP>y9v](k ڶpR&RQf_7jGUBZZ?+-U3r|%ZΰrжBJm0;{~6g%HFf(׫,s`kܷ8>kHz_.b0A 9V<ЇVQ(zBJ+*f}ο7S"ZM7Wh-ŖSy…Lw,zeԘBj4p$_PBUD(!3_MX ;[G eF(wHc^+4(9u]a6iEФBOV&`>Ĝa m S4L}BJ /`~_> ni|n.N'QSU$]A+/4e3 t^鼢9T~DEVa,* 8[DN}_ĸN_qLT+ zd o(@P(Հ#Qmz_@r(짱 >4D]o3DT*!EYp^}1P@HÊ4n(ҷiWO8`U½ 8]^̇Yj 7p9/p_>`*}e@KB!~،OP /p> lE+@\H8%Z>^rQ`.݀xOB]JGީ+,< Ae2;NpTV42@ЊȽQkFů$ ZQz]/[/0,!.]P+ 腱Au6 թo$@mͩXɅ0 ,g@}0.U2z1CP´^DqsDq?f-"Dӽ~aCj!Ocfu "`zc-=uXXGRT EKo:nD^[6_.A߳Cd )ϛbٶ DkEԬ# #YAnu1ѩ75vbZ}0+#d!3c8<`¶-VTahQ|J ^*i \a@R݁D²P} >Gv"qDm( υ\y _}k^3BlE$B+tfI?D}Vi,s+{#Y%wY0PDCH40Ӏ}6WUF1i=/L Г Ή<3 l┴ 8Īi_=CJB V,'"NCy"xyI+8_!r e񊯘JM?{V3ٵK{,m&׽LD8H`Zcp޴DňufWȇ+yMi8^j2W\YK~iKyAp}ByT$' :W$ZN߲QjQs^\/ {: X ovpxl._!. 8#//obN; q!^tk]ޗx n{ay u/ 9 w< OA9WCԊ9h@7BVt _HHCQ[&# %vi1:fHGicIA/fƼB `&ɢ,@_egY7@Wzg]X *hB~[ d!L *`W}nxP?s-W(~_.pETϻE ~w?"O{4w7(\4(>ω`%+DgJ+زiO9 kHJ,$~_.q0'+ٜ^C](?p̓35^ ga\P}BrED Y*> .]P,WdU>pW@DW/$nqP(fq]x8L>P,W˹@@LNhq/3&Q3!@* r$EL[s6[nhFX} ++x)]F %Tfc~M^ 3DH)+/EJ_f B1r>Di48+@>i5N_}ݲOi w@7qK#!?<(b>Ⳣ4|ZpW0Z @힃 ]J"; 0¢;蝧+BPO/((y{5ǜz*Km]`#P>7Sfc"`:rh}(!bTaN}b |?w!gH4TǢ2bKYT;8z(r4\q(7dL`3[" Qz}, AߚQDzE]by7"fNl[0c} @ MXSb6} jBBj9@TzpN/ -2J*jݵ! o SZ-8x/r]`eSENHc `%P^'? JTc5F G46L4;VN۰9Cxdk1ZimG*@`vzO]g-Wa3 sU1fu+d}@?HQ6@~mXwGjVXa< %/P~ /-b 8Rj֘Lpw(,+2ߟhl?(p>p;D -zC>{<4ĕV_]Bd´mPi _>0۶sn(}/hK _.sV2/ A_Dή0s"4js}sL=Q]JZYOJY EpC0Xoz['!0?*CRH QB{,KH/3Xgwz5q/=AYܾжg/`}W@z_>>\)7zH`nYmo`:Q W|ô,L]@s;NY68Ijb/逈B)ȧI10P 3xF1L^6@tq0X=6z2~jlP1ӊCݡIˊ:uɿQ˶\y@3_BzU%0|lXWY4W 3W=ʷ{GJV *fƪQ _>@*@Jɭ90 3 EWِFhJ@Qb}yE CD%kQ8/pzxS& ` +Օ"QN˯Pn"`%/{˒*\[n"J=x;րS؂X 2 {̩Cv_ FJvE]<@!bc[.Di t&Z+~k0j Gsi0Z# Ƙk`f D5uC;b)0ӘG+hcbpF`kc_)TTR`3J$Ł ] HGnW$ yLy;BsO97r32;MyNj`6р_lu"sq׫^ kE)XZseQH1ea,CD,G輰Wd:T1'=#QffjQY35G Qd2 "rANI˄Ц1 m Zvȴ\}>X Z! ⤊2x-tVG Lb_.4`[LŨ,yxEN}̡u'EQ=бS6HJ– ѦVߍn8u3٥zdp(۠Cm{V"tĈ/K! jo a?mjyf=}) PbUQbǭ6d@ֈ@!W䁅w+اiW=*(,O}#RX \Qgp_EPh)>ST>6(afp> l2WsD  \<}< s{r#ԥʱ4߀刵z{j>xKQA`\F`:ퟜ+"/DZ7t57Xj$9"x `]jE]Wȴ-{=@Üo ̺ JP=b ifc T> 5'G =\`V.DY_NR2z1SP´^LJ F`̰eR~ZaP[*C<]8t!>]a hts;W,yVt8͛87Nf-ZzpfBs˦At0Q]%k Fxm3S80 _3xbSLϑfe5\0`¶-C+Ppm OɿZᦒ/'bwot:/4` Cq-~(z32Up;bDmXHEy.4LʳMݷ셜,>#-|k-FOV6-GLGڞ~xZWrS Vwt'lP+R-] m."LK\rwwE׈#E9R@jq8Va桹Ys%K AT?D"\lBji */#;6`8e93<B7S =YJVR0^[2F 0 #~ș_>PQ]jy݊ok^ nܽox$we>fEk }yAy;rۆXRB\:_.`Wi4/t_.L`/(0^.H~ Ǹ}ZQ|G b3\ ] tMQgܗy$%"}&o̔EY׊E7@oJ,{ H s>o2ShE C8 k%`+ƾy6ro#\!r̽)`˦Dp_!G/q[j<[BlyE 6啀 dη)OE k*Ò `0Kf%l}B8Z-jLPѦ{D JmiwF"0w,iL0i˱<8Ƚ`_LuytG>Am`9Qkfweq7? ~\x6yO`>b#.е>F֍r'8O"Et|@^਋xn(^{]tF U>Ѧt=9 _ >0Sm& 5\i93?NLAĂ]GQߌ(@4w282RWۺA^Ol~9|:=PE By ʡbtA|J-/xcM>PfRN~"%/ BZ  /`ܪ/`#<$4a=3brUAO*T_s'_PUbv*dao0=F_# > ~?P+^[T|z/0؄wv@k1mkEzU 0ʢ;#(譒8T ?*S@)31:q9q-~(zAb\(g4T|=)8^Zv)_7 c{v:;ħ{"z_@R+R/vzNidojV;D{1WT*ݜ{# R`hMӕm}JYvABBUQ_.0_>`.x`:XE[ˑB|]jt)Z-nq~&+*W!?rDxOG(y_P0ϕ/Xh8SS>"M703Ak {[UnAP%\9ߎ/ 7{[xe2Yt^8c/p~D_Q^DZ|WA߽,L֭Pb@4 BuvA^' F R.PNjrׄ}!R!X+>̺`xҳD9$ >;߆D -zCj!6ﱽWZ}t ^w w/жeCՌr_.sf ӌR/Kz/V|@b/ AEXg "yO޻/6|=uٞPkm1ԗ=LyO&Cbywe]P`9rru|mMZŇݺ#~ܫ`/|hE1y|b](5\߶{8L)5MLܚS3JV)<|Tb Mi;E .V[D 2E4r-PN4 .l5[WL9/B2 ږW< v# 1*l#/Ќ=\`ԡ|{WFM}~Bjď.{NPZmP^{~{L5-`hGsi0F ,1,H)2;4Zb9nOyGobyX9lml-kdMm/@9c{ _ @Rgp/ ޔEr gЀ_lu"sq׫^ kE)XZseQ؃y`O1@,ₛ\(SD9"S+17Ab q_5 LՀ~5P"쉞MX)QaKhS+F 8@0NaLkE`v)G76PO\ (l#1zIlCԋߖ>~`iv`g,iGU~m ^i/pEXx7E WtVqKX)tRǺ7A%:E q3ЈP 3Epal#!aF :}`Te ٴz'p<_iy@h{!,Hܣ,pz4E"xy\xKQAe2; _ 8WA r_"ro#еjl׌F[DDpԶVԥ {Lry@[ԌY}/P[]/) cj +T' @[sEx"xrBU$)E *3%L+703l)VTַ P!Ocfu]HU{ 9Euҽ%5Uh uth^ i c˦AB-YC-n0 v#603ՊLa b6#8/*M||cD?vک60Z+6xΎk8 t<97`6(So 9PW @ u4Ch7r='?eGr>3@cp\ Cs,Kw~`Eo ZG~TexD}tSDz<|3<B7S =Y3lT7 GTtr<J]^ (rě6 .mP,;V|]pr}L0^s㑨E|fdq~d@xbD+G{ DIgW视^siKՋC/3B?*2n Ũr|DctpRZ-P[aS+\ͺB\/pF_.`_>=a/Ń /6}zs[47?et_Lz @ac OA97B+"3qtx#%ȣ  Z{IشqhGmcI\6WZЂ-r=w]Z>r(_I@e"譐o($mb CB~<$b879@m e.E_3E ׆io.q \̃Ӽ/xT6r1ۧ$ނ-}Ur8tUD XH\bx ̷[x%`0drf/ZaEhE)*ހ:r/U@@)P#`I+dr L[Έ%݋rA䞊~-@e_]&@|(;A x3 r5#h- Gxą: :_h4}rP@:_8(Pdzl8"=>7=.:Ni&6=$N%#08nxxL_d2@k93IZ_ Ă @G{T8G9ʶ9qir:7\tk&<hi,Z r7#xđi|J`>r LRj|K~'Y0/i}n2ƭ6DŎ\" Rm#@yO8W\t5ۻ:"Mrh)(-N{pn2{ߥfP6u6t}%J9V&Z@i]b1]1LmpF LAaZ"R" e[Q35h/c-+}L֭Pj(}!Y<‚õ8ssC 9j})P(2e/6r9j[!P*ToTÊOy6c'0⊂߷!`v !^ФR]@>(2=bD97m/ 0^ܠe)۳`C07-@쓉 ;cdr g\:9ojM[Osw#roCl+ E^۶s)e^ hj(z_/}؏ҋjW}hj([/mH!`&lu/Ad*AJȢr]uUcN )ؓVⵆe-E @.ĶVVC)-y6T.ź|_ЊLBڡu&V1p_,,D)o5b )0f-{ E)2 5/k-cEwEmZB``U#VZ} XMiY pLyzL+CJB?R[*>mL'վbO ޳0k[b_vNY~ϓzj7UTob/xRj[XSɫ=Ymd`P*+mG)14]si}{ `#I o6AF?56t̴EФs_S|9_ZU.h ݺ2@I <✽^?8B/B3y_T#{oyfK(cMoh#5nLxoQ ͠|LcN8 Ɨ;HEb1v)E5uC;@L1m)0G;lhcG`kco\#o@m{)E0fS|o` /EV_f) [X &Av~AɊԹ=+P:@ ن0/~[nilyf=}) PbUQbǭ6d@+»@ Ӵ+JXTojp<[Hj` 'pDBs_ t<b!"R|}>l>WP/p> lg@\TGqۧP8>È E0m/{.Vx HZ/=5(oНeGwhWjÜ+u/E RLKn@ootȱ6pIsDP*{`׼zai[/y2Y[cAI۽ ZL:Ld 5'(@[r;+ m ̢W)RP~+SP^IĈ~T uLH ڷUt y[G B|";Eջ +XKO+ fZG]!-XRSUr )x^ (vGa 00ӰƖM/!+G[Z`) Yx_603ՊLa >X f}WT;mD3(gs ZG~/ '~_=@ey`|$Ro5_|[IS P>"4LwWx4w @s PQ]ڠXtGwؖ#f.\dm3G_}̊>@eqHňr^lm4AO "J}_>w#-tLP_Ц폊Lq[kC1:Nӧl#G>#]r/n : X9/۬+ō2gev[=RAG/+Ux/ [~_t_&L` PQRs=wK]tqz)-<Tz#d@wpq;R"<*СK|cp֎65WxW-)'޳}}ו~ |WPe_)L an6B 2q,J[c8?7mYL2.E_3E ׆64w7>Ҋ`d`\+DoM*X9Cr;@2@ۊUٿ&0b7@lB+Ȝoώ.?lԅ%vat|K5h=~"ô;#Bu;rB&O֍:$bw,qe]N@|vC@ 3q?G`(е>F֍r'8O"Et|@^਋xn(^{]xA V+ v*| }M-[_#$`(ۺ>pM&կk2r(%(fMq< U(>hf8lu8/PTrd 2lxk|)XZ r 1-Vk*W/0 9{e)y >T.Az_~"{g# GPמ|A[Vewd_M3GVzw\rԊUkk9MxWkvA.[%0ʢ;#Ws,譒8T o?d"| Bm\m™"F_kq9xYu="[=.rW.?!>ۍpW@S/0KOC d) Ժ]@VhlGw"xEby7"f;]ڶ`  X)1NiD+i)i/e0S|{0x[<0G7V#?Cliu8?poz9 "T͠|v' LQ0^9V&Zjȃk>Lc>|o+6l~LAaZ"Rxxl4i- (<@\5a_H`{?D9$Un^@ܾ7.(%M1(2bD9#m/Yj` _.O3jK5bԡ| P|$y-1S~%~w6ZGߍ)Ĩ\b fP_p1'`"s ̂AA;"ӚC yL6 1b#ŷ RC`1q` =/so |gfev\xlB4`[{bz4w4Ǯ {v`=h9RLY1r Ql1:/lNgyI (Rr~3){KL3@heT0ԌrtX&ԌrtѬX&Ԍr87̾N [>=B+d^T@&/ENx^T  ;^,Vuc V)^ZԖg"`t< 6Nec )5IQ$Fw6T-7|Vhĺ~(ڳGȒ*@y/P֋2@!W䁅w+اiW=*(,O/lBX \QG 8/0>2C@ELQ!O l2WsD0A8/mC #64< T}7b biދE@xCP&N.8us[PTieHQ+Rp ^<]&x;C `*BE`/#XZQb/_.`_0.!.^L@06"JP@4֜DF~QY}g ~;GJDLA z12#~T uW?VTַ P!Oc먁Q¡-(>jYLK@Dѽ`auto`IMUa-)Κ_`۽y/LL^[65\gmjqQާo̔EY׊Eo?Hޫ* e"譐o($mb *gBP|l7FgGQ۲Br.E_3E ׆io.sۧ_ZLZ|Kf⸭q0 V䀧|⸝_> lU.(>hz3r]HAVcE,G1^1^j ԫX-S>PEB[!׭mOiU6:\5c]"Լ/*yN/iM7؃4|V}A1b ,.WE"@[{n^Z lB&Sp~tLat~'x~ԊU'9ZbķsKVI`q vej`E z9@Pj%bU-.UcfAe c}2e`F>!~[6.6NLr/wŸqy]LCt@e>.rW.?!>=PԌtNi@]jP5Q+Vȣ@VhlGw"^Q}KGk|E׊&l3b{(4Rc\i\`854(*r)40x[<0] XE[ˑB|V- "i58> w\>Iy͠*lm#;Ye*6_α5"pড়.VD\%fp:P}㶂8ynLgFV{GLsimG|K)@<*dJP%\9"!{Jxe2u7^8c/p~;h\~9 k^cgg@-f nO@   58V-y 86M~Zc %/_/$c!P*ToTÊO96c?`{?D9$ >v [`j&}NćpyWZ}t |< ȱxGhBsbj9b )%-/y4_>P,i?L1CЋ_PduP> М紻{͡nJ׎^LWXx EsJj0ŏݖ OG /&XrruA(:lLzZSwx5?^8qЊs d`1myFG:a`uc?Jr]UB=ڪU `o/g?/VH #>glxsm@#bYtQ Xf9-T`OSW5f$ѰWtoWÊG(zˢFV }y#g׼;X0"^+7$9"_CW_**2Y-h -4pd:NAq@ф\!`[Ma>VC)Hpq~)BB-f60BH;q.$W"m/ KG z[MB|m%E L'2)u.HQLC Je]B:})*ju>֊}yE *kEo[lyhuWr:|Rjoi LRmo`:)^-^޳0k[b_v~{?=jŇ*xD`ko"{I#RrJ^-Blj^>e#Sc+F1n!L{[cPfO *3mp;4c jl~< j&u倒yd99+֕+\P#:^wh #`{1hrW|R&&@On)i%+̔_>\} y"[hL"J)kQ87pz=h`apaAeܺrAd 7x*mYlvoY@kM<"~ր۱-FR>B3vG̒)u([mq|Av{^&L|}Cr1Wk0Z ʈGsi0F ,1,H)2;4Zb9nOy?a@{#(V>[[|Y}SjK)!P08w0~_9` ?|Y}W<^'hdna50~ ^'+0w= kE)X_(c=#n-9gm#짱 v)k vȒ*@yTE]w=#5\Py`GZl-LY2a6B ,.\hrg i`*}d@KB8H)JZ!aj9ieS*#Al>Psam_A\8A,{8^=5(RC@8LvtשmAEPG <\)jE G!4@ۈ@|(`ݞ(֊{׈r%|@Üof]B\ @+B)T 3؃b?; 5'g@{Y}g ~;GJo.E z12#~T uWLORGy[G ]m DUb}\r' +{c=Kj +b۽ 022l_A߳CWd (S;#oT+25E=$^2.r쪆\{fЌr#E9R@jq8Vao'p%`I|7]$y@>+M>bS/ 30 e_|zGB(f A'|[I󵼜J T24Q30 3X /Tw_.k|څK{,ڣm&׽L/ }̊>`ڀzf.xbD X9;(<+RpԌ՛lcS;Ԍ@ gBRӷA_'LCS6-j=  j+l4`f8VXWkW@ҡfdʉZ04 ֌r@EI^-`wAS?V@mgZQ|G *h;)DMPЎ?M1C8jkG+^-h}g L9YE뻮|Xtsx"_> djVs˷61`!(Vbg##FV(_pԥ/kq9%@P7_ԍ=ർ/xT6r1ۧ$ނ-}Ur8tUD XH6@/D5[]bZ^ @|{vt )hazblۅyXҭ7-ZQp[Ԥ{ MQ8R({GVdcB Zŷd+]=P傯< >r>r<>7 <w@,P|r\Y5^PHgaW(]\ꁊҋr;EEG]dpOE)^Q=.*whwKm0? >20Sm<3|j938nG Ă=GQwF>1r+2S\b~! /`n?UǻȃؑKAm~ Q[k1wM~o0痳ELat>%}wP+^[Tf]XTl·ZkZ @|=ToD vzG/T+PϟV_>pu_}xK۰㘌ɔEmڸx;3E=8:L@1~,3s{"X].rW.?!>> +ȩtNi.!c) :-(*~ƶRo(zEby7"f;]ٶ.` E|$Tm1`9t>5PTzgp/ -W#QV#?C S觵[<@K|8JUȏꃜG fA> xP(JbY^-g ~b@i]b1~|6lL`#&9´#EyrP*dJP%\9/niw[x6oL>"_>^Aj \."#,X ?V D;nV}^xxl4 J_._>5a_Hp;߆D -zCCuP\i%d>h }m[3ˮF,m/sS _i.\P,Xe?/ A/"S y^<'wL݃6|;iC= o::c/}C۲=>"3FL1M&`9rruwnjǮr4j ?"{< rL,@|[r^%tK+Z'"4D_>`uc?J]UB=ڪU `o/gO䁩@rfRG4|z?M=_y@#.uVrY\1^Z?{+ZCjk0#@-]ډmE9xB[b#+u` K1{lHbkMgxZܻ;LI3(rfޡ_**2Y-h -4pd8xdhq8B/`_(%۴Xmg#E 榰 A؞l҄ !劺p\Gsܾj,,Dx0wZ)׶_RTp(SR %o.!ھ:[Wk EHAyWhZi2hbue)ÌrrA)m{.<0譿ro0Cow*9Aɿ5_h =n]@I <JmyG3Eyo(iwb c0lE->e)*~_wR#lZZUp6Mn'>v)i.3%C/V>#6A/m#짱 v)k vȒ*@yTE]w=#50PpAT.4fLEPh)>ST>6&<Fp> l2WsD0A8/W>0"lCCBW -j=9RX"ip{j>x Cw(' %Sۂ"#_"ro#еjlo ȱ6pIsDP*{Ԋ{׋v1s_.0bk,(BurD)T 3؃P^$6pDG ʅ賊m ̢W)RP~+SP^IĈ~T uWLORGy[G ]HU{ 9EQWHKzTiNEEo]P Oec# < 2+6vrUhU=Z`_>`U01h{k& >>x^ 1NM_0070[1hkh1t^h9;(Y$ހ]؎kLQsv/'C@k(qa G]*:/f ˍ/hy) P8+0ܬoJbGM"Xth`lT6!TO54LFadK!`PcYFio=#!z3Г Z^Nm%E L*xC_Q#NzwoVB/ .5YGL{Q}>_P1+XGykN|Nȏ ⑊՗3`p+pSwHR#FZR5\P#pF@hGE­A_'LCS6-j= G ӀSȏ_>ͺB\/<|9sO:B\:_.`Wi4/tQ9Q _ ֈ򁊒L.H~pY=_Њ8Zqtx#%ȣ  Z{Iqrʢ@Zp_`e3SNg+_+Gn n8X h SB~[ ) e,X H, (j[V(_>KQ=_LQ!r; -] O"5=ർ/*l cE/{[e" sVǐ܎*",$MGD5[]bZ^ @|{vt )hazblۅyXҭ7-aъoQÒg74KU46E #azX aӖ3\@I#@ne]N@|vC@ 3q?G`(е>F֍r'8O"Et|@^਋xn(^{]tgT[E_=mzoI|H#Qx3Eq=k2@~]@)A1o@-`ר2@G{7#1U! ?|$E"Ի/P˻@^znyV}Aqb ,.WE"@<^{n^Z lB&Sp~sLate>r/EiZbķsKVI`C9]YttX~@Pj%bUGaYL]|<Yv:q9 *^[P|(Ÿ ,q LCs@֡I >v/ ~.Pԋ:L=PZ!j}  :-(*~Pcۀu)CзfDIVGk|tm[`cPlVayf9S yZ yZ/Jrs0G^+ZZ R+ΦO֊nٺF0/X P Q} AU :G8owE oŗs{M))>)8\\!"s}e{[p`{?D9$ >;߆D -zCCu|}K] X/ж5f Ռr4\0Ef4jyX{hy`z/(2:[`\Eyhs}r=xPq%kY ,"Xl! Eo:d"<`s14]k=6_[SVocW9̯ߺj ?ZG ff߁rL^>-hu2B1 _.0e4P<{FU,G9_ΰhmBJm0齀E?c{2G]}FY<1^}*㵆֋r0 @9)Vbo31s 2Y-zh -4pd8xwqA4P߈B/`_(%c9rw7:.$b7+)ج*C+⊑ܾj,,D)o5b )0f-{ E)2 5V(y{u e- \ܾC+RPq.n_l/|z>=-VU\/p/@JY zH`nܢVy-fx iY{s;_g,?󤾀GEK: 0T`OV@)sCwwFb qek{qVZ0CI o6AF?56t̴EФsГ ]^~_.Zl\-4߭+#!^t@gh(f ?7^(Be9 X5b)Z%PyR&&@On)i%+̔~_F.>ʆfShbyX9lml-kdMm/@9c{ _ @/<츂7:A#s لFv~AɊkB/ā|&wENx^T qv/X X0-}UgfJybgs#YȃG4`A#hS4P>R#_F8F`mq{{8 Xw WC-*WRd]A/[_.Nj4VTʲWt:t^*Z 쉞MX `TiA Ԋ6N8j8UԊR=S2 o8mP>س|$FT/= mz_@rGOc83Si5@L%-U󨊺;n!^ y"}"7اiW=*(,O}#RY\h#FX i;B8H_@ 3\Esl4\ b90O~}/B aA:֙ur,{8^=5(RC@8LvtiΕe:mieHQ+Rp ^<]&x;CK>#P֥Vԥ {LҽC aηw.!.Ƃ*T'{@Buk/X'թO$@mIl`/ wV߻|)L^0#ӽ%s&ܞ,x̰eR~ZaP[*C<5% @U.c-=Qt(XXG]!-XRSUyg/PYv{4셱eS3!r%k Fxm3S80 _3:5-v@1Ŵ `[F|@JZ#ck-/ F/lB9 צ n*iPr*A-vJLB6nPm"0GU(|Q[6A>R@ "ӹl,;a{!'H _ZE vq@w&yVi.8G#%0[1Zk!)M6Ÿ5hN ص!*+:'Ɖ2pԥBoM!{Td{_) P8+0ܬ9˒% "Xth`lT6!TO *< #pJڀyXg|zGB(f A' ro+)R`*P3p3NzwogX 3\PQ]ev+G̮]8ɢ=f} D}lYZ>3{F:~l@xbD%rwtQy8W\AߍХyݡ^}M ׆bt+2 -OG9H/KC .'NVN!?cuQ}_.<\?|{m^,@<zzjQ1z -p/P:/dʉZ`=\PQRs=wK]tqz)-<Tz#d@wpq;R"<*СK|cp az u [603d{\xD>Ģ %Uo\)L an6B 0`!(v\lxP?s-sCwn>-ak@|miio ǯƞLZ|mOvzg$R({GVdci/i_C6-2Ůa&9Nr|F܀0Vi~߇#_#?p̃Y8YX`#J{(WT(4/|(Pd`pEf{\7]9 V+ U8>Ѧ-u~@|: O`(^OL_䁣 PJPF: 2J 3LP|uf ãe[sitk&i,]=r}"rHLSZxVc.!˷䇪_BxAH?e[lwg-b_J =BBX#s1Ok9gw '(Zڢ<`tc-P Zo͋Хz$RS,C}t'SPп/(讒8T}vL]XLYA֡ˡ.xmC9󾙘yPˡ pLCu@`rQګw~oPԍ2:L]P EsiGQ8[تu'h϶uWT*ݜ{# R`hMӕ>,XCBk7%aS y{I|0^[3a]7slw R+ΦO֊nٺߍ\`~_r 'A6upd)_r|3?c5'"Gcy߇bm~h{AJ__/$c!P*ToTcw#\(X, Z!an6$Ln!Dk+xC߱ ~]h ye/o97hy`>/4jXb)FЈ2_PduP> М䎙wsCƕz=0m(}g-M 07g OuDy1bZ0+']/߹ ښzф?,w5#^33srwֈ@|v!0Lֈ2@M E#Q_&@ @Ӿg4_M r- F V+]X3 <[]K~_&Ȣr][n%`]jUӂiAE d-x!u< ,Bf Dvb[Q+P3VԍJ,챁#g׽;lb (8n|>Zww^(r^ 0Y𵮨\d] *S*#ita%Pߋ2A-٦0!l8{q!!3 DYIG=BH;q.$W"m/ Kl9)o5b )0f-{ whB{KH/3EEm> j%Twm] *^_8_ aV-^iMut@Ef+a{&`m;n׹Sjw!5em0+~;\8Lwoc-B>p/& 1w]}]`}F1(381~Nz3g{5_QI3,8g lWLP#|ʷ{GF!+JPY=?'׊ +W )>MLܚS3JV)} \} y"3.nahZ? ^{i^y֕ "SN˷Pn"`#/*\[n⑨w)0GA bU؂X X)<ʷwU*@hd+ڴOMP!]Ǿ oh#5_ޘ2~{L5-`heGsi0F ,1,H)2;4Zb9nOyGobyX9lml-kdM@9c{ Syoy՗qouFV gЀ_lu"sq׫^ `觽0W{h={Z r Ql1:/lZQ k{ in`f]35G 7LL=@AT04`i M0@HcЀo_)0n>=B+d^T@&/ENx^T qv/X X_&ʙ}UgfJyf=#g {8 ؃h }`@@r21z_\  0n]Ppqy :]-η[/0cA *c ; -[~_Ǎ24+b*F}e+:Wt:c;)ʞ ؄E@A Up6K@X&@0NaLkE`v)PHK&{q|$FT/= m_@rGOc83Si5@L%-U󨊺-+<eB V<5 =:o1WgǺ7A%:E y3ЋrA(}d@KB8^6ᑐ0/?4A\Ti%kJnP|D݁TDyPXV7ʷSoCћe)) ۟#j"G*sy@d:Wme/5`/di ^h1z"ny<0;01h{k& % Ԁ# VwZjE żky츽!@P}ct^N!JMDnxrG_Ѝ2#E9R@jq8Va桹Y% "Xth`{q|짺_> *'0wpJڀyXb9gx$Rozx9x-/'2<\_tһ+x << W偊R/[ `>bv%K<1xGl@Ǭc-Yܽ߀2Y< Q}9CVn J:"G?5~7+uw#-t_@w-L J;dCEP|m(F}l xE[B>eMkq;CCs(NVN!?.mEy@[pSIC)=a/Ń_`WQG(Oϵo@Ë2@fꨜ/X] 01۠}f -<2wDyT4CA;.6-F m,9@Zp_`e3SNg+_+Gn+ Ŋ*#E4[!?-PH2Aol7FG3P۲B.E_3E ׆io.q n}c+D>%l41"BƳM`%VoF؄W69ߞ]~J/ZX{TPl aъoQÒg74KU46E #azX ll?Y/|C/|#).3'?p,5>P|u~,.rF3^Gxka}O(=pDr5@EB=Eq"kQ܀/P:= V+ v*| }M-{s@|9 `(ۺ>pM&կk2r(%(fjlރF8ڣW1YLcն.0{Wӭ9_y_NT`j킐[]ACrdҪ|mtn%0 9{e)y >T.Az_U_Fyܻ<8m^r/Dm=B+/TN~X#]Le6Z "q>%EiZb_]sAW5=]YttX~?%bUa7@E 6fc2">'Sfc"uhrhz *^[P|(Ÿ |_wQizn(RpRnE2;݋rw'Zh9<S)ԥVZw_.Ȣ/)m!kƶKշE7=Z#tkzk3b{(4Rc.liu8?poz{ߥfP6u6t= @^-g ~b5@i]b1/S̺{YagfoHrmHGz_>:LAbD9#m/?m5\0/Lѧ5ͥ_(^2_^3LV7*9xD\13w^09m\ {iC= o`NI ۠{XpbZ@~kk՚ z}^ {ǽ@+ܛ߁rLCaJ#f j#oq@ԥV⻴ @Ӿg4_M r- f V+= X3 <[]K/ydEw$V֥VU9-T`Oޛ x!\ ,Bf|cK@;(P(EԍJ,!zw=PLg pk<ʅL%LJ{wh -4pd8xdhwjq4T-6r_7 P|K)js>es@ܽ`n 븐Dެ`룞!ڸ(nk-/`nΖ¬~Z)׶_RTp(SR4Z=P%CۗXgpVܾ+RPq.n_7y 4nzҲayty Wx6vPݯ[*>mL'%s9k+a{&`m@) R6ˋr7±ʊsJT"E`-BsϥϥWmt23~jlPiCݡI'=s/K/-6U|m$0rs>o8{{ 6 P#t~7BVT{$Uc/B ^GhBH)ib-PLh\% Mi;E .V[D 2E4r-PN4 .l5[WL9/B2 ږW< v[BoC<\@шr#fIʷwU*@hd+*K20 m/SxoQ ͠<#6A/[Ι6qgj'ؙ"Kz\PbUQѷ%x# Py`G6\@q[#B--bw@<ֽ B ,.\E p_>b!"R|}>l>Mx$$̈rͱ˦*sUPeΦUpmx$}39E/\8A0E@,<e:7`:չ-*42@)8{/}LW` fP6" X' .^+odZ#b|;<`%E˺)q^(SXDISHښgUZbg%1AQ\X͢Y[*KQ¸4+ۏ#Q 0xm!XAo}4`VwՖ@NQ 9EQWHKzTF {@ 7`a/-_.A߳CWd@ FxY|d~fZ)-q$a1ȭ.f:(s#!>x^ 1;luLjjV0Zk@bYIUt|}Z 9PW @i u4Ch7r/K/8R# `Z&`>gYPDC. <|͕J&j}1^SEdx䙏PJSDz6io=#!z3Г VRT7g(g0 /"g.3|V|]priE{ :w8/P1+XGaF|2Y< Q}9CVn J:"G?5~7+4eRZ֋2|K_7sY r}5<ӧl#Z{ 3mPMB~]۬+ňrgve{}EW@(>8!<-c2[_.t_Lzz "?۠}XLo@qtx#%ȣ  Z{Iش3$$A/3|f,z"]WV, |WPe_p25z+䇹 IP&΂Z "؊ol|Eږ.E_3E ׆io@P7_ԍ=ർ/xT6r1ۧ$ނ-}Ur8tUD XH\bx ̷"J2۳KOE 2Ò `_>?;l}B8a*RP3S[G*h"0w,iL6e!^ @cŽk*S\uG?}XgE`Vb9އF5~GyB = ld/BO}*WT(4^)(2}68"=܀?x?.wsJ@WU>pW@D[/$nz)ށbL>p J [AbQ#;#(ۂ.VTrd 2 nrsWu2>Vkn\By >H,x?p0 9we)5˹ >T2.9 BZ A_.U_Fy<8D>FxW4PHޚ]`&Sp~9[4F_#ZQҟFmu=V:/0؄o֠{"j( `Wݡ?HAAb#^QR/6 oqtzvշ1{>0#CCXX]PrD9(Əeb\~n|0P5ܢPxk إ\Tev{"_.@vR6 (~N:-(*~ƶRo(zEby7"f;]ٶ.`  X)1xNiVWR_(*38Lg]|@rg}Zp6} Vtz[.<\`%@*'g6T;(kx(a+/gQ5"p.VD\%fp8P]0|6l}fDlw=GP6pȷ2T}%-Eϻ/b]vp3K{ ^Eii 0W>"_>P_5a_Hp;߆D xqS(2}bF&0{a _>0sn|`>!5ͥB %}+^L1!/PduP> М䎙{sCƕ}g>0m(}g-)b?v['<'Awƈ)9_`VN?]{έ=T[|U& `hE1=sAT1)/o=B hj(BLCf_7/U i3Zf9rC· )|Dç,%L_<\Wo%`]sZ05H5FHl1_ "w1%VÊG(μ 6bnP7*_ )l:|bjE]`w8fEΌr;t˵W@EB&[)bR[h4:AqU0@㚯jq4T-6rUU؈J o6XmͷldMah1@ԛl҄ !G~v~ln_kiywtf@k1K Oe 3S=\Z=P%CۗXg^jz)8M+}tC[.,t_.<_.F&V"ZTf mxI\Zop Xzm? un;\QEEq"S%PJBXeE9APwXq|0Ao å1kD,汇F1(381~Nz3g;lBkBzܺyd99{7=py`_(njr:{GF!+JPYjg_`I*qR['03 wh\% Mi;E .Vߥ-L\ `:[83 + n]y 2| ,6k[^µ&K/`B9aFHst/{YR] P|$ي6;>x@Zebd/SxoQ ͠<\cN8 Ɨ;HEb1v)E5uC;@L1m)0Yl=+-Ep(yLy;BsO97r32;MyNj`6!  NVa1zc׫?vhݳ#^k,4}]4),lb9`h(6L(m`J5`_.r4c703ŮWJ\A8ny{FP9 R4Pr /./`Pqn0 ~ jE ۭ#B:; Y'Ug/ o:^źj60;F ,V rfkՙRjHmiyp8- )H/AhS4P>R3_faC1 j4`9ut8ߪq8^mn P"S4`_> Lһ?F )i9 kt^鼢9T8*{'`:})`TiA Ԋ6p؍`r0Tϔ̣BeT|{=++g#1zIlCԈrߖ>~`ibOv`g,iGU~m ^i/pEXx7}v@IÁoYn>"E%:E qgP 3EpaJful4\T'VU fsrۧ_BW -jGNEEo]P,l"- h υ\y րgBxߟGڞ~xZWrVvZ AHaWtm:/pxDsoml5P(T9;݁s!mh> ^h \@oF 4?=q\^ qQ}|) L`/pEf{<7 .Ni]*V^@%#qxP}=מ|A[Vewd_\x0S܋'.;.@xmQu_.0؄wv@k1mDGz7]YttX~kLQ(譒8T ۘ=Ɉ7`C̣'?C= A18b\n|0PܢPxykإ\TevN^EN/l]u @QlcuZQTj .0e؎Dqm[[Ţ~oD  v=ZфcPlV }ݔr\ ^\sl-0ǽaV@rg}Zp6} bF0/X P 뤐mAa3 A['N@(a+_α5"p|.VDhp,A>2Xs܆͙όsЈ4#Eyr~PP/^.ŜoG h_Sjk(-5)[ ⵢpr{Y.0zZ//i.Ռ@b)FЌ_.PduP> М紻{͡nJ޳^LWXx EsJj0ŏݖ OG /&XY9t:{nmj\iݑ_> "{<1D"X3m۹Ô2Y3G 0Dh~f@ VRӤBN_h`>{~6g1dz Ez_un`iנ"{r x!\ ,Bf|cK^Q+P-Y17z-F~w]`#.*l:\EPkr0%/P/.\{TT.d[)bR[h4:Aq7]x$dф\!`U-\@i)z46Xm,+s)c#ނ{h1@vEm*C+Mr)bqZK/,;C]#Y&ZL!"@̔e(E %o.!ھ:[Wk>""b5Z]r<`9,!:B#&tR2[-gaֶq ľ|Pϓj#UTG b/xRj[XSɫ|AJT"E`-BsϥϥWmt23~jlPiCݡI'=s/K/-6֕ JJ`}pBmG#{ݽFJ*Tsj֪33R#_F8F`mq{{8 XwjqU$p6yr%Ei\ L^"Nj4%/-bWPGeOlB"E%:E q3ЈP 3EpaJfieS*#Al>Psam_.A\8A,{8^=5(RC@8Lvt[9WT%^0eHQ+Rp ^<]&Ђ?L/pI%*yu)^y#b_0.!.^L^{S"`@4֜DF~QY}g ~;GJDLA z12#~T uWLORGy[G 0pjK OWXbzwak鉢~-auto`IMUa a_> Zzpfز=;xhKP>3 L"SX[4Hc6[]tj FPL `[FcֈXZK PhBi>%kJmXOUt#Zǧ"2 ؄²P/!3xT5rW8l,|n"ӹl,;a{!'H _ZE vq@X4Q^hP,)f{oVvGF#Zh1t^h9;(Y$ހ]؎kLQsv/'8oC(S8R!y}ju[ f8_ieGr>3@cp\ Cs,Kw~`EﳹR ؄P#f?Ջr`2@<">C)icY_>`N} ԛ),^Nm%ro+)R`*P3p3NzwogX #4ߋXtGwؖ#f.\d_/^׹{HTYZ>3{F:~loT!+{G7%]^xE Εz_H]^&o-kC1:Nӧl#Z{ s%!q`S+\ͺB\/pF_.`_>=a/Ń '#cбkWSVHQ9Q _>lv.y*q$`?cܾb x(>Y zҲ\!aKz_wi1:fHGmcI\/K^-h}g L9Yu@_ukŢ *^ka0< djVs˷61L ADc<}ްDvi`*j[EP|-5_"2bF̴/HA vO&x- 5B{^l41$ _ bV5[]ba dηgGҋeԅ%v1| n# @G+:EMKހ:r/U@@)P#`I+dd/I\pr.F.|+xYdɊa } (]|)6e/?̀/0x+ib>^C](?p?pef=xz_>pUP*-T$`?(K1̀?P٧\vgvA^򁻊= x'q C Cw 2@z[&Zbhq/36U8CwF>)F8BP p.G1^/z/42zk Qt2>Vk 1[є.g)WK(!@fR㽜 x@/?h \%mDi48z@9i5,/ҺxO4t}4ۧ:E߇8 0CyQjENu[hgEiѵn9@UVk Zs| PCnLztpE W?+r  +.w`wY|2">V}3r]uhk,.P|Vl(zAb| @1^~f|0ѢLa@E]ʢrWl\CpJPhf+P>1 8[E"5 X;D}.1GkNgqdVTaۘQT|¤JS /Jsx9p;Ba<\r@n!VߵĕV_]B\QAmM/Wdd̶m0snh0t ;HCstZ,憞?Ae?&0PjW(7SR16w'\B,P䊹0{ WJcb1ĻVqf^{n `᜛EwŖ+ l-f(CRh#ht~Aq Uw񁨠Єįdbz;MFO7uLHƌ >`sHBH;,<$V#D9_תf ;DEջC?vIS1 PLePEj@Yb]Wku_z^x|]}m5l/`}W@{^OT}Z!:eWMDe.g{-¯L:+{,u:뜔`C KP_.`(N/HgIDJ|JB(C` C`0ʖ QsäѵIc-=g1=1z e&8M+u&}6?'=y3 G_6W PP|@U 429{7=py`_c߽#@%{+~ Uc/8<|O\)un'L4+)=\,ʆ4BSryEYZ1S=?dd-PNo^46nHcNZ{[Jy " DqՀv 8 2 @T gl_>0/` 4eŹa}_Zg?F)ZN /i9(rWI:^bY`sՋj9nSV pfkՙRJ5'>~^:LPQA{aʠ)pT>V! 0L/8FCacy j4`>[7N'Q{- H< ؃8ʂ_y@ /]j9_1~l{E1__pTDO*-ZQ- XSWԩߋS`ZQ8llPi($aP>CĈ'AT3#cP޹a8;FLgZ е;CdNU bRE1Pjy@HÊ4n(P6 V*ܛ߀X ݲ|DPUAuE qgP 3B8_>Es4(E檠O b+΁t!0)}|`^R?*E X=qX"ipwj>PQ 2qR[Dw+0JNj+q9z BhE>(е8\&JWm(VE셽Fb_.(aηfYB\v6P`؃<5"`%/@{,\ (>dU2z1CP´^DVl3l! RGyGG 0/Oӊ8)R.c-=uXZ!-SSU_>_(v hƑ!{vo!̶m`&Z+nJ80Ҙ\g7SQc!<]kk)^@T%k +yK0z]G‚iQ|J ^*i \a@R݁#iЀU؆C1 >& Q* P1lAFQTBHԅmVbca(اBlEm>6|`Zw`F1+h[! M"DQ /J^(Lj}jv~aYZ V0j+6\_97`6To P7|LDQ\@kr !]=]+p- 0>wY0e #&\4h`(b_* /D;6`e93D ԇ)BO.>N%q()B`*(rNt__!r(ʂK /𳿿 (fn.s3(Q倊>xtN|NE1q,ݠ(lE~jXn!8WAХrݡ_(0FߠPmD[_'DC[63Jkzax~Jۓ# W!?4|cobg8=Ŝ}]BhXKThy#p( 2QGZr` /P\*c.H~7zCԊ1!+^HAB&, (m,5lKE-L0('>}}-fp;(OПk zZ3iE} 1W_`D|@\`FqEA5P}<Eji0nQP؃=Q2cP١|R({EƦo};@x%W"5 (F! w29i9P%@v@1ccS1>f䣜C4` 8"xxA׊~5g嶌f:}@YwE3BBB@4KUqI?r Rjh(2i!] -`;EaЇHcxAYMDE״@ֵxf IGX}S}_j^`0:?\(uZaqgi0PbD9Х$Bk\a]Xt++BPOo*G8Y|2">V}3ry}mˡHP|x9rQ?"-fTxkKYT;r3;pW "OW:QP>1 8[E"5;,֝>V(K̺9A@њYY߂0ThtUcm4lc>.`ê\m4QZlt)SMi> _>J)"'A{R pd*C-Xh8C)Fq48} \_g`Vp'Ͻ9CxZ2ZwGL9aZ"4P8Ok(qĞVQ !?NKX,9܅ ޖ{es|+ 6rwY0C>[|WŜD{[B֧d B}XaGj}(<|c9k~i@QH>QMꤏ}S+2505$L^An!VǵJ.!a.v@Tc/{j9E/RC,HCsbNÊ 1G/9"Q+ "ǛjxV.u?;z0PjW(kc16w'@AZd` įdbz;MFO7uLHƌ >`sHBH;,<$V#D9_תf ;DEջC?vIS1 PLePEj@Yb]Wku_z^x|]}m[^_P@JÅ~R[Vh[}NTr"W|ô,L5,'CO%`E9"Q%Q(na*y0P %6}Q- cn/ 4iXOfΆ2~jP٦C>̙N/?BᙯPfJt&|xaDM۽#@%{+~ t3c]IO/0+ ~EskNDC(bEWِFhJ?e1[hL"J!@8zr ` +Kr^~w,VrK, MDG?~< b/_(J)(Ɔ̜:o? FJvEz\lVcb/p7_.@S.xoQ @8ҘNr!Hl0\3cP`U$;4Zs6MyGoM@}s1ea,( 2bxaH Qs" DqՀvpT$ _.@ h@DSŹaZve\}6X }Ph {_)N'xeU/ ;LM/p%`<g:k `kՙRJ[3y,@#pUE !()pT>V!_c4`f*qӀoN$ж%lTsK©*)OGY+1|4pWLŨ,ixEN}̡W= c176Up:uEzq'jøuՊae*#mI=+P:_ #Q6s(q v(δk vȜ@4(q_.Ұ" ," M m@U 7,wy@nQ@ ž2C@E }?lF(aCcX6I檠O b+΁t!0)}b`^V ( \8A,{8^;5T|E!LT&pt;]9Wʰu R lE>(е8|MůQZ( {Dn /(aη,!.ƂVNn i*ή:yH ښS@{Y}gPl}:(Aebi$@2gBf6ÖI"bC_}St<ݗ'iŎ@OVȱȺWd,vG̩*QAQiP^0/#K}b>d45#cl0dzmLV$q$a1+ȭ.&:Cx(>WBi+2UI[" ^B>jEL6So`~RI bZ N_1W>F"`Cњd!*[*FT5 υ\y,;pրŷI [ي%B+Ӻ3YAQp_U( n/x%`/cD>5;uLjj@+B5] yΎk Rsom5 !E'gC@k(1aGYr}k@Ŗ_~ !}f>u8aQ.KcDCM$i@y\,bӚ_6(lU_.(Ww8%m4p-7`J''$> L/TP5"_>OWX_>+D( .5\n7%W0^#JiP\Z>f " `7pdL%HO W\YH]J M 2Mc uHO5?yuHr͌Rc(G zpӀ_ۺ(~8#g⽇SLM/`+Ң<1_.@r| uKW)C4 +?{C97p1DJQ|C *h};X\TD*t(h2Β@1:ېƒXh@ >̯l`&ɢ,@_egY7ϑ@oJ,r#DTѻB~G Cʄ+Hc\]b9ږ+ O/8""?;E 24O7oVL|/x;E~,zTpe=IvH<Vj<WBly"(V++Ȝoϩ ҋ;r˒ w/ bώ>.jҧi&P?R۱'#" u>;rT!0rtw &_P8e0\AkZgfoe;_Pk >U,,|(wA X| >\=!TP=/[H~Q2cOR(b"coSw{tA{%O6(F!qw့ebQ \-U1 8n {*Q;#rlg s#/ztk&`YN(C0c뮐㿩!t)?Oʳ ~r d)u^~%J18xAH0{P /`V?Fi48ɕ PDi~nVZ(flh,CRÄ3=`t%V[5h- כKQI`׻|]Xt++BPO/8xENXActA|ѥ.0oc8[Ff"|6ضmx3D=8:(ˡMT^XDH4TfTxk إ,*W{vgN^) /h]hPzbbuZ!*3Pc M;D}.1GkNz{[0cmc GƦ }͔|<DWSUS /JsRF?/ur`3(g&ΦOm2] ^r+ ꋜFHgл x !J/\r|3rX=ipmwh a@uk76gKx@6pȯ2 Х**"%,ŜopniP﵂Zm-E_\B,P䊹0 a WїH"gvbw̦ SwŖk<EB&0~@5ED s_(kDgh+Y!` 0M/_:qvrߍ, o0또DD}XIZhvheEYxH^Gs>\)zH`nYmo`:Q`+ag&`i~y_,J"JQ_.`f"` /00zt"p԰`@P{xF17(9c]I'T.ڇq֜Pr6 EWِFhJ.(XB5fQ E <c** ' ޗYvY@띛"^#5 1{v,#{UF6_vPbdW( m{<&v&~hbm11 `X4`F,1Ej w@1 FS``S=R0TTR`4< QL[ZY2;nXyB4`/:Y9yՀCD?Cߏ *c3i3|`#AC1/lNc4椵'yBӀw 򡹍L^ 8*ig p @T gl_>bq$yu:^@Hc @qnX /hEۭGB:'p/N$s@uIJfAs܀ \ 1uޣcV(^8D= {PUTP=o :N4*rh(l6 E1p0㭛D|3{zPAMSU$SAe+O/(hJ_b*FdL+:Wt:c;G@UX-J– QS1> 8!(.öTztd'7P:쩑!bDғ *ن0r;7~`hLv`g̩JTLCwWD<򀐆i`Q޸2@AmQ W8ib>*PUAuE qgSQ+3TZ flB0hcX6I@2gS Qx죾fpl" B'wPGN JNFnr.Z3_6G9B@j@hskai<˒9 "h"L9\QV!T54(lU_(Ww8%m4p-r9gBSv~+> k(`I+0\+DEYv~v+(fn.s3Ee=%?P\Z>̻^puB66/7(؃mi2ݠ(lE~jXn!8WAХ4\oPӶGEx­PxE-5!q8iP W!?4|cobgg⽇SL /}z1 y-*GP:L/d_>ȩ"?^~Bz)J;P+Rg+=+D^HABvv]lmHGiSseKE-L0('>}}-fl (!=49!{9DC)^ù`e"- " bmr%Ƞ>'-(-JKŌ;}_N`0:2|O+6C= A1^3D$*~38@E]ʟؽH&`C|3{49_@5Je =@uMe35 X^+4 S(K̺9A@њө1BcS>fJLf>>+*䩮 Dyu@LK%y]͠8>~Rߋ\`~_p%@cX]{RHgp XA !J/\r|3XMipmwh k@5 76g_KX }Pk೵(-4![ jg_|ey-~+,D{/P^ Bkq5zsC g?#FRP2ׄ R}̇+;,n;v4I@ap ߯!`v !^Фq&B .WZ𳟹QA|mky` 5<0E_ /hn2a*CQC@E#P Ҩ931Gu+?zBS <"SR1Ī}C{9YDs10cqf>ӷ е߽ YMպ-9Pf볖{|k@H#rCl+ۅ"m|S_|:El[wDY+v]Z?@+rG /m2(-R3 @+憾4\G_"a!k`6}_"Z,V,P"1uVy}j+<}_ɐRpT&V_62Nί&`i]}y_,J"JQ}_`f"`\/=a{C@8J10P %X>6[5i~ 5i}k `%17hS〪68 d}69{|]P UJ`(1E+^!؞ 4L߽#@%9PY;ƪQ _த*@Jɭ90 mJ_/D%r!ДAQb}Z+CD%}[u-NL46,5|Lr^~w,V2K+bpsQߣo 8yA *pǨuF6>(F1sPBQ]Q}hԶ}MP>/mn=/(\Qc f ?/8ҘNr!Hl0\3cP`U$;4Z!m03XA{# g,x0ZQ"3)>qC<oֿ_~B_/80_fM%B%oB4`/:Y9x%ǩW6VTYך+ c3i3|(.xu@eȇW$:(Ҙ֞ Mveȇ6v3Qz5ਤ8w*D]/pƆT:4L:/<X&hy87k3ZX0RABʼnD|tһZK IJfAs܀\ 1uޣcV(^8D= {PUTP}`ڻu3iUHe/Pmq{ނ@+z/ﭛiqz={=&©*)OGY .b_Te3 N>PpTDO*t, B`SaKSWԩ1nøuՊaE=S2 7 6P4n p]%F=mYt^Z`024<-UDv`g̩JTLCwWD<2i`Q m@(ZT[B<{ ,( pz_.EPh)>C(cQ QB lp8B!hGh9/{AT!/:n(k QQ 2qRkA"P9B+Bp ^D}&xCV }1_","@/72@1 /;(i5nՖ@VItb'Q+`=s/N-N /P۽ 7`_hhy }^>z'k FxMyތ̶m`&Z+nJ80Ҙ_xQc!ϕfxeܝ4*z_ ^`[G۫A󳅗J-WXE7bw?64^h*,, ǨWl(Z32DE>4eaqDm( υ\y,;pրŷI [ي%B+Ӻ3YAQp_U( n/x%`/  Zw(AaԘWtm/9;a(#JIqנ2P|t>N JNFnr er@]/8BR|Bcp,\ La])QEfP bӺ_>ЪzrUSLײ<\O/P(a Г|GIo` <\_tr,TBlK_.ۥ_&gbv^ ncc36Q傊>>0#O{ "bD X8;AQɔ!VxEΕǔi|KC;QA ~6(^hh9}fF)<}3 բ@i : X W8=Ŝ}]ؖll^cֺbZ/F<=Ͼ@|bS*2@&(u.݊bC4" P> \ (>@MƝ,.D" E:erJe\Yh@ >̯l`&ɢ,@_egY7ϑ@oJ,QAF a6B@ Ae,X4)ڀ9@mD ?GYD_g9m >QEj{2g^QVBgmS_M~*X8\C:*EP!@[Ū__ Շ"(V++Ȝoω.LP^l [oWb_PA\p[38:r/UQA{(BTDݖ*dqz_&gyneS @1wx]_`V|Q^%n~(w{!D X| >\=!TP=/[H~Q2cOR(b"coSw{tA\=rp]u(z!qwᓶwm|j9IHF~0z*D}l}C4`< x֑ȩtk&`YN(C0c뮐㽽MR~6:X.)~0{h!BJr.R/ k= 0n`#4[DJA}NZ(~ o?Bl+-3HB!Cp~aBi{V|VT]X3Dk1Ѷ{"0t>*zW/T gOW}L3^S/VX%]_qtz'0!͔Elmx96 g{~qt?PC.D  Pe.`\;ev:;ħ8z(r4\avʢBI띋}V=U0"56؎D=4}!0{&(tu36fb}ThlLi3J@z[ҲMcۛV|(=|ǻ,0C.`-L@}D j3ކrDZ}Gfl7 E8{a}sC gy# h@(<\@1|k~i@QH>QMc/0bEbƞ&`"M3xi+ g. } _>0۶sn(}/hn\ =xAe? _.z C>G/H<7wDۃuSsg)bՏ!뽳=is"41ber3/0 L@hE?j]}ćƖU(xO_^8q?P+҈܇BQ8@.@W5 xnL\ tc#f_7Σ _@~ yg `CD/ڶVH f)^}K>/Ȭz?eyf`^EuYCj*֘ aE9V4 h#pE >@+憾4- _+yWD]/iEYp" Ertb˵Up!P@)1XFPQ{ | -VB56|Ҳh !h|Jvq~y(2l? e9V$ pV"D9_n(rtv9zۚbg@'RH4@P(ҡBQZ^jM0Kwž.9) ;\!QQ_>P(Β(R{70<5JXblAoPs{TѵIc=a{ǜ:ݮ0f@܁ }f4w 56:Օ*F8g{ź=pâ "^ ^irj^46nHƨXv>K#0ũWJ_. ߩH4<"LX&_> X&_>P}ja9{#ܹl!.j,܋2x+wp/,EYA7`Wf +`CD)OR H g8 ؃y#=hV)pT>V! 0L/8FCacy j4`>޺@tHK [gpDqӀ=h,eȱC0"4JY#޺bTm5Wt:t^*~?w"ʞ XE@߲Al4 l u:{pڍk V.Ꙓi($aP>Y#ʞ,:/-0 ChFa? SL"sRӐ,bUod@jy@HÊ4n(P6 VCMb}'t~!B TA.4BQ+3TZ f~Jfq&\AAl990O B aAu&GF1Ա4E"x!*"P&N*8uڀs嶡4bx /xy BhE>(е8otȱު!Dp_)Weˢe{a- irY[cAN+T'y@X^ gW~P@T֜<\`HYbg%1(.Z`f]Aebi$@(G5PbaˤTj=/;(i5nՖ@VItb'Q+`=soi޼)ŝuH4 #Bw5x蝬7;5e! kf"QԬ# #YAnu1ѩ75vb\ `WF|@0T%]cZ_^{ UX0m OɿK% +Qj;P7p$: C1 >& Q* P1lAFQTBHt<{ _8}k^ۤBlE vӺ3YAQp_U( n/x%`/cD>5;uLjj@+B5] yΎk Rsom5 !89;݁3!5n0, 5\qHb@ /8BR|Bcp,\ La])QEfP [54(lU_(Ww8%m4*sW%R=V||GISA Ppr>]W``WRV|Q̮+xmc} Q}}#@aF.&DnȘwG7(J!VxEΕFZR_.@wr7(ԩV JMv+_'DC[63J-j= %!qP W!?4|cobg8=Ŝ}mfhXKThy#p( 2QG@@+r=X95s{yc  c<+Ey -A (-e)TNv6ĽC6@/~3f,"]V~P۾*#DTѻB~G CYiRGy7rň"WBly"(V++Ȝoϩ ҋ;}NZP^l d g^KFDwQ>M3Nڎ !*PnK`N28~Kjر=sVD7{9 eytQ>A۶0wS 3(6G`D|=x' 0|ۃ!>JO(=pDr5"PAu|ޢ"ѻ{,e3WxR(b"cwSo}w@op8g(|A1Ή!q{wbuL.T DIZŌM( !@;hv28"x3Wӭ9-k9|:= !}<r$MR~6:[}^R0}h!BJm_ɆR/{!(^̀/`"*Ta=3 bmr%Ƞ>'-Qڻ|-JKŌ;}_`0:2܇'.;.V|VT^Y|*YbmD`R}T!u0?`AמW_.((y"`UGjw?~@)3"`:rhm1*0V{PC.D  PŊA4v/ ~pJPyF(E+=Vih.Ʀ~ 59Ĭ~D 0 ;m=X*6Sb6q.Z{Ai]V avb^(Q傊Zw-G6B|[jlVtK#<bvŎb_6^(J~_x_.$c!PR}pES̲XXG1y`א0(Ԥq&B k{WZ\삨 rlۚ_.sCM/LW4Kky@}X5\PȮ0s"4js}sL=x<樮c%g] JY EpsC0XozlOyZ眬"!5,\Y3Vd{S1\:#[_Zi [i@kf]y 5\m- nZ7v&jy@0FDM/}8eTP@+憾4[X("V{;WD^xrba`J&B:MY> -Vy…Lg=2jL!6 FPQ{Dg> -Vkry !h?dO7uLHƌ >`sHBH;}I!bV=/0c :][Czۚbg.)B`*8?*CRH4@P(ҡBQZ^0Dx|ݗW,_9z_h[=XP%^ 8ԇ qU< Eej(}PX"QEEfݻ` XZ:뜔`C=K /HT *7c0JPګblAoPs{TѵIc=a{ǜ:ݮ0f TuiEФ' .6s~_.(xP~\L#Qb]?8a^/@Q|Sv/Pފ_Be9 X5b!ܕ< mb֜Pr6EWِFhJ۠(Bp@܊>nad-n N~o DcEU 2"2 4*\D(}vMHt /X//(%*u7&PHm10PU^Qc f /8ҘNr!Hl0\3cP`U$;4Zs6My?ؠV(p6RQ+RC`1gfsoPhߟL,~`M٠P[7D|[}٨SU$SA`W_.(hJ\S16+:Wt:c;GeOB"o 6Up:uEq'v-V.Ꙓi($aP>س]%F=mYt^Z`0;7~`jy&3}!2*P1 )"v\F6䩞4HQ8ύjQ=+tVqjle#B ,(\hWf!±(%rq&\AAl990O -$xQgrdRr,7`>bN_5m(' `:mrPD1<{B#"V@]l]M#pM/u[8Je{a-iY[cAN+T'y@X^ gW~P@T֜<ⳜJbQ\̺TD A z1+IQF"`Cњd!*[*FԖ"( \hΕgo o 9Y|Uh1a? viqŬm(/*MEE \Pƶ %OsZ¨14^sv\PMGxvm8AeVuN| (qe>&" (BoM!{(r='?Pr>3: 0ӨyXs%s A?DpDsB0O9Ue2+_.,O/0~ QB(a Г|GI|;J J O4Ptҧ+ ,] (r eۥ Ĭ;ީJ`F1 mL0^#J@EsEkPI6.7(|û%HO "~yD鷑|Q(pk ~VWkz_.ӷlfZ{/KC.'NB~CK_kpF_.`_>3^̩ŋ_@<rx {ay u:_>=XO/(r] +?{C97p1DJQ|C w@wEi)+$ O7&,=32c,@/~3f,"(Eӫu$2 djo($2q,g Dq7r|M >3 4tW|Q^%n~(w{!D X| >\=!TP=/[H~Q2cOR(b"coSw{tAԩ{'q C Cջp2@z[&Zbw?@vQ[A1<({.@G1^/|!c^OlܰU.P`j!]!{ǔh4Kcwk%C RjJ6b~ qD񂐮a_.~ ҨB3,vdP6QZbipT0!8#fO/0J}:հ"8@UhD9n>Qz7]Xt={"򁂒W[/V RzvilLf"|6ضmxϊ P7|P3{_,/VC-h^$ /~r:Q(k8@QlcuZ!* @M+4;D}.1Aԇ&(tu36fb}ThlLi3J@z~R" \ P8'hŞ gcϠw6' PB0Ôs{M!ؔצ T; /76gKx@6pȯ2 }9UEKXs_>]A gkQZb 0W9"`c/v7Lֻ-Wo^ |)afYX,{#@`8_C"<\r@n!VߵĕNx?P { i8$LYhD)lۂ̹S]Zr!F(`T$9+ "\1}o~`sTױJY EpsC0XozlOyZ眬" 9~wbn= •k޽YMպ-9Pfn={aZF dynop/\s dD۶q)erbJFD̾nG< jSh~VZf>JQmk`FafmZ>%D Did֋r(9,.ɵpVⳆԮU_WA$7\9V4 h#pE 3o+bnT 䪘=6p5@ Q+QMxh-v*l"Tєk'x>PlP.dr !Pc ]hH4:8 *hC^.ܥAX]i "SU Rj0.S DrE_i5j\ag&`i~y_,jXRrDEq@E8K: PJ c0JPC`0Aq D&40(9u]alӊCݡI BOVg] <|Pcj =^]id>so8{{ 6< r:{GJ!+rZc0<Ʈɭ90 mJ/D%r!ДAQb}yE CD%kQ8/pzxS&n<{uHʈzr,VK+bpsQQ aPA(sxBj~0oẊC(y6ys`X4`F,1Ej w@1 FS`16+hcbl Q+RC`11`g ߠUQ38/) *GX *Av`kiC^rz5`ckE!uPi>hrc󁍈~#^+aEsړpDqӀ=hOI`?nPД\S16+:Wt:c;GeOB"o 6Up:uEN8}?[X0Q(]3%PH~($=y @,+ĈڿD%_.@{QO3Qi5@ 9U)iHQ7 O5< aE}#7@ ۴+rXpo~b}'t~!B TA.4G7 $&T 3B8_j> lUALC(r+J*j} e.W /0Hײ /|z(!0@ Y>N%EL%XCB\Eh OWX4`Q(r(ʂKYwtm7ڽb6&/^yz%?P\Z>frquB6qADQ~! wG7(J:[VxEΕ5lo#-t) /;h9Q(pk ~6^hh9}fFEͱGz#x~J[8iU /ۺ(~P5 8#k;$c{EGHgP /xnrA&(u /`EN^ޭ"?{C97p1DJQ|xn*h8I\}PJ@i)+$ O7&, (m,5lKE-L0('>`!JQ*fVj<WBlaUJ 2sK˒ w1} HEMOuOvlmQ:w[:skyuH@nee. P ܶOy@5~L,. Qn%_Pfc/QuwX`%r'8O@B_>poQ\P݃Q2_P٫-U1o@1cwSe1>>cx!P]\Q81^/|{2zxkQ>ef. 1[є.g*W/0}h!BJrR/xAH3=0nAqb ,vdP6Qڻ|-JKŌ;}_M3VZw\: /]X6Eރ1Du*(PzS.,=AA?\PPj9bU{`7"YmG }o,gCmˡ[X=P|x9rQL4TzfTxykإA݋dvNh:Vk,} c(pN4DE@ݙivt'(K̺9A@њөXۘQBk3%a3(킨 y yw;V 5~\m4sZlPD?Պn{"\ P8'hŞ{R pd*C^-g6c57"Gcyߗbu kp3%~wh># !+L󳆺o HT\xbη܅_Zl-J6enoZ٢prwY.0Cݧ`-+["(3 noyZPAŒ!䇵8a]a~}>Bm,QBʏ -9J( )> |)afY,D쨱|v~ VBK MB\iZX(v,އ 5@M/̶97r}5|@sĜ~25<0}M/T$9+ "\1o^09X Y+>빇w{B\!V;@9'+H{#[&0c8petj]}ćƖU(u>p^P+҈L@1)k ڶ{8L)ky@RSC"Q]T *9-grж-c*"Y?cyA$z PL#^GXkf\-l5P`Os5v=/T\ {D NJ&mĶ"Bt-b%W ՕJ\a!jE>rbᴢ,w8f"gtuA*@Q֋(CRh#ht~Aq Ue7 @T{Єįdbz;M}OX{1c+)'@i6^~@lg7`cV=/0c :V?EջC?vIS1 PLe&.J>eYB:2C(Jkad EAyQ\&@8?xX Z׌i׊ 2&CJÅ~R[Vh[}NTr"4;sP8֢L_uRj6ԳDEq"Q%Q(na*y+j! BI6V|z=(1L/L`X@q̹ cp@UgVVԩCOVg]~_.(xP:id>so8{{ 6 :{GJ!+rZw$Uc/8\]I'T: Г[s `&B,EWِFhJ۠(BpkT+"*Yyӫߛ*0p[W+D_1ŏ=X?/(ߵ+G`Np|b*phfNw_Q1JT>[b!Tllےh}a(\Qc f /8ҘNr!Hl0\3cP`U$;4Z!m03XA{# PUK)!P0Әw0D3l97(3 evT"(T2U;V'+0O8j֊ =;B0Zse>@}s1ea,( 2bxaHt7P1'=mf8jQI;M/pd@er4e ``ldDka9{#J\C\ Y'd9 W60?@, lzQmVyxA23{t >֪3tߺ :{F%=("Q4` /`W_.(hJ\S16!*~?w"ʞ XE@߲Al4 l u:}N8}?[X^@+ mL40(@Pe&WJ2J({ڲ輴4 a93 iy&3}!2*P1ef]^TBVwWDlM m@(Wc(C@"@nP`DUX8F߀3xWT>W(-kCI! f~Jf8ie A8DG})D "ۥ:{b `{悊t'2qRkA"Pie!8/@>[W\(~o(~yi9J {Dn9`DQ[6 (*sy@$:W/5`/dmVA|h`/c-fX4Q^#J^(Lj}jv~aY%L!kBO/೿?¦  ŧ<XKTeT=\@0<: CO/ 95s{yc  c<+Ey -A `q'REi(С8K (m,4%"}&_LEYv |WPe_p 25zWȷb*gB ~ "c߼鞥D eyNQgC䴵GHc0}`dc1d1Ϣۦ$#Tpt UCUJ>A ]^ XA|{Nt ؔ}M`d] /Ϳ>$&ݧ\:'BPj;6pBƻ-9Ud5 :$r}n]= qra(F׶0u ./0x+ib>^C](?Pfc/QBz;J|Wz@Bz_x(>Pۃ,e0@gqۥQ{Eަ*肨S_O6ؽe ?`ǭޅޖ2r.P%ZŌM( O1zM?EϷg[s6[nXN(C0c뮐㽽MR~6:X.)~0Dw!{9DC)^ҿP5xJD-" bmr%Ƞ>'-Qڷ[yw$Z! !80} atFyO|ܷ~Њϊkrf[s| PCnLztpE %oS/VX%]_qt) o?ec}3e`F>Bl[6^mgņrD>(k,>@1^~f|0PkE?Pe.`\;ev{R9_.@0Je >@C+VHCT~Ʀѝ>^Q|G>y"f]XۘQBS-TQ+*䩆Dwri`TԺk9Bs1TakO[q^u(B~/rDg ŞA2 'mN2(a)-Xh8C)צ}w T; /76g3R~wh># !+L%n*ANU~q%LbYvw9QjqcfT,-`sE_>]ݡz+9#(3 noyZPAŒ!䇵86AGjV((<\@1|kBK*BJ0hw{Y+28{_ kH z_/-2XA~WZ;=|@Tc>|{[KB1 f6Rj974S`]A-~sCϟk2Wp ATz?s"4js{{󘣺bRB!ؽ=ib>x#C-gYta:{?Zo0WkH׳;= ~{@H#^33{!(c S| ڶ{8L) _.q؈(׍PAmYi+rGRjZ0glx>oX"Did֋rH<3 0jak"{rߺ !k<7=@"D NJ&mĶ"BG(Vr[0bK$³x;1ĻVqf^{n `᜛EwŖk<EB&[/ SH@GŹ/TE3_lCVBN/`_u4Y@]I'T.: Г[s `&B۔_.Jz_eC)mZ1S=?dd-PNL46,5WWD9/9(b,"ʽV@|Q(0[BoCl<`<M/63/(%*y-1 S~*6GL|mIzk7/Qc fVGsi0Z# Ƙk`f D5uC;b)0ӘGl1p3JA8; VTa/@9Lcc;[ZY2;nXyB4`/:Y9x%ǩW6VTYך+ c3i3|`#AC1/lNc4椵'Ud7( 򡹍L^ 8*ig p D /pƆ*fOP_.`f-tZX0ҳzP 4 Dpo+PIJfAs܀ \ 1uޣcV(^_p i9TA{7NyӠ2 )5\e91  0n[P iqIlTjERU(Ny /p[bN4~1;eS!*~?w"ʞ Xy?[#!u:{pڍ`ZQ8lgJAz/\ ((1iˢ0[Fa?cc4Dq]o3DT*!EYĎ# 婆4H .lV*ܛ߀*tK>Yj 7p9N/ 4b_!"R|PǾ6 \4DZOBYd 䈠 hh9/z;څjA7b biދE2ީ@WDYxIelunuy-H4bx / ]"V@"E!B|K⾘SPE+"^y#Q[N/0,!.]P+Ae8:)ϣ PA[s*VpD …;bIFQE_Q(aZ/F_vQjEL6So`~RI bZǦ" Xeu| Ek]lڞ#jFdEy.4Dʳ`ӷ셜,MZŻv{hiqŬm(/*M|l1z_`n`ֺcD 7hEƼkx7q Co7QjN ص!'g;q1ƍ2pE!|k@q4* 8BRzV-gZ&`E~+s A?DpDsB0OkiPت0<QrNI0 \2`NP''g8w!0` e9`w]eL'}r9eۥ٭0]W,+:O8D*7MkᱷuQ q1|3vbN;.^t4<4x&nx*H$_Wp&ntҊbEN^ޭ"?{C97p1DJQ|C *h};X\TD*t(h2Β@1:ېƒXZЂ+r3wYbsP۾*#DTo@{WfZYv7FG3Pr2yNQgC䴵GHKxq n{bDX cEMI|G6 0`p Aad>&0bEPBWV9ߞ]6e_,,{E B8I)NQ8BTDݖ*dq_gn7[%PlFi*| sN{3 `ǭҸ_pDT DIZŌM( !@;hv28m]` [s6[nhFT!Z ++xooDSxЊ\(!Z""Ӊ uկ8<̀/`"y _OP}(4[DJA}NZ(~ Qڻ|-JKŌ;}_`0:2܇'.;.V|VT }vJBo- V+kU1@D vat.pE 傂Ws̩+譒8f20# !C/6F r/kwx9~Bh̢bKYT;rgw'^EN,t=P>1 8[E"p:35 X^+46(K̺9A@њYY߂0ThtUcf>QQTTDwtix)D *jݵ! )- "VtK#g+ ꋜ5 zwQ8ˋBZrQx䊖s{M!ؔjHkӾDcZ1,;# !+L󳆺Kn@bη܅_{[ Cp0W9"`c?/p~{;"_ip]=[!yDazýk0Aq7V~}>BmXɿ ]KJ~_x_.-b 8Rj֘Lpw(,+2-= j99x_C"<< 3 5s c! m /[N/̶97r}5|@sĜJcU5\PȮ0s"4js{o=NYR!sv+,|"9!Cl{9YDssLj!+@~g5U#>45rO?^Kp 53.<s d*h[h9nLl05B16"m}-g@ @ӽ `CDZKZ!6Q^MYg2@1zQ X #}*㳆Ԯ*֘ ڐ@@MڈmE>\B,P䊹0 a p{@ qU -VB/`_u4Y@<` 1!!36!xYQW"Ɯq|]1nn"okZ!m a&* B"PBg,KH_fEiήz5/=AY+VK\/p/@JÅ~R[Vh[}NԶXc}a: Zj0EHTfwxFpP+j! BI6V|z=(1#y}}j-9PfO:۴"PwhgsГl 56@-T߫+*F8g{ź=py`_cy߽#@%9PY;ƪQ ~_.த*@Jɭ90 mJ?/D%r!ДAQb}yE CD%kQ8/pz=h``A|徺2@$ x*߽/X,Awn"J>;pր{X/dnc/9u(}!D(QɮSPHmۦ7&>$n2ZvC3i hX$6c1(h0* b9n/L(fmK?D}Vi,cGP  Zs?;FyEצBon:Ԝkq *C7N@w b(q۪ rE!-G9:\hA=/8BR|Bcp,\ La])QEfP Z(f?V"\xSLײ<|3D ԇ)BO.>N%q()B`*(pNt_X|_.Poz݊o3ٵ{2mL0^{QsF?/cc-] 8ULi (F3| V视^se=/ mE.ӦB&1:m{T$' Ũ!W$ZN߲QjQs^\<CupC{[ů xbN HS񢣧Xj򴭀xJ=/dPEN;E_hsAS?KP+Ey&*h2`q'REi(p@8K:bslC8JKb=/ z 43}&_LEYn#7% Be_p 25zWȷb*gB ~ "c߼9@mʄ enŝφik)uXL|/X(+Y!r̳)ȦDp?,!C"(l:[ַWBl!y su): %`b@l1 AGWt~>uCQ{DJmQĶm̩B&Oe~! @Si=/(C fb#/v۔@g<ƷxL5-'0|| (g{p!D};J{(W(BT [T$>(Kq̀ v(mb"c|+>9Q>:-q?p (F!qߖ2yh9I-[}(fLf1>tf C8(ˑh}f~5gY?pT!Z{ ++xooDSxhW> (!Z""yl(}06t]3؃6H{qHX\2Io J'? t˶@1c;D+da0痺&!L([hgEyg*Vkh- V+ϪbB ׻0¢;賧{!( J^1^J RmN`(Cs`0f!Duh4Ć:M`C9 "P 8CD﹃xkإ,*WeEc"N^)]/ hPbuZ!*3R+46Dm]wY7>=Z`v:շ536fb}ThlLig@z/p>/ -2J@E#A!>-5p6} T+# k6+ N ~6=dN{ND %V+Zα5"p`S^ " MAhŘ <*Ŝ< kkݫVDPk೵(-4![ }<]ODoHf#Qc极6 5 Bkq5zsC sGj}( De2& A2E!GW4w;Y+250^TXڡI_P=&`J-j1c#1;$LYLfjy`_..e1ÊT偊Dή0s"4js}sL{{yQ]J~wД)Ϲ` GߐA&)er /Qq؈M3 h+i3[ |h9cRjM^}K~_&(Y/~v#ˢ%}*㳆Ԯ*֘ a NJ&mĶ"BG(Vr[0bK$³};l1wb̦^ZSErwb˵Up!EO SH@GŹ/TEk3_hq4H įdbz;M)WTC6gƌ >`sHBHYX1y݀pB;zÎNFf5A϶]RTpT0n!ThZ3P%C/3Xgg``/=AY+VK\>/p?/@JÅ~R[Di5f iYwb_q~l(Պ(E `coJyQrE9R(}lF17(k@tk<X@J' cEnW3:۴"PwhgsГlk@3_Bid>sW+We!?݋>T>Y #`{1J>2ԹMLܚS3Jئ2@T(*yEYŪs+62!le#l9ՊDc1X('`ޗYdV^:$RbkH4oB( ז.Eր۱RFێռ/B*@1JTuR%6LlL|;A~&p[ ^cbC3(_p1'0B``fƠ(H`h}!m03f5F "lܠ"9iIo4`ǽ in`&ꩲ4ਤA_ Q$ L:`kՙRJH {8 ؃ }  :Nec ){h 0n]Ppqy :vU`_T0[*P"Q4`<( LS? L{+b*F}eL+:Wt:c;)ʞ XE@AUp:N݈'>v)h(.3%ӨC xj@`+Ĉ'ATwuo 6qgj'"sZ%Qe}[WD<4\ .E WtVe"ـX)tRǺ7VpDBs|<rA(}d@KB8e/%${.cۧMU檠z1 #S}(0"lCC:?pz4E"xqh^FPXq)zj7Wu6[\i9<| BԊȽQkot1/n+u{8J[+R셽Fn@LÜo/e q.epܮ腱Au6S'$V}``_0 ߻RT&Z/fJ֋(W1G(03l!VT]/;T:j`pjK OWX\)(XKOd+2QWHKzTi~Fi-/Pua/܀0lDN+}^>ڒ5#c צ n*iPh9aݠE݁TDyPXV7ʷSo|ԔOecd DʳMݷ셜,>#-|g5FOV6-/L(fmO?DyVi,8Gpo+J_0070k1 'ԊFyEצBq GϚ(xvmc;2Dm І N*:u9R!׷&to/zN~@ !R|>X fY)QD3 (gs Z(f?} "0 eyr9gB7S Y^Nm%EL*xCyr"x2]W,>z@EY+R#{2څK{,f} Q }̊>@6ұKQ*FCn J=2DӽdrFZRuݡ/}N φb+ -O(Z{ Ң/n : X8۬+{/`Om؋95z)E/+bs[T=y2@&(_. *rjp-.H~ Ǹ}ZQ|  Z1 ޑAQQX]E@ N͕E/3f,܇ bP_^Q\ x djVs˷61`!(~v\lxP?s-+ _pe N~' Q+9%@P7_iP| J9^tWe"2E')B1n+V{J?L.lfXA|޵!`Szj%vatJ5=~"ô;#B:L9sZ!'EIg 9w1T8e0Q?3^PsL,>p |Q^%?pefkBz+Y\t'>p*B*H)(}68">}l= {EƞQwtA%O6 Gq[dL&ZD$~@-bƞQbG}ԝp rmAsshrz74~5gtAef}>r no@4Ucw;%E"yl{cl/i 7irƭ6H@Y% 6_s(' p{WG_M3/0Vyw|{@lQu|ZbZbmDp̓Dj( `ݡ?AA?s  +.Uo2>0#֡ˡk,.lq9!"P5ܢPxgCoA4v/ ~0{"\S)m8 AViFQ.5Z݉ ٶ^!0{&(tgۺk3b}(4D6>59_>a:9\m4u^P!>.li薭;Nn|+ W!?ڥfP6uV9(JJ|^-g6 ipmgh BW#Q/, 3'X{}(\hDuz"R4P8oP/^n bη^ZBt-sR 0=6pw]P 5_y>Z,ܻ;LIP_d!zϺp!5ܢ ڢ@G s(a5_hZ(-/D|6)k$sSXDž j0f%[!劲V1kvKһAt~0JaV~ CmP0n!JhB{,KH/3DEi`PTwEJoA5nҲar|XRjo0i Dݲ| ֱut@Ef+a{&`i׹S fVj ?(_>H{IDJm c>L%ʊsJWo3" 0Ao ^\3 -ʡ$`]ǠDT:f"Pwh9Al9_> ؼ-Tǭ+()FCy W6+T(GwF^FJ*Tsjmn P"Q4`S,0/xhJݰN+CN'zVcЧlF-ANS1> 8q &Z+ KL4*$KIlj@`+Ĉ'ATv\QOc83Qi5@ 9-UӨ;n!/pE.=DnDXZTpeAmQ! 8m ݲں7A%:E ͱm 8ϊng*}d@KB8e/%$|\4ǶO,UALG(r>fp텰 q7b biދE2+EYxgdGw;NfKV|f=y BԊȽQkotȱ6pIsDP*{Ԋ{ah[y4"0e]\]/! cl," թO$@mI \`.DYw'!L^0#Ql?b(G5Pwaˤ ڷUt y\pjK OWXbzwak鉬{E:zPr/N) 8lyޏ4L`&`a/- A߳Cd )ϝ(mjEhǑƬ ;bZ}0(WpR3cpL}s~i0zaU(6mŧpSIB (Zǧ" X²@E%ALU "Uh"- TTBHt<_}k^3WA|VQcDheݲ/-X(fmO?DyVi,%JcDf;FTAZ¨1t^h9;(YEsoml5P(9;r_J\DC8R!y}58pZ4y! Phskaihn7p%`Ne #&,H40Ӏ}6W*bS_ "0(,io=CJBPV,/'"_Q 0  X 3@EYpwV|Q̮]8ɢ>f} Q^tFѼRݘ6ұ "JňpwtQi8W\w#-t\PP폊Dq[gC1:Nӧlf-j= G (ӀSȏ|cuQ| ,sP腥PH`쉷 {1f_/(t4^ޯZc/nJp<96XT\q$`?cܾb(>Y\\"*t(hbbt̐$L/3f,z" QDK̺ |WPe"*譐o($mb*gBPl7FgFQ27t},Mv;aZ φio.sۧ?ZLY|-gfweq7? 6G`D|^0Xka}Pz >j }D GYds@٫{=3.1Xwv@k1Ѷ{"̃DS.,C >^S/V[%=_qtvD]XLYAmVT|P| @1;BDLs@`rQګwt{q\G 8zE9yS(Kp9~HTwfjlBc;Aǵm}+on!0{&(tkzk3b}(4Rc4l:]`׫E8L'0x[<0{,W|sp`3TϾK8>~Z+e<yJUȏꃜF fAF(C%s%^-g6c5'"Gcy߇bq mp܆ϓz;b~o !+L󆺀O H~*wKXs h g(-9J߽,Ajr " iD6[!(}!YDa@HZ.ྩ ?{(.6M~.HB(?/pM1(R}*aESZXrꊌ=>;߆D -zme "D =J.!.vATcn;$!Jm5` \0E/i.|bNŊ(CCkr"Qy^<'wD݃muW~`PlW(ζbKߐlOyO&H6CLu,\v]_sk0WkZGw$`{Vyw (c SkrAm;pR&k@1f_74Ԯ*!Ol*0QD_.(VH f= 3 :!-V@ZnZWqz8ԫ@JB?R[*`b耊4W|ô,L=n{I7PlI}5UT/(^Rj[ØSɫ=Ymd`Pګwb7si si~}Z09ia0u L4Ac-u&}̙\rPc㚯h n]fq g/t@^!PF=ʷ{GJ!+rPYjc3_`N*wR_+pܚS3JV)y *((Mi;E.VbE CD%עqn0TG_`UhN& 7x*mY,myECkMDK`m?BoClwMQhƶc5ߧl%]Q0%Qbc7.L1eWk0j i hX$6c1(h0J);4Zb9n5F "Q+17Ab q/D>jb׫G% zQ8 2 @Ta93 " XAY1 N0@HcЀmksa{~鴰=`~eEAgZ! ⤊2x+tVGvځU(loxV|PZ5 >6Uz0 :}`Te z`:6pDOp4È E0U_*ܿ ҼISs+: l~7Wus[PT{eQ+Bp ^D}LW` !TC%qAWeR+R셽Fnb|kl`%XSvSNfkY:9^x"…賊m ̬W)BP*CP,^IĈ~T uWLO+ }[@wup!>]a݅r'3̩*>v2{?3e_0lDN+}^>ڒ5#cl0d1~m`&xYGFbSo0jbi=9L`JZƂZ_^ض|hE MD)70?+TҠr*A1%DBVawh|8 >. |ڟ#J? TTBHt<_}k^3WA|VQcDherUbVCk&ʂ >>x^ 1NM_0070k1Zk!!M6Ÿ5Q4'v\eB񍝳x9?J\DC8R!y}5@ f8-sz Qg(49µ0L4470A?D"Lʷ{s Z(f?{TERiX/0 %! =Yx9/`*P(/`:|fEk Ȳ8~yADQ}9Cn J:" G?5~7+7QnE.U8o i"Q\֠PxEӧlf-j= G (ӀSȏz\ͺ(B\_.<[=RAG_`Wi/2QGD-xKݡ D OA97B+"h@7BVtx#%H  ڱ@ش3$$n ZЂ+r=wYY1>r(_I@e/VT!L an6B 0 +HCb,~ j[V(~\(en7?3E φ64w7@e{ 0 O`\+D_M*X8Cr;@rAۊUٿ&0b7@B++Ȝoώ.ҋ'U%vatJo4ߢ&m%Wo4KUT6EE0wiL6| :${o o/T-gfweq7? 6G`D|^0Xka}Pz >j }D GYds@٫pM&[%i9&}< fU(FqG}3ãe[bE,G1^1^ tk&`= >[]r nM h4U! >(!|/|!}9DCU/xAH_ "{g# GP|=מ|kt5ۻ:"Mrh!?Q"׻ԊUFז/X6Z @힃>Jw`*؅EwX~rs z+.Uw?2>0#֡ˡ-lq9xYF&*[/y MؽH&`{\oN^EN_@R6(~N:-(*՝[؎Dqm[o@9uE}@kNW1(ևBc+>VZ\ϕ]NiD+i)i_>PTz[ ôzysӸ9 _.PԺ! R+ΦO֊nYwF0_p 'A6uQ8owE \?h9jDMD\%&9P=6l~L{{0m_)e(7}9-EW[ŲxZ/V0>Eiٮ AM/p~;^[NZ|Wa3 sYam݊[B֟PBŒõ8oY#*,}x0P({ B2BJO`>hʻYWd,m506$Lz| t\+f&({3Jw_.m@ fjr4`>_>P\ŜދPC|E#[]a(\Eihs}rL=xPq%gY ,|"Xl! Yo:d"4`s14iY40 '\g?pϭ T[|h*Gu>p^i@kfy \m=ɚ; m5fa42]ډmE>Bt-sR 0=6pzw=P g^ w{Sx Ė/+ 2Y-z -4p$8 *]Z Uy5r@)jsrw7:.$Qc7+)'@i6.WeOZV1k-_`` :V?0wZ!϶_RTp(CRH4Z=P%CۗXg^0DY(xE*λhiշ`Ƞ>t< ZWqZ*R R{OT&-ulPYcgaq ľ|l6P.!^Zp F5WA4`F,1 1 FS`1v,VОYA8? C+RC`1q`=lso {gfev\xUQ;3h/:Y9ĸU]lZQAgGf\YTi>`@:@Lci5󡢸("P|xEٸAEsړܡiy QӌL^ 8*gP8 2 @T{e0|4P`P f_>eB_.Ðia9{#Ѓ.!.BId W餭8yA,EYA7`{+3p}Ug&Jyb(g !@,؃ `@@r2 1mn P"Q4`8oyr?/@S| kt^鼢9T8*{'`:}!`TiA Ԋ:N8}?SX0A(.3%Ө.QHK&{q#j *ن0(~[n4< T'"sZ%Qe)vjC6i_(4\X{܈5 =8m ݲں7A%:E ͱm 8ϊng*}d@KB8e/%$x.cۧMU檠w#hGh9nT G38PP;Bt܀#'y/˻W4Ϛ=rAtשmAEPF _3~ !jE(еjl|(į(m(Kx1 s<`%E˺!q^(CXDNSH ښX y,\ [_/R.E z1#~T uWLO+ }[@wb^]8t%ŧ+,Sn0Dֽ"cauto`NxN8ua/܀ܲi9=;xhKPY2۶V$ kf}Ii r믋Nm!HH3R|7.503G0o!ZQkQ|J 74(nP@|*"ЀU(, ǩPfqeE>DQ[6AF υ\y րgBe_[Q ڞ~bDYJ0 cDf;FTAZ¨1t^h9;(YEsoml5P(9;r_J\DC8R!y}5@ ?"DzN~@!R|>X f}WT;mD3 (gs Z(f?{Te.W<SR{ |4߷!JL!(dro+i~|[IS P|G<yӉPv)_!r/Twz2?fkew`xE_}G({>fEk }ƁbD X8;(4+Bp`F黑T_@wP폊Dq[gC1:Nӧlf-j= G (ӀSȏz\ͺ(B\pr;$쉷 {1f_/t|e=q_.<-c|eT=a@&(6u<l\PSs=wK]tqz!+<Tz#d@wpq;R"4*Сώ@1C8JKⶐ KE-L0('޳BQn#7TY/8BDm @ Ae,X H, (j[G^Teٽlӵ CJ ~6DN{{4w7>ъ`d1RX"܋n l@|pZsqT`!{ƳM`~%VoFXWV9ߞ]6-Plxam@Vt~trT?RaB:w[:sZ!'EI,|1w+̇sA 3/O?`Dy<`F !,J|Wz"D9"g,2c@٧\vsJ@,WdU>pW@D|pe8 ?`(zx&ůg2r.(%(&z'jq܎_.3*8c+8G9ʶ99\H4K9ߞ!nl9?\X} r 1-hJwH`F 9we)5˹ b~! _.U_Fi48U@>P| ϞBl/3HT! {!8h>`0:|FyO|zw|{@lQu|Zb,~k1Ѷ{"0t*0_`ݡ?AA?s  +.Uo2>0#֡ˡS8CĨy}b\^Ÿ`kE?2bKك tvO?Gp(rjr:L PZ!j}PbuZQT;35Z݉ c ۆy7"fl[0ccPV }ݔ|<D+i)i_(*-aZuk9B*gߥVMwB?ݲF 0_.p 'A6TE!]sE oE9V&ZlJjOjEĘ, >s6gO{{0m_)e(7(q=٭T`8-bYvZ/ n+xբlXny&Њϊ{Y>`v.`Y?iL@E j̴l Y.V@ " 3B jω]aQ>lQ(<c ] )>)ffY\1WQc 3oC"BXڡI_PiWZ|@Tcw0m[_̶_>0E5ͥ/s.V@b "Qϑ0s"44>c&Pq%g]YOJY E!CL}ޖ OuDi1bi29ܳh`N?]/lMZŇƮrTa_{Np~@+҈L /.[ZQeBxB1 /0%*]UBjl*0QDi`*@+3O3 EPkp 0%_>@39rPQnT@UHmG#ŹTEw]u@-J 0_(~%7lqq~@Ԙa J 6kE !劲p\Gsܾj,DRջjg/)B`*8?!D[pAR$j`P(ҡ QQZF^j}݇W\ܾz_h>>-VU\}cR{OT& mk4X::" _0= ~@) ;|Dt@DDXeE9AP c\v& 1M=\/` `nhScJL[M?'=y`ks=|*u%%0|sW+,+hrAnjҋ>T9U,^#8<W\)uN'L4fJ_.J.>ʆ4BSE-Xc?f Cfo0DTr-PNw !ArGi|!.BId W60?x^Tqv_.0cXY[0XLt/PZ-@Fgi$EFp{ж*{8 i)|/A06=wA =ǸjqU$p|6*yp%Ei^e<?/@S`WLŨ,ixEN}̡u'EQ=бS6J– QVԩߍn8u٥zdp(۠~QD@`+Ĉ/K! jrߖFa?m4D]O3DTJL*?ByZ i" ,Xų]4 V%߀X ݲ/|DPK8Au 9 xV|PZ fJf.cۧMU檠ʜM%ZH> ~|(05{c54E"x|@,< A`\F`:m"6/DZ7" tc[rM5\T|^F,,^+o$Z 4vrY[cAN۽ jL:p'$Vx*>Y$&(־YR2z1CP´^DJ F`̰eR~ZaP[*C<]8tOWX\)(XKOd+2QWHKzt9yp̺EKo:nD^́슲 Cy@[Z`dה ,<Ư׶ D"QXW4HHcV[]Ltj FP 1>GBi#2UIkrXZK Bi(>%gJZNXE7(FbwoHt:/4` Cq-6|\vB퀊ecd \hΕg` o 9Y|FZ*4*jl[|+Ŭ(8/*M||cD``n`ֺcD;aZ¨1t^h9;(YEsoml5P(9;݁s!FCN]T 8z;D]lȺ/8B# }p- 0 z, S( !EfPJ%`B>Q~KTa@DpJڀiX4߷!JL!(dro+i~|[IS P/(Nzw_,~ș|,x~v+(f} ƋWu7pD_P1+XGaFwHbD%pwtQi8!" fiKxtg :mT$+?ѹuH4>e3hQs._΍=\NM,B~x۬+EAe\vB `x۰sjAGč_>@yZf):^H ҨBV^h=32cv6Ŀ0Z53}&_LEYϊY7@oJ,!L an6B 0`!(~Vbg##mYLxGYv/ tw  -] u@ؓ >H`%Ws/}J+زiW9 cHQEĸX5za~%Ė_bZ^ XA|{vmؔ^>,<, [oWg+߸:M3AE!( !Qm 0i˱<8䳷,|1}xF }ni4P|r#ʫ\,|r̓BYX/`%+.Dr@EBr;EEGYdpOvX|3|஢?p.:q/$n(1p~ Q<L&_d\PJPLN\ fU(FqV'xl8?(H4K9/_ȘWӭ9-7rf[s5>Qz7]Xtzt"|Ws̩+W]ކfuec}2e`F>!CCXX]PbC9 "2@1.?7hn(BpR.*W{vN^EN_.@vR+R/BlN4@w NQ϶uW*fݜ{# B`hMQ,kE@>[)vSb6>59_>a:9\m4u(jZl wgݧOkEyL (\uR4\YfAF(C%p%>@r|3rX=ipmgh BW_;VN۰9C{{0m_)e(7(qT rZDbpe1h4Sjg(-9zrZl8x;]w[NZHf-Qc`Vp@_HQ6@~'`'pnh>/pD6 A3 R>@pM*Gi+Jr`>hʷ{YWd,[zV1\߷!`v !^Фq.B c{WZ|@Tw_>@֮Exm_>0L'r@MsŜ/PCx!_>Hsd+ " yN?09u\ YW|ӆ _`NI ۠mٞ򴁘pbi29{@sk5U hz.`n=H#ryܯ%92Em۹Ô2Yxbw:B1 /0%*]UBnB~j(W  mRjEç\[;{1̺(ڍ,scN !ؓUg $֘ѰWLorLt +aE ޲(sCoa_)V;VDq1;Vqfj-v(r/CW[* 2Y- -4p$8k͛>2y^uv4!`%W/u b%[@ܽ`n 븐D"k-JkHT!ڸ\Qncؾxf ӵ7$@aV~ CmP0n!JhB{,KH/3DEiZq=AŹ}ж5|/`}[@z|C}r<`>,!:B#&tR+5j\a{&`i׹S 5o8{{ 6yF 9U,n`{1hxJz\r9MLܚS3JV)= *((Mi;E.V[D 2DTr-PNw {)E0fS|qy iŗqouJV =Ս`kiC^jƮ{v`k͕E꣯#Ĕ@  2^t6nPƜJ{Cy_.|4c70ŮWJp D_@ @L(Yx, |@ CԊ[(r'_.(!Lւx/|EN~^ŲjPׂ xf +Q8D)OR m`N^:L .`@@r2 1\erc4.Ӏw| :]-ηsF%o[H< ؃/p|b\`tV|TʲWt:t^*~_wR= y~F-ANS1> 8q &Z+ KL4*$PAECm* P,QbDӗM L5o 6qgj'"sZ%Qe)vQ(Ok@! Ww+@ Ӵ+r58`U% 8Y-G5Tp9_>hr@(}d@KB8|ieS*#Al>ryassiZ';VGuڀs4bxF_"roEt51mD ~EnOGikEYWH-/i|,!.]2W8"`@T֜DJ\fBU{wQJD A z1U"B8F`̰eR~/bHV"il5¡-(>]a hts'  t(Goq9@_䰎_-^ {e rZ!{va_.;5e! ŹV$ kf}Ii r믋Nm!HH3 2sQ*i_. ^kq~i0z]ȇVTڴAM%6'*A1%GyPXV7ʷ{mJn<D>'WVBHBj-v[BNc Ⳋ'n98bVC xbN15`/,Ljj)J_00ȘcDN Mk9o㐀]؎k Q(sv/'8_ :u9R!] Q.;GaT9-s<Qg(49µ0L447}β$`N|7]$i@>+UF1/ Se.W_>)icY/|z(!z3Г Y^Nm%EL*xC/`:|/"g򁊲RYkfkew`xE_}G(xE|fdqtlloQ*Fˑr@tvE~jxn!8Wn0H]/;x-L JMv[φbt+ -O(Z{ s%!q`S 56 q1g/`Om؋95zH{/<-c4y-pP:_.Dæ|"zn/0 6(`ChWDYƅuLY):^H ҨBV^hcp6m!@Zp_`~e3QNg.+?+fGn+ _p 25z+䇹 ۋY?+A[1ͳ{CAb%+ _>(eNV!r#KnӠ4 >#\!r̽)`˦Dp_,!G_>bx ̯ڿVUhy%`{׆ME |%v19  HъoQ].:'BPj;L{8B(PnK`N+d(P~!/@l6@bcbio-nextgen-1.2.9/bcbio/data/umis/10x_v2-transform.json000066400000000000000000000003151415626112400231370ustar00rootroot00000000000000{ "read1": "(?P@.*) .*\\n(?P.{16})(?P.{10})(.*)\\n\\+(.*)\\n(.*)\\n", "read2": "(@.*) .*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read3": "(@.*)\\n(?P.*)\\n\\+(.*)\\n(.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/dropseq-transform.json000066400000000000000000000002331415626112400235740ustar00rootroot00000000000000{ "read1": "(?P[^\\s]+).*\\n(?P.{12})(?P.{8})(.*)\\n\\+(.*)\\n(.*)\\n", "read2": "(@.*)\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v2-cb1.txt.gz000066400000000000000000000025221415626112400243060ustar00rootroot00000000000000cjYharvard-indrop-v2-cb1.txtMˑ$9 C Hmiၪ EoG>-F3w2?h-0.ki ؟zL'n]?8ۿxDp?e.3a*!/e~^O.^e=_]%eQy/Dk37iNRO2UnZJC]~"'5/|8iDEN"9`Re2FDD9C7 >)ϛE7{jŒUf{~^U ?Se^޺k担P0h=iB>ͿN=oDL=Rz>Tj͘NaR&K2cErEr#vDM <&3m m&Ҽ6 =PP2TC2]b5ު4ˤ9F@#G{nN??qf$eFvs?tD<4j{MX@*s{nvQc'6xGbb4Lzf6l'Iɀ ĒBIp1%tԉS} tRIʗ\'W͛`s l-RO23LZZ Lĝ72 ɽ_?;\&6f,atGNtc0(anb4"|W +6ŀ>izҬͮN06s5l;#өhw$2ݞCUȨLj|hV/vATL{_Qr~+h7Zcɋ &[6IT_B칖,ݪz3̻N0i&N_&J}yw&񎲙ޞ,N#wǾj(d@sjDՈml{|Lp@ߎ~0zʹɚ򖻠ݪ>ʭ;#ZЅbcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v2-cb2.txt.gz000066400000000000000000000022151415626112400243060ustar00rootroot00000000000000cjYharvard-indrop-v2-cb2.txt5˱1  PИ-m%RIν7ϱ3 q'TlW' 4']1f<o=eyFStة[<8Te8ד8;uʊI};7[NvOEMHwAq Fu \~ԠɅ&?@k/@O}jAcV`jL;2Iah,iOMR$(li o%0B̆e1;2%P}ѭ73t.ymH"rQ߆[Ϩ:Ob&_@HT zv(|r+=)6d~ (?QZ/ P|$4 : $=C.bF>up(M0Ue zAx5Tio&7 ז1 $Q2 q.UNOrċ><*n _3;՚*F L2y 06u${ĸ@uc BDvzęF8;/ zhό}FQ; m<ϟn 0VEfSlH$r@vM/yv>qIRc=QlkQDM3KfHcV-׶H$ $&Rz]ňuVqӊ;E'z 񩩜'rpx}rvLֆy*ʬ2TD :5&.mw6=0zI3#\^<:q*D` 6'el!:"p~J bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v2-transform.json000066400000000000000000000003101415626112400253600ustar00rootroot00000000000000{ "read1": "(@.*)\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(?P^@.*)\\n(?P\\w{8,11})(GAGTGATTGCTTGTGACGCCTT){s<=3}(?P\\w{8})(?P\\w{6})(.*)\\n+(.*)\\n(.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v3-cb1.txt.gz000066400000000000000000000022521415626112400243070ustar00rootroot00000000000000cjYharvard-indrop-v3-cb1.txt5A$1+>)wl̄ 9יrO{@r |O-@UI?<4.hLsOIƫO`ݡ`Jp=-'9KLc]ޚύmq9ESY=6.`gISdͳ`&=Z~q(h3&#XIر$)1ZO)Q8> e3Օ 4*I8_<; 0sZmcòhb;L$05#F\礐L:iև <`#Ѳ|v}( W٪~rC;G[죅KگWȏS'!a<}+ ub' X*2c7֚L!'[ DzL;0(p.g )@>?PZ%9ll5?UTGR(ˬC%W-}i (Ǣ(IuBJtCs9 GzgAem-Bm3?/¡%^[A ~ZTCdZS|HOJUZt'8Ltԟ[}J?U3P-P54a:W^9@[XAl)pחO,[Q0=GB : Q?n bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v3-cb2.txt.gz000066400000000000000000000022151415626112400243070ustar00rootroot00000000000000cjYharvard-indrop-v3-cb2.txt5˱1  PИ-m%RIν7ϱ3 q'TlW' 4']1f<o=eyFStة[<8Te8ד8;uʊI};7[NvOEMHwAq Fu \~ԠɅ&?@k/@O}jAcV`jL;2Iah,iOMR$(li o%0B̆e1;2%P}ѭ73t.ymH"rQ߆[Ϩ:Ob&_@HT zv(|r+=)6d~ (?QZ/ P|$4 : $=C.bF>up(M0Ue zAx5Tio&7 ז1 $Q2 q.UNOrċ><*n _3;՚*F L2y 06u${ĸ@uc BDvzęF8;/ zhό}FQ; m<ϟn 0VEfSlH$r@vM/yv>qIRc=QlkQDM3KfHcV-׶H$ $&Rz]ňuVqӊ;E'z 񩩜'rpx}rvLֆy*ʬ2TD :5&.mw6=0zI3#\^<:q*D` 6'el!:"p~J bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v3-sample_barcodes.txt.gz000066400000000000000000000002321415626112400267610ustar00rootroot00000000000000cjYharvard-indrop-v3-sample_barcodes.txt% 1 l`pOR\׺޵>9{T_tyly[r>{9ZX 2?F~ ~,3˷bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v3-transform.json000066400000000000000000000003761415626112400253750ustar00rootroot00000000000000{ "read1": "(?P[^\\s]+).*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(.*)\\n(?P.*)\\n(.*)\\n(.*)\\n", "read3": "(.*)\\n(?P.*)\\n(.*)\\n(.*)\\n", "read4": "(.*)\\n(?P.{8})(?P.{6})(.*)\\n(.*)\\n(.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v31-cb1.txt.gz000066400000000000000000000045111415626112400243700ustar00rootroot00000000000000`harvard-indrop-v31-cb1.txtE˭1 ʊ 0X<]}aь$nnUu}_9iM7M L f܎l7[>+5wM̖v}xߤ G N1kN8߆F8rac]3|t;{&/t7 s}6g$.`1Bcxe$`d vyͣ͞;⃝Ѐ@6ZϷ6r)1׮#T=7n'| ?tOo,p>8uN5q3@6 X?F^֊ .P1;pA}Zc9@-Wc0 '=1c;;:vyڷ%,0H$K/ e8WNL/fN? 8@Vq?m*W Uy/wHtqu/`@sb̞<#4;rnxOvockiv%]`Zݦ Hj2ȳ.FkH$\$G )ۑ܎#}#r4svD+F2 7Fw!FbB搖>He܈ ޹vMXyRY`VdN>Ht\H1Bx3ŵ⼮5&jF8, -A`NBlq.JmhEem4ss}YJHYKdn)_Gl&%Hb-3xr%wYGH.nd?԰ArN6yNKO 0Pt[HľlH6 -WDKJ2@՜,;saϒ0%HxiDpBFR2?/"Cu p'z_r8K1[g[.]GLk .B-&oid-| '([ۮc( sKhvcWYɞql [ U/k٨1RY Z.0H˾+C̍$4IԲh`[irabJ&YMc>1vXs@4^)*`ךQz!$HvF@8B xɴddL $LNJeĺy:l)V=p@|Wջ-;G4S% qC_́E!Q \򞫯rqg$Z|;z`֒ ^6'"IT+ 5_-ZNѪrR{9%e@V֑9|!'Wi/`=4uk"[IyTZ=px/`p% LVqm2xCxL>&rGLƼ=}Y.F%+ۨTUX"s~zg۹ ΗuS0iE-VDPHv~:ɪj9O'Vت=M'u/4=' EiM>{RȆ }e;EYUڪK*]5苃~m۬- ;k3mApeS)O(o4r?RcnU#E9c*UkMA0]rT@ue;jz_vZ{vT*&R] 35{I辶K!ɆF6%B7uO/ɤ!bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v31-cb2.txt.gz000066400000000000000000000045111415626112400243710ustar00rootroot00000000000000`harvard-indrop-v31-cb2.txtE˭1 ʊ 0X<]}aь$nnUu}_9iM7M L f܎l7[>+5wM̖v}xߤ G N1kN8߆F8rac]3|t;{&/t7 s}6g$.`1Bcxe$`d vyͣ͞;⃝Ѐ@6ZϷ6r)1׮#T=7n'| ?tOo,p>8uN5q3@6 X?F^֊ .P1;pA}Zc9@-Wc0 '=1c;;:vyڷ%,0H$K/ e8WNL/fN? 8@Vq?m*W Uy/wHtqu/`@sb̞<#4;rnxOvockiv%]`Zݦ Hj2ȳ.FkH$\$G )ۑ܎#}#r4svD+F2 7Fw!FbB搖>He܈ ޹vMXyRY`VdN>Ht\H1Bx3ŵ⼮5&jF8, -A`NBlq.JmhEem4ss}YJHYKdn)_Gl&%Hb-3xr%wYGH.nd?԰ArN6yNKO 0Pt[HľlH6 -WDKJ2@՜,;saϒ0%HxiDpBFR2?/"Cu p'z_r8K1[g[.]GLk .B-&oid-| '([ۮc( sKhvcWYɞql [ U/k٨1RY Z.0H˾+C̍$4IԲh`[irabJ&YMc>1vXs@4^)*`ךQz!$HvF@8B xɴddL $LNJeĺy:l)V=p@|Wջ-;G4S% qC_́E!Q \򞫯rqg$Z|;z`֒ ^6'"IT+ 5_-ZNѪrR{9%e@V֑9|!'Wi/`=4uk"[IyTZ=px/`p% LVqm2xCxL>&rGLƼ=}Y.F%+ۨTUX"s~zg۹ ΗuS0iE-VDPHv~:ɪj9O'Vت=M'u/4=' EiM>{RȆ }e;EYUڪK*]5苃~m۬- ;k3mApeS)O(o4r?RcnU#E9c*UkMA0]rT@ue;jz_vZ{vT*&R] 35{I辶K!ɆF6%B7uO/ɤ!bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-indrop-v31-transform.json000066400000000000000000000003761415626112400254560ustar00rootroot00000000000000{ "read1": "(?P[^\\s]+).*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(.*)\\n(?P.*)\\n(.*)\\n(.*)\\n", "read3": "(.*)\\n(?P.*)\\n(.*)\\n(.*)\\n", "read4": "(.*)\\n(?P.{8})(?P.{6})(.*)\\n(.*)\\n(.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-scrb-cb1.txt.gz000066400000000000000000000015611415626112400234210ustar00rootroot00000000000000:W([harvard-scrb-cb1.txt5չuADQA˗ K{o*Úǚ?VYaGU֦omwKNyq|%\&0$W'!;Ɂ<D8G& ~$I{P~79Ct;lTD}$M_ V6cD#q@б}_s)yI3]oK$ !Cz ,,p6%29gv%v$d$\}Ě"\v*y֦OA.$H卸 6WXur3֏X3f4cnȭF`U&s'$k*IR0%B|[q"RԇLyw*aNتKgrّN 2ּ~ydr#n7_ e{jmڵ3{2K]#L&V꛺,MzTr+@Hso]YYmgJY\YT,{cItX l6>+>duŹrq<ޕ3!9lHV>RTn6G ':]6PL0=sT"q`Jbz2p9w  "8N9f"FޘY@u5 ֌V,Id)p8N<1iYgY5O KOT[#;βuK٪Nm8q#Y6^46/—'.c>YKM~}ޝ^aZܧf $L!鑥TR/JD4q bcbio-nextgen-1.2.9/bcbio/data/umis/harvard-scrb-transform.json000066400000000000000000000002311415626112400244730ustar00rootroot00000000000000{ "read1": "(?P@.*) .*\\n(?P.{6})(?P.{10})(.*)\\n\\+(.*)\\n(.*)\\n", "read2": "(@.*)\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/icell8-cb1.txt.gz000066400000000000000000000471741415626112400222350ustar00rootroot00000000000000.Zicell8-cb1.txtU[n47E?%TIUs_tW~M39}s_NϝK|~߷ݫE~]{~i~9o^;J{;};6c<\{7qV޽ޚO:߇?On |}} ~ ܡȽ>Ps j'C|{a.~Ռn,5~p}I<.s;^9wt@ݑ~Ѿ}(7z,r9âmsCpٽ}~;fp}kKX,K7};Pw5ګ;s'}A;Xw}<.zw]'`o* =^ܽU5"[]ߧr7%vGN3wG;N]w'{. .wg;;ųB~ w|Gt yqL[ٛ%F ]}*Kz6ȡ i.K/ݯoUA-|;C{SN:軸.>8~Ρ>ue$f]/M7Cugvaw:-]^'9[߱d۶鶄]/j5E} 9%Zޱ5X*/ bO۷ou:Vػu%C;,vHK8;GjŶ 8l(;yht7:A6ݍPFv1%Epm۳z3=@0uNv#MJ;Ka`VݮQ {?Lue 3d)Ӯ8ƁK_xZj歡kOzYm+3;kK•ΝY^߾ƁbލPrZᖧM͆o_cWKyJ:&f;9TTo9~БpAJU@}rSn vXh,ԃ AZr;-R76k,F6r/#<7 COA*8S-̎t%w~l?sٷk4iB_1uvzʳۃѤsC=gp^fz(V=mӦjt"Wr1K~N3xhS*t[2=0ͼԊ=E;"HVPY 4l8W)քХpY"(5.Y,ϴt@) oӦnaH+8D,K؝NN׼UU¢B#d햱s(?PaIPXUE6EaKy tQ [!dAw(4-m@]l [0Bf/V/k[9"cDVԔ c">i mdc[CP.3bMGm U+]ZvAIC 5dn:Pm`FFgoW:9*5%*u3,Zt>p7 yU i%c;S-pVB[E|6#Z-g*: V*%`jvdQ3;6%^DQ.wdh5@EFM@A/s/{+`Tv+59ó^(\XT{;ɝFI݀HjU!#N*{es *UqcK{xX㈿ӊ~@1r&T`:N A}uc̃7mK^/?EhqjWhWD<:wH5&)`T*2 `05nt[;LMY-Z^$D}ԟɞD<'§a NڙXGRECf@*]T*}x,fh1o,T|HPgkbȎk"I2Kudp:g8ct_ƸM(FmѽT%ۈ s1 8g 6>԰ p= ΋1h'2]DmQ W hw((Q)I!\J-QsFۂ_lZРe/xgkjI LHn&R\ Lɣf-_ lo4F^8ۣ;v"$PEv#VCINi hhUhcW >t,h#Z;wY'ydA喱Y%U/R_6(D9qRܖxvXǽRޠrOڤ+hv ڠ{Ak)vE]j($!PY7M&J}Mf&QzS@T~bPHKԛaK@%/+x輵dc).NR/Q gms= gaf6u;ba;ݩWj*F(^Q-6k$(AB&H' LhU0ٝI8A!S/N yHN, MKw#Q7\גWwFq%}i(&R /J"7PuuJm a:J#c: 0VQٟfxꖌ(lФWo2k#F=w J&;5hbaI=PaoG'qNhD'&l8D2sI{gv@Zs5d3N6a?&E} P)€~MY- -^#LEcVlPo*%h΋>NGOiiI*YK=WŤb=r(zP8a\񖊨b>Y"^cL>ۡv@S'9.TU*aՑGg:fOC'bPtM{j\kb*%)'( F CGDUvZ;Vo#(f%RJ^U""Sm(#kdIG,K!X`Ě4G'a#fl4gr"[ڛmhM6+ >`f—iTb`Q+bM@>1$h'Zؘ6 9 M͛û`k r.s7T$4LBUж#tsr&rp^9L8"J G*w}$XJ'>:tBc*:ah c~#oP‰$JY̜؛ѩEȢVY ٴDwpV-`7d)*6o5J`R~RxYZI qɉ­> Sw+|AV)ooP] MP)T>Mj[y-k5@ k2ZsK0ݮ:#'8# GdQsV݇/GG{_{Sc2V[ڃFSE_),ĵS,%bZ !6obmV$T Ĥ{ބM&*!'4ڠdwgz{ chxhANF=xF%94ApJ _Lu9aFx۽{,(R_Ƀ<5<_*WX=8wTem [(Rh{! FÇUލ̃-K1FIDTy2Rn9ɝ0_ }?a o}n~VJfm' k)ڗ5i㪳KTZ< ; D Y!wwK5v*y8OyHw[\Sj;m3::1S{WGKpf";".zݝRģ'Ϫyc@,8~r#E|Ҹ2!pOܨw)O&wMwD ET zՙLY;"#'Uԩ8fK~,me٫t|)~~QRAҼK`$䍼1*BdzϠQ`D_F:qPW9z$+~<\|d*sqC=G3\osΉT%3&ftxn۔{&~s?vri?Y]dF˝Ps)8q h)4MgAhh 6o#ګJ6;;F͓gYQB!j:` 688Xd=;o =Clg_UwuOB6?v{7fvwd)g֟"4wCC4ZJ_$%i :6J{do>Hogþ)ѕfx>ʤo3 "Wjsޞ ZP&(<_r܅t`"Бhe%Mg֭p~P5&+fl֭Pr\F]W#4L B)5K5UO0N ѭ:QSr''}rZ,h~U5Q{n*фŒLJ`:*x:O1ΐ 'jWZ%`QG@S'1 I#Boy6pIcL;<ĉG z*|2HN凪U~Q*i XkԄZV4)&{#Y"D(DěVe.,z#q4*\:i(Z-hYSrj_A9L R"Q (f=ZtIkAY,l|q!SR#ZnUh!4֪`[ M?eڎ{lto=P(A[[;`7CpvlSE^K[N.S{,4 ёR9Pept~^c[ %޳+e9`;YF~TXvyikut1%Bp;ȓEtrKrۋ$AEi9h\sA>\Zޘ{gfI>tGO 3{H Nnt@'Qs'=0UXW9}cp;#sv#bCg~ļJn_,- ،L1¡)̮ǧ| h#7w8:B? QOYXL Qj&Q3@p|N(C tGc'[%=I)9{h/t;ޥ"F& TBN/=w>SjU4>{Yo' ibaRy9+6StYo4'fÓqch΃}vƈ 6p  \`+ZqQFzEL W!3TFW!3Q\~2 iIM۸ƞ(!,`iT͉拉F&RUa!#B?>yOɉ3)$\u?;(dk4aDIcV۽ =tP;+YuG~Wɍ :5C]1xUs yU4nE"7ID$PYY+'F; şr392Dv%bY tٿP9ɈeNe31$ZgK` zDڳ3BcFIt:r_<"DFrH0썠,REs1mwylVrh)y\?$ 3!魾sz(@Sԑi[56d#0oI&٢,ؑGRIt@)L?6̉8b/)nZg l6Zl{ͨ䈎сՒ p OiLR&rkA-| A00k)q+ZLp_*-by2$_8VER^VvղqkҺcdė1ŀۢung@8Y,DRld).evJ0> "WG0Aҳ8B6|fU N4fEUō=v-ӶzR{mK4TaS \{Ov|$PTXS:uIVVjդJR۹zș/I6AM\J"!n4iE8@+Ѕ|2lyrF?{ŴhIf#,V'.B+^2J~gʶ}t-q{{azM_R'iÛ:B,77C~(5~JFQC!YpuY#M$ԕ F).^Cmq}e'$꽫Ghń2bk,9df0SGKq~'b<),IoL=d5ΐ ~:;?Nt U̴f14̢0Pި Ĕ@p:4kO--G,]R c*R(,lP; ٞul N+Ha8|A Em oYF?5J5ZP]4NXDm.gkm" ?Jˮlz;(Fǚ PƲ(p;BVv%v, o6 9%x'?U|}Ɛa$JrbrgAT 7'(׊'HGl /%/b>ȕ#iRҩE\"q偶FpvQFUuU7x`j6 Of[isϾѕꙡ;+LAM$Jߗ-߻"z,9?_Zx[~\yh#ipĽTV<@UWnb%1V0ׅ_J')3y=lcݚwS:>fG}stIn-՛zd>R$<c@uj8@Y;T8' _Kò s+j)QIC]f 蜊U bUy//1Srz֜'6}UH޵(EȥOFg}N9#/8jQl HT5Q uz5n1W/;q&UE!*U͠yo{+$KL 䉏oebPa}ks,{j f%ȑ[=}ŎvT۠N*8B!Ϟ N'}v2KIWX[ȅ? Wj-Ga^![$+A2vaO#\Ʋ2+I f&UVbufh{U~άfL}T|6kiǑ |k.]6ʉm|lke]Ub͡%ɞB^B~&BIucThĶk^&JS19&NN>)'/(!jJhB1 t Klt+ ?/L=TT]~P y;;,Xw .gCP U,bȪ1z'1@؊TзF L4išo0H RCB bF%tQ?epFG[w]aN\V'S[@k_M5)XF0e'W3)$tf`=#aW)„~W|A[Zji&nm{G:maFZ4!eԇyh:DŽjvٻ? \wF46J1{ltc!]!l 7^mlo3XaS<DANb>[({ ]V5$~X*}DKTN*+Zt-H L~*G=59MB*)m = w`ݎAr_=CHw;]}H*R#|j!A- I[;$yⲤo.I9@e?EY=Q`bK:U9y$X!Qۢd@1L b?_BK L0xINMmAW_GIuVRjb@UށT)ܯ["ucy2y(:9do|]blFH^Ki 'MęgUNZ&e#]q$ e{XEb̜D9Om*e*; z)i/;'.'-ĥ'Şd[B=? Z4]rGb.4ꢧ2&=:.uTɞ* wLl"P̩y:{-47қj@D,ajh8刼c^y8CXgXtZB. -F;ԭ9Q#Y;=wvsq>~G♷p?KLYx+ZBj6JJj74MzxokBpL"tu|?+%Z< NfsE3/lV;S>z[BITRR/8$ X}q×p]/蝓Xo3 1DG(clB)pC.wJyKBЁSdJu~|#tP*KҒ$L*Hdc,XJ1kSb5qHqDOnzOtvxMlrciGObW-Q|l 蒺 ֺT$:IDݾݕ*rB[)uHtb%Өքtx]Z""?eus y-. |RFUTb(!]#~_h*y![&~6Js0ΖN 9Yvt%YUJd@'}fٚEUc>6'O/U2JթMJ]#:wunO'gPʣ~졡HP1T%C- ^EM4B;"&lǠӲV[ئO4#cj< qTimwm18kkwK+kͬ{ԃPclJ}oQ2 sHR u!I$ w&Ms4clOS 'C~ V7X5_ [G{~kJy dPe*2IZBRce _Ձ$]g#UɓS̙6)_ ٔB}Jg@#\/k^|EqC4pfΉo%N$"GP [oJM)vƬ*I%#9x&>?b<Ů]x8H*p$wVE?+2#ES?z7|e&~ڏp:|"`C.=+u1*Q&Gz"̳=;JmoťB6}h 89]{=j$4t(o֞8*RP7'2 8YuR@ ͛O =>xDĕW4Qs*ӪZ!L?Xg4MkvD?}eof͏\G-G Nklh= LxwKjQ;;2x˷W"Q~-B]qN;ňȩo}u^keB(dPO] NWI$sM%Yaa)0䈚)ptuҙy|4|3Cn?#Cr =AeH-j ojMA`bX'ȒƢ59Jwjˣ4m) T+6#Y KkuM ^ r$z\if6P-bO7Q$,G0,<{FT^DrFuEL"bJR|:fFgsC%,5&4t,Im_(\v^2.icTj0sВnruߎ)h`+8.J9dsWjP_ͩ"Ⲯe˶w-yYGɡT[qP+4S/D@H6)KM|$_7g&&}gS ^ 3`#hJלԓA'){[\'zșJPѰ<2+7:GԿ]g&ḫrxuLvYNu$wZw@q=u4 8ҩ։Ch7>[<-p>Q D5-[~˸p[[Dpo[DK;#MFd$Gz~K :oNFȅRu$M@ Z?҂wSEmAQ\@.CJ@ϔωmA(xƐ91(Ȇ(Qh. U 4#&ZNB6Eʂ^|%'HxOȆg+Ȥƞ't6^oυp{tU,G.4ꈲj䄸Q!Z$ dn껅T̈[egNDJ Y}8Q?u._۠ퟥlZB/\J"؟R$k~JG6ĥVO?s"9{ΰKoR(&{P{Ob S"kMX̱IԾ"B!ډnNEB_š2lg"M|{|E ~0A0k;DCuѕ _'帷HϾAkJk#Tꢇ>шq!C 69m~F9-,~N~%\9 <3h^OP/( ț]u;ѸĦE(Y 0Q>?׼"_{բ>?]D|`;AfdNf[@};dqD0j븍yw,ZtcNso~ZZ  lU3ћW뉟O3E֛IS#$8Ax]J9wwVPsUl6D‘OX0[D=*(kzUٕ1o׎qJi!)5du÷5RtDY^~j8yՊԕ>?y-uxذRl-mO_ߪDO&ƽUw8YbMU{o䮐R&:oO0!Yu_@iqb'KoR_TTXg*F頛=YE0(إl^:@QY #!'˽ݑκV/-  '38r/n!36~zIܤs2֗lZmq5ɓG'OzVs۶+;AB݋:27xV%3λ t[Š]if0ZTdߥ*-Vlmljjm \ Ejc%GӶ.2CȀDXͶ]g{vgm#52nw4GEmI<_ٶMNA^ԃ9%{sjvxw S=X$jJEĚP#~_ m#P 6O @W vQ[j(XO^&mZzoM (*lܸͥ&N'/^VG+:;Μ@)ޑ}`%A|j< E[wzsM?ƩA'hg!ۨ-XKjX9hnL 4Qu֬ˢ`tԙ4foGER: 8GSr@:P ua_iZ{R$w@\T_%t&F9/=ӂ`t+KXEk,Ѡd*Rc> p r,1d%c%qFgY1Q' dhP%HQoz9@:vV S#'VmU8j dA;IJli>f*/RŽ#@CT^S$8E1īrО> b3&Pfw"H3!y$) 1YD늊c ޜ=^ xw,)'uVml~4'rڽs$/'X''Zgi~zZX^Ev/֝(vX@|hMicY0D@)rzb:mivu&98 V'0CFo,4죉6Ya`f4ڻ _G,(IAiOP@OųǐeR[j/$sm-J6cfz!12ȸVg,UIھ!+7RE%sN? Fu'}]G=s\$b/Ks&G1:k>;62J+ ˷7j{A0ȱBGxEN^ 5\NJLpRN,s{6Ek2VQT]Ѩ+]Y[3UMq9e%"GNξl둏 ,}%<> AgD(/BQ/(-tM,amG.iSQ-: mZ-"MVg~KV|&:'o&a#9- J?cje 2 `CG=ռ(Clo7 3j83i ~femK:~Bq7 DB,4P \бo P *'>1yGu휜f78dЎbd׈8EO>AnD( 9<$-$Ey~^X۳Hmߚh:_$y4bs6ūF!I Zϲayax p~#L}''&%v) g[:D:w!VjfDM@?_ %19s9GF y~p%φ:=YAPw!rkͩt7+z^Lׇ/1 s(B$@njW`AP#̛Zֺ}.A#KGbNyy&wҾuΊkҰ=V3J:Ҩx.)6ޡ3wTOO@}Åa1Ef$eOD-giBpO6\fW|FU'Ƿ]|^_;qt*VrJol? +(wwOU,Bn[v0İȋ`S— J:dLS1]b|b\Eo;,MI'e;z f]_5&>S[6 b tw<( ZU '9#:WZҪ@[:E2fɉ4\M.r~Hȧy{ܵC~!.{11})(?P.{10})(.*)\\n\\+(.*)\\n(.*)\\n", "read2": "(?P@.*) .*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read3": "(?P@.*) .*\\n(?P.*)\\n\\+(.*)\\n\\+(.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/qiagen_smallRNA_umi-transform.json000066400000000000000000000001711415626112400257670ustar00rootroot00000000000000{ "read1": "(?P@.*) .*\\n(?P.*AACTGTAGGCACCATCAAT(?P.{12})AGATCGGAA(.*))\\n\\+(.*)\\n(?P.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/qiaseq-upx-384-cb1.txt.gz000066400000000000000000000027051415626112400234550ustar00rootroot00000000000000V^qiaseq-upx-384-cb1.txt5ۍ 1 ,btm1}oTO׹|̓~̭> y0ϨNU?g܁={Avo1ss3 ae&?KlfuLY'ߜSb]D,]`'\*Nh$CV B@q5| `n$l'b |ǃuvv;-Sѓ % \6 sv rr]$k9I 9UVsE20o>@*6y N$)-Av9dR@j$ M-gtzy?N":"$4&I  %U Lb@s$*7m!մSNXlL./l+ql $& |;$0LI՝M&ɡEast.Ĺ@h $m8z&KJ~HTn[(1YWj9g6)D(|}4pa0"YUqYEP|^'$jѰ@u$|Eɡ RXZ4_ewW{y2 D̠bZG4Jh%WwI{WiEs &CK "*c^oB z-m[%$ե̀ )#ME%ا%Cȓ1,$mms .m, ȥ&3aLZCwViTnF笁P5AE9C-3C0>B, s,0www,R,L0Bg)ıF9mx2bz]pG"ZmBEs0[T;RF 8P!cMŘiX]2*E+҅.Trj<`U!<`^@?m АHH$A]j2d.bؐP䂙tuǎse F䗩p* ݷj8Nh*$V,c !L$+1KCW&2D'/hK,U4 DvE`P#p/PF瓠;.n+)bcbio-nextgen-1.2.9/bcbio/data/umis/qiaseq-upx-384-transform.json000066400000000000000000000002471415626112400245350ustar00rootroot00000000000000{ "read1": "(?P[^\\s]+).*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(.*)\\n(.*CAGAGT).{2}(?P.{10})(?P.{12})ACG.*\\n(.*)\\n(.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/qiaseq-upx-96-cb1.txt.gz000066400000000000000000000006501415626112400233720ustar00rootroot00000000000000y^qiaseq-upx-96-cb1.txt- 0txגqteB/{fog.y\D0}DF{ݛe÷dH9~%#kvD8$ ڈŌɨ`-vDBYpg{)qG Qx.,eK:(rXXE@\Rr{Q6na[~u{Lߠ۩׊=;Z9#gRDJ) kBpy({l[^\\s]+).*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(.*)\\n(.*CAGAGT).{2}(?P.{10})(?P.{12})ACG.*\\n(.*)\\n(.*)\\n" } bcbio-nextgen-1.2.9/bcbio/data/umis/surecell-cb1.txt.gz000066400000000000000000000004401415626112400226540ustar00rootroot00000000000000djYsurecell-cb1.txt! zʥTz &̛Ɋ4 nSІe-8"dD [ i=aP$[[kHpG3vJ@C%Y(HpPPAP:9hfL+{g aIgX KIKtx0 T ;d .{6})TAGCCATCGCATTGC(?P.{6})TACCTCTGAGCTGAA(?P.{6})ACG(?P.{8})GAC(.*)\\n\\+(.*)\\n(.*)\\n", "read2": "(?P@.*) .*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n" } bcbio-nextgen-1.2.9/bcbio/distributed/000077500000000000000000000000001415626112400176515ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/distributed/__init__.py000066400000000000000000000001141415626112400217560ustar00rootroot00000000000000"""Handle distributing processing functionality over multiple machines. """ bcbio-nextgen-1.2.9/bcbio/distributed/clargs.py000066400000000000000000000023361415626112400215020ustar00rootroot00000000000000"""Parsing of command line arguments into parallel inputs. """ def to_parallel(args, module="bcbio.distributed"): """Convert input arguments into a parallel dictionary for passing to processing. """ ptype, cores = _get_cores_and_type(args.numcores, getattr(args, "paralleltype", None), args.scheduler) local_controller = getattr(args, "local_controller", False) parallel = {"type": ptype, "cores": cores, "scheduler": args.scheduler, "queue": args.queue, "tag": args.tag, "module": module, "resources": args.resources, "timeout": args.timeout, "retries": args.retries, "run_local": args.queue == "localrun", "local_controller": local_controller} return parallel def _get_cores_and_type(numcores, paralleltype, scheduler): """Return core and parallelization approach from command line providing sane defaults. """ if scheduler is not None: paralleltype = "ipython" if paralleltype is None: paralleltype = "local" if not numcores or int(numcores) < 1: numcores = 1 return paralleltype, int(numcores) bcbio-nextgen-1.2.9/bcbio/distributed/clusterk.py000066400000000000000000000023431415626112400220610ustar00rootroot00000000000000"""Distributed execution on AWS spot instances using Clusterk. http://www.clusterk.com/ https://clusterk.atlassian.net/wiki/display/DOC/Public+Documentation """ import contextlib from bcbio.log import logger @contextlib.contextmanager def create(parallel): """Create a queue based on the provided parallel arguments. TODO Startup/tear-down. Currently using default queue for testing """ queue = {k: v for k, v in parallel.items() if k in ["queue", "cores_per_job", "mem"]} yield queue def runner(queue, parallel): """Run individual jobs on an existing queue. """ def run(fn_name, items): logger.info("clusterk: %s" % fn_name) assert "wrapper" in parallel, "Clusterk requires bcbio-nextgen-vm wrapper" fn = getattr(__import__("{base}.clusterktasks".format(base=parallel["module"]), fromlist=["clusterktasks"]), parallel["wrapper"]) wrap_parallel = {k: v for k, v in parallel.items() if k in set(["fresources", "pack"])} out = [] for data in [fn(fn_name, queue, parallel.get("wrapper_args"), wrap_parallel, x) for x in items]: if data: out.extend(data) return out return run bcbio-nextgen-1.2.9/bcbio/distributed/ipython.py000066400000000000000000000131161415626112400217170ustar00rootroot00000000000000"""Distributed execution using an IPython cluster. Uses IPython parallel to setup a cluster and manage execution: http://ipython.org/ipython-doc/stable/parallel/index.html Cluster implementation from ipython-cluster-helper: https://github.com/roryk/ipython-cluster-helper """ import collections import math import os import time try: import ipyparallel # msgpack not working with IPython 4.0 ipyparallel msgpack = None except ImportError: try: import msgpack except ImportError: msgpack = None from bcbio import utils, setpath from bcbio.log import logger, get_log_dir from bcbio.pipeline import config_utils from bcbio.provenance import diagnostics from cluster_helper import cluster as ipython_cluster def create(parallel, dirs, config): """Create a cluster based on the provided parallel arguments. Returns an IPython view on the cluster, enabling processing on jobs. Adds a mincores specification if he have machines with a larger number of cores to allow jobs to be batched together for shared memory usage. """ profile_dir = utils.safe_makedir(os.path.join(dirs["work"], get_log_dir(config), "ipython")) has_mincores = any(x.startswith("mincores=") for x in parallel["resources"]) cores = min(_get_common_cores(config["resources"]), parallel["system_cores"]) if cores > 1 and not has_mincores: adj_cores = max(1, int(math.floor(cores * float(parallel.get("mem_pct", 1.0))))) # if we have less scheduled cores than per machine, use the scheduled count if cores > parallel["cores"]: cores = parallel["cores"] # if we have less total cores required for the entire process, use that elif adj_cores > parallel["num_jobs"] * parallel["cores_per_job"]: cores = parallel["num_jobs"] * parallel["cores_per_job"] else: cores = adj_cores cores = per_machine_target_cores(cores, parallel["num_jobs"]) parallel["resources"].append("mincores=%s" % cores) return ipython_cluster.cluster_view(parallel["scheduler"].lower(), parallel["queue"], parallel["num_jobs"], parallel["cores_per_job"], profile=profile_dir, start_wait=parallel["timeout"], extra_params={"resources": parallel["resources"], "mem": parallel["mem"], "tag": parallel.get("tag"), "run_local": parallel.get("run_local"), "local_controller": parallel.get("local_controller")}, retries=parallel.get("retries")) def per_machine_target_cores(cores, num_jobs): """Select target cores on larger machines to leave room for batch script and controller. On resource constrained environments, we want to pack all bcbio submissions onto a specific number of machines. This gives up some cores to enable sharing cores with the controller and batch script on larger machines. """ if cores >= 32 and num_jobs == 1: cores = cores - 2 elif cores >= 16 and num_jobs in [1, 2]: cores = cores - 1 return cores def _get_common_cores(resources): """Retrieve the most common configured number of cores in the input file. """ all_cores = [] for vs in resources.values(): cores = vs.get("cores") if cores: all_cores.append(int(vs["cores"])) return collections.Counter(all_cores).most_common(1)[0][0] def stop(view): try: ipython_cluster.stop_from_view(view) time.sleep(10) except: logger.exception("Did not stop IPython cluster correctly") def _get_ipython_fn(fn_name, parallel): import_fn_name = parallel.get("wrapper", fn_name) return getattr(__import__("{base}.ipythontasks".format(base=parallel["module"]), fromlist=["ipythontasks"]), import_fn_name) def zip_args(args, config=None): """Compress arguments using msgpack. """ if msgpack: return [msgpack.packb(x, use_single_float=True, use_bin_type=True) for x in args] else: return args def unzip_args(args): """Uncompress arguments using msgpack. """ if msgpack: return [msgpack.unpackb(x) for x in args] else: return args def runner(view, parallel, dirs, config): """Run a task on an ipython parallel cluster, allowing alternative queue types. view provides map-style access to an existing Ipython cluster. """ def run(fn_name, items): setpath.prepend_bcbiopath() out = [] fn, fn_name = (fn_name, fn_name.__name__) if callable(fn_name) else (_get_ipython_fn(fn_name, parallel), fn_name) items = [x for x in items if x is not None] items = diagnostics.track_parallel(items, fn_name) logger.info("ipython: %s" % fn_name) if len(items) > 0: items = [config_utils.add_cores_to_config(x, parallel["cores_per_job"], parallel) for x in items] if "wrapper" in parallel: wrap_parallel = {k: v for k, v in parallel.items() if k in set(["fresources"])} items = [[fn_name] + parallel.get("wrapper_args", []) + [wrap_parallel] + list(x) for x in items] items = zip_args([args for args in items]) for data in view.map_sync(fn, items, track=False): if data: out.extend(unzip_args(data)) return out return run bcbio-nextgen-1.2.9/bcbio/distributed/ipythontasks.py000066400000000000000000000467351415626112400230020ustar00rootroot00000000000000"""Ipython parallel ready entry points for parallel execution """ import contextlib import os try: from ipyparallel import require except ImportError: from IPython.parallel import require from bcbio import heterogeneity, hla, chipseq, structural, upload, utils from bcbio.bam import callable from bcbio.rnaseq import (sailfish, rapmap, salmon, umi, kallisto, spikein, bcbiornaseq, featureCounts) from bcbio.distributed import ipython from bcbio.ngsalign import alignprep from bcbio.srna import sample as srna from bcbio.srna import group as seqcluster from bcbio.chipseq import peaks from bcbio.wgbsseq import cpg_caller, deduplication, trimming from bcbio.pipeline import (archive, config_utils, disambiguate, sample, qcsummary, shared, variation, run_info, rnaseq) from bcbio.provenance import system from bcbio.qc import multiqc, qsignature from bcbio.structural import regions from bcbio.variation import (bamprep, genotype, ensemble, joint, multi, population, validate, vcfutils, peddy) from bcbio.log import logger, setup_local_logging @contextlib.contextmanager def _setup_logging(args): # Set environment to standard to use periods for decimals and avoid localization locale_to_use = utils.get_locale() os.environ["LC_ALL"] = locale_to_use os.environ["LC"] = locale_to_use os.environ["LANG"] = locale_to_use config = None if len(args) == 1 and isinstance(args[0], (list, tuple)): args = args[0] for arg in args: if config_utils.is_nested_config_arg(arg): config = arg["config"] break elif config_utils.is_std_config_arg(arg): config = arg break elif isinstance(arg, (list, tuple)) and config_utils.is_nested_config_arg(arg[0]): config = arg[0]["config"] break if config is None: raise NotImplementedError("No config found in arguments: %s" % args[0]) handler = setup_local_logging(config, config.get("parallel", {})) try: yield config except: logger.exception("Unexpected error") raise finally: if hasattr(handler, "close"): handler.close() # Potential wrapper to avoid boilerplate if we can get dill working for closures from functools import wraps def _pack_n_log(f): from bcbio.distributed import ipython @wraps(f) def wrapper(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(fn(*args)) return wrapper def apply(object, args=None, kwargs=None): """Python3 apply replacement for double unpacking of inputs during apply. Thanks to: https://github.com/stefanholek/apply """ if args is None: args = () if kwargs is None: kwargs = {} return object(*args, **kwargs) require(sample) def prepare_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.prepare_sample, *args)) @require(sample) def prepare_bcbio_samples(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.prepare_bcbio_samples, *args)) @require(sample) def trim_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.trim_sample, *args)) @require(srna) def trim_srna_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(srna.trim_srna_sample, *args)) @require(trimming) def trim_bs_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(trimming.trim, *args)) @require(srna) def srna_annotation(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(srna.sample_annotation, *args)) @require(seqcluster) def seqcluster_prepare(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(seqcluster.run_prepare, *args)) @require(seqcluster) def seqcluster_cluster(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(seqcluster.run_cluster, *args)) @require(seqcluster) def srna_alignment(* args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(seqcluster.run_align, *args)) @require(peaks) def peakcalling(* args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(peaks.calling, *args)) @require(cpg_caller) def cpg_calling(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(cpg_caller.calling, *args)) @require(cpg_caller) def cpg_processing(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(cpg_caller.cpg_postprocessing, *args)) @require(cpg_caller) def cpg_stats(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(cpg_caller.cpg_stats, *args)) @require(deduplication) def deduplicate_bismark(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(deduplication.dedup_bismark, *args)) @require(sailfish) def run_sailfish(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(sailfish.run_sailfish, *args)) @require(kallisto) def run_kallisto_rnaseq(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(kallisto.run_kallisto_rnaseq, *args)) @require(spikein) def run_counts_spikein(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(spikein.run_counts_spikein, *args)) @require(sailfish) def run_sailfish_index(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(sailfish.run_sailfish_index, *args)) @require(rapmap) def run_rapmap_align(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(rapmap.run_rapmap_align, *args)) @require(umi) def run_umi_transform(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(umi.umi_transform, *args)) @require(umi) def demultiplex_samples(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(umi.demultiplex_samples, *args)) @require(umi) def run_filter_barcodes(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(umi.filter_barcodes, *args)) @require(peddy) def run_peddy(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(peddy.run_peddy, *args)) @require(featureCounts) def run_chipseq_count(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(featureCounts.chipseq_count, *args)) @require(umi) def run_tagcount(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(umi.tagcount, *args)) @require(umi) def run_concatenate_sparse_counts(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(umi.concatenate_sparse_counts, *args)) @require(umi) def run_barcode_histogram(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(umi.barcode_histogram, *args)) @require(kallisto) def run_kallisto_index(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(kallisto.run_kallisto_index, *args)) @require(kallisto) def run_kallisto_singlecell(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(kallisto.run_kallisto_singlecell, *args)) @require(salmon) def run_salmon_bam(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(salmon.run_salmon_bam, *args)) @require(salmon) def run_salmon_decoy(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(salmon.run_salmon_decoy, *args)) @require(salmon) def run_salmon_reads(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(salmon.run_salmon_reads, *args)) @require(salmon) def run_salmon_index(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(salmon.run_salmon_index, *args)) @require(rapmap) def run_rapmap_index(*args): args = ipython.unzip_args(args) with _setup_logging(args): return ipython.zip_args(apply(rapmap.run_rapmap_index, *args)) @require(sample) def process_alignment(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.process_alignment, *args)) @require(alignprep) def prep_align_inputs(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(alignprep.create_inputs, *args)) @require(sample) def postprocess_alignment(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.postprocess_alignment, *args)) @require(sample) def prep_samples(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.prep_samples, *args)) @require(sample) def merge_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.merge_sample, *args)) @require(sample) def delayed_bam_merge(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.delayed_bam_merge, *args)) @require(sample) def merge_split_alignments(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.merge_split_alignments, *args)) @require(sample) def recalibrate_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(sample.recalibrate_sample, *args)) @require(multi) def split_variants_by_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(multi.split_variants_by_sample, *args)) @require(bamprep) def piped_bamprep(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(bamprep.piped_bamprep, *args)) @require(variation) def postprocess_variants(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(variation.postprocess_variants, *args)) @require(qcsummary) def pipeline_summary(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(qcsummary.pipeline_summary, *args)) @require(qsignature) def qsignature_summary(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(qsignature.summary, *args)) @require(multiqc) def multiqc_summary(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(multiqc.summary, *args)) @require(rnaseq) def generate_transcript_counts(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.generate_transcript_counts, *args)) @require(rnaseq) def detect_fusions(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.detect_fusions, *args)) @require(rnaseq) def run_cufflinks(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.run_cufflinks, *args)) @require(rnaseq) def run_stringtie_expression(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.run_stringtie_expression, *args)) @require(rnaseq) def run_rnaseq_variant_calling(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.run_rnaseq_variant_calling, *args)) @require(rnaseq) def run_rnaseq_ann_filter(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.run_rnaseq_ann_filter, *args)) @require(rnaseq) def run_express(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.run_express, *args)) @require(rnaseq) def run_dexseq(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.run_dexseq, *args)) @require(shared) def combine_bam(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(shared.combine_bam, *args)) @require(callable) def combine_sample_regions(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(callable.combine_sample_regions, *args)) @require(genotype) def variantcall_sample(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(genotype.variantcall_sample, *args)) @require(vcfutils) def combine_variant_files(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(vcfutils.combine_variant_files, *args)) @require(vcfutils) def concat_variant_files(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(vcfutils.concat_variant_files, *args)) @require(vcfutils) def merge_variant_files(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(vcfutils.merge_variant_files, *args)) @require(population) def prep_gemini_db(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(population.prep_gemini_db, *args)) @require(hla) def call_hla(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(hla.call_hla, *args)) @require(regions) def calculate_sv_bins(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(regions.calculate_sv_bins, *args)) @require(regions) def calculate_sv_coverage(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(regions.calculate_sv_coverage, *args)) @require(regions) def normalize_sv_coverage(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(regions.normalize_sv_coverage, *args)) @require(structural) def detect_sv(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(structural.detect_sv, *args)) @require(structural) def validate_sv(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(structural.validate_sv, *args)) @require(structural) def finalize_sv(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(structural.finalize_sv, *args)) @require(heterogeneity) def heterogeneity_estimate(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(heterogeneity.estimate, *args)) @require(ensemble) def combine_calls(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(ensemble.combine_calls, *args)) @require(validate) def compare_to_rm(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(validate.compare_to_rm, *args)) @require(disambiguate) def run_disambiguate(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(disambiguate.run, *args)) @require(disambiguate) def disambiguate_split(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(disambiguate.split, *args)) @require(disambiguate) def disambiguate_merge_extras(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(disambiguate.merge_extras, *args)) @require(system) def machine_info(*args): args = ipython.unzip_args(args) return ipython.zip_args(system.machine_info()) @require(chipseq) def clean_chipseq_alignment(*args): args = ipython.unzip_args(args) return ipython.zip_args(apply(chipseq.clean_chipseq_alignment, *args)) @require(archive) def archive_to_cram(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(archive.to_cram, *args)) @require(joint) def square_batch_region(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(joint.square_batch_region, *args)) @require(rnaseq) def cufflinks_assemble(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.cufflinks_assemble, *args)) @require(rnaseq) def cufflinks_merge(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.cufflinks_merge, *args)) @require(rnaseq) def stringtie_merge(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(rnaseq.stringtie_merge, *args)) @require(run_info) def organize_samples(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(run_info.organize, *args)) @require(run_info) def prep_system(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(run_info.prep_system, *args)) @require(upload) def upload_samples(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(upload.from_sample, *args)) @require(upload) def upload_samples_project(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(upload.project_from_sample, *args)) @require(bcbiornaseq) def run_bcbiornaseqload(*args): args = ipython.unzip_args(args) with _setup_logging(args) as config: return ipython.zip_args(apply(bcbiornaseq.make_bcbiornaseq_object, *args)) bcbio-nextgen-1.2.9/bcbio/distributed/multi.py000066400000000000000000000072611415626112400213630ustar00rootroot00000000000000"""Run tasks in parallel on a single machine using multiple cores. """ import functools try: import joblib except ImportError: joblib = False from bcbio.distributed import resources from bcbio.log import logger, setup_local_logging from bcbio.pipeline import config_utils from bcbio.provenance import diagnostics, system def runner(parallel, config): """Run functions, provided by string name, on multiple cores on the current machine. """ def run_parallel(fn_name, items): items = [x for x in items if x is not None] if len(items) == 0: return [] items = diagnostics.track_parallel(items, fn_name) fn, fn_name = (fn_name, fn_name.__name__) if callable(fn_name) else (get_fn(fn_name, parallel), fn_name) logger.info("multiprocessing: %s" % fn_name) if "wrapper" in parallel: wrap_parallel = {k: v for k, v in parallel.items() if k in set(["fresources", "checkpointed"])} items = [[fn_name] + parallel.get("wrapper_args", []) + [wrap_parallel] + list(x) for x in items] return run_multicore(fn, items, config, parallel=parallel) return run_parallel def get_fn(fn_name, parallel): taskmod = "multitasks" imodule = parallel.get("module", "bcbio.distributed") import_fn_name = parallel.get("wrapper", fn_name) return getattr(__import__("{base}.{taskmod}".format(base=imodule, taskmod=taskmod), fromlist=[taskmod]), import_fn_name) def zeromq_aware_logging(f): """Ensure multiprocessing logging uses ZeroMQ queues. ZeroMQ and local stdout/stderr do not behave nicely when intertwined. This ensures the local logging uses existing ZeroMQ logging queues. """ @functools.wraps(f) def wrapper(*args, **kwargs): config = None for arg in args: if config_utils.is_std_config_arg(arg): config = arg break elif config_utils.is_nested_config_arg(arg): config = arg["config"] elif isinstance(arg, (list, tuple)) and config_utils.is_nested_config_arg(arg[0]): config = arg[0]["config"] break assert config, "Could not find config dictionary in function arguments." if config.get("parallel", {}).get("log_queue") and not config.get("parallel", {}).get("wrapper"): handler = setup_local_logging(config, config["parallel"]) else: handler = None try: out = f(*args, **kwargs) finally: if handler and hasattr(handler, "close"): handler.close() return out return wrapper def run_multicore(fn, items, config, parallel=None): """Run the function using multiple cores on the given items to process. """ if len(items) == 0: return [] if parallel is None or "num_jobs" not in parallel: if parallel is None: parallel = {"type": "local", "cores": config["algorithm"].get("num_cores", 1)} sysinfo = system.get_info({}, parallel) parallel = resources.calculate(parallel, items, sysinfo, config, parallel.get("multiplier", 1), max_multicore=int(parallel.get("max_multicore", sysinfo["cores"]))) items = [config_utils.add_cores_to_config(x, parallel["cores_per_job"]) for x in items] if joblib is None: raise ImportError("Need joblib for multiprocessing parallelization") out = [] for data in joblib.Parallel(parallel["num_jobs"], batch_size=1, backend="multiprocessing")(joblib.delayed(fn)(*x) for x in items): if data: out.extend(data) return out bcbio-nextgen-1.2.9/bcbio/distributed/multitasks.py000066400000000000000000000273141415626112400224320ustar00rootroot00000000000000"""Multiprocessing ready entry points for sample analysis. """ from bcbio import heterogeneity, hla, structural, utils, chipseq, upload from bcbio.bam import callable from bcbio.srna import sample as srna from bcbio.srna import group as seqcluster from bcbio.chipseq import peaks from bcbio.wgbsseq import cpg_caller, deduplication, trimming from bcbio.cwl import create as cwl_create from bcbio.cwl import cwlutils from bcbio.rnaseq import (sailfish, rapmap, salmon, umi, kallisto, spikein, bcbiornaseq, featureCounts) from bcbio.ngsalign import alignprep from bcbio.pipeline import (archive, alignment, disambiguate, qcsummary, region, sample, main, shared, variation, run_info, rnaseq) from bcbio.qc import multiqc, qsignature from bcbio.structural import regions as svregions from bcbio.variation import (bamprep, genotype, ensemble, joint, multi, population, validate, vcfutils, peddy) @utils.map_wrap def run_peddy(*args): return peddy.run_peddy(*args) @utils.map_wrap def run_tagcount(*args): return umi.tagcount(*args) @utils.map_wrap def run_chipseq_count(*args): return featureCounts.chipseq_count(*args) @utils.map_wrap def run_concatenate_sparse_counts(*args): return umi.concatenate_sparse_counts(*args) @utils.map_wrap def run_filter_barcodes(*args): return umi.filter_barcodes(*args) @utils.map_wrap def run_barcode_histogram(*args): return umi.barcode_histogram(*args) @utils.map_wrap def run_umi_transform(*args): return umi.umi_transform(*args) @utils.map_wrap def demultiplex_samples(*args): return umi.demultiplex_samples(*args) @utils.map_wrap def run_kallisto_singlecell(*args): return kallisto.run_kallisto_singlecell(*args) @utils.map_wrap def run_kallisto_index(*args): return kallisto.run_kallisto_index(*args) @utils.map_wrap def run_kallisto_rnaseq(*args): return kallisto.run_kallisto_rnaseq(*args) @utils.map_wrap def run_salmon_decoy(*args): return salmon.run_salmon_decoy(*args) @utils.map_wrap def run_salmon_reads(*args): return salmon.run_salmon_reads(*args) @utils.map_wrap def run_salmon_bam(*args): return salmon.run_salmon_bam(*args) @utils.map_wrap def run_salmon_index(*args): return salmon.run_salmon_index(*args) @utils.map_wrap def run_rapmap_index(*args): return rapmap.run_rapmap_index(*args) @utils.map_wrap def run_counts_spikein(*args): return spikein.run_counts_spikein(*args) @utils.map_wrap def run_bcbiornaseqload(*args): return bcbiornaseq.make_bcbiornaseq_object(*args) @utils.map_wrap def run_sailfish(*args): return sailfish.run_sailfish(*args) @utils.map_wrap def run_sailfish_index(*args): return sailfish.run_sailfish_index(*args) @utils.map_wrap def run_rapmap_align(*args): return rapmap.run_rapmap_align(*args) @utils.map_wrap def prepare_sample(*args): return sample.prepare_sample(*args) @utils.map_wrap def prepare_bcbio_samples(*args): return sample.prepare_bcbio_samples(*args) @utils.map_wrap def trim_sample(*args): return sample.trim_sample(*args) @utils.map_wrap def trim_srna_sample(*args): return srna.trim_srna_sample(*args) @utils.map_wrap def process_alignment_to_rec(*args): return cwlutils.to_rec(*args) @utils.map_wrap def process_alignment(*args): return sample.process_alignment(*args) @utils.map_wrap def alignment_to_rec(*args): default_keys = ["config__algorithm__align_split_size", "config__algorithm__aligner", "config__algorithm__mark_duplicates", "reference__bwa__indexes", "reference__snap__indexes", "reference__bowtie2__indexes", "reference__novoalign__indexes", "rgnames__pl", "rgnames__sample", "rgnames__pu", "rgnames__lane", "rgnames__rg", "rgnames__lb"] return cwlutils.to_rec_single(*args, default_keys=default_keys) @utils.map_wrap def organize_noalign(*args): return alignment.organize_noalign(args) @utils.map_wrap def postprocess_alignment_to_rec(*args): default_keys = ["config__algorithm__coverage_interval", "config__algorithm__seq2c_bed_ready", "config__algorithm__coverage", "config__algorithm__coverage_merged", "config__algorithm__coverage_orig", "config__algorithm__variant_regions", "config__algorithm__variant_regions_merged", "config__algorithm__variant_regions_orig"] return cwlutils.to_rec(*args, default_keys=default_keys) @utils.map_wrap def postprocess_alignment(*args): return sample.postprocess_alignment(*args) @utils.map_wrap def prep_samples(*args): return sample.prep_samples(*args) @utils.map_wrap def prep_samples_to_rec(*args): return cwlutils.to_rec(*args) @utils.map_wrap def srna_annotation(*args): return srna.sample_annotation(*args) @utils.map_wrap def seqcluster_prepare(*args): return seqcluster.run_prepare(*args) @utils.map_wrap def seqcluster_cluster(*args): return seqcluster.run_cluster(*args) @utils.map_wrap def srna_alignment(*args): return seqcluster.run_align(*args) @utils.map_wrap def peakcalling(*args): return peaks.calling(*args) @utils.map_wrap def trim_bs_sample(*args): return trimming.trim(*args) @utils.map_wrap def cpg_calling(*args): return cpg_caller.calling(*args) @utils.map_wrap def cpg_processing(*args): return cpg_caller.cpg_postprocessing(*args) @utils.map_wrap def cpg_stats(*args): return cpg_caller.cpg_stats(*args) @utils.map_wrap def deduplicate_bismark(*args): return deduplication.dedup_bismark(*args) @utils.map_wrap def prep_align_inputs(*args): return alignprep.create_inputs(*args) @utils.map_wrap def merge_sample(*args): return sample.merge_sample(*args) @utils.map_wrap def delayed_bam_merge(*args): return sample.delayed_bam_merge(*args) @utils.map_wrap def merge_split_alignments(*args): return sample.merge_split_alignments(*args) @utils.map_wrap def piped_bamprep(*args): return bamprep.piped_bamprep(*args) @utils.map_wrap def split_variants_by_sample(*args): return multi.split_variants_by_sample(*args) @utils.map_wrap def postprocess_variants(*args): return variation.postprocess_variants(*args) @utils.map_wrap def pipeline_summary(*args): return qcsummary.pipeline_summary(*args) @utils.map_wrap def qc_to_rec(*args): return qcsummary.qc_to_rec(*args) @utils.map_wrap def qsignature_summary(*args): return qsignature.summary(*args) @utils.map_wrap def multiqc_summary(*args): return multiqc.summary(*args) @utils.map_wrap def generate_transcript_counts(*args): return rnaseq.generate_transcript_counts(*args) @utils.map_wrap def detect_fusions(*args): return rnaseq.detect_fusions(*args) @utils.map_wrap def rnaseq_quantitate(*args): return rnaseq.quantitate(*args) @utils.map_wrap def run_cufflinks(*args): return rnaseq.run_cufflinks(*args) @utils.map_wrap def run_stringtie_expression(*args): return rnaseq.run_stringtie_expression(*args) @utils.map_wrap def run_express(*args): return rnaseq.run_express(*args) @utils.map_wrap def run_dexseq(*args): return rnaseq.run_dexseq(*args) @utils.map_wrap def run_rnaseq_variant_calling(*args): return rnaseq.run_rnaseq_variant_calling(*args) @utils.map_wrap def run_rnaseq_ann_filter(*args): return rnaseq.run_rnaseq_ann_filter(*args) @utils.map_wrap def combine_bam(*args): return shared.combine_bam(*args) @utils.map_wrap def batch_for_variantcall(*args): return genotype.batch_for_variantcall(*args) @utils.map_wrap def vc_output_record(*args): return genotype.vc_output_record(*args) @utils.map_wrap def variantcall_batch_region(*args): return genotype.variantcall_batch_region(*args) @utils.map_wrap def concat_batch_variantcalls(*args): return genotype.concat_batch_variantcalls(*args) @utils.map_wrap def get_parallel_regions(*args): return region.get_parallel_regions_block(*args) @utils.map_wrap def variantcall_sample(*args): return genotype.variantcall_sample(*args) @utils.map_wrap def combine_variant_files(*args): return vcfutils.combine_variant_files(*args) @utils.map_wrap def concat_variant_files(*args): return vcfutils.concat_variant_files(*args) @utils.map_wrap def merge_variant_files(*args): return vcfutils.merge_variant_files(*args) @utils.map_wrap def hla_to_rec(*args): return cwlutils.to_rec(*args) @utils.map_wrap def call_hla(*args): return hla.call_hla(*args) @utils.map_wrap def calculate_sv_bins(*args): return svregions.calculate_sv_bins(*args) @utils.map_wrap def calculate_sv_coverage(*args): return svregions.calculate_sv_coverage(*args) @utils.map_wrap def normalize_sv_coverage(*args): return svregions.normalize_sv_coverage(*args) @utils.map_wrap def batch_for_sv(*args): return structural.batch_for_sv(*args) @utils.map_wrap def detect_sv(*args): return structural.detect_sv(*args) @utils.map_wrap def summarize_sv(*args): return structural.summarize_sv(*args) @utils.map_wrap def validate_sv(*args): return structural.validate_sv(*args) @utils.map_wrap def heterogeneity_estimate(*args): return heterogeneity.estimate(*args) @utils.map_wrap def finalize_sv(*args): return structural.finalize_sv(*args) @utils.map_wrap def combine_calls(*args): return ensemble.combine_calls(*args) @utils.map_wrap def batch_for_ensemble(*args): return ensemble.batch(*args) @utils.map_wrap def prep_gemini_db(*args): return population.prep_gemini_db(*args) @utils.map_wrap def combine_sample_regions(*args): return callable.combine_sample_regions(*args) @utils.map_wrap def compare_to_rm(*args): return validate.compare_to_rm(*args) @utils.map_wrap def summarize_vc(*args): return variation.summarize_vc(*args) @utils.map_wrap def run_disambiguate(*args): return disambiguate.run(*args) @utils.map_wrap def disambiguate_split(*args): return disambiguate.split(*args) @utils.map_wrap def disambiguate_merge_extras(*args): return disambiguate.merge_extras(*args) @utils.map_wrap def clean_chipseq_alignment(*args): return chipseq.clean_chipseq_alignment(*args) @utils.map_wrap def archive_to_cram(*args): return archive.to_cram(*args) @utils.map_wrap def square_batch_region(*args): return joint.square_batch_region(*args) @utils.map_wrap def batch_for_jointvc(*args): return joint.batch_for_jointvc(*args) @utils.map_wrap def run_jointvc(*args): return joint.run_jointvc(*args) @utils.map_wrap def finalize_jointvc(*args): return joint.finalize_jointvc(*args) @utils.map_wrap def get_parallel_regions_jointvc(*args): return region.get_parallel_regions(*args) @utils.map_wrap def concat_batch_variantcalls_jointvc(*args): return joint.concat_batch_variantcalls_jointvc(*args) @utils.map_wrap def cufflinks_assemble(*args): return rnaseq.cufflinks_assemble(*args) @utils.map_wrap def cufflinks_merge(*args): return rnaseq.cufflinks_merge(*args) @utils.map_wrap def stringtie_merge(*args): return rnaseq.stringtie_merge(*args) @utils.map_wrap def organize_samples(*args): return run_info.organize(*args) @utils.map_wrap def prep_system(*args): return run_info.prep_system(*args) @utils.map_wrap def upload_samples(*args): return upload.from_sample(*args) @utils.map_wrap def upload_samples_project(*args): return upload.project_from_sample(*args) @utils.map_wrap def create_cwl(*args): return cwl_create.from_world(*args) @utils.map_wrap def run_main(*args): work_dir, ready_config_file, systemconfig, fcdir, parallel, samples = args return main.run_main(work_dir, run_info_yaml=ready_config_file, config_file=systemconfig, fc_dir=fcdir, parallel=parallel, samples=samples) bcbio-nextgen-1.2.9/bcbio/distributed/objectstore.py000066400000000000000000000556251415626112400225630ustar00rootroot00000000000000""" Manage pushing and pulling files from an object store like Amazon Web Services S3. """ # pylint: disable=redefined-builtin import abc import collections import os import re import subprocess import sys import time import zlib import six from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio import utils SUPPORTED_REMOTES = ("s3://",) BIODATA_INFO = {"s3": "s3://biodata/prepped/{build}/{build}-{target}.tar.gz"} REGIONS_NEWPERMS = {"s3": ["eu-central-1"]} @six.add_metaclass(abc.ABCMeta) class FileHandle(object): """Contract class for the file handle.""" def __init__(self): self._iter = self._line_iter() def __enter__(self): """Define what the context manager should do at the beginning of the block created by the with statement. """ return self def __exit__(self, *args): """Define what the context manager should do after its block has been executed (or terminates). """ self.close() def __iter__(self): """Return the iterator for the current file.""" return self def _line_iter(self): """Storage manager file iterator splits by buffer size instead of by newline. This wrapper puts them back into lines. From mrjob: https://github.com/Yelp/mrjob/blob/master/mrjob/util.py """ buf = "" search_offset = 0 for chunk in self._chunk_iter(): buf += chunk start = 0 while True: end = buf.find("\n", start + search_offset) + 1 if end: # if find() returned -1, end would be 0 yield buf[start:end] start = end # reset the search offset search_offset = 0 else: # this will happen eventually buf = buf[start:] # set search offset so we do not need to scan this part # of the buffer again search_offset = len(buf) break if buf: yield buf + '\n' @abc.abstractmethod def _chunk_iter(self): """Chunk iterator over the received file.""" pass @abc.abstractmethod def read(self, size=sys.maxsize): """Read at most size bytes from the file (less if the read hits EOF before obtaining size bytes). """ pass @abc.abstractmethod def next(self): """Return the next item from the container.""" pass @abc.abstractmethod def close(self): """Close the file handle.""" pass class S3Handle(FileHandle): """File object for the Amazon S3 files.""" def __init__(self, key): super(S3Handle, self).__init__() self._key = key if self._key.name.endswith(".gz"): decompress = zlib.decompressobj(16 | zlib.MAX_WBITS) self._decompress = decompress.decompress else: self._decompress = lambda value: value def _chunk_iter(self): """Iterator over the S3 file.""" for chunk in self._key: yield self._decompress(chunk) def read(self, size=sys.maxsize): """Read at most size bytes from the file (less if the read hits EOF before obtaining size bytes). """ return self._key.read(size) def next(self): """Return the next item from the container.""" return next(self._iter) def close(self): """Close the file handle.""" self._key.close(fast=True) class BlobHandle(FileHandle): """File object for the Azure Blob files.""" def __init__(self, blob_service, container, blob, chunk_size): super(BlobHandle, self).__init__() self._blob_service = blob_service self._container_name = container self._blob_name = blob self._chunk_size = chunk_size self._blob_properties = {} self._pointer = 0 if blob.endswith(".gz"): decompress = zlib.decompressobj(16 | zlib.MAX_WBITS) self._decompress = decompress.decompress else: self._decompress = lambda value: value @property def blob_properties(self): """Returns all user-defined metadata, standard HTTP properties, and system properties for the blob. """ if not self._blob_properties: self._blob_properties = self._blob_service.get_blob_properties( container_name=self._container_name, blob_name=self._blob_name) return self._blob_properties def _chunk_offsets(self): """Iterator over chunk offests.""" index = 0 blob_size = self.blob_properties.get('content-length') while index < blob_size: yield index index = index + self._chunk_size def _chunk_iter(self): """Iterator over the blob file.""" for chunk_offset in self._chunk_offsets(): yield self._download_chunk(chunk_offset=chunk_offset, chunk_size=self._chunk_size) def _download_chunk_with_retries(self, chunk_offset, chunk_size, retries=3, retry_wait=1): """Reads or downloads the received blob from the system.""" import azure while True: try: chunk = self._download_chunk(chunk_offset, chunk_size) except azure.WindowsAzureError: if retries > 0: retries = retries - 1 time.sleep(retry_wait) else: raise else: return chunk def _download_chunk(self, chunk_offset, chunk_size): """Reads or downloads the received blob from the system.""" range_id = 'bytes={0}-{1}'.format( chunk_offset, chunk_offset + chunk_size - 1) return self._blob_service.get_blob( container_name=self._container_name, blob_name=self._blob_name, x_ms_range=range_id) def read(self, size=sys.maxsize): """Read at most size bytes from the file (less if the read hits EOF before obtaining size bytes). """ blob_size = int(self.blob_properties.get('content-length')) if self._pointer < blob_size: chunk = self._download_chunk_with_retries( chunk_offset=self._pointer, chunk_size=size) self._pointer += size return chunk def next(self): """Return the next item from the container.""" return next(self._iter) def close(self): """Close the file handle.""" pass @six.add_metaclass(abc.ABCMeta) class StorageManager(object): """The contract class for all the storage managers.""" @abc.abstractmethod def check_resource(self, resource): """Check if the received resource can be processed by the current storage manager. """ pass @abc.abstractmethod def parse_remote(self, filename): """Parse a remote filename in order to obtain information related to received resource. """ pass @abc.abstractmethod def connect(self, resource): """Return a connection object pointing to the endpoint associated to the received resource. """ pass @abc.abstractmethod def download(self, filename, input_dir, dl_dir=None): """Download the resource from the storage.""" pass @abc.abstractmethod def list(self, path): """Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order. """ pass @abc.abstractmethod def open(self, filename): """Provide a handle-like object for streaming.""" pass class AmazonS3(StorageManager): """Amazon Simple Storage Service (Amazon S3) Manager.""" _DEFAULT_REGION = "us-east-1" _REMOTE_FILE = collections.namedtuple( "RemoteFile", ["store", "bucket", "key", "region"]) _S3_FILE = "s3://%(bucket)s%(region)s/%(key)s" def __init__(self): super(AmazonS3, self).__init__() @classmethod def parse_remote(cls, filename): """Parses a remote filename into bucket and key information. Handles S3 with optional region name specified in key: BUCKETNAME@REGIONNAME/KEY """ parts = filename.split("//")[-1].split("/", 1) bucket, key = parts if len(parts) == 2 else (parts[0], None) if bucket.find("@") > 0: bucket, region = bucket.split("@") else: region = None return cls._REMOTE_FILE("s3", bucket, key, region) @classmethod def _cl_aws_cli(cls, file_info, region): """Command line required for download using the standard AWS command line interface. """ s3file = cls._S3_FILE % {"bucket": file_info.bucket, "key": file_info.key, "region": ""} command = [os.path.join(os.path.dirname(sys.executable), "aws"), "s3", "cp", "--region", region, s3file] return (command, "awscli") @staticmethod def _cl_gof3r(file_info, region): """Command line required for download using gof3r.""" command = ["gof3r", "get", "--no-md5", "-k", file_info.key, "-b", file_info.bucket] if region != "us-east-1": command += ["--endpoint=s3-%s.amazonaws.com" % region] return (command, "gof3r") @classmethod def _download_cl(cls, filename): """Provide potentially streaming download from S3 using gof3r or the AWS CLI. Selects the correct endpoint for non us-east support: http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region In eu-central-1 gof3r does not support new AWS signatures, so we fall back to the standard AWS commandline interface: https://github.com/rlmcpherson/s3gof3r/issues/45 """ file_info = cls.parse_remote(filename) region = cls.get_region(filename) if region in REGIONS_NEWPERMS["s3"]: return cls._cl_aws_cli(file_info, region) else: return cls._cl_gof3r(file_info, region) @classmethod def get_region(cls, resource=None): """Retrieve region from standard environmental variables or file name. More information of the following link: http://goo.gl/Vb9Jky """ if resource: resource_info = cls.parse_remote(resource) if resource_info.region: return resource_info.region return os.environ.get("AWS_DEFAULT_REGION", cls._DEFAULT_REGION) @classmethod def check_resource(cls, resource): """Check if the received resource can be processed by the current storage manager. """ if resource and resource.startswith("s3://"): return True return False @classmethod def connect(cls, resource): """Connect to this Region's endpoint. Returns a connection object pointing to the endpoint associated to the received resource. """ import boto return boto.s3.connect_to_region(cls.get_region(resource)) @classmethod def download(cls, filename, input_dir, dl_dir=None): """Provide potentially streaming download from S3 using gof3r or the AWS CLI. """ file_info = cls.parse_remote(filename) if not dl_dir: dl_dir = os.path.join(input_dir, file_info.bucket, os.path.dirname(file_info.key)) utils.safe_makedir(dl_dir) out_file = os.path.join(dl_dir, os.path.basename(file_info.key)) if not utils.file_exists(out_file): with file_transaction({}, out_file) as tx_out_file: command, prog = cls._download_cl(filename) if prog == "gof3r": command.extend(["-p", tx_out_file]) elif prog == "awscli": command.extend([tx_out_file]) else: raise NotImplementedError( "Unexpected download program %s" % prog) subprocess.check_call(command) return out_file @classmethod def cl_input(cls, filename, unpack=True, anonpipe=True): """Return command line input for a file, handling streaming remote cases. """ command, prog = cls._download_cl(filename) if prog == "awscli": command.append("-") command = " ".join(command) if filename.endswith(".gz") and unpack: command = "%(command)s | gunzip -c" % {"command": command} elif filename.endswith(".bz2") and unpack: command = "%(command)s | bunzip2 -c" % {"command": command} if anonpipe: command = "<(%(command)s)" % {"command": command} return command @classmethod def list(cls, path): """Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order. """ file_info = cls.parse_remote(path) connection = cls.connect(path) bucket = connection.get_bucket(file_info.bucket) region = "@%s" % file_info.region if file_info.region else "" output = [] for key in bucket.get_all_keys(prefix=file_info.key): output.append(cls._S3_FILE % {"bucket": file_info.bucket, "key": key.name, "region": region}) return output @classmethod def open(cls, filename): """Return a handle like object for streaming from S3.""" import boto file_info = cls.parse_remote(filename) connection = cls.connect(filename) try: s3_bucket = connection.get_bucket(file_info.bucket) except boto.exception.S3ResponseError as error: # if we don't have bucket permissions but folder permissions, # try without validation if error.status == 403: s3_bucket = connection.get_bucket(file_info.bucket, validate=False) else: raise s3_key = s3_bucket.get_key(file_info.key) if s3_key is None: raise ValueError("Did not find S3 key: %s" % filename) return S3Handle(s3_key) class AzureBlob(StorageManager): """Azure Blob storage service manager.""" _BLOB_FILE = ("https://{storage}.blob.core.windows.net/" "{container}/{blob}") _REMOTE_FILE = collections.namedtuple( "RemoteFile", ["store", "storage", "container", "blob"]) _URL_FORMAT = re.compile(r'http.*\/\/(?P[^.]+).blob.core.windows.net\/' r'(?P[^/]+)\/*(?P.*)') _BLOB_CHUNK_DATA_SIZE = 4 * 1024 * 1024 def __init__(self): super(AzureBlob, self).__init__() @classmethod def check_resource(cls, resource): """Check if the received resource can be processed by the current storage manager. """ return cls._URL_FORMAT.match(resource or "") @classmethod def parse_remote(cls, filename): """Parses a remote filename into blob information.""" blob_file = cls._URL_FORMAT.search(filename) return cls._REMOTE_FILE("blob", storage=blob_file.group("storage"), container=blob_file.group("container"), blob=blob_file.group("blob")) @classmethod def connect(cls, resource): """Returns a connection object pointing to the endpoint associated to the received resource. """ from azure import storage as azure_storage file_info = cls.parse_remote(resource) return azure_storage.BlobService(file_info.storage) @classmethod def download(cls, filename, input_dir, dl_dir=None): """Download the resource from the storage.""" file_info = cls.parse_remote(filename) if not dl_dir: dl_dir = os.path.join(input_dir, file_info.container, os.path.dirname(file_info.blob)) utils.safe_makedir(dl_dir) out_file = os.path.join(dl_dir, os.path.basename(file_info.blob)) if not utils.file_exists(out_file): with file_transaction({}, out_file) as tx_out_file: blob_service = cls.connect(filename) blob_service.get_blob_to_path( container_name=file_info.container, blob_name=file_info.blob, file_path=tx_out_file) return out_file @classmethod def list(cls, path): """Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order. """ import azure from azure import storage as azure_storage output = [] path_info = cls.parse_remote(path) blob_service = azure_storage.BlobService(path_info.storage) try: blob_enum = blob_service.list_blobs(path_info.container) except azure.WindowsAzureMissingResourceError: return output for item in blob_enum: output.append(cls._BLOB_FILE.format(storage=path_info.storage, container=path_info.container, blob=item.name)) return output @classmethod def open(cls, filename): """Provide a handle-like object for streaming.""" file_info = cls.parse_remote(filename) blob_service = cls.connect(filename) return BlobHandle(blob_service=blob_service, container=file_info.container, blob=file_info.blob, chunk_size=cls._BLOB_CHUNK_DATA_SIZE) class ArvadosKeep: """Files stored in Arvados Keep. Partial implementation, integration in bcbio-vm. """ @classmethod def check_resource(self, resource): return resource.startswith("keep:") @classmethod def download(self, filename, input_dir, dl_dir=None): return None class SevenBridges: """Files stored in SevenBridges. Partial implementation, integration in bcbio-vm. """ @classmethod def check_resource(self, resource): return resource.startswith("sbg:") @classmethod def download(self, filename, input_dir, dl_dir=None): return None class DNAnexus: """Files stored in DNAnexus. Partial implementation, integration in bcbio-vm. """ @classmethod def check_resource(self, resource): return resource.startswith("dx:") @classmethod def download(self, filename, input_dir, dl_dir=None): return None class GoogleCloud: """Files stored in Google Cloud Storage. Partial implementation, integration in bcbio-vm. """ @classmethod def check_resource(self, resource): return resource.startswith("gs:") @classmethod def download(self, filename, input_dir, dl_dir=None): return None class RegularServer: """Files stored in FTP/http that can be downloaded by wget """ @classmethod def _parse_url(self, fn): regex = re.compile(r'^(?:http|ftp)s?://.*(.fastq.gz)[^/]*|' # http:// or https:// r'^(?:http|ftp)s?://.*(.fastq)[^/]*|' r'^(?:http|ftp)s?://.*(.bam)[^/]*' , re.IGNORECASE) return regex.match(fn) @classmethod def check_resource(self, resource): if self._parse_url(resource): return True @classmethod def download(self, filename, input_dir, dl_dir=None): match = self._parse_url(filename) file_info = os.path.basename(filename) ext = file_info.find(match.group(1)) name = file_info[:ext] if not dl_dir: dl_dir = os.path.join(input_dir, name) utils.safe_makedir(dl_dir) fixed_name = "%s%s" % (name, match.group(1)) out_file = os.path.join(dl_dir, fixed_name) if not utils.file_exists(out_file): with file_transaction({}, out_file) as tx_out_file: cmd = "wget -O {tx_out_file} {filename}" do.run(cmd.format(**locals()), "Download %s" % out_file) return out_file def _get_storage_manager(resource): """Return a storage manager which can process this resource.""" for manager in (AmazonS3, ArvadosKeep, SevenBridges, DNAnexus, AzureBlob, GoogleCloud, RegularServer): if manager.check_resource(resource): return manager() raise ValueError("Unexpected object store %(resource)s" % {"resource": resource}) def is_remote(fname): """Check if the received file is recognised by one of the available storage managers. """ try: _get_storage_manager(fname) except ValueError: return False return True def file_exists_or_remote(fname): """Check if a file exists or is accessible remotely.""" return is_remote(fname) or utils.file_exists(fname) def default_region(fname): """Return the default region for the received resource. Note: This feature is available only for AmazonS3 storage manager. """ manager = _get_storage_manager(fname) if hasattr(manager, "get_region"): return manager.get_region() raise NotImplementedError("Unexpected object store %s" % fname) def connect(filename): """Returns a connection object pointing to the endpoint associated to the received resource. """ manager = _get_storage_manager(filename) return manager.connect(filename) def download(fname, input_dir, dl_dir=None): """Download the resource from the storage.""" try: manager = _get_storage_manager(fname) except ValueError: return fname return manager.download(fname, input_dir, dl_dir) def cl_input(fname, unpack=True, anonpipe=True): """Return command line input for a file, handling streaming remote cases. """ try: manager = _get_storage_manager(fname) except ValueError: return fname return manager.cl_input(fname, unpack, anonpipe) def list(remote_dirname): """Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order. """ manager = _get_storage_manager(remote_dirname) return manager.list(remote_dirname) def open_file(fname): """Provide a handle-like object for streaming.""" manager = _get_storage_manager(fname) return manager.open(fname) def parse_remote(fname): """Parses a remote filename in order to obtain information related to received resource. """ manager = _get_storage_manager(fname) return manager.parse_remote(fname) bcbio-nextgen-1.2.9/bcbio/distributed/prun.py000066400000000000000000000055611415626112400212160ustar00rootroot00000000000000"""Generalized running of parallel tasks in multiple environments. """ import contextlib import os from bcbio import utils from bcbio.log import logger from bcbio.provenance import system from bcbio.distributed import multi, resources @contextlib.contextmanager def start(parallel, items, config, dirs=None, name=None, multiplier=1, max_multicore=None): """Start a parallel cluster or machines to be used for running remote functions. Returns a function used to process, in parallel items with a given function. Allows sharing of a single cluster across multiple functions with identical resource requirements. Uses local execution for non-distributed clusters or completed jobs. A checkpoint directory keeps track of finished tasks, avoiding spinning up clusters for sections that have been previous processed. multiplier - Number of expected jobs per initial input item. Used to avoid underscheduling cores when an item is split during processing. max_multicore -- The maximum number of cores to use for each process. Can be used to process less multicore usage when jobs run faster on more single cores. """ if name: checkpoint_dir = utils.safe_makedir(os.path.join(dirs["work"], "checkpoints_parallel")) checkpoint_file = os.path.join(checkpoint_dir, "%s.done" % name) else: checkpoint_file = None sysinfo = system.get_info(dirs, parallel, config.get("resources", {})) items = [x for x in items if x is not None] if items else [] max_multicore = int(max_multicore or sysinfo.get("cores", 1)) parallel = resources.calculate(parallel, items, sysinfo, config, multiplier=multiplier, max_multicore=max_multicore) try: view = None if parallel["type"] == "ipython": if checkpoint_file and os.path.exists(checkpoint_file): logger.info("Running locally instead of distributed -- checkpoint passed: %s" % name) parallel["cores_per_job"] = 1 parallel["num_jobs"] = 1 parallel["checkpointed"] = True yield multi.runner(parallel, config) else: from bcbio.distributed import ipython with ipython.create(parallel, dirs, config) as view: yield ipython.runner(view, parallel, dirs, config) else: yield multi.runner(parallel, config) except: if view is not None: from bcbio.distributed import ipython ipython.stop(view) raise else: for x in ["cores_per_job", "num_jobs", "mem"]: parallel.pop(x, None) if checkpoint_file: with open(checkpoint_file, "w") as out_handle: out_handle.write("done\n") bcbio-nextgen-1.2.9/bcbio/distributed/resources.py000066400000000000000000000227511415626112400222440ustar00rootroot00000000000000"""Estimate resources required for processing a set of tasks. Uses annotations provided in multitasks.py for each function to identify utilized programs, then extracts resource requirements from the input bcbio_system file. """ import copy import math import operator from bcbio.pipeline import config_utils from bcbio.log import logger from functools import reduce def _get_resource_programs(progs, algs): """Retrieve programs used in analysis based on algorithm configurations. Handles special cases like aligners and variant callers. """ checks = {"gatk-vqsr": config_utils.use_vqsr, "snpeff": config_utils.use_snpeff, "bcbio-variation-recall": config_utils.use_bcbio_variation_recall} parent_child = {"vardict": _parent_prefix("vardict")} out = set([]) for p in progs: if p == "aligner": for alg in algs: aligner = alg.get("aligner") if aligner and not isinstance(aligner, bool): out.add(aligner) elif p in ["variantcaller", "svcaller", "peakcaller"]: if p == "variantcaller": for key, fn in parent_child.items(): if fn(algs): out.add(key) for alg in algs: callers = alg.get(p) if callers and not isinstance(callers, bool): if isinstance(callers, dict): callers = reduce(operator.add, callers.values()) if isinstance(callers, (list, tuple)): for x in callers: out.add(x) else: out.add(callers) elif p in checks: if checks[p](algs): out.add(p) else: out.add(p) return sorted(list(out)) def _parent_prefix(prefix): """Identify a parent prefix we should add to resources if present in a caller name. """ def run(algs): for alg in algs: vcs = alg.get("variantcaller") if vcs: if isinstance(vcs, dict): vcs = reduce(operator.add, vcs.values()) if not isinstance(vcs, (list, tuple)): vcs = [vcs] return any(vc.startswith(prefix) for vc in vcs if vc) return run def _ensure_min_resources(progs, cores, memory, min_memory): """Ensure setting match minimum resources required for used programs. """ for p in progs: if p in min_memory: if not memory or cores * memory < min_memory[p]: memory = float(min_memory[p]) / cores return cores, memory def _str_memory_to_gb(memory): val = float(memory[:-1]) units = memory[-1] if units.lower() == "m": val = val / 1000.0 else: assert units.lower() == "g", "Unexpected memory units: %s" % memory return val def _get_prog_memory(resources, cores_per_job): """Get expected memory usage, in Gb per core, for a program from resource specification. """ out = None for jvm_opt in resources.get("jvm_opts", []): if jvm_opt.startswith("-Xmx"): out = _str_memory_to_gb(jvm_opt[4:]) memory = resources.get("memory") if memory: out = _str_memory_to_gb(memory) prog_cores = resources.get("cores") # if a single core with memory is requested for the job # and we run multiple cores, scale down to avoid overscheduling if out and prog_cores and int(prog_cores) == 1 and cores_per_job > int(prog_cores): out = out / float(cores_per_job) return out def _scale_cores_to_memory(cores, mem_per_core, sysinfo, system_memory): """Scale multicore usage to avoid excessive memory usage based on system information. """ total_mem = "%.2f" % (cores * mem_per_core + system_memory) if "cores" not in sysinfo: return cores, total_mem, 1.0 total_mem = min(float(total_mem), float(sysinfo["memory"]) - system_memory) cores = min(cores, int(sysinfo["cores"])) mem_cores = int(math.floor(float(total_mem) / mem_per_core)) # cores based on available memory if mem_cores < 1: out_cores = 1 elif mem_cores < cores: out_cores = mem_cores else: out_cores = cores mem_pct = float(out_cores) / float(cores) return out_cores, total_mem, mem_pct def _scale_jobs_to_memory(jobs, mem_per_core, sysinfo): """When scheduling jobs with single cores, avoid overscheduling due to memory. """ if "cores" not in sysinfo: return jobs, 1.0 sys_mem_per_core = float(sysinfo["memory"]) / float(sysinfo["cores"]) if sys_mem_per_core < mem_per_core: pct = sys_mem_per_core / float(mem_per_core) target_jobs = int(math.floor(jobs * pct)) return max(target_jobs, 1), pct else: return jobs, 1.0 def cpu_and_memory(programs, items): """Retrieve CPU and memory/core specified in configuration input. """ assert len(items) > 0, "Finding job resources but no items to process" config = items[0]["config"] all_cores = [] all_memory = [] algs = [config_utils.get_algorithm_config(x) for x in items] progs = _get_resource_programs(programs, algs) # Calculate cores for prog in progs: resources = config_utils.get_resources(prog, config) all_cores.append(resources.get("cores", 1)) if len(all_cores) == 0: all_cores.append(1) cores_per_job = max(all_cores) # Calculate memory. Use 1Gb memory usage per core as min baseline if not specified for prog in progs: resources = config_utils.get_resources(prog, config) memory = _get_prog_memory(resources, cores_per_job) if memory: all_memory.append(memory) if len(all_memory) == 0: all_memory.append(1) memory_per_core = max(all_memory) return cores_per_job, memory_per_core def calculate(parallel, items, sysinfo, config, multiplier=1, max_multicore=None): """Determine cores and workers to use for this stage based on used programs. multiplier specifies the number of regions items will be split into during processing. max_multicore specifies an optional limit on the maximum cores. Can use to force single core processing during specific tasks. sysinfo specifies cores and memory on processing nodes, allowing us to tailor jobs for available resources. """ assert len(items) > 0, "Finding job resources but no items to process" all_cores = [] all_memory = [] # Provide 100Mb of additional memory for the system system_memory = 0.10 algs = [config_utils.get_algorithm_config(x) for x in items] progs = _get_resource_programs(parallel.get("progs", []), algs) # Calculate cores for prog in progs: resources = config_utils.get_resources(prog, config) all_cores.append(resources.get("cores", 1)) if len(all_cores) == 0: all_cores.append(1) cores_per_job = max(all_cores) if max_multicore: cores_per_job = min(cores_per_job, max_multicore) if "cores" in sysinfo: cores_per_job = min(cores_per_job, int(sysinfo["cores"])) total = parallel["cores"] if total > cores_per_job: num_jobs = total // cores_per_job else: num_jobs, cores_per_job = 1, total # Calculate memory. Use 1Gb memory usage per core as min baseline if not specified for prog in progs: resources = config_utils.get_resources(prog, config) memory = _get_prog_memory(resources, cores_per_job) if memory: all_memory.append(memory) if len(all_memory) == 0: all_memory.append(1) memory_per_core = max(all_memory) logger.debug("Resource requests: {progs}; memory: {memory}; cores: {cores}".format( progs=", ".join(progs), memory=", ".join("%.2f" % x for x in all_memory), cores=", ".join(str(x) for x in all_cores))) cores_per_job, memory_per_core = _ensure_min_resources(progs, cores_per_job, memory_per_core, min_memory=parallel.get("ensure_mem", {})) if cores_per_job == 1: memory_per_job = "%.2f" % memory_per_core num_jobs, mem_pct = _scale_jobs_to_memory(num_jobs, memory_per_core, sysinfo) # For single core jobs, avoid overscheduling maximum cores_per_job num_jobs = min(num_jobs, total) else: cores_per_job, memory_per_job, mem_pct = _scale_cores_to_memory(cores_per_job, memory_per_core, sysinfo, system_memory) # For local runs with multiple jobs and multiple cores, potentially scale jobs down if num_jobs > 1 and parallel.get("type") == "local": memory_per_core = float(memory_per_job) / cores_per_job num_jobs, _ = _scale_jobs_to_memory(num_jobs, memory_per_core, sysinfo) # do not overschedule if we don't have extra items to process num_jobs = int(min(num_jobs, len(items) * multiplier)) logger.debug("Configuring %d jobs to run, using %d cores each with %sg of " "memory reserved for each job" % (num_jobs, cores_per_job, str(memory_per_job))) parallel = copy.deepcopy(parallel) parallel["cores_per_job"] = cores_per_job parallel["num_jobs"] = num_jobs parallel["mem"] = str(memory_per_job) parallel["mem_pct"] = "%.2f" % mem_pct parallel["system_cores"] = sysinfo.get("cores", 1) return parallel bcbio-nextgen-1.2.9/bcbio/distributed/runfn.py000066400000000000000000000647411415626112400213670ustar00rootroot00000000000000"""Run distributed functions provided a name and json/YAML file with arguments. Enables command line access and alternative interfaces to run specific functionality within bcbio-nextgen. """ import collections import contextlib import json import os import pprint import shutil import six import toolz as tz import yaml from bcbio import log, utils, setpath, utils from bcbio.log import logger from bcbio.cwl import cwlutils from bcbio.distributed import multitasks from bcbio.pipeline import config_utils, run_info def process(args): """Run the function in args.name given arguments in args.argfile. """ # Set environment to standard to use periods for decimals and avoid localization locale_to_use = utils.get_locale() os.environ["LC_ALL"] = locale_to_use os.environ["LC"] = locale_to_use os.environ["LANG"] = locale_to_use setpath.prepend_bcbiopath() try: fn = getattr(multitasks, args.name) except AttributeError: raise AttributeError("Did not find exposed function in bcbio.distributed.multitasks named '%s'" % args.name) if args.moreargs or args.raw: fnargs = [args.argfile] + args.moreargs work_dir = None argfile = None else: with open(args.argfile) as in_handle: fnargs = yaml.safe_load(in_handle) work_dir = os.path.dirname(args.argfile) fnargs = config_utils.merge_resources(fnargs) argfile = args.outfile if args.outfile else "%s-out%s" % os.path.splitext(args.argfile) if not work_dir: work_dir = os.getcwd() if len(fnargs) > 0 and fnargs[0] == "cwl": fnargs, parallel, out_keys, input_files = _world_from_cwl(args.name, fnargs[1:], work_dir) # Can remove this awkward Docker merge when we do not need custom GATK3 installs fnargs = config_utils.merge_resources(fnargs) argfile = os.path.join(work_dir, "cwl.output.json") else: parallel, out_keys, input_files = None, {}, [] with utils.chdir(work_dir): with contextlib.closing(log.setup_local_logging(parallel={"wrapper": "runfn"})): try: out = fn(*fnargs) except: logger.exception() raise finally: # Clean up any copied and unpacked workflow inputs, avoiding extra disk usage wf_input_dir = os.path.join(work_dir, "wf-inputs") if os.path.exists(wf_input_dir) and os.path.isdir(wf_input_dir): shutil.rmtree(wf_input_dir) if argfile: try: _write_out_argfile(argfile, out, fnargs, parallel, out_keys, input_files, work_dir) except: logger.exception() raise def _cwlvar_to_wdl(var): """Convert a CWL output object into a WDL output. This flattens files and other special CWL outputs that are plain strings in WDL. """ if isinstance(var, (list, tuple)): return [_cwlvar_to_wdl(x) for x in var] elif isinstance(var, dict): assert var.get("class") == "File", var # XXX handle secondary files return var.get("path") or var["value"] else: return var def _write_out_argfile(argfile, out, fnargs, parallel, out_keys, input_files, work_dir): """Write output argfile, preparing a CWL ready JSON or YAML representation of the world. """ with open(argfile, "w") as out_handle: if argfile.endswith(".json"): record_name, record_attrs = _get_record_attrs(out_keys) if record_name: if parallel in ["multi-batch"]: recs = _nested_cwl_record(out, record_attrs, input_files) elif parallel in ["single-split", "multi-combined", "multi-parallel", "batch-single", "single-single"]: recs = [_collapse_to_cwl_record_single(utils.to_single_data(xs), record_attrs, input_files) for xs in out] else: samples = [utils.to_single_data(xs) for xs in out] recs = [_collapse_to_cwl_record(samples, record_attrs, input_files)] json.dump(_combine_cwl_records(recs, record_name, parallel), out_handle, sort_keys=True, indent=4, separators=(', ', ': ')) elif parallel in ["single-split", "multi-combined", "batch-split"]: json.dump(_convert_to_cwl_json([utils.to_single_data(xs) for xs in out], fnargs, input_files), out_handle, sort_keys=True, indent=4, separators=(', ', ': ')) else: json.dump(_convert_to_cwl_json(utils.to_single_data(utils.to_single_data(out)), fnargs, input_files), out_handle, sort_keys=True, indent=4, separators=(', ', ': ')) else: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) def _get_record_attrs(out_keys): """Check for records, a single key plus output attributes. """ if len(out_keys) == 1: attr = list(out_keys.keys())[0] if out_keys[attr]: return attr, out_keys[attr] return None, None def _add_resources(data, runtime): """Merge input resources with current CWL runtime parameters. """ if "config" not in data: data["config"] = {} # Convert input resources, which may be a JSON string resources = data.get("resources", {}) or {} if isinstance(resources, six.string_types) and resources.startswith(("{", "[")): resources = json.loads(resources) data["resources"] = resources assert isinstance(resources, dict), (resources, data) data["config"]["resources"] = resources # Add in memory and core usage from CWL memory = int(float(runtime["ram"]) / float(runtime["cores"])) data["config"]["resources"].update({"default": {"cores": int(runtime["cores"]), "memory": "%sM" % memory, "jvm_opts": ["-Xms%sm" % min(1000, memory // 2), "-Xmx%sm" % memory]}}) data["config"]["algorithm"]["num_cores"] = int(runtime["cores"]) return data def _world_from_cwl(fn_name, fnargs, work_dir): """Reconstitute a bcbio world data object from flattened CWL-compatible inputs. Converts the flat CWL representation into a nested bcbio world dictionary. Handles single sample inputs (returning a single world object) and multi-sample runs (returning a list of individual samples to get processed together). """ parallel = None output_cwl_keys = None runtime = {} out = [] data = {} passed_keys = [] for fnarg in fnargs: key, val = fnarg.split("=") # extra values pulling in nested indexes if key == "ignore": continue if key == "sentinel_parallel": parallel = val continue if key == "sentinel_runtime": runtime = dict(tz.partition(2, val.split(","))) continue if key == "sentinel_outputs": output_cwl_keys = _parse_output_keys(val) continue if key == "sentinel_inputs": input_order = collections.OrderedDict([x.split(":") for x in val.split(",")]) continue else: assert key not in passed_keys, "Multiple keys should be handled via JSON records" passed_keys.append(key) key = key.split("__") data = _update_nested(key, _convert_value(val), data) if data: out.append(_finalize_cwl_in(data, work_dir, passed_keys, output_cwl_keys, runtime)) # Read inputs from standard files instead of command line assert os.path.exists(os.path.join(work_dir, "cwl.inputs.json")) out, input_files = _read_from_cwlinput(os.path.join(work_dir, "cwl.inputs.json"), work_dir, runtime, parallel, input_order, output_cwl_keys) if parallel in ["single-parallel", "single-merge", "multi-parallel", "multi-combined", "multi-batch", "batch-split", "batch-parallel", "batch-merge", "batch-single"]: out = [out] else: assert len(out) == 1, "%s\n%s" % (pprint.pformat(out), pprint.pformat(fnargs)) return out, parallel, output_cwl_keys, input_files def _parse_output_keys(val): """Parse expected output keys from string, handling records. """ out = {} for k in val.split(","): # record output if ":" in k: name, attrs = k.split(":") out[name] = attrs.split(";") else: out[k] = None return out def _find_input_files(var, out): """Find input files within the given CWL object. """ if isinstance(var, (list, tuple)): for x in var: out = _find_input_files(x, out) elif isinstance(var, dict): if var.get("class") == "File": out.append(var["path"]) out = _find_input_files(var.get("secondaryFiles", []), out) for key, val in var.items(): out = _find_input_files(val, out) return out def _read_from_cwlinput(in_file, work_dir, runtime, parallel, input_order, output_cwl_keys): """Read data records from a JSON dump of inputs. Avoids command line flattening of records. """ with open(in_file) as in_handle: inputs = json.load(in_handle) items_by_key = {} input_files = [] passed_keys = set([]) for key, input_val in ((k, v) for (k, v) in inputs.items() if not k.startswith(("sentinel", "ignore"))): if key.endswith("_toolinput"): key = key.replace("_toolinput", "") if input_order[key] == "record": cur_keys, items = _read_cwl_record(input_val) passed_keys |= cur_keys items_by_key[key] = items else: items_by_key[tuple(key.split("__"))] = _cwlvar_to_wdl(input_val) input_files = _find_input_files(input_val, input_files) prepped = _merge_cwlinputs(items_by_key, input_order, parallel) out = [] for data in prepped: if isinstance(data, (list, tuple)): out.append([_finalize_cwl_in(utils.to_single_data(x), work_dir, list(passed_keys), output_cwl_keys, runtime) for x in data]) else: out.append(_finalize_cwl_in(data, work_dir, list(passed_keys), output_cwl_keys, runtime)) return out, input_files def _is_nested_item(x): return isinstance(x, (list, tuple)) def _maybe_nest_bare_single(items_by_key, parallel): """Nest single inputs to avoid confusing single items and lists like files. """ if (parallel == "multi-parallel" and (sum([1 for x in items_by_key.values() if not _is_nested_item(x)]) >= sum([1 for x in items_by_key.values() if _is_nested_item(x)]))): out = {} for k, v in items_by_key.items(): out[k] = [v] return out else: return items_by_key def _item_count(x): return len(x) if _is_nested_item(x) else 1 def _is_nested_single(v, target): return target > 1 and _is_nested_item(v) and _item_count(v) == 1 and _item_count(v[0]) == target def _check_for_single_nested(target, items_by_key, input_order): """Check for single nested inputs that match our target count and unnest. Handles complex var inputs where some have an extra layer of nesting. """ out = utils.deepish_copy(items_by_key) for (k, t) in input_order.items(): if t == "var": v = items_by_key[tuple(k.split("__"))] if _is_nested_single(v, target): out[tuple(k.split("__"))] = v[0] return out def _concat_records(items_by_key, input_order): """Concatenate records into a single key to avoid merging. Handles heterogeneous records that will then be sorted out in the processing fuction. """ all_records = [] for (k, t) in input_order.items(): if t == "record": all_records.append(k) out_items_by_key = utils.deepish_copy(items_by_key) out_input_order = utils.deepish_copy(input_order) if len(all_records) > 1: final_k = all_records[0] final_v = items_by_key[final_k] for k in all_records[1:]: final_v += items_by_key[k] del out_items_by_key[k] del out_input_order[k] out_items_by_key[final_k] = final_v return out_items_by_key, out_input_order def _merge_cwlinputs(items_by_key, input_order, parallel): """Merge multiple cwl records and inputs, handling multiple data items. Special cases: - Single record but multiple variables (merging arrayed jobs). Assign lists of variables to the record. """ items_by_key = _maybe_nest_bare_single(items_by_key, parallel) if parallel == "multi-combined": items_by_key, input_order = _concat_records(items_by_key, input_order) var_items = set([_item_count(items_by_key[tuple(k.split("__"))]) for (k, t) in input_order.items() if t == "var"]) rec_items = set([_item_count(items_by_key[k]) for (k, t) in input_order.items() if t == "record"]) if var_items: num_items = var_items if len(num_items) == 2 and 1 in num_items: num_items.remove(1) items_by_key_test = _check_for_single_nested(num_items.pop(), items_by_key, input_order) var_items = set([_item_count(items_by_key_test[tuple(k.split("__"))]) for (k, t) in input_order.items() if t == "var"]) num_items = var_items assert len(num_items) == 1, "Non-consistent variable data counts in CWL input:\n%s" % \ (pprint.pformat(items_by_key)) items_by_key, num_items = _nest_vars_in_rec(var_items, rec_items, input_order, items_by_key, parallel) else: num_items = rec_items assert len(num_items) == 1, "Non-consistent record data counts in CWL input:\n%s" % \ (pprint.pformat(items_by_key)) target_items = num_items.pop() out = [{} for _ in range(target_items)] for (cwl_key, cwl_type) in input_order.items(): if cwl_type == "var": cwl_key = tuple(cwl_key.split("__")) cur_vals = items_by_key[cwl_key] if _is_nested_single(cur_vals, target_items): cur_vals = [[x] for x in cur_vals[0]] for i, cur_val in enumerate(cur_vals): if isinstance(cwl_key, (list, tuple)): # nested batches with records if (parallel.startswith(("batch", "multi-parallel")) and isinstance(out[i], (list, tuple))): for j in range(len(out[i])): out[i][j] = _update_nested(list(cwl_key), cur_val, out[i][j], allow_overwriting=True) else: out[i] = _update_nested(list(cwl_key), cur_val, out[i], allow_overwriting=True) elif out[i] == {}: out[i] = cur_val else: # Handle single non-batched records if isinstance(cur_val, (list, tuple)) and len(cur_val) == 1: cur_val = cur_val[0] assert isinstance(cur_val, dict), (cwl_key, cur_val) for k, v in cur_val.items(): out[i] = _update_nested([k], v, out[i], allow_overwriting=True) return out def _nest_vars_in_rec(var_items, rec_items, input_order, items_by_key, parallel): """Nest multiple variable inputs into a single record or list of batch records. Custom CWL implementations extract and merge these. """ num_items = var_items var_items = list(var_items)[0] if rec_items: rec_items = list(rec_items)[0] if ((rec_items == 1 and var_items > 1) or parallel.startswith("batch")): num_items = set([rec_items]) for var_key in (k for (k, t) in input_order.items() if t != "record"): var_key = tuple(var_key.split("__")) items_by_key[var_key] = [items_by_key[var_key]] * rec_items else: assert var_items == rec_items, (var_items, rec_items) return items_by_key, num_items def _expand_rec_to_vars(var_items, rec_items, input_order, items_by_key, parallel): """Expand record to apply to number of variants. Alternative approach to _nest_vars_in_rec to combining a single record with multiple variants. """ num_items = var_items var_items = list(var_items)[0] if rec_items: for rec_key in (k for (k, t) in input_order.items() if t == "record"): rec_vals = items_by_key[rec_key] if len(rec_vals) == 1 and var_items > 1: items_by_key[rec_key] = rec_vals * var_items else: assert var_items == len(rec_vals), (var_items, rec_vals) return items_by_key, num_items def _read_cwl_record(rec): """Read CWL records, handling multiple nesting and batching cases. """ keys = set([]) out = [] if isinstance(rec, dict): is_batched = all([isinstance(v, (list, tuple)) for v in rec.values()]) cur = [{} for _ in range(len(rec.values()[0]) if is_batched else 1)] for k in rec.keys(): keys.add(k) val = rec[k] val = val if is_batched else [val] for i, v in enumerate(val): v = _cwlvar_to_wdl(v) cur[i] = _update_nested(k.split("__"), v, cur[i]) if is_batched: out.append(cur) else: assert len(cur) == 1 out.append(cur[0]) else: assert isinstance(rec, (list, tuple)) for sub_rec in rec: sub_keys, sub_out = _read_cwl_record(sub_rec) keys |= sub_keys out.append(sub_out) return keys, out def _finalize_cwl_in(data, work_dir, passed_keys, output_cwl_keys, runtime): """Finalize data object with inputs from CWL. """ data["dirs"] = {"work": work_dir} if not tz.get_in(["config", "algorithm"], data): if "config" not in data: data["config"] = {} data["config"]["algorithm"] = {} if "rgnames" not in data and "description" in data: data["rgnames"] = {"sample": data["description"]} data["cwl_keys"] = passed_keys data["output_cwl_keys"] = output_cwl_keys data = _add_resources(data, runtime) data = cwlutils.normalize_missing(data) data = run_info.normalize_world(data) return data def _convert_value(val): """Handle multiple input type values. """ def _is_number(x, op): try: op(x) return True except ValueError: return False if isinstance(val, (list, tuple)): return [_convert_value(x) for x in val] elif val is None: return val elif _is_number(val, int): return int(val) elif _is_number(val, float): return float(val) elif val.find(";;") >= 0: return [_convert_value(v) for v in val.split(";;")] elif val.startswith(("{", "[")): # Can get ugly JSON output from CWL with unicode and ' instead of " # This tries to fix it so parsed correctly by json loader return json.loads(val.replace("u'", "'").replace("'", '"')) elif val.lower() == "true": return True elif val.lower() == "false": return False else: return val def _convert_to_cwl_json(data, fnargs, input_files): """Convert world data object (or list of data objects) into outputs for CWL ingestion. """ out = {} for outvar in _get_output_cwl_keys(fnargs): keys = [] for key in outvar.split("__"): try: key = int(key) except ValueError: pass keys.append(key) if isinstance(data, dict): out[outvar] = _to_cwl(tz.get_in(keys, data), input_files) else: out[outvar] = [_to_cwl(tz.get_in(keys, x), input_files) for x in data] return out def _get_output_cwl_keys(fnargs): """Retrieve output_cwl_keys from potentially nested input arguments. """ for d in utils.flatten(fnargs): if isinstance(d, dict) and d.get("output_cwl_keys"): return d["output_cwl_keys"] raise ValueError("Did not find output_cwl_keys in %s" % (pprint.pformat(fnargs))) def _combine_cwl_records(recs, record_name, parallel): """Provide a list of nexted CWL records keyed by output key. Handles batches, where we return a list of records, and single items where we return one record. """ if parallel not in ["multi-batch", "single-split", "multi-combined", "batch-single"]: assert len(recs) == 1, pprint.pformat(recs) return {record_name: recs[0]} else: return {record_name: recs} def _collapse_to_cwl_record_single(data, want_attrs, input_files): """Convert a single sample into a CWL record. """ out = {} for key in want_attrs: key_parts = key.split("__") out[key] = _to_cwl(tz.get_in(key_parts, data), input_files) return out def _nested_cwl_record(xs, want_attrs, input_files): """Convert arbitrarily nested samples into a nested list of dictionaries. nests only at the record level, rather than within records. For batching a top level list is all of the batches and sub-lists are samples within the batch. """ if isinstance(xs, (list, tuple)): return [_nested_cwl_record(x, want_attrs, input_files) for x in xs] else: assert isinstance(xs, dict), pprint.pformat(xs) return _collapse_to_cwl_record_single(xs, want_attrs, input_files) def _collapse_to_cwl_record(samples, want_attrs, input_files): """Convert nested samples from batches into a CWL record, based on input keys. """ input_keys = sorted(list(set().union(*[d["cwl_keys"] for d in samples])), key=lambda x: (-len(x), tuple(x))) out = {} for key in input_keys: if key in want_attrs: key_parts = key.split("__") vals = [] cur = [] for d in samples: vals.append(_to_cwl(tz.get_in(key_parts, d), input_files)) # Remove nested keys to avoid specifying multiple times cur.append(_dissoc_in(d, key_parts) if len(key_parts) > 1 else d) samples = cur out[key] = vals return out def _file_and_exists(val, input_files): """Check if an input is a file and exists. Checks both locally (staged) and from input files (re-passed but never localized). """ return ((os.path.exists(val) and os.path.isfile(val)) or val in input_files) def _to_cwl(val, input_files): """Convert a value into CWL formatted JSON, handling files and complex things. """ if isinstance(val, six.string_types): if _file_and_exists(val, input_files): val = {"class": "File", "path": val} secondary = [] for idx in [".bai", ".tbi", ".gbi", ".fai", ".crai", ".db"]: idx_file = val["path"] + idx if _file_and_exists(idx_file, input_files): secondary.append({"class": "File", "path": idx_file}) for idx in [".dict"]: idx_file = os.path.splitext(val["path"])[0] + idx if _file_and_exists(idx_file, input_files): secondary.append({"class": "File", "path": idx_file}) cur_dir, cur_file = os.path.split(val["path"]) # Handle relative paths if not cur_dir: cur_dir = os.getcwd() if cur_file.endswith(cwlutils.DIR_TARGETS): if os.path.exists(cur_dir): for fname in os.listdir(cur_dir): if fname != cur_file and not os.path.isdir(os.path.join(cur_dir, fname))\ and fname != 'sbg.worker.log': secondary.append({"class": "File", "path": os.path.join(cur_dir, fname)}) else: for f in input_files: if f.startswith(cur_dir) and f != cur_file and not os.path.isdir(f): secondary.append({"class": "File", "path": f}) if secondary: val["secondaryFiles"] = _remove_duplicate_files(secondary) elif isinstance(val, (list, tuple)): val = [_to_cwl(x, input_files) for x in val] elif isinstance(val, dict): # File representation with secondary files if "base" in val and "secondary" in val: out = {"class": "File", "path": val["base"]} secondary = [{"class": "File", "path": x} for x in val["secondary"] if not os.path.isdir(x)] if secondary: out["secondaryFiles"] = _remove_duplicate_files(secondary) val = out else: val = json.dumps(val, sort_keys=True, separators=(',', ':')) return val def _remove_duplicate_files(xs): """Remove files specified multiple times in a list. """ seen = set([]) out = [] for x in xs: if x["path"] not in seen: out.append(x) seen.add(x["path"]) return out def _dissoc_in(d, key_parts): if len(key_parts) > 1: d[key_parts[0]] = _dissoc_in(d[key_parts[0]], key_parts[1:]) else: d.pop(key_parts[0], None) return d def _update_nested(key, val, data, allow_overwriting=False): """Update the data object, avoiding over-writing with nested dictionaries. """ if isinstance(val, dict): for sub_key, sub_val in val.items(): data = _update_nested(key + [sub_key], sub_val, data, allow_overwriting=allow_overwriting) else: already_there = tz.get_in(key, data) is not None if already_there and val: if not allow_overwriting: raise ValueError("Duplicated key %s: %s and %s" % (key, val, tz.get_in(key, data))) else: already_there = False if val or not already_there: data = tz.update_in(data, key, lambda x: val) return data def add_subparser(subparsers): parser = subparsers.add_parser("runfn", help=("Run a specific bcbio-nextgen function." "Intended for distributed use.")) parser.add_argument("name", help="Name of the function to run") parser.add_argument("argfile", help="JSON file with arguments to the function") parser.add_argument("moreargs", nargs="*", help="Additional arguments to pass in the case of raw input") parser.add_argument("--raw", action="store_true", default=False, help="Treat the inputs as raw file arguments to the function, instead of parsing them.") parser.add_argument("-o", "--outfile", help="Output file to write, defaults to inputfile-out.yaml") bcbio-nextgen-1.2.9/bcbio/distributed/split.py000066400000000000000000000142671415626112400213700ustar00rootroot00000000000000"""Split files or tasks for distributed processing across multiple machines. This tackles parallel work within the context of a program, where we split based on input records like fastq or across regions like chromosomes in a BAM file. Following splitting, individual records and run and then combined back into a summarized output file. This provides a framework for that process, making it easier to utilize with splitting specific code. """ import collections import six from bcbio import utils def grouped_parallel_split_combine(args, split_fn, group_fn, parallel_fn, parallel_name, combine_name, file_key, combine_arg_keys, split_outfile_i=-1): """Parallel split runner that allows grouping of samples during processing. This builds on parallel_split_combine to provide the additional ability to group samples and subsequently split them back apart. This allows analysis of related samples together. In addition to the arguments documented in parallel_split_combine, this needs: group_fn: A function that groups samples together given their configuration details. """ grouped_args = group_fn(args) split_args, combine_map, finished_out, extras = _get_split_tasks(grouped_args, split_fn, file_key, split_outfile_i) final_output = parallel_fn(parallel_name, split_args) combine_args, final_args = _organize_output(final_output, combine_map, file_key, combine_arg_keys) parallel_fn(combine_name, combine_args) return finished_out + final_args + extras def parallel_split_combine(args, split_fn, parallel_fn, parallel_name, combiner, file_key, combine_arg_keys, split_outfile_i=-1): """Split, run split items in parallel then combine to output file. split_fn: Split an input file into parts for processing. Returns the name of the combined output file along with the individual split output names and arguments for the parallel function. parallel_fn: Reference to run_parallel function that will run single core, multicore, or distributed as needed. parallel_name: The name of the function, defined in bcbio.distributed.tasks/multitasks/ipythontasks to run in parallel. combiner: The name of the function, also from tasks, that combines the split output files into a final ready to run file. Can also be a callable function if combining is delayed. split_outfile_i: the location of the output file in the arguments generated by the split function. Defaults to the last item in the list. """ args = [x[0] for x in args] split_args, combine_map, finished_out, extras = _get_split_tasks(args, split_fn, file_key, split_outfile_i) split_output = parallel_fn(parallel_name, split_args) if isinstance(combiner, six.string_types): combine_args, final_args = _organize_output(split_output, combine_map, file_key, combine_arg_keys) parallel_fn(combiner, combine_args) elif callable(combiner): final_args = combiner(split_output, combine_map, file_key) return finished_out + final_args + extras def _get_extra_args(extra_args, arg_keys): """Retrieve extra arguments to pass along to combine function. Special cases like reference files and configuration information are passed as single items, the rest as lists mapping to each data item combined. """ # XXX back compatible hack -- should have a way to specify these. single_keys = set(["sam_ref", "config"]) out = [] for i, arg_key in enumerate(arg_keys): vals = [xs[i] for xs in extra_args] if arg_key in single_keys: out.append(vals[-1]) else: out.append(vals) return out def _organize_output(output, combine_map, file_key, combine_arg_keys): """Combine output details for parallelization. file_key is the key name of the output file used in merging. We extract this file from the output data. combine_arg_keys are extra items to pass along to the combine function. """ out_map = collections.defaultdict(list) extra_args = collections.defaultdict(list) final_args = collections.OrderedDict() extras = [] for data in output: cur_file = data.get(file_key) if not cur_file: extras.append([data]) else: cur_out = combine_map[cur_file] out_map[cur_out].append(cur_file) extra_args[cur_out].append([data[x] for x in combine_arg_keys]) data[file_key] = cur_out if cur_out not in final_args: final_args[cur_out] = [data] else: extras.append([data]) combine_args = [[v, k] + _get_extra_args(extra_args[k], combine_arg_keys) for (k, v) in out_map.items()] return combine_args, list(final_args.values()) + extras def _get_split_tasks(args, split_fn, file_key, outfile_i=-1): """Split up input files and arguments, returning arguments for parallel processing. outfile_i specifies the location of the output file in the arguments to the processing function. Defaults to the last item in the list. """ split_args = [] combine_map = {} finished_map = collections.OrderedDict() extras = [] for data in args: out_final, out_parts = split_fn(data) for parts in out_parts: split_args.append([utils.deepish_copy(data)] + list(parts)) for part_file in [x[outfile_i] for x in out_parts]: combine_map[part_file] = out_final if len(out_parts) == 0: if out_final is not None: if out_final not in finished_map: data[file_key] = out_final finished_map[out_final] = [data] else: extras.append([data]) else: extras.append([data]) return split_args, combine_map, list(finished_map.values()), extras bcbio-nextgen-1.2.9/bcbio/distributed/transaction.py000066400000000000000000000121631415626112400225530ustar00rootroot00000000000000"""Handle file based transactions allowing safe restarts at any point. To handle interrupts,this defines output files written to temporary locations during processing and copied to the final location when finished. This ensures output files will be complete independent of method of interruption. """ import contextlib import os import shutil import tempfile import toolz as tz from bcbio import utils from bcbio.log import logger DEFAULT_TMP = 'bcbiotx' @contextlib.contextmanager def tx_tmpdir(data=None, base_dir=None, remove=True): """Context manager to create and remove a transactional temporary directory. Handles creating a transactional directory for running commands in. Will use either the current directory or /tmp/bcbiotx. Creates an intermediary location and time specific directory for global temporary directories to prevent collisions. data can be the full world information object being process or a configuration dictionary. """ base_dir = base_dir or os.getcwd() tmpdir_base = utils.get_abspath(_get_base_tmpdir(data, base_dir)) utils.safe_makedir(tmpdir_base) tmp_dir = tempfile.mkdtemp(dir=tmpdir_base) #logger.debug("Created tmp dir %s " % tmp_dir) try: yield tmp_dir finally: if remove: utils.remove_safe(tmp_dir) def _get_base_tmpdir(data, fallback_base_dir): config_tmpdir = tz.get_in(("config", "resources", "tmp", "dir"), data) if not config_tmpdir: config_tmpdir = tz.get_in(("resources", "tmp", "dir"), data) return config_tmpdir or os.path.join(fallback_base_dir, DEFAULT_TMP) @contextlib.contextmanager def file_transaction(*data_and_files): """Wrap file generation in a transaction, moving to output if finishes. The initial argument can be the world descriptive `data` dictionary, or a `config` dictionary. This is used to identify global settings for temporary directories to create transactional files in. """ with _flatten_plus_safe(data_and_files) as (safe_names, orig_names): # remove any half-finished transactions map(utils.remove_safe, safe_names) # no need for try except block here, # because exceptions and tmp dir removal # are handled by tx_tmpdir contextmanager if len(safe_names) == 1: yield safe_names[0] else: yield tuple(safe_names) for safe, orig in zip(safe_names, orig_names): if os.path.exists(safe): _move_tmp_files(safe, orig) def _move_tmp_files(safe, orig): exts = { ".vcf": ".idx", ".bam": ".bai", ".vcf.gz": ".tbi", ".bed.gz": ".tbi" } utils.safe_makedir(os.path.dirname(orig)) # If we are rolling back a directory and it already exists # this will avoid making a nested set of directories if os.path.isdir(orig) and os.path.isdir(safe): utils.remove_safe(orig) _move_file_with_sizecheck(safe, orig) # Move additional, associated files in the same manner for check_ext, check_idx in exts.items(): if not safe.endswith(check_ext): continue safe_idx = safe + check_idx if os.path.exists(safe_idx): _move_file_with_sizecheck(safe_idx, orig + check_idx) def _move_file_with_sizecheck(tx_file, final_file): """Move transaction file to final location, with size checks avoiding failed transfers. Creates an empty file with '.bcbiotmp' extention in the destination location, which serves as a flag. If a file like that is present, it means that transaction didn't finish successfully. """ #logger.debug("Moving %s to %s" % (tx_file, final_file)) tmp_file = final_file + ".bcbiotmp" open(tmp_file, 'wb').close() want_size = utils.get_size(tx_file) shutil.move(tx_file, final_file) transfer_size = utils.get_size(final_file) assert want_size == transfer_size, ( 'distributed.transaction.file_transaction: File copy error: ' 'file or directory on temporary storage ({}) size {} bytes ' 'does not equal size of file or directory after transfer to ' 'shared storage ({}) size {} bytes'.format( tx_file, want_size, final_file, transfer_size) ) utils.remove_safe(tmp_file) @contextlib.contextmanager def _flatten_plus_safe(data_and_files): """Flatten names of files and create temporary file names. """ data, rollback_files = _normalize_args(data_and_files) with tx_tmpdir(data) as tmpdir: tx_files = [os.path.join(tmpdir, os.path.basename(f)) for f in rollback_files] yield tx_files, rollback_files def _normalize_args(data_and_files): data, files = _get_args(data_and_files) rollback_files = [f for f in _flatten(files) if f] return (data, rollback_files) def _get_args(data_and_files): if isinstance(data_and_files[0], dict): return data_and_files[0], data_and_files[1:] return None, data_and_files def _flatten(iterable): for elem in iterable: if isinstance(elem, (tuple, list)): for i in elem: yield i else: yield elem bcbio-nextgen-1.2.9/bcbio/dragen/000077500000000000000000000000001415626112400165675ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/dragen/__init__.py000066400000000000000000000000001415626112400206660ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/dragen/dragen.py000066400000000000000000000070201415626112400204000ustar00rootroot00000000000000import os import pysam from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction from bcbio.utils import file_exists, splitext_plus from bcbio import bam, broad from bcbio.log import logger def fix_umi_dragen_bam(data, bam=None): """ fixes the UMI BAM from DRAGEN. Accepts a pre UMI collapsed BAM file and adds several missing tags needed to use fgbio's UMI tools """ if not bam: bam = dd.get_work_bam(data) base, ext = os.path.splitext(bam) sample_name = dd.get_sample_name(data) out_bam = os.path.join(dd.get_work_dir(data), "align", sample_name, sample_name + "-fgbio" + ext) out_bam = add_fgbio_tags(bam, out_bam, data) data = dd.set_work_bam(data, out_bam) return data def add_fgbio_tags(in_bam, out_bam, data): """ Add missing MC (mate cigar), MQ (mate quality) and RX (UMI) tags to a DRAGEN BAM file """ if has_fgbio_tags(in_bam): logger.info(f"{in_bam} is properly formatted to run fgbio.") return in_bam if file_exists(out_bam): return out_bam samtools = config_utils.get_program("samtools", data) bamsormadup = config_utils.get_program("bamsormadup", data) fgbio = config_utils.get_program("fgbio", data) with file_transaction(out_bam) as tx_out_bam: tmpdir = os.path.dirname(tx_out_bam) jvm_opts = _get_fgbio_jvm_opts(data, tmpdir, 1) tx_out_dup = "%s-markdup" % splitext_plus(tx_out_bam)[0] cmd = (f"{samtools} view -b {in_bam} | " f"{bamsormadup} outputformat=sam tmpfile={tx_out_dup} | " f"awk '/^@/ {{print;next}} {{N=split($1,n,\":\");print $0 \"\tRX:Z:\" n[N]}}' | " f"{fgbio} {jvm_opts} SortBam -i /dev/stdin -o /dev/stdout -s Queryname |" f"{fgbio} {jvm_opts} SetMateInformation | " f"{fgbio} {jvm_opts} SortBam -i /dev/stdin -o /dev/stdout -s Coordinate |" f"{samtools} view -bh > {tx_out_bam}") message = f"Adding MC/MQ/RX tags to DRAGEN BAM file {in_bam}." do.run(cmd, message) return out_bam def has_fgbio_tags(in_bam): """ Checks to see if the MC/MQ or RX tag are present """ FGBIO_TAGS = set(["MC", "MQ", "RX"]) return bam.has_tags(in_bam, FGBIO_TAGS) def _get_fgbio_jvm_opts(data, tmpdir, scale_factor=None): cores, mem = _get_cores_memory(data) resources = config_utils.get_resources("fgbio", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx4g"]) if scale_factor and cores > scale_factor: jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": {"direction": "increase", "magnitude": cores // scale_factor}}}) jvm_opts += broad.get_default_jvm_opts() jvm_opts = " ".join(jvm_opts) return jvm_opts + " --tmp-dir %s" % tmpdir def _get_cores_memory(data, downscale=2): """Retrieve cores and memory, using samtools as baseline. For memory, scaling down because we share with alignment and de-duplication. """ resources = config_utils.get_resources("samtools", data["config"]) num_cores = data["config"]["algorithm"].get("num_cores", 1) max_mem = config_utils.adjust_memory(resources.get("memory", "2G"), downscale, "decrease").upper() return num_cores, max_mem bcbio-nextgen-1.2.9/bcbio/galaxy/000077500000000000000000000000001415626112400166145ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/galaxy/__init__.py000066400000000000000000000000711415626112400207230ustar00rootroot00000000000000"""Shared functionality for interacting with Galaxy. """ bcbio-nextgen-1.2.9/bcbio/galaxy/api.py000066400000000000000000000054521415626112400177450ustar00rootroot00000000000000"""Access Galaxy NGLIMS functionality via the standard API. """ from six.moves import urllib import json import time class GalaxyApiAccess: """Simple front end for accessing Galaxy's REST API. """ def __init__(self, galaxy_url, api_key): self._base_url = galaxy_url self._key = api_key self._max_tries = 5 def _make_url(self, rel_url, params=None): if not params: params = dict() params['key'] = self._key vals = urllib.parse.urlencode(params) return ("%s%s" % (self._base_url, rel_url), vals) def _get(self, url, params=None): url, params = self._make_url(url, params) num_tries = 0 while 1: response = urllib.request.urlopen("%s?%s" % (url, params)) try: out = json.loads(response.read()) break except ValueError as msg: if num_tries > self._max_tries: raise time.sleep(3) num_tries += 1 return out def _post(self, url, data, params=None, need_return=True): url, params = self._make_url(url, params) request = urllib.request.Request("%s?%s" % (url, params), headers = {'Content-Type' : 'application/json'}, data = json.dumps(data)) response = urllib.request.urlopen(request) try: data = json.loads(response.read()) except ValueError: if need_return: raise else: data = {} return data def run_details(self, run_bc, run_date=None): """Next Gen LIMS specific API functionality. """ try: details = self._get("/nglims/api_run_details", dict(run=run_bc)) except ValueError: raise ValueError("Could not find information in Galaxy for run: %s" % run_bc) if "error" in details and run_date is not None: try: details = self._get("/nglims/api_run_details", dict(run=run_date)) except ValueError: raise ValueError("Could not find information in Galaxy for run: %s" % run_date) return details def sequencing_projects(self): """Next Gen LIMS: retrieve summary information of sequencing projects. """ return self._get("/nglims/api_projects") def sqn_run_summary(self, run_info): """Next Gen LIMS: Upload sequencing run summary information. """ return self._post("/nglims/api_upload_sqn_run_summary", data=run_info) def sqn_report(self, start_date, end_date): """Next Gen LIMS: report of items sequenced in a time period. """ return self._get("/nglims/api_sqn_report", dict(start=start_date, end=end_date)) bcbio-nextgen-1.2.9/bcbio/galaxy/loc.py000066400000000000000000000061501415626112400177450ustar00rootroot00000000000000""" functions for finding, retrieving data from and updating the Galaxy .loc files """ import os from bcbio.utils import file_exists import tempfile import shutil REF_FILES = {"bwa": "bwa_index.loc", "bowtie": "bowtie_indices.loc", "samtools": "sam_fa_indices.loc", "maq": "bowtie_indices.loc", "seq": "alignseq.loc", "bowtie2": "bowtie2_indices.loc"} def samtools_formatter(build, loc, name=None): return "\t".join(["index", build, loc]) + "\n" def ucsc_formatter(build, loc, name=None): return "\t".join(["seq", build, loc]) + "\n" def generic_formatter(build, loc, name=None): name = build if not name else name return "\t".join([build, build, name, loc]) + "\n" def get_locformatter(loc_type): if loc_type in ["samtools", "ucsc"]: return eval("%s_formatter" % loc_type) else: return generic_formatter def get_loc_file(galaxy_base, loc_type): loc_file = REF_FILES.get(loc_type, None) if not loc_file: return None return os.path.abspath(os.path.join(galaxy_base, "tool-data", loc_file)) def get_loc_files(galaxy_base): """ get dictionary of loc_type: loc_file, .loc files in the galaxy base for example: {"bwa": "/galaxy_base_path/tool-dir/bwa_index.loc"} """ return {k: os.path.join(galaxy_base, "tool-data", v) for k, v in REF_FILES.items()} def get_genome_refs(loc_file, loc_type): """ get dictionary of genome: location for all genomes of type in a .loc file for example: {'hg19': '/genomedir/Hsapiens/hg19/seq/hg19.fa'} """ if not file_exists(loc_file): return None refs = {} with open(loc_file) as in_handle: for line in in_handle: if not line.startswith("#"): parts = line.strip().split() if loc_type in ["bowtie2", "samtools", "alignseq"]: refs[parts[1]] = parts[-1] else: refs[parts[0]] = parts[-1] return refs def update_loc_file(galaxy_base, loc_type, genome_build, ref_loc): ref_loc = os.path.abspath(ref_loc) loc_file = get_loc_file(galaxy_base, loc_type) if not loc_file: return None formatter = get_locformatter(loc_type) builds = [] tmp_out = tempfile.NamedTemporaryFile(delete=False).name if file_exists(loc_file): with open(loc_file) as in_handle, open(tmp_out, "w") as out_handle: for line in in_handle: if line.startswith("#"): out_handle.write(line) else: parts = line.strip().split() build = parts[1] if len(parts) > 2 else None builds.append(build) if build != genome_build: out_handle.write(line) else: out_handle.write(formatter(genome_build, ref_loc)) shutil.copyfile(tmp_out, loc_file) if genome_build not in builds or not file_exists(loc_file): with open(loc_file, "a") as out_handle: out_handle.write(formatter(genome_build, ref_loc)) return loc_file bcbio-nextgen-1.2.9/bcbio/galaxy/nglims.py000066400000000000000000000175171415626112400204720ustar00rootroot00000000000000"""Integration with Galaxy nglims. """ from __future__ import print_function import collections import copy import glob import operator import os import subprocess import joblib import six import yaml from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.galaxy.api import GalaxyApiAccess from bcbio.illumina import flowcell from bcbio.pipeline.run_info import clean_name from bcbio.workflow import template from functools import reduce def prep_samples_and_config(run_folder, ldetails, fastq_dir, config): """Prepare sample fastq files and provide global sample configuration for the flowcell. Handles merging of fastq files split by lane and also by the bcl2fastq preparation process. """ fastq_final_dir = utils.safe_makedir(os.path.join(fastq_dir, "merged")) cores = utils.get_in(config, ("algorithm", "num_cores"), 1) ldetails = joblib.Parallel(cores)(joblib.delayed(_prep_sample_and_config)(x, fastq_dir, fastq_final_dir) for x in _group_same_samples(ldetails)) config_file = _write_sample_config(run_folder, [x for x in ldetails if x]) return config_file, fastq_final_dir def _prep_sample_and_config(ldetail_group, fastq_dir, fastq_final_dir): """Prepare output fastq file and configuration for a single sample. Only passes non-empty files through for processing. """ files = [] print("->", ldetail_group[0]["name"], len(ldetail_group)) for read in ["R1", "R2"]: fastq_inputs = sorted(list(set(reduce(operator.add, (_get_fastq_files(x, read, fastq_dir) for x in ldetail_group))))) if len(fastq_inputs) > 0: files.append(_concat_bgzip_fastq(fastq_inputs, fastq_final_dir, read, ldetail_group[0])) if len(files) > 0: if _non_empty(files[0]): out = ldetail_group[0] out["files"] = files return out def _non_empty(f): with utils.open_gzipsafe(f) as in_handle: for line in in_handle: return True return False def _write_sample_config(run_folder, ldetails): """Generate a bcbio-nextgen YAML configuration file for processing a sample. """ out_file = os.path.join(run_folder, "%s.yaml" % os.path.basename(run_folder)) with open(out_file, "w") as out_handle: fc_name, fc_date = flowcell.parse_dirname(run_folder) out = {"details": sorted([_prepare_sample(x, run_folder) for x in ldetails], key=operator.itemgetter("name", "description")), "fc_name": fc_name, "fc_date": fc_date} yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) return out_file def _prepare_sample(data, run_folder): """Extract passed keywords from input LIMS information. """ want = set(["description", "files", "genome_build", "name", "analysis", "upload", "algorithm"]) out = {} for k, v in data.items(): if k in want: out[k] = _relative_paths(v, run_folder) if "algorithm" not in out: analysis, algorithm = _select_default_algorithm(out.get("analysis")) out["algorithm"] = algorithm out["analysis"] = analysis description = "%s-%s" % (out["name"], clean_name(out["description"])) out["name"] = [out["name"], description] out["description"] = description return out def _select_default_algorithm(analysis): """Provide default algorithm sections from templates or standard """ if not analysis or analysis == "Standard": return "Standard", {"aligner": "bwa", "platform": "illumina", "quality_format": "Standard", "recalibrate": False, "realign": False, "mark_duplicates": True, "variantcaller": False} elif "variant" in analysis: try: config, _ = template.name_to_config(analysis) except ValueError: config, _ = template.name_to_config("freebayes-variant") return "variant", config["details"][0]["algorithm"] else: return analysis, {} def _relative_paths(xs, base_path): """Adjust paths to be relative to the provided base path. """ if isinstance(xs, six.string_types): if xs.startswith(base_path): return xs.replace(base_path + "/", "", 1) else: return xs elif isinstance(xs, (list, tuple)): return [_relative_paths(x, base_path) for x in xs] elif isinstance(xs, dict): out = {} for k, v in xs.items(): out[k] = _relative_paths(v, base_path) return out else: return xs def _get_fastq_files(ldetail, read, fastq_dir): """Retrieve fastq files corresponding to the sample and read number. """ return glob.glob(os.path.join(fastq_dir, "Project_%s" % ldetail["project_name"], "Sample_%s" % ldetail["name"], "%s_*_%s_*.fastq.gz" % (ldetail["name"], read))) def _concat_bgzip_fastq(finputs, out_dir, read, ldetail): """Concatenate multiple input fastq files, preparing a bgzipped output file. """ out_file = os.path.join(out_dir, "%s_%s.fastq.gz" % (ldetail["name"], read)) if not utils.file_exists(out_file): with file_transaction(out_file) as tx_out_file: subprocess.check_call("zcat %s | bgzip -c > %s" % (" ".join(finputs), tx_out_file), shell=True) return out_file def _group_same_samples(ldetails): """Move samples into groups -- same groups have identical names. """ sample_groups = collections.defaultdict(list) for ldetail in ldetails: sample_groups[ldetail["name"]].append(ldetail) return sorted(sample_groups.values(), key=lambda xs: xs[0]["name"]) def get_runinfo(galaxy_url, galaxy_apikey, run_folder, storedir): """Retrieve flattened run information for a processed directory from Galaxy nglims API. """ galaxy_api = GalaxyApiAccess(galaxy_url, galaxy_apikey) fc_name, fc_date = flowcell.parse_dirname(run_folder) galaxy_info = galaxy_api.run_details(fc_name, fc_date) if "error" in galaxy_info: return galaxy_info if not galaxy_info["run_name"].startswith(fc_date) and not galaxy_info["run_name"].endswith(fc_name): raise ValueError("Galaxy NGLIMS information %s does not match flowcell %s %s" % (galaxy_info["run_name"], fc_date, fc_name)) ldetails = _flatten_lane_details(galaxy_info) out = [] for item in ldetails: # Do uploads for all non-controls if item["description"] != "control" or item["project_name"] != "control": item["upload"] = {"method": "galaxy", "run_id": galaxy_info["run_id"], "fc_name": fc_name, "fc_date": fc_date, "dir": storedir, "galaxy_url": galaxy_url, "galaxy_api_key": galaxy_apikey} for k in ["lab_association", "private_libs", "researcher", "researcher_id", "sample_id", "galaxy_library", "galaxy_role"]: item["upload"][k] = item.pop(k, "") out.append(item) return out def _flatten_lane_details(runinfo): """Provide flattened lane information with multiplexed barcodes separated. """ out = [] for ldetail in runinfo["details"]: # handle controls if "project_name" not in ldetail and ldetail["description"] == "control": ldetail["project_name"] = "control" for i, barcode in enumerate(ldetail.get("multiplex", [{}])): cur = copy.deepcopy(ldetail) cur["name"] = "%s-%s" % (ldetail["name"], i + 1) cur["description"] = barcode.get("name", ldetail["description"]) cur["bc_index"] = barcode.get("sequence", "") cur["project_name"] = clean_name(ldetail["project_name"]) out.append(cur) return out bcbio-nextgen-1.2.9/bcbio/graph/000077500000000000000000000000001415626112400164305ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/graph/__init__.py000066400000000000000000000001311415626112400205340ustar00rootroot00000000000000"""Generate system graphs (CPU/memory/network/disk I/O consumption) from bcbio runs. """ bcbio-nextgen-1.2.9/bcbio/graph/collectl.py000066400000000000000000000271461415626112400206150ustar00rootroot00000000000000import calendar import glob import gzip import math import os.path import re import pandas as pd def _parse_raw(fp, start_tstamp, end_tstamp): import progressbar widgets = [ os.path.basename(fp.name), ': ', progressbar.Bar(marker='-', left='[', right=']'), ' ', progressbar.Percentage(), ' ', progressbar.ETA(), ] # We don't know what the file's uncompressed size will wind up being, # so take an educated guess and ignore the AssertionError later on # if it winds up being bigger than we guess. bar = progressbar.ProgressBar( widgets=widgets, maxval=os.path.getsize(fp.name) * 15) bar.start() bar.update(0) tstamp = 0 hardware = {} data = {} for line in fp: matches = re.search(r'^>>> (\d+).\d+ <<<', line) if matches: try: bar.update(fp.tell()) except AssertionError: pass tstamp = int(matches.group(1)) if (tstamp >= start_tstamp) or (tstamp <= end_tstamp): data[tstamp] = { 'disk': {}, 'mem': {}, 'net': {}, 'proc': {}, } continue if line.startswith('# SubSys: '): matches = re.search(r'\sNumCPUs: (\d+)\s+', line) if matches: hardware['num_cpus'] = int(matches.group(1)) continue if line.startswith('# Kernel: '): matches = re.search(r'\sMemory: (\d+)\s+kB', line) if matches: hardware['memory'] = int(math.ceil(float(matches.group(1)) / math.pow(1024.0, 2.0))) continue if (tstamp < start_tstamp) or (tstamp > end_tstamp): continue if line.startswith('cpu '): # Don't know what the last two fields are, but they # always seem to be 0, and collectl doesn't parse them # in formatit::dataAnalyze(). (title, user, nice, sys, idle, wait, irq, soft, steal) = line.split()[:9] data[tstamp]['cpu'] = { 'user': user, 'nice': nice, 'sys': sys, 'idle': idle, 'wait': wait, 'irq': irq, 'soft': soft, 'steal': steal, } elif line.startswith('disk '): (title, major, minor, node, num_reads, reads_merged, sectors_read, msec_spent_reading, num_writes, writes_merged, sectors_written, msec_spent_writing, iops_in_progress, msec_spent_on_iops, weighted_msec_spent_on_iops) = line.split() data[tstamp]['disk'][node] = { 'num_reads': num_reads, 'reads_merged': reads_merged, 'sectors_read': sectors_read, 'msec_spent_reading': msec_spent_reading, 'num_writes': num_writes, 'writes_merged': writes_merged, 'sectors_written': sectors_written, 'msec_spent_writing': msec_spent_writing, 'iops_in_progress': iops_in_progress, 'msec_spent_on_iops': msec_spent_on_iops, 'weighted_msec_spent_on_iops': weighted_msec_spent_on_iops, } elif line.startswith('Net '): # Older kernel versions don't have whitespace after # the interface colon: # # Net eth0:70627391 # # unlike newer kernels: # # Net eth0: 415699541 line = re.sub(r'^(Net\s+[^:]+):', r'\1: ', line) (title, iface, rbyte, rpkt, rerr, rdrop, rfifo, rframe, rcomp, rmulti, tbyte, tpkt, terr, tdrop, tfifo, tcoll, tcarrier, tcomp) = line.split() iface = iface.replace(':', '') data[tstamp]['net'][iface] = { 'rbyte': rbyte, 'rpkt': rpkt, 'rerr': rerr, 'rdrop': rdrop, 'rfifo': rfifo, 'rframe': rframe, 'rcomp': rcomp, 'rmulti': rmulti, 'tbyte': tbyte, 'tpkt': tpkt, 'terr': terr, 'tdrop': tdrop, 'tfifo': tfifo, 'tcoll': tcoll, 'tcarrier': tcarrier, 'tcomp': tcomp, } elif line.startswith('MemTotal:'): title, amount, unit = line.split() data[tstamp]['mem']['total'] = amount elif line.startswith('MemFree:'): title, amount, unit = line.split() data[tstamp]['mem']['free'] = amount elif line.startswith('Buffers:'): title, amount, unit = line.split() data[tstamp]['mem']['buffers'] = amount elif line.startswith('Cached:'): title, amount, unit = line.split() data[tstamp]['mem']['cached'] = amount # We don't currently do anything with process data, # so don't bother parsing it. elif False and line.startswith('proc:'): title_pid, rest = line.split(None, 1) title, pid = title_pid.split(':') if pid not in data[tstamp]['proc']: data[tstamp]['proc'][pid] = {} if rest.startswith('cmd '): title, cmd = rest.split(None, 1) data[tstamp]['proc'][pid]['cmd'] = cmd elif rest.startswith('io read_bytes: '): value = rest.split(':')[1].strip() data[tstamp]['proc'][pid]['read_bytes'] = value elif rest.startswith('io write_bytes: '): value = rest.split(':')[1].strip() data[tstamp]['proc'][pid]['write_bytes'] = value bar.finish() return hardware, data class _CollectlGunzip(gzip.GzipFile): """collectl writes data to its files incrementally, and doesn't add a CRC to the end until it rotates the log. Ignore the CRC errors; they're innocuous in this case. """ def _read_eof(self): return def load_collectl(pattern, start_time, end_time): """Read data from collectl data files into a pandas DataFrame. :pattern: Absolute path to raw collectl files """ start_tstamp = calendar.timegm(start_time.utctimetuple()) end_tstamp = calendar.timegm(end_time.utctimetuple()) cols = [] rows = [] for path in glob.glob(pattern): hardware, raw = _parse_raw( _CollectlGunzip(path, 'r'), start_tstamp, end_tstamp) if not cols: instances = { 'disk': set(), 'net': set(), 'proc': set(), } for tstamp, sample in raw.items(): for group, items in sample.items(): if group == 'disk': instances['disk'] = instances['disk'].union( items.keys()) elif group == 'net': instances['net'] = instances['net'].union( items.keys()) elif group == 'proc': instances['proc'] = instances['proc'].union( items.keys()) cols = ['tstamp'] cols.extend([ 'cpu_{}'.format(var) for var in ['user', 'nice', 'sys', 'idle', 'wait', 'irq', 'soft', 'steal'] ]) for node in instances['disk']: cols.extend([ '{}_{}'.format(node, var) for var in ['num_reads', 'reads_merged', 'sectors_read', 'msec_spent_reading', 'num_writes', 'writes_merged', 'sectors_written', 'msec_spent_writing', 'iops_in_progress', 'msec_spent_on_iops', 'weighted_msec_spent_on_iops'] ]) cols.extend([ 'mem_{}'.format(var) for var in ['total', 'free', 'buffers', 'cached'] ]) for iface in instances['net']: cols.extend([ '{}_{}'.format(iface, var) for var in ['rbyte', 'rpkt', 'rerr', 'rdrop', 'rfifo', 'rframe', 'rcomp', 'rmulti', 'tbyte', 'tpkt', 'terr', 'tdrop', 'tfifo', 'tcoll', 'tcarrier', 'tcomp'] ]) for pid in instances['proc']: cols.extend([ '{}_{}'.format(pid, var) for var in ['name', 'read_bytes', 'write_bytes'] ]) for tstamp, sample in raw.items(): if ('cpu' not in sample or 'disk' not in sample or 'mem' not in sample): # Skip incomplete samples; there might be a truncated # sample on the end of the file. continue values = [tstamp] values.extend([ sample['cpu']['user'], sample['cpu']['nice'], sample['cpu']['sys'], sample['cpu']['idle'], sample['cpu']['wait'], sample['cpu']['irq'], sample['cpu']['soft'], sample['cpu']['steal'], ]) for node in instances['disk']: data = sample['disk'].get(node, {}) values.extend([ data.get('num_reads', 0), data.get('reads_merged', 0), data.get('sectors_read', 0), data.get('msec_spent_reading', 0), data.get('num_writes', 0), data.get('writes_merged', 0), data.get('sectors_written', 0), data.get('msec_spent_writing', 0), data.get('iops_in_progress', 0), data.get('msec_spent_on_iops', 0), data.get('weighted_msec_spent_on_iops', 0), ]) values.extend([ sample['mem']['total'], sample['mem']['free'], sample['mem']['buffers'], sample['mem']['cached'], ]) for iface in instances['net']: data = sample['net'].get(iface, {}) values.extend([ data.get('rbyte', 0), data.get('rpkt', 0), data.get('rerr', 0), data.get('rdrop', 0), data.get('rfifo', 0), data.get('rframe', 0), data.get('rcomp', 0), data.get('rmulti', 0), data.get('tbyte', 0), data.get('tpkt', 0), data.get('terr', 0), data.get('tdrop', 0), data.get('tfifo', 0), data.get('tcoll', 0), data.get('tcarrier', 0), data.get('tcomp', 0), ]) if 'proc' in sample: for pid in instances['proc']: data = sample['proc'].get(pid, {}) values.extend([ data.get('cmd', ''), data.get('read_bytes', 0), data.get('write_bytes', 0), ]) rows.append(values) if len(rows) == 0: return pd.DataFrame(columns=cols), {} df = pd.DataFrame(rows, columns=cols) df = df.convert_objects(convert_numeric=True) df['tstamp'] = df['tstamp'].astype('datetime64[s]') df.set_index('tstamp', inplace=True) df = df.tz_localize('UTC') return df, hardware bcbio-nextgen-1.2.9/bcbio/graph/graph.py000066400000000000000000000355111415626112400201100ustar00rootroot00000000000000from __future__ import print_function from datetime import datetime import collections import functools import os import gzip import pytz import re import socket import pandas as pd import pickle from bcbio import utils from bcbio.graph.collectl import load_collectl mpl = utils.LazyImport("matplotlib") plt = utils.LazyImport("matplotlib.pyplot") pylab = utils.LazyImport("pylab") def _setup_matplotlib(): # plt.style.use('ggplot') mpl.use('Agg') pylab.rcParams['image.cmap'] = 'viridis' pylab.rcParams['figure.figsize'] = (35.0, 12.0) # pylab.rcParams['figure.figsize'] = (100, 100) pylab.rcParams['figure.dpi'] = 300 pylab.rcParams['font.size'] = 25 def get_bcbio_nodes(path): """Fetch the local nodes (-c local) that contain collectl files from the bcbio log file. :returns: A list with unique (non-FQDN) local hostnames where collectl raw logs can be found. """ with open(path, 'r') as file_handle: hosts = collections.defaultdict(dict) for line in file_handle: matches = re.search(r'\]\s([^:]+):', line) if not matches: continue # Format of the record will be "[Date] host: Timing: Step" if distributed, # otherwise the host will be missing and it means its a local run, we can stop elif 'Timing: ' in line and line.split(': ')[1] != 'Timing': hosts = collections.defaultdict(dict, {socket.gethostname() : {}}) break hosts[matches.group(1)] return hosts def get_bcbio_timings(path): """Fetch timing information from a bcbio log file.""" with open(path, 'r') as file_handle: steps = {} for line in file_handle: matches = re.search(r'^\[([^\]]+)\] ([^:]+: .*)', line) if not matches: continue tstamp = matches.group(1) msg = matches.group(2) # XXX: new special logs do not have this #if not msg.find('Timing: ') >= 0: # continue when = datetime.strptime(tstamp, '%Y-%m-%dT%H:%MZ').replace( tzinfo=pytz.timezone('UTC')) step = msg.split(":")[-1].strip() steps[when] = step return steps def plot_inline_jupyter(plot): """ Plots inside the output cell of a jupyter notebook if %matplotlib magic is defined. """ _setup_matplotlib() try: get_ipython() plt.show(plot) except NameError: pass def this_and_prev(iterable): """Walk an iterable, returning the current and previous items as a two-tuple.""" try: item = next(iterable) while True: next_item = next(iterable) yield item, next_item item = next_item except StopIteration: return def delta_from_prev(prev_values, tstamps, value): try: prev_val = next(prev_values) cur_tstamp, prev_tstamp = next(tstamps) except StopIteration: return 0 # Take the difference from the previous value and divide by the interval # since the previous sample, so we always return values in units/second. return (prev_val - value) / (prev_tstamp - cur_tstamp).seconds def calc_deltas(data_frame, series=None): """Many of collectl's data values are cumulative (monotonically increasing), so subtract the previous value to determine the value for the current interval. """ series = series or [] data_frame = data_frame.sort_index(ascending=True) for s in series: prev_values = iter(data_frame[s]) # Burn the first value, so the first row we call delta_from_prev() # for gets its previous value from the second row in the series, # and so on. next(prev_values) data_frame[s] = data_frame[s].apply(functools.partial( delta_from_prev, iter(prev_values), this_and_prev(iter(data_frame.index)))) return data_frame def remove_outliers(series, stddev): """Remove the outliers from a series.""" return series[(series - series.mean()).abs() < stddev * series.std()] def prep_for_graph(data_frame, series=None, delta_series=None, smoothing=None, outlier_stddev=None): """Prepare a dataframe for graphing by calculating deltas for series that need them, resampling, and removing outliers. """ series = series or [] delta_series = delta_series or [] graph = calc_deltas(data_frame, delta_series) for s in series + delta_series: if smoothing: graph[s] = graph[s].resample(smoothing) if outlier_stddev: graph[s] = remove_outliers(graph[s], outlier_stddev) return graph[series + delta_series] def add_common_plot_features(plot, steps): """Add plot features common to all plots, such as bcbio step information. """ _setup_matplotlib() plot.yaxis.set_tick_params(labelright=True) plot.set_xlabel('') ymax = plot.get_ylim()[1] ticks = {} for tstamp, step in steps.items(): if step == 'finished': continue plot.vlines(tstamp, 0, ymax, linestyles='dashed') tstamp = mpl.dates.num2epoch(mpl.dates.date2num(tstamp)) ticks[tstamp] = step tick_kvs = sorted(ticks.items()) top_axis = plot.twiny() top_axis.set_xlim(*plot.get_xlim()) top_axis.set_xticks([k for k, v in tick_kvs]) top_axis.set_xticklabels([v for k, v in tick_kvs], rotation=45, ha='left', size=pylab.rcParams['font.size']) plot.set_ylim(0) return plot def graph_cpu(data_frame, steps, num_cpus): graph = prep_for_graph( data_frame, delta_series=['cpu_user', 'cpu_sys', 'cpu_wait']) graph['cpu_user'] /= 100.0 graph['cpu_sys'] /= 100.0 graph['cpu_wait'] /= 100.0 plot = graph.plot() plot.set_ylabel('CPU core usage') plot.set_ylim(0, num_cpus) add_common_plot_features(plot, steps) plot_inline_jupyter(plot) return plot, graph def graph_net_bytes(data_frame, steps, ifaces): series = [] for iface in ifaces: series.extend(['{}_rbyte'.format(iface), '{}_tbyte'.format(iface)]) graph = prep_for_graph(data_frame, delta_series=series) for iface in ifaces: old_series = '{}_rbyte'.format(iface) new_series = '{}_receive'.format(iface) graph[new_series] = graph[old_series] * 8 / 1024 / 1024 del graph[old_series] old_series = '{}_tbyte'.format(iface) new_series = '{}_transmit'.format(iface) graph[new_series] = graph[old_series] * 8 / 1024 / 1024 del graph[old_series] plot = graph.plot() plot.set_ylabel('mbits/s') plot.set_ylim(0, 2000) add_common_plot_features(plot, steps) plot_inline_jupyter(plot) return plot, graph def graph_net_pkts(data_frame, steps, ifaces): series = [] for iface in ifaces: series.extend(['{}_rpkt'.format(iface), '{}_tpkt'.format(iface)]) graph = prep_for_graph(data_frame, delta_series=series) plot = graph.plot() plot.set_ylabel('packets/s') add_common_plot_features(plot, steps) plot_inline_jupyter(plot) return plot, graph def graph_memory(data_frame, steps, total_mem): graph = prep_for_graph( data_frame, series=['mem_total', 'mem_free', 'mem_buffers', 'mem_cached']) free_memory = graph['mem_free'] + graph['mem_buffers'] + \ graph['mem_cached'] graph = (graph['mem_total'] - free_memory) / 1024 / 1024 plot = graph.plot() plot.set_ylabel('gbytes') plot.set_ylim(0, total_mem) add_common_plot_features(plot, steps) plot_inline_jupyter(plot) return plot, graph def graph_disk_io(data_frame, steps, disks): series = [] for disk in disks: series.extend([ '{}_sectors_read'.format(disk), '{}_sectors_written'.format(disk), ]) graph = prep_for_graph(data_frame, delta_series=series, outlier_stddev=2) for disk in disks: old_series = '{}_sectors_read'.format(disk) new_series = '{}_read'.format(disk) graph[new_series] = graph[old_series] * 512 / 1024 / 1024 del graph[old_series] old_series = '{}_sectors_written'.format(disk) new_series = '{}_write'.format(disk) graph[new_series] = graph[old_series] * 512 / 1024 / 1024 del graph[old_series] plot = graph.plot() plot.set_ylabel('mbytes/s') add_common_plot_features(plot, steps) plot_inline_jupyter(plot) return plot, graph def log_time_frame(bcbio_log): """The bcbio running time frame. :return: an instance of :class collections.namedtuple: with the following fields: start and end """ output = collections.namedtuple("Time", ["start", "end", "steps"]) bcbio_timings = get_bcbio_timings(bcbio_log) return output(min(bcbio_timings), max(bcbio_timings), bcbio_timings) def rawfile_within_timeframe(rawfile, timeframe): """ Checks whether the given raw filename timestamp falls within [start, end] timeframe. """ matches = re.search(r'-(\d{8})-', rawfile) if matches: ftime = datetime.strptime(matches.group(1), "%Y%m%d") ftime = pytz.utc.localize(ftime) return ftime.date() >= timeframe[0].date() and ftime.date() <= timeframe[1].date() def resource_usage(bcbio_log, cluster, rawdir, verbose): """Generate system statistics from bcbio runs. Parse the obtained files and put the information in a :class pandas.DataFrame:. :param bcbio_log: local path to bcbio log file written by the run :param cluster: :param rawdir: directory to put raw data files :param verbose: increase verbosity :return: a tuple with three dictionaries, the first one contains an instance of :pandas.DataFrame: for each host, the second one contains information regarding the hardware configuration and the last one contains information regarding timing. :type return: tuple """ data_frames = {} hardware_info = {} time_frame = log_time_frame(bcbio_log) for collectl_file in sorted(os.listdir(rawdir)): if not collectl_file.endswith('.raw.gz'): continue # Only load filenames within sampling timerange (gathered from bcbio_log time_frame) if rawfile_within_timeframe(collectl_file, time_frame): collectl_path = os.path.join(rawdir, collectl_file) data, hardware = load_collectl( collectl_path, time_frame.start, time_frame.end) if len(data) == 0: #raise ValueError("No data present in collectl file %s, mismatch in timestamps between raw collectl and log file?", collectl_path) continue host = re.sub(r'-\d{8}-\d{6}\.raw\.gz$', '', collectl_file) hardware_info[host] = hardware if host not in data_frames: data_frames[host] = data else: data_frames[host] = pd.concat([data_frames[host], data]) return (data_frames, hardware_info, time_frame.steps) def generate_graphs(data_frames, hardware_info, steps, outdir, verbose=False): """Generate all graphs for a bcbio run.""" _setup_matplotlib() # Hash of hosts containing (data, hardware, steps) tuple collectl_info = collections.defaultdict(dict) for host, data_frame in data_frames.items(): if verbose: print('Generating CPU graph for {}...'.format(host)) graph, data_cpu = graph_cpu(data_frame, steps, hardware_info[host]['num_cpus']) graph.get_figure().savefig( os.path.join(outdir, '{}_cpu.png'.format(host)), bbox_inches='tight', pad_inches=0.25) pylab.close() ifaces = set([series.split('_')[0] for series in data_frame.keys() if series.startswith(('eth', 'ib'))]) if verbose: print('Generating network graphs for {}...'.format(host)) graph, data_net_bytes = graph_net_bytes(data_frame, steps, ifaces) graph.get_figure().savefig( os.path.join(outdir, '{}_net_bytes.png'.format(host)), bbox_inches='tight', pad_inches=0.25) pylab.close() graph, data_net_pkts = graph_net_pkts(data_frame, steps, ifaces) graph.get_figure().savefig( os.path.join(outdir, '{}_net_pkts.png'.format(host)), bbox_inches='tight', pad_inches=0.25) pylab.close() if verbose: print('Generating memory graph for {}...'.format(host)) graph, data_mem = graph_memory(data_frame, steps, hardware_info[host]["memory"]) graph.get_figure().savefig( os.path.join(outdir, '{}_memory.png'.format(host)), bbox_inches='tight', pad_inches=0.25) pylab.close() if verbose: print('Generating storage I/O graph for {}...'.format(host)) drives = set([ series.split('_')[0] for series in data_frame.keys() if series.startswith(('sd', 'vd', 'hd', 'xvd')) ]) graph, data_disk = graph_disk_io(data_frame, steps, drives) graph.get_figure().savefig( os.path.join(outdir, '{}_disk_io.png'.format(host)), bbox_inches='tight', pad_inches=0.25) pylab.close() print('Serializing output to pickle object for node {}...'.format(host)) # "Clean" dataframes ready to be plotted collectl_info[host] = { "hardware": hardware_info, "steps": steps, "cpu": data_cpu, "mem": data_mem, "disk": data_disk, "net_bytes": data_net_bytes, "net_pkts": data_net_pkts } return collectl_info def serialize_plot_data(collectl_info, pre_graph_info, outdir, fname="collectl_info.pickle.gz"): # Useful to regenerate and slice graphs quickly and/or inspect locally collectl_pickle = os.path.join(outdir, fname) print("Saving plot pickle file with all hosts on: {}".format(collectl_pickle)) with gzip.open(collectl_pickle, "wb") as f: pickle.dump((collectl_info, pre_graph_info), f) def add_subparser(subparsers): parser = subparsers.add_parser( "graph", help=("Generate system graphs (CPU/memory/network/disk I/O " "consumption) from bcbio runs")) parser.add_argument( "log", help="Local path to bcbio log file written by the run.") parser.add_argument( "-o", "--outdir", default="monitoring/graphs", help="Directory to write graphs to.") parser.add_argument( "-r", "--rawdir", default="monitoring/collectl", required=True, help="Directory to put raw collectl data files.") parser.add_argument( "-v", "--verbose", action="store_true", default=False, help="Emit verbose output") return parser bcbio-nextgen-1.2.9/bcbio/heterogeneity/000077500000000000000000000000001415626112400202025ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/heterogeneity/__init__.py000066400000000000000000000133311415626112400223140ustar00rootroot00000000000000"""Calculate heterogeneity and sub-clonal populations for complex input samples. Use allele frequencies, copy number calls and structural variants to infer sub-clonal populations within a potentially mixed population. This attempts to infer these sub-clones to help improve variant calls and interpretation especially in complex cancer samples. """ from __future__ import print_function import collections import os from bcbio import utils from bcbio.heterogeneity import bubbletree, phylowgs, theta from bcbio.pipeline import datadict as dd from bcbio.variation import vcfutils def _get_calls(data, cnv_only=False): """Retrieve calls, organized by name, to use for heterogeneity analysis. """ cnvs_supported = set(["cnvkit", "battenberg"]) out = {} for sv in data.get("sv", []): if not cnv_only or sv["variantcaller"] in cnvs_supported: out[sv["variantcaller"]] = sv return out def get_variants(data, include_germline=False): """Retrieve set of variant calls to use for heterogeneity analysis. """ data = utils.deepish_copy(data) supported = ["precalled", "vardict", "vardict-java", "vardict-perl", "freebayes", "octopus", "strelka2"] # Right now mutect2 and mutect do not provide heterozygous germline calls # to be useful https://github.com/bcbio/bcbio-nextgen/issues/2464 # supported += ["mutect2", "mutect"] if include_germline: supported.insert(1, "gatk-haplotype") out = [] # CWL based input if isinstance(data.get("variants"), dict) and "samples" in data["variants"]: cur_vs = [] # Unpack single sample list of files if (isinstance(data["variants"]["samples"], (list, tuple)) and len(data["variants"]["samples"]) == 1 and isinstance(data["variants"]["samples"][0], (list, tuple))): data["variants"]["samples"] = data["variants"]["samples"][0] for fname in data["variants"]["samples"]: variantcaller = utils.splitext_plus(os.path.basename(fname))[0] variantcaller = variantcaller.replace(dd.get_sample_name(data) + "-", "") for batch in dd.get_batches(data): variantcaller = variantcaller.replace(batch + "-", "") cur_vs.append({"vrn_file": fname, "variantcaller": variantcaller}) data["variants"] = cur_vs for v in data.get("variants", []): if v["variantcaller"] in supported and v.get("vrn_file"): out.append((supported.index(v["variantcaller"]), v)) out.sort() return [xs[1] for xs in out] def _ready_for_het_analysis(items): """Check if a sample has input information for heterogeneity analysis. We currently require a tumor/normal sample containing both CNV and variant calls. """ paired = vcfutils.get_paired_bams([dd.get_align_bam(d) for d in items], items) has_het = any(dd.get_hetcaller(d) for d in items) if has_het and paired: return get_variants(paired.tumor_data) and _get_calls(paired.tumor_data, cnv_only=True) def _get_batches(data): batches = dd.get_batch(data) or dd.get_sample_name(data) if not isinstance(batches, (list, tuple)): batches = [batches] return batches def _group_by_batches(items): out = collections.OrderedDict() for data in (utils.to_single_data(xs) for xs in items): for b in _get_batches(data): try: out[b].append(data) except KeyError: out[b] = [data] return out def _get_hetcallers(items): out = set([]) for d in items: hetcaller = dd.get_hetcaller(d) if hetcaller: out = out.union(set(hetcaller)) return sorted(list(out)) def estimate(items, batch, config): """Estimate heterogeneity for a pair of tumor/normal samples. Run in parallel. """ hetcallers = {"theta": theta.run, "phylowgs": phylowgs.run, "bubbletree": bubbletree.run} paired = vcfutils.get_paired_bams([dd.get_align_bam(d) for d in items], items) calls = _get_calls(paired.tumor_data) variants = get_variants(paired.tumor_data) het_info = [] for hetcaller in _get_hetcallers(items): try: hetfn = hetcallers[hetcaller] except KeyError: hetfn = None print("%s not yet implemented" % hetcaller) if hetfn: hetout = hetfn(variants[0], calls, paired) if hetout: het_info.append(hetout) out = [] for data in items: if batch == _get_batches(data)[0]: if dd.get_sample_name(data) == paired.tumor_name: if het_info: data["heterogeneity"] = het_info out.append([data]) return out def run(items, run_parallel): """Top level entry point for calculating heterogeneity, handles organization and job distribution. """ to_process = [] extras = [] for batch, cur_items in _group_by_batches(items).items(): if _ready_for_het_analysis(cur_items): to_process.append((batch, cur_items)) else: for data in cur_items: extras.append([data]) processed = run_parallel("heterogeneity_estimate", ([xs, b, xs[0]["config"]] for b, xs in to_process)) return _group_by_sample_and_batch(extras + processed) def _group_by_sample_and_batch(samples): """Group samples split by heterogeneity method back one per sample-batch. Groups potentially multiple shared samples (multi batch normals) into single items per group. """ out = collections.defaultdict(list) for data in [utils.to_single_data(x) for x in samples]: out[(dd.get_sample_name(data), dd.get_align_bam(data), tuple(_get_batches(data)))].append(data) return [[xs[0]] for xs in out.values()] bcbio-nextgen-1.2.9/bcbio/heterogeneity/bubbletree.py000066400000000000000000000527251415626112400227020ustar00rootroot00000000000000"""Estimate tumor purity and frequency using copy number and allele freqencies with BubbleTree. http://www.bioconductor.org/packages/release/bioc/html/BubbleTree.html http://www.bioconductor.org/packages/release/bioc/vignettes/BubbleTree/inst/doc/BubbleTree-vignette.html """ from __future__ import print_function import collections import csv import os import re import subprocess import numpy as np import pysam import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.heterogeneity import chromhacks from bcbio.structural import shared from bcbio.variation import bedutils population_keys = ['AC_AFR', 'AC_AMR', 'AC_EAS', 'AC_FIN', 'AC_NFE', 'AC_OTH', 'AC_SAS'] PARAMS = {"min_freq": 0.2, "max_freq": 0.8, "tumor_only": {"min_freq": 0.10, "max_freq": 0.90}, "min_depth": 15, "hetblock": {"min_alleles": 25, "allowed_misses": 2}} def run(vrn_info, calls_by_name, somatic_info, do_plots=True, handle_failures=True): """Run BubbleTree given variant calls, CNVs and somatic """ if "seq2c" in calls_by_name: cnv_info = calls_by_name["seq2c"] elif "cnvkit" in calls_by_name: cnv_info = calls_by_name["cnvkit"] else: raise ValueError("BubbleTree only currently support CNVkit and Seq2c: %s" % ", ".join(calls_by_name.keys())) work_dir = _cur_workdir(somatic_info.tumor_data) class OutWriter: def __init__(self, out_handle): self.writer = csv.writer(out_handle) def write_header(self): self.writer.writerow(["chrom", "start", "end", "freq"]) def write_row(self, rec, stats): self.writer.writerow([_to_ucsc_style(rec.chrom), rec.start, rec.stop, stats["tumor"]["freq"]]) vcf_csv = prep_vrn_file(vrn_info["vrn_file"], vrn_info["variantcaller"], work_dir, somatic_info, OutWriter, cnv_info["cns"]) cnv_csv = _prep_cnv_file(cnv_info["cns"], cnv_info["variantcaller"], work_dir, somatic_info.tumor_data) wide_lrr = cnv_info["variantcaller"] == "cnvkit" and somatic_info.normal_bam is None return _run_bubbletree(vcf_csv, cnv_csv, somatic_info.tumor_data, wide_lrr, do_plots, handle_failures) def _run_bubbletree(vcf_csv, cnv_csv, data, wide_lrr=False, do_plots=True, handle_failures=True): """Create R script and run on input data BubbleTree has some internal hardcoded paramters that assume a smaller distribution of log2 scores. This is not true for tumor-only calls, so if we specify wide_lrr we scale the calculations to actually get calls. Need a better long term solution with flexible parameters. """ lrr_scale = 10.0 if wide_lrr else 1.0 local_sitelib = utils.R_sitelib() base = utils.splitext_plus(vcf_csv)[0] r_file = "%s-run.R" % base bubbleplot_out = "%s-bubbleplot.pdf" % base trackplot_out = "%s-trackplot.pdf" % base calls_out = "%s-calls.rds" % base freqs_out = "%s-bubbletree_prevalence.txt" % base sample = dd.get_sample_name(data) do_plots = "yes" if do_plots else "no" with open(r_file, "w") as out_handle: out_handle.write(_script.format(**locals())) if not utils.file_exists(freqs_out): cmd = "%s && %s --vanilla %s" % (utils.get_R_exports(), utils.Rscript_cmd(), r_file) try: do.run(cmd, "Assess heterogeneity with BubbleTree") except subprocess.CalledProcessError as msg: if handle_failures and _allowed_bubbletree_errorstates(str(msg)): with open(freqs_out, "w") as out_handle: out_handle.write('bubbletree failed:\n %s"\n' % (str(msg))) else: logger.exception() raise return {"caller": "bubbletree", "report": freqs_out, "plot": {"bubble": bubbleplot_out, "track": trackplot_out}} def _allowed_bubbletree_errorstates(msg): allowed = ["Error in p[i, ] : subscript out of bounds", "replacement has .* rows, data has"] return any([len(re.findall(m, msg)) > 0 for m in allowed]) def _cns_to_coords(line): chrom, start, end = line.split()[:3] return (chrom, start, end) def _prep_cnv_file(cns_file, svcaller, work_dir, data): """Create a CSV file of CNV calls with log2 and number of marks. """ in_file = cns_file out_file = os.path.join(work_dir, "%s-%s-prep.csv" % (utils.splitext_plus(os.path.basename(in_file))[0], svcaller)) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: with open(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: reader = csv.reader(in_handle, dialect="excel-tab") writer = csv.writer(out_handle) writer.writerow(["chrom", "start", "end", "num.mark", "seg.mean"]) header = next(reader) for line in reader: cur = dict(zip(header, line)) if chromhacks.is_autosomal(cur["chromosome"]): writer.writerow([_to_ucsc_style(cur["chromosome"]), cur["start"], cur["end"], cur["probes"], cur["log2"]]) return out_file def prep_vrn_file(in_file, vcaller, work_dir, somatic_info, writer_class, seg_file=None, params=None): """Select heterozygous variants in the normal sample with sufficient depth. writer_class implements write_header and write_row to write VCF outputs from a record and extracted tumor/normal statistics. """ data = somatic_info.tumor_data if not params: params = PARAMS out_file = os.path.join(work_dir, "%s-%s-prep.csv" % (utils.splitext_plus(os.path.basename(in_file))[0], vcaller)) if not utils.file_uptodate(out_file, in_file): # ready_bed = _identify_heterogeneity_blocks_seg(in_file, seg_file, params, work_dir, somatic_info) ready_bed = None if ready_bed and utils.file_exists(ready_bed): sub_file = _create_subset_file(in_file, ready_bed, work_dir, data) else: sub_file = in_file max_depth = max_normal_germline_depth(sub_file, params, somatic_info) with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: writer = writer_class(out_handle) writer.write_header() bcf_in = pysam.VariantFile(sub_file) for rec in bcf_in: stats = _is_possible_loh(rec, bcf_in, params, somatic_info, max_normal_depth=max_depth) if chromhacks.is_autosomal(rec.chrom) and stats is not None: writer.write_row(rec, stats) return out_file # thresholds for filtering normal samples based on depth # matches those used in PURPLE AMBER caller # https://github.com/hartwigmedical/hmftools/blob/a8c5dd2487c8c294c457eb8961c78e08c61a604a/amber/src/main/java/com/hartwig/hmftools/amber/AmberApplication.java#L41 NORMAL_FILTER_PARAMS = {"min_depth_percent": 0.5, "max_depth_percent": 1.5, "min_freq_narrow": 0.4, "max_freq_narrow": 0.65} def max_normal_germline_depth(in_file, params, somatic_info): """Calculate threshold for excluding potential heterozygotes based on normal depth. """ bcf_in = pysam.VariantFile(in_file) depths = [] for rec in bcf_in: stats = _is_possible_loh(rec, bcf_in, params, somatic_info) if tz.get_in(["normal", "depth"], stats): depths.append(tz.get_in(["normal", "depth"], stats)) if depths: return np.median(depths) * NORMAL_FILTER_PARAMS["max_depth_percent"] def _identify_heterogeneity_blocks_seg(in_file, seg_file, params, work_dir, somatic_info): """Identify heterogeneity blocks corresponding to segmentation from CNV input file. """ def _segment_by_cns(target_chrom, freqs, coords): with open(seg_file) as in_handle: reader = csv.reader(in_handle, dialect="excel-tab") next(reader) # header for cur_chrom, start, end in (xs[:3] for xs in reader): if cur_chrom == target_chrom: block_freqs = [] for i, (freq, coord) in enumerate(zip(freqs, coords)): if coord >= int(start) and coord < int(end): block_freqs.append(freq) elif coord >= int(end): break coords = coords[max(0, i - 1):] freqs = freqs[max(0, i - 1):] if len(block_freqs) > params["hetblock"]["min_alleles"]: yield start, end return _identify_heterogeneity_blocks_shared(in_file, _segment_by_cns, params, work_dir, somatic_info) def _identify_heterogeneity_blocks_hmm(in_file, params, work_dir, somatic_info): """Use a HMM to identify blocks of heterogeneity to use for calculating allele frequencies. The goal is to subset the genome to a more reasonable section that contains potential loss of heterogeneity or other allele frequency adjustment based on selection. """ def _segment_by_hmm(chrom, freqs, coords): cur_coords = [] for j, state in enumerate(_predict_states(freqs)): if state == 0: # heterozygote region if len(cur_coords) == 0: num_misses = 0 cur_coords.append(coords[j]) else: num_misses += 1 if num_misses > params["hetblock"]["allowed_misses"]: if len(cur_coords) >= params["hetblock"]["min_alleles"]: yield min(cur_coords), max(cur_coords) cur_coords = [] if len(cur_coords) >= params["hetblock"]["min_alleles"]: yield min(cur_coords), max(cur_coords) return _identify_heterogeneity_blocks_shared(in_file, _segment_by_hmm, params, work_dir, somatic_info) def _identify_heterogeneity_blocks_shared(in_file, segment_fn, params, work_dir, somatic_info): """Identify heterogeneity blocks corresponding to segmentation from CNV input file. """ out_file = os.path.join(work_dir, "%s-hetblocks.bed" % utils.splitext_plus(os.path.basename(in_file))[0]) if not utils.file_uptodate(out_file, in_file): with file_transaction(somatic_info.tumor_data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for chrom, freqs, coords in _freqs_by_chromosome(in_file, params, somatic_info): for start, end in segment_fn(chrom, freqs, coords): out_handle.write("%s\t%s\t%s\n" % (chrom, start, end)) return out_file def _predict_states(freqs): """Use frequencies to predict states across a chromosome. Normalize so heterozygote blocks are assigned state 0 and homozygous are assigned state 1. """ from hmmlearn import hmm freqs = np.column_stack([np.array(freqs)]) model = hmm.GaussianHMM(2, covariance_type="full") model.fit(freqs) states = model.predict(freqs) freqs_by_state = collections.defaultdict(list) for i, state in enumerate(states): freqs_by_state[state].append(freqs[i]) if np.median(freqs_by_state[0]) > np.median(freqs_by_state[1]): states = [0 if s == 1 else 1 for s in states] return states def _freqs_by_chromosome(in_file, params, somatic_info): """Retrieve frequencies across each chromosome as inputs to HMM. """ freqs = [] coords = [] cur_chrom = None with pysam.VariantFile(in_file) as bcf_in: for rec in bcf_in: if _is_biallelic_snp(rec) and _passes_plus_germline(rec) and chromhacks.is_autosomal(rec.chrom): if cur_chrom is None or rec.chrom != cur_chrom: if cur_chrom and len(freqs) > 0: yield cur_chrom, freqs, coords cur_chrom = rec.chrom freqs = [] coords = [] stats = _tumor_normal_stats(rec, somatic_info) if tz.get_in(["tumor", "depth"], stats, 0) > params["min_depth"]: # not a ref only call if len(rec.samples) == 0 or sum(rec.samples[somatic_info.tumor_name].allele_indices) > 0: freqs.append(tz.get_in(["tumor", "freq"], stats)) coords.append(rec.start) if cur_chrom and len(freqs) > 0: yield cur_chrom, freqs, coords def _create_subset_file(in_file, het_region_bed, work_dir, data): """Subset the VCF to a set of pre-calculated smaller regions. """ cnv_regions = shared.get_base_cnv_regions(data, work_dir) region_bed = bedutils.intersect_two(het_region_bed, cnv_regions, work_dir, data) out_file = os.path.join(work_dir, "%s-origsubset.bcf" % utils.splitext_plus(os.path.basename(in_file))[0]) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: regions = ("-R %s" % region_bed) if utils.file_exists(region_bed) else "" cmd = "bcftools view {regions} -o {tx_out_file} -O b {in_file}" do.run(cmd.format(**locals()), "Extract regions for BubbleTree frequency determination") return out_file def _to_ucsc_style(chrom): """BubbleTree assumes hg19 UCSC style chromosome inputs. """ return "chr%s" % chrom if not str(chrom).startswith("chr") else chrom def is_info_germline(rec): """Check if a variant record is germline based on INFO attributes. Works with VarDict's annotation of STATUS. """ if hasattr(rec, "INFO"): status = rec.INFO.get("STATUS", "").lower() else: status = rec.info.get("STATUS", "").lower() return status == "germline" or status.find("loh") >= 0 def _passes_plus_germline(rec, use_status=False): """Check if a record passes filters (but might be germline -- labelled with REJECT). """ if use_status and is_info_germline(rec): return True allowed = set(["PASS", "REJECT", "."]) if hasattr(rec, "FILTER"): if not rec.FILTER: filters = [] else: filters = [x for x in rec.FILTER.split(";") if x not in allowed] else: filters = [x for x in rec.filter.keys() if x not in allowed] return len(filters) == 0 def _is_biallelic_snp(rec): if hasattr(rec, "ALT"): return _is_snp(rec) and len(rec.ALT) == 1 else: return _is_snp(rec) and len(rec.alts) == 1 def _is_snp(rec): if hasattr(rec, "ALT"): return max([len(x) for x in rec.ALT + [rec.REF]]) == 1 else: return max([len(x) for x in rec.alleles]) == 1 def _tumor_normal_stats(rec, somatic_info, vcf_rec): """Retrieve depth and frequency of tumor and normal samples. """ out = {"normal": {"alt": None, "depth": None, "freq": None}, "tumor": {"alt": 0, "depth": 0, "freq": None}} if hasattr(vcf_rec, "samples"): samples = [(s, {}) for s in vcf_rec.samples] for fkey in ["AD", "AO", "RO", "AF", "DP"]: try: for i, v in enumerate(rec.format(fkey)): samples[i][1][fkey] = v except KeyError: pass # Handle INFO only inputs elif len(rec.samples) == 0: samples = [(somatic_info.tumor_name, None)] else: samples = rec.samples.items() for name, sample in samples: alt, depth, freq = sample_alt_and_depth(rec, sample) if depth is not None and freq is not None: if name == somatic_info.normal_name: key = "normal" elif name == somatic_info.tumor_name: key = "tumor" out[key]["freq"] = freq out[key]["depth"] = depth out[key]["alt"] = alt return out def _is_possible_loh(rec, vcf_rec, params, somatic_info, use_status=False, max_normal_depth=None): """Check if the VCF record is a het in the normal with sufficient support. Only returns SNPs, since indels tend to have less precise frequency measurements. """ if _is_biallelic_snp(rec) and _passes_plus_germline(rec, use_status=use_status): stats = _tumor_normal_stats(rec, somatic_info, vcf_rec) depths = [tz.get_in([x, "depth"], stats) for x in ["normal", "tumor"]] depths = [d for d in depths if d is not None] normal_freq = tz.get_in(["normal", "freq"], stats) tumor_freq = tz.get_in(["tumor", "freq"], stats) if all([d > params["min_depth"] for d in depths]): if max_normal_depth and tz.get_in(["normal", "depth"], stats, 0) > max_normal_depth: return None if normal_freq is not None: if normal_freq >= params["min_freq"] and normal_freq <= params["max_freq"]: return stats elif (tumor_freq >= params["tumor_only"]["min_freq"] and tumor_freq <= params["tumor_only"]["max_freq"]): if (vcf_rec and not _has_population_germline(vcf_rec)) or is_population_germline(rec): return stats def _has_population_germline(rec): """Check if header defines population annotated germline samples for tumor only. """ for k in population_keys: if k in rec.header.info: return True return False def is_population_germline(rec): """Identify a germline calls based on annoations with ExAC or other population databases. """ min_count = 50 for k in population_keys: if k in rec.info: val = rec.info.get(k) if "," in val: val = val.split(",")[0] if isinstance(val, (list, tuple)): val = max(val) if int(val) > min_count: return True return False def sample_alt_and_depth(rec, sample): """Flexibly get ALT allele and depth counts, handling FreeBayes, MuTect and other cases. """ if sample and "AD" in sample: all_counts = [int(x) for x in sample["AD"]] alt_counts = sum(all_counts[1:]) depth = sum(all_counts) elif sample and "AO" in sample and sample.get("RO") is not None: alts = sample["AO"] if not isinstance(alts, (list, tuple)): alts = [alts] alt_counts = sum([int(x) for x in alts]) depth = alt_counts + int(sample["RO"]) elif "DP" in rec.info and "AF" in rec.info: af = rec.info["AF"][0] if isinstance(rec.info["AF"], (tuple, list)) else rec.info["AF"] return None, rec.info["DP"], af else: alt_counts = None if alt_counts is None or depth is None or depth == 0: return None, None, None else: freq = float(alt_counts) / float(depth) return alt_counts, depth, freq def _cur_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "heterogeneity", dd.get_sample_name(data), "bubbletree")) if __name__ == "__main__": import sys bcf_in = pysam.VariantFile(sys.argv[1]) somatic = collections.namedtuple("Somatic", "normal_name,tumor_name") params = {"min_freq": 0.4, "max_freq": 0.6, "min_depth": 15} for rec in bcf_in: if _is_possible_loh(rec, bcf_in, params, somatic(sys.argv[2], sys.argv[3])): print(rec.filter.keys(), len(rec.filter)) _script = """ .libPaths(c("{local_sitelib}")) library(BubbleTree) library(GenomicRanges) library(ggplot2) vc.df = read.csv("{vcf_csv}", header=T) vc.gr = GRanges(vc.df$chrom, IRanges(vc.df$start, vc.df$end), freq=vc.df$freq, score=vc.df$freq) cnv.df = read.csv("{cnv_csv}", header=T) cnv.gr = GRanges(cnv.df$chrom, IRanges(cnv.df$start, cnv.df$end), num.mark=cnv.df$num.mark, seg.mean=cnv.df$seg.mean, score=cnv.df$seg.mean) print(vc.gr) print(cnv.gr) r <- new("RBD") rbd <- makeRBD(r, vc.gr, cnv.gr) rbd$lrr <- rbd$lrr / {lrr_scale} print(head(rbd)) calls <- new("BTreePredictor", rbd=rbd) calls <- btpredict(calls) saveRDS(calls, "{calls_out}") purity <- calls@result$prev[1] adj <- calls@result$ploidy.adj["adj"] # when purity is low the calculation result is not reliable ploidy <- (2*adj -2)/purity + 2 out <- data.frame(sample="{sample}", purity=round(purity,3), prevalences=paste(round(calls@result$prev,3), collapse=";"), tumor_ploidy=round(ploidy,1)) write.csv(out, file="{freqs_out}", row.names=FALSE) title <- sprintf("{sample} (%s)", info(calls)) # XXX Needs to be generalized for non-build 37/hg19 plots # hg19.seqinfo is hardcoded in TrackPlotter but we might # be able to work around with just an external centromere.dat import if ("{do_plots}" == "yes") {{ load(system.file("data", "centromere.dat.rda", package="BubbleTree")) load(system.file("data", "hg19.seqinfo.rda", package="BubbleTree")) trackplotter <- new("TrackPlotter") z1 <- heteroLociTrack(trackplotter, calls@result, centromere.dat, vc.gr) + ggplot2::labs(title=title) z2 <- RscoreTrack(trackplotter, calls@result, centromere.dat, cnv.gr) t2 <- getTracks(z1, z2) pdf(file="{trackplot_out}", width=8, height=6) g <- gridExtra::grid.arrange(t2, ncol=1) print(g) dev.off() pdf(file="{bubbleplot_out}", width=8, height=6) btreeplotter <- new("BTreePlotter") g <- drawBTree(btreeplotter, calls@rbd.adj) + ggplot2::labs(title=title) print(g) dev.off() }} """ bcbio-nextgen-1.2.9/bcbio/heterogeneity/chromhacks.py000066400000000000000000000056551415626112400227110ustar00rootroot00000000000000"""Hacks to handle subsetting of chromosomes for heterogeneity analysis. This puts ugly chromosome naming assumptions that restrict heterogeneity estimations to autosomal chromosomes in a single place. """ import os from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.bam import ref def is_autosomal(chrom): """Keep chromosomes that are a digit 1-22, or chr prefixed digit chr1-chr22 """ try: int(chrom) return True except ValueError: try: int(str(chrom.lower().replace("chr", "").replace("_", "").replace("-", ""))) return True except ValueError: return False def is_sex(chrom): return chrom in ["X", "chrX", "Y", "chrY"] def is_mitochondrial(chrom): return chrom in ["MT", "chrM", "chrMT"] def is_autosomal_or_x(chrom): return is_autosomal(chrom) or chrom in ["X", "chrX"] def is_autosomal_or_sex(chrom): return is_autosomal(chrom) or is_sex(chrom) def is_nonalt(chrom): """Check that a chromosome is on 1-22, X, Y, MT. """ return is_autosomal_or_sex(chrom) or is_mitochondrial(chrom) def bed_to_standardonly(in_file, data, headers=None, include_sex_chroms=False, out_dir=None): out_file = "%s-stdchrs%s" % utils.splitext_plus(in_file) if out_dir: out_file = os.path.join(out_dir, os.path.basename(out_file)) checkfn = is_autosomal_or_sex if include_sex_chroms else is_autosomal if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: for line in in_handle: if checkfn(line.split()[0]) or (headers and line.startswith(headers)): out_handle.write(line) return out_file def get_mitochondrial_chroms(data): ref_file = dd.get_ref_file(data) mito = [c.name for c in ref.file_contigs(ref_file) if is_mitochondrial(c.name)] return mito def get_nonmitochondrial_chroms(data): ref_file = dd.get_ref_file(data) nonmito = [c.name for c in ref.file_contigs(ref_file) if not is_mitochondrial(c.name)] return nonmito def get_EBV(data): EBVCONTIGS = ["chrEBV", "EBV"] ref_file = dd.get_ref_file(data) for c in ref.file_contigs(ref_file): if c.name in EBVCONTIGS: return c.name return False def is_alt(chrom): """ check if chromosome is an ALT """ return chrom.endswith("_alt") def is_hla(chrom): """ check if a chromosome is an HLA """ return chrom.startswith("HLA") def is_human(data): return dd.get_genome_build(data) in ["hg38", "GRCh37", "GRCh38", "hg19"] def is_mouse(data): return dd.get_genome_build(data) in ["mm10"] def get_hla_chroms(ref_file): hla = [c.name for c in ref.file_contigs(ref_file) if is_hla(c.name)] return hla bcbio-nextgen-1.2.9/bcbio/heterogeneity/loh.py000066400000000000000000000366521415626112400213520ustar00rootroot00000000000000"""Summarize amplification and loss of heterozygosity (LOH) from heterogeneity callers. Provides high level summaries of calls in regions of interest. """ import csv import collections import os import decimal import uuid import pandas as pd import six from six import StringIO import toolz as tz import yaml from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd # Standard sets of coordinates we always include _COORDS = {"LOH": {"hg38": {"HLA": ("chr6", 28510120, 33480577), "B2M": ("chr15", 44711487, 44718877)}, "hg19": {"HLA": ("chr6", 29640000, 33120000), "B2M": ("chr15", 45003675, 45011075)}, "GRCh37": {"HLA": ("6", 29640000, 33120000), "B2M": ("15", 45003675, 45011075)}}} def get_coords(data): """Retrieve coordinates of genes of interest for prioritization. Can read from CIViC input data or a supplied BED file of chrom, start, end and gene information. """ for category, vtypes in [("LOH", {"LOSS", "HETEROZYGOSITY"}), ("amplification", {"AMPLIFICATION"})]: out = tz.get_in([category, dd.get_genome_build(data)], _COORDS, {}) priority_file = dd.get_svprioritize(data) if priority_file: if os.path.basename(priority_file).find("civic") >= 0: for chrom, start, end, gene in _civic_regions(priority_file, vtypes, dd.get_disease(data)): out[gene] = (chrom, start, end) elif os.path.basename(priority_file).find(".bed") >= 0: for line in utils.open_gzipsafe(priority_file): parts = line.strip().split("\t") if len(parts) >= 4: chrom, start, end, gene = parts[:4] out[gene] = (chrom, int(start), int(end)) yield category, out def _matches(tocheck, target): for t in target: t = t.lower() for c in tocheck: if c.lower().find(t) >= 0: return True def _civic_regions(civic_file, variant_types=None, diseases=None, drugs=None): """Retrieve gene regions and names filtered by variant_types and diseases. """ if isinstance(diseases, six.string_types): diseases = [diseases] with utils.open_gzipsafe(civic_file) as in_handle: reader = csv.reader(in_handle, delimiter="\t") for chrom, start, end, info_str in reader: info = edn_loads(info_str) if not variant_types or _matches(info["support"]["variants"], variant_types): if not diseases or _matches(info["support"]["diseases"], diseases): if not drugs or _matches(info["support"]["drugs"], drugs): yield (chrom, int(start), int(end), list(info["name"])[0]) def summary_status(call, data): """Retrieve status in regions of interest, along with heterogeneity metrics. Provides output with overall purity and ploidy, along with region specific calls. """ out_file = None if call.get("vrn_file") and os.path.exists(call.get("vrn_file")): out_file = os.path.join(os.path.dirname(call["vrn_file"]), "%s-%s-lohsummary.yaml" % (dd.get_sample_name(data), call["variantcaller"])) if not utils.file_uptodate(out_file, call["vrn_file"]): out = {} if call["variantcaller"] == "titancna": out.update(_titancna_summary(call, data)) pass elif call["variantcaller"] == "purecn": out.update(_purecn_summary(call, data)) if out: out["description"] = dd.get_sample_name(data) out["variantcaller"] = call["variantcaller"] with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) return out_file if out_file and os.path.exists(out_file) else None def _check_copy_number_changes(svtype, cn, minor_cn, data): """Check if copy number changes match the expected svtype. """ if svtype == "LOH" and minor_cn == 0: return svtype elif svtype == "amplification" and cn > dd.get_ploidy(data): return svtype else: return "std" def _to_cn(v): return int(round(float(v))) def _titancna_summary(call, data): """Summarize purity, ploidy and LOH for TitanCNA. """ out = {} for svtype, coords in get_coords(data): cur_calls = {k: collections.defaultdict(int) for k in coords.keys()} with open(call["subclones"]) as in_handle: header = in_handle.readline().strip().split() for line in in_handle: val = dict(zip(header, line.strip().split())) start = int(val["Start_Position.bp."]) end = int(val["End_Position.bp."]) for region, cur_coords in coords.items(): if val["Chromosome"] == cur_coords[0] and are_overlapping((start, end), cur_coords[1:]): cur_calls[region][_check_copy_number_changes(svtype, _to_cn(val["Copy_Number"]), _to_cn(val["MinorCN"]), data)] += 1 out[svtype] = {r: _merge_cn_calls(c, svtype) for r, c in cur_calls.items()} with open(call["hetsummary"]) as in_handle: vals = dict(zip(in_handle.readline().strip().split("\t"), in_handle.readline().strip().split("\t"))) out["purity"] = vals["purity"] out["ploidy"] = vals["ploidy"] return out def _purecn_summary(call, data): """Summarize purity, ploidy and LOH for PureCN. """ out = {} loh_calls = pd.read_csv(call["loh"]) for svtype, coords in get_coords(data): cur_calls = {k: collections.defaultdict(int) for k in coords.keys()} for rowid, row in loh_calls.iterrows(): _, chrom, start, end, _, cn, minor_cn = row.iloc[0:7] if pd.isnull(cn) or pd.isnull(minor_cn): # NA copy number calls - skip continue start = int(start) end = int(end) for region, cur_coords in coords.items(): if chrom == cur_coords[0] and are_overlapping((start, end), cur_coords[1:]): cur_calls[region][_check_copy_number_changes(svtype, _to_cn(cn), _to_cn(minor_cn), data)] += 1 out[svtype] = {r: _merge_cn_calls(c, svtype) for r, c in cur_calls.items()} with open(call["hetsummary"]) as in_handle: vals = dict(zip(in_handle.readline().strip().replace('"', '').split(","), in_handle.readline().strip().split(","))) out["purity"] = vals["Purity"] out["ploidy"] = vals["Ploidy"] return out def _merge_cn_calls(calls, svtype): if calls[svtype]: return "mixed" if calls["std"] else svtype else: return "no" def are_overlapping(r, s): """Test if two coordinates overlap. https://stackoverflow.com/a/27182551 """ return r[1] >= s[0] and s[1] >= r[0] # ## EDN parser # Thanks to https://github.com/sunng87/pyclj # Slightly adapter to avoid external dependencies def edn_load(fp): decoder = CljDecoder(fp) return decoder.decode() def edn_loads(s): buf = StringIO(s) result = edn_load(buf) buf.close() return result def _number(v): if v.endswith('M'): out = decimal.Decimal(v[:-1]) else: try: out = int(v) except ValueError as e: out = float(v) return out _STOP_CHARS = [" ", ",", "\n", "\r", "\t"] _COLL_OPEN_CHARS = ["#", "[", "{", "("] _COLL_CLOSE_CHARS = ["]", "}", ")"] _EXTRA_NUM_CHARS = ["-", "+", ".", "e", "E", "M"] class CljDecoder(object): def __init__(self, fd): self.fd = fd self.cur_line = 1 self.cur_pos = 1 self.value_stack = [] self.terminator = None ## for collection type def decode(self): while True: v = self.__read_token() if len(self.value_stack) == 0: return v def __seek_back(self, size): self.fd.seek(self.fd.tell()-size, 0) def __read_and_back(self, size): s = self.fd.read(size) self.__seek_back(size) return s def __get_type_from_char(self, c): """return a tuple of type information * type name * a flag to indicate if it's a collection """ if c.isdigit() or c =='-': return ("number", False, None) elif c == 't' or c == 'f': ## true/false return ("boolean", False, None) elif c == 'n': ## nil return ("nil", False, None) elif c == '\\' : return ("char", False, None) elif c == ':': return ("keyword", False, None) elif c == '"': return ("string", False, None) elif c == '#': if self.__read_and_back(1) == '{': return ("set", True, "}") if self.__read_and_back(1) == ':': return ("namespaced_dict", True, "}") if self.__read_and_back(4) == 'inst': return ("datetime", False, None) if self.__read_and_back(4) == 'uuid': return ("uuid", False, None) elif c == '{': return ("dict", True, "}") elif c == '(': return ("list", True, ")") elif c == '[': return ('list', True, "]") return (None, False, None) def __read_fd(self, size): if size == 1: c = self.fd.read(size) if c == '\n': self.cur_pos = 0 self.cur_line = self.cur_line + 1 return c else: self.cur_pos = self.cur_pos + size cs = self.fd.read(size) return cs def __read_token(self): c = self.__read_fd(1) ## skip all stop chars if necessary while c in _STOP_CHARS: c = self.__read_fd(1) ## raise exception when unexpected EOF found if c == '': raise ValueError("Unexpected EOF") t, coll, term = self.__get_type_from_char(c) if coll: ## move cursor if t == "set": ## skip { self.__read_fd(1) namespace = None if t == "namespaced_dict": ## skip : self.__read_fd(1) ## get namespace buf = [] while c != '{': c = self.__read_fd(1) buf.append(c) namespace = ''.join(buf[:-1]) self.terminator = term self.value_stack.append(([], self.terminator, t, namespace)) return None else: v = None ## token value e = None ## end char r = True ## the token contains data or not if t == "boolean": if c == 't': chars = self.__read_fd(4) if chars[:3] != 'rue': raise ValueError('Expect true, got t%s at line %d, col %d' % (chars[:3], self.cur_line, self.cur_pos)) e = chars[-1] v = True else: chars = self.__read_fd(5) if chars[:4] != 'alse': raise ValueError('Expect true, got t%s at line %d, col %d' % (chars[:3], self.cur_line, self.cur_pos)) e = chars[-1] v = False elif t == "char": buf = [] while c is not self.terminator and c != "" and c not in _STOP_CHARS: c = self.__read_fd(1) buf.append(c) e = c v = ''.join(buf[:-1]) elif t == "nil": chars = self.__read_fd(3) if chars[:2] != 'il': raise ValueError('Expect nil, got n%s at line %d, col %d' % (chars[:2], self.cur_line, self.cur_pos)) e = chars[-1] v = None elif t == "number": buf = [] while c.isdigit() or (c in _EXTRA_NUM_CHARS): buf.append(c) c = self.__read_fd(1) e = c numstr = ''.join(buf) v = _number(numstr) ## special case for ## [23[12]] ## this is a valid clojure form if e in _COLL_OPEN_CHARS: self.__seek_back(1) elif t == "keyword": buf = [] ##skip the leading ":" while c is not self.terminator and c != "" and c not in _STOP_CHARS: c = self.__read_fd(1) buf.append(c) e = c v = ''.join(buf[:-1]) elif t == "string": buf = [] cp = c = self.__read_fd(1) ## to check escaping character \ while not(c == '"' and cp != '\\'): buf.append(c) cp = c c = self.__read_fd(1) e = c v = unicode(''.join(buf).decode('unicode-escape')) elif t == "datetime": ## skip "inst" self.__read_fd(4) ## read next value as string s = self.__read_token() if not isinstance(s, six.string_types): raise ValueError('Str expected, but got %s' % str(s)) ## remove read string from the value_stack if len(self.value_stack) > 0: self.value_stack[-1][0].pop() e = '"' v = pyrfc3339.parse(s) elif t == "uuid": ## skip "uuid" self.__read_fd(4) ## read next value as string s = self.__read_token() if not isinstance(s, six.string_types): raise ValueError('Str expected, but got %s' % str(s)) ## remove read string from the value_stack if len(self.value_stack) > 0: self.value_stack[-1][0].pop() e = '"' v = uuid.UUID(s) else: if c not in _COLL_CLOSE_CHARS: raise ValueError('Unexpected char: "%s" at line %d, col %d' % (c, self.cur_line, self.cur_pos)) r = False e = c if e == self.terminator: current_scope, _, container, namespace = self.value_stack.pop() if r: current_scope.append(v) if container == "set": try: v = set(current_scope) except TypeError: v = tuple(current_scope) elif container == "list": v = current_scope elif container in ["dict", "namespaced_dict"]: v = {} for i in range(0, len(current_scope), 2): key = '%s/%s' % (namespace, current_scope[i]) if namespace else current_scope[i] v[key] = current_scope[i+1] r = True if r and len(self.value_stack) > 0: self.value_stack[-1][0].append(v) self.terminator = self.value_stack[-1][1] return v bcbio-nextgen-1.2.9/bcbio/heterogeneity/phylowgs.py000066400000000000000000000275551415626112400224460ustar00rootroot00000000000000"""Reconstruct subclones and phylogenetic history using PhyloWGS. PhyloWGS uses phylogenetic histories inferred through Battenberg CNV calls along with variant frequencies. https://github.com/morrislab/phylowgs http://genomebiology.com/2015/16/1/35 """ from __future__ import print_function import collections import os import sys import pybedtools from pysam import VariantFile from bcbio import utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.structural import annotate def run(vrn_info, cnvs_by_name, somatic_info): """Run PhyloWGS given variant calls, CNVs and tumor/normal information. """ config = {"sample_size": 5000} work_dir = _cur_workdir(somatic_info.tumor_data) if "battenberg" not in cnvs_by_name: logger.warn("PhyloWGS requires Battenberg CNV calls, skipping %s" % dd.get_sample_name(somatic_info.tumor_data)) else: ssm_file, cnv_file = _prep_inputs(vrn_info, cnvs_by_name["battenberg"], somatic_info, work_dir, config) evolve_file = _run_evolve(ssm_file, cnv_file, work_dir, somatic_info.tumor_data) summary_file = _prepare_summary(evolve_file, ssm_file, cnv_file, work_dir, somatic_info) print(summary_file) def _prepare_summary(evolve_file, ssm_file, cnv_file, work_dir, somatic_info): """Prepare a summary with gene-labelled heterogeneity from PhyloWGS predictions. """ out_file = os.path.join(work_dir, "%s-phylowgs.txt" % somatic_info.tumor_name) if not utils.file_uptodate(out_file, evolve_file): with file_transaction(somatic_info.tumor_data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: ssm_locs = _read_ssm_locs(ssm_file) cnv_ssms = _read_cnv_ssms(cnv_file) for i, (ids, tree) in enumerate(_evolve_reader(evolve_file)): out_handle.write("* Tree %s\n" % (i + 1)) out_handle.write("\n" + "\n".join(tree) + "\n\n") for nid, freq, gids in ids: genes = _gids_to_genes(gids, ssm_locs, cnv_ssms, somatic_info.tumor_data) out_handle.write("%s\t%s\t%s\n" % (nid, freq, ",".join(genes))) out_handle.write("\n") return out_file def _gids_to_genes(gids, ssm_locs, cnv_ssms, data): """Convert support ids for SNPs and SSMs into associated genes. """ locs = collections.defaultdict(set) for gid in gids: cur_locs = [] try: cur_locs.append(ssm_locs[gid]) except KeyError: for ssm_loc in cnv_ssms.get(gid, []): cur_locs.append(ssm_locs[ssm_loc]) for chrom, pos in cur_locs: locs[chrom].add(pos) genes = set([]) with tx_tmpdir(data) as tmpdir: chrom_prefix = "chr" if next(ref.file_contigs(dd.get_ref_file(data))).name.startswith("chr") else "" loc_file = os.path.join(tmpdir, "battenberg_find_genes.bed") with open(loc_file, "w") as out_handle: for chrom in sorted(locs.keys()): for loc in sorted(list(locs[chrom])): out_handle.write("%s%s\t%s\t%s\n" % (chrom_prefix, chrom, loc - 1, loc)) ann_file = annotate.add_genes(loc_file, data, max_distance=10000) for r in pybedtools.BedTool(ann_file): for gene in r.name.split(","): if gene != ".": genes.add(gene) return sorted(list(genes)) def _evolve_reader(in_file): """Generate a list of region IDs and trees from a top_k_trees evolve.py file. """ cur_id_list = None cur_tree = None with open(in_file) as in_handle: for line in in_handle: if line.startswith("id,"): if cur_id_list: yield cur_id_list, cur_tree cur_id_list = [] cur_tree = None elif cur_tree is not None: if line.strip() and not line.startswith("Number of non-empty"): cur_tree.append(line.rstrip()) elif not line.strip() and cur_id_list and len(cur_id_list) > 0: cur_tree = [] elif line.strip(): parts = [] for part in line.strip().split("\t"): if part.endswith(","): part = part[:-1] parts.append(part) if len(parts) > 4: nid, freq, _, _, support = parts cur_id_list.append((nid, freq, support.split("; "))) if cur_id_list: yield cur_id_list, cur_tree def _read_cnv_ssms(in_file): """Map CNVs to associated SSMs """ out = {} with open(in_file) as in_handle: in_handle.readline() # header for line in in_handle: parts = line.strip().split() if len(parts) > 3: cnvid, _, _, ssms = parts out[cnvid] = [x.split(",")[0] for x in ssms.split(";")] return out def _read_ssm_locs(in_file): """Map SSMs to chromosomal locations. """ out = {} with open(in_file) as in_handle: in_handle.readline() # header for line in in_handle: sid, loc = line.split()[:2] chrom, pos = loc.split("_") out[sid] = (chrom, int(pos)) return out def _run_evolve(ssm_file, cnv_file, work_dir, data): """Run evolve.py to infer subclonal composition. """ exe = os.path.join(os.path.dirname(sys.executable), "evolve.py") assert os.path.exists(exe), "Could not find evolve script for PhyloWGS runs." out_dir = os.path.join(work_dir, "evolve") out_file = os.path.join(out_dir, "top_k_trees") if not utils.file_uptodate(out_file, cnv_file): with file_transaction(data, out_dir) as tx_out_dir: with utils.chdir(tx_out_dir): cmd = [sys.executable, exe, "-r", "42", ssm_file, cnv_file] do.run(cmd, "Run PhyloWGS evolution") return out_file def _prep_inputs(vrn_info, cnv_info, somatic_info, work_dir, config): """Prepare inputs for running PhyloWGS from variant and CNV calls. """ exe = os.path.join(os.path.dirname(sys.executable), "create_phylowgs_inputs.py") assert os.path.exists(exe), "Could not find input prep script for PhyloWGS runs." ssm_file = os.path.join(work_dir, "ssm_data.txt") cnv_file = os.path.join(work_dir, "cnv_data.txt") if not utils.file_exists(ssm_file) or not utils.file_exists(cnv_file): with file_transaction(somatic_info.tumor_data, ssm_file, cnv_file) as (tx_ssm_file, tx_cnv_file): variant_type, input_vcf_file = _prep_vrn_file(vrn_info["vrn_file"], vrn_info["variantcaller"], work_dir, somatic_info, cnv_info["ignore"], config) input_cnv_file = _prep_cnv_file(cnv_info["subclones"], work_dir, somatic_info) cmd = [sys.executable, exe, "--sample-size", str(config["sample_size"]), "--tumor-sample", somatic_info.tumor_name, "--battenberg", input_cnv_file, "--cellularity", _read_contam(cnv_info["contamination"]), "--output-cnvs", tx_cnv_file, "--output-variants", tx_ssm_file, "--variant-type", variant_type, input_vcf_file] do.run(cmd, "Prepare PhyloWGS inputs.") return ssm_file, cnv_file def _prep_cnv_file(in_file, work_dir, somatic_info): """Prepare Battenberg CNV file for ingest by PhyloWGS. The PhyloWGS preparation script does not handle 'chr' prefixed chromosomes (hg19 style) correctly. This converts them over to GRCh37 (no 'chr') style to match preparation work in _prep_vrn_file. """ out_file = os.path.join(work_dir, "%s-prep%s" % utils.splitext_plus(os.path.basename(in_file))) if not utils.file_uptodate(out_file, in_file): with file_transaction(somatic_info.tumor_data, out_file) as tx_out_file: with open(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: out_handle.write(in_handle.readline()) # header for line in in_handle: parts = line.split("\t") parts[1] = _phylowgs_compatible_chroms(parts[1]) out_handle.write("\t".join(parts)) return out_file def _phylowgs_compatible_chroms(chrom): """PhyloWGS prep scripts to not correctly support chr-prefixed contigs, so we remove them. """ return chrom if not chrom.startswith("chr") else chrom.replace("chr", "") def _prep_vrn_file(in_file, vcaller, work_dir, somatic_info, ignore_file, config): """Create a variant file to feed into the PhyloWGS prep script, limiting records. Sorts by depth, adding top covered samples up to the sample_size supported by PhyloWGS. The logic is that the higher depth samples will have better resolution for frequency differences. More complex implementations could try to subset based on a distribution of frequencies to best sample the potential heterogeneity. Handles MuTect and VarDict as inputs to PhyloWGS. Fixes chromosome naming to use non chr-prefixed contigs, to match _prep_cnv_file. """ if vcaller.startswith("vardict"): variant_type = "vardict" elif vcaller == "mutect": variant_type = "mutect-smchet" else: raise ValueError("Unexpected variant caller for PhyloWGS prep: %s" % vcaller) out_file = os.path.join(work_dir, "%s-%s-prep.vcf" % (utils.splitext_plus(os.path.basename(in_file))[0], vcaller)) if not utils.file_uptodate(out_file, in_file): check_fn = _min_sample_pass(ignore_file) with file_transaction(somatic_info.tumor_data, out_file) as tx_out_file: tx_out_file_raw = "%s-raw%s" % utils.splitext_plus(tx_out_file) # Filter inputs with VariantFile(in_file) as bcf_in: depths = [_sample_depth(rec, somatic_info.tumor_name) for rec in filter(check_fn, bcf_in)] depths.sort(reverse=True) depth_thresh = depths[:config["sample_size"]][-1] if depths else 0 with VariantFile(in_file) as bcf_in: with VariantFile(tx_out_file_raw, "w", header=bcf_in.header) as bcf_out: for rec in bcf_in: if (check_fn(rec) and (depth_thresh < 5 or _sample_depth(rec, somatic_info.tumor_name) >= depth_thresh)): bcf_out.write(rec) # Fix potential chromosome issues with open(tx_out_file_raw) as in_handle: with open(tx_out_file, "w") as out_handle: for line in in_handle: if not line.startswith("#"): parts = line.split("\t") parts[0] = _phylowgs_compatible_chroms(parts[0]) line = "\t".join(parts) out_handle.write(line) return variant_type, out_file def _min_sample_pass(ignore_file): with open(ignore_file) as in_handle: ignore_chrs = set([x.strip() for x in in_handle]) def _check(rec): return rec.chrom not in ignore_chrs and _is_snp(rec) and "PASS" in rec.filter.keys() return _check def _sample_depth(rec, sample_name): return sum(rec.samples[sample_name].get("AD", [0])) def _is_snp(rec): return max([len(x) for x in rec.alleles]) == 1 def _read_contam(in_file): with open(in_file) as in_handle: normal_contam = float(in_handle.readline().strip()) return "%.2f" % (1.0 - normal_contam) def _cur_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "heterogeneity", dd.get_sample_name(data), "phylowgs")) bcbio-nextgen-1.2.9/bcbio/heterogeneity/theta.py000066400000000000000000000236211415626112400216650ustar00rootroot00000000000000"""Provide estimates of sample purity and subclonal copy number using THetA. Identifying cellularity and subclonal populations within somatic calling using tumor normal pairs. https://github.com/raphael-group/THetA """ import os import sys import subprocess import pybedtools import pysam import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.variation import vcfutils from bcbio.provenance import do from bcbio.structural import convert def run(vrn_info, cnvs_by_name, somatic_info): """Run THetA analysis given output from CNV caller on a tumor/normal pair. """ cmd = _get_cmd("RunTHeTA.py") if not cmd: logger.info("THetA scripts not found in current PATH. Skipping.") else: from bcbio.structural import cnvkit work_dir = _sv_workdir(somatic_info.tumor_data) assert "cnvkit" in cnvs_by_name, "THetA requires CNVkit calls" cnv_info = cnvkit.export_theta(cnvs_by_name["cnvkit"], somatic_info.tumor_data) cnv_info["theta_input"] = subset_by_supported(cnv_info["theta_input"], _theta_to_coords, cnvs_by_name, work_dir, somatic_info.tumor_data) return _run_theta(cnv_info, somatic_info.tumor_data, work_dir, run_n3=False) def _theta_to_coords(line): _, chrom, start, end = line.split()[:4] return (chrom, start, end) def subset_by_supported(input_file, get_coords, calls_by_name, work_dir, data, headers=("#",)): """Limit CNVkit input to calls with support from another caller. get_coords is a function that return chrom, start, end from a line of the input_file, allowing handling of multiple input file types. """ support_files = [(c, tz.get_in([c, "vrn_file"], calls_by_name)) for c in convert.SUBSET_BY_SUPPORT["cnvkit"]] support_files = [(c, f) for (c, f) in support_files if f and vcfutils.vcf_has_variants(f)] if len(support_files) == 0: return input_file else: out_file = os.path.join(work_dir, "%s-havesupport%s" % utils.splitext_plus(os.path.basename(input_file))) if not utils.file_uptodate(out_file, input_file): input_bed = _input_to_bed(input_file, work_dir, get_coords, headers) pass_coords = set([]) with file_transaction(data, out_file) as tx_out_file: support_beds = " ".join([_sv_vcf_to_bed(f, c, out_file) for c, f in support_files]) tmp_cmp_bed = "%s-intersectwith.bed" % utils.splitext_plus(tx_out_file)[0] cmd = "bedtools intersect -wa -f 0.5 -r -a {input_bed} -b {support_beds} > {tmp_cmp_bed}" do.run(cmd.format(**locals()), "Intersect CNVs with support files") for r in pybedtools.BedTool(tmp_cmp_bed): pass_coords.add((str(r.chrom), str(r.start), str(r.stop))) with open(input_file) as in_handle: with open(tx_out_file, "w") as out_handle: for line in in_handle: passes = True if not line.startswith(headers): passes = get_coords(line) in pass_coords if passes: out_handle.write(line) return out_file def _sv_vcf_to_bed(orig_vcf, caller, base_out): out_file = "%s-inputcmp-%s.bed" % (utils.splitext_plus(base_out)[0], caller) if not utils.file_exists(out_file): with pysam.VariantFile(orig_vcf) as bcf_in: with open(out_file, "w") as out_handle: for rec in bcf_in: if len(rec.filter.keys()) == 0 or rec.filter.keys()[0] in ["PASS", "."]: out_handle.write("%s\t%s\t%s\n" % (rec.chrom, rec.start, rec.info.get("END", rec.start))) return out_file def _input_to_bed(theta_input, work_dir, get_coords, headers): """Convert input file to a BED file for comparisons """ theta_bed = os.path.join(work_dir, "%s.bed" % os.path.splitext(os.path.basename(theta_input))[0]) with open(theta_input) as in_handle: with open(theta_bed, "w") as out_handle: for line in in_handle: if not line.startswith(headers): chrom, start, end = get_coords(line) out_handle.write("\t".join([chrom, start, end]) + "\n") return theta_bed def _run_theta(cnv_info, data, work_dir, run_n3=True): """Run theta, calculating subpopulations and normal contamination. """ out = {"caller": "theta"} max_normal = "0.9" opts = ["-m", max_normal] n2_result = _safe_run_theta(cnv_info["theta_input"], os.path.join(work_dir, "n2"), ".n2.results", ["-n", "2"] + opts, data) if n2_result: out["estimate"] = n2_result if run_n3: n2_bounds = "%s.withBounds" % os.path.splitext(n2_result)[0] n3_result = _safe_run_theta(n2_bounds, os.path.join(work_dir, "n3"), ".n3.results", ["-n", "3", "--RESULTS", n2_result] + opts, data) if n3_result: best_result = _select_model(n2_bounds, n2_result, n3_result, os.path.join(work_dir, "n3"), data) out["estimate"] = best_result out["cnvs"] = _merge_theta_calls(n2_bounds, best_result, cnv_info["vrn_file"], data) return out def _update_with_calls(result_file, cnv_file): """Update bounds with calls from CNVkit, inferred copy numbers and p-values from THetA. """ results = {} with open(result_file) as in_handle: in_handle.readline() # header _, _, cs, ps = in_handle.readline().strip().split() for i, (c, p) in enumerate(zip(cs.split(":"), ps.split(","))): results[i] = (c, p) cnvs = {} with open(cnv_file) as in_handle: for line in in_handle: chrom, start, end, _, count = line.rstrip().split()[:5] cnvs[(chrom, start, end)] = count def update(i, line): parts = line.rstrip().split("\t") chrom, start, end = parts[1:4] parts += cnvs.get((chrom, start, end), ".") parts += list(results[i]) return "\t".join(parts) + "\n" return update def _merge_theta_calls(bounds_file, result_file, cnv_file, data): """Create a final output file with merged CNVkit and THetA copy and population estimates. """ out_file = "%s-merged.txt" % (result_file.replace(".BEST.results", "")) if not utils.file_uptodate(out_file, result_file): with file_transaction(data, out_file) as tx_out_file: updater = _update_with_calls(result_file, cnv_file) with open(bounds_file) as in_handle: with open(tx_out_file, "w") as out_handle: i = 0 for line in in_handle: if line.startswith("#"): parts = line.rstrip().split("\t") parts += ["cnv", "pop_cnvs", "pop_pvals"] out_handle.write("\t".join(parts) + "\n") else: out_handle.write(updater(i, line)) i += 1 return out_file def _select_model(n2_bounds, n2_result, n3_result, out_dir, data): """Run final model selection from n=2 and n=3 options. """ n2_out_file = n2_result.replace(".n2.results", ".BEST.results") n3_out_file = n3_result.replace(".n3.results", ".BEST.results") if not utils.file_exists(n2_out_file) and not utils.file_exists(n3_out_file): cmd = _get_cmd("ModelSelection.py") + [n2_bounds, n2_result, n3_result] do.run(cmd, "Select best THetA model") if utils.file_exists(n2_out_file): return n2_out_file else: assert utils.file_exists(n3_out_file) return n3_out_file def _safe_run_theta(input_file, out_dir, output_ext, args, data): """Run THetA, catching and continuing on any errors. """ out_file = os.path.join(out_dir, _split_theta_ext(input_file) + output_ext) skip_file = out_file + ".skipped" if utils.file_exists(skip_file): return None if not utils.file_exists(out_file): with file_transaction(data, out_dir) as tx_out_dir: utils.safe_makedir(tx_out_dir) cmd = _get_cmd("RunTHetA.py") + args + \ [input_file, "--NUM_PROCESSES", dd.get_cores(data), "--FORCE", "-d", tx_out_dir] try: do.run(cmd, "Run THetA to calculate purity", log_error=False) except subprocess.CalledProcessError as msg: if ("Number of intervals must be greater than 1" in str(msg) or "This sample isn't a good candidate for THetA analysis" in str(msg)): with open(os.path.join(tx_out_dir, os.path.basename(skip_file)), "w") as out_handle: out_handle.write("Expected TheTA failure, skipping") return None else: raise return out_file def _split_theta_ext(fname): base = os.path.splitext(os.path.basename(fname))[0] if base.endswith((".n2", ".n3")): base = os.path.splitext(base)[0] return base def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "heterogeneity", dd.get_sample_name(data), "theta")) def _get_cmd(cmd): """Retrieve required commands for running THetA with our local bcbio python. """ check_cmd = "RunTHetA.py" try: local_cmd = subprocess.check_output(["which", check_cmd]).strip() except subprocess.CalledProcessError: return None return [sys.executable, "%s/%s" % (os.path.dirname(os.path.realpath(local_cmd)), cmd)] bcbio-nextgen-1.2.9/bcbio/hla/000077500000000000000000000000001415626112400160735ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/hla/__init__.py000066400000000000000000000017371415626112400202140ustar00rootroot00000000000000"""Main entry point for HLA typing on samples. """ import toolz as tz from bcbio import utils from bcbio.hla import bwakit, optitype _CALLERS = {"bwakit": bwakit.run, "optitype": optitype.run} def call_hla(data): data = utils.to_single_data(utils.to_single_data(data)) hlacaller = tz.get_in(["config", "algorithm", "hlacaller"], data) if hlacaller and "hla" in data and tz.get_in(["hla", "fastq"], data): data = _CALLERS[hlacaller](data) elif "hla" not in data: data["hla"] = {} return [[data]] def run(samples, run_parallel): """Run HLA detection on the input samples. """ to_process = [] extras = [] for data in (xs[0] for xs in samples): hlacaller = tz.get_in(["config", "algorithm", "hlacaller"], data) if hlacaller: to_process.append(data) else: extras.append([data]) processed = run_parallel("call_hla", ([x] for x in to_process)) return extras + processed bcbio-nextgen-1.2.9/bcbio/hla/bwakit.py000066400000000000000000000076701415626112400177400ustar00rootroot00000000000000"""Call HLA alleles with assembly methods implemented in bwakit. https://github.com/lh3/bwa/blob/master/README-alt.md#hla-typing https://github.com/lh3/bwa/tree/master/bwakit """ import csv import glob import os import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.hla import groups as hla_groups from bcbio.pipeline import datadict as dd from bcbio.provenance import do def run(data): """HLA typing with bwakit, parsing output from called genotype files. """ bwakit_dir = os.path.dirname(os.path.realpath(utils.which("run-bwamem"))) hla_fqs = tz.get_in(["hla", "fastq"], data, []) if len(hla_fqs) > 0: hla_base = os.path.commonprefix(hla_fqs) while hla_base.endswith("."): hla_base = hla_base[:-1] out_file = hla_base + ".top" if not utils.file_exists(out_file): cmd = "{bwakit_dir}/run-HLA {hla_base}" do.run(cmd.format(**locals()), "HLA typing with bwakit") out_file = _organize_calls(out_file, hla_base, data) data["hla"].update({"call_file": out_file, "hlacaller": "bwakit"}) return data def _organize_calls(out_file, hla_base, data): """Prepare genotype calls, reporting best call along with quality metrics. """ hla_truth = get_hla_truthset(data) sample = dd.get_sample_name(data) with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: writer = csv.writer(out_handle) writer.writerow(["sample", "locus", "mismatches", "options", "alleles", "p-groups", "expected", "validates"]) for genotype_file in glob.glob("%s.HLA-*.gt" % (hla_base)): hla_locus = os.path.basename(genotype_file).replace( "%s.HLA-" % os.path.basename(hla_base), "").replace(".gt", "") with open(genotype_file) as in_handle: total_options = set([]) for i, line in enumerate(in_handle): _, aone, atwo, m = line.split("\t")[:4] pgroups = (hla_groups.hla_protein(aone, data), hla_groups.hla_protein(atwo, data)) if i == 0: call_alleles = [aone, atwo] call_pgroups = pgroups mismatches = m total_options.add(pgroups) if len(total_options) > 0: truth_alleles = tz.get_in([sample, hla_locus], hla_truth, []) writer.writerow([sample, hla_locus, mismatches, len(total_options), ";".join(call_alleles), ";".join(call_pgroups), ";".join(truth_alleles), matches_truth(call_alleles, truth_alleles, data)]) return out_file def matches_truth(call_alleles, truth_alleles, data): """Flexibly check if truth and call alleles match, using p-groups. """ if not truth_alleles: return "" else: def _remove_p(x): return x[:-1] if x.endswith("P") else x t_cmp = set([_remove_p(hla_groups.hla_protein(x, data)) for x in truth_alleles]) c_cmp = set([_remove_p(hla_groups.hla_protein(x, data)) for x in call_alleles]) return "yes" if len(t_cmp.intersection(c_cmp)) == len(t_cmp) else "no" def get_hla_truthset(data): """Retrieve expected truth calls for annotating HLA called output. """ val_csv = tz.get_in(["config", "algorithm", "hlavalidate"], data) out = {} if val_csv and utils.file_exists(val_csv): with open(val_csv) as in_handle: reader = csv.reader(in_handle) next(reader) # header for sample, locus, alleles in (l for l in reader if l): out = tz.update_in(out, [sample, locus], lambda x: [x.strip() for x in alleles.split(";")]) return out bcbio-nextgen-1.2.9/bcbio/hla/groups.py000066400000000000000000000352431415626112400177730ustar00rootroot00000000000000"""Place HLA calls into group for validation and presentation. Uses p-groups with identical protein sequences in the antigen binding domains: http://hla.alleles.org/alleles/p_groups.html HLA allele nomenclature: https://www.ebi.ac.uk/ipd/imgt/hla/ https://github.com/jrob119/IMGTHLA HLA sequences are from the 1000 genomes build 38 reference: ftp://ftp.1000genomes.ebi.ac.uk/vol1/ftp/technical/reference/GRCh38_reference_genome/ based on IMGT/HLA-3.18.0 """ import toolz as tz def hla_protein(name, data): group = tz.get_in([data["genome_build"], name], pgroups) if group: base = name.split("*")[0] group = "%s*%s" % (base, group) else: group = _from_name(name) return group def _from_name(name): """Parse the HLA base name (group + protein) from a full name. Separates out synonymous and non-coding indicators. http://hla.alleles.org/nomenclature/naming.html """ return ":".join(name.split(":")[:2]) pgroups = {} pgroups["hg38"] = \ {'HLA-A*01:01:01:01': '01:01P', 'HLA-A*01:01:01:02N': '', 'HLA-A*01:01:38L': '01:01P', 'HLA-A*01:02': '', 'HLA-A*01:03': '', 'HLA-A*01:04N': '', 'HLA-A*01:09': '', 'HLA-A*01:11N': '', 'HLA-A*01:14': '', 'HLA-A*01:16N': '', 'HLA-A*01:20': '', 'HLA-A*02:01:01:01': '02:01P', 'HLA-A*02:01:01:02L': '02:01P', 'HLA-A*02:01:01:03': '02:01P', 'HLA-A*02:01:01:04': '02:01P', 'HLA-A*02:02:01': '', 'HLA-A*02:03:01': '02:03P', 'HLA-A*02:03:03': '02:03P', 'HLA-A*02:05:01': '02:05P', 'HLA-A*02:06:01': '', 'HLA-A*02:07:01': '02:07P', 'HLA-A*02:10': '02:10P', 'HLA-A*02:251': '', 'HLA-A*02:259': '', 'HLA-A*02:264': '02:03P', 'HLA-A*02:265': '02:07P', 'HLA-A*02:266': '02:01P', 'HLA-A*02:269': '', 'HLA-A*02:279': '', 'HLA-A*02:32N': '', 'HLA-A*02:376': '', 'HLA-A*02:43N': '', 'HLA-A*02:455': '02:01P', 'HLA-A*02:48': '', 'HLA-A*02:51': '', 'HLA-A*02:533': '', 'HLA-A*02:53N': '', 'HLA-A*02:57': '', 'HLA-A*02:60:01': '02:60P', 'HLA-A*02:65': '02:65P', 'HLA-A*02:68': '', 'HLA-A*02:77': '', 'HLA-A*02:81': '02:81P', 'HLA-A*02:89': '02:01P', 'HLA-A*02:95': '', 'HLA-A*03:01:01:01': '03:01P', 'HLA-A*03:01:01:02N': '', 'HLA-A*03:01:01:03': '03:01P', 'HLA-A*03:02:01': '03:02P', 'HLA-A*03:11N': '', 'HLA-A*03:21N': '', 'HLA-A*03:36N': '', 'HLA-A*11:01:01': '', 'HLA-A*11:01:18': '11:01P', 'HLA-A*11:02:01': '11:02P', 'HLA-A*11:05': '', 'HLA-A*11:110': '11:02P', 'HLA-A*11:25': '', 'HLA-A*11:50Q': '', 'HLA-A*11:60': '', 'HLA-A*11:69N': '', 'HLA-A*11:74': '', 'HLA-A*11:75': '', 'HLA-A*11:77': '11:02P', 'HLA-A*23:01:01': '23:01P', 'HLA-A*23:09': '', 'HLA-A*23:38N': '', 'HLA-A*24:02:01:01': '24:02P', 'HLA-A*24:02:01:02L': '24:02P', 'HLA-A*24:02:01:03': '24:02P', 'HLA-A*24:02:03Q': '24:02P', 'HLA-A*24:02:10': '24:02P', 'HLA-A*24:03:01': '24:03P', 'HLA-A*24:07:01': '24:07P', 'HLA-A*24:08': '', 'HLA-A*24:09N': '', 'HLA-A*24:10:01': '24:10P', 'HLA-A*24:11N': '', 'HLA-A*24:152': '', 'HLA-A*24:20': '', 'HLA-A*24:215': '', 'HLA-A*24:61': '', 'HLA-A*24:86N': '', 'HLA-A*25:01:01': '25:01P', 'HLA-A*26:01:01': '', 'HLA-A*26:11N': '', 'HLA-A*26:15': '', 'HLA-A*26:50': '', 'HLA-A*29:01:01:01': '29:01P', 'HLA-A*29:01:01:02N': '', 'HLA-A*29:02:01:01': '29:02P', 'HLA-A*29:02:01:02': '29:02P', 'HLA-A*29:46': '29:02P', 'HLA-A*30:01:01': '30:01P', 'HLA-A*30:02:01:01': '30:02P', 'HLA-A*30:02:01:02': '30:02P', 'HLA-A*30:04:01': '30:04P', 'HLA-A*30:89': '', 'HLA-A*31:01:02': '', 'HLA-A*31:01:23': '31:01P', 'HLA-A*31:04': '', 'HLA-A*31:14N': '', 'HLA-A*31:46': '31:01P', 'HLA-A*32:01:01': '32:01P', 'HLA-A*32:06': '', 'HLA-A*33:01:01': '33:01P', 'HLA-A*33:03:01': '33:03P', 'HLA-A*33:07': '', 'HLA-A*34:01:01': '34:01P', 'HLA-A*34:02:01': '34:02P', 'HLA-A*36:01': '', 'HLA-A*43:01': '', 'HLA-A*66:01:01': '66:01P', 'HLA-A*66:17': '66:01P', 'HLA-A*68:01:01:01': '68:01P', 'HLA-A*68:01:01:02': '68:01P', 'HLA-A*68:01:02:01': '68:01P', 'HLA-A*68:01:02:02': '68:01P', 'HLA-A*68:02:01:01': '68:02P', 'HLA-A*68:02:01:02': '68:02P', 'HLA-A*68:02:01:03': '68:02P', 'HLA-A*68:02:02': '68:02P', 'HLA-A*68:03:01': '68:03P', 'HLA-A*68:08:01': '68:08P', 'HLA-A*68:113': '', 'HLA-A*68:17': '', 'HLA-A*68:18N': '', 'HLA-A*68:22': '', 'HLA-A*68:71': '', 'HLA-A*69:01': '', 'HLA-A*74:01': '', 'HLA-A*74:02:01:01': '74:01P', 'HLA-A*74:02:01:02': '74:01P', 'HLA-A*80:01:01:01': '80:01P', 'HLA-A*80:01:01:02': '80:01P', 'HLA-B*07:02:01': '07:02P', 'HLA-B*07:05:01': '07:05P', 'HLA-B*07:06': '07:05P', 'HLA-B*07:156': '07:02P', 'HLA-B*07:33:01': '07:33P', 'HLA-B*07:41': '', 'HLA-B*07:44': '07:02P', 'HLA-B*07:50': '', 'HLA-B*08:01:01': '08:01P', 'HLA-B*08:08N': '', 'HLA-B*08:132': '', 'HLA-B*08:134': '', 'HLA-B*08:19N': '', 'HLA-B*08:20': '', 'HLA-B*08:33': '', 'HLA-B*08:79': '', 'HLA-B*13:01:01': '13:01P', 'HLA-B*13:02:01': '13:02P', 'HLA-B*13:02:03': '13:02P', 'HLA-B*13:02:09': '13:02P', 'HLA-B*13:08': '', 'HLA-B*13:15': '', 'HLA-B*13:25': '', 'HLA-B*14:01:01': '14:01P', 'HLA-B*14:02:01': '', 'HLA-B*14:07N': '', 'HLA-B*15:01:01:01': '15:01P', 'HLA-B*15:01:01:02N': '', 'HLA-B*15:01:01:03': '15:01P', 'HLA-B*15:02:01': '15:02P', 'HLA-B*15:03:01': '', 'HLA-B*15:04:01': '15:04P', 'HLA-B*15:07:01': '15:07P', 'HLA-B*15:108': '', 'HLA-B*15:10:01': '15:10P', 'HLA-B*15:11:01': '15:11P', 'HLA-B*15:13:01': '15:13P', 'HLA-B*15:16:01': '15:16P', 'HLA-B*15:17:01:01': '15:17P', 'HLA-B*15:17:01:02': '15:17P', 'HLA-B*15:18:01': '15:18P', 'HLA-B*15:220': '15:03P', 'HLA-B*15:25:01': '15:25P', 'HLA-B*15:27:01': '15:27P', 'HLA-B*15:32:01': '15:32P', 'HLA-B*15:42': '', 'HLA-B*15:58': '', 'HLA-B*15:66': '', 'HLA-B*15:77': '', 'HLA-B*15:83': '', 'HLA-B*18:01:01:01': '18:01P', 'HLA-B*18:01:01:02': '18:01P', 'HLA-B*18:02': '', 'HLA-B*18:03': '', 'HLA-B*18:17N': '', 'HLA-B*18:26': '', 'HLA-B*18:94N': '', 'HLA-B*27:04:01': '27:04P', 'HLA-B*27:05:02': '27:05P', 'HLA-B*27:05:18': '27:05P', 'HLA-B*27:06': '', 'HLA-B*27:07:01': '27:07P', 'HLA-B*27:131': '', 'HLA-B*27:24': '', 'HLA-B*27:25': '', 'HLA-B*27:32': '', 'HLA-B*35:01:01:01': '35:01P', 'HLA-B*35:01:01:02': '35:01P', 'HLA-B*35:01:22': '35:01P', 'HLA-B*35:02:01': '35:02P', 'HLA-B*35:03:01': '35:03P', 'HLA-B*35:05:01': '35:05P', 'HLA-B*35:08:01': '35:08P', 'HLA-B*35:14:02': '35:14P', 'HLA-B*35:241': '35:01P', 'HLA-B*35:41': '', 'HLA-B*37:01:01': '37:01P', 'HLA-B*37:01:05': '37:01P', 'HLA-B*38:01:01': '38:01P', 'HLA-B*38:02:01': '38:02P', 'HLA-B*38:14': '', 'HLA-B*39:01:01:01': '39:01P', 'HLA-B*39:01:01:02L': '39:01P', 'HLA-B*39:01:01:03': '39:01P', 'HLA-B*39:01:03': '39:01P', 'HLA-B*39:01:16': '39:01P', 'HLA-B*39:01:21': '39:01P', 'HLA-B*39:05:01': '39:05P', 'HLA-B*39:06:02': '39:06P', 'HLA-B*39:10:01': '39:10P', 'HLA-B*39:13:02': '39:13P', 'HLA-B*39:14': '', 'HLA-B*39:34': '', 'HLA-B*39:38Q': '', 'HLA-B*40:01:01': '40:01P', 'HLA-B*40:01:02': '40:01P', 'HLA-B*40:02:01': '40:02P', 'HLA-B*40:03': '40:03P', 'HLA-B*40:06:01:01': '40:06P', 'HLA-B*40:06:01:02': '40:06P', 'HLA-B*40:10:01': '', 'HLA-B*40:150': '40:01P', 'HLA-B*40:40': '40:40P', 'HLA-B*40:72:01': '40:72P', 'HLA-B*40:79': '', 'HLA-B*41:01:01': '41:01P', 'HLA-B*41:02:01': '41:02P', 'HLA-B*42:01:01': '42:01P', 'HLA-B*42:02': '', 'HLA-B*42:08': '', 'HLA-B*44:02:01:01': '44:02P', 'HLA-B*44:02:01:02S': '44:02P', 'HLA-B*44:02:01:03': '44:02P', 'HLA-B*44:02:17': '44:02P', 'HLA-B*44:02:27': '44:02P', 'HLA-B*44:03:01': '', 'HLA-B*44:03:02': '44:03P', 'HLA-B*44:04': '', 'HLA-B*44:09': '', 'HLA-B*44:138Q': '', 'HLA-B*44:150': '', 'HLA-B*44:23N': '', 'HLA-B*44:26': '', 'HLA-B*44:46': '', 'HLA-B*44:49': '', 'HLA-B*44:56N': '', 'HLA-B*45:01:01': '45:01P', 'HLA-B*45:04': '', 'HLA-B*46:01:01': '46:01P', 'HLA-B*46:01:05': '46:01P', 'HLA-B*47:01:01:01': '47:01P', 'HLA-B*47:01:01:02': '47:01P', 'HLA-B*48:01:01': '48:01P', 'HLA-B*48:03:01': '48:03P', 'HLA-B*48:04': '', 'HLA-B*48:08': '', 'HLA-B*49:01:01': '49:01P', 'HLA-B*49:32': '', 'HLA-B*50:01:01': '50:01P', 'HLA-B*51:01:01': '', 'HLA-B*51:01:02': '51:01P', 'HLA-B*51:02:01': '51:02P', 'HLA-B*51:07:01': '51:07P', 'HLA-B*51:42': '', 'HLA-B*52:01:01:01': '52:01P', 'HLA-B*52:01:01:02': '52:01P', 'HLA-B*52:01:01:03': '52:01P', 'HLA-B*52:01:02': '52:01P', 'HLA-B*53:01:01': '53:01P', 'HLA-B*53:11': '', 'HLA-B*54:01:01': '54:01P', 'HLA-B*54:18': '', 'HLA-B*55:01:01': '55:01P', 'HLA-B*55:01:03': '55:01P', 'HLA-B*55:02:01': '', 'HLA-B*55:12': '', 'HLA-B*55:24': '', 'HLA-B*55:48': '', 'HLA-B*56:01:01': '', 'HLA-B*56:03': '', 'HLA-B*56:04': '', 'HLA-B*57:01:01': '57:01P', 'HLA-B*57:03:01': '57:03P', 'HLA-B*57:06': '', 'HLA-B*57:11': '', 'HLA-B*57:29': '57:01P', 'HLA-B*58:01:01': '', 'HLA-B*58:31N': '', 'HLA-B*59:01:01:01': '59:01P', 'HLA-B*59:01:01:02': '59:01P', 'HLA-B*67:01:01': '67:01P', 'HLA-B*67:01:02': '67:01P', 'HLA-B*67:02': '', 'HLA-B*73:01': '', 'HLA-B*78:01:01': '78:01P', 'HLA-B*81:01': '81:01P', 'HLA-B*82:02:01': '82:02P', 'HLA-C*01:02:01': '01:02P', 'HLA-C*01:02:11': '01:02P', 'HLA-C*01:02:29': '01:02P', 'HLA-C*01:02:30': '01:02P', 'HLA-C*01:03': '01:03P', 'HLA-C*01:06': '', 'HLA-C*01:08': '', 'HLA-C*01:14': '', 'HLA-C*01:21': '', 'HLA-C*01:30': '', 'HLA-C*01:40': '01:02P', 'HLA-C*02:02:02:01': '02:02P', 'HLA-C*02:02:02:02': '02:02P', 'HLA-C*02:10': '02:02P', 'HLA-C*02:11': '', 'HLA-C*02:16:02': '02:16P', 'HLA-C*02:69': '02:02P', 'HLA-C*02:85': '', 'HLA-C*02:86': '', 'HLA-C*02:87': '', 'HLA-C*03:02:01': '03:02P', 'HLA-C*03:02:02:01': '03:02P', 'HLA-C*03:02:02:02': '03:02P', 'HLA-C*03:02:02:03': '03:02P', 'HLA-C*03:03:01': '03:03P', 'HLA-C*03:04:01:01': '03:04P', 'HLA-C*03:04:01:02': '03:04P', 'HLA-C*03:04:02': '03:04P', 'HLA-C*03:04:04': '03:04P', 'HLA-C*03:05': '', 'HLA-C*03:06': '', 'HLA-C*03:100': '03:04P', 'HLA-C*03:13:01': '03:13P', 'HLA-C*03:20N': '', 'HLA-C*03:219': '03:04P', 'HLA-C*03:261': '', 'HLA-C*03:40:01': '03:40P', 'HLA-C*03:41:02': '03:41P', 'HLA-C*03:46': '', 'HLA-C*03:61': '', 'HLA-C*04:01:01:01': '04:01P', 'HLA-C*04:01:01:02': '04:01P', 'HLA-C*04:01:01:03': '04:01P', 'HLA-C*04:01:01:04': '04:01P', 'HLA-C*04:01:01:05': '04:01P', 'HLA-C*04:01:62': '04:01P', 'HLA-C*04:03:01': '04:03P', 'HLA-C*04:06': '', 'HLA-C*04:09N': '', 'HLA-C*04:128': '', 'HLA-C*04:161': '04:01P', 'HLA-C*04:177': '', 'HLA-C*04:70': '', 'HLA-C*04:71': '', 'HLA-C*05:01:01:01': '05:01P', 'HLA-C*05:01:01:02': '05:01P', 'HLA-C*05:08': '', 'HLA-C*05:09:01': '05:09P', 'HLA-C*05:93': '05:01P', 'HLA-C*06:02:01:01': '06:02P', 'HLA-C*06:02:01:02': '06:02P', 'HLA-C*06:02:01:03': '06:02P', 'HLA-C*06:23': '', 'HLA-C*06:24': '', 'HLA-C*06:46N': '', 'HLA-C*07:01:01:01': '07:01P', 'HLA-C*07:01:01:02': '07:01P', 'HLA-C*07:01:02': '07:01P', 'HLA-C*07:01:19': '07:01P', 'HLA-C*07:01:27': '07:01P', 'HLA-C*07:01:45': '07:01P', 'HLA-C*07:02:01:01': '07:02P', 'HLA-C*07:02:01:02': '07:02P', 'HLA-C*07:02:01:03': '07:02P', 'HLA-C*07:02:01:04': '07:02P', 'HLA-C*07:02:01:05': '07:02P', 'HLA-C*07:02:05': '07:02P', 'HLA-C*07:02:06': '07:02P', 'HLA-C*07:02:64': '07:02P', 'HLA-C*07:04:01': '07:04P', 'HLA-C*07:04:02': '07:04P', 'HLA-C*07:06': '07:01P', 'HLA-C*07:149': '', 'HLA-C*07:18': '07:01P', 'HLA-C*07:19': '', 'HLA-C*07:26': '', 'HLA-C*07:30': '', 'HLA-C*07:32N': '', 'HLA-C*07:384': '', 'HLA-C*07:385': '', 'HLA-C*07:386': '', 'HLA-C*07:391': '', 'HLA-C*07:392': '', 'HLA-C*07:49': '', 'HLA-C*07:56:02': '07:56P', 'HLA-C*07:66': '07:02P', 'HLA-C*07:67': '', 'HLA-C*08:01:01': '08:01P', 'HLA-C*08:01:03': '08:01P', 'HLA-C*08:02:01:01': '08:02P', 'HLA-C*08:02:01:02': '08:02P', 'HLA-C*08:03:01': '08:03P', 'HLA-C*08:04:01': '08:04P', 'HLA-C*08:112': '', 'HLA-C*08:20': '08:01P', 'HLA-C*08:21': '', 'HLA-C*08:22': '08:01P', 'HLA-C*08:24': '08:01P', 'HLA-C*08:27': '', 'HLA-C*08:36N': '', 'HLA-C*08:40': '08:03P', 'HLA-C*08:41': '', 'HLA-C*08:62': '', 'HLA-C*12:02:02': '12:02P', 'HLA-C*12:03:01:01': '12:03P', 'HLA-C*12:03:01:02': '12:03P', 'HLA-C*12:08': '', 'HLA-C*12:13': '', 'HLA-C*12:19': '', 'HLA-C*12:22': '', 'HLA-C*12:99': '', 'HLA-C*14:02:01': '14:02P', 'HLA-C*14:03': '', 'HLA-C*14:21N': '', 'HLA-C*14:23': '14:02P', 'HLA-C*15:02:01': '', 'HLA-C*15:05:01': '15:05P', 'HLA-C*15:05:02': '15:05P', 'HLA-C*15:13': '15:02P', 'HLA-C*15:16': '', 'HLA-C*15:17': '', 'HLA-C*15:96Q': '', 'HLA-C*16:01:01': '', 'HLA-C*16:02:01': '16:02P', 'HLA-C*16:04:01': '16:04P', 'HLA-C*17:01:01:01': '17:01P', 'HLA-C*17:01:01:02': '17:01P', 'HLA-C*17:01:01:03': '17:01P', 'HLA-C*17:03': '17:01P', 'HLA-C*18:01': '18:01P', 'HLA-DQA1*01:01:02': '01:01P', 'HLA-DQA1*01:02:01:01': '01:02P', 'HLA-DQA1*01:02:01:02': '01:02P', 'HLA-DQA1*01:02:01:03': '01:02P', 'HLA-DQA1*01:02:01:04': '01:02P', 'HLA-DQA1*01:03:01:01': '01:03P', 'HLA-DQA1*01:03:01:02': '01:03P', 'HLA-DQA1*01:04:01:01': '01:01P', 'HLA-DQA1*01:04:01:02': '01:01P', 'HLA-DQA1*01:05:01': '01:01P', 'HLA-DQA1*01:07': '', 'HLA-DQA1*01:10': '', 'HLA-DQA1*01:11': '01:02P', 'HLA-DQA1*02:01': '', 'HLA-DQA1*03:01:01': '03:01P', 'HLA-DQA1*03:02': '03:01P', 'HLA-DQA1*03:03:01': '03:01P', 'HLA-DQA1*04:01:02:01': '04:01P', 'HLA-DQA1*04:01:02:02': '04:01P', 'HLA-DQA1*04:02': '04:01P', 'HLA-DQA1*05:01:01:01': '05:01P', 'HLA-DQA1*05:01:01:02': '05:01P', 'HLA-DQA1*05:03': '05:01P', 'HLA-DQA1*05:05:01:01': '05:01P', 'HLA-DQA1*05:05:01:02': '05:01P', 'HLA-DQA1*05:05:01:03': '05:01P', 'HLA-DQA1*05:11': '05:01P', 'HLA-DQA1*06:01:01': '06:01P', 'HLA-DQB1*02:01:01': '02:01P', 'HLA-DQB1*02:02:01': '', 'HLA-DQB1*03:01:01:01': '03:01P', 'HLA-DQB1*03:01:01:02': '03:01P', 'HLA-DQB1*03:01:01:03': '03:01P', 'HLA-DQB1*03:02:01': '03:02P', 'HLA-DQB1*03:03:02:01': '03:03P', 'HLA-DQB1*03:03:02:02': '03:03P', 'HLA-DQB1*03:03:02:03': '03:03P', 'HLA-DQB1*03:05:01': '03:05P', 'HLA-DQB1*05:01:01:01': '05:01P', 'HLA-DQB1*05:01:01:02': '05:01P', 'HLA-DQB1*05:03:01:01': '05:03P', 'HLA-DQB1*05:03:01:02': '05:03P', 'HLA-DQB1*06:01:01': '06:01P', 'HLA-DQB1*06:02:01': '06:02P', 'HLA-DQB1*06:03:01': '06:03P', 'HLA-DQB1*06:09:01': '06:09P', 'HLA-DRB1*01:01:01': '01:01P', 'HLA-DRB1*01:02:01': '01:02P', 'HLA-DRB1*03:01:01:01': '03:01P', 'HLA-DRB1*03:01:01:02': '03:01P', 'HLA-DRB1*04:03:01': '04:03P', 'HLA-DRB1*07:01:01:01': '07:01P', 'HLA-DRB1*07:01:01:02': '07:01P', 'HLA-DRB1*08:03:02': '08:03P', 'HLA-DRB1*09:21': '09:01P', 'HLA-DRB1*10:01:01': '10:01P', 'HLA-DRB1*11:01:01': '11:01P', 'HLA-DRB1*11:01:02': '11:01P', 'HLA-DRB1*11:04:01': '11:04P', 'HLA-DRB1*12:01:01': '12:01P', 'HLA-DRB1*12:17': '12:01P', 'HLA-DRB1*13:01:01': '13:01P', 'HLA-DRB1*13:02:01': '13:02P', 'HLA-DRB1*14:05:01': '14:05P', 'HLA-DRB1*14:54:01': '14:01P', 'HLA-DRB1*15:01:01:01': '15:01P', 'HLA-DRB1*15:01:01:02': '15:01P', 'HLA-DRB1*15:01:01:03': '15:01P', 'HLA-DRB1*15:01:01:04': '15:01P', 'HLA-DRB1*15:02:01': '15:02P', 'HLA-DRB1*15:03:01:01': '15:03P', 'HLA-DRB1*15:03:01:02': '15:03P', 'HLA-DRB1*16:02:01': '16:02P'} bcbio-nextgen-1.2.9/bcbio/hla/optitype.py000066400000000000000000000147241415626112400203320ustar00rootroot00000000000000"""HLA typing from extracted HLA alleles with OptiType https://github.com/FRED-2/OptiType """ import csv import glob import os import re import sys import shutil import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.hla import bwakit from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do SUPPORTED_HLAS = ["HLA-A", "HLA-B", "HLA-C"] def run(data): """HLA typing with OptiType, parsing output from called genotype files. """ hlas = [] for hla_fq in tz.get_in(["hla", "fastq"], data, []): hla_type = re.search(r"[.-](?PHLA-[\w-]+).fq", hla_fq).group("hlatype") if hla_type in SUPPORTED_HLAS: if utils.file_exists(hla_fq): hlas.append((hla_type, hla_fq)) if len(hlas) > 0: out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data), "hla", "OptiType-HLA-A_B_C")) # When running UMIs and hla typing we want to pick the original fastqs if len(hlas) > len(SUPPORTED_HLAS): hlas = [x for x in hlas if os.path.basename(x[1]).find("-cumi") == -1] if len(hlas) == len(SUPPORTED_HLAS): hla_fq = combine_hla_fqs(hlas, out_dir + "-input.fq", data) if utils.file_exists(hla_fq): out_file = glob.glob(os.path.join(out_dir, "*", "*_result.tsv")) if len(out_file) > 0: out_file = out_file[0] else: out_file = _call_hla(hla_fq, out_dir, data) out_file = _prepare_calls(out_file, os.path.dirname(out_dir), data) data["hla"].update({"call_file": out_file, "hlacaller": "optitype"}) return data def combine_hla_fqs(hlas, out_file, data): """OptiType performs best on a combination of all extracted HLAs. """ if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for hla_type, hla_fq in hlas: if utils.file_exists(hla_fq): with open(hla_fq) as in_handle: shutil.copyfileobj(in_handle, out_handle) return out_file def _prepare_calls(result_file, out_dir, data): """Write summary file of results of HLA typing by allele. """ sample = dd.get_sample_name(data) out_file = os.path.join(out_dir, "%s-optitype.csv" % (sample)) if not utils.file_uptodate(out_file, result_file): hla_truth = bwakit.get_hla_truthset(data) with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: writer = csv.writer(out_handle) allele_info = _parse_result_file(result_file) if len(allele_info) == 1: writer.writerow(["sample", "locus", "alleles", "expected", "validates"]) else: writer.writerow(["sample", "local", "index", "alleles", "score"]) for j, (alleles, score) in enumerate(allele_info): for hla_locus, call_alleles in alleles: truth_alleles = tz.get_in([sample, hla_locus], hla_truth, []) if len(allele_info) == 1: writer.writerow([sample, hla_locus, ";".join(call_alleles), ";".join(truth_alleles), bwakit.matches_truth(call_alleles, truth_alleles, data)]) else: writer.writerow([sample, hla_locus, j, ";".join(call_alleles), score]) return out_file def _parse_result_file(result_file): with open(result_file) as in_handle: header = in_handle.readline().rstrip("\r\n").split("\t") all_locus_is = [] for hla_locus in SUPPORTED_HLAS: hla_locus = hla_locus.replace("HLA-", "") all_locus_is.append((hla_locus, [i for i, h in enumerate(header) if h.startswith(hla_locus)])) score_i = [i for i, h in enumerate(header) if h == "Objective"][0] hits = [] for line in in_handle: hit = line.rstrip("\r\n").split("\t") assert len(hit) == len(header), result_file cur_hlas = [] for hla_locus, locus_is in all_locus_is: cur_hlas.append((hla_locus, ["HLA-%s" % hit[i] for i in locus_is])) hits.append((cur_hlas, hit[score_i])) return hits def _call_hla(hla_fq, out_dir, data): """Run OptiType HLA calling for a specific fastq input.""" out_dir = utils.safe_makedir(out_dir) with tx_tmpdir(data, os.path.dirname(out_dir)) as tx_out_dir: config_file = os.path.join(tx_out_dir, "config.ini") with open(config_file, "w") as out_handle: razers3 = os.path.realpath(utils.which("razers3")) if not os.path.exists(razers3): raise ValueError(f"Could not find razers3 executable at {razers3}") out_handle.write(CONFIG_TMPL.format(razers3=razers3, cores=dd.get_cores(data))) resources = config_utils.get_resources("optitype", data["config"]) if resources.get("options"): opts = " ".join([str(x) for x in resources["options"]]) else: opts = "" # optitype is looking for the reference in ./data which is in env/python3.6 not in tools/bin optitype = os.path.realpath(utils.which("OptiTypePipeline.py")) # techically, optitype is not a python package, conda is not able to set up its shebang properly python_bin = os.path.join(os.path.dirname(optitype), "python") cmd = f"{python_bin} {optitype} -v --dna {opts} -o {tx_out_dir} --enumerate 10 "\ f" -i {hla_fq} -c {config_file}" do.run(cmd, "HLA typing with OptiType") for outf in os.listdir(tx_out_dir): shutil.move(os.path.join(tx_out_dir, outf), os.path.join(out_dir, outf)) out_file = glob.glob(os.path.join(out_dir, "*", "*_result.tsv")) assert len(out_file) == 1, "Expected one result file for OptiType, found %s" % out_file return out_file[0] CONFIG_TMPL = """ [mapping] razers3={razers3} threads={cores} [ilp] solver=cbc threads={cores} [behavior] deletebam=true unpaired_weight=0 use_discordant=false """ bcbio-nextgen-1.2.9/bcbio/hmmer/000077500000000000000000000000001415626112400164375ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/hmmer/__init__.py000066400000000000000000000000511415626112400205440ustar00rootroot00000000000000"""Utilities for dealing with HMMER. """ bcbio-nextgen-1.2.9/bcbio/hmmer/search.py000066400000000000000000000072031415626112400202600ustar00rootroot00000000000000"""Search using HMMER's online REST interface. http://hmmer.janelia.org/search From Nick Loman's EntrezAjax: https://github.com/nickloman/entrezajax """ from __future__ import print_function from six.moves import urllib import logging class SmartRedirectHandler(urllib.request.HTTPRedirectHandler): def http_error_302(self, req, fp, code, msg, headers): logging.debug(headers) return headers def _hmmer(endpoint, args1, args2): opener = urllib.request.build_opener(SmartRedirectHandler()) urllib.request.install_opener(opener); params = urllib.parse.urlencode(args1) try: req = urllib.request.Request(endpoint, data = params, headers={"Accept" : "application/json"}) v = urllib.request.urlopen(req) except urllib.error.HTTPError as e: raise Exception("HTTP Error 400: %s" % e.read()) results_url = v['location'] enc_res_params = urllib.parse.urlencode(args2) modified_res_url = results_url + '?' + enc_res_params results_request = urllib.request.Request(modified_res_url) f = urllib.request.urlopen(results_request) return f def phmmer(**kwargs): """Search a protein sequence against a HMMER sequence database. Arguments: seq - The sequence to search -- a Fasta string. seqdb -- Sequence database to search against. range -- A string range of results to return (ie. 1,10 for the first ten) output -- The output format (defaults to JSON). """ logging.debug(kwargs) args = {'seq' : kwargs.get('seq'), 'seqdb' : kwargs.get('seqdb')} args2 = {'output' : kwargs.get('output', 'json'), 'range' : kwargs.get('range')} return _hmmer("http://hmmer.janelia.org/search/phmmer", args, args2) def hmmscan(**kwargs): logging.debug(kwargs) args = {'seq' : kwargs.get('seq'), 'hmmdb' : kwargs.get('hmmdb')} args2 = {'output' : 'json'} range = kwargs.get('range', None) if range: args2['range'] = range return _hmmer("http://hmmer.janelia.org/search/hmmscan", args, args2) def test(): seq = """>lcl||YPD4_1219|ftsK|128205128 putative cell division protein MSQEYTEDKEVTLKKLSNGRRLLEAVLIVVTILAAYLMVALVSFNPSDPSWSQTAWHEPI HNLGGSIGAWMADTLFSTFGVLAYAIPPIMVIFCWTAFRQRDASEYLDYFALSLRLIGTL ALILTSCGLAALNIDDLYYFASGGVIGSLFSNAMLPWFNGVGATLTLLCIWVVGLTLFTG WSWLVIAEKIGAAVLGSLTFITNRSRREERYDDEDSYHDDDHADGRDITGQEKGVVSNKG VVSNNAVVGAGVAASSALAHGDDDVLFSAPSVTDSIVEHGSVVATGTETTDTKATDTNDE YDPLLSPLRATDYSVQDATSSPIADVAVEPVLNHDAAAIYGTTPVMTNTATPPLYSFELP EESLPIQTHAAPTERPEPKLGAWDMSPTPVSHSPFDFSAIQRPVGQLESRQPGSNQSGSH QIHSAQSSHISVGNTPYMNPGLDAQIDGLSTTSLTNKPVLASGTVAAATAAAAFMPAFTA TSDSSSQIKQGIGPELPRPNPVRIPTRRELASFGIKLPSQRMAEQELRERDGDETQNPQM AASSYGTEITSDEDAALQQAILRKAFADQQSERYALSTLAEQSSITERSPAAEMPTTPSQ VSDLEDEQALQEAELRQAFAAQQQHRYGATGDTDNAVDNIRSVDTSTAFTFSPIADLVDD SPREPLFTLSPYVDETDVDEPVQLEGKEESLLQDYPEQVPTYQPPVQQAHLGQSAPTQPS HTQSTYGQSTYGQSTYGQSTPAPVSQPVVTSASAISTSVTPTSIASLNTAPVSAAPVAPS PQPPAFSQPTAAMDSLIHPFLMRNDQPLQKPTTPLPTLDLLSSPPAEEEPVDMFALEQTA RLVEARLGDYRVKAEVVGISPGPVITRFELDLAPGVKASRISNLSRDLARSLSAIAVRVV EVIPGKPYVGLELPNKHRQTVYLREVLDCAKFRENPSPLAIVLGKDIAGQPVVADLAKMP HLLVAGTTGSGKSVGVNAMILSILYKATPDDVRFIMIDPKMLELSVYEGIPHLLTGVVTD MKDAANALRWCVGEMERRYKLMSALGVRNLAGYNERVAQAEAMGRPIPDPFWKPSDSMDI SPPMLVKLPYIVVMVDEFADLMMTVGKKVEELIARLAQKARAAGIHLVLATQRPSVDVIT GLIKANIPTRIAFTVSSKIDSRTILDQGGAESLLGMGDMLYMAPNSSIPVRVHGAFVRDQ EVHAVVNDWKARGRPQYIDSILSGGEEGEGGGLGLDSDEELDPLFDQAVNFVLEKRRASI SGVQRQFRIGYNRAARIIEQMEAQQIVSTPGHNGNREVLAPPPHE""" handle = hmmscan(hmmdb = 'pfam', seq = seq) import json j = json.loads(handle.read()) print(json.dumps(j, sort_keys=True, indent=4)) # test() bcbio-nextgen-1.2.9/bcbio/illumina/000077500000000000000000000000001415626112400171415ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/illumina/__init__.py000066400000000000000000000001021415626112400212430ustar00rootroot00000000000000"""Integration with Illumina sequencing machines and outputs. """ bcbio-nextgen-1.2.9/bcbio/illumina/demultiplex.py000066400000000000000000000044371415626112400220570ustar00rootroot00000000000000"""Demultiplex and fastq conversion from Illumina output directories. Uses Illumina's bcl2fastq: http://support.illumina.com/downloads/bcl2fastq_conversion_software_184.ilmn """ import os import subprocess import time from bcbio import utils def run_bcl2fastq(run_folder, ss_csv, config): """Run bcl2fastq for de-multiplexing and fastq generation. run_folder -- directory of Illumina outputs ss_csv -- Samplesheet CSV file describing samples. """ bc_dir = os.path.join(run_folder, "Data", "Intensities", "BaseCalls") output_dir = os.path.join(run_folder, "fastq") if not os.path.exists(os.path.join(output_dir, "Makefile")): subprocess.check_call(["configureBclToFastq.pl", "--no-eamss", "--input-dir", bc_dir, "--output-dir", output_dir, "--sample-sheet", ss_csv]) with utils.chdir(output_dir): cores = str(utils.get_in(config, ("algorithm", "num_cores"), 1)) cmd = ["make", "-j", cores] if "submit_cmd" in config["process"] and "bcl2fastq_batch" in config["process"]: _submit_and_wait(cmd, cores, config, output_dir) else: subprocess.check_call(cmd) return output_dir def _submit_and_wait(cmd, cores, config, output_dir): """Submit command with batch script specified in configuration, wait until finished """ batch_script = "submit_bcl2fastq.sh" if not os.path.exists(batch_script + ".finished"): if os.path.exists(batch_script + ".failed"): os.remove(batch_script + ".failed") with open(batch_script, "w") as out_handle: out_handle.write(config["process"]["bcl2fastq_batch"].format( cores=cores, bcl2fastq_cmd=" ".join(cmd), batch_script=batch_script)) submit_cmd = utils.get_in(config, ("process", "submit_cmd")) subprocess.check_call(submit_cmd.format(batch_script=batch_script), shell=True) # wait until finished or failure checkpoint file while 1: if os.path.exists(batch_script + ".finished"): break if os.path.exists(batch_script + ".failed"): raise ValueError("bcl2fastq batch script failed: %s" % os.path.join(output_dir, batch_script)) time.sleep(5) bcbio-nextgen-1.2.9/bcbio/illumina/flowcell.py000066400000000000000000000057111415626112400213260ustar00rootroot00000000000000"""Utilities to manage processing flowcells and retrieving Galaxy stored info. """ import os import glob from six.moves import urllib, http_cookiejar import json def parse_dirname(fc_dir): """Parse the flow cell ID and date from a flow cell directory. """ (_, fc_dir) = os.path.split(fc_dir) parts = fc_dir.split("_") name = None date = None for p in parts: if p.endswith(("XX", "xx", "XY", "X2", "X3")): name = p elif len(p) == 6: try: int(p) date = p except ValueError: pass if name is None or date is None: raise ValueError("Did not find flowcell name: %s" % fc_dir) return name, date def get_qseq_dir(fc_dir): """Retrieve the qseq directory within Solexa flowcell output. """ machine_bc = os.path.join(fc_dir, "Data", "Intensities", "BaseCalls") if os.path.exists(machine_bc): return machine_bc # otherwise assume we are in the qseq directory # XXX What other cases can we end up with here? else: return fc_dir def get_fastq_dir(fc_dir): """Retrieve the fastq directory within Solexa flowcell output. """ full_goat_bc = glob.glob(os.path.join(fc_dir, "Data", "*Firecrest*", "Bustard*")) bustard_bc = glob.glob(os.path.join(fc_dir, "Data", "Intensities", "*Bustard*")) machine_bc = os.path.join(fc_dir, "Data", "Intensities", "BaseCalls") if os.path.exists(machine_bc): return os.path.join(machine_bc, "fastq") elif len(full_goat_bc) > 0: return os.path.join(full_goat_bc[0], "fastq") elif len(bustard_bc) > 0: return os.path.join(bustard_bc[0], "fastq") # otherwise assume we are in the fastq directory # XXX What other cases can we end up with here? else: return fc_dir class GalaxySqnLimsApi: """Manage talking with the Galaxy REST api for sequencing information. """ def __init__(self, base_url, user, passwd): self._base_url = base_url # build cookies so we keep track of being logged in cj = http_cookiejar.LWPCookieJar() opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj)) urllib.request.install_opener(opener) login = dict(email=user, password=passwd, login_button='Login') req = urllib.request.Request("%s/user/login" % self._base_url, urllib.parse.urlencode(login)) response = urllib.request.urlopen(req) def run_details(self, run): """Retrieve sequencing run details as a dictionary. """ run_data = dict(run=run) req = urllib.request.Request("%s/nglims/api_run_details" % self._base_url, urllib.parse.urlencode(run_data)) response = urllib.request.urlopen(req) info = json.loads(response.read()) if "error" in info: raise ValueError("Problem retrieving info: %s" % info["error"]) else: return info["details"] bcbio-nextgen-1.2.9/bcbio/illumina/machine.py000066400000000000000000000161051415626112400211220ustar00rootroot00000000000000"""Support integration with Illumina sequencer machines. """ from __future__ import print_function import glob import json import os import operator import subprocess from xml.etree.ElementTree import ElementTree import requests import yaml from bcbio import utils from bcbio.log import setup_local_logging from bcbio.illumina import demultiplex, samplesheet, transfer from bcbio.galaxy import nglims from functools import reduce # ## bcbio-nextgen integration def check_and_postprocess(args): """Check for newly dumped sequencer output, post-processing and transferring. """ with open(args.process_config) as in_handle: config = yaml.safe_load(in_handle) setup_local_logging(config) for dname in _find_unprocessed(config): lane_details = nglims.get_runinfo(config["galaxy_url"], config["galaxy_apikey"], dname, utils.get_in(config, ("process", "storedir"))) if isinstance(lane_details, dict) and "error" in lane_details: print("Flowcell not found in Galaxy: %s" % lane_details) else: lane_details = _tweak_lane(lane_details, dname) fcid_ss = samplesheet.from_flowcell(dname, lane_details) _update_reported(config["msg_db"], dname) fastq_dir = demultiplex.run_bcl2fastq(dname, fcid_ss, config) bcbio_config, ready_fastq_dir = nglims.prep_samples_and_config(dname, lane_details, fastq_dir, config) transfer.copy_flowcell(dname, ready_fastq_dir, bcbio_config, config) _start_processing(dname, bcbio_config, config) def _tweak_lane(lane_details, dname): """Potentially tweak lane information to handle custom processing, reading a lane_config.yaml file. """ tweak_config_file = os.path.join(dname, "lane_config.yaml") if os.path.exists(tweak_config_file): with open(tweak_config_file) as in_handle: tweak_config = yaml.safe_load(in_handle) if tweak_config.get("uniquify_lanes"): out = [] for ld in lane_details: ld["name"] = "%s-%s" % (ld["name"], ld["lane"]) out.append(ld) return out return lane_details def _remap_dirname(local, remote): """Remap directory names from local to remote. """ def do(x): return x.replace(local, remote, 1) return do def _start_processing(dname, sample_file, config): """Initiate processing: on a remote server or locally on a cluster. """ to_remote = _remap_dirname(dname, os.path.join(utils.get_in(config, ("process", "dir")), os.path.basename(dname))) args = {"work_dir": to_remote(os.path.join(dname, "analysis")), "run_config": to_remote(sample_file), "fc_dir": to_remote(dname)} # call a remote server if utils.get_in(config, ("process", "server")): print("%s/run?args=%s" % (utils.get_in(config, ("process", "server")), json.dumps(args))) requests.get(url="%s/run" % utils.get_in(config, ("process", "server")), params={"args": json.dumps(args)}) # submit to a cluster scheduler elif "submit_cmd" in config["process"] and "bcbio_batch" in config["process"]: with utils.chdir(utils.safe_makedir(args["work_dir"])): batch_script = "submit_bcbio.sh" with open(batch_script, "w") as out_handle: out_handle.write(config["process"]["bcbio_batch"].format(fcdir=args["fc_dir"], run_config=args["run_config"])) submit_cmd = utils.get_in(config, ("process", "submit_cmd")) subprocess.check_call(submit_cmd.format(batch_script=batch_script), shell=True) else: raise ValueError("Unexpected processing approach: %s" % config["process"]) def add_subparser(subparsers): """Add command line arguments for post-processing sequencer results. """ parser = subparsers.add_parser("sequencer", help="Post process results from a sequencer.") parser.add_argument("process_config", help="YAML file specifying sequencer details for post-processing.") return parser # ## Dump directory processing def _find_unprocessed(config): """Find any finished directories that have not been processed. """ reported = _read_reported(config["msg_db"]) for dname in _get_directories(config): if os.path.isdir(dname) and dname not in reported: if _is_finished_dumping(dname): yield dname def _get_directories(config): for directory in config["dump_directories"]: for dname in sorted(glob.glob(os.path.join(directory, "*[Aa]*[Xx][XxYy23]"))): if os.path.isdir(dname): yield dname def _is_finished_dumping(directory): """Determine if the sequencing directory has all files. The final checkpoint file will differ depending if we are a single or paired end run. """ #if _is_finished_dumping_checkpoint(directory): # return True # Check final output files; handles both HiSeq and GAII run_info = os.path.join(directory, "RunInfo.xml") hi_seq_checkpoint = "Basecalling_Netcopy_complete_Read%s.txt" % \ _expected_reads(run_info) to_check = ["Basecalling_Netcopy_complete_SINGLEREAD.txt", "Basecalling_Netcopy_complete_READ2.txt", hi_seq_checkpoint] return reduce(operator.or_, [os.path.exists(os.path.join(directory, f)) for f in to_check]) def _is_finished_dumping_checkpoint(directory): """Recent versions of RTA (1.10 or better), write the complete file. This is the most straightforward source but as of 1.10 still does not work correctly as the file will be created at the end of Read 1 even if there are multiple reads. """ check_file = os.path.join(directory, "Basecalling_Netcopy_complete.txt") check_v1, check_v2 = (1, 10) if os.path.exists(check_file): with open(check_file) as in_handle: line = in_handle.readline().strip() if line: version = line.split()[-1] v1, v2 = [float(v) for v in version.split(".")[:2]] if ((v1 > check_v1) or (v1 == check_v1 and v2 >= check_v2)): return True def _expected_reads(run_info_file): """Parse the number of expected reads from the RunInfo.xml file. """ reads = [] if os.path.exists(run_info_file): tree = ElementTree() tree.parse(run_info_file) read_elem = tree.find("Run/Reads") reads = read_elem.findall("Read") return len(reads) # ## Flat file of processed directories def _read_reported(msg_db): """Retrieve a list of directories previous reported. """ reported = [] if os.path.exists(msg_db): with open(msg_db) as in_handle: for line in in_handle: reported.append(line.strip()) return reported def _update_reported(msg_db, new_dname): """Add a new directory to the database of reported messages. """ with open(msg_db, "a") as out_handle: out_handle.write("%s\n" % new_dname) bcbio-nextgen-1.2.9/bcbio/illumina/samplesheet.py000066400000000000000000000117071415626112400220330ustar00rootroot00000000000000"""Converts Illumina SampleSheet CSV files to the run_info.yaml input file. This allows running the analysis pipeline without Galaxy, using CSV input files from Illumina SampleSheet or Genesifter. """ import os import csv import itertools import difflib import glob import io import yaml from bcbio.illumina import flowcell from bcbio import utils # ## Create samplesheets def from_flowcell(run_folder, lane_details, out_dir=None): """Convert a flowcell into a samplesheet for demultiplexing. """ fcid = os.path.basename(run_folder) if out_dir is None: out_dir = run_folder out_file = os.path.join(out_dir, "%s.csv" % fcid) with open(out_file, "w") as out_handle: writer = csv.writer(out_handle) writer.writerow(["FCID", "Lane", "Sample_ID", "SampleRef", "Index", "Description", "Control", "Recipe", "Operator", "SampleProject"]) for ldetail in lane_details: writer.writerow(_lane_detail_to_ss(fcid, ldetail)) return out_file def _lane_detail_to_ss(fcid, ldetail): """Convert information about a lane into Illumina samplesheet output. """ return [fcid, ldetail["lane"], ldetail["name"], ldetail["genome_build"], ldetail["bc_index"], ldetail["description"].encode("ascii", "ignore"), "N", "", "", ldetail["project_name"]] # ## Use samplesheets to create YAML files def _organize_lanes(info_iter, barcode_ids): """Organize flat lane information into nested YAML structure. """ all_lanes = [] for (fcid, lane, sampleref), info in itertools.groupby(info_iter, lambda x: (x[0], x[1], x[1])): info = list(info) cur_lane = dict(flowcell_id=fcid, lane=lane, genome_build=info[0][3], analysis="Standard") if not _has_barcode(info): cur_lane["description"] = info[0][1] else: # barcoded sample cur_lane["description"] = "Barcoded lane %s" % lane multiplex = [] for (_, _, sample_id, _, bc_seq) in info: bc_type, bc_id = barcode_ids[bc_seq] multiplex.append(dict(barcode_type=bc_type, barcode_id=bc_id, sequence=bc_seq, name=sample_id)) cur_lane["multiplex"] = multiplex all_lanes.append(cur_lane) return all_lanes def _has_barcode(sample): if sample[0][4]: return True def _generate_barcode_ids(info_iter): """Create unique barcode IDs assigned to sequences """ bc_type = "SampleSheet" barcodes = list(set([x[-1] for x in info_iter])) barcodes.sort() barcode_ids = {} for i, bc in enumerate(barcodes): barcode_ids[bc] = (bc_type, i+1) return barcode_ids def _read_input_csv(in_file): """Parse useful details from SampleSheet CSV file. """ with io.open(in_file, newline=None) as in_handle: reader = csv.reader(in_handle) next(reader) # header for line in reader: if line: # empty lines (fc_id, lane, sample_id, genome, barcode) = line[:5] yield fc_id, lane, sample_id, genome, barcode def _get_flowcell_id(in_file, require_single=True): """Retrieve the unique flowcell id represented in the SampleSheet. """ fc_ids = set([x[0] for x in _read_input_csv(in_file)]) if require_single and len(fc_ids) > 1: raise ValueError("There are several FCIDs in the same samplesheet file: %s" % in_file) else: return fc_ids def csv2yaml(in_file, out_file=None): """Convert a CSV SampleSheet to YAML run_info format. """ if out_file is None: out_file = "%s.yaml" % os.path.splitext(in_file)[0] barcode_ids = _generate_barcode_ids(_read_input_csv(in_file)) lanes = _organize_lanes(_read_input_csv(in_file), barcode_ids) with open(out_file, "w") as out_handle: out_handle.write(yaml.safe_dump(lanes, default_flow_style=False)) return out_file def run_has_samplesheet(fc_dir, config, require_single=True): """Checks if there's a suitable SampleSheet.csv present for the run """ fc_name, _ = flowcell.parse_dirname(fc_dir) sheet_dirs = config.get("samplesheet_directories", []) fcid_sheet = {} for ss_dir in (s for s in sheet_dirs if os.path.exists(s)): with utils.chdir(ss_dir): for ss in glob.glob("*.csv"): fc_ids = _get_flowcell_id(ss, require_single) for fcid in fc_ids: if fcid: fcid_sheet[fcid] = os.path.join(ss_dir, ss) # difflib handles human errors while entering data on the SampleSheet. # Only one best candidate is returned (if any). 0.85 cutoff allows for # maximum of 2 mismatches in fcid potential_fcids = difflib.get_close_matches(fc_name, fcid_sheet.keys(), 1, 0.85) if len(potential_fcids) > 0 and potential_fcids[0] in fcid_sheet: return fcid_sheet[potential_fcids[0]] else: return None bcbio-nextgen-1.2.9/bcbio/illumina/transfer.py000066400000000000000000000037661415626112400213530ustar00rootroot00000000000000"""Transfer files from sequencer to remote analysis machine. """ import glob import operator import os import subprocess from bcbio import utils from bcbio.log import logger from functools import reduce def copy_flowcell(dname, fastq_dir, sample_cfile, config): """Copy required files for processing using rsync, potentially to a remote server. """ with utils.chdir(dname): reports = reduce(operator.add, [glob.glob("*.xml"), glob.glob("Data/Intensities/BaseCalls/*.xml"), glob.glob("Data/Intensities/BaseCalls/*.xsl"), glob.glob("Data/Intensities/BaseCalls/*.htm"), ["Data/Intensities/BaseCalls/Plots", "Data/reports", "Data/Status.htm", "Data/Status_Files", "InterOp"]]) run_info = reduce(operator.add, [glob.glob("run_info.yaml"), glob.glob("*.csv")]) fastq = glob.glob(os.path.join(fastq_dir.replace(dname + "/", "", 1), "*.gz")) configs = [sample_cfile.replace(dname + "/", "", 1)] include_file = os.path.join(dname, "transfer_files.txt") with open(include_file, "w") as out_handle: out_handle.write("+ */\n") for fname in configs + fastq + run_info + reports: out_handle.write("+ %s\n" % fname) out_handle.write("- *\n") # remote transfer if utils.get_in(config, ("process", "host")): dest = "%s@%s:%s" % (utils.get_in(config, ("process", "username")), utils.get_in(config, ("process", "host")), utils.get_in(config, ("process", "dir"))) # local transfer else: dest = utils.get_in(config, ("process", "dir")) cmd = ["rsync", "-akmrtv", "--include-from=%s" % include_file, dname, dest] logger.info("Copying files to analysis machine") logger.info(" ".join(cmd)) subprocess.check_call(cmd) bcbio-nextgen-1.2.9/bcbio/install.py000066400000000000000000001107021415626112400173500ustar00rootroot00000000000000"""Handle installation and updates of bcbio-nextgen, third party software and data. Enables automated installation tool and in-place updates to install additional data and software. """ from __future__ import print_function import argparse import collections import contextlib import datetime import dateutil from distutils.version import LooseVersion import gzip import json import os import shutil import subprocess import sys import glob import six from six.moves import urllib import toolz as tz import yaml from bcbio import broad, utils from bcbio.cwl import create from bcbio.pipeline import genome, version from bcbio.variation import effects from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd REMOTES = { "requirements": "https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/requirements-conda.txt", "gitrepo": "https://github.com/bcbio/bcbio-nextgen/archive/%s.tar.gz", "cloudbiolinux": "https://github.com/chapmanb/cloudbiolinux/archive/%s.tar.gz", "genome_resources": "https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/genomes/%s-resources.yaml", "snpeff_dl_url": ("https://snpeff.blob.core.windows.net/databases/v{snpeff_ver}/" "snpEff_v{snpeff_ver}_{genome}.zip")} SUPPORTED_GENOMES = ["GRCh37", "hg19", "hg38", "hg38-noalt", "mm10", "mm9", "rn6", "rn5", "canFam3", "dm3", "galGal4", "phix", "pseudomonas_aeruginosa_ucbpp_pa14", "sacCer3", "TAIR10", "WBcel235", "xenTro3", "GRCz10", "GRCz11", "Sscrofa11.1", "BDGP6"] TARBALL_DIRECTORIES = ["bwa", "rtg", "hisat2"] SUPPORTED_INDEXES = TARBALL_DIRECTORIES +\ ["bbmap", "bowtie", "bowtie2", "minimap2", "novoalign", "twobit", "bismark", "snap", "star", "seq"] DEFAULT_INDEXES = ["rtg"] Tool = collections.namedtuple("Tool", ["name", "fname"]) def upgrade_bcbio(args): """Perform upgrade of bcbio to latest release, or from GitHub development version. Handles bcbio, third party tools and data. """ print("Upgrading bcbio") args = add_install_defaults(args) if args.upgrade in ["stable", "system", "deps", "development"]: if args.upgrade == "development": anaconda_dir = _update_conda_latest() _check_for_conda_problems() print("Upgrading bcbio-nextgen to latest development version") pip_bin = os.path.join(os.path.dirname(os.path.realpath(sys.executable)), "pip") # default is master # egg installation with --update is not always working git_url = REMOTES["gitrepo"] % args.revision _pip_safe_ssl([[pip_bin, "install", "--force-reinstall", "--no-deps", git_url]], anaconda_dir) print("Upgrade of bcbio-nextgen development code complete.") else: _update_conda_packages() _check_for_conda_problems() print("Upgrade of bcbio-nextgen code complete.") if args.cwl and args.upgrade: _update_bcbiovm() try: _set_matplotlib_default_backend() except OSError: pass if args.tooldir: with bcbio_tmpdir(): print("Upgrading third party tools to latest versions") _symlink_bcbio(args, script="bcbio_nextgen.py") _symlink_bcbio(args, script="bcbio_setup_genome.py") _symlink_bcbio(args, script="bcbio_prepare_samples.py") _symlink_bcbio(args, script="bcbio_fastq_umi_prep.py") if args.cwl: _symlink_bcbio(args, "bcbio_vm.py", "bcbiovm") _symlink_bcbio(args, "python", "bcbiovm", "bcbiovm") upgrade_thirdparty_tools(args, REMOTES) print("Third party tools upgrade complete.") if args.toolplus: print("Installing additional tools") _install_toolplus(args) if args.install_data: for default in DEFAULT_INDEXES: if default not in args.aligners: args.aligners.append(default) if len(args.aligners) == 0: print("Warning: no aligners provided with `--aligners` flag") if len(args.genomes) == 0: print("Data not installed, no genomes provided with `--genomes` flag") else: with bcbio_tmpdir(): print("Upgrading bcbio-nextgen data files") upgrade_bcbio_data(args, REMOTES) print("bcbio-nextgen data upgrade complete.") if args.isolate and args.tooldir: print("Isolated tool installation not automatically added to environmental variables") print(" Add:\n {t}/bin to PATH".format(t=args.tooldir)) save_install_defaults(args) args.datadir = _get_data_dir() _install_container_bcbio_system(args.datadir) print("Upgrade completed successfully.") return args def _pip_safe_ssl(cmds, anaconda_dir): """Run pip, retrying with conda SSL certificate if global certificate fails. """ try: for cmd in cmds: subprocess.check_call(cmd) except subprocess.CalledProcessError: _set_pip_ssl(anaconda_dir) for cmd in cmds: subprocess.check_call(cmd) def _set_pip_ssl(anaconda_dir): """Set PIP SSL certificate to installed conda certificate to avoid SSL errors """ if anaconda_dir: cert_file = os.path.join(anaconda_dir, "ssl", "cert.pem") if os.path.exists(cert_file): os.environ["PIP_CERT"] = cert_file def _set_matplotlib_default_backend(): """ matplotlib will try to print to a display if it is available, but don't want to run it in interactive mode. we tried setting the backend to 'Agg'' before importing, but it was still resulting in issues. we replace the existing backend with 'agg' in the default matplotlibrc. This is a hack until we can find a better solution """ if _matplotlib_installed(): import matplotlib matplotlib.use('Agg', force=True) config = matplotlib.matplotlib_fname() if os.access(config, os.W_OK): with file_transaction(config) as tx_out_file: with open(config) as in_file, open(tx_out_file, "w") as out_file: for line in in_file: if line.split(":")[0].strip() == "backend": out_file.write("backend: agg\n") else: out_file.write(line) def _matplotlib_installed(): try: import matplotlib except ImportError: return False return True def _symlink_bcbio(args, script="bcbio_nextgen.py", env_name=None, prefix=None): """Ensure a bcbio-nextgen script symlink in final tool directory. """ if env_name: bcbio_anaconda = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(sys.executable))), "envs", env_name, "bin", script) else: bcbio_anaconda = os.path.join(os.path.dirname(os.path.realpath(sys.executable)), script) bindir = os.path.join(args.tooldir, "bin") if not os.path.exists(bindir): os.makedirs(bindir) if prefix: script = "%s_%s" % (prefix, script) bcbio_final = os.path.join(bindir, script) if not os.path.exists(bcbio_final): if os.path.lexists(bcbio_final): subprocess.check_call(["rm", "-f", bcbio_final]) subprocess.check_call(["ln", "-s", bcbio_anaconda, bcbio_final]) def _install_container_bcbio_system(datadir): """Install limited bcbio_system.yaml file for setting core and memory usage. Adds any non-specific programs to the exposed bcbio_system.yaml file, only when upgrade happening inside a docker container. """ base_file = os.path.join(datadir, "config", "bcbio_system.yaml") if not os.path.exists(base_file): return expose_file = os.path.join(datadir, "galaxy", "bcbio_system.yaml") expose = set(["memory", "cores", "jvm_opts"]) with open(base_file) as in_handle: config = yaml.safe_load(in_handle) if os.path.exists(expose_file): with open(expose_file) as in_handle: expose_config = yaml.safe_load(in_handle) else: expose_config = {"resources": {}} for pname, vals in config["resources"].items(): expose_vals = {} for k, v in vals.items(): if k in expose: expose_vals[k] = v if len(expose_vals) > 0 and pname not in expose_config["resources"]: expose_config["resources"][pname] = expose_vals if expose_file and os.path.exists(os.path.dirname(expose_file)): with open(expose_file, "w") as out_handle: yaml.safe_dump(expose_config, out_handle, default_flow_style=False, allow_unicode=False) return expose_file def _get_conda_bin(): conda_bin = os.path.join(os.path.dirname(os.path.realpath(sys.executable)), "conda") if os.path.exists(conda_bin): return conda_bin def _get_mamba_bin(): mamba_bin = os.path.join(os.path.dirname(os.path.realpath(sys.executable)), "mamba") if os.path.exists(mamba_bin): return mamba_bin def _check_for_conda_problems(): """Identify post-install conda problems and fix. - libgcc upgrades can remove libquadmath, which moved to libgcc-ng """ conda_bin = _get_conda_bin() lib_dir = os.path.join(os.path.dirname(conda_bin), os.pardir, "lib") for l in ["libgomp.so.1", "libquadmath.so"]: if not os.path.exists(os.path.join(lib_dir, l)): subprocess.check_call([conda_bin, "install", "-f", "--yes", "libgcc-ng"]) def _update_bcbiovm(): """Update or install a local bcbiovm install with tools and dependencies""" print("## CWL support with bcbio-vm") python_env = "python=3.7" conda_bin, env_name = _add_environment("bcbiovm", python_env) base_cmd = [conda_bin, "install", "--yes", "--name", env_name] subprocess.check_call(base_cmd + [python_env, "nomkl", "bcbio-nextgen"]) extra_uptodate = ["cromwell"] subprocess.check_call(base_cmd + [python_env, "bcbio-nextgen-vm"] + extra_uptodate) def _get_envs(conda_bin): info = json.loads(subprocess.check_output("{conda_bin} info --envs --json".format(**locals()), shell=True)) return [e for e in info["envs"] if e.startswith(info["conda_prefix"])] def _add_environment(addenv, deps): conda_bin = _get_conda_bin() conda_envs = _get_envs(conda_bin) if not any(x.endswith("/%s" % addenv) for x in conda_envs): subprocess.check_call("{conda_bin} create --no-default-packages -y " "--name {addenv} {deps}".format(**locals()), shell=True) conda_envs = _get_envs(conda_bin) return conda_bin, addenv def _update_conda_packages(): """If installed in an anaconda directory, upgrade conda packages""" conda_bin = _get_mamba_bin() if not conda_bin: conda_bin = _get_conda_bin() assert conda_bin, ("Could not find anaconda distribution for upgrading bcbio.\n" "Using python at %s but could not find conda." % (os.path.realpath(sys.executable))) req_file = "bcbio-update-requirements.txt" if os.path.exists(req_file): os.remove(req_file) subprocess.check_call(["wget", "-O", req_file, "--no-check-certificate", REMOTES["requirements"]]) subprocess.check_call([conda_bin, "install", "--quiet", "--yes", "--file", req_file]) if os.path.exists(req_file): os.remove(req_file) return os.path.dirname(os.path.dirname(conda_bin)) def _update_conda_latest(): """Update to the latest bcbio conda package""" conda_bin = _get_conda_bin() output = subprocess.run([conda_bin, "search", "-c", "bioconda", "bcbio-nextgen"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout lines = [l for l in output.decode().split("\n") if l] latest = lines.pop() tokens = latest.split() conda_version = tokens[1].strip() print(f"Detected {conda_version} as latest version of bcbio-nextgen on bioconda.") bcbio_version = version.__version__ if LooseVersion(bcbio_version) < LooseVersion(conda_version): print(f"Installing bcbio {conda_version} from bioconda.") subprocess.check_call([conda_bin, "install", "--quiet", "--yes", f"bcbio-nextgen>={conda_version}"]) else: print(f"bcbio version {bcbio_version} is newer than the conda version {conda_version}, " f"skipping upgrade from conda") return os.path.dirname(os.path.dirname(conda_bin)) def _update_conda_devel(): """Update to the latest development conda package""" conda_bin = _get_conda_bin() assert conda_bin, "Could not find anaconda distribution for upgrading bcbio" subprocess.check_call([conda_bin, "install", "--quiet", "--yes", "bcbio-nextgen>=%s" % version.__version__.replace("a0", "a")]) return os.path.dirname(os.path.dirname(conda_bin)) def get_genome_dir(gid, galaxy_dir, data): """Return standard location of genome directories. """ if galaxy_dir: refs = genome.get_refs(gid, None, galaxy_dir, data) seq_file = tz.get_in(["fasta", "base"], refs) if seq_file and os.path.exists(seq_file): return os.path.dirname(os.path.dirname(seq_file)) else: gdirs = glob.glob(os.path.join(_get_data_dir(), "genomes", "*", gid)) if len(gdirs) == 1 and os.path.exists(gdirs[0]): return gdirs[0] def _get_data_dir(): base_dir = os.path.realpath(os.path.dirname(os.path.dirname(os.path.realpath(sys.executable)))) if "anaconda" not in os.path.basename(base_dir) and "virtualenv" not in os.path.basename(base_dir): raise ValueError("Cannot update data for bcbio-nextgen not installed by installer.\n" "bcbio-nextgen needs to be installed inside an anaconda environment \n" "located in the same directory as the `genomes` directory.") return os.path.dirname(base_dir) def get_gemini_dir(data=None): try: data_dir = _get_data_dir() return os.path.join(data_dir, "gemini_data") except ValueError: if data: galaxy_dir = dd.get_galaxy_dir(data) data_dir = os.path.realpath(os.path.dirname(os.path.dirname(galaxy_dir))) return os.path.join(data_dir, "gemini_data") else: return None def upgrade_bcbio_data(args, remotes): """Upgrade required genome data files in place. """ if hasattr(args, "datadir") and args.datadir and os.path.exists(args.datadir): data_dir = args.datadir else: data_dir = _get_data_dir() tooldir = args.tooldir or get_defaults().get("tooldir") galaxy_home = os.path.join(data_dir, "galaxy") cbl = get_cloudbiolinux(args, remotes) tool_data_table_conf_file = os.path.join(cbl["dir"], "installed_files", "tool_data_table_conf.xml") genome_opts = _get_biodata(cbl["biodata"], args) sys.path.insert(0, cbl["dir"]) cbl_genomes = __import__("cloudbio.biodata.genomes", fromlist=["genomes"]) cbl_genomes.install_data_local(genome_opts, tooldir, data_dir, galaxy_home, tool_data_table_conf_file, args.cores, ["ggd", "s3", "raw"]) _upgrade_genome_resources(galaxy_home, remotes["genome_resources"]) _upgrade_snpeff_data(galaxy_home, args, remotes) if "vep" in args.datatarget: _upgrade_vep_data(galaxy_home, tooldir) if "kraken" in args.datatarget: _install_kraken_db(_get_data_dir(), args) if args.cwl: _prepare_cwl_tarballs(data_dir) def _prepare_cwl_tarballs(data_dir): """Create CWL ready tarballs for complex directories. Avoids need for CWL runners to pass and serialize complex directories of files, which is inconsistent between runners. """ for dbref_dir in filter(os.path.isdir, glob.glob(os.path.join(data_dir, "genomes", "*", "*"))): base_dir, dbref = os.path.split(dbref_dir) for indexdir in TARBALL_DIRECTORIES: cur_target = os.path.join(dbref_dir, indexdir) if os.path.isdir(cur_target): # Some indices, like rtg, have a single nested directory subdirs = [x for x in os.listdir(cur_target) if os.path.isdir(os.path.join(cur_target, x))] if len(subdirs) == 1: cur_target = os.path.join(cur_target, subdirs[0]) create.directory_tarball(cur_target) def _upgrade_genome_resources(galaxy_dir, base_url): """Retrieve latest version of genome resource YAML configuration files. """ import requests for dbkey, ref_file in genome.get_builds(galaxy_dir): # Check for a remote genome resources file remote_url = base_url % dbkey requests.packages.urllib3.disable_warnings() r = requests.get(remote_url, verify=False) if r.status_code == requests.codes.ok: local_file = os.path.join(os.path.dirname(ref_file), os.path.basename(remote_url)) if os.path.exists(local_file): with open(local_file) as in_handle: local_config = yaml.safe_load(in_handle) remote_config = yaml.safe_load(r.text) needs_update = remote_config["version"] > local_config.get("version", 0) if needs_update: shutil.move(local_file, local_file + ".old%s" % local_config.get("version", 0)) else: needs_update = True if needs_update: print("Updating %s genome resources configuration" % dbkey) with open(local_file, "w") as out_handle: out_handle.write(r.text) def _upgrade_vep_data(galaxy_dir, tooldir): for dbkey, ref_file in genome.get_builds(galaxy_dir): effects.prep_vep_cache(dbkey, ref_file, tooldir) def _upgrade_snpeff_data(galaxy_dir, args, remotes): """Install or upgrade snpEff databases, localized to reference directory.""" snpeff_version = effects.snpeff_version(args) if not snpeff_version: return for dbkey, ref_file in genome.get_builds(galaxy_dir): resource_file = os.path.join(os.path.dirname(ref_file), "%s-resources.yaml" % dbkey) if os.path.exists(resource_file): with open(resource_file) as in_handle: resources = yaml.safe_load(in_handle) snpeff_db, snpeff_base_dir = effects.get_db({"genome_resources": resources, "reference": {"fasta": {"base": ref_file}}}) if snpeff_db: snpeff_db_dir = os.path.join(snpeff_base_dir, snpeff_db) if os.path.exists(snpeff_db_dir) and _is_old_database(snpeff_db_dir, args): shutil.rmtree(snpeff_db_dir) if not os.path.exists(snpeff_db_dir): print("Installing snpEff database %s in %s" % (snpeff_db, snpeff_base_dir)) dl_url = remotes["snpeff_dl_url"].format( snpeff_ver=snpeff_version.replace(".", "_"), genome=snpeff_db) dl_file = os.path.basename(dl_url) with utils.chdir(snpeff_base_dir): subprocess.check_call(["wget", "--no-check-certificate", "-c", "-O", dl_file, dl_url]) subprocess.check_call(["unzip", dl_file]) os.remove(dl_file) dl_dir = os.path.join(snpeff_base_dir, "data", snpeff_db) shutil.move(dl_dir, snpeff_db_dir) os.rmdir(os.path.join(snpeff_base_dir, "data")) if args.cwl: create.directory_tarball(snpeff_db_dir) def _is_old_database(db_dir, args): """Check for old database versions, supported in snpEff 4.1. """ snpeff_version = effects.snpeff_version(args) if LooseVersion(snpeff_version) >= LooseVersion("4.1"): pred_file = os.path.join(db_dir, "snpEffectPredictor.bin") if not utils.file_exists(pred_file): return True with utils.open_gzipsafe(pred_file, is_gz=True) as in_handle: version_info = in_handle.readline().strip().split("\t") program, version = version_info[:2] if not program.lower() == "snpeff" or LooseVersion(snpeff_version) > LooseVersion(version): return True return False def _get_biodata(base_file, args): """Retrieve biodata genome targets customized by install parameters. """ with open(base_file) as in_handle: config = yaml.safe_load(in_handle) config["install_liftover"] = False config["genome_indexes"] = args.aligners ann_groups = config.pop("annotation_groups", {}) config["genomes"] = [_setup_genome_annotations(g, args, ann_groups) for g in config["genomes"] if g["dbkey"] in args.genomes] return config def _setup_genome_annotations(g, args, ann_groups): """Configure genome annotations to install based on datatarget. """ available_anns = g.get("annotations", []) + g.pop("annotations_available", []) anns = [] for orig_target in args.datatarget: if orig_target in ann_groups: targets = ann_groups[orig_target] else: targets = [orig_target] for target in targets: if target in available_anns: anns.append(target) g["annotations"] = anns if "variation" not in args.datatarget and "validation" in g: del g["validation"] return g def upgrade_thirdparty_tools(args, remotes): """Install and update third party tools used in the pipeline. Creates a manifest directory with installed programs on the system. """ conda_bin = _get_mamba_bin() if not conda_bin: conda_bin = _get_conda_bin() cbl = get_cloudbiolinux(args, remotes) if args.toolconf and os.path.exists(args.toolconf): package_yaml = args.toolconf else: package_yaml = os.path.join(cbl["dir"], "contrib", "flavor", "ngs_pipeline_minimal", "packages-conda.yaml") sys.path.insert(0, cbl["dir"]) cbl_conda = __import__("cloudbio.package.conda", fromlist=["conda"]) cbl_conda.install_in(conda_bin, args.tooldir, package_yaml) manifest_dir = os.path.join(_get_data_dir(), "manifest") print("Creating manifest of installed packages in %s" % manifest_dir) cbl_manifest = __import__("cloudbio.manifest", fromlist=["manifest"]) if os.path.exists(manifest_dir): for fname in os.listdir(manifest_dir): if not fname.startswith("toolplus"): os.remove(os.path.join(manifest_dir, fname)) cbl_manifest.create(manifest_dir, args.tooldir) def _install_toolplus(args): """Install additional tools we cannot distribute, updating local manifest. """ manifest_dir = os.path.join(_get_data_dir(), "manifest") toolplus_manifest = os.path.join(manifest_dir, "toolplus-packages.yaml") system_config = os.path.join(_get_data_dir(), "galaxy", "bcbio_system.yaml") # Handle toolplus installs inside Docker container if not os.path.exists(system_config): docker_system_config = os.path.join(_get_data_dir(), "config", "bcbio_system.yaml") if os.path.exists(docker_system_config): system_config = docker_system_config toolplus_dir = os.path.join(_get_data_dir(), "toolplus") for tool in args.toolplus: if tool.name in set(["gatk", "mutect"]): print("Installing %s" % tool.name) _install_gatk_jar(tool.name, tool.fname, toolplus_manifest, system_config, toolplus_dir) else: raise ValueError("Unexpected toolplus argument: %s %s" % (tool.name, tool.fname)) def get_gatk_jar_version(name, fname): if name == "gatk": return broad.get_gatk_version(fname) elif name == "mutect": return broad.get_mutect_version(fname) else: raise ValueError("Unexpected GATK input: %s" % name) def _install_gatk_jar(name, fname, manifest, system_config, toolplus_dir): """Install a jar for GATK or associated tools like MuTect. """ if not fname.endswith(".jar"): raise ValueError("--toolplus argument for %s expects a jar file: %s" % (name, fname)) version = get_gatk_jar_version(name, fname) store_dir = utils.safe_makedir(os.path.join(toolplus_dir, name, version)) shutil.copyfile(fname, os.path.join(store_dir, os.path.basename(fname))) _update_system_file(system_config, name, {"dir": store_dir}) _update_manifest(manifest, name, version) def _update_manifest(manifest_file, name, version): """Update the toolplus manifest file with updated name and version """ if os.path.exists(manifest_file): with open(manifest_file) as in_handle: manifest = yaml.safe_load(in_handle) else: manifest = {} manifest[name] = {"name": name, "version": version} with open(manifest_file, "w") as out_handle: yaml.safe_dump(manifest, out_handle, default_flow_style=False, allow_unicode=False) def _update_system_file(system_file, name, new_kvs): """Update the bcbio_system.yaml file with new resource information. """ if os.path.exists(system_file): bak_file = system_file + ".bak%s" % datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") shutil.copyfile(system_file, bak_file) with open(system_file) as in_handle: config = yaml.safe_load(in_handle) else: utils.safe_makedir(os.path.dirname(system_file)) config = {} new_rs = {} added = False for rname, r_kvs in config.get("resources", {}).items(): if rname == name: for k, v in new_kvs.items(): r_kvs[k] = v added = True new_rs[rname] = r_kvs if not added: new_rs[name] = new_kvs config["resources"] = new_rs with open(system_file, "w") as out_handle: yaml.safe_dump(config, out_handle, default_flow_style=False, allow_unicode=False) def _install_kraken_db(datadir, args): """Install kraken minimal DB in genome folder. """ import requests kraken = os.path.join(datadir, "genomes/kraken") url = "https://ccb.jhu.edu/software/kraken/dl/minikraken.tgz" compress = os.path.join(kraken, os.path.basename(url)) base, ext = utils.splitext_plus(os.path.basename(url)) db = os.path.join(kraken, base) tooldir = args.tooldir or get_defaults()["tooldir"] requests.packages.urllib3.disable_warnings() last_mod = urllib.request.urlopen(url).info().get('Last-Modified') last_mod = dateutil.parser.parse(last_mod).astimezone(dateutil.tz.tzutc()) if os.path.exists(os.path.join(tooldir, "bin", "kraken")): if not os.path.exists(db): is_new_version = True else: cur_file = glob.glob(os.path.join(kraken, "minikraken_*"))[0] cur_version = datetime.datetime.utcfromtimestamp(os.path.getmtime(cur_file)) is_new_version = last_mod.date() > cur_version.date() if is_new_version: shutil.move(cur_file, cur_file.replace('minikraken', 'old')) if not os.path.exists(kraken): utils.safe_makedir(kraken) if is_new_version: if not os.path.exists(compress): subprocess.check_call(["wget", "-O", compress, url, "--no-check-certificate"]) cmd = ["tar", "-xzvf", compress, "-C", kraken] subprocess.check_call(cmd) last_version = glob.glob(os.path.join(kraken, "minikraken_*")) utils.symlink_plus(os.path.join(kraken, last_version[0]), os.path.join(kraken, "minikraken")) utils.remove_safe(compress) else: print("You have the latest version %s." % last_mod) else: raise argparse.ArgumentTypeError("kraken not installed in tooldir %s." % os.path.join(tooldir, "bin", "kraken")) # ## Store a local configuration file with upgrade details def _get_install_config(): """Return the YAML configuration file used to store upgrade information. """ try: data_dir = _get_data_dir() except ValueError: return None config_dir = utils.safe_makedir(os.path.join(data_dir, "config")) return os.path.join(config_dir, "install-params.yaml") def save_install_defaults(args): """Save installation information to make future upgrades easier. """ install_config = _get_install_config() if install_config is None: return if utils.file_exists(install_config): with open(install_config) as in_handle: cur_config = yaml.safe_load(in_handle) else: cur_config = {} if args.tooldir: cur_config["tooldir"] = args.tooldir cur_config["isolate"] = args.isolate for attr in ["genomes", "aligners", "datatarget"]: if not cur_config.get(attr): cur_config[attr] = [] for x in getattr(args, attr): if x not in cur_config[attr]: cur_config[attr].append(x) # toolplus -- save non-filename inputs attr = "toolplus" if not cur_config.get(attr): cur_config[attr] = [] for x in getattr(args, attr): if not x.fname: if x.name not in cur_config[attr]: cur_config[attr].append(x.name) with open(install_config, "w") as out_handle: yaml.safe_dump(cur_config, out_handle, default_flow_style=False, allow_unicode=False) def add_install_defaults(args): """Add any saved installation defaults to the upgrade. """ # Ensure we install data if we've specified any secondary installation targets if len(args.genomes) > 0 or len(args.aligners) > 0 or len(args.datatarget) > 0: args.install_data = True install_config = _get_install_config() if install_config is None or not utils.file_exists(install_config): default_args = {} else: with open(install_config) as in_handle: default_args = yaml.safe_load(in_handle) # if we are upgrading to development, also upgrade the tools if args.upgrade in ["development"] and (args.tooldir or "tooldir" in default_args): args.tools = True if args.tools and args.tooldir is None: if "tooldir" in default_args: args.tooldir = str(default_args["tooldir"]) else: raise ValueError("Default tool directory not yet saved in config defaults. " "Specify the '--tooldir=/path/to/tools' to upgrade tools. " "After a successful upgrade, the '--tools' parameter will " "work for future upgrades.") for attr in ["genomes", "aligners"]: # don't upgrade default genomes if a genome was specified if attr == "genomes" and len(args.genomes) > 0: continue for x in default_args.get(attr, []): x = str(x) new_val = getattr(args, attr) if x not in getattr(args, attr): new_val.append(x) setattr(args, attr, new_val) args = _datatarget_defaults(args, default_args) if "isolate" in default_args and args.isolate is not True: args.isolate = default_args["isolate"] return args def _datatarget_defaults(args, default_args): """Set data installation targets, handling defaults. Sets variation, rnaseq, smallrna as default targets if we're not isolated to a single method. Provides back compatibility for toolplus specifications. """ default_data = default_args.get("datatarget", []) # back-compatible toolplus specifications for x in default_args.get("toolplus", []): val = None if x == "data": val = "gemini" elif x in ["dbnsfp", "dbscsnv", "kraken", "gnomad"]: val = x if val and val not in default_data: default_data.append(val) new_val = getattr(args, "datatarget") for x in default_data: if x not in new_val: new_val.append(x) has_std_target = False std_targets = ["variation", "rnaseq", "smallrna"] for target in std_targets: if target in new_val: has_std_target = True break if not has_std_target: new_val = new_val + std_targets setattr(args, "datatarget", new_val) return args def get_defaults(): install_config = _get_install_config() if install_config is None or not utils.file_exists(install_config): return {} with open(install_config) as in_handle: return yaml.safe_load(in_handle) def _check_toolplus(x): """Parse options for adding non-standard/commercial tools like GATK and MuTecT. """ if "=" in x and len(x.split("=")) == 2: name, fname = x.split("=") fname = os.path.normpath(os.path.realpath(fname)) if not os.path.exists(fname): raise argparse.ArgumentTypeError("Unexpected --toolplus argument for %s. File does not exist: %s" % (name, fname)) return Tool(name, fname) else: raise argparse.ArgumentTypeError("Unexpected --toolplus argument. Expect toolname=filename.") def add_subparser(subparsers): parser = subparsers.add_parser("upgrade", help="Install or upgrade bcbio-nextgen") parser.add_argument("--cores", default=1, help="Number of cores to use if local indexing is necessary.") parser.add_argument("--tooldir", help="Directory to install 3rd party software tools. Leave unspecified for no tools", type=lambda x: (os.path.abspath(os.path.expanduser(x))), default=None) parser.add_argument("--tools", help="Boolean argument specifying upgrade of tools. Uses previously saved install directory", action="store_true", default=False) parser.add_argument("-u", "--upgrade", help="Code version to upgrade", choices=["stable", "development", "system", "deps", "skip"], default="skip") parser.add_argument("--toolconf", help="YAML configuration file of tools to install", default=None, type=lambda x: (os.path.abspath(os.path.expanduser(x)))) parser.add_argument("--revision", help="Specify a git commit hash or tag to install", default="master") parser.add_argument("--toolplus", help="Specify additional tool categories to install", action="append", default=[], type=_check_toolplus) parser.add_argument("--datatarget", help="Data to install. Allows customization or install of extra data.", action="append", default=[], choices=["variation", "rnaseq", "smallrna", "gemini", "vep", "dbnsfp", "dbscsnv", "battenberg", "kraken", "ericscript", "gnomad", "topmed"]) parser.add_argument("--genomes", help="Genomes to download", action="append", default=[], choices=SUPPORTED_GENOMES) parser.add_argument("--aligners", help="Aligner indexes to download", action="append", default=[], choices=SUPPORTED_INDEXES) parser.add_argument("--data", help="Upgrade data dependencies", dest="install_data", action="store_true", default=False) parser.add_argument("--cwl", help="Install code and data for running CWL workflows", dest="cwl", action="store_true", default=False) parser.add_argument("--isolate", help="Created an isolated installation without PATH updates", dest="isolate", action="store_true", default=False) parser.add_argument("--cloudbiolinux", help="Specify a cloudbiolinux git commit hash or tag to install", default="master") parser.add_argument("--distribution", help="Operating system distribution", default="", choices=["ubuntu", "debian", "centos", "scientificlinux", "macosx"]) return parser def get_cloudbiolinux(args, remotes): base_dir = os.path.join(os.getcwd(), "cloudbiolinux") cloudbiolinux_remote = remotes["cloudbiolinux"] % args.cloudbiolinux if not os.path.exists(base_dir): subprocess.check_call("wget --progress=dot:mega --no-check-certificate -O- %s | tar xz && " "(mv cloudbiolinux-%s cloudbiolinux || mv %s cloudbiolinux)" % (cloudbiolinux_remote, args.cloudbiolinux, args.cloudbiolinux), shell=True) return {"biodata": os.path.join(base_dir, "config", "biodata.yaml"), "dir": base_dir} @contextlib.contextmanager def bcbio_tmpdir(): orig_dir = os.getcwd() work_dir = os.path.join(os.getcwd(), "tmpbcbio-install") if not os.path.exists(work_dir): os.makedirs(work_dir) os.chdir(work_dir) yield work_dir os.chdir(orig_dir) shutil.rmtree(work_dir) bcbio-nextgen-1.2.9/bcbio/log/000077500000000000000000000000001415626112400161105ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/log/__init__.py000066400000000000000000000153751415626112400202340ustar00rootroot00000000000000"""Utility functionality for logging. """ import multiprocessing import os import socket import sys import time import logbook import logbook.queues from bcbio import utils LOG_NAME = "bcbio-nextgen" DEFAULT_LOG_DIR = 'log' def get_log_dir(config): d = config.get("log_dir", DEFAULT_LOG_DIR) return d logger = logbook.Logger(LOG_NAME) logger_cl = logbook.Logger(LOG_NAME + "-commands") logger_stdout = logbook.Logger(LOG_NAME + "-stdout") mpq = multiprocessing.Queue(-1) def _is_cl(record, _): return record.channel == LOG_NAME + "-commands" def _is_stdout(record, _): return record.channel == LOG_NAME + "-stdout" def _not_cl(record, handler): return not _is_cl(record, handler) and not _is_stdout(record, handler) class CloseableNestedSetup(logbook.NestedSetup): def close(self): for obj in self.objects: if hasattr(obj, "close"): obj.close() class IOSafeMultiProcessingSubscriber(logbook.queues.MultiProcessingSubscriber): """Recover from zeromq interrupted system call IOErrors that stop logging. """ def recv(self, timeout=None): try: return super(IOSafeMultiProcessingSubscriber, self).recv(timeout) except IOError as e: if "Interrupted system call" in str(e): return None else: raise def _create_log_handler(config, add_hostname=False, direct_hostname=False, write_toterm=True): logbook.set_datetime_format("utc") handlers = [logbook.NullHandler()] format_str = "".join(["[{record.time:%Y-%m-%dT%H:%MZ}] " if config.get("include_time", True) else "", "{record.extra[source]}: " if add_hostname else "", "%s: " % (socket.gethostname)() if direct_hostname else "", "{record.message}"]) log_dir = get_log_dir(config) if log_dir: if not os.path.exists(log_dir): utils.safe_makedir(log_dir) # Wait to propagate, Otherwise see logging errors on distributed filesystems. time.sleep(5) handlers.append(logbook.FileHandler(os.path.join(log_dir, "%s.log" % LOG_NAME), format_string=format_str, level="INFO", filter=_not_cl)) handlers.append(logbook.FileHandler(os.path.join(log_dir, "%s-debug.log" % LOG_NAME), format_string=format_str, level="DEBUG", bubble=True, filter=_not_cl)) handlers.append(logbook.FileHandler(os.path.join(log_dir, "%s-commands.log" % LOG_NAME), format_string=format_str, level="DEBUG", filter=_is_cl)) if write_toterm: handlers.append(logbook.StreamHandler(sys.stdout, format_string="{record.message}", level="DEBUG", filter=_is_stdout)) handlers.append(logbook.StreamHandler(sys.stderr, format_string=format_str, bubble=True, filter=_not_cl)) email = config.get("email", config.get("resources", {}).get("log", {}).get("email")) if email: email_str = u'''Subject: [bcbio-nextgen] {record.extra[run]} \n\n {record.message}''' handlers.append(logbook.MailHandler(email, [email], format_string=email_str, level='INFO', bubble=True)) return CloseableNestedSetup(handlers) def create_base_logger(config=None, parallel=None): """Setup base logging configuration, also handling remote logging. Correctly sets up for local, multiprocessing and distributed runs. Creates subscribers for non-local runs that will be references from local logging. Retrieves IP address using tips from http://stackoverflow.com/a/1267524/252589 """ if parallel is None: parallel = {} parallel_type = parallel.get("type", "local") cores = parallel.get("cores", 1) if parallel_type == "ipython": from bcbio.log import logbook_zmqpush fqdn_ip = socket.gethostbyname(socket.getfqdn()) ips = [fqdn_ip] if (fqdn_ip and not fqdn_ip.startswith("127.")) else [] if not ips: ips = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] if not ips: ips += [(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close())[1] for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]] if not ips: sys.stderr.write("Cannot resolve a local IP address that isn't 127.x.x.x " "Your machines might not have a local IP address " "assigned or are not able to resolve it.\n") sys.exit(1) uri = "tcp://%s" % ips[0] subscriber = logbook_zmqpush.ZeroMQPullSubscriber() mport = subscriber.socket.bind_to_random_port(uri) wport_uri = "%s:%s" % (uri, mport) parallel["log_queue"] = wport_uri subscriber.dispatch_in_background(_create_log_handler(config, True)) elif cores > 1: subscriber = IOSafeMultiProcessingSubscriber(mpq) subscriber.dispatch_in_background(_create_log_handler(config)) else: # Do not need to setup anything for local logging pass return parallel def setup_local_logging(config=None, parallel=None): """Setup logging for a local context, directing messages to appropriate base loggers. Handles local, multiprocessing and distributed setup, connecting to handlers created by the base logger. """ if config is None: config = {} if parallel is None: parallel = {} parallel_type = parallel.get("type", "local") cores = parallel.get("cores", 1) wrapper = parallel.get("wrapper", None) if parallel_type == "ipython": from bcbio.log import logbook_zmqpush handler = logbook_zmqpush.ZeroMQPushHandler(parallel["log_queue"]) elif cores > 1: handler = logbook.queues.MultiProcessingHandler(mpq) else: handler = _create_log_handler(config, direct_hostname=wrapper is not None, write_toterm=wrapper is None) handler.push_thread() return handler def setup_script_logging(): """ Use this logger for standalone scripts, or script-like subcommands, such as bcbio_prepare_samples and bcbio_nextgen.py -w template. """ handlers = [logbook.NullHandler()] format_str = ("[{record.time:%Y-%m-%dT%H:%MZ}] " "{record.level_name}: {record.message}") handler = logbook.StreamHandler(sys.stderr, format_string=format_str, level="DEBUG") handler.push_thread() return handler bcbio-nextgen-1.2.9/bcbio/log/logbook_zmqpush.py000066400000000000000000000102061415626112400217040ustar00rootroot00000000000000"""Enable multiple processes to send logs to a central server through ZeroMQ. Thanks to Zachary Voase: https://github.com/zacharyvoase/logbook-zmqpush Slightly modified to support Logbook 0.4.1. """ import errno import json import socket import logbook.queues from logbook.base import LogRecord import zmq from zmq.utils.garbage import gc MAX_SOCKETS = 32000 def _increase_gc_sockets(): """Increase default sockets for zmq gc. Avoids scaling issues. https://github.com/zeromq/pyzmq/issues/471 """ ctx = zmq.Context() ctx.max_sockets = MAX_SOCKETS gc.context = ctx class ZeroMQPushHandler(logbook.queues.ZeroMQHandler): """ A handler that pushes JSON log records over a ZMQ socket. Specifically, this handler opens a ``zmq.PUSH`` socket and connects to a ``zmq.PULL`` socket at the specified address. You can use :class:`ZeroMQPullSubscriber` to receive the log record. Example: >>> import logbook >>> handler = ZeroMQPushHandler('tcp://127.0.0.1:5501') >>> with handler.applicationbound(): ... logbook.debug("Something happened") Switch off hostname injection with `hostname=False`: >>> handler = ZeroMQPushHandler('tcp://127.0.0.1:5501', hostname=False) >>> with handler.applicationbound(): ... logbook.debug("No hostname info") """ def __init__(self, addr=None, level=logbook.NOTSET, filter=None, bubble=False, context=None, hostname=True): logbook.Handler.__init__(self, level, filter, bubble) self.hostname = hostname if context is None: context = zmq.Context() self._context = context else: self._context = None self._context.max_sockets = MAX_SOCKETS _increase_gc_sockets() self.socket = context.socket(zmq.PUSH) if addr is not None: self.socket.connect(addr) def emit(self, record): if self.hostname: inject_hostname.process(record) return super(ZeroMQPushHandler, self).emit(record) def close(self): if self._context: self._context.destroy(linger=0) self.socket.close(linger=0) class ZeroMQPullSubscriber(logbook.queues.ZeroMQSubscriber): """ A subscriber which listens on a PULL socket for log records. This subscriber opens a ``zmq.PULL`` socket and binds to the specified address. You should probably use this in conjunction with :class:`ZeroMQPushHandler`. Example: >>> subscriber = ZeroMQPullSubscriber('tcp://*:5501') >>> log_record = subscriber.recv() """ def __init__(self, addr=None, context=None): self._zmq = zmq self.context = context or zmq.Context.instance() self.context.max_sockets = MAX_SOCKETS _increase_gc_sockets() self.socket = self.context.socket(zmq.PULL) if addr is not None: self.socket.bind(addr) def recv(self, timeout=None): """Overwrite standard recv for timeout calls to catch interrupt errors. """ if timeout: try: testsock = self._zmq.select([self.socket], [], [], timeout)[0] except zmq.ZMQError as e: if e.errno == errno.EINTR: testsock = None else: raise if not testsock: return rv = self.socket.recv(self._zmq.NOBLOCK) return LogRecord.from_dict(json.loads(rv)) else: return super(ZeroMQPullSubscriber, self).recv(timeout) @logbook.Processor def inject_hostname(log_record): """A Logbook processor to inject the current hostname into log records.""" log_record.extra['source'] = socket.gethostname() def inject(**params): """ A Logbook processor to inject arbitrary information into log records. Simply pass in keyword arguments and use as a context manager: >>> with inject(identifier=str(uuid.uuid4())).applicationbound(): ... logger.debug('Something happened') """ def callback(log_record): log_record.extra.update(params) return logbook.Processor(callback) bcbio-nextgen-1.2.9/bcbio/ngsalign/000077500000000000000000000000001415626112400171315ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/ngsalign/__init__.py000066400000000000000000000001051415626112400212360ustar00rootroot00000000000000"""Functionality to help perform next-gen sequencing alignments. """ bcbio-nextgen-1.2.9/bcbio/ngsalign/alignprep.py000066400000000000000000001013701415626112400214660ustar00rootroot00000000000000"""Prepare read inputs (fastq, gzipped fastq and BAM) for parallel NGS alignment. """ import collections import copy import glob import os import shutil import subprocess import six import toolz as tz from bcbio import bam, utils from bcbio.bam import cram, fastq from bcbio.cwl import cwlutils from bcbio.log import logger from bcbio.distributed import objectstore from bcbio.distributed.multi import run_multicore, zeromq_aware_logging from bcbio.distributed.transaction import file_transaction from bcbio.ngsalign import rtg from bcbio.pipeline import config_utils, tools from bcbio.pipeline import datadict as dd from bcbio.provenance import do def create_inputs(data): """Index input reads and prepare groups of reads to process concurrently. Allows parallelization of alignment beyond processors available on a single machine. Prepares a bgzip and grabix indexed file for retrieving sections of files. """ from bcbio.pipeline import sample data = cwlutils.normalize_missing(data) aligner = tz.get_in(("config", "algorithm", "aligner"), data) # CRAM files must be converted to bgzipped fastq, unless not aligning. # Also need to prep and download remote files. if not ("files" in data and data["files"] and aligner and (_is_cram_input(data["files"]) or objectstore.is_remote(data["files"][0]))): # skip indexing on samples without input files or not doing alignment if ("files" not in data or not data["files"] or data["files"][0] is None or not aligner): return [[data]] # if this is a DRAGEN BAM, we need to do further alignments with this BAM, so don't convert it if dd.get_umi_type(data) == "dragen": return [[data]] data["files_orig"] = data["files"] data["files"] = prep_fastq_inputs(data["files"], data) # preparation converts illumina into sanger format data["config"]["algorithm"]["quality_format"] = "standard" # Handle any necessary trimming data = utils.to_single_data(sample.trim_sample(data)[0]) _prep_grabix_indexes(data["files"], data) data = _set_align_split_size(data) out = [] if tz.get_in(["config", "algorithm", "align_split_size"], data): splits = _find_read_splits(data["files"][0], int(data["config"]["algorithm"]["align_split_size"])) for split in splits: cur_data = copy.deepcopy(data) cur_data["align_split"] = split out.append([cur_data]) else: out.append([data]) if "output_cwl_keys" in data: out = cwlutils.samples_to_records([utils.to_single_data(x) for x in out], ["files", "align_split", "config__algorithm__quality_format"]) return out def _set_align_split_size(data): """Set useful align_split_size, generating an estimate if it doesn't exist. We try to split on larger inputs and avoid too many pieces, aiming for size chunks of 5Gb or at most 50 maximum splits. The size estimate used in calculations is 20 million reads for ~5Gb. For UMI calculations we skip splitting since we're going to align and re-align after consensus. For CWL runs, we pick larger split sizes to avoid overhead of staging each chunk. """ if cwlutils.is_cwl_run(data): target_size = 20 # Gb target_size_reads = 80 # million reads else: target_size = 5 # Gb target_size_reads = 20 # million reads max_splits = 100 # Avoid too many pieces, causing merge memory problems val = dd.get_align_split_size(data) umi_consensus = dd.get_umi_consensus(data) if val is None: if not umi_consensus: total_size = 0 # Gb # Use original files if we might have reduced the size of our prepped files input_files = data.get("files_orig", []) if dd.get_save_diskspace(data) else data.get("files", []) for fname in input_files: if os.path.exists(fname): total_size += os.path.getsize(fname) / (1024.0 * 1024.0 * 1024.0) # Only set if we have files and are bigger than the target size if total_size > target_size: data["config"]["algorithm"]["align_split_size"] = \ int(1e6 * _pick_align_split_size(total_size, target_size, target_size_reads, max_splits)) elif val: assert not umi_consensus, "Cannot set align_split_size to %s with UMI conensus specified" % val return data def _pick_align_split_size(total_size, target_size, target_size_reads, max_splits): """Do the work of picking an alignment split size for the given criteria. """ # Too many pieces, increase our target size to get max_splits pieces if total_size // target_size > max_splits: piece_size = total_size // max_splits return int(piece_size * target_size_reads / target_size) else: return int(target_size_reads) def split_namedpipe_cls(pair1_file, pair2_file, data): """Create a commandline suitable for use as a named pipe with reads in a given region. """ if "align_split" in data: start, end = [int(x) for x in data["align_split"].split("-")] else: start, end = None, None if pair1_file.endswith(".sdf"): assert not pair2_file, pair2_file return rtg.to_fastq_apipe_cl(pair1_file, start, end) else: out = [] for in_file in pair1_file, pair2_file: if in_file: assert _get_grabix_index(in_file), "Need grabix index for %s" % in_file out.append("<(grabix grab {in_file} {start} {end})".format(**locals())) else: out.append(None) return out def _seqtk_fastq_prep_cl(data, in_file=None, read_num=0): """Provide a commandline for prep of fastq inputs with seqtk. Handles fast conversion of fastq quality scores and trimming. """ needs_convert = dd.get_quality_format(data).lower() == "illumina" trim_ends = dd.get_trim_ends(data) seqtk = config_utils.get_program("seqtk", data["config"]) if in_file: in_file = objectstore.cl_input(in_file) else: in_file = "/dev/stdin" cmd = "" if needs_convert: cmd += "{seqtk} seq -Q64 -V {in_file}".format(**locals()) if trim_ends: left_trim, right_trim = trim_ends[0:2] if data.get("read_num", read_num) == 0 else trim_ends[2:4] if left_trim or right_trim: trim_infile = "/dev/stdin" if needs_convert else in_file pipe = " | " if needs_convert else "" cmd += "{pipe}{seqtk} trimfq -b {left_trim} -e {right_trim} {trim_infile}".format(**locals()) return cmd def fastq_convert_pipe_cl(in_file, data): """Create an anonymous pipe converting Illumina 1.3-1.7 to Sanger. Uses seqtk: https://github.com/lh3/seqt """ cmd = _seqtk_fastq_prep_cl(data, in_file) if not cmd: cat_cmd = "zcat" if in_file.endswith(".gz") else "cat" cmd = cat_cmd + " " + in_file return "<(%s)" % cmd # ## configuration def parallel_multiplier(items): """Determine if we will be parallelizing items during processing. """ multiplier = 1 for data in (x[0] for x in items): if (tz.get_in(["config", "algorithm", "align_split_size"], data) is not False and tz.get_in(["algorithm", "align_split_size"], data) is not False): multiplier += 50 return multiplier # ## merge def setup_combine(final_file, data): """Setup the data and outputs to allow merging data back together. """ if "align_split" not in data: return final_file, data align_dir = os.path.dirname(final_file) base, ext = os.path.splitext(os.path.basename(final_file)) start, end = [int(x) for x in data["align_split"].split("-")] out_file = os.path.join(utils.safe_makedir(os.path.join(align_dir, "split")), "%s-%s_%s%s" % (base, start, end, ext)) data["combine"] = {"work_bam": {"out": final_file, "extras": []}} return out_file, data def merge_split_alignments(samples, run_parallel): """Manage merging split alignments back into a final working BAM file. Perform de-duplication on the final merged file. """ ready = [] file_key = "work_bam" to_merge = collections.defaultdict(list) for data in (xs[0] for xs in samples): if data.get("combine"): out_key = tz.get_in(["combine", file_key, "out"], data) if not out_key: out_key = data["rgnames"]["lane"] to_merge[out_key].append(data) else: ready.append([data]) ready_merge = [] hla_merges = [] for mgroup in to_merge.values(): cur_data = mgroup[0] del cur_data["align_split"] for x in mgroup[1:]: cur_data["combine"][file_key]["extras"].append(x[file_key]) ready_merge.append([cur_data]) cur_hla = None for d in mgroup: hla_files = tz.get_in(["hla", "fastq"], d) if hla_files: if not cur_hla: cur_hla = {"rgnames": {"sample": dd.get_sample_name(cur_data)}, "config": cur_data["config"], "dirs": cur_data["dirs"], "hla": {"fastq": []}} cur_hla["hla"]["fastq"].append(hla_files) if cur_hla: hla_merges.append([cur_hla]) if not tz.get_in(["config", "algorithm", "kraken"], data): # kraken requires fasta filenames from data['files'] as input. # We don't want to remove those files if kraken qc is required. _save_fastq_space(samples) merged = run_parallel("delayed_bam_merge", ready_merge) hla_merge_raw = run_parallel("merge_split_alignments", hla_merges) hla_merges = {} for hla_merge in [x[0] for x in hla_merge_raw]: hla_merges[dd.get_sample_name(hla_merge)] = tz.get_in(["hla", "fastq"], hla_merge) # Add stable 'align_bam' target to use for retrieving raw alignment out = [] for data in [x[0] for x in merged + ready]: if data.get("work_bam"): data["align_bam"] = data["work_bam"] if dd.get_sample_name(data) in hla_merges: data["hla"]["fastq"] = hla_merges[dd.get_sample_name(data)] else: hla_files = glob.glob(os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data), "hla", "*.fq")) if hla_files: data["hla"]["fastq"] = hla_files out.append([data]) return out def _save_fastq_space(items): """Potentially save fastq space prior to merging, since alignments done. """ to_cleanup = {} for data in (utils.to_single_data(x) for x in items): for fname in data.get("files", []): if os.path.realpath(fname).startswith(dd.get_work_dir(data)): to_cleanup[fname] = data["config"] for fname, config in to_cleanup.items(): utils.save_diskspace(fname, "Cleanup prep files after alignment finished", config) # ## determine file sections def _get_grabix_index(in_file): gbi_file = in_file + ".gbi" if utils.file_exists(gbi_file): with open(gbi_file) as in_handle: header = next(in_handle) if header.find("Not grabix indexed") == -1: return gbi_file def get_downsample_params(data): ds_mult = dd.get_maxcov_downsample(data) if ds_mult and ds_mult > 0: return {"min_coverage_for_downsampling": 10, "maxcov_downsample_multiplier": ds_mult} def total_reads_from_grabix(in_file): """Retrieve total reads in a fastq file from grabix index. """ gbi_file = _get_grabix_index(in_file) if gbi_file: with open(gbi_file) as in_handle: next(in_handle) # throw away num_lines = int(next(in_handle).strip()) assert num_lines % 4 == 0, f"Expected lines to be multiple of 4 for file: {in_file} with {num_lines} lines" return num_lines // 4 else: return 0 def _find_read_splits(in_file, split_size): """Determine sections of fastq files to process in splits. Assumes a 4 line order to input files (name, read, name, quality). grabix is 1-based inclusive, so return coordinates in that format. """ num_lines = total_reads_from_grabix(in_file) * 4 assert num_lines and num_lines > 0, "Did not find grabix index reads: %s %s" % (in_file, num_lines) split_lines = split_size * 4 chunks = [] last = 1 for chunki in range(num_lines // split_lines + min(1, num_lines % split_lines)): new = last + split_lines - 1 chunks.append((last, min(new, num_lines))) last = new + 1 return ["%s-%s" % (s, e) for s, e in chunks] # ## bgzip and grabix def _is_bam_input(in_files): return in_files and in_files[0].endswith(".bam") and (len(in_files) == 1 or in_files[1] is None) def _is_cram_input(in_files): return in_files and in_files[0].endswith(".cram") and (len(in_files) == 1 or in_files[1] is None) def _ready_gzip_fastq(in_files, data, require_bgzip=False): """Check if we have gzipped fastq and don't need format conversion or splitting. Avoid forcing bgzip if we don't need indexed files. """ all_gzipped = all([not x or x.endswith(".gz") for x in in_files]) if require_bgzip and all_gzipped: all_gzipped = all([not x or not _check_gzipped_input(x, data)[0] for x in in_files]) needs_convert = dd.get_quality_format(data).lower() == "illumina" needs_trim = dd.get_trim_ends(data) do_splitting = dd.get_align_split_size(data) is not False return (all_gzipped and not needs_convert and not do_splitting and not objectstore.is_remote(in_files[0]) and not needs_trim and not get_downsample_params(data)) def prep_fastq_inputs(in_files, data): """Prepare bgzipped fastq inputs """ if len(in_files) == 1 and _is_bam_input(in_files): out = _bgzip_from_bam(in_files[0], data["dirs"], data) elif len(in_files) == 1 and _is_cram_input(in_files): out = _bgzip_from_cram(in_files[0], data["dirs"], data) elif len(in_files) in [1, 2] and _ready_gzip_fastq(in_files, data): out = _symlink_in_files(in_files, data) else: if len(in_files) > 2: fpairs = fastq.combine_pairs(in_files) pair_types = set([len(xs) for xs in fpairs]) assert len(pair_types) == 1 fpairs.sort(key=lambda x: os.path.basename(x[0])) organized = [[xs[0] for xs in fpairs]] if len(fpairs[0]) > 1: organized.append([xs[1] for xs in fpairs]) in_files = organized parallel = {"type": "local", "num_jobs": len(in_files), "cores_per_job": max(1, data["config"]["algorithm"]["num_cores"] // len(in_files))} inputs = [{"in_file": x, "read_num": i, "dirs": data["dirs"], "config": data["config"], "is_cwl": "cwl_keys" in data, "rgnames": data["rgnames"]} for i, x in enumerate(in_files) if x] out = run_multicore(_bgzip_from_fastq_parallel, [[d] for d in inputs], data["config"], parallel) return out def _symlink_in_files(in_files, data): """Symlink (shared filesystem) or copy (CWL) inputs into align_prep directory. """ work_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "align_prep")) out = [] for in_file in in_files: out_file = os.path.join(work_dir, "%s_%s" % (dd.get_sample_name(data), os.path.basename(in_file))) out_file = _symlink_or_copy_grabix(in_file, out_file, data) out.append(out_file) return out def _symlink_or_copy_grabix(in_file, out_file, data): """We cannot symlink in CWL, but may be able to use inputs or copy """ if cwlutils.is_cwl_run(data): # Has grabix indexes, we're okay to go if utils.file_exists(in_file + ".gbi"): out_file = in_file else: utils.copy_plus(in_file, out_file) else: utils.symlink_plus(in_file, out_file) return out_file def _prep_grabix_indexes(in_files, data): """Parallel preparation of grabix indexes for files. """ # if we have gzipped but not bgzipped, add a fake index for CWL support # Also skips bgzip indexing if we don't need alignment splitting if _ready_gzip_fastq(in_files, data) and (not _ready_gzip_fastq(in_files, data, require_bgzip=True) or dd.get_align_split_size(data) is False): for in_file in in_files: if not utils.file_exists(in_file + ".gbi"): with file_transaction(data, in_file + ".gbi") as tx_gbi_file: with open(tx_gbi_file, "w") as out_handle: out_handle.write("Not grabix indexed; index added for compatibility.\n") else: items = [[{"bgzip_file": x, "config": copy.deepcopy(data["config"])}] for x in in_files if x] run_multicore(_grabix_index, items, data["config"]) return data def _bgzip_from_cram(cram_file, dirs, data): """Create bgzipped fastq files from an input CRAM file in regions of interest. Returns a list with a single file, for single end CRAM files, or two files for paired end input. """ import pybedtools region_file = (tz.get_in(["config", "algorithm", "variant_regions"], data) if tz.get_in(["config", "algorithm", "coverage_interval"], data) in ["regional", "exome", "amplicon"] else None) if region_file: regions = ["%s:%s-%s" % tuple(r[:3]) for r in pybedtools.BedTool(region_file)] else: regions = [None] work_dir = utils.safe_makedir(os.path.join(dirs["work"], "align_prep")) out_s, out_p1, out_p2 = [os.path.join(work_dir, "%s-%s.fq.gz" % (utils.splitext_plus(os.path.basename(cram_file))[0], fext)) for fext in ["s1", "p1", "p2"]] if (not utils.file_exists(out_s) and (not utils.file_exists(out_p1) or not utils.file_exists(out_p2))): cram.index(cram_file, data["config"]) fastqs, part_dir = _cram_to_fastq_regions(regions, cram_file, dirs, data) if len(fastqs[0]) == 1: with file_transaction(data, out_s) as tx_out_file: _merge_and_bgzip([xs[0] for xs in fastqs], tx_out_file, out_s) else: for i, out_file in enumerate([out_p1, out_p2]): if not utils.file_exists(out_file): ext = "/%s" % (i + 1) with file_transaction(data, out_file) as tx_out_file: _merge_and_bgzip([xs[i] for xs in fastqs], tx_out_file, out_file, ext) shutil.rmtree(part_dir) if utils.file_exists(out_p1): return [out_p1, out_p2] else: assert utils.file_exists(out_s) return [out_s] def _bgzip_from_cram_sambamba(cram_file, dirs, data): """Use sambamba to extract from CRAM via regions. """ raise NotImplementedError("sambamba doesn't yet support retrieval from CRAM by BED file") region_file = (tz.get_in(["config", "algorithm", "variant_regions"], data) if tz.get_in(["config", "algorithm", "coverage_interval"], data) in ["regional", "exome"] else None) base_name = utils.splitext_plus(os.path.basename(cram_file))[0] work_dir = utils.safe_makedir(os.path.join(dirs["work"], "align_prep", "%s-parts" % base_name)) f1, f2, o1, o2, si = [os.path.join(work_dir, "%s.fq" % x) for x in ["match1", "match2", "unmatch1", "unmatch2", "single"]] ref_file = dd.get_ref_file(data) region = "-L %s" % region_file if region_file else "" cmd = ("sambamba view -f bam -l 0 -C {cram_file} -T {ref_file} {region} | " "bamtofastq F={f1} F2={f2} S={si} O={o1} O2={o2}") do.run(cmd.format(**locals()), "Convert CRAM to fastq in regions") def _merge_and_bgzip(orig_files, out_file, base_file, ext=""): """Merge a group of gzipped input files into a final bgzipped output. Also handles providing unique names for each input file to avoid collisions on multi-region output. Handles renaming with awk magic from: https://www.biostars.org/p/68477/ """ assert out_file.endswith(".gz") full_file = out_file.replace(".gz", "") run_file = "%s-merge.bash" % utils.splitext_plus(base_file)[0] cmds = ["set -e\n"] for i, fname in enumerate(orig_files): cmd = ("""zcat %s | awk '{print (NR%%4 == 1) ? "@%s_" ++i "%s" : $0}' >> %s\n""" % (fname, i, ext, full_file)) cmds.append(cmd) cmds.append("bgzip -f %s\n" % full_file) with open(run_file, "w") as out_handle: out_handle.write("".join("".join(cmds))) do.run([do.find_bash(), run_file], "Rename, merge and bgzip CRAM fastq output") assert os.path.exists(out_file) and not _is_gzip_empty(out_file) def _cram_to_fastq_regions(regions, cram_file, dirs, data): """Convert CRAM files to fastq, potentially within sub regions. Returns multiple fastq files that can be merged back together. """ base_name = utils.splitext_plus(os.path.basename(cram_file))[0] work_dir = utils.safe_makedir(os.path.join(dirs["work"], "align_prep", "%s-parts" % base_name)) fnames = run_multicore(_cram_to_fastq_region, [(cram_file, work_dir, base_name, region, data) for region in regions], data["config"]) # check if we have paired or single end data if any(not _is_gzip_empty(p1) for p1, p2, s in fnames): out = [[p1, p2] for p1, p2, s in fnames] else: out = [[s] for p1, p2, s in fnames] return out, work_dir @utils.map_wrap @zeromq_aware_logging def _cram_to_fastq_region(cram_file, work_dir, base_name, region, data): """Convert CRAM to fastq in a specified region. """ ref_file = tz.get_in(["reference", "fasta", "base"], data) resources = config_utils.get_resources("bamtofastq", data["config"]) cores = tz.get_in(["config", "algorithm", "num_cores"], data, 1) max_mem = config_utils.convert_to_bytes(resources.get("memory", "1G")) * cores rext = "-%s" % region.replace(":", "_").replace("-", "_") if region else "full" out_s, out_p1, out_p2, out_o1, out_o2 = [os.path.join(work_dir, "%s%s-%s.fq.gz" % (base_name, rext, fext)) for fext in ["s1", "p1", "p2", "o1", "o2"]] if not utils.file_exists(out_p1): with file_transaction(data, out_s, out_p1, out_p2, out_o1, out_o2) as \ (tx_out_s, tx_out_p1, tx_out_p2, tx_out_o1, tx_out_o2): cram_file = objectstore.cl_input(cram_file) sortprefix = "%s-sort" % utils.splitext_plus(tx_out_s)[0] cmd = ("bamtofastq filename={cram_file} inputformat=cram T={sortprefix} " "gz=1 collate=1 colsbs={max_mem} exclude=SECONDARY,SUPPLEMENTARY " "F={tx_out_p1} F2={tx_out_p2} S={tx_out_s} O={tx_out_o1} O2={tx_out_o2} " "reference={ref_file}") if region: cmd += " ranges='{region}'" do.run(cmd.format(**locals()), "CRAM to fastq %s" % region if region else "") return [[out_p1, out_p2, out_s]] def _is_gzip_empty(fname): count = subprocess.check_output("zcat %s | head -1 | wc -l" % fname, shell=True, stderr=open("/dev/null", "w")) return int(count) < 1 def _bgzip_from_bam(bam_file, dirs, data, is_retry=False, output_infix=''): """Create bgzipped fastq files from an input BAM file. """ # tools config = data["config"] bamtofastq = config_utils.get_program("bamtofastq", config) resources = config_utils.get_resources("bamtofastq", config) cores = config["algorithm"].get("num_cores", 1) max_mem = config_utils.convert_to_bytes(resources.get("memory", "1G")) * cores bgzip = tools.get_bgzip_cmd(config, is_retry) # files work_dir = utils.safe_makedir(os.path.join(dirs["work"], "align_prep")) out_file_1 = os.path.join(work_dir, "%s%s-1.fq.gz" % (os.path.splitext(os.path.basename(bam_file))[0], output_infix)) out_file_2 = out_file_1.replace("-1.fq.gz", "-2.fq.gz") needs_retry = False if is_retry or not utils.file_exists(out_file_1): if not bam.is_paired(bam_file): out_file_2 = None with file_transaction(config, out_file_1) as tx_out_file: for f in [tx_out_file, out_file_1, out_file_2]: if f and os.path.exists(f): os.remove(f) fq1_bgzip_cmd = "%s -c /dev/stdin > %s" % (bgzip, tx_out_file) prep_cmd = _seqtk_fastq_prep_cl(data, read_num=0) if prep_cmd: fq1_bgzip_cmd = prep_cmd + " | " + fq1_bgzip_cmd sortprefix = "%s-sort" % os.path.splitext(tx_out_file)[0] if bam.is_paired(bam_file): prep_cmd = _seqtk_fastq_prep_cl(data, read_num=1) fq2_bgzip_cmd = "%s -c /dev/stdin > %s" % (bgzip, out_file_2) if prep_cmd: fq2_bgzip_cmd = prep_cmd + " | " + fq2_bgzip_cmd out_str = ("F=>({fq1_bgzip_cmd}) F2=>({fq2_bgzip_cmd}) S=/dev/null O=/dev/null " "O2=/dev/null collate=1 colsbs={max_mem}") else: out_str = "S=>({fq1_bgzip_cmd})" bam_file = objectstore.cl_input(bam_file) extra_opts = " ".join([str(x) for x in resources.get("options", [])]) cmd = "{bamtofastq} filename={bam_file} T={sortprefix} {extra_opts} " + out_str try: do.run(cmd.format(**locals()), "BAM to bgzipped fastq", checks=[do.file_reasonable_size(tx_out_file, bam_file)], log_error=False) except subprocess.CalledProcessError as msg: if not is_retry and "deflate failed" in str(msg): logger.info("bamtofastq deflate IO failure preparing %s. Retrying with single core." % (bam_file)) needs_retry = True else: logger.exception() raise if needs_retry: return _bgzip_from_bam(bam_file, dirs, data, is_retry=True) else: return [x for x in [out_file_1, out_file_2] if x is not None and utils.file_exists(x)] @utils.map_wrap @zeromq_aware_logging def _grabix_index(data): """Create grabix index of bgzip input file. grabix does not allow specification of output file, so symlink the original file into a transactional directory. """ in_file = data["bgzip_file"] config = data["config"] grabix = config_utils.get_program("grabix", config) gbi_file = _get_grabix_index(in_file) # We always build grabix input so we can use it for counting reads and doing downsampling if not gbi_file or _is_partial_index(gbi_file): if gbi_file: utils.remove_safe(gbi_file) else: gbi_file = in_file + ".gbi" with file_transaction(data, gbi_file) as tx_gbi_file: tx_in_file = os.path.splitext(tx_gbi_file)[0] utils.symlink_plus(in_file, tx_in_file) do.run([grabix, "index", tx_in_file], "Index input with grabix: %s" % os.path.basename(in_file)) assert utils.file_exists(gbi_file) return [gbi_file] def _is_partial_index(gbi_file): """Check for truncated output since grabix doesn't write to a transactional directory. """ with open(gbi_file) as in_handle: for i, _ in enumerate(in_handle): if i > 2: return False return True @utils.map_wrap @zeromq_aware_logging def _bgzip_from_fastq_parallel(data): return [_bgzip_from_fastq(data)] def _bgzip_from_fastq(data): """Prepare a bgzipped file from a fastq input, potentially gzipped (or bgzipped already). """ in_file = data["in_file"] if isinstance(in_file, (list, tuple)): in_file = in_file[0] needs_convert = dd.get_quality_format(data).lower() == "illumina" # special case, empty files that have been cleaned if not objectstore.is_remote(in_file) and os.path.getsize(in_file) == 0: needs_bgzip, needs_gunzip = False, False elif in_file.endswith(".gz") and not objectstore.is_remote(in_file): if needs_convert or dd.get_trim_ends(data): needs_bgzip, needs_gunzip = True, True else: needs_bgzip, needs_gunzip = _check_gzipped_input(in_file, data) elif in_file.endswith(".bz2"): needs_bgzip, needs_gunzip = True, True elif objectstore.is_remote(in_file) and not tz.get_in(["config", "algorithm", "align_split_size"], data): needs_bgzip, needs_gunzip = False, False else: needs_bgzip, needs_gunzip = True, False work_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "align_prep")) if (needs_bgzip or needs_gunzip or needs_convert or dd.get_trim_ends(data) or objectstore.is_remote(in_file) or (isinstance(data["in_file"], (tuple, list)) and len(data["in_file"]) > 1)): out_file = _bgzip_file(data["in_file"], data["config"], work_dir, needs_bgzip, needs_gunzip, needs_convert, data) else: out_file = os.path.join(work_dir, "%s_%s" % (dd.get_sample_name(data), os.path.basename(in_file))) out_file = _symlink_or_copy_grabix(in_file, out_file, data) return out_file def _bgzip_file(finput, config, work_dir, needs_bgzip, needs_gunzip, needs_convert, data): """Handle bgzip of input file, potentially gunzipping an existing file. Handles cases where finput might be multiple files and need to be concatenated. """ if isinstance(finput, six.string_types): in_file = finput else: assert not needs_convert, "Do not yet handle quality conversion with multiple inputs" return _bgzip_multiple_files(finput, work_dir, data) out_file = os.path.join(work_dir, os.path.basename(in_file).replace(".bz2", "") + (".gz" if not in_file.endswith(".gz") else "")) if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: bgzip = tools.get_bgzip_cmd(config) is_remote = objectstore.is_remote(in_file) in_file = objectstore.cl_input(in_file, unpack=needs_gunzip or needs_convert or needs_bgzip or dd.get_trim_ends(data)) if needs_convert or dd.get_trim_ends(data): in_file = fastq_convert_pipe_cl(in_file, data) if needs_gunzip and not (needs_convert or dd.get_trim_ends(data)): if in_file.endswith(".bz2"): gunzip_cmd = "bunzip2 -c {in_file} |".format(**locals()) else: gunzip_cmd = "gunzip -c {in_file} |".format(**locals()) bgzip_in = "/dev/stdin" else: gunzip_cmd = "" bgzip_in = in_file if needs_bgzip: do.run("{gunzip_cmd} {bgzip} -c {bgzip_in} > {tx_out_file}".format(**locals()), "bgzip input file") elif is_remote: bgzip = "| bgzip -c" if (needs_convert or dd.get_trim_ends(data)) else "" do.run("cat {in_file} {bgzip} > {tx_out_file}".format(**locals()), "Get remote input") else: raise ValueError("Unexpected inputs: %s %s %s %s" % (in_file, needs_bgzip, needs_gunzip, needs_convert)) return out_file def _bgzip_multiple_files(in_files, work_dir, data): out_file = os.path.join(work_dir, "%s-combined-%s" % (dd.get_sample_name(data), os.path.basename(in_files[0]).replace(".bz2", "") + (".gz" if not in_files[0].endswith(".gz") else ""))) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: if in_files[0].endswith(".bz2"): gunzip_cmd = "bunzip2 -c" elif in_files[0].endswith(".gz"): gunzip_cmd = "gunzip -c" else: gunzip_cmd = "cat" cmd = "%s %s | bgzip -c > %s" % (gunzip_cmd, " ".join(in_files), tx_out_file) do.run(cmd, "Combine and bgzip multiple input files: %s" % dd.get_sample_name(data)) return out_file def _check_gzipped_input(in_file, data): """Determine if a gzipped input file is blocked gzip or standard. """ grabix = config_utils.get_program("grabix", data["config"]) is_bgzip = subprocess.check_output([grabix, "check", in_file]).decode().strip() if is_bgzip.strip() == "yes": return False, False else: return True, True bcbio-nextgen-1.2.9/bcbio/ngsalign/bbmap.py000066400000000000000000000035741415626112400205750ustar00rootroot00000000000000"""Alignment with bbmap: https://sourceforge.net/projects/bbmap/ """ import os from bcbio import utils from bcbio.pipeline import datadict as dd from bcbio.ngsalign import alignprep, novoalign, postalign from bcbio.provenance import do def align(fastq_file, pair_file, index_dir, names, align_dir, data): """Perform piped alignment of fastq input files, generating sorted, deduplicated BAM. """ umi_ext = "-cumi" if "umi_bam" in data else "" out_file = os.path.join(align_dir, "{0}-sort{1}.bam".format(dd.get_sample_name(data), umi_ext)) num_cores = data["config"]["algorithm"].get("num_cores", 1) rg_info = "rgid={rg} rgpl={pl} rgpu={pu} rgsm={sample}".format(**names) pair_file = pair_file if pair_file else "" final_file = None if data.get("align_split"): # BBMap does not accept input fastq streams raise ValueError("bbmap is not compatible with alignment splitting, set `align_split: false`") pair_arg = "in2=%s" % pair_file if pair_file else "" if not utils.file_exists(out_file) and (final_file is None or not utils.file_exists(final_file)): with postalign.tobam_cl(data, out_file, pair_file != "") as (tobam_cl, tx_out_file): if index_dir.endswith(("/ref", "/ref/")): index_dir = os.path.dirname(index_dir) # sam=1.3 required for compatibility with strelka2 cmd = ("bbmap.sh sam=1.3 mdtag=t {rg_info} path={index_dir} in1={fastq_file} " "{pair_arg} out=stdout.sam | ") do.run(cmd.format(**locals()) + tobam_cl, "bbmap alignment: %s" % dd.get_sample_name(data)) data["work_bam"] = out_file return data def remap_index_fn(ref_file): index_dir = os.path.join(os.path.dirname(ref_file), os.pardir, "bbmap") if os.path.exists(index_dir) and os.path.isdir(index_dir): return index_dir else: return os.path.dirname(ref_file) bcbio-nextgen-1.2.9/bcbio/ngsalign/bismark.py000066400000000000000000000161451415626112400211420ustar00rootroot00000000000000import os import glob import sys import shutil import pysam from bcbio.pipeline import config_utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.utils import (safe_makedir, file_exists) from bcbio.provenance import do from bcbio import utils from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio import bam from bcbio import broad from bcbio.wgbsseq import kits def align(fastq_file, pair_file, ref_file, names, align_dir, data): assert data["analysis"].lower().startswith("wgbs-seq"), "No comparible alignment." config = data["config"] sample = dd.get_sample_name(data) out_prefix = os.path.join(align_dir, dd.get_lane(data)) out_dir = os.path.join(align_dir, "%s_bismark" % dd.get_lane(data)) if not ref_file: logger.error("bismark index not found. You can install " "the index for your genome with: bcbio_nextgen.py upgrade " "--aligners bismark --genomes genome-build-name --data") sys.exit(1) final_out = os.path.join(align_dir, "{0}.bam".format(sample)) if file_exists(final_out): data = dd.set_work_bam(data, final_out) data["bam_report"] = glob.glob(os.path.join(out_dir, "*report.txt"))[0] data = dd.update_summary_qc(data, "bismark", base=data["bam_report"]) return data bismark = config_utils.get_program("bismark", config) # bismark uses 5 threads/sample and ~12GB RAM/sample (hg38) resources = config_utils.get_resources("bismark", data["config"]) max_cores = dd.get_num_cores(data) max_mem = config_utils.convert_to_bytes(resources.get("memory", "1G")) / (1024.0 * 1024.0) instances = calculate_bismark_instances(max_cores, max_mem * max_cores) # override instances if specified in the config if resources and resources.get("bismark_threads"): instances = resources.get("bismark_threads") logger.info(f"Using {instances} bismark instances - overriden by resources") bowtie_threads = 2 if resources and resources.get("bowtie_threads"): bowtie_threads = resources.get("bowtie_threads") logger.info(f"Using {bowtie_threads} bowtie threads per bismark instance") kit = kits.KITS.get(dd.get_kit(data), None) directional = "--non_directional" if kit and not kit.is_directional else "" other_opts = "" if resources and resources.get("options", []): other_opts = resources.get("options", []) if "--non_directional" in other_opts: if directional != "--non_directional": directional = "--non_directional" logger.info(f"Directional setting in the kit != setting in the yaml/resources, using {directional}") other_opts.remove("--non_directional") other_opts = " ".join([str(x) for x in other_opts]).strip() fastq_files = " ".join([fastq_file, pair_file]) if pair_file else fastq_file safe_makedir(align_dir) cmd = "{bismark} {other_opts} {directional} --bowtie2 --temp_dir {tx_out_dir} --gzip --parallel {instances} -p {bowtie_threads} -o {tx_out_dir} --unmapped {ref_file} {fastq_file} " if pair_file: fastq_file = "-1 %s -2 %s" % (fastq_file, pair_file) raw_bam = glob.glob(out_dir + "/*bismark*bt2*bam") if not raw_bam: with tx_tmpdir() as tx_out_dir: run_message = "Running Bismark aligner on %s and %s" % (fastq_file, ref_file) do.run(cmd.format(**locals()), run_message, None) shutil.move(tx_out_dir, out_dir) raw_bam = glob.glob(out_dir + "/*bismark*bt2*bam") # don't process bam in the bismark pipeline! utils.symlink_plus(raw_bam[0], final_out) data = dd.set_work_bam(data, final_out) data["bam_report"] = glob.glob(os.path.join(out_dir, "*report.txt"))[0] data = dd.update_summary_qc(data, "bismark", base=data["bam_report"]) return data def _process_bam(bam_file, in_fastq, sample, reference, config): broad_runner = broad.runner_from_config(config) names = {'rg': in_fastq, 'library': 'WGBS_LIB', 'pl': 'Illumina', 'pu': 'R1', 'sm': in_fastq, 'sample': sample} out_fix_bam = broad_runner.run_fn("picard_fix_rgs", bam_file, names) order_bam = utils.append_stem(out_fix_bam, "_order") broad_runner.run_fn("picard_reorder", out_fix_bam, reference, order_bam) bam.index(order_bam, config) # order_bam = _set_quality(order_bam) # bam.index(order_bam, config) return order_bam def remap_index_fn(ref_file): """Map sequence references to equivalent bismark indexes """ return os.path.join(os.path.dirname(os.path.dirname(ref_file)), "bismark") def _set_quality(in_bam): """ change all quality to 255 """ bam = pysam.AlignmentFile(in_bam, "rb") out_file = utils.append_stem(in_bam, "_normqual") if file_exists(out_file): return out_file with file_transaction(out_file) as tx_out: with pysam.AlignmentFile(tx_out, "wb", template=bam) as out_handle: for read in bam.fetch(): read.mapping_quality = 255 out_handle.write(read) return out_file def index(ref_file, out_dir, data): """Create a bismark index in the defined reference directory. """ (ref_dir, local_file) = os.path.split(ref_file) gtf_file = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) bismark = config_utils.find_program("bismark", data["config"]) if not utils.file_exists(gtf_file): raise ValueError("%s not found, could not create a bismark index." % (gtf_file)) if not utils.file_exists(out_dir): with tx_tmpdir(data, os.path.dirname(out_dir)) as tx_out_dir: num_cores = dd.get_cores(data) other_opts = config_utils.get_resources("bismark", data["config"]).get("options", []) other_opts = " ".join([str(x) for x in other_opts]).strip() cmd = "{bismark} {other_opts} --bowtie2 -p {num_cores} -n 1 -o {tx_out_dir} --basename {sample} --unmapped {ref_file} {in_fastq}" do.run(cmd.format(**locals()), "Index STAR") if os.path.exists(out_dir): shutil.rmtree(out_dir) shutil.move(tx_out_dir, out_dir) return out_dir def calculate_bismark_instances(cores, memory): """ calculate number of parallel bismark instances to run, based on disussion here https://github.com/FelixKrueger/Bismark/issues/96 cores and memory here are the maximum amounts available for us to use """ BISMARK_CORES = 1 BOWTIE_CORES_PER_INSTANCE = 2 SAMTOOLS_CORES_PER_INSTANCE = 1 CORES_PER_INSTANCE = BOWTIE_CORES_PER_INSTANCE + SAMTOOLS_CORES_PER_INSTANCE GENOME_MEMORY_GB = 12 INSTANCE_MEMORY_GB = 10 available_instance_memory = memory - GENOME_MEMORY_GB instances_in_memory = max(available_instance_memory / INSTANCE_MEMORY_GB, 1) available_instance_cores = cores - BISMARK_CORES instances_in_cores = max(available_instance_cores / CORES_PER_INSTANCE, 1) instances = int(min(instances_in_memory, instances_in_cores)) logger.info(f"{cores} cores and {memory} memory are available. Spinning up {instances} instances of bismark.") return instances bcbio-nextgen-1.2.9/bcbio/ngsalign/bowtie.py000066400000000000000000000061001415626112400207710ustar00rootroot00000000000000"""Next gen sequence alignments with Bowtie (http://bowtie-bio.sourceforge.net). """ import os from bcbio import utils from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.ngsalign import alignprep, novoalign, postalign from bcbio.provenance import do galaxy_location_file = "bowtie_indices.loc" def _bowtie_args_from_config(data): """Configurable high level options for bowtie. """ config = data['config'] qual_format = config["algorithm"].get("quality_format", "") if qual_format.lower() == "illumina": qual_flags = ["--phred64-quals"] else: qual_flags = [] multi_mappers = config["algorithm"].get("multiple_mappers", True) multi_flags = ["-M", 1] if multi_mappers else ["-m", 1] multi_flags = [] if data["analysis"].lower().startswith("smallrna-seq") else multi_flags cores = config.get("resources", {}).get("bowtie", {}).get("cores", None) num_cores = config["algorithm"].get("num_cores", 1) core_flags = ["-p", str(num_cores)] if num_cores > 1 else [] return core_flags + qual_flags + multi_flags def align(fastq_file, pair_file, ref_file, names, align_dir, data, extra_args=None): """Do standard or paired end alignment with bowtie. """ num_hits = 1 if data["analysis"].lower().startswith("smallrna-seq"): num_hits = 1000 config = data['config'] out_file = os.path.join(align_dir, "{0}-sort.bam".format(dd.get_sample_name(data))) if data.get("align_split"): final_file = out_file out_file, data = alignprep.setup_combine(final_file, data) fastq_file, pair_file = alignprep.split_namedpipe_cls(fastq_file, pair_file, data) else: final_file = None if fastq_file.endswith(".gz"): fastq_file = "<(gunzip -c %s)" % fastq_file if pair_file: pair_file = "<(gunzip -c %s)" % pair_file if not utils.file_exists(out_file) and (final_file is None or not utils.file_exists(final_file)): with postalign.tobam_cl(data, out_file, pair_file is not None) as (tobam_cl, tx_out_file): cl = [config_utils.get_program("bowtie", config)] cl += _bowtie_args_from_config(data) cl += extra_args if extra_args is not None else [] cl += ["-q", "-v", 2, "-k", num_hits, "-X", 2000, # default is too selective for most data "--best", "--strata", "--sam", ref_file] if pair_file: cl += ["-1", fastq_file, "-2", pair_file] else: cl += [fastq_file] cl = [str(i) for i in cl] fix_rg_cmd = r"samtools addreplacerg -r '%s' -" % novoalign.get_rg_info(data["rgnames"]) if fix_rg_cmd: cmd = " ".join(cl) + " | " + fix_rg_cmd + " | " + tobam_cl else: cmd = " ".join(cl) + " | " + tobam_cl do.run(cmd, "Running Bowtie on %s and %s." % (fastq_file, pair_file), data) return out_file bcbio-nextgen-1.2.9/bcbio/ngsalign/bowtie2.py000066400000000000000000000154431415626112400210650ustar00rootroot00000000000000"""Next gen sequence alignments with Bowtie2. http://bowtie-bio.sourceforge.net/bowtie2/index.shtml """ import os from bcbio.pipeline import config_utils from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio import bam, utils from bcbio.pipeline import datadict as dd from bcbio.rnaseq import gtf from bcbio.ngsalign import alignprep, postalign def _bowtie2_args_from_config(config, curcl): """Configurable high level options for bowtie2. """ qual_format = config["algorithm"].get("quality_format", "") if qual_format.lower() == "illumina": qual_flags = ["--phred64-quals"] else: qual_flags = [] num_cores = config["algorithm"].get("num_cores", 1) core_flags = ["-p", str(num_cores)] if num_cores > 1 else [] user_opts = config_utils.get_resources("bowtie2", config).get("options", []) for flag_opt in (o for o in user_opts if str(o).startswith("-")): if flag_opt in curcl: raise ValueError("Duplicate option %s in resources and bcbio commandline: %s %s" % flag_opt, user_opts, curcl) return core_flags + qual_flags + user_opts def align(fastq_file, pair_file, ref_file, names, align_dir, data, extra_args=None): """Alignment with bowtie2. """ config = data["config"] analysis_config = ANALYSIS.get(data["analysis"].lower()) assert analysis_config, "Analysis %s is not supported by bowtie2" % (data["analysis"]) out_file = os.path.join(align_dir, "{0}-sort.bam".format(dd.get_sample_name(data))) if data.get("align_split"): final_file = out_file out_file, data = alignprep.setup_combine(final_file, data) fastq_file, pair_file = alignprep.split_namedpipe_cls(fastq_file, pair_file, data) else: final_file = None if not utils.file_exists(out_file) and (final_file is None or not utils.file_exists(final_file)): with postalign.tobam_cl(data, out_file, pair_file is not None) as (tobam_cl, tx_out_file): cl = [config_utils.get_program("bowtie2", config)] cl += extra_args if extra_args is not None else [] cl += ["-q", "-x", ref_file] cl += analysis_config.get("params", []) if pair_file: cl += ["-1", fastq_file, "-2", pair_file] else: cl += ["-U", fastq_file] if names and "rg" in names: cl += ["--rg-id", names["rg"]] for key, tag in [("sample", "SM"), ("pl", "PL"), ("pu", "PU"), ("lb", "LB")]: if names.get(key): cl += ["--rg", "%s:%s" % (tag, names[key])] cl += _bowtie2_args_from_config(config, cl) cl = [str(i) for i in cl] cmd = "unset JAVA_HOME && " + " ".join(cl) + " | " + tobam_cl do.run(cmd, "Aligning %s and %s with Bowtie2." % (fastq_file, pair_file)) return out_file # Optional galaxy location file. Falls back on remap_index_fn if not found galaxy_location_file = "bowtie2_indices.loc" def remap_index_fn(ref_file): """Map sequence references to equivalent bowtie2 indexes. """ return os.path.splitext(ref_file)[0].replace("/seq/", "/bowtie2/") def filter_multimappers(align_file, data): """ It does not seem like bowtie2 has a corollary to the -m 1 flag in bowtie, there are some options that are close but don't do the same thing. Bowtie2 sets the XS flag for reads mapping in more than one place, so we can just filter on that. This will not work for other aligners. """ config = dd.get_config(data) type_flag = "" if bam.is_bam(align_file) else "S" base, ext = os.path.splitext(align_file) out_file = base + ".unique" + ext bed_file = dd.get_variant_regions(data) or dd.get_sample_callable(data) bed_cmd = '-L {0}'.format(bed_file) if bed_file else " " if utils.file_exists(out_file): return out_file base_filter = '-F "[XS] == null and not unmapped {paired_filter}" ' if bam.is_paired(align_file): paired_filter = "and paired and proper_pair" else: paired_filter = "" filter_string = base_filter.format(paired_filter=paired_filter) sambamba = config_utils.get_program("sambamba", config) num_cores = dd.get_num_cores(data) with file_transaction(out_file) as tx_out_file: cmd = ('{sambamba} view -h{type_flag} ' '--nthreads {num_cores} ' '-f bam {bed_cmd} ' '{filter_string} ' '{align_file} ' '> {tx_out_file}') message = "Removing multimapped reads from %s." % align_file do.run(cmd.format(**locals()), message) bam.index(out_file, config) return out_file ANALYSIS = {"chip-seq": {"params": ["-X", 2000, "--very-sensitive-local"]}, "variant2": {"params": ["-X", 2000]}, "standard": {"params": ["-X", 2000]}, "rna-seq": {"params": ["--sensitive", "-X", 2000]}, "smallrna-seq": {"params": ["-N", 1, "-k", 1000, "--sensitive", "-X", 200]}} def index_transcriptome(gtf_file, ref_file, data): """ use a GTF file and a reference FASTA file to index the transcriptome """ gtf_fasta = gtf.gtf_to_fasta(gtf_file, ref_file) bowtie2_index = os.path.splitext(gtf_fasta)[0] bowtie2_build = config_utils.get_program("bowtie2", data["config"]) + "-build" cmd = "{bowtie2_build} --offrate 1 {gtf_fasta} {bowtie2_index}".format(**locals()) message = "Creating transcriptome index of %s with bowtie2." % (gtf_fasta) do.run(cmd, message) return bowtie2_index def align_transcriptome(fastq_file, pair_file, ref_file, data): """ bowtie2 with settings for aligning to the transcriptome for eXpress/RSEM/etc """ work_bam = dd.get_work_bam(data) base, ext = os.path.splitext(work_bam) out_file = base + ".transcriptome" + ext if utils.file_exists(out_file): data = dd.set_transcriptome_bam(data, out_file) return data bowtie2 = config_utils.get_program("bowtie2", data["config"]) gtf_file = dd.get_gtf_file(data) gtf_index = index_transcriptome(gtf_file, ref_file, data) num_cores = data["config"]["algorithm"].get("num_cores", 1) fastq_cmd = "-1 %s" % fastq_file if pair_file else "-U %s" % fastq_file pair_cmd = "-2 %s " % pair_file if pair_file else "" cmd = ("{bowtie2} -p {num_cores} -a -X 600 --rdg 6,5 --rfg 6,5 --score-min L,-.6,-.4 --no-discordant --no-mixed -x {gtf_index} {fastq_cmd} {pair_cmd} ") with file_transaction(data, out_file) as tx_out_file: message = "Aligning %s and %s to the transcriptome." % (fastq_file, pair_file) cmd += "| " + postalign.sam_to_sortbam_cl(data, tx_out_file, name_sort=True) do.run(cmd.format(**locals()), message) data = dd.set_transcriptome_bam(data, out_file) return data bcbio-nextgen-1.2.9/bcbio/ngsalign/bsmap.py000066400000000000000000000040761415626112400206140ustar00rootroot00000000000000import os from bcbio.pipeline import config_utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.utils import (safe_makedir, file_exists) from bcbio.provenance import do from bcbio import utils from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.ngsalign import postalign from bcbio import bam from bcbio import broad def align(fastq_file, pair_file, ref_file, names, align_dir, data): assert data["analysis"].lower().startswith("wgbs-seq"), "No comparible alignment" config = data["config"] sample = dd.get_sample_name(data) out_prefix = os.path.join(align_dir, dd.get_lane(data)) ref_file = dd.get_sam_ref(data) final_out = os.path.join(align_dir, "{0}.bam".format(sample)) if file_exists(final_out): data = dd.set_work_bam(data, final_out) return data bsmap = config_utils.get_program("bsmap", config) fastq_files = " -a %s" % fastq_file num_cores = dd.get_num_cores(data) num_cores = "-p %d" % num_cores safe_makedir(align_dir) cmd = "{bsmap} {num_cores} -w 100 -v 0.07 -m 10 -x 300 -o {tx_out_bam} -d {ref_file} {fastq_files}" if pair_file: fastq_files = "-a %s -b %s" % (fastq_file, pair_file) if not final_out: with file_transaction(final_out) as tx_out_bam: run_message = "Running BSMAP aligner on %s and %s" % (fastq_file, ref_file) do.run(cmd.format(**locals()), run_message, None) data = dd.set_work_bam(data, final_out) return data def _process_bam(bam_file, in_fastq, sample, reference, config): broad_runner = broad.runner_from_config(config) names = {'rg': in_fastq, 'library': 'WGBS_LIB', 'pl': 'Illumina', 'pu': 'R1', 'sm': in_fastq, 'sample': sample} out_fix_bam = broad_runner.run_fn("picard_fix_rgs", bam_file, names) order_bam = utils.append_stem(out_fix_bam, "_order") broad_runner.run_fn("picard_reorder", out_fix_bam, reference, order_bam) bam.index(order_bam, config) # order_bam = _set_quality(order_bam) # bam.index(order_bam, config) return order_bam bcbio-nextgen-1.2.9/bcbio/ngsalign/bwa.py000066400000000000000000000420511415626112400202560ustar00rootroot00000000000000"""BWA (https://github.com/lh3/bwa) """ import os import signal import subprocess from bcbio.pipeline import config_utils from bcbio import bam, utils from bcbio.distributed import objectstore from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.ngsalign import alignprep, novoalign, postalign, rtg from bcbio.provenance import do from bcbio.rnaseq import gtf from bcbio.variation import sentieon import bcbio.pipeline.datadict as dd from bcbio.bam import fastq from bcbio.log import logger galaxy_location_file = "bwa_index.loc" def align_bam(in_bam, ref_file, names, align_dir, data): """Perform direct alignment of an input BAM file with BWA using pipes. This avoids disk IO by piping between processes: - samtools sort of input BAM to queryname - bedtools conversion to interleaved FASTQ - bwa-mem alignment - samtools conversion to BAM - samtools sort to coordinate """ config = data["config"] out_file = os.path.join(align_dir, "{0}-sort.bam".format(names["lane"])) samtools = config_utils.get_program("samtools", config) bedtools = config_utils.get_program("bedtools", config) resources = config_utils.get_resources("samtools", config) num_cores = config["algorithm"].get("num_cores", 1) # adjust memory for samtools since used for input and output max_mem = config_utils.adjust_memory(resources.get("memory", "1G"), 3, "decrease").upper() if not utils.file_exists(out_file): with tx_tmpdir(data) as work_dir: with postalign.tobam_cl(data, out_file, bam.is_paired(in_bam)) as (tobam_cl, tx_out_file): if not hla_on(data) or needs_separate_hla(data): bwa_cmd = _get_bwa_mem_cmd(data, out_file, ref_file, "-", with_hla=False) else: bwa_cmd = _get_bwa_mem_cmd(data, out_file, ref_file, "-", with_hla=True) tx_out_prefix = os.path.splitext(tx_out_file)[0] prefix1 = "%s-in1" % tx_out_prefix cmd = ("unset JAVA_HOME && " "{samtools} sort -n -l 1 -@ {num_cores} -m {max_mem} {in_bam} -T {prefix1} " "| {bedtools} bamtofastq -i /dev/stdin -fq /dev/stdout -fq2 /dev/stdout " "| {bwa_cmd} | ") cmd = cmd.format(**locals()) + tobam_cl do.run(cmd, "bwa mem alignment from BAM: %s" % names["sample"], None, [do.file_nonempty(tx_out_file), do.file_reasonable_size(tx_out_file, in_bam)]) data["work_bam"] = out_file hla_file = "HLA-" + out_file if needs_separate_hla(data) and not utils.file_exists(hla_file): with tx_tmpdir(data) as work_dir: with postalign.tobam_cl(data, hla_file, bam.is_paired(in_bam)) as (tobam_cl, tx_out_file): bwa_cmd = _get_bwa_mem_cmd(data, hla_file, ref_file, "-", with_hla=True) tx_out_prefix = os.path.splitext(tx_out_file)[0] prefix1 = "%s-in1" % tx_out_prefix cmd = ("unset JAVA_HOME && " "{samtools} sort -n -l 1 -@ {num_cores} -m {max_mem} {in_bam} -T {prefix1} " "| {bedtools} bamtofastq -i /dev/stdin -fq /dev/stdout -fq2 /dev/stdout " "| {bwa_cmd} | ") cmd = cmd.format(**locals()) + tobam_cl do.run(cmd, "bwa mem alignment from BAM: %s" % names["sample"], None, [do.file_nonempty(tx_out_file), do.file_reasonable_size(tx_out_file, in_bam)]) hla_file = _align_mem_hla(fastq_file, pair_file, ref_file, hla_file, names, rg_info, data) data["hla_bam"] = hla_file return data def _get_bwa_mem_cmd(data, out_file, ref_file, fastq1, fastq2="", with_hla=False): """Perform piped bwa mem mapping potentially with alternative alleles in GRCh38 + HLA typing. Commands for HLA post-processing: base=TEST run-HLA $base.hla > $base.hla.top cat $base.hla.HLA*.gt | grep ^GT | cut -f2- > $base.hla.all rm -f $base.hla.HLA*gt rm -f $base.hla.HLA*gz """ alt_file = ref_file + ".alt" if with_hla: bwakit_dir = os.path.dirname(os.path.realpath(utils.which("run-bwamem"))) hla_base = os.path.join(utils.safe_makedir(os.path.join(os.path.dirname(out_file), "hla")), os.path.basename(out_file) + ".hla") alt_cmd = (" | {bwakit_dir}/k8 {bwakit_dir}/bwa-postalt.js -p {hla_base} {alt_file}") else: alt_cmd = "" if dd.get_aligner(data) == "sentieon-bwa": bwa_exe = "sentieon-bwa" exports = sentieon.license_export(data) else: bwa_exe = "bwa" exports = "" bwa = config_utils.get_program(bwa_exe, data["config"]) num_cores = data["config"]["algorithm"].get("num_cores", 1) bwa_resources = config_utils.get_resources("bwa", data["config"]) bwa_params = (" ".join([str(x) for x in bwa_resources.get("options", [])]) if "options" in bwa_resources else "") rg_info = novoalign.get_rg_info(data["rgnames"]) # For UMI runs, pass along consensus tags c_tags = "-C" if "umi_bam" in data else "" pairing = "-p" if not fastq2 else "" # Restrict seed occurances to 1/2 of default, manage memory usage for centromere repeats in hg38 # https://sourceforge.net/p/bio-bwa/mailman/message/31514937/ # http://ehc.ac/p/bio-bwa/mailman/message/32268544/ mem_usage = "-c 250" bwa_cmd = ("{exports}{bwa} mem {pairing} {c_tags} {mem_usage} -M -t {num_cores} {bwa_params} -R '{rg_info}' " "-v 1 {ref_file} {fastq1} {fastq2} ") return (bwa_cmd + alt_cmd).format(**locals()) def is_precollapsed_bam(data): return dd.get_umi_type(data) == "fastq_name" and not has_umi(data) def hla_on(data): return has_hla(data) and dd.get_hlacaller(data) def has_umi(data): return "umi_bam" in data def has_hla(data): from bcbio.heterogeneity import chromhacks return len(chromhacks.get_hla_chroms(dd.get_ref_file(data))) != 0 def fastq_size_output(fastq_file, tocheck): head_count = 8000000 fastq_file = objectstore.cl_input(fastq_file) gzip_cmd = "zcat {fastq_file}" if fastq_file.endswith(".gz") else "cat {fastq_file}" cmd = (utils.local_path_export() + gzip_cmd + " | head -n {head_count} | " "seqtk sample -s42 - {tocheck} | " "awk '{{if(NR%4==2) print length($1)}}' | sort | uniq -c") def fix_signal(): """Avoid spurious 'cat: write error: Broken pipe' message due to head command. Work around from: https://bitbucket.org/brodie/cram/issues/16/broken-pipe-when-heading-certain-output """ signal.signal(signal.SIGPIPE, signal.SIG_DFL) count_out = subprocess.check_output(cmd.format(**locals()), shell=True, executable="/bin/bash", preexec_fn=fix_signal).decode() if not count_out.strip(): raise IOError("Failed to check fastq file sizes with: %s" % cmd.format(**locals())) for count, size in (l.strip().split() for l in count_out.strip().split("\n")): yield count, size def _can_use_mem(fastq_file, data, read_min_size=None): """bwa-mem handle longer (> 70bp) reads with improved piping. Randomly samples 5000 reads from the first two million. Default to no piping if more than 75% of the sampled reads are small. If we've previously calculated minimum read sizes (from rtg SDF output) we can skip the formal check. """ min_size = 70 if read_min_size and read_min_size >= min_size: return True thresh = 0.75 tocheck = 5000 shorter = 0 for count, size in fastq_size_output(fastq_file, tocheck): if int(size) < min_size: shorter += int(count) return (float(shorter) / float(tocheck)) <= thresh def align_pipe(fastq_file, pair_file, ref_file, names, align_dir, data): """Perform piped alignment of fastq input files, generating sorted output BAM. """ pair_file = pair_file if pair_file else "" # back compatible -- older files were named with lane information, use sample name now if names["lane"] != dd.get_sample_name(data): out_file = os.path.join(align_dir, "{0}-sort.bam".format(names["lane"])) else: out_file = None if not out_file or not utils.file_exists(out_file): umi_ext = "-cumi" if "umi_bam" in data else "" out_file = os.path.join(align_dir, "{0}-sort{1}.bam".format(dd.get_sample_name(data), umi_ext)) qual_format = data["config"]["algorithm"].get("quality_format", "").lower() min_size = None if data.get("align_split") or fastq_file.endswith(".sdf"): if fastq_file.endswith(".sdf"): min_size = rtg.min_read_size(fastq_file) final_file = out_file out_file, data = alignprep.setup_combine(final_file, data) fastq_file, pair_file = alignprep.split_namedpipe_cls(fastq_file, pair_file, data) else: final_file = None if qual_format == "illumina": fastq_file = alignprep.fastq_convert_pipe_cl(fastq_file, data) if pair_file: pair_file = alignprep.fastq_convert_pipe_cl(pair_file, data) rg_info = novoalign.get_rg_info(names) if not utils.file_exists(out_file) and (final_file is None or not utils.file_exists(final_file)): # If we cannot do piping, use older bwa aln approach if ("bwa-mem" not in dd.get_tools_on(data) and ("bwa-mem" in dd.get_tools_off(data) or not _can_use_mem(fastq_file, data, min_size))): out_file = _align_backtrack(fastq_file, pair_file, ref_file, out_file, names, rg_info, data) else: if is_precollapsed_bam(data) or not hla_on(data) or needs_separate_hla(data): out_file = _align_mem(fastq_file, pair_file, ref_file, out_file, names, rg_info, data) else: out_file = _align_mem_hla(fastq_file, pair_file, ref_file, out_file, names, rg_info, data) data["work_bam"] = out_file # bwakit will corrupt the non-HLA alignments in a UMI collapsed BAM file # (see https://github.com/bcbio/bcbio-nextgen/issues/3069) if needs_separate_hla(data): hla_file = os.path.join(os.path.dirname(out_file), "HLA-" + os.path.basename(out_file)) hla_file = _align_mem_hla(fastq_file, pair_file, ref_file, hla_file, names, rg_info, data) data["hla_bam"] = hla_file return data def _align_mem(fastq_file, pair_file, ref_file, out_file, names, rg_info, data): """Perform bwa-mem alignment on supported read lengths. """ with postalign.tobam_cl(data, out_file, pair_file != "") as (tobam_cl, tx_out_file): cmd = ("unset JAVA_HOME && " "%s | %s" % (_get_bwa_mem_cmd(data, out_file, ref_file, fastq_file, pair_file, with_hla=False), tobam_cl)) do.run(cmd, "bwa mem alignment from fastq: %s" % names["sample"], None, [do.file_nonempty(tx_out_file), do.file_reasonable_size(tx_out_file, fastq_file)]) return out_file def _align_mem_hla(fastq_file, pair_file, ref_file, out_file, names, rg_info, data): """Perform bwa-mem alignment on supported read lengths with HLA alignments """ with postalign.tobam_cl(data, out_file, pair_file != "") as (tobam_cl, tx_out_file): cmd = ("unset JAVA_HOME && " "%s | %s" % (_get_bwa_mem_cmd(data, out_file, ref_file, fastq_file, pair_file, with_hla=True), tobam_cl)) do.run(cmd, "bwa mem alignment from fastq: %s" % names["sample"], None, [do.file_nonempty(tx_out_file), do.file_reasonable_size(tx_out_file, fastq_file)]) return out_file def needs_separate_hla(data): """ bwakit will corrupt the non-HLA alignments in a UMI collapsed BAM file (see https://github.com/bcbio/bcbio-nextgen/issues/3069) """ return hla_on(data) and has_umi(data) def _align_backtrack(fastq_file, pair_file, ref_file, out_file, names, rg_info, data): """Perform a BWA alignment using 'aln' backtrack algorithm. """ bwa = config_utils.get_program("bwa", data["config"]) config = data["config"] sai1_file = "%s_1.sai" % os.path.splitext(out_file)[0] sai2_file = "%s_2.sai" % os.path.splitext(out_file)[0] if pair_file else "" if not utils.file_exists(sai1_file): with file_transaction(data, sai1_file) as tx_sai1_file: _run_bwa_align(fastq_file, ref_file, tx_sai1_file, config) if sai2_file and not utils.file_exists(sai2_file): with file_transaction(data, sai2_file) as tx_sai2_file: _run_bwa_align(pair_file, ref_file, tx_sai2_file, config) with postalign.tobam_cl(data, out_file, pair_file != "") as (tobam_cl, tx_out_file): align_type = "sampe" if sai2_file else "samse" cmd = ("unset JAVA_HOME && {bwa} {align_type} -r '{rg_info}' {ref_file} {sai1_file} {sai2_file} " "{fastq_file} {pair_file} | ") cmd = cmd.format(**locals()) + tobam_cl do.run(cmd, "bwa %s" % align_type, data) return out_file def _bwa_args_from_config(config): num_cores = config["algorithm"].get("num_cores", 1) core_flags = ["-t", str(num_cores)] if num_cores > 1 else [] return core_flags def _run_bwa_align(fastq_file, ref_file, out_file, config): aln_cl = [config_utils.get_program("bwa", config), "aln", "-n 2", "-k 2"] aln_cl += _bwa_args_from_config(config) aln_cl += [ref_file, fastq_file] cmd = "{cl} > {out_file}".format(cl=" ".join(aln_cl), out_file=out_file) do.run(cmd, "bwa aln: {f}".format(f=os.path.basename(fastq_file)), None) def index_transcriptome(gtf_file, ref_file, data): """ use a GTF file and a reference FASTA file to index the transcriptome """ gtf_fasta = gtf.gtf_to_fasta(gtf_file, ref_file) return build_bwa_index(gtf_fasta, data) def build_bwa_index(fasta_file, data): bwa = config_utils.get_program("bwa", data["config"]) cmd = "{bwa} index {fasta_file}".format(**locals()) message = "Creating transcriptome index of %s with bwa." % (fasta_file) do.run(cmd, message) return fasta_file def align_transcriptome(fastq_file, pair_file, ref_file, data): """ bwa mem with settings for aligning to the transcriptome for eXpress/RSEM/etc """ work_bam = dd.get_work_bam(data) base, ext = os.path.splitext(work_bam) out_file = base + ".transcriptome" + ext if utils.file_exists(out_file): data = dd.set_transcriptome_bam(data, out_file) return data # bwa mem needs phred+33 quality, so convert if it is Illumina if dd.get_quality_format(data).lower() == "illumina": logger.info("bwa mem does not support the phred+64 quality format, " "converting %s and %s to phred+33.") fastq_file = fastq.groom(fastq_file, data, in_qual="fastq-illumina") if pair_file: pair_file = fastq.groom(pair_file, data, in_qual="fastq-illumina") bwa = config_utils.get_program("bwa", data["config"]) gtf_file = dd.get_gtf_file(data) gtf_fasta = index_transcriptome(gtf_file, ref_file, data) args = " ".join(_bwa_args_from_config(data["config"])) num_cores = data["config"]["algorithm"].get("num_cores", 1) samtools = config_utils.get_program("samtools", data["config"]) cmd = ("{bwa} mem {args} -a -t {num_cores} {gtf_fasta} {fastq_file} " "{pair_file} ") with file_transaction(data, out_file) as tx_out_file: message = "Aligning %s and %s to the transcriptome." % (fastq_file, pair_file) cmd += "| " + postalign.sam_to_sortbam_cl(data, tx_out_file, name_sort=True) do.run(cmd.format(**locals()), message) data = dd.set_transcriptome_bam(data, out_file) return data def filter_multimappers(align_file, data): """ Filtering a BWA alignment file for uniquely mapped reads, from here: https://bioinformatics.stackexchange.com/questions/508/obtaining-uniquely-mapped-reads-from-bwa-mem-alignment """ config = dd.get_config(data) type_flag = "" if bam.is_bam(align_file) else "S" base, ext = os.path.splitext(align_file) out_file = base + ".unique" + ext bed_file = dd.get_variant_regions(data) or dd.get_sample_callable(data) bed_cmd = '-L {0}'.format(bed_file) if bed_file else " " if utils.file_exists(out_file): return out_file base_filter = '-F "not unmapped {paired_filter} and [XA] == null and [SA] == null and not supplementary " ' if bam.is_paired(align_file): paired_filter = "and paired and proper_pair" else: paired_filter = "" filter_string = base_filter.format(paired_filter=paired_filter) sambamba = config_utils.get_program("sambamba", config) num_cores = dd.get_num_cores(data) with file_transaction(out_file) as tx_out_file: cmd = ('{sambamba} view -h{type_flag} ' '--nthreads {num_cores} ' '-f bam {bed_cmd} ' '{filter_string} ' '{align_file} ' '> {tx_out_file}') message = "Removing multimapped reads from %s." % align_file do.run(cmd.format(**locals()), message) bam.index(out_file, config) return out_file bcbio-nextgen-1.2.9/bcbio/ngsalign/hisat2.py000066400000000000000000000137301415626112400207010ustar00rootroot00000000000000import os from bcbio.utils import file_exists, safe_makedir from bcbio import bam from bcbio import bed import bcbio.pipeline.datadict as dd from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.ngsalign import alignprep, postalign from bcbio.provenance import do def align(fastq_file, pair_file, ref_file, names, align_dir, data): paired = True if pair_file else False hisat2 = config_utils.get_program("hisat2", data) num_cores = dd.get_num_cores(data) quality_flag = _get_quality_flag(data) stranded_flag = _get_stranded_flag(data, paired) rg_flags = _get_rg_flags(names) out_file = os.path.join(align_dir, "{0}-sort.bam".format(dd.get_sample_name(data))) if data.get("align_split"): final_file = out_file out_file, data = alignprep.setup_combine(final_file, data) fastq_file, pair_file = alignprep.split_namedpipe_cls(fastq_file, pair_file, data) else: final_file = None if not file_exists(out_file) and (final_file is None or not file_exists(final_file)): cmd = ("{hisat2} --new-summary -x {ref_file} -p {num_cores} {quality_flag} {stranded_flag} " "{rg_flags} ") if paired: cmd += "-1 {fastq_file} -2 {pair_file} " else: cmd += "-U {fastq_file} " if dd.get_analysis(data).lower() == "smallrna-seq": cmd += "-k 1000 " # if assembling transcripts, set flags that cufflinks/stringtie can use if dd.get_transcript_assembler(data): cmd += "--dta-cufflinks " if dd.get_analysis(data).lower() == "rna-seq": splicesites = get_known_splicesites_file(align_dir, data) if file_exists(splicesites): cmd += "--known-splicesite-infile {splicesites} " novel_splicesite_file = os.path.join(align_dir, "{0}-novelsplicesites.bed".format(dd.get_sample_name(data))) cmd += "--novel-splicesite-outfile {novel_splicesite_file} " # apply additional hisat2 options cmd += " ".join(_get_options_from_config(data)) message = "Aligning %s and %s with hisat2." % (fastq_file, pair_file) with postalign.tobam_cl(data, out_file, pair_file is not None) as (tobam_cl, tx_out_file): cmd += " | " + tobam_cl do.run(cmd.format(**locals()), message) data = dd.set_work_bam(data, out_file) junctionbed = get_splicejunction_file(align_dir, data) data = dd.set_junction_bed(data, junctionbed) return data def get_known_splicesites_file(align_dir, data): gtf_file = dd.get_gtf_file(data) splicesites = os.path.join(os.path.dirname(gtf_file), "ref-transcripts-splicesites.txt") if not file_exists(splicesites): splicesites = create_splicesites_file(gtf_file, align_dir, data) return splicesites def create_splicesites_file(gtf_file, align_dir, data): """ if not pre-created, make a splicesites file to use with hisat2 """ out_file = os.path.join(align_dir, "ref-transcripts-splicesites.txt") if file_exists(out_file): return out_file safe_makedir(align_dir) hisat2_ss = config_utils.get_program("hisat2_extract_splice_sites.py", data) cmd = "{hisat2_ss} {gtf_file} > {tx_out_file}" message = "Creating hisat2 splicesites file from %s." % gtf_file with file_transaction(out_file) as tx_out_file: do.run(cmd.format(**locals()), message) return out_file def _get_quality_flag(data): qual_format = dd.get_quality_format(data) if qual_format.lower() == "illumina": return "--phred64" elif qual_format.lower() == "solexa": return "--solexa-quals" else: return "--phred33" def _get_options_from_config(config): opts = [] resources = config_utils.get_resources("hisat2", config) if resources.get("options"): opts += [str(x) for x in resources["options"]] return opts def _get_stranded_flag(data, paired): strandedness = dd.get_strandedness(data) base = "--rna-strandness " if paired: if strandedness and strandedness.lower() in ["firstrand", "firststrand"]: return base + "RF" elif strandedness and strandedness.lower() == "secondstrand": return base + "FR" else: return "" else: if strandedness and strandedness.lower() in ["firstrand", "firststrand"]: return base + "R" elif strandedness and strandedness.lower() == "secondstrand": return base + "F" else: return "" def _get_rg_flags(names): rg_id = names["rg"] rg_sample = names["sample"] rg_library = names["pl"] rg_platform_unit = names["pu"] rg_lb = ("--rg LB:%s " % names.get("lb")) if names.get("lb") else "" flags = ("--rg-id {rg_id} --rg PL:{rg_library} --rg PU:{rg_platform_unit} " "--rg SM:{rg_sample} {rg_lb}") return flags.format(**locals()) def remap_index_fn(ref_file): """Map sequence references to equivalent hisat2 indexes """ return os.path.splitext(ref_file)[0].replace("/seq/", "/hisat2/") def get_splicejunction_file(align_dir, data): """ locate the splice junction file from hisat2. hisat2 outputs a novel splicesites file to go along with the provided file, if available. this combines the two together and outputs a combined file of all of the known and novel splice junctions """ samplename = dd.get_sample_name(data) align_dir = os.path.dirname(dd.get_work_bam(data)) knownfile = get_known_splicesites_file(align_dir, data) novelfile = os.path.join(align_dir, "%s-novelsplicesites.bed" % samplename) bed_files = [x for x in [knownfile, novelfile] if file_exists(x)] splicejunction = bed.concat(bed_files) splicejunctionfile = os.path.join(align_dir, "%s-splicejunctions.bed" % samplename) if splicejunction: splicejunction.saveas(splicejunctionfile) return splicejunctionfile else: return None bcbio-nextgen-1.2.9/bcbio/ngsalign/minimap2.py000066400000000000000000000045141415626112400212230ustar00rootroot00000000000000"""Alignment with minimap2: https://github.com/lh3/minimap2 """ import os from bcbio import utils from bcbio.pipeline import datadict as dd from bcbio.ngsalign import alignprep, novoalign, postalign from bcbio.provenance import do def align(fastq_file, pair_file, index_dir, names, align_dir, data): """Perform piped alignment of fastq input files, generating sorted, deduplicated BAM. """ umi_ext = "-cumi" if "umi_bam" in data else "" out_file = os.path.join(align_dir, "{0}-sort{1}.bam".format(dd.get_sample_name(data), umi_ext)) num_cores = data["config"]["algorithm"].get("num_cores", 1) rg_info = novoalign.get_rg_info(names) preset = "sr" pair_file = pair_file if pair_file else "" if data.get("align_split"): final_file = out_file out_file, data = alignprep.setup_combine(final_file, data) fastq_file, pair_file = alignprep.split_namedpipe_cls(fastq_file, pair_file, data) else: final_file = None if not utils.file_exists(out_file) and (final_file is None or not utils.file_exists(final_file)): with postalign.tobam_cl(data, out_file, pair_file != "") as (tobam_cl, tx_out_file): index_file = None # Skip trying to use indices now as they provide only slight speed-ups # and give inconsitent outputs in BAM headers # If a single index present, index_dir points to that # if index_dir and os.path.isfile(index_dir): # index_dir = os.path.dirname(index_dir) # index_file = os.path.join(index_dir, "%s-%s.mmi" % (dd.get_genome_build(data), preset)) if not index_file or not os.path.exists(index_file): index_file = dd.get_ref_file(data) cmd = ("minimap2 -a -x {preset} -R '{rg_info}' -t {num_cores} {index_file} " "{fastq_file} {pair_file} | ") do.run(cmd.format(**locals()) + tobam_cl, "minimap2 alignment: %s" % dd.get_sample_name(data)) data["work_bam"] = out_file return data def remap_index_fn(ref_file): """minimap2 can build indexes on the fly but will also store commons ones. """ index_dir = os.path.join(os.path.dirname(ref_file), os.pardir, "minimap2") if os.path.exists(index_dir) and os.path.isdir(index_dir): return index_dir else: return os.path.dirname(ref_file) bcbio-nextgen-1.2.9/bcbio/ngsalign/mosaik.py000066400000000000000000000077161415626112400210010ustar00rootroot00000000000000"""Next gen sequence alignment with Mosaik. https://code.google.com/p/mosaik-aligner/ """ import os import subprocess from bcbio.pipeline import config_utils from bcbio.utils import file_exists from bcbio.distributed.transaction import file_transaction galaxy_location_file = "mosaik_index.loc" def _mosaik_args_from_config(config): """Configurable high level options for mosaik. """ multi_mappers = config["algorithm"].get("multiple_mappers", True) multi_flags = ["-m", "all"] if multi_mappers else ["-m", "unique"] error_flags = ["-mm", "2"] num_cores = config["algorithm"].get("num_cores", 1) core_flags = ["-p", str(num_cores)] if num_cores > 1 else [] return core_flags + multi_flags + error_flags def _convert_fastq(fastq_file, pair_file, rg_name, out_file, config): """Convert fastq inputs into internal Mosaik representation. """ out_file = "{0}-fq.mkb".format(os.path.splitext(out_file)[0]) if not file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: cl = [config_utils.get_program("mosaik", config, default="MosaikAligner").replace("Aligner", "Build")] cl += ["-q", fastq_file, "-out", tx_out_file, "-st", config["algorithm"].get("platform", "illumina").lower()] if pair_file: cl += ["-q2", pair_file] if rg_name: cl += ["-id", rg_name] env_set = "export MOSAIK_TMP={0}".format(os.path.dirname(tx_out_file)) subprocess.check_call(env_set + " && " + " ".join(cl), shell=True) return out_file def _get_mosaik_nn_args(out_file): """Retrieve default neural network files from GitHub to pass to Mosaik. """ base_nn_url = "https://raw.githubusercontent.com/wanpinglee/MOSAIK/master/src/networkFile/" out = [] for arg, fname in [("-annse", "2.1.26.se.100.005.ann"), ("-annpe", "2.1.26.pe.100.0065.ann")]: arg_fname = os.path.join(os.path.dirname(out_file), fname) if not file_exists(arg_fname): subprocess.check_call(["wget", "-O", arg_fname, base_nn_url + fname]) out += [arg, arg_fname] return out def align(fastq_file, pair_file, ref_file, names, align_dir, data, extra_args=None): """Alignment with MosaikAligner. """ config = data["config"] rg_name = names.get("rg", None) if names else None out_file = os.path.join(align_dir, "%s-align.bam" % names["lane"]) if not file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: built_fastq = _convert_fastq(fastq_file, pair_file, rg_name, out_file, config) cl = [config_utils.get_program("mosaik", config, default="MosaikAligner")] cl += _mosaik_args_from_config(config) cl += extra_args if extra_args is not None else [] cl += ["-ia", ref_file, "-in", built_fastq, "-out", os.path.splitext(tx_out_file)[0]] jump_base = os.path.splitext(ref_file)[0] key_file = "{0}_keys.jmp".format(jump_base) if file_exists(key_file): cl += ["-j", jump_base] # XXX hacky way to guess key size which needs to match # Can I get hash size directly jump_size_gb = os.path.getsize(key_file) / 1073741824.0 if jump_size_gb < 1.0: cl += ["-hs", "13"] cl += _get_mosaik_nn_args(out_file) env_set = "export MOSAIK_TMP={0}".format(os.path.dirname(tx_out_file)) subprocess.check_call(env_set + " && "+ " ".join([str(x) for x in cl]), shell=True) os.remove(built_fastq) return out_file def remap_index_fn(ref_file): """Map bowtie references to equivalent mosaik indexes. """ return ref_file.replace("/bowtie/", "/mosaik/") bcbio-nextgen-1.2.9/bcbio/ngsalign/novoalign.py000066400000000000000000000142341415626112400215030ustar00rootroot00000000000000"""Next-gen sequencing alignment with Novoalign: http://www.novocraft.com For BAM input handling this requires: novoalign (with license for multicore) samtools """ import os import subprocess from bcbio import bam, utils from bcbio.ngsalign import alignprep, postalign from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.distributed.transaction import tx_tmpdir from bcbio.utils import (memoize_outfile, file_exists) import six # ## BAM realignment def get_rg_info(names): out = r"@RG\tID:{rg}\tPL:{pl}\tPU:{pu}\tSM:{sample}".format(**names) if names.get("lb"): out += r"\tLB:{lb}".format(**names) return out def align_bam(in_bam, ref_file, names, align_dir, data): """Perform realignment of input BAM file; uses unix pipes for avoid IO. """ config = data["config"] out_file = os.path.join(align_dir, "{0}-sort.bam".format(names["lane"])) novoalign = config_utils.get_program("novoalign", config) samtools = config_utils.get_program("samtools", config) resources = config_utils.get_resources("novoalign", config) num_cores = config["algorithm"].get("num_cores", 1) max_mem = resources.get("memory", "4G").upper() extra_novo_args = " ".join(_novoalign_args_from_config(config, False)) if not file_exists(out_file): with tx_tmpdir(data, base_dir=align_dir) as work_dir: with postalign.tobam_cl(data, out_file, bam.is_paired(in_bam)) as (tobam_cl, tx_out_file): rg_info = get_rg_info(names) tx_out_prefix = os.path.splitext(tx_out_file)[0] prefix1 = "%s-in1" % tx_out_prefix cmd = ("unset JAVA_HOME && " "{samtools} sort -n -o -l 1 -@ {num_cores} -m {max_mem} {in_bam} {prefix1} " "| {novoalign} -o SAM '{rg_info}' -d {ref_file} -f /dev/stdin " " -F BAMPE -c {num_cores} {extra_novo_args} | ") cmd = (cmd + tobam_cl).format(**locals()) do.run(cmd, "Novoalign: %s" % names["sample"], None, [do.file_nonempty(tx_out_file), do.file_reasonable_size(tx_out_file, in_bam)]) return out_file # ## Fastq to BAM alignment def align_pipe(fastq_file, pair_file, ref_file, names, align_dir, data): """Perform piped alignment of fastq input files, generating sorted output BAM. """ pair_file = pair_file if pair_file else "" # back compatible -- older files were named with lane information, use sample name now out_file = os.path.join(align_dir, "{0}-sort.bam".format(names["lane"])) if not utils.file_exists(out_file): out_file = os.path.join(align_dir, "{0}-sort.bam".format(dd.get_sample_name(data))) if data.get("align_split") or fastq_file.endswith(".sdf"): final_file = out_file out_file, data = alignprep.setup_combine(final_file, data) fastq_file, pair_file = alignprep.split_namedpipe_cls(fastq_file, pair_file, data) else: final_file = None samtools = config_utils.get_program("samtools", data["config"]) novoalign = config_utils.get_program("novoalign", data["config"]) resources = config_utils.get_resources("novoalign", data["config"]) num_cores = data["config"]["algorithm"].get("num_cores", 1) max_mem = resources.get("memory", "1G") extra_novo_args = " ".join(_novoalign_args_from_config(data["config"])) rg_info = get_rg_info(names) if not utils.file_exists(out_file) and (final_file is None or not utils.file_exists(final_file)): with tx_tmpdir(data) as work_dir: with postalign.tobam_cl(data, out_file, pair_file != "") as (tobam_cl, tx_out_file): tx_out_prefix = os.path.splitext(tx_out_file)[0] cmd = ("unset JAVA_HOME && " "{novoalign} -o SAM '{rg_info}' -d {ref_file} -f {fastq_file} {pair_file} " " -c {num_cores} {extra_novo_args} | ") cmd = (cmd + tobam_cl).format(**locals()) do.run(cmd, "Novoalign: %s" % names["sample"], None, [do.file_nonempty(tx_out_file), do.file_reasonable_size(tx_out_file, fastq_file)]) data["work_bam"] = out_file return data def _novoalign_args_from_config(config, need_quality=True): """Select novoalign options based on configuration parameters. """ if need_quality: qual_format = config["algorithm"].get("quality_format", "").lower() qual_flags = ["-F", "ILMFQ" if qual_format == "illumina" else "STDFQ"] else: qual_flags = [] multi_mappers = config["algorithm"].get("multiple_mappers") if multi_mappers is True: multi_flag = "Random" elif isinstance(multi_mappers, six.string_types): multi_flag = multi_mappers else: multi_flag = "None" multi_flags = ["-r"] + multi_flag.split() resources = config_utils.get_resources("novoalign", config) # default arguments for improved variant calling based on # comparisons to reference materials: turn off soft clipping and recalibrate if resources.get("options") is None: extra_args = ["-o", "FullNW", "-k"] else: extra_args = [str(x) for x in resources.get("options", [])] return qual_flags + multi_flags + extra_args # Tweaks to add # -k -t 200 -K quality calibration metrics # paired end sizes # ## Indexing @memoize_outfile(ext=".ndx") def refindex(ref_file, kmer_size=None, step_size=None, out_file=None): cl = ["novoindex"] if kmer_size: cl += ["-k", str(kmer_size)] if step_size: cl += ["-s", str(step_size)] cl += [out_file, ref_file] subprocess.check_call(cl) # ## Galaxy integration # Optional galaxy location file. Falls back on remap_index_fn if not found galaxy_location_file = "novoalign_indices.loc" def remap_index_fn(ref_file): """Map sequence references to equivalent novoalign indexes. """ checks = [os.path.splitext(ref_file)[0].replace("/seq/", "/novoalign/"), os.path.splitext(ref_file)[0] + ".ndx", ref_file + ".bs.ndx", ref_file + ".ndx"] for check in checks: if os.path.exists(check): return check return checks[0] bcbio-nextgen-1.2.9/bcbio/ngsalign/postalign.py000066400000000000000000000400301415626112400215000ustar00rootroot00000000000000"""Perform streaming post-alignment preparation -- de-duplication and sorting. Centralizes a pipelined approach to generating sorted, de-duplicated BAM output from sequencer results. samblaster: http://arxiv.org/pdf/1403.7486v1.pdf biobambam bammarkduplicates: http://arxiv.org/abs/1306.0836 """ import contextlib import math import os import toolz as tz from bcbio import bam, broad, utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.log import logger from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import coverage import six pysam = utils.LazyImport("pysam") @contextlib.contextmanager def tobam_cl(data, out_file, is_paired=False): """Prepare command line for producing de-duplicated sorted output. - If no deduplication, sort and prepare a BAM file. - If paired, then use samblaster and prepare discordant outputs. - If unpaired, use biobambam's bammarkduplicates """ do_dedup = _check_dedup(data) umi_consensus = dd.get_umi_consensus(data) with file_transaction(data, out_file) as tx_out_file: if not do_dedup: yield (sam_to_sortbam_cl(data, tx_out_file), tx_out_file) elif umi_consensus: yield (_sam_to_grouped_umi_cl(data, umi_consensus, tx_out_file), tx_out_file) elif is_paired and _need_sr_disc_reads(data) and not _too_many_contigs(dd.get_ref_file(data)): sr_file = "%s-sr.bam" % os.path.splitext(out_file)[0] disc_file = "%s-disc.bam" % os.path.splitext(out_file)[0] with file_transaction(data, sr_file) as tx_sr_file: with file_transaction(data, disc_file) as tx_disc_file: yield (samblaster_dedup_sort(data, tx_out_file, tx_sr_file, tx_disc_file), tx_out_file) else: yield (_biobambam_dedup_sort(data, tx_out_file), tx_out_file) def _too_many_contigs(ref_file): """Check for more contigs than the maximum samblaster deduplication supports. """ max_contigs = 32768 return len(list(ref.file_contigs(ref_file))) >= max_contigs def _need_sr_disc_reads(data): """Check if we need split and discordant reads in downstream processing. We use samblaster when needed and otherwise use an approach that does not extract these reads to be less resource intensive. """ from bcbio import structural return "lumpy" in structural.get_svcallers(data) def _get_cores_memory(data, downscale=2): """Retrieve cores and memory, using samtools as baseline. For memory, scaling down because we share with alignment and de-duplication. """ resources = config_utils.get_resources("samtools", data["config"]) num_cores = data["config"]["algorithm"].get("num_cores", 1) max_mem = config_utils.adjust_memory(resources.get("memory", "2G"), downscale, "decrease").upper() return num_cores, max_mem def sam_to_sortbam_cl(data, tx_out_file, name_sort=False): """Convert to sorted BAM output. Set name_sort to True to sort reads by queryname """ samtools = config_utils.get_program("samtools", data["config"]) cores, mem = _get_cores_memory(data, downscale=2) tmp_file = "%s-sorttmp" % utils.splitext_plus(tx_out_file)[0] sort_flag = "-n" if name_sort else "" return ("{samtools} sort -@ {cores} -m {mem} {sort_flag} " "-T {tmp_file} -o {tx_out_file} /dev/stdin".format(**locals())) def samblaster_dedup_sort(data, tx_out_file, tx_sr_file, tx_disc_file): """Deduplicate and sort with samblaster, produces split read and discordant pair files. """ samblaster = config_utils.get_program("samblaster", data["config"]) samtools = config_utils.get_program("samtools", data["config"]) tmp_prefix = "%s-sorttmp" % utils.splitext_plus(tx_out_file)[0] tobam_cmd = ("{samtools} sort {sort_opt} -@ {cores} -m {mem} -T {tmp_prefix}-{dext} {out_file} -") # full BAM -- associate more memory and cores cores, mem = _get_cores_memory(data, downscale=2) # Potentially downsample to maximum coverage here if not splitting and whole genome sample ds_cmd = None if data.get("align_split") else bam.get_maxcov_downsample_cl(data, "samtools") sort_opt = "-n" if data.get("align_split") and dd.get_mark_duplicates(data) else "" if ds_cmd: dedup_cmd = "%s %s > %s" % (tobam_cmd.format(out_file="", dext="full", **locals()), ds_cmd, tx_out_file) else: dedup_cmd = tobam_cmd.format(out_file="-o %s" % tx_out_file, dext="full", **locals()) # split and discordant BAMs -- give less memory/cores since smaller files sort_opt = "" cores, mem = _get_cores_memory(data, downscale=4) splitter_cmd = tobam_cmd.format(out_file="-o %s" % tx_sr_file, dext="spl", **locals()) discordant_cmd = tobam_cmd.format(out_file="-o %s" % tx_disc_file, dext="disc", **locals()) # samblaster 0.1.22 and better require the -M flag for compatibility with bwa-mem cmd = ("{samblaster} --addMateTags -M --splitterFile >({splitter_cmd}) --discordantFile >({discordant_cmd}) " "| {dedup_cmd}") return cmd.format(**locals()) def _biobambam_dedup_sort(data, tx_out_file): """Perform streaming deduplication and sorting with biobambam's bamsormadup """ samtools = config_utils.get_program("samtools", data["config"]) cores, mem = _get_cores_memory(data, downscale=2) tmp_file = "%s-sorttmp" % utils.splitext_plus(tx_out_file)[0] if data.get("align_split"): sort_opt = "-n" if data.get("align_split") and _check_dedup(data) else "" cmd = "{samtools} sort %s -@ {cores} -m {mem} -O bam -T {tmp_file}-namesort -o {tx_out_file} -" % sort_opt else: # scale core usage to avoid memory issues with larger WGS samples cores = max(1, int(math.ceil(cores * 0.75))) ds_cmd = bam.get_maxcov_downsample_cl(data, "bamsormadup") bamsormadup = config_utils.get_program("bamsormadup", data) cmd = ("{bamsormadup} inputformat=sam threads={cores} tmpfile={tmp_file}-markdup " "SO=coordinate %s > {tx_out_file}" % ds_cmd) return cmd.format(**locals()) def _sam_to_grouped_umi_cl(data, umi_consensus, tx_out_file): """Mark duplicates on aligner output and convert to grouped UMIs by position. Works with either a separate umi_file or UMI embedded in the read names. """ tmp_file = "%s-sorttmp" % utils.splitext_plus(tx_out_file)[0] jvm_opts = _get_fgbio_jvm_opts(data, os.path.dirname(tmp_file), 1) cores, mem = _get_cores_memory(data) bamsormadup = config_utils.get_program("bamsormadup", data) cmd = ("{bamsormadup} tmpfile={tmp_file}-markdup inputformat=sam threads={cores} outputformat=bam " "level=0 SO=coordinate | ") # UMIs in a separate file if os.path.exists(umi_consensus) and os.path.isfile(umi_consensus): cmd += "fgbio {jvm_opts} AnnotateBamWithUmis -i /dev/stdin -f {umi_consensus} -o {tx_out_file}" # UMIs embedded in read name else: cmd += ("%s %s bamtag - | samtools view -b > {tx_out_file}" % (utils.get_program_python("umis"), config_utils.get_program("umis", data["config"]))) return cmd.format(**locals()) def _get_fgbio_jvm_opts(data, tmpdir, scale_factor=None): cores, mem = _get_cores_memory(data) resources = config_utils.get_resources("fgbio", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx4g"]) if scale_factor and cores > scale_factor: jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": {"direction": "increase", "magnitude": cores // scale_factor}}}) jvm_opts += broad.get_default_jvm_opts() jvm_opts = " ".join(jvm_opts) return jvm_opts + " --tmp-dir %s" % tmpdir def _estimate_fgbio_defaults(avg_coverage): """Provide fgbio defaults based on input sequence depth and coverage. For higher depth/duplication we want to use `--min-reads` to allow consensus calling in the duplicates: https://fulcrumgenomics.github.io/fgbio/tools/latest/CallMolecularConsensusReads.html If duplicated adjusted depth leaves a coverage of 800x or higher (giving us ~4 reads at 0.5% detection frequency), then we use `--min-reads 2`, otherwise `--min-reads 1` """ out = {} if avg_coverage >= 800: out["--min-reads"] = 2 else: out["--min-reads"] = 1 return out def correct_umis(data): """Correct umis against the whitelist in correct_umi_file http://fulcrumgenomics.github.io/fgbio/tools/latest/CorrectUmis.html """ input_bam = dd.get_work_bam(data) output_bam = os.path.join(utils.safe_makedir(os.path.join(os.getcwd(), "align", dd.get_sample_name(data))), "%s-umis_corrected%s" % utils.splitext_plus(os.path.basename(input_bam))) jvm_opts = _get_fgbio_jvm_opts(data, os.path.dirname(output_bam), 2) # Improve speeds by avoiding compression read/write bottlenecks io_opts = "--async-io=true --compression=0" umis_whitelist = tz.get_in(["config", "algorithm", "correct_umis"], data) fgbio = config_utils.get_program("fgbio", data["config"]) samtools = config_utils.get_program("samtools", data["config"]) if not utils.file_exists(output_bam): umi_method, umi_tag = _check_umi_type(input_bam) cmd = ("unset JAVA_HOME && " "{fgbio} {jvm_opts} {io_opts} CorrectUmis " "-t {umi_tag} -m 3 -d 1 -x " "-U {umis_whitelist} " "-i {input_bam} -o /dev/stdout | {samtools} view -bh > {output_bam}") do.run(cmd.format(**locals()), "Correcting UMIs") bam.index(output_bam, data["config"]) return output_bam def umi_consensus(data): """Convert UMI grouped reads into fastq pair for re-alignment. """ align_bam = dd.get_work_bam(data) if dd.get_umi_type(data) == "dragen": umi_method = "adjacency" umi_tag = "RX" else: umi_method, umi_tag = _check_umi_type(align_bam) base_name = utils.splitext_plus(align_bam)[0] f1_out = f"{base_name}-cumi-1.fq.gz" f2_out = f"{base_name}-cumi-2.fq.gz" f_family_size_histogram = f"{base_name}.family_size_histogram.tsv" avg_coverage = coverage.get_average_coverage("rawumi", dd.get_variant_regions(data), data) fgbio = config_utils.get_program("fgbio", data["config"]) bamtofastq = config_utils.get_program("bamtofastq", data["config"]) if not utils.file_uptodate(f1_out, align_bam): with file_transaction(data, f1_out, f2_out, f_family_size_histogram) as (tx_f1_out, tx_f2_out, tx_fhist_out): jvm_opts = _get_fgbio_jvm_opts(data, os.path.dirname(tx_f1_out), 2) # Improve speeds by avoiding compression read/write bottlenecks io_opts = "--async-io=true --compression=0" est_options = _estimate_fgbio_defaults(avg_coverage) group_opts, cons_opts, filter_opts = _get_fgbio_options(data, est_options, umi_method) cons_method = "CallDuplexConsensusReads" if umi_method == "paired" else "CallMolecularConsensusReads" tempfile = "%s-bamtofastq-tmp" % utils.splitext_plus(f1_out)[0] ref_file = dd.get_ref_file(data) cmd = ("unset JAVA_HOME && " "{fgbio} {jvm_opts} {io_opts} GroupReadsByUmi {group_opts} -t {umi_tag} -s {umi_method} " "-i {align_bam} -f {tx_fhist_out} | " "{fgbio} {jvm_opts} {io_opts} {cons_method} {cons_opts} --sort-order=:none: " "-i /dev/stdin -o /dev/stdout | " "{fgbio} {jvm_opts} {io_opts} FilterConsensusReads {filter_opts} -r {ref_file} " "-i /dev/stdin -o /dev/stdout | " "{bamtofastq} collate=1 T={tempfile} F={tx_f1_out} F2={tx_f2_out} tags=cD,cM,cE gz=1") do.run(cmd.format(**locals()), "UMI consensus fastq generation") return f1_out, f2_out, avg_coverage def _check_umi_type(bam_file): """Determine the type of UMI from BAM tags: standard or paired. """ with pysam.Samfile(bam_file, "rb") as in_bam: for read in in_bam: cur_umi = None for tag in ["RX", "XC"]: try: cur_umi = read.get_tag(tag) break except KeyError: pass if cur_umi: if "-" in cur_umi and len(cur_umi.split("-")) == 2: return "paired", tag else: return "adjacency", tag def _get_fgbio_options(data, estimated_defaults, umi_method): """Get adjustable, through resources, or default options for fgbio. """ group_opts = ["--edits", "--min-map-q"] cons_opts = ["--min-input-base-quality"] if umi_method != "paired": cons_opts += ["--min-reads", "--max-reads"] filter_opts = ["--min-reads", "--min-base-quality", "--max-base-error-rate"] defaults = {"--min-reads": "1", "--max-reads": "100000", "--min-map-q": "1", "--min-base-quality": "13", "--max-base-error-rate": "0.1", "--min-input-base-quality": "2", "--edits": "1"} defaults.update(estimated_defaults) ropts = config_utils.get_resources("fgbio", data["config"]).get("options", []) assert len(ropts) % 2 == 0, "Expect even number of options for fgbio" % ropts ropts = dict(tz.partition(2, ropts)) # Back compatibility for older base quality settings if "--min-consensus-base-quality" in ropts: ropts["--min-base-quality"] = ropts.pop("--min-consensus-base-quality") defaults.update(ropts) group_out = " ".join(["%s=%s" % (x, defaults[x]) for x in group_opts]) cons_out = " ".join(["%s=%s" % (x, defaults[x]) for x in cons_opts]) filter_out = " ".join(["%s=%s" % (x, defaults[x]) for x in filter_opts]) if umi_method != "paired": cons_out += " --output-per-base-tags=false" return group_out, cons_out, filter_out def _check_dedup(data): """Check configuration for de-duplication. Defaults to no de-duplication for RNA-seq and small RNA, the back compatible default. Allow overwriting with explicit `mark_duplicates: true` setting. Also defaults to false for no alignment inputs. """ if dd.get_analysis(data).lower() in ["rna-seq", "smallrna-seq"] or not dd.get_aligner(data): dup_param = utils.get_in(data, ("config", "algorithm", "mark_duplicates"), False) else: dup_param = utils.get_in(data, ("config", "algorithm", "mark_duplicates"), True) if dup_param and isinstance(dup_param, six.string_types): logger.info("Warning: bcbio no longer support explicit setting of mark_duplicate algorithm. " "Using best-practice choice based on input data.") dup_param = True return dup_param def dedup_bam(in_bam, data): """Perform non-stream based duplicate marking of BAM input files using biobambam. """ if _check_dedup(data): out_file = os.path.join(utils.safe_makedir(os.path.join(os.getcwd(), "align", dd.get_sample_name(data))), "%s-dedup%s" % utils.splitext_plus(os.path.basename(in_bam))) if not utils.file_exists(out_file): with tx_tmpdir(data) as tmpdir: with file_transaction(data, out_file) as tx_out_file: bammarkduplicates = config_utils.get_program("bammarkduplicates", data["config"]) base_tmp = os.path.join(tmpdir, os.path.splitext(os.path.basename(tx_out_file))[0]) cores, mem = _get_cores_memory(data, downscale=2) cmd = ("{bammarkduplicates} tmpfile={base_tmp}-markdup " "markthreads={cores} I={in_bam} O={tx_out_file}") do.run(cmd.format(**locals()), f"Mark duplication of {in_bam} with biobambam.") bam.index(out_file, data["config"]) return out_file else: return in_bam bcbio-nextgen-1.2.9/bcbio/ngsalign/rtg.py000066400000000000000000000070361415626112400203050ustar00rootroot00000000000000"""Provide indexing and retrieval of files using Real Time Genomics SDF format. Prepares a sdf representation of reads suitable for indexed retrieval, normalizing many different input types. https://github.com/RealTimeGenomics/rtg-tools """ import os import subprocess from bcbio import bam, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do def to_sdf(files, data): """Convert a fastq or BAM input into a SDF indexed file. """ # BAM if len(files) == 1 and files[0].endswith(".bam"): qual = [] format = ["-f", "sam-pe" if bam.is_paired(files[0]) else "sam-se"] inputs = [files[0]] # fastq else: qual = ["-q", "illumina" if dd.get_quality_format(data).lower() == "illumina" else "sanger"] format = ["-f", "fastq"] if len(files) == 2: inputs = ["-l", files[0], "-r", files[1]] else: assert len(files) == 1 inputs = [files[0]] work_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "align_prep")) out_file = os.path.join(work_dir, "%s.sdf" % utils.splitext_plus(os.path.basename(os.path.commonprefix(files)))[0]) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = _rtg_cmd(["rtg", "format", "-o", tx_out_file] + format + qual + inputs) do.run(cmd, "Format inputs to indexed SDF") return out_file def _rtg_cmd(cmd): return "export RTG_JAVA_OPTS='-Xms500m' && export RTG_MEM=2g && " + " ".join(cmd) def calculate_splits(sdf_file, split_size): """Retrieve """ counts = _sdfstats(sdf_file)["counts"] splits = [] cur = 0 for i in range(counts // split_size + (0 if counts % split_size == 0 else 1)): splits.append("%s-%s" % (cur, min(counts, cur + split_size))) cur += split_size return splits def _sdfstats(sdf_file): cmd = ["rtg", "sdfstats", sdf_file] pairs = [] counts = [] lengths = [] for line in subprocess.check_output(_rtg_cmd(cmd), shell=True).split("\n"): if line.startswith("Paired arm"): pairs.append(line.strip().split()[-1]) elif line.startswith("Number of sequences"): counts.append(int(line.strip().split()[-1])) elif line.startswith("Minimum length"): lengths.append(int(line.strip().split()[-1])) assert len(set(counts)) == 1, counts return {"counts": counts[0], "pairs": pairs, "min_size": min(lengths)} def min_read_size(sdf_file): """Retrieve minimum read size from SDF statistics. """ return _sdfstats(sdf_file)["min_size"] def is_paired(sdf_file): """Check if we have paired inputs in a SDF file. """ pairs = _sdfstats(sdf_file)["pairs"] return len(set(pairs)) > 1 def to_fastq_apipe_cl(sdf_file, start=None, end=None): """Return a command lines to provide streaming fastq input. For paired end, returns a forward and reverse command line. For single end returns a single command line and None for the pair. """ cmd = ["rtg", "sdf2fastq", "--no-gzip", "-o", "-"] if start is not None: cmd += ["--start-id=%s" % start] if end is not None: cmd += ["--end-id=%s" % end] if is_paired(sdf_file): out = [] for ext in ["left", "right"]: out.append("<(%s)" % _rtg_cmd(cmd + ["-i", os.path.join(sdf_file, ext)])) return out else: cmd += ["-i", sdf_file] return ["<(%s)" % _rtg_cmd(cmd), None]bcbio-nextgen-1.2.9/bcbio/ngsalign/snap.py000066400000000000000000000102071415626112400204440ustar00rootroot00000000000000"""Alignment with SNAP: http://snap.cs.berkeley.edu/ """ import os from bcbio import utils from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.ngsalign import alignprep, novoalign, postalign from bcbio.provenance import do def align(fastq_file, pair_file, index_dir, names, align_dir, data): """Perform piped alignment of fastq input files, generating sorted, deduplicated BAM. Pipes in input, handling paired and split inputs, using interleaving magic from: https://biowize.wordpress.com/2015/03/26/the-fastest-darn-fastq-decoupling-procedure-i-ever-done-seen/ Then converts a tab delimited set of outputs into interleaved fastq. awk changes spaces to underscores since SNAP only takes the initial name. SNAP requires /1 and /2 at the end of read names. If these are not present in the initial fastq may need to expand awk code to do this. """ out_file = os.path.join(align_dir, "{0}-sort.bam".format(dd.get_sample_name(data))) num_cores = data["config"]["algorithm"].get("num_cores", 1) resources = config_utils.get_resources("snap", data["config"]) rg_info = novoalign.get_rg_info(names) if data.get("align_split"): final_file = out_file out_file, data = alignprep.setup_combine(final_file, data) fastq_file, pair_file = alignprep.split_namedpipe_cls(fastq_file, pair_file, data) fastq_file = fastq_file[2:-1] if pair_file: pair_file = pair_file[2:-1] stream_input = (r"paste <({fastq_file} | paste - - - -) " r"<({pair_file} | paste - - - -) | " r"""awk 'BEGIN {{FS="\t"; OFS="\n"}} """ r"""{{ """ r"""split($1, P1, " "); split($5, P5, " "); """ r"""if ($1 !~ /\/1$/) $1 = P1[1]"/1"; if ($5 !~ /\/2$/) $5 = P5[1]"/2"; """ r"""gsub(" ", "_", $1); gsub(" ", "_", $5); """ r"""print $1, $2, "+", $4, $5, $6, "+", $8}}' """) else: stream_input = fastq_file[2:-1] else: final_file = None assert fastq_file.endswith(".gz") if pair_file: stream_input = (r"paste <(zcat {fastq_file} | paste - - - -) " r"<(zcat {pair_file} | paste - - - -) | " r"""awk 'BEGIN {{FS="\t"; OFS="\n"}} """ r"""{{ """ r"""split($1, P1, " "); split($5, P5, " "); """ r"""if ($1 !~ /\/1$/) $1 = P1[1]"/1"; if ($5 !~ /\/2$/) $5 = P5[1]"/2"; """ r"""gsub(" ", "_", $1); gsub(" ", "_", $5); """ r"""print $1, $2, "+", $4, $5, $6, "+", $8}}' """) else: stream_input = "zcat {fastq_file}" pair_file = pair_file if pair_file else "" if not utils.file_exists(out_file) and (final_file is None or not utils.file_exists(final_file)): with postalign.tobam_cl(data, out_file, pair_file is not None) as (tobam_cl, tx_out_file): if pair_file: sub_cmd = "paired" input_cmd = "-pairedInterleavedFastq -" else: sub_cmd = "single" input_cmd = "-fastq -" stream_input = stream_input.format(**locals()) tmp_dir = os.path.dirname(tx_out_file) cmd = ("export TMPDIR={tmp_dir} && unset JAVA_HOME && {stream_input} | " "snap-aligner {sub_cmd} {index_dir} {input_cmd} " "-R '{rg_info}' -t {num_cores} -M -o -sam - | ") do.run(cmd.format(**locals()) + tobam_cl, "SNAP alignment: %s" % names["sample"]) data["work_bam"] = out_file return data # Optional galaxy location file. Falls back on remap_index_fn if not found galaxy_location_file = "snap_indices.loc" def remap_index_fn(ref_file): """Map sequence references to snap reference directory, using standard layout. """ snap_dir = os.path.join(os.path.dirname(ref_file), os.pardir, "snap") assert os.path.exists(snap_dir) and os.path.isdir(snap_dir), snap_dir return snap_dir bcbio-nextgen-1.2.9/bcbio/ngsalign/star.py000066400000000000000000000343761415626112400204710ustar00rootroot00000000000000import os import sys import shutil import subprocess import contextlib from collections import namedtuple import bcbio.bed as bed from bcbio.pipeline import config_utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.utils import (safe_makedir, file_exists, is_gzipped) from bcbio.provenance import do from bcbio import utils from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.ngsalign import postalign from bcbio.bam import fastq from bcbio.heterogeneity import chromhacks CLEANUP_FILES = ["Aligned.out.sam", "Log.out", "Log.progress.out"] ALIGN_TAGS = ["NH", "HI", "NM", "MD", "AS"] def align(fastq_file, pair_file, ref_file, names, align_dir, data): if not ref_file: logger.error("STAR index not found. We don't provide the STAR indexes " "by default because they are very large. You can install " "the index for your genome with: bcbio_nextgen.py upgrade " "--aligners star --genomes genome-build-name --data") sys.exit(1) max_hits = 10 srna = True if data["analysis"].lower().startswith("smallrna-seq") else False srna_opts = "" if srna: max_hits = 1000 srna_opts = "--alignIntronMax 1" config = data["config"] star_dirs = _get_star_dirnames(align_dir, data, names) if file_exists(star_dirs.final_out): data = _update_data(star_dirs.final_out, star_dirs.out_dir, names, data) out_log_file = os.path.join(align_dir, dd.get_lane(data) + "Log.final.out") data = dd.update_summary_qc(data, "star", base=out_log_file) return data star_path = config_utils.get_program("STAR", config) def _unpack_fastq(f): """Use process substitution instead of readFilesCommand for gzipped inputs. Prevents issues on shared filesystems that don't support FIFO: https://github.com/alexdobin/STAR/issues/143 """ if f and is_gzipped(f): return "<(gunzip -c %s)" % f else: return f fastq_files = (" ".join([_unpack_fastq(fastq_file), _unpack_fastq(pair_file)]) if pair_file else _unpack_fastq(fastq_file)) num_cores = dd.get_num_cores(data) gtf_file = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) if ref_file.endswith("chrLength"): ref_file = os.path.dirname(ref_file) if index_has_alts(ref_file): logger.error( "STAR is being run on an index with ALTs which STAR is not " "designed for. Please remake your STAR index or use an ALT-aware " "aligner like hisat2") sys.exit(1) with file_transaction(data, align_dir) as tx_align_dir: tx_1pass_dir = tx_align_dir + "1pass" tx_star_dirnames = _get_star_dirnames(tx_1pass_dir, data, names) tx_out_dir, tx_out_file, tx_out_prefix, tx_final_out = tx_star_dirnames safe_makedir(tx_1pass_dir) safe_makedir(tx_out_dir) cmd = ("{star_path} --genomeDir {ref_file} --readFilesIn {fastq_files} " "--runThreadN {num_cores} --outFileNamePrefix {tx_out_prefix} " "--outReadsUnmapped Fastx --outFilterMultimapNmax {max_hits} " "--outStd BAM_Unsorted {srna_opts} " "--limitOutSJcollapsed 2000000 " "--outSAMtype BAM Unsorted " "--outSAMmapqUnique 60 " "--outSAMunmapped Within --outSAMattributes %s " % " ".join(ALIGN_TAGS)) cmd += _add_sj_index_commands(fastq_file, ref_file, gtf_file) if not srna else "" cmd += _read_group_option(names) if dd.get_fusion_caller(data): if "arriba" in dd.get_fusion_caller(data): cmd += ( "--chimSegmentMin 10 --chimOutType WithinBAM " "--chimJunctionOverhangMin 10 --chimScoreMin 1 --chimScoreDropMax 30 " "--chimScoreJunctionNonGTAG 0 --chimScoreSeparation 1 " "--alignSJstitchMismatchNmax 5 -1 5 5 " "--chimSegmentReadGapMax 3 " "--peOverlapNbasesMin 10 " "--alignSplicedMateMapLminOverLmate 0.5 ") else: cmd += (" --chimSegmentMin 12 --chimJunctionOverhangMin 12 " "--chimScoreDropMax 30 --chimSegmentReadGapMax 5 " "--chimScoreSeparation 5 ") if "oncofuse" in dd.get_fusion_caller(data): cmd += "--chimOutType Junctions " else: cmd += "--chimOutType WithinBAM " strandedness = utils.get_in(data, ("config", "algorithm", "strandedness"), "unstranded").lower() if strandedness == "unstranded" and not srna: cmd += " --outSAMstrandField intronMotif " if not srna: cmd += " --quantMode TranscriptomeSAM " resources = config_utils.get_resources("star", data["config"]) if resources.get("options", []): cmd += " " + " ".join([str(x) for x in resources.get("options", [])]) cmd += " | " + postalign.sam_to_sortbam_cl(data, tx_final_out) cmd += " > {tx_final_out} " run_message = "Running 1st pass of STAR aligner on %s and %s" % (fastq_file, ref_file) do.run(cmd.format(**locals()), run_message, None) sjfile = get_splicejunction_file(tx_out_dir, data) sjflag = f"--sjdbFileChrStartEnd {sjfile}" if sjfile else "" tx_star_dirnames = _get_star_dirnames(tx_align_dir, data, names) tx_out_dir, tx_out_file, tx_out_prefix, tx_final_out = tx_star_dirnames safe_makedir(tx_align_dir) safe_makedir(tx_out_dir) cmd = ("{star_path} --genomeDir {ref_file} --readFilesIn {fastq_files} " "--runThreadN {num_cores} --outFileNamePrefix {tx_out_prefix} " "--outReadsUnmapped Fastx --outFilterMultimapNmax {max_hits} " "--outStd BAM_Unsorted {srna_opts} " "--limitOutSJcollapsed 2000000 " "{sjflag} " "--outSAMtype BAM Unsorted " "--outSAMmapqUnique 60 " "--outSAMunmapped Within --outSAMattributes %s " % " ".join(ALIGN_TAGS)) cmd += _add_sj_index_commands(fastq_file, ref_file, gtf_file) if not srna else "" cmd += _read_group_option(names) if dd.get_fusion_caller(data): if "arriba" in dd.get_fusion_caller(data): cmd += ( "--chimSegmentMin 10 --chimOutType WithinBAM SoftClip Junctions " "--chimJunctionOverhangMin 10 --chimScoreMin 1 --chimScoreDropMax 30 " "--chimScoreJunctionNonGTAG 0 --chimScoreSeparation 1 " "--alignSJstitchMismatchNmax 5 -1 5 5 " "--chimSegmentReadGapMax 3 ") else: cmd += (" --chimSegmentMin 12 --chimJunctionOverhangMin 12 " "--chimScoreDropMax 30 --chimSegmentReadGapMax 5 " "--chimScoreSeparation 5 ") if "oncofuse" in dd.get_fusion_caller(data): cmd += "--chimOutType Junctions " else: cmd += "--chimOutType WithinBAM " strandedness = utils.get_in(data, ("config", "algorithm", "strandedness"), "unstranded").lower() if strandedness == "unstranded" and not srna: cmd += " --outSAMstrandField intronMotif " if not srna: cmd += " --quantMode TranscriptomeSAM " resources = config_utils.get_resources("star", data["config"]) if resources.get("options", []): cmd += " " + " ".join([str(x) for x in resources.get("options", [])]) cmd += " | " + postalign.sam_to_sortbam_cl(data, tx_final_out) cmd += " > {tx_final_out} " run_message = "Running 2nd pass of STAR aligner on %s and %s" % (fastq_file, ref_file) do.run(cmd.format(**locals()), run_message, None) data = _update_data(star_dirs.final_out, star_dirs.out_dir, names, data) out_log_file = os.path.join(align_dir, dd.get_lane(data) + "Log.final.out") data = dd.update_summary_qc(data, "star", base=out_log_file) return data StarOutDirs = namedtuple( 'StarOutDirs', ['out_dir', 'out_file', 'out_prefix', 'final_out'] ) def _get_star_dirnames(align_dir, data, names): ALIGNED_OUT_FILE = "Aligned.out.sam" out_prefix = os.path.join(align_dir, dd.get_lane(data)) out_file = out_prefix + ALIGNED_OUT_FILE out_dir = os.path.join(align_dir, "%s_star" % dd.get_lane(data)) final_out = os.path.join(out_dir, "{0}.bam".format(names["sample"])) return StarOutDirs(out_dir, out_file, out_prefix, final_out) def _add_sj_index_commands(fq1, ref_file, gtf_file): """ newer versions of STAR can generate splice junction databases on thephfly this is preferable since we can tailor it to the read lengths """ if _has_sj_index(ref_file): return "" else: rlength = fastq.estimate_maximum_read_length(fq1) cmd = " --sjdbGTFfile %s " % gtf_file cmd += " --sjdbOverhang %s " % str(rlength - 1) return cmd def _has_sj_index(ref_file): """this file won't exist if we can do on the fly splice junction indexing""" return (file_exists(os.path.join(ref_file, "sjdbInfo.txt")) and (file_exists(os.path.join(ref_file, "transcriptInfo.tab")))) def _update_data(align_file, out_dir, names, data): data = dd.set_work_bam(data, align_file) data = dd.set_align_bam(data, align_file) transcriptome_file = _move_transcriptome_file(out_dir, names) data = dd.set_transcriptome_bam(data, transcriptome_file) sjfile = get_splicejunction_file(out_dir, data) if sjfile: data = dd.set_starjunction(data, sjfile) sjbed = junction2bed(sjfile) data = dd.set_junction_bed(data, sjbed) sjchimfile = get_chimericjunction_file(out_dir, data) data = dd.set_chimericjunction(data, sjchimfile) return data def _move_transcriptome_file(out_dir, names): out_file = os.path.join(out_dir, "{0}.transcriptome.bam".format(names["sample"])) star_file = os.path.join(out_dir, os.pardir, "{0}Aligned.toTranscriptome.out.bam".format(names["lane"])) # if the out_file or the star_file doesn't exist, we didn't run the # transcriptome mapping if not file_exists(out_file): if not file_exists(star_file): return None else: shutil.move(star_file, out_file) return out_file def _read_group_option(names): rg_id = names["rg"] rg_sample = names["sample"] rg_library = names["pl"] rg_platform_unit = names["pu"] rg_lb = ("LB:%s " % names.get("lb")) if names.get("lb") else "" return (" --outSAMattrRGline ID:{rg_id} PL:{rg_library} " "PU:{rg_platform_unit} SM:{rg_sample} {rg_lb}").format(**locals()) def remap_index_fn(ref_file): """Map sequence references to equivalent star indexes """ return os.path.join(os.path.dirname(os.path.dirname(ref_file)), "star") def index(ref_file, out_dir, data): """Create a STAR index in the defined reference directory. """ (ref_dir, local_file) = os.path.split(ref_file) gtf_file = dd.get_transcriptome_gtf(data, dd.get_gtf_file(data)) if not utils.file_exists(gtf_file): raise ValueError("%s not found, could not create a star index." % (gtf_file)) if not utils.file_exists(out_dir): with tx_tmpdir(data, os.path.dirname(out_dir)) as tx_out_dir: num_cores = dd.get_cores(data) cmd = ("STAR --genomeDir {tx_out_dir} --genomeFastaFiles {ref_file} " "--runThreadN {num_cores} " "--runMode genomeGenerate --sjdbOverhang 99 --sjdbGTFfile {gtf_file}") do.run(cmd.format(**locals()), "Index STAR") if os.path.exists(out_dir): shutil.rmtree(out_dir) shutil.move(tx_out_dir, out_dir) return out_dir def get_star_version(data): star_path = config_utils.get_program("STAR", dd.get_config(data)) cmd = "%s --version" % star_path subp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) with contextlib.closing(subp.stdout) as stdout: for line in stdout: if "STAR_" in line: version = line.split("STAR_")[1].strip() return version def get_chimericjunction_file(out_dir, data): """ locate the chimeric splice junction file starting from the alignment directory """ samplename = dd.get_sample_name(data) sjfile = os.path.join(out_dir, os.pardir, f"{samplename}Chimeric.out.junction") if file_exists(sjfile): return sjfile else: return None def get_splicejunction_file(out_dir, data): """ locate the splicejunction file starting from the alignment directory """ samplename = dd.get_sample_name(data) sjfile = os.path.join(out_dir, os.pardir, f"{samplename}SJ.out.tab") if file_exists(sjfile): return sjfile else: return None def junction2bed(junction_file): """ reformat the STAR junction file to BED3 format, one end of the splice junction per line """ base, _ = os.path.splitext(junction_file) out_file = base + "-minimized.bed" if file_exists(out_file): return out_file if not file_exists(junction_file): return None with file_transaction(out_file) as tx_out_file: with open(junction_file) as in_handle: with open(tx_out_file, "w") as out_handle: for line in in_handle: tokens = line.split() chrom, sj1, sj2 = tokens[0:3] if int(sj1) > int(sj2): tmp = sj1 sj1 = sj2 sj2 = tmp out_handle.write("\t".join([chrom, sj1, sj1]) + "\n") out_handle.write("\t".join([chrom, sj2, sj2]) + "\n") minimize = bed.minimize(tx_out_file) minimize.saveas(tx_out_file) return out_file def index_has_alts(ref_file): name_file = os.path.join(os.path.dirname(ref_file), "chrName.txt") with open(name_file) as in_handle: names = [x.strip() for x in in_handle.readlines()] has_alts = [chromhacks.is_alt(chrom) for chrom in names] return any(has_alts) bcbio-nextgen-1.2.9/bcbio/ngsalign/tophat.py000066400000000000000000000336421415626112400210120ustar00rootroot00000000000000"""Next-gen alignments with TopHat a spliced read mapper for RNA-seq experiments. http://tophat.cbcb.umd.edu """ import os import shutil import glob import subprocess import numpy import pysam from bcbio.pipeline import config_utils from bcbio.ngsalign import bowtie, bowtie2 from bcbio.utils import safe_makedir, file_exists, get_in, symlink_plus from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio import bam, broad, utils import bcbio.pipeline.datadict as dd def _set_quality_flag(options, data): qual_format = dd.get_quality_format(data) if qual_format.lower() == "illumina": options["solexa1.3-quals"] = True elif qual_format.lower() == "solexa": options["solexa-quals"] = True return options def _set_transcriptome_option(options, data, ref_file): # prefer transcriptome-index vs a GTF file if available transcriptome_index = get_in(data, ("genome_resources", "rnaseq", "transcriptome_index", "tophat")) fusion_mode = _should_run_fusion(data) if transcriptome_index and file_exists(transcriptome_index) and not fusion_mode: options["transcriptome-index"] = os.path.splitext(transcriptome_index)[0] return options gtf_file = dd.get_gtf_file(data) if gtf_file: options["GTF"] = gtf_file return options return options def _set_cores(options, config): num_cores = config["algorithm"].get("num_cores", 0) if num_cores > 1 and "num-threads" not in options: options["num-threads"] = num_cores return options def _set_rg_options(options, names): if not names: return options options["rg-id"] = names["rg"] options["rg-sample"] = names["sample"] options["rg-library"] = names["lb"] or names["pl"] options["rg-platform-unit"] = names["pu"] return options def _set_stranded_flag(options, config): strand_flag = {"unstranded": "fr-unstranded", "firststrand": "fr-firststrand", "secondstrand": "fr-secondstrand", "auto": "fr-unstranded"} stranded = get_in(config, ("algorithm", "strandedness"), "unstranded").lower() assert stranded in strand_flag, ("%s is not a valid strandedness value. " "Valid values are 'firststrand', " "'secondstrand' and 'unstranded" % (stranded)) flag = strand_flag[stranded] options["library-type"] = flag return options def _set_fusion_mode(options, data): if _should_run_fusion(data): options["fusion-search"] = True return options def tophat_align(fastq_file, pair_file, ref_file, out_base, align_dir, data, names=None): """ run alignment using Tophat v2 """ config = data["config"] options = get_in(config, ("resources", "tophat", "options"), {}) options = _set_fusion_mode(options, data) options = _set_quality_flag(options, data) options = _set_transcriptome_option(options, data, ref_file) options = _set_cores(options, config) options = _set_rg_options(options, names) options = _set_stranded_flag(options, config) ref_file, runner = _determine_aligner_and_reference(ref_file, data) # fusion search does not work properly with Bowtie2 if options.get("fusion-search", False): ref_file = ref_file.replace("/bowtie2", "/bowtie") if _tophat_major_version(config) == 1: raise NotImplementedError("Tophat versions < 2.0 are not supported, please " "download the newest version of Tophat here: " "http://tophat.cbcb.umd.edu") if _ref_version(ref_file) == 1 or options.get("fusion-search", False): options["bowtie1"] = True out_dir = os.path.join(align_dir, "%s_tophat" % out_base) final_out = os.path.join(out_dir, "{0}.bam".format(names["sample"])) if file_exists(final_out): return final_out out_file = os.path.join(out_dir, "accepted_hits.bam") unmapped = os.path.join(out_dir, "unmapped.bam") files = [ref_file, fastq_file] if not file_exists(out_file): with file_transaction(config, out_dir) as tx_out_dir: safe_makedir(tx_out_dir) if pair_file and not options.get("mate-inner-dist", None): d, d_stdev = _estimate_paired_innerdist(fastq_file, pair_file, ref_file, out_base, tx_out_dir, data) options["mate-inner-dist"] = d options["mate-std-dev"] = d_stdev files.append(pair_file) options["output-dir"] = tx_out_dir options["no-coverage-search"] = True options["no-mixed"] = True cmd = [utils.get_program_python("tophat"), config_utils.get_program("tophat", config)] for k, v in options.items(): if v is True: cmd.append("--%s" % k) else: assert not isinstance(v, bool) cmd.append("--%s=%s" % (k, v)) # tophat requires options before arguments, otherwise it silently ignores them cmd += files do.run(cmd, "Running Tophat on %s and %s." % (fastq_file, pair_file)) if pair_file and _has_alignments(out_file): fixed = _fix_mates(out_file, os.path.join(out_dir, "%s-align.bam" % out_base), ref_file, config) else: fixed = out_file fixed_unmapped = _fix_unmapped(fixed, unmapped, data) fixed = merge_unmapped(fixed, fixed_unmapped, config) fixed = _add_rg(fixed, config, names) fixed = bam.sort(fixed, config) picard = broad.runner_from_path("picard", config) # set the contig order to match the reference file so GATK works fixed = picard.run_fn("picard_reorder", fixed, data["sam_ref"], os.path.splitext(fixed)[0] + ".picard.bam") fixed = fix_insert_size(fixed, config) if not file_exists(final_out): symlink_plus(fixed, final_out) return final_out def merge_unmapped(bam_file, unmapped_bam, config): merged_bam = os.path.join(os.path.dirname(bam_file), "merged.bam") if not file_exists(merged_bam): merged_bam = bam.merge([bam_file, unmapped_bam], merged_bam, config) return merged_bam def _has_alignments(sam_file): with open(sam_file) as in_handle: try: for line in in_handle: if line.startswith("File removed to save disk space"): return False elif not line.startswith("@"): return True except UnicodeDecodeError: return not bam.is_empty(sam_file) return False def _fix_mates(orig_file, out_file, ref_file, config): """Fix problematic unmapped mate pairs in TopHat output. TopHat 2.0.9 appears to have issues with secondary reads: https://groups.google.com/forum/#!topic/tuxedo-tools-users/puLfDNbN9bo This cleans the input file to only keep properly mapped pairs, providing a general fix that will handle correctly mapped secondary reads as well. """ if not file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: samtools = config_utils.get_program("samtools", config) cmd = "{samtools} view -bS -h -t {ref_file}.fai -F 8 {orig_file} > {tx_out_file}" do.run(cmd.format(**locals()), "Fix mate pairs in TopHat output", {}) return out_file def _add_rg(unmapped_file, config, names): """Add the missing RG header.""" picard = broad.runner_from_path("picard", config) rg_fixed = picard.run_fn("picard_fix_rgs", unmapped_file, names) return rg_fixed def _fix_unmapped(mapped_file, unmapped_file, data): """ The unmapped.bam file up until at least Tophat 2.1.1 is broken in various ways, see https://github.com/cbrueffer/tophat-recondition for details. Run TopHat-Recondition to fix these issues. """ out_file = os.path.splitext(unmapped_file)[0] + "_fixup.bam" if file_exists(out_file): return out_file assert os.path.dirname(mapped_file) == os.path.dirname(unmapped_file) cmd = config_utils.get_program("tophat-recondition", data) cmd += " -q" tophat_out_dir = os.path.dirname(mapped_file) tophat_logfile = os.path.join(tophat_out_dir, 'tophat-recondition.log') with file_transaction(data, tophat_logfile) as tx_logfile: cmd += ' --logfile %s' % tx_logfile cmd += " -m %s" % mapped_file cmd += " -u %s" % unmapped_file cmd += " %s" % tophat_out_dir do.run(cmd, "Fixing unmapped reads with Tophat-Recondition.", None) return out_file def align(fastq_file, pair_file, ref_file, names, align_dir, data,): out_files = tophat_align(fastq_file, pair_file, ref_file, names["lane"], align_dir, data, names) return out_files def _estimate_paired_innerdist(fastq_file, pair_file, ref_file, out_base, out_dir, data): """Use Bowtie to estimate the inner distance of paired reads. """ mean, stdev = _bowtie_for_innerdist("100000", fastq_file, pair_file, ref_file, out_base, out_dir, data, True) if not mean or not stdev: mean, stdev = _bowtie_for_innerdist("1", fastq_file, pair_file, ref_file, out_base, out_dir, data, True) # No reads aligning so no data to process, set some default values if not mean or not stdev: mean, stdev = 200, 50 return mean, stdev def _bowtie_for_innerdist(start, fastq_file, pair_file, ref_file, out_base, out_dir, data, remove_workdir=False): work_dir = os.path.join(out_dir, "innerdist_estimate") if os.path.exists(work_dir): shutil.rmtree(work_dir) safe_makedir(work_dir) extra_args = ["-s", str(start), "-u", "250000"] ref_file, bowtie_runner = _determine_aligner_and_reference(ref_file, data) out_sam = bowtie_runner.align(fastq_file, pair_file, ref_file, {"lane": out_base}, work_dir, data, extra_args) dists = [] with pysam.Samfile(out_sam) as work_sam: for read in work_sam: if read.is_proper_pair and read.is_read1: dists.append(abs(read.isize) - 2 * read.rlen) if dists: median = float(numpy.median(dists)) deviations = [] for d in dists: deviations.append(abs(d - median)) # this is the median absolute deviation estimator of the # standard deviation mad = 1.4826 * float(numpy.median(deviations)) return int(median), int(mad) else: return None, None def _calculate_average_read_length(sam_file): with pysam.Samfile(sam_file) as work_sam: count = 0 read_lengths = [] for read in work_sam: count = count + 1 read_lengths.append(read.rlen) avg_read_length = int(float(sum(read_lengths)) / float(count)) return avg_read_length def _bowtie_major_version(stdout): """ bowtie --version returns strings like this: bowtie version 0.12.7 32-bit Built on Franklin.local Tue Sep 7 14:25:02 PDT 2010 """ version_line = stdout.split("\n")[0] version_string = version_line.strip().split()[2] major_version = int(version_string.split(".")[0]) # bowtie version 1 has a leading character of 0 or 1 if major_version == 0 or major_version == 1: major_version = 1 return major_version def _should_run_fusion(data): return dd.get_fusion_caller(data) def _determine_aligner_and_reference(ref_file, data): fusion_mode = _should_run_fusion(data) # fusion_mode only works with bowtie1 if fusion_mode: return _get_bowtie_with_reference(ref_file, 1) else: return _get_bowtie_with_reference(ref_file, 2) def _get_bowtie_with_reference(ref_file, version): if version == 1: ref_file = ref_file.replace("/bowtie2/", "/bowtie/") return ref_file, bowtie else: ref_file = ref_file.replace("/bowtie/", "/bowtie2/") return ref_file, bowtie2 def _tophat_major_version(config): cmd = [ utils.get_program_python("tophat"), config_utils.get_program("tophat", config, default="tophat"), "--version" ] # tophat --version returns strings like this: Tophat v2.0.4 version_string = str(subprocess.check_output(cmd)).strip().split()[1] major_version = int(version_string.split(".")[0][1:]) return major_version def _ref_version(ref_file): for ext in [os.path.splitext(x)[1] for x in glob.glob(ref_file + "*")]: if ext == ".ebwt": return 1 elif ext == ".bt2": return 2 raise ValueError("Cannot detect which reference version %s is. " "Should end in either .ebwt (bowtie) or .bt2 " "(bowtie2)." % (ref_file)) def fix_insert_size(in_bam, config): """ Tophat sets PI in the RG to be the inner distance size, but the SAM spec states should be the insert size. This fixes the RG in the alignment file generated by Tophat header to match the spec """ fixed_file = os.path.splitext(in_bam)[0] + ".pi_fixed.bam" if file_exists(fixed_file): return fixed_file header_file = os.path.splitext(in_bam)[0] + ".header.sam" read_length = bam.estimate_read_length(in_bam) bam_handle= bam.open_samfile(in_bam) header = bam_handle.header.copy() rg_dict = header['RG'][0] if 'PI' not in rg_dict: return in_bam PI = int(rg_dict.get('PI')) PI = PI + 2*read_length rg_dict['PI'] = PI header['RG'][0] = rg_dict with pysam.Samfile(header_file, "wb", header=header) as out_handle: with bam.open_samfile(in_bam) as in_handle: for record in in_handle: out_handle.write(record) shutil.move(header_file, fixed_file) return fixed_file bcbio-nextgen-1.2.9/bcbio/picard/000077500000000000000000000000001415626112400165715ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/picard/__init__.py000066400000000000000000000001601415626112400206770ustar00rootroot00000000000000# Back compatibility -- use broad subdirectory for new code from bcbio.broad import BroadRunner as PicardRunner bcbio-nextgen-1.2.9/bcbio/picard/metrics.py000066400000000000000000000001361415626112400206110ustar00rootroot00000000000000# Back compatibility -- use broad subdirectory for new code from bcbio.broad.metrics import * bcbio-nextgen-1.2.9/bcbio/picard/utils.py000066400000000000000000000001001415626112400202720ustar00rootroot00000000000000# Placeholder for back compatibility. from bcbio.utils import * bcbio-nextgen-1.2.9/bcbio/pipeline/000077500000000000000000000000001415626112400171345ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/pipeline/__init__.py000066400000000000000000000011261415626112400212450ustar00rootroot00000000000000"""High level code for driving a next-gen analysis pipeline. This structures processing steps into the following modules: - lane.py: Analyze a single fastq file. - fastq.py: Utilities to retrieve fastq files. - alignment.py: Align to a reference genome. - sample.py: Analyze a sample, which may consist of multiple lanes or barcoded samples on a lane. - merge.py: Merge multiple sample files in one processing run. - variation.py: Calculate SNP/indel variations for a sample. - qcsummary.py: Quality control, alignment metrics and summary information. """ bcbio-nextgen-1.2.9/bcbio/pipeline/alignment.py000066400000000000000000000173371415626112400214770ustar00rootroot00000000000000"""Pipeline code to run alignments and prepare BAM files. This works as part of the lane/flowcell process step of the pipeline. """ from collections import namedtuple import glob import os import toolz as tz from bcbio import bam, utils from bcbio.bam import cram from bcbio.ngsalign import (bbmap, bowtie, bwa, tophat, bowtie2, minimap2, novoalign, snap, star, hisat2, bismark, bsmap) from bcbio.pipeline import datadict as dd # Define a next-generation sequencing tool to plugin: # align_fn -- runs an aligner and generates SAM output # galaxy_loc_file -- name of a Galaxy location file to retrieve # the genome index location # bam_align_fn -- runs an aligner on a BAM file # remap_index_fn -- Function that will take the location provided # from galaxy_loc_file and find the actual location of the index file. # This is useful for indexes that don't have an associated location file # but are stored in the same directory structure. NgsTool = namedtuple("NgsTool", ["align_fn", "bam_align_fn", "galaxy_loc_file", "remap_index_fn"]) BASE_LOCATION_FILE = "sam_fa_indices.loc" TOOLS = { "bbmap": NgsTool(bbmap.align, None, None, bbmap.remap_index_fn), "bowtie": NgsTool(bowtie.align, None, bowtie.galaxy_location_file, None), "bowtie2": NgsTool(bowtie2.align, None, bowtie2.galaxy_location_file, bowtie2.remap_index_fn), "bwa": NgsTool(bwa.align_pipe, bwa.align_bam, bwa.galaxy_location_file, None), "bismark": NgsTool(bismark.align, None, None, bismark.remap_index_fn), "bsmap": NgsTool(bsmap.align, None, None, None), "sentieon-bwa": NgsTool(bwa.align_pipe, bwa.align_bam, bwa.galaxy_location_file, None), "minimap2": NgsTool(minimap2.align, None, None, minimap2.remap_index_fn), "novoalign": NgsTool(novoalign.align_pipe, novoalign.align_bam, novoalign.galaxy_location_file, novoalign.remap_index_fn), "tophat": NgsTool(tophat.align, None, bowtie2.galaxy_location_file, bowtie2.remap_index_fn), "samtools": NgsTool(None, None, BASE_LOCATION_FILE, None), "snap": NgsTool(snap.align, None, snap.galaxy_location_file, snap.remap_index_fn), "star": NgsTool(star.align, None, None, star.remap_index_fn), "tophat2": NgsTool(tophat.align, None, bowtie2.galaxy_location_file, bowtie2.remap_index_fn), "hisat2": NgsTool(hisat2.align, None, None, hisat2.remap_index_fn)} metadata = {"support_bam": [k for k, v in TOOLS.items() if v.bam_align_fn is not None]} def organize_noalign(data): """CWL target to skip alignment and organize input data. """ data = utils.to_single_data(data[0]) work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data))) work_bam = os.path.join(work_dir, "%s-input.bam" % dd.get_sample_name(data)) if data.get("files"): if data["files"][0].endswith(".cram"): work_bam = cram.to_bam(data["files"][0], work_bam, data) else: assert data["files"][0].endswith(".bam"), data["files"][0] utils.copy_plus(data["files"][0], work_bam) bam.index(work_bam, data["config"]) else: work_bam = None data["align_bam"] = work_bam return data def align_to_sort_bam(fastq1, fastq2, aligner, data): """Align to the named genome build, returning a sorted BAM file""" names = data["rgnames"] align_dir_parts = [data["dirs"]["work"], "align", names["sample"]] if data.get("disambiguate"): align_dir_parts.append(data["disambiguate"]["genome_build"]) aligner_index = get_aligner_index(aligner, data) align_dir = utils.safe_makedir(os.path.join(*align_dir_parts)) ref_file = tz.get_in(("reference", "fasta", "base"), data) if fastq1.endswith(".bam"): data = _align_from_bam(fastq1, aligner, aligner_index, ref_file, names, align_dir, data) else: data = _align_from_fastq(fastq1, fastq2, aligner, aligner_index, ref_file, names, align_dir, data) if data["work_bam"] and utils.file_exists(data["work_bam"]): if data.get("align_split") and dd.get_mark_duplicates(data): # If merging later with with bamsormadup need query sorted inputs # but CWL requires a bai file. Create a fake one to make it happy. bam.fake_index(data["work_bam"], data) else: # can't index non-sorted bam from bismark if not data["analysis"].lower().startswith("wgbs-seq"): bam.index(data["work_bam"], data["config"]) for extra in ["-sr", "-disc"]: extra_bam = utils.append_stem(data['work_bam'], extra) if utils.file_exists(extra_bam): bam.index(extra_bam, data["config"]) return data def get_aligner_with_aliases(aligner, data): """Retrieve aligner index retriever, including aliases for shared. Handles tricky cases like gridss where we need bwa indices even with no aligner specified since they're used internally within GRIDSS. """ aligner_aliases = {"sentieon-bwa": "bwa"} from bcbio import structural if not aligner and "gridss" in structural.get_svcallers(data): aligner = "bwa" return aligner_aliases.get(aligner) or aligner def allow_noindices(): return set(["minimap2"]) def get_aligner_index(aligner, data): """Handle multiple specifications of aligner indexes, returning value to pass to aligner. Original bcbio case -- a list of indices. CWL case: a single file with secondaryFiles staged in the same directory. """ aligner_indexes = tz.get_in(("reference", get_aligner_with_aliases(aligner, data), "indexes"), data) # standard bcbio case if aligner_indexes and isinstance(aligner_indexes, (list, tuple)): aligner_index = os.path.commonprefix(aligner_indexes) if aligner_index.endswith("."): aligner_index = aligner_index[:-1] return aligner_index # single file -- check for standard naming or directory elif aligner_indexes and os.path.exists(aligner_indexes): aligner_dir = os.path.dirname(aligner_indexes) aligner_prefix = os.path.splitext(aligner_indexes)[0] if len(glob.glob("%s.*" % aligner_prefix)) > 0: return aligner_prefix else: return aligner_dir if aligner not in allow_noindices(): raise ValueError("Did not find reference indices for aligner %s in genome: %s" % (aligner, data["reference"])) def _align_from_bam(fastq1, aligner, align_ref, sam_ref, names, align_dir, data): assert not data.get("align_split"), "Do not handle split alignments with BAM yet" align_fn = TOOLS[aligner].bam_align_fn if align_fn is None: raise NotImplementedError("Do not yet support BAM alignment with %s" % aligner) out = align_fn(fastq1, align_ref, names, align_dir, data) if isinstance(out, dict): assert "work_bam" in out return out else: data["work_bam"] = out return data def _align_from_fastq(fastq1, fastq2, aligner, align_ref, sam_ref, names, align_dir, data): """Align from fastq inputs, producing sorted BAM output. """ config = data["config"] align_fn = TOOLS[aligner].align_fn out = align_fn(fastq1, fastq2, align_ref, names, align_dir, data) # handle align functions that update the main data dictionary in place if isinstance(out, dict): assert out.get("work_bam"), (dd.get_sample_name(data), out.get("work_bam")) return out # handle output of raw SAM files that need to be converted to BAM else: work_bam = bam.sam_to_bam(out, config) data["work_bam"] = bam.sort(work_bam, config) return data bcbio-nextgen-1.2.9/bcbio/pipeline/archive.py000066400000000000000000000017441415626112400211350ustar00rootroot00000000000000"""Perform archiving of output files for compressed storage. Handles conversion to CRAM format. """ from bcbio import utils from bcbio.bam import cram from bcbio.cwl import cwlutils from bcbio.pipeline import datadict as dd def to_cram(data): """Convert BAM archive files into indexed CRAM. """ data = utils.to_single_data(data) cram_file = cram.compress(dd.get_work_bam(data) or dd.get_align_bam(data), data) out_key = "archive_bam" if cwlutils.is_cwl_run(data) else "work_bam" data[out_key] = cram_file return [[data]] def compress(samples, run_parallel): """Perform compression of output files for long term storage. """ to_cram = [] finished = [] for data in [x[0] for x in samples]: if "cram" in dd.get_archive(data) or "cram-lossless" in dd.get_archive(data): to_cram.append([data]) else: finished.append([data]) crammed = run_parallel("archive_to_cram", to_cram) return finished + crammed bcbio-nextgen-1.2.9/bcbio/pipeline/cleanbam.py000066400000000000000000000202211415626112400212450ustar00rootroot00000000000000"""Clean an input BAM file to work with downstream pipelines. GATK and Picard based pipelines have specific requirements for chromosome order, run group information and other BAM formatting. This provides a pipeline to prepare and resort an input. """ import os import sys import pysam from bcbio import bam, broad, utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.heterogeneity import chromhacks from bcbio.ngsalign import novoalign from bcbio.pipeline import datadict as dd from bcbio.provenance import do def fixrg(in_bam, names, ref_file, dirs, data): """Fix read group in a file, using samtools addreplacerg. addreplacerg does not remove the old read group, causing confusion when checking. We use reheader to work around this """ work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "bamclean", dd.get_sample_name(data))) out_file = os.path.join(work_dir, "%s-fixrg.bam" % utils.splitext_plus(os.path.basename(in_bam))[0]) if not utils.file_exists(out_file): out_file = os.path.join(work_dir, "%s-fixrg.bam" % dd.get_sample_name(data)) if not utils.file_uptodate(out_file, in_bam): with file_transaction(data, out_file) as tx_out_file: rg_info = novoalign.get_rg_info(names) new_header = "%s-header.txt" % os.path.splitext(out_file)[0] cores = dd.get_cores(data) do.run("samtools view -H {in_bam} | grep -v ^@RG > {new_header}".format(**locals()), "Create empty RG header: %s" % dd.get_sample_name(data)) cmd = ("samtools reheader {new_header} {in_bam} | " "samtools addreplacerg -@ {cores} -r '{rg_info}' -m overwrite_all -O bam -o {tx_out_file} -") do.run(cmd.format(**locals()), "Fix read groups: %s" % dd.get_sample_name(data)) return out_file def remove_extracontigs(in_bam, data): """Remove extra contigs (non chr1-22,X,Y) from an input BAM. These extra contigs can often be arranged in different ways, causing incompatibility issues with GATK and other tools. This also fixes the read group header as in fixrg. This does not yet handle mapping over 1 -> chr1 issues since this requires a ton of search/replace which slows down conversion. """ work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "bamclean", dd.get_sample_name(data))) out_file = os.path.join(work_dir, "%s-noextras.bam" % utils.splitext_plus(os.path.basename(in_bam))[0]) if not utils.file_exists(out_file): out_file = os.path.join(work_dir, "%s-noextras.bam" % dd.get_sample_name(data)) if not utils.file_uptodate(out_file, in_bam): with file_transaction(data, out_file) as tx_out_file: target_chroms = _target_chroms_and_header(in_bam, data) str_chroms = " ".join(target_chroms) rg_info = novoalign.get_rg_info(data["rgnames"]) bcbio_py = sys.executable ref_file = dd.get_ref_file(data) local_bam = os.path.join(os.path.dirname(tx_out_file), os.path.basename(in_bam)) cores = dd.get_cores(data) utils.symlink_plus(in_bam, local_bam) bam.index(local_bam, data["config"]) cmd = ("samtools view -@ {cores} -h {local_bam} {str_chroms} | " """{bcbio_py} -c 'from bcbio.pipeline import cleanbam; """ """cleanbam.fix_header("{ref_file}")' | """ "samtools view -@ {cores} -u - | " "samtools addreplacerg -@ {cores} -r '{rg_info}' -m overwrite_all -O bam -o {tx_out_file} - ") do.run(cmd.format(**locals()), "bamprep, remove extra contigs: %s" % dd.get_sample_name(data)) return out_file def _target_chroms_and_header(bam_file, data): """Get a list of chromosomes to target and new updated ref_file header. Could potentially handle remapping from chr1 -> 1 but currently disabled due to speed issues. """ special_remaps = {"chrM": "MT", "MT": "chrM"} target_chroms = dict([(x.name, i) for i, x in enumerate(ref.file_contigs(dd.get_ref_file(data))) if chromhacks.is_autosomal_or_sex(x.name)]) out_chroms = [] with pysam.Samfile(bam_file, "rb") as bamfile: for bami, bam_contig in enumerate([c["SN"] for c in bamfile.header["SQ"]]): if bam_contig in target_chroms: target_chrom = bam_contig elif bam_contig in special_remaps and special_remaps[bam_contig] in target_chroms: target_chrom = special_remaps[bam_contig] elif bam_contig.startswith("chr") and bam_contig.replace("chr", "") in target_chroms: target_chrom = bam_contig.replace("chr", "") elif "chr%s" % bam_contig in target_chroms: target_chrom = "chr%s" % bam_contig else: target_chrom = None # target_chrom == bam_contig ensures we don't try chr1 -> 1 style remapping if target_chrom and target_chrom == bam_contig: # Order not required if dealing with SAM file header fixing #assert bami == target_chroms[target_chrom], \ # ("remove_extracontigs: Non-matching order of standard contig: %s %s (%s vs %s)" % # (bam_file, target_chrom, bami, target_chroms[target_chrom])) out_chroms.append(target_chrom) assert out_chroms, ("remove_extracontigs: Did not find any chromosomes in reference file: %s %s" % (bam_file, target_chroms)) return out_chroms def fix_header(ref_file): added_ref = False for line in sys.stdin: # skip current read groups, since adding new # skip current contigs since adding new sequence dictionary if line.startswith(("@RG", "@SQ")): pass elif not added_ref and not line.startswith("@"): for x in ref.file_contigs(ref_file): sys.stdout.write("@SQ\tSN:%s\tLN:%s\n" % (x.name, x.size)) added_ref = True else: sys.stdout.write(line) def picard_prep(in_bam, names, ref_file, dirs, data): """Prepare input BAM using Picard and GATK cleaning tools. - ReorderSam to reorder file to reference - AddOrReplaceReadGroups to add read group information and coordinate sort - PrintReads to filters to remove problem records: - filterMBQ to remove reads with mismatching bases and base qualities """ runner = broad.runner_from_path("picard", data["config"]) work_dir = utils.safe_makedir(os.path.join(dirs["work"], "bamclean", names["sample"])) runner.run_fn("picard_index_ref", ref_file) reorder_bam = os.path.join(work_dir, "%s-reorder.bam" % os.path.splitext(os.path.basename(in_bam))[0]) if not utils.file_exists(reorder_bam): reorder_bam = os.path.join(work_dir, "%s-reorder.bam" % dd.get_sample_name(data)) reorder_bam = runner.run_fn("picard_reorder", in_bam, ref_file, reorder_bam) rg_bam = runner.run_fn("picard_fix_rgs", reorder_bam, names) return _filter_bad_reads(rg_bam, ref_file, data) def _filter_bad_reads(in_bam, ref_file, data): """Use GATK filter to remove problem reads which choke GATK and Picard. """ bam.index(in_bam, data["config"]) out_file = "%s-gatkfilter.bam" % os.path.splitext(in_bam)[0] if not utils.file_exists(out_file): with tx_tmpdir(data) as tmp_dir: with file_transaction(data, out_file) as tx_out_file: params = [("FixMisencodedBaseQualityReads" if dd.get_quality_format(data, "").lower() == "illumina" else "PrintReads"), "-R", ref_file, "-I", in_bam, "-O", tx_out_file, "-RF", "MatchingBasesAndQualsReadFilter", "-RF", "SeqIsStoredReadFilter", "-RF", "CigarContainsNoNOperator"] jvm_opts = broad.get_gatk_opts(data["config"], tmp_dir) do.run(broad.gatk_cmd("gatk", jvm_opts, params), "Filter problem reads") bam.index(out_file, data["config"]) return out_file bcbio-nextgen-1.2.9/bcbio/pipeline/config_utils.py000066400000000000000000000462211415626112400222000ustar00rootroot00000000000000"""Loads configurations from .yaml files and expands environment variables. """ import copy import collections import glob import math import os import pprint import sys import yaml import toolz as tz import six class CmdNotFound(Exception): pass # ## Generalized configuration def update_w_custom(config, lane_info): """Update the configuration for this lane if a custom analysis is specified. """ name_remaps = {"variant": ["SNP calling", "variant", "variant2"], "SNP calling": ["SNP calling", "variant", "variant2"], "variant2": ["SNP calling", "variant", "variant2"]} config = copy.deepcopy(config) base_name = lane_info.get("analysis") if "algorithm" not in config: config["algorithm"] = {} for analysis_type in name_remaps.get(base_name, [base_name]): custom = config.get("custom_algorithms", {}).get(analysis_type) if custom: for key, val in custom.items(): config["algorithm"][key] = val # apply any algorithm details specified with the lane for key, val in lane_info.get("algorithm", {}).items(): config["algorithm"][key] = val # apply any resource details specified with the lane for prog, pkvs in lane_info.get("resources", {}).items(): if prog not in config["resources"]: config["resources"][prog] = {} for key, val in pkvs.items(): config["resources"][prog][key] = val return config # ## Retrieval functions def load_system_config(config_file=None, work_dir=None, allow_missing=False): """Load bcbio_system.yaml configuration file, handling standard defaults. Looks for configuration file in default location within final base directory from a standard installation. Handles both standard installs (galaxy/bcbio_system.yaml) and docker installs (config/bcbio_system.yaml). """ docker_config = _get_docker_config() if config_file is None: config_file = "bcbio_system.yaml" if not os.path.exists(config_file): base_dir = get_base_installdir() test_config = os.path.join(base_dir, "galaxy", config_file) if os.path.exists(test_config): config_file = test_config elif allow_missing: config_file = None else: raise ValueError("Could not find input system configuration file %s, " "including inside standard directory %s" % (config_file, os.path.join(base_dir, "galaxy"))) config = load_config(config_file) if config_file else {} if docker_config: assert work_dir is not None, "Need working directory to merge docker config" config_file = os.path.join(work_dir, "%s-merged%s" % os.path.splitext(os.path.basename(config_file))) config = _merge_system_configs(config, docker_config, config_file) if "algorithm" not in config: config["algorithm"] = {} config["bcbio_system"] = config_file return config, config_file def get_base_installdir(cmd=sys.executable): return os.path.normpath(os.path.join(os.path.realpath(cmd), os.pardir, os.pardir, os.pardir)) def _merge_system_configs(host_config, container_config, out_file=None): """Create a merged system configuration from external and internal specification. """ out = copy.deepcopy(container_config) for k, v in host_config.items(): if k in set(["galaxy_config"]): out[k] = v elif k == "resources": for pname, resources in v.items(): if not isinstance(resources, dict) and pname not in out[k]: out[k][pname] = resources else: for rname, rval in resources.items(): if (rname in set(["cores", "jvm_opts", "memory"]) or pname in set(["gatk", "mutect"])): if pname not in out[k]: out[k][pname] = {} out[k][pname][rname] = rval # Ensure final file is relocatable by mapping back to reference directory if "bcbio_system" in out and ("galaxy_config" not in out or not os.path.isabs(out["galaxy_config"])): out["galaxy_config"] = os.path.normpath(os.path.join(os.path.dirname(out["bcbio_system"]), os.pardir, "galaxy", "universe_wsgi.ini")) if out_file: with open(out_file, "w") as out_handle: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) return out def _get_docker_config(): base_dir = get_base_installdir() docker_configfile = os.path.join(base_dir, "config", "bcbio_system.yaml") if os.path.exists(docker_configfile): return load_config(docker_configfile) def merge_resources(args): """Merge docker local resources and global resource specification in a set of arguments. Finds the `data` object within passed arguments and updates the resources from a local docker configuration if present. """ docker_config = _get_docker_config() if not docker_config: return args else: def _update_resources(config): config["resources"] = _merge_system_configs(config, docker_config)["resources"] return config return _update_config(args, _update_resources, allow_missing=True) def load_config(config_file): """Load YAML config file, replacing environmental variables. """ with open(config_file) as in_handle: config = yaml.safe_load(in_handle) config = _expand_paths(config) if 'resources' not in config: config['resources'] = {} # lowercase resource names, the preferred way to specify, for back-compatibility newr = {} for k, v in config["resources"].items(): if k.lower() != k: newr[k.lower()] = v config["resources"].update(newr) return config def _expand_paths(config): for field, setting in config.items(): if isinstance(config[field], dict): config[field] = _expand_paths(config[field]) else: config[field] = expand_path(setting) return config def expand_path(path): """ Combines os.path.expandvars with replacing ~ with $HOME. """ try: return os.path.expandvars(path.replace("~", "$HOME")) except AttributeError: return path def get_resources(name, config): """Retrieve resources for a program, pulling from multiple config sources. """ return tz.get_in(["resources", name], config, tz.get_in(["resources", "default"], config, {})) def get_program(name, config, ptype="cmd", default=None): """Retrieve program information from the configuration. This handles back compatible location specification in input YAML. The preferred location for program information is in `resources` but the older `program` tag is also supported. """ # support taking in the data dictionary config = config.get("config", config) try: pconfig = config.get("resources", {})[name] # If have leftover old except KeyError: pconfig = {} old_config = config.get("program", {}).get(name, None) if old_config: for key in ["dir", "cmd"]: if not key in pconfig: pconfig[key] = old_config if ptype == "cmd": return _get_program_cmd(name, pconfig, config, default) elif ptype == "dir": return _get_program_dir(name, pconfig) else: raise ValueError("Don't understand program type: %s" % ptype) def _get_check_program_cmd(fn): def wrap(name, pconfig, config, default): is_ok = lambda f: os.path.isfile(f) and os.access(f, os.X_OK) bcbio_system = config.get("bcbio_system", None) if bcbio_system: system_bcbio_path = os.path.join(os.path.dirname(bcbio_system), os.pardir, "anaconda", "bin", name) if is_ok(system_bcbio_path): return system_bcbio_path # support bioconda installed programs if is_ok(os.path.join(os.path.dirname(sys.executable), name)): return (os.path.join(os.path.dirname(sys.executable), name)) # find system bioconda installed programs if using private code install # makes notfound out of picard program = expand_path(fn(name, pconfig, config, default)) if is_ok(program): return program # search the PATH now for adir in os.environ['PATH'].split(":"): apath = os.path.realpath(os.path.join(adir, name)) if is_ok(apath): return apath if is_ok(os.path.join(adir, program)): return os.path.join(adir, program) raise CmdNotFound(" ".join(map(repr, (fn.__name__ if six.PY3 else fn.func_name, name, pconfig, default)))) return wrap @_get_check_program_cmd def _get_program_cmd(name, pconfig, config, default): """Retrieve commandline of a program. """ if pconfig is None: return name elif isinstance(pconfig, six.string_types): return pconfig elif "cmd" in pconfig: return pconfig["cmd"] elif default is not None: return default else: return name def _get_program_dir(name, config): """Retrieve directory for a program (local installs/java jars). """ if config is None: raise ValueError("Could not find directory in config for %s" % name) elif isinstance(config, six.string_types): return config elif "dir" in config: return expand_path(config["dir"]) else: raise ValueError("Could not find directory in config for %s" % name) def get_jar(base_name, dname): """Retrieve a jar in the provided directory """ jars = glob.glob(os.path.join(expand_path(dname), "%s*.jar" % base_name)) if len(jars) == 1: return jars[0] elif len(jars) > 1: raise ValueError("Found multiple jars for %s in %s. Need single jar: %s" % (base_name, dname, jars)) else: raise ValueError("Could not find java jar %s in %s" % (base_name, dname)) # ## Retrieval and update to configuration from arguments def is_std_config_arg(x): return isinstance(x, dict) and "algorithm" in x and "resources" in x and "files" not in x def is_nested_config_arg(x): return isinstance(x, dict) and "config" in x and is_std_config_arg(x["config"]) def get_algorithm_config(xs): """Flexibly extract algorithm configuration for a sample from any function arguments. """ if isinstance(xs, dict): xs = [xs] for x in xs: if is_std_config_arg(x): return x["algorithm"] elif is_nested_config_arg(x): return x["config"]["algorithm"] elif isinstance(x, (list, tuple)) and is_nested_config_arg(x[0]): return x[0]["config"]["algorithm"] raise ValueError("Did not find algorithm configuration in items: {0}" .format(pprint.pformat(xs))) def get_dataarg(args): """Retrieve the world 'data' argument from a set of input parameters. """ for i, arg in enumerate(args): if is_nested_config_arg(arg): return i, arg elif is_std_config_arg(arg): return i, {"config": arg} elif isinstance(arg, (list, tuple)) and is_nested_config_arg(arg[0]): return i, arg[0] raise ValueError("Did not find configuration or data object in arguments: %s" % args) def add_cores_to_config(args, cores_per_job, parallel=None): """Add information about available cores for a job to configuration. Ugly hack to update core information in a configuration dictionary. """ def _update_cores(config): config["algorithm"]["num_cores"] = int(cores_per_job) if parallel: parallel.pop("view", None) config["parallel"] = parallel return config return _update_config(args, _update_cores) def _update_config(args, update_fn, allow_missing=False): """Update configuration, nested in argument list, with the provided update function. """ new_i = None for i, arg in enumerate(args): if (is_std_config_arg(arg) or is_nested_config_arg(arg) or (isinstance(arg, (list, tuple)) and is_nested_config_arg(arg[0]))): new_i = i break if new_i is None: if allow_missing: return args else: raise ValueError("Could not find configuration in args: %s" % str(args)) new_arg = args[new_i] if is_nested_config_arg(new_arg): new_arg["config"] = update_fn(copy.deepcopy(new_arg["config"])) elif is_std_config_arg(new_arg): new_arg = update_fn(copy.deepcopy(new_arg)) elif isinstance(arg, (list, tuple)) and is_nested_config_arg(new_arg[0]): new_arg_first = new_arg[0] new_arg_first["config"] = update_fn(copy.deepcopy(new_arg_first["config"])) new_arg = [new_arg_first] + new_arg[1:] else: raise ValueError("Unexpected configuration dictionary: %s" % new_arg) args = list(args)[:] args[new_i] = new_arg return args def convert_to_bytes(mem_str): """Convert a memory specification, potentially with M or G, into bytes. """ if str(mem_str)[-1].upper().endswith("G"): return int(round(float(mem_str[:-1]) * 1024 * 1024)) elif str(mem_str)[-1].upper().endswith("M"): return int(round(float(mem_str[:-1]) * 1024)) else: return int(round(float(mem_str))) def adjust_cores_to_mb_target(target_mb, mem_str, cores): """Scale core usage to match a Mb/core target. Useful for memory dependent programs where we don't have control over memory usage so need to scale cores. """ cur_mb = convert_to_bytes(mem_str) / 1024.0 scale = target_mb / cur_mb if scale >= 1: return cores else: return max(1, int(math.ceil(scale * cores))) def adjust_memory(val, magnitude, direction="increase", out_modifier="", maximum=None): """Adjust memory based on number of cores utilized. """ modifier = val[-1:] amount = float(val[:-1]) if direction == "decrease": new_amount = amount / float(magnitude) # dealing with a specifier like 1G, need to scale to Mb if new_amount < 1 or (out_modifier.upper().startswith("M") and modifier.upper().startswith("G")): if modifier.upper().startswith("G"): new_amount = (amount * 1024) / magnitude modifier = "M" + modifier[1:] else: raise ValueError("Unexpected decrease in memory: %s by %s" % (val, magnitude)) amount = int(new_amount) elif direction == "increase" and magnitude > 1: # for increases with multiple cores, leave small percentage of # memory for system to maintain process running resource and # avoid OOM killers adjuster = 0.91 amount = int(math.ceil(amount * (adjuster * magnitude))) if out_modifier.upper().startswith("G") and modifier.upper().startswith("M"): modifier = out_modifier amount = int(math.floor(amount / 1024.0)) if out_modifier.upper().startswith("M") and modifier.upper().startswith("G"): modifier = out_modifier modifier = int(amount * 1024) if maximum: max_modifier = maximum[-1] max_amount = float(maximum[:-1]) if modifier.upper() == "G" and max_modifier.upper() == "M": max_amount = max_amount / 1024.0 elif modifier.upper() == "M" and max_modifier.upper() == "G": max_amount = max_amount * 1024.0 amount = min([amount, max_amount]) return "{amount}{modifier}".format(amount=int(math.floor(amount)), modifier=modifier) def adjust_opts(in_opts, config): """Establish JVM opts, adjusting memory for the context if needed. This allows using less or more memory for highly parallel or multicore supporting processes, respectively. """ memory_adjust = config["algorithm"].get("memory_adjust", {}) out_opts = [] for opt in in_opts: if opt.startswith("-Xmx") or (opt.startswith("-Xms") and memory_adjust.get("direction") == "decrease"): arg = opt[:4] opt = "{arg}{val}".format(arg=arg, val=adjust_memory(opt[4:], memory_adjust.get("magnitude", 1), memory_adjust.get("direction"), maximum=memory_adjust.get("maximum"))) out_opts.append(opt) return out_opts # specific program usage def use_vqsr(algs, call_file=None): """Processing uses GATK's Variant Quality Score Recalibration. """ from bcbio.variation import vcfutils vqsr_callers = set(["gatk", "gatk-haplotype"]) vqsr_sample_thresh = 50 vqsr_supported = collections.defaultdict(int) coverage_intervals = set([]) for alg in algs: callers = alg.get("variantcaller") if isinstance(callers, six.string_types): callers = [callers] if not callers: # no variant calling, no VQSR continue if "vqsr" in (alg.get("tools_off") or []): # VQSR turned off continue for c in callers: if c in vqsr_callers: if "vqsr" in (alg.get("tools_on") or []): # VQSR turned on: vqsr_supported[c] += 1 coverage_intervals.add("genome") # Do not try VQSR for gVCF inputs elif call_file and vcfutils.is_gvcf_file(call_file): pass else: coverage_intervals.add(alg.get("coverage_interval", "exome").lower()) vqsr_supported[c] += 1 if len(vqsr_supported) > 0: num_samples = max(vqsr_supported.values()) if "genome" in coverage_intervals or num_samples >= vqsr_sample_thresh: return True return False def use_snpeff(algs): """Processing uses snpEff. Avoids memory requirements if not used. """ return any(alg.get("effects", "snpeff") == "snpeff" and alg.get("variantcaller") for alg in algs) def use_bcbio_variation_recall(algs): """Processing uses bcbio-variation-recall. Avoids core requirement if not used. """ for alg in algs: jointcaller = alg.get("jointcaller", []) if not isinstance(jointcaller, (tuple, list)): jointcaller = [jointcaller] for caller in jointcaller: if caller not in set(["gatk-haplotype-joint", None, False]): return True return False ## functions for navigating through the standard galaxy directory of files def get_rRNA_interval(genome_dir): return os.path.join(genome_dir, "rnaseq", "rRNA.interval_list") def get_transcript_refflat(genome_dir): return os.path.join(genome_dir, "rnaseq", "ref-transcripts.refFlat") def get_rRNA_sequence(genome_dir): return os.path.join(genome_dir, "rnaseq", "rRNA.fa") def program_installed(program, data): """ returns True if the path to a program can be found """ try: path = get_program(program, data) except CmdNotFound: return False return True bcbio-nextgen-1.2.9/bcbio/pipeline/datadict.py000066400000000000000000000474501415626112400212750ustar00rootroot00000000000000""" functions to access the data dictionary in a clearer way """ import os import toolz as tz from bcbio.utils import file_exists, to_single_data, deepish_copy, flatten from bcbio.log import logger from collections import namedtuple import sys LOOKUPS = { "config": {"keys": ['config']}, "tmp_dir": {"keys": ['config', 'resources', 'tmp', 'dir']}, "num_cores": {"keys": ['config', 'algorithm', 'num_cores'], "default": 1}, "svprioritize": {"keys": ['config', 'algorithm', 'svprioritize']}, "effects_transcripts": {"keys": ["config", "algorithm", "effects_transcripts"], "default": "all"}, "genome_build": {"keys": ["genome_build"]}, "gtf_file": {"keys": ['genome_resources', 'rnaseq', 'transcripts'], "checker": file_exists}, "transcriptome_fasta": {"keys": ["config", "algorithm", "transcriptome_fasta"], "default": None}, "transcriptome_gtf": {"keys": ["config", "algorithm", "transcriptome_gtf"], "default": None}, "singlecell_quantifier": {"keys": ["config", "algorithm", "singlecell_quantifier"], "default": "rapmap"}, "positional_umi": {"keys": ["config", "algorithm", "positional_umi"]}, "tx2gene": {"keys": ["tx2gene"]}, "ref_file": {"keys": ["reference", "fasta", "base"]}, "ref_file_compressed": {"keys": ["reference", "fastagz", "base"]}, "srna_gtf_file": {"keys": ['genome_resources', 'srnaseq', 'srna_transcripts'], "checker": file_exists}, "srna_trna_file": {"keys": ['genome_resources', 'srnaseq', 'trna_fasta'], "checker": file_exists}, "srna_mint_lookup": {"keys": ['genome_resources', 'srnaseq', 'mint_lookup'], "checker": file_exists}, "srna_mint_space": {"keys": ['genome_resources', 'srnaseq', 'mint_space'], "checker": file_exists}, "srna_mint_other": {"keys": ['genome_resources', 'srnaseq', 'mint_other'], "checker": file_exists}, "mirdeep2_file": {"keys": ['genome_resources', 'srnaseq', 'mirdeep2_fasta'], "checker": file_exists}, "mirbase_hairpin": {"keys": ['genome_resources', 'srnaseq', 'mirbase_hairpin'], "checker": file_exists}, "mirbase_mature": {"keys": ['genome_resources', 'srnaseq', 'mirbase_mature'], "checker": file_exists}, "gene_bed": {"keys": ['genome_resources', 'rnaseq', 'gene_bed'], "checker": file_exists}, "work_dir": {"keys": ['dirs', 'work']}, "sam_ref": {"keys": ["sam_ref"]}, "disambiguate": {"keys": ["config", "algorithm", "disambiguate"], "default": False}, "lane": {"keys": ["rgnames", "lane"]}, "cores": {"keys": ["config", "algorithm", "num_cores"], "default": 1}, "sample_name": {"keys": ['rgnames', 'sample']}, "strandedness": {"keys": ['config', 'algorithm', 'strandedness'], "default": "unstranded"}, "vcfanno": {"keys": ['config', 'algorithm', 'vcfanno'], "default": [], "always_list": True}, "analysis": {"keys": ["analysis"], "default": ""}, "square_vcf": {"keys": ['square_vcf']}, "ploidy": {"keys": ['config', 'algorithm', 'ploidy'], "default": 2}, "gender": {"keys": ["metadata", "sex"], "default": ""}, "batch": {"keys": ["metadata", "batch"]}, "bcbiornaseq": {"keys": ["config", "algorithm", "bcbiornaseq"], "default": {}}, "mark_duplicates": {"keys": ["config", "algorithm", "mark_duplicates"], "default": True}, "phenotype": {"keys": ["metadata", "phenotype"], "default": ""}, "svclass": {"keys": ["metadata", "svclass"], "default": ""}, "prep_method": {"keys": ["metadata", "prep_method"], "default": ""}, "disease": {"keys": ["metadata", "disease"], "default": ""}, "hetcaller": {"keys": ["config", "algorithm", "hetcaller"]}, "variantcaller": {"keys": ['config', 'algorithm', 'variantcaller']}, "variantcaller_order": {"keys": ['config', 'algorithm', 'variantcaller_order'], "default": 0}, "keep_duplicates": {"keys": ['config', 'algorithm', "keep_duplicates"], "default": False}, "keep_multimapped": {"keys": ['config', 'algorithm', "keep_multimapped"], "default": False}, "svcaller": {"keys": ['config', 'algorithm', 'svcaller'], "default": [], "always_list": True}, "jointcaller": {"keys": ['config', 'algorithm', 'jointcaller']}, "hlacaller": {"keys": ['config', 'algorithm', 'hlacaller']}, "recalibrate": {"keys": ['config', 'algorithm', 'recalibrate'], "default": False}, "realign": {"keys": ['config', 'algorithm', 'realign'], "default": False}, "ensemble": {"keys": ["config", "algorithm", "ensemble"], "default": {}}, "background_variant": {"keys": ["config", "algorithm", "background", "variant"]}, "peakcaller": {"keys": ['config', 'algorithm', 'peakcaller'], "default": []}, "chip_method": {"keys": ['config', 'algorithm', 'chip_method'], "default": "chip"}, "spikein_counts": {"keys": ["spikein_counts"]}, "count_file": {"keys": ["count_file"]}, "hla_bam": {"keys": ["hla_bam"]}, "mirna_counts": {"keys": ["mirna_counts"]}, "isomir_counts": {"keys": ["isomir_counts"]}, "novel_mirna_counts": {"keys": ["novel_mirna_counts"]}, "novel_isomir_counts": {"keys": ["novel_isomir_counts"]}, "combined_counts": {"keys": ["combined_counts"]}, "combined_histogram": {"keys": ["combined_histogram"]}, "annotated_combined_counts": {"keys": ["annotated_combined_counts"]}, "genome_context_files": {"keys": ["reference", "genome_context"], "default": [], "always_list": True}, "viral_files": {"keys": ["reference", "viral"], "default": [], "always_list": True}, "archive": {"keys": ["config", "algorithm", "archive"], "default": [], "always_list": True}, "dexseq_gff": {"keys": ['genome_resources', 'rnaseq', 'dexseq']}, "combined_fpkm": {"keys": ['combined_fpkm']}, "combined_fpkm_isoform": {"keys": ['combined_fpkm_isoform']}, "express_fpkm": {"keys": ['express_fpkm']}, "express_tpm": {"keys": ['express_tpm']}, "express_counts": {"keys": ['express_counts']}, "histogram_counts": {"keys": ['histogram_counts']}, "isoform_to_gene": {"keys": ['isoform_to_gene']}, "fusion_mode": {"keys": ['config', 'algorithm', 'fusion_mode']}, "fusion_caller": {"keys": ['config', 'algorithm', 'fusion_caller']}, "known_fusions": {"keys": ['config', 'algorithm', 'known_fusions']}, "dexseq_counts": {"keys": ['dexseq_counts']}, "description": {"keys": ['description']}, "aligner": {"keys": ['config', 'algorithm', 'aligner']}, "align_split_size": {"keys": ['config', 'algorithm', 'align_split_size']}, "bam_clean": {"keys": ['config', 'algorithm', 'bam_clean']}, "kit": {"keys": ['config', 'algorithm', 'kit']}, "platform": {"keys": ['config', 'algorithm', 'platform'], "default": "illumina"}, "quality_format": {"keys": ['config', 'algorithm', 'quality_format'], "default": "standard"}, "algorithm_qc": {"keys": ['config', 'algorithm', 'qc'], "default": [], "always_list": True}, "summary_qc": {"keys": ['summary', 'qc'], "default": {}}, "summary_metrics": {"keys": ['summary', 'metrics'], "default": {}}, "adapters": {"keys": ['config', 'algorithm', 'adapters'], "default": [], "always_list": True}, "custom_trim": {"keys": ['config', 'algorithm', 'custom_trim'], "default": []}, "species": {"keys": ['config', 'algorithm', 'species'], "default": None}, "trim_reads": {"keys": ['config', 'algorithm', 'trim_reads'], "default": None}, "trim_ends": {"keys": ['config', 'algorithm', 'trim_ends'], "default": []}, "min_read_length": {"keys": ['config', 'algorithm', 'min_read_length'], "default": 25}, "variation_resources": {"keys": ["genome_resources", "variation"], "default": {}}, "qsig_file": {"keys": ['genome_resources', 'variation', 'qsignature'], "checker": file_exists}, "mixup_check": {"keys": ["config", "algorithm", "mixup_check"], "default": False}, "cufflinks_dir": {"keys": ['cufflinks_dir']}, "stringtie_dir": {"keys": ['stringtie_dir']}, "rsem": {"keys": ["config", "algorithm", "rsem"], "default": False}, "transcriptome_align": {"keys": ["config", "algorithm", "transcriptome_align"], "default": False}, "quantify_genome_alignments": {"keys": ["config", "algorithm", "quantify_genome_alignments"], "default": False}, "expression_caller": {"keys": ["config", "algorithm", "expression_caller"], "default": [], "always_list": True}, "fusion_caller": {"keys": ["config", "algorithm", "fusion_caller"], "default": []}, "spikein_fasta" : {"keys": ["config", "algorithm", "spikein_fasta"], "default": None}, "transcriptome_bam": {"keys": ["transcriptome_bam"]}, "junction_bed": {"keys": ["junction_bed"]}, "starjunction": {"keys": ["starjunction"]}, "chimericjunction": {"keys": ["chimericjunction"]}, "star_log": {"keys": ["STAR", "log"], "default": None}, "fpkm_isoform": {"keys": ["fpkm_isoform"]}, "fpkm": {"keys": ["fpkm"]}, "galaxy_dir": {"keys": ["dirs", "galaxy"]}, "assembled_gtf": {"keys": ["assembled_gtf"], "default": []}, "merged_gtf": {"keys": ["merged_gtf"], "default": None}, "transcript_assembler": {"keys": ["config", "algorithm", "transcript_assembler"], "default": []}, "oncofuse_file": {"keys": ["oncofuse_file"]}, "pizzly_dir": {"keys": ["pizzly_dir"]}, "split_bam": {"keys": ["split_bam"]}, "vrn_file": {"keys": ["vrn_file"]}, "exclude_regions": {"keys": ["config", "algorithm", "exclude_regions"], "default": [], "always_list": True}, "variant_regions": {"keys": ["config", "algorithm", "variant_regions"]}, "variant_regions_merged": {"keys": ["config", "algorithm", "variant_regions_merged"]}, "variant_regions_orig": {"keys": ["config", "algorithm", "variant_regions_orig"]}, "sv_regions": {"keys": ["config", "algorithm", "sv_regions"]}, "coverage": {"keys": ["config", "algorithm", "coverage"]}, "coverage_merged": {"keys": ["config", "algorithm", "coverage_merged"]}, "coverage_orig": {"keys": ["config", "algorithm", "coverage_orig"]}, "callable_regions": {"keys": ["regions", "callable"]}, "avg_coverage": {"keys": ["regions", "avg_coverage"]}, "callable_min_size": {"keys": ["config", "algorithm", "callable_min_size"], "default": 1000000}, "min_allele_fraction": {"keys": ["config", "algorithm", "min_allele_fraction"], "default": 10}, "normalized_depth": {"keys": ["depth", "bins", "normalized"]}, "save_diskspace": {"keys": ["config", "algorithm", "save_diskspace"]}, "salmon": {"keys": ["salmon"]}, "umi_type": {"keys": ["config", "algorithm", "umi_type"]}, "correct_umis": {"keys": ["config", "algorithm", "correct_umis"]}, "use_lowfreq_filter": {"keys": ["config", "algorithm", "use_lowfreq_filter"]}, "sample_barcodes": {"keys": ["config", "algorithm", "sample_barcodes"]}, "cellular_barcodes": {"keys": ["config", "algorithm", "cellular_barcodes"], "default": []}, "minimum_barcode_depth": {"keys": ["config", "algorithm", "minimum_barcode_depth"], "default": 100000}, "cellular_barcode_correction": {"keys": ["config", "algorithm", "cellular_barcode_correction"], "default": 1}, "demultiplexed": {"keys": ["config", "algorithm", "demultiplexed"]}, "kallisto_quant": {"keys": ["kallisto_quant"]}, "tximport": {"keys": ["tximport"], "default": None}, "summarized_experiment": {"keys": ["summarized_experiment"], "default": None}, "salmon_dir": {"keys": ["salmon_dir"]}, "salmon_fraglen_file": {"keys": ["salmon_fraglen_file"]}, "sailfish": {"keys": ["sailfish"]}, "sailfish_dir": {"keys": ["sailfish_dir"]}, "sailfish_transcript_tpm": {"keys": ["sailfish_transcript_tpm"]}, "sailfish_gene_tpm": {"keys": ["sailfish_gene_tpm"]}, "sample_callable": {"keys": ["regions", "sample_callable"]}, "coverage_interval": {"keys": ["config", "algorithm", "coverage_interval"]}, "coverage_depth_min": {"keys": ["config", "algorithm", "coverage_depth_min"], "default": 4}, "maxcov_downsample": {"keys": ["config", "algorithm", "maxcov_downsample"], "default": False}, "joint_group_size": {"keys": ["config", "algorithm", "joint_group_size"], "default": 200}, "arriba": {"keys": ["arriba"], "default": {}}, "report": {"keys": ["config", "algorithm", "report"]}, "work_bam": {"keys": ["work_bam"]}, "deduped_bam": {"keys": ["deduped_bam"]}, "align_bam": {"keys": ["align_bam"]}, "disc_bam": {"keys": ["work_bam_plus", "disc"]}, "sr_bam": {"keys": ["work_bam_plus", "sr"]}, "peddy_report": {"keys": ["peddy_report"]}, "antibody": {"keys": ["config", "algorithm", "antibody"], "default": ""}, "tools_off": {"keys": ["config", "algorithm", "tools_off"], "default": [], "always_list": True}, "tools_on": {"keys": ["config", "algorithm", "tools_on"], "default": [], "always_list": True}, "cwl_reporting": {"keys": ["config", "algorithm", "cwl_reporting"]}, } def get_background_cnv_reference(data, caller): out = tz.get_in(["config", "algorithm", "background", "cnv_reference"], data) if out: return out.get(caller) if isinstance(out, dict) else out def get_batches(data): batches = get_batch(data) if batches: if not isinstance(batches, (list, tuple)): batches = [batches] return batches return [] def get_input_sequence_files(data, default=None): """ returns the input sequencing files, these can be single or paired FASTQ files or BAM files """ if "files" not in data or data.get("files") is None: file1, file2 = None, None elif len(data["files"]) == 2: file1, file2 = data["files"] else: assert len(data["files"]) == 1, data["files"] file1, file2 = data["files"][0], None return file1, file2 def get_umi_consensus(data): """Retrieve UMI for consensus based preparation. We specify this either as a separate fastq file or embedded in the read name as `fastq_name`.` """ consensus_choices = (["fastq_name", "dragen"]) umi = tz.get_in(["config", "algorithm", "umi_type"], data) # don't run consensus UMI calling for scrna-seq if tz.get_in(["analysis"], data, "").lower() == "scrna-seq": return False if umi and (umi in consensus_choices or os.path.exists(umi)): assert tz.get_in(["config", "algorithm", "mark_duplicates"], data, True), \ "Using consensus UMI inputs requires marking duplicates" return umi def get_correct_umis(data): """ Do we need to correct UMIs with a whitelist? """ umi_whitelist = tz.get_in(["config", "algorithm", "correct_umis"], data) if umi_whitelist: return True else: return False def get_dexseq_gff(config, default=None): """ some older versions of the genomes have the DEXseq gff file as gff instead of gff3, so this handles that by looking for either one """ dexseq_gff = tz.get_in(tz.get_in(['dexseq_gff', 'keys'], LOOKUPS, {}), config, None) if not dexseq_gff: return None gtf_file = get_gtf_file(config) if gtf_file: base_dir = os.path.dirname(gtf_file) else: base_dir = os.path.dirname(dexseq_gff) base, _ = os.path.splitext(dexseq_gff) gff_file = os.path.join(base_dir, base + ".gff") if file_exists(gff_file): return gff_file gtf_file = os.path.join(base_dir, base + ".gff3") if file_exists(gtf_file): return gtf_file else: return None def getter(keys, global_default=None, always_list=False): def lookup(config, default=None): default = global_default if not default else default val = tz.get_in(keys, config, default) if always_list: if not val: val = [] elif not isinstance(val, (list, tuple)): val = [val] return val return lookup def setter(keys, checker): def update(config, value): if checker and not checker(value): logger.error("%s fails check %s." % (value, checker)) sys.exit(1) return tz.update_in(config, keys, lambda x: value, default=value) return update def is_setter(keys): def present(config): try: value = tz.get_in(keys, config, no_default=True) except: value = False return True if value else False return present """ generate the getter and setter functions but don't override any explicitly defined """ _g = globals() for k, v in LOOKUPS.items(): keys = v['keys'] getter_fn = 'get_' + k if getter_fn not in _g: _g["get_" + k] = getter(keys, v.get('default', None), v.get("always_list", False)) setter_fn = 'set_' + k if setter_fn not in _g: _g["set_" + k] = setter(keys, v.get('checker', None)) is_setter_fn = "is_set" + k if is_setter_fn not in _g: _g["is_set_" + k] = is_setter(keys) def sample_data_iterator(samples): """ for a list of samples, return the data dictionary of each sample """ for sample in samples: yield to_single_data(sample) def get_in_samples(samples, fn): """ for a list of samples, return the value of a global option """ for sample in samples: sample = to_single_data(sample) if fn(sample, None): return fn(sample) return None def set_in_samples(samples, fn, value): """ update a list of samples with a given value """ return [fn(x, value) for x in samples] def get_keys(lookup): """ return the keys used to look up a function in the datadict """ return tz.get_in((lookup, "keys"), LOOKUPS, None) def update_summary_qc(data, key, base=None, secondary=None): """ updates summary_qc, keyed by key. key is generally the program the quality control metrics came from. if key already exists, the specified base/secondary files are added as secondary files to the existing key, removing duplicates. stick files into summary_qc if you want them propagated forward and available for multiqc """ summary = deepish_copy(get_summary_qc(data, {})) files = [[base], [secondary], tz.get_in([key, "base"], summary, []), tz.get_in([key, "secondary"], summary, [])] files = list(set([x for x in flatten(files) if x])) base = tz.first(files) secondary = list(tz.drop(1, files)) if base and secondary: summary[key] = {"base": base, "secondary": secondary} elif base: summary[key] = {"base": base} data = set_summary_qc(data, summary) return data def has_variantcalls(data): """ returns True if the data dictionary is configured for variant calling """ analysis = get_analysis(data).lower() variant_pipeline = analysis.startswith(("standard", "variant", "variant2")) variantcaller = get_variantcaller(data) return variant_pipeline or variantcaller def get_algorithm_keys(): """ returns a list of all defined keys under the algorithm section """ keys = [] for k, v in LOOKUPS.items(): if not "algorithm" in v["keys"]: continue if k == v["keys"][2]: keys.append(k) return keys def get_data_from_sample(sample): """ get a data object from a single sample """ return sample[0] def get_samples_from_datalist(datalist): """ return a samples object from a list of data dicts """ return [[x] for x in datalist] bcbio-nextgen-1.2.9/bcbio/pipeline/disambiguate/000077500000000000000000000000001415626112400215725ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/pipeline/disambiguate/__init__.py000066400000000000000000000165641415626112400237170ustar00rootroot00000000000000"""Handle disambiguation of reads from a chimeric input, splitting by organism. Given specification of mixed input samples, splits a sample into multiple sub-samples for alignment to individual genomes, then runs third-party disambiguation scripts to reconcile. Uses disambiguation scripts contributed by AstraZeneca, incorporated into bcbio-nextgen: https://github.com/mjafin/disambiguate """ from __future__ import print_function import collections import copy import os from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline.disambiguate.run import main as disambiguate_main from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils, merge, run_info from bcbio.provenance import do from bcbio import bam import six def split(*items): """Split samples into all possible genomes for alignment. """ out = [] for data in [x[0] for x in items]: dis_orgs = data["config"]["algorithm"].get("disambiguate") if dis_orgs: if not data.get("disambiguate", None): data["disambiguate"] = {"genome_build": data["genome_build"], "base": True} out.append([data]) # handle the instance where a single organism is disambiguated if isinstance(dis_orgs, six.string_types): dis_orgs = [dis_orgs] for dis_org in dis_orgs: dis_data = copy.deepcopy(data) dis_data["disambiguate"] = {"genome_build": dis_org} dis_data["genome_build"] = dis_org dis_data["config"]["algorithm"]["effects"] = False dis_data = run_info.add_reference_resources(dis_data) out.append([dis_data]) else: out.append([data]) return out def resolve(items, run_parallel): """Combine aligned and split samples into final set of disambiguated reads. """ out = [] to_process = collections.defaultdict(list) for data in [x[0] for x in items]: if "disambiguate" in data: split_part = tuple([int(x) for x in data["align_split"].split("-")]) if data.get("combine") else None to_process[(dd.get_sample_name(data), split_part)].append(data) else: out.append([data]) if len(to_process) > 0: dis1 = run_parallel("run_disambiguate", [(xs, xs[0]["config"]) for xs in to_process.values()]) disambigs_by_name = collections.defaultdict(list) print(len(dis1)) for xs in dis1: assert len(xs) == 1 data = xs[0] disambigs_by_name[dd.get_sample_name(data)].append(data) dis2 = run_parallel("disambiguate_merge_extras", [(xs, xs[0]["config"]) for xs in disambigs_by_name.values()]) else: dis2 = [] return out + dis2 def merge_extras(items, config): """Merge extra disambiguated reads into a final BAM file. """ final = {} for extra_name in items[0]["disambiguate"].keys(): in_files = [] for data in items: in_files.append(data["disambiguate"][extra_name]) out_file = "%s-allmerged%s" % os.path.splitext(in_files[0]) if in_files[0].endswith(".bam"): merged_file = merge.merge_bam_files(in_files, os.path.dirname(out_file), items[0], out_file=out_file) else: assert extra_name == "summary", extra_name merged_file = _merge_summary(in_files, out_file, items[0]) final[extra_name] = merged_file out = [] for data in items: data["disambiguate"] = final out.append([data]) return out def _merge_summary(in_files, out_file, data): """Create one big summary file for disambiguation from multiple splits. """ if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for i, in_file in enumerate(in_files): with open(in_file) as in_handle: for j, line in enumerate(in_handle): if j == 0: if i == 0: out_handle.write(line) else: out_handle.write(line) return out_file def run(items, config): """Run third party disambiguation script, resolving into single set of calls. """ assert len(items) == 2, "Can only resolve two organism disambiguation" # check aligner, handling tophat/tophat2 distinctions aligner = config["algorithm"].get("aligner") aligner = "tophat" if aligner.startswith("tophat") else aligner assert aligner in ["bwa", "hisat2", "tophat", "star"], "Disambiguation only supported for bwa, hisat2, star and tophat alignments." if items[0]["disambiguate"].get("base"): data_a, data_b = items else: data_b, data_a = items work_bam_a = bam.sort(data_a["work_bam"], config, "queryname") work_bam_b = bam.sort(data_b["work_bam"], config, "queryname") if data_a.get("align_split"): base_dir = utils.safe_makedir(os.path.normpath(os.path.join(os.path.dirname(work_bam_a), os.pardir, os.pardir, "disambiguate_%s" % aligner))) out_dir = os.path.join(base_dir, "_".join([str(x) for x in data_a["align_split"].split("-")])) else: out_dir = os.path.normpath(os.path.join(os.path.dirname(work_bam_a), os.pardir, "disambiguate_%s" % aligner)) base_name = os.path.join(out_dir, os.path.splitext(os.path.basename(work_bam_a))[0]) summary_file = "%s_summary.txt" % base_name if not utils.file_exists(summary_file): with file_transaction(items[0], out_dir) as tx_out_dir: _run_cplusplus(work_bam_a, work_bam_b, tx_out_dir, aligner, os.path.basename(base_name), items) data_a["disambiguate"] = \ {data_b["genome_build"]: bam.sort("%s.disambiguatedSpeciesB.bam" % base_name, config), "%s-ambiguous" % data_a["genome_build"]: bam.sort("%s.ambiguousSpeciesA.bam" % base_name, config), "%s-ambiguous" % data_b["genome_build"]: bam.sort("%s.ambiguousSpeciesB.bam" % base_name, config), "summary": summary_file} data_a["work_bam"] = bam.sort("%s.disambiguatedSpeciesA.bam" % base_name, config) bam.index(dd.get_work_bam(data_a), data_a["config"]) return [[data_a]] def _run_python(work_bam_a, work_bam_b, out_dir, aligner, prefix, items): """Run python version of disambiguation """ Args = collections.namedtuple("Args", "A B output_dir intermediate_dir " "no_sort prefix aligner") args = Args(work_bam_a, work_bam_b, out_dir, out_dir, True, "", aligner) disambiguate_main(args) def _run_cplusplus(work_bam_a, work_bam_b, out_dir, aligner, prefix, items): """Run third party disambiguation script, resolving into single set of calls. """ ngs_disambiguate = config_utils.get_program("ngs_disambiguate", items[0]["config"]) cmd = [ngs_disambiguate, "--no-sort", "--prefix", prefix, "--aligner", aligner, "--output-dir", out_dir, work_bam_a, work_bam_b] do.run(cmd, "Disambiguation", items[0]) bcbio-nextgen-1.2.9/bcbio/pipeline/disambiguate/run.py000066400000000000000000000411361415626112400227550ustar00rootroot00000000000000#!/usr/bin/env python """ This is the main function to call for disambiguating between BAM files from two species that have alignments from the same source of fastq files. It is part of the explant RNA/DNA-Seq workflow where an informatics approach is used to distinguish between e.g. human and mouse or rat RNA/DNA reads. For reads that have aligned to both organisms, the functionality is based on comparing quality scores from either Tophat, Hisat2, STAR or BWA. Read name is used to collect all alignments for both mates (_1 and _2) and compared between the alignments from the two species. For Tophat (default, can be changed using option -a) and Hisat2, the sum of the flags XO, NM and NH is evaluated and the lowest sum wins the paired end reads. For equal scores, the reads are assigned as ambiguous. The alternative algorithm (STAR, bwa) disambiguates (for aligned reads) by tags AS (alignment score, higher better), followed by NM (edit distance, lower better). Code by Miika Ahdesmaki July-August 2013, based on original Perl implementation for Tophat by Zhongwu Lai. Included in bcbio-nextgen from: https://github.com/mjafin/disambiguate """ from __future__ import print_function import sys, re, pysam from array import array from os import path, makedirs from argparse import ArgumentParser, RawTextHelpFormatter # "natural comparison" for strings def nat_cmp(a, b): convert = lambda text: int(text) if text.isdigit() else text # lambda function to convert text to int if number present alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] # split string to piecewise strings and string numbers #return cmp(alphanum_key(a), alphanum_key(b)) # use internal cmp to compare piecewise strings and numbers return (alphanum_key(a) > alphanum_key(b))-(alphanum_key(a) < alphanum_key(b)) # read reads into a list object for as long as the read qname is constant (sorted file). Return the first read with new qname or None def read_next_reads(fileobject, listobject): qnamediff = False while not qnamediff: try: myRead=next(fileobject) except StopIteration: #print("5") return None # return None as the name of the new reads (i.e. no more new reads) if nat_cmp(myRead.qname, listobject[0].qname)==0: listobject.append(myRead) else: qnamediff = True return myRead # this is the first read with a new qname # disambiguate between two lists of reads def disambiguate(humanlist, mouselist, disambalgo): if disambalgo in ['tophat','hisat2']: dv = 2**13 # a high quality score to replace missing quality scores (no real quality score should be this high) sa = array('i',(dv for i in range(0,4))) # score array, with [human_1_QS, human_2_QS, mouse_1_QS, mouse_2_QS] for read in humanlist: if read.is_unmapped: continue QScore = read.opt('XO') + read.opt('NM') + read.opt('NH') # directionality (_1 or _2) d12 = 0 if read.is_read1 else 1 if sa[d12]>QScore: sa[d12]=QScore # update to lowest (i.e. 'best') quality score for read in mouselist: if read.is_unmapped: continue QScore = read.opt('XO') + read.opt('NM') + read.opt('NH') # directionality (_1 or _2) d12 = 2 if read.is_read1 else 3 if sa[d12]>QScore: sa[d12]=QScore # update to lowest (i.e. 'best') quality score if min(sa[0:2])==min(sa[2:4]) and max(sa[0:2])==max(sa[2:4]): # ambiguous return 0 elif min(sa[0:2]) < min(sa[2:4]) or min(sa[0:2]) == min(sa[2:4]) and max(sa[0:2]) < max(sa[2:4]): # assign to human return 1 else: # assign to mouse return -1 elif disambalgo.lower() in ('bwa', 'star'): dv = -2^13 # default value, low bwatags = ['AS', 'NM']# ,'XS'] # in order of importance (compared sequentially, not as a sum as for tophat) bwatagsigns = [1, -1]#,1] # for AS and XS higher is better. for NM lower is better, thus multiply by -1 AS = list() for x in range(0, len(bwatagsigns)): AS.append(array('i',(dv for i in range(0,4)))) # alignment score array, with [human_1_Score, human_2_Score, mouse_1_Score, mouse_2_Score] # for read in humanlist: if read.is_unmapped: continue # directionality (_1 or _2) d12 = 0 if read.is_read1 else 1 for x in range(0, len(bwatagsigns)): try: QScore = bwatagsigns[x]*read.opt(bwatags[x]) except KeyError: if bwatags[x] == 'NM': bwatags[x] = 'nM' # oddity of STAR elif bwatags[x] == 'AS': continue # this can happen for e.g. hg38 ALT-alignments (missing AS) QScore = bwatagsigns[x]*read.opt(bwatags[x]) if AS[x][d12] max(AS[x][2:4]) or max(AS[x][0:2]) == max(AS[x][2:4]) and min(AS[x][0:2]) > min(AS[x][2:4]): # assign to human return 1 elif max(AS[x][0:2]) < max(AS[x][2:4]) or max(AS[x][0:2]) == max(AS[x][2:4]) and min(AS[x][0:2]) < min(AS[x][2:4]): # assign to mouse return -1 return 0 # ambiguous else: print("Not implemented yet") sys.exit(2) #code def main(args): numhum = nummou = numamb = 0 #starttime = time.clock() # parse inputs humanfilename = args.A mousefilename = args.B samplenameprefix = args.prefix outputdir = args.output_dir intermdir = args.intermediate_dir disablesort = args.no_sort disambalgo = args.aligner supportedalgorithms = set(['tophat', 'hisat2', 'bwa', 'star']) # check existence of input BAM files if not (file_exists(humanfilename) and file_exists(mousefilename)): sys.stderr.write("\nERROR in disambiguate.py: Two existing input BAM files " "must be specified as positional arguments\n") sys.exit(2) if len(samplenameprefix) < 1: humanprefix = path.basename(humanfilename.replace(".bam","")) mouseprefix = path.basename(mousefilename.replace(".bam","")) else: if samplenameprefix.endswith(".bam"): samplenameprefix = samplenameprefix[0:samplenameprefix.rfind(".bam")] # the above if is not stricly necessary for this to work humanprefix = samplenameprefix mouseprefix = samplenameprefix samplenameprefix = None # clear variable if disambalgo.lower() not in supportedalgorithms: print(disambalgo+" is not a supported disambiguation scheme at the moment.") sys.exit(2) if disablesort: humanfilenamesorted = humanfilename # assumed to be sorted externally... mousefilenamesorted = mousefilename # assumed to be sorted externally... else: if not path.isdir(intermdir): makedirs(intermdir) humanfilenamesorted = path.join(intermdir,humanprefix+".speciesA.namesorted.bam") mousefilenamesorted = path.join(intermdir,mouseprefix+".speciesB.namesorted.bam") if not path.isfile(humanfilenamesorted): pysam.sort("-n","-m","2000000000",humanfilename,humanfilenamesorted.replace(".bam","")) if not path.isfile(mousefilenamesorted): pysam.sort("-n","-m","2000000000",mousefilename,mousefilenamesorted.replace(".bam","")) # read in human reads and form a dictionary myHumanFile = pysam.Samfile(humanfilenamesorted, "rb" ) myMouseFile = pysam.Samfile(mousefilenamesorted, "rb" ) if not path.isdir(outputdir): makedirs(outputdir) myHumanUniqueFile = pysam.Samfile(path.join(outputdir, humanprefix+".disambiguatedSpeciesA.bam"), "wb", template=myHumanFile) myHumanAmbiguousFile = pysam.Samfile(path.join(outputdir, humanprefix+".ambiguousSpeciesA.bam"), "wb", template=myHumanFile) myMouseUniqueFile = pysam.Samfile(path.join(outputdir, mouseprefix+".disambiguatedSpeciesB.bam"), "wb", template=myMouseFile) myMouseAmbiguousFile = pysam.Samfile(path.join(outputdir, mouseprefix+".ambiguousSpeciesB.bam"), "wb", template=myMouseFile) summaryFile = open(path.join(outputdir,humanprefix+'_summary.txt'),'w') #initialise try: nexthumread=next(myHumanFile) nextmouread=next(myMouseFile) except StopIteration: print("No reads in one or either of the input files") sys.exit(2) EOFmouse = EOFhuman = False prevHumID = '-+=RANDOMSTRING=+-' prevMouID = '-+=RANDOMSTRING=+-' while not EOFmouse&EOFhuman: while not (nat_cmp(nexthumread.qname,nextmouread.qname) == 0): # check order between current human and mouse qname (find a point where they're identical, i.e. in sync) while nat_cmp(nexthumread.qname,nextmouread.qname) > 0 and not EOFmouse: # mouse is "behind" human, output to mouse disambiguous myMouseUniqueFile.write(nextmouread) if not nextmouread.qname == prevMouID: nummou+=1 # increment mouse counter for unique only prevMouID = nextmouread.qname try: nextmouread=next(myMouseFile) except StopIteration: EOFmouse=True while nat_cmp(nexthumread.qname,nextmouread.qname) < 0 and not EOFhuman: # human is "behind" mouse, output to human disambiguous myHumanUniqueFile.write(nexthumread) if not nexthumread.qname == prevHumID: numhum+=1 # increment human counter for unique only prevHumID = nexthumread.qname try: nexthumread=next(myHumanFile) except StopIteration: EOFhuman=True if EOFhuman or EOFmouse: break # at this point the read qnames are identical and/or we've reached EOF humlist = list() moulist = list() if nat_cmp(nexthumread.qname,nextmouread.qname) == 0: humlist.append(nexthumread) nexthumread = read_next_reads(myHumanFile, humlist) # read more reads with same qname (the function modifies humlist directly) if nexthumread == None: EOFhuman = True moulist.append(nextmouread) nextmouread = read_next_reads(myMouseFile, moulist) # read more reads with same qname (the function modifies moulist directly) if nextmouread == None: EOFmouse = True # perform comparison to check mouse, human or ambiguous if len(moulist) > 0 and len(humlist) > 0: myAmbiguousness = disambiguate(humlist, moulist, disambalgo) if myAmbiguousness < 0: # mouse nummou+=1 # increment mouse counter for myRead in moulist: myMouseUniqueFile.write(myRead) elif myAmbiguousness > 0: # human numhum+=1 # increment human counter for myRead in humlist: myHumanUniqueFile.write(myRead) else: # ambiguous numamb+=1 # increment ambiguous counter for myRead in moulist: myMouseAmbiguousFile.write(myRead) for myRead in humlist: myHumanAmbiguousFile.write(myRead) if EOFhuman: #flush the rest of the mouse reads while not EOFmouse: myMouseUniqueFile.write(nextmouread) if not nextmouread.qname == prevMouID: nummou+=1 # increment mouse counter for unique only prevMouID = nextmouread.qname try: nextmouread=next(myMouseFile) except StopIteration: #print("3") EOFmouse=True if EOFmouse: #flush the rest of the human reads while not EOFhuman: myHumanUniqueFile.write(nexthumread) if not nexthumread.qname == prevHumID: numhum+=1 # increment human counter for unique only prevHumID = nexthumread.qname try: nexthumread=next(myHumanFile) except StopIteration: EOFhuman=True summaryFile.write("sample\tunique species A pairs\tunique species B pairs\tambiguous pairs\n") summaryFile.write(humanprefix+"\t"+str(numhum)+"\t"+str(nummou)+"\t"+str(numamb)+"\n") summaryFile.close() myHumanFile.close() myMouseFile.close() myHumanUniqueFile.close() myHumanAmbiguousFile.close() myMouseUniqueFile.close() myMouseAmbiguousFile.close() def file_exists(fname): """Check if a file exists and is non-empty. """ return path.exists(fname) and path.getsize(fname) > 0 if __name__ == "__main__": description = """ disambiguate.py disambiguates between two organisms that have alignments from the same source of fastq files. An example where this might be useful is as part of an explant RNA/DNA-Seq workflow where an informatics approach is used to distinguish between human and mouse RNA/DNA reads. For reads that have aligned to both organisms, the functionality is based on comparing quality scores from either Tophat of BWA. Read name is used to collect all alignments for both mates (_1 and _2) and compared between human and mouse alignments. For Tophat (default, can be changed using option -a), the sum of the tags XO, NM and NH is evaluated and the lowest sum wins the paired end reads. For equal scores (both mates, both species), the reads are assigned as ambiguous. The alternative algorithm (STAR, bwa) disambiguates (for aligned reads) by tags AS (alignment score, higher better), followed by NM (edit distance, lower better). The output directory will contain four files:\n ...disambiguatedSpeciesA.bam: Reads that could be assigned to species A ...disambiguatedSpeciesB.bam: Reads that could be assigned to species B ...ambiguousSpeciesA.bam: Reads aligned to species A that also aligned \n\tto B but could not be uniquely assigned to either ...ambiguousSpeciesB.bam: Reads aligned to species B that also aligned \n\tto A but could not be uniquely assigned to either ..._summary.txt: A summary of unique read names assigned to species A, B \n\tand ambiguous. Examples: disambiguate.py test/human.bam test/mouse.bam disambiguate.py -s mysample1 test/human.bam test/mouse.bam """ parser = ArgumentParser(description=description, formatter_class=RawTextHelpFormatter) parser.add_argument('A', help='Input BAM file for species A.') parser.add_argument('B', help='Input BAM file for species B.') parser.add_argument('-o', '--output-dir', default="disambres", help='Output directory.') parser.add_argument('-i', '--intermediate-dir', default="intermfiles", help='Location to store intermediate files') parser.add_argument('-d', '--no-sort', action='store_true', default=False, help='Disable BAM file sorting. Use this option if the ' 'files have already been name sorted.') parser.add_argument('-s', '--prefix', default='', help='A prefix (e.g. sample name) to use for the output ' 'BAM files. If not provided, the input BAM file prefix ' 'will be used. Do not include .bam in the prefix.') parser.add_argument('-a', '--aligner', default='tophat', choices=('tophat', 'hisat2', 'bwa', 'star'), help='The aligner used to generate these reads. Some ' 'aligners set different tags.') args = parser.parse_args() main(args) bcbio-nextgen-1.2.9/bcbio/pipeline/fastq.py000066400000000000000000000133761415626112400206360ustar00rootroot00000000000000"""Pipeline utilities to retrieve FASTQ formatted files for processing. """ import os import shutil from bcbio import bam, broad, utils from bcbio.bam import fastq from bcbio.distributed import objectstore from bcbio.pipeline import alignment from bcbio.pipeline import datadict as dd from bcbio.utils import file_exists, safe_makedir, splitext_plus from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction from bcbio.ngsalign import alignprep def get_fastq_files(data): """Retrieve fastq files for the given lane, ready to process. """ assert "files" in data, "Did not find `files` in input; nothing to process" ready_files = [] should_gzip = True # Bowtie does not accept gzipped fastq if 'bowtie' in data['reference'].keys(): should_gzip = False for fname in data["files"]: if fname.endswith(".bam"): if _pipeline_needs_fastq(data["config"], data): ready_files = convert_bam_to_fastq(fname, data["dirs"]["work"], data, data["dirs"], data["config"]) else: ready_files = [fname] elif objectstore.is_remote(fname): ready_files.append(fname) # Trimming does quality conversion, so if not doing that, do an explicit conversion elif not(dd.get_trim_reads(data)) and dd.get_quality_format(data) != "standard": out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "fastq_convert")) ready_files.append(fastq.groom(fname, data, out_dir=out_dir)) else: ready_files.append(fname) ready_files = [x for x in ready_files if x is not None] if should_gzip: out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "fastq")) ready_files = [_gzip_fastq(x, out_dir) for x in ready_files] for in_file in ready_files: if not objectstore.is_remote(in_file): assert os.path.exists(in_file), "%s does not exist." % in_file return ready_files def _gzip_fastq(in_file, out_dir=None): """ gzip a fastq file if it is not already gzipped, handling conversion from bzip to gzipped files """ if fastq.is_fastq(in_file) and not objectstore.is_remote(in_file): if utils.is_bzipped(in_file): return _bzip_gzip(in_file, out_dir) elif not utils.is_gzipped(in_file): if out_dir: gzipped_file = os.path.join(out_dir, os.path.basename(in_file) + ".gz") else: gzipped_file = in_file + ".gz" if file_exists(gzipped_file): return gzipped_file message = "gzipping {in_file} to {gzipped_file}.".format( in_file=in_file, gzipped_file=gzipped_file) with file_transaction(gzipped_file) as tx_gzipped_file: do.run("gzip -c {in_file} > {tx_gzipped_file}".format(**locals()), message) return gzipped_file return in_file def _bzip_gzip(in_file, out_dir=None): """ convert from bz2 to gz """ if not utils.is_bzipped(in_file): return in_file base, _ = os.path.splitext(in_file) if out_dir: gzipped_file = os.path.join(out_dir, os.path.basename(base) + ".gz") else: gzipped_file = base + ".gz" if (fastq.is_fastq(base) and not objectstore.is_remote(in_file)): if file_exists(gzipped_file): return gzipped_file message = "gzipping {in_file} to {gzipped_file}.".format( in_file=in_file, gzipped_file=gzipped_file) with file_transaction(gzipped_file) as tx_gzipped_file: do.run("bunzip2 -c {in_file} | gzip > {tx_gzipped_file}".format(**locals()), message) return gzipped_file return in_file def _pipeline_needs_fastq(config, data): """Determine if the pipeline can proceed with a BAM file, or needs fastq conversion. """ aligner = config["algorithm"].get("aligner") support_bam = aligner in alignment.metadata.get("support_bam", []) return aligner and not support_bam def convert_bam_to_fastq(in_file, work_dir, data, dirs, config): """Convert BAM input file into FASTQ files. """ return alignprep.prep_fastq_inputs([in_file], data) def merge(files, out_file, config): """merge smartly fastq files. It recognizes paired fastq files.""" pair1 = [fastq_file[0] for fastq_file in files] if len(files[0]) > 1: path = splitext_plus(out_file) pair1_out_file = path[0] + "_R1" + path[1] pair2 = [fastq_file[1] for fastq_file in files] pair2_out_file = path[0] + "_R2" + path[1] _merge_list_fastqs(pair1, pair1_out_file, config) _merge_list_fastqs(pair2, pair2_out_file, config) return [pair1_out_file, pair2_out_file] else: return _merge_list_fastqs(pair1, out_file, config) def _merge_list_fastqs(files, out_file, config): """merge list of fastq files into one""" if not all(map(fastq.is_fastq, files)): raise ValueError("Not all of the files to merge are fastq files: %s " % (files)) assert all(map(utils.file_exists, files)), ("Not all of the files to merge " "exist: %s" % (files)) if not file_exists(out_file): files = [_gzip_fastq(fn) for fn in files] if len(files) == 1: if "remove_source" in config and config["remove_source"]: shutil.move(files[0], out_file) else: os.symlink(files[0], out_file) return out_file with file_transaction(out_file) as file_txt_out: files_str = " ".join(list(files)) cmd = "cat {files_str} > {file_txt_out}".format(**locals()) do.run(cmd, "merge fastq files %s" % files) return out_file bcbio-nextgen-1.2.9/bcbio/pipeline/genome.py000066400000000000000000000324471415626112400207720ustar00rootroot00000000000000"""Read genome build configurations from Galaxy *.loc and bcbio-nextgen resource files. """ from six.moves import configparser import glob import os import sys from xml.etree import ElementTree import six import toolz as tz import yaml from bcbio import utils from bcbio.cwl import cwlutils from bcbio.distributed import objectstore from bcbio.log import logger from bcbio.ngsalign import star from bcbio.pipeline import alignment from bcbio.provenance import do from bcbio.rnaseq import gtf # ## bcbio-nextgen genome resource files def get_resources(genome, ref_file, data): """Retrieve genome information from a genome-references.yaml file. """ base_dir = os.path.normpath(os.path.dirname(ref_file)) resource_file = os.path.join(base_dir, "%s-resources.yaml" % genome.replace("-test", "")) if not os.path.exists(resource_file): raise IOError("Did not find resource file for %s: %s\n" "To update bcbio_nextgen.py with genome resources for standard builds, run:\n" "bcbio_nextgen.py upgrade -u skip" % (genome, resource_file)) with open(resource_file) as in_handle: resources = yaml.safe_load(in_handle) def resource_file_path(x): if isinstance(x, six.string_types) and os.path.exists(os.path.join(base_dir, x)): return os.path.normpath(os.path.join(base_dir, x)) return x cleaned = utils.dictapply(resources, resource_file_path) return ensure_annotations(cleaned, data) def add_required_resources(resources): """Add default or empty values for required resources referenced in CWL """ required = [["variation", "cosmic"], ["variation", "clinvar"], ["variation", "dbsnp"], ["variation", "lcr"], ["variation", "polyx"], ["variation", "encode_blacklist"], ["variation", "gc_profile"], ["variation", "germline_het_pon"], ["variation", "train_hapmap"], ["variation", "train_indels"], ["variation", "editing"], ["variation", "exac"], ["variation", "esp"], ["variation", "gnomad_exome"], ["variation", "1000g"], ["aliases", "human"]] for key in required: if not tz.get_in(key, resources): resources = tz.update_in(resources, key, lambda x: None) return resources def ensure_annotations(resources, data): """Prepare any potentially missing annotations for downstream processing in a local directory. """ transcript_gff = tz.get_in(["rnaseq", "transcripts"], resources) if transcript_gff and utils.file_exists(transcript_gff): out_dir = os.path.join(tz.get_in(["dirs", "work"], data), "inputs", "data", "annotations") resources["rnaseq"]["gene_bed"] = gtf.gtf_to_bed(transcript_gff, out_dir) return resources # ## Utilities def abs_file_paths(xs, base_dir=None, ignore_keys=None, fileonly_keys=None, cur_key=None, do_download=True): """Normalize any file paths found in a subdirectory of configuration input. base_dir -- directory to normalize relative paths to ignore_keys -- algorithm key names to ignore normalize for (keywords, not files/directories) fileonly_keys -- algorithm key names to only expand files (not directories) cur_key -- current key when calling recursively """ ignore_keys = set([]) if ignore_keys is None else set(ignore_keys) fileonly_keys = set([]) if fileonly_keys is None else set(fileonly_keys) if base_dir is None: base_dir = os.getcwd() orig_dir = os.getcwd() os.chdir(base_dir) input_dir = os.path.join(base_dir, "inputs") if isinstance(xs, dict): out = {} for k, v in xs.items(): if k not in ignore_keys and v and isinstance(v, six.string_types): if v.lower() == "none": out[k] = None else: out[k] = abs_file_paths(v, base_dir, ignore_keys, fileonly_keys, k, do_download=do_download) elif isinstance(v, (list, tuple)): out[k] = [abs_file_paths(x, base_dir, ignore_keys, fileonly_keys, k, do_download=do_download) for x in v] else: out[k] = v elif isinstance(xs, six.string_types): if os.path.exists(xs) or (do_download and objectstore.is_remote(xs)): dl = objectstore.download(xs, input_dir) if dl and cur_key not in ignore_keys and not (cur_key in fileonly_keys and not os.path.isfile(dl)): out = os.path.normpath(os.path.join(base_dir, dl)) else: out = xs else: out = xs else: out = xs os.chdir(orig_dir) return out # ## Galaxy integration -- *.loc files def _get_galaxy_loc_file(name, galaxy_dt, ref_dir, galaxy_base): """Retrieve Galaxy *.loc file for the given reference/aligner name. First tries to find an aligner specific *.loc file. If not defined or does not exist, then we need to try and remap it from the default reference file """ if "file" in galaxy_dt and os.path.exists(os.path.join(galaxy_base, galaxy_dt["file"])): loc_file = os.path.join(galaxy_base, galaxy_dt["file"]) need_remap = False elif alignment.TOOLS[name].galaxy_loc_file is None: loc_file = os.path.join(ref_dir, alignment.BASE_LOCATION_FILE) need_remap = True else: loc_file = os.path.join(ref_dir, alignment.TOOLS[name].galaxy_loc_file) need_remap = False if not os.path.exists(loc_file): loc_file = os.path.join(ref_dir, alignment.BASE_LOCATION_FILE) need_remap = True return loc_file, need_remap def _galaxy_loc_iter(loc_file, galaxy_dt, need_remap=False): """Iterator returning genome build and references from Galaxy *.loc file. """ if "column" in galaxy_dt: dbkey_i = galaxy_dt["column"].index("dbkey") path_i = galaxy_dt["column"].index("path") else: dbkey_i = None if os.path.exists(loc_file): with open(loc_file) as in_handle: for line in in_handle: if line.strip() and not line.startswith("#"): parts = [x.strip() for x in line.strip().split("\t")] # Detect and report spaces instead of tabs if len(parts) == 1: parts = [x.strip() for x in line.strip().split(" ") if x.strip()] if len(parts) > 1: raise IOError("Galaxy location file uses spaces instead of " "tabs to separate fields: %s" % loc_file) if dbkey_i is not None and not need_remap: dbkey = parts[dbkey_i] cur_ref = parts[path_i] else: if parts[0] == "index": parts = parts[1:] dbkey = parts[0] cur_ref = parts[-1] yield (dbkey, cur_ref) def _get_ref_from_galaxy_loc(name, genome_build, loc_file, galaxy_dt, need_remap, galaxy_config, data): """Retrieve reference genome file from Galaxy *.loc file. Reads from tool_data_table_conf.xml information for the index if it exists, otherwise uses heuristics to find line based on most common setups. """ refs = [ref for dbkey, ref in _galaxy_loc_iter(loc_file, galaxy_dt, need_remap) if dbkey == genome_build] remap_fn = alignment.TOOLS[name].remap_index_fn need_remap = remap_fn is not None if len(refs) == 0: raise ValueError("Did not find genome build %s in bcbio installation: %s" % (genome_build, os.path.normpath(loc_file))) else: cur_ref = refs[-1] # Find genome directory and check for packed wf tarballs cur_ref_norm = os.path.normpath(utils.add_full_path(cur_ref, galaxy_config["tool_data_path"])) base_dir_i = cur_ref_norm.find("/%s/" % genome_build) base_dir = os.path.join(cur_ref_norm[:base_dir_i], genome_build) for tarball in glob.glob(os.path.join(base_dir, "*-wf.tar.gz")): cwlutils.unpack_tarballs(tarball, {"dirs": {"work": base_dir}}, use_subdir=False) if need_remap: assert remap_fn is not None, "%s requires remapping function from base location file" % name cur_ref = os.path.normpath(utils.add_full_path(cur_ref, galaxy_config["tool_data_path"])) cur_ref = remap_fn(os.path.abspath(cur_ref)) return cur_ref def _get_galaxy_tool_info(galaxy_base): """Retrieve Galaxy tool-data information from defaults or galaxy config file. """ ini_file = os.path.join(galaxy_base, "universe_wsgi.ini") info = {"tool_data_table_config_path": os.path.join(galaxy_base, "tool_data_table_conf.xml"), "tool_data_path": os.path.join(galaxy_base, "tool-data")} config = configparser.ConfigParser() config.read(ini_file) if "app:main" in config.sections(): for option in config.options("app:main"): if option in info: info[option] = os.path.join(galaxy_base, config.get("app:main", option)) return info def _get_galaxy_data_table(name, dt_config_file): """Parse data table config file for details on tool *.loc location and columns. """ out = {} if os.path.exists(dt_config_file): tdtc = ElementTree.parse(dt_config_file) for t in tdtc.iter("table"): if t.attrib.get("name", "") in [name, "%s_indexes" % name]: out["column"] = [x.strip() for x in t.find("columns").text.split(",")] out["file"] = t.find("file").attrib.get("path", "") return out def get_refs(genome_build, aligner, galaxy_base, data): """Retrieve the reference genome file location from galaxy configuration. """ out = {} name_remap = {"samtools": "fasta"} if genome_build: galaxy_config = _get_galaxy_tool_info(galaxy_base) for name in [x for x in ("samtools", aligner) if x]: galaxy_dt = _get_galaxy_data_table(name, galaxy_config["tool_data_table_config_path"]) loc_file, need_remap = _get_galaxy_loc_file(name, galaxy_dt, galaxy_config["tool_data_path"], galaxy_base) cur_ref = _get_ref_from_galaxy_loc(name, genome_build, loc_file, galaxy_dt, need_remap, galaxy_config, data) base = os.path.normpath(utils.add_full_path(cur_ref, galaxy_config["tool_data_path"])) # Expand directories unless we are an aligner like minimap2 that uses the seq directory if os.path.isdir(base) and not (need_remap and os.path.basename(base) == "seq"): indexes = sorted(glob.glob(os.path.join(base, "*"))) elif name != "samtools": indexes = sorted(glob.glob("%s*" % utils.splitext_plus(base)[0])) else: indexes = [] name = name_remap.get(name, name) out[name] = {} if os.path.exists(base) and os.path.isfile(base): out[name]["base"] = base if indexes: out[name]["indexes"] = indexes # For references, add compressed inputs and indexes if they exist if name == "fasta" and "base" in out[name] and os.path.exists(out[name]["base"] + ".gz"): indexes = [out[name]["base"] + ".gz.fai", out[name]["base"] + ".gz.gzi", utils.splitext_plus(out[name]["base"])[0] + ".dict"] out[name + "gz"] = {"base": out[name]["base"] + ".gz", "indexes": [x for x in indexes if os.path.exists(x)]} # add additional indices relative to the base if tz.get_in(["fasta", "base"], out): ref_dir, ref_filebase = os.path.split(out["fasta"]["base"]) rtg_dir = os.path.normpath(os.path.join(ref_dir, os.path.pardir, "rtg", "%s.sdf" % (os.path.splitext(ref_filebase)[0]))) out["rtg"] = {"base": os.path.join(rtg_dir, "mainIndex"), "indexes": [x for x in glob.glob(os.path.join(rtg_dir, "*")) if not x.endswith("/mainIndex")]} twobit = os.path.normpath(os.path.join(ref_dir, os.path.pardir, "ucsc", "%s.2bit" % (os.path.splitext(ref_filebase)[0]))) if os.path.exists(twobit): out["twobit"] = twobit return out def get_builds(galaxy_base): """Retrieve configured genome builds and reference files, using Galaxy configuration files. Allows multiple dbkey specifications in the same file, using the most recently added. """ name = "samtools" galaxy_config = _get_galaxy_tool_info(galaxy_base) galaxy_dt = _get_galaxy_data_table(name, galaxy_config["tool_data_table_config_path"]) loc_file, need_remap = _get_galaxy_loc_file(name, galaxy_dt, galaxy_config["tool_data_path"], galaxy_base) assert not need_remap, "Should not need to remap reference files" fnames = {} for dbkey, fname in _galaxy_loc_iter(loc_file, galaxy_dt): fnames[dbkey] = fname out = [] for dbkey in sorted(fnames.keys()): out.append((dbkey, fnames[dbkey])) return out bcbio-nextgen-1.2.9/bcbio/pipeline/main.py000066400000000000000000000660751415626112400204500ustar00rootroot00000000000000"""Main entry point for distributed next-gen sequencing pipelines. Handles running the full pipeline based on instructions """ from __future__ import print_function from collections import defaultdict import copy import os import sys import resource import tempfile import toolz as tz from bcbio import log, heterogeneity, hla, structural, utils from bcbio.cwl.inspect import initialize_watcher from bcbio.distributed import prun from bcbio.distributed.transaction import tx_tmpdir from bcbio.log import logger, DEFAULT_LOG_DIR from bcbio.ngsalign import alignprep from bcbio.pipeline import datadict as dd from bcbio.pipeline import (archive, config_utils, disambiguate, region, run_info, qcsummary, rnaseq) from bcbio.provenance import profile, system from bcbio.variation import (ensemble, genotype, population, validate, joint, peddy) from bcbio.chipseq import peaks, atac def run_main(workdir, config_file=None, fc_dir=None, run_info_yaml=None, parallel=None, workflow=None): """Run variant analysis, handling command line options. """ # Set environment to standard to use periods for decimals and avoid localization locale_to_use = utils.get_locale() os.environ["LC_ALL"] = locale_to_use os.environ["LC"] = locale_to_use os.environ["LANG"] = locale_to_use workdir = utils.safe_makedir(os.path.abspath(workdir)) os.chdir(workdir) config, config_file = config_utils.load_system_config(config_file, workdir) parallel = log.create_base_logger(config, parallel) log.setup_local_logging(config, parallel) logger.info(f"System YAML configuration: {os.path.abspath(config_file)}.") logger.info(f"Locale set to {locale_to_use}.") if config.get("log_dir", None) is None: config["log_dir"] = os.path.join(workdir, DEFAULT_LOG_DIR) if parallel["type"] in ["local", "clusterk"]: _setup_resources() _run_toplevel(config, config_file, workdir, parallel, fc_dir, run_info_yaml) elif parallel["type"] == "ipython": assert parallel["scheduler"] is not None, "IPython parallel requires a specified scheduler (-s)" if parallel["scheduler"] != "sge": assert parallel["queue"] is not None, "IPython parallel requires a specified queue (-q)" elif not parallel["queue"]: parallel["queue"] = "" _run_toplevel(config, config_file, workdir, parallel, fc_dir, run_info_yaml) else: raise ValueError("Unexpected type of parallel run: %s" % parallel["type"]) def _setup_resources(): """Attempt to increase resource limits up to hard limits. This allows us to avoid out of file handle limits where we can move beyond the soft limit up to the hard limit. """ target_procs = 10240 cur_proc, max_proc = resource.getrlimit(resource.RLIMIT_NPROC) target_proc = min(max_proc, target_procs) if max_proc > 0 else target_procs resource.setrlimit(resource.RLIMIT_NPROC, (max(cur_proc, target_proc), max_proc)) cur_hdls, max_hdls = resource.getrlimit(resource.RLIMIT_NOFILE) target_hdls = min(max_hdls, target_procs) if max_hdls > 0 else target_procs resource.setrlimit(resource.RLIMIT_NOFILE, (max(cur_hdls, target_hdls), max_hdls)) def _run_toplevel(config, config_file, work_dir, parallel, fc_dir=None, run_info_yaml=None): """ Run toplevel analysis, processing a set of input files. config_file -- Main YAML configuration file with system parameters fc_dir -- Directory of fastq files to process run_info_yaml -- YAML configuration file specifying inputs to process """ dirs = run_info.setup_directories(work_dir, fc_dir, config, config_file) config_file = os.path.join(dirs["config"], os.path.basename(config_file)) pipelines, config = _pair_samples_with_pipelines(run_info_yaml, config) system.write_info(dirs, parallel, config) with tx_tmpdir(config if parallel.get("type") == "local" else None) as tmpdir: tempfile.tempdir = tmpdir for pipeline, samples in pipelines.items(): for xs in pipeline(config, run_info_yaml, parallel, dirs, samples): pass # ## Generic pipeline framework def _wres(parallel, progs, fresources=None, ensure_mem=None): """Add resource information to the parallel environment on required programs and files. Enables spinning up required machines and operating in non-shared filesystem environments. progs -- Third party tools used in processing fresources -- Required file-based resources needed. These will be transferred on non-shared filesystems. ensure_mem -- Dictionary of required minimum memory for programs used. Ensures enough memory gets allocated on low-core machines. """ parallel = copy.deepcopy(parallel) parallel["progs"] = progs if fresources: parallel["fresources"] = fresources if ensure_mem: parallel["ensure_mem"] = ensure_mem return parallel def variant2pipeline(config, run_info_yaml, parallel, dirs, samples): ## Alignment and preparation requiring the entire input file (multicore cluster) # Assign GATK supplied memory if required for post-process recalibration align_programs = ["aligner", "samtools", "sambamba"] if any(tz.get_in(["algorithm", "recalibrate"], utils.to_single_data(d)) in [True, "gatk"] for d in samples): align_programs.append("gatk") with prun.start(_wres(parallel, align_programs, (["reference", "fasta"], ["reference", "aligner"], ["files"])), samples, config, dirs, "multicore", multiplier=alignprep.parallel_multiplier(samples)) as run_parallel: with profile.report("organize samples", dirs): samples = run_parallel("organize_samples", [[dirs, config, run_info_yaml, [x[0]["description"] for x in samples]]]) with profile.report("alignment preparation", dirs): samples = run_parallel("prep_align_inputs", samples) samples = run_parallel("disambiguate_split", [samples]) with profile.report("alignment", dirs): samples = run_parallel("process_alignment", samples) samples = disambiguate.resolve(samples, run_parallel) samples = alignprep.merge_split_alignments(samples, run_parallel) with profile.report("callable regions", dirs): samples = run_parallel("prep_samples", [samples]) samples = run_parallel("postprocess_alignment", samples) samples = run_parallel("combine_sample_regions", [samples]) samples = run_parallel("calculate_sv_bins", [samples]) samples = run_parallel("calculate_sv_coverage", samples) samples = run_parallel("normalize_sv_coverage", [samples]) samples = region.clean_sample_data(samples) with profile.report("hla typing", dirs): samples = hla.run(samples, run_parallel) ## Variant calling on sub-regions of the input file (full cluster) with prun.start(_wres(parallel, ["gatk", "picard", "variantcaller"]), samples, config, dirs, "full", multiplier=region.get_max_counts(samples), max_multicore=1) as run_parallel: with profile.report("alignment post-processing", dirs): samples = region.parallel_prep_region(samples, run_parallel) with profile.report("variant calling", dirs): samples = genotype.parallel_variantcall_region(samples, run_parallel) with profile.report("joint squaring off/backfilling", dirs): samples = joint.square_off(samples, run_parallel) ## Finalize variants, BAMs and population databases (per-sample multicore cluster) with prun.start(_wres(parallel, ["gatk", "gatk-vqsr", "snpeff", "bcbio_variation", "gemini", "samtools", "fastqc", "sambamba", "bcbio-variation-recall", "qsignature", "svcaller", "kraken", "preseq"]), samples, config, dirs, "multicore2", multiplier=structural.parallel_multiplier(samples)) as run_parallel: with profile.report("variant post-processing", dirs): samples = run_parallel("postprocess_variants", samples) samples = run_parallel("split_variants_by_sample", samples) with profile.report("prepped BAM merging", dirs): samples = region.delayed_bamprep_merge(samples, run_parallel) with profile.report("validation", dirs): samples = run_parallel("compare_to_rm", samples) samples = genotype.combine_multiple_callers(samples) with profile.report("ensemble calling", dirs): samples = ensemble.combine_calls_parallel(samples, run_parallel) with profile.report("validation summary", dirs): samples = validate.summarize_grading(samples) with profile.report("structural variation", dirs): samples = structural.run(samples, run_parallel, "initial") with profile.report("structural variation", dirs): samples = structural.run(samples, run_parallel, "standard") with profile.report("structural variation ensemble", dirs): samples = structural.run(samples, run_parallel, "ensemble") with profile.report("structural variation validation", dirs): samples = run_parallel("validate_sv", samples) with profile.report("heterogeneity", dirs): samples = heterogeneity.run(samples, run_parallel) with profile.report("population database", dirs): samples = population.prep_db_parallel(samples, run_parallel) # after SV calling and SNV merging with profile.report("create CNV PON", dirs): samples = structural.create_cnv_pon(samples) with profile.report("peddy check", dirs): samples = peddy.run_peddy_parallel(samples, run_parallel) with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) with profile.report("archive", dirs): samples = archive.compress(samples, run_parallel) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for sample in samples: run_parallel("upload_samples_project", [sample]) logger.info("Timing: finished") return samples def _debug_samples(i, samples): print("---", i, len(samples)) for sample in (utils.to_single_data(x) for x in samples): print(" ", sample["description"], sample.get("region"), \ utils.get_in(sample, ("config", "algorithm", "variantcaller")), \ utils.get_in(sample, ("config", "algorithm", "jointcaller")), \ utils.get_in(sample, ("metadata", "batch")), \ [x.get("variantcaller") for x in sample.get("variants", [])], \ sample.get("work_bam"), \ sample.get("vrn_file")) def standardpipeline(config, run_info_yaml, parallel, dirs, samples): ## Alignment and preparation requiring the entire input file (multicore cluster) with prun.start(_wres(parallel, ["aligner", "samtools", "sambamba"]), samples, config, dirs, "multicore") as run_parallel: with profile.report("organize samples", dirs): samples = run_parallel("organize_samples", [[dirs, config, run_info_yaml, [x[0]["description"] for x in samples]]]) with profile.report("alignment", dirs): samples = run_parallel("process_alignment", samples) with profile.report("callable regions", dirs): samples = run_parallel("prep_samples", [samples]) samples = run_parallel("postprocess_alignment", samples) samples = run_parallel("combine_sample_regions", [samples]) samples = region.clean_sample_data(samples) ## Quality control with prun.start(_wres(parallel, ["fastqc", "qsignature", "kraken", "gatk", "samtools", "preseq"]), samples, config, dirs, "multicore2") as run_parallel: with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for sample in samples: run_parallel("upload_samples_project", [sample]) logger.info("Timing: finished") return samples def rnaseqpipeline(config, run_info_yaml, parallel, dirs, samples): samples = rnaseq_prep_samples(config, run_info_yaml, parallel, dirs, samples) with prun.start(_wres(parallel, ["aligner", "picard", "samtools"], ensure_mem={"tophat": 10, "tophat2": 10, "star": 2, "hisat2": 8}), samples, config, dirs, "alignment", multiplier=alignprep.parallel_multiplier(samples)) as run_parallel: with profile.report("alignment", dirs): samples = run_parallel("disambiguate_split", [samples]) samples = run_parallel("process_alignment", samples) with prun.start(_wres(parallel, ["samtools", "cufflinks"]), samples, config, dirs, "rnaseqcount") as run_parallel: with profile.report("disambiguation", dirs): samples = disambiguate.resolve(samples, run_parallel) with profile.report("transcript assembly", dirs): samples = rnaseq.assemble_transcripts(run_parallel, samples) with profile.report("estimate expression (threaded)", dirs): samples = rnaseq.quantitate_expression_parallel(samples, run_parallel) with prun.start(_wres(parallel, ["dexseq", "express"]), samples, config, dirs, "rnaseqcount-singlethread", max_multicore=1) as run_parallel: with profile.report("estimate expression (single threaded)", dirs): samples = rnaseq.quantitate_expression_noparallel(samples, run_parallel) samples = rnaseq.combine_files(samples) with prun.start(_wres(parallel, ["gatk", "vardict"]), samples, config, dirs, "rnaseq-variation") as run_parallel: with profile.report("RNA-seq variant calling", dirs): samples = rnaseq.rnaseq_variant_calling(samples, run_parallel) with prun.start(_wres(parallel, ["samtools", "fastqc", "qualimap", "kraken", "gatk", "preseq"], ensure_mem={"qualimap": 4}), samples, config, dirs, "qc") as run_parallel: with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) with profile.report("create SummarizedExperiment object", dirs): samples = rnaseq.load_summarizedexperiment(samples) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for sample in samples: run_parallel("upload_samples_project", [sample]) with profile.report("bcbioRNAseq loading", dirs): tools_on = dd.get_in_samples(samples, dd.get_tools_on) bcbiornaseq_on = tools_on and "bcbiornaseq" in tools_on if bcbiornaseq_on: if len(samples) < 3: logger.warn("bcbioRNASeq needs at least three samples total, skipping.") elif len(samples) > 100: logger.warn("Over 100 samples, skipping bcbioRNASeq.") else: run_parallel("run_bcbiornaseqload", [sample]) logger.info("Timing: finished") return samples def fastrnaseqpipeline(config, run_info_yaml, parallel, dirs, samples): samples = rnaseq_prep_samples(config, run_info_yaml, parallel, dirs, samples) ww = initialize_watcher(samples) with prun.start(_wres(parallel, ["samtools"]), samples, config, dirs, "fastrnaseq") as run_parallel: with profile.report("fastrnaseq", dirs): samples = rnaseq.fast_rnaseq(samples, run_parallel) ww.report("fastrnaseq", samples) samples = rnaseq.combine_files(samples) with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) ww.report("qcsummary", samples) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for samples in samples: run_parallel("upload_samples_project", [samples]) logger.info("Timing: finished") return samples def singlecellrnaseqpipeline(config, run_info_yaml, parallel, dirs, samples): samples = rnaseq_prep_samples(config, run_info_yaml, parallel, dirs, samples) with prun.start(_wres(parallel, ["samtools", "rapmap"]), samples, config, dirs, "singlecell-rnaseq") as run_parallel: with profile.report("singlecell-rnaseq", dirs): samples = rnaseq.singlecell_rnaseq(samples, run_parallel) with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for samples in samples: run_parallel("upload_samples_project", [samples]) logger.info("Timing: finished") return samples def smallrnaseqpipeline(config, run_info_yaml, parallel, dirs, samples): # causes a circular import at the top level from bcbio.srna.group import report as srna_report samples = rnaseq_prep_samples(config, run_info_yaml, parallel, dirs, samples) with prun.start(_wres(parallel, ["aligner", "picard", "samtools"], ensure_mem={"bowtie": 8, "bowtie2": 8, "star": 2}), [samples[0]], config, dirs, "alignment") as run_parallel: with profile.report("prepare", dirs): samples = run_parallel("seqcluster_prepare", [samples]) with profile.report("seqcluster alignment", dirs): samples = run_parallel("srna_alignment", [samples]) with prun.start(_wres(parallel, ["aligner", "picard", "samtools"], ensure_mem={"tophat": 10, "tophat2": 10, "star": 2, "hisat2": 8}), samples, config, dirs, "alignment_samples", multiplier=alignprep.parallel_multiplier(samples)) as run_parallel: with profile.report("alignment", dirs): samples = run_parallel("process_alignment", samples) with prun.start(_wres(parallel, ["picard", "miraligner"]), samples, config, dirs, "annotation") as run_parallel: with profile.report("small RNA annotation", dirs): samples = run_parallel("srna_annotation", samples) with prun.start(_wres(parallel, ["seqcluster", "mirge"], ensure_mem={"seqcluster": 8}), [samples[0]], config, dirs, "cluster") as run_parallel: with profile.report("cluster", dirs): samples = run_parallel("seqcluster_cluster", [samples]) with prun.start(_wres(parallel, ["picard", "fastqc"]), samples, config, dirs, "qc") as run_parallel: with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) with profile.report("report", dirs): srna_report(samples) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for sample in samples: run_parallel("upload_samples_project", [sample]) return samples def chipseqpipeline(config, run_info_yaml, parallel, dirs, samples): with prun.start(_wres(parallel, ["aligner", "picard"]), samples, config, dirs, "multicore", multiplier=alignprep.parallel_multiplier(samples)) as run_parallel: with profile.report("organize samples", dirs): samples = run_parallel("organize_samples", [[dirs, config, run_info_yaml, [x[0]["description"] for x in samples]]]) with profile.report("alignment", dirs): samples = run_parallel("prepare_sample", samples) samples = run_parallel("trim_sample", samples) samples = run_parallel("disambiguate_split", [samples]) samples = run_parallel("process_alignment", samples) with profile.report("disambiguation", dirs): samples = disambiguate.resolve(samples, run_parallel) samples = run_parallel("clean_chipseq_alignment", samples) with prun.start(_wres(parallel, ["peakcaller"]), samples, config, dirs, "peakcalling", multiplier = peaks._get_multiplier(samples)) as run_parallel: with profile.report("peakcalling", dirs): samples = peaks.peakcall_prepare(samples, run_parallel) samples = peaks.call_consensus(samples) samples = run_parallel("run_chipseq_count", samples) samples = peaks.create_peaktable(samples) with prun.start(_wres(parallel, ["picard", "fastqc"]), samples, config, dirs, "qc") as run_parallel: with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) samples = atac.create_ataqv_report(samples) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for sample in samples: run_parallel("upload_samples_project", [sample]) logger.info("Timing: finished") return samples def wgbsseqpipeline(config, run_info_yaml, parallel, dirs, samples): with prun.start(_wres(parallel, ["fastqc", "picard"], ensure_mem={"fastqc" : 4}), samples, config, dirs, "trimming") as run_parallel: with profile.report("organize samples", dirs): samples = run_parallel("organize_samples", [[dirs, config, run_info_yaml, [x[0]["description"] for x in samples]]]) samples = run_parallel("prepare_sample", samples) samples = run_parallel("trim_bs_sample", samples) with prun.start(_wres(parallel, ["aligner", "bismark", "picard", "samtools"]), samples, config, dirs, "multicore", multiplier=alignprep.parallel_multiplier(samples)) as run_parallel: with profile.report("alignment", dirs): samples = run_parallel("process_alignment", samples) with prun.start(_wres(parallel, ['samtools']), samples, config, dirs, 'deduplication') as run_parallel: with profile.report('deduplicate', dirs): samples = run_parallel('deduplicate_bismark', samples) with prun.start(_wres(parallel, ["caller"], ensure_mem={"caller": 5}), samples, config, dirs, "multicore2", multiplier=24) as run_parallel: with profile.report("cpg calling", dirs): samples = run_parallel("cpg_calling", samples) with prun.start(_wres(parallel, ["picard", "fastqc", "samtools"]), samples, config, dirs, "qc") as run_parallel: with profile.report("quality control", dirs): samples = qcsummary.generate_parallel(samples, run_parallel) with profile.report("upload", dirs): samples = run_parallel("upload_samples", samples) for sample in samples: run_parallel("upload_samples_project", [sample]) logger.info("Timing: finished") return samples def rnaseq_prep_samples(config, run_info_yaml, parallel, dirs, samples): """ organizes RNA-seq and small-RNAseq samples, converting from BAM if necessary and trimming if necessary """ pipeline = dd.get_in_samples(samples, dd.get_analysis) trim_reads_set = any([tz.get_in(["algorithm", "trim_reads"], d) for d in dd.sample_data_iterator(samples)]) resources = ["picard"] needs_trimming = (_is_smallrnaseq(pipeline) or trim_reads_set) if needs_trimming: resources.append("atropos") with prun.start(_wres(parallel, resources), samples, config, dirs, "trimming", max_multicore=1 if not needs_trimming else None) as run_parallel: with profile.report("organize samples", dirs): samples = run_parallel("organize_samples", [[dirs, config, run_info_yaml, [x[0]["description"] for x in samples]]]) samples = run_parallel("prepare_sample", samples) if needs_trimming: with profile.report("adapter trimming", dirs): if _is_smallrnaseq(pipeline): samples = run_parallel("trim_srna_sample", samples) else: samples = run_parallel("trim_sample", samples) return samples def _get_pipeline(item): from bcbio.log import logger analysis_type = item.get("analysis", "").lower() if analysis_type not in SUPPORTED_PIPELINES: logger.error("Cannot determine which type of analysis to run, " "set in the run_info under details.") sys.exit(1) else: return SUPPORTED_PIPELINES[analysis_type] def _pair_samples_with_pipelines(run_info_yaml, config): """Map samples defined in input file to pipelines to run. """ samples = config_utils.load_config(run_info_yaml) if isinstance(samples, dict): resources = samples.pop("resources") samples = samples["details"] else: resources = {} ready_samples = [] for sample in samples: if "files" in sample: del sample["files"] # add any resources to this item to recalculate global configuration usample = copy.deepcopy(sample) usample.pop("algorithm", None) if "resources" not in usample: usample["resources"] = {} for prog, pkvs in resources.items(): if prog not in usample["resources"]: usample["resources"][prog] = {} if pkvs is not None: for key, val in pkvs.items(): usample["resources"][prog][key] = val config = config_utils.update_w_custom(config, usample) sample["resources"] = {} ready_samples.append(sample) paired = [(x, _get_pipeline(x)) for x in ready_samples] d = defaultdict(list) for x in paired: d[x[1]].append([x[0]]) return d, config SUPPORTED_PIPELINES = {"variant2": variant2pipeline, "snp calling": variant2pipeline, "variant": variant2pipeline, "standard": standardpipeline, "minimal": standardpipeline, "rna-seq": rnaseqpipeline, "smallrna-seq": smallrnaseqpipeline, "chip-seq": chipseqpipeline, "wgbs-seq": wgbsseqpipeline, "fastrna-seq": fastrnaseqpipeline, "scrna-seq": singlecellrnaseqpipeline} def _is_smallrnaseq(pipeline): return pipeline.lower() == "smallrna-seq" bcbio-nextgen-1.2.9/bcbio/pipeline/merge.py000066400000000000000000000142121415626112400206050ustar00rootroot00000000000000"""Handle multiple samples present on a single flowcell Merges samples located in multiple lanes on a flowcell. Unique sample names identify items to combine within a group. """ import os import shutil import subprocess from bcbio import bam, utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do, system def combine_fastq_files(in_files, work_dir, config): if len(in_files) == 1: return in_files[0] else: cur1, cur2 = in_files[0] out1 = os.path.join(work_dir, os.path.basename(cur1)) out2 = os.path.join(work_dir, os.path.basename(cur2)) if cur2 else None if not os.path.exists(out1): with open(out1, "a") as out_handle: for (cur1, _) in in_files: with open(cur1) as in_handle: shutil.copyfileobj(in_handle, out_handle) if out2 and not os.path.exists(out2): with open(out2, "a") as out_handle: for (_, cur2) in in_files: with open(cur2) as in_handle: shutil.copyfileobj(in_handle, out_handle) for f1, f2 in in_files: utils.save_diskspace(f1, "fastq merged to %s" % out1, config) if f2: utils.save_diskspace(f2, "fastq merged to %s" % out2, config) return out1, out2 def merge_bam_files(bam_files, work_dir, data, out_file=None, batch=None): """Merge multiple BAM files from a sample into a single BAM for processing. Checks system open file limit and merges in batches if necessary to avoid file handle limits. """ out_file = _merge_outfile_fname(out_file, bam_files, work_dir, batch) if not utils.file_exists(out_file): if len(bam_files) == 1 and bam.bam_already_sorted(bam_files[0], data["config"], "coordinate"): with file_transaction(data, out_file) as tx_out_file: _create_merge_filelist(bam_files, tx_out_file, data["config"]) out_file = bam_files[0] samtools = config_utils.get_program("samtools", data["config"]) do.run('{} quickcheck -v {}'.format(samtools, out_file), "Check for valid merged BAM after transfer") else: with tx_tmpdir(data) as tmpdir: with utils.chdir(tmpdir): with file_transaction(data, out_file) as tx_out_file: tx_bam_file_list = _create_merge_filelist(bam_files, tx_out_file, data["config"]) samtools = config_utils.get_program("samtools", data["config"]) resources = config_utils.get_resources("samtools", data["config"]) num_cores = dd.get_num_cores(data) # Aim for 3.5Gb/core memory for BAM merging num_cores = config_utils.adjust_cores_to_mb_target( 3500, resources.get("memory", "2G"), num_cores) max_mem = config_utils.adjust_memory(resources.get("memory", "1G"), 2, "decrease").upper() if dd.get_mark_duplicates(data): cmd = _biobambam_merge_dedup_maxcov(data) else: cmd = _biobambam_merge_maxcov(data) do.run(cmd.format(**locals()), "Merge bam files to %s" % os.path.basename(out_file), None) do.run('{} quickcheck -v {}'.format(samtools, tx_out_file), "Check for valid merged BAM") do.run('{} quickcheck -v {}'.format(samtools, out_file), "Check for valid merged BAM after transfer") _finalize_merge(out_file, bam_files, data["config"]) bam.index(out_file, data["config"]) return out_file def _create_merge_filelist(bam_files, base_file, config): """Create list of input files for merge, ensuring all files are valid. """ bam_file_list = "%s.list" % os.path.splitext(base_file)[0] samtools = config_utils.get_program("samtools", config) with open(bam_file_list, "w") as out_handle: for f in sorted(bam_files): do.run('{} quickcheck -v {}'.format(samtools, f), "Ensure integrity of input merge BAM files") out_handle.write("%s\n" % f) return bam_file_list def _merge_outfile_fname(out_file, bam_files, work_dir, batch): """Derive correct name of BAM file based on batching. """ if out_file is None: out_file = os.path.join(work_dir, os.path.basename(sorted(bam_files)[0])) if batch is not None: base, ext = os.path.splitext(out_file) out_file = "%s-b%s%s" % (base, batch, ext) return out_file def _finalize_merge(out_file, bam_files, config): """Handle indexes and cleanups of merged BAM and input files. """ # Ensure timestamps are up to date on output file and index # Works around issues on systems with inconsistent times for ext in ["", ".bai"]: if os.path.exists(out_file + ext): subprocess.check_call(["touch", out_file + ext]) for b in bam_files: utils.save_diskspace(b, "BAM merged to %s" % out_file, config) def _biobambam_merge_dedup_maxcov(data): """Combine query sorted BAM files, de-duplicate, sort and truncate to maximum coverage. Handles split files, checking for large scale whole genome coverage where we want to downsample to a maximum coverage. """ ds_cmd = bam.get_maxcov_downsample_cl(data, "bamsormadup") return ("bamcat level=0 tmpfile={tx_out_file}-bammerge `cat {tx_bam_file_list}` | " "bamsormadup threads={num_cores} " "tmpfile={tx_out_file}-bamsormaduptmp %s > {tx_out_file}" % ds_cmd) def _biobambam_merge_maxcov(data): """Combine query sorted BAM files, sort and truncate to maximum coverage. No de-duplication. """ ds_cmd = bam.get_maxcov_downsample_cl(data, "bamsormadup") return ("bammerge IL={tx_bam_file_list} tmpfile={tx_out_file}-merge %s > {tx_out_file}" % ds_cmd) bcbio-nextgen-1.2.9/bcbio/pipeline/qcsummary.py000066400000000000000000000420771415626112400215410ustar00rootroot00000000000000"""Quality control and summary metrics for next-gen alignments and analysis. """ import collections import copy import csv import os import yaml from datetime import datetime import pandas as pd import glob import toolz as tz from bcbio import bam from bcbio import utils from bcbio.cwl import cwlutils from bcbio.log import logger from bcbio.pipeline import config_utils, run_info import bcbio.pipeline.datadict as dd from bcbio.provenance import do from bcbio.rnaseq import gtf from bcbio.variation import damage, peddy, vcfutils, vcfanno import six # ## High level functions to generate summary def qc_to_rec(samples): """CWL: Convert a set of input samples into records for parallelization. """ samples = [utils.to_single_data(x) for x in samples] samples = cwlutils.assign_complex_to_samples(samples) to_analyze, extras = _split_samples_by_qc(samples) recs = cwlutils.samples_to_records([utils.to_single_data(x) for x in to_analyze + extras]) return [[x] for x in recs] def generate_parallel(samples, run_parallel): """Provide parallel preparation of summary information for alignment and variant calling. """ to_analyze, extras = _split_samples_by_qc(samples) qced = run_parallel("pipeline_summary", to_analyze) samples = _combine_qc_samples(qced) + extras qsign_info = run_parallel("qsignature_summary", [samples]) metadata_file = _merge_metadata([samples]) summary_file = write_project_summary(samples, qsign_info) out = [] for data in samples: if "summary" not in data[0]: data[0]["summary"] = {} data[0]["summary"]["project"] = summary_file data[0]["summary"]["metadata"] = metadata_file if qsign_info: data[0]["summary"]["mixup_check"] = qsign_info[0]["out_dir"] out.append(data) out = _add_researcher_summary(out, summary_file) # MultiQC must be run after all file outputs are set: return [[utils.to_single_data(d)] for d in run_parallel("multiqc_summary", [out])] def pipeline_summary(data): """Provide summary information on processing sample. Handles standard and CWL (single QC output) cases. """ data = utils.to_single_data(data) if data["analysis"].startswith("wgbs-seq"): bismark_bam = dd.get_align_bam(data) sorted_bam = bam.sort(bismark_bam, data["config"]) data = dd.set_align_bam(data, sorted_bam) data = dd.set_work_bam(data, bismark_bam) work_bam = dd.get_align_bam(data) or dd.get_work_bam(data) if not work_bam or not work_bam.endswith(".bam"): work_bam = None if dd.get_ref_file(data): if work_bam or (tz.get_in(["config", "algorithm", "kraken"], data)): # kraken doesn't need bam logger.info("QC: %s %s" % (dd.get_sample_name(data), ", ".join(dd.get_algorithm_qc(data)))) work_data = cwlutils.unpack_tarballs(utils.deepish_copy(data), data) data["summary"] = _run_qc_tools(work_bam, work_data) if (len(dd.get_algorithm_qc(data)) == 1 and "output_cwl_keys" in data): data["summary"]["qc"] = data["summary"]["qc"].get(dd.get_algorithm_qc(data)[0]) return [[data]] def get_qc_tools(data): """Retrieve a list of QC tools to use based on configuration and analysis type. Uses defaults if previously set. """ if dd.get_algorithm_qc(data): return dd.get_algorithm_qc(data) analysis = data["analysis"].lower() to_run = [] if tz.get_in(["config", "algorithm", "kraken"], data): to_run.append("kraken") if "fastqc" not in dd.get_tools_off(data): to_run.append("fastqc") if any([tool in dd.get_tools_on(data) for tool in ["qualimap", "qualimap_full"]]): to_run.append("qualimap") if analysis.startswith("rna-seq") or analysis == "smallrna-seq": if "qualimap" not in dd.get_tools_off(data): if gtf.is_qualimap_compatible(dd.get_gtf_file(data)): to_run.append("qualimap_rnaseq") else: logger.debug("GTF not compatible with Qualimap, skipping.") if analysis.startswith("chip-seq"): to_run.append("chipqc") if dd.get_chip_method(data) == "atac": to_run.append("ataqv") if analysis.startswith("smallrna-seq"): to_run.append("small-rna") to_run.append("atropos") if "coverage_qc" not in dd.get_tools_off(data): to_run.append("samtools") if dd.has_variantcalls(data): if "coverage_qc" not in dd.get_tools_off(data): to_run += ["coverage", "picard"] to_run += ["qsignature", "variants"] if vcfanno.is_human(data): to_run += ["peddy"] if "contamination" not in dd.get_tools_off(data): to_run += ["contamination"] if vcfutils.get_paired_phenotype(data): if "viral" not in dd.get_tools_off(data): to_run += ["viral"] if damage.should_filter([data]): to_run += ["damage"] if dd.get_umi_consensus(data): to_run += ["umi"] if tz.get_in(["config", "algorithm", "preseq"], data): to_run.append("preseq") to_run = [tool for tool in to_run if tool not in dd.get_tools_off(data)] to_run.sort() return to_run def _run_qc_tools(bam_file, data): """Run a set of third party quality control tools, returning QC directory and metrics. :param bam_file: alignments in bam format :param data: dict with all configuration information :returns: dict with output of different tools """ from bcbio.qc import (atropos, contamination, coverage, damage, fastqc, kraken, qsignature, qualimap, samtools, picard, srna, umi, variant, viral, preseq, chipseq, atac) tools = {"fastqc": fastqc.run, "atropos": atropos.run, "small-rna": srna.run, "samtools": samtools.run, "qualimap": qualimap.run, "qualimap_rnaseq": qualimap.run_rnaseq, "qsignature": qsignature.run, "contamination": contamination.run, "coverage": coverage.run, "damage": damage.run, "variants": variant.run, "peddy": peddy.run_qc, "kraken": kraken.run, "picard": picard.run, "umi": umi.run, "viral": viral.run, "preseq": preseq.run, "chipqc": chipseq.run, "ataqv": atac.run } qc_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "qc", data["description"])) metrics = {} qc_out = utils.deepish_copy(dd.get_summary_qc(data)) for program_name in dd.get_algorithm_qc(data): if not bam_file and program_name != "kraken": # kraken doesn't need bam continue if dd.get_phenotype(data) == "germline" and program_name != "variants": continue qc_fn = tools[program_name] cur_qc_dir = os.path.join(qc_dir, program_name) out = qc_fn(bam_file, data, cur_qc_dir) qc_files = None if out and isinstance(out, dict): # Check for metrics output, two cases: # 1. output with {"metrics"} and files ("base") if "metrics" in out: metrics.update(out.pop("metrics")) # 2. a dictionary of metrics elif "base" not in out: metrics.update(out) # Check for files only output if "base" in out: qc_files = out elif out and isinstance(out, six.string_types) and os.path.exists(out): qc_files = {"base": out, "secondary": []} if not qc_files: qc_files = _organize_qc_files(program_name, cur_qc_dir) if qc_files: qc_out[program_name] = qc_files metrics["Name"] = dd.get_sample_name(data) metrics["Quality format"] = dd.get_quality_format(data).lower() return {"qc": qc_out, "metrics": metrics} def _organize_qc_files(program, qc_dir): """Organize outputs from quality control runs into a base file and secondary outputs. Provides compatibility with CWL output. Returns None if no files created during processing. """ base_files = {"fastqc": "fastqc_report.html", "qualimap_rnaseq": "qualimapReport.html", "qualimap": "qualimapReport.html"} if os.path.exists(qc_dir): out_files = [] for fname in [os.path.join(qc_dir, x) for x in os.listdir(qc_dir)]: if os.path.isfile(fname) and not fname.endswith(".bcbiotmp"): out_files.append(fname) elif os.path.isdir(fname) and not fname.endswith("tx"): for root, dirs, files in os.walk(fname): for f in files: if not f.endswith(".bcbiotmp"): out_files.append(os.path.join(root, f)) if len(out_files) > 0 and all([not f.endswith("-failed.log") for f in out_files]): if len(out_files) == 1: base = out_files[0] secondary = [] else: base = None if program in base_files: base_choices = [x for x in out_files if x.endswith("/%s" % base_files[program])] if len(base_choices) == 1: base = base_choices[0] if not base: base = out_files[0] secondary = [x for x in out_files if x != base] return {"base": base, "secondary": secondary} # ## Allow parallelization for separate QC runs def _split_samples_by_qc(samples): """Split data into individual quality control steps for a run. """ to_process = [] extras = [] for data in [utils.to_single_data(x) for x in samples]: qcs = dd.get_algorithm_qc(data) # kraken doesn't need bam if qcs and (dd.get_align_bam(data) or dd.get_work_bam(data) or tz.get_in(["config", "algorithm", "kraken"], data)): for qc in qcs: add = copy.deepcopy(data) add["config"]["algorithm"]["qc"] = [qc] to_process.append([add]) else: extras.append([data]) return to_process, extras def _combine_qc_samples(samples): """Combine split QC analyses into single samples based on BAM files. """ by_bam = collections.defaultdict(list) for data in [utils.to_single_data(x) for x in samples]: batch = dd.get_batch(data) or dd.get_sample_name(data) if not isinstance(batch, (list, tuple)): batch = [batch] batch = tuple(batch) by_bam[(dd.get_align_bam(data) or dd.get_work_bam(data), batch)].append(data) out = [] for data_group in by_bam.values(): data = data_group[0] alg_qc = [] qc = {} metrics = {} for d in data_group: qc.update(dd.get_summary_qc(d)) metrics.update(dd.get_summary_metrics(d)) alg_qc.extend(dd.get_algorithm_qc(d)) data["config"]["algorithm"]["qc"] = alg_qc data["summary"]["qc"] = qc data["summary"]["metrics"] = metrics out.append([data]) return out # ## Generate project level QC summary for quickly assessing large projects def write_project_summary(samples, qsign_info=None): """Write project summary information on the provided samples. write out dirs, genome resources, """ work_dir = samples[0][0]["dirs"]["work"] out_file = os.path.join(work_dir, "project-summary.yaml") upload_dir = (os.path.join(work_dir, samples[0][0]["upload"]["dir"]) if "dir" in samples[0][0]["upload"] else "") date = str(datetime.now()) prev_samples = _other_pipeline_samples(out_file, samples) with open(out_file, "w") as out_handle: yaml.safe_dump({"date": date}, out_handle, default_flow_style=False, allow_unicode=False) if qsign_info: qsign_out = utils.deepish_copy(qsign_info[0]) qsign_out.pop("out_dir", None) yaml.safe_dump({"qsignature": qsign_out}, out_handle, default_flow_style=False, allow_unicode=False) yaml.safe_dump({"upload": upload_dir}, out_handle, default_flow_style=False, allow_unicode=False) yaml.safe_dump({"bcbio_system": samples[0][0]["config"].get("bcbio_system", "")}, out_handle, default_flow_style=False, allow_unicode=False) yaml.safe_dump({"samples": prev_samples + [_save_fields(sample[0]) for sample in samples]}, out_handle, default_flow_style=False, allow_unicode=False) return out_file def _merge_metadata(samples): """Merge all metadata into CSV file""" samples = list(utils.flatten(samples)) out_dir = dd.get_work_dir(samples[0]) logger.info("summarize metadata") out_file = os.path.join(out_dir, "metadata.csv") sample_metrics = collections.defaultdict(dict) for s in samples: m = tz.get_in(['metadata'], s) if isinstance(m, six.string_types): m = json.loads(m) if m: for me in list(m.keys()): if isinstance(m[me], list) or isinstance(m[me], dict) or isinstance(m[me], tuple): m.pop(me, None) sample_metrics[dd.get_sample_name(s)].update(m) pd.DataFrame(sample_metrics).transpose().to_csv(out_file) return out_file def _other_pipeline_samples(summary_file, cur_samples): """Retrieve samples produced previously by another pipeline in the summary output. """ cur_descriptions = set([s[0]["description"] for s in cur_samples]) out = [] if utils.file_exists(summary_file): with open(summary_file) as in_handle: for s in yaml.safe_load(in_handle).get("samples", []): if s["description"] not in cur_descriptions: out.append(s) return out def _save_fields(sample): to_save = ["dirs", "genome_resources", "genome_build", "sam_ref", "metadata", "description"] saved = {k: sample[k] for k in to_save if k in sample} if "summary" in sample and "metrics" in sample["summary"]: saved["summary"] = {"metrics": sample["summary"]["metrics"]} return saved # ## Generate researcher specific summaries def _add_researcher_summary(samples, summary_yaml): """Generate summary files per researcher if organized via a LIMS. """ by_researcher = collections.defaultdict(list) for data in (x[0] for x in samples): researcher = utils.get_in(data, ("upload", "researcher")) if researcher: by_researcher[researcher].append(data["description"]) out_by_researcher = {} for researcher, descrs in by_researcher.items(): out_by_researcher[researcher] = _summary_csv_by_researcher(summary_yaml, researcher, set(descrs), samples[0][0]) out = [] for data in (x[0] for x in samples): researcher = utils.get_in(data, ("upload", "researcher")) if researcher: data["summary"]["researcher"] = out_by_researcher[researcher] out.append([data]) return out def _summary_csv_by_researcher(summary_yaml, researcher, descrs, data): """Generate a CSV file with summary information for a researcher on this project. """ out_file = os.path.join(utils.safe_makedir(os.path.join(data["dirs"]["work"], "researcher")), "%s-summary.tsv" % run_info.clean_name(researcher)) metrics = ["Total_reads", "Mapped_reads", "Mapped_reads_pct", "Duplicates", "Duplicates_pct"] with open(summary_yaml) as in_handle: with open(out_file, "w") as out_handle: writer = csv.writer(out_handle, dialect="excel-tab") writer.writerow(["Name"] + metrics) for sample in yaml.safe_load(in_handle)["samples"]: if sample["description"] in descrs: row = [sample["description"]] + [utils.get_in(sample, ("summary", "metrics", x), "") for x in metrics] writer.writerow(row) return out_file # ## Galaxy functionality def prep_pdf(qc_dir, config): """Create PDF from HTML summary outputs in QC directory. Requires wkhtmltopdf installed: http://www.msweet.org/projects.php?Z1 Thanks to: https://www.biostars.org/p/16991/ Works around issues with CSS conversion on CentOS by adjusting CSS. """ html_file = os.path.join(qc_dir, "fastqc", "fastqc_report.html") html_fixed = "%s-fixed%s" % os.path.splitext(html_file) try: topdf = config_utils.get_program("wkhtmltopdf", config) except config_utils.CmdNotFound: topdf = None if topdf and utils.file_exists(html_file): out_file = "%s.pdf" % os.path.splitext(html_file)[0] if not utils.file_exists(out_file): cmd = ("sed 's/div.summary/div.summary-no/' %s | sed 's/div.main/div.main-no/' > %s" % (html_file, html_fixed)) do.run(cmd, "Fix fastqc CSS to be compatible with wkhtmltopdf") cmd = [topdf, html_fixed, out_file] do.run(cmd, "Convert QC HTML to PDF") return out_file bcbio-nextgen-1.2.9/bcbio/pipeline/region.py000066400000000000000000000173521415626112400210010ustar00rootroot00000000000000"""Provide analysis of input files by chromosomal regions. Handle splitting and analysis of files from chromosomal subsets separated by no-read regions. """ import collections import os import six import toolz as tz from bcbio import utils from bcbio.distributed.split import parallel_split_combine from bcbio.pipeline import datadict as dd def get_max_counts(samples): """Retrieve number of regions that can be processed in parallel from current samples. """ counts = [] for data in (x[0] for x in samples): count = tz.get_in(["config", "algorithm", "callable_count"], data, 1) vcs = tz.get_in(["config", "algorithm", "variantcaller"], data, []) if isinstance(vcs, six.string_types): vcs = [vcs] if vcs: count *= len(vcs) counts.append(count) return max(counts) # ## BAM preparation def to_safestr(region): if region[0] in ["nochrom", "noanalysis"]: return region[0] else: return "_".join([str(x) for x in region]) # ## Split and delayed BAM combine def _split_by_regions(dirname, out_ext, in_key): """Split a BAM file data analysis into chromosomal regions. """ def _do_work(data): # XXX Need to move retrieval of regions into preparation to avoid # need for files when running in non-shared filesystems regions = _get_parallel_regions(data) def _sort_by_size(region): _, start, end = region return end - start regions.sort(key=_sort_by_size, reverse=True) bam_file = data[in_key] if bam_file is None: return None, [] part_info = [] base_out = os.path.splitext(os.path.basename(bam_file))[0] nowork = [["nochrom"], ["noanalysis", data["config"]["algorithm"]["non_callable_regions"]]] for region in regions + nowork: out_dir = os.path.join(data["dirs"]["work"], dirname, data["name"][-1], region[0]) region_outfile = os.path.join(out_dir, "%s-%s%s" % (base_out, to_safestr(region), out_ext)) part_info.append((region, region_outfile)) out_file = os.path.join(data["dirs"]["work"], dirname, data["name"][-1], "%s%s" % (base_out, out_ext)) return out_file, part_info return _do_work def _get_parallel_regions(data): """Retrieve regions to run in parallel, putting longest intervals first. """ callable_regions = tz.get_in(["config", "algorithm", "callable_regions"], data) if not callable_regions: raise ValueError("Did not find any callable regions for sample: %s\n" "Check 'align/%s/*-callableblocks.bed' and 'regions' to examine callable regions" % (dd.get_sample_name(data), dd.get_sample_name(data))) with open(callable_regions) as in_handle: regions = [(xs[0], int(xs[1]), int(xs[2])) for xs in (l.rstrip().split("\t") for l in in_handle) if (len(xs) >= 3 and not xs[0].startswith(("track", "browser",)))] return regions def get_parallel_regions(batch): """CWL target to retrieve a list of callable regions for parallelization. """ samples = [utils.to_single_data(d) for d in batch] regions = _get_parallel_regions(samples[0]) return [{"region": "%s:%s-%s" % (c, s, e)} for c, s, e in regions] def get_parallel_regions_block(batch): """CWL target to retrieve block group of callable regions for parallelization. Uses blocking to handle multicore runs. """ samples = [utils.to_single_data(d) for d in batch] regions = _get_parallel_regions(samples[0]) out = [] # Currently don't have core information here so aim for about 10 items per partition n = 10 for region_block in tz.partition_all(n, regions): out.append({"region_block": ["%s:%s-%s" % (c, s, e) for c, s, e in region_block]}) return out def _add_combine_info(output, combine_map, file_key): """Do not actually combine, but add details for later combining work. Each sample will contain information on the out file and additional files to merge, enabling other splits and recombines without losing information. """ files_per_output = collections.defaultdict(list) for part_file, out_file in combine_map.items(): files_per_output[out_file].append(part_file) out_by_file = collections.defaultdict(list) out = [] for data in output: # Do not pass along nochrom, noanalysis regions if data["region"][0] not in ["nochrom", "noanalysis"]: cur_file = data[file_key] # If we didn't process, no need to add combine information if cur_file in combine_map: out_file = combine_map[cur_file] if "combine" not in data: data["combine"] = {} data["combine"][file_key] = {"out": out_file, "extras": files_per_output.get(out_file, [])} out_by_file[out_file].append(data) elif cur_file: out_by_file[cur_file].append(data) else: out.append([data]) for samples in out_by_file.values(): regions = [x["region"] for x in samples] region_bams = [x["work_bam"] for x in samples] assert len(regions) == len(region_bams) if len(set(region_bams)) == 1: region_bams = [region_bams[0]] data = samples[0] data["region_bams"] = region_bams data["region"] = regions data = dd.set_mark_duplicates(data, data["config"]["algorithm"]["orig_markduplicates"]) del data["config"]["algorithm"]["orig_markduplicates"] out.append([data]) return out def parallel_prep_region(samples, run_parallel): """Perform full pre-variant calling BAM prep work on regions. """ file_key = "work_bam" split_fn = _split_by_regions("bamprep", "-prep.bam", file_key) # identify samples that do not need preparation -- no recalibration or realignment extras = [] torun = [] for data in [x[0] for x in samples]: if data.get("work_bam"): data["align_bam"] = data["work_bam"] if (not dd.get_realign(data) and not dd.get_variantcaller(data)): extras.append([data]) elif not data.get(file_key): extras.append([data]) else: # Do not want to re-run duplicate marking after realignment data["config"]["algorithm"]["orig_markduplicates"] = dd.get_mark_duplicates(data) data = dd.set_mark_duplicates(data, False) torun.append([data]) return extras + parallel_split_combine(torun, split_fn, run_parallel, "piped_bamprep", _add_combine_info, file_key, ["config"]) def delayed_bamprep_merge(samples, run_parallel): """Perform a delayed merge on regional prepared BAM files. """ if any("combine" in data[0] for data in samples): return run_parallel("delayed_bam_merge", samples) else: return samples # ## Utilities def clean_sample_data(samples): """Clean unnecessary information from sample data, reducing size for message passing. """ out = [] for data in (utils.to_single_data(x) for x in samples): if "dirs" in data: data["dirs"] = {"work": data["dirs"]["work"], "galaxy": data["dirs"]["galaxy"], "fastq": data["dirs"].get("fastq")} data["config"] = {"algorithm": data["config"]["algorithm"], "resources": data["config"]["resources"]} for remove_attr in ["config_file", "algorithm"]: data.pop(remove_attr, None) out.append([data]) return out bcbio-nextgen-1.2.9/bcbio/pipeline/rnaseq.py000066400000000000000000000665331415626112400210140ustar00rootroot00000000000000import os import sys from bcbio.rnaseq import (featureCounts, cufflinks, oncofuse, count, dexseq, express, variation, stringtie, sailfish, spikein, pizzly, ericscript, kallisto, salmon, singlecellexperiment, arriba) from bcbio.ngsalign import bowtie2, alignprep from bcbio.variation import effects, joint, multi, population, vardict import bcbio.pipeline.datadict as dd from bcbio.utils import filter_missing, flatten, to_single_data, file_exists, Rscript_cmd, safe_makedir from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.provenance import do from bcbio.pipeline import qcsummary def fast_rnaseq(samples, run_parallel): to_index = determine_indexes_to_make(samples) run_parallel("run_salmon_index", [to_index]) samples = run_parallel("run_salmon_reads", samples) samples = run_parallel("run_counts_spikein", samples) samples = spikein.combine_spikein(samples) return samples def singlecell_rnaseq(samples, run_parallel): quantifier = dd.get_in_samples(samples, dd.get_singlecell_quantifier) quantifier = quantifier.lower() samples = run_parallel("run_umi_transform", samples) demultiplexed = run_parallel("demultiplex_samples", samples) # break demultiplixed lanes into their own samples samples = [] for lane in demultiplexed: for index in lane: samples.append([index]) if not samples: logger.error(f"No samples were found matching the supplied sample barcodes. See " f"https://github.com/bcbio/bcbio-nextgen/issues/3428#issuecomment-772609904 " f"for how to debug this issue.") sys.exit(1) samples = run_parallel("run_filter_barcodes", samples) samples = run_parallel("run_barcode_histogram", samples) if quantifier == "rapmap": samples = run_parallel("run_rapmap_index", [samples]) samples = run_parallel("run_rapmap_align", samples) samples = run_parallel("run_tagcount", samples) samples = run_parallel("run_concatenate_sparse_counts", [samples]) elif quantifier == "kallisto": samples = run_parallel("run_kallisto_singlecell", samples) else: logger.error(("%s is not supported for singlecell RNA-seq " "quantification." % quantifier)) sys.exit(1) samples = scrnaseq_concatenate_metadata(samples) singlecellexperiment.make_scrnaseq_object(samples) return samples def scrnaseq_concatenate_metadata(samples): """ Create file same dimension than mtx.colnames with metadata and sample name to help in the creation of the SC object. """ barcodes = {} counts = "" metadata = {} has_sample_barcodes = False for sample in dd.sample_data_iterator(samples): if dd.get_sample_barcodes(sample): has_sample_barcodes = True with open(dd.get_sample_barcodes(sample)) as inh: for line in inh: cols = line.strip().split(",") if len(cols) == 1: # Assign sample name in case of missing in barcodes cols.append("NaN") barcodes[(dd.get_sample_name(sample), cols[0])] = cols[1:] else: barcodes[(dd.get_sample_name(sample), "NaN")] = [dd.get_sample_name(sample), "NaN"] counts = dd.get_combined_counts(sample) meta = map(str, list(sample["metadata"].values())) meta_cols = list(sample["metadata"].keys()) meta = ["NaN" if not v else v for v in meta] metadata[dd.get_sample_name(sample)] = meta metadata_fn = counts + ".metadata" if file_exists(metadata_fn): return samples with file_transaction(metadata_fn) as tx_metadata_fn: with open(tx_metadata_fn, 'w') as outh: outh.write(",".join(["sample"] + meta_cols) + '\n') with open(counts + ".colnames") as inh: for line in inh: sample = line.split(":")[0] if has_sample_barcodes: barcode = sample.split("-")[1] else: barcode = "NaN" outh.write(",".join(barcodes[(sample, barcode)] + metadata[sample]) + '\n') return samples def rnaseq_variant_calling(samples, run_parallel): """ run RNA-seq variant calling using GATK """ samples = run_parallel("run_rnaseq_variant_calling", samples) variantcaller = dd.get_variantcaller(to_single_data(samples[0])) jointcaller = dd.get_jointcaller(to_single_data(samples[0])) if jointcaller and 'gatk-haplotype-joint' in jointcaller: out = [] for d in joint.square_off(samples, run_parallel): out.extend([[to_single_data(xs)] for xs in multi.split_variants_by_sample(to_single_data(d))]) samples = out if variantcaller or jointcaller: samples = run_parallel("run_rnaseq_ann_filter", samples) if jointcaller and 'gatk-haplotype-joint' in jointcaller: out = [] for data in (to_single_data(xs) for xs in samples): if "variants" not in data: data["variants"] = [] data["variants"].append({"variantcaller": "gatk-haplotype", "vcf": data["vrn_file_orig"], "population": {"vcf": data["vrn_file"]}}) data["vrn_file"] = data.pop("vrn_file_orig") out.append([data]) samples = out return samples def run_rnaseq_variant_calling(data): """ run RNA-seq variant calling, variation file is stored in `vrn_file` in the datadict """ variantcaller = dd.get_variantcaller(data) if isinstance(variantcaller, list) and len(variantcaller) > 1: logger.error("Only one variantcaller can be run for RNA-seq at " "this time. Post an issue here " "(https://github.com/bcbio/bcbio-nextgen/issues) " "if this is something you need to do.") sys.exit(1) if variantcaller: if "gatk-haplotype" in variantcaller: data = variation.rnaseq_gatk_variant_calling(data) if vardict.get_vardict_command(data): data = variation.rnaseq_vardict_variant_calling(data) vrn_file = dd.get_vrn_file(data) return [[data]] def run_rnaseq_ann_filter(data): """Run RNA-seq annotation and filtering. """ data = to_single_data(data) if dd.get_vrn_file(data): eff_file = effects.add_to_vcf(dd.get_vrn_file(data), data)[0] if eff_file: data = dd.set_vrn_file(data, eff_file) ann_file = population.run_vcfanno(dd.get_vrn_file(data), data) if ann_file: data = dd.set_vrn_file(data, ann_file) jointcaller = dd.get_jointcaller(data) if jointcaller and 'gatk-haplotype-joint' in jointcaller: filter_file = variation.gatk_filter_rnaseq(dd.get_vrn_file(data), data) data = dd.set_vrn_file(data, filter_file) # remove variants close to splice junctions vrn_file = dd.get_vrn_file(data) vrn_file = variation.filter_junction_variants(vrn_file, data) data = dd.set_vrn_file(data, vrn_file) return [[data]] def quantitate(data): """CWL target for quantitation. XXX Needs to be split and parallelized by expression caller, with merging of multiple calls. """ data = to_single_data(to_single_data(data)) data = generate_transcript_counts(data)[0][0] data["quant"] = {} if "sailfish" in dd.get_expression_caller(data): data = to_single_data(sailfish.run_sailfish(data)[0]) data["quant"]["tsv"] = data["sailfish"] data["quant"]["hdf5"] = os.path.join(os.path.dirname(data["sailfish"]), "abundance.h5") if ("kallisto" in dd.get_expression_caller(data) or "pizzly" in dd.get_fusion_caller(data, [])): data = to_single_data(kallisto.run_kallisto_rnaseq(data)[0]) data["quant"]["tsv"] = os.path.join(data["kallisto_quant"], "abundance.tsv") data["quant"]["hdf5"] = os.path.join(data["kallisto_quant"], "abundance.h5") if (os.path.exists(os.path.join(data["kallisto_quant"], "fusion.txt"))): data["quant"]["fusion"] = os.path.join(data["kallisto_quant"], "fusion.txt") else: data["quant"]["fusion"] = None if "salmon" in dd.get_expression_caller(data): if dd.get_quantify_genome_alignments(data): if dd.get_aligner(data).lower() != "star": if dd.get_genome_build(data) == "hg38": logger.warning("Whole genome alignment-based Salmon quantification is " "only supported for the STAR aligner. Since this is hg38 we will fall " "back to the decoy method") data = to_single_data(salmon.run_salmon_decoy(data)[0]) else: logger.warning( "Whole genome alignment-based Salmon quantification is " "only supported for the STAR aligner. Falling back to the " "transcriptome-only method.") data = to_single_data(salmon.run_salmon_reads(data)[0]) else: data = to_single_data(salmon.run_salmon_bam(data)[0]) else: data = to_single_data(salmon.run_salmon_reads(data)[0]) data["quant"]["tsv"] = data["salmon"] data["quant"]["hdf5"] = os.path.join(os.path.dirname(data["salmon"]), "abundance.h5") return [[data]] def quantitate_expression_parallel(samples, run_parallel): """ quantitate expression, all programs run here should be multithreaded to take advantage of the threaded run_parallel environment """ data = samples[0][0] to_index = determine_indexes_to_make(samples) samples = run_parallel("generate_transcript_counts", samples) if "cufflinks" in dd.get_expression_caller(data): samples = run_parallel("run_cufflinks", samples) if "stringtie" in dd.get_expression_caller(data): samples = run_parallel("run_stringtie_expression", samples) if ("kallisto" in dd.get_expression_caller(data) or dd.get_fusion_mode(data) or "pizzly" in dd.get_fusion_caller(data, [])): run_parallel("run_kallisto_index", [to_index]) samples = run_parallel("run_kallisto_rnaseq", samples) if "sailfish" in dd.get_expression_caller(data): run_parallel("run_sailfish_index", [to_index]) samples = run_parallel("run_sailfish", samples) # always run salmon run_parallel("run_salmon_index", [to_index]) if dd.get_quantify_genome_alignments(data): if dd.get_aligner(data).lower() != "star": if dd.get_genome_build(data) == "hg38": logger.warning("Whole genome alignment-based Salmon quantification is " "only supported for the STAR aligner. Since this is hg38 we will fall " "back to the decoy method") samples = run_parallel("run_salmon_decoy", samples) else: logger.warning( "Whole genome alignment-based Salmon quantification is " "only supported for the STAR aligner. Falling back to the " "transcriptome-only method.") samples = run_parallel("run_salmon_reads", samples) else: samples = run_parallel("run_salmon_bam", samples) else: samples = run_parallel("run_salmon_reads", samples) samples = run_parallel("detect_fusions", samples) return samples def detect_fusions(data): data = to_single_data(data) # support the old style of fusion mode calling if dd.get_fusion_mode(data, False): data = dd.set_fusion_caller(data, ["oncofuse", "pizzly"]) logger.warning("``fusion_mode`` is deprecated in favor of turning on " "callers with ``fusion_caller``. It will run pizzly and " "oncofuse for now, but will eventually have support " "dropped.") fusion_caller = dd.get_fusion_caller(data, []) if "oncofuse" in fusion_caller: oncofuse_file = oncofuse.run(data) if oncofuse_file: data = dd.set_oncofuse_file(data, oncofuse_file) if "pizzly" in fusion_caller: pizzly_dir = pizzly.run_pizzly(data) if pizzly_dir: data = dd.set_pizzly_dir(data, pizzly_dir) data["fusion"] = {"fasta": os.path.join(pizzly_dir, "%s.fusions.fasta" % dd.get_sample_name(data)), "json": os.path.join(pizzly_dir, "%s.json" % dd.get_sample_name(data))} if "ericscript" in fusion_caller: ericscript_dir = ericscript.run(data) if "arriba" in fusion_caller: data = arriba.run_arriba(data) return [[data]] def quantitate_expression_noparallel(samples, run_parallel): """ run transcript quantitation for algorithms that don't run in parallel """ data = samples[0][0] if "express" in dd.get_expression_caller(data): samples = run_parallel("run_express", samples) if "dexseq" in dd.get_expression_caller(data): samples = run_parallel("run_dexseq", samples) return samples def generate_transcript_counts(data): """Generate counts per transcript and per exon from an alignment""" data["count_file"] = featureCounts.count(data) if dd.get_fusion_mode(data, False) and not dd.get_fusion_caller(data): oncofuse_file = oncofuse.run(data) if oncofuse_file: data = dd.set_oncofuse_file(data, oncofuse_file) if dd.get_transcriptome_align(data): # to create a disambiguated transcriptome file realign with bowtie2 if dd.get_disambiguate(data): logger.info("Aligning to the transcriptome with bowtie2 using the " "disambiguated reads.") bam_path = data["work_bam"] fastq_paths = alignprep._bgzip_from_bam(bam_path, data["dirs"], data, is_retry=False, output_infix='-transcriptome') if len(fastq_paths) == 2: file1, file2 = fastq_paths else: file1, file2 = fastq_paths[0], None ref_file = dd.get_ref_file(data) data = bowtie2.align_transcriptome(file1, file2, ref_file, data) else: file1, file2 = dd.get_input_sequence_files(data) if not dd.get_transcriptome_bam(data): ref_file = dd.get_ref_file(data) logger.info("Transcriptome alignment was flagged to run, but the " "transcriptome BAM file was not found. Aligning to the " "transcriptome with bowtie2.") data = bowtie2.align_transcriptome(file1, file2, ref_file, data) data = spikein.counts_spikein(data) return [[data]] def run_stringtie_expression(data): """Calculate transcript and gene level FPKM with Stringtie""" data = stringtie.run_stringtie_expression(data) return [[data]] def run_dexseq(data): """Quantitate exon-level counts with DEXSeq""" if dd.get_dexseq_gff(data, None): data = dexseq.bcbio_run(data) return [[data]] def run_express(data): """Quantitative isoform expression by eXpress""" data = express.run(data) return [[data]] def combine_express(samples, combined): """Combine tpm, effective counts and fpkm from express results""" if not combined: return None to_combine = [dd.get_express_counts(x) for x in dd.sample_data_iterator(samples) if dd.get_express_counts(x)] gtf_file = dd.get_gtf_file(samples[0][0]) isoform_to_gene_file = os.path.join(os.path.dirname(combined), "isoform_to_gene.txt") if len(to_combine) > 0: isoform_to_gene_file = express.isoform_to_gene_name( gtf_file, isoform_to_gene_file, next(dd.sample_data_iterator(samples))) eff_counts_combined_file = os.path.splitext(combined)[0] + ".isoform.express_counts" eff_counts_combined = count.combine_count_files(to_combine, eff_counts_combined_file, ext=".counts") to_combine = [dd.get_express_tpm(x) for x in dd.sample_data_iterator(samples) if dd.get_express_tpm(x)] tpm_counts_combined_file = os.path.splitext(combined)[0] + ".isoform.express_tpm" tpm_counts_combined = count.combine_count_files(to_combine, tpm_counts_combined_file) to_combine = [dd.get_express_fpkm(x) for x in dd.sample_data_iterator(samples) if dd.get_express_fpkm(x)] fpkm_counts_combined_file = os.path.splitext(combined)[0] + ".isoform.express_fpkm" fpkm_counts_combined = count.combine_count_files(to_combine, fpkm_counts_combined_file, ext=".fpkm") return {'counts': eff_counts_combined, 'tpm': tpm_counts_combined, 'fpkm': fpkm_counts_combined, 'isoform_to_gene': isoform_to_gene_file} return {} def run_cufflinks(data): """Quantitate transcript expression with Cufflinks""" if "cufflinks" in dd.get_tools_off(data): return [[data]] work_bam = dd.get_work_bam(data) ref_file = dd.get_sam_ref(data) out_dir, fpkm_file, fpkm_isoform_file = cufflinks.run(work_bam, ref_file, data) data = dd.set_cufflinks_dir(data, out_dir) data = dd.set_fpkm(data, fpkm_file) data = dd.set_fpkm_isoform(data, fpkm_isoform_file) return [[data]] def cufflinks_assemble(data): bam_file = dd.get_work_bam(data) ref_file = dd.get_sam_ref(data) out_dir = os.path.join(dd.get_work_dir(data), "assembly") num_cores = dd.get_num_cores(data) assembled_gtf = cufflinks.assemble(bam_file, ref_file, num_cores, out_dir, data) dd.get_assembled_gtf(data).append(assembled_gtf) return [[data]] def cufflinks_merge(*samples): to_merge = set(filter_missing(flatten([dd.get_assembled_gtf(data) for data in dd.sample_data_iterator(samples)]))) data = samples[0][0] ref_file = dd.get_sam_ref(data) gtf_file = dd.get_gtf_file(data) num_cores = dd.get_num_cores(data) merged_gtf = cufflinks.merge(to_merge, ref_file, gtf_file, num_cores, samples[0][0]) updated_samples = [] for data in dd.sample_data_iterator(samples): data = dd.set_merged_gtf(data, merged_gtf) updated_samples.append([data]) return updated_samples def stringtie_merge(*samples): to_merge = set(filter_missing(flatten([dd.get_assembled_gtf(data) for data in dd.sample_data_iterator(samples)]))) data = samples[0][0] ref_file = dd.get_sam_ref(data) gtf_file = dd.get_gtf_file(data) num_cores = dd.get_num_cores(data) merged_gtf = stringtie.merge(to_merge, ref_file, gtf_file, num_cores, data) updated_samples = [] for data in dd.sample_data_iterator(samples): data = dd.set_merged_gtf(data, merged_gtf) updated_samples.append([data]) return updated_samples def assemble_transcripts(run_parallel, samples): """ assembly strategy rationale implemented as suggested in http://www.nature.com/nprot/journal/v7/n3/full/nprot.2012.016.html run Cufflinks in without a reference GTF for each individual sample merge the assemblies with Cuffmerge using a reference GTF """ assembler = dd.get_in_samples(samples, dd.get_transcript_assembler) data = samples[0][0] if assembler: if "cufflinks" in assembler: samples = run_parallel("cufflinks_assemble", samples) if "stringtie" in assembler: samples = run_parallel("run_stringtie_expression", samples) if "stringtie" in assembler and stringtie.supports_merge(data): samples = run_parallel("stringtie_merge", [samples]) else: samples = run_parallel("cufflinks_merge", [samples]) return samples def combine_files(samples): """ after quantitation, combine the counts/FPKM/TPM/etc into a single table with all samples """ data = samples[0][0] # prefer the supplied transcriptome gtf file gtf_file = dd.get_transcriptome_gtf(data, None) if not gtf_file: gtf_file = dd.get_gtf_file(data, None) dexseq_gff = dd.get_dexseq_gff(data) # combine featureCount files count_files = filter_missing([dd.get_count_file(x[0]) for x in samples]) combined = count.combine_count_files(count_files, ext=".counts") annotated = count.annotate_combined_count_file(combined, gtf_file) # add tx2gene file tx2gene_file = os.path.join(dd.get_work_dir(data), "annotation", "tx2gene.csv") if gtf_file: tx2gene_file = sailfish.create_combined_tx2gene(data) # combine eXpress files express_counts_combined = combine_express(samples, combined) # combine Cufflinks files fpkm_files = filter_missing([dd.get_fpkm(x[0]) for x in samples]) if fpkm_files and combined: fpkm_combined_file = os.path.splitext(combined)[0] + ".fpkm" fpkm_combined = count.combine_count_files(fpkm_files, fpkm_combined_file) else: fpkm_combined = None isoform_files = filter_missing([dd.get_fpkm_isoform(x[0]) for x in samples]) if isoform_files and combined: fpkm_isoform_combined_file = os.path.splitext(combined)[0] + ".isoform.fpkm" fpkm_isoform_combined = count.combine_count_files(isoform_files, fpkm_isoform_combined_file, ".isoform.fpkm") else: fpkm_isoform_combined = None # combine DEXseq files to_combine_dexseq = list(filter_missing([dd.get_dexseq_counts(data[0]) for data in samples])) if to_combine_dexseq and combined: dexseq_combined_file = os.path.splitext(combined)[0] + ".dexseq" dexseq_combined = count.combine_count_files(to_combine_dexseq, dexseq_combined_file, ".dexseq") if dexseq_combined: dexseq.create_dexseq_annotation(dexseq_gff, dexseq_combined) else: dexseq_combined = None samples = spikein.combine_spikein(samples) tximport = load_tximport(data) updated_samples = [] for data in dd.sample_data_iterator(samples): if combined: data = dd.set_combined_counts(data, combined) if annotated: data = dd.set_annotated_combined_counts(data, annotated) if fpkm_combined: data = dd.set_combined_fpkm(data, fpkm_combined) if fpkm_isoform_combined: data = dd.set_combined_fpkm_isoform(data, fpkm_isoform_combined) if express_counts_combined: data = dd.set_express_counts(data, express_counts_combined['counts']) data = dd.set_express_tpm(data, express_counts_combined['tpm']) data = dd.set_express_fpkm(data, express_counts_combined['fpkm']) data = dd.set_isoform_to_gene(data, express_counts_combined['isoform_to_gene']) if dexseq_combined: data = dd.set_dexseq_counts(data, dexseq_combined_file) if gtf_file: data = dd.set_tx2gene(data, tx2gene_file) data = dd.set_tximport(data, tximport) updated_samples.append([data]) return updated_samples def determine_indexes_to_make(samples): """ returns a subset of the samples that have different indexes in them to make sure we only make each index once """ samples = [to_single_data(x) for x in samples] indexes = set() tomake = [] for data in samples: out_dir = os.path.join(dd.get_work_dir(data), "inputs", "transcriptome") out_stem = os.path.join(out_dir, dd.get_genome_build(data)) if dd.get_disambiguate(data): out_stem = "-".join([out_stem] + (dd.get_disambiguate(data) or [])) if dd.get_disambiguate(data): out_stem = "-".join([out_stem] + (dd.get_disambiguate(data) or [])) combined_file = out_stem + ".fa" if combined_file not in indexes: tomake.append(data) indexes.add(combined_file) return tomake def load_tximport(data): rcmd = Rscript_cmd("base") salmon_dir = os.path.join(dd.get_work_dir(data), "salmon") tx2gene_file = os.path.join(dd.get_work_dir(data), "inputs", "transcriptome", "tx2gene.csv") out_dir = os.path.join(salmon_dir, "combined") safe_makedir(out_dir) tpm_file = os.path.join(out_dir, "tximport-tpm.csv") counts_file = os.path.join(out_dir, "tximport-counts.csv") if file_exists(tpm_file) and file_exists(counts_file): return {"gene_tpm": tpm_file, "gene_counts": counts_file} with file_transaction(tpm_file) as tx_tpm_file, file_transaction(counts_file) as tx_counts_file: render_string = ( f'library(tidyverse);' f'salmon_files = list.files("{salmon_dir}", pattern="quant.sf", recursive=TRUE, full.names=TRUE);' f'tx2gene = readr::read_csv("{tx2gene_file}", col_names=c("transcript", "gene")); ' f'samples = basename(dirname(salmon_files));' f'names(salmon_files) = samples;' f'txi = tximport::tximport(salmon_files, type="salmon", tx2gene=tx2gene, countsFromAbundance="lengthScaledTPM", dropInfReps=TRUE);' f'readr::write_csv(round(txi$counts) %>% as.data.frame() %>% tibble::rownames_to_column("gene"), "{tx_counts_file}");' f'readr::write_csv(txi$abundance %>% as.data.frame() %>% tibble::rownames_to_column("gene"), "{tx_tpm_file}");' ) do.run([rcmd, "--vanilla", "-e", render_string], f"Loading tximport.") return {"gene_tpm": tpm_file, "gene_counts": counts_file} def load_summarizedexperiment(samples): """ create summarizedexperiment rds object fails with n_samples = 1 """ rcmd = Rscript_cmd("base") se_script = os.path.join(os.path.dirname(__file__), os.pardir, "scripts", "R", "bcbio2se.R") data = samples[0][0] work_dir = dd.get_work_dir(data) out_dir = os.path.join(work_dir, "salmon") summarized_experiment = os.path.join(out_dir, "bcbio-se.rds") if not file_exists(summarized_experiment): with file_transaction(summarized_experiment) as tx_out_file: cmd = f"{rcmd} --vanilla {se_script} {work_dir} {tx_out_file}" message = f"Loading SummarizedExperiment." try: do.run(cmd, message) except Exception: logger.error("SE creation failed") if file_exists(summarized_experiment): try: se_qc_report = generate_se_qc_report(work_dir) except Exception: se_qc_report = None logger.error("SE QC failed") updated_samples = [] for data in dd.sample_data_iterator(samples): data = dd.set_summarized_experiment(data, summarized_experiment) updated_samples.append([data]) return updated_samples else: return samples def generate_se_qc_report(work_dir): """ generate QC report based on SE RDS object""" rcmd = Rscript_cmd("base") qc_script = os.path.join(os.path.dirname(__file__), os.pardir, "scripts", "R", "se2qc.Rmd") out_file = os.path.join(work_dir, "qc", "bcbio-se.html") rds_file = os.path.join(work_dir, "salmon", "bcbio-se.rds") if file_exists(out_file): return out_file with file_transaction(out_file) as tx_out_file: cmd = ( f"""{rcmd} --vanilla """ f"""-e 'rmarkdown::render("{qc_script}", params = list(rds_file="{rds_file}"), output_file="{tx_out_file}")'""" ) message = f"Creating SE QC report" do.run(cmd, message) return out_file bcbio-nextgen-1.2.9/bcbio/pipeline/run_info.py000066400000000000000000001515551415626112400213410ustar00rootroot00000000000000"""Retrieve run information describing files to process in a pipeline. This handles two methods of getting processing information: from a Galaxy next gen LIMS system or an on-file YAML configuration. """ import collections from contextlib import closing import copy import glob import itertools import operator import os import string import sys import six import toolz as tz import yaml from bcbio import install, utils, structural from bcbio.bam import fastq, ref from bcbio.log import logger from bcbio.distributed import objectstore from bcbio.illumina import flowcell from bcbio.pipeline import alignment, config_utils, genome from bcbio.pipeline import datadict as dd from bcbio.provenance import diagnostics, programs, versioncheck from bcbio.provenance import data as provenancedata from bcbio.qc import viral from bcbio.variation import annotation, effects, genotype, population, joint, vcfutils, vcfanno from bcbio.variation.cortex import get_sample_name from bcbio.bam.fastq import open_fastq from functools import reduce ALLOWED_CONTIG_NAME_CHARS = set(list(string.digits) + list(string.ascii_letters) + ["-", "_", "*", ":", "."]) ALGORITHM_NOPATH_KEYS = ["variantcaller", "realign", "recalibrate", "peakcaller", "expression_caller", "singlecell_quantifier", "fusion_caller", "svcaller", "hetcaller", "jointcaller", "tools_off", "tools_on", "mixup_check", "qc", "transcript_assembler"] ALGORITHM_FILEONLY_KEYS = ["custom_trim", "vcfanno"] # these analysis pipelines use R heavily downstream, and need to have samplenames # cleaned up to conform to R specifications R_DOWNSTREAM_ANALYSIS = ["rna-seq", "fastrna-seq", "scrna-seq", "chip-seq", "scrna-seq"] def organize(dirs, config, run_info_yaml, sample_names=None, is_cwl=False, integrations=None): """Organize run information from a passed YAML file or the Galaxy API. Creates the high level structure used for subsequent processing. sample_names is a list of samples to include from the overall file, for cases where we are running multiple pipelines from the same configuration file. """ from bcbio.pipeline import qcsummary if integrations is None: integrations = {} logger.info("Using input YAML configuration: %s" % run_info_yaml) assert run_info_yaml and os.path.exists(run_info_yaml), \ "Did not find input sample YAML file: %s" % run_info_yaml run_details = _run_info_from_yaml(dirs, run_info_yaml, config, sample_names, is_cwl=is_cwl, integrations=integrations) remote_retriever = None for iname, retriever in integrations.items(): if iname in config: run_details = retriever.add_remotes(run_details, config[iname]) remote_retriever = retriever out = [] for item in run_details: item["dirs"] = dirs if "name" not in item: item["name"] = ["", item["description"]] elif isinstance(item["name"], six.string_types): description = "%s-%s" % (item["name"], clean_name(item["description"])) item["name"] = [item["name"], description] item["description"] = description # add algorithm details to configuration, avoid double specification item["resources"] = _add_remote_resources(item["resources"]) item["config"] = config_utils.update_w_custom(config, item) item.pop("algorithm", None) item = add_reference_resources(item, remote_retriever) item["config"]["algorithm"]["qc"] = qcsummary.get_qc_tools(item) item["config"]["algorithm"]["vcfanno"] = vcfanno.find_annotations(item, remote_retriever) # Create temporary directories and make absolute, expanding environmental variables tmp_dir = tz.get_in(["config", "resources", "tmp", "dir"], item) if tmp_dir: # if no environmental variables, make and normalize the directory # otherwise we normalize later in distributed.transaction: if os.path.expandvars(tmp_dir) == tmp_dir: tmp_dir = utils.safe_makedir(os.path.expandvars(tmp_dir)) tmp_dir = genome.abs_file_paths(tmp_dir, do_download=not integrations) item["config"]["resources"]["tmp"]["dir"] = tmp_dir out.append(item) out = _add_provenance(out, dirs, config, not is_cwl) return out def normalize_world(data): """Normalize a data object, useful after serializetion via CWL. """ data = _normalize_files(data) return data def _add_provenance(items, dirs, config, add_provenance=True): if add_provenance: p = programs.write_versions(dirs, config=config) d = provenancedata.write_versions(dirs, items) versioncheck.testall(items) p_db = diagnostics.initialize(dirs) out = [] for item in items: if add_provenance: entity_id = diagnostics.store_entity(item) item["config"]["resources"]["program_versions"] = p item["provenance"] = {"programs": p, "entity": entity_id, "db": p_db, "data": d} out.append([item]) return out def setup_directories(work_dir, fc_dir, config, config_file): fastq_dir, galaxy_dir, config_dir = _get_full_paths(flowcell.get_fastq_dir(fc_dir) if fc_dir else None, config, config_file) # check default install for tool data if not found locally if not os.path.exists(os.path.join(galaxy_dir, "tool-data")): _, config_file = config_utils.load_system_config(work_dir=work_dir, allow_missing=True) if config_file and os.path.exists(os.path.join(os.path.dirname(config_file), "tool-data")): galaxy_dir = os.path.dirname(config_file) return {"fastq": fastq_dir, "galaxy": galaxy_dir, "work": work_dir, "flowcell": fc_dir, "config": config_dir} def _get_full_paths(fastq_dir, config, config_file): """Retrieve full paths for directories in the case of relative locations. """ if fastq_dir: fastq_dir = utils.add_full_path(fastq_dir) config_dir = utils.add_full_path(os.path.dirname(config_file)) galaxy_config_file = utils.add_full_path(config.get("galaxy_config", "universe_wsgi.ini"), config_dir) return fastq_dir, os.path.dirname(galaxy_config_file), config_dir # ## Remote resources def _add_remote_resources(resources): """Retrieve remote resources like GATK/MuTect jars present in S3. """ out = copy.deepcopy(resources) for prog, info in resources.items(): for key, val in info.items(): if key == "jar" and objectstore.is_remote(val): store_dir = utils.safe_makedir(os.path.join(os.getcwd(), "inputs", "jars", prog)) fname = objectstore.download(val, store_dir, store_dir) version_file = os.path.join(store_dir, "version.txt") if not utils.file_exists(version_file): version = install.get_gatk_jar_version(prog, fname) with open(version_file, "w") as out_handle: out_handle.write(version) else: with open(version_file) as in_handle: version = in_handle.read().strip() del out[prog][key] out[prog]["dir"] = store_dir out[prog]["version"] = version return out # ## Genome reference information def add_reference_resources(data, remote_retriever=None): """Add genome reference information to the item to process. """ aligner = data["config"]["algorithm"].get("aligner", None) if remote_retriever: data["reference"] = remote_retriever.get_refs(data["genome_build"], alignment.get_aligner_with_aliases(aligner, data), data["config"]) else: data["reference"] = genome.get_refs(data["genome_build"], alignment.get_aligner_with_aliases(aligner, data), data["dirs"]["galaxy"], data) _check_ref_files(data["reference"], data) # back compatible `sam_ref` target data["sam_ref"] = utils.get_in(data, ("reference", "fasta", "base")) ref_loc = utils.get_in(data, ("config", "resources", "species", "dir"), utils.get_in(data, ("reference", "fasta", "base"))) if remote_retriever: data = remote_retriever.get_resources(data["genome_build"], ref_loc, data) else: data["genome_resources"] = genome.get_resources(data["genome_build"], ref_loc, data) data["genome_resources"] = genome.add_required_resources(data["genome_resources"]) if effects.get_type(data) == "snpeff" and "snpeff" not in data["reference"]: data["reference"]["snpeff"] = effects.get_snpeff_files(data) if "genome_context" not in data["reference"]: data["reference"]["genome_context"] = annotation.get_context_files(data) if "viral" not in data["reference"]: data["reference"]["viral"] = viral.get_files(data) if not data["reference"]["viral"]: data["reference"]["viral"] = None if "versions" not in data["reference"]: data["reference"]["versions"] = _get_data_versions(data) data = _fill_validation_targets(data) data = _fill_prioritization_targets(data) data = _fill_capture_regions(data) # Re-enable when we have ability to re-define gemini configuration directory if False: data["reference"]["gemini"] = population.get_gemini_files(data) return data def _get_data_versions(data): """Retrieve CSV file with version information for reference data. """ genome_dir = install.get_genome_dir(data["genome_build"], data["dirs"].get("galaxy"), data) if genome_dir: version_file = os.path.join(genome_dir, "versions.csv") if version_file and os.path.exists(version_file): return version_file return None def _check_ref_files(ref_info, data): problems = [] if not data["genome_build"]: problems.append("Did not find 'genome_build' for sample: %s" % dd.get_sample_name(data)) elif not tz.get_in(["fasta", "base"], ref_info): problems.append("Did not find fasta reference file for genome %s.\n" % (data["genome_build"]) + "Check tool-data/*.loc files to ensure paths to reference data are correct.") else: for contig in ref.file_contigs(ref_info["fasta"]["base"], data["config"]): cur_problems = set([]) for char in list(contig.name): if char not in ALLOWED_CONTIG_NAME_CHARS: cur_problems.add(char) if len(cur_problems) > 0: problems.append("Found non-allowed characters in chromosome name %s: %s" % (contig.name, " ".join(list(cur_problems)))) if len(problems) > 0: msg = ("\nProblems with input reference file %s\n" % tz.get_in(["fasta", "base"], ref_info)) raise ValueError(msg + "\n".join(problems) + "\n") def _fill_validation_targets(data): """Fill validation targets pointing to globally installed truth sets. """ ref_file = dd.get_ref_file(data) sv_truth = tz.get_in(["config", "algorithm", "svvalidate"], data, {}) sv_targets = (zip(itertools.repeat("svvalidate"), sv_truth.keys()) if isinstance(sv_truth, dict) else [["svvalidate"]]) for vtarget in [list(xs) for xs in [["validate"], ["validate_regions"]] + list(sv_targets)]: val = tz.get_in(["config", "algorithm"] + vtarget, data) if val and not os.path.exists(val) and not objectstore.is_remote(val): installed_val = os.path.normpath(os.path.join(os.path.dirname(ref_file), os.pardir, "validation", val)) if os.path.exists(installed_val): data = tz.update_in(data, ["config", "algorithm"] + vtarget, lambda x: installed_val) else: raise ValueError("Configuration problem. Validation file not found for %s: %s" % (vtarget, val)) return data def _fill_capture_regions(data): """Fill short-hand specification of BED capture regions. """ special_targets = {"sv_regions": ("exons", "transcripts")} ref_file = dd.get_ref_file(data) for target in ["variant_regions", "sv_regions", "coverage"]: val = tz.get_in(["config", "algorithm", target], data) if val and not os.path.exists(val) and not objectstore.is_remote(val): installed_vals = [] # Check prioritize directory for ext in [".bed", ".bed.gz"]: installed_vals += glob.glob(os.path.normpath(os.path.join(os.path.dirname(ref_file), os.pardir, "coverage", val + ext))) if len(installed_vals) == 0: if target not in special_targets or not val.startswith(special_targets[target]): raise ValueError("Configuration problem. BED file not found for %s: %s" % (target, val)) else: assert len(installed_vals) == 1, installed_vals data = tz.update_in(data, ["config", "algorithm", target], lambda x: installed_vals[0]) return data def _fill_prioritization_targets(data): """Fill in globally installed files for prioritization. """ ref_file = dd.get_ref_file(data) for target in ["svprioritize", "coverage"]: val = tz.get_in(["config", "algorithm", target], data) if val and not os.path.exists(val) and not objectstore.is_remote(val): installed_vals = [] # Check prioritize directory for ext in [".bed", ".bed.gz"]: installed_vals += glob.glob(os.path.normpath(os.path.join(os.path.dirname(ref_file), os.pardir, "coverage", "prioritize", val + "*%s" % ext))) # Check sv-annotation directory for prioritize gene name lists if target == "svprioritize": simple_sv_bin = utils.which("simple_sv_annotation.py") if simple_sv_bin: installed_vals += glob.glob(os.path.join(os.path.dirname(os.path.realpath(simple_sv_bin)), "%s*" % os.path.basename(val))) if len(installed_vals) == 0: # some targets can be filled in later if target not in set(["coverage"]): raise ValueError("Configuration problem. BED file not found for %s: %s" % (target, val)) else: installed_val = val elif len(installed_vals) == 1: installed_val = installed_vals[0] else: # check for partial matches installed_val = None for v in installed_vals: if v.endswith(val + ".bed.gz") or v.endswith(val + ".bed"): installed_val = v break # handle date-stamped inputs if not installed_val: installed_val = sorted(installed_vals, reverse=True)[0] data = tz.update_in(data, ["config", "algorithm", target], lambda x: installed_val) return data # ## Sample and BAM read group naming def _clean_metadata(data): batches = tz.get_in(("metadata", "batch"), data) # Ensure batches are strings and have no duplicates if batches: if isinstance(batches, (list, tuple)): batches = [_clean_characters(x) for x in sorted(list(set(batches)))] else: batches = _clean_characters(batches) data["metadata"]["batch"] = batches # If we have jointcalling, add a single batch if not present elif tz.get_in(["algorithm", "jointcaller"], data) or "gvcf" in tz.get_in(["algorithm", "tools_on"], data): if "metadata" not in data: data["metadata"] = {} data["metadata"]["batch"] = "%s-joint" % dd.get_sample_name(data) analysis = dd.get_analysis(data).lower() if tz.get_in(("metadata", "sample"), data) and analysis == "rna-seq": logger.error("'sample' is a reserved keyword in metadata for RNA-seq. Please " "rename this column to something else and rerun.") sys.exit(1) return data def _clean_algorithm(data): """Clean algorithm keys, handling items that can be specified as lists or single items. """ # convert single items to lists for key in ["variantcaller", "jointcaller", "svcaller"]: val = tz.get_in(["algorithm", key], data) if val: if not isinstance(val, (list, tuple)) and isinstance(val, six.string_types): val = [val] # check for cases like [false] or [None] if isinstance(val, (list, tuple)): if len(val) == 1 and not val[0] or (isinstance(val[0], six.string_types) and val[0].lower() in ["none", "false"]): val = False data["algorithm"][key] = val return data def _organize_tools_on(data, is_cwl): """Ensure tools_on inputs match items specified elsewhere. """ # want tools_on: [gvcf] if joint calling specified in CWL if is_cwl: if tz.get_in(["algorithm", "jointcaller"], data): val = tz.get_in(["algorithm", "tools_on"], data) if not val: val = [] if not isinstance(val, (list, tuple)): val = [val] if "gvcf" not in val: val.append("gvcf") data["algorithm"]["tools_on"] = val return data def _clean_background(data): """Clean up background specification, remaining back compatible. """ allowed_keys = set(["variant", "cnv_reference"]) val = tz.get_in(["algorithm", "background"], data) errors = [] if val: out = {} # old style specification, single string for variant if isinstance(val, six.string_types): out["variant"] = _file_to_abs(val, [os.getcwd()]) elif isinstance(val, dict): for k, v in val.items(): if k in allowed_keys: if isinstance(v, six.string_types): out[k] = _file_to_abs(v, [os.getcwd()]) else: assert isinstance(v, dict) for ik, iv in v.items(): v[ik] = _file_to_abs(iv, [os.getcwd()]) out[k] = v else: errors.append("Unexpected key: %s" % k) else: errors.append("Unexpected input: %s" % val) if errors: raise ValueError("Problematic algorithm background specification for %s:\n %s" % (data["description"], "\n".join(errors))) out["cnv_reference"] = structural.standardize_cnv_reference({"config": data, "description": data["description"]}) data["algorithm"]["background"] = out return data def _clean_characters(x): """Clean problem characters in sample lane or descriptions. """ if not isinstance(x, six.string_types): x = str(x) else: if not all(ord(char) < 128 for char in x): msg = "Found unicode character in input YAML (%s)" % (x) raise ValueError(repr(msg)) for problem in [" ", ".", "/", "\\", "[", "]", "&", ";", "#", "+", ":", ")", "("]: x = x.replace(problem, "_") return x def prep_rg_names(item, config, fc_name, fc_date): """Generate read group names from item inputs. """ if fc_name and fc_date: lane_name = "%s_%s_%s" % (item["lane"], fc_date, fc_name) else: lane_name = item["description"] return {"rg": item["description"], "sample": item["description"], "lane": lane_name, "pl": (tz.get_in(["algorithm", "platform"], item) or tz.get_in(["algorithm", "platform"], item, "illumina")).lower(), "lb": tz.get_in(["metadata", "library"], item), "pu": tz.get_in(["metadata", "platform_unit"], item) or lane_name} # ## Configuration file validation def _check_for_duplicates(xs, attr, check_fn=None): """Identify and raise errors on duplicate items. """ dups = [] for key, vals in itertools.groupby(x[attr] for x in xs): if len(list(vals)) > 1: dups.append(key) if len(dups) > 0: psamples = [] for x in xs: if x[attr] in dups: psamples.append(x) # option to skip problem based on custom input function. if check_fn and check_fn(psamples): return descrs = [x["description"] for x in psamples] raise ValueError("Duplicate '%s' found in input sample configuration.\n" "Required to be unique for a project: %s\n" "Problem found in these samples: %s" % (attr, dups, descrs)) def _check_for_batch_clashes(xs): """Check that batch names do not overlap with sample names. """ names = set([x["description"] for x in xs]) dups = set([]) for x in xs: batches = tz.get_in(("metadata", "batch"), x) if batches: if not isinstance(batches, (list, tuple)): batches = [batches] for batch in batches: if batch in names: dups.add(batch) if len(dups) > 0: raise ValueError("Batch names must be unique from sample descriptions.\n" "Clashing batch names: %s" % sorted(list(dups))) def _check_for_problem_somatic_batches(items, config): """Identify problem batch setups for somatic calling. We do not support multiple tumors in a single batch and VarDict(Java) does not handle pooled calling, only tumor/normal. We allow multiple normals when batch: pon_build is set """ to_check = [] for data in items: data = copy.deepcopy(data) data["config"] = config_utils.update_w_custom(config, data) to_check.append(data) data_by_batches = collections.defaultdict(list) for data in to_check: batches = dd.get_batches(data) if batches: for batch in batches: data_by_batches[batch].append(data) for batch, items in data_by_batches.items(): if batch == "pon_build": pass elif vcfutils.get_paired(items): vcfutils.check_paired_problems(items) elif len(items) > 1: vcs = vcfutils.get_somatic_variantcallers(items) if "vardict" in vcs: raise ValueError("VarDict does not support pooled non-tumor/normal calling, in batch %s: %s" % (batch, [dd.get_sample_name(data) for data in items])) elif "mutect" in vcs or "mutect2" in vcs: raise ValueError("MuTect and MuTect2 require a 'phenotype: tumor' sample for calling, " "in batch %s: %s" % (batch, [dd.get_sample_name(data) for data in items])) def _check_for_misplaced(xs, subkey, other_keys): """Ensure configuration keys are not incorrectly nested under other keys. """ problems = [] for x in xs: check_dict = x.get(subkey, {}) for to_check in other_keys: if to_check in check_dict: problems.append((x["description"], to_check, subkey)) if len(problems) > 0: raise ValueError("\n".join(["Incorrectly nested keys found in sample YAML. These should be top level:", " sample | key name | nested under ", "----------------+-----------------+----------------"] + ["% 15s | % 15s | % 15s" % (a, b, c) for (a, b, c) in problems])) def _check_for_degenerate_interesting_groups(items): """ Make sure interesting_groups specify existing metadata and that the interesting_group is not all of the same for all of the samples """ igkey = ("algorithm", "bcbiornaseq", "interesting_groups") interesting_groups = tz.get_in(igkey, items[0], []) if isinstance(interesting_groups, str): interesting_groups = [interesting_groups] for group in interesting_groups: values = [tz.get_in(("metadata", group), x, None) for x in items] if all(x is None for x in values): raise ValueError("group %s is labelled as an interesting group, " "but does not appear in the metadata." % group) if len(items) > 1 and len(list(tz.unique(values))) == 1: raise ValueError("group %s is marked as an interesting group, " "but all samples have the same value." % group) TOPLEVEL_KEYS = set(["description", "analysis", "genome_build", "metadata", "algorithm", "resources", "files", "vrn_file", "lane", "upload", "rgnames"]) ALGORITHM_KEYS = set(["bam_sort", "custom_trim", "kraken", "write_summary", "merge_bamprep", "indelcaller", "effects", "svvalidate", "hlavalidate", "phasing", "validate", "validate_regions", "validate_genome_build", "validate_method", "clinical_reporting", "nomap_split_size", "nomap_split_targets", "background", "qc", "preseq",] + # back compatibility ["remove_lcr", "coverage_depth_max", "coverage_depth"] + # from datadict.LOOKUPS dd.get_algorithm_keys()) ALG_ALLOW_BOOLEANS = set(["merge_bamprep", "mark_duplicates", "remove_lcr", "demultiplexed", "clinical_reporting", "transcriptome_align", "fusion_mode", "assemble_transcripts", "trim_reads", "quantify_genome_alignments", "recalibrate", "realign", "cwl_reporting", "save_diskspace", "keep_multimapped", "keep_duplicates"]) ALG_ALLOW_FALSE = set(["aligner", "align_split_size", "bam_clean", "bam_sort", "effects", "phasing", "mixup_check", "indelcaller", "variantcaller", "positional_umi", "maxcov_downsample", "preseq", "use_lowfreq_filter"]) ALG_DOC_URL = "https://bcbio-nextgen.readthedocs.org/en/latest/contents/configuration.html#algorithm-parameters" def _check_algorithm_keys(item): """Check for unexpected keys in the algorithm section. Needs to be manually updated when introducing new keys, but avoids silent bugs with typos in key names. """ problem_keys = [k for k in item["algorithm"].keys() if k not in ALGORITHM_KEYS] if len(problem_keys) > 0: raise ValueError("Unexpected configuration keyword in 'algorithm' section: %s\n" "See configuration documentation for supported options:\n%s\n" % (problem_keys, ALG_DOC_URL)) def _check_algorithm_values(item): """Check for misplaced inputs in the algorithms. - Identify incorrect boolean values where a choice is required. """ problems = [] for k, v in item.get("algorithm", {}).items(): if v is True and k not in ALG_ALLOW_BOOLEANS: problems.append("%s set as true" % k) elif v is False and (k not in ALG_ALLOW_BOOLEANS and k not in ALG_ALLOW_FALSE): problems.append("%s set as false" % k) if len(problems) > 0: raise ValueError("Incorrect settings in 'algorithm' section for %s:\n%s" "\nSee configuration documentation for supported options:\n%s\n" % (item["description"], "\n".join(problems), ALG_DOC_URL)) def _check_toplevel_misplaced(item): """Check for algorithm keys accidentally placed at the top level. """ problem_keys = [k for k in item.keys() if k in ALGORITHM_KEYS] if len(problem_keys) > 0: raise ValueError("Unexpected configuration keywords found in top level of %s: %s\n" "This should be placed in the 'algorithm' section." % (item["description"], problem_keys)) problem_keys = [k for k in item.keys() if k not in TOPLEVEL_KEYS] if len(problem_keys) > 0: raise ValueError("Unexpected configuration keywords found in top level of %s: %s\n" % (item["description"], problem_keys)) def _detect_fastq_format(in_file, MAX_RECORDS=1000): ranges = {"sanger": (33, 126), "solexa": (59, 126), "illumina_1.3+": (64, 126), "illumina_1.5+": (66, 126)} gmin, gmax = 99, 0 possible = set(ranges.keys()) with closing(open_fastq(in_file)) as in_handle: four = itertools.islice(in_handle, 3, None, 4) count = 0 for line in four: if len(possible) == 1: return possible if count > MAX_RECORDS: break count += 1 vals = [ord(c) for c in line.rstrip()] # if there is a short sequence, skip it if len(vals) < 20: continue lmin = min(vals) lmax = max(vals) for encoding, (emin, emax) in ranges.items(): if encoding in possible: if lmin < emin or lmax > emax: possible.remove(encoding) return possible def _check_quality_format(items): """ Check if quality_format="standard" and fastq_format is not sanger """ SAMPLE_FORMAT = {"illumina_1.3+": "illumina", "illumina_1.5+": "illumina", "illumina_1.8+": "standard", "solexa": "solexa", "sanger": "standard"} fastq_extensions = ["fq.gz", "fastq.gz", ".fastq", ".fq"] for item in items: specified_format = item["algorithm"].get("quality_format", "standard").lower() if specified_format not in SAMPLE_FORMAT.values(): raise ValueError("Quality format specified in the YAML file" "is not supported. Supported values are %s." % (SAMPLE_FORMAT.values())) fastq_file = next((f for f in item.get("files") or [] if f.endswith(tuple(fastq_extensions))), None) if fastq_file and specified_format and not objectstore.is_remote(fastq_file): fastq_format = _detect_fastq_format(fastq_file) detected_encodings = set([SAMPLE_FORMAT[x] for x in fastq_format]) if detected_encodings: if specified_format not in detected_encodings: raise ValueError("Quality format specified in the YAML " "file might be a different encoding. " "'%s' was specified but possible formats " "detected were %s." % (specified_format, ", ".join(detected_encodings))) def _check_aligner(item): """Ensure specified aligner is valid choice. """ allowed = set(list(alignment.TOOLS.keys()) + [None, False]) if item["algorithm"].get("aligner") not in allowed: raise ValueError("Unexpected algorithm 'aligner' parameter: %s\n" "Supported options: %s\n" % (item["algorithm"].get("aligner"), sorted(list(allowed)))) def _check_variantcaller(item): """Ensure specified variantcaller is a valid choice. """ allowed = set(list(genotype.get_variantcallers().keys()) + [None, False]) vcs = item["algorithm"].get("variantcaller") if not isinstance(vcs, dict): vcs = {"variantcaller": vcs} for vc_set in vcs.values(): if not isinstance(vc_set, (tuple, list)): vc_set = [vc_set] problem = [x for x in vc_set if x not in allowed] if len(problem) > 0: raise ValueError("Unexpected algorithm 'variantcaller' parameter: %s\n" "Supported options: %s\n" % (problem, sorted(map(str, list(allowed))))) # Ensure germline somatic calling only specified with tumor/normal samples if "germline" in vcs or "somatic" in vcs: paired = vcfutils.get_paired_phenotype(item) if not paired: raise ValueError("%s: somatic/germline calling in 'variantcaller' " "but tumor/normal metadata phenotype not specified" % dd.get_sample_name(item)) def _check_svcaller(item): """Ensure the provide structural variant caller is valid. """ allowed = set(reduce(operator.add, [list(d.keys()) for d in structural._CALLERS.values()]) + [None, False]) svs = item["algorithm"].get("svcaller") if not isinstance(svs, (list, tuple)): svs = [svs] problem = [x for x in svs if x not in allowed] if len(problem) > 0: raise ValueError("Unexpected algorithm 'svcaller' parameters: %s\n" "Supported options: %s\n" % (" ".join(["'%s'" % x for x in problem]), list(allowed))) if "gatk-cnv" in svs and "cnvkit" in svs: raise ValueError("%s uses `gatk-cnv' and 'cnvkit', please use on one of these CNV callers" % dd.get_sample_name(item)) def _get_as_list(item, k): out = item["algorithm"].get(k) if not out: out = [] if not isinstance(out, (list, tuple)): out = [svs] return out def _check_hetcaller(item): """Ensure upstream SV callers requires to heterogeneity analysis are available. purecn has its own segmentation - no need in cnvkit or gatk-cnv """ hets = _get_as_list(item, "hetcaller") svs = _get_as_list(item, "svcaller") needing_cnv = hets.copy() for s in svs: if s in ["titancna"]: needing_cnv.append(s) if needing_cnv and not any([x in svs for x in ["cnvkit", "gatk-cnv"]]): raise ValueError("Heterogeneity caller(s) %s used but need CNV calls. Add `gatk-cnv` " "or `cnvkit` to `svcaller` in sample: %s" % (", ".join(needing_cnv), item["description"])) def _check_jointcaller(data): """Ensure specified jointcaller is valid. """ allowed = set(joint.get_callers() + [None, False]) cs = data["algorithm"].get("jointcaller", []) if not isinstance(cs, (tuple, list)): cs = [cs] problem = [x for x in cs if x not in allowed] if len(problem) > 0: raise ValueError("Unexpected algorithm 'jointcaller' parameter: %s\n" "Supported options: %s\n" % (problem, sorted(list(allowed), key=lambda x: x or ""))) def _check_indelcaller(data): c = data["algorithm"].get("indelcaller") if c and isinstance(c, (tuple, list)): raise ValueError("In sample %s, indelcaller specified as list. Can only be a single item: %s" % (data["description"], str(c))) def _check_hlacaller(data): supported_genomes = set(["hg38"]) c = data["algorithm"].get("hlacaller") if c: if data["genome_build"] not in supported_genomes: raise ValueError("In sample %s, HLA caller specified but genome %s not in supported: %s" % (data["description"], data["genome_build"], ", ".join(sorted(list(supported_genomes))))) def _check_realign(data): """Check for realignment, which is not supported in GATK4 """ if "gatk4" not in data["algorithm"].get("tools_off", []) and not "gatk4" == data["algorithm"].get("tools_off"): if data["algorithm"].get("realign"): raise ValueError("In sample %s, realign specified but it is not supported for GATK4. " "Realignment is generally not necessary for most variant callers." % (dd.get_sample_name(data))) def _check_trim(data): """Check for valid values for trim_reads. """ trim = data["algorithm"].get("trim_reads") if trim: if trim == "fastp" and data["algorithm"].get("align_split_size") is not False: raise ValueError("In sample %s, `trim_reads: fastp` currently requires `align_split_size: false`" % (dd.get_sample_name(data))) def _check_hla_align(data): """ Check for align: bwa if hlacaller: optitype """ algorithm = tz.get_in(["algorithm"], data) if algorithm and "aligner" in algorithm and "hlacaller" in algorithm: if algorithm["aligner"] != "bwa" and algorithm["hlacaller"].lower() == "optitype": raise ValueError(f"In sample {dd.get_sample_name(data)}, hlacaller: optitype requires aligner: bwa") def _check_sample_config(items, in_file, config): """Identify common problems in input sample configuration files.""" logger.info("Checking sample YAML configuration: %s" % in_file) _check_quality_format(items) _check_for_duplicates(items, "lane") _check_for_duplicates(items, "description") _check_for_degenerate_interesting_groups(items) _check_for_batch_clashes(items) _check_for_problem_somatic_batches(items, config) _check_for_misplaced(items, "algorithm", ["resources", "metadata", "analysis", "description", "genome_build", "lane", "files"]) [_check_toplevel_misplaced(x) for x in items] [_check_algorithm_keys(x) for x in items] [_check_algorithm_values(x) for x in items] [_check_aligner(x) for x in items] [_check_variantcaller(x) for x in items] [_check_svcaller(x) for x in items] [_check_hetcaller(x) for x in items] [_check_indelcaller(x) for x in items] [_check_jointcaller(x) for x in items] [_check_hlacaller(x) for x in items] [_check_realign(x) for x in items] [_check_trim(x) for x in items] [_check_hla_align(x) for x in items] # ## Read bcbio_sample.yaml files def _file_to_abs(x, dnames, makedir=False): """Make a file absolute using the supplied base directory choices. """ if x is None or os.path.isabs(x): return x elif isinstance(x, six.string_types) and objectstore.is_remote(x): return x elif isinstance(x, six.string_types) and x.lower() == "none": return None else: for dname in dnames: if dname: normx = os.path.normpath(os.path.join(dname, x)) if os.path.exists(normx): return normx elif makedir: utils.safe_makedir(normx) return normx raise ValueError("Did not find input file %s in %s" % (x, dnames)) def _normalize_files(item, fc_dir=None): """Ensure the files argument is a list of absolute file names. Handles BAM, single and paired end fastq, as well as split inputs. """ files = item.get("files") if files: if isinstance(files, six.string_types): files = [files] fastq_dir = flowcell.get_fastq_dir(fc_dir) if fc_dir else os.getcwd() files = [_file_to_abs(x, [os.getcwd(), fc_dir, fastq_dir]) for x in files] files = [x for x in files if x] _sanity_check_files(item, files) item["files"] = files return item def _sanity_check_files(item, files): """Ensure input files correspond with supported approaches. Handles BAM, fastqs, plus split fastqs. """ msg = None file_types = set([("bam" if x.endswith(".bam") else "fastq") for x in files if x]) if len(file_types) > 1: msg = "Found multiple file types (BAM and fastq)" file_type = file_types.pop() if file_type == "bam": if len(files) != 1: msg = "Expect a single BAM file input as input" elif file_type == "fastq": if len(files) not in [1, 2] and item["analysis"].lower() != "scrna-seq": pair_types = set([len(xs) for xs in fastq.combine_pairs(files)]) if len(pair_types) != 1 or pair_types.pop() not in [1, 2]: msg = "Expect either 1 (single end) or 2 (paired end) fastq inputs" if len(files) == 2 and files[0] == files[1]: msg = "Expect both fastq files to not be the same" if msg: raise ValueError("%s for %s: %s" % (msg, item.get("description", ""), files)) def validate_yaml(yaml_in, yaml_fn): """Check with yamllint the yaml syntaxes Looking for duplicate keys.""" try: import yamllint.linter as linter from yamllint.config import YamlLintConfig except ImportError: return conf = """{"extends": "relaxed", "rules": {"trailing-spaces": {"level": "warning"}, "new-lines": {"level": "warning"}, "new-line-at-end-of-file": {"level": "warning"}}}""" if utils.file_exists(yaml_in): with open(yaml_in) as in_handle: yaml_in = in_handle.read() out = linter.run(yaml_in, YamlLintConfig(conf)) for problem in out: msg = '%(fn)s:%(line)s:%(col)s: [%(level)s] %(msg)s' % {'fn': yaml_fn, 'line': problem.line, 'col': problem.column, 'level': problem.level, 'msg': problem.message} if problem.level == "error": raise ValueError(msg) def _run_info_from_yaml(dirs, run_info_yaml, config, sample_names=None, is_cwl=False, integrations=None): """Read run information from a passed YAML file. """ validate_yaml(run_info_yaml, run_info_yaml) with open(run_info_yaml) as in_handle: loaded = yaml.safe_load(in_handle) fc_name, fc_date = None, None if dirs.get("flowcell"): try: fc_name, fc_date = flowcell.parse_dirname(dirs.get("flowcell")) except ValueError: pass global_config = {} global_vars = {} resources = {} integration_config = {} if isinstance(loaded, dict): global_config = copy.deepcopy(loaded) del global_config["details"] if "fc_name" in loaded: fc_name = loaded["fc_name"].replace(" ", "_") if "fc_date" in loaded: fc_date = str(loaded["fc_date"]).replace(" ", "_") global_vars = global_config.pop("globals", {}) resources = global_config.pop("resources", {}) for iname in ["arvados"]: integration_config[iname] = global_config.pop(iname, {}) loaded = loaded["details"] if sample_names: loaded = [x for x in loaded if x["description"] in sample_names] if integrations: for iname, retriever in integrations.items(): if iname in config: config[iname] = retriever.set_cache(config[iname]) loaded = retriever.add_remotes(loaded, config[iname]) run_details = [] for i, item in enumerate(loaded): item = _normalize_files(item, dirs.get("flowcell")) if "lane" not in item: item["lane"] = str(i + 1) item["lane"] = _clean_characters(item["lane"]) if "description" not in item: if _item_is_bam(item): item["description"] = get_sample_name(item["files"][0]) else: raise ValueError("No `description` sample name provided for input #%s" % (i + 1)) description = _clean_characters(item["description"]) item["description"] = description # make names R safe if we are likely to use R downstream if item["analysis"].lower() in R_DOWNSTREAM_ANALYSIS: if description[0].isdigit(): valid = "X" + description logger.info("%s is not a valid R name, converting to %s." % (description, valid)) item["description"] = valid if "upload" not in item and not is_cwl: upload = global_config.get("upload", {}) # Handle specifying a local directory directly in upload if isinstance(upload, six.string_types): upload = {"dir": upload} if not upload: upload["dir"] = "../final" if fc_name: upload["fc_name"] = fc_name if fc_date: upload["fc_date"] = fc_date upload["run_id"] = "" if upload.get("dir"): upload["dir"] = _file_to_abs(upload["dir"], [dirs.get("work")], makedir=True) item["upload"] = upload item["algorithm"] = _replace_global_vars(item["algorithm"], global_vars) item["algorithm"] = genome.abs_file_paths(item["algorithm"], ignore_keys=ALGORITHM_NOPATH_KEYS, fileonly_keys=ALGORITHM_FILEONLY_KEYS, do_download=all(not x for x in integrations.values())) item["genome_build"] = str(item.get("genome_build", "")) item["algorithm"] = _add_algorithm_defaults(item["algorithm"], item.get("analysis", ""), is_cwl) item["metadata"] = add_metadata_defaults(item.get("metadata", {})) item["rgnames"] = prep_rg_names(item, config, fc_name, fc_date) if item.get("files"): item["files"] = [genome.abs_file_paths(f, do_download=all(not x for x in integrations.values())) for f in item["files"]] elif "files" in item: del item["files"] if item.get("vrn_file") and isinstance(item["vrn_file"], six.string_types): item["vrn_file"] = genome.abs_file_paths(item["vrn_file"], do_download=all(not x for x in integrations.values())) if os.path.isfile(item["vrn_file"]): # Try to prepare in place (or use ready to go inputs) try: item["vrn_file"] = vcfutils.bgzip_and_index(item["vrn_file"], config, remove_orig=False) # In case of permission errors, fix in inputs directory except IOError: inputs_dir = utils.safe_makedir(os.path.join(dirs.get("work", os.getcwd()), "inputs", item["description"])) item["vrn_file"] = vcfutils.bgzip_and_index(item["vrn_file"], config, remove_orig=False, out_dir=inputs_dir) if not tz.get_in(("metadata", "batch"), item) and tz.get_in(["algorithm", "validate"], item): raise ValueError("%s: Please specify a metadata batch for variant file (vrn_file) input.\n" % (item["description"]) + "Batching with a standard sample provides callable regions for validation.") item = _clean_metadata(item) item = _clean_algorithm(item) item = _organize_tools_on(item, is_cwl) item = _clean_background(item) # Add any global resource specifications if "resources" not in item: item["resources"] = {} for prog, pkvs in resources.items(): if prog not in item["resources"]: item["resources"][prog] = {} if pkvs is not None: for key, val in pkvs.items(): item["resources"][prog][key] = val for iname, ivals in integration_config.items(): if ivals: if iname not in item: item[iname] = {} for k, v in ivals.items(): item[iname][k] = v run_details.append(item) _check_sample_config(run_details, run_info_yaml, config) return run_details def _item_is_bam(item): files = item.get("files", []) return len(files) == 1 and files[0].endswith(".bam") def add_metadata_defaults(md): """Central location for defaults for algorithm inputs. """ defaults = {"batch": None, "phenotype": ""} for k, v in defaults.items(): if k not in md: md[k] = v return md def _get_nomap_split_targets(analysis, is_cwl): """Chromosome splitting logic based on run type. RNA-seq -- aim for smaller chunks (half chromosomes) to avoid memory issues CWL -- aim for larger chunks to allow batching and multicore old style -- larger number of chunks for better parallelization """ if analysis.lower().find("rna-seq") >= 0: return 50 elif is_cwl: return 20 else: return 200 def _add_algorithm_defaults(algorithm, analysis, is_cwl): """Central location specifying defaults for algorithm inputs. Converts allowed multiple inputs into lists if specified as a single item. Converts required single items into string if specified as a list """ if not algorithm: algorithm = {} defaults = {"archive": None, "tools_off": [], "tools_on": [], "qc": [], "trim_reads": False, "adapters": [], "effects": "snpeff", "quality_format": "standard", "expression_caller": ["salmon"] if analysis.lower().find("rna-seq") >= 0 else None, "align_split_size": None, "bam_clean": False, "nomap_split_size": 250, "nomap_split_targets": _get_nomap_split_targets(analysis, is_cwl), "mark_duplicates": False if not algorithm.get("aligner") else True, "coverage_interval": None, "min_allele_fraction": 10.0, "recalibrate": False, "realign": False, "ensemble": None, "exclude_regions": [], "variant_regions": None, "svcaller": [], "svvalidate": None, "svprioritize": None, "validate": None, "validate_regions": None, "vcfanno": []} convert_to_list = set(["tools_off", "tools_on", "hetcaller", "variantcaller", "svcaller", "qc", "disambiguate", "vcfanno", "adapters", "custom_trim", "exclude_regions"]) convert_to_single = set(["hlacaller", "indelcaller", "validate_method"]) for k, v in defaults.items(): if k not in algorithm: algorithm[k] = v for k, v in algorithm.items(): if k in convert_to_list: if v and not isinstance(v, (list, tuple)) and not isinstance(v, dict): algorithm[k] = [v] # ensure dictionary specified inputs get converted into individual lists elif v and not isinstance(v, (list, tuple)) and isinstance(v, dict): new = {} for innerk, innerv in v.items(): if innerv and not isinstance(innerv, (list, tuple)) and not isinstance(innerv, dict): innerv = [innerv] new[innerk] = innerv algorithm[k] = new elif v is None: algorithm[k] = [] elif k in convert_to_single: if v and not isinstance(v, six.string_types): if isinstance(v, (list, tuple)) and len(v) == 1: algorithm[k] = v[0] else: raise ValueError("Unexpected input in sample YAML; need a single item for %s: %s" % (k, v)) return algorithm def _replace_global_vars(xs, global_vars): """Replace globally shared names from input header with value. The value of the `algorithm` item may be a pointer to a real file specified in the `global` section. If found, replace with the full value. """ if isinstance(xs, (list, tuple)): return [_replace_global_vars(x) for x in xs] elif isinstance(xs, dict): final = {} for k, v in xs.items(): if isinstance(v, six.string_types) and v in global_vars: v = global_vars[v] final[k] = v return final else: return xs def clean_name(xs): final = [] safec = "_" for x in xs: if x not in string.ascii_letters + string.digits: if len(final) > 0 and final[-1] != safec: final.append(safec) else: final.append(x) if final[-1] == safec: final = final[:-1] return "".join(final) def prep_system(run_info_yaml, bcbio_system=None): """Prepare system configuration information from an input configuration file. This does the work of parsing the system input file and setting up directories for use in 'organize'. """ work_dir = os.getcwd() config, config_file = config_utils.load_system_config(bcbio_system, work_dir) dirs = setup_directories(work_dir, os.path.normpath(os.path.dirname(os.path.dirname(run_info_yaml))), config, config_file) return [dirs, config, run_info_yaml] bcbio-nextgen-1.2.9/bcbio/pipeline/sample.py000066400000000000000000000464741415626112400210060ustar00rootroot00000000000000"""High level entry point for processing a sample. Samples may include multiple lanes, or barcoded subsections of lanes, processed together. """ import collections import copy import glob import os import re import toolz as tz from bcbio import utils, bam, broad from bcbio.cwl import cwlutils from bcbio.log import logger from bcbio.distributed import objectstore from bcbio.pipeline.merge import merge_bam_files from bcbio.bam import callable, readstats, trim from bcbio.hla import optitype from bcbio.ngsalign import postalign from bcbio.pipeline.fastq import get_fastq_files from bcbio.pipeline.alignment import align_to_sort_bam from bcbio.pipeline import cleanbam from bcbio.variation import coverage, recalibrate, gatk from bcbio.variation import multi as vmulti import bcbio.pipeline.datadict as dd from bcbio.pipeline.fastq import merge as fq_merge from bcbio.bam import merge as bam_merge from bcbio.pipeline.sra import query_gsm, query_srr from bcbio.bam import skewer from bcbio.structural.seq2c import prep_seq2c_bed from bcbio.variation.bedutils import clean_file, merge_overlaps from bcbio.structural import get_svcallers, regions from bcbio.qc import samtools from bcbio.dragen import dragen def prepare_sample(data): """Prepare a sample to be run, potentially converting from BAM to FASTQ and/or downsampling the number of reads for a test run """ data = utils.to_single_data(data) logger.debug("Preparing %s" % data["rgnames"]["sample"]) data["files"] = get_fastq_files(data) # get_fastq_files swaps over quality scores to standard, unless trimming if not(dd.get_trim_reads(data)): data = dd.set_quality_format(data, "standard") return [[data]] def trim_sample(data): """Trim from a sample with the provided trimming method. Support methods: read_through. """ data = utils.to_single_data(data) trim_reads = dd.get_trim_reads(data) # this block is to maintain legacy configuration files if not trim_reads: logger.info("Skipping trimming of %s." % dd.get_sample_name(data)) else: if "skewer" in dd.get_tools_on(data) or trim_reads == "skewer": trim_adapters = skewer.trim_adapters else: trim_adapters = trim.trim_adapters out_files = trim_adapters(data) data["files"] = out_files return [[data]] # ## Alignment def _link_bam_file(in_file, new_dir, data): """Provide symlinks of BAM file and existing indexes if needed. """ new_dir = utils.safe_makedir(new_dir) out_file = os.path.join(new_dir, os.path.basename(in_file)) if not utils.file_exists(out_file): out_file = os.path.join(new_dir, "%s-prealign.bam" % dd.get_sample_name(data)) if data.get("cwl_keys"): # Has indexes, we're okay to go with the original file if utils.file_exists(in_file + ".bai"): out_file = in_file else: utils.copy_plus(in_file, out_file) else: utils.symlink_plus(in_file, out_file) return out_file def _add_supplemental_bams(data): """Add supplemental files produced by alignment, useful for structural variant calling. """ file_key = "work_bam" if data.get(file_key): for supext in ["disc", "sr"]: base, ext = os.path.splitext(data[file_key]) test_file = "%s-%s%s" % (base, supext, ext) if os.path.exists(test_file): sup_key = file_key + "_plus" if sup_key not in data: data[sup_key] = {} data[sup_key][supext] = test_file return data def _add_hla_files(data): """Add extracted fastq files of HLA alleles for typing. """ if "hla" not in data: data["hla"] = {} # if HLA bam was created separately, FASTQ files will be based off of it if dd.get_hla_bam(data): align_file = dd.get_hla_bam(data) else: align_file = dd.get_align_bam(data) hla_dir = os.path.join(os.path.dirname(align_file), "hla") if not os.path.exists(hla_dir): hla_files = None else: hla_files = sorted(list(glob.glob(os.path.join(hla_dir, "%s.*.fq" % os.path.basename(align_file))))) data["hla"]["fastq"] = hla_files return data def process_alignment(data, alt_input=None): """Do an alignment of fastq files, preparing a sorted BAM output file. """ data = cwlutils.normalize_missing(utils.to_single_data(data)) data = cwlutils.unpack_tarballs(data, data) fastq1, fastq2 = dd.get_input_sequence_files(data) if alt_input: fastq1, fastq2 = alt_input config = data["config"] aligner = config["algorithm"].get("aligner", None) if fastq1 and objectstore.file_exists_or_remote(fastq1) and aligner: if dd.get_umi_type(data) == "dragen": assert bam.is_bam(fastq1), f"umi_type: dragen needs a BAM file as input." data = dragen.fix_umi_dragen_bam(data, bam=fastq1) # fastq1 = bam.sort(fastq1, dd.get_config(data)) # bam.index(fastq1, dd.get_config(data)) # data["work_bam"] = fastq1 else: # logger.info("Aligning lane %s with %s aligner" % (data["rgnames"]["lane"], aligner)) data = align_to_sort_bam(fastq1, fastq2, aligner, data) if dd.get_correct_umis(data): data["work_bam"] = postalign.correct_umis(data) if dd.get_umi_consensus(data): data["umi_bam"] = dd.get_work_bam(data) if fastq2 or dd.get_umi_type(data) == "dragen": f1, f2, avg_cov = postalign.umi_consensus(data) data["config"]["algorithm"]["rawumi_avg_cov"] = avg_cov del data["config"]["algorithm"]["umi_type"] data["config"]["algorithm"]["mark_duplicates"] = False data = align_to_sort_bam(f1, f2, aligner, data) else: raise ValueError("Single fastq input for UMI processing; fgbio needs paired reads: %s" % dd.get_sample_name(data)) data = _add_supplemental_bams(data) elif fastq1 and objectstore.file_exists_or_remote(fastq1) and fastq1.endswith(".bam"): sort_method = config["algorithm"].get("bam_sort") bamclean = config["algorithm"].get("bam_clean") if bamclean is True or bamclean == "picard": if sort_method and sort_method != "coordinate": raise ValueError("Cannot specify `bam_clean: picard` with `bam_sort` other than coordinate: %s" % sort_method) ref_file = dd.get_ref_file(data) out_bam = cleanbam.picard_prep(fastq1, data["rgnames"], ref_file, data["dirs"], data) elif bamclean == "fixrg": out_bam = cleanbam.fixrg(fastq1, data["rgnames"], dd.get_ref_file(data), data["dirs"], data) elif bamclean == "remove_extracontigs": out_bam = cleanbam.remove_extracontigs(fastq1, data) elif sort_method: runner = broad.runner_from_path("picard", config) out_file = os.path.join(data["dirs"]["work"], "{}-sort.bam".format( os.path.splitext(os.path.basename(fastq1))[0])) if not utils.file_exists(out_file): work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "bamclean", dd.get_sample_name(data))) out_file = os.path.join(work_dir, "{}-sort.bam".format(dd.get_sample_name(data))) out_bam = runner.run_fn("picard_sort", fastq1, sort_method, out_file) else: out_bam = _link_bam_file(fastq1, os.path.join(dd.get_work_dir(data), "prealign", dd.get_sample_name(data)), data) bam.index(out_bam, data["config"]) bam.check_header(out_bam, data["rgnames"], dd.get_ref_file(data), data["config"]) dedup_bam = postalign.dedup_bam(out_bam, data) bam.index(dedup_bam, data["config"]) data["work_bam"] = dedup_bam elif fastq1 and objectstore.file_exists_or_remote(fastq1) and fastq1.endswith(".cram"): data["work_bam"] = fastq1 elif fastq1 is None and not dd.get_aligner(data): data["config"]["algorithm"]["variantcaller"] = False data["work_bam"] = None elif not fastq1: raise ValueError("No 'files' specified for input sample: %s" % dd.get_sample_name(data)) elif "kraken" in config["algorithm"]: # kraken doesn's need bam pass else: raise ValueError("Could not process input file from sample configuration. \n" + fastq1 + "\nIs the path to the file correct or is empty?\n" + "If it is a fastq file (not pre-aligned BAM or CRAM), " "is an aligner specified in the input configuration?") if data.get("work_bam"): # Add stable 'align_bam' target to use for retrieving raw alignment data["align_bam"] = data["work_bam"] data = _add_hla_files(data) return [[data]] def prep_samples(*items): """Handle any global preparatory steps for samples with potentially shared data. Avoids race conditions in postprocess alignment when performing prep tasks on shared files between multiple similar samples. Cleans input BED files to avoid issues with overlapping input segments. """ out = [] for data in (utils.to_single_data(x) for x in items): data = cwlutils.normalize_missing(data) data = cwlutils.unpack_tarballs(data, data) data = clean_inputs(data) out.append([data]) return out def clean_inputs(data): """Clean BED input files to avoid overlapping segments that cause downstream issues. Per-merges inputs to avoid needing to call multiple times during later parallel steps. """ if not utils.get_in(data, ("config", "algorithm", "variant_regions_orig")): data["config"]["algorithm"]["variant_regions_orig"] = dd.get_variant_regions(data) clean_vr = clean_file(dd.get_variant_regions(data), data, prefix="cleaned-") merged_vr = merge_overlaps(clean_vr, data) data["config"]["algorithm"]["variant_regions"] = clean_vr data["config"]["algorithm"]["variant_regions_merged"] = merged_vr if dd.get_coverage(data): if not utils.get_in(data, ("config", "algorithm", "coverage_orig")): data["config"]["algorithm"]["coverage_orig"] = dd.get_coverage(data) clean_cov_bed = clean_file(dd.get_coverage(data), data, prefix="cov-", simple=True) merged_cov_bed = merge_overlaps(clean_cov_bed, data) data["config"]["algorithm"]["coverage"] = clean_cov_bed data["config"]["algorithm"]["coverage_merged"] = merged_cov_bed if "seq2c" in get_svcallers(data): seq2c_ready_bed = prep_seq2c_bed(data) if not seq2c_ready_bed: logger.warning("Can't run Seq2C without a svregions or variant_regions BED file") else: data["config"]["algorithm"]["seq2c_bed_ready"] = seq2c_ready_bed elif regions.get_sv_bed(data): dd.set_sv_regions(data, clean_file(regions.get_sv_bed(data), data, prefix="svregions-")) if "purecn" in get_svcallers(data): from bcbio.structural import purecn purecn_ready_bed = purecn.process_intervals(data) if not purecn_ready_bed: logger.warning("Can't run PureCN without a svregions or variant_regions BED file") else: data["config"]["algorithm"]["purecn_bed_ready"] = purecn_ready_bed return data def postprocess_alignment(data): """Perform post-processing steps required on full BAM files. Prepares list of callable genome regions allowing subsequent parallelization. """ data = cwlutils.normalize_missing(utils.to_single_data(data)) data = cwlutils.unpack_tarballs(data, data) bam_file = data.get("align_bam") or data.get("work_bam") ref_file = dd.get_ref_file(data) artifacts = gatk.collect_artifact_metrics(data) if artifacts: data = dd.update_summary_qc(data, "picard", artifacts.pop(), artifacts) oxog = gatk.collect_oxog_metrics(data) data = dd.update_summary_qc(data, "picard", oxog.pop(), oxog) if vmulti.bam_needs_processing(data) and bam_file and bam_file.endswith(".bam"): out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data))) bam_file_ready = os.path.join(out_dir, os.path.basename(bam_file)) if not utils.file_exists(bam_file_ready): utils.symlink_plus(bam_file, bam_file_ready) bam.index(bam_file_ready, data["config"]) covinfo = callable.sample_callable_bed(bam_file_ready, ref_file, data) callable_region_bed, nblock_bed = \ callable.block_regions(covinfo.raw_callable, bam_file_ready, ref_file, data) data["regions"] = {"nblock": nblock_bed, "callable": covinfo.raw_callable, "sample_callable": covinfo.callable, "mapped_stats": readstats.get_cache_file(data)} data["depth"] = covinfo.depth_files data = coverage.assign_interval(data) data = samtools.run_and_save(data) data = recalibrate.prep_recal(data) data = recalibrate.apply_recal(data) elif dd.get_variant_regions(data): callable_region_bed, nblock_bed = \ callable.block_regions(dd.get_variant_regions(data), bam_file, ref_file, data) data["regions"] = {"nblock": nblock_bed, "callable": dd.get_variant_regions(data), "sample_callable": dd.get_variant_regions(data)} return [[data]] def _merge_out_from_infiles(in_files): """Generate output merged file name from set of input files. Handles non-shared filesystems where we don't know output path when setting up split parts. """ fname = os.path.commonprefix([os.path.basename(f) for f in in_files]) while fname.endswith(("-", "_", ".")): fname = fname[:-1] ext = os.path.splitext(in_files[0])[-1] dirname = os.path.dirname(in_files[0]) while dirname.endswith(("split", "merge")): dirname = os.path.dirname(dirname) return os.path.join(dirname, "%s%s" % (fname, ext)) def delayed_bam_merge(data): """Perform a merge on previously prepped files, delayed in processing. Handles merging of associated split read and discordant files if present. """ if data.get("combine"): assert len(data["combine"].keys()) == 1 file_key = list(data["combine"].keys())[0] extras = [] for x in data["combine"][file_key].get("extras", []): if isinstance(x, (list, tuple)): extras.extend(x) else: extras.append(x) if file_key in data: extras.append(data[file_key]) in_files = sorted(list(set(extras))) out_file = tz.get_in(["combine", file_key, "out"], data, _merge_out_from_infiles(in_files)) sup_exts = data.get(file_key + "_plus", {}).keys() for ext in list(sup_exts) + [""]: merged_file = None if os.path.exists(utils.append_stem(out_file, "-" + ext)): cur_out_file, cur_in_files = out_file, [] if ext: cur_in_files = list(filter(os.path.exists, (utils.append_stem(f, "-" + ext) for f in in_files))) cur_out_file = utils.append_stem(out_file, "-" + ext) if len(cur_in_files) > 0 else None else: cur_in_files, cur_out_file = in_files, out_file if cur_out_file: config = copy.deepcopy(data["config"]) if len(cur_in_files) > 0: merged_file = merge_bam_files(cur_in_files, os.path.dirname(cur_out_file), data, out_file=cur_out_file) else: assert os.path.exists(cur_out_file) merged_file = cur_out_file if merged_file: if ext: data[file_key + "_plus"][ext] = merged_file else: data[file_key] = merged_file data.pop("region", None) data.pop("combine", None) return [[data]] def merge_split_alignments(data): """Merge split BAM inputs generated by common workflow language runs. """ data = utils.to_single_data(data) data = _merge_align_bams(data) data = _merge_hla_fastq_inputs(data) return [[data]] def _merge_align_bams(data): """Merge multiple alignment BAMs, including split and discordant reads. """ for key in (["work_bam"], ["work_bam_plus", "disc"], ["work_bam_plus", "sr"], ["umi_bam"]): in_files = tz.get_in(key, data, []) if not isinstance(in_files, (list, tuple)): in_files = [in_files] in_files = [x for x in in_files if x and x != "None"] if in_files: ext = "-%s" % key[-1] if len(key) > 1 else "" out_file = os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data), "%s-sort%s.bam" % (dd.get_sample_name(data), ext)) merged_file = merge_bam_files(in_files, utils.safe_makedir(os.path.dirname(out_file)), data, out_file=out_file) data = tz.update_in(data, key, lambda x: merged_file) else: data = tz.update_in(data, key, lambda x: None) if "align_bam" in data and "work_bam" in data: data["align_bam"] = data["work_bam"] return data def _merge_hla_fastq_inputs(data): """Merge HLA inputs from a split initial alignment. """ hla_key = ["hla", "fastq"] hla_sample_files = [x for x in (tz.get_in(hla_key, data) or []) if x and x != "None"] merged_hlas = None if hla_sample_files: out_files = collections.defaultdict(list) for hla_file in utils.flatten(hla_sample_files): rehla = re.search(r".hla.(?P[\w-]+).fq", hla_file) if rehla: hlatype = rehla.group("hlatype") out_files[hlatype].append(hla_file) if len(out_files) > 0: hla_outdir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data), "hla")) merged_hlas = [] for hlatype, files in out_files.items(): out_file = os.path.join(hla_outdir, "%s-%s.fq" % (dd.get_sample_name(data), hlatype)) optitype.combine_hla_fqs([(hlatype, f) for f in files], out_file, data) merged_hlas.append(out_file) data = tz.update_in(data, hla_key, lambda x: merged_hlas) return data def prepare_bcbio_samples(sample): """ Function that will use specific function to merge input files """ logger.info("Preparing %s files %s to merge into %s." % (sample['name'], sample['files'], sample['out_file'])) if sample['fn'] == "fq_merge": out_file = fq_merge(sample['files'], sample['out_file'], sample['config']) elif sample['fn'] == "bam_merge": out_file = bam_merge(sample['files'], sample['out_file'], sample['config']) elif sample['fn'] == "query_gsm": out_file = query_gsm(sample['files'], sample['out_file'], sample['config']) elif sample['fn'] == "query_srr": out_file = query_srr(sample['files'], sample['out_file'], sample['config']) sample['out_file'] = out_file return [sample] bcbio-nextgen-1.2.9/bcbio/pipeline/shared.py000066400000000000000000000310411415626112400207530ustar00rootroot00000000000000"""Pipeline functionality shared amongst multiple analysis types. """ import os from contextlib import contextmanager import functools import operator import tempfile import pybedtools import pysam import six import toolz as tz from bcbio import bam, broad, utils from bcbio.bam import ref from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.utils import file_exists, save_diskspace from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.provenance import do from functools import reduce # ## Split/Combine helpers def combine_bam(in_files, out_file, config): """Parallel target to combine multiple BAM files. """ runner = broad.runner_from_path("picard", config) runner.run_fn("picard_merge", in_files, out_file) for in_file in in_files: save_diskspace(in_file, "Merged into {0}".format(out_file), config) bam.index(out_file, config) return out_file def get_noalt_contigs(data): """Retrieve contigs without alternatives as defined in bwa *.alts files. If no alt files present (when we're not aligning with bwa), work around with standard set of alts based on hg38 -- anything with HLA, _alt or _decoy in the name. """ alts = set([]) alt_files = [f for f in tz.get_in(["reference", "bwa", "indexes"], data, []) if f.endswith("alt")] if alt_files: for alt_file in alt_files: with open(alt_file) as in_handle: for line in in_handle: if not line.startswith("@"): alts.add(line.split()[0].strip()) else: for contig in ref.file_contigs(dd.get_ref_file(data)): if ("_alt" in contig.name or "_decoy" in contig.name or contig.name.startswith("HLA-") or ":" in contig.name): alts.add(contig.name) return [c for c in ref.file_contigs(dd.get_ref_file(data)) if c.name not in alts] def write_nochr_reads(in_file, out_file, config): """Write a BAM file of reads that are not mapped on a reference chromosome. This is useful for maintaining non-mapped reads in parallel processes that split processing by chromosome. """ if not file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: samtools = config_utils.get_program("samtools", config) cmd = "{samtools} view -b -f 4 {in_file} > {tx_out_file}" do.run(cmd.format(**locals()), "Select unmapped reads") return out_file def write_noanalysis_reads(in_file, region_file, out_file, config): """Write a BAM file of reads in the specified region file that are not analyzed. We want to get only reads not in analysis regions but also make use of the BAM index to perform well on large files. The tricky part is avoiding command line limits. There is a nice discussion on SeqAnswers: http://seqanswers.com/forums/showthread.php?t=29538 sambamba supports intersection via an input BED file so avoids command line length issues. """ if not file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: bedtools = config_utils.get_program("bedtools", config) sambamba = config_utils.get_program("sambamba", config) cl = ("{sambamba} view -f bam -l 0 -L {region_file} {in_file} | " "{bedtools} intersect -abam - -b {region_file} -f 1.0 -nonamecheck" "> {tx_out_file}") do.run(cl.format(**locals()), "Select unanalyzed reads") return out_file def subset_bam_by_region(in_file, region, config, out_file_base=None): """Subset BAM files based on specified chromosome region. """ if out_file_base is not None: base, ext = os.path.splitext(out_file_base) else: base, ext = os.path.splitext(in_file) out_file = "%s-subset%s%s" % (base, region, ext) if not file_exists(out_file): with pysam.Samfile(in_file, "rb") as in_bam: target_tid = in_bam.gettid(region) assert region is not None, \ "Did not find reference region %s in %s" % \ (region, in_file) with file_transaction(config, out_file) as tx_out_file: with pysam.Samfile(tx_out_file, "wb", template=in_bam) as out_bam: for read in in_bam: if read.tid == target_tid: out_bam.write(read) return out_file def subset_bed_by_chrom(in_file, chrom, data, out_dir=None): """Subset a BED file to only have items from the specified chromosome. """ if out_dir is None: out_dir = os.path.dirname(in_file) base, ext = os.path.splitext(os.path.basename(in_file)) out_file = os.path.join(out_dir, "%s-%s%s" % (base, chrom, ext)) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: _rewrite_bed_with_chrom(in_file, tx_out_file, chrom) return out_file def _rewrite_bed_with_chrom(in_file, out_file, chrom): with open(in_file) as in_handle: with open(out_file, "w") as out_handle: for line in in_handle: if line.startswith("%s\t" % chrom): out_handle.write(line) def _subset_bed_by_region(in_file, out_file, regions, ref_file, do_merge=True): orig_bed = pybedtools.BedTool(in_file) region_bed = pybedtools.BedTool("\n".join(["%s\t%s\t%s" % (c, s, e) for c, s, e in regions]) + "\n", from_string=True) sort_kwargs = {"faidx": ref.fasta_idx(ref_file)} if ref_file else {} if do_merge: orig_bed.intersect(region_bed, nonamecheck=True).saveas().sort(**sort_kwargs).saveas().\ filter(lambda x: len(x) >= 1).saveas().merge().saveas(out_file) else: orig_bed.intersect(region_bed, nonamecheck=True).saveas().sort(**sort_kwargs).saveas().\ filter(lambda x: len(x) >= 1).saveas(out_file) def remove_lcr_regions(orig_bed, items): """If configured and available, update a BED file to remove low complexity regions. """ lcr_bed = tz.get_in(["genome_resources", "variation", "lcr"], items[0]) if lcr_bed and os.path.exists(lcr_bed) and "lcr" in get_exclude_regions(items): return _remove_regions(orig_bed, [lcr_bed], "nolcr", items[0]) else: return orig_bed def remove_polyx_regions(in_file, items): """Remove polyX stretches, contributing to long variant runtimes. """ ex_bed = tz.get_in(["genome_resources", "variation", "polyx"], items[0]) if ex_bed and os.path.exists(ex_bed): return _remove_regions(in_file, [ex_bed], "nopolyx", items[0]) else: return in_file def add_highdepth_genome_exclusion(items): """Add exclusions to input items to avoid slow runtimes on whole genomes. """ out = [] for d in items: d = utils.deepish_copy(d) if dd.get_coverage_interval(d) == "genome": e = dd.get_exclude_regions(d) if "highdepth" not in e: e.append("highdepth") d = dd.set_exclude_regions(d, e) out.append(d) return out def remove_highdepth_regions(in_file, items): """Remove high depth regions from a BED file for analyzing a set of calls. Tries to avoid spurious errors and slow run times in collapsed repeat regions. Also adds ENCODE blacklist regions which capture additional collapsed repeats around centromeres. """ encode_bed = tz.get_in(["genome_resources", "variation", "encode_blacklist"], items[0]) if encode_bed and os.path.exists(encode_bed): return _remove_regions(in_file, [encode_bed], "glimit", items[0]) else: return in_file def _remove_regions(in_file, remove_beds, ext, data): """Subtract a list of BED files from an input BED. General approach handling none, one and more remove_beds. """ from bcbio.variation import bedutils out_file = "%s-%s.bed" % (utils.splitext_plus(in_file)[0], ext) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: with bedtools_tmpdir(data): if len(remove_beds) == 0: to_remove = None elif len(remove_beds) == 1: to_remove = remove_beds[0] else: to_remove = "%s-all.bed" % utils.splitext_plus(tx_out_file)[0] with open(to_remove, "w") as out_handle: for b in remove_beds: with utils.open_gzipsafe(b) as in_handle: for line in in_handle: parts = line.split("\t") out_handle.write("\t".join(parts[:4]).rstrip() + "\n") if utils.file_exists(to_remove): to_remove = bedutils.sort_merge(to_remove, data) if to_remove and utils.file_exists(to_remove): cmd = "bedtools subtract -nonamecheck -a {in_file} -b {to_remove} > {tx_out_file}" do.run(cmd.format(**locals()), "Remove problematic regions: %s" % ext) else: utils.symlink_plus(in_file, out_file) return out_file @contextmanager def bedtools_tmpdir(data): with tx_tmpdir(data) as tmpdir: orig_tmpdir = tempfile.gettempdir() pybedtools.set_tempdir(tmpdir) yield if orig_tmpdir and os.path.exists(orig_tmpdir): pybedtools.set_tempdir(orig_tmpdir) else: tempfile.tempdir = None def get_exclude_regions(items): """Retrieve regions to exclude from a set of items. Includes back compatibility for older custom ways of specifying different exclusions. """ def _get_sample_excludes(d): excludes = dd.get_exclude_regions(d) # back compatible if tz.get_in(("config", "algorithm", "remove_lcr"), d, False): excludes.append("lcr") return excludes out = reduce(operator.add, [_get_sample_excludes(d) for d in items]) return sorted(list(set(out))) def remove_exclude_regions(f): """Remove regions to exclude based on configuration: polyA, LCR, high depth. """ exclude_fns = {"lcr": remove_lcr_regions, "highdepth": remove_highdepth_regions, "polyx": remove_polyx_regions} @functools.wraps(f) def wrapper(variant_regions, region, out_file, items=None, do_merge=True, data=None): region_bed = f(variant_regions, region, out_file, items, do_merge, data) if region_bed and isinstance(region_bed, six.string_types) and os.path.exists(region_bed) and items: for e in get_exclude_regions(items): if e in exclude_fns: region_bed = exclude_fns[e](region_bed, items) return region_bed return wrapper def to_multiregion(region): """Convert a single region or multiple region specification into multiregion list. If a single region (chrom, start, end), returns [(chrom, start, end)] otherwise returns multiregion. """ assert isinstance(region, (list, tuple)), region if isinstance(region[0], (list, tuple)): return region else: assert len(region) == 3 return [tuple(region)] @remove_exclude_regions def subset_variant_regions(variant_regions, region, out_file, items=None, do_merge=True, data=None): """Return BED file subset by a specified chromosome region. variant_regions is a BED file, region is a chromosome name or tuple of (name, start, end) for a genomic region. """ if region is None: return variant_regions elif variant_regions is None: return region elif not isinstance(region, (list, tuple)) and region.find(":") > 0: raise ValueError("Partial chromosome regions not supported") else: merge_text = "-unmerged" if not do_merge else "" subset_file = "{0}".format(utils.splitext_plus(out_file)[0]) subset_file += "%s-regions.bed" % (merge_text) if not os.path.exists(subset_file): data = items[0] if items else data with file_transaction(data, subset_file) as tx_subset_file: if isinstance(region, (list, tuple)): _subset_bed_by_region(variant_regions, tx_subset_file, to_multiregion(region), dd.get_ref_file(data), do_merge=do_merge) else: _rewrite_bed_with_chrom(variant_regions, tx_subset_file, region) if os.path.getsize(subset_file) == 0: return region else: return subset_file bcbio-nextgen-1.2.9/bcbio/pipeline/sra.py000066400000000000000000000121231415626112400202720ustar00rootroot00000000000000"""Deal with sra Id names as input""" import os import subprocess import json import re import traceback from bcbio.log import logger from bcbio import utils from bcbio.provenance import do from bcbio.bam.fastq import combine_pairs from bcbio.pipeline import fastq def is_gsm(fn): p = re.compile(r"^GSM[0-9]+$") if p.match(fn) and not utils.file_exists(fn): return True def is_srr(fn): p = re.compile(r"^SRR[0-9]+$") if p.match(fn) and not utils.file_exists(fn): return True def _query_info(db, ids): """ returns a list of urls to download SRR """ url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db={0}\&id={1}".format(db, ids) cmd = "curl {0}".format(url) process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out = process.stdout.read().decode().strip() data = [] for line in out.split("RUN_SET")[1].split("RUN")[1].split("SRAFile"): if line.find("url") > -1: srr = line.split("url=")[1].split(" ")[0].replace("\"", "") data.append(srr) return data def query_gsm(gsm, out_file, config = {}): gsm = gsm[0] out_dir = os.path.dirname(os.path.abspath(out_file)) name = utils.splitext_plus(os.path.basename(out_file))[0] url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=sra\&term={0}\&retmode=json".format(gsm) cmd = "curl {0}".format(url) process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out = process.stdout.read().decode().strip() data = json.loads(out) ids = data.get("esearchresult", {}).get("idlist", []) logger.debug("Get id sample for %s" % gsm) if ids: srrall = _query_info("sra", ids[-1]) logger.debug("Get FTP link for %s : %s" % (ids[-1], srrall)) outs = [] for srx in srrall: sra_dir = utils.safe_makedir(os.path.join(out_dir, name)) srafiles = _download_srx(srx, sra_dir) if srafiles: logger.debug("Get SRA for %s: %s" % (gsm, " ".join(srafiles))) for sra in srafiles: fastq_fn = _convert_fastq(sra, out_dir) if fastq_fn: outs.extend(fastq_fn) logger.debug("Get FASTQ for %s: %s" % (gsm, " ".join(outs))) if outs: files = combine_pairs(outs) out_file = fastq.merge(files, out_file, config) return out_file def query_srr(sra, out_file, config = {}): sra = sra[0] outs = [] out_dir = os.path.dirname(os.path.abspath(out_file)) name = utils.splitext_plus(os.path.basename(out_file))[0] srrall = [] for srr in sra: srrall.append(_create_link(srr)) logger.debug("Get FTP link for %s : %s" % (name, srrall)) for srx in srrall: sra_dir = utils.safe_makedir(os.path.join(out_dir, name)) srafiles = _download_srx(srx, sra_dir) if srafiles: logger.debug("Get SRA for %s: %s" % (sra, " ".join(srafiles))) for sra in srafiles: fastq_fn = _convert_fastq(sra, out_dir) if fastq_fn: outs.extend(fastq_fn) logger.debug("Get FASTQ for %s: %s" % (sra, " ".join(outs))) if outs: files = combine_pairs(outs) out_file = fastq.merge(files, out_file, config) return out_file def _create_link(sraid): sraprex = sraid[0:6] url = "ftp://ftp-trace.ncbi.nih.gov/sra/sra-instant/reads/ByRun/sra/SRR/{sraprex}/{sraid}" return url.format(**locals()) def _download_srx(url, out_dir): cmd = "wget -N -r -nH -nd -np -nv {0}".format(url) out_dir = os.path.abspath(utils.safe_makedir(out_dir)) with utils.chdir(out_dir): try: do.run(cmd, "Download %s" % url ) except: logger.warning("Sample path not found in database. Skipping.") traceback.print_exc() return None return [os.path.join(out_dir, fn) for fn in os.listdir(out_dir)] def _download_sra(sraid, outdir): url = _create_link(sraid) cmd = "wget -O {out_file} {url}" out_file = os.path.join(outdir, "%s.sra" % sraid) if not utils.file_exists(out_file): do.run(cmd, "Download %s" % sraid) return out_file def _convert_fastq(srafn, outdir, single=False): "convert sra to fastq" cmd = "fastq-dump --split-files --gzip {srafn}" cmd = "%s %s" % (utils.local_path_export(), cmd) # note /path/dir/SRRRXXX.1 sraid = os.path.basename(srafn) if not srafn: return None if not single: out_file = [os.path.join(outdir, "%s_1.fastq.gz" % sraid), os.path.join(outdir, "%s_2.fastq.gz" % sraid)] if not utils.file_exists(out_file[0]): with utils.chdir(outdir): do.run(cmd.format(**locals()), "Convert to fastq %s" % sraid) if not utils.file_exists(out_file[0]): raise IOError("SRA %s didn't convert, something happened." % srafn) return [out for out in out_file if utils.file_exists(out)] else: raise ValueError("Not supported single-end sra samples for now.") bcbio-nextgen-1.2.9/bcbio/pipeline/tools.py000066400000000000000000000026671415626112400206610ustar00rootroot00000000000000"""Access tool command lines, handling back compatibility and file type issues. Abstracts out """ import subprocess import toolz as tz from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils def get_tabix_cmd(config): """Retrieve tabix command, handling new bcftools tabix and older tabix. """ try: bcftools = config_utils.get_program("bcftools", config) # bcftools has terrible error codes and stderr output, swallow those. bcftools_tabix = subprocess.check_output("{bcftools} 2>&1; echo $?".format(**locals()), shell=True).decode().find("tabix") >= 0 except config_utils.CmdNotFound: bcftools_tabix = False if bcftools_tabix: return "{0} tabix".format(bcftools) else: tabix = config_utils.get_program("tabix", config) return tabix def get_bgzip_cmd(config, is_retry=False): """Retrieve command to use for bgzip, trying to use bgzip parallel threads. By default, parallel bgzip is enabled in bcbio. If it causes problems please report them. You can turn parallel bgzip off with `tools_off: [pbgzip]` """ num_cores = tz.get_in(["algorithm", "num_cores"], config, 1) cmd = config_utils.get_program("bgzip", config) if (not is_retry and num_cores > 1 and "pbgzip" not in dd.get_tools_off({"config": config})): cmd += " --threads %s" % num_cores return cmd bcbio-nextgen-1.2.9/bcbio/pipeline/variation.py000066400000000000000000000167231415626112400215130ustar00rootroot00000000000000"""Next-gen variant detection and evaluation with GATK and SnpEff. """ import collections import os import toolz as tz from bcbio import utils from bcbio.cwl import cwlutils from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.variation.genotype import variant_filtration, get_variantcaller from bcbio.variation import (annotation, damage, effects, genotype, germline, population, prioritize, validate, vcfutils) from bcbio.variation import multi as vmulti # ## CWL summarization def summarize_vc(items): """CWL target: summarize variant calls and validation for multiple samples. """ items = [utils.to_single_data(x) for x in utils.flatten(items)] items = [_normalize_vc_input(x) for x in items] items = validate.summarize_grading(items) items = [utils.to_single_data(x) for x in items] out = {"validate": validate.combine_validations(items), "variants": {"calls": [], "gvcf": [], "samples": []}} added = set([]) variants_by_sample = collections.defaultdict(list) sample_order = [] for data in items: batch_samples = data.get("batch_samples", [dd.get_sample_name(data)]) for s in batch_samples: if s not in sample_order: sample_order.append(s) if data.get("vrn_file"): # Only get batches if we're actually doing variantcalling in bcbio # otherwise we'll be using the original files names = dd.get_batches(data) if dd.get_variantcaller(data) else None if not names: names = [dd.get_sample_name(data)] batch_name = names[0] if data.get("vrn_file_joint") is not None: to_add = [("vrn_file", "gvcf", dd.get_sample_name(data)), ("vrn_file_joint", "calls", batch_name)] else: to_add = [("vrn_file", "calls", batch_name)] for vrn_key, out_key, name in to_add: cur_name = "%s-%s" % (name, dd.get_variantcaller(data)) out_file = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "variants", out_key)), "%s.vcf.gz" % cur_name) for s in batch_samples: variants_by_sample[s].append(out_file) if cur_name not in added: added.add(cur_name) # Ideally could symlink here but doesn't appear to work with # Docker container runs on Toil where PATHs don't get remapped utils.copy_plus(os.path.realpath(data[vrn_key]), out_file) vcfutils.bgzip_and_index(out_file, data["config"]) out["variants"][out_key].append(out_file) for sample in sample_order: out["variants"]["samples"].append(variants_by_sample[sample]) return [out] def _normalize_vc_input(data): """Normalize different types of variant calling inputs. Handles standard and ensemble inputs. """ if data.get("ensemble"): for k in ["batch_samples", "validate", "vrn_file"]: data[k] = data["ensemble"][k] data["config"]["algorithm"]["variantcaller"] = "ensemble" data["metadata"] = {"batch": data["ensemble"]["batch_id"]} return data # ## Genotyping def postprocess_variants(items): """Provide post-processing of variant calls: filtering and effects annotation. """ vrn_key = "vrn_file" if not isinstance(items, dict): items = [utils.to_single_data(x) for x in items] if "vrn_file_joint" in items[0]: vrn_key = "vrn_file_joint" data, items = _get_batch_representative(items, vrn_key) items = cwlutils.unpack_tarballs(items, data) data = cwlutils.unpack_tarballs(data, data) cur_name = "%s, %s" % (dd.get_sample_name(data), get_variantcaller(data, require_bam=False)) logger.info("Finalizing variant calls: %s" % cur_name) orig_vrn_file = data.get(vrn_key) data = _symlink_to_workdir(data, [vrn_key]) data = _symlink_to_workdir(data, ["config", "algorithm", "variant_regions"]) if data.get(vrn_key): logger.info("Calculating variation effects for %s" % cur_name) ann_vrn_file, vrn_stats = effects.add_to_vcf(data[vrn_key], data) if ann_vrn_file: data[vrn_key] = ann_vrn_file if vrn_stats: data["vrn_stats"] = vrn_stats orig_items = _get_orig_items(items) logger.info("Annotate VCF file: %s" % cur_name) data[vrn_key] = annotation.finalize_vcf(data[vrn_key], get_variantcaller(data, require_bam=False), orig_items) if cwlutils.is_cwl_run(data): logger.info("Annotate with population level variation data") ann_file = population.run_vcfanno(data[vrn_key], data) if ann_file: data[vrn_key] = ann_file logger.info("Filtering for %s" % cur_name) data[vrn_key] = variant_filtration(data[vrn_key], dd.get_ref_file(data), tz.get_in(("genome_resources", "variation"), data, {}), data, orig_items) logger.info("Prioritization for %s" % cur_name) prio_vrn_file = prioritize.handle_vcf_calls(data[vrn_key], data, orig_items) if prio_vrn_file != data[vrn_key]: data[vrn_key] = prio_vrn_file logger.info("Germline extraction for %s" % cur_name) data = germline.extract(data, orig_items) if dd.get_align_bam(data): data = damage.run_filter(data[vrn_key], dd.get_align_bam(data), dd.get_ref_file(data), data, orig_items) if orig_vrn_file and os.path.samefile(data[vrn_key], orig_vrn_file): data[vrn_key] = orig_vrn_file return [[data]] def _get_orig_items(data): """Retrieve original items in a batch, handling CWL and standard cases. """ if isinstance(data, dict): if dd.get_align_bam(data) and tz.get_in(["metadata", "batch"], data) and "group_orig" in data: return vmulti.get_orig_items(data) else: return [data] else: return data def _symlink_to_workdir(data, key): """For CWL support, symlink files into a working directory if in read-only imports. """ orig_file = tz.get_in(key, data) if orig_file and not orig_file.startswith(dd.get_work_dir(data)): variantcaller = genotype.get_variantcaller(data, require_bam=False) if not variantcaller: variantcaller = "precalled" out_file = os.path.join(dd.get_work_dir(data), variantcaller, os.path.basename(orig_file)) utils.safe_makedir(os.path.dirname(out_file)) utils.symlink_plus(orig_file, out_file) data = tz.update_in(data, key, lambda x: out_file) return data def _get_batch_representative(items, key): """Retrieve a representative data item from a batch. Handles standard bcbio cases (a single data item) and CWL cases with batches that have a consistent variant file. """ if isinstance(items, dict): return items, items else: vals = set([]) out = [] for data in items: if key in data: vals.add(data[key]) out.append(data) if len(vals) != 1: raise ValueError("Incorrect values for %s: %s" % (key, list(vals))) return out[0], items bcbio-nextgen-1.2.9/bcbio/provenance/000077500000000000000000000000001415626112400174675ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/provenance/__init__.py000066400000000000000000000001261415626112400215770ustar00rootroot00000000000000"""Track program versions, commandline arguments and workflows used for analysis. """ bcbio-nextgen-1.2.9/bcbio/provenance/data.py000066400000000000000000000030711415626112400207530ustar00rootroot00000000000000"""Report version information for data used in an analysis. """ import csv import os from bcbio import install, utils def write_versions(dirs, items): """Write data versioning for genomes present in the configuration. """ genomes = {} for d in items: genomes[d["genome_build"]] = d.get("reference", {}).get("versions") out_file = _get_out_file(dirs) found_versions = False if genomes and out_file: with open(out_file, "w") as out_handle: writer = csv.writer(out_handle) writer.writerow(["genome", "resource", "version"]) for genome, version_file in genomes.items(): if not version_file: genome_dir = install.get_genome_dir(genome, dirs.get("galaxy"), items[0]) if genome_dir: version_file = os.path.join(genome_dir, "versions.csv") if version_file and os.path.exists(version_file): found_versions = True with open(version_file) as in_handle: reader = csv.reader(in_handle) for parts in reader: if len(parts) >= 2: resource, version = parts[:2] writer.writerow([genome, resource, version]) if found_versions: return out_file def _get_out_file(dirs): if dirs and dirs.get("work"): base_dir = utils.safe_makedir(os.path.join(dirs["work"], "provenance")) return os.path.join(base_dir, "data_versions.csv") bcbio-nextgen-1.2.9/bcbio/provenance/diagnostics.py000066400000000000000000000046131415626112400223540ustar00rootroot00000000000000"""Provide logging and diagnostics of running pipelines. This wraps the BioLite diagnostics database format to provide tracking of command lines, run times and inspection into run progress. The goal is to allow traceability and reproducibility of pipelines. https://bitbucket.org/caseywdunn/biolite Also interfaces with Galaxy's history export format, to provide a set of metadata that could be imported into object stores. """ import os import uuid import toolz as tz try: import biolite, biolite.config, biolite.database except ImportError: biolite = None from bcbio import utils def start_cmd(cmd, descr, data): """Retain details about starting a command, returning a command identifier. """ if data and "provenance" in data: entity_id = tz.get_in(["provenance", "entity"], data) def end_cmd(cmd_id, succeeded=True): """Mark a command as finished with success or failure. """ pass def initialize(dirs): """Initialize the biolite database to load provenance information. """ if biolite and dirs.get("work"): base_dir = utils.safe_makedir(os.path.join(dirs["work"], "provenance")) p_db = os.path.join(base_dir, "biolite.db") biolite.config.resources["database"] = p_db biolite.database.connect() def store_entity(data): fc_name = tz.get_in(["upload", "fn_name"], data) run_id = ("%s.%s" % (tz.get_in(["upload", "fc_date"], data), fc_name) if fc_name else str(uuid.uuid1())) return str(uuid.uuid1()) def track_parallel(items, sub_type): """Create entity identifiers to trace the given items in sub-commands. Helps handle nesting in parallel program execution: run id => sub-section id => parallel ids """ out = [] for i, args in enumerate(items): item_i, item = _get_provitem_from_args(args) if item: sub_entity = "%s.%s.%s" % (item["provenance"]["entity"], sub_type, i) item["provenance"]["entity"] = sub_entity args = list(args) args[item_i] = item out.append(args) # TODO: store mapping of entity to sub identifiers return out def _has_provenance(x): return isinstance(x, dict) and "provenance" in x def _get_provitem_from_args(xs): """Retrieve processed item from list of input arguments. """ for i, x in enumerate(xs): if _has_provenance(x): return i, x return -1, None bcbio-nextgen-1.2.9/bcbio/provenance/do.py000066400000000000000000000125571415626112400204550ustar00rootroot00000000000000"""Centralize running of external commands, providing logging and tracking. """ import collections import os import subprocess from bcbio import utils from bcbio.log import logger, logger_cl, logger_stdout from bcbio.pipeline import datadict as dd from bcbio.provenance import diagnostics import six def run(cmd, descr=None, data=None, checks=None, region=None, log_error=True, log_stdout=False, env=None): """Run the provided command, logging details and checking for errors. """ if descr: descr = _descr_str(descr, data, region) logger.debug(descr) cmd_id = diagnostics.start_cmd(cmd, descr or "", data) try: logger_cl.debug(" ".join(str(x) for x in cmd) if not isinstance(cmd, six.string_types) else cmd) _do_run(cmd, checks, log_stdout, env=env) except: diagnostics.end_cmd(cmd_id, False) if log_error: logger.exception() raise finally: diagnostics.end_cmd(cmd_id) def _descr_str(descr, data, region): """Add additional useful information from data to description string. """ if data: name = dd.get_sample_name(data) if name: descr = "{0} : {1}".format(descr, name) elif "work_bam" in data: descr = "{0} : {1}".format(descr, os.path.basename(data["work_bam"])) if region: descr = "{0} : {1}".format(descr, region) return descr def find_bash(): for test_bash in [find_cmd("bash"), "/bin/bash", "/usr/bin/bash", "/usr/local/bin/bash"]: if test_bash and os.path.exists(test_bash): return test_bash raise IOError("Could not find bash in any standard location. Needed for unix pipes") def find_cmd(cmd): try: return subprocess.check_output(["which", cmd]).decode().strip() except subprocess.CalledProcessError: return None def _normalize_cmd_args(cmd): """Normalize subprocess arguments to handle list commands, string and pipes. Piped commands set pipefail and require use of bash to help with debugging intermediate errors. """ if isinstance(cmd, six.string_types): # check for standard or anonymous named pipes if cmd.find(" | ") > 0 or cmd.find(">(") or cmd.find("<("): return "set -o pipefail; " + cmd, True, find_bash() else: return cmd, True, None else: return [str(x) for x in cmd], False, None def _do_run(cmd, checks, log_stdout=False, env=None): """Perform running and check results, raising errors for issues. """ cmd, shell_arg, executable_arg = _normalize_cmd_args(cmd) s = subprocess.Popen( cmd, shell=shell_arg, executable=executable_arg, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True, env=env, ) debug_stdout = collections.deque(maxlen=100) while 1: line = s.stdout.readline().decode("utf-8", errors="replace") if line.rstrip(): debug_stdout.append(line) if log_stdout: logger_stdout.debug(line.rstrip()) else: logger.debug(line.rstrip()) exitcode = s.poll() if exitcode is not None: for line in s.stdout: debug_stdout.append(line.decode("utf-8", errors="replace")) if exitcode is not None and exitcode != 0: error_msg = " ".join(cmd) if not isinstance(cmd, six.string_types) else cmd error_msg += "\n" error_msg += "".join(debug_stdout) s.communicate() s.stdout.close() raise subprocess.CalledProcessError(exitcode, error_msg) else: break s.communicate() s.stdout.close() # Check for problems not identified by shell return codes if checks: for check in checks: if not check(): raise IOError("External command failed") # checks for validating run completed successfully def file_nonempty(target_file): def check(): ok = utils.file_exists(target_file) if not ok: logger.info("Did not find non-empty output file {0}".format(target_file)) return ok return check def file_exists(target_file): def check(): ok = os.path.exists(target_file) if not ok: logger.info("Did not find output file {0}".format(target_file)) return ok return check def file_reasonable_size(target_file, input_file): def check(): # named pipes -- we can't calculate size if input_file.strip().startswith("<("): return True if input_file.endswith((".gz")): scale = 10.0 # bams can be compressed at different levels so use larger scale factor # to account for that potential elif input_file.endswith((".bam")): scale = 25.0 else: scale = 20.0 orig_size = os.path.getsize(input_file) / pow(1024.0, 3) out_size = os.path.getsize(target_file) / pow(1024.0, 3) if out_size < (orig_size / scale): logger.info("Output file unexpectedly small. %.1fGb for output versus " "%.1fGb for the input file. This often indicates a truncated " "BAM file or memory errors during the run." % (out_size, orig_size)) return False else: return True return check bcbio-nextgen-1.2.9/bcbio/provenance/profile.py000066400000000000000000000004771415626112400215110ustar00rootroot00000000000000"""Profiling of system resources (CPU, memory, disk, filesystem IO) during pipeline runs. """ import contextlib from bcbio.log import logger @contextlib.contextmanager def report(label, dirs): """Log timing information for later graphing of resource usage.""" logger.info("Timing: %s" % label) yield None bcbio-nextgen-1.2.9/bcbio/provenance/programs.py000066400000000000000000000271441415626112400217030ustar00rootroot00000000000000"""Identify program versions used for analysis, reporting in structured table. Catalogs the full list of programs used in analysis, enabling reproduction of results and tracking of provenance in output files. """ from __future__ import print_function import os import contextlib import subprocess import sys import yaml import toolz as tz from bcbio import utils from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.log import logger _cl_progs = [{"cmd": "bamtofastq", "name": "biobambam", "args": "--version", "stdout_flag": "This is biobambam2 version"}, {"cmd": "bamtools", "args": "--version", "stdout_flag": "bamtools"}, {"cmd": "bcftools", "stdout_flag": "Version:"}, {"cmd": "bedtools", "args": "--version", "stdout_flag": "bedtools"}, {"cmd": "bowtie2", "args": "--version", "stdout_flag": "bowtie2-align version"}, {"cmd": "bwa", "stdout_flag": "Version:"}, {"cmd": "cutadapt", "args": "--version"}, {"cmd": "fastqc", "args": "--version", "stdout_flag": "FastQC"}, {"cmd": "freebayes", "stdout_flag": "version:"}, {"cmd": "gemini", "args": "--version", "stdout_flag": "gemini "}, {"cmd": "novosort", "args": "--version"}, {"cmd": "novoalign", "stdout_flag": "Novoalign"}, {"cmd": "samtools", "stdout_flag": "Version:"}, {"cmd": "qualimap", "args": "-h", "stdout_flag": "QualiMap"}, {"cmd": "preseq", "stdout_flag": "preseq"}, {"cmd": "vcflib", "has_cl_version": False}, {"cmd": "featureCounts", "args": "-v", "stdout_flag": "featureCounts"}] _manifest_progs = [ 'atropos', 'bcbio-variation', 'bioconductor-bubbletree', 'bioconductor-dexseq', 'cufflinks', 'cnvkit', 'express', 'fgbio', 'gatk4', 'hisat2', 'sailfish', 'salmon', 'grabix', 'htseq', 'kallisto', 'lumpy-sv', 'manta', 'break-point-inspector', 'metasv', 'multiqc', 'seq2c', 'mirdeep2', 'oncofuse', 'picard', 'phylowgs', 'platypus-variant', 'rapmap', 'star', 'rtg-tools', 'sambamba', 'samblaster', 'scalpel', 'seqbuster', 'snpeff', 'stringtie', 'vardict', 'vardict-java', 'varscan', 'ensembl-vep', 'vt', 'wham', 'umis'] def _broad_versioner(type): def get_version(config): from bcbio import broad try: runner = broad.runner_from_config(config) except ValueError: return "" if type == "gatk": return runner.get_gatk_version() elif type == "mutect": try: runner = broad.runner_from_config(config, "mutect") return runner.get_mutect_version() except ValueError: return "" else: raise NotImplementedError(type) return get_version def jar_versioner(program_name, jar_name): """Retrieve version information based on jar file. """ def get_version(config): try: pdir = config_utils.get_program(program_name, config, "dir") # not configured except ValueError: return "" jar = os.path.basename(config_utils.get_jar(jar_name, pdir)) for to_remove in [jar_name, ".jar", "-standalone"]: jar = jar.replace(to_remove, "") if jar.startswith(("-", ".")): jar = jar[1:] if not jar: logger.warn("Unable to determine version for program '{}' from jar file {}".format( program_name, config_utils.get_jar(jar_name, pdir))) return jar return get_version def java_versioner(pname, jar_name, **kwargs): def get_version(config): try: pdir = config_utils.get_program(pname, config, "dir") except ValueError: return "" jar = config_utils.get_jar(jar_name, pdir) kwargs["cmd"] = "java" kwargs["args"] = "-Xms128m -Xmx256m -jar %s" % jar return _get_cl_version(kwargs, config) return get_version _alt_progs = [{"name": "gatk", "version_fn": _broad_versioner("gatk")}, {"name": "mutect", "version_fn": _broad_versioner("mutect")}] def _parse_from_stdoutflag(stdout, x): for line in (l.decode() for l in stdout): if line.find(x) >= 0: parts = [p for p in line[line.find(x) + len(x):].split() if p.strip()] return parts[0].strip() return "" def _parse_from_parenflag(stdout, x): for line in (l.decode() for l in stdout): if line.find(x) >= 0: return line.split("(")[-1].split(")")[0] return "" def _get_cl_version(p, config): """Retrieve version of a single commandline program. """ if not p.get("has_cl_version", True): return "" try: prog = config_utils.get_program(p["cmd"], config) except config_utils.CmdNotFound: localpy_cmd = os.path.join(os.path.dirname(sys.executable), p["cmd"]) if os.path.exists(localpy_cmd): prog = localpy_cmd else: return "" args = p.get("args", "") cmd = "{prog} {args}" subp = subprocess.Popen(cmd.format(**locals()), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) with contextlib.closing(subp.stdout) as stdout: if p.get("stdout_flag"): v = _parse_from_stdoutflag(stdout, p["stdout_flag"]) elif p.get("paren_flag"): v = _parse_from_parenflag(stdout, p["paren_flag"]) else: lines = [l.strip() for l in stdout.read().decode().split("\n") if l.strip()] v = lines[-1] if v.endswith("."): v = v[:-1] return v def _get_versions(config=None): """Retrieve details on all programs available on the system. """ try: from bcbio.pipeline import version if hasattr(version, "__version__"): bcbio_version = ("%s-%s" % (version.__version__, version.__git_revision__) if version.__git_revision__ else version.__version__) else: bcbio_version = "" except ImportError: bcbio_version = "" out = [{"program": "bcbio-nextgen", "version": bcbio_version}] # get programs from the conda manifest, if available manifest_dir = _get_manifest_dir(config) manifest_vs = _get_versions_manifest(manifest_dir) if manifest_dir else [] if manifest_vs: out += manifest_vs programs = {x["program"] for x in out if x["version"]} # get program versions from command line for p in _cl_progs: if p["cmd"] not in programs: out.append({"program": p["cmd"], "version": _get_cl_version(p, config)}) programs.add(p["cmd"]) for p in _alt_progs: if p["name"] not in programs: out.append({"program": p["name"], "version": (p["version_fn"](config))}) programs.add(p["name"]) out.sort(key=lambda x: x["program"]) # remove entries with empty version strings out = [x for x in out if x["version"]] return out def _get_manifest_dir(data=None, name=None): """ get manifest directory from the data dictionary, falling back on alternatives it prefers, in order: 1. locating it from the bcbio_system.yaml file 2. locating it from the galaxy directory 3. location it from the python executable. it can accept either the data or config dictionary """ manifest_dir = None if data: bcbio_system = tz.get_in(["config", "bcbio_system"], data, None) bcbio_system = bcbio_system if bcbio_system else data.get("bcbio_system", None) if bcbio_system: sibling_dir = os.path.normpath(os.path.dirname(bcbio_system)) else: sibling_dir = dd.get_galaxy_dir(data) if sibling_dir: manifest_dir = os.path.normpath(os.path.join(sibling_dir, os.pardir, "manifest")) if not manifest_dir or not os.path.exists(manifest_dir): manifest_dir = os.path.join(config_utils.get_base_installdir(), "manifest") if not os.path.exists(manifest_dir) and name: manifest_dir = os.path.join(config_utils.get_base_installdir(name), "manifest") return manifest_dir def _get_versions_manifest(manifest_dir): """Retrieve versions from a pre-existing manifest of installed software. """ all_pkgs = _manifest_progs + [p.get("name", p["cmd"]) for p in _cl_progs] + [p["name"] for p in _alt_progs] if os.path.exists(manifest_dir): out = [] for plist in ["toolplus", "python", "r", "debian", "custom"]: pkg_file = os.path.join(manifest_dir, "%s-packages.yaml" % plist) if os.path.exists(pkg_file): logger.info(f"Retreiving program versions from {pkg_file}.") with open(pkg_file) as in_handle: pkg_info = yaml.safe_load(in_handle) if not pkg_info: continue added = [] for pkg in all_pkgs: if pkg in pkg_info: added.append(pkg) out.append({"program": pkg, "version": pkg_info[pkg]["version"]}) for x in added: all_pkgs.remove(x) out.sort(key=lambda x: x["program"]) for pkg in all_pkgs: out.append({"program": pkg, "version": ""}) return out def _get_program_file(dirs): if dirs.get("work"): base_dir = utils.safe_makedir(os.path.join(dirs["work"], "provenance")) return os.path.join(base_dir, "programs.txt") def write_versions(dirs, config=None, is_wrapper=False): """Write CSV file with versions used in analysis pipeline. """ out_file = _get_program_file(dirs) if is_wrapper: assert utils.file_exists(out_file), "Failed to create program versions from VM" elif out_file is None: for p in _get_versions(config): print("{program},{version}".format(**p)) else: with open(out_file, "w") as out_handle: for p in _get_versions(config): program = p["program"] version = p["version"] out_handle.write(f"{program},{version}\n") return out_file def get_version_manifest(name, data=None, required=False): """Retrieve a version from the currently installed manifest. """ manifest_dir = _get_manifest_dir(data, name) manifest_vs = _get_versions_manifest(manifest_dir) or [] for x in manifest_vs: if x["program"] == name: v = x.get("version", "") if v: return v if required: raise ValueError("Did not find %s in install manifest. Could not check version." % name) return "" def add_subparser(subparsers): """Add command line option for exporting version information. """ parser = subparsers.add_parser("version", help="Export versions of used software to stdout or a file ") parser.add_argument("--workdir", help="Directory export programs to in workdir/provenance/programs.txt", default=None) def get_version(name, dirs=None, config=None): """Retrieve the current version of the given program from cached names. """ if dirs: p = _get_program_file(dirs) else: p = tz.get_in(["resources", "program_versions"], config) if p: with open(p) as in_handle: for line in in_handle: prog, version = line.rstrip().split(",") if prog == name and version: return version raise KeyError("Version information not found for %s in %s" % (name, p)) bcbio-nextgen-1.2.9/bcbio/provenance/system.py000066400000000000000000000237541415626112400214000ustar00rootroot00000000000000"""Identify system information for distributed systems, used to manage resources. This provides a background on cluster and single multicore systems allowing jobs to be reasonably distributed in cases of higher memory usage. """ import copy import multiprocessing import os import resource import shlex import socket import subprocess import yaml from xml.etree import ElementTree as ET from bcbio import utils from bcbio.log import logger def _get_cache_file(dirs, parallel): base_dir = utils.safe_makedir(os.path.join(dirs["work"], "provenance")) return os.path.join(base_dir, "system-%s-%s.yaml" % (parallel["type"], parallel.get("queue", "default"))) def write_info(dirs, parallel, config): """Write cluster or local filesystem resources, spinning up cluster if not present. """ if parallel["type"] in ["ipython"] and not parallel.get("run_local"): out_file = _get_cache_file(dirs, parallel) if not utils.file_exists(out_file): sys_config = copy.deepcopy(config) minfos = _get_machine_info(parallel, sys_config, dirs, config) with open(out_file, "w") as out_handle: yaml.safe_dump(minfos, out_handle, default_flow_style=False, allow_unicode=False) def _get_machine_info(parallel, sys_config, dirs, config): """Get machine resource information from the job scheduler via either the command line or the queue. """ if parallel.get("queue") and parallel.get("scheduler"): # dictionary as switch statement; can add new scheduler implementation functions as (lowercase) keys sched_info_dict = { "slurm": _slurm_info, "torque": _torque_info, "sge": _sge_info } if parallel["scheduler"].lower() in sched_info_dict: try: return sched_info_dict[parallel["scheduler"].lower()](parallel.get("queue", "")) except: # If something goes wrong, just hit the queue logger.exception("Couldn't get machine information from resource query function for queue " "'{0}' on scheduler \"{1}\"; " "submitting job to queue".format(parallel.get("queue", ""), parallel["scheduler"])) else: logger.info("Resource query function not implemented for scheduler \"{0}\"; " "submitting job to queue".format(parallel["scheduler"])) from bcbio.distributed import prun with prun.start(parallel, [[sys_config]], config, dirs) as run_parallel: return run_parallel("machine_info", [[sys_config]]) def _slurm_info(queue): """Returns machine information for a slurm job scheduler. """ cl = "sinfo -h -p {} --format '%c %m %D'".format(queue) num_cpus, mem, num_nodes = subprocess.check_output(shlex.split(cl)).decode().split() # if the queue contains multiple memory configurations, the minimum value is printed with a trailing '+' mem = float(mem.replace('+', '')) num_cpus = int(num_cpus.replace('+', '')) # handle small clusters where we need to allocate memory for bcbio and the controller # This will typically be on cloud AWS machines bcbio_mem = 2000 controller_mem = 4000 if int(num_nodes) < 3 and mem > (bcbio_mem + controller_mem) * 2: mem = mem - bcbio_mem - controller_mem return [{"cores": int(num_cpus), "memory": mem / 1024.0, "name": "slurm_machine"}] def _torque_info(queue): """Return machine information for a torque job scheduler using pbsnodes. To identify which host to use it tries to parse available hosts from qstat -Qf `acl_hosts`. If found, it uses these and gets the first node from pbsnodes matching to the list. If no attached hosts are available, it uses the first host found from pbsnodes. """ nodes = _torque_queue_nodes(queue) pbs_out = subprocess.check_output(["pbsnodes"]).decode() info = {} for i, line in enumerate(pbs_out.split("\n")): if i == 0 and len(nodes) == 0: info["name"] = line.strip() elif line.startswith(nodes): info["name"] = line.strip() elif info.get("name"): if line.strip().startswith("np = "): info["cores"] = int(line.replace("np = ", "").strip()) elif line.strip().startswith("status = "): mem = [x for x in pbs_out.split(",") if x.startswith("physmem=")][0] info["memory"] = float(mem.split("=")[1].rstrip("kb")) / 1048576.0 return [info] def _torque_queue_nodes(queue): """Retrieve the nodes available for a queue. Parses out nodes from `acl_hosts` in qstat -Qf and extracts the initial names of nodes used in pbsnodes. """ qstat_out = subprocess.check_output(["qstat", "-Qf", queue]).decode() hosts = [] in_hosts = False for line in qstat_out.split("\n"): if line.strip().startswith("acl_hosts = "): hosts.extend(line.replace("acl_hosts = ", "").strip().split(",")) in_hosts = True elif in_hosts: if line.find(" = ") > 0: break else: hosts.extend(line.strip().split(",")) return tuple([h.split(".")[0].strip() for h in hosts if h.strip()]) def median_left(x): if len(x) < 1: return None sortedval = sorted(x) centre = int((len(sortedval)-1)/2) return sortedval[centre] def _sge_info(queue): """Returns machine information for an sge job scheduler. """ qhost_out = subprocess.check_output(["qhost", "-q", "-xml"]).decode() qstat_queue = ["-q", queue] if queue and "," not in queue else [] qstat_out = subprocess.check_output(["qstat", "-f", "-xml"] + qstat_queue).decode() slot_info = _sge_get_slots(qstat_out) mem_info = _sge_get_mem(qhost_out, queue) machine_keys = list(slot_info.keys()) #num_cpus_vec = [slot_info[x]["slots_total"] for x in machine_keys] #mem_vec = [mem_info[x]["mem_total"] for x in machine_keys] mem_per_slot = [mem_info[x]["mem_total"] / float(slot_info[x]["slots_total"]) for x in machine_keys] min_ratio_index = mem_per_slot.index(median_left(mem_per_slot)) mem_info[machine_keys[min_ratio_index]]["mem_total"] return [{"cores": slot_info[machine_keys[min_ratio_index]]["slots_total"], "memory": mem_info[machine_keys[min_ratio_index]]["mem_total"], "name": "sge_machine"}] def _sge_get_slots(xmlstring): """ Get slot information from qstat """ rootxml = ET.fromstring(xmlstring) my_machine_dict = {} for queue_list in rootxml.iter("Queue-List"): # find all hosts supporting queues my_hostname = queue_list.find("name").text.rsplit("@")[-1] my_slots = queue_list.find("slots_total").text my_machine_dict[my_hostname] = {} my_machine_dict[my_hostname]["slots_total"] = int(my_slots) return my_machine_dict def _sge_get_mem(xmlstring, queue_name): """ Get memory information from qhost """ rootxml = ET.fromstring(xmlstring) my_machine_dict = {} # on some machines rootxml.tag looks like "{...}qhost" where the "{...}" gets prepended to all attributes rootTag = rootxml.tag.rstrip("qhost") for host in rootxml.findall(rootTag + 'host'): # find all hosts supporting queues for queues in host.findall(rootTag + 'queue'): # if the user specified queue matches that in the xml: if not queue_name or any(q in queues.attrib['name'] for q in queue_name.split(",")): my_machine_dict[host.attrib['name']] = {} # values from xml for number of processors and mem_total on each machine for hostvalues in host.findall(rootTag + 'hostvalue'): if('mem_total' == hostvalues.attrib['name']): if hostvalues.text.lower().endswith('g'): multip = 1 elif hostvalues.text.lower().endswith('m'): multip = 1 / float(1024) elif hostvalues.text.lower().endswith('t'): multip = 1024 else: raise Exception("Unrecognized suffix in mem_tot from SGE") my_machine_dict[host.attrib['name']]['mem_total'] = \ float(hostvalues.text[:-1]) * float(multip) break return my_machine_dict def _combine_machine_info(xs): if len(xs) == 1: return xs[0] else: raise NotImplementedError("Add logic to pick specification from non-homogeneous clusters.") def get_info(dirs, parallel, resources=None): """Retrieve cluster or local filesystem resources from pre-retrieved information. """ # Allow custom specification of cores/memory in resources if resources and isinstance(resources, dict) and "machine" in resources: minfo = resources["machine"] assert "memory" in minfo, "Require memory specification (Gb) in machine resources: %s" % minfo assert "cores" in minfo, "Require core specification in machine resources: %s" % minfo return minfo if parallel["type"] in ["ipython"] and not parallel["queue"] == "localrun": cache_file = _get_cache_file(dirs, parallel) if utils.file_exists(cache_file): with open(cache_file) as in_handle: minfo = yaml.safe_load(in_handle) return _combine_machine_info(minfo) else: return {} else: return _combine_machine_info(machine_info()) def machine_info(): """Retrieve core and memory information for the current machine. """ import psutil BYTES_IN_GIG = 1073741824.0 free_bytes = psutil.virtual_memory().total return [{"memory": float("%.1f" % (free_bytes / BYTES_IN_GIG)), "cores": multiprocessing.cpu_count(), "name": socket.gethostname()}] def open_file_limit(): return resource.getrlimit(resource.RLIMIT_NOFILE)[0] bcbio-nextgen-1.2.9/bcbio/provenance/versioncheck.py000066400000000000000000000077511415626112400225360ustar00rootroot00000000000000"""Check specific required program versions required during the pipeline. """ from distutils.version import LooseVersion import subprocess from bcbio import setpath, utils from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.log import logger def samtools(items): """Ensure samtools has parallel processing required for piped analysis. """ samtools = config_utils.get_program("samtools", items[0]["config"]) p = subprocess.Popen([samtools, "sort", "-h"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, stderr = p.communicate() p.stdout.close() p.stderr.close() if str(output.decode()).find("-@") == -1 and str(stderr.decode()).find("-@") == -1: return ("Installed version of samtools sort does not have support for " "multithreading (-@ option) " "required to support bwa piped alignment and BAM merging. " "Please upgrade to the latest version " "from http://samtools.sourceforge.net/") def _has_pipeline(items): """Only perform version checks when we're running an analysis pipeline. """ return any(item.get("analysis", "") != "" for item in items) def _needs_java(data): """Check if a caller needs external java for MuTect. No longer check for older GATK (<3.6) versions because of time cost; this won't be relevant to most runs so we skip the sanity check. """ vc = dd.get_variantcaller(data) if isinstance(vc, dict): out = {} for k, v in vc.items(): if not isinstance(v, (list, tuple)): v = [v] out[k] = v vc = out elif not isinstance(vc, (list, tuple)): vc = [vc] if "mutect" in vc or ("somatic" in vc and "mutect" in vc["somatic"]): return True if "gatk" in vc or "gatk-haplotype" in vc or ("germline" in vc and "gatk-haplotype" in vc["germline"]): pass # runner = broad.runner_from_config(data["config"]) # version = runner.get_gatk_version() # if LooseVersion(version) < LooseVersion("3.6"): # return True return False def java(items): """Check for presence of external Java 1.7 for tools that require it. """ if any([_needs_java(d) for d in items]): min_version = "1.7" max_version = "1.8" with setpath.orig_paths(): java = utils.which("java") if not java: return ("java not found on PATH. Java %s required for MuTect and GATK < 3.6." % min_version) p = subprocess.Popen([java, "-Xms250m", "-Xmx250m", "-version"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output, _ = p.communicate() p.stdout.close() version = "" for line in output.decode().split("\n"): if line.startswith(("java version", "openjdk version")): version = line.strip().split()[-1] if version.startswith('"'): version = version[1:] if version.endswith('"'): version = version[:-1] if (not version or LooseVersion(version) >= LooseVersion(max_version) or LooseVersion(version) < LooseVersion(min_version)): return ("java version %s required for running MuTect and GATK < 3.6.\n" "It needs to be first on your PATH so running 'java -version' give the correct version.\n" "Found version %s at %s" % (min_version, version, java)) def testall(items): logger.info("Testing minimum versions of installed programs") msgs = [] if _has_pipeline(items): for fn in [samtools, java]: out = fn(items) if out: msgs.append(out) if msgs: raise OSError("Program problems found. You can upgrade dependencies with:\n" + "bcbio_nextgen.py upgrade -u skip --tooldir=/usr/local\n\n" + "\n".join(msgs)) bcbio-nextgen-1.2.9/bcbio/qc/000077500000000000000000000000001415626112400157325ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/qc/__init__.py000066400000000000000000000000541415626112400200420ustar00rootroot00000000000000"""Interfaces to quality control tools. """ bcbio-nextgen-1.2.9/bcbio/qc/atac.py000066400000000000000000000002131415626112400172100ustar00rootroot00000000000000from bcbio.chipseq import atac def run(_, data, out_dir): """Standard QC metrics for ATAC-seq """ return atac.run_ataqv(data) bcbio-nextgen-1.2.9/bcbio/qc/atropos.py000066400000000000000000000015561415626112400200020ustar00rootroot00000000000000"""Get log file from trimming step if file inside data["log_trimming"]""" from bcbio import utils def run(bam_file, data, dir_out): m = {} if "log_trimming" in data and utils.file_exists(data["log_trimming"]): with open(data["log_trimming"]) as inh: for line in inh: cols = line.strip().split(":") if line.find("Total reads processed") > -1: m["reads_before_trimming"] = _get_value(cols[1]) elif line.find("Reads with adapter") > -1: m["read_with_adapter"] = _get_value(cols[1]) elif line.find("Reads written") > -1: m["read_pass_filter"] = _get_value(cols[1]) return {"metrics": m, "base": data["log_trimming"]} def _get_value(information): return int(information.strip().split()[0].strip().replace(",", "")) bcbio-nextgen-1.2.9/bcbio/qc/chipseq.py000066400000000000000000000056011415626112400177420ustar00rootroot00000000000000"""Qc for chipseq pipeline""" import os import shutil import glob import toolz as tz from bcbio.log import logger from bcbio import utils from bcbio.bam.readstats import number_of_mapped_reads from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.distributed.transaction import tx_tmpdir from bcbio.chipseq.atac import get_full_peaks supported = ["hg19", "hg38", "mm10", "mm9", "rn4", "ce6", "dm3"] def run(bam_file, sample, out_dir): """Standard QC metrics for chipseq""" out = {} # if "rchipqc" in dd.get_tools_on(sample): # out = chipqc(bam_file, sample, out_dir) peaks = sample.get("peaks_files", {}).get("main") # find ATAC peak files if not peaks: peaks = get_full_peaks(sample) if peaks: out.update(_reads_in_peaks(bam_file, peaks, sample)) return out def _reads_in_peaks(bam_file, peaks_file, sample): """Calculate number of reads in peaks""" if not peaks_file: return {} rip = number_of_mapped_reads(sample, bam_file, bed_file = peaks_file) return {"metrics": {"RiP": rip}} def chipqc(bam_file, sample, out_dir): """Attempt code to run ChIPQC bioconductor packate in one sample""" sample_name = dd.get_sample_name(sample) logger.warning("ChIPQC is unstable right now, if it breaks, turn off the tool.") if utils.file_exists(out_dir): return _get_output(out_dir) with tx_tmpdir() as tmp_dir: rcode = _sample_template(sample, tmp_dir) if rcode: # local_sitelib = utils.R_sitelib() rscript = utils.Rscript_cmd() do.run([rscript, "--vanilla", rcode], "ChIPQC in %s" % sample_name, log_error=False) shutil.move(tmp_dir, out_dir) return _get_output(out_dir) def _get_output(out_dir): files = glob.glob(out_dir) if files: return {'secondary': files} else: return {} def _sample_template(sample, out_dir): """R code to get QC for one sample""" bam_fn = dd.get_work_bam(sample) genome = dd.get_genome_build(sample) if genome in supported: peaks = sample.get("peaks_files", []).get("main") if peaks: r_code = ("library(ChIPQC);\n" "sample = ChIPQCsample(\"{bam_fn}\"," "\"{peaks}\", " "annotation = \"{genome}\"," ");\n" "ChIPQCreport(sample);\n") r_code_fn = os.path.join(out_dir, "chipqc.r") with open(r_code_fn, 'w') as inh: inh.write(r_code.format(**locals())) return r_code_fn def _template(): r_code = ("library(ChIPQC);\n" "metadata = read.csv(\"metadata.csv\");\n" "qc = ChIPQC(metadata, annotation = {genome}," " chromosomes = {chr}, fragmentLength = {fl});\n" "ChIPQCreport(qc, facetBy=c(\"{facet1}\", \"{facet2}\"));\n") bcbio-nextgen-1.2.9/bcbio/qc/contamination.py000066400000000000000000000127721415626112400211600ustar00rootroot00000000000000"""Estimate contamination using VerifyBamID2. """ import os import shutil import subprocess import sys from bcbio import utils from bcbio.log import logger from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.qc import samtools as qc_samtools from bcbio.variation import samtools def run(bam_file, data, out_dir): out_base = os.path.join(utils.safe_makedir(out_dir), "%s-verifybamid" % (dd.get_sample_name(data))) out_file = out_base + ".selfSM" failed_file = out_base + ".failed" exts = [".out"] out = {} if not utils.file_exists(out_file) and not utils.file_exists(failed_file): _generate_estimates(bam_file, out_base, failed_file, exts, data) if utils.file_exists(out_file): out["base"] = out_file out["secondary"] = [out_base + e for e in exts if os.path.exists(out_base + e)] return out def _generate_estimates(bam_file, out_base, failed_file, exts, data): background = {"dataset": "1000g.phase3", "nvars": "100k", "build":"b38" if dd.get_genome_build(data) == "hg38" else "b37"} with file_transaction(data, out_base) as tx_out_base: num_cores = dd.get_num_cores(data) cmd = ["verifybamid2", background["dataset"], background["nvars"], background["build"], "--Reference", dd.get_ref_file(data), "--Output", tx_out_base, "--NumThread", num_cores] cmd += _get_input_args(bam_file, data, out_base, background) try: do.run(cmd, "VerifyBamID contamination checks") except subprocess.CalledProcessError as msg: def allowed_errors(l): return (l.find("Insufficient Available markers") >= 0 or l.find("No reads found in any of the regions") >= 0) if any([allowed_errors(l) for l in str(msg).split("\n")]): logger.info("Skipping VerifyBamID, not enough overlapping markers found: %s" % dd.get_sample_name(data)) with open(failed_file, "w") as out_handle: out_handle.write(str(msg)) else: logger.warning(str(msg)) # don't escalate, it breaks some terminals on AWS Ubuntu # raise else: # Fix any sample name problems, for pileups shutil.move(tx_out_base + ".selfSM", tx_out_base + ".selfSM.orig") with open(tx_out_base + ".selfSM.orig") as in_handle: with open(tx_out_base + ".selfSM", "w") as out_handle: sample_name = None for line in in_handle: if line.startswith("DefaultSampleName"): line = line.replace("DefaultSampleName", dd.get_sample_name(data)) # work around bug in finding SM from BAM RG at end of line if len(line.strip().split("\t")) == 1: sample_name = line.strip() line = None elif sample_name: parts = line.split("\t") parts[0] = sample_name line = "\t".join(parts) sample_name = None if line: out_handle.write(line) for e in exts + [".selfSM"]: if os.path.exists(tx_out_base + e): shutil.copy(tx_out_base + e, out_base + e) def _get_input_args(bam_file, data, out_base, background): """Retrieve input args, depending on genome build. VerifyBamID2 only handles GRCh37 (1, 2, 3) not hg19, so need to generate a pileup for hg19 and fix chromosome naming. """ if dd.get_genome_build(data) in ["hg19"]: return ["--PileupFile", _create_pileup(bam_file, data, out_base, background)] else: return ["--BamFile", bam_file] def _create_pileup(bam_file, data, out_base, background): """Create pileup calls in the regions of interest for hg19 -> GRCh37 chromosome mapping. """ out_file = "%s-mpileup.txt" % out_base if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: background_bed = os.path.normpath(os.path.join( os.path.dirname(os.path.realpath(utils.which("verifybamid2"))), "resource", "%s.%s.%s.vcf.gz.dat.bed" % (background["dataset"], background["nvars"], background["build"]))) local_bed = os.path.join(os.path.dirname(out_base), "%s.%s-hg19.bed" % (background["dataset"], background["nvars"])) if not utils.file_exists(local_bed): with file_transaction(data, local_bed) as tx_local_bed: with open(background_bed) as in_handle: with open(tx_local_bed, "w") as out_handle: for line in in_handle: out_handle.write("chr%s" % line) mpileup_cl = samtools.prep_mpileup([bam_file], dd.get_ref_file(data), data["config"], want_bcf=False, target_regions=local_bed) cl = ("{mpileup_cl} | sed 's/^chr//' > {tx_out_file}") do.run(cl.format(**locals()), "Create pileup from BAM input") return out_file bcbio-nextgen-1.2.9/bcbio/qc/coverage.py000066400000000000000000000126601415626112400201040ustar00rootroot00000000000000"""Coverage based QC calculations. """ import glob import os import subprocess from bcbio.bam import ref, readstats, utils from bcbio.distributed import transaction from bcbio.heterogeneity import chromhacks import bcbio.pipeline.datadict as dd from bcbio.provenance import do from bcbio.variation import coverage as cov from bcbio.variation import bedutils def run(bam_file, data, out_dir): """Run coverage QC analysis """ out = dict() out_dir = utils.safe_makedir(out_dir) if dd.get_coverage(data) and dd.get_coverage(data) not in ["None"]: merged_bed_file = bedutils.clean_file(dd.get_coverage_merged(data), data, prefix="cov-", simple=True) target_name = "coverage" elif dd.get_coverage_interval(data) != "genome": merged_bed_file = dd.get_variant_regions_merged(data) or dd.get_sample_callable(data) target_name = "variant_regions" else: merged_bed_file = None target_name = "genome" avg_depth = cov.get_average_coverage(target_name, merged_bed_file, data) if target_name == "coverage": out_files = cov.coverage_region_detailed_stats(target_name, merged_bed_file, data, out_dir) else: out_files = [] out['Avg_coverage'] = avg_depth samtools_stats_dir = os.path.join(out_dir, os.path.pardir, 'samtools') from bcbio.qc import samtools samtools_stats = samtools.run(bam_file, data, samtools_stats_dir)["metrics"] out["Total_reads"] = total_reads = int(samtools_stats["Total_reads"]) out["Mapped_reads"] = mapped = int(samtools_stats["Mapped_reads"]) out["Mapped_paired_reads"] = int(samtools_stats["Mapped_paired_reads"]) out['Duplicates'] = dups = int(samtools_stats["Duplicates"]) if total_reads: out["Mapped_reads_pct"] = 100.0 * mapped / total_reads if mapped: out['Duplicates_pct'] = 100.0 * dups / mapped if dd.get_coverage_interval(data) == "genome": mapped_unique = mapped - dups else: mapped_unique = readstats.number_of_mapped_reads(data, bam_file, keep_dups=False) out['Mapped_unique_reads'] = mapped_unique if merged_bed_file: ontarget = readstats.number_of_mapped_reads( data, bam_file, keep_dups=False, bed_file=merged_bed_file, target_name=target_name) out["Ontarget_unique_reads"] = ontarget if mapped_unique: out["Ontarget_pct"] = 100.0 * ontarget / mapped_unique out['Offtarget_pct'] = 100.0 * (mapped_unique - ontarget) / mapped_unique if dd.get_coverage_interval(data) != "genome": # Skip padded calculation for WGS even if the "coverage" file is specified # the padded statistic makes only sense for exomes and panels padded_bed_file = bedutils.get_padded_bed_file(out_dir, merged_bed_file, 200, data) ontarget_padded = readstats.number_of_mapped_reads( data, bam_file, keep_dups=False, bed_file=padded_bed_file, target_name=target_name + "_padded") out["Ontarget_padded_pct"] = 100.0 * ontarget_padded / mapped_unique if total_reads: out['Usable_pct'] = 100.0 * ontarget / total_reads indexcov_files = _goleft_indexcov(bam_file, data, out_dir) out_files += [x for x in indexcov_files if x and utils.file_exists(x)] out = {"metrics": out} if len(out_files) > 0: out["base"] = out_files[0] out["secondary"] = out_files[1:] return out def _goleft_indexcov(bam_file, data, out_dir): """Use goleft indexcov to estimate coverage distributions using BAM index. Only used for whole genome runs as captures typically don't have enough data to be useful for index-only summaries. """ if not dd.get_coverage_interval(data) == "genome": return [] out_dir = utils.safe_makedir(os.path.join(out_dir, "indexcov")) out_files = [os.path.join(out_dir, "%s-indexcov.%s" % (dd.get_sample_name(data), ext)) for ext in ["roc", "ped", "bed.gz"]] if not utils.file_uptodate(out_files[-1], bam_file): with transaction.tx_tmpdir(data) as tmp_dir: tmp_dir = utils.safe_makedir(os.path.join(tmp_dir, dd.get_sample_name(data))) gender_chroms = [x.name for x in ref.file_contigs(dd.get_ref_file(data)) if chromhacks.is_sex(x.name)] gender_args = "--sex %s" % (",".join(gender_chroms)) if gender_chroms else "" cmd = "goleft indexcov --directory {tmp_dir} {gender_args} -- {bam_file}" try: do.run(cmd.format(**locals()), "QC: goleft indexcov") except subprocess.CalledProcessError as msg: if not ("indexcov: no usable" in str(msg) or ("indexcov: expected" in str(msg) and "sex chromosomes, found:" in str(msg))): raise for out_file in out_files: orig_file = os.path.join(tmp_dir, os.path.basename(out_file)) if utils.file_exists(orig_file): utils.copy_plus(orig_file, out_file) # MultiQC needs non-gzipped/BED inputs so unpack the file out_bed = out_files[-1].replace(".bed.gz", ".tsv") if utils.file_exists(out_files[-1]) and not utils.file_exists(out_bed): with transaction.file_transaction(data, out_bed) as tx_out_bed: cmd = "gunzip -c %s > %s" % (out_files[-1], tx_out_bed) do.run(cmd, "Unpack indexcov BED file") out_files[-1] = out_bed return [x for x in out_files if utils.file_exists(x)] bcbio-nextgen-1.2.9/bcbio/qc/damage.py000066400000000000000000000021771415626112400175310ustar00rootroot00000000000000"""Provide summary details on damage filtering for MultiQC. """ import os from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.variation import vcfutils from bcbio.qc import variant def run(bam_file, data, out_dir): out = {} vcinfo = variant.get_active_vcinfo(data, use_ensemble=False) dkfzbiasfilter = config_utils.get_program("dkfzbiasfilter_summarize.py", data) if vcinfo and vcfutils.vcf_has_variants(vcinfo["vrn_file"]): out_file = os.path.join(utils.safe_makedir(out_dir), "%s-damage.yaml" % (dd.get_sample_name(data))) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [dkfzbiasfilter, "--sample=%s" % dd.get_sample_name(data), "--outfile=%s" % tx_out_file, vcinfo["vrn_file"]] do.run(cmd, "Summarize damage filtering") if utils.file_exists(out_file): out["base"] = out_file return out bcbio-nextgen-1.2.9/bcbio/qc/fastqc.py000066400000000000000000000136731415626112400175770ustar00rootroot00000000000000"""Run and parse output from FastQC. http://www.bioinformatics.babraham.ac.uk/projects/fastqc/ """ import os import shutil import pandas as pd try: from fadapa import Fadapa except ImportError: Fadapa = None from bcbio import bam, utils from bcbio.distributed.transaction import tx_tmpdir from bcbio.log import logger from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils def run(bam_file, data, fastqc_out): """Run fastqc, generating report in specified directory and parsing metrics. Downsamples to 10 million reads to avoid excessive processing times with large files, unless we're running a Standard/smallRNA-seq/QC pipeline. Handles fastqc 0.11+, which use a single HTML file and older versions that use a directory of files + images. The goal is to eventually move to only 0.11+ """ sentry_file = os.path.join(fastqc_out, "fastqc_report.html") if not os.path.exists(sentry_file): work_dir = os.path.dirname(fastqc_out) utils.safe_makedir(work_dir) ds_file = (bam.downsample(bam_file, data, 1e7, work_dir=work_dir) if data.get("analysis", "").lower() not in ["standard", "smallrna-seq"] else None) if ds_file is not None: bam_file = ds_file frmt = "bam" if bam_file.endswith("bam") else "fastq" fastqc_name = utils.splitext_plus(os.path.basename(bam_file))[0] fastqc_clean_name = dd.get_sample_name(data) # FastQC scales memory with threads (250mb per thread) so we avoid # very low memory usage num_cores = max(data["config"]["algorithm"].get("num_cores", 1), 2) with tx_tmpdir(data, work_dir) as tx_tmp_dir: with utils.chdir(tx_tmp_dir): cl = [config_utils.get_program("fastqc", data["config"]), "-d", tx_tmp_dir, "-t", str(num_cores), "--extract", "-o", tx_tmp_dir, "-f", frmt, bam_file] cl = "%s %s %s" % (utils.java_freetype_fix(), utils.local_path_export(), " ".join([str(x) for x in cl])) do.run(cl, "FastQC: %s" % dd.get_sample_name(data)) tx_fastqc_out = os.path.join(tx_tmp_dir, "%s_fastqc" % fastqc_name) tx_combo_file = os.path.join(tx_tmp_dir, "%s_fastqc.html" % fastqc_name) if not os.path.exists(sentry_file) and os.path.exists(tx_combo_file): utils.safe_makedir(fastqc_out) # Use sample name for reports instead of bam file name with open(os.path.join(tx_fastqc_out, "fastqc_data.txt"), 'r') as fastqc_bam_name, \ open(os.path.join(tx_fastqc_out, "_fastqc_data.txt"), 'w') as fastqc_sample_name: for line in fastqc_bam_name: fastqc_sample_name.write(line.replace(os.path.basename(bam_file), fastqc_clean_name)) shutil.move(os.path.join(tx_fastqc_out, "_fastqc_data.txt"), os.path.join(fastqc_out, 'fastqc_data.txt')) shutil.move(tx_combo_file, sentry_file) if os.path.exists("%s.zip" % tx_fastqc_out): shutil.move("%s.zip" % tx_fastqc_out, os.path.join(fastqc_out, "%s.zip" % fastqc_clean_name)) elif not os.path.exists(sentry_file): raise ValueError("FastQC failed to produce output HTML file: %s" % os.listdir(tx_tmp_dir)) logger.info("Produced HTML report %s" % sentry_file) parser = FastQCParser(fastqc_out, dd.get_sample_name(data)) stats = parser.get_fastqc_summary() parser.save_sections_into_file() return stats class FastQCParser: def __init__(self, base_dir, sample=None): self._dir = base_dir self.sample = sample def get_fastqc_summary(self): ignore = set(["Total Sequences", "Filtered Sequences", "Filename", "File type", "Encoding"]) stats = {} for stat_line in self._fastqc_data_section("Basic Statistics")[1:]: k, v = stat_line.split("\t")[:2] if k not in ignore: stats[k] = v return stats def _fastqc_data_section(self, section_name): out = [] in_section = False data_file = os.path.join(self._dir, "fastqc_data.txt") if os.path.exists(data_file): with open(data_file) as in_handle: for line in in_handle: if line.startswith(">>%s" % section_name): in_section = True elif in_section: if line.startswith(">>END"): break out.append(line.rstrip("\r\n")) return out def save_sections_into_file(self): data_file = os.path.join(self._dir, "fastqc_data.txt") if os.path.exists(data_file) and Fadapa: parser = Fadapa(data_file) module = [m[1] for m in parser.summary()][2:9] for m in module: out_file = os.path.join(self._dir, m.replace(" ", "_") + ".tsv") dt = self._get_module(parser, m) dt.to_csv(out_file, sep="\t", index=False) def _get_module(self, parser, module): """ Get module using fadapa package """ dt = [] lines = parser.clean_data(module) header = lines[0] for data in lines[1:]: if data[0].startswith("#"): # some modules have two headers header = data continue if data[0].find("-") > -1: # expand positions 1-3 to 1, 2, 3 f, s = map(int, data[0].split("-")) for pos in range(f, s): dt.append([str(pos)] + data[1:]) else: dt.append(data) dt = pd.DataFrame(dt) dt.columns = [h.replace(" ", "_") for h in header] dt['sample'] = self.sample return dt bcbio-nextgen-1.2.9/bcbio/qc/kraken.py000066400000000000000000000101251415626112400175560ustar00rootroot00000000000000"""Contamination detection using Kraken. https://ccb.jhu.edu/software/kraken/ """ import os import shutil import toolz as tz from bcbio import bam, install, utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.log import logger from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils def run(_, data, out_dir): """Run kraken, generating report in specified directory and parsing metrics. Using only first paired reads. """ # logger.info("Number of aligned reads < than 0.60 in %s: %s" % (dd.get_sample_name(data), ratio)) logger.info("Running kraken to determine contaminant: %s" % dd.get_sample_name(data)) # ratio = bam.get_aligned_reads(bam_file, data) out = out_stats = None db = tz.get_in(["config", "algorithm", "kraken"], data) if db and isinstance(db, (list, tuple)): db = db[0] kraken_cmd = config_utils.get_program("kraken", data["config"]) if db == "minikraken": db = os.path.join(install._get_data_dir(), "genomes", "kraken", "minikraken") if not os.path.exists(db): logger.info("kraken: no database found %s, skipping" % db) return {"kraken_report": "null"} if not os.path.exists(os.path.join(out_dir, "kraken_out")): work_dir = os.path.dirname(out_dir) utils.safe_makedir(work_dir) num_cores = data["config"]["algorithm"].get("num_cores", 1) fn_file = data["files_orig"][0] if dd.get_save_diskspace(data) else data["files"][0] if fn_file.endswith("bam"): logger.info("kraken: need fastq files as input") return {"kraken_report": "null"} with tx_tmpdir(data) as tx_tmp_dir: with utils.chdir(tx_tmp_dir): out = os.path.join(tx_tmp_dir, "kraken_out") out_stats = os.path.join(tx_tmp_dir, "kraken_stats") cat = "zcat" if fn_file.endswith(".gz") else "cat" cl = ("{cat} {fn_file} | {kraken_cmd} --db {db} --quick " "--preload --min-hits 2 " "--threads {num_cores} " "--output {out} --fastq-input /dev/stdin 2> {out_stats}").format(**locals()) do.run(cl, "kraken: %s" % dd.get_sample_name(data)) if os.path.exists(out_dir): shutil.rmtree(out_dir) shutil.move(tx_tmp_dir, out_dir) metrics = _parse_kraken_output(out_dir, db, data) return metrics def _parse_kraken_output(out_dir, db, data): """Parse kraken stat info comming from stderr, generating report with kraken-report """ in_file = os.path.join(out_dir, "kraken_out") stat_file = os.path.join(out_dir, "kraken_stats") out_file = os.path.join(out_dir, "kraken_summary") kraken_cmd = config_utils.get_program("kraken-report", data["config"]) classify = unclassify = None with open(stat_file, 'r') as handle: for line in handle: if line.find(" classified") > -1: classify = line[line.find("(") + 1:line.find(")")] if line.find(" unclassified") > -1: unclassify = line[line.find("(") + 1:line.find(")")] if os.path.getsize(in_file) > 0 and not os.path.exists(out_file): with file_transaction(data, out_file) as tx_out_file: cl = ("{kraken_cmd} --db {db} {in_file} > {tx_out_file}").format(**locals()) do.run(cl, "kraken report: %s" % dd.get_sample_name(data)) kraken = {"kraken_clas": classify, "kraken_unclas": unclassify} kraken_sum = _summarize_kraken(out_file) kraken.update(kraken_sum) return kraken def _summarize_kraken(fn): """get the value at species level""" kraken = {} list_sp, list_value = [], [] with open(fn) as handle: for line in handle: cols = line.strip().split("\t") sp = cols[5].strip() if len(sp.split(" ")) > 1 and not sp.startswith("cellular"): list_sp.append(sp) list_value.append(cols[0]) kraken = {"kraken_sp": list_sp, "kraken_value": list_value} return kraken bcbio-nextgen-1.2.9/bcbio/qc/multiqc.py000066400000000000000000000644461415626112400200000ustar00rootroot00000000000000"""High level summaries of samples and programs with MultiQC. https://github.com/ewels/MultiQC """ import collections import glob import io import json import mimetypes import os import pandas as pd import shutil import numpy as np from collections import OrderedDict import pybedtools import six import toolz as tz import yaml from bcbio import utils from bcbio.cwl import cwlutils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.log import logger from bcbio.provenance import do, programs from bcbio.provenance import data as provenancedata from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.bam import ref from bcbio.qc.qsignature import get_qsig_multiqc_files from bcbio.structural import annotate from bcbio.utils import walk_json from bcbio.variation import bedutils from bcbio.qc.variant import get_active_vcinfo from bcbio.upload import get_all_upload_paths_from_sample from bcbio.variation import coverage from bcbio.chipseq import atac def summary(*samples): """Summarize all quality metrics together""" samples = list(utils.flatten(samples)) work_dir = dd.get_work_dir(samples[0]) multiqc = config_utils.get_program("multiqc", samples[0]["config"]) if not multiqc: logger.debug("multiqc not found. Update bcbio_nextgen.py tools to fix this issue.") out_dir = utils.safe_makedir(os.path.join(work_dir, "qc", "multiqc")) out_data = os.path.join(out_dir, "multiqc_data") out_file = os.path.join(out_dir, "multiqc_report.html") file_list = os.path.join(out_dir, "list_files.txt") work_samples = cwlutils.unpack_tarballs([utils.deepish_copy(x) for x in samples], samples[0]) work_samples = _summarize_inputs(work_samples, out_dir) if not utils.file_exists(out_file): with tx_tmpdir(samples[0], work_dir) as tx_out: in_files = _get_input_files(work_samples, out_dir, tx_out) in_files += _merge_metrics(work_samples, out_dir) if _one_exists(in_files): with utils.chdir(out_dir): config_file = _create_config_file(out_dir, work_samples) input_list_file = _create_list_file(in_files, file_list) if dd.get_tmp_dir(samples[0]): export_tmp = "export TMPDIR=%s && " % dd.get_tmp_dir(samples[0]) else: export_tmp = "" locale_export = utils.locale_export() path_export = utils.local_path_export() other_opts = config_utils.get_resources("multiqc", samples[0]["config"]).get("options", []) other_opts = " ".join([str(x) for x in other_opts]) cmd = ("{path_export}{export_tmp}{locale_export} " "{multiqc} -c {config_file} -f -l {input_list_file} {other_opts} -o {tx_out}") do.run(cmd.format(**locals()), "Run multiqc") if utils.file_exists(os.path.join(tx_out, "multiqc_report.html")): shutil.move(os.path.join(tx_out, "multiqc_report.html"), out_file) shutil.move(os.path.join(tx_out, "multiqc_data"), out_data) samples = _group_by_sample_and_batch(samples) if utils.file_exists(out_file) and samples: data_files = set() for i, data in enumerate(samples): data_files.add(os.path.join(out_dir, "report", "metrics", dd.get_sample_name(data) + "_bcbio.txt")) data_files.add(os.path.join(out_dir, "report", "metrics", "target_info.yaml")) data_files.add(os.path.join(out_dir, "multiqc_config.yaml")) [data_files.add(f) for f in glob.glob(os.path.join(out_dir, "multiqc_data", "*"))] data_files = [f for f in data_files if f and utils.file_exists(f)] if "summary" not in samples[0]: samples[0]["summary"] = {} samples[0]["summary"]["multiqc"] = {"base": out_file, "secondary": data_files} data_json = os.path.join(out_dir, "multiqc_data", "multiqc_data.json") data_json_final = _save_uploaded_data_json(samples, data_json, os.path.join(out_dir, "multiqc_data")) if data_json_final: samples[0]["summary"]["multiqc"]["secondary"].append(data_json_final) # Prepare final file list and inputs for downstream usage file_list_final = _save_uploaded_file_list(samples, file_list, out_dir) if file_list_final: samples[0]["summary"]["multiqc"]["secondary"].append(file_list_final) if any([cwlutils.is_cwl_run(d) for d in samples]): for indir in ["inputs", "report"]: tarball = os.path.join(out_dir, "multiqc-%s.tar.gz" % (indir)) if not utils.file_exists(tarball): with utils.chdir(out_dir): cmd = ["tar", "-czvpf", tarball, indir] do.run(cmd, "Compress multiqc inputs: %s" % indir) samples[0]["summary"]["multiqc"]["secondary"].append(tarball) if any([cwlutils.is_cwl_run(d) for d in samples]): samples = _add_versions(samples) return [[data] for data in samples] def _add_versions(samples): """Add tool and data versions to the summary. """ samples[0]["versions"] = {"tools": programs.write_versions(samples[0]["dirs"], samples[0]["config"]), "data": provenancedata.write_versions(samples[0]["dirs"], samples)} return samples def _summarize_inputs(samples, out_dir): """Summarize inputs for MultiQC reporting in display. """ logger.info("summarize target information") if samples[0].get("analysis", "").lower() in ["variant", "variant2"]: metrics_dir = utils.safe_makedir(os.path.join(out_dir, "report", "metrics")) samples = _merge_target_information(samples, metrics_dir) logger.info("summarize fastqc") out_dir = utils.safe_makedir(os.path.join(out_dir, "report", "fastqc")) with utils.chdir(out_dir): _merge_fastqc(samples) preseq_samples = [s for s in samples if tz.get_in(["config", "algorithm", "preseq"], s)] if preseq_samples: logger.info("summarize preseq") out_dir = utils.safe_makedir(os.path.join(out_dir, "report", "preseq")) with utils.chdir(out_dir): _merge_preseq(preseq_samples) return samples def _save_uploaded_data_json(samples, data_json_work, out_dir): """ Fixes all absolute work-rooted paths to relative final-rooted paths """ if not utils.file_exists(data_json_work): return None upload_path_mapping = dict() for sample in samples: upload_path_mapping.update(get_all_upload_paths_from_sample(sample)) if not upload_path_mapping: return data_json_work with io.open(data_json_work, encoding="utf-8") as f: data = json.load(f, object_pairs_hook=OrderedDict) upload_base = samples[0]["upload"]["dir"] data = walk_json(data, lambda s: _work_path_to_rel_final_path(s, upload_path_mapping, upload_base)) data_json_final = os.path.join(out_dir, "multiqc_data_final.json") with io.open(data_json_final, "w", encoding="utf-8") as f: json.dump(data, f, indent=4) return data_json_final def _save_uploaded_file_list(samples, file_list_work, out_dir): """ Fixes all absolute work-rooted paths to relative final-rooted paths For CWL, prepare paths relative to output directory. """ if not utils.file_exists(file_list_work): return None if any([cwlutils.is_cwl_run(d) for d in samples]): upload_paths = [] with open(file_list_work) as f: for p in (l.strip() for l in f.readlines() if os.path.exists(l.strip())): if p.startswith(out_dir): upload_paths.append(p.replace(out_dir + "/", "")) else: upload_path_mapping = dict() for sample in samples: upload_path_mapping.update(get_all_upload_paths_from_sample(sample)) if not upload_path_mapping: return None with open(file_list_work) as f: paths = [l.strip() for l in f.readlines() if os.path.exists(l.strip())] upload_paths = [p for p in [ _work_path_to_rel_final_path(path, upload_path_mapping, samples[0]["upload"]["dir"]) for path in paths ] if p] if not upload_paths: return None file_list_final = os.path.join(out_dir, "list_files_final.txt") with open(file_list_final, "w") as f: for path in upload_paths: f.write(path + '\n') return file_list_final def _work_path_to_rel_final_path(path, upload_path_mapping, upload_base_dir): """ Check if `path` is a work-rooted path, and convert to a relative final-rooted path """ if not path or not isinstance(path, str): return path upload_path = None # First, check in the mapping: if it's there is a direct reference and # it's a file, we immediately return it (saves lots of iterations) if upload_path_mapping.get(path) is not None and os.path.isfile(path): upload_path = upload_path_mapping[path] else: # Not a file: check for elements in the mapping that contain # it paths_to_check = [key for key in upload_path_mapping if path.startswith(key)] if paths_to_check: for work_path in paths_to_check: if os.path.isdir(work_path): final_path = upload_path_mapping[work_path] upload_path = path.replace(work_path, final_path) break if upload_path is not None: return os.path.relpath(upload_path, upload_base_dir) else: return None def _one_exists(input_files): """ at least one file must exist for multiqc to run properly """ for f in input_files: if os.path.exists(f): return True return False def _get_input_files(samples, base_dir, tx_out_dir): """Retrieve input files, keyed by sample and QC method name. Stages files into the work directory to ensure correct names for MultiQC sample assessment when running with CWL. """ in_files = collections.defaultdict(list) for data in samples: sum_qc = tz.get_in(["summary", "qc"], data, {}) if sum_qc in [None, "None"]: sum_qc = {} elif isinstance(sum_qc, six.string_types): sum_qc = {dd.get_algorithm_qc(data)[0]: sum_qc} elif not isinstance(sum_qc, dict): raise ValueError("Unexpected summary qc: %s" % sum_qc) for program, pfiles in sum_qc.items(): if isinstance(pfiles, dict): pfiles = [pfiles["base"]] + pfiles.get("secondary", []) # CWL: presents output files as single file plus associated secondary files elif isinstance(pfiles, six.string_types): if os.path.exists(pfiles): pfiles = [os.path.join(basedir, f) for basedir, subdir, filenames in os.walk(os.path.dirname(pfiles)) for f in filenames] else: pfiles = [] in_files[(dd.get_sample_name(data), program)].extend(pfiles) staged_files = [] for (sample, program), files in in_files.items(): cur_dir = utils.safe_makedir(os.path.join(base_dir, "inputs", sample, program)) for f in files: if _check_multiqc_input(f) and _is_good_file_for_multiqc(f): if _in_temp_directory(f) or any([cwlutils.is_cwl_run(d) for d in samples]): staged_f = os.path.join(cur_dir, os.path.basename(f)) shutil.copy(f, staged_f) staged_files.append(staged_f) else: staged_files.append(f) staged_files.extend(get_qsig_multiqc_files(samples)) # Back compatible -- to migrate to explicit specifications in input YAML if not any([cwlutils.is_cwl_run(d) for d in samples]): staged_files += ["trimmed", "htseq-count/*summary"] # Add in created target_info file if os.path.isfile(os.path.join(base_dir, "report", "metrics", "target_info.yaml")): staged_files += [os.path.join(base_dir, "report", "metrics", "target_info.yaml")] return sorted(list(set(staged_files))) def _in_temp_directory(f): return any(x.startswith("tmp") for x in f.split("/")) def _get_batches(data): batches = dd.get_batch(data) or dd.get_sample_name(data) if not isinstance(batches, (list, tuple)): batches = [batches] return batches def _group_by_sample_and_batch(samples): """Group samples split by QC method back one per sample-batch. """ out = collections.defaultdict(list) for data in samples: out[(dd.get_sample_name(data), dd.get_align_bam(data), tuple(_get_batches(data)))].append(data) return [xs[0] for xs in out.values()] def _create_list_file(paths, out_file): with open(out_file, "w") as f: for path in paths: f.write(path + '\n') return out_file def _create_config_file(out_dir, samples): """Provide configuration file for multiqc report.""" out_file = os.path.join(out_dir, "multiqc_config.yaml") out = {"table_columns_visible": dict()} extra_fn_clean_trim = [] extra_fn_clean_trim.extend(["coverage.mosdepth.region.dist", "coverage.mosdepth.global.dist"]) out["extra_fn_clean_trim"] = extra_fn_clean_trim # Avoid duplicated bcbio columns with qualimap if any(("qualimap" in dd.get_tools_on(d) or "qualimap_full" in dd.get_tools_on(d)) for d in samples): # Hiding metrics duplicated by Qualimap out["table_columns_visible"]["bcbio"] = {"Average_insert_size": False} out["table_columns_visible"]["FastQC"] = {"percent_gc": False} # Setting up thresholds for Qualimap depth cutoff calculations, based on sample avg depths avg_depths = [tz.get_in(["summary", "metrics", "Avg_coverage"], s) for s in samples] avg_depths = [x for x in avg_depths if x] # Picking all thresholds up to the highest sample average depth thresholds = [t for t in coverage.DEPTH_THRESHOLDS if not avg_depths or t <= max(avg_depths)] # ...plus one more if len(thresholds) < len(coverage.DEPTH_THRESHOLDS): thresholds.append(coverage.DEPTH_THRESHOLDS[len(thresholds)]) # Showing only thresholds surrounding any of average depths thresholds_hidden = [] for i, t in enumerate(thresholds): if t > 20: # Not hiding anything below 20x if any(thresholds[i-1] <= c < thresholds[i] for c in avg_depths if c and i-1 >= 0) or \ any(thresholds[i] <= c < thresholds[i+1] for c in avg_depths if c and i+1 < len(thresholds)): pass else: thresholds_hidden.append(t) # Hide coverage unless running full qualimap, downsampled inputs are confusing if not any(("qualimap_full" in dd.get_tools_on(d)) for d in samples): thresholds_hidden = thresholds + thresholds_hidden thresholds_hidden.sort() thresholds = [] out['qualimap_config'] = { 'general_stats_coverage': [str(t) for t in thresholds], 'general_stats_coverage_hidden': [str(t) for t in thresholds_hidden]} # Avoid confusing peddy outputs, sticking to ancestry and sex prediction out["table_columns_visible"]["Peddy"] = {"family_id": False, "sex_het_ratio": False, "error_sex_check": False} # Setting the module order module_order = [] module_order.extend([ "bcbio", "samtools", "goleft_indexcov", "peddy" ]) out['bcftools'] = {'write_separate_table': True} # if germline calling was performed: if any("germline" in (get_active_vcinfo(s) or {}) or # tumor-only somatic with germline extraction dd.get_phenotype(s) == "germline" or # or paired somatic with germline calling for normal _has_bcftools_germline_stats(s) # CWL organized statistics for s in samples): # Split somatic and germline variant stats into separate multiqc submodules, # with somatic going into General Stats, and germline going into a separate table: module_order.extend([{ 'bcftools': { 'name': 'Bcftools (somatic)', 'info': 'Bcftools stats for somatic variant calls only.', 'path_filters': ['*_bcftools_stats.txt'], 'custom_config': {'write_general_stats': True}, }}, {'bcftools': { 'name': 'Bcftools (germline)', 'info': 'Bcftools stats for germline variant calls only.', 'path_filters': ['*_bcftools_stats_germline.txt'], 'custom_config': {'write_general_stats': False}, }}, ]) else: module_order.append("bcftools") module_order.extend([ "salmon", "star", "picard", "qualimap", "snpeff", "bismark", "fastqc", "preseq" ]) out["module_order"] = module_order preseq_samples = [s for s in samples if tz.get_in(["config", "algorithm", "preseq"], s)] if preseq_samples: out["preseq"] = _make_preseq_multiqc_config(preseq_samples) with open(out_file, "w") as out_handle: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) return out_file def _has_bcftools_germline_stats(data): """Check for the presence of a germline stats file, CWL compatible. """ stats_file = tz.get_in(["summary", "qc"], data) if isinstance(stats_file, dict): stats_file = tz.get_in(["variants", "base"], stats_file) if not stats_file: stats_file = "" return stats_file.find("bcftools_stats_germline") > 0 def _check_multiqc_input(path): """Check if file exists, and return empty if it doesn't""" if utils.file_exists(path): return path # ## report and coverage def _is_good_file_for_multiqc(fpath): """Returns False if the file is binary or image.""" # Use mimetypes to exclude binary files where possible (ftype, encoding) = mimetypes.guess_type(fpath) if encoding is not None: return False if ftype is not None and ftype.startswith('image'): return False return True def _parse_disambiguate(disambiguatestatsfilename): """Parse disambiguation stats from given file.""" disambig_stats = [0, 0, 0] with open(disambiguatestatsfilename, "r") as in_handle: for i, line in enumerate(in_handle): fields = line.strip().split("\t") if i == 0: assert fields == ['sample', 'unique species A pairs', 'unique species B pairs', 'ambiguous pairs'] else: disambig_stats = [x + int(y) for x, y in zip(disambig_stats, fields[1:])] # stats is reported in read pairs while Reads in the final bam in single # reporting here single reads as well disambig_stats_single_reads = [2 * x for x in disambig_stats] return disambig_stats_single_reads def _add_disambiguate(sample): # check if disambiguation was run if "disambiguate" in sample: if utils.file_exists(sample["disambiguate"]["summary"]): disambigStats = _parse_disambiguate(sample["disambiguate"]["summary"]) sample["summary"]["metrics"]["Disambiguated %s reads" % str(sample["genome_build"])] = disambigStats[0] disambigGenome = (sample["config"]["algorithm"]["disambiguate"][0] if isinstance(sample["config"]["algorithm"]["disambiguate"], (list, tuple)) else sample["config"]["algorithm"]["disambiguate"]) sample["summary"]["metrics"]["Disambiguated %s reads" % disambigGenome] = disambigStats[1] sample["summary"]["metrics"]["Disambiguated ambiguous reads"] = disambigStats[2] return sample def _add_atac(sample): atac_metrics = atac.calculate_encode_complexity_metrics(sample) if not atac_metrics: return sample sample["summary"]["metrics"] = tz.merge(atac_metrics, sample["summary"]["metrics"]) return sample def _fix_duplicated_rate(dt): """Get RNA duplicated rate if exists and replace by samtools metric""" if "Duplication_Rate_of_Mapped" in dt: dt["Duplicates_pct"] = 100.0 * dt["Duplication_Rate_of_Mapped"] return dt def _merge_metrics(samples, out_dir): """Merge metrics from multiple QC steps """ logger.info("summarize metrics") out_dir = utils.safe_makedir(os.path.join(out_dir, "report", "metrics")) sample_metrics = collections.defaultdict(dict) for s in samples: s = _add_disambiguate(s) s = _add_atac(s) m = tz.get_in(['summary', 'metrics'], s) if isinstance(m, six.string_types): m = json.loads(m) if m: for me in list(m.keys()): if isinstance(m[me], list) or isinstance(m[me], dict) or isinstance(m[me], tuple): m.pop(me, None) sample_metrics[dd.get_sample_name(s)].update(m) out = [] for sample_name, m in sample_metrics.items(): sample_file = os.path.join(out_dir, "%s_bcbio.txt" % sample_name) with file_transaction(samples[0], sample_file) as tx_out_file: dt = pd.DataFrame(m, index=['1']) dt.columns = [k.replace(" ", "_").replace("(", "").replace(")", "") for k in dt.columns] dt['sample'] = sample_name if m.get('rRNA_rate'): dt['rRNA_rate'] = m.get('rRNA_rate') if m.get("RiP"): dt['RiP_pct'] = "%.3f" % (int(m.get("RiP")) / float(m.get("Total_reads", 1)) * 100) dt = _fix_duplicated_rate(dt) dt.transpose().to_csv(tx_out_file, sep="\t", header=False) out.append(sample_file) return out def _merge_fastqc(samples): """ merge all fastqc samples into one by module """ fastqc_list = collections.defaultdict(list) seen = set() for data in samples: name = dd.get_sample_name(data) if name in seen: continue seen.add(name) fns = glob.glob(os.path.join(dd.get_work_dir(data), "qc", dd.get_sample_name(data), "fastqc") + "/*") for fn in fns: if fn.endswith("tsv"): metric = os.path.basename(fn) fastqc_list[metric].append([name, fn]) for metric in fastqc_list: dt_by_sample = [] for fn in fastqc_list[metric]: dt = pd.read_csv(fn[1], sep="\t") dt['sample'] = fn[0] dt_by_sample.append(dt) dt = utils.rbind(dt_by_sample) dt.to_csv(metric, sep="\t", index=False, mode ='w') return samples def _merge_preseq(samples): metrics = [utils.get_in(s, ("summary", "metrics")) for s in samples] real_counts_file = os.path.abspath(os.path.join("preseq_real_counts.txt")) with file_transaction(samples[0], real_counts_file) as tx_out_file: with open(tx_out_file, "w") as f: for s, m in zip(samples, metrics): line = dd.get_sample_name(s) + "\t" + str(m["Preseq_read_count"]) if m.get("Preseq_unique_count") is not None: line += "\t" + str(m["Preseq_unique_count"]) line += "\n" f.write(line) samples[0]["summary"]["qc"]["preseq"]["secondary"] = [real_counts_file] def _make_preseq_multiqc_config(samples): metrics = [utils.get_in(s, ("summary", "metrics")) for s in samples] out = {"read_length": float(np.median([m["Preseq_read_length"] for m in metrics]))} genome_sizes = list(set(m["Preseq_genome_size"] for m in metrics)) if len(genome_sizes) == 1: out["genome_size"] = genome_sizes[0] return out def _merge_target_information(samples, metrics_dir): out_file = os.path.abspath(os.path.join(metrics_dir, "target_info.yaml")) if utils.file_exists(out_file): return samples genomes = set(dd.get_genome_build(data) for data in samples) coverage_beds = set(dd.get_coverage(data) for data in samples) original_variant_regions = set(dd.get_variant_regions_orig(data) for data in samples) data = samples[0] info = {} # Reporting in MultiQC only if the genome is the same across all samples if len(genomes) == 1: info["genome_info"] = { "name": dd.get_genome_build(data), "size": sum([c.size for c in ref.file_contigs(dd.get_ref_file(data), data["config"])]), } # Reporting in MultiQC only if the target is the same across all samples vcr_orig = None if len(original_variant_regions) == 1 and list(original_variant_regions)[0] is not None: vcr_orig = list(original_variant_regions)[0] vcr_clean = bedutils.clean_file(vcr_orig, data) info["variants_regions_info"] = { "bed": vcr_orig, "size": sum(len(x) for x in pybedtools.BedTool(dd.get_variant_regions_merged(data))), "regions": pybedtools.BedTool(vcr_clean).count(), } gene_num = annotate.count_genes(vcr_clean, data) if gene_num is not None: info["variants_regions_info"]["genes"] = gene_num else: info["variants_regions_info"] = { "bed": "callable regions", } # Reporting in MultiQC only if the target is the same across samples if len(coverage_beds) == 1: cov_bed = list(coverage_beds)[0] if cov_bed not in [None, "None"]: if vcr_orig and vcr_orig == cov_bed: info["coverage_bed_info"] = info["variants_regions_info"] else: clean_bed = bedutils.clean_file(cov_bed, data, prefix="cov-", simple=True) info["coverage_bed_info"] = { "bed": cov_bed, "size": pybedtools.BedTool(cov_bed).total_coverage(), "regions": pybedtools.BedTool(clean_bed).count(), } gene_num = annotate.count_genes(clean_bed, data) if gene_num is not None: info["coverage_bed_info"]["genes"] = gene_num else: info["coverage_bed_info"] = info["variants_regions_info"] coverage_intervals = set(data["config"]["algorithm"]["coverage_interval"] for data in samples) if len(coverage_intervals) == 1: info["coverage_interval"] = list(coverage_intervals)[0] if info: with open(out_file, "w") as out_handle: yaml.safe_dump(info, out_handle) return samples bcbio-nextgen-1.2.9/bcbio/qc/picard.py000066400000000000000000000033671415626112400175570ustar00rootroot00000000000000import os from bcbio import utils from bcbio import broad from bcbio.broad.metrics import PicardMetrics from bcbio import bam from bcbio.distributed.transaction import tx_tmpdir from bcbio.provenance import do from bcbio.pipeline import datadict as dd def run(bam_file, data, out_dir): if "picard" not in dd.get_tools_on(data): return {} ref_file = dd.get_ref_file(data) sample = dd.get_sample_name(data) target_file = dd.get_variant_regions(data) or dd.get_sample_callable(data) broad_runner = broad.PicardCmdRunner("picard", data["config"]) bam_fname = os.path.abspath(bam_file) path = os.path.dirname(bam_fname) utils.safe_makedir(out_dir) out_base = utils.splitext_plus(os.path.basename(bam_fname))[0] hsmetric_file = os.path.join(out_dir, "%s.hs_metrics" % out_base) hsinsert_file = os.path.join(out_dir, "%s.insert_metrics" % out_base) if not utils.file_exists(hsmetric_file) and not utils.file_exists(hsinsert_file): with utils.chdir(out_dir): with tx_tmpdir() as tmp_dir: cur_bam = os.path.basename(bam_fname) if not os.path.exists(cur_bam): os.symlink(bam_fname, cur_bam) gen_metrics = PicardMetrics(broad_runner, tmp_dir) gen_metrics.report(cur_bam, ref_file, bam.is_paired(bam_fname), target_file, target_file, None, data["config"]) if utils.file_exists(hsmetric_file): do.run("sed -i 's/%s.bam//g' %s" % (out_base.replace(sample, ""), hsmetric_file), "") if utils.file_exists(hsinsert_file): do.run("sed -i 's/%s.bam//g' %s" % (out_base.replace(sample, ""), hsinsert_file), "") return hsmetric_file bcbio-nextgen-1.2.9/bcbio/qc/preseq.py000066400000000000000000000147111415626112400176070ustar00rootroot00000000000000"""Runs Preseq, a tool that estimates the complexity of a library. http://smithlabresearch.org/software/preseq/ Executes `lc_extrap` or `c_curve` commands that predict the yield for future experiments (for higher or lower input correspondingly). """ import os import math import pybedtools import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.bam import ref, readstats from bcbio.variation import coverage as cov from bcbio.qc import samtools def run(bam_file, data, out_dir): out = {} preseq_cmd = tz.get_in(["config", "algorithm", "preseq"], data) if not preseq_cmd: return out samtools_stats_dir = os.path.join(out_dir, os.path.pardir, "samtools") samtools_stats = samtools.run(bam_file, data, samtools_stats_dir)["metrics"] stats_file = os.path.join(out_dir, "%s.txt" % dd.get_sample_name(data)) if not utils.file_exists(stats_file): utils.safe_makedir(out_dir) preseq = config_utils.get_program("preseq", data["config"]) params = _get_preseq_params(data, preseq_cmd, int(samtools_stats["Total_reads"])) param_line = "{options} -step {step} -seg_len {seg_len} " if preseq_cmd == "lc_extrap": param_line += "-extrap {extrap} " param_line = param_line.format(**params) with file_transaction(data, stats_file) as tx_out_file: cmd = "{preseq} {preseq_cmd} -bam -pe {bam_file} -o {tx_out_file} {param_line}".format(**locals()) do.run(cmd.format(**locals()), "preseq " + preseq_cmd, data) out = _prep_real_counts(bam_file, data, samtools_stats) return {"base": stats_file, "metrics": out} def _get_preseq_params(data, preseq_cmd, read_count): """ Get parameters through resources. If "step" or "extrap" limit are not provided, then calculate optimal values based on read count. """ defaults = { 'seg_len': 100000, # maximum segment length when merging paired end bam reads 'steps': 300, # number of points on the plot 'extrap_fraction': 3, # extrapolate up to X times read_count 'extrap': None, # extrapolate up to X reads 'step': None, # step size (number of reads between points on the plot) 'options': '', } params = {} main_opts = [("-e", "-extrap"), ("-l", "-seg_len"), ("-s", "-step")] other_opts = config_utils.get_resources("preseq", data["config"]).get("options", []) if isinstance(other_opts, str): other_opts = [other_opts] for sht, lng in main_opts: if sht in other_opts: i = other_opts.index(sht) elif lng in other_opts: i = other_opts.index(lng) else: i = None if i is not None: params[lng[1:]] = other_opts[i + 1] other_opts = other_opts[:i] + other_opts[i + 2:] params['options'] = ' '.join(other_opts) for k, v in config_utils.get_resources("preseq", data["config"]).items(): if k != 'options': params[k] = v params['steps'] = params.get('steps', defaults['steps']) if preseq_cmd == 'c_curve': params['extrap_fraction'] = 1 else: if params.get('step') is None: if params.get('extrap') is None: unrounded__extrap = read_count * params.get('extrap_fraction', defaults['extrap_fraction']) unrounded__step = unrounded__extrap // params['steps'] if params.get('extrap_fraction') is not None: # extrap_fraction explicitly provided params['extrap'] = unrounded__extrap params['step'] = unrounded__step else: power_of_10 = 10 ** math.floor(math.log(unrounded__step, 10)) rounded__step = int(math.floor(unrounded__step // power_of_10) * power_of_10) rounded__extrap = int(rounded__step) * params['steps'] params['step'] = rounded__step params['extrap'] = rounded__extrap else: params['step'] = params['extrap'] // params['steps'] elif params.get('extrap') is None: params['extrap'] = params['step'] * params['steps'] params['step'] = params.get('step', defaults['step']) params['extrap'] = params.get('extrap', defaults['extrap']) params['seg_len'] = params.get('seg_len', defaults['seg_len']) logger.info("Preseq: running {steps} steps of size {step}, extap limit {extrap}".format(**params)) return params def _prep_real_counts(bam_file, data, samtools_stats): out = {} if dd.get_coverage(data) and dd.get_coverage(data) not in ["None"]: bed = dd.get_coverage_merged(data) target_name = "coverage" elif dd.get_coverage_interval(data) != "genome": bed = dd.get_variant_regions_merged(data) or dd.get_sample_callable(data) target_name = "variant_regions" else: bed = None target_name = "genome" dedupped = utils.get_in(data, ("config", "algorithm", "mark_duplicates"), True) if bed: out["Preseq_genome_size"] = pybedtools.BedTool(bed).total_coverage() out["Preseq_read_count"] = readstats.number_of_mapped_reads( data, bam_file, keep_dups=True, bed_file=bed, target_name=target_name) ontrg_unique_depth = cov.get_average_coverage(target_name, bed, data, bam_file) if dedupped: out["Preseq_unique_count"] = readstats.number_of_mapped_reads( data, bam_file, keep_dups=False, bed_file=bed, target_name=target_name) # Counting average on-target alignment length, based on the equation: # avg depth ~~ num (unique) on-target alignments * avg on-target aln length / target size total_alignments = out.get("Preseq_unique_count") or out["Preseq_read_count"] out["Preseq_read_length"] = ontrg_unique_depth * out["Preseq_genome_size"] // total_alignments else: # WGS out["Preseq_genome_size"] = sum([c.size for c in ref.file_contigs(dd.get_ref_file(data), data["config"])]) out["Preseq_read_count"] = int(samtools_stats["Total_reads"]) out["Preseq_read_length"] = int(samtools_stats["Average_read_length"]) if dedupped: out["Preseq_unique_count"] = out["Preseq_read_count"] - int(samtools_stats["Duplicates"]) return out bcbio-nextgen-1.2.9/bcbio/qc/qsignature.py000066400000000000000000000210251415626112400204660ustar00rootroot00000000000000"""Qsignature: detection of sample mixups. https://sourceforge.net/p/adamajava/wiki/qSignature/ """ import os import shutil import subprocess import xml.etree.ElementTree as ET import pysam import toolz as tz from bcbio import bam, utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils def run(bam_file, data, out_dir): """ Run SignatureGenerator to create normalize vcf that later will be input of qsignature_summary :param bam_file: (str) path of the bam_file :param data: (list) list containing the all the dictionary for this sample :param out_dir: (str) path of the output :returns: (string) output normalized vcf file """ qsig = config_utils.get_program("qsignature", data["config"]) res_qsig = config_utils.get_resources("qsignature", data["config"]) jvm_opts = " ".join(res_qsig.get("jvm_opts", ["-Xms750m", "-Xmx8g"])) if not qsig: logger.info("There is no qsignature tool. Skipping...") return None position = dd.get_qsig_file(data) mixup_check = dd.get_mixup_check(data) if mixup_check and mixup_check.startswith("qsignature"): utils.safe_makedir(out_dir) if not position: logger.info("There is no qsignature for this species: %s" % tz.get_in(['genome_build'], data)) return None if mixup_check == "qsignature_full": down_bam = bam_file else: down_bam = _slice_bam_chr21(bam_file, data) position = _slice_vcf_chr21(position, out_dir) out_name = os.path.basename(down_bam).replace("bam", "qsig.vcf") out_file = os.path.join(out_dir, out_name) log_file = os.path.join(out_dir, "qsig.log") cores = dd.get_cores(data) base_cmd = ("{qsig} {jvm_opts} " "org.qcmg.sig.SignatureGenerator " "--noOfThreads {cores} " "-log {log_file} -i {position} " "-i {down_bam} ") if not os.path.exists(out_file): file_qsign_out = "{0}.qsig.vcf".format(down_bam) do.run(base_cmd.format(**locals()), "qsignature vcf generation: %s" % dd.get_sample_name(data)) if os.path.exists(file_qsign_out): with file_transaction(data, out_file) as file_txt_out: shutil.move(file_qsign_out, file_txt_out) else: raise IOError("File doesn't exist %s" % file_qsign_out) return out_file return None def summary(*samples): """Run SignatureCompareRelatedSimple module from qsignature tool. Creates a matrix of pairwise comparison among samples. The function will not run if the output exists :param samples: list with only one element containing all samples information :returns: (dict) with the path of the output to be joined to summary """ warnings, similar = [], [] qsig = config_utils.get_program("qsignature", samples[0][0]["config"]) if not qsig: return [[]] res_qsig = config_utils.get_resources("qsignature", samples[0][0]["config"]) jvm_opts = " ".join(res_qsig.get("jvm_opts", ["-Xms750m", "-Xmx8g"])) work_dir = samples[0][0]["dirs"]["work"] count = 0 for data in samples: data = data[0] vcf = tz.get_in(["summary", "qc", "qsignature", "base"], data) if vcf: count += 1 vcf_name = dd.get_sample_name(data) + ".qsig.vcf" out_dir = utils.safe_makedir(os.path.join(work_dir, "qsignature")) if not os.path.lexists(os.path.join(out_dir, vcf_name)): os.symlink(vcf, os.path.join(out_dir, vcf_name)) if count > 0: qc_out_dir = utils.safe_makedir(os.path.join(work_dir, "qc", "qsignature")) out_file = os.path.join(qc_out_dir, "qsignature.xml") out_ma_file = os.path.join(qc_out_dir, "qsignature.ma") out_warn_file = os.path.join(qc_out_dir, "qsignature.warnings") log = os.path.join(work_dir, "qsignature", "qsig-summary.log") if not os.path.exists(out_file): with file_transaction(samples[0][0], out_file) as file_txt_out: base_cmd = ("{qsig} {jvm_opts} " "org.qcmg.sig.SignatureCompareRelatedSimple " "-log {log} -dir {out_dir} " "-o {file_txt_out} ") do.run(base_cmd.format(**locals()), "qsignature score calculation") error, warnings, similar = _parse_qsignature_output(out_file, out_ma_file, out_warn_file, samples[0][0]) return [{'total samples': count, 'similar samples pairs': len(similar), 'warnings samples pairs': len(warnings), 'error samples': list(error), 'out_dir': qc_out_dir}] else: return [] def get_qsig_multiqc_files(*samples): work_dir = samples[0][0]["dirs"]["work"] qc_out_dir = utils.safe_makedir(os.path.join(work_dir, "qc", "qsignature")) return [os.path.join(qc_out_dir, "qsignature.ma")] def _parse_qsignature_output(in_file, out_file, warning_file, data): """ Parse xml file produced by qsignature :param in_file: (str) with the path to the xml file :param out_file: (str) with the path to output file :param warning_file: (str) with the path to warning file :returns: (list) with samples that could be duplicated """ name = {} error, warnings, similar = set(), set(), set() same, replicate, related = 0, 0.1, 0.18 mixup_check = dd.get_mixup_check(data) if mixup_check == "qsignature_full": same, replicate, related = 0, 0.01, 0.061 with open(in_file, 'r') as in_handle: with file_transaction(data, out_file) as out_tx_file: with file_transaction(data, warning_file) as warn_tx_file: with open(out_tx_file, 'w') as out_handle: with open(warn_tx_file, 'w') as warn_handle: et = ET.parse(in_handle) for i in list(et.iter('file')): name[i.attrib['id']] = os.path.basename(i.attrib['name']).replace(".qsig.vcf", "") for i in list(et.iter('comparison')): msg = None pair = "-".join([name[i.attrib['file1']], name[i.attrib['file2']]]) out_handle.write("%s\t%s\t%s\n" % (name[i.attrib['file1']], name[i.attrib['file2']], i.attrib['score'])) if float(i.attrib['score']) == same: msg = 'qsignature ERROR: read same samples:%s\n' error.add(pair) elif float(i.attrib['score']) < replicate: msg = 'qsignature WARNING: read similar/replicate samples:%s\n' warnings.add(pair) elif float(i.attrib['score']) < related: msg = 'qsignature NOTE: read relative samples:%s\n' similar.add(pair) if msg: logger.info(msg % pair) warn_handle.write(msg % pair) return error, warnings, similar def _slice_bam_chr21(in_bam, data): """ return only one BAM file with only chromosome 21 """ sambamba = config_utils.get_program("sambamba", data["config"]) out_file = "%s-chr%s" % os.path.splitext(in_bam) if not utils.file_exists(out_file): bam.index(in_bam, data['config']) with pysam.Samfile(in_bam, "rb") as bamfile: bam_contigs = [c["SN"] for c in bamfile.header["SQ"]] chromosome = "21" if "chr21" in bam_contigs: chromosome = "chr21" with file_transaction(data, out_file) as tx_out_file: cmd = ("{sambamba} slice -o {tx_out_file} {in_bam} {chromosome}").format(**locals()) out = subprocess.check_output(cmd, shell=True) return out_file def _slice_vcf_chr21(vcf_file, out_dir): """ Slice chr21 of qsignature SNPs to reduce computation time """ tmp_file = os.path.join(out_dir, "chr21_qsignature.vcf") if not utils.file_exists(tmp_file): cmd = ("grep chr21 {vcf_file} > {tmp_file}").format(**locals()) out = subprocess.check_output(cmd, shell=True) return tmp_file bcbio-nextgen-1.2.9/bcbio/qc/qualimap.py000066400000000000000000000437151415626112400201270ustar00rootroot00000000000000"""Quality control using Qualimap. http://qualimap.bioinfo.cipf.es/ """ import glob import os import shutil import pandas as pd import pybedtools import toolz as tz import toolz.dicttoolz as dtz from bcbio.log import logger from bcbio import bam, utils from bcbio.bam import readstats from bcbio.ngsalign import postalign from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.distributed.transaction import file_transaction from bcbio.rnaseq import gtf, salmon from bcbio.variation import bedutils # ## Standard Qualimap def run(bam_file, data, out_dir): """Run qualimap to assess alignment quality metrics. """ # Qualimap results should be saved to a directory named after sample. # MultiQC (for parsing additional data) picks the sample name after the dir as follows: # /raw_data_qualimapReport/insert_size_histogram.txt results_dir = os.path.join(out_dir, dd.get_sample_name(data)) resources = config_utils.get_resources("qualimap", data["config"]) options = " ".join(resources.get("options", "")) results_file = os.path.join(results_dir, "genome_results.txt") report_file = os.path.join(results_dir, "qualimapReport.html") utils.safe_makedir(results_dir) pdf_file = "qualimapReport.pdf" if not utils.file_exists(results_file) and not utils.file_exists(os.path.join(results_dir, pdf_file)): if "qualimap_full" in tz.get_in(("config", "algorithm", "tools_on"), data, []): logger.info("Full qualimap analysis for %s may be slow." % bam_file) ds_bam = bam_file else: ds_bam = bam.downsample(bam_file, data, 1e7, work_dir=out_dir) bam_file = ds_bam if ds_bam else bam_file if options.find("PDF") > -1: options = "%s -outfile %s" % (options, pdf_file) num_cores = data["config"]["algorithm"].get("num_cores", 1) qualimap = config_utils.get_program("qualimap", data["config"]) max_mem = config_utils.adjust_memory(resources.get("memory", "1G"), num_cores) with file_transaction(data, results_dir) as tx_results_dir: utils.safe_makedir(tx_results_dir) export = "%s%s export JAVA_OPTS='-Xms32m -Xmx%s -Djava.io.tmpdir=%s' && " % ( utils.java_freetype_fix(), utils.local_path_export(), max_mem, tx_results_dir) cmd = ("unset DISPLAY && {export} {qualimap} bamqc -bam {bam_file} -outdir {tx_results_dir} " "--skip-duplicated --skip-dup-mode 0 " "-nt {num_cores} {options}") species = None if (tz.get_in(("genome_resources", "aliases", "human"), data, "") or dd.get_genome_build(data).startswith(("hg", "GRCh"))): species = "HUMAN" elif dd.get_genome_build(data).startswith(("mm", "GRCm")): species = "MOUSE" if species in ["HUMAN", "MOUSE"]: cmd += " -gd {species}" regions = (dd.get_coverage(data) if dd.get_coverage(data) not in [None, False, "None"] else dd.get_variant_regions_merged(data)) if regions: regions = bedutils.merge_overlaps(bedutils.clean_file(regions, data), data) bed6_regions = _bed_to_bed6(regions, out_dir) cmd += " -gff {bed6_regions}" bcbio_env = utils.get_bcbio_env() do.run(cmd.format(**locals()), "Qualimap: %s" % dd.get_sample_name(data), env=bcbio_env) tx_results_file = os.path.join(tx_results_dir, "genome_results.txt") cmd = "sed -i 's/bam file = .*/bam file = %s.bam/' %s" % (dd.get_sample_name(data), tx_results_file) do.run(cmd, "Fix Name Qualimap for {}".format(dd.get_sample_name(data))) # Qualimap output folder (results_dir) needs to be named after the sample (see comments above). However, in order # to keep its name after upload, we need to put the base QC file (results_file) into the root directory (out_dir): base_results_file = os.path.join(out_dir, os.path.basename(results_file)) shutil.copyfile(results_file, base_results_file) return {"base": base_results_file, "secondary": _find_qualimap_secondary_files(results_dir, base_results_file)} def _parse_qualimap_metrics(report_file, data): """Extract useful metrics from the qualimap HTML report file. """ if not utils.file_exists(report_file): return {} from bs4 import BeautifulSoup out = {} parsers = {"Globals": _parse_qualimap_globals, "Globals (inside of regions)": _parse_qualimap_globals_inregion, "Coverage": _parse_qualimap_coverage, "Coverage (inside of regions)": _parse_qualimap_coverage, "Insert size": _parse_qualimap_insertsize, "Insert size (inside of regions)": _parse_qualimap_insertsize} with open(report_file) as in_handle: root = BeautifulSoup(in_handle.read(), "html.parser") for table in root.find_all("div", class_="table-summary"): h3 = table.find("h3") if h3.text in parsers: out.update(parsers[h3.text](table.find("table"))) new_names = [] for metric in out: if "qualimap_full" not in tz.get_in(("config", "algorithm", "tools_on"), data, []): metric += "_qualimap_1e7reads_est" new_names.append(metric) out = dict(zip(new_names, out.values())) return out def _parse_num_pct(k, v): num, pct = v.split(" / ") return {k: num.replace(",", "").strip(), "%s pct" % k: pct.strip()} def _parse_qualimap_globals(table): """Retrieve metrics of interest from globals table. """ out = {} want = {"Mapped reads": _parse_num_pct, "Duplication rate": lambda k, v: {k: v}} for row in table.find_all("tr"): col, val = [x.text for x in row.find_all("td")] if col in want: out.update(want[col](col, val)) return out def _parse_qualimap_globals_inregion(table): """Retrieve metrics from the global targeted region table. """ out = {} for row in table.find_all("tr"): col, val = [x.text for x in row.find_all("td")] if col == "Mapped reads": out.update(_parse_num_pct("%s (in regions)" % col, val)) return out def _parse_qualimap_coverage(table): """Parse summary qualimap coverage metrics. """ out = {} for row in table.find_all("tr"): col, val = [x.text for x in row.find_all("td")] if col == "Mean": out["Coverage (Mean)"] = val return out def _parse_qualimap_insertsize(table): """Parse insert size metrics. """ out = {} for row in table.find_all("tr"): col, val = [x.text for x in row.find_all("td")] if col == "Median": out["Insert size (Median)"] = val return out def _bed_to_bed6(orig_file, out_dir): """Convert bed to required bed6 inputs. """ bed6_file = os.path.join(out_dir, "%s-bed6%s" % os.path.splitext(os.path.basename(orig_file))) if not utils.file_exists(bed6_file): with open(bed6_file, "w") as out_handle: for i, region in enumerate(list(x) for x in pybedtools.BedTool(orig_file)): region = [x for x in list(region) if x] fillers = [str(i), "1.0", "+"] full = region + fillers[:6 - len(region)] out_handle.write("\t".join(full) + "\n") return bed6_file # ## RNAseq Qualimap def _parse_metrics(metrics): # skipped metrics can sometimes be in unicode, replace unicode with NA if it exists # This is removing correct values # metrics = dtz.valmap(lambda x: 'nan' if isinstance(x, unicode) else x, metrics) # missing = set(["Genes Detected", "Transcripts Detected", "Mean Per Base Cov."]) correct = set(["rRNA", "rRNA_rate"]) percentages = set(["Intergenic pct", "Intronic pct", "Exonic pct"]) to_change = dict({"5'-3' bias": 1, "Intergenic pct": "Intergenic Rate", "Intronic pct": "Intronic Rate", "Exonic pct": "Exonic Rate", "Duplication Rate of Mapped": 1, "Average_insert_size": 1, }) total = ["Not aligned", "Aligned to genes", "No feature assigned"] out = {} def _safe_int(x): """Handle non integer values like nan """ try: return int(x) except ValueError: return 0 total_reads = sum([_safe_int(metrics[name]) for name in total]) out.update({key: val for key, val in metrics.items() if key in correct}) [metrics.update({name: 1.0 * float(metrics[name]) / 100}) for name in percentages] for name in to_change: if not to_change[name] or metrics[name] is None: continue try: if to_change[name] == 1: out.update({name: float(metrics[name])}) else: out.update({to_change[name]: float(metrics[name])}) # if we can't convert metrics[name] to float (?'s or other non-floats) except ValueError: continue return out def _detect_duplicates(bam_file, out_dir, data): """ count duplicate percentage """ out_file = os.path.join(out_dir, "dup_metrics.txt") if not utils.file_exists(out_file): dup_align_bam = postalign.dedup_bam(bam_file, data) logger.info("Detecting duplicates in %s." % dup_align_bam) not_dup_count = readstats.number_of_mapped_reads(data, dup_align_bam, keep_dups=False) tot_count = readstats.number_of_mapped_reads(data, dup_align_bam, keep_dups=True) with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: out_handle.write("%s\n%s\n" % (not_dup_count, tot_count)) with open(out_file) as in_handle: not_dupes = float(next(in_handle).strip()) total = float(next(in_handle).strip()) if total == 0: rate = "NA" else: rate = 1 - not_dupes / total return {"Duplication Rate of Mapped": rate} def _transform_browser_coor(rRNA_interval, rRNA_coor): """ transform interval format to browser coord: chr:start-end """ with open(rRNA_coor, 'w') as out_handle: with open(rRNA_interval, 'r') as in_handle: for line in in_handle: c, bio, source, s, e = line.split("\t")[:5] if bio.startswith("rRNA"): out_handle.write(("{0}:{1}-{2}\n").format(c, s, e)) def _detect_rRNA(data, out_dir): out_file = os.path.join(out_dir, "rRNA_metrics.txt") if not utils.file_exists(out_file): gtf_file = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) quant = tz.get_in(["quant", "tsv"], data) if not quant: salmon_dir = dd.get_salmon_dir(data) if salmon_dir: quant = os.path.join(salmon_dir, "quant.sf") logger.info("Calculating RNA-seq rRNA metrics for %s." % quant) rrna_features = gtf.get_rRNA(gtf_file) transcripts = set([x[1] for x in rrna_features if x]) if not (transcripts and quant and utils.file_exists(quant)): return {'rRNA': "NA", "rRNA_rate": "NA"} sample_table = pd.read_csv(quant, sep="\t") rrna_exp = list(map(float, sample_table[sample_table["Name"].isin(transcripts)]["NumReads"])) total_exp = list(map(float, sample_table["NumReads"])) rrna = sum(rrna_exp) if sum(total_exp) == 0: rrna_rate = "NA" else: rrna_rate = float(rrna) / sum(total_exp) with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: out_handle.write(",".join(["rRNA", str(rrna)]) + "\n") out_handle.write(",".join(["rRNA_rate", str(rrna_rate)]) + "\n") return _read_memoized_rrna(out_file) def _read_memoized_rrna(rrna_file): rrna_dict = {} with open(rrna_file) as in_handle: for line in in_handle: tokens = line.strip().split(",") rrna_dict[tokens[0]] = tokens[1] return rrna_dict def _parse_qualimap_rnaseq(table): """ Retrieve metrics of interest from globals table. """ out = {} for row in table.find_all("tr"): col, val = [x.text for x in row.find_all("td")] col = col.replace(":", "").strip() val = val.replace(",", "") m = {col: val} if val.find("/") > -1: m = _parse_num_pct(col, val.replace("%", "")) out.update(m) return out def _parse_rnaseq_qualimap_metrics(report_file): """Extract useful metrics from the qualimap HTML report file. """ from bs4 import BeautifulSoup out = {} parsers = ["Reads alignment", "Reads genomic origin", "Transcript coverage profile"] with open(report_file) as in_handle: root = BeautifulSoup(in_handle.read(), "html.parser") for table in root.find_all("div", class_="table-summary"): h3 = table.find("h3") if h3.text in parsers: out.update(_parse_qualimap_rnaseq(table.find("table"))) return out def run_rnaseq(bam_file, data, out_dir): """ Run qualimap for a rnaseq bam file and parse results """ strandedness = {"firststrand": "strand-specific-forward", "secondstrand": "strand-specific-reverse", "unstranded": "non-strand-specific", "auto": "non-strand-specific"} # Qualimap results should be saved to a directory named after sample. # MultiQC (for parsing additional data) picks the sample name after the dir as follows: # /raw_data_qualimapReport/insert_size_histogram.txt results_dir = os.path.join(out_dir, dd.get_sample_name(data)) results_file = os.path.join(results_dir, "rnaseq_qc_results.txt") report_file = os.path.join(results_dir, "qualimapReport.html") config = data["config"] gtf_file = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) library = strandedness[dd.get_strandedness(data)] # don't run qualimap on the full bam by default if "qualimap_full" in tz.get_in(("config", "algorithm", "tools_on"), data, []): logger.info(f"Full qualimap analysis for {bam_file} may be slow.") ds_bam = bam_file else: logger.info(f"Downsampling {bam_file} for Qualimap run.") ds_bam = bam.downsample(bam_file, data, 1e7, work_dir=out_dir) bam_file = ds_bam if ds_bam else bam_file if not utils.file_exists(results_file): with file_transaction(data, results_dir) as tx_results_dir: utils.safe_makedir(tx_results_dir) bam.index(bam_file, config) cmd = _rnaseq_qualimap_cmd(data, bam_file, tx_results_dir, gtf_file, library) do.run(cmd, "Qualimap for {}".format(dd.get_sample_name(data))) tx_results_file = os.path.join(tx_results_dir, "rnaseq_qc_results.txt") cmd = "sed -i 's/bam file = .*/bam file = %s.bam/' %s" % (dd.get_sample_name(data), tx_results_file) do.run(cmd, "Fix Name Qualimap for {}".format(dd.get_sample_name(data))) metrics = _parse_rnaseq_qualimap_metrics(report_file) metrics.update(_detect_duplicates(bam_file, results_dir, data)) metrics.update(_detect_rRNA(data, results_dir)) metrics.update({"Average_insert_size": salmon.estimate_fragment_size(data)}) metrics = _parse_metrics(metrics) # Qualimap output folder (results_dir) needs to be named after the sample (see comments above). However, in order # to keep its name after upload, we need to put the base QC file (results_file) into the root directory (out_dir): base_results_file = os.path.join(out_dir, os.path.basename(results_file)) shutil.copyfile(results_file, base_results_file) return {"base": base_results_file, "secondary": _find_qualimap_secondary_files(results_dir, base_results_file), "metrics": metrics} def _rnaseq_qualimap_cmd(data, bam_file, out_dir, gtf_file=None, library="non-strand-specific"): """ Create command lines for qualimap """ config = data["config"] qualimap = config_utils.get_program("qualimap", config) resources = config_utils.get_resources("qualimap", config) num_cores = resources.get("cores", dd.get_num_cores(data)) max_mem = config_utils.adjust_memory(resources.get("memory", "2G"), num_cores) export = "%s%s" % (utils.java_freetype_fix(), utils.local_path_export()) export = "%s%s export JAVA_OPTS='-Xms32m -Xmx%s -Djava.io.tmpdir=%s' && " % ( utils.java_freetype_fix(), utils.local_path_export(), max_mem, out_dir) if library != "non-strand-specific": logger.info("Qualimap can get the orientation wrong for stranded reads, so we run it in unstranded mode. This gives comparable results to unstranded for RNA-seq data (see https://groups.google.com/forum/#!topic/qualimap/ZGo-k8LGmHQ) for a further explanation.") library = "non-strand-specific" paired = " --paired" if bam.is_paired(bam_file) else "" cmd = ("unset DISPLAY && {export} {qualimap} rnaseq -outdir {out_dir} " "-a proportional -bam {bam_file} -p {library}{paired} " "-gtf {gtf_file}").format(**locals()) return cmd def _find_qualimap_secondary_files(results_dir, base_file): """Retrieve additional files, avoiding double uploading the base file. """ def not_dup(x): is_dup = (os.path.basename(x) == os.path.basename(base_file) and os.path.getsize(x) == os.path.getsize(base_file)) return not is_dup return list(filter(not_dup, glob.glob(os.path.join(results_dir, 'qualimapReport.html')) + glob.glob(os.path.join(results_dir, '*.txt')) + glob.glob(os.path.join(results_dir, "css", "*")) + glob.glob(os.path.join(results_dir, "raw_data_qualimapReport", "*")) + glob.glob(os.path.join(results_dir, "images_qualimapReport", "*")))) bcbio-nextgen-1.2.9/bcbio/qc/samtools.py000066400000000000000000000065031415626112400201510ustar00rootroot00000000000000"""Quality control metrics from samtools. """ import os import toolz as tz from bcbio.distributed.transaction import file_transaction from bcbio import utils from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do def run(_, data, out_dir=None): """Run samtools stats with reports on mapped reads, duplicates and insert sizes. """ stats_file, idxstats_file = _get_stats_files(data, out_dir) samtools = config_utils.get_program("samtools", data["config"]) bam_file = dd.get_align_bam(data) or dd.get_work_bam(data) if not utils.file_exists(stats_file): utils.safe_makedir(out_dir) with file_transaction(data, stats_file) as tx_out_file: cores = dd.get_num_cores(data) cmd = "{samtools} stats -@ {cores} {bam_file}" cmd += " > {tx_out_file}" do.run(cmd.format(**locals()), "samtools stats", data) if not utils.file_exists(idxstats_file): utils.safe_makedir(out_dir) with file_transaction(data, idxstats_file) as tx_out_file: cmd = "{samtools} idxstats {bam_file}" cmd += " > {tx_out_file}" do.run(cmd.format(**locals()), "samtools index stats", data) out = {"base": idxstats_file, "secondary": [stats_file]} out["metrics"] = _parse_samtools_stats(stats_file) return out def run_and_save(data): """Run QC, saving file outputs in data dictionary. """ run(None, data) stats_file, idxstats_file = _get_stats_files(data) data = tz.update_in(data, ["depth", "samtools", "stats"], lambda x: stats_file) data = tz.update_in(data, ["depth", "samtools", "idxstats"], lambda x: idxstats_file) return data def _get_stats_files(data, out_dir=None): """Retrieve stats files from pre-existing dictionary or filesystem. """ if not out_dir: out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "qc", dd.get_sample_name(data), "samtools")) stats_file = tz.get_in(["depth", "samtools", "stats"], data) idxstats_file = tz.get_in(["depth", "samtools", "idxstats"], data) if not stats_file: stats_file = os.path.join(out_dir, "%s.txt" % dd.get_sample_name(data)) if not idxstats_file: idxstats_file = os.path.join(out_dir, "%s-idxstats.txt" % dd.get_sample_name(data)) return stats_file, idxstats_file def _parse_samtools_stats(stats_file): out = {} want = {"raw total sequences": "Total_reads", "reads mapped": "Mapped_reads", "reads mapped and paired": "Mapped_paired_reads", "reads duplicated": "Duplicates", "insert size average": "Average_insert_size", "average length": "Average_read_length", } with open(stats_file) as in_handle: for line in in_handle: if not line.startswith("SN"): continue parts = line.split("\t") metric, stat_str = parts[1:3] metric = metric.replace(":", "").strip() if metric in want: stat = float(stat_str.strip()) out[want[metric]] = stat # Ensure we have zero values for any metrics not present in stats output for metric in want.values(): if metric not in out: out[metric] = 0 return out bcbio-nextgen-1.2.9/bcbio/qc/srna.py000066400000000000000000000064131415626112400172530ustar00rootroot00000000000000""" Create log files to be parsed by multiqc """ from __future__ import print_function import os import pandas as pd from bcbio import utils from bcbio.provenance.programs import get_version_manifest from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd def run(bam_file, data, out_dir): """Create several log files""" m = {"base": None, "secondary": []} m.update(_mirbase_stats(data, out_dir)) m["secondary"].append(_seqcluster_stats(data, out_dir)) def _mirbase_stats(data, out_dir): """Create stats from miraligner""" utils.safe_makedir(out_dir) out_file = os.path.join(out_dir, "%s_bcbio_mirbase.txt" % dd.get_sample_name(data)) out_file_novel = os.path.join(out_dir, "%s_bcbio_mirdeeep2.txt" % dd.get_sample_name(data)) mirbase_fn = data.get("seqbuster", None) if mirbase_fn: _get_stats_from_miraligner(mirbase_fn, out_file, "seqbuster") mirdeep_fn = data.get("seqbuster_novel", None) if mirdeep_fn: _get_stats_from_miraligner(mirdeep_fn, out_file_novel, "mirdeep2") return {"base": out_file, "secondary": [out_file_novel]} def _get_stats_from_miraligner(fn, out_file, name): df = pd.read_csv(fn, sep="\t", dtype={"mism": "str", "add": "str", "t5": "str", "t3": "str"}, na_values=["."]) dfmirs = df[['mir', 'freq']].groupby(['mir']).count() df5 = df.loc[df.t5 != "0", ['mir', 't5']].groupby(['mir']).count() df3 = df.loc[df.t3 != "0", ['mir', 't3']].groupby(['mir']).count() dfadd = df.loc[df["add"] != "0", ['mir', 'add']].groupby(['mir']).count() dfmut = df.loc[df.mism != "0", ['mir', 'mism']].groupby(['mir']).count() if not utils.file_exists(out_file): version = get_version_manifest("seqbuster") with file_transaction(out_file) as tx_out: with open(tx_out, "w") as out_handle: print(("# stats {name}, version: {version}").format(**locals()), file=out_handle) print(("mirs\t{mirs}\nisomirs\t{isomirs}").format( mirs=len(dfmirs.index), isomirs=len(df.index)), file=out_handle) print(("mirs_mutations\t{muts}\nmirs_additions\t{add}").format( muts=len(dfmut.index), add=len(dfadd.index)), file=out_handle) print(("mirs_5-trimming\t{t5}\nmirs_3-trimming\t{t3}").format( t5=len(df5.index), t3=len(df3.index)), file=out_handle) print(("iso_mutations\t{muts}\niso_additions\t{add}").format( muts=sum(dfmut.mism), add=sum(dfadd["add"])), file=out_handle) print(("iso_5-trimming\t{t5}\niso_3-trimming\t{t3}").format( t5=sum(df5.t5), t3=sum(df3.t3)), file=out_handle) return out_file def _seqcluster_stats(data, out_dir): """Parse seqcluster output""" name = dd.get_sample_name(data) fn = data.get("seqcluster", {}).get("stat_file", None) if not fn: return None out_file = os.path.join(out_dir, "%s.txt" % name) df = pd.read_csv(fn, sep="\t", names = ["reads", "sample", "type"]) df_sample = df[df["sample"] == name] df_sample.to_csv(out_file, sep="\t") return out_file bcbio-nextgen-1.2.9/bcbio/qc/umi.py000066400000000000000000000061401415626112400170770ustar00rootroot00000000000000"""Calculate quality control metrics for UMI tags and consensus generation. """ import collections import math import os import numpy as np import pysam import yaml from bcbio import bam, utils from bcbio.pipeline import datadict as dd def run(_, data, out_dir): stats_file = os.path.join(utils.safe_makedir(out_dir), "%s_umi_stats.yaml" % dd.get_sample_name(data)) if not utils.file_uptodate(stats_file, dd.get_align_bam(data)): out = {} total = 0 mapped = 0 duplicates = 0 umi_reductions = [] umi_counts = collections.defaultdict(int) with pysam.AlignmentFile(data["umi_bam"], "rb", check_sq=False) as bam_iter: cur_counts = collections.defaultdict(int) cur_key = None for rec in bam_iter: total += 1 umi = _get_umi_tag(rec) if umi and not rec.is_unmapped: mapped += 1 if rec.is_duplicate: duplicates += 1 chrom = bam_iter.getrname(rec.reference_id) pos = rec.reference_start key = (chrom, pos) if key != cur_key: # update counts if cur_counts: for c in cur_counts.values(): umi_counts[c] += 1 total_seqs = sum(cur_counts.values()) umi_count = len(cur_counts) umi_reductions.append(float(total_seqs) / umi_count) # update current keys cur_key = key cur_counts = collections.defaultdict(int) cur_counts[umi] += 1 if cur_counts: for c in cur_counts.values(): umi_counts[c] += 1 total_seqs = sum(cur_counts.values()) umi_count = len(cur_counts) umi_reductions.append(float(total_seqs) / umi_count) consensus_count = sum([x.aligned for x in bam.idxstats(dd.get_align_bam(data), data)]) out["umi_baseline_all"] = total out["umi_baseline_mapped"] = mapped out["umi_baseline_duplicate_pct"] = float(duplicates) / float(mapped) * 100.0 out["umi_consensus_mapped"] = consensus_count out["umi_consensus_pct"] = (100.0 - float(consensus_count) / float(mapped) * 100.0) out["umi_reduction_median"] = int(math.ceil(np.median(umi_reductions))) out["umi_reduction_max"] = int(max(umi_reductions)) out["umi_counts"] = dict(umi_counts) out["umi_raw_avg_cov"] = data["config"]["algorithm"].get("rawumi_avg_cov", 0) with open(stats_file, "w") as out_handle: yaml.safe_dump({dd.get_sample_name(data): out}, out_handle, default_flow_style=False, allow_unicode=False) return stats_file def _get_umi_tag(rec): """Handle UMI and duplex tag retrieval. """ for tag in ["RX", "XC"]: try: return rec.get_tag(tag) except KeyError: pass bcbio-nextgen-1.2.9/bcbio/qc/variant.py000066400000000000000000000141531415626112400177540ustar00rootroot00000000000000"""Variant quality control summaries TODO: - Add plot of depth metrics to replace GATK based depth metrics calculation """ import os import shutil import six import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.variation import genotype, germline def run(_, data, out_dir): """Prepare variants QC analysis: bcftools stats and snpEff output. """ out = [] vcinfo = get_active_vcinfo(data) if vcinfo: if dd.get_phenotype(data) == "normal" and "germline" in vcinfo: out.append(_bcftools_stats(data, out_dir, "germline", germline=True)) elif dd.get_phenotype(data) != "germline": out.append(_bcftools_stats(data, out_dir)) if "germline" in vcinfo: out.append(_bcftools_stats(data, out_dir, "germline", germline=True)) else: out.append(_bcftools_stats(data, out_dir, germline=True)) out.append(_snpeff_stats(data, out_dir)) out = [item for item in out if item] if out: return {"base": out[0], "secondary": out[1:]} def _snpeff_stats(data, out_dir): vcinfo = get_active_vcinfo(data) if vcinfo and vcinfo.get("vrn_stats"): effects_csv = tz.get_in(["vrn_stats", "effects-stats-csv"], vcinfo) if effects_csv and utils.file_exists(effects_csv): out_dir = utils.safe_makedir(out_dir) out_file = os.path.join(out_dir, "%s.txt" % dd.get_sample_name(data)) with file_transaction(data, out_file) as tx_out_file: shutil.copy(effects_csv, tx_out_file) return out_file def _bcftools_stats(data, out_dir, vcf_file_key=None, germline=False): """Run bcftools stats. """ vcinfo = get_active_vcinfo(data) if vcinfo: out_dir = utils.safe_makedir(out_dir) vcf_file = vcinfo[vcf_file_key or "vrn_file"] if dd.get_jointcaller(data) or "gvcf" in dd.get_tools_on(data): opts = "" else: opts = "-f PASS,." name = dd.get_sample_name(data) out_file = os.path.join(out_dir, "%s_bcftools_stats%s.txt" % (name, ("_germline" if germline else ""))) bcftools = config_utils.get_program("bcftools", data["config"]) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: orig_out_file = os.path.join(os.path.dirname(tx_out_file), "orig_%s" % os.path.basename(tx_out_file)) cmd = ("{bcftools} stats -s {name} {opts} {vcf_file} > {orig_out_file}") do.run(cmd.format(**locals()), "bcftools stats %s" % name) with open(orig_out_file) as in_handle: with open(tx_out_file, "w") as out_handle: for line in in_handle: if line.startswith("ID\t"): parts = line.split("\t") parts[-1] = "%s\n" % name line = "\t".join(parts) out_handle.write(line) return out_file def _add_filename_details(full_f): """Add variant callers and germline information standard CWL filenames. This is an ugly way of working around not having metadata with calls. """ out = {"vrn_file": full_f} f = os.path.basename(full_f) for vc in list(genotype.get_variantcallers().keys()) + ["ensemble"]: if f.find("-%s.vcf" % vc) > 0: out["variantcaller"] = vc if f.find("-germline-") >= 0: out["germline"] = full_f return out def _get_variants(data): """Retrieve variants from CWL and standard inputs for organizing variants. """ active_vs = [] if "variants" in data: variants = data["variants"] # CWL based list of variants if isinstance(variants, dict) and "samples" in variants: variants = variants["samples"] for v in variants: # CWL -- a single variant file if isinstance(v, six.string_types) and os.path.exists(v): active_vs.append(_add_filename_details(v)) elif (isinstance(v, (list, tuple)) and len(v) > 0 and isinstance(v[0], six.string_types) and os.path.exists(v[0])): for subv in v: active_vs.append(_add_filename_details(subv)) elif isinstance(v, dict): if v.get("vrn_file"): active_vs.append(v) elif v.get("population"): vrnfile = v.get("population").get("vcf") active_vs.append(_add_filename_details(vrnfile)) elif v.get("vcf"): active_vs.append(_add_filename_details(v.get("vcf"))) return active_vs def get_active_vcinfo(data, use_ensemble=True): """Use first caller if ensemble is not active """ active_vs = _get_variants(data) if len(active_vs) > 0: e_active_vs = [] if use_ensemble: e_active_vs = [v for v in active_vs if v.get("variantcaller") == "ensemble"] if len(e_active_vs) == 0: e_active_vs = [v for v in active_vs if v.get("variantcaller") != "ensemble"] if len(e_active_vs) > 0: return e_active_vs[0] def extract_germline_vcinfo(data, out_dir): """Extract germline VCFs from existing tumor inputs. """ supported_germline = set(["vardict", "octopus", "freebayes"]) if dd.get_phenotype(data) in ["tumor"]: for v in _get_variants(data): if v.get("variantcaller") in supported_germline: if v.get("germline"): return v else: d = utils.deepish_copy(data) d["vrn_file"] = v["vrn_file"] gd = germline.extract(d, [d], out_dir) v["germline"] = gd["vrn_file_plus"]["germline"] return v def extract_population_vcinfo(data): """Extract population level VCFs """ for v in _get_variants(data): if v.get("population"): return v bcbio-nextgen-1.2.9/bcbio/qc/viral.py000066400000000000000000000142121415626112400174210ustar00rootroot00000000000000"""Detect viral infections via bwa alignment of unaligned reads. This is primarily useful for cancer samples where viral infection can inform treatment. """ import glob import os import subprocess import time from bcbio import bam, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.variation import vcfutils from bcbio.heterogeneity import chromhacks from bcbio.log import logger def run(bam_file, data, out_dir): """Run viral QC analysis: 1. Extract the unmapped reads 2. BWA-MEM to the viral sequences from GDC database https://gdc.cancer.gov/about-data/data-harmonization-and-generation/gdc-reference-files 3. Report viruses that are in more than 50% covered by at least 5x """ source_link = 'https://gdc.cancer.gov/about-data/data-harmonization-and-generation/gdc-reference-files' viral_target = "gdc-viral" out = {} viral_refs = [x for x in dd.get_viral_files(data) if os.path.basename(x) == "%s.fa" % viral_target] if viral_refs and utils.file_exists(viral_refs[0]): viral_ref = viral_refs[0] viral_bam = os.path.join(utils.safe_makedir(out_dir), "%s-%s.bam" % (dd.get_sample_name(data), utils.splitext_plus(os.path.basename(viral_ref))[0])) out_file = "%s-completeness.txt" % utils.splitext_plus(viral_bam)[0] cores = dd.get_num_cores(data) samtools = config_utils.get_program("samtools", data["config"]) bamtofastq = config_utils.get_program("bamtofastq", data["config"]) bamsort = config_utils.get_program("bamsort", data["config"]) if not utils.file_uptodate(out_file, bam_file): if not utils.file_uptodate(viral_bam, bam_file): with file_transaction(data, viral_bam) as tx_out_file: tmpfile = "%s-tmp" % utils.splitext_plus(tx_out_file)[0] tmpbam = "%s-tmpbam" % utils.splitext_plus(tx_out_file)[0] # the weirdest bug # in bcbio1.2.9a ipython (only ipython not multicore) runs fail after this step with bgzf error, see issue 3581 # what helps is to samtools view the file to restore the proper EOF cmd = ( f"{samtools} view -u -f 4 {bam_file} | " f"{bamtofastq} collate=0 | " f"bwa mem -t {cores} {viral_ref} - | " f"{bamsort} tmpfile={tmpfile} inputthreads={cores} outputthreads={cores} " f"inputformat=sam index=1 indexfilename={tmpbam}.bai O={tmpbam}.bam &&" f"{samtools} view -bh {tmpbam}.bam > {tx_out_file} && " f"{samtools} index {tx_out_file}" ) do.run(cmd, "Align unmapped reads to viral genome") total_reads = _count_reads(bam_file, data) assert total_reads > 0, 'Reads count is {total_reads}, is there a bug in counting the read count? {bam_file}'.format(**locals()) with file_transaction(data, out_file) as tx_out_file: sample_name = dd.get_sample_name(data) mosdepth_prefix = os.path.splitext(viral_bam)[0] mosdepth = config_utils.get_program("mosdepth", data) cmd = ("{mosdepth} -t {cores} {mosdepth_prefix} {viral_bam} -n --thresholds 1,5,25 --by " "<(awk 'BEGIN {{FS=\"\\t\"}}; {{print $1 FS \"0\" FS $2}}' {viral_ref}.fai) && " "echo '## Viral sequences (from {source_link}) found in unmapped reads' > {tx_out_file} &&" "echo '## Sample: {sample_name}' >> {tx_out_file} && " "echo '#virus\tsize\tdepth\t1x\t5x\t25x\treads\treads_pct' >> {tx_out_file} && " "paste " "<(zcat {mosdepth_prefix}.regions.bed.gz) " "<(zgrep -v ^# {mosdepth_prefix}.thresholds.bed.gz) " "<(samtools idxstats {viral_bam} | grep -v '*') | " "awk 'BEGIN {{FS=\"\\t\"}} {{ print $1 FS $3 FS $4 FS $10/$3 FS $11/$3 FS $12/$3 FS $15 FS $15/{total_reads}}}' | " "sort -n -r -k 5,5 >> {tx_out_file}") do.run(cmd.format(**locals()), "Analyse coverage of viral genomes") if chromhacks.get_EBV(data): ref_file = dd.get_ref_file(data) work_bam = dd.get_work_bam(data) ebv = chromhacks.get_EBV(data) mosdepth_prefix = os.path.splitext(work_bam)[0] + "-EBV" mosdepth = config_utils.get_program("mosdepth", data) cmd = ("{mosdepth} -t {cores} {mosdepth_prefix} {work_bam} -n --thresholds 1,5,25 --by " "<(grep {ebv} {ref_file}.fai | awk 'BEGIN {{FS=\"\\t\"}}; {{print $1 FS \"0\" FS $2}}') && " "paste " "<(zcat {mosdepth_prefix}.regions.bed.gz) " "<(zgrep -v ^# {mosdepth_prefix}.thresholds.bed.gz) " "<(samtools idxstats {work_bam} | grep {ebv}) | " "awk 'BEGIN {{FS=\"\\t\"}} {{ print $1 FS $3 FS $4 FS $10/$3 FS $11/$3 FS $12/$3 FS $15 FS $15/{total_reads}}}' | " "sort -n -r -k 5,5 >> {tx_out_file}") do.run(cmd.format(**locals()), "Analyse coverage of EBV") out["base"] = out_file out["secondary"] = [] return out def get_files(data): """Retrieve pre-installed viral reference files. """ all_files = glob.glob(os.path.normpath(os.path.join(os.path.dirname(dd.get_ref_file(data)), os.pardir, "viral", "*"))) return sorted(all_files) def _count_reads(bam_file, data): samtools = config_utils.get_program("samtools", data) cmd = "%s idxstats %s | awk '{sum += $3 + $4} END {print sum}'" count = subprocess.check_output(cmd % (samtools, bam_file), shell=True) return int(count.strip()) bcbio-nextgen-1.2.9/bcbio/rnaseq/000077500000000000000000000000001415626112400166205ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/rnaseq/__init__.py000066400000000000000000000001011415626112400207210ustar00rootroot00000000000000"""RNA-seq analysis code for assessing transcript abundance. """ bcbio-nextgen-1.2.9/bcbio/rnaseq/annotate_gtf.py000066400000000000000000000064731415626112400216550ustar00rootroot00000000000000import os from bcbio.rnaseq import gtf, cpat from bcbio.bam import fasta from bcbio.utils import file_exists from bcbio.distributed.transaction import file_transaction from bcbio.log import logger def annotate_novel_coding(assembled_gtf, ref_gtf, ref_fasta, data, out_file=None): if not out_file: out_file = os.path.splitext(assembled_gtf)[0] + ".annotated.gtf" if file_exists(out_file): return out_file classification = cpat.classify_with_cpat(assembled_gtf, ref_gtf, ref_fasta, data) if not classification: logger.info("Protein coding classification of %s was skipped because " "CPAT was not found." % assembled_gtf) return assembled_gtf ref_db = gtf.get_gtf_db(ref_gtf) known_transcript = {feature['transcript_id'][0]: feature.source for feature in gtf.complete_features(ref_db)} assembled_db = gtf.get_gtf_db(assembled_gtf) with file_transaction(out_file) as tx_out_file: with open(tx_out_file, 'w') as out_handle: for feature in gtf.complete_features(assembled_db): transcript_id = feature['transcript_id'][0] if transcript_id not in known_transcript: feature.source = classification[transcript_id] else: feature.source = known_transcript[transcript_id] out_handle.write(str(feature) + "\n") return out_file def cleanup_transcripts(assembled_gtf, ref_gtf, ref_fasta, out_file=None): """ Clean up a GTF file of assembled transcripts 1) if a known gene is known to code for a protein, remove any *novel* isoforms of the that do not also code for a protein. 2) if a new gene has been annotated and none of its isoforms are protein coding and it is > 200 bp, mark it as a lincRNA. < 200 bp mark it as ncRNA """ if not out_file: out_file = os.path.splitext(assembled_gtf)[0] + ".cleaned.gtf" if file_exists(out_file): return out_file ref_db = gtf.get_gtf_db(ref_gtf) known_transcript = {feature['transcript_id'][0]: feature.source for feature in gtf.complete_features(ref_db)} ref_gene_to_source = gtf.get_gene_source_set(ref_gtf) assembled_db = gtf.get_gtf_db(assembled_gtf) assembled_fasta = gtf.gtf_to_fasta(assembled_gtf, ref_fasta) lengths = fasta.sequence_length(assembled_fasta) with file_transaction(out_file) as tx_out_file: with open(tx_out_file, 'w') as out_handle: for feature in gtf.complete_features(assembled_db): transcript_id = feature['transcript_id'][0] gene_id = feature['gene_id'][0] if transcript_id in known_transcript: out_handle.write(str(feature) + "\n") continue known_coding = "protein_coding" in ref_gene_to_source.get(gene_id, [None]) if known_coding and feature.source != "protein_coding": continue if feature.source != "protein_coding": if lengths[transcript_id] > 200: feature.source = "lincRNA" else: feature.source = "ncRNA" out_handle.write(str(feature) + "\n") return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/arriba.py000066400000000000000000000052011415626112400204300ustar00rootroot00000000000000import os from bcbio.heterogeneity import chromhacks from bcbio.pipeline import config_utils, shared from bcbio.pipeline import datadict as dd from bcbio.log import logger from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do SUPPORTED_BUILDS = ("hg38", "GRCh37", "hg19", "mm10") def run_arriba(data): build = dd.get_genome_build(data) if build not in SUPPORTED_BUILDS: logger.info(f"{build} not supported for arriba, skipping.") return data arriba_dir = os.path.join(dd.get_work_dir(data), "arriba", dd.get_sample_name(data)) utils.safe_makedir(arriba_dir) bam_file = dd.get_work_bam(data) ref_file = dd.get_ref_file(data) gtf = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) arriba = config_utils.get_program("arriba", data) fusion_file = os.path.join(arriba_dir, "fusions.tsv") discarded_fusion_file = os.path.join(arriba_dir, "fusions.discarded.tsv") blacklist_file = get_arriba_blacklist_file(data) contigs = get_contigs(data) contig_list = ",".join(contigs) if utils.file_exists(fusion_file): data["arriba"] = {"fusions": fusion_file, "discarded": discarded_fusion_file} return(data) with file_transaction(fusion_file) as tx_fusion_file, \ file_transaction(discarded_fusion_file) as tx_discarded_fusion_file: cmd = (f"{arriba} -x {bam_file} -g {gtf} -a {ref_file} -o {tx_fusion_file} " f"-O {tx_discarded_fusion_file} -T -P " f"-i {contig_list} ") if blacklist_file: logger.info(f"arriba blacklist file found, running blacklisting with {blacklist_file}.") cmd += (f"-b {blacklist_file} ") else: logger.info("arriba blacklist file not found, disabling blacklist filtering.") cmd += (f"-f blacklist ") if dd.get_known_fusions(data): cmd += (f"-k {dd.get_known_fusions(data)} ") message = f"Running arriba on {dd.get_sample_name(data)}." do.run(cmd, message) data["arriba"] = {"fusions": fusion_file, "discarded": discarded_fusion_file} return(data) def get_arriba_blacklist_file(data): arriba_dir = os.path.join(os.path.dirname(dd.get_gtf_file(data)), "fusion-blacklist") blacklist = os.path.join(arriba_dir, "arriba-blacklist.tsv.gz") if utils.file_exists(blacklist): return blacklist else: return None def get_contigs(data): contigs = [x.name for x in shared.get_noalt_contigs(data)] keep = [x for x in contigs if chromhacks.is_autosomal(x) or chromhacks.is_sex(x)] return keep bcbio-nextgen-1.2.9/bcbio/rnaseq/bcbiornaseq.py000066400000000000000000000174721415626112400214750ustar00rootroot00000000000000import os import shutil import toolz as tz from string import Template from bcbio.utils import file_exists, Rscript_cmd, safe_makedir, chdir from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.pipeline import datadict as dd from datetime import datetime as dt from pathlib import Path from bcbio.log import logger import six def make_bcbiornaseq_object(data): """ load the initial bcb.rda object using bcbioRNASeq """ if "bcbiornaseq" not in dd.get_tools_on(data): return data upload_dir = tz.get_in(("upload", "dir"), data) report_dir = os.path.join(upload_dir, "bcbioRNASeq") safe_makedir(report_dir) organism = dd.get_bcbiornaseq(data).get("organism", None) groups = dd.get_bcbiornaseq(data).get("interesting_groups", None) loadstring = create_load_string(upload_dir, groups, organism, "gene") r_file = os.path.join(report_dir, "load_bcbioRNAseq.R") with file_transaction(r_file) as tmp_file: memoize_write_file(loadstring, tmp_file) rcmd = Rscript_cmd(env = "rbcbiornaseq") with chdir(report_dir): do.run([rcmd, "--vanilla", r_file], "Loading bcbioRNASeq object.") # bcbiornaseq 0.3.44 writes to data/bcb.rds write_counts(os.path.join(report_dir, "data", "bcb.rds"), "gene") loadstring = create_load_string(upload_dir, groups, organism, "transcript") r_file = os.path.join(report_dir, "load_transcript_bcbioRNAseq.R") with file_transaction(r_file) as tmp_file: memoize_write_file(loadstring, tmp_file) rcmd = Rscript_cmd(env = "rbcbiornaseq") with chdir(report_dir): do.run([rcmd, "--vanilla", r_file], "Loading transcript-level bcbioRNASeq object.") write_counts(os.path.join(report_dir, "data-transcript", "bcb.rds"), "transcript") try: make_quality_report(data) except: logger.error("bcbiornaseq error at quality report") finally: return data def make_quality_report(data): """ create and render the bcbioRNASeq quality report """ MAX_SAMPLES = 100 if "bcbiornaseq" not in dd.get_tools_on(data): return data upload_dir = tz.get_in(("upload", "dir"), data) report_dir = os.path.join(upload_dir, "bcbioRNASeq") nsamples = len(list(Path(upload_dir).rglob('quant.sf'))) groups = dd.get_bcbiornaseq(data).get("interesting_groups", None) safe_makedir(report_dir) quality_rmd = os.path.join(report_dir, "quality_control.Rmd") quality_html = os.path.join(report_dir, "quality_control.html") quality_rmd = rmarkdown_draft(quality_rmd, "01-quality-control", "bcbioRNASeq") if nsamples > MAX_SAMPLES and not groups: logger.warn(f"{nsamples} detected, disabling a few bcbioRNASeq plots which break " f"with many samples. Setting `interesting_groups` would allow these plots " f"to be created.") quality_rmd = many_samples_workaround(quality_rmd) if not file_exists(quality_html): render_rmarkdown_file(quality_rmd) return data def many_samples_workaround(quality_rmd): """ bcbioRNASeq has a few plots that are broken if many samples are included, this disables those plots as a workaround """ disable_pca_cmd = "sed -i '/plotPCA(/ { N;N;N;N; s/^/#/gm }' " + f"{quality_rmd}" disable_saturation_cmd = f"sed -i s/plotGeneSaturation/#plotGeneSaturation/ {quality_rmd}" message = f"Disabling PCA plot." do.run(disable_pca_cmd, "Disabling PCA plot.") do.run(disable_saturation_cmd, "Disabling gene saturation plot.") return quality_rmd def rmarkdown_draft(filename, template, package): """ create a draft rmarkdown file from an installed template """ if file_exists(filename): return filename draft_template = Template( 'rmarkdown::draft("$filename", template="$template", package="$package", edit=FALSE)' ) draft_string = draft_template.substitute( filename=filename, template=template, package=package) report_dir = os.path.dirname(filename) rcmd = Rscript_cmd(env = "rbcbiornaseq") with chdir(report_dir): do.run([rcmd, "--vanilla", "-e", draft_string], "Creating bcbioRNASeq quality control template.") do.run(["sed", "-i", "s/YYYY-MM-DD\///g", filename], "Editing bcbioRNAseq quality control template.") return filename def render_rmarkdown_file(filename): """ render a rmarkdown file using the rmarkdown library """ render_template = Template( 'rmarkdown::render("$filename")' ) render_string = render_template.substitute( filename=filename) report_dir = os.path.dirname(filename) rcmd = Rscript_cmd(env = "rbcbiornaseq") with chdir(report_dir): do.run([rcmd, "--vanilla", "-e", render_string], "Rendering bcbioRNASeq quality control report.") return filename def create_load_string(upload_dir, groups=None, organism=None, level="gene"): """ create the code necessary to load the bcbioRNAseq object """ libraryline = 'library(bcbioRNASeq)' load_template = Template( ('bcb <- bcbioRNASeq(uploadDir="$upload_dir",' 'interestingGroups=$groups,' 'level="$level",' 'organism="$organism")')) load_noorganism_template = Template( ('bcb <- bcbioRNASeq(uploadDir="$upload_dir",' 'interestingGroups=$groups,' 'level="$level",' 'organism=NULL)')) flatline = 'flat <- coerceToList(bcb)' if level == "gene": out_dir = '"data"' else: out_dir = '"data-transcript"' saveline = f'saveData(bcb, flat, dir={out_dir})' if groups: groups = _list2Rlist(groups) else: groups = _quotestring("sampleName") if organism: load_bcbio = load_template.substitute( upload_dir=upload_dir, groups=groups, organism=organism, level=level) else: load_bcbio = load_noorganism_template.substitute(upload_dir=upload_dir, groups=groups, level=level) return ";\n".join([libraryline, load_bcbio, flatline, saveline]) def write_counts(bcb, level="gene"): """ pull counts and metadata out of the bcbioRNASeq object """ date = dt.strftime(dt.now(), "%Y-%m-%d") out_dir = os.path.join(os.path.dirname(bcb), "..", "results", date, level, "counts") out_dir_string = _quotestring(out_dir) out_file = os.path.join(out_dir, "counts.csv.gz") safe_makedir(out_dir) if file_exists(out_file): return out_file bcb_string = _quotestring(bcb) rcmd = Rscript_cmd(env = "rbcbiornaseq") render_string = ( f'bcb<-readRDS({bcb_string});' f'date=format(Sys.time(), "%Y-%m-%d");' f'dir={out_dir_string};' f'library(tidyverse);' f'library(bcbioRNASeq);' f'counts = bcbioRNASeq::counts(bcb) |> as.data.frame() |> round() |> tibble::rownames_to_column("gene");' f'metadata = colData(bcb) |> as.data.frame() |> tibble::rownames_to_column("sample");' f'readr::write_csv(counts, file.path(dir, "counts.csv.gz"));' f'readr::write_csv(metadata, file.path(dir, "metadata.csv.gz"));') do.run([rcmd, "--vanilla", "-e", render_string], f"Writing counts table to {out_file}.") return out_file def memoize_write_file(string, filename): if file_exists(filename): return filename with file_transaction(filename) as tx_out_file: with open(tx_out_file, "w") as out_handle: out_handle.write(string) return filename def _quotestring(string, double=True): """ escape quote a string """ if double: return "\"" + string + "\"" else: return "\'" + string + "\'" def _list2Rlist(xs): """ convert a python list to an R list """ if isinstance(xs, six.string_types): xs = [xs] rlist = ",".join([_quotestring(x) for x in xs]) return "c(" + rlist + ")" bcbio-nextgen-1.2.9/bcbio/rnaseq/count.py000066400000000000000000000052211415626112400203220ustar00rootroot00000000000000""" count number of reads mapping to features of transcripts """ import os import pandas as pd from collections import defaultdict import gffutils from bcbio.log import logger from bcbio.utils import file_exists def combine_count_files(files, out_file=None, ext=".counts"): """ combine a set of count files into a single combined file ext: remove this extension from the count files """ files = list(files) files = [x for x in files if file_exists(x)] if not files: return None col_names = [os.path.basename(x.replace(ext, "")) for x in files] if not out_file: out_dir = os.path.join(os.path.dirname(files[0])) out_file = os.path.join(out_dir, "combined.counts") if file_exists(out_file): return out_file logger.info("Combining count files into %s." % out_file) row_names = [] col_vals = defaultdict(list) for i, f in enumerate(files): vals = [] if i == 0: with open(f) as in_handle: for line in in_handle: if not line.strip().startswith("#"): rname, val = line.strip().split("\t") row_names.append(rname) vals.append(val) else: with open(f) as in_handle: for line in in_handle: if not line.strip().startswith("#"): try: _, val = line.strip().split("\t") except ValueError: print(f, line) raise vals.append(val) col_vals[col_names[i]] = vals df = pd.DataFrame(col_vals, index=row_names) df.to_csv(out_file, sep="\t", index_label="id") return out_file def annotate_combined_count_file(count_file, gtf_file, out_file=None): if not count_file: return None dbfn = gtf_file + ".db" if not file_exists(dbfn): return None if not gffutils: return None db = gffutils.FeatureDB(dbfn, keep_order=True) if not out_file: out_dir = os.path.dirname(count_file) out_file = os.path.join(out_dir, "annotated_combined.counts") # if the genes don't have a gene_id or gene_name set, bail out try: symbol_lookup = {f['gene_id'][0]: f['gene_name'][0] for f in db.features_of_type('exon')} except KeyError: return None df = pd.io.parsers.read_csv(count_file, sep="\t", index_col=0, header=0) df['symbol'] = df.apply(lambda x: symbol_lookup.get(x.name, ""), axis=1) df.to_csv(out_file, sep="\t", index_label="id") return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/cpat.py000066400000000000000000000142301415626112400201210ustar00rootroot00000000000000""" run the Coding Potential Assessment Tool (CPAT) http://nar.oxfordjournals.org/content/early/2013/01/17/nar.gkt006.full """ import numpy import shutil import tempfile import os from bcbio import utils from bcbio.rnaseq import gtf from bcbio.utils import file_exists, safe_makedir from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.bam import fasta from bcbio.pipeline import config_utils def classify_with_cpat(assembled_gtf, ref_gtf, ref_fasta, data): cpat_cmd = config_utils.get_program("cpat.py", data) if not cpat_cmd: return {} if not gtf.is_cpat_compatible(ref_gtf): return {} cutoff, hexamer, logit = get_coding_potential_cutoff(ref_gtf, ref_fasta, data) assembled_fasta = gtf.gtf_to_fasta(assembled_gtf, ref_fasta) cpat_fn = cpat(assembled_fasta, hexamer, logit, data) coding_probabilities = load_cpat_coding_prob(cpat_fn) lengths = fasta.sequence_length(assembled_fasta) classification = {} for transcript, prob in coding_probabilities.items(): if prob > cutoff: classification[transcript] = "protein_coding" if lengths[transcript] > 200: classification[transcript] = "lncRNA" else: classification[transcript] = "ncRNA" return classification def cpat(assembled_fasta, hexamer, logit, data, out_file=None): if out_file and file_exists(out_file): return out_file if not out_file: out_file = tempfile.NamedTemporaryFile(delete=False, suffix=".cpat").name cpat_cmd = config_utils.get_program("cpat.py", data) r_setup = utils.get_R_exports() cmd = ("{r_setup} && {cpat_cmd} --gene={assembled_fasta} --hex={hexamer} " "--logitModel={logit} --outfile={tx_out_file}") message = "Predicing coding potential of %s." % (assembled_fasta) with file_transaction(out_file) as tx_out_file: do.run(cmd.format(**locals()), message) return out_file def load_cpat_coding_prob(cpat_file): with open(cpat_file) as in_handle: header = next(in_handle) return {line.split()[0]: float(line.split()[5]) for line in in_handle} def load_cpat_orf_size(cpat_file): with open(cpat_file) as in_handle: header = next(in_handle) return {line.split()[0]: float(line.split()[2]) for line in in_handle} def grade_cpat(coding_transcripts, noncoding_transcripts, cpat, cutoff): coding_tp = 0 coding_fp = 0 noncoding_tp = 0 noncoding_fp = 0 for transcript in coding_transcripts: if cpat[transcript] < cutoff: noncoding_fp += 1 else: coding_tp += 1 for transcript in noncoding_transcripts: if cpat[transcript] >= cutoff: coding_fp += 1 else: noncoding_tp += 1 tp = float(coding_tp) fp = float(coding_fp) tn = float(noncoding_tp) fn = float(noncoding_fp) sensitivity = tp / (tp + fn) specificity = tn / (tn + fp) accuracy = (tp + tn) / (tp + tn + fp + fn) precision = tp / (tp + fp) if (tp + fp > 0) else -1 return {"sensitivity": sensitivity, "specificity": specificity, "accuracy": accuracy, "precision": precision} def make_logit_model(coding_fasta, noncoding_fasta, hexamers, data, out_dir=None): safe_makedir(out_dir) out_prefix = os.path.join(out_dir, "logit") out_file = out_prefix + ".logit.RData" if file_exists(out_file): return out_file tx_prefix = tempfile.NamedTemporaryFile(delete=False).name tx_out_file = tx_prefix + ".logit.RData" logit_cmd = config_utils.get_program("make_logitModel.py", data) r_setup = utils.get_R_exports() cmd = ("{r_setup} && {logit_cmd} --cgene={coding_fasta} --ngene={noncoding_fasta} " "--hex={hexamers} --outfile={tx_prefix}") message = "Building coding/noncoding logistical model." do.run(cmd.format(**locals()), message) shutil.move(tx_out_file, out_file) return out_file def get_coding_potential_cutoff(ref_gtf, ref_fasta, data): """ estimate the coding potential cutoff that best classifies coding/noncoding transcripts by splitting the reference annotation into a test and training set and determining the cutoff where the sensitivity and specificity meet """ train_gtf, test_gtf = gtf.split_gtf(ref_gtf, sample_size=2000) coding_gtf = gtf.partition_gtf(train_gtf, coding=True) noncoding_gtf = gtf.partition_gtf(train_gtf) noncoding_fasta = gtf.gtf_to_fasta(noncoding_gtf, ref_fasta) cds_fasta = gtf.gtf_to_fasta(coding_gtf, ref_fasta, cds=True) hexamer_content = hexamer_table(cds_fasta, noncoding_fasta, data) coding_fasta = gtf.gtf_to_fasta(coding_gtf, ref_fasta) logit_model = make_logit_model(coding_fasta, noncoding_fasta, hexamer_content, data, "test_gtf") test_fasta = gtf.gtf_to_fasta(test_gtf, ref_fasta) cpat_fn = cpat(test_fasta, hexamer_content, logit_model, data) cpat_prob = load_cpat_coding_prob(cpat_fn) coding, noncoding = gtf.get_coding_noncoding_transcript_ids(test_gtf) best_score = 1 best_cutoff = 0 best_sensitivity = 0 best_specificity = 0 for cutoff in list(numpy.arange(0.1, 1, 0.01)): grade = grade_cpat(coding, noncoding, cpat_prob, cutoff) score = abs(grade["sensitivity"] - grade["specificity"]) if score < best_score: best_score = score best_cutoff = cutoff best_sensitivity = grade["sensitivity"] best_specificity = grade["specificity"] return best_cutoff, hexamer_content, logit_model def hexamer_table(cds_fasta, noncoding_fasta, data, out_file=None): if out_file and file_exists(out_file): return out_file if not out_file: out_file = tempfile.NamedTemporaryFile(delete=False, suffix=".hexamers").name hex_cmd = config_utils.get_program("make_hexamer_tab.py", data) cmd = ("{hex_cmd} --cod={cds_fasta} --noncod={noncoding_fasta} " "> {tx_out_file}") with file_transaction(out_file) as tx_out_file: message = ("Calculating hexamer content in %s and %s." % (cds_fasta, noncoding_fasta)) do.run(cmd.format(**locals()), message) return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/cufflinks.py000066400000000000000000000252101415626112400211560ustar00rootroot00000000000000"""Assess transcript abundance in RNA-seq experiments using Cufflinks. http://cufflinks.cbcb.umd.edu/manual.html """ import os import shutil import tempfile import pandas as pd from bcbio import bam from bcbio.utils import get_in, file_exists, safe_makedir from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.rnaseq import gtf, annotate_gtf def run(align_file, ref_file, data): align_file = bam.convert_cufflinks_mapq(align_file) config = data["config"] cmd = _get_general_options(align_file, config) cmd.extend(_get_no_assembly_options(ref_file, data)) out_dir = _get_output_dir(align_file, data) tracking_file = os.path.join(out_dir, "genes.fpkm_tracking") fpkm_file = os.path.join(out_dir, data['rgnames']['sample']) + ".fpkm" tracking_file_isoform = os.path.join(out_dir, "isoforms.fpkm_tracking") fpkm_file_isoform = os.path.join(out_dir, data['rgnames']['sample']) + ".isoform.fpkm" if not file_exists(fpkm_file): with file_transaction(data, out_dir) as tmp_out_dir: safe_makedir(tmp_out_dir) cmd.extend(["--output-dir", tmp_out_dir]) cmd.extend([align_file]) cmd = list(map(str, cmd)) do.run(cmd, "Cufflinks on %s." % (align_file)) fpkm_file = gene_tracking_to_fpkm(tracking_file, fpkm_file) fpkm_file_isoform = gene_tracking_to_fpkm(tracking_file_isoform, fpkm_file_isoform) return out_dir, fpkm_file, fpkm_file_isoform def gene_tracking_to_fpkm(tracking_file, out_file): """ take a gene-level tracking file from Cufflinks and output a two column table with the first column as IDs and the second column as FPKM for the sample. combines FPKM from the same genes into one FPKM value to fix this bug: http://seqanswers.com/forums/showthread.php?t=5224&page=2 """ if file_exists(out_file): return out_file df = pd.io.parsers.read_csv(tracking_file, sep="\t", header=0) df = df[['tracking_id', 'FPKM']] df = df.groupby(['tracking_id']).sum() df.to_csv(out_file, sep="\t", header=False, index_label=False) return out_file def _get_general_options(align_file, config): options = [] cufflinks = config_utils.get_program("cufflinks", config) options.extend([cufflinks]) options.extend(["--num-threads", config["algorithm"].get("num_cores", 1)]) options.extend(["--quiet"]) options.extend(["--no-update-check"]) options.extend(["--max-bundle-frags", 2000000]) options.extend(_get_stranded_flag(config)) return options def _get_no_assembly_options(ref_file, data): options = [] options.extend(["--frag-bias-correct", ref_file]) options.extend(["--multi-read-correct"]) options.extend(["--upper-quartile-norm"]) gtf_file = data["genome_resources"]["rnaseq"].get("transcripts", "") if gtf_file: options.extend(["--GTF", gtf_file]) mask_file = data["genome_resources"]["rnaseq"].get("transcripts_mask", "") if mask_file: options.extend(["--mask-file", mask_file]) return options def _get_stranded_flag(config): strand_flag = {"unstranded": "fr-unstranded", "firststrand": "fr-firststrand", "secondstrand": "fr-secondstrand", "auto": "fr-unstranded"} stranded = get_in(config, ("algorithm", "strandedness"), "unstranded").lower() assert stranded in strand_flag, ("%s is not a valid strandedness value. " "Valid values are 'firststrand', " "'secondstrand' and 'unstranded" % (stranded)) flag = strand_flag[stranded] return ["--library-type", flag] def _get_output_dir(align_file, data, sample_dir=True): config = data["config"] name = data["rgnames"]["sample"] if sample_dir else "" return os.path.join(get_in(data, ("dirs", "work")), "cufflinks", name) def assemble(bam_file, ref_file, num_cores, out_dir, data): out_dir = os.path.join(out_dir, data["rgnames"]["sample"]) safe_makedir(out_dir) out_file = os.path.join(out_dir, "cufflinks-assembly.gtf") cufflinks_out_file = os.path.join(out_dir, "transcripts.gtf") library_type = " ".join(_get_stranded_flag(data["config"])) if file_exists(out_file): return out_file bam_file = bam.convert_cufflinks_mapq(bam_file) with file_transaction(data, out_dir) as tmp_out_dir: cmd = ("cufflinks --output-dir {tmp_out_dir} --num-threads {num_cores} " "--frag-bias-correct {ref_file} " "--quiet " "{library_type} --multi-read-correct --upper-quartile-norm {bam_file}") cmd = cmd.format(**locals()) do.run(cmd, "Assembling transcripts with Cufflinks using %s." % bam_file) shutil.move(cufflinks_out_file, out_file) return out_file def clean_assembly(gtf_file, clean=None, dirty=None): """ clean the likely garbage transcripts from the GTF file including: 1. any novel single-exon transcripts 2. any features with an unknown strand """ base, ext = os.path.splitext(gtf_file) db = gtf.get_gtf_db(gtf_file, in_memory=True) clean = clean if clean else base + ".clean" + ext dirty = dirty if dirty else base + ".dirty" + ext if file_exists(clean): return clean, dirty logger.info("Cleaning features with an unknown strand from the assembly.") with open(clean, "w") as clean_handle, open(dirty, "w") as dirty_handle: for gene in db.features_of_type('gene'): for transcript in db.children(gene, level=1): if is_likely_noise(db, transcript): write_transcript(db, dirty_handle, transcript) else: write_transcript(db, clean_handle, transcript) return clean, dirty def write_transcript(db, handle, transcript): for feature in db.children(transcript): handle.write(str(feature) + "\n") def is_likely_noise(db, transcript): if is_novel_single_exon(db, transcript): return True if strand_unknown(db, transcript): return True def strand_unknown(db, transcript): """ for unstranded data with novel transcripts single exon genes will have no strand information. single exon novel genes are also a source of noise in the Cufflinks assembly so this removes them """ features = list(db.children(transcript)) strand = features[0].strand if strand == ".": return True else: return False def is_novel_single_exon(db, transcript): features = list(db.children(transcript)) exons = [x for x in features if x.featuretype == "exon"] class_code = features[0].attributes.get("class_code", None)[0] if len(exons) == 1 and class_code == "u": return True return False def fix_cufflinks_attributes(ref_gtf, merged_gtf, data, out_file=None): """ replace the cufflinks gene_id and transcript_id with the gene_id and transcript_id from ref_gtf, where available """ base, ext = os.path.splitext(merged_gtf) fixed = out_file if out_file else base + ".clean.fixed" + ext if file_exists(fixed): return fixed ref_db = gtf.get_gtf_db(ref_gtf) merged_db = gtf.get_gtf_db(merged_gtf, in_memory=True) ref_tid_to_gid = {} for gene in ref_db.features_of_type('gene'): for transcript in ref_db.children(gene, level=1): ref_tid_to_gid[transcript.id] = gene.id ctid_to_cgid = {} ctid_to_oid = {} for gene in merged_db.features_of_type('gene'): for transcript in merged_db.children(gene, level=1): ctid_to_cgid[transcript.id] = gene.id feature = list(merged_db.children(transcript))[0] oid = feature.attributes.get("oId", [None])[0] if oid: ctid_to_oid[transcript.id] = oid cgid_to_gid = {} for ctid, oid in ctid_to_oid.items(): cgid = ctid_to_cgid.get(ctid, None) oid = ctid_to_oid.get(ctid, None) gid = ref_tid_to_gid.get(oid, None) if oid else None if cgid and gid: cgid_to_gid[cgid] = gid with file_transaction(data, fixed) as tmp_fixed_file: with open(tmp_fixed_file, "w") as out_handle: for gene in merged_db.features_of_type('gene'): for transcript in merged_db.children(gene, level=1): for feature in merged_db.children(transcript): cgid = feature.attributes.get("gene_id", [None])[0] gid = cgid_to_gid.get(cgid, None) ctid = None if gid: feature.attributes["gene_id"][0] = gid ctid = feature.attributes.get("transcript_id", [None])[0] tid = ctid_to_oid.get(ctid, None) if tid: feature.attributes["transcript_id"][0] = tid if "nearest_ref" in feature.attributes: del feature.attributes["nearest_ref"] if "oId" in feature.attributes: del feature.attributes["oId"] out_handle.write(str(feature) + "\n") return fixed def merge(assembled_gtfs, ref_file, gtf_file, num_cores, data): """ run cuffmerge on a set of assembled GTF files """ assembled_file = tempfile.NamedTemporaryFile(delete=False).name with open(assembled_file, "w") as temp_handle: for assembled in assembled_gtfs: temp_handle.write(assembled + "\n") out_dir = os.path.join("assembly", "cuffmerge") merged_file = os.path.join(out_dir, "merged.gtf") out_file = os.path.join(out_dir, "assembled.gtf") if file_exists(out_file): return out_file if not file_exists(merged_file): with file_transaction(data, out_dir) as tmp_out_dir: cmd = ("cuffmerge -o {tmp_out_dir} --ref-gtf {gtf_file} " "--num-threads {num_cores} --ref-sequence {ref_file} " "{assembled_file}") cmd = cmd.format(**locals()) message = ("Merging the following transcript assemblies with " "Cuffmerge: %s" % ", ".join(assembled_gtfs)) do.run(cmd, message) clean, _ = clean_assembly(merged_file) fixed = fix_cufflinks_attributes(gtf_file, clean, data) classified = annotate_gtf.annotate_novel_coding(fixed, gtf_file, ref_file, data) filtered = annotate_gtf.cleanup_transcripts(classified, gtf_file, ref_file) shutil.move(filtered, out_file) return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/dexseq.py000066400000000000000000000102521415626112400204630ustar00rootroot00000000000000""" perform exon-level counting using DEXSeq """ import sys import os from bcbio.utils import R_sitelib, file_exists, safe_makedir, which from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio import bam from bcbio.log import logger import bcbio.pipeline.datadict as dd def bcbio_run(data): out_dir = os.path.join(dd.get_work_dir(data), "dexseq") safe_makedir(out_dir) sample_name = dd.get_sample_name(data) out_file = os.path.join(out_dir, sample_name + ".dexseq") bam_file = dd.get_work_bam(data) dexseq_gff = dd.get_dexseq_gff(data) stranded = dd.get_strandedness(data) counts = run_count(bam_file, dexseq_gff, stranded, out_file, data) data = dd.set_dexseq_counts(data, counts) return data def run_count(bam_file, dexseq_gff, stranded, out_file, data): """ run dexseq_count on a BAM file """ assert file_exists(bam_file), "%s does not exist." % bam_file sort_order = bam._get_sort_order(bam_file, {}) assert sort_order, "Cannot determine sort order of %s." % bam_file strand_flag = _strand_flag(stranded) assert strand_flag, "%s is not a valid strandedness value." % stranded if not dexseq_gff: logger.info("No DEXSeq GFF file was found, skipping exon-level counting.") return None elif not file_exists(dexseq_gff): logger.info("%s was not found, so exon-level counting is being " "skipped." % dexseq_gff) return None dexseq_count = _dexseq_count_path() if not dexseq_count: logger.info("DEXseq is not installed, skipping exon-level counting.") return None if dd.get_aligner(data) == "bwa": logger.info("Can't use DEXSeq with bwa alignments, skipping exon-level counting.") return None sort_flag = "name" if sort_order == "queryname" else "pos" is_paired = bam.is_paired(bam_file) paired_flag = "yes" if is_paired else "no" if file_exists(out_file): return out_file cmd = ("python {dexseq_count} -f bam -r {sort_flag} -p {paired_flag} " "-s {strand_flag} {dexseq_gff} {bam_file} {tx_out_file}") message = "Counting exon-level counts with %s and %s." % (bam_file, dexseq_gff) with file_transaction(data, out_file) as tx_out_file: do.run(cmd.format(**locals()), message) return out_file def _strand_flag(stranded): strand_flag = {"unstranded": "no", "firststrand": "reverse", "secondstrand": "yes", "auto": "no"} return strand_flag.get(stranded, None) def _dexseq_count_path(): package_path = R_sitelib() if not package_path: return None return os.path.join(package_path, "DEXSeq", "python_scripts", "dexseq_count.py") def _dexseq_gtf_path(genome_dir): return os.path.join(genome_dir, "rnaseq", "ref-transcripts.dexseq.gff") def create_dexseq_annotation(gff, count_file): """ Create an easy data frame to allow easy annotation during differential expression analysis i.e gene:exon_id chr start end strand """ out_file = count_file + ".ann" if file_exists(out_file): return out_file with file_transaction(out_file) as tx_out: with open(tx_out, 'w') as out_handle: with open(gff) as in_handle: for line in in_handle: cols = line.strip().split("\t") if cols[2] == "exonic_part": exon = [f for f in cols[8].split(";") if f.strip().startswith("exonic_part_number")] gene = [f for f in cols[8].split(";") if f.strip().startswith("gene_id")] exon = exon[0].replace("\"", "").split()[1] gene = gene[0].replace("\"", "").split()[1] length = int(cols[4]) - int(cols[3]) + 1 line = "%s:%s\t%s\t%s\t%s\t%s\t%s\t%s\n" % (gene, exon, gene, cols[0], cols[3], cols[4], length, cols[6]) out_handle.write(line) bcbio-nextgen-1.2.9/bcbio/rnaseq/ericscript.py000066400000000000000000000150001415626112400213350ustar00rootroot00000000000000"""Runs gene fusion caller with EricScript. Install EricScript via `bcbio upgrade --toolplus ericscript`, or manually add the path to conda environment where it can be found to the system config. Reference data can be installed via `bcbio upgrade --datatarget ericscript`. Alternatively, you can add path to the database into the system config. EricScript requires bwa index to be built for its reference data. To run gene fusion detection on disambiguated reads, we convert the .bam file which was output by disambiguate to fastq files. """ import glob import os from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.pipeline.fastq import convert_bam_to_fastq from bcbio.provenance import do from bcbio.pipeline import config_utils def run(config): input_files = prepare_input_data(config) run_ericscript(config, input_files) return config def prepare_input_data(config): """ In case of disambiguation, we want to run fusion calling on the disambiguated reads, which are in the work_bam file. As EricScript accepts 2 fastq files as input, we need to convert the .bam to 2 .fq files. """ if not dd.get_disambiguate(config): return dd.get_input_sequence_files(config) work_bam = dd.get_work_bam(config) logger.info("Converting disambiguated reads to fastq...") fq_files = convert_bam_to_fastq( work_bam, dd.get_work_dir(config), None, None, config ) return fq_files def run_ericscript(data, input_files): es_config = EricScriptConfig(data) if not es_config.has_ericscript_db(): logger.info("Skipping ericscript because ericscript database not found.") return None db_location = es_config._db_location work_dir = dd.get_work_dir(data) sample_name = dd.get_sample_name(data) out_dir = os.path.join(work_dir, "ericscript", sample_name) ericscript = config_utils.get_program("ericscript.pl", data) ericscript_path = os.path.dirname(os.path.realpath(ericscript)) samtools_path = os.path.join(ericscript_path, "..", "..", "bin") pathprepend = "export PATH=%s:\"$PATH\"; " % samtools_path files = " ".join(input_files) num_cores = dd.get_num_cores(data) cmd = ("{pathprepend} {ericscript} -db {db_location} -name {sample_name} -o {tx_out_dir} " "--nthreads {num_cores} {files}") message = "Running ericscript on %s using %s." %(files, db_location) with file_transaction(out_dir) as tx_out_dir: do.run(cmd.format(**locals()), message) class EricScriptConfig(object): """This class which encapsulates access to the dat related to EricScript in the sample config dictionary. Public constants: info_message: text message passed as an argument to do.run EXECUTABLE: name of the EricScipt command Private constants: _OUTPUT_DIR_NAME: name of the dir created in working directory for ericscript output """ info_message = 'Detect gene fusions with EricScript' EXECUTABLE = 'ericscript.pl' _OUTPUT_DIR_NAME = 'ericscript' _REF_INDEX = 'allseq.fa.bwt' _REF_FASTA = 'allseq.fa' def __init__(self, data): self._db_location = self._get_ericscript_db(data) self._sample_name = dd.get_lane(data) self._work_dir = dd.get_work_dir(data) self._env = None self._output_dir = None self._sample_out_dir = None def _get_ericscript_db(self, data): transcript_file = dd.get_gtf_file(data) if transcript_file and os.path.exists(transcript_file): transcript_dir = os.path.dirname(transcript_file) ericscript_dirs = glob.glob(os.path.join(transcript_dir, "ericscript", "ericscript_db*")) if ericscript_dirs: return sorted(ericscript_dirs)[-1] def has_ericscript_db(self): return self._db_location is not None def get_run_command(self, tx_output_dir, input_files): """Constructs a command to run EricScript via do.run function. :param tx_output_dir: A location where all EricScript output will be written during execution. :param input_files: an iterable with paths to 2 fastq files with input data. :return: list """ logger.debug("Input data: %s" % ', '.join(input_files)) cmd = [ self.EXECUTABLE, '-db', self._db_location, '-name', self._sample_name, '-o', tx_output_dir, ] + list(input_files) return "export PATH=%s:%s:\"$PATH\"; %s;" % (self._get_samtools0_path(), self._get_ericscript_path(), " ".join(cmd)) def _get_ericscript_path(self): """Retrieve PATH to the isolated eriscript anaconda environment. """ es = utils.which(os.path.join(utils.get_bcbio_bin(), self.EXECUTABLE)) return os.path.dirname(os.path.realpath(es)) def _get_samtools0_path(self): """Retrieve PATH to the samtools version specific for eriscript. """ samtools_path = os.path.realpath(os.path.join(self._get_ericscript_path(),"..", "..", "bin")) return samtools_path @property def output_dir(self): """Absolute path to permanent location in working directory where EricScript output will be stored. """ if self._output_dir is None: self._output_dir = self._get_output_dir() return self._output_dir @property def sample_out_dir(self): """Absolute path to permanent location in working directory where EricScript output for the current sample will be stored. (a subdirectory of `output_dir`) """ if self._sample_out_dir is None: self._sample_out_dir = os.path.join( self.output_dir, self._sample_name ) return self._sample_out_dir @property def reference_index(self): """Absolute path to the BWA index for EricScript reference data.""" if self._db_location: ref_indices = glob.glob(os.path.join(self._db_location, "*", self._REF_INDEX)) if ref_indices: return ref_indices[0] @property def reference_fasta(self): """Absolute path to the fasta file with EricScript reference data.""" if self._db_location: ref_files = glob.glob(os.path.join(self._db_location, "*", self._REF_FASTA)) if ref_files: return ref_files[0] def _get_output_dir(self): return os.path.join(self._work_dir, self._OUTPUT_DIR_NAME) bcbio-nextgen-1.2.9/bcbio/rnaseq/express.py000066400000000000000000000101351415626112400206630ustar00rootroot00000000000000import os import shutil import tempfile from bcbio.utils import file_exists from bcbio.bam import is_paired, _get_sort_order, sort from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.pipeline import config_utils from bcbio.rnaseq import gtf from bcbio.log import logger def run(data): """Quantitaive isoforms expression by eXpress""" name = dd.get_sample_name(data) in_bam = dd.get_transcriptome_bam(data) config = data['config'] if not in_bam: logger.info("Transcriptome-mapped BAM file not found, skipping eXpress.") return data out_dir = os.path.join(dd.get_work_dir(data), "express", name) out_file = os.path.join(out_dir, name + ".xprs") express = config_utils.get_program("express", data['config']) strand = _set_stranded_flag(in_bam, data) if not file_exists(out_file): gtf_fasta = gtf.gtf_to_fasta(dd.get_gtf_file(data), dd.get_ref_file(data)) with tx_tmpdir(data) as tmp_dir: with file_transaction(data, out_dir) as tx_out_dir: bam_file = _prepare_bam_file(in_bam, tmp_dir, config) cmd = ("{express} --no-update-check -o {tx_out_dir} {strand} {gtf_fasta} {bam_file}") do.run(cmd.format(**locals()), "Run express on %s." % in_bam, {}) shutil.move(os.path.join(out_dir, "results.xprs"), out_file) eff_count_file = _get_column(out_file, out_file.replace(".xprs", "_eff.counts"), 7, data=data) tpm_file = _get_column(out_file, out_file.replace("xprs", "tpm"), 14, data=data) fpkm_file = _get_column(out_file, out_file.replace("xprs", "fpkm"), 10, data=data) data = dd.set_express_counts(data, eff_count_file) data = dd.set_express_tpm(data, tpm_file) data = dd.set_express_fpkm(data, fpkm_file) return data def _get_column(in_file, out_file, column, data=None): """Subset one column from a file """ with file_transaction(data, out_file) as tx_out_file: with open(in_file) as in_handle: with open(tx_out_file, 'w') as out_handle: for line in in_handle: cols = line.strip().split("\t") if line.find("eff_count") > 0: continue number = cols[column] if column == 7: number = int(round(float(number), 0)) out_handle.write("%s\t%s\n" % (cols[1], number)) return out_file def _set_stranded_flag(bam_file, data): strand_flag = {"unstranded": "", "firststrand": "--rf-stranded", "secondstrand": "--fr-stranded", "firststrand-s": "--r-stranded", "secondstrand-s": "--f-stranded"} stranded = dd.get_strandedness(data) assert stranded in strand_flag, ("%s is not a valid strandedness value. " "Valid values are 'firststrand', " "'secondstrand' and 'unstranded" % (stranded)) if stranded != "unstranded" and not is_paired(bam_file): stranded += "-s" flag = strand_flag[stranded] return flag def _prepare_bam_file(bam_file, tmp_dir, config): """ Pipe sort by name cmd in case sort by coordinates """ sort_mode = _get_sort_order(bam_file, config) if sort_mode != "queryname": bam_file = sort(bam_file, config, "queryname") return bam_file def isoform_to_gene_name(gtf_file, out_file, data): """ produce a table of isoform -> gene mappings for loading into EBSeq """ if not out_file: out_file = tempfile.NamedTemporaryFile(delete=False).name if file_exists(out_file): return out_file db = gtf.get_gtf_db(gtf_file) line_format = "{transcript}\t{gene}\n" with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for feature in db.features_of_type('transcript'): transcript = feature['transcript_id'][0] gene = feature['gene_id'][0] out_handle.write(line_format.format(**locals())) return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/featureCounts.py000066400000000000000000000163411415626112400220260ustar00rootroot00000000000000import os import shutil import bcbio.bam as bam import toolz as tz from bcbio.utils import (file_exists, safe_makedir, append_stem) from bcbio.pipeline import config_utils from bcbio.bam import is_paired from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction import bcbio.pipeline.datadict as dd try: import pandas as pd except ImportError: pd = None def count(data): """ count reads mapping to genes using featureCounts http://subread.sourceforge.net """ in_bam = dd.get_work_bam(data) or dd.get_align_bam(data) out_dir = os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data)) if dd.get_aligner(data) == "star": out_dir = os.path.join(out_dir, "%s_%s" % (dd.get_sample_name(data), dd.get_aligner(data))) sorted_bam = bam.sort(in_bam, dd.get_config(data), order="queryname", out_dir=safe_makedir(out_dir)) gtf_file = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) work_dir = dd.get_work_dir(data) out_dir = os.path.join(work_dir, "htseq-count") safe_makedir(out_dir) count_file = os.path.join(out_dir, dd.get_sample_name(data)) + ".counts" summary_file = os.path.join(out_dir, dd.get_sample_name(data)) + ".counts.summary" if file_exists(count_file) and _is_fixed_count_file(count_file): return count_file featureCounts = config_utils.get_program("featureCounts", dd.get_config(data)) paired_flag = _paired_flag(in_bam) strand_flag = _strand_flag(data) filtered_bam = bam.filter_primary(sorted_bam, data) cmd = ("{featureCounts} -a {gtf_file} -o {tx_count_file} -s {strand_flag} " "{paired_flag} {filtered_bam}") resources = config_utils.get_resources("featureCounts", data["config"]) if resources: options = resources.get("options") if options: cmd += " %s" % " ".join([str(x) for x in options]) message = ("Count reads in {tx_count_file} mapping to {gtf_file} using " "featureCounts") with file_transaction(data, [count_file, summary_file]) as tx_files: tx_count_file, tx_summary_file = tx_files do.run(cmd.format(**locals()), message.format(**locals())) fixed_count_file = _format_count_file(count_file, data) fixed_summary_file = _change_sample_name( summary_file, dd.get_sample_name(data), data=data) shutil.move(fixed_count_file, count_file) shutil.move(fixed_summary_file, summary_file) return count_file def chipseq_count(data): """ count reads mapping to ChIP/ATAC consensus peaks with featureCounts """ method = dd.get_chip_method(data) if method == "chip": in_bam = dd.get_work_bam(data) elif method == "atac": if bam.is_paired(dd.get_work_bam(data)): in_bam = tz.get_in(("atac", "align", "NF"), data) else: in_bam = tz.get_in(("atac", "align", "full"), data) out_dir = os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data)) sorted_bam = bam.sort(in_bam, dd.get_config(data), order="queryname", out_dir=safe_makedir(out_dir)) consensus_file = tz.get_in(("peaks_files", "consensus", "main"), data) if not consensus_file: return [[data]] saf_file = os.path.splitext(consensus_file)[0] + ".saf" work_dir = dd.get_work_dir(data) out_dir = os.path.join(work_dir, "consensus") safe_makedir(out_dir) count_file = os.path.join(out_dir, dd.get_sample_name(data)) + ".counts" summary_file = os.path.join(out_dir, dd.get_sample_name(data)) + ".counts.summary" if file_exists(count_file) and _is_fixed_count_file(count_file): if method == "atac": if bam.is_paired(dd.get_work_bam(data)): data = tz.assoc_in(data, ("peak_counts", "NF"), count_file) else: data = tz.assoc_in(data, ("peak_counts", "full"), count_file) elif method == "chip": data = tz.assoc_in(data, ("peak_counts"), count_file) return [[data]] featureCounts = config_utils.get_program("featureCounts", dd.get_config(data)) paired_flag = _paired_flag(in_bam) strand_flag = _strand_flag(data) cmd = ("{featureCounts} -F SAF -a {saf_file} -o {tx_count_file} -s {strand_flag} " "{paired_flag} {sorted_bam}") message = ("Count reads in {sorted_bam} overlapping {saf_file} using " "featureCounts.") with file_transaction(data, [count_file, summary_file]) as tx_files: tx_count_file, tx_summary_file = tx_files do.run(cmd.format(**locals()), message.format(**locals())) fixed_count_file = _format_count_file(count_file, data) fixed_summary_file = _change_sample_name( summary_file, dd.get_sample_name(data), data=data) shutil.move(fixed_count_file, count_file) shutil.move(fixed_summary_file, summary_file) if method == "atac": if bam.is_paired(dd.get_work_bam(data)): data = tz.assoc_in(data, ("peak_counts", "NF"), count_file) else: data = tz.assoc_in(data, ("peak_counts", "full"), count_file) elif method == "chip": data = tz.assoc_in(data, ("peak_counts"), count_file) return [[data]] def _change_sample_name(in_file, sample_name, data=None): """Fix name in feature counts log file to get the same name in multiqc report. """ out_file = append_stem(in_file, "_fixed") with file_transaction(data, out_file) as tx_out: with open(tx_out, "w") as out_handle: with open(in_file) as in_handle: for line in in_handle: if line.startswith("Status"): line = "Status\t%s.bam" % sample_name out_handle.write("%s\n" % line.strip()) return out_file def _is_fixed_count_file(count_file): if os.path.exists(count_file): with open(count_file) as in_handle: line = in_handle.readline().split("\t") return len(line) == 2 def _format_count_file(count_file, data): """ this cuts the count file produced from featureCounts down to a two column file of gene ids and number of reads mapping to each gene """ COUNT_COLUMN = 5 out_file = os.path.splitext(count_file)[0] + ".fixed.counts" if file_exists(out_file) and _is_fixed_count_file(out_file): return out_file df = pd.io.parsers.read_csv(count_file, sep="\t", index_col=0, header=1) df_sub = df.iloc[:, COUNT_COLUMN] with file_transaction(data, out_file) as tx_out_file: df_sub.to_csv(tx_out_file, sep="\t", index_label="id", header=False) return out_file def _strand_flag(data): """ 0: unstranded 1: stranded 2: reverse stranded """ strand_flag = {"unstranded": "0", "firststrand": "2", "secondstrand": "1", "auto": "0"} stranded = dd.get_strandedness(data) assert stranded in strand_flag, ("%s is not a valid strandedness value. " "Valid values are 'firststrand', 'secondstrand', " "and 'unstranded") return strand_flag[stranded] def _paired_flag(bam_file): """ sets flags to handle paired-end BAM files """ if is_paired(bam_file): return "-p -B -C" else: return "" bcbio-nextgen-1.2.9/bcbio/rnaseq/gtf.py000066400000000000000000000412231415626112400177540ustar00rootroot00000000000000import gffutils from gffutils import pybedtools_integration import tempfile import os import random import re from bcbio import utils from bcbio.utils import file_exists, open_gzipsafe from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.log import logger from bcbio.pipeline import datadict as dd def guess_infer_extent(gtf_file): """ guess if we need to use the gene extent option when making a gffutils database by making a tiny database of 1000 lines from the original GTF and looking for all of the features """ _, ext = os.path.splitext(gtf_file) tmp_out = tempfile.NamedTemporaryFile(suffix=".gtf", delete=False).name with open(tmp_out, "w") as out_handle: count = 0 in_handle = utils.open_gzipsafe(gtf_file) for line in in_handle: if count > 1000: break out_handle.write(line) count += 1 in_handle.close() db = gffutils.create_db(tmp_out, dbfn=":memory:", infer_gene_extent=False) os.remove(tmp_out) features = [x for x in db.featuretypes()] if "gene" in features and "transcript" in features: return False else: return True def get_gtf_db(gtf, in_memory=False): """ create a gffutils DB, in memory if we don't have write permissions """ db_file = gtf + ".db" if file_exists(db_file): return gffutils.FeatureDB(db_file) if not os.access(os.path.dirname(db_file), os.W_OK | os.X_OK): in_memory = True db_file = ":memory:" if in_memory else db_file if in_memory or not file_exists(db_file): infer_extent = guess_infer_extent(gtf) disable_extent = not infer_extent db = gffutils.create_db(gtf, dbfn=db_file, disable_infer_genes=disable_extent, disable_infer_transcripts=disable_extent) if in_memory: return db else: return gffutils.FeatureDB(db_file) def gtf_to_bed(gtf, alt_out_dir=None): """ create a BED file of transcript-level features with attached gene name or gene ids """ out_file = os.path.splitext(gtf)[0] + ".bed" if file_exists(out_file): return out_file if not os.access(os.path.dirname(out_file), os.W_OK | os.X_OK): if not alt_out_dir: raise IOError("Cannot write transcript BED output file %s" % out_file) else: out_file = os.path.join(utils.safe_makedir(alt_out_dir), os.path.basename(out_file)) if file_exists(out_file): return out_file with open(out_file, "w") as out_handle: db = get_gtf_db(gtf) for feature in db.features_of_type('transcript', order_by=("seqid", "start", "end")): chrom = feature.chrom start = feature.start - 1 end = feature.end attributes = feature.attributes.keys() strand = feature.strand name = (feature['gene_name'][0] if 'gene_name' in attributes else feature['gene_id'][0]) line = "\t".join([str(x) for x in [chrom, start, end, name, ".", strand]]) out_handle.write(line + "\n") return out_file def complete_features(db): """ iterator returning features which are complete (have a 'gene_id' and a 'transcript_id') """ for feature in db.all_features(): gene_id = feature.attributes.get('gene_id', [None])[0] transcript_id = feature.attributes.get('transcript_id', [None])[0] if gene_id and transcript_id and feature.featuretype != "transcript": yield feature def gtf_to_fasta(gtf_file, ref_fasta, cds=False, out_file=None): """ convert a GTF to FASTA format if cds=True, use the start/stop codons to output only the CDS handles malformed FASTA files where a single transcript is repeated multiple times by just using the first one handles stripping of transcript version IDs if they exist """ if out_file and file_exists(out_file): return out_file if not out_file: out_file = tempfile.NamedTemporaryFile(delete=False, suffix=".fa").name tmp_file = out_file + ".tmp" if cds: cmd = "gffread -g {ref_fasta} -x {tx_tmp_file} {gtf_file}" else: cmd = "gffread -g {ref_fasta} -w {tx_tmp_file} {gtf_file}" message = "Converting %s to FASTA format." % gtf_file with file_transaction(tmp_file) as tx_tmp_file: do.run(cmd.format(**locals()), message) transcript = "" skipping = False with file_transaction(out_file) as tx_out_file: with open(tmp_file) as in_handle, open(tx_out_file, "w") as out_handle: for line in in_handle: if line.startswith(">"): cur_transcript = line.split(" ")[0][1:] if transcript == cur_transcript: logger.info("Transcript %s has already been seen, skipping this " "version." % cur_transcript) skipping = True else: transcript = cur_transcript skipping = False transcript = _strip_feature_version(transcript) line = ">" + transcript + "\n" if not skipping: out_handle.write(line) os.remove(tmp_file) return out_file def partition_gtf(gtf, coding=False, out_file=False): """ return a GTF file of all non-coding or coding transcripts. the GTF must be annotated with gene_biotype = "protein_coding" or to have the source column set to the biotype for all coding transcripts. set coding to True to get only the coding, false to get only the non-coding """ if out_file and file_exists(out_file): return out_file if not out_file: out_file = tempfile.NamedTemporaryFile(delete=False, suffix=".gtf").name if coding: pred = lambda biotype: biotype and biotype == "protein_coding" else: pred = lambda biotype: biotype and biotype != "protein_coding" biotype_lookup = _biotype_lookup_fn(gtf) db = get_gtf_db(gtf) with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for feature in db.all_features(): biotype = biotype_lookup(feature) if pred(biotype): out_handle.write(str(feature) + "\n") return out_file def split_gtf(gtf, sample_size=None, out_dir=None): """ split a GTF file into two equal parts, randomly selecting genes. sample_size will select up to sample_size genes in total """ if out_dir: part1_fn = os.path.basename(os.path.splitext(gtf)[0]) + ".part1.gtf" part2_fn = os.path.basename(os.path.splitext(gtf)[0]) + ".part2.gtf" part1 = os.path.join(out_dir, part1_fn) part2 = os.path.join(out_dir, part2_fn) if file_exists(part1) and file_exists(part2): return part1, part2 else: part1 = tempfile.NamedTemporaryFile(delete=False, suffix=".part1.gtf").name part2 = tempfile.NamedTemporaryFile(delete=False, suffix=".part2.gtf").name db = get_gtf_db(gtf) gene_ids = set([x['gene_id'][0] for x in db.all_features()]) if not sample_size or (sample_size and sample_size > len(gene_ids)): sample_size = len(gene_ids) gene_ids = set(random.sample(gene_ids, sample_size)) part1_ids = set(random.sample(gene_ids, sample_size // 2)) part2_ids = gene_ids.difference(part1_ids) with open(part1, "w") as part1_handle: for gene in part1_ids: for feature in db.children(gene): part1_handle.write(str(feature) + "\n") with open(part2, "w") as part2_handle: for gene in part2_ids: for feature in db.children(gene): part2_handle.write(str(feature) + "\n") return part1, part2 def get_coding_noncoding_transcript_ids(gtf): """ return a set of coding and non-coding transcript_ids from a GTF """ coding_gtf = partition_gtf(gtf, coding=True) coding_db = get_gtf_db(coding_gtf) coding_ids = set([x['transcript_id'][0] for x in coding_db.all_features() if 'transcript_id' in x.attributes]) noncoding_gtf = partition_gtf(gtf) noncoding_db = get_gtf_db(noncoding_gtf) noncoding_ids = set([x['transcript_id'][0] for x in noncoding_db.all_features() if 'transcript_id' in x.attributes]) return coding_ids, noncoding_ids def get_gene_source_set(gtf): """ get a dictionary of the set of all sources for a gene """ gene_to_source = {} db = get_gtf_db(gtf) for feature in complete_features(db): gene_id = feature['gene_id'][0] sources = gene_to_source.get(gene_id, set([])).union(set([feature.source])) gene_to_source[gene_id] = sources return gene_to_source def get_transcript_source_set(gtf): """ get a dictionary of the set of all sources of the gene for a given transcript """ gene_to_source = get_gene_source_set(gtf) transcript_to_source = {} db = get_gtf_db(gtf) for feature in complete_features(db): gene_id = feature['gene_id'][0] transcript_to_source[feature['transcript_id'][0]] = gene_to_source[gene_id] return transcript_to_source def get_rRNA(gtf): """ extract rRNA genes and transcripts from a gtf file """ rRNA_biotypes = ["rRNA", "Mt_rRNA", "tRNA", "MT_tRNA", "rRNA_pseudogene"] features = set() with open_gzipsafe(gtf) as in_handle: for line in in_handle: if not "gene_id" in line or not "transcript_id" in line: continue if any(x in line for x in rRNA_biotypes): geneid = line.split("gene_id")[1].split(" ")[1] geneid = _strip_non_alphanumeric(geneid) geneid = _strip_feature_version(geneid) txid = line.split("transcript_id")[1].split(" ")[1] txid = _strip_non_alphanumeric(txid) txid = _strip_feature_version(txid) features.add((geneid, txid)) return features def _biotype_lookup_fn(gtf): """ return a function that will look up the biotype of a feature this checks for either gene_biotype or biotype being set or for the source column to have biotype information """ db = get_gtf_db(gtf) sources = set([feature.source for feature in db.all_features()]) gene_biotypes = set([feature.attributes.get("gene_biotype", [None])[0] for feature in db.all_features()]) biotypes = set([feature.attributes.get("biotype", [None])[0] for feature in db.all_features()]) if "protein_coding" in sources: return lambda feature: feature.source elif "protein_coding" in biotypes: return lambda feature: feature.attributes.get("biotype", [None])[0] elif "protein_coding" in gene_biotypes: return lambda feature: feature.attributes.get("gene_biotype", [None])[0] else: return None def tx2genedict(gtf, keep_version=False): """ produce a tx2gene dictionary from a GTF file """ d = {} with open_gzipsafe(gtf) as in_handle: for line in in_handle: if "gene_id" not in line or "transcript_id" not in line: continue geneid = line.split("gene_id")[1].split(" ")[1] geneid = _strip_non_alphanumeric(geneid) if not geneid: continue txid = line.split("transcript_id")[1].split(" ")[1] txid = _strip_non_alphanumeric(txid) if keep_version and "transcript_version" in line: txversion = line.split("transcript_version")[1].split(" ")[1] txversion = _strip_non_alphanumeric(txversion) txid += "." + txversion if has_transcript_version(line) and not keep_version: txid = _strip_feature_version(txid) geneid = _strip_feature_version(geneid) txid = txid.strip() geneid = geneid.strip() if not txid or not geneid: continue d[txid] = geneid return d def _strip_feature_version(featureid): """ some feature versions are encoded as featureid.version, this strips those off, if they exist """ version_detector = re.compile(r"(?P.*)(?P\.\d+)") match = version_detector.match(featureid) if match: return match.groupdict()["featureid"] else: return featureid def _strip_non_alphanumeric(string): return string.replace('"', '').replace(';', '') def has_transcript_version(line): version_detector = re.compile(r".*(?P\.\d+)") if "transcript_version" in line: return True txid = line.split("transcript_id")[1].split(" ")[1] txid = _strip_non_alphanumeric(txid) if version_detector.match(txid): return True def tx2genefile(gtf, out_file=None, data=None, tsv=True, keep_version=False): """ write out a file of transcript->gene mappings. """ if tsv: extension = ".tsv" sep = "\t" else: extension = ".csv" sep = "," if file_exists(out_file): return out_file with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for k, v in tx2genedict(gtf, keep_version).items(): out_handle.write(sep.join([k, v]) + "\n") logger.info("tx2gene file %s created from %s." % (out_file, gtf)) return out_file def is_qualimap_compatible(gtf): """ Qualimap needs a very specific GTF format or it fails, so skip it if the GTF is not in that format """ if not gtf: return False db = get_gtf_db(gtf) def qualimap_compatible(feature): gene_id = feature.attributes.get('gene_id', [None])[0] transcript_id = feature.attributes.get('transcript_id', [None])[0] gene_biotype = feature.attributes.get('gene_biotype', [None])[0] return gene_id and transcript_id and gene_biotype for feature in db.all_features(): if qualimap_compatible(feature): return True return False def canonical_transcripts(gtf, out_file): """ given a GTF file, produce a new GTF file with only the longest transcript for each gene function lifted from: https://pythonhosted.org/gffutils/_modules/gffutils/helpers.html """ if file_exists(out_file): return out_file db = get_gtf_db(gtf) with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for gene in db.features_of_type('gene'): exon_list = [] for ti, transcript in enumerate(db.children(gene, level=1)): cds_len = 0 total_len = 0 exons = list(db.children(transcript, level=1)) for exon in exons: exon_length = len(exon) if exon.featuretype == 'CDS': cds_len += exon_length total_len += exon_length exon_list.append((cds_len, total_len, transcript, exons)) # If we have CDS, then use the longest coding transcript if max(i[0] for i in exon_list) > 0: best = sorted(exon_list)[0] # Otherwise, just choose the longest else: best = sorted(exon_list, key=lambda x: x[1])[0] for exon in db.children(best[2], level=1): out_handle.write(str(exon) + "\n") return out_file def is_cpat_compatible(gtf): """ CPAT needs some transcripts annotated with protein coding status to work properly """ if not gtf: return False db = get_gtf_db(gtf) pred = lambda biotype: biotype and biotype == "protein_coding" biotype_lookup = _biotype_lookup_fn(gtf) if not biotype_lookup: return False db = get_gtf_db(gtf) for feature in db.all_features(): biotype = biotype_lookup(feature) if pred(biotype): return True return False def get_tss_bed(gtf, out_file, data, padding=1000): """ get a BED file of transcription start sites (TSS), padded in both directions by `padding` """ if file_exists(out_file): return out_file db = get_gtf_db(gtf) tsses = pybedtools_integration.tsses(db, merge_overlapping=True) genome = dd.get_ref_file(data) + ".fai" tsses = tsses.slop(l=padding, r=padding, g=genome) with file_transaction(out_file) as tx_out_file: tsses.saveas(tx_out_file) return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/kallisto.py000066400000000000000000000204131415626112400210140ustar00rootroot00000000000000""" kallisto https://github.com/pachterlab/kallisto """ import os import pandas as pd import toolz as tz import bcbio.pipeline.datadict as dd from bcbio.rnaseq import sailfish from bcbio.utils import (file_exists, safe_makedir, chdir) from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.pipeline import config_utils from bcbio.rnaseq import umi from bcbio.bam import fasta def run_kallisto_rnaseq(data): samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) kallisto_dir = os.path.join(work_dir, "kallisto", samplename) gtf_file = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) files = dd.get_input_sequence_files(data) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None assert file_exists(gtf_file), "%s was not found, exiting." % gtf_file fasta_file = dd.get_ref_file(data) assert file_exists(fasta_file), "%s was not found, exiting." % fasta_file assert fq2, ("We don't support kallisto for single-end reads and fusion " "calling with pizzly does not accept single end reads.") out_file = kallisto_rnaseq(fq1, fq2, kallisto_dir, gtf_file, fasta_file, data) data = dd.set_kallisto_quant(data, out_file) return [[data]] def kallisto_rnaseq(fq1, fq2, kallisto_dir, gtf_file, fasta_file, data): samplename = dd.get_sample_name(data) quant_dir = os.path.join(kallisto_dir, "quant") safe_makedir(kallisto_dir) sentinel_file = os.path.join(quant_dir, "abundance.h5") if os.path.exists(sentinel_file): return quant_dir num_cores = dd.get_num_cores(data) strandedness = dd.get_strandedness(data).lower() kallisto = config_utils.get_program("kallisto", dd.get_config(data)) index = kallisto_index(gtf_file, fasta_file, data, os.path.dirname(kallisto_dir)) fusion_flag = "--fusion" if dd.get_fusion_mode(data) or dd.get_fusion_caller(data) else "" single_flag = "--single" if not fq2 else "" fraglength_flag = "--fragment-length=200" if not fq2 else "" sd_flag = "--sd=25" if not fq2 else "" bootstrap_flag = "--bootstrap-samples=30" fq2 = "" if not fq2 else fq2 if not fq2: logger.warning("kallisto was run on single-end data and we set the " "estimated fragment length to 200 and the standard " "deviation to 25, if these don't reflect your data then " "the results may be inaccurate. Use with caution. See " "https://groups.google.com/forum/#!topic/kallisto-sleuth-users/h5LeAlWS33w " "for details.") cmd = ("{kallisto} quant {fusion_flag} -t {num_cores} {single_flag} " "{fraglength_flag} {sd_flag} {bootstrap_flag} " "-o {tx_out_dir} -i {index} {fq1} {fq2}") with file_transaction(data, quant_dir) as tx_out_dir: message = ("Quantifying transcripts with kallisto.") do.run(cmd.format(**locals()), message, None) return quant_dir def run_kallisto_singlecell(data): samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) kallisto_dir = os.path.join(work_dir, "kallisto", samplename) gtf_file = dd.get_transcriptome_gtf(data, dd.get_gtf_file(data)) files = dd.get_input_sequence_files(data) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None assert file_exists(gtf_file), "%s was not found, exiting." % gtf_file fasta_file = dd.get_ref_file(data) assert file_exists(fasta_file), "%s was not found, exiting." % fasta_file out_file = kallisto_singlecell(fq1, kallisto_dir, gtf_file, fasta_file, data) data = dd.set_kallisto_quant(data, out_file) return [[data]] def kallisto_singlecell(fq1, kallisto_dir, gtf_file, fasta_file, data): samplename = dd.get_sample_name(data) quant_dir = os.path.join(kallisto_dir, "quant") safe_makedir(kallisto_dir) num_cores = dd.get_num_cores(data) strandedness = dd.get_strandedness(data).lower() kallisto = config_utils.get_program("kallisto", dd.get_config(data)) # unsure how to estimate from single end data, so go with a reasonable default frag_length = 250 batch_file = umi.convert_to_kallisto(data) index = kallisto_index(gtf_file, fasta_file, data, kallisto_dir) cmd = ("{kallisto} pseudo --umi " "-t {num_cores} -o {tx_out_dir} -b {batch_file} -i {index}") with chdir(os.path.dirname(batch_file)): with file_transaction(data, quant_dir) as tx_out_dir: message = ("Quantifying transcripts with Kallisto.") do.run(cmd.format(**locals()), message, None) kallisto_table(kallisto_dir, index) return quant_dir def kallisto_index(gtf_file, ref_file, data, out_dir): out_dir = os.path.join(out_dir, "index") out_stem = dd.get_genome_build(data) if dd.get_disambiguate(data): out_stem = "-".join([out_stem] + dd.get_disambiguate(data)) index_dir = os.path.join(out_dir, out_stem) out_file = os.path.join(index_dir, out_stem + ".idx") kallisto = config_utils.get_program("kallisto", dd.get_config(data)) if dd.get_transcriptome_fasta(data): gtf_fa = dd.get_transcriptome_fasta(data) else: gtf_fa = sailfish.create_combined_fasta(data) if file_exists(out_file): return out_file with file_transaction(out_file) as tx_out_file: cmd = "{kallisto} index -k 31 -i {tx_out_file} {gtf_fa}" message = "Creating Kallisto index for {gtf_fa}." do.run(cmd.format(**locals()), message.format(**locals()), None) return out_file def kallisto_table(kallisto_dir, index): """ convert kallisto output to a count table where the rows are equivalence classes and the columns are cells """ quant_dir = os.path.join(kallisto_dir, "quant") out_file = os.path.join(quant_dir, "matrix.csv") if file_exists(out_file): return out_file tsvfile = os.path.join(quant_dir, "matrix.tsv") ecfile = os.path.join(quant_dir, "matrix.ec") cellsfile = os.path.join(quant_dir, "matrix.cells") fastafile = os.path.splitext(index)[0] + ".fa" fasta_names = fasta.sequence_names(fastafile) ec_names = get_ec_names(ecfile, fasta_names) df = pd.read_csv(tsvfile, header=None, names=["ec", "cell", "count"], sep="\t") df["ec"] = [ec_names[x] for x in df["ec"]] df = df.pivot(index='ec', columns='cell', values='count') cellnames = get_cell_names(cellsfile) colnames = [cellnames[x] for x in df.columns] df.columns = colnames df.to_csv(out_file) return out_file def get_ec_names(ecfile, fasta_names): """ convert equivalence classes to their set of transcripts """ df = pd.read_csv(ecfile, header=None, names=["ec", "transcripts"], sep="\t") transcript_groups = [x.split(",") for x in df["transcripts"]] transcripts = [] for group in transcript_groups: transcripts.append(":".join([fasta_names[int(x)] for x in group])) return transcripts def get_cell_names(cellsfile): """ get barcode identifies of cells """ with open(cellsfile) as in_handle: return [x.strip() for x in in_handle] def get_kallisto_h5(data): out_file = tz.get_in(["quant", "hdf5"], data) if out_file: return out_file else: samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) kallisto_dir = os.path.join(work_dir, "kallisto", samplename, "quant") return os.path.join(kallisto_dir, "abundance.h5") def get_kallisto_fusions(data): out_file = tz.get_in(["quant", "fusion"], data) if out_file: return out_file else: samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) kallisto_dir = os.path.join(work_dir, "kallisto", samplename, "quant") return os.path.join(kallisto_dir, "fusion.txt") def run_kallisto_index(*samples): for data in dd.sample_data_iterator(samples): work_dir = dd.get_work_dir(data) kallisto_dir = os.path.join(work_dir, "kallisto") gtf_file = dd.get_transcriptome_gtf(data, default=dd.get_gtf_file(data)) assert file_exists(gtf_file), "%s was not found, exiting." % gtf_file fasta_file = dd.get_ref_file(data) assert file_exists(fasta_file), "%s was not found, exiting." % fasta_file kallisto_index(gtf_file, fasta_file, data, kallisto_dir) return samples bcbio-nextgen-1.2.9/bcbio/rnaseq/oncofuse.py000066400000000000000000000175201415626112400210200ustar00rootroot00000000000000"""annotate fusion outputs from STAR and Tophat Supported: oncofuse: http://www.unav.es/genetica/oncofuse.html github: https://github.com/mikessh/oncofuse """ from __future__ import print_function import os import pysam import toolz as tz from bcbio.utils import file_exists from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.provenance import do import bcbio.pipeline.datadict as dd from bcbio.log import logger # ## oncofuse fusion trancript detection def run(data): if not aligner_supports_fusion(data): aligner = dd.get_aligner(data) logger.warning("Oncofuse is not supported for the %s aligner, " "skipping. " % aligner) return None config = data["config"] genome_build = data.get("genome_build", "") input_type, input_dir, input_file = _get_input_para(data) if genome_build == "GRCh37": # assume genome_build is hg19 otherwise if config["algorithm"].get("aligner") in ["star"]: if file_exists(input_file): input_file = _fix_star_junction_output(input_file) if config["algorithm"].get("aligner") in ["tophat", "tophat2"]: if file_exists(input_file): input_file = _fix_tophat_junction_output(input_file) elif "hg19" not in genome_build: return None #handle cases when fusion file doesn't exist if not file_exists(input_file): return None out_file = os.path.join(input_dir, "oncofuse_out.txt") if file_exists(out_file): return out_file oncofuse = config_utils.get_program("oncofuse", config) tissue_type = _oncofuse_tissue_arg_from_config(data) resources = config_utils.get_resources("oncofuse", config) if not file_exists(out_file): cl = [oncofuse] cl += resources.get("jvm_opts", ["-Xms750m", "-Xmx5g"]) with file_transaction(data, out_file) as tx_out_file: cl += [input_file, input_type, tissue_type, tx_out_file] cmd = " ".join(cl) try: do.run(cmd, "oncofuse fusion detection", data) except: do.run("touch %s && echo '# failed' >> %s" % (tx_out_file, tx_out_file), "oncofuse failed", data) #return out_file return out_file def is_non_zero_file(fpath): return True if os.path.isfile(fpath) and os.path.getsize(fpath) > 0 else False def aligner_supports_fusion(data): SUPPORTED_ALIGNERS = ["tophat2", "tophat", "star"] aligner = dd.get_aligner(data) return aligner and aligner.lower() in SUPPORTED_ALIGNERS def _get_input_para(data): TOPHAT_FUSION_OUTFILE = "fusions.out" STAR_FUSION_OUTFILE = "Chimeric.out.junction" config = data["config"] is_disambiguate = len(config["algorithm"].get("disambiguate", [])) > 0 aligner = config["algorithm"].get("aligner") if aligner == "tophat2": aligner = "tophat" names = data["rgnames"] # set some default hard filters: N = 2 # min. spanning reads M = 4 # min. supporting reads (spanning + encompassing) align_dir_parts = os.path.join(data["dirs"]["work"], "align", names["sample"]) align_dir_parts = os.path.join(align_dir_parts, data["genome_build"]) if is_disambiguate else align_dir_parts if aligner in ["tophat", "tophat2"]: align_dir_parts = os.path.join(data["dirs"]["work"], "align", names["sample"], names["lane"]+"_%s" % aligner) return "tophat-%d-%d" % (N,M), align_dir_parts, os.path.join(align_dir_parts, TOPHAT_FUSION_OUTFILE) if aligner in ["star"]: star_junction_file = os.path.join(align_dir_parts, names["lane"]+STAR_FUSION_OUTFILE) if is_disambiguate: contamination_bam = data["disambiguate"][ config["algorithm"]["disambiguate"][0] ] disambig_out_file = star_junction_file + "_disambiguated" if file_exists(disambig_out_file): star_junction_file = disambig_out_file elif file_exists(star_junction_file) and file_exists(contamination_bam): star_junction_file = _disambiguate_star_fusion_junctions(star_junction_file, contamination_bam, disambig_out_file, data) return "rnastar-%d-%d" % (N,M), align_dir_parts, star_junction_file return None def _fix_tophat_junction_output(chimeric_out_junction_file): #for fusion.out out_file = chimeric_out_junction_file + ".hg19" with open(out_file, "w") as out_handle: with open(chimeric_out_junction_file, "r") as in_handle: for line in in_handle: parts = line.split("\t") left, right = parts[0].split("-") leftchr = _h37tohg19(left) rightchr = _h37tohg19(right) if not leftchr or not rightchr: continue parts[0] = "%s-%s" % (_h37tohg19(left), _h37tohg19(right)) out_handle.write("\t".join(parts)) return out_file def _fix_star_junction_output(chimeric_out_junction_file): #for Chimeric.out.junction out_file = chimeric_out_junction_file + ".hg19" with open(out_file, "w") as out_handle: with open(chimeric_out_junction_file, "r") as in_handle: for line in in_handle: parts = line.split("\t") parts[0] = _h37tohg19(parts[0]) parts[3] = _h37tohg19(parts[3]) if not parts[0] or not parts[3]: continue out_handle.write("\t".join(parts)) return out_file def _h37tohg19(chromosome): MAX_CHROMOSOMES = 23 if chromosome in [str(x) for x in range(1, MAX_CHROMOSOMES)] + ["X", "Y"]: new_chrom = "chr%s" % chromosome elif chromosome == "MT": new_chrom = "chrM" # not a supported chromosome else: return None return new_chrom def _oncofuse_tissue_arg_from_config(data): """Retrieve oncofuse arguments supplied through input configuration. tissue_type is the library argument, which tells Oncofuse to use its own pre-built gene expression libraries. There are four pre-built libraries, corresponding to the four supported tissue types: EPI (epithelial origin), HEM (hematological origin), MES (mesenchymal origin) and AVG (average expression, if tissue source is unknown). """ SUPPORTED_TISSUE_TYPE = ["EPI", "HEM", "MES", "AVG"] tissue_type = tz.get_in(("metadata", "tissue"), data, None) if not tissue_type: logger.info("Oncofuse: tissue type not set, using average expression (AVG).") tissue_type = "AVG" elif tissue_type not in SUPPORTED_TISSUE_TYPE: logger.info("Oncofuse: %s not a supported tissue type, using average " "expression (AVG)." % tissue_type) tissue_type = "AVG" else: logger.info("Oncofuse: using %s as tissue type." % tissue_type) return tissue_type def _disambiguate_star_fusion_junctions(star_junction_file, contamination_bam, disambig_out_file, data): """ Disambiguate detected fusions based on alignments to another species. """ out_file = disambig_out_file fusiondict = {} with open(star_junction_file, "r") as in_handle: for my_line in in_handle: my_line_split = my_line.strip().split("\t") if len(my_line_split) < 10: continue fusiondict[my_line_split[9]] = my_line.strip("\n") with pysam.Samfile(contamination_bam, "rb") as samfile: for my_read in samfile: if my_read.is_unmapped or my_read.is_secondary: continue if my_read.qname in fusiondict: fusiondict.pop(my_read.qname) with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, 'w') as myhandle: for my_key in fusiondict: print(fusiondict[my_key], file=myhandle) return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/pizzly.py000066400000000000000000000116631415626112400205420ustar00rootroot00000000000000""" run the pizzly fusion caller for RNA-seq https://github.com/pmelsted/pizzly http://www.biorxiv.org/content/early/2017/07/20/166322 """ from __future__ import print_function import os from bcbio.log import logger from bcbio import utils import bcbio.pipeline.datadict as dd from bcbio.pipeline import config_utils from bcbio.distributed.transaction import file_transaction from bcbio.rnaseq import kallisto, sailfish, gtf from bcbio.provenance import do from bcbio.utils import file_exists, safe_makedir from bcbio.bam import fasta h5py = utils.LazyImport("h5py") import numpy as np import pandas as pd def get_fragment_length(data): """ lifted from https://github.com/pmelsted/pizzly/scripts/pizzly_get_fragment_length.py """ h5 = kallisto.get_kallisto_h5(data) cutoff = 0.95 with h5py.File(h5) as f: x = np.asarray(f['aux']['fld'], dtype='float64') y = np.cumsum(x)/np.sum(x) fraglen = np.argmax(y > cutoff) return(fraglen) def run_pizzly(data): samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) pizzlydir = os.path.join(work_dir, "pizzly") gtf = dd.get_transcriptome_gtf(data) if not gtf: gtf = dd.get_gtf_file(data) if dd.get_transcriptome_fasta(data): gtf_fa = dd.get_transcriptome_fasta(data) else: gtf_fa = sailfish.create_combined_fasta(data) stripped_fa = os.path.splitext(os.path.basename(gtf_fa))[0] + "-noversions.fa" stripped_fa = os.path.join(pizzlydir, stripped_fa) gtf_fa = fasta.strip_transcript_versions(gtf_fa, stripped_fa) fraglength = get_fragment_length(data) cachefile = os.path.join(pizzlydir, "pizzly.cache") fusions = kallisto.get_kallisto_fusions(data) pizzlypath = config_utils.get_program("pizzly", dd.get_config(data)) outdir = pizzly(pizzlypath, gtf, gtf_fa, fraglength, cachefile, pizzlydir, fusions, samplename, data) return outdir def pizzly(pizzly_path, gtf, gtf_fa, fraglength, cachefile, pizzlydir, fusions, samplename, data): outdir = os.path.join(pizzlydir, samplename) out_stem = os.path.join(outdir, samplename) pizzly_gtf = make_pizzly_gtf(gtf, os.path.join(pizzlydir, "pizzly.gtf"), data) sentinel = os.path.join(out_stem, "-flat-filtered.tsv") pizzlycalls = out_stem + ".json" if not file_exists(pizzlycalls): with file_transaction(data, outdir) as tx_out_dir: safe_makedir(tx_out_dir) tx_out_stem = os.path.join(tx_out_dir, samplename) with file_transaction(cachefile) as tx_cache_file: cmd = ("{pizzly_path} -k 31 --gtf {pizzly_gtf} --cache {tx_cache_file} " "--align-score 2 --insert-size {fraglength} --fasta {gtf_fa} " "--output {tx_out_stem} {fusions}") message = ("Running pizzly on %s." % fusions) do.run(cmd.format(**locals()), message) flatfile = out_stem + "-flat.tsv" filteredfile = out_stem + "-flat-filtered.tsv" flatten_pizzly(pizzlycalls, flatfile, data) filter_pizzly(flatfile, filteredfile, data) return outdir def make_pizzly_gtf(gtf_file, out_file, data): """ pizzly needs the GTF to be in gene -> transcript -> exon order for each gene. it also wants the gene biotype set as the source """ if file_exists(out_file): return out_file db = gtf.get_gtf_db(gtf_file) with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for gene in db.features_of_type("gene"): children = [x for x in db.children(id=gene)] for child in children: if child.attributes.get("gene_biotype", None): gene_biotype = child.attributes.get("gene_biotype") gene.attributes['gene_biotype'] = gene_biotype gene.source = gene_biotype[0] print(gene, file=out_handle) for child in children: child.source = gene_biotype[0] # gffread produces a version-less FASTA file child.attributes.pop("transcript_version", None) print(child, file=out_handle) return out_file def flatten_pizzly(in_file, out_file, data): pizzlyflatten = config_utils.get_program("pizzly_flatten_json.py", data) if file_exists(out_file): return out_file cmd = "{pizzlyflatten} {in_file} > {tx_out_file}" message = "Flattening {in_file} to {out_file}." with file_transaction(data, out_file) as tx_out_file: do.run(cmd.format(**locals()), message.format(**locals())) return out_file def filter_pizzly(in_file, out_file, data): df = pd.read_csv(in_file, header=0, sep="\t") df = df.query('paircount > 1 and splitcount > 1') if file_exists(out_file): return out_file with file_transaction(out_file) as tx_out_file: df.to_csv(tx_out_file, sep="\t", index=False) return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/qc.py000066400000000000000000000042251415626112400176000ustar00rootroot00000000000000"""Run Broad's RNA-SeqQC tool and handle reporting of useful summary metrics. """ # soft imports try: import pandas as pd import statsmodels.formula.api as sm except ImportError: pd, sm = None, None from bcbio import bam def starts_by_depth(bam_file, data, sample_size=10000000): """ Return a set of x, y points where x is the number of reads sequenced and y is the number of unique start sites identified If sample size < total reads in a file the file will be downsampled. """ binsize = (sample_size / 100) + 1 seen_starts = set() counted = 0 num_reads = [] starts = [] buffer = [] downsampled = bam.downsample(bam_file, data, sample_size) with bam.open_samfile(downsampled) as samfile: for read in samfile: if read.is_unmapped: continue counted += 1 buffer.append(str(read.tid) + ":" + str(read.pos)) if counted % binsize == 0: seen_starts.update(buffer) buffer = [] num_reads.append(counted) starts.append(len(seen_starts)) seen_starts.update(buffer) num_reads.append(counted) starts.append(len(seen_starts)) return pd.DataFrame({"reads": num_reads, "starts": starts}) def estimate_library_complexity(df, algorithm="RNA-seq"): """ estimate library complexity from the number of reads vs. number of unique start sites. returns "NA" if there are not enough data points to fit the line """ DEFAULT_CUTOFFS = {"RNA-seq": (0.25, 0.40)} cutoffs = DEFAULT_CUTOFFS[algorithm] if len(df) < 5: return {"unique_starts_per_read": 'nan', "complexity": "NA"} model = sm.ols(formula="starts ~ reads", data=df) fitted = model.fit() slope = fitted.params["reads"] if slope <= cutoffs[0]: complexity = "LOW" elif slope <= cutoffs[1]: complexity = "MEDIUM" else: complexity = "HIGH" # for now don't return the complexity flag return {"Unique Starts Per Read": float(slope)} # return {"unique_start_per_read": float(slope), # "complexity": complexity} bcbio-nextgen-1.2.9/bcbio/rnaseq/rapmap.py000066400000000000000000000105241415626112400204540ustar00rootroot00000000000000""" Wrapper for RapMap: https://github.com/COMBINE-lab/RapMap http://biorxiv.org/content/early/2015/10/22/029652 """ import os from bcbio.rnaseq import sailfish import bcbio.pipeline.datadict as dd from bcbio.utils import (file_exists, safe_makedir, is_gzipped) from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.pipeline import config_utils from bcbio.ngsalign import postalign from bcbio import bam import bcbio.bam.fasta as fasta def run_rapmap_index(*samples): for data in dd.sample_data_iterator(samples): work_dir = dd.get_work_dir(data) rapmap_dir = os.path.join(work_dir, "rapmap") gtf_file = dd.get_gtf_file(data) fasta_file = dd.get_ref_file(data) assert file_exists(fasta_file), "%s was not found, exiting." % fasta_file rapmap_index(gtf_file, fasta_file, "quasi", data, rapmap_dir) return samples def run_rapmap_align(data): samplename = dd.get_sample_name(data) files = dd.get_input_sequence_files(data) work_dir = dd.get_work_dir(data) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None rapmap_dir = os.path.join(work_dir, "rapmap", samplename) gtf_file = dd.get_gtf_file(data) fasta_file = dd.get_ref_file(data) out_file = rapmap_align(fq1, fq2, rapmap_dir, gtf_file, fasta_file, "quasi", data) data = dd.set_transcriptome_bam(data, out_file) return [[data]] def rapmap_index(gtf_file, ref_file, algorithm, data, out_dir): out_dir = os.path.join(out_dir, "index") valid_indexes = ["pseudoindex", "quasiindex"] index_type = algorithm + "index" assert index_type in valid_indexes, \ "RapMap only supports %s indices." % valid_indexes out_dir = os.path.join(out_dir, index_type, sailfish.get_build_string(data)) if dd.get_disambiguate(data): out_dir = "-".join([out_dir] + dd.get_disambguate(data)) rapmap = config_utils.get_program("rapmap", dd.get_config(data)) # use user supplied transcriptome FASTA file if it exists if dd.get_transcriptome_fasta(data): gtf_fa = dd.get_transcriptome_fasta(data) else: gtf_fa = sailfish.create_combined_fasta(data) gtf_fa = fasta.strip_transcript_versions(gtf_fa, os.path.join(out_dir, os.path.basename(gtf_fa))) tmpdir = dd.get_tmp_dir(data) if file_exists(os.path.join(out_dir, "sa.bin")): return out_dir files = dd.get_input_sequence_files(data) kmersize = sailfish.pick_kmersize(files[0]) message = "Creating rapmap {index_type} for {gtf_fa} with {kmersize} bp kmers." with file_transaction(out_dir) as tx_out_dir: cmd = "{rapmap} {index_type} -k {kmersize} -i {tx_out_dir} -t {gtf_fa}" do.run(cmd.format(**locals()), message.format(**locals()), None) return out_dir def rapmap_align(fq1, fq2, rapmap_dir, gtf_file, ref_file, algorithm, data): valid_algorithms = ["pseudo", "quasi"] assert algorithm in valid_algorithms, \ "RapMap algorithm needs to be one of %s." % valid_algorithms safe_makedir(rapmap_dir) base_dir = os.path.dirname(rapmap_dir) samplename = dd.get_sample_name(data) out_file = os.path.join(rapmap_dir, samplename + ".bam") if file_exists(out_file): bam.index(out_file, dd.get_config(data)) return out_file rapmap_index_loc = rapmap_index(gtf_file, ref_file, algorithm, data, base_dir) num_cores = dd.get_num_cores(data) algorithm_subcommand = algorithm + "map" rapmap = config_utils.get_program("rapmap", dd.get_config(data)) cmd = "{rapmap} {algorithm_subcommand} -t {num_cores} -i {rapmap_index_loc} " fq1_cmd = "{fq1} " if not is_gzipped(fq1) else "<(gzip -cd {fq1}) " fq1_cmd = fq1_cmd.format(fq1=fq1) if not fq2: cmd += "-r {fq1_cmd} " else: fq2_cmd = "{fq2} " if not is_gzipped(fq2) else "<(gzip -cd {fq2}) " fq2_cmd = fq2_cmd.format(fq2=fq2) cmd += "-1 {fq2_cmd} -2 {fq2_cmd} " with file_transaction(out_file) as tx_out_file: cmd += "| " + postalign.sam_to_sortbam_cl(data, tx_out_file) run_message = ("%smapping %s and %s to %s with Rapmap. " % (algorithm, fq1, fq2, rapmap_index_loc)) do.run(cmd.format(**locals()), run_message, None) bam.index(out_file, dd.get_config(data)) return out_file bcbio-nextgen-1.2.9/bcbio/rnaseq/rsem.py000066400000000000000000000044551415626112400201500ustar00rootroot00000000000000import os from bcbio import bam from bcbio import utils from bcbio.log import logger from bcbio.distributed import transaction from bcbio.provenance import do CALCULATE_EXP = ( "rsem-calculate-expression --bam {core_flag} {paired_flag} " "--no-bam-output --forward-prob 0.5 " "--estimate-rspd {bam_file} {rsem_genome_dir}/{build} {samplename}") PREPARE_REFERENCE = "rsem-prepare-reference --gtf {gtf} {multifasta} {build}" def prepare_rsem_reference(gtf, multifasta, build): """ gtf: path to GTF file (must have gene_id and transcript_id) multifasta: path to multifasta file build: name of organism build (e.g. hg19) """ if not utils.which("rsem-prepare-reference"): logger.info("Skipping prepping RSEM reference because " "rsem-prepare-reference could not be found.") return None command = PREPARE_REFERENCE.format(gtf=gtf, multifasta=multifasta, build=build) with transaction.tx_tmpdir(remove=False) as rsem_genome_dir: with utils.chdir(rsem_genome_dir): message = "Preparing rsem reference from %s" % gtf do.run(command, message) return rsem_genome_dir def rsem_calculate_expression(bam_file, rsem_genome_dir, samplename, build, out_dir, cores=1): """ works only in unstranded mode for now (--forward-prob 0.5) """ if not utils.which("rsem-calculate-expression"): logger.info("Skipping RSEM because rsem-calculate-expression could " "not be found.") return None sentinel_file = os.path.join(out_dir, samplename + "Test.genes.results") if utils.file_exists(sentinel_file): return out_dir paired_flag = "--paired" if bam.is_paired(bam_file) else "" core_flag = "-p {cores}".format(cores=cores) command = CALCULATE_EXP.format( core_flag=core_flag, paired_flag=paired_flag, bam_file=bam_file, rsem_genome_dir=rsem_genome_dir, build=build, samplename=samplename) message = "Calculating transcript expression of {bam_file} using RSEM." with transaction.file_transaction(out_dir) as tx_out_dir: utils.safe_makedir(tx_out_dir) with utils.chdir(tx_out_dir): do.run(command, message.format(bam_file=bam_file)) return out_dir bcbio-nextgen-1.2.9/bcbio/rnaseq/sailfish.py000066400000000000000000000203711415626112400207770ustar00rootroot00000000000000import os from collections import namedtuple import pandas as pd from bcbio import utils import bcbio.pipeline.datadict as dd import bcbio.rnaseq.gtf as gtf from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.utils import (file_exists, safe_makedir, is_gzipped, R_package_path, Rscript_cmd) from bcbio.pipeline import config_utils, disambiguate from bcbio.bam import fastq from bcbio import bam def run_sailfish(data): samplename = dd.get_sample_name(data) files = dd.get_input_sequence_files(data) work_dir = dd.get_work_dir(data) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None if not fastq.is_fastq(fq1): return [[data]] sailfish_dir = os.path.join(work_dir, "sailfish", samplename) gtf_file = dd.get_gtf_file(data) assert file_exists(gtf_file), "%s was not found, exiting." % gtf_file fasta_file = dd.get_ref_file(data) assert file_exists(fasta_file), "%s was not found, exiting." % fasta_file stranded = dd.get_strandedness(data).lower() out_file = sailfish(fq1, fq2, sailfish_dir, gtf_file, fasta_file, stranded, data) data = dd.set_sailfish(data, out_file) data = dd.set_sailfish_dir(data, sailfish_dir) return [[data]] def sailfish(fq1, fq2, sailfish_dir, gtf_file, ref_file, strandedness, data): safe_makedir(sailfish_dir) samplename = dd.get_sample_name(data) quant_dir = os.path.join(sailfish_dir, "quant") out_file = os.path.join(quant_dir, "quant.sf") if file_exists(out_file): return out_file build_string = get_build_string(data) sailfish_idx = sailfish_index(ref_file, gtf_file, data, build_string) num_cores = dd.get_num_cores(data) sailfish = config_utils.get_program("sailfish", data["config"]) cmd = "{sailfish} quant -i {sailfish_idx} -p {num_cores} " cmd += _libtype_string(fq1, fq2, strandedness) fq1_cmd = "{fq1}" if not is_gzipped(fq1) else "<(gzip -cd {fq1})" fq1_cmd = fq1_cmd.format(fq1=fq1) if not fq2: cmd += " -r {fq1_cmd} " else: fq2_cmd = "{fq2}" if not is_gzipped(fq2) else "<(gzip -cd {fq2})" fq2_cmd = fq2_cmd.format(fq2=fq2) cmd += " -1 {fq1_cmd} -2 {fq2_cmd} " cmd += "--useVBOpt --numBootstraps 30 " cmd += "-o {tx_out_dir}" message = "Quantifying transcripts in {fq1} and {fq2}." with file_transaction(data, quant_dir) as tx_out_dir: do.run(cmd.format(**locals()), message.format(**locals()), None) sleuthify_sailfish(tx_out_dir) return out_file def sleuthify_sailfish(sailfish_dir): """ if installed, use wasabi to create abundance.h5 output for use with sleuth """ if not R_package_path("wasabi"): return None else: rscript = Rscript_cmd() cmd = """{rscript} --vanilla -e 'library("wasabi"); prepare_fish_for_sleuth(c("{sailfish_dir}"))'""" do.run(cmd.format(**locals()), "Converting Sailfish to Sleuth format.") return os.path.join(sailfish_dir, "abundance.h5") def create_combined_fasta(data): """ if there are genomes to be disambiguated, create a FASTA file of all of the transcripts for all genomes """ out_dir = os.path.join(dd.get_work_dir(data), "inputs", "transcriptome") items = disambiguate.split([data]) fasta_files = [] for i in items: odata = i[0] gtf_file = dd.get_gtf_file(odata) ref_file = dd.get_ref_file(odata) out_file = os.path.join(out_dir, dd.get_genome_build(odata) + ".fa") if file_exists(out_file): fasta_files.append(out_file) else: out_file = gtf.gtf_to_fasta(gtf_file, ref_file, out_file=out_file) fasta_files.append(out_file) out_stem = os.path.join(out_dir, dd.get_genome_build(data)) if dd.get_disambiguate(data): out_stem = "-".join([out_stem] + (dd.get_disambiguate(data) or [])) combined_file = out_stem + ".fa" if file_exists(combined_file): return combined_file fasta_file_string = " ".join(fasta_files) cmd = "cat {fasta_file_string} > {tx_out_file}" with file_transaction(data, combined_file) as tx_out_file: do.run(cmd.format(**locals()), "Combining transcriptome FASTA files.") return combined_file def create_combined_tx2gene(data): out_dir = os.path.join(dd.get_work_dir(data), "inputs", "transcriptome") items = disambiguate.split([data]) tx2gene_files = [] for i in items: odata = i[0] gtf_file = dd.get_transcriptome_gtf(odata) if not gtf_file: gtf_file = dd.get_gtf_file(odata) out_file = os.path.join(out_dir, dd.get_genome_build(odata) + "-tx2gene.csv") tools_on = dd.get_tools_on(odata) if tools_on and "keep_gene_version" in tools_on: k_version = True else: k_version = False if file_exists(out_file): tx2gene_files.append(out_file) else: out_file = gtf.tx2genefile(gtf_file, out_file, tsv=False, keep_version = k_version) tx2gene_files.append(out_file) combined_file = os.path.join(out_dir, "tx2gene.csv") if file_exists(combined_file): return combined_file tx2gene_file_string = " ".join(tx2gene_files) cmd = "cat {tx2gene_file_string} > {tx_out_file}" with file_transaction(data, combined_file) as tx_out_file: do.run(cmd.format(**locals()), "Combining tx2gene CSV files.") return combined_file def get_build_string(data): build_string = dd.get_genome_build(data) if dd.get_disambiguate(data): build_string = "-".join([build_string] + (dd.get_disambiguate(data) or [])) return build_string def run_sailfish_index(*samples): samples = [utils.to_single_data(x) for x in samples] Build = namedtuple('Build', ['build', 'ref', 'gtf']) builds = {Build(get_build_string(x), dd.get_ref_file(x), dd.get_gtf_file(x)) for x in samples} data = samples[0] indexdirs = {} for build in builds: indexdirs[build.build] = sailfish_index(build.ref, build.gtf, data, build.build) return [[x] for x in samples] def sailfish_index(gtf_file, ref_file, data, build): work_dir = dd.get_work_dir(data) out_dir = os.path.join(work_dir, "sailfish", "index", build) sailfish = config_utils.get_program("sailfish", data["config"]) num_cores = dd.get_num_cores(data) gtf_fa = create_combined_fasta(data) if file_exists(os.path.join(out_dir, "versionInfo.json")): return out_dir with file_transaction(data, out_dir) as tx_out_dir: fq1, _ = dd.get_input_sequence_files(data) kmersize = pick_kmersize(fq1) cmd = ("{sailfish} index -p {num_cores} -t {gtf_fa} -o {tx_out_dir} " "-k {kmersize}") message = "Creating sailfish index for {gtf_fa} with {kmersize} bp kmers." do.run(cmd.format(**locals()), message.format(**locals()), None) return out_dir def _libtype_string(fq1, fq2, strandedness): """supports just the Tophat unstranded/firstrand/secondstrand""" libtype = "-l " strand = "A" if strandedness != "auto": libtype = "-l I" if fq2 else "-l " strand = _sailfish_strand_string(strandedness) return libtype + strand def _sailfish_strand_string(strandedness): return {'unstranded': "U", 'firststrand': "SR", 'secondstrand': "SF"}.get(strandedness, "U") def _sailfish_expression_parser(sailfish_file, samplename): col_names = ["name", "length", "effectiveLength", "tpm", "numreads"] df = pd.read_csv(sailfish_file, comment="#", header=None, skiprows=1, index_col=0, names=col_names, sep="\t") df["sample"] = samplename return df def pick_kmersize(fq): """ pick an appropriate kmer size based off of https://www.biostars.org/p/201474/ tl;dr version: pick 31 unless the reads are very small, if not then guess that readlength / 2 is about right. """ if bam.is_bam(fq): readlength = bam.estimate_read_length(fq) else: readlength = fastq.estimate_read_length(fq) halfread = int(round(readlength / 2)) if halfread >= 31: kmersize = 31 else: kmersize = halfread if kmersize % 2 == 0: kmersize += 1 return kmersize bcbio-nextgen-1.2.9/bcbio/rnaseq/salmon.py000066400000000000000000000256761415626112400205030ustar00rootroot00000000000000""" Wrapper for Salmon: https://github.com/COMBINE-lab/salmon http://biorxiv.org/content/early/2015/06/27/021592 """ import os import numpy as np from bcbio.rnaseq import sailfish import bcbio.pipeline.datadict as dd from bcbio.utils import (file_exists, safe_makedir, is_gzipped) import bcbio.utils as utils from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.pipeline import config_utils, fastq from bcbio import bam from bcbio.log import logger def run_salmon_bam(data): samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) salmon_dir = os.path.join(work_dir, "salmon", samplename) gtf_file = dd.get_gtf_file(data) bam_file = dd.get_transcriptome_bam(data) out_file = salmon_quant_bam(bam_file, salmon_dir, gtf_file, data) data = dd.set_salmon(data, out_file) data = dd.set_salmon_dir(data, salmon_dir) # sometimes there is no fraglen file fraglen_file = _get_fraglen_file(salmon_dir) data = dd.set_salmon_fraglen_file(data, _get_fraglen_file(salmon_dir)) if fraglen_file: data = dd.update_summary_qc(data, "salmon", base = fraglen_file) return [[data]] def run_salmon_reads(data): data = utils.to_single_data(data) files = dd.get_input_sequence_files(data) if bam.is_bam(files[0]): files = fastq.convert_bam_to_fastq(files[0], data["dirs"]["work"], data, data["dirs"], data["config"]) samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) salmon_dir = os.path.join(work_dir, "salmon", samplename) gtf_file = dd.get_transcriptome_gtf(data, dd.get_gtf_file(data)) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None index = salmon_index(gtf_file, data, os.path.dirname(salmon_dir)) out_file = salmon_quant_reads(fq1, fq2, salmon_dir, gtf_file, data, index) data = dd.set_salmon(data, out_file) data = dd.set_salmon_dir(data, salmon_dir) data = dd.set_salmon_fraglen_file(data, _get_fraglen_file(salmon_dir)) data = dd.update_summary_qc(data, "salmon", base=dd.get_salmon_fraglen_file(data)) return [[data]] def run_salmon_decoy(data): data = utils.to_single_data(data) files = dd.get_input_sequence_files(data) if bam.is_bam(files[0]): files = fastq.convert_bam_to_fastq(files[0], data["dirs"]["work"], data, data["dirs"], data["config"]) samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) salmon_dir = os.path.join(work_dir, "salmon", samplename) gtf_file = dd.get_transcriptome_gtf(data, dd.get_gtf_file(data)) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None index = salmon_decoy_index(gtf_file, data, os.path.dirname(salmon_dir)) out_file = salmon_quant_reads(fq1, fq2, salmon_dir, gtf_file, data, index) data = dd.set_salmon(data, out_file) data = dd.set_salmon_dir(data, salmon_dir) data = dd.set_salmon_fraglen_file(data, _get_fraglen_file(salmon_dir)) data = dd.update_summary_qc(data, "salmon", base=dd.get_salmon_fraglen_file(data)) return [[data]] def salmon_quant_reads(fq1, fq2, salmon_dir, gtf_file, data, index): samplename = dd.get_sample_name(data) quant_dir = salmon_dir safe_makedir(salmon_dir) out_file = os.path.join(quant_dir, "quant.sf") if file_exists(out_file): return out_file num_cores = dd.get_num_cores(data) strandedness = dd.get_strandedness(data).lower() salmon = config_utils.get_program("salmon", dd.get_config(data)) libtype = sailfish._libtype_string(fq1, fq2, strandedness) num_cores = dd.get_num_cores(data) resources = config_utils.get_resources("salmon", dd.get_config(data)) params = "" bias = True if resources.get("options") is not None: params = " ".join([str(x) for x in resources.get("options", [])]) if any("--noLengthCorrection" in x for x in resources.get("options", [])): bias=False cmd = ("{salmon} quant {libtype} -i {index} -p {num_cores} " " --validateMappings " "-o {tx_out_dir} {params} ") if bias: cmd += " --seqBias " fq1_cmd = "<(cat {fq1})" if not is_gzipped(fq1) else "<(gzip -cd {fq1})" fq1_cmd = fq1_cmd.format(fq1=fq1) if not fq2: cmd += " -r {fq1_cmd} " else: if bias: cmd += " --gcBias " fq2_cmd = "<(cat {fq2})" if not is_gzipped(fq2) else "<(gzip -cd {fq2})" fq2_cmd = fq2_cmd.format(fq2=fq2) cmd += " -1 {fq1_cmd} -2 {fq2_cmd} " # skip --useVBOpt for now, it can cause segfaults cmd += "--numBootstraps 30 " with file_transaction(data, quant_dir) as tx_out_dir: message = ("Quantifying transcripts in %s and %s with Salmon." %(fq1, fq2)) do.run(cmd.format(**locals()), message, None) sailfish.sleuthify_sailfish(tx_out_dir) return out_file def salmon_quant_bam(bam_file, salmon_dir, gtf_file, data): samplename = dd.get_sample_name(data) quant_dir = salmon_dir safe_makedir(salmon_dir) out_file = os.path.join(quant_dir, "quant.sf") if file_exists(out_file): return out_file if dd.get_transcriptome_fasta(data): gtf_fa = dd.get_transcriptome_fasta(data) else: gtf_fa = sailfish.create_combined_fasta(data) num_cores = dd.get_num_cores(data) strandedness = dd.get_strandedness(data).lower() salmon = config_utils.get_program("salmon", dd.get_config(data)) libtype = _libtype_string(bam_file, strandedness) num_cores = dd.get_num_cores(data) cmd = ("{salmon} quant {libtype} -p {num_cores} -t {gtf_fa} " "-o {tx_out_dir} -a {bam_file} ") cmd += "--numBootstraps 30 " with file_transaction(data, quant_dir) as tx_out_dir: message = "Quantifying transcripts in %s with Salmon." % bam_file do.run(cmd.format(**locals()), message, None) return out_file def _libtype_string(bam_file, strandedness): # auto by default libtype = "-l " strand = "A" if strandedness != "auto": libtype = "-l I" if bam.is_paired(bam_file) else "-l " strand = sailfish._sailfish_strand_string(strandedness) return libtype + strand def run_salmon_index(*samples): for data in dd.sample_data_iterator(samples): work_dir = dd.get_work_dir(data) salmon_dir = os.path.join(work_dir, "salmon") gtf_file = dd.get_transcriptome_gtf(data, dd.get_gtf_file(data)) salmon_index(gtf_file, data, salmon_dir) return samples def salmon_index(gtf_file, data, out_dir): out_dir = os.path.join(out_dir, "index", sailfish.get_build_string(data)) if dd.get_disambiguate(data): out_dir = "-".join([out_dir] + dd.get_disambiguate(data)) salmon = config_utils.get_program("salmon", dd.get_config(data)) num_cores = dd.get_num_cores(data) if dd.get_transcriptome_fasta(data): gtf_fa = dd.get_transcriptome_fasta(data) else: gtf_fa = sailfish.create_combined_fasta(data) assert file_exists(gtf_fa), "%s was not found, exiting." % gtf_fa tmpdir = dd.get_tmp_dir(data) out_file = os.path.join(out_dir, "versionInfo.json") if file_exists(out_file): return out_dir files = dd.get_input_sequence_files(data) kmersize = sailfish.pick_kmersize(files[0]) with file_transaction(data, out_dir) as tx_out_dir: cmd = "{salmon} index --keepDuplicates -k {kmersize} -p {num_cores} -i {tx_out_dir} -t {gtf_fa}" message = "Creating Salmon index for {gtf_fa} with {kmersize} bp kmers." do.run(cmd.format(**locals()), message.format(**locals()), None) return out_dir def salmon_decoy_index(gtf_file, data, out_dir): input_dir = os.path.join(dd.get_work_dir(data), "inputs", "transcriptome") decoy_transcriptome = os.path.join(input_dir, sailfish.get_build_string(data) + "-decoy.fa") out_dir = os.path.join(out_dir, "index", sailfish.get_build_string(data)) if dd.get_disambiguate(data): out_dir = "-".join([out_dir] + dd.get_disambiguate(data)) salmon = config_utils.get_program("salmon", dd.get_config(data)) num_cores = dd.get_num_cores(data) if dd.get_transcriptome_fasta(data): gtf_fa = dd.get_transcriptome_fasta(data) else: gtf_fa = sailfish.create_combined_fasta(data) assert file_exists(gtf_fa), "%s was not found, exiting." % gtf_fa decoy_sequence_file = get_decoy_sequence_file(data) decoy_name_file = get_decoy_name_file(data) gtf_fa = create_decoy_transcriptome(gtf_fa, get_decoy_sequence_file(data), decoy_transcriptome) out_file = os.path.join(out_dir, "versionInfo.json") if file_exists(out_file): logger.info("Transcriptome index for %s detected, skipping building." % gtf_fa) return out_dir files = dd.get_input_sequence_files(data) kmersize = sailfish.pick_kmersize(files[0]) with file_transaction(data, out_dir) as tx_out_dir: cmd = ("{salmon} index -k {kmersize} -p {num_cores} -i {tx_out_dir} -t {gtf_fa} " "--decoys {decoy_name_file} ") message = "Creating decoy-aware Salmon index for {gtf_fa} with {kmersize} bp kmers." do.run(cmd.format(**locals()), message.format(**locals()), None) return out_dir def create_decoy_transcriptome(transcriptome, decoys, out_file): if file_exists(out_file): return out_file with file_transaction(out_file) as tx_out_file: cmd = f"cat {transcriptome} {decoys} > {tx_out_file}" message = f"Making decoy transcriptome with {transcriptome} and {decoys} to {out_file}." do.run(cmd, message) return out_file def _get_fraglen_file(salmondir): flenfile = os.path.join(salmondir, "libParams", "flenDist.txt") if not file_exists(flenfile): return None else: return flenfile def parse_fragment_length_file(filename): with open(filename) as in_handle: flens = [float(x) for x in next(in_handle).split("\t")] return flens def estimate_fragment_size(data): filename = dd.get_salmon_fraglen_file(data) if not file_exists(filename): return None flen = parse_fragment_length_file(filename) return float(np.sum(np.multiply(flen, range(len(flen))))) def get_decoy_sequence_file(data): """ decoys are located in the rnaseq/salmon-decoys directory decoys.fa: decoy sequences to append to transcriptome """ rnaseq_dir = os.path.dirname(dd.get_gtf_file(data)) decoy_dir = os.path.join(rnaseq_dir, "salmon-decoys") decoys = os.path.join(decoy_dir, "decoys.fa") if file_exists(decoys): return decoys else: return None def get_decoy_name_file(data): """ decoys are located in the rnaseq/salmon-decoys directory decoys.txt: names of decoy sequences """ rnaseq_dir = os.path.dirname(dd.get_gtf_file(data)) decoy_dir = os.path.join(rnaseq_dir, "salmon-decoys") decoys = os.path.join(decoy_dir, "decoys.txt") if file_exists(decoys): return decoys else: return None bcbio-nextgen-1.2.9/bcbio/rnaseq/singlecellexperiment.py000066400000000000000000000055601415626112400234220ustar00rootroot00000000000000from __future__ import print_function import os import subprocess from bcbio.rnaseq import gtf from bcbio.utils import file_exists, Rscript_cmd, R_sitelib from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.log import logger def make_scrnaseq_object(samples): """ load the initial se.rda object using sinclecell-experiment """ local_sitelib = R_sitelib() counts_dir = os.path.dirname(dd.get_in_samples(samples, dd.get_combined_counts)) gtf_file = dd.get_in_samples(samples, dd.get_transcriptome_gtf) if not gtf_file: gtf_file = dd.get_in_samples(samples, dd.get_gtf_file) rda_file = os.path.join(counts_dir, "se.rda") if not file_exists(rda_file): with file_transaction(rda_file) as tx_out_file: rcode = "%s-run.R" % os.path.splitext(rda_file)[0] rrna_file = "%s-rrna.txt" % os.path.splitext(rda_file)[0] rrna_file = _find_rRNA_genes(gtf_file, rrna_file) with open(rcode, "w") as out_handle: out_handle.write(_script.format(**locals())) rscript = Rscript_cmd() try: # do.run([rscript, "--vanilla", rcode], # "SingleCellExperiment", # log_error=False) rda_file = rcode except subprocess.CalledProcessError as msg: logger.exception() def _find_rRNA_genes(gtf_file, rrna_file): rrna_features = gtf.get_rRNA(gtf_file) transcripts = set([x[0] for x in rrna_features if x]) with open(rrna_file, 'w') as outh: outh.write("\n".join(transcripts)) return rrna_file _script = """ library(SingleCellExperiment) library(Matrix) counts = readMM("{counts_dir}/tagcounts.mtx") rownames = read.csv("{counts_dir}/tagcounts.mtx.rownames", header = F)[["V1"]] rownames = as.character(rownames) colnames = read.csv("{counts_dir}/tagcounts.mtx.colnames", header = F)[["V1"]] colnames = make.names(as.character(colnames)) reads = read.csv("{counts_dir}/cb-histogram.txt", header = F, sep="\t", row.names = 1) rownames(reads) = make.names(rownames(reads)) counts = as(counts, "dgCMatrix") rownames(counts) = rownames colnames(counts) = colnames metadata = read.csv("{counts_dir}/tagcounts.mtx.metadata") rownames(metadata) = colnames metadata[["nUMI"]] = colSums(counts) metadata[["nGenes"]] = colSums(counts>0) metadata[["log10GenesPerUMI"]] = log10(metadata$nGene) / log10(metadata$nUMI) metadata[["nReads"]] = reads[colnames,] rrna = read.csv("{rrna_file}", header=F, stringsAsFactors = F) metadata[["mtUMI"]] = colSums(counts[rrna[["V1"]],], na.rm = T) metadata[["mtUMI"]][is.na(metadata[["mtUMI"]])] = 0 metadata[["mitoRatio"]] = metadata$mtUMI/metadata$nUMI se = SingleCellExperiment(assays=list(raw=counts), colData = metadata) save(se, file = "{counts_dir}/se.rda") """ bcbio-nextgen-1.2.9/bcbio/rnaseq/spikein.py000066400000000000000000000112701415626112400206350ustar00rootroot00000000000000"""Function to counts on the fly the spike in sequences given as a parameter in the yaml file""" import os import pandas as pd # from bcbio.rnaseq import sailfish import bcbio.pipeline.datadict as dd from bcbio.utils import (file_exists, safe_makedir, is_gzipped, partition, rbind) import bcbio.utils as utils from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.pipeline import config_utils from bcbio.rnaseq import sailfish from bcbio.bam import fastq from bcbio.log import logger # from bcbio import bam def run_counts_spikein(data): return [[counts_spikein(data)]] def counts_spikein(data): data = utils.to_single_data(data) samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) salmon_dir = os.path.join(work_dir, "spikein", samplename) fasta_file = dd.get_spikein_fasta(data) if not fasta_file: return data files = dd.get_input_sequence_files(data) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None assert file_exists(fasta_file), "%s was not found, exiting." % fasta_file readlength = fastq.estimate_read_length(fq1) if readlength % 2 == 0: readlength -= 1 kmersize = min(readlength, 31) logger.info("kmersize used for salmon index at spikein quant: %s" % kmersize) kmersize = kmersize if not dd.get_analysis(data).lower() == "smallrna-seq" else 15 fasta_index = _index_spikein(fasta_file, salmon_dir, data, kmersize) out_file = _salmon_quant_reads(fq1, fq2, salmon_dir, fasta_index, data) data = dd.set_spikein_counts(data, out_file) return data def _salmon_quant_reads(fq1, fq2, salmon_dir, index, data): samplename = dd.get_sample_name(data) quant_dir = os.path.join(salmon_dir, "quant") safe_makedir(salmon_dir) out_file = os.path.join(quant_dir, "quant.sf") if file_exists(out_file): return out_file num_cores = dd.get_num_cores(data) salmon = config_utils.get_program("salmon", dd.get_config(data)) num_cores = dd.get_num_cores(data) cmd = ("{salmon} quant --validateMappings -l A -i {index} -p {num_cores} " "-o {tx_out_dir} ") fq1_cmd = "<(cat {fq1})" if not is_gzipped(fq1) else "<(gzip -cd {fq1})" fq1_cmd = fq1_cmd.format(fq1=fq1) if not fq2: cmd += " -r {fq1_cmd} " else: fq2_cmd = "<(cat {fq2})" if not is_gzipped(fq2) else "<(gzip -cd {fq2})" fq2_cmd = fq2_cmd.format(fq2=fq2) cmd += " -1 {fq1_cmd} -2 {fq2_cmd} " with file_transaction(data, quant_dir) as tx_out_dir: message = ("Quantifying transcripts in %s and %s with Salmon." %(fq1, fq2)) do.run(cmd.format(**locals()), message, None) return out_file def _index_spikein(fasta, out_dir, data, kmer=31): out_dir = safe_makedir(os.path.join(out_dir, "index")) salmon = config_utils.get_program("salmon", dd.get_config(data)) num_cores = dd.get_num_cores(data) out_file = os.path.join(out_dir, "versionInfo.json") if file_exists(out_file): return out_dir with file_transaction(out_dir) as tx_out_dir: cmd = "{salmon} index -k {kmer} -p {num_cores} -i {tx_out_dir} -t {fasta}" message = "Creating Salmon index for {fasta}." do.run(cmd.format(**locals()), message.format(**locals()), None) return out_dir def combine_spikein(samples): work_dir = dd.get_in_samples(samples, dd.get_work_dir) sailfish_dir = os.path.join(work_dir, "spikein") dont_combine, to_combine = partition(dd.get_spikein_counts, dd.sample_data_iterator(samples), True) if not to_combine: return samples tidy_file = os.path.join(sailfish_dir, "spikein.sf") if not file_exists(tidy_file): logger.info("Combining count files into %s." % tidy_file) df = pd.DataFrame() for data in to_combine: sailfish_file = dd.get_spikein_counts(data) samplename = dd.get_sample_name(data) new_df = sailfish._sailfish_expression_parser(sailfish_file, samplename) if df.empty: df = new_df else: df = rbind([df, new_df]) df["id"] = df.index # some versions of the transcript annotations can have duplicated entries df = df.drop_duplicates(["id", "sample"]) with file_transaction(tidy_file) as tx_out_file: df.to_csv(tx_out_file, sep="\t", index_label="name") logger.info("Finished combining count files into %s." % tidy_file) updated_samples = [] for data in dd.sample_data_iterator(samples): data = dd.set_spikein_counts(data, tidy_file) updated_samples.append([data]) return updated_samples bcbio-nextgen-1.2.9/bcbio/rnaseq/stringtie.py000066400000000000000000000123701415626112400212050ustar00rootroot00000000000000""" implements support for StringTie, intended to be a drop in replacement for Cufflinks http://ccb.jhu.edu/software/stringtie/ http://www.nature.com/nbt/journal/v33/n3/full/nbt.3122.html manual: http://ccb.jhu.edu/software/stringtie/#contact """ import os import pandas as pd import subprocess import contextlib from distutils.version import LooseVersion from bcbio.provenance import do from bcbio.utils import file_exists from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils import bcbio.pipeline.datadict as dd def _stringtie_expression(bam, data, out_dir="."): """ only estimate expression the Stringtie, do not assemble new transcripts """ gtf_file = dd.get_transcriptome_gtf(data, dd.get_gtf_file(data)) num_cores = dd.get_num_cores(data) error_message = "The %s file for %s is missing. StringTie has an error." stringtie = config_utils.get_program("stringtie", data, default="stringtie") # don't assemble transcripts unless asked exp_flag = ("-e" if "stringtie" not in dd.get_transcript_assembler(data) else "") base_cmd = ("{stringtie} {exp_flag} -b {out_dir} -p {num_cores} -G {gtf_file} " "-o {out_gtf} {bam}") transcript_file = os.path.join(out_dir, "t_data.ctab") exon_file = os.path.join(out_dir, "e_data.ctab") out_gtf = os.path.join(out_dir, "stringtie-assembly.gtf") if file_exists(transcript_file): return exon_file, transcript_file, out_gtf cmd = base_cmd.format(**locals()) do.run(cmd, "Running Stringtie on %s." % bam) assert file_exists(exon_file), error_message % ("exon", exon_file) assert file_exists(transcript_file), error_message % ("transcript", transcript_file) return transcript_file def run_stringtie_expression(data): """ estimate expression from Stringtie, using the bcbio datadict does not do transcriptome assembly """ bam = dd.get_work_bam(data) sample_name = dd.get_sample_name(data) out_dir = os.path.join("stringtie", sample_name) isoform_fpkm = os.path.join(out_dir, sample_name + ".isoform.fpkm") gene_fpkm = os.path.join(out_dir, sample_name + ".fpkm") assembly = os.path.abspath(os.path.join(out_dir, "stringtie-assembly.gtf")) if file_exists(isoform_fpkm) and file_exists(gene_fpkm): data = dd.set_stringtie_dir(data, out_dir) data = dd.set_fpkm(data, gene_fpkm) data = dd.set_fpkm_isoform(data, isoform_fpkm) if "stringtie" in dd.get_transcript_assembler(data): assembled_gtfs = dd.get_assembled_gtf(data) assembled_gtfs.append(assembly) data = dd.set_assembled_gtf(data, assembled_gtfs) return data with file_transaction(data, out_dir) as tx_out_dir: transcript_file = _stringtie_expression(bam, data, tx_out_dir) df = _parse_ballgown(transcript_file) _write_fpkms(df, tx_out_dir, sample_name) data = dd.set_stringtie_dir(data, out_dir) data = dd.set_fpkm(data, gene_fpkm) data = dd.set_fpkm_isoform(data, isoform_fpkm) if "stringtie" in dd.get_transcript_assembler(data): assembled_gtfs = dd.get_assembled_gtf(data) assembled_gtfs.append(assembly) data = dd.set_assembled_gtf(data, assembled_gtfs) return data def _write_fpkms(df, out_dir, sample_name): transcript_file = os.path.join(out_dir, sample_name + ".isoform.fpkm") transcripts = df[["t_name", "FPKM"]] transcripts.to_csv(transcript_file, sep="\t", header=False, index=False) # sum of transcript FPKM is the gene FPKM gene_file = os.path.join(out_dir, sample_name + ".fpkm") genes = df[["gene_id", "FPKM"]].groupby(['gene_id']).sum() genes.to_csv(gene_file, sep="\t", header=False, index=True) return transcript_file, gene_file def _parse_ballgown(in_file): return(pd.read_csv(in_file, header=0, sep="\t")) def merge(to_merge, ref_file, gtf_file, num_cores, data): stringtie = config_utils.get_program("stringtie", data, default="stringtie") gtf_list = " ".join(to_merge) out_dir = os.path.join("assembly", "stringtie-merge") merged_file = os.path.join(out_dir, "merged.gtf") cmd = "{stringtie} --merge -o {tx_merged_file} -G {gtf_file} {gtf_list}" if not file_exists(merged_file): with file_transaction(merged_file) as tx_merged_file: message = "Merging transcriptome assemblies with Stringtie." do.run(cmd.format(**locals()), message) return merged_file def version(data): stringtie = config_utils.get_program("stringtie", data, default="stringtie") cmd = "%s --version" % stringtie subp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) with contextlib.closing(subp.stdout) as stdout: for line in stdout: version = line.decode().strip() return LooseVersion(version) def supports_merge(data): """ 1.2.0 and up supports the --merge option and a planned utility gffcompare (https://github.com/gpertea/stringtie/issues/29) will add the class codes which will remove the need for cufflinks merge """ gffcompare_installed = config_utils.program_installed("gffcompare", data) return version(data) >= LooseVersion("1.2.0") and gffcompare_installed bcbio-nextgen-1.2.9/bcbio/rnaseq/umi.py000066400000000000000000000475161415626112400200010ustar00rootroot00000000000000""" Unique Molecular Identifier (UMI) handling Most of this either uses Valentine Svennson's umis repository or adapts code written from it. https://github.com/vals/umis """ import pandas as pd import scipy.io import os import copy import glob import sys import subprocess from itertools import repeat, islice from distutils.version import LooseVersion import bcbio.pipeline.datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio import utils from bcbio.utils import (file_exists, safe_makedir) from bcbio.distributed.transaction import file_transaction from bcbio.bam.fastq import open_fastq from bcbio.log import logger from bcbio.rnaseq import gtf import six class SparseMatrix(object): def __init__(self, matrix=None, rownames=None, colnames=None): self.matrix = matrix self.rownames = rownames self.colnames = colnames def __repr__(self): return "%d x %d matrix of class %s" %(len(self.rownames), len(self.colnames), type(self.matrix)) def read(self, filename, rowprefix=None, colprefix=None, delim=":"): """read a sparse matrix, loading row and column name files. if specified, will add a prefix to the row or column names""" self.matrix = scipy.io.mmread(filename) with open(filename + ".rownames") as in_handle: self.rownames = [x.strip() for x in in_handle] if rowprefix: self.rownames = [rowprefix + delim + x for x in self.rownames] with open(filename + ".colnames") as in_handle: self.colnames = [x.strip() for x in in_handle] if colprefix: self.colnames = [colprefix + delim + x for x in self.colnames] def write(self, filename): """read a sparse matrix, loading row and column name files""" if file_exists(filename): return filename out_files = [filename, filename + ".rownames", filename + ".colnames"] with file_transaction(out_files) as tx_out_files: with open(tx_out_files[0], "wb") as out_handle: scipy.io.mmwrite(out_handle, scipy.sparse.csr_matrix(self.matrix)) pd.Series(self.rownames).to_csv(tx_out_files[1], index=False, header=False) pd.Series(self.colnames).to_csv(tx_out_files[2], index=False, header=False) return filename def cat(self, newsm, byrow=False): if self.matrix is None: self.matrix = newsm.matrix self.colnames = newsm.colnames self.rownames = newsm.rownames else: catter = scipy.sparse.vstack if byrow else scipy.sparse.hstack self.matrix = catter((self.matrix, newsm.matrix)) if byrow: self.rownames = self.rownames + newsm.rownames else: self.colnames = self.colnames + newsm.colnames TRANSFORM_DIR = os.path.join(os.path.dirname(__file__), os.pardir, "data", "umis") TRANSFORM_FILES = glob.glob(os.path.join(TRANSFORM_DIR, "*-transform.json")) SUPPORTED_TRANSFORMS = set([os.path.basename(x).replace("-transform.json", "") for x in TRANSFORM_FILES]) def is_supported_transform(data): return dd.get_umi_type(data) in SUPPORTED_TRANSFORMS def get_transform_file(stem): transform_file = os.path.join(TRANSFORM_DIR, stem + "-transform.json") return transform_file def get_cellular_barcodes(data): if dd.get_cellular_barcodes(data): return dd.get_cellular_barcodes(data) if is_supported_transform(data): stem = dd.get_umi_type(data) bc1 = os.path.join(TRANSFORM_DIR, stem + "-cb1.txt.gz") bc2 = os.path.join(TRANSFORM_DIR, stem + "-cb2.txt.gz") bc3 = os.path.join(TRANSFORM_DIR, stem + "-cb3.txt.gz") return list(filter(file_exists, [bc1, bc2, bc3])) else: return [] def get_sample_barcodes(fn, out_dir): if not fn: logger.error("Sample demultiplexing needs a list of known indexes provided " "with via the sample_barcodes option in the algorithm section.") sys.exit(1) utils.safe_makedir(out_dir) out_fn = os.path.join(out_dir, "barcodes.csv") with open(fn) as inh: with open(out_fn, 'w') as outh: for line in inh: outh.write("%s\n" % (line.strip().split(",")[0])) return out_fn def _umis_cmd(data): """Return umis command line argument, with correct python and locale. """ return "%s %s %s" % (utils.locale_export(), utils.get_program_python("umis"), config_utils.get_program("umis", data["config"], default="umis")) def umi_transform(data): """ transform each read by identifying the barcode and UMI for each read and putting the information in the read name """ fqfiles = data["files"] fqfiles.extend(list(repeat("", 4-len(fqfiles)))) fq1, fq2, fq3, fq4 = fqfiles umi_dir = os.path.join(dd.get_work_dir(data), "umis") safe_makedir(umi_dir) transform = dd.get_umi_type(data) if not transform: logger.info("No UMI transform specified, assuming pre-transformed data.") if is_transformed(fq1): logger.info("%s detected as pre-transformed, passing it on unchanged." % fq1) data["files"] = [fq1] return [[data]] else: logger.error("No UMI transform was specified, but %s does not look " "pre-transformed." % fq1) sys.exit(1) if file_exists(transform): transform_file = transform else: transform_file = get_transform_file(transform) if not file_exists(transform_file): logger.error( "The UMI transform can be specified as either a file or a " "bcbio-supported transform. Either the file %s does not exist " "or the transform is not supported by bcbio. Supported " "transforms are %s." %(dd.get_umi_type(data), ", ".join(SUPPORTED_TRANSFORMS))) sys.exit(1) out_base = dd.get_sample_name(data) + ".umitransformed.fq.gz" out_file = os.path.join(umi_dir, out_base) if file_exists(out_file): data["files"] = [out_file] return [[data]] cellular_barcodes = get_cellular_barcodes(data) if len(cellular_barcodes) > 1: split_option = "--separate_cb" else: split_option = "" if dd.get_demultiplexed(data): demuxed_option = "--demuxed_cb %s" % dd.get_sample_name(data) split_option = "" else: demuxed_option = "" cores = dd.get_num_cores(data) # skip transformation if the file already looks transformed with open_fastq(fq1) as in_handle: read = next(in_handle) if "UMI_" in read: data["files"] = [out_file] return [[data]] locale_export = utils.locale_export() umis = _umis_cmd(data) cmd = ("{umis} fastqtransform {split_option} {transform_file} " "--cores {cores} {demuxed_option} " "{fq1} {fq2} {fq3} {fq4}" "| seqtk seq -L 20 - | gzip > {tx_out_file}") message = ("Inserting UMI and barcode information into the read name of %s" % fq1) with file_transaction(out_file) as tx_out_file: do.run(cmd.format(**locals()), message) data["files"] = [out_file] return [[data]] def filter_barcodes(data): # if data was pre-demultiplexed, there is no need to filter the barcodes if dd.get_demultiplexed(data): return [[data]] fq1 = dd.get_input_sequence_files(data)[0] umi_dir = os.path.join(dd.get_work_dir(data), "umis") correction = dd.get_cellular_barcode_correction(data) bc = get_cellular_barcodes(data) if not bc: logger.info("No cellular barcodes found, skipping filtering.") return [[data]] bc1 = None bc2 = None bc3 = None umi_dir = os.path.join(dd.get_work_dir(data), "umis") if isinstance(bc, six.string_types): bc1 = bc if len(bc) == 1: bc1 = bc[0] if len(bc) > 1: bc1 = bc[0] bc2 = bc[1] if len(bc) == 3: bc3 = bc[2] out_base = dd.get_sample_name(data) + ".filtered.fq.gz" out_file = os.path.join(umi_dir, out_base) if file_exists(out_file): data["files"] = [out_file] return [[data]] ncores = dd.get_num_cores(data) umis = _umis_cmd(data) cmd = "{umis} cb_filter --cores {ncores} " if bc1: cmd += "--bc1 {bc1} " if correction: cmd += "--nedit {correction} " if bc2: cmd += "--bc2 {bc2} " if bc3: cmd += "--bc3 {bc3} " fq1_cmd = "{fq1} " fq1_cmd = fq1_cmd.format(fq1=fq1) cmd += "{fq1_cmd} | gzip -c > {tx_out_file}" sample_dir = os.path.join(umi_dir, dd.get_sample_name(data)) safe_makedir(sample_dir) with file_transaction(out_file) as tx_out_file: message = "Filtering by cellular barcode." do.run(cmd.format(**locals()), message) data["files"] = [out_file] return [[data]] def barcode_histogram(data): fq1 = dd.get_input_sequence_files(data)[0] umi_dir = os.path.join(dd.get_work_dir(data), "umis") sample_dir = os.path.join(umi_dir, dd.get_sample_name(data)) safe_makedir(sample_dir) out_file = os.path.join(sample_dir, "cb-histogram.txt") filtered_out_file = os.path.join(sample_dir, "cb-histogram-filtered.txt") fq1_cmd = fq1 umis = _umis_cmd(data) cmd = "{umis} cb_histogram {fq1_cmd} > {tx_out_file}" if not file_exists(out_file): with file_transaction(out_file) as tx_out_file: message = "Computing cellular barcode counts for %s." % fq1 do.run(cmd.format(**locals()), message) cutoff = dd.get_minimum_barcode_depth(data) filter_barcode_histogram(filtered_out_file, out_file, cutoff) newdata = dd.set_histogram_counts(data, filtered_out_file) return [[newdata]] def tagcount(data): bam = dd.get_transcriptome_bam(data) umi_dir = os.path.join(dd.get_work_dir(data), "umis") sample_dir = os.path.join(umi_dir, dd.get_sample_name(data)) out_prefix = os.path.join(sample_dir, dd.get_sample_name(data)) out_file = out_prefix + ".mtx" if file_exists(out_file): data = dd.set_count_file(data, out_file) return [[data]] safe_makedir(sample_dir) cutoff = dd.get_minimum_barcode_depth(data) cb_histogram = os.path.join(sample_dir, "cb-histogram.txt") positional = "--positional" if dd.get_positional_umi(data, False) else "" if use_installed_transcriptome(data): gtf_file = dd.get_gtf_file(data) else: gtf_file = dd.get_transcriptome_gtf(data, None) if gtf_file: gene_map_file = os.path.join(dd.get_work_dir(data), "annotation", os.path.basename(os.path.splitext(gtf_file)[0]) + "-tx2gene.tsv") gene_map_file = gtf.tx2genefile(gtf_file, gene_map_file, tsv=True) gene_map_flag = " --genemap {0} ".format(gene_map_file) else: gene_map_flag = "" message = "Counting alignments of transcripts in %s." % bam umis = _umis_cmd(data) cmd = ("{umis} fasttagcount --cb_cutoff {cutoff} " "{gene_map_flag} " "{positional} " "--cb_histogram {cb_histogram}") out_files = [out_file, out_file + ".rownames", out_file + ".colnames"] umi_matrix_file = out_prefix + "-dupes.mtx" out_files += [umi_matrix_file, umi_matrix_file + ".rownames", umi_matrix_file + ".colnames"] if has_umi_matrix(data): umi_matrix_flag = " --umi_matrix {tx_umi_matrix_full} " else: umi_matrix_flag = "" cmd += umi_matrix_flag cmd += " {bam} {tx_out_file_full}" with file_transaction(out_files) as tx_out_files: tx_out_file = tx_out_files[0] tx_out_file_full = tx_out_file + ".full" tx_umi_matrix = tx_out_files[3] tx_umi_matrix_full = tx_out_files[3] + ".full" do.run(cmd.format(**locals()), message) cmd = ("{umis} sparse {tx_out_file_full} {tx_out_file}") message = "Converting %s to sparse format." % tx_out_file_full do.run(cmd.format(**locals()), message) if has_umi_matrix(data): cmd = ("{umis} sparse {tx_umi_matrix_full} {tx_umi_matrix}") message = "Converting %s to sparse format." % tx_umi_matrix_full do.run(cmd.format(**locals()), message) data = dd.set_count_file(data, out_file) return [[data]] def get_barcode_metadata(data): barcode_file = dd.get_barcode_file(data) df = pd.read_csv(barcode_file, sep=",", header=0) barcodes = df["barcodes"] def convert_to_kallisto(data): files = dd.get_input_sequence_files(data) if len(files) == 2: fq1, fq2 = files else: fq1, fq2 = files[0], None samplename = dd.get_sample_name(data) work_dir = dd.get_work_dir(data) kallisto_dir = os.path.join(work_dir, "kallisto", samplename, "fastq") out_file = os.path.join(kallisto_dir, "barcodes.batch") umis = _umis_cmd(data) if file_exists(out_file): return out_file if dd.get_minimum_barcode_depth(data): cb_histogram = os.path.join(work_dir, "umis", samplename, "cb-histogram.txt") cb_cutoff = dd.get_minimum_barcode_depth(data) cb_options = "--cb_histogram {cb_histogram} --cb_cutoff {cb_cutoff}" cb_options = cb_options.format(**locals()) else: cb_options = "" cmd = ("{umis} kallisto {cb_options} --out_dir {tx_kallisto_dir} {fq1}") with file_transaction(data, kallisto_dir) as tx_kallisto_dir: safe_makedir(tx_kallisto_dir) message = ("Transforming %s to Kallisto singlecell format. " % fq1) do.run(cmd.format(**locals()), message) return out_file def demultiplex_samples(data): """ demultiplex a fastqtransformed FASTQ file into separate sample barcode files """ work_dir = os.path.join(dd.get_work_dir(data), "umis") sample_dir = os.path.join(work_dir, dd.get_sample_name(data)) demulti_dir = os.path.join(sample_dir, "demultiplexed") files = data["files"] if len(files) == 2: logger.error("Sample demultiplexing doesn't handle paired-end reads, but " "we can add it. Open an issue here https://github.com/bcbio/bcbio-nextgen/issues if you need this and we'll add it.") sys.exit(1) else: fq1 = files[0] # check if samples need to be demultiplexed with open_fastq(fq1) as in_handle: read = next(in_handle) if "SAMPLE_" not in read: return [[data]] bcfile = get_sample_barcodes(dd.get_sample_barcodes(data), sample_dir) demultiplexed = glob.glob(os.path.join(demulti_dir, "*.fq*")) if demultiplexed: return [split_demultiplexed_sampledata(data, demultiplexed)] umis = _umis_cmd(data) cmd = ("{umis} demultiplex_samples --nedit 1 --barcodes {bcfile} " "--out_dir {tx_dir} {fq1}") msg = "Demultiplexing {fq1}." with file_transaction(data, demulti_dir) as tx_dir: do.run(cmd.format(**locals()), msg.format(**locals())) demultiplexed = glob.glob(os.path.join(demulti_dir, "*.fq*")) return [split_demultiplexed_sampledata(data, demultiplexed)] def split_demultiplexed_sampledata(data, demultiplexed): """ splits demultiplexed samples into separate entries in the global sample datadict """ datadicts = [] samplename = dd.get_sample_name(data) for fastq in demultiplexed: barcode = os.path.basename(fastq).split(".")[0] datadict = copy.deepcopy(data) datadict = dd.set_sample_name(datadict, samplename + "-" + barcode) datadict = dd.set_description(datadict, samplename + "-" + barcode) datadict["rgnames"]["rg"] = samplename + "-" + barcode datadict["name"]= ["", samplename + "-" + barcode] datadict["files"] = [fastq] datadicts.append(datadict) return datadicts def concatenate_sparse_counts(*samples): samples = concatenate_sparse_matrices(samples, deduped=True) samples = concatenate_sparse_matrices(samples, deduped=False) samples = concatenate_cb_histograms(samples) return samples def concatenate_sparse_matrices(samples, deduped=True): work_dir = dd.get_in_samples(samples, dd.get_work_dir) umi_dir = os.path.join(work_dir, "umis") if deduped: out_file = os.path.join(umi_dir, "tagcounts.mtx") else: out_file = os.path.join(umi_dir, "tagcounts-dupes.mtx") if file_exists(out_file): if deduped: newsamples = [] for data in dd.sample_data_iterator(samples): newsamples.append([dd.set_combined_counts(data, out_file)]) return newsamples else: return samples files = [dd.get_count_file(data) for data in dd.sample_data_iterator(samples) if dd.get_count_file(data)] if not deduped: files = [os.path.splitext(x)[0] + "-dupes.mtx" for x in files] files = [fn for fn in files if file_exists(fn)] descriptions = [dd.get_sample_name(data) for data in dd.sample_data_iterator(samples) if dd.get_count_file(data)] if not files: return samples counts = SparseMatrix() counts.read(filename=files.pop(), colprefix=descriptions.pop()) for filename, description in zip(files, descriptions): newcounts = SparseMatrix() newcounts.read(filename=filename, colprefix=description) counts.cat(newcounts) counts.write(out_file) newsamples = [] if deduped: for data in dd.sample_data_iterator(samples): newsamples.append([dd.set_combined_counts(data, out_file)]) return newsamples return samples def concatenate_cb_histograms(samples): work_dir = dd.get_in_samples(samples, dd.get_work_dir) umi_dir = os.path.join(work_dir, "umis") out_file = os.path.join(umi_dir, "cb-histogram.txt") files = [dd.get_histogram_counts(data) for data in dd.sample_data_iterator(samples) if dd.get_histogram_counts(data)] files = " ".join(files) cmd = "cat {files} > {out_file}" if not file_exists(out_file): with file_transaction(out_file) as tx_out_file: message = "Concat cellular barcode histograms: %s." % files do.run(cmd.format(**locals()), message) newsamples = [] for data in dd.sample_data_iterator(samples): newsamples.append([dd.set_combined_histogram(data, out_file)]) return newsamples def version(data): umis = _umis_cmd(data) version_cmd = "%s version" % umis try: output = subprocess.check_output(version_cmd, shell=True).decode().strip() except: output = None return output def has_umi_matrix(data): umis_version = version(data) if not version: return False return LooseVersion(umis_version) >= "1.0.0" def filter_barcode_histogram(filtered_out_file, out_file, cutoff): if file_exists(filtered_out_file): return filtered_out_file sample_name = os.path.basename(os.path.dirname(out_file)) with file_transaction(filtered_out_file) as tx_out_file: with open(tx_out_file, "w") as outh: with open(out_file) as inh: for line in inh: barcode, reads = line.strip().split() if int(reads) > cutoff: outh.write("%s-%s\t%s\n" % (sample_name, barcode, reads)) return filtered_out_file def is_transformed(fastq): """ check the first 100 reads to see if a FASTQ file has already been transformed by umis """ with open_fastq(fastq) as in_handle: for line in islice(in_handle, 400): if "UMI_" in line: return True return False def use_installed_transcriptome(data): user_fa = dd.get_transcriptome_fasta(data) user_gtf = dd.get_transcriptome_gtf(data) if not user_fa and not user_gtf: return True else: return False bcbio-nextgen-1.2.9/bcbio/rnaseq/variation.py000066400000000000000000000232331415626112400211710ustar00rootroot00000000000000import os from bcbio import utils from bcbio.utils import file_exists, get_R_exports from bcbio.bam import ref from bcbio.heterogeneity import chromhacks import bcbio.pipeline.datadict as dd from bcbio.pipeline import config_utils, shared from bcbio.ngsalign.postalign import dedup_bam from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.variation import vardict from bcbio import broad, bam from bcbio.variation import gatk, vcfutils from bcbio.structural import regions from bcbio.variation.bedutils import get_padded_bed_file from bcbio.log import logger pybedtools = utils.LazyImport("pybedtools") def rnaseq_gatk_variant_calling(data): data = dd.set_deduped_bam(data, dedup_bam(dd.get_work_bam(data), data)) data = gatk_splitreads(data) data = gatk_rnaseq_calling(data) return data def gatk_splitreads(data): """ use GATK to split reads with Ns in the CIGAR string, hard clipping regions that end up in introns """ broad_runner = broad.runner_from_config(dd.get_config(data)) ref_file = dd.get_ref_file(data) deduped_bam = dd.get_deduped_bam(data) base, ext = os.path.splitext(deduped_bam) split_bam = base + ".splitN" + ext if file_exists(split_bam): data = dd.set_split_bam(data, split_bam) return data gatk_type = broad_runner.gatk_type() with file_transaction(data, split_bam) as tx_split_bam: params = ["-T", "SplitNCigarReads", "-R", ref_file, "-I", deduped_bam] if gatk_type == "gatk4": params += ["--output", tx_split_bam] else: params += ["-rf", "ReassignOneMappingQuality", "-RMQF", "255", "-RMQT", "60", "-rf", "UnmappedRead", "-U", "ALLOW_N_CIGAR_READS", "-o", tx_split_bam] if dd.get_quality_format(data) == "illumina": params += ["--fix_misencoded_quality_scores", "-fixMisencodedQuals"] broad_runner.run_gatk(params) bam.index(split_bam, dd.get_config(data)) data = dd.set_split_bam(data, split_bam) return data def _setup_variant_regions(data, out_dir): """Ensure we have variant regions for calling, using transcript if not present. Respects noalt_calling by removing additional contigs to improve speeds. """ vr_file = dd.get_variant_regions(data) if not vr_file: vr_file = regions.get_sv_bed(data, "transcripts", out_dir=out_dir) contigs = set([c.name for c in ref.file_contigs(dd.get_ref_file(data))]) out_file = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "bedprep")), "%s-rnaseq_clean.bed" % utils.splitext_plus(os.path.basename(vr_file))[0]) if not utils.file_uptodate(out_file, vr_file): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: with shared.bedtools_tmpdir(data): for r in pybedtools.BedTool(vr_file): if r.chrom in contigs: if chromhacks.is_nonalt(r.chrom): out_handle.write(str(r)) data = dd.set_variant_regions(data, out_file) return data def gatk_rnaseq_calling(data): """Use GATK to perform gVCF variant calling on RNA-seq data """ from bcbio.bam import callable data = utils.deepish_copy(data) tools_on = dd.get_tools_on(data) if not tools_on: tools_on = [] tools_on.append("gvcf") data = dd.set_tools_on(data, tools_on) data = dd.set_jointcaller(data, ["%s-joint" % v for v in dd.get_variantcaller(data)]) out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "variation", "rnaseq", "gatk-haplotype")) data = _setup_variant_regions(data, out_dir) out_file = os.path.join(out_dir, "%s-gatk-haplotype.vcf.gz" % dd.get_sample_name(data)) if not utils.file_exists(out_file): region_files = [] regions = [] for cur_region in callable.get_split_regions(dd.get_variant_regions(data), data): str_region = "_".join([str(x) for x in cur_region]) region_file = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "variation", "rnaseq", "gatk-haplotype", "regions")), "%s-%s-gatk-haplotype.vcf.gz" % (dd.get_sample_name(data), str_region)) region_file = gatk.haplotype_caller([dd.get_split_bam(data)], [data], dd.get_ref_file(data), {}, region=cur_region, out_file=region_file) region_files.append(region_file) regions.append(cur_region) out_file = vcfutils.concat_variant_files(region_files, out_file, regions, dd.get_ref_file(data), data["config"]) return dd.set_vrn_file(data, out_file) def rnaseq_vardict_variant_calling(data): sample = dd.get_sample_name(data) out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "variation", "rnaseq", "vardict")) out_file = os.path.join(out_dir, sample + "-vardict.vcf.gz") if file_exists(out_file): data = dd.set_vrn_file(data, out_file) return data vardict_cmd = vardict.get_vardict_command(data) strandbias = "teststrandbias.R" var2vcf = "var2vcf_valid.pl" vcfstreamsort = config_utils.get_program("vcfstreamsort", data) compress_cmd = "| bgzip -c" freq = float(dd.get_min_allele_fraction(data, 20) / 100.0) var2vcf_opts = "-v 50" fix_ambig = vcfutils.fix_ambiguous_cl() remove_dup = vcfutils.remove_dup_cl() r_setup = get_R_exports() ref_file = dd.get_ref_file(data) bamfile = dd.get_work_bam(data) data = _setup_variant_regions(data, out_dir) opts, _ = vardict._vardict_options_from_config([data], data["config"], out_file, dd.get_variant_regions(data), is_rnaseq=True) cores = dd.get_num_cores(data) if cores and cores > 1: opts += " -th %s" % str(cores) with file_transaction(data, out_file) as tx_out_file: jvm_opts = vardict._get_jvm_opts(data, tx_out_file) cmd = ("{r_setup} && {jvm_opts}{vardict_cmd} -G {ref_file} -f {freq} " "-N {sample} -b {bamfile} {opts} " "| {strandbias}" "| {var2vcf} -N {sample} -E -f {freq} {var2vcf_opts} " "| {fix_ambig} | {remove_dup} | {vcfstreamsort} {compress_cmd} " "> {tx_out_file}") message = "Calling RNA-seq variants with VarDict" do.run(cmd.format(**locals()), message) out_file = vcfutils.bgzip_and_index(out_file, data["config"]) data = dd.set_vrn_file(data, out_file) return data def gatk_filter_rnaseq(vrn_file, data): """ this incorporates filters listed here, dropping clusters of variants within a 35 nucleotide window, high fischer strand values and low quality by depth https://software.broadinstitute.org/gatk/guide/article?id=3891 java -jar GenomeAnalysisTK.jar -T VariantFiltration -R hg_19.fasta -V input.vcf -window 35 -cluster 3 -filterName FS -filter "FS > 30.0" -filterName QD -filter "QD < 2.0" -o output.vcf """ out_file = "%s-filter%s" % utils.splitext_plus(vrn_file) if not file_exists(out_file): ref_file = dd.get_ref_file(data) with file_transaction(data, out_file) as tx_out_file: params = ["VariantFiltration", "-R", ref_file, "-V", vrn_file, "--cluster-window-size", "35", "--cluster-size", "3", "--filter-expression", "'FS > 30.0'", "--filter-name", "FS", "--filter-expression", "'QD < 2.0'", "--filter-name", "QD", "--output", tx_out_file] # Use GATK4 for filtering, tools_off is for variant calling config = utils.deepish_copy(dd.get_config(data)) if "gatk4" in dd.get_tools_off({"config": config}): config["algorithm"]["tools_off"].remove("gatk4") jvm_opts = broad.get_gatk_opts(config, os.path.dirname(tx_out_file)) do.run(broad.gatk_cmd("gatk", jvm_opts, params, config), "Filter RNA-seq variants.") return out_file def filter_junction_variants(vrn_file, data): """ filter out variants within 10 basepairs of a splice junction, these are very prone to being false positives with RNA-seq data """ SJ_BP_MASK = 10 vrn_dir = os.path.dirname(vrn_file) splicebed = dd.get_junction_bed(data) if not file_exists(splicebed): logger.info("Splice junction BED file not found, skipping filtering of " "variants closed to splice junctions.") return vrn_file spliceslop = get_padded_bed_file(vrn_dir, splicebed, SJ_BP_MASK, data) out_file = os.path.splitext(vrn_file)[0] + "-junctionfiltered.vcf.gz" if file_exists(out_file): return out_file with file_transaction(data, out_file) as tx_out_file: out_base = os.path.splitext(tx_out_file)[0] logger.info("Removing variants within %d bases of splice junctions listed in %s from %s. " % (SJ_BP_MASK, spliceslop, vrn_file)) pybedtools.BedTool(vrn_file).intersect(spliceslop, wa=True, header=True, v=True).saveas(out_base) tx_out_file = vcfutils.bgzip_and_index(out_base, dd.get_config(data)) return out_file bcbio-nextgen-1.2.9/bcbio/scripts/000077500000000000000000000000001415626112400170165ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/scripts/R/000077500000000000000000000000001415626112400172175ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/scripts/R/bcbio2se.R000066400000000000000000000044421415626112400210360ustar00rootroot00000000000000# create SummarizedExperiment object (se) from bcbio output # usage: # Rscript bcbio2se.R work_dir out_file # output: out_file a RDS file with the SE object in it # needs work/metadata.csv provided by qcsummary._merge_metadata() library(tidyverse) library(tximport) library(SummarizedExperiment) library(janitor) library(DESeq2) args <- commandArgs(trailingOnly = T) work_dir <- args[1] out_file <- args[2] metadata <- read_csv(file.path(work_dir, "metadata.csv")) colnames(metadata)[1] <- "sample" metadata$sample = make_clean_names(metadata$sample) if (! "category" %in% colnames(metadata)){ metadata$category <- "fake_category" } metrics <- read_tsv(file.path(work_dir, "qc", "multiqc", "multiqc_data", "multiqc_bcbio_metrics.txt")) %>% clean_names(case = "snake") salmon_dir = file.path(work_dir, "salmon") salmon_files = file.path(salmon_dir, metrics$sample, "quant.sf") metrics$sample = make_clean_names(metrics$sample) names(salmon_files) = metrics$sample # we need replicates to create SE object if (nrow(metrics) < 2){ stop(paste0("Too few samples to create SE object: ", nrow(metrics))) } transcripts2genes_file <- file.path(work_dir, "inputs", "transcriptome", "tx2gene.csv") transcripts2genes <- read_csv(transcripts2genes_file, col_names = c("transcript_id", "gene_id")) txi_salmon <- tximport(salmon_files, type = "salmon", tx2gene = transcripts2genes, countsFromAbundance = "lengthScaledTPM", dropInfReps=TRUE) col_data <- metadata %>% column_to_rownames(var = "sample") col_data$sample <- rownames(col_data) col_data = col_data[names(salmon_files),] raw_counts <- round(data.frame(txi_salmon$counts, check.names = FALSE), 0) %>% as.matrix() se_metadata <- list(metrics = metrics, countsFromAbundance = txi_salmon$countsFromAbundance) vst <- vst(raw_counts) se <- SummarizedExperiment(assays = list(raw = raw_counts, tpm = txi_salmon$abundance, length = txi_salmon$length, vst = vst), colData = col_data, metadata = se_metadata) saveRDS(se, out_file) bcbio-nextgen-1.2.9/bcbio/scripts/R/se2qc.Rmd000066400000000000000000000150741415626112400207070ustar00rootroot00000000000000--- title: "Quality Control" author: "bcbio" date: "`r Sys.Date()`" output: html_document: code_folding: hide df_print: paged highlights: pygments number_sections: true self_contained: true theme: default toc: true toc_float: collapsed: true smooth_scroll: true params: rds_file: bcbio-se.rds --- # Overview - Principal Investigator: - Researcher - Experiment: ```{r, cache = FALSE, message = FALSE} library(tidyverse) library(knitr) library(DESeq2) library(DEGreport) library(ggrepel) ggplot2::theme_set(theme_light(base_size = 14)) opts_chunk[["set"]]( cache = FALSE, dev = c("png", "pdf"), error = TRUE, highlight = TRUE, message = FALSE, prompt = FALSE, tidy = FALSE, warning = FALSE) ``` # Metadata ```{r show-metadata} se <- readRDS(params$rds_file) metadata <- colData(se) %>% as_tibble(rownames = NULL) %>% select(sample, category) metrics <- metadata(se)$metrics %>% left_join(metadata, by = c("sample" = "sample")) metadata ``` # Read metrics {.tabset} ## Total reads ```{r plot_total_reads} metrics %>% ggplot(aes(x = reorder(sample, -total_reads), y = total_reads/1e6L, fill = category)) + geom_bar(stat = "identity") + coord_flip() + scale_y_continuous(name = "mln reads") + geom_text(aes(label = floor(total_reads/1e6L)), hjust = 0, nudge_y = 0.5)+ xlab("sample") + ggtitle("Total reads") ``` ## Mapped reads The number of mapped reads should correspond to the number of total reads. ```{r plot_mapped_reads} metrics %>% ggplot(aes(x = reorder(sample, -mapped_reads), y = mapped_reads, fill = category)) + geom_bar(stat = "identity") + coord_flip() + scale_y_continuous(name = "mln reads") + geom_text(aes(label = floor(total_reads/1e6L)), hjust = 0, nudge_y = 0.5)+ xlab("sample") + ggtitle("Mapped reads") ``` ## Mapping rate The genomic mapping rate represents the percentage of reads mapping to the reference genome. Low mapping rates are indicative of sample contamination, poor sequencing quality or other artifacts. ```{r plot_mapping_rate} metrics$mapped_reads_pct <- metrics$mapped_reads/metrics$total_reads metrics %>% ggplot(aes(x = reorder(sample, -mapped_reads_pct), y = mapped_reads_pct, fill = category)) + geom_bar(stat = "identity") + coord_flip() + geom_text(aes(label = floor(mapped_reads_pct)), hjust = 0, nudge_y = 0.5)+ xlab("sample") + ggtitle("Mapping rate") ``` ## Number of genes detected ```{r plot_genes_detected} genes_detected <- colSums(assays(se)[["raw"]] > 0) %>% enframe() colnames(genes_detected) <- c("sample", "n_genes") metrics <- metrics %>% left_join(genes_detected, by = c("sample" = "sample")) metrics %>% ggplot(aes(x = reorder(sample, -n_genes), y = n_genes, fill = category)) + geom_bar(stat = "identity") + coord_flip() + geom_text(aes(label = n_genes), hjust = 0, nudge_y = 0.5)+ xlab("sample") + ylim(0, 30000) + ggtitle("Number of genes") ``` ## Gene detection saturation We should observe a linear trend in the number of genes detected with the number of mapped reads, which indicates that the sample input was not overloaded. ```{r plot_gene_saturation} metrics %>% ggplot(aes(x = log10(total_reads), y = n_genes, color = category)) + geom_point()+ geom_text_repel(aes(label = sample))+ ggtitle("Gene saturation") ``` ## Exonic mapping rate Ideally, at least 60% of total reads should map to exons. ```{r plot_exonic_mapping_rate} metrics %>% ggplot(aes(x = reorder(sample, -exonic_rate), y = exonic_rate * 100, fill = category)) + geom_bar(stat = "identity") + geom_text(aes(label = floor(exonic_rate*100)), hjust = 0, nudge_y = 0.5)+ xlab("sample") + ylab("Exonic rate %") + ggtitle("Exonic mapping rate") + coord_flip() ``` ## Intronic mapping rate The majority of reads should map to exons and not introns. ```{r plot_intronic_mapping_rate} metrics %>% ggplot(aes(x = reorder(sample, -intronic_rate), y = intronic_rate * 100, fill = category)) + geom_bar(stat = "identity") + geom_text(aes(label = floor(intronic_rate*100)), hjust = 0, nudge_y = 0.5)+ xlab("sample") + ylab("Intronic rate %") ggtitle("Intronic mapping rate") + coord_flip() ``` ## rRNA mapping rate Samples should have a ribosomal RNA (rRNA) contamination rate below 10%. ```{r plot_rrna_mapping_rate} # for some bad samples it could be > 50% rrna_ylim <- max(round(metrics$r_rna_rate*100, 2)) + 10 metrics %>% ggplot(aes(x = reorder(sample, -r_rna_rate), y = r_rna_rate * 100, fill = category)) + geom_bar(stat = "identity") + geom_text(aes(label = round(r_rna_rate*100,2)), hjust = 0, nudge_y = 0.5)+ xlab("sample") + ylab("rRNA rate, %")+ ylim(0, rrna_ylim) + ggtitle("rRNA mapping rate") + coord_flip() ``` ## 5'->3' bias ```{r plot_53_bias} metrics %>% ggplot(aes(x = reorder(sample, -x5_3_bias), y = x5_3_bias, fill = category)) + geom_bar(stat = "identity") + geom_text(aes(label = x5_3_bias), hjust = 0, nudge_y = 0.01)+ xlab("sample") + ylim(0, 1.1)+ ggtitle("5'-3' bias") + coord_flip() ``` ## Counts per gene - all genes We expected similar spread for every sample. ```{r plot_counts_per_gene} metrics_small <- metrics %>% select(sample, category) assays(se)[["raw"]] %>% as_tibble() %>% filter(rowSums(.)!=0) %>% gather(sample, counts) %>% left_join(metadata, by = c("sample" = "sample")) %>% ggplot(aes(sample, log2(counts+1), fill = category)) + geom_boxplot() + coord_flip() + ggtitle("Counts per gene, all non-zero genes") ``` # Sample similarity analysis ## Principal component analysis (PCA) - non zero genes ```{r pca} raw_counts <- assays(se)[["raw"]] %>% as_tibble() %>% filter(rowSums(.)!=0) %>% as.matrix() vst <- vst(raw_counts) pca <- degPCA(vst, colData(se), condition = "category", name = "sample", data = T)[["plot"]] pca_labels <- pca[["labels"]] pca_data <- pca[["data"]] %>% as_tibble() %>% select(sample, PC1, PC2, category) pca_data %>% ggplot(aes(x = PC1, y = PC2, color = category, label = sample)) + geom_point() + geom_text_repel() + xlab(pca_labels$x) + ylab(pca_labels$y) + ggtitle(paste0("PCA: ", nrow(vst), " genes")) ``` # R session ```{r} sessionInfo() ```bcbio-nextgen-1.2.9/bcbio/server/000077500000000000000000000000001415626112400166355ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/server/__init__.py000066400000000000000000000001101415626112400207360ustar00rootroot00000000000000"""Provide a web server allowing remote execution and status query. """ bcbio-nextgen-1.2.9/bcbio/server/background.py000066400000000000000000000112561415626112400213330ustar00rootroot00000000000000"""Provide asynchronous background running of subprocesses. Modified from: https://github.com/vukasin/tornado-subprocess - Do not store all stdout/stderr, instead print out to avoid filling up buffer Copyright (c) 2012, Vukasin Toroman """ from __future__ import print_function import subprocess import tornado.ioloop import time import fcntl import functools import os class GenericSubprocess (object): def __init__ ( self, timeout=-1, **popen_args ): self.args = dict() self.args["stdout"] = subprocess.PIPE self.args["stderr"] = subprocess.PIPE self.args["close_fds"] = True self.args.update(popen_args) self.ioloop = None self.expiration = None self.pipe = None self.timeout = timeout self.streams = [] self.has_timed_out = False def start(self): """Spawn the task. Throws RuntimeError if the task was already started.""" if not self.pipe is None: raise RuntimeError("Cannot start task twice") self.ioloop = tornado.ioloop.IOLoop.instance() if self.timeout > 0: self.expiration = self.ioloop.add_timeout( time.time() + self.timeout, self.on_timeout ) self.pipe = subprocess.Popen(**self.args) self.streams = [ (self.pipe.stdout.fileno(), []), (self.pipe.stderr.fileno(), []) ] for fd, d in self.streams: flags = fcntl.fcntl(fd, fcntl.F_GETFL)| os.O_NDELAY fcntl.fcntl( fd, fcntl.F_SETFL, flags) self.ioloop.add_handler( fd, self.stat, self.ioloop.READ|self.ioloop.ERROR) def on_timeout(self): self.has_timed_out = True self.cancel() def cancel (self ) : """Cancel task execution Sends SIGKILL to the child process.""" try: self.pipe.kill() except: pass def stat( self, *args ): '''Check process completion and consume pending I/O data''' self.pipe.poll() if not self.pipe.returncode is None: '''cleanup handlers and timeouts''' if not self.expiration is None: self.ioloop.remove_timeout(self.expiration) for fd, dest in self.streams: self.ioloop.remove_handler(fd) '''schedulle callback (first try to read all pending data)''' self.ioloop.add_callback(self.on_finish) for fd, dest in self.streams: while True: try: data = os.read(fd, 4096) if len(data) == 0: break print(data.rstrip()) except: break @property def stdout(self): return self.get_output(0) @property def stderr(self): return self.get_output(1) @property def status(self): return self.pipe.returncode def get_output(self, index ): return "".join(self.streams[index][1]) def on_finish(self): raise NotImplemented() class Subprocess (GenericSubprocess): """Create new instance Arguments: callback: method to be called after completion. This method should take 3 arguments: statuscode(int), stdout(str), stderr(str), has_timed_out(boolean) timeout: wall time allocated for the process to complete. After this expires Task.cancel is called. A negative timeout value means no limit is set The task is not started until start is called. The process will then be spawned using subprocess.Popen(**popen_args). The stdout and stderr are always set to subprocess.PIPE. """ def __init__ ( self, callback, *args, **kwargs): """Create new instance Arguments: callback: method to be called after completion. This method should take 3 arguments: statuscode(int), stdout(str), stderr(str), has_timed_out(boolean) timeout: wall time allocated for the process to complete. After this expires Task.cancel is called. A negative timeout value means no limit is set The task is not started until start is called. The process will then be spawned using subprocess.Popen(**popen_args). The stdout and stderr are always set to subprocess.PIPE. """ self.callback = callback self.done_callback = False GenericSubprocess.__init__(self, *args, **kwargs) def on_finish(self): if not self.done_callback: self.done_callback = True '''prevent calling callback twice''' self.ioloop.add_callback(functools.partial(self.callback, self.status, self.stdout, self.stderr, self.has_timed_out)) bcbio-nextgen-1.2.9/bcbio/server/main.py000066400000000000000000000032141415626112400201330ustar00rootroot00000000000000"""Top level functionality for running a bcbio-nextgen web server allowing remote jobs. """ import tornado.web import tornado.ioloop from bcbio.server import run def start(args): """Run server with provided command line arguments. """ application = tornado.web.Application([(r"/run", run.get_handler(args)), (r"/status", run.StatusHandler)]) application.runmonitor = RunMonitor() application.listen(args.port) tornado.ioloop.IOLoop.instance().start() class RunMonitor: """Track current runs and provide status. """ def __init__(self): self._running = {} def set_status(self, run_id, status): self._running[run_id] = status def get_status(self, run_id): return self._running.get(run_id, "not-running") def add_subparser(subparsers): """Add command line arguments as server subparser. """ parser = subparsers.add_parser("server", help="Run a bcbio-nextgen server allowing remote job execution.") parser.add_argument("-c", "--config", help=("Global YAML configuration file specifying system details." "Defaults to installed bcbio_system.yaml")) parser.add_argument("-p", "--port", help="Port to listen on (default 8080)", default=8080, type=int) parser.add_argument("-n", "--cores", help="Cores to use when processing locally when not requested (default 1)", default=1, type=int) parser.add_argument("-d", "--biodata_dir", help="Directory with biological data", default="/mnt/biodata", type=str) return parser bcbio-nextgen-1.2.9/bcbio/server/run.py000066400000000000000000000071651415626112400200240ustar00rootroot00000000000000"""Provide ability to run bcbio-nextgen workflows. """ import collections import os import sys import uuid from six import StringIO import tornado.gen import tornado.web import yaml from bcbio import utils from bcbio.distributed import clargs from bcbio.server import background def run_bcbio_nextgen(**kwargs): callback = kwargs.pop("callback", None) app = kwargs.pop("app") args = [x for x in [kwargs["config_file"], kwargs["fc_dir"], kwargs["run_info_yaml"]] if x] run_id = str(uuid.uuid1()) def set_done(status, stdout, stderr, has_timed_out): app.runmonitor.set_status(run_id, "finished" if status == 0 else "failed") if utils.get_in(kwargs, ("parallel", "type")) == "local": _run_local(kwargs["workdir"], args, utils.get_in(kwargs, ("parallel", "cores")), set_done) else: # XXX Need to work on ways to prepare batch scripts for bcbio submission # when analysis server talks to an HPC cluster raise ValueError("Do not yet support automated execution of this parallel config: %s" % kwargs["parallel"]) app.runmonitor.set_status(run_id, "running") if callback: callback(run_id) else: return run_id def _run_local(workdir, args, cores, callback): cmd = [os.path.join(os.path.dirname(sys.executable), "bcbio_nextgen.py")] + args + \ ["-n", cores] with utils.chdir(workdir): p = background.Subprocess(callback, timeout=-1, args=[str(x) for x in cmd]) p.start() def _rargs_to_parallel_args(rargs, args): Args = collections.namedtuple("Args", "numcores scheduler queue resources timeout retries tag") return Args(int(rargs.get("numcores", args.cores)), rargs.get("scheduler"), rargs.get("queue"), rargs.get("resources", ""), int(rargs.get("timeout", 15)), rargs.get("retries"), rargs.get("tag")) def get_handler(args): class RunHandler(tornado.web.RequestHandler): @tornado.web.asynchronous @tornado.gen.coroutine def get(self): rargs = yaml.safe_load(StringIO(str(self.get_argument("args", "{}")))) system_config = args.config or "bcbio_system.yaml" if "system_config" in rargs: system_config = os.path.join(rargs["work_dir"], "web-system_config.yaml") with open(system_config, "w") as out_handle: yaml.safe_dump(rargs["system_config"], out_handle, default_flow_style=False, allow_unicode=False) if "sample_config" in rargs: sample_config = os.path.join(rargs["work_dir"], "web-sample_config.yaml") with open(sample_config, "w") as out_handle: yaml.safe_dump(rargs["sample_config"], out_handle, default_flow_style=False, allow_unicode=False) else: sample_config = rargs.get("run_config") kwargs = {"workdir": rargs["work_dir"], "config_file": system_config, "run_info_yaml": sample_config, "fc_dir": rargs.get("fc_dir"), "parallel": clargs.to_parallel(_rargs_to_parallel_args(rargs, args)), "app": self.application} run_id = yield tornado.gen.Task(run_bcbio_nextgen, **kwargs) self.write(run_id) self.finish() return RunHandler class StatusHandler(tornado.web.RequestHandler): def get(self): run_id = self.get_argument("run_id", None) if run_id is None: status = "server-up" else: status = self.application.runmonitor.get_status(run_id) self.write(status) self.finish() bcbio-nextgen-1.2.9/bcbio/setpath.py000066400000000000000000000053071415626112400173560ustar00rootroot00000000000000"""Update the PATH environment variable to reflect the value of BCBIOPATH. """ from __future__ import print_function import contextlib import os from bcbio import utils def _prepend(original, to_prepend): """Prepend paths in a string representing a list of paths to another. original and to_prepend are expected to be strings representing os.pathsep-separated lists of filepaths. If to_prepend is None, original is returned. The list of paths represented in the returned value consists of the first of occurrences of each non-empty path in the list obtained by prepending the paths in to_prepend to the paths in original. examples: # Unix _prepend('/b:/d:/a:/d', '/a:/b:/c:/a') -> '/a:/b:/c:/d' _prepend('/a:/b:/a', '/a:/c:/c') -> '/a:/c:/b' _prepend('/c', '/a::/b:/a') -> '/a:/b:/c' _prepend('/a:/b:/a', None) -> '/a:/b:/a' _prepend('/a:/b:/a', '') -> '/a:/b' """ if to_prepend is None: return original sep = os.pathsep def split_path_value(path_value): return [] if path_value == '' else path_value.split(sep) seen = set() components = [] for path in split_path_value(to_prepend) + split_path_value(original): if path not in seen and path != '': components.append(path) seen.add(path) return sep.join(components) def prepend_bcbiopath(): """Prepend paths in the BCBIOPATH environment variable (if any) to PATH. Uses either a pre-sent global environmental variable (BCBIOPATH) or the local anaconda directory. """ if os.environ.get('BCBIOPATH'): os.environ['PATH'] = _prepend(os.environ.get('PATH', ''), os.environ.get('BCBIOPATH', None)) else: os.environ['PATH'] = _prepend(os.environ.get('PATH', ''), utils.get_bcbio_bin()) def remove_bcbiopath(): """Remove bcbio internal path from first element in PATH. Useful when we need to access remote programs, like Java 7 for older installations. """ to_remove = os.environ.get("BCBIOPATH", utils.get_bcbio_bin()) + ":" if os.environ["PATH"].startswith(to_remove): os.environ["PATH"] = os.environ["PATH"][len(to_remove):] @contextlib.contextmanager def orig_paths(): """Run using original paths in a `with` block. """ remove_bcbiopath() yield None prepend_bcbiopath() if __name__ == '__main__': # check examples (poor-man's doctest) print(_prepend('/b:/d:/a:/d', '/a:/b:/c:/a')) print(_prepend('/a:/b:/a', '/a:/c:/c')) print(_prepend('/c', '/a::/b:/a')) print(_prepend('/a:/b:/a', None)) print(_prepend('/a:/b:/a', '')) bcbio-nextgen-1.2.9/bcbio/srna/000077500000000000000000000000001415626112400162725ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/srna/__init__.py000066400000000000000000000000521415626112400204000ustar00rootroot00000000000000""" small RNA-seq specific functions """ bcbio-nextgen-1.2.9/bcbio/srna/group.py000066400000000000000000000222361415626112400200050ustar00rootroot00000000000000import os import string import os.path as op import shutil from collections import namedtuple try: from seqcluster import prepare_data as prepare from seqcluster import templates as template_seqcluster from seqcluster.seqbuster import _create_counts, _read_miraligner, _tab_output except ImportError: pass from bcbio.utils import file_exists, safe_makedir, move_safe, append_stem, get_bcbio_bin from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.pipeline.sample import process_alignment from bcbio.srna import mirdeep from bcbio.rnaseq import spikein from bcbio.srna import mirge def run_prepare(*data): """ Run seqcluster prepare to merge all samples in one file """ out_dir = os.path.join(dd.get_work_dir(data[0][0]), "seqcluster", "prepare") out_dir = os.path.abspath(safe_makedir(out_dir)) prepare_dir = os.path.join(out_dir, "prepare") tools = dd.get_expression_caller(data[0][0]) if len(tools) == 0: logger.info("You didn't specify any other expression caller tool." "You can add to the YAML file:" "expression_caller:[trna, seqcluster, mirdeep2]") fn = [] for sample in data: name = sample[0]["rgnames"]['sample'] fn.append("%s\t%s" % (sample[0]['collapse'], name)) args = namedtuple('args', 'debug print_debug minc minl maxl out') args = args(False, False, 2, 17, 40, out_dir) ma_out = op.join(out_dir, "seqs.ma") seq_out = op.join(out_dir, "seqs.fastq") min_shared = max(int(len(fn) / 10.0), 1) if not file_exists(ma_out): seq_l, sample_l = prepare._read_fastq_files(fn, args) with file_transaction(ma_out) as ma_tx: with open(ma_tx, 'w') as ma_handle: with open(seq_out, 'w') as seq_handle: logger.info("Prepare seqs.fastq with -minl 17 -maxl 40 -minc 2 --min_shared 0.1") prepare._create_matrix_uniq_seq(sample_l, seq_l, ma_handle, seq_handle, min_shared) for sample in data: sample[0]["seqcluster_prepare_ma"] = ma_out sample[0]["seqcluster_prepare_fastq"] = seq_out return data def run_align(*data): """ Prepare data to run alignment step, only once for each project """ work_dir = dd.get_work_dir(data[0][0]) out_dir = op.join(work_dir, "seqcluster", "prepare") seq_out = op.join(out_dir, "seqs.fastq") bam_dir = op.join(work_dir, "align") new_bam_file = op.join(bam_dir, "seqs.bam") tools = dd.get_expression_caller(data[0][0]) if not file_exists(new_bam_file): sample = process_alignment(data[0][0], [seq_out, None]) bam_file = dd.get_work_bam(sample[0][0]) shutil.move(bam_file, new_bam_file) shutil.move(bam_file + ".bai", new_bam_file + ".bai") shutil.rmtree(op.join(bam_dir, sample[0][0]["rgnames"]['sample'])) for sample in data: # sample[0]["align_bam"] = sample[0]["clean_fastq"] sample[0]["cluster_bam"] = new_bam_file if "mirdeep2" in tools: novel_db = mirdeep.run(data) return data def run_cluster(*data): """ Run seqcluster cluster to detect smallRNA clusters """ sample = data[0][0] tools = dd.get_expression_caller(data[0][0]) work_dir = dd.get_work_dir(sample) out_dir = op.join(work_dir, "seqcluster", "cluster") out_dir = op.abspath(safe_makedir(out_dir)) prepare_dir = op.join(work_dir, "seqcluster", "prepare") bam_file = data[0][0]["cluster_bam"] if "seqcluster" in tools: gtf_file = dd.get_transcriptome_gtf(sample) if dd.get_transcriptome_gtf(sample) else dd.get_srna_gtf_file(sample) sample["seqcluster"] = _cluster(bam_file, data[0][0]["seqcluster_prepare_ma"], out_dir, dd.get_ref_file(sample), gtf_file) sample["report"] = _report(sample, dd.get_ref_file(sample)) if "mirge" in tools: sample["mirge"] = mirge.run(data) out_mirna = _make_isomir_counts(data, out_dir=op.join(work_dir, "mirbase")) if out_mirna: sample = dd.set_mirna_counts(sample, out_mirna[0]) sample = dd.set_isomir_counts(sample, out_mirna[1]) out_novel = _make_isomir_counts(data, "seqbuster_novel", op.join(work_dir, "mirdeep2"), "_novel") if out_novel: sample = dd.set_novel_mirna_counts(sample, out_novel[0]) sample = dd.set_novel_isomir_counts(sample, out_novel[1]) data[0][0] = sample data = spikein.combine_spikein(data) return data def _cluster(bam_file, ma_file, out_dir, reference, annotation_file=None): """ Connect to seqcluster to run cluster with python directly """ seqcluster = op.join(get_bcbio_bin(), "seqcluster") # cl = ["cluster", "-o", out_dir, "-m", ma_file, "-a", bam_file, "-r", reference] if annotation_file: annotation_file = "-g " + annotation_file else: annotation_file = "" if not file_exists(op.join(out_dir, "counts.tsv")): cmd = ("{seqcluster} cluster -o {out_dir} -m {ma_file} -a {bam_file} -r {reference} {annotation_file}") do.run(cmd.format(**locals()), "Running seqcluster.") counts = op.join(out_dir, "counts.tsv") stats = op.join(out_dir, "read_stats.tsv") json = op.join(out_dir, "seqcluster.json") return {'out_dir': out_dir, 'count_file': counts, 'stat_file': stats, 'json': json} def _report(data, reference): """ Run report of seqcluster to get browser options for results """ seqcluster = op.join(get_bcbio_bin(), "seqcluster") work_dir = dd.get_work_dir(data) out_dir = safe_makedir(os.path.join(work_dir, "seqcluster", "report")) out_file = op.join(out_dir, "seqcluster.db") json = op.join(work_dir, "seqcluster", "cluster", "seqcluster.json") cmd = ("{seqcluster} report -o {out_dir} -r {reference} -j {json}") if not file_exists(out_file): do.run(cmd.format(**locals()), "Run report on clusters") return out_file def report(data): """Create a Rmd report for small RNAseq analysis""" work_dir = dd.get_work_dir(data[0][0]) out_dir = op.join(work_dir, "report") safe_makedir(out_dir) summary_file = op.join(out_dir, "summary.csv") with file_transaction(summary_file) as out_tx: with open(out_tx, 'w') as out_handle: out_handle.write("sample_id,%s\n" % _guess_header(data[0][0])) for sample in data: info = sample[0] group = _guess_group(info) files = info["seqbuster"] if "seqbuster" in info else "None" out_handle.write(",".join([dd.get_sample_name(info), group]) + "\n") _modify_report(work_dir, out_dir) return summary_file def _guess_header(info): """Add the first group to get report with some factor""" value = "group" if "metadata" in info: if info["metadata"]: return ",".join(map(str, info["metadata"].keys())) return value def _guess_group(info): """Add the first group to get report with some factor""" value = "fake" if "metadata" in info: if info["metadata"]: return ",".join(map(str, info["metadata"].values())) return value def _modify_report(summary_path, out_dir): """Read Rmd template and dump with project path.""" summary_path = op.abspath(summary_path) template = op.normpath(op.join(op.dirname(op.realpath(template_seqcluster.__file__)), "report.rmd")) content = open(template).read() out_content = string.Template(content).safe_substitute({'path_abs': summary_path}) out_file = op.join(out_dir, "srna_report.rmd") with open(out_file, 'w') as out_handle: out_handle.write(out_content) return out_file def _make_isomir_counts(data, srna_type="seqbuster", out_dir=None, stem=""): """ Parse miraligner files to create count matrix. """ work_dir = dd.get_work_dir(data[0][0]) if not out_dir: out_dir = op.join(work_dir, "mirbase") out_novel_isomir = append_stem(op.join(out_dir, "counts.tsv"), stem) out_novel_mirna = append_stem(op.join(out_dir, "counts_mirna.tsv"), stem) logger.debug("Create %s count data at %s." % (srna_type, out_dir)) if file_exists(out_novel_mirna): return [out_novel_mirna, out_novel_isomir] out_dts = [] for sample in data: if sample[0].get(srna_type): miraligner_fn = sample[0][srna_type] reads = _read_miraligner(miraligner_fn) if reads: out_file, dt, dt_pre = _tab_output(reads, miraligner_fn + ".back", dd.get_sample_name(sample[0])) out_dts.append(dt) else: logger.debug("WARNING::%s has NOT miRNA annotated for %s. Check if fasta files is small or species value." % (dd.get_sample_name(sample[0]), srna_type)) if out_dts: out_files = _create_counts(out_dts, out_dir) out_files = [move_safe(out_files[0], out_novel_isomir), move_safe(out_files[1], out_novel_mirna)] return out_files else: logger.debug("WARNING::any samples have miRNA annotated for %s. Check if fasta files is small or species value." % srna_type) bcbio-nextgen-1.2.9/bcbio/srna/mirdeep.py000066400000000000000000000110631415626112400202720ustar00rootroot00000000000000import os import sys import os.path as op import pysam from bcbio.log import logger from bcbio.utils import file_exists, safe_makedir, chdir, get_perl_exports from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd def run(data): config = data[0][0]['config'] work_dir = dd.get_work_dir(data[0][0]) genome = dd.get_ref_file(data[0][0]) mirdeep2 = os.path.join(os.path.dirname(sys.executable), "miRDeep2.pl") perl_exports = get_perl_exports() hairpin, mature, species = "none", "none", "na" rfam_file = dd.get_mirdeep2_file(data[0][0]) if file_exists(dd.get_mirbase_hairpin(data[0][0])): species = dd.get_species(data[0][0]) hairpin = dd.get_mirbase_hairpin(data[0][0]) mature = dd.get_mirbase_mature(data[0][0]) logger.debug("Preparing for mirdeep2 analysis.") bam_file = op.join(work_dir, "align", "seqs.bam") seqs_dir = op.join(work_dir, "seqcluster", "prepare") collapsed = op.join(seqs_dir, "seqs.ma") out_dir = op.join(work_dir, "mirdeep2") out_file = op.join(out_dir, "result_res.csv") safe_makedir(out_dir) if not file_exists(rfam_file): logger.warning("mirdeep2 Rfam file not instaled. Skipping...") return None if not file_exists(mirdeep2): logger.warning("mirdeep2 executable file not found. Skipping...") return None with chdir(out_dir): collapsed, bam_file = _prepare_inputs(collapsed, bam_file, out_dir) cmd = ("{perl_exports} && perl {mirdeep2} {collapsed} {genome} {bam_file} {mature} none {hairpin} -f {rfam_file} -r simple -c -P -t {species} -z res -g -1").format(**locals()) if not file_exists(out_file): try: do.run(cmd.format(**locals()), "Running mirdeep2.") except: logger.warning("mirdeep2 failed. Please report the error to https://github.com/lpantano/mirdeep2_core/issues.") if file_exists(out_file): novel_db = _parse_novel(out_file, dd.get_species(data[0][0])) return novel_db def _prepare_inputs(ma_fn, bam_file, out_dir): """ Convert to fastq with counts """ fixed_fa = os.path.join(out_dir, "file_reads.fa") count_name =dict() with file_transaction(fixed_fa) as out_tx: with open(out_tx, 'w') as out_handle: with open(ma_fn) as in_handle: h = next(in_handle) for line in in_handle: cols = line.split("\t") name_with_counts = "%s_x%s" % (cols[0], sum(map(int, cols[2:]))) count_name[cols[0]] = name_with_counts out_handle.write(">%s\n%s\n" % (name_with_counts, cols[1])) fixed_bam = os.path.join(out_dir, "align.bam") bam_handle = pysam.AlignmentFile(bam_file, "rb") with pysam.AlignmentFile(fixed_bam, "wb", template=bam_handle) as out_handle: for read in bam_handle.fetch(): read.query_name = count_name[read.query_name] out_handle.write(read) return fixed_fa, fixed_bam def _parse_novel(csv_file, sps="new"): """Create input of novel miRNAs from miRDeep2""" read = 0 seen = set() safe_makedir("novel") with open("novel/hairpin.fa", "w") as fa_handle, open("novel/miRNA.str", "w") as str_handle: with open(csv_file) as in_handle: for line in in_handle: if line.startswith("mature miRBase miRNAs detected by miRDeep2"): break if line.startswith("novel miRNAs predicted"): read = 1 line = next(in_handle) continue if read and line.strip(): cols = line.strip().split("\t") name, start, score = cols[0], cols[16], cols[1] if float(score) < 1: continue m5p, m3p, pre = cols[13], cols[14], cols[15].replace('u', 't').upper() m5p_start = cols[15].find(m5p) + 1 m3p_start = cols[15].find(m3p) + 1 m5p_end = m5p_start + len(m5p) - 1 m3p_end = m3p_start + len(m3p) - 1 if m5p in seen: continue fa_handle.write(">{sps}-{name} {start}\n{pre}\n".format(**locals())) str_handle.write(">{sps}-{name} ({score}) [{sps}-{name}-5p:{m5p_start}-{m5p_end}] [{sps}-{name}-3p:{m3p_start}-{m3p_end}]\n".format(**locals())) seen.add(m5p) return op.abspath("novel") bcbio-nextgen-1.2.9/bcbio/srna/mirge.py000066400000000000000000000056061415626112400177560ustar00rootroot00000000000000"""Run mirge tool""" import os import sys import shutil import glob from bcbio.distributed.transaction import tx_tmpdir from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.log import logger from bcbio import utils SPS = {'hsa': 'human', 'mmu': 'mouse', 'rno': 'rat', 'dre': 'zebrafish', 'cel': 'nematode', 'dme': 'fruitfly'} def run(data): """Proxy function to run the tool""" sample = data[0][0] work_dir = dd.get_work_dir(sample) out_dir = os.path.join(work_dir, "mirge") lib = _find_lib(sample) mirge = _find_mirge(sample) bowtie = _find_bowtie(sample) sps = dd.get_species(sample) species = SPS.get(sps, "") if not species: raise ValueError("species not supported (hsa, mmu, rno, dre, cel, dme): %s" % sps) if not lib: raise ValueError("-lib option is not set up in resources for mirge tool." " Read above warnings lines.") if not utils.file_exists(out_dir): with tx_tmpdir() as tmp_dir: sample_file = _create_sample_file(data, tmp_dir) do.run(_cmd().format(**locals()), "Running miRge2.0.") shutil.move(tmp_dir, out_dir) return [os.path.abspath(fn) for fn in glob.glob(os.path.join(out_dir, "*", "*"))] def _find_mirge(data): try: mirge = config_utils.get_program("miRge2.0", data) return mirge except config_utils.CmdNotFound: logger.warning("miRge2.0 is not found. Install it first, and try again.") return None def _cmd(): cmd = "{mirge} annotate -s {sample_file} -o {tmp_dir} -pb {bowtie} {lib} -sp {species} -di -ai -gff" return cmd def _create_sample_file(data, out_dir): """from data list all the fastq files in a file""" sample_file = os.path.join(out_dir, "sample_file.txt") with open(sample_file, 'w') as outh: for sample in data: outh.write(sample[0]["clean_fastq"] + "\n") return sample_file def _find_bowtie(data): try: bowtie = config_utils.get_program("bowtie", data) return os.path.dirname(bowtie) except config_utils.CmdNotFound: logger.watning("bowtie is not found. Install it first, and try again.") return None def _find_lib(data): """Find mirge libs""" options = " ".join(data.get('resources', {}).get('mirge', {}).get("options", "")) if options.find("-lib") > -1 and utils.file_exists(options.split()[1]): return options if not options: logger.warning("miRge libraries not found. Follow these instructions to install them:") logger.warning("https://github.com/mhalushka/miRge#download-libraries") logger.warning("Then, pass -lib LIB_PATH with resourcces:mirge:options:[...]") logger.warning("More information: https://bcbio-nextgen.readthedocs.io/en/latest/contents/pipelines.html#smallrna-seq") bcbio-nextgen-1.2.9/bcbio/srna/qc.py000066400000000000000000000000501415626112400172420ustar00rootroot00000000000000"""Functions to create QC metrics""" bcbio-nextgen-1.2.9/bcbio/srna/sample.py000066400000000000000000000356231415626112400201360ustar00rootroot00000000000000import os import sys import glob import re import os.path as op import shutil from collections import Counter try: from dnapilib.apred import iterative_adapter_prediction error_dnapi = None except ImportError: error_dnapi = ("No dnapi installed. Need to give adapter sequence." "Please, install with bcbio_conda install dnapi -c bioconda" " or add adapters: ['ADAPTER_SEQ'] to config file.") pass from bcbio.utils import (file_exists, append_stem, replace_directory, symlink_plus) from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio import utils from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.log import logger from bcbio.rnaseq import spikein from bcbio.srna.umis import umi_transform def trim_srna_sample(data): """ Remove 3' adapter for smallRNA-seq Uses cutadapt but with different parameters than for other pipelines. """ data = umi_transform(data) in_file = data["files"][0] names = data["rgnames"]['sample'] work_dir = os.path.join(dd.get_work_dir(data), "trimmed") out_dir = os.path.join(work_dir, names) log_out = os.path.join(out_dir, "%s.log" % names) utils.safe_makedir(out_dir) out_file = replace_directory(append_stem(in_file, ".clean"), out_dir) trim_reads = data["config"]["algorithm"].get("trim_reads", True) if utils.file_exists(out_file): data["files"][0] = out_file data["clean_fastq"] = out_file data["collapse"] = _collapse(data["clean_fastq"]) data["size_stats"] = _summary(data['collapse']) data["log_trimming"] = log_out return [[data]] adapter = dd.get_adapters(data) is_4n = any([a == "4N" for a in adapter]) adapter = [a for a in adapter if re.compile(r"^([NATGC]+)$").match(a)] if adapter and not trim_reads: trim_reads = True logger.info("Adapter is set up in config file, but trim_reads is not true." "If you want to skip trimming, skip adapter option from config.") if trim_reads and not adapter and error_dnapi: raise ValueError(error_dnapi) if trim_reads: adapters = adapter if adapter else _dnapi_prediction(in_file, out_dir) times = "" if not trim_reads or len(adapters) == 1 else "--times %s" % len(adapters) if trim_reads and adapters: adapter_cmd = " ".join(map(lambda x: "-a " + x, adapters)) if any([a for a in adapters if re.compile(r"^N+$").match(a)]): adapter_cmd = "-N %s" % adapter_cmd out_noadapter_file = replace_directory(append_stem(in_file, ".fragments"), out_dir) out_short_file = replace_directory(append_stem(in_file, ".short"), out_dir) # atropos = _get_atropos() atropos = config_utils.get_program("atropos", data, default="atropos") options = " ".join(data.get('resources', {}).get('atropos', {}).get("options", "")) if options.strip() == "-u 4 -u -4": options = "" is_4n = "4N" cores = ("--threads %s" % dd.get_num_cores(data) if dd.get_num_cores(data) > 1 else "") if " ".join(data.get('resources', {}).get('cutadapt', {}).get("options", "")): raise ValueError("Atropos is now used, but cutadapt options found in YAML file." "See https://atropos.readthedocs.io/en/latest/") cmd = _cmd_atropos() if not utils.file_exists(out_file): with file_transaction(out_file) as tx_out_file: do.run(cmd.format(**locals()), "remove adapter for %s" % names) if utils.file_exists(log_out): content = open(log_out).read().replace(out_short_file, names) open(log_out, 'w').write(content) if is_4n: options = "-u 4 -u -4" in_file = append_stem(tx_out_file, ".tmp") utils.move_safe(tx_out_file, in_file) cmd = "{atropos} {cores} {options} -se {in_file} -o {tx_out_file} -m 17" do.run(cmd.format(**locals()), "atropos with this parameters %s for %s" %(options, names)) data["log_trimming"] = log_out else: if not trim_reads: logger.debug("Skip trimming for: %s" % names) elif not adapters: logger.info("No adapter founds in %s, this is an issue related" " to no small RNA enrichment in your sample." % names) symlink_plus(in_file, out_file) data["files"][0] = out_file data["clean_fastq"] = out_file data["collapse"] = _collapse(data["clean_fastq"]) data["size_stats"] = _summary(data['collapse']) return [[data]] def sample_annotation(data): """ Annotate miRNAs using miRBase database with seqbuster tool """ names = data["rgnames"]['sample'] tools = dd.get_expression_caller(data) work_dir = os.path.join(dd.get_work_dir(data), "mirbase") out_dir = os.path.join(work_dir, names) utils.safe_makedir(out_dir) out_file = op.join(out_dir, names) if dd.get_mirbase_hairpin(data): mirbase = op.abspath(op.dirname(dd.get_mirbase_hairpin(data))) if utils.file_exists(data["collapse"]): data['transcriptome_bam'] = _align(data["collapse"], dd.get_mirbase_hairpin(data), out_file, data) data['seqbuster'] = _miraligner(data["collapse"], out_file, dd.get_species(data), mirbase, data['config']) data["mirtop"] = _mirtop(data['seqbuster'], dd.get_species(data), mirbase, out_dir, data['config']) else: logger.debug("Trimmed collapsed file is empty for %s." % names) else: logger.debug("No annotation file from miRBase.") sps = dd.get_species(data) if dd.get_species(data) else "None" logger.debug("Looking for mirdeep2 database for %s" % names) if file_exists(op.join(dd.get_work_dir(data), "mirdeep2", "novel", "hairpin.fa")): data['seqbuster_novel'] = _miraligner(data["collapse"], "%s_novel" % out_file, sps, op.join(dd.get_work_dir(data), "mirdeep2", "novel"), data['config']) if "trna" in tools: data['trna'] = _mint_trna_annotation(data) data = spikein.counts_spikein(data) return [[data]] def _prepare_file(fn, out_dir): """Cut the beginning of the reads to avoid detection of miRNAs""" atropos = _get_atropos() cmd = "{atropos} trim --max-reads 500000 -u 22 -se {fn} -o {tx_file}" out_file = os.path.join(out_dir, append_stem(os.path.basename(fn), "end")) if file_exists(out_file): return out_file with file_transaction(out_file) as tx_file: do.run(cmd.format(**locals())) return out_file def _dnapi_prediction(fn, out_dir): end_file = _prepare_file(fn, out_dir) iterative_result = iterative_adapter_prediction(end_file, [1.2, 1.3, 1.4, 1.7, 2], [7, 11], 500000) max_score = iterative_result[1][1] adapters = list() for a in iterative_result: if a[1] > max_score * 0.40: logger.debug("Adding adapter to the list: %s with score %s" % (a[0], a[1])) adapters.append(a[0]) return adapters def _cmd_atropos(): """ Run cutadapt for smallRNA data that needs some specific values. """ cmd = "{atropos} {cores} {times} {options} {adapter_cmd} --untrimmed-output={out_noadapter_file} -o {tx_out_file} -m 17 --overlap=8 -se {in_file} --too-short-output {out_short_file} | tee > {log_out}" return cmd def _collapse(in_file): """ Collpase reads into unique sequences with seqcluster """ seqcluster = op.join(utils.get_bcbio_bin(), "seqcluster") out_file = "%s.fastq" % utils.splitext_plus(append_stem(in_file, "_trimmed"))[0] out_dir = os.path.dirname(in_file) if file_exists(out_file): return out_file cmd = ("{seqcluster} collapse -o {out_dir} -f {in_file} -m 1 --min_size 16") do.run(cmd.format(**locals()), "Running seqcluster collapse in %s." % in_file) return out_file def _summary(in_file): """ Calculate size distribution after adapter removal """ data = Counter() out_file = in_file + "_size_stats" if file_exists(out_file): return out_file with open(in_file) as in_handle: for line in in_handle: counts = int(line.strip().split("_x")[1]) line = next(in_handle) l = len(line.strip()) next(in_handle) next(in_handle) data[l] += counts with file_transaction(out_file) as tx_out_file: with open(tx_out_file, 'w') as out_handle: for l, c in data.items(): out_handle.write("%s %s\n" % (l, c)) return out_file def _align(infile, ref, out_file, data): out_file = "%s.bam" % out_file razers3 = config_utils.get_program("razers3", data["config"]) cmd = "{razers3} -dr 0 -i 80 -rr 90 -f -o {tx_out} {ref} {infile}" if not razers3: logger.info("razers3 is not installed, skipping BAM file creation") return None if not file_exists(out_file): with file_transaction(data, out_file) as tx_out: do.run(cmd.format(**locals()), "Running razers3 against hairpins with %s" % infile) return out_file def _miraligner(fastq_file, out_file, species, db_folder, config): """ Run miraligner tool (from seqcluster suit) with default parameters. """ resources = config_utils.get_resources("miraligner", config) miraligner = config_utils.get_program("miraligner", config) jvm_opts = "-Xms750m -Xmx4g" if resources and resources.get("jvm_opts"): jvm_opts = " ".join(resources.get("jvm_opts")) export = _get_env() cmd = ("{export} {miraligner} {jvm_opts} -freq -sub 1 -trim 3 -add 3 -minl 16" " -s {species} -i {fastq_file} -db {db_folder} -o {tx_out_file}") if not file_exists(out_file + ".mirna"): with file_transaction(out_file) as tx_out_file: do.run(cmd.format(**locals()), "Do miRNA annotation for %s" % fastq_file) shutil.move(tx_out_file + ".mirna", out_file + ".mirna") return out_file + ".mirna" def _get_env(): anaconda_bin = os.path.dirname(utils.Rscript_cmd()) return "unset JAVA_HOME && export PATH=%s:\"$PATH\" && " % (anaconda_bin) def _get_atropos(): anaconda = os.path.dirname(os.path.realpath(sys.executable)) return os.path.join(anaconda, "..", "envs", "python3", "bin", "atropos") def _mirtop(input_fn, sps, db, out_dir, config): """ Convert to GFF3 standard format """ hairpin = os.path.join(db, "hairpin.fa") gtf = os.path.join(db, "mirbase.gff3") if not file_exists(hairpin) or not file_exists(gtf): logger.warning("%s or %s are not installed. Skipping." % (hairpin, gtf)) return None out_gtf_fn = "%s.gtf" % utils.splitext_plus(os.path.basename(input_fn))[0] out_gff_fn = "%s.gff" % utils.splitext_plus(os.path.basename(input_fn))[0] export = _get_env() cmd = ("{export} mirtop gff --sps {sps} --hairpin {hairpin} " "--gtf {gtf} --format seqbuster -o {out_tx} {input_fn}") if not file_exists(os.path.join(out_dir, out_gtf_fn)) and \ not file_exists(os.path.join(out_dir, out_gff_fn)): with tx_tmpdir() as out_tx: do.run(cmd.format(**locals()), "Do miRNA annotation for %s" % input_fn) with utils.chdir(out_tx): out_fn = out_gtf_fn if utils.file_exists(out_gtf_fn) \ else out_gff_fn if utils.file_exists(out_fn): shutil.move(os.path.join(out_tx, out_fn), os.path.join(out_dir, out_fn)) out_fn = out_gtf_fn if utils.file_exists(os.path.join(out_dir, out_gtf_fn)) \ else os.path.join(out_dir, out_gff_fn) if utils.file_exists(os.path.join(out_dir, out_fn)): return os.path.join(out_dir, out_fn) def _trna_annotation(data): """ use tDRmapper to quantify tRNAs """ trna_ref = op.join(dd.get_srna_trna_file(data)) name = dd.get_sample_name(data) work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "trna", name)) in_file = op.basename(data["clean_fastq"]) tdrmapper = os.path.join(os.path.dirname(sys.executable), "TdrMappingScripts.pl") perl_export = utils.get_perl_exports() if not file_exists(trna_ref) or not file_exists(tdrmapper): logger.info("There is no tRNA annotation to run TdrMapper.") return work_dir out_file = op.join(work_dir, in_file + ".hq_cs.mapped") if not file_exists(out_file): with tx_tmpdir(data) as txdir: with utils.chdir(txdir): utils.symlink_plus(data["clean_fastq"], op.join(txdir, in_file)) cmd = ("{perl_export} && perl {tdrmapper} {trna_ref} {in_file}").format(**locals()) do.run(cmd, "tRNA for %s" % name) for filename in glob.glob("*mapped*"): shutil.move(filename, work_dir) return work_dir def _mint_trna_annotation(data): """ use MINTmap to quantify tRNAs """ name = dd.get_sample_name(data) work_dir = os.path.join(dd.get_work_dir(data), "trna_mint", name) if not dd.get_srna_mint_lookup(data): logger.info("There is no tRNA annotation to run MINTmap.") return work_dir trna_lookup = op.join(dd.get_srna_mint_lookup(data)) trna_space = op.join(dd.get_srna_mint_space(data)) trna_other = op.join(dd.get_srna_mint_other(data)) in_file = op.basename(data["clean_fastq"]) mintmap = os.path.realpath(os.path.join(os.path.dirname(sys.executable), "MINTmap.pl")) perl_export = utils.get_perl_exports() if not file_exists(trna_lookup) or not file_exists(mintmap): logger.info("There is no tRNA annotation to run MINTmap.") return work_dir jar_folder = os.path.join(os.path.dirname(mintmap), "MINTplates") out_file = op.join(work_dir, name + "-MINTmap_v1-exclusive-tRFs.expression.txt") if not file_exists(out_file): with tx_tmpdir(data) as txdir: with utils.chdir(txdir): utils.symlink_plus(data["clean_fastq"], op.join(txdir, in_file)) cmd = ("{perl_export} && {mintmap} -f {in_file} -p {name} " "-l {trna_lookup} -s {trna_space} -j {jar_folder} " "-o {trna_other}").format(**locals()) do.run(cmd, "tRNA for %s" % name) for filename in glob.glob("*MINTmap*"): shutil.move(filename, work_dir) return work_dir bcbio-nextgen-1.2.9/bcbio/srna/umis.py000066400000000000000000000062461415626112400176310ustar00rootroot00000000000000""" Unique Molecular Identifier (UMI) handling for small RNAseq. Most of this either uses Valentine Svennson's umis repository or adapts code written from it. https://github.com/vals/umis """ import os import sys import glob import re import bcbio.pipeline.datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.utils import (file_exists, safe_makedir) from bcbio.distributed.transaction import file_transaction from bcbio.bam.fastq import open_fastq from bcbio.rnaseq.umi import get_transform_file, \ is_transformed from bcbio.log import logger TD = os.path.join(os.path.dirname(__file__), os.pardir, "data", "umis") p = re.compile(r'smallrna', re.IGNORECASE) TF = glob.glob(os.path.join(TD, "*-transform.json")) TF = [t for t in TF if p.match(t)] SUPPORTED_TRANSFORMS = set([os.path.basename(x).replace("-transform.json", "") for x in TF]) def umi_transform(data): """ transform each read by identifying the barcode and UMI for each read and putting the information in the read name """ fq1 = data["files"][0] umi_dir = os.path.join(dd.get_work_dir(data), "umis") safe_makedir(umi_dir) transform = dd.get_umi_type(data) if not transform: logger.info("No UMI transform specified, assuming pre-transformed data.") if is_transformed(fq1): logger.info("%s detected as pre-transformed, passing it on unchanged." % fq1) data["files"] = [fq1] return data else: logger.error("No UMI transform was specified, but %s does not look " "pre-transformed. Assuming non-umi data." % fq1) return data if file_exists(transform): transform_file = transform else: transform_file = get_transform_file(transform) if not file_exists(transform_file): logger.error( "The UMI transform can be specified as either a file or a " "bcbio-supported transform. Either the file %s does not exist " "or the transform is not supported by bcbio. Supported " "transforms are %s." % (dd.get_umi_type(data), ", ".join(SUPPORTED_TRANSFORMS))) sys.exit(1) out_base = dd.get_sample_name(data) + ".umitransformed.fq.gz" out_file = os.path.join(umi_dir, out_base) if file_exists(out_file): data["files"] = [out_file] return data umis = config_utils.get_program("umis", data, default="umis") cores = dd.get_num_cores(data) # skip transformation if the file already looks transformed with open_fastq(fq1) as in_handle: read = next(in_handle) if "UMI_" in read: data["files"] = [out_file] return data cmd = ("{umis} fastqtransform {transform_file} " "--cores {cores} " "{fq1}" "| seqtk seq -L 20 - | gzip > {tx_out_file}") message = ("Inserting UMI and barcode information into the read name of %s" % fq1) with file_transaction(out_file) as tx_out_file: do.run(cmd.format(**locals()), message) data["files"] = [out_file] return data bcbio-nextgen-1.2.9/bcbio/structural/000077500000000000000000000000001415626112400175375ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/structural/__init__.py000066400000000000000000000413351415626112400216560ustar00rootroot00000000000000"""Detect structural variation in genomes using high-throughput sequencing data. """ import collections import copy import operator import os import toolz as tz from bcbio import utils from bcbio.cwl import cwlutils from bcbio.pipeline import datadict as dd from bcbio.structural import (battenberg, cn_mops, cnvkit, delly, gatkcnv, gridss, lumpy, manta, metasv, prioritize, purecn, purple, plot, scramble, seq2c, titancna, validate, wham) from bcbio.variation import validate as vcvalidate from bcbio.variation import vcfutils import six from functools import reduce # Stratify callers by stage -- see `run` documentation below for definitions _CALLERS = { "initial": {"cnvkit": cnvkit.run}, "standard": {"cn.mops": cn_mops.run, "manta": manta.run, "cnvkit": cnvkit.run, "delly": delly.run, "lumpy": lumpy.run, "wham": wham.run, "battenberg": battenberg.run, "seq2c": seq2c.run, "gridss": gridss.run, "titancna": titancna.run, "purecn": purecn.run, "purple": purple.run, "gatk-cnv": gatkcnv.run, "scramble": scramble.run}, "ensemble": {"metasv": metasv.run, "prioritize": prioritize.run}} _NEEDS_BACKGROUND = set(["cn.mops"]) _GLOBAL_BATCHING = set(["seq2c"]) # CNV callers that have background references _CNV_REFERENCE = set(["seq2c", "cnvkit", "gatk-cnv", "purecn"]) def _get_callers(items, stage, special_cases=False): """Retrieve available callers for the provided stage. Handles special cases like CNVkit that can be in initial or standard depending on if fed into Lumpy analysis. """ callers = utils.deepish_copy(_CALLERS[stage]) if special_cases and "cnvkit" in callers: has_lumpy = any("lumpy" in get_svcallers(d) or "lumpy" in d["config"]["algorithm"].get("svcaller_orig", []) for d in items) if has_lumpy and any("lumpy_usecnv" in dd.get_tools_on(d) for d in items): if stage != "initial": del callers["cnvkit"] else: if stage != "standard": del callers["cnvkit"] return callers def get_svcallers(data): """why this exists? dd.get_svcaller(data)""" svs = data["config"]["algorithm"].get("svcaller") if svs is None: svs = [] elif isinstance(svs, six.string_types): svs = [svs] return svs def _handle_multiple_svcallers(data, stage): """Retrieve configured structural variation caller, handling multiple. data is one sample """ svs = get_svcallers(data) # special cases -- prioritization if stage == "ensemble" and dd.get_svprioritize(data): svs.append("prioritize") out = [] for svcaller in svs: if svcaller in _get_callers([data], stage): base = copy.deepcopy(data) # clean SV callers present in multiple rounds and not this caller final_svs = [] for sv in data.get("sv", []): if (stage == "ensemble" or sv["variantcaller"] == svcaller or sv["variantcaller"] not in svs or svcaller not in _get_callers([data], stage, special_cases=True)): final_svs.append(sv) base["sv"] = final_svs base["config"]["algorithm"]["svcaller"] = svcaller base["config"]["algorithm"]["svcaller_orig"] = svs out.append(base) return out def finalize_sv(samples, config): """Combine results from multiple sv callers into a single ordered 'sv' key. """ by_bam = collections.OrderedDict() for x in samples: batch = dd.get_batch(x) or [dd.get_sample_name(x)] try: by_bam[x["align_bam"], tuple(batch)].append(x) except KeyError: by_bam[x["align_bam"], tuple(batch)] = [x] by_batch = collections.OrderedDict() lead_batches = {} for grouped_calls in by_bam.values(): def orig_svcaller_order(x): orig_callers = tz.get_in(["config", "algorithm", "svcaller_orig"], x) cur_caller = tz.get_in(["config", "algorithm", "svcaller"], x) return orig_callers.index(cur_caller) sorted_svcalls = sorted([x for x in grouped_calls if "sv" in x], key=orig_svcaller_order) final = grouped_calls[0] if len(sorted_svcalls) > 0: final["sv"] = reduce(operator.add, [x["sv"] for x in sorted_svcalls]) final["config"]["algorithm"]["svcaller"] = final["config"]["algorithm"].pop("svcaller_orig") batch = dd.get_batch(final) or dd.get_sample_name(final) batches = batch if isinstance(batch, (list, tuple)) else [batch] if len(batches) > 1: lead_batches[(dd.get_sample_name(final), dd.get_phenotype(final) == "germline")] = batches[0] for batch in batches: try: by_batch[batch].append(final) except KeyError: by_batch[batch] = [final] out = [] for batch, items in by_batch.items(): if any("svplots" in dd.get_tools_on(d) for d in items): items = plot.by_regions(items) for data in items: if lead_batches.get((dd.get_sample_name(data), dd.get_phenotype(data) == "germline")) in [batch, None]: out.append([data]) return out def validate_sv(data): """Validate structural variant calls for a sample. """ return [[validate.evaluate(data)]] def create_cnv_pon(samples): """create normal db using SNV PON and coverage information""" coverage_files = [] sample0 = utils.to_single_data(samples[0]) genome = dd.get_genome_build(sample0) purecn_pon_build = tz.get_in(["config", "algorithm", "purecn_pon_build"], sample0) if purecn_pon_build: for sample in (utils.to_single_data(x) for x in samples): sample_coverage = tz.get_in(["depth", "bins", "purecn"], sample) if os.path.exists(sample_coverage): coverage_files.append(sample_coverage) work_dir = tz.get_in(["dirs", "work"], sample0) out_dir = utils.safe_makedir(os.path.join(work_dir, "gemini")) purecn_coverage_files_txt = os.path.join(out_dir, "purecn_coverage_files.txt") with open(purecn_coverage_files_txt, "w") as out_handle: for fname in coverage_files: out_handle.write(fname + "\n") snv_pon = tz.get_in(["config", "algorithm", "purecn_snv_pon"], sample0) normal_db = os.path.join(out_dir, "normalDB_{}.rds".format(genome)) # delete normal db in work/gemini if you'd like to rebuild it! if os.path.exists(snv_pon) and len(coverage_files) >= 3 and not os.path.exists(normal_db): purecn.create_normal_db(purecn_coverage_files_txt, snv_pon, out_dir, genome) return samples def batch_for_sv(samples): """Prepare a set of samples for parallel structural variant calling. CWL input target -- groups samples into batches and structural variant callers for parallel processing. """ samples = cwlutils.assign_complex_to_samples(samples) to_process, extras, background = _batch_split_by_sv(samples, "standard") out = [cwlutils.samples_to_records(xs) for xs in to_process.values()] + extras return out def _batch_split_by_sv(samples, stage): """Return - to_process = svcaller-batch => [svcaller-sample1, svcaller-sample2...] odict - extras = samples without sv calling (should there be any?) - background - all samples """ to_process = collections.OrderedDict() extras = [] background = [] for data in (utils.to_single_data(x) for x in samples): # data = sample ready_data = _handle_multiple_svcallers(data, stage) if len(ready_data) > 0: # why appending every sample to background? background.append(data) # x is sample - sv caller pair for x in ready_data: svcaller = tz.get_in(["config", "algorithm", "svcaller"], x) batch = dd.get_batch(x) or dd.get_sample_name(x) if stage in ["ensemble"]: # no batching for ensemble methods if isinstance(batch, six.string_types) and batch != dd.get_sample_name(x): batch += "_%s" % dd.get_sample_name(x) else: batch = dd.get_sample_name(x) if dd.get_phenotype(x) == "germline": batch += "_germline" elif svcaller in _GLOBAL_BATCHING: # All samples batched together for analyses batch = "all" # just creating PON - no calling if stage in ["standard"] and batch in ["pon_build"]: extras.append(x) else: batches = batch if isinstance(batch, (list, tuple)) else [batch] for b in batches: try: to_process[(svcaller, b)].append(x) except KeyError: to_process[(svcaller, b)] = [x] else: extras.append([data]) return to_process, extras, background def run(samples, run_parallel, stage): """Run structural variation detection. The stage indicates which level of structural variant calling to run. - initial, callers that can be used in subsequent structural variation steps (cnvkit -> lumpy) - standard, regular batch calling - ensemble, post-calling, combine other callers or prioritize results """ to_process, extras, background = _batch_split_by_sv(samples, stage) processed = run_parallel("detect_sv", ([xs, background, stage] for xs in to_process.values())) finalized = (run_parallel("finalize_sv", [([xs[0] for xs in processed], processed[0][0]["config"])]) if len(processed) > 0 else []) return extras + finalized def detect_sv(items, all_items=None, stage="standard"): """Top level parallel target for examining structural variation. items = sample-sv_caller list, from one batch """ items = [utils.to_single_data(x) for x in items] items = cwlutils.unpack_tarballs(items, items[0]) svcaller = items[0]["config"]["algorithm"].get("svcaller") caller_fn = _get_callers(items, stage, special_cases=True).get(svcaller) out = [] batch = dd.get_batch(items[0]) # no SV calling when just creating a PON for PureCN if batch == "pon_build" and "purecn" in dd.get_svcaller(items[0]): return out if svcaller and caller_fn: if (all_items and svcaller in _NEEDS_BACKGROUND and not vcfutils.is_paired_analysis([x.get("align_bam") for x in items], items)): names = set([dd.get_sample_name(x) for x in items]) background = [x for x in all_items if dd.get_sample_name(x) not in names] for svdata in caller_fn(items, background): out.append([svdata]) else: for svdata in caller_fn(items): out.append([svdata]) else: for data in items: out.append([data]) # Avoid nesting of callers for CWL runs for easier extraction if cwlutils.is_cwl_run(items[0]): out_cwl = [] for data in [utils.to_single_data(x) for x in out]: # Run validation directly from CWL runs since we're single stage data = validate.evaluate(data) data["svvalidate"] = {"summary": tz.get_in(["sv-validate", "csv"], data)} svs = data.get("sv") if svs: assert len(svs) == 1, svs data["sv"] = svs[0] else: data["sv"] = {} data = _add_supplemental(data) out_cwl.append([data]) return out_cwl return out def _add_supplemental(data): """Add additional supplemental files to CWL sv output, give useful names. """ if "supplemental" not in data["sv"]: data["sv"]["supplemental"] = [] if data["sv"].get("variantcaller"): cur_name = _useful_basename(data) for k in ["cns", "vrn_bed"]: if data["sv"].get(k) and os.path.exists(data["sv"][k]): dname, orig = os.path.split(data["sv"][k]) orig_base, orig_ext = utils.splitext_plus(orig) orig_base = _clean_name(orig_base, data) if orig_base: fname = "%s-%s%s" % (cur_name, orig_base, orig_ext) else: fname = "%s%s" % (cur_name, orig_ext) sup_out_file = os.path.join(dname, fname) utils.symlink_plus(data["sv"][k], sup_out_file) data["sv"]["supplemental"].append(sup_out_file) return data def _clean_name(fname, data): """Remove standard prefixes from a filename before renaming with useful names. """ for to_remove in dd.get_batches(data) + [dd.get_sample_name(data), data["sv"]["variantcaller"]]: for ext in ("-", "_"): if fname.startswith("%s%s" % (to_remove, ext)): fname = fname[len(to_remove) + len(ext):] if fname.startswith(to_remove): fname = fname[len(to_remove):] return fname def _useful_basename(data): """Provide a useful file basename for outputs, referencing batch/sample and caller. """ names = dd.get_batches(data) if not names: names = [dd.get_sample_name(data)] batch_name = names[0] return "%s-%s" % (batch_name, data["sv"]["variantcaller"]) def _group_by_sample(items): """Group a set of items by sample names + multiple callers for prioritization """ by_sample = collections.defaultdict(list) for d in items: by_sample[dd.get_sample_name(d)].append(d) out = [] for sample_group in by_sample.values(): cur = utils.deepish_copy(sample_group[0]) svs = [] for d in sample_group: svs.append(d["sv"]) cur["sv"] = svs out.append(cur) return out def summarize_sv(items): """CWL target: summarize structural variants for multiple samples. XXX Need to support non-VCF output as tabix indexed output """ items = [utils.to_single_data(x) for x in vcvalidate.summarize_grading(items, "svvalidate")] out = {"sv": {"calls": [], "supplemental": [], "prioritize": {"tsv": [], "raw": []}}, "svvalidate": vcvalidate.combine_validations(items, "svvalidate")} added = set([]) # Standard callers for data in items: if data.get("sv"): if data["sv"].get("vrn_file"): ext = utils.splitext_plus(data["sv"]["vrn_file"])[-1] cur_name = _useful_basename(data) if cur_name not in added and ext.startswith(".vcf"): added.add(cur_name) out_file = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "sv", "calls")), "%s%s" % (cur_name, ext)) utils.copy_plus(data["sv"]["vrn_file"], out_file) out_file = vcfutils.bgzip_and_index(out_file, data["config"]) out["sv"]["calls"].append(out_file) if data["sv"].get("supplemental"): out["sv"]["supplemental"].extend([x for x in data["sv"]["supplemental"] if x]) # prioritization for pdata in _group_by_sample(items): prioritysv = [x for x in prioritize.run([utils.deepish_copy(pdata)])[0].get("sv", []) if x["variantcaller"] == "sv-prioritize"] if prioritysv: out["sv"]["prioritize"]["tsv"].append(prioritysv[0]["vrn_file"]) out["sv"]["prioritize"]["raw"].extend(prioritysv[0]["raw_files"].values()) return [out] # ## configuration def standardize_cnv_reference(data): """Standardize cnv_reference background to support multiple callers. """ out = tz.get_in(["config", "algorithm", "background", "cnv_reference"], data, {}) cur_callers = set(data["config"]["algorithm"].get("svcaller")) & _CNV_REFERENCE if isinstance(out, six.string_types): if not len(cur_callers) == 1: raise ValueError("Multiple CNV callers and single background reference for %s: %s" % data["description"], list(cur_callers)) else: out = {cur_callers.pop(): out} return out def supports_cnv_reference(c): return c in _CNV_REFERENCE def parallel_multiplier(items): """Use more resources (up to available limits) if we have multiple QC samples/svcallers. """ machines = [] for data in (xs[0] for xs in items): machines.append(max(1, len(get_svcallers(data)), len(dd.get_algorithm_qc(data)))) return sum(machines) bcbio-nextgen-1.2.9/bcbio/structural/annotate.py000066400000000000000000000111741415626112400217260ustar00rootroot00000000000000"""Annotate structural variant calls with associated genes. """ import os import sys from bcbio import utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.structural import regions from bcbio.variation import bedutils from bcbio.pipeline import config_utils import pybedtools def add_genes(in_file, data, max_distance=10000, work_dir=None): """Add gene annotations to a BED file from pre-prepared RNA-seq data. max_distance -- only keep annotations within this distance of event """ gene_file = regions.get_sv_bed(data, "exons", out_dir=os.path.dirname(in_file)) if gene_file and utils.file_exists(in_file): out_file = "%s-annotated.bed" % utils.splitext_plus(in_file)[0] if work_dir: out_file = os.path.join(work_dir, os.path.basename(out_file)) if not utils.file_uptodate(out_file, in_file): fai_file = ref.fasta_idx(dd.get_ref_file(data)) with file_transaction(data, out_file) as tx_out_file: _add_genes_to_bed(in_file, gene_file, fai_file, tx_out_file, data, max_distance) return out_file else: return in_file def _add_genes_to_bed(in_file, gene_file, fai_file, out_file, data, max_distance=10000): """Re-usable subcomponent that annotates BED file genes from another BED """ try: input_rec = next(iter(pybedtools.BedTool(in_file))) except StopIteration: # empty file utils.copy_plus(in_file, out_file) return # keep everything after standard chrom/start/end, 1-based extra_fields = list(range(4, len(input_rec.fields) + 1)) # keep the new gene annotation gene_index = len(input_rec.fields) + 4 extra_fields.append(gene_index) columns = ",".join([str(x) for x in extra_fields]) max_column = max(extra_fields) + 1 ops = ",".join(["distinct"] * len(extra_fields)) # swap over gene name to '.' if beyond maximum distance # cut removes the last distance column which can cause issues # with bedtools merge: 'ERROR: illegal character '.' found in integer conversion of string' distance_filter = (r"""awk -F$'\t' -v OFS='\t' '{if ($NF > %s || $NF < -%s) $%s = "."} {print}'""" % (max_distance, max_distance, gene_index)) sort_cmd = bedutils.get_sort_cmd(os.path.dirname(out_file)) cat_cmd = "zcat" if in_file.endswith(".gz") else "cat" # Ensure gene transcripts match reference genome ready_gene_file = os.path.join(os.path.dirname(out_file), "%s-genomeonly.bed" % (utils.splitext_plus(os.path.basename(gene_file))[0])) ready_gene_file = bedutils.subset_to_genome(gene_file, ready_gene_file, data) exports = "export TMPDIR=%s && %s" % (os.path.dirname(out_file), utils.local_path_export()) bcbio_py = sys.executable gsort = config_utils.get_program("gsort", data) cmd = ("{exports}{cat_cmd} {in_file} | grep -v ^track | grep -v ^browser | grep -v ^# | " "{bcbio_py} -c 'from bcbio.variation import bedutils; bedutils.remove_bad()' | " "{gsort} - {fai_file} | " "bedtools closest -g {fai_file} " "-D ref -t first -a - -b <({gsort} {ready_gene_file} {fai_file}) | " "{distance_filter} | cut -f 1-{max_column} | " "bedtools merge -i - -c {columns} -o {ops} -delim ',' -d -10 > {out_file}") do.run(cmd.format(**locals()), "Annotate BED file with gene info") def gene_one_per_line(in_file, data): """Split comma-separated gene annotations (after add_genes). Leads to duplicated records. Input: chr1 100 200 F1,F2 Output: chr1 100 200 F1 chr1 100 200 F2 """ if in_file: # Report all duplicated annotations one-per-line one_per_line_file = "%s-opl.bed" % utils.splitext_plus(in_file)[0] if not utils.file_uptodate(one_per_line_file, in_file): with file_transaction(data, one_per_line_file) as tx_out_file: with open(tx_out_file, 'w') as out: for r in pybedtools.BedTool(in_file): for g in r.name.split(','): out.write('\t'.join(map(str, [r.chrom, r.start, r.end, g])) + '\n') return one_per_line_file def count_genes(in_file, data): if pybedtools.BedTool(in_file).field_count() <= 3: ann_bed = add_genes(in_file, data) ann_bed = gene_one_per_line(ann_bed, data) else: ann_bed = in_file if ann_bed: return len(list(set(r.name for r in pybedtools.BedTool(ann_bed) if r.name and r.name != "."))) bcbio-nextgen-1.2.9/bcbio/structural/battenberg.py000066400000000000000000000130211415626112400222230ustar00rootroot00000000000000"""Copy number variant calling with cgpBattenberg from Sanger https://github.com/cancerit/cgpBattenberg """ import os import toolz as tz from bcbio import utils from bcbio.bam import ref from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import population, vcfutils def run(items, background=None): """Detect copy number variations from tumor/normal samples using Battenberg. """ paired = vcfutils.get_paired_bams([x["align_bam"] for x in items], items) if not paired or not paired.normal_bam: logger.warn("Battenberg only works on paired tumor/normal inputs, skipping %s" % dd.get_sample_name(items[0])) batout = None elif not tz.get_in(["genome_resources", "aliases", "human"], paired.tumor_data): logger.warn("Battenberg only works on human data, skipping %s" % dd.get_sample_name(items[0])) batout = None else: batout = _do_run(paired) batout["variantcaller"] = "battenberg" out = [] for data in items: if batout and dd.get_sample_name(data) == paired.tumor_name: if "sv" not in data: data["sv"] = [] data["sv"].append(batout) out.append(data) return out def _do_run(paired): """Perform Battenberg caling with the paired dataset. This purposely does not use a temporary directory for the output since Battenberg does smart restarts. """ work_dir = _sv_workdir(paired.tumor_data) out = _get_battenberg_out(paired, work_dir) ignore_file = os.path.join(work_dir, "ignore_chromosomes.txt") if len(_missing_files(out)) > 0: ref_file = dd.get_ref_file(paired.tumor_data) bat_datadir = os.path.normpath(os.path.join(os.path.dirname(ref_file), os.pardir, "battenberg")) ignore_file, gl_file = _make_ignore_file(work_dir, ref_file, ignore_file, os.path.join(bat_datadir, "impute", "impute_info.txt")) tumor_bam = paired.tumor_bam normal_bam = paired.normal_bam platform = dd.get_platform(paired.tumor_data) genome_build = paired.tumor_data["genome_build"] # scale cores to avoid over-using memory during imputation cores = max(1, int(dd.get_num_cores(paired.tumor_data) * 0.5)) gender = {"male": "XY", "female": "XX", "unknown": "L"}.get(population.get_gender(paired.tumor_data)) if gender == "L": gender_str = "-ge %s -gl %s" % (gender, gl_file) else: gender_str = "-ge %s" % (gender) r_export_cmd = utils.get_R_exports() local_sitelib = utils.R_sitelib() cmd = ("export R_LIBS_USER={local_sitelib} && {r_export_cmd} && " "battenberg.pl -t {cores} -o {work_dir} -r {ref_file}.fai " "-tb {tumor_bam} -nb {normal_bam} -e {bat_datadir}/impute/impute_info.txt " "-u {bat_datadir}/1000genomesloci -c {bat_datadir}/probloci.txt " "-ig {ignore_file} {gender_str} " "-assembly {genome_build} -species Human -platform {platform}") do.run(cmd.format(**locals()), "Battenberg CNV calling") assert len(_missing_files(out)) == 0, "Missing Battenberg output: %s" % _missing_files(out) out["plot"] = _get_battenberg_out_plots(paired, work_dir) out["ignore"] = ignore_file return out def _make_ignore_file(work_dir, ref_file, ignore_file, impute_file): """Create input files with chromosomes to ignore and gender loci. """ gl_file = os.path.join(work_dir, "gender_loci.txt") chroms = set([]) with open(impute_file) as in_handle: for line in in_handle: chrom = line.split()[0] chroms.add(chrom) if not chrom.startswith("chr"): chroms.add("chr%s" % chrom) with open(ignore_file, "w") as out_handle: for contig in ref.file_contigs(ref_file): if contig.name not in chroms: out_handle.write("%s\n" % contig.name) with open(gl_file, "w") as out_handle: for contig in ref.file_contigs(ref_file): if contig.name in ["Y", "chrY"]: # From https://github.com/cancerit/cgpBattenberg/blob/dev/perl/share/gender/GRCh37d5_Y.loci positions = [2934912, 4546684, 4549638, 4550107] for pos in positions: out_handle.write("%s\t%s\n" % (contig.name, pos)) return ignore_file, gl_file def _missing_files(out): missing_files = [] for key, fname in out.items(): if not os.path.exists(fname): missing_files.append((key, fname)) return missing_files def _get_battenberg_out(paired, work_dir): out = {} for key, ext in [("vrn_file", "battenberg_cn.vcf.gz"), ("subclones", "subclones.txt"), ("contamination", "normal_contamination.txt")]: out[key] = os.path.join(work_dir, "%s_%s" % (paired.tumor_name, ext)) return out def _get_battenberg_out_plots(paired, work_dir): out = {} for key, ext in [("copynumberprofile", "copynumberprofile"), ("sunrise_plot", "distance"), ("freq_plot", "Tumor")]: plot_file = os.path.join(work_dir, "%s_%s.png" % (paired.tumor_name, ext)) if os.path.exists(plot_file): out[key] = plot_file return out def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "battenberg")) bcbio-nextgen-1.2.9/bcbio/structural/cn_mops.py000066400000000000000000000253651415626112400215620ustar00rootroot00000000000000"""Copy number detection using read counts, with cn.mops. http://www.bioconductor.org/packages/release/bioc/html/cn.mops.html """ import os import re import shutil import subprocess import pysam import toolz as tz from bcbio import bam, utils from bcbio.distributed.multi import run_multicore, zeromq_aware_logging from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import shared from bcbio.provenance import do from bcbio.structural import shared as sshared from bcbio.variation import bedutils, vcfutils def run(items, background=None): """Detect copy number variations from batched set of samples using cn.mops. """ if not background: background = [] names = [tz.get_in(["rgnames", "sample"], x) for x in items + background] work_bams = [x["align_bam"] for x in items + background] if len(items + background) < 2: raise ValueError("cn.mops only works on batches with multiple samples") data = items[0] work_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", names[0], "cn_mops")) parallel = {"type": "local", "cores": data["config"]["algorithm"].get("num_cores", 1), "progs": ["delly"]} with pysam.Samfile(work_bams[0], "rb") as pysam_work_bam: chroms = [None] if _get_regional_bed_file(items[0]) else pysam_work_bam.references out_files = run_multicore(_run_on_chrom, [(chrom, work_bams, names, work_dir, items) for chrom in chroms], data["config"], parallel) out_file = _combine_out_files(out_files, work_dir, data) out = [] for data in items: if "sv" not in data: data["sv"] = [] data["sv"].append({"variantcaller": "cn_mops", "vrn_file": _prep_sample_cnvs(out_file, data)}) out.append(data) return out def _combine_out_files(chr_files, work_dir, data): """Concatenate all CNV calls into a single file. """ out_file = "%s.bed" % sshared.outname_from_inputs(chr_files) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for chr_file in chr_files: with open(chr_file) as in_handle: is_empty = in_handle.readline().startswith("track name=empty") if not is_empty: with open(chr_file) as in_handle: shutil.copyfileobj(in_handle, out_handle) return out_file def _prep_sample_cnvs(cnv_file, data): """Convert a multiple sample CNV file into a single BED file for a sample. Handles matching and fixing names where R converts numerical IDs (1234) into strings by adding an X (X1234), and converts other characters into '.'s. http://stat.ethz.ch/R-manual/R-devel/library/base/html/make.names.html """ import pybedtools sample_name = tz.get_in(["rgnames", "sample"], data) def make_names(name): return re.sub(r"[^\w.]", '.', name) def matches_sample_name(feat): return (feat.name == sample_name or feat.name == "X%s" % sample_name or feat.name == make_names(sample_name)) def update_sample_name(feat): feat.name = sample_name return feat sample_file = os.path.join(os.path.dirname(cnv_file), "%s-cnv.bed" % sample_name) if not utils.file_exists(sample_file): with file_transaction(data, sample_file) as tx_out_file: with shared.bedtools_tmpdir(data): pybedtools.BedTool(cnv_file).filter(matches_sample_name).each(update_sample_name).saveas(tx_out_file) return sample_file @utils.map_wrap @zeromq_aware_logging def _run_on_chrom(chrom, work_bams, names, work_dir, items): """Run cn.mops on work BAMs for a specific chromosome. """ local_sitelib = utils.R_sitelib() batch = sshared.get_cur_batch(items) ext = "-%s-cnv" % batch if batch else "-cnv" out_file = os.path.join(work_dir, "%s%s-%s.bed" % (os.path.splitext(os.path.basename(work_bams[0]))[0], ext, chrom if chrom else "all")) if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: rcode = "%s-run.R" % os.path.splitext(out_file)[0] with open(rcode, "w") as out_handle: out_handle.write(_script.format(prep_str=_prep_load_script(work_bams, names, chrom, items), out_file=tx_out_file, local_sitelib=local_sitelib)) rscript = utils.Rscript_cmd() try: do.run([rscript, "--vanilla", rcode], "cn.mops CNV detection", items[0], log_error=False) except subprocess.CalledProcessError as msg: # cn.mops errors out if no CNVs found. Just write an empty file. if _allowed_cnmops_errorstates(str(msg)): with open(tx_out_file, "w") as out_handle: out_handle.write('track name=empty description="No CNVs found"\n') else: logger.exception() raise return [out_file] def _allowed_cnmops_errorstates(msg): return (msg.find("No CNV regions in result object. Rerun cn.mops with different parameters") >= 0 or msg.find("Normalization might not be applicable for this small number of segments") >= 0 or msg.find("Error in if (is.finite(mv2m)) { : argument is of length zero") >= 0 or msg.find("Some normalization factors are zero") >= 0) def _prep_load_script(work_bams, names, chrom, items): if not chrom: chrom = "" pairmode = "paired" if bam.is_paired(work_bams[0]) else "unpaired" if len(items) == 2 and vcfutils.get_paired_phenotype(items[0]): load_script = _paired_load_script else: load_script = _population_load_script return load_script(work_bams, names, chrom, pairmode, items) def _get_regional_bed_file(data): """If we are running a non-genome analysis, pull the regional file for analysis. """ variant_regions = bedutils.merge_overlaps(tz.get_in(["config", "algorithm", "variant_regions"], data), data) is_genome = data["config"]["algorithm"].get("coverage_interval", "exome").lower() in ["genome"] if variant_regions and utils.file_exists(variant_regions) and not is_genome: return variant_regions def _population_load_script(work_bams, names, chrom, pairmode, items): """Prepare BAMs for assessing CNVs in a population. """ bed_file = _get_regional_bed_file(items[0]) if bed_file: return _population_prep_targeted.format(bam_file_str=",".join(work_bams), names_str=",".join(names), chrom=chrom, num_cores=0, pairmode=pairmode, bed_file=bed_file) else: return _population_prep.format(bam_file_str=",".join(work_bams), names_str=",".join(names), chrom=chrom, num_cores=0, pairmode=pairmode) def _paired_load_script(work_bams, names, chrom, pairmode, items): """Prepare BAMs for assessing CNVs in a paired tumor/normal setup. """ paired = vcfutils.get_paired_bams(work_bams, items) bed_file = _get_regional_bed_file(items[0]) if bed_file: return _paired_prep_targeted.format(case_file=paired.tumor_bam, case_name=paired.tumor_name, ctrl_file=paired.normal_bam, ctrl_name=paired.normal_name, num_cores=0, chrom=chrom, pairmode=pairmode, bed_file=bed_file) else: return _paired_prep.format(case_file=paired.tumor_bam, case_name=paired.tumor_name, ctrl_file=paired.normal_bam, ctrl_name=paired.normal_name, num_cores=0, chrom=chrom, pairmode=pairmode) _script = """ .libPaths(c("{local_sitelib}")) library(cn.mops) library(rtracklayer) {prep_str} calc_cnvs <- cnvs(cnv_out) strcn_to_cn <- function(x) {{ as.numeric(substring(x, 3, 20))}} calc_cnvs$score <- strcn_to_cn(calc_cnvs$CN) calc_cnvs$name <- calc_cnvs$sampleName export.bed(calc_cnvs, "{out_file}") """ _population_prep = """ bam_files <- strsplit("{bam_file_str}", ",")[[1]] sample_names <- strsplit("{names_str}", ",")[[1]] count_drs <- getReadCountsFromBAM(bam_files, sampleNames=sample_names, mode="{pairmode}", refSeqName="{chrom}", parallel={num_cores}) prep_counts <- cn.mops(count_drs, parallel={num_cores}) cnv_out <- calcIntegerCopyNumbers(prep_counts) """ _paired_prep = """ case_count <- getReadCountsFromBAM(c("{case_file}"), sampleNames=c("{case_name}"), mode="{pairmode}", refSeqName="{chrom}", parallel={num_cores}) ctrl_count <- getReadCountsFromBAM(c("{ctrl_file}"), sampleNames=c("{ctrl_name}"), mode="{pairmode}", refSeqName="{chrom}", parallel={num_cores}, WL=width(case_count)[[1]]) prep_counts <- referencecn.mops(case_count, ctrl_count, parallel={num_cores}) cnv_out <- calcIntegerCopyNumbers(prep_counts) """ _population_prep_targeted = """ bam_files <- strsplit("{bam_file_str}", ",")[[1]] sample_names <- strsplit("{names_str}", ",")[[1]] my_gr <- import.bed(c("{bed_file}"), trackLine=FALSE, asRangedData=FALSE) if ("{chrom}" != "") my_gr = subset(my_gr, seqnames(my_gr) == "{chrom}") if (length(my_gr) < 1) stop("No CNV regions in result object. Rerun cn.mops with different parameters!") count_drs <- getSegmentReadCountsFromBAM(bam_files, sampleNames=sample_names, mode="{pairmode}", GR=my_gr, parallel={num_cores}) prep_counts <- cn.mops(count_drs, parallel={num_cores}) cnv_out <- calcIntegerCopyNumbers(prep_counts) """ _paired_prep_targeted = """ my_gr <- import.bed(c("{bed_file}"), trackLine=FALSE, asRangedData=FALSE) if ("{chrom}" != "") my_gr = subset(my_gr, seqnames(my_gr) == "{chrom}") if (length(my_gr) < 1) stop("No CNV regions in result object. Rerun cn.mops with different parameters!") case_count <- getSegmentReadCountsFromBAM(c("{case_file}"), GR=my_gr, sampleNames=c("{case_name}"), mode="{pairmode}", parallel={num_cores}) ctrl_count <- getSegmentReadCountsFromBAM(c("{ctrl_file}"), GR=my_gr, sampleNames=c("{case_name}"), mode="{pairmode}", parallel={num_cores}) prep_counts <- referencecn.mops(case_count, ctrl_count, parallel={num_cores}) cnv_out <- calcIntegerCopyNumbers(prep_counts) """ bcbio-nextgen-1.2.9/bcbio/structural/cnvkit.py000066400000000000000000001063731415626112400214210ustar00rootroot00000000000000"""Copy number detection with CNVkit with specific support for targeted sequencing. http://cnvkit.readthedocs.org """ import collections import copy import glob import math import operator import os import shutil import sys import tempfile import pybedtools import numpy as np import toolz as tz from bcbio import utils from bcbio.bam import ref from bcbio.distributed.multi import run_multicore, zeromq_aware_logging from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.variation import effects, ploidy, population, vcfutils from bcbio.structural import annotate, plot, shared from functools import reduce def use_general_sv_bins(data): """Check if we should use a general binning approach for a sample. Checks if CNVkit is enabled and we haven't already run CNVkit. """ if any([c in dd.get_svcaller(data) for c in ["cnvkit", "titancna", "purecn", "gatk-cnv"]]): if not _get_original_coverage(data): return True return False def bin_approach(data): """Check for binning approach from configuration or normalized file. """ for approach in ["cnvkit", "gatk-cnv"]: if approach in dd.get_svcaller(data): return approach norm_file = tz.get_in(["depth", "bins", "normalized"], data) if norm_file.endswith(("-crstandardized.tsv", "-crdenoised.tsv")): return "gatk-cnv" if norm_file.endswith(".cnr"): return "cnvkit" def run(items, background=None): """Detect copy number variations from batched set of samples using CNVkit. """ if not background: background = [] return _cnvkit_by_type(items, background) def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "cnvkit")) def _cnvkit_by_type(items, background): """Dispatch to specific CNVkit functionality based on input type. """ if len(items + background) == 1: return _run_cnvkit_single(items[0]) elif vcfutils.get_paired_phenotype(items[0]): return _run_cnvkit_cancer(items, background) else: return _run_cnvkit_population(items, background) def _associate_cnvkit_out(ckouts, items, is_somatic=False): """Associate cnvkit output with individual items. """ assert len(ckouts) == len(items) out = [] upload_counts = collections.defaultdict(int) for ckout, data in zip(ckouts, items): ckout = copy.deepcopy(ckout) ckout["variantcaller"] = "cnvkit" if utils.file_exists(ckout["cns"]) and _cna_has_values(ckout["cns"]): ckout = _add_seg_to_output(ckout, data) ckout = _add_gainloss_to_output(ckout, data) ckout = _add_segmetrics_to_output(ckout, data) ckout = _add_variantcalls_to_output(ckout, data, items, is_somatic) # ckout = _add_coverage_bedgraph_to_output(ckout, data) ckout = _add_cnr_bedgraph_and_bed_to_output(ckout, data) if "svplots" in dd.get_tools_on(data): ckout = _add_plots_to_output(ckout, data) ckout["do_upload"] = upload_counts[ckout.get("vrn_file")] == 0 if "sv" not in data: data["sv"] = [] data["sv"].append(ckout) if ckout.get("vrn_file"): upload_counts[ckout["vrn_file"]] += 1 out.append(data) return out def _run_cnvkit_single(data, background=None): """Process a single input file with BAM or uniform background. """ if not background: background = [] ckouts = _run_cnvkit_shared([data], background) if not ckouts: return [data] else: assert len(ckouts) == 1 return _associate_cnvkit_out(ckouts, [data]) def _run_cnvkit_cancer(items, background): """Run CNVkit on a tumor/normal pair. """ paired = vcfutils.get_paired_bams([x["align_bam"] for x in items], items) normal_data = [x for x in items if dd.get_sample_name(x) != paired.tumor_name] tumor_ready, normal_ready = _match_batches(paired.tumor_data, normal_data[0] if normal_data else None) ckouts = _run_cnvkit_shared([tumor_ready], [normal_ready] if normal_ready else []) if not ckouts: return items assert len(ckouts) == 1 tumor_data = _associate_cnvkit_out(ckouts, [paired.tumor_data], is_somatic=True) return tumor_data + normal_data def _match_batches(tumor, normal): """Fix batch names for shared tumor/normals to ensure matching """ def _get_batch(x): b = dd.get_batch(x) return [b] if not isinstance(b, (list, tuple)) else b if normal: tumor = copy.deepcopy(tumor) normal = copy.deepcopy(normal) cur_batch = list(set(_get_batch(tumor)) & set(_get_batch(normal))) assert len(cur_batch) == 1, "No batch overlap: %s and %s" % (_get_batch(tumor), _get_batch(normal)) cur_batch = cur_batch[0] tumor["metadata"]["batch"] = cur_batch normal["metadata"]["batch"] = cur_batch return tumor, normal def _run_cnvkit_population(items, background): """Run CNVkit on a population of samples. Tries to calculate background based on case/controls, otherwise uses samples from the same batch as background. """ if background and len(background) > 0: inputs = items else: inputs, background = shared.find_case_control(items) # if we have case/control organized background or a single sample if len(inputs) == 1 or len(background) > 0: ckouts = _run_cnvkit_shared(inputs, background) return _associate_cnvkit_out(ckouts, inputs) + background # otherwise run each sample with the others in the batch as background else: out = [] for cur_input in items: background = [d for d in items if dd.get_sample_name(d) != dd.get_sample_name(cur_input)] ckouts = _run_cnvkit_shared([cur_input], background) out.extend(_associate_cnvkit_out(ckouts, [cur_input])) return out def _get_cmd(script_name="cnvkit.py"): return os.path.join(os.path.dirname(os.path.realpath(sys.executable)), script_name) def _prep_cmd(cmd, tx_out_file): """Wrap CNVkit commands ensuring we use local temporary directories. """ cmd = " ".join(cmd) if isinstance(cmd, (list, tuple)) else cmd return "export TMPDIR=%s && %s" % (os.path.dirname(tx_out_file), cmd) def _bam_to_outbase(bam_file, work_dir, data): """Convert an input BAM file into CNVkit expected output. Handles previous non-batch cases to avoid re-calculating, returning both new and old values: """ batch = dd.get_batch(data) or dd.get_sample_name(data) out_base = os.path.splitext(os.path.basename(bam_file))[0].split(".")[0] base = os.path.join(work_dir, out_base) return "%s-%s" % (base, batch), base def _get_original_coverage(data, itype="target"): """Back compatible: get existing coverage files if they exist """ work_dir = os.path.join(_sv_workdir(data), "raw") work_bam = dd.get_work_bam(data) or dd.get_align_bam(data) out = [] base, _ = _bam_to_outbase(work_bam, work_dir, data) target_cnn = "%s.targetcoverage.cnn" % base anti_cnn = "%s.antitargetcoverage.cnn" % base if os.path.exists(target_cnn) and os.path.exists(anti_cnn): out.append({"bam": work_bam, "file": target_cnn, "cnntype": "target", "itype": itype, "sample": dd.get_sample_name(data)}) out.append({"bam": work_bam, "file": anti_cnn, "cnntype": "antitarget", "itype": itype, "sample": dd.get_sample_name(data)}) return out def _run_cnvkit_shared(inputs, backgrounds): """Shared functionality to run CNVkit, parallelizing over multiple BAM files. Handles new style cases where we have pre-normalized inputs and old cases where we run CNVkit individually. """ if tz.get_in(["depth", "bins", "normalized"], inputs[0]): ckouts = [] for data in inputs: cnr_file = tz.get_in(["depth", "bins", "normalized"], data) cns_file = os.path.join(_sv_workdir(data), "%s.cns" % dd.get_sample_name(data)) cns_file = _cnvkit_segment(cnr_file, dd.get_coverage_interval(data), data, inputs + backgrounds, cns_file) ckouts.append({"cnr": cnr_file, "cns": cns_file, "background": tz.get_in(["depth", "bins", "background"], data)}) return ckouts else: return _run_cnvkit_shared_orig(inputs, backgrounds) def _get_original_targets(data): """Back compatible: get pre-existing target BEDs. """ work_dir = os.path.join(_sv_workdir(data), "raw") batch = dd.get_batch(data) or dd.get_sample_name(data) return (glob.glob(os.path.join(work_dir, "*-%s.target.bed" % batch))[0], glob.glob(os.path.join(work_dir, "*-%s.antitarget.bed" % batch))[0]) def _get_general_coverage(data, itype): """Retrieve coverage information from new shared SV bins. """ work_bam = dd.get_align_bam(data) or dd.get_work_bam(data) return [{"bam": work_bam, "file": tz.get_in(["depth", "bins", "target"], data), "cnntype": "target", "itype": itype, "sample": dd.get_sample_name(data)}, {"bam": work_bam, "file": tz.get_in(["depth", "bins", "antitarget"], data), "cnntype": "antitarget", "itype": itype, "sample": dd.get_sample_name(data)}] def _run_cnvkit_shared_orig(inputs, backgrounds): """Original CNVkit implementation with full normalization and segmentation. """ work_dir = _sv_workdir(inputs[0]) raw_work_dir = utils.safe_makedir(os.path.join(work_dir, "raw")) background_name = dd.get_sample_name(backgrounds[0]) if backgrounds else "flat" background_cnn = os.path.join(raw_work_dir, "%s_background.cnn" % (background_name)) ckouts = [] for cur_input in inputs: cur_raw_work_dir = utils.safe_makedir(os.path.join(_sv_workdir(cur_input), "raw")) out_base, out_base_old = _bam_to_outbase(dd.get_align_bam(cur_input), cur_raw_work_dir, cur_input) if utils.file_exists(out_base_old + ".cns"): out_base = out_base_old ckouts.append({"cnr": "%s.cnr" % out_base, "cns": "%s.cns" % out_base}) if not utils.file_exists(ckouts[0]["cns"]): cov_interval = dd.get_coverage_interval(inputs[0]) samples_to_run = list(zip(["background"] * len(backgrounds), backgrounds)) + \ list(zip(["evaluate"] * len(inputs), inputs)) # New style shared SV bins if tz.get_in(["depth", "bins", "target"], inputs[0]): target_bed = tz.get_in(["depth", "bins", "target"], inputs[0]) antitarget_bed = tz.get_in(["depth", "bins", "antitarget"], inputs[0]) raw_coverage_cnns = reduce(operator.add, [_get_general_coverage(cdata, itype) for itype, cdata in samples_to_run]) # Back compatible with pre-existing runs else: target_bed, antitarget_bed = _get_original_targets(inputs[0]) raw_coverage_cnns = reduce(operator.add, [_get_original_coverage(cdata, itype) for itype, cdata in samples_to_run]) # Currently metrics not calculated due to speed and needing re-evaluation # We could re-enable with larger truth sets to evaluate background noise # But want to reimplement in a more general fashion as part of normalization if False: coverage_cnns = reduce(operator.add, [_cnvkit_metrics(cnns, target_bed, antitarget_bed, cov_interval, inputs + backgrounds) for cnns in tz.groupby("bam", raw_coverage_cnns).values()]) background_cnn = cnvkit_background(_select_background_cnns(coverage_cnns), background_cnn, inputs, target_bed, antitarget_bed) else: coverage_cnns = raw_coverage_cnns background_cnn = cnvkit_background([x["file"] for x in coverage_cnns if x["itype"] == "background"], background_cnn, inputs, target_bed, antitarget_bed) parallel = {"type": "local", "cores": dd.get_cores(inputs[0]), "progs": ["cnvkit"]} fixed_cnrs = run_multicore(_cnvkit_fix, [(cnns, background_cnn, inputs, ckouts) for cnns in tz.groupby("bam", [x for x in coverage_cnns if x["itype"] == "evaluate"]).values()], inputs[0]["config"], parallel) [_cnvkit_segment(cnr, cov_interval, data, inputs + backgrounds) for cnr, data in fixed_cnrs] return ckouts def _cna_has_values(fname): with open(fname) as in_handle: for i, line in enumerate(in_handle): if i > 0: return True return False def _cnvkit_segment(cnr_file, cov_interval, data, items, out_file=None, detailed=False): """Perform segmentation and copy number calling on normalized inputs """ if not out_file: out_file = "%s.cns" % os.path.splitext(cnr_file)[0] if not utils.file_uptodate(out_file, cnr_file): with file_transaction(data, out_file) as tx_out_file: if not _cna_has_values(cnr_file): with open(tx_out_file, "w") as out_handle: out_handle.write("chromosome\tstart\tend\tgene\tlog2\tprobes\tCN1\tCN2\tbaf\tweight\n") else: # Scale cores to avoid memory issues with segmentation # https://github.com/etal/cnvkit/issues/346 if cov_interval == "genome": cores = max(1, dd.get_cores(data) // 2) else: cores = dd.get_cores(data) cmd = [_get_cmd(), "segment", "-p", str(cores), "-o", tx_out_file, cnr_file] small_vrn_files = _compatible_small_variants(data, items) if len(small_vrn_files) > 0 and _cna_has_values(cnr_file) and cov_interval != "genome": cmd += ["--vcf", small_vrn_files[0].name, "--sample-id", small_vrn_files[0].sample] if small_vrn_files[0].normal: cmd += ["--normal-id", small_vrn_files[0].normal] resources = config_utils.get_resources("options", data["config"]) user_options = resources.get("cnvkit_segment", []) cmd += [str(x) for x in user_options] if cov_interval == "genome" and "--threshold" not in user_options: cmd += ["--threshold", "0.00001"] # For tumors, remove very low normalized regions, avoiding upcaptured noise # https://github.com/bcbio/bcbio-nextgen/issues/2171#issuecomment-348333650 # unless we want detailed segmentation for downstream tools paired = vcfutils.get_paired(items) if paired: #if detailed: # cmd += ["-m", "hmm-tumor"] if "--drop-low-coverage" not in user_options: cmd += ["--drop-low-coverage"] # preferentially use conda installed Rscript export_cmd = ("%s && export TMPDIR=%s && " % (utils.get_R_exports(), os.path.dirname(tx_out_file))) do.run(export_cmd + " ".join(cmd), "CNVkit segment") return out_file def _cnvkit_metrics(cnns, target_bed, antitarget_bed, cov_interval, items): """Estimate noise of a sample using a flat background. Only used for panel/targeted data due to memory issues with whole genome samples. """ if cov_interval == "genome": return cnns target_cnn = [x["file"] for x in cnns if x["cnntype"] == "target"][0] background_file = "%s-flatbackground.cnn" % utils.splitext_plus(target_cnn)[0] background_file = cnvkit_background([], background_file, items, target_bed, antitarget_bed) cnr_file, data = _cnvkit_fix_base(cnns, background_file, items, "-flatbackground") cns_file = _cnvkit_segment(cnr_file, cov_interval, data) metrics_file = "%s-metrics.txt" % utils.splitext_plus(target_cnn)[0] if not utils.file_exists(metrics_file): with file_transaction(data, metrics_file) as tx_metrics_file: cmd = [_get_cmd(), "metrics", "-o", tx_metrics_file, "-s", cns_file, "--", cnr_file] do.run(_prep_cmd(cmd, tx_metrics_file), "CNVkit metrics") metrics = _read_metrics_file(metrics_file) out = [] for cnn in cnns: cnn["metrics"] = metrics out.append(cnn) return out def _read_metrics_file(in_file): with open(in_file) as in_handle: header = next(in_handle).strip().split("\t")[1:] vals = map(float, next(in_handle).strip().split("\t")[1:]) return dict(zip(header, vals)) @utils.map_wrap @zeromq_aware_logging def _cnvkit_fix(cnns, background_cnn, items, ckouts): """Normalize samples, correcting sources of bias. """ return [_cnvkit_fix_base(cnns, background_cnn, items, ckouts)] def _cnvkit_fix_base(cnns, background_cnn, items, ckouts, ext=""): assert len(cnns) == 2, "Expected target and antitarget CNNs: %s" % cnns target_cnn = [x["file"] for x in cnns if x["cnntype"] == "target"][0] antitarget_cnn = [x["file"] for x in cnns if x["cnntype"] == "antitarget"][0] dindex, data = [(i, x) for (i, x) in enumerate(items) if dd.get_sample_name(x) == cnns[0]["sample"]][0] out_file = ckouts[dindex]["cnr"] return (run_fix(target_cnn, antitarget_cnn, background_cnn, out_file, data), data) @utils.map_wrap @zeromq_aware_logging def run_fix_parallel(target_cnn, antitarget_cnn, background_cnn, out_file, data): return [run_fix(target_cnn, antitarget_cnn, background_cnn, out_file, data)] def run_fix(target_cnn, antitarget_cnn, background_cnn, out_file, data): if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [_get_cmd(), "fix", "-o", tx_out_file, target_cnn, antitarget_cnn, background_cnn, "--sample-id", dd.get_sample_name(data)] do.run(_prep_cmd(cmd, tx_out_file), "CNVkit fix") return out_file def _select_background_cnns(cnns): """Select cnns to use for background calculations. Uses background samples in cohort, and will remove CNNs with high on target variability. Uses (number of segments * biweight midvariance) as metric for variability with higher numbers being more unreliable. """ min_for_variability_analysis = 20 pct_keep = 0.10 b_cnns = [x for x in cnns if x["itype"] == "background" and x.get("metrics")] assert len(b_cnns) % 2 == 0, "Expect even set of target/antitarget cnns for background" if len(b_cnns) >= min_for_variability_analysis: b_cnns_w_metrics = [] for b_cnn in b_cnns: unreliability = b_cnn["metrics"]["segments"] * b_cnn["metrics"]["bivar"] b_cnns_w_metrics.append((unreliability, b_cnn)) b_cnns_w_metrics.sort() to_keep = int(math.ceil(pct_keep * len(b_cnns) / 2.0) * 2) b_cnns = [x[1] for x in b_cnns_w_metrics][:to_keep] assert len(b_cnns) % 2 == 0, "Expect even set of target/antitarget cnns for background" return [x["file"] for x in b_cnns] def cnvkit_background(background_cnns, out_file, items, target_bed=None, antitarget_bed=None): """Calculate background reference, handling flat case with no normal sample. """ if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: cmd = [_get_cmd(), "reference", "-f", dd.get_ref_file(items[0]), "-o", tx_out_file] gender = _get_batch_gender(items) if gender: cmd += ["--sample-sex", gender] if len(background_cnns) == 0: assert target_bed and antitarget_bed, "Missing CNNs and target BEDs for flat background" cmd += ["-t", target_bed, "-a", antitarget_bed] else: cmd += background_cnns do.run(_prep_cmd(cmd, tx_out_file), "CNVkit background") return out_file def _get_batch_gender(items): """Retrieve gender for a batch of items if consistent. Better not to specify for mixed populations, CNVkit will work it out https://github.com/bcbio/bcbio-nextgen/commit/1a0e217c8a4d3cee10fa890fb3cfd4db5034281d#r26279752 """ genders = set([population.get_gender(x) for x in items]) if len(genders) == 1: gender = genders.pop() if gender != "unknown": return gender def targets_w_bins(cnv_file, access_file, target_anti_fn, work_dir, data): """Calculate target and anti-target files with pre-determined bins. """ target_file = os.path.join(work_dir, "%s-target.bed" % dd.get_sample_name(data)) anti_file = os.path.join(work_dir, "%s-antitarget.bed" % dd.get_sample_name(data)) if not utils.file_exists(target_file): target_bin, _ = target_anti_fn() with file_transaction(data, target_file) as tx_out_file: cmd = [_get_cmd(), "target", cnv_file, "--split", "-o", tx_out_file, "--avg-size", str(target_bin)] do.run(_prep_cmd(cmd, tx_out_file), "CNVkit target") if not os.path.exists(anti_file): _, anti_bin = target_anti_fn() with file_transaction(data, anti_file) as tx_out_file: # Create access file without targets to avoid overlap # antitarget in cnvkit is meant to do this but appears to not always happen # after chromosome 1 tx_access_file = os.path.join(os.path.dirname(tx_out_file), os.path.basename(access_file)) pybedtools.BedTool(access_file).subtract(cnv_file).saveas(tx_access_file) cmd = [_get_cmd(), "antitarget", "-g", tx_access_file, cnv_file, "-o", tx_out_file, "--avg-size", str(anti_bin)] do.run(_prep_cmd(cmd, tx_out_file), "CNVkit antitarget") return target_file, anti_file def targets_from_background(back_cnn, work_dir, data): """Retrieve target and antitarget BEDs from background CNN file. """ target_file = os.path.join(work_dir, "%s.target.bed" % dd.get_sample_name(data)) anti_file = os.path.join(work_dir, "%s.antitarget.bed" % dd.get_sample_name(data)) if not utils.file_exists(target_file): with file_transaction(data, target_file) as tx_out_file: out_base = tx_out_file.replace(".target.bed", "") cmd = [_get_cmd("reference2targets.py"), "-o", out_base, back_cnn] do.run(_prep_cmd(cmd, tx_out_file), "CNVkit targets from background") shutil.copy(out_base + ".antitarget.bed", anti_file) return target_file, anti_file def _add_seg_to_output(out, data, enumerate_chroms=False): """Export outputs to 'seg' format compatible with IGV and GenePattern. """ out_file = "%s.seg" % os.path.splitext(out["cns"])[0] if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [os.path.join(os.path.dirname(sys.executable), "cnvkit.py"), "export", "seg"] if enumerate_chroms: cmd += ["--enumerate-chroms"] cmd += ["-o", tx_out_file, out["cns"]] do.run(cmd, "CNVkit export seg") out["seg"] = out_file return out def _add_cnr_bedgraph_and_bed_to_output(out, data): cnr_file = out["cnr"] bedgraph_file = os.path.join(_sv_workdir(data), os.path.basename(cnr_file) + ".bedgraph") if not utils.file_exists(bedgraph_file): with file_transaction(data, bedgraph_file) as tx_out_file: cmd = "sed 1d {cnr_file} | cut -f1,2,3,5 > {tx_out_file}" do.run(cmd.format(**locals()), "Converting cnr to bedgraph format") out["cnr_bedgraph"] = bedgraph_file bed_file = os.path.join(_sv_workdir(data), os.path.basename(cnr_file) + ".bed") if not utils.file_exists(bed_file): with file_transaction(data, bed_file) as tx_out_file: cmd = "sed 1d {cnr_file} | cut -f1,2,3,4,5 > {tx_out_file}" do.run(cmd.format(**locals()), "Converting cnr to bed format") out["cnr_bed"] = bed_file return out def _compatible_small_variants(data, items): """Retrieve small variant (SNP, indel) VCFs compatible with CNVkit. """ from bcbio import heterogeneity VarFile = collections.namedtuple("VarFile", ["name", "sample", "normal"]) out = [] paired = vcfutils.get_paired(items) for v in heterogeneity.get_variants(data, include_germline=not paired): vrn_file = v["vrn_file"] base, ext = utils.splitext_plus(os.path.basename(vrn_file)) if paired: out.append(VarFile(vrn_file, paired.tumor_name, paired.normal_name)) else: out.append(VarFile(vrn_file, dd.get_sample_name(data), None)) return out def _add_variantcalls_to_output(out, data, items, is_somatic=False): """Call ploidy and convert into VCF and BED representations. """ call_file = "%s-call%s" % os.path.splitext(out["cns"]) if not utils.file_exists(call_file): with file_transaction(data, call_file) as tx_call_file: filters = ["--filter", "cn"] cmd = [os.path.join(os.path.dirname(sys.executable), "cnvkit.py"), "call"] + \ filters + \ ["--ploidy", str(ploidy.get_ploidy([data])), "-o", tx_call_file, out["cns"]] small_vrn_files = _compatible_small_variants(data, items) if len(small_vrn_files) > 0 and _cna_has_values(out["cns"]): cmd += ["--vcf", small_vrn_files[0].name, "--sample-id", small_vrn_files[0].sample] if small_vrn_files[0].normal: cmd += ["--normal-id", small_vrn_files[0].normal] if not is_somatic: cmd += ["-m", "clonal"] gender = _get_batch_gender(items) if gender: cmd += ["--sample-sex", gender] do.run(cmd, "CNVkit call ploidy") calls = {} for outformat in ["bed", "vcf"]: out_file = "%s.%s" % (os.path.splitext(call_file)[0], outformat) calls[outformat] = out_file if not os.path.exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [os.path.join(os.path.dirname(sys.executable), "cnvkit.py"), "export", outformat, "--sample-id", dd.get_sample_name(data), "--ploidy", str(ploidy.get_ploidy([data])), "-o", tx_out_file, call_file] do.run(cmd, "CNVkit export %s" % outformat) out["call_file"] = call_file out["vrn_bed"] = annotate.add_genes(calls["bed"], data) effects_vcf, _ = effects.add_to_vcf(calls["vcf"], data, "snpeff") out["vrn_file"] = effects_vcf or calls["vcf"] out["vrn_file"] = shared.annotate_with_depth(out["vrn_file"], items) return out def _add_segmetrics_to_output(out, data): """Add metrics for measuring reliability of CNV estimates. """ out_file = "%s-segmetrics.txt" % os.path.splitext(out["cns"])[0] if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [os.path.join(os.path.dirname(sys.executable), "cnvkit.py"), "segmetrics", "--median", "--iqr", "--ci", "--pi", "-s", out["cns"], "-o", tx_out_file, out["cnr"]] # Use less fine grained bootstrapping intervals for whole genome runs if dd.get_coverage_interval(data) == "genome": cmd += ["--alpha", "0.1", "--bootstrap", "50"] else: cmd += ["--alpha", "0.01", "--bootstrap", "500"] do.run(cmd, "CNVkit segmetrics") out["segmetrics"] = out_file return out def _add_gainloss_to_output(out, data): """Add gainloss based on genes, helpful for identifying changes in smaller genes. """ out_file = "%s-gainloss.txt" % os.path.splitext(out["cns"])[0] if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [os.path.join(os.path.dirname(sys.executable), "cnvkit.py"), "gainloss", "-s", out["cns"], "-o", tx_out_file, out["cnr"]] gender = _get_batch_gender([data]) if gender: cmd += ["--sample-sex", gender] do.run(cmd, "CNVkit gainloss") out["gainloss"] = out_file return out def _add_coverage_bedgraph_to_output(out, data): """Add BedGraph representation of coverage to the output """ out_file = "%s.coverage.bedgraph" % os.path.splitext(out["cns"])[0] if utils.file_exists(out_file): out["bedgraph"] = out_file return out bam_file = dd.get_align_bam(data) bedtools = config_utils.get_program("bedtools", data["config"]) samtools = config_utils.get_program("samtools", data["config"]) cns_file = out["cns"] bed_file = tempfile.NamedTemporaryFile(suffix=".bed", delete=False).name with file_transaction(data, out_file) as tx_out_file: cmd = ("sed 1d {cns_file} | cut -f1,2,3 > {bed_file}; " "{samtools} view -b -L {bed_file} {bam_file} | " "{bedtools} genomecov -bg -ibam - -g {bed_file} >" "{tx_out_file}").format(**locals()) do.run(cmd, "CNVkit bedGraph conversion") os.remove(bed_file) out["bedgraph"] = out_file return out def _add_plots_to_output(out, data): """Add CNVkit plots summarizing called copy number values. """ out["plot"] = {} diagram_plot = _add_diagram_plot(out, data) if diagram_plot: out["plot"]["diagram"] = diagram_plot scatter = _add_scatter_plot(out, data) if scatter: out["plot"]["scatter"] = scatter scatter_global = _add_global_scatter_plot(out, data) if scatter_global: out["plot"]["scatter_global"] = scatter_global return out def _get_larger_chroms(ref_file): """Retrieve larger chromosomes, avoiding the smaller ones for plotting. """ from scipy.cluster.vq import kmeans, vq all_sizes = [] for c in ref.file_contigs(ref_file): all_sizes.append(float(c.size)) all_sizes.sort() if len(all_sizes) > 5: # separate out smaller chromosomes and haplotypes with kmeans centroids, _ = kmeans(np.array(all_sizes), 2) idx, _ = vq(np.array(all_sizes), centroids) little_sizes = tz.first(tz.partitionby(lambda xs: xs[0], zip(idx, all_sizes))) little_sizes = [x[1] for x in little_sizes] # create one more cluster with the smaller, removing the haplotypes centroids2, _ = kmeans(np.array(little_sizes), 2) idx2, _ = vq(np.array(little_sizes), centroids2) little_sizes2 = tz.first(tz.partitionby(lambda xs: xs[0], zip(idx2, little_sizes))) little_sizes2 = [x[1] for x in little_sizes2] # get any chromosomes not in haplotype/random bin thresh = max(little_sizes2) else: thresh = 0 larger_chroms = [] for c in ref.file_contigs(ref_file): if c.size > thresh: larger_chroms.append(c.name) return larger_chroms def _remove_haplotype_chroms(in_file, data): """Remove shorter haplotype chromosomes from cns/cnr files for plotting. """ larger_chroms = set(_get_larger_chroms(dd.get_ref_file(data))) out_file = os.path.join(_sv_workdir(data), "%s-chromfilter%s" % utils.splitext_plus(os.path.basename(in_file))) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: for line in in_handle: if ((line.find("chromosome") >= 0 and line.find("start") >= 0) or line.split()[0] in larger_chroms): out_handle.write(line) return out_file def _add_global_scatter_plot(out, data): out_file = os.path.join(_sv_workdir(data), os.path.splitext(os.path.basename(out["cnr"]))[0] + "-scatter_global.pdf") if utils.file_exists(out_file): return out_file cnr = _remove_haplotype_chroms(out["cnr"], data) cns = _remove_haplotype_chroms(out["cns"], data) with file_transaction(data, out_file) as tx_out_file: cmd = [_get_cmd(), "scatter", "-s", cns, "-o", tx_out_file, cnr] do.run(_prep_cmd(cmd, tx_out_file), "CNVkit global scatter plot") return out_file def _add_scatter_plot(out, data): out_file = os.path.join(_sv_workdir(data), os.path.splitext(os.path.basename(out["cnr"]))[0] + "-scatter.pdf") priority_bed = dd.get_svprioritize(data) if not priority_bed: return None priority_bed = plot._prioritize_plot_regions(pybedtools.BedTool(priority_bed), data, os.path.dirname(out_file)) if utils.file_exists(out_file): return out_file cnr = _remove_haplotype_chroms(out["cnr"], data) cns = _remove_haplotype_chroms(out["cns"], data) with file_transaction(data, out_file) as tx_out_file: cmd = [_get_cmd(), "scatter", "-s", cns, "-o", tx_out_file, "-l", priority_bed, cnr] do.run(_prep_cmd(cmd, tx_out_file), "CNVkit scatter plot") return out_file def _cnx_is_empty(in_file): """Check if cnr or cns files are empty (only have a header) """ with open(in_file) as in_handle: for i, line in enumerate(in_handle): if i > 0: return False return True def _add_diagram_plot(out, data): out_file = os.path.join(_sv_workdir(data), os.path.splitext(os.path.basename(out["cnr"]))[0] + "-diagram.pdf") cnr = _remove_haplotype_chroms(out["cnr"], data) cns = _remove_haplotype_chroms(out["cns"], data) if _cnx_is_empty(cnr) or _cnx_is_empty(cns): return None if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [_get_cmd(), "diagram", "-s", cns, "-o", tx_out_file, cnr] gender = _get_batch_gender([data]) if gender: cmd += ["--sample-sex", gender] do.run(_prep_cmd(cmd, tx_out_file), "CNVkit diagram plot") return out_file def segment_from_cnr(cnr_file, data, out_base): """Provide segmentation on a cnr file, used in external PureCN integration. """ cns_file = _cnvkit_segment(cnr_file, dd.get_coverage_interval(data), data, [data], out_file="%s.cns" % out_base, detailed=True) out = _add_seg_to_output({"cns": cns_file}, data, enumerate_chroms=False) return out["seg"] # ## Theta support def export_theta(ckout, data): """Provide updated set of data with export information for TheTA2 input. """ cns_file = chromhacks.bed_to_standardonly(ckout["cns"], data, headers="chromosome") cnr_file = chromhacks.bed_to_standardonly(ckout["cnr"], data, headers="chromosome") out_file = "%s-theta.input" % utils.splitext_plus(cns_file)[0] if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = [_get_cmd(), "export", "theta", cns_file, cnr_file, "-o", tx_out_file] do.run(_prep_cmd(cmd, tx_out_file), "Export CNVkit calls as inputs for TheTA2") ckout["theta_input"] = out_file return ckout bcbio-nextgen-1.2.9/bcbio/structural/convert.py000066400000000000000000000103231415626112400215700ustar00rootroot00000000000000"""Handle conversions between structural variant formats. """ import os import pybedtools import vcf from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.variation import vcfutils # ## Conversions to simplified BED files MAX_SVSIZE = 1e6 # 1Mb maximum size from callers to avoid huge calls collapsing all structural variants def _vcf_to_bed(in_file, caller, out_file): if in_file and in_file.endswith((".vcf", "vcf.gz")): with utils.open_gzipsafe(in_file) as in_handle: with open(out_file, "w") as out_handle: for rec in vcf.Reader(in_handle, in_file): if not rec.FILTER: if (rec.samples[0].gt_type != 0 and not (hasattr(rec.samples[0].data, "FT") and rec.samples[0].data.FT and rec.samples[0].data.FT not in ["PASS"])): start = max(0, rec.start - 1) end = rec.INFO.get("END") if not end: end = start + 1 if isinstance(end, (list, tuple)): end = end[0] end = int(end) if end - start < MAX_SVSIZE: out_handle.write("\t".join([rec.CHROM, str(start), str(end), "%s_%s" % (_get_svtype(rec), caller)]) + "\n") def _get_svtype(rec): try: return rec.INFO["SVTYPE"] except KeyError: return "-".join(str(x).replace("<", "").replace(">", "") for x in rec.ALT) def _cnvbed_to_bed(in_file, caller, out_file): """Convert cn_mops CNV based bed files into flattened BED """ with open(out_file, "w") as out_handle: for feat in pybedtools.BedTool(in_file): out_handle.write("\t".join([feat.chrom, str(feat.start), str(feat.end), "cnv%s_%s" % (feat.score, caller)]) + "\n") CALLER_TO_BED = {"lumpy": _vcf_to_bed, "longranger": _vcf_to_bed, "delly": _vcf_to_bed, "manta": _vcf_to_bed, "metasv": _vcf_to_bed, "cnvkit": _vcf_to_bed, "gridss": _vcf_to_bed, "seq2c": _vcf_to_bed, "cn_mops": _cnvbed_to_bed, "wham": _vcf_to_bed} SUBSET_BY_SUPPORT = {} def to_bed(call, sample, work_dir, calls, data): """Create a simplified BED file from caller specific input. """ out_file = os.path.join(work_dir, "%s-%s-flat.bed" % (sample, call["variantcaller"])) if call.get("vrn_file") and not utils.file_uptodate(out_file, call["vrn_file"]): with file_transaction(data, out_file) as tx_out_file: convert_fn = CALLER_TO_BED.get(call["variantcaller"]) if convert_fn: vrn_file = call["vrn_file"] if call["variantcaller"] in SUBSET_BY_SUPPORT: ecalls = [x for x in calls if x["variantcaller"] in SUBSET_BY_SUPPORT[call["variantcaller"]]] if len(ecalls) > 0: vrn_file = _subset_by_support(call["vrn_file"], ecalls, data) convert_fn(vrn_file, call["variantcaller"], tx_out_file) if utils.file_exists(out_file): return out_file def _subset_by_support(orig_vcf, cmp_calls, data): """Subset orig_vcf to calls also present in any of the comparison callers. """ cmp_vcfs = [x["vrn_file"] for x in cmp_calls] out_file = "%s-inensemble.vcf.gz" % utils.splitext_plus(orig_vcf)[0] if not utils.file_uptodate(out_file, orig_vcf): with file_transaction(data, out_file) as tx_out_file: cmd = "bedtools intersect -header -wa -f 0.5 -r -a {orig_vcf} -b " for cmp_vcf in cmp_vcfs: cmd += "<(bcftools view -f 'PASS,.' %s) " % cmp_vcf cmd += "| bgzip -c > {tx_out_file}" do.run(cmd.format(**locals()), "Subset calls by those present in Ensemble output") return vcfutils.bgzip_and_index(out_file, data["config"]) bcbio-nextgen-1.2.9/bcbio/structural/delly.py000066400000000000000000000215131415626112400212240ustar00rootroot00000000000000"""Structural variant calling with Delly https://github.com/tobiasrausch/delly """ import collections import copy import os import subprocess import vcf from bcbio import bam, utils from bcbio.distributed.multi import run_multicore, zeromq_aware_logging from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.structural import shared as sshared from bcbio.variation import vcfutils def _get_full_exclude_file(items, work_bams, work_dir): base_file = os.path.join(work_dir, "%s-svs" % (os.path.splitext(os.path.basename(work_bams[0]))[0])) return sshared.prepare_exclude_file(items, base_file) def _delly_exclude_file(items, base_file, chrom): """Prepare a delly-specific exclude file eliminating chromosomes. Delly wants excluded chromosomes listed as just the chromosome, with no coordinates. """ base_exclude = sshared.prepare_exclude_file(items, base_file, chrom) out_file = "%s-delly%s" % utils.splitext_plus(base_exclude) with file_transaction(items[0], out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: with open(base_exclude) as in_handle: for line in in_handle: parts = line.split("\t") if parts[0] == chrom: out_handle.write(line) else: out_handle.write("%s\n" % parts[0]) return out_file @utils.map_wrap @zeromq_aware_logging def _run_delly(bam_files, chrom, ref_file, work_dir, items): """Run delly, calling structural variations for the specified type. """ batch = sshared.get_cur_batch(items) ext = "-%s-svs" % batch if batch else "-svs" out_file = os.path.join(work_dir, "%s%s-%s.bcf" % (os.path.splitext(os.path.basename(bam_files[0]))[0], ext, chrom)) final_file = "%s.vcf.gz" % (utils.splitext_plus(out_file)[0]) cores = min(utils.get_in(items[0], ("config", "algorithm", "num_cores"), 1), len(bam_files)) if not utils.file_exists(out_file) and not utils.file_exists(final_file): with file_transaction(items[0], out_file) as tx_out_file: if sshared.has_variant_regions(items, out_file, chrom): exclude = ["-x", _delly_exclude_file(items, out_file, chrom)] cmd = ["delly", "call", "-g", ref_file, "-o", tx_out_file] + exclude + bam_files locale_to_use = utils.get_locale() multi_cmd = "export OMP_NUM_THREADS=%s && export LC_ALL=%s && " % (cores, locale_to_use) try: do.run(multi_cmd + " ".join(cmd), "delly structural variant") except subprocess.CalledProcessError as msg: # Small input samples, write an empty vcf if "Sample has not enough data to estimate library parameters" in str(msg): pass # delly returns an error exit code if there are no variants elif "No structural variants found" not in str(msg): raise return [_bgzip_and_clean(out_file, items)] def _bgzip_and_clean(bcf_file, items): """Create a clean bgzipped VCF output file from bcf for downstream processing. Also corrects problems with missing likelihoods: https://github.com/dellytools/delly/issues/37 GATK does not like missing GLs like '.,.,.'. This converts them to the recognized '.' """ out_file = "%s.vcf.gz" % (utils.splitext_plus(bcf_file)[0]) if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: if not utils.file_exists(bcf_file): vcfutils.write_empty_vcf(tx_out_file, samples=[dd.get_sample_name(d) for d in items]) else: cmd = (f"bcftools view {bcf_file} | " fr"sed 's/\.,\.,\././' | " f"bgzip -c > {tx_out_file}") do.run(cmd, "Convert and clean delly output") return vcfutils.bgzip_and_index(out_file, items[0]["config"]) @utils.map_wrap @zeromq_aware_logging def _prep_subsampled_bams(data, work_dir): """Prepare a subsampled BAM file with discordants from samblaster and minimal correct pairs. This attempts to minimize run times by pre-extracting useful reads mixed with subsampled normal pairs to estimate paired end distributions: https://groups.google.com/d/msg/delly-users/xmia4lwOd1Q/uaajoBkahAIJ Subsamples correctly aligned reads to 100 million based on speedseq defaults and evaluations on NA12878 whole genome data: https://github.com/cc2qe/speedseq/blob/ca624ba9affb0bd0fb88834ca896e9122639ec94/bin/speedseq#L1102 XXX Currently not used as new versions of delly do not get good sensitivity with downsampled BAMs. """ sr_bam, disc_bam = sshared.get_split_discordants(data, work_dir) ds_bam = bam.downsample(dd.get_align_bam(data), data, 1e8, read_filter="-F 'not secondary_alignment and proper_pair'", always_run=True, work_dir=work_dir) out_bam = "%s-final%s" % utils.splitext_plus(ds_bam) if not utils.file_exists(out_bam): bam.merge([ds_bam, sr_bam, disc_bam], out_bam, data["config"]) bam.index(out_bam, data["config"]) return [out_bam] def _delly_count_evidence_filter(in_file, data): """Filter delly outputs based on read support (DV) and evidence (split and paired). We require DV > 4 and either both paired end and split read evidence or 5 or more evidence for either individually. """ filtname = "DVSupport" filtdoc = "FMT/DV < 4 || (SR < 1 && PE < 5) || (SR < 5 && PE < 1)" out_file = "%s-filter%s" % utils.splitext_plus(in_file) cur_out_file = out_file.replace(".vcf.gz", ".vcf") if not utils.file_exists(out_file): with file_transaction(data, cur_out_file) as tx_out_file: with utils.open_gzipsafe(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: inp = vcf.Reader(in_handle, in_file) inp.filters["DVSupport"] = vcf.parser._Filter(filtname, filtdoc) outp = vcf.Writer(out_handle, inp) for rec in inp: sr = rec.INFO.get("SR", 0) pe = rec.INFO.get("PE", 0) call = rec.samples[0].data dv = call.DV if hasattr(call, "DV") else 0 if dv < 4 or (sr < 1 and pe < 5) or (sr < 5 and pe < 1): rec.add_filter(filtname) outp.write_record(rec) if out_file.endswith(".vcf.gz"): out_file = vcfutils.bgzip_and_index(cur_out_file, data["config"]) return out_file def run(items): """Perform detection of structural variations with delly. Performs post-call filtering with a custom filter tuned based on NA12878 Moleculo and PacBio data, using calls prepared by @ryanlayer and @cc2qe Filters using the high quality variant pairs (DV) compared with high quality reference pairs (DR). """ work_dir = utils.safe_makedir(os.path.join(items[0]["dirs"]["work"], "structural", dd.get_sample_name(items[0]), "delly")) # Add core request for delly config = copy.deepcopy(items[0]["config"]) delly_config = utils.get_in(config, ("resources", "delly"), {}) delly_config["cores"] = 1 config["resources"]["delly"] = delly_config parallel = {"type": "local", "cores": config["algorithm"].get("num_cores", 1), "progs": ["delly"]} work_bams = [dd.get_align_bam(d) for d in items] ref_file = dd.get_ref_file(items[0]) exclude_file = _get_full_exclude_file(items, work_bams, work_dir) bytype_vcfs = run_multicore(_run_delly, [(work_bams, chrom, ref_file, work_dir, items) for chrom in sshared.get_sv_chroms(items, exclude_file)], config, parallel) out_file = "%s.vcf.gz" % sshared.outname_from_inputs(bytype_vcfs) combo_vcf = vcfutils.combine_variant_files(bytype_vcfs, out_file, ref_file, config) out = [] upload_counts = collections.defaultdict(int) for data in items: if "sv" not in data: data["sv"] = [] base, ext = utils.splitext_plus(combo_vcf) final_vcf = sshared.finalize_sv(combo_vcf, data, items) if final_vcf: delly_vcf = _delly_count_evidence_filter(final_vcf, data) data["sv"].append({"variantcaller": "delly", "vrn_file": delly_vcf, "do_upload": upload_counts[final_vcf] == 0, # only upload a single file per batch "exclude": exclude_file}) upload_counts[final_vcf] += 1 out.append(data) return out bcbio-nextgen-1.2.9/bcbio/structural/gatkcnv.py000066400000000000000000000415601415626112400215540ustar00rootroot00000000000000"""Support for Copy Number Variations (CNVs) with GATK4 https://software.broadinstitute.org/gatk/documentation/article?id=11682 https://gatkforums.broadinstitute.org/dsde/discussion/11683/ """ import glob import os import shutil import numpy as np import toolz as tz from bcbio import broad, utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.variation import bedutils, vcfutils def run(items, background=None): """Detect copy number variations from batched set of samples using GATK4 CNV calling. TODO: implement germline calling with DetermineGermlineContigPloidy and GermlineCNVCaller """ if not background: background = [] paired = vcfutils.get_paired(items + background) if paired: out = _run_paired(paired) else: out = items logger.warn("GATK4 CNV calling currently only available for somatic samples: %s" % ", ".join([dd.get_sample_name(d) for d in items + background])) return out def _run_paired(paired): """Run somatic variant calling pipeline. """ from bcbio.structural import titancna work_dir = _sv_workdir(paired.tumor_data) seg_files = model_segments(tz.get_in(["depth", "bins", "normalized"], paired.tumor_data), work_dir, paired) call_file = call_copy_numbers(seg_files["seg"], work_dir, paired.tumor_data) out = [] if paired.normal_data: out.append(paired.normal_data) if "sv" not in paired.tumor_data: paired.tumor_data["sv"] = [] paired.tumor_data["sv"].append({"variantcaller": "gatk-cnv", "call_file": call_file, "vrn_file": titancna.to_vcf(call_file, "GATK4-CNV", _get_seg_header, _seg_to_vcf, paired.tumor_data), "seg": seg_files["seg"], "plot": plot_model_segments(seg_files, work_dir, paired.tumor_data)}) out.append(paired.tumor_data) return out def call_copy_numbers(seg_file, work_dir, data): """Call copy numbers from a normalized and segmented input file. """ out_file = os.path.join(work_dir, "%s-call.seg" % dd.get_sample_name(data)) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: params = ["-T", "CallCopyRatioSegments", "-I", seg_file, "-O", tx_out_file] _run_with_memory_scaling(params, tx_out_file, data) return out_file def plot_model_segments(seg_files, work_dir, data): """Diagnostic plots of segmentation and inputs. """ from bcbio.heterogeneity import chromhacks out_file = os.path.join(work_dir, "%s.modeled.png" % dd.get_sample_name(data)) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: dict_file = utils.splitext_plus(dd.get_ref_file(data))[0] + ".dict" plot_dict = os.path.join(os.path.dirname(tx_out_file), os.path.basename(dict_file)) with open(dict_file) as in_handle: with open(plot_dict, "w") as out_handle: for line in in_handle: if line.startswith("@SQ"): cur_chrom = [x.split(":", 1)[1].strip() for x in line.split("\t") if x.startswith("SN:")][0] if chromhacks.is_autosomal_or_sex(cur_chrom): out_handle.write(line) else: out_handle.write(line) params = ["-T", "PlotModeledSegments", "--denoised-copy-ratios", tz.get_in(["depth", "bins", "normalized"], data), "--segments", seg_files["final_seg"], "--allelic-counts", seg_files["tumor_hets"], "--sequence-dictionary", plot_dict, "--minimum-contig-length", "10", "--output-prefix", dd.get_sample_name(data), "-O", os.path.dirname(tx_out_file)] _run_with_memory_scaling(params, tx_out_file, data) return {"seg": out_file} def model_segments(copy_file, work_dir, paired): """Perform segmentation on input copy number log2 ratio file. """ out_file = os.path.join(work_dir, "%s.cr.seg" % dd.get_sample_name(paired.tumor_data)) tumor_counts, normal_counts = heterogzygote_counts(paired) if not utils.file_exists(out_file): with file_transaction(paired.tumor_data, out_file) as tx_out_file: params = ["-T", "ModelSegments", "--denoised-copy-ratios", copy_file, "--allelic-counts", tumor_counts, "--output-prefix", dd.get_sample_name(paired.tumor_data), "-O", os.path.dirname(tx_out_file)] if normal_counts: params += ["--normal-allelic-counts", normal_counts] _run_with_memory_scaling(params, tx_out_file, paired.tumor_data) for tx_fname in glob.glob(os.path.join(os.path.dirname(tx_out_file), "%s*" % dd.get_sample_name(paired.tumor_data))): shutil.copy(tx_fname, os.path.join(work_dir, os.path.basename(tx_fname))) return {"seg": out_file, "tumor_hets": out_file.replace(".cr.seg", ".hets.tsv"), "final_seg": out_file.replace(".cr.seg", ".modelFinal.seg")} def denoise(data, pon, work_dir): """Normalize read counts using panel of normal background or GC/mappability """ std_file = os.path.join(work_dir, "%s-crstandardized.tsv" % dd.get_sample_name(data)) denoise_file = os.path.join(work_dir, "%s-crdenoised.tsv" % dd.get_sample_name(data)) if not utils.file_exists(std_file): with file_transaction(data, std_file, denoise_file) as (tx_std_file, tx_denoise_file): params = ["-T", "DenoiseReadCounts", "-I", tz.get_in(["depth", "bins", "target"], data), "--standardized-copy-ratios", tx_std_file, "--denoised-copy-ratios", tx_denoise_file] if pon: params += ["--count-panel-of-normals", pon] else: params += ["--annotated-intervals", tz.get_in(["regions", "bins", "gcannotated"], data)] _run_with_memory_scaling(params, tx_std_file, data) return denoise_file if pon else std_file def create_panel_of_normals(items, group_id, work_dir): """Create a panel of normals from one or more background read counts. """ out_file = os.path.join(work_dir, "%s-%s-pon.hdf5" % (dd.get_sample_name(items[0]), group_id)) if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: params = ["-T", "CreateReadCountPanelOfNormals", "-O", tx_out_file, "--annotated-intervals", tz.get_in(["regions", "bins", "gcannotated"], items[0])] for data in items: params += ["-I", tz.get_in(["depth", "bins", "target"], data)] _run_with_memory_scaling(params, tx_out_file, items[0], ld_preload=True) return out_file def pon_to_bed(pon_file, out_dir, data): """Extract BED intervals from a GATK4 hdf5 panel of normal file. """ out_file = os.path.join(out_dir, "%s-intervals.bed" % (utils.splitext_plus(os.path.basename(pon_file))[0])) if not utils.file_uptodate(out_file, pon_file): import h5py with file_transaction(data, out_file) as tx_out_file: with h5py.File(pon_file, "r") as f: with open(tx_out_file, "w") as out_handle: intervals = f["original_data"]["intervals"] for i in range(len(intervals["transposed_index_start_end"][0])): chrom = intervals["indexed_contig_names"][intervals["transposed_index_start_end"][0][i]] if isinstance(chrom, bytes): chrom = chrom.decode("utf-8") start = int(intervals["transposed_index_start_end"][1][i]) - 1 end = int(intervals["transposed_index_start_end"][2][i]) out_handle.write("%s\t%s\t%s\n" % (chrom, start, end)) return out_file def prepare_intervals(data, region_file, work_dir): """Prepare interval regions for targeted and gene based regions. """ target_file = os.path.join(work_dir, "%s-target.interval_list" % dd.get_sample_name(data)) if not utils.file_uptodate(target_file, region_file): with file_transaction(data, target_file) as tx_out_file: params = ["-T", "PreprocessIntervals", "-R", dd.get_ref_file(data), "--interval-merging-rule", "OVERLAPPING_ONLY", "-O", tx_out_file] if dd.get_coverage_interval(data) == "genome": params += ["--bin-length", "1000", "--padding", "0"] else: params += ["-L", region_file, "--bin-length", "0", "--padding", "250"] _run_with_memory_scaling(params, tx_out_file, data) return target_file def annotate_intervals(target_file, data): """Provide GC annotated intervals for error correction during panels and denoising. TODO: include mappability and segmentation duplication inputs """ out_file = "%s-gcannotated.tsv" % utils.splitext_plus(target_file)[0] if not utils.file_uptodate(out_file, target_file): with file_transaction(data, out_file) as tx_out_file: params = ["-T", "AnnotateIntervals", "-R", dd.get_ref_file(data), "-L", target_file, "--interval-merging-rule", "OVERLAPPING_ONLY", "-O", tx_out_file] _run_with_memory_scaling(params, tx_out_file, data) return out_file def collect_read_counts(data, work_dir): """Count reads in defined bins using CollectReadCounts. """ out_file = os.path.join(work_dir, "%s-target-coverage.hdf5" % dd.get_sample_name(data)) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: params = ["-T", "CollectReadCounts", "-I", dd.get_align_bam(data), "-L", tz.get_in(["regions", "bins", "target"], data), "--interval-merging-rule", "OVERLAPPING_ONLY", "-O", tx_out_file, "--format", "HDF5"] _run_with_memory_scaling(params, tx_out_file, data) return out_file def heterogzygote_counts(paired): """Provide tumor/normal counts at population heterozyogte sites with CollectAllelicCounts. """ work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(paired.tumor_data), "structural", "counts")) key = "germline_het_pon" het_bed = tz.get_in(["genome_resources", "variation", key], paired.tumor_data) vr = bedutils.population_variant_regions([x for x in [paired.tumor_data, paired.normal_data] if x]) cur_het_bed = bedutils.intersect_two(het_bed, vr, work_dir, paired.tumor_data) tumor_counts = _run_collect_allelic_counts(cur_het_bed, key, work_dir, paired.tumor_data) normal_counts = (_run_collect_allelic_counts(cur_het_bed, key, work_dir, paired.normal_data) if paired.normal_data else None) if normal_counts: tumor_counts, normal_counts = _filter_by_normal(tumor_counts, normal_counts, paired.tumor_data) return tumor_counts, normal_counts def _filter_by_normal(tumor_counts, normal_counts, data): """Filter count files based on normal frequency and median depth, avoiding high depth regions. For frequency, restricts normal positions to those between 0.4 and 0.65 For depth, matches approach used in AMBER to try and avoid problematic genomic regions with high count in the normal: https://github.com/hartwigmedical/hmftools/tree/master/amber#usage """ from bcbio.heterogeneity import bubbletree fparams = bubbletree.NORMAL_FILTER_PARAMS tumor_out = "%s-normfilter%s" % utils.splitext_plus(tumor_counts) normal_out = "%s-normfilter%s" % utils.splitext_plus(normal_counts) if not utils.file_uptodate(tumor_out, tumor_counts): with file_transaction(data, tumor_out, normal_out) as (tx_tumor_out, tx_normal_out): median_depth = _get_normal_median_depth(normal_counts) min_normal_depth = median_depth * fparams["min_depth_percent"] max_normal_depth = median_depth * fparams["max_depth_percent"] with open(tumor_counts) as tumor_handle: with open(normal_counts) as normal_handle: with open(tx_tumor_out, "w") as tumor_out_handle: with open(tx_normal_out, "w") as normal_out_handle: header = None for t, n in zip(tumor_handle, normal_handle): if header is None: if not n.startswith("@"): header = n.strip().split() tumor_out_handle.write(t) normal_out_handle.write(n) elif (_normal_passes_depth(header, n, min_normal_depth, max_normal_depth) and _normal_passes_freq(header, n, fparams)): tumor_out_handle.write(t) normal_out_handle.write(n) return tumor_out, normal_out def _normal_passes_freq(header, line, fparams): vals = dict(zip(header, line.strip().split())) cur_depth = float(vals["REF_COUNT"]) + int(vals["ALT_COUNT"]) if cur_depth > 0: cur_freq = float(vals["ALT_COUNT"]) / cur_depth else: cur_freq = 0.0 return cur_freq >= fparams["min_freq_narrow"] and cur_freq <= fparams["max_freq_narrow"] def _normal_passes_depth(header, line, min_normal_depth, max_normal_depth): vals = dict(zip(header, line.strip().split())) cur_depth = int(vals["REF_COUNT"]) + int(vals["ALT_COUNT"]) return cur_depth >= min_normal_depth and cur_depth <= max_normal_depth def _get_normal_median_depth(normal_counts): depths = [] with open(normal_counts) as in_handle: header = None for line in in_handle: if header is None and not line.startswith("@"): header = line.strip().split() elif header: n_vals = dict(zip(header, line.strip().split())) depths.append(int(n_vals["REF_COUNT"]) + int(n_vals["ALT_COUNT"])) return np.median(depths) def _run_collect_allelic_counts(pos_file, pos_name, work_dir, data): """Counts by alleles for a specific sample and set of positions. """ out_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", "counts")) out_file = os.path.join(out_dir, "%s-%s-counts.tsv" % (dd.get_sample_name(data), pos_name)) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: params = ["-T", "CollectAllelicCounts", "-L", pos_file, "-I", dd.get_align_bam(data), "-R", dd.get_ref_file(data), "-O", tx_out_file] _run_with_memory_scaling(params, tx_out_file, data) return out_file def _run_with_memory_scaling(params, tx_out_file, data, ld_preload=False): num_cores = dd.get_num_cores(data) memscale = {"magnitude": 0.9 * num_cores, "direction": "increase"} if num_cores > 1 else None # Ignore tools_off: [gatk4], since it doesn't apply to GATK CNV calling config = utils.deepish_copy(data["config"]) if "gatk4" in dd.get_tools_off({"config": config}): config["algorithm"]["tools_off"].remove("gatk4") broad_runner = broad.runner_from_config(config) broad_runner.run_gatk(params, os.path.dirname(tx_out_file), memscale=memscale, ld_preload=ld_preload) # ## VCF output def _get_seg_header(in_handle): for line in in_handle: if not line.startswith("@"): break return line.strip().split("\t"), in_handle def _seg_to_vcf(vals): """Convert GATK CNV calls seg output to a VCF line. """ call_to_cn = {"+": 3, "-": 1} call_to_type = {"+": "DUP", "-": "DEL"} if vals["CALL"] not in ["0"]: info = ["FOLD_CHANGE_LOG=%s" % vals["MEAN_LOG2_COPY_RATIO"], "PROBES=%s" % vals["NUM_POINTS_COPY_RATIO"], "SVTYPE=%s" % call_to_type[vals["CALL"]], "SVLEN=%s" % (int(vals["END"]) - int(vals["START"])), "END=%s" % vals["END"], "CN=%s" % call_to_cn[vals["CALL"]]] return [vals["CONTIG"], vals["START"], ".", "N", "<%s>" % call_to_type[vals["CALL"]], ".", ".", ";".join(info), "GT", "0/1"] def _sv_workdir(data): return utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", dd.get_sample_name(data), "gatk-cnv")) bcbio-nextgen-1.2.9/bcbio/structural/gridss.py000066400000000000000000000120671415626112400214120ustar00rootroot00000000000000"""Structural variant detection with GRIDSS The Genomic Rearrangement IDentification Software Suite https://github.com/PapenfussLab/gridss """ import os import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.structural import shared as sshared from bcbio.variation import effects, vcfutils def run(items, background=None): """Perform detection of structural variations with Manta. """ paired = vcfutils.get_paired(items) if paired: inputs = [paired.tumor_data] background = [paired.normal_data] if paired.normal_bam else [] else: assert not background inputs, background = sshared.find_case_control(items) work_dir = _sv_workdir(inputs[0]) variant_file = _run_gridss(inputs, background, work_dir) out = [] for data in items: sample_file = variant_file if "sv" not in data: data["sv"] = [] effects_vcf, _ = effects.add_to_vcf(sample_file, data, "snpeff") data["sv"].append({"variantcaller": "gridss", "vrn_file": effects_vcf or sample_file}) out.append(data) return out def _run_gridss(inputs, background, work_dir): out_file = os.path.join(work_dir, "%s-gridss.sv.vcf" % (dd.get_batch(inputs[0]) or dd.get_sample_name(inputs[0]))) if not utils.file_exists(out_file) and not utils.file_exists(out_file + ".gz"): with file_transaction(inputs[0], out_file) as tx_out_file: htsjdk_opts = ["-Dsamjdk.create_index=true", "-Dsamjdk.use_async_io_read_samtools=true", "-Dsamjdk.use_async_io_write_samtools=true", "-Dsamjdk.use_async_io_write_tribble=true"] cores = dd.get_cores(inputs[0]) resources = config_utils.get_resources("gridss", inputs[0]["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx4g"]) jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": {"direction": "increase", "magnitude": cores}}}) jvm_opts = _finalize_memory(jvm_opts) tx_ref_file = _setup_reference_files(inputs[0], os.path.dirname(tx_out_file)) blacklist_bed = sshared.prepare_exclude_file(inputs + background, out_file) cmd = ["gridss"] + jvm_opts + htsjdk_opts + ["gridss.CallVariants"] + \ ["THREADS=%s" % cores, "TMP_DIR=%s" % os.path.dirname(tx_out_file), "WORKING_DIR=%s" % os.path.dirname(tx_out_file), "OUTPUT=%s" % tx_out_file, "ASSEMBLY=%s" % tx_out_file.replace(".sv.vcf", ".gridss.assembly.bam"), "REFERENCE_SEQUENCE=%s" % tx_ref_file, "BLACKLIST=%s" % blacklist_bed] for data in inputs + background: cmd += ["INPUT=%s" % dd.get_align_bam(data), "INPUT_LABEL=%s" % dd.get_sample_name(data)] exports = utils.local_path_export() cmd = exports + " ".join(cmd) do.run(cmd, "GRIDSS SV analysis") return vcfutils.bgzip_and_index(out_file, inputs[0]["config"]) def _finalize_memory(jvm_opts): """GRIDSS does not recommend setting memory between 32 and 48Gb. https://github.com/PapenfussLab/gridss#memory-usage """ avoid_min = 32 avoid_max = 48 out_opts = [] for opt in jvm_opts: if opt.startswith("-Xmx"): spec = opt[4:] val = int(spec[:-1]) mod = spec[-1] if mod.upper() == "M": adjust = 1024 min_val = avoid_min * 1024 max_val = avoid_max * 1024 else: adjust = 1 min_val, max_val = avoid_min, avoid_max if val >= min_val and val < max_val: val = min_val - adjust opt = "%s%s%s" % (opt[:4], val, mod) out_opts.append(opt) return out_opts def _setup_reference_files(data, tx_out_dir): """Create a reference directory with fasta and bwa indices. GRIDSS requires all files in a single directory, so setup with symlinks. This needs bwa aligner indices available, which we ensure with `get_aligner_with_aliases` during YAML sample setup. """ aligner = dd.get_aligner(data) or "bwa" out_dir = utils.safe_makedir(os.path.join(tx_out_dir, aligner)) ref_fasta = dd.get_ref_file(data) ref_files = ["%s%s" % (utils.splitext_plus(ref_fasta)[0], ext) for ext in [".fa", ".fa.fai", ".dict"]] for orig_file in ref_files + tz.get_in(("reference", aligner, "indexes"), data): utils.symlink_plus(orig_file, os.path.join(out_dir, os.path.basename(orig_file))) return os.path.join(out_dir, os.path.basename(ref_fasta)) def _sv_workdir(data): return os.path.join( data["dirs"]["work"], "structural", dd.get_sample_name(data), "gridss") bcbio-nextgen-1.2.9/bcbio/structural/hydra.py000066400000000000000000000160141415626112400212220ustar00rootroot00000000000000"""Use Hydra to detect structural variation using discordant read pairs. Hydra: http://code.google.com/p/hydra-sv/ Pipeline: http://code.google.com/p/hydra-sv/wiki/TypicalWorkflow """ import os import copy import collections import subprocess import pysam from bcbio import utils, broad from bcbio.pipeline.alignment import align_to_sort_bam from bcbio.pipeline import lane from bcbio.distributed.transaction import file_transaction from bcbio.structural import shared ## Prepare alignments to identify discordant pair mappings def select_unaligned_read_pairs(in_bam, extra, out_dir, config): """Retrieve unaligned read pairs from input alignment BAM, as two fastq files. """ runner = broad.runner_from_config(config) base, ext = os.path.splitext(os.path.basename(in_bam)) nomap_bam = os.path.join(out_dir, "{}-{}{}".format(base, extra, ext)) if not utils.file_exists(nomap_bam): with file_transaction(nomap_bam) as tx_out: runner.run("FilterSamReads", [("INPUT", in_bam), ("OUTPUT", tx_out), ("EXCLUDE_ALIGNED", "true"), ("WRITE_READS_FILES", "false"), ("SORT_ORDER", "queryname")]) has_reads = False with pysam.Samfile(nomap_bam, "rb") as in_pysam: for read in in_pysam: if read.is_paired: has_reads = True break if has_reads: out_fq1, out_fq2 = ["{}-{}.fq".format(os.path.splitext(nomap_bam)[0], i) for i in [1, 2]] runner.run_fn("picard_bam_to_fastq", nomap_bam, out_fq1, out_fq2) return out_fq1, out_fq2 else: return None, None def remove_nopairs(in_bam, out_dir, config): """Remove any reads without both pairs present in the file. """ runner = broad.runner_from_config(config) out_bam = os.path.join(out_dir, "{}-safepair{}".format(*os.path.splitext(os.path.basename(in_bam)))) if not utils.file_exists(out_bam): read_counts = collections.defaultdict(int) with pysam.Samfile(in_bam, "rb") as in_pysam: for read in in_pysam: if read.is_paired: read_counts[read.qname] += 1 with pysam.Samfile(in_bam, "rb") as in_pysam: with file_transaction(out_bam) as tx_out_bam: with pysam.Samfile(tx_out_bam, "wb", template=in_pysam) as out_pysam: for read in in_pysam: if read_counts[read.qname] == 2: out_pysam.write(read) return runner.run_fn("picard_sort", out_bam, "queryname") def tiered_alignment(in_bam, tier_num, multi_mappers, extra_args, genome_build, pair_stats, work_dir, dirs, config): """Perform the alignment of non-mapped reads from previous tier. """ nomap_fq1, nomap_fq2 = select_unaligned_read_pairs(in_bam, "tier{}".format(tier_num), work_dir, config) if nomap_fq1 is not None: base_name = "{}-tier{}out".format(os.path.splitext(os.path.basename(in_bam))[0], tier_num) config = copy.deepcopy(config) dirs = copy.deepcopy(dirs) config["algorithm"]["bam_sort"] = "queryname" config["algorithm"]["multiple_mappers"] = multi_mappers config["algorithm"]["extra_align_args"] = ["-i", int(pair_stats["mean"]), int(pair_stats["std"])] + extra_args out_bam, ref_file = align_to_sort_bam(nomap_fq1, nomap_fq2, lane.rg_names(base_name, base_name, config), genome_build, "novoalign", dirs, config, dir_ext=os.path.join("hydra", os.path.split(nomap_fq1)[0])) return out_bam else: return None ## Run hydra to identify structural variation breakpoints @utils.memoize_outfile(ext=".bed") def convert_bam_to_bed(in_bam, out_file): """Convert BAM to bed file using BEDTools. """ with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: subprocess.check_call(["bamToBed", "-i", in_bam, "-tag", "NM"], stdout=out_handle) return out_file @utils.memoize_outfile(ext="-pair.bed") def pair_discordants(in_bed, pair_stats, out_file): with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: subprocess.check_call(["pairDiscordants.py", "-i", in_bed, "-m", "hydra", "-z", str(int(pair_stats["median"]) + 10 * int(pair_stats["mad"]))], stdout=out_handle) return out_file @utils.memoize_outfile(ext="-dedup.bed") def dedup_discordants(in_bed, out_file): with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: subprocess.check_call(["dedupDiscordants.py", "-i", in_bed, "-s", "3"], stdout=out_handle) return out_file def run_hydra(in_bed, pair_stats): base_out = "{}-hydra.breaks".format(os.path.splitext(in_bed)[0]) final_file = "{}.final".format(base_out) if not utils.file_exists(final_file): subprocess.check_call(["hydra", "-in", in_bed, "-out", base_out, "-ms", "1", "-li", "-mld", str(int(pair_stats["mad"]) * 10), "-mno", str(int(pair_stats["median"]) + 20 * int(pair_stats["mad"]))]) return final_file def hydra_breakpoints(in_bam, pair_stats): """Detect structural variation breakpoints with hydra. """ in_bed = convert_bam_to_bed(in_bam) if os.path.getsize(in_bed) > 0: pair_bed = pair_discordants(in_bed, pair_stats) dedup_bed = dedup_discordants(pair_bed) return run_hydra(dedup_bed, pair_stats) else: return None ## Top level organizational code def detect_sv(align_bam, genome_build, dirs, config): """Detect structural variation from discordant aligned pairs. """ work_dir = utils.safe_makedir(os.path.join(dirs["work"], "structural")) pair_stats = shared.calc_paired_insert_stats(align_bam) fix_bam = remove_nopairs(align_bam, work_dir, config) tier2_align = tiered_alignment(fix_bam, "2", True, [], genome_build, pair_stats, work_dir, dirs, config) if tier2_align: tier3_align = tiered_alignment(tier2_align, "3", "Ex 1100", ["-t", "300"], genome_build, pair_stats, work_dir, dirs, config) if tier3_align: hydra_bps = hydra_breakpoints(tier3_align, pair_stats) bcbio-nextgen-1.2.9/bcbio/structural/lumpy.py000066400000000000000000000253361415626112400212700ustar00rootroot00000000000000"""Structural variation detection for split and paired reads using lumpy. Uses smoove for automating lumpy variant calling: https://github.com/brentp/smoove https://github.com/arq5x/lumpy-sv """ import collections import os import re import subprocess import six import vcf from bcbio import utils from bcbio.bam import ref from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.structural import shared as sshared from bcbio.variation import effects, vcfutils, vfilter # ## Lumpy main def _run_smoove(full_bams, sr_bams, disc_bams, work_dir, items): """Run lumpy-sv using smoove. """ data = items[0] batch = sshared.get_cur_batch(items) ext = "-%s-svs" % batch if batch else "-svs" name = "%s%s" % (dd.get_sample_name(items[0]), ext) out_file = os.path.join(work_dir, "%s-smoove.genotyped.vcf.gz" % name) sv_exclude_bed = sshared.prepare_exclude_file(items, out_file) old_out_file = os.path.join(work_dir, "%s%s-prep.vcf.gz" % (os.path.splitext(os.path.basename(items[0]["align_bam"]))[0], ext)) if utils.file_exists(old_out_file): return old_out_file, sv_exclude_bed if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: cores = dd.get_num_cores(items[0]) out_dir = os.path.dirname(tx_out_file) ref_file = dd.get_ref_file(items[0]) full_bams = " ".join(_prepare_smoove_bams(full_bams, sr_bams, disc_bams, items, os.path.dirname(tx_out_file))) std_excludes = ["~^GL", "~^HLA", "~_random", "~^chrUn", "~alt", "~decoy"] def _is_std_exclude(n): clean_excludes = [x.replace("~", "").replace("^", "") for x in std_excludes] return any([n.startswith(x) or n.endswith(x) for x in clean_excludes]) exclude_chrs = [c.name for c in ref.file_contigs(ref_file) if not chromhacks.is_nonalt(c.name) and not _is_std_exclude(c.name)] exclude_chrs = "--excludechroms '%s'" % ",".join(std_excludes + exclude_chrs) exclude_bed = ("--exclude %s" % sv_exclude_bed) if utils.file_exists(sv_exclude_bed) else "" tempdir = os.path.dirname(tx_out_file) smoove = config_utils.get_program("smoove", data) smoovepath = os.path.dirname(os.path.realpath(smoove)) cmd = ("export TMPDIR={tempdir} && export PATH={smoovepath}:$PATH && " "{smoove} call --processes {cores} --genotype --removepr --fasta {ref_file} " "--name {name} --outdir {out_dir} " "{exclude_bed} {exclude_chrs} {full_bams}") with utils.chdir(tempdir): try: do.run(cmd.format(**locals()), "smoove lumpy calling", items[0]) except subprocess.CalledProcessError as msg: if _allowed_errors(msg): vcfutils.write_empty_vcf(tx_out_file, config=items[0]["config"], samples=[dd.get_sample_name(d) for d in items]) else: logger.exception() raise vcfutils.bgzip_and_index(out_file, items[0]["config"]) return out_file, sv_exclude_bed def _prepare_smoove_bams(full_bams, sr_bams, disc_bams, items, tx_work_dir): """Prepare BAMs for smoove, linking in pre-existing split/disc BAMs if present. Smoove can use pre-existing discordant and split BAMs prepared by samblaster if present as $sample.split.bam and $sample.disc.bam. """ input_dir = utils.safe_makedir(tx_work_dir) out = [] for full, sr, disc, data in zip(full_bams, sr_bams, disc_bams, items): if sr and disc: new_full = os.path.join(input_dir, "%s.bam" % dd.get_sample_name(data)) new_sr = os.path.join(input_dir, "%s.split.bam" % dd.get_sample_name(data)) new_disc = os.path.join(input_dir, "%s.disc.bam" % dd.get_sample_name(data)) utils.symlink_plus(full, new_full) utils.symlink_plus(sr, new_sr) utils.symlink_plus(disc, new_disc) out.append(new_full) else: out.append(full) return out def _allowed_errors(msg): if six.PY3: msg = str(msg) else: msg = unicode(msg).encode("ascii", "replace") allowed = ["covmed: not enough reads to sample for bam stats", "missing pair end parameters:", "mean stdev read_length min_non_overlap"] return any([len(re.findall(m, msg)) > 0 for m in allowed]) def _filter_by_support(in_file, data): """Filter call file based on supporting evidence, adding FILTER annotations to VCF. Filters based on the following criteria: - Minimum read support for the call (SU = total support) - Large calls need split read evidence. """ rc_filter = ("FORMAT/SU < 4 || " "(FORMAT/SR == 0 && FORMAT/SU < 15 && ABS(SVLEN)>50000) || " "(FORMAT/SR == 0 && FORMAT/SU < 5 && ABS(SVLEN)<2000) || " "(FORMAT/SR == 0 && FORMAT/SU < 15 && ABS(SVLEN)<300)") return vfilter.cutoff_w_expression(in_file, rc_filter, data, name="ReadCountSupport", limit_regions=None) def _filter_by_background(base_name, back_samples, gt_vcfs, data): """Filter base samples, marking any also present in the background. """ filtname = "InBackground" filtdoc = "Variant also present in background samples with same genotype" orig_vcf = gt_vcfs[base_name] out_file = "%s-backfilter.vcf" % (utils.splitext_plus(orig_vcf)[0]) if not utils.file_exists(out_file) and not utils.file_exists(out_file + ".gz"): with file_transaction(data, out_file) as tx_out_file: with utils.open_gzipsafe(orig_vcf) as in_handle: inp = vcf.Reader(in_handle, orig_vcf) inp.filters[filtname] = vcf.parser._Filter(filtname, filtdoc) with open(tx_out_file, "w") as out_handle: outp = vcf.Writer(out_handle, inp) for rec in inp: if _genotype_in_background(rec, base_name, back_samples): rec.add_filter(filtname) outp.write_record(rec) if utils.file_exists(out_file + ".gz"): out_file = out_file + ".gz" gt_vcfs[base_name] = vcfutils.bgzip_and_index(out_file, data["config"]) return gt_vcfs def _genotype_in_background(rec, base_name, back_samples): """Check if the genotype in the record of interest is present in the background records. """ def passes(rec): return not rec.FILTER or len(rec.FILTER) == 0 return (passes(rec) and any(rec.genotype(base_name).gt_alleles == rec.genotype(back_name).gt_alleles for back_name in back_samples)) def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "lumpy")) def run(items): """Perform detection of structural variations with lumpy. """ paired = vcfutils.get_paired(items) work_dir = _sv_workdir(paired.tumor_data if paired and paired.tumor_data else items[0]) previous_evidence = {} full_bams, sr_bams, disc_bams = [], [], [] for data in items: full_bams.append(dd.get_align_bam(data)) sr_bam, disc_bam = sshared.find_existing_split_discordants(data) sr_bams.append(sr_bam) disc_bams.append(disc_bam) cur_dels, cur_dups = _bedpes_from_cnv_caller(data, work_dir) previous_evidence[dd.get_sample_name(data)] = {} if cur_dels and utils.file_exists(cur_dels): previous_evidence[dd.get_sample_name(data)]["dels"] = cur_dels if cur_dups and utils.file_exists(cur_dups): previous_evidence[dd.get_sample_name(data)]["dups"] = cur_dups lumpy_vcf, exclude_file = _run_smoove(full_bams, sr_bams, disc_bams, work_dir, items) lumpy_vcf = sshared.annotate_with_depth(lumpy_vcf, items) gt_vcfs = {} # Retain paired samples with tumor/normal genotyped in one file if paired and paired.normal_name: batches = [[paired.tumor_data, paired.normal_data]] else: batches = [[x] for x in items] for batch_items in batches: for data in batch_items: gt_vcfs[dd.get_sample_name(data)] = _filter_by_support(lumpy_vcf, data) if paired and paired.normal_name: gt_vcfs = _filter_by_background(paired.tumor_name, [paired.normal_name], gt_vcfs, paired.tumor_data) out = [] upload_counts = collections.defaultdict(int) for data in items: if "sv" not in data: data["sv"] = [] vcf_file = gt_vcfs.get(dd.get_sample_name(data)) if vcf_file: effects_vcf, _ = effects.add_to_vcf(vcf_file, data, "snpeff") data["sv"].append({"variantcaller": "lumpy", "vrn_file": effects_vcf or vcf_file, "do_upload": upload_counts[vcf_file] == 0, # only upload a single file per batch "exclude_file": exclude_file}) upload_counts[vcf_file] += 1 out.append(data) return out def _bedpes_from_cnv_caller(data, work_dir): """Retrieve BEDPEs deletion and duplications from CNV callers. Currently integrates with CNVkit. """ supported = set(["cnvkit"]) cns_file = None for sv in data.get("sv", []): if sv["variantcaller"] in supported and "cns" in sv and "lumpy_usecnv" in dd.get_tools_on(data): cns_file = sv["cns"] break if not cns_file: return None, None else: out_base = os.path.join(work_dir, utils.splitext_plus(os.path.basename(cns_file))[0]) out_dels = out_base + "-dels.bedpe" out_dups = out_base + "-dups.bedpe" if not os.path.exists(out_dels) or not os.path.exists(out_dups): with file_transaction(data, out_dels, out_dups) as (tx_out_dels, tx_out_dups): try: cnvanator_path = config_utils.get_program("cnvanator_to_bedpes.py", data) except config_utils.CmdNotFound: return None, None cmd = [cnvanator_path, "-c", cns_file, "--cnvkit", "--del_o=%s" % tx_out_dels, "--dup_o=%s" % tx_out_dups, "-b", "250"] # XXX Uses default piece size for CNVkit. Right approach? do.run(cmd, "Prepare CNVkit as input for lumpy", data) return out_dels, out_dups bcbio-nextgen-1.2.9/bcbio/structural/manta.py000066400000000000000000000200341415626112400212100ustar00rootroot00000000000000"""Structural variant detection with the Manta caller from Illumina. https://github.com/Illumina/manta """ import collections import glob import os from bcbio import utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.variation import vcfutils from bcbio.provenance import do, programs from bcbio.structural import shared def run(items): """Perform detection of structural variations with Manta. """ paired = vcfutils.get_paired(items) data = paired.tumor_data if paired else items[0] work_dir = _sv_workdir(data) variant_file = _get_out_file(work_dir, paired) if not utils.file_exists(variant_file): with file_transaction(data, work_dir) as tx_work_dir: utils.safe_makedir(tx_work_dir) tx_workflow_file = _prep_config(items, paired, tx_work_dir) _run_workflow(items, paired, tx_workflow_file, tx_work_dir) assert utils.file_exists(variant_file), "Manta finished without output file %s" % variant_file variant_file = shared.annotate_with_depth(variant_file, items) out = [] upload_counts = collections.defaultdict(int) for data in items: if "break-point-inspector" in dd.get_tools_on(data): if paired and paired.normal_bam and paired.tumor_name == dd.get_sample_name(data): variant_file = _run_break_point_inspector(data, variant_file, paired, work_dir) if "sv" not in data: data["sv"] = [] final_vcf = shared.finalize_sv(variant_file, data, items) vc = {"variantcaller": "manta", "do_upload": upload_counts[final_vcf] == 0, # only upload a single file per batch "vrn_file": final_vcf} evidence_bam = _get_evidence_bam(work_dir, data) if evidence_bam: vc["read_evidence"] = evidence_bam data["sv"].append(vc) upload_counts[final_vcf] += 1 out.append(data) return out def _run_break_point_inspector(data, variant_file, paired, work_dir): output_vcf = "%s-%s.vcf.gz" % (utils.splitext_plus(variant_file)[0], "bpi") stats_file = "%s-%s_stats.txt" % (utils.splitext_plus(variant_file)[0], "bpi") if not utils.file_exists(output_vcf): with file_transaction(data, output_vcf) as tx_output_vcf, file_transaction(data, stats_file) as tx_stats_file: cores = dd.get_num_cores(data) resources = config_utils.get_resources("break-point-inspector", data["config"]) jvm_mem_opts = config_utils.adjust_opts(resources.get("jvm_opts", ["-Xms1000m", "-Xmx2000m"]), {"algorithm": {"memory_adjust": {"magnitude": cores, "direction": "increase"}}}) jvm_tmp_arg = "-Djava.io.tmpdir=" + utils.safe_makedir(os.path.join(work_dir, "bpi_tmp")) cmd = ["break-point-inspector"] + jvm_mem_opts + [jvm_tmp_arg, "-vcf", variant_file] if paired: cmd += ["-ref", paired.normal_bam, "-tumor", paired.tumor_bam] cmd += ["-output_vcf", tx_output_vcf, ">", tx_stats_file] do.run(cmd, "Running Break Point Inspector for Manta SV calls") return output_vcf def _get_out_file(work_dir, paired): """Retrieve manta output variant file, depending on analysis. """ if paired: if paired.normal_bam: base_file = "somaticSV.vcf.gz" else: base_file = "tumorSV.vcf.gz" else: base_file = "diploidSV.vcf.gz" return os.path.join(work_dir, "results", "variants", base_file) def _get_evidence_bam(work_dir, data): """Retrieve evidence BAM for the sample if it exists """ evidence_bam = glob.glob(os.path.join(work_dir, "results", "evidence", "evidence_*.%s*.bam" % (dd.get_sample_name(data)))) if evidence_bam: return evidence_bam[0] def _run_workflow(items, paired, workflow_file, work_dir): """Run manta analysis inside prepared workflow directory. """ utils.remove_safe(os.path.join(work_dir, "workspace")) data = paired.tumor_data if paired else items[0] cmd = [utils.get_program_python("configManta.py"), workflow_file, "-m", "local", "-j", dd.get_num_cores(data)] do.run(cmd, "Run manta SV analysis") utils.remove_safe(os.path.join(work_dir, "workspace")) def _prep_config(items, paired, work_dir): """Run initial configuration, generating a run directory for Manta. """ assert utils.which("configManta.py"), "Could not find installed configManta.py" out_file = os.path.join(work_dir, "runWorkflow.py") if not utils.file_exists(out_file) or _out_of_date(out_file): config_script = os.path.realpath(utils.which("configManta.py")) cmd = [utils.get_program_python("configManta.py"), config_script] if paired: if paired.normal_bam: cmd += ["--normalBam=%s" % paired.normal_bam, "--tumorBam=%s" % paired.tumor_bam] else: cmd += ["--tumorBam=%s" % paired.tumor_bam] else: cmd += ["--bam=%s" % dd.get_align_bam(data) for data in items] data = paired.tumor_data if paired else items[0] cmd += ["--referenceFasta=%s" % dd.get_ref_file(data), "--runDir=%s" % work_dir] if dd.get_coverage_interval(data) not in ["genome"]: cmd += ["--exome"] for region in _maybe_limit_chromosomes(data): cmd += ["--region", region] resources = config_utils.get_resources("manta", data["config"]) if resources.get("options"): cmd += [str(x) for x in resources["options"]] # If we are removing polyX, avoid calling on small indels which require # excessively long runtimes on noisy WGS runs if "polyx" in dd.get_exclude_regions(data): cmd += ["--config", _prep_streamlined_config(config_script, work_dir)] do.run(cmd, "Configure manta SV analysis") return out_file def _prep_streamlined_config(config_script, work_dir): """Create manta INI file without steps that potentially increase runtimes. This removes calling of small indels. """ new_min_size = 100 in_file = config_script + ".ini" out_file = os.path.join(work_dir, os.path.basename(in_file)) with open(in_file) as in_handle: with open(out_file, "w") as out_handle: for line in in_handle: if line.startswith("minCandidateVariantSize"): out_handle.write("minCandidateVariantSize = %s\n" % new_min_size) else: out_handle.write(line) return out_file def _maybe_limit_chromosomes(data): """Potentially limit chromosomes to avoid problematically named HLA contigs. HLAs have ':' characters in them which confuse downstream processing. If we have no problematic chromosomes we don't limit anything. """ std_chroms = [] prob_chroms = [] noalt_calling = "noalt_calling" in dd.get_tools_on(data) or "altcontigs" in dd.get_exclude_regions(data) for contig in ref.file_contigs(dd.get_ref_file(data)): if contig.name.find(":") > 0 or (noalt_calling and not chromhacks.is_nonalt(contig.name)): prob_chroms.append(contig.name) else: std_chroms.append(contig.name) if len(prob_chroms) > 0: return std_chroms else: return [] def _sv_workdir(data): return os.path.join( data["dirs"]["work"], "structural", dd.get_sample_name(data), "manta") def _out_of_date(rw_file): """Check if a run workflow file points to an older version of manta and needs a refresh. """ with open(rw_file) as in_handle: for line in in_handle: if line.startswith("sys.path.append"): file_version = line.split("/lib/python")[0].split("Cellar/manta/")[-1] if file_version != programs.get_version_manifest("manta"): return True return False bcbio-nextgen-1.2.9/bcbio/structural/metasv.py000066400000000000000000000056411415626112400214160ustar00rootroot00000000000000"""Perform ensemble calling of structural variants using MetaSV. https://github.com/chapmanb/metasv http://dx.doi.org/10.1093/bioinformatics/btv204 """ import os import sys from bcbio import utils from bcbio.provenance import do from bcbio.pipeline import datadict as dd from bcbio.structural import shared from bcbio.variation import effects, vfilter MIN_CALLERS = 2 SUPPORTED = set(["manta", "lumpy", "cnvkit", "wham"]) def run(items): """Run MetaSV if we have enough supported callers, adding output to the set of calls. """ assert len(items) == 1, "Expect one input to MetaSV ensemble calling" data = items[0] work_dir = _sv_workdir(data) out_file = os.path.join(work_dir, "variants.vcf.gz") cmd = _get_cmd() + ["--sample", dd.get_sample_name(data), "--reference", dd.get_ref_file(data), "--bam", dd.get_align_bam(data), "--outdir", work_dir] methods = [] for call in data.get("sv", []): vcf_file = call.get("vcf_file", call.get("vrn_file", None)) if call["variantcaller"] in SUPPORTED and call["variantcaller"] not in methods and vcf_file is not None: methods.append(call["variantcaller"]) cmd += ["--%s_vcf" % call["variantcaller"], vcf_file] if len(methods) >= MIN_CALLERS: if not utils.file_exists(out_file): tx_work_dir = utils.safe_makedir(os.path.join(work_dir, "raw")) ins_stats = shared.calc_paired_insert_stats_save(dd.get_align_bam(data), os.path.join(tx_work_dir, "insert-stats.yaml")) cmd += ["--workdir", tx_work_dir, "--num_threads", str(dd.get_num_cores(data))] cmd += ["--spades", utils.which("spades.py"), "--age", utils.which("age_align")] cmd += ["--assembly_max_tools=1", "--assembly_pad=500"] cmd += ["--boost_sc", "--isize_mean", ins_stats["mean"], "--isize_sd", ins_stats["std"]] do.run(cmd, "Combine variant calls with MetaSV") filters = ("(NUM_SVTOOLS = 1 && ABS(SVLEN)>50000) || " "(NUM_SVTOOLS = 1 && ABS(SVLEN)<4000 && BA_FLANK_PERCENT>80) || " "(NUM_SVTOOLS = 1 && ABS(SVLEN)<4000 && BA_NUM_GOOD_REC=0) || " "(ABS(SVLEN)<4000 && BA_NUM_GOOD_REC>2)") filter_file = vfilter.cutoff_w_expression(out_file, filters, data, name="ReassemblyStats", limit_regions=None) effects_vcf, _ = effects.add_to_vcf(filter_file, data, "snpeff") data["sv"].append({"variantcaller": "metasv", "vrn_file": effects_vcf or filter_file}) return [data] def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "metasv")) def _get_cmd(): return [utils.get_program_python("run_metasv.py"), utils.which("run_metasv.py")] bcbio-nextgen-1.2.9/bcbio/structural/pindel.py000066400000000000000000000153111415626112400213650ustar00rootroot00000000000000"""calling using Pindel http://gmt.genome.wustl.edu/packages/pindel/ """ from __future__ import print_function import os import six import time import shutil from bcbio import bam, utils, broad from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.pipeline import config_utils from bcbio.pipeline.shared import subset_variant_regions, remove_lcr_regions from bcbio.variation.vcfutils import bgzip_and_index, get_paired_bams from bcbio.variation import annotation from bcbio.provenance import do from six.moves import zip def _pindel_options(items, config, out_file, region, tmp_path): """parse pindel options. Add region to cmd. :param items: (dict) information from yaml :param config: (dict) information from yaml (items[0]['config']) :param region: (str or tupple) region to analyze :param tmp_path: (str) temporal folder :returns: (list) options for pindel """ variant_regions = utils.get_in(config, ("algorithm", "variant_regions")) target = subset_variant_regions(variant_regions, region, out_file, items) opts = "" if target: if isinstance(target, six.string_types) and os.path.isfile(target): target_bed = target else: target_bed = os.path.join(tmp_path, "tmp.bed") with file_transaction(config, target_bed) as tx_tmp_bed: if not isinstance(region, (list, tuple)): message = ("Region must be a tuple - something odd just happened") raise ValueError(message) chrom, start, end = region with open(tx_tmp_bed, "w") as out_handle: print("%s\t%s\t%s" % (chrom, start, end), file=out_handle) opts = "-j " + remove_lcr_regions(target_bed, items) return opts def is_installed(config): """Check for pindel installation on machine. :param config: (dict) information from yaml(items[0]['config']) :returns: (boolean) if pindel is installed """ try: config_utils.get_program("pindel2vcf", config) config_utils.get_program("pindel", config) return True except config_utils.CmdNotFound: return False def _run_tumor_pindel_caller(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect indels with pindel in tumor/[normal] analysis. Only attempts to detect small insertion/deletions and not larger structural events. :param align_bam: (list) bam files :param items: (dict) information from yaml :param ref_file: (str) genome in fasta format :param assoc_file: (dict) files for annotation :param region: (str or tupple) region to analyze :param out_file: (str) final vcf file :returns: (str) final vcf file """ config = items[0]["config"] paired = get_paired_bams(align_bams, items) if out_file is None: out_file = "%s-indels.vcf" % os.path.splitext(align_bams[0])[0] paired_bam = [paired.tumor_bam] paired_name = [paired.tumor_name] if paired.normal_bam: paired_bam.append(paired.normal_bam) paired_name.append(paired.normal_name) if not utils.file_exists(out_file): with tx_tmpdir(config) as tmp_path: for align_bam in align_bams: bam.index(align_bam, config) root_pindel = os.path.join(tmp_path, "pindelroot") pindel = config_utils.get_program("pindel", config) opts = _pindel_options(items, config, out_file, region, tmp_path) tmp_input = _create_tmp_input(paired_bam, paired_name, tmp_path, config) cmd = ("{pindel} -f {ref_file} -i {tmp_input} -o {root_pindel} " + "{opts} --max_range_index 2 --IndelCorrection " "--report_breakpoints false --report_interchromosomal_events false") do.run(cmd.format(**locals()), "Genotyping with pindel", {}) out_file = _create_vcf(root_pindel, out_file, ref_file, items, paired) return out_file def _create_tmp_input(input_bams, names, tmp_path, config): """Create input file for pindel. tab file: bam file, insert size, name :param input_bams: (list) bam files :param names: (list) names of samples :param tmp_path: (str) temporal dir :param config: (dict) information from yaml file(itmes[0]['config']) :returns: (str) input file for pindel """ tmp_input = os.path.join(tmp_path, "pindel.txt") with open(tmp_input, 'w') as out_handle: for bam_file, name in zip(input_bams, names): print("%s\t%s\t%s\n" % (bam_file, 250, name), file=out_handle) return tmp_input def _create_vcf(root_file, out_file, reference, items, paired=None): """use pindel2vcf to create vcf file from pindel format :param root_file: (str) prefix for pindel :param out_file: (str) final vcf file :param reference (str) genome in fasta format :param items: (dics) information fro yaml file :param paired: (tupple) bam files and name of tumor/normal samples :returns: (str) final vcf file """ config = items[0]["config"] name_ref = items[0]["genome_build"] date = time.strftime("%Y%m%d") if not utils.file_exists(out_file): pindel2vcf = config_utils.get_program("pindel2vcf", config) vcf_file = out_file.replace(".gz", "") with file_transaction(items[0], vcf_file) as tx_out_file: cmd = ("{pindel2vcf} --gatk_compatible -P {root_file} -r {reference} -R {name_ref} " "-d {date} -v {tx_out_file} --compact_output_limit 15") do.run(cmd.format(**locals()), "Converting to vcf", {}) if paired.normal_name: _filter_paired(paired.tumor_name, paired.normal_name, tx_out_file, reference, items[0]) out_file = bgzip_and_index(vcf_file, config) return out_file def _filter_paired(tumor, normal, out_file, reference, data): """filter paired vcf file with GATK :param tumor: (str) sample name for tumor :param normal: (str) sample name for normal :param out_file: (str) final vcf file :param reference: (str) genome in fasta format :param data: (dict) information from yaml file(items[0]) :returns: (str) name of final vcf file """ in_file = utils.splitext_plus(out_file)[0] + "-tmp.vcf" shutil.move(out_file, in_file) config = data["config"] with file_transaction(data, out_file) as tx_out_file: params = ["-T", "SomaticPindelFilter", "-V", in_file, "-o", tx_out_file, "-TID", tumor, "-NID", normal, "-R", reference] jvm_opts = broad.get_gatk_opts(config) do.run(broad.gatk_cmd("gatk-framework", jvm_opts, params), "Filter pindel variants") return out_file bcbio-nextgen-1.2.9/bcbio/structural/plot.py000066400000000000000000000107211415626112400210700ustar00rootroot00000000000000"""Provide plots of structural variations to manually validate results. Uses existing plots from CNVkit along with custom plotting of coverage to provide the ability to quickly validate and explore predicted structural variants. """ import os from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.variation import vcfutils from bcbio.bam.coverage import plot_multiple_regions_coverage from bcbio.bed import concat from bcbio.utils import file_exists, safe_makedir from bcbio import bed def breakpoints_by_caller(bed_files): """ given a list of BED files of the form chrom start end caller return a BedTool of breakpoints as each line with the fourth column the caller with evidence for the breakpoint chr1 1 10 caller1 -> chr1 1 1 caller1 chr1 1 20 caller2 chr1 1 1 caller2 chr1 10 10 caller1 chr1 20 20 caller2 """ merged = concat(bed_files) if not merged: return [] grouped_start = merged.groupby(g=[1, 2, 2], c=4, o=["distinct"]).filter(lambda r: r.end > r.start).saveas() grouped_end = merged.groupby(g=[1, 3, 3], c=4, o=["distinct"]).filter(lambda r: r.end > r.start).saveas() together = concat([grouped_start, grouped_end]) if together: final = together.expand(c=4) final = final.sort() return final def _get_sv_callers(items): """ return a sorted list of all of the structural variant callers run """ callers = [] for data in items: for sv in data.get("sv", []): callers.append(sv["variantcaller"]) return list(set([x for x in callers if x != "sv-ensemble"])).sort() def _get_ensemble_bed_files(items): """ get all ensemble structural BED file calls, skipping any normal samples from tumor/normal calls """ bed_files = [] for data in items: for sv in data.get("sv", []): if sv["variantcaller"] == "sv-ensemble": if ("vrn_file" in sv and not vcfutils.get_paired_phenotype(data) == "normal" and file_exists(sv["vrn_file"])): bed_files.append(sv["vrn_file"]) return bed_files def _add_regional_coverage_plot(items, plot): out = [] added = False for data in items: for sv in data.get("sv", []): if not added and sv["variantcaller"] == "sv-ensemble": added = True if "plot" not in sv: sv["plot"] = {} sv["plot"]["coverage"] = plot out.append(data) return out def _prioritize_plot_regions(region_bt, data, out_dir=None): """Avoid plotting large numbers of regions due to speed issues. Prioritize most interesting. XXX For now, just removes larger regions and avoid plotting thousands of regions. Longer term we'll insert biology-based prioritization. """ max_plots = 1000 max_size = 100 * 1000 # 100kb out_file = "%s-priority%s" % utils.splitext_plus(region_bt.fn) if out_dir: out_file = os.path.join(out_dir, os.path.basename(out_file)) num_plots = 0 if not utils.file_uptodate(out_file, region_bt.fn): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for r in region_bt: if r.stop - r.start < max_size: if num_plots < max_plots: num_plots += 1 out_handle.write("%s\t%s\t%s\n" % (r.chrom, r.start, r.stop)) return out_file def by_regions(items): """Plot for a union set of combined ensemble regions across all of the data items. """ work_dir = os.path.join(dd.get_work_dir(items[0]), "structural", "coverage") safe_makedir(work_dir) out_file = os.path.join(work_dir, "%s-coverage.pdf" % (dd.get_sample_name(items[0]))) if file_exists(out_file): items = _add_regional_coverage_plot(items, out_file) else: bed_files = _get_ensemble_bed_files(items) merged = bed.merge(bed_files) breakpoints = breakpoints_by_caller(bed_files) if merged: priority_merged = _prioritize_plot_regions(merged, items[0]) out_file = plot_multiple_regions_coverage(items, out_file, items[0], priority_merged, breakpoints) items = _add_regional_coverage_plot(items, out_file) return items bcbio-nextgen-1.2.9/bcbio/structural/prioritize.py000066400000000000000000000253751415626112400223250ustar00rootroot00000000000000"""Prioritize structural variants based on biological information. Provides high level summaries of structural variants in regions of interest, as defined by the input configuration. Tries to narrow structural variant calls based on potential biological targets. """ import os import pandas as pd import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import bedutils, vcfutils POST_PRIOR_FNS = {} def run(items): assert len(items) == 1, ("Expect one input to biological prioritization: %s" % ", ".join([dd.get_sample_name(d) for d in items])) data = items[0] inputs = [] for call in data.get("sv", []): vcf_file = call.get("vcf_file", call.get("vrn_file")) if vcf_file and vcf_file.endswith((".vcf", "vcf.gz")): pp_fn = POST_PRIOR_FNS.get(call["variantcaller"]) if pp_fn: pp_fn = pp_fn(call) inputs.append((call["variantcaller"], vcf_file, pp_fn)) if len(inputs) > 0: prioritize_by = tz.get_in(["config", "algorithm", "svprioritize"], data) if prioritize_by: work_dir = _sv_workdir(data) priority_files = [_prioritize_vcf(vcaller, vfile, prioritize_by, post_prior_fn, work_dir, data) for vcaller, vfile, post_prior_fn in inputs] priority_tsv = _combine_files([xs[0] for xs in priority_files], work_dir, data) raw_files = {} for svcaller, fname in zip([xs[0] for xs in inputs], [xs[1] for xs in priority_files]): clean_fname = os.path.join(os.path.dirname(fname), "%s-%s-prioritized%s" % (dd.get_sample_name(data), svcaller, utils.splitext_plus(fname)[-1])) utils.symlink_plus(fname, clean_fname) raw_files[svcaller] = clean_fname data["sv"].append({"variantcaller": "sv-prioritize", "vrn_file": priority_tsv, "raw_files": raw_files}) # Disabled on move to CWL, not used and tested with CNVkit changes # data = _cnv_prioritize(data) return [data] def is_gene_list(bed_file): """Check if the file is only a list of genes, not a BED """ with utils.open_gzipsafe(bed_file) as in_handle: for line in in_handle: if not line.startswith("#"): if len(line.split()) == 1: return True else: return False def _find_gene_list_from_bed(bed_file, base_file, data): """Retrieve list of gene names from input BED file. """ # Check for a gene list, we can just return that. if is_gene_list(bed_file): return bed_file out_file = "%s-genes.txt" % utils.splitext_plus(base_file)[0] if not os.path.exists(out_file): genes = set([]) import pybedtools with utils.open_gzipsafe(bed_file) as in_handle: for r in pybedtools.BedTool(in_handle): if r.name: if not r.name.startswith("{"): genes.add(r.name) with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: if len(genes) > 0: out_handle.write("\n".join(sorted(list(genes))) + "\n") if utils.file_exists(out_file): return out_file def _prioritize_vcf(caller, vcf_file, prioritize_by, post_prior_fn, work_dir, data): """Provide prioritized tab delimited output for a single caller. """ sample = dd.get_sample_name(data) out_file = os.path.join(work_dir, "%s-%s-prioritize.tsv" % (sample, caller)) simple_vcf = os.path.join(work_dir, "%s-%s-simple.vcf.gz" % (sample, caller)) if not utils.file_exists(simple_vcf): gene_list = _find_gene_list_from_bed(prioritize_by, out_file, data) # If we have a standard gene list we can skip BED based prioritization priority_vcf = "%s.vcf.gz" % utils.splitext_plus(out_file)[0] if gene_list: if vcf_file.endswith(".vcf.gz"): utils.symlink_plus(vcf_file, priority_vcf) else: assert vcf_file.endswith(".vcf") utils.symlink_plus(vcf_file, priority_vcf.replace(".vcf.gz", ".vcf")) vcfutils.bgzip_and_index(priority_vcf.replace(".vcf.gz", ".vcf"), data["config"], remove_orig=False) # otherwise prioritize based on BED and proceed else: if not utils.file_exists(priority_vcf): with file_transaction(data, priority_vcf) as tx_out_file: resources = config_utils.get_resources("bcbio_prioritize", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms1g", "-Xmx4g"]) jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": {"direction": "increase", "maximum": "30000M", "magnitude": dd.get_cores(data)}}}) jvm_opts = " ".join(jvm_opts) export = utils.local_path_export() cmd = ("{export} bcbio-prioritize {jvm_opts} known -i {vcf_file} -o {tx_out_file} " " -k {prioritize_by}") do.run(cmd.format(**locals()), "Prioritize: select in known regions of interest") data_dir = os.path.dirname(os.path.realpath(utils.which("simple_sv_annotation.py"))) with file_transaction(data, simple_vcf) as tx_out_file: fusion_file = os.path.join(data_dir, "fusion_pairs.txt") opts = "" if os.path.exists(fusion_file): opts += " --known_fusion_pairs %s" % fusion_file if not gene_list: opts += " --gene_list %s" % os.path.join(data_dir, "az-cancer-panel.txt") else: opts += " --gene_list %s" % gene_list cmd = "simple_sv_annotation.py {opts} -o - {priority_vcf} | bgzip -c > {tx_out_file}" do.run(cmd.format(**locals()), "Prioritize: simplified annotation output") simple_vcf = vcfutils.bgzip_and_index(vcfutils.sort_by_ref(simple_vcf, data), data["config"]) if post_prior_fn: simple_vcf = post_prior_fn(simple_vcf, work_dir, data) if not utils.file_uptodate(out_file, simple_vcf): with file_transaction(data, out_file) as tx_out_file: export = utils.local_path_export(env_cmd="vawk") cmd = ("{export} zcat {simple_vcf} | vawk -v SNAME={sample} -v CALLER={caller} " """'{{if (($7 == "PASS" || $7 == ".") && (S${sample}$GT != "0/0")) """ "print CALLER,SNAME,$1,$2,I$END," """I$SVTYPE=="BND" ? I$SVTYPE":"$3":"I$MATEID : I$SVTYPE,""" "I$LOF,I$SIMPLE_ANN," "S${sample}$SR,S${sample}$PE,S${sample}$PR}}' > {tx_out_file}") do.run(cmd.format(**locals()), "Prioritize: convert to tab delimited") return out_file, simple_vcf def _combine_files(tsv_files, work_dir, data): """Combine multiple priority tsv files into a final sorted output. """ header = "\t".join(["caller", "sample", "chrom", "start", "end", "svtype", "lof", "annotation", "split_read_support", "paired_support_PE", "paired_support_PR"]) sample = dd.get_sample_name(data) out_file = os.path.join(work_dir, "%s-prioritize.tsv" % (sample)) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: tmpdir = os.path.dirname(tx_out_file) input_files = " ".join(tsv_files) sort_cmd = bedutils.get_sort_cmd(tmpdir) cmd = "{{ echo '{header}'; cat {input_files} | {sort_cmd} -k3,3 -k4,4n; }} > {tx_out_file}" do.run(cmd.format(**locals()), "Combine prioritized from multiple callers") return out_file def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "prioritize")) # ## CNV prioritization by genes of interest and confidence intervals def _cnvkit_prioritize(sample, genes, allele_file, metrics_file): """Summarize non-diploid calls with copy numbers and confidence intervals. """ mdf = pd.read_csv(metrics_file, sep="\t") mdf.columns = [x.lower() for x in mdf.columns] if len(genes) > 0: mdf = mdf[mdf["gene"].str.contains("|".join(genes))] mdf = mdf[["chromosome", "start", "end", "gene", "log2", "ci_hi", "ci_lo"]] adf = pd.read_csv(allele_file, sep="\t") if len(genes) > 0: adf = adf[adf["gene"].str.contains("|".join(genes))] if "cn1" in adf.columns and "cn2" in adf.columns: adf = adf[["chromosome", "start", "end", "cn", "cn1", "cn2"]] else: adf = adf[["chromosome", "start", "end", "cn"]] df = pd.merge(mdf, adf, on=["chromosome", "start", "end"]) df = df[df["cn"] != 2] if len(df) > 0: def passes(row): spread = abs(row["ci_hi"] - row["ci_lo"]) return spread < 0.25 df["passes"] = df.apply(passes, axis=1) df.insert(0, "sample", [sample] * len(df)) return df def _cnv_prioritize(data): """Perform confidence interval based prioritization for CNVs. """ supported = {"cnvkit": {"inputs": ["call_file", "segmetrics"], "fn": _cnvkit_prioritize}} pcall = None priority_files = None for call in data.get("sv", []): if call["variantcaller"] in supported: priority_files = [call.get(x) for x in supported[call["variantcaller"]]["inputs"]] priority_files = [x for x in priority_files if x is not None and utils.file_exists(x)] if len(priority_files) == len(supported[call["variantcaller"]]["inputs"]): pcall = call break prioritize_by = tz.get_in(["config", "algorithm", "svprioritize"], data) if pcall and prioritize_by: out_file = "%s-prioritize.tsv" % utils.splitext_plus(priority_files[0])[0] gene_list = _find_gene_list_from_bed(prioritize_by, out_file, data) if gene_list: with open(gene_list) as in_handle: genes = [x.strip() for x in in_handle] args = [dd.get_sample_name(data), genes] + priority_files df = supported[pcall["variantcaller"]]["fn"](*args) with file_transaction(data, out_file) as tx_out_file: df.to_csv(tx_out_file, sep="\t", index=False) pcall["priority"] = out_file return data bcbio-nextgen-1.2.9/bcbio/structural/purecn.py000066400000000000000000000527401415626112400214150ustar00rootroot00000000000000"""PureCN: Copy number calling and SNV classification using targeted short read sequencing https://github.com/lima1/PureCN """ import os import re import shutil import subprocess import pandas as pd import toolz as tz from bcbio import utils from bcbio.heterogeneity import chromhacks from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import loh from bcbio.provenance import do from bcbio.variation import germline, vcfutils from bcbio.structural import cnvkit, gatkcnv, regions def run(items): paired = vcfutils.get_paired(items) # paired is PairedInfo of one T/N pair (or just T) - named tuple, paired.tumor_config if not paired: logger.info("Skipping PureCN; no somatic tumor calls in batch: %s" % " ".join([dd.get_sample_name(d) for d in items])) return items work_dir = _sv_workdir(paired.tumor_data) normaldb = tz.get_in(["algorithm", "background", "cnv_reference", "purecn_normaldb"], paired.tumor_config) # the right way of running purecn is with normaldb if normaldb: purecn_out = _run_purecn_normaldb(paired, work_dir) # don't run signature analysis if there is no purecn solution if "rds" in purecn_out: purecn_out = _run_purecn_dx(purecn_out, paired) else: purecn_out = _run_purecn(paired, work_dir) out = [] if paired.normal_data: out.append(paired.normal_data) if purecn_out: purecn_out["variantcaller"] = "purecn" if "loh" in purecn_out: from bcbio.structural import titancna purecn_out["vrn_file"] = titancna.to_vcf(purecn_out["loh"], "PureCN", _get_header, _loh_to_vcf, paired.tumor_data, sep=",") purecn_out["lohsummary"] = loh.summary_status(purecn_out, paired.tumor_data) if "sv" not in paired.tumor_data: paired.tumor_data["sv"] = [] paired.tumor_data["sv"].append(purecn_out) out.append(paired.tumor_data) return out def _run_purecn_normaldb(paired, out): """Run PureCN with normaldb and native segmentation paired is one t/n pair or only """ sample = utils.to_single_data(paired.tumor_data) bed_file = tz.get_in(["config", "algorithm", "purecn_bed_ready"], sample) sample_name = dd.get_sample_name(sample) work_dir = _sv_workdir(sample) rscript = utils.Rscript_cmd() purecn_r = utils.R_package_script("PureCN", "extdata/PureCN.R", env="base") intervals = tz.get_in(["config", "algorithm", "purecn_bed_ready"], sample) bam_file = dd.get_align_bam(sample) # termline and somatic - just annotated and filters assigned variants_vcf = tz.get_in(["variants"], sample)[0].get("germline") # in a T/N case, there is no germline file - vrn file with all variants if not variants_vcf: variants_vcf = tz.get_in(["variants"], sample)[0].get("vrn_file") normaldb = tz.get_in(["config", "algorithm", "background", "cnv_reference", "purecn_normaldb"], sample) mappingbiasfile = tz.get_in(["config", "algorithm", "background", "cnv_reference", "purecn_mapping_bias"], sample) sample_coverage = tz.get_in(["depth", "bins", "purecn"], sample) simple_repeat_bed = dd.get_variation_resources(sample)["simple_repeat"] result_file = os.path.join(work_dir, sample_name + ".rds") genome = dd.get_genome_build(sample) cmd = [ rscript, purecn_r, "--out", work_dir, "--tumor", sample_coverage, "--sampleid", sample_name, "--vcf", variants_vcf, "--normaldb", normaldb, "--mapping-bias-file", mappingbiasfile, "--intervals", intervals, "--snp-blacklist", simple_repeat_bed, "--genome", genome, "--force", "--post-optimize", "--seed", "123", "--bootstrapn", "500", "--cores", dd.get_num_cores(sample)] resources = config_utils.get_resources("purecn", sample) if "options" in resources: cmd += [str(x) for x in resources.get("options", [])] # it is not recommended to use matched normal sample in PureCN analysis, # because then it skips PON coverage normalization and denoising steps! # but still, if it is supplied, we useit if paired.normal_data: normal_sample = utils.to_single_data(paired.normal_data) if normal_sample: normal_coverage = tz.get_in(["depth", "bins", "purecn"], normal_sample) cmd.extend(["--normal", normal_coverage]) if not os.path.exists(result_file): try: cmd_line = "export R_LIBS_USER=%s && %s && %s" % (utils.R_sitelib(env = "base"), utils.get_R_exports(env = "base"), " ".join([str(x) for x in cmd])) do.run(cmd_line, "PureCN copy number calling") logger.debug("Saved PureCN output to " + work_dir) except subprocess.CalledProcessError as msg: logger.info("PureCN failed") out_base, out, all_files = _get_purecn_files(paired, work_dir, require_exist = True) return out def _run_purecn_dx(out, paired): """Extract signatures and mutational burdens from PureCN rds file.""" # no solution - no signatures if not "rds" in out: return out rscript = utils.Rscript_cmd() purecndx_r = utils.R_package_script("PureCN", "extdata/Dx.R", env="base") simple_repeat_bed = dd.get_variation_resources(paired.tumor_data)["simple_repeat"] callable_bed = dd.get_sample_callable(paired.tumor_data) out_base = utils.splitext_plus(out["rds"])[0] mutation_burden_csv = out_base + "_mutation_burden.csv" if not utils.file_uptodate(mutation_burden_csv, out["rds"]): # no signatures - so we generate them with file_transaction(paired.tumor_data, out_base) as tx_out_base: cmd = [rscript, purecndx_r, "--rds", out["rds"], "--callable", callable_bed, "--signatures", "--exclude", simple_repeat_bed, "--out", tx_out_base] do.run(cmd, "PureCN Dx mutational burden and signatures") out_base, out, all_files = _get_purecn_dx_files(paired, out, require_exist = True) # if a file was not generated it would not go to the upload for f in all_files: if os.path.exists(os.path.join(os.path.dirname(tx_out_base), f)): shutil.move(os.path.join(os.path.dirname(tx_out_base), f), os.path.join(os.path.dirname(out_base), f)) return out def _get_purecn_dx_files(paired, out, require_exist = False): """Retrieve files generated by PureCN_Dx""" out_base = utils.splitext_plus(out["rds"])[0] all_files = [] for key, ext in [[("mutation_burden",), "_mutation_burden.csv"], [("plot", "signatures"), "_signatures.pdf"], [("signatures",), "_signatures.csv"], [("chrom_instability",), "_cin.csv"]]: cur_file = f"{out_base}{ext}" if not require_exist or os.path.exists(cur_file): out = tz.update_in(out, key, lambda x: cur_file) all_files.append(os.path.basename(cur_file)) return out_base, out, all_files def _run_purecn(paired, work_dir): """Run PureCN.R wrapper with pre-segmented CNVkit or GATK4 inputs. """ segfns = {"cnvkit": _segment_normalized_cnvkit, "gatk-cnv": _segment_normalized_gatk} out_base, out, all_files = _get_purecn_files(paired, work_dir) failed_file = out_base + "-failed.log" cnr_file = tz.get_in(["depth", "bins", "normalized"], paired.tumor_data) if not utils.file_uptodate(out["rds"], cnr_file) and not utils.file_exists(failed_file): cnr_file, seg_file = segfns[cnvkit.bin_approach(paired.tumor_data)](cnr_file, work_dir, paired) from bcbio import heterogeneity vcf_file = heterogeneity.get_variants(paired.tumor_data, include_germline=False)[0]["vrn_file"] vcf_file = germline.filter_to_pass_and_reject(vcf_file, paired, out_dir=work_dir) with file_transaction(paired.tumor_data, out_base) as tx_out_base: # Use UCSC style naming for human builds to support BSgenome genome = ("hg19" if dd.get_genome_build(paired.tumor_data) in ["GRCh37", "hg19"] else dd.get_genome_build(paired.tumor_data)) rscript = utils.Rscript_cmd() purecn_r = utils.R_package_script("PureCN", "extdata/PureCN.R", env="base") cmd = [rscript, purecn_r, "--seed", "42", "--out", tx_out_base, "--rds", "%s.rds" % tx_out_base, "--sampleid", dd.get_sample_name(paired.tumor_data), "--genome", genome, "--vcf", vcf_file, "--tumor", cnr_file, "--segfile", seg_file, "--funsegmentation", "Hclust", "--maxnonclonal", "0.3"] if dd.get_num_cores(paired.tumor_data) > 1: cmd += ["--cores", str(dd.get_num_cores(paired.tumor_data))] try: cmd = "export R_LIBS_USER=%s && %s && %s" % (utils.R_sitelib(env="base"), utils.get_R_exports(env="base"), " ".join([str(x) for x in cmd])) do.run(cmd, "PureCN copy number calling") except subprocess.CalledProcessError as msg: if _allowed_errors(str(msg)): logger.info("PureCN failed to find solution for %s: skipping" % dd.get_sample_name(paired.tumor_data)) with open(failed_file, "w") as out_handle: out_handle.write(str(msg)) else: logger.exception() raise for f in all_files: if os.path.exists(os.path.join(os.path.dirname(tx_out_base), f)): shutil.move(os.path.join(os.path.dirname(tx_out_base), f), os.path.join(os.path.dirname(out_base), f)) out = _get_purecn_files(paired, work_dir, require_exist=True)[1] return out if (out.get("rds") and os.path.exists(out["rds"])) else None def _allowed_errors(msg): allowed = ["Could not find valid purity and ploidy solution.", "Cannot find valid purity/ploidy solution", "None of the variants in provided VCF passed filtering."] return any([len(re.findall(m, msg)) > 0 for m in allowed]) def _segment_normalized_gatk(cnr_file, work_dir, paired): """Segmentation of normalized inputs using GATK4, converting into standard input formats. """ work_dir = utils.safe_makedir(os.path.join(work_dir, "gatk-cnv")) seg_file = gatkcnv.model_segments(cnr_file, work_dir, paired)["seg"] std_seg_file = seg_file.replace(".cr.seg", ".seg") if not utils.file_uptodate(std_seg_file, seg_file): with file_transaction(std_seg_file) as tx_out_file: df = pd.read_csv(seg_file, sep="\t", comment="@", header=0, names=["chrom", "loc.start", "loc.end", "num.mark", "seg.mean"]) df.insert(0, "ID", [dd.get_sample_name(paired.tumor_data)] * len(df)) df.to_csv(tx_out_file, sep="\t", header=True, index=False) std_cnr_file = os.path.join(work_dir, "%s.cnr" % dd.get_sample_name(paired.tumor_data)) if not utils.file_uptodate(std_cnr_file, cnr_file): with file_transaction(std_cnr_file) as tx_out_file: logdf = pd.read_csv(cnr_file, sep="\t", comment="@", header=0, names=["chrom", "start", "end", "log2"]) covdf = pd.read_csv(tz.get_in(["depth", "bins", "antitarget"], paired.tumor_data), sep="\t", header=None, names=["chrom", "start", "end", "orig.name", "depth", "gene"]) df = pd.merge(logdf, covdf, on=["chrom", "start", "end"]) del df["orig.name"] df = df[["chrom", "start", "end", "gene", "log2", "depth"]] df.insert(6, "weight", [1.0] * len(df)) df.to_csv(tx_out_file, sep="\t", header=True, index=False) return std_cnr_file, std_seg_file def _segment_normalized_cnvkit(cnr_file, work_dir, paired): """Segmentation of normalized inputs using CNVkit. """ cnvkit_base = os.path.join(utils.safe_makedir(os.path.join(work_dir, "cnvkit")), dd.get_sample_name(paired.tumor_data)) cnr_file = chromhacks.bed_to_standardonly(cnr_file, paired.tumor_data, headers="chromosome", include_sex_chroms=True, out_dir=os.path.dirname(cnvkit_base)) cnr_file = _remove_overlaps(cnr_file, os.path.dirname(cnvkit_base), paired.tumor_data) seg_file = cnvkit.segment_from_cnr(cnr_file, paired.tumor_data, cnvkit_base) return cnr_file, seg_file def _remove_overlaps(in_file, out_dir, data): """Remove regions that overlap with next region, these result in issues with PureCN. """ out_file = os.path.join(out_dir, "%s-nooverlaps%s" % utils.splitext_plus(os.path.basename(in_file))) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: with open(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: prev_line = None for line in in_handle: if prev_line: pchrom, pstart, pend = prev_line.split("\t", 4)[:3] cchrom, cstart, cend = line.split("\t", 4)[:3] # Skip if chromosomes match and end overlaps start if pchrom == cchrom and int(pend) > int(cstart): pass else: out_handle.write(prev_line) prev_line = line out_handle.write(prev_line) return out_file def _get_purecn_files(paired, work_dir, require_exist=False): """Retrieve organized structure of PureCN output files.""" sample_name = dd.get_sample_name(paired.tumor_data) out_base = os.path.join(work_dir, sample_name) out = {"plot": {}} all_files = [] for plot in ["chromosomes", "local_optima", "segmentation", "summary"]: if plot == "summary": cur_file = f"{out_base}.pdf" else: cur_file = f"{out_base}_{plot}.pdf" if not require_exist or os.path.exists(cur_file): out["plot"][plot] = cur_file all_files.append(os.path.basename(cur_file)) for key, ext in [["hetsummary", ".csv"], ["dnacopy", "_dnacopy.seg"], ["genes", "_genes.csv"], ["log", ".log"], ["loh", "_loh.csv"], ["rds", ".rds"], ["variants", "_variants.csv"]]: cur_file = f"{out_base}{ext}" if not require_exist or os.path.exists(cur_file): out[key] = cur_file all_files.append(os.path.basename(cur_file)) sample_name = dd.get_sample_name(paired.tumor_data) more_files = [sample_name + item for item in ["_amplification_pvalues.csv", "_chromosomes.pdf", ".csv", "_dnacopy.seg", "_genes.csv", "_local_optima.pdf", ".log", "_loh.csv", ".pdf", ".rds", "_segmentation.pdf", "_variants.csv"]] for purecn_file in more_files: purecn_file_path = os.path.join(work_dir, purecn_file) if not require_exist or os.path.exists(purecn_file_path): out[purecn_file] = purecn_file_path all_files.append(purecn_file_path) return out_base, out, all_files def _sv_workdir(data): return utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", dd.get_sample_name(data), "purecn")) # ## VCF output def _get_header(in_handle): return in_handle.readline().strip().split(","), in_handle def _loh_to_vcf(cur): """Convert LOH output into standardized VCF.""" # PureCN 1.14 outputs segments without informative SNPs, skip those # see https://github.com/lima1/PureCN/blob/ed7d10c7ca578bc7d1aabef86893c23ddddf79dc/NEWS#L92-L94 if cur["C"] == "NA" or cur["M"] == "NA": return None cn = int(float(cur["C"])) minor_cn = int(float(cur["M"])) if cur["type"].find("LOH") > -1: svtype = "LOH" elif cn > 2: svtype = "DUP" elif cn < 1: svtype = "DEL" else: svtype = None if svtype: # end could be 100.5 start = int(float(cur["start"])) end = int(float(cur["end"])) info = [f"SVTYPE={svtype}", f"END={end}", f"SVLEN={end-start+1}", f"CN={cn}", f"MajorCN={cn - minor_cn}", f"MinorCN={minor_cn}"] return [cur["chr"], cur["start"], ".", "N", "<%s>" % svtype, ".", ".", ";".join(info), "GT", "0/1"] def process_intervals(data): """Prepare intervals file""" bed_file = regions.get_sv_bed(data) if not bed_file: bed_file = bedutils.clean_file(dd.get_variant_regions(data), data) if not bed_file: return None basename = os.path.splitext(bed_file)[0] ready_file = basename + ".txt" if os.path.exists(ready_file): return ready_file optimized_bed = basename + ".optimized.bed" rscript = utils.Rscript_cmd("base") interval_file_r = utils.R_package_script("PureCN", "extdata/IntervalFile.R", env="base") ref_file = dd.get_ref_file(data) mappability_resource = dd.get_variation_resources(data)["purecn_mappability"] genome = dd.get_genome_build(data) tools_off = dd.get_tools_off(data) if tools_off and "purecn_offtarget" in tools_off: offtarget_flag = "" else: offtarget_flag = "--off-target" cmd = [rscript, interval_file_r, "--in-file", bed_file, "--fasta", ref_file, "--out-file", ready_file, offtarget_flag, "--genome", genome, "--export", optimized_bed, "--mappability", mappability_resource] try: cmd_line = "export R_LIBS_USER=%s && %s && %s" % (utils.R_sitelib(env = "base"), utils.get_R_exports(env = "base"), " ".join([str(x) for x in cmd])) do.run(cmd_line, "PureCN intervals") except subprocess.CalledProcessError as msg: logger.info("PureCN failed to prepare intervals") logger.debug("Saved PureCN interval file into " + ready_file) return ready_file def get_coverage(data): """Calculate coverage for a sample.bam, account for GC content data is single sample """ data = utils.to_single_data(data) bed_file = tz.get_in(["config", "algorithm", "purecn_bed_ready"], data) sample_name = dd.get_sample_name(data) work_dir = _sv_workdir(data) rscript = utils.Rscript_cmd("base") coverage_r = utils.R_package_script("PureCN", "extdata/Coverage.R", env="base") intervals = tz.get_in(["config", "algorithm", "purecn_bed_ready"], data) # PureCN resolves symlinks and the actual output PureCN coverage file name # is derived from the end bam not from bam_file bam_file = os.path.realpath(dd.get_align_bam(data)) bam_name = os.path.basename(bam_file) (bname, ext) = os.path.splitext(bam_name) result_file = os.path.join(work_dir, bname + "_coverage_loess.txt.gz") if not os.path.exists(result_file): cmd = [rscript, coverage_r, "--out-dir", work_dir, "--bam", bam_file, "--intervals", intervals] try: cmd_line = "export R_LIBS_USER=%s && %s && %s" % (utils.R_sitelib(env = "base"), utils.get_R_exports(env = "base"), " ".join([str(x) for x in cmd])) do.run(cmd_line, "PureCN coverage") except subprocess.CalledProcessError as msg: logger.info("PureCN failed to calculate coverage") logger.debug("Saved PureCN coverage files to " + result_file) return result_file def create_normal_db(coverage_files_txt, snv_pon, out_dir, genome_build): """create normal db input: coverage files calculated by purecn for each sample snv_pon - mutect2 SNV PON output: mapping_bias_hg38.rds normalDB_hg38.rds """ rscript = utils.Rscript_cmd("base") normaldb_r = utils.R_package_script("PureCN", "extdata/NormalDB.R", env="base") cmd = [rscript, normaldb_r, "--out-dir", out_dir, "--coverage-files", coverage_files_txt, "--normal-panel" , snv_pon, "--genome", genome_build, "--force"] try: cmd_line = "export R_LIBS_USER=%s && %s && %s" % (utils.R_sitelib(env = "base"), utils.get_R_exports(env = "base"), " ".join([str(x) for x in cmd])) do.run(cmd_line, "PureCN normalDB") except subprocess.CalledProcessError as msg: logger.info("PureCN failed to create a normal db") return out_dir bcbio-nextgen-1.2.9/bcbio/structural/purple.py000066400000000000000000000411401415626112400214200ustar00rootroot00000000000000"""PURPLE: Purity and ploidy estimates for somatic tumor/normal samples https://github.com/hartwigmedical/hmftools/tree/master/purity-ploidy-estimator """ import csv import os import re import shutil import subprocess import toolz as tz from bcbio import broad, utils from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.structural import titancna from bcbio.variation import vcfutils def run(items): paired = vcfutils.get_paired(items) if not paired or not paired.normal_name: logger.info("Skipping PURPLE; need tumor/normal somatic calls in batch: %s" % " ".join([dd.get_sample_name(d) for d in items])) return items work_dir = _sv_workdir(paired.tumor_data) from bcbio import heterogeneity vrn_files = heterogeneity.get_variants(paired.tumor_data, include_germline=False) het_file = _amber_het_file("pon", vrn_files, work_dir, paired) depth_file = _run_cobalt(paired, work_dir) purple_out = _run_purple(paired, het_file, depth_file, vrn_files, work_dir) out = [] if paired.normal_data: out.append(paired.normal_data) if "sv" not in paired.tumor_data: paired.tumor_data["sv"] = [] paired.tumor_data["sv"].append(purple_out) out.append(paired.tumor_data) return out def _get_jvm_opts(out_file, data): """Retrieve Java options, adjusting memory for available cores. """ resources = config_utils.get_resources("purple", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx3500m"]) jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": {"direction": "increase", "maximum": "30000M", "magnitude": dd.get_cores(data)}}}) jvm_opts += broad.get_default_jvm_opts(os.path.dirname(out_file)) return jvm_opts def _run_purple(paired, het_file, depth_file, vrn_files, work_dir): """Run PURPLE with pre-calculated AMBER and COBALT compatible inputs. """ purple_dir = utils.safe_makedir(os.path.join(work_dir, "purple")) out_file = os.path.join(purple_dir, "%s.purple.cnv" % dd.get_sample_name(paired.tumor_data)) if not utils.file_exists(out_file): with file_transaction(paired.tumor_data, out_file) as tx_out_file: cmd = ["PURPLE"] + _get_jvm_opts(tx_out_file, paired.tumor_data) + \ ["-amber", os.path.dirname(het_file), "-baf", het_file, "-cobalt", os.path.dirname(depth_file), "-gc_profile", dd.get_variation_resources(paired.tumor_data)["gc_profile"], "-output_dir", os.path.dirname(tx_out_file), "-ref_genome", "hg38" if dd.get_genome_build(paired.tumor_data) == "hg38" else "hg19", "-run_dir", work_dir, "-threads", dd.get_num_cores(paired.tumor_data), "-tumor_sample", dd.get_sample_name(paired.tumor_data), "-ref_sample", dd.get_sample_name(paired.normal_data)] if vrn_files: cmd += ["-somatic_vcf", vrn_files[0]["vrn_file"]] # Avoid X11 display errors when writing plots cmd = "unset DISPLAY && %s" % " ".join([str(x) for x in cmd]) do.run(cmd, "PURPLE: purity and ploidy estimation") for f in os.listdir(os.path.dirname(tx_out_file)): if f != os.path.basename(tx_out_file): shutil.move(os.path.join(os.path.dirname(tx_out_file), f), os.path.join(purple_dir, f)) out_file_export = os.path.join(purple_dir, "%s-purple-cnv.tsv" % (dd.get_sample_name(paired.tumor_data))) if not utils.file_exists(out_file_export): utils.symlink_plus(out_file, out_file_export) out = {"variantcaller": "purple", "call_file": out_file_export, "vrn_file": titancna.to_vcf(out_file_export, "PURPLE", _get_header, _export_to_vcf, paired.tumor_data), "plot": {}, "metrics": {}} for name, ext in [("copy_number", "copyNumber"), ("minor_allele", "minor_allele"), ("variant", "variant")]: plot_file = os.path.join(purple_dir, "plot", "%s.%s.png" % (dd.get_sample_name(paired.tumor_data), ext)) if os.path.exists(plot_file): out["plot"][name] = plot_file purity_file = os.path.join(purple_dir, "%s.purple.purity" % dd.get_sample_name(paired.tumor_data)) with open(purity_file) as in_handle: header = in_handle.readline().replace("#", "").split("\t") vals = in_handle.readline().split("\t") for h, v in zip(header, vals): try: v = float(v) except ValueError: pass out["metrics"][h] = v return out def _normalize_baf(baf): """Provide normalized BAF in the same manner as Amber, relative to het. https://github.com/hartwigmedical/hmftools/blob/637e3db1a1a995f4daefe2d0a1511a5bdadbeb05/hmf-common/src7/main/java/com/hartwig/hmftools/common/amber/AmberBAF.java#L16 """ if baf is None: baf = 0.0 return 0.5 + abs(baf - 0.5) def _counts_to_amber(t_vals, n_vals): """Converts a line of CollectAllelicCounts into AMBER line. """ t_depth = int(t_vals["REF_COUNT"]) + int(t_vals["ALT_COUNT"]) n_depth = int(n_vals["REF_COUNT"]) + int(n_vals["ALT_COUNT"]) if n_depth > 0 and t_depth > 0: t_baf = float(t_vals["ALT_COUNT"]) / float(t_depth) n_baf = float(n_vals["ALT_COUNT"]) / float(n_depth) return [t_vals["CONTIG"], t_vals["POSITION"], t_baf, _normalize_baf(t_baf), t_depth, n_baf, _normalize_baf(n_baf), n_depth] def _count_files_to_amber(tumor_counts, normal_counts, work_dir, data): """Converts tumor and normal counts from GATK CollectAllelicCounts into Amber format. """ amber_dir = utils.safe_makedir(os.path.join(work_dir, "amber")) out_file = os.path.join(amber_dir, "%s.amber.baf" % dd.get_sample_name(data)) if not utils.file_uptodate(out_file, tumor_counts): with file_transaction(data, out_file) as tx_out_file: with open(tumor_counts) as tumor_handle: with open(normal_counts) as normal_handle: with open(tx_out_file, "w") as out_handle: writer = csv.writer(out_handle, delimiter="\t") writer.writerow(["Chromosome", "Position", "TumorBAF", "TumorModifiedBAF", "TumorDepth", "NormalBAF", "NormalModifiedBAF", "NormalDepth"]) header = None for t, n in zip(tumor_handle, normal_handle): if header is None and t.startswith("CONTIG"): header = t.strip().split() elif header is not None: t_vals = dict(zip(header, t.strip().split())) n_vals = dict(zip(header, n.strip().split())) amber_line = _counts_to_amber(t_vals, n_vals) if amber_line: writer.writerow(amber_line) return out_file class AmberWriter: def __init__(self, out_handle): self.writer = csv.writer(out_handle, delimiter="\t") def write_header(self): self.writer.writerow(["Chromosome", "Position", "TumorBAF", "TumorModifiedBAF", "TumorDepth", "NormalBAF", "NormalModifiedBAF", "NormalDepth"]) def write_row(self, rec, stats): if stats["normal"]["freq"] is not None and stats["normal"]["depth"] is not None: self.writer.writerow([rec.chrom, rec.pos, stats["tumor"]["freq"], _normalize_baf(stats["tumor"]["freq"]), stats["tumor"]["depth"], stats["normal"]["freq"], _normalize_baf(stats["normal"]["freq"]), stats["normal"]["depth"]]) def _amber_het_file(method, vrn_files, work_dir, paired): """Create file of BAFs in normal heterozygous positions compatible with AMBER. Two available methods: - pon -- Use panel of normals with likely heterozygous sites. - variants -- Use pre-existing variant calls, filtered to likely heterozygotes. https://github.com/hartwigmedical/hmftools/tree/master/amber https://github.com/hartwigmedical/hmftools/blob/637e3db1a1a995f4daefe2d0a1511a5bdadbeb05/hmf-common/src/test/resources/amber/new.amber.baf """ assert vrn_files, "Did not find compatible variant calling files for PURPLE inputs" from bcbio.heterogeneity import bubbletree if method == "variants": amber_dir = utils.safe_makedir(os.path.join(work_dir, "amber")) out_file = os.path.join(amber_dir, "%s.amber.baf" % dd.get_sample_name(paired.tumor_data)) prep_file = bubbletree.prep_vrn_file(vrn_files[0]["vrn_file"], vrn_files[0]["variantcaller"], work_dir, paired, AmberWriter) utils.symlink_plus(prep_file, out_file) pcf_file = out_file + ".pcf" if not utils.file_exists(pcf_file): with file_transaction(paired.tumor_data, pcf_file) as tx_out_file: r_file = os.path.join(os.path.dirname(tx_out_file), "bafSegmentation.R") with open(r_file, "w") as out_handle: out_handle.write(_amber_seg_script) cmd = "%s && %s --vanilla %s %s %s" % (utils.get_R_exports(), utils.Rscript_cmd(), r_file, out_file, pcf_file) do.run(cmd, "PURPLE: AMBER baf segmentation") else: assert method == "pon" out_file = _run_amber(paired, work_dir) return out_file def _run_amber(paired, work_dir, lenient=False): """AMBER: calculate allele frequencies at likely heterozygous sites. lenient flag allows amber runs on small test sets. """ amber_dir = utils.safe_makedir(os.path.join(work_dir, "amber")) out_file = os.path.join(amber_dir, "%s.amber.baf" % dd.get_sample_name(paired.tumor_data)) if not utils.file_exists(out_file) or not utils.file_exists(out_file + ".pcf"): with file_transaction(paired.tumor_data, out_file) as tx_out_file: key = "germline_het_pon" het_bed = tz.get_in(["genome_resources", "variation", key], paired.tumor_data) cmd = ["AMBER"] + _get_jvm_opts(tx_out_file, paired.tumor_data) + \ ["-threads", dd.get_num_cores(paired.tumor_data), "-tumor", dd.get_sample_name(paired.tumor_data), "-tumor_bam", dd.get_align_bam(paired.tumor_data), "-reference", dd.get_sample_name(paired.normal_data), "-reference_bam", dd.get_align_bam(paired.normal_data), "-ref_genome", dd.get_ref_file(paired.tumor_data), "-bed", het_bed, "-output_dir", os.path.dirname(tx_out_file)] if lenient: cmd += ["-max_het_af_percent", "1.0"] try: do.run(cmd, "PURPLE: AMBER baf generation") except subprocess.CalledProcessError as msg: if not lenient and _amber_allowed_errors(str(msg)): return _run_amber(paired, work_dir, True) for f in os.listdir(os.path.dirname(tx_out_file)): if f != os.path.basename(tx_out_file): shutil.move(os.path.join(os.path.dirname(tx_out_file), f), os.path.join(amber_dir, f)) return out_file def _amber_allowed_errors(msg): allowed = ["R execution failed. Unable to complete segmentation."] return any([len(re.findall(m, msg)) > 0 for m in allowed]) # BAF segmentation with copynumber from AMBER # https://github.com/hartwigmedical/hmftools/blob/master/amber/src/main/resources/r/bafSegmentation.R _amber_seg_script = """ # Parse the arguments args <- commandArgs(trailing=T) bafFile <- args[1] pcfFile <- args[2] library(copynumber) baf <- read.table(bafFile, header=TRUE) chromosomeLevels = levels(baf$Chromosome) chromosomePrefix = "" if (any(grepl("chr", chromosomeLevels, ignore.case = T))) { chromosomePrefix = substr(chromosomeLevels[1], 1, 3) } baf <- baf[,c("Chromosome","Position","TumorModifiedBAF")] baf$Chromosome <- gsub(chromosomePrefix, "", baf$Chromosome, ignore.case = T) baf.seg<-pcf(baf,verbose=FALSE,gamma=100,kmin=1) baf.seg$chrom = paste0(chromosomePrefix, baf.seg$chrom) write.table(baf.seg, file = pcfFile, row.names = F, sep = "\t", quote = F) """ def _run_cobalt(paired, work_dir): """Run Cobalt for counting read depth across genomic windows. PURPLE requires even 1000bp windows so use integrated counting solution directly rather than converting from CNVkit calculations. If this approach is useful should be moved upstream to be available to other tools as an input comparison. https://github.com/hartwigmedical/hmftools/tree/master/count-bam-lines """ cobalt_dir = utils.safe_makedir(os.path.join(work_dir, "cobalt")) out_file = os.path.join(cobalt_dir, "%s.cobalt" % dd.get_sample_name(paired.tumor_data)) if not utils.file_exists(out_file): with file_transaction(paired.tumor_data, out_file) as tx_out_file: cmd = ["COBALT"] + _get_jvm_opts(tx_out_file, paired.tumor_data) + \ ["-reference", paired.normal_name, "-reference_bam", paired.normal_bam, "-tumor", paired.tumor_name, "-tumor_bam", paired.tumor_bam, "-threads", dd.get_num_cores(paired.tumor_data), "-output_dir", os.path.dirname(tx_out_file), "-gc_profile", dd.get_variation_resources(paired.tumor_data)["gc_profile"]] cmd = "%s && %s" % (utils.get_R_exports(), " ".join([str(x) for x in cmd])) do.run(cmd, "PURPLE: COBALT read depth normalization") for f in os.listdir(os.path.dirname(tx_out_file)): if f != os.path.basename(tx_out_file): shutil.move(os.path.join(os.path.dirname(tx_out_file), f), os.path.join(cobalt_dir, f)) return out_file def _cobalt_ratio_file(paired, work_dir): """Convert CNVkit binning counts into cobalt ratio output. This contains read counts plus normalization for GC, from section 7.2 "Determine read depth ratios for tumor and reference genomes" https://www.biorxiv.org/content/biorxiv/early/2018/09/20/415133.full.pdf Since CNVkit cnr files already have GC bias correction, we re-center the existing log2 ratios to be around 1, rather than zero, which matches the cobalt expectations. XXX This doesn't appear to be a worthwhile direction since PURPLE requires 1000bp even binning. We'll leave this here as a starting point for future work but work on using cobalt directly. """ cobalt_dir = utils.safe_makedir(os.path.join(work_dir, "cobalt")) out_file = os.path.join(cobalt_dir, "%s.cobalt" % dd.get_sample_name(paired.tumor_data)) if not utils.file_exists(out_file): cnr_file = tz.get_in(["depth", "bins", "normalized"], paired.tumor_data) with file_transaction(paired.tumor_data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: writer = csv.writer(out_handle, delimiter="\t") writer.writerow(["Chromosome", "Position", "ReferenceReadCount", "TumorReadCount", "ReferenceGCRatio", "TumorGCRatio", "ReferenceGCDiploidRatio"]) raise NotImplementedError return out_file def _sv_workdir(data): return utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", dd.get_sample_name(data), "purple")) # ## VCF output def _get_header(in_handle): return in_handle.readline().replace("#", "").strip().split(), in_handle def _export_to_vcf(cur): """Convert PURPLE custom output into VCF. """ if float(cur["copyNumber"]) > 2.0: svtype = "DUP" elif float(cur["copyNumber"]) < 2.0: svtype = "DEL" else: svtype = None if svtype: info = ["END=%s" % cur["end"], "SVLEN=%s" % (int(cur["end"]) - int(cur["start"])), "SVTYPE=%s" % svtype, "CN=%s" % cur["copyNumber"], "PROBES=%s" % cur["depthWindowCount"]] return [cur["chromosome"], cur["start"], ".", "N", "<%s>" % svtype, ".", ".", ";".join(info), "GT", "0/1"] bcbio-nextgen-1.2.9/bcbio/structural/regions.py000066400000000000000000000610301415626112400215570ustar00rootroot00000000000000"""Subset the genome into standard sets of regions surrounding transcripts. Provides a central place to bin the genome into smaller transcript-based regions for structural variant calling and prioritization. """ import collections import itertools import math import operator import os import numpy as np import pybedtools import toolz as tz from bcbio import utils from bcbio.bam import ref from bcbio.cwl import cwlutils from bcbio.distributed.multi import run_multicore from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.structural import gatkcnv from bcbio.variation import bedutils, multi from functools import reduce def calculate_sv_bins(*items): """Determine bin sizes and regions to use for samples. Unified approach to prepare regional bins for coverage calculations across multiple CNV callers. Splits into target and antitarget regions allowing callers to take advantage of both. Provides consistent target/anti-target bin sizes across batches. Uses callable_regions as the access BED file and mosdepth regions in variant_regions to estimate depth for bin sizes. """ calcfns = {"cnvkit": _calculate_sv_bins_cnvkit, "gatk-cnv": _calculate_sv_bins_gatk} from bcbio.structural import cnvkit items = [utils.to_single_data(x) for x in cwlutils.handle_combined_input(items)] from bcbio.structural import get_svcallers sv_callers = get_svcallers(items[0]) has_cnvkit_gatkcnv = bool(set(sv_callers) & set(["cnvkit", "gatk-cnv"])) if all(not cnvkit.use_general_sv_bins(x) for x in items) or not has_cnvkit_gatkcnv: return [[d] for d in items] out = [] for i, cnv_group in enumerate(_group_by_cnv_method(multi.group_by_batch(items, False))): size_calc_fn = MemoizedSizes(cnv_group.region_file, cnv_group.items).get_target_antitarget_bin_sizes for data in cnv_group.items: if cnvkit.use_general_sv_bins(data): target_bed, anti_bed, gcannotated_tsv = calcfns[cnvkit.bin_approach(data)](data, cnv_group, size_calc_fn) if not data.get("regions"): data["regions"] = {} data["regions"]["bins"] = {"target": target_bed, "antitarget": anti_bed, "group": str(i), "gcannotated": gcannotated_tsv} out.append([data]) if not len(out) == len(items): raise AssertionError("Inconsistent samples in and out of SV bin calculation:\nout: %s\nin : %s" % (sorted([dd.get_sample_name(utils.to_single_data(x)) for x in out]), sorted([dd.get_sample_name(x) for x in items]))) return out def _calculate_sv_bins_gatk(data, cnv_group, size_calc_fn): """Calculate structural variant bins using GATK4 CNV callers region or even intervals approach. """ if dd.get_background_cnv_reference(data, "gatk-cnv"): target_bed = gatkcnv.pon_to_bed(dd.get_background_cnv_reference(data, "gatk-cnv"), cnv_group.work_dir, data) else: target_bed = gatkcnv.prepare_intervals(data, cnv_group.region_file, cnv_group.work_dir) gc_annotated_tsv = gatkcnv.annotate_intervals(target_bed, data) return target_bed, None, gc_annotated_tsv def _calculate_sv_bins_cnvkit(data, cnv_group, size_calc_fn): """Calculate structural variant bins using target/anti-target approach from CNVkit. """ from bcbio.structural import cnvkit if dd.get_background_cnv_reference(data, "cnvkit"): target_bed, anti_bed = cnvkit.targets_from_background(dd.get_background_cnv_reference(data, "cnvkit"), cnv_group.work_dir, data) else: target_bed, anti_bed = cnvkit.targets_w_bins(cnv_group.region_file, cnv_group.access_file, size_calc_fn, cnv_group.work_dir, data) return target_bed, anti_bed, None class MemoizedSizes: """Delay calculating sizes unless needed; cache to calculate a single time. """ def __init__(self, cnv_file, items): self.result = None self.cnv_file = cnv_file self.items = items def get_target_antitarget_bin_sizes(self): if self.result: return self.result else: self.result = self._calc_sizes(self.cnv_file, self.items) return self.result def _calc_sizes(self, cnv_file, items): """Retrieve target and antitarget bin sizes based on depth. Similar to CNVkit's do_autobin but tries to have a standard set of ranges (50bp intervals for target and 10kb intervals for antitarget). """ bp_per_bin = 100000 # same target as CNVkit range_map = {"target": (100, 250), "antitarget": (10000, 1000000)} target_bps = [] anti_bps = [] checked_beds = set([]) for data in items: region_bed = tz.get_in(["depth", "variant_regions", "regions"], data) if region_bed and region_bed not in checked_beds: with utils.open_gzipsafe(region_bed) as in_handle: for r in pybedtools.BedTool(in_handle).intersect(cnv_file): if r.stop - r.start > range_map["target"][0]: target_bps.append(float(r.name)) with utils.open_gzipsafe(region_bed) as in_handle: for r in pybedtools.BedTool(in_handle).intersect(cnv_file, v=True): if r.stop - r.start > range_map["target"][1]: anti_bps.append(float(r.name)) checked_beds.add(region_bed) def scale_in_boundary(raw, round_interval, range_targets): min_val, max_val = range_targets out = int(math.ceil(raw / float(round_interval)) * round_interval) if out > max_val: return max_val elif out < min_val: return min_val else: return out if target_bps and np.median(target_bps) > 0: raw_target_bin = bp_per_bin / float(np.median(target_bps)) target_bin = scale_in_boundary(raw_target_bin, 50, range_map["target"]) else: target_bin = range_map["target"][1] if anti_bps and np.median(anti_bps) > 0: raw_anti_bin = bp_per_bin / float(np.median(anti_bps)) anti_bin = scale_in_boundary(raw_anti_bin, 10000, range_map["antitarget"]) else: anti_bin = range_map["antitarget"][1] return target_bin, anti_bin def _group_by_cnv_method(batches): """Group into batches samples with identical CNV/SV approaches. Allows sharing of background samples across multiple batches, using all normals from tumor/normal pairs with the same prep method for background. """ CnvGroup = collections.namedtuple("CnvGroup", "items, work_dir, access_file, region_file") out = [] groups = collections.defaultdict(list) for batch, items in batches.items(): for data in items: work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", "bins", batch)) cnv_file = get_base_cnv_regions(data, work_dir, "transcripts100", include_gene_names=False) if cnv_file: break assert cnv_file, ("Did not find coverage regions for batch %s: %s" % (batch, " ".join([dd.get_sample_name(d) for d in items]))) groups[(cnv_file, dd.get_prep_method(data))].append((items, data, work_dir)) for (cnv_file, _), cur_group in groups.items(): group_items = reduce(operator.add, [xs[0] for xs in cur_group]) access_file = tz.get_in(["config", "algorithm", "callable_regions"], cur_group[0][1]) out.append(CnvGroup(group_items, cur_group[0][2], access_file, cnv_file)) return out def calculate_sv_coverage(data): """Calculate coverage within bins for downstream CNV calling. Creates corrected cnr files with log2 ratios and depths. data is one sample """ calcfns = {"cnvkit": _calculate_sv_coverage_cnvkit, "gatk-cnv": _calculate_sv_coverage_gatk} from bcbio.structural import cnvkit data = utils.to_single_data(data) from bcbio.structural import get_svcallers sv_callers = get_svcallers(data) has_cnvkit_or_gatkcnv = bool(set(["cnvkit", "gatk-cnv"]) & set(sv_callers)) if not cnvkit.use_general_sv_bins(data) or not has_cnvkit_or_gatkcnv: out_target_file, out_anti_file = (None, None) else: work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", dd.get_sample_name(data), "bins")) out_target_file, out_anti_file = calcfns[cnvkit.bin_approach(data)](data, work_dir) if not os.path.exists(out_target_file): out_target_file, out_anti_file = (None, None) if "seq2c" in dd.get_svcaller(data): from bcbio.structural import seq2c seq2c_target = seq2c.precall(data) else: seq2c_target = None if "purecn" in dd.get_svcaller(data): # set purecn_pon_build flag batches = dd.get_batch(data) if batches and "pon_build" in dd.get_batch(data): data["config"]["algorithm"]["purecn_pon_build"] = True from bcbio.structural import purecn # still calculate coverage even when not building pon - for t-only analysis purecn_target = purecn.get_coverage(data) else: purecn_target = None if not tz.get_in(["depth", "bins"], data): data = tz.update_in(data, ["depth", "bins"], lambda x: {}) data["depth"]["bins"] = {"target": out_target_file, "antitarget": out_anti_file, "seq2c": seq2c_target, "purecn": purecn_target} return [[data]] def _calculate_sv_coverage_gatk(data, work_dir): """Calculate coverage in defined regions using GATK tools TODO: This does double calculations to get GATK4 compatible HDF read counts and then depth and gene annotations. Both are needed for creating heterogeneity inputs. Ideally replace with a single mosdepth coverage calculation, and creat GATK4 TSV format: CONTIG START END COUNT chrM 1 1000 13268 """ from bcbio.variation import coverage from bcbio.structural import annotate # GATK compatible target_file = gatkcnv.collect_read_counts(data, work_dir) # heterogeneity compatible target_in = bedutils.clean_file(tz.get_in(["regions", "bins", "target"], data), data, bedprep_dir=work_dir) target_cov = coverage.run_mosdepth(data, "target-gatk", target_in) target_cov_genes = annotate.add_genes(target_cov.regions, data, max_distance=0) return target_file, target_cov_genes def _calculate_sv_coverage_cnvkit(data, work_dir): """Calculate coverage in an CNVkit ready format using mosdepth. """ from bcbio.variation import coverage from bcbio.structural import annotate out_target_file = os.path.join(work_dir, "%s-target-coverage.cnn" % dd.get_sample_name(data)) out_anti_file = os.path.join(work_dir, "%s-antitarget-coverage.cnn" % dd.get_sample_name(data)) if ((not utils.file_exists(out_target_file) or not utils.file_exists(out_anti_file)) and (dd.get_align_bam(data) or dd.get_work_bam(data))): target_cov = coverage.run_mosdepth(data, "target", tz.get_in(["regions", "bins", "target"], data)) anti_cov = coverage.run_mosdepth(data, "antitarget", tz.get_in(["regions", "bins", "antitarget"], data)) target_cov_genes = annotate.add_genes(target_cov.regions, data, max_distance=0) out_target_file = _add_log2_depth(target_cov_genes, out_target_file, data) out_anti_file = _add_log2_depth(anti_cov.regions, out_anti_file, data) return out_target_file, out_anti_file def _add_log2_depth(in_file, out_file, data): """Create a CNVkit cnn file with depths http://cnvkit.readthedocs.io/en/stable/fileformats.html?highlight=cnn#target-and-antitarget-bin-level-coverages-cnn """ if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with utils.open_gzipsafe(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: out_handle.write("chromosome\tstart\tend\tgene\tlog2\tdepth\n") for line in in_handle: parts = line.rstrip().split("\t") if len(parts) > 4: # Handle inputs unannotated with gene names if len(parts) == 5: chrom, start, end, orig_name, depth = parts gene_name = orig_name if (orig_name in ["Antitarget", "Background"]) else "." else: assert len(parts) == 6, parts chrom, start, end, orig_name, depth, gene_name = parts depth = float(depth) log2_depth = math.log(float(depth), 2) if depth else -20.0 out_handle.write("%s\t%s\t%s\t%s\t%.3f\t%.2f\n" % (chrom, start, end, gene_name, log2_depth, depth)) return out_file def normalize_sv_coverage(*items): """Normalize CNV coverage, providing flexible point for multiple methods. Don't normalize when running purecn alone """ out = [] items = [utils.to_single_data(x) for x in cwlutils.handle_combined_input(items)] from bcbio.structural import get_svcallers sv_callers = get_svcallers(items[0]) if "gatk-cnv" in sv_callers or "cnvkit" in sv_callers: calcfns = {"cnvkit": _normalize_sv_coverage_cnvkit, "gatk-cnv": _normalize_sv_coverage_gatk} from bcbio.structural import cnvkit from bcbio.structural import shared as sshared if all(not cnvkit.use_general_sv_bins(x) for x in items): return [[d] for d in items] out_files = {} back_files = {} for group_id, gitems in itertools.groupby(items, lambda x: tz.get_in(["regions", "bins", "group"], x)): # No CNVkit calling for this particular set of samples if group_id is None: continue inputs, backgrounds = sshared.find_case_control(list(gitems)) assert inputs, "Did not find inputs for sample batch: %s" % (" ".join(dd.get_sample_name(x) for x in items)) work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(inputs[0]), "structural", dd.get_sample_name(inputs[0]), "bins")) back_files, out_files = calcfns[cnvkit.bin_approach(inputs[0])](group_id, inputs, backgrounds, work_dir, back_files, out_files) for data in items: if dd.get_sample_name(data) in out_files: data["depth"]["bins"]["background"] = back_files[dd.get_sample_name(data)] data["depth"]["bins"]["normalized"] = out_files[dd.get_sample_name(data)] out.append([data]) else: out = [[d] for d in items] return out def _normalize_sv_coverage_gatk(group_id, inputs, backgrounds, work_dir, back_files, out_files): """Normalize CNV coverage using panel of normals with GATK's de-noise approaches. """ input_backs = set(filter(lambda x: x is not None, [dd.get_background_cnv_reference(d, "gatk-cnv") for d in inputs])) if input_backs: assert len(input_backs) == 1, "Multiple backgrounds in group: %s" % list(input_backs) pon = list(input_backs)[0] elif backgrounds: pon = gatkcnv.create_panel_of_normals(backgrounds, group_id, work_dir) for item in itertools.chain(inputs, backgrounds): if "sv" not in item: item["sv"] = [] cur_sv = {"variantcaller": "gatkcnv", "pon": pon} item["sv"].append(cur_sv) else: pon = None for data in inputs: work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", dd.get_sample_name(data), "bins")) denoise_file = gatkcnv.denoise(data, pon, work_dir) out_files[dd.get_sample_name(data)] = denoise_file back_files[dd.get_sample_name(data)] = pon return back_files, out_files def _normalize_sv_coverage_cnvkit(group_id, inputs, backgrounds, work_dir, back_files, out_files): """Normalize CNV coverage depths by GC, repeats and background using CNVkit - reference: calculates reference backgrounds from normals and pools including GC and repeat information - fix: Uses background to normalize coverage estimations http://cnvkit.readthedocs.io/en/stable/pipeline.html#fix """ from bcbio.structural import cnvkit cnns = reduce(operator.add, [[tz.get_in(["depth", "bins", "target"], x), tz.get_in(["depth", "bins", "antitarget"], x)] for x in backgrounds], []) for d in inputs: if tz.get_in(["depth", "bins", "target"], d): target_bed = tz.get_in(["depth", "bins", "target"], d) antitarget_bed = tz.get_in(["depth", "bins", "antitarget"], d) input_backs = set(filter(lambda x: x is not None, [dd.get_background_cnv_reference(d, "cnvkit") for d in inputs])) if input_backs: assert len(input_backs) == 1, "Multiple backgrounds in group: %s" % list(input_backs) back_file = list(input_backs)[0] else: back_file = cnvkit.cnvkit_background(cnns, os.path.join(work_dir, "background-%s-cnvkit.cnn" % (group_id)), backgrounds or inputs, target_bed, antitarget_bed) fix_cmd_inputs = [] for data in inputs: work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", dd.get_sample_name(data), "bins")) if tz.get_in(["depth", "bins", "target"], data): fix_file = os.path.join(work_dir, "%s-normalized.cnr" % (dd.get_sample_name(data))) fix_cmd_inputs.append((tz.get_in(["depth", "bins", "target"], data), tz.get_in(["depth", "bins", "antitarget"], data), back_file, fix_file, data)) out_files[dd.get_sample_name(data)] = fix_file back_files[dd.get_sample_name(data)] = back_file parallel = {"type": "local", "cores": dd.get_cores(inputs[0]), "progs": ["cnvkit"]} run_multicore(cnvkit.run_fix_parallel, fix_cmd_inputs, inputs[0]["config"], parallel) return back_files, out_files # Region retrieval for SV calling def get_base_cnv_regions(data, work_dir, genome_default="transcripts1e4", include_gene_names=True): """Retrieve set of target regions for CNV analysis. Subsets to extended transcript regions for WGS experiments to avoid long runtimes. """ cov_interval = dd.get_coverage_interval(data) base_regions = get_sv_bed(data, include_gene_names=include_gene_names) # if we don't have a configured BED or regions to use for SV caling if not base_regions: # For genome calls, subset to regions near genes as targets if cov_interval == "genome": base_regions = get_sv_bed(data, genome_default, work_dir, include_gene_names=include_gene_names) if base_regions: base_regions = remove_exclude_regions(base_regions, base_regions, [data]) # Finally, default to the defined variant regions if not base_regions: base_regions = dd.get_variant_regions(data) or dd.get_sample_callable(data) return bedutils.clean_file(base_regions, data) def remove_exclude_regions(orig_bed, base_file, items, remove_entire_feature=False): """Remove centromere and short end regions from an existing BED file of regions to target. """ from bcbio.structural import shared as sshared out_bed = os.path.join("%s-noexclude.bed" % (utils.splitext_plus(base_file)[0])) if not utils.file_uptodate(out_bed, orig_bed): exclude_bed = sshared.prepare_exclude_file(items, base_file) with file_transaction(items[0], out_bed) as tx_out_bed: pybedtools.BedTool(orig_bed).subtract(pybedtools.BedTool(exclude_bed), A=remove_entire_feature, nonamecheck=True).saveas(tx_out_bed) if utils.file_exists(out_bed): return out_bed else: return orig_bed def get_sv_bed(data, method=None, out_dir=None, include_gene_names=True): """Retrieve a BED file of regions for SV and heterogeneity calling using the provided method. method choices: - exons: Raw BED file of exon regions - transcripts: Full collapsed regions with the min and max of each transcript. - transcriptsXXXX: Collapsed regions around transcripts with a window size of XXXX. - A custom BED file of regions """ if method is None: method = (tz.get_in(["config", "algorithm", "sv_regions"], data) or dd.get_variant_regions(data) or dd.get_sample_callable(data)) gene_file = dd.get_gene_bed(data) if method and os.path.isfile(method): return method elif not gene_file or not method: return None elif method == "exons": return gene_file elif method.startswith("transcripts"): window = method.split("transcripts")[-1] window = int(float(window)) if window else 0 return _collapse_transcripts(gene_file, window, data, out_dir, include_gene_names=include_gene_names) else: raise ValueError("Unexpected transcript retrieval method: %s" % method) def _collapse_transcripts(in_file, window, data, out_dir, include_gene_names=True): """Collapse transcripts into min/max coordinates and optionally add windows. """ if out_dir is None: out_dir = os.path.dirname(in_file) out_file = os.path.join(out_dir, "%s-transcripts_w%s.bed" % (os.path.splitext(os.path.basename(in_file))[0], window)) chrom_sizes = {} for contig in ref.file_contigs(dd.get_ref_file(data), data["config"]): chrom_sizes[contig.name] = contig.size if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: prep_file = "%s-sortprep%s" % os.path.splitext(tx_out_file) sort_cmd = bedutils.get_sort_cmd(os.path.dirname(tx_out_file)) cmd = "{sort_cmd} -k4,4 -k1,1 {in_file} > {prep_file}" do.run(cmd.format(**locals()), "Sort BED file by transcript name") with open(tx_out_file, "w") as out_handle: # Work around for segmentation fault issue with groupby # https://github.com/daler/pybedtools/issues/131#issuecomment-89832476 x = pybedtools.BedTool(prep_file) def gen(): for r in x: yield r for name, rs in itertools.groupby(gen(), lambda r: (r.name, r.chrom)): rs = list(rs) r = rs[0] if r.chrom in chrom_sizes: for gcoords in _group_coords(rs): min_pos = max(min(gcoords) - window, 0) max_pos = min(max(gcoords) + window, chrom_sizes[r.chrom]) if include_gene_names: out_handle.write("%s\t%s\t%s\t%s\n" % (r.chrom, min_pos, max_pos, r.name)) else: out_handle.write("%s\t%s\t%s\n" % (r.chrom, min_pos, max_pos)) return bedutils.sort_merge(out_file, data) def _group_coords(rs): """Organize coordinate regions into groups for each transcript. Avoids collapsing very large introns or repetitive genes spread across the chromosome by limiting the intron size to 100kb for creating a single transcript """ max_intron_size = 1e5 coords = [] for r in rs: coords.append(r.start) coords.append(r.end) coord_groups = [] cur_group = [] for coord in sorted(coords): if not cur_group or coord - cur_group[-1] < max_intron_size: cur_group.append(coord) else: coord_groups.append(cur_group) cur_group = [coord] if cur_group: coord_groups.append(cur_group) return coord_groups bcbio-nextgen-1.2.9/bcbio/structural/scramble.py000066400000000000000000000032351415626112400217040ustar00rootroot00000000000000"""Mobile element insertion detection using SCRAMble (Soft Clipped Read Alignment Mapper) https://github.com/GeneDx/scramble https://doi.org/10.1038/s41436-020-0749-x """ import os from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do def run(items): for index, data in enumerate(items): work_dir = os.path.join(dd.get_work_dir(data), 'structural', dd.get_sample_name(data)) output_clusters_file_path = os.path.join(work_dir, 'clusters.txt') if not utils.file_exists(output_clusters_file_path): with file_transaction(output_clusters_file_path) as temp_output_file_path: do.run(f'cluster_identifier {dd.get_work_bam(data)} > {temp_output_file_path}', 'Running SCRAMble cluster_identifier') output_mei_file_path = os.path.join(work_dir, 'out_MEIs.txt') if not utils.file_exists(output_mei_file_path): with file_transaction(output_mei_file_path) as temp_mei_file_path: output_file_prefix = temp_mei_file_path.replace('_MEIs.txt', '', 1) do.run(f'scramble.sh ' f'--out-name {output_file_prefix} ' f'--cluster-file {output_clusters_file_path} ' f'--eval-meis', 'Analyzing cluster file for likely MEIs') items[index].get('sv', []).append({'variantcaller': 'scramble', 'clusters_file': output_clusters_file_path, 'mei_file': output_mei_file_path}) return items bcbio-nextgen-1.2.9/bcbio/structural/seq2c.py000066400000000000000000000444071415626112400211370ustar00rootroot00000000000000"""Cohort based copy number calling in gene regions using Seq2C. Seq2C calls across multiple samples without explicit background samples, using gene regions as segments. This requires coverage calculation in each sample and gene, followed by global calling across all samples. """ import os import shutil import subprocess from collections import defaultdict import pybedtools as bt import toolz as tz from bcbio import utils from bcbio.variation.vcfutils import get_paired_phenotype from bcbio.pipeline import datadict as dd, config_utils from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.structural import annotate, regions from bcbio.log import logger from bcbio.variation.coverage import regions_coverage from bcbio.variation import bedutils, population, vcfutils def precall(data): """Perform initial pre-calling steps -- coverage calcuation by sample. Use mosdepth to call average region coverage in regions, and convert into seq2c format. """ data = utils.to_single_data(data) bed_file = tz.get_in(["config", "algorithm", "seq2c_bed_ready"], data) if not bed_file: raise ValueError("Error: svregions or variant_regions BED file required for Seq2C") sample_name = dd.get_sample_name(data) work_dir = _sv_workdir(data) return _calculate_coverage(data, work_dir, bed_file, sample_name) def run(items): """Normalization and log2 ratio calculation plus CNV calling for full cohort. - Combine coverage of each region for each sample - Prepare read counts for each sample - Normalize coverages in cohort by gene and sample, and calculate log2 ratios - Call amplifications and deletions """ items = [utils.to_single_data(x) for x in items] work_dir = _sv_workdir(items[0]) input_backs = list(set(filter(lambda x: x is not None, [dd.get_background_cnv_reference(d, "seq2c") for d in items]))) coverage_file = _combine_coverages(items, work_dir, input_backs) read_mapping_file = _calculate_mapping_reads(items, work_dir, input_backs) normal_names = [] if input_backs: with open(input_backs[0]) as in_handle: for line in in_handle: if len(line.split()) == 2: normal_names.append(line.split()[0]) normal_names += [dd.get_sample_name(x) for x in items if population.get_affected_status(x) == 1] seq2c_calls_file = _call_cnv(items, work_dir, read_mapping_file, coverage_file, normal_names) items = _split_cnv(items, seq2c_calls_file, read_mapping_file, coverage_file) return items def prep_seq2c_bed(data): """Selecting the bed file, cleaning, and properly annotating for Seq2C """ if dd.get_background_cnv_reference(data, "seq2c"): bed_file = _background_to_bed(dd.get_background_cnv_reference(data, "seq2c"), data) else: bed_file = regions.get_sv_bed(data) if bed_file: bed_file = bedutils.clean_file(bed_file, data, prefix="svregions-") else: bed_file = bedutils.clean_file(dd.get_variant_regions(data), data) if not bed_file: return None col_num = bt.BedTool(bed_file).field_count() if col_num < 4: annotated_file = annotate.add_genes(bed_file, data, max_distance=0) if annotated_file == bed_file: raise ValueError("BED file for Seq2C must be annotated with gene names, " "however the input BED is 3-columns and we have no transcript " "data to annotate with " + bed_file) annotated_file = annotate.gene_one_per_line(annotated_file, data) else: annotated_file = bed_file ready_file = "%s-seq2cclean.bed" % (utils.splitext_plus(annotated_file)[0]) if not utils.file_uptodate(ready_file, annotated_file): bed = bt.BedTool(annotated_file) if col_num > 4 and col_num != 8: bed = bed.cut(range(4)) bed = bed.filter(lambda x: x.name not in ["", ".", "-"]) with file_transaction(data, ready_file) as tx_out_file: bed.saveas(tx_out_file) logger.debug("Saved Seq2C clean annotated ready input BED into " + ready_file) return ready_file def _background_to_bed(back_file, data): """Convert a seq2c background file with calls into BED regions for coverage. seq2c background files are a concatenation of mapping and sample_coverages from potentially multiple samples. We use the coverage information from the first sample to translate into BED. """ out_file = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "bedprep")), "%s-regions.bed" % utils.splitext_plus(os.path.basename(back_file))[0]) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(back_file) as in_handle: with open(tx_out_file, "w") as out_handle: sample = in_handle.readline().split("\t")[0] for line in in_handle: if line.startswith(sample) and len(line.split()) >= 5: _, gene, chrom, start, end = line.split()[:5] out_handle.write("%s\n" % ("\t".join([chrom, str(int(start) - 1), end, gene]))) return out_file def _get_seq2c_options(data): """Get adjustable, through resources, or default options for seq2c. """ cov2lr_possible_opts = ["-F"] defaults = {} ropts = config_utils.get_resources("seq2c", data["config"]).get("options", []) assert len(ropts) % 2 == 0, "Expect even number of options for seq2c" % ropts defaults.update(dict(tz.partition(2, ropts))) cov2lr_out, lr2gene_out = [], [] for k, v in defaults.items(): if k in cov2lr_possible_opts: cov2lr_out += [str(k), str(v)] else: lr2gene_out += [str(k), str(v)] return cov2lr_out, lr2gene_out def _call_cnv(items, work_dir, read_mapping_file, coverage_file, control_sample_names): output_fpath = os.path.join(work_dir, "calls_combined.tsv") cov2lr = "cov2lr.pl" lr2gene = "lr2gene.pl" cov2lr_opts, lr2gene_opts = _get_seq2c_options(items[0]) if control_sample_names: cov2lr_opts += ["-c", ":".join(control_sample_names)] if "-c" not in lr2gene_opts: lr2gene_opts += ["-c"] cov2lr_opt = " ".join(cov2lr_opts) lr2gene_opt = " ".join(lr2gene_opts) if not utils.file_exists(output_fpath): with file_transaction(items[0], output_fpath) as tx_out_file: with utils.chdir(work_dir): export = utils.local_path_export() cmd = ("{export} {cov2lr} -a {cov2lr_opt} {read_mapping_file} {coverage_file} | " + "{lr2gene} {lr2gene_opt} > {tx_out_file}") do.run(cmd.format(**locals()), "Seq2C CNV calling") return output_fpath def _split_cnv(items, calls_fpath, read_mapping_file, coverage_file): out_items = [] for item in items: cur_sv = {"variantcaller": "seq2c", "coverage": tz.get_in(["depth", "bins", "seq2c"], item)} if not get_paired_phenotype(item) == "normal": sample_name = dd.get_sample_name(item) work_dir = _sv_workdir(item) out_fname = os.path.join(work_dir, sample_name + '-calls.tsv') gender_fname = os.path.join(work_dir, 'gender_predicted.txt') out_gender_name = os.path.join(work_dir, sample_name + '-gender_predicted.txt') if not utils.file_exists(out_fname): with file_transaction(item, out_fname) as tx: with open(tx, "w") as out, open(calls_fpath) as inp: out.write(next(inp)) for l in inp: if l.split("\t")[0] == sample_name: out.write(l) cur_sv.update({"calls": out_fname, "vrn_file": to_vcf(out_fname, item), "read_mapping": read_mapping_file, "calls_all": calls_fpath, "coverage_all": coverage_file}) if utils.file_exists(gender_fname): if not utils.file_exists(out_gender_name): shutil.copyfile(gender_fname, out_gender_name) cur_sv.update({"gender_predicted": out_gender_name}) if "sv" not in item: item["sv"] = [] assert "seq2c" not in [x["variantcaller"] for x in item["sv"]], \ "Do not expect existing seq2c variant output: %s" % (dd.get_sample_name(item)) item["sv"].append(cur_sv) out_items.append(item) return out_items VCF_HEADER = """##fileformat=VCFv4.1 ##INFO= ##INFO= ##INFO= ##INFO= ##INFO= ##INFO= ##ALT= ##ALT= ##FORMAT= """ def to_vcf(in_tsv, data): """Convert seq2c output file into BED output. """ call_convert = {"Amp": "DUP", "Del": "DEL"} out_file = "%s.vcf" % utils.splitext_plus(in_tsv)[0] if not utils.file_uptodate(out_file, in_tsv): with file_transaction(data, out_file) as tx_out_file: with open(in_tsv) as in_handle: with open(tx_out_file, "w") as out_handle: out_handle.write(VCF_HEADER + "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\t%s\n" % (dd.get_sample_name(data))) header = in_handle.readline().split("\t") for cur in (dict(zip(header, l.split("\t"))) for l in in_handle): if cur["Amp_Del"] in call_convert: svtype = call_convert[cur["Amp_Del"]] info = "SVTYPE=%s;END=%s;SVLEN=%s;FOLD_CHANGE_LOG=%s;PROBES=%s;GENE=%s" % ( svtype, cur["End"], int(cur["End"]) - int(cur["Start"]), cur["Log2ratio"], cur["Ab_Seg"], cur["Gene"]) out_handle.write("\t".join([cur["Chr"], cur["Start"], ".", "N", "<%s>" % (svtype), ".", ".", info, "GT", "1/1"]) + "\n") return vcfutils.sort_by_ref(out_file, data) def _calculate_coverage(data, work_dir, bed_file, sample_name): depth_file = regions_coverage(bed_file, "seq2c_bed_ready", data) out_file = os.path.join(work_dir, sample_name + '-coverage.tsv') if not utils.file_exists(out_file): logger.debug('Converting depth output to cov2lr.pl input in ' + sample_name) with file_transaction(data, out_file) as tx_out_file: _depth_to_seq2cov(depth_file, tx_out_file, sample_name) logger.debug("Saved to " + out_file) return out_file def _depth_to_seq2cov(input_fpath, output_fpath, sample_name): """Args: input_fpath: output of "mosdepth": chr22 14250 15500 name3 5.54 chrM 100 1000 name1 916.08 output_fpath: path to write results - input for Seq2C's cov2lr.pl, e.g.: seq2cov: chr20_tumor_1 DEFB125 chr20 68346 68413 Amplicon 68 28.0 chr20_tumor_1 DEFB125 chr20 76641 77301 Amplicon 661 24.0 chr20_tumor_1 DEFB125 chr20 68346 77301 Whole-Gene 729 24.3731138546 sample_name: sample name (e.g. chr20_tumor_1) """ # First round: collecting gene ends gene_end_by_gene = defaultdict(lambda: -1) with utils.open_gzipsafe(input_fpath) as f: for xs in (l.rstrip().split() for l in f if not l.startswith("#")): xs = [x for x in xs if x.strip()] if any(x == "." for x in xs): continue end = int(xs[2]) gene_name = xs[3] gene_end_by_gene[gene_name] = max(gene_end_by_gene[gene_name], end) # Second round: calculating gene level coverage, and writing file for Seq2C total_cov_by_gene = dict() gene_start_by_gene = dict() total_size_by_gene = dict() with utils.open_gzipsafe(input_fpath) as f, open(output_fpath, 'w') as out: for xs in (l.rstrip().split() for l in f if not l.startswith("#")): xs = [x for x in xs if x.strip()] if any(x == "." for x in xs): continue chrom, start, end, gene_name = xs[:4] start, end = int(start), int(end) ave_depth = float(xs[-1]) if gene_name not in gene_start_by_gene: gene_start_by_gene[gene_name] = start total_cov_by_gene[gene_name] = 0 total_size_by_gene[gene_name] = 0 else: gene_start_by_gene[gene_name] = min(start, gene_start_by_gene[gene_name]) total_cov_by_gene[gene_name] += ave_depth * (end - start) total_size_by_gene[gene_name] += end - start fs = [sample_name, gene_name, chrom, str(start + 1), str(end), 'Amplicon', str(end - start), str(ave_depth)] out.write('\t'.join(fs) + '\n') if end >= gene_end_by_gene[gene_name]: assert end == gene_end_by_gene[gene_name], (end, gene_end_by_gene[gene_name]) start = gene_start_by_gene[gene_name] ave_depth = total_cov_by_gene[gene_name] / total_size_by_gene[gene_name] size = total_size_by_gene[gene_name] fs = [sample_name, gene_name, chrom, str(start + 1), str(end), 'Whole-Gene', str(size), str(ave_depth)] out.write('\t'.join(fs) + '\n') return output_fpath def _combine_coverages(items, work_dir, input_backs=None): """Combine coverage cnns calculated for individual inputs into single file. Optionally moves over pre-calculated coverage samples from a background file. """ out_file = os.path.join(work_dir, "sample_coverages.txt") if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: with open(tx_out_file, 'w') as out_f: for data in items: cov_file = tz.get_in(["depth", "bins", "seq2c"], data) with open(cov_file) as cov_f: out_f.write(cov_f.read()) if input_backs: for input_back in input_backs: with open(input_back) as in_handle: for line in in_handle: if len(line.split()) >= 4: out_f.write(line) return out_file def _calculate_mapping_reads(items, work_dir, input_backs=None): """Calculate read counts from samtools idxstats for each sample. Optionally moves over pre-calculated mapping counts from a background file. """ out_file = os.path.join(work_dir, "mapping_reads.txt") if not utils.file_exists(out_file): lines = [] for data in items: count = 0 for line in subprocess.check_output([ "samtools", "idxstats", dd.get_align_bam(data)]).decode().split("\n"): if line.strip(): count += int(line.split("\t")[2]) lines.append("%s\t%s" % (dd.get_sample_name(data), count)) with file_transaction(items[0], out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: out_handle.write("\n".join(lines) + "\n") if input_backs: for input_back in input_backs: with open(input_back) as in_handle: for line in in_handle: if len(line.split()) == 2: out_handle.write(line) return out_file # def _count_mapped_reads(data, work_dir, bed_file, bam_file): # """Calculate read counts from samtools idxstats for each sample. # """ # sambamba = config_utils.get_program("sambamba", data["config"]) # num_cores = dd.get_cores(data) # out_file = os.path.join(work_dir, "mapped_reads_count.txt") # if not utils.file_exists(out_file): # logger.debug('Counting mapped reads in ' + dd.get_sample_name(data)) # with file_transaction(data, out_file) as tx_out_file: # cmd = ("{sambamba} view -c -t {num_cores} " # "-F \"not duplicate and not failed_quality_control\" " # "-L {bed_file} {bam_file} > {tx_out_file}") # do.run(cmd.format(**locals()), "Counting mapped reads") # return out_file # # def _combine_read_counts(items, work_dir): # out_file = os.path.join(work_dir, "mapped_reads_counts.txt") # if not utils.file_exists(out_file): # with file_transaction(items[0], out_file) as tx_out_file: # with open(tx_out_file, "w") as out_handle: # for data in items: # with open(data["sv"][0]["read_count"]) as f: # out_handle.write(dd.get_sample_name(data) + "\t" + f.read()) # return out_file def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "seq2c")) """ Seq2c columns Sample Gene Chromosome Start End Length Log2ratio Gene level log2 ratio (median) Sig Significance (p-value if >= 3 exons, MAD value if < 3 exons) BP_Whole BP or Whole: Value "Whole" means the gene is Del/Amp in whole, Value "BP" means with breakpoint. Empty means no copy number aberration Amp_Del Amp or Del: Possible values are: "Amp", "Del", "NA", or empty Ab_Seg: No. of segments/exons show aberration. Total_Seg: Total segments/exons for the gene Ab_log2ratio: The mean log2 ratio for exons with aberration. Log2r_Diff Log2ratio Diff: The absolute log2 ratio difference between exons with aberration and other exons Ab_Seg_Loc Exons and their location with aberration Ab_Samples: No. of samples with the same exon(s) aberration (to catch false positives for exon with high variances) Ab_Samples_Pcnt: Percentage of samples with the same exon(s) aberration """ bcbio-nextgen-1.2.9/bcbio/structural/shared.py000066400000000000000000000340301415626112400213570ustar00rootroot00000000000000"""Shared functionality useful across multiple structural variant callers. Handles exclusion regions and preparing discordant regions. """ import collections import os import numpy import pybedtools import pysam import toolz as tz import yaml from bcbio import bam, utils from bcbio.distributed.transaction import file_transaction from bcbio.bam import callable from bcbio.pipeline import datadict as dd from bcbio.pipeline import shared from bcbio.provenance import do from bcbio.variation import effects, population, vcfutils from functools import reduce # ## Finalizing samples def finalize_sv(orig_vcf, data, items): """Finalize structural variants, adding effects and splitting if needed. """ paired = vcfutils.get_paired(items) # For paired/somatic, attach combined calls to tumor sample if paired: sample_vcf = orig_vcf if paired.tumor_name == dd.get_sample_name(data) else None else: sample_vcf = "%s-%s.vcf.gz" % (utils.splitext_plus(orig_vcf)[0], dd.get_sample_name(data)) sample_vcf = vcfutils.select_sample(orig_vcf, dd.get_sample_name(data), sample_vcf, data["config"]) if sample_vcf: effects_vcf, _ = effects.add_to_vcf(sample_vcf, data, "snpeff") else: effects_vcf = None return effects_vcf or sample_vcf def annotate_with_depth(in_file, items): """Annotate called VCF file with depth using duphold (https://github.com/brentp/duphold) Currently annotates single sample and tumor samples in somatic analysis. """ bam_file = None if len(items) == 1: bam_file = dd.get_align_bam(items[0]) else: paired = vcfutils.get_paired(items) if paired: bam_file = paired.tumor_bam if bam_file: out_file = "%s-duphold.vcf.gz" % utils.splitext_plus(in_file)[0] if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: if not in_file.endswith(".gz"): in_file = vcfutils.bgzip_and_index(in_file, remove_orig=False, out_dir=os.path.dirname(tx_out_file)) ref_file = dd.get_ref_file(items[0]) # cores for BAM reader thread, so max out at 4 based on recommendations cores = min([dd.get_num_cores(items[0]), 4]) cmd = ("duphold --threads {cores} --vcf {in_file} --bam {bam_file} --fasta {ref_file} " "-o {tx_out_file}") do.run(cmd.format(**locals()), "Annotate SV depth with duphold") vcfutils.bgzip_and_index(out_file) return out_file else: return in_file # ## Case/control def find_case_control(items): """Find case/control items in a population of multiple samples. """ cases = [] controls = [] for data in items: if population.get_affected_status(data) == 1: controls.append(data) else: cases.append(data) return cases, controls # ## Prepare exclusion regions (repeats, telomeres, centromeres) def _get_sv_exclude_file(items): """Retrieve SV file of regions to exclude. """ sv_bed = utils.get_in(items[0], ("genome_resources", "variation", "sv_repeat")) if sv_bed and os.path.exists(sv_bed): return sv_bed def _get_variant_regions(items): """Retrieve variant regions defined in any of the input items. """ return list(filter(lambda x: x is not None, [tz.get_in(("config", "algorithm", "variant_regions"), data) for data in items if tz.get_in(["config", "algorithm", "coverage_interval"], data) != "genome"])) def has_variant_regions(items, base_file, chrom=None): """Determine if we should process this chromosome: needs variant regions defined. """ if chrom: all_vrs = _get_variant_regions(items) if len(all_vrs) > 0: test = shared.subset_variant_regions(tz.first(all_vrs), chrom, base_file, items) if test == chrom: return False return True def prepare_exclude_file(items, base_file, chrom=None): """Prepare a BED file for exclusion. Excludes high depth and centromere regions which contribute to long run times and false positive structural variant calls. """ items = shared.add_highdepth_genome_exclusion(items) out_file = "%s-exclude%s.bed" % (utils.splitext_plus(base_file)[0], "-%s" % chrom if chrom else "") if not utils.file_exists(out_file) and not utils.file_exists(out_file + ".gz"): with shared.bedtools_tmpdir(items[0]): with file_transaction(items[0], out_file) as tx_out_file: # Get a bedtool for the full region if no variant regions want_bedtool = callable.get_ref_bedtool(tz.get_in(["reference", "fasta", "base"], items[0]), items[0]["config"], chrom) want_bedtool = pybedtools.BedTool(shared.subset_variant_regions(want_bedtool.saveas().fn, chrom, tx_out_file, items)) sv_exclude_bed = _get_sv_exclude_file(items) if sv_exclude_bed and len(want_bedtool) > 0: want_bedtool = want_bedtool.subtract(sv_exclude_bed, nonamecheck=True).saveas() full_bedtool = callable.get_ref_bedtool(tz.get_in(["reference", "fasta", "base"], items[0]), items[0]["config"]) if len(want_bedtool) > 0: full_bedtool.subtract(want_bedtool, nonamecheck=True).saveas(tx_out_file) else: full_bedtool.saveas(tx_out_file) return out_file def exclude_by_ends(in_file, exclude_file, data, in_params=None): """Exclude calls based on overlap of the ends with exclusion regions. Removes structural variants with either end being in a repeat: a large source of false positives. Parameters tuned based on removal of LCR overlapping false positives in DREAM synthetic 3 data. """ params = {"end_buffer": 50, "rpt_pct": 0.9, "total_rpt_pct": 0.2, "sv_pct": 0.5} if in_params: params.update(in_params) assert in_file.endswith(".bed") out_file = "%s-norepeats%s" % utils.splitext_plus(in_file) to_filter = collections.defaultdict(list) removed = 0 if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: with shared.bedtools_tmpdir(data): for coord, end_name in [(1, "end1"), (2, "end2")]: base, ext = utils.splitext_plus(tx_out_file) end_file = _create_end_file(in_file, coord, params, "%s-%s%s" % (base, end_name, ext)) to_filter = _find_to_filter(end_file, exclude_file, params, to_filter) with open(tx_out_file, "w") as out_handle: with open(in_file) as in_handle: for line in in_handle: key = "%s:%s-%s" % tuple(line.strip().split("\t")[:3]) total_rpt_size = sum(to_filter.get(key, [0])) if total_rpt_size <= (params["total_rpt_pct"] * params["end_buffer"]): out_handle.write(line) else: removed += 1 return out_file, removed def _find_to_filter(in_file, exclude_file, params, to_exclude): """Identify regions in the end file that overlap the exclusion file. We look for ends with a large percentage in a repeat or where the end contains an entire repeat. """ for feat in pybedtools.BedTool(in_file).intersect(pybedtools.BedTool(exclude_file), wao=True, nonamecheck=True): us_chrom, us_start, us_end, name, other_chrom, other_start, other_end, overlap = feat.fields if float(overlap) > 0: other_size = float(other_end) - float(other_start) other_pct = float(overlap) / other_size us_pct = float(overlap) / (float(us_end) - float(us_start)) if us_pct > params["sv_pct"] or (other_pct > params["rpt_pct"]): to_exclude[name].append(float(overlap)) return to_exclude def _create_end_file(in_file, coord, params, out_file): with open(in_file) as in_handle: with open(out_file, "w") as out_handle: for line in in_handle: parts = line.strip().split("\t") name = "%s:%s-%s" % tuple(parts[:3]) curpos = int(parts[coord]) if coord == 1: start, end = curpos, curpos + params["end_buffer"] else: start, end = curpos - params["end_buffer"], curpos if start > 0: out_handle.write("\t".join([parts[0], str(start), str(end), name]) + "\n") return out_file def get_sv_chroms(items, exclude_file): """Retrieve chromosomes to process on, avoiding extra skipped chromosomes. """ exclude_regions = {} for region in pybedtools.BedTool(exclude_file): if int(region.start) == 0: exclude_regions[region.chrom] = int(region.end) out = [] with pysam.Samfile(dd.get_align_bam(items[0]) or dd.get_work_bam(items[0]))as pysam_work_bam: for chrom, length in zip(pysam_work_bam.references, pysam_work_bam.lengths): exclude_length = exclude_regions.get(chrom, 0) if exclude_length < length: out.append(chrom) return out # ## Read preparation def _extract_split_and_discordants(in_bam, work_dir, data): """Retrieve split-read alignments from input BAM file. """ sr_file = os.path.join(work_dir, "%s-sr.bam" % os.path.splitext(os.path.basename(in_bam))[0]) disc_file = os.path.join(work_dir, "%s-disc.bam" % os.path.splitext(os.path.basename(in_bam))[0]) if not utils.file_exists(sr_file) or not utils.file_exists(disc_file): with file_transaction(data, sr_file) as tx_sr_file: with file_transaction(data, disc_file) as tx_disc_file: cores = dd.get_num_cores(data) ref_file = dd.get_ref_file(data) cmd = ("extract-sv-reads -e --threads {cores} -T {ref_file} " "-i {in_bam} -s {tx_sr_file} -d {tx_disc_file}") do.run(cmd.format(**locals()), "extract split and discordant reads", data) for fname in [sr_file, disc_file]: bam.index(fname, data["config"]) return sr_file, disc_file def find_existing_split_discordants(data): """Check for pre-calculated split reads and discordants done as part of alignment streaming. """ in_bam = dd.get_align_bam(data) sr_file = "%s-sr.bam" % os.path.splitext(in_bam)[0] disc_file = "%s-disc.bam" % os.path.splitext(in_bam)[0] if utils.file_exists(sr_file) and utils.file_exists(disc_file): return sr_file, disc_file else: sr_file = dd.get_sr_bam(data) disc_file = dd.get_disc_bam(data) if sr_file and utils.file_exists(sr_file) and disc_file and utils.file_exists(disc_file): return sr_file, disc_file else: return None, None def get_split_discordants(data, work_dir): """Retrieve split and discordant reads, potentially calculating with extract_sv_reads as needed. """ align_bam = dd.get_align_bam(data) sr_bam, disc_bam = find_existing_split_discordants(data) if not sr_bam: work_dir = (work_dir if not os.access(os.path.dirname(align_bam), os.W_OK | os.X_OK) else os.path.dirname(align_bam)) sr_bam, disc_bam = _extract_split_and_discordants(align_bam, work_dir, data) return sr_bam, disc_bam def get_cur_batch(items): """Retrieve name of the batch shared between all items in a group. """ batches = [] for data in items: batch = tz.get_in(["metadata", "batch"], data, []) batches.append(set(batch) if isinstance(batch, (list, tuple)) else set([batch])) combo_batches = reduce(lambda b1, b2: b1.intersection(b2), batches) if len(combo_batches) == 1: return combo_batches.pop() elif len(combo_batches) == 0: return None else: raise ValueError("Found multiple overlapping batches: %s -- %s" % (combo_batches, batches)) def outname_from_inputs(in_files): base = os.path.commonprefix(in_files) if base.endswith("chr"): base = base[:-3] while base.endswith(("-", "_", ".")): base = base[:-1] return base # -- Insert size calculation def insert_size_stats(dists): """Calcualtes mean/median and MAD from distances, avoiding outliers. MAD is the Median Absolute Deviation: http://en.wikipedia.org/wiki/Median_absolute_deviation """ med = numpy.median(dists) filter_dists = list(filter(lambda x: x < med + 10 * med, dists)) median = numpy.median(filter_dists) return {"mean": float(numpy.mean(filter_dists)), "std": float(numpy.std(filter_dists)), "median": float(median), "mad": float(numpy.median([abs(x - median) for x in filter_dists]))} def calc_paired_insert_stats(in_bam, nsample=1000000): """Retrieve statistics for paired end read insert distances. """ dists = [] n = 0 with pysam.Samfile(in_bam, "rb") as in_pysam: for read in in_pysam: if read.is_proper_pair and read.is_read1: n += 1 dists.append(abs(read.isize)) if n >= nsample: break return insert_size_stats(dists) def calc_paired_insert_stats_save(in_bam, stat_file, nsample=1000000): """Calculate paired stats, saving to a file for re-runs. """ if utils.file_exists(stat_file): with open(stat_file) as in_handle: return yaml.safe_load(in_handle) else: stats = calc_paired_insert_stats(in_bam, nsample) with open(stat_file, "w") as out_handle: yaml.safe_dump(stats, out_handle, default_flow_style=False, allow_unicode=False) return stats bcbio-nextgen-1.2.9/bcbio/structural/titancna.py000066400000000000000000000311251415626112400217140ustar00rootroot00000000000000"""TitanCNA: Subclonal CNV calling and loss of heterogeneity in cancer. https://github.com/gavinha/TitanCNA """ import csv import glob import os import shutil import pandas as pd from bcbio import utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.heterogeneity import chromhacks, loh from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import effects, vcfutils from bcbio.structural import cnvkit def run(items): from bcbio import heterogeneity paired = vcfutils.get_paired(items) if not paired: logger.info("Skipping TitanCNA; no somatic tumor calls in batch: %s" % " ".join([dd.get_sample_name(d) for d in items])) return items work_dir = _sv_workdir(paired.tumor_data) cn_file = _titan_cn_file(dd.get_normalized_depth(paired.tumor_data), work_dir, paired.tumor_data) het_file = _titan_het_file(heterogeneity.get_variants(paired.tumor_data), work_dir, paired) if _should_run(het_file): ploidy_outdirs = [] for ploidy in [2, 3, 4]: for num_clusters in [1, 2, 3]: out_dir = _run_titancna(cn_file, het_file, ploidy, num_clusters, work_dir, paired.tumor_data) ploidy_outdirs.append((ploidy, out_dir)) solution_file = _run_select_solution(ploidy_outdirs, work_dir, paired.tumor_data) else: logger.info("Skipping TitanCNA; not enough input data: %s" % " ".join([dd.get_sample_name(d) for d in items])) return items out = [] if paired.normal_data: out.append(paired.normal_data) if "sv" not in paired.tumor_data: paired.tumor_data["sv"] = [] paired.tumor_data["sv"].append(_finalize_sv(solution_file, paired.tumor_data)) out.append(paired.tumor_data) return out def _finalize_sv(solution_file, data): """Add output files from TitanCNA calling optional solution. """ out = {"variantcaller": "titancna"} with open(solution_file) as in_handle: solution = dict(zip(in_handle.readline().strip("\r\n").split("\t"), in_handle.readline().strip("\r\n").split("\t"))) if solution.get("path"): out["purity"] = solution["purity"] out["ploidy"] = solution["ploidy"] out["cellular_prevalence"] = [x.strip() for x in solution["cellPrev"].split(",")] base = os.path.basename(solution["path"]) out["plot"] = dict([(n, solution["path"] + ext) for (n, ext) in [("rplots", ".Rplots.pdf"), ("cf", "/%s_CF.pdf" % base), ("cna", "/%s_CNA.pdf" % base), ("loh", "/%s_LOH.pdf" % base)] if os.path.exists(solution["path"] + ext)]) out["subclones"] = "%s.segs.txt" % solution["path"] out["hetsummary"] = solution_file out["vrn_file"] = to_vcf(out["subclones"], "TitanCNA", _get_header, _seg_to_vcf, data) out["lohsummary"] = loh.summary_status(out, data) return out def _should_run(het_file): """Check for enough input data to proceed with analysis. """ has_hets = False with open(het_file) as in_handle: for i, line in enumerate(in_handle): if i > 1: has_hets = True break return has_hets def _run_select_solution(ploidy_outdirs, work_dir, data): """Select optimal """ out_file = os.path.join(work_dir, "optimalClusters.txt") if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: ploidy_inputs = " ".join(["--ploidyRun%s=%s" % (p, d) for p, d in ploidy_outdirs]) cmd = "titanCNA_selectSolution.R {ploidy_inputs} --outFile={tx_out_file}" do.run(cmd.format(**locals()), "TitanCNA: select optimal solution") return out_file def _run_titancna(cn_file, het_file, ploidy, num_clusters, work_dir, data): """Run titanCNA wrapper script on given ploidy and clusters. """ sample = dd.get_sample_name(data) cores = dd.get_num_cores(data) export_cmd = utils.get_R_exports() ploidy_dir = utils.safe_makedir(os.path.join(work_dir, "run_ploidy%s" % ploidy)) cluster_dir = "%s_cluster%02d" % (sample, num_clusters) out_dir = os.path.join(ploidy_dir, cluster_dir) if not utils.file_uptodate(out_dir + ".titan.txt", cn_file): with tx_tmpdir(data) as tmp_dir: with utils.chdir(tmp_dir): cmd = ("{export_cmd} && titanCNA.R --id {sample} --hetFile {het_file} --cnFile {cn_file} " "--numClusters {num_clusters} --ploidy {ploidy} --numCores {cores} --outDir {tmp_dir} " "--libdir None") chroms = ["'%s'" % c.name.replace("chr", "") for c in ref.file_contigs(dd.get_ref_file(data)) if chromhacks.is_autosomal_or_x(c.name)] if "'X'" not in chroms: chroms += ["'X'"] # Use UCSC style naming for human builds to support BSgenome genome_build = ("hg19" if dd.get_genome_build(data) in ["GRCh37", "hg19"] else dd.get_genome_build(data)) cmd += """ --chrs "c(%s)" """ % ",".join(chroms) cmd += " --genomeBuild {genome_build}" if data["genome_build"] in ("hg19", "hg38"): cmd += " --genomeStyle UCSC" if data["genome_build"] in ["hg38"]: data_dir = os.path.normpath(os.path.join( os.path.dirname(os.path.realpath(os.path.join( os.path.dirname(utils.Rscript_cmd()), "titanCNA.R"))), os.pardir, os.pardir, "data")) cytoband_file = os.path.join(data_dir, "cytoBand_hg38.txt") assert os.path.exists(cytoband_file), cytoband_file cmd += " --cytobandFile %s" % cytoband_file # TitanCNA's model is influenced by the variance in read coverage data # and data type: set reasonable defaults for non-WGS runs # (see https://github.com/gavinha/TitanCNA/tree/master/scripts/R_scripts) if dd.get_coverage_interval(data) != "genome": cmd += " --alphaK=2500 --alphaKHigh=2500" do.run(cmd.format(**locals()), "TitanCNA CNV detection: ploidy %s, cluster %s" % (ploidy, num_clusters)) for fname in glob.glob(os.path.join(tmp_dir, cluster_dir + "*")): shutil.move(fname, ploidy_dir) if os.path.exists(os.path.join(tmp_dir, "Rplots.pdf")): shutil.move(os.path.join(tmp_dir, "Rplots.pdf"), os.path.join(ploidy_dir, "%s.Rplots.pdf" % cluster_dir)) return ploidy_dir def _sv_workdir(data): return utils.safe_makedir(os.path.join(dd.get_work_dir(data), "structural", dd.get_sample_name(data), "titancna")) def _titan_het_file(vrn_files, work_dir, paired): assert vrn_files, "Did not find compatible variant calling files for TitanCNA inputs" from bcbio.heterogeneity import bubbletree class OutWriter: def __init__(self, out_handle): self.writer = csv.writer(out_handle, dialect="excel-tab") def write_header(self): self.writer.writerow(["Chr", "Position", "Ref", "RefCount", "Nref", "NrefCount", "NormQuality"]) def write_row(self, rec, stats): if rec.qual and float(rec.qual) > 0: self.writer.writerow([rec.chrom, rec.pos, rec.ref, stats["tumor"]["depth"] - stats["tumor"]["alt"], rec.alts[0], stats["tumor"]["alt"], rec.qual]) return bubbletree.prep_vrn_file(vrn_files[0]["vrn_file"], vrn_files[0]["variantcaller"], work_dir, paired, OutWriter) def _titan_cn_file(cnr_file, work_dir, data): """Convert CNVkit or GATK4 normalized input into TitanCNA ready format. """ out_file = os.path.join(work_dir, "%s.cn" % (utils.splitext_plus(os.path.basename(cnr_file))[0])) support_cols = {"cnvkit": ["chromosome", "start", "end", "log2"], "gatk-cnv": ["CONTIG", "START", "END", "LOG2_COPY_RATIO"]} cols = support_cols[cnvkit.bin_approach(data)] if not utils.file_uptodate(out_file, cnr_file): with file_transaction(data, out_file) as tx_out_file: iterator = pd.read_csv(cnr_file, sep="\t", iterator=True, header=0, comment="@") with open(tx_out_file, "w") as handle: for chunk in iterator: chunk = chunk[cols] chunk.columns = ["chrom", "start", "end", "logR"] if cnvkit.bin_approach(data) == "cnvkit": chunk['start'] += 1 chunk.to_csv(handle, mode="a", sep="\t", index=False) return out_file # ## VCF converstion _vcf_header = """##fileformat=VCFv4.2 ##source={caller} ##INFO= ##INFO= ##INFO= ##INFO= ##INFO= ##INFO= ##INFO= ##INFO= ##ALT= ##ALT= ##ALT= ##ALT= ##FORMAT= """ def _get_header(in_handle): return in_handle.readline().strip().split("\t"), in_handle def _seg_to_vcf(cur): svtype = _get_svtype(cur["TITAN_call"]) info = ["SVTYPE=%s" % svtype, "END=%s" % cur["End_Position.bp."], "SVLEN=%s" % (int(cur["End_Position.bp."]) - int(cur["Start_Position.bp."])), "CN=%s" % cur["Copy_Number"], "MajorCN=%s" % cur["MajorCN"], "MinorCN=%s" % cur["MinorCN"], "FOLD_CHANGE_LOG=%s" % cur["Median_logR"]] return [cur["Chromosome"], cur["Start_Position.bp."], ".", "N", "<%s>" % svtype, ".", ".", ";".join(info), "GT", "0/1"] def to_vcf(in_file, caller, header_fn, vcf_fn, data, sep="\t"): """Convert output TitanCNA segs file into bgzipped VCF.""" out_file = "%s.vcf" % utils.splitext_plus(in_file)[0] out_file_gz = out_file + ".gz" if not utils.file_exists(out_file + ".gz") and not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: out_handle.write(_vcf_header.format(caller=caller)) out_handle.write("\t".join(["#CHROM", "POS", "ID", "REF", "ALT", "QUAL", "FILTER", "INFO", "FORMAT", dd.get_sample_name(data)]) + "\n") header, in_handle = header_fn(in_handle) for line in in_handle: out = vcf_fn(dict(zip(header, line.strip().split(sep)))) if out: out_handle.write("\t".join(out) + "\n") # also does bgzip and index out_file_prep_vcf_gz = vcfutils.sort_by_ref(out_file, data) shutil.move(out_file_prep_vcf_gz, out_file_gz) shutil.move(out_file_prep_vcf_gz + ".tbi", out_file_gz + ".tbi") effects_vcf, _ = effects.add_to_vcf(out_file_gz, data, "snpeff") return effects_vcf or out_file_gz def _get_svtype(call): """Retrieve structural variant type from current TitanCNA events. homozygous deletion (HOMD), hemizygous deletion LOH (DLOH), copy neutral LOH (NLOH), diploid heterozygous (HET), amplified LOH (ALOH), gain/duplication of 1 allele (GAIN), allele-specific copy number amplification (ASCNA), balanced copy number amplification (BCNA), unbalanced copy number amplification (UBCNA) """ if call in set(["HOMD", "DLOH"]): return "DEL" elif call in set(["ALOH", "GAIN", "ASCNA", "BCNA", "UBCNA"]): return "DUP" elif call in set(["NLOH"]): return "LOH" else: return "CNV" bcbio-nextgen-1.2.9/bcbio/structural/validate.py000066400000000000000000000451531415626112400217120ustar00rootroot00000000000000"""Provide validation of structural variations against truth sets. """ import csv import os import six import toolz as tz import numpy as np import pandas as pd import pybedtools from bcbio.log import logger from bcbio import utils from bcbio.bam import ref from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.structural import convert from bcbio.distributed.transaction import file_transaction from bcbio.variation import vcfutils, ploidy, validateplot from bcbio.pipeline import config_utils mpl = utils.LazyImport("matplotlib") plt = utils.LazyImport("matplotlib.pyplot") sns = utils.LazyImport("seaborn") # -- VCF based validation def _evaluate_vcf(calls, truth_vcf, work_dir, data): out_file = os.path.join(work_dir, os.path.join("%s-sv-validate.csv" % dd.get_sample_name(data))) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: writer = csv.writer(out_handle) writer.writerow(["sample", "caller", "vtype", "metric", "value"]) for call in calls: detail_dir = utils.safe_makedir(os.path.join(work_dir, call["variantcaller"])) if call.get("vrn_file"): for stats in _validate_caller_vcf(call["vrn_file"], truth_vcf, dd.get_sample_callable(data), call["variantcaller"], detail_dir, data): writer.writerow(stats) return out_file def _validate_caller_vcf(call_vcf, truth_vcf, callable_bed, svcaller, work_dir, data): """Validate a caller VCF against truth within callable regions using SURVIVOR. Combines files with SURIVOR merge and counts (https://github.com/fritzsedlazeck/SURVIVOR/) """ stats = _calculate_comparison_stats(truth_vcf) call_vcf = _prep_vcf(call_vcf, callable_bed, dd.get_sample_name(data), dd.get_sample_name(data), stats, work_dir, data) truth_vcf = _prep_vcf(truth_vcf, callable_bed, vcfutils.get_samples(truth_vcf)[0], "%s-truth" % dd.get_sample_name(data), stats, work_dir, data) cmp_vcf = _survivor_merge(call_vcf, truth_vcf, stats, work_dir, data) return _comparison_stats_from_merge(cmp_vcf, stats, svcaller, data) def _comparison_stats_from_merge(in_file, stats, svcaller, data): """Extract true/false positive/negatives from a merged SURIVOR VCF. """ truth_stats = {"tp": [], "fn": [], "fp": []} samples = ["truth" if x.endswith("-truth") else "eval" for x in vcfutils.get_samples(in_file)] with open(in_file) as in_handle: for call in (l.rstrip().split("\t") for l in in_handle if not l.startswith("#")): supp_vec_str = [x for x in call[7].split(";") if x.startswith("SUPP_VEC=")][0] _, supp_vec = supp_vec_str.split("=") calls = dict(zip(samples, [int(x) for x in supp_vec])) if calls["truth"] and calls["eval"]: metric = "tp" elif calls["truth"]: metric = "fn" else: metric = "fp" truth_stats[metric].append(_summarize_call(call)) return _to_csv(truth_stats, stats, dd.get_sample_name(data), svcaller) def _survivor_merge(call_vcf, truth_vcf, stats, work_dir, data): """Perform a merge of two callsets using SURVIVOR, """ out_file = os.path.join(work_dir, "eval-merge.vcf") if not utils.file_uptodate(out_file, call_vcf): in_call_vcf = call_vcf.replace(".vcf.gz", ".vcf") if not utils.file_exists(in_call_vcf): with file_transaction(data, in_call_vcf) as tx_in_call_vcf: do.run("gunzip -c {call_vcf} > {tx_in_call_vcf}".format(**locals())) in_truth_vcf = truth_vcf.replace(".vcf.gz", ".vcf") if not utils.file_exists(in_truth_vcf): with file_transaction(data, in_truth_vcf) as tx_in_truth_vcf: do.run("gunzip -c {truth_vcf} > {tx_in_truth_vcf}".format(**locals())) in_list_file = os.path.join(work_dir, "eval-inputs.txt") with open(in_list_file, "w") as out_handle: out_handle.write("%s\n%s\n" % (in_call_vcf, in_truth_vcf)) with file_transaction(data, out_file) as tx_out_file: cmd = ("SURVIVOR merge {in_list_file} {stats[merge_size]} 1 0 0 0 {stats[min_size]} {tx_out_file}") do.run(cmd.format(**locals()), "Merge SV files for validation: %s" % dd.get_sample_name(data)) return out_file def _to_csv(truth_stats, stats, sample, svcaller): out = [] for metric, vals in truth_stats.items(): for svtype in sorted(list(stats["svtypes"])): count = len([x for x in vals if x["svtype"] == svtype]) out.append([sample, svcaller, svtype, metric, count]) for start, end in stats["ranges"]: count = len([x for x in vals if (x["svtype"] == svtype and x["size"] >= start and x["size"] < end)]) out.append([sample, svcaller, "%s_%s-%s" % (svtype, start, end), metric, count]) return out def _calculate_comparison_stats(truth_vcf): """Identify calls to validate from the input truth VCF. """ # Avoid very small events for average calculations min_stat_size = 50 min_median_size = 250 sizes = [] svtypes = set([]) with utils.open_gzipsafe(truth_vcf) as in_handle: for call in (l.rstrip().split("\t") for l in in_handle if not l.startswith("#")): stats = _summarize_call(call) if stats["size"] > min_stat_size: sizes.append(stats["size"]) svtypes.add(stats["svtype"]) pct10 = int(np.percentile(sizes, 10)) pct25 = int(np.percentile(sizes, 25)) pct50 = int(np.percentile(sizes, 50)) pct75 = int(np.percentile(sizes, 75)) ranges_detailed = [(int(min(sizes)), pct10), (pct10, pct25), (pct25, pct50), (pct50, pct75), (pct75, max(sizes))] ranges_split = [(int(min(sizes)), pct50), (pct50, max(sizes))] return {"min_size": int(min(sizes) * 0.95), "max_size": int(max(sizes) + 1.05), "svtypes": svtypes, "merge_size": int(np.percentile([x for x in sizes if x > min_median_size], 50)), "ranges": []} def _get_start_end(parts, index=7): """Retrieve start and end for a VCF record, skips BNDs without END coords """ start = parts[1] end = [x.split("=")[-1] for x in parts[index].split(";") if x.startswith("END=")] if end: end = end[0] return start, end return None, None def _summarize_call(parts): """Provide summary metrics on size and svtype for a SV call. """ svtype = [x.split("=")[1] for x in parts[7].split(";") if x.startswith("SVTYPE=")] svtype = svtype[0] if svtype else "" start, end = _get_start_end(parts) return {"svtype": svtype, "size": int(end) - int(start)} def _prep_vcf(in_file, region_bed, sample, new_sample, stats, work_dir, data): """Prepare VCF for SV validation: - Subset to passing variants - Subset to genotyped variants -- removes reference and no calls - Selects and names samples - Subset to callable regions - Remove larger annotations which slow down VCF processing """ in_file = vcfutils.bgzip_and_index(in_file, data, remove_orig=False) out_file = os.path.join(work_dir, "%s-vprep.vcf.gz" % utils.splitext_plus(os.path.basename(in_file))[0]) if not utils.file_uptodate(out_file, in_file): callable_bed = _prep_callable_bed(region_bed, work_dir, stats, data) with file_transaction(data, out_file) as tx_out_file: ann_remove = _get_anns_to_remove(in_file) ann_str = " | bcftools annotate -x {ann_remove}" if ann_remove else "" cmd = ("bcftools view -T {callable_bed} -f 'PASS,.' --min-ac '1:nref' -s {sample} {in_file} " + ann_str + r"| sed 's|\t{sample}|\t{new_sample}|' " "| bgzip -c > {out_file}") do.run(cmd.format(**locals()), "Create SV validation VCF for %s" % new_sample) return vcfutils.bgzip_and_index(out_file, data["config"]) def _prep_callable_bed(in_file, work_dir, stats, data): """Sort and merge callable BED regions to prevent SV double counting """ out_file = os.path.join(work_dir, "%s-merge.bed.gz" % utils.splitext_plus(os.path.basename(in_file))[0]) gsort = config_utils.get_program("gsort", data) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: fai_file = ref.fasta_idx(dd.get_ref_file(data)) cmd = ("{gsort} {in_file} {fai_file} | bedtools merge -i - -d {stats[merge_size]} | " "bgzip -c > {tx_out_file}") do.run(cmd.format(**locals()), "Prepare SV callable BED regions") return vcfutils.bgzip_and_index(out_file, data["config"]) def _get_anns_to_remove(in_file): """Find larger annotations, if present in VCF, that slow down processing. """ to_remove = ["ANN", "LOF"] to_remove_str = tuple(["##INFO= 0: val = float(x) / float(n) * 100.0 return {"label": "%.1f%% (%s / %s)" % (val, x, n), "val": val} else: return {"label": "", "val": 0} def cnv_to_event(name, data): """Convert a CNV to an event name. """ cur_ploidy = ploidy.get_ploidy([data]) if name.startswith("cnv"): num = max([int(x) for x in name.split("_")[0].replace("cnv", "").split(";")]) if num < cur_ploidy: return "DEL" elif num > cur_ploidy: return "DUP" else: return name else: return name def _evaluate_one(caller, svtype, size_range, ensemble, truth, data): """Compare a ensemble results for a caller against a specific caller and SV type. """ def cnv_matches(name): return cnv_to_event(name, data) == svtype def is_breakend(name): return name.startswith("BND") def in_size_range(max_buffer=0): def _work(feat): minf, maxf = size_range buffer = min(max_buffer, int(((maxf + minf) / 2.0) / 10.0)) size = feat.end - feat.start return size >= max([0, minf - buffer]) and size < maxf + buffer return _work def is_caller_svtype(feat): for name in feat.name.split(","): if ((name.startswith(svtype) or cnv_matches(name) or is_breakend(name)) and (caller == "sv-ensemble" or name.endswith(caller))): return True return False minf, maxf = size_range efeats = pybedtools.BedTool(ensemble).filter(in_size_range(0)).filter(is_caller_svtype).saveas().sort().merge() tfeats = pybedtools.BedTool(truth).filter(in_size_range(0)).sort().merge().saveas() etotal = efeats.count() ttotal = tfeats.count() match = efeats.intersect(tfeats, u=True).sort().merge().saveas().count() return {"sensitivity": _stat_str(match, ttotal), "precision": _stat_str(match, etotal)} def _evaluate_multi(calls, truth_svtypes, work_dir, data): base = os.path.join(work_dir, "%s-sv-validate" % (dd.get_sample_name(data))) out_file = base + ".csv" df_file = base + "-df.csv" if any((not utils.file_uptodate(out_file, x["vrn_file"]) or not utils.file_uptodate(df_file, x["vrn_file"])) for x in calls): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: with open(df_file, "w") as df_out_handle: writer = csv.writer(out_handle) dfwriter = csv.writer(df_out_handle) writer.writerow(["svtype", "size", "caller", "sensitivity", "precision"]) dfwriter.writerow(["svtype", "size", "caller", "metric", "value", "label"]) for svtype, truth in truth_svtypes.items(): for size in EVENT_SIZES: str_size = "%s-%s" % size for call in calls: call_bed = convert.to_bed(call, dd.get_sample_name(data), work_dir, calls, data) if utils.file_exists(call_bed): evalout = _evaluate_one(call["variantcaller"], svtype, size, call_bed, truth, data) writer.writerow([svtype, str_size, call["variantcaller"], evalout["sensitivity"]["label"], evalout["precision"]["label"]]) for metric in ["sensitivity", "precision"]: dfwriter.writerow([svtype, str_size, call["variantcaller"], metric, evalout[metric]["val"], evalout[metric]["label"]]) return out_file, df_file def _plot_evaluation(df_csv): if mpl is None or plt is None or sns is None: not_found = ", ".join([x for x in ['mpl', 'plt', 'sns'] if eval(x) is None]) logger.info("No validation plot. Missing imports: %s" % not_found) return None mpl.use('Agg', force=True) df = pd.read_csv(df_csv).fillna("0%") out = {} for event in df["svtype"].unique(): out[event] = _plot_evaluation_event(df_csv, event) return out def _plot_evaluation_event(df_csv, svtype): """Provide plot of evaluation metrics for an SV event, stratified by event size. """ titles = {"INV": "Inversions", "DEL": "Deletions", "DUP": "Duplications", "INS": "Insertions"} out_file = "%s-%s.png" % (os.path.splitext(df_csv)[0], svtype) sns.set(style='white') if not utils.file_uptodate(out_file, df_csv): metrics = ["sensitivity", "precision"] df = pd.read_csv(df_csv).fillna("0%") df = df[(df["svtype"] == svtype)] event_sizes = _find_events_to_include(df, EVENT_SIZES) fig, axs = plt.subplots(len(event_sizes), len(metrics), tight_layout=True) if len(event_sizes) == 1: axs = [axs] callers = sorted(df["caller"].unique()) if "sv-ensemble" in callers: callers.remove("sv-ensemble") callers.append("sv-ensemble") for i, size in enumerate(event_sizes): size_label = "%s to %sbp" % size size = "%s-%s" % size for j, metric in enumerate(metrics): ax = axs[i][j] ax.get_xaxis().set_ticks([]) ax.spines['bottom'].set_visible(False) ax.spines['left'].set_visible(False) ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.set_xlim(0, 125.0) if i == 0: ax.set_title(metric, size=12, y=1.2) vals, labels = _get_plot_val_labels(df, size, metric, callers) ax.barh(range(1,len(vals)+1), vals) if j == 0: ax.tick_params(axis='y', which='major', labelsize=8) ax.locator_params(axis="y", tight=True) ax.set_yticks(range(1,len(callers)+1,1)) ax.set_yticklabels(callers, va="center") ax.text(100, len(callers)+1, size_label, fontsize=10) else: ax.get_yaxis().set_ticks([]) for ai, (val, label) in enumerate(zip(vals, labels)): ax.annotate(label, (val + 0.75, ai + 1), va='center', size=7) if svtype in titles: fig.text(0.025, 0.95, titles[svtype], size=14) fig.set_size_inches(7, len(event_sizes) + 1) fig.savefig(out_file) return out_file def _find_events_to_include(df, event_sizes): out = [] for size in event_sizes: str_size = "%s-%s" % size curdf = df[(df["size"] == str_size) & (df["metric"] == "sensitivity")] for val in list(curdf["label"]): if val != "0%": out.append(size) break return out def _get_plot_val_labels(df, size, metric, callers): curdf = df[(df["size"] == size) & (df["metric"] == metric)] vals, labels = [], [] for caller in callers: row = curdf[curdf["caller"] == caller] val = list(row["value"])[0] if val == 0: val = 0.1 vals.append(val) labels.append(list(row["label"])[0]) return vals, labels # -- general functionality def evaluate(data): """Provide evaluations for multiple callers split by structural variant type. """ work_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "validate")) truth_sets = tz.get_in(["config", "algorithm", "svvalidate"], data) if truth_sets and data.get("sv"): if isinstance(truth_sets, dict): val_summary, df_csv = _evaluate_multi(data["sv"], truth_sets, work_dir, data) summary_plots = _plot_evaluation(df_csv) data["sv-validate"] = {"csv": val_summary, "plot": summary_plots, "df": df_csv} else: assert isinstance(truth_sets, six.string_types) and utils.file_exists(truth_sets), truth_sets val_summary = _evaluate_vcf(data["sv"], truth_sets, work_dir, data) title = "%s structural variants" % dd.get_sample_name(data) summary_plots = validateplot.classifyplot_from_valfile(val_summary, outtype="png", title=title) data["sv-validate"] = {"csv": val_summary, "plot": summary_plots[0] if len(summary_plots) > 0 else None} return data if __name__ == "__main__": #_, df_csv = _evaluate_multi(["lumpy", "delly", "wham", "sv-ensemble"], # {"DEL": "synthetic_challenge_set3_tumor_20pctmasked_truth_sv_DEL.bed"}, # "syn3-tumor-ensemble-filter.bed", "sv_exclude.bed") #_, df_csv = _evaluate_multi(["lumpy", "delly", "cn_mops", "sv-ensemble"], # {"DEL": "NA12878.50X.ldgp.molpb_val.20140508.bed"}, # "NA12878-ensemble.bed", "LCR.bed.gz") import sys _plot_evaluation(sys.argv[1]) bcbio-nextgen-1.2.9/bcbio/structural/wham.py000066400000000000000000000076171415626112400210600ustar00rootroot00000000000000"""Identify structural variants using association testing with WHAM. https://github.com/jewmanchue/wham """ import collections import os import vcf from bcbio import utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import datadict as dd from bcbio.structural import shared from bcbio.variation import vcfutils from bcbio.provenance import do def run(items, background=None): """Detect copy number variations from batched set of samples using WHAM. """ if not background: background = [] background_bams = [] paired = vcfutils.get_paired_bams([x["align_bam"] for x in items], items) if paired: inputs = [paired.tumor_data] if paired.normal_bam: background = [paired.normal_data] background_bams = [paired.normal_bam] else: assert not background inputs, background = shared.find_case_control(items) background_bams = [x["align_bam"] for x in background] orig_vcf = _run_wham(inputs, background_bams) out = [] for data in inputs: if "sv" not in data: data["sv"] = [] final_vcf = shared.finalize_sv(orig_vcf, data, items) data["sv"].append({"variantcaller": "wham", "vrn_file": final_vcf}) out.append(data) return out def _sv_workdir(data): return utils.safe_makedir(os.path.join(data["dirs"]["work"], "structural", dd.get_sample_name(data), "wham")) def _run_wham(inputs, background_bams): """Run WHAM on a defined set of inputs and targets. """ out_file = os.path.join(_sv_workdir(inputs[0]), "%s-wham.vcf.gz" % dd.get_sample_name(inputs[0])) if not utils.file_exists(out_file): with file_transaction(inputs[0], out_file) as tx_out_file: cores = dd.get_cores(inputs[0]) ref_file = dd.get_ref_file(inputs[0]) include_chroms = ",".join([c.name for c in ref.file_contigs(ref_file) if chromhacks.is_autosomal_or_x(c.name)]) all_bams = ",".join([x["align_bam"] for x in inputs] + background_bams) cmd = ("whamg -x {cores} -a {ref_file} -f {all_bams} -c {include_chroms} " "| bgzip -c > {tx_out_file}") do.run(cmd.format(**locals()), "WHAM SV caller: %s" % ", ".join(dd.get_sample_name(d) for d in inputs)) return vcfutils.bgzip_and_index(out_file, inputs[0]["config"]) def filter_by_background(in_vcf, full_vcf, background, data): """Filter SV calls also present in background samples. Skips filtering of inversions, which are not characterized differently between cases and controls in test datasets. """ Filter = collections.namedtuple('Filter', ['id', 'desc']) back_filter = Filter(id='InBackground', desc='Rejected due to presence in background sample') out_file = "%s-filter.vcf" % utils.splitext_plus(in_vcf)[0] if not utils.file_uptodate(out_file, in_vcf) and not utils.file_uptodate(out_file + ".vcf.gz", in_vcf): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: reader = vcf.VCFReader(filename=in_vcf) reader.filters["InBackground"] = back_filter full_reader = vcf.VCFReader(filename=full_vcf) writer = vcf.VCFWriter(out_handle, template=reader) for out_rec, rec in zip(reader, full_reader): rec_type = rec.genotype(dd.get_sample_name(data)).gt_type if rec_type == 0 or any(rec_type == rec.genotype(dd.get_sample_name(x)).gt_type for x in background): out_rec.add_filter("InBackground") writer.write_record(out_rec) return vcfutils.bgzip_and_index(out_file, data["config"]) bcbio-nextgen-1.2.9/bcbio/upload/000077500000000000000000000000001415626112400166135ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/upload/__init__.py000066400000000000000000001215521415626112400207320ustar00rootroot00000000000000"""Handle extraction of final files from processing pipelines into storage. """ import datetime import os import six import toolz as tz from bcbio import log, utils from bcbio.upload import shared, filesystem, galaxy, s3, irods from bcbio.pipeline import run_info from bcbio.variation import vcfutils import bcbio.pipeline.datadict as dd from bcbio.rnaseq.ericscript import EricScriptConfig _approaches = {"filesystem": filesystem, "galaxy": galaxy, "s3": s3, "irods": irods} def project_from_sample(sample): upload_config = sample.get("upload") if upload_config: approach = _approaches[upload_config.get("method", "filesystem")] for finfo in _get_files_project(sample, upload_config): approach.update_file(finfo, None, upload_config) return [[sample]] def from_sample(sample): """Upload results of processing from an analysis pipeline sample. """ upload_config = sample.get("upload") if upload_config: approach = _approaches[upload_config.get("method", "filesystem")] for finfo in _get_files(sample): approach.update_file(finfo, sample, upload_config) return [[sample]] def get_all_upload_paths_from_sample(sample): upload_path_mapping = dict() upload_config = sample.get("upload") if upload_config: method = upload_config.get("method", "filesystem") if method == "filesystem": approach = _approaches[method] for finfo in _get_files_project(sample, upload_config): path = approach.get_upload_path(finfo, None, upload_config) upload_path_mapping[finfo["path"]] = path for finfo in _get_files(sample): path = approach.get_upload_path(finfo, sample, upload_config) upload_path_mapping[finfo["path"]] = path return upload_path_mapping # ## File information from sample def _get_files(sample): """Retrieve files for the sample, dispatching by analysis type. Each file is a dictionary containing the path plus associated metadata about the file and pipeline versions. """ analysis = sample.get("analysis") if analysis.lower() in ["variant", "snp calling", "variant2", "standard"]: return _get_files_variantcall(sample) elif analysis.lower() in ["rna-seq", "fastrna-seq"]: return _get_files_rnaseq(sample) elif analysis.lower() in ["smallrna-seq"]: return _get_files_srnaseq(sample) elif analysis.lower() in ["chip-seq"]: return _get_files_chipseq(sample) elif analysis.lower() in ["scrna-seq"]: return _get_files_scrnaseq(sample) elif analysis.lower() in ["wgbs-seq"]: return _get_files_wgbsseq(sample) else: return [] def _get_files_rnaseq(sample): out = [] algorithm = sample["config"]["algorithm"] out = _maybe_add_summary(algorithm, sample, out) out = _maybe_add_alignment(algorithm, sample, out) out = _maybe_add_transcriptome_alignment(sample, out) out = _maybe_add_disambiguate(algorithm, sample, out) out = _maybe_add_counts(algorithm, sample, out) out = _maybe_add_cufflinks(algorithm, sample, out) out = _maybe_add_stringtie(algorithm, sample, out) out = _maybe_add_oncofuse(algorithm, sample, out) out = _maybe_add_pizzly(algorithm, sample, out) out = _maybe_add_rnaseq_variant_file(algorithm, sample, out) out = _maybe_add_sailfish_files(algorithm, sample, out) out = _maybe_add_salmon_files(algorithm, sample, out) out = _maybe_add_kallisto_files(algorithm, sample, out) out = _maybe_add_ericscript_files(algorithm, sample, out) out = _maybe_add_arriba_files(algorithm, sample, out) out = _maybe_add_junction_files(algorithm, sample, out) return _add_meta(out, sample) def _get_files_srnaseq(sample): out = [] algorithm = sample["config"]["algorithm"] out = _maybe_add_summary(algorithm, sample, out) out = _maybe_add_trimming(algorithm, sample, out) out = _maybe_add_seqbuster(algorithm, sample, out) out = _maybe_add_trna(algorithm, sample, out) out = _maybe_add_transcriptome_alignment(sample, out) return _add_meta(out, sample) def _get_files_scrnaseq(sample): out = [] algorithm = sample["config"]["algorithm"] out = _maybe_add_summary(algorithm, sample, out) out = _maybe_add_transcriptome_alignment(sample, out) out = _maybe_add_scrnaseq(algorithm, sample, out) out = _maybe_add_barcode_histogram(algorithm, sample, out) return _add_meta(out, sample) def _get_files_chipseq(sample): out = [] algorithm = sample["config"]["algorithm"] out = _maybe_add_summary(algorithm, sample, out) out = _maybe_add_alignment(algorithm, sample, out) out = _maybe_add_nucleosome_alignments(algorithm, sample, out) out = _maybe_add_peaks(algorithm, sample, out) out = _maybe_add_greylist(algorithm, sample, out) return _add_meta(out, sample) def _get_files_wgbsseq(sample): out = [] algorithm = sample["config"]["algorithm"] # upload sorted bam as output sample["work_bam"] = sample["align_bam"] out = _maybe_add_alignment(algorithm, sample, out) bismark_report_dir = sample.get("bismark_report") if bismark_report_dir: out.append({"path": bismark_report_dir, "type": "directory", "ext": "bismark"}) bam_report = sample.get("bam_report") if bam_report: out.append({"path": bam_report, "type": "txt", "ext": "bam_report"}) deduplication_report = sample.get("deduplication_report") if deduplication_report: out.append({"path": deduplication_report, "type": "txt", "ext": "deduplication_report"}) return _add_meta(out, sample) def _add_meta(xs, sample=None, config=None): """Add top level information about the sample or flowcell to output. Sorts outputs into sample names (sample input) and project (config input). """ out = [] for x in xs: if not isinstance(x["path"], six.string_types) or not os.path.exists(x["path"]): raise ValueError("Unexpected path for upload: %s" % x) x["mtime"] = shared.get_file_timestamp(x["path"]) if sample: sample_name = dd.get_sample_name(sample) if "sample" not in x: x["sample"] = sample_name elif x["sample"] != sample_name: x["run"] = sample_name if config: fc_name = config.get("fc_name") or "project" fc_date = config.get("fc_date") or datetime.datetime.now().strftime("%Y-%m-%d") x["run"] = "%s_%s" % (fc_date, fc_name) out.append(x) return out def _get_files_variantcall(sample): """Return output files for the variant calling pipeline""" out = [] algorithm = sample["config"]["algorithm"] out = _maybe_add_summary(algorithm, sample, out) out = _maybe_add_alignment(algorithm, sample, out) out = _maybe_add_callable(sample, out) out = _maybe_add_disambiguate(algorithm, sample, out) out = _maybe_add_variant_file(algorithm, sample, out) out = _maybe_add_sv(sample, out) out = _maybe_add_hla(algorithm, sample, out) out = _maybe_add_heterogeneity(algorithm, sample, out) out = _maybe_add_validate(algorithm, sample, out) out = _maybe_add_purecn_files(sample, out) return _add_meta(out, sample) def _maybe_add_purecn_files(sample, out): """keep all files from purecn dir""" purecn_coverage = tz.get_in(["depth", "bins", "purecn"], sample) if purecn_coverage: purecn_dir, purecn_file = os.path.split(purecn_coverage) out.append({"path": purecn_dir, "type": "directory", "ext": "purecn"}) return out def _maybe_add_validate(algorith, sample, out): for i, plot in enumerate(tz.get_in(("validate", "grading_plots"), sample, [])): ptype = os.path.splitext(plot)[-1].replace(".", "") out.append({"path": plot, "type": ptype, "ext": "validate%s" % ("" if i == 0 else "-%s" % (i + 1))}) return out def _maybe_add_rnaseq_variant_file(algorithm, sample, out): vfile = sample.get("vrn_file") if vfile: ftype = "vcf.gz" if vfile.endswith(".gz") else "vcf" out.append({"path": vfile, "type": ftype}) if utils.file_exists(vfile + ".tbi"): out.append({"path": vfile + ".tbi", "type": "vcf.gz.tbi", "index": True}) return out def _maybe_add_callable(data, out): """Add callable and depth regions to output folder. """ callable_bed = dd.get_sample_callable(data) if callable_bed: out.append({"path": callable_bed, "type": "bed", "ext": "callable"}) perbase_bed = tz.get_in(["depth", "variant_regions", "per_base"], data) if perbase_bed: out.append({"path": perbase_bed, "type": "bed.gz", "ext": "depth-per-base"}) return out def _maybe_add_variant_file(algorithm, sample, out): if sample.get("align_bam") is not None and sample.get("vrn_file"): for x in sample["variants"]: if not _sample_variant_file_in_population(x): out.extend(_get_variant_file(x, ("vrn_file",))) if x.get("bed_file"): out.append({"path": x["bed_file"], "type": "bed", "ext": "%s-callregions" % x["variantcaller"], "variantcaller": x["variantcaller"]}) if x.get("vrn_stats"): for extra, fname in x["vrn_stats"].items(): ext = utils.splitext_plus(fname)[-1].replace(".", "") out.append({"path": fname, "type": ext, "ext": "%s-%s" % (x["variantcaller"], extra), "variantcaller": x["variantcaller"]}) if x.get("germline") and os.path.exists(x["germline"]): out.extend(_get_variant_file(x, ("germline",), "-germline")) return out def _maybe_add_hla(algorithm, sample, out): if sample.get("align_bam") is not None and sample.get("hla") and "call_file" in sample["hla"]: out.append({"path": sample["hla"]["call_file"], "type": "csv", "ext": "hla-%s" % (sample["hla"]["hlacaller"])}) return out def _maybe_add_heterogeneity(algorithm, sample, out): for hetinfo in sample.get("heterogeneity", []): report = hetinfo.get("report") if report and os.path.exists(report): out.append({"path": report, "type": utils.splitext_plus(report)[-1].replace(".", "").replace("-", ""), "ext": "%s-report" % (hetinfo["caller"])}) for plot_type, plot_file in hetinfo.get("plots", {}).items(): if plot_file and os.path.exists(plot_file): out.append({"path": plot_file, "type": utils.splitext_plus(plot_file)[-1].replace(".", ""), "ext": "%s-%s-plot" % (hetinfo["caller"], plot_type)}) return out def _get_batch_name(sample): """Retrieve batch name for use in SV calling outputs. Handles multiple batches split via SV calling. """ batch = dd.get_batch(sample) or dd.get_sample_name(sample) if isinstance(batch, (list, tuple)) and len(batch) > 1: batch = dd.get_sample_name(sample) return batch def _maybe_add_sv(sample, out): if sample.get("align_bam") is not None and sample.get("sv"): batch = _get_batch_name(sample) for svcall in sample["sv"]: if svcall.get("variantcaller") == "seq2c": out.extend(_get_variant_file(svcall, ("calls",), sample=batch)) out.extend(_get_variant_file(svcall, ("gender_predicted",), sample=batch)) elif svcall.get('variantcaller') == 'scramble': out.extend(_get_variant_file(svcall, ('clusters_file',), suffix='-clusters', sample=batch)) out.extend(_get_variant_file(svcall, ('mei_file',), suffix='-mei', sample=batch)) for key in ["vrn_file", "cnr", "cns", "seg", "gainloss", "segmetrics", "vrn_bed", "vrn_bedpe"]: out.extend(_get_variant_file(svcall, (key,), sample=batch)) out.extend(_get_variant_file(svcall, ("background",), suffix="-background", sample=batch)) out.extend(_get_variant_file(svcall, ("call_file",), suffix="-call", sample=batch)) out.extend(_get_variant_file(svcall, ("priority",), suffix="-priority", sample=batch)) if "plot" in svcall: for plot_name, fname in svcall["plot"].items(): ext = os.path.splitext(fname)[-1].replace(".", "") out.append({"path": fname, "sample": batch, "type": ext, "ext": "%s-%s" % (svcall["variantcaller"], plot_name), "variantcaller": svcall["variantcaller"]}) if "raw_files" in svcall: for caller, fname in svcall["raw_files"].items(): ext = utils.splitext_plus(fname)[-1][1:] out.append({"path": fname, "sample": batch, "type": ext, "ext": "%s-%s" % (svcall["variantcaller"], caller), "variantcaller": svcall["variantcaller"]}) if utils.file_exists(fname + ".tbi"): out.append({"path": fname + ".tbi", "sample": batch, "type": "vcf.gz.tbi", "index": True, "ext": "%s-%s" % (svcall["variantcaller"], caller), "variantcaller": svcall["variantcaller"]}) for extra in ["subclones", "contamination", "hetsummary", "lohsummary", "read_evidence"]: svfile = svcall.get(extra) if svfile and os.path.exists(svfile): ftype = os.path.splitext(svfile)[-1].replace(".", "") out.append({"path": svfile, "sample": dd.get_sample_name(sample) if ftype == "bam" else batch, "type": ftype, "ext": "%s-%s" % (svcall["variantcaller"], extra), "variantcaller": svcall["variantcaller"]}) fext = ".bai" if ftype == "bam" else "" if fext and os.path.exists(svfile + fext): out.append({"path": svfile + fext, "sample": dd.get_sample_name(sample) if ftype == "bam" else batch, "type": ftype + fext, "index": True, "ext": "%s-%s" % (svcall["variantcaller"], extra), "variantcaller": svcall["variantcaller"]}) if "sv-validate" in sample: for vkey in ["csv", "plot", "df"]: vfile = tz.get_in(["sv-validate", vkey], sample) if vfile: to_u = [] if isinstance(vfile, dict): for svtype, fname in vfile.items(): to_u.append((fname, "-%s" % svtype)) else: to_u.append((vfile, "-%s" % vkey if vkey in ["df"] else "")) for vfile, ext in to_u: vext = os.path.splitext(vfile)[-1].replace(".", "") out.append({"path": vfile, "sample": batch, "type": vext, "ext": "sv-validate%s" % ext}) return out def _sample_variant_file_in_population(x): """Check if a sample file is the same as the population file. This is true for batches where we don't extract into samples and do not run decomposition for gemini. '""" if "population" in x: a = _get_project_vcf(x) b = _get_variant_file(x, ("vrn_file",)) decomposed = tz.get_in(("population", "decomposed"), x) if (a and b and not decomposed and len(a) > 0 and len(b) > 0 and vcfutils.get_samples(a[0]["path"]) == vcfutils.get_samples(b[0]["path"])): return True return False def _get_variant_file(x, key, suffix="", sample=None, ignore_do_upload=False): """Retrieve VCF file with the given key if it exists, handling bgzipped. """ out = [] fname = utils.get_in(x, key) upload_key = list(key) upload_key[-1] = "do_upload" do_upload = tz.get_in(tuple(upload_key), x, True) if fname and (ignore_do_upload or do_upload): if fname.endswith(".vcf.gz"): out.append({"path": fname, "type": "vcf.gz", "ext": "%s%s" % (x["variantcaller"], suffix), "variantcaller": x["variantcaller"]}) if utils.file_exists(fname + ".tbi"): out.append({"path": fname + ".tbi", "type": "vcf.gz.tbi", "index": True, "ext": "%s%s" % (x["variantcaller"], suffix), "variantcaller": x["variantcaller"]}) elif fname.endswith((".vcf", ".bed", ".bedpe", ".bedgraph", ".cnr", ".cns", ".cnn", ".txt", ".tsv")): ftype = utils.splitext_plus(fname)[-1][1:] if ftype == "txt": extended_ftype = fname.split("-")[-1] if "/" not in extended_ftype: ftype = extended_ftype out.append({"path": fname, "type": ftype, "ext": "%s%s" % (x["variantcaller"], suffix), "variantcaller": x["variantcaller"]}) if sample: out_sample = [] for x in out: x["sample"] = sample out_sample.append(x) return out_sample else: return out def _maybe_add_sailfish_files(algorithm, sample, out): analysis = dd.get_analysis(sample) sailfish_dir = os.path.join(dd.get_work_dir(sample), "sailfish", dd.get_sample_name(sample), "quant") if os.path.exists(sailfish_dir): out.append({"path": sailfish_dir, "type": "directory", "ext": "sailfish"}) return out def _maybe_add_salmon_files(algorithm, sample, out): salmon_dir = os.path.join(dd.get_work_dir(sample), "salmon", dd.get_sample_name(sample)) if os.path.exists(salmon_dir): out.append({"path": salmon_dir, "type": "directory", "ext": "salmon"}) return out def _maybe_add_kallisto_files(algorithm, sample, out): kallisto_dir = os.path.join(dd.get_work_dir(sample), "kallisto", dd.get_sample_name(sample), "quant") if os.path.exists(kallisto_dir): out.append({"path": kallisto_dir, "type": "directory", "ext": "kallisto"}) return out def _maybe_add_ericscript_files(algorithm, sample, out): config = EricScriptConfig(sample) if os.path.exists(config.sample_out_dir): out.append({ 'path': config.sample_out_dir, 'type': 'directory', 'ext': 'ericscript', }) return out def _flatten_file_with_secondary(input, out_dir): """Flatten file representation with secondary indices (CWL-like) """ out = [] orig_dir = os.path.dirname(input["base"]) for finfo in [input["base"]] + input.get("secondary", []): cur_dir = os.path.dirname(finfo) if cur_dir != orig_dir and cur_dir.startswith(orig_dir): cur_out_dir = os.path.join(out_dir, cur_dir.replace(orig_dir + "/", "")) else: cur_out_dir = out_dir out.append({"path": finfo, "dir": cur_out_dir}) return out def _maybe_add_summary(algorithm, sample, out): out = [] if "summary" in sample: if sample["summary"].get("pdf"): out.append({"path": sample["summary"]["pdf"], "type": "pdf", "ext": "summary"}) if sample["summary"].get("qc"): for program, finfo in sample["summary"]["qc"].items(): out.extend(_flatten_file_with_secondary(finfo, os.path.join("qc", program))) if utils.get_in(sample, ("summary", "researcher")): out.append({"path": sample["summary"]["researcher"], "type": "tsv", "sample": run_info.clean_name(utils.get_in(sample, ("upload", "researcher"))), "ext": "summary"}) return out def _maybe_add_alignment(algorithm, sample, out): if _has_alignment_file(algorithm, sample) and dd.get_phenotype(sample) != "germline": for (fname, ext, isplus) in [(sample.get("work_bam"), "ready", False), (sample.get("umi_bam"), "umi", False), (sample.get("bigwig"), "ready", False), (dd.get_disc_bam(sample), "disc", True), (dd.get_sr_bam(sample), "sr", True)]: if fname and os.path.exists(fname): if fname.endswith("bam"): ftype, fext = "bam", ".bai" elif fname.endswith("cram"): ftype, fext = "cram", ".crai" elif fname.endswith("bw"): ftype, fext = "bw", ".bw" else: raise ValueError("Unexpected alignment file type %s" % fname) out.append({"path": fname, "type": ftype, "plus": isplus, "ext": ext}) if utils.file_exists(fname + fext): out.append({"path": fname + fext, "type": ftype + fext, "plus": isplus, "index": True, "ext": ext}) return out def _maybe_add_disambiguate(algorithm, sample, out): if "disambiguate" in sample and _has_alignment_file(algorithm, sample): for extra_name, fname in sample["disambiguate"].items(): ftype = os.path.splitext(fname)[-1].replace(".", "") fext = ".bai" if ftype == "bam" else "" if fname and os.path.exists(fname): out.append({"path": fname, "type": ftype, "plus": True, "ext": "disambiguate-%s" % extra_name}) if fext and utils.file_exists(fname + fext): out.append({"path": fname + fext, "type": ftype + fext, "plus": True, "index": True, "ext": "disambiguate-%s" % extra_name}) return out def _maybe_add_transcriptome_alignment(sample, out): transcriptome_bam = dd.get_transcriptome_bam(sample) if transcriptome_bam and utils.file_exists(transcriptome_bam): out.append({"path": transcriptome_bam, "type": "bam", "ext": "transcriptome"}) return out def _maybe_add_nucleosome_alignments(algorithm, sample, out): """ for ATAC-seq, also upload NF, MN, DN and TN bam files """ atac_align = tz.get_in(("atac", "align"), sample, {}) for alignment in atac_align.keys(): out.append({"path": atac_align[alignment], "type": "bam", "ext": alignment}) return out def _maybe_add_counts(algorithm, sample, out): if not dd.get_count_file(sample): return out out.append({"path": sample["count_file"], "type": "counts", "ext": "ready"}) stats_file = os.path.splitext(sample["count_file"])[0] + ".stats" if utils.file_exists(stats_file): out.append({"path": stats_file, "type": "count_stats", "ext": "ready"}) return out def _maybe_add_scrnaseq(algorithm, sample, out): count_file = dd.get_count_file(sample) if not count_file: return out else: out.append({"path": count_file, "type": "mtx"}) out.append({"path": count_file + ".rownames", "type": "rownames"}) out.append({"path": count_file + ".colnames", "type": "colnames"}) umi_file = os.path.splitext(count_file)[0] + "-dupes.mtx" if utils.file_exists(umi_file): out.append({"path": umi_file, "type": "mtx"}) out.append({"path": umi_file + ".rownames", "type": "rownames"}) out.append({"path": umi_file + ".colnames", "type": "colnames"}) return out def _maybe_add_barcode_histogram(algorithm, sample, out): if not dd.get_count_file(sample): return out count_file = sample["count_file"] histogram_file = os.path.join(os.path.dirname(count_file), "cb-histogram.txt") histogram_filtered_file = os.path.join(os.path.dirname(count_file), "cb-histogram-filtered.txt") out.append({"path": histogram_file, "type": "tsv", "ext": "barcodes"}) out.append({"path": histogram_file, "type": "tsv", "ext": "barcodes-filtered"}) return out def _maybe_add_oncofuse(algorithm, sample, out): if sample.get("oncofuse_file", None) is not None: out.append({"path": sample["oncofuse_file"], "type": "tsv", "dir": "oncofuse", "ext": "ready"}) return out def _maybe_add_pizzly(algorithm, sample, out): pizzly_dir = dd.get_pizzly_dir(sample) if pizzly_dir: out.append({"path": pizzly_dir, "type": "directory", "ext": "pizzly"}) return out def _maybe_add_arriba_files(algorithm, sample, out): pizzly_dir = dd.get_pizzly_dir(sample) arriba = dd.get_arriba(sample) if arriba: out.append({"path": arriba["fusions"], "type": "tsv", "ext": "arriba-fusions", "dir": "arriba"}) out.append({"path": arriba["discarded"], "type": "tsv", "ext": "arriba-discarded-fusions", "dir": "arriba"}) return out def _maybe_add_junction_files(algorithm, sample, out): """ add splice junction files from STAR, if available """ junction_bed = dd.get_junction_bed(sample) if junction_bed: out.append({"path": junction_bed, "type": "bed", "ext": "SJ", "dir": "STAR"}) chimeric_file = dd.get_chimericjunction(sample) if chimeric_file: out.append({"path": chimeric_file, "type": "tsv", "ext": "chimericSJ", "dir": "STAR"}) sj_file = dd.get_starjunction(sample) if sj_file: out.append({"path": sj_file, "type": "tab", "ext": "SJ", "dir": "STAR"}) star_summary = dd.get_summary_qc(sample).get("star", None) if star_summary: star_log = star_summary["base"] if star_log: out.append({"path": star_log, "type": "log", "dir": "STAR"}) return out def _maybe_add_cufflinks(algorithm, sample, out): if "cufflinks_dir" in sample: out.append({"path": sample["cufflinks_dir"], "type": "directory", "ext": "cufflinks"}) return out def _maybe_add_stringtie(algorithm, sample, out): if "stringtie_dir" in sample: out.append({"path": sample["stringtie_dir"], "type": "directory", "ext": "stringtie"}) return out def _maybe_add_trimming(algorithm, sample, out): fn = sample["collapse"] + "_size_stats" if utils.file_exists(fn): out.append({"path": fn, "type": "trimming_stats", "ext": "ready"}) return out def _maybe_add_seqbuster(algorithm, sample, out): if "seqbuster" not in sample: return out fn = sample["seqbuster"] if utils.file_exists(fn): out.append({"path": fn, "type": "counts", "ext": "mirbase-ready"}) fn = sample.get("seqbuster_novel") fn = sample["mirtop"] if utils.file_exists(fn): out.append({"path": fn, "type": "gff", "ext": "mirbase-ready"}) if "seqbuster_novel" in sample and utils.file_exists(sample["seqbuster_novel"]): fn = sample["seqbuster_novel"] out.append({"path": fn, "type": "counts", "ext": "novel-ready"}) return out def _maybe_add_trna(algorithm, sample, out): if "trna" not in sample: return out fn = sample["trna"] if utils.file_exists(fn): out.append({"path": fn, "type": "directory", "ext": "mintmap"}) return out def _maybe_add_peaks(algorithm, sample, out): out_dir = sample.get("peaks_files", {}) if dd.get_chip_method(sample) == "atac": for files in out_dir.values(): for caller in files: if caller == "main": continue for fn in files[caller]: if os.path.exists(fn): out.append({"path": fn, "dir": caller, "ext": utils.splitext_plus(fn)[1]}) else: for caller in out_dir: if caller == "main": continue for fn in out_dir[caller]: if os.path.exists(fn): out.append({"path": fn, "dir": caller, "ext": utils.splitext_plus(fn)[1]}) return out def _maybe_add_greylist(algorithm, sample, out): greylist = sample.get("greylist", None) if greylist: out.append({"path": greylist, "type": "directory", "ext": "greylist"}) return out def _has_alignment_file(algorithm, sample): return (((algorithm.get("aligner") or algorithm.get("realign") or algorithm.get("recalibrate") or algorithm.get("bam_clean") or algorithm.get("mark_duplicates", algorithm.get("aligner")))) and sample.get("work_bam") is not None and "upload_alignment" not in dd.get_tools_off(sample)) # ## File information from full project def _add_batch(x, sample): """Potentially add batch name to an upload file. """ added = False for batch in sorted(dd.get_batches(sample) or [], key=len, reverse=True): if batch and os.path.basename(x["path"]).startswith(("%s-" % batch, "%s.vcf" % batch)): x["batch"] = batch added = True break if not added: x["batch"] = dd.get_sample_name(sample) return x def _get_project_vcf(x, suffix=""): """Get our project VCF, either from the population or the variant batch file. """ vcfs = _get_variant_file(x, ("population", "vcf"), suffix=suffix) if not vcfs: vcfs = _get_variant_file(x, ("vrn_file_batch", ), suffix=suffix, ignore_do_upload=True) if not vcfs and x.get("variantcaller") == "ensemble": vcfs = _get_variant_file(x, ("vrn_file", ), suffix=suffix) return vcfs def _get_files_project(sample, upload_config): """Retrieve output files associated with an entire analysis project. """ out = [{"path": sample["provenance"]["programs"]}] if os.path.exists(tz.get_in(["provenance", "data"], sample) or ""): out.append({"path": sample["provenance"]["data"]}) for fname in ["bcbio-nextgen.log", "bcbio-nextgen-commands.log"]: if os.path.exists(os.path.join(log.get_log_dir(sample["config"]), fname)): out.append({"path": os.path.join(log.get_log_dir(sample["config"]), fname), "type": "external_command_log", "ext": ""}) if "summary" in sample and sample["summary"].get("project"): out.append({"path": sample["summary"]["project"]}) if "summary" in sample and sample["summary"].get("metadata"): out.append({"path": sample["summary"]["metadata"]}) mixup_check = tz.get_in(["summary", "mixup_check"], sample) if mixup_check: out.append({"path": sample["summary"]["mixup_check"], "type": "directory", "ext": "mixup_check"}) report = os.path.join(dd.get_work_dir(sample), "report") if utils.file_exists(report): out.append({"path": report, "type": "directory", "ext": "report"}) multiqc = tz.get_in(["summary", "multiqc"], sample) if multiqc: out.extend(_flatten_file_with_secondary(multiqc, "multiqc")) ataqv = tz.get_in(["ataqv_report"], sample) if ataqv: out.extend(_flatten_file_with_secondary(ataqv, "ataqv")) if sample.get("seqcluster", {}): out.append({"path": sample["seqcluster"].get("out_dir"), "type": "directory", "ext": "seqcluster"}) if sample.get("mirge", {}): for fn in sample["mirge"]: out.append({"path": fn, "dir": "mirge"}) if sample.get("report", None): out.append({"path": os.path.dirname(sample["report"]), "type": "directory", "ext": "seqclusterViz"}) for x in sample.get("variants", []): if "pop_db" in x: out.append({"path": x["pop_db"], "type": "sqlite", "variantcaller": x["variantcaller"]}) for x in sample.get("variants", []): if "population" in x: pop_db = tz.get_in(["population", "db"], x) if pop_db: out.append({"path": pop_db, "type": "sqlite", "variantcaller": x["variantcaller"]}) suffix = "-annotated-decomposed" if tz.get_in(("population", "decomposed"), x) else "-annotated" vcfs = _get_project_vcf(x, suffix) out.extend([_add_batch(f, sample) for f in vcfs]) for x in sample.get("variants", []): if x.get("validate") and x["validate"].get("grading_summary"): out.append({"path": x["validate"]["grading_summary"]}) break sv_project = set() pon_project = set() for svcall in sample.get("sv", []): if svcall.get("variantcaller") == "seq2c": if svcall.get("calls_all") and svcall["calls_all"] not in sv_project: out.append({"path": svcall["coverage_all"], "batch": "seq2c", "ext": "coverage", "type": "tsv"}) out.append({"path": svcall["read_mapping"], "batch": "seq2c", "ext": "read_mapping", "type": "txt"}) out.append({"path": svcall["calls_all"], "batch": "seq2c", "ext": "calls", "type": "tsv"}) sv_project.add(svcall["calls_all"]) if svcall.get("variantcaller") == "gatkcnv": if svcall.get("pon") and svcall["pon"] not in pon_project: out.append({"path": svcall["pon"], "batch": "gatkcnv", "ext": "pon", "type": "hdf5"}) pon_project.add(svcall.get("pon")) purecn_pon = tz.get_in(["config", "algorithm", "purecn_pon_build"], sample) genome_build = dd.get_genome_build(sample) if purecn_pon: work_dir = tz.get_in(["dirs", "work"], sample) gemini_dir = os.path.join(work_dir, "gemini") mapping_bias_filename = f"mapping_bias_{genome_build}.rds" mapping_bias_file = os.path.join(gemini_dir, mapping_bias_filename) normal_db_file = f"normalDB_{genome_build}.rds" normal_db = os.path.join(gemini_dir, normal_db_file) if mapping_bias_file and normal_db: out.append({"path": mapping_bias_file}) out.append({"path": normal_db}) if "coverage" in sample: cov_db = tz.get_in(["coverage", "summary"], sample) if cov_db: out.append({"path": cov_db, "type": "sqlite", "ext": "coverage"}) all_coverage = tz.get_in(["coverage", "all"], sample) if all_coverage: out.append({"path": all_coverage, "type": "bed", "ext": "coverage"}) if dd.get_mirna_counts(sample): out.append({"path": dd.get_mirna_counts(sample)}) if dd.get_isomir_counts(sample): out.append({"path": dd.get_isomir_counts(sample)}) if dd.get_novel_mirna_counts(sample): out.append({"path": dd.get_novel_mirna_counts(sample)}) if dd.get_novel_isomir_counts(sample): out.append({"path": dd.get_novel_isomir_counts(sample)}) if dd.get_combined_counts(sample): count_file = dd.get_combined_counts(sample) if sample["analysis"].lower() == "scrna-seq": out.append({"path": count_file, "type": "mtx"}) out.append({"path": count_file + ".rownames", "type": "rownames"}) out.append({"path": count_file + ".colnames", "type": "colnames"}) out.append({"path": count_file + ".metadata", "type": "metadata"}) umi_file = os.path.splitext(count_file)[0] + "-dupes.mtx" if utils.file_exists(umi_file): out.append({"path": umi_file, "type": "mtx"}) out.append({"path": umi_file + ".rownames", "type": "rownames"}) out.append({"path": umi_file + ".colnames", "type": "colnames"}) if dd.get_combined_histogram(sample): out.append({"path": dd.get_combined_histogram(sample), "type": "txt"}) rda = os.path.join(os.path.dirname(count_file), "se.rda") if utils.file_exists(rda): out.append({"path": rda, "type": "rda"}) else: out.append({"path": dd.get_combined_counts(sample), "dir": "featureCounts"}) if dd.get_summarized_experiment(sample): out.append({"path": dd.get_summarized_experiment(sample), "dir": "counts"}) if dd.get_tximport(sample): out.append({"path": dd.get_tximport(sample)["gene_tpm"], "dir": "tpm"}) out.append({"path": dd.get_tximport(sample)["gene_counts"], "dir": "counts"}) if dd.get_annotated_combined_counts(sample): out.append({"path": dd.get_annotated_combined_counts(sample), "dir": "featureCounts"}) if dd.get_combined_fpkm(sample): out.append({"path": dd.get_combined_fpkm(sample)}) if dd.get_combined_fpkm_isoform(sample): out.append({"path": dd.get_combined_fpkm_isoform(sample)}) if dd.get_transcript_assembler(sample): out.append({"path": dd.get_merged_gtf(sample)}) if dd.get_dexseq_counts(sample): out.append({"path": dd.get_dexseq_counts(sample)}) out.append({"path": "%s.ann" % dd.get_dexseq_counts(sample)}) if dd.get_express_counts(sample): out.append({"path": dd.get_express_counts(sample)}) if dd.get_express_fpkm(sample): out.append({"path": dd.get_express_fpkm(sample)}) if dd.get_express_tpm(sample): out.append({"path": dd.get_express_tpm(sample)}) if dd.get_isoform_to_gene(sample): out.append({"path": dd.get_isoform_to_gene(sample)}) if dd.get_square_vcf(sample): out.append({"path": dd.get_square_vcf(sample)}) if dd.get_sailfish_transcript_tpm(sample): out.append({"path": dd.get_sailfish_transcript_tpm(sample)}) if dd.get_sailfish_gene_tpm(sample): out.append({"path": dd.get_sailfish_gene_tpm(sample)}) if dd.get_tx2gene(sample): out.append({"path": dd.get_tx2gene(sample)}) if dd.get_spikein_counts(sample): out.append({"path": dd.get_spikein_counts(sample)}) if tz.get_in(("peaks_files", "consensus", "main"), sample): out.append({"path": tz.get_in(("peaks_files", "consensus", "main"), sample), "dir": "consensus"}) if tz.get_in(("peak_counts", "peaktable"), sample): out.append({"path": tz.get_in(("peak_counts", "peaktable"), sample), "dir": "consensus"}) transcriptome_dir = os.path.join(dd.get_work_dir(sample), "inputs", "transcriptome") if os.path.exists(transcriptome_dir): out.append({"path": transcriptome_dir, "type": "directory", "ext": "transcriptome"}) rnaseq_se_qc_file = os.path.join(dd.get_work_dir(sample), "qc", "bcbio-se.html") if os.path.exists(rnaseq_se_qc_file): out.append({"path": rnaseq_se_qc_file}) return _add_meta(out, config=upload_config) bcbio-nextgen-1.2.9/bcbio/upload/filesystem.py000066400000000000000000000070251415626112400213550ustar00rootroot00000000000000"""Extract files from processing run into output directory, organized by sample. """ import os import shutil from bcbio import utils from bcbio.log import logger from bcbio.upload import shared def update_file(finfo, sample_info, config, pass_uptodate=False): """Update the file in local filesystem storage. """ storage_dir = utils.safe_makedir(_get_storage_dir(finfo, config)) if finfo.get("type") == "directory": return _copy_finfo_directory(finfo, storage_dir) else: return _copy_finfo(finfo, storage_dir, pass_uptodate=pass_uptodate) def get_upload_path(finfo, sample_info, config): """"Dry" update the file: only return the upload path """ try: storage_dir = _get_storage_dir(finfo, config) except ValueError: return None if finfo.get("type") == "directory": return _get_dir_upload_path(finfo, storage_dir) else: return _get_file_upload_path(finfo, storage_dir) def _get_storage_dir(finfo, config): # skip if we have no directory to upload to if "dir" not in config: raise ValueError("Expect `dir` in upload specification: " "http://bcbio-nextgen.readthedocs.io/en/latest/contents/configuration.html#upload") if "run" in finfo: storage_dir = os.path.join(config["dir"], finfo["run"]) elif "sample" in finfo: storage_dir = os.path.join(config["dir"], finfo["sample"]) else: raise ValueError("Unexpected input file information: %s" % finfo) if "dir" in finfo: storage_dir = os.path.join(storage_dir, finfo["dir"]) return storage_dir def _get_file_upload_path(finfo, storage_dir): if "sample" in finfo and "ext" in finfo and "type" in finfo: out_file = os.path.join(storage_dir, "%s-%s%s%s" % (finfo["sample"], finfo["ext"], "-" if (".txt" in finfo["type"]) else ".", finfo["type"])) elif "batch" in finfo and "ext" in finfo and "type" in finfo: out_file = os.path.join(storage_dir, "%s-%s%s%s" % (finfo["batch"], finfo["ext"], "-" if (".txt" in finfo["type"]) else ".", finfo["type"])) else: out_file = os.path.join(storage_dir, os.path.basename(finfo["path"])) return os.path.abspath(out_file) def _get_dir_upload_path(finfo, storage_dir): return os.path.abspath(os.path.join(storage_dir, finfo["ext"])) def _copy_finfo(finfo, storage_dir, pass_uptodate=False): """Copy a file into the output storage directory. """ out_file = _get_file_upload_path(finfo, storage_dir) if not shared.up_to_date(out_file, finfo): logger.info("Storing in local filesystem: %s" % out_file) shutil.copy(finfo["path"], out_file) return out_file if pass_uptodate: return out_file def _copy_finfo_directory(finfo, out_dir): """Copy a directory into the final output directory. """ out_dir = _get_dir_upload_path(finfo, out_dir) if not shared.up_to_date(out_dir, finfo): logger.info("Storing directory in local filesystem: %s" % out_dir) if os.path.exists(out_dir): shutil.rmtree(out_dir) shutil.copytree(finfo["path"], out_dir) for tmpdir in ["tx", "tmp"]: if os.path.exists(os.path.join(out_dir, tmpdir)): shutil.rmtree(os.path.join(out_dir, tmpdir)) os.utime(out_dir, None) return out_dir bcbio-nextgen-1.2.9/bcbio/upload/galaxy.py000066400000000000000000000200701415626112400204510ustar00rootroot00000000000000"""Move files to local Galaxy upload directory and add to Galaxy Data Libraries. Required configurable variables in upload: dir """ from __future__ import print_function import collections import os import shutil import time import warnings from bcbio import utils from bcbio.log import logger from bcbio.upload import filesystem from bcbio.pipeline import qcsummary # Avoid bioblend import errors, raising at time of use try: with warnings.catch_warnings(): warnings.simplefilter("ignore") import bioblend from bioblend.galaxy import GalaxyInstance import simplejson except ImportError: GalaxyInstance, bioblend, simplejson = None, None, None def update_file(finfo, sample_info, config): """Update file in Galaxy data libraries. """ if GalaxyInstance is None: raise ImportError("Could not import bioblend.galaxy") if "dir" not in config: raise ValueError("Galaxy upload requires `dir` parameter in config specifying the " "shared filesystem path to move files to.") if "outputs" in config: _galaxy_tool_copy(finfo, config["outputs"]) else: _galaxy_library_upload(finfo, sample_info, config) def _galaxy_tool_copy(finfo, outputs): """Copy information directly to pre-defined outputs from a Galaxy tool. XXX Needs generalization """ tool_map = {"align": "bam", "variants": "vcf.gz"} for galaxy_key, finfo_type in tool_map.items(): if galaxy_key in outputs and finfo.get("type") == finfo_type: shutil.copy(finfo["path"], outputs[galaxy_key]) def _galaxy_library_upload(finfo, sample_info, config): """Upload results to galaxy library. """ folder_name = "%s_%s" % (config["fc_date"], config["fc_name"]) storage_dir = utils.safe_makedir(os.path.join(config["dir"], folder_name)) if finfo.get("type") == "directory": storage_file = None if finfo.get("ext") == "qc": pdf_file = qcsummary.prep_pdf(finfo["path"], config) if pdf_file: finfo["path"] = pdf_file finfo["type"] = "pdf" storage_file = filesystem.copy_finfo(finfo, storage_dir, pass_uptodate=True) else: storage_file = filesystem.copy_finfo(finfo, storage_dir, pass_uptodate=True) if "galaxy_url" in config and "galaxy_api_key" in config: galaxy_url = config["galaxy_url"] if not galaxy_url.endswith("/"): galaxy_url += "/" gi = GalaxyInstance(galaxy_url, config["galaxy_api_key"]) else: raise ValueError("Galaxy upload requires `galaxy_url` and `galaxy_api_key` in config") if storage_file and sample_info and not finfo.get("index", False) and not finfo.get("plus", False): _to_datalibrary_safe(storage_file, gi, folder_name, sample_info, config) def _to_datalibrary_safe(fname, gi, folder_name, sample_info, config): """Upload with retries for intermittent JSON failures. """ num_tries = 0 max_tries = 5 while 1: try: _to_datalibrary(fname, gi, folder_name, sample_info, config) break except (simplejson.scanner.JSONDecodeError, bioblend.galaxy.client.ConnectionError) as e: num_tries += 1 if num_tries > max_tries: raise print("Retrying upload, failed with:", str(e)) time.sleep(5) def _to_datalibrary(fname, gi, folder_name, sample_info, config): """Upload a file to a Galaxy data library in a project specific folder. """ library = _get_library(gi, sample_info, config) libitems = gi.libraries.show_library(library.id, contents=True) folder = _get_folder(gi, folder_name, library, libitems) _file_to_folder(gi, fname, sample_info, libitems, library, folder) def _file_to_folder(gi, fname, sample_info, libitems, library, folder): """Check if file exists on Galaxy, if not upload to specified folder. """ full_name = os.path.join(folder["name"], os.path.basename(fname)) # Handle VCF: Galaxy reports VCF files without the gzip extension file_type = "vcf_bgzip" if full_name.endswith(".vcf.gz") else "auto" if full_name.endswith(".vcf.gz"): full_name = full_name.replace(".vcf.gz", ".vcf") for item in libitems: if item["name"] == full_name: return item logger.info("Uploading to Galaxy library '%s': %s" % (library.name, full_name)) return gi.libraries.upload_from_galaxy_filesystem(str(library.id), fname, folder_id=str(folder["id"]), link_data_only="link_to_files", dbkey=sample_info["genome_build"], file_type=file_type, roles=str(library.roles) if library.roles else None) def _get_folder(gi, folder_name, library, libitems): """Retrieve or create a folder inside the library with the specified name. """ for item in libitems: if item["type"] == "folder" and item["name"] == "/%s" % folder_name: return item return gi.libraries.create_folder(library.id, folder_name)[0] GalaxyLibrary = collections.namedtuple("GalaxyLibrary", ["id", "name", "roles"]) def _get_library(gi, sample_info, config): """Retrieve the appropriate data library for the current user. """ galaxy_lib = sample_info.get("galaxy_library", config.get("galaxy_library")) role = sample_info.get("galaxy_role", config.get("galaxy_role")) if galaxy_lib: return _get_library_from_name(gi, galaxy_lib, role, sample_info, create=True) elif config.get("private_libs") or config.get("lab_association") or config.get("researcher"): return _library_from_nglims(gi, sample_info, config) else: raise ValueError("No Galaxy library specified for sample: %s" % sample_info["description"]) def _get_library_from_name(gi, name, role, sample_info, create=False): for lib in gi.libraries.get_libraries(): if lib["name"].lower() == name.lower() and not lib.get("deleted", False): return GalaxyLibrary(lib["id"], lib["name"], role) if create and name: logger.info("Creating Galaxy library: '%s'" % name) lib = gi.libraries.create_library(name) librole = str(gi.users.get_current_user()["id"] if not role else role) try: gi.libraries.set_library_permissions(str(lib["id"]), librole, librole, librole, librole) # XXX Returns error on Galaxy side but seems to work -- ugly except: pass return GalaxyLibrary(lib["id"], lib["name"], role) else: raise ValueError("Could not find Galaxy library matching '%s' for sample %s" % (name, sample_info["description"])) def _library_from_nglims(gi, sample_info, config): """Retrieve upload library from nglims specified user libraries. """ names = [config.get(x, "").strip() for x in ["lab_association", "researcher"] if config.get(x)] for name in names: for ext in ["sequencing", "lab"]: check_name = "%s %s" % (name.split()[0], ext) try: return _get_library_from_name(gi, check_name, None, sample_info) except ValueError: pass check_names = set([x.lower() for x in names]) for libname, role in config["private_libs"]: # Try to find library for lab or rsearcher if libname.lower() in check_names: return _get_library_from_name(gi, libname, role, sample_info) # default to first private library if available if len(config.get("private_libs", [])) > 0: libname, role = config["private_libs"][0] return _get_library_from_name(gi, libname, role, sample_info) # otherwise use the lab association or researcher name elif len(names) > 0: return _get_library_from_name(gi, names[0], None, sample_info, create=True) else: raise ValueError("Could not find Galaxy library for sample %s" % sample_info["description"]) bcbio-nextgen-1.2.9/bcbio/upload/irods.py000066400000000000000000000030751415626112400203120ustar00rootroot00000000000000""" Handle upload and retrieval of files from iRODS. This method requires a preconfigured connection to an iRODS repository throught the `iinit` command config options: upload: dir: ../final method: irods folder: absolute parent path in iRODS repository resource: (optional) iRODS resource name, if other than default """ import os from bcbio.provenance import do from bcbio.upload import filesystem def _check_create_collection(irods_fname,isdir=False): irods_dir="" if isdir: irods_dir=irods_fname else: irods_dir=os.path.dirname(irods_fname) cmd = ["imkdir", "-p",irods_dir] do.run(cmd,"iRODS: create collection %s" % (irods_dir)) def update_file(finfo, sample_info, config): """ Update the file to an iRODS repository. """ ffinal = filesystem.update_file(finfo, sample_info, config, pass_uptodate=True) _upload_dir_icommands_cli(config.get("dir"), config.get("folder"), config) def _upload_dir_icommands_cli(local_dir, irods_dir, config=None, metadata=None): """ Upload directory recursively via the standard icommands CLI. example: irsync -Kvar -R $resource $local_dir i:$irods_dir go to https://docs.irods.org/4.2.0/icommands/user/#irsync for more info """ args = ["-K","-v","-a","-r"] if config: if config.get("resource"): args += ["-R", config.get("resource")] _check_create_collection(irods_dir,isdir=True) cmd = ["irsync"] + args + [local_dir, "i:"+irods_dir] do.run(cmd, "Uploading to iRODS") bcbio-nextgen-1.2.9/bcbio/upload/s3.py000066400000000000000000000077571415626112400175320ustar00rootroot00000000000000"""Handle upload and retrieval of files from S3 on Amazon AWS. """ import datetime import email import os import sys from bcbio.distributed import objectstore from bcbio.provenance import do from bcbio.upload import filesystem def _update_val(key, val): if key == "mtime": return val.isoformat() elif key in ["path", "ext"]: return None else: return val def update_file(finfo, sample_info, config): """Update the file to an Amazon S3 bucket, using server side encryption. """ ffinal = filesystem.update_file(finfo, sample_info, config, pass_uptodate=True) if os.path.isdir(ffinal): to_transfer = [] for path, dirs, files in os.walk(ffinal): for f in files: full_f = os.path.join(path, f) k = full_f.replace(os.path.abspath(config["dir"]) + "/", "") to_transfer.append((full_f, k)) else: k = ffinal.replace(os.path.abspath(config["dir"]) + "/", "") to_transfer = [(ffinal, k)] region = "@%s" % config["region"] if config.get("region") else "" fname = "s3://%s%s/%s" % (config["bucket"], region, to_transfer[0][1]) conn = objectstore.connect(fname) bucket = conn.lookup(config["bucket"]) if not bucket: bucket = conn.create_bucket(config["bucket"], location=config.get("region", "us-east-1")) for fname, orig_keyname in to_transfer: keyname = os.path.join(config.get("folder", ""), orig_keyname) key = bucket.get_key(keyname) if bucket else None modified = datetime.datetime.fromtimestamp(email.utils.mktime_tz( email.utils.parsedate_tz(key.last_modified))) if key else None no_upload = key and modified >= finfo["mtime"] if not no_upload: _upload_file_aws_cli(fname, config["bucket"], keyname, config, finfo) def _upload_file_gof3r(fname, bucket, keyname, config=None, mditems=None): metadata = ["-m", "x-amz-server-side-encryption:AES256"] endpoint = [] if mditems: for name, val in mditems.items(): val = _update_val(name, val) if val: metadata += ["-m", "x-amz-meta-%s:%s" % (name, val)] if config: if config.get("reduced_redundancy"): metadata += ["-m", "x-amz-storage-class:REDUCED_REDUNDANCY"] if config.get("region"): if config.get("region") != "us-east-1": endpoint = ["--endpoint=s3-%s.amazonaws.com" % config.get("region")] cmd = ["gof3r", "put", "--no-md5", "-b", bucket, "-k", keyname, "-p", fname] + endpoint + metadata do.run(cmd, "Upload to s3: %s %s" % (bucket, keyname)) def _upload_file_aws_cli(local_fname, bucket, keyname, config=None, mditems=None): """Streaming upload via the standard AWS command line interface. """ s3_fname = "s3://%s/%s" % (bucket, keyname) args = ["--sse", "--expected-size", str(os.path.getsize(local_fname))] if config: if config.get("region"): args += ["--region", config.get("region")] if config.get("reduced_redundancy"): args += ["--storage-class", "REDUCED_REDUNDANCY"] cmd = [os.path.join(os.path.dirname(sys.executable), "aws"), "s3", "cp"] + args + \ [local_fname, s3_fname] do.run(cmd, "Upload to s3: %s %s" % (bucket, keyname)) def upload_file_boto(fname, remote_fname, mditems=None): """Upload a file using boto instead of external tools. """ r_fname = objectstore.parse_remote(remote_fname) conn = objectstore.connect(remote_fname) bucket = conn.lookup(r_fname.bucket) if not bucket: bucket = conn.create_bucket(r_fname.bucket, location=objectstore.get_region(remote_fname)) key = bucket.get_key(r_fname.key, validate=False) if mditems is None: mditems = {} if "x-amz-server-side-encryption" not in mditems: mditems["x-amz-server-side-encryption"] = "AES256" for name, val in mditems.items(): key.set_metadata(name, val) key.set_contents_from_filename(fname, encrypt_key=True) bcbio-nextgen-1.2.9/bcbio/upload/shared.py000066400000000000000000000007401415626112400204340ustar00rootroot00000000000000"""Shared functionality for managing upload of final files. """ import os import datetime from bcbio import utils def get_file_timestamp(f): return datetime.datetime.fromtimestamp(os.path.getmtime(f)) def up_to_date(new, orig): if os.path.isdir(orig["path"]): return (os.path.exists(new) and get_file_timestamp(new) >= orig["mtime"]) else: return (utils.file_exists(new) and get_file_timestamp(new) >= orig["mtime"]) bcbio-nextgen-1.2.9/bcbio/utils.py000066400000000000000000001015221415626112400170420ustar00rootroot00000000000000"""Helpful utilities for building analysis pipelines. """ import glob import gzip import os import tempfile import time import shutil import contextlib import itertools import functools import random import fnmatch import subprocess import sys import types import six import toolz as tz import yaml try: from collections.abc import Mapping except ImportError: from collections import Mapping from collections import OrderedDict try: from concurrent import futures except ImportError: try: import futures except ImportError: futures = None @contextlib.contextmanager def cpmap(cores=1): """Configurable parallel map context manager. Returns appropriate map compatible function based on configuration: - Local single core (the default) - Multiple local cores """ if int(cores) == 1: yield itertools.imap else: if futures is None: raise ImportError("concurrent.futures not available") pool = futures.ProcessPoolExecutor(cores) yield pool.map pool.shutdown() def map_wrap(f): """Wrap standard function to easily pass into 'map' processing. """ @functools.wraps(f) def wrapper(*args, **kwargs): return f(*args, **kwargs) return wrapper def transform_to(ext): """ Decorator to create an output filename from an output filename with the specified extension. Changes the extension, in_file is transformed to a new type. Takes functions like this to decorate: f(in_file, out_dir=None, out_file=None) or, f(in_file=in_file, out_dir=None, out_file=None) examples: @transform(".bam") f("the/input/path/file.sam") -> f("the/input/path/file.sam", out_file="the/input/path/file.bam") @transform(".bam") f("the/input/path/file.sam", out_dir="results") -> f("the/input/path/file.sam", out_file="results/file.bam") """ def decor(f): @functools.wraps(f) def wrapper(*args, **kwargs): out_file = kwargs.get("out_file", None) if not out_file: in_path = kwargs.get("in_file", args[0]) out_dir = kwargs.get("out_dir", os.path.dirname(in_path)) safe_makedir(out_dir) out_name = replace_suffix(os.path.basename(in_path), ext) out_file = os.path.join(out_dir, out_name) kwargs["out_file"] = out_file if not file_exists(out_file): out_file = f(*args, **kwargs) return out_file return wrapper return decor def filter_to(word): """ Decorator to create an output filename from an input filename by adding a word onto the stem. in_file is filtered by the function and the results are written to out_file. You would want to use this over transform_to if you don't know the extension of the file going in. This also memoizes the output file. Takes functions like this to decorate: f(in_file, out_dir=None, out_file=None) or, f(in_file=in_file, out_dir=None, out_file=None) examples: @filter_to(".foo") f("the/input/path/file.sam") -> f("the/input/path/file.sam", out_file="the/input/path/file.foo.bam") @filter_to(".foo") f("the/input/path/file.sam", out_dir="results") -> f("the/input/path/file.sam", out_file="results/file.foo.bam") """ def decor(f): @functools.wraps(f) def wrapper(*args, **kwargs): out_file = kwargs.get("out_file", None) if not out_file: in_path = kwargs.get("in_file", args[0]) out_dir = kwargs.get("out_dir", os.path.dirname(in_path)) safe_makedir(out_dir) out_name = append_stem(os.path.basename(in_path), word) out_file = os.path.join(out_dir, out_name) kwargs["out_file"] = out_file if not file_exists(out_file): out_file = f(*args, **kwargs) return out_file return wrapper return decor def memoize_outfile(ext=None, stem=None): """ Memoization decorator. See docstring for transform_to and filter_to for details. """ if ext: return transform_to(ext) if stem: return filter_to(stem) def to_single_data(input): """Convert an input to a single bcbio data/world object. Handles both single sample cases (CWL) and all sample cases (standard bcbio). """ if (isinstance(input, (list, tuple)) and len(input) == 1): return input[0] else: assert isinstance(input, dict), input return input def unpack_worlds(items): """Handle all the ways we can pass multiple samples for back-compatibility. """ # Unpack nested lists of samples grouped together (old IPython style) if isinstance(items[0], (list, tuple)) and len(items[0]) == 1: out = [] for d in items: assert len(d) == 1 and isinstance(d[0], dict), len(d) out.append(d[0]) # Unpack a single argument with multiple samples (CWL style) elif isinstance(items, (list, tuple)) and len(items) == 1 and isinstance(items[0], (list, tuple)): out = items[0] else: out = items return out def safe_makedir(dname): """Make a directory if it doesn't exist, handling concurrent race conditions. """ if not dname: return dname num_tries = 0 max_tries = 5 while not os.path.exists(dname): # we could get an error here if multiple processes are creating # the directory at the same time. Grr, concurrency. try: os.makedirs(dname) except OSError: if num_tries > max_tries: raise num_tries += 1 time.sleep(2) return dname @contextlib.contextmanager def chdir(new_dir): """Context manager to temporarily change to a new directory. http://lucentbeing.com/blog/context-managers-and-the-with-statement-in-python/ """ # On busy filesystems can have issues accessing main directory. Allow retries num_tries = 0 max_tries = 5 cur_dir = None while cur_dir is None: try: cur_dir = os.getcwd() except OSError: if num_tries > max_tries: raise num_tries += 1 time.sleep(2) safe_makedir(new_dir) os.chdir(new_dir) try: yield finally: os.chdir(cur_dir) @contextlib.contextmanager def tmpfile(*args, **kwargs): """Make a tempfile, safely cleaning up file descriptors on completion. """ (fd, fname) = tempfile.mkstemp(*args, **kwargs) try: yield fname finally: os.close(fd) if os.path.exists(fname): os.remove(fname) def file_exists(fname): """Check if a file exists and is non-empty. """ try: return fname and os.path.exists(fname) and os.path.getsize(fname) > 0 except OSError: return False def get_size(path): """ Returns the size in bytes if `path` is a file, or the size of all files in `path` if it's a directory. Analogous to `du -s`. """ if os.path.isfile(path): return os.path.getsize(path) return sum(get_size(os.path.join(path, f)) for f in os.listdir(path)) def file_uptodate(fname, cmp_fname): """Check if a file exists, is non-empty and is more recent than cmp_fname. """ try: return (file_exists(fname) and file_exists(cmp_fname) and os.path.getmtime(fname) >= os.path.getmtime(cmp_fname)) except OSError: return False def create_dirs(config, names=None): if names is None: names = config["dir"].keys() for dname in names: d = config["dir"][dname] safe_makedir(d) def save_diskspace(fname, reason, config): """Overwrite a file in place with a short message to save disk. This keeps files as a sanity check on processes working, but saves disk by replacing them with a short message. """ if config["algorithm"].get("save_diskspace", False): for ext in ["", ".bai"]: if os.path.exists(fname + ext): with open(fname + ext, "w") as out_handle: out_handle.write("File removed to save disk space: %s" % reason) def read_galaxy_amqp_config(galaxy_config, base_dir): """Read connection information on the RabbitMQ server from Galaxy config. """ galaxy_config = add_full_path(galaxy_config, base_dir) config = six.moves.configparser.ConfigParser() config.read(galaxy_config) amqp_config = {} for option in config.options("galaxy_amqp"): amqp_config[option] = config.get("galaxy_amqp", option) return amqp_config def add_full_path(dirname, basedir=None): if basedir is None: basedir = os.getcwd() if not dirname.startswith("/"): dirname = os.path.join(basedir, dirname) return dirname def splitext_plus(f): """Split on file extensions, allowing for zipped extensions. """ base, ext = os.path.splitext(f) if ext in [".gz", ".bz2", ".zip"]: base, ext2 = os.path.splitext(base) ext = ext2 + ext return base, ext def remove_safe(f): try: if os.path.isdir(f): shutil.rmtree(f) else: os.remove(f) except OSError: pass def move_safe(origin, target): """ Move file, skip if exists """ if origin == target: return origin if file_exists(target): return target shutil.move(origin, target) return target def file_plus_index(fname): """Convert a file name into the file plus required indexes. """ exts = {".vcf": ".idx", ".bam": ".bai", ".vcf.gz": ".tbi", ".bed.gz": ".tbi", ".fq.gz": ".gbi"} ext = splitext_plus(fname)[-1] if ext in exts: return [fname, fname + exts[ext]] else: return [fname] def remove_plus(orig): """Remove a fils, including biological index files. """ for ext in ["", ".idx", ".gbi", ".tbi", ".bai"]: if os.path.exists(orig + ext): remove_safe(orig + ext) def copy_plus(orig, new): """Copy a fils, including biological index files. """ for ext in ["", ".idx", ".gbi", ".tbi", ".bai"]: if os.path.exists(orig + ext) and (not os.path.lexists(new + ext) or not os.path.exists(new + ext)): shutil.copyfile(orig + ext, new + ext) def symlink_plus(orig, new): """Create relative symlinks and handle associated biological index files. """ orig = os.path.abspath(orig) if not os.path.exists(orig): raise RuntimeError("File not found: %s" % orig) for ext in ["", ".idx", ".gbi", ".tbi", ".bai", ".fai"]: if os.path.exists(orig + ext) and (not os.path.lexists(new + ext) or not os.path.exists(new + ext)): with chdir(os.path.dirname(new)): remove_safe(new + ext) # Work around symlink issues on some filesystems. Randomly # fail to symlink. try: os.symlink(os.path.relpath(orig + ext), os.path.basename(new + ext)) except OSError: if not os.path.exists(new + ext) or not os.path.lexists(new + ext): remove_safe(new + ext) shutil.copyfile(orig + ext, new + ext) orig_noext = splitext_plus(orig)[0] new_noext = splitext_plus(new)[0] for sub_ext in [".bai", ".dict"]: if os.path.exists(orig_noext + sub_ext) and not os.path.lexists(new_noext + sub_ext): with chdir(os.path.dirname(new_noext)): os.symlink(os.path.relpath(orig_noext + sub_ext), os.path.basename(new_noext + sub_ext)) def open_gzipsafe(f, is_gz=False): if f.endswith(".gz") or is_gz: if six.PY3: return gzip.open(f, "rt", encoding="utf-8", errors="ignore") else: return gzip.open(f) else: if six.PY3: return open(f, encoding="utf-8", errors="ignore") else: return open(f) def is_empty_gzipsafe(f): h = open_gzipsafe(f) is_empty = len(h.read(1)) > 0 h.close() return is_empty def append_stem(to_transform, word): """ renames a filename or list of filenames with 'word' appended to the stem of each one: example: append_stem("/path/to/test.sam", "_filtered") -> "/path/to/test_filtered.sam" """ if is_sequence(to_transform): return [append_stem(f, word) for f in to_transform] elif is_string(to_transform): (base, ext) = splitext_plus(to_transform) return "".join([base, word, ext]) else: raise ValueError("append_stem takes a single filename as a string or " "a list of filenames to transform.") def replace_suffix(to_transform, suffix): """ replaces the suffix on a filename or list of filenames example: replace_suffix("/path/to/test.sam", ".bam") -> "/path/to/test.bam" """ if is_sequence(to_transform): transformed = [] for f in to_transform: (base, _) = os.path.splitext(f) transformed.append(base + suffix) return transformed elif is_string(to_transform): (base, _) = os.path.splitext(to_transform) return base + suffix else: raise ValueError("replace_suffix takes a single filename as a string or " "a list of filenames to transform.") # ## Functional programming def partition_all(n, iterable): """Partition a list into equally sized pieces, including last smaller parts http://stackoverflow.com/questions/5129102/python-equivalent-to-clojures-partition-all """ it = iter(iterable) while True: chunk = list(itertools.islice(it, n)) if not chunk: break yield chunk def robust_partition_all(n, iterable): """ replaces partition_all with a more robust version. Workaround for a segfault in pybedtools when using a BedTool as an iterator: https://github.com/daler/pybedtools/issues/88 for the discussion """ it = iter(iterable) while True: x = [] for _ in range(n): try: x.append(next(it)) except StopIteration: yield x # Omitting this StopIteration results in a segfault! raise StopIteration yield x def partition(pred, iterable, tolist=False): 'Use a predicate to partition entries into false entries and true entries' # partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9 t1, t2 = itertools.tee(iterable) ifalse = six.moves.filterfalse(pred, t1) itrue = six.moves.filter(pred, t2) if tolist: return list(ifalse), list(itrue) else: return ifalse, itrue # ## Dealing with configuration files def merge_config_files(fnames): """Merge configuration files, preferring definitions in latter files. """ def _load_yaml(fname): with open(fname) as in_handle: config = yaml.safe_load(in_handle) return config out = _load_yaml(fnames[0]) for fname in fnames[1:]: cur = _load_yaml(fname) for k, v in cur.items(): if k in out and isinstance(out[k], dict): out[k].update(v) else: out[k] = v return out def deepish_copy(org): """Improved speed deep copy for dictionaries of simple python types. Thanks to Gregg Lind: http://writeonly.wordpress.com/2009/05/07/deepcopy-is-a-pig-for-simple-data/ """ out = dict().fromkeys(org) for k, v in org.items(): if isinstance(v, dict): out[k] = deepish_copy(v) else: try: out[k] = v.copy() # dicts, sets except AttributeError: try: out[k] = v[:] # lists, tuples, strings, unicode except TypeError: out[k] = v # ints return out def safe_to_float(x): """Convert to float, handling None and non-float inputs. Useful for cleaning complicated output from variant callers. """ if x is None: return None else: try: return float(x) except ValueError: return None def get_in(d, t, default=None): """ look up if you can get a tuple of values from a nested dictionary, each item in the tuple a deeper layer example: get_in({1: {2: 3}}, (1, 2)) -> 3 example: get_in({1: {2: 3}}, (2, 3)) -> {} """ return tz.get_in(t, d, default) def flatten(l): """ flatten an irregular list of lists example: flatten([[[1, 2, 3], [4, 5]], 6]) -> [1, 2, 3, 4, 5, 6] lifted from: http://stackoverflow.com/questions/2158395/ """ for el in l: if isinstance(el, (list, tuple)): for sub in flatten(el): yield sub else: yield el def is_sequence(arg): """ check if 'arg' is a sequence example: arg([]) -> True example: arg("lol") -> False """ return (not is_string(arg) and (hasattr(arg, "__getitem__") or hasattr(arg, "__iter__"))) def is_pair(arg): """ check if 'arg' is a two-item sequence """ return is_sequence(arg) and len(arg) == 2 def is_string(arg): return isinstance(arg, six.string_types) def locate(pattern, root=os.curdir): '''Locate all files matching supplied filename pattern in and below supplied root directory.''' for path, dirs, files in os.walk(os.path.abspath(root)): for filename in fnmatch.filter(files, pattern): yield os.path.join(path, filename) def itersubclasses(cls, _seen=None): """ snagged from: http://code.activestate.com/recipes/576949/ itersubclasses(cls) Generator over all subclasses of a given class, in depth first order. >>> list(itersubclasses(int)) == [bool] True >>> class A(object): pass >>> class B(A): pass >>> class C(A): pass >>> class D(B,C): pass >>> class E(D): pass >>> >>> for cls in itersubclasses(A): ... print(cls.__name__) B D E C >>> # get ALL (new-style) classes currently defined >>> [cls.__name__ for cls in itersubclasses(object)] #doctest: +ELLIPSIS ['type', ...'tuple', ...] """ if not isinstance(cls, type): raise TypeError('itersubclasses must be called with ' 'new-style classes, not %.100r' % cls) if _seen is None: _seen = set() try: subs = cls.__subclasses__() except TypeError: # fails only when cls is type subs = cls.__subclasses__(cls) for sub in subs: if sub not in _seen: _seen.add(sub) yield sub for sub in itersubclasses(sub, _seen): yield sub def replace_directory(out_files, dest_dir): """ change the output directory to dest_dir can take a string (single file) or a list of files """ if is_sequence(out_files): filenames = map(os.path.basename, out_files) return [os.path.join(dest_dir, x) for x in filenames] elif is_string(out_files): return os.path.join(dest_dir, os.path.basename(out_files)) else: raise ValueError("in_files must either be a sequence of filenames " "or a string") def which(program, env=None): """ returns the path to an executable or None if it can't be found""" if env is None: env = os.environ.copy() def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: for path in env["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file for path in get_all_conda_bins(): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None def reservoir_sample(stream, num_items, item_parser=lambda x: x): """ samples num_items from the stream keeping each with equal probability """ kept = [] for index, item in enumerate(stream): if index < num_items: kept.append(item_parser(item)) else: r = random.randint(0, index) if r < num_items: kept[r] = item_parser(item) return kept def compose(f, g): return lambda x: f(g(x)) def dictapply(d, fn): """ apply a function to all non-dict values in a dictionary """ for k, v in d.items(): if isinstance(v, dict): v = dictapply(v, fn) else: d[k] = fn(v) return d def Rscript_cmd(env="base"): """Retrieve path to locally installed Rscript in the given env. Prefers Rscript version installed via conda to a system version. """ if env == "base": rscript = which(os.path.join(get_bcbio_bin(), "Rscript")) else: conda_dir = get_conda_dir() rscript = os.path.join(conda_dir, "envs", env, "bin", "Rscript") if rscript: return rscript else: return which("Rscript") def R_sitelib(env="base"): """Retrieve the R site-library installed with the bcbio installer for a given environment. Defaults to the base environment. """ if env == "base": return os.path.join(os.path.dirname(get_bcbio_bin()), "lib", "R", "library") else: conda_dir = get_conda_dir() sitelib = os.path.join(conda_dir, "envs", env, "lib", "R", "library") if not os.path.exists(sitelib): raise OSError("The {env} environment does not have R installed.") return sitelib def R_package_script(package, script, env="base"): """Return path to a script in an R package within env (PureCN)""" conda_dir = get_conda_dir() if env == "base": env_dir = conda_dir else: env_dir = os.path.join(conda_dir, "envs", env) script_path = os.path.join(env_dir, "lib", "R", "library", package, script) if not file_exists(script_path): return None else: return script_path def R_package_path(package): """ return the path to an installed R package """ local_sitelib = R_sitelib() rscript = Rscript_cmd() cmd = """{rscript} --vanilla -e '.libPaths(c("{local_sitelib}")); find.package("{package}")'""" try: output = subprocess.check_output(cmd.format(**locals()), shell=True) except subprocess.CalledProcessError as e: return None for line in output.decode().split("\n"): if "[1]" not in line: continue dirname = line.split("[1]")[1].replace("\"", "").strip() if os.path.exists(dirname): return dirname return None def R_package_resource(package, resource): """ return a path to an R package resource, if it is available """ package_path = R_package_path(package) if not package_path: return None package_resource = os.path.join(package_path, resource) if not file_exists(package_resource): return None else: return package_resource def get_java_binpath(cmd=None): """Retrieve path for java to use, handling custom BCBIO_JAVA_HOME Defaults to the dirname of cmd, or local anaconda directory """ if os.environ.get("BCBIO_JAVA_HOME"): test_cmd = os.path.join(os.environ["BCBIO_JAVA_HOME"], "bin", "java") if os.path.exists(test_cmd): cmd = test_cmd if not cmd: cmd = Rscript_cmd() return os.path.dirname(cmd) def clear_java_home(): """Clear JAVA_HOME environment or reset to BCBIO_JAVA_HOME. Avoids accidental java injection but respects custom BCBIO_JAVA_HOME command. """ if os.environ.get("BCBIO_JAVA_HOME"): test_cmd = os.path.join(os.environ["BCBIO_JAVA_HOME"], "bin", "java") if os.path.exists(test_cmd): return "export JAVA_HOME=%s" % os.environ["BCBIO_JAVA_HOME"] return "unset JAVA_HOME" def get_java_clprep(cmd=None): """Correctly prep command line for java commands, setting PATH and unsetting JAVA_HOME. """ return "%s && export PATH=%s:\"$PATH\"" % (clear_java_home(), get_java_binpath(cmd)) def get_R_exports(env="base"): if env == "base": rpath = os.path.dirname(Rscript_cmd()) else: conda_dir = get_conda_dir() rpath = os.path.join(conda_dir, "envs", env, "bin") return f"unset R_HOME && unset R_LIBS && export PATH={rpath}:\"$PATH\"" def perl_cmd(): """Retrieve path to locally installed conda Perl or first in PATH. """ perl = which(os.path.join(get_bcbio_bin(), "perl")) if perl: return perl else: return which("perl") def get_perl_exports(tmpdir=None): """Environmental exports to use conda installed perl. """ perl_path = os.path.dirname(perl_cmd()) out = "unset PERL5LIB && export PATH=%s:\"$PATH\"" % (perl_path) if tmpdir: out += " && export TMPDIR=%s" % (tmpdir) return out def get_bcbio_env(): env = os.environ.copy() env["PATH"] = append_path(get_bcbio_bin(), env['PATH']) return env def append_path(bin, path, at_start=True): if at_start: tmpl = "{bin}:{path}" else: tmpl = "{path}:{bin}" return tmpl.format(bin=bin, path=path) def get_bcbio_bin(): return os.path.dirname(os.path.realpath(sys.executable)) def get_conda_dir(): bcbio_bin = get_bcbio_bin() return os.path.dirname(bcbio_bin) def get_all_conda_bins(): """Retrieve all possible conda bin directories, including environments. """ bcbio_bin = get_bcbio_bin() conda_dir = get_conda_dir() if os.path.join("anaconda", "envs") in conda_dir: conda_dir = os.path.join(conda_dir[:conda_dir.rfind(os.path.join("anaconda", "envs"))], "anaconda") return [bcbio_bin] + list(glob.glob(os.path.join(conda_dir, "envs", "*", "bin"))) def get_program_python(cmd): """Get the full path to a python version linked to the command. Allows finding python based programs in python 2 versus python 3 environments. """ full_cmd = os.path.realpath(which(cmd)) cmd_python = os.path.join(os.path.dirname(full_cmd), "python") env_python = None if "envs" in cmd_python: parts = cmd_python.split(os.sep) env_python = os.path.join(os.sep.join(parts[:parts.index("envs") + 2]), "bin", "python") if os.path.exists(cmd_python): return cmd_python elif env_python and os.path.exists(env_python): return env_python else: return os.path.realpath(sys.executable) def local_path_export(at_start=True, env_cmd=None): """Retrieve paths to local install, also including environment paths if env_cmd included. """ paths = [get_bcbio_bin()] if env_cmd: env_path = os.path.dirname(get_program_python(env_cmd)) if env_path not in paths: paths.insert(0, env_path) if at_start: return "export PATH=%s:\"$PATH\" && " % (":".join(paths)) else: return "export PATH=\"$PATH\":%s && " % (":".join(paths)) def locale_export(): """Exports for dealing with Click-based programs and ASCII/Unicode errors. RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment. Consult https://click.palletsprojects.com/en/7.x/python3/ for mitigation steps. """ locale_to_use = get_locale() return "export LC_ALL=%s && export LANG=%s && " % (locale_to_use, locale_to_use) def get_locale(): """ Looks up available locales on the system to find an appropriate one to pick, defaulting to C.UTF-8 which is globally available on newer systems. Prefers C.UTF-8 and en_US encodings, if available """ default_locale = "C.UTF-8" preferred_locales = {"c.utf-8", "c.utf8", "en_us.utf-8", "en_us.utf8"} locale_to_use = None try: locales = subprocess.check_output(["locale", "-a"]).decode(errors="ignore").split("\n") except subprocess.CalledProcessError: locales = [] # check for preferred locale for locale in locales: if locale.lower() in preferred_locales: locale_to_use = locale break # if preferred locale not available take first UTF-8 locale if not locale_to_use: for locale in locales: if locale.lower().endswith(("utf-8", "utf8")): locale_to_use = locale break # if locale listing not available, try using the default locale if not locale_to_use: locale_to_use = default_locale return locale_to_use def java_freetype_fix(): """Provide workaround for issues FreeType library symbols. libfontconfig.so.1: undefined symbol: FT_Done_MM_Var Cheap workaround with LD_PRELOAD, I don't know a better one. """ return "export LD_PRELOAD=%s/lib/libfreetype.so && " % os.path.dirname(get_bcbio_bin()) def is_gzipped(fname): _, ext = os.path.splitext(fname) return ext in [".gz", "gzip"] def is_bzipped(fname): _, ext = os.path.splitext(fname) return ext in [".bz2", "bzip2"] def open_possible_gzip(fname, flag="r"): if is_gzipped(fname): if "b" not in flag: flag += "b" return gzip.open(fname, flag) else: return open(fname, flag) def filter_missing(xs): """ remove items from a list if they evaluate to False """ return filter(lambda x: x, xs) def rbind(dfs): """ acts like rbind for pandas dataframes """ if len(dfs) == 1: return dfs[0] df = dfs[0] for d in dfs[1:]: df = df.append(d) return df def max_command_length(): """ get the maximum length of the command line, in bytes, defaulting to a conservative number if not set http://www.in-ulm.de/~mascheck/various/argmax/ """ DEFAULT_MAX_LENGTH = 150000 # lowest seen so far is 200k try: arg_max = os.sysconf('SC_ARG_MAX') env_lines = len(os.environ) * 4 env_chars = sum([len(x) + len(y) for x, y in os.environ.items()]) arg_length = arg_max - env_lines - 2048 except ValueError: arg_length = DEFAULT_MAX_LENGTH return arg_length if arg_length > 0 else DEFAULT_MAX_LENGTH def get_abspath(path, pardir=None): if pardir is None: pardir = os.getcwd() path = os.path.expandvars(path) return os.path.normpath(os.path.join(pardir, path)) def sort_filenames(filenames): """ sort a list of files by filename only, ignoring the directory names """ basenames = [os.path.basename(x) for x in filenames] indexes = [i[0] for i in sorted(enumerate(basenames), key=lambda x:x[1])] return [filenames[x] for x in indexes] # LazyImport from NIPY # https://github.com/nipy/nitime/blob/master/nitime/lazyimports.py class LazyImport(types.ModuleType): """ This class takes the module name as a parameter, and acts as a proxy for that module, importing it only when the module is used, but effectively acting as the module in every other way (including inside IPython with respect to introspection and tab completion) with the *exception* of reload()- reloading a :class:`LazyImport` raises an :class:`ImportError`. >>> mlab = LazyImport('matplotlib.mlab') No import happens on the above line, until we do something like call an ``mlab`` method or try to do tab completion or introspection on ``mlab`` in IPython. >>> mlab Now the :class:`LazyImport` will do an actual import, and call the dist function of the imported module. >>> mlab.dist(1969,2011) 42.0 """ def __getattribute__(self, x): # This method will be called only once, since we'll change # self.__class__ to LoadedLazyImport, and __getattribute__ will point # to module.__getattribute__ name = object.__getattribute__(self, '__name__') __import__(name) # if name above is 'package.foo.bar', package is returned, the docs # recommend that in order to get back the full thing, that we import # and then lookup the full name is sys.modules, see: # http://docs.python.org/library/functions.html#__import__ module = sys.modules[name] # Now that we've done the import, cutout the middleman and make self # act as the imported module class LoadedLazyImport(types.ModuleType): __getattribute__ = module.__getattribute__ __repr__ = module.__repr__ object.__setattr__(self, '__class__', LoadedLazyImport) # The next line will make "reload(l)" a silent no-op # sys.modules[name] = self return module.__getattribute__(x) def __repr__(self): return "" %\ object.__getattribute__(self,'__name__') def walk_json(d, func): """ Walk over a parsed JSON nested structure `d`, apply `func` to each leaf element and replace it with result """ if isinstance(d, Mapping): return OrderedDict((k, walk_json(v, func)) for k, v in d.items()) elif isinstance(d, list): return [walk_json(v, func) for v in d] else: return func(d) bcbio-nextgen-1.2.9/bcbio/variation/000077500000000000000000000000001415626112400173235ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/variation/__init__.py000066400000000000000000000001321415626112400214300ustar00rootroot00000000000000"""Analyze next-gen genomic variation, wrapping the GATK toolkit and other utilities. """ bcbio-nextgen-1.2.9/bcbio/variation/annotation.py000066400000000000000000000165201415626112400220530ustar00rootroot00000000000000"""Annotated variant VCF files with additional information. - GATK variant annotation with snpEff predicted effects. """ import glob import os import pybedtools import toolz as tz from bcbio import broad, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import vcfutils def get_gatk_annotations(config, include_depth=True, include_baseqranksum=True, gatk_input=True): """Retrieve annotations to use for GATK VariantAnnotator. If include_depth is false, we'll skip annotating DP. Since GATK downsamples this will undercount on high depth sequencing and the standard outputs from the original callers may be preferable. BaseQRankSum can cause issues with some MuTect2 and other runs, so we provide option to skip it. """ broad_runner = broad.runner_from_config(config) anns = ["MappingQualityRankSumTest", "MappingQualityZero", "QualByDepth", "ReadPosRankSumTest", "RMSMappingQuality"] if include_baseqranksum: anns += ["BaseQualityRankSumTest"] # Some annotations not working correctly with external datasets and GATK 3 if gatk_input or broad_runner.gatk_type() == "gatk4": anns += ["FisherStrand"] if broad_runner.gatk_type() == "gatk4": anns += ["MappingQuality"] else: anns += ["GCContent", "HaplotypeScore", "HomopolymerRun"] if include_depth: anns += ["DepthPerAlleleBySample"] if broad_runner.gatk_type() in ["restricted", "gatk4"]: anns += ["Coverage"] else: anns += ["DepthOfCoverage"] return anns def finalize_vcf(in_file, variantcaller, items): """Perform cleanup of the final VCF. - Adds contigs to header for bcftools compatibility - adds sample information for tumor/normal """ out_file = "%s-annotated%s" % utils.splitext_plus(in_file) if not utils.file_uptodate(out_file, in_file): header_cl = _add_vcf_header_sample_cl(in_file, items, out_file) contig_cl = _add_contig_cl(in_file, items, out_file) cls = [x for x in (contig_cl, header_cl) if x] if cls: post_cl = " | ".join(cls) + " | " with file_transaction(out_file) as tx_out_file: cmd = f"bcftools view {in_file} | {post_cl} bgzip -c > {tx_out_file}" do.run(cmd, "Finalize vcf") if utils.file_exists(out_file): return vcfutils.bgzip_and_index(out_file, items[0]["config"]) else: return in_file def _add_contig_cl(in_file, items, out_file): has_contigs = False with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if line.startswith("##contig"): has_contigs = True break elif not line.startswith("##"): break if not has_contigs: return vcfutils.add_contig_to_header_cl(dd.get_ref_file(items[0]), out_file) def _fix_generic_tn_names(paired): """Convert TUMOR/NORMAL names in output into sample IDs. """ def run(line): parts = line.rstrip("\n\r").split("\t") if "TUMOR" in parts: parts[parts.index("TUMOR")] = paired.tumor_name if "TUMOUR" in parts: parts[parts.index("TUMOUR")] = paired.tumor_name if "NORMAL" in parts: assert paired.normal_name parts[parts.index("NORMAL")] = paired.normal_name return "\t".join(parts) + "\n" return run def _add_vcf_header_sample_cl(in_file, items, base_file): """Add phenotype information to a VCF header. Encode tumor/normal relationships in VCF header. Could also eventually handle more complicated pedigree information if useful. returns a cmd """ paired = vcfutils.get_paired(items) if paired: toadd = ["##SAMPLE=" % paired.tumor_name] if paired.normal_name: toadd.append("##SAMPLE=" % paired.normal_name) toadd.append("##PEDIGREE=" % (paired.tumor_name, paired.normal_name)) new_header = _update_header(in_file, base_file, toadd, _fix_generic_tn_names(paired)) if vcfutils.vcf_has_variants(in_file): cmd = f"bcftools reheader -h {new_header} | bcftools view " return cmd def _update_header(orig_vcf, base_file, new_lines, chrom_process_fn=None): """Fix header with additional lines and remapping of generic sample names. """ new_header = "%s-sample_header.txt" % utils.splitext_plus(base_file)[0] with open(new_header, "w") as out_handle: chrom_line = None with utils.open_gzipsafe(orig_vcf) as in_handle: for line in in_handle: if line.startswith("##"): out_handle.write(line) else: chrom_line = line break assert chrom_line is not None for line in new_lines: out_handle.write(line + "\n") if chrom_process_fn: chrom_line = chrom_process_fn(chrom_line) out_handle.write(chrom_line) return new_header def get_context_files(data): """Retrieve pre-installed annotation files for annotating genome context. """ ref_file = dd.get_ref_file(data) all_files = [] for ext in [".bed.gz"]: all_files += sorted(glob.glob(os.path.normpath(os.path.join(os.path.dirname(ref_file), os.pardir, "coverage", "problem_regions", "*", "*%s" % ext)))) return sorted(all_files) def add_genome_context(orig_file, data): """Annotate a file with annotations of genome context using vcfanno. """ out_file = "%s-context.vcf.gz" % utils.splitext_plus(orig_file)[0] if not utils.file_uptodate(out_file, orig_file): with file_transaction(data, out_file) as tx_out_file: config_file = "%s.toml" % (utils.splitext_plus(tx_out_file)[0]) with open(config_file, "w") as out_handle: all_names = [] for fname in dd.get_genome_context_files(data): bt = pybedtools.BedTool(fname) if bt.field_count() >= 4: d, base = os.path.split(fname) _, prefix = os.path.split(d) name = "%s_%s" % (prefix, utils.splitext_plus(base)[0]) out_handle.write("[[annotation]]\n") out_handle.write('file = "%s"\n' % fname) out_handle.write("columns = [4]\n") out_handle.write('names = ["%s"]\n' % name) out_handle.write('ops = ["uniq"]\n') all_names.append(name) out_handle.write("[[postannotation]]\n") out_handle.write("fields = [%s]\n" % (", ".join(['"%s"' % n for n in all_names]))) out_handle.write('name = "genome_context"\n') out_handle.write('op = "concat"\n') out_handle.write('type = "String"\n') cmd = "vcfanno {config_file} {orig_file} | bgzip -c > {tx_out_file}" do.run(cmd.format(**locals()), "Annotate with problem annotations", data) return vcfutils.bgzip_and_index(out_file, data["config"]) bcbio-nextgen-1.2.9/bcbio/variation/bamprep.py000066400000000000000000000130641415626112400213270ustar00rootroot00000000000000"""Provide piped, no disk-IO, BAM preparation for variant calling. Handles independent analysis of chromosome regions, allowing parallel runs of this step. """ import os from bcbio import bam, broad, utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.pipeline import shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import realign # ## GATK/Picard preparation def region_to_gatk(region): if isinstance(region, (list, tuple)): chrom, start, end = region return "%s:%s-%s" % (chrom, start + 1, end) else: return region def _gatk_extract_reads_cl(data, region, prep_params, tmp_dir): """Use GATK to extract reads from full BAM file. """ args = ["PrintReads", "-L", region_to_gatk(region), "-R", dd.get_ref_file(data), "-I", data["work_bam"]] # GATK3 back compatibility, need to specify analysis type if "gatk4" in dd.get_tools_off(data): args = ["--analysis_type"] + args runner = broad.runner_from_config(data["config"]) return runner.cl_gatk(args, tmp_dir) def _piped_input_cl(data, region, tmp_dir, out_base_file, prep_params): """Retrieve the commandline for streaming input into preparation step. """ return data["work_bam"], _gatk_extract_reads_cl(data, region, prep_params, tmp_dir) def _piped_realign_gatk(data, region, cl, out_base_file, tmp_dir, prep_params): """Perform realignment with GATK, using input commandline. GATK requires writing to disk and indexing before realignment. """ broad_runner = broad.runner_from_config(data["config"]) pa_bam = "%s-prealign%s" % os.path.splitext(out_base_file) if not utils.file_exists(pa_bam): with file_transaction(data, pa_bam) as tx_out_file: cmd = "{cl} -o {tx_out_file}".format(**locals()) do.run(cmd, "GATK re-alignment {0}".format(region), data) bam.index(pa_bam, data["config"]) realn_file = realign.gatk_realigner_targets(broad_runner, pa_bam, dd.get_ref_file(data), data["config"], region=region_to_gatk(region), known_vrns=dd.get_variation_resources(data)) realn_cl = realign.gatk_indel_realignment_cl(broad_runner, pa_bam, dd.get_ref_file(data), realn_file, tmp_dir, region=region_to_gatk(region), known_vrns=dd.get_variation_resources(data)) return pa_bam, realn_cl def _cleanup_tempfiles(data, tmp_files): for tmp_file in tmp_files: if tmp_file and tmp_file != data["work_bam"]: for ext in [".bam", ".bam.bai", ".bai"]: fname = "%s%s" % (os.path.splitext(tmp_file)[0], ext) if os.path.exists(fname): os.remove(fname) def _piped_bamprep_region_gatk(data, region, prep_params, out_file, tmp_dir): """Perform semi-piped BAM preparation using Picard/GATK tools. """ broad_runner = broad.runner_from_config(data["config"]) cur_bam, cl = _piped_input_cl(data, region, tmp_dir, out_file, prep_params) if not prep_params["realign"]: prerecal_bam = None elif prep_params["realign"] == "gatk": prerecal_bam, cl = _piped_realign_gatk(data, region, cl, out_file, tmp_dir, prep_params) else: raise NotImplementedError("Realignment method: %s" % prep_params["realign"]) with file_transaction(data, out_file) as tx_out_file: out_flag = ("-o" if (prep_params["realign"] == "gatk" or not prep_params["realign"]) else ">") cmd = "{cl} {out_flag} {tx_out_file}".format(**locals()) do.run(cmd, "GATK: realign {0}".format(region), data) _cleanup_tempfiles(data, [cur_bam, prerecal_bam]) # ## Shared functionality def _get_prep_params(data): """Retrieve configuration parameters with defaults for preparing BAM files. """ realign_param = dd.get_realign(data) realign_param = "gatk" if realign_param is True else realign_param return {"realign": realign_param} def _need_prep(data): prep_params = _get_prep_params(data) return prep_params["realign"] def _piped_bamprep_region(data, region, out_file, tmp_dir): """Do work of preparing BAM input file on the selected region. """ if _need_prep(data): prep_params = _get_prep_params(data) _piped_bamprep_region_gatk(data, region, prep_params, out_file, tmp_dir) else: raise ValueError("No realignment specified") def piped_bamprep(data, region=None, out_file=None): """Perform full BAM preparation using pipes to avoid intermediate disk IO. Handles realignment of original BAMs. """ data["region"] = region if not _need_prep(data): return [data] else: utils.safe_makedir(os.path.dirname(out_file)) if region[0] == "nochrom": prep_bam = shared.write_nochr_reads(data["work_bam"], out_file, data["config"]) elif region[0] == "noanalysis": prep_bam = shared.write_noanalysis_reads(data["work_bam"], region[1], out_file, data["config"]) else: if not utils.file_exists(out_file): with tx_tmpdir(data) as tmp_dir: _piped_bamprep_region(data, region, out_file, tmp_dir) prep_bam = out_file bam.index(prep_bam, data["config"]) data["work_bam"] = prep_bam return [data] bcbio-nextgen-1.2.9/bcbio/variation/bedutils.py000066400000000000000000000274461415626112400215250ustar00rootroot00000000000000"""Utilities for manipulating BED files. """ import os import shutil import sys import subprocess import toolz as tz from bcbio import utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import vcfutils def get_sort_cmd(tmp_dir=None): """Retrieve GNU coreutils sort command, using version-sort if available. Recent versions of sort have alpha-numeric sorting, which provides more natural sorting of chromosomes (chr1, chr2) instead of (chr1, chr10). This also fixes versions of sort, like 8.22 in CentOS 7.1, that have broken sorting without version sorting specified. https://github.com/bcbio/bcbio-nextgen/issues/624 https://github.com/bcbio/bcbio-nextgen/issues/1017 """ has_versionsort = subprocess.check_output("sort --help | grep version-sort; exit 0", shell=True).strip() if has_versionsort: cmd = "sort -V" else: cmd = "sort" if tmp_dir and os.path.exists(tmp_dir) and os.path.isdir(tmp_dir): cmd += " -T %s" % tmp_dir return cmd def check_bed_contigs(in_file, data): """Ensure BED file contigs match the reference genome. """ if not dd.get_ref_file(data): return contigs = set([]) with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if not line.startswith(("#", "track", "browser", "@")) and line.strip(): contigs.add(line.split()[0]) ref_contigs = set([x.name for x in ref.file_contigs(dd.get_ref_file(data))]) if contigs and len(contigs - ref_contigs) / float(len(contigs)) > 0.25: raise ValueError("Contigs in BED file %s not in reference genome:\n %s\n" % (in_file, list(contigs - ref_contigs)) + "This is typically due to chr1 versus 1 differences in BED file and reference.") def has_regions(in_file): with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if not line.startswith(("#", "track", "browser", "@")) and line.strip(): return True return False def check_bed_coords(in_file, data): """Ensure BED file coordinates match reference genome. Catches errors like using a hg38 BED file for an hg19 genome run. """ if dd.get_ref_file(data): contig_sizes = {} for contig in ref.file_contigs(dd.get_ref_file(data)): contig_sizes[contig.name] = contig.size with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if not line.startswith(("#", "track", "browser", "@")) and line.strip(): parts = line.split() if len(parts) > 3: try: end = int(parts[2]) except ValueError: continue contig = parts[0] check_size = contig_sizes.get(contig) if check_size and end > check_size: raise ValueError("Found BED coordinate off the end of the chromosome:\n%s%s\n" "Is the input BED from the right genome build?" % (line, in_file)) def clean_file(in_file, data, prefix="", bedprep_dir=None, simple=None): """Prepare a clean sorted input BED file without headers """ # Remove non-ascii characters. Used in coverage analysis, to support JSON code in one column # and be happy with sambamba: simple = "iconv -c -f utf-8 -t ascii | sed 's/ //g' |" if simple else "" if in_file: if not bedprep_dir: bedprep_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "bedprep")) # Avoid running multiple times with same prefix if prefix and os.path.basename(in_file).startswith(prefix): return in_file out_file = os.path.join(bedprep_dir, "%s%s" % (prefix, os.path.basename(in_file))) out_file = out_file.replace(".interval_list", ".bed") if out_file.endswith(".gz"): out_file = out_file[:-3] if not utils.file_uptodate(out_file, in_file): check_bed_contigs(in_file, data) check_bed_coords(in_file, data) with file_transaction(data, out_file) as tx_out_file: bcbio_py = sys.executable cat_cmd = "zcat" if in_file.endswith(".gz") else "cat" sort_cmd = get_sort_cmd(os.path.dirname(tx_out_file)) cmd = ("{cat_cmd} {in_file} | grep -v ^track | grep -v ^browser | grep -v ^@ | " "grep -v ^# | {simple} " "{bcbio_py} -c 'from bcbio.variation import bedutils; bedutils.remove_bad()' | " "{sort_cmd} -k1,1 -k2,2n > {tx_out_file}") do.run(cmd.format(**locals()), "Prepare cleaned BED file", data) vcfutils.bgzip_and_index(out_file, data.get("config", {}), remove_orig=False) return out_file def sort_merge(in_file, data, out_dir=None): """Sort and merge a BED file, collapsing gene names. Output is a 3 or 4 column file (the 4th column values go comma-separated). """ out_file = "%s-sortmerge.bed" % os.path.splitext(in_file)[0] bedtools = config_utils.get_program("bedtools", data, default="bedtools") if out_dir: out_file = os.path.join(out_dir, os.path.basename(out_file)) if not utils.file_uptodate(out_file, in_file): column_opt = "" with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if not line.startswith(("#", "track", "browser", "@")): parts = line.split() if len(parts) >= 4: column_opt = "-c 4 -o distinct" with file_transaction(data, out_file) as tx_out_file: cat_cmd = "zcat" if in_file.endswith(".gz") else "cat" sort_cmd = get_sort_cmd(os.path.dirname(tx_out_file)) cmd = ("{cat_cmd} {in_file} | {sort_cmd} -k1,1 -k2,2n | " "{bedtools} merge -i - {column_opt} > {tx_out_file}") do.run(cmd.format(**locals()), "Sort and merge BED file", data) return out_file def remove_bad(): """Remove non-increasing BED lines which will cause variant callers to choke. Also fixes space separated BED inputs. """ for line in sys.stdin: parts = line.strip().split("\t") if len(parts) == 1 and len(line.strip().split()) > 1: parts = line.strip().split() if line.strip() and len(parts) > 2 and int(parts[2]) > int(parts[1]): sys.stdout.write("\t".join(parts) + "\n") def merge_overlaps(in_file, data, distance=None, out_dir=None): """Merge bed file intervals to avoid overlapping regions. Output is always a 3 column file. Overlapping regions (1:1-100, 1:90-100) cause issues with callers like FreeBayes that don't collapse BEDs prior to using them. """ config = data["config"] if in_file: bedtools = config_utils.get_program("bedtools", config, default="bedtools") work_dir = tz.get_in(["dirs", "work"], data) if out_dir: bedprep_dir = out_dir elif work_dir: bedprep_dir = utils.safe_makedir(os.path.join(work_dir, "bedprep")) else: bedprep_dir = os.path.dirname(in_file) out_file = os.path.join(bedprep_dir, "%s-merged.bed" % (utils.splitext_plus(os.path.basename(in_file))[0])) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: distance = "-d %s" % distance if distance else "" cmd = "{bedtools} merge {distance} -i {in_file} > {tx_out_file}" do.run(cmd.format(**locals()), "Prepare merged BED file", data) vcfutils.bgzip_and_index(out_file, data["config"], remove_orig=False) return out_file def population_variant_regions(items, merged=False): """Retrieve the variant region BED file from a population of items. If tumor/normal, return the tumor BED file. If a population, return the BED file covering the most bases. """ def _get_variant_regions(data): out = dd.get_variant_regions(data) or dd.get_sample_callable(data) # Only need to merge for variant region inputs, not callable BED regions which don't overlap if merged and dd.get_variant_regions(data): merged_out = dd.get_variant_regions_merged(data) if merged_out: out = merged_out else: out = merge_overlaps(out, data) return out import pybedtools if len(items) == 1: return _get_variant_regions(items[0]) else: paired = vcfutils.get_paired(items) if paired: return _get_variant_regions(paired.tumor_data) else: vrs = [] for data in items: vr_bed = _get_variant_regions(data) if vr_bed: vrs.append((pybedtools.BedTool(vr_bed).total_coverage(), vr_bed)) vrs.sort(reverse=True) if vrs: return vrs[0][1] def combine(in_files, out_file, config): """Combine multiple BED files into a single output. """ if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for in_file in in_files: with open(in_file) as in_handle: shutil.copyfileobj(in_handle, out_handle) return out_file def intersect_two(f1, f2, work_dir, data): """Intersect two regions, handling cases where either file is not present. """ bedtools = config_utils.get_program("bedtools", data, default="bedtools") f1_exists = f1 and utils.file_exists(f1) f2_exists = f2 and utils.file_exists(f2) if not f1_exists and not f2_exists: return None elif f1_exists and not f2_exists: return f1 elif f2_exists and not f1_exists: return f2 else: out_file = os.path.join(work_dir, "%s-merged.bed" % (utils.splitext_plus(os.path.basename(f1))[0])) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = "{bedtools} intersect -a {f1} -b {f2} > {tx_out_file}" do.run(cmd.format(**locals()), "Intersect BED files", data) return out_file def get_padded_bed_file(out_dir, bed_file, padding, data): bedtools = config_utils.get_program("bedtools", data, default="bedtools") out_file = os.path.join(out_dir, "%s-padded.bed" % (utils.splitext_plus(os.path.basename(bed_file))[0])) if utils.file_uptodate(out_file, bed_file): return out_file fai_file = ref.fasta_idx(dd.get_ref_file(data)) with file_transaction(data, out_file) as tx_out_file: cmd = "{bedtools} slop -i {bed_file} -g {fai_file} -b {padding} | bedtools merge -i - > {tx_out_file}" do.run(cmd.format(**locals()), "Pad BED file", data) return out_file def subset_to_genome(in_file, out_file, data): """Subset a BED file to only contain contigs present in the reference genome. """ if not utils.file_uptodate(out_file, in_file): contigs = set([x.name for x in ref.file_contigs(dd.get_ref_file(data))]) with utils.open_gzipsafe(in_file) as in_handle: with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for line in in_handle: parts = line.split() if parts and parts[0] in contigs: out_handle.write(line) return out_file bcbio-nextgen-1.2.9/bcbio/variation/cortex.py000066400000000000000000000362111415626112400212040ustar00rootroot00000000000000"""Perform regional de-novo assembly calling with cortex_var. Using a pre-mapped set of reads and BED file of regions, performs de-novo assembly and variant calling against the reference sequence in each region. This avoids whole genome costs while gaining the advantage of de-novo prediction. http://cortexassembler.sourceforge.net/index_cortex_var.html """ from __future__ import print_function import os import glob import subprocess import itertools import shutil import pysam from Bio import Seq from Bio.SeqIO.QualityIO import FastqGeneralIterator from bcbio import bam from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline.shared import subset_variant_regions from bcbio.utils import file_exists, safe_makedir from bcbio.variation import vcfutils def run_cortex(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Top level entry to regional de-novo based variant calling with cortex_var. """ raise NotImplementedError("Cortex currently out of date and needs reworking.") if len(align_bams) == 1: align_bam = align_bams[0] config = items[0]["config"] else: raise NotImplementedError("Need to add multisample calling for cortex_var") if out_file is None: out_file = "%s-cortex.vcf" % os.path.splitext(align_bam)[0] if region is not None: work_dir = safe_makedir(os.path.join(os.path.dirname(out_file), region.replace(".", "_"))) else: work_dir = os.path.dirname(out_file) if not file_exists(out_file): bam.index(align_bam, config) variant_regions = config["algorithm"].get("variant_regions", None) if not variant_regions: raise ValueError("Only support regional variant calling with cortex_var: set variant_regions") target_regions = subset_variant_regions(variant_regions, region, out_file) if os.path.isfile(target_regions): with open(target_regions) as in_handle: regional_vcfs = [_run_cortex_on_region(x.strip().split("\t")[:3], align_bam, ref_file, work_dir, out_file, config) for x in in_handle] combine_file = "{0}-raw{1}".format(*os.path.splitext(out_file)) _combine_variants(regional_vcfs, combine_file, ref_file, config) _select_final_variants(combine_file, out_file, config) else: vcfutils.write_empty_vcf(out_file) return out_file def _passes_cortex_depth(line, min_depth): """Do any genotypes in the cortex_var VCF line passes the minimum depth requirement? """ parts = line.split("\t") cov_index = parts[8].split(":").index("COV") passes_depth = False for gt in parts[9:]: cur_cov = gt.split(":")[cov_index] cur_depth = sum(int(x) for x in cur_cov.split(",")) if cur_depth >= min_depth: passes_depth = True return passes_depth def _select_final_variants(base_vcf, out_vcf, config): """Filter input file, removing items with low depth of support. cortex_var calls are tricky to filter by depth. Count information is in the COV FORMAT field grouped by alleles, so we need to sum up values and compare. """ min_depth = int(config["algorithm"].get("min_depth", 4)) with file_transaction(out_vcf) as tx_out_file: with open(base_vcf) as in_handle: with open(tx_out_file, "w") as out_handle: for line in in_handle: if line.startswith("#"): passes = True else: passes = _passes_cortex_depth(line, min_depth) if passes: out_handle.write(line) return out_vcf def _combine_variants(in_vcfs, out_file, ref_file, config): """Combine variant files, writing the header from the first non-empty input. in_vcfs is a list with each item starting with the chromosome regions, and ending with the input file. We sort by these regions to ensure the output file is in the expected order. """ in_vcfs.sort() wrote_header = False with open(out_file, "w") as out_handle: for in_vcf in (x[-1] for x in in_vcfs): with open(in_vcf) as in_handle: header = list(itertools.takewhile(lambda x: x.startswith("#"), in_handle)) if not header[0].startswith("##fileformat=VCFv4"): raise ValueError("Unexpected VCF file: %s" % in_vcf) for line in in_handle: if not wrote_header: wrote_header = True out_handle.write("".join(header)) out_handle.write(line) if not wrote_header: out_handle.write("".join(header)) return out_file def _run_cortex_on_region(region, align_bam, ref_file, work_dir, out_file_base, config): """Run cortex on a specified chromosome start/end region. """ kmers = [31, 51, 71] min_reads = 1750 cortex_dir = config_utils.get_program("cortex", config, "dir") stampy_dir = config_utils.get_program("stampy", config, "dir") vcftools_dir = config_utils.get_program("vcftools", config, "dir") if cortex_dir is None or stampy_dir is None: raise ValueError("cortex_var requires path to pre-built cortex and stampy") region_str = "{0}-{1}-{2}".format(*region) base_dir = safe_makedir(os.path.join(work_dir, region_str)) try: out_vcf_base = os.path.join(base_dir, "{0}-{1}".format( os.path.splitext(os.path.basename(out_file_base))[0], region_str)) out_file = os.path.join(work_dir, os.path.basename("{0}.vcf".format(out_vcf_base))) if not file_exists(out_file): fastq = _get_fastq_in_region(region, align_bam, out_vcf_base) if _count_fastq_reads(fastq, min_reads) < min_reads: vcfutils.write_empty_vcf(out_file) else: local_ref, genome_size = _get_local_ref(region, ref_file, out_vcf_base) indexes = _index_local_ref(local_ref, cortex_dir, stampy_dir, kmers) cortex_out = _run_cortex(fastq, indexes, {"kmers": kmers, "genome_size": genome_size, "sample": get_sample_name(align_bam)}, out_vcf_base, {"cortex": cortex_dir, "stampy": stampy_dir, "vcftools": vcftools_dir}, config) if cortex_out: _remap_cortex_out(cortex_out, region, out_file) else: vcfutils.write_empty_vcf(out_file) finally: if os.path.exists(base_dir): shutil.rmtree(base_dir) return [region[0], int(region[1]), int(region[2]), out_file] def _remap_cortex_out(cortex_out, region, out_file): """Remap coordinates in local cortex variant calls to the original global region. """ def _remap_vcf_line(line, contig, start): parts = line.split("\t") if parts[0] == "" or parts[1] == "": return None parts[0] = contig try: parts[1] = str(int(parts[1]) + start) except ValueError: raise ValueError("Problem in {0} with \n{1}".format( cortex_out, parts)) return "\t".join(parts) def _not_filtered(line): parts = line.split("\t") return parts[6] == "PASS" contig, start, _ = region start = int(start) with open(cortex_out) as in_handle: with open(out_file, "w") as out_handle: for line in in_handle: if line.startswith("##fileDate"): pass elif line.startswith("#"): out_handle.write(line) elif _not_filtered(line): update_line = _remap_vcf_line(line, contig, start) if update_line: out_handle.write(update_line) def _run_cortex(fastq, indexes, params, out_base, dirs, config): """Run cortex_var run_calls.pl, producing a VCF variant file. """ print(out_base) fastaq_index = "{0}.fastaq_index".format(out_base) se_fastq_index = "{0}.se_fastq".format(out_base) pe_fastq_index = "{0}.pe_fastq".format(out_base) reffasta_index = "{0}.list_ref_fasta".format(out_base) with open(se_fastq_index, "w") as out_handle: out_handle.write(fastq + "\n") with open(pe_fastq_index, "w") as out_handle: out_handle.write("") with open(fastaq_index, "w") as out_handle: out_handle.write("{0}\t{1}\t{2}\t{2}\n".format(params["sample"], se_fastq_index, pe_fastq_index)) with open(reffasta_index, "w") as out_handle: for x in indexes["fasta"]: out_handle.write(x + "\n") os.environ["PERL5LIB"] = "{0}:{1}:{2}".format( os.path.join(dirs["cortex"], "scripts/calling"), os.path.join(dirs["cortex"], "scripts/analyse_variants/bioinf-perl/lib"), os.environ.get("PERL5LIB", "")) kmers = sorted(params["kmers"]) kmer_info = ["--first_kmer", str(kmers[0])] if len(kmers) > 1: kmer_info += ["--last_kmer", str(kmers[-1]), "--kmer_step", str(kmers[1] - kmers[0])] subprocess.check_call(["perl", os.path.join(dirs["cortex"], "scripts", "calling", "run_calls.pl"), "--fastaq_index", fastaq_index, "--auto_cleaning", "yes", "--bc", "yes", "--pd", "yes", "--outdir", os.path.dirname(out_base), "--outvcf", os.path.basename(out_base), "--ploidy", str(config["algorithm"].get("ploidy", 2)), "--stampy_hash", indexes["stampy"], "--stampy_bin", os.path.join(dirs["stampy"], "stampy.py"), "--refbindir", os.path.dirname(indexes["cortex"][0]), "--list_ref_fasta", reffasta_index, "--genome_size", str(params["genome_size"]), "--max_read_len", "30000", #"--max_var_len", "4000", "--format", "FASTQ", "--qthresh", "5", "--do_union", "yes", "--mem_height", "17", "--mem_width", "100", "--ref", "CoordinatesAndInCalling", "--workflow", "independent", "--vcftools_dir", dirs["vcftools"], "--logfile", "{0}.logfile,f".format(out_base)] + kmer_info) final = glob.glob(os.path.join(os.path.dirname(out_base), "vcfs", "{0}*FINALcombined_BC*decomp.vcf".format(os.path.basename(out_base)))) # No calls, need to setup an empty file if len(final) != 1: print("Did not find output VCF file for {0}".format(out_base)) return None else: return final[0] def _get_cortex_binary(kmer, cortex_dir): cortex_bin = None for check_bin in sorted(glob.glob(os.path.join(cortex_dir, "bin", "cortex_var_*"))): kmer_check = int(os.path.basename(check_bin).split("_")[2]) if kmer_check >= kmer: cortex_bin = check_bin break assert cortex_bin is not None, \ "Could not find cortex_var executable in %s for kmer %s" % (cortex_dir, kmer) return cortex_bin def _index_local_ref(fasta_file, cortex_dir, stampy_dir, kmers): """Pre-index a generated local reference sequence with cortex_var and stampy. """ base_out = os.path.splitext(fasta_file)[0] cindexes = [] for kmer in kmers: out_file = "{0}.k{1}.ctx".format(base_out, kmer) if not file_exists(out_file): file_list = "{0}.se_list".format(base_out) with open(file_list, "w") as out_handle: out_handle.write(fasta_file + "\n") subprocess.check_call([_get_cortex_binary(kmer, cortex_dir), "--kmer_size", str(kmer), "--mem_height", "17", "--se_list", file_list, "--format", "FASTA", "--max_read_len", "30000", "--sample_id", base_out, "--dump_binary", out_file]) cindexes.append(out_file) if not file_exists("{0}.stidx".format(base_out)): subprocess.check_call([os.path.join(stampy_dir, "stampy.py"), "-G", base_out, fasta_file]) subprocess.check_call([os.path.join(stampy_dir, "stampy.py"), "-g", base_out, "-H", base_out]) return {"stampy": base_out, "cortex": cindexes, "fasta": [fasta_file]} def _get_local_ref(region, ref_file, out_vcf_base): """Retrieve a local FASTA file corresponding to the specified region. """ out_file = "{0}.fa".format(out_vcf_base) if not file_exists(out_file): with pysam.Fastafile(ref_file) as in_pysam: contig, start, end = region seq = in_pysam.fetch(contig, int(start), int(end)) with open(out_file, "w") as out_handle: out_handle.write(">{0}-{1}-{2}\n{3}".format(contig, start, end, str(seq))) with open(out_file) as in_handle: in_handle.readline() size = len(in_handle.readline().strip()) return out_file, size def _get_fastq_in_region(region, align_bam, out_base): """Retrieve fastq files in region as single end. Paired end is more complicated since pairs can map off the region, so focus on local only assembly since we've previously used paired information for mapping. """ out_file = "{0}.fastq".format(out_base) if not file_exists(out_file): with pysam.Samfile(align_bam, "rb") as in_pysam: with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: contig, start, end = region for read in in_pysam.fetch(contig, int(start), int(end)): seq = Seq.Seq(read.seq) qual = list(read.qual) if read.is_reverse: seq = seq.reverse_complement() qual.reverse() out_handle.write("@{name}\n{seq}\n+\n{qual}\n".format( name=read.qname, seq=str(seq), qual="".join(qual))) return out_file ## Utility functions def _count_fastq_reads(in_fastq, min_reads): """Count the number of fastq reads in a file, stopping after reaching min_reads. """ with open(in_fastq) as in_handle: items = list(itertools.takewhile(lambda i : i <= min_reads, (i for i, _ in enumerate(FastqGeneralIterator(in_handle))))) return len(items) def get_sample_name(align_bam): with pysam.Samfile(align_bam, "rb") as in_pysam: if "RG" in in_pysam.header: return in_pysam.header["RG"][0]["SM"] bcbio-nextgen-1.2.9/bcbio/variation/coverage.py000066400000000000000000000325161415626112400214770ustar00rootroot00000000000000"""Examine and query coverage in sequencing experiments. Provides estimates of coverage intervals based on callable regions """ import collections import itertools import os import shutil import yaml import pybedtools import numpy as np import pysam import toolz as tz from bcbio import bam, utils from bcbio.bam import ref, readstats from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.pipeline import shared from bcbio.variation import bedutils from bcbio.pipeline import config_utils GENOME_COV_THRESH = 0.40 # percent of genome covered for whole genome analysis OFFTARGET_THRESH = 0.01 # percent of offtarget reads required to be capture (not amplification) based DEPTH_THRESHOLDS = [1,5] + sorted([k*10**exp10 for k in [1,2,5] for exp10 in range(1,6)]) # 10,20,50,100... def assign_interval(data): """Identify coverage based on percent of genome covered and relation to targets. Classifies coverage into 3 categories: - genome: Full genome coverage - regional: Regional coverage, like exome capture, with off-target reads - amplicon: Amplication based regional coverage without off-target reads """ if not dd.get_coverage_interval(data): vrs = dd.get_variant_regions_merged(data) callable_file = dd.get_sample_callable(data) if vrs: callable_size = pybedtools.BedTool(vrs).total_coverage() else: callable_size = pybedtools.BedTool(callable_file).total_coverage() total_size = sum([c.size for c in ref.file_contigs(dd.get_ref_file(data), data["config"])]) genome_cov_pct = callable_size / float(total_size) if genome_cov_pct > GENOME_COV_THRESH: cov_interval = "genome" offtarget_pct = 0.0 elif not vrs: cov_interval = "regional" offtarget_pct = 0.0 else: offtarget_pct = _count_offtarget(data, dd.get_align_bam(data) or dd.get_work_bam(data), vrs or callable_file, "variant_regions") if offtarget_pct > OFFTARGET_THRESH: cov_interval = "regional" else: cov_interval = "amplicon" logger.info("%s: Assigned coverage as '%s' with %.1f%% genome coverage and %.1f%% offtarget coverage" % (dd.get_sample_name(data), cov_interval, genome_cov_pct * 100.0, offtarget_pct * 100.0)) data["config"]["algorithm"]["coverage_interval"] = cov_interval return data def _count_offtarget(data, bam_file, bed_file, target_name): mapped_unique = readstats.number_of_mapped_reads(data, bam_file, keep_dups=False) ontarget = readstats.number_of_mapped_reads( data, bam_file, keep_dups=False, bed_file=bed_file, target_name=target_name) if mapped_unique: return float(mapped_unique - ontarget) / mapped_unique else: return 0.0 def calculate(bam_file, data, sv_bed): """Calculate coverage in parallel using mosdepth. Removes duplicates and secondary reads from the counts: if ( b->core.flag & (BAM_FUNMAP | BAM_FSECONDARY | BAM_FQCFAIL | BAM_FDUP) ) continue; """ params = {"min": dd.get_coverage_depth_min(data)} variant_regions = dd.get_variant_regions_merged(data) if not variant_regions: variant_regions = _create_genome_regions(data) # Back compatible with previous pre-mosdepth callable files callable_file = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data))), "%s-coverage.callable.bed" % (dd.get_sample_name(data))) if not utils.file_uptodate(callable_file, bam_file): vr_quantize = ("0:1:%s:" % (params["min"]), ["NO_COVERAGE", "LOW_COVERAGE", "CALLABLE"]) to_calculate = [("variant_regions", variant_regions, vr_quantize, None, "coverage_perbase" in dd.get_tools_on(data)), ("sv_regions", bedutils.clean_file(sv_bed, data, prefix="svregions-"), None, None, False), ("coverage", bedutils.clean_file(dd.get_coverage(data), data, prefix="cov-"), None, DEPTH_THRESHOLDS, False)] depth_files = {} for target_name, region_bed, quantize, thresholds, per_base in to_calculate: if region_bed: cur_depth = {} depth_info = run_mosdepth(data, target_name, region_bed, quantize=quantize, thresholds=thresholds, per_base=per_base) for attr in ("dist", "regions", "thresholds", "per_base"): val = getattr(depth_info, attr, None) if val: cur_depth[attr] = val depth_files[target_name] = cur_depth if target_name == "variant_regions": callable_file = depth_info.quantize else: depth_files = {} final_callable = _subset_to_variant_regions(callable_file, variant_regions, data) return final_callable, depth_files def _create_genome_regions(data): """Create whole genome contigs we want to process, only non-alts. Skips problem contigs like HLAs for downstream analysis. """ work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "coverage", dd.get_sample_name(data))) variant_regions = os.path.join(work_dir, "target-genome.bed") with file_transaction(data, variant_regions) as tx_variant_regions: with open(tx_variant_regions, "w") as out_handle: for c in shared.get_noalt_contigs(data): out_handle.write("%s\t%s\t%s\n" % (c.name, 0, c.size)) return variant_regions def _subset_to_variant_regions(callable_file, variant_regions, data): """Subset output callable file to only variant regions of interest. """ out_file = "%s-vrsubset.bed" % utils.splitext_plus(callable_file)[0] if not utils.file_uptodate(out_file, callable_file): with file_transaction(data, out_file) as tx_out_file: with utils.open_gzipsafe(callable_file) as in_handle: pybedtools.BedTool(in_handle).intersect(variant_regions).saveas(tx_out_file) return out_file def _get_cache_file(data, target_name): prefix = os.path.join( utils.safe_makedir(os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data))), "%s-coverage" % (dd.get_sample_name(data))) cache_file = prefix + "-" + target_name + "-stats.yaml" return cache_file def _read_cache(cache_file, reuse_cmp_files): reuse_cmp_file = [fn for fn in reuse_cmp_files if fn] if all(utils.file_uptodate(cache_file, fn) for fn in reuse_cmp_file): with open(cache_file) as in_handle: return yaml.safe_load(in_handle) return dict() def _write_cache(cache, cache_file): with open(cache_file, "w") as out_handle: yaml.safe_dump(cache, out_handle, default_flow_style=False, allow_unicode=False) def get_average_coverage(target_name, bed_file, data, bam_file=None): if not bam_file: bam_file = dd.get_align_bam(data) or dd.get_work_bam(data) cache_file = _get_cache_file(data, target_name) if dd.get_disambiguate(data): cache = _read_cache(cache_file, [bed_file]) else: cache = _read_cache(cache_file, [bam_file, bed_file]) if "avg_coverage" in cache: return int(cache["avg_coverage"]) if bed_file: avg_cov = _average_bed_coverage(bed_file, target_name, data) else: avg_cov = _average_genome_coverage(data, bam_file) cache["avg_coverage"] = int(avg_cov) _write_cache(cache, cache_file) return int(avg_cov) def _average_genome_coverage(data, bam_file): """Quickly calculate average coverage for whole genome files using indices. Includes all reads, with duplicates. Uses sampling of 10M reads. """ total = sum([c.size for c in ref.file_contigs(dd.get_ref_file(data), data["config"])]) read_counts = sum(x.aligned for x in bam.idxstats(bam_file, data)) with pysam.Samfile(bam_file, "rb") as pysam_bam: read_size = np.median(list(itertools.islice((a.query_length for a in pysam_bam.fetch()), int(1e7)))) avg_cov = float(read_counts * read_size) / total return avg_cov def _average_bed_coverage(bed_file, target_name, data): depth_file = regions_coverage(bed_file, target_name, data) avg_covs = [] total_len = 0 with utils.open_gzipsafe(depth_file) as fh: for line_tokens in (l.rstrip().split() for l in fh if not l.startswith("#")): line_tokens = [x for x in line_tokens if x.strip()] start, end = map(int, line_tokens[1:3]) size = end - start avg_covs.append(float(line_tokens[-1]) * size) total_len += size avg_cov = sum(avg_covs) / total_len if total_len > 0 else 0 return avg_cov def regions_coverage(bed_file, target_name, data): """Generate coverage over regions of interest using mosdepth. """ ready_bed = tz.get_in(["depth", target_name, "regions"], data) if ready_bed: return ready_bed else: return run_mosdepth(data, target_name, bed_file).regions def run_mosdepth(data, target_name, bed_file, per_base=False, quantize=None, thresholds=None): """Run mosdepth generating distribution, region depth and per-base depth. """ MosdepthCov = collections.namedtuple("MosdepthCov", ("dist", "per_base", "regions", "quantize", "thresholds")) bam_file = dd.get_align_bam(data) or dd.get_work_bam(data) work_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "coverage", dd.get_sample_name(data))) prefix = os.path.join(work_dir, "%s-%s" % (dd.get_sample_name(data), target_name)) old_dist_file = "%s.mosdepth.dist.txt" % (prefix) out = MosdepthCov((old_dist_file if utils.file_uptodate(old_dist_file, bam_file) else "%s.mosdepth.%s.dist.txt" % (prefix, "region" if bed_file else "global")), ("%s.per-base.bed.gz" % prefix) if per_base else None, ("%s.regions.bed.gz" % prefix) if bed_file else None, ("%s.quantized.bed.gz" % prefix) if quantize else None, ("%s.thresholds.bed.gz" % prefix) if thresholds else None) if not utils.file_uptodate(out.dist, bam_file): bam.index(bam_file, dd.get_config(data)) with file_transaction(data, out.dist) as tx_out_file: tx_prefix = os.path.join(os.path.dirname(tx_out_file), os.path.basename(prefix)) num_cores = dd.get_cores(data) bed_arg = ("--by %s" % bed_file) if bed_file else "" perbase_arg = "" if per_base else "--no-per-base" mapq_arg = "-Q 1" if (per_base or quantize) else "" if quantize: quant_arg = "--quantize %s" % quantize[0] quant_export = " && ".join(["export MOSDEPTH_Q%s=%s" % (i, x) for (i, x) in enumerate(quantize[1])]) quant_export += " && " else: quant_arg, quant_export = "", "" thresholds_cmdl = ("-T " + ",".join([str(t) for t in thresholds])) if out.thresholds else "" mosdepth = config_utils.get_program("mosdepth", data) cmd = ("{quant_export}{mosdepth} -t {num_cores} -F 1804 {mapq_arg} {perbase_arg} {bed_arg} {quant_arg} " "{tx_prefix} {bam_file} {thresholds_cmdl}") message = "Calculating coverage: %s %s" % (dd.get_sample_name(data), target_name) do.run(cmd.format(**locals()), message.format(**locals())) if out.per_base: shutil.move(os.path.join(os.path.dirname(tx_out_file), os.path.basename(out.per_base)), out.per_base) if out.regions: shutil.move(os.path.join(os.path.dirname(tx_out_file), os.path.basename(out.regions)), out.regions) if out.quantize: shutil.move(os.path.join(os.path.dirname(tx_out_file), os.path.basename(out.quantize)), out.quantize) if out.thresholds: shutil.move(os.path.join(os.path.dirname(tx_out_file), os.path.basename(out.thresholds)), out.thresholds) return out def coverage_region_detailed_stats(target_name, bed_file, data, out_dir): """ Calculate coverage at different completeness cutoff for region in coverage option. """ if bed_file and utils.file_exists(bed_file): ready_depth = tz.get_in(["depth", target_name], data) if ready_depth: cov_file = ready_depth["regions"] dist_file = ready_depth["dist"] thresholds_file = ready_depth.get("thresholds") out_cov_file = os.path.join(out_dir, os.path.basename(cov_file)) out_dist_file = os.path.join(out_dir, os.path.basename(dist_file)) out_thresholds_file = os.path.join(out_dir, os.path.basename(thresholds_file)) \ if thresholds_file and os.path.isfile(thresholds_file) else None if not utils.file_uptodate(out_cov_file, cov_file): utils.copy_plus(cov_file, out_cov_file) utils.copy_plus(dist_file, out_dist_file) utils.copy_plus(thresholds_file, out_thresholds_file) if out_thresholds_file else None return [out_cov_file, out_dist_file] + ([out_thresholds_file] if out_thresholds_file else []) return [] bcbio-nextgen-1.2.9/bcbio/variation/damage.py000066400000000000000000000105611415626112400211160ustar00rootroot00000000000000"""Annotate with potential DNA damage artifacts by examining strand/read bias. Uses DKFZBiasFilter to identify strand and PCR bias and converts these into INFO level annotations of low frequency variants: https://github.com/bcbio/bcbio.github.io/blob/master/_posts/2017-01-31-damage-filters.md """ import io import os import shutil from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.variation import vcfutils def run_filter(vrn_file, align_bam, ref_file, data, items): """Filter and annotate somatic VCFs with damage/bias artifacts on low frequency variants. Moves damage estimation to INFO field, instead of leaving in FILTER. """ # can't parse octopus.vcf caller = vrn_file.split("/")[-2] if caller and caller == "octopus": return data if not should_filter(items) or not vcfutils.vcf_has_variants(vrn_file): return data else: raw_file = "%s-damage.vcf" % utils.splitext_plus(vrn_file)[0] out_plot_files = ["%s%s" % (utils.splitext_plus(raw_file)[0], ext) for ext in ["_seq_bias_simplified.pdf", "_pcr_bias_simplified.pdf"]] if not utils.file_uptodate(raw_file, vrn_file) and not utils.file_uptodate(raw_file + ".gz", vrn_file): with file_transaction(items[0], raw_file) as tx_out_file: # Does not apply --qcSummary plotting due to slow runtimes dkfzbiasfilter = utils.which(config_utils.get_program("dkfzbiasfilter.py", data)) cmd = [dkfzbiasfilter, "--filterCycles", "1", "--passOnly", "--tempFolder", os.path.dirname(tx_out_file), vrn_file, align_bam, ref_file, tx_out_file] do.run(cmd, "Filter low frequency variants for DNA damage and strand bias") for out_plot in out_plot_files: tx_plot_file = os.path.join("%s_qcSummary" % utils.splitext_plus(tx_out_file)[0], "plots", os.path.basename(out_plot)) if utils.file_exists(tx_plot_file): shutil.move(tx_plot_file, out_plot) raw_file = vcfutils.bgzip_and_index(raw_file, items[0]["config"]) data["vrn_file"] = _filter_to_info(raw_file, items[0]) out_plot_files = [x for x in out_plot_files if utils.file_exists(x)] data["damage_plots"] = out_plot_files return data def _filter_to_info(in_file, data): """Move DKFZ filter information into INFO field. """ header = ("""##INFO=\n""") out_file = "%s-ann.vcf" % utils.splitext_plus(in_file)[0] if not utils.file_uptodate(out_file, in_file) and not utils.file_uptodate(out_file + ".gz", in_file): with file_transaction(data, out_file) as tx_out_file: with utils.open_gzipsafe(in_file) as in_handle: with io.open(tx_out_file, "w", encoding="utf-8") as out_handle: for line in in_handle: if line.startswith("#CHROM"): out_handle.write(header + line) elif line.startswith("#"): out_handle.write(line) else: out_handle.write(_rec_filter_to_info(line)) return vcfutils.bgzip_and_index(out_file, data["config"]) def _rec_filter_to_info(line): """Move a DKFZBias filter to the INFO field, for a record. """ parts = line.rstrip().split("\t") move_filters = {"bSeq": "strand", "bPcr": "damage"} new_filters = [] bias_info = [] for f in parts[6].split(";"): if f in move_filters: bias_info.append(move_filters[f]) elif f not in ["."]: new_filters.append(f) if bias_info: parts[7] += ";DKFZBias=%s" % ",".join(bias_info) parts[6] = ";".join(new_filters or ["PASS"]) return "\t".join(parts) + "\n" def should_filter(items): """Check if we should do damage filtering on somatic calling with low frequency events. """ return (vcfutils.get_paired(items) is not None and any("damage_filter" in dd.get_tools_on(d) for d in items)) bcbio-nextgen-1.2.9/bcbio/variation/deepvariant.py000066400000000000000000000101241415626112400221750ustar00rootroot00000000000000"""DeepVariant calling: https://github.com/google/deepvariant """ import os import glob from bcbio import utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import strelka2, vcfutils def run(align_bams, items, ref_file, assoc_files, region, out_file): """Return DeepVariant calling on germline samples. region can be a single region or list of multiple regions for multicore calling. """ assert not vcfutils.is_paired_analysis(align_bams, items), \ ("DeepVariant currently only supports germline calling: %s" % (", ".join([dd.get_sample_name(d) for d in items]))) assert len(items) == 1, \ ("DeepVariant currently only supports single sample calling: %s" % (", ".join([dd.get_sample_name(d) for d in items]))) out_file = _run_germline(align_bams[0], items[0], ref_file, region, out_file) return vcfutils.bgzip_and_index(out_file, items[0]["config"]) def _run_germline(bam_file, data, ref_file, region, out_file): """Single sample germline variant calling. """ work_dir = utils.safe_makedir("%s-work" % utils.splitext_plus(out_file)[0]) region_bed = strelka2.get_region_bed(region, [data], out_file, want_gzip=False) example_dir = _make_examples(bam_file, data, ref_file, region_bed, out_file, work_dir) if _has_candidate_variants(example_dir): tfrecord_file = _call_variants(example_dir, region_bed, data, out_file) return _postprocess_variants(tfrecord_file, data, ref_file, out_file) else: return vcfutils.write_empty_vcf(out_file, data["config"], [dd.get_sample_name(data)]) def _has_candidate_variants(example_dir): return all(utils.is_empty_gzipsafe(f) for f in glob.glob(os.path.join(example_dir, "*tfrecord*gz"))) def _make_examples(bam_file, data, ref_file, region_bed, out_file, work_dir): """Create example pileup images to feed into variant calling. """ log_dir = utils.safe_makedir(os.path.join(work_dir, "log")) example_dir = utils.safe_makedir(os.path.join(work_dir, "examples")) if len(glob.glob(os.path.join(example_dir, "%s.tfrecord*.gz" % dd.get_sample_name(data)))) == 0: with tx_tmpdir(data) as tx_example_dir: cmd = ["dv_make_examples.py", "--cores", dd.get_num_cores(data), "--ref", ref_file, "--reads", bam_file, "--regions", region_bed, "--logdir", log_dir, "--examples", tx_example_dir, "--sample", dd.get_sample_name(data)] do.run(cmd, "DeepVariant make_examples %s" % dd.get_sample_name(data)) for fname in glob.glob(os.path.join(tx_example_dir, "%s.tfrecord*.gz" % dd.get_sample_name(data))): utils.copy_plus(fname, os.path.join(example_dir, os.path.basename(fname))) return example_dir def _call_variants(example_dir, region_bed, data, out_file): """Call variants from prepared pileup examples, creating tensorflow record file. """ tf_out_file = "%s-tfrecord.gz" % utils.splitext_plus(out_file)[0] if not utils.file_exists(tf_out_file): with file_transaction(data, tf_out_file) as tx_out_file: model = "wes" if strelka2.coverage_interval_from_bed(region_bed) == "targeted" else "wgs" cmd = ["dv_call_variants.py", "--cores", dd.get_num_cores(data), "--outfile", tx_out_file, "--examples", example_dir, "--sample", dd.get_sample_name(data), "--model", model] do.run(cmd, "DeepVariant call_variants %s" % dd.get_sample_name(data)) return tf_out_file def _postprocess_variants(record_file, data, ref_file, out_file): """Post-process variants, converting into standard VCF file. """ if not utils.file_uptodate(out_file, record_file): with file_transaction(data, out_file) as tx_out_file: cmd = ["dv_postprocess_variants.py", "--ref", ref_file, "--infile", record_file, "--outfile", tx_out_file] do.run(cmd, "DeepVariant postprocess_variants %s" % dd.get_sample_name(data)) return out_file bcbio-nextgen-1.2.9/bcbio/variation/effects.py000066400000000000000000000531701415626112400213220ustar00rootroot00000000000000"""Calculate potential effects of variations using external programs. Supported: snpEff: http://sourceforge.net/projects/snpeff/ VEP: http://www.ensembl.org/info/docs/tools/vep/index.html """ import os import glob import shutil import subprocess import string import six import toolz as tz import yaml from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils, tools from bcbio.pipeline import datadict as dd from bcbio.provenance import do, programs from bcbio.variation import vcfutils, vcfanno # ## High level def add_to_vcf(in_file, data, effect_todo=None): if effect_todo is None: effect_todo = get_type(data) if effect_todo: stats = None if effect_todo == "snpeff": ann_vrn_file, stats_files = snpeff_effects(in_file, data) if stats_files: stats = {} for key, val in zip(["effects-stats", "effects-stats-csv"], stats_files): if utils.file_exists(val): stats[key] = val elif effect_todo == "vep": ann_vrn_file = run_vep(in_file, data) else: raise ValueError("Unexpected variant effects configuration: %s" % effect_todo) if ann_vrn_file: return ann_vrn_file, stats return None, None def get_type(data): """Retrieve the type of effects calculation to do. """ if data["analysis"].lower().startswith("var") or dd.get_variantcaller(data): etype = tz.get_in(("config", "algorithm", "effects"), data, "snpeff") if isinstance(etype, (list, tuple)): if len(etype) == 1: return etype[0] else: raise ValueError("Unexpected variant effect type for %s: %s" % (dd.get_sample_name(data), etype)) else: return etype # ## Ensembl VEP def _special_dbkey_maps(dbkey, ref_file): """Avoid duplicate VEP information for databases with chromosome differences like hg19/GRCh37. """ remaps = {"hg19": "GRCh37", "hg38-noalt": "hg38"} if dbkey in remaps: base_dir = os.path.normpath(os.path.join(os.path.dirname(ref_file), os.pardir)) vep_dir = os.path.normpath(os.path.join(base_dir, "vep")) other_dir = os.path.relpath(os.path.normpath(os.path.join(base_dir, os.pardir, remaps[dbkey], "vep")), base_dir) if os.path.exists(os.path.join(base_dir, other_dir)): if not os.path.lexists(vep_dir): os.symlink(other_dir, vep_dir) return vep_dir else: return None else: return None def prep_vep_cache(dbkey, ref_file, tooldir=None, config=None): """VEP cache installation. Called from bcbio/install.py """ if config is None: config = {} resource_file = os.path.join(os.path.dirname(ref_file), "%s-resources.yaml" % dbkey) if os.path.exists(resource_file): with open(resource_file) as in_handle: resources = yaml.safe_load(in_handle) ensembl_name = tz.get_in(["aliases", "ensembl"], resources) symlink_dir = _special_dbkey_maps(dbkey, ref_file) if ensembl_name and ensembl_name.find("_vep_") == -1: raise ValueError("%s has ensembl an incorrect value." "It should have _vep_ in the name." "Remove line or fix the name to avoid error.") if symlink_dir and ensembl_name: species, vepv = ensembl_name.split("_vep_") return symlink_dir, species elif ensembl_name: species, vepv = ensembl_name.split("_vep_") vep_dir = utils.safe_makedir(os.path.normpath(os.path.join( os.path.dirname(os.path.dirname(ref_file)), "vep"))) out_dir = os.path.join(vep_dir, species, vepv) if not os.path.exists(out_dir): tmp_dir = utils.safe_makedir(os.path.join(vep_dir, species, "txtmp")) eversion = vepv.split("_")[0] if int(eversion) >= 98: vep_url_string = "indexed_vep_cache" elif int(eversion) == 97: vep_url_string = "vep" else: vep_url_string = "VEP" url = "http://ftp.ensembl.org/pub/release-%s/variation/%s/%s.tar.gz" % (eversion, vep_url_string, ensembl_name) with utils.chdir(tmp_dir): subprocess.check_call(["wget", "--no-check-certificate", "-c", url]) vep_path = "%s/bin/" % tooldir if tooldir else "" perl_exports = utils.get_perl_exports() cmd = ["%svep_install" % vep_path, "-a", "c", "-s", ensembl_name, "-c", vep_dir, "-u", tmp_dir, "--NO_UPDATE", "--VERSION", eversion] do.run("%s && %s" % (perl_exports, " ".join(cmd)), "Prepare VEP directory for %s" % ensembl_name) cmd = ["%svep_convert_cache" % vep_path, "--species", species, "--version", vepv, "--dir", vep_dir, "--force_overwrite", "--remove"] do.run("%s && %s" % (perl_exports, " ".join(cmd)), "Convert VEP cache to tabix %s" % ensembl_name) for tmp_fname in os.listdir(tmp_dir): os.remove(os.path.join(tmp_dir, tmp_fname)) os.rmdir(tmp_dir) tmp_dir = os.path.join(vep_dir, "tmp") if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir) return vep_dir, species return None, None def get_vep_cache(dbkey, ref_file, tooldir=None, config=None): """ don't install VEP cache when running bcbio, just return its location """ if config is None: config = {} resource_file = os.path.join(os.path.dirname(ref_file), "%s-resources.yaml" % dbkey) if os.path.exists(resource_file): with open(resource_file) as in_handle: resources = yaml.safe_load(in_handle) ensembl_name = tz.get_in(["aliases", "ensembl"], resources) symlink_dir = _special_dbkey_maps(dbkey, ref_file) if symlink_dir and ensembl_name: species, vepv = ensembl_name.split("_vep_") return symlink_dir, species elif ensembl_name: species, vepv = ensembl_name.split("_vep_") vep_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.dirname(ref_file)), "vep")) return vep_dir, species return None, None def run_vep(in_file, data): """Annotate input VCF file with Ensembl variant effect predictor. """ if not vcfutils.vcf_has_variants(in_file): return None out_file = utils.append_stem(in_file, "-vepeffects") assert in_file.endswith(".gz") and out_file.endswith(".gz") if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: vep_dir, ensembl_name = get_vep_cache(data["genome_build"], tz.get_in(["reference", "fasta", "base"], data)) if vep_dir: cores = tz.get_in(("config", "algorithm", "num_cores"), data, 1) fork_args = ["--fork", str(cores)] if cores > 1 else [] vep = config_utils.get_program("vep", data["config"]) # HGVS requires a bgzip compressed, faidx indexed input file or is unusable slow if dd.get_ref_file_compressed(data): hgvs_compatible = True config_args = ["--fasta", dd.get_ref_file_compressed(data)] else: hgvs_compatible = False config_args = ["--fasta", dd.get_ref_file(data)] if vcfanno.is_human(data): plugin_fns = {"loftee": _get_loftee, "maxentscan": _get_maxentscan, "genesplicer": _get_genesplicer, "spliceregion": _get_spliceregion, "G2P": _get_G2P} plugins = ["loftee", "G2P"] if "vep_splicesite_annotations" in dd.get_tools_on(data): # "genesplicer" too unstable so currently removed plugins += ["maxentscan", "spliceregion"] for plugin in plugins: plugin_args = plugin_fns[plugin](data) config_args += plugin_args config_args += ["--sift", "b", "--polyphen", "b", "--humdiv"] if hgvs_compatible: config_args += ["--hgvsg", "--hgvs", "--shift_hgvs", "1"] if (dd.get_effects_transcripts(data).startswith("canonical") or tz.get_in(("config", "algorithm", "clinical_reporting"), data)): config_args += ["--most_severe"] else: config_args += ["--flag_pick_allele_gene", "--appris", "--biotype", "--canonical", "--ccds", "--domains", "--numbers", "--protein", "--symbol", "--tsl", "--uniprot"] if ensembl_name.endswith("_merged"): config_args += ["--merged"] ensembl_name = ensembl_name.replace("_merged", "") resources = config_utils.get_resources("vep", data["config"]) extra_args = [str(x) for x in resources.get("options", [])] cmd = [vep, "--vcf", "-o", "stdout", "-i", in_file] + fork_args + extra_args + \ ["--species", ensembl_name, "--no_stats", "--cache", "--offline", "--dir", vep_dir, "--total_length", "--gene_phenotype", "--regulatory", "--af", "--max_af", "--af_1kg", "--af_esp", "--af_gnomad", "--pubmed", "--variant_class", "--allele_number"] + config_args perl_exports = utils.get_perl_exports() # Remove empty fields (';;') which can cause parsing errors downstream cmd = "%s && %s | sed '/^#/! s/;;/;/g' | bgzip -c > %s" % (perl_exports, " ".join(cmd), tx_out_file) do.run(cmd, "Ensembl variant effect predictor", data) if utils.file_exists(out_file): return vcfutils.bgzip_and_index(out_file, data["config"]) def _get_loftee(data): """Retrieve loss of function plugin parameters for LOFTEE. https://github.com/konradjk/loftee """ ancestral_file = tz.get_in(("genome_resources", "variation", "ancestral"), data) if not ancestral_file or not os.path.exists(ancestral_file): ancestral_file = "false" vep = config_utils.get_program("vep", data["config"]) args = ["--plugin", "LoF,human_ancestor_fa:%s,loftee_path:%s" % (ancestral_file, os.path.dirname(os.path.realpath(vep)))] return args def _get_maxentscan(data): """ The plugin executes the logic from one of the scripts depending on which splice region the variant overlaps: score5.pl : last 3 bases of exon --> first 6 bases of intron score3.pl : last 20 bases of intron --> first 3 bases of exon The plugin reports the reference, alternate and difference (REF - ALT) maximumentropy scores. https://github.com/Ensembl/VEP_plugins/blob/master/MaxEntScan.pm """ maxentscan_dir = os.path.dirname(os.path.realpath(config_utils.get_program("maxentscan_score3.pl", data["config"]))) if maxentscan_dir and os.path.exists(maxentscan_dir): return ["--plugin", "MaxEntScan,%s" % (maxentscan_dir)] else: return [] def _get_genesplicer(data): """ This is a plugin for the Ensembl Variant Effect Predictor (VEP) that runs GeneSplicer (https://ccb.jhu.edu/software/genesplicer/) to get splice site predictions. https://github.com/Ensembl/VEP_plugins/blob/master/GeneSplicer.pm """ genesplicer_exec = os.path.realpath(config_utils.get_program("genesplicer", data["config"])) genesplicer_training = tz.get_in(("genome_resources", "variation", "genesplicer"), data) if (genesplicer_exec and os.path.exists(genesplicer_exec) and genesplicer_training and os.path.exists(genesplicer_training)): return ["--plugin", "GeneSplicer,%s,%s" % (genesplicer_exec, genesplicer_training)] else: return [] def _get_spliceregion(data): """ This is a plugin for the Ensembl Variant Effect Predictor (VEP) that provides more granular predictions of splicing effects. Three additional terms may be added: # splice_donor_5th_base_variant : variant falls in the 5th base after the splice donor junction (5' end of intron) # splice_donor_region_variant : variant falls in region between 3rd and 6th base after splice junction (5' end of intron) # splice_polypyrimidine_tract_variant : variant falls in polypyrimidine tract at 3' end of intron, between 17 and 3 bases from the end https://github.com/Ensembl/VEP_plugins/blob/release/89/SpliceRegion.pm """ return ["--plugin", "SpliceRegion"] def _get_G2P(data): """ A VEP plugin that uses G2P allelic requirements to assess variants in genes for potential phenotype involvement. """ G2P_file = os.path.realpath(tz.get_in(("genome_resources", "variation", "genotype2phenotype"), data)) args = ["--plugin", "G2P,file:%s" % (G2P_file)] if G2P_file: return args else: return [] # ## snpEff variant effects def snpeff_version(args=None, data=None): raw_version = programs.get_version_manifest("snpeff", data=data) if not raw_version: raw_version = "" snpeff_version = "".join([x for x in str(raw_version) if x in set(string.digits + ".")]) # Only return major version (4.3 not 4.3.1) which maps to databases snpeff_version = ".".join(snpeff_version.split(".")[:2]) return snpeff_version def snpeff_effects(vcf_in, data): """Annotate input VCF file with effects calculated by snpEff. """ if vcfutils.vcf_has_variants(vcf_in): return _run_snpeff(vcf_in, "vcf", data) else: return None, None def _snpeff_args_from_config(data): """Retrieve snpEff arguments supplied through input configuration. """ config = data["config"] args = ["-hgvs"] # General supplied arguments resources = config_utils.get_resources("snpeff", config) if resources.get("options"): args += [str(x) for x in resources.get("options", [])] # cancer specific calling arguments if vcfutils.get_paired_phenotype(data): args += ["-cancer"] effects_transcripts = dd.get_effects_transcripts(data) if effects_transcripts in set(["canonical_cancer"]): _, snpeff_base_dir = get_db(data) canon_list_file = os.path.join(snpeff_base_dir, "transcripts", "%s.txt" % effects_transcripts) if not utils.file_exists(canon_list_file): raise ValueError("Cannot find expected file for effects_transcripts: %s" % canon_list_file) args += ["-canonList", canon_list_file] elif effects_transcripts == "canonical" or tz.get_in(("config", "algorithm", "clinical_reporting"), data): args += ["-canon"] return args def get_db(data): """Retrieve a snpEff database name and location relative to reference file. """ snpeff_db = utils.get_in(data, ("genome_resources", "aliases", "snpeff")) snpeff_base_dir = None if snpeff_db: snpeff_base_dir = utils.get_in(data, ("reference", "snpeff")) if not (isinstance(snpeff_base_dir, six.string_types) and os.path.isdir(snpeff_base_dir)): snpeff_base_dir = utils.get_in(data, ("reference", "snpeff", snpeff_db)) if not snpeff_base_dir: # We need to mask '.' characters for CWL/WDL processing, check for them here snpeff_base_dir = utils.get_in(data, ("reference", "snpeff", snpeff_db.replace(".", "_"))) if snpeff_base_dir: snpeff_db = snpeff_db.replace("_", ".") if isinstance(snpeff_base_dir, dict) and snpeff_base_dir.get("base"): snpeff_base_dir = snpeff_base_dir["base"] if (snpeff_base_dir and isinstance(snpeff_base_dir, six.string_types) and os.path.isfile(snpeff_base_dir)): snpeff_base_dir = os.path.dirname(snpeff_base_dir) if (snpeff_base_dir and isinstance(snpeff_base_dir, six.string_types) and snpeff_base_dir.endswith("%s%s" % (os.path.sep, snpeff_db))): snpeff_base_dir = os.path.dirname(snpeff_base_dir) if not snpeff_base_dir: ref_file = utils.get_in(data, ("reference", "fasta", "base")) snpeff_base_dir = utils.safe_makedir(os.path.normpath(os.path.join( os.path.dirname(os.path.dirname(ref_file)), "snpeff"))) # back compatible retrieval of genome from installation directory if "config" in data and not os.path.exists(os.path.join(snpeff_base_dir, snpeff_db)): snpeff_base_dir, snpeff_db = _installed_snpeff_genome(snpeff_db, data["config"]) if snpeff_base_dir.endswith("/%s" % snpeff_db): snpeff_base_dir = os.path.dirname(snpeff_base_dir) return snpeff_db, snpeff_base_dir def get_snpeff_files(data): try: snpeff_db, datadir = get_db(data) except ValueError: snpeff_db = None if snpeff_db: # Clean problem characters for CWL/WDL representation clean_snpeff_db = snpeff_db.replace(".", "_") snpeff_files = glob.glob(os.path.join(datadir, snpeff_db, "*")) if len(snpeff_files) > 0: base_files = [x for x in snpeff_files if x.endswith("/snpEffectPredictor.bin")] assert len(base_files) == 1, base_files del snpeff_files[snpeff_files.index(base_files[0])] return {"base": base_files[0], "indexes": snpeff_files} else: return {} def _get_snpeff_cmd(cmd_name, datadir, data, out_file): """Retrieve snpEff base command line. """ resources = config_utils.get_resources("snpeff", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx3g"]) # scale by cores, defaulting to 2x base usage to ensure we have enough memory # for single core runs to use with human genomes. # Sets a maximum amount of memory to avoid core dumps exceeding 32Gb # We shouldn't need that much memory for snpEff, so avoid issues # https://www.elastic.co/guide/en/elasticsearch/guide/current/heap-sizing.html#compressed_oops jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": {"direction": "increase", "maximum": "30000M", "magnitude": max(2, dd.get_cores(data))}}}) memory = " ".join(jvm_opts) snpeff = config_utils.get_program("snpEff", data["config"]) java_args = "-Djava.io.tmpdir=%s" % utils.safe_makedir(os.path.join(os.path.dirname(out_file), "tmp")) export = "unset JAVA_HOME && export PATH=%s:\"$PATH\" && " % (utils.get_java_binpath()) cmd = "{export} {snpeff} {memory} {java_args} {cmd_name} -dataDir {datadir}" return cmd.format(**locals()) def _run_snpeff(snp_in, out_format, data): """Run effects prediction with snpEff, skipping if snpEff database not present. """ snpeff_db, datadir = get_db(data) if not snpeff_db: return None, None assert os.path.exists(os.path.join(datadir, snpeff_db)), \ "Did not find %s snpEff genome data in %s" % (snpeff_db, datadir) ext = utils.splitext_plus(snp_in)[1] if out_format == "vcf" else ".tsv" out_file = "%s-effects%s" % (utils.splitext_plus(snp_in)[0], ext) stats_file = "%s-stats.html" % utils.splitext_plus(out_file)[0] csv_file = "%s-stats.csv" % utils.splitext_plus(out_file)[0] if not utils.file_exists(out_file): config_args = " ".join(_snpeff_args_from_config(data)) if ext.endswith(".gz"): bgzip_cmd = "| %s -c" % tools.get_bgzip_cmd(data["config"]) else: bgzip_cmd = "" with file_transaction(data, out_file) as tx_out_file: snpeff_cmd = _get_snpeff_cmd("eff", datadir, data, tx_out_file) cmd = ("{snpeff_cmd} {config_args} -noLog -i vcf -o {out_format} " "-csvStats {csv_file} -s {stats_file} {snpeff_db} {snp_in} {bgzip_cmd} > {tx_out_file}") do.run(cmd.format(**locals()), "snpEff effects", data) if ext.endswith(".gz"): out_file = vcfutils.bgzip_and_index(out_file, data["config"]) return out_file, [stats_file, csv_file] # ## back-compatibility def _find_snpeff_datadir(config_file): with open(config_file) as in_handle: for line in in_handle: if line.startswith("data_dir"): data_dir = config_utils.expand_path(line.split("=")[-1].strip()) if not data_dir.startswith("/"): data_dir = os.path.join(os.path.dirname(config_file), data_dir) return data_dir raise ValueError("Did not find data directory in snpEff config file: %s" % config_file) def _installed_snpeff_genome(base_name, config): """Find the most recent installed genome for snpEff with the given name. """ snpeff_config_file = os.path.join(config_utils.get_program("snpeff", config, "dir"), "snpEff.config") if os.path.exists(snpeff_config_file): data_dir = _find_snpeff_datadir(snpeff_config_file) dbs = [d for d in sorted(glob.glob(os.path.join(data_dir, "%s*" % base_name)), reverse=True) if os.path.isdir(d)] else: data_dir = None dbs = [] if len(dbs) == 0: raise ValueError("No database found in %s for %s" % (data_dir, base_name)) else: return data_dir, os.path.split(dbs[0])[-1] bcbio-nextgen-1.2.9/bcbio/variation/ensemble.py000066400000000000000000000304741415626112400214770ustar00rootroot00000000000000"""Ensemble methods that create consensus calls from multiple approaches. This handles merging calls produced by multiple calling methods or technologies into a single consolidated callset. Uses the bcbio.variation toolkit: https://github.com/chapmanb/bcbio.variation and bcbio.variation.recall: https://github.com/chapmanb/bcbio.variation.recall """ import collections import copy import glob import math import os import yaml import toolz as tz from bcbio import utils from bcbio.cwl import cwlutils from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import population, validate, vcfutils, multi, normalize, effects def batch(samples): """CWL: batch together per sample, joint and germline calls for ensemble combination. Sets up groups of same sample/batch variant calls for ensemble calling, as long as we have more than one caller per group. """ samples = [utils.to_single_data(x) for x in samples] sample_order = [dd.get_sample_name(x) for x in samples] batch_groups = collections.defaultdict(list) for data in samples: batch_samples = tuple(data.get("batch_samples", [dd.get_sample_name(data)])) batch_groups[(batch_samples, dd.get_phenotype(data))].append(data) out = [] for (batch_samples, phenotype), gsamples in batch_groups.items(): if len(gsamples) > 1: batches = set([]) for d in gsamples: batches |= set(dd.get_batches(d)) gsamples.sort(key=dd.get_variantcaller_order) cur = copy.deepcopy(gsamples[0]) cur.update({"batch_id": sorted(list(batches))[0] if batches else "_".join(batch_samples), "batch_samples": batch_samples, "variants": {"variantcallers": [dd.get_variantcaller(d) for d in gsamples], "calls": [d.get("vrn_file") for d in gsamples]}}) out.append(cur) def by_original_order(d): return min([sample_order.index(s) for s in d["batch_samples"] if s in sample_order]) return sorted(out, key=by_original_order) def combine_calls(*args): """Combine multiple callsets into a final set of merged calls. """ if len(args) == 3: is_cwl = False batch_id, samples, data = args caller_names, vrn_files = _organize_variants(samples, batch_id) else: is_cwl = True samples = [utils.to_single_data(x) for x in args] samples = [cwlutils.unpack_tarballs(x, x) for x in samples] data = samples[0] batch_id = data["batch_id"] caller_names = data["variants"]["variantcallers"] vrn_files = data["variants"]["calls"] logger.info("Ensemble consensus calls for {0}: {1}".format( batch_id, ",".join(caller_names))) edata = copy.deepcopy(data) base_dir = utils.safe_makedir(os.path.join(edata["dirs"]["work"], "ensemble", batch_id)) if any([vcfutils.vcf_has_variants(f) for f in vrn_files]): # Decompose multiallelic variants and normalize passonly = not tz.get_in(["config", "algorithm", "ensemble", "use_filtered"], edata, False) vrn_files = [normalize.normalize(f, data, passonly=passonly, rerun_effects=False, remove_oldeffects=True, nonrefonly=True, work_dir=utils.safe_makedir(os.path.join(base_dir, c))) for c, f in zip(caller_names, vrn_files)] if "classifiers" not in (dd.get_ensemble(edata) or {}): callinfo = _run_ensemble_intersection(batch_id, vrn_files, caller_names, base_dir, edata) else: config_file = _write_config_file(batch_id, caller_names, base_dir, edata) callinfo = _run_ensemble(batch_id, vrn_files, config_file, base_dir, dd.get_ref_file(edata), edata) callinfo["vrn_file"] = vcfutils.bgzip_and_index(callinfo["vrn_file"], data["config"]) # After decomposing multiallelic variants and normalizing, re-evaluate effects ann_ma_file, _ = effects.add_to_vcf(callinfo["vrn_file"], data) if ann_ma_file: callinfo["vrn_file"] = ann_ma_file edata["config"]["algorithm"]["variantcaller"] = "ensemble" edata["vrn_file"] = callinfo["vrn_file"] edata["ensemble_bed"] = callinfo["bed_file"] callinfo["validate"] = validate.compare_to_rm(edata)[0][0].get("validate") else: out_vcf_file = os.path.join(base_dir, "{0}-ensemble.vcf".format(batch_id)) vcfutils.write_empty_vcf(out_vcf_file, samples=[dd.get_sample_name(d) for d in samples]) callinfo = {"variantcaller": "ensemble", "vrn_file": vcfutils.bgzip_and_index(out_vcf_file, data["config"]), "bed_file": None} if is_cwl: callinfo["batch_samples"] = data["batch_samples"] callinfo["batch_id"] = batch_id return [{"ensemble": callinfo}] else: return [[batch_id, callinfo]] def combine_calls_parallel(samples, run_parallel): """Combine calls using batched Ensemble approach. """ batch_groups, extras = _group_by_batches(samples, _has_ensemble) out = [] if batch_groups: processed = run_parallel("combine_calls", ((b, xs, xs[0]) for b, xs in batch_groups.items())) for batch_id, callinfo in processed: for data in batch_groups[batch_id]: data["variants"].insert(0, callinfo) out.append([data]) return out + extras def _has_ensemble(data): # for tumour-normal calling, a sample may have "ensemble" for the normal # sample configured but there won't be any variant files per se variants_to_process = (len(data["variants"]) > 1 and any([x.get('vrn_file', None) is not None or x.get('vrn_file_batch', None) is not None for x in data["variants"]])) return variants_to_process and dd.get_ensemble(data) def _group_by_batches(samples, check_fn): """Group calls by batches, processing families together during ensemble calling. """ batch_groups = collections.defaultdict(list) extras = [] for data in [x[0] for x in samples]: if check_fn(data): batch_groups[multi.get_batch_for_key(data)].append(data) else: extras.append([data]) return batch_groups, extras def _organize_variants(samples, batch_id): """Retrieve variant calls for all samples, merging batched samples into single VCF. """ caller_names = [x["variantcaller"] for x in samples[0]["variants"]] calls = collections.defaultdict(list) for data in samples: for vrn in data["variants"]: calls[vrn["variantcaller"]].append(vrn["vrn_file"]) data = samples[0] vrn_files = [] for caller in caller_names: fnames = calls[caller] if len(fnames) == 1: vrn_files.append(fnames[0]) else: vrn_files.append(population.get_multisample_vcf(fnames, batch_id, caller, data)) return caller_names, vrn_files def _handle_somatic_ensemble(vrn_file, data): """For somatic ensemble, discard normal samples and filtered variants from vcfs. Only needed for bcbio.variation based ensemble calling. """ if tz.get_in(["metadata", "phenotype"], data, "").lower().startswith("tumor"): vrn_file_temp = vrn_file.replace(".vcf", "_tumorOnly_noFilteredCalls.vcf") # Select tumor sample and keep only PASS and . calls vrn_file = vcfutils.select_sample(in_file=vrn_file, sample=data["name"][1], out_file=vrn_file_temp, config=data["config"], filters="PASS,.") return vrn_file def _bcbio_variation_ensemble(vrn_files, out_file, ref_file, config_file, base_dir, data): """Run a variant comparison using the bcbio.variation toolkit, given an input configuration. """ vrn_files = [_handle_somatic_ensemble(v, data) for v in vrn_files] tmp_dir = utils.safe_makedir(os.path.join(base_dir, "tmp")) resources = config_utils.get_resources("bcbio_variation", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx2g"]) java_args = ["-Djava.io.tmpdir=%s" % tmp_dir] cmd = ["bcbio-variation"] + jvm_opts + java_args + \ ["variant-ensemble", config_file, ref_file, out_file] + vrn_files with utils.chdir(base_dir): cmd = "%s %s" % (utils.local_path_export(), " ".join(str(x) for x in cmd)) do.run(cmd, "Ensemble calling: %s" % os.path.basename(base_dir)) def _run_ensemble(batch_id, vrn_files, config_file, base_dir, ref_file, data): """Run an ensemble call using merging and SVM-based approach in bcbio.variation """ out_vcf_file = os.path.join(base_dir, "{0}-ensemble.vcf".format(batch_id)) out_bed_file = os.path.join(base_dir, "{0}-callregions.bed".format(batch_id)) work_dir = "%s-work" % os.path.splitext(out_vcf_file)[0] if not utils.file_exists(out_vcf_file): _bcbio_variation_ensemble(vrn_files, out_vcf_file, ref_file, config_file, base_dir, data) if not utils.file_exists(out_vcf_file): base_vcf = glob.glob(os.path.join(work_dir, "prep", "*-cfilter.vcf"))[0] utils.symlink_plus(base_vcf, out_vcf_file) if not utils.file_exists(out_bed_file): multi_beds = glob.glob(os.path.join(work_dir, "prep", "*-multicombine.bed")) if len(multi_beds) > 0: utils.symlink_plus(multi_beds[0], out_bed_file) return {"variantcaller": "ensemble", "vrn_file": out_vcf_file, "bed_file": out_bed_file if os.path.exists(out_bed_file) else None} def _write_config_file(batch_id, caller_names, base_dir, data): """Write YAML configuration to generate an ensemble set of combined calls. """ config_dir = utils.safe_makedir(os.path.join(base_dir, "config")) config_file = os.path.join(config_dir, "{0}-ensemble.yaml".format(batch_id)) algorithm = data["config"]["algorithm"] econfig = {"ensemble": algorithm["ensemble"], "names": caller_names, "prep-inputs": False} intervals = validate.get_analysis_intervals(data, None, base_dir) if intervals: econfig["intervals"] = os.path.abspath(intervals) with open(config_file, "w") as out_handle: yaml.safe_dump(econfig, out_handle, allow_unicode=False, default_flow_style=False) return config_file def _get_num_pass(data, n): """Calculate the number of samples needed to pass ensemble calling. """ numpass = tz.get_in(["config", "algorithm", "ensemble", "numpass"], data) if numpass: return int(numpass) trusted_pct = tz.get_in(["config", "algorithm", "ensemble", "trusted_pct"], data) if trusted_pct: return int(math.ceil(float(trusted_pct) * n)) return 2 def _run_ensemble_intersection(batch_id, vrn_files, callers, base_dir, edata): """Run intersection n out of x based ensemble method using bcbio.variation.recall. """ out_vcf_file = os.path.join(base_dir, "{0}-ensemble.vcf.gz".format(batch_id)) if not utils.file_exists(out_vcf_file): num_pass = _get_num_pass(edata, len(vrn_files)) bvr_cmd = config_utils.get_program("bcbio-variation-recall", edata["config"]) cmd = [ bvr_cmd, "ensemble", "--cores=%s" % edata["config"]["algorithm"].get("num_cores", 1), "--numpass", str(num_pass), "--names", ",".join(callers) ] # Remove filtered calls, do not try to rescue, unless configured if not tz.get_in(["config", "algorithm", "ensemble", "use_filtered"], edata): cmd += ["--nofiltered"] # b-v-r could be not in the main but in java env with file_transaction(edata, out_vcf_file) as tx_out_file: cmd += [tx_out_file, dd.get_ref_file(edata)] + vrn_files cmd = "%s && %s" % (utils.get_java_clprep(bvr_cmd), " ".join(str(x) for x in cmd)) do.run(cmd, "Ensemble intersection calling: %s" % (batch_id)) in_data = utils.deepish_copy(edata) in_data["vrn_file"] = out_vcf_file return {"variantcaller": "ensemble", "vrn_file": out_vcf_file, "bed_file": None} bcbio-nextgen-1.2.9/bcbio/variation/freebayes.py000066400000000000000000000430331415626112400216450ustar00rootroot00000000000000"""Bayesian variant calling with FreeBayes. https://github.com/ekg/freebayes """ import os import sys import six import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import config_utils, shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import annotation, bedutils, ploidy, vcfutils from bcbio.variation.vcfutils import (get_paired_bams, is_paired_analysis, move_vcf) def region_to_freebayes(region): if isinstance(region, (list, tuple)): chrom, start, end = region return "%s:%s..%s" % (chrom, start, end) else: return region def _freebayes_options_from_config(items, config, out_file, region=None): """Prepare standard options from configuration input. Input BED target files are merged to avoid overlapping regions which cause FreeBayes to call multiple times. Checks for empty sets of target regions after filtering for high depth, in which case we should skip the FreeBayes run. """ opts = ["--genotype-qualities", "--strict-vcf"] cur_ploidy = ploidy.get_ploidy(items, region) base_ploidy = ploidy.get_ploidy(items) opts += ["--ploidy", str(cur_ploidy)] # Adjust min fraction when trying to call more sensitively in certain # regions. This is primarily meant for pooled mitochondrial calling. if (isinstance(region, (list, tuple)) and chromhacks.is_mitochondrial(region[0]) and cur_ploidy >= base_ploidy and "--min-alternate-fraction" not in opts and "-F" not in opts): opts += ["--min-alternate-fraction", "0.01"] variant_regions = bedutils.population_variant_regions(items, merged=True) # Produce gVCF output if any("gvcf" in dd.get_tools_on(d) for d in items): opts += ["--gvcf", "--gvcf-chunk", "50000"] no_target_regions = False target = shared.subset_variant_regions(variant_regions, region, out_file, items) if target: if isinstance(target, six.string_types) and os.path.isfile(target): if os.path.getsize(target) == 0: no_target_regions = True else: opts += ["--targets", target] else: opts += ["--region", region_to_freebayes(target)] resources = config_utils.get_resources("freebayes", config) if resources.get("options"): opts += resources["options"] return opts, no_target_regions def _add_somatic_opts(opts, paired): """Add somatic options to current set. See _run_freebayes_paired for references. """ if "--min-alternate-fraction" not in opts and "-F" not in opts: # add minimum reportable allele frequency # FreeBayes defaults to 20%, but use 10% by default for the # tumor case min_af = float(utils.get_in(paired.tumor_config, ("algorithm", "min_allele_fraction"), 10)) / 100.0 opts += " --min-alternate-fraction %s" % min_af # Recommended settings for cancer calling opts += (" --pooled-discrete --pooled-continuous " "--report-genotype-likelihood-max --allele-balance-priors-off") return opts def run_freebayes(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Run FreeBayes variant calling, either paired tumor/normal or germline calling. """ items = shared.add_highdepth_genome_exclusion(items) if is_paired_analysis(align_bams, items): paired = get_paired_bams(align_bams, items) if not paired.normal_bam: call_file = _run_freebayes_caller(align_bams, items, ref_file, assoc_files, region, out_file, somatic=paired) else: call_file = _run_freebayes_paired([paired.tumor_bam, paired.normal_bam], [paired.tumor_data, paired.normal_data], ref_file, assoc_files, region, out_file) else: vcfutils.check_paired_problems(items) call_file = _run_freebayes_caller(align_bams, items, ref_file, assoc_files, region, out_file) return call_file def _run_freebayes_caller(align_bams, items, ref_file, assoc_files, region=None, out_file=None, somatic=None): """Detect SNPs and indels with FreeBayes. Performs post-filtering to remove very low quality variants which can cause issues feeding into GATK. Breaks variants into individual allelic primitives for analysis and evaluation. """ config = items[0]["config"] if out_file is None: out_file = "%s-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not utils.file_exists(out_file): if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: freebayes = config_utils.get_program("freebayes", config) input_bams = " ".join("-b %s" % x for x in align_bams) opts, no_target_regions = _freebayes_options_from_config(items, config, out_file, region) if no_target_regions: vcfutils.write_empty_vcf(tx_out_file, config, samples=[dd.get_sample_name(d) for d in items]) else: opts = " ".join(opts) # Recommended options from 1000 genomes low-complexity evaluation # https://groups.google.com/d/msg/freebayes/GvxIzjcpbas/1G6e3ArxQ4cJ opts += " --min-repeat-entropy 1" # Remove partial observations, which cause a preference for heterozygote calls # https://github.com/ekg/freebayes/issues/234#issuecomment-205331765 opts += " --no-partial-observations" if somatic: opts = _add_somatic_opts(opts, somatic) compress_cmd = "| bgzip -c" if out_file.endswith("gz") else "" # For multi-sample outputs, ensure consistent order samples = ("-s" + ",".join([dd.get_sample_name(d) for d in items])) if len(items) > 1 else "" fix_ambig = vcfutils.fix_ambiguous_cl() py_cl = config_utils.get_program("py", config) cmd = ("{freebayes} -f {ref_file} {opts} {input_bams} " """| bcftools filter -i 'ALT="<*>" || QUAL > 5' """ "| {fix_ambig} | bcftools view {samples} -a - | " "{py_cl} -x 'bcbio.variation.freebayes.remove_missingalt(x)' | " "vcfallelicprimitives -t DECOMPOSED --keep-geno | vcffixup - | vcfstreamsort | " "vt normalize -n -r {ref_file} -q - | vcfuniqalleles | vt uniq - 2> /dev/null " "{compress_cmd} > {tx_out_file}") do.run(cmd.format(**locals()), "Genotyping with FreeBayes", {}) return out_file def _run_freebayes_paired(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect SNPs and indels with FreeBayes for paired tumor/normal samples. Sources of options for FreeBayes: mailing list: https://groups.google.com/d/msg/freebayes/dTWBtLyM4Vs/HAK_ZhJHguMJ mailing list: https://groups.google.com/forum/#!msg/freebayes/LLH7ZfZlVNs/63FdD31rrfEJ speedseq: https://github.com/cc2qe/speedseq/blob/e6729aa2589eca4e3a946f398c1a2bdc15a7300d/bin/speedseq#L916 sga/freebayes: https://github.com/jts/sga-extra/blob/7e28caf71e8107b697f9be7162050e4fa259694b/ sga_generate_varcall_makefile.pl#L299 """ config = items[0]["config"] if out_file is None: out_file = "%s-paired-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not utils.file_exists(out_file): if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: paired = get_paired_bams(align_bams, items) assert paired.normal_bam, "Require normal BAM for FreeBayes paired calling and filtering" freebayes = config_utils.get_program("freebayes", config) opts, no_target_regions = _freebayes_options_from_config(items, config, out_file, region) if no_target_regions: vcfutils.write_empty_vcf(tx_out_file, config, samples=[x for x in [paired.tumor_name, paired.normal_name] if x]) else: opts = " ".join(opts) opts += " --min-repeat-entropy 1" opts += " --no-partial-observations" opts = _add_somatic_opts(opts, paired) compress_cmd = "| bgzip -c" if out_file.endswith("gz") else "" # For multi-sample outputs, ensure consistent order samples = ("-s " + ",".join([dd.get_sample_name(d) for d in items])) if len(items) > 1 else "" fix_ambig = vcfutils.fix_ambiguous_cl() bcbio_py = sys.executable py_cl = os.path.join(os.path.dirname(sys.executable), "py") cl = ("{freebayes} -f {ref_file} {opts} " "{paired.tumor_bam} {paired.normal_bam} " """| bcftools filter -i 'ALT="<*>" || QUAL > 5' """ """| {bcbio_py} -c 'from bcbio.variation import freebayes; """ """freebayes.call_somatic("{paired.tumor_name}", "{paired.normal_name}")' """ "| {fix_ambig} | bcftools view {samples} -a - | " "{py_cl} -x 'bcbio.variation.freebayes.remove_missingalt(x)' | " "vcfallelicprimitives -t DECOMPOSED --keep-geno | vcffixup - | vcfstreamsort | " "vt normalize -n -r {ref_file} -q - | vcfuniqalleles | vt uniq - 2> /dev/null " "{compress_cmd} > {tx_out_file}") do.run(cl.format(**locals()), "Genotyping paired variants with FreeBayes", {}) return out_file # ## Filtering def _check_lods(parts, tumor_thresh, normal_thresh, indexes): """Ensure likelihoods for tumor and normal pass thresholds. Skipped if no FreeBayes GL annotations available. """ try: gl_index = parts[8].split(":").index("GL") except ValueError: return True try: tumor_gls = [float(x) for x in parts[indexes["tumor"]].strip().split(":")[gl_index].split(",") if x != "."] if tumor_gls: tumor_lod = max(tumor_gls[i] - tumor_gls[0] for i in range(1, len(tumor_gls))) else: tumor_lod = -1.0 # No GL information, no tumor call (so fail it) except IndexError: tumor_lod = -1.0 try: normal_gls = [float(x) for x in parts[indexes["normal"]].strip().split(":")[gl_index].split(",") if x != "."] if normal_gls: normal_lod = min(normal_gls[0] - normal_gls[i] for i in range(1, len(normal_gls))) else: normal_lod = normal_thresh # No GL inofmration, no normal call (so pass it) except IndexError: normal_lod = normal_thresh return normal_lod >= normal_thresh and tumor_lod >= tumor_thresh def _check_freqs(parts, indexes): """Ensure frequency of tumor to normal passes a reasonable threshold. Avoids calling low frequency tumors also present at low frequency in normals, which indicates a contamination or persistent error. """ thresh_ratio = 2.7 try: # FreeBayes ao_index = parts[8].split(":").index("AO") ro_index = parts[8].split(":").index("RO") except ValueError: ao_index, ro_index = None, None try: # VarDict af_index = parts[8].split(":").index("AF") except ValueError: af_index = None if af_index is None and ao_index is None: # okay to skip if a gVCF record if parts[4].find("<*>") == -1: raise NotImplementedError("Unexpected format annotations: %s" % parts[8]) def _calc_freq(item): try: if ao_index is not None and ro_index is not None: ao = sum([int(x) for x in item.split(":")[ao_index].split(",")]) ro = int(item.split(":")[ro_index]) freq = ao / float(ao + ro) elif af_index is not None: freq = float(item.split(":")[af_index]) else: freq = 0.0 except (IndexError, ValueError, ZeroDivisionError): freq = 0.0 return freq tumor_freq, normal_freq = _calc_freq(parts[indexes["tumor"]]), _calc_freq(parts[indexes["normal"]]) return normal_freq <= 0.001 or normal_freq <= tumor_freq / thresh_ratio def remove_missingalt(line): """Remove lines that are missing an alternative allele. During cleanup of extra alleles, bcftools has an issue in complicated cases with duplicate alleles and will end up stripping all alternative alleles. This removes those lines to avoid issues downstream. """ if not line.startswith("#"): parts = line.split("\t") if parts[4] == ".": return None return line def call_somatic(tumor_name, normal_name): """Call SOMATIC variants from tumor/normal calls, adding REJECT filters and SOMATIC flag. Works from stdin and writes to stdout, finding positions of tumor and normal samples. Uses MuTect like somatic filter based on implementation in speedseq: https://github.com/cc2qe/speedseq/blob/e6729aa2589eca4e3a946f398c1a2bdc15a7300d/bin/speedseq#L62 Extracts the genotype likelihoods (GLs) from FreeBayes, which are like phred scores except not multiplied by 10.0 (https://en.wikipedia.org/wiki/Phred_quality_score). For tumors, we retrieve the best likelihood to not be reference (the first GL) and for normal, the best likelhood to be reference. After calculating the likelihoods, we compare these to thresholds to pass variants at tuned sensitivity/precision. Tuning done on DREAM synthetic 3 dataset evaluations. We also check that the frequency of the tumor exceeds the frequency of the normal by a threshold to avoid calls that are low frequency in both tumor and normal. This supports both FreeBayes and VarDict output frequencies. """ # Thresholds are like phred scores, so 3.5 = phred35 tumor_thresh, normal_thresh = 3.5, 3.5 new_headers = ['##INFO=\n', ('##FILTER=\n') % (int(tumor_thresh * 10), int(normal_thresh * 10))] def _output_filter_line(line, indexes): parts = line.split("\t") if _check_lods(parts, tumor_thresh, normal_thresh, indexes) and _check_freqs(parts, indexes): parts[7] = parts[7] + ";SOMATIC" else: if parts[6] in set([".", "PASS"]): parts[6] = "REJECT" else: parts[6] += ";REJECT" line = "\t".join(parts) sys.stdout.write(line) def _write_header(header): for hline in header[:-1] + new_headers + [header[-1]]: sys.stdout.write(hline) header = [] indexes = None for line in sys.stdin: if not indexes: if line.startswith("#"): header.append(line) else: parts = header[-1].rstrip().split("\t") indexes = {"tumor": parts.index(tumor_name), "normal": parts.index(normal_name)} _write_header(header) _output_filter_line(line, indexes) else: _output_filter_line(line, indexes) # no calls, only output the header if not indexes: _write_header(header) def _clean_freebayes_output(line): """Clean FreeBayes output to make post-processing with GATK happy. XXX Not applied on recent versions which fix issues to be more compatible with bgzip output, but retained in case of need. - Remove lines from FreeBayes outputs where REF/ALT are identical: 2 22816178 . G G 0.0339196 or there are multiple duplicate alleles: 4 60594753 . TGAAA T,T - Remove Type=Int specifications which are not valid VCF and GATK chokes on. """ if line.startswith("#"): line = line.replace("Type=Int,D", "Type=Integer,D") return line else: parts = line.split("\t") alleles = [x.strip() for x in parts[4].split(",")] + [parts[3].strip()] if len(alleles) == len(set(alleles)): return line return None def clean_vcf_output(orig_file, clean_fn, config, name="clean"): """Provide framework to clean a file in-place, with the specified clean function. """ base, ext = utils.splitext_plus(orig_file) out_file = "{0}-{1}{2}".format(base, name, ext) if not utils.file_exists(out_file): with open(orig_file) as in_handle: with file_transaction(config, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for line in in_handle: update_line = clean_fn(line) if update_line: out_handle.write(update_line) move_vcf(orig_file, "{0}.orig".format(orig_file)) move_vcf(out_file, orig_file) with open(out_file, "w") as out_handle: out_handle.write("Moved to {0}".format(orig_file)) bcbio-nextgen-1.2.9/bcbio/variation/gatk.py000066400000000000000000000326171415626112400206340ustar00rootroot00000000000000"""GATK variant calling -- HaplotypeCaller and UnifiedGenotyper. """ import os from distutils.version import LooseVersion import shutil import subprocess import toolz as tz from bcbio import bam, broad, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline.shared import subset_variant_regions from bcbio.pipeline import datadict as dd from bcbio.variation import annotation, bamprep, bedutils, ploidy, vcfutils from bcbio.provenance import do def standard_cl_params(items): """Shared command line parameters for GATK programs. Handles no removal of duplicate reads for amplicon or non mark duplicate experiments. If we have pre-aligned inputs we ignore the value or mark duplicates (since they may already be marked in the input BAM). """ out = [] def _skip_duplicates(data): return (dd.get_coverage_interval(data) == "amplicon" or (dd.get_aligner(data) and not dd.get_mark_duplicates(data))) if any(_skip_duplicates(d) for d in items): broad_runner = broad.runner_from_config(items[0]["config"]) gatk_type = broad_runner.gatk_type() if gatk_type == "gatk4": out += ["--disable-read-filter", "NotDuplicateReadFilter"] elif LooseVersion(broad_runner.gatk_major_version()) >= LooseVersion("3.5"): out += ["-drf", "DuplicateRead"] return out def _shared_gatk_call_prep(align_bams, items, ref_file, region, out_file, num_cores=1): """Shared preparation work for GATK variant calling. """ data = items[0] config = data["config"] broad_runner = broad.runner_from_config(config) gatk_type = broad_runner.gatk_type() for x in align_bams: bam.index(x, config) picard_runner = broad.runner_from_path("picard", config) picard_runner.run_fn("picard_index_ref", ref_file) params = ["-R", ref_file] coverage_depth_min = tz.get_in(["algorithm", "coverage_depth_min"], config) if coverage_depth_min and coverage_depth_min < 4: confidence = "4.0" params += ["--standard_min_confidence_threshold_for_calling", confidence] for a in annotation.get_gatk_annotations(config): params += ["--annotation", a] for x in align_bams: params += ["-I", x] variant_regions = bedutils.population_variant_regions(items) region = subset_variant_regions(variant_regions, region, out_file, items) if region: params += ["-L", bamprep.region_to_gatk(region), "-isr", "INTERSECTION"] params += standard_cl_params(items) return broad_runner, params def unified_genotyper(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Perform SNP genotyping on the given alignment file. """ if out_file is None: out_file = "%s-variants.vcf.gz" % utils.splitext_plus(align_bams[0])[0] if not utils.file_exists(out_file): broad_runner, params = \ _shared_gatk_call_prep(align_bams, items, ref_file, region, out_file) with file_transaction(items[0], out_file) as tx_out_file: params += ["-T", "UnifiedGenotyper", "-o", tx_out_file, "-ploidy", (str(ploidy.get_ploidy(items, region)) if broad_runner.gatk_type() == "restricted" else "2"), "--genotype_likelihoods_model", "BOTH"] resources = config_utils.get_resources("gatk", items[0]["config"]) if "options" in resources: params += [str(x) for x in resources.get("options", [])] broad_runner.run_gatk(params) return vcfutils.bgzip_and_index(out_file, items[0]["config"]) def _joint_calling(items): """Determine if this call feeds downstream into joint calls. """ jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), items[0]) if jointcaller: assert len(items) == 1, "Can only do joint calling preparation with GATK with single samples" assert tz.get_in(("metadata", "batch"), items[0]) is not None, \ "Joint calling requires batched samples, %s has no metadata batch." % dd.get_sample_name(items[0]) return jointcaller def _use_spark(num_cores, gatk_type, items, opts): data = items[0] use_spark = False if dd.get_analysis(data).lower() != "rna-seq": use_spark = (len(items) == 1 and num_cores > 1 and gatk_type == "gatk4") or "--spark-master" in opts return use_spark def haplotype_caller(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Call variation with GATK's HaplotypeCaller. This requires the full non open-source version of GATK. """ if out_file is None: out_file = "%s-variants.vcf.gz" % utils.splitext_plus(align_bams[0])[0] if not utils.file_exists(out_file): num_cores = dd.get_num_cores(items[0]) broad_runner, params = \ _shared_gatk_call_prep(align_bams, items, ref_file, region, out_file, num_cores) gatk_type = broad_runner.gatk_type() assert gatk_type in ["restricted", "gatk4"], \ "Require full version of GATK 2.4+, or GATK4 for haplotype calling" with file_transaction(items[0], out_file) as tx_out_file: resources = config_utils.get_resources("gatk-spark", items[0]["config"]) spark_opts = [str(x) for x in resources.get("options", [])] if _use_spark(num_cores, gatk_type, items, spark_opts): params += ["-T", "HaplotypeCallerSpark"] if spark_opts: params += spark_opts else: params += ["--spark-master", "local[%s]" % num_cores, "--conf", "spark.local.dir=%s" % os.path.dirname(tx_out_file), "--conf", "spark.driver.host=localhost", "--conf", "spark.network.timeout=800", "--conf", "spark.executor.heartbeatInterval=100"] else: params += ["-T", "HaplotypeCaller"] params += ["--annotation", "ClippingRankSumTest", "--annotation", "DepthPerSampleHC"] # Enable hardware based optimizations in GATK 3.1+ if LooseVersion(broad_runner.gatk_major_version()) >= LooseVersion("3.1"): if _supports_avx(): # Scale down HMM thread default to avoid overuse of cores # https://github.com/bcbio/bcbio-nextgen/issues/2442 if gatk_type == "gatk4": params += ["--native-pair-hmm-threads", "1"] # GATK4 selects the right HMM optimization automatically with FASTEST_AVAILABLE # GATK3 needs to be explicitly set else: params += ["--pair_hmm_implementation", "VECTOR_LOGLESS_CACHING"] resources = config_utils.get_resources("gatk-haplotype", items[0]["config"]) if "options" in resources: params += [str(x) for x in resources.get("options", [])] # Prepare gVCFs if doing joint calling is_joint = False if _joint_calling(items) or any("gvcf" in dd.get_tools_on(d) for d in items): is_joint = True # If joint calling parameters not set in user options if not any([x in ["--emit-ref-confidence", "-ERC", "--emitRefConfidence"] for x in params]): if gatk_type == "gatk4": params += ["--emit-ref-confidence", "GVCF"] else: params += ["--emitRefConfidence", "GVCF"] params += ["--variant_index_type", "LINEAR", "--variant_index_parameter", "128000"] # Set GQ banding to not be single GQ resolution # No recommended default but try to balance resolution and size # http://gatkforums.broadinstitute.org/gatk/discussion/7051/recommendation-best-practices-gvcf-gq-bands if not any([x in ["-GQB"] for x in params]): for boundary in [10, 20, 30, 40, 60, 80]: params += ["-GQB", str(boundary)] # Enable non-diploid calling in GATK 3.3+ if LooseVersion(broad_runner.gatk_major_version()) >= LooseVersion("3.3"): params += ["-ploidy", str(ploidy.get_ploidy(items, region))] if gatk_type == "gatk4": # GATK4 Spark calling does not support bgzipped output, use plain VCFs if is_joint and _use_spark(num_cores, gatk_type, items, spark_opts): tx_out_file = tx_out_file.replace(".vcf.gz", ".vcf") params += ["--output", tx_out_file] else: params += ["-o", tx_out_file] broad_runner.new_resources("gatk-haplotype") memscale = {"magnitude": 0.9 * num_cores, "direction": "increase"} if num_cores > 1 else None try: broad_runner.run_gatk(params, os.path.dirname(tx_out_file), memscale=memscale, parallel_gc=_use_spark(num_cores, gatk_type, items, spark_opts)) except subprocess.CalledProcessError as msg: # Spark failing on regions without any reads, write an empty VCF instead # https://github.com/broadinstitute/gatk/issues/4234 if (_use_spark(num_cores, gatk_type, items, spark_opts) and str(msg).find("java.lang.UnsupportedOperationException: empty collection") >= 0 and str(msg).find("at org.apache.spark.rdd.RDD") >= 0): vcfutils.write_empty_vcf(tx_out_file, samples=[dd.get_sample_name(d) for d in items]) else: raise if tx_out_file.endswith(".vcf"): vcfutils.bgzip_and_index(tx_out_file, items[0]["config"]) # avoid bug in GATK where files can get output as non-compressed if out_file.endswith(".gz") and not os.path.exists(out_file + ".tbi"): with open(out_file, "r") as in_handle: is_plain_text = in_handle.readline().startswith("##fileformat") if is_plain_text: text_out_file = out_file out_file = out_file.replace(".vcf.gz", ".vcf") shutil.move(text_out_file, out_file) return vcfutils.bgzip_and_index(out_file, items[0]["config"]) def _supports_avx(): """Check for support for Intel AVX acceleration.""" if os.path.exists("/proc/cpuinfo"): with open("/proc/cpuinfo") as in_handle: for line in in_handle: if line.startswith("flags") and line.find("avx") > 0: return True def collect_artifact_metrics(data): """Run CollectSequencingArtifacts to collect pre-adapter ligation artifact metrics https://gatk.broadinstitute.org/hc/en-us/articles/360037429491-CollectSequencingArtifactMetrics-Picard- use picard wrapper rather than gatk - works for gatk4 and gatk3 projects refactor - move to broad/picardrun """ OUT_SUFFIXES = [".bait_bias_detail_metrics", ".error_summary_metrics", ".pre_adapter_detail_metrics", ".pre_adapter_summary_metrics"] picard = broad.runner_from_path("picard", dd.get_config(data)) ref_file = dd.get_ref_file(data) bam_file = dd.get_work_bam(data) if not bam_file: return None if "collectsequencingartifacts" in dd.get_tools_off(data): return None out_dir = os.path.join(dd.get_work_dir(data), "metrics", "artifact", dd.get_sample_name(data)) utils.safe_makedir(out_dir) out_base = os.path.join(out_dir, dd.get_sample_name(data)) out_files = [out_base + x for x in OUT_SUFFIXES] if all([utils.file_exists(x) for x in out_files]): return out_files with file_transaction(data, out_dir) as tx_out_dir: utils.safe_makedir(tx_out_dir) out_base = os.path.join(tx_out_dir, dd.get_sample_name(data)) params = [("-REFERENCE_SEQUENCE", ref_file), ("-INPUT", bam_file), ("-OUTPUT", out_base)] # picard runner sets VALIDATION_STRINGENCY picard.run("CollectSequencingArtifactMetrics", params) return out_files def collect_oxog_metrics(data): """ extracts 8-oxoguanine (OxoG) artifact metrics from CollectSequencingArtifacts output so we don't have to run CollectOxoGMetrics. """ input_base = os.path.join(dd.get_work_dir(data), "metrics", "artifact", dd.get_sample_name(data), dd.get_sample_name(data)) if not utils.file_exists(input_base + ".pre_adapter_detail_metrics"): return None OUT_SUFFIXES = [".oxog_metrics"] picard = broad.runner_from_path("picard", dd.get_config(data)) out_dir = os.path.join(dd.get_work_dir(data), "metrics", "oxog", dd.get_sample_name(data)) utils.safe_makedir(out_dir) ref_file = dd.get_ref_file(data) out_base = os.path.join(out_dir, dd.get_sample_name(data)) out_files = [out_base + x for x in OUT_SUFFIXES] if all([utils.file_exists(x) for x in out_files]): return out_files with file_transaction(data, out_dir) as tx_out_dir: utils.safe_makedir(tx_out_dir) out_base = os.path.join(tx_out_dir, dd.get_sample_name(data)) params = [("--INPUT_BASE", input_base), ("--OUTPUT_BASE", out_base), ("--REFERENCE_SEQUENCE", ref_file)] picard.run("ConvertSequencingArtifactToOxoG", params) return out_files bcbio-nextgen-1.2.9/bcbio/variation/gatkfilter.py000066400000000000000000000347671415626112400220520ustar00rootroot00000000000000"""Perform GATK based filtering: soft filters, CNNs and VQSR. """ import os import gzip from distutils.version import LooseVersion from bcbio import broad, utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import vcfutils, vfilter def run(call_file, ref_file, vrn_files, data): """Run filtering on the input call file, handling SNPs and indels separately. """ algs = [data["config"]["algorithm"]] * len(data.get("vrn_files", [1])) if includes_missingalt(data): logger.info("Removing variants with missing alts from %s." % call_file) call_file = gatk_remove_missingalt(call_file, data) if "gatkcnn" in dd.get_tools_on(data): return _cnn_filter(call_file, vrn_files, data) elif config_utils.use_vqsr(algs, call_file): if vcfutils.is_gvcf_file(call_file): raise ValueError("Cannot force gVCF output with joint calling using tools_on: [gvcf] and use VQSR. " "Try using cutoff-based soft filtering with tools_off: [vqsr]") snp_file, indel_file = vcfutils.split_snps_indels(call_file, ref_file, data["config"]) snp_filter_file = _variant_filtration(snp_file, ref_file, vrn_files, data, "SNP", vfilter.gatk_snp_cutoff) indel_filter_file = _variant_filtration(indel_file, ref_file, vrn_files, data, "INDEL", vfilter.gatk_indel_cutoff) orig_files = [snp_filter_file, indel_filter_file] out_file = "%scombined.vcf.gz" % os.path.commonprefix(orig_files) combined_file = vcfutils.combine_variant_files(orig_files, out_file, ref_file, data["config"]) return combined_file else: snp_filter = vfilter.gatk_snp_cutoff(call_file, data) indel_filter = vfilter.gatk_indel_cutoff(snp_filter, data) return indel_filter # ## Convolutional Neural Networks (CNN) def _cnn_filter(in_file, vrn_files, data): """Perform CNN filtering on input VCF using pre-trained models. """ #tensor_type = "reference" # 1D, reference sequence tensor_type = "read_tensor" # 2D, reads, flags, mapping quality score_file = _cnn_score_variants(in_file, tensor_type, data) return _cnn_tranch_filtering(score_file, vrn_files, tensor_type, data) def _cnn_tranch_filtering(in_file, vrn_files, tensor_type, data): """Filter CNN scored VCFs in tranches using standard SNP and Indel truth sets. """ out_file = "%s-filter.vcf.gz" % utils.splitext_plus(in_file)[0] if not utils.file_uptodate(out_file, in_file): runner = broad.runner_from_config(data["config"]) gatk_type = runner.gatk_type() assert gatk_type == "gatk4", "CNN filtering requires GATK4" if "train_hapmap" not in vrn_files: raise ValueError("CNN filtering requires HapMap training inputs: %s" % vrn_files) with file_transaction(data, out_file) as tx_out_file: params = ["-T", "FilterVariantTranches", "--variant", in_file, "--output", tx_out_file, "--snp-truth-vcf", vrn_files["train_hapmap"], "--indel-truth-vcf", vrn_files["train_indels"]] if tensor_type == "reference": params += ["--info-key", "CNN_1D", "--tranche", "99"] else: assert tensor_type == "read_tensor" params += ["--info-key", "CNN_2D", "--tranche", "99"] runner.run_gatk(params) return vcfutils.bgzip_and_index(out_file, data["config"]) def _cnn_score_variants(in_file, tensor_type, data): """Score variants with pre-trained CNN models. """ out_file = "%s-cnnscore.vcf.gz" % utils.splitext_plus(in_file)[0] if not utils.file_uptodate(out_file, in_file): runner = broad.runner_from_config(data["config"]) gatk_type = runner.gatk_type() assert gatk_type == "gatk4", "CNN filtering requires GATK4" with file_transaction(data, out_file) as tx_out_file: params = ["-T", "CNNScoreVariants", "--variant", in_file, "--reference", dd.get_ref_file(data), "--output", tx_out_file, "--input", dd.get_align_bam(data)] params += ["--tensor-type", tensor_type] runner.run_gatk(params) return vcfutils.bgzip_and_index(out_file, data["config"]) # ## Variant Quality Score Recalibration (VQSR) def _apply_vqsr(in_file, ref_file, recal_file, tranch_file, sensitivity_cutoff, filter_type, data): """Apply VQSR based on the specified tranche, returning a filtered VCF file. """ base, ext = utils.splitext_plus(in_file) out_file = "{base}-{filter}filter{ext}".format(base=base, ext=ext, filter=filter_type) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: broad_runner = broad.runner_from_config(data["config"]) gatk_type = broad_runner.gatk_type() if gatk_type == "gatk4": params = ["-T", "ApplyVQSR", "--variant", in_file, "--output", tx_out_file, "--recal-file", recal_file, "--tranches-file", tranch_file] else: params = ["-T", "ApplyRecalibration", "--input", in_file, "--out", tx_out_file, "--recal_file", recal_file, "--tranches_file", tranch_file] params += ["-R", ref_file, "--mode", filter_type] resources = config_utils.get_resources("gatk_apply_recalibration", data["config"]) opts = resources.get("options", []) if not opts: if gatk_type == "gatk4": opts += ["--truth-sensitivity-filter-level", sensitivity_cutoff] else: opts += ["--ts_filter_level", sensitivity_cutoff] params += opts broad_runner.run_gatk(params) return out_file def _get_training_data(vrn_files): """Retrieve training data, returning an empty set of information if not available. """ out = {"SNP": [], "INDEL": []} # SNPs for name, train_info in [("train_hapmap", "known=false,training=true,truth=true,prior=15.0"), ("train_omni", "known=false,training=true,truth=true,prior=12.0"), ("train_1000g", "known=false,training=true,truth=false,prior=10.0"), ("dbsnp", "known=true,training=false,truth=false,prior=2.0")]: if name not in vrn_files: return {} else: out["SNP"].append((name.replace("train_", ""), train_info, vrn_files[name])) # Indels if "train_indels" in vrn_files: out["INDEL"].append(("mills", "known=true,training=true,truth=true,prior=12.0", vrn_files["train_indels"])) else: return {} return out def _have_training_data(vrn_files): return len(_get_training_data(vrn_files)) > 0 def _get_vqsr_training(filter_type, vrn_files, gatk_type): """Return parameters for VQSR training, handling SNPs and Indels. """ params = [] for name, train_info, fname in _get_training_data(vrn_files)[filter_type]: if gatk_type == "gatk4": params.extend(["--resource:%s,%s" % (name, train_info), fname]) if filter_type == "INDEL": params.extend(["--max-gaussians", "4"]) else: params.extend(["-resource:%s,VCF,%s" % (name, train_info), fname]) if filter_type == "INDEL": params.extend(["--maxGaussians", "4"]) return params def _get_vqsr_annotations(filter_type, data): """Retrieve appropriate annotations to use for VQSR based on filter type. Issues reported with MQ and bwa-mem quality distribution, results in intermittent failures to use VQSR: http://gatkforums.broadinstitute.org/discussion/4425/variant-recalibration-failing http://gatkforums.broadinstitute.org/discussion/4248/variantrecalibrator-removing-all-snps-from-the-training-set """ if filter_type == "SNP": # MQ, MQRankSum anns = ["QD", "FS", "ReadPosRankSum", "SOR"] else: assert filter_type == "INDEL" # MQRankSum anns = ["QD", "FS", "ReadPosRankSum", "SOR"] if dd.get_coverage_interval(data) == "genome": anns += ["DP"] return anns def _run_vqsr(in_file, ref_file, vrn_files, sensitivity_cutoff, filter_type, data): """Run variant quality score recalibration. """ cutoffs = ["100.0", "99.99", "99.98", "99.97", "99.96", "99.95", "99.94", "99.93", "99.92", "99.91", "99.9", "99.8", "99.7", "99.6", "99.5", "99.0", "98.0", "90.0"] if sensitivity_cutoff not in cutoffs: cutoffs.append(sensitivity_cutoff) cutoffs.sort() broad_runner = broad.runner_from_config(data["config"]) gatk_type = broad_runner.gatk_type() base = utils.splitext_plus(in_file)[0] recal_file = ("%s-vqsrrecal.vcf.gz" % base) if gatk_type == "gatk4" else ("%s.recal" % base) tranches_file = "%s.tranches" % base plot_file = "%s-plots.R" % base if not utils.file_exists(recal_file): with file_transaction(data, recal_file, tranches_file, plot_file) as (tx_recal, tx_tranches, tx_plot_file): params = ["-T", "VariantRecalibrator", "-R", ref_file, "--mode", filter_type] if gatk_type == "gatk4": params += ["--variant", in_file, "--output", tx_recal, "--tranches-file", tx_tranches, "--rscript-file", tx_plot_file] else: params += ["--input", in_file, "--recal_file", tx_recal, "--tranches_file", tx_tranches, "--rscript_file", tx_plot_file] params += _get_vqsr_training(filter_type, vrn_files, gatk_type) resources = config_utils.get_resources("gatk_variant_recalibrator", data["config"]) opts = resources.get("options", []) if not opts: for cutoff in cutoffs: opts += ["-tranche", str(cutoff)] for a in _get_vqsr_annotations(filter_type, data): opts += ["-an", a] params += opts cores = dd.get_cores(data) memscale = {"magnitude": 0.9 * cores, "direction": "increase"} if cores > 1 else None try: broad_runner.new_resources("gatk-vqsr") broad_runner.run_gatk(params, log_error=False, memscale=memscale, parallel_gc=True) except: # Can fail to run if not enough values are present to train. return None, None if gatk_type == "gatk4": vcfutils.bgzip_and_index(recal_file, data["config"]) return recal_file, tranches_file # ## SNP and indel specific variant filtration def _already_cutoff_filtered(in_file, filter_type): """Check if we have a pre-existing cutoff-based filter file from previous VQSR failure. """ filter_file = "%s-filter%s.vcf.gz" % (utils.splitext_plus(in_file)[0], filter_type) return utils.file_exists(filter_file) def _variant_filtration(in_file, ref_file, vrn_files, data, filter_type, hard_filter_fn): """Filter SNP and indel variant calls using GATK best practice recommendations. Use cutoff-based soft filters if configuration indicates too little data or already finished a cutoff-based filtering step, otherwise try VQSR. """ # Algorithms multiplied by number of input files to check for large enough sample sizes algs = [data["config"]["algorithm"]] * len(data.get("vrn_files", [1])) if (not config_utils.use_vqsr(algs, in_file) or _already_cutoff_filtered(in_file, filter_type)): logger.info("Skipping VQSR, using cutoff-based filers: we don't have whole genome input data") return hard_filter_fn(in_file, data) elif not _have_training_data(vrn_files): logger.info("Skipping VQSR, using cutoff-based filers: genome build does not have sufficient training data") return hard_filter_fn(in_file, data) else: sensitivities = {"INDEL": "98.0", "SNP": "99.97"} recal_file, tranches_file = _run_vqsr(in_file, ref_file, vrn_files, sensitivities[filter_type], filter_type, data) if recal_file is None: # VQSR failed logger.info("VQSR failed due to lack of training data. Using cutoff-based soft filtering.") return hard_filter_fn(in_file, data) else: return _apply_vqsr(in_file, ref_file, recal_file, tranches_file, sensitivities[filter_type], filter_type, data) def includes_missingalt(data): """ As of GATK 4.1.0.0, variants with missing alts are generated (see https://github.com/broadinstitute/gatk/issues/5650) """ MISSINGALT_VERSION = LooseVersion("4.1.0.0") version = LooseVersion(broad.get_gatk_version(config=dd.get_config(data))) try: return version >= MISSINGALT_VERSION except TypeError: logger.error(f"LooseVersion failing with {version} as the detected version.") sys.exit(1) def gatk_remove_missingalt(in_file, data): """ GATK 4.1.0.0 outputs variants that have missing ALTs, which breaks downstream tools, this filters those out. """ base = in_file.split('.vcf.gz')[0] out_file = "%s-nomissingalt%s" % (base, '.vcf.gz') if utils.file_exists(out_file): return out_file no_gzip_out = out_file.replace(".vcf.gz", ".vcf") with file_transaction(no_gzip_out) as tx_out_file: with utils.open_gzipsafe(in_file) as in_handle, open(tx_out_file, "w") as out_handle: for line in in_handle: line = remove_missingalt(line) if line: out_handle.write(line) return vcfutils.bgzip_and_index(no_gzip_out, data["config"]) def remove_missingalt(line): """Remove lines that are missing an alternative allele. During cleanup of extra alleles, bcftools has an issue in complicated cases with duplicate alleles and will end up stripping all alternative alleles. This removes those lines to avoid issues downstream. """ if not line.startswith("#"): parts = line.split("\t") if parts[4] == ".": return None return line bcbio-nextgen-1.2.9/bcbio/variation/gatkjoint.py000066400000000000000000000222431415626112400216720ustar00rootroot00000000000000"""Perform joint genotyping using GATK HaplotypeCaller with gVCF inputs. For GATK4, merges into a shared database using GenomicsDBImport. For GATK3 handles merging of large batch sizes using CombineGVCFs. For both, follows this with joint variant calling using GenotypeGVCFs. """ import math import os import shutil import toolz as tz import tempfile from bcbio import broad, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from bcbio.variation import bamprep, ploidy, vcfutils def run_region(data, region, vrn_files, out_file): """Perform variant calling on gVCF inputs in a specific genomic region. """ broad_runner = broad.runner_from_config(data["config"]) if broad_runner.gatk_type() == "gatk4": genomics_db = _run_genomicsdb_import(vrn_files, region, out_file, data) return _run_genotype_gvcfs_genomicsdb(genomics_db, region, out_file, data) else: vrn_files = _batch_gvcfs(data, region, vrn_files, dd.get_ref_file(data), out_file) return _run_genotype_gvcfs_gatk3(data, region, vrn_files, dd.get_ref_file(data), out_file) # ## gVCF joint calling -- GATK4 def _run_genomicsdb_import(vrn_files, region, out_file, data): """Create a GenomicsDB reference for all the variation files: GATK4. Not yet tested as scale, need to explore --batchSize to reduce memory usage if needed. Does not support transactional directories yet, since GenomicsDB databases cannot be moved to new locations. We try to identify half-finished databases and restart: https://gatkforums.broadinstitute.org/gatk/discussion/10061/using-genomicsdbimport-to-prepare-gvcfs-for-input-to-genotypegvcfs-in-gatk4 Known issue -- Genomics DB workspace path core dumps on longer paths: (std::string::compare(char const*)) """ out_dir = "%s_genomicsdb" % utils.splitext_plus(out_file)[0] if not os.path.exists(out_dir) or _incomplete_genomicsdb(out_dir): if os.path.exists(out_dir): shutil.rmtree(out_dir) with utils.chdir(os.path.dirname(out_file)): with file_transaction(data, out_dir) as tx_out_dir: broad_runner = broad.runner_from_config(data["config"]) cores = dd.get_cores(data) params = ["-T", "GenomicsDBImport", "--reader-threads", str(cores), "--genomicsdb-workspace-path", os.path.relpath(out_dir, os.getcwd()), "-L", bamprep.region_to_gatk(region)] for vrn_file in vrn_files: vcfutils.bgzip_and_index(vrn_file, data["config"]) samplemap = _create_samplemap_file(vrn_files) params += ["--sample-name-map", samplemap] resources = config_utils.get_resources("GenomicsDBImport", data["config"]) if resources and resources.get("options", []): params += resources.get("options", []) # For large inputs, reduce memory usage by batching # https://github.com/bcbio/bcbio-nextgen/issues/2852 if len(vrn_files) > 200: params += ["--batch-size", "50"] memscale = {"magnitude": 0.9 * cores, "direction": "increase"} if cores > 1 else None broad_runner.run_gatk(params, memscale=memscale) return out_dir def _create_samplemap_file(vrn_files): tf = tempfile.NamedTemporaryFile(suffix=".tsv", delete=False) samplemap = tf.name samplenames = [vcfutils.get_samples(vrn_file)[0] for vrn_file in vrn_files] with open(samplemap, "w") as out_handle: for samplename, vrn_file in zip(samplenames, vrn_files): print(f"{samplename}\t{vrn_file}", file=out_handle) return samplemap def _incomplete_genomicsdb(dbdir): """Check if a GenomicsDB output is incomplete and we should regenerate. Works around current inability to move GenomicsDB outputs and support transactional directories. """ for test_file in ["callset.json", "vidmap.json", "genomicsdb_array/genomicsdb_meta.json"]: if not os.path.exists(os.path.join(dbdir, test_file)): return True return False def _run_genotype_gvcfs_genomicsdb(genomics_db, region, out_file, data): """GenotypeGVCFs from a merged GenomicsDB input: GATK4. ropts += [str(x) for x in resources.get("options", [])] No core scaling -- not yet supported in GATK4. """ if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: broad_runner = broad.runner_from_config(data["config"]) # see issue https://github.com/bcbio/bcbio-nextgen/issues/3263 # for why --genomicsdb-use-vcf-codec is necessary params = ["-T", "GenotypeGVCFs", "--variant", "gendb://%s" % genomics_db, "-R", dd.get_ref_file(data), "--output", tx_out_file, "-L", bamprep.region_to_gatk(region)] params += ["-ploidy", str(ploidy.get_ploidy([data], region))] # Avoid slow genotyping runtimes with improved quality score calculation in GATK4 # https://gatkforums.broadinstitute.org/gatk/discussion/11471/performance-troubleshooting-tips-for-genotypegvcfs/p1 resources = config_utils.get_resources("gatk", data["config"]) params += [str(x) for x in resources.get("options", [])] cores = dd.get_cores(data) memscale = {"magnitude": 0.9 * cores, "direction": "increase"} if cores > 1 else None broad_runner.run_gatk(params, memscale=memscale) return vcfutils.bgzip_and_index(out_file, data["config"]) # ## gVCF joint genotype calling -- GATK3 def _run_genotype_gvcfs_gatk3(data, region, vrn_files, ref_file, out_file): """Performs genotyping of gVCFs into final VCF files. """ if not utils.file_exists(out_file): broad_runner = broad.runner_from_config(data["config"]) with file_transaction(data, out_file) as tx_out_file: assoc_files = tz.get_in(("genome_resources", "variation"), data, {}) if not assoc_files: assoc_files = {} params = ["-T", "GenotypeGVCFs", "-R", ref_file, "-o", tx_out_file, "-L", bamprep.region_to_gatk(region), "--max_alternate_alleles", "4"] for vrn_file in vrn_files: params += ["--variant", vrn_file] if assoc_files.get("dbsnp"): params += ["--dbsnp", assoc_files["dbsnp"]] broad_runner.new_resources("gatk-haplotype") cores = dd.get_cores(data) if cores > 1: # GATK performs poorly with memory usage when parallelizing # with a large number of cores but makes use of extra memory, # so we cap at 6 cores. # See issue #1565 for discussion # Recent GATK 3.x versions also have race conditions with multiple # threads, so limit to 1 and keep memory available # https://gatkforums.broadinstitute.org/wdl/discussion/8718/concurrentmodificationexception-in-gatk-3-7-genotypegvcfs # params += ["-nt", str(min(6, cores))] memscale = {"magnitude": 0.9 * cores, "direction": "increase"} else: memscale = None broad_runner.run_gatk(params, memscale=memscale, parallel_gc=True) return vcfutils.bgzip_and_index(out_file, data["config"]) # ## gVCF batching def _batch_gvcfs(data, region, vrn_files, ref_file, out_file=None): """Perform batching of gVCF files if above recommended input count. """ if out_file is None: out_file = vrn_files[0] # group to get below the maximum batch size, using 200 as the baseline max_batch = int(dd.get_joint_group_size(data)) if len(vrn_files) > max_batch: out = [] num_batches = int(math.ceil(float(len(vrn_files)) / max_batch)) for i, batch_vrn_files in enumerate(tz.partition_all(num_batches, vrn_files)): base, ext = utils.splitext_plus(out_file) batch_out_file = "%s-b%s%s" % (base, i, ext) out.append(run_combine_gvcfs(batch_vrn_files, region, ref_file, batch_out_file, data)) return _batch_gvcfs(data, region, out, ref_file) else: return vrn_files def run_combine_gvcfs(vrn_files, region, ref_file, out_file, data): if not utils.file_exists(out_file): broad_runner = broad.runner_from_config(data["config"]) with file_transaction(data, out_file) as tx_out_file: params = ["-T", "CombineGVCFs", "-R", ref_file, "-o", tx_out_file] if region: params += ["-L", bamprep.region_to_gatk(region)] for vrn_file in vrn_files: params += ["--variant", vrn_file] cores = dd.get_cores(data) memscale = {"magnitude": 0.9 * cores, "direction": "increase"} if cores > 1 else None broad_runner.new_resources("gatk-haplotype") broad_runner.run_gatk(params, memscale=memscale, parallel_gc=True) return vcfutils.bgzip_and_index(out_file, data["config"]) bcbio-nextgen-1.2.9/bcbio/variation/genotype.py000066400000000000000000000531161415626112400215350ustar00rootroot00000000000000"""High level parallel SNP and indel calling using multiple variant callers. """ import os import collections import copy import pprint import six import toolz as tz from bcbio import bam, utils from bcbio.cwl import cwlutils from bcbio.distributed.split import (grouped_parallel_split_combine, parallel_split_combine) from bcbio.distributed import multi as dmulti from bcbio.pipeline import datadict as dd from bcbio.pipeline import region as pregion from bcbio.pipeline import shared as pshared from bcbio.variation import (gatk, gatkfilter, germline, multi, ploidy, vcfutils, vfilter) # ## Variant filtration -- shared functionality def variant_filtration(call_file, ref_file, vrn_files, data, items): """Filter variant calls using Variant Quality Score Recalibration. Newer GATK with Haplotype calling has combined SNP/indel filtering. """ caller = data["config"]["algorithm"].get("variantcaller") if "gvcf" not in dd.get_tools_on(data): call_file = ploidy.filter_vcf_by_sex(call_file, items) if caller in ["freebayes"]: return vfilter.freebayes(call_file, ref_file, vrn_files, data) elif caller in ["platypus"]: return vfilter.platypus(call_file, data) elif caller in ["samtools"]: return vfilter.samtools(call_file, data) elif caller in ["gatk", "gatk-haplotype", "haplotyper"]: if dd.get_analysis(data).lower().find("rna-seq") >= 0: from bcbio.rnaseq import variation as rnaseq_variation return rnaseq_variation.gatk_filter_rnaseq(call_file, data) else: return gatkfilter.run(call_file, ref_file, vrn_files, data) # no additional filtration for callers that filter as part of call process else: return call_file # ## High level functionality to run genotyping in parallel def get_variantcaller(data, key="variantcaller", default=None, require_bam=True): if not require_bam or data.get("align_bam"): return tz.get_in(["config", "algorithm", key], data, default) def combine_multiple_callers(samples): """Collapse together variant calls from multiple approaches into single data item with `variants`. """ by_bam = collections.OrderedDict() for data in (x[0] for x in samples): work_bam = tz.get_in(("combine", "work_bam", "out"), data, data.get("align_bam")) # For pre-computed VCF inputs, we don't have BAM files if not work_bam: work_bam = dd.get_sample_name(data) jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), data) variantcaller = get_variantcaller(data) key = (multi.get_batch_for_key(data), work_bam) if key not in by_bam: by_bam[key] = [] by_bam[key].append((variantcaller, jointcaller, data)) out = [] for callgroup in by_bam.values(): ready_calls = [] for variantcaller, jointcaller, data in callgroup: if variantcaller: cur = data.get("vrn_file_plus", {}) cur.update({"variantcaller": variantcaller, "vrn_file": data.get("vrn_file_orig") if jointcaller else data.get("vrn_file"), "vrn_file_batch": data.get("vrn_file_batch") if not jointcaller else None, "vrn_stats": data.get("vrn_stats"), "validate": data.get("validate") if not jointcaller else None}) if jointcaller: cur["population"] = False ready_calls.append(cur) if jointcaller: cur = {"variantcaller": jointcaller, "vrn_file": data.get("vrn_file"), "vrn_file_batch": data.get("vrn_file_batch"), "validate": data.get("validate"), "do_upload": False} if not variantcaller: cur["population"] = {"vcf": data.get("vrn_file")} ready_calls.append(cur) if not jointcaller and not variantcaller: ready_calls.append({"variantcaller": "precalled", "vrn_file": data.get("vrn_file"), "validate": data.get("validate"), "do_upload": False}) final = callgroup[0][-1] def orig_variantcaller_order(x): try: return final["config"]["algorithm"]["orig_variantcaller"].index(x["variantcaller"]) except ValueError: return final["config"]["algorithm"]["orig_jointcaller"].index(x["variantcaller"]) if len(ready_calls) > 1 and "orig_variantcaller" in final["config"]["algorithm"]: final["variants"] = sorted(ready_calls, key=orig_variantcaller_order) final["config"]["algorithm"]["variantcaller"] = final["config"]["algorithm"].pop("orig_variantcaller") if "orig_jointcaller" in final["config"]["algorithm"]: final["config"]["algorithm"]["jointcaller"] = final["config"]["algorithm"].pop("orig_jointcaller") else: final["variants"] = ready_calls final.pop("vrn_file_batch", None) final.pop("vrn_file_orig", None) final.pop("vrn_file_plus", None) final.pop("vrn_stats", None) out.append([final]) return out def _split_by_ready_regions(ext, file_key, dir_ext_fn): """Organize splits based on regions generated by parallel_prep_region. Sort splits so largest regions analyzed first, avoiding potentially lagging runs at end. """ def _sort_by_size(region_w_bams): region, _ = region_w_bams _, start, end = region return end - start def _assign_bams_to_regions(data): """Ensure BAMs aligned with input regions, either global or individual. """ for i, region in enumerate(data["region"]): work_bams = [] for xs in data["region_bams"]: if len(xs) == 1: work_bams.append(xs[0]) else: work_bams.append(xs[i]) for work_bam in work_bams: assert os.path.exists(work_bam), work_bam yield region, work_bams def _do_work(data): if "region" in data: name = data["group"][0] if "group" in data else data["description"] out_dir = os.path.join(data["dirs"]["work"], dir_ext_fn(data)) out_file = os.path.join(out_dir, "%s%s" % (name, ext)) assert isinstance(data["region"], (list, tuple)) out_parts = [] for r, work_bams in sorted(_assign_bams_to_regions(data), key=_sort_by_size, reverse=True): out_region_dir = os.path.join(out_dir, r[0]) out_region_file = os.path.join(out_region_dir, "%s-%s%s" % (name, pregion.to_safestr(r), ext)) out_parts.append((r, work_bams, out_region_file)) return out_file, out_parts else: return None, [] return _do_work def _collapse_by_bam_variantcaller(samples): """Collapse regions to a single representative by BAM input, variant caller and batch. """ by_bam = collections.OrderedDict() for data in (x[0] for x in samples): work_bam = utils.get_in(data, ("combine", "work_bam", "out"), data.get("align_bam")) variantcaller = get_variantcaller(data) if isinstance(work_bam, list): work_bam = tuple(work_bam) key = (multi.get_batch_for_key(data), work_bam, variantcaller) try: by_bam[key].append(data) except KeyError: by_bam[key] = [data] out = [] for grouped_data in by_bam.values(): cur = grouped_data[0] cur.pop("region", None) region_bams = cur.pop("region_bams", None) if region_bams and len(region_bams[0]) > 1: cur.pop("work_bam", None) out.append([cur]) return out def _dup_samples_by_variantcaller(samples, require_bam=True): """Prepare samples by variant callers, duplicating any with multiple callers. """ samples = [utils.to_single_data(x) for x in samples] samples = germline.split_somatic(samples) to_process = [] extras = [] for data in samples: added = False for i, add in enumerate(handle_multiple_callers(data, "variantcaller", require_bam=require_bam)): added = True add = dd.set_variantcaller_order(add, i) to_process.append([add]) if not added: data = _handle_precalled(data) data = dd.set_variantcaller_order(data, 0) extras.append([data]) return to_process, extras def parallel_variantcall_region(samples, run_parallel): """Perform variant calling and post-analysis on samples by region. """ to_process, extras = _dup_samples_by_variantcaller(samples) split_fn = _split_by_ready_regions(".vcf.gz", "work_bam", get_variantcaller) samples = _collapse_by_bam_variantcaller( grouped_parallel_split_combine(to_process, split_fn, multi.group_batches, run_parallel, "variantcall_sample", "concat_variant_files", "vrn_file", ["region", "sam_ref", "config"])) return extras + samples def vc_output_record(samples): """Prepare output record from variant calling to feed into downstream analysis. Prep work handles reformatting so we return generated dictionaries. For any shared keys that are calculated only once for a batch, like variant calls for the batch, we assign to every sample. """ shared_keys = [["vrn_file"], ["validate", "summary"], ["validate", "tp"], ["validate", "fp"], ["validate", "fn"]] raw = cwlutils.samples_to_records([utils.to_single_data(x) for x in samples]) shared = {} for key in shared_keys: cur = list(set([x for x in [tz.get_in(key, d) for d in raw] if x])) if len(cur) > 0: assert len(cur) == 1, (key, cur) shared[tuple(key)] = cur[0] else: shared[tuple(key)] = None out = [] for d in raw: for key, val in shared.items(): d = tz.update_in(d, key, lambda x: val) out.append([d]) return out def is_joint(data): return "gvcf" in dd.get_tools_on(data) or dd.get_jointcaller(data) def batch_for_variantcall(samples): """Prepare a set of samples for parallel variant calling. CWL input target that groups samples into batches and variant callers for parallel processing. If doing joint calling, with `tools_on: [gvcf]`, split the sample into individuals instead of combining into a batch. """ sample_order = [dd.get_sample_name(utils.to_single_data(x)) for x in samples] to_process, extras = _dup_samples_by_variantcaller(samples, require_bam=False) batch_groups = collections.defaultdict(list) to_process = [utils.to_single_data(x) for x in to_process] for data in cwlutils.samples_to_records(to_process): vc = get_variantcaller(data, require_bam=False) batches = dd.get_batches(data) or dd.get_sample_name(data) if not isinstance(batches, (list, tuple)): batches = [batches] for b in batches: batch_groups[(b, vc)].append(utils.deepish_copy(data)) batches = [] for cur_group in batch_groups.values(): joint_calling = any([is_joint(d) for d in cur_group]) if joint_calling: for d in cur_group: batches.append([d]) else: batches.append(cur_group) def by_original_order(xs): return (min([sample_order.index(dd.get_sample_name(x)) for x in xs]), min([dd.get_variantcaller_order(x) for x in xs])) return sorted(batches + extras, key=by_original_order) def _handle_precalled(data): """Copy in external pre-called variants fed into analysis. Symlinks for non-CWL runs where we want to ensure VCF present in a local directory. """ if data.get("vrn_file") and not cwlutils.is_cwl_run(data): vrn_file = data["vrn_file"] if isinstance(vrn_file, (list, tuple)): assert len(vrn_file) == 1 vrn_file = vrn_file[0] precalled_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(data), "precalled")) ext = utils.splitext_plus(vrn_file)[-1] orig_file = os.path.abspath(vrn_file) our_vrn_file = os.path.join(precalled_dir, "%s-precalled%s" % (dd.get_sample_name(data), ext)) utils.copy_plus(orig_file, our_vrn_file) data["vrn_file"] = our_vrn_file return data def handle_multiple_callers(data, key, default=None, require_bam=True): """Split samples that potentially require multiple variant calling approaches. """ callers = get_variantcaller(data, key, default, require_bam=require_bam) if isinstance(callers, six.string_types): return [data] elif not callers: return [] else: out = [] for caller in callers: base = copy.deepcopy(data) if not base["config"]["algorithm"].get("orig_%s" % key): base["config"]["algorithm"]["orig_%s" % key] = \ base["config"]["algorithm"][key] base["config"]["algorithm"][key] = caller # if splitting by variant caller, also split by jointcaller if key == "variantcaller": jcallers = get_variantcaller(data, "jointcaller", []) if isinstance(jcallers, six.string_types): jcallers = [jcallers] if jcallers: base["config"]["algorithm"]["orig_jointcaller"] = jcallers jcallers = [x for x in jcallers if x.startswith(caller)] if jcallers: base["config"]["algorithm"]["jointcaller"] = jcallers[0] else: base["config"]["algorithm"]["jointcaller"] = False out.append(base) return out # Avoid use of multicore GATK HaplotypeCallerSpark due to bugs in gVCF output # during joint calling Intermittent failures where we don't produce correct headers # https://github.com/broadinstitute/gatk/issues/4821 # "gatk-haplotype" SUPPORT_MULTICORE = ["strelka2", "haplotyper", "tnhaplotyper", "tnscope", "deepvariant", "pisces", "octopus", "smcounter2"] def get_variantcallers(): from bcbio.variation import (freebayes, cortex, samtools, varscan, mutect, mutect2, octopus, pisces, platypus, scalpel, sentieon, strelka2, vardict, qsnp, deepvariant, smcounter2) return {"gatk": gatk.unified_genotyper, "gatk-haplotype": gatk.haplotype_caller, "mutect2": mutect2.mutect2_caller, "freebayes": freebayes.run_freebayes, "cortex": cortex.run_cortex, "deepvariant": deepvariant.run, "samtools": samtools.run_samtools, "varscan": varscan.run_varscan, "mutect": mutect.mutect_caller, "octopus": octopus.run, "pisces": pisces.run, "platypus": platypus.run, "scalpel": scalpel.run_scalpel, "smcounter2": smcounter2.run, "strelka2": strelka2.run, "vardict": vardict.run_vardict, "vardict-java": vardict.run_vardict, "vardict-perl": vardict.run_vardict, "haplotyper": sentieon.run_haplotyper, "tnhaplotyper": sentieon.run_tnhaplotyper, "tnscope": sentieon.run_tnscope, "qsnp": qsnp.run_qsnp} def variantcall_sample(data, region=None, align_bams=None, out_file=None): """Parallel entry point for doing genotyping of a region of a sample. """ if out_file is None or not os.path.exists(out_file) or not os.path.lexists(out_file): utils.safe_makedir(os.path.dirname(out_file)) ref_file = dd.get_ref_file(data) config = data["config"] caller_fns = get_variantcallers() caller_fn = caller_fns[config["algorithm"].get("variantcaller")] if len(align_bams) == 1: items = [data] else: items = multi.get_orig_items(data) assert len(items) == len(align_bams) assoc_files = tz.get_in(("genome_resources", "variation"), data, {}) if not assoc_files: assoc_files = {} for bam_file in align_bams: bam.index(bam_file, data["config"], check_timestamp=False) out_file = caller_fn(align_bams, items, ref_file, assoc_files, region, out_file) if region: data["region"] = region data["vrn_file"] = out_file return [data] def concat_batch_variantcalls(items, region_block=True, skip_jointcheck=False): """CWL entry point: combine variant calls from regions into single VCF. """ items = [utils.to_single_data(x) for x in items] batch_name = _get_batch_name(items, skip_jointcheck) variantcaller = _get_batch_variantcaller(items) # Pre-called input variant files if not variantcaller and all(d.get("vrn_file") for d in items): return {"vrn_file": items[0]["vrn_file"]} out_file = os.path.join(dd.get_work_dir(items[0]), variantcaller, "%s.vcf.gz" % (batch_name)) utils.safe_makedir(os.path.dirname(out_file)) if region_block: regions = [_region_to_coords(rs[0]) for rs in items[0]["region_block"]] else: regions = [_region_to_coords(r) for r in items[0]["region"]] vrn_file_regions = items[0]["vrn_file_region"] out_file = vcfutils.concat_variant_files(vrn_file_regions, out_file, regions, dd.get_ref_file(items[0]), items[0]["config"]) return {"vrn_file": out_file} def _region_to_coords(region): """Split GATK region specification (chr1:1-10) into a tuple of chrom, start, end """ chrom, coords = region.split(":") start, end = coords.split("-") return (chrom, int(start), int(end)) def _get_batch_name(items, skip_jointcheck=False): """Retrieve the shared batch name for a group of items. """ batch_names = collections.defaultdict(int) has_joint = any([is_joint(d) for d in items]) for data in items: if has_joint and not skip_jointcheck: batches = dd.get_sample_name(data) else: batches = dd.get_batches(data) or dd.get_sample_name(data) if not isinstance(batches, (list, tuple)): batches = [batches] for b in batches: batch_names[b] += 1 return sorted(batch_names.items(), key=lambda x: x[-1], reverse=True)[0][0] def _get_batch_variantcaller(items): variantcaller = [vc for vc in list(set([get_variantcaller(x, require_bam=False) for x in items])) if vc] if not variantcaller: return None assert len(variantcaller) == 1, "%s\n%s" % (variantcaller, pprint.pformat(items)) return variantcaller[0] def variantcall_batch_region(items): """CWL entry point: variant call a batch of samples in a block of regions. """ items = [utils.to_single_data(x) for x in items] align_bams = [dd.get_align_bam(x) for x in items] variantcaller = _get_batch_variantcaller(items) region_blocks = list(set([tuple(x.get("region_block")) for x in items if "region_block" in x])) assert len(region_blocks) == 1, region_blocks region_block = region_blocks[0] # Pre-called input variant files if not variantcaller and all(d.get("vrn_file") for d in items): return {"vrn_file_region": None, "region_block": region_block} caller_fn = get_variantcallers()[variantcaller] assoc_files = tz.get_in(("genome_resources", "variation"), items[0], {}) region = _region_to_coords(region_block[0]) chrom, start, end = region region_str = "_".join(str(x) for x in region) batch_name = _get_batch_name(items) out_file = os.path.join(dd.get_work_dir(items[0]), variantcaller, chrom, "%s-%s-block.vcf.gz" % (batch_name, region_str)) utils.safe_makedir(os.path.dirname(out_file)) with pshared.bedtools_tmpdir(items[0]): if variantcaller in SUPPORT_MULTICORE: call_file = caller_fn(align_bams, items, dd.get_ref_file(items[0]), assoc_files, [_region_to_coords(r) for r in region_block], out_file) else: call_file = _run_variantcall_batch_multicore(items, region_block, out_file) return {"vrn_file_region": call_file, "region_block": region_block} def _run_variantcall_batch_multicore(items, regions, final_file): """Run variant calling on a batch of items using multiple cores. """ batch_name = _get_batch_name(items) variantcaller = _get_batch_variantcaller(items) work_bams = [dd.get_work_bam(d) or dd.get_align_bam(d) for d in items] def split_fn(data): out = [] for region in regions: region = _region_to_coords(region) chrom, start, end = region region_str = "_".join(str(x) for x in region) out_file = os.path.join(dd.get_work_dir(items[0]), variantcaller, chrom, "%s-%s.vcf.gz" % (batch_name, region_str)) out.append((region, work_bams, out_file)) return final_file, out parallel = {"type": "local", "num_jobs": dd.get_num_cores(items[0]), "cores_per_job": 1} run_parallel = dmulti.runner(parallel, items[0]["config"]) to_run = copy.deepcopy(items[0]) to_run["sam_ref"] = dd.get_ref_file(to_run) to_run["group_orig"] = items parallel_split_combine([[to_run]], split_fn, run_parallel, "variantcall_sample", "concat_variant_files", "vrn_file", ["region", "sam_ref", "config"]) return final_file bcbio-nextgen-1.2.9/bcbio/variation/germline.py000066400000000000000000000261041415626112400215020ustar00rootroot00000000000000"""Extract germline calls from tumor/normal pairs into separate VCF file. In tumor/normal pipelines, pre-existing germline calls are often of interest in addition to somatic variants. Different callers distinguish germline calls in different ways. This unifies the output and extracts into a separate VCF with germline calls included. """ import os import contextlib from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import vcfutils cyvcf2 = utils.LazyImport("cyvcf2") def split_somatic(items): """Split somatic batches, adding a germline target. Enables separate germline calling of samples using shared alignments. """ items = [_clean_flat_variantcaller(x) for x in items] somatic_groups, somatic, non_somatic = vcfutils.somatic_batches(items) # extract germline samples to run from normals in tumor/normal pairs germline_added = set([]) germline = [] for somatic_group in somatic_groups: paired = vcfutils.get_paired(somatic_group) if paired and paired.normal_data: cur = utils.deepish_copy(paired.normal_data) vc = dd.get_variantcaller(cur) if isinstance(vc, dict) and "germline" in vc: if cur["description"] not in germline_added: germline_added.add(cur["description"]) cur["rgnames"]["sample"] = cur["description"] cur["metadata"]["batch"] = "%s-germline" % cur["description"] cur["metadata"]["phenotype"] = "germline" cur = remove_align_qc_tools(cur) cur["config"]["algorithm"]["variantcaller"] = vc["germline"] germline.append(cur) # Fix variantcalling specification for only somatic targets somatic_out = [] for data in somatic: vc = dd.get_variantcaller(data) if isinstance(vc, dict) and "somatic" in vc: data["config"]["algorithm"]["variantcaller"] = vc["somatic"] somatic_out.append(data) return non_somatic + somatic_out + germline def _clean_flat_variantcaller(data): """Convert flattened dictionary from CWL representation into dictionary. CWL flattens somatic/germline tags into a set of strings, which we reconstitute as a dictionary. """ vc = dd.get_variantcaller(data) if isinstance(vc, (list, tuple)) and all([x.count(":") == 1 for x in vc]): out = {} for v in vc: k, v = v.split(":") if k in out: out[k].append(v) else: out[k] = [v] data = dd.set_variantcaller(data, out) return data def remove_align_qc_tools(data): """Remove alignment based QC tools we don't need for data replicates. When we do multiple variant calling on a sample file (somatic/germline), avoid re-running QC. """ align_qc = set(["qsignature", "coverage", "picard", "samtools", "fastqc"]) data["config"]["algorithm"]["qc"] = [t for t in dd.get_algorithm_qc(data) if t not in align_qc] return data def extract(data, items, out_dir=None): """Extract germline calls for the given sample, if tumor only. """ if vcfutils.get_paired_phenotype(data): if len(items) == 1: germline_vcf = _remove_prioritization(data["vrn_file"], data, out_dir) germline_vcf = vcfutils.bgzip_and_index(germline_vcf, data["config"]) data["vrn_file_plus"] = {"germline": germline_vcf} return data def filter_to_pass_and_reject(in_file, paired, out_dir=None): """Filter VCF to only those with a strict PASS/REJECT: somatic + germline. Removes low quality calls filtered but also labeled with REJECT. """ from bcbio.heterogeneity import bubbletree out_file = "%s-prfilter.vcf.gz" % utils.splitext_plus(in_file)[0] if out_dir: out_file = os.path.join(out_dir, os.path.basename(out_file)) if not utils.file_uptodate(out_file, in_file): with file_transaction(paired.tumor_data, out_file) as tx_out_file: max_depth = bubbletree.max_normal_germline_depth(in_file, bubbletree.PARAMS, paired) tx_out_plain = tx_out_file.replace(".vcf.gz", ".vcf") with contextlib.closing(cyvcf2.VCF(in_file)) as reader: reader = _add_db_to_header(reader) with contextlib.closing(cyvcf2.Writer(tx_out_plain, reader)) as writer: for rec in reader: filters = rec.FILTER.split(";") if rec.FILTER else [] other_filters = [x for x in filters if x not in ["PASS", ".", "REJECT"]] if len(other_filters) == 0 or bubbletree.is_info_germline(rec): # Germline, check if we should include based on frequencies if "REJECT" in filters or bubbletree.is_info_germline(rec): stats = bubbletree._is_possible_loh(rec, reader, bubbletree.PARAMS, paired, use_status=True, max_normal_depth=max_depth) if stats: rec.FILTER = "PASS" rec.INFO["DB"] = True writer.write_record(rec) # Somatic, always include else: writer.write_record(rec) vcfutils.bgzip_and_index(tx_out_plain, paired.tumor_data["config"]) return out_file def _add_db_to_header(reader): try: reader["DB"] except KeyError: reader.add_info_to_header({'ID': 'DB', 'Description': 'Likely germline variant', 'Type': 'Flag', 'Number': '0'}) return reader def fix_germline_samplename(in_file, sample_name, data): """Replace germline sample names, originally from normal BAM file. """ out_file = "%s-fixnames%s" % utils.splitext_plus(in_file) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: sample_file = "%s-samples.txt" % utils.splitext_plus(tx_out_file)[0] with open(sample_file, "w") as out_handle: out_handle.write("%s\n" % sample_name) cmd = ("bcftools reheader -s {sample_file} {in_file} -o {tx_out_file}") do.run(cmd.format(**locals()), "Fix germline samplename: %s" % sample_name) return vcfutils.bgzip_and_index(out_file, data["config"]) def _remove_prioritization(in_file, data, out_dir=None): """Remove tumor-only prioritization and return non-filtered calls. """ out_file = "%s-germline.vcf" % utils.splitext_plus(in_file)[0] if out_dir: out_file = os.path.join(out_dir, os.path.basename(out_file)) if not utils.file_uptodate(out_file, in_file) and not utils.file_uptodate(out_file + ".gz", in_file): with file_transaction(data, out_file) as tx_out_file: reader = cyvcf2.VCF(str(in_file)) reader.add_filter_to_header({'ID': 'Somatic', 'Description': 'Variant called as Somatic'}) # with open(tx_out_file, "w") as out_handle: # out_handle.write(reader.raw_header) with contextlib.closing(cyvcf2.Writer(tx_out_file, reader)) as writer: for rec in reader: rec = _update_prioritization_filters(rec) # out_handle.write(str(rec)) writer.write_record(rec) return out_file def _update_prioritization_filters(rec): rec = vcfutils.cyvcf_remove_filter(rec, "LowPriority") return _update_germline_filters(rec) def _extract_germline(in_file, data): """Extract germline calls non-somatic, non-filtered calls. """ out_file = "%s-germline.vcf" % utils.splitext_plus(in_file)[0] if not utils.file_uptodate(out_file, in_file) and not utils.file_uptodate(out_file + ".gz", in_file): with file_transaction(data, out_file) as tx_out_file: reader = cyvcf2.VCF(str(in_file)) reader.add_filter_to_header({'ID': 'Somatic', 'Description': 'Variant called as Somatic'}) #with contextlib.closing(cyvcf2.Writer(tx_out_file, reader)) as writer: with open(tx_out_file, "w") as out_handle: out_handle.write(reader.raw_header) for rec in reader: rec = _update_germline_filters(rec) out_handle.write(str(rec)) #writer.write_record(rec) return out_file def _update_germline_filters(rec): rec = _remove_germline_filter(rec, "REJECT") rec = _remove_germline_filter(rec, "germline_risk") rec = _add_somatic_filter(rec) return rec def _add_somatic_filter(rec): if _is_somatic(rec): return vcfutils.cyvcf_add_filter(rec, "Somatic") return rec def _remove_germline_filter(rec, name): """Check if germline based on STATUS/SS and REJECT flag. Handles VarDict, FreeBayes, MuTect, MuTect2 and VarScan. """ if _is_germline(rec): if rec.FILTER and name in rec.FILTER: return vcfutils.cyvcf_remove_filter(rec, name) elif not _is_somatic(rec): if rec.FILTER and name in rec.FILTER: return vcfutils.cyvcf_remove_filter(rec, name) return rec def _is_somatic(rec): """Handle somatic classifications from MuTect, MuTect2, VarDict and VarScan """ if _has_somatic_flag(rec): return True if _is_mutect2_somatic(rec): return True ss_flag = rec.INFO.get("SS") if ss_flag is not None: if str(ss_flag) == "2": return True status_flag = rec.INFO.get("STATUS") if status_flag is not None: if str(status_flag).lower() in ["somatic", "likelysomatic", "strongsomatic", "samplespecific"]: return True epr = rec.INFO.get("EPR", "").split(",") if epr and all([p == "pass" for p in epr]): return True return False def _has_somatic_flag(rec): try: rec.INFO["SOMATIC"] return True except KeyError: return False def _is_mutect2_somatic(rec): """MuTect2 does not use SOMATIC flag, instead using presence of tumor TLOD and PASS. """ return rec.INFO.get("TLOD") is not None and rec.FILTER is None def _is_germline(rec): """Handle somatic INFO classifications from MuTect, MuTect2, VarDict, VarScan and Octopus. """ if _has_somatic_flag(rec): return False if _is_mutect2_somatic(rec): return False ss_flag = rec.INFO.get("SS") if ss_flag is not None: if str(ss_flag) == "1": return True # Octopus, assessed for potentially being Germline and not flagged SOMATIC # https://github.com/luntergroup/octopus/wiki/Calling-models:-Cancer#qual-vs-pp pp = rec.INFO.get("PP") if pp and float(pp) / float(rec.QUAL) >= 0.5: return True status_flag = rec.INFO.get("STATUS") if status_flag is not None: if str(status_flag).lower() in ["germline", "likelyloh", "strongloh", "afdiff", "deletion"]: return True return False bcbio-nextgen-1.2.9/bcbio/variation/joint.py000066400000000000000000000263211415626112400210240ustar00rootroot00000000000000"""Joint variant calling with multiple samples: aka squaring off, or backfilling. Handles the N+1 problem of variant calling by combining and recalling samples previously calling individually (or in smaller batches). Recalls at all positions found variable in any of the input samples within each batch. Takes a general approach supporting GATK's incremental joint discovery (http://www.broadinstitute.org/gatk/guide/article?id=3893) and FreeBayes's N+1 approach (https://groups.google.com/d/msg/freebayes/-GK4zI6NsYY/Wpcp8nt_PVMJ) as implemented in bcbio.variation.recall (https://github.com/chapmanb/bcbio.variation.recall). """ import collections import math import os import pysam import toolz as tz from bcbio import broad, utils from bcbio.bam import ref from bcbio.distributed.split import grouped_parallel_split_combine from bcbio.pipeline import config_utils, region from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import bamprep, gatkjoint, genotype, multi SUPPORTED = {"general": ["freebayes", "platypus", "samtools"], "gatk": ["gatk-haplotype"], "gvcf": ["strelka2"], "sentieon": ["haplotyper"]} # ## CWL joint calling targets def batch_for_jointvc(items): batch_groups = collections.defaultdict(list) for data in [utils.to_single_data(x) for x in items]: vc = dd.get_variantcaller(data) if genotype.is_joint(data): batches = dd.get_batches(data) or dd.get_sample_name(data) if not isinstance(batches, (list, tuple)): batches = [batches] else: batches = [dd.get_sample_name(data)] for b in batches: data = utils.deepish_copy(data) data["vrn_file_gvcf"] = data["vrn_file"] batch_groups[(b, vc)].append(data) return list(batch_groups.values()) def run_jointvc(items): items = [utils.to_single_data(x) for x in items] data = items[0] if not dd.get_jointcaller(data): data["config"]["algorithm"]["jointcaller"] = "%s-joint" % dd.get_variantcaller(data) # GenomicsDBImport uses 1-based coordinates. That's unexpected, convert over to these. chrom, coords = data["region"].split(":") start, end = coords.split("-") ready_region = "%s:%s-%s" % (chrom, int(start) + 1, end) str_region = ready_region.replace(":", "_") batches = dd.get_batches(data) or dd.get_sample_name(data) if not isinstance(batches, (list, tuple)): batches = [batches] out_file = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(data), "joint", dd.get_variantcaller(data), str_region)), "%s-%s-%s.vcf.gz" % (batches[0], dd.get_variantcaller(data), str_region)) joint_out = square_batch_region(data, ready_region, [], [d["vrn_file"] for d in items], out_file)[0] data["vrn_file_region"] = joint_out["vrn_file"] return data def concat_batch_variantcalls_jointvc(items): concat_out = genotype.concat_batch_variantcalls(items, region_block=False, skip_jointcheck=True) return {"vrn_file_joint": concat_out["vrn_file"]} def finalize_jointvc(items): return [utils.to_single_data(x) for x in items] def _get_callable_regions(data): """Retrieve regions to parallelize by from callable regions or chromosomes. """ import pybedtools callable_files = data.get("callable_regions") if callable_files: assert len(callable_files) == 1 regions = [(r.chrom, int(r.start), int(r.stop)) for r in pybedtools.BedTool(callable_files[0])] else: work_bam = list(tz.take(1, filter(lambda x: x and x.endswith(".bam"), data["work_bams"]))) if work_bam: with pysam.Samfile(work_bam[0], "rb") as pysam_bam: regions = [(chrom, 0, length) for (chrom, length) in zip(pysam_bam.references, pysam_bam.lengths)] else: regions = [(r.name, 0, r.size) for r in ref.file_contigs(dd.get_ref_file(data), data["config"])] return regions def _split_by_callable_region(data): """Split by callable or variant regions. We expect joint calling to be deep in numbers of samples per region, so prefer splitting aggressively by regions. """ batch = tz.get_in(("metadata", "batch"), data) jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), data) name = batch if batch else tz.get_in(("rgnames", "sample"), data) out_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "joint", jointcaller, name)) utils.safe_makedir(os.path.join(out_dir, "inprep")) parts = [] for feat in _get_callable_regions(data): region_dir = utils.safe_makedir(os.path.join(out_dir, feat[0])) region_prep_dir = os.path.join(region_dir, "inprep") if not os.path.exists(region_prep_dir): os.symlink(os.path.join(os.pardir, "inprep"), region_prep_dir) region_outfile = os.path.join(region_dir, "%s-%s.vcf.gz" % (batch, region.to_safestr(feat))) parts.append((feat, data["work_bams"], data["vrn_files"], region_outfile)) out_file = os.path.join(out_dir, "%s-joint.vcf.gz" % name) return out_file, parts def _is_jointcaller_compatible(data): """Match variant caller inputs to compatible joint callers. """ jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), data) variantcaller = tz.get_in(("config", "algorithm", "variantcaller"), data) if isinstance(variantcaller, (list, tuple)) and len(variantcaller) == 1: variantcaller = variantcaller[0] return jointcaller == "%s-joint" % variantcaller or not variantcaller def square_off(samples, run_parallel): """Perform joint calling at all variants within a batch. """ to_process = [] extras = [] for data in [utils.to_single_data(x) for x in samples]: added = False if tz.get_in(("metadata", "batch"), data): for add in genotype.handle_multiple_callers(data, "jointcaller", require_bam=False): if _is_jointcaller_compatible(add): added = True to_process.append([add]) if not added: extras.append([data]) processed = grouped_parallel_split_combine(to_process, _split_by_callable_region, multi.group_batches_joint, run_parallel, "square_batch_region", "concat_variant_files", "vrn_file", ["region", "sam_ref", "config"]) return _combine_to_jointcaller(processed) + extras def _combine_to_jointcaller(processed): """Add joint calling information to variants, while collapsing independent regions. """ by_vrn_file = collections.OrderedDict() for data in (x[0] for x in processed): key = (tz.get_in(("config", "algorithm", "jointcaller"), data), data["vrn_file"]) if key not in by_vrn_file: by_vrn_file[key] = [] by_vrn_file[key].append(data) out = [] for grouped_data in by_vrn_file.values(): cur = grouped_data[0] out.append([cur]) return out def want_gvcf(items): jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), items[0]) want_gvcf = any("gvcf" in dd.get_tools_on(d) for d in items) return jointcaller or want_gvcf def get_callers(): return ["%s-joint" % x for x in SUPPORTED["general"]] + \ ["%s-merge" % x for x in SUPPORTED["general"]] + \ ["%s-joint" % x for x in SUPPORTED["gatk"]] + \ ["%s-joint" % x for x in SUPPORTED["gvcf"]] + \ ["%s-joint" % x for x in SUPPORTED["sentieon"]] def square_batch_region(data, region, bam_files, vrn_files, out_file): """Perform squaring of a batch in a supplied region, with input BAMs """ from bcbio.variation import sentieon, strelka2 if not utils.file_exists(out_file): jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), data) if jointcaller in ["%s-joint" % x for x in SUPPORTED["general"]]: _square_batch_bcbio_variation(data, region, bam_files, vrn_files, out_file, "square") elif jointcaller in ["%s-merge" % x for x in SUPPORTED["general"]]: _square_batch_bcbio_variation(data, region, bam_files, vrn_files, out_file, "merge") elif jointcaller in ["%s-joint" % x for x in SUPPORTED["gatk"]]: gatkjoint.run_region(data, region, vrn_files, out_file) elif jointcaller in ["%s-joint" % x for x in SUPPORTED["gvcf"]]: strelka2.run_gvcfgenotyper(data, region, vrn_files, out_file) elif jointcaller in ["%s-joint" % x for x in SUPPORTED["sentieon"]]: sentieon.run_gvcftyper(vrn_files, out_file, region, data) else: raise ValueError("Unexpected joint calling approach: %s." % jointcaller) if region: data["region"] = region data = _fix_orig_vcf_refs(data) data["vrn_file"] = out_file return [data] def _fix_orig_vcf_refs(data): """Supply references to initial variantcalls if run in addition to batching. """ variantcaller = tz.get_in(("config", "algorithm", "variantcaller"), data) jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), data) if variantcaller or jointcaller: data["vrn_file_orig"] = data["vrn_file"] for i, sub in enumerate(data.get("group_orig", [])): sub_vrn = sub.pop("vrn_file", None) if sub_vrn: sub["vrn_file_orig"] = sub_vrn data["group_orig"][i] = sub return data def _square_batch_bcbio_variation(data, region, bam_files, vrn_files, out_file, todo="square"): """Run squaring or merging analysis using bcbio.variation.recall. """ ref_file = tz.get_in(("reference", "fasta", "base"), data) cores = tz.get_in(("config", "algorithm", "num_cores"), data, 1) resources = config_utils.get_resources("bcbio-variation-recall", data["config"]) # adjust memory by cores but leave room for run program memory memcores = int(math.ceil(float(cores) / 5.0)) jvm_opts = config_utils.adjust_opts(resources.get("jvm_opts", ["-Xms250m", "-Xmx2g"]), {"algorithm": {"memory_adjust": {"direction": "increase", "magnitude": memcores}}}) # Write unique VCFs and BAMs to input file input_file = "%s-inputs.txt" % os.path.splitext(out_file)[0] with open(input_file, "w") as out_handle: out_handle.write("\n".join(sorted(list(set(vrn_files)))) + "\n") if todo == "square": out_handle.write("\n".join(sorted(list(set(bam_files)))) + "\n") variantcaller = tz.get_in(("config", "algorithm", "jointcaller"), data).replace("-joint", "") cmd = ["bcbio-variation-recall", todo] + jvm_opts + broad.get_default_jvm_opts() + \ ["-c", cores, "-r", bamprep.region_to_gatk(region)] if todo == "square": cmd += ["--caller", variantcaller] cmd += [out_file, ref_file, input_file] bcbio_env = utils.get_bcbio_env() cmd = " ".join(str(x) for x in cmd) do.run(cmd, "%s in region: %s" % (cmd, bamprep.region_to_gatk(region)), env=bcbio_env) return out_file bcbio-nextgen-1.2.9/bcbio/variation/multi.py000066400000000000000000000227071415626112400210370ustar00rootroot00000000000000"""Organize samples for coordinated multi-sample processing. Handles grouping of related families or batches to go through variant calling simultaneously. """ import collections import toolz as tz from bcbio import utils from bcbio.pipeline import datadict as dd from bcbio.variation import vcfutils # ## Group batches to process together def group_by_batch(items, require_bam=True): """Group a set of sample items by batch (or singleton) name. Items in multiple batches cause two batches to be merged together. """ out = collections.defaultdict(list) batch_groups = _get_representative_batch(_merge_batches(_find_all_groups(items, require_bam))) for data in items: batches = _get_batches(data, require_bam) # take first batch as representative batch = batch_groups[batches[0]] out[batch].append(utils.deepish_copy(data)) return dict(out) def bam_needs_processing(data): """Check if a work input needs processing for parallelization. """ return ((data.get("work_bam") or data.get("align_bam")) and (any(tz.get_in(["config", "algorithm", x], data) for x in ["variantcaller", "mark_duplicates", "recalibrate", "realign", "svcaller", "jointcaller", "variant_regions"]) or any(k in data for k in ["cwl_keys", "output_cwl_keys"]))) def get_batch_for_key(data): """Retrieve batch information useful as a unique key for the sample. """ batches = _get_batches(data, require_bam=False) if len(batches) == 1: return batches[0] else: return tuple(batches) def _get_batches(data, require_bam=True): if bam_needs_processing(data) or not require_bam: batches = dd.get_batch(data) or dd.get_sample_name(data) else: batches = dd.get_sample_name(data) if not isinstance(batches, (list, tuple)): batches = [batches] return batches def _find_all_groups(items, require_bam=True): """Find all groups """ all_groups = [] for data in items: batches = _get_batches(data, require_bam) all_groups.append(batches) return all_groups def _merge_batches(all_groups): """Merge batches with overlapping groups. Uses merge approach from: http://stackoverflow.com/a/4842897/252589 """ merged = [] while len(all_groups) > 0: first, rest = all_groups[0], all_groups[1:] first = set(first) lf = -1 while len(first) > lf: lf = len(first) rest2 = [] for r in rest: if len(first.intersection(set(r))) > 0: first |= set(r) else: rest2.append(r) rest = rest2 merged.append(first) all_groups = rest return merged def _get_representative_batch(merged): """Prepare dictionary matching batch items to a representative within a group. """ out = {} for mgroup in merged: mgroup = sorted(list(mgroup)) for x in mgroup: out[x] = mgroup[0] return out def _list_to_tuple(xs): if isinstance(xs, (list, tuple)): return tuple([_list_to_tuple(x) for x in xs]) else: return xs def _group_batches_shared(xs, caller_batch_fn, prep_data_fn): """Shared functionality for grouping by batches for variant calling and joint calling. when creating a pon (batch: pon_build) process samples as singles first """ singles = [] batch_groups = collections.defaultdict(list) for args in xs: data = utils.to_single_data(args) caller, batch = caller_batch_fn(data) region = _list_to_tuple(data["region"]) if "region" in data else () if batch is not None and batch != "pon_build": batches = batch if isinstance(batch, (list, tuple)) else [batch] for b in batches: batch_groups[(b, region, caller)].append(utils.deepish_copy(data)) else: data = prep_data_fn(data, [data]) singles.append(data) batches = [] for batch, items in batch_groups.items(): batch_data = utils.deepish_copy(_pick_lead_item(items)) # For nested primary batches, split permanently by batch if tz.get_in(["metadata", "batch"], batch_data): batch_name = batch[0] batch_data["metadata"]["batch"] = batch_name batch_data = prep_data_fn(batch_data, items) batch_data["group_orig"] = _collapse_subitems(batch_data, items) batch_data["group"] = batch batches.append(batch_data) return singles + batches def group_batches(xs): """Group samples into batches for simultaneous variant calling. Identify all samples to call together: those in the same batch and variant caller. Pull together all BAM files from this batch and process together, Provide details to pull these finalized files back into individual expected files. Only batches files if joint calling not specified. """ def _caller_batches(data): caller = tz.get_in(("config", "algorithm", "variantcaller"), data) jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), data) batch = tz.get_in(("metadata", "batch"), data) if not jointcaller else None return caller, batch def _prep_data(data, items): data["region_bams"] = [x["region_bams"] for x in items] return data return _group_batches_shared(xs, _caller_batches, _prep_data) def group_batches_joint(samples): """Perform grouping by batches for joint calling/squaring off. """ def _caller_batches(data): jointcaller = tz.get_in(("config", "algorithm", "jointcaller"), data) batch = tz.get_in(("metadata", "batch"), data) if jointcaller else None return jointcaller, batch def _prep_data(data, items): for r in ["callable_regions", "variant_regions"]: data[r] = list(set(filter(lambda x: x is not None, [tz.get_in(("config", "algorithm", r), d) for d in items]))) data["work_bams"] = [dd.get_align_bam(x) or dd.get_work_bam(x) for x in items] data["vrn_files"] = [x["vrn_file"] for x in items] return data return _group_batches_shared(samples, _caller_batches, _prep_data) # ## Collapse and uncollapse groups to save memory def _collapse_subitems(base, items): """Collapse full data representations relative to a standard base. """ out = [] for d in items: newd = _diff_dict(base, d) out.append(newd) return out def _diff_dict(orig, new): """Diff a nested dictionary, returning only key/values that differ. """ final = {} for k, v in new.items(): if isinstance(v, dict): v = _diff_dict(orig.get(k, {}), v) if len(v) > 0: final[k] = v elif v != orig.get(k): final[k] = v for k, v in orig.items(): if k not in new: final[k] = None return final def _pick_lead_item(items): """Pick single representative sample for batch calling to attach calls to. For cancer samples, attach to tumor. """ if vcfutils.is_paired_analysis([dd.get_align_bam(x) for x in items], items): for data in items: if vcfutils.get_paired_phenotype(data) == "tumor": return data print(items) raise ValueError("Did not find tumor sample in paired tumor/normal calling") else: return items[0] def get_orig_items(base): """Retrieve original items from a diffed set of nested samples. """ assert "group_orig" in base out = [] for data_diff in base["group_orig"]: new = utils.deepish_copy(base) new.pop("group_orig") out.append(_patch_dict(data_diff, new)) return out def _patch_dict(diff, base): """Patch a dictionary, substituting in changed items from the nested diff. """ for k, v in diff.items(): if isinstance(v, dict): base[k] = _patch_dict(v, base.get(k, {})) elif not v: base.pop(k, None) else: base[k] = v return base # ## Split batched variants def split_variants_by_sample(data): """Split a multi-sample call file into inputs for individual samples. For tumor/normal paired analyses, do not split the final file and attach it to the tumor input. """ # not split, do nothing if "group_orig" not in data: return [[data]] # cancer tumor/normal elif (vcfutils.get_paired_phenotype(data) and "tumor" in [vcfutils.get_paired_phenotype(d) for d in get_orig_items(data)]): out = [] for i, sub_data in enumerate(get_orig_items(data)): if vcfutils.get_paired_phenotype(sub_data) == "tumor": cur_batch = tz.get_in(["metadata", "batch"], data) if cur_batch: sub_data["metadata"]["batch"] = cur_batch sub_data["vrn_file"] = data["vrn_file"] else: sub_data.pop("vrn_file", None) out.append([sub_data]) return out # joint calling or population runs, do not split back up and keep in batches else: out = [] for sub_data in get_orig_items(data): cur_batch = tz.get_in(["metadata", "batch"], data) if cur_batch: sub_data["metadata"]["batch"] = cur_batch sub_data["vrn_file_batch"] = data["vrn_file"] sub_data["vrn_file"] = data["vrn_file"] out.append([sub_data]) return out bcbio-nextgen-1.2.9/bcbio/variation/mutect.py000066400000000000000000000313361415626112400212040ustar00rootroot00000000000000"""Provide support for MuTect and other paired analysis tools.""" from distutils.version import LooseVersion import os import toolz as tz from bcbio import bam, broad, utils from bcbio.utils import file_exists, get_in, open_gzipsafe from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.pipeline.shared import subset_variant_regions from bcbio.variation import bamprep, bedutils, vcfutils, scalpel from bcbio.variation.realign import has_aligned_reads from bcbio.variation.vcfutils import bgzip_and_index from bcbio.log import logger _PASS_EXCEPTIONS = set(["java.lang.RuntimeException: " "java.lang.IllegalArgumentException: " "Comparison method violates its general contract!", "java.lang.IllegalArgumentException: " "Comparison method violates its general contract!"]) def _check_mutect_version(broad_runner): mutect_version = broad_runner.get_mutect_version() try: assert mutect_version is not None except AssertionError: logger.warn("WARNING") logger.warn("MuTect version could not be determined from jar file. " "Please ensure you are using at least version 1.1.5, " "as versions 1.1.4 and lower have known issues.") logger.warn("Proceeding but assuming correct version 1.1.5.") else: try: assert LooseVersion(mutect_version) >= LooseVersion("1.1.5") except AssertionError: message = ("MuTect 1.1.4 and lower is known to have incompatibilities " "with Java < 7, and this may lead to problems in analyses. " "Please use MuTect 1.1.5 or higher (note that it requires " "Java 7).") raise ValueError(message) def _config_params(base_config, assoc_files, region, out_file, items): """Add parameters based on configuration variables, associated files and genomic regions. """ params = [] dbsnp = assoc_files.get("dbsnp") if dbsnp: params += ["--dbsnp", dbsnp] cosmic = assoc_files.get("cosmic") if cosmic: params += ["--cosmic", cosmic] variant_regions = bedutils.population_variant_regions(items) region = subset_variant_regions(variant_regions, region, out_file, items) if region: params += ["-L", bamprep.region_to_gatk(region), "--interval_set_rule", "INTERSECTION"] # set low frequency calling parameter if adjusted # to set other MuTect parameters on contamination, pass options to resources for mutect # --fraction_contamination --minimum_normal_allele_fraction min_af = tz.get_in(["algorithm", "min_allele_fraction"], base_config) if min_af: params += ["--minimum_mutation_cell_fraction", "%.2f" % (min_af / 100.0)] resources = config_utils.get_resources("mutect", base_config) if resources.get("options") is not None: params += [str(x) for x in resources.get("options", [])] # Output quality scores if "--enable_qscore_output" not in params: params.append("--enable_qscore_output") # drf not currently supported in MuTect to turn off duplicateread filter # params += gatk.standard_cl_params(items) return params def _mutect_call_prep(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Preparation work for MuTect. """ base_config = items[0]["config"] broad_runner = broad.runner_from_path("picard", base_config) broad_runner.run_fn("picard_index_ref", ref_file) broad_runner = broad.runner_from_config(base_config, "mutect") _check_mutect_version(broad_runner) for x in align_bams: bam.index(x, base_config) paired = vcfutils.get_paired_bams(align_bams, items) if not paired: raise ValueError("Specified MuTect calling but 'tumor' phenotype not present in batch\n" "https://bcbio-nextgen.readthedocs.org/en/latest/contents/" "pipelines.html#cancer-variant-calling\n" "for samples: %s" % ", " .join([dd.get_sample_name(x) for x in items])) params = ["-R", ref_file, "-T", "MuTect", "-U", "ALLOW_N_CIGAR_READS"] params += ["--read_filter", "NotPrimaryAlignment"] params += ["-I:tumor", paired.tumor_bam] params += ["--tumor_sample_name", paired.tumor_name] if paired.normal_bam is not None: params += ["-I:normal", paired.normal_bam] params += ["--normal_sample_name", paired.normal_name] if paired.normal_panel is not None: params += ["--normal_panel", paired.normal_panel] params += _config_params(base_config, assoc_files, region, out_file, items) return broad_runner, params def mutect_caller(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Run the MuTect paired analysis algorithm. """ config = items[0]["config"] if out_file is None: out_file = "%s-paired-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not file_exists(out_file): base_config = items[0]["config"] broad_runner = broad.runner_from_config(base_config, "mutect") out_file_mutect = (out_file.replace(".vcf", "-mutect.vcf") if "vcf" in out_file else out_file + "-mutect.vcf") broad_runner, params = \ _mutect_call_prep(align_bams, items, ref_file, assoc_files, region, out_file_mutect) if (not isinstance(region, (list, tuple)) and not all(has_aligned_reads(x, region) for x in align_bams)): paired = vcfutils.get_paired(items) vcfutils.write_empty_vcf(out_file, samples=[x for x in (paired.tumor_name, paired.normal_name) if x]) return out_file_orig = "%s-orig%s" % utils.splitext_plus(out_file_mutect) if not file_exists(out_file_orig): with file_transaction(config, out_file_orig) as tx_out_file: # Rationale: MuTect writes another table to stdout, which we don't need params += ["--vcf", tx_out_file, "-o", os.devnull] broad_runner.run_mutect(params) is_paired = "-I:normal" in params if not utils.file_uptodate(out_file_mutect, out_file_orig): out_file_mutect = _fix_mutect_output(out_file_orig, config, out_file_mutect, is_paired) indelcaller = vcfutils.get_indelcaller(base_config) if ("scalpel" in indelcaller.lower() and region and isinstance(region, (tuple, list)) and chromhacks.is_autosomal_or_sex(region[0])): # Scalpel InDels out_file_indels = (out_file.replace(".vcf", "-somaticIndels.vcf") if "vcf" in out_file else out_file + "-somaticIndels.vcf") if scalpel.is_installed(items[0]["config"]): if not is_paired: vcfutils.check_paired_problems(items) scalpel._run_scalpel_caller(align_bams, items, ref_file, assoc_files, region=region, out_file=out_file_indels) else: scalpel._run_scalpel_paired(align_bams, items, ref_file, assoc_files, region=region, out_file=out_file_indels) out_file = vcfutils.combine_variant_files(orig_files=[out_file_mutect, out_file_indels], out_file=out_file, ref_file=items[0]["sam_ref"], config=items[0]["config"], region=region) else: utils.symlink_plus(out_file_mutect, out_file) elif "pindel" in indelcaller.lower(): from bcbio.structural import pindel out_file_indels = (out_file.replace(".vcf", "-somaticIndels.vcf") if "vcf" in out_file else out_file + "-somaticIndels.vcf") if pindel.is_installed(items[0]["config"]): pindel._run_tumor_pindel_caller(align_bams, items, ref_file, assoc_files, region=region, out_file=out_file_indels) out_file = vcfutils.combine_variant_files(orig_files=[out_file_mutect, out_file_indels], out_file=out_file, ref_file=ref_file, config=items[0]["config"], region=region) else: utils.symlink_plus(out_file_mutect, out_file) elif (("somaticindeldetector" in indelcaller.lower() or "sid" in indelcaller.lower()) and "appistry" in broad_runner.get_mutect_version()): # SomaticIndelDetector InDels out_file_indels = (out_file.replace(".vcf", "-somaticIndels.vcf") if "vcf" in out_file else out_file + "-somaticIndels.vcf") params_indels = _SID_call_prep(align_bams, items, ref_file, assoc_files, region, out_file_indels) with file_transaction(config, out_file_indels) as tx_out_file: params_indels += ["-o", tx_out_file] broad_runner.run_mutect(params_indels) out_file = vcfutils.combine_variant_files(orig_files=[out_file_mutect, out_file_indels], out_file=out_file, ref_file=items[0]["sam_ref"], config=items[0]["config"], region=region) else: utils.symlink_plus(out_file_mutect, out_file) return out_file def _SID_call_prep(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Preparation work for SomaticIndelDetector. """ base_config = items[0]["config"] for x in align_bams: bam.index(x, base_config) params = ["-R", ref_file, "-T", "SomaticIndelDetector", "-U", "ALLOW_N_CIGAR_READS"] # Limit per base read start count to between 200-10000, i.e. from any base # can no more 10000 new reads begin. # Further, limit maxNumberOfReads accordingly, otherwise SID discards # windows for high coverage panels. paired = vcfutils.get_paired_bams(align_bams, items) params += ["--read_filter", "NotPrimaryAlignment"] params += ["-I:tumor", paired.tumor_bam] min_af = float(get_in(paired.tumor_config, ("algorithm", "min_allele_fraction"), 10)) / 100.0 if paired.normal_bam is not None: params += ["-I:normal", paired.normal_bam] # notice there must be at least 4 reads of coverage in normal params += ["--filter_expressions", "T_COV<6||N_COV<4||T_INDEL_F<%s||T_INDEL_CF<0.7" % min_af] else: params += ["--unpaired"] params += ["--filter_expressions", "COV<6||INDEL_F<%s||INDEL_CF<0.7" % min_af] if region: params += ["-L", bamprep.region_to_gatk(region), "--interval_set_rule", "INTERSECTION"] return params def _fix_mutect_output(orig_file, config, out_file, is_paired): """Adjust MuTect output to match other callers. - Rename allelic fraction field in mutect output from FA to FREQ to standarize with other tools - Remove extra 'none' samples introduced when calling tumor-only samples """ out_file_noc = out_file.replace(".vcf.gz", ".vcf") none_index = -1 with file_transaction(config, out_file_noc) as tx_out_file: with open_gzipsafe(orig_file) as in_handle: with open(tx_out_file, 'w') as out_handle: for line in in_handle: if not is_paired and line.startswith("#CHROM"): parts = line.rstrip().split("\t") none_index = parts.index("none") del parts[none_index] line = "\t".join(parts) + "\n" elif line.startswith("##FORMAT= 0: parts = line.rstrip().split("\t") del parts[none_index] line = "\t".join(parts) + "\n" line = line.replace("FA", "FREQ") out_handle.write(line) return bgzip_and_index(out_file_noc, config) bcbio-nextgen-1.2.9/bcbio/variation/mutect2.py000066400000000000000000000335541415626112400212720ustar00rootroot00000000000000"""GATK variant calling -- MuTect2. """ from distutils.version import LooseVersion import os import shutil import numpy as np import toolz as tz from bcbio import bam, broad, utils from bcbio.bam import is_paired from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline.shared import subset_variant_regions from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import annotation, bamprep, bedutils, gatk, vcfutils, ploidy cyvcf2 = utils.LazyImport("cyvcf2") def _add_tumor_params(paired, items, gatk_type): """Add tumor/normal BAM input parameters to command line. """ params = [] if not paired: raise ValueError("Specified MuTect2 calling but 'tumor' phenotype not present in batch\n" "https://bcbio-nextgen.readthedocs.org/en/latest/contents/" "pipelines.html#cancer-variant-calling\n" "for samples: %s" % ", " .join([dd.get_sample_name(x) for x in items])) if gatk_type == "gatk4": params += ["-I", paired.tumor_bam] params += ["--tumor-sample", paired.tumor_name] else: params += ["-I:tumor", paired.tumor_bam] if paired.normal_bam is not None: if gatk_type == "gatk4": params += ["-I", paired.normal_bam] params += ["--normal-sample", paired.normal_name] else: params += ["-I:normal", paired.normal_bam] if paired.normal_panel is not None: panel_dir = utils.safe_makedir(os.path.join(dd.get_work_dir(items[0]), "mutect2", "panels")) normal_panel = vcfutils.bgzip_and_index(paired.normal_panel, items[0]["config"], out_dir=panel_dir) if gatk_type == "gatk4": params += ["--panel-of-normals", normal_panel] else: params += ["--normal_panel", normal_panel] return params def _add_region_params(region, out_file, items, gatk_type): """Add parameters for selecting by region to command line. """ params = [] variant_regions = bedutils.population_variant_regions(items) region = subset_variant_regions(variant_regions, region, out_file, items) if region: if gatk_type == "gatk4": params += ["-L", bamprep.region_to_gatk(region), "--interval-set-rule", "INTERSECTION"] else: params += ["-L", bamprep.region_to_gatk(region), "--interval_set_rule", "INTERSECTION"] params += gatk.standard_cl_params(items) return params def _add_assoc_params(assoc_files): params = [] if assoc_files.get("dbsnp"): params += ["--dbsnp", assoc_files["dbsnp"]] if assoc_files.get("cosmic"): params += ["--cosmic", assoc_files["cosmic"]] return params def _prep_inputs(align_bams, ref_file, items): """Ensure inputs to calling are indexed as expected. """ broad_runner = broad.runner_from_path("picard", items[0]["config"]) broad_runner.run_fn("picard_index_ref", ref_file) for x in align_bams: bam.index(x, items[0]["config"]) def mutect2_caller(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Call variation with GATK's MuTect2. This requires the full non open-source version of GATK 3.5+. items = 1 sample or T/N pair """ if out_file is None: out_file = "%s-variants.vcf.gz" % utils.splitext_plus(align_bams[0])[0] if not utils.file_exists(out_file): # call somatic variants keeping germline sites and using germline 1KG resource # use --native-pair-hmm-threads? broad_runner = broad.runner_from_config(items[0]["config"]) gatk_type = broad_runner.gatk_type() # shared Mutect2 settings for PureCN analysis in the case of: # - PON creation # - Tumor-only PureCN run # - T/N PureCN run # PURECN requirement alters Mutect2 variants calling! if "purecn" in dd.get_svcaller(items[0]): # mutect call for PON creation or purecn T-only analysis _prep_inputs(align_bams, ref_file, items) with file_transaction(items[0], out_file) as tx_out_file: germline_resource = tz.get_in(["genome_resources", "variation", "af_only_gnomad"], items[0]) germline_path = os.path.normpath(os.path.join(os.path.dirname(ref_file), germline_resource)) input_bam = dd.get_work_bam(items[0]) tx_prefilt_vcf = utils.splitext_plus(tx_out_file)[0] + ".prefilt.vcf" tx_vcf = os.path.splitext(tx_out_file)[0] out_file_ungz = os.path.splitext(out_file)[0] params = ["-T", "Mutect2"] # T/N pair if len(items) == 2: paired = vcfutils.get_paired_bams(align_bams, items) # not really running purecn with mutect1/gatk3 params += _add_tumor_params(paired, items, gatk_type) logger.debug("You are running mutect2 in PureCN analysis in T/N mode, T-only + PON is recommended") else: #T only params += ["-I", input_bam] # adding SNV PON from background/variant snv_pon = tz.get_in(["config", "algorithm", "background", "variant"], items[0]) if snv_pon and dd.get_batch(items[0]) != "pon_build": params += ["-pon", snv_pon] params += ["--genotype-pon-sites"] opt_list = config_utils.get_resources("mutect2", items[0]["config"]).get("options") # default is 50, sometimes 100 or 200 is recommended for better sensitivity in detection # hom del CNVs (calling more variants helps) interval_padding = 50 if opt_list: opt_dict = dict(zip(opt_list[::2], opt_list[1::2])) if "--interval_padding" in opt_dict: interval_padding = opt_dict["--interval_padding"] params += ["--max-mnp-distance", "0", "--interval-padding", interval_padding, "--germline-resource", germline_path, "--genotype-germline-sites", "--reference", ref_file, "-O", tx_prefilt_vcf] params += _add_region_params(region, out_file, items, gatk_type) broad_runner.new_resources("mutect2") gatk_cmd = broad_runner.cl_gatk(params, os.path.dirname(tx_out_file)) filter_cmd = _mutect2_filter(broad_runner, items, tx_prefilt_vcf, out_file_ungz, ref_file) cmd = "{gatk_cmd} && {filter_cmd}" do.run(cmd.format(**locals()), "MuTect2") # no AF filter for PureCN variants out_file = vcfutils.bgzip_and_index(out_file_ungz, items[0]["config"]) else: # a regular mutect call paired = vcfutils.get_paired_bams(align_bams, items) f1r2_file = None _prep_inputs(align_bams, ref_file, items) with file_transaction(items[0], out_file) as tx_out_file: params = ["-T", "Mutect2" if gatk_type == "gatk4" else "MuTect2", "--annotation", "ClippingRankSumTest", "--annotation", "DepthPerSampleHC"] if gatk_type == "gatk4": params += ["--reference", ref_file] else: params += ["-R", ref_file] for a in annotation.get_gatk_annotations(items[0]["config"], include_baseqranksum=False): params += ["--annotation", a] # Avoid issues with BAM CIGAR reads that GATK doesn't like if gatk_type == "gatk4": params += ["--read-validation-stringency", "LENIENT"] params += _add_tumor_params(paired, items, gatk_type) params += _add_region_params(region, out_file, items, gatk_type) if all(is_paired(bam) for bam in align_bams) and ( "mutect2_readmodel" in utils.get_in(items[0], "config", "tools_on")): orientation_filter = True else: orientation_filter = False if gatk_type == "gatk4" and orientation_filter: f1r2_file = "{}-f1r2.tar.gz".format(utils.splitext_plus(out_file)[0]) params += ["--f1r2-tar-gz", f1r2_file] # Avoid adding dbSNP/Cosmic so they do not get fed to variant filtering algorithm # Not yet clear how this helps or hurts in a general case. #params += _add_assoc_params(assoc_files) resources = config_utils.get_resources("mutect2", items[0]["config"]) if "options" in resources: params += [str(x) for x in resources.get("options", [])] assert LooseVersion(broad_runner.gatk_major_version()) >= LooseVersion("3.5"), \ "Require full version of GATK 3.5+ for mutect2 calling" broad_runner.new_resources("mutect2") gatk_cmd = broad_runner.cl_gatk(params, os.path.dirname(tx_out_file)) if gatk_type == "gatk4": tx_raw_prefilt_file = "%s-raw%s" % utils.splitext_plus(out_file) tx_raw_file = "%s-raw-filt%s" % utils.splitext_plus(tx_out_file) if orientation_filter: tx_f1r2_file = "{}-read-orientation-model.tar.gz" tx_f1r2_file = tx_f1r2_file.format(utils.splitext_plus(f1r2_file)[0]) tx_read_orient_cmd = _mutect2_read_filter(broad_runner, f1r2_file, tx_f1r2_file) filter_cmd = _mutect2_filter(broad_runner, items, tx_raw_prefilt_file, tx_raw_file, ref_file, tx_f1r2_file) else: filter_cmd = _mutect2_filter(broad_runner, items, tx_raw_prefilt_file, tx_raw_file, ref_file) if orientation_filter: cmd = "{gatk_cmd} -O {tx_raw_prefilt_file} && {tx_read_orient_cmd} && {filter_cmd}" else: cmd = "{gatk_cmd} -O {tx_raw_prefilt_file} && {filter_cmd}" else: tx_raw_file = "%s-raw%s" % utils.splitext_plus(tx_out_file) cmd = "{gatk_cmd} > {tx_raw_file}" do.run(cmd.format(**locals()), "MuTect2") out_file = _af_filter(paired.tumor_data, tx_raw_file, out_file) return vcfutils.bgzip_and_index(out_file, items[0]["config"]) def _mutect2_read_filter(broad_runner, in_file, out_file): """Calculate and apply the Mutect2 read model to compensate for stand bias and artefacts such as those cause by FFPE.""" params = ["-T", "LearnReadOrientationModel", "-I", in_file, "-O", out_file] return "{}".format(broad_runner.cl_gatk(params, os.path.dirname(out_file))) def _mutect2_filter(broad_runner, items, in_file, out_file, ref_file, orient_file=None): """Filter of MuTect2 calls, a separate step in GATK4. Includes a pre-step to avoid stats information with zero callable reads, which cause MuTect2 filter errors when there are calls. The sed file increases this to 10 reads, which matches with actually having a call in the output file. """ params = ["-T", "FilterMutectCalls", "--reference", ref_file, "--variant", in_file, "--output", out_file] resources = config_utils.get_resources("mutect2_filter", items[0]["config"]) if "options" in resources: params += [str(x) for x in resources.get("options", [])] if orient_file is not None: params += ["--ob-priors", orient_file] avoid_zero_callable = r"sed -i 's/callable\t0.0/callable\t10.0/' %s.stats" % in_file return "%s && %s" % (avoid_zero_callable, broad_runner.cl_gatk(params, os.path.dirname(out_file))) def _af_filter(data, in_file, out_file): """Soft-filter variants with AF below min_allele_fraction (appends "MinAF" to FILTER) """ min_freq = float(utils.get_in(data["config"], ("algorithm", "min_allele_fraction"), 10)) / 100.0 logger.debug("Filtering MuTect2 calls with allele fraction threshold of %s" % min_freq) ungz_out_file = "%s.vcf" % utils.splitext_plus(out_file)[0] if not utils.file_exists(ungz_out_file) and not utils.file_exists(ungz_out_file + ".gz"): with file_transaction(data, ungz_out_file) as tx_out_file: vcf = cyvcf2.VCF(in_file) vcf.add_filter_to_header({ 'ID': 'MinAF', 'Description': 'Allele frequency is lower than %s%% ' % (min_freq*100) + ( '(configured in bcbio as min_allele_fraction)' if utils.get_in(data["config"], ("algorithm", "min_allele_fraction")) else '(default threshold in bcbio; override with min_allele_fraction in the algorithm section)')}) w = cyvcf2.Writer(tx_out_file, vcf) # GATK 3.x can produce VCFs without sample names for empty VCFs try: tumor_index = vcf.samples.index(dd.get_sample_name(data)) except ValueError: tumor_index = None for rec in vcf: if tumor_index is not None and np.all(rec.format('AF')[tumor_index] < min_freq): vcfutils.cyvcf_add_filter(rec, 'MinAF') w.write_record(rec) w.close() return vcfutils.bgzip_and_index(ungz_out_file, data["config"]) bcbio-nextgen-1.2.9/bcbio/variation/naming.py000066400000000000000000000241531415626112400211530ustar00rootroot00000000000000"""Fix chromosome naming incompatibilities for common issues, like hg19/GRCh37. Fixes issues relating to chr1 versus 1 naming. Uses Devon Ryan's great collection of contig mappings: https://github.com/dpryan79/ChromosomeMappings """ import os import requests from bcbio import utils from bcbio.bam import ref from bcbio.distributed.transaction import file_transaction from bcbio.variation import vcfutils # ## Cached results GMAP = {} # read_mapping("https://raw.githubusercontent.com/dpryan79/ChromosomeMappings/master/GRCh37_ensembl2UCSC.txt") GMAP["hg19"] = {'GL000219.1': 'chrUn_gl000219', 'GL000192.1': 'chr1_gl000192_random', 'GL000236.1': 'chrUn_gl000236', 'GL000211.1': 'chrUn_gl000211', 'GL000234.1': 'chrUn_gl000234', '20': 'chr20', '21': 'chr21', '22': 'chr22', 'GL000196.1': 'chr8_gl000196_random', 'GL000213.1': 'chrUn_gl000213', 'GL000205.1': 'chr17_gl000205_random', '4': 'chr4', 'GL000222.1': 'chrUn_gl000222', 'GL000215.1': 'chrUn_gl000215', '8': 'chr8', 'GL000232.1': 'chrUn_gl000232', 'GL000242.1': 'chrUn_gl000242', 'GL000244.1': 'chrUn_gl000244', 'GL000223.1': 'chrUn_gl000223', 'GL000229.1': 'chrUn_gl000229', 'GL000240.1': 'chrUn_gl000240', 'X': 'chrX', 'GL000202.1': 'chr11_gl000202_random', 'GL000217.1': 'chrUn_gl000217', 'GL000200.1': 'chr9_gl000200_random', 'GL000230.1': 'chrUn_gl000230', 'GL000206.1': 'chr17_gl000206_random', 'HSCHR6_MHC_QBL': 'chr6_qbl_hap6', 'HSCHR6_MHC_MANN': 'chr6_mann_hap4', 'GL000237.1': 'chrUn_gl000237', 'GL000204.1': 'chr17_gl000204_random', 'GL000235.1': 'chrUn_gl000235', 'HSCHR6_MHC_APD': 'chr6_apd_hap1', 'HSCHR6_MHC_COX': 'chr6_cox_hap2', '3': 'chr3', '7': 'chr7', 'GL000233.1': 'chrUn_gl000233', 'GL000221.1': 'chrUn_gl000221', 'GL000220.1': 'chrUn_gl000220', 'GL000245.1': 'chrUn_gl000245', 'GL000228.1': 'chrUn_gl000228', 'GL000231.1': 'chrUn_gl000231', 'MT': 'chrM', 'HSCHR6_MHC_SSTO': 'chr6_ssto_hap7', 'GL000238.1': 'chrUn_gl000238', 'GL000195.1': 'chr7_gl000195_random', 'GL000249.1': 'chrUn_gl000249', '2': 'chr2', '6': 'chr6', 'GL000247.1': 'chrUn_gl000247', 'GL000199.1': 'chr9_gl000199_random', 'HSCHR6_MHC_DBB': 'chr6_dbb_hap3', 'GL000246.1': 'chrUn_gl000246', 'GL000225.1': 'chrUn_gl000225', 'HSCHR4_1': 'chr4_ctg9_hap1', 'GL000227.1': 'chrUn_gl000227', '11': 'chr11', '10': 'chr10', '13': 'chr13', '12': 'chr12', '15': 'chr15', '14': 'chr14', '17': 'chr17', '16': 'chr16', '19': 'chr19', '18': 'chr18', 'GL000193.1': 'chr4_gl000193_random', 'GL000210.1': 'chr21_gl000210_random', 'GL000239.1': 'chrUn_gl000239', 'GL000191.1': 'chr1_gl000191_random', 'HSCHR17_1': 'chr17_ctg5_hap1', 'GL000194.1': 'chr4_gl000194_random', 'GL000212.1': 'chrUn_gl000212', 'GL000248.1': 'chrUn_gl000248', 'GL000197.1': 'chr8_gl000197_random', '1': 'chr1', '5': 'chr5', 'GL000208.1': 'chr19_gl000208_random', '9': 'chr9', 'GL000214.1': 'chrUn_gl000214', 'GL000224.1': 'chrUn_gl000224', 'GL000243.1': 'chrUn_gl000243', 'HSCHR6_MHC_MCF': 'chr6_mcf_hap5', 'GL000209.1': 'chr19_gl000209_random', 'GL000203.1': 'chr17_gl000203_random', 'GL000226.1': 'chrUn_gl000226', 'GL000241.1': 'chrUn_gl000241', 'Y': 'chrY', 'GL000201.1': 'chr9_gl000201_random', 'GL000198.1': 'chr9_gl000198_random', 'GL000216.1': 'chrUn_gl000216', 'GL000218.1': 'chrUn_gl000218', 'GL000207.1': 'chr18_gl000207_random'} #read_mapping("https://raw.githubusercontent.com/dpryan79/ChromosomeMappings/master/GRCh37_UCSC2ensembl.txt") GMAP["GRCh37"] = {'chr19_gl000208_random': 'GL000208.1', 'chr21_gl000210_random': 'GL000210.1', 'chr6_apd_hap1': 'HSCHR6_MHC_APD', 'chr13': '13', 'chr12': '12', 'chr11': '11', 'chr10': '10', 'chr17': '17', 'chr16': '16', 'chr15': '15', 'chr14': '14', 'chr19': '19', 'chr18': '18', 'chr9_gl000198_random': 'GL000198.1', 'chrUn_gl000239': 'GL000239.1', 'chrUn_gl000238': 'GL000238.1', 'chrUn_gl000233': 'GL000233.1', 'chrUn_gl000232': 'GL000232.1', 'chrUn_gl000231': 'GL000231.1', 'chrUn_gl000230': 'GL000230.1', 'chrUn_gl000237': 'GL000237.1', 'chrUn_gl000236': 'GL000236.1', 'chrUn_gl000235': 'GL000235.1', 'chrUn_gl000234': 'GL000234.1', 'chr6_qbl_hap6': 'HSCHR6_MHC_QBL', 'chr11_gl000202_random': 'GL000202.1', 'chr17_gl000206_random': 'GL000206.1', 'chr6_cox_hap2': 'HSCHR6_MHC_COX', 'chr4_gl000193_random': 'GL000193.1', 'chrUn_gl000248': 'GL000248.1', 'chrUn_gl000249': 'GL000249.1', 'chrUn_gl000246': 'GL000246.1', 'chrUn_gl000247': 'GL000247.1', 'chrUn_gl000244': 'GL000244.1', 'chrUn_gl000245': 'GL000245.1', 'chrUn_gl000242': 'GL000242.1', 'chrUn_gl000243': 'GL000243.1', 'chrUn_gl000240': 'GL000240.1', 'chrUn_gl000241': 'GL000241.1', 'chr17_gl000204_random': 'GL000204.1', 'chr17_ctg5_hap1': 'HSCHR17_1', 'chr17_gl000205_random': 'GL000205.1', 'chr9_gl000199_random': 'GL000199.1', 'chr9_gl000201_random': 'GL000201.1', 'chr8': '8', 'chr6_ssto_hap7': 'HSCHR6_MHC_SSTO', 'chr8_gl000197_random': 'GL000197.1', 'chr6_dbb_hap3': 'HSCHR6_MHC_DBB', 'chr7_gl000195_random': 'GL000195.1', 'chr1_gl000191_random': 'GL000191.1', 'chr4_ctg9_hap1': 'HSCHR4_1', 'chr3': '3', 'chr2': '2', 'chr1': '1', 'chr17_gl000203_random': 'GL000203.1', 'chrUn_gl000225': 'GL000225.1', 'chrY': 'Y', 'chrX': 'X', 'chr9_gl000200_random': 'GL000200.1', 'chr9': '9', 'chrM': 'MT', 'chr8_gl000196_random': 'GL000196.1', 'chr6_mann_hap4': 'HSCHR6_MHC_MANN', 'chrUn_gl000211': 'GL000211.1', 'chrUn_gl000213': 'GL000213.1', 'chrUn_gl000212': 'GL000212.1', 'chrUn_gl000215': 'GL000215.1', 'chrUn_gl000214': 'GL000214.1', 'chrUn_gl000217': 'GL000217.1', 'chrUn_gl000216': 'GL000216.1', 'chrUn_gl000219': 'GL000219.1', 'chrUn_gl000218': 'GL000218.1', 'chr19_gl000209_random': 'GL000209.1', 'chr22': '22', 'chr20': '20', 'chr21': '21', 'chr6_mcf_hap5': 'HSCHR6_MHC_MCF', 'chr7': '7', 'chr6': '6', 'chr5': '5', 'chr4': '4', 'chrUn_gl000228': 'GL000228.1', 'chrUn_gl000229': 'GL000229.1', 'chr1_gl000192_random': 'GL000192.1', 'chrUn_gl000224': 'GL000224.1', 'chr4_gl000194_random': 'GL000194.1', 'chrUn_gl000226': 'GL000226.1', 'chrUn_gl000227': 'GL000227.1', 'chrUn_gl000220': 'GL000220.1', 'chrUn_gl000221': 'GL000221.1', 'chrUn_gl000222': 'GL000222.1', 'chrUn_gl000223': 'GL000223.1', 'chr18_gl000207_random': 'GL000207.1'} def handle_synonyms(in_file, ref_file, genome_build, work_dir, data): """Potentially handle remapping synonymous chromosome names between builds. Handles tab delimited file formats like BED and VCF where the contig is in the first column. """ if genome_build in GMAP and ref_file: mappings = GMAP[genome_build] contigs = set([c.name for c in ref.file_contigs(ref_file)]) out_file = os.path.join(work_dir, "%s-fixed_contigs%s" % utils.splitext_plus(os.path.basename(in_file))) if not utils.file_exists(out_file): if out_file.endswith(".gz"): out_file = out_file.replace(".gz", "") needs_bgzip = True else: needs_bgzip = False checked_file = "%s.checked" % utils.splitext_plus(out_file)[0] if not _matches_contigs(in_file, contigs, checked_file): with file_transaction(data, out_file) as tx_out_file: _write_newname_file(in_file, tx_out_file, mappings) if needs_bgzip: out_file = vcfutils.bgzip_and_index(out_file, data["config"]) return out_file return in_file def _write_newname_file(in_file, out_file, mappings): """Re-write an input file with contigs matching the correct reference. """ with utils.open_gzipsafe(in_file) as in_handle: with open(out_file, "w") as out_handle: for line in in_handle: if line.startswith("#"): out_handle.write(line) else: parts = line.split("\t") new_contig = mappings.get(parts[0]) if new_contig: parts[0] = new_contig out_handle.write("\t".join(parts)) def _matches_contigs(in_file, contigs, checked_file): """Check if the contigs in the input file match the defined contigs in the reference genome. """ tocheck_contigs = 2 if utils.file_exists(checked_file): with open(checked_file) as in_handle: return in_handle.read().strip() == "match" else: with utils.open_gzipsafe(in_file) as in_handle: to_check = set([]) for line in in_handle: if not line.startswith("#"): to_check.add(line.split()[0]) if len(to_check) >= tocheck_contigs: break with open(checked_file, "w") as out_handle: if any([c not in contigs for c in to_check]): out_handle.write("different") return False else: out_handle.write("match") return True # ## Retrieval of mappings def read_mapping(url): mappings = {} for line in requests.get(url).text.split("\n"): parts = line.strip().split() if len(parts) == 2: first, second = parts mappings[str(first)] = str(second) return mappings bcbio-nextgen-1.2.9/bcbio/variation/normalize.py000066400000000000000000000132151415626112400216770ustar00rootroot00000000000000"""Normalization of VCF files for GEMINI and ensemble calling. 1. Split multi-allelic variants into single sample records. Downstream tools like GEMINI don't handle multi-allelic variants. `normalize` splits these into multiple single allele variants. More generally, multi-allelic variants are tricky to represent in comparisons and storage. There are useful discussions on-going in the GA4GH about allele/count based approaches to handling this more generally: https://github.com/ga4gh/schemas/issues/169 There are multiple approaches to do the decomposition: - vt decompose: https://github.com/atks/vt - vcfbreakmulti: https://github.com/ekg/vcflib - bcftools norm -m '-any': https://samtools.github.io/bcftools/bcftools.html - vcf_parser --split: https://github.com/moonso/vcf_parser https://github.com/moonso/genmod vt handles the most cases cleanly and correctly reconstructs PLs for each genotype, removing other FORMAT items which are not changed so the resulting VCF is still valid. 2. Decompose biallelic block substitutions As part of normalization, decompose MNPs into SNPs, e.g. AG>CT -> A>C and G>T There are a few approaches: - vcfallelicprimitives -t DECOMPOSED --keep-geno: https://github.com/vcflib/vcflib#vcfallelicprimitives - vt decompose_blocksub: https://genome.sph.umich.edu/wiki/Vt#Decompose_biallelic_block_substitutions with `-a`, align/aggressive mode is turned on, which runs 3-4 longer but resolves additional clumped SNPs We are using `vcfallelicprimitives` in this module. 3. Normalizing indels Left-align and normalize indels, check if REF alleles match the reference. - bcftools norm: https://samtools.github.io/bcftools/bcftools.html - vt normalize: https://github.com/atks/vt We are using `vt normalize` in this module. """ import os from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import effects, vcfutils cyvcf2 = utils.LazyImport("cyvcf2") def normalize(in_file, data, passonly=False, normalize_indels=True, split_biallelic=True, rerun_effects=True, remove_oldeffects=False, nonrefonly=False, work_dir=None): """Normalizes variants and reruns SnpEFF for resulting VCF """ if remove_oldeffects: out_file = "%s-noeff-nomultiallelic%s" % utils.splitext_plus(in_file) else: out_file = "%s-nomultiallelic%s" % utils.splitext_plus(in_file) if work_dir: out_file = os.path.join(work_dir, os.path.basename(out_file)) if not utils.file_exists(out_file): if vcfutils.vcf_has_variants(in_file): ready_ma_file = _normalize(in_file, data, passonly=passonly, normalize_indels=normalize_indels, split_biallelic=split_biallelic, remove_oldeffects=remove_oldeffects, nonrefonly=nonrefonly, work_dir=work_dir) if rerun_effects: ann_ma_file, _ = effects.add_to_vcf(ready_ma_file, data) if ann_ma_file: ready_ma_file = ann_ma_file utils.symlink_plus(ready_ma_file, out_file) else: utils.symlink_plus(in_file, out_file) return vcfutils.bgzip_and_index(out_file, data["config"]) def _normalize(in_file, data, passonly=False, normalize_indels=True, split_biallelic=True, remove_oldeffects=False, nonrefonly=False, work_dir=None): """Convert multi-allelic variants into single allelic. `vt normalize` has the -n flag passed (skipping reference checks) because of errors where the reference genome has non GATCN ambiguous bases. These are not supported in VCF, so you'll have a mismatch of N in VCF versus R (or other ambiguous bases) in the genome. """ if remove_oldeffects: out_file = "%s-noeff-decompose%s" % utils.splitext_plus(in_file) old_effects = [a for a in ["CSQ", "ANN"] if a in cyvcf2.VCF(in_file)] if old_effects: clean_effects_cmd = " | bcftools annotate -x %s " % (",".join(["INFO/%s" % x for x in old_effects])) else: clean_effects_cmd = "" else: clean_effects_cmd = "" out_file = "%s-decompose%s" % utils.splitext_plus(in_file) if passonly or nonrefonly: subset_vcf_cmd = " | bcftools view " if passonly: subset_vcf_cmd += "-f 'PASS,.' " if nonrefonly: subset_vcf_cmd += "--min-ac 1:nref " else: subset_vcf_cmd = "" if work_dir: out_file = os.path.join(work_dir, os.path.basename(out_file)) if not utils.file_exists(out_file): ref_file = dd.get_ref_file(data) assert out_file.endswith(".vcf.gz") with file_transaction(data, out_file) as tx_out_file: cmd = ("gunzip -c " + in_file + subset_vcf_cmd + clean_effects_cmd + (" | vcfallelicprimitives -t DECOMPOSED --keep-geno" if split_biallelic else "") + " | sed 's/ID=AD,Number=./ID=AD,Number=R/'" + " | vt decompose -s - " + ((" | vt normalize -n -r " + ref_file + " - ") if normalize_indels else "") + " | awk '{ gsub(\"./-65\", \"./.\"); print $0 }'" + " | sed -e 's/Number=A/Number=1/g'" + " | bgzip -c > " + tx_out_file ) do.run(cmd, "Multi-allelic to single allele") return vcfutils.bgzip_and_index(out_file, data["config"]) bcbio-nextgen-1.2.9/bcbio/variation/octopus.py000066400000000000000000000162431415626112400213770ustar00rootroot00000000000000"""Octopus germline and somatic calling. https://github.com/luntergroup/octopus """ import os import subprocess import pysam import six from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import bamprep, bedutils, vcfutils def run(align_bams, items, ref_file, assoc_files, region, out_file): """Run octopus variant calling, handling both somatic and germline calling. """ if not utils.file_exists(out_file): paired = vcfutils.get_paired_bams(align_bams, items) regions = _get_regions(region, out_file, items) if paired: return _run_somatic(paired, ref_file, regions, out_file) else: return _run_germline(align_bams, items, ref_file, regions, out_file) return out_file def _get_regions(region, out_file, items): """Retrieve region to run analysis in. Handles no targets, BED and regions. """ vrs = bedutils.population_variant_regions(items) target = shared.subset_variant_regions(vrs, region, out_file, items=items, do_merge=True) if target: if isinstance(target, six.string_types) and os.path.isfile(target): return "--regions-file %s" % target else: return "--regions %s" % bamprep.region_to_gatk(target) else: return "" def _produce_compatible_vcf(out_file, data, is_somatic=False): """Create a compatible VCF that downstream tools can deal with. - htsjdk and thus GATK and Picard do not support VCF4.3: https://github.com/broadinstitute/gatk/issues/2092 - Use octopus legacy format to avoid incompatibilities. https://github.com/luntergroup/octopus#output-format - Fixes `##contig` lines since octopus only writes contigs used in the BED file region, causing incompatibilies with GatherVcfs when merging - Fixes alleles prefixed with '*' like 'C,*T' which cause downstream failures when reading with GATK. - Changes phase set (PS) header to be type Integer. """ base, ext = utils.splitext_plus(out_file) #legacy_file = "%s.legacy%s" % (base, ext) legacy_file=out_file if is_somatic: legacy_file = _covert_to_diploid(legacy_file, data) final_file = "%s.vcf.gz" % base cat_cmd = "zcat" if legacy_file.endswith(".gz") else "cat" contig_cl = vcfutils.add_contig_to_header_cl(dd.get_ref_file(data), out_file) remove_problem_alleles = r"sed 's/,\*\([A-Z]\)/,\1/'" fix_phasing_header = r"sed 's/ID=PS,Number=1,Type=String/ID=PS,Number=1,Type=Integer/'" cmd = ("{cat_cmd} {legacy_file} | sed 's/fileformat=VCFv4.3/fileformat=VCFv4.2/' | " "{remove_problem_alleles} | {fix_phasing_header} | {contig_cl} | bgzip -c > {final_file}") do.run(cmd.format(**locals()), "Produce compatible VCF output file from octopus") return vcfutils.bgzip_and_index(out_file, data["config"]) def _covert_to_diploid(in_file, data): """Converts non-diploid somatic outputs into diploid. https://github.com/luntergroup/octopus/wiki/Case-study:-Tumour-only-UMI#evaluate-variant-calls """ sample = dd.get_sample_name(data) out_file = "%s-diploid.vcf" % utils.splitext_plus(in_file)[0] in_vcf = pysam.VariantFile(in_file) out_vcf = pysam.VariantFile(out_file, 'w', header=in_vcf.header) for record in in_vcf: gt = list(record.samples[sample]['GT']) if 'SOMATIC' in record.info: for allele in set(gt): if allele != gt[0]: record.samples[sample]['GT'] = gt[0], allele out_vcf.write(record) else: if len(gt) == 1: record.samples[sample]['GT'] = gt else: record.samples[sample]['GT'] = gt[0], gt[1] out_vcf.write(record) in_vcf.close() out_vcf.close() return vcfutils.bgzip_and_index(out_file, data["config"]) def _run_germline(align_bams, items, ref_file, regions, out_file): """Run germline calling, handling populations. TODO: - We could better handle trio calling with ped inputs as octopus has special support. """ align_bams = " ".join(align_bams) cores = dd.get_num_cores(items[0]) cmd = ("octopus --threads {cores} --reference {ref_file} --reads {align_bams} " "{regions} " "--working-directory {tmp_dir} " "-o {tx_out_file} --legacy") with file_transaction(items[0], out_file) as tx_out_file: tmp_dir = os.path.dirname(tx_out_file) do.run(cmd.format(**locals()), "Octopus germline calling") _produce_compatible_vcf(tx_out_file, items[0]) return out_file def _run_somatic(paired, ref_file, regions, out_file): """Run somatic calling with octopus, handling both paired and tumor-only cases. Tweaks for low frequency, tumor only and UMI calling documented in: https://github.com/luntergroup/octopus/blob/develop/configs/UMI.config """ align_bams = paired.tumor_bam if paired.normal_bam: align_bams += " %s --normal-sample %s" % (paired.normal_bam, paired.normal_name) cores = dd.get_num_cores(paired.tumor_data) # Do not try to search below 0.4% currently as leads to long runtimes # https://github.com/luntergroup/octopus/issues/29#issuecomment-428167979 min_af = max([float(dd.get_min_allele_fraction(paired.tumor_data)) / 100.0, 0.004]) min_af_floor = min_af / 4.0 # no somatic-snv-mutation-rate in octopus0.7.4 - use priors instead cmd = ("octopus --threads {cores} --reference {ref_file} --reads {align_bams} " "{regions} " "--min-credible-somatic-frequency {min_af_floor} --min-expected-somatic-frequency {min_af} " "--downsample-above 4000 --downsample-target 4000 --min-kmer-prune 5 --min-bubble-score 20 " "--max-haplotypes 200 --somatic-snv-prior '5e-4' --somatic-indel-prior '1e-05' " "--target-working-memory 5G --target-read-buffer-memory 5G --max-somatic-haplotypes 3 " "--caller cancer " "--working-directory {tmp_dir} " "-o {tx_out_file}") if not paired.normal_bam: cmd += (" --tumour-germline-concentration 5") if dd.get_umi_type(paired.tumor_data) or _is_umi_consensus_bam(paired.tumor_bam): cmd += (" --allow-octopus-duplicates --disable-overlap-masking " "--somatic-filter-expression 'GQ < 200 | MQ < 30 | SB > 0.2 | SD[.25] > 0.1 " "| BQ < 40 | DP < 100 | MF > 0.1 | AD < 5 | CC > 1.1 | GQD > 2'") with file_transaction(paired.tumor_data, out_file) as tx_out_file: tmp_dir = os.path.dirname(tx_out_file) do.run(cmd.format(**locals()), "Octopus somatic calling") _produce_compatible_vcf(tx_out_file, paired.tumor_data, is_somatic=True) return out_file def _is_umi_consensus_bam(in_file): """Check if input BAM file generated by fgbio consensus calls on UMIs. Identify these by lack of duplicated reads. This is useful for pre-aligned consensus BAMs feeding into octopus. """ cmd = "samtools view -h %s | head -500000 | samtools view -c -f 1024" count = subprocess.check_output(cmd % in_file, shell=True) return int(count) == 0 bcbio-nextgen-1.2.9/bcbio/variation/peddy.py000066400000000000000000000157401415626112400210110ustar00rootroot00000000000000""" correspondence checking with peddy (https://github.com/brentp/peddy) """ import collections import os import shutil import toolz as tz from collections import defaultdict from bcbio.distributed.transaction import tx_tmpdir from bcbio import utils from bcbio.cwl import cwlutils from bcbio.utils import safe_makedir, file_exists from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.log import logger from bcbio.variation import vcfutils, vcfanno from bcbio.variation.population import create_ped_file from bcbio.qc import variant from bcbio.provenance import do PEDDY_OUT_EXTENSIONS = [".background_pca.json", ".het_check.csv", ".pca_check.png", ".ped_check.png", ".ped_check.rel-difference.csv", ".ped_check.csv", ".peddy.ped", ".sex_check.csv", ".ped_check.png", ".html"] def run_peddy_parallel(samples, parallel_fn): batch_samples = get_samples_by_batch(samples) to_run = batch_samples.values() samples = parallel_fn("run_peddy", [[x] for x in to_run]) return [[utils.to_single_data(x)] for x in samples] def run_qc(_, data, out_dir): """Run quality control in QC environment on a single sample. Enables peddy integration with CWL runs. """ if cwlutils.is_cwl_run(data): qc_data = run_peddy([data], out_dir) if tz.get_in(["summary", "qc", "peddy"], qc_data): return tz.get_in(["summary", "qc", "peddy"], qc_data) def run_peddy(samples, out_dir=None): data = samples[0] batch = dd.get_batch(data) or dd.get_sample_name(data) if isinstance(batch, (list, tuple)): batch = batch[0] if out_dir: peddy_dir = safe_makedir(out_dir) else: peddy_dir = safe_makedir(os.path.join(dd.get_work_dir(data), "qc", batch, "peddy")) peddy_prefix = os.path.join(peddy_dir, batch) peddy_report = peddy_prefix + ".html" vcf_file = None for d in samples: vcinfo = None if dd.get_jointcaller(d): vcinfo = variant.extract_population_vcinfo(d) elif dd.get_phenotype(d) == "germline" or dd.get_phenotype(d) not in ["tumor"]: vcinfo = variant.get_active_vcinfo(d, use_ensemble=False) if not vcinfo and dd.get_phenotype(d) in ["tumor"]: vcinfo = variant.extract_germline_vcinfo(d, peddy_dir) if vcinfo: for key in ["germline", "vrn_file"]: if vcinfo and vcinfo.get(key) and utils.file_exists(vcinfo[key]): if vcinfo[key] and dd.get_sample_name(d) in vcfutils.get_samples(vcinfo[key]): if vcinfo[key] and vcfutils.vcf_has_nonfiltered_variants(vcinfo[key]): vcf_file = vcinfo[key] break peddy = config_utils.get_program("peddy", data) if config_utils.program_installed("peddy", data) else None config_skips = any(["peddy" in dd.get_tools_off(d) for d in samples]) if not peddy or not vcf_file or not vcfanno.is_human(data) or config_skips: if not peddy: reason = "peddy executable not found" elif config_skips: reason = "peddy in tools_off configuration" elif not vcfanno.is_human(data): reason = "sample is not human" else: assert not vcf_file reason = "no suitable VCF files found with the sample and non-filtered variants" msg = "Skipping peddy QC, %s: %s" % (reason, [dd.get_sample_name(d) for d in samples]) with open(peddy_prefix + "-failed.log", "w") as out_handle: out_handle.write(msg) logger.info(msg) return samples if file_exists(peddy_prefix + "-failed.log"): return samples if not file_exists(peddy_report): ped_file = create_ped_file(samples, vcf_file, out_dir=out_dir) num_cores = dd.get_num_cores(data) with tx_tmpdir(data) as tx_dir: peddy_prefix_tx = os.path.join(tx_dir, os.path.basename(peddy_prefix)) # Redirects stderr because incredibly noisy with no intervals found messages from cyvcf2 stderr_log = os.path.join(tx_dir, "run-stderr.log") sites_str = "--sites hg38" if dd.get_genome_build(data) == "hg38" else "" locale = utils.locale_export() cmd = ("{locale} {peddy} -p {num_cores} {sites_str} --plot --prefix {peddy_prefix_tx} " "{vcf_file} {ped_file} 2> {stderr_log}") message = "Running peddy on {vcf_file} against {ped_file}." try: do.run(cmd.format(**locals()), message.format(**locals())) except: to_show = collections.deque(maxlen=100) with open(stderr_log) as in_handle: for line in in_handle: to_show.append(line) def allowed_errors(l): return ((l.find("IndexError") >= 0 and l.find("is out of bounds for axis") >= 0) or (l.find("n_components=") >= 0 and l.find("must be between 1 and n_features=") >= 0) or (l.find("n_components=") >= 0 and l.find("must be between 1 and min") >= 0) or (l.find("Input contains NaN, infinity or a value too large for dtype") >= 0) or (l.find("peddy: no hets found for sample") >= 0) or (l.find("ValueError: need at least one array to concatenate") >= 0)) def all_line_errors(l): return (l.find("no intervals found for") >= 0) if any([allowed_errors(l) for l in to_show]) or all([all_line_errors(l) for l in to_show]): logger.info("Skipping peddy because no variants overlap with checks: %s" % batch) with open(peddy_prefix + "-failed.log", "w") as out_handle: out_handle.write("peddy did not find overlaps with 1kg sites in VCF, skipping") return samples else: logger.warning("".join(to_show)) raise for ext in PEDDY_OUT_EXTENSIONS: if os.path.exists(peddy_prefix_tx + ext): shutil.move(peddy_prefix_tx + ext, peddy_prefix + ext) peddyfiles = expected_peddy_files(peddy_report, batch) return dd.set_in_samples(samples, dd.set_summary_qc, peddyfiles) def get_samples_by_batch(samples): batch_samples = defaultdict(list) for data in dd.sample_data_iterator(samples): batch = dd.get_batch(data) or dd.get_sample_name(data) if isinstance(batch, list): batch = tuple(batch) batch_samples[batch].append(data) return batch_samples def expected_peddy_files(peddy_report, batch): peddydir = os.path.dirname(peddy_report) secondary = [batch + x for x in PEDDY_OUT_EXTENSIONS] secondary = [os.path.join(peddydir, x) for x in secondary] secondary = [x for x in secondary if os.path.exists(x)] return {"peddy": {"base": peddy_report, "secondary": secondary}} bcbio-nextgen-1.2.9/bcbio/variation/pisces.py000066400000000000000000000076701415626112400211750ustar00rootroot00000000000000"""Tumor only somatic calling with Pisces. https://github.com/Illumina/Pisces """ import os import shutil import pysam from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import bedutils, ploidy, vcfutils def run(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Run tumor only pisces calling Handles bgzipping output file and fixing VCF sample naming to match BAM sample. """ paired = vcfutils.get_paired_bams(align_bams, items) assert paired and not paired.normal_bam, ("Pisces supports tumor-only variant calling: %s" % (",".join([dd.get_sample_name(d) for d in items]))) vrs = bedutils.population_variant_regions(items) target = shared.subset_variant_regions(vrs, region, out_file, items=items, do_merge=True) min_af = float(dd.get_min_allele_fraction(paired.tumor_data)) / 100.0 if not utils.file_exists(out_file): base_out_name = utils.splitext_plus(os.path.basename(paired.tumor_bam))[0] raw_file = "%s.vcf" % utils.splitext_plus(out_file)[0] with file_transaction(paired.tumor_data, raw_file) as tx_out_file: ref_dir = _prep_genome(os.path.dirname(tx_out_file), paired.tumor_data) out_dir = os.path.dirname(tx_out_file) cores = dd.get_num_cores(paired.tumor_data) emit_min_af = min_af / 10.0 cmd = ("pisces --bampaths {paired.tumor_bam} --genomepaths {ref_dir} --intervalpaths {target} " "--maxthreads {cores} --minvf {emit_min_af} --vffilter {min_af} " "--ploidy somatic --gvcf false -o {out_dir}") # Recommended filtering for low frequency indels # https://github.com/bcbio/bcbio-nextgen/commit/49d0cbb1f6dcbea629c63749e2f9813bd06dcee3#commitcomment-29765373 cmd += " -RMxNFilter 5,9,0.35" # For low frequency UMI tagged variants, set higher variant thresholds # https://github.com/Illumina/Pisces/issues/14#issuecomment-399756862 if min_af < (1.0 / 100.0): cmd += " --minbasecallquality 30" do.run(cmd.format(**locals()), "Pisces tumor-only somatic calling") shutil.move(os.path.join(out_dir, "%s.vcf" % base_out_name), tx_out_file) vcfutils.bgzip_and_index(raw_file, paired.tumor_data["config"], prep_cmd="sed 's#%s.bam#%s#' | %s" % (base_out_name, dd.get_sample_name(paired.tumor_data), vcfutils.add_contig_to_header_cl(dd.get_ref_file(paired.tumor_data), out_file))) return vcfutils.bgzip_and_index(out_file, paired.tumor_data["config"]) def _prep_genome(out_dir, data): """Create prepped reference directory for pisces. Requires a custom GenomeSize.xml file present. """ genome_name = utils.splitext_plus(os.path.basename(dd.get_ref_file(data)))[0] out_dir = utils.safe_makedir(os.path.join(out_dir, genome_name)) ref_file = dd.get_ref_file(data) utils.symlink_plus(ref_file, os.path.join(out_dir, os.path.basename(ref_file))) with open(os.path.join(out_dir, "GenomeSize.xml"), "w") as out_handle: out_handle.write('' % genome_name) for c in pysam.AlignmentFile("%s.dict" % utils.splitext_plus(ref_file)[0]).header["SQ"]: cur_ploidy = ploidy.get_ploidy([data], region=[c["SN"]]) out_handle.write('' % (os.path.basename(ref_file), c["SN"], c["LN"], c["LN"], cur_ploidy, c["M5"])) out_handle.write('') return out_dir bcbio-nextgen-1.2.9/bcbio/variation/platypus.py000066400000000000000000000072541415626112400215660ustar00rootroot00000000000000"""Detect variants with the Platypus Haplotype-Based variant caller. http://www.well.ox.ac.uk/platypus https://github.com/andyrimmer/Platypus """ import os from bcbio import bam, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.pipeline import shared as pshared from bcbio.provenance import do from bcbio.variation import bamprep, bedutils, vcfutils import six def run(align_bams, items, ref_file, assoc_files, region, out_file): """Run platypus variant calling, germline whole genome or exome. """ assert out_file.endswith(".vcf.gz") if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: for align_bam in align_bams: bam.index(align_bam, items[0]["config"]) cmd = ["platypus", "callVariants", "--regions=%s" % _subset_regions(region, out_file, items), "--bamFiles=%s" % ",".join(align_bams), "--refFile=%s" % dd.get_ref_file(items[0]), "--output=-", "--logFileName", "/dev/null", "--verbosity=1"] resources = config_utils.get_resources("platypus", items[0]["config"]) if resources.get("options"): # normalize options so we can set defaults without overwriting user specified for opt in resources["options"]: if "=" in opt: key, val = opt.split("=") cmd.extend([key, val]) else: cmd.append(opt) if any("gvcf" in dd.get_tools_on(d) for d in items): cmd += ["--outputRefCalls", "1", "--refCallBlockSize", "50000"] # Adjust default filter thresholds to achieve similar sensitivity/specificity to other callers # Currently not used after doing more cross validation as they increase false positives # which seems to be a major advantage for Platypus users. # tuned_opts = ["--hapScoreThreshold", "10", "--scThreshold", "0.99", "--filteredReadsFrac", "0.9", # "--rmsmqThreshold", "20", "--qdThreshold", "0", "--abThreshold", "0.0001", # "--minVarFreq", "0.0", "--assemble", "1"] # for okey, oval in utils.partition_all(2, tuned_opts): # if okey not in cmd: # cmd.extend([okey, oval]) # Avoid filtering duplicates on high depth targeted regions where we don't mark duplicates if any(not dd.get_mark_duplicates(data) for data in items): cmd += ["--filterDuplicates=0"] post_process_cmd = (" | %s | %s | %s | vcfallelicprimitives -t DECOMPOSED --keep-geno | vcffixup - | " "vcfstreamsort | bgzip -c > %s" % (vcfutils.fix_ambiguous_cl(), vcfutils.fix_ambiguous_cl(5), vcfutils.add_contig_to_header_cl(dd.get_ref_file(items[0]), tx_out_file), tx_out_file)) do.run(" ".join(cmd) + post_process_cmd, "platypus variant calling") out_file = vcfutils.bgzip_and_index(out_file, items[0]["config"]) return out_file def _subset_regions(region, base_file, items): """Subset to a BED file (or genomic region) for calling. """ variant_regions = bedutils.population_variant_regions(items, merged=True) target = pshared.subset_variant_regions(variant_regions, region, base_file, items) if isinstance(target, six.string_types) and os.path.isfile(target): return target else: return bamprep.region_to_gatk(target) bcbio-nextgen-1.2.9/bcbio/variation/ploidy.py000066400000000000000000000070561415626112400212050ustar00rootroot00000000000000"""Calculate expected ploidy for a genomic regions. Handles configured ploidy, with custom handling for sex chromosomes and pooled haploid mitochondrial DNA. """ import collections import io import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.variation import vcfutils def chromosome_special_cases(chrom): if chrom in ["MT", "M", "chrM", "chrMT"]: return "mitochondrial" elif chrom in ["X", "chrX"]: return "X" elif chrom in ["Y", "chrY"]: return "Y" else: return chrom def _configured_ploidy(items): ploidies = collections.defaultdict(set) for data in items: ploidy = dd.get_ploidy(data) if isinstance(ploidy, dict): for k, v in ploidy.items(): ploidies[k].add(v) else: ploidies["default"].add(ploidy) out = {} for k, vs in ploidies.items(): assert len(vs) == 1, "Multiple ploidies set for group calling: %s %s" % (k, list(vs)) out[k] = vs.pop() return out def _configured_genders(items): return set([str(tz.get_in(["metadata", "sex"], data, "")).lower() for data in items]) def get_ploidy(items, region=None): """Retrieve ploidy of a region, handling special cases. """ chrom = chromosome_special_cases(region[0] if isinstance(region, (list, tuple)) else None) ploidy = _configured_ploidy(items) sexes = _configured_genders(items) if chrom == "mitochondrial": # For now, do haploid calling. Could also do pooled calling # but not entirely clear what the best default would be. return ploidy.get("mitochondrial", 1) elif chrom == "X": # Do standard diploid calling if we have any females or unspecified. if "female" in sexes or "f" in sexes: return ploidy.get("female", ploidy["default"]) elif "male" in sexes or "m" in sexes: return ploidy.get("male", 1) else: return ploidy.get("female", ploidy["default"]) elif chrom == "Y": # Always call Y single. If female, filter_vcf_by_sex removes Y regions. return 1 else: return ploidy["default"] def filter_vcf_by_sex(vcf_file, items): """Post-filter a single sample VCF, handling sex chromosomes. Removes Y chromosomes from batches with all female samples. """ out_file = "%s-ploidyfix%s" % utils.splitext_plus(vcf_file) if not utils.file_exists(out_file): genders = list(_configured_genders(items)) is_female = len(genders) == 1 and genders[0] and genders[0] in ["female", "f"] if is_female: orig_out_file = out_file out_file = orig_out_file.replace(".vcf.gz", ".vcf") with file_transaction(items[0], out_file) as tx_out_file: with io.open(tx_out_file, "w", encoding="utf-8") as out_handle: with utils.open_gzipsafe(vcf_file) as in_handle: for line in in_handle: if line.startswith("#"): out_handle.write(line) else: chrom = chromosome_special_cases(line.split("\t")) if chrom != "Y": out_handle.write(line) if orig_out_file.endswith(".gz"): out_file = vcfutils.bgzip_and_index(out_file, items[0]["config"]) else: out_file = vcf_file return out_file bcbio-nextgen-1.2.9/bcbio/variation/population.py000066400000000000000000000446241415626112400221010ustar00rootroot00000000000000"""Provide infrastructure to allow exploration of variations within populations. Uses the gemini framework (https://github.com/arq5x/gemini) to build SQLite database of variations for query and evaluation. """ import collections import csv import os import toolz as tz from bcbio import install, utils from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import normalize, vcfanno, vcfutils # Current callers we can't create databases for # mutect2 -- fails on multi-allelic inputs represented as non-diploid # https://github.com/broadinstitute/gatk/issues/3564 # Ensemble calls contain a mix of variant inputs which aren't suited # for GEMINI database creation NO_DB_CALLERS = ["mutect2", "ensemble"] def prep_gemini_db(fnames, call_info, samples, extras): """Prepare a gemini database from VCF inputs prepared with snpEff. """ data = samples[0] name, caller, is_batch = call_info build_type = _get_build_type(fnames, samples, caller) out_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "gemini")) # could be multisample vcf of a SNV PON vcf gemini_vcf = get_multisample_vcf(fnames, name, caller, data) # If we're building a gemini database, normalize the inputs if build_type: passonly = all("gemini_allvariants" not in dd.get_tools_on(d) for d in samples) gemini_vcf = normalize.normalize(gemini_vcf, data, passonly=passonly) decomposed = True else: decomposed = False ann_vcf = run_vcfanno(gemini_vcf, data, decomposed) gemini_db = os.path.join(out_dir, "%s-%s.db" % (name, caller)) if ann_vcf and build_type and not utils.file_exists(gemini_db): ped_file = create_ped_file(samples + extras, gemini_vcf) # Original approach for hg19/GRCh37 if vcfanno.is_human(data, builds=["37"]) and "gemini_orig" in build_type: gemini_db = create_gemini_db_orig(gemini_vcf, data, gemini_db, ped_file) else: gemini_db = create_gemini_db(ann_vcf, data, gemini_db, ped_file) # only pass along gemini_vcf_downstream if uniquely created here if os.path.islink(gemini_vcf): gemini_vcf = None return [[(name, caller), {"db": gemini_db if utils.file_exists(gemini_db) else None, "vcf": ann_vcf or gemini_vcf, "decomposed": decomposed}]] def _back_compatible_gemini(conf_files, data): """Provide old install directory for configuration with GEMINI supplied tidy VCFs. Handles new style (bcbio installed) and old style (GEMINI installed) configuration and data locations. """ if vcfanno.is_human(data, builds=["37"]): for f in conf_files: if f and os.path.basename(f) == "gemini.conf" and os.path.exists(f): with open(f) as in_handle: for line in in_handle: if line.startswith("file"): fname = line.strip().split("=")[-1].replace('"', '').strip() if fname.find(".tidy.") > 0: return install.get_gemini_dir(data) return None def run_vcfanno(vcf_file, data, decomposed=False): """Run vcfanno, providing annotations from external databases if needed. Puts together lua and conf files from multiple inputs by file names. """ conf_files = dd.get_vcfanno(data) if conf_files: with_basepaths = collections.defaultdict(list) gemini_basepath = _back_compatible_gemini(conf_files, data) for f in conf_files: name = os.path.splitext(os.path.basename(f))[0] if f.endswith(".lua"): conf_file = None lua_file = f else: conf_file = f lua_file = "%s.lua" % utils.splitext_plus(conf_file)[0] if lua_file and not os.path.exists(lua_file): lua_file = None data_basepath = gemini_basepath if name == "gemini" else None if conf_file and os.path.exists(conf_file): with_basepaths[(data_basepath, name)].append(conf_file) if lua_file and os.path.exists(lua_file): with_basepaths[(data_basepath, name)].append(lua_file) conf_files = with_basepaths.items() out_file = None if conf_files: VcfannoIn = collections.namedtuple("VcfannoIn", ["conf", "lua"]) bp_files = collections.defaultdict(list) for (data_basepath, name), anno_files in conf_files: anno_files = list(set(anno_files)) if len(anno_files) == 1: cur = VcfannoIn(anno_files[0], None) elif len(anno_files) == 2: lua_files = [x for x in anno_files if x.endswith(".lua")] assert len(lua_files) == 1, anno_files lua_file = lua_files[0] anno_files.remove(lua_file) cur = VcfannoIn(anno_files[0], lua_file) else: raise ValueError("Unexpected annotation group %s" % anno_files) bp_files[data_basepath].append(cur) for data_basepath, anno_files in bp_files.items(): ann_file = vcfanno.run(vcf_file, [x.conf for x in anno_files], [x.lua for x in anno_files], data, basepath=data_basepath, decomposed=decomposed) if ann_file: out_file = ann_file vcf_file = ann_file return out_file def create_gemini_db(gemini_vcf, data, gemini_db=None, ped_file=None): """Generalized vcfanno/vcf2db workflow for loading variants into a GEMINI database. """ if not gemini_db: gemini_db = "%s.db" % utils.splitext_plus(gemini_vcf)[0] if not vcfutils.vcf_has_variants(gemini_vcf): return None if not utils.file_exists(gemini_db): with file_transaction(data, gemini_db) as tx_gemini_db: vcf2db = config_utils.get_program("vcf2db.py", data) if "vcf2db_expand" in dd.get_tools_on(data): vcf2db_args = ["--expand", "gt_types", "--expand", "gt_ref_depths", "--expand", "gt_alt_depths"] else: vcf2db_args = [] cmd = [vcf2db, gemini_vcf, ped_file, tx_gemini_db] + vcf2db_args do.run(cmd, "GEMINI: create database with vcf2db") return gemini_db def create_gemini_db_orig(gemini_vcf, data, gemini_db=None, ped_file=None): """Original GEMINI specific data loader, only works with hg19/GRCh37. """ if not gemini_db: gemini_db = "%s.db" % utils.splitext_plus(gemini_vcf)[0] if not utils.file_exists(gemini_db): if not vcfutils.vcf_has_variants(gemini_vcf): return None with file_transaction(data, gemini_db) as tx_gemini_db: gemini = config_utils.get_program("gemini", data["config"]) load_opts = "" if "gemini_allvariants" not in dd.get_tools_on(data): load_opts += " --passonly" # For small test files, skip gene table loading which takes a long time if _is_small_vcf(gemini_vcf): load_opts += " --skip-gene-tables" if "/test_automated_output/" in gemini_vcf: load_opts += " --test-mode" # Skip CADD or gerp-bp if neither are loaded gemini_dir = install.get_gemini_dir(data) for skip_cmd, check_file in [("--skip-cadd", "whole_genome_SNVs.tsv.compressed.gz")]: if not os.path.exists(os.path.join(gemini_dir, check_file)): load_opts += " %s" % skip_cmd # skip gerp-bp which slows down loading load_opts += " --skip-gerp-bp " num_cores = data["config"]["algorithm"].get("num_cores", 1) tmpdir = os.path.dirname(tx_gemini_db) eanns = _get_effects_flag(data) # Apply custom resource specifications, allowing use of alternative annotation_dir resources = config_utils.get_resources("gemini", data["config"]) gemini_opts = " ".join([str(x) for x in resources["options"]]) if resources.get("options") else "" exports = utils.local_path_export() cmd = ("{exports} {gemini} {gemini_opts} load {load_opts} " "-v {gemini_vcf} {eanns} --cores {num_cores} " "--tempdir {tmpdir} {tx_gemini_db}") cmd = cmd.format(**locals()) do.run(cmd, "Create gemini database for %s" % gemini_vcf, data) if ped_file: cmd = [gemini, "amend", "--sample", ped_file, tx_gemini_db] do.run(cmd, "Add PED file to gemini database", data) return gemini_db def _get_effects_flag(data): effects_config = tz.get_in(("config", "algorithm", "effects"), data, "snpeff") if effects_config == "snpeff": return "-t snpEff" elif effects_config == "vep": return "-t VEP" else: return "" def get_affected_status(data): """Retrieve the affected/unaffected status of sample. Uses unaffected (1), affected (2), unknown (0) coding from PED files: http://pngu.mgh.harvard.edu/~purcell/plink/data.shtml#ped """ affected = set(["tumor", "affected", "2"]) unaffected = set(["normal", "unaffected", "1"]) phenotype = str(tz.get_in(["metadata", "phenotype"], data, "")).lower() if dd.get_svclass(data) == "control": return 1 elif phenotype in affected: return 2 elif phenotype in unaffected: return 1 else: return 0 def get_gender(data): """Retrieve gender from metadata, codified as male/female/unknown. """ g = str(dd.get_gender(data)) if g and str(g).lower() in ["male", "m", "1"]: return "male" elif g and str(g).lower() in ["female", "f", "2"]: return "female" else: return "unknown" def get_ped_info(data, samples): """Retrieve all PED info from metadata """ family_id = tz.get_in(["metadata", "family_id"], data, None) if not family_id: family_id = _find_shared_batch(samples) return { "gender": {"male": 1, "female": 2, "unknown": 0}.get(get_gender(data)), "individual_id": dd.get_sample_name(data), "family_id": family_id, "maternal_id": tz.get_in(["metadata", "maternal_id"], data, -9), "paternal_id": tz.get_in(["metadata", "paternal_id"], data, -9), "affected": get_affected_status(data) } def create_ped_file(samples, base_vcf, out_dir=None): """Create a GEMINI-compatible PED file, including gender, family and phenotype information. Checks for a specified `ped` file in metadata, and will use sample information from this file before reconstituting from metadata information. """ out_file = "%s.ped" % utils.splitext_plus(base_vcf)[0] if out_dir: out_file = os.path.join(out_dir, os.path.basename(out_file)) sample_ped_lines = {} header = ["#Family_ID", "Individual_ID", "Paternal_ID", "Maternal_ID", "Sex", "Phenotype"] for md_ped in list(set([x for x in [tz.get_in(["metadata", "ped"], data) for data in samples] if x is not None])): with open(md_ped) as in_handle: reader = csv.reader(in_handle, dialect="excel-tab") for parts in reader: if parts[0].startswith("#") and len(parts) > len(header): header = header + parts[len(header):] else: sample_ped_lines[parts[1]] = parts if not utils.file_exists(out_file): with file_transaction(samples[0], out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: want_samples = set(vcfutils.get_samples(base_vcf)) writer = csv.writer(out_handle, dialect="excel-tab") writer.writerow(header) for data in samples: ped_info = get_ped_info(data, samples) sname = ped_info["individual_id"] if sname in want_samples: want_samples.remove(sname) if sname in sample_ped_lines: writer.writerow(sample_ped_lines[sname]) else: writer.writerow([ped_info["family_id"], ped_info["individual_id"], ped_info["paternal_id"], ped_info["maternal_id"], ped_info["gender"], ped_info["affected"]]) return out_file def _find_shared_batch(samples): for data in samples: batch = tz.get_in(["metadata", "batch"], data, dd.get_sample_name(data)) if not isinstance(batch, (list, tuple)): return batch def _is_small_vcf(vcf_file): """Check for small VCFs which we want to analyze quicker. """ count = 0 small_thresh = 250 with utils.open_gzipsafe(vcf_file) as in_handle: for line in in_handle: if not line.startswith("#"): count += 1 if count > small_thresh: return False return True def get_multisample_vcf(fnames, name, caller, data): """Retrieve a multiple sample VCF file in a standard location. Handles inputs with multiple repeated input files from batches. """ unique_fnames = [] for f in fnames: if f not in unique_fnames: unique_fnames.append(f) out_dir = utils.safe_makedir(os.path.join(data["dirs"]["work"], "gemini")) if len(unique_fnames) > 1: gemini_vcf = os.path.join(out_dir, "%s-%s.vcf.gz" % (name, caller)) vrn_file_batch = None for variant in data.get("variants", []): if variant["variantcaller"] == caller and variant.get("vrn_file_batch"): vrn_file_batch = variant["vrn_file_batch"] if vrn_file_batch: utils.symlink_plus(vrn_file_batch, gemini_vcf) return gemini_vcf else: return vcfutils.merge_variant_files(unique_fnames, gemini_vcf, dd.get_ref_file(data), data["config"]) else: gemini_vcf = os.path.join(out_dir, "%s-%s%s" % (name, caller, utils.splitext_plus(unique_fnames[0])[1])) utils.symlink_plus(unique_fnames[0], gemini_vcf) return gemini_vcf def _get_build_type(fnames, samples, caller): """Confirm we should build a gemini database: need gemini in tools_on. Checks for valid conditions for running a database and gemini or gemini_orig configured in tools on. """ build_type = set() if any(vcfutils.vcf_has_variants(f) for f in fnames) and caller not in NO_DB_CALLERS: for data in samples: if any([x in dd.get_tools_on(data) for x in ["gemini", "gemini_orig", "gemini_allvariants", "vcf2db_expand"]]): if vcfanno.annotate_gemini(data): build_type.add("gemini_orig" if "gemini_orig" in dd.get_tools_on(data) else "gemini") else: logger.info("Not running gemini, input data not found: %s" % dd.get_sample_name(data)) else: logger.info("Not running gemini, not configured in tools_on: %s" % dd.get_sample_name(data)) else: logger.info("Not running gemini, no samples with variants found: %s" % (", ".join([dd.get_sample_name(d) for d in samples]))) return build_type def get_gemini_files(data): """Enumerate available gemini data files in a standard installation. """ try: from gemini import annotations, config except ImportError: return {} return {"base": config.read_gemini_config()["annotation_dir"], "files": annotations.get_anno_files().values()} def _group_by_batches(samples, check_fn): """Group data items into batches, providing details to retrieve results. """ batch_groups = collections.defaultdict(list) singles = [] out_retrieve = [] extras = [] for data in [x[0] for x in samples]: if check_fn(data): batch = tz.get_in(["metadata", "batch"], data) name = str(dd.get_sample_name(data)) if batch: out_retrieve.append((str(batch), data)) else: out_retrieve.append((name, data)) for vrn in data["variants"]: if vrn.get("population", True): if batch: batch_groups[(str(batch), vrn["variantcaller"])].append((vrn["vrn_file"], data)) else: singles.append((name, vrn["variantcaller"], data, vrn["vrn_file"])) else: extras.append(data) return batch_groups, singles, out_retrieve, extras def _has_variant_calls(data): for vrn in data["variants"]: if vrn.get("vrn_file") and vcfutils.vcf_has_variants(vrn["vrn_file"]): return True return False def prep_db_parallel(samples, parallel_fn): """Prepares gemini databases in parallel, handling jointly called populations. """ batch_groups, singles, out_retrieve, extras = _group_by_batches(samples, _has_variant_calls) to_process = [] has_batches = False for (name, caller), info in batch_groups.items(): fnames = [x[0] for x in info] to_process.append([fnames, (str(name), caller, True), [x[1] for x in info], extras]) has_batches = True for name, caller, data, fname in singles: to_process.append([[fname], (str(name), caller, False), [data], extras]) output = parallel_fn("prep_gemini_db", to_process) out_fetch = {} for batch_id, out_file in output: out_fetch[tuple(batch_id)] = out_file out = [] for batch_name, data in out_retrieve: out_variants = [] for vrn in data["variants"]: use_population = vrn.pop("population", True) if use_population: vrn["population"] = out_fetch[(batch_name, vrn["variantcaller"])] out_variants.append(vrn) data["variants"] = out_variants # save SNV PON file name to use when creating normal_db if batch_name == "pon_build": data["config"]["algorithm"]["purecn_snv_pon"] = output[0][1]["vcf"] out.append([data]) for x in extras: out.append([x]) return out bcbio-nextgen-1.2.9/bcbio/variation/prioritize.py000066400000000000000000000216171415626112400221040ustar00rootroot00000000000000"""Prioritization scheme for identifying follow up variants in tumor-only samples. Generalizes the filtering scheme used in VarDict post-processing: https://github.com/AstraZeneca-NGS/VarDict/blob/9ffec9168e91534fac5fb74b3ec7bdd2badd3464/vcf2txt.pl#L190 The goal is to build up a standard set of prioritization filters based on known data. Uses GEMINI to load a database of variants with associated third party query information. Makes use of ExAC, dbSNP, 1000 genomes, clinvar, cosmic and effects annotations. The general idea is to prioritize deleterious variants missing or present at a low frequency in the population, or secondarily identified in external databases like COSMIC and ClinVar. """ import collections import csv import re from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import population, vcfutils geneimpacts = utils.LazyImport("geneimpacts") cyvcf2 = utils.LazyImport("cyvcf2") def handle_vcf_calls(vcf_file, data, orig_items): """Prioritize VCF calls based on external annotations supplied through GEMINI. """ if not _do_prioritize(orig_items): return vcf_file else: ann_vcf = population.run_vcfanno(vcf_file, data) if ann_vcf: priority_file = _prep_priority_filter_vcfanno(ann_vcf, data) return _apply_priority_filter(ann_vcf, priority_file, data) # No data available for filtering, return original file else: return vcf_file def _apply_priority_filter(in_file, priority_file, data): """Annotate variants with priority information and use to apply filters. """ out_file = "%s-priority%s" % utils.splitext_plus(in_file) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: header = ('##INFO=') header_file = "%s-repeatheader.txt" % utils.splitext_plus(tx_out_file)[0] with open(header_file, "w") as out_handle: out_handle.write(header) if "tumoronly_germline_filter" in dd.get_tools_on(data): filter_cmd = ("bcftools filter -m '+' -s 'LowPriority' " """-e "EPR[0] != 'pass'" |""") else: filter_cmd = "" # bcftools 1.13+ requires to skip TO cmd = ("bcftools annotate -a {priority_file} -h {header_file} " "-c CHROM,FROM,-,REF,ALT,INFO/EPR {in_file} | " "{filter_cmd} bgzip -c > {tx_out_file}") do.run(cmd.format(**locals()), "Run external annotation based prioritization filtering") vcfutils.bgzip_and_index(out_file, data["config"]) return out_file def _prep_priority_filter_vcfanno(in_vcf, data): """Prepare tabix file with priority filters based on vcfanno annotations. """ pops = ['af_adj_exac_afr', 'af_adj_exac_amr', 'af_adj_exac_eas', 'af_adj_exac_fin', 'af_adj_exac_nfe', 'af_adj_exac_oth', 'af_adj_exac_sas', 'af_exac_all', 'max_aaf_all', "af_esp_ea", "af_esp_aa", "af_esp_all", "af_1kg_amr", "af_1kg_eas", "af_1kg_sas", "af_1kg_afr", "af_1kg_eur", "af_1kg_all"] known = ["cosmic_ids", "cosmic_id", "clinvar_sig"] out_file = "%s-priority.tsv" % utils.splitext_plus(in_vcf)[0] if not utils.file_exists(out_file) and not utils.file_exists(out_file + ".gz"): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: writer = csv.writer(out_handle, dialect="excel-tab") header = ["#chrom", "start", "end", "ref", "alt", "filter"] writer.writerow(header) vcf_reader = cyvcf2.VCF(in_vcf) impact_info = _get_impact_info(vcf_reader) for rec in vcf_reader: row = _prepare_vcf_rec(rec, pops, known, impact_info) cur_filter = _calc_priority_filter(row, pops) writer.writerow([rec.CHROM, rec.start, rec.end, rec.REF, ",".join(rec.ALT), cur_filter]) return vcfutils.bgzip_and_index(out_file, data["config"], tabix_args="-0 -c '#' -s 1 -b 2 -e 3") def _get_impact_info(vcf_reader): """Retrieve impact parsing information from INFO header. """ ImpactInfo = collections.namedtuple("ImpactInfo", "header, gclass, id") KEY_2_CLASS = { 'CSQ': geneimpacts.VEP, 'ANN': geneimpacts.SnpEff, 'BCSQ': geneimpacts.BCFT} for l in (x.strip() for x in _from_bytes(vcf_reader.raw_header).split("\n")): if l.startswith("##INFO"): patt = re.compile(r"(\w+)=(\"[^\"]+\"|[^,]+)") stub = l.split("=<")[1].rstrip(">") d = dict(patt.findall(_from_bytes(stub))) if d["ID"] in KEY_2_CLASS: return ImpactInfo(_parse_impact_header(d), KEY_2_CLASS[d["ID"]], d["ID"]) def _from_bytes(s): if isinstance(s, bytes): import locale ENC = locale.getpreferredencoding() try: return s.decode(ENC) except UnicodeDecodeError: return s.decode('utf8') return s def _parse_impact_header(hdr_dict): """Parse fields for impact, taken from vcf2db """ desc = hdr_dict["Description"] if hdr_dict["ID"] == "ANN": parts = [x.strip("\"'") for x in re.split("\s*\|\s*", desc.split(":", 1)[1].strip('" '))] elif hdr_dict["ID"] == "EFF": parts = [x.strip(" [])'(\"") for x in re.split("\||\(", desc.split(":", 1)[1].strip())] elif hdr_dict["ID"] == "CSQ": parts = [x.strip(" [])'(\"") for x in re.split("\||\(", desc.split(":", 1)[1].strip())] elif hdr_dict["ID"] == "BCSQ": parts = desc.split(']', 1)[1].split(']')[0].replace('[','').split("|") else: raise Exception("don't know how to use %s as annotation" % hdr_dict["ID"]) return parts def _prepare_vcf_rec(rec, pops, known, impact_info): """Parse a vcfanno output into a dictionary of useful attributes. """ out = {} for k in pops + known: out[k] = rec.INFO.get(k) if impact_info: cur_info = rec.INFO.get(impact_info.id) if cur_info: cur_impacts = [impact_info.gclass(e, impact_info.header) for e in _from_bytes(cur_info).split(",")] top = geneimpacts.Effect.top_severity(cur_impacts) if isinstance(top, list): top = top[0] out["impact_severity"] = top.effect_severity return out def _calc_priority_filter(row, pops): """Calculate the priority filter based on external associated data. - Pass high/medium impact variants not found in population databases - Pass variants found in COSMIC or Clinvar provided they don't have two additional reasons to filter (found in multiple external populations) """ filters = [] passes = [] passes.extend(_find_known(row)) filters.extend(_known_populations(row, pops)) if len(filters) == 0 or (len(passes) > 0 and len(filters) < 2): passes.insert(0, "pass") return ",".join(passes + filters) def _known_populations(row, pops): """Find variants present in substantial frequency in population databases. """ cutoff = 0.01 out = set([]) for pop, base in [("esp", "af_esp_all"), ("1000g", "af_1kg_all"), ("exac", "af_exac_all"), ("anypop", "max_aaf_all")]: for key in [x for x in pops if x.startswith(base)]: val = row[key] if val and val > cutoff: out.add(pop) return sorted(list(out)) def _find_known(row): """Find variant present in known pathogenic databases. """ out = [] clinvar_no = set(["unknown", "untested", "non-pathogenic", "probable-non-pathogenic", "uncertain_significance", "uncertain_significance", "not_provided", "benign", "likely_benign"]) if row["cosmic_ids"] or row["cosmic_id"]: out.append("cosmic") if row["clinvar_sig"] and not row["clinvar_sig"].lower() in clinvar_no: out.append("clinvar") return out def _do_prioritize(items): """Determine if we should perform prioritization. Currently done on tumor-only input samples and feeding into PureCN which needs the germline annotations. """ if not any("tumoronly-prioritization" in dd.get_tools_off(d) for d in items): if vcfutils.get_paired_phenotype(items[0]): has_tumor = False has_normal = False for sub_data in items: if vcfutils.get_paired_phenotype(sub_data) == "tumor": has_tumor = True elif vcfutils.get_paired_phenotype(sub_data) == "normal": has_normal = True return has_tumor and not has_normal bcbio-nextgen-1.2.9/bcbio/variation/qsnp.py000066400000000000000000000224111415626112400206560ustar00rootroot00000000000000"""identify somatic variants in cancer samples https://qcmg.org/bioinformatics/tiki-index.php?page=qSNP#EXAMPLES """ from __future__ import print_function import os import shutil from re import sub from bcbio import utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.pipeline import config_utils from bcbio.pipeline.shared import subset_variant_regions from bcbio.provenance import do from bcbio.variation import annotation, bedutils from bcbio.variation.vcfutils import get_paired_bams, bgzip_and_index, combine_variant_files, PairedData import six def is_installed(config): """Check for qsnp installation on machine. """ try: config_utils.get_program("qsnp", config) return True except config_utils.CmdNotFound: return False def run_qsnp(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Run qSNP calling on paired tumor/normal. """ if utils.file_exists(out_file): return out_file paired = get_paired_bams(align_bams, items) if paired.normal_bam: region_files = [] regions = _clean_regions(items, region) if regions: for region in regions: out_region_file = out_file.replace(".vcf.gz", _to_str(region) + ".vcf.gz") region_file = _run_qsnp_paired(align_bams, items, ref_file, assoc_files, region, out_region_file) region_files.append(region_file) out_file = combine_variant_files(region_files, out_file, ref_file, items[0]["config"]) if not region: out_file = _run_qsnp_paired(align_bams, items, ref_file, assoc_files, region, out_file) return out_file else: raise ValueError("qSNP only works on paired samples") def _run_qsnp_paired(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect somatic mutations with qSNP. This is used for paired tumor / normal samples. """ config = items[0]["config"] if out_file is None: out_file = "%s-paired-variants.vcf" % os.path.splitext(align_bams[0])[0] if not utils.file_exists(out_file): out_file = out_file.replace(".gz", "") with file_transaction(config, out_file) as tx_out_file: with tx_tmpdir(config) as tmpdir: with utils.chdir(tmpdir): paired = get_paired_bams(align_bams, items) qsnp = config_utils.get_program("qsnp", config) resources = config_utils.get_resources("qsnp", config) mem = " ".join(resources.get("jvm_opts", ["-Xms750m -Xmx4g"])) qsnp_log = os.path.join(tmpdir, "qsnp.log") qsnp_init = os.path.join(tmpdir, "qsnp.ini") if region: paired = _create_bam_region(paired, region, tmpdir) _create_input(paired, tx_out_file, ref_file, assoc_files['dbsnp'], qsnp_init) cl = ("{qsnp} {mem} -i {qsnp_init} -log {qsnp_log}") do.run(cl.format(**locals()), "Genotyping paired variants with Qsnp", {}) out_file = _filter_vcf(out_file) out_file = bgzip_and_index(out_file, config) return out_file def _clean_regions(items, region): """Intersect region with target file if it exists""" variant_regions = bedutils.population_variant_regions(items, merged=True) with utils.tmpfile() as tx_out_file: target = subset_variant_regions(variant_regions, region, tx_out_file, items) if target: if isinstance(target, six.string_types) and os.path.isfile(target): target = _load_regions(target) else: target = [target] return target def _load_regions(target): """Get list of tupples from bed file""" regions = [] with open(target) as in_handle: for line in in_handle: if not line.startswith("#"): c, s, e = line.strip().split("\t") regions.append((c, s, e)) return regions def _create_bam_region(paired, region, tmp_dir): """create temporal normal/tumor bam_file only with reads on that region""" tumor_name, normal_name = paired.tumor_name, paired.normal_name normal_bam = _slice_bam(paired.normal_bam, region, tmp_dir, paired.tumor_config) tumor_bam = _slice_bam(paired.tumor_bam, region, tmp_dir, paired.tumor_config) paired = PairedData(tumor_bam, tumor_name, normal_bam, normal_name, None, None, None) return paired def _slice_bam(in_bam, region, tmp_dir, config): """Use sambamba to slice a bam region""" name_file = os.path.splitext(os.path.basename(in_bam))[0] out_file = os.path.join(tmp_dir, os.path.join(tmp_dir, name_file + _to_str(region) + ".bam")) sambamba = config_utils.get_program("sambamba", config) region = _to_sambamba(region) with file_transaction(out_file) as tx_out_file: cmd = ("{sambamba} slice {in_bam} {region} -o {tx_out_file}") do.run(cmd.format(**locals()), "Slice region", {}) return out_file def _create_input(paired, out_file, ref_file, snp_file, qsnp_file): """Create INI input for qSNP""" ini_file["[inputFiles]"]["dbSNP"] = snp_file ini_file["[inputFiles]"]["ref"] = ref_file ini_file["[inputFiles]"]["normalBam"] = paired.normal_bam ini_file["[inputFiles]"]["tumourBam"] = paired.tumor_bam ini_file["[ids]"]["normalSample"] = paired.normal_name ini_file["[ids]"]["tumourSample"] = paired.tumor_name ini_file["[ids]"]["donor"] = paired.tumor_name ini_file["[outputFiles]"]["vcf"] = out_file with open(qsnp_file, "w") as out_handle: for k, v in ini_file.items(): out_handle.write("%s\n" % k) for opt, value in v.items(): if value != "": out_handle.write("%s = %s\n" % (opt, value)) def _has_ambiguous_ref_allele(line): if not line.startswith("#"): parts = line.split("\t") return len(parts) > 4 and parts[3].upper() not in set(["C", "A", "T", "G"]) def _filter_vcf(out_file): """Fix sample names, FILTER and FORMAT fields. Remove lines with ambiguous reference. """ in_file = out_file.replace(".vcf", "-ori.vcf") FILTER_line = ('##FILTER=\n' '##FILTER=\n' '##FILTER=\n') SOMATIC_line = '##INFO=\n' if not utils.file_exists(in_file): shutil.move(out_file, in_file) with file_transaction(out_file) as tx_out_file: with open(in_file) as in_handle, open(tx_out_file, "w") as out_handle: for line in in_handle: if line.startswith("##normalSample="): normal_name = line.strip().split("=")[1] if line.startswith("##patient_id="): tumor_name = line.strip().split("=")[1] if line.startswith("#CHROM"): line = line.replace("Normal", normal_name) line = line.replace("Tumour", tumor_name) if line.startswith("##INFO= - 1 and line.find("SOMATIC") == -1: line = _set_reject(line) if not _has_ambiguous_ref_allele(line): out_handle.write(line) if line.startswith("##FILTER") and FILTER_line: out_handle.write("%s" % FILTER_line) FILTER_line = "" if line.startswith("##INFO") and SOMATIC_line: out_handle.write("%s" % SOMATIC_line) SOMATIC_line = "" return out_file def _to_str(region): return "_" + "_".join(map(str, list(region))) def _to_sambamba(region): return "%s:%s-%s" % (region[0], region[1]+1, region[2]+1) def _set_reject(line): """Set REJECT in VCF line, or add it if there is something else.""" if line.startswith("#"): return line parts = line.split("\t") if parts[6] == "PASS": parts[6] = "REJECT" else: parts[6] += ";REJECT" return "\t".join(parts) ini_file = {"[inputFiles]":{ "dbSNP":"", "ref":"", "normalBam":"", "tumourBam":""}, "[parameters]":{ "annotateMode":"vcf", "runMode":"standard", "minimumBaseQuality":"10", "includeIndels": "true"}, "[ids]":{ "donor":"", "normalSample":"", "tumourSample":"", "somaticAnalysis":"", "germlineAnalysis":""}, "[outputFiles]":{ "vcf":""}, "[rules]":{ "normal1":"0,20,3", "normal2":"21,50,4", "normal3":"51,,10", "tumour1":"0,20,3", "tumour2":"21,50,4", "tumour3":"51,,5"}} bcbio-nextgen-1.2.9/bcbio/variation/realign.py000066400000000000000000000074631415626112400213300ustar00rootroot00000000000000"""Perform realignment of BAM files around indels using the GATK toolkit. """ import os import pysam from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.pipeline.shared import subset_variant_regions import six # ## GATK realignment def gatk_realigner_targets(runner, align_bam, ref_file, config, dbsnp=None, region=None, out_file=None, deep_coverage=False, variant_regions=None, known_vrns=None): """Generate a list of interval regions for realignment around indels. """ if not known_vrns: known_vrns = {} if out_file: out_file = "%s.intervals" % os.path.splitext(out_file)[0] else: out_file = "%s-realign.intervals" % os.path.splitext(align_bam)[0] # check only for file existence; interval files can be empty after running # on small chromosomes, so don't rerun in those cases if not os.path.exists(out_file): with file_transaction(config, out_file) as tx_out_file: logger.debug("GATK RealignerTargetCreator: %s %s" % (os.path.basename(align_bam), region)) params = ["-T", "RealignerTargetCreator", "-I", align_bam, "-R", ref_file, "-o", tx_out_file, "-l", "INFO", ] region = subset_variant_regions(variant_regions, region, tx_out_file) if region: params += ["-L", region, "--interval_set_rule", "INTERSECTION"] if known_vrns.get("train_indels"): params += ["--known", known_vrns["train_indels"]] if deep_coverage: params += ["--mismatchFraction", "0.30", "--maxIntervalSize", "650"] runner.run_gatk(params, memscale={"direction": "decrease", "magnitude": 2}) return out_file def gatk_indel_realignment_cl(runner, align_bam, ref_file, intervals, tmp_dir, region=None, deep_coverage=False, known_vrns=None): """Prepare input arguments for GATK indel realignment. """ if not known_vrns: known_vrns = {} params = ["-T", "IndelRealigner", "-I", align_bam, "-R", ref_file, "-targetIntervals", intervals, ] if region: params += ["-L", region] if known_vrns.get("train_indels"): params += ["--knownAlleles", known_vrns["train_indels"]] if deep_coverage: params += ["--maxReadsInMemory", "300000", "--maxReadsForRealignment", str(int(5e5)), "--maxReadsForConsensuses", "500", "--maxConsensuses", "100"] return runner.cl_gatk(params, tmp_dir) # ## Utilities def has_aligned_reads(align_bam, region=None): """Check if the aligned BAM file has any reads in the region. region can be a chromosome string ("chr22"), a tuple region (("chr22", 1, 100)) or a file of regions. """ import pybedtools if region is not None: if isinstance(region, six.string_types) and os.path.isfile(region): regions = [tuple(r) for r in pybedtools.BedTool(region)] else: regions = [region] with pysam.Samfile(align_bam, "rb") as cur_bam: if region is not None: for region in regions: if isinstance(region, six.string_types): for item in cur_bam.fetch(str(region)): return True else: for item in cur_bam.fetch(str(region[0]), int(region[1]), int(region[2])): return True else: for item in cur_bam: if not item.is_unmapped: return True return False bcbio-nextgen-1.2.9/bcbio/variation/recalibrate.py000066400000000000000000000240221415626112400221520ustar00rootroot00000000000000"""Perform quality score recalibration with the GATK toolkit. Corrects read quality scores post-alignment to provide improved estimates of error rates based on alignments to the reference genome. http://www.broadinstitute.org/gsa/wiki/index.php/Base_quality_score_recalibration """ import os from distutils.version import LooseVersion import toolz as tz from bcbio import bam, broad, utils from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.variation.realign import has_aligned_reads from bcbio.variation import sentieon def prep_recal(data): """Do pre-BQSR recalibration, calculation of recalibration tables. """ if dd.get_recalibrate(data) in [True, "gatk"]: logger.info("Prepare BQSR tables with GATK: %s " % str(dd.get_sample_name(data))) dbsnp_file = tz.get_in(("genome_resources", "variation", "dbsnp"), data) if not dbsnp_file: logger.info("Skipping GATK BaseRecalibrator because no VCF file of known variants was found.") return data broad_runner = broad.runner_from_config(data["config"]) data["prep_recal"] = _gatk_base_recalibrator(broad_runner, dd.get_align_bam(data), dd.get_ref_file(data), dd.get_platform(data), dbsnp_file, dd.get_variant_regions(data) or dd.get_sample_callable(data), data) elif dd.get_recalibrate(data) == "sentieon": logger.info("Prepare BQSR tables with sentieon: %s " % str(dd.get_sample_name(data))) data["prep_recal"] = sentieon.bqsr_table(data) elif dd.get_recalibrate(data): raise NotImplementedError("Unsupported recalibration type: %s" % (dd.get_recalibrate(data))) return data def apply_recal(data): """Apply recalibration tables to the sorted aligned BAM, producing recalibrated BAM. """ orig_bam = dd.get_align_bam(data) or dd.get_work_bam(data) had_work_bam = "work_bam" in data if dd.get_recalibrate(data) in [True, "gatk"]: if data.get("prep_recal"): logger.info("Applying BQSR recalibration with GATK: %s " % str(dd.get_sample_name(data))) data["work_bam"] = _gatk_apply_bqsr(data) elif dd.get_recalibrate(data) == "sentieon": if data.get("prep_recal"): logger.info("Applying BQSR recalibration with sentieon: %s " % str(dd.get_sample_name(data))) data["work_bam"] = sentieon.apply_bqsr(data) elif dd.get_recalibrate(data): raise NotImplementedError("Unsupported recalibration type: %s" % (dd.get_recalibrate(data))) # CWL does not have work/alignment BAM separation if not had_work_bam and dd.get_work_bam(data): data["align_bam"] = dd.get_work_bam(data) if orig_bam != dd.get_work_bam(data) and orig_bam != dd.get_align_bam(data): utils.save_diskspace(orig_bam, "BAM recalibrated to %s" % dd.get_work_bam(data), data["config"]) return data # ## GATK recalibration def _gatk_base_recalibrator(broad_runner, dup_align_bam, ref_file, platform, dbsnp_file, intervals, data): """Step 1 of GATK recalibration process, producing table of covariates. For GATK 4 we use local multicore spark runs: https://github.com/broadinstitute/gatk/issues/2345 For GATK3, Large whole genome BAM files take an excessively long time to recalibrate and the extra inputs don't help much beyond a certain point. See the 'Downsampling analysis' plots in the GATK documentation: http://gatkforums.broadinstitute.org/discussion/44/base-quality-score-recalibrator#latest This identifies large files and calculates the fraction to downsample to. spark host and timeout settings help deal with runs on restricted systems where we encounter network and timeout errors """ target_counts = 1e8 # 100 million reads per read group, 20x the plotted max out_file = os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data), "%s-recal.grp" % utils.splitext_plus(os.path.basename(dup_align_bam))[0]) if not utils.file_exists(out_file): if has_aligned_reads(dup_align_bam, intervals): with file_transaction(data, out_file) as tx_out_file: gatk_type = broad_runner.gatk_type() assert gatk_type in ["restricted", "gatk4"], \ "Require full version of GATK 2.4+ or GATK4 for BQSR" params = ["-I", dup_align_bam] cores = dd.get_num_cores(data) if gatk_type == "gatk4": resources = config_utils.get_resources("gatk-spark", data["config"]) spark_opts = [str(x) for x in resources.get("options", [])] params += ["-T", "BaseRecalibratorSpark", "--output", tx_out_file, "--reference", dd.get_ref_file(data)] if spark_opts: params += spark_opts else: params += ["--spark-master", "local[%s]" % cores, "--conf", "spark.driver.host=localhost", "--conf", "spark.network.timeout=800", "--conf", "spark.executor.heartbeatInterval=100", "--conf", "spark.local.dir=%s" % os.path.dirname(tx_out_file)] if dbsnp_file: params += ["--known-sites", dbsnp_file] if intervals: params += ["-L", intervals, "--interval-set-rule", "INTERSECTION"] else: params += ["-T", "BaseRecalibrator", "-o", tx_out_file, "-R", ref_file] downsample_pct = bam.get_downsample_pct(dup_align_bam, target_counts, data) if downsample_pct: params += ["--downsample_to_fraction", str(downsample_pct), "--downsampling_type", "ALL_READS"] if platform.lower() == "solid": params += ["--solid_nocall_strategy", "PURGE_READ", "--solid_recal_mode", "SET_Q_ZERO_BASE_N"] if dbsnp_file: params += ["--knownSites", dbsnp_file] if intervals: params += ["-L", intervals, "--interval_set_rule", "INTERSECTION"] memscale = {"magnitude": 0.9 * cores, "direction": "increase"} if cores > 1 else None broad_runner.run_gatk(params, os.path.dirname(tx_out_file), memscale=memscale, parallel_gc=True) else: with open(out_file, "w") as out_handle: out_handle.write("# No aligned reads") return out_file def _gatk_apply_bqsr(data): """Parallel BQSR support for GATK4. Normalized qualities to 3 bin outputs at 10, 20 and 30 based on pipeline standard recommendations, which will help with output file sizes: https://github.com/CCDG/Pipeline-Standardization/blob/master/PipelineStandard.md#base-quality-score-binning-scheme https://github.com/gatk-workflows/broad-prod-wgs-germline-snps-indels/blob/5585cdf7877104f2c61b2720ddfe7235f2fad577/PairedEndSingleSampleWf.gatk4.0.wdl#L1081 spark host and timeout settings help deal with runs on restricted systems where we encounter network and timeout errors """ in_file = dd.get_align_bam(data) or dd.get_work_bam(data) out_file = os.path.join(dd.get_work_dir(data), "align", dd.get_sample_name(data), "%s-recal.bam" % utils.splitext_plus(os.path.basename(in_file))[0]) if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: broad_runner = broad.runner_from_config(data["config"]) gatk_type = broad_runner.gatk_type() cores = dd.get_num_cores(data) if gatk_type == "gatk4": resources = config_utils.get_resources("gatk-spark", data["config"]) spark_opts = [str(x) for x in resources.get("options", [])] params = ["-T", "ApplyBQSRSpark", "--input", in_file, "--output", tx_out_file, "--bqsr-recal-file", data["prep_recal"], "--static-quantized-quals", "10", "--static-quantized-quals", "20", "--static-quantized-quals", "30"] if spark_opts: params += spark_opts else: params += ["--spark-master", "local[%s]" % cores, "--conf", "spark.local.dir=%s" % os.path.dirname(tx_out_file), "--conf", "spark.driver.host=localhost", "--conf", "spark.network.timeout=800"] # Avoid problems with StreamClosedErrors on GATK 4.1+ # https://github.com/bcbio/bcbio-nextgen/issues/2806#issuecomment-492504497 params += ["--create-output-bam-index", "false"] else: params = ["-T", "PrintReads", "-R", dd.get_ref_file(data), "-I", in_file, "-BQSR", data["prep_recal"], "-o", tx_out_file] # Avoid problems with intel deflater for GATK 3.8 and GATK4 # https://github.com/bcbio/bcbio-nextgen/issues/2145#issuecomment-343095357 if gatk_type == "gatk4": params += ["--jdk-deflater", "--jdk-inflater"] elif LooseVersion(broad_runner.gatk_major_version()) > LooseVersion("3.7"): params += ["-jdk_deflater", "-jdk_inflater"] memscale = {"magnitude": 0.9 * cores, "direction": "increase"} if cores > 1 else None broad_runner.run_gatk(params, os.path.dirname(tx_out_file), memscale=memscale, parallel_gc=True) bam.index(out_file, data["config"]) return out_file bcbio-nextgen-1.2.9/bcbio/variation/samtools.py000066400000000000000000000115651415626112400215460ustar00rootroot00000000000000"""Variant calling using samtools 1.0 mpileup and bcftools. http://www.htslib.org/workflow/#mapping_to_variant """ import os from distutils.version import LooseVersion from bcbio.utils import file_exists from bcbio.distributed.transaction import file_transaction from bcbio.log import logger from bcbio.pipeline import config_utils from bcbio.pipeline.shared import subset_variant_regions from bcbio.provenance import do, programs from bcbio.variation import annotation, bamprep, bedutils, vcfutils import six def shared_variantcall(call_fn, name, align_bams, ref_file, items, assoc_files, region=None, out_file=None): """Provide base functionality for prepping and indexing for variant calling. """ config = items[0]["config"] if out_file is None: if vcfutils.is_paired_analysis(align_bams, items): out_file = "%s-paired-variants.vcf.gz" % config["metdata"]["batch"] else: out_file = "%s-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not file_exists(out_file): logger.debug("Genotyping with {name}: {region} {fname}".format( name=name, region=region, fname=os.path.basename(align_bams[0]))) variant_regions = bedutils.population_variant_regions(items, merged=True) target_regions = subset_variant_regions(variant_regions, region, out_file, items=items) if (variant_regions is not None and isinstance(target_regions, six.string_types) and not os.path.isfile(target_regions)): vcfutils.write_empty_vcf(out_file, config) else: with file_transaction(config, out_file) as tx_out_file: call_fn(align_bams, ref_file, items, target_regions, tx_out_file) if out_file.endswith(".gz"): out_file = vcfutils.bgzip_and_index(out_file, config) return out_file def run_samtools(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect SNPs and indels with samtools mpileup and bcftools. """ return shared_variantcall(_call_variants_samtools, "samtools", align_bams, ref_file, items, assoc_files, region, out_file) def prep_mpileup(align_bams, ref_file, config, max_read_depth=None, target_regions=None, want_bcf=True): cl = [config_utils.get_program("samtools", config), "mpileup", "-f", ref_file] if max_read_depth: cl += ["-d", str(max_read_depth), "-L", str(max_read_depth)] if want_bcf: cl += ["-t", "DP", "-t", "AD", "-u", "-g"] if target_regions: str_regions = bamprep.region_to_gatk(target_regions) if os.path.isfile(str_regions): cl += ["-l", str_regions] else: cl += ["-r", str_regions] cl += align_bams return " ".join(cl) def prep_bcftools_mpileup(align_bams, ref_file, config, max_read_depth=None, target_regions=None, want_bcf=True): cl = [config_utils.get_program("bcftools", config), "mpileup", "-f", ref_file] # samtools default max read depth was 8000 as opposed to 250 in bcftools max_read_depth = 8000 if not max_read_depth else max_read_depth cl += ["-d", str(max_read_depth)] if want_bcf: cl += ["-a", "DP", "-a", "AD"] if target_regions: str_regions = bamprep.region_to_gatk(target_regions) if os.path.isfile(str_regions): cl += ["-R", str_regions] else: cl += ["-r", str_regions] cl += align_bams return " ".join(cl) def _call_variants_samtools(align_bams, ref_file, items, target_regions, tx_out_file): """Call variants with samtools in target_regions. Works around a GATK VCF 4.2 compatibility issue in samtools 1.0 by removing addition 4.2-only isms from VCF header lines. """ config = items[0]["config"] mpileup = prep_bcftools_mpileup(align_bams, ref_file, config, target_regions=target_regions, want_bcf=True) bcftools = config_utils.get_program("bcftools", config) samtools_version = programs.get_version("samtools", config=config) if samtools_version and LooseVersion(samtools_version) <= LooseVersion("0.1.19"): raise ValueError("samtools calling not supported with pre-1.0 samtools") bcftools_opts = "call -v -m" compress_cmd = "| bgzip -c" if tx_out_file.endswith(".gz") else "" fix_ambig_ref = vcfutils.fix_ambiguous_cl() fix_ambig_alt = vcfutils.fix_ambiguous_cl(5) cmd = ("{mpileup} " "| {bcftools} {bcftools_opts} - " "| {fix_ambig_ref} | {fix_ambig_alt} " "| vt normalize -n -q -r {ref_file} - " "| sed 's/VCFv4.2/VCFv4.1/' " "| sed 's/,Version=3>/>/' " "| sed 's/,Version=\"3\">/>/' " "| sed 's/Number=R/Number=./' " "{compress_cmd} > {tx_out_file}") do.run(cmd.format(**locals()), "Variant calling with samtools", items[0]) bcbio-nextgen-1.2.9/bcbio/variation/scalpel.py000066400000000000000000000235311415626112400213240ustar00rootroot00000000000000"""InDel calling using Scalpel https://sourceforge.net/p/scalpel/code/ci/master/tree/ """ from __future__ import print_function import os import shutil try: import vcf except ImportError: vcf = None from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils, shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import annotation, bedutils, vcfutils from bcbio.variation.vcfutils import get_paired_bams, is_paired_analysis, bgzip_and_index import six def _scalpel_bed_file_opts(items, config, out_file, region, tmp_path): variant_regions = bedutils.population_variant_regions(items) target = shared.subset_variant_regions(variant_regions, region, out_file, items) if target: if isinstance(target, six.string_types) and os.path.isfile(target): target_bed = target else: target_bed = os.path.join(tmp_path, "tmp.bed") if not utils.file_exists(target_bed): with file_transaction(config, target_bed) as tx_tmp_bed: if not isinstance(region, (list, tuple)): message = ("Region must be a tuple - something odd just happened") raise ValueError(message) chrom, start, end = region with open(tx_tmp_bed, "w") as out_handle: print("%s\t%s\t%s" % (chrom, start, end), file=out_handle) if any(dd.get_coverage_interval(x) == "genome" for x in items): target_bed = shared.remove_lcr_regions(target_bed, items) return ["--bed", target_bed] else: return [] def _scalpel_options_from_config(items, config, out_file, region, tmp_path): opts = [] # output vcf, report only variants within bed regions opts += ["--format", "vcf", "--intarget"] # Improve sensitivity in low coverage regions opts += ["--covthr 3", "--lowcov 1"] # Avoid oversampling in repeat regions opts += ["--pathlimit", "10000"] opts += _scalpel_bed_file_opts(items, config, out_file, region, tmp_path) resources = config_utils.get_resources("scalpel", config) if resources.get("options"): opts += resources["options"] if "--outratio" not in " ".join(opts): # add minimum reportable allele frequency, for which Scalpel defaults to 5 # but other somatic tools in bcbio default to 10 min_af = float(utils.get_in(config, ("algorithm", "min_allele_fraction"), 10)) / 100.0 opts += ["--outratio", str(min_af)] return opts def is_installed(config): """Check for scalpel installation on machine. """ try: config_utils.get_program("scalpel-discovery", config) return True except config_utils.CmdNotFound: return False def run_scalpel(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Run Scalpel indel calling, either paired tumor/normal or germline calling. """ if region is None: message = ("A region must be provided for Scalpel") raise ValueError(message) if is_paired_analysis(align_bams, items): call_file = _run_scalpel_paired(align_bams, items, ref_file, assoc_files, region, out_file) else: call_file = _run_scalpel_caller(align_bams, items, ref_file, assoc_files, region, out_file) return call_file def _run_scalpel_caller(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect indels with Scalpel. Single sample mode. """ config = items[0]["config"] if out_file is None: out_file = "%s-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: if len(align_bams) > 1: message = ("Scalpel does not currently support batch calling!") raise ValueError(message) input_bams = " ".join("%s" % x for x in align_bams) tmp_path = "%s-scalpel-work" % utils.splitext_plus(out_file)[0] tx_tmp_path = "%s-scalpel-work" % utils.splitext_plus(tx_out_file)[0] if os.path.exists(tmp_path): utils.remove_safe(tmp_path) opts = " ".join(_scalpel_options_from_config(items, config, out_file, region, tmp_path)) opts += " --dir %s" % tx_tmp_path min_cov = "3" # minimum coverage opts += " --mincov %s" % min_cov perl_exports = utils.get_perl_exports(os.path.dirname(tx_out_file)) cmd = ("{perl_exports} && " "scalpel-discovery --single {opts} --ref {ref_file} --bam {input_bams} ") do.run(cmd.format(**locals()), "Genotyping with Scalpel", {}) shutil.move(tx_tmp_path, tmp_path) # parse produced variant file further scalpel_tmp_file = bgzip_and_index(os.path.join(tmp_path, "variants.indel.vcf"), config) compress_cmd = "| bgzip -c" if out_file.endswith("gz") else "" bcftools_cmd_chi2 = get_scalpel_bcftools_filter_expression("chi2", config) sample_name_str = items[0]["name"][1] fix_ambig = vcfutils.fix_ambiguous_cl() add_contig = vcfutils.add_contig_to_header_cl(dd.get_ref_file(items[0]), tx_out_file) cl2 = ("{bcftools_cmd_chi2} {scalpel_tmp_file} | " r"sed 's/FORMAT\tsample\(_name\)\{{0,1\}}/FORMAT\t{sample_name_str}/g' " "| {fix_ambig} | vcfallelicprimitives -t DECOMPOSED --keep-geno | vcffixup - | vcfstreamsort " "| {add_contig} {compress_cmd} > {tx_out_file}") do.run(cl2.format(**locals()), "Finalising Scalpel variants", {}) return out_file def _run_scalpel_paired(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect indels with Scalpel. This is used for paired tumor / normal samples. """ config = items[0]["config"] if out_file is None: out_file = "%s-paired-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: paired = get_paired_bams(align_bams, items) if not paired.normal_bam: ann_file = _run_scalpel_caller(align_bams, items, ref_file, assoc_files, region, out_file) return ann_file vcfstreamsort = config_utils.get_program("vcfstreamsort", config) perl_exports = utils.get_perl_exports(os.path.dirname(tx_out_file)) tmp_path = "%s-scalpel-work" % utils.splitext_plus(out_file)[0] db_file = os.path.join(tmp_path, "main", "somatic.db") if not os.path.exists(db_file + ".dir"): if os.path.exists(tmp_path): utils.remove_safe(tmp_path) opts = " ".join(_scalpel_options_from_config(items, config, out_file, region, tmp_path)) opts += " --ref {}".format(ref_file) opts += " --dir %s" % tmp_path # caling cl = ("{perl_exports} && " "scalpel-discovery --somatic {opts} --tumor {paired.tumor_bam} --normal {paired.normal_bam}") do.run(cl.format(**locals()), "Genotyping paired variants with Scalpel", {}) # filtering to adjust input parameters bed_opts = " ".join(_scalpel_bed_file_opts(items, config, out_file, region, tmp_path)) use_defaults = True if use_defaults: scalpel_tmp_file = os.path.join(tmp_path, "main/somatic.indel.vcf") # Uses default filters but can tweak min-alt-count-tumor and min-phred-fisher # to swap precision for sensitivity else: scalpel_tmp_file = os.path.join(tmp_path, "main/somatic-indel-filter.vcf.gz") with file_transaction(config, scalpel_tmp_file) as tx_indel_file: cmd = ("{perl_exports} && " "scalpel-export --somatic {bed_opts} --ref {ref_file} --db {db_file} " "--min-alt-count-tumor 5 --min-phred-fisher 10 --min-vaf-tumor 0.1 " "| bgzip -c > {tx_indel_file}") do.run(cmd.format(**locals()), "Scalpel somatic indel filter", {}) scalpel_tmp_file = bgzip_and_index(scalpel_tmp_file, config) scalpel_tmp_file_common = bgzip_and_index(os.path.join(tmp_path, "main/common.indel.vcf"), config) compress_cmd = "| bgzip -c" if out_file.endswith("gz") else "" bcftools_cmd_chi2 = get_scalpel_bcftools_filter_expression("chi2", config) bcftools_cmd_common = get_scalpel_bcftools_filter_expression("reject", config) fix_ambig = vcfutils.fix_ambiguous_cl() add_contig = vcfutils.add_contig_to_header_cl(dd.get_ref_file(items[0]), tx_out_file) cl2 = ("vcfcat <({bcftools_cmd_chi2} {scalpel_tmp_file}) " "<({bcftools_cmd_common} {scalpel_tmp_file_common}) | " " {fix_ambig} | {vcfstreamsort} | {add_contig} {compress_cmd} > {tx_out_file}") do.run(cl2.format(**locals()), "Finalising Scalpel variants", {}) return out_file def get_scalpel_bcftools_filter_expression(filter_type, config): bcftools = config_utils.get_program("bcftools", config) filter_string = "{bcftools} filter -m '+' -O v --soft-filter " if filter_type == "chi2": filter_string += "'CHI2FILTER' -e 'INFO/CHI2 > 20.0' " elif filter_type == "reject": filter_string += "'REJECT' -e '%TYPE=\"indel\"' " else: return "zcat" return filter_string.format(**locals()) bcbio-nextgen-1.2.9/bcbio/variation/sentieon.py000066400000000000000000000221271415626112400215250ustar00rootroot00000000000000"""Variant calling support for Sentieon tools. Sentieon provides optimized versions of standard tools like GATK HaplotypeCaller and MuTect2 as well as their own developed versions. These require a license from Sentieon for use: http://sentieon.com/about/ https://peerj.com/preprints/1672/ """ import os import pprint import toolz as tz from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils, shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import bamprep, bedutils, joint, vcfutils import six def license_export(data): """Retrieve export statement for sentieon license server. """ resources = config_utils.get_resources("sentieon", data["config"]) server = resources.get("keyfile") if not server: server = tz.get_in(["resources", "sentieon", "keyfile"], data) if not server: raise ValueError("Need to set resources keyfile with URL:port of license server, local license file or " "environmental variables to export \n" "http://bcbio-nextgen.readthedocs.io/en/latest/contents/configuration.html#resources\n" "Configuration: %s" % pprint.pformat(data)) if isinstance(server, six.string_types): return "export SENTIEON_LICENSE=%s && " % server else: assert isinstance(server, dict), server exports = "" for key, val in server.items(): exports += "export %s=%s && " % (key.upper(), val) return exports def _get_interval(variant_regions, region, out_file, items): """Retrieve interval to run analysis in. Handles no targets, BED and regions region can be a single region or list of multiple regions for multicore calling. """ target = shared.subset_variant_regions(variant_regions, region, out_file, items) if target: if isinstance(target, six.string_types) and os.path.isfile(target): return "--interval %s" % target else: return "--interval %s" % bamprep.region_to_gatk(target) else: return "" def run_tnscope(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Call variants with Sentieon's TNscope somatic caller. """ if out_file is None: out_file = "%s-variants.vcf.gz" % utils.splitext_plus(align_bams[0])[0] if not utils.file_exists(out_file): variant_regions = bedutils.population_variant_regions(items, merged=True) interval = _get_interval(variant_regions, region, out_file, items) with file_transaction(items[0], out_file) as tx_out_file: paired = vcfutils.get_paired_bams(align_bams, items) assert paired and paired.normal_bam, "Require normal BAM for Sentieon TNscope" dbsnp = "--dbsnp %s" % (assoc_files.get("dbsnp")) if "dbsnp" in assoc_files else "" license = license_export(items[0]) cores = dd.get_num_cores(items[0]) cmd = ("{license}sentieon driver -t {cores} -r {ref_file} " "-i {paired.tumor_bam} -i {paired.normal_bam} {interval} " "--algo TNscope " "--tumor_sample {paired.tumor_name} --normal_sample {paired.normal_name} " "{dbsnp} {tx_out_file}") do.run(cmd.format(**locals()), "Sentieon TNscope") return out_file def run_tnhaplotyper(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Call variants with Sentieon's TNhaplotyper (MuTect2 like). """ if out_file is None: out_file = "%s-variants.vcf.gz" % utils.splitext_plus(align_bams[0])[0] if not utils.file_exists(out_file): variant_regions = bedutils.population_variant_regions(items, merged=True) interval = _get_interval(variant_regions, region, out_file, items) with file_transaction(items[0], out_file) as tx_out_file: paired = vcfutils.get_paired_bams(align_bams, items) assert paired.normal_bam, "Require normal BAM for Sentieon TNhaplotyper" dbsnp = "--dbsnp %s" % (assoc_files.get("dbsnp")) if "dbsnp" in assoc_files else "" cosmic = "--cosmic %s" % (assoc_files.get("cosmic")) if "cosmic" in assoc_files else "" license = license_export(items[0]) tx_orig_file = "%s-orig%s" % utils.splitext_plus(tx_out_file) cores = dd.get_num_cores(items[0]) cmd = ("{license}sentieon driver -t {cores} -r {ref_file} " "-i {paired.tumor_bam} -i {paired.normal_bam} {interval} " "--algo TNhaplotyper " "--tumor_sample {paired.tumor_name} --normal_sample {paired.normal_name} " "{dbsnp} {cosmic} {tx_orig_file}") do.run(cmd.format(**locals()), "Sentieon TNhaplotyper") cmd = ("gunzip -c {tx_orig_file} | " "sed 's/ID=ECNT,Number=1,Type=Integer/ID=ECNT,Number=1,Type=String/' | " "sed 's/ID=HCNT,Number=1,Type=Integer/ID=HCNT,Number=1,Type=String/' | " "sed 's/ID=NLOD,Number=1,Type=Float/ID=NLOD,Number=1,Type=String/' | " "sed 's/ID=TLOD,Number=1,Type=Float/ID=TLOD,Number=1,Type=String/' | " "sed 's/ID=PON,Number=1,Type=Integer/ID=PON,Number=1,Type=String/' | " "bgzip -c > {tx_out_file}") do.run(cmd.format(**locals()), "Sentieon TNhaplotyper: make headers GATK compatible") vcfutils.bgzip_and_index(tx_out_file, items[0]["config"]) return out_file def run_haplotyper(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Call variants with Sentieon's haplotyper (GATK HaplotypeCaller like). """ if out_file is None: out_file = "%s-variants.vcf.gz" % utils.splitext_plus(align_bams[0])[0] if not utils.file_exists(out_file): variant_regions = bedutils.population_variant_regions(items, merged=True) interval = _get_interval(variant_regions, region, out_file, items) with file_transaction(items[0], out_file) as tx_out_file: dbsnp = "--dbsnp %s" % (assoc_files.get("dbsnp")) if "dbsnp" in assoc_files else "" bams = " ".join(["-i %s" % x for x in align_bams]) license = license_export(items[0]) cores = dd.get_num_cores(items[0]) out_mode = "--emit_mode gvcf" if joint.want_gvcf(items) else "" cmd = ("{license}sentieon driver -t {cores} -r {ref_file} " "{bams} {interval} --algo Haplotyper {out_mode} {dbsnp} {tx_out_file}") do.run(cmd.format(**locals()), "Sentieon Haplotyper") return out_file def run_gvcftyper(vrn_files, out_file, region, data): """Produce joint called variants from input gVCF files. """ if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: license = license_export(data) ref_file = dd.get_ref_file(data) input_files = " ".join(vrn_files) region = bamprep.region_to_gatk(region) cmd = ("{license}sentieon driver -r {ref_file} --interval {region} " "--algo GVCFtyper {tx_out_file} {input_files}") do.run(cmd.format(**locals()), "Sentieon GVCFtyper") return out_file def bqsr_table(data): """Generate recalibration tables as inputs to BQSR. """ in_file = dd.get_align_bam(data) out_file = "%s-recal-table.txt" % utils.splitext_plus(in_file)[0] if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file) as tx_out_file: assoc_files = dd.get_variation_resources(data) known = "-k %s" % (assoc_files.get("dbsnp")) if "dbsnp" in assoc_files else "" license = license_export(data) cores = dd.get_num_cores(data) ref_file = dd.get_ref_file(data) cmd = ("{license}sentieon driver -t {cores} -r {ref_file} " "-i {in_file} --algo QualCal {known} {tx_out_file}") do.run(cmd.format(**locals()), "Sentieon QualCal generate table") return out_file def apply_bqsr(data): """Apply recalibration, producing a updated BAM file. """ in_file = dd.get_align_bam(data) out_table_file = "%s-recal-table-post.txt" % utils.splitext_plus(in_file)[0] out_file = "%s-recal.bam" % utils.splitext_plus(in_file)[0] if not utils.file_uptodate(out_file, in_file): with file_transaction(data, out_file, out_table_file) as (tx_out_file, tx_table_file): assoc_files = dd.get_variation_resources(data) known = "-k %s" % (assoc_files.get("dbsnp")) if "dbsnp" in assoc_files else "" license = license_export(data) cores = dd.get_num_cores(data) ref_file = dd.get_ref_file(data) cmd = ("{license}sentieon driver -t {cores} -r {ref_file} " "-i {in_file} --algo QualCal {known} {tx_table_file} " "--algo ReadWriter {tx_out_file}") do.run(cmd.format(**locals()), "Sentieon QualCal apply recalibration") return out_file bcbio-nextgen-1.2.9/bcbio/variation/smcounter2.py000066400000000000000000000045411415626112400220020ustar00rootroot00000000000000"""Low frequency somatic variant calling with smCounter2. https://github.com/qiaseq/qiaseq-smcounter-v2 """ import glob import os import shutil from bcbio import utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import bedutils, vcfutils def run(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Run tumor only smCounter2 calling. """ paired = vcfutils.get_paired_bams(align_bams, items) assert paired and not paired.normal_bam, ("smCounter2 supports tumor-only variant calling: %s" % (",".join([dd.get_sample_name(d) for d in items]))) vrs = bedutils.population_variant_regions(items) target = shared.subset_variant_regions(vrs, region, out_file, items=items, do_merge=True) out_file = out_file.replace(".vcf.gz", ".vcf") out_prefix = utils.splitext_plus(os.path.basename(out_file))[0] if not utils.file_exists(out_file) and not utils.file_exists(out_file + ".gz"): with file_transaction(paired.tumor_data, out_file) as tx_out_file: cmd = ["smCounter2", "--runPath", os.path.dirname(tx_out_file), "--outPrefix", out_prefix, "--bedTarget", target, "--refGenome", ref_file, "--bamFile", paired.tumor_bam, "--bamType", "consensus", "--nCPU", dd.get_num_cores(paired.tumor_data)] do.run(cmd, "smcounter2 variant calling") for fname in glob.glob(os.path.join(os.path.dirname(tx_out_file), "*.smCounter*")): shutil.move(fname, os.path.join(os.path.dirname(out_file), os.path.basename(fname))) utils.symlink_plus(os.path.join(os.path.dirname(out_file), "%s.smCounter.cut.vcf" % out_prefix), out_file) return vcfutils.bgzip_and_index(out_file, paired.tumor_data["config"], remove_orig=False, prep_cmd="sed 's#FORMAT\t%s#FORMAT\t%s#' | %s" % (out_prefix, dd.get_sample_name(paired.tumor_data), vcfutils.add_contig_to_header_cl(dd.get_ref_file(paired.tumor_data), out_file))) bcbio-nextgen-1.2.9/bcbio/variation/split.py000066400000000000000000000031011415626112400210230ustar00rootroot00000000000000"""Utilities for manipulating VCF files. """ import os from bcbio.bam import ref from bcbio.utils import file_exists, replace_suffix, append_stem from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.variation import bamprep, vcfutils def split_vcf(in_file, ref_file, config, out_dir=None): """Split a VCF file into separate files by chromosome. """ if out_dir is None: out_dir = os.path.join(os.path.dirname(in_file), "split") out_files = [] with open(ref.fasta_idx(ref_file, config)) as in_handle: for line in in_handle: chrom, size = line.split()[:2] out_file = os.path.join(out_dir, os.path.basename(replace_suffix(append_stem(in_file, "-%s" % chrom), ".vcf"))) subset_vcf(in_file, (chrom, 0, size), out_file, config) out_files.append(out_file) return out_files def subset_vcf(in_file, region, out_file, config): """Subset VCF in the given region, handling bgzip and indexing of input. """ work_file = vcfutils.bgzip_and_index(in_file, config) if not file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: bcftools = config_utils.get_program("bcftools", config) region_str = bamprep.region_to_gatk(region) cmd = "{bcftools} view -r {region_str} {work_file} > {tx_out_file}" do.run(cmd.format(**locals()), "subset %s: %s" % (os.path.basename(work_file), region_str)) return out_file bcbio-nextgen-1.2.9/bcbio/variation/strelka2.py000066400000000000000000000511611415626112400214300ustar00rootroot00000000000000"""Germline and somatic calling with Strelka2: https://github.com/illumina/strelka """ import collections import os import six import sys import numpy as np from bcbio import utils from bcbio.log import logger from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import bamprep, bedutils, joint, ploidy, vcfutils cyvcf2 = utils.LazyImport("cyvcf2") def run(align_bams, items, ref_file, assoc_files, region, out_file): """Run strelka2 variant calling, either paired tumor/normal or germline calling. region can be a single region or list of multiple regions for multicore calling. """ call_file = "%s-raw.vcf.gz" % utils.splitext_plus(out_file)[0] strelka_work_dir = "%s-work" % utils.splitext_plus(out_file)[0] paired = vcfutils.get_paired_bams(align_bams, items) if paired: assert paired.normal_bam, "Strelka2 requires a normal sample" call_file = _run_somatic(paired, ref_file, assoc_files, region, call_file, strelka_work_dir) else: call_file = _run_germline(align_bams, items, ref_file, assoc_files, region, call_file, strelka_work_dir) return _af_annotate_and_filter(paired, items, call_file, out_file) def get_region_bed(region, items, out_file, want_gzip=True): """Retrieve BED file of regions to analyze, either single or multi-region. """ variant_regions = bedutils.population_variant_regions(items, merged=True) target = shared.subset_variant_regions(variant_regions, region, out_file, items) if not target: raise ValueError("Need BED input for strelka2 regions: %s %s" % (region, target)) if not isinstance(target, six.string_types) or not os.path.isfile(target): chrom, start, end = target target = "%s-regions.bed" % utils.splitext_plus(out_file)[0] with file_transaction(items[0], target) as tx_out_file: with open(tx_out_file, "w") as out_handle: out_handle.write("%s\t%s\t%s\n" % (chrom, start, end)) out_file = target if want_gzip: out_file = vcfutils.bgzip_and_index(out_file, items[0]["config"]) if bedutils.has_regions(out_file): return out_file def coverage_interval_from_bed(bed_file, per_chrom=True): """Calculate a coverage interval for the current region BED. This helps correctly work with cases of uneven coverage across an analysis genome. strelka2 and other model based callers have flags for targeted and non which depend on the local context. Checks coverage per chromosome, avoiding non-standard chromosomes, if per_chrom is set. Otherwise does a global check over all regions. The global check performs better for strelka2 but not for DeepVariant: https://github.com/bcbio/bcbio_validations/tree/master/deepvariant#deepvariant-v06-release-strelka2-stratification-and-initial-gatk-cnn """ total_starts = {} total_ends = {} bed_bases = collections.defaultdict(int) with utils.open_gzipsafe(bed_file) as in_handle: for line in in_handle: parts = line.split() if len(parts) >= 3: chrom, start, end = parts[:3] if chromhacks.is_autosomal(chrom): start = int(start) end = int(end) bed_bases[chrom] += (end - start) total_starts[chrom] = min([start, total_starts.get(chrom, sys.maxsize)]) total_ends[chrom] = max([end, total_ends.get(chrom, 0)]) # can check per chromosome -- any one chromosome with larger, or over all regions if per_chrom: freqs = [float(bed_bases[c]) / float(total_ends[c] - total_starts[c]) for c in sorted(bed_bases.keys())] elif len(bed_bases) > 0: freqs = [sum([bed_bases[c] for c in sorted(bed_bases.keys())]) / sum([float(total_ends[c] - total_starts[c]) for c in sorted(bed_bases.keys())])] else: freqs = [] # Should be importing GENOME_COV_THRESH but get circular imports if any([f >= 0.40 for f in freqs]): return "genome" else: return "targeted" def _is_targeted_region(cur_bed, data): """Calculate if we should process region as a targeted or WGS. Currently always based on total coverage interval, as that validates best and is consistent between CWL (larger blocks) and non-CWL runs (smaller blocks). We can check core usage and provide a consistent report when moving to CWL exclusively. """ cores = dd.get_num_cores(data) if cores > 0: # Apply to all core setups now for consistency return dd.get_coverage_interval(data) not in ["genome"] else: return coverage_interval_from_bed(cur_bed, per_chrom=False) == "targeted" def _get_ploidy(regions, items, base_file): samples = [dd.get_sample_name(d) for d in items] out_file = "%s-ploidy.vcf" % utils.splitext_plus(base_file)[0] if not utils.file_exists(out_file) and not utils.file_exists(out_file + ".gz"): with file_transaction(items[0], out_file) as tx_outfile: with open(tx_outfile, "w") as h: h.write("##fileformat=VCFv4.1\n") h.write('##INFO=\n') h.write('##FORMAT=\n') h.write("#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\t" + "\t".join(samples) + "\n") for region in regions: ploidies = [ploidy.get_ploidy([d], region) for d in items] h.write("\t".join([region[0], str(region[1]), ".", "N", "", ".", ".", "END=%s" % region[2], "CN"] + [str(x) for x in ploidies]) + "\n") return vcfutils.bgzip_and_index(out_file, items[0]["config"]) def _configure_germline(align_bams, items, ref_file, region, out_file, tx_work_dir): utils.safe_makedir(tx_work_dir) cmd = [utils.get_program_python("configureStrelkaGermlineWorkflow.py"), os.path.realpath(utils.which("configureStrelkaGermlineWorkflow.py"))] cur_bed = get_region_bed(region, items, out_file) if cur_bed: cmd += ["--referenceFasta=%s" % ref_file, "--callRegions=%s" % cur_bed, "--ploidy=%s" % _get_ploidy(shared.to_multiregion(region), items, out_file), "--runDir=%s" % tx_work_dir] cmd += ["--bam=%s" % b for b in align_bams] if _is_targeted_region(cur_bed, items[0]): cmd += ["--targeted"] do.run(cmd, "Configure Strelka2 germline calling: %s" % (", ".join([dd.get_sample_name(d) for d in items]))) return os.path.join(tx_work_dir, "runWorkflow.py") def _run_germline(align_bams, items, ref_file, assoc_files, region, out_file, work_dir): if not utils.file_exists(out_file): with file_transaction(items[0], work_dir) as tx_work_dir: workflow_file = _configure_germline(align_bams, items, ref_file, region, out_file, tx_work_dir) if workflow_file: has_variants = True _run_workflow(items[0], workflow_file, tx_work_dir) else: has_variants = False vcfutils.write_empty_vcf(out_file, items[0]["config"], [dd.get_sample_name(d) for d in items]) if has_variants: raw_file = os.path.join(work_dir, "results", "variants", "genome.vcf.gz" if joint.want_gvcf(items) else "variants.vcf.gz") utils.copy_plus(raw_file, out_file) # Remove files with relative symlinks utils.remove_plus(os.path.join(work_dir, "results", "variants", "genome.vcf.gz")) return vcfutils.bgzip_and_index(out_file, items[0]["config"]) def _configure_somatic(paired, ref_file, region, out_file, tx_work_dir): utils.safe_makedir(tx_work_dir) cmd = [utils.get_program_python("configureStrelkaSomaticWorkflow.py"), os.path.realpath(utils.which("configureStrelkaSomaticWorkflow.py"))] cur_bed = get_region_bed(region, [paired.tumor_data, paired.normal_data], out_file) if cur_bed: cmd += ["--referenceFasta=%s" % ref_file, "--callRegions=%s" % cur_bed, "--runDir=%s" % tx_work_dir, "--normalBam=%s" % paired.normal_bam, "--tumorBam=%s" % paired.tumor_bam] if _is_targeted_region(cur_bed, paired.tumor_data): cmd += ["--targeted"] do.run(cmd, "Configure Strelka2 germline calling: %s" % paired.tumor_name) return os.path.join(tx_work_dir, "runWorkflow.py") def _tumor_normal_genotypes(ref, alt, info, fname, coords): """Retrieve standard 0/0, 0/1, 1/1 style genotypes from INFO field. Normal -- NT field (ref, het, hom, conflict) Tumor -- SGT field - for SNPs specified as GG->TT for the normal and tumor diploid alleles. These can also represent more complex alleles in which case we set at heterozygotes pending longer term inclusion of genotypes in Strelka2 directly (https://github.com/Illumina/strelka/issues/16) - For indels, uses the ref, het, hom convention ref: The REF allele from a VCF line alt: A list of potentially multiple ALT alleles (rec.ALT.split(";")) info: The VCF INFO field fname, coords: not currently used, for debugging purposes """ known_names = set(["het", "hom", "ref", "conflict"]) def name_to_gt(val): if val.lower() == "het": return "0/1" elif val.lower() == "hom": return "1/1" elif val.lower() in set(["ref", "conflict"]): return "0/0" else: # Non-standard representations, het is our best imperfect representation # print(fname, coords, ref, alt, info, val) return "0/1" def alleles_to_gt(val): gt_indices = {gt.upper(): i for i, gt in enumerate([ref] + alt)} tumor_gts = [gt_indices[x.upper()] for x in val if x in gt_indices] if tumor_gts and val not in known_names: if max(tumor_gts) == 0: tumor_gt = "0/0" elif 0 in tumor_gts: tumor_gt = "0/%s" % min([x for x in tumor_gts if x > 0]) else: tumor_gt = "%s/%s" % (min(tumor_gts), max(tumor_gts)) else: tumor_gt = name_to_gt(val) return tumor_gt nt_val = [x.split("=")[-1] for x in info if x.startswith("NT=")][0] normal_gt = name_to_gt(nt_val) sgt_val = [x.split("=")[-1] for x in info if x.startswith("SGT=")] if not sgt_val: tumor_gt = "0/0" else: sgt_val = sgt_val[0].split("->")[-1] tumor_gt = alleles_to_gt(sgt_val) return tumor_gt, normal_gt def _af_annotate_and_filter(paired, items, in_file, out_file): """Populating FORMAT/AF, and dropping variants with AFU/DP (somatic snps), ' 'TIR/DPI (somatic indels)', 'Type': 'Float', 'Number': '.'}) vcf.add_filter_to_header({ 'ID': 'MinAF', 'Description': 'Allele frequency is lower than %s%% ' % (min_freq*100) + ( '(configured in bcbio as min_allele_fraction)' if utils.get_in(data["config"], ("algorithm", "min_allele_fraction")) else '(default threshold in bcbio; override with min_allele_fraction in the algorithm section)')}) w = cyvcf2.Writer(tx_out_file, vcf) tumor_index = vcf.samples.index(data['description']) for rec in vcf: if paired: # somatic? if rec.is_snp: # snps? alt_counts = rec.format(rec.ALT[0] + 'U')[:,0] # {ALT}U=tier1_depth,tier2_depth else: # indels alt_counts = rec.format('TIR')[:,0] # TIR=tier1_depth,tier2_depth dp = rec.format('DP')[:,0] elif rec.format("AD") is not None: # germline? alt_counts = rec.format('AD')[:,1:] # AD=REF,ALT1,ALT2,... dp = np.sum(rec.format('AD')[:,0:], axis=1)[:, None] else: # germline gVCF record alt_counts, dp = (None, None) if dp is not None: with np.errstate(divide='ignore', invalid='ignore'): # ignore division by zero and put AF=.0 af = np.true_divide(alt_counts, dp) af[~np.isfinite(af)] = .0 # -inf inf NaN -> .0 rec.set_format('AF', af) if paired and np.all(af[tumor_index] < min_freq): vcfutils.cyvcf_add_filter(rec, 'MinAF') w.write_record(rec) w.close() return vcfutils.bgzip_and_index(ungz_out_file, data["config"]) def _postprocess_somatic(in_file, paired): """Post-process somatic calls to provide standard output. - Converts SGT and NT into standard VCF GT fields - Replace generic TUMOR NORMAL names in VCF with sample names. """ out_file = in_file.replace(".vcf.gz", "-fixed.vcf") if not utils.file_exists(out_file) and not utils.file_exists(out_file + ".gz"): with file_transaction(paired.tumor_data, out_file) as tx_out_file: with utils.open_gzipsafe(in_file) as in_handle: with open(tx_out_file, "w") as out_handle: added_gt = False normal_index, tumor_index = (None, None) for line in in_handle: if line.startswith("##FORMAT") and not added_gt: added_gt = True out_handle.write('##FORMAT=\n') out_handle.write(line) elif line.startswith("#CHROM"): assert added_gt parts = line.strip().split("\t") normal_index = parts.index("NORMAL") tumor_index = parts.index("TUMOR") line = line.replace("NORMAL", paired.normal_name).replace("TUMOR", paired.tumor_name) out_handle.write(line) elif line.startswith("#"): out_handle.write(line) else: parts = line.rstrip().split("\t") tumor_gt, normal_gt = _tumor_normal_genotypes(parts[3], parts[4].split(","), parts[7].split(";"), in_file, parts[:2]) parts[8] = "GT:%s" % parts[8] parts[normal_index] = "%s:%s" % (normal_gt, parts[normal_index]) parts[tumor_index] = "%s:%s" % (tumor_gt, parts[tumor_index]) out_handle.write("\t".join(parts) + "\n") return vcfutils.bgzip_and_index(out_file, paired.tumor_data["config"]) def _run_somatic(paired, ref_file, assoc_files, region, out_file, work_dir): if not utils.file_exists(out_file): with file_transaction(paired.tumor_data, work_dir) as tx_work_dir: workflow_file = _configure_somatic(paired, ref_file, region, out_file, tx_work_dir) if workflow_file: has_variants = True _run_workflow(paired.tumor_data, workflow_file, tx_work_dir) else: has_variants = False vcfutils.write_empty_vcf(out_file, paired.tumor_data["config"], [dd.get_sample_name(d) for d in [paired.tumor_data, paired.normal_data]]) if has_variants: var_dir = os.path.join(work_dir, "results", "variants") vcfutils.combine_variant_files([_postprocess_somatic(os.path.join(var_dir, f), paired) for f in ["somatic.snvs.vcf.gz", "somatic.indels.vcf.gz"]], out_file, ref_file, paired.tumor_data["config"], region=region) return out_file def _run_workflow(data, workflow_file, work_dir): """Run Strelka2 analysis inside prepared workflow directory. """ utils.remove_safe(os.path.join(work_dir, "workspace")) cmd = [utils.get_program_python("configureStrelkaGermlineWorkflow.py"), workflow_file, "-m", "local", "-j", dd.get_num_cores(data), "--quiet"] do.run(cmd, "Run Strelka2: %s" % dd.get_sample_name(data)) utils.remove_safe(os.path.join(work_dir, "workspace")) # ## Joint calling def run_gvcfgenotyper(data, orig_region, vrn_files, out_file): """Merge strelka2 and Illumina compatible gVCFs with gvcfgenotyper. https://github.com/Illumina/gvcfgenotyper Also need to explore GLnexus (https://github.com/dnanexus-rnd/GLnexus) """ if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: regions = _find_gvcf_blocks(vrn_files[0], bamprep.region_to_gatk(orig_region), os.path.dirname(tx_out_file)) if len(regions) == 1: _run_gvcfgenotyper(data, regions[0], vrn_files, tx_out_file) else: split_outs = [_run_gvcfgenotyper(data, r, vrn_files, "%s-%s.vcf.gz" % (utils.splitext_plus(out_file)[0], r.replace(":", "_").replace("-", "_"))) for r in regions] vcfutils.concat_variant_files(split_outs, tx_out_file, regions, dd.get_ref_file(data), data["config"]) return vcfutils.bgzip_and_index(out_file, data["config"]) def _run_gvcfgenotyper(data, region, vrn_files, out_file): """Run gvcfgenotyper on a single gVCF region in input file. """ if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: input_file = "%s-inputs.txt" % utils.splitext_plus(tx_out_file)[0] with open(input_file, "w") as out_handle: out_handle.write("%s\n" % "\n".join(vrn_files)) cmd = ["gvcfgenotyper", "-f", dd.get_ref_file(data), "-l", input_file, "-r", region, "-O", "z", "-o", tx_out_file] do.run(cmd, "gvcfgenotyper: %s %s" % (dd.get_sample_name(data), region)) return out_file def _find_gvcf_blocks(vcf_file, region, tmp_dir): """Retrieve gVCF blocks within our current evaluation region. gvcfgenotyper does not support calling larger regions with individual coverage blocks, so we split our big region into potentially multiple. """ region_file = os.path.join(tmp_dir, "cur_region.bed") with open(region_file, "w") as out_handle: chrom, coords = region.split(":") start, end = coords.split("-") out_handle.write("\t".join([chrom, start, end]) + "\n") final_file = os.path.join(tmp_dir, "split_regions.bed") cmd = "gvcf_regions.py {vcf_file} | bedtools intersect -a - -b {region_file} > {final_file}" do.run(cmd.format(**locals())) regions = [] with open(final_file) as in_handle: for line in in_handle: chrom, start, end = line.strip().split("\t") regions.append("%s:%s-%s" % (chrom, start, end)) return regions bcbio-nextgen-1.2.9/bcbio/variation/validate.py000066400000000000000000001042551415626112400214750ustar00rootroot00000000000000"""Perform validation of final calls against known reference materials. Automates the process of checking pipeline results against known valid calls to identify discordant variants. This provides a baseline for ensuring the validity of pipeline updates and algorithm changes. """ import collections import contextlib import csv import hashlib import os import shutil import subprocess import time from pysam import VariantFile import six import toolz as tz import yaml from bcbio import broad, utils from bcbio.cwl import cwlutils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils, shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.variation import annotation, bedutils, validateplot, vcfutils, multi, naming # ## Individual sample comparisons def _get_validate(data): """Retrieve items to validate, from single samples or from combined joint calls. """ if data.get("vrn_file") and tz.get_in(["config", "algorithm", "validate"], data): return utils.deepish_copy(data) elif "group_orig" in data: for sub in multi.get_orig_items(data): if "validate" in sub["config"]["algorithm"]: sub_val = utils.deepish_copy(sub) sub_val["vrn_file"] = data["vrn_file"] return sub_val return None def normalize_input_path(x, data): """Normalize path for input files, handling relative paths. Looks for non-absolute paths in local and fastq directories """ if x is None: return None elif os.path.isabs(x): return os.path.normpath(x) else: for d in [data["dirs"].get("fastq"), data["dirs"].get("work")]: if d: cur_x = os.path.normpath(os.path.join(d, x)) if os.path.exists(cur_x): return cur_x raise IOError("Could not find validation file %s" % x) def _gunzip(f, data): if f is None: return None elif f.endswith(".gz"): out_file = f.replace(".gz", "") if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: cmd = "gunzip -c {f} > {tx_out_file}" do.run(cmd.format(**locals()), "gunzip input file") return out_file else: return f def _get_caller(data): callers = [tz.get_in(["config", "algorithm", "jointcaller"], data), tz.get_in(["config", "algorithm", "variantcaller"], data), "precalled"] caller = [c for c in callers if c][0] if isinstance(caller, (list, tuple)): assert len(caller) == 1, caller return caller[0] else: return caller def _get_caller_supplement(caller, data): """Some callers like MuTect incorporate a second caller for indels. """ if caller == "mutect": icaller = tz.get_in(["config", "algorithm", "indelcaller"], data) if icaller: caller = "%s/%s" % (caller, icaller) return caller def _pick_lead_item(items): """Choose lead item for a set of samples. Picks tumors for tumor/normal pairs and first sample for batch groups. """ paired = vcfutils.get_paired(items) if paired: return paired.tumor_data else: return list(items)[0] def _normalize_cwl_inputs(items): """Extract variation and validation data from CWL input list of batched samples. """ with_validate = {} vrn_files = [] ready_items = [] batch_samples = [] for data in (cwlutils.normalize_missing(utils.to_single_data(d)) for d in items): batch_samples.append(dd.get_sample_name(data)) if tz.get_in(["config", "algorithm", "validate"], data): with_validate[_checksum(tz.get_in(["config", "algorithm", "validate"], data))] = data if data.get("vrn_file"): vrn_files.append(data["vrn_file"]) ready_items.append(data) if len(with_validate) == 0: data = _pick_lead_item(ready_items) data["batch_samples"] = batch_samples return data else: assert len(with_validate) == 1, len(with_validate) assert len(set(vrn_files)) == 1, set(vrn_files) data = _pick_lead_item(with_validate.values()) data["batch_samples"] = batch_samples data["vrn_file"] = vrn_files[0] return data def _checksum(in_file, block_size=65536): """sha256 checksum, thanks to: https://gist.github.com/rji/b38c7238128edf53a181 """ cs = hashlib.sha256() with open(in_file, "rb") as f: for block in iter(lambda: f.read(block_size), b''): cs.update(block) return cs.hexdigest() def compare_to_rm(data): """Compare final variant calls against reference materials of known calls. """ if isinstance(data, (list, tuple)) and cwlutils.is_cwl_run(utils.to_single_data(data[0])): data = _normalize_cwl_inputs(data) toval_data = _get_validate(data) toval_data = cwlutils.unpack_tarballs(toval_data, toval_data) if toval_data: caller = _get_caller(toval_data) sample = dd.get_sample_name(toval_data) base_dir = utils.safe_makedir(os.path.join(toval_data["dirs"]["work"], "validate", sample, caller)) if isinstance(toval_data["vrn_file"], (list, tuple)): raise NotImplementedError("Multiple input files for validation: %s" % toval_data["vrn_file"]) else: vrn_file = os.path.abspath(toval_data["vrn_file"]) rm_file = normalize_input_path(toval_data["config"]["algorithm"]["validate"], toval_data) rm_interval_file = _gunzip(normalize_input_path(toval_data["config"]["algorithm"].get("validate_regions"), toval_data), toval_data) rm_interval_file = bedutils.clean_file(rm_interval_file, toval_data, prefix="validateregions-", bedprep_dir=utils.safe_makedir(os.path.join(base_dir, "bedprep"))) rm_file = naming.handle_synonyms(rm_file, dd.get_ref_file(toval_data), data.get("genome_build"), base_dir, data) rm_interval_file = (naming.handle_synonyms(rm_interval_file, dd.get_ref_file(toval_data), data.get("genome_build"), base_dir, data) if rm_interval_file else None) vmethod = tz.get_in(["config", "algorithm", "validate_method"], data, "rtg") # RTG can fail on totally empty files. Call everything in truth set as false negatives if not vcfutils.vcf_has_variants(vrn_file): eval_files = _setup_call_false(rm_file, rm_interval_file, base_dir, toval_data, "fn") data["validate"] = _rtg_add_summary_file(eval_files, base_dir, toval_data) # empty validation file, every call is a false positive elif not vcfutils.vcf_has_variants(rm_file): eval_files = _setup_call_fps(vrn_file, rm_interval_file, base_dir, toval_data, "fp") data["validate"] = _rtg_add_summary_file(eval_files, base_dir, toval_data) elif vmethod in ["rtg", "rtg-squash-ploidy"]: eval_files = _run_rtg_eval(vrn_file, rm_file, rm_interval_file, base_dir, toval_data, vmethod) eval_files = _annotate_validations(eval_files, toval_data) data["validate"] = _rtg_add_summary_file(eval_files, base_dir, toval_data) elif vmethod == "hap.py": data["validate"] = _run_happy_eval(vrn_file, rm_file, rm_interval_file, base_dir, toval_data) elif vmethod == "bcbio.variation": data["validate"] = _run_bcbio_variation(vrn_file, rm_file, rm_interval_file, base_dir, sample, caller, toval_data) return [[data]] def _annotate_validations(eval_files, data): """Add annotations about potential problem regions to validation VCFs. """ for key in ["tp", "tp-calls", "fp", "fn"]: if eval_files.get(key): eval_files[key] = annotation.add_genome_context(eval_files[key], data) return eval_files # ## Empty truth sets def _setup_call_false(vrn_file, rm_bed, base_dir, data, call_type): """Create set of false positives or ngatives for inputs with empty truth sets. """ out_file = os.path.join(base_dir, "%s.vcf.gz" % call_type) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: if not vrn_file.endswith(".gz"): vrn_file = vcfutils.bgzip_and_index(vrn_file, out_dir=os.path.dirname(tx_out_file)) cmd = ("bcftools view -R {rm_bed} -f 'PASS,.' {vrn_file} -O z -o {tx_out_file}") do.run(cmd.format(**locals()), "Prepare %s with empty reference" % call_type, data) return {call_type: out_file} # ## Real Time Genomics vcfeval def _get_sample_and_caller(data): return [tz.get_in(["metadata", "validate_sample"], data) or dd.get_sample_name(data), _get_caller_supplement(_get_caller(data), data)] def _rtg_add_summary_file(eval_files, base_dir, data): """Parse output TP FP and FN files to generate metrics for plotting. """ out_file = os.path.join(base_dir, "validate-summary.csv") if not utils.file_uptodate(out_file, eval_files.get("tp", eval_files.get("fp", eval_files["fn"]))): with file_transaction(data, out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: writer = csv.writer(out_handle) writer.writerow(["sample", "caller", "vtype", "metric", "value"]) base = _get_sample_and_caller(data) for metric in ["tp", "fp", "fn"]: for vtype, bcftools_types in [("SNPs", "--types snps"), ("Indels", "--exclude-types snps")]: in_file = eval_files.get(metric) if in_file and os.path.exists(in_file): cmd = ("bcftools view {bcftools_types} {in_file} | grep -v ^# | wc -l") count = int(subprocess.check_output(cmd.format(**locals()), shell=True)) else: count = 0 writer.writerow(base + [vtype, metric, count]) eval_files["summary"] = out_file return eval_files def _prepare_inputs(vrn_file, rm_file, rm_interval_file, base_dir, data): """Prepare input VCF and BED files for validation. """ if not rm_file.endswith(".vcf.gz") or not os.path.exists(rm_file + ".tbi"): rm_file = vcfutils.bgzip_and_index(rm_file, data["config"], out_dir=base_dir) if len(vcfutils.get_samples(vrn_file)) > 1: base = utils.splitext_plus(os.path.basename(vrn_file))[0] sample_file = os.path.join(base_dir, "%s-%s.vcf.gz" % (base, dd.get_sample_name(data))) vrn_file = vcfutils.select_sample(vrn_file, dd.get_sample_name(data), sample_file, data["config"]) # rtg fails on bgzipped VCFs produced by GatherVcfs so we re-prep them else: vrn_file = vcfutils.bgzip_and_index(vrn_file, data["config"], out_dir=base_dir) interval_bed = _get_merged_intervals(rm_interval_file, vrn_file, base_dir, data) return vrn_file, rm_file, interval_bed def _run_rtg_eval(vrn_file, rm_file, rm_interval_file, base_dir, data, validate_method): """Run evaluation of a caller against the truth set using rtg vcfeval. """ out_dir = os.path.join(base_dir, "rtg") if not utils.file_exists(os.path.join(out_dir, "done")): if os.path.exists(out_dir): shutil.rmtree(out_dir) vrn_file, rm_file, interval_bed = _prepare_inputs(vrn_file, rm_file, rm_interval_file, base_dir, data) rtg_ref = tz.get_in(["reference", "rtg"], data) if isinstance(rtg_ref, dict) and "base" in rtg_ref: rtg_ref = os.path.dirname(rtg_ref["base"]) assert rtg_ref and os.path.exists(rtg_ref), ("Did not find rtg indexed reference file for validation:\n%s\n" "Run bcbio_nextgen.py upgrade --data --aligners rtg" % rtg_ref) # handle CWL where we have a reference to a single file in the RTG directory if os.path.isfile(rtg_ref): rtg_ref = os.path.dirname(rtg_ref) # get core and memory usage from standard configuration threads = min(dd.get_num_cores(data), 6) resources = config_utils.get_resources("rtg", data["config"]) memory = config_utils.adjust_opts(resources.get("jvm_opts", ["-Xms500m", "-Xmx1500m"]), {"algorithm": {"memory_adjust": {"magnitude": threads, "direction": "increase"}}}) jvm_stack = [x for x in memory if x.startswith("-Xms")] jvm_mem = [x for x in memory if x.startswith("-Xmx")] jvm_stack = jvm_stack[0] if len(jvm_stack) > 0 else "-Xms500m" jvm_mem = jvm_mem[0].replace("-Xmx", "") if len(jvm_mem) > 0 else "3g" cmd = ["rtg", "vcfeval", "--threads", str(threads), "-b", rm_file, "--bed-regions", interval_bed, "-c", vrn_file, "-t", rtg_ref, "-o", out_dir] if validate_method == "rtg-squash-ploidy": cmd += ["--squash-ploidy"] rm_samples = vcfutils.get_samples(rm_file) if len(rm_samples) > 1 and dd.get_sample_name(data) in rm_samples: cmd += ["--sample=%s" % dd.get_sample_name(data)] cmd += ["--vcf-score-field='%s'" % (_pick_best_quality_score(vrn_file))] mem_export = "%s export RTG_JAVA_OPTS='%s' && export RTG_MEM=%s" % (utils.local_path_export(), jvm_stack, jvm_mem) cmd = mem_export + " && " + " ".join(cmd) do.run(cmd, "Validate calls using rtg vcfeval", data) out = {"fp": os.path.join(out_dir, "fp.vcf.gz"), "fn": os.path.join(out_dir, "fn.vcf.gz")} tp_calls = os.path.join(out_dir, "tp.vcf.gz") tp_baseline = os.path.join(out_dir, "tp-baseline.vcf.gz") if os.path.exists(tp_baseline): out["tp"] = tp_baseline out["tp-calls"] = tp_calls else: out["tp"] = tp_calls return out def _pick_best_quality_score(vrn_file): """Flexible quality score selection, picking the best available. Implementation based on discussion: https://github.com/bcbio/bcbio-nextgen/commit/a538cecd86c0000d17d3f9d4f8ac9d2da04f9884#commitcomment-14539249 (RTG=AVR/GATK=VQSLOD/MuTect=t_lod_fstar, otherwise GQ, otherwise QUAL, otherwise DP.) For MuTect, it's not clear how to get t_lod_fstar, the right quality score, into VCF cleanly. MuTect2 has TLOD in the INFO field. """ # pysam fails on checking reference contigs if input is empty if not vcfutils.vcf_has_variants(vrn_file): return "DP" to_check = 25 scores = collections.defaultdict(int) try: in_handle = VariantFile(vrn_file) except ValueError: raise ValueError("Failed to parse input file in preparation for validation: %s" % vrn_file) with contextlib.closing(in_handle) as val_in: for i, rec in enumerate(val_in): if i > to_check: break if "VQSLOD" in rec.info and rec.info.get("VQSLOD") is not None: scores["INFO=VQSLOD"] += 1 if "TLOD" in rec.info and rec.info.get("TLOD") is not None: scores["INFO=TLOD"] += 1 for skey in ["AVR", "GQ", "DP"]: if len(rec.samples) > 0 and rec.samples[0].get(skey) is not None: scores[skey] += 1 if rec.qual: scores["QUAL"] += 1 for key in ["AVR", "INFO=VQSLOD", "INFO=TLOD", "GQ", "QUAL", "DP"]: if scores[key] > 0: return key raise ValueError("Did not find quality score for validation from %s" % vrn_file) def _get_merged_intervals(rm_interval_file, vrn_file, base_dir, data): """Retrieve intervals to run validation on, merging reference and callable BED files. """ a_intervals = get_analysis_intervals(data, vrn_file, base_dir) if a_intervals: final_intervals = shared.remove_lcr_regions(a_intervals, [data]) if rm_interval_file: caller = _get_caller(data) sample = dd.get_sample_name(data) combo_intervals = os.path.join(base_dir, "%s-%s-%s-wrm.bed" % (utils.splitext_plus(os.path.basename(final_intervals))[0], sample, caller)) if not utils.file_uptodate(combo_intervals, final_intervals): with file_transaction(data, combo_intervals) as tx_out_file: with utils.chdir(os.path.dirname(tx_out_file)): # Copy files locally to avoid issues on shared filesystems # where BEDtools has trouble accessing the same base # files from multiple locations a = os.path.basename(final_intervals) b = os.path.basename(rm_interval_file) try: shutil.copyfile(final_intervals, a) except IOError: time.sleep(60) shutil.copyfile(final_intervals, a) try: shutil.copyfile(rm_interval_file, b) except IOError: time.sleep(60) shutil.copyfile(rm_interval_file, b) cmd = ("bedtools intersect -nonamecheck -a {a} -b {b} > {tx_out_file}") do.run(cmd.format(**locals()), "Intersect callable intervals for rtg vcfeval") final_intervals = combo_intervals else: assert rm_interval_file, "No intervals to subset analysis with for %s" % vrn_file final_intervals = shared.remove_lcr_regions(rm_interval_file, [data]) return final_intervals def _callable_from_gvcf(data, vrn_file, out_dir): """Retrieve callable regions based on ref call regions in gVCF. Uses https://github.com/lijiayong/gvcf_regions """ methods = {"freebayes": "freebayes", "platypus": "platypus", "gatk-haplotype": "gatk"} gvcf_type = methods.get(dd.get_variantcaller(data)) if gvcf_type: out_file = os.path.join(out_dir, "%s-gcvf-coverage.bed" % utils.splitext_plus(os.path.basename(vrn_file))[0]) if not utils.file_uptodate(out_file, vrn_file): with file_transaction(data, out_file) as tx_out_file: cmd = ("gvcf_regions.py --gvcf_type {gvcf_type} {vrn_file} " "| bedtools merge > {tx_out_file}") do.run(cmd.format(**locals()), "Convert gVCF to BED file of callable regions") return out_file def get_analysis_intervals(data, vrn_file, base_dir): """Retrieve analysis regions for the current variant calling pipeline. """ from bcbio.bam import callable if vrn_file and vcfutils.is_gvcf_file(vrn_file): callable_bed = _callable_from_gvcf(data, vrn_file, base_dir) if callable_bed: return callable_bed if data.get("ensemble_bed"): return data["ensemble_bed"] elif dd.get_sample_callable(data): return dd.get_sample_callable(data) elif data.get("align_bam"): return callable.sample_callable_bed(data["align_bam"], dd.get_ref_file(data), data)[0] elif data.get("work_bam"): return callable.sample_callable_bed(data["work_bam"], dd.get_ref_file(data), data)[0] elif data.get("work_bam_callable"): data = utils.deepish_copy(data) data["work_bam"] = data.pop("work_bam_callable") return callable.sample_callable_bed(data["work_bam"], dd.get_ref_file(data), data)[0] elif tz.get_in(["config", "algorithm", "callable_regions"], data): return tz.get_in(["config", "algorithm", "callable_regions"], data) elif tz.get_in(["config", "algorithm", "variant_regions"], data): return tz.get_in(["config", "algorithm", "variant_regions"], data) # ## hap.py def _run_happy_eval(vrn_file, rm_file, rm_interval_file, base_dir, data): """Validation with hap.py: https://github.com/Illumina/hap.py XXX Does not yet parse out metrics for plotting. """ out_dir = utils.safe_makedir(os.path.join(base_dir, "happy")) out_prefix = os.path.join(out_dir, "val") if not utils.file_exists(out_prefix + ".summary.csv"): vrn_file, rm_file, interval_bed = _prepare_inputs(vrn_file, rm_file, rm_interval_file, base_dir, data) cmd = ["hap.py", "-V", "-f", interval_bed, "-r", dd.get_ref_file(data), "-l", ",".join(_get_location_list(interval_bed)), "-o", out_prefix, rm_file, vrn_file] do.run(cmd, "Validate calls using hap.py", data) return {"vcf": out_prefix + ".vcf.gz"} def _get_location_list(interval_bed): """Retrieve list of locations to analyze from input BED file. """ import pybedtools regions = collections.OrderedDict() for region in pybedtools.BedTool(interval_bed): regions[str(region.chrom)] = None return regions.keys() # ## bcbio.variation comparison -- deprecated approach def _run_bcbio_variation(vrn_file, rm_file, rm_interval_file, base_dir, sample, caller, data): """Run validation of a caller against the truth set using bcbio.variation. """ val_config_file = _create_validate_config_file(vrn_file, rm_file, rm_interval_file, base_dir, data) work_dir = os.path.join(base_dir, "work") out = {"summary": os.path.join(work_dir, "validate-summary.csv"), "grading": os.path.join(work_dir, "validate-grading.yaml"), "discordant": os.path.join(work_dir, "%s-eval-ref-discordance-annotate.vcf" % sample)} if not utils.file_exists(out["discordant"]) or not utils.file_exists(out["grading"]): bcbio_variation_comparison(val_config_file, base_dir, data) out["concordant"] = filter(os.path.exists, [os.path.join(work_dir, "%s-%s-concordance.vcf" % (sample, x)) for x in ["eval-ref", "ref-eval"]])[0] return out def bcbio_variation_comparison(config_file, base_dir, data): """Run a variant comparison using the bcbio.variation toolkit, given an input configuration. """ tmp_dir = utils.safe_makedir(os.path.join(base_dir, "tmp")) resources = config_utils.get_resources("bcbio_variation", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx2g"]) cmd = ["bcbio-variation"] + jvm_opts + broad.get_default_jvm_opts(tmp_dir) + \ ["variant-compare", config_file] do.run(cmd, "Comparing variant calls using bcbio.variation", data) def _create_validate_config_file(vrn_file, rm_file, rm_interval_file, base_dir, data): config_dir = utils.safe_makedir(os.path.join(base_dir, "config")) config_file = os.path.join(config_dir, "validate.yaml") if not utils.file_uptodate(config_file, vrn_file): with file_transaction(data, config_file) as tx_config_file: with open(tx_config_file, "w") as out_handle: out = _create_validate_config(vrn_file, rm_file, rm_interval_file, base_dir, data) yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) return config_file def _create_validate_config(vrn_file, rm_file, rm_interval_file, base_dir, data): """Create a bcbio.variation configuration input for validation. """ ref_call = {"file": str(rm_file), "name": "ref", "type": "grading-ref", "fix-sample-header": True, "remove-refcalls": True} a_intervals = get_analysis_intervals(data, vrn_file, base_dir) if a_intervals: a_intervals = shared.remove_lcr_regions(a_intervals, [data]) if rm_interval_file: ref_call["intervals"] = rm_interval_file eval_call = {"file": vrn_file, "name": "eval", "remove-refcalls": True} exp = {"sample": data["name"][-1], "ref": dd.get_ref_file(data), "approach": "grade", "calls": [ref_call, eval_call]} if a_intervals: exp["intervals"] = os.path.abspath(a_intervals) if data.get("align_bam"): exp["align"] = data["align_bam"] elif data.get("work_bam"): exp["align"] = data["work_bam"] return {"dir": {"base": base_dir, "out": "work", "prep": "work/prep"}, "experiments": [exp]} # ## Summarize comparisons def _flatten_grading(stats): vtypes = ["snp", "indel"] cat = "concordant" for vtype in vtypes: yield vtype, cat, stats[cat][cat].get(vtype, 0) for vtype in vtypes: for vclass, vitems in sorted(stats["discordant"].get(vtype, {}).items()): for vreason, val in sorted(vitems.items()): yield vtype, "discordant-%s-%s" % (vclass, vreason), val yield vtype, "discordant-%s-total" % vclass, sum(vitems.values()) def _has_grading_info(samples, vkey): for data in samples: if data.get(vkey): return True for variant in data.get("variants", []): if variant.get(vkey): return True return False def _group_validate_samples(samples, vkey, batch_keys): extras = [] validated = collections.defaultdict(list) for data in samples: is_v = False if data.get(vkey): is_v = True for variant in data.get("variants", []): if isinstance(variant, dict) and variant.get(vkey): is_v = True if is_v: for batch_key in batch_keys: vname = tz.get_in(batch_key, data) if vname and not (isinstance(vname, six.string_types) and vname.lower() in ["none", "false"]): break if isinstance(vname, (list, tuple)): vname = vname[0] validated[vname].append(data) else: extras.append([data]) return validated, extras def summarize_grading(samples, vkey="validate"): """Provide summaries of grading results across all samples. Handles both traditional pipelines (validation part of variants) and CWL pipelines (validation at top level) """ samples = list(utils.flatten(samples)) if not _has_grading_info(samples, vkey): return [[d] for d in samples] validate_dir = utils.safe_makedir(os.path.join(samples[0]["dirs"]["work"], vkey)) header = ["sample", "caller", "variant.type", "category", "value"] _summarize_combined(samples, vkey) validated, out = _group_validate_samples(samples, vkey, (["metadata", "validate_batch"], ["metadata", "batch"], ["description"])) for vname, vitems in validated.items(): out_csv = os.path.join(validate_dir, "grading-summary-%s.csv" % vname) with open(out_csv, "w") as out_handle: writer = csv.writer(out_handle) writer.writerow(header) plot_data = [] plot_files = [] for data in sorted(vitems, key=lambda x: x.get("lane", dd.get_sample_name(x)) or ""): validations = [variant.get(vkey) for variant in data.get("variants", []) if isinstance(variant, dict)] validations = [v for v in validations if v] if len(validations) == 0 and vkey in data: validations = [data.get(vkey)] for validate in validations: if validate: validate["grading_summary"] = out_csv if validate.get("grading"): for row in _get_validate_plotdata_yaml(validate["grading"], data): writer.writerow(row) plot_data.append(row) elif validate.get("summary") and not validate.get("summary") == "None": if isinstance(validate["summary"], (list, tuple)): plot_files.extend(list(set(validate["summary"]))) else: plot_files.append(validate["summary"]) if plot_files: plots = validateplot.classifyplot_from_plotfiles(plot_files, out_csv) elif plot_data: plots = validateplot.create(plot_data, header, 0, data["config"], os.path.splitext(out_csv)[0]) else: plots = [] for data in vitems: if data.get(vkey): data[vkey]["grading_plots"] = plots for variant in data.get("variants", []): if isinstance(variant, dict) and variant.get(vkey): variant[vkey]["grading_plots"] = plots out.append([data]) return out def _summarize_combined(samples, vkey): """Prepare summarized CSV and plot files for samples to combine together. Helps handle cases where we want to summarize over multiple samples. """ validate_dir = utils.safe_makedir(os.path.join(samples[0]["dirs"]["work"], vkey)) combined, _ = _group_validate_samples(samples, vkey, [["metadata", "validate_combine"]]) for vname, vitems in combined.items(): if vname: cur_combined = collections.defaultdict(int) for data in sorted(vitems, key=lambda x: x.get("lane", dd.get_sample_name(x))): validations = [variant.get(vkey) for variant in data.get("variants", [])] validations = [v for v in validations if v] if len(validations) == 0 and vkey in data: validations = [data.get(vkey)] for validate in validations: with open(validate["summary"]) as in_handle: reader = csv.reader(in_handle) next(reader) # header for _, caller, vtype, metric, value in reader: cur_combined[(caller, vtype, metric)] += int(value) out_csv = os.path.join(validate_dir, "grading-summary-%s.csv" % vname) with open(out_csv, "w") as out_handle: writer = csv.writer(out_handle) header = ["sample", "caller", "vtype", "metric", "value"] writer.writerow(header) for (caller, variant_type, category), val in cur_combined.items(): writer.writerow(["combined-%s" % vname, caller, variant_type, category, val]) plots = validateplot.classifyplot_from_valfile(out_csv) def combine_validations(items, vkey="validate"): """Combine multiple batch validations into validation outputs. """ csvs = set([]) pngs = set([]) for v in [x.get(vkey) for x in items]: if v and v.get("grading_summary"): csvs.add(v.get("grading_summary")) if v and v.get("grading_plots"): pngs |= set(v.get("grading_plots")) if len(csvs) == 1: grading_summary = csvs.pop() else: grading_summary = os.path.join(utils.safe_makedir(os.path.join(dd.get_work_dir(items[0]), vkey)), "grading-summary-combined.csv") with open(grading_summary, "w") as out_handle: for i, csv in enumerate(sorted(list(csvs))): with open(csv) as in_handle: h = in_handle.readline() if i == 0: out_handle.write(h) for l in in_handle: out_handle.write(l) return {"grading_plots": sorted(list(pngs)), "grading_summary": grading_summary} def _get_validate_plotdata_yaml(grading_file, data): """Retrieve validation plot data from grading YAML file (old style). """ with open(grading_file) as in_handle: grade_stats = yaml.safe_load(in_handle) for sample_stats in grade_stats: sample = sample_stats["sample"] for vtype, cat, val in _flatten_grading(sample_stats): yield [sample, variant.get("variantcaller", ""), vtype, cat, val] # ## Summarize by frequency def freq_summary(val_file, call_file, truth_file, target_name): """Summarize true and false positive calls by variant type and frequency. Resolve differences in true/false calls based on output from hap.py: https://github.com/sequencing/hap.py """ out_file = "%s-freqs.csv" % utils.splitext_plus(val_file)[0] truth_freqs = _read_truth_freqs(truth_file) call_freqs = _read_call_freqs(call_file, target_name) with VariantFile(val_file) as val_in: with open(out_file, "w") as out_handle: writer = csv.writer(out_handle) writer.writerow(["vtype", "valclass", "freq"]) for rec in val_in: call_type = _classify_rec(rec) val_type = _get_validation_status(rec) key = _get_key(rec) freq = truth_freqs.get(key, call_freqs.get(key, 0.0)) writer.writerow([call_type, val_type, freq]) return out_file def _get_key(rec): return (rec.contig, rec.pos, rec.ref, rec.alts[0]) def _classify_rec(rec): """Determine class of variant in the record. """ if max([len(x) for x in rec.alleles]) == 1: return "snp" else: return "indel" def _get_validation_status(rec): """Retrieve the status of the validation, supporting hap.py output """ return rec.info["type"] def _read_call_freqs(in_file, sample_name): """Identify frequencies for calls in the input file. """ from bcbio.heterogeneity import bubbletree out = {} with VariantFile(in_file) as call_in: for rec in call_in: if rec.filter.keys() == ["PASS"]: for name, sample in rec.samples.items(): if name == sample_name: alt, depth, freq = bubbletree.sample_alt_and_depth(rec, sample) if freq is not None: out[_get_key(rec)] = freq return out def _read_truth_freqs(in_file): """Read frequency of calls from truth VCF. Currently handles DREAM data, needs generalization for other datasets. """ out = {} with VariantFile(in_file) as bcf_in: for rec in bcf_in: freq = float(rec.info.get("VAF", 1.0)) out[_get_key(rec)] = freq return out bcbio-nextgen-1.2.9/bcbio/variation/validateplot.py000066400000000000000000000401711415626112400223700ustar00rootroot00000000000000"""Plot validation results from variant calling comparisons. Handles data normalization and plotting, emphasizing comparisons on methodology differences. """ import collections import os from distutils.version import LooseVersion import numpy as np import pandas as pd from bcbio.log import logger from bcbio import utils from bcbio.variation import bamprep mpl = utils.LazyImport("matplotlib") plt = utils.LazyImport("matplotlib.pyplot") mpl_ticker = utils.LazyImport("matplotlib.ticker") sns = utils.LazyImport("seaborn") def classifyplot_from_plotfiles(plot_files, out_csv, outtype="png", title=None, size=None): """Create a plot from individual summary csv files with classification metrics. """ dfs = [pd.read_csv(x) for x in plot_files] samples = [] for df in dfs: for sample in df["sample"].unique(): if sample not in samples: samples.append(sample) df = pd.concat(dfs) df.to_csv(out_csv, index=False) return classifyplot_from_valfile(out_csv, outtype, title, size, samples) def classifyplot_from_valfile(val_file, outtype="png", title=None, size=None, samples=None, callers=None): """Create a plot from a summarized validation file. Does new-style plotting of summarized metrics of false negative rate and false discovery rate. https://en.wikipedia.org/wiki/Sensitivity_and_specificity """ mpl.use('Agg', force=True) df = pd.read_csv(val_file) grouped = df.groupby(["sample", "caller", "vtype"]) df = grouped.apply(_calculate_fnr_fdr) df = df.reset_index() if len(df) == 0: return [] else: out_file = "%s.%s" % (os.path.splitext(val_file)[0], outtype) _do_classifyplot(df, out_file, title, size, samples, callers) return [out_file] def _calculate_fnr_fdr(group): """Calculate the false negative rate (1 - sensitivity) and false discovery rate (1 - precision). """ data = {k: d["value"] for k, d in group.set_index("metric").T.to_dict().items()} return pd.DataFrame([{"fnr": data["fn"] / float(data["tp"] + data["fn"]) * 100.0 if data["tp"] > 0 else 0.0, "fdr": data["fp"] / float(data["tp"] + data["fp"]) * 100.0 if data["tp"] > 0 else 0.0, "tpr": "TP: %s FN: %s" % (data["tp"], data["fn"]), "spc": "FP: %s" % (data["fp"])}]) def _do_classifyplot(df, out_file, title=None, size=None, samples=None, callers=None): """Plot using classification-based plot using seaborn. """ metric_labels = {"fdr": "False discovery rate", "fnr": "False negative rate"} metrics = [("fnr", "tpr"), ("fdr", "spc")] is_mpl2 = LooseVersion(mpl.__version__) >= LooseVersion('2.0') colors = ["light grey", "greyish"] * 10 data_dict = df.set_index(["sample", "caller", "vtype"]).T.to_dict() plt.ioff() plt.style.use('seaborn-white') vtypes = sorted(df["vtype"].unique(), reverse=True) if not callers: callers = sorted(df["caller"].unique()) if not samples: samples = sorted(df["sample"].unique()) if len(samples) >= len(callers): cats, groups = (samples, callers) data_dict = df.set_index(["sample", "caller", "vtype"]).T.to_dict() else: cats, groups = (callers, samples) data_dict = df.set_index(["caller", "sample", "vtype"]).T.to_dict() fig, axs = plt.subplots(len(vtypes) * len(groups), len(metrics)) fig.text(.5, .95, title if title else "", horizontalalignment='center', size=14) for vi, vtype in enumerate(vtypes): for gi, group in enumerate(groups): for mi, (metric, label) in enumerate(metrics): row_plots = axs if len(vtypes) * len(groups) == 1 else axs[vi * len(groups) + gi] cur_plot = row_plots if len(metrics) == 1 else row_plots[mi] vals, labels = [], [] for cat in cats: cur_data = data_dict.get((cat, group, vtype)) if cur_data: vals.append(cur_data[metric]) labels.append(cur_data[label]) cur_plot.barh(np.arange(len(vals)), vals, color=sns.xkcd_palette([colors[vi]])) all_vals = [] for k, d in data_dict.items(): if k[-1] == vtype: for m in metrics: all_vals.append(d[m[0]]) metric_max = max(all_vals) cur_plot.set_xlim(0, metric_max) pad = 0.1 * metric_max ai_adjust = 0.0 if is_mpl2 else 0.35 for ai, (val, label) in enumerate(zip(vals, labels)): cur_plot.annotate(label, (pad + (0 if max(vals) > metric_max / 2.0 else max(vals)), ai + ai_adjust), va='center', size=7) cur_plot.locator_params(nbins=len(cats) + (2 if len(cats) > 2 else 1), axis="y", tight=True) if mi == 0: cur_plot.tick_params(axis='y', which='major', labelsize=8) plot_cats = ([""] + cats) if is_mpl2 else cats plot_va = "center" if is_mpl2 else "bottom" cur_plot.set_yticklabels(plot_cats, size=8, va=plot_va) cur_plot.set_title("%s: %s" % (vtype, group), fontsize=12, loc="left") else: cur_plot.get_yaxis().set_ticks([]) if gi == len(groups) - 1: cur_plot.tick_params(axis='x', which='major', labelsize=8) cur_plot.get_xaxis().set_major_formatter( mpl_ticker.FuncFormatter(lambda v, p: "%s%%" % (int(v) if round(v) == v else v))) if vi == len(vtypes) - 1: cur_plot.get_xaxis().set_label_text(metric_labels[metric], size=12) else: cur_plot.get_xaxis().set_ticks([]) cur_plot.spines['bottom'].set_visible(False) cur_plot.spines['left'].set_visible(False) cur_plot.spines['top'].set_visible(False) cur_plot.spines['right'].set_visible(False) x, y = (6, len(vtypes) * len(groups) + 1 * 0.5 * len(cats)) if size is None else size fig.set_size_inches(x, y) fig.tight_layout(rect=(0, 0, 1, 0.95)) plt.subplots_adjust(hspace=0.6) fig.savefig(out_file) def create_from_csv(in_csv, config=None, outtype="png", title=None, size=None): df = pd.read_csv(in_csv) create(df, None, 0, config or {}, os.path.splitext(in_csv)[0], outtype, title, size) def create(plot_data, header, ploti, sample_config, out_file_base, outtype="png", title=None, size=None): """Create plots of validation results for a sample, labeling prep strategies. """ if mpl is None or plt is None or sns is None: not_found = ", ".join([x for x in ['mpl', 'plt', 'sns'] if eval(x) is None]) logger.info("No validation plot. Missing imports: %s" % not_found) return None mpl.use('Agg', force=True) if header: df = pd.DataFrame(plot_data, columns=header) else: df = plot_data df["aligner"] = [get_aligner(x, sample_config) for x in df["sample"]] df["bamprep"] = [get_bamprep(x, sample_config) for x in df["sample"]] floors = get_group_floors(df, cat_labels) df["value.floor"] = [get_floor_value(x, cat, vartype, floors) for (x, cat, vartype) in zip(df["value"], df["category"], df["variant.type"])] out = [] for i, prep in enumerate(df["bamprep"].unique()): out.append(plot_prep_methods(df, prep, i + ploti, out_file_base, outtype, title, size)) return out cat_labels = {"concordant": "Concordant", "discordant-missing-total": "Discordant (missing)", "discordant-extra-total": "Discordant (extra)", "discordant-shared-total": "Discordant (shared)"} vtype_labels = {"snp": "SNPs", "indel": "Indels"} prep_labels = {} caller_labels = {"ensemble": "Ensemble", "freebayes": "FreeBayes", "gatk": "GATK Unified\nGenotyper", "gatk-haplotype": "GATK Haplotype\nCaller"} def plot_prep_methods(df, prep, prepi, out_file_base, outtype, title=None, size=None): """Plot comparison between BAM preparation methods. """ samples = df[(df["bamprep"] == prep)]["sample"].unique() assert len(samples) >= 1, samples out_file = "%s-%s.%s" % (out_file_base, samples[0], outtype) df = df[df["category"].isin(cat_labels)] _seaborn(df, prep, prepi, out_file, title, size) return out_file def _seaborn(df, prep, prepi, out_file, title=None, size=None): """Plot using seaborn wrapper around matplotlib. """ plt.ioff() sns.set(style='dark') vtypes = df["variant.type"].unique() callers = sorted(df["caller"].unique()) cats = _check_cats(["concordant", "discordant-missing-total", "discordant-extra-total", "discordant-shared-total"], vtypes, df, prep, callers) fig, axs = plt.subplots(len(vtypes), len(cats)) width = 0.8 for i, vtype in enumerate(vtypes): ax_row = axs[i] if len(vtypes) > 1 else axs for j, cat in enumerate(cats): vals, labels, maxval = _get_chart_info(df, vtype, cat, prep, callers) if len(cats) == 1: assert j == 0 ax = ax_row else: ax = ax_row[j] if i == 0: ax.set_title(cat_labels[cat], size=14) ax.get_yaxis().set_ticks([]) if j == 0: ax.set_ylabel(vtype_labels[vtype], size=14) ax.bar(np.arange(len(callers)), vals, width=width) ax.set_ylim(0, maxval) if i == len(vtypes) - 1: ax.set_xticks(np.arange(len(callers)) + width / 2.0) ax.set_xticklabels([caller_labels.get(x, x).replace("__", "\n") if x else "" for x in callers], size=8, rotation=45) else: ax.get_xaxis().set_ticks([]) _annotate(ax, labels, vals, np.arange(len(callers)), width) fig.text(.5, .95, prep_labels.get(prep, "") if title is None else title, horizontalalignment='center', size=16) fig.subplots_adjust(left=0.05, right=0.95, top=0.87, bottom=0.15, wspace=0.1, hspace=0.1) x, y = (10, 5) if size is None else size fig.set_size_inches(x, y) fig.savefig(out_file) def _check_cats(cats, vtypes, df, prep, callers): """Only include categories in the final output if they have values. """ out = [] for cat in cats: all_vals = [] for vtype in vtypes: vals, labels, maxval = _get_chart_info(df, vtype, cat, prep, callers) all_vals.extend(vals) if sum(all_vals) / float(len(all_vals)) > 2: out.append(cat) if len(out) == 0: return cats else: return out def _get_chart_info(df, vtype, cat, prep, callers): """Retrieve values for a specific variant type, category and prep method. """ maxval_raw = max(list(df["value.floor"])) curdf = df[(df["variant.type"] == vtype) & (df["category"] == cat) & (df["bamprep"] == prep)] vals = [] labels = [] for c in callers: row = curdf[df["caller"] == c] if len(row) > 0: vals.append(list(row["value.floor"])[0]) labels.append(list(row["value"])[0]) else: vals.append(1) labels.append("") return vals, labels, maxval_raw def _annotate(ax, annotate, height, left, width): """Annotate axis with labels. """ annotate_yrange_factor = 0.010 xticks = np.array(left) + width / 2.0 ymin, ymax = ax.get_ylim() yrange = ymax - ymin # Reset ymax and ymin so there's enough room to see the annotation of # the top-most if ymax > 0: ymax += yrange * 0.15 if ymin < 0: ymin -= yrange * 0.15 ax.set_ylim(ymin, ymax) yrange = ymax - ymin offset_ = yrange * annotate_yrange_factor if isinstance(annotate, collections.Iterable): annotations = map(str, annotate) else: annotations = ['%.3f' % h if type(h) is np.float_ else str(h) for h in height] for x, h, annotation in zip(xticks, height, annotations): # Adjust the offset to account for negative bars offset = offset_ if h >= 0 else -1 * offset_ verticalalignment = 'bottom' if h >= 0 else 'top' if len(str(annotation)) > 6: size = 7 elif len(str(annotation)) > 5: size = 8 else: size = 10 # Finally, add the text to the axes ax.annotate(annotation, (x, h + offset), verticalalignment=verticalalignment, horizontalalignment='center', size=size) def _ggplot(df, out_file): """Plot faceted items with ggplot wrapper on top of matplotlib. XXX Not yet functional """ import ggplot as gg df["variant.type"] = [vtype_labels[x] for x in df["variant.type"]] df["category"] = [cat_labels[x] for x in df["category"]] df["caller"] = [caller_labels.get(x, None) for x in df["caller"]] p = (gg.ggplot(df, gg.aes(x="caller", y="value.floor")) + gg.geom_bar() + gg.facet_wrap("variant.type", "category") + gg.theme_seaborn()) gg.ggsave(p, out_file) def get_floor_value(x, cat, vartype, floors): """Modify values so all have the same relative scale for differences. Using the chosen base heights, adjusts an individual sub-plot to be consistent relative to that height. """ all_base = floors[vartype] cur_max = floors[(cat, vartype)] if cur_max > all_base: diff = cur_max - all_base x = max(1, x - diff) return x def get_group_floors(df, cat_labels): """Retrieve the floor for a given row of comparisons, creating a normalized set of differences. We need to set non-zero floors so large numbers (like concordance) don't drown out small numbers (like discordance). This defines the height for a row of comparisons as either the minimum height of any sub-plot, or the maximum difference between higher and lower (plus 10%). """ group_maxes = collections.defaultdict(list) group_diffs = collections.defaultdict(list) diff_pad = 0.1 # 10% padding onto difference to avoid large numbers looking like zero for name, group in df.groupby(["category", "variant.type"]): label, stype = name if label in cat_labels: diff = max(group["value"]) - min(group["value"]) group_diffs[stype].append(diff + int(diff_pad * diff)) group_maxes[stype].append(max(group["value"])) group_maxes[name].append(max(group["value"])) out = {} for k, vs in group_maxes.items(): if k in group_diffs: out[k] = max(max(group_diffs[stype]), min(vs)) else: out[k] = min(vs) return out def get_aligner(x, config): return utils.get_in(config, ("algorithm", "aligner"), "") def get_bamprep(x, config): params = bamprep._get_prep_params({"config": {"algorithm": config.get("algorithm", {})}}) if params["realign"] == "gatk" and params["recal"] == "gatk": return "gatk" elif not params["realign"] and not params["recal"]: return "none" elif not params.get("recal") or not params.get("realign"): return "mixed" else: return "" # ## Frequency plots def facet_freq_plot(freq_csv, caller): """Prepare a facet plot of frequencies stratified by variant type and status (TP, FP, FN). Makes a nice plot with the output from validate.freq_summary """ out_file = "%s.png" % os.path.splitext(freq_csv)[0] plt.ioff() sns.set(style='dark') df = pd.read_csv(freq_csv) g = sns.FacetGrid(df, row="vtype", col="valclass", margin_titles=True, col_order=["TP", "FN", "FP"], row_order=["snp", "indel"], sharey=False) g.map(plt.hist, "freq", bins=20, align="left") g.set(xlim=(0.0, 1.0)) g.fig.set_size_inches(8, 6) g.fig.text(.05, .97, caller, horizontalalignment='center', size=14) g.fig.savefig(out_file) bcbio-nextgen-1.2.9/bcbio/variation/vardict.py000066400000000000000000000464771415626112400213530ustar00rootroot00000000000000"""Sensitive variant calling using VarDict. Defaults to using the faster, equally sensitive Java port: https://github.com/AstraZeneca-NGS/VarDictJava if 'vardict' or 'vardict-java' is specified in the configuration. To use the VarDict perl version: https://github.com/AstraZeneca-NGS/VarDict specify 'vardict-perl'. """ from decimal import * from distutils.version import LooseVersion import os import sys from six.moves import zip import six import toolz as tz import pybedtools from bcbio import bam, broad, utils from bcbio.distributed.transaction import file_transaction from bcbio.heterogeneity import chromhacks from bcbio.pipeline import config_utils, shared from bcbio.pipeline import datadict as dd from bcbio.provenance import do, programs from bcbio.variation import bamprep, bedutils, vcfutils def _is_bed_file(target): return target and isinstance(target, six.string_types) and os.path.isfile(target) def _vardict_options_from_config(items, config, out_file, target=None, is_rnaseq=False): var2vcf_opts = [] opts = ["-c 1", "-S 2", "-E 3", "-g 4"] # ["-z", "-F", "-c", "1", "-S", "2", "-E", "3", "-g", "4", "-x", "0", # "-k", "3", "-r", "4", "-m", "8"] cores = dd.get_num_cores(items[0]) if cores and cores > 1: opts += ["-th", str(cores)] # Disable SV calling for vardict, causes issues with regional analysis # by detecting SVs outside of target regions, which messes up merging # SV calling will be worked on as a separate step vardict_cl = get_vardict_command(items[0]) version = programs.get_version_manifest(vardict_cl) # turn off structural variants if (vardict_cl and version and ((vardict_cl == "vardict-java" and LooseVersion(version) >= LooseVersion("1.5.5")) or (vardict_cl == "vardict"))): opts += ["--nosv"] if (vardict_cl and version and (vardict_cl == "vardict-java" and LooseVersion(version) >= LooseVersion("1.5.6"))): opts += ["--deldupvar"] # remove low mapping quality reads if not is_rnaseq: opts += ["-Q", "10"] # Remove QCfail reads, avoiding high depth repetitive regions opts += ["-F", "0x700"] resources = config_utils.get_resources("vardict", config) if resources.get("options"): opts += [str(x) for x in resources["options"]] resources = config_utils.get_resources("var2vcf", config) if resources.get("options"): var2vcf_opts += [str(x) for x in resources["options"]] if target and _is_bed_file(target): target = _enforce_max_region_size(target, items[0]) opts += [target] # this must be the last option _add_freq_options(config, opts, var2vcf_opts) return " ".join(opts), " ".join(var2vcf_opts) def _add_freq_options(config, opts, var2vcf_opts): """ Setting -f option for vardict and var2vcf_valid Prioritizing settings in resources/vardict/options, then algorithm/min_allele_fraction: min_allele_fraction "-f" in opts var2vcfopts -> vardict -f var2vcf -f yes yes yes opts var2vcfopts yes yes - opts - yes - yes min_allele_fraction var2vcfopts yes - - min_allele_fraction min_allele_fraction default yes yes opts var2vcfopts default yes - opts - default - yes min_allele_fraction var2vcfopts default - - min_allele_fraction min_allele_fraction """ if "-f" not in opts: freq = Decimal(utils.get_in(config, ("algorithm", "min_allele_fraction"), 10)) / Decimal(100.0) opts.extend(["-f", str(freq)]) if "-f" not in var2vcf_opts: var2vcf_opts.extend(["-f", str(freq)]) def _enforce_max_region_size(in_file, data): """Ensure we don't have any chunks in the region greater than 20kb. VarDict memory usage depends on size of individual windows in the input file. This breaks regions into 20kb chunks with 250bp overlaps. 20kb gives ~1Gb/core memory usage and the overlaps avoid missing indels spanning a gap. Downstream VarDict merging sorts out any variants across windows. https://github.com/AstraZeneca-NGS/VarDictJava/issues/64 """ max_size = 20000 overlap_size = 250 def _has_larger_regions(f): return any(r.stop - r.start > max_size for r in pybedtools.BedTool(f)) out_file = "%s-regionlimit%s" % utils.splitext_plus(in_file) if not utils.file_exists(out_file): if _has_larger_regions(in_file): with file_transaction(data, out_file) as tx_out_file: pybedtools.BedTool().window_maker(w=max_size, s=max_size - overlap_size, b=pybedtools.BedTool(in_file)).saveas(tx_out_file) else: utils.symlink_plus(in_file, out_file) return out_file def run_vardict(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Run VarDict variant calling. """ items = shared.add_highdepth_genome_exclusion(items) if vcfutils.is_paired_analysis(align_bams, items): call_file = _run_vardict_paired(align_bams, items, ref_file, assoc_files, region, out_file) else: vcfutils.check_paired_problems(items) call_file = _run_vardict_caller(align_bams, items, ref_file, assoc_files, region, out_file) return call_file def _get_jvm_opts(data, out_file): """Retrieve JVM options when running the Java version of VarDict. """ if get_vardict_command(data) == "vardict-java": resources = config_utils.get_resources("vardict", data["config"]) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx4g"]) jvm_opts += broad.get_default_jvm_opts(os.path.dirname(out_file)) return "export VAR_DICT_OPTS='%s' && " % " ".join(jvm_opts) else: return "" def _run_vardict_caller(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect SNPs and indels with VarDict. var2vcf_valid uses -A flag which reports all alleles and improves sensitivity: https://github.com/AstraZeneca-NGS/VarDict/issues/35#issuecomment-276738191 """ config = items[0]["config"] if out_file is None: out_file = "%s-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: vrs = bedutils.population_variant_regions(items) target = shared.subset_variant_regions( vrs, region, out_file, items=items, do_merge=False) num_bams = len(align_bams) sample_vcf_names = [] # for individual sample names, given batch calling may be required for bamfile, item in zip(align_bams, items): # prepare commands sample = dd.get_sample_name(item) vardict = get_vardict_command(items[0]) opts, var2vcf_opts = _vardict_options_from_config(items, config, out_file, target) vcfstreamsort = config_utils.get_program("vcfstreamsort", config) compress_cmd = "| bgzip -c" if tx_out_file.endswith("gz") else "" fix_ambig_ref = vcfutils.fix_ambiguous_cl() fix_ambig_alt = vcfutils.fix_ambiguous_cl(5) remove_dup = vcfutils.remove_dup_cl() py_cl = os.path.join(utils.get_bcbio_bin(), "py") jvm_opts = _get_jvm_opts(items[0], tx_out_file) setup = ("%s && unset JAVA_HOME &&" % utils.get_R_exports()) contig_cl = vcfutils.add_contig_to_header_cl(ref_file, tx_out_file) use_lowfreq_filter = config["algorithm"].get("use_lowfreq_filter") if use_lowfreq_filter is False: lowfreq_filter = " | " else: lowfreq_filter = " | " + _lowfreq_linear_filter(0, False) + " | " teststrandbias = config_utils.get_program("teststrandbias.R", config) var2vcf_valid = config_utils.get_program("var2vcf_valid.pl", config) fudge_vcf_version = "sed 's/^##fileformat=VCFv4.3/##fileformat=VCFv4.2/'" cmd = ("{setup}{jvm_opts}{vardict} -G {ref_file} " "-N {sample} -b {bamfile} {opts} " "| {teststrandbias} " "| {var2vcf_valid} -A -N {sample} -E {var2vcf_opts} " "| {contig_cl} | bcftools filter -i 'QUAL >= 0' {lowfreq_filter} " "{fix_ambig_ref} | {fix_ambig_alt} | {fudge_vcf_version} | {remove_dup} | {vcfstreamsort} {compress_cmd}") if num_bams > 1: temp_file_prefix = out_file.replace(".gz", "").replace(".vcf", "") + item["name"][1] tmp_out = temp_file_prefix + ".temp.vcf" tmp_out += ".gz" if out_file.endswith("gz") else "" sample_vcf_names.append(tmp_out) with file_transaction(item, tmp_out) as tx_tmp_file: if not _is_bed_file(target): vcfutils.write_empty_vcf(tx_tmp_file, config, samples=[sample]) else: cmd += " > {tx_tmp_file}" do.run(cmd.format(**locals()), "Genotyping with VarDict: Inference", {}) else: if not _is_bed_file(target): vcfutils.write_empty_vcf(tx_out_file, config, samples=[sample]) else: cmd += " > {tx_out_file}" do.run(cmd.format(**locals()), "Genotyping with VarDict: Inference", {}) if num_bams > 1: # N.B. merge_variant_files wants region in 1-based end-inclusive # coordinates. Thus use bamprep.region_to_gatk vcfutils.merge_variant_files(orig_files=sample_vcf_names, out_file=tx_out_file, ref_file=ref_file, config=config, region=bamprep.region_to_gatk(region)) return out_file def _lowfreq_linear_filter(tumor_index, is_paired): """Linear classifier for removing low frequency false positives. Uses a logistic classifier based on 0.5% tumor only variants from the smcounter2 paper: https://github.com/bcbio/bcbio_validations/tree/master/somatic-lowfreq The classifier uses strand bias (SBF) and read mismatches (NM) and applies only for low frequency (<2%) and low depth (<30) variants. """ if is_paired: sbf = "FORMAT/SBF[%s]" % tumor_index nm = "FORMAT/NM[%s]" % tumor_index else: sbf = "INFO/SBF" nm = "INFO/NM" cmd = ("""bcftools filter --soft-filter 'LowFreqBias' --mode '+' """ """-e 'FORMAT/AF[{tumor_index}:0] < 0.02 && FORMAT/VD[{tumor_index}] < 30 """ """&& {sbf} < 0.1 && {nm} >= 2.0'""") return cmd.format(**locals()) def add_db_germline_flag(line): """Adds a DB flag for Germline filters, allowing downstream compatibility with PureCN. """ if line.startswith("#CHROM"): headers = ['##INFO='] return "\n".join(headers) + "\n" + line elif line.startswith("#"): return line else: parts = line.split("\t") if parts[7].find("STATUS=Germline") >= 0: parts[7] += ";DB" return "\t".join(parts) def depth_freq_filter(line, tumor_index, aligner): """Command line to filter VarDict calls based on depth, frequency and quality. Looks at regions with low depth for allele frequency (AF * DP < 6, the equivalent of < 13bp for heterogygote calls, but generalized. Within these calls filters if a calls has: - Low mapping quality and multiple mismatches in a read (NM) For bwa only: MQ < 55.0 and NM > 1.0 or MQ < 60.0 and NM > 2.0 - Low depth (DP < 10) - Low QUAL (QUAL < 45) Also filters in low allele frequency regions with poor quality, if all of these are true: - Allele frequency < 0.2 - Quality < 55 - P-value (SSF) > 0.06 """ if line.startswith("#CHROM"): headers = [('##FILTER='), ('##FILTER=')] return "\n".join(headers) + "\n" + line elif line.startswith("#"): return line else: parts = line.split("\t") sample_ft = {a: v for (a, v) in zip(parts[8].split(":"), parts[9 + tumor_index].split(":"))} qual = utils.safe_to_float(parts[5]) dp = utils.safe_to_float(sample_ft.get("DP")) af = utils.safe_to_float(sample_ft.get("AF")) nm = utils.safe_to_float(sample_ft.get("NM")) mq = utils.safe_to_float(sample_ft.get("MQ")) ssfs = [x for x in parts[7].split(";") if x.startswith("SSF=")] pval = utils.safe_to_float(ssfs[0].split("=")[-1] if ssfs else None) fname = None if not chromhacks.is_sex(parts[0]) and dp is not None and af is not None: if dp * af < 6: if aligner == "bwa" and nm is not None and mq is not None: if (mq < 55.0 and nm > 1.0) or (mq < 60.0 and nm > 2.0): fname = "LowAlleleDepth" if dp < 10: fname = "LowAlleleDepth" if qual is not None and qual < 45: fname = "LowAlleleDepth" if af is not None and qual is not None and pval is not None: if af < 0.2 and qual < 45 and pval > 0.06: fname = "LowFreqQuality" if fname: if parts[6] in set([".", "PASS"]): parts[6] = fname else: parts[6] += ";%s" % fname line = "\t".join(parts) return line def _run_vardict_paired(align_bams, items, ref_file, assoc_files, region=None, out_file=None): """Detect variants with Vardict. This is used for paired tumor / normal samples. """ config = items[0]["config"] if out_file is None: out_file = "%s-paired-variants.vcf.gz" % os.path.splitext(align_bams[0])[0] if not utils.file_exists(out_file): with file_transaction(items[0], out_file) as tx_out_file: vrs = bedutils.population_variant_regions(items) target = shared.subset_variant_regions(vrs, region, out_file, items=items, do_merge=True) paired = vcfutils.get_paired_bams(align_bams, items) if not _is_bed_file(target): vcfutils.write_empty_vcf(tx_out_file, config, samples=[x for x in [paired.tumor_name, paired.normal_name] if x]) else: if not paired.normal_bam: ann_file = _run_vardict_caller(align_bams, items, ref_file, assoc_files, region, out_file) return ann_file vardict = get_vardict_command(items[0]) vcfstreamsort = config_utils.get_program("vcfstreamsort", config) compress_cmd = "| bgzip -c" if out_file.endswith("gz") else "" freq = float(utils.get_in(config, ("algorithm", "min_allele_fraction"), 10)) / 100.0 # merge bed file regions as amplicon VarDict is only supported in single sample mode opts, var2vcf_opts = _vardict_options_from_config(items, config, out_file, target) fix_ambig_ref = vcfutils.fix_ambiguous_cl() fix_ambig_alt = vcfutils.fix_ambiguous_cl(5) remove_dup = vcfutils.remove_dup_cl() if any("vardict_somatic_filter" in tz.get_in(("config", "algorithm", "tools_off"), data, []) for data in items): somatic_filter = "" freq_filter = "" else: var2vcf_opts += " -M " # this makes VarDict soft filter non-differential variants somatic_filter = ("| sed 's/\\\\.*Somatic\\\\/Somatic/' " "| sed 's/REJECT,Description=\".*\">/REJECT,Description=\"Not Somatic via VarDict\">/' " """| %s -c 'from bcbio.variation import freebayes; """ """freebayes.call_somatic("%s", "%s")' """ % (sys.executable, paired.tumor_name, paired.normal_name)) freq_filter = ("| bcftools filter -m '+' -s 'REJECT' -e 'STATUS !~ \".*Somatic\"' 2> /dev/null " "| %s -x 'bcbio.variation.vardict.add_db_germline_flag(x)' " "| %s " "| %s -x 'bcbio.variation.vardict.depth_freq_filter(x, %s, \"%s\")'" % (os.path.join(os.path.dirname(sys.executable), "py"), _lowfreq_linear_filter(0, True), os.path.join(os.path.dirname(sys.executable), "py"), 0, bam.aligner_from_header(paired.tumor_bam))) jvm_opts = _get_jvm_opts(items[0], tx_out_file) py_cl = os.path.join(utils.get_bcbio_bin(), "py") setup = ("%s && unset JAVA_HOME &&" % utils.get_R_exports()) contig_cl = vcfutils.add_contig_to_header_cl(ref_file, tx_out_file) fudge_vcf_version = "sed 's/^##fileformat=VCFv4.3/##fileformat=VCFv4.2/'" cmd = ("{setup}{jvm_opts}{vardict} -G {ref_file} " "-N {paired.tumor_name} -b \"{paired.tumor_bam}|{paired.normal_bam}\" {opts} " "| awk 'NF>=48' | testsomatic.R " "| var2vcf_paired.pl -P 0.9 -m 4.25 {var2vcf_opts} " "-N \"{paired.tumor_name}|{paired.normal_name}\" " "| {contig_cl} {freq_filter} " "| bcftools filter -i 'QUAL >= 0' " "{somatic_filter} | {fix_ambig_ref} | {fix_ambig_alt} | {remove_dup} | {vcfstreamsort} | " "{fudge_vcf_version} {compress_cmd} > {tx_out_file}") do.run(cmd.format(**locals()), "Genotyping with VarDict: Inference", {}) return out_file def get_vardict_command(data): """ convert variantcaller specification to proper vardict command, handling string or list specification """ vcaller = dd.get_variantcaller(data) if isinstance(vcaller, list): vardict = [x for x in vcaller if "vardict" in x] if not vardict: return None vardict = vardict[0] elif not vcaller: return None else: vardict = vcaller vardict = "vardict-java" if not vardict.endswith("-perl") else "vardict" return vardict bcbio-nextgen-1.2.9/bcbio/variation/varscan.py000066400000000000000000000337131415626112400213410ustar00rootroot00000000000000"""Provide variant calling with VarScan from TGI at Wash U. http://varscan.sourceforge.net/ """ import os import sys from bcbio import broad, utils from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio.pipeline import config_utils from bcbio.provenance import do from bcbio.variation import samtools, vcfutils from bcbio.variation.vcfutils import (combine_variant_files, write_empty_vcf, get_paired_bams, bgzip_and_index) import pysam def run_varscan(align_bams, items, ref_file, assoc_files, region=None, out_file=None): paired = get_paired_bams(align_bams, items) if paired and paired.normal_bam and paired.tumor_bam: call_file = samtools.shared_variantcall(_varscan_paired, "varscan", align_bams, ref_file, items, assoc_files, region, out_file) else: vcfutils.check_paired_problems(items) call_file = samtools.shared_variantcall(_varscan_work, "varscan", align_bams, ref_file, items, assoc_files, region, out_file) return call_file def _get_jvm_opts(config, tmp_dir): """Retrieve common options for running VarScan. Handles jvm_opts, setting user and country to English to avoid issues with different locales producing non-compliant VCF. """ resources = config_utils.get_resources("varscan", config) jvm_opts = resources.get("jvm_opts", ["-Xmx750m", "-Xmx2g"]) jvm_opts = config_utils.adjust_opts(jvm_opts, {"algorithm": {"memory_adjust": {"magnitude": 1.1, "direction": "decrease"}}}) jvm_opts += ["-Duser.language=en", "-Duser.country=US"] jvm_opts += broad.get_default_jvm_opts(tmp_dir) return " ".join(jvm_opts) def _varscan_options_from_config(config): """Retrieve additional options for VarScan from the configuration. """ opts = ["--min-coverage 5", "--p-value 0.98", "--strand-filter 1"] resources = config_utils.get_resources("varscan", config) if resources.get("options"): opts += [str(x) for x in resources["options"]] return opts def spv_freq_filter(line, tumor_index): """Filter VarScan calls based on the SPV value and frequency. Removes calls with SPV < 0.05 and a tumor FREQ > 0.35. False positives dominate these higher frequency, low SPV calls. They appear to be primarily non-somatic/germline variants not removed by other filters. """ if line.startswith("#CHROM"): headers = [('##FILTER= 0.35) ' 'and low p-value for somatic (SPV < 0.05)">')] return "\n".join(headers) + "\n" + line elif line.startswith("#"): return line else: parts = line.split("\t") sample_ft = {a: v for (a, v) in zip(parts[8].split(":"), parts[9 + tumor_index].split(":"))} freq = utils.safe_to_float(sample_ft.get("FREQ")) spvs = [x for x in parts[7].split(";") if x.startswith("SPV=")] spv = utils.safe_to_float(spvs[0].split("=")[-1] if spvs else None) fname = None if spv is not None and freq is not None: if spv < 0.05 and freq > 0.35: fname = "SpvFreq" if fname: if parts[6] in set([".", "PASS"]): parts[6] = fname else: parts[6] += ";%s" % fname line = "\t".join(parts) return line def _varscan_paired(align_bams, ref_file, items, target_regions, out_file): """Run a paired VarScan analysis, also known as "somatic". """ max_read_depth = "1000" config = items[0]["config"] paired = get_paired_bams(align_bams, items) if not paired.normal_bam: affected_batch = items[0]["metadata"]["batch"] message = ("Batch {} requires both tumor and normal BAM files for" " VarScan cancer calling").format(affected_batch) raise ValueError(message) if not utils.file_exists(out_file): assert out_file.endswith(".vcf.gz"), "Expect bgzipped output to VarScan" normal_mpileup_cl = samtools.prep_mpileup([paired.normal_bam], ref_file, config, max_read_depth, target_regions=target_regions, want_bcf=False) tumor_mpileup_cl = samtools.prep_mpileup([paired.tumor_bam], ref_file, config, max_read_depth, target_regions=target_regions, want_bcf=False) base, ext = utils.splitext_plus(out_file) indel_file = base + "-indel.vcf" snp_file = base + "-snp.vcf" with file_transaction(config, indel_file, snp_file) as (tx_indel, tx_snp): with tx_tmpdir(items[0]) as tmp_dir: jvm_opts = _get_jvm_opts(config, tmp_dir) opts = " ".join(_varscan_options_from_config(config)) remove_zerocoverage = r"{ ifne grep -v -P '\t0\t\t$' || true; }" export = utils.local_path_export() varscan_cmd = ("{export} varscan {jvm_opts} somatic " "<({normal_mpileup_cl} | {remove_zerocoverage}) " "<({tumor_mpileup_cl} | {remove_zerocoverage}) " "--output-snp {tx_snp} --output-indel {tx_indel} " "--output-vcf {opts} ") # add minimum AF min_af = float(utils.get_in(paired.tumor_config, ("algorithm", "min_allele_fraction"), 10)) / 100.0 varscan_cmd += "--min-var-freq {min_af} " do.run(varscan_cmd.format(**locals()), "Varscan", None, None) to_combine = [] for fname in [snp_file, indel_file]: if utils.file_exists(fname): fix_file = "%s-fix.vcf.gz" % (utils.splitext_plus(fname)[0]) with file_transaction(config, fix_file) as tx_fix_file: fix_ambig_ref = vcfutils.fix_ambiguous_cl() fix_ambig_alt = vcfutils.fix_ambiguous_cl(5) py_cl = os.path.join(os.path.dirname(sys.executable), "py") normal_name = paired.normal_name tumor_name = paired.tumor_name cmd = ("cat {fname} | " "{py_cl} -x 'bcbio.variation.varscan.fix_varscan_output(x," """ "{normal_name}", "{tumor_name}")' | """ "{fix_ambig_ref} | {fix_ambig_alt} | ifne vcfuniqalleles | " """{py_cl} -x 'bcbio.variation.vcfutils.add_contig_to_header(x, "{ref_file}")' | """ """bcftools filter -m + -s REJECT -e "SS != '.' && SS != '2'" 2> /dev/null | """ "bgzip -c > {tx_fix_file}") do.run(cmd.format(**locals()), "Varscan paired fix") to_combine.append(fix_file) if not to_combine: out_file = write_empty_vcf(out_file, config) else: out_file = combine_variant_files(to_combine, out_file, ref_file, config, region=target_regions) if os.path.getsize(out_file) == 0: write_empty_vcf(out_file) if out_file.endswith(".gz"): out_file = bgzip_and_index(out_file, config) def fix_varscan_output(line, normal_name="", tumor_name=""): """Fix a varscan VCF line. Fixes the ALT column and also fixes floating point values output as strings to by Floats: FREQ, SSC. This function was contributed by Sean Davis , with minor modifications by Luca Beltrame . """ line = line.strip() tofix = ("##INFO= 9: line = _normalize_freq(line, 9) if len(line) > 10: line = _normalize_freq(line, 10) # HACK: The position of the SS= changes, so we just search for it ss_vals = [item for item in line[7].split(";") if item.startswith("SS=")] if len(ss_vals) > 0: somatic_status = int(ss_vals[0].split("=")[1]) # Get the number else: somatic_status = None if somatic_status == 5: # "Unknown" states are broken in current versions of VarScan # so we just bail out here for now return # fix FREQ for any additional samples -- multi-sample VarScan calling if len(line) > 11: for i in range(11, len(line)): line = _normalize_freq(line, i) #FIXME: VarScan also produces invalid REF records (e.g. CAA/A) # This is not handled yet. if "+" in ALT or "-" in ALT: if "/" not in ALT: if ALT[0] == "+": R = REF A = REF + ALT[1:] elif ALT[0] == "-": R = REF + ALT[1:] A = REF else: Ins = [p[1:] for p in ALT.split("/") if p[0] == "+"] Del = [p[1:] for p in ALT.split("/") if p[0] == "-"] if len(Del): REF += sorted(Del, key=lambda x: len(x))[-1] A = ",".join([REF[::-1].replace(p[::-1], "", 1)[::-1] for p in Del] + [REF + p for p in Ins]) R = REF REF = R ALT = A else: ALT = ALT.replace('/', ',') line[3] = REF line[4] = ALT return "\t".join(line) def _create_sample_list(in_bams, vcf_file): """Pull sample names from input BAMs and create input sample list. """ out_file = "%s-sample_list.txt" % os.path.splitext(vcf_file)[0] with open(out_file, "w") as out_handle: for in_bam in in_bams: with pysam.Samfile(in_bam, "rb") as work_bam: for rg in work_bam.header.get("RG", []): out_handle.write("%s\n" % rg["SM"]) return out_file def _varscan_work(align_bams, ref_file, items, target_regions, out_file): """Perform SNP and indel genotyping with VarScan. """ config = items[0]["config"] orig_out_file = out_file out_file = orig_out_file.replace(".vcf.gz", ".vcf") max_read_depth = "1000" sample_list = _create_sample_list(align_bams, out_file) mpileup = samtools.prep_mpileup(align_bams, ref_file, config, max_read_depth, target_regions=target_regions, want_bcf=False) # VarScan fails to generate a header on files that start with # zerocoverage calls; strip these with grep, we're not going to # call on them remove_zerocoverage = r"{ ifne grep -v -P '\t0\t\t$' || true; }" # we use ifne from moreutils to ensure we process only on files with input, skipping otherwise # http://manpages.ubuntu.com/manpages/natty/man1/ifne.1.html with tx_tmpdir(items[0]) as tmp_dir: jvm_opts = _get_jvm_opts(config, tmp_dir) opts = " ".join(_varscan_options_from_config(config)) min_af = float(utils.get_in(config, ("algorithm", "min_allele_fraction"), 10)) / 100.0 fix_ambig_ref = vcfutils.fix_ambiguous_cl() fix_ambig_alt = vcfutils.fix_ambiguous_cl(5) py_cl = os.path.join(os.path.dirname(sys.executable), "py") export = utils.local_path_export() cmd = ("{export} {mpileup} | {remove_zerocoverage} | " "ifne varscan {jvm_opts} mpileup2cns {opts} " "--vcf-sample-list {sample_list} --min-var-freq {min_af} --output-vcf --variants | " """{py_cl} -x 'bcbio.variation.vcfutils.add_contig_to_header(x, "{ref_file}")' | """ "{py_cl} -x 'bcbio.variation.varscan.fix_varscan_output(x)' | " "{fix_ambig_ref} | {fix_ambig_alt} | ifne vcfuniqalleles > {out_file}") do.run(cmd.format(**locals()), "Varscan", None, [do.file_exists(out_file)]) os.remove(sample_list) # VarScan can create completely empty files in regions without # variants, so we create a correctly formatted empty file if os.path.getsize(out_file) == 0: write_empty_vcf(out_file) if orig_out_file.endswith(".gz"): vcfutils.bgzip_and_index(out_file, config) bcbio-nextgen-1.2.9/bcbio/variation/vcfanno.py000066400000000000000000000205711415626112400213340ustar00rootroot00000000000000"""Run and organization variant file annotations with vcfanno. """ import os import six import toolz as tz from bcbio import utils from bcbio.bam import ref from bcbio.log import logger from bcbio.distributed import objectstore from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.pipeline import config_utils import bcbio.pipeline.datadict as dd from bcbio.variation import naming, vcfutils def run(vcf, conf_fns, lua_fns, data, basepath=None, decomposed=False): """Annotate a VCF file using vcfanno (https://github.com/brentp/vcfanno) decomposed -- if set to true we'll convert allele based output into single values to match alleles and make compatible with vcf2db (https://github.com/quinlan-lab/vcf2db/issues/14) """ conf_fns.sort(key=lambda x: os.path.basename(x) if x else "") lua_fns.sort(key=lambda x: os.path.basename(x) if x else "") ext = "-annotated-%s" % utils.splitext_plus(os.path.basename(conf_fns[0]))[0] if vcf.find(ext) > 0: out_file = vcf else: out_file = "%s%s.vcf.gz" % (utils.splitext_plus(vcf)[0], ext) if not utils.file_exists(out_file): vcfanno = config_utils.get_program("vcfanno", data) with file_transaction(out_file) as tx_out_file: conffn = _combine_files(conf_fns, out_file, data, basepath is None) luafn = _combine_files(lua_fns, out_file, data, False) luaflag = "-lua {0}".format(luafn) if luafn and utils.file_exists(luafn) else "" basepathflag = "-base-path {0}".format(basepath) if basepath else "" cores = dd.get_num_cores(data) post_ann = "sed -e 's/Number=A/Number=1/g' |" if decomposed else "" cmd = ("{vcfanno} -p {cores} {luaflag} {basepathflag} {conffn} {vcf} " "| {post_ann} bgzip -c > {tx_out_file}") message = "Annotating {vcf} with vcfanno, using {conffn}".format(**locals()) do.run(cmd.format(**locals()), message) return vcfutils.bgzip_and_index(out_file, data["config"]) def _combine_files(orig_files, base_out_file, data, fill_paths=True): """Combine multiple input files, fixing file paths if needed. We fill in full paths from files in the data dictionary if we're not using basepath (old style GEMINI). """ orig_files = [x for x in orig_files if x and utils.file_exists(x)] if not orig_files: return None out_file = "%s-combine%s" % (utils.splitext_plus(base_out_file)[0], utils.splitext_plus(orig_files[0])[-1]) with open(out_file, "w") as out_handle: for orig_file in orig_files: with open(orig_file) as in_handle: for line in in_handle: if fill_paths and line.startswith("file"): line = _fill_file_path(line, data) out_handle.write(line) out_handle.write("\n\n") return out_file def _fill_file_path(line, data): """Fill in a full file path in the configuration file from data dictionary. """ def _find_file(xs, target): if isinstance(xs, dict): for v in xs.values(): f = _find_file(v, target) if f: return f elif isinstance(xs, (list, tuple)): for x in xs: f = _find_file(x, target) if f: return f elif isinstance(xs, six.string_types) and os.path.exists(xs) and xs.endswith("/%s" % target): return xs orig_file = line.split("=")[-1].replace('"', '').strip() full_file = _find_file(data, os.path.basename(orig_file)) if not full_file and os.path.exists(os.path.abspath(orig_file)): full_file = os.path.abspath(orig_file) assert full_file, "Did not find vcfanno input file %s" % (orig_file) return 'file="%s"\n' % full_file def find_annotations(data, retriever=None): """Find annotation configuration files for vcfanno, using pre-installed inputs. Creates absolute paths for user specified inputs and finds locally installed defaults. Default annotations: - gemini for variant pipelines - somatic for variant tumor pipelines - rnaedit for RNA-seq variant calling """ conf_files = dd.get_vcfanno(data) if not isinstance(conf_files, (list, tuple)): conf_files = [conf_files] for c in _default_conf_files(data, retriever): if c not in conf_files: conf_files.append(c) conf_checkers = {"gemini": annotate_gemini, "somatic": _annotate_somatic} out = [] annodir = os.path.normpath(os.path.join(os.path.dirname(dd.get_ref_file(data)), os.pardir, "config", "vcfanno")) if not retriever: annodir = os.path.abspath(annodir) for conf_file in conf_files: if objectstore.is_remote(conf_file) or (os.path.exists(conf_file) and os.path.isfile(conf_file)): conffn = conf_file elif not retriever: conffn = os.path.join(annodir, conf_file + ".conf") else: conffn = os.path.join(dd.get_genome_build(data), "config", "vcfanno", conf_file + ".conf") luafn = "%s.lua" % utils.splitext_plus(conffn)[0] if retriever: conffn, luafn = [(x if objectstore.is_remote(x) else None) for x in retriever.add_remotes([conffn, luafn], data["config"])] if not conffn: pass elif conf_file in conf_checkers and not conf_checkers[conf_file](data, retriever): logger.warn("Skipping vcfanno configuration: %s. Not all input files found." % conf_file) if dd.get_genome_build(data) == "hg38" and conf_file == "somatic": logger.warn("COSMIC needs to be installed manually for somatic annotation with hg38. " "See https://bcbio-nextgen.readthedocs.io/en/latest/contents/installation.html#customizing-data-installation " "for instructions.") elif not objectstore.file_exists_or_remote(conffn): build = dd.get_genome_build(data) CONF_NOT_FOUND = ( "The vcfanno configuration {conffn} was not found for {build}, skipping.") logger.warn(CONF_NOT_FOUND.format(**locals())) else: out.append(conffn) if luafn and objectstore.file_exists_or_remote(luafn): out.append(luafn) return out def _default_conf_files(data, retriever): conf_files = [] if dd.get_variantcaller(data) or dd.get_vrn_file(data): if annotate_gemini(data, retriever): conf_files.append("gemini") if _annotate_somatic(data, retriever): conf_files.append("somatic") if dd.get_analysis(data).lower().find("rna-seq") >= 0: conf_files.append("rnaedit") return conf_files def annotate_gemini(data, retriever=None): """Annotate with population calls if have data installed. """ r = dd.get_variation_resources(data) return all([r.get(k) and objectstore.file_exists_or_remote(r[k]) for k in ["exac", "gnomad_exome"]]) def _annotate_somatic(data, retriever=None): """Annotate somatic calls if we have cosmic data installed. """ if is_human(data): paired = vcfutils.get_paired([data]) if paired: r = dd.get_variation_resources(data) if r.get("cosmic") and objectstore.file_exists_or_remote(r["cosmic"]): return True return False def is_human(data, builds=None): """Check if human, optionally with build number, search by name or extra GL contigs. """ def has_build37_contigs(data): for contig in ref.file_contigs(dd.get_ref_file(data)): if contig.name.startswith("GL") or contig.name.find("_gl") >= 0: if contig.name in naming.GMAP["hg19"] or contig.name in naming.GMAP["GRCh37"]: return True return False if not builds and tz.get_in(["genome_resources", "aliases", "human"], data): return True if not builds or "37" in builds: target_builds = ["hg19", "GRCh37"] if any([dd.get_genome_build(data).startswith(b) for b in target_builds]): return True elif has_build37_contigs(data): return True if not builds or "38" in builds: target_builds = ["hg38"] if any([dd.get_genome_build(data).startswith(b) for b in target_builds]): return True return False bcbio-nextgen-1.2.9/bcbio/variation/vcfutils.py000066400000000000000000000773441415626112400215530ustar00rootroot00000000000000"""Utilities for manipulating variant files in standard VCF format. """ from collections import namedtuple, defaultdict import copy import os import pprint import shutil import subprocess import toolz as tz import six from six.moves import zip from bcbio import broad, utils from bcbio.bam import ref from bcbio.distributed.multi import run_multicore, zeromq_aware_logging from bcbio.distributed.split import parallel_split_combine from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils, tools from bcbio.pipeline import datadict as dd from bcbio.provenance import do from bcbio.log import logger # ## Tumor/normal paired cancer analyses PairedData = namedtuple("PairedData", ["tumor_bam", "tumor_name", "normal_bam", "normal_name", "normal_panel", "tumor_config", "tumor_data", "normal_data"]) def is_paired_analysis(align_bams, items): """Determine if BAMs are from a tumor/normal paired analysis. """ return get_paired_bams(align_bams, items) is not None def somatic_batches(items): """Group items into somatic calling batches (tumor-only or tumor/normal). Returns batches, where a data item may be in pairs, and somatic and non_somatic (which are the original list of items). """ non_somatic = [] somatic = [] data_by_batches = defaultdict(list) for data in items: if not get_paired_phenotype(data): non_somatic.append(data) else: somatic.append(data) batches = dd.get_batches(data) if batches: for batch in batches: data_by_batches[batch].append(data) return data_by_batches.values(), somatic, non_somatic def get_paired(items): return get_paired_bams([dd.get_align_bam(d) for d in items], items) def get_paired_bams(align_bams, items): """Split aligned bams into tumor / normal pairs if this is a paired analysis. Allows cases with only tumor BAMs to handle callers that can work without normal BAMs or with normal VCF panels. """ tumor_bam, tumor_name, tumor_data, normal_bam, normal_name, normal_panel, tumor_config, normal_data = (None,) * 8 for bamfile, item in zip(align_bams, items): phenotype = get_paired_phenotype(item) if phenotype == "normal": normal_bam = bamfile normal_name = dd.get_sample_name(item) normal_data = item elif phenotype == "tumor": tumor_bam = bamfile tumor_name = dd.get_sample_name(item) tumor_data = item tumor_config = item["config"] normal_panel = dd.get_background_variant(item) if tumor_bam or tumor_name: return PairedData(tumor_bam, tumor_name, normal_bam, normal_name, normal_panel, tumor_config, tumor_data, normal_data) def get_somatic_variantcallers(items): """Retrieve all variant callers for somatic calling, handling somatic/germline. """ out = [] for data in items: vcs = dd.get_variantcaller(data) if isinstance(vcs, dict) and "somatic" in vcs: vcs = vcs["somatic"] if not isinstance(vcs, (list, tuple)): vcs = [vcs] out += vcs return set(vcs) def check_paired_problems(items): """Check for incorrectly paired tumor/normal samples in a batch.""" # ensure we're in a paired batch if not get_paired(items): return num_tumor = len([x for x in items if dd.get_phenotype(x).lower() == "tumor"]) if num_tumor > 1: raise ValueError("Unsupported configuration: found multiple tumor samples in batch %s: %s" % (tz.get_in(["metadata", "batch"], items[0]), [dd.get_sample_name(data) for data in items])) elif num_tumor == 0 and any(dd.get_phenotype(data).lower() == "normal" for data in items): raise ValueError("Found normal sample without tumor in batch %s: %s" % (tz.get_in(["metadata", "batch"], items[0]), [dd.get_sample_name(data) for data in items])) else: vcs = get_somatic_variantcallers(items) if "mutect" in vcs or "mutect2" in vcs or "strelka2" in vcs: paired = get_paired(items) if not (paired.normal_data or paired.normal_panel): # give a warning for mutect2, error out for mutect and strelka if "mutect2" in vcs: logger.info("Using a PON or a normal sample is recommended!") else: raise ValueError("MuTect and Strelka2 somatic calling requires normal sample or panel: %s" % [dd.get_sample_name(data) for data in items]) def get_paired_phenotype(data): """Retrieve the phenotype for a paired tumor/normal analysis. """ allowed_names = set(["tumor", "normal"]) p = tz.get_in(["metadata", "phenotype"], data) return p if p in allowed_names else None # ## General utilities def fix_ambiguous_cl(column=4): """awk command to replace non-N ambiguous REF bases with N. Some callers include these if present in the reference genome but GATK does not like them. """ return r"""awk -F$'\t' -v OFS='\t' '{if ($0 !~ /^#/) gsub(/[KMRYSWBVHDXkmryswbvhdx]/, "N", $%s) } {print}'""" % column def remove_dup_cl(): """awk command line to remove duplicate alleles where the ref and alt are the same. """ return r""" awk -F$'\t' -v OFS='\t' '$1!~/^#/ && $4 == $5 {next} {print}'""" def get_indelcaller(d_or_c): """Retrieve string for indelcaller to use, or empty string if not specified. """ config = d_or_c if isinstance(d_or_c, dict) and "config" in d_or_c else d_or_c indelcaller = config["algorithm"].get("indelcaller", "") if not indelcaller: indelcaller = "" if isinstance(indelcaller, (list, tuple)): indelcaller = indelcaller[0] if (len(indelcaller) > 0) else "" return indelcaller def write_empty_vcf(out_file, config=None, samples=None): needs_bgzip = False if out_file.endswith(".vcf.gz"): needs_bgzip = True out_file = out_file.replace(".vcf.gz", ".vcf") with open(out_file, "w") as out_handle: format_samples = ("\tFORMAT\t" + "\t".join(samples)) if samples else "" out_handle.write("##fileformat=VCFv4.1\n" "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO%s\n" % (format_samples)) if needs_bgzip: return bgzip_and_index(out_file, config or {}) else: return out_file def to_standardonly(in_file, ref_file, data): """Subset a VCF input file to standard chromosomes (1-22,X,Y,MT). """ from bcbio.heterogeneity import chromhacks out_file = "%s-stdchrs.vcf.gz" % utils.splitext_plus(in_file)[0] if not utils.file_exists(out_file): stds = [] for c in ref.file_contigs(ref_file): if chromhacks.is_nonalt(c.name): stds.append(c.name) if stds: with file_transaction(data, out_file) as tx_out_file: stds = ",".join(stds) in_file = bgzip_and_index(in_file, data["config"]) cmd = "bcftools view -o {tx_out_file} -O z {in_file} {stds}" do.run(cmd.format(**locals()), "Subset to standard chromosomes") return bgzip_and_index(out_file, data["config"]) if utils.file_exists(out_file) else in_file def split_snps_indels(orig_file, ref_file, config): """Split a variant call file into SNPs and INDELs for processing. """ base, ext = utils.splitext_plus(orig_file) snp_file = "{base}-snp{ext}".format(base=base, ext=ext) indel_file = "{base}-indel{ext}".format(base=base, ext=ext) for out_file, select_arg in [(snp_file, "--types snps"), (indel_file, "--exclude-types snps")]: if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: bcftools = config_utils.get_program("bcftools", config) output_type = "z" if out_file.endswith(".gz") else "v" cmd = "{bcftools} view -O {output_type} {orig_file} {select_arg} > {tx_out_file}" do.run(cmd.format(**locals()), "Subset to SNPs and indels") if out_file.endswith(".gz"): bgzip_and_index(out_file, config) return snp_file, indel_file def get_normal_sample(in_file): """Retrieve normal sample if normal/turmor """ with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if line.startswith("##PEDIGREE"): parts = line.strip().split("Original=")[1][:-1] return parts def get_samples(in_file): """Retrieve samples present in a VCF file """ with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if line.startswith("#CHROM"): parts = line.strip().split("\t") return parts[9:] raise ValueError("Did not find sample header in VCF file %s" % in_file) def _get_exclude_samples(in_file, to_exclude): """Identify samples in the exclusion list which are actually in the VCF. """ include, exclude = [], [] to_exclude = set(to_exclude) for s in get_samples(in_file): if s in to_exclude: exclude.append(s) else: include.append(s) return include, exclude def exclude_samples(in_file, out_file, to_exclude, ref_file, config, filters=None): """Exclude specific samples from an input VCF file. """ include, exclude = _get_exclude_samples(in_file, to_exclude) # can use the input sample, all exclusions already gone if len(exclude) == 0: out_file = in_file elif not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: bcftools = config_utils.get_program("bcftools", config) output_type = "z" if out_file.endswith(".gz") else "v" include_str = ",".join(include) filter_str = "-f %s" % filters if filters is not None else "" # filters could be e.g. 'PASS,.' cmd = "{bcftools} view -O {output_type} -s {include_str} {filter_str} {in_file} > {tx_out_file}" do.run(cmd.format(**locals()), "Exclude samples: {}".format(to_exclude)) return out_file def select_sample(in_file, sample, out_file, config, filters=None): """Select a single sample from the supplied multisample VCF file. """ if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: if len(get_samples(in_file)) == 1: shutil.copy(in_file, tx_out_file) else: if in_file.endswith(".gz"): bgzip_and_index(in_file, config) bcftools = config_utils.get_program("bcftools", config) output_type = "z" if out_file.endswith(".gz") else "v" filter_str = "-f %s" % filters if filters is not None else "" # filters could be e.g. 'PASS,.' cmd = "{bcftools} view -O {output_type} {filter_str} {in_file} -s {sample} > {tx_out_file}" do.run(cmd.format(**locals()), "Select sample: %s" % sample) if out_file.endswith(".gz"): bgzip_and_index(out_file, config) return out_file def vcf_has_variants(in_file): if os.path.exists(in_file): with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if line.strip() and not line.startswith("#"): return True return False def vcf_has_nonfiltered_variants(in_file): if os.path.exists(in_file): with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if line.strip() and not line.startswith("#"): parts = line.split("\t") if parts[6] in set(["PASS", "."]): return True return False # ## Merging of variant files def merge_variant_files(orig_files, out_file, ref_file, config, region=None): """Combine multiple VCF files with different samples into a single output file. Uses bcftools merge on bgzipped input files, handling both tricky merge and concatenation of files. Does not correctly handle files with the same sample (use combine_variant_files instead). """ in_pipeline = False if isinstance(orig_files, dict): file_key = config["file_key"] in_pipeline = True orig_files = orig_files[file_key] if tz.get_in(["algorithm", "purecn_pon_build"], config): out_vcf, ext = os.path.splitext(out_file) out_file = _do_combine_variants(orig_files, out_vcf, ref_file, config, region) else: out_file = _do_merge(orig_files, out_file, config, region) if in_pipeline: return [{file_key: out_file, "region": region, "sam_ref": ref_file, "config": config}] else: return out_file def _do_merge(orig_files, out_file, config, region): """Do the actual work of merging with bcftools merge. """ if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: _check_samples_nodups(orig_files) prep_files = run_multicore(p_bgzip_and_index, [[x, config] for x in orig_files], config) input_vcf_file = "%s-files.txt" % utils.splitext_plus(out_file)[0] with open(input_vcf_file, "w") as out_handle: for fname in prep_files: out_handle.write(fname + "\n") bcftools = config_utils.get_program("bcftools", config) output_type = "z" if out_file.endswith(".gz") else "v" region_str = "-r {}".format(region) if region else "" cmd = "{bcftools} merge -O {output_type} {region_str} `cat {input_vcf_file}` > {tx_out_file}" do.run(cmd.format(**locals()), "Merge variants") if out_file.endswith(".gz"): bgzip_and_index(out_file, config) return out_file def _do_combine_variants(orig_files, out_vcf, ref_file, config, region, minimumN = 3): """combine variants with gatk3 using minimum N threshold for PureCN PON""" gatk3 = config_utils.get_program("gatk3", config) cmd = [gatk3, "-Xmx12g", "-T", "CombineVariants", "-R", ref_file, "-o", out_vcf, "--minimumN", minimumN] out_gz = out_vcf + ".gz" if not os.path.exists(out_gz): try: cmd_line = " ".join([str(x) for x in cmd]) + " -V " + " -V ".join(orig_files) do.run(cmd_line, "combine variants") except subprocess.CalledProcessError as msg: logger.info("PON merge failed") bgzip_and_index(out_vcf, config) logger.debug("Saved SNV PON to " + out_gz) return out_gz def _check_samples_nodups(fnames): """Ensure a set of input VCFs do not have duplicate samples. """ counts = defaultdict(int) for f in fnames: for s in get_samples(f): counts[s] += 1 duplicates = [s for s, c in counts.items() if c > 1] if duplicates: raise ValueError("Duplicate samples found in inputs %s: %s" % (duplicates, fnames)) def _sort_by_region(fnames, regions, ref_file, config): """Sort a set of regionally split files by region for ordered output. """ contig_order = {} for i, sq in enumerate(ref.file_contigs(ref_file, config)): contig_order[sq.name] = i sitems = [] assert len(regions) == len(fnames), (regions, fnames) added_fnames = set([]) for region, fname in zip(regions, fnames): if fname not in added_fnames: if isinstance(region, (list, tuple)): c, s, e = region elif isinstance(region, six.string_types) and region.find(":") >= 0: c, coords = region.split(":") s, e = [int(x) for x in coords.split("-")] else: c = region s, e = 0, 0 sitems.append(((contig_order[c], s, e), c, fname)) added_fnames.add(fname) sitems.sort() return [(x[1], x[2]) for x in sitems] def concat_variant_files(orig_files, out_file, regions, ref_file, config): """Concatenate multiple variant files from regions into a single output file. Uses GATK4's GatherVcfs, falling back to bcftools concat --naive if it fails. These both only combine samples and avoid parsing, allowing scaling to large file sizes. """ if not utils.file_exists(out_file): input_file_list = _get_file_list(orig_files, out_file, regions, ref_file, config) try: out_file = _run_concat_variant_files_gatk4(input_file_list, out_file, config) except subprocess.CalledProcessError as msg: if ("We require all VCFs to have complete VCF headers" in str(msg) or "Features added out of order" in str(msg) or "The reference allele cannot be missing" in str(msg)): out_file = _run_concat_variant_files_bcftools(input_file_list, out_file, config, naive=True) else: print("## Original contigs") pprint.pprint(zip(regions, orig_files)) print("## Ordered file list") with open(input_file_list) as in_handle: print(in_handle.read()) raise if out_file.endswith(".gz"): bgzip_and_index(out_file, config) return out_file def _run_concat_variant_files_gatk4(input_file_list, out_file, config): """Use GATK4 GatherVcfs for concatenation of scattered VCFs. """ if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: params = ["-T", "GatherVcfs", "-I", input_file_list, "-O", tx_out_file] # Use GATK4 for merging, tools_off: [gatk4] applies to variant calling config = utils.deepish_copy(config) if "gatk4" in dd.get_tools_off({"config": config}): config["algorithm"]["tools_off"].remove("gatk4") # Allow specification of verbosity in the unique style this tool uses resources = config_utils.get_resources("gatk", config) opts = [str(x) for x in resources.get("options", [])] if "--verbosity" in opts: params += ["--VERBOSITY:%s" % opts[opts.index("--verbosity") + 1]] broad_runner = broad.runner_from_config(config) broad_runner.run_gatk(params) return out_file def _get_file_list(orig_files, out_file, regions, ref_file, config): """Create file with region sorted list of non-empty VCFs for concatenating. """ sorted_files = _sort_by_region(orig_files, regions, ref_file, config) exist_files = [(c, x) for c, x in sorted_files if os.path.exists(x) and vcf_has_variants(x)] if len(exist_files) == 0: # no non-empty inputs, merge the empty ones exist_files = [x for c, x in sorted_files if os.path.exists(x)] elif len(exist_files) > 1: exist_files = _fix_gatk_header(exist_files, out_file, config) else: exist_files = [x for c, x in exist_files] ready_files = run_multicore(p_bgzip_and_index, [[x, config] for x in exist_files], config) input_file_list = "%s-files.list" % utils.splitext_plus(out_file)[0] with open(input_file_list, "w") as out_handle: for fname in ready_files: out_handle.write(fname + "\n") return input_file_list def _fix_gatk_header(exist_files, out_file, config): """Ensure consistent headers for VCF concatenation. Fixes problems for genomes that start with chrM by reheadering the first file. These files do haploid variant calling which lack the PID phasing key/value pair in FORMAT, so initial chrM samples cause errors during concatenation due to the lack of header merging. This fixes this by updating the first header. """ from bcbio.variation import ploidy c, base_file = exist_files[0] replace_file = base_file items = [{"config": config}] if ploidy.get_ploidy(items, region=(c, 1, 2)) == 1: for c, x in exist_files[1:]: if ploidy.get_ploidy(items, (c, 1, 2)) > 1: replace_file = x break base_fix_file = os.path.join(os.path.dirname(out_file), "%s-fixheader%s" % utils.splitext_plus(os.path.basename(base_file))) with file_transaction(config, base_fix_file) as tx_out_file: header_file = "%s-header.vcf" % utils.splitext_plus(tx_out_file)[0] do.run("zgrep ^# %s > %s" % (replace_file, header_file), "Prepare header file for merging") resources = config_utils.get_resources("picard", config) ropts = [] if "options" in resources: ropts += [str(x) for x in resources.get("options", [])] bcftools = config_utils.get_program("bcftools", config) cmd = f"{bcftools} reheader --header {header_file} --output {tx_out_file} {base_file}" message = f"Reheader {base_file} with header from {replace_file}." do.run(cmd, message) bgzip_and_index(base_fix_file, config) return [base_fix_file] + [x for (c, x) in exist_files[1:]] def concat_variant_files_bcftools(orig_files, out_file, config): if not utils.file_exists(out_file): exist_files = [x for x in orig_files if os.path.exists(x)] ready_files = run_multicore(p_bgzip_and_index, [[x, config] for x in exist_files], config) input_file_list = "%s-files.list" % utils.splitext_plus(out_file)[0] with open(input_file_list, "w") as out_handle: for fname in ready_files: out_handle.write(fname + "\n") return _run_concat_variant_files_bcftools(input_file_list, out_file, config) else: return bgzip_and_index(out_file, config) def _run_concat_variant_files_bcftools(in_list, out_file, config, naive=False): """Concatenate variant files using bcftools concat, potentially using the fast naive option. """ if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: bcftools = config_utils.get_program("bcftools", config) output_type = "z" if out_file.endswith(".gz") else "v" if naive: args = "--naive" else: args = "--allow-overlaps" cmd = "{bcftools} concat {args} -O {output_type} --file-list {in_list} -o {tx_out_file}" do.run(cmd.format(**locals()), "bcftools concat variants") if out_file.endswith(".gz"): bgzip_and_index(out_file, config) return out_file def combine_variant_files(orig_files, out_file, ref_file, config, quiet_out=True, region=None): """Combine VCF files from the same sample into a single output file. Handles cases where we split files into SNPs/Indels for processing then need to merge back into a final file. """ in_pipeline = False if isinstance(orig_files, dict): file_key = config["file_key"] in_pipeline = True orig_files = orig_files[file_key] if not utils.file_exists(out_file): with file_transaction(config, out_file) as tx_out_file: exist_files = [x for x in orig_files if os.path.exists(x)] ready_files = run_multicore(p_bgzip_and_index, [[x, config] for x in exist_files], config) dict_file = "%s.dict" % utils.splitext_plus(ref_file)[0] cores = dd.get_num_cores({"config": config}) memscale = {"magnitude": 0.9 * cores, "direction": "increase"} if cores > 1 else None cmd = ["picard"] + broad.get_picard_opts(config, memscale) + \ ["MergeVcfs", "D=%s" % dict_file, "O=%s" % tx_out_file] + \ ["I=%s" % f for f in ready_files] cmd = "%s && %s" % (utils.get_java_clprep(os.path.realpath(utils.which("picard"))), " ".join(cmd)) do.run(cmd, "Combine variant files") if out_file.endswith(".gz"): bgzip_and_index(out_file, config) if in_pipeline: return [{file_key: out_file, "region": region, "sam_ref": ref_file, "config": config}] else: return out_file def sort_by_ref(vcf_file, data): """Sort a VCF file by genome reference and position, adding contig information. """ out_file = "%s-prep.vcf.gz" % utils.splitext_plus(vcf_file)[0] if not utils.file_uptodate(out_file, vcf_file): with file_transaction(data, out_file) as tx_out_file: header_file = "%s-header.txt" % utils.splitext_plus(tx_out_file)[0] with open(header_file, "w") as out_handle: for region in ref.file_contigs(dd.get_ref_file(data), data["config"]): out_handle.write("##contig=\n" % (region.name, region.size)) cat_cmd = "zcat" if vcf_file.endswith("vcf.gz") else "cat" cmd = ("{cat_cmd} {vcf_file} | grep -v ^##contig | bcftools annotate -h {header_file} | " "vt sort -m full -o {tx_out_file} -") with utils.chdir(os.path.dirname(tx_out_file)): do.run(cmd.format(**locals()), "Sort VCF by reference") return bgzip_and_index(out_file, data["config"]) def add_contig_to_header_cl(ref_file, out_file): """Add update ##contig lines to VCF header, required for bcftools/GATK compatibility. """ header_file = "%s-contig_header.txt" % utils.splitext_plus(out_file)[0] with open(header_file, "w") as out_handle: for region in ref.file_contigs(ref_file, {}): out_handle.write("##contig=\n" % (region.name, region.size)) return ("grep -v ^##contig | bcftools annotate -h %s" % header_file) def add_contig_to_header(line, ref_file): """Streaming target to add contigs to a VCF file header. """ if line.startswith("##fileformat=VCF"): out = [line] for region in ref.file_contigs(ref_file): out.append("##contig=" % (region.name, region.size)) return "\n".join(out) else: return line # ## Parallel VCF file combining def parallel_combine_variants(orig_files, out_file, ref_file, config, run_parallel): """Combine variants in parallel by chromosome, concatenating final outputs. """ file_key = "vcf_files" def split_by_region(data): base, ext = utils.splitext_plus(os.path.basename(out_file)) args = [] for region in [x.name for x in ref.file_contigs(ref_file, config)]: region_out = os.path.join(os.path.dirname(out_file), "%s-regions" % base, "%s-%s%s" % (base, region, ext)) utils.safe_makedir(os.path.dirname(region_out)) args.append((region_out, ref_file, config, region)) return out_file, args config = copy.deepcopy(config) config["file_key"] = file_key prep_files = run_multicore(p_bgzip_and_index, [[x, config] for x in orig_files], config) items = [[{file_key: prep_files}]] parallel_split_combine(items, split_by_region, run_parallel, "merge_variant_files", "concat_variant_files", file_key, ["region", "sam_ref", "config"], split_outfile_i=0) return out_file # ## VCF preparation def move_vcf(orig_file, new_file): """Move a VCF file with associated index. """ for ext in ["", ".idx", ".tbi"]: to_move = orig_file + ext if os.path.exists(to_move): shutil.move(to_move, new_file + ext) def bgzip_and_index(in_file, config=None, remove_orig=True, prep_cmd="", tabix_args=None, out_dir=None): """bgzip and tabix index an input file, handling VCF and BED. """ if config is None: config = {} out_file = in_file if in_file.endswith(".gz") else in_file + ".gz" if out_dir: remove_orig = False out_file = os.path.join(out_dir, os.path.basename(out_file)) if (not utils.file_exists(out_file) or not os.path.lexists(out_file) or (utils.file_exists(in_file) and not utils.file_uptodate(out_file, in_file))): assert not in_file == out_file, "Input file is bgzipped but not found: %s" % in_file assert os.path.exists(in_file), "Input file %s not found" % in_file if not utils.file_uptodate(out_file, in_file): with file_transaction(config, out_file) as tx_out_file: bgzip = tools.get_bgzip_cmd(config) cat_cmd = "zcat" if in_file.endswith(".gz") else "cat" if prep_cmd: prep_cmd = "| %s " % prep_cmd cmd = "{cat_cmd} {in_file} {prep_cmd} | {bgzip} -c > {tx_out_file}" try: do.run(cmd.format(**locals()), "bgzip %s" % os.path.basename(in_file)) except subprocess.CalledProcessError: # Race conditions: ignore errors where file has been deleted by another if os.path.exists(in_file) and not os.path.exists(out_file): raise if remove_orig: try: os.remove(in_file) except OSError: # Handle cases where run in parallel and file has been deleted pass tabix_index(out_file, config, tabix_args=tabix_args) return out_file @utils.map_wrap @zeromq_aware_logging def p_bgzip_and_index(in_file, config): """Parallel-aware bgzip and indexing """ return [bgzip_and_index(in_file, config)] def _guess_preset(f): if f.lower().endswith(".vcf.gz"): return "vcf" elif f.lower().endswith(".bed.gz"): return "bed" elif f.lower().endswith(".gff.gz"): return "gff" else: raise ValueError("Unexpected tabix input: %s" % f) def tabix_index(in_file, config, preset=None, tabix_args=None): """Index a file using tabix. """ in_file = os.path.abspath(in_file) out_file = in_file + ".tbi" if not utils.file_exists(out_file) or not utils.file_uptodate(out_file, in_file): # Remove old index files to prevent linking into tx directory utils.remove_safe(out_file) with file_transaction(config, out_file) as tx_out_file: tabix = tools.get_tabix_cmd(config) tx_in_file = os.path.splitext(tx_out_file)[0] utils.symlink_plus(in_file, tx_in_file) if tabix_args: cmd = "{tabix} -f {tabix_args} {tx_in_file}" else: preset = _guess_preset(in_file) if preset is None else preset cmd = "{tabix} -f -p {preset} {tx_in_file}" do.run(cmd.format(**locals()), "tabix index %s" % os.path.basename(in_file)) return out_file def is_gvcf_file(in_file): """Check if an input file is raw gVCF """ to_check = 100 n = 0 with utils.open_gzipsafe(in_file) as in_handle: for line in in_handle: if not line.startswith("##"): if n > to_check: break n += 1 parts = line.split("\t") # GATK if parts[4] == "": return True # strelka2 if parts[4] == "." and parts[7].startswith("BLOCKAVG"): return True # freebayes if parts[4] == "<*>": return True # platypue if parts[4] == "N" and parts[6] == "REFCALL": return True def cyvcf_add_filter(rec, name): """Add a FILTER value to a cyvcf2 record """ if rec.FILTER: filters = rec.FILTER.split(";") else: filters = [] if name not in filters: filters.append(name) rec.FILTER = filters return rec def cyvcf_remove_filter(rec, name): """Remove filter with the given name from a cyvcf2 record """ if rec.FILTER: filters = rec.FILTER.split(";") else: filters = [] new_filters = [x for x in filters if not str(x) == name] if len(new_filters) == 0: new_filters = ["PASS"] rec.FILTER = new_filters return rec bcbio-nextgen-1.2.9/bcbio/variation/vfilter.py000066400000000000000000000251571415626112400213620ustar00rootroot00000000000000"""Cutoff-based soft filtering of genomic variants. """ from distutils.version import LooseVersion import math import os import shutil import numpy import toolz as tz import yaml from bcbio import broad, utils from bcbio.distributed.transaction import file_transaction from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.provenance import do, programs from bcbio.variation import vcfutils # ## General functionality def cutoff_w_expression(vcf_file, expression, data, name="+", filterext="", extra_cmd="", limit_regions="variant_regions"): """Perform cutoff-based soft filtering using bcftools expressions like %QUAL < 20 || DP < 4. """ base, ext = utils.splitext_plus(vcf_file) out_file = "{base}-filter{filterext}{ext}".format(**locals()) if not utils.file_exists(out_file): with file_transaction(data, out_file) as tx_out_file: if vcfutils.vcf_has_variants(vcf_file): bcftools = config_utils.get_program("bcftools", data["config"]) bgzip_cmd = "| bgzip -c" if out_file.endswith(".gz") else "" intervals = "" if limit_regions == "variant_regions": variant_regions = dd.get_variant_regions(data) if variant_regions: intervals = "-T %s" % vcfutils.bgzip_and_index(variant_regions, data["config"]) cmd = ("{bcftools} filter -O v {intervals} --soft-filter '{name}' " "-e '{expression}' -m '+' {vcf_file} {extra_cmd} {bgzip_cmd} > {tx_out_file}") do.run(cmd.format(**locals()), "Cutoff-based soft filtering %s with %s" % (vcf_file, expression), data) else: shutil.copy(vcf_file, out_file) if out_file.endswith(".vcf.gz"): out_file = vcfutils.bgzip_and_index(out_file, data["config"]) return out_file # ## Caller specific def freebayes(in_file, ref_file, vrn_files, data): """FreeBayes filters: cutoff-based soft filtering. """ out_file = _freebayes_cutoff(in_file, data) #out_file = _freebayes_custom(in_file, ref_file, data) return out_file def _freebayes_custom(in_file, ref_file, data): """Custom FreeBayes filtering using bcbio.variation, tuned to human NA12878 results. Experimental: for testing new methods. """ if vcfutils.get_paired_phenotype(data): return None config = data["config"] bv_ver = programs.get_version("bcbio_variation", config=config) if LooseVersion(bv_ver) < LooseVersion("0.1.1"): return None out_file = "%s-filter%s" % os.path.splitext(in_file) if not utils.file_exists(out_file): tmp_dir = utils.safe_makedir(os.path.join(os.path.dirname(in_file), "tmp")) resources = config_utils.get_resources("bcbio_variation", config) jvm_opts = resources.get("jvm_opts", ["-Xms750m", "-Xmx2g"]) java_args = ["-Djava.io.tmpdir=%s" % tmp_dir] cmd = ["bcbio-variation"] + jvm_opts + java_args + \ ["variant-filter", "freebayes", in_file, ref_file] do.run(cmd, "Custom FreeBayes filtering using bcbio.variation") return out_file def _freebayes_cutoff(in_file, data): """Perform filtering of FreeBayes results, flagging low confidence calls. Filters using cutoffs on low depth based on Meynert et al's work modeling sensitivity of homozygote and heterozygote calling on depth: http://www.ncbi.nlm.nih.gov/pubmed/23773188 and high depth heterozygote SNP filtering based on Heng Li's work evaluating variant calling artifacts: http://arxiv.org/abs/1404.0929 Tuned based on NA12878 call comparisons to Genome in a Bottle reference genome. """ if not vcfutils.vcf_has_variants(in_file): base, ext = utils.splitext_plus(in_file) out_file = "{base}-filter{ext}".format(**locals()) if not utils.file_exists(out_file): shutil.copy(in_file, out_file) if out_file.endswith(".vcf.gz"): out_file = vcfutils.bgzip_and_index(out_file, data["config"]) return out_file depth_thresh, qual_thresh = None, None if _do_high_depth_filter(data): stats = _calc_vcf_stats(in_file) if stats["avg_depth"] > 0: depth_thresh = int(math.ceil(stats["avg_depth"] + 3 * math.pow(stats["avg_depth"], 0.5))) qual_thresh = depth_thresh * 2.0 # Multiplier from default GATK QD cutoff filter filters = ('(AF[0] <= 0.5 && (max(FORMAT/DP) < 4 || (max(FORMAT/DP) < 13 && %QUAL < 10))) || ' '(AF[0] > 0.5 && (max(FORMAT/DP) < 4 && %QUAL < 50))') if depth_thresh: filters += ' || (%QUAL < {qual_thresh} && max(FORMAT/DP) > {depth_thresh} && AF[0] <= 0.5)'.format(**locals()) return cutoff_w_expression(in_file, filters, data, name="FBQualDepth") def _do_high_depth_filter(data): """Check if we should do high depth filtering -- only on germline non-regional calls. """ is_genome = tz.get_in(["config", "algorithm", "coverage_interval"], data, "").lower() == "genome" is_paired = vcfutils.get_paired_phenotype(data) return is_genome and not is_paired def _calc_vcf_stats(in_file): """Calculate statistics on VCF for filtering, saving to a file for quick re-runs. """ out_file = "%s-stats.yaml" % utils.splitext_plus(in_file)[0] if not utils.file_exists(out_file): stats = {"avg_depth": _average_called_depth(in_file)} with open(out_file, "w") as out_handle: yaml.safe_dump(stats, out_handle, default_flow_style=False, allow_unicode=False) return stats else: with open(out_file) as in_handle: stats = yaml.safe_load(in_handle) return stats def _average_called_depth(in_file): """Retrieve the average depth of called reads in the provided VCF. """ import cyvcf2 depths = [] for rec in cyvcf2.VCF(str(in_file)): d = rec.INFO.get("DP") if d is not None: depths.append(int(d)) if len(depths) > 0: return int(math.ceil(numpy.mean(depths))) else: return 0 def platypus(in_file, data): """Filter Platypus calls, removing Q20 filter and replacing with depth and quality based filter. Platypus uses its own VCF nomenclature: TC == DP, FR == AF Platypus gVCF output appears to have an 0/1 index problem so the reference block regions are 1 base outside regions of interest. We avoid limiting regions during filtering when using it. """ filters = ('(FR[0] <= 0.5 && TC < 4 && %QUAL < 20) || ' '(TC < 13 && %QUAL < 10) || ' '(FR[0] > 0.5 && TC < 4 && %QUAL < 50)') limit_regions = "variant_regions" if not vcfutils.is_gvcf_file(in_file) else None return cutoff_w_expression(in_file, filters, data, name="PlatQualDepth", extra_cmd="| sed 's/\\tQ20\\t/\\tPASS\\t/'", limit_regions=limit_regions) def samtools(in_file, data): """Filter samtools calls based on depth and quality, using similar approaches to FreeBayes. """ filters = ('((AC[0] / AN) <= 0.5 && max(FORMAT/DP) < 4 && %QUAL < 20) || ' '(max(FORMAT/DP) < 13 && %QUAL < 10) || ' '((AC[0] / AN) > 0.5 && max(format/DP) < 4 && %QUAL < 50)') return cutoff_w_expression(in_file, filters, data, name="stQualDepth") def _gatk_general(): """General filters useful for both GATK SNPs and indels. Remove low quality, low allele fraction variants at the ends of reads. Generally useful metric identified by looking at 10x data. https://community.10xgenomics.com/t5/Genome-Exome-Forum/Best-practices-for-trimming-adapters-when-variant-calling/m-p/473 https://github.com/bcbio/bcbio_validations/tree/master/gatk4#10x-adapter-trimming--low-frequency-allele-filter see https://github.com/bcbio/bcbio-nextgen/issues/3508 """ return ['(GT[0]="het" && QD < 10.0 && AD[0:1] / (AD[0:1] + AD[0:0]) < 0.25 && ReadPosRankSum < 0.0)'] def gatk_snp_cutoff(in_file, data): """Perform cutoff-based soft filtering on GATK SNPs using best-practice recommendations. We have a more lenient mapping quality (MQ) filter compared to GATK defaults. The recommended filter (MQ < 40) is too stringent, so we adjust to 30: http://imgur.com/a/oHRVB QD and FS are not calculated when generating gVCF output: https://github.com/broadgsa/gatk-protected/blob/e91472ddc7d58ace52db0cab4d70a072a918d64c/protected/gatk-tools-protected/src/main/java/org/broadinstitute/gatk/tools/walkers/haplotypecaller/HaplotypeCaller.java#L300 The extra command removes escaped quotes in the VCF output which pyVCF fails on. Does not use the GATK best practice recommend SOR filter (SOR > 3.0) as it has a negative impact on sensitivity relative to precision: https://github.com/bcbio/bcbio_validations/tree/master/gatk4#na12878-hg38 """ filters = ["MQRankSum < -12.5", "ReadPosRankSum < -8.0"] # GATK Haplotype caller (v2.2) appears to have much larger HaplotypeScores # resulting in excessive filtering, so avoid this metric variantcaller = utils.get_in(data, ("config", "algorithm", "variantcaller")) if variantcaller not in ["gatk-haplotype", "haplotyper"]: filters.append("HaplotypeScore > 13.0") # Additional filter metrics, unless using raw GATK HaplotypeCaller or Sentieon gVCFs if not (vcfutils.is_gvcf_file(in_file) and variantcaller in ["gatk-haplotype", "haplotyper"]): filters += ["QD < 2.0"] filters += ["FS > 60.0"] if "gatk_ad_filter" not in tz.get_in(["config", "algorithm", "tools_off"], data, []): filters += _gatk_general() filters += ["MQ < 30.0"] return cutoff_w_expression(in_file, 'TYPE="snp" && (%s)' % " || ".join(filters), data, "GATKCutoffSNP", "SNP", extra_cmd=r"""| sed 's/\\"//g'""") def gatk_indel_cutoff(in_file, data): """Perform cutoff-based soft filtering on GATK indels using best-practice recommendations. """ filters = ["ReadPosRankSum < -20.0"] variantcaller = utils.get_in(data, ("config", "algorithm", "variantcaller")) # Additional filter metrics, unless using raw GATK HaplotypeCaller or Sentieon gVCFs if not (vcfutils.is_gvcf_file(in_file) and variantcaller in ["gatk-haplotype", "haplotyper"]): filters += ["QD < 2.0"] filters += ["FS > 200.0"] filters += ["SOR > 10.0"] if "gatk_ad_filter" not in tz.get_in(["config", "algorithm", "tools_off"], data, []): filters += _gatk_general() return cutoff_w_expression(in_file, 'TYPE="indel" && (%s)' % " || ".join(filters), data, "GATKCutoffIndel", "INDEL", extra_cmd=r"""| sed 's/\\"//g'""") bcbio-nextgen-1.2.9/bcbio/wgbsseq/000077500000000000000000000000001415626112400170025ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/wgbsseq/__init__.py000066400000000000000000000000001415626112400211010ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/wgbsseq/align.py000066400000000000000000000064621415626112400204560ustar00rootroot00000000000000import os import shutil import os.path as op import pysam # from collections import Counter from bcbio.utils import splitext_plus, file_exists, safe_makedir, chdir from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio import broad from bcbio.bam import index from bcbio.pipeline import datadict as dd from bcbio.pipeline import config_utils from ichwrapper import log def _set_quality(in_bam): """ change all quality to 255 """ bam = pysam.AlignmentFile(in_bam, "rb") out_file = op.splitext(in_bam)[0] + "_normqual.bam" if file_exists(out_file): return out_file with pysam.AlignmentFile(out_file, "wb", template=bam) as out_handle: for read in bam.fetch(): read.mapping_quality = 255 out_handle.write(read) return out_file def _align(in_fastq, sample, workdir, genome_index, is_directional, bowtie2, reference, config): """ align with bismark. this is actually not used. the align is in ngsalign.bismark.align """ bismark = do.find_cmd("bismark") resources = config_utils.get_resources("bismark") num_cores = 1 if resources and resources.get("bismark_threads"): num_cores = resources.get("bismark_threads") else: num_cores = max(int(config['algorithm'].get('cores', 1) / 2), 1) bowtie_threads = 1 if resources and resources.get("bowtie_threads"): bowtie_threads = resources.get("bowtie_threads") basename = sample if is_directional: is_directional = "" else: is_directional = "--non_directional" cmd = "{bismark} -n 1 -o {tx_dir} --basename {sample} --unmapped {is_directional} {genome_index} {in_fastq}" if bowtie2: cmd = "{bismark} --bowtie2 --parallel {num_cores} -p {bowtie_threads} -o {tx_dir} --basename {sample} --unmapped {is_directional} {genome_index} {in_fastq}" out_dir = op.join(workdir, sample) out_bam = op.join(out_dir, sample + ".bam") with chdir(workdir): if not file_exists(out_bam): with tx_tmpdir() as tx_dir: cmd = cmd.format(**locals()) log.logger.debug(cmd) do.run(cmd, "bismark in %s" % in_fastq) shutil.move(tx_dir, out_dir) broad_runner = broad.runner_from_config(config) # out_bam, _ = broad_runner.run_fn("picard_formatconverter", out_sam) names = {'rg': in_fastq, 'library': 'BS_LIB', 'pl': 'Illumina', 'pu': 'R1', 'sm': in_fastq, 'sample': sample} out_fix_bam = broad_runner.run_fn("picard_fix_rgs", out_bam, names) order_bam = splitext_plus(out_fix_bam)[0] + "_order.bam" broad_runner.run_fn("picard_reorder", out_fix_bam, reference, order_bam) index(order_bam, config) if bowtie2: order_bam = _set_quality(order_bam) index(order_bam, config) return order_bam def create_bam(data, args): """ aligner and conversion to BAM file """ workdir = safe_makedir("align") sample = data['name'] # workdir = op.join("align", sample) data['final_bam'] = _align(data['trimmed'], sample, op.abspath(workdir), args.index, args.is_directional, args.bowtie2, args.reference, data['config']) data['order_bam'] = data['final_bam'] return data bcbio-nextgen-1.2.9/bcbio/wgbsseq/cpg_caller.py000066400000000000000000000277551415626112400214670ustar00rootroot00000000000000""" Some reports for the analysis """ import shutil import os import sys import copy from contextlib import closing from collections import Counter import pandas as pd import math import pysam import scipy.stats as stats from bcbio.utils import splitext_plus, file_exists, safe_makedir, chdir, append_stem from bcbio.log import logger from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction, tx_tmpdir from bcbio import bam from bcbio.pipeline import config_utils from bcbio.pipeline import datadict as dd from bcbio.pipeline.alignment import get_aligner_index def _run_meth_extractor(bam_in, sample, workdir, index_dir, config): """Run bismark_methylation_extractor command""" bismark = config_utils.get_program("bismark_methylation_extractor", config) cores = config["algorithm"].get('cores', 1) memory = config["algorithm"].get('mem', 5) # don't sort even by read name! # bam_in = bam.sort(bam_in, config, order="queryname") cmd = "{bismark} --no_overlap --comprehensive --cytosine_report --genome_folder {index_dir} --merge_non_CpG --multicore {cores} --buffer_size {memory}G --bedGraph --gzip {bam_in}" out_dir = os.path.join(workdir, sample) mbias_file = os.path.join(out_dir, os.path.basename(splitext_plus(bam_in)[0]) + '.M-bias.txt') if not file_exists(mbias_file): with tx_tmpdir() as tx_dir: with chdir(tx_dir): do.run(cmd.format(**locals()), "bismark_methylation_extractor in %s" % bam_in) shutil.move(tx_dir, out_dir) assert os.path.exists(mbias_file), "mbias report doesn't exists:%s" % mbias_file return mbias_file def _run_report(bam_in, bam_report, sample, biasm_file, workdir, config): """ Run bismark2report command """ bismark = config_utils.get_program("bismark2report", config) cmd = "{bismark} --alignment_report {bam_report} -o {tx_out} --mbias_report {biasm_file}" out_dir = os.path.join(workdir, sample) out_file = os.path.join(out_dir, sample + '.html') with chdir(out_dir): if not file_exists(out_file): with file_transaction(out_file) as tx_out: do.run(cmd.format(**locals()), "bismarkr2report in %s" % bam_in) return out_dir def _bismark_calling(data): workdir = safe_makedir(os.path.join(dd.get_work_dir(data), "cpg")) config = data["config"] sample = dd.get_sample_name(data) index_dir = get_aligner_index('bismark', data) biasm_file = _run_meth_extractor(data["work_bam"], sample, workdir, index_dir, config) data['bismark_report'] = _run_report(data["work_bam"], data["bam_report"], sample, biasm_file, workdir, config) splitting_report = biasm_file.replace(".M-bias", "_splitting_report") data = dd.update_summary_qc(data, "bismark", base=biasm_file) data = dd.update_summary_qc(data, "bismark", base=data["bam_report"]) data = dd.update_summary_qc(data, "bismark", base=splitting_report) return data def _bsmap_calling(data): sample = dd.get_sample_name(data) workdir = safe_makedir(os.path.join(dd.get_work_dir(data), "cpg_split", sample)) config = data["config"] ref = dd.get_sam_ref(data) work_bam = dd.get_work_bam(data) python = os.path.join(os.path.dirname(sys.executable), "python") methratio = config_utils.get_program("methratio.py", config) cmd = ("{python} {methratio} -g -n -u -p -r -m 5 --chr={chrom} --ref={ref} {work_bam} >> {out_tx}") chrom = data["chr_to_run"] out_file = os.path.join(workdir, "methyratios_%s.txt" % chrom) if not file_exists(out_file): with file_transaction(out_file) as out_tx: do.run(cmd.format(**locals()), "Extract methylation for: %s" % sample) data["cpg_file"] = out_file return data def calling(data): if dd.get_aligner(data) == "bismark": data = _bismark_calling(data) if dd.get_aligner(data) == "bsmap": data = _bsmap_calling(data) return [[data]] # All these functions were very specific to a consult. Probably remove is # the best option since they are not run for the general pipeline. def parallel_calling(data, run_parallel): """This is needed only if running methylated veruss hidroxy-methulated""" out = [] for sample in data: work_bam = dd.get_work_bam(sample[0]) with closing(pysam.Samfile(work_bam, "rb")) as pysam_work_bam: chroms = pysam_work_bam.references for chrom in chroms: new_sample = copy.deepcopy(sample) if chrom.find("_") > -1: continue new_sample[0]['chr_to_run'] = chrom out.append(new_sample) out = run_parallel("cpg_calling", out) for sample in out: phenotype = dd.get_phenotype(sample[0]) batch = dd.get_batch(sample[0]) if phenotype == "mC": for sample2 in out: if batch in dd.get_batch(sample2[0]) and dd.get_phenotype(sample2[0]) == "hmC": if sample[0]["chr_to_run"] == sample2[0]["chr_to_run"]: sample[0]["control"] = sample2[0]["cpg_file"] break out = run_parallel("cpg_processing", out) for sample in data: sample[0]["cpg_split"] = [] sample[0]["hmc_split"] = [] name = dd.get_sample_name(sample[0]) for chunck in out: if name == dd.get_sample_name(chunck[0]): sample[0]["cpg_split"].append(chunck[0]["cpg_file"]) if "hmc_file" in chunck[0]: sample[0]["hmc_split"].append(chunck[0]["hmc_file"]) # run_parallel("cpg_stats", data) def _sync_pos(handle, tag): for line in handle: cols = line.strip().split("\t") info = cols[4:] if cols[3] != "CG": continue pos = int(cols[1]) ratio = [int(float(cols[5])), int(cols[6])] if tag <= pos: return [handle, {"pos": pos, "counts": ratio, "info": info, "ratio": float(cols[4])}] return [None, None] def _call_hmc(mc, hmc): n1, n2 = mc[0] - mc[1], mc[1] n1 = max(0, n1) m1, m2 = hmc[0] - hmc[1], hmc[1] m1 = max(0, m1) oddsratio, pvalue = stats.fisher_exact([[n1, n2], [m1, m2]]) return pvalue def cpg_postprocessing(data): mC = data["cpg_file"] if not "control" in data: return [[data]] hmC = data["control"] out_file = append_stem(mC, "_hmC") pos = 0 pos_hmC = 0 data["hmc_file"] = out_file if file_exists(out_file): return [[data]] logger.debug("processing %s versus %s" % (mC, hmC)) with file_transaction(out_file) as out_tx: with open(out_tx, "w") as out_handle: with open(mC) as mC_h: with open(hmC) as hmC_h: for line in mC_h: cols = line.strip().split("\t") if cols[3] != "CG": continue pos = int(cols[1]) counts = [int(float(cols[5])), int(cols[6])] if pos < pos_hmC: continue elif pos > pos_hmC: hmC_h, hmC = _sync_pos(hmC_h, pos) if not hmC_h: break pos_hmC = hmC["pos"] if counts[0] < 9 or hmC["counts"][0] < 9: continue if pos == hmC["pos"]: pvalue = _call_hmc(counts, hmC["counts"]) print >>out_handle, "%s\t%s\t%s" % (line.strip(), "\t".join(hmC["info"]), pvalue) return [[data]] def hmc_stats(sample): dt = Counter() work_dir = dd.get_work_dir(sample) sample_name = dd.get_sample_name(sample) out = os.path.join(work_dir, "cpg_split", sample_name, "%s_hmC.tsv" % sample_name) cmd = "cat %s > {out}" % " ".join(sample["hmc_split"]) do.run(cmd.format(**locals()), "") def cpg_stats(sample): dtdepth = Counter() dtratio = Counter() work_dir = dd.get_work_dir(sample) sample_name = dd.get_sample_name(sample) depth_out = os.path.join(work_dir, "cpg_split", sample_name, "depth.tsv") ratio_out = os.path.join(work_dir, "cpg_split", sample_name, "ratio.tsv") hmc_out = os.path.join(work_dir, "cpg_split", sample_name, "%s_hmc.tsv.gz" % sample_name) hmc_files = " ".join(sample["hmc_split"]) with file_transaction(hmc_out) as tx_out: header = " ".join(["chr", "pos", "strand", "context", "ratio", "eff_CT_counts", "C_counts", "CT_counts", "rev_G_counts", "rev_GA_counts", "CI_lover", "CI_upper", "ox_ratio", "ox_eff_CT_counts", "ox_C_counts", "ox_CT_counts", "ox_rev_G_counts", "ox_rev_GA_counts", "ox_CI_lower", "ox_CI_upper", "pvalue"]) cmd = "cat <(echo {header} | sed 's/ /\t/g') {hmc_files} | gzip -c > {tx_out}" if not file_exists(hmc_out): do.run(cmd.format(**locals()), "Merging %s" % sample_name) work_bam = dd.get_work_bam(sample) if not file_exists(depth_out): for cpg_file in sample["cpg_split"]: logger.debug("Reading %s of sample %s" % (cpg_file, sample_name)) if file_exists(cpg_file): with open(cpg_file) as in_handle: for line in in_handle: cols = line.strip().split("\t") if cols[3] == "CG": ratio = int(float(cols[4]) * 100) dtratio[ratio] += 1 depth = int(math.ceil(float(cols[5]))) if float(cols[5]) < 50 else 50 dtdepth[depth] += 1 pd.DataFrame(dtdepth, index=[1]).to_csv(depth_out, sep="\t") pd.DataFrame(dtratio, index=[1]).to_csv(ratio_out, sep="\t") # calculate mlml if not hmc_files: return None out_dir = safe_makedir(os.path.join(work_dir, "mlml", sample_name)) mlml_out = os.path.join(out_dir, "%s_mlml.txt.gz" % sample_name) if not file_exists(mlml_out) and file_exists(hmc_out): with chdir(out_dir): with file_transaction(mlml_out) as tx_out: tx_out_1 = "%s_noheader" % tx_out tx_out_2 = "%s_alone" % tx_out cmd = " ".join(["zcat %s | sed -e '1d' | awk " % hmc_out, ''' '{rounded = sprintf("%d", $14);print $1"\\t"$2"\t"$3"\\tCpG\\t"$13"\\t"rounded}' ''', "> %s_ox.txt" % sample_name]) do.run(cmd, "Creating OX input for %s" % sample_name) cmd = " ".join(["zcat %s | sed -e '1d' | awk " % hmc_out, ''' '{rounded = sprintf("%d", $6);print $1"\\t"$2"\\t"$3"\\tCpG\\t"$5"\\t"rounded}' ''', "> %s_bs.txt" % sample_name]) do.run(cmd, "Creating BS input for %s" % sample_name) cmd = ("mlml -o {tx_out_1} -u {sample_name}_bs.txt -m {sample_name}_ox.txt -v").format(**locals()) do.run(cmd, "Run MLML with %s" % sample_name) cmd = ("cat <(echo chrom start end mC hmC C conflicts | sed 's/ /\t/g') {tx_out_1} | gzip -c > {tx_out_2} ").format(**locals()) do.run(cmd, "") tx_out_1 = "%s.woFDR.gz" % tx_out cmd = ("paste <(zcat {hmc_out}) <(zcat {tx_out_2}) | gzip -c > {tx_out}").format(**locals()) do.run(cmd, "Merge data for %s" % sample_name) merge_out = [os.path.join(out_dir, "%s_merged.txt.gz" % sample_name), os.path.join(out_dir, "%s_merged_pass.txt.gz" % sample_name)] if not file_exists(merge_out[0]): with file_transaction(merge_out) as tx_outs: tx_out, tx_out_pass = tx_outs df = pd.read_csv(mlml_out, sep="\t") import statsmodels.sandbox.stats.multicomp df["fdr"] = statsmodels.sandbox.stats.multicomp.fdrcorrection0(df["pvalue"])[1] df_p_pass = df[df.fdr<0.05] logger.debug("Pass FDR 5 pct in %s:%s " % (sample_name, float(df_p_pass.shape[1])/float(df.shape[1]))) df.to_csv(tx_out, sep="\t") df_p_pass.to_csv(tx_out_pass, sep="\t") bcbio-nextgen-1.2.9/bcbio/wgbsseq/deduplication.py000066400000000000000000000037751415626112400222140ustar00rootroot00000000000000import os from bcbio import utils from bcbio.distributed import transaction from bcbio.pipeline import datadict, config_utils from bcbio.provenance import do from bcbio import bam from bcbio.pipeline import datadict as dd def dedup_bismark(data): """ Remove alignments to the same position in the genome from the Bismark mapping output using deduplicate_bismark """ config = data["config"] input_file = datadict.get_work_bam(data) # don't sort even by read names # input_file = bam.sort(input_file, config, order="queryname") sample_name = datadict.get_sample_name(data) output_dir = os.path.join(datadict.get_work_dir(data), 'dedup', sample_name) output_dir = utils.safe_makedir(output_dir) input_file_name, input_file_extension = os.path.splitext(os.path.basename( input_file )) output_file = os.path.join( output_dir, f'{input_file_name}.deduplicated{input_file_extension}' ) if utils.file_exists(output_file): data = datadict.set_work_bam(data, output_file) data["deduplication_report"] = output_file.replace("deduplicated.bam", "deduplication_report.txt") data = dd.update_summary_qc(data, "bismark", base=data["deduplication_report"]) return [[data]] deduplicate_bismark = config_utils.get_program('deduplicate_bismark', config) resources = config_utils.get_resources("deduplicate_bismark", data) opt = "" if "options" in resources: opt_list = [str(x) for x in resources.get("options", [])] opt = ' '.join(opt_list) command = f'{deduplicate_bismark} {opt} --output_dir {output_dir} {input_file}' with transaction.file_transaction(output_dir): do.run(command, 'remove deduplicate alignments') data = datadict.set_work_bam(data, output_file) data["deduplication_report"] = output_file.replace("deduplicated.bam", "deduplication_report.txt") data = dd.update_summary_qc(data, "bismark", base=data["deduplication_report"]) return [[data]] bcbio-nextgen-1.2.9/bcbio/wgbsseq/kits.py000066400000000000000000000005131415626112400203250ustar00rootroot00000000000000from collections import namedtuple Kit = namedtuple('Kit', 'name clip_r1_5 clip_r1_3 clip_r2_5 clip_r2_3 is_directional') _KITS = [ Kit("truseq", 8, 8, 8, 8, False), Kit("accelngs", 10, 10, 19, 5, True), Kit("nebemseq", 5, 5, 11, 5, True) ] KITS = {x.name: x for x in _KITS} SUPPORTED_KITS = {x.name for x in _KITS} bcbio-nextgen-1.2.9/bcbio/wgbsseq/trimming.py000066400000000000000000000064231415626112400212070ustar00rootroot00000000000000import os from bcbio.utils import append_stem, replace_directory from bcbio.provenance import do from bcbio.distributed.transaction import file_transaction from bcbio import utils from bcbio.pipeline import datadict as dd from bcbio.qc import fastqc from bcbio.bam import fastq from bcbio.log import logger from bcbio.pipeline import config_utils from bcbio.wgbsseq import kits def trim(data): """Remove adapter for bisulphite conversion sequencing data""" in_files = data["files"] names = dd.get_sample_name(data) work_dir = os.path.join(dd.get_work_dir(data), "trimmed", names) out_dir = utils.safe_makedir(work_dir) out_files = [ os.path.join(out_dir, utils.splitext_plus(os.path.basename(in_files[0]))[0] + '_val_1.fq.gz'), os.path.join(out_dir, utils.splitext_plus(os.path.basename(in_files[1]))[0] + '_val_2.fq.gz') ] if utils.file_exists(out_files[0]): data["files"] = out_files return [[data]] kit = kits.KITS.get(dd.get_kit(data), None) if kit: logger.info(f"{kit.name} specified, using clip settings: R1 5'-{kit.clip_r1_5}nt/--/{kit.clip_r1_3}nt-3', R2 5'-{kit.clip_r2_5}nt/--/{kit.clip_r2_3}nt-3'") clipsettings = _get_clip_settings(kit) else: logger.info(f"No kit specified, using default clip settings") clipsettings = "" trim_galore = config_utils.get_program("trim_galore", data["config"]) # trim_galore actual cores used = 3x + 3 where x = value of the parameter (according to manual) tg_cores = max(int((dd.get_num_cores(data) - 3) / 3), 1) other_opts = config_utils.get_resources("trim_galore", data["config"]).get("options", []) other_opts = " ".join([str(x) for x in other_opts]).strip() cmd = "{trim_galore} {other_opts} {clipsettings} --cores {tg_cores} --length 30 --quality 30 --fastqc --paired -o {tx_out_dir} {files}" log_file = os.path.join(out_dir, names + "_cutadapt_log.txt") if not utils.file_exists(out_files[0]): with file_transaction(out_dir) as tx_out_dir: files = "%s %s" % (in_files[0], in_files[1]) do.run(cmd.format(**locals()), "remove adapters with trimgalore") data["files"] = out_files return [[data]] def _run_qc_fastqc(in_files, data, out_dir): in_files = fastq.downsample(in_files[0], in_files[1], N=5000000) for fastq_file in in_files: if fastq_file: fastqc.run(fastq_file, data, os.path.join(out_dir, utils.splitext_plus(os.path.basename(fastq_file))[0])) def _fix_output(in_file, stem, out_dir): out_file = utils.splitext_plus(replace_directory(append_stem(in_file, stem), out_dir)) return "%s%s" % (out_file[0], out_file[1].replace("fastq", "fq")) def _get_clip_settings(kit): clip_settings = "" if kit.clip_r1_5 > 0: clip_settings = clip_settings + "--clip_r1 " + str(kit.clip_r1_5) + " " if kit.clip_r2_5 > 0: clip_settings = clip_settings + "--clip_r2 " + str(kit.clip_r2_5) + " " if kit.clip_r1_3 > 0: clip_settings = clip_settings + "--three_prime_clip_r1 " + str(kit.clip_r1_3) + " " if kit.clip_r2_3 > 0: clip_settings = clip_settings + "--three_prime_clip_r2 " + str(kit.clip_r2_3) + " " return clip_settings.strip() bcbio-nextgen-1.2.9/bcbio/workflow/000077500000000000000000000000001415626112400172015ustar00rootroot00000000000000bcbio-nextgen-1.2.9/bcbio/workflow/__init__.py000066400000000000000000000005571415626112400213210ustar00rootroot00000000000000"""Prepare pre-defined workflows that handle creation of input sample configs. """ from bcbio.workflow import xprize, stormseq, template workflows = {"xprize": xprize, "stormseq": stormseq, "template": template} def setup(name, inputs): workflow = workflows[name] args = workflow.parse_args(inputs) return workflow.setup(args) bcbio-nextgen-1.2.9/bcbio/workflow/stormseq.py000066400000000000000000000060221415626112400214300ustar00rootroot00000000000000"""Prepare a workflow for running on AWS using STORMSeq as a front end. http://www.stormseq.org/ """ import json import os import yaml from bcbio import utils from bcbio.upload import s3 from bcbio.workflow import xprize def parse_args(args): parser = xprize.HelpArgParser(description="Run STORMSeq processing on AWS") parser.add_argument("config_file", help="JSON configuration file with form parameters") parser.add_argument("base_dir", help="Base directory to process in") parser.add_argument("bcbio_config_file", help="bcbio system YAML config") args = parser.parse_args(args) return args def _get_s3_files(local_dir, file_info, params): """Retrieve s3 files to local directory, handling STORMSeq inputs. """ assert len(file_info) == 1 files = file_info.values()[0] fnames = [] for k in ["1", "2"]: if files[k] not in fnames: fnames.append(files[k]) out = [] for fname in fnames: bucket, key = fname.replace("s3://", "").split("/", 1) if params["access_key_id"] == "TEST": out.append(os.path.join(local_dir, os.path.basename(key))) else: out.append(s3.get_file(local_dir, bucket, key, params)) return out def setup(args): configdir = utils.safe_makedir(os.path.join(args.base_dir, "config")) inputdir = utils.safe_makedir(os.path.join(args.base_dir, "inputs")) workdir = utils.safe_makedir(os.path.join(args.base_dir, "work")) finaldir = utils.safe_makedir(os.path.join(args.base_dir, "ready")) out_config_file = os.path.join(configdir, "%s.yaml" % os.path.splitext(os.path.basename(args.config_file))[0]) with open(args.config_file) as in_handle: ss_config = json.load(in_handle) ss_params = ss_config["parameters"] out = {"fc_date": xprize.get_fc_date(out_config_file), "fc_name": ss_config["sample"], "upload": {"dir": finaldir, "method": "s3", "bucket": ss_params["s3_bucket"], "access_key_id": ss_params["access_key_id"], "secret_access_key": ss_params["secret_access_key"]}, "details": [{ "files": _get_s3_files(inputdir, ss_config["files"], ss_params), "lane": 1, "description": ss_params["sample"], "analysis": "variant", "genome_build": ss_params["genome_version"], "algorithm": { "aligner": ss_params["alignment_pipeline"], "variantcaller": ss_params["calling_pipeline"], "quality_format": "Standard", "coverage_interval": "genome" if ss_params["data_type"] == "data_wgs" else "exome", }}]} with open(out_config_file, "w") as out_handle: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) return workdir, {"config_file": args.bcbio_config_file, "run_info_yaml": out_config_file} bcbio-nextgen-1.2.9/bcbio/workflow/template.py000066400000000000000000000617701415626112400214010ustar00rootroot00000000000000"""Create bcbio_sample.yaml files from standard templates and lists of input files. Provides an automated way to generate a full set of analysis files from an inpu YAML template. Default templates are provided for common approaches which can be tweaked as needed. """ from __future__ import print_function import collections import contextlib import copy import csv import datetime import glob import fnmatch import itertools import os import shutil from six.moves import urllib import six import toolz as tz import yaml import sys from bcbio import utils from bcbio.bam import fastq, sample_name from bcbio.distributed import objectstore from bcbio.upload import s3 from bcbio.pipeline import config_utils, run_info from bcbio.workflow.xprize import HelpArgParser from bcbio.log import setup_script_logging def parse_args(inputs): parser = HelpArgParser( description="Create a bcbio_sample.yaml file from a standard template and inputs") parser = setup_args(parser) args = parser.parse_args(inputs) if args.template.endswith("csv"): parser.print_help() print("\nError: Looks like you've swapped the order of the metadata CSV and template YAML arguments, it should go YAML first, CSV second.") sys.exit(1) return parser.parse_args(inputs) def setup_args(parser): parser.add_argument("template", help=("Template name or path to template YAML file. " "Built in choices: freebayes-variant, gatk-variant, tumor-paired, " "noalign-variant, illumina-rnaseq, illumina-chipseq")) parser.add_argument("metadata", help="CSV file with project metadata. Name of file used as project name.") parser.add_argument("input_files", nargs="*", help="Input read files, in BAM or fastq format") parser.add_argument("--only-metadata", help="Ignore samples not present in metadata CSV file", action="store_true", default=False) parser.add_argument("--force-single", help="Treat all files as single reads", action="store_true", default=False) parser.add_argument("--separators", help="semicolon separated list of separators that indicates paired files.", default="R,_,-,.") setup_script_logging() return parser # ## Prepare sequence data inputs def _prep_bam_input(f, base): if not os.path.exists(f) and not objectstore.is_remote(f): raise ValueError("Could not find input file: %s" % f) cur = copy.deepcopy(base) if objectstore.is_remote(f): cur["files"] = [f] cur["description"] = os.path.splitext(os.path.basename(f))[0] else: cur["files"] = [os.path.abspath(f)] cur["description"] = ((sample_name(f) if f.endswith(".bam") else None) or os.path.splitext(os.path.basename(f))[0]) return cur def _prep_fastq_input(fs, base): for f in fs: if not os.path.exists(f) and not objectstore.is_remote(f): raise ValueError("Could not find input file: %s" % f) cur = copy.deepcopy(base) cur["files"] = [os.path.abspath(f) if not objectstore.is_remote(f) else f for f in fs] d = os.path.commonprefix([utils.splitext_plus(os.path.basename(f))[0] for f in fs]) cur["description"] = fastq.rstrip_extra(d) return cur def _prep_vcf_input(f, base): if not os.path.exists(f) and not objectstore.is_remote(f): raise ValueError("Could not find input file: %s" % f) cur = copy.deepcopy(base) cur["vrn_file"] = f cur["description"] = utils.splitext_plus(os.path.basename(f))[0] return cur KNOWN_EXTS = {".bam": "bam", ".cram": "bam", ".fq": "fastq", ".fastq": "fastq", ".txt": "fastq", ".fastq.gz": "fastq", ".fq.gz": "fastq", ".txt.gz": "fastq", ".gz": "fastq", ".fastq.bz2": "fastq", ".fq.bz2": "fastq", ".txt.bz2": "fastq", ".bz2": "fastq", ".vcf": "vcf", ".vcf.gz": "vcf"} def _prep_items_from_base(base, in_files, metadata, separators, force_single=False): """Prepare a set of configuration items for input files. """ details = [] in_files = _expand_dirs(in_files, KNOWN_EXTS) in_files = _expand_wildcards(in_files) ext_groups = collections.defaultdict(list) for ext, files in itertools.groupby( in_files, lambda x: KNOWN_EXTS.get(utils.splitext_plus(x)[-1].lower())): ext_groups[ext].extend(list(files)) for ext, files in ext_groups.items(): if ext == "bam": for f in files: details.append(_prep_bam_input(f, base)) elif ext in ["fastq", "fq", "fasta"]: files, glob_files = _find_glob_matches(files, metadata) for fs in glob_files: details.append(_prep_fastq_input(fs, base)) for fs in fastq.combine_pairs(files, force_single, separators=separators): details.append(_prep_fastq_input(fs, base)) elif ext in ["vcf"]: for f in files: details.append(_prep_vcf_input(f, base)) else: print("Ignoring unexpected input file types %s: %s" % (ext, list(files))) return details def _find_glob_matches(in_files, metadata): """Group files that match by globs for merging, rather than by explicit pairs. """ reg_files = copy.deepcopy(in_files) glob_files = [] for glob_search in [x for x in metadata.keys() if "*" in x]: cur = [] for fname in in_files: if fnmatch.fnmatch(fname, "*/%s" % glob_search): cur.append(fname) reg_files.remove(fname) assert cur, "Did not find file matches for %s" % glob_search glob_files.append(cur) return reg_files, glob_files def _expand_file(x): return os.path.abspath(os.path.normpath(os.path.expanduser(os.path.expandvars(x)))) def _expand_dirs(in_files, known_exts): def _is_dir(in_file): return os.path.isdir(os.path.expanduser(in_file)) files, dirs = utils.partition(_is_dir, in_files) for dir in dirs: for ext in known_exts.keys(): wildcard = os.path.join(os.path.expanduser(dir), "*" + ext) files = itertools.chain(glob.glob(wildcard), files) return list(files) def _expand_wildcards(in_files): def _has_wildcard(in_file): return "*" in in_file files, wildcards = utils.partition(_has_wildcard, in_files) for wc in wildcards: abs_path = os.path.expanduser(wc) files = itertools.chain(glob.glob(abs_path), files) return list(files) # ## Read and write configuration files def name_to_config(template): """Read template file into a dictionary to use as base for all samples. Handles well-known template names, pulled from GitHub repository and local files. """ if objectstore.is_remote(template): with objectstore.open_file(template) as in_handle: config = yaml.safe_load(in_handle) with objectstore.open_file(template) as in_handle: txt_config = in_handle.read() elif os.path.isfile(template): if template.endswith(".csv"): raise ValueError("Expected YAML file for template and found CSV, are arguments switched? %s" % template) with open(template) as in_handle: txt_config = in_handle.read() with open(template) as in_handle: config = yaml.safe_load(in_handle) else: base_url = "https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/templates/%s.yaml" try: with contextlib.closing(urllib.request.urlopen(base_url % template)) as in_handle: txt_config = in_handle.read().decode() with contextlib.closing(urllib.request.urlopen(base_url % template)) as in_handle: config = yaml.safe_load(in_handle) except (urllib.error.HTTPError, urllib.error.URLError): raise ValueError("Could not find template '%s' locally or in standard templates on GitHub" % template) return config, txt_config def _write_template_config(template_txt, project_name, out_dir): config_dir = utils.safe_makedir(os.path.join(out_dir, "config")) out_config_file = os.path.join(config_dir, "%s-template.yaml" % project_name) with open(out_config_file, "w") as out_handle: out_handle.write(template_txt) return out_config_file def _write_config_file(items, global_vars, template, project_name, out_dir, remotes): """Write configuration file, adding required top level attributes. """ config_dir = utils.safe_makedir(os.path.join(out_dir, "config")) out_config_file = os.path.join(config_dir, "%s.yaml" % project_name) out = {"fc_name": project_name, "upload": {"dir": "../final"}, "details": items} if remotes.get("base"): r_base = objectstore.parse_remote(remotes.get("base")) out["upload"]["method"] = r_base.store out["upload"]["bucket"] = r_base.bucket out["upload"]["folder"] = os.path.join(r_base.key, "final") if r_base.key else "final" if r_base.region: out["upload"]["region"] = r_base.region if global_vars: out["globals"] = global_vars for k, v in template.items(): if k not in ["details"]: out[k] = v if os.path.exists(out_config_file): shutil.move(out_config_file, out_config_file + ".bak%s" % datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")) with open(out_config_file, "w") as out_handle: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) return out_config_file def _safe_name(x): for prob in [" ", "."]: x = x.replace(prob, "_") return x def _set_global_vars(metadata): """Identify files used multiple times in metadata and replace with global variables """ fnames = collections.defaultdict(list) for sample in metadata.keys(): for k, v in metadata[sample].items(): if isinstance(v, six.string_types) and os.path.isfile(v): v = _expand_file(v) metadata[sample][k] = v fnames[v].append(k) global_vars = {} # Skip global vars -- more confusing than useful # loc_counts = collections.defaultdict(int) # global_var_sub = {} # for fname, locs in fnames.items(): # if len(locs) > 1: # loc_counts[locs[0]] += 1 # name = "%s%s" % (locs[0], loc_counts[locs[0]]) # global_var_sub[fname] = name # global_vars[name] = fname # for sample in metadata.keys(): # for k, v in metadata[sample].items(): # if isinstance(v, six.string_types) and v in global_var_sub: # metadata[sample][k] = global_var_sub[v] return metadata, global_vars def _clean_string(v, sinfo): """Test for and clean unicode present in template CSVs. """ if isinstance(v, (list, tuple)): return [_clean_string(x, sinfo) for x in v] else: assert isinstance(v, six.string_types), v try: if hasattr(v, "decode"): return str(v.decode("ascii")) else: return str(v.encode("ascii").decode("ascii")) except UnicodeDecodeError as msg: raise ValueError("Found unicode character in template CSV line %s:\n%s" % (sinfo, str(msg))) def _parse_metadata(in_handle): """Reads metadata from a simple CSV structured input file. samplename,batch,phenotype ERR256785,batch1,normal """ metadata = {} reader = csv.reader(in_handle) while 1: header = next(reader) if not header[0].startswith("#"): break keys = [x.strip() for x in header[1:]] for sinfo in (x for x in reader if x and not x[0].startswith("#")): sinfo = [_strip_and_convert_lists(x) for x in sinfo] sample = sinfo[0] if isinstance(sample, list): sample = tuple(sample) # sanity check to avoid duplicate rows if sample in metadata: raise ValueError("Sample %s present multiple times in metadata file.\n" "If you need to specify multiple attributes as a list " "use a semi-colon to separate them on a single line.\n" "https://bcbio-nextgen.readthedocs.org/en/latest/" "contents/configuration.html#automated-sample-configuration\n" "Duplicate line is %s" % (sample, sinfo)) vals = [_clean_string(v, sinfo) for v in sinfo[1:]] metadata[sample] = dict(zip(keys, vals)) metadata, global_vars = _set_global_vars(metadata) return metadata, global_vars def _strip_and_convert_lists(field): field = field.strip() if "," in field: field = [x.strip() for x in field.split(",")] elif ";" in field: field = [x.strip() for x in field.split(";")] return field def _pname_and_metadata(in_file): """Retrieve metadata and project name from the input metadata CSV file. Uses the input file name for the project name and for back compatibility, accepts the project name as an input, providing no metadata. """ if os.path.isfile(in_file): with open(in_file) as in_handle: md, global_vars = _parse_metadata(in_handle) base = os.path.splitext(os.path.basename(in_file))[0] md_file = in_file elif objectstore.is_remote(in_file): with objectstore.open_file(in_file) as in_handle: md, global_vars = _parse_metadata(in_handle) base = os.path.splitext(os.path.basename(in_file))[0] md_file = None else: if in_file.endswith(".csv"): raise ValueError("Did not find input metadata file: %s" % in_file) base, md, global_vars = _safe_name(os.path.splitext(os.path.basename(in_file))[0]), {}, {} md_file = None return _safe_name(base), md, global_vars, md_file def _handle_special_yaml_cases(v): """Handle values that pass integer, boolean, list or dictionary values. """ if "::" in v: out = {} for part in v.split("::"): k_part, v_part = part.split(":") out[k_part] = v_part.split(";") v = out elif ";" in v: # split lists and remove accidental empty values v = [x for x in v.split(";") if x != ""] elif isinstance(v, list): v = v else: try: v = int(v) except ValueError: if v.lower() == "true": v = True elif v.lower() == "false": v = False return v def _add_ped_metadata(name, metadata): """Add standard PED file attributes into metadata if not present. http://pngu.mgh.harvard.edu/~purcell/plink/data.shtml#ped """ ignore = set(["-9", "undefined", "unknown", "."]) def _ped_mapping(x, valmap): try: x = int(x) except ValueError: x = -1 for k, v in valmap.items(): if k == x: return v return None def _ped_to_gender(x): return _ped_mapping(x, {1: "male", 2: "female"}) def _ped_to_phenotype(x): known_phenotypes = set(["unaffected", "affected", "tumor", "normal"]) if x in known_phenotypes: return x else: return _ped_mapping(x, {1: "unaffected", 2: "affected"}) def _ped_to_batch(x): if x not in ignore and x != "0": return x with open(metadata["ped"]) as in_handle: for line in in_handle: parts = line.split("\t")[:6] if parts[1] == str(name): for index, key, convert_fn in [(4, "sex", _ped_to_gender), (0, "batch", _ped_to_batch), (5, "phenotype", _ped_to_phenotype)]: val = convert_fn(parts[index]) if val is not None and key not in metadata: metadata[key] = val break return metadata def _get_file_keys(item): if item.get("files"): return [item["files"][0], os.path.basename(item["files"][0]), tuple([os.path.basename(f) for f in item["files"]]), utils.splitext_plus(os.path.basename(item["files"][0]))[0], os.path.commonprefix([os.path.basename(f) for f in item["files"]])] else: return [] def _get_vrn_keys(item): if item.get("vrn_file"): return [item["vrn_file"], os.path.basename(item["vrn_file"]), utils.splitext_plus(os.path.basename(item["vrn_file"]))[0]] else: return [] def _add_metadata(item, metadata, remotes, only_metadata=False): """Add metadata information from CSV file to current item. Retrieves metadata based on 'description' parsed from input CSV file. Adds to object and handles special keys: - `description`: A new description for the item. Used to relabel items based on the pre-determined description from fastq name or BAM read groups. - Keys matching supported names in the algorithm section map to key/value pairs there instead of metadata. """ for check_key in [item["description"]] + _get_file_keys(item) + _get_vrn_keys(item): item_md = metadata.get(check_key) if item_md: break if not item_md: item_md = _find_glob_metadata(item["files"], metadata) if remotes.get("region"): item["algorithm"]["variant_regions"] = remotes["region"] TOP_LEVEL = set(["description", "genome_build", "lane", "vrn_file", "files", "analysis"]) keep_sample = True if item_md and len(item_md) > 0: if "metadata" not in item: item["metadata"] = {} for k, v in item_md.items(): if v: if k in TOP_LEVEL: item[k] = v elif k in run_info.ALGORITHM_KEYS: v = _handle_special_yaml_cases(v) item["algorithm"][k] = v else: v = _handle_special_yaml_cases(v) item["metadata"][k] = v elif len(metadata) > 0: warn = "Dropped sample" if only_metadata else "Added minimal sample information" print("WARNING: %s: metadata not found for %s, %s" % (warn, item["description"], [os.path.basename(f) for f in item["files"]])) keep_sample = not only_metadata if tz.get_in(["metadata", "ped"], item): item["metadata"] = _add_ped_metadata(item["description"], item["metadata"]) return item if keep_sample else None def _find_glob_metadata(cur_files, metadata): md_key = None for check_key in metadata.keys(): matches = 0 if "*" in check_key: for fname in cur_files: if fnmatch.fnmatch(fname, "*/%s" % check_key): matches += 1 if matches == len(cur_files): md_key = check_key break if md_key: return metadata[md_key] def _retrieve_remote(fnames): """Retrieve remote inputs found in the same bucket as the template or metadata files. """ for fname in fnames: if objectstore.is_remote(fname): inputs = [] regions = [] remote_base = os.path.dirname(fname) for rfname in objectstore.list(remote_base): if rfname.endswith(tuple(KNOWN_EXTS.keys())): inputs.append(rfname) elif rfname.endswith((".bed", ".bed.gz")): regions.append(rfname) return {"base": remote_base, "inputs": inputs, "region": regions[0] if len(regions) == 1 else None} return {} def _convert_to_relpaths(data, work_dir): """Convert absolute paths in the input data to relative paths to the work directory. """ work_dir = os.path.abspath(work_dir) data["files"] = [os.path.relpath(f, work_dir) for f in data["files"]] for topk in ["metadata", "algorithm"]: for k, v in data[topk].items(): if isinstance(v, six.string_types) and os.path.isfile(v) and os.path.isabs(v): data[topk][k] = os.path.relpath(v, work_dir) return data def _check_all_metadata_found(metadata, items): """Print warning if samples in CSV file are missing in folder""" for name in metadata: seen = False for sample in items: check_file = sample["files"][0] if sample.get("files") else sample["vrn_file"] if isinstance(name, (tuple, list)): if check_file.find(name[0]) > -1: seen = True elif check_file.find(name) > -1: seen = True elif "*" in name and fnmatch.fnmatch(check_file, "*/%s" % name): seen = True if not seen: print("WARNING: sample not found %s" % str(name)) def _copy_to_configdir(items, out_dir, args): """Copy configuration files like PED inputs to working config directory. """ out = [] for item in items: ped_file = tz.get_in(["metadata", "ped"], item) if ped_file and os.path.exists(ped_file): ped_config_file = os.path.join(out_dir, "config", os.path.basename(ped_file)) if not os.path.exists(ped_config_file): shutil.copy(ped_file, ped_config_file) item["metadata"]["ped"] = ped_config_file out.append(item) if hasattr(args, "systemconfig") and args.systemconfig: shutil.copy(args.systemconfig, os.path.join(out_dir, "config", os.path.basename(args.systemconfig))) return out def _find_remote_inputs(metadata): out = [] for fr_key in metadata.keys(): if isinstance(fr_key, (list, tuple)): frs = fr_key else: frs = [fr_key] for fr in frs: if objectstore.is_remote(fr): out.append(fr) return out def check_hla_align(base_item): algorithm = tz.get_in(["algorithm"], base_item) if algorithm and "aligner" in algorithm and "hlacaller" in algorithm: if algorithm["aligner"] != "bwa" and algorithm["hlacaller"].lower() == "optitype": print("WARNING: Optitype needs aligner: bwa; no HLA calls will be made with aligner: false") def setup(args): template, template_txt = name_to_config(args.template) run_info.validate_yaml(template_txt, args.template) base_item = template["details"][0] check_hla_align(base_item) project_name, metadata, global_vars, md_file = _pname_and_metadata(args.metadata) remotes = _retrieve_remote([args.metadata, args.template]) inputs = args.input_files + remotes.get("inputs", []) + _find_remote_inputs(metadata) remote_retriever = None remote_config = None if hasattr(args, "systemconfig") and args.systemconfig and hasattr(args, "integrations"): config, _ = config_utils.load_system_config(args.systemconfig) for iname, retriever in args.integrations.items(): if iname in config: remote_retriever = retriever remote_config = remote_retriever.set_cache(config[iname]) inputs += remote_retriever.get_files(metadata, remote_config) raw_items = [_add_metadata(item, metadata, remotes, args.only_metadata) for item in _prep_items_from_base(base_item, inputs, metadata, args.separators.split(","), args.force_single)] items = [x for x in raw_items if x] _check_all_metadata_found(metadata, items) if remote_retriever and remote_config: items = remote_retriever.add_remotes(items, remote_config) out_dir = os.path.join(os.getcwd(), project_name) work_dir = utils.safe_makedir(os.path.join(out_dir, "work")) if hasattr(args, "relpaths") and args.relpaths: items = [_convert_to_relpaths(x, work_dir) for x in items] out_config_file = _write_template_config(template_txt, project_name, out_dir) if md_file: shutil.copyfile(md_file, os.path.join(out_dir, "config", os.path.basename(md_file))) items = _copy_to_configdir(items, out_dir, args) if len(items) == 0: print() print("Template configuration file created at: %s" % out_config_file) print("Edit to finalize custom options, then prepare full sample config with:") print(" bcbio_nextgen.py -w template %s %s sample1.bam sample2.fq" % (out_config_file, project_name)) else: out_config_file = _write_config_file(items, global_vars, template, project_name, out_dir, remotes) print() print("Configuration file created at: %s" % out_config_file) print("Edit to finalize and run with:") print(" cd %s" % work_dir) print(" bcbio_nextgen.py ../config/%s" % os.path.basename(out_config_file)) if remotes.get("base"): remote_path = os.path.join(remotes["base"], os.path.basename(out_config_file)) s3.upload_file_boto(out_config_file, remote_path) print("Also uploaded to AWS S3 in %s" % remotes["base"]) print("Run directly with bcbio_vm.py run %s" % remote_path) bcbio-nextgen-1.2.9/bcbio/workflow/xprize.py000066400000000000000000000061731415626112400211030ustar00rootroot00000000000000"""XPrize scoring workflow that converts input BAMs into consolidated Ensemble calls. Automates the Ensemble approach described here (http://j.mp/VUbz9A) to prepare a final set of reference haploid variant calls for X Prize scoring. """ import argparse import datetime import os import sys import yaml from bcbio import utils class HelpArgParser(argparse.ArgumentParser): def error(self, message): sys.stderr.write('error: %s\n' % message) self.print_help() sys.exit(2) def parse_args(args): parser = HelpArgParser( description="Automate ensemble variant approach for X Prize preparation") parser.add_argument("sample", help="Sample name") parser.add_argument("bam_file", help="Input BAM file") parser.add_argument("bed_file", help="BED file of fosmid regions") parser.add_argument("base_dir", help="Base directory to process in") parser.add_argument("bcbio_config_file", help="bcbio system YAML config") args = parser.parse_args(args) return args def get_fc_date(out_config_file): """Retrieve flowcell date, reusing older dates if refreshing a present workflow. """ if os.path.exists(out_config_file): with open(out_config_file) as in_handle: old_config = yaml.safe_load(in_handle) fc_date = old_config["fc_date"] else: fc_date = datetime.datetime.now().strftime("%y%m%d") return fc_date def setup(args): final_dir = utils.safe_makedir(os.path.join(args.base_dir, "ready")) configdir = utils.safe_makedir(os.path.join(args.base_dir, args.sample, "config")) out_config_file = os.path.join(configdir, "%s.yaml" % args.sample) callers = ["gatk", "freebayes", "samtools", "varscan"] out = {"fc_date": get_fc_date(out_config_file), "fc_name": args.sample, "upload": {"dir": final_dir}, "details": [{ "files": [args.bam_file], "lane": 1, "description": args.sample, "analysis": "variant", "genome_build": "GRCh37", "algorithm": { "aligner": False, "recalibrate": False, "realign": False, "ploidy": 1, "variantcaller": callers, "quality_format": "Standard", "variant_regions": args.bed_file, "coverage_interval": "regional", "ensemble": { "format-filters": ["DP < 4"], "classifiers": { "balance": ["AD", "FS", "Entropy"], "calling": ["ReadPosEndDist", "PL", "Entropy", "NBQ"]}, "classifier-params": { "type": "svm"}, "trusted-pct": 0.65}}}]} with open(out_config_file, "w") as out_handle: yaml.safe_dump(out, out_handle, default_flow_style=False, allow_unicode=False) workdir = utils.safe_makedir(os.path.join(args.base_dir, args.sample, "work")) return workdir, {"config_file": args.bcbio_config_file, "run_info_yaml": out_config_file} bcbio-nextgen-1.2.9/config/000077500000000000000000000000001415626112400155165ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/bcbio_sample.yaml000066400000000000000000000021051415626112400210170ustar00rootroot00000000000000--- # Example file for specifying run information to bcbio_nextgen.py # In a fully Galaxy automated setup this information can be retrieved # from the Galaxy server based on user inputs. This YAML files allows you to # run the automated pipeline separately or from other external programs # If your folder naming is not standard Illumina style # (110729_SN728_0036_A81UJUABXX) you can optionally specify a date and a unique name # to use for naming the output files and project directories. fc_date: '110812' fc_name: unique_name # Directory to upload final results to. Also supports Galaxy and S3 upload. upload: dir: ../final details: # For each flowcell, you specify either the lane if the files follow standard # naming conventions (1_110729_A81UJUABXX) or the names of the files if they # are differently named. Can specify either one file for single end or two for # paired. - files: [/path/to/1_1-fastq.txt, /path/to/1_2-fastq.txt] description: 'Sample 1' genome_build: GRCh37 analysis: variant2 algorithm: aligner: novoalign variantcaller: gatkbcbio-nextgen-1.2.9/config/bcbio_system.yaml000066400000000000000000000040521415626112400210650ustar00rootroot00000000000000--- # Configuration file specifying system details for running an analysis pipeline # These pipeline apply generally across multiple projects. Adjust them in sample # specific configuration files when needed. # -- Base setup # Define resources to be used for individual programs on multicore machines. # These can be defined specifically for memory and processor availability. # - memory: Specify usage for memory intensive programs. The indicated value # specifies the wanted *per core* usage. # - cores: Define cores that can be used for multicore programs. The indicated # value is the maximum cores that should be allocated for a program. # - jvm_opts: specify details resources: # default options, used if other items below are not present # avoids needing to configure/adjust for every program default: memory: 4G cores: 16 jvm_opts: ["-Xms750m", "-Xmx3500m"] # Can also set program specific options # gatk: # jvm_opts: ["-Xms500m", "-Xmx3500m"] snpeff: jvm_opts: ["-Xms750m", "-Xmx3g"] qualimap: memory: 4g express: memory: 8g dexseq: memory: 10g macs2: memory: 16g seqcluster: memory: 8g # Location of galaxy configuration file, which has pointers to reference data # https://bcbio-nextgen.readthedocs.org/en/latest/contents/configuration.html#reference-genome-files galaxy_config: universe_wsgi.ini # -- Additional options for specific integration, not required for standalone usage. # Galaxy integration. Required for retrieving information from Galaxy LIMS. #galaxy_url: http://your/galaxy/url #galaxy_api_key: your_galaxy_api_key # Details for hooking automated processing to a sequencer machine. # Not required if running standalone pipelines. # analysis: # # Can specify a different remote host to initiate # # the copy from. This is useful for NFS shared filesystems # # where you want to manage the copy from the base machine. # copy_user: # copy_host: # store_dir: /store4/solexadata # base_dir: /array0/projects/Sequencing # worker_program: nextgen_analysis_server.py bcbio-nextgen-1.2.9/config/examples/000077500000000000000000000000001415626112400173345ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/examples/HCC2218-sv-getdata.sh000077500000000000000000000017521415626112400226470ustar00rootroot00000000000000#!/bin/bash # # Prepare a run directory for somatic SV validations with the HCC2218 breast # cancer cell line. set -eu -o pipefail mkdir -p config cd config wget -c https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/HCC2218-sv.yaml cd ../ mkdir -p input cd input wget -c --no-check-certificate https://s3.amazonaws.com/bcbio/HCC2218/HCC2218Truth-clean-prep.vcf.gz wget -c --no-check-certificate https://s3.amazonaws.com/bcbio/HCC2218/HCC2218Truth-clean-prep.vcf.gz.tbi wget -c --no-check-certificate https://s3.amazonaws.com/bcbio/HCC2218/NexteraRapidCapture_Exome_TargetedRegions_v1.2Used.bed.gz wget -c --no-check-certificate https://s3.amazonaws.com/bcbio/HCC2218/HCC2218BL_S1.bam wget -c --no-check-certificate https://s3.amazonaws.com/bcbio/HCC2218/HCC2218BL_S1.bam.bai wget -c --no-check-certificate https://s3.amazonaws.com/bcbio/HCC2218/HCC2218C_S1.bam wget -c --no-check-certificate https://s3.amazonaws.com/bcbio/HCC2218/HCC2218C_S1.bam.bai cd ../ mkdir -p work bcbio-nextgen-1.2.9/config/examples/HCC2218-sv.yaml000066400000000000000000000024141415626112400215610ustar00rootroot00000000000000# Somatic deletion/duplication for HCC2218 breast cancer cell lines # https://github.com/Illumina/Canvas#demo-tumor-normal-enrichment-workflow --- upload: dir: ../final details: - files: [../input/HCC2218BL_S1.bam] description: HCC2218BL metadata: batch: HCC2218 phenotype: normal analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa save_diskspace: true variantcaller: germline: [freebayes] somatic: [vardict] svcaller: [cnvkit, seq2c, manta, delly, lumpy, wham, gridss, titancna] vcfanno: [gemini] tools_off: [vqsr] variant_regions: ../input/NexteraRapidCapture_Exome_TargetedRegions_v1.2Used.bed.gz - files: [../input/HCC2218C_S1.bam] description: HCC2218C metadata: batch: HCC2218 phenotype: tumor analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa save_diskspace: true variantcaller: germline: [freebayes] somatic: [vardict] svcaller: [cnvkit, seq2c, manta, delly, lumpy, wham, gridss, titancna] vcfanno: [gemini] tools_off: [vqsr] svvalidate: ../input/HCC2218Truth-clean-prep.vcf.gz variant_regions: ../input/NexteraRapidCapture_Exome_TargetedRegions_v1.2Used.bed.gz bcbio-nextgen-1.2.9/config/examples/NA12878-ensemble.yaml000066400000000000000000000050321415626112400227200ustar00rootroot00000000000000# Example configuration to perform variant calling with multiple methods on a set of # NA12878 replicates. The final calls are merged into a finalized ensemble callset # using a support vector machine based on several classifier metrics. --- fc_date: '121119' fc_name: cliacmp details: - files: [/usr/local/projects/CLIA-Validation/secondary/NA12878-NGv3-LAB1360-A/alignment/NA12878-NGv3-LAB1360-A.bam] lane: NA12878-NGv3-LAB1360-A description: NA12878-NGv3-LAB1360-A analysis: variant genome_build: GRCh37 algorithm: aligner: false recalibrate: false realign: false variantcaller: [gatk, freebayes, samtools, gatk-haplotype, varscan] ensemble: format-filters: [DP < 4] classifiers: balance: [AD, FS, Entropy] calling: [ReadPosEndDist, PL, PLratio, Entropy, NBQ] classifier-params: type: svm trusted-pct: 0.65 variant_regions: /usr/local/projects/CLIA-Validation/secondary/NA12878-NGv3-LAB1360-A/enrichment/padded_targets_200.bed - files: [/usr/local/projects/CLIA-Validation/secondary/NA12878-NGv3-LAB1363-A/alignment/NA12878-NGv3-LAB1363-A.bam] lane: NA12878-NGv3-LAB1363-A description: NA12878-NGv3-LAB1363-A analysis: variant genome_build: GRCh37 algorithm: aligner: false recalibrate: false realign: false variantcaller: [gatk, freebayes, samtools, gatk-haplotype, varscan] ensemble: format-filters: [DP < 4] classifiers: balance: [AD, FS, Entropy] calling: [ReadPosEndDist, PL, PLratio, Entropy, NBQ] classifier-params: type: svm trusted-pct: 0.65 variant_regions: /usr/local/projects/CLIA-Validation/secondary/NA12878-NGv3-LAB1363-A/enrichment/padded_targets_200.bed - files: [/usr/local/projects/CLIA-Validation/secondary/NA12878-AGXT2-LAB1368-A/alignment/NA12878-AGXT2-LAB1368-A.bam] lane: NA12878-AGXT2-LAB1368-A description: NA12878-AGXT2-LAB1368-A analysis: variant genome_build: GRCh37 algorithm: aligner: false recalibrate: false realign: false variantcaller: [gatk, freebayes, samtools, gatk-haplotype, varscan] ensemble: format-filters: [DP < 4] classifiers: balance: [AD, FS, Entropy] calling: [ReadPosEndDist, PL, PLratio, Entropy, NBQ] classifier-params: type: svm trusted-pct: 0.65 variant_regions: /usr/local/projects/CLIA-Validation/secondary/NA12878-AGXT2-LAB1368-A/enrichment/padded_targets_200.bed bcbio-nextgen-1.2.9/config/examples/NA12878-exome-methodcmp-getdata.sh000077500000000000000000000014271415626112400253070ustar00rootroot00000000000000#!/bin/bash set -eu -o pipefail # Data retrieval script for validation comparing alignment methods, preparation approaches # and variant callers for an NA12878 exome dataset from EdgeBio. # # See the bcbio-nextgen documentation for full instructions to # run this analysis: # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines mkdir -p config cd config wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-exome-methodcmp.yaml cd .. mkdir -p input cd input wget -c -O NA12878-NGv3-LAB1360-A_1.fastq.gz https://s3.amazonaws.com/bcbio_nextgen/NA12878-NGv3-LAB1360-A_1.fastq.gz wget -c -O NA12878-NGv3-LAB1360-A_2.fastq.gz https://s3.amazonaws.com/bcbio_nextgen/NA12878-NGv3-LAB1360-A_2.fastq.gz cd .. mkdir -p work bcbio-nextgen-1.2.9/config/examples/NA12878-exome-methodcmp.yaml000066400000000000000000000014151415626112400242220ustar00rootroot00000000000000# Configuration comparing alignment methods, preparation approaches # and variant callers for an NA12878 exome dataset from EdgeBio. # # See the bcbio-nextgen documentation for full instructions to # run this analysis: # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines --- upload: dir: ../final details: - files: [../input/NA12878-NGv3-LAB1360-A_1.fastq.gz, ../input/NA12878-NGv3-LAB1360-A_2.fastq.gz] description: NA12878 metadata: sex: female analysis: variant2 genome_build: hg38 algorithm: aligner: bwa variantcaller: gatk-haplotype validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed variant_regions: capture_regions/Exome-NGv3 bcbio-nextgen-1.2.9/config/examples/NA12878-hg38-validate-getdata.sh000077500000000000000000000010751415626112400245530ustar00rootroot00000000000000#!/bin/bash # # Retrieve data for hg38/GRCh38 validation # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines set -eu -o pipefail mkdir -p config cd config wget -c https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-hg38-validate.yaml cd .. mkdir -p input cd input # Genome data wget -c -O NA12878_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_1.fastq.gz wget -c -O NA12878_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_2.fastq.gz mkdir -p work bcbio-nextgen-1.2.9/config/examples/NA12878-hg38-validate.yaml000066400000000000000000000133361415626112400234740ustar00rootroot00000000000000# Validation for hg38/GRCh38 # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines # # Uses two build 38 reference genomes # - hg38 -- full reference with alternative alleles and HLA # - hg38-noalt -- no alternative alleles # # Uses 4 validation sets: # - Genome in a Bottle native hg38 validation calls # - Genome in a Bottle converted to build 38 with NCBI remap # - Genome in a Bottle converted to build 38 with CrossMap and a UCSC chain file # - Illumina's platinum genome --- upload: dir: ../final details: - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] description: NA12878-1 metadata: sex: female validate_batch: giab validate_sample: giab-hg38 analysis: variant2 genome_build: hg38 algorithm: aligner: bwa save_diskspace: true mark_duplicates: true recalibrate: false realign: false remove_lcr: true tools_off: [vqsr] variantcaller: [freebayes, gatk-haplotype] validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-1 # metadata: # sex: female # validate_batch: giab # validate_sample: remap-hg38 # analysis: variant2 # genome_build: hg38 # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: giab-NA12878-remap/truth_small_variants.vcf.gz # validate_regions: giab-NA12878-remap/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-2 # metadata: # sex: female # validate_batch: giab # validate_sample: remap-hg38-noalt # analysis: variant2 # genome_build: hg38-noalt # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: giab-NA12878-remap/truth_small_variants.vcf.gz # validate_regions: giab-NA12878-remap/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-3 # metadata: # sex: female # validate_batch: giab # validate_sample: GRCh37 # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: giab-NA12878/truth_small_variants.vcf.gz # validate_regions: giab-NA12878/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-4 # metadata: # sex: female # validate_batch: giab # validate_sample: crossmap-hg38 # analysis: variant2 # genome_build: hg38 # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: giab-NA12878-crossmap/truth_small_variants.vcf.gz # validate_regions: giab-NA12878-crossmap/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-5 # metadata: # sex: female # validate_batch: giab # validate_sample: crossmap-hg38-noalt # analysis: variant2 # genome_build: hg38-noalt # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: giab-NA12878-crossmap/truth_small_variants.vcf.gz # validate_regions: giab-NA12878-crossmap/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-6 # metadata: # sex: female # validate_batch: platinum # validate_sample: hg19 # analysis: variant2 # genome_build: hg19 # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: platinum-genome-NA12878/truth_small_variants.vcf.gz # validate_regions: platinum-genome-NA12878/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-7 # metadata: # sex: female # validate_batch: platinum # validate_sample: hg38 # analysis: variant2 # genome_build: hg38 # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: platinum-genome-NA12878/truth_small_variants.vcf.gz # validate_regions: platinum-genome-NA12878/truth_regions.bed # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-8 # metadata: # sex: female # validate_batch: platinum # validate_sample: hg38-noalt # analysis: variant2 # genome_build: hg38-noalt # algorithm: # aligner: bwa # mark_duplicates: true # recalibrate: false # realign: false # remove_lcr: true # tools_off: [vqsr] # variantcaller: [freebayes, gatk-haplotype] # validate: platinum-genome-NA12878/truth_small_variants.vcf.gz # validate_regions: platinum-genome-NA12878/truth_regions.bed bcbio-nextgen-1.2.9/config/examples/NA12878-illumina.yaml000066400000000000000000000014601415626112400227410ustar00rootroot00000000000000# Example configuration for running a whole genome variant calling # pipeline on public NA12878 data from Illumina's Platinum Genome project # http://www.illumina.com/platinumgenomes/ # # For a quick-start guide to running this analysis, see the example # pipeline section of the documentation: # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines --- upload: dir: ../final fc_date: '130327' fc_name: iplat details: - algorithm: aligner: bwa variantcaller: gatk-haplotype validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed analysis: variant2 description: NA12878 genome_build: GRCh37 metadata: sex: female files: [../input/ERR091571_1.fastq.gz, ../input/ERR091571_2.fastq.gz] bcbio-nextgen-1.2.9/config/examples/NA12878-sv-getdata.sh000077500000000000000000000021021415626112400226330ustar00rootroot00000000000000#!/bin/bash # # Prepare a run directory for structural variant evaluations for NA12878 against # Genome in a Bottle truth sets of deletions and insertions. # # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines # set -eu -o pipefail mkdir -p config cd config wget -c https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-sv.yaml cd .. mkdir -p input cd input # Genome data wget -c -O NA12878_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_1.fastq.gz wget -c -O NA12878_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_2.fastq.gz # Validation data wget -O - ftp://ftp.ncbi.nih.gov/giab/ftp/technical/svclassify_Manuscript/Supplementary_Information/Personalis_1000_Genomes_deduplicated_deletions.bed | grep -v ^Chr > giab-svclassify-deletions-2015-05-22.bed wget -O - ftp://ftp.ncbi.nih.gov/giab/ftp/technical/svclassify_Manuscript/Supplementary_Information/Spiral_Genetics_insertions.bed | grep -v ^Chr > giab-svclassify-insertions-2015-05-22.bed cd .. mkdir -p work bcbio-nextgen-1.2.9/config/examples/NA12878-sv.yaml000066400000000000000000000017121415626112400215570ustar00rootroot00000000000000# Evaluate structural variant calling on NA12878 whole genome data, # using validated deletions and insertions from the Genome in a Bottle svclassify project # https://groups.google.com/d/msg/genome-in-a-bottle/v3EDUgZT0Xo/eGYsQlJk2JMJ # # See the bcbio-nextgen documentation for full instructions to # run this analysis: # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines --- details: - algorithm: aligner: bwa align_split_size: 5000000 recalibrate: false realign: false variantcaller: false remove_lcr: true svcaller: [lumpy, manta, cnvkit, metasv, wham] svvalidate: DEL: ../input/giab-svclassify-deletions-2015-05-22.bed INS: ../input/giab-svclassify-insertions-2015-05-22.bed analysis: variant2 description: NA12878 files: - ../input/NA12878_1.fastq.gz - ../input/NA12878_2.fastq.gz genome_build: GRCh37 metadata: batch: ceu sex: female upload: dir: ../final bcbio-nextgen-1.2.9/config/examples/NA12878-trio-wgs-joint.yaml000066400000000000000000000163361415626112400240330ustar00rootroot00000000000000# Configuration comparing alignment methods and variant callers # for a CEPH NA12878 whole genome trio, using Illumina platinum # genome inputs and Genome in a Bottle reference calls. # # Compares 4 variant callers: FreeBayes, GATKHaplotype, Platypus, samtools # Compares 3 calling method: batched concurrently, separate with joint recalling and single sample # Compares SNAP and bwa aligners # # See the bcbio-nextgen documentation for full instructions to # run this analysis: # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines --- upload: dir: ../final details: # bwa, batch calling - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] description: NA12878-1 metadata: batch: ceph-bwa sex: female analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: [freebayes, gatk-haplotype, platypus, samtools] remove_lcr: true validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed - files: [../input/NA12891_1.fastq.gz, ../input/NA12891_2.fastq.gz] description: NA12891-1 metadata: batch: ceph-bwa sex: male analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: [freebayes, gatk-haplotype, platypus, samtools] - files: [../input/NA12892_1.fastq.gz, ../input/NA12892_2.fastq.gz] description: NA12892-1 metadata: batch: ceph-bwa sex: female analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: [freebayes, gatk-haplotype, platypus, samtools] # bwa, joint calling - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] description: NA12878-3 metadata: batch: ceph-bwa-j sex: female analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: [freebayes, gatk-haplotype, platypus, samtools] jointcaller: [freebayes-joint, gatk-haplotype-joint, platypus-joint, samtools-joint] remove_lcr: true validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed - files: [../input/NA12891_1.fastq.gz, ../input/NA12891_2.fastq.gz] description: NA12891-3 metadata: batch: ceph-bwa-j sex: male analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: [freebayes, gatk-haplotype, platypus, samtools] jointcaller: [freebayes-joint, gatk-haplotype-joint, platypus-joint, samtools-joint] - files: [../input/NA12892_1.fastq.gz, ../input/NA12892_2.fastq.gz] description: NA12892-3 metadata: batch: ceph-bwa-j sex: female analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: [freebayes, gatk-haplotype, platypus, samtools] jointcaller: [freebayes-joint, gatk-haplotype-joint, platypus-joint, samtools-joint] # bwa, single sample calling - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] description: NA12878-5 metadata: sex: female analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: [freebayes, gatk-haplotype, platypus, samtools] remove_lcr: true validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed # # snap, batch calling # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-2 # metadata: # batch: ceph-snap # sex: female # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: snap # mark_duplicates: true # recalibrate: false # realign: false # variantcaller: [freebayes, gatk-haplotype, platypus] # remove_lcr: true # validate: giab-NA12878/truth_small_variants.vcf.gz # validate_regions: giab-NA12878/truth_regions.bed # - files: [../input/NA12891_1.fastq.gz, ../input/NA12891_2.fastq.gz] # description: NA12891-2 # metadata: # batch: ceph-snap # sex: male # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: snap # mark_duplicates: true # recalibrate: false # realign: false # variantcaller: [freebayes, gatk-haplotype, platypus] # - files: [../input/NA12892_1.fastq.gz, ../input/NA12892_2.fastq.gz] # description: NA12892-2 # metadata: # batch: ceph-snap # sex: female # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: snap # mark_duplicates: true # recalibrate: false # realign: false # variantcaller: [freebayes, gatk-haplotype, platypus] # # snap, joint calling # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-4 # metadata: # batch: ceph-snap-j # sex: female # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: snap # mark_duplicates: true # recalibrate: false # realign: false # variantcaller: [freebayes, gatk-haplotype, platypus] # jointcaller: [freebayes-joint, gatk-haplotype-joint, platypus-joint] # remove_lcr: true # validate: giab-NA12878/truth_small_variants.vcf.gz # validate_regions: giab-NA12878/truth_regions.bed # - files: [../input/NA12891_1.fastq.gz, ../input/NA12891_2.fastq.gz] # description: NA12891-4 # metadata: # batch: ceph-snap-j # sex: male # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: snap # mark_duplicates: true # recalibrate: false # realign: false # variantcaller: [freebayes, gatk-haplotype, platypus] # jointcaller: [freebayes-joint, gatk-haplotype-joint, platypus-joint] # - files: [../input/NA12892_1.fastq.gz, ../input/NA12892_2.fastq.gz] # description: NA12892-4 # metadata: # batch: ceph-snap-j # sex: female # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: snap # mark_duplicates: true # recalibrate: false # realign: false # variantcaller: [freebayes, gatk-haplotype, platypus] # jointcaller: [freebayes-joint, gatk-haplotype-joint, platypus-joint] # # snap, single sample calling # - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] # description: NA12878-6 # metadata: # sex: female # analysis: variant2 # genome_build: GRCh37 # algorithm: # aligner: snap # mark_duplicates: true # recalibrate: false # realign: false # variantcaller: [freebayes, gatk-haplotype, platypus] # remove_lcr: true # validate: giab-NA12878/truth_small_variants.vcf.gz # validate_regions: giab-NA12878/truth_regions.bed bcbio-nextgen-1.2.9/config/examples/NA12878-trio-wgs-validate-getdata.sh000077500000000000000000000012311415626112400255470ustar00rootroot00000000000000#!/bin/bash set -eu -o pipefail # Genome data wget -c -O NA12878_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_1.fastq.gz wget -c -O NA12878_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_2.fastq.gz wget -c -O NA12891_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194160/ERR194160_1.fastq.gz wget -c -O NA12891_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194160/ERR194160_2.fastq.gz wget -c -O NA12892_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194161/ERR194161_1.fastq.gz wget -c -O NA12892_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194161/ERR194161_2.fastq.gz bcbio-nextgen-1.2.9/config/examples/NA12878-trio-wgs-validate.yaml000066400000000000000000000030271415626112400244720ustar00rootroot00000000000000# Configuration comparing alignment methods, preparation approaches # and variant callers for a CEPH NA12878 whole genome trio, using Illumina platinum # genome inputs and Genome in a Bottle reference calls. # # See the bcbio-nextgen documentation for full instructions to # run this analysis: # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines --- upload: dir: ../final details: - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] description: NA12878 metadata: batch: ceph sex: female analysis: variant2 genome_build: hg38 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: gatk-haplotype remove_lcr: true validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed - files: [../input/NA12891_1.fastq.gz, ../input/NA12891_2.fastq.gz] description: NA12891 metadata: batch: ceph sex: male analysis: variant2 genome_build: hg38 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: gatk-haplotype - files: [../input/NA12892_1.fastq.gz, ../input/NA12892_2.fastq.gz] description: NA12892 metadata: batch: ceph sex: female analysis: variant2 genome_build: hg38 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false variantcaller: gatk-haplotype bcbio-nextgen-1.2.9/config/examples/NA12878.validate.sh000077500000000000000000000022321415626112400223720ustar00rootroot00000000000000#!/bin/bash # validate a vcf file against genome in a bottle calls for NA12878 # $1 - variants.vcf.gz # #2 - giab file, i.e. bcbio/genomes/Hsapiens/GRCh37/validation/giab-NA12878/truth_small_variants.vcf.gz # $3 - regions.bed # $4 - rtg sdf reference, i.e. bcbio/genomes/Hsapiens/GRCh37/rtg/GRCh37.sdf # rtg manual # https://github.com/RealTimeGenomics/rtg-tools/blob/master/installer/resources/tools/RTGOperationsManual.pdf # how bed file is produced in bcbio # bedtools intersect -nonamecheck -a NA12878-sort-callable_sample.bed -b GiaB_v2_19_regions.bed > NA12878-sort-callable_sample-NA12878-wrm.bed # uses PASS variants only # use --vc-score-field='QUAL' for vardict # memory demanding 10G # same script works for hg38, use hg38 truth set, bed and SDF export RTG_JAVA_OPTS='-Xms750m' && export RTG_MEM=9100m && \ rtg vcfeval --threads 5 \ -b $2 \ --bed-regions $3 \ -c $1 \ -t $4 \ -o rtg --vcf-score-field='GQ' # --all-records for f in {tp-baseline,fp,fn} do echo snp $f `bcftools view --types snps rtg/$f.vcf.gz | grep -vc "^#"` >> $1.stat echo indels $f `bcftools view --exclude-types snps rtg/$f.vcf.gz | grep -vc "^#"` >> $1.stat done bcbio-nextgen-1.2.9/config/examples/NA24385-10x-getdata.sh000077500000000000000000000026201415626112400226140ustar00rootroot00000000000000#!/bin/bash # Germline small and structural variant analysis of NA24385 against Genome in a Bottle references # Uses 50x HiSeq x10 dataset from 10x genomics: # https://support.10xgenomics.com/de-novo-assembly/datasets # http://biorxiv.org/content/early/2016/08/19/070425 set -eu -o pipefail CORES=4 mkdir -p input cd input # Input prep method from raw files # # aws s3 cp --source-region us-west-2 s3://10x.files/samples/assembly/msNA24385/msNA24385_fastqs.tar . # wget -O - https://s3-us-west-2.amazonaws.com/10x.files/samples/assembly/msNA24385/msNA24385_fastqs.tar | tar -xvp # # combine, de-interleave and bgzip the fastq files # # https://gist.github.com/nathanhaigh/3521724 # OUT1=NA24385_1.fastq.gz # OUT2=NA24385_2.fastq.gz # zcat 25534_FlowCell0/read-RA_si-*.fastq.gz | paste - - - - - - - - | tee >(cut -f 1-4 | tr "\t" "\n" | pbgzip -c -n $CORES > $OUT1) | cut -f 5-8 | tr "\t" "\n" | pbgzip -c -n $CORES > $OUT2 # zcat 25534_FlowCell0/read-I1_si-*.fastq.gz | pbgzip -c -n $CORES > NA24385_index.fastq.gz # Generated files moved to # s3://biodata/giab/na24385/ wget -c --no-check-certificate https://s3.amazonaws.com/biodata/giab/na24385/NA24385_1.fastq.gz wget -c --no-check-certificate https://s3.amazonaws.com/biodata/giab/na24385/NA24385_2.fastq.gz cd .. mkdir -p config cd config wget -c https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA24385-10x.yaml cd .. mkdir -p work bcbio-nextgen-1.2.9/config/examples/NA24385-10x.yaml000066400000000000000000000021501415626112400215300ustar00rootroot00000000000000# Germline small and structural variant analysis of NA24385 against Genome in a Bottle references # Uses 50x HiSeq x10 dataset from 10x genomics: # https://support.10xgenomics.com/de-novo-assembly/datasets # http://biorxiv.org/content/early/2016/08/19/070425 --- upload: dir: ../final #resources: # sentieon: # keyfile: /mnt/work/bcbio/license/Harvard_Chapman_eval.lic details: - files: [../input/NA24385_1.fastq.gz, ../input/NA24385_2.fastq.gz] description: NA24385 metadata: sex: male analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa trim_ends: [23, 0, 1, 0] save_diskspace: true remove_lcr: true variantcaller: [freebayes, gatk-haplotype, strelka2] svcaller: [cnvkit, seq2c, manta, delly] # lumpy, gridss, wham vcfanno: [gemini] tools_off: [vqsr, gemini] validate: giab-NA24385/truth_small_variants.vcf.gz validate_regions: giab-NA24385/truth_regions.bed validate: giab-NA24385/truth_sv.vcf.gz #sv_regions: capture_regions/Exome-AZ_V2 #svvalidate: # DEL: giab-NA24385/truth_DEL_crowd.bed.gz bcbio-nextgen-1.2.9/config/examples/archived/000077500000000000000000000000001415626112400211215ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/examples/archived/NA12878-trio-sv-getdata.sh000077500000000000000000000014001415626112400253730ustar00rootroot00000000000000#!/bin/bash set -eu -o pipefail # Genome data wget -O NA12878_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_1.fastq.gz wget -O NA12878_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_2.fastq.gz wget -O NA12891_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194160/ERR194160_1.fastq.gz wget -O NA12891_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194160/ERR194160_2.fastq.gz wget -O NA12892_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194161/ERR194161_1.fastq.gz wget -O NA12892_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194161/ERR194161_2.fastq.gz # Validation data wget https://s3.amazonaws.com/bcbio_nextgen/NA12878.50X.ldgp.molpb_val.20140508.bed.gz gunzip *.bed.gz bcbio-nextgen-1.2.9/config/examples/archived/NA12878-trio-sv.yaml000066400000000000000000000031451415626112400243210ustar00rootroot00000000000000# Evaluate structural variant calling on NA12878 whole genome trio, # using Illumina platinum genome inputs and validated breakpoints from the LUMPY paper # (http://genomebiology.com/2014/15/6/R84/abstract). # # See the bcbio-nextgen documentation for full instructions to # run this analysis: # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines --- details: - algorithm: aligner: bwa align_split_size: 5000000 recalibrate: false realign: false variantcaller: false remove_lcr: true svcaller: [cn.mops, lumpy, delly] svvalidate: DEL: ../input/NA12878.50X.ldgp.molpb_val.20140508.bed analysis: variant2 description: NA12878 files: - ../input/NA12878_1.fastq.gz - ../input/NA12878_2.fastq.gz genome_build: GRCh37 metadata: batch: ceu sex: female - algorithm: aligner: bwa align_split_size: 5000000 recalibrate: false realign: false variantcaller: false remove_lcr: true svcaller: [cn.mops, lumpy, delly] analysis: variant2 description: NA12891 files: - ../input/NA12891_1.fastq.gz - ../input/NA12891_2.fastq.gz genome_build: GRCh37 metadata: batch: ceu sex: male - algorithm: aligner: bwa align_split_size: 5000000 recalibrate: false realign: false variantcaller: false remove_lcr: true svcaller: [cn.mops, lumpy, delly] analysis: variant2 description: NA12892 files: - ../input/NA12892_1.fastq.gz - ../input/NA12892_2.fastq.gz genome_build: GRCh37 metadata: batch: ceu sex: female fc_date: '2014-07-05' fc_name: ceu upload: dir: ../final bcbio-nextgen-1.2.9/config/examples/cancer-dream-syn3-getdata.sh000077500000000000000000000033471415626112400245240ustar00rootroot00000000000000#!/bin/bash set -eu -o pipefail # Retrieve data for doing cancer calling evaluation using synthetic dataset 3 # from the ICGC-TCGA DREAM challenge: # https://www.synapse.org/#!Synapse:syn312572/wiki/62018 # Full input data #wget --no-check-certificate https://cghub.ucsc.edu/software/downloads/GeneTorrent/3.8.5a/GeneTorrent-download-3.8.5a-94-CentOS5.8.x86_64.tar.gz #tar -xzvpf GeneTorrent-download-3.8.5a-94-CentOS5.8.x86_64.tar.gz #cghub/bin/gtdownload -v -c http://dream.annailabs.com/dream_public.pem -d https://dream.annailabs.com/cghub/data/analysis/download/b19d76a0-a487-4c50-8f9c-3b4d5e53239d #ln -s b19d76a0-a487-4c50-8f9c-3b4d5e53239d/*.bam #ln -s b19d76a0-a487-4c50-8f9c-3b4d5e53239d/*.bam.bai #cghub/bin/gtdownload -v -c http://dream.annailabs.com/dream_public.pem -d https://dream.annailabs.com/cghub/data/analysis/download/8fe6fc33-2daf-4393-929f-7c3493d04bef #ln -s 8fe6fc33-2daf-4393-929f-7c3493d04bef/*.bam #ln -s 8fe6fc33-2daf-4393-929f-7c3493d04bef/*.bam.bai # Exome only data wget https://s3.amazonaws.com/bcbio_nextgen/dream/synthetic_challenge_set3_normal_NGv3_1.fq.gz wget https://s3.amazonaws.com/bcbio_nextgen/dream/synthetic_challenge_set3_normal_NGv3_2.fq.gz wget https://s3.amazonaws.com/bcbio_nextgen/dream/synthetic_challenge_set3_tumor_NGv3_1.fq.gz wget https://s3.amazonaws.com/bcbio_nextgen/dream/synthetic_challenge_set3_tumor_NGv3_2.fq.gz # Evaluation data and BED files wget https://s3.amazonaws.com/bcbio_nextgen/dream/synthetic_challenge_set3_tumor_20pctmasked_truth.tar.gz tar -xzvpf synthetic_challenge_set3_tumor_20pctmasked_truth.tar.gz wget -O refseq-merged.bed.gz https://s3.amazonaws.com/bcbio_nextgen/dream/refseq-merged.bed.gz wget -O NGv3.bed.gz https://s3.amazonaws.com/bcbio_nextgen/NGv3.bed.gz gunzip *.bed.gz bcbio-nextgen-1.2.9/config/examples/cancer-dream-syn3.yaml000066400000000000000000000024071415626112400234360ustar00rootroot00000000000000# Cancer tumor/normal calling evaluation using synthetic dataset 3 # from the ICGC-TCGA DREAM challenge: # https://www.synapse.org/#!Synapse:syn312572/wiki/62018 --- details: - algorithm: aligner: bwa mark_duplicates: true remove_lcr: true variantcaller: [mutect2, vardict] variant_regions: /path/to/bcbio/genomes/Hsapiens/hg38/coverage/capture_regions/NGv3.bed # svcaller: [cnvkit, lumpy, delly] # coverage_interval: amplicon analysis: variant2 description: syn3-normal #files: ../input/synthetic.challenge.set3.normal.bam files: - ../input/synthetic_challenge_set3_normal_NGv3_1.fq.gz - ../input/synthetic_challenge_set3_normal_NGv3_2.fq.gz genome_build: hg38 metadata: batch: syn3 phenotype: normal - algorithm: aligner: bwa mark_duplicates: true remove_lcr: true variantcaller: [mutect2, vardict] variant_regions: /path/to/bcbio/genomes/Hsapiens/hg38/coverage/capture_regions/NGv3.bed analysis: variant2 description: syn3-tumor #files: ../input/synthetic.challenge.set3.tumor.bam files: - ../input/synthetic_challenge_set3_tumor_NGv3_1.fq.gz - ../input/synthetic_challenge_set3_tumor_NGv3_2.fq.gz genome_build: hg38 metadata: batch: syn3 phenotype: tumor upload: dir: ../final bcbio-nextgen-1.2.9/config/examples/cancer-dream-syn4.yaml000066400000000000000000000063111415626112400234350ustar00rootroot00000000000000# Cancer tumor/normal calling evaluation using synthetic dataset 4 # from the ICGC-TCGA DREAM challenge: # https://www.synapse.org/#!Synapse:syn412572/wiki/62018 --- details: - algorithm: aligner: bwa align_split_size: 5000000 mark_duplicates: true recalibrate: false realign: false remove_lcr: true platform: illumina quality_format: standard tools_on: [svplots] variantcaller: [vardict, mutect2, mutect, freebayes, varscan] indelcaller: scalpel svprioritize: cancer/az300 ensemble: numpass: 2 # svcaller: [battenberg, cnvkit, lumpy, manta, metasv, wham] # hetcaller: [theta, bubbletree] analysis: variant2 description: syn4-normal files: ../input/synthetic.challenge.set4.normal.bam genome_build: GRCh37 metadata: batch: syn4 phenotype: normal - algorithm: aligner: bwa align_split_size: 5000000 mark_duplicates: true recalibrate: false realign: false remove_lcr: true platform: illumina quality_format: standard tools_on: [svplots] variantcaller: [vardict, mutect2, mutect, freebayes, varscan] indelcaller: scalpel svprioritize: cancer/az300 ensemble: numpass: 2 #svcaller: [battenberg, cnvkit, lumpy, manta, metasv, wham] #svprioritize: cancer/civic #hetcaller: [theta, bubbletree] validate: dream-syn4/truth_small_variants.vcf.gz validate_regions: dream-syn4/truth_regions.bed svvalidate: DEL: dream-syn4/truth_DEL.bed DUP: dream-syn4/truth_DUP.bed INV: dream-syn4/truth_INV.bed analysis: variant2 description: syn4-tumor files: ../input/synthetic.challenge.set4.tumour.bam genome_build: GRCh37 metadata: batch: syn4 phenotype: tumor validate_sample: DREAM synthetic 4 (GRCh37) - algorithm: aligner: bwa align_split_size: 5000000 mark_duplicates: true recalibrate: false realign: false remove_lcr: true platform: illumina quality_format: standard variantcaller: [vardict, mutect2, mutect, freebayes, varscan] indelcaller: scalpel #svcaller: [lumpy, metasv, manta, wham] #hetcaller: [theta, bubbletree] analysis: variant2 description: syn4-38-normal files: ../input/synthetic.challenge.set4.normal.bam genome_build: hg38 metadata: batch: syn4-38 phenotype: normal - algorithm: aligner: bwa align_split_size: 5000000 mark_duplicates: true recalibrate: false realign: false remove_lcr: true platform: illumina quality_format: standard variantcaller: [vardict, mutect2, mutect, freebayes, varscan] indelcaller: scalpel #svcaller: [lumpy, metasv, manta, wham] #hetcaller: [theta, bubbletree] validate: dream-syn4-crossmap/truth_small_variants.vcf.gz validate_regions: dream-syn4-crossmap/truth_regions.bed svvalidate: DEL: dream-syn4-crossmap/truth_DEL.bed DUP: dream-syn4-crossmap/truth_DUP.bed INV: dream-syn4-crossmap/truth_INV.bed analysis: variant2 description: syn4-38-tumor files: ../input/synthetic.challenge.set4.tumour.bam genome_build: hg38 metadata: batch: syn4-38 phenotype: tumor validate_sample: DREAM synthetic 4 (hg38) fc_date: '2015-08-17' fc_name: dream-syn4 upload: dir: ../final bcbio-nextgen-1.2.9/config/examples/cancer-giab-na12878-na24385-getdata.sh000077500000000000000000000017741415626112400254560ustar00rootroot00000000000000#!/bin/bash # # Cancer-like mixture of two Genome in a Bottle samples (NA12878 and NA24385) # ftp://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/use_cases/mixtures/UMCUTRECHT_NA12878_NA24385_mixture_10052016/ set -eu -o pipefail mkdir -p config cd config wget -c https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/cancer-giab-na12878-na24385.yaml cd .. base_url=ftp://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/use_cases/mixtures/UMCUTRECHT_NA12878_NA24385_mixture_10052016 mkdir -p input cd input # Genome data wget -c $base_url/README-NA12878_NA24385_mixture.txt wget -c $base_url/24385-12878-30-200_R1_001.fastq.gz wget -c $base_url/24385-12878-30-200_R2_001.fastq.gz wget -c $base_url/24385-200_AH5G7WCCXX_S4_L004_R1_001.fastq.gz wget -c $base_url/24385-200_AH5G7WCCXX_S4_L004_R2_001.fastq.gz # Truth sets wget -c $base_url/na12878-na24385-somatic-truth-regions.bed wget -c $base_url/na12878-na24385-somatic-truth.vcf.gz wget -c $base_url/na12878-na24385-somatic-truth.vcf.gz.tbi cd .. mkdir -p work bcbio-nextgen-1.2.9/config/examples/cancer-giab-na12878-na24385.yaml000066400000000000000000000024101415626112400243600ustar00rootroot00000000000000details: - algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false platform: illumina quality_format: standard variantcaller: [vardict, mutect2, freebayes, mutect, varscan, tnhaplotyper] ensemble: numpass: 2 validate: ../input/na12878-na24385-somatic-truth.vcf.gz validate_regions: ../input/na12878-na24385-somatic-truth-regions.bed analysis: variant2 description: 24385-12878-30-200 files: [../input/24385-12878-30-200_R1_001.fastq.gz, ../input/24385-12878-30-200_R2_001.fastq.gz] genome_build: GRCh37 metadata: batch: 24385 phenotype: tumor validate_sample: NA12878/NA24385 mixture - algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false platform: illumina quality_format: standard variantcaller: [vardict, mutect2, freebayes, mutect, varscan, tnhaplotyper] ensemble: numpass: 2 analysis: variant2 description: 24385-200 files: [../input/24385-200_AH5G7WCCXX_S4_L004_R1_001.fastq.gz, ../input/24385-200_AH5G7WCCXX_S4_L004_R2_001.fastq.gz] genome_build: GRCh37 metadata: batch: 24385 phenotype: normal validate_sample: NA12878/NA24385 mixture fc_date: '20161212' fc_name: giab-mixture upload: dir: ../final bcbio-nextgen-1.2.9/config/examples/chip_seq.yaml000066400000000000000000000012171415626112400220140ustar00rootroot00000000000000details: - algorithm: aligner: bowtie2 chip_method: chip peakcaller: macs2 quality_format: standard trim_reads: read_through analysis: chip-seq description: sample_input files: - /path/project/sample_input.fq.gz genome_build: GRCh37 metadata: batch: b_pair phenotype: input - algorithm: aligner: bowtie2 chip_method: chip peakcaller: macs2 quality_format: standard trim_reads: read_through analysis: chip-seq description: sample_chip files: - /path/project/sample_chip.fq.gz genome_build: GRCh37 metadata: batch: b_pair phenotype: chip upload: dir: /path/project/final bcbio-nextgen-1.2.9/config/examples/giab-validate-setup.sh000077500000000000000000000014711415626112400235250ustar00rootroot00000000000000#!/bin/bash # # Prepare a run directory for evaluations against # Genome in a Bottle truth sets. # # https://bcbio-nextgen.readthedocs.org/en/latest/contents/testing.html#example-pipelines # set -eu -o pipefail mkdir -p config cd config wget -c https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/giab-validate.yaml cd .. mkdir -p input cd input # Genome data wget -c -O NA12878_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_1.fastq.gz wget -c -O NA12878_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147_2.fastq.gz wget -c -O NA24385_60x.bam ftp://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/AshkenazimTrio/HG002_NA24385_son/NIST_HiSeq_HG002_Homogeneity-10953946/NHGRI_Illumina300X_AJtrio_novoalign_bams/HG002.hs37d5.60x.1.bam cd .. mkdir -p work bcbio-nextgen-1.2.9/config/examples/giab-validate.yaml000066400000000000000000000024741415626112400227200ustar00rootroot00000000000000# Run multiple sample validations using Genome in a Bottle inputs # # Samples: # - NA12878 -- Caucasian female # - NA24385 -- Ashkenazim son # # http://jimb.stanford.edu/giab --- upload: dir: ../final details: - files: [../input/NA12878_1.fastq.gz, ../input/NA12878_2.fastq.gz] description: NA12878-bwa metadata: sex: female validate_batch: NA12878 validate_sample: bwa analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false remove_lcr: true tools_off: [vqsr, gemini] variantcaller: [samtools, freebayes, platypus, gatk-haplotype] validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed - files: [../input/NA24385_60x.bam] description: NA24385-bwa metadata: sex: male validate_batch: NA24385 validate_sample: bwa analysis: variant2 genome_build: GRCh37 algorithm: aligner: bwa mark_duplicates: true recalibrate: false realign: false remove_lcr: true tools_off: [vqsr, gemini] variantcaller: [samtools, freebayes, platypus, gatk-haplotype] validate: giab-NA24385/truth_small_variants.vcf.gz validate_regions: giab-NA24385/truth_regions.bed bcbio-nextgen-1.2.9/config/examples/mitochondrial_variants_amplicons.yaml000066400000000000000000000021661415626112400270350ustar00rootroot00000000000000# mitochondrial variant calling from Amplicon sequencing # using mutect2 - somatic caller and tumor phenotype # more elaborated approach: # - https://gatk.broadinstitute.org/hc/en-us/community/posts/360056028651-GATK-Best-Practices-Mitochondrial-Analysis # - https://gatkforums.broadinstitute.org/gatk/discussion/23598/new-mitochondrial-analysis-with-mutect2#latest # no alignment, because amplicon already captures mt Read and alignment will map them back to autosomes which have nuclear mt DNA segments # mt.bed in grch37: MT 1 16569 details: - algorithm: aligner: false bam_clean: picard coverage_interval: amplicon effects: vep effects_transcripts: all realign: false recalibrate: false mark_duplicates: true save_diskspace: true tools_on: - vep_splicesite_annotations variantcaller: - mutect2 variant_regions: /path/mt.bed analysis: variant2 description: sample files: - /path/input/sample.MT.bam genome_build: GRCh37 metadata: phenotype: tumor resources: default: cores: 7 jvm_opts: - -Xms750m - -Xmx7000m memory: 7G upload: dir: ../final bcbio-nextgen-1.2.9/config/examples/rnaseq-seqc-getdata.sh000077500000000000000000000020231415626112400235210ustar00rootroot00000000000000#!/bin/bash set -eu -o pipefail # We need about 100Gb for the input files. Confirm we have the space. REQ_DISK_SPACE=100 df --block-size=G --output='avail' . | sed s/G//g | awk -v req_disk_space=${REQ_DISK_SPACE} '{ if ($1 !~ /Avail/ && $1 < req_disk_space ) printf("Warning: Not enough disk space.\n Warning: Requires %sGb in total but only has %sGb.\n", req_disk_space, $1) }' mkdir -p seqc/input wget --no-check-certificate https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/rnaseq-seqc.yaml cd seqc/input for SAMPLE in SRR950078 SRR950079 SRR950080 SRR950081 SRR950082 SRR950083 do wget -c -O ${SAMPLE}_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR950/${SAMPLE}/${SAMPLE}_1.fastq.gz wget -c -O ${SAMPLE}_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR950/${SAMPLE}/${SAMPLE}_2.fastq.gz done cd ../../ wget -c --no-check-certificate https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/seqc.csv bcbio_nextgen.py -w template rnaseq-seqc.yaml seqc.csv seqc/input/*.gz bcbio-nextgen-1.2.9/config/examples/rnaseq-seqc.yaml000066400000000000000000000004411415626112400224410ustar00rootroot00000000000000# Template for human RNA-seq using Illumina prepared samples --- details: - analysis: RNA-seq genome_build: hg38 algorithm: quality_format: standard aligner: star strandedness: unstranded upload: dir: ../final resources: star: cores: 10 memory: 10G bcbio-nextgen-1.2.9/config/examples/rnaseq.variant_calling.yaml000066400000000000000000000006421415626112400246470ustar00rootroot00000000000000# variant calling in RNA-seq using gatk3.x details: - algorithm: aligner: star variantcaller: gatk-haplotype tools_off: - gatk4 strandedness: unstranded analysis: RNA-seq description: AN-C1-1 files: - /path/to/file_1.fq.gz - /path/to/file_2.fq.gz genome_build: hg38 resources: default: cores: 4 jvm_opts: - -Xms750m - -Xmx7000m memory: 15G upload: dir: ../final bcbio-nextgen-1.2.9/config/examples/seqc.csv000066400000000000000000000002661415626112400210100ustar00rootroot00000000000000samplename,description,category SRR950078,UHRR_rep1,UHRR SRR950079,HBRR_rep1,HBRR SRR950080,UHRR_rep2,UHRR SRR950081,HBRR_rep2,HBRR SRR950082,UHRR_rep3,UHRR SRR950083,HBRR_rep3,HBRR bcbio-nextgen-1.2.9/config/examples/somatic_tumor_normal_gatkcnv.yaml000066400000000000000000000035431415626112400261770ustar00rootroot00000000000000details: - algorithm: align_split_size: false aligner: bwa coverage: /path/coverage.bed coverage_interval: regional effects_transcripts: canonical_cancer hlacaller: optitype mark_duplicates: true min_allele_fraction: 1 platform: Illumina quality_format: Standard realign: false recalibrate: false sv_regions: /path/variants.bed svcaller: - manta - seq2c - gatk-cnv - purecn svprioritize: cancer/az-cancer-panel tools_off: - gemini tools_on: - qualimap_full - damage_filter - gatk4 variant_regions: variants.bed variantcaller: germline: - gatk-haplotype somatic: - vardict vcfanno: somatic analysis: variant2 description: sample_n files: - /path/sample_n.bam genome_build: hg38 metadata: batch: sample_t_batch phenotype: normal resources: qualimap: memory: 16g - algorithm: align_split_size: false aligner: bwa coverage: /path/coverage.bed coverage_interval: regional effects_transcripts: canonical_cancer hlacaller: optitype mark_duplicates: true min_allele_fraction: 1 platform: Illumina quality_format: Standard realign: false recalibrate: false sv_regions: /path/coverage.bed svcaller: - manta - seq2c - gatk-cnv - purecn svprioritize: cancer/az-cancer-panel tools_off: - gemini tools_on: - qualimap_full - damage_filter - gatk4 variant_regions: /path/variants.bed variantcaller: germline: - gatk-haplotype somatic: - vardict vcfanno: somatic analysis: variant2 description: sample_t files: - /path/sample_t.bam genome_build: hg38 metadata: batch: sample_t_batch phenotype: tumor resources: qualimap: memory: 16g fc_name: bcbio upload: dir: ../final bcbio-nextgen-1.2.9/config/galaxy/000077500000000000000000000000001415626112400170035ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/galaxy/bcbio/000077500000000000000000000000001415626112400200615ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/galaxy/bcbio/variant.xml000066400000000000000000000051371415626112400222550ustar00rootroot00000000000000 SNP and indel detection bcbio-nextgen bcbio_nextgen.py $sample_config -n \${GALAXY_SLOTS:-1} upload: method: galaxy dir: final outputs: align: $out_align variants: $out_variants details: - analysis: variant2 genome_build: $genome_build.fields.dbkey files: [$input1, $input2] description: $name algorithm: aligner: $aligner mark_duplicates: true recalibrate: false realign: false variantcaller: $variantcaller platform: illumina quality_format: Standard variant_regions: $variant_regions SNP and indel variant calling using `bcbio-nextgen`_. .. _bcbio-nextgen: https://github.com/bcbio/bcbio-nextgen bcbio-nextgen-1.2.9/config/genomes/000077500000000000000000000000001415626112400171535ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/genomes/BDGP6-resources.yaml000066400000000000000000000004341415626112400226520ustar00rootroot00000000000000version: 22 aliases: ensembl: drosophila_melanogaster_vep_100_BDGP6.28 snpeff: BDGP6.86 srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa bcbio-nextgen-1.2.9/config/genomes/GRCh37-resources.yaml000066400000000000000000000042601415626112400230060ustar00rootroot00000000000000version: 55 aliases: human: true snpeff: GRCh37.75 ensembl: homo_sapiens_merged_vep_100_GRCh37 variation: dbsnp: ../variation/dbsnp.vcf.gz train_hapmap: ../variation/hapmap_3.3.vcf.gz train_omni: ../variation/1000G_omni2.5.vcf.gz train_1000g: ../variation/1000G_phase1.snps.high_confidence.vcf.gz train_indels: ../variation/Mills_and_1000G_gold_standard.indels.vcf.gz cosmic: ../variation/cosmic.vcf.gz clinvar: ../variation/clinvar.vcf.gz esp: ../variation/esp.vcf.gz exac: ../variation/exac.vcf.gz gnomad_exome: ../variation/gnomad_exome.vcf.gz gnomad_genome: ../variation/gnomad_genome.vcf.gz 1000g: ../variation/1000g.vcf.gz lcr: ../coverage/problem_regions/repeats/LCR.bed.gz polyx: ../coverage/problem_regions/repeats/polyx.bed.gz sv_repeat: ../coverage/problem_regions/repeats/sv_repeat_telomere_centromere.bed encode_blacklist: ../coverage/problem_regions/ENCODE/wgEncodeDacMapabilityConsensusExcludable.bed.gz gc_profile: ../coverage/gc/GC_profile.1000bp.cnp germline_het_pon: ../variation/germline_het_pon.bed.gz dbnsfp: ../variation/dbNSFP.txt.gz dbscsnv: ../variation/dbscSNV.txt.gz ancestral: ../variation/human_ancestor.fa.gz qsignature: ../variation/qsignature.vcf genesplicer: ../variation/genesplicer editing: ../editing/RADAR.bed.gz genotype2phenotype: ../variation/G2P.csv af_only_gnomad: ../variation/af_only_gnomad.vcf.gz rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/GRCh37_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa trna_fasta: ../srnaseq/trna_mature_pre.fa mint_lookup: ../srnaseq/LookupTable.tRFs.MINTmap_v1.txt mint_space: ../srnaseq/tRNAspace.Spliced.Sequences.MINTmap_v1.fa mint_other: ../srnaseq/OtherAnnotations.MINTmap_v1.txt coverage: coverage_problem_dir: ../coverage/problem_regions MIG: ../prioritization/MIG.bed bcbio-nextgen-1.2.9/config/genomes/GRCz10-resources.yaml000066400000000000000000000001161415626112400230130ustar00rootroot00000000000000version: 9 aliases: ensembl: danio_rerio_vep_91_GRCz10 snpeff: GRCz10.86 bcbio-nextgen-1.2.9/config/genomes/GRCz11-resources.yaml000066400000000000000000000001061415626112400230130ustar00rootroot00000000000000version: 7 aliases: ensembl: danio_rerio_vep_100_GRCz11 #snpeff: bcbio-nextgen-1.2.9/config/genomes/Sscrofa11.1-resources.yaml000066400000000000000000000001121415626112400237420ustar00rootroot00000000000000version: 7 aliases: ensembl: sus_scrofa_vep_100_Sscrofa11.1 #snpeff: bcbio-nextgen-1.2.9/config/genomes/TAIR10-resources.yaml000066400000000000000000000003001415626112400227400ustar00rootroot00000000000000version: 6 aliases: snpeff: athaliana130 srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa bcbio-nextgen-1.2.9/config/genomes/WBcel235-resources.yaml000066400000000000000000000001371415626112400232760ustar00rootroot00000000000000version: 18 aliases: ensembl: caenorhabditis_elegans_vep_100_WBcel235 snpeff: WBcel235.86 bcbio-nextgen-1.2.9/config/genomes/canFam3-resources.yaml000066400000000000000000000012211415626112400233130ustar00rootroot00000000000000version: 25 aliases: ensembl: canis_familiaris_vep_100_CanFam3.1 snpeff: CanFam3.1.86 variation: dbsnp: ../variation/canFam3-dbSNP-2014-05-10.vcf.gz rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/CanFam3_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa bcbio-nextgen-1.2.9/config/genomes/dm3-resources.yaml000066400000000000000000000001351415626112400225310ustar00rootroot00000000000000version: 20 aliases: ensembl: drosophila_melanogaster_vep_100_BDGP6.22 snpeff: BDGP6.86 bcbio-nextgen-1.2.9/config/genomes/galGal4-resources.yaml000066400000000000000000000001241415626112400233170ustar00rootroot00000000000000version: 14 aliases: ensembl: gallus_gallus_vep_100_Galgal4 snpeff: Galgal4.75 bcbio-nextgen-1.2.9/config/genomes/hg19-resources.yaml000066400000000000000000000045131415626112400226220ustar00rootroot00000000000000version: 57 aliases: human: true snpeff: GRCh37.75 ensembl: homo_sapiens_merged_vep_100_GRCh37 variation: dbsnp: ../variation/dbsnp.vcf.gz train_hapmap: ../variation/hapmap_3.3.vcf.gz train_omni: ../variation/1000G_omni2.5.vcf.gz train_1000g: ../variation/1000G_phase1.snps.high_confidence.vcf.gz train_indels: ../variation/Mills_and_1000G_gold_standard.indels.vcf.gz cosmic: ../variation/cosmic.vcf.gz clinvar: ../variation/clinvar.vcf.gz esp: ../variation/esp.vcf.gz exac: ../variation/exac.vcf.gz gnomad_exome: ../variation/gnomad_exome.vcf.gz gnomad_genome: ../variation/gnomad_genome.vcf.gz 1000g: ../variation/1000g.vcf.gz lcr: ../coverage/problem_regions/repeats/LCR.bed.gz polyx: ../coverage/problem_regions/repeats/polyx.bed.gz sv_repeat: ../coverage/problem_regions/repeats/sv_repeat_telomere_centromere.bed encode_blacklist: ../coverage/problem_regions/ENCODE/wgEncodeDacMapabilityConsensusExcludable.bed.gz gc_profile: ../coverage/gc/GC_profile.1000bp.cnp germline_het_pon: ../variation/germline_het_pon.bed.gz dbnsfp: ../variation/dbNSFP.txt.gz dbscsnv: ../variation/dbscSNV.txt.gz ancestral: ../variation/human_ancestor.fa.gz qsignature: ../variation/qsignature.vcf genesplicer: ../variation/genesplicer editing: ../editing/RADAR.bed.gz genotype2phenotype: ../variation/G2P.csv af_only_gnomad: ../variation/af_only_gnomad.vcf.gz purecn_mappability: ../coverage/mappability/wgEncodeCrgMapabilityAlign100mer.bigWig simple_repeat: ../coverage/problem_regions/repeats/simple_repeat.bed rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/hg19_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa trna_fasta: ../srnaseq/trna_mature_pre.fa mint_lookup: ../srnaseq/LookupTable.tRFs.MINTmap_v1.txt mint_space: ../srnaseq/tRNAspace.Spliced.Sequences.MINTmap_v1.fa mint_other: ../srnaseq/OtherAnnotations.MINTmap_v1.txt coverage: coverage_problem_dir: ../coverage/problem_regions MIG: ../prioritization/MIG.bed bcbio-nextgen-1.2.9/config/genomes/hg38-noalt-resources.yaml000066400000000000000000000024771415626112400237450ustar00rootroot00000000000000version: 30 aliases: human: true snpeff: hg38kg ensembl: homo_sapiens_merged_vep_100_GRCh38 variation: dbsnp: ../variation/dbsnp-151.vcf.gz dbnsfp: ../variation/dbNSFP.txt.gz dbscsnv: ../variation/dbscSNV.txt.gz genesplicer: ../variation/genesplicer train_hapmap: ../variation/hapmap_3.3.vcf.gz train_omni: ../variation/1000G_omni2.5.vcf.gz train_1000g: ../variation/1000G_phase1.snps.high_confidence.vcf.gz train_indels: ../variation/Mills_and_1000G_gold_standard.indels.vcf.gz cosmic: ../variation/cosmic.vcf.gz lcr: ../variation/LCR.bed.gz genotype2phenotype: ../variation/G2P.csv rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/hg38-noalt_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa trna_fasta: ../srnaseq/trna_mature_pre.fa mint_lookup: ../srnaseq/LookupTable.tRFs.MINTmap_v1.txt mint_space: ../srnaseq/tRNAspace.Spliced.Sequences.MINTmap_v1.fa mint_other: ../srnaseq/OtherAnnotations.MINTmap_v1.txt bcbio-nextgen-1.2.9/config/genomes/hg38-resources.yaml000066400000000000000000000040751415626112400226260ustar00rootroot00000000000000version: 47 aliases: human: true snpeff: GRCh38.99 ensembl: homo_sapiens_merged_vep_100_GRCh38 variation: dbsnp: ../variation/dbsnp.vcf.gz dbnsfp: ../variation/dbNSFP.txt.gz dbscsnv: ../variation/dbscSNV.txt.gz train_hapmap: ../variation/hapmap_3.3.vcf.gz train_omni: ../variation/1000G_omni2.5.vcf.gz train_1000g: ../variation/1000G_phase1.snps.high_confidence.vcf.gz train_indels: ../variation/Mills_and_1000G_gold_standard.indels.vcf.gz cosmic: ../variation/cosmic.vcf.gz clinvar: ../variation/clinvar.vcf.gz esp: ../variation/esp.vcf.gz exac: ../variation/exac.vcf.gz gnomad_exome: ../variation/gnomad_exome.vcf.gz gnomad_genome: ../variation/gnomad_genome.vcf.gz lcr: ../coverage/problem_regions/repeats/LCR.bed.gz polyx: ../coverage/problem_regions/repeats/polyx.bed.gz gc_profile: ../coverage/gc/GC_profile.1000bp.cnp germline_het_pon: ../variation/germline_het_pon.bed.gz sv_repeat: ../coverage/problem_regions/repeats/sv_repeat_telomere_centromere.bed qsignature: ../variation/qsignature.txt genesplicer: ../variation/genesplicer editing: ../editing/RADAR.bed.gz genotype2phenotype: ../variation/G2P.csv af_only_gnomad: ../variation/af_only_gnomad.vcf.gz purecn_mappability: ../coverage/mappability/GCA_000001405.15_GRCh38_no_alt_analysis_set_100.bw simple_repeat: ../coverage/problem_regions/repeats/simple_repeat.bed rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/hg38_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa trna_fasta: ../srnaseq/trna_mature_pre.fa mint_lookup: ../srnaseq/LookupTable.tRFs.MINTmap_v1.txt mint_space: ../srnaseq/tRNAspace.Spliced.Sequences.MINTmap_v1.fa mint_other: ../srnaseq/OtherAnnotations.MINTmap_v1.txt bcbio-nextgen-1.2.9/config/genomes/mm10-resources.yaml000066400000000000000000000013551415626112400226250ustar00rootroot00000000000000version: 33 aliases: snpeff: GRCm38.99 ensembl: mus_musculus_vep_100_GRCm38 variation: dbsnp: ../variation/mm10-dbSNP-2013-09-12.vcf.gz lcr: ../coverage/problem_regions/repeats/LCR.bed.gz rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/mm10_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa trna_fasta: ../srnaseq/trna_mature_pre.fa bcbio-nextgen-1.2.9/config/genomes/mm9-resources.yaml000066400000000000000000000003021415626112400225440ustar00rootroot00000000000000version: 7 rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/mm9_transcriptome.ver bcbio-nextgen-1.2.9/config/genomes/phix-resources.yaml000066400000000000000000000001301415626112400230110ustar00rootroot00000000000000# Resource file for phiX standard to allow alignments/processing in bcbio --- version: 0bcbio-nextgen-1.2.9/config/genomes/pseudomonas_aeruginosa_ucbpp_pa14-resources.yaml000066400000000000000000000001041415626112400306320ustar00rootroot00000000000000version: 1 #aliases: # ensembl: pseudomonas_aeruginosa_ucbpp_pa14 bcbio-nextgen-1.2.9/config/genomes/rn5-resources.yaml000066400000000000000000000005351415626112400225560ustar00rootroot00000000000000version: 10 aliases: snpeff: Rnor_5.0.75 rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/rn5_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa bcbio-nextgen-1.2.9/config/genomes/rn6-resources.yaml000066400000000000000000000011211415626112400225470ustar00rootroot00000000000000version: 17 aliases: ensembl: rattus_norvegicus_vep_100_Rnor_6.0 snpeff: Rnor_6.0.86 rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/rn6_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa srnaseq: srna_transcripts: ../srnaseq/srna-transcripts.gtf mirbase_hairpin: ../srnaseq/hairpin.fa mirbase_mature: ../srnaseq/mature.fa mirdeep2_fasta: ../srnaseq/Rfam_for_miRDeep.fa bcbio-nextgen-1.2.9/config/genomes/sacCer3-resources.yaml000066400000000000000000000006231415626112400233330ustar00rootroot00000000000000version: 21 aliases: ensembl: saccharomyces_cerevisiae_vep_100_R64-1-1 snpeff: R64-1-1.86 rnaseq: transcripts: ../rnaseq/ref-transcripts.gtf transcripts_mask: ../rnaseq/ref-transcripts-mask.gtf transcriptome_index: tophat: ../rnaseq/tophat/sacCer3_transcriptome.ver dexseq: ../rnaseq/ref-transcripts.dexseq.gff3 refflat: ../rnaseq/ref-transcripts.refFlat rRNA_fa: ../rnaseq/rRNA.fa bcbio-nextgen-1.2.9/config/genomes/xenTro3-resources.yaml000066400000000000000000000001311415626112400234040ustar00rootroot00000000000000version: 20 aliases: ensembl: xenopus_tropicalis_vep_100_JGI_4.2 snpeff: JGI_4.2.86 bcbio-nextgen-1.2.9/config/teaching/000077500000000000000000000000001415626112400173005ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/teaching/cancer-syn3-chr6-prep.sh000077500000000000000000000010121415626112400235620ustar00rootroot00000000000000#!/bin/bash # Setup directory for running a minimal DREAM synthetic 3 dataset # The original DREAM data is subset to exomes on chromosome 6 set -eu -o pipefail mkdir -p cancer-syn3-chr6 cd cancer-syn3-chr6 wget -c https://s3.amazonaws.com/bcbio_nextgen/dream/cancer-syn3-chr6-input.tar.gz tar -xzvpf cancer-syn3-chr6-input.tar.gz rm -f cancer-syn3-chr6-input.tar.gz mkdir -p config cd config wget -c https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/teaching/cancer-syn3-chr6.yaml cd .. mkdir -p work bcbio-nextgen-1.2.9/config/teaching/cancer-syn3-chr6.yaml000066400000000000000000000032251415626112400231530ustar00rootroot00000000000000# Cancer tumor/normal calling evaluation using synthetic dataset 3 # from the ICGC-TCGA DREAM challenge: # https://www.synapse.org/#!Synapse:syn312572/wiki/62018 # Subset to chromosome 6 for teaching purposes --- details: - algorithm: aligner: bwa align_split_size: 5000000 recalibrate: false realign: false remove_lcr: true variant_regions: ../input/NGv3-chr6-hg38.bed min_allele_fraction: 2 variantcaller: [vardict, freebayes, varscan] ensemble: numpass: 2 svcaller: [lumpy, manta] analysis: variant2 description: syn3-normal files: [../input/cancer-syn3-chr6-normal-1.fq.gz, ../input/cancer-syn3-chr6-normal-2.fq.gz] genome_build: hg38 metadata: batch: syn3 phenotype: normal sex: female - algorithm: aligner: bwa align_split_size: 5000000 recalibrate: false realign: false variant_regions: ../input/NGv3-chr6-hg38.bed min_allele_fraction: 2 variantcaller: [vardict, freebayes, varscan] ensemble: numpass: 2 svcaller: [lumpy, manta] svprioritize: cancer/civic hlacaller: optitype remove_lcr: true validate: dream-syn3-crossmap/truth_small_variants.vcf.gz validate_regions: dream-syn3-crossmap/truth_regions.bed svvalidate: DEL: dream-syn3-crossmap/truth_DEL.bed DUP: dream-syn3-crossmap/truth_DUP.bed INV: dream-syn3-crossmap/truth_INV.bed analysis: variant2 description: syn3-tumor files: [../input/cancer-syn3-chr6-tumor-1.fq.gz, ../input/cancer-syn3-chr6-tumor-2.fq.gz] genome_build: hg38 metadata: batch: syn3 phenotype: tumor sex: female fc_date: '2015-11-18' fc_name: syn3-cshl upload: dir: ../final bcbio-nextgen-1.2.9/config/templates/000077500000000000000000000000001415626112400175145ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/templates/bisulfite_seq.yaml000066400000000000000000000003661415626112400232430ustar00rootroot00000000000000details: - analysis: wgbs-seq algorithm: aligner: bismark # this option will set up the same tool for calling and alignment description: test genome_build: hg19 # files: [../../raw/test_R1.fastq, ../../raw/test_R2.fastq] bcbio-nextgen-1.2.9/config/templates/freebayes-variant.yaml000066400000000000000000000010231415626112400240030ustar00rootroot00000000000000# Template for whole genome Illumina variant calling with FreeBayes # This is a GATK-free pipeline without post-alignment BAM pre-processing # (recalibration and realignment) --- details: - analysis: variant2 genome_build: GRCh37 # to do multi-sample variant calling, assign samples the same metadata / batch # metadata: # batch: your-arbitrary-batch-name algorithm: aligner: bwa variantcaller: freebayes # for targetted projects, set the region # variant_regions: /path/to/your.bed bcbio-nextgen-1.2.9/config/templates/gatk-joint-genotyping.yaml000066400000000000000000000007671415626112400246420ustar00rootroot00000000000000 # Template for joint genotyping of gvcf inputs created with GATK --- details: - analysis: variant2 genome_build: hg38 # to do multi-sample variant calling, assign samples the same metadata / batch # metadata: # batch: your-arbitrary-batch-name algorithm: variantcaller: gatk-haplotype # for targetted projects, set the region # variant_regions: /path/to/your.bed jointcaller: gatk-haplotype-joint # set the path to your gvcf file here vrn_file: bcbio-nextgen-1.2.9/config/templates/gatk-variant.yaml000066400000000000000000000007071415626112400227740ustar00rootroot00000000000000# Template for whole genome Illumina variant calling with GATK pipeline --- details: - analysis: variant2 genome_build: hg38 # to do multi-sample variant calling, assign samples the same metadata / batch # metadata: # batch: your-arbitrary-batch-name algorithm: aligner: bwa recalibrate: gatk variantcaller: gatk-haplotype # for targetted projects, set the region # variant_regions: /path/to/your.bed bcbio-nextgen-1.2.9/config/templates/illumina-chipseq.yaml000066400000000000000000000012611415626112400236440ustar00rootroot00000000000000# Template for mouse chip-seq using Illumina prepared samples --- details: - analysis: chip-seq # In order to do paired peak calling, samples should belong to the # same batch ("batch" under "metadata" below") and have a "phenotype" # field stating either "input" or chip". For each batch there # should be a sample with "chip" phenotype and a sample with "input" # phenotype (no more than two samples per batch) metadata: batch: your-batch-name phenotype: chip # or input genome_build: mm10 algorithm: aligner: bowtie2 adapters: [truseq] trim_reads: read_through peakcaller: [macs2] resources: macs2: options: ["--broad", "-q 0.05"] bcbio-nextgen-1.2.9/config/templates/illumina-fastrnaseq.yaml000066400000000000000000000002261415626112400243570ustar00rootroot00000000000000# Template for fast rna-seq with human data --- details: - analysis: fastrna-seq genome_build: GRCh37 algorithm: {} upload: dir: ../final bcbio-nextgen-1.2.9/config/templates/illumina-rnaseq.yaml000066400000000000000000000023161415626112400235030ustar00rootroot00000000000000# Template for human RNA-seq using Illumina prepared samples --- details: - analysis: RNA-seq genome_build: GRCh37 algorithm: ## for hg38, change the aligner to hisat2 aligner: star ## uncomment below if adapter trimming needs to be performed ## most samples will not need this # trim_reads: read_through # adapters: [truseq, polya] ## uncomment below if strandedness needs to be set # strandedness: unstranded ## uncomment below if fusion calling is necessary # fusion_caller: [pizzly, oncofuse] ## uncomment below if variant calling is necessary, vardict also supported # variantcaller: [gatk-haplotype, vardict] ## uncomment below if you want other expression callers, salmon is run by default # expression_caller: [cufflinks, express, stringtie, sailfish, dexseq, kallisto, salmon] ## uncomment below if you want to provide a custom transcriptome FASTA file # transcriptome_fasta: your-transcriptome.fa ## uncomment below if you want to provide a custom transcriptome GTF file # transcriptome_gtf: your-transcriptome.gtf ## uncomment below if you want to want to provide a FASTA file of spikeins to quantify # spikein_fasta: your-spikein.fa upload: dir: ../final bcbio-nextgen-1.2.9/config/templates/illumina-srnaseq.yaml000066400000000000000000000011461415626112400236660ustar00rootroot00000000000000upload: dir: ../final details: - analysis: smallRNA-seq algorithm: aligner: star # any other aligner is supported. # change adapter according project adapters: ["TGGAATTCTCGGGTGC"] expression_caller: [trna, seqcluster, mirdeep2] # expression_caller: [trna, seqcluster, mirdeep2, mirge] Read docs to know how to use # miRge tools: https://bcbio-nextgen.readthedocs.io/en/latest/contents/pipelines.html#smallrna-seq species: hsa genome_build: hg19 #resources: # atropos: # options: ["-u 4", "-u -4"] # mirge: # options: ["-lib $PATH_TO_LIBS_FOLDER"] bcbio-nextgen-1.2.9/config/templates/indrop-singlecell.yaml000066400000000000000000000004471415626112400240170ustar00rootroot00000000000000details: - analysis: scRNA-seq algorithm: #transcriptome_fasta: path-to-transcriptome-fasta umi_type: harvard-indrop-v3 minimum_barcode_depth: 10000 cellular_barcode_correction: 1 #sample_barcodes: path-to-list-of-valid-sample-barcodes genome_build: mm10 bcbio-nextgen-1.2.9/config/templates/noalign-variant.yaml000066400000000000000000000012401415626112400234660ustar00rootroot00000000000000# Template for variant calling from pre-aligned input BAM files. # Fixes read group information to that specified in the input and # ensures sorting to match the reference genome. # Uses freebayes calling without GATK post-alignment BAM pre-processing # (recalibration and realignment) --- details: - analysis: variant2 genome_build: GRCh37 # to do multi-sample variant calling, assign samples the same metadata / batch # metadata: # batch: your-arbitrary-batch-name algorithm: aligner: false bam_clean: fixrg variantcaller: gatk-haplotype # for targetted projects, set the region # variant_regions: /path/to/your.bed bcbio-nextgen-1.2.9/config/templates/purecn_pon.yaml000066400000000000000000000002711415626112400225500ustar00rootroot00000000000000details: - analysis: variant2 genome_build: hg38 algorithm: aligner: false svcaller: purecn variant_regions: /path/to/panel.bed variantcaller: mutect2 bcbio-nextgen-1.2.9/config/templates/purecn_ton.yaml000066400000000000000000000010251415626112400225520ustar00rootroot00000000000000# Tumor only PureCN analysis with a PON (panel of normals) details: - analysis: variant2 genome_build: hg38 algorithm: aligner: false svcaller: purecn variant_regions: /path/ton/config/panel.bed variantcaller: mutect2 background: variant: /path/ton/config/pon_build-mutect2-annotated.vcf.gz cnv_reference: purecn_normaldb: /path/ton/config/normalDB_hg38.rds purecn_mapping_bias: /path/ton/config/mapping_bias_hg38.rds metadata: phenotype: tumor bcbio-nextgen-1.2.9/config/templates/somatic-duplex-umi.yaml000066400000000000000000000030431415626112400241260ustar00rootroot00000000000000# this template is for somatic tumor only variant calling using duplex UMIs # and high coverage panel data # min_allele_fraction is % i.e. 0.01% = 0.0001 # use_lowfreq_filter: false forces vardict to report all variants, # including those with low variant frequency # to report intronic varints use +-200 padded bed file # for TS data first parse UMIs with: # bcbio_fastq_umi_prep.py autopair -c 1 --tag1 8 --tag2 8 samplex_1.fq.gz samplex_2.fq.gz, # where tag1 8 means 8 bp of UMI # trim_ends trims a spacer between UMI and read details: - algorithm: aligner: bwa align_split_size: false correct_umis: /path/config/whitelist.txt coverage_interval: regional coverage: /path/to/Panel/coverage.bed sv_regions: /path/to/Panel/coverage.bed variant_regions: /path/to/Panel/variants.bed effects_transcripts: canonical_cancer mark_duplicates: true min_allele_fraction: 0.01 variantcaller: somatic: vardict germline: gatk-haplotype platform: Illumina quality_format: Standard recalibrate: false realign: false svcaller: [manta, seq2c, cnvkit] svprioritize: cancer/az-cancer-panel tools_off: - gemini tools_on: [qualimap_full, damage_filter, gatk4] trim_ends: [2,0,2,0] variant_regions: panel.bed umi_type: fastq_name use_lowfreq_filter: false analysis: variant2 description: samplea files: - /path/input/sample_a1_1.fq.gz - /path/input/sample_a1_2.fq.gz genome_build: hg38 metadata: phenotype: tumor resources: fgbio: options: [--min-reads, 3] bcbio-nextgen-1.2.9/config/templates/somatic-single-umi.yaml000066400000000000000000000025041415626112400241070ustar00rootroot00000000000000# single UMI variant calling (high coverage panels) # somatic, tumor only # vardict # specify coverage.bed and variants.bed according to the capture kit used # preprosess libraries with UMIs: # bcbio_fastq_umi_prep.py autopair sample_R1.fastq.gz sample_R2.fastq.gz sample_R3.fastq.gz # result in with_umis: sample_R1.fq.gz, sample_R2.fq.gz details: - algorithm: align_split_size: false aligner: bwa coverage: /path/coverage.bed coverage_interval: regional effects_transcripts: canonical_cancer mark_duplicates: true min_allele_fraction: 0.05 platform: Illumina quality_format: Standard realign: false recalibrate: false sv_regions: /path/coverage.bed svcaller: - manta - seq2c - cnvkit svprioritize: cancer/az-cancer-panel tools_off: - gemini tools_on: - qualimap_full - damage_filter - gatk4 umi_type: fastq_name variant_regions: /path/variants.bed variantcaller: germline: - gatk-haplotype somatic: - vardict analysis: variant2 description: sample_name files: - /path/input/sample_name_R1.fq.gz - /path_input/sample_name_R2.fq.gz genome_build: hg38 metadata: batch: sample_name-batch phenotype: tumor resources: fgbio: options: - --min-reads - 3 - --edits - 1 bcbio-nextgen-1.2.9/config/templates/somatic_tumor_only.yaml000066400000000000000000000011631415626112400243270ustar00rootroot00000000000000details: - algorithm: aligner: bwa background: /path/to/1000g_pon.hg38.vcf.gz mark_duplicates: false recalibrate: false realign: false remove_lcr: true platform: illumina quality_format: standard variantcaller: mutect2 vcfanno: somatic tools_on: - noalt_calling variant_regions: /path/to/panel.bed coverage: /path/to/panel.bed effects_transcripts: canonical_cancer min_allele_fraction: 0.5 analysis: variant2 description: sample_tumor files: ../input/tumor.bam genome_build: hg38 metadata: batch: batch1 phenotype: tumor upload: dir: ../final bcbio-nextgen-1.2.9/config/templates/tumor-paired.yaml000066400000000000000000000013561415626112400230150ustar00rootroot00000000000000# Template for paired (tumor/normal) variant calling --- details: - analysis: variant2 genome_build: GRCh37 # In order to do paired variant calling, samples should belong to the # same batch ("batch" under "metadata" below") and have a "phenotype" # field stating either "normal" or "tumor". For each batch there # should be a sample with "tumor" phenotype and a sample with "normal" # phenotype (no more than two samples per batch) metadata: batch: your-batch-name phenotype: tumor # or "normal" algorithm: aligner: bwa variantcaller: [vardict, mutect2, strelka2] ensemble: numpass: 2 # for targetted projects, set the region # variant_regions: /path/to/your.bed bcbio-nextgen-1.2.9/config/transfer_info.yaml000066400000000000000000000041641415626112400212460ustar00rootroot00000000000000# -- LIMS integration # nglims integration requires a Galaxy server containing # information about samples on each flowcell. galaxy_url: http://nglims.you.org/galaxy galaxy_apikey: apikey_from_Galaxy # -- Machine directories # Directoryies where Illumina puts finished flowcells dump_directories: - /array1 - /array2 # Pointer to a plain text file which will be used to keep track of # directories that have already been transferred. msg_db: /opt/transfer/transferred.db # Logging output for preparation and transfer steps log_dir: /opt/transfer/log # -- Post-processing # Cores to use for processing bcl to bgzipped fastq files algorithm: num_cores: 8 # General options for post-processing: # dir -- directory for processing/transfer # storedir -- Base directory for long term storage. Needs to connect with Galaxy # data libraries. # # Two approaches for running post-processing: # = 1. Occur on non-shared filesystem remote multicore processing machine. # Specify the locaton of processing machine. Files will be rsync'ed using the # provided username which assumes correct setup of passwordless ssh-keys. # Starts a remote bcbio server for kicking off analysis. process: host: workserver.you.org username: bcbio_user dir: /array1/bcbio storedir: /galaxydata/upload/storage server: http://workserver.you.org/bcbio # = 2. Process directly on the same machine, potentially submitting to a cluster. # Supply batch script templates for running bcl2fastq and submitting bcbio jobs. process: dir: /array1/bcbio storedir: /galaxydata/upload/storage submit_cmd: "qsub {batch_script}" bcl2fastq_batch: | #!/bin/bash -e # PBS -q queue_name # PBS -j oe # PBS -N bcl2fastq # PBS -l nodes=1;ppn={cores} cd $PBS_O_WORKDIR function checkpoint_err () { touch {batch_script}.failed } trap checkpoint_err ERR {bcl2fastq_cmd} trap - ERR touch {batch_script}.finished bcbio_batch: | #!/bin/bash -e # PBS -q queue_name # PBS -j oe # PBS -N bcl2fastq cd $PBS_O_WORKDIR bcbio_nextgen.py {fcdir} {run_config} -t ipython -s torque -q queue_name -n 48bcbio-nextgen-1.2.9/config/vcfanno/000077500000000000000000000000001415626112400171505ustar00rootroot00000000000000bcbio-nextgen-1.2.9/config/vcfanno/GRCh37-dbnsfp.conf000066400000000000000000000065731415626112400222410ustar00rootroot00000000000000#dbNSFP v3.5a [[annotation]] file = "variation/dbNSFP.txt.gz" names = ["cds_strand","refcodon","codonpos","codon_degeneracy","Ancestral_allele","AltaiNeandertal","Denisova","Ensembl_geneid","Ensembl_transcriptid","Ensembl_proteinid","LRT_score","LRT_converted_rankscore","LRT_pred","LRT_Omega","MutationTaster_score","MutationTaster_converted_rankscore","MutationTaster_pred","MutationTaster_model","MutationTaster_AAE","MutationAssessor_UniprotID","MutationAssessor_variant","MutationAssessor_score","MutationAssessor_score_rankscore","MutationAssessor_pred","FATHMM_score","FATHMM_converted_rankscore","FATHMM_pred","PROVEAN_score","PROVEAN_converted_rankscore","PROVEAN_pred","Transcript_id_VEST3","Transcript_var_VEST3","VEST3_score","VEST3_rankscore","MetaSVM_score","MetaSVM_rankscore","MetaSVM_pred","MetaLR_score","MetaLR_rankscore","MetaLR_pred","Reliability_index","M-CAP_score","M-CAP_rankscore","M-CAP_pred","REVEL_score","REVEL_rankscore","MutPred_score","MutPred_rankscore","MutPred_protID","MutPred_AAchange","MutPred_Top5features","CADD_raw","CADD_raw_rankscore","CADD_phred","DANN_score","DANN_rankscore","fathmm-MKL_coding_score","fathmm-MKL_coding_rankscore","fathmm-MKL_coding_pred","fathmm-MKL_coding_group","Eigen_coding_or_noncoding","Eigen-raw","Eigen-phred","Eigen-PC-raw","Eigen-PC-phred","Eigen-PC-raw_rankscore","GenoCanyon_score","GenoCanyon_score_rankscore","integrated_fitCons_score","integrated_fitCons_score_rankscore","integrated_confidence_value","GM12878_fitCons_score","GM12878_fitCons_score_rankscore","GM12878_confidence_value","H1-hESC_fitCons_score","H1-hESC_fitCons_score_rankscore","H1-hESC_confidence_value","HUVEC_fitCons_score","HUVEC_fitCons_score_rankscore","HUVEC_confidence_value","GERP++_NR","GERP++_RS","GERP++_RS_rankscore","phyloP100way_vertebrate","phyloP100way_vertebrate_rankscore","phyloP20way_mammalian","phyloP20way_mammalian_rankscore","phastCons100way_vertebrate","phastCons100way_vertebrate_rankscore","phastCons20way_mammalian","phastCons20way_mammalian_rankscore","SiPhy_29way_pi","SiPhy_29way_logOdds","SiPhy_29way_logOdds_rankscore","gnomAD_exomes_AC","gnomAD_exomes_AN","gnomAD_exomes_AF","gnomAD_genomes_AC","gnomAD_genomes_AN","gnomAD_genomes_AF","Interpro_domain","GTEx_V6p_gene","GTEx_V6p_tissue"] columns = [13,14,15,16,17,18,19,20,21,22,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,188,189,190,215,216,217,243,244,245] ops = ["first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first"]bcbio-nextgen-1.2.9/config/vcfanno/GRCh37-dbscsnv.conf000066400000000000000000000006631415626112400224210ustar00rootroot00000000000000[[annotation]] file = "variation/dbscSNV.txt.gz" names = ["RefSeq?","Ensembl?","RefSeq_region","RefSeq_gene","RefSeq_functional_consequence","RefSeq_id_c.change_p.change","Ensembl_region","Ensembl_gene","Ensembl_functional_consequence","Ensembl_id_c.change_p.change","ada_score","rf_score"] columns = [7,8,9,10,11,12,13,14,15,16,17,18] ops = ["first","first","first","first","first","first","first","first","first","first","max","max"]bcbio-nextgen-1.2.9/config/vcfanno/GRCh37-gemini.conf000066400000000000000000000102511415626112400222210ustar00rootroot00000000000000[[annotation]] file="variation/exac.vcf.gz" fields=["AC_Adj", "AN_Adj", "AC_AFR", "AN_AFR", "AC_AMR", "AN_AMR", "AC_EAS", "AN_EAS", "AC_FIN", "AN_FIN", "AC_NFE", "AN_NFE", "AC_OTH", "AN_OTH", "AC_SAS", "AN_SAS", "AC_Het", "AC_Hom"] names=["ac_exac_all", "an_exac_all", "ac_adj_exac_afr", "an_adj_exac_afr", "ac_adj_exac_amr", "an_adj_exac_amr", "ac_adj_exac_eas", "an_adj_exac_eas", "ac_adj_exac_fin", "an_adj_exac_fin", "ac_adj_exac_nfe", "an_adj_exac_nfe", "ac_adj_exac_oth", "an_adj_exac_oth", "ac_adj_exac_sas", "an_adj_exac_sas", "num_exac_Het", "num_exac_Hom"] ops=["max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max"] [[annotation]] file="variation/gnomad_exome.vcf.gz" fields=["AF","AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth","AF_sas","AF_popmax","AC","AC_afr","AC_amr","AC_asj","AC_eas","AC_fin","AC_nfe","AC_oth","AC_sas","AC_popmax","AN","AN_afr","AN_amr","AN_asj","AN_eas","AN_fin","AN_nfe","AN_oth","AN_sas","AN_popmax","popmax","nhomalt","nhomalt_male","nhomalt_female"] names=["gnomAD_AF","gnomAD_AF_AFR","gnomAD_AF_AMR","gnomAD_AF_ASJ","gnomAD_AF_EAS","gnomAD_AF_FIN","gnomAD_AF_NFE","gnomAD_AF_OTH","gnomAD_AF_SAS","gnomAD_AF_POPMAX","gnomAD_AC","gnomAD_AC_AFR","gnomAD_AC_AMR","gnomAD_AC_ASJ","gnomAD_AC_EAS","gnomAD_AC_FIN","gnomAD_AC_NFE","gnomAD_AC_OTH","gnomAD_AC_SAS","gnomAD_AC_POPMAX","gnomAD_AN","gnomAD_AN_AFR","gnomAD_AN_AMR","gnomAD_AN_ASJ","gnomAD_AN_EAS","gnomAD_AN_FIN","gnomAD_AN_NFE","gnomAD_AN_OTH","gnomAD_AN_SAS","gnomAD_AN_POPMAX","gnomAD_POPMAX","gnomAD_Hom","gnomAD_Hom_Male","gnomAD_Hom_Female"] ops=["self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","min","min","min","min","min","min","min","min","min","min","self","self","self","self"] [[annotation]] file="variation/esp.vcf.gz" fields=["EA_AC", "AA_AC", "TAC"] names=["af_esp_ea_float", "af_esp_aa_float", "af_esp_all_float"] ops=["lua:ratio(vals)", "lua:ratio(vals)", "lua:ratio(vals)"] [[annotation]] file="variation/dbsnp.vcf.gz" fields=["ID", "CAF", "FREQ", "ID"] names=["rs_id", "CAF", "FREQ", "DB"] ops=["first", "self", "self", "flag"] [[annotation]] file="variation/1000g.vcf.gz" fields=["AMR_AF", "EAS_AF", "SAS_AF", "AFR_AF", "EUR_AF", "AF"] names=["af_1kg_amr", "af_1kg_eas", "af_1kg_sas", "af_1kg_afr", "af_1kg_eur", "af_1kg_all"] ops=["max", "max", "max", "max", "max", "max"] [[annotation]] file="variation/clinvar.vcf.gz" fields=["CLNSIG", "CLNDBN", "GENEINFO"] names=["clinvar_sig", "clinvar_disease_name", "clinvar_geneinfo"] ops=["self", "self", "self"] # calculate allele frequencies for all populations. [[postannotation]] fields=["ac_exac_all", "an_exac_all"] name="af_exac_all" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_afr", "an_adj_exac_afr"] name="af_adj_exac_afr" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_amr", "an_adj_exac_amr"] name="af_adj_exac_amr" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_eas", "an_adj_exac_eas"] name="af_adj_exac_eas" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_fin", "an_adj_exac_fin"] name="af_adj_exac_fin" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_nfe", "an_adj_exac_nfe"] name="af_adj_exac_nfe" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_oth", "an_adj_exac_oth"] name="af_adj_exac_oth" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_sas", "an_adj_exac_sas"] name="af_adj_exac_sas" op="div2" type="Float" [[postannotation]] fields=['af_adj_exac_afr', 'af_adj_exac_amr', 'af_adj_exac_eas', 'af_adj_exac_fin', 'af_adj_exac_nfe', 'af_adj_exac_oth', 'af_adj_exac_sas', "af_esp_ea", "af_esp_aa", "af_esp_all", "af_1kg_amr", "af_1kg_eas", "af_1kg_sas", "af_1kg_afr", "af_1kg_eur", "af_1kg_all"] op="max" name="max_aaf_all" type="Float" [[postannotation]] fields=["clinvar_sig", "max_aaf_all"] op="lua:check_clinvar_aaf(clinvar_sig, max_aaf_all, 0.005)" name="common_pathogenic" type="Flag" [[postannotation]] fields=["max_aaf_all"] op="lua:check_population_aaf(max_aaf_all, 0.01)" name="DB" type="Flag" [[postannotation]] name="ID" fields=["rs_id", "ID"] op="setid" type="String" bcbio-nextgen-1.2.9/config/vcfanno/GRCh37-gemini.lua000066400000000000000000000074741415626112400220720ustar00rootroot00000000000000function mean(vals) local sum=0 for i=1,#vals do sum = sum + vals[i] end return sum / #vals end function loc(chrom, start, stop) return chrom .. ":" .. start .. "-" .. stop end CLINVAR_LOOKUP = {} CLINVAR_LOOKUP['0'] = 'unknown' CLINVAR_LOOKUP['1'] = 'germline' CLINVAR_LOOKUP['2'] = 'somatic' CLINVAR_LOOKUP['4'] = 'inherited' CLINVAR_LOOKUP['8'] = 'paternal' CLINVAR_LOOKUP['16'] = 'maternal' CLINVAR_LOOKUP['32'] = 'de-novo' CLINVAR_LOOKUP['64'] = 'biparental' CLINVAR_LOOKUP['128'] = 'uniparental' CLINVAR_LOOKUP['256'] = 'not-tested' CLINVAR_LOOKUP['512'] = 'tested-inconclusive' CLINVAR_LOOKUP['1073741824'] = 'other' CLINVAR_SIG = {} CLINVAR_SIG['0'] = 'uncertain' CLINVAR_SIG['1'] = 'not-provided' CLINVAR_SIG['2'] = 'benign' CLINVAR_SIG['3'] = 'likely-benign' CLINVAR_SIG['4'] = 'likely-pathogenic' CLINVAR_SIG['5'] = 'pathogenic' CLINVAR_SIG['6'] = 'drug-response' CLINVAR_SIG['7'] = 'histocompatibility' CLINVAR_SIG['255'] = 'other' CLINVAR_SIG['.'] = '.' function intotbl(ud) local tbl = {} for i=1,#ud do tbl[i] = ud[i] end return tbl end -- from lua-users wiki function split(str, sep) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) str:gsub(pattern, function(c) fields[#fields+1] = c end) return fields end function contains(str, tok) return string.find(str, tok) ~= nil end function div2(a, b) if(a == 0) then return "0.0" end return string.format("%.9f", (a + 0) / b) end function ratio(vals) vals = vals[1] -- get 2 values per element. ref and alt counts. if vals[2] == 0 then return "0.0" end return string.format("%.9f", vals[2] / (vals[1] + vals[2])) end function clinvar_sig(vals) local t = type(vals) -- just a single-value if(t == "string" or t == "number") and not contains(vals, "|") then return CLINVAR_SIG[vals] elseif t ~= "table" then if not contains(t, "userdata") then if t == "string" then vals = split(vals, ",") else vals = {vals} end else vals = intotbl(vals) end end local ret = {} for i=1,#vals do if not contains(vals[i], "|") then ret[#ret+1] = CLINVAR_SIG[vals[i]] else local invals = split(vals[i], "|") local inret = {} for j=1,#invals do inret[#inret+1] = CLINVAR_SIG[invals[j]] end ret[#ret+1] = join(inret, "|") end end return join(ret, ",") end join = table.concat function check_clinvar_aaf(clinvar_sig, max_aaf_all, aaf_cutoff) -- didn't find an aaf for this so can't be common if max_aaf_all == nil or clinvar_sig == nil then return false end if type(clinvar_sig) ~= "string" then clinvar_sig = join(clinvar_sig, ",") end if false == contains(clinvar_sig, "pathogenic") then return false end if type(max_aaf_all) ~= "table" then return max_aaf_all > aaf_cutoff end for i, aaf in pairs(max_aaf_all) do if aaf > aaf_cutoff then return true end end return false end function check_population_aaf(max_aaf_all, aaf_cutoff) -- didn't find an aaf for this so can't be common if max_aaf_all == nil then return false end if type(max_aaf_all) ~= "table" then return max_aaf_all > aaf_cutoff end for i, aaf in pairs(max_aaf_all) do if aaf > aaf_cutoff then return true end end return false end function setid(...) local t = {...} local res = {} local seen = {} for i, v in pairs(t) do if v ~= "." and v ~= nil and v ~= "" then if seen[v] == nil then res[#res+1] = string.gsub(v, ",", ";") seen[v] = true end end end return table.concat(res, ";") end bcbio-nextgen-1.2.9/config/vcfanno/GRCh37-gnomad_genome.conf000066400000000000000000000022311415626112400235470ustar00rootroot00000000000000[[annotation]] file="variation/gnomad_genome.vcf.gz" fields=["AF","AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth","AF_sas","AF_popmax","AC","AC_afr","AC_amr","AC_asj","AC_eas","AC_fin","AC_nfe","AC_oth","AC_sas","AC_popmax","AN","AN_afr","AN_amr","AN_asj","AN_eas","AN_fin","AN_nfe","AN_oth","AN_sas","AN_popmax","popmax","nhomalt","nhomalt_male","nhomalt_female"] names=["gnomAD_AF","gnomAD_AF_AFR","gnomAD_AF_AMR","gnomAD_AF_ASJ","gnomAD_AF_EAS","gnomAD_AF_FIN","gnomAD_AF_NFE","gnomAD_AF_OTH","gnomAD_AF_SAS","gnomAD_AF_POPMAX","gnomAD_AC","gnomAD_AC_AFR","gnomAD_AC_AMR","gnomAD_AC_ASJ","gnomAD_AC_EAS","gnomAD_AC_FIN","gnomAD_AC_NFE","gnomAD_AC_OTH","gnomAD_AC_SAS","gnomAD_AC_POPMAX","gnomAD_AN","gnomAD_AN_AFR","gnomAD_AN_AMR","gnomAD_AN_ASJ","gnomAD_AN_EAS","gnomAD_AN_FIN","gnomAD_AN_NFE","gnomAD_AN_OTH","gnomAD_AN_SAS","gnomAD_AN_POPMAX","gnomAD_POPMAX","gnomAD_Hom","gnomAD_Hom_Male","gnomAD_Hom_Female"] ops=["self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self"] bcbio-nextgen-1.2.9/config/vcfanno/hg38-dbnsfp.conf000066400000000000000000000066461415626112400220560ustar00rootroot00000000000000#dbNSFP v3.5a [[annotation]] file = "variation/dbNSFP.txt.gz" names = ["hg19_chr","hg19_pos","cds_strand","refcodon","codonpos","codon_degeneracy","Ancestral_allele","AltaiNeandertal","Denisova","Ensembl_geneid","Ensembl_transcriptid","Ensembl_proteinid","LRT_score","LRT_converted_rankscore","LRT_pred","LRT_Omega","MutationTaster_score","MutationTaster_converted_rankscore","MutationTaster_pred","MutationTaster_model","MutationTaster_AAE","MutationAssessor_UniprotID","MutationAssessor_variant","MutationAssessor_score","MutationAssessor_score_rankscore","MutationAssessor_pred","FATHMM_score","FATHMM_converted_rankscore","FATHMM_pred","PROVEAN_score","PROVEAN_converted_rankscore","PROVEAN_pred","Transcript_id_VEST3","Transcript_var_VEST3","VEST3_score","VEST3_rankscore","MetaSVM_score","MetaSVM_rankscore","MetaSVM_pred","MetaLR_score","MetaLR_rankscore","MetaLR_pred","Reliability_index","M-CAP_score","M-CAP_rankscore","M-CAP_pred","REVEL_score","REVEL_rankscore","MutPred_score","MutPred_rankscore","MutPred_protID","MutPred_AAchange","MutPred_Top5features","CADD_raw","CADD_raw_rankscore","CADD_phred","DANN_score","DANN_rankscore","fathmm-MKL_coding_score","fathmm-MKL_coding_rankscore","fathmm-MKL_coding_pred","fathmm-MKL_coding_group","Eigen_coding_or_noncoding","Eigen-raw","Eigen-phred","Eigen-PC-raw","Eigen-PC-phred","Eigen-PC-raw_rankscore","GenoCanyon_score","GenoCanyon_score_rankscore","integrated_fitCons_score","integrated_fitCons_score_rankscore","integrated_confidence_value","GM12878_fitCons_score","GM12878_fitCons_score_rankscore","GM12878_confidence_value","H1-hESC_fitCons_score","H1-hESC_fitCons_score_rankscore","H1-hESC_confidence_value","HUVEC_fitCons_score","HUVEC_fitCons_score_rankscore","HUVEC_confidence_value","GERP++_NR","GERP++_RS","GERP++_RS_rankscore","phyloP100way_vertebrate","phyloP100way_vertebrate_rankscore","phyloP20way_mammalian","phyloP20way_mammalian_rankscore","phastCons100way_vertebrate","phastCons100way_vertebrate_rankscore","phastCons20way_mammalian","phastCons20way_mammalian_rankscore","SiPhy_29way_pi","SiPhy_29way_logOdds","SiPhy_29way_logOdds_rankscore","gnomAD_exomes_AC","gnomAD_exomes_AN","gnomAD_exomes_AF","gnomAD_genomes_AC","gnomAD_genomes_AN","gnomAD_genomes_AF","Interpro_domain","GTEx_V6p_gene","GTEx_V6p_tissue"] columns = [8,9,13,14,15,16,17,18,19,20,21,22,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,188,189,190,215,216,217,243,244,245] ops = ["first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first","first"] bcbio-nextgen-1.2.9/config/vcfanno/hg38-dbscsnv.conf000066400000000000000000000006621415626112400222340ustar00rootroot00000000000000[[annotation]] file = "variation/dbscSNV.txt.gz" names = ["RefSeq?","Ensembl?","RefSeq_region","RefSeq_gene","RefSeq_functional_consequence","RefSeq_id_c.change_p.change","Ensembl_region","Ensembl_gene","Ensembl_functional_consequence","Ensembl_id_c.change_p.change","ada_score","rf_score"] columns =[7,8,9,10,11,12,13,14,15,16,17,18] ops = ["first","first","first","first","first","first","first","first","first","first","max","max"]bcbio-nextgen-1.2.9/config/vcfanno/hg38-gemini.conf000066400000000000000000000075671415626112400220550ustar00rootroot00000000000000[[annotation]] file="variation/exac.vcf.gz" fields = ["AC_Adj", "AN_Adj", "AC_AFR", "AN_AFR", "AC_AMR", "AN_AMR", "AC_EAS", "AN_EAS", "AC_FIN", "AN_FIN", "AC_NFE", "AN_NFE", "AC_OTH", "AN_OTH", "AC_SAS", "AN_SAS", "AC_Het", "AC_Hom"] names = ["ac_exac_all", "an_exac_all", "ac_adj_exac_afr", "an_adj_exac_afr", "ac_adj_exac_amr", "an_adj_exac_amr", "ac_adj_exac_eas", "an_adj_exac_eas", "ac_adj_exac_fin", "an_adj_exac_fin", "ac_adj_exac_nfe", "an_adj_exac_nfe", "ac_adj_exac_oth", "an_adj_exac_oth", "ac_adj_exac_sas", "an_adj_exac_sas", "num_exac_Het", "num_exac_Hom"] ops=["max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max", "max"] [[annotation]] file="variation/gnomad_exome.vcf.gz" fields=["AF","AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth","AF_sas","AF_popmax","AC","AC_afr","AC_amr","AC_asj","AC_eas","AC_fin","AC_nfe","AC_oth","AC_sas","AC_popmax","AN","AN_afr","AN_amr","AN_asj","AN_eas","AN_fin","AN_nfe","AN_oth","AN_sas","AN_popmax","popmax","nhomalt","nhomalt_male","nhomalt_female"] names=["gnomAD_AF","gnomAD_AF_AFR","gnomAD_AF_AMR","gnomAD_AF_ASJ","gnomAD_AF_EAS","gnomAD_AF_FIN","gnomAD_AF_NFE","gnomAD_AF_OTH","gnomAD_AF_SAS","gnomAD_AF_POPMAX","gnomAD_AC","gnomAD_AC_AFR","gnomAD_AC_AMR","gnomAD_AC_ASJ","gnomAD_AC_EAS","gnomAD_AC_FIN","gnomAD_AC_NFE","gnomAD_AC_OTH","gnomAD_AC_SAS","gnomAD_AC_POPMAX","gnomAD_AN","gnomAD_AN_AFR","gnomAD_AN_AMR","gnomAD_AN_ASJ","gnomAD_AN_EAS","gnomAD_AN_FIN","gnomAD_AN_NFE","gnomAD_AN_OTH","gnomAD_AN_SAS","gnomAD_AN_POPMAX","gnomAD_POPMAX","gnomAD_Hom","gnomAD_Hom_Male","gnomAD_Hom_Female"] ops=["self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","min","min","min","min","min","min","min","min","min","min","self","self","self","self"] [[annotation]] file="variation/esp.vcf.gz" fields=["EA_AC", "AA_AC", "TAC"] names=["af_esp_ea_float", "af_esp_aa_float", "af_esp_all_float"] ops=["lua:ratio(vals)", "lua:ratio(vals)", "lua:ratio(vals)"] [[annotation]] file="variation/dbsnp.vcf.gz" fields=["ID", "CAF", "FREQ", "ID"] names=["rs_id", "CAF", "FREQ", "ID"] ops=["first", "self", "self", "flag"] [[annotation]] file="variation/clinvar.vcf.gz" fields=["CLNSIG", "CLNDBN", "GENEINFO"] names=["clinvar_sig", "clinvar_disease_name", "clinvar_geneinfo"] ops=["self", "self", "self"] # calculate allele frequencies for all populations. [[postannotation]] fields=["ac_exac_all", "an_exac_all"] name="af_exac_all" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_afr", "an_adj_exac_afr"] name="af_adj_exac_afr" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_amr", "an_adj_exac_amr"] name="af_adj_exac_amr" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_eas", "an_adj_exac_eas"] name="af_adj_exac_eas" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_fin", "an_adj_exac_fin"] name="af_adj_exac_fin" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_nfe", "an_adj_exac_nfe"] name="af_adj_exac_nfe" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_oth", "an_adj_exac_oth"] name="af_adj_exac_oth" op="div2" type="Float" [[postannotation]] fields=["ac_adj_exac_sas", "an_adj_exac_sas"] name="af_adj_exac_sas" op="div2" type="Float" [[postannotation]] fields=['af_adj_exac_afr', 'af_adj_exac_amr', 'af_adj_exac_eas', 'af_adj_exac_fin', 'af_adj_exac_nfe', 'af_adj_exac_oth', 'af_adj_exac_sas', "af_esp_ea", "af_esp_aa", "af_esp_all"] op="max" name="max_aaf_all" type="Float" [[postannotation]] fields=["clinvar_sig", "max_aaf_all"] op="lua:check_clinvar_aaf(clinvar_sig, max_aaf_all, 0.005)" name="common_pathogenic" type="Flag" [[postannotation]] fields=["max_aaf_all"] op="lua:check_population_aaf(max_aaf_all, 0.01)" name="DB" type="Flag" [[postannotation]] name="ID" fields=["rs_id", "ID"] op="setid" type="String" bcbio-nextgen-1.2.9/config/vcfanno/hg38-gemini.lua000066400000000000000000000070421415626112400216750ustar00rootroot00000000000000function mean(vals) local sum=0 for i=1,#vals do sum = sum + vals[i] end return sum / #vals end function loc(chrom, start, stop) return chrom .. ":" .. start .. "-" .. stop end CLINVAR_LOOKUP = {} CLINVAR_LOOKUP['0'] = 'unknown' CLINVAR_LOOKUP['1'] = 'germline' CLINVAR_LOOKUP['2'] = 'somatic' CLINVAR_LOOKUP['4'] = 'inherited' CLINVAR_LOOKUP['8'] = 'paternal' CLINVAR_LOOKUP['16'] = 'maternal' CLINVAR_LOOKUP['32'] = 'de-novo' CLINVAR_LOOKUP['64'] = 'biparental' CLINVAR_LOOKUP['128'] = 'uniparental' CLINVAR_LOOKUP['256'] = 'not-tested' CLINVAR_LOOKUP['512'] = 'tested-inconclusive' CLINVAR_LOOKUP['1073741824'] = 'other' CLINVAR_SIG = {} CLINVAR_SIG['0'] = 'uncertain' CLINVAR_SIG['1'] = 'not-provided' CLINVAR_SIG['2'] = 'benign' CLINVAR_SIG['3'] = 'likely-benign' CLINVAR_SIG['4'] = 'likely-pathogenic' CLINVAR_SIG['5'] = 'pathogenic' CLINVAR_SIG['6'] = 'drug-response' CLINVAR_SIG['7'] = 'histocompatibility' CLINVAR_SIG['255'] = 'other' CLINVAR_SIG['.'] = '.' function intotbl(ud) local tbl = {} for i=1,#ud do tbl[i] = ud[i] end return tbl end -- from lua-users wiki function split(str, sep) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) str:gsub(pattern, function(c) fields[#fields+1] = c end) return fields end function contains(str, tok) return string.find(str, tok) ~= nil end function div2(a, b) if(a == 0) then return "0.0" end return string.format("%.9f", (a + 0) / b) end function ratio(vals) vals = vals[1] -- get 2 values per element. alt and ref counts. if vals[2] == 0 then return "0.0" end return string.format("%.9f", vals[1] / (vals[1] + vals[2])) end function clinvar_sig(vals) local t = type(vals) -- just a single-value if(t == "string" or t == "number") and not contains(vals, "|") then return CLINVAR_SIG[vals] elseif t ~= "table" then if not contains(t, "userdata") then if t == "string" then vals = split(vals, ",") else vals = {vals} end else vals = intotbl(vals) end end local ret = {} for i=1,#vals do if not contains(vals[i], "|") then ret[#ret+1] = CLINVAR_SIG[vals[i]] else local invals = split(vals[i], "|") local inret = {} for j=1,#invals do inret[#inret+1] = CLINVAR_SIG[invals[j]] end ret[#ret+1] = join(inret, "|") end end return join(ret, ",") end join = table.concat function check_clinvar_aaf(clinvar_sig, max_aaf_all, aaf_cutoff) -- didn't find an aaf for this so can't be common if max_aaf_all == nil or clinvar_sig == nil then return false end if type(clinvar_sig) ~= "string" then clinvar_sig = join(clinvar_sig, ",") end if false == contains(clinvar_sig, "pathogenic") then return false end if type(max_aaf_all) ~= "table" then return max_aaf_all > aaf_cutoff end for i, aaf in pairs(max_aaf_all) do if aaf > aaf_cutoff then return true end end return false end function check_population_aaf(max_aaf_all, aaf_cutoff) -- didn't find an aaf for this so can't be common if max_aaf_all == nil then return false end if type(max_aaf_all) ~= "table" then return max_aaf_all > aaf_cutoff end for i, aaf in pairs(max_aaf_all) do if aaf > aaf_cutoff then return true end end return false end bcbio-nextgen-1.2.9/config/vcfanno/hg38-gnomad_genome.conf000066400000000000000000000022561415626112400233720ustar00rootroot00000000000000[[annotation]] file="variation/gnomad_genome.vcf.gz" fields=["AF","AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth","AF_sas","AF_popmax","AC","AC_afr","AC_amr","AC_asj","AC_eas","AC_fin","AC_nfe","AC_oth","AC_sas","AC_popmax","AN","AN_afr","AN_amr","AN_asj","AN_eas","AN_fin","AN_nfe","AN_oth","AN_sas","AN_popmax","popmax","nhomalt","nhomalt_male","nhomalt_female"] names=["gnomAD_AF","gnomAD_AF_AFR","gnomAD_AF_AMR","gnomAD_AF_ASJ","gnomAD_AF_EAS","gnomAD_AF_FIN","gnomAD_AF_NFE","gnomAD_AF_OTH","gnomAD_AF_SAS","gnomAD_AF_POPMAX","gnomAD_AC","gnomAD_AC_AFR","gnomAD_AC_AMR","gnomAD_AC_ASJ","gnomAD_AC_EAS","gnomAD_AC_FIN","gnomAD_AC_NFE","gnomAD_AC_OTH","gnomAD_AC_SAS","gnomAD_AC_POPMAX","gnomAD_AN","gnomAD_AN_AFR","gnomAD_AN_AMR","gnomAD_AN_ASJ","gnomAD_AN_EAS","gnomAD_AN_FIN","gnomAD_AN_NFE","gnomAD_AN_OTH","gnomAD_AN_SAS","gnomAD_AN_POPMAX","gnomAD_POPMAX","gnomAD_Hom","gnomAD_Hom_Male","gnomAD_Hom_Female"] ops=["self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self","self"] bcbio-nextgen-1.2.9/config/vcfanno/mm10-gemini.conf000066400000000000000000000003741415626112400220430ustar00rootroot00000000000000# Simple gemini annotation for mm10, enabling GEMINI db creation. [[annotation]] file="variation/mm10-dbSNP-2013-09-12.vcf.gz" fields=["ID"] names=["rs_ids"] ops=["concat"] [[postannotation]] name="ID" fields=["rs_ids", "ID"] op="setid" type="String" bcbio-nextgen-1.2.9/config/vcfanno/rnaedit.conf000066400000000000000000000001721415626112400214450ustar00rootroot00000000000000[[annotation]] file="editing/RADAR.bed.gz" columns=[4] ops=["lua:is_edit_flag(ref, alt)"] names=["possible_rnaedit_flag"] bcbio-nextgen-1.2.9/config/vcfanno/rnaedit.lua000066400000000000000000000002611415626112400213000ustar00rootroot00000000000000function is_snp(ref, alt) return ref:len() == 1 and alt[1]:len() == 1 end function is_edit_flag(ref, alt) if is_snp(ref, alt) then return true end return false end bcbio-nextgen-1.2.9/config/vcfanno/somatic.conf000066400000000000000000000006301415626112400214550ustar00rootroot00000000000000# ID annotations for somatic projects, including COSMIC # Requires a manual installation of COSMIC # https://bcbio-nextgen.readthedocs.io/en/latest/contents/installation.html?highlight=cosmic#customizing-data-installation [[annotation]] file="variation/cosmic.vcf.gz" fields=["ID"] names=["cosmic_id"] ops=["uniq"] [[postannotation]] name="ID" fields=["cosmic_id", "rs_id", "ID"] op="setid" type="String" bcbio-nextgen-1.2.9/docs/000077500000000000000000000000001415626112400152015ustar00rootroot00000000000000bcbio-nextgen-1.2.9/docs/Makefile000066400000000000000000000127301415626112400166440ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/bcbio_nextgen.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/bcbio_nextgen.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/bcbio_nextgen" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/bcbio_nextgen" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." bcbio-nextgen-1.2.9/docs/conf.py000066400000000000000000000047461415626112400165130ustar00rootroot00000000000000# Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html import os from recommonmark.transform import AutoStructify # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- project = 'bcbio-nextgen' copyright = '2021, bcbio-nextgen contributors' author = 'bcbio-nextgen contributors' # The full version, including alpha/beta/rc tags version = release = '1.2.9' # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.viewcode', 'sphinx.ext.autosectionlabel', 'myst_parser', ] # Prefix document path to section labels, otherwise autogenerated labels would look like 'heading' # rather than 'path/to/file:heading' autosectionlabel_prefix_document = True source_suffix = { '.md': 'markdown', } # Add any paths that contain templates here, relative to this directory. templates_path = ['templates'] # The master toctree document (required by Read the Docs). master_doc = 'index' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['_build'] # -- Options for HTML output ------------------------------------------------- # to use Read The Docs theme when building docs locally if not os.getenv('READTHEDOCS'): try: import sphinx_rtd_theme except ModuleNotFoundError: pass else: html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # enable automatic table of contents on the index page def setup(app): app.add_config_value('recommonmark_config', { 'auto_toc_tree_section': 'Contents', 'auto_toc_maxdepth': 2, }, True) app.add_transform(AutoStructify) bcbio-nextgen-1.2.9/docs/contents/000077500000000000000000000000001415626112400170365ustar00rootroot00000000000000bcbio-nextgen-1.2.9/docs/contents/3prime_dge.md000066400000000000000000000134011415626112400213750ustar00rootroot00000000000000# 3' DGE 3' DGE has some additional complexity when compared to standard bulk RNA-seq experiments. 3' DGE is sequencing just the 3' end of each transcript, so quantification needs to proceed differently. 3' DGE also often incorporates UMIs, which need to be accounted for during the quantification step of RNA-seq. Different kits have different ways of incorporating the UMI and may or may not include optional well barcodes for plates and sample barcodes for individual samples. bcbio can be extended to handle arbitrary kits, and comes with support for several commonly used DGE kits out of the box. ## Description of example dataset This example takes a small sample of reads generated from the [QIAseq UPX 3' Transcriptome kit](https://www.qiagen.com/us/products/discovery-and-translational-research/next-generation-sequencing/rna-sequencing/three-rnaseq/qiaseq-upx-3-transcriptome-kits/). This particular kit has 96 well and 384 well versions, which are supported in bcbio via the `umi_type: qiaseq-upx-96` and `umi_type: qiaseq-upx-384` options. ### 1. Download the example data and configuration files This downloads the input data, creates the project structure and example configuration files. #### 1.1 Create input directory and download FASTQ files. ```bash mkdir qiaseq-upx-96-example cd qiaseq-upx-96-example mkdir -p fastq cd fastq wget --no-check-certificate http://s3.amazonaws.com/bcbio-nextgen/dge_userstory_data/fastq/qiaseq-upx_R1.fastq.gz wget --no-check-certificate http://s3.amazonaws.com/bcbio-nextgen/dge_userstory_data/fastq/qiaseq-upx_R2.fastq.gz cd .. ``` #### 1.2 Download template YAML file describing 3' DGE analysis ```bash wget --no-check-certificate http://s3.amazonaws.com/bcbio-nextgen/dge_userstory_data/qiaseq-upx.yaml ``` qiaseq-upx.yaml: ```yaml details: - analysis: scrna-seq genome_build: hg38 algorithm: umi_type: qiaseq-upx-96 cellular_barcode_correction: 1 minimum_barcode_depth: 0 upload: dir: ../final ``` #### 1.3 Create a sample sheet ```bash wget --no-check-certificate http://s3.amazonaws.com/bcbio-nextgen/dge_userstory_data/example_dge.csv ``` example_dge.csv: ``` samplename,description qiaseq-upx_R1.fastq.gz,testrun ``` ### 2. Generate YAML config file for analysis ``` bcbio_nextgen.py -w template qiaseq-upx.yaml example_dge.csv fastq ``` In the result you should see a folder structure: ``` example_dge |---config |---final |---work ``` `example_dge/config/example_dge.yaml` is the main config file to run the bcbio project. You will see this file has a copy of the parameters in `qiaseq-upx.yaml` for each sample. ### 3. Run the analysis This will run the analysis on a local machine, using just one core. ```bash cd example_dge/work bcbio_nextgen.py ../config/example_dge.yaml -n 1 ``` ## Parameters * `umi_type` DGE kit: [harvard-scrb, qiaseq-upx-96, qiaseq-upx-384] * `minimum_barcode_depth=0` Cellular barcodes with less reads are discarded. This should be 0 if you are using one of these plate-based kits. * `singlecell_quantifier=rapmap` Quantifier to use for single-cell RNA-sequencing. Supports `rapmap` or `kallisto`. We recommend using `rapmap`. * *optional* `transcriptome_fasta` alternative transcriptome reference. * *optional* `transcriptome_gtf` An optional GTF file of the transcriptome to quantitate, rather than the bcbio installed version. ## Output Project directory: ``` ├── bcbio-nextgen-commands.log -- commands run by bcbio ├── bcbio-nextgen.log -- logging information from bcbio run ├── cb-histogram.txt -- histogram of reads per cellular barcode ├── data_versions.csv -- version information for data used by bcbio ├── metadata.csv -- provided metadata about each sample ├── programs.txt -- program versions of tools run ├── project-summary.yaml -- YAML description of project with derived metadata ├── tagcounts-dupes.mtx -- Matrix Market of gene counts without UMI duplicate removed ├── tagcounts-dupes.mtx.colnames -- column names to go with tagcounts-dupes.mtx ├── tagcounts-dupes.mtx.rownames -- row names to go with tagcounts-dupes.mtx ├── tagcounts.mtx -- Matrix Market of gene counts, use these for downstream analyses ├── tagcounts.mtx.colnames -- column names to go with tagcounts.mtx ├── tagcounts.mtx.metadata -- optional sample-level metadata for samples in tagcounts.mtx ├── tagcounts.mtx.rownames -- row names to go with tagcounts.mtx └── transcriptome └── mm10.fa -- transcriptome used for quantification ``` Sample directories: ``` testrun/ ├── testrun-barcodes-filtered.tsv -- filtered list of cell/well barcodes ├── testrun-barcodes.tsv -- list of cell/well barcodes with number of reads assigned to each barcode └── testrun-transcriptome.bam -- transcriptome alignments ``` ## Downstream analysis The starting point for downstream analyses will be the count table of counts per gene per cell/well in the `tagcounts.mtx`, `tagcounts.mtx.rownames` and `tagcounts.mtx.colnames` files. You can load these into R using the [readMM function](https://stat.ethz.ch/R-manual/R-devel/library/Matrix/html/externalFormats.html) from the [Matrix](https://cran.r-project.org/web/packages/Matrix/index.html) package. You can use any standard count-based differential RNA-seq differential expression tool to operate on these count tables such as [DESeq2](https://bioconductor.org/packages/release/bioc/html/DESeq2.html)/[edgeR](https://bioconductor.org/packages/release/bioc/html/DESeq2.html)/[limma](https://bioconductor.org/packages/release/bioc/html/limma.html) and the analysis will be similar to a bulk RNA-seq experiment. With a large number of samples you will find making [UMAP plots](https://cran.r-project.org/web/packages/umap/vignettes/umap.html) a useful way to visualize the relationships between your samples. bcbio-nextgen-1.2.9/docs/contents/atac.md000066400000000000000000000320521415626112400202720ustar00rootroot00000000000000# ATAC-seq The ATAC-seq pipeline in bcbio follows recommendations from the [ENCODE ATAC-seq pipeline](https://www.encodeproject.org/atac-seq/) and [Yiwei Niu's excellent guide](https://yiweiniu.github.io/blog/2019/03/ATAC-seq-data-analysis-from-FASTQ-to-peaks/). bcbio aligns the reads and cleans up the alignments, removing duplicates, multimappers and reads aligning to mitochondria. It then breaks up the BAM files into separate BAM files for nucleosome free (NF), mononucleosome (MN), dinucleosome (DN) and trinucleosome (TN) fractions and calls peaks separately on each fraction and also calls peaks on all of the fractions together. Consensus peaks of the nucleosome free peaks are created by choosing the peak with the highest score when peaks overlap, described more in depth in the [bedops documentation](https://bedops.readthedocs.io/en/latest/content/usage-examples/master-list.html). A matrix of peak counts is created with featureCounts that can be used with downstream count-based differential expression callers like DESeq2/limma/edgeR. ENCODE quality control metrics and other quality control information is added to the [MultiQC](https://multiqc.info) report. A separate ATAC-seq specific quality control report is generated using [ataqv](https://github.com/ParkerLab/ataqv). For CHIP-seq analysis use this config: [chip_seq.yaml](https://github.com/bcbio/bcbio-nextgen/blob/master/config/examples/chip_seq.yaml). ## Description of example dataset We will be using [ENCSR312LQX](https://www.encodeproject.org/experiments/ENCSR312LQX) and [ENCSR310MLB](https://www.encodeproject.org/experiments/ENCSR310MLB/) from the ENCODE project as our example datasets. These are P0 samples from the mouse hindbrain and mouse forebrain, each with a single replicate each. We'll use these samples to call differential affinity between the mouse hindbrain and forebrain. ### 1. Download the example data and configuration files This downloads the input data, creates the project structure and example configuration files. #### 1.1 Create input directory and download FASTQ files. ```bash mkdir atac-example cd atac-example mkdir -p fastq # hindbrain samples wget --no-check-certificate https://www.encodeproject.org/files/ENCFF547YID/@@download/ENCFF547YID.fastq.gz -O fastq/hindbrain_rep1_R1.fastq.gz wget --no-check-certificate https://www.encodeproject.org/files/ENCFF131VHT/@@download/ENCFF131VHT.fastq.gz -O fastq/hindbrain_rep1_R2.fastq.gz wget --no-check-certificate https://www.encodeproject.org/files/ENCFF971XEA/@@download/ENCFF971XEA.fastq.gz -O fastq/hindbrain_rep2_R1.fastq.gz wget --no-check-certificate https://www.encodeproject.org/files/ENCFF215WAD/@@download/ENCFF215WAD.fastq.gz -O fastq/hindbrain_rep2_R2.fastq.gz # forebrain samples wget --no-check-certificate https://www.encodeproject.org/files/ENCFF296GZG/@@download/ENCFF296GZG.fastq.gz -O fastq/forebrain_rep1_R1.fastq.gz wget --no-check-certificate https://www.encodeproject.org/files/ENCFF664RZO/@@download/ENCFF664RZO.fastq.gz -O fastq/forebrain_rep1_R2.fastq.gz wget --no-check-certificate https://www.encodeproject.org/files/ENCFF197GTC/@@download/ENCFF197GTC.fastq.gz -O fastq/forebrain_rep2_R1.fastq.gz wget --no-check-certificate https://www.encodeproject.org/files/ENCFF209GGJ/@@download/ENCFF209GGJ.fastq.gz -O fastq/forebrain_rep2_R2.fastq.gz ``` #### 1.2 Download template YAML file describing the ATAC-seq analysis ```bash mkdir -p metadata wget --no-check-certificate http://s3.amazonaws.com/bcbio-nextgen/atac_userstory_data/atac-example.yaml -O metadata/atac-example.yaml ``` atac-example.yaml: ```yaml details: - analysis: chip-seq genome_build: mm10 algorithm: aligner: bwa peakcaller: [macs2] chip_method: atac keep_duplicates: False keep_multimapped: False upload: dir: ../final ``` #### 1.3 Create a sample sheet ```bash wget --no-check-certificate http://s3.amazonaws.com/bcbio-nextgen/atac_userstory_data/hindbrain_forebrain.csv -O metadata/hindbrain_forebrain.csv ``` #### For ATAC-Seq hindbrain_forebrain.csv: ``` samplename,description,region,replicate forebrain_rep1_R1.fastq.gz,forebrain_rep1,forebrain,rep1 forebrain_rep2_R1.fastq.gz,forebrain_rep2,forebrain,rep2 hindbrain_rep1_R1.fastq.gz,hindbrain_rep1,hindbrain,rep1 hindbrain_rep2_R1.fastq.gz,hindbrain_rep2,hindbrain,rep2 ``` The only two fields required in this file are `samplename` and `description`, you can put whatever you want for the other columns. We recommend adding any additional metdata you know about the samples here. ##### For ChIP-Seq ``` samplename,description,batch,phenotype,replicate,treatment,antibody Lib4.R1.bc.2.WTMTF2.fq,WTMTF2_1,pair1,chip,1,WT,narrow Lib9.R1R2.bc.19.WTMTF2.fq,WTMTF2_2,pair2,chip,2,WT,narrow Lib3.bc.1.WTH3K27ME3.fq,WTH3k27ME3_1,pair3,chip,1,WT,H3k27ME3 Lib9.R1R2.bc.1.WTH3K27ME3.fq,WTH3k27ME3_2,pair4,chip,2,WT,H3k27ME3 Lib2.bc.1.MKOFLAG.fq,MTF2KO_1,pair5,chip,1,MTF2KO,narrow Lib9.R1R2.bc.30.MKOFLAG.fq,MTF2KO_2,pair6,chip,2,MTF2KO,narrow Lib2.bc.2.MKOWTFLAG.fq,MTF2KO_WTRES_1,pair7,chip,1,MTF2KO_WTRES,narrow Lib9.R1R2.bc.31.MKOWTFLAG.fq,MTF2KO_WTRES_2,pair8,chip,2,MTF2KO_WTRES,narrow Lib2.bc.15.MKOMUTFLAG.fq,MTF2KO_MUTRES_1,pair9,chip,1,MTF2KO_MUTRES,narrow Lib9.R1R2.bc.32.MKOMUTFLAG.fq,MTF2KO_MUTRES_2,pair10,chip,2,MTF2KO_MUTRES,narrow Lib3.bc.7.EKOH3K27ME3.fq,EEDKO_1,pair11,chip,1,EEDKO,H3k27ME3 Lib3.bc.8.EKOH3K27ME3.fq,EEDKO_2,pair12,chip,2,EEDKO,H3k27ME3 Lib10.R1R2.bc.3.EKOWTRES.fq,EKOWT_1,pair13,chip,1,EKO_WT,H3k27ME3 Lib10.R1R2.bc.5.EKOWTRES.fq,EKOWT_2,pair14,chip,2,EKO_WT,H3k27ME3 Lib8.R1R2.bc.16.EKOMUTRES.fq,EKOMUT_1,pair15,chip,1,EKO_MUT,H3k27ME3 Lib10.R1R2.bc.4.EKOMUTRES.fq,EKOMUT_2,pair16,chip,2,EKO_MUT,H3k27ME3 Lib2.bc.14.INPUT.fq,input_global,pair1;pair2;pair3;pair4;pair5;pair6;pair7;pair8;pair9;pair10;pair11;pair12;pair13;pair14;pair15;pair16,input,1,WT,Input ``` For ChIP-seq, bcbio requires `batch` and `phenotype` in addition. However, please note that the `antibody` column should be added with caution. - Valid antibodies are: {'h3k36me3', 'narrow', 'h3k4me1', 'h2afz', 'h3ac', 'h4k20me1', 'h3k4me3', 'h3k4me2', 'h3k9ac', 'h3k79me2', 'h3k9me2', 'h3f3a', 'h3k79me3', 'h3k27me3', 'broad', 'h3k9me3', 'h3k9me1', 'h3k27ac'}. If you know your antibody should be called with narrow or broad peaks, supply 'narrow' or 'broad' as the antibody. ``` Bcbio will call narrow peaks if you have a antibody column, but do not have a vaild antibody within that list. By default, you will get *.narrowPeak files if you do not have a antibody column. ``` ### 2. Generate YAML config file for analysis ```bash bcbio_nextgen.py -w template metadata/atac-example.yaml metadata/hindbrain_forebrain.csv fastq ``` In the result you should see a folder structure: ``` hindbrain_forebrain |---config |---final |---work ``` `hindbrain_forebrain/config/hindbrain_forebrain.yaml` is the main config file to run the bcbio project. You will see this file has a copy of the parameters in `atac-example.yaml` for each sample. ### 3. Run the analysis This will run the analysis on a local machine, using 16 cores. ```bash cd hindbrain_forebrain/work bcbio_nextgen.py ../config/hindbrain_forebrain.yaml -n 16 ``` ## Parameters * `peakcaller`: `[macs2]` bcbio just supports MACS2 * `aligner`: supports `bowtie2` and `bwa`. `bwa` will result in a superset of the peaks called by `bowtie2`. * `chip_method`: set to `atac` to run the ATAC-seq pipeline * `keep_duplicates`: do not remove duplicates before peak calling. Defaults to _False_. * `keep_multimapped`: do not remove multimappers before peak calling. Defaults to _False_. ## Output ### Project directory ``` ├── 2020-05-01_hindbrain_forebrain │   ├── ataqv │   │   ├── index.html -- QC report from ataqv │   ├── bcbio-nextgen-commands.log -- list of commands run by bcbio │   ├── bcbio-nextgen.log -- stdout of bcbio log │   ├── consensus │   │   ├── consensus.bed -- consensus peaks from NF fraction │   │   ├── consensus-counts.tsv -- table of alignments per peak for each sample, calculated by featureCounts │   ├── data_versions.csv -- versions of data used in the pipeline │   ├── metadata.csv -- supplied metadata about the samples │   ├── multiqc │   │   ├── multiqc_report.html -- multiQC report with useful quality control metrics │   ├── programs.txt -- versions of programs run in the pipeline ``` ### Sample directories ``` ├── forebrain_rep1 │   ├── forebrain_rep1-DN.bam -- dinucleosome alignments │   ├── forebrain_rep1-full.bam -- all fraction alignments │   ├── forebrain_rep1-MN.bam -- mononucleosome alignments │   ├── forebrain_rep1-NF.bam -- nucleosome-free alignments │   ├── forebrain_rep1-ready.bam -- identifical to -full │   ├── forebrain_rep1-ready.bam.bai │   ├── forebrain_rep1-ready.bw -- bigwig file of full alignments │   ├── forebrain_rep1-TN.bam -- trinucleosome alignments │   ├── macs2 -- contains peak calls for each fraction, including the full peak calls ``` read.bam contains only uniquely mapped non-duplicated reads, see [bam cleaning function](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/chipseq/__init__.py#L18). The stats in the `project/multiqc/multiqc_report.html` include all reads (duplicated, multimappers). ## Downstream analysis ### Quality Control The **MultiQC** report in the project directory under `multiqc/multiqc_report.html` and at the **ataqv** report in the project directory under `ataqv/ataqv_report.html` have useful quality control information that you can use to help decide if your ATAC-seq project worked. It is hard to give specific cutoffs of metrics to use since the kit, the sample material, the organism, the genome annotations and so on all affect all of the metrics. We generally look at the samples as a whole for an experiment and see if any of the samples are outliers in the important metrics. In the **MultiQC** report, we look at the percentage of reads in the peaks, the mapping percentage, the [ENCODE library complexity statistics](https://www.encodeproject.org/data-standards/terms/) and the FastQC metrics to try to spot samples with problems. In the **ataqv** report, we look at the HQAA fragment length distribution plot. Ideally, this plot should show a periodic uptick every 200 bases, which corresponds to the different nucleosome fractions. The samples should be enriched for < 100 which is the nucleosome free fraction, 200 for the mononucleosome fraction, 400 for the dinucleosome fraction and 600 for the trinucleosome fraction. Often you will not see this behavior though even in libraries that were successful. But if some of your samples have this and others do not, that is something to be concerned about. You should see an enrichment around the transcription start sites, if you are missing that then your experiment likely failed. The **peaks** table in the **tables** tab in the **ataqv** report has a measurement of the high quality autosomal alignments overlapping peaks, **ataqv** calculates this metric using all of the peaks, not just the peaks from the nucleosome-free fraction, so this is useful to look at as well. See the [ataqv github repository](https://github.com/ParkerLab/ataqv/issues/13) for a discussion of the ranges of values you can expect to see for metrics in the **ataqv** report along with other values to look at that might be informative. The Parker lab reprocessed samples from many publications with **ataqv** and posted the reports [here](https://theparkerlab.med.umich.edu/data/porchard/ataqv-public-survey/) which is helpful to browse through to get an idea of what ranges of values you can expect. As you can see, they can be all over the place. #### hindbrain vs forebrain QC reports - [MultiQC report](http://atac-userstory.s3-website.us-east-2.amazonaws.com/multiqc_report.html) - [ataqv report](http://atac-userstory.s3-website.us-east-2.amazonaws.com) ### Differential affinity analysis For doing differential affinity analysis we recommend loading the consensus peak table from the `consensus/consensus.counts` file in the project directory. This is a table of counts per peak in the nucleosome-free fraction for each sample that you can use in any standard count-based differential expression tools like [DESeq2]( https://bioconductor.org/packages/release/bioc/html/DESeq2.html)/[edgeR](https://bioconductor.org/packages/release/bioc/html/edgeR.html)/[limma](https://bioconductor.org/packages/release/bioc/html/limma.html). Often you will find tutorials using [DiffBind](https://bioconductor.org/packages/release/bioc/html/DiffBind.html) but that uses these callers under the hood, so you can just call them directly and skip an intermediate step if you want. Either way works. The DiffBind tutorials are great for understanding how to go about with your downstream analyses. #### hindbrain vs forebrain differential affinity reports - [RMarkdown](http://atac-userstory.s3-website.us-east-2.amazonaws.com/peaks.Rmd) - [HTML report](http://atac-userstory.s3-website.us-east-2.amazonaws.com/peaks.html) - [example data](http://atac-userstory.s3-website.us-east-2.amazonaws.com/differential-affinity-example.tar.gz) bcbio-nextgen-1.2.9/docs/contents/bulk_rnaseq.md000066400000000000000000000351261415626112400216750ustar00rootroot00000000000000# Bulk RNA-seq Bulk RNA-seq pipeline in bcbio: - aligns reads with STAR (2pass), or hisat2 vs genome and transcriptome references (human, mouse, custom references); - quantifies expression counts with salmon, kallisto; - runs quality control; - calculates TPM with tximport; - detects rusions with arriba, pizzly; - creates a SummarizedExperiment object for downstream analysis in R; - calls variants with gatk or with vardict; - supports [spike-in](https://en.wikipedia.org/wiki/RNA_spike-in) calibration ## Workflow This example processes 6 RNA-seq samples from the [FDA's Sequencing Quality Control project](http://www.fdaseqc.org/). ### 1. Install STAR index (if there is no STAR in the current bcbio installation) ```bash bcbio_nextgen.py upgrade -u skip --genomes hg38 --aligners star --cores 10 ``` ### 2. Setup bcbio project Download input data, create project structure and config files. This will download six samples from the SEQC project, three from the HBRR panel and three from the UHRR panel (100G download). : ```shell wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/rnaseq-seqc-getdata.sh bash rnaseq-seqc-getdata.sh ``` Step 2 in detail: #### 2.1 Create input directory and download fastq files ```bash mkdir -p seqc/input ``` #### 2.2 Download a template yaml file describing RNA-seq analysis ```bash wget --no-check-certificate https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/rnaseq-seqc.yaml ``` rnaseq-seqc.yaml: ```yaml # Template for human RNA-seq using Illumina prepared samples --- details: - analysis: RNA-seq genome_build: hg38 algorithm: aligner: star expression_caller: - salmon - kallisto fusion_caller: - arriba - pizzly quality_format: standard strandedness: auto trim_reads: false quantify_genome_alignments: true upload: dir: ../final resources: star: cores: 10 memory: 10G ``` #### 2.3 Download fastq files into input dir ```bash cd seqc/input for SAMPLE in SRR950078 SRR950079 SRR950080 SRR950081 SRR950082 SRR950083 do wget -c -O ${SAMPLE}_1.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR950/${SAMPLE}/${SAMPLE}_1.fastq.gz wget -c -O ${SAMPLE}_2.fastq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR950/${SAMPLE}/${SAMPLE}_2.fastq.gz done cd ../../ ``` #### 2.4 Prepare a sample sheet ``` wget -c --no-check-certificate https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/seqc.csv ``` seqc.csv: ``` samplename,description,panel SRR950078,UHRR_rep1,UHRR SRR950079,HBRR_rep1,HBRR SRR950080,UHRR_rep2,UHRR SRR950081,HBRR_rep2,HBRR SRR950082,UHRR_rep3,UHRR SRR950083,HBRR_rep3,HBRR ``` #### 2.5 Generate yaml config file for analysis project.yaml = template.yaml x sample_sheet.csv ``` bcbio_nextgen.py -w template rnaseq-seqc.yaml seqc.csv seqc/input/*.gz ``` In the result you should see a folder structure: ``` seqc |---config |---input |---final |---work ``` `seqc/config/seqc.yaml` is the main config file to run the bcbio project. ### 3. Run the analysis: Single node: ```bash cd seqc/work bcbio_nextgen.py ../config/seqc.yaml -n 8 ``` ipython: `sbatch bcbio.sh`: ```bash #!/bin/bash # https://slurm.schedmd.com/sbatch.html #SBATCH --partition=priority # Partition (queue) #SBATCH --time=5-00:00:00 # Runtime in D-HH:MM format #SBATCH --job-name=bulkrnatest # Job name #SBATCH -c 1 #SBATCH --mem-per-cpu=10G # Memory needed per CPU #SBATCH --output=project_%j.out # File to which STDOUT will be written, including job ID #SBATCH --error=project_%j.err # File to which STDERR will be written, including job ID #SBATCH --mail-type=NONE # Type of email notification (BEGIN, END, FAIL, ALL) bcbio_nextgen.py ../config/seqc.yaml -n 72 -t ipython -s slurm -q medium -r t=0-72:00 -r conmem=20 --timeout 3000 --tag "rna" ``` ## Parameters * `transcript_assembler` If set, will assemble novel genes and transcripts and merge the results into the known annotation. Can have multiple values set in a list. Supports ['cufflinks', 'stringtie']. * `transcriptome_align` If set to True, will also align reads to just the transcriptome, for use with EBSeq and others. * `expression_caller` A list of optional expression callers to turn on. Supports ['cufflinks', 'express', 'stringtie', 'dexseq', 'kallisto']. Salmon and count based expression estimation are run by default. Sailfish is deprecated. * `fusion_caller` A list of optional fusion callers to turn on. Supports [oncofuse, pizzly, ericscript, arriba]. * `variantcaller` Variant calling algorithm to call variants on RNA-seq data. Supports [gatk-haplotype] or [vardict]. * `spikein_fasta` A FASTA file of spike in sequences to quantitate. There are quantitated separately, so should be things you are not expecting to match anywhere to the genome or trancriptome of the species you are working with. * `quantify_genome_alignments` If set to True, run Salmon quantification using the genome alignments from STAR, when available. If STAR alignments are not available, use Salmon's SA mode with decoys. * `transcriptome_gtf` A GTF file to use to specify transcripts which will override the bcbio-installed versions. This is used if you have an alternate transcriptome you want to quantitate. You can also use this option to add your own transcripts to a set to quantitate, just append them to your GTF file and sort it. * `transcriptome_fasta` A fasta file - transcriptome fasta reference, use along with the transcriptome_gtf to override the installed references. How to generate the fasta with [gffread](http://ccb.jhu.edu/software/stringtie/gff.shtml#gffread_ex). * `strandedness`: `[unstranded (default), firststrand, secondstrand, auto]`. Set if your library is stranded. For dUTP marked libraries, firststrand is correct; for Scriptseq prepared libraries, secondstrand is correct. The wrongly set strandedness could cause up to 90% count loss in salmon. If you are unsure run one sample with `unstranded` and infer strandedness from the data, see more info in the [HBC knowledgebase](https://github.com/hbc/knowledgebase/blob/master/rnaseq/strandedness.md). For example dUTP + [xGEN IDT UMI](https://www.idtdna.com/pages/products/next-generation-sequencing/adapters/xgen-udi-umi-adapters) gives secondstrand, not firststrand. We don't set strandedness in STAR, because it is irreversible, see [this discussion](https://github.com/COMBINE-lab/salmon/issues/590#issuecomment-733417813). Currently we don't set strandedness in kallisto as well. `auto` forces strand auto-detection in salmon with `-l A` option. See why auto strandedness and the properly set known strandedness give slightly different counts [here](https://github.com/COMBINE-lab/salmon/issues/669). * `disambiguation: mm10`- use for PDX samples. Aligns reads to human and mouse genome. `quantify_genome_alignments: true` with disambiguation does not produce mouse counts in the final counts file becase the refined STAR alignment is used as salmon input, also this combination might produce a lot of messages in the stderr (20M) and fail for some AWS instances. If you need human and mouse counts, use pseudoalignment with `quantify_genome_alignments: false`. ## QC and Basic DE analysis By default, bcbio runs simple [R scripts](https://github.com/bcbio/bcbio-nextgen/tree/master/bcbio/scripts/R). To make them work, you need >1 sample, and `category` in the metadata for each sample: ```yaml algorithm: aligner: star strandedness: unstranded metadata: category: normal ``` If there is no category in the yaml, the script assigns the same `fake_category` to all samples. A more comprehensive QC and DE analysis is possible with [bcbiornaseq](https://bioinformatics.sph.harvard.edu/bcbioRNASeq/) * `bcbiornaseq` A dictionary of key-value pairs to be passed as options to bcbioRNAseq. Currently supports _organism_ as a key and takes the latin name of the genome used (_mus musculus_, _homo sapiens_, etc) and _interesting_groups_ which will be used to color quality control plots: ```yaml algorithm: tools_on: [bcbiornaseq] bcbiornaseq: organism: homo sapiens interesting_groups: [treatment, genotype, etc, etc] ``` ## Output ### RNA-seq Project directory: ``` ├── counts ├── tximport-counts.csv -- gene-level counts for DE analysis generated from salmon counts by tximport ├── bcbio-se.rds -- SummarizedExperiment object with all counts bcbio-se.html -- a simple Rmd QC report ├── annotated_combined.counts -- gene counts with symbols from featureCounts (don't use this) ├── bcbio-nextgen-commands.log -- commands run by bcbio ├── bcbio-nextgen.log -- logging information from bcbio run ├── combined.counts -- gene counts with gene IDs from featureCounts (don't use this) ├── metadata.csv -- provided metadata about each sample ├── multiqc     ├── multiqc_report.html -- multiQC report ├── programs.txt -- program versions of tools run ├── project-summary.yaml -- YAML description of project, with derived metadata └── tx2gene.csv -- transcript to gene mappings for use with tximport ``` Sample directories: ``` S1 ├── S1-ready.bam -- coordinate-sorted whole genome alignments ├── S1-ready.counts -- featureCounts counts (don't use this) ├── S1-transcriptome.bam -- alignments to the transcriptome ├── salmon │ ├── abundance.h5 -- h5 object, usable with sleuth │ └── quant.sf -- salmon quantifications, usable with tximport └── STAR     ├── S1-SJ.bed -- STAR junction file in BED format     └── S1-SJ.tab -- STAR junction file in tabular format ``` bcbioRNASeq directory: ``` bcbioRNASeq/ ├── data │ ├── bcb.rda -- bcbioRNASeq object with gene-level data ├── data-transcript │ ├── bcb.rda -- bcbioRNASeq object with transcript-level data ├── quality_control.html -- quality control report ├── quality_control.Rmd -- RMarkdown that generated quality control report ├── results │ └── 2019-11-21 │ ├── gene -- gene level information │ │ └── counts │ │ ├── counts.csv.gz -- count matrix from tximport, suitable for count-based analyses │ │ └── metadata.csv.gz -- metadata and quality control data for samples │ ├── quality_control │ │ └── tpm.csv.gz -- TPM from tximport, use for visualization │ └── transcript -- transcript level information │ └── counts │ ├── counts.csv.gz -- transcript level count matrix, suitable for count-based analyses needed transcript-level data │ └── metadata.csv.gz -- metadata and quality control for samples ``` Workflow for analysis: For gene-level analyses, we recommend loading the gene-level counts.csv.gz and the metadata.csv.gz and using [DESeq2](https://bioconductor.org/packages/release/bioc/html/DESeq2.html) to do the analysis. For a more in-depth walkthrough of how to use DESeq2, refer to our [DGE_workshop](https://hbctraining.github.io/DGE_workshop_salmon/schedule/). For transcript-level analyses, we recommend using [sleuth](https://seqcluster.readthedocs.io/mirna_annotation.html) with the bootstrap samples. You can load the abundance.h5 files from Salmon, or if you set `kallisto` as an expression caller, use the abundance.h5 files from that. Another great alternative is to use the Salmon quantification to look at differential transcript usage (DTU) instead of differential transcript expression (DTE). The idea behind DTU is you are looking for transcripts of genes that have been flipped from one isoform to another. The [Swimming downstream](https://www.bioconductor.org/packages/devel/workflows/vignettes/rnaseqDTU/inst/doc/rnaseqDTU.html#salmon-quantification) tutorial has a nice walkthrough of how to do that. ## Steps Step are outlined [here](https://www.michaelchimenti.com/2019/03/bcbio-rna-seq-under-the-hood/) ## Description RNA-seq pipeline includes steps for quality control, adapter trimming, alignment, variant calling, transcriptome reconstruction and post-alignment quantitation at the level of the gene and isoform. We recommend using the STAR aligner for all genomes. Use Tophat2 only if you do not have enough RAM available to run STAR (about 30 GB). Our current recommendation is to run adapter trimming only if using the Tophat2 aligner. Adapter trimming is very slow, and aligners that soft clip the ends of reads such as STAR and hisat2, or algorithms using pseudoalignments like Salmon handle contaminant sequences at the ends properly. This makes trimming unnecessary. Tophat2 does not perform soft clipping so if using Tophat2, trimming must still be done. Salmon, which is an extremely fast alignment-free method of quantitation, is run for all experiments. Salmon can accurately quantitate the expression of genes, even ones which are hard to quantitate with other methods (see [this paper](https://doi.org/10.1186/s13059-015-0734-x) for example for Sailfish, which performs similarly to Salmon). Salmon can also quantitate at the transcript level which can help gene-level analyses (see [this paper](https://doi.org/10.12688/f1000research.7563.1) for example). We recommend using the Salmon quantitation rather than the counts from featureCounts to perform downstream quantification. Still, we had at least two projects with initally low % mapped (STAR) at 50-70% which greatly benefited from trimming both in terms of % mapped and N mapped reads. We trimmed with bcbio.yaml: ```yaml algorithm: trim_reads: read_through adapters: illumina ``` or with [fastp](https://github.com/OpenGene/fastp) ```bash #!/bin/bash fastp -I {input.R1]} -I {input.R2} -o {output.R1_trim_fastq} -O {output.R2_trim_fastq} -h {output.fastp_html} -g -x -5 -3 # Additional flag definitions: # -g trims polyG, common artifact in Illumina 2-dye sequencing chemistry (MiniSeq, NextSeq, Novaseq) # -x trims polyX, any other homopolymeric stretch # -5 sliding window 5’ quality trimming # -3 sliding window 3’ quality trimming ``` Although we do not recommend using the featureCounts based counts, the alignments are still useful because they give you many more quality metrics than the quasi-alignments from Salmon. After a bcbio RNA-seq run there will be in the `upload` directory a directory for each sample which contains a BAM file of the aligned and unaligned reads, a `salmon` directory with the output of Salmon, including TPM values, and a `qc` directory with plots from FastQC and qualimap. In addition to directories for each sample, in the `upload` directory there is a project directory which contains a YAML file describing some summary statistics for each sample and some provenance data about the bcbio run. In that directory is also a `combined.counts` file with the featureCounts derived counts per cell. bcbio-nextgen-1.2.9/docs/contents/citations.md000066400000000000000000000373441415626112400213700ustar00rootroot00000000000000# Citations If you use bcbio in your work, please cite it via Zenodo to help us track how and where it is being used: Please cite individual tools in the manuscript methods, not just bcbio. To promote citation, we are maitaining easy-to-paste reference lists below. Feel free to contribute, if you see a tool that is used through bioconda, but is not included here. Try to look at the particular tool's documentation, article, and github issues before submitting an issue to bcbio. This might help to discriminate early between bcbio issues and tools' issues. The authors of the tool might be of better help to fix the issue. Raising the issue in tool's github and referencing it in bcbio github issue could speed up its resolution. ## Variant calling Overall, the parameters of our variant calling workflows are based on GATK best practices (https://gatk.broadinstitute.org/hc/en-us/sections/360007226651-Best-Practices-Workflows), contributions from bcbio community (https://github.com/bcbio/bcbio-nextgen) and our validations (https://github.com/bcbio/bcbio_validations/). ## Read alignment We align reads with `bwa mem` [1], using samtools [2], and sambamba [3], to sort bam files and mark duplicate reads. 1. Li H. Aligning sequence reads, clone sequences and assembly contigs with BWA-MEM. 2013 arXiv:1303.3997. https://github.com/lh3/bwa. 2. Li H, Handsaker B, Wysoker A, Fennell T, Ruan J, Homer N, Marth G, Abecasis G, Durbin R, and 1000 Genome Project Data Processing Subgroup, The Sequence alignment/map (SAM) format and SAMtools, Bioinformatics (2009) 25(16) 2078-9 [19505943]. https://github.com/samtools/. 3. A. Tarasov, A. J. Vilella, E. Cuppen, I. J. Nijman, and P. Prins. Sambamba: fast processing of NGS alignment formats. Bioinformatics, 2015. https://github.com/biod/sambamba. ## Interval arithmetics. We use bedtools[1] and pybedtools[2] to wok with genomic intervals 1. Quinlan AR and Hall IM, 2010. BEDTools: a flexible suite of utilities for comparing genomic features. Bioinformatics. 26, 6, pp. 841–842. 2. Dale RK, Pedersen BS, and Quinlan AR. Pybedtools: a flexible Python library for manipulating genomic datasets and annotations. Bioinformatics (2011). doi:10.1093/bioinformatics/btr539 ## Quality control We run many tools to gather QC metrics: - peddy [1] - verifybamid (https://genome.sph.umich.edu/wiki/VerifyBamID) - DKFZ bias filter(https://github.com/DKFZ-ODCF/DKFZBiasFilter) - fastqc (https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) - qualimap (http://qualimap.bioinfo.cipf.es/) - samtools (https://github.com/samtools/) - bcftools (http://www.htslib.org/doc/bcftools.html) We aggregate all metrics in a single QC report with multiqc [2]. 1. Pedersen BS, Quinlan AR. Who's Who? Detecting and Resolving Sample Anomalies in Human DNA Sequencing Studies with Peddy. Am J Hum Genet. 2017;100(3):406‐413. doi:10.1016/j.ajhg.2017.01.017 https://github.com/brentp/peddy 2. Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PMID: 27312411; PMCID: PMC5039924.https://multiqc.info/ ## Coverage and callable regions We calculate coverage using mosdepth [1] and calculate callable regions based on real coverage and bed files provided. 1. Pedersen BS, Quinlan AR. Mosdepth: quick coverage calculation for genomes and exomes. Bioinformatics. 2018;34(5):867‐868. doi:10.1093/bioinformatics/btx699. https://github.com/brentp/mosdepth. ## SNP and indels in germline (WES, WGS, gene panels) We support variant calling in germline with: - gatk4x (https://github.com/broadinstitute/gatk/) - gatk3.8x (https://console.cloud.google.com/storage/browser/gatk-software/package-archive) - freebayes (https://github.com/ekg/freebayes) - samtools (https://github.com/samtools/) - octopus (https://github.com/luntergroup/octopus). We support: - single sample variant calling - batch variant calling - population variant calling (joint genotyping). ## Structural and copy number variants in germline (WGS data) We call structural variants with - manta [1] - lumpy [2] - delly [3] - wham [4] We annotate structural variant calls with coverage information using duphold (https://github.com/brentp/duphold) 1. Chen, X. et al. (2016) Manta: rapid detection of structural variants and indels for germline and cancer sequencing applications. Bioinformatics, 32, 1220-1222. doi:10.1093/bioinformatics/btv710. https://github.com/Illumina/manta 2. Layer RM, Chiang C, Quinlan AR, Hall IM. LUMPY: a probabilistic framework for structural variant discovery. Genome Biol. 2014;15(6):R84. Published 2014 Jun 26. doi:10.1186/gb-2014-15-6-r84. https://github.com/arq5x/lumpy-sv 3. Rausch T, Zichner T, Schlattl A, Stütz AM, Benes V, Korbel JO. DELLY: structural variant discovery by integrated paired-end and split-read analysis. Bioinformatics. 2012;28(18):i333‐i339. doi:10.1093/bioinformatics/bts378. https://github.com/dellytools/delly 4. Kronenberg ZN, Osborne EJ, Cone KR, et al. Wham: Identifying Structural Variants of Biological Consequence. PLoS Comput Biol. 2015;11(12):e1004572. Published 2015 Dec 1. doi:10.1371/journal.pcbi.1004572. https://github.com/zeeev/wham ## Somatic small variants We call somatic variants in tumor only or tumor/normal mode with: - mutect2 (https://gatk.broadinstitute.org/hc/en-us/articles/360037593851-Mutect2) - vardict: [vardict - Github](https://github.com/AstraZeneca-NGS/VarDict), [vardict-java - Github](https://github.com/AstraZeneca-NGS/VarDictJava), vardict - publication: Lai Z, Markovets A, Ahdesmaki M, Chapman B, Hofmann O, McEwen R, Johnson J, Dougherty B, Barrett JC, Dry JR. VarDict: a novel and versatile variant caller for next-generation sequencing in cancer research. Nucleic Acids Res. 2016 Jun 20;44(11):e108. doi: 10.1093/nar/gkw227. Epub 2016 Apr 7. PMID: 27060149; PMCID: PMC4914105. - strelka2 (https://github.com/Illumina/strelka) - varscan2 (Koboldt DC, Zhang Q, Larson DE, Shen D, McLellan MD, Lin L, Miller CA, Mardis ER, Ding L, & Wilson RK (2012). VarScan 2: Somatic mutation and copy number alteration discovery in cancer by exome sequencing. Genome Research PMID: 22300766) We support ensemble approach to combine somatic calls from several callers (https://github.com/bcbio/bcbio.variation.recall) ## Somatic copy number variants We use - gatk-cnv (https://gatkforums.broadinstitute.org/gatk/discussion/9143/how-to-call-somatic-copy-number-variants-using-gatk4-cnv) - pureCN (https://bioconductor.org/packages/release/bioc/html/PureCN.html) - seq2c (https://github.com/AstraZeneca-NGS/Seq2C) - titanCNA (https://github.com/gavinha/TitanCNA) - cnvkit ## Variant annotation We annotate variants with - VEP [1] - snpEff [2] - using vcfanno [3] (https://github.com/brentp/vcfanno) and many annotation sources: - gnomad (https://gnomad.broadinstitute.org/) - topmed (https://bravo.sph.umich.edu/freeze5/hg38/) - cosmic (https://cancer.sanger.ac.uk/cosmic) - dbsnp (https://www.ncbi.nlm.nih.gov/snp/) - dbnsfp (https://sites.google.com/site/jpopgen/dbNSFP) - clinvar (https://www.ncbi.nlm.nih.gov/clinvar/) We create a gemini database [4] as output (https://gemini.readthedocs.io/en/latest/). We support any internal vcf or bed based annotation (internal frequency database) via vcfanno. 1. McLaren W, Gil L, Hunt SE, et al. The Ensembl Variant Effect Predictor. Genome Biol. 2016;17(1):122. Published 2016 Jun 6. doi:10.1186/s13059-016-0974-4. https://useast.ensembl.org/info/docs/tools/vep/index.html 2. A program for annotating and predicting the effects of single nucleotide polymorphisms, SnpEff: SNPs in the genome of Drosophila melanogaster strain w1118; iso-2; iso-3.", Cingolani P, Platts A, Wang le L, Coon M, Nguyen T, Wang L, Land SJ, Lu X, Ruden DM. Fly (Austin). 2012 Apr-Jun;6(2):80-92. PMID: 22728672]. 3. Pedersen BS, Layer RM, Quinlan AR. Vcfanno: fast, flexible annotation of genetic variants. Genome Biol. 2016;17(1):118. Published 2016 Jun 1. doi:10.1186/s13059-016-0973-5. 4. Paila U, Chapman BA, Kirchner R, Quinlan AR. GEMINI: integrative exploration of genetic variation and genome annotations. PLoS Comput Biol. 2013;9(7):e1003153. doi:10.1371/journal.pcbi.1003153. ## bulk RNA-seq We align with STAR[1] or hisat[2], quantify transcripts with salmon[3], kallisto[4], stringtie [5]. 1. Dobin A, Davis CA, Schlesinger F, et al. STAR: ultrafast universal RNA-seq aligner. Bioinformatics. 2013;29(1):15‐21. doi:10.1093/bioinformatics/bts635 2. Kim D, Paggi JM, Park C, Bennett C, Salzberg SL. Graph-based genome alignment and genotyping with HISAT2 and HISAT-genotype. Nat Biotechnol. 2019;37(8):907‐915. doi:10.1038/s41587-019-0201-4 3. Patro R, Duggal G, Love MI, Irizarry RA, Kingsford C. Salmon provides fast and bias-aware quantification of transcript expression. Nat Methods. 2017;14(4):417‐419. doi:10.1038/nmeth.4197 4. Bray NL, Pimentel H, Melsted P, Pachter L. Near-optimal probabilistic RNA-seq quantification [published correction appears in Nat Biotechnol. 2016 Aug 9;34(8):888]. Nat Biotechnol. 2016;34(5):525‐527. doi:10.1038/nbt.3519 5. Pertea M, Pertea GM, Antonescu CM, Chang TC, Mendell JT, Salzberg SL. StringTie enables improved reconstruction of a transcriptome from RNA-seq reads. Nat Biotechnol. 2015;33(3):290‐295. doi:10.1038/nbt.3122 ## Fusion calling - RNA-seq We call fusions with oncofuse[1], pizzly[2], ericscript[3], arriba[4]. 4. Uhrig S. Arriba - Fast and accurate gene fusion detection from RNA-Seq data 2019. Available from: https://github.com/suhrig/arriba. ## ATAC-seq We are using ataqv[1] for quality control. 1. Orchard P, Kyono Y, Hensley J, Kitzman JO, Parker SCJ. Quantification, Dynamic Visualization, and Validation of Bias in ATAC-Seq Data with ataqv. Cell Syst. 2020;10(3):298‐306.e4. doi:10.1016/j.cels.2020.02.009 https://www.cell.com/cell-systems/pdfExtended/S2405-4712(20)30079-X https://github.com/ParkerLab/ataqv ## small RNA-seq Data was analyzed with bcbio-nextgen () using piDNA to detect the adapter, cutadapt to remove it, STAR/bowtie to align against the genome and seqcluster to detect small RNA transcripts. miRNAs were detected using miraligner tool with miRBase as the reference miRNA database. tRNA profiles were detected using tdrmapper tool. mirdeep2 was used for discovery of novel miRNAs. FastQC was used for QC metrics and multiqc for reporting. Download BIB format: ### Tools * Tsuji J, Weng Z. (2016) DNApi: A De Novo Adapter Prediction Algorithm for Small RNA Sequencing Data. 11(10):e0164228. * Andrews, S. (2010). FastQC: A quality control tool for high throughput sequence data. Bioinformatics. doi:citeulike-article-id:11583827 * Didion, J. P., Martin, M., & Collins, F. S. (2017). Atropos: specific, sensitive, and speedy trimming of sequencing reads. * Dale, R. K., Pedersen, B. S., & Quinlan, A. R. (2011). Pybedtools: A flexible Python library for manipulating genomic datasets and annotations. Bioinformatics, 27(24), 3423--3424. * Quinlan, A. R., & Hall, I. M. (2010). BEDTools: A flexible suite of utilities for comparing genomic features. Bioinformatics, 26(6), 841--842. * Tarasov, A., Vilella, A. J., Cuppen, E., Nijman, I. J., & Prins, P. (2015). Sambamba: Fast processing of NGS alignment formats. Bioinformatics, 31(12), 2032--2034. * Heger, A. (2009). Pysam. github.com. Retrieved from * Li, H. (2011). A statistical framework for SNP calling, mutation discovery, association mapping and population genetical parameter estimation from sequencing data. Bioinformatics, 27(21), 2987--2993. * Li, H., Handsaker, B., Wysoker, A., Fennell, T., Ruan, J., Homer, N., ... Durbin, R. (2009). The Sequence Alignment/Map format and SAMtools. Bioinformatics, 25(16), 2078--2079. * Pantano, L., Estivill, X., & Martí, E. (2010). SeqBuster, a bioinformatic tool for the processing and analysis of small RNAs datasets, reveals ubiquitous miRNA modifications in human embryonic cells. Nucleic Acids Research, 38(5), e34. Retrieved from * Pantano, L., Friedlander, M. R., Escaramis, G., Lizano, E., Pallares-Albanell, J., Ferrer, I., ... Marti, E. (2015). Specific small-RNA signatures in the amygdala at premotor and motor stages of Parkinson's disease revealed by deep sequencing analysis. Bioinformatics (Oxford, England). For the alignment, add what you have used: * Dobin, A., Davis, C. A., Schlesinger, F., Drenkow, J., Zaleski, C., Jha, S., ... Gingeras, T. R. (2013). STAR: Ultrafast universal RNA-seq aligner. Bioinformatics, 29(1), 15--21. * Langmead, B., Trapnell, C., Pop, M., & Salzberg, S. L. (2009). Ultrafast and memory-efficient alignment of short DNA sequences to the human genome. Genome Biology, 10, R25. * Kim, D., Langmead, B. & Salzberg, SL. (2016). HISAT: a fast spliced aligner with low memory requirements. Nature Methods, 12(4): 357--360. doi: 10.1038/nmeth.3317 If you used TopHat2 for alignment: * Kim, D., Pertea, G., Trapnell, C., Pimentel, H., Kelley, R. & Salzberg SL. (2013). TopHat2: accurate alignment of transcriptomes in the presence of insertions, deletions and gene fusions. Genome Biology, 14(4): R36. * Brueffer, C. & Saal, LH. (2016). TopHat-Recondition: A post-processor for TopHat unmapped reads. BMC Bioinformatics, 17(1):199. If you have in the output novel miRNA discovering, add: * Friedlander, M. R., MacKowiak, S. D., Li, N., Chen, W., & Rajewsky, N. (2012). MiRDeep2 accurately identifies known and hundreds of novel microRNA genes in seven animal clades. Nucleic Acids Research, 40(1), 37--52. If you have tRNA mapping output, add: * Selitsky, S. R., & Sethupathy, P. (2015). tDRmapper: challenges and solutions to mapping, naming, and quantifying tRNA-derived RNAs from human small RNA-sequencing data. BMC Bioinformatics, 16(1), 354. If you have miRge activated: * Yin Lu, Alexander S. Baras, Marc K Halushka. miRge2.0: An updated tool to comprehensively analyze microRNA sequencing data. bioRxiv.org. If you have MINTmap activated: * Loher, P, Telonis, AG, Rigoutsos, I. MINTmap: fast and exhaustive profiling of nuclear and mitochondrial tRNA fragments from short RNA-seq data. Sci Rep. 2017;7 :41184. doi: 10.1038/srep41184. PubMed PubMed Central PMC5318995. ### Data * Griffiths-Jones, S. (2004). The microRNA Registry. Nucleic Acids Research, 32(Database issue), D109--11. * Griffiths-Jones, S. (2006). miRBase: the microRNA sequence database. Methods in Molecular Biology (Clifton, N.J.), 342, 129--38. * Griffiths-Jones, S., Saini, H. K., Van Dongen, S., & Enright, A. J. (2008). miRBase: Tools for microRNA genomics. Nucleic Acids Research, 36(SUPPL. 1). * Kozomara, A., & Griffiths-Jones, S. (2011). MiRBase: Integrating microRNA annotation and deep-sequencing data. Nucleic Acids Research, 39(SUPPL. 1). * Kozomara, A., & Griffiths-Jones, S. (2014). MiRBase: Annotating high confidence microRNAs using deep sequencing data. Nucleic Acids Research, 42(D1). bcbio-nextgen-1.2.9/docs/contents/cloud.md000066400000000000000000000475411415626112400205010ustar00rootroot00000000000000# Cloud bcbio has two approaches to running on cloud providers like [Amazon Web Services (AWS)](https://aws.amazon.com/), [Google Cloud Platform (GCP)](https://cloud.google.com/) and [Microsoft Azure](https://azure.microsoft.com). For smaller projects we use a [simplified ansible based approach](https://github.com/bcbio/bcbio-nextgen/tree/master/scripts/ansible#simplified-bcbio-cloud-usage) which automates spinning up single multicore machines for running either traditional or [Common Workflow Language (CWL)](cwl) bcbio runs. For larger distributed projects, we're actively working on using [Common Workflow Language (CWL)](cwl) support with runners like [Cromwell](https://cromwell.readthedocs.io) that directly interface and run on cloud services. We'll document these approaches here as they're tested and available. For getting started, the CWL [Installation](contents/cwl:installation) documentation describes how to install [bcbio-vm](https://github.com/bcbio/bcbio-nextgen-vm), which provides a wrapper around bcbio that automates interaction with cloud providers and [Docker](https://www.docker.com/). `bcbio_vm.py` also cleans up the command line usage to make it more intuitive and provides a superset of functionality available in `bcbio_nextgen.py`. ## Google Cloud Platform Cromwell runs bcbio CWL pipelines on Google Cloud using the [Google Pipelines API](https://cloud.google.com/genomics/reference/rest/). ### GCP Setup To setup a Google Compute environment, you'll make use of the [Web based console](https://console.cloud.google.com) and [gcloud and gsutil from the Google Cloud SDK](https://cloud.google.com/sdk/), which provide command line interfacts to manage data in Google Storage and Google Compute instances. You can install with: ```shell bcbio_conda install -c conda-forge -c bioconda google-cloud-sdk ``` For authentication, you want to set up a [Google Cloud Platform service account](https://cloud.google.com/docs/authentication/production). The environmental variable `GOOGLE_APPLICATION_CREDENTIALS` identifies a [JSON file of credentials](https://cloud.google.com/docs/authentication/getting-started) which bcbio passes to Cromwell for authentication: ```shell gcloud auth login gcloud projects create your-project gcloud iam service-accounts create your-service-account gcloud projects add-iam-policy-binding your-project --member \ "serviceAccount:your-service-account@your-project.iam.gserviceaccount.com" --role "roles/owner" gcloud iam service-accounts keys create ~/.config/gcloud/your-service-account.json \ --iam-account your-service-account@your-project.iam.gserviceaccount.com export GOOGLE_APPLICATION_CREDENTIALS=~/.config/gcloud/your-service-account.json ``` You'll need a project for your run along, with the Google Genomics API enabled, and a Google Storage bucket for your data and run intermediates: ```shell gcloud config set project your-project gcloud services enable genomics.googleapis.com gsutil mb gs://your-project ``` Additional documentation for Cromwell: [Google Pipelines API](https://cromwell.readthedocs.io/en/stable/tutorials/PipelinesApi101/) and [Google authentication](https://cromwell.readthedocs.io/en/stable/backends/Google/). ### GCP data preparation Cromwell can localize data present in Google Storage buckets as part of the run process and bcbio will translate the data present in these storage bucket into references for the CWL run inputs. Upload your data with `gsutil`: ```shell gsutil cp your_data.bam gs://your-project/inputs/ ``` Create a `bcbio_system-gcp.yaml` input file for [Generating CWL for input to a tool](contents/cwl:generating%20CWL%20for%20input%20to%20a%20tool): ```yaml gs: ref: gs://bcbiodata/collections inputs: - gs://your-project/inputs resources: default: {cores: 8, memory: 3G, jvm_opts: [-Xms750m, -Xmx3000m]} ``` Then create a sample input CSV and template YAML file for [Automated sample configuration](contents/configuration:automated%20sample%20configuration). The first column of the CSV file should contain references to your input files (`your_file.bam` or `your_file_R1.fastq.gz;your_file_R2.fastq.gz`), which avoids needing to specify the inputs on the command line. Generate a Common Workflow Language representation: ```shell bcbio_vm.py template --systemconfig bcbio_system-gcp.yaml ${TEMPLATE}-template.yaml $PNAME.csv bcbio_vm.py cwl --systemconfig bcbio_system-gcp.yaml $PNAME/config/$PNAME.yaml ``` ### Running on GCP Run the CWL using Cromwell by specifying the project and root Google Storage bucket for intermediates: ```shell bcbio_vm.py cwlrun cromwell $PNAME-workflow --cloud-project your-project \ --cloud-root gs://your-project/work_cromwell ``` ## Amazon Web Services We're working to support [Amazon Web Services (AWS)](https://aws.amazon.com/) using AWS Batch and Cromwell, following the [AWS for Genomics documentation](https://docs.opendata.aws/genomics-workflows/). This documents the current work in progress; it is not yet fully running and needs [additional Cromwell development](https://github.com/broadinstitute/cromwell/issues/4586) for AWS CWL support. ### AWS Setup Optionally, create a bcbio [IAM user](https://aws.amazon.com/iam/) and bcbio keypair for creating AWS Batch specific resources. bcbio-vm can automate this process, although they can also be pre-existing. If you'd like to use bcbio-vm automation, you'll need to have an account at Amazon and your Access Key ID and Secret Key ID from the [AWS security credentials page](https://console.aws.amazon.com/iam/home?#security_credential). These can be [IAM credentials](https://aws.amazon.com/iam/getting-started/) instead of root credentials as long as they have administrator privileges. Make them available to bcbio using the standard environmental variables: ```shell export AWS_ACCESS_KEY_ID=your_access_key export AWS_SECRET_ACCESS_KEY=your_secret_key ``` With this in place, create public/private keys and a bcbio IAM user with: ```shell bcbio_vm.py aws iam --region=us-east-1 ``` 1. Use either existing credentials or those created by bcbio, setup [AWS Credentials](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration) for accessing AWS resources from your machine by editing `~/.aws/credentials`: ```ini [default] aws_access_key_id = YOURACCESSID aws_secret_access_key = yoursecretkey region = us-east-1 ``` 1. Automation creation of resources for AWS Batch. This includes creating a [custom Amazon Machine Image (AMI) for AWS Batch](https://docs.opendata.aws/genomics-workflows/aws-batch/create-custom-ami/), which allows automatic allocation of additional disk space during workflow runs. It also sets up an [AWS Batch environment, VPC and IAM for running workflows](https://docs.opendata.aws/genomics-workflows/aws-batch/configure-aws-batch-cfn/). A single bcbio-vm commands runs both CloudFormation scripts: ```shell bcbio_vm.py aws cromwell --keypair bcbio --bucket bcbio-batch-cromwell-test ``` This will output the S3 bucket and job queue for running Cromwell: ```shell AMI: ami-00bd75374ccaa1fc6 Region: us-east-1 S3 bucket: s3://your-project Job Queue (Spot instances): arn:aws:batch:us-east-1:678711657553:job-queue/GenomicsDefaultQueue-358a1deb9f4536b High priority Job Queue: arn:aws:batch:us-east-1:678711657553:job-queue/GenomicsHighPriorityQue-3bff21e3c4f44d4 ``` ### AWS data preparation The easiest way to organize AWS projects is using an analysis folder inside an [S3 bucket](https://aws.amazon.com/s3/). Create a bucket and folder for your analysis and upload input files (fastq or BAM) and other associated files. Bucket names should include only lowercase letters, numbers and hyphens (`-`) to conform to [S3 bucket naming restrictions](https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html) and avoid issues with resolution of SSL keys. You can create buckets and upload files using the [the AWS cli client](https://aws.amazon.com/cli/) or [AWS S3 web console](https://console.aws.amazon.com/s3/): ```shell aws s3 sync /local/inputs s3://your-bucket/inputs ``` Create a `bcbio_system-aws.yaml` input file for [Generating CWL for input to a tool](contents/cwl:generating%20CWL%20for%20input%20to%20a%20tool): ```yaml s3: ref: s3://bcbiodata/collections inputs: - s3://your-bucket/inputs resources: default: {cores: 8, memory: 3G, jvm_opts: [-Xms750m, -Xmx3000m]} ``` Generate a Common Workflow Language representation: ```shell CLOUD=aws bcbio_vm.py template --systemconfig bcbio_system-$CLOUD.yaml ${TEMPLATE}-template.yaml $PNAME.csv bcbio_vm.py cwl --systemconfig bcbio_system-$CLOUD.yaml $PNAME/config/$PNAME.yaml ``` ### Running on AWS Run the CWL using Cromwell by specifying the batch job queue [Amazon Resource Name (ARN)](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) and bucket from the setup process: ```shell bcbio_vm.py cwlrun cromwell $PNAME-workflow \ -cloud-project arn:aws:batch:us-east-1:678711657553:job-queue/GenomicsDefaultQueue-358a1deb9f4536b \ -cloud-root s3://your-project ``` ## Amazon Web Services (old) We're phasing out this approach to AWS support in bcbio and are actively moving to Common Workflow Language based approaches. This documents the old [Elasticluster](https://github.com/gc3-uzh-ch/elasticluster) approach to build a cluster on AWS with an encrypted NFS mounted drive and an optional Lustre shared filesystem. ### Data preparation You need a template file describing the type of run to do and a CSV file mapping samples in the bucket to names and any other metadata. See the [Automated sample configuration](contents/configuration:automated%20sample%20configuration) docs for more details about these files. Also upload both of these files to S3. With that in place, prepare and upload the final configuration to S3 with: ```shell bcbio_vm.py template s3://your-project/your-analysis/template.yaml s3://your-project/your-analysis/name.csv ``` This will find the input files in the `s3://your-project/your-analysis` bucket, associate fastq and BAM files with the right samples, and add a found BED files as `variant_regions` in the configuration. It will then upload the final configuration back to S3 as `s3://your-project/your-analysis/name.yaml`, which you can run directly from a bcbio cluster on AWS. By default, bcbio will use the us-east S3 region, but you can specify a different region in the s3 path to the metadata file: `s3://your-project@eu-central-1/your-analysis/name.csv` We currently support human analysis with both the GRCh37 and hg19 genomes. We can also add additional genomes as needed by the community and generally welcome feedback and comments on reference data support. ### Cluster setup The first time running bcbio on AWS you'll need to setup permissions, VPCs and local configuration files. We provide commands to automate all these steps and once finished, they can be re-used for subsequent runs. To start you'll need to have an account at Amazon and your Access Key ID and Secret Key ID from the [AWS security credentials page](https://console.aws.amazon.com/iam/home?#security_credential). These can be [IAM credentials](https://aws.amazon.com/iam/getting-started/) instead of root credentials as long as they have administrator privileges. Make them available to bcbio using the standard environmental variables: ```shell export AWS_ACCESS_KEY_ID=your_access_key export AWS_SECRET_ACCESS_KEY=your_secret_key ``` With this in place, two commands setup your elasticluster and AWS environment to run a bcbio cluster. The first creates public/private keys, a bcbio IAM user, and sets up an elasticluster config in `~/.bcbio/elasticluster/config`: ```shell bcbio_vm.py aws iam --region=us-east-1 ``` The second configures a VPC to host bcbio: ```shell bcbio_vm.py aws vpc --region=us-east-1 ``` The `aws vpc` command is idempotent and can run multiple times if you change or remove parts of the infrastructure. You can also rerun the `aws iam` command, but if you'd like to generate a new elasticluster configuration file (`~/.bcbio/elasticluster/config`) add the recreate flag: `bcbio_vm.py aws iam --recreate`. This generates a new set of IAM credentials and public/private keys. These are only stored in the `~/.bcbio` directory so you need to fully recreate them if you delete the old ones. ### Running a cluster Following this setup, you're ready to run a bcbio cluster on AWS. We start from a standard Ubuntu AMI, installing all software for bcbio and the cluster as part of the boot process. To configure your cluster run: ```shell bcbio_vm.py aws config edit ``` This dialog allows you to define the cluster size and machine resources you'd like to use. The defaults only have small instances to prevent accidentally starting an [expensive run](https://aws.amazon.com/ec2/pricing/). If you're planning a run with less than 32 cores, do not use a cluster and instead run directly on a single machine using one of the [large r3 or c3 instances](https://aws.amazon.com/ec2/instance-types/). This script also sets the size of the [encrypted NFS-mounted drive](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html), which you can use to store processing data when running across a distributed cluster. At scale, you can replace this with a Lustre shared filesystem. See below for details on launching and attaching a Lustre filesystem to a cluster. To ensure everything is correctly configured, run: ```shell bcbio_vm.py aws info ``` When happy with your setup, start the cluster with: ```shell bcbio_vm.py aws cluster start ``` The cluster will take five to ten minutes to start and be provisioned. If you encounter any intermittent failures, you can rerun the cluster configuration step with `bcbio_vm.py aws cluster setup` or the bcbio-specific installation with `bcbio_vm.py aws cluster bootstrap`. ### Running Lustre Elasticluster mounts the `/encrypted` directory as a NFS share available across all of the worker machines. You can use this as a processing directory for smaller runs but for larger runs may need a scalable distributed file system. bcbio supports using [Intel Cloud Edition for Lustre (ICEL)](https://wiki.hpdd.intel.com/display/PUB/Intel+Cloud+Edition+for+Lustre*+Software) to set up a Lustre scratch filesystem on AWS. * Subscribe to [ICEL in the Amazon Marketplace](https://aws.amazon.com/marketplace/pp/B00GK6D19A). * By default, the Lustre filesystem will be 2TB and will be accessible to all hosts in the VPC. Creation takes about ten minutes and can happen in parallel while elasticluster sets up the cluster. Start the stack: ```shell bcbio_vm.py aws icel create ``` If you encounter any intermittent failures when installing collectl plugin, that means lustre server is created successfully, you can rerun the lustre configuration step with `bcbio_vm.py aws icel create --setup`. If you had any failure creating the lustre server before the collectl plugin installation, you should stop it, and try again. * Once the ICEL stack and elasticluster cluster are both running, mount the filesystem on the cluster: ```shell bcbio_vm.py aws icel mount ``` * The cluster instances will reboot with the Lustre filesystem mounted. ### Running an analysis To run the analysis, connect to the head node with: ```shell bcbio_vm.py aws cluster ssh ``` Create your project directory and link the global bcbio configuration file in there with: * NFS file system (no Lustre): ```shell mkdir /encrypted/your-project cd !$ && mkdir work && cd work ``` - Lustre file system: ```shell sudo mkdir /scratch/cancer-dream-syn3-exome sudo chown ubuntu !$ cd !$ && mkdir work && cd work ``` If you started a single machine, run with: ```shell bcbio_vm.py run -n 8 s3://your-project/your-analysis/name.yaml ``` Where the `-n` argument should be the number of cores on the machine. To run on a full cluster: ```shell bcbio_vm.py ipythonprep s3://your-project/your-analysis/name.yaml slurm cloud -n 60 sbatch bcbio_submit.sh ``` Where 60 is the total number of cores to use across all the worker nodes. Of your total machine cores, allocate 2 for the base bcbio_vm script and IPython controller instances. The [SLURM workload manager](https://slurm.schedmd.com/) distributes jobs across your cluster on a queue called `cloud`. A `slurm-PID.out` file in the work directory contains the current status of the job, and `sacct_std` provides the status of jobs on the cluster. If you are new to SLURM, here is a summary of useful [SLURM commands](https://docs.rc.fas.harvard.edu/kb/running-jobs/#Summary_of_Slurm_commands). On successful completion, bcbio uploads the results of the analysis back into your s3 bucket and folder as `s3://your-project/your-analysis/final`. You can now cleanup the cluster and Lustre filesystem. ### Graphing resource usage AWS runs include automatic monitoring of resource usage with [collectl](http://collectl.sourceforge.net/). bcbio_vm uses collectl statistics to plot CPU, memory, disk and network usage during each step of a run. To prepare resource usage plots after finishing an analysis, first copy the `bcbio-nextgen.log` file to your local computer. Either use `bcbio_vm.py elasticluster sftp bcbio` to copy from the work directory on AWS (`/encrypted/your-project/work/log/bcbio-nextgen.log`) or transfer it from the output S3 bucket (`your-project/your-analysis/final/DATE_your-project/bcbio-nextgen.log`). If your run worked cleanly you can use the log input file directly. If you had failures and restarts, or would only like to graph part of the run, you can edit the timing steps. Run `grep Timing bcbio-nextgen.log > your-run.txt` to get the timing steps only, then edit as desired. Retrieve the collectl statistics from the AWS cluster and prepare the resource usage graphs with: ```shell bcbio_vm.py graph bcbio-nextgen.log ``` By default the collectl stats will be in `monitoring/collectl` and plots in `monitoring/graphs` based on the above log timeframe. If you need to re-run plots later after shutting the cluster down, you can use the _none_ cluster flag by running `bcbio_vm.py graph bcbio-nextgen.log --cluster none`. If you'd like to run graphing from a local non-AWS run, such as a local HPC cluster, run `bcbio_vm.py graph bcbio-nextgen.log --cluster local` instead. For convenience, there's a "serialize" flag ('-s') that saves the dataframe used for plotting. In order to explore the data and extract specific datapoints or zoom, one could just deserialize the output like a python pickle file: ```python import cPickle as pickle with gzip.open("./monitoring/collectl_info.pickle.gz", "rb") as decomp: collectl_info = pickle.load(decomp) data, hardware, steps = collectl_info[1][0], collectl_info[1][1], collectl_info[1][2] ``` And plot, slice, zoom it in an jupyter notebook using matplotlib, [highcharts](https://github.com/arnoutaertgeerts/python-highcharts). In addition to plots, the [summarize_timing.py](https://github.com/bcbio/bcbio-nextgen/blob/master/scripts/utils/summarize_timing.py) utility script prepares a summary table of run times per step. ### Shutting down The bcbio Elasticluster and Lustre integration can spin up a lot of AWS resources. You'll be paying for these by the hour so you want to clean them up when you finish running your analysis. To stop the cluster: ```shell bcbio_vm.py aws cluster stop ``` To remove the Lustre stack: ```shell bcbio_vm.py aws icel stop ``` Double check that all instances have been properly stopped by looking in the AWS console. ### Manual configuration Experienced [elasticluster](https://github.com/gc3-uzh-ch/elasticluster) users can edit the configuration files themselves. bcbio provides a small wrapper that automatically reads and writes these configurations to avoid users needing to understand elasticluster internals, but all functionality is fully available. Edit your `~/.bcbio/elasticluster/config` file to change parameters. You can also see the [latest example configuration](https://github.com/bcbio/bcbio-nextgen-vm/blob/master/elasticluster/config). in the bcbio-vm GitHub repository for more details on the other available options. bcbio-nextgen-1.2.9/docs/contents/configuration.md000066400000000000000000001677061415626112400222500ustar00rootroot00000000000000# Configuration ## Project structure bcbio encourages a project structure: ``` project/ ├── config ├── final ├── input └── work ``` with the `project.yaml` configuration in the `config` directory, the input files (fastq, bam, bed) in the `input` directory, the outputs of the pipeline in the `final` directory, and the actual processing done in the `work` directory. Typical bcbio run: * copy or link input files in the `input` directory * set pipeline parameters in `config/project.yaml` * run the `bcbio_nextgen.py` script from inside the `work` * review the results in `final` * delete `work` with intermediate files. ## System and sample configuration files Two configuration files, in easy to write [YAML format](https://en.wikipedia.org/wiki/YAML#Example), specify details about your system and samples to run: * `bcbio_sample.yaml` Details about a set of samples to process, including input files and analysis options. You configure these for each set of samples to process. This will be the main file prepared for each sample run and the documentation below details techniques to help prepare them. * `bcbio_system.yaml` High level information about the system, including locations of installed programs like GATK and cores and memory usage (see [Tuning core and memory usage](contents/parallel:tuning%20core%20and%20memory%20usage)). These apply across multiple runs. The automated installer creates a ready to go system configuration file that can be manually edited to match the system. Find the file in the galaxy sub-directory within your installation data location (ie. `/usr/local/share/bcbio-nextgen/galaxy`). To modify system parameters for a specific run, supply [sample or run specific resources](#sample-or-run-specific-resources) in your `bcbio_sample.yaml` file. Commented [system](https://github.com/bcbio/bcbio-nextgen/blob/master/config/bcbio_system.yaml) and [sample](https://github.com/bcbio/bcbio-nextgen/blob/master/config/bcbio_sample.yaml) example files are available in the `config` directory. ## Sample configuration ### Sample information The sample configuration file defines `details` of each sample to process: ```yaml details: - analysis: variant2 lane: 1 description: Example1 files: [in_pair_1.fq, in_pair_2.fq] genome_build: hg19 algorithm: platform: illumina metadata: batch: Batch1 sex: female platform_unit: flowcell-barcode.lane library: library_type ``` * `analysis` Analysis method to use [variant2, RNA-seq, smallRNA-seq] * `lane` A unique number within the project. Corresponds to the `ID` parameter in the BAM read group. * `description` Unique name for this sample, corresponding to the `SM` parameter in the BAM read group. Required. * `files` A list of files to process. This currently supports either a single end or two paired-end FASTQ files, or a single BAM file. It does not yet handle merging BAM files or more complicated inputs. * `genome_build` Genome build to align to, which references a genome keyword in Galaxy to find location build files. * `algorithm` Parameters to configure algorithm inputs. Options described in more detail below: * `platform` Sequencing platform used. Corresponds to the `PL` parameter in BAM read groups. Optional, defaults to `illumina`. * `metadata` Additional descriptive metadata about the sample: * `batch` defines a group that the sample falls in. We perform multi-sample variant calling on all samples with the same batch name. This can also be a list, allowing specification of a single normal sample to pair with multiple tumor samples in paired cancer variant calling (`batch: [MatchWithTumor1, MatchWithTumor2]`). * `sex` specifies the sample gender used to correctly prepare X/Y chromosomes. Use `male` and `female` or PED style inputs (1=male, 2=female). * `phenotype` stratifies cancer samples into `tumor` and `normal` or case/controls into `affected` and `unaffected`. Also accepts PED style specifications (1=unaffected, 2=affected). CNVkit uses case/control status to determine how to set background samples for CNV calling. * `disease` identifies a specific disease name for the sample. Used along with `svprioritize` to help identify gene regions for reporting during analysis with heterogeneity callers like PureCN and TitanCNA. This is primarily for cancer studies and you can narrow genes by disease using inputs like _lung_, _breast_ or _pancreatic_ for different cancer types. * `prep_method` A free text description of the method used in sample prep. Used to group together samples during CNV calling for background. This is not required and when not present bcbio assumes all samples in an analysis use the same method. * `svclass` defines a classification for a sample for use in SV case/control setups. When set as `control` will put samples into the background samples used for normalization. * `ped` provides a [PED phenotype file](http://zzz.bwh.harvard.edu/plink/data.shtml#ped) containing sample phenotype and family information. Template creation uses this to supplement `batch`, `sex` and `phenotype` information provided in the template CSV. GEMINI database creation uses the PED file as input. * `platform_unit` -- Unique identifier for sample. Optional, defaults to `lane` if not specified. * `library` -- Name of library preparation used. Optional, empty if not present. * `validate_batch` -- Specify a batch name to group samples together for preparing validation plots. This is useful if you want to process samples in specific batches, but include multiple batches into the same validation plot. * `validate_combine` -- Specify a batch name to combine multiple samples into an additional validation summary. Useful for larger numbers of small samples to evaluate together. ### Automated sample configuration bcbio-nextgen provides a utility to create configuration files for multiple sample inputs using a base template. Start with one of the [best-practice templates](https://github.com/bcbio/bcbio-nextgen/tree/master/config/templates), or define your own, then apply to multiple samples using the template workflow command: ```shell bcbio_nextgen.py -w template freebayes-variant project1.csv sample1.bam sample2_1.fq sample2_2.fq ``` * `freebayes-variant` is the name of the standard `freebayes-variant.yaml` input, which the script fetches from GitHub. This argument can also be a path to a locally customized YAML configuration. In both cases, the script replicates the single sample template configuration to all input samples. * `project1.csv` is a comma separated value file containing sample metadata, descriptions and algorithm tweaks: ``` samplename,description,batch,phenotype,sex,variant_regions sample1,ERR256785,batch1,normal,female,/path/to/regions.bed sample2,ERR256786,batch1,tumor,,/path/to/regions.bed ``` The first column links the metadata to a specific input file. The template command tries to identify the `samplename` from read group information in a BAM file, or uses the base filename if no read group information is present. For BAM files, this would be the filename without the extension and path (`/path/to/yourfile.bam => yourfile`). For FASTQ files, the template functionality will identify pairs using standard conventions (`_1` and `_2`, including Illumina extensions like `_R1`), so use the base filename without these (`/path/to/yourfile_R1.fastq => yourfile`). Note that paired-end samples sequentially numbered without leading zeros (e.g., `sample_1_1.fastq`, `sample_1_2.fastq`, `sample_2_1.fastq`, `sample_2_2.fastq`, etc., will likely not be parsed correctly; see [issue #1919](https://github.com/bcbio/bcbio-nextgen/issues/1919) for more info). In addition, `.` characters could be problematic, so it's better to avoid this character and use it only as separation for the file extension. For [Common Workflow Language (CWL)](cwl) inputs, the first `samplename` column should contain the base filename. For BAM files, this is `your_file.bam`. For fastqs this is `your_file_R1.fastq.gz;your_file_R2.fastq.gz`, separating individual files with a semicolon. By putting paths to the actual locations of the inputs in your `bcbio_system.yaml` input when generating CWL, you can easily move projects between different filesystems. The remaining columns can contain: * `description` Changes the sample description, originally supplied by the file name or BAM read group, to this value. You can also set the `lane`, although this is less often done as the default sequential numbering works here. * Algorithm parameters specific for this sample. If the column name matches an available [Algorithm parameters](#algorithm-parameters), then this value substitutes into the sample `algorithm`, replacing the defaults from the template. You can also change other information in the BAM read group through the `algorithm` parameters. See [alignment](#alignment) configuration documentation for details on how these map to read group information. * metadata key/value pairs. Any columns not falling into the above cases will go into the metadata section. A `ped` specification will allow bcbio to read family, gender and phenotype information from a PED input file and use it for batch, sex and phenotype, respectively. The PED inputs supplement information from the standard template file, so if you specify a value in the template CSV the PED information will no overwrite it. Alternatively, `ped` fields can be specified directly in the metadata as columns. If `family_id` is specified it will be used as the `family_id` for that sample, otherwise `batch` will be used. The `description` column is used as the `individual_id` column and the `phenotype` column will be used for as the `affected` column in the PED format: ``` samplename,description,phenotype,batch,sex,ethnicity,maternal_id,paternal_id,family_id NA12878.bam,NA12878,-9,CEPH,female,-9,NA12892,NA12891,NA12878FAM ``` Individual column items can contain booleans (true or false), integers, or lists (separated by semi-colons). These get converted into the expected time in the output YAML file. For instance, to specify a sample that should go into multiple batches: ``` samplename,description,phenotype,batch normal.bam,two_normal,normal,Batch1;Batch2 ``` For dictionary inputs like `somatic with germline variants` setups, you can separate items in a dictionary with colons and double colons, and also use semicolons for lists: ``` samplename,description,phenotype,variantcaller tumor.bam,sample1,tumor,germline:freebayes;gatk-haplotype::somatic:vardict;freebayes ``` The name of the metadata file, minus the `.csv` extension, is a short name identifying the current project. The script creates a `project1` directory containing the sample configuration in `project1/config/project1.yaml`. * The remaining arguments are input BAM or FASTQ files. The script pairs FASTQ files (identified by `_1` and `_2`) and extracts sample names from input BAMs, populating the `files` and `description` field in the final configuration file. Specify the full path to sample files on your current machine. To make it easier to define your own project specific template, an optional first step is to download and edit a local template. First retrieve a standard template: ```shell bcbio_nextgen.py -w template freebayes-variant project1 ``` This pulls the current GATK best practice variant calling template into your project directory in `project1/config/project1-template.yaml`. Manually edit this file to define your options, then run the full template creation for your samples, pointing to this custom configuration file: ```shell bcbio_nextgen.py -w template project1/config/project1-template.yaml project1.csv folder/* ``` If your sample folder contains additional BAM or FASTQ files you do not wish to include in the sample YAML configuration, you can restrict the output to only include samples in the metadata CSV with `--only-metadata`. The output will print warnings about samples not present in the metadata file, then leave these out of the final output YAML: ```shell bcbio_nextgen.py -w template --only-metadata project1/config/project1-template.yaml project1.csv folder/* ``` ### Multiple files per sample In case you have multiple FASTQ or BAM files for each sample you can use `bcbio_prepare_samples.py`. The main parameters are: * `--out`: the folder where the merged files will be * `--csv`: the CSV file that is exactly the same as described previously, but having as many duplicate lines for each sample as files to be merged: ``` samplename,description,batch,phenotype,sex,variant_regions file1.fastq,sample1,batch1,normal,female,/path/to/regions.bed file2.fastq,sample1,batch1,normal,female,/path/to/regions.bed file1.fastq,sample2,batch1,tumor,,/path/to/regions.bed ``` An example of usage is: ```shell bcbio_prepare_samples.py --out merged --csv project1.csv ``` The script will create the `sample1.fastq,sample2.fastq` in the `merged` folder, and a new CSV file in the same folder than the input CSV:`project1-merged.csv`. Later, it can be used for bcbio: ```shell bcbio_nextgen.py -w template project1/config/project1-template.yaml project1-merged.csv merged/*fastq ``` The new CSV file will look like: ``` samplename,description,batch,phenotype,sex,variant_regions sample1.fastq,sample1,batch1,normal,female,/path/to/regions.bed sample2.fastq,sample2,batch1,tumor,,/path/to/regions.bed ``` It supports parallelization the same way `bcbio_nextgen.py` does: ```shell python $BCBIO_PATH/scripts/utils/bcbio_prepare_samples.py --out merged --csv project1.csv -t ipython -q queue_name -s lsf -n 1 ``` See more examples at [parallelize pipeline](parallel). In case of paired reads, the CSV file should contain all files: ``` samplename,description,batch,phenotype,sex,variant_regions file1_R1.fastq,sample1,batch1,normal,female,/path/to/regions.bed file2_R1.fastq,sample1,batch1,normal,female,/path/to/regions.bed file1_R2.fastq,sample1,batch1,normal,femela,/path/to/regions.bed file2_R2.fastq,sample1,batch1,normal,female,/path/to/regions.bed ``` The script will try to guess the paired files the same way that `bcbio_nextgen.py -w template` does. It would detect paired files if the difference among two files is only `_R1/_R2` or `-1/-2` or `_1/_2` or `.1/.2` The output CSV will look like and is compatible with bcbio: ``` samplename,description,batch,phenotype,sex,variant_regions sample1,sample1,batch1,normal,female,/path/to/regions.bed ``` ## Algorithm parameters ### Alignment * `platform` Sequencing platform used. Corresponds to the `PL` parameter in BAM read groups. Default 'Illumina'. * `aligner` Aligner to use: [bwa, bowtie, bowtie2, hisat2, minimap2, novoalign, snap, star, tophat2, false] To use pre-aligned BAM files as inputs to the pipeline, set to `false`, which will also skip duplicate marking by default. Using pre-aligned inputs requires proper assignment of BAM read groups and sorting. The `bam_clean` argument can often resolve issues with problematic input BAMs. * `bam_clean` Clean an input BAM when skipping alignment step. This handles adding read groups, sorting to a reference genome and filtering problem records that cause problems with GATK. Options: * `remove_extracontigs` -- Remove non-standard chromosomes (for human, anything that is not chr1-22,X,Y) from the BAM file. This allows compatibility when the BAM reference genome has different contigs from the reference file but consistent ordering for standard chromosomes. Also fixes the read groups in the BAM file as in `fixrg`. This is faster than the full `picard` cleaning option. * `fixrg` -- only adjust read groups, assuming everything else in BAM file is compatible. * `picard` -- Picard/GATK based cleaning. Includes read group changes, fixing of problematic reads and re-ordering chromosome order to match the reference genome. To fix misencoded input BAMs with non-standard scores, set `quality_format` to `illumina`. * `bam_sort` Allow sorting of input BAMs when skipping alignment step (`aligner` set to false). Options are coordinate or queryname. For additional processing through standard pipelines requires coordinate sorted inputs. The default is to not do additional sorting and assume pre-sorted BAMs. * `align_split_size`: Increase parallelization of alignment. As of 0.9.8, bcbio will try to determine a useful parameter and you don't need to set this. If you manually set it, bcbio will respect your specification. Set to false to avoid splitting entirely. If set, this defines the number of records to feed into each independent parallel step (for example, 5000000 = 5 million reads per chunk). It converts the original inputs into bgzip grabix indexed FASTQ files, and then retrieves chunks for parallel alignment. Following alignment, it combines all chunks back into the final merged alignment file. This allows parallelization at the cost of additional work of preparing inputs and combining split outputs. The tradeoff makes sense when you have large files and lots of distributed compute. When you have fewer large multicore machines this parameter may not help speed up processing. * `quality_format` Quality format of FASTQ or BAM inputs [standard, illumina]. `standard` means Sanger, `illumina` means Illumina [1.3, 1.8). * `strandedness` For RNA-seq libraries, if your library is strand specific, set the appropriate flag from [unstranded, firststrand, secondstrand]. Defaults to unstranded. For dUTP marked libraries, firststrand is correct; for Scriptseq prepared libraries, secondstrand is correct. * `save_diskspace` Remove align prepped bgzip and split BAM files after merging into final BAMs. Helps reduce space on limited filesystems during a run. `tools_off: [upload_alignment]` may also be useful in conjunction with this. `[false, true]` ### Read trimming * `trim_reads` Trims low quality or adapter sequences or at the ends of reads using atropos. `adapters` and `custom_trim` specify the sequences to trim. For RNA-seq, it's recommended to leave as False unless running Tophat2. For variant calling, we recommend trimming only in special cases where standard soft-clipping does not resolve false positive problems. Supports trimming with [atropos](https://github.com/jdidion/atropos) or [fastp](https://github.com/OpenGene/fastp). `fastp` is currently not compatible with alignment splitting in variant calling and requires `align_split_size: false`. The old parameter `read_through` defaults to using atropos trimming. `[False, atropos, fastp]`. Default to False. * `adapters` If trimming adapter read through, trim a set of stock adapter sequences. Allows specification of multiple items in a list, for example [truseq, polya] will trim both TruSeq adapter sequences and polyA tails. polyg trimming removes high quality G stretches present in NovaSeq and NextSeq data. In the small RNA pipeline, bcbio will try to detect the adapter using DNApi. If you set up this parameter, then bcbio will use this value instead. Choices: `[truseq, illumina, nextera, polya, polyx, polyg, nextera2, truseq2]`. * nextera2: Illumina NEXTera DNA prep kit from NEB * truseq2: SMARTer Universal Low Input RNA Kit * `custom_trim` A list of sequences to trim from the end of reads, for example: `[AAAATTTT, GGGGCCCC]` * `min_read_length` Minimum read length to maintain when `read_through` trimming set in `trim_reads`. Defaults to 25. * `trim_ends` Specify values for trimming at ends of reads, using a fast approach built into fastq preparation. This does not do quality or adapter trimming but will quickly cut off a defined set of values from either the 5' or 3' end of the first and second reads. Expects a list of 4 values: `[5' trim read1, 3' trim read1, 5' trim read2, 3' trim read2]`. Set values to 0 if you don't need trimming (ie. `[6, 0, 12, 0]` will trim 6bp from the start of read 1 and 12bp from the start of read 2. Only implemented for variant calling pipelines. ### Alignment postprocessing * `mark_duplicates` Mark duplicated reads [true, false]. If true, will perform streaming duplicate marking with [biobambam's bammarkduplicates or bamsormadup](https://github.com/gt1/biobambam). Uses [samblaster](https://github.com/GregoryFaust/samblaster) as an alternative if you have paired reads and specifying `lumpy` as an `svcaller`. Defaults to true for variant calling and false for RNA-seq and small RNA analyses. Also defaults to false if you're not doing alignment (`aligner: false`). * `recalibrate` Perform base quality score recalibration on the aligned BAM file, adjusting quality scores to reflect alignments and known variants. Supports both GATK and Sentieon recalibration. Defaults to false, no recalibration. [false, gatk, sentieon] * `realign` Perform GATK's realignment around indels on the aligned BAM file. Defaults to no realignment since realigning callers like FreeBayes and GATK HaplotypeCaller handle this as part of the calling process. [false, gatk] ### Coverage information * `coverage_interval` Regions covered by sequencing. bcbio calculates this automatically from alignment coverage information, so you only need to specify it in the input configuration if you have specific needs or bcbio does not determine coverage correctly. `genome` specifies full genome sequencing, `regional` identifies partial-genome pull down sequencing like exome analyses, and `amplicon` is partial-genome sequencing from PCR amplicon sequencing. This influences GATK options for filtering: we use Variant Quality Score Recalibration when set to `genome`, otherwise we apply cutoff-based soft filters. Also affects copy number calling with CNVkit, structural variant calling and deep panel calling in cancer samples, where we tune regional/amplicon analyses to maximize sensitivity. [genome, regional, amplicon] * `maxcov_downsample` bcbio downsamples whole genome runs with >10x average coverage to a maximum coverage, avoiding slow runtimes in collapsed repeats and poly-A/T/G/C regions. This parameter specified the multiplier of average coverage to downsample at. For example, _200_ downsamples at 6000x coverage for a 30x whole genome. Set to _false_ or _0_ to disable downsampling. Current defaults to _false_ pending runtime improvements. * `coverage_depth_min` Minimum depth of coverage. When calculating regions to call in, bcbio may exclude regions with less than this many reads. It is not a hard filter for variant calling, but rather a guideline for determining callable regions. It's primarily useful when trying to call on very low depth samples. Defaults to 4. Setting lower than 4 will trigger low-depth calling options for GATK. ### Analysis regions These BED files define the regions of the genome to analyze and report on. `variant_regions` adjusts regions for small variant (SNP and indel) calling. `sv_regions` defines regions for structural variant calling if different than `variant_regions`. For coverage-based quality control metrics, we first use `coverage` if specified, then `sv_regions` if specified, then `variant_regions`. See the section on [input file preparation](#input-file-preparation) for tips on ensuring chromosome naming in these files match your reference genome. bcbio pre-installs some standard BED files for human analyses. Reference these using the naming schemes described in the [reference data repository](https://github.com/AstraZeneca-NGS/reference_data#capture-region-bed-files). * `variant_regions` BED file of regions to call variants in. * `sv_regions` -- A specification of regions to target during structural variant calling. By default, bcbio uses regions specified in `variant_regions` but this allows custom specification for structural variant calling. This can be a pointer to a BED file or special inputs: `exons` for only exon regions, `transcripts` for transcript regions (the min start and max end of exons) or `transcriptsXXXX` for transcripts plus a window of XXXX size around it. The size can be an integer (`transcripts1000`) or exponential (`transcripts1e5`). This applies to CNVkit and heterogeneity analysis. * `coverage` A BED file of regions to check for coverage and completeness in QC reporting. This can also be a shorthand for a BED file installed by bcbio (see [Structural variant calling](#structural-variant-calling) for options). * `exclude_regions` List of regions to remove as part of analysis. This allows avoidance of slow and potentially misleading regions. This is a list of the following options: * `polyx` Avoid calling variants in regions of single nucleotide stretches greater than 50. These can contribute to long variant calling runtimes when errors in polyX stretches align in high depth to these regions and take a lot of work to resolve. Since we don't expect decent resolution through these types of repeats, this helps avoid extra calculations for assessing the noise. This is an alternative to trimming polyX from the 3' ends for reads with `trim_reads` and `adapters`. Requires an organism with a defined `polyx` file in genome resources. For structural variant calling, adding `polyx` avoids calling small indels for Manta, where these can contribute to long runtimes. * `lcr` Avoid calling variants in low complexity regions (LCRs). [Heng Li's variant artifacts paper](https://arxiv.org/abs/1404.0929) provides these regions, which cover ~2% of the genome but contribute to a large fraction of problematic calls due to the difficulty of resolving variants in repetitive regions. Removal can help facilitate comparisons between methods and reduce false positives if you don't need calls in LCRs for your biological analysis. Requires an organism with a defined `lcr` file in genome resources. * `highdepth` Remove high depth regions during variant calling, identified by collapsed repeats around centromeres in hg19 and GRCh37 as characterized in the [ENCODE blacklist](https://hgdownload-test.cse.ucsc.edu/goldenPath/hg19/encodeDCC/wgEncodeMapability/). This is on by default for VarDict and FreeBayes whole genome calling to help with slow runtimes in these regions, and also on for whole genome structural variant calling to avoid false positives from high depth repeats. * `altcontigs` Skip calling in unplaced contigs (Un), limit analysis to standard chromosomes -- chr1-22,X,Y,MT for human -- to avoid slowdowns on the additional contigs. By default bcbio calls variants in unplaced but not in alternative contigs (alleles). Alt contig calling is currently not supported. * `remove_lcr: true` - removes low complexity regions from analysis in variant2 pipeline (somatic and germline variant calling).[remove_lcr_regions](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/shared.py#L143) function is looking for a resource in genome resources, for example `genomes/Hsapiens/hg38/seq/hg38-resources.yaml`: `lcr: ../coverage/problem_regions/repeats/LCR.bed.gz`, and fetching a bed file: `genomes/Hsapiens/hg38/coverage/problem_regions/repeats/LCR.bed.gz`. The file is installed by [the cloudbiolinux recipe](https://github.com/chapmanb/cloudbiolinux/blob/master/ggd-recipes/hg38/coverage.yaml) from [https://github.com/lh3/varcmp](https://github.com/lh3/varcmp). [Motivation in Li2014](https://www.ncbi.nlm.nih.gov/pubmed/24974202) ### Standard This pipeline implements `alignment` and `qc` tools. Furthermore, it will run [qsignature](http://sourceforge.net/p/adamajava/wiki/qSignature/) to detect possible duplicated samples, or mislabeling. It uses SNPs signature to create a distance matrix that helps easily to create groups. The project yaml file will show the number of total samples analyzed, the number of very similar samples, and samples that could be duplicated. We will assume that you installed bcbio-nextgen with the automated installer, and so your default [bcbio_system.yaml](http://github.com/bcbio/bcbio-nextgen/blob/master/config/bcbio_system.yaml) file is configured correctly with all of the tools pointing to the right places. If that is the case, to run bcbio-nextgen on a set of samples you just need to set up a YAML file that describes your samples and what you would like to do to them. Let's say that you have a single paired-end control lane, prepared with the [Illumina TruSeq Kit](https://www.illumina.com/products/by-type/sequencing-kits/library-prep-kits/truseq-rna-v2.html) from a human. Here is what a well-formed sample YAML file for that RNA-seq experiment would look like: ```yaml fc_date: '070113' fc_name: control_experiment upload: dir: final details: - files: [/full/path/to/control_1.fastq, /full/path/to/control_2.fastq] description: 'Control_rep1' genome_build: GRCh37 analysis: RNA-seq algorithm: aligner: tophat2 quality_format: Standard trim_reads: read_through adapters: [truseq, polya] strandedness: unstranded ``` `fc_date` and `fc_name` will be combined to form a prefix to name intermediate files, and can be set to whatever you like. `upload` is explained pretty well in the [configuration documentation](contents/configuration:upload) and the above will direct bcbio-nextgen to put the output files from the pipeine into the `final` directory. Under `details` is a list of sections each describing a sample to process. You can set many [parameters](configuration) under each section but most of the time just setting a few like the above is all that is necessary. `analysis` tells bcbio-nextgen to run the best-practice RNA-seq pipeline on this sample. In the above, since there are two files, `control_1.fastq` and `control_2.fastq` will be automatically run as paired-end data. If you have single end data you can just supply one file and it will run as single-end. The `description` field will be used to eventually rename the files, so make it very evocative since you will be looking at it a lot later. `genome_build` is self-explanatory. Sometimes you need a little bit more flexibility than the standard pipeline, and the `algorithm` section has many options to fine-tune the behavior of the algorithm. `quality_format` tells bcbio-nextgen what quality format your FASTQ inputs are using, if your samples were sequenced any time past 2009 or so, you probably want to set it to `Standard`. Adapter read-through is a problem in RNA-seq libraries, so we want to trim off possible adapter sequences on the ends of reads, so `trim_reads` is set to `read_through`, which will also trim off poor quality ends. Since your library is a RNA-seq library prepared with the TruSeq kit, the set of adapters to trim off are the TruSeq adapters and possible polyA tails, so `adapters` is set to both of those. `strandedness` can be set if your library was prepared in a strand-specific manner and can be set to firststrand, secondstrand or unstranded (the default). #### Parallelization * `nomap_split_size` Unmapped base pair regions required to split analysis into blocks. Creates islands of mapped reads surrounded by unmapped (or N) regions, allowing each mapped region to run in parallel. (default: 250) * `nomap_split_targets` Number of target intervals to attempt to split processing into. This picks unmapped regions evenly spaced across the genome to process concurrently. Limiting targets prevents a large number of small targets which can blow up the memory for runs with many samples. (default: 200 for standard runs, 20 for CWL runs) #### Multiple samples Lets say you have a set of mouse samples to analyze and each sample is a single lane of single-end RNA-seq reads prepared using the NextEra kit. There are two case and two control samples. Here is a sample configuration file for that analysis: ```yaml fc_date: '070113' fc_name: mouse_analysis upload: dir: final details: - files: [/full/path/to/control_rep1.fastq] description: 'Control_rep1' genome_build: mm10 analysis: RNA-seq algorithm: aligner: tophat2 quality_format: Standard trim_reads: read_through adapters: [nextera, polya] - files: [/full/path/to/control_rep2.fastq] description: 'Control_rep2' genome_build: mm10 analysis: RNA-seq algorithm: aligner: tophat2 quality_format: Standard trim_reads: read_through adapters: [nextera, polya] - files: [/full/path/to/case_rep1.fastq] description: 'Case_rep1' genome_build: mm10 analysis: RNA-seq algorithm: aligner: tophat2 quality_format: Standard trim_reads: read_through adapters: [nextera, polya] - files: [/full/path/to/case_rep2.fastq] description: 'Case_rep2' genome_build: mm10 analysis: RNA-seq algorithm: aligner: tophat2 quality_format: Standard trim_reads: read_through adapters: [nextera, polya] ``` More samples are added just by adding more entries under the details section. This is tedious and error prone to do by hand, so there is an automated [template](contents/configuration:automated%20sample%20configuration) system for common experiments. You could set up the previous experiment by making a mouse version of the [illumina-rnaseq](https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/templates/illumina-rnaseq.yaml) template file and saving it to a local file such as `illumina-mouse-rnaseq.yaml`. Then you can set up the sample file using the templating system: ```shell bcbio_nextgen.py -w template illumina-mouse-rnaseq.yaml mouse_analysis /full/path/to/control_rep1.fastq /full/path/to/control_rep2.fastq /full/path/to/case_rep1.fastq /full/path/to/case_rep2.fastq ``` If you had paired-end samples instead of single-end samples, you can still use the template system as long as the forward and reverse read filenames are the same, barring a `_1` and `_2`. For example: `control\_1.fastq` and `control\_2.fastq` will be detected as paired and combined in the YAML file output by the templating system. ### Quality control * `qc` Allows you to specifically assign quality control modules to run. Generally you want to leave this unset and allow bcbio to run the correct QC metrics for your experiment, or remove specific QC steps you don't want using `tools_off` ([Changing bcbio defaults](#changing-bcbio-defaults)). However, this can allow turning off most of the QC by specifying a single quick running step like `picard`. Available tools are `fastqc`, `samtools`, `coverage`, `picard`, `contamination` (VerifyBamID), `peddy`, `viral`, `damage`, `umi`, `small-rna`, `atropos`, `chipqc`. * `mixup_check` Detect potential sample mixups. Currently supports [qSignature](https://sourceforge.net/p/adamajava/wiki/qSignature/). `qsignature_full` runs a larger analysis while `qsignature` runs a smaller subset on chromosome 22. [False, qsignature, qsignature_full] * Detect bacterial, viral, and archaeal contamination with [kraken](https://github.com/DerrickWood/kraken). First, install minikraken database: `bcbio_nextgen.py upgrade -u skip --datatarget kraken`. It gets installed in `bcbio/genomes/kraken` and takes 4G. Second, turn on kraken algorithm with `kraken: minikraken`. Optionally, create a custom kraken database outside of bcbio and use it with: `kraken: /path/to/custom/kraken`. Kraken reports are in `project/final/sample/qc/kraken`. Kraken option works for `variant2` and `RNA-seq` pipelines. * `preseq` Accepts `lc_extrap` or `c_curve`, and runs [Preseq](https://smithlabresearch.org/software/preseq/), a tool that predicts the yield for future experiments. By default, it runs 300 steps of estimation using the segment length of 100000. The default extrapolation limit for `lc_extrap` is 3x of the reads number. You can override the parameters `seg_len`, `steps`, `extrap_fraction` using the [resources](#resources) section: ```yaml resources: preseq: extrap_fraction: 5 steps: 500 seg_len: 5000 ``` And you can also set `extrap` and `step` parameters directly, as well as provide any other command line option via `options`: ```yaml resources: preseq: extrap: 10000000 step: 30000 options: ["-D"] ``` * bcbio uses [MultiQC](https://multiqc.info/) to combine QC output for all samples into a single report file. If you need to tweak configuration settings from bcbio defaults, you can use [resources](#resources). For instance to display read counts with full numbers instead of the default millions: ```yaml resources: multiqc: options: ["--cl_config", "'read_count_multiplier: 1'"] ``` or as thousands: ```yaml resources: multiqc: options: ["--cl_config", "'{read_count_multiplier: 0.001, read_count_prefix: K}'"] ``` #### Post-processing `archive` Specify targets for long term archival. `cram` removes fastq names and does 8-bin compression of BAM files into [CRAM format](https://www.ebi.ac.uk/ena/software/cram-toolkit). `cram-lossless` generates CRAM files without changes to quality scores or fastq name. Default: [] -- no archiving. Lossy cram has some issues, lossless cram provides pretty good compression relative to BAM, and many machines output binned values now, so `cram-lossless` is what we recommend you use. #### Changing bcbio defaults bcbio provides some hints to change default behavior be either turning specific defaults on or off, with `tools_on` and `tools_off`. Both can be lists with multiple options: * `tools_off` Specify third party tools to skip as part of analysis pipeline. Enables turning off specific components of pipelines if not needed: * `gatk4` Use older GATK versions (3.x) for GATK commands like BQSR, HaplotypeCaller and VQSR. By default bcbio includes GATK4 and uses it. * `vqsr` turns off variant quality score recalibration for all samples. * `bwa-mem` forces use of original `bwa aln` alignment. Without this, we use bwa mem with 70bp or longer reads. * `lumpy-genotype` skip genotyping for Lumpy samples, which can be slow in the case of many structural variants. * `seqcluster` turns off use of seqcluster tool in srnaseq pipeline. * `tumoronly-prioritization` turns off attempted removal of germline variants from tumor only calls using external population data sources like ExAC and 1000 genomes. * `vardict_somatic_filter` disables running a post calling filter for VarDict to remove variants found in normal samples. Without `vardict_somatic_filter` in paired analyses no soft filtering of germline variants is performed but all high quality variants pass. * `upload_alignment` turns off final upload of large alignment files. * `pbgzip` turns off use of bgzip with multiple threads. * For quality control, you can turn off any specific tool by adding to `tools_off`. For example, `fastqc` turns off quality control FastQC usage. and `coverage_qc` turns off calculation of coverage statistics with samtools-stats and picard. See the [Methylation](#methylation) docs for details on tools. * `tools_on` Specify functionality to enable that is off by default: * `bcbiornaseq` loads a bcbioRNASeq object for use with [bcbioRNASeq](https://github.com/hbc/bcbioRNASeq). * `bnd-genotype` enables genotyping of breakends in Lumpy calls, which improves accuracy but can be slow. * `bwa-mem` forces use of bwa mem even for samples with less than 70bp reads. * `coverage_perbase` calculates per-base coverage depth for analyzed variant regions. * `damage_filter` annotates low frequency somatic calls in INFO/DKFZBias for DNA damage artifacts using [DKFZBiasFilter](https://github.com/eilslabs/DKFZBiasFilter). * `gemini` Create a [GEMINI database](https://github.com/arq5x/gemini) of variants for downstream query using the new vcfanno and vcf2db approach. * `gemini_allvariants` enables all variants to go into GEMINI, not only those that pass filters. * `gemini_orig` Create a [GEMINI database](https://github.com/arq5x/gemini) of variants using the older GEMINI loader. Only works for GRCh37 and hg19. * `gvcf` forces gVCF output for callers that support it (GATK HaplotypeCaller, FreeBayes, Platypus). For joint calling using a population of samples, please use _jointcaller_. * `lumpy_usecnv` uses input calls from CNVkit as prior evidence to Lumpy calling. * `noalt_calling` call variants only for chr1,,22,X,Y,MT. * `qualimap` runs [Qualimap](http://qualimap.bioinfo.cipf.es/) (qualimap uses downsampled files and numbers here are an estimation of 1e7 reads). * `qualimap_full` runs Qualimap with full bam files but it may be slow. * `svplots` adds additional coverage and summary plots for CNVkit and detected ensemble variants. * `tumoronly_germline_filter` applies a `LowPriority` filter to tumor-only calls that match population germline databases. The default is to just apply a tag `EPR` (external prioritization) that flags variants present in external databases. Anything missing a `pass` here is a likely germline. * `vcf2db_expand` decompresses and expands the genotype columns in the vcfanno prepared GEMINI databases, enabling standard SQL queries on genotypes and depths. * `vqsr` makes GATK try quality score recalibration for variant filtration, even for smaller sample sizes. * `vep_splicesite_annotations` enables the use of the MaxEntScan and SpliceRegion plugin for VEP. Both optional plugins add extra splice site annotations. ## Resources The `resources` section allows customization of locations of programs and memory and compute resources to devote to them: ```yaml resources: bwa: cores: 12 cmd: /an/alternative/path/to/bwa samtools: cores: 16 memory: 2G gatk: jvm_opts: ["-Xms2g", "-Xmx4g"] mutect2_filter: options: ["--max-events-in-region", "2"] ``` * `cmd` Location of an executable. By default, we assume executables are on the path. * `cores` Cores to use for multi-proccessor enabled software. This is how many cores will be allocated per job. For example if you are running 10 samples and passed -n 40 to bcbio-nextgen and the step you are running has cores: 8 set, a maximum of five samples will run in parallel, each using 8 cores. * `jvm_opts` Specific memory usage options for Java software. For memory usage on programs like GATK, specify the maximum usage per core. On multicore machines, that's machine-memory divided by cores. This avoids memory errors when running multiple jobs simultaneously, while the framework will adjust memory up when running multicore jobs. * `memory` Specify the memory per core used by a process. For programs where memory control is available, like `samtools sort`, this limits memory usage. For other programs this is an estimate of usage, used by [Memory management](contents/parallel:memory%20management) to avoid over-scheduling memory. Always specify this as the memory usage for a single core, and the pipeline handles scaling this when a process uses multiple cores. * `keyfile` Specify the location of a program specific key file or license server, obtained from a third party software tool. Supports licenses for [novoalign](http://www.novocraft.com/products/novoalign/) and [Sentieon](https://www.sentieon.com/products/). For more complex Sentieon setups this can also be a dictionary of environmental variables: ```yaml resources: sentieon: keyfile: SENTIEON_LICENSE_SERVER: 100.100.100.100:8888 SENTIEON_AUTH_MECH: XXX SENTIEON_AUTH_DATA: signature ``` * `options` Adjust specific command line options for a program. This can be hard to support for many tools due to conflicts with other existing options but is available for some tools: - `mutect2`, `mutect2_filter`: Adjust for Mutect2 calls and filtering. ### Temporary directory You also use the resource section to specify system specific parameters like global temporary directories: ```yaml resources: tmp: dir: /scratch ``` This is useful on cluster systems with large attached local storage, where you can avoid some shared filesystem IO by writing temporary files to the local disk. When setting this keep in mind that the global temporary disk must have enough space to handle intermediates. The space differs between steps but generally you'd need to have 2x the largest input file per sample and account for samples running simultaneously on multiple core machines. To handle clusters that specify local scratch space with an environmental variable, bcbio will resolve environmental variables like: ```yaml resources: tmp: dir: $YOUR_SCRATCH_LOCATION ``` ### Sample or run specific resources To override any of the global resource settings in a sample specific manner, you write a resource section within your sample YAML configuration. For example, to create a sample specific temporary directory and pass a command line option to novoalign, write a sample resource specification like: ```yaml - description: Example analysis: variant2 resources: novoalign: options: ["-o", "FullNW", "--rOQ"] tmp: dir: tmp/sampletmpdir ``` To adjust resources for an entire run, you can add this resources specification at the top level of your sample YAML: ```yaml details: - description: Example resources: default: cores: 16 ``` ### Input file preparation Input files for supplementing analysis, like `variant_regions` need to match the specified reference genome. A common cause of confusion is the two chromosome naming schemes for human genome build 37: UCSC-style in hg19 (chr1, chr2) and Ensembl/NCBI style in GRCh37 (1, 2). To help avoid some of this confusion, in build 38 we only support the commonly agreed on chr1, chr2 style. It's important to ensure that the chromosome naming in your input files match those in the reference genome selected. bcbio will try to detect this and provide helpful errors if you miss it. To convert chromosome names, you can use [Devon Ryan's collection of chromosome mappings](https://github.com/dpryan79/ChromosomeMappings) as an input to sed. For instance, to convert hg19 chr-style coordinates to GRCh37: ```shell wget --no-check-certificate -qO- https://raw.githubusercontent.com/dpryan79/ChromosomeMappings/master/GRCh37_UCSC2ensembl.txt \ | awk '{if($1!=$2) print "s/^"$1"/"$2"/g"}' > remap.sed sed -f remap.sed original.bed > final.bed ``` ### Genome configuration files Each genome build has an associated `buildname-resources.yaml` configuration file which contains organism specific naming and resource files. bcbio-nextgen expects a resource file present next to the genome FASTA file. [Example genome configuration files](https://github.com/bcbio/bcbio-nextgen/tree/master/config/genomes) are available, and automatically installed for natively supported genomes. Create these by hand to support additional organisms or builds. The major sections of the file are: * `aliases` -- Names for third-party programs used as part of the analysis, since naming expectations can differ between software programs. * `variation` -- Supporting data files for variant analysis. For human analyses, the dbSNP and training files are from the [GATK resource bundle](https://gatk.broadinstitute.org/hc/en-us/articles/360036212652-Resource-Bundle). These are inputs into the training models for recalibration. The automated [CloudBioLinux](https://github.com/chapmanb/cloudbiolinux) data scripts will download and install these in the variation subdirectory relative to the genome files. * `rnaseq` -- Supporting data files for RNA-seq analysis. The automated installer and updater handles retrieval and installation of these resources for supported genome builds. * `srnaseq` -- Supporting data files for smallRNA-seq analysis. Same as in rnaseq, the automated installer and updater handle this for supported genome builds. By default, we place the `buildname-resources.yaml` files next to the genome FASTA files in the reference directory. For custom setups, you specify an alternative directory in the [resources](#resources) section of your `bcbio_system.yaml` file: ```yaml resources: genome: dir: /path/to/resources/files ``` ### Reference genome files For human genomes, we recommend using build 38 (hg38). This is [fully supported and validated](http://bcb.io/2015/09/17/hg38-validation/) in bcbio, and corrects a lot of issues in the previous build 37. We use the [1000 genomes distribution](ftp://ftp.1000genomes.ebi.ac.uk/vol1/ftp/technical/reference/GRCh38_reference_genome/) which includes HLAs and decoy sequences. For human build 37, GRCh37 and hg19, we use the 1000 genome references provided in the [GATK resource bundle](https://gatk.broadinstitute.org/hc/en-us/articles/360036212652-Resource-Bundle). These differ in chromosome naming: hg19 uses chr1, chr2, chr3 style contigs while GRCh37 uses 1, 2, 3. They also differ [slightly in content](https://gatkforums.broadinstitute.org/gatk/discussion/1810/whats-the-difference-between-b37-and-hg19-resources): GRCh37 has masked [Pseudoautosomal regions](https://en.wikipedia.org/wiki/Pseudoautosomal_region) on chromosome Y allowing alignment to these regions on chromosome X. You can use pre-existing data and reference indexes by pointing bcbio-nextgen at these resources. We use the [Galaxy .loc files](https://galaxyproject.org/admin/data-integration/#set-up-the-loc-file) approach to describing the location of the sequence and index data, as described in [Data requirements](contents/installation:data%20requirements). This does not require a Galaxy installation since the installer sets up a minimal set of `.loc` files. It finds these by identifying the root `galaxy` directory, in which it expects a `tool-data` sub-directory with the `.loc` files. It can do this in two ways: * Using the directory of your `bcbio-system.yaml`. This is the default mechanism setup by the automated installer and requires no additional work. * From the path specified by the `galaxy_config` option in your `bcbio-system.yaml`. If you'd like to move your system YAML file, add the full path to your `galaxy` directory here. This is useful if you have a pre-existing Galaxy installation with reference data. To manually make genomes available to bcbio-nextgen, edit the individual `.loc` files with locations to your reference and index genomes. You need to edit `sam_fa_indices.loc` to point at the FASTA files and then any genome indexes corresponding to aligners you'd like to use (for example: `bwa_index.loc` for bwa and `bowtie2_indices.loc` for bowtie2). The database key names used (like `GRCh37` and `mm10`) should match those used in the `genome_build` of your sample input configuration file. To remove a reference genome, delete its directory `bcbio/genomes/species/reference` and remove all the records corresponding to that genome from `bcbio/galaxy/tool-data/*.loc` files. `genomes/Hsapiens/hg38/seq/hg38-resources.yaml` specifies relative locations of the resources. To determine the absolute path, bcbio fetches a value from `bcbio/galaxy/tool-data/sam_fa_indices.loc` and uses it is a basedir for all resources. If there are several installations of bcbio `data`, it is important to have separate `tool-data` as well. ### Adding custom genomes [bcbio_setup_genome.py](https://github.com/bcbio/bcbio-nextgen/blob/master/scripts/bcbio_setup_genome.py) installs a custom genome for variant and bulk-RNA-seq analyses and updates the configuration files. ```shell bcbio_setup_genome.py \ -f genome.fa \ -g annotation.gtf \ -i bwa star seq \ -n Celegans -b WBcel135 --buildversion WormBase_34 ``` Arguments: - run `bcbio_setup_genome.py --help` to see all available arguments - `-f genome.fasta` - genome in FASTA format - `-g annotation.gtf` - annotation file in GTF or GFF3 format - `-i seq bwa` - list of aligner indices to create. `seq` is a sequence dictionary, always created. - `-n Name` - name of the species, for example `Celegans`. - `-b Build` - genome build, for example `WBcel135`. - `--buildversion annotation_build` - annotation build, for example `WormBase_34` or ensembl build. It is saved in `bcbio/genomes/Name/Build/rnaseq/version.txt`. References for many species are available from Ensembl: - [genomes](http://ftp.ensembl.org/pub/release-100/fasta/) - [transriptome annotations](http://ftp.ensembl.org/pub/release-100/gtf/) If you want to add smallRNA-seq data files, you will need to add the 3 letters code of mirbase for your genome (i.e hsa for human) and the GTF file for the annotation of smallRNA data. Here you can use the same file than the transcriptome if no other available. ```shell bcbio_setup_genome.py -f genome.fa -g annotation.gtf -i bowtie2 star seq -n Celegans -b WBcel135 --species cel --srna_gtf another_annotation.gtf --buildversion WormBase_34 ``` To use that genome just need to configure your YAML files as: ```yaml genome_build: WBcel135 ``` The GTF file you provide for the `bcbio_setup_genome.py` script must have the following features: 1) each entry must have a `transcript_id` and a `gene_id` 2) for each transcript there must be entries where the **feature** field (field 3) is `exon` with the coordinates describing the stop and end of the exon for example, this is a snippet from a valid GTF file: ``` 1 pseudogene gene 11869 14412 . + . gene_source "ensembl_havana"; gene_biotype "pseudogene"; gene_id "ENSG00000223972"; gene_name "DDX11L1"; 1 processed_transcript transcript 11869 14409 . + . transcript_source "havana"; gene_id "ENSG00000223972"; gene_source "ensembl_havana"; trans cript_name "DDX11L1-002"; gene_biotype "pseudogene"; transcript_id "ENST00000456328"; gene_name "DDX11L1"; 1 processed_transcript exon 11869 12227 . + . exon_number "1"; transcript_source "havana"; gene_id "ENSG00000223972"; exon_id "ENSE00002234944"; gene_source "ensembl_havana"; transcript_id "ENST00000456328"; gene_biotype "pseudogene"; transcript_name "DDX11L1-002"; gene_name "DDX11L1"; 1 processed_transcript exon 12613 12721 . + . exon_number "2"; transcript_source "havana"; gene_id "ENSG00000223972"; exon_id "ENSE00003582793"; gene_source "ensembl_havana"; transcript_id "ENST00000456328"; gene_biotype "pseudogene"; transcript_name "DDX11L1-002"; gene_name "DDX11L1"; 1 processed_transcript exon 13221 14409 . + . exon_number "3"; transcript_source "havana"; gene_id "ENSG00000223972"; exon_id "ENSE00002312635"; gene_source "ensembl_havana"; transcript_id "ENST00000456328"; gene_biotype "pseudogene"; transcript_name "DDX11L1-002"; gene_name "DDX11L1"; ``` #### Effects prediction To perform variant calling and predict effects in a custom genome you'd have to manually download and link this into your installation. First find the snpEff genome build: ```shell $ snpEff databases | grep Lactobacillus | grep pentosus Lactobacillus_pentosus_dsm_20314 Lactobacillus_pentosus_dsm_20314 ENSEMBL_BFMPP_32_179 http://downloads.sourceforge.net/project/snpeff/databases/v4_3/snpEff_v4_3_ENSEMBL_BFMPP_32_179.zip Lactobacillus_pentosus_kca1 Lactobacillus_pentosus_kca1 ENSEMBL_BFMPP_32_179 http://downloads.sourceforge.net/project/snpeff/databases/v4_3/snpEff_v4_3_ENSEMBL_BFMPP_32_179.zip ``` then download to the appropriate location: ```shell $ cd /path/to/bcbio/genomes/Lacto/Lactobacillus_pentosus $ mkdir snpEff $ cd snpEff $ wget http://downloads.sourceforge.net/project/snpeff/databases/v4_3/snpEff_v4_3_ENSEMBL_BFMPP_32_179.zip $ unzip snpEff_v4_3_ENSEMBL_BFMPP_32_179.zip $ find . -name "Lactobacillus_pentosus_dsm_20314" ./home/pcingola/snpEff/data/Lactobacillus_pentosus_dsm_20314 $ mv ./home/pcingola/snpEff/data/Lactobacillus_pentosus_dsm_20314 . ``` finally add to your genome configuration file (`seq/Lactobacillus_pentosus-resources.yaml`): ```yaml aliases: snpeff: Lactobacillus_pentosus_dsm_20314 ``` For adding an organism not present in snpEff, please see this [mailing list discussion](https://groups.google.com/d/msg/biovalidation/LPFBlwVBh5s/AMU7MVvQAwAJ). ## Download data from SRA Use SRA toolkit [prefetch/fastq-dump](https://wiki.rc.hms.harvard.edu/pages/viewpage.action?pageId=42402938) ## Upload The `upload` section of the sample configuration file describes where to put the final output files of the pipeline. At its simplest, you can configure bcbio-nextgen to upload results to a local directory, for example a folder shared amongst collaborators or a Dropbox account. You can also configure it to upload results automatically to a Galaxy instance, to [Amazon S3](https://aws.amazon.com/s3/) or to iRODS. Here is the simplest configuration, uploading to a local directory: ```yaml upload: dir: /local/filesystem/directory ``` General parameters, always required: * `method` Upload method to employ: `[filesystem, galaxy, s3, irods]`. Defaults to local filesystem. * `dir` Local filesystem directory to copy to. Galaxy parameters: * `galaxy_url` URL of the Galaxy instance to upload to. Upload assumes you are able to access a shared directory also present on the Galaxy machine. * `galaxy_api_key` User API key to access Galaxy: see the [Galaxy API](https://galaxyproject.org/develop/api/) documentation. * `galaxy_library` Name of the Galaxy Data Library to upload to. You can specify this globally for a project in `upload` or for individual samples in the sample details section. * `galaxy_role` Specific Galaxy access roles to assign to the uploaded datasets. This is optional and will default to the access of the parent data library if not supplied. You can specify this globally for a project in `upload` or for individual samples in the sample details section. The [Galaxy Admin](https://galaxyproject.org/data-libraries/#permissions) documentation has more details about roles. Here is an example configuration for uploading to a Galaxy instance. This assumes you have a shared mounted filesystem that your Galaxy instance can also access: ```yaml upload: method: galaxy dir: /path/to/shared/galaxy/filesystem/folder galaxy_url: http://url-to-galaxy-instance galaxy_api_key: YOURAPIKEY galaxy_library: data_library_to_upload_to ``` Your Galaxy `universe_wsgi.ini` configuration needs to have `allow_library_path_paste = True` set to enable uploads. S3 parameters: * `bucket` AWS bucket to direct output. * `folder` A folder path within the AWS bucket to prefix the output. * `region` AWS region name to use. Defaults to us-east-1 * `reduced_redundancy` Flag to determine if we should store S3 data with reduced redundancy: cheaper but less reliable `[false, true]` For S3 access credentials, set the standard environmental variables, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` or use [IAM access roles](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) with an instance profile on EC2 to give your instances permission to create temporary S3 access. iRODS parameters: * `folder` Full directory name within iRODS to prefix the output. * `resource` (optional) iRODS resource name, if other than default. Example configuration: ```yaml upload: method: irods dir: ../final folder: /irodsZone/your/path/ resource: yourResourceName ``` Uploads to iRODS depend on a valid installation of the iCommands CLI, and a preconfigured connection through the _iinit_ command. ## Globals You can define files used multiple times in the `algorithm` section of your configuration in a top level `globals` dictionary. This saves copying and pasting across the configuration and makes it easier to manually adjust the configuration if inputs change: ```yaml globals: my_custom_locations: /path/to/file.bed details: - description: sample1 algorithm: variant_regions: my_custom_locations - description: sample2 algorithm: variant_regions: my_custom_locations ``` ## Logging Bcbio creates 3 log files: * `bcbio-nextgen.log` High level logging information about the analysis. This provides an overview of major processing steps and useful checkpoints for assessing run times. * `bcbio-nextgen-debug.log` Detailed information about processes including stdout/stderr from third party software and error traces for failures. Look here to identify the status of running pipelines or to debug errors. It labels each line with the hostname of the machine it ran on to ease debugging in distributed cluster environments. * `bcbio-nextgen-commands.log` Full command lines for all third party software tools run. * Default location for log files is `work/log` directory. Also 2 logs are saved in `final/project` * `log_dir: /path/to/logs` in `/bcbio/galaxy/bcbio-system.yaml` sets logging destination for all projects. ## Persistence Every pipeline has multiple steps. Bcbio saves intermediate results in the work directory. If a step has been successfully finished (alignment bam file is generated, variants vcf is calculated, purecn normal db is generated), and the pipeline failed one of the subsequent steps, then upon re-running the pipeline, the finished steps would not be re-calculated. If you'd like to re-generate data for a particular step, simply remove the corresponding `work/step` folder, for example, remove `work/gemini` if you'd like to re-generate a gemini database or purecn normaldb. bcbio-nextgen-1.2.9/docs/contents/cwl.md000066400000000000000000000621341415626112400201530ustar00rootroot00000000000000# Common Workflow Language (CWL) **CWL functionality is not supported as of bcbio1.2.8** bcbio runs with [Common Workflow Language (CWL)](https://github.com/common-workflow-language/common-workflow-language) compatible parallelization software. bcbio generates a CWL workflow from a [standard bcbio sample YAML description file](configuration) and any tool that supports CWL input can run the workflow. CWL-based tools do the work of managing files and workflows, and bcbio performs the biological analysis using either a Docker container or a local installation. ## Current status bcbio creates CWL for alignment, small variant calls (SNPs and indels), coverage assessment, HLA typing, quality control and structural variant calling. It generates a [CWL v1.0.2](https://www.commonwl.org/v1.0/) compatible workflow. The actual biological code execution during runs works with either a [bcbio docker container](https://github.com/bcbio/bcbio_docker) or a [local installation of bcbio](installation). The implementation includes bcbio's approaches to splitting and batching analyses. At the top level workflow, we parallelize by samples. Using sub-workflows, we split fastq inputs into sections for parallel alignment over multiple machines following by merging. We also use sub-workflows, along with CWL records, to batch multiple samples and run in parallel. This enables pooled and tumor/normal cancer calling with parallelization by chromosome regions based on coverage calculations. ![cwl example](https://i.imgur.com/iyU8VIZ.png) bcbio supports these CWL-compatible tools: * [Cromwell](https://cromwell.readthedocs.io/) -- multicore local runs and distributed runs on HPC systems with shared filesystems and schedulers like SLURM, SGE and PBSPro. * [Arvados](https://arvados.org/) -- a hosted platform that runs on top of parallel cloud environments. We include an example below of running on the [public Curoverse](https://playground.arvados.org/users/welcome) instance running on [Microsoft Azure](https://azure.microsoft.com). * [DNANexus](https://www.dnanexus.com/) -- a hosted platform running distributed jobs on cloud environments, working with both AWS and Azure. * [Seven Bridges](https://www.sevenbridges.com/) -- parallel distributed analyses on the Seven Bridges platform and [Cancer Genomics Cloud](https://www.cancergenomicscloud.org/). * [Toil](https://github.com/BD2KGenomics/toil) -- parallel local and distributed cluster runs on schedulers like SLURM, SGE and PBSPro. * [rabix bunny](https://github.com/rabix/bunny) -- multicore local runs. * [cwltool](https://github.com/common-workflow-language/cwltool) -- a single core analysis engine, primarily used for testing. We plan to continue to expand CWL support to include more components of bcbio, and also need to evaluate the workflow on larger, real life analyses. This includes supporting additional CWL runners. We're working on evaluating [Galaxy/Planemo](https://github.com/galaxyproject/planemo) for integration with the Galaxy community. ## Installation [bcbio-vm](https://github.com/bcbio/bcbio-nextgen-vm) installs all dependencies required to generate CWL and run bcbio, along with supported CWL runners. There are two install choices, depending on your usage of bcbio: running CWL with a existing local bcbio install, or running with containers. ### Install bcbio-vm with a local bcbio To run bcbio without using containers, first and make it available in your path. You'll need both the bcbio code and tools. To only run the tests and bcbio validations, you don't need a full data installation so can install with `--nodata`. To then install bcbio-vm, add the `--cwl` flag to the install: ```shell bcbio_nextgen.py upgrade --cwl ``` Adding this to any future upgrades will also update the bcbio-vm wrapper code and tools. When you begin running your own analysis and need the data available, pre-prepare your bcbio data directory with `bcbio_nextgen.py upgrade --data --cwl`. ### Install bcbio-vm with containers If you don't have an existing local bcbio installation and want to run with CWL using the tools and data embedded in containers, you can do a stand along install of just bcbio-vm. To install using [Miniconda](https://docs.conda.io/en/latest/miniconda.html) and [bioconda packages](https://bioconda.github.io/) on Linux: ```shell export TARGETDIR=~/install/bcbio-vm/anaconda export BINDIR=/usr/local/bin wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p $TARGETDIR $TARGETDIR/bin/conda install --yes -c conda-forge -c bioconda python=3 bcbio-nextgen $TARGETDIR/bin/conda install --yes -c conda-forge -c bioconda python=3 bcbio-nextgen-vm mkdir -p $BINDIR ln -s $TARGETDIR/bin/bcbio_vm.py $BINDIR/bcbio_vm.py ln -s $TARGETDIR/bin/conda $BINDIR/bcbiovm_conda ln -s $TARGETDIR/bin/python $BINDIR/bcbiovm_python ``` In the above commands, the _bcbio-vm_ install goes in `$TARGETDIR`. The example is in your home directory but set it anywhere you have space. Also, as an alternative to symbolic linking to a `$BINDIR`, you can add the install bin directory to your PATH: ```shell export PATH=$TARGETDIR/bin:$PATH ``` This install includes bcbio-nextgen libraries, used in generating CWL and orchestrating runs, but is not a full bcbio installation. It requires [Docker](https://www.docker.com/) present on your system this is all you need to get started running examples, since the CWL runners will pull in Docker containers with the bcbio tools. ## Getting started To make it easy to get started, we have pre-built CWL descriptions that use test data. These run in under 5 minutes on a local machine and don't require a bcbio installation if you have Docker available on your machine: 1. Download and unpack the [test repository](https://github.com/bcbio/test_bcbio_cwl): ```shell wget -O test_bcbio_cwl.tar.gz https://github.com/bcbio/test_bcbio_cwl/archive/master.tar.gz tar -xzvpf test_bcbio_cwl.tar.gz cd test_bcbio_cwl-master/somatic ``` 2. Run the analysis using either Cromwell, Rabix bunny or Toil. If you have Docker available on your machine, the runner will download the correct [bcbio container](https://github.com/bcbio/bcbio_docker) and you don't need to install anything else to get started. If you have an old version of the container you want to update to the latest with `docker pull quay.io/bcbio/bcbio-vc`. There are shell scripts that provide the command lines for running: ```shell bash run_cromwell.sh bash run_bunny.sh bash run_toil.sh ``` Or you can run directly using the `bcbio_vm.py` wrappers: ```shell bcbio_vm.py cwlrun cromwell somatic-workflow bcbio_vm.py cwlrun toil somatic-workflow bcbio_vm.py cwlrun bunny somatic-workflow ``` These wrappers automatically handle temporary directories, permissions, logging and re-starts. If running without Docker, use a [local installation of bcbio](installation) add `--no-container` to the commands in the shell scripts. ## Generating CWL for input to a tool The first step in running your analysis project in bcbio is to generate CWL. If you're already familiar with bcbio, the [process of preparing information about your sample inputs and analysis](configuration) are almost identical: * A [standard bcbio sample configuration file](configuration) defining the samples. This can either be a full prepared YAML file or a [template file and CSV with sample data](contents/configuration:automated%20sample%20configuration). * A `bcbio_system.yaml` file defining the system environment for running the program. This includes the resource specification with [cores and memory per core for your machines](contents/configuration:resources). For choosing cores and memory per cores, you generally want to set this to match the parameters of a single machine either for a local run or on a cluster. In addition to [resources](contents/configuration:resources) specifications, the bcbio system file now also includes paths to the reference biodata and optionally input file directories if you want to avoid specifying full paths to your inputs in the `bcbio_vm.py template` command. bcbio will recursively look up file locations within those `inputs`, and this has the advantage of working identically for non-local file locations. Here is an example for a 16 core machine with 3.5GB of memory per core: ```yaml local: ref: /path/to/bcbio/genomes/Hsapiens inputs: - /path/to/input/files resources: default: cores: 16 memory: 3500M jvm_opts: [-Xms1g, -Xmx3500m] ``` Generate CWL with: ```shell bcbio_vm.py template --systemconfig bcbio_system.yaml template.yaml samples.csv [optional list of fastq or BAM inputs] bcbio_vm.py cwl --systemconfig bcbio_system.yaml samples/config/samples.yaml ``` producing a `sample-workflow` output directory with the CWL. On a first CWL generation run with a new genome, this process will run for a longer time as it needs to make your reference compatible with CWL. This includes creating single tar.gz files from some reference directories so they can get passed to CWL steps where they'll get unpacked. This process only happens a single time and keeps unpacked versions so your reference setup is compatible with both old bcbio IPython and new CWL runs. You can now run this with any CWL compatible runner and the `bcbio_vm.py cwlrun` wrappers standardize running across multiple tools in different environments. ### Running with Cromwell The [Cromwell](https://cromwell.readthedocs.io/) workflow management system runs bcbio either locally on a single machine or distributed on a cluster using a scheduler like SLURM, SGE or PBSPro. To run a bcbio CWL workflow locally using Docker: ```shell bcbio_vm.py cwlrun cromwell sample-workflow ``` If you want to run from a locally installed bcbio add `--no-container` to the commandline. To run distributed on a SLURM cluster: ```shell bcbio_vm.py cwlrun cromwell sample-workflow --no-container -q your_queue -s slurm -r timelimit=0-12:00 ``` Tweak scheduler parameters using the [same options as the older bcbio IPython approach](contents/parallel:ipython%20parallel). To control the resources used Cromwell, set `--joblimit` to the allowed jobs allocated concurrently. This isn't total cores used, but rather the number of jobs either locally or remotely scheduled concurrently. Since CWL steps are heterogeneous and use only cores necessary for that job, the total cores used will max out at joblimit times maximum cores for an individual process. Setting this helps avoid over-committing jobs to a shared scheduler during highly parallel processes like variant calling. Cromwell can also run directly on cloud resources: [Google Cloud Platform](contents/cloud:google%20cloud%20platform). ## Running with Toil The [Toil pipeline management system](https://github.com/BD2KGenomics/toil) runs CWL workflows in parallel on a local machine, on a cluster or at AWS. To run a bcbio CWL workflow locally with Toil using Docker: ```shell bcbio_vm.py cwlrun toil sample-workflow ``` If you want to run from a locally installed bcbio add `--no-container` to the commandline. To run distributed on a Slurm cluster: ``` bcbio_vm.py cwlrun toil sample-workflow -- --batchSystem slurm ``` ## Running on Arvados bcbio generated CWL workflows run on [Arvados](https://arvados.org/) and these instructions detail how to run on the [Arvdos public instance](https://playground.arvados.org). [Arvados cwl-runner](https://github.com/curoverse/arvados) comes pre-installed with [bcbio-vm](https://github.com/bcbio/bcbio-nextgen-vm#installation). We have a publicly accessible project, called [bcbio_resources](https://workbench.qr1hi.arvadosapi.com/projects/qr1hi-j7d0g-8g1u4lh8mwev36n) that contains the latest Docker images, test data and genome references you can use for runs. Retrieve API keys from the [Arvados public instance](https://playground.arvados.org). Login, then go to 'User Icon-> Personal Token'. Copy and paste the commands given there into your shell. You'll specifically need to set `ARVADOS_API_HOST` and `ARVADOS_API_TOKEN`. To run an analysis: 1. Create a new project from the web interface (Projects -> Add a new project). Note the project ID from the URL of the project (an identifier like `qr1hi-j7d0g-7t73h4hrau3l063`). 1. Upload reference data to Arvados Keep. Note the genome collection UUID. You can also use the existing genomes pre-installed in the `bcbio_resources` project if using the public Arvados playground: ```shell arv-put --name testdata_genomes --project-uuid $PROJECT_ID testdata/genomes/hg19 ``` 1. Upload input data to Arvados Keep. Note the collection UUID: ```shell arv-put --name testdata_inputs --project-uuid $PROJECT_ID testdata/100326_FC6107FAAXX testdata/automated testdata/reference_material ``` 1. Create an Arvados section in a `bcbio_system.yaml` file specifying locations to look for reference and input data. `input` can be one or more collections containing files or associated files in the original sample YAML: ```shell arvados: reference: qr1hi-4zz18-kuz1izsj3wkfisq input: [qr1hi-j7d0g-h691y6104tlg8b4] resources: default: {cores: 4, memory: 2G, jvm_opts: [-Xms750m, -Xmx2500m]} ``` 1. Generate the CWL to run your samples. If you're using multiple input files with a [CSV metadata file and template](contents/configuration:automated%20sample%20configuration) start with creation of a configuration file: ```shell bcbio_vm.py template --systemconfig bcbio_system_arvados.yaml testcwl_template.yaml testcwl.csv ``` To generate the CWL from the system and sample configuration files: ```shell bcbio_vm.py cwl --systemconfig bcbio_system_arvados.yaml testcwl/config/testcwl.yaml ``` 1. In most cases, Arvados should directly pick up the Docker images you need from the public bcbio_resources project in your instance. If you need to manually add to your project, you can copy latest bcbio Docker image into your project from bcbio_resources using [arv-copy](https://doc.arvados.org/user/topics/arv-copy.html). You'll need to find the UUID of `quay.io/bcbio/bcbio-vc` and `arvados/jobs`: ``` arv-copy $JOBS_ID --project-uuid $PROJECT_ID --src qr1hi --dst qr1hi arv-copy $BCBIO_VC_ID --project-uuid $PROJECT_ID --src qr1hi --dst qr1hi ``` or import local Docker images to your Arvados project: ```shell docker pull arvados/jobs:1.0.20180216164101 arv-keepdocker --project $PROJECT_ID -- arvados/jobs 1.0.20180216164101 docker pull quay.io/bcbio/bcbio-vc arv-keepdocker --project $PROJECT_ID -- quay.io/bcbio/bcbio-vc latest ``` 7. Run the CWL on the Arvados public cloud using the Arvados cwl-runner: ```shell bcbio_vm.py cwlrun arvados arvados_testcwl-workflow -- --project-uuid $PROJECT_ID ``` ## Running on DNAnexus bcbio runs on the [DNAnexus platform](https://www.dnanexus.com/) by converting bcbio generated CWL into DNAnexus workflows and apps using [dx-cwl](https://github.com/dnanexus/dx-cwl). This describes the process using the bcbio workflow app (bcbio-run-workflow) and [bcbio workflow applet (bcbio_resources:/applets/bcbio-run-workflow)](https://platform.dnanexus.com/projects/F541fX00f5v9vKJjJ34gvgbv/data/applets) in the public [bcbio_resources](https://platform.dnanexus.com/projects/F541fX00f5v9vKJjJ34gvgbv/data/) project, both are [regularly updated and maintained on the DNAnexus platform](https://github.com/bcbio/bcbio-dnanexus-wrapper). Secondarily, we also show how to install and create workflows locally for additional control and debugging. Set some useful environmental variables: * `$PNAME` -- The name of the project you're analyzing. For convenience here we keep this the same for your local files and remote DNAnexus project, although that does not have to be true. * `$DX_AUTH_TOKEN` -- The DNAnexus authorization token for access, used for the `dx` command line tool and bcbio scripts. * `$DX_PROJECT_ID` -- The DNAnexus GUID identifier for your project (similar to `project-F8Q7fJj0XFJJ3XbBPQYXP4B9`). You can get this from `dx env` after creating/selecting a project in steps 1 and 2. 1. Create an analysis project: ```shell dx new project $PNAME ``` 1. Upload sample data to the project: ```shell dx select $PNAME dx upload -p --path /data/input *.bam ``` 1. Create a bcbio system YAML file with projects, locations of files and desired core and memory usage for jobs. bcbio uses the core and memory specifications to determine machine instance types to use: ```yaml dnanexus: project: PNAME ref: project: bcbio_resources folder: /reference_genomes inputs: - /data/input - /data/input/regions resources: default: {cores: 8, memory: 3000M, jvm_opts: [-Xms1g, -Xmx3000m]} ``` 1. Create a bcbio sample CSV file referencing samples to run. The files can be relative to the `inputs` directory specified above; bcbio will search recursively for files, so you don't need to specify full paths if your file names are unique. Start with a sample specification: ``` samplename,description,batch,phenotype file1.bam,sample1,b1,tumor file2.bam,sample2,b1,normal file3.bam,sample3,b2,tumor file4.bam,sample4,b2,normal ``` 1. Pick a template file that describes the [bcbio configuration](configuration) variables. You can define parameters either globally (in the template) file or by sample (in the csv) using the [standard bcbio templating](contents/configuration:automated%20sample%20configuration). An example template for GATK4 germline variant calling is: ```yaml details: - algorithm: aligner: bwa variantcaller: gatk-haplotype analysis: variant2 genome_build: hg38 ``` 1. Supply the three inputs (`bcbio_system.yaml`, `project.csv` and `template.yaml`) to the either the bcbio-run-workflow app or applet. This example uses a specific version of the bcbio app for full reproducibility; any future re-runs will always use the exact same versioned tools and workflows. You can do this using the web interface or via the command line with a small script like: ```shell TEMPLATE=germline APP_VERSION=0.0.2 FOLDER=/bcbio/$PNAME dx select "$PROJECT" dx mkdir -p $FOLDER for F in $TEMPLATE-template.yaml $PNAME.csv bcbio_system-dnanexus.yaml do dx rm -a /$FOLDER/$F || true dx upload --path /$FOLDER/ $F done dx ls $FOLDER dx rm -a -r /$FOLDER/dx-cwl-run || true dx run bcbio-run-workflow/$APP_VERSION -iyaml_template=/$FOLDER/$TEMPLATE-template.yaml -isample_spec=/$FOLDER/$PNAME.csv -isystem_configuration=/$FOLDER/bcbio_system-dnanexus.yaml -ioutput_folder=/$FOLDER/dx-cwl-run ``` Alternatively if you want the latest bcbio code, change the final command to use the applet. Everything else in the script is identical: ```shell dx run bcbio_resources:/applets/bcbio-run-workflow -iyaml_template=/$FOLDER/$TEMPLATE-template.yaml -isample_spec=/$FOLDER/$PNAME.csv -isystem_configuration=/$FOLDER/bcbio_system-dnanexus.yaml -ioutput_folder=/$FOLDER/dx-cwl-run ``` The app will lookup all files, prepare a bcbio CWL workflow, convert into a DNAnexus workflow, and submit to the platform. The workflow runs as a standard DNAnexus workflow and you can monitor through the command line (with `dx find executions --root job-YOURJOBID` and `dx watch`) or the web interface (`Monitor` tab). If you prefer not to use the DNAnexus app, you can also submit jobs locally by installing [bcbio-vm](https://github.com/bcbio/bcbio-nextgen-vm#installation) on your local machine. This can also be useful to test generation of CWL and manually ensure identification of all your samples and associated files on the DNAnexus platform. 1. Follow the [Automated sample configuration](contents/configuration:automated%20sample%20configuration) workflow to generate a full configuration, and generate a CWL description of the workflow: ```shell TEMPLATE=germline rm -rf $PNAME $PNAME-workflow bcbio_vm.py template --systemconfig bcbio_system-dnanexus.yaml $TEMPLATE-template.yaml $PNAME.csv bcbio_vm.py cwl --systemconfig bcbio_system-dnanexus.yaml $PNAME/config/$PNAME.yaml ``` 1. Determine project information and login credentials. You'll want to note the `Auth token used` and `Current workspace` project ID: ```shell dx env ``` 1. Compile the CWL workflow into a DNAnexus workflow: ```shell dx-cwl compile-workflow $PNAME-workflow/main-$PNAME.cwl \ --project PROJECT_ID --token $DX_AUTH_TOKEN \ --rootdir $FOLDER/dx-cwl-run ``` 1. Upload sample information from generated CWL and run workflow: ```shell FOLDER=/bcbio/$PNAME dx mkdir -p $DX_PROJECT_ID:$FOLDER/$PNAME-workflow dx upload -p --path $DX_PROJECT_ID:$FOLDER/$PNAME-workflow $PNAME-workflow/main-$PNAME-samples.json dx-cwl run-workflow $FOLDER/dx-cwl-run/main-$PNAME/main-$PNAME \ $FOLDER/$PNAME-workflow/main-$PNAME-samples.json \ --project PROJECT_ID --token $DX_AUTH_TOKEN \ --rootdir $FOLDER/dx-cwl-run ``` ## Running on Seven Bridges bcbio runs on the [Seven Bridges](https://www.sevenbridges.com/) including the main platform and specialized data sources like the [Cancer Genomics Cloud](https://www.cancergenomicscloud.org/) and [Cavatica](https://cavatica.squarespace.com/). Seven Bridges uses generated CWL directly and bcbio has utilities to query your remote data on the platform and prepare CWL for direct submission. 1. Since Seven Bridges is available on multiple platforms and data access points, we authenticate with a configuration file in `$HOME/.sevenbridges/credentials` with potentially [multiple profiles defining API access URLs and authentication keys](https://sevenbridges-python.readthedocs.io/en/latest/quickstart/#initialize-the-library-using-a-configuration-file). We reference the [specified credentials](https://docs.sevenbridges.com/docs/store-credentials-to-access-seven-bridges-client-applications-and-libraries#section-unified-configuration-file) when setting up a `bcbio_system-sbg.yaml` file to ensure correct authentication. 1. Upload your inputs and bcbio reference data using the [Seven Bridges command line uploader](https://docs.sevenbridges.com/docs/upload-via-the-command-line). We plan to host standard bcbio reference data in a public project so you should only need to upload your project specific data: ```shell sbg-uploader.sh -p chapmanb/bcbio-test --folder inputs --preserve-folder fastq_files regions ``` 1. Create `bcbio_system-sbg.yaml` file defining locations of inputs: ```yaml sbgenomics: profile: default project: chapmanb/bcbio-test inputs: - /testdata/100326_FC6107FAAXX - /testdata/automated - /testdata/genomes - /testdata/reference_material resources: default: cores: 2 memory: 3G jvm_opts: [-Xms750m, -Xmx3000m] ``` 1. Follow the [Automated sample configuration](contents/configuration:automated%20sample%20configuration) workflow to generate a full configuration, and generate a CWL description of the workflow: ```shell PNAME=somatic bcbio_vm.py template --systemconfig=bcbio_system-sbg.yaml ${PNAME}_template.yaml $PNAME.csv bcbio_vm.py cwl --systemconfig=bcbio_system-sbg.yaml $PNAME/config/$PNAME.yaml ``` 1. Run the job on the Seven Bridges platform: ```shell PNAME=somatic SBG_PROJECT=bcbio-test bcbio_vm.py cwlrun sbg ${PNAME}-workflow -- --project ${SBG_PROJECT} ``` ## Development notes bcbio generates a common workflow language description. Internally, bcbio represents the files and information related to processing as [a comprehensive dictionary](contents/development:data). This world object describes the state of a run and associated files, and new processing steps update or add information to it. The world object is roughly equivalent to CWL's JSON-based input object, but CWL enforces additional annotations to identify files and models new inputs/outputs at each step. The work in bcbio is to move from our laissez-faire approach to the more structured CWL model. The generated CWL workflow is in `run_info-cwl-workflow`: * `main-*.cwl` -- the top level CWL file describing the workflow steps * `main*-samples.json` -- the flattened bcbio world structure represented as CWL inputs * `wf-*.cwl` -- CWL sub-workflows, describing sample level parallel processing of a section of the workflow, with potential internal parallelization. * `steps/*.cwl` -- CWL descriptions of sections of code run inside bcbio. Each of these are potential parallelization points and make up the nodes in the workflow. To help with defining the outputs at each step, there is a `WorldWatcher` object that can output changed files and world dictionary objects between steps in the pipeline when running a bcbio in the standard way. The [variant pipeline](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/main.py) has examples using it. This is useful when preparing the CWL definitions of inputs and outputs for new steps in the [bcbio CWL step definitions](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/cwl/workflow.py). ## ToDo * Support the full variant calling workflow with additional steps like ensemble calling, heterogeneity detection and disambiguation. * Port RNA-seq and small RNA workflows to CWL. bcbio-nextgen-1.2.9/docs/contents/development.md000066400000000000000000001000071415626112400217000ustar00rootroot00000000000000# Development This section provides useful concepts for getting started digging into the code and contributing new functionality. We welcome contributors and hope these notes help make it easier to get started. ## bcbio dev installation When developing, you'd like to avoid breaking your production bcbio instance. Use the installer script to create a separate bcbio instance without downloading any data. Before installing the second bcbio instance, investigate your PATH and PYTHONPATH variables and clean them from referenceing the production bcbio python. It is better to avoid mixing bcbio instances in the PATH. Also watch `~/.conda/environments.txt`, `~/.condarc` config files, CONDA_EXE, CONDA_PYTHON_EXE environment variables : having a reference to the production package cache: `/n/app/bcbio/dev/anaconda/pkgs` leads to `bcbio/tools/bin` not being populated in some installs. To install in `${HOME}/local/share/bcbio` (your location might be different, make sure you have ~30GB of disk quota there): ```shell wget https://raw.githubusercontent.com/chapmanb/bcbio-nextgen/master/scripts/bcbio_nextgen_install.py python bcbio_nextgen_install.py ${HOME}/local/share/bcbio --tooldir=${HOME}/local --nodata --isolate ``` Make soft links to the data from your production bcbio instance (your installation path could be different from /n/app/bcbio): ```shell ln -s /n/app/bcbio/biodata/genomes/ ${HOME}/local/share/genomes ln -s /n/app/bcbio/biodata/galaxy/tool-data ${HOME}/local/share/bcbio/galaxy/tool-data ``` Create `.bcbio_devel_profile` to clear PATH from the production bcbio executables and reference the development version: ```bash # use everything you need except of production bcbio export PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin: export PATH=${HOME}/local/share/bcbio/anaconda/bin:${HOME}/local/bin:$PATH export CONDA_EXE=${HOME}/local/share/bcbio/anaconda/bin/conda export CONDA_PYTHON_EXE=${HOME}/local/share/bcbio/anaconda/bin/python ``` Or directly call the testing bcbio: `${HOME}/local/share/bcbio/anaconda/bin/bcbio_nextgen.py`. ## Injecting bcbio code into bcbio installation To install from your bcbio-nextgen source tree for testing do: ```shell # make sure you are using the development bcbio instance which bcbio_python # local git folder cd ~/code/bcbio-nextgen bcbio_python setup.py install ``` One tricky part that we don't yet know how to work around is that pip and standard `setup.py install` have different ideas about how to write Python eggs. `setup.py install` will create an isolated python egg directory like `bcbio_nextgen-1.1.5-py3.6.egg`, while pip creates an egg pointing to a top level `bcbio` directory. Where this gets tricky is that the top level `bcbio` directory takes precedence. The best way to work around this problem is to manually remove the current pip installed bcbio-nextgen code (`rm -rf /path/to/anaconda/lib/python3.6/site-packages/bcbio*`) before managing it manually with `bcbio_python setup.py install`. We'd welcome tips about ways to force consistent installation across methods. ## Testing The test suite exercises the scripts driving the analysis, so are a good starting point to ensure correct installation. Tests use the [pytest](https://doc.pytest.org/en/latest/) framework. The tests are available in the bcbio source code: ```shell git clone https://github.com/bcbio/bcbio-nextgen.git ``` There is a small wrapper script that finds the pytest and other dependencies pre-installed with bcbio you can use to run tests: ```shell cd tests ./run_tests.sh ``` You can use this to run specific test targets: ```shell ./run_tests.sh cancer ./run_tests.sh rnaseq ./run_tests.sh devel ./run_tests.sh docker ``` Optionally, you can run pytest directly from the bcbio install to tweak more options. It will be in `/path/to/bcbio/anaconda/bin/pytest`. Pass `-s` to `pytest` to see the stdout log, and `-v` to make pytest output more verbose. The `-x` flag will stop the test at the first failure and `--lf` will run only the tests that failed the last go-around. Sometimes it is useful to drop into the debugger on failure, wihch you can do by setting `-s --pdb`. The tests are marked with labels which you can use to run a specific subset of the tests using the `-m` argument: ```shell pytest -m rnaseq ``` To run unit tests: ```shell pytest tests/unit ``` To run integration pipeline tests: ```shell pytest tests/integration ``` To run tests which use bcbio_vm: ```shell pytest tests/bcbio_vm ``` To see the test coverage, add the `--cov=bcbio` argument to `pytest`. By default the test suite will use your installed system configuration for running tests, substituting the test genome information instead of using full genomes. If you need a specific testing environment, copy `tests/data/automated/post_process-sample.yaml` to `tests/data/automated/post_process.yaml` to provide a test-only configuration. The environment variable `BCBIO_TEST_DIR` can put the tests in a different directory if the full path to the new directory is specified. For example: ```bash export BCBIO_TEST_DIR=$(pwd)/output ``` will put the output in your current working directory/output. The test directory can be kept around after running by passing the `--keep-test-dir` flag. Repeat a failed test: ```bash export BCBIO_TEST_DIR=/path/to/test; \ pytest -s -x --keep-test-dir tests/integration/test_automated_analysis.py::failed_test ``` ## New release checklist - [ ] pull from master to make sure you are up to date - [ ] inject the latest code to bcbio dev instance - [ ] run integration tests: `pytest -s -x tests/integration/test_automated_analysis.py` - 24 tests, breaks after the first failed test - [ ] run unit tests: `pytest -s -x tests/unit` - [ ] create a branch release_xyz_prep - [ ] update version in [setup.py](https://github.com/bcbio/bcbio-nextgen/blob/master/setup.py) and [docs/conf.py](https://github.com/bcbio/bcbio-nextgen/blob/master/docs/conf.py) - [ ] move all finished items from the pinned issue and add release date to [HISTORY.md](https://github.com/bcbio/bcbio-nextgen/blob/master/HISTORY.md), start new (in progress) section - [ ] commit and push changes to bcbio - [ ] draft new release, copy and paste changes from [HISTORY.md](https://github.com/bcbio/bcbio-nextgen/blob/master/HISTORY.md) to the changelog - [ ] wait for [bioconda-recipes](https://github.com/bioconda/bioconda-recipes/pulls) to pick up the new release - [ ] review and approve bioconda recipe once it passes the tests - [ ] merge recipe by commenting `@bioconda-bot please merge` - [ ] wait until new version is available on [bioconda](https://anaconda.org/bioconda/bcbio-nextgen/files) - [ ] update [requirements-conda.txt](https://github.com/bcbio/bcbio-nextgen/blob/master/requirements-conda.txt) - [ ] update [requirements.txt](https://github.com/bcbio/bcbio-nextgen/blob/master/requirements.txt) - [ ] push changes to bcbio - [ ] run installation test (`--no-data`) - [ ] run T/N end2end test ### not working for now - [ ] update BCBIO_VERSION in [bcbio_docker](https://github.com/bcbio/bcbio_docker/blob/master/.travis.yml) - [ ] update BCBIO_REVISION in [bcbio_docker](https://github.com/bcbio/bcbio_docker/blob/master/.travis.yml) - [ ] push changes to bcbio_docker - [ ] make sure the image builds successfully ## Goals bcbio-nextgen provides best-practice pipelines for automated analysis of high throughput sequencing data with the goal of being: * Quantifiable: Doing good science requires being able to accurately assess the quality of results and re-verify approaches as new algorithms and software become available. * Analyzable: Results feed into tools to make it easy to query and visualize the results. * Scalable: Handle large datasets and sample populations on distributed heterogeneous compute environments. * Reproducible: Track configuration, versions, provenance and command lines to enable debugging, extension and reproducibility of results. * Community developed: The development process is fully open and sustained by contributors from multiple institutions. By working together on a shared framework, we can overcome the challenges associated with maintaining complex pipelines in a rapidly changing area of research. * Accessible: Bioinformaticians, biologists and the general public should be able to run these tools on inputs ranging from research materials to clinical samples to personal genomes. During development we seek to maximize functionality and usefulness, while avoiding complexity. Since these goals are sometimes in conflict, it's useful to understand the design approaches: * Support high level configurability but avoid exposing all program options. Since pipelines support a wide variety of tools, each with a large number of options, we try to define configuration variables at high level based on biological intent and then translate these into best-practice options for each tool. The goal is to avoid having an overwhelming number of input configuration options. * Provide best-practice pipelines that make recommended decisions for processing. Coupled with goal of minimizing configuration parameters, this requires trust and discussion around algorithm choices. An example is bwa alignment, which uses `bwa aln` for reads shorter than 75bp and `bwa mem` for longer reads, based on recommendations from Heng Li. Our general goal is to encourage discussion and development of best-practices to make it easy to do the right thing. * Support extensive debugging output. In complex distributed systems, programs fail in unexpected ways even during production runs. We try to maximize logging to help identify and diagnose these type of unexpected problems. * Avoid making mistakes. This results in being conservative about decisions like deleting file intermediates. Coupled with extensive logging, we trade off disk usage for making it maximally easy to restart and debug problems. If you'd like to delete work or log directories automatically, we recommend doing this as part of your batch scripts wrapping bcbio-nextgen. * Strive for a clean, readable code base. We strive to make the code a secondary source of information after hand written docs. Practically, this means maximizing information content in source files while using in-line documentation to clarify as needed. * Focus on a functional coding style with minimal use of global mutable objects. This approach works well with distributed code and isolates debugging to individual functions rather than globally mutable state. * Make sure your changes integrate correctly by running the test suite before submitting a pull request. The pipeline is automatically tested in [Travis-CI](https://travis-ci.org/bcbio/bcbio-nextgen), and a red label will appear in the pull request if the former causes any issue. ## Style guide General: * Delete unnecessary code (do not just comment it out) * Refactor existing code to help deliver new functionality * Specify exact version numbers for dependencies Python: * Follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) and [PEP 20](https://www.python.org/dev/peps/pep-0020/) * Limit all lines to a maximum of 99 characters * Add docstrings to each module * Follow [PEP 257](https://www.python.org/dev/peps/pep-0257/) for docstrings: * the `"""` that ends a multiline docstring should be on a line by itself * for one-liner docstrings keep the closing `"""` on the same line * Clarify function calls with keyword arguments for readability * Use [type hints](https://www.python.org/dev/peps/pep-0484/) ## Modules The most useful modules inside `bcbio`, ordered by likely interest: * `pipeline` -- Top level functionality that drives the analysis pipeline. `main.py` contains top level definitions of pipelines like variant calling and RNAseq, and is the best place to start understanding the overall organization of the code. * `ngsalign` -- Integration with aligners for high-throughput sequencing data. We support individual aligners with their own separate modules. * `variation` -- Tools for variant calling. Individual variant calling and processing approaches each have their own submodules. * `rnaseq` -- Run RNA-seq pipelines, currently supporting TopHat/Cufflinks. * `provenance` -- Track third party software versions, command lines and program flow. Handle writing of debugging details. * `distributed` -- Handle distribution of programs across multiple cores, or across multiple machines using IPython. * `workflow` -- Provide high level tools to run customized analyses. They tie into specialized analyses or visual front ends to make running bcbio-nextgen easier for specific common tasks. * `broad` -- Code to handle calling Broad tools like GATK and Picard, as well as other Java-based programs. ## GitHub bcbio-nextgen uses GitHub for code development, and we welcome pull requests. GitHub makes it easy to establish custom forks of the code and contribute those back. The Biopython documentation has great information on [using git and GitHub](https://biopython.org/wiki/GitUsage) for a community developed project. In short, make a fork of the [bcbio code](https://github.com/bcbio/bcbio-nextgen) by clicking the `Fork` button in the upper right corner of the GitHub page, commit your changes to this custom fork and keep it up to date with the main bcbio repository as you develop. The GitHub help pages have detailed information on keeping your fork updated with the main GitHub repository (e.g. ). After commiting changes, click `New Pull Request` from your fork when you'd like to submit your changes for integration in bcbio. ## Installing development tools ```shell conda install --file requirements-dev.txt ``` ## Documentation To build this documentation locally and see how it looks like you can do so by installing the dependencies: ```shell cd docs conda install --file requirements-local.txt --file requirements.txt ``` and running: ```shell make html ``` The documentation will be built under `docs/_build/html`, open `index.html` with your browser to load your local build. ## Adding tools ### Aligner Write new aligners within their own submodule inside the `ngsalign` directory. [bwa.py](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/ngsalign/bwa.py) is a good example to follow along with. There are two functions to implement, based on which type of alignment you'd like to allow: * `align_bam` -- Performs alignment given an input BAM file. Expected to return a sorted BAM output file. * `align` -- Performs alignment given FASTQ inputs (gzipped or not). This is generally expected to implement an approach with unix-pipe that minimizes intermediates and disk IO, returning a sorted BAM output file. For back-compatibility this can also return a text based SAM file. See the [names](#names) section for more details on arguments. Other required implementation details include: * `galaxy_loc_file` -- Provides the name of the [Galaxy loc file](https://galaxyproject.org/admin/data-integration/) used to identify locations of indexes for this aligner. The automated installer sets up these loc files automatically. * `remap_index_fn` -- A function that remaps an index from the Galaxy location file into the exact one for this aligner. This is useful for tools which aren't supported by a Galaxy .loc file but you can locate them relative to another index. Once implemented, plug the aligner into the pipeline by defining it as a `_tool` in [bcbio/pipeline/alignment.py](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/alignment.py). You can then use it as normal by specifying the name of the aligner in the _aligner_ section of your configuration input. ### Variant caller New variant calling approaches live within their own module inside `bcbio/variation`. The [freebayes.py](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/variation/freebayes.py) implementation is a good example to follow for providing your own variant caller. Implement a function to run variant calling on multiple BAMs in an input region that takes the following inputs: * `align_bams` -- A list of BAM files to call simultaneously. * `items` -- List of `data` dictionaries associated with each of the samples in `align_bams`. Enables customization of variant calling based on sample configuration inputs. See documentation on the [data](#data) dictionary for all of the information contained inside each `data` item. * `ref_file` -- Fasta reference genome file. * `assoc_files` -- Useful associated files for variant calling. This includes the DbSNP VCF file. It's a named tuple mapping to files specified in the configuration. [bcbio/pipeline/shared.py](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/shared.py#L176) has the available inputs. * `region` -- A tuple of (chromosome, start, end) specifying the region to call in. * `out_file`-- The output file to write to. This should contain calls for all input samples in the supplied region. Once implemented, add the variant caller into the pipeline by updating `caller_fns` in the `variantcall_sample` function in [bcbio/variation/genotype.py](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/variation/genotype.py#L548). You can use it by specifying it in the `variantcaller` parameter of your sample configuration. ## Adding new organisms While bcbio-nextgen and supporting tools receive the most testing and development on human or human-like diploid organisms, the algorithms are generic and we strive to support the wide diversity of organisms used in your research. We welcome contributors interested in setting up and maintaining support for their particular research organism, and this section defines the steps in integrating a new genome. We also welcome suggestions and implementations that improve this process. Setup CloudBioLinux to automatically download and prepare the genome: * Add the genome database key and organism name to list of supported organisms in the CloudBioLinux configuration ([config/biodata.yaml](https://github.com/chapmanb/cloudbiolinux/blob/master/config/biodata.yaml)). * Add download details to specify where to get the fasta genome files ([cloudbio/biodata/genomes.py](https://github.com/chapmanb/cloudbiolinux/blob/7a2161a415d3dcd76f41095cd8f16bec84d4b1f3/cloudbio/biodata/genomes.py#L267)). CloudBioLinux supports common genome providers like UCSC and Ensembl directly. Add the organism to the supported installs within bcbio (in two places): * for the initial installer ([scripts/bcbio_nextgen_install.py](https://github.com/bcbio/bcbio-nextgen/blob/8c93fe2dc4d2966e106a4b3edf5aa23550703481/scripts/bcbio_nextgen_install.py#L236)) * for the updater ([bcbio/install.py](https://github.com/bcbio/bcbio-nextgen/blob/8c93fe2dc4d2966e106a4b3edf5aa23550703481/bcbio/install.py#L523)). Test installation of genomes by pointing to your local cloudbiolinux edits during a data installation: ```shell mkdir -p tmpbcbio-install ln -s ~/bio/cloudbiolinux tmpbcbio-install bcbio_nextgen.py upgrade --data --genomes DBKEY ``` Add configuration information to bcbio-nextgen by creating a `config/genomes/DBKEY-resources.yaml` file. Copy an existing minimal template like `canFam3` and edit with pointers to snpEff and other genome resources. The [VEP database directory](ftp://ftp.ensembl.org/pub/current_variation/VEP/) has Ensembl names. SnpEff has a command to list available databases: ```shell snpEff databases ``` Finally, send pull requests for CloudBioLinux and bcbio-nextgen and we'll happily integrate the new genome. This will provide basic integration with bcbio and allow running a minimal pipeline with alignment and quality control. We also have utility scripts in CloudBioLinux to help with preparing dbSNP ([utils/prepare_dbsnp.py](https://github.com/chapmanb/cloudbiolinux/blob/master/utils/prepare_dbsnp.py)) and RNA-seq ([utils/prepare_tx_gff.py](https://github.com/chapmanb/cloudbiolinux/blob/master/utils/prepare_tx_gff.py)) resources for some genomes. For instance, to prepare RNA-seq transcripts for mm9: ```shell bcbio_python prepare_tx_gff.py --genome-dir /path/to/bcbio/genomes Mmusculus mm9 ``` We are still working on ways to best include these as part of the standard build and install since they either require additional tools to run locally, or require preparing copies in S3 buckets. ## Enabling new MultiQC modules [MultiQC modules](https://multiqc.info/docs/#multiqc-modules) can be turned on in `bcbio/qc/multiqc.py`. `bcbio` collects the files to be used rather than searching through the work directory to support CWL workflows. Quality control files can be added by using the `datadict.update_summary_qc` function which adds the files in the appropriate place in the `data` dict. For example, here is how to add the quality control reports from bismark methylation calling: ```python data = dd.update_summary_qc(data, "bismark", base=biasm_file) data = dd.update_summary_qc(data, "bismark", base=data["bam_report"]) data = dd.update_summary_qc(data, "bismark", base=splitting_report) ``` Files that can be added for each tool in MultiQC can be found in the [MultiQC module documentation](https://multiqc.info/docs/#multiqc-modules) ## Standard function arguments ### names This dictionary provides lane and other [BAM run group](https://samtools.github.io/hts-specs/SAMv1.pdf) naming information used to correctly build BAM files. We use the `rg` attribute as the ID within a BAM file: ``` {'lane': '7_100326_FC6107FAAXX', 'pl': 'illumina', 'pu': '7_100326_FC6107FAAXX', 'rg': '7', 'sample': 'Test1'} ``` ### data The _data_ dictionary is a large dictionary representing processing, configuration and files associated with a sample. The standard work flow is to pass this dictionary between functions, updating with associated files from the additional processing. Populating this dictionary only with standard types allows serialization to JSON for distributed processing. The dictionary is dynamic throughout the workflow depending on the step, but some of the most useful key/values available throughout are: * `config` -- Input configuration variables about how to process in the `algorithm` section and locations of programs in the `resources` section. * `dirs` -- Useful directories for building output files or retrieving inputs. * `metadata` -- Top level metadata associated with a sample, specified in the initial configuration. * `genome_resources` -- Naming aliases and associated files associated with the current genome build. Retrieved from organism specific configuration files (`buildname-resources.yaml`) this specifies the location of supplemental organism specific files like support files for variation and RNA-seq analysis. It also contains information the genome build, sample name and reference genome file throughout. Here's an example of these inputs: ```python {'config': {'algorithm': {'aligner': 'bwa', 'callable_regions': 'analysis_blocks.bed', 'coverage_depth': 'low', 'coverage_interval': 'regional', 'mark_duplicates': 'samtools', 'nomap_split_size': 50, 'nomap_split_targets': 20, 'num_cores': 1, 'platform': 'illumina', 'quality_format': 'Standard', 'realign': 'gkno', 'recalibrate': 'gatk', 'save_diskspace': True, 'upload_fastq': False, 'validate': '../reference_material/7_100326_FC6107FAAXX-grade.vcf', 'variant_regions': '../data/automated/variant_regions-bam.bed', 'variantcaller': 'freebayes'}, 'resources': {'bcbio_variation': {'dir': '/usr/share/java/bcbio_variation'}, 'bowtie': {'cores': None}, 'bwa': {'cores': 4}, 'cortex': {'dir': '~/install/CORTEX_release_v1.0.5.14'}, 'cram': {'dir': '/usr/share/java/cram'}, 'gatk': {'cores': 2, 'dir': '/usr/share/java/gatk', 'jvm_opts': ['-Xms750m', '-Xmx2000m'], 'version': '2.4-9-g532efad'}, 'gemini': {'cores': 4}, 'novoalign': {'cores': 4, 'memory': '4G', 'options': ['-o', 'FullNW']}, 'picard': {'cores': 1, 'dir': '/usr/share/java/picard'}, 'snpEff': {'dir': '/usr/share/java/snpeff', 'jvm_opts': ['-Xms750m', '-Xmx3g']}, 'stampy': {'dir': '~/install/stampy-1.0.18'}, 'tophat': {'cores': None}, 'varscan': {'dir': '/usr/share/java/varscan'}, 'vcftools': {'dir': '~/install/vcftools_0.1.9'}}}, 'genome_resources': {'aliases': {'ensembl': 'human', 'human': True, 'snpeff': 'hg19'}, 'rnaseq': {'transcripts': '/path/to/rnaseq/ref-transcripts.gtf', 'transcripts_mask': '/path/to/rnaseq/ref-transcripts-mask.gtf'}, 'variation': {'dbsnp': '/path/to/variation/dbsnp_132.vcf', 'train_1000g_omni': '/path/to/variation/1000G_omni2.5.vcf', 'train_hapmap': '/path/to/hg19/variation/hapmap_3.3.vcf', 'train_indels': '/path/to/variation/Mills_Devine_2hit.indels.vcf'}, 'version': 1}, 'dirs': {'fastq': 'input fastq directory', 'galaxy': 'directory with galaxy loc and other files', 'work': 'base work directory'}, 'metadata': {'batch': 'TestBatch1'}, 'genome_build': 'hg19', 'name': ('', 'Test1'), 'sam_ref': '/path/to/hg19.fa'} ``` Processing also injects other useful key/value pairs. Here's an example of additional information supplied during a variant calling workflow: ```python {'prep_recal': 'Test1/7_100326_FC6107FAAXX-sort.grp', 'summary': {'metrics': [('Reference organism', 'hg19', ''), ('Total', '39,172', '76bp paired'), ('Aligned', '39,161', '(100.0\\%)'), ('Pairs aligned', '39,150', '(99.9\\%)'), ('Pair duplicates', '0', '(0.0\\%)'), ('Insert size', '152.2', '+/- 31.4')], 'pdf': '7_100326_FC6107FAAXX-sort-prep-summary.pdf', 'project': 'project-summary.yaml'}, 'validate': {'concordant': 'Test1-ref-eval-concordance.vcf', 'discordant': 'Test1-eval-ref-discordance-annotate.vcf', 'grading': 'validate-grading.yaml', 'summary': 'validate-summary.csv'}, 'variants': [{'population': {'db': 'gemini/TestBatch1-freebayes.db', 'vcf': None}, 'validate': None, 'variantcaller': 'freebayes', 'vrn_file': '7_100326_FC6107FAAXX-sort-variants-gatkann-filter-effects.vcf'}], 'vrn_file': '7_100326_FC6107FAAXX-sort-variants-gatkann-filter-effects.vcf', 'work_bam': '7_100326_FC6107FAAXX-sort-prep.bam'} ``` ## Parallelization framework bcbio-nextgen supports parallel runs on local machines using multiple cores and distributed on a cluster using IPython using a general framework. The first parallelization step starts up a set of resources for processing. On a cluster this spawns a IPython parallel controller and set of engines for processing. The [prun (parallel run)](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/distributed/prun.py) `start` function is the entry point to spawning the cluster and the main argument is a `parallel` dictionary which contains arguments to the engine processing command. Here is an example input from an IPython parallel run: ``` {'cores': 12, 'type': 'ipython' 'progs': ['aligner', 'gatk'], 'ensure_mem': {'star': 30, 'tophat': 8, 'tophat2': 8}, 'module': 'bcbio.distributed', 'queue': 'batch', 'scheduler': 'torque', 'resources': [], 'retries': 0, 'tag': '', 'timeout': 15} ``` The `cores` and `type` arguments must be present, identifying the total cores to use and type of processing, respectively. Following that are arguments to help identify the resources to use. `progs` specifies the programs used, here the aligner, which bcbio looks up from the input sample file, and gatk. `ensure_mem` is an optional argument that specifies minimum memory requirements to programs if used in the workflow. The remaining arguments are all specific to IPython to help it spin up engines on the appropriate computing cluster. A shared component of all processing runs is the identification of used programs from the `progs` argument. The run creation process looks up required memory and CPU resources for each program from the [Resources](contents/configuration:resources) section of your `bcbio_system.yaml` file. It combines these resources into required memory and cores using the logic described in the [Memory management](contents/parallel:memory%20management) section of the parallel documentation. Passing these requirements to the cluster creation process ensures the available machines match program requirements. bcbio-nextgen's [pipeline.main](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/main.py) code contains examples of starting and using set of available processing engines. This example starts up machines that use samtools, gatk and cufflinks then runs an RNA-seq expression analysis: ```python with prun.start(_wprogs(parallel, ["samtools", "gatk", "cufflinks"]), samples, config, dirs, "rnaseqcount") as run_parallel: samples = rnaseq.estimate_expression(samples, run_parallel) ``` The pipelines often reuse a single set of machines for multiple distributed functions to avoid the overhead of starting up and tearing down machines and clusters. The `run_parallel` function returned from the `prun.start` function enables running on jobs in the parallel on the created machines. The [ipython wrapper](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/distributed/ipython.py) code contains examples of implementing this. It is a simple function that takes two arguments, the name of the function to run and a set of multiple arguments to pass to that function: ```python def run(fn_name, items): ``` The `items` arguments need to be strings, lists and dictionaries to allow serialization to JSON format. The internals of the run function take care of running all of the code in parallel and returning the results back to the caller function. In this setup, the main processing code is fully independent from the parallel method used so running on a single multicore machine or in parallel on a cluster return identical results and require no changes to the logical code defining the pipeline. During re-runs, we avoid the expense of spinning up processing clusters for completed tasks using simple checkpoint files in the `checkpoints_parallel` directory. The `prun.start` wrapper writes these on completion of processing for a group of tasks with the same parallel architecture, and on subsequent runs will go through these on the local machine instead of parallelizing. The processing code supports these quick re-runs by checking for and avoiding re-running of tasks when it finds output files. Plugging new parallelization approaches into this framework involves writing interface code that handles the two steps. First, create a cluster of ready to run machines given the `parallel` function with expected core and memory utilization: * `num_jobs` -- Total number of machines to start. * `cores_per_job` -- Number of cores available on each machine. * `mem` -- Expected memory needed for each machine. Divide by `cores_per_job` to get the memory usage per core on a machine. Second, implement a `run_parallel` function that handles using these resources to distribute jobs and return results. The [multicore wrapper](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/distributed/multi.py) and [ipython wrapper](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/distributed/ipython.py) are useful starting points for understanding the current implementations. bcbio-nextgen-1.2.9/docs/contents/disambiguation.md000066400000000000000000000032151415626112400223600ustar00rootroot00000000000000# Disambiguation * `disambiguate` For mixed or explant samples, provide a list of `genome_build` identifiers to check and remove from alignment. Currently supports cleaning a single organism. For example, with `genome_build: hg19` and `disambiguate: [mm10]`, it will align to hg19 and mm10, run disambiguation and discard reads confidently aligned to mm10 and not hg19. Affects fusion detection when `star` is chosen as the aligner. Aligner must be set to a non false value for this to run. Example config: ``` details: - algorithm: aligner: bwa background: /path/to/project/config/1000g_pon.hg38.vcf.gz disambiguate: mm10 mark_duplicates: true platform: illumina quality_format: standard realign: false recalibrate: false remove_lcr: true tools_on: - noalt_calling variantcaller: - vardict - mutect2 vcfanno: somatic analysis: variant2 description: SAMPLE files: - /path/to/project/input/sample_1.fq.gz - /path/to/project/input/sample_2.fq.gz genome_build: hg38 metadata: batch: bSAMPLE phenotype: tumor upload: dir: ../final ``` The resulting `final/project/multiqc/multiqc_report.html` will contain hg38 and mm10 columns with numbers of reads aligned to hg38 and mm10. Also `final/sample` contains sample-ready.bam - reads aligned to hg38 and sample-disambiguate-mm10.bam - reads aligned to mm10. ## Output - final/project/multiqc: Reads = single reads in the final bam (mapped to human genome), hg38 = single reads mapped to human genome (same as Reads), mm10 = single reads mapped to mouse genome; Ambig. = single reads ambiguously mapped; Total reads = sum (hg38 + mm10 + Ambig.). bcbio-nextgen-1.2.9/docs/contents/fast_rnaseq.md000066400000000000000000000011311415626112400216620ustar00rootroot00000000000000# fast RNA-seq This mode of `bcbio-nextgen` quantitates transcript expression using [Salmon](https://salmon.readthedocs.io/en/latest/) and does nothing else. It is an order of magnitude faster or more than running the full RNA-seq analysis. The cost of the increased speed is that you will have much less information about your samples at the end of the run, which can make troubleshooting trickier. Invoke with `analysis: fastrna-seq`. ## Parameters - `transcriptome_fasta` An optional FASTA file of transcriptome sequences to quantitate rather than using bcbio installed transcriptome sequences. bcbio-nextgen-1.2.9/docs/contents/germline_variants.md000066400000000000000000000524561415626112400231050ustar00rootroot00000000000000# Small germline variants ## Workflow1: validate hg38 calls This workflow validates variant calls using WES data for NA12878 sample. ### 1. Create project structure ```shell mkdir validate_giab cd validate_giab mkdir config input final work ``` ### 2. Prepare input data ```shell cd input wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7035_TAAGGCGA_L001_R1_001.fastq.gz wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7035_TAAGGCGA_L001_R2_001.fastq.gz wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7035_TAAGGCGA_L002_R1_001.fastq.gz wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7035_TAAGGCGA_L002_R2_001.fastq.gz wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7086_CGTACTAG_L001_R1_001.fastq.gz wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7086_CGTACTAG_L001_R2_001.fastq.gz wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7086_CGTACTAG_L002_R1_001.fastq.gz wget -c ftp://ftp-trace.ncbi.nih.gov/ReferenceSamples/giab/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/NIST7086_CGTACTAG_L002_R2_001.fastq.gz # hg19 wget -c ftp://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/NA12878/Garvan_NA12878_HG001_HiSeq_Exome/nexterarapidcapture_expandedexome_targetedregions.bed.gz gunzip nexterarapidcapture_expandedexome_targetedregions.bed.gz cat *R1* > NA12878_1.fq.gz cat *R2* > NA12878_2.fq.gz rm Garvan_NA12878* ``` ### 3. Convert capture regions file to hg38 coordinates with [UCSC liftover](https://genome.ucsc.edu/cgi-bin/hgLiftOver). ``` Successfully converted 200993 records: View Conversions Conversion failed on 78 records. ``` Save file to `validate_giab/input/nexterarapidcapture_expandedexome_targetedregions.hg38.bed` ### 4. Set analysis parameters in `config/NA12878.yaml`: ```yaml details: - files: - /full/path/validate_giab/input/NA12878_1.fq.gz - /full/path/validate_giab/input/NA12878_2.fq.gz description: NA12878 metadata: sex: female analysis: variant2 genome_build: hg38 algorithm: aligner: bwa variantcaller: gatk-haplotype validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed variant_regions: /full/path/validate_giab/input/nexterarapidcapture_expandedexome_targetedregions.hg38.bed resources: default: cores: 7 jvm_opts: - -Xms750m - -Xmx7000m memory: 8G upload: dir: ../final ``` ### 5. Run the project (8cores/64G RAM) ```bash cd validate_giab/work bcbio_nextgen.py ../config/NA12878.yaml -n 8 ``` Running time ~ 2.4h ### 6. Review results: - `final/[date]_project/grading-summary-NA12878.csv`: ``` sample,caller,vtype,metric,value NA12878,gatk-haplotype,SNPs,tp,36710 NA12878,gatk-haplotype,Indels,tp,3588 NA12878,gatk-haplotype,SNPs,fp,285 NA12878,gatk-haplotype,Indels,fp,981 NA12878,gatk-haplotype,SNPs,fn,323 NA12878,gatk-haplotype,Indels,fn,611 ``` - Here FDR_SNPS = 285 / (285 + 36710) = 0.77%, so precision is 99.23% - FNR_SNPS = 323 / (323 + 36710) = 0.87%, so sensitivity is 99.13% - more improvement is possible with higher coverage depth and custom filters, but overall 99.23% precision / 99.13% sensitivity is a good result for out of the box pipeline. ## Workflow2: Basic germline calling The best approach to build a bcbio configuration for germline calling is to use the automated sample configuration with one of the default templates: * [FreeBayes template](https://github.com/bcbio/bcbio-nextgen/blob/master/config/templates/freebayes-variant.yaml) --Call variants using FreeBayes with a minimal preparation pipeline. This is a freely available unrestricted pipeline fully included in the bcbio installation. * [GATK HaplotypeCaller template](https://github.com/bcbio/bcbio-nextgen/blob/master/config/templates/gatk-variant.yaml) --Run GATK best practices, including Base Quality Score Recalibration, realignment and HaplotypeCaller variant calling. This requires a license from Broad for commercial use. You need to manually install GATK along with bcbio using downloads from the GATK Broad site or Appistry. ## Workflow3: Population calling When calling multiple samples, we recommend calling together to provide improved sensitivity and a fully squared off final callset. To associate samples together in a population add a `metadata` `batch` to the sample configuration: ```yaml - description: Sample1 metadata: batch: Batch1 - description: Sample2 metadata: batch: Batch1 ``` Batching samples results in output VCFs and GEMINI databases containing all merged sample calls. bcbio has two methods to call samples together: * Batch or pooled calling -- This calls all samples simultaneously by feeding them to the variant caller. This works for smaller batch sizes (< 100 samples) as memory requirements become limiting in larger pools. This is the default approach taken when you specify a `variantcaller` in the variant calling configuration. * Joint calling -- This calls samples independently, then combines them together into a single callset by integrating the individual calls. This scales to larger population sizes by avoiding the computational bottlenecks of pooled calling. We recommend joint calling with HaplotypeCaller but also support joint calling with FreeBayes using a custom implementation. Specifying a `jointcaller` along with the appropriate `variantcaller` in the variant calling configuration enables this ```yaml - description: Sample1 algorithm: variantcaller: gatk-haplotype jointcaller: gatk-haplotype-joint metadata: batch: Batch1 - description: Sample2 algorithm: variantcaller: gatk-haplotype jointcaller: gatk-haplotype-joint metadata: batch: Batch1 ``` ## Workflow4: Whole genome trio (50x) - hg38 This input configuration runs whole genome bwa alignment and GATK variant calling. It uses a father/mother/child trio from the [CEPH NA12878 family](https://blog.goldenhelix.com/wp-content/uploads/2013/03/Utah-Pedigree-1463-with-NA12878.png): NA12891, NA12892, NA12878. Illumina's [Platinum genomes project](https://www.illumina.com/platinumgenomes.html) has 50X whole genome sequencing of the three members. The analysis compares results against a reference NA12878 callset from NIST's [Genome in a Bottle](https://www.nist.gov/programs-projects/genome-bottle) initiative. To run the analysis do: ```shell mkdir NA12878-trio-eval cd NA12878-trio-eval mkdir config input work cd config wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-trio-wgs-validate.yaml cd ../input wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-trio-wgs-validate-getdata.sh bash NA12878-trio-wgs-validate-getdata.sh cd ../work bcbio_nextgen.py ../config/NA12878-trio-wgs-validate.yaml -n 16 ``` This is a large whole genome analysis and meant to test both pipeline scaling and validation across the entire genome. It can take multiple days to run depending on available cores. It requires 300GB for the input files, 1.3TB for the work directory, and 48GB of memory (with 16 cores). Smaller examples below exercise the pipeline with less disk and computational requirements. ## Workflow5: Whole genome (10x) An input configuration for running whole gnome variant calling with bwa and GATK, using Illumina's [Platinum genomes project](https://www.illumina.com/platinumgenomes.html) [NA12878-illumina.yaml](https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-illumina.yaml). See this [blog post on whole genome scaling](https://bcb.io/2013/05/22/scaling-variant-detection-pipelines-for-whole-genome-sequencing-analysis/) for expected run times and more information about the pipeline. To run the analysis: * Create an input directory structure like: ```shell ├── config │   └── NA12878-illumina.yaml ├── input └── work ``` * Retrieve inputs and comparison calls: ```shell cd input wget ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR091/ERR091571/ERR091571_1.fastq.gz wget ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR091/ERR091571/ERR091571_2.fastq.gz ``` * Retrieve configuration input file: ```shell cd config wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-illumina.yaml ``` * Run analysis on 16 core machine: ```shell cd work bcbio_nextgen.py ../config/NA12878-illumina.yaml -n 16 ``` * Examine summary of concordance and discordance to comparison calls from the `grading-summary.csv` file in the work directory. ## Parameters * `variantcaller` Variant calling algorithm. Can be a list of multiple options or false to skip [false, freebayes, gatk-haplotype, haplotyper, platypus, mutect, mutect2, scalpel, tnhaplotyper, tnscope, vardict, varscan, samtools, gatk] * Paired (typically somatic, tumor-normal) variant calling is currently supported by vardict, freebayes, mutect2, mutect (see disclaimer below), scalpel (indels only), tnhaplotyper (Sentieon), tnscope (Sentieon) and varscan. See somatic variant calling documentation for details on pairing tumor and normal samples. * You can generate both somatic and germline calls for paired tumor-normal samples using different sets of callers. The pipeline documentation on calling `Somatic with germline variants` details how to do this. * mutect, a SNP-only caller, can be combined with indels from scalpel or sid. Mutect operates in both tumor-normal and tumor-only modes. In tumor-only mode the indels from scalpel will reflect all indels in the sample, as there is currently no way of separating the germline from somatic indels in tumor-only mode. * `indelcaller` For the MuTect SNP only variant caller it is possible to add calls from an indelcaller such as scalpel, pindel and somatic indel detector (for Appistry MuTect users only). Currently an experimental option that adds these indel calls to MuTect's SNP-only output. Only one caller supported. Omit to ignore. [scalpel, pindel, sid, false] * `jointcaller` Joint calling algorithm, combining variants called with the specified `variantcaller`. Can be a list of multiple options but needs to match with appropriate `variantcaller`. Joint calling is only needed for larger input sample sizes (>100 samples), otherwise use standard pooled `population calling`: * `gatk-haplotype-joint` [GATK incremental joint discovery](https://gatkforums.broadinstitute.org/gatk/discussion/3896/the-gatk-reference-model-pipeline-for-incremental-joint-discovery-in-full-detail) with HaplotypeCaller. Takes individual gVCFs called by `gatk-haploype` and perform combined genotyping. * `freebayes-joint` Combine freebayes calls using [bcbio.variation.recall](https://github.com/chapmanb/bcbio.variation.recall) with recalling at all positions found in each individual sample. Requires `freebayes` variant calling. * `platypus-joint` Combine platypus calls using bcbio.variation.recall with squaring off at all positions found in each individual sample. Requires `platypus` variant calling. * `samtools-joint` Combine samtools calls using bcbio.variation.recall with squaring off at all positions found in each individual sample. Requires `samtools` variant calling. * `joint_group_size` Specify the maximum number of gVCF samples to feed into joint calling. Currently applies to GATK HaplotypeCaller joint calling and defaults to the GATK recommendation of 200. Larger numbers of samples will first get combined prior to genotyping. * `ploidy` Ploidy of called reads. Defaults to 2 (diploid). You can also tweak specialty ploidy like mitochondrial calling by setting ploidy as a dictionary. The defaults are: ```yaml ploidy: default: 2 mitochondrial: 1 female: 2 male: 1 ``` * `background` Provide pre-calculated files to use as backgrounds for different processes. Organized as a dictionary with individual keys for different components of the pipeline. You can enter as many or few as needed: * `variant` A VCF file with variants to use as a background reference during variant calling. For tumor/normal paired calling use this to supply a panel of normal individuals. * `cnv_reference` Background reference file for copy number calling. This can be either a single file for one CNV method or a dictionary for multiple methods. Supports [CNVkit cnn inputs](https://cnvkit.readthedocs.io/en/stable/fileformats.html#copy-number-reference-profile-cnn), [GATK4 HDF5 panel of normals](https://software.broadinstitute.org/gatk/documentation/article?id=11682) and [seq2c](https://github.com/AstraZeneca-NGS/Seq2C) combined mapping plus coverage files: ```yaml background: cnv_reference: cnvkit: /path/to/background.cnn gatk-cnv: /path/to/background_pon.hdf5 seq2c: /path/to/background.tsv ``` ### Variant annotation * `effects` Method used to calculate expected variant effects; defaults to [snpEff](http://snpeff.sourceforge.net/). [Ensembl variant effect predictor (VEP)](https://www.ensembl.org/info/docs/tools/vep/index.html) is also available when downloaded using `Customizing data installation`. [snpeff, vep, false] * `effects_transcripts` Define the transcripts to use for effect prediction annotation. Options `all`: Standard Ensembl transcript list (the default); `canonical`: Report single canonical transcripts (`-canon` in snpEff, `-pick` in VEP); `canonical_cancer` Canonical transcripts with hand curated changes for more common cancer transcripts (effects snpEff only). * `vcfanno` Configuration files for [vcfanno](https://github.com/brentp/vcfanno), allowing the application of additional annotations to variant calls. By default, bcbio will try and apply: * `gemini` -- External population level annotations from [GEMINI](https://gemini.readthedocs.io). This is only run for human samples with gemini data installed. * `somatic` -- Somatic annotations from COSMIC, ClinVar and friends. COSMIC need a custom installation within bcbio. Only added for tumor or tumor/normal somatic calling. * `rnaedit` -- RNA editing sites for RNA-seq variant calling runs. bcbio installs pre-prepared configuration files in `genomes/build/config/vcfanno` or you can specify the full path to a `/path/your/anns.conf` and optionally an equivalently named `/path/your/anns.lua` file. This value can be a list for multiple inputs. ## Output See description in somatic_variants. ## Validation ```eval_rst +----------+-------------------+-----+-----+------------+------+---+---+-----+-----+-------+------------+ |date |data |type |bcbio|caller |TP |FP |FN |FDR |FNR |Target |Total called| +==========+===================+=====+=====+============+======+===+===+=====+=====+=======+============+ |2020-05-14|Garvan_NA12878(WES)|SNP |1.2.3|gatk,4.1.6.0|36,710|285|323|0.77%|0.87%|37,033 |36,995 | +----------+-------------------+-----+-----+------------+------+---+---+-----+-----+-------+------------+ |2020-05-14|Garvan_NA12878(WES)|INDEL|1.2.3|gatk,4.1.6.0|3,588 |981|611|21% |15% |4,199 |4,569 | +----------+-------------------+-----+-----+------------+------+---+---+-----+-----+-------+------------+ ``` bcbio pre-installs standard truth sets for performing validation, and also allows use of custom local files for assessing reliability of your runs: * `validate` A VCF file of expected variant calls to perform validation and grading of small variants (SNPs and indels) from the pipeline. This provides a mechanism to ensure consistency of calls against a known set of variants, supporting comparisons to genotyping array data or reference materials. * `validate_regions` A BED file of regions to evaluate small variant calls in. This defines specific regions covered by the `validate` VCF file. * `svvalidate` -- Dictionary of call types and pointer to BED file of known regions. For example: `DEL: known_deletions.bed` does deletion based validation of outputs against the BED file. Each option can be either the path to a local file, or a partial path to a file in the pre-installed truth sets. For instance, to validate an NA12878 run against the [Genome in a Bottle](https://github.com/genome-in-a-bottle) truth set: ```yaml validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed svvalidate: DEL: giab-NA12878/truth_DEL.bed ``` follow the same naming schemes for small variants, regions and different structural variant types. bcbio has the following validation materials for germline validations: * `giab-NA12878` -- [Genome in a Bottle](https://github.com/genome-in-a-bottle) for NA12878, a Caucasian sample. Truth sets: small_variants, regions, DEL; Builds: GRCh37, hg19, hg38 * `giab-NA24385` -- [Genome in a Bottle](https://github.com/genome-in-a-bottle) for NA24385, an Ashkenazic Jewish sample. Truth sets: small_variants, regions; Builds: GRCh37, hg19, hg38 * `giab-NA24631` -- [Genome in a Bottle](https://github.com/genome-in-a-bottle) for NA24631, a Chinese sample. Truth sets: small_variants, regions; Builds: GRCh37, hg19, hg38 * `giab-NA12878-crossmap` -- [Genome in a Bottle](https://github.com/genome-in-a-bottle) for NA12878 converted to hg38 with CrossMap. Truth sets: small_variants, regions, DEL; Builds: hg38 * `giab-NA12878-remap` -- [Genome in a Bottle](https://github.com/genome-in-a-bottle) for NA12878 converted to hg38 with Remap. Truth sets: small_variants, regions, DEL; Builds: hg38 * `platinum-genome-NA12878` -- [Illumina Platinum Genome](https://www.illumina.com/platinumgenomes/) for NA12878. Truth sets: small_variants, regions; Builds: hg19, hg38 For more information on the hg38 truth set preparation see the work on [validation on build 38 and conversion of human build 37 truth sets to build 38](https://bcb.io/2015/09/17/hg38-validation/). The [installation recipes](https://github.com/chapmanb/cloudbiolinux/tree/master/ggd-recipes) contain provenance details about the origins of the installed files. ## References - [NIST genome in a bottle](https://www.nist.gov/programs-projects/genome-bottle) - [GIAB data index](https://github.com/genome-in-a-bottle/giab_data_indexes) - [Illumina Platinum Genomes](https://www.illumina.com/platinumgenomes.html) - An introduction to the [variant evaluation framework](https://bcb.io/2013/05/06/framework-for-evaluating-variant-detection-methods-comparison-of-aligners-and-callers/). This includes a comparison of the [bwa mem](http://bio-bwa.sourceforge.net/) and [novoalign](http://www.novocraft.com) aligners. We also compared the [FreeBayes](https://github.com/ekg/freebayes), [GATK HaplotypeCaller](https://software.broadinstitute.org/gatk/gatkdocs/org_broadinstitute_gatk_tools_walkers_haplotypecaller_HaplotypeCaller.php) and [GATK UnifiedGenotyper](https://software.broadinstitute.org/gatk/gatkdocs/org_broadinstitute_gatk_tools_walkers_genotyper_UnifiedGenotyper.php) variant callers. - An in-depth evaluation of [FreeBayes and BAM post-alignment processing](https://bcb.io/2013/10/21/updated-comparison-of-variant-detection-methods-ensemble-freebayes-and-minimal-bam-preparation-pipelines/). We found that FreeBayes quality was equal to GATK HaplotypeCaller. Additionally, a lightweight post-alignment preparation method using only de-duplication was equivalent to GATK's recommended Base Quality Score Recalibration (BQSR) and realignment around indels, when using good quality input datasets and callers that do local realignment. - Additional work to [improve variant filtering](https://bcb.io/2014/05/12/wgs-trio-variant-evaluation/), providing methods to remove low complexity regions (LCRs) that can bias indel results. We also tuned [GATK's Variant Quality Score Recalibrator](https://software.broadinstitute.org/gatk/gatkdocs/org_broadinstitute_gatk_tools_walkers_variantrecalibration_VariantRecalibrator.php) (VQSR) and compared it with cutoff-based soft filtering. VQSR requires a large number of variants and we use it in bcbio with GATK HaplotypeCaller when your `algorithm parameters` contain high depth samples (`coverage_depth` is not low) and you are calling on the whole genome (`coverage_interval` is genome) or have more than 50 regional or exome samples called concurrently. - An [evaluation of joint calling](https://bcb.io/2014/10/07/joint-calling/) with GATK HaplotypeCaller, FreeBayes, Platypus and samtools. This validates the joint calling implementation, allowing scaling of large population germline experiments. It also demonstrates improved performance of new callers: samtools 1.0 and Platypus. - Support for [build 38 of the human genome](https://bcb.io/2015/09/17/hg38-validation/), improving precision of detection thanks to the improved genome representation. - bcbio automates post-variant calling annotation to make the outputs easier to feed directly into your biological analysis. We annotate variant effects using [snpEff](http://snpeff.sourceforge.net/) or [Variant Effect Predictor](https://www.ensembl.org/info/docs/tools/vep/index.html) (VEP), and prepare a [GEMINI database](https://gemini.readthedocs.io/en/latest/) that associates variants with multiple external annotations in a SQL-based query interface. GEMINI databases have the most associated external information for human samples (GRCh37/hg19 and hg38) but are available for any organism with the database populated using the VCF INFO column and predicted effects. bcbio-nextgen-1.2.9/docs/contents/hla_typing.md000066400000000000000000000012111415626112400215110ustar00rootroot00000000000000# HLA typing `hlacaller` -- Perform identification of highly polymorphic HLAs with human build 38 (hg38). The recommended option is `optitype`, using the [OptiType](https://github.com/FRED-2/OptiType) caller. Also supports using the [bwa HLA typing implementation](https://github.com/lh3/bwa/blob/master/README-alt.md#hla-typing) with `bwakit` For typing either with optitype or with bwakit, `aligner` must be set to `bwa`. `aligner: false` + `hlacaller: optitype` in the template yaml gives a warning whan attempting to create a project yaml, and errors out when running bcbio, [issue 3252](https://github.com/bcbio/bcbio-nextgen/issues/3252). bcbio-nextgen-1.2.9/docs/contents/images/000077500000000000000000000000001415626112400203035ustar00rootroot00000000000000bcbio-nextgen-1.2.9/docs/contents/images/banner.png000066400000000000000000000462241415626112400222660ustar00rootroot00000000000000PNG  IHDRoFsRGB@IDATx|EǟTB{*tTT*REv$`Q RDB'$@H3۽ۻ۽ۻ{Sy;yvg@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@CoЍ@%*ɖjD2,;?1$Gby.$_2yD),Km/Rq>@#C;Mxn穕(ڐ,a%1dYoyjZ8`  '`q0"mJ)Bw{$Ie͠,^E6ut zA֏%$@$s/TW5ZU}\loi?E@`-]6D?Fd-ITUu3" ;lf]:lPbv'R|7?-;g7ct\9h   (0 ;?*NQ/g:w5t_aM'SZꇴ35MvޞCJS<vR^mS4;TH0 m#BDHpEM_+<0w2*00Z??ǁ;&aor6Cw i=J+3I   .1 zQ/H1tؽKY4ߌ !C;x28F5 "8QpuEh^&C;7=DS|4P^+ngQ))e,-q58FQ@xs|wRBBA3f7֬4o6}@@@ /Ab&&m FsdglI0F9h9::DNc7 b<v'CtIY&C;}G"c'䀁K>.r8}+9rM}٢z j^8eY,+l}__NϤбWjM=^NhnVʁ@0C>uD}!҄8jڍCg.ӎc "JP&3`2   d 2yo8U쑁4pvLT>})zs9y+9F4q4?m   `kmUȼIPldWd^)?2x%Lj<'ͨvTt7}@&egw0+5=Eݕ[,,'<ԜssDb@@@t%`οBH,X^EyQԨR]z Pⱺ2B}xHn`hncb7bG5猈 @@@@HI{d3˨뢱TP4͆iVݺniUY~ҹ|JQɸ(ݷRlWD|3e9yh 4^@@ @9#a,0ZB#hb&hdHt%-~ݣKQ6%&wTpLbYehg+GtvA@@<#=VJMFJEz=Ҵ"aze-dkNmuWUJR1rVsR1_d^N*6HA2gA@@'C}fhD[BH(WP-q}]T4V9Huh泭)4QwY8X^]GnQ\̥S$  Sߠx%԰ieotv!IϾʭVYۈ8qSΚ~C[GNz\򜒘[$fy "H ͆!a584-h*r=-oJ\3*V@y[MX oS+^xv_p2JV,~)(6PKrz$J9%1H   nfH-b#dzAP,˷;uV^eeNuϷ:bd E8W吏*[C}y    ēkкM@$nDH_ jIU9=MZU_M~z°zGG7Pi"oUpIEӌe !mHs65ռM; B%WH`n% tQl!95/dޢ4zVS)4馪9F2Ffl|aԧUUvЮ&T]NI)qs&UQ|(JLJ]x/6u~TSqre֐*Q}L޸gsͣO? SQ0&U3;Fͫp*ūe }mu<8z:^C)bCbeڥxa>rNy'm=zE[{qy*QFr|zskm2q&=%w}\t8}+um@nF*[05Rq؁<票V9ڹd" @@e$O!`"eJ1[mܨ]dTw|mcE[R(ѥ˪Y6Zzm/7@~zzeٿ*I;uM=nq8oQ֛3pk.@@@`E 2i2ᴎbWh+t-êTl;~*-ulXέp[ط*U,CuJpi{[}u{jД5g9u^*FЅbgb=-⼪PO  H%`11Bh,*쾏QE5VJ -vsCR'NT3G(<2I90QX=&}||D|7MsvZ'ikrʖ <ٷ}VjI?[@ $C;'Ր!JJmc;!s!&?,GuOSKof8KFCͪ9Nϴݧh?|c"uN(&Exu˰d.>~7~^!(^&D4%o|k6z}⼺gۘ,qpemc$N&e0tpB@@Q!-"MhE%-6&8(G&RNՙaꗰgI l2:4xJI;gBgbU[o L@-{ѫsԙFSa ϟLdO9z%h%mj"H S3{'4IL6;]Mˤ~||+#;\uNCx63 F#n }W3KLͤ_W(F m`Nc#qxH~(%Ol $|zMZE. 꽚VO+jiQo6Q+G>E@7]6&@g6bPDYz_o/]#a$ qDoPho8DizW#Փ./gu@mRQEvBhW\VF'0rwJ^0(d軽WFahupjU^g'd玽[?JKA_&E{FPDxM5ǧNVlKW3r&U 6ӹ4b]3"fz,Բ-{5Ӵ% 1u4!vʭݶғ<g4X ৕@ʖl̼ʦfހ&$(_Ͻ$q9RRTjLypZqX_x)o fٍlB.|JOBNjU @!`I;^-YֲnGe0 m*Vx&OJߏmi 1p-}~j5K{jRr^VM|}CۈzIanܣ٣vh B||^3Fkwqo )%jW|!VUIbռ]ݮ|7&>M?3o Aj* &!`UHy;Q"C(,׾ ϭӧO5e )!~jbYgND1ƸKS$}@gF<;H  7Ziw.EQdYnђ*z1VU__:V⠛wVT 36kF؟~v y U;M".QCT@`0 -G{NU|+vUۭZ =NWM@z  `J/%l0֙rRtzk8,lCW6]okwLt9 8i3/FGl0aPo>15]̳nxAYzGEҸCV+,Ҧh)"9:;uVIA.2@@)F4'>7oi6P+JꞐYLE8 gZJ'jɧ-ڌ4r+?96+iT(mڼz jV8ǹ3I!iE3mY0P^a,G{؃Ѭ!m(*BbΌG/[TTQ(X񅢨hL$g /ePJj&>yϱ$_^7Mx"{5棗(!@@@[B 0ZTv:pchl$=ޢ =զ*,]PjvWeێWk/OPNWB4V4m RCݡaYZC2@@@|KoyބۈiviސWjq0 ʐX]w7TDqwЧLv;eYe͟h=_X"do -pL5Z\q^M˴ OXx^{>d4H%C>PjѨ6Ӝ?!bzտtW[ōXnPuC2@ ȲާZ#kWNv&kF9eG ?"EF->LU$s^"GM-w'm;rwH6ۊVZHMELreyzhM*GξeY(>d$9دCŽPXĿRLO W ;9( ?G}K= aqCfJ7-3''t-H|>Uw;PkӠ(/LEQ 5e)pR~2jQMnZ>yF9rQO?ON=F֋0y\4,/GXoBUyg] yu>*U~iy`VzdF5~ݘryˎ&²VYUhj; $C{ԹQy=s!bPd_-!~߬ϛ )&S;n{vo<~֏`_έG:PdNf?kt~}/`hs6=2ؘҩ_q%јN[<4/CS3.Yu?Y{23ft Cq^3FyAgٶcNgJ4cp+ v۸,}z/c͏⠻x[BԲF zUUjXCn=GV)`~nr9{ڼ#8ޜt CLqSw s Y' @ԯPXUS3qh^5}m1M_W'8v>"^^Hwzg*Q 6J.NqiC4v5zbӧ%r@@#l|5KI5)0z~+#>$h5ZN̓n֗FPɖ9[T8Qp0 Gw:ϛC3?Cz89/^.|Mwbc{ r W$6_NyZSWq-M" 99߰S1&=ZZ7"Vy0l,ó:H0L婉STAQ_03fh_Fz >SK?+h#jU4ٍY0-P;+/NFJ­J p9 /4eJ)obbiS W6wyZ1Flz]|DapuJ즡%S+6¿il^T,M6R$ D^Tq E@$غJS[1⠏14F]=}s CK_\AWrK-E^n|eGSRoOյo4j17܌BeϋY˻+͑Bz͹_A7$c[<{2y[P/T/!G z 8A+0k{[)ZU^mt|OM ~m9j >񅢩MWHlD$=L>dHOFH[Z($˺9+؊ќwY/ZvL9viv\ߖYOھK鎃0a6,C車E&/F䪩k77?铽 #ەl{z~VCN{9x¢&CۜpZv?XkjZ88^](O"&ن7 26zmU "?XD?p:E%ᣭ)FCqIY=+Ն+[VJ/jmcߑZzR֏}NQWzbYAyOͽ(2"x,u$~О$&D! DM~zAm3m`]6v~zpжsKgc`*-rLucdF}C?G+ zq oԽg8ݵo1w8ɡ4rњJ!Gly;-?[\'}No~Ey3i%׷֡NJxV{UTh/_ ho(d m?@.O\Jy_W8EvX*|3Nx\+(e'VR:)Tdx9 >!Ʃu ~WStN*xZc>G͙}}V=G~`R %JIYj\6mu52Տ6ǕB 9VdXʮUƭ}Yr-pnh-]NjGZ6λ8 p5x}流\չQv~;=:Eݍ^M5Gr&z{%fFFG^J.#q֋t}@0}9v71D|Cfӄ;4wn@vexe? PluɱRR7EԑO-aE[ u'" mӟ-"zg<ґHn׫A!#]ڢ}CiĥԁRs^.JZ؃v%CۿD"܈o6QӫkN\kaT졳MתGvZv.*"Ʒ:C=tGlah; Aa}rK9m2mu/lfZ~Zʗ2^Zu=΃k=GYG*TJD!EfM&r% MS3Uor0}˨e9醅ut"Ǟqp ԽIEb16jJ H-ͥy[LE~V+cZGm0FQQq6=N~s\w72zL.pWj-^{4eK A%ƱM% FѫwgdxC'j J'DǮxyWEx;*UL<8k2nt m))~I{/SWȔ,i^Vh5&zC^ e9F+CRq8p.Ur!-Cۨ -0kɧ$.ڍ_5<3"L1t[B'ЇP^VLg8.[*827.J9&Jfţe@9a99y )BCϮo zŅb{E_}* @Jj"urw*YQZlm:f *F~z8׻$~!X3vGuvK<$-1A T]kV^iAT<$4BOt1/RWj%Tfpui'iIYa '3$V^ ){d^;C2x~xĦM$>G!x HIjQ/RQ?,PZ CѧA' at5+RΎoS$s+6nZjϪi-¸}e?8l @sV{-BZFs!nĚb^ C;/̲IǸtfoyB=nuVU}nh?ּxEȿ]'uUlYswCa\O׼rɋ5UY 9 H:EVɶ,F m_F?DR ¤,7jP`h|U=qR{;+B{bd)G|OMjXѹ'}n#bgS*w4vv 8})." \ީDH3Vp>**$C;' \@evGwi\^h'mU)W;N(Y,M߂ۭ gffH8LepKAwgg-* ]YO6C",9Њ0tUm᫼TtACڜ6R)|uVڔT+_kGaJbTGċ'/nF\t8My|g#@" e&g̙ei\5u=U!ZNlY.hkFeYf%t1qcX;SO;ΪU죬 uKӬ!m(<Ը|;ӅiVѱW<Ҩz MG/ҕ47V˜ΊCE!@#kW9אdzTESJYl9֓zλz΃QiZMmk" ywCH׌˕zk+Qpj! LK%<0^dlWFvF5bWM?j.$Nri뻝uư;s"+zمc"G+/AZ#ڍݐGH"e21tg(8qYMkYrA#uٿ?BHsR)_~>bb~5'Sy^Iq `4.]ED!:cMS*O\(! +B"+w2?x+<MGE^$зkUWe|uW-2mzڲlGk钤,h_%σ;p\Gҩ_jjגg7:.'6Bp4I櫤f>=Qа,hcFR [PMeGE3#]W)٫"T`wvegY^PIiIb*5  NM,?nk?ot:73ԥ9pS[3|sgy0݅hB&jݝ:5 쐉 C; )|e " pk젻ZFU]Ee]6V?t&EZ,ۿ|Yƶ*$@ Y"raeX]NT e_jU_Im|<[o=3Mk}zK()يeJ>j?E4=ڦS025._ˤ{ pWU+O 5Ge9T8;m!h/j5Rk]Ԛ"~O4{yr\C?wJBvxKLwkR2IwC]sm mV{Ju)vg >.HN]?\IqH΢-G}<"O/GͫC>0fL+~^2Is]4XTlٖWim6n-ٝh6+UJ>۷fo8QM}-8}ՒuQB AlSK>=Lw8yp,5Z0&թUt)fB,WOE{b\!^6c/ RL9EK3-ԻY'ŧ.Z9HܜU4-ln tfU\ä%@g}Sy*RcJTҲC/9i/P9g2 #lO7, c7$E- c5~5V '}w)*RQH#^)Ac=n5%#WB[ecj݂1!`hx w/->P--ގ6~y^m&,x՘MخΧ[ ?;zɃГ@{( ƶ%>u%*jD`؀ߖ562LRQi{'"Pd2RL6!P1YA|?ھe3TQ@$\FgTVfNݒxfijzgcvIn\4/ B==H:"9/{ux Mկ>>7tEP q5F- .!gt&Z2V_ sUh=&r}+b`0cY)aXo?급u͒h#'dL8H!/ulbU]M*J.5);@!R*, m;rq׃ru -RK*PpZ4e'W~FoW3K嬔d(KRD^[lzzT2u|#z6T_μRl1ϖRȭVR۩k#ĄahpRLR$|N".[R}>qQl9xao"m{25_ ֖G(E|KW3P2\6fA@@ A|DuZ`gdl/`c;.:BwЋ&m+R)ZE<7x @@\fH|0dx=9fOlǚ]tɐ該!;Mb1b ]l6P'C;\iAЇ+U9g^7|!ͳlctpRQw灖?7_+ҁ܏T)mWUI5׫1j^,dUmqJPI<n CYp mxgO}5Fy Ν DS7).7۽YglzA08if8ZiP25P3/]MSR:GC99J=|tknRY`)6*j+P%_z`h{-6:{ V,_-n]  Z~eMЄ*GNYΧ,C[ ^ $[(Cb:qg9    } ܸ$i!vd4e]+T)KB)m9tN)[1Շ)٢xGbbc|k}z'_ɝ69Mm~QGA@@ Gۑ rX0H,߾ꬊ/UTQ BIDATrHp=y^˫4osjVf9gT\RN,7_πozC/   `hM9'ʦ_OQLtj?w{6<gS};${EE28ļ716M ȹ+.՚T~W/Axx-%eCh߶yckԓ @@@@ښ0s>/V n# жb{o2yvMϦ)HT=  #͐曓hNyrO$ҵ$\gPjjKN'F9*HY>Lh@",bSs܈Y\a٬}AU@G[ ?틬|B{4 Eu]<.JLd~j(@mx:otkHs7O%9]GTilv. C@@\G~ ldZlGצz#chʫТWh0֒3ƼmUEl|!jQGD%)E mMgW {5Lׅ6ݙ=Re*+}z/T9_ڊDWKYs) @@@c0=Fڶ:gL[VԂNyL_m)cGݪfd:| +]?touRmgcss$ @@@44B%p@xsw[7"QOv,YP}s+H2z(}CTL!nl=JWӳIbTXbܙDGhwTv@@6$0IoYT^٦jF"\?0 ui6|m,\ ^aܻed]Iˤި)W)4_| -{IJ6pM>ڮ7Z >ވmJE9u5vxI0n9f e$>v?;g?!;.xQ}Egoc    `h+@A'># Rڸ<)WB_ObYtG墴͎ct*V|-ryJvZBeo||> @@2VA^&OaY> ^_%~lt- ='/'kUe9&W  M ( ]̞+CqАk.Hk +ЁO3O'a43͢`%C;Xg:>a/fV3tedNlx@@@p2ٮwZC^]$H `gad6'MNՕĿpՏ@i }O|+'L~Is@@@@0"pBSȽnNjUͥ6xׯWM~ArA@@ @->nSJE>e >Ǝ.N $ mG߾' BFP:QMw5ǹNSA@@`h83S(JBzWglǰ1lp#Fe.ooR(QmK~Z2 z?@ *cIENDB`bcbio-nextgen-1.2.9/docs/contents/images/docker-parallel.png000066400000000000000000001513361415626112400240630ustar00rootroot00000000000000PNG  IHDR&sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATxwxUǿg6B5&M)`_Q`+((7C ɖ9?fwlB̓:w̜{3C WD4FU.A;`%31 ^JAowk  b=3y+!\,D4 6"ﮏ@Qt+!@ @ @Ё[ @ @ @ 5+7áf \. "rg.0f.nn@ !jHDfT 0(4( 88lC>È ""KD~P%B-&LBh&x?3|1k ̼5u:};_#9)!"w?3BIo!E&^0;BmN l l DEq WYD>.B h/bKRFd"ZͤM]2/ M_ѳ\DVV[vB ̜E89he5|Nטy3jڶI^Pl8^6\a0006P& VAIf^vt(o8 epw]#!p 9@gsBbJ7-b`eO/u}%V3MMR_433s奮Ӆ@D|{UH ƏRM" p{$̬e+Ҕ]\&*(9FQ3_:" !w4UQ9!/hȥ@Z~8" s/<"  ʈ(KD-%"zVQIm4,lM7N"* <"BD}IDb"ZEDۈ(k""~-m%|ñP';"zQU un]˚r >D:*CdF:wÀr04ћh%eQ!eD4<>sQBDljU"iE]hD4*N"%DKɛfqn5{Vv3EDD%8IDP1D=54"lHgߚ53 kCYs"( @p6!qCW`cy,10UD9(&(qg{7f l;И.=7@1qQAӾcU}VBQe(6au*o/ fhЫ:b` (BCYQ+~C|z3Kݗ uks 2.m361s#effH࿆p'=Yf(.}d. q~13ʻ:ۡ<öxu7?4\GfBy[3K[ mڬĤ$Qz } P5ʼnpy"Rܺm`̫XY,slbYP>ցP fa.^0` <>[=[M"LY `?p fo 52! ]+Ϻc~?`1VpUzOfy9;HC\Ry `UثFM23g33C^yVAoByqnbYjUCx0 2w| " 6)(gsƴ"A@ h ff̜ۆ=TC&aU aȯf;ߒ[3㤵6X{&w 3?Uxt3mB1* 9Oko5lˬND4mPZ6_8l@s3 "9ul42@}|:3be">`)ƼYYއf1Ca 80Q/X2MX]dv%r*TƁ߆@jYejۜ Z[ŒF2Π*]VBPh(#f>'sauVRASW}n P`!y4˺gm'mmk}bK6^ E"p0s_fK-lB`xi^F11\# 6@܃K[n"XKi6}^F;zSg"۬i}aA-EF㰜Y|S]ԥھ{zs>hQ}bP7oA@ h"/ʖE%X{Sv@keOQj@YPF݀[󍴎cG[?KD,X 6NmHOoFZ}l=_MU3ҋIwz& j(3DVy^lg%P|l u=P7 ~4P|:ff@`"eD4l8*Xr"qN1!O#ڮD+}}A ̼5F<#D&2VCk' X{ #"flU۬| oڬ2L ɘy?FaћDt7 Eș]7d>ODϗ]pDtu80{`phH"NDv]U5D!Z@ i+EIkh"1P 3pYUhj2j7qVᣉ(,_4e,Z " ץ|0);#Dv2h۠(..Ŏ;8! ?74s#:>62EYL7aص=XP'Ct:AP:GV@xPe񒚩KS8!CѦς"|ʣh3( N.Z(>ZywHoiiY,t6;W|lj;F0節Šؙ ŴźPvI4{_(SE3)(46gAyy3EV`1u8(^:]>G@p@D<>H ZPXf0 K n2B`h㸍 .G/.P6JdžMp31;`03aqH(~sbffCٔ&wlv@<+kh Pڀd0s\J&p n @ @Ё؍=nĥ@"כFZ ;?hGW @ \,ؘe[ ;usל/҂Ylm.s8 [ l8p+!\ <ۊxEJ#WhR @ @-@ t 2)5˿IkIWۀ nNc餯m<sϷoϟRAS}?/;W@ Un"MtE}f 455vH-ù=cXSZCը[so^-@ ˆ DpCܝ;"^.ӓo֜eܨ $T @p6vNm>;Og@mIC* џ%KN7 n?,J7^"G .|R]Mu4jY;,š+hiyd3P_{Ggtݿ^&iObFN.4vǨz[+tڪzhkG \Vaշo6$"{Sܥ`ߺ[xWWQ:w=k%od_8T䓽Fkci[eNaeǪoY 6Q98:#s7艞ưX_E<$yvhYE_(50g&ױwʋ1r9<)XE5j/RWMcn@ zF^R҉ы{KYiD߿ziw:8:ci|b6dvGvU߾!4o;C*ÖϟIaW_HsӐt"_P5cNQC'\S{sukz[<"? dQNjdgȊGN:v5yvXm$?K?+Us'w7RVpZSR#&-p38s5yxTO@BՃ=}/L[([_׈qTT@9 <7ېZTM\b 8`n"&gQ כU JIW]m{UuR]J!*)ԇz{xM.uM. ]8{{D7V甡xK,5Vc'/t@v 򲝉̨)AѦS.#_7_ӇJw&-6}B)[iI$7hMaN}mYWFѦST^L;!< נx)=[Hvn𿦯5# "Fb8^rprAC#1['OK=?x+k:wٹ}4Χ?B/n;rmUtrߟ$^h7oHw?w%}GN|ybyܩs7t܍ KH}<ܑ$TwkRI ~Nl 3~oo^Gb'Cd?^*p;8ow;rԑ\[6)r~CvДע>DB#SeRYvg)Ւ{t v u)cVszڳT1Ҕ:?0}*VYE%ZAuTd| ZҔ*;=&o.=A]v2.Lǁ⍧(u2Av*8sA1{YG|U߄(:Iϯ =׻7*Gh_u&ѷ3KvHyo%:=V~_? mCWy,6$Y @|~a:ZYjⰇsѦST/X/9a~r+Iv.,%YeJI25?S]݂*y!kx/+~MW٩HE]W?Raɶ>|f,w^msyxW<nsz%8*]U=V>skcFSK"\c"'Z6ɣ/gO'ũj \Xr: G蝣N7ac Gg}j+GiD˩ٔ6=^)C"x`}V*G3aZ>;(=; e/#uyb䅨S^*\{3JlW"pFcq5.Qg =]~u{q5,μOL]"M^r< ۹9w\o^e-%ij~Q;45}H-y$߷<ǙNfR;I܂ {4Z4-wPƙTYV$l3C'rDܜ0XZ{Mo' fsWQRnZ< j襼ˑx/B}mQ.-ȢcRPxO:qu?PMe)|;٬_0Dl%d9Nɧ$/5t`*'/#rRP_[g7|;B Gw0`4=xJzNLi GџNi7O8*K P_SC5\MeE4qòO*Jp`r"0zޏfq҉=SMe)NHi 7P_MUau] nY.U 87!WRctxJQ(UeE8c%f%;Gt=Liʣ +SbQ_[ZLI$rҐtԵUPc={p :Dgod脈y&SS7QmUk5dP_Kg͖]|ZU-劒<|M҉}҄X IDAT߾y'4qrvEei5Ж7=u>yUI^:]scw/xV?~ `fgEH[.ܲOwe͓ˋmr (Gmr8(\y733,zG$Nagdwo^g>NC[i~e='ܿt:-\M ߺ_I'4Hy<'R^z"ʌoI|4j|}/%Gu5Rڰiuعzҏw<$fSeI-*zǝڿ>&U]u9M YRg^kjܴxZeI7Bܼ~iIq.au5H1-+裹UzSn+GĿ.xQْޔߛ-Eiw=+>}dr]ܽu|iOHylU{=SaWЉxo/jjFuv=igI'I;V~M6/-I#f>hɞ)<ƇM ~$Co޳n1}:oTQgJWQbNAz1ڰiwLCq^rҔPg5%ccW<07䮽o_"-9g*-{ҖKzlȲO?~?Hk{[:uɲ'n?&E-ґhd뫱Ɵ?YGB e|:ou)`&A(B: .Ou؃d9ah}\3JYE_+fKcˮ83 rfڲ^nMyWl,\{:SI+H; Z}Ty$jr16^JRf j-Kyu 狷ƒ-t> r f(=,ҖY׫5Ͷ}m:ea߮VD&OgѮѪ>Mq#FsYƲM2!{$A۰)zo娡9 +f{xW$sK?~Z(Σ^JN'Fu2<}Ɣ۟oA1Ə#u3o);L{ | U'GR:5j({f7˿؜橘0+Ynzmy脙1ɷ=!\-ܿ {?d(M7>@gg&33xa7#&1 0g~S5M5ػ'zdNa5MY+L>욛ir-]ϓn(1[{Wry|*J'OK?I>!]zoߔuƬoʾ-N/䐮F_PIYV I߿zU1Vt@Sg>bіMѝiǪoh7ރDZo \PW]S67+y? 6_]=G/%D=x ۗ/K% F;gEGv"9v;~rpK_#vpDžЮ+W\Ƣ*s ק+#&tqH5Q17 E`o@2mE=bc'*cS3J 2&e.eRSR$]WnsUU3(9|w:6dtO*)FM%X\eiE9.l ,a2x{GdPf%lZ] d(p n` p¬??OohlGC}-lZFA=9K0d|fھ+tr'N|twqچ>BM ?Q}mpFA]H!Ɉn0EyՅ^ʮ;A,-897U4Ɵ?1`4vɛ~[W̧c[Ǻ W/| 1;: 2BνYq,BqrQw$6 3>{Fhh %VcͳSb| N.n ?OF:H-;8C1M0 7.eX4<}?Д۟6d}VSseSbiʯieӜ#;VQa:߹[{imO(ɐ~#+7T|Ů5J 0‹0"q҉|LN4tLV]pJ!*+́o-ww_D =צed4eGgW^-*;{(n=l"RbLqs(.4v]>6163\ߠ3ï6?TەH[tƢ*m-CWpmu=XђPPi)MQtu`d'=b>ֿm"34JD̙$mekCvE7HڲZ4V{%AAk/I)^2g\q$őc'"Bk5,^Y@r; `QEfFцR߯rV~)Նi^N.H^?WRx3nő%GOIw9T ܬa\,i\Pbg˅پi,T4]uv*li4h]-v~PPI5 ma-KwfqlJU[n/hVPevY wJ1y=ٵ@D1M)0A8{X$WNGHSRvË=`̴{3`e\]TiRcΌ~U6`tr\W EF%6xu-OCd{h+:n|U6;B=&3&B ;8w,GO]>\wqNH˯璝#w_ڿ{ߑ9몛,0,ӗU I~TZSc.5Sf:Mc ZMbNm++ij hwḎ̌h?QC'*:C嫘uvoqOܨmrl_Z\he1װHvUFFy4)eI3Ko:Z=&zV X3PLӗ,t2rȿE` 5԰3 *kJkp$ŋy+doI}YrC7g$I(X{*4.:Hը.X۲l]U=6l*p؎śOFo@ Yp&*KǨ)w 3BDrz=C^@daP$Fu-Ω_Rspo_"gú+k4skP|ÁhTa_5-NQQjKZ$ztz;j-c.50rl .d{hK ,+Diav0skgo }aIYSq阓gFiDq^:yx# +{UENmDɷ=Si_tb=ΜC/5yZ/& JjnrAV2ݹ!I3T*D|QZaCI~&(lLITP@DNMi G:Lijhb,5}9?!RI 6jNUt ( r#4:^5Z|*:I5yi+A1r'.}bc԰ k4vdCkYgZb\Fou w\oۙYG?3 42ɽW07HM3 PUYpݵnpW=l y8y71o|KuUGg~JL>mj';gw mJř^AR]jkה즁U_(=1r70^Z ];ua mDWsWG=/ ZjXI|TwMw/Lq8^0z3{"S\YO*K VC{{_uX&whWM<}7J>\~z~d7Vy鴶IYǭWspĮhҏ,̌~8 ZYLwCʲ^Y|Ko$\Kރ:c}4,V3y;y2&M(X;Wߴ.W.Ϟ>^QΕԵUszlw`f }*5EXia6>7SRfۧ=Ospľ?ZϱRC}-3O6dL]1XPN=OڿqY՛K" wTvvIw>5oI]kd雹-qMrhd(ox^ ,-p.Ы f!پR2>3;%\{7kE;89E9dIBuy14X Dl=W Nge;(5K O,]kR|sBQ?2፶$]OrύET+@%[ nʣiTq(̯wHn=:LTĤHi¹?X'CSZCHJasFsE*$^[u< ~Y]JHڊ:UQꈔt|pVoz(g*o9M TMΡ>푱`$7 7hQJ0?/7WP,*XuD*Z\*X{La8m <1I֫Hxg)oAInԢ!<wa=Jw'RS-%Z-xWQ;4%ՔtTq8:]l?1N&WFq.'ɣOg8* J<1)T#VJvSƂџ-۹:B_׈ϷHkJJ~jTJ!{oW!R޲ѽb$+-ˡo̒%Ǧ.inj X'l2/^W2%K*'{ B}pd<+j-<^nw+j mߎ0䭷Z}8*C-ů./ƎUH{-uՐ:}ݵ6-L,-]OgfJsڥ`ki $G'gjhÏʊsi? GȮRɽ|_҄Y9zDN,*M#m"50e&!]{X$E6.S)%mi{)ܨŎU%YGnZ5sy'0GN̤trF:eGGwџK?4 xod]g`h$]ܱN2tbz/n}EH^F"mc)?3j*˨BFsAV2muTLUeT_SIa3Agӑ+? t: 2NPQN*y$?dQyQ.5R#8Vڽf!USaN*13F i߆%T]QBŹdgon}#VڿgJ;DI'eK~5WR\6iqiMN=z뭷6~|[oT= E[[VЖIʬojJ_VK~&.{!k4o\*椐3bц%J3{A3^Ehhtdj)7-%T]|,bRJ!jPNo NBnVOs,-cJ){wTYZ@\$ n]b*I k)knfMc=l.RNӴgb:gΧ?bf[egF"J<]=yX4t,eI^ґ$VDx.!70A$!?#rR]@FO㢜TN6J))%.줬S4+o'fF^ ZlS)+$5ע({pEImY>_IZTQH(vvuG(;mNSN9MH#ZC{-+PLFzПUiи'H޹YssBT^AKnQ!5+۹7DSZK)$;7gٍw  ;gNIT}: ǞÛ׫5҄s[o^M5yДTKvn#%7]=vNm֮ 3KP{&3K1}WXGulE>}BYr: bK;B;Ok1@@x B4[qtj5=ta!7h)Y{cIyjs6)=<[rت3,u ->n|vڪzԞkv'ȪM6uc璵Y+t @Mbj-350xOJADø +mrU*;tgOSن.0 (}&)*LFpވfr֨Everprnd70c% 6fЯǐ<}/(UkpA*MO`gt5skWSj5t{ؙa#lx̤ɍ3{ RNj:-zoi^F"YUGd[;L6GyQ.RNS~rrq5h,jp~L/ºk>Y#-;}C`1Ո_33Bg3)'5Sxs5j({6sqe$(봚&`H( E)'5*QC'V[sl <4Ν Df[p)YX/c}48|* pvE&"'1s!"O]$2s_ne6-' uQ^n2n2Bn˖R5ʢV[6 Kd5ADD4VQ,6?z8 `LODSJx5h]d( H}[@ SXrC}f U̲q$۝h  N=j + @ 0p* 6<rb,|Fvg@ܝXSZCϒc,? .0sUu@q ]yg="Onl ݹ{yP6w'hWb 3?\b"ZND_Dt9?"h`g!_D,cDtj(#"{hIDND[p"AD( hͱӇQF"a?-$L"*%*C㉨QuID{,s"5Dyٞ4%L,KDhADߴ@ <wQT_ɦH! =ޛHnXQX^l(DTJk ${/9&Pt?ϳO3ޙ9sρC{vh"v@>3=ԏ^@7 م<Y:9h8crm<gifh0dS 5m>^Pf m=dPN82muyb󃶍c'"3`/6AD4qeh+!wjD:aT13f̘1s[c͘p&,3= `̥D $ 9V:x %D4u!d/jlF0ǖh={- +nC̼Ơpt! =zW| <\-kҗfADc!O1^ Z3 6coDf̘1clRb߇#jo4v_z ciEQnFK sKLg̍ ?+Kޟ.R;|/_\}r̿m%7yd"،!|3 }A6֗vo@DPADkHw-´S?ǂø3!.`gP_5\!oG'm;FL`BZ)/ǹ;ɲN쥯gO\w4kyKw-LuE;*J*ğOY)qW x@lim?.OyƉ(0c٤Č8C(/]cWgy<=d[%"C3 YLu`f59ZBEB ە5@23j,³i,M=9Y vD^jߨSQye?݌릢ΐnmY6c+ț$ZATctEt5`DD6jYgGf&#v$Mzlk=oD67"cJm=eK!k!oL`U\ӂKD ӵe)Q*-ѐB[zlڳ )DԅO5Ҏ[Sz,]=6z[4zbV78AmEH8w4uuh(T5,,`aie 1(?+>ԧE!Nz 1|fF#K5BucPFFr sH;e0'B;pQ^UW@Ba{G<I{$:f,`>>'-)񧨦ۨ˱ݗ\qALW@(vp\$rԇ=[7HSU^ '(/.~ԫ}PAC ~/k[{XY5/ROQz9X(кm77FQn uG/ և7 ' NPEi!B=@d^"EDZGC҅v.MO$ݧ ; T!*-́W@#9?+B;4ՕeH9L)pvAD}uJAEi!GFszyJ; jzv3OI~ץ86v8}X$-+|m`m aI%y_mȞ*ǐmt<| G ސ=}fùkD@m*Q9d̼vX Y Y\j #mvs$#! oA]_x " لppf$@63yDyG'W%&򍶾v wjAVj+ĥ3:UGyNU_)ZK.hԨ,+FX^̜gsG !PשHr`ԋgh;otizyZ6g(ˀJ siI_6I %ԪZtq?b}K gEBaoҢεhOLBpd4?JIimr,|k>x"O~(\Cm$?JXv/?#*J釪bThԘ>Au 1OfBxrpv,6w6Q;/7k ^\ @sRUfFڒ93nw;wiJAnfNO7#w+d1ރ;,Oi kbO36mq2A6#͝-GmY8C[prd)̺7l u""0=V3 /0U)zE~f{}_5D4kƥpn!+к\cm瀿HV|,v8lkq&zeRn?WXk*1 wb/[X-w{4B#Iya%GFsڥ۷ҊO/ءQX4ﵕG#xA6x[c_L( V~OeNSU_O1T3'_>'V|xe;G2_"x說gOB(? vF6.w?=*988f5?9w=YzkS;Y(,}Tqxgw_fR,eVZ`·ġ?Wѝ?hJWIm:GiwEo=jV6L^]{PT;,+S9i4ץNsey1L߽G]UnXFgJ==G6djb6QR} ycUPש7;5HOd"[xW"":E~l F?[6Jk[<|Igڞ##ʮuRwT# w (w;]?V}㞧cWOHRvp4~8k-UWa#_\=u8NK1T"4ߺ-^ˮI$ڰN ~#T|8jrJ`\?aE|mBصe)}Xas%Fχ![+jQE [+8w fʹc+>H 9gvbHXYkt;w 13r7ө.m'&,]f TC>IJ+9tRtk ;+epPk?GR6G/S*,m'}:dԞ)T+j2` ]ء^x jJ5 gvΧueNnU ZnU _ZfKjĖuZrf!CvM^m]Wv] :2PApD?G#Y N5*;ܜ 8t'=#ޒ{69Ik8F vػ~QZ"tW/L}sq'C~7+h fF^ew׃MeLFȲ<QmT5UWkh'w%YxEҪe΄llT(-̅ !XP0ޭ;6(ο8MO$UMu1UQVE3?>}~⛷yIO [g{j2]nz"̞lԖ:E07lퟭ3T5i-u Y+5o3(y( Ä9DS5Pr< OJ>Cty(مy \.reK$1A=6uwmn)bf,SWW]E3p_<~9BwD^w?I}7Km1iccVkp~JQz:\zNPS.?=Qþ/'|AJ<"AX#!_SrYL:UŤr| -l~KX8_Wg!s!Z=6H5"hf.A(:tr֟ȹInd)y/]I?c(]Y6cLsrchjתL&wre=VF (Jtz]6sM7KV.N!x5H`t bK+Uٲ_ f j 5UMWACCs V6v73-Q%C+7jkp\UT`f(,浰Tǿ _yh|MQBh{cJQSZͻe>u54j2QS]{'7LxO`2 !\?* eՈ{H_yPCcl½q$yg9FÁ;-&Y8% QWEyiwQ) w X7K8jg yhi7KZM y5uU8>v"wI Y)˳& yaX|h(mޝ žJ.#RU'4 %\zf)}9DO'K6ܕ 9x'?}$!m^J[W?+/R귻EFIw7!/@ +Eҗۄۀ+CRb?3L&/ql\[]٬14jKҖȮs}|MX^v:U e&ǑM}<|Ժ]7VZ7]״ch{y۰p,ԡ<6 3dCaEc@输ߍ!'MOQ;b n#.ԋw#TpyVa\eleag 3RK'[GrMv>M3'VPV@UXM [qyܕ׾m8~l|Sd:Lm޿[ MQ/~抰-_K)ַ ڢ*S`,ʒt6(=`i73f̘1D2tj&ypPZ">u%]$QĞߍX/X|۰O`sXlk.hmu%O6vld#ڵ!xOEiaѹJxZߗ_U4ϥ)>O Iseÿ/D9h,_'t1t}*/)[Ͷ7I21*/)$O?iͤ:%8~9gse|kuع*+Gc7t3J =^:C]3F,3WO?~B{Ұ'Eo˱4: i4 RB!(-ĩ}}F~Ш#\C:Ӓ377V#/T%mG A\Wf򼪰J k?e۴rCU 6Dbz3wp76 IDATkKhD(ʄo{Cs"jvmRRz8@X5:* rpiNac e̘1s((DqVEd%ǑoPItqH fOV|(EXެPX"awFAgOzZBdie'].55sĄߖV},+IEmT[]I"oB(wГl쐙GyqsIAmor:}` =^S_\ZTGߐY>k-}+k[L4d )i ҟ݌F "\8H<7 'o߾+z#'=i&y1'N?}*J ~M1b,)aύT>R␞x" ^£qq҅ž ӿ5rӑt#\>)CaR҅bٜ/7klމ=|/?ߒ~_zdGOtҙoK'VEDqMU9SyI:lhi8pV̪chzPULJC{5ϵXo~E ɽ9ɡWDAmV1AJϤ%ɴbJ(-/i@G+# OZ1d[Dẙ3f̘]ζN?<ѥhiiFA1\=#;~8R0xRA}xމc廉 0/WN"v4B{~t< M-Wg$pcJ 4[w 7OU%huO6w:j+K_k ܇8OJAuelѦs_~s>0'ZlF?J8?^aw0)l3sVK1˱ǩ(/w[<%Gv1꛵OɾÛ['7o>i&uKgR~v =/ MgHQ}GQT=1aےN41 HK~ܮ6 =&yiMUC_n߼ϑ("v_w͖JCTTHJ3 ;a:hԹ;c{L_^_$ڿQd&RXެ+_9'ŝG:7"0wu&-!]ڞw-e%Ǒaվrx>S7Qnz";臥[EF`gw}:h\xeM tGDrHЍ39ٿ6N}]Qy98Hmޝ 鼟5!"hȑ!C Ğ}7nmc\ 9r|1b;!Ga0zy ͩ0]|8 =О/G Glf~%1OPgORGveWO??)82"̘YÂYɿtg< 4ĹDҶ!hvaSqVajUA96Jxҧ+G),mQWoy OL^.\+3#;nn"9dp)"kQA6$y%d:m^(=p$®& m`$'(R]=tD/J Bi׾5 o?h;~҇+nTBSQ}̬",`,"| ff}.8z!~43A[b0m-mcAD3e>¿!5#g!Gl'^: +[;v/;^5M^\z2j2alaCK]q%c36Np{7);FV^N\SBYslml)ϵ,(lp&&(Ēp}?*Q~!j2abH_}}IR/IuY5*rHhԶLV^p֚ j(@B[DtYLQRQ~>A {JuZe5F)v 2kVnup߻ G8`3?Z/'7df&"ȡgg44B֐? 0|Y{!GTk`"r@D!s `Wc憑Rh?̓oIMf\8K6ҝ X\3K)!3fn'jhDyMn k8E˛cfb׾rZy;cFh,:cVfQo1aҵ~uX8试Q>kr.yvhuz!w'S;N]ةKja0a#X;mഡ9s7a&!ɷP?'5wU{y2{! 7 "0@_ӏxc Ҽ S(ԅy'ނ=D3wy6bz-368i#^Mb̘1c̵qߩ:@X0KB Vd!Mݨ7?v&%B6iyDAM! 6B7q"I,^ѽ~"mY iP]F+$ X?;dG$ڲ1cƌf",&Ud`6A? l涣;+fF0s!} eDtvkna,!o`vs!Q Ȧ,7Ul' smȚieuH symho.f; $d5kƌ3fns-C{vh\ 3<^ڿ`Z!/B6xc>"wNpqi,13%? exUkg~mA^% IB% /mSg)B"BmoD='Gw!u O▄7pbzslҥ!e8o#EX%!-!b]O7o%+9.=~w= 扁wJyp0_53f>\̜0sgNF0_k\j{* ~` Ѷ0م zlRtȦ!W=Dd棋23$@o~ptr=lm嫛>۳n1[qt@^f}ޣ"/lSVo}D$]8N>)/)sEnC/K;{r K?~߿[Ij̿J5̼kQ-KgQ֜ @|i {"uvdZe@uU±5W|55P{Ǥ7[lbGCaٿh{kܽ[O_|K~]Tbʬyҭ4(-]-[N i׍GMyQڶzJw;p댴zID]7u0Ĺ1ڿ1e wk@D!զ+(""Z!@_BCk O&B֨7.@1$ku6#uspƈ9iNHӊr3GuejjdSaNzʮ,Cf*)Am qJ):lY EIOD1>ɥG~ι )}%}o~V&RKE%n! ^(]潻[$y[aWMy˟n_%rx9b do~:r`foGb߆e3 R>.  L{]҆׳orGN%/y`K_Hэ%XK‰zA <ԡhAm8 =ǏԜf~9xS;>Oyǽ*Z e^!gp6S|?&^_C* mpmu%NL X4 ;s&`{ꕡPw$WWaWٿЏ=I3?^Y)g)'-@&mw-m[(,,u8'w -QVG f5G)ypO  UQ=ܽ5kU` 4߀Z1m5W~M u+kIB&'~Y8vt#a "+0N{^G *cpE[mDi>~lkL̜HD5'_# l;uk%"Yh.076 {:Y ٝ_șBuG!ol5WgD<0 B.CÍ&!j=`lo< Cr 6v-gsӥP_!6XL tᓥp)+8? ߚ*Z Ů^طq9ac(u8y]c\\ -|shdݫ*R/?\%Gp~v*ڿ S08OTT68o%nW?Wө]ܾ0/8u3EÏTsĦ%}FjMqr?V}.p RO).#iKOg欖YIՋ̚'v࿶(򵰰=}}vڸI3:U bөh߾}'Qw'-nMe-R-|&tcu\Q{ebyy?L3wHE]T,)">f/3nAf0 4"r@.Arh}I7֬b}yS=f0k_7R~ ulZ ǫ^Y9C6oJHRsސ7Z PL)  E3׷'ytgȸ|J+x k>w}h^#g69ܼeO ;.J5|o<§\QZ 8Ot8NR6̚'@@huo?SsBqS3.sx v&5ojg%O@ifK PZV]#gt,(={K?ze^ʸ|"BN1KvєY$Dwݻt s:[~r~I:WbiS˱D$zm_v_.pCFn"YiU||`w,+t U^ʁ}=JN$QYL:ZM?VC[PuZ}]9&+B֯G$]bx kxT'쉣s$H][ XթxRT%CڱaȜEE+]W{/*̨QU#g)N) (ac 18k1EK 4*SSUՇ".VphԝH]Ge0^@3o'}ufĵoW fNV᝸=copb/j"d﨩FCƈvF>%:Ɓu%PQz[9OP^R@UK|zmVE;&*ˮ"/+9L4ô8ux fmжTO ʏҟ\%}=^D!0+,Loqqኒ45 {.kPt25YH^Cx3-G%Ǔm@ + b; R*ַ pkR,ow l uE ROs%a% U%S6\+St]F'\U Uq% ef(pH[%UA9qmV1C q4Iߔ; ;S/G{LԾx.d"m^TD֚ >k~=BUd(=5GEMlM5KbQH"Y鄜 ')w)Eʧ4VMwb őn}*V5FZ{gtln)Tհs۵VBq}ۉ*ʊ7(Ae";5o芌˱2}C+ l^!Jж f(ֶ3+ TobcF#_Y&{g?vm! T(-27}PVL&_-+?M$45\<|17}G6HoekUm] qYs@ IDATbK'^a.FdtEX,g8YT7/)l ԸVµo튖Dzҽ5 kK@(;nL^vڞ RebCpo8{% GZovov 78w 5G*9lC<*95PX[Erڞ:T&τnM U=׎4:Wbf,Sȥ/#{<2ߊHp+BԊw w1IVknN ޲]YOj,楚:w"{ ctV\FEJ>CX*x0?qDG%wcTr&F `.9|nfN'A=WhYz얠5#|3ʾ90&vDxCLO}(, 8yHUZ0]~=|-,2 2 MYQ6,#_*O˨Ad! 9 ov>)7ǸvRWZ ÕB-m (=B9NRG,h/Ǔ$L @ G@bTgQӔ_$֡:E/?ΒKlhUaTPs e^V>Ψ+[9!4 3j! u]9yqnKPuCՕyھ;'ǟ4rQqrF "d(e\F3ھG贄sG?^|Aڢ\ f]=!E-Z:L׃mqyIFL~}m_~b'$u {7,x_yułwi 1td/A7_/u+.̤ 4i Two}nT V6vR=.V6؋w_B$ K+=S/;|y/_ F4jvgì8}NzF@RD*aa!( H+%ݰ,ɲ]lwyܽMX<>3'f̼=ox7.&K /[8{7+wP3y8V; 6O[+?MS{ֈ(6ٷܼ Zvv>~/&`KQ! Oru4eAIY+(.@>df }Gs „ 2s8ߑ\\1+%RѪq1Zs֋dѹN/Rw4k÷0>Q)dٹ$AH?F9camfȾGMO2mƀj[ll;I’-S?xE8&^.9ڑIKՠDi÷ bVaӯ){ORG<.6_|i)0-OUg{he~122w"pZ«Q֩b.mV޲=wK*$02 ['lغrUpל']-]:oY*ʄy3U\8WQ g[=LmȯC_8ClЊ-m+Z:jԆkzҜkÿ$sk{xx+]/U{z.22{w~ިtcaPt/ ^U~7kRQ WΖlচdVr@Jv%6{ M arC C߹}?"6s[S׊w6 _'J641 MĤBW}oV o([yhLPԎٷ>Ȣ7A[ i(ȃCu=:pי!}u]ev2Fخ+}#B[Hf3)JΆvܖy^9M"*ğ}T= |4i߇SAkҠU }kB땧MܦZ={ZwX@Ax7_lz`[/PO6#[t2?o}Q|d2ذXU4y}4Pa^*eL-1}Z K;g 0K4aV: ǝ{<77?m{q㶽48{5W;%!ocߗyN6ܺf2GnhUw BV Vr8 K"3GrT!sno,_PBW #XDa⣅2en)͹ywΗ{!{7υVXXukiB0iYTJ[;_!m4̫eKQ{ţ$)N%eI01w%tmL`[Ѥ + v6B$lDlI X qRq)ROѽ},1;̹tw,ӮKťȸx"u M >HFїD # DT4FDӉh)}EDȥR9W"z^u"QrFe~"9e4Tn؎DQUyӔ,E2'>2l[N=!҅Û a-:{UVLՁ:-QH7˄Zyp Q=ֳ7Civ9ܿaPqyb) ҡkc_ͯeF?nRq{:߯)-j{ )?ա+Qm3C[06Vjø3g߈!RfElGw7*P[}ZO)74Q>/H%RաjC[B@е5E/GjBZum6Ba e~1 ܭYάV6pU☈]w\*ATn֜H/B>n?)"+ kc怕j$?2yw.f\ @$_$"{˕oUɶPŠ/+beś@!@ucWv6[[0P*gPEf)&F̬~V{fPTY{ס2H`Gˤ Rl\kQ.<^#?}Gs틼bWŦȟ+>A֢mOuy|g]oZ{Vy%e()LVʏLTTJF2ȼA1is0YK.#[**A82emqKs HFXax2 &tXywT! ) Ov\!]q)2DP~T lMaңJԢ48VGBGԄTXT[0kl8oŒA$9ȸxJ` 8zٙ:8SԞI37G$C&M]Y_5KU( -xr~d AbMk{q`ї3PM&~.OnH -T6*CNP<ƥCF*\xRh̜ԄO V;Q>wӭx4:1r}s*s<9\yC9l_vl =lQܸߵX#3ǔ.63.; 3{H0= La?nܳLqFw7A" Ђ @FDь@Du,L[i wfhTe|vеŤLV0Ёe ]mX-#jӱ6xeAP`\>l:I|-lӆMΩܯ9jgE-iG'Icg6i\sV.uӶBAe =mkUOu 667E۪(8U봛86]~'3U*U# XxO-l̐4ZLj/"ϭ-#### }>$΢~̿<.̚VV03EY0=]?!n(l˴UbG֎MZѿ!LS|;Zʾ„ 9șۛ=Z*d7d;y"X<QU̙D wY9YB|d0[ٳI>- E6\>L]IOCiq)I7|.Cɦ 22ٟ@)v$[oNkne]r_UWmya濘#c8@D *+-8-$51!!J ͌ک=kR? bܠofѡk3_d/;8$Փy3f |:^; 2/g3Ǐg"ŕy).bfBxBD.DTS#U  .ȹ9ed-nRAP M|)oʿ'D̜eQ;zjS F3XPg.VVїP]vk7עhXV#;y8"*ğ рOTEoYFahĴl7EAfqjb4.*$I(u}D$PZR/n_:g eSa~ͭиMO=jgddY>{s7+eu3%ń5Ƽ'ii[ IJGɓ_4[u@{wq`b@Euqgѐ8m9=@dnvFJ]Od"@ڹr>5nۋ /YX[­^3:x"uG-lednԺ;@Stx2J !=CugK&*DtX+zpqeg`/tf:5ct`w"bf4؟MD3r2SyG^l8dA 3է#`صBOQA^56Iv;WW>~UH֬y^|߼_z 5"w{iJH#4-eB}F-oمIKfҚ+nqtrѬ5}ԺP)6nϘ먑522fNЅ4 sUŬjΉ0,%|}^P w\Ji |uCh,-)uD/~c1ܲ`yXq_Ԥ} N+o+1]Qs|?݇)L-{JǤ9ح^s݇rQ3 Qzn_:Jo|^\q^,)؟+DӔ0䵹R[b7oP^=.Q!;W)\KѶH1uf;y4VMܹy|k۹/6(kL]IR 851Z^9F=`m|5؟gishت=@%E(*ǧ(5*vRLtVA[[fܱ߫hZoqFVSv@4E$?)3'&aDPˤ8*x|-ۮ93**w6Te a7Αoӎpf͒3k|fKT$FT>B៓dnԄ(&Di` IDAT72AFJ< g ۪>Y*l 8G(7;)TZ\,<0) /Xwf}C^&pDeW*׬>{5ņߢ-T]Xx4`ؿq19X[GfVg 9/F[W9LKZZO7oW7AGѨ %YՃ Yq6JJ@DH _{MqMN +g⃻+< 8KwPVjrADNM΄^_.  -4iߛ /a4ja`ö^~R{}}]8܌fV 9^g_Dѽl͕5k"mmS6l\jjv2cRjֽI9Ay̬8$72Eyn0rPS6N9KҏGP(ո-F-S;Ғb,-v62)0vMK:qm갑7/"b]W[]K[,W>'DD~n&|vd+{76B㒕D0r|*FFJ?VȬa~ xNJyGmm$C1\E:cFθpϐ;}%S?WoB(V% E(m9i55Uɴ{_)rIdd;|֝ "Rp:3~oh PMR~sE-#5lխ0Z,\;eg`ϚEc1w-Y;SV81:gaaㄶ=G24jӓ<eQJVv.|&qf:jm([;U湿~gqѐr26/cgJ Zr~nE'+N(ZZ8wp]9ޘ^21+,MX՛b­BK wť#Ƚ~K  \A,IYtvjk$74ܷf]8s%Uwh6wvLMqӥ)6,~[󞔟EGL1a7hʧI@D=js|рZvwo_#["m=t2]||FEoJލ۱ BԤ3?7VLښ20t"?*n34'nD6lҝL0>]dS/T]ѳ0ԁ9bM)@҈)ra hh{%i% Z/H[FIf-=8\zXP<x7iǯ['\9_,F0sAo"/#vK:zTQ3B.^%?jܖ_8oYP(xWRW3nQsqBT򵞁1?!APtymob1I:e]߿?L0K8C_))KKŶŖutI6.~Gh>֦pߵ^qv~AK;Lddfe_a<(1uҮUezCGZ` A;~'z}vd@e6Lj] zy"io۷7dlfIG.EF-ٶRǡCWػ>L-巤]i~dž9wŜv^iӒbJ;iNrQAt`bwB'}&xeuӔwB5Z:2x"w:?'pSKm @[2ghzdIsqiCݱYJ(C܆"n9|0 +p7 $(J•!KQ1PV|־.7g _WM|NQo'E]*u5bH=Dm}$-Flc7..ߪWhj J I =Rzq_&x~3 l% p;h˞ZP 44U2e<[EzIsV/|7(?EoHF☈Ys::Z\zH$\Ot9rB ` 3qtdyH'SK[~hRafFYZ(վ}F|d3'3 s K q/.[sucjӑO65FLQA.ҒbIȄͬJxQoMD3?d`OIYh(aaX!3ӒSmԛ̴$fx,kmLd'vN2q/K/T/-ܹ4;Ti 6 p'A5I{)*5oʑ[T.ncf٥>ژ(9sWf҃cVۅY .ʃ˄)pkv`3Nv(uHG [.t4fzrsC(˖r>ұ6U$?6pF"/ _NhêkN I%Bژ)gNh6}8}"; M29Aqv*X0}xE222222222wp*N˅i37 Mi)H-pYIK!!`T߁"H6w^5qGڦ0mV[X-H5)r!(ʇ-{ qenjޒȶZGw6bT-!yqw)'3zFplĽG`&,ߋÚo x.B-(%!FLB:wE]%SK[ S 8G%D>͖ Eؿ[|$e&΅ ­כѩݿQ\D Yٻq1rV4.N2㩨06k߇{.i /L-^zPtt/{K$3+{tjoFhЪ+8CIBY™}ґmGFpl^nO֬SC&I[},#‹GPQA4ZK 7Ӆ6ӽpw!沫OSsIgCДOHN 6Z8;x2%9;_kul|t M mmX1@̴$ syصKq%N7;}vЏ+(1: MP Ya0)t%tyxfiCzr'ٷ^C̳#5)I1w j0M~/m{]ґma;#WO|53Rpv:70?N!c3@~^6 rвiϤC_2R|vǡo{ b)1Zf/]DaA.3T>~t006i_J*Es fշT"ЗǼXwKf'wUWBۖnо˜EO1wnjʥ$D;{]gLai1,Zt7Ek?7}/v:Ok#})u[?[Ph!Z2)?mn_:J>M;pMN[ φТ`H>~Y3ͭp"C49 ~nuAw?<{8{6b=#q[x5n c3.FKU &{()*@qQfao4rڗ~ ޵v4ano#> &W;VCW$cs>7ڱr\~NuɟI^,$DO^Yix5Q33(y6l̀hzEFrpPF,=ZtčZwp~Iq^ԲEۗe!~9 uFbLɣ!`ESɣ+63#7+֎,udbiH8{6b-swec3+D]!Grƾ[Ft?y7/EҪDA^|ud+;W6[63*Jq]}XWPU^,r2pjϚ*}sh%ExPr'F~f6~'oYJo?Ejb~"B~JVI106;I[$UET){o3Vi@*-);W;W͇: +u4FfVHO*u? Y}qѐ;yǕc<5؟Λ~x稸(Z:l؊'O%φN\ܬoߋlڳoN ?D%i7f\~1R^*zE/"g+;WxUynǾ/ٷm^`d0? TY[g`h3^MIG$n;H -m4lՍyFL=?7̭؆lR"####}CcJ$ /`V.YwxffVhҮ7o[>Q!@/MT:i U{,|CS ȩ ǯƏ9 MyW)"UAṋ2RqhcX*5KYŅCziRFFFFBQA^ zP~5@ Z(?'eJ^-)Kv,OJB$BI|RػP(pj{DI25QR\[SL %PjQVMohV]#̾i~\^Vo̭Ѭ2ɫQvJS63- Q!vjSRPm4?`wahbP =%d'#>2\k{&k{WwǷ.WSΜ$1:@sA^B)987k' oрyj" 3 :\|X-l?qNf*V/"}~/Rӎ4ͦrЕdUa[i~.#~Ur/&^\.C=v]^]K|:^GsTIW羪8{Rp72-~wPijb4ݼpҒbq"/'=GN G-;7/˴w"gj˝弜 ܋NUޜ<rn/uġ?RBd0%Fc$",Gqt/D9uE\#z4u]8|I^9^aYP,Hp|SĒ/U\$D:J̳H^*޹Ӕ3ӲY/+tti}Fm]oAWNPӎ5Ʌ : EtX_;I|l{~\:|I];MMHJONRjR B޵Ī$v^hg4{q`w"."ʉ"ƹ ttHېIqۻ+>pcFftHF=!Amp,4F?Ŕ4@cvI9ť]@=Mbm[d"0,q,I 4ϟ;7x=w?0W~y?cv4„1t(_<#2Vت,zi*ʙRѥ\w?9ߐn]+I6&J/; uTQ\gd7"kKڪҁ-q͖\9iKzV49q6Z,]>1))<Bcp)%@! /+o.{Ǟ\"Gd7No /o@<|ڧ ʜ/$Lj𪜻}}\SjnqgԷ+-xUYl>9Y'OADD97tfHY=-6BȔ7օjRv>ADd ſ.ۛ&mr{O/0=7LQcƈ)3s)k&H9ۥc%"/%~IEt?ey\8u;;iʣ<&"z8IH-MwrD O^>CgKy1롦³l얖7Z(qtϒM#f>-nU\njSK]} Rr~kzx/IH5:=8)OwHd >޵)d&2vZhWxHk(jyu/hƈxnl-ޗgn/DD>AeRC"!uV|8GƮxi;9ϧ- S?rNzit``* jjmibI~u#띟K7Ɂ!S}p5~u, ]Lye{yˮNo}, wxY$!EѮmjN/jjo@To5Xvm%`lG6yNLog;=֖;T_[˷U V1 7IvKxy{RQEDU(bRqp&ܶVzwdG*T^Z޾\xMa36F'N` uN^\ݎY"?I*/ot[f&_]%~eoڪR[յ?߀ZCO,/] ;?븺sjf?S4&6l ԔѼ+S; t gE-4pPxc)6nlk\2\_3 image/svg+xml Cluster scheduler(SLURM, Torque, SGE, LSF) bcbio-nextgen(workflow and parallel) IPython parallel bcbio-nextgen-vm Docker Container bcbio-nextgen(run tools) external tools(bwa, freebayes...) Machine 1 Docker Container bcbio-nextgen(run tools) external tools(bwa, freebayes...) Machine 2 bcbio-nextgen-1.2.9/docs/contents/images/parallel-clustertypes.png000066400000000000000000002656351415626112400253720ustar00rootroot00000000000000PNG  IHDRF&t bKGD IDATxwXKYzP,`TT55ĚXrh7^Kk%h4X^D *D ]R]Vهg9SywcBJJJ$ۻJDZgϞaر1tЦ.N<)SԘ|'MPyڹ6U43BۂC @Hs1uTx:_D>wnx?SNM6ܼ&,i lقh$''om(dHMM/:uob!t 䭣G"88Çm6c֬Y8`xyyI߼y3`־}{L4 6lhꢐԔ{ߡC&,r 6mjHxڹ96U43BۂC PWW ك]ڵk/5+WTjN>?nݺ)5BiNi|Ҷիbl޼1RvvvM] j;7ܦ-'4mADABOWWW !Ů]JvnJԦm BZzB!B!*AABiFD"E't.׍iq@!!ɓ>|8LLLΝ;c޼yxD:{{{xҴ"g?~1̙CGGX~=$JQo2r,KPPNmBCCڵɓPkzEY}CR׮]3BP"]Ϟ=%|\z[.~+KʲRelyy /k}՘2mBF0k׮ /**[[[י7|a233cBr٩SؼynN:Ž[$s1'''. 2www_cr߿c} svvf׮]cӓ`f5{n,--Yhh(Dȑ#LCC`Æ T>yڭEEE+7|VX 2dx dϟ?WR򘿿?377Cnynn..ȣyxx0MMMvgXHHHuMyy9[`F=zIJb:::]v+&[s;v[1{YDD+,,dА`mBv6|p.ʕ+k_cI]***ؗ_~0 4v}6encEY}C̶R^ݓ'OX~2-_eggKy ;pwΞ={-u]o޼)վ+k=d95Ds_~1جY֭[7&$)++c... swwgܲ(~… +˗/ŋ|nCSzm*7nw[_~ cǎ1lҥ5>m6ZڬX`_PPmOooon~C_ nة,_BBÇ%.ªͫQ߅"ǒ2Y`,22I&չ3q]Ch[)z~ϙ&O\kdݹsGk}mHS|{H{Gs"U$PE*mBZ3 :RxAW]A` BVXXXcݻwЗEKcP֧O6~xVZZnܸ;ydu5߿_+((|Yϧ@v<‚{ٳػw/@ `ѵ~ރ6_~槦r \gffJ֣GZW*F 2ǏW^RsN0Ơoooeڵ{ァ7LuN}[988`ӦMϱqFpsrrꭟy,seΝ\?SN5Mm*wu9g޼yo55.Q~H*Q+-YIM}}JLZZZׯ_i霩YyW~:\⋄8@kkkDEE(--::uĥIMMwҥF&L)Uaԩؽ{7 '''L>ӦM $u^+++J,311/;;;!ʬ8vvV~?k R}]rZJ{}aee)fp,%>>ЦM [:E;w.֮]Hܾ} .ݻͫw4~\ +EI-QվMHkEABA?r۷kh+ǽ/^Ą ~znnnp 333>}/Y7E[^^νe̙:t('ODff&_[0TS\(njvV~!!!Xd ݻ9r...(**ºuTJMy,Շ!s PVVcРAٳg9͡ Ԓ[UۄF-/HH TgZT@/NU VYg$~)}_Ư OOOXZZHߔms*"d='6DU6!iURgRԹ3U]aÆ|ΫJJJ)_!oܸWWW:tDxv}McMYU .yyxx ??򂏏֯_WivvvݻrI\S׭[ 6B?DZ6n\8T@eK9Y(r4Wߥ@eIGpZ*kUDs(Cy?YIͩ}ֆ43gr7o\g-[`„ ğHyKKKQk___SK,[x1%znZmTvU%++D᧟~uٳTv*MӧOoٲts'h5c>hgqɓ'*TޑDmi7PƱ Urq\{~ȑ#ѱcG!0xZ**KSAOsRSWToڴ̳!*$yyyJI?b;_a5n]l5cGY,Ϻ߉':t`ׯg~-ի۱cڵkٳgejrcʊݻwO K8kϡC2sܹs,--x[uԉޞ=xK!ql^vVF[)r~Frr2糴:)Jۮ "e`L!YIW i[6! y`]Y"̙3Mk׮(//g+`LSSٱ׸ÄB!cnnnl׮],//Oʘv ~t;v,333c‚7]p .nݺfnkٲe1ƍWݻ˽^eQH.\glܹӧ,&&F0f/^d{ad:::LSSуYFb_Vqq1۶m0`go߾lΝ1իWzr˗/7yݚӱH;+ny~9::2---֦M6qD a{fZZZsdjsPXkXR_2k.ַo_& >2dYDDD "yyy}}̶R.>{ u]w9v=95Ds<4icn}ւX3ꚜ9tVZ>ƍn„ 9sMXbB!Ҡ;yWѾMrQ ǜ9s'N`̙^ ɓ'9B!]E6!GABܻwj갩G*/!h&D(@Q.]p..-- Ν͛%#:wۄ(뛺w bbbsΡЀH$qQ̞=|>ΝCSBHNUo|ԑ$!D/xRRRPTTMMMcƌ .*!h&Dy(@!B!>!B!t B!BJPЁB!B!*AAB!B!!B!t B!BJPЁB!Bʄqg6uH#!B!/_uVӃ RJe!B!7nkjjٹ-tE6m/i(@!B!-x`> =B!>|'''n(**0@߾}?JσTիWȨt۶m%ݺu <ȕq!ܸqɨFUVJssszjDFF")) ͅP(D1x`X\>O>Ezz:7-k˗/^֭>CL6 2ѫW/n%oߎ7owرcFjj*]v6lV\Ν;KÇ#88 (,,lll)SSh!B!2;wdP(zYZZbjͣWllTy`c"M6޴FFFɓ'2`} Yrr2/"<&&F˗355:Xff\uf={Hqqq^bct6|z700򯨨`o]Gw:B!BZ[GFEEߏB@JJ %~o | qQ|}}r|r c۷/ݻ}|rJ7#F#ttt"22@L>dmڴ]uԩS%Fpvv'qe8::F@}Ν;(,,c666jjjR Tށp)ܸqO0qDt\l/À 4tUܹ={(Tgifnn.1}Z]vΜ9|4dڵz*233%2O>5w@!Bi5 MW@< ggg1cf̘x!k!~H$–-[`ccY{1^~ صktuuaee'NϏڵk%h(tnyEEбcGbڵ嬺.,,Çkotϟ|||0x`щ۷o#00{ kl]vE޽##G L IDAT///"33ׯ_۷b www5 666PWWGtt~jFh B!BHq$0[DizyzzriN8jM|qF:[|Wz7ʊ˳/_AAALWWz`O>i,KDD,؅ Xii)i0DRGKGw:B!BZ ;|>7ܴ,9ڦM~h׮&O̥2e lllm6!==BVVV6l-Z]ʜ/رcHNN11|,]QQQρ4Z+?~[ʕ+Gyy9LLLп|GֳgO DGGFFF@߾}1fxzzv ???!11"ZZZD1e;VbwB!B!(u$I!B!!B!BTB!BQ :B!B!D%(@!B!!B!BTB!BQ :B!B!D%(@!B!4uȻP\\ (((@ii)1'U<}}}|ZB!BH 3g`„ MX""/ :\"?/˫|";;{_5?;;IM]|!x<Ӄ o`MBo&&&015iSWB!VӃ jEQСDFz:222td#%%H>3#%%%M]\PDLMM%fff033]׮˶mbB!lmmѦM&, QHNJBll,^"K|{=@dSQQAx70jRSS ֚6;ݺuC=е[7u O!BÇ#88 (,,lll)Sӳ<}`prrh}r@vv6?Oaffƥ{ď~|}}q1W~Ю]; 6 +WDΝnC\<Q2< O""*_Oqx8b_Dyykjjڵ%ڶm KKсtuu kƍC0{ln:&&vvv L:W^~F=|N&sDGE!""#*2QQxyx/_׮]СC[\9CCCaoo#F:::HJJ @L>\ BN0zhdffСCpXZZb޽{!*y B̚5 ÇG~~>VZ͛7dmڴƒaccp̟?"ؼy3=bth$CBp2塥 @uuuC @MM iiiHNJBvv6TTbKYL2(|Dii);/ć|B^Ыwo8۱S'5!BfϞ]H[ZZ"::F\wAndz B)gqq1ȳ@ >tFM ..0a9s[ֹsg|K MMMip .mFF7ߎn7sL>|K?`ժU1vX={?~<Ξ= X~=[w\ܹsGCc{m.;T< !UlTG{++͛7(++ eee}Ri7&&&҂P(Gtuu MMMp5T C)+Sgdu?JW=QcUNdeeqe}\1%&$ 1!>bw\,'7a!BZSRR`iiAprrK<嬨Sp Tsi3f &&055* Hd %tyii*} EZu64uQ!BZ/AAAtǚ5k憳gJ5L*;'NҥK!O;d{!oG+111˫uc >;|D2xt\LLLzէD>tCYYB~~I<7H  ! y|>|>aeն];ڢ-:w Ҩ2ֆ6[Y5677))HKKC|\7TX"9) */@ 7o꼅B!N(aaa8}:w]2tP,ZG۶mammd5A}}}888Ժ :7d7od6|>:w#УG.@c``t֭o޼5*6J Ja710 #Fێv!BHMgΜAп~YXXOOOӧMYL˹o>.࠯???1/_r q3B/1EppDZWWW}rrDguu" 6ĉxcppp9s0sLvϯ1DϞ=]v(((,,,зo_3 xmkw:[7& apqsGZD*רi]Zuڅe+-?>}ްa:l\Vht6nݼ~~ |>{x`'`g!BQHGCVX[6qHSjՏW< U](oo 1J(]"""ɓ'?hu+ն`m֘3'O ??ܾu o޼H_^^˗2B!OO9=z&&(,,DII P\\ X\BCC\JB! GA :C˗ ~>|=zǏkװFAAE޽;ƍsX~E3 ݻw~R*=zė+V.^ęӧwR)m#F Fne611@fF233ʽDYYD"Q,455 ]==026xollVVDN8B!>"藁>"萟cGcpO m---„1z 8}4>yOi6_VHWWMLH$N:KPXXX#}rR++B!FzyaI=f Hœ˗/*6bcDTTT4ZYJJJPRRl/,۶E1]lmakkK}Bi,Y%K4u1H3NB?8'Nuc`ĉRۻwo$%%Ç~(qKn~~>v OOO\~KrS6lD/u>¤>Baa!.;ߏC+pJ⊊pp\'"WEE^x0<Gۿq*>UݽP]iiF'8{47 A>} A[[B!1sID"v3=|(|> ӧ *(('N:I&qi~Z AAApssxE@@FKb5!ХKDGGsK?cܹǪU ۷oݻw :gСCtǏǞ={rt 3g… t=B>}0}tlݺ7n_t,ZH׮]ömpXnڷovu015 u BOOfffjkCGGGggA__|O'~;rPSS|>444PQQCܜ~)HHH@B| wvFggL6 vvrCHkVVVdgW{ͽg!??eee(|Uqq1Dz|PuuuCO_<zӃ~ӫdeeYaԩhdnk]p!lق 6`ĉx(**¶m0zh899ɝwCya߾}Ç~-sssk6mիѣGQQQ?p-%K`Ν055455qM,]8{l>-Ϻv*1 cׯ_gXΝYrrIJW^/1إKӹ4gݻ>dPVVV&;wXiiIJӧO3GNznwww=zH"]ii)_Y\\7m#k;HӶʐǜ> UzyV\V\:i"BS!&:;2u#Gⓙ31nxhhh(lK.Ŷm۰aغu+п+}}ʰk.͛kt2immm۶غuDD]GG{쁏ۇ HQД;vʕ+)  Tj=%''@>ST=짞m`<t6nƊ/9spbXبx~'>&.QC8s. KC(mv>tުlhhݺWo< UPE^n.wkvVf&ҐT %%i5keCl߶ 'NI!iI޼y' CTd$?11xB#Bndavt G#Ըm 9u << xPWWGii) E"rHnn.rL/+..g3\}A]];u#`ooGGtԩGD!DQ-.gNY===|2s&.^θ xblܸ'OFBBN<4Tn9 رKԸJKKݾ۷nB! B @2ݗ,FnnniQ\\l0Pw٧11PgS߾׿?9;_077WHrmAq/_ ///n͛pwwH-R)Qfm??#//Ot_}O?L_e211… ?`ݺu %LHJJBNNN_P Z{wOIIǓ韢>RSS===_EzE WFtt4BCCqM?~}ڷovh,{-X˖ ~;4~< w6Q_+Wl&Ϟ>Ο~oG|\& ..w4 }= }=n^p߿!!w>l~H`W_aܹXl[Y " *w:ݻ~dwOCEEkvuՅ }}}hjjBWO:::Ғ黊Aj a (,,(,,DQQr+D,ׯ2$%&*1q~~<7ma{/mmm%!QSS5>oiiٳg 988LDuuZ` .Z(?cVć'7/`֭N:5`a4QUgY{trrBRR$o߾HJJ­[0zhe111̄L~… 8uf͚%Suw;xoۆ;wbʴiXW [AT]CB?__G ̞;fmff033%L  Ztuu+ar^Д!++ YHJJBjJ D$'%!%9iii*ݟ㑖uwWPPAggghjjLD:i'co.]ǎF/o+SyyyL 0===KnӧO7 LMMڃy]6?`]ta)))ي+c]x`,--K#vͯaau?Xppp~~~ܨ ua,**F96l-[p6yGEÝz&ACTT T0KН®2=ٝu[yEϞMՔE7qcRmNN_$Gy &{Ŗ-[ʽSS[oQ ;GG} ZE%{_WWwUrdffRpp0ә3gNAǎd]UT=9֮^M=JA^^#"话;i2x0nޜdU)^^Jyyyrr]&ڶmmذZnMժU#MMMի|Ξ=K#}}}РvQLLĐLGJJ\sV!!!-Z0eڵc䱱vADDVbɋ666bDzw^<-?hٲedccCTzu>|8+^I:CRݺuIUUTUUܜƎKϟ?ZhԼys#SuڕmFYYYQQQ4zhjժ*YZZ҄ (>>U۷.^H}!]]]jٲw-**ƌC 6$MMMRTT$---#Gҹs礚Jgt8u42FXV-r сˋ&uؑQzIet "ruu%dmmMԧOڼysM0 4~7ر#)**)So i4b255%ԫW/Aڅ0(ǣVZш#hTN@ݺu+uneGI u'G-Zqє)SK.B䇢k#@ Tņ::4ÃByٴikѦ&q!(VZRS[!4k((U(۳GNDD\nCEnn.y{{x<%''їvC-]]]Vu֬/[el̚OU萑A#MOKMΥLy^fFl:u*2YZZ?eddF5k'333ڿ9x 999.|QFQTTݻu֤NdkkKk֬-8""ܨf͚LdggG~~~b Jq4\01b'mmm RZZH%]Y硲ibZ88ХiI1r >f5QQQ̍M6Naa!8@ ,,ghkxOO*Ƌ|q:yM:b=uCRNNU娤dddО]G׮߼XtijR.](ߟBCE9ʇlC{v"ߙ3 խUKkgnjJϞMyB6 J}۫Žz%o988VL 6j$at1K G-۷o)00ie~Uή{ G=uϟv'--V\I{tuiͩ*BnnnFVT3ghС]Z֪E#v;oSAAQ:}̟O{X3 =uPYec֭22KJJhR!>'NjsLcyZZZ2ec׽{wLIXV-lȑ@wi:͟?OVV3GQ}[h!q@;wHӧO뉈hşO۴iÔ#sss `:eIHH`LLLNضL 4o_ڶu+%+:z0mے뭮B L+oK͛7ƍBҒvSN|e|:oժU,]ttt2q"\űʶm:wݺuudhhX@ѣG^[[Rue;88vH@d֬Y#rA UVvJ .)wXh̛'12qQkThj=c-hѲ%&MȡCs6'fϚ{wvnߎBlٶbyfN!!%32231SlJ]ʁ @ww?zs46)ǁ}p`> ,A2HSVѲW W,? tCkkt.=z]bs815ESS0g\™SpQ{|7i#Fw>0)ccc'eD۷o3˒֭[طoLzAWWz1%ŝwUe+Ç&;V* ;rDjrppbbĺx҉cǨM,e&{EL+ J WzuZzHf|ڶu+(CINNoe4OAܡH;vb9~n]ӦL%TѡIc6{,.ONff& W@_;w~wwan¨=ujUx<Nd;ߧ_ĄJ֬KиA Ϟ[}JLVVOjP穹=Y+T?aF2 Xgʺw*6leHZ^f-ZGI~~~ԡCh,RRRbʊQ,~e v,̹~zZ~=+p±ܹ͛siݺu4w\j׮x<9sfע,,,Xk׎͛G#'''@7o&/^pzzzL] Zhڵ\\\X͛7O>2.]ǣҥKitaZh+6w!ŒF VꏙZ\3j؅275eyA|opD&{Ŏ;h?K}@lլ 9oH,tԉ[x@VVBۦ"!!O"uV =MM7v,拃4._M]̨Qtƍ ),, cYe-b[4蟫k[5+***s.\jsb֭رA=ѵkW̔ZI| oU+=>}b455Cbb"̘!Ғnm(޽}KsR-c?wmZE˂ X Uxx8S[OBB 4 HEE5jDtMyWKGjj* < HAA|>իWv~f-i,seTUUidooOZZZImڴ;wxїԲeK&EEE200ƍӈ#Ô+5y%M0,--瓒S^Ħlz*Q5HII455aÆEO<)q~lڴ ;vGll,233y*"-- #ݻKu@ @dd$lll7vr";;ڵí \uLMq#TVM>} +++@[[")Sqzzzz:99Uf۷cq%%%!;@=pssT Ξ)Sٳ멨`oaʴikfVAqp<ܾ Ǐ%=kttt*PC@LL 5kQOqȄL1ddƍ%٪S:TI73ÃG@䜚L唆7ۗU70E"K˳gϘ}po[EJʩ'HKM鱾3MU?Ұ!CJנѰ!CVh̨Qn[e dݺu8 VCwbb"|}% QիW^*T) пDGGZjXx1wٳgxUfѹsg577ǃm9h!-uLMsnx<,7AA 001cFvj, [ֱS'\v WVx< etbi+U9ɓA_ ̺g܌kV,1Ú lժrtjjjGnX_Ǐr԰)`ǣAAA,tb;@ IDAT<ٵKvuttoe̙bˆ3!!e(33<ԃ %'Oo߾VENA())!8n޼~-O+<¡C\F|F޽ ^Fpi^Eܔ98*=zĭ1ݝ")1.ݻ9Ç}-/U988\IIIزinn["… v Ç@YY:׭+13s6 "ec<=mR[PSSÀ$e'Gӫwol,"==.1cZhL%qo۷ҩ֮^-^`"ܸ}=z,98 }}};x;wbb7ٳӡ@Q7YcP*F+6l(n>|Իz*<==a``_~Æ åKЪU+ܽ{W9n\uN8!u{Xl-[UȲKs󦈼{شuk%,, <SN[ zQvm >.]*:u ˗/ϟ۷oׅ'X[Rx"\]]a``ԩScǎś7oXܹaÆ!!!'ND5$QXr%5o.w,dggS?#nnn:q:H48(++cE8~h5n+ׯåH&'O8 g̀&AkKM(Ȕ/_m־Ie%GLhCVYN:4qDe)))@ެ餦F...,;Qhh(K'jܸ1uؑ S-YTTڵkvCb?Ԯ];+WŋYeÆ #MMMadJͪ?i$233c7iDDG"'RHH`cSb$kǖ-nݻwLի֕8Vaۨ< TfR놆2erEEEb߿OhРA%ʤahȐ!EΤD%-LZZZ4|p9s& 2 ݿn޼Iƍ#T~}cioʕ‚&L@gϦ>}ׯo&dmmMzzzӸqd>yBժ~Zϱ#G{i͚t%*Jjrp)4ig]'?__d!kGP+.GFJ,`Dzuuu@ZаaCV"""0p@V]]]˗yyyě7o@DVgggBCCYE-[ $$^UUk׆uE˖-EX_ػw7P9y8~111}<@޽1~xԩ5k:k׮rw{ m׮l< VR߫ç |+VjʂJb8C"iLMMz2/-- DJJJ1bLmɬ2GGG <<\A2j^2'NĉcpXIII8t 8cǎ1]vltaCH48 1[og8GFFtuuacc#qgU{;>|>~)??|111\ZEJB*ݽsG|⩌_ЫWjלBIK Dd?Ʋe.]cǎV$BAYYٿz{+ k8"/44I&شiqq@q) #?-ZdTKŋXrHDݺ3 ԬYS$@eBhuvv\]]q}iCE֭+++'\@Pb qmǢaʕhٴgn͜ߗ1OVN!<~sb?z'''Ȉu=|>WcΜ9-GsUmVުT.!!!pqq7V\YEzZV,[ѴY3ܼq a/ט;L:IzXʛJ)0G%66]t%Ο?,?}$RWAAzzzHNNϟYY2*#B볶ѣG߿?B"88:u*vY*WZadlw$*E#ϟ?# PZ5̛7Ltx9|۰{+BZZ|>tuu+aذaiajj 9R>~ :tHbH* ;{{ twǡYׯ#>.uLM+LȞ={c7ϗ\ 4?~[lJL-Y˗ADc-ٳؽ{7;h&`)GreF%""СCrcҥgggg#+֭Wp1<lقƏ/7888L,GaaaK;۶mczqF&x۝;w%RА{ҶH{ܛ4Ni3fIvppEVy<1l0 -Y9//Ol͚5Caaa {9hs=iG9%EܻSN, @{",, TUUannɓ' IJJǃ#0gXXX@II Çz|!!!۷/LLL }}}8;;#((Hd ̙3Ѯ];BUUjjjhР|}}E^8CQQx5PV-Yfonll,<==QvmgϞ֫W0fԨQh޼ظ)jԨMs, gϞŀPF F>|8+8]_={nÆ &r)z]x<W\Aaa!TFy(6f= "޿18##˖,y^988ʘL?%o+ˮ8@ZZСC ݛ)11=zD Zp!?~hͤH&&&w^qݻۛ($$VXAdffF4k,F;w%yxxPbb"Ǔݾ}>Lorvv۷oٳg~'Spp0]|vIdhhH{'OP^^mҁ(..^|I֭[1c3c <ڴiäKJJyѺu1)**Rv(""ݿ:t@uI(:8:63gj'77)00V^]Zˏ2fH-Ȓ2ӧOD FSѣ('N daaA x1cFm˪ѣ"zZ|9# ӣO>sy@tsѴiӘ)3ҦX0owkQFI֩}{<ΝK| EEE߿3gZx1}gxzzǣ]iҥԭ[7@wq@7&]]]@:::dllL6ljlL>>>`2d萆+urr2)((=|||hdhhHh̘1Ϟ=UFԷo_$dddDf"%%%277>}PFihhPJJH[ʊzM'իW >:%C6lHӧOYfQNˮ]-YDdxԶm[WLL 5PvhҥM gի$S|\TQ>iLteyyy۷wJJJ^c=wE:t(:tcǎ! hٲ%f̘\ڵ ?ܹsslmmC}I&aҤI0!fggg4؟>}±cXixȽÇhܸ1DГACC[neqƈő#Gp!晆`cch5-SSS,_ӧΜ9÷"qd5j燀\EEE<"s-** D6m02ivرb^ֲU+1sssǖ-XyOdkkK .4SRRӓj֬I|>h:F5k$eeeRWW';;;cyUTCVVD##˵ʎ ÇRv.r\mFDDyyyG+V CCCRPP]vQxx8kRjj!|2~۶m ݹsbʕ( B899ނ]vX&NyH[ϟ?g@y׏0\2ǒ۷Ժt!"&>O999"^0'N`d\/WWWRt2mbxrppTp@BXXYv///*,,S֭iǎLY޽[naMח\\\.7U[+IV~~>eҥ9%o8V"[-rI `./IAJWG‚Ξ=ٳĺE?*ծ][^ѿNhh(5atQz|W^TV-RTTd-(( uuu222VڵI[[}C%0'??%O M>%722"}}}K9. 6[nZW. 5B[F׫%WY֊-b)&&>x ;p=xzzÃ)-W'2$hkkC]o&H@,qjZ궈˾VVV"1?ϟ=c/.GyRfM?dR=zHb555,_spu1|> ѬY38::2~ 333+))1ASo߾}QqALPΝ;cXd 6oތ͛75jիWk׮Lݓ'ObԨQHOOG0bBOOwɓ'Y[޽,VB޼yׯ_E$qRR={GGG&(-Iŋ+++FS$&&<X>K+Nv""''111_> #(Y+ΈQlRel(<Ol$ 4eJYvWQWWǀ4q!##݃?#8wxS'OXޫwo۪*+^~}bRQ<AN@)&\~999իVbHJJBvv6pQD2cܸqh8qǎC~<{ 022Bdd$6ljCё c0K(!n-.p_GxkűCӦ#RoDTmppp=ejtESSĽz%R~233K !;aaaftnϟGRR[T\K_V###8w,u{  r N(oXkqNWjIaL͛7C_ab}KӧKՏp'BMx?\R.-,eAhРF6mիx5 w^b֬Y"ϟ?ƍ_> Egt/^V \ $u֕Ƿ̱$DoB~ IDATmi+::`#ƻ>k]uktxਬH^qe8RLdi EVXFÇO>044DPPg!ؿw/RSS%:JJOy<|||YfO>:8*'y"2]]]9hRy8{,:C!33Sb/^|[n zGA LMM???oՄL<_fdW^:lmmҧ8۷oǹsD x)jԨƍxwyyy"(TV "}\|***hѢ2'5.YpmCKK k׮iGUU͚5ms,Zj߿ÇYe;wd %tdz#̄?|P`%z/[)SQb<8/n ) Kb&M|ŋ,y֭)((%۶mҥK98Maa!7i"xyY)iX>kΜ>-o85F_&o䊙(O\d!NyREjjj'9ǎc3ّy{{S.]HYYtuuqqq:v(U޽;FӘ1cH__… LÇRRRݻӰaèYfHիW'sNׯ uITRPP֭[eee5i҄3ؘL^^^BOW\a@ڵceغu+ EEErss9sЈ#ĄP\\\RUU={R=HCCիGHWW.2e  3339s&7VXM𭟵ǏI|nxep ebt#%FWɓe%Gĥ;' [%2ѣ%O&7;{l&?MmmYse&yQŨn` MOOZr̙3LLEnԗq-@۷Ik׮ĄHSSZhAgϦw28@hΜ92_7oرc‚|>|ɓ'ӫWDZLMMSݺuiرt=&ӧOE;wH;gΜ!4sL .?~<#ۿ? 4hnݺ4uTiO9Bh"eα49rڵkGD4rH:|deeѸqؘTUUݻz/# 8I=lnnJ)<|g-55UsÍejl tptկJl??ٰiPl!c`q`}ђ%fZ)ݣ1e4XZqT%^üX:x^L0[fr r|?&M† p2_Q1BkܽeseB= kV*n988~R-XPGGCKKK涫B bJK;Q\zUD;W%&x\eee4mTުp@IYr 8,{E'''89;#\L^,Z]uwHXJ? EZZS)RɓXbEܿб#&M KK_hJ ?ܼ4I#91gd22m4}T5k֔\.hŒwiӦP֜r$V ֆ(7m*V^^ ҳghjjbڴi2/_bڴiضm[9hRPP?bݘ5k?.oJ$99~UjG}026ooo&ht7w8{jɓ,G^QLtezeyQhnZުpȓ'Oʛ@YY`Y>-]*UϞסCŦYq233qXm!/Ο?/GgCCC?^^^VT0 ᄒ )Siϊk7v|ןAGE:wy@]bO?.8 "IQqC4C`{iL8U\OѣGŖ߽{)))%Yh9!"@ĥK%SQQa=kiiaҔ)2___.]]\/\+XuDd.ӧOrЦrj*#88kזXaF"O={V&B蠠1?QJ z)1C*X#aؿwox<jծzCpoPl2,[ ߤsefСLK/`m8ΞDR `'?z$*]vܠ-u|>ׯGڵo>CQQW^Eƍ`Sy (('N@nݠ?B[[f͂"S˗Xx1aeeDGGcȐ!pwwg_acc;wbHIIATT98X]]]PxzzbСLW^޽{aoo---Ç8}L f?~z2Μ9nݺa̙u ==="::XjH6m‘#Gйsg|@CC(ȑ#8p @DqpU|lذJ*''==wϞR17oÇMMMܺw$((p}cccaÆn޼I&&&~Enܸ1mۖfΜI?&@ׯ'"ر#ٓ s?N|>CDD deeE٬>^|I5k֔iԸqcxөf͚4gFFjբ}wss:uPrr2K^PP@ԤI#6m#;|0 ///:x kLMMG2{IHHv[Ku_з/5nWPW?"==%i%V>}JÇҢ233iɴvZq?~tuuiϳgϨYfԳgOw%''Stt4=l"Rdmm蓚Jׯ' :}4+ɉwXtJ^Qkkb4/hM1&jb1vE%V b+-" t˲ , ,<0sw3PNNM>|}}ܜ)//+K{ѣGStt4Ν;I[[.\ +Wg}F)))DTyڿ?ijj֯Gc"vm4RSS$":u*l3'HKF֭#"[D 0dee)((HhyRRkJDD+$4qD""'cccK.:yr777RVV&""*..;wPqq1}>|(QFR)==]+/qҥKIQQKԩP/ڽ{T?Nݝ[&H:{=I]]]}zW>$sccΥC -۸~}ښeddUYNnݼ)i锚JDD={$+++4i=\iiis$$$p Ɗ 9r$|رӧ"ۺtٳgEֹ -_SBBeff 6˅b RQQ"<#TUk=n9aG${{ĉv}^H[[-+))C ߿[HK.H:XZZ,opK"""*((*SRRB4n8ǟ;wЙdZSUV=zDDDw^@6m@NNNBGI222BLʨ},vׯ)11H__;p zۗP\\:~Zŋ"@VZnjjJ\BǏ %I{Ǐ[V^^׬s-clںcٹs' ,)͚3~Wd]bBƎ k׮cˆ#ĉsSuЀj#66FskhhŋHMM+`ǎ(..F߾}kfqM<]1 8u!MvsC\lD9ׯ㏝;6rdGXٳgcÆ ؿ?֭[_;>} kkkDGGs|kPb\իWE*>>>=zt*"2CvuD ɉ dY[YQQ[lٲz{РAx1ܽ{ǐ!CCֻ EEEy9, ///DEE}<{ 7n*+x-h?__̛;Wdp'qƍB,̘5 ;Shѷ^QF/;;ƍ3יl vvv\ڵkÇKJJBDDb7n`ii)vjLvUuj^*t011زe2< ѣG'N;deeѳgO 2̓e16#Ǖ+-uv6j|b5Ok-efkj|?3L[r=8Jp='##7CD È$Sf>c%~LRb"ƍ'6t չsgx9 ++ѣGC__{ŕ+Wr )]|7s"kyӧOܻwQQQ>W`aaTnrrrp f+)==D'''g҂ 233'Lnn.?ѣ>l޼PRRɓ'%zNx닋9spe>}@b|)hjjxm ^Kiy ̜qGKppvqMB c_5JA~ڵXvm롣oZ+ v cj=&CPUqwϟ?"> %i]S; w, WMM bBBBׂѣسg %%%_Eq=)=|sfά7=i n?OOOxzz"""β1cj]_VVI^^aZȈx_ͩf̚+kfaq=T^:k4q1tMaf̘4L>SNbҤI8r; &4x iʋ7K.]tZkܹsGl cǎÆ 8p>˗/GYY|||D֕c̙OOOWLp VJp+Vǎ믿F~~>JJJpQprr!++#G]#::poBeS \]|9tYL *Mp!Z[K4~Z1}.O?aæM .òe˰lٲkEu}׮Za+4'"BPP,--N_y1ݽC%MijjlU:mm"QXX ZSfff fB`` |äIRϝ;1s4VضcGs>>>&x<3sZdeeaС*--Ž{pڵFÇc߾} sj2Ǝ;Vkt<}7o=x7nܨ8tۇ7nZNNNƱcǰ{n߿ HKKóg$K˗\b&%%%AKK ?טa%Pe:Il|W ~7a}ԄP%}޼yHOORM }􁮮.TVѡCLFF&4.q_:qqqϗx pm_uu׮]CyyؤCQQ;;;$Ι3/W_}[nq+**rJ̟?@#''+W~!V\۷ ,˗/]ĉj*,_;-x-[`\Ewz|JJ $ ݻqu'O,lmmC ׯ`fee!((]tgPVVi:u*-[o;*8 IDATؗsCii)T&0_r"""D{߯fLz[Y[㜿?b])wSO?TǏ>xЌQU琞KNNFpp0Uׯ_/q2M(**λaV⺢T   Q vvvDnn.222j-'ٳ}|t ֭öm͍MW&;tttXYYG*cd ڥ"+##C j>ٵk>#صk츛mɳH ߿$&|>zeK 4.I6h nrܾwe]\wW_ Bnj={yEN<G ~gA[[Ɔ_FJGGG,\SLy?w_1p@x{{Qhi& իѥKtsέjx"o``4ic۶mx)TUUyyy,\PhĿ.]y_~El۷oc۶m "hkkU$Ξ= ((|>***Œ%KBː tٷo_|\2l۶ gϞ-tuu  ,, ~-? uyr vCCCx8 ضm.\ȭ+**§~HcٳH1c]p?ݻcĈ8wHY"- hgXO??Sy'O?5kb[eYYYvhL9mΞ>-v! //|>'NlOkĵ0`ăauᣪ'OWcܠm ݭ9%/Qll,)))ќ9snLMMΎ˅֍=ڵkG˖-?`+WlիmFDD?3ڊGy8v)M ȥO>zQQQfZTҁ(//[T*0df&2>-X@jJJMM:z0 3ե5w,ܿJL7++}VaddDbϧǏӁhŊoBvvvCtw߷oҪU;wВ%KĄΝ;'Tvǎ4c RVV&ԭ[7;w.m߾]l,4w\233ݻwSDDЬYhϞ=\5kP.]ӓիWG{!{{:غԕ~6|rtpv \akIsNۦFhn/TZZ*?N<LLLĮ߸q#OܵEy{{׺͙3g1c@ќ'EEEPXXH|>h۶m̙Cϟ?*J?}EEEܙ " Y0<Ģ pjƆng˖agx0 <:]Dhhh`ٷߢx aXaC Tvt5kV^Qݥ1ãΙ+|>a*ni}=zݻC>}Ď?#)"Bpp0nܸaBV#<<222pppaø1Ubbb1!@ǎkٳgx"RRR`ddOOO!!!044޽;.GcJxsfά;XMMr6wADظy3>_bzY>|7ppph6}ꬬqa8r\teee022BZZꊡCbʔ)\LIڵ q…z[YYٳgz* $̷~5k>jݹN{% >:::ؾ}mϜ9ָ{.GLMMѿ :Mzh ^c1[Oo''hhhrU[c\~ƵL_0H7Q Z=dinN]Ky/aǟ2-(;k)BvBA l*4{$Ɔ.](pf0ͭAg rٓ_KUΟvȭ;fԥczYe99aŊf&BCCΎ{V[\DUTTݾ}2V"&\ҡz:Ďj +OH走T5:tiiIZTF={&AjWHc֭i6bc06Ipl 4C##/p'4***}͌_׭CG:,#^^<,Çm0Wc`[y|>C?xp> n#7Ujbe!!uj8:8o|ҳgO&/bb0bP̜6 _[FEE_/_Vp-XV 0L "GCy6_/?ڵ$f/aD69@ڷU?@H[]]h,-7O-6oL˖-e˖QRRTciiGZGddh fGu*..׋ruؑƸ 4Erks :q8qQ= "scxl@ѣGiʕ"QNѱA "ԩS'ʏ9k-3g@[lZ.hPsZ D%%%n/_N!!!b|ZEEEn͚z-߯BX>\h@`aZVtϧM7q~j؋(E>FNǎôUt%0ށ]͍i˦MA_.Z$2xn~h'^^B稟^daZVt(((M7R'3zd;k߾ԧW/U}X:z0H{FjBܡ/&z}8x0s=|̜)}Xz葴wKH^ʊ-[&lkk0a8  v茄ul^ruJ5gZvÇSJJwa )3ݐu+N22ǏGTTOOOͯ]&633c-gEE|}}qeddd|TgΜ tuuqĠݺuĉ[8shREw.DWsNnPO===lش ^'6w ü. C`݈zβ,-1{\XZZJ@"Ke;v!|Bs3LKFDw.Ξ>ӧNytt70'&kDD={J@Ȩff1c,hii5.0RV^^'O~BDxzs ".6iiiB 1cƍC?ggh&EEE8s݋k+v#cct x-737/k`g#3 3qD;v 퍏?I/;;ZR_~Qc͸0練zUUU|hmfdff dڌX~=`VM:8]; //a#F`ԩ004L@;2x=<>cGdee0p ,\GJΝ;_Jc޼y055rDKEE|U,2RdEǎ022P独c v5GmJ{8|`.Pyqo`h| ZZZXw7>LɼfyިgW_Oz>YYYTTT%'5q"&M=%V=w-B0utXt숭7#.6[7zdVO:TWRRqA\3믩qGAAr׮^ūW>. g50 >b[aԩ:}::YZ6n4`J9֩G`˦Mb]HBAA.p:oʍicG☷7,>n*~._coɓ(//Y#''GhM׮4e <ص #"ٽ7sk253s{"n]/GG^ ii"m*PݫWp'}|p-_rrr쌡Æyt4+o~ѳ'zCh߾}c^ڿJ@$ =zČY`naWqʾcǏǴ3СU8DPP~ rDߵŖMpOl~Iɡ#\\]ػ7z9:ظ#}͛={~יh5  T2-ȋlڸW:ASS٫O 0hV7o܀8qX-9;ɓݻv uɳV X.yO٤Cu={gOƿW9ec015q35dZ$\_zDIt nj^༯/b_)'++a'ƌ^%˼&'Nl&mARb"<;УgOv]amc+kk())5[ׯ_ի󵶼]]][X/Efk9~ӧCEECgl߾KxΟ?_ tض v[9ۨQAdDn޸!Twpȑp5 ={b6r|?>>b*YcƍðqM>xP(e۽;%&NYY af5ࢿ?N:K.444`۽;¶{wv+kk73-SYY{o½wqzMWt  bbbpe抔B:*62ܾu ÉcΖ.z9:ݻ͖e|<J@ܿ_gC>YbgCJKKq-\˗wj66tuuaٹ3:YZ%,~[t_{~wnF۸u&BkPKOOĀѣgO$'%CHJLP_9998'LaUaa!.]©'+WmL4 nZ DGEÇX***(--EFFػɘ1kB!Eg سgf͚%D=y{b? `PEkݖ17v}Y˗qY\uZ29~t ={EEEB'MƦ9gFXҡ222 җ"x`hd٫XYI56~o޼G<|CC,2RL)J2dffzP]PVV&q>b!C޽{Ubd̙ܹ#j;t.]"&歶o`ѱcGX~,,``hbw K">.qEoPkUUU@UU/bb^[Y[ ^^; ElU^z\ծgOƉqFz}O߾phhPVV{{wz]!У:YZB^^W._ei3fkD֚atxu&n\ׯ#>.N!~۸Ra0URXpw0c?oP#W IDAT{ñwotBnn.!8(${>#`gob+faĈx"… >|#j38w >xРcBEEE[XcG}hC}{hkkCGGZ7Zk,իWxddd +!-5HNJkĻxcb1!hqi?V<v=lvY5*//ǓÍtu>FII ***004GG#55U6&Ni3f]S0-K:4Dܸ~n`?}d1x<QZZ*tp5g7bŋx/SELPs†015Eo''8 ;{{ S ݐ<|>8h g777GI9"p%ܼqn)**rQ**)AQQ@Eob yUմƌѣo` 퐘\rR닫bgxW be],-afn3ss7UEEEUu}Ma۽;^Hn޸!8uuuqcl?iXҡ ~h(n޸7o"+EEEnu>E_~ u###;oiiw.ӑ4$$$EL ^x䤤FK.M6 Ə:Rq7$ţL^xŝ۷q7$!wÇ(--1|>JJxxH4mmm;cǏ!CXaK:4r1~h("":tm@GWzzz蠯OVVVldgW6NO HMMEjJ ӑRoƿ!''jjjNN?}@WWd())< =CdD"##A#)) 1ϟ#3DGE!##Ca5tB^={B=Y/mۆ H9j` ]ڤfD`_FFwBtt4<:Zq9ԧQRR'۷nغ- a#Fva$͈áG8-+((Gp?4<#z3 Q^^ZMN^^PЀFՏoMMM &4Y]CPVVP٤NFFPJbJ4rQQT3';D5k*[TTTվ޼y%~-kl5\YYYt >}V֐B #=fJJJ\dggyt4GG#::/bb*# 4uԄ5lv УTUUӈ:eaYs怈B[%C^^F042j3fgg#9) IIIHIN˗/+oUI` FFFPQQAQQnݼ7=7cT&Qc09ҡ*))Aӧx?z?FDxxcHF]]lm{ va&OnݺI9"FrrrDd~| ''FYYY444񠩥]]]AUM ?f RSRסLMMalbccclllX mģG]5=,II q=8ҠSSFư aٳ3VVVRa8wʮ]GrDCQQRabjgx8G||<^xX`A| qqM%5QWW vwp@0mK:0@`999(,(@II QZZ<#TTT ''D53|S5`$UTf˂A,M ۩BEE***ЀJvPQQ Zm|@[G70J,՚]2 0L]/_u֮]e˖I9!++ )HLLDjJ DxyyA1 !""Э.4p2 󡫧###AAAAa1 ü5ݻ{ni$0ۏGo>ܹs0c ӧ1Bk~,l?Z 0 駟 0 0 ¼/- ۏG쇳3\\\ؘ 0 0L튊PTT$0aV~ܹs1j(i ߋ/E- ۏGeaѲ/0 0oC00,@1 0 üV^+WVXYI}IhY~,l?Ze?\\\+iN>q$i """Fnݤ0 4=60mN@@v 055eIa5&aisd0LsS_EE#aaak0L3f+hi+|}}q!Q0e)G0 0M%isCJ; aژhYҁaiX aaf : 8 0L[Z:0 777J9"aڂ#G`ii)hay0mεkװa6K:0 ,,--YaisX a6{0 0 4ҁa6gĈ 0@0 V\|{|ᇘ={#baǒ ô90mLll,7{K:0 0m^0 0  0L[#0L@СC1d)G0L[ ܿ`aa={J9"aiz{0m͛7n:K:0 ,,,,`aa!0aY ô930 0 4ҁa6>"Y0 V? ,rD 0 XҁaZ @FF9;CVٹAɆ2ܿEYYвry#54Z_CEEE|>Tڵ*Ӯ];q|Tɡ]!##EEE(*)455%-054DQa!IZ ffͶ?Byy@NN ''(GII ,:vCo\/_fPPP`IaM`5Y$'蝶!##5uue^XXWHII iiiHOKCFF2ӑWuuuBGG'NB 5}:+@^^@8 P*((@IYp[VV*+222PPT<ԫ}&WMLM*U?XRT~.k|.W뒓,eyyy(--/))AA~PiLPPPχj> j %%%x011q>uTd2r<^ PPPx14EEElݾK4 |=#G$n$edJME|MCCkCqoa;#Wgee֭bZۨTҔPX2: Zs;Ueeeh@MM zzz\!yDvDx8HCĉ y>>xP5P̯tfxm7">xzBN< vՓJY(\+- *߂s% %σsot#1hna˖5xЁk[= TwjI\\\ªA|,xK{ߔ1`@ؿw/Zu^PQQ::w,C?u*[]juY=y '-%KҲy!3eoɭYF]Dܵ÷+V[M=@o lkȪD\]ٔL(jۘ4e ]\D ND\'"(** -,`ffCCBCnG/yBwT"˹3g0g^XmF~7,믹,j3mdx9%ڷ^sAJCS{ ,kny )q"$ 몋d wy⺖;_ϑcÛ?;4m.E(VʎljEPT dd)Deud\(T P@iiI$m~4g$dfh*8,- H$s%{g>ݬ['jʼn#G`0`4Qb4ŋ0Mf(J8⨁鄑quJf3JJJPj2yu >d`(6C\dC#8HT5F,ǰ!21l0LZ,ѣ˘3>6qTp_%b4 a6֣k^Zb3N0%{eV+%FD">>8ӎ&|Vĉ>?6ދFIIz ֮^B@  }Pf111/_12Bv׮^ RXQ^=hH A H$„IZX[7{6gM\͢Ŭ>LnD_}s^$-&TBrJBBڶkG |IFOL$0gߣGcz !w=~ٳAÆTͽĵWqӣ_VԩS?GGN/8‚jJByy94 NK j&=v & (++7np3Hml,t:t:>mDX~ CcٰfVF qW֣%HhR\ZJ,!!!qh4RDFhT*h4hhMu*GGGSߘ1SOǢ {NUBWq}A:b#GZƲwKT/L }Ɖ`۩gqpKX(':zg0** qjdt":}t%P8^qc(J8޼ XW&M»+VpPIa0PrD"HRT*hccj!JѴiSQQQUu2 r1{"V&Xd2`QZZJ9<ךhĸDt:"_X8i&9kp8pE8Nr%TVVVutccRRjhƢwCV-˗QPPK/"զu=hĴ3!QRRSx8~9q z=a4}|A8Q]xV*O7\.Gb:^3dBAAA9Ms[" !!GK+))359u qqq>b}U^@6m`Zg>ÇU]'{%ZtT*\)>>M$JEDb1j5$HPn]j GU ,` kBAK$Dd 'z'Eii)Nj9s8z!Æy}XZ]0L_0LJ-//(bRSz{%JsGz~0(v 6ןlvs\IfAdyk_~AEEEBCЧ QN͛Xz5c^}Pшbu: /.FϠS/.v!X >CK)DNCFPZ]N%Y =;JSn޼oGlH~9/e#aLfHf}ė^c!^p2롇d 8xk\7'`:D\jUF`\cZMSD0 p86())llhT*oH8hccZM:Jo 8/.Fg LPT}JxrhAc]}J=+W@srFap DVEVKu?K$*$** "z_bD6r ɵ"X,t:hn*:&Z2`7Jfe2aZ t:~{VZ4p11PT„Gk"d IDAT{PXXK/.Z(4l*P*2H]#^O z=^˯_N R `0NԫW HHH@Dԩ[F%&ȳm0`Zjj`bAYYYUg0BC"=lf'-3cL%%{LiN!{H\},-ZPQQQP(tDp:3)ׯ_bAJ`q9GJ%b\mZMF=5b=1ˇS At VꅩRA*"mt9i^!O1㡡 L=ZyCYRL=5Nj'V՘`!ɨ':<VTTxUU}h4n1\-'* B*2&t;E?k9+mnlNgVQkT ItX,׻71'PѾ`,_v߸x3:7&&,G3&br LD(!jCՠbd߸R50vM$Nxa4ѰQ#po'+W0|8 QQQp8(u+`]\ĉ騾STTHR׊nIkc*)ldPe1QTXTX`u] psL&j +jE…7`޿6rš~TZ(ܸq8XAۚf7MܼyEEEYR oh4BDWN1"HuޣGD`|lݲsf @DłgAkYb4pDU*UU+ ~㾶mZ KL B W}\r_ V+5j2j v5RSbV׌ouᙜ5p8с+V2U(r9*++Q RF`֭K尠KPfzFW&MBtL ff")) j)H0+㏸Y3$&&⡎1a$||sp/G2~(wP0"_H"nz뮻G @޽aِt:O $S5$tUFC':uCYYT*ѹKk0U.aCSjJ\A:G ޜ9ӭ$zк\3\9nݺ˗s4mI@ `* !gϞś3gbyϥlZͿ={{>X ?/jrx>ϝ[|c),W)GEP(' :l5;JL`\.Vi:Dt`t8~8ԩwD< NځB‘tZInbn۴)qŋ$:_W48)vuVӡwsG$ 扯7&I% ώnݻcsϡx% 5]VVV# #`=k)̚TJ ~kW׊.:rTQQQ-wusW3SH9= ӳ˗dbL CTTߪW5fҌ GT^}I. r?t)vlۆ&Mb`q3 2M,]u+P{)Z!P^^^c;N_X1a„j:* 71M@+2JT2, ࿭AG{ZFygO<ܳguFHwU,з/~>y@NRS}m⾶m4BJ P^^RSD MbH8ymʔ>`~Hۗ#b6#J&EkS*$TVV"::;t})Rq̛}F%P*T|U7%u =3;Ii5IÎ:!5Do]S_r jtSBVjW r,CRN"Uҕ z‡JnH$ L+RP$@"Ɏ%e $"uy2O^/ T.8"ڵc%6A@ XL&D"?$ p:BA 7oR+F#'сr:وR`ܜl+p<Jvu׊Ap:0,Vgeڎӡ`O ӇLjڣfR FBUU#:קjEzOR,'tգ-..v+Cj׹z* zOH@tt4U"&!!*XҨF#l6U/Ce$d2fUp2K/zΊW^ſ7mbt2 DpVBQ &8 %jCZK 0J-"͞N0+H? E t**%:zF4AVWiްq:f]q!"x+TFrָjrwPU5%3"Hj[111"::;u""qqqj:7aPXX3[EE(**c[Xݎ:u">! OH@:u{е[7^%Z5611>F#or[T钒\~hDGGaF!:m0hJ[`iFsg2PI&![I)U+V]w[N I" qb RfA& @HY8@Ee3*HOGRUUDrtA6mn#H#@E Cƍѯu'{װ :>Зs .jX-ZԊ;r43ſ Dp@':tЁ^&@nC&C$!At=3pOFppΞ=ٳgZjޖ DpMzpdp" 0F^O+Ps!}ƍT*}&$}wNOL&s 0!!s|cr" ](jt~E6m1DP@LHJf ed!+nݺEUҥ gA$Q.N9+v{ ݍ$\E;IWI t`D"b1P^^R @Bgx[ALA* Xr:zץkWL|*+l( y"h>\J%W$Ξ9Ytzp#gL6םW*(h!PlE LF9jUOtrsIс?rNz2,dU +f:T M x%N~ 7oPMg5%8wBgiWTTTՀt8~g+v˖-񜏯T*-MGI cV(0X I^t4x0vDirXf!Aޥ2y_с7gڭ nNPAr:r:9 D"Jt JxF# ]t8r߶vX T`2xB!rsC t8AStH$r[~}O;(rss1w\={볬,D"]m3< 6^zxѡCHg$Ӂk \.!ӁgPb6hMh4I6W1y4[xŵWnc47R5EUp8ZAkMO/ ]tH$ `g.`^9(l yfgg#??>,tW^y>`H9Xrss1o; OK,SDzErr}{:!Nf* V|rL^t \6m%K޶?J?Q.A,W'KK Љv+khbC턋bP}&N'4 JKK"@ zDzBQQQFHKK AaРAn.^޽{u y l6(]$''S@It:,++ka5rJJDF^Ѯ];Nb4M rT*Q}6SZ-\TD, tP2A|!x_XWhsク\P]%3E>DB:%%%tܥKHϵ6i&c޽xǫtj~"V%aƻ:Q(*ФIzV崭 6UrW>srkir9, R)'};IR%3*f3h,@> p8l tRxqAdggcڵ矽‰'pX7o:w}k~!//[l~ǏC,S6mڠGBA222}2o˖-ϺuFLܸqK0 J1v`~*tx"UX}Aڧ'JR$&&'8|Kzn|%Ua$iBb"fϝ[8(| ϭAR+yNү@d{l6 `5!t:g4еWzAte$`NBq?t&(A`np1Ďi&4l*uuxeee_fТE ?~kѣGLo֬pҥݓ1c@.CW&*w֭x'(ב(K ~&G63'tz쉷z o&RSSq˗/.!:0%USaĆh0yYx"H$B W 6UNL{"\j S320eНlr:t]Hy&Wna3&!%$$u ?mڴ xovСCPT^gϞ^gu\V Թ3z ~-._ J(X,xC~;@9Zl,deea̘1~E@!޽;f͚9s~>}:{61h ޽SxS"T6 &@$oD&MиqcΡ#&\zՓׯcС:t(^yNZ-*Y" uX, sN@PTRX8ۅZ^RNyD"HܒYt f lԀoƬYAϲ$n~pqƿ-[:n8; ǏGee%>cU͛7G>}v;@CӦM1m4L6 C/ru:xRn]<Ӱl8y$/"5j\&M`0n;N^=t:t:ڷoɓ'(`@#55-ZFB@1k,V"dԩSѸqcd2$%%!##bMlcs݅ yP*HIIsNtjM4o8C䳅]+,9΢f8z(1bĈ#&":El6cؾ};+ۆj Kڸqcup)9G!n$P=k׮`/Ug^$ ׫N$ɻVj'H|V+++Bl1&*Hft`3F,1.Ĺ~B}W"%6Lpxtv&ɐ .\WT~(((@ǎ:'{bgϞHNNƺuЯ_?x}Fvk_C}@qq1:u|9-[DNN/_رcTv֬YXhRSS1bl6;v +WDjj*礧ܺu ݻ74hTs!;;G#G8OĉxG1zhb>;z+裏B&aLek dfq^j˾X,ŋE%KӠlĦp\.]k׮`/]vhժUV ׋Mۉ.f0aV^ogn/ӉM/_h3f`͚5awbǎxk}B^@V7u:m:* (*^G`2jw'Zj:+{?TN&UIc_^^q郳g?tbΝ^6 Xlg}s Μ9k{O233quddd@P gc.^ӧcn5 8σ :t̟?yyyϰn:L>[lUKRx_ॗ^”)SsN!99sSOڷoL IDATk׮ٳ1sL[ӦMѣGqy9;;'N;#/o֮]JJgp6l؀O>ׯfùs?cXz5~'hZىH&{_tՌwzz:L&vf{ C\!'|2 >(Ͼ8bux"ϢrL֫W۶möms6+ 3g?w[/iii!9Nm-0$ӧGD! zN$i0s:).GtD"ID"F wzIϝ͛7!Hl6]tɡ^紭G ( ޽{׮]Î;O}>k,T* 8iiix &xkܹHII)Sн{w̞=o6U=" ڵCzh"̚5 .ŋy %6\xCuKd)DWR+6ow_Ÿp|ӧΜ9_:c$''{fff"!!†Z˗nFX%!]n&Nh"urrr0~x{hT*ł ^b 鈍Mfu￟Zϭm!W]gIJBn%MOOH$b<n.fԩ3gvl 8&LرcaXСC4i҄q=>3f -Zm"==nBff[€I&aݺuXn&OgrCh m8*"Wd }NR6ktt40'FYYo|6//t' ݻw7|B$&&R}駐d Ct")) ,ѢE ϓsNk׎Z$rw~rJJ6m~zsF\'k׮E^Or |+j 9TǞ1c{"55W\z! +1lڴ) `cK^b|C СC!PNoߞ1Ꞟ.]`˖-8~8>m۶a8v5kw[b֭>?2e uR8PPF|vܹ۰a9Q(ܝԌw(bFGÇc֭4ijÀ*`p5L&p֭| nܸ RÆ X>f[oa֭믿P^=6l@ff&V\777֭õkТE ,^?8v܉KԩSSFyyK,֭[qeh4-Brr2s.Ct`^d~#åKz>׬sF0m4W88[ۧP(аaC^9\pKHoE6mڄQFa͚5Xt)蠟fW^СCCR刏 0"|ֳS'b+oߎcƠW޼3-- 'NĦM(a(//b v„c*wLh:U˩p pB(6b1M{[n,u=CB| O\B32+Bu|% U[M;s#^+_^ps!pB  J>WН@BzjB)W(PRRBl\^A2ذaJ%va۶mxxenlέHRfnu:zFi$D.:$ Š+sN7'ׇ~"*wnǿodddP#HDD4** ZOv{y_~uY&z۷ѣ֭J w}˖-X,ѫW/eso=46-ɂ 8[n:~)t:RSS &w ==L B͞WVV5k0z4Laȑ3gFX;纡 Iz0(]+**^;+̫+[aЗ>}tc;.+{d2`tpt3vk7e2˩>1/ѡ8,=*tcϞ=x'L}{E߾}yLnT*9 YLZG[bӦM7n>Lɀp8a"o %I]}t:l۶ 8IVVV`0̙*1ydxW:pB%*aP|+4fu\qee%fs;.n$z 8l]btrvr}IN6NMOa@:}nBy@ v6;|pL:7n-:ԴqdtZId2At`uֵR`^cɒ%:$ u?w 8~8̙{bÆ W^~e̙3`* |Gؾ};>~ҥ v؁{@pIO,XLc͚5hٲ%-ZTJŢs%%%J}v(Jv!НJ v!B x> r:ԩSS HDF T vpnݺիRRR J?/Ĉ#jTH"x%P&q{v·| 4m8'̂ >{$1SP훩11WᠪWhZN$Zm Iz0(p$:wnh%;t#WR$L~HAzE8Irvj7WPO".qF}x?߹s'n݊3gpΤ)dFp8pIflRrh F0̂rl!%Mht|AAP$b-HP\\V {wMB,W^8y$k@-^{.gbD"/ɗsI\x@(nL.͛e'_HKK I5kCzEٳC3\pv;r9|-;xl,1-plg6׷:rȤ-r!.$lgMzBeĹs0sL >[nņ 8Y #@ER6S񠓇**e3deeaƌXf׌cMܓN*S7o;oK4_(ؽ{wuF8Ӂħdj;w֭[K*^m6d2|7(v }M^qq\i5+(D8Ɩ@.PȻB J@qa(vS N7|ѿt:|Xp!=r ne6 Jtbk58p 6mZݧiIҒ)..WjՊt:!ˡ/.ʜ XӁ!}֭[KRw 2{N:Ρ\Q]ԦЫys:8Nl6j5ݤI aժUXjur9ݖqpQ|K23o>T8|s ^?ާ2\QQB^*ۿ@eРA4hPuOd2<裼a20uT4n2 IIIȀX,vmڴ "KT+,,ċ/FA.I&YĉxG1zhbbt 9r$Zl,_ıcǼ:ZcƌAee% ]bDÆ )d֬YXhRSS1bl6;v +WDjj*~asH$DIt:+HW6At|;$lR-fk_"+R)6oz;zyWl.taPT `5ՍU_Wt(n|8 yHB6ND+MM)8d2*@f+**P*+8ϟZ /"|Ttt")) ,ѢE N߇>ljʕ+HIIٳYYY8q:]RˇmwҥKYwRRv%q9Fvv6N8wy*`N xG^^>sЋݻ_ҥK1{lm뇕+W">>0m4$''c_|kMtG$+H&I @@`f bWHe2a^z=AbR{5VlWQUh4bfUQO"):cxt`xWZ):TN"* WqM/D&) m˖-hҤW]X6q"66R_N\}7nAҥK*_ĦMЭ[7<(++5k-Zp1c Fclڴ 6K/tv؁d\HHHf=YfHJJ¥Kej/_Fnn۶52!Js:H$i00}tL>YYY~'Sx?;w.sNVVD"֮][ gHt#ϢD6S8 Xm۶a۶mغu+lL.fϫvcU•HRV;kE3=-:TwϜD(RCpyNNoNłnキm6tvB߾}l2|TL>ך' ~:vyyy8tPU ٳgysJ\p[%̕^I$4oyyyj .^GJJ 7oaÆaժU^fKOV9L&,Y%K`~+t-7oPӫTJݧՑCO$)N,2HrȐ![袃_ kdfmFk3|BNڹRG IDATfsLfB=(%T^:*JpDTz*<Vc_L2 ߱|r+HL@ŠA{nIAd6 hjwm"4UB\.uHLU%6WAPlr^j t 7/D"۟\.GzC6''fqƀThO~C҇aCA++$q:c࣢PN>f\z=z@ݺuCBϳgB$)T*Q~}cǎm۶ C.#>>-  6ğ &wߍ7x_ 6͛Xfm$ _9VKU1cs;ι/сTؽ{7.\-Z@P 99|}U&a[qTow~ltR >SOQ/lB"R+ $YbjPE&@U^ RP Cn Iɟ*Z!PQ9n5vHR7/A"hthwXx1/^7x={ľ}зo_8qq 6@$!11ѧ@Xx1ؒ%K}.epZ,lPT^s!P"ҥKݖ;N޽QQQj8}xuPɓعs'y| 6 Xlg}/1z\=zm:֠Ap9ܹm~" ?0`eҤIXn֭[l)Go߾?>:u˗GeQnjEm۶HOOǭ[q"D"A>'d SeX J|*W d1SpĶo!.>]vaؾ}[[b׷X,PհNl"k"* J]DHRs19He2z"k׮Tn9s`˖-Ά7|~EE6oތ=zgŅ p14hΜ9?mynn.K7^!l   ϟf͚GZZ0}ti'N?OFǎ1e5 ZO?{gFFƍy!##;wFLL }ǚ;w.RRR0etgo $%%y .|r7|J @zz:&O_T@ ٳѴiS 6 cǎҥK1rHL8)))x9EEƍVZaڴiXf .\{ * =mI +Xivx#Gŋظq#6mڄ_~o&')) 'Oą ?bTU`Ŋļyp! K]g̙3n:L6 GYi=zP%zedd ##}*)}֭[ӧc˖-Xjrrr+yyyزe >C?~bׯgu SxE9ٓ`A hL&v튅 u֘;w.FsaҤIz|``#1FJJ O{ =@{|D>,v}uT6o"o:t@Æ ȭ$2q[9N'V^z::۷ɓQTTHҠ+u׫\+b{B"I\LD` Qv>E:—Ӂy~o7n@zz:T9|ѯ_?Xhl$'' %!QBNTDN2Y 駟0||/:`ر @&aXf ZlEA*^=Gq%bujZ?~˗/ǎ;l2b4mÇdz>;=FJJ 8_۷oR?˗k׮=$$$3g݋ 6^zx1g^e% >#l߾| JJJP~}t;vs[TJeee^b6[oj|;&5iiR)kYer7DA.* \Q .W@EE" EؕUҖ6m֞'I2&MKH'3g̙ɜ=vo III/jҐѴiS*HpU>Qzޜ,X۷oӧQXX(LΞ=[W9Em;J T%GfffҬJD LxaLvq?N(()W Ddq ׭l LhB._\$* %v2!ĉ쭷ފ&M`ҥx}Ǟ={0uTa,(4h^ÇW_Ŗ-[e}Qh֬ meTii)뇮]?ѣ_~8vy<Sb֬Y4h>\.رo [nůJ&[.^:u "WF_Za0l&O;+DtB%łt 8~8w?!C`С_t)L&222`ZѡC\ow)S0tP|4hN<),D[ KKKCݱWd+gUy'1}:#9llܹlܣw.dsav}6K9s`k?ag}Ve˖1/`1p86p@kܥK۳6mȶSoݚ=r1#? 7N: 3l)!ۓ7n̼^o}FڴiV͛7 IQͶ@}:w,}ײTx|c#<" v=;g7u୷Bno̙ }O0iZvǗS2Ì?{l޽omۿ٥KGeZINNf7xcNbgΜ h[.]`&LOII KZn*D_1K_1z~f`?1qꫬWng?ׯg3<# 74h<;~88p k޼93,&&5k֌=>Ѽy{ IMMe1sknͯTf0XZZ8q"ُ+9={6kժ3Le˖{7={`_}wYtִQ#fon0nw,f6٬Yn9ƲC ΝL}zY-M7clܸqQFrL-\0RY^=[۝tYOh'D+&h"IV+|,JJJ*f/^@YXȡ7@Rr_JV`UIO.RzyydgϞU'\#URNM$ݱy:pBn\q{ʕ{m۶EJJ 6mڄsTX-ﭷLە-=6m/^~ 裏ЧOƓɟ7?zIU֓)..Ǐ/=װaà*qverk_ z#ƪ-]èQЮ];9s ,7ߌ}aÆUB& R"b:q 뮻9997o6n܈;vT #EH<ǑZC<wunes<|w:u*>sl۶MWZ 6L8{O?e˖Ϡj1ydˆ#VX,4oGԩp%ԩSG<Æ ôi0|pl6^c%3)S!6.]7hZ1Zz޽{1g+8y$^}U|6O5ziNfgh4 +&L!5koWw'zv4h8p#Q%%HIgcUIb 2%+KeVʈk׮WtTvhp\BE%K~4h~\p1o<#㐫Di"InPA ͐!CpB{xG1Y ,1BeJ^z!33[nEn݄JVʄWZ̔k'nv4lK,wߍ,<>)\QrD`UM6*B0ư|r<XplEI\x_j+[c/3ۍcǎرc~'Z[*"u.Ӊ3g`>th޼9rrr+|aįyURcٲe`aBRc1b.]S-JѣDP?[J`X#сHT;z~PK{RxxŪ+ѺM?n[Xa0Jrׯ݋+V@;f͚*, 'J0j1Xz5&Ny!&&&4URӁJ=x>Jg̘c̘1ذa:w|]W\G%P{_|Wn݊}lʔ^չx¹z0rH̘1&LJɶyTn|1b0h4'DOp@ 筅}TԮj Bɵ4zh]˗/eUƦwb{yNg=<͛BHȲeдiS?^իWcŊ8pP%&..=XDl qk+: "8:W'z^<oii)fϞ ,B租*p(ᮻ’%K7b!OٌSbԩa;`̙3wJ1cƌQlvolaÆ$Zԯ_)\#|"mĉ$y]S 5\tSIb 2%+KeV &rwqc#Gb̙Xbz]/Y)Rmz'0j(+2d7n˗/cٲeC=]>4pk[_M2EWB/%}%FM"Pr-V 7 y5bs"ID@Ķmۄ`nϟǺup11{Ν;qa<3~۹{b ,]/rJB >>^HHO@D {ӧZt 1DP!Ϥ$̟?aIN"S O:Yo0DT"):e1w\L4bܹ'1J8I4iX~=z)l裏ƍtPr1?ի}:\L>v=8r:eC8mܸ7nP[lZѶm[L6 ?2/LXϳGᥗ^]U:*#Noǎa{A7vUM&d2&&q~\^+6MvMGjʊ#}o $僪#yyy¿ ʕ+€PX+} Rii) \.ˮ'Y1 ng=h%{:F!"/A {tt@T qxLuxEck2U]7OѲU+ĔBY13f ._ xwVL"7P*8֒m%'HzCMO |}ե4M---ƴZ֧$| Bɵ[$r 6mٳgG:ue9rB5=^Ơ9]vUo6~5gddD5𽎪r:ڧ 2WD槟"77AҌ^W\Qd`LL 4m*d&$~38&bΜ>- Ĉbr!:u Ex^񠨰N¤^TEau khMH^Hb1NpFl^z0 X,W>֭$Md^G槟ɓ3d!!!&L#FҥK^X .0 M$|@,~gh]f t:ݟV̾k:u 0w\uMQa- p'2}"/벲ШQ#H󥦟Bɵ[$FYYY7n֭[N}"33[s1y<!1c0bHd}]a *^1;1` pC /1yyyȻ|yyy|2|}3o!lfblF,v30[,lenx$$$k4x<o6>Y_}Sl,L&L&FPG=&&fY0 h@#>>lud@ժ:J= … UTyyy̙} RŞ$\8r0 ΂hּ9;On$x^Á,pt£~)u^BD+AqopW_ĉ#rN"5.…hּ*Oq_@T5 IDATud~)xaJQk R06hѢ֭[WaӧC>Pr1 FSlPNSdD9D Վto)`cBĈ z=lp:xΝ;*Edk8ILL A oJn݄R\RၑFĉ$+;s ψE֭ NCqq1<j Ԣvu2e/t\p8*5AV":{Pm"I}o-Qc( :u(:&хOpMr}TjbƩ5 (wdABB/y:j+u6G+@|1 q΃`JR>7Whxk%"H_61Es3g|Yeϩ+JU`O߾h$Gբ]*P@DSV/DqDd %꫞~"r'+5Gz<TtW6#uz^t:4)Cp80D{Y\j\n7JKK)QixxŲ?Eޭڶk@6UGi* MB-G@zb@blyE(tpɒ\th4& Cp!uT6(:/,,.:*2>a-..F~~>Ti'4RDdiw P'?^ܼksy(]Y"w5a5$ F!PӁj\@0Lٷ/`_f>Ԗ %сRс " 'T6<+$B{:_ҡ vp˕&"~z V.I<H:!P K!66ab+ځӦM/BA4kLU?1u111&"u I6ltp`0PŨw(`0vSU!Ҿ2yF۽X$fa*tt:y:>Dq8(WJ!xoXD qQ)WI^rNx (+Vt PL2 ѡ|Bb~IBt-2A< ]}ECբ&(ӡfc2Wx!)Q]p:wMB"|'|O#cPU7Zx^!e\pvy/̙3->9hc0|(ΝgTڶ$4no9\.J1Ɛ>BXB͉)Jr:qq N$:WB Nhh\TXE AtqzV1^IՒ@ łxf!jET\ײ%`jbd2!&&qfG_IܛѣXhRQg*. ǻSPPw[lt:jp:V?KZHNNP6GD_LJJ RRR*x1;g^xfS=JKK׋xPXXl۲%h{ӦMbnyE0!Dдj GxɓfϞ&k bUWEK9T-jQ r𳀞^/y:ǏD>}Q p88s4ݰ'O.械Pd2!1) hڬvۣ^zZQNԫWr!4k\V,&RᡤNSKE+<6Ă'ѕfIZ"ob~˅Qen4*-'(̅sEX,Ǐz>Ti9J4$g`PU4"7nO?LP#:8!t:ԄՈQyGTjCNgOz91D<˖ O07ylHkpn\)(&ܓ=?s)T7܀$ϤĉrH;нG6m[+ ;1L#el٦ ?`GA;X "r8N6{vP[BQZv*<0!M$ &:YD᫨uCZƸ9=]qTb!O*Fzs2CWzJrz:P3gJ+ӡxʟ@D&Ok{q 5R|jx+F!\&"qcL2сU Ⱥ\.MխZ-NV*F*Y,ϨӡG 7+E3&4/z<*AO$ 3e!"nnǹs|0~<v [ϟ?{QN8B?w.`51<?_Rr2:qq(ȅ p#iuqe`mDؾk_{mVӁ#S"vݎ3f@˖-t:a4PRG qHgT\.W٤IJ9Q} HG KM9 3vXbvp_/Rl6[g@yIcbb|#8=y(L&ߜ" }W⅒uָAo.l6$&&aÆBXgiiSr _Rd܀WIQ\8BU9[EVm6@٠!???9z]]O~"v˃nGQQw$I۴m{ C,b{emSzݤG|/-(It/nq CwOR(FW ӡ }em7 <#1*F)S#N$ɽR(ĆY3<*y:A^Cnn.੧ CǎX(**Cp)˂'gN(7݄m;wp2q'mZE*mҬR|.^– px( Tg>bFx^ ]2ZVCٌ oh4:%>F)#!=?Ot:&6&S-ep28=$%> rH,/Ƙ =%KDAW;ρkC鄱X|zI=UoWDJmO_*HF\ih4*+׋g 8s57R(/I~998yrssoQPP7I*:,_>6i/~Ŀo/ΚUkPSriH!с Zᅬ#Gz!EQ~Qͪq|re(((j%> HHH%>VUQ H#~Js:Rb̙BH"e)O?-шh2`BfXDC^ )G:q*..d8A*xX,STN vN{7Ν;"y8v(֫УGUsKii)V\Ug&yjIYcbbW..E$HD"-1g%7_&@.lM`s , bR. Z)!GCP*0;p:v),Dtք!R],rnҥJ..LI;.wvo\P nmҐQqj#MD}EnǦa٠ %ٷVqM@M-/1@ի ǃs O LDwmd [b"_=~ر#t{(,,ĥK*ՎE2h q`UiXxk0`.w.Ly Gy=w>0#Wu:5>lpn*. n__/ /Ъcǎa)ؚ ш EEEe[B; \4\… y~}ĂRl L"A)^"(ŕ'@QR9հ}VAl+#C_FAQQ4n|hC(ӱ<N K|?c2`( 9租pY`ȑ8zfsdzQGq4,zh(4k 0[,bf Dqy6LR޹r V 0(񿹰͓'Ubx9Y^=X,xIIIj>b"/NɄx. N'芻Eݎ }SxJo bht!;/5B  YKRʕ+8| rPPP xqʕ+p_x47+QAE ?"ONw!?D +HP8)4|ŭn/[+_y `NЊWšbs8τ8 jΝ?:K<쳸^a(oǎ޻ZM\_M&4׉ ^#8$@puEÆ 1t(8sM5ÿ}Tv"ߜ;W; x% G9NHH>'҉GӡN:[A&Mp̙7/gϞEZ `"& !ry!7].~ VjU /|=@מ#R R\* b5aC4k {>ɠ9/͘M}۷+UO61Tvx|x[CAADѿdeekO񻳳%RUF[@pdqo`_@X,E% I\hT'npT|F,ZC;`{iXE z Xd@H^WѲ ( Z 8AADAJƌ7n]c5[زe CݣlAAD^t(,,Dbb"ڷo={Dۜ];j{ AB~Gdff @AqrxťKjhL&4iÇСC>h4U^~E׮]nKMCE/| 4 |ɨ@A\PhAQa۶m`Cݻ7c|2tR|gصkZj8t0pN>hRӐv:͛=z Dհh"=zyQ رcѯ_?@Νl AADWL8ûヒѣG ].z;v`?~، ^zaӦM8s 4hU[jڥcΝtmAn6_@K߾}lAAA\}^uV@Ϟ=}`С\@qq1 nat:tǏ? l6ow}~-Nd2Yf7n.]䳟]ФIa,gԞ3g`ĉhܸ1bccѦMXR㩧BnݐɄXlQ\\[՜Ch4Ȑm?//)))HNNM $''wx7xcM6A`ǎ(--ERR6C3AAAD+w^k3g@ΆAzz?R9s-[Dƍq7ѿݞz1vXӧƌɄglݺg"ŋhѢIO?aÆuh߾}H"77:ڷo>}N:t֮]ٳg#77~ȶrk׶m[z۷O{L4 ϟDzeP~}L2 ڶm#F ..DVVc5BI; xdt ի}=Lgȑ[-Z1A}lذ0j('ADa!70ٱcXbb"c'N`16sL}~SNeXΝw}'lx2dz뭐m DAA;w\ ZhQ)[C9ܵcv1F |oܸ` `1kP{ IDAT.ݛy< &CM;gfҥKeRjp}g 2vX`ov! Rxૄn'OĜ9sХK`…hԨ`ೊc+|B4t:n'6m‚ 0}t\Yf/ %BElOVVn-Z_E^^ nݺ!9%ر#c`ѰZxwyt :-Ç&CM;gjp}g B]AD#{J/y,++Kطl6*lsl6lrJM8QW+S^=,xXʳlfՓ{eXvvvȶ"77laÆL3iҤm r׎37=S {m6l`hd׿իӧem5Bi;,99=C e|ll_9AV\V\Ɏ9ms "r$!hDݺuѹsg ݎAɞ~\wuʒ~whҤ /^6^$Çq 4HG=o߾f;v ɖ@]> УG >iiiHJJҥKvZw5zk{żyлwo5J[o… 1k,,\ .ir@(m ΄2>s|gn [EA:v& բCvv69sݟ|6vޭ[7chIŋQRR*t#Phv9ӧOĉݻ7z=Ξ=9rCEzu y QckfСCeb? шEUw̘1xGp!ڵ k֬g}8qԩ`(i6Hn?x3rq&  ȣZt3r9ݻ˶yfGƍ@Xm?z(N'FcAnͿ/#8N<Āb޽-ZɷPHtlhҤ gƞ={o }%EѠe˖hٲ%o?N:UAt+9^ ٵkT sx$3aÆoPV *Xt)K#  T'ܲe ۷oG\\Bη e݋Cjbngc縳gbܸq8uꔰm۶m0Lܹs@[o K'K.v :._Cډر#\.{9G|ѢEXn]Ξ=ÇA>a.A_~Aff&233qhCAGCii)v؁XEΝo[nEp?uN> hԨz:uѣذal6֭[WaxܹsqFtFł7|p9rݺu8$:u ={ٺu+z=t-ٳ'~mL:7oFrr2<{^z|PlU{k'CXz5bbbxb7uXz5ЦMO>> +Wf-[oѣB4k O>$u}=LATo( u:gu]Vb3<#lO6rHv]wTf4Yƍل sNRRR^g+2e )S1VX{Ve7xcȶcܹ,--MFb%>|Ҷ9ܵ /0lٲlԨQyh42Ȯ:6n8vq}EPNnn.`h4f͚5k죴C |'B{F j W8p AD0&0?8z-l۶MqQ}8x :v숶mbΝt6Ax˖-ðaâlAAA\}PYvN:UJz1|px^,^?=^3 g  539dIENDB`bcbio-nextgen-1.2.9/docs/contents/images/parallel-clustertypes.svg000066400000000000000000002600101415626112400253630ustar00rootroot00000000000000 image/svg+xml n = total coress = samplesm = multiple cores Multicore cluster Alignment Post-alignmentpreparation Pipeline analysis steps Variant calling Identifycallable regions Mergevariants Filtervariants Variantevaluation MergeBAM Heterogeneous cluster creation during variant calling Per-sample cluster Full cluster bcbio-nextgen-1.2.9/docs/contents/images/parallel-genome.png000066400000000000000000000572451415626112400240720ustar00rootroot00000000000000PNG  IHDRp~bKGD IDATxy|LW$}'$ dFRT jG)*vBK.U -TTiZJJ M$<3?#ܙc~jͽ{s3s.ᅭ- :%K.eVVVlŊB»I&1gggfbbz222Nh]i_W_}j>~=Uvk@M6066#z-?_5R|:u imڵx >sSխ[ JakkoUUUx"~wS#Z@{Q߹s_t.WK..\Ν;ǏYfܹsQYYRlH>}`l׮]8z(_k޽{m ]HJJٳgѥKwݻ Ӿο|Å+]95Io?~h߾e˖]J244Da`;j*EW{ i7k*++ p՚nnnɓ'BөDѾNi zsFqss`ܹ5VgSN_ о}{̛7')) cƌ+<<<+V HGfΜ HH`͚5D"ׯ\|aaapss+ZhѣG㯿R?<ސ!CæMssshV^kA$au*^kt9ôi OOO*#HP2l7>֍V{euΝ;eo???XZZ}شiSyo qȐ!(,,ٳwwwǫ,exGGGc̘1 41V3dDzz:J [d KOOg,;;1ݻwYǎT+[2CCC6p@v}cc}ab}7 3׏7xEGGѣGq\\\VYzz:[d zQ;'))0cfVVVL$_y.Muu;dggN:1llر,44]˗m6^+]vʃ~ vֲeKu֍ 09rD^ƍҲn;mO7`b?~<䰎;2gggc,559991~'ϫ\9X|Wے>Ϙr!U֏Dž5vzrxDM%1N8,--ogsao̥߮K!>}zi `تUwsLLL3+..}vyݓ?z: .0CCCfoo_#fiib1x´UV1Ȉ=zTaژ1c=j90Xhh(fΜ9ƘjF Ç1аօ7duYlYzz:c_`-RiY\cڱ߿k@~Q/OоwQf5 aUUU ̙0'''֯_0SSSV]]-O>sT&OUb2ƽʱ(zUf[pq]?\wU_U;/'o߾z*F ctnn.>sxyya޼y~ǨBHHHx~~~cǎ5lqVXgϞaӧjz *yPUUPX[[+LGpp0*++k&711PN 0mذaj5S9"##y֭ UY7n~aС d ;vQF)L Wd^ЪU+cǎaҥ*-cM6d&N(P(bggܹsχX,ÇcR۷/D"viT%*:6zUf[pq]?\Ʈw^&zU j6 ^:tTTT`ݺux7VTTb>|8LMM mׇk 9r HbM4 ;wo{{{ųgpq@```t @MQP]v+..H\}*Cʮ M{3XYYW_JO>7;`eem۶)s}>~FprrB=@ݧO_'Oң3<'_1dž[uy~p~=.ruVzW quuEdd$]Y>l̑#GVxN:2gϞyJKKp6FFFeLy%yZh(--E~~:˗#00?x9ܹm۶Ųe UuY\]C4׬Y TUUa׮]>|8# @Bvv="w Tݻڐ-N:~aԨQh۶-M3g"!!y\4}UYm,Mosss8q? X,,^Æ S6344T/PsGm…puuŶmD?th/\P+'\Ce M?i6ћJ˗;}PEކƍ*/k'''+==]6U~QɩsZ˚{CCC֭[z*V^ цh,e]C4c(++H$¨Qo!;;+V?~IڲEv'N6ΝիWgϞ?лwoV1_c1uƨpq]?M}(қJ bbb[#5w7nX… 5|fVWWcʔ) eî\`/Z|9b18G)Laaayq9ر/_FnnF|mhv4}UYmModdd`ڵvuYeܼygCNN[o~G/6OHHGlSŬ& @,U.!.GBOc|eQ}F)_+W;ƚ5kڶm+NF6v;۳g;z(7n7n|Lo%%%)*1;Wyo,Um~:Qz4t3ڹYKD۷/۴it:u*k׮311aL*kײz;vޞN:hVZZc_~a ;#t8/YPPaw5_~~>1bf, mڴeee1OOOLMMٶm_|59991GGG"""#ܹso^!9Yii)ܹ3300O311a˖-Sb )CVVRA,nݺ), uD"o)QfnlǎٳgC ,--Yll,cΝ;J .\֥Y=-eYn;m;}4 f͚5cO Ჯ]Fuy"ڶm-ZTerrrXXXco߾A{gϞͬ#7oyrXe˖vWzzUe[*.?~,t*BQ1ƄN|#Atȳ3Zh!t:-bxyyҲWҝ@*n T͛7ÇO5&MT[HTRYY gB~׽{JXLWp/033:B@OnzlS%dĉB@^qrrD"ڱN>!}`JcQɴi_ jU@$==111hݺ5}]!c%U g1@$Zt CNN(t:-? :uicS`'"D֭[T={+==yȌ-FT{)5?U gT $DlwuDFFbǎj"hL!bbbQ9!D !ɉbL:U4+nnnH$prrR;&D7u ʴ@ JJJ}B8ںu+n {{{tItHر#&L >|'O|mժU+mRk2!/;w:҄$ vr+W|999:l,[ <@vNP;V֭ѽ{w=.\i~K.᭷ނ3LLLcڵ(--FDD|}}###X[[C"`ݺuPX+W ׯ#<<@PPԴ o#Jqzc733Cq!N_ĉ>|8all L2Eތ۶mX,Ƹq0aTVVb׮]J-**BAAK񗞞X$$$!6F+m۶<|III@*++addWWWEEE8y$0vXϕ+W 777>>>aee3fO?9|}}d"--M>,aii.] 33iii000"_~rr2t邷~[᝛ׯǼyA׮]áC)"SRRСCHOO':uꄤF(56;#t ;w/^Tk:ڷo޽ sssB$).mڴsDdgguϏ:U'!кu:ׯn*g8QQQ@||˜`ؽ{P(իҥBBHR޽Wsssxb̛7O>ԩSe_X`f† e,[L!Vyy9֯_iӦ@SL9s HTp>#DDD 66V}UVaxѶm'NP%(('ODBBRұ^ cBddc *z޽ TJjUZZ۷o lmv]52cn ZŵFD*F^7o:9K,Qlܸqزe BCCrJi&L `С9sg'O͛(cX 6@$aU[[[QUUv 'N'Ob۶mVtI>1P^^; !z)^D?ob>|81cƠW^󃗗W' lܸǎÍ7j,//WjJO]Fe=2HLLDJJJsΡ xQ3?Tzyb֭~i&j* 0@qqq4X4OlmmQYY}!001xfΜݻw*:jرcHMMlӰj%%%3f ,,,W<2fff믱qFlܸвeK,_gϞŠASa֬Ypwwك*1l]pV͛RbccM@B4$??x___!DTTTի022ReF DС 6y) KKZ@UVV000@Ϟ=W*;ʊCyy9O IDATW]] T{y@6"9 4K>|w楱իW!D@*bСJ1j:UԚ(`(..ݿ?~G窤D1quu5-Z[naȑP*m۶A$!,,"cƌAuu5;bj;z!练qD%h8oѽ{w׮]ñcжm[L[9r]tA۶myȐ"4B4bjBNw =:?D ]v !D"mt7ceeDiD;/8t Ç !Xܾ}SNE6mNbҤIػw/BCCNG`ݥK 777UUUr ѭ[7M:!;{,gϞǎcpzGzz:5k֭[+zQ!UXXToΝFVV/!5-Z͍xUUU}6"##c+ HR,]TeН@5*'D>#>>+/1 gHMMȑ#yGGGTWW?kyFkBB^;#DyXl|||`aaGGG;ws9?v܉^z...7oBe~H$Bll,ك޽{ Zcaaׯ_;ӧOy1D#z$m!u300D"3/Hr.__>Z|7orT $>}J !PVV PƜ9sxȊݶrJ<|uHFٳgHHH@^0k,@^ /_ƀw5QQQ`{www# $%Q`B4#==Ro/bbbB^k]6)!!Ϟ=ƕ+WxwJqiw ]vA*/P*6@@YSjODf1dՈǏyGIOOGAARrUQ;}4LLLdHԩS077_RǏGϞ=މ !wYEEEЫ>gϞ!zyuu5Ξ= Ju|.^@5:?;hD߾}- !dbbD:|'aD8qJJJ`aa!VPP Psw[nRBBΝ;]*īŋQVVԣ`pttD"Q= @@X$&&bԩH$BCСOZ-BH {{{̚5 _|zꅈ"11CTTT"<={(C#&&FFFxd@>:s8&UT 䁹91"!!?:'O"00P,addS* Hv,On􄻻;LMM.Cga֭>wm6|:S ,**¼y`ee ! ~KcFRR/1 !۴i5m/]z 011kע@mƈ FFFD"uPQQʕ+D{{{XXX ((jJ8~xD"/cffݻСC'0|p2e ߿)NCd?H[L#66A?Fbb" Ԏ5k!3?~AihǏۜ^&Ν?7o*DСCaff8;;?C$%%sΨ\]]ɓرck.y+WnnnɁ|||ׯ 3f~ sss"//055EZZ‹e񜜜KKKtHKKߏ5.]ƞ={V1o}s9s4A6M/ lLUU VPQQxtU>Cee%v kkk5 ^.](*,,T*ݻzj+Lŋ1o<0uTlٲׯGdd$,XsssYalٲ˖-xyy9֯_iӦuVL2sApppw.\>Uho>bժUؼyR+RM&'Op SsI!2X\lll MMlll;e׺uk׽xHJJB@@ƌ^z^^^ddd`ƍ8vnܸ!o/(S^^BVyh֬ ??_X2HLLDJJJsΡ u}qpUU=z'N`ܹ7nlmm1l0rHHH,mתHBgkknݺO>9enn[i&{4iV]I\MӦMkkkdgg#00P#|||ԼO"66]v;#t:腂$&&}jOR%ruTWWO2":t@xx8bcc=z@Mo[KKZ@mPYYӧOѷsHRTWW7x'O,hYB4T*#ŋSN!DTVVb̘1ݻ7r'OFJJJ ;kj*1ŵ~9߿?isWRR𨸺-­[0rHy1cu >z(>^rٳcǎ%Sh>q"##rR!>p[t~~~011kp1m'O̝;3f@>}kkk$''Ν;pqq pww?[nSޞ!Ċ+l2G³gp9ܽ{SAA$!33 (++Cppp/-["&&NNN:B+ۙd7Ǹޠعs'Ol۶ hժ0sL{=4k Ѹtlmmѻwo޽yRuӧڷopttᅬK;4fҥ۷/6n܈s!11h׮ƍy8RرCoX ;;; "": IL}wAFF|Vu*t745333/njAֹ277ךH;r)'b/Ig/hVjj*>3xyy؜9qqyyyBCXHH,,,NhԺpr]bT $DC]Ocǎ033S+1p@2#h_=hc&Dsz-HRĉf=HR >S9NhB4_~Add$OcB#w4Wnݺ4ne]tALL Zl)t* >frUk: NZl)Lь:VI.222D"A֭9J $!![lT*Ŕ)SNp!b/{ !kݺJ}i!!..cǎŘ1c{n!D/ߨD׮]1.!R\~СVR '"D TBc>|HNN!3B6 J1aNJN8Dh?ك]vEܹ!D; 111:B&4z !ヲ2{!H@CG~G:BGvBrr2q0!Lz*bccannN@B4$11x%<<\RTT7oڵS&P{"B41Tݻo޽۷yGޟ Tٳgs*GWr '"D7ѣ֭ڴiKLBcшAݺu:B?n>!! ___ Do0 Hxyo0@@Bt$ ڷoϩ&8|0 !͛7Ν;6mZj%t:P`ŋ-[R%  X]oڴiDhCK_4hyIu !1rHoz:B9c!!ѫW/Abģ> =͛7D"ًzNvލӧOcرӧB8Z~==zsAt!¡'Ob֭޽;U р2?055ENԎ7w\"hprrw0%Yn݂T*ѣy_#::EEE#テT*ņ 8;jTNf}}'>Ǝ kkk^bBECFDDDw9 wBCC߿?/t H$tܙxT $D8::B"ݝS9L8ټy3/L6 BChŊx)-[333!g%U '!!!qA !:ɓ'qо}{!hLdggE\zNw0!T_[~=叅 !//R;wTN=! s%!Dx;hᅬ7|Ak !wBCF :T+H$R;c D00@ WWWH$p*GC'~)nݺym۶BCᠺ .>!znpy;w&D pm١M6BCBwA^^Zj͛+[znd퉨w0!qQHR,ZHXBIDATCfm|rHR/Q%p"k|J >{"22QQQj"hL4b…C˖-Ngo^DF9R+vvvH$aM-[D"=r/Uǐ+WcǎŮ]NGeocϞ=BҥKCDEEIt!O>5.\(t:a~ǐ_~"={:X !zѣGHLLݻwՎemm5kPs-$&&ǜ|%-[<")"DTu֩ш!3B5kR)Ξ=˩7 ߿?ܹ#t:Y|s=Bdd$ڵkw}WxyBNc0l07nN||D=zt9bҤIpqq :uꄸz{ >066L9#Gзo_XZZy z>oՈAf̈́NwGnRf3ښ3fW_}bֲeK3g2ޞc2www*ܘ1cAAAC b ,`bY[[ ֹsg:cf͚>}0OOO*䚔~ޜ,--+|}}:uhݺuL$m۲ӧ f``ؽ{OfllBBBXnݘH$!eL" 6ի ܹ3BŔ)SD"a\E1N<0OOO0ǝ;w؜9s>rYNNb6l0}We.SSSŞ>}xbVRR"3lb5oޜ}WB>oaX֭Yuu*lɒ%X>mƍ VXϟglĉ e? {w%&&2֢E 0'^JٳԩS!吕ϟϾ S!{6Z"$$;ewe"uE5vZ>}`cƌ5-11ִb1ƘD"a˗5T +NYYDK0fhhRRR؃jڲvwm۶Zː-eZYY1HT ,!!tB~:KHHP(pW_mqBB rHNNFYYYԼE6gƑ(]E&&&A^^ΝCUUR믰 СCUEQ`B4k͐Jغuڱ;w!D[7Rׯ_TN `bb"5066s5cx1LMM^0:ƫnhZ}]DR&//ػwo匌 ###8::h\zz:"##qƩzw 233QXX[[ "33EEE5D kSammlyƘ#77Ű=|WJ !wOnR6???5C4F"Μ9SkZjj*rssѩSF6'OZ]R |^/^=!M<SNΏ3NVpqqD"ڱN>! M' ,@vv üy:u|ޜ祥={}Щ7fϞGXXB޽{֭[s*'`L>6m [[[̙3pss>*:0:+AKQa#Q(",&B,gqE6 !/ qH5f` Y3¼\9w~>g F@@x<JKK!!RBś%jjjp #%%eDιxbٳqqqH$7oۋ ( ۯ_'OĥKYfuuu?q}}}HOOCjj!d\P(}6\]]D2#텷7x<;lb?P*Xnݠ4RSS HRdggW ,+W JӃp\t `λk.aժUhnnӧ!J1i$ȑ#(,,DDD&LL>۷#HR=}WIC,㣏>28_$NbBƎ`AosðL%ڝ;waooCY6mŸ'8qB=tG_Xr%VX<2$P(RDKK z)mG:DkVVVHKKQ3!0\N栉!&!D<o'B4@$q2X!Ĵx{{C(^utt ::|>IIINZ9sgƫjt!Ƶ@f 2.ܸq?ݵՉ2```>>>LK+x"BF_TTb1JJJ UWW$p!dH$թDk!/_UUU.SEy4BF3Ҍ/4!_i>!I iv0!lԩD4ihv0!eYa7렉!DkHHH vit!:'Nb\#?1 h,Gc0ZoyǫVx"BFQcc#d2:;; D* 1!dѹ/M !ZDPb III(++ 3BXX ܗ@5LWQQbbbPTTdp,B`fzC4899իNqA _T,aBLĽ{EEEE8rpcƍ pUܼy=^{ ۷o^bH쯿>3tuua֬YCPP/))CPYYwB  00qqq z])ؼy3 =jtONL8X"# wE} ;;;_~%Μ9r455xP/O> ___L2wEii)P[[z]0k,J׿|raÞ´i{{{444ԩSJ`CC= wwwcBȸtR|ᇜĒH$+_ILB1 xPDbڴi(//ǔ)S rS'xuuu5kFbdeeapqq9}cؼyqSqF[Xlyyo5~GXj8\rcŊT2J!0sLXYY+008<w RRR СC3 3H ꫯtNĐ/"nݪQmذ"|Ͱ꒓0 ֆ[nH$|uM&2Ν;X \npb$%%ATr!d`Y/_ֹ9IhI.#%%EEE~:5>s"#{ܹdv|||ۮ>}c $q}|9=z{18!dluE`GGx<Ӄ bpqqΜ9?XG(3 *$yl}'g}iiipppPq ,.@9}~YB6}VU*Cdd$+Wj|V]]s#4d;;;;_.fiiL1df*# !DgFoo/~buuuB鰳ӹ9BTVC}}=lmmi\:vii)s N,ܹs 89p4*ɓfcAȸ Q[[ ///bk&!!d277GXXؐm1ylK$JcA 477#997|JHnn.Ξ=kݻWUݻQWW_~Ye۶m8w"##1cƌA7BjL1˲"B&ˇ6; ./_["55^^^Xd |>Q^^P.yl۶ ?<,X;;;ףib][*B(bΜ9DMM nܸwww,^{A\\$ ͛/// ]OM:4˲SWWxxxRV>o>w!!oǎ… ϣXnBCC"""0i$$%%CVVrssqA7D"ɓq%ܾ}G||Uv2 믿k}]hNc'N4[Qbii P(Y^f aٲey&BLfq„ HKKOߌ2,$Z/Q^^@2cCȸpU\p]]]1(+:t---eH16eqC~N@K !L$q6W5C!"HaZN Z~~> b ,YBt Bp;Bq:D{HOOǴiӨ$dz-S[n +BXގ&8::◿N}iP5ոzD}6b1g_222xχX,FBB}L'a* 1!&11nnn2eS!zj<ӐH$Nq4;c}b -Z&cA H$dC$ŅxTbz!tupmm-ڵk"""O>$[oit())eKKKbӦMhiiy h"  0xW{XVV$ &N"99Y]<|-ظq#L3gӏe^<Xh}twwk/j233?ة2.yyy Ett49G1TWW#**J_\ooo|033z{{՟aee᫯ɓ'uJ7G899_ŋ}v#77ffʐKKK555o P^ݶK.5^z%%%%Xt)u ##χ!x / Bv-(Jذ01LƚB>c!!!c_|Šc,˲~) ;w.ڪ>cǎʊ}Ng))),vկ~`kkk5\.g ˾,633ة2.gg$^JJ ޻wx۷o ݱc]5ٳ4099 ::mmmuD"Gqqc000{]#EjZZpvvV0aRSS0 >A^~ec„ cЍm;::`~WWW5e4ĐĠxlbP+**ߏӧ? 0Uuu5t \]]Q__:ǃ=5/[ _|,X5k`5w7n?ΝkTh`Bp YW;A{{;lmm6nkk&OsR耕,--Xŝ;w-L%>>8~8RRRpssݻot " Nq"L)Ds2uhgg~;qa[[[ ݰ91>Rwn~-x'sNڵkdx"~zB z7z*n݊g}byTWWs7ammYLBqmٲ[lѫ;b $a^^^86H$mmm9sVO0 f̘k"==BcO?]­{A&۽{79_BƆd2vҺܶm 22>/,,oʕ+qqqRonnNp;vU}[BCCqڵAo޼ /~aP|SA{2 _C}HJJ*!ҹ֯/^={ ..̓z{{QQQB@uP@صkʰj*477ӐJ4ibccqu[KKKa˖-`%%%P*xիk3x0-33JÇU19l[ ">>ppp0(ؾ};8N9XE?C@eY넆cŊ8p}#%(--Edd$077G__GBm߾}Żヒ7t;E\.Ʊn Bcc#<==GBΝ;anncC1-b1J%OP\xoƻヒ?#ujB!x{GtPPP[[raaaxWFԄB!d ˲!BUeZIIENDB`bcbio-nextgen-1.2.9/docs/contents/images/parallel-genome.svg000066400000000000000000000232011415626112400240660ustar00rootroot00000000000000 image/svg+xml Selection of genome regions for parallel processing chr1 sample A sample B combinedcallableregions bcbio-nextgen-1.2.9/docs/contents/images/variant-calling-overview.png000066400000000000000000003536321415626112400257440ustar00rootroot00000000000000PNG  IHDRR=bKGD IDATxwxU߶lɦ{PTE>^QWAB "PB$H nd&@ (kҥVu -VjWZׯɓ'6JL&9t]GR(xN,].\{ndggcɒ%VuT*.\ &f̘۷oK.d ^^^jժ};@5 ˖-+z]@בT5qU7TPDFFI&w6HR`ٲeعs'FWbh"T*hZ\JP={`k׮qUܢ5jԨLu HL7|`Νׯ_ufv(J|WUcHu<&L0ݻj{E׮]ѪUh!Gs( }j߿в+yBϩ'o߾rX,ƨQ -sL2k׆D"37o0h4qqqVO|Xz57n ̚5 a .vy>>>P(ܹ3N:e͛C =I&jN:ѣGr 6ԩSqΝ2oYw|;{,^z%B$դIJtǎèQPfMHRxyyرc=r5kbH$‰',ڵ }􁧧'd2ի3f֭[Ş?[eiѣ}YYYH$VtqqVhh(jԨ^/̴P(R츚sIV3R0P?~l\~B70X̆ XNN;~8swwg؀{0l̙[nllСϳ/]Ɔ ow…l޼yݝۗу IRocǎ6c ~Wfh,ZF[o1_~,55=zd2̢toC^_u(믙P(dŋLVm۶1'''ݛ?ϟ/2ƘNc'NdXΒـֽ{w׹z*k۶-|b1fϞm}izX̎9c_痟]Mڵk1رb̙3<==-n%(Kۊ%m{zz:d >|Um۶{WGDD0OOOkCϳ'N7on~ҥK.ǏXS~ݪUj4~ɓ/^dmڴa#F 0 cY^1blРڶmks}YX>k.uv5jT.[¯ce?K,?ybѣGuwﶹm[N:+x9ǎlڴbݠA zΝ;[,;{,r9ɱ_%(M8]Ҷ8;;[ь16x`&HSiӦl'qHisgϞ |%~c }NZh-Z`Ŋ6m/_n|"K.a߾}{ѴiS˹/>|hW{Jc VS׬Y?7z◗VҜϧO߻Y3bw;ib1lL^P(7oX7c NÎ;~%7| oE@޵ޙ4m+Ni>rHyO<l4hF$&&,IMM嗋D">?̙3cƌH$zsθ|ͯ+Wʕ+Xb]bKiVҶ=z OOOh4صk֯_oooٳ7T>~, gʔ)͑}lvMrhD͋2Km+NY>byAuLL 222p +o>}9Dkm6l۶ 5B틬wEtΝ̙3믿SN,o}.( ___@8ڣ{8y$Z- ///{iiiغu+ gLq"(%m[q#FAܡCpk׎ԩߵ8$%%/2IСCXnxb-[ :r~:|J-kx믿S":u ;wƖ-[jVq=|(z /PؠaN7n|jpjZl۶ | fΜis{\0Bۦ둝m$m+NY?t"""0~x2ƍ7i }fңӓBѣGQ sUy}+zAU|"ayժU2e TVYfARa=@Gslo2G:uaaa޽Ͳ3UVᥗ^*(IۊSֶs\/^'OZ ZF_\<{ͿNܙO //bp)Ǐr^9s?|jc^87Ղ}Վ\=bH?P12bt@S˗/~1L É',kuދ[_u|r틕+W⫯ڶmlֵSN6mGV˿yܸqv~TVVV)뇡Cߏ0n{bŊ裏e%(Mۀci ?5&Mu\sT#ZtÃ`?]uɆjժҥKYVؗ_~ɚ7o0B>Co>֭[7fqqqh4ZΝ;W.0n صk,}}j_zz:suu#F޽{Ǐ{X˖-Zb،3XÆ Y-ݻw|z2dTŭ/:<|0sqqR*l۶mŞ[mڴa+KHH`gϞe=z`بQ&*ɓ'L,3H,o;3f`saݺuc >|آNI~/J6{cin.$$`?Wfذa>>PhS3ff0쮳cֲeK&ɘ9r$hֺuk&Xzؚ5k`` E.)m_pa{*̿4ibǏ6m0\\\\X.]W_}ehZ石:0WWWT*YHHgsɒ'&ͿB!_]_u(󙓓<7n\d"yS#GC2ooo&H6l;x>|8ի]eF#ۺu+۷/bR5lؐei~/J6{~Jv[VXJ1#& :.p. s=!T-[߇H$'|aÆÃ_ॗ^Bff&Lb5!ڋ1jƔ)SpL4"ݻ7Ǝ | !jܹsƎ;YZc!j}-/&+(11 b5BȳEVՍ ڵkƍÁ'''jc!RiB!T. >!R( BHB!B!T* >!R( BHB!B!T* >!RUBHc4d$&&")1-ZDsz!PANff&RSS/ R Ddb3@7w"Tl$%&"))*dErR$ __~A BQ_ M5իpyvm`A'O#4n( |ja2Ю}{>/f+NK k?7Q  8$eT fI=󬐭 -vQKe0 HQA 9V-@6m_MҐJȥ!W<Xl* j y$cġhq;`zuR4 >C2 QzT4c~He3ye>ġPA*FCO!E8.>yRA* h|l|3;&X8F5jqQA*7χX,b!E8F!C" q.P4 r9/DT4A!E8NǿT<|Rr| '''_4FhGЀSBCq(|A|Jb|,[( %77 >H%#P/#P z=$ Ҙg>-!v8ۅIG@3fTuSJh|<؇P+h۶-֭[˱#..aaa~zU7@ @!8.(]VZ-[t邈իY^tR > >@Hy(kwHIIbԨQF⸸|R4|RYc>n @~ VBӦM!ѤIlڴf?F JѰaCl޼٢ڵk!p}k׮k֬q#F໇hW###yfl `ɒ%hԨR)<==1j(ܼyb[Ghh(4hR TcHOO(s"00 ͚5G}d1[:t<<<sAauDBCP࣌.za2/k׮8pM5kZ`„ P(0`:t耣Gbʔ)J0aB/ذaf͚`@͚5?sLܽ{CHHj׮ jݻ7._SEx1֭[Ν; "99}A@@b1n޼UV8}4i{K.w AVV66ӧOGX3}&$$۬Y&̙cW ݻ8偁#A}( EoKQnJo4]eիxqE6nzoɓ'!˭_n1c ѯ_?|g8x Ν 0L0u5kg#==-Z@1vX|HKK./|bv!{`0T $'\%ssjr4 ;),,f\?oI0LL<~;v,ZÇ1f DoooǗ-uŢEc;wīcN#Hdw拐u¥O?.ԩ8vEV?\v5vX>Z~ 777\z"y -ׯ_ѣGe1۷jz~- L su |R |b|pp}yOXٳڵ /PmN4  ĝ;wk./_gϞ[.>Sܽ{^^^8}4nݺe+uÊ+h ! `R3,, 'NyO?gϞpqqիWq!{L>VBǎѽ{w$%%Vm]x18aÆ!44>>>8}4n߾mшSbʕ9r$j׮4رr'O.U]e1 IDATݧ@,SAH1(Ad?1oO={/"&&k֬1l0DGG~|THGExx85k˗/jطoZl/k֬ӧON777DEEᣏ>BVV>3,[ .]¸q0|˱h"dv'J[n믿bg%Ϟ!9<Bqɪm!W,e>C1L`8> o-uR4 >C)nBJ||R, >C攐J|Jc|ЀSBGq(\!˫M1i$0h+풓S!8& ͢|*l !ġp7L\@RUq#DBH QA wdb8\섔'Xlj<< (  >1/?|Ay4񹐒^{ J&~@ 1cJ\W$1b1h념BQA 7T풭R Gtt40n8|G3g@ X|999Fb&-[f}ر26l(qW^y۷o  O\\p2mW^ҥKm۶X .PL]/Pc0LH$0Le|̚5 ^^^X~}'|O>-B^pa.\(t۷o@ wG(O>O?Ba5~~W̜9.]޽{iӦ W\\.]Z{Li\ z"D"z=B!Rm=zXp!lڵ+}Xd ñj* 7rF#~oqBK/ڵkػw85jTܹsн{*nIB\Ʌ|p?S惐QAP(`P(X,FzzzoNNN8qbIR@:ul?v>}'޾}{0`ڴi+VX,_j6l#G}x뭷'''Ԯ]sEffE[B  227oF˖-!H0hРBa 0vXK#44 4RT*Exb[l1u֡C1w\`͚57n`ĈSœ9sPfMd2ԭ[&MP(Č3߫W/ԩS~`惺])@Hy DH$HO/՘ш'N`pww/\FFݻt8<>C9۷oL&èQ֭[c.-XcƌC <<7n,QKZZ:uc„ hԨbcc_ĉ8{, E3gݻWBBBPvB߫W/;1m4t кuk@jj*ѧO@,͛XjN>f/\x1VXP?8{,+_۷a̚5ZfM@NNz쉘 <HKKñcNJ|_'|VZŞS|R ҦE l,ۛ9 ,77ۉam?_lŊLV[dr3_g1,"">6mČF#kذ!Сccjb,""ȶ={6k|ݺu [t)cXYLLLDFF2lǎv7Ll y&ӓkΪÇǏc3lV.]kZ,OOOgm%j3`1F$;u] y]nP3bNNN|$͚5+رc~߿͛1|p,^zeuϞ=h40alܸqDE< xp9o1o޼۞={аaCK˧M///DDDXY`(>}:7owwwb,_ ݻ8(v?=o}5]Lub? >C1p*HJ=#99PF"5nÇ1bعs',Yh|oR#>>P Add$RRR ׄ ^{ JSL)1t:<~ 6Z'P~}ܾ}D,ݻw#$$G~g;w.i?cE_>Ǝiiih4">>͚5dB?Pn]iB Gq(\C(ߒ߿?ҥKFӦMѠA+::zn sEnn.̙\^üy+W/ɓ1x`4nتĉq ,_7ƩSoI&IF&JD|Rr48]$ Joooz^`-c0ưvZ~P$1I&a5kV۝6mb1^}I*f͚q:xԫW۵ZÇ1fUnݺXhssNX~=֬Ycu899n*q;333a2)lz-!q(B像N0`0/Rw؁ub5jѣ1tP\p׮]+t o6\]]K. oΐ7ob߾}7n܈?[pssիW-'OXe|z=[ ~@ @Νu뇛7o1ưgϞ"yU]` MNH(A -m ɓ -w\@ 311G۷1i$_͛Xpa7n~Gl߾|I]?رckqƸ|2~hn3}tZ ;vDݑX=j41uT\#GDڵ;v@.פuÊ+h ! `,^K/PxAm`$i\D\2P9/IJ;C$o߾8t233 ĉ8qOWWW4oK,{˖=>R8^^^’%Kp!+gƒ%K\!,_[nѨQ#Xbo&_N*bӦM͛t{AeSۇwy_|.&M~üypa`Ȑ!G˖- mcxx84i Il!v'} )g}z`'Mb˺w^Ro_~a^-$Uy>;Vkbr&Xܕ+1ϝ$[fB A ^.WGm'V:ve˖,q śOnw=nub? >C 0]؍_";;g.jոz*V^m5|Q puuO<8saF`A"@Q]v ?Pa0H۷o>=ď1sw!ѩsg_bBw48P7DROYh?y[=]K/Y<[\c߻C-u|$nJgQ-Ӭ)D"2CyCח-ʄ(AH1( vj4T.^^U"B?E7TՖ Be>C P惐bP8\L&PT8ub >j`AC.ABGq8\AR >B!ţ8V FCc>Hg>z=L&SgpzڅT.a)AHipt:?Y|$''c- pss@ ;nnn puuH$bJ&ܘ\899=s |jVjw@R`0 ''::xԨ}hfv @ '''ߪkDd;hBT \Lo_*ͻ0mDgNX s~#ꚷ͹{xX-3oGIeffQm1ofcs!ωX > ]Bƀd?Xis.n ̛?߮c v}8Z !V( BHI!<N8Q 88|B,bt:cN!PbI*H.! >!r9 E!ĂL&+rr0B)+ >!r9 E!uB* Bh|B,PR( X!QAPdv[nYaÆx7D:ujY|r>}AHb<3-'R)޽k>)) nB׮].^ruw5|(-8qU7RWؼy3<9s >Μ9|QV-\~VҥKU7JEB|̞=QNB4l0~xhªܖ-[ЪU+r x뭷 ˱qFرcѴiSlڴ !!!dUUwWnƍT*EZ?"66&M? TvB.]T*QF :wܱ2ydL>1xyyA N:%=̈́<!3g˴]v1Lܹclf͚VڵkF\N6m42'Ofr}СC믿fڵcX\\_.(( 6i$n޼$ Ȱ(' ٛo._o֬Y3j֬6nܹ"""doZhvbbbؑ#GXFXN,lO[㙿?5ja111,>>'gev!9___g[3֭]h4?>}|ڵt:HR@NNbbb/{.:uokΝoGrJx4mc<|֭Ûoɗ1b?O͍/aL>/׳gO<|\]]uԁL&CBB`8y$Ν;Bhݺ5pB~[ xѺuk-!]y-]2bǡCezjL&̜9Ά?c>_`{={,?cƌ< ** :u@ ۿr J]E}ZwZjV&M10ܺu pww>CԪUWҶx<!ϹmۢC8qZn L,S0rH[ήm=z~)rrrmݻ3g@P 88@^@Fqu{Vۉٳ-~Az,EGG#$$϶VܹsVO؜?@^ppڶm?bJ A,9s:tXg(**~M@ݺu-u$%%Yd L9ɄsaڴiEuRRR={ mڴ 3)I[:tPqTBs ڵVŠAO{ZF5РAbsYcŊڵFqL&<}b?GD"A:.]?䃔EEEUF#** ۷X,:{t[s2L8W\Zƶm^20{l@>J⃏hZtܙ wwwPؽ{7>]/^DnnE]1EEE^?h4"::h׮ZlVEdd$vލ9~89F֭[[u(A#=771(J <}.\e˖Zf͚|qD">CHvݱk.r̘1K.E޽Q~} 8/DmZ/** 6ǞU`#..*D"?~1}t$%%aƍH$%j Z1|~<Cyj 2B|"_1x`ܸq,yvR !0i$,^9992\^eǦMuB" &&_~%-[F!8 >!ѣGc}ʥ"ܸq?RRR JѪU+lڴ cǎ6BuBx5qU*Xv-&O\ŭ"8XpJM8d2gϞU BC;v,¼? U9ރ( 4h5jF!ѣb. B)O|B,7h!.+ݺuQ 8&IƮAY0iZh5"nL*BPX,suuH$Dpqu(#N;!kT*!Hggg; R)r94mZM'hڵUB@nn.^UDU)L&,eS[(`@B!9; "wP7@21A( ;'''+MNt:2ӡR`0`d2!+3p9&? CBu%T 1:e97ebO@{/ Td|T!== OB!Cc7o@ƍXǏU{x[k^YYY0%Wڛn=ШQ#` T*2N.@@Z,˶ўL!==gl 9?r];,<2"vWқ IDATE,999H$xemBs/owFRb"=}|.w#ゎgh|hQr3[YLg`h4|7(J[tw/sbآ{cpVzD)^ׯ#)) >>>%Ʉ$$'#!!IHNNƛ3g3BHiOZnݻf``60sܸsXL܎жTp@2?@Dߠ|}}!?Dg`0Yx>+&Z-T?Nƾ={0㭷Jb>x:,UIq79`AaU3 HNJBrr2>>_A oooxy{ۻ8HNJ*mskgT(PZGBTc L&SS[.^>*풪Crr2RħO߫D4m fϮf*''ׯ]- >j+{_Q̇B`@ 7D"iӪ-'''BiqnRSRЧ_?H$'8997{hZd>Pn]:T<|DF T*zh4ܽsc+-\/oohZԩS~~0=|y_8 f| fy0W,Zt:n>{U0hsNq\p@*h4ZpvUyN: y“'eަưUr>0F䤤l_~`eL`bb"pxxx/|}}6hޢEN:yfvg?ț_2 z.Sbg1{Gmu: !GZzj`kuh ˑ:u"~"G`w➦;6Z* lhZr __d28;;nt~Aׇ d]޽GmhZ[qq/5ր\$'%Y4(qOefdYYn7 {x]$...prrY RJe2&NĪ>Âc۶r9?w߅X,O.dGzO RSR&"Qh4Brss!Jҹk_#pk1\F0#=HKKCRb"? k#00Aj!8$.l`a$P5oΜ2V7~i3AAׯcV4 9ш՟~ %./'uץ'HၠZvqR LWWW(X?K[]js\pEouEZZZYO]Gpww\0'LO//>P(8z4 RxzzZ_?lСR9g*୷gÚ?NADpQ+V* ZVVߟ]Zw.{pVkZҢ(U=$@f$yxLn9s9|-[x֪{0ҵ-|>?;C':}VZ(=}O> `oo~h|Ϧ2g {- PHc5be[xiaZQ*ER]@a[;;HR8::®iőrA*gc#惙|pzyR8kD.ïm[(JH$l{`d׎5s1@bݔ2'xg m Y>R^51M2w T*! iכZ>r9|>T*ϘA+g/E´QM8&\\\ Bbd2( B^Z#vtrB77hcc;{{888;etvvpi#4T'@yy9߶ Z<=N; O;Biii5W&2CcJ`{zi\}ET*Tfϓ\%aǞ=pZLh(r\c)DV,L{{{ k!vNPbpIEED"QP>t zN -suOꙫyDB+^޴Ю* ɉ:;;q5^xQgϖۉzp!N:U;SP1/E̴hǶPR;{{ffI`*<?p D"}Kx]M+eLˑAE88A,ZS(Vx,$kDzY؝w}[XVT,/||}c](XRm-l6ڵo_+LTJ Jkrn#DPTVA!㡬{9R AP>(`-[[39br|(S(4`_DUW{9Q+4T! ZR$+2L=шD"(J#rQǨP)5J h)Ծj 0a e(,uDCh`Sv> Jl6Vۊ T*N356J!(ˇ* (ʘQ4m:Bv,`햏RLjeh\4gya|(bN0|(t Ěӫ)hҤ ]9j6v1"`n}T*]SlŖ\O//t768j*/A8 X) ,s6՝7Z!J!m4s}fu_pE!!dVY>5zyy9 [kT>;vDtL К(++D"7s6|(f͛|σib4o8[UNfŁaƍT,\iiiu"CjQ0'XVi(//X,FYIa]b'LfmۥUtšHvZZ8CŋxWͺ*2dڴiCKMMŢEйsgk׮ePVeV=q1A,'G@[V钤n-GC)tA>Lڵk1m48qS>j1|zATB T6*FQ0Wʇ5Z>*** 8僣046tֆN)6UÇm~~~;w.5~OѵkW]t3s]ii),XH$4iѸ{Ia􄍍 ||| >TիWʕ+:}xyy!44FˆvȊ+0zhahWWqIx<|}+J2iL9C/BAAx<3PKj5|>[V*5ׇ6.+۷ok|~Ce3ˇ nLj#0rH݋/3DDDE {.q9;wn;w\,[ QQQ3f q|7B^P(ׯwEpp0?~_Uի]ҥ p )k  @zz:6n܈>]txzz"""ضm/^e\~-AR[>ژ`oܸΝ;-Z8̞=6lh/tUyyU.P(غu+ر#Ǜ00(JџʇZ_PZ>֬Y5khCHHF.]ҥK!ƒ%Kp=mi&k8|FG/ĸ8\rgϞհ89:uիbŊj_b]իWcڴip'41z!((aaaظq#1tP'OYfM6A(bҤI&ɯԪNh&ۊZj777$&&|p4>]򑑑Aԩbccl}sqy%v _+=zbCmmmC$xW5 m۶xQر^^^xͺl{wyyfZ(,,ݻ1x`h¤ClLJJ;w",, ]vqv8jjAdmqAYgXr%>3fbҥGpp00j([yyy8{,R_ZZQq* GPPI. c0z-AӦM1l0`III(--B'M5B1ƴ\N8\7ƍPi 1}b|hٲ%D"Yc(C@HRo[la=qPEEE1c`kk |Z|wر#D"hfn<YQQ8A" ۶m3| Vҿٳg:u* Ѻuk̘12;Xb0w Nk{ ,իW3g 7n@fv999:7nz]vŋ矱w^,^.\'_~Xp!Ri2RҘ1` ΔSL={bɒ%شiЦT*!xX僞`k).!!666#:w{b͚55*Q@*]r3wށZƀbx%ѻwo\z AQQX{=dff!!!hݺIeĎYz.Rˇ!c߾}ӧ9X:&}?"}EnO?a„ D;vsY*^`M&رc7n`ժU8u.\@>P;XbԪE%%%*ZL#GxsP9hocÆ Xb<<q՘ | 4i5k}v8+Vիꫯ0sLd07O*)QnL%V ɐb_YfhժZ:&}= nBpp0ϟ_axA_pd>`xb~pSNŊ+tbԌO,1~X.iP*Xj`n޼Ʈ]4~[QQo?N]ȨQ+WꜿO6J>}ݻ8v}dT Tƍxlqmm&OlB"wީѹTZ Z`&[0 <99r\c2=z4kgRR<==PLqPԟv%Cu]c={a<@e|Ԕ)SСC8;;C(bɒ%4Όcer !ք1jWU[}FEEъlÇGff&222 ǔ:؞}S|$99: 'Ombb|b#h▏#..ɓ'8~8.xt ={ӧOqAR"..#F@֭DHRL8@vy)̜9B^7oȑ#ӧë >|8s!++Km^˗#33nnn8wݻs^)t͛7DzeQ|>gϦbΜ9q42S`ɵfR+Ò/ߧ %%ϟ?jܿf999A.ӟ8t.CR޽{ӧ㜘+P[ocƌAмys9s+WxSe_t)&L`,޳gO=VkV>UVA-%$D# L@"LJ)eM0s烲2<~ N 7n0/qX2ԩS8u}"GGGt ,`ɒ%Dؾ};6l؀,[ BGH$زe ۇEEE@=L~qrrŋj*$''cʕhӦ F &%qi̜9G ]vѥ?!зo_۷VL^ScժUx54iQQQHNN6k/RaPUR/ܹs 00ͮ]ݧR!"1]iTj5!oj@={蘏 JСCqYX|M}F:;w:t(vmV eåKp]rݻw#!!_~}ϛ7G0l0_~gB56s2dFSzzzm]ϧrL&ӈhܺu N”)S`V_P>T*.\d۷&ݻwh[>,Ad ѿ`ǎXt}ɓOo>ؠW^XjBCCH@9 0 a JmyL2VvcćSZ-ݑt6"11%%%puuEHHf̘zn_lK.GaW IDAT!33|>G||Q[|-/h͝pE,XGABB7oiӦa5~3~Yc~͚5@ xBx{\b#'[[5$y࠸x ?߾ua:&6m"{&b8::>OD*R^^n9SKxB"ȖM,o]smXEᨆl" !;zyFޱcHff}}dƍħeKdvuGCϙCDzBHpՕB JSr(JQ-T6O63 eNܻw/RSS!h?acc___̞=?F BgئMkVڂ&d֭kz,h9'NDfзo_ <{6ys ؽ{7>Cl۶ 2 kテR' 7Щ5ČPմ2a=4|Bjr4XHJJ¸qpo@ewy)))߿K0vJDdd$V\ϟ̙38r~'㡴;v,k\R J6|>o18̀n:NBj(JrI) h|OAЭ[7?^Cf*#k֬uVѦM1b<==5Ɔ <h2cDtJ\\fϞ 6\RSS7|ڵΚ$h(pssCLL bbbTƄB! M*c{pqqH$6sSNٳ'S>8  _! }? BORSSh"tYG&9D5C L6 J? 6@V*HMEV푣@MګReXzY9rFٳ'z- 8ƐKR*>8jm 5Vd2O7C$a`:UkSۧ\B!z=zxirir-+J/q*C{v ǏǛoRB  &&#GD= 8 @"7 Jz4mKM,۷oCJJ ;t"N[uB,XH$hҤ qW+{II Ν  @e(mH$ܹsoP֤$x<=zT绊 ضmIkl+VW 6 <<9'g0uTxyyA,u֘1c YeTx(Z85{aҤI(--EHH]QP <<˗/G߾}_?_.V\\P,]Xp!ƌwjz={|X`BCC!CXcժU޽;bbb & ))5Vб|mۆm۶aƌzCݱe/Fݱj*Nx-[N:aܸqx&Om8XbmV!QЈ,/_… 1zh|ߝ?V^?X͛#::gϞ7,^ *㫡67n[Xhۇ r,`q>s̚5 W^œ'On:DDDlVxDoT)S[{۷pqqA.]{g ]H$2ku#ʕ+8{,BCC#GDNzjX/ƍ7n:L:n_jDw.]8!Xd ݻgTj]mFxZBpp0ϟz-((aaaظq#1tj[x1?hdz쉩SbŊ?ooNJ4k,c)S[okYVՐH$6; 6l&""*󨤥8t.^Ț'%!!<nnnHLLy~||3fNP5&sűc' &&F'KCFugvmڴHA k49P0ulC]$88Xs޽J|_ؼy3֯_3f`:ۚLFRDFz:|(;{lD(IIIx7ꫯjB}}}Ѷm[,]кuk|>_'?믿ѣG(..XNNN( O˖-1|pl߾1zkC6HNNνvbbbw^|!<<6l0hkhxZI2hv<,E17f|:6"##pB߳gO̝;WXVVbccrJD"yLPh[>E5c>!׆+**gB*!??x1w^ӧV\Çl[eggվd+++Ǐ@ ѕH̚)m(h$obƍ3T`0ۮ'N 77ƍNHHW~+`ٲeo0Y\޽ѦM|&_X_a9*mhD.ɚCc\ZltsN<&;t|P'-@R&~$R)}~cV3g΄nܸf͚srrX *Qk}f k}PkC!O* NBlmAA4x6e1 Qo38}4Ν399r\Ci=z4>S$&&"::|>fĉ{n|3ju նmH0KV$TQ9*CP4 aL 85xuLv)WWZ/\N̙3q! t>} <</Ɖ'ꫯFQQ#dʔ)GnгgO<}4h11XDEE سgvZ0EΝ;yXl]Jc٬}ϟ?GŨQ0~xkׯ_Ν;O>n <geYC;@&-WWj۶kNgԄ  `ǎt ߧۇ %%ϟ?g͔ cǎł 0~x8;;cҤIF] |މ" n@n%cLJ)c0-Tn'www dyz1:Ԋ /^_|"\/իWPY˘6m^#11~~~X~=ߒ%K0gdggcÆ HMMŲeW_%gXX.] Gq% O}"ߏ;bժUXbA /^ĉ?Νôipܹ:Koؔ>R 9^߾}W^Pܹs())A`` ڶmK]|b3f@yy9OnrkSZͅRVVfK]C]Un[LJذ4 JmLrz,5xV[sْ&CuD",Y%K|Mwرeol{Sdݻ[ MѬY3lܸQ#2^~o`33#:t𕏦M@{ QRR#11^.NocÒ(J,_BǏgmX?χ`R[ 3 .R0ei(9B!č$@esP*XjIiӦfؽ{7n߾۳o,7o4oܤY;x JV3|(r:h9``"'''Nĕ+Wh":۷6uL|r|B  5ppPP)vd,K@Y>8@_uHIIĉ =<Tn ?t""".]ݻwgؽ{7t#CJJ ʤL PQ%w|}F֭[ul#grzCFF%gCBÚ>OD "0elԾictG/:BrKYYx<|paM+89;c¤ITFw /[Q*>}:]m lUY)W)bo ア!>&JvpBr$ےqnj"6Ϝ @@[>%\֮]AW_}7o⫯j;qJHE@v- 3O$5 6>43?˙y>h壤DüwX[bcb k^… sNa6ǼycҶ܆=Svu꒷Ǝſ !"QY>5> cxR H[[[)GvCmBt4UŜ9s0gΜ$4BŨH$m;ni# e|RP(Ξ ;;;|u, S>8tvvϷ*;GㄊDJ2jQP@T+W4rZ(/+RJWm 55 .DZZZ}` 8<LDbX9lʇY>J9))98LՖ ⡬!CM6kqRSSh"N0Mg|2p*R>5g](rZ|0rJ)׈1|p @@g^5"@&#p*P^V&MA !5ƄNP3#)) <Gm߾<B||<!JѾ}{lٲETۃbҥh۶-$ wi]z5x<\#BCC+V396^k'f ֫|(--RʗGfa6@ WF֡,KY߆|0Kyj 08x &O OOOb>cǎ-뇮]4i$ k0`ӱqF|ҥ T0 [1PhneEd%% @TJJ jG}*CjHkd8Cٯ_?c׮]ؼy3.^>۷;v,222$Ǽyj BXX <<.3ߧOs/^J- V8 GmC(jmPC u3) bnC?M4?:mUVƃXs lUmZ> d2?QQ}K6aZ>`ZT>prr2 xqma6GCQ>IaZ>˭Azp@;]E ^ЮGa=RI***rS(t05Ѹh(1 |Xms!H2w-XCyM|lll%%%FYP20\nu ʞ8}r666JH$X,]C |>NNxpvvo.666V8\N/ 88j 僂V>r9`gg[R8t8q{ر/^-Zܾ}nn|T*ri'Oׯ]Ó'O4Pr9%$m||L98Og{{{ N볃FmGGGÇqhb5V1堾prrPi&J$-yNNzJq^~Аu_ JbDʐbXG^yNU/ȼ>Jc/SJ&kvUڂ_JFN1\ƎEǝ 222g899a͚5t^z˗/Gff&p9ܻwEعsg4o˖-\.T*ٳM¾3"i`BomR)~}[ₛ8yE$e #͛Ӳ2ȫv L???sL&߀i5373yezDa}ͅzd1sicZ✫Tm's2ak!77nϼߔF)`<NUrSGtM eS߉i%eKV#K*mرcuQ95ظ~:QFa۶m՞Ǐ9#ݻwŋC?Aky2dfdmېo򐗗* \4+||}퍎:Uhڴ)aggGO #dEHA_nf͚aDLY\ ~1늢T&YTT; `Wf XK* YVZZϟCTKH^NB9V`v6r9zGDXCR=BCq?X, #?/2 EEE(**L&EEEd(PXd2xJJ*dpqqiwҶ`Q/118}2kQk<D m_2-[e!V1+Wq=; 8 *3'X03QPȔ@V% Cd=|.];ΆEl m5V#+A 抅 e^^ð# t35OF~!0c,ݸdbcc,"\W6 Dyy9ݢQQQ "NNP$-///Y"//GD^T*pqqѰ:88nnng{]U5ɓ'6eee&wEZJQQQw!\l6EDTDtR۸~W߳t2aP|8}:̛!Y!(*,37N7CV <>S>8BY> 1@+m}`hU ۄCahrc:PiSC^X'Y&Oo$T%Ǐ˫NNNh +5\'`]f`2OAor uqYf&Qo222Tj<3].* QV: };ִc&.mX˖aUxS !2|pO]V֬|XbXQ3azџjO+**R_RTlZFÇPT.+ /*f>%Y_ Q; 3 }Cc:C&*WJF +KC۲Ȇ\.ǏlTVGSRM !uFϞ|C̮ ŇpXB*qAD"1y[yCAKOM/ۻsmL僡|p}8bggkQJ3Z_G[7>)//ǭ[pԩ*.Tugۅv'+7޽wΝ;s޽Ǐ;wf;OGCP3v2pphOsB ܼynBFF222 FPPg5L$$$Yf;Zhf͚Ymrѱ|B||9>z U{1YתۓRf0*L̉`L0a(C.Ÿ{qMdddEۛ{,ZZիW'O ;;O>B4o􄻻;ݹ"i ZŴQk4ϧUmUYufTlYR2R:e⤵ П̗`(6&O \ҐR;whX/(e DPPbbb0k,rUbk___,Z;B< ;;իW5ߨ@-lْ @eTU' d(..FQa!d26R)ѬysD"8;;k$Jt ZKmћI߾BvV83[6\0Ln&ZiUb@]/KR!==.˹su nmW$$$ƍ$V Zh-Z $$`[\dgg?@vv6ӧpttVI\#\po Uv2 C5Qȼh襭O}o*l NT*A.}ԽGMYR(%̔생_yK3,җoܹsG'#==> MB)"??_C!a*+cʈ>eۛa7@%b@nnN+ Ml鉷 Y=-EaSx6+ Q>W~,* iiiFI|||87 QAAAsddd_eeeATrnfj*v&%ո3hV{BK"Q0n޼k(0>L%%''=on š]v2dk|4~74i~~~~:U¹I88ꏚ}SV퓛.]:u*ڵkW'8壡VqQ,Y[޽{-wii)n߾ gggMрVѵkW:fΜ#GBKᔏB۱xbprr{gI&iӦxfrú"8tHMM… ?BV[lmmm_"88(7 \DFFZ$;;YYY!C@Pٳq=\tNy)ݻ>sMGvv6233ѳg\WX{5),,'|׷(T*2())\ӧs~";;['ZFII JJJh",Z{|q*9< 666D P($$22xxxGGGңG2ydGKRSSB0d\pAѣ ѣ:~ ȝ;wX?״}ٳ YYY5Խ1k?G"++[[[9O߯_?ַq+iEj$&&8}4 kR͛(,,i&̚5 111 Ҩ:pRN&MIII AӦM!ѢE ƢP7ҥ N<HRDEE}?g {A=`ooWWW <UEϣUV~:A*" G̜9vvv:Yrsrr쌙3g<!;vo4m}ř3g,~o˘k6tlz>w֭ԩR)ZjSB*bt1cEj56l؀W^yhժ>3FB`` lقؠe˖ؾ}F_/^DTT\]]akkvޫRFzz:T X L8۷oGjj*pqg+J:Di^ڡ񈭭-Yr%Q-E޽; 8VTTD<==I~!,X|dϞ=ĉdٲeD >Hw-Z ё=̘19rĤ>^{52l0}Lɵkȏ?HH W^yBҭ[7vZ_OOO@!$%%6li۶-)--ۿZ&cƌ!/$gΜ!v"aaa$>>ޢؾf}{0|ĉT*%#G!֭#@RSSvmڴ!'O?T*2tPJVZEN8A,X@|>vބXrer]ID")(( r"ԩSɹsș3g󉿿omlݺ" T*%vvv$$$L:l۶\zշ:|X޽{䧟~"6l 3f '~~~tww'͛7'$,,<{72"HȬY\.'/^ ǎ#]t!nnn$&&C5<}Ԩk!ɈP($+Wdߒ:LO||< zGQQdrB!7o$Ȯ]6?x6xx<Zxkc1/cc?cMLL$|>={VM\\qqqٶmfժUD k׮i6::xzzBy@֯_fݺuIKK#2h Ҿ}{ߚPo!QQQd޼y-G) gϞ~ڵ,]3wwwҲeKzn\pAǺ# ɰaHzz:.%%L8+iӦD*/޽`|1}:u gZMD"!NNN666Go?駟Xe>~8@NSB!ÃL:`*hт5`;s)}{r|ovțo!CPT* cƌ~J!{mΝK$ Cb1YbsNr#vi@ ;,F2Eq[RGՖVE;jXwJ*-uTKQG]h@8.E6 ?EA{?ϓn}??JKKɓzd8qR)T l f;v ǏGPP4h+W`ڴiܹ3.;;;CꈉT*E6m4>_|D4!Rzt+ݻD"lٳg|M_r>D~_]ccH]b6t]ԛׯcܹZO9mmm HNNFzz{̖spp@F8yrY ǬY`gg@,Y +obNid27n=zh~͈Fll,ڶm˦>}bd27CꈉA ?(;Ab=ҥF޽{ѪU+i[ƾ}pilݺGy3237TR}X! ]ׇ>^x4)C ,Hr;vQTE`` ₨(ŋ ŲeйsgSZ O@&}~ȹ!::>>>033P6'$$hLކԡT*qX3 5ڸ{.Eii)bccѵkWN}pqs[n L0۷o%իߥW}V㯍ʮ}511Pv:D"asqttܾ}Sv̙3P(p% ]VIOOgJڵ+f̘&oq߿4$cΜ9Arr2"""1u_x%%%Zo.֑?'֭׬YSi ~~~hٲ%.\Pf͚ƍ@PPPoկkCz۴ikkk̛7ؽ{7G !!r:ubF˖- @C}_]QFh͚5Ըqcꫯ<}vܹC#F [[[277zUVD"xd: O?Dݺu#sssH$I ,JSKHvy(((@VЮ];DFFִ8<;AƍhذaM::1g"44EOLC" !!ׯǢExŃx僇5ĉشi"##aggW'q~g>>ضm[GbRsא͛ۆr M}j//LLLH$Gԫ9^t1i$ WLLLGSL!B( v 4Tyj::Uc6ѣGgϞdiiIVVVԡC5|(..͛7S=֖ɉ"##_>?k֬2NJ{4ˣ֭[k<<<<ڨ M6匍9////6_m[=xZj.J֖ѣGk򑜜L$ yyyH:z(;P￉СCl1tN{+V`KNN֐ޞ;CUʏ?mDDTRRqqWw>CXf [>>>3f  m:\*NNN{czz:J D?壤y{{ŋӣG믿fcǎQII ͛7<66+V={6m޼mۦq&akׯ׏ݫUf]U*YZZҥ W{233Ϟ=!{ZZ;Furr"deeE>>>4l0ھ};T*6Om[ԅylB=-ZGJm zpzQ\v j*b1{5l޽{{£X,7'_rJm2#ձő#G*YW#778'[2UV՞/)) Y$ |}}9iׯ_ǐ!CC"""FQFBZZqa+V@=yf1ѽ{w,X+V.\011ѸqciKhڴ)继OM6#Gׯ_g]srrDDEE!>>֭;v ##ή󕖖ZpY@Dtt4ԈՉ^O\|}߲eK9 ŋnbfff "#n߾vk׮wO?% IDAT3@$a՞Dy m۶ظFQŨbT, D@@8m=rFŦ[ZZ">>(((c`mm ظq#Je[ !!0|p<~ofc7ވŨ^ʇ̙3cǎرc~:={|T`]+G}c֬Ywpp`={`߾}W{ʸ>ɓ'Oŋ!祉rx]Ճ/,,, JѻwoxyyB!Ba[CTwwwٓXȠu;ooojذ!8 gB=""7oi mݺMhgԩKcPvؘ"H$f̘apy"۳ߛ[jE999/-69e$ '"{ĈRn&6l` >=JGk׮۷`+WtcAu>CׯiΝA)##>|H֭cJLDeO0u31 wf&MRBPaÆQ~~>hтPzߟI$ }TZZJ'O&uDD+8eѨQ#J%Y拉z[Ç4i$ruu%cccjذ!͝;W#赺i Zxq]l9nݺt-6om[}l͛AFFFtZ+Om_۷zA$ĄiܹNm[QHH5i҄LLLN:4rHtR@DDy5$Rx僇+<<<<<<<v8yS(**“L#3#jLfܿw+T*e7Ŝ=j^yٹ};kcc;HKKKesYZYi-gmm @b7IXo5xLdfd ==O23QtNNNppp=֭ rv~{a7 +)LLLp@N", Lǐ|S?PcZi7 x5imS:󙘘7[rmΜR**ݥͦ'%&ͅR|nll S] vsFFa155)T*={,d}dfB.nnn2(NNNppt=`@Jݽ*[TXB8󢢽T#"0ԓxFQa!ϯRC.C.Z...֫ s X[>9u@aa! >x`ccFçukr(TTN!J9ifH$4uuuJ8u$~gVRQ󑟟sIIs0} 8VP(˜T*`͛7n ??_+UǏǏxǏ̘Q">7ix1-&4T$S)((rssި,,,n@r9  QZZ<-7WTT\b ;;ڌ喖ppp9,--abbsss[X(oVF;AÆpov+))A~~>N<'OBS~G2cUH$k>ڢyŬC]ᱶ.MMamm HRX*0WW2 ]ָFFFH|z gϜѪЊ38r^ hCp5Š0U<(J'#6H]xT>3XY[uօC)M5{킒>} lfۻנ:**)|̪\[Y}!J{ʕ+Qnjooɒ%֭uVu{xxK.l"S>U{{95Iʭ[f=}}{FFFe{633[eʨ+j_ECk(**1 Prr2BN<,/ s215SĄQŒ1!9VoP]ĔS{_Ǐcv޿u*,[k@,#8RSH[#¢"( X[[C.k\p`^nb~vfcc*4ɛd,--ٴ)4lWWWԭW[SݺpttWMQQEG?WYu:׮^׿\J'V+>1m4 6 rNBhh(nݺ .Tk{X`^,.֭[7oٳgcС^memM]'%;~ٳocǏ?rҴ9z @&ƒT:d\.\P ж]Z|0(KKمJBzJ"w B]BzTUM,??>O^bTJ߻t| ++ NNNGȢEMw1ˌC ,((ଶ=Ca\lmcG''4tw/TXX R6660J˂],-aii T 0 :wu.]?`PP0vaQdcuNmC `?EX&?\hccî0,,,`dd+++">AuX LZj*#"|N\kǏ055@U .)J͛7c˖-q1n8,\?#ɰl2;wrnnnի;L6u4h;wT)Ν;vZܿ999C߾}n:V<<c9::bʕh֮֬]?999ҥ "##akkۮ]~z$%%]tw}ǺeҤI= RP>x,J,¹D僈pMl޴ ())C(f9n&Ņ dV֐J033e=睟X5\.cǴ*zZ]5 &Dd--P٘fb1LB0Ť'?ztpiLSLS~P(؋T\dc͉@{q۷/,,,R0j(9s ,7Ν;ŋW:u }Ŕ)S0g(J}ϓ'O?YfGDDr9L&Cjj*Ο?~裏#F״L&CZZm6B7\xo6BCCpBӧӘ3g7ot̜9&LEu`jj<8::Ceñ|Tv!"cӖ-*8,0kF+YOb7p*9]G˦i[Wtڢ+=2(:je<sVvq%|g(,,ą `( /_@||<|||}իWk.VXz57n 6mt_|2?== `5Ύ~f՚jǏΝ;;iΝضmO[l<<:-- <ƍFǏѣGb:u*;88QF|qqqe' ]bccs/*/_Fjj*"##ѡC K7FP(Ӈ<7,GGG۷9ׯGVVfΜ XT]bF_]1!! 64XFGGG⑗h J.\\JJJ޸ϣG8:tUb .]qÿvrrrX%EW> &Qjݻ[u|IeB^CA^#---[Dpp0\\\pAlذL2D &;.]~~~l)?C>>> ==śTU<򑐐\ZUڴikkk̛7ؽ{7Ǻ9.^b k S'P~}ΰJqqq2ڵC˖-arݻK/Ywl_' !P\\|R-uQ)dnU(Ey]f^!;bΜ95jp!ݻc…1bOvu֡Çǜ9s4ܹs1h lذfBzz:n xHıd2D"+v킩)M={Dƍ9,2 cia=<<`oo_eV+W //cD8~8>DGGc:u*222eH$eyޱ}`r_TR- @-׮^aXh2h}QQPT.+r1 47nx]oo '''ݽEXxx^NĪoA#CGWϖĻ]xju-?E Cff&!HcѢEPTQ\\j7n?'OZBXXƌSӢ\.g.*Q*=1K|2ϫ) }Xj>|b!&&W<^#~^ykσ$LGq-~ܖu@P5-Kvv6MVӢ˖]6)EExO͠~2yϋP(н|}fߘʈ@ `_b:t(syx*.:c>r9DĞQ7OP(=e Gٳ'J%ݻ}Xf A!B|( vj{rs.S-( [X\[nFHHƍ[.͛q26&!d&kW]9o.xŒ%KpNZNND"LRCRTscǎEqq18|0ѲeKH$ 8-WXXxzzg b`߰tR4i@xx8'{ӟallƍ#88XC1NsssHRx{{ccU+!c`D7} ڴi }L ՃX,͛7rJ9sFC)УG\t ={/rss?jǐ2d =88˖-Ð!C0~x1dt V>($V,[F-HPqq1Uٳg p=zDu%###ʪ Ϟ=#4uԚ ^u,,H.џ'NS'Ox͛7@ 'OԴ(4T@IIek׮G޽ٳg' 3|ѨcΝڵ+ڶm \ξ5j&M$3|pMׇ?޽;wIII:u*7okkkb,YqΝpvv6K6y /}٥R)޽+Wp]\\P^.򘏒 XPؘ=XbEݛd 3sUEuȣ8*wuԃ^s!##<Ν;!wyc'hL<5  ̎qi̙3͛7Gzz:fΜ &'VJJ F >> , ֮][>Ν;/X4d2Ӈ[RaԨQ8s ,Xooo;w/FII V^͖KMM?}1bXYYq$^픔@"h} *BCC~+0g۾}6n߾͞|\f͚UspZZݱ{n;SƏ͛ 'OիU_J%nݺ>}T PYCe_t)>hтt ƍC:u^BU9FL[lv[ BQYLtoyzLt)6rWҒs$hTǫݻ~GN ,wݻwИ1c(##w֭Լys*((य\bmӓ.7}V&>剈222s=zжmشkגH$Ҹ~ٙRSS mܸgÆ _IOLLg5?%'[[:r0I \̜oӞ={~ϳ.Qu9ÈM IDATׯd2DZ` LFDDH= MTQ]*cx;#۷iɒ%4h rtt$@)))z@Tg?s-|<̘芋oDW<湈ܹsLS7nĹs琚}`@%T22f.oonw{ҥxZhƍc̘1ذa 6(¯sٙ$`}ҍ7Pv'˗$&&r^.*))a0rHaQtɣoyLY'L[[[6=99߿ݻwl9___kяӫ1cʕ+{MBU(666033^ʙ>|ȗ&c޽qu)?(}b+{II nYt -RS}^ocѐH$ppp@6m4뇅 jͣVfpYfIII Q[@RuɨR@D[=qDtd8}4vލE7}Νcڵ j]&i]0ʱyXmۖsibU*͛*Ѿ}{:*CV0\SNal9Z R@S%/2W .ĉ'0k,DEE{իWq=˷~g!Cv킕֭[:u*V\:[no\ʕ2~ða0d888̙3} :ʮT*1eXFB ;v&M2? ǩHn3"&7<'_~ٳgٕ\.GBBVqE@̀_~bÆ òe8 %K@" ""6m'-[X?Ǐcو ۷@Y }e766FXXكpnݺܹ3qcP>0 $ USmTgZjwtĉ*뉍%HDdӬۛJ%F={4(0PǍQJpNC}),,JJJ8m>}z}Tښ̟ODDW._& @~Au 68""8@s%HDӦMc?5(---[P(3fСCh߾}4ebѷ9s={6OL...>*ѧ<=5mڔ|8\]]qIuD"DEE?ǜ9sP(C2 cqa=<<8AIIIטxtÜT-<.僙4n:_qqd$*5|ŋUV$JܜZhA1]xQ%sssѣGk< T\\L_~%9;;T*֭[Shh(mڴ`ˇ!2:uDdggG'N/Vy }VTF}%[[[H$Fƍ˗/Wٿ[[Ӑ͛$9s eӫW/z뭷޸xz.J.؋7XXXXhЦMWʶxLٷ6+)))+2rH$''__ryNP(Ċ+YPlQK/j X,=VpssÊ+82y^qYmٵrQ055kQsNDGGiʕ+SSS4k aaazsae˖H$8p !!!􄱱1lmm7ojԗ9s P(Ĵi*dff⣏> РA!''G/['NԻ sJ6ѣG#L8{:ׯZne˖qW\ 5Jg=zaÆغuk2|TӧѩS'u0y[hàApIBǎ>}`ѢEر#֮]zK[ET*q ֕ݻwq]ܸq;wW_}QFi]m߾&&&7|||{J/8pܹsu]Ǝׯq֐5& @c~[SW6l9rZcij[ɉ9̙:z˗i…4vX266&XL:?sdooO76ӆP(f͚qNeZhA;v전:tyzzRǎ*ƏO|r:y$EFF[oE+W$"Zx1ڵ=J˖-#HD}Gvш# 6@N֭[X,:)44‚>Pݺuߟ(!!=oLJNuԡkѣG)$$B!}l>WWW@qqqtMݻ7I$]Q+UYfǎ|ر6=%%B![n}HHD":=\B"شК5k8y={q>}~WN7믫 ZIu9W̌-[1䐩)=M[z5={h?,,J%yxxP퉈hƌFŴgϞJe=s ;vT$믾*kԯW/ld,a*sa@ׯ֭[GhҥߕuޝΝKܹsZg'{n/_&@@GyVZUe[y{SMuH JUeWͽ{3s;֭[yʕ+I,CCCI  }T*2POOOdWPP@bV^MDD="m66Onn.D"Zh۷s_ȒA(<JT|h;w~Զm[FQݩHմiSԩI&L:U>CCR͛Wk:D̙3:0s1ch~ڷoI(e lÇI$СCV2e###I*Oo+3s@hHp0]HP7#% KKKAD055+*Y?XA+|Q ~dEq}'",\nBz`mm;+(3C._GFǎ9u ( P#F|;w"$$qqq駟ؼ۷o97n8|0T* .]~C`` 9FUΝ;hԨd}2e Zh4lܸ:uBbb"\\\{!3367x=L0HJJڵkq ?RZ e?Koߠ%\nh/ѣq 2nٲE/q}櫍1"mMLL*mU#`gg1y]|D41G\r>ԹKoII q1?AAAhР\iӦqn111JhӦ +-<==9ycBkI/Cd9<8mk)99Z=8;;ШQ#N8VzR ann^uWN _~Xp>N9zhj }VZl5k`̙llvY-۷믿bȑlznGaժUꫯ/_Fvv6 Piuaݺu4333BPp\DEEaСL8AAA8pǫ`ԨQҥK1d^Ä U qL0Ag>Xp -e2V"-- @ʠU9Vd͈Fll,ڶm˦>}b~~~lZLL ڷoеtܽ{UVpuuYYd2ڷoNz>|A.ԩS;vwi%Dl߾]xw#''*J:Z]O`/R|駸z T{@Fj_hfw܉]m۶QFhҤ k>f:;;cƌՏ{Ãxe4;;;ٳG̋===]i1c`ؿ?ۇp >ѣ'}޽(**(ƍH$kSs"66 n݊Yf?`uP{XHHHи)`كj|w]v FzFtd28::rnyyy/\*%%%VZZXtڕξ}pqW/}e w6@ô~zdeea̙P(t钆<׮]?{gUl03̠;*$Rj&,Q抹_Wa.XeT.HHb 6wAV=׋33wy<T*+K#''R﫺^곂u^3gp:Çڵk8p'}ӦM.ѝ\|}}W\)Xf ~M4i0b[o_ΝCjjrR)}#0VݺuKXv>]gEX`YcwL,/?o޼iLԪU+LAf&fLNNv,g 3n8`ѢEرcƎ 7`w}-˜1cP(*?hQݔ`0T>:u@DFFaj8z(˶AHHxb|j W^Ett4fΜ ???ddd`Μ9СRSS4L6}^rr2j5|$%%ArҸp o>HRx{{ٳXz5/{rT,#G@ѠCxLmڴA`` ,X???>|Xnڴiz}A8_H0ʇhX"AZZU8ŋ~ìYpAk˗q!z,\1l0x{{̙3x"]~)bbb1cƠe˖x"v܉vaZmBPѣJ+W(=zcǎ͛;v,zgڵk7or~m޽=VXQnu9z( b\Ɠbo!!Րu:z}>Ae}ny jCTB SNV bٲe  ѵkWlڴD"`ܹXbj57oP 8˗ \A!**  `K8r+Xr%Ѽys|^"""O IDAT(rFDD`СhР ܪC.CTb͚5ؿ?V^ >Ю];bطob1^{5YJ}J%-ZCGݺu1m4,ZI O>8tT*U;o}2 m۶ŢE؅߶[΀;v`V]vUVL(vt7ömw}6ĿA8,}M6%H9P%QvmyuI`pjI3ugr /aҥꫯȾ}8{%Rj,Bu[T*6eYL;v@>7{98rP(9?y˝:qc5}zUU:9~ͽIjuPDqcB:p|KA~~Ւg l !1JM|L&"??[}Ö-[Vׯt%KRXXӧۡ* >Łk֮A"X")R> Vg BʊU>ɶJ`_{u8uBW^h׮B!/>|GZP]Xv-viӦq ||2mn`v9}zQ|>Hh Jáx} P`|T׀S `Kx^,|>zBRR?h޼9>s̘1ONxb,X[Z$8p.\zeuàח2R.|0v,I$Hu >>}HHPBPJpL 1lL"f""|]bQ^ \|2o_ҿwo{Y.|>F#\\\hP|$ؼq#B!t? L0JŚkq3wޅFFٳgif (Z\XX{:|]0ʇ#[ox?Z6[RA `U,Ul2>}(OϝER3`,"f}ǃP(9Jb~baa!|s)ΩUMff&_nR0{lU,Y吚 Tgx<!ϝER3`,"}'9y|>4iRUN>9Vhذ!̋3gjv/ERvgwDTT*n΍70l0DFFØ2e onuءRĕ+W 6ҥKhѢ9{xx8&Lc׮]7oohZR7n7߄&O.q2e /_I&!..;vk:]8ά_TZ0/x ۷8wZ-{z*.^[ܹsd3f nݺ!!!=N8uֱ:RwG7o|}}1b$%%!))cf)0|P62t7S>B!}I) v1Lvr߾}m6<(>l0Çرcp 0͗{Kݻtaݺu_;6bNQyd22220pjD!b`pZ^DgϞEaa!kag|,_#G(/2x}p޹s۷,ΆVEV0jB9N()#1›wٕBL,N+#F'0zh̜97FJJ &NhFӦM9e+_Wb֬YVJHH@XXX2)Jxyyq .]BZZvڅ.]X')>DqV(JԮ]-ZP亹r """l8m4>[yV_G^3,IHH[ߚcp}:0 쿶`](yGuV>6n܈$&&⥗^bO:P6c2pE6t8˸L<==9sYyck׮J[n!33QZ2בmT;ĉֽgؒGTs%UJUlNAaaͥ|' 8T6bP* j111Сt:\pjPR؁U  JU>Z-lƅxzz>lٝ;wp}F#Ξ=c0p9s>|y֑#G pېq3Y*\J!!! սgؒ'))ZnχV֫(';vB(_A7T65燌 ̙3:t@jj*ƺV+A&cǎdPn]L&DGGoU%ϟ`|t ÀjqQݻYYY'99jU>j9 BܹsP{"&&!!!H$HHHp]JjCRFחM3?1uTjbccqh4tbUPUӧuÆ!?/2|>lȀ8nRH$EJ777v- @`spjۅZ>(Ŗy:˗/#22r BTT `!8&= Ğ={0}ttM6{g;rԩgXlbbbart6mH$r>qqqc ĉѠAL<W\aimZZ=RRRVY|׈СCѠA|;Ʉ~Y?w.܋iQPF#ԹV8t:Wt:4S!Օ]!+^20 V9`HhJ FsS cX,8VȭX*= W([B gK`0/YĄ?Ľw6y<x< \"fYOFqʣwX-|W&Dw:Bo rrp?nz[ )U0wl̚3cbޘ1SxҪ 8qիWkyUhѢ.\@6mnn67oooʁrưaVJBZ\BVCJ^?ST-Ng͖r3dWfczFibB#˗+Pf x|>'0$$\4^>>>Jd[L&'Naa!j5+@wssAA~~>%  :8`=QY:xW\)<=t: l(, ¦Xl"7QV|>;vYbKi2'j&.¤ɓq!PT11xql#W(YJkŦ@ҥ8z{,,}df$s{XlW,Omjh1JcNy -9ؽsUWp-gK:sy\))hт*5UVaժUU-łw}* ^^^:u f3kf 3ܼ`0 ?/)ޜ^owS۰BE3F؉ۘ$ڛtmBRvg] L?-6O^H-8{2+C&Caa!}Uʖ%׮^EfPۛ#eKs1>t(5M,ח3H2 @˖-QϏ#T995TTɱ!BL33F:!Hv>~]<˾FN9,53se4HF)$3s175&<;xLAP [ne z FFwLH\B7oݺ,dggeffG2 ~AB\Bf |_PPecTjim1wGEy_.׆hyE/&4ZIZ-6L\oۼϒRPB)wJ\>k1TBhe ``߾e.ѴiSbt=8[2~@h&\S= x۴`K^+/m۬m)5 gK+&6de^.R~}\TΔ Bo0 W:jծ B;/(63 pv Wfg>4PY!@e#"7 HjH`+gdX~0Xk/V ݖ -EʖŸ~=~]nIIWVNs]-g-t\i B][PYi( B$ KC`JAP( y-BP(h=(C BPСCo^PBP(H$iU>( BqXlw%%qQpƍBP( |T(?]VbP( *e@"ЗBP^@|GSr) R@2@- bB*ej bB*ej bB*ej bBWT(P(ڥ|G/Bg@2@_> By17$T45|jP(?Xؚ|:tiii-Z*eF;S(ʋ0qDL&֓ϓ'Ob̙hРAUX#G]( `ضmBCC9Ͽ GXʚU>ʀ=Q(D"AϞ=q1FZɄV5|8@bb"ږDVVVeEP(J߇;пk׮PDٳgUXʇ\v SNe-_/wUHP( btx!rssVAT*EƍZU>`Ȑ!X~=PXXȉvNHH@hh(:vXRR( "d t:`P{Uerd ?C @"99>? By7n<<<8i4hPIT%QQQAAӦMCt:jۨ[nUIP( ''x?D]'*#4j:0EzzzUHP( K.uAfffJTcInAV0xӧOUFP(J`̘1pssciG١ʇ7GP(/ ÇhaU,Qͅ*N0|prz=^{BP(GӦM9ikצ {C,@g*NhB`5 &PIF( ^^^xWZ U>@}~U@rr2x<"## >}ST?~3ee˖V=0n8וQw z(3c xFQF LF={l~{bɒ%|T*̞=3eT,\999R=233quvgy T|)\]8ǸqаaêFC2B:uTբd2ԪU w޵ӧm۶0aB>>U-B*eM6pww/\բT>~_ꫯ ۷oGpp0ԩԫWcǎJb1b޽{C" 44@]vl^G֭[cX,FÆ 0aBZvA;ꫯuA~8%_\\٥׶HlقC"QF裏 Hi&N׃>+ JUR)Zlɓ'`0yos???L2SYڵX,F-ù|& ~-:vTFaܹ-k ԛB)Zʔ)SV/,HHHc޼y:t(zͦ߸qÆ C@@<==q9,\Xf ]V71yd6GTo߾Nܗlذ }1l0r̛7GEn0|:B{=:t| .]bÆ 8wz|qqq嵭;R'sN̚5 !!!wjɄ7|O… ѦMcҥ0 Xz5ۆ޵VZ}7|y123G#dge!33>DvV/d.?8l+R)՚rH$;L._dH$,U>ȤIhGz|f;yŋsm۶bGu֡N:lG+Wip}_&MbӇ X<|r2 8p :tPj###sNsd cIII5jk[uwN۷o֭[ ̄Gl>Z7nu̙I&GիѬY3NkO>trss,Jwضmp6lk9oڵ8tΝ;~}˗g^ IDATw-++HKѣG3s&z= #=c) |>U6@j6x ΀*IBf B!gc;QŃKC";+ x2=BVV,<} ' :uヺhּ9|օx{sSx,{_###Be|يc6GiРAUBB߿M"-- V&Mp;v Dž >͚5@!>>׷Zpxn֬RSSa{.ׯ`]+]p%hЬysT*t:D" F9 m-((Ns|K5oL*>-!?zbU&??).!%w7vBX--|8SNA׳Snn..]dݻqڵ˩|˛7or3k׮œ'O0}5-l Ի44 Nh WO$<Ãm3X0ffX w2 ϝI+I9x)~ܷϫH~mos D*u(~jb={_쵹""-2;S򑓓ÇQvmt4+r\tXli&ƒ? ߣB9%k"yyyETӖH$BF燖Zᵞ=ؾ=|||ñT999br-͛8y,}x&އBtRX ___l޼鈏2?!##sAh`0\6Vz))S[͖yD"All,9F:X5BBBŋUVz*1sLKNNZf;,m:AP`ܹχP(޽{VݻC,#++f?~<!xwѨQ#ܻw˗/GHHooo=zx<{DFFŅUΞ= Ʉ@PvڈêU0qD6|mڴA`` ,X???>|Xn޻VһHKCѠ/Ǩ]{:t_U`ˍff[o(l{v_KrQأ,ZjqRiQB(NʇVgZ=vq,...e238$od(&@sh4VvnTTPpf,7n8u$<==9l0,]l|>;[Esm1}ss (sBDDEU"XT-!֭[[.]xwl#""peDFFB.cРA€8q9RsH$X N,_ : 4`갅H$BLL Ν+V@Vy ѿ䋋@ `Ak[uwN {1qD4h'Oƕ+W!^z٭96n܈pt:4i#GDDDwaҥ 4icǢ{P$>>[ƼyclQQQ냣<3f`Μ9tƑ#GXw .8Z`b)Z֒"(8AU-1 Dvxo޸aHh(~ض {dhxkn`& śiZegjɁVVANN\\\ J!3Hd"W)O,E2q OO("xPX,khl._FBqD-}8ue03o2T Ӱtck9fڒO>VnԩIб#p\A:N8իnVY8yd,7)))}ӡCU-9Q85V?6~ع8hp=ob2N\>ZgL"Ghi8ˣG}t4g[l?gƔ eA)F#|DV"V*3+iOC6oތ,4i"IIIXv-,YRmшDL:\4 x<t:]|Pκ]4 coWed23yg{ssb0T&H52kK+8ʀ 2N\z;wDvv6\]]Ѿ}{l޼aaaU- )mGUGjۅ|"GN&hȾX^Aʧ$JaժUXjUUQ"AAAm 0~`ѯ[,ǘ稆L,ԅ*J@uJeZ>5Ay>0 DKj!S(gCi_TYZ>A, !n h4٫)RYJX>@(Gi9 lh4T)hdrP \UV`ܸqe˖Ӝ4J@Ǘ3(eI&0aBUQj즄_T4̄I]K%T 6Aff&_Yj ZR0{l3@ JIOO۷ѽ{Zؙ()cph(?~L_RJ`TK\Q3gNgmذ!V\iswgA);L{R @Jc|ҽ;3vlʇVA`pqq/)R0 N+aaahݺ56mڄ aÆؽ{71vXB*_~x1{oѳgO20e:..|0a!cw=z4ڵkǑ/ k֬Av ѢE pi ={[nQگCǃo߾S\\\P^=;j9Gs$߈#X6oѱcGHR4jsεeQ !رc^}Uxۯ_?84n.]B= HаaCDGG[#mT*ZjA*e˖r9ׯ_>Z=ʠ" (=CTիx"n݊sA&a̘1R7n7߄&O &d27Ă 0f ̟?i !xGa8t֭[^sα홞Yf!44k׮ 9#m|I 6q!66 z=|P* f#ϷӉ4|y3i۲%DS(N^"''" ͟F 6p'OLd2QTtXL !\x 'Ϟ={rmB!D(իWy233 wq}!@nJ!Ν;ٶm'O?D?3H۶mI~~>?BmR-Z o{|{.@Hff&'ߚ5k@ III#F;-u# |&S4ln0;v ~! TW"00|S*%Kp"4L1j(tЁs&MC6LXbFiexRhĸq837v% n޼իWڵkl(m}uF׳wVe}vxG)JxyyYŬ"## ݻ_Sr ==fy qqqh۶-'?Dpp0\]]j/ yТE x{{c5_4=9*VѫW/xyyA$N:ݻ7k_Xr%x<6lPJIIŋqʕ -|~۫S1ג倥)ׯ#;;*=!!R;vdܹ3'NCRRFšsֽLos˞={ЦMֺb<==Cn0hРnFNoݺ!C 55۷رc!ɐX|ظq#矊% o^:t耖-[V, Gi6,z", "1W>^NÅ  o˝P^[nY `N^g48{פ$`0ܹs콹t钕kf8s ,X`Ç[Ν;%4J%|||8ZFLL :t777s$VERRw>>>7or׮]'O`N͸._l "11J+W ;;Mw322tTW_}SNP6F#B!*M~^_W\ pEZ ~)6l؀ׯwL)Ç?W(3떁"C !Ǐ#Ddq?СC%O>%Ȅ ʵ\c4kܘ 0=}$Yy riNĉIF8iÃ̟?M&mڴ!.\ IIIdŅVK!9~8:uꐖ-[Ç7nDB?Nݻhr!A8q"[g@ԩSɑ#Gȁ\.'znΙ3 g&;v , ~~~6mQǩeu?~L:~z$00r__[;w,EɠAΝ;I||<ٵki۶- ){/ {׮%߸qUۂi;w!Cf͚777B6mJϟO~mO`5jTnR Hę)3VjlѥK4icǎEݡV}F f_5"""0tP4hJ%:D֭[c޼yx1Zl(;-3bccl2`Æ ڵ+6mTΈ\|4h0`xGs$e8x f̘9s@!88GA~[$!&&sŊ+VѼysbزe{G@@h;ظq#áФI95ryNJ|۷X=vx1лwoԫWB׮]ӧO[EZzŋ1~xk<ѵkW\xui4.\@^\/=O>Krv7.\ }$o9vX?k׮]駟*Y 斏J%J{~yһwoң/etT^dffꑽw@^ҥ>>>癞i2Ȃ r56~}ѢED 3gpMII!̜9M[d @ N^ge˖V s>cɝ;w/c޽rs{vlGE7n>Y^R^vmҩS'> IDAT%lyPu i3I-̒bsm7hy!?3֮]뼪Da>|8^bT VWF#؀ꆣUzPx#c4yrU*5j3~z#-- j p@͝*oxWK/qvmڴ)7ox1yׯ_$},Z[l'ر}jg'X-7/ gr̘1]6{ݴiS4hЀ]VRwAJJ ge`_pj)D˗/cԩ6Ox6l~WEKBCCѼys͚5 8*:KAA-Z-Zkƈ#p59s& JѦM,]ԡ8q<jwF`ԯ_=͙FGGѣHA\_ pq<[nLJ~LmР81m߾Jݿ|7.""ƠAЦM6l@^0tPnܸ:uRҬW( 5YP#FU>[ :'OĪU7g0q}9ܖފb61ƍ[nŨQpQ̚5`_~՞I&E۷?[v,i6w8e&hbV8Crr2&LmBP@(bٲeʦ9Z lٲM+7L}:[???ԫWrQ> 9L&`~[ǏGƍ~z]ѣ4h qe]vY氰0`Vg+Wرcl!pƍCrr2>cF?[e3}sjj*'`0 **=R(d3 $]A%Z>5n\l,wyjѣѶm[<.YT5MT4w[DSPJ%,TknY⚚KK}%afpoK̹>rs9縺ѣXhsoݺŻ bݻw`:uJ Vd+QТE >4!Cy< F‰o|*\}O>0aV\ #%%ǎİ0,X۷G`` ?~rfϞÇ?ǯ7x666t݋ݻk׮ C0`ggg-pgF¼yuVt &c*vVpB&M˜1cw}x`iiѣG?9o޸93gb7H(>j5Q4Mm ćn;x~ =]g;7"::QQQΆ0yd :0oxݺuy%[ҐV͍)%%b1M:UNY>pQ}~Wd޾};]vz oܸͽ/ |$ߺEDDm^aꂡ]O::mKsf$ @7lj/9w! @ӊ=vM7rUTZ-Q(b'6 (C(8~ζUǏq >ʕ+1cQ3##SL7Si`h);/kQQz>J E|` ~WȪC(KJegmU`w 6ln_Eaꂡ]쬎^wʂ"ä{5&b~- hxyyaժUyaڴix!VX/"<<}sw Ν;Xh;wC _|gkll,ڴiر[ɓ'|^.6`Eb-[Ē%KpBO? &`hݺ5Ξ= >/MݤشiTz!$$|k֬A@@d26l 6a+D 3gΘ5rᮅ6l[")) !!![.r9z/b+uŨM777|zepvvF&M0zh@;l0hB؄hڴ)ƍǿs=I&Xd ZhL ˶mбcGX[[Grrr"͛ѹsg =zѣGwCLixr[;Ǝ KKK^>h44+:7]9: KBG~!F-Ã:w@DDO Z͇c =:eu-ZׯyA2S,o_Цw.kO"ٳq ԫWvvv̙3ѰaCVŷ~A]0Q[؜eYp2?> _]^BB:tP𦮃P(VL&CJ\m2%KzDTxh KLbv)((;@ `سg,Y8!!F뎜={7p5YÜ|s#Qz6x`oooBpn) ?ޜ{yp\rr2?~\!󑖖+kr`a*Z2 0^܃P(,V|$$$EoBLL Zj+++ܹsF˗/###[XX0uqO,<.SvA,CR!99h`<~8T*^Oֳ'11QPP?SXor9:w( is=L\ph ݺu+N8ӧO.4o>rΝw@.]2ѣGf.Sv^{sA.(ؿ?$z^tgd2C `ƌUmIl@AU)Usy>,--R0x1H$Ŋ777&L믿R޴9=W+@P <<jƍ5*uΓwwwԭ[/h48{,?KR8;;:t(6n܈˗C* III,--#//ZӧOT*3f >q=̟?ڵC=W,o_O> VݻwuA||<.\>^l۶-Zl˗C gϞP*8poߎb?ڵC˖-1{lB4k ׮]Æ 0yd%Sv311Qڛ{nvvv:u*rrr }vĠ]vYU8qjaaagϞT9{,fϞ!C`ܹq!22BMGDhԨZ-ܹ[T*n:ܹ7aj˖-ѿ|ܹs?:t(n޼Yf|PWcŇήz]Z-Y[X/7S)ר]t_P,6ҢY3j3ʊ5nlӧOO>$˩nݺ4zh:x ۷… I"Pnnޱ!!!zK8@M6%\N-Z  7cWqq3[ϗݻI*RӦM)""բ?̛-[P H"'ݽ{.]J"z7o@&DB>>>4c 6z3g$KKK裏^zdaaAz3r'Q̞Ǔ'IRrrrжmی)ܻwJdeeEZ3fPZZ}7˔׾,N$Jˋ/^L4icԫ{w >MMPϠ i*h׮MUNHH 4bĈb;~8 ֭[ԬY3@4yd3gЛ)v @;v/7KPvhN^^IYUџjVIaiI6nmP6mȷIMg&Z5oN~>>gG[[psBIn_j3j "DB=GovF# oMݷު_4 l24iB666F#44˗(??H M'*|߽{7|'>tׯ)#GZpY_ Lw.Iж-WEnb cX,6 T]G̙382fc֭صkOw}|QNbvIOO9k׮T*Í>|8mJŽ;ЦM~ p%?aaaF8tsۥK4jk׮}6j"\·Ѯ:& ]cb#"xxxaÆz)JDFFk׮pttD"u^/->>ğcС3gv؁.F5F$]gX\ ƒjOKuڵk1bرcXf NZaM5 RYFϞ= ]@M6}o>aĈ|َ;&M*LիWq޽rS}k\K85T* *PO+VeÇGdd$6mTlb҉'p]L:OJJNNF߾}q#$$ >Dll,&NUVzmuر/?}t۷SLApp0ryEt`P* r/ĨZZn]!),\ .sp{ . ==z2;q!ꭟyfH$ 2D=ٖ9s`Μ9F剉hժ^Y^"..עb Z-ȨqY,[ |yѤIٳ+W4MyfUJBqU\EGDƲeˌ ٳKU("""]vŊ+0yvFcH$ "`0ʎG5qnڸ_uFǏc֭ƌA^x.RbTk8eGnjH|p7izzzII /`0JУ F]i8p ,--B/;v@~~XP(J\'$a;Bi/#mWpZoRYbh NXg0ÉvB%b  gƍ =F(ŝ;w*f]j[Y-(ix@ Z7iYcTFlTrŕ<5`0*N|<}\r8Jǽ8nڴ 1h ŷz J͹)gjF{8bh6|Z7hSH>^=,6XML>L|0P(沈>׹իWKݣGb͐ "=O6ǘ1ctRDFFI&OŋKYFMD$m]!QPP*+6XZ)Gm Z^`8χH$jy氳Á0zbD" :/?x{{P.c߾}ӧ&L+W"((HIIcpu4o޼\v8pXvj".nv ȀD"@ 7) ,D`T VM|D"!&&%<iii&'p")) ~- hxyyaժU/f͚Aja0|4)>RRR  kMb5 HuQl`Ht=ʓ51Jnݺ@D9sfu NӧO#-- ~ꍁ:u?1cƘUe۽[3PH$5&Ս nlp%=<<e˖\4ݻw쮭AÛva0*w;xBVVVUlѣGo| C"x$,[ ٘0aBUR"}.].Yʏƌ!HвeK~eo@A"Ȱ ,D"[1`T<<mgƖ-[06$wƌ3lқ^<slpv C%;wĺuJ\ 4g'.6h.\lpfݔ* R߄r>tTMiӦU;F-!cDBԩSTCNIpoc\|P,w>*f?Qv8χL&u3/HJS#ݝW(FXlfݔ֭C؇B,q&hܤI[`ET"7'Fo;2M0-烈T2|T+FN R`uFcN7؄SV<dT:C`0ʏRDnn.C`Fiu;@PBf0GP繮27#_$ AvQT`T,xarm~~> 0^9Q%x_ q; mlyLf֌/?֭2 y$ !accHB@ۢs P(B཯wB [[{ˢkn -oeeB'b4ĤP*P*jl0`T:a`0*RK/NLL@zZ 33_OoUލSl~PTx!>}Z`媤={J *=n#l>ŵn"6:פ89?2bД"+$B!ls6Rtχ{NsJ=`0*R  @@d2ԭW 7qtDڳgx >}Lddd ++ YYYFFF222 J,ddd hFU \6 mAn0ō7z}DGVVV󑟟p'ʠnzB /7l+Z^LƯTE(hӶ- == \_Vhx!T*$52lwRץTFe#b9 FBDχ@ @zݸ1Ҟ=C[x)Ҟ=ógsFԩ:u`ggXYYAneWWWX[[aeeUcm7@O/S}R!h4*$9222=1<xuy2 Ñi|ŵ&_?~(3+3yyyخ0-](C:e^J1J:* y>*qJǏqφq?]ǰJc_L >0(tF\ 0ǩo"5ΩH];tV:Nvv6_@?)J!/RŹ+ ݜ`Tګ{^y1LLOVN{{{$:(6< F# xBgdd@V#3#@ |]g!L l3:GȨQ…Şׯze/ˀNSx]/.ey8G8 )o.Z挵:l"ލ#x` l]\e3={ 33YFNN푕'fdd ;+ JQ(P~}޽;'9j*rωbWz,(T*b@j4Y\* O<1KMMrLbDƍϺ b91`0/72{ՙSK,BEo62ɕ%h^^^hw!]L8;;77OWfjkt5yn SL2RIꊗ7w+`TPԛL6 5ZʀZ/ҪU(88nݺLV6QE瓅Q^ht!tUJJJ"~zkR)''G X,&"w>>\j_RRROiݿPdd^˗z*=~O?df߾}YfFyyyQuL ? FSf1JhĈ}dܜ:u"`ܹB 4Kʕ+CVKnnndaaAz?2<==h֭]ftަM{gT>`ݻwS$ 'uԽ{wѣG+BNNNdiiIhܹezǜoNx/‚J%EGGLR.\H׮]EJԬY3zQU(L|T4nݢUVHɢEH,Çҥ ;1bթS?/tm""0a9::ƍz ie:OIxyyLDDdaaAׯ_WTԿ?6mD:rH}!"2e }mhҤIl^=^?ŞT*%H_5{&hZaooOVY燉FW4lؐ\]])88.]J'{$ 8[oIx{{S>}7 g]vԷo_}:~^[0枧$O]tTYf}?P(+?>b./DD:u⯏oߞ WOѐ-M2/ܹ7ENNQpp0}XQPDD5nܘiժUVf1y6ۥDhh(6n܈wɓ۷/._?_lCJBB:tž={pf͛7p۷Ϩ;w ==Jzqp߿ڵ3G/@VplذDŽ W}ILLR䯏9qmT*k)miiX߿yyyhժ0f}޽{?>ڵk=zzmÝ;wrJlڴ 1bve4-PŮ<۷Shh(B ?erWC$۷o[gԩ$(++K4~x$TJNNN4`ڶm}w&חR)yyyŋۛfΜY7eȐ!&)Ӈr9խ[FM$}RtRih…$H(77Wi[l D"!OOO{.m޼ښ$ Ќ3B;AR)((/K.UY>'Oꫯ"((;vī DRf2 k׮*Ֆ7obڵظq#~DKնٳ|#;vDNTZf2^k֬Ajj*<==!He˖믿ԩS<C\lڴ W?#GbԨQhҤIUx0QIMMӧ#;wf{|زe j999HHHXдiS^lj0Oɣ3f FuVi \;w9}4|||x1[[۪6`T#ի}bĈ0&>᯿2#\kPPb&]<~ׯaaaqaРAlQFYaQ2jIII|ȩS nݺdTyyyH}=Bx\'HII))HMMžѰh)HhzT y`gg@pyunvH$NRP@$@GTTbccPTi .gȑ#pqqH׮]QN6$9993s&.[6lut/P[Y E"^n5$ b1ml666ŐJ^& [[BdN))$5=?/2>P(+WWW8;; ...pvq< 3O׭][7o(?w=sssh`cc<(J۾r9{J,H`mmɄ ӷor{.VX͛7aaaxXN"`Q>4 Ο?ϋÇAAA B.]XsRRRʝvI}!֭g‚ṕpB!EYYYݧ:u pQAAJBNN^2S=rStRL&C~~>rF\R.L&/NdHOGZZӑgL&GFpwwwhۮ|6 ^ȴׯcúu3gpر m"+WVRPPh^ϟСC1b`T4L|0*FW9#G-ڥK4hРΝ;@Z86/^  vjXZZ;jdeeUyaem͋]rssoV;...z! C nޏ᛿ǰ D+o_g]] dee!;;9fX[[C*VG) XXXƆnC*9˗ѴiS=r 5,*d^QQQe˝3*$-BDk l>gϞhذa~gĒ%K?bȐ!|\yyjx [ªk "  mSC4iii * jYY ^FNNͰ3;!2 VVVQ( `mm +6aaaW:y/]2*7Y)((@NQHCZ蒜ltlfsaeeLh4h4d٩T*K BCH*AAxg@j+ځ;v ** 7FÇiӦUmDhhǼy Hx1ңGxxxaeeH 4F~zkl;p2>RVnnKDԹ'(ӰL&BʪpP{iW._F޽{|'rtA^^6GE=׹^R..*ݜGѶ];;&ʼn 1.: .Ν;Ѻukl  ǔrFáR֠ x .x ҥ ڷo5kuJ"//[ Tj?CAAҋ<,bvӜB!7t @aj3"ȀV-10PeQF7SܣAVIqK#''7oի#G̙30{􄧧'Fx!3Rɋ)S !!j8~8= +^- F9GW<J'NDnJΝêU#""ХKZ9eQ`QW @_| "BhZޥqFرK.ŰaLsCTV{x90|7쒜7|YYYMygϞ!,, .\@zun"a2=2e xKnn.>}1cƠy8G^^krPPPDR!9х/ۺ IDAThٲ%1i$;bcc1h 4j'ODDDn޼/ Fy>՞<|7Xt) hT*qekݻѨQ<znχJBhh(v؁\r;uaÆ Oj*Þj;}0n8ܽ{2 jDJP H$HRXZZ!GaΜ94i.V:kY0'>qmCnn.$ 3gcӦMl!0FF%33ؼy3D"D"Q]EDVC];z 999P|C?ƚ5kخӌ jB@PPP|<{x!<烈0||F rrr0qD FN<ѥ )Qhʘ󑖖]b&Qx)k࣏>2Zm 05񛿕uq,y0\$qxzz"..r9 ADXj7o)S35vaJXY[W* FIpZ0aЫjHR8:: hذ!4hԫWpuu QQ05T*H$|0^q5bDFFExݛZJbFH$B?6n4*:X֠Rx|0^D@BMŮ FuFy>/V GP(Zf—Z['!ʆK6veF-2 6@ UmYC ࣏>jS^ʼnr`05T*^|V*D׮]D'''t =+ #""+WjSj-\y> 6ۅQ((c%99}ŕ+W( <|8q"VZ˗/WB&M0`~_Ƌ]`Qk|&>T*Wbʕ e˖U;#wyͨa&> vaʒpa\t Ǐ7 oСC|Yjj*Ǝ 777HRxxx`0j[ _ L-Z &&{nkiv6ե|||~z:6m@ 7c%5k5k'77f͂,,,PN 8ׯ_7ɓ' r~~~;wn Wξয়~B˖-!Hлwoܽ{Cƍamm x{{czˌ߽{w?@ ѣzmڴAfd05E|ر0iҤI$gСCܽ{>|||%K8urޱ#GP(D޽!Hcիbbbн{wѣ&Nhd|D=z}1j(H$^#GBբW^ԩw s_vc̘1hѢr> %XItaUb]rqq1 &ڵk^ydd$9seׯ'4tPJKKwEYft9<33lmmuzms;wBFeQQQkt{GO}oFm`Sm %T*HR߼y+ hҤw"޸uV(wmn ///Ç>F[[[(,oݺcǎի|F78T۷oG@@كݻcѢE0ydSv @^ك}[npqq] h޼9+f``  8vܹͤy^J:ms"Kw絅Co&fϞm>V[W9\ ???#''–-[  ocXhΜ9V͜(d0^V` EA4[oرcXp!~bǵk׌Wոy&xQ\z7.w[2 uŃо}rݼy-?4h(]b гgOrJٳ>D׮]+n!'>N| >hDEE!;;ɓ1tP#0k,ݻ7n+&LYfFh^u>}o߆P(DϞ=` p"!!K,Ν;h"B4jC QŔ)S 7nD@@@3olF-|h4d2*N |0L|0j Ғy>/ va0aQ+ćVLr|0Vj!+S>-uͨ4u= |0V%]VX?{gĵd!+ \EQܗVZwԥu׺zZ[k-zKmm vRj*nW֭źR\PB!3&!y̙wL&3yB6ؠ.JQl]b1t:̫ 0\@]([lNE"ِݭjϊ+0 /^\]qa0rHO=4BR#`󑕕EwˎUValܸJNNƲep5ܹsXlƌ?0c 0 cǎ܎04ln8^X {Ƨ~ Z͵=}4)/-- cǎ|]v9 .:PtnJZZt 27ChѢO1sL#..[6a"!!}uݩSp̟?1x`\z۷ǤIP(?~gƗ_~V׮]ѭ[7Q( &;t͛#F@*zZB) aX FÇ+^ȑ#8w6lR-ܹ3"""w^lܸޖm۶^{5_~e\v 7nBt>}b UVW^\/i):BDZc0 .\t}TTBBB`XpDGGYfDhڴ)-Zl0 >M6]v x饗 `R޷oV^VZA"e˖ڮ]cƌ 60`yll,{9T*T*DFFbܹx[o&LPd݄ jXdhĮ]бcGlْ;+Wg 6 GuoxѸqc|7 Ba |PjX  ѧO4n[l~ȹ? h"|( J ҦE o7M#BL8e[>{l۷]nkZɢEr n͛ ҽ{wr"mݺ (ѣGǏsoݺEx<1b۷d޽ED:uTd{]ŋs٦GD  导  $33[VNRNk˩Sɓ' uVUBBH=E"٧P(R#`@T[/&eXt)[ 8`2m65^|4hZ՞f͚^`:tV==qDqTRoFrr2ڴi-oР[ۧZnk'N`ǎ9s& ''̵ɱ;ߞ*N:E}a ۘ`EsE( m+>v_> ɓ' iӦqv܉c"00ƍC6mPn]/Xn݃Se[Tzb L2m۶円w1c 00333ض*z-$$$pc׮]0 ED ]'pʢR{l`ECC&ym?JUJ{u2m4߿ 5k6oތ:u ::k; 88/_{f˂l3 Q &k׮ؾ};p ܹ˗/Ǚ3gۯB!Ccܼy͚5öm۠R/j +n߾2>ƛxzÙ(xR.S(>2=0`4h͛7ѣG8|0&O6޽{ѣS7~Ymg'M4… qAc˖-ȰZj@Gؠ҄ĉ9r$b:t(,0L%8rrr`Z{>}%)ؘ>V͔)Spe̞=SNd2(J\r!l߾Lm`X ^jd2o{`2 .](H-z@S뇺ub۶mضm!vY.,SNEXXbccaB9|0SZ\[n"-N@](5v؅q w*N2111رcz&Mح>}:V^Ν;{@bbvPn]\H$x3gNUVW^AXXuVH$%nӦ pb|;1>#4mڔ9HR:t ¬YqF* >į7nǖÇw^&;|; -4F@F@V|nȡhԨ#G@(">>qqqh޼9V\ @7xL}mL={^{ "_5vڅM6AѠ^zڵ+vO>8prrr*:k?Fvv6fϞ]V̟Dlݺ DTTΝcǖ\l߾-[Dhhh"gBa7^(JZF?g'O /Ttת%GEX2p1sx!Ri7_џF_~(*eA( 9wQ&N;w.^Qf̙3kvZ,lc>ߴihQX:BPAx<4l ljgQdž YfUtWe͚5r ֬Ym!(ш jP+RRܸ4{:ue˖NJ+*;Nٳg/^#F8ʹ)+lbV= C 0Ps.\rvҊ 0L^VP:AQ|B  L&B P(T|Pj<x(5 ܵ`𩻝B~a!FmڶQ(*>(5 NT|P|Yx> T|Pj p':R(PAQz |P| `]B)JBs3}ۺA<J s1a@54BqP| PCFa+>ÀkhZ^R˽w}dv̤rU/7| 3D"HRA&A(B&C <J @PT0 R ~A@UVDž^ @ϭc1FS(z=|9`49o^>?01rhoKH@=缼<mTEFFY1"Z X ^Q χBA*(X,Z  [X̉sW:y۷m+¦obP,s%B!r90 xl/T H@v*.A@FХkWt B^zmhǏCVC 77ZZ9j54 ZjV\`XW.??* d2$ g^C+@ #Q>Y,dggtԩS8j/?( 7KmĀ`T*ԭW]uj<Z ZP.X,h4Ëzm۶R AFaP iS0YYYy&'O _ *02 2 rʀ4hz(Jd2KP._^zGo`dNN6\9lLBS`vFnnˡ/e%9]NWƓ'Oq8v[g mld[^B+#Fn޸+|P(C/Rl׎v) H@N:UϺp,Coΰ}mv]6q,|>ߩg&`v˜|nV-el6sp&* =z[gEwBH.SFq?>> 6.{y.u-jyj4ܿ1LP[8{8{zfC_~](˰pāEnZNbBqWD IDATos%<.@wW9n)t)v=R BP(eZBp\p;wnP(j ֭[+ CBᨈ" ABH$EE) PAP8BT|P(P( z>(Jy@B᠞ RPAP8BT|P(_y>5ja͙3999:u*MDDLbg'&&'Oz*gmyTm. ݻ2e Xd}dd$rrr0o< ܼy]z/ƾ}ڿؽMu=o  #)) 0qDteUVq?}4[nܲSNatիh6lhwަ7JՆP(PrFp|teqơm۶ӧOvڈ>}:!0hܸ1~@׮]!_~7W_Edd$?޽{C" ::e,XLy7333R0c @BBPV-~4irf8.nQFUVX "fV[RRT-Z`ƌ0L. `6l?xԿ7py\8??Ǿ{]ضu++lŚ>š>p|z-9}:L1#GޫC+W謶 ŎܹsJ+tFy3Xr9I&۷/K> `Ϟ= ڵ+.\Gxx8fΜ'NwE6m9s 00gΜ@Ղa 4GϞ=1x`}NHH pm4jԈ[>e>|׮]RIJe J/̙3~znxlذ!0qDo'N 33Jyw뇩SbѰX,_c\~_ !?`6m_ٌ'O :^b, 4 NoS՜4L!9j5aa6_dB^n. ;; g)2 ԁH$T*B@Pp0r9* 0(WT_χ?*;xqB6h4… 0 Meغu+=zT< @/^ѣ 8p :t-ߴi~WT*txwŃ0j(|gUVnݺ5ڵk8{,m6,[n}eݵy}ܻwx7Æ C(Jmhڴ) nYϞ=`Mi0o_d2{v@@T\ڵk(xxKRbjaZll6sjr6w#wy^&7o܀Vh4bİa-)%T-mrd2He2w_6T|P(5( cGvv6N>]0+Ο?KgϞvX?`gϞl`-Bl2dff~v 6liТE x<\~jŌ3ЧO3kw޽.\@ZZrsssmۿ㱻kݮ_~v!3%%֭Ctt45ka :?tANO?Ǜo"88|>{Bp?- PBvv6j5u:hZqj5ԅ [d2DMNVS R2 VJX"X, *cͺfqBff;gk5͛b*NUT|P(5zGHLLDHHtۼ< 8k׮-}kI&.y =R)"##6gΜApp0OaܹsŏD"Aƍq5_~+W?PWq17sEXXa_mSkFxxs!**{:;o`0;#`L6 111`.& stطw/󑟟aRA,C"@RA"BX‡uU*(c/ lYaɰ6fj& ˜u9X롵َ&*??P( ˹W(*Jn.}տ;]:}ziN@RJFdd$Μ9pa0ЧO\x>l'%%nݺ.V<>}=xvRR{9aJŽc]Znk׮Xp!ϟf͚(#?@'N@ ؝oSZiӦٵsVEVemt6q.Rhx0T xx<뇰%I@R?~<=N:ɓH$Ctt4Ν;;ϯTХKM&~w,Z@Aٳg1{lv/^ĤI얱Cvn߾b\xH;j [ll:u؉VCzw;w"33Νd*%p֭[ؼy3pC@ ==.:t耫W">>iii5k.x4E+ay5k!?~<5jwbŊxgĐx 6}l6L䔕6mZJ Ϗ}F`#FJↄ*ZBrt ? NHT$P]xGRR|>:u`ȅyXСCB(x뭷pA :ӧOGFF+"=x5j{4h ;HOO7|Eb3\q'6Ba)III juvƎ\L6 ={IJe0l0%I[Ҋ>JU'<2x0L>Kس{7RRR@&>Bi>Ѕ_|asCǥAa 6mڄ9sإ/999vP`K|pQjD"h0ٕ7;PTZBVVӶ~~~! tQV*P"qc< ]$ARfJTn[m6=#Urj!++ FE ǃRcÊ HRH$0 E&A$q`$FG֭[s[8._ BۨH$rYBV|xidfvj*z}**6  MIZFAvV?~Ǐ#deeɓ'zO<;wUSTUڵkN: Pʹ=4#R1;)-B3gӻ499h4NnxK/Pj5ĉqND"rPJmϧK$0Ug|>Q^=D"D"{ yR(V=z˗83=Bff&gfB(Vڨ]6k77DPp7ɛj4\.ymK%>~ZV[??3!(([A ^ygXdp8Ja0O|**Ng=hf6bN<}xCVԿWKۉXNcʓ\wSǜ '@JNٌ@"*>uEDDt8!PGÊz>Q|XVlk4m̫Stӧc͜ n ;kKsD;&NV{P)cpj1& & ֬O>©NA6LbÆ >_#fNcO$ 839r\t- ;dP.Y޴)T#R\3A-*' x{z>bA~~~Z +>wS'ORQݻ7Μ92###33@ƣGx!gfXNg_;%+)ְaQ,t產޽#G=H0\)_צrO]D", t:Y`oR(aXW_qiə-]ǡ+CA6ga~6l19ZDfF>|gA^n..=zǙx233JZPN.=VhZ<*Xݻ63|r@}*??;Bj6V1\ω3/w'4vxt{on䟳g~CC]J#<uC$z>KͰ˗._+V $$;Wj;lWa :;ݺwG¹IrsF| }u:\zd2AC,[Tf'S%@ Bh P՜jB$!qc4juCڵ:uVZUt첒>XV(JԪ]<Jf#""m۵C_@V ٌ lj OBik[Nǥr;8o< _׮ZnM.qV1Xdћ0 222ɺu2???H =Eru:rss[X@װS He2H$( _???)@w-V-$'n\^X0^.RʆP(^TCa6'A\RxK*PP}ŇhX,{ש[W3ˮ^_~|>cF`(J!< D}]ڰ!Wї}+P(JC ܿ3gϺȰ{. (곰ceaadee!0(=c„ EBBKq)ܹs5!Cq^d|СC3z0 8Zj=TW^իW=l`ؾsgEwRFf3*6 G`Ν;#""{ƍ>7mx׼ڿÇc^Ya?Cܸe'LHHHpنUƍ Za_U@lAT=XTۻx.&LV"F#vڅ;e˖sѬY3rD"4m-*e08|06mڄvA(⥗^PamJc߾}Xz5ZjD-[믿ڭ]c 6l00`'8^P(@Ann.D 0 R]JQ0F`P=z݄ d$$$piC!;;?yݻ7ׯ@7n`8y$NL2c "<<QQQ sٗ؟qV[kbAP11ШQ#tGEffݺm۶A(rH={7nĒ%Kcxp)ܼyP\xnٳg/߿`ꫯx@֭ѣG@^0i$L4ex,.>v`L] VWG\Z=v54xO8;v`̙ R<Mze/ҠjSzz:5kfg{Сĉ}Ghh(RSSާ/,ק.<RGl[]QOU-"&&7o,rbϞ=v8߿?>sB|xK޸q#zꅡCzx*vUm;B=V|Klꫯ⭷BBB'>vΝ;1vXbܸqhӦ ֭_~֭+󐰷+ a6! hJ%>0[\piVI֓'n ) lǃH$\./P(0dر{۶mT*vqeԩS[>{>;%Ee|X,W_}L*5** {E߾}n:߿s2`oٮL ,p^%a6! ka'$$ -- 'Nȑ#gI^^ݻ=z oKqouvI.] VWG\ZlGU| *JգH&>x<Ý\~Pn]l۶ R?LR+Wjrؾ}{Kn2x>|*>XPz(;v !!SNʼn'0m4;o RGuKKP(CC\X*RlaR||;1>#4m]tk3}t^;wFݑD}eC[.V\|H$x<,X+.Q!,(IUUPh7sU NxPA)h ϣa?Fvv6fϞ]d}LL B!͛cʕx7g_ٗdسg~m_~~~^W "Y VWG\ZcU caLhR.QXF5d>ǃah߾}mB!bbbSdl= W?ǏK.Y#))e|+>{8 (o| 6< >.h IDAT Crr2V\5k֔i߾*vaXv->|X磪y=ҐzB 58>+J|0 z쉌GSi]XJRTjMQ6棪HHH p }:6n贍b@Ppe3Fm+>(Ge> X#0\uJG(rsTe9}4W_ZZVZa\>(e˖yEo) Q &}0 \^eԫ j`(J| ˬSK⃽&=vݺusNPv:En8fD +aG)@,vP ɓ> TmiG>}l2G\TCPߟz>*`cL, -v.,|>T($͊Lǀg3({=oigff7D 燰0̝;999\f}vXܙ=Zaҥh޼9D"ꫯƍEh0w\4hR[Ƈ~fjRu@c>* j`Vͨd2L|GI3A]l7tWׄa÷|̌ X׻sX`⣤SOqxΝ;v,1n8iu/u֕yvtffw{hڴ)._\nb26Zl N͛7ѷo2߰m|T4֭CDDzud?KfaEyݻwcTvARUYaZ ,@\\\f{*+>V+W]r4>;i{#^w)(YQbZAJR N &Nݻhذ!G~XQ7tD 8Uh^ÿ(QFdbso}{:;D"E֙fܺu 2W>{z,bԫWGΝ! QV-ܺuNk^4iIIIڵ+_テlFxx8+uHFV*\Rmy<j5|jÑWtW׮]Ñ#Ge"Ro ѤIbzf\~k֬A yv<|tҤL&Z M6H$BͱyR(bccsARAR!22sǏvx>X,t裏cܾ}r/"V\cЯ_?XbEQQQx!޽4[va2ѣGcܹPTO>9socǎv4h0>}@ξ֮]y(aGq{Kb@+`ɒ%P qR~:㑚0ۘ:u'_χ]p!Gm> oTٙ=aɒ%8x F'Et{mۖ-ɱggٲe駟;`߾}ٳ'q8p}E^-Bbb" hԮ]'ODJJG瀽=qZNmɄ۩jL:WlFAn޼cxx1e;֥Wbl65dI:ҭK>qDB;wL2B-ʕ+qh4̙3={z^s0 |>rJpD7Ɩ-[= \p-i Gplf+X-A ;v %%G֭[dlagKLL B!͛cʕx7*mw FRR.]`˖-[.f͚KB&qmY~m_~~~ מKqvJ%~z޽֭Cƍ1fL2ӪU+?~b˖-r7|Owg IRn@`ض Z\x<cԨQ1bD1yyyV{udڵp֬Ywy[fg-# 44111y&5k֭[Gظq#zꅡCʎ-cƌիݻh۶-,Y‰O~ԩScWZ]ȑ#Ѿ}{|'XvsR<>ѳ[7ҦE ٮ_mI}LL @퐳<{l۷]Ǔ ׯ'oVNHHڵkT:I֘eo}G|h҄ݻ,:8p7(J"Ɉ@ BDGGMw!Ɏ'B|aERPÏay!W"_~Y=h4}DbWF"DB5jD.\H~wbXܶ}ި!=w[#""r%2m4ҺukT* } ]I5cܵO>\ƤIPRV-g1_IϞ=I~~~-Z.]֖+\.}N>l0''OҥKb \۶mC߾}ѨQ#/k(8}V5!`MZ=|\~{Ŏ;_A,Cre2ѧj 85UaJGx,f 2'NhR[lI&_F&MJe[rRJK6XhҤGvWX)Sm۶GTTw1c 00УRUԌ>zXN]BIxzׯAax pAdffbڴi\;_PpWfOj6mǘ?cطo 8!i&H' 3 tv˚5k_|ѭ~; &vm؅R}aۻBNÇs=z4 2uK|x쭴toa) &k׮ؾ};p ܹ˗/Ǚ3gaxwKvإ&~χL&ht߳L6 GBBf͚͛7N:x"+}lćp#O~z\xGEbb".]X}ܽ>}`8r K3;[/A[{j/^Ğ={Я_?Nkd2äI)0ҥ QFO>u0w\;:gϞ2öz>LF#  OO4ǔ)S|r̞=.[ѣvo۶mÓ'O8~>|8>3ٳ.0c x+>؛hjf!** QQQX`qyػw/\HV<,^&.۰߇bX,.r2{i! ??)n!i"m=IgVuiR'Mh4hP(a>VZW^yaaa֭[!HGiQ#]F#rssKU`4'zʔ);лw"ResгgO4i}RSS'O͛Elx Oj%x 6&'HE"[n֭-ZtO8x ;\`.ΛBaZ+.A|OHb'CꞤ3{+ݺ4)=zٳg `vID믱k.lڴ C׮]{nigiQ]|jH  (?$۷'RrҶm[2c ry 0 ?CuF,\TJyg8/\[Wӕ_~ߟ(JHFM]V$֓}Bș3gHΝT*%gx!>}:_> $44̞=dgg۵+.5}uNϣ#>$CC/!@v|= Ɉhtk{wz*ٰa&r]<<#Ұ^=od? j%B2t(!۩D cVpʇ-[)S!};dܫNRm CEtŇ'B3׻iiYD-D.zj ˝۷IfGh҄L2}(1OFGBIwaܫa_oI!\}X\PJb!@gI9, fT}c>Fc ˂H$ɼ1a2lbYS\b 0 ŋWtW߃a9ҫv|>Q,.Fs}R8F=& i$ST|؎SQaڢBܤrӀSۘJy3\jƍ}d,[ ׮]>Ν;e˖a̘1Da3f08v! CÆ D^Gll,z`.UwOVO&sc>]wyA 8-c>*>*;ocpaN?? 6|pj[?Aa-tVG^n.BaR2deKChѢO1sL#..[6a"!!}uݩSp̟?o <W^E1i$( }\.dxXjzꅸ"Q|F2 &N&ܱN4LEayW= v<z>Xj}*>lftƱc0 W}Б(bΝ;Ff !дiS,Zvǃa>|6mBv  Y0  Ν;cΝ 0-c݋ VlWx, J!HX9O JQV#8$9>,:w{޳0|w|20 PPPgym۶H$ױadee!++˦yRӨi3f̀dȑ#SO!33qqqh׮+9yyy裏0|$f5 &MhDvv6>C5 vxp1w!2e;HKKc ʩSVY:t`׭fnXv-ݻ:ԩ.Hdcv޳B3>^TVVB,\4Za|АL1@.}MC^ʋϥKd9IݼI:thV՜{w.]ŋɄ_& yi^ ?,'$$PHܹc\D ru82p@rxq~ZIaa![͛D(X:m9޺ukҧO?3w6Br @on̠AH$"h"IAA{,((9.[lowZkѱ];~&cPz=3II!{RR9Nϣ\bbZ鹤65oܐ!#*M-aCm> P&Y] #f̘a'***{;vd`ܹ֭!zj .]ݻww7ԤiӦYl#}}דs]fq<44M=2SNEee%8h48y$F@S %KDZ] ~ni^φv:|EFq1L8|0ƎC&A.#22ӦMñc,r%i6eSSSy-cֻwofMkBCCmt5B:ҹkvpLVT2; m۶ /Ǐ[ɓ'QPP81qD`ҤI֭ 6ms>_T )) 3gDTTk8p &Lò111xא6j"&pJQT l7C +3S(Jaa!bccqY_Dpp0JJJLݻSL޽{-ueY(bڵ4iM4ٱĚ 6ݻ9s& ǢL۶mܹs4h{JDh1F6m5նp5ddd` .)Pi=Va.qqq8~8aԨQlE!00999i>Gmk:M2 qE;wĪUtez=GmժFƍGzz:T*8{,ܹ?Z!A`iNzH$F{Q@84zhdgg#)) K,h4b׮]6:fرcÇ#66=~5:u 8xyCeCCCcS&>>k֬[o/:m:]Ъ#<77-fDҸ-͝А܅eOJg YFP~ӧ1c V?cРAjҐܞ$,, ˖-ɓ'믿b޽yWOhkSiZZ߿s_?ƌ:JPmh40Llh/SX XpslݑW"W^bJIDAT:{ѣ֬Ycq|Æ @tttŋ_ѣuj'YVم[ܗАҀPgc.dN|d] c3gDNNح)P*͵߿mo?`q;wd=jM@]CD΄aÆ!88HOO!"ʅ2gt ۶m֭[yw>}4S[rssuZFujvћGZgQ[ ^.K.իWq {~,YΉ e˖Yuaq=.FԸG0*| |@uڊ+еkWHRn111~:o]HJJBxx8R)"""k.kW_Ehh($ :uꄅ BѸFg< kÇ=Z>dY.3g΄P(ā0tPY|?w\_~XhNH\t^PwXf kײVdd$,Y۷#)) /|||0k,uSӧO;,0 &N<_]ta.rNBǎ{ :VXsk׮x(J;p:h>ZP1éȉ%%%iNnիW\묿SS.ш@RR`ӦMh۶-&\˗~TSS*|4a}>4Ԯ5^Cի3gm۶z*BCC-ٳ!JT\\'|wɓѵkW`˖-8s m^6:˝i|>QXXzQK *|BVX ;vİagY8RV^ Xݻwcڵ+֬YHW^yo}}}qزe $ N T;vСCصkJKK ##ݺusZ70xgq h4>`SN͛V`ܟg`۶mDjj*^za…8qbexGѾ}:Tk:,>-C0H$tlB{8h4eo8 c5q8Nj%K`֬Y8pv܉u՛wؼy3V\I&EQ. CD }B%F@Xba?k0d…6u͝;hZ;wԩp||<@>lQmFG<㙙d9|l.]jՌRܺ5׿-61@4v=9@6oMq/^;o_~~4<@59"a~={ڵk@N"˖-#˖-#/&Htt4=b ewA!DBڴiCz=!C_SPP@q9?dB!ڵ# rN.&BxbR!sg&2Wɝ۷ޏa|P1]Ur5^4<ݻ7 # <<׃x̘1܎;"&&waddd ""fO8]icsX4G8Z;Baao?իWcX|y5 .hĂ \1n8k׮Eiiiw.Ds(zg@^^Ξ= ѩg= 磼)0 t邼z W_S]aHRwn݊27vSqFbƍaZم zP8!4|W_}XnaÆ:(Bh>sBQu>/^s:rmx=OO|H$ddfB(}jӧV\}|M#G`刍却-""2H,/4GJs.曼A u C.^CVnZ38djQ1u8pT_d2 ??S] lLvO?ٔ͛7k4X8˝i4P(!CGǻɕXl݁cǎ+/hć[B$A$a3ϠKxx_|p(|p#"b1N<ѣG#991b:t耲2ܾ}gΜݔիWm~_}޽ >222ЧO^GY.֭C߾}T-,oQ 7n}lڴ&^_C:ҥK8vFJzp ?7om; ]\:]Ъl)olrJ9s-±c0x`( ĉxlӧcԨQ ŭ[駟BTZh;8y$ƍiӦ!22W^ž}7|6rs'<|>>> XtiwaSa`2 }zk/0A3}zTm:sAFF>,XX,ԩS]6=S.oW[뺭C]_֭[ؼyrM6q=W*x"{=bӦMXj._ &`69W\Arr2?ѣGҥKҥ [&00/^ĬYpiB||<\Ά ;ǖ-[\/;d66pJHt+/^ t‡NXxVdTS-‡H$j-f\支 ӧOwEbb"]sܸqHIIqZ.((}VɵiO>AMA3q80 Bi{yqԿj@> DFhٳǩ|4f`[4>>> Ž=QavPo*xbn_EEz.5d2Y8y"|xBdTS-kGcLVmvMȼ aPYY&2zi|(u6\>Tiv-IƄB!*++‡C;)<.XtCVzҒK7݉[.BA]jAe-h4-l2~DVc2,2z|#|x;N=u5 ^͇amviIB` Mf/|p.ސfEj>GK kKK|+* [rs8m|~C^K+|xq#\ w!2knT*8R0QìIK5-χ``=f/ MK|X;dFlM˥)i>ܒd]<{: PCW.[2 e.HRH$B0PjPR @JBZ0S( YFj=<- k͇ j@u5%%Kxo2PѰטP(0nw7̜=Q5n! Qa4z K5\C(B&`0xs5 q`vh40L&`1QwnՓrbggk!@a_ůn͝l*ygV =@jVf#Ǘ[n\|Pf! lڸ>H?=f2ڸJ¶iho6;TOg?څ-o0,DOљM ;PRRŽY%f!Z->8ό>d2vO>#"k>:Yظ~=qY W#EgW 9@RAT UUU(--e?  ORV0~S y7oݻ3xXnP((h cN 6k4AV :zj:1())NNCV F~֖d2c`zbڱA9;QTsN)v4xD___b=V y Ve˔}z=NKx8"""pԩeva|`޼s{iYœ?G` \*q`>8v mSmRH$B+6+**PY0#s/\.Ns4]J`TG^`ZFyy9QhJcGetZ7Xh4x!;;2|~%e2l|vc??? n4Y?]##ѻOy < n+u>BBB,^nJɁ"<TTT\/' *zWCqq1P\T"O?iPWrH  T*!8$P(PhYMTUUa Xjt:EB!~7s'Q{Q4%c>Wmxp$7pܶh_nM͕ٳ8v(q-}Xpק@rpd2t!Y+A(6KINOMŌS?JKKv :jTVVLe;PTUU+uz~0*U#S8򶞐rr6)YzU*`N%%%s6NH$hmBT"ukt*J%T*~=}πJ|e0HUUx~~>~ǘcwnd8v4 G͛.Jt C```*o̺qn]ci>HZXҹ UTv氒.:b1RҽGnݚ|`>|- Dۄ+/OLt3; JRH$2D"zвV#j8(9>ԄټxTu5 eeZm|___( ` /@bL!JpUUU zq9;uoycuZ+@tWo.?tH\]%7Uo\n]*Cyͪd{o*§.(<WlW'~ˮp&8c{>\.zq WZq{{i$ F]vؓ?䰌iW&z>'?DD׮.K`0@Ѱv=MI kT`[RRbfJ;3[L ,ɰ;5ccbNxOMTh\Ր/^Z9BHnѣFcƌ{/^xq7!S +d:IENDB`bcbio-nextgen-1.2.9/docs/contents/images/variant-calling-overview.svg000066400000000000000000002362211415626112400257510ustar00rootroot00000000000000 image/svg+xml Input reads(BAM or fastq) Variant calling overview Aligned reads (BAM) Callable regions (BED) Base qualityrecalibrationinput Prepared readsin region (BAM) Prepared readsin region (BAM) Called variants (VCF) Called variants (VCF) Combined rawvariants (VCF) Final annotatedvariants (VCF) Variantdatabase (GEMINI) Variantevaluationreport Alignment Post-alignment preparation:recalibration and realignment chr1:5000-6000 chr1:1000-2000 Variant calling: supportsmultiple approachesand multisample calling Merge variants Filter variants Parallel by callable regions bcbio-nextgen-1.2.9/docs/contents/installation.md000066400000000000000000000613711415626112400220710ustar00rootroot00000000000000# Installation ## Fresh installation (HPC cluster, server, AMI instance) ### 1. Install bcbio package and tools `bcbio_nextgen_install.py` script installs: - bcbio-nextgen python package; - python library dependencies; - third party analysis tools: ```bash wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/scripts/bcbio_nextgen_install.py python3 bcbio_nextgen_install.py [bcbio_path] --tooldir=[bcbio_tools_path] --nodata ``` You have to specify where to install bcbio in your filesystem and where to install tools, for example: ```bash python3 bcbio_nextgen_install.py /bcbio --tooldir=/bcbio/tools --nodata ``` or inside your home directory (make sure it has enough disk quota, 1.2.8 installation with no data takes ~37G - 44G depending on the filesystem): ```bash python3 bcbio_nextgen_install.py /home/user/bcbio --tooldir=/home/user/bcbio/tools --nodata ``` Installation takes 2h or more (depending on the throughput of your storage system and Internet connection). Recommended HPC job parameters for the installation process: 1 CPU core, 20 GB RAM (conda solves could take a lot of RAM). By default, bcbio_nextgen_install.py uses conda package manager (2h installation time without data as of bcbio1.2.8/2021-04-17), `--mamba` option switches to mamba package manager. The performance of conda vs mamba differs from version to version and the geographical location of the installation. Two examples: mid-2020 - conda installation took > 20h, sometimes w/o success, mamba installation - 30min, 2021/04 - conda installation ~ 2h, mamba installation is freezing, finished successfully after restart(s). Check if installation works: ```bash which bcbio_nextgen.py bcbio_nextgen.py --version ``` ### 2. Install data Bcbio needs reference files, indices, and databases. It is possible to install bcbio package and data at once, but we recommend to split these steps, because: - (i) some datatargets (dbNSFP, gnomad, snpEff) may take from tens of hours to several days to finish, they could break in the middle due to unstable connections, i.e. it is better to tackle them one by one; - (ii) you can re-use your data installation between bcbio instances. Data does not change much even between years, so you can just create symlinks `/old_bcbio/genomes -> /new_bcbio/genomes`, `/old_bcbio/galaxy/tool-data -> /new_bcbio/galaxy/tool-data`. - (iii) it is easier to debug conda/mamba issues (code installation) and cloudbiolinux issues (recipes) separately. ```bash bcbio_nextgen.py upgrade -u skip --genomes hg38 --aligners bwa ``` This command installs hg38 human reference genome and bwa aligner index - the bare minimum required to run germline or somatic variant calling pipelines. ## Installation notes - bcbio should install cleanly on Linux systems. For Mac OSX, we suggest trying [bcbio-vm](https://github.com/bcbio/bcbio-nextgen-vm) which runs bcbio on [Cloud](cloud) or isolates all the third party tools inside a Docker container. bcbio-vm is still a work in progress but not all of the dependencies bcbio uses install cleanly on OSX. - Don't run the installer with sudo or as the root user. Do not use directories with `:` in the name, it is not POSIX compliant and will cause installation failures. - To use custom mirrors for `conda-forge` and `bioconda` channels used during bcbio installation, set appropriate [channel alias](https://docs.conda.io/projects/conda/en/latest/user-guide/configuration/use-condarc.html#set-a-channel-alias-channel-alias) in your `.condarc` configuration file. - The machine will need to have some basic requirements for installing and running bcbio: * Python 3.x * Basic system setup for unpacking files: tar, gzip, unzip, bzip2, xz-utils * The git version control system () * wget for file retrieval () - Optional tool specific requirements: * Java 1.7, needed when running GATK < 3.6 or MuTect. This must be available in your path so typing `java -version` resolves a 1.7 version. bcbio distributes Java 8 as part of the Anaconda installation for recent versions of GATK and MuTect2. You can override the Java 8 installed with bcbio by setting `BCBIO_JAVA_HOME=/path/to/your/javadir` if you have the Java you want in `/path/to/your/javadir/bin/java`. * An OpenGL library, like [Mesa](https://www.mesa3d.org/) (On Ubuntu/deb systems: `libglu1-mesa`, On RedHat/rpm systems: `mesa-libGLU-devel`). This is only required for cancer heterogeneity analysis with BubbleTree. * The Pisces tumor-only variant callers requires the [Microsoft .NET runtime](https://docs.microsoft.com/en-us/dotnet/core/install/linux-package-managers). - The [bcbio-nextgen Dockerfile](https://github.com/bcbio/bcbio-nextgen/blob/master/Dockerfile#L5) contains the packages needed to install on bare Ubuntu systems. - The automated installer creates a fully integrated environment that allows simultaneous updates of the framework, third party tools and biological data. This offers the advantage over manual installation of being able to manage and evolve a consistent analysis environment as algorithms continue to evolve and improve. Installing this way is as isolated and self-contained as possible without virtual machines or lightweight system containers like [Docker](https://www.docker.com/). ## Installation parameters Run ``` bcbio_nextgen.py upgrade --help ``` to see all supported installation options: ``` bcbio_nextgen.py upgrade --help usage: bcbio_nextgen.py upgrade [-h] [--cores CORES] [--tooldir TOOLDIR] [--tools] [-u {stable,development,system,deps,skip}] [--toolconf TOOLCONF] [--revision REVISION] [--toolplus TOOLPLUS] [--datatarget {variation,rnaseq,smallrna,gemini,vep,dbnsfp,dbscsnv,battenberg,kraken,ericscript,gnomad}] [--genomes {GRCh37,hg19,hg38,hg38-noalt,mm10,mm9,rn6,rn5,canFam3,dm3,galGal4,phix,pseudomonas_aeruginosa_ucbpp_pa14,sacCer3,TAIR10,WBcel235,xenTro3,GRCz10,GRCz11,Sscrofa11.1,BDGP6}] [--aligners {bwa,rtg,hisat2,bbmap,bowtie,bowtie2,minimap2,novoalign,twobit,bismark,snap,star,seq}] [--data] [--cwl] [--isolate] [--distribution {ubuntu,debian,centos,scientificlinux,macosx}] optional arguments: -h, --help show this help message and exit --cores CORES Number of cores to use if local indexing is necessary. --tooldir TOOLDIR Directory to install 3rd party software tools. Leave unspecified for no tools --tools Boolean argument specifying upgrade of tools. Uses previously saved install directory -u {stable,development,system,deps,skip}, --upgrade {stable,development,system,deps,skip} Code version to upgrade --toolconf TOOLCONF YAML configuration file of tools to install --revision REVISION Specify a git commit hash or tag to install --toolplus TOOLPLUS Specify additional tool categories to install --datatarget {variation,rnaseq,smallrna,gemini,vep,dbnsfp,dbscsnv,battenberg,kraken,ericscript,gnomad} Data to install. Allows customization or install of extra data. --genomes {GRCh37,hg19,hg38,hg38-noalt,mm10,mm9,rn6,rn5,canFam3,dm3,galGal4,phix,pseudomonas_aeruginosa_ucbpp_pa14,sacCer3,TAIR10,WBcel235,xenTro3,GRCz10,GRCz11,Sscrofa11.1,BDGP6} Genomes to download --aligners {bwa,rtg,hisat2,bbmap,bowtie,bowtie2,minimap2,novoalign,twobit,bismark,snap,star,seq} Aligner indexes to download --data Upgrade data dependencies --cwl Install code and data for running CWL workflows --isolate Created an isolated installation without PATH updates --distribution {ubuntu,debian,centos,scientificlinux,macosx} Operating system distribution ``` Some useful arguments are: * `--isolate` Avoid updating the user's `~/.bashrc` if installing in a non-standard PATH. This facilitates creation of isolated modules without disrupting the user's environmental setup. Manually edit your `~/.bashrc` to allow bcbio runs with: ```shell export PATH=/path_to_bcbio/anaconda/bin:/path_to_bcbio/tools/bin:$PATH ``` * `--nodata` Do not install genome data. ## On a Virtual Machine If you are looking to quickly try out bcbio-nextgen on your personal machine before installing it on your cluster, installing bcbio-nextgen on a virtual machine is easy using [Vagrant](https://www.vagrantup.com/). ### macOS * Install [Git](https://git-scm.com/download/mac), [VirtualBox](https://download.virtualbox.org/virtualbox/6.1.6/VirtualBox-6.1.6-137129-OSX.dmg), and [Vagrant](https://releases.hashicorp.com/vagrant/2.2.7/vagrant_2.2.7_x86_64.dmg) * Download bcbio-nextgen and provision Vagrant VM: ```shell git clone git@github.com:bcbio/bcbio-nextgen.git cd bcbio-nextgen vagrant up ``` * Install bcbio-nextgen (this should take about 30 minutes): ```shell vagrant ssh python3 /vagrant/scripts/bcbio_nextgen_install.py ~/local/share/bcbio --tooldir=~/local --nodata ``` Optional steps: * Inside the VM (`vagrant ssh`): * Test your installation once it's complete: ```shell bcbio_nextgen.py --version ``` * Set the time zone in the VM for easier log viewing, for example: ```shell sudo timedatectl set-timezone America/New_York ``` * Outside the VM: * To make any additional data from the host available inside the VM (for example: reference genomes, pipeline inputs, etc) set `BCBIO_DATA_DIR` environment variable on the host to a directory that contains the data, for example: ```shell export BCBIO_DATA_DIR=~/biodata vagrant reload ``` This directory will be mounted inside Vagrant VM under `/data` ## Upgrade We use the same automated installation process for performing upgrades of tools, software and data in place. Since there are multiple targets and we want to avoid upgrading anything unexpectedly, we have specific arguments for each. Generally, you'd want to upgrade the code, tools and data together with: ```shell bcbio_nextgen.py upgrade -u stable --tools --data ``` Tune the upgrade with these options: * `-u` Type of upgrade to do for bcbio-nextgen code. `stable` gets the most recent released version and `development` retrieves the latest code from GitHub. * `--datatarget` Customized installed data or download additional files not included by default: * `--toolplus` Specify additional tools to include. See the section on `extra software` for more details. * `--genomes` and `--aligners` options add additional aligner indexes to download and prepare. `bcbio_nextgen.py upgrade -h` lists available genomes and aligners. If you want to install multiple genomes or aligners at once, specify `--genomes` or `--aligners` multiple times, like this: `--genomes GRCh37 --genomes mm10 --aligners bwa --aligners bowtie2` * Leave out the `--tools` option if you don't want to upgrade third party tools. If using `--tools`, it will use the same directory as specified during installation. If you're using an older version that has not yet gone through a successful upgrade or installation and saved the tool directory, you should manually specify `--tooldir` for the first upgrade. You can also pass `--tooldir` to install to a different directory. * Leave out the `--data` option if you don't want to get any upgrades of associated genome data. * Some aligners such as STAR don't have pre-built indices due to the large file sizes of these. You set the number of cores to use for indexing with `--cores 8`. * For example, recommended HPC job parameters for `bcbio_nextgen.py upgrade -u skip --data --datatarget rnaseq --genomes GRCh37` are: 2 CPU cores, 2GB memory, and 2 hours run time. ## Customizing data installation bcbio supports the following [genome references](https://github.com/chapmanb/cloudbiolinux/blob/master/config/biodata.yaml), 12 of them have [additional data downloads](https://github.com/chapmanb/cloudbiolinux/tree/master/ggd-recipes). If you need a reference which is absent in the list, you may install it as a [custom genome](configuration.html#adding-custom-genomes). bcbio installs associated data files for sequence processing, and you're able to customize this to install larger files or change the defaults. Use the `--datatarget` flag (potentially multiple times) to customize or add new targets. By default, bcbio will install data files for `variation`, `rnaseq` and `smallrna` but you can sub-select a single one of these if you don't require other analyses. The available targets are: * `variation` -- Data files required for variant calling: SNPs, indels and structural variants. These include files for annotation like dbSNP, associated files for variant filtering, coverage and annotation files. * `rnaseq` -- Transcripts and indices for running RNA-seq. The transcript files are also used for annotating and prioritizing structural variants. * `smallrna` -- Data files for doing small RNA analysis. * `gemini` -- The [GEMINI](https://gemini.readthedocs.io) framework associates publicly available metadata with called variants, and provides utilities for query and analysis. This target installs the required GEMINI data files, including [ExAC](http://exac.broadinstitute.org/). * `gnomad` -- [gnomAD](https://gnomad.broadinstitute.org/) is a large scale collection of genome variants, expanding on ExAC to include whole genome and more exome inputs. This is a large 25Gb download, available for human genome builds GRCh37, hg19 and hg38. * `vep` -- Data files for the [Variant Effects Predictor (VEP)](https://www.ensembl.org/info/docs/tools/vep/index.html). To use VEP as an alternative to the default installed snpEff, set `vep` in the `variant calling` configuration. * `dbnsfp` -- Like CADD, [dbNSFP](https://sites.google.com/site/jpopgen/dbNSFP) provides integrated and generalized metrics from multiple sources to help with prioritizing variations for follow up. The files are large: dbNSFP is 10Gb, expanding to 100Gb during preparation. * `dbscsnv` -- [dbscSNV](https://sites.google.com/site/jpopgen/dbNSFP) includes all potential human SNVs within splicing consensus regions (−3 to +8 at the 5' splice site and −12 to +2 at the 3' splice site), i.e. scSNVs, related functional annotations and two ensemble prediction scores for predicting their potential of altering splicing. * `battenberg` -- Data files for [Battenberg](https://github.com/cancerit/cgpBattenberg), which detects subclonality and copy number changes in whole genome cancer samples. * `kraken` -- Database for [Kraken](https://ccb.jhu.edu/software/kraken/), optionally used for contamination detection. * `ericscript` -- Database for [EricScript](https://sites.google.com/site/bioericscript/), based gene fusion detection. Supports hg38, hg19 and GRCh37. * `TOPMed` -- [TOPMed](https://www.nhlbiwgs.org) Allele frequencies for whole genome variants from heart, lung, blood and sleep disorders. Supports hg38, hg19 and GRCh37. For somatic analyses, bcbio includes [COSMIC](https://cancer.sanger.ac.uk/cosmic) v68 for hg19 and GRCh37 only. Due to license restrictions, we cannot include updated versions of this dataset and hg38 support with the installer. To prepare these datasets yourself you can use [a utility script shipped with cloudbiolinux](https://github.com/chapmanb/cloudbiolinux/blob/master/utils/prepare_cosmic.py) that downloads, sorts and merges the VCFs, then copies into your bcbio installation: ```shell export COSMIC_USER="you@example.org" export COSMIC_PASS="your_cosmic_password" bcbio_python prepare_cosmic.py 89 /path/to/bcbio ``` `/path/to/bcbio/` here is the directory one up from the `genomes` directory. The script removes variants marked as `SNP` in COSMIC, i.e. leaving only somatic variants. From version a minor portion of variants gets re-classified, for example: 3,779 variants were SNPs in cosmic-90 and became mutations in cosmic-92, 656 variants were mutations in cosmic-90 and became SNPs in cosmic-92. ## Extra software We're not able to automatically install some useful tools due to licensing restrictions, so we provide a mechanism to manually download and add these to bcbio-nextgen during an upgrade with the `--toolplus` command line option. ### GATK and MuTect/MuTect2 bcbio includes an installation of GATK4, which is freely available for all uses. This is the default runner for HaplotypeCaller or MuTect2. If you want to use an older version of GATK, it requires manual installation. This is freely available for academic users, but requires a [license for commercial use](https://gatk.broadinstitute.org/hc/en-us#licensing). It is not freely redistributable, so requires a manual download from the [GATK download](https://console.cloud.google.com/storage/browser/gatk-software/package-archive) site, direct [link](https://storage.googleapis.com/gatk-software/package-archive/gatk/GenomeAnalysisTK-3.8-1-0-gf15c1c3ef.tar.bz2). You also need to include `tools_off: [gatk4]` in your configuration for runs: see `changing bcbio defaults`. To install GATK3, register with the pre-installed gatk bioconda wrapper: ```shell gatk3-register /path/to/GenomeAnalysisTK.tar.bz2 ``` If you're not using the most recent post-3.6 version of GATK, or using a nightly build, you can add `--noversioncheck` to the command line to skip comparisons to the GATK version. [MuTect2](https://gatk.broadinstitute.org/hc/en-us/articles/360037593851-Mutect2) is distributed with GATK in versions 3.5 and later. To install versions of GATK < 3.6, download and unzip the latest version from the GATK distribution. Then make this jar available to bcbio-nextgen with: ```shell bcbio_nextgen.py upgrade --tools --toolplus gatk=/path/to/gatk/GenomeAnalysisTK.jar ``` This will copy the jar and update your `bcbio_system.yaml` and manifest files to reflect the new version. MuTect also has similar licensing terms and requires a license for commercial use. After [downloading the MuTect jar](https://www.broadinstitute.org/gatk/download/), make it available to bcbio: ```shell bcbio_nextgen.py upgrade --tools --toolplus mutect=/path/to/mutect/mutect-1.1.7.jar ``` Note that muTect does not provide an easy way to query for the current version, so your input jar needs to include the version in the name. ## System requirements bcbio-nextgen provides a wrapper around external tools and data, so the actual tools used drive the system requirements. For small projects, it should install on workstations or laptops with a couple GB of memory, and then scale as needed on clusters or multicore machines. Disk space requirement for the tools, including all system packages is about 22GB (or more, depending on the type of the file system). Biological data requirements will depend on the genomes and aligner indices used, but a suggested install with GRCh37 and bowtie/bwa2 indexes uses approximately 35GB of storage during preparation and ~25GB after: ```shell $ du -shc genomes/Hsapiens/GRCh37/* 3.8G bowtie2 5.1G bwa 3.0G rnaseq-2014-05-02 3.0G seq 340M snpeff 4.2G variation 4.4G vep 23.5G total ``` ## Troubleshooting ### Proxy or firewall problems Some steps retrieve third party tools from GitHub, which can run into issues if you're behind a proxy or block git ports. To instruct git to use `https://` globally instead of `git://`: ```shell git config --global url.https://github.com/.insteadOf git://github.com/ ``` ### GATK or Java Errors Most software tools used by bcbio require Java 1.8. bcbio distributes an OpenJDK Java build and uses it so you don't need to install anything. Older versions of GATK (< 3.6) and MuTect require a locally installed Java 1.7. If you have version incompatibilities, you'll see errors like: ``` Unsupported major.minor version 51.0 ``` Fixing this requires either installing Java 1.7 for old GATK and MuTect or avoiding pointing to an incorrect java (`unset JAVA_HOME`). You can also tweak the java used by bcbio, described in the [Automated](#automated) installation section. ### ImportErrors Import errors with tracebacks containing Python libraries outside of the bcbio distribution (`/path/to/bcbio/anaconda`) are often due to other conflicting Python installations. bcbio tries to isolate itself as much as possible but external libraries can get included during installation due to the `PYTHONHOME` or `PYTHONPATH` environmental variables or local site libraries. These commands will temporary unset those to get bcbio installed, after which it should ignore them automatically: ```shell unset PYTHONHOME unset PYTHONPATH export PYTHONNOUSERSITE=1 ``` Finally, having a `.pydistutils.cfg` file in your home directory can mess with where the libraries get installed. If you have this file in your home directory, temporarily renaming it to something else may fix your installation issue. ## Manual process The manual process does not allow the in-place updates and management of third party tools that the automated installer makes possible. It's a more error-prone and labor intensive process. If you find you can't use the installer we'd love to hear why to make it more amenable to your system. If you'd like to develop against a bcbio installation, see the documentation on setting up a `development environment`. ### Tool requirements The code drives a number of next-generation sequencing analysis tools that you need to install on any machines involved in the processing. The [CloudBioLinux](http://cloudbiolinux.org) toolkit provides automated scripts to help with installation for both software and associated data files: ```shell fab -f cloudbiolinux/fabfile.py -H localhost install_biolinux:flavor=ngs_pipeline_minimal ``` You can also install them manually, adjusting locations in the `resources` section of your `bcbio_system.yaml` configuration file as needed. The CloudBioLinux infrastructure provides a full list of third party software installed with bcbio-nextgen in [packages-conda.yaml](https://github.com/chapmanb/cloudbiolinux/blob/master/contrib/flavor/ngs_pipeline_minimal/packages-conda.yaml), which lists all third party tools installed through [Bioconda](https://bioconda.github.io/). ### Data requirements In addition to existing bioinformatics software the pipeline requires associated data files for reference genomes, including pre-built indexes for aligners. The [CloudBioLinux](http://cloudbiolinux.org) toolkit again provides an automated way to download and prepare these reference genomes: ```shell fab -f data_fabfile.py -H localhost -c your_fabricrc.txt install_data_s3:your_biodata.yaml ``` The [biodata.yaml](https://github.com/chapmanb/cloudbiolinux/blob/master/config/biodata.yaml) file contains information about what genomes to download. The [fabricrc.txt](https://github.com/chapmanb/cloudbiolinux/blob/master/config/fabricrc.txt) describes where to install the genomes by adjusting the `data_files` variable. This creates a tree structure that includes a set of Galaxy-style location files to describe locations of indexes: ``` ├── galaxy │   ├── tool-data │   │   ├── alignseq.loc │   │   ├── bowtie_indices.loc │   │   ├── bwa_index.loc │   │   ├── sam_fa_indices.loc │   │   └── twobit.loc │   └── tool_data_table_conf.xml ├── genomes │   ├── Hsapiens │   │   ├── GRCh37 │   │   └── hg19 │   └── phiX174 │   └── phix └── liftOver ``` Individual genome directories contain indexes for aligners in individual sub-directories prefixed by the aligner name. This structured scheme helps manage aligners that don't have native Galaxy `.loc` files. The automated installer will download and set this up automatically: ``` `-- phix |-- bowtie | |-- phix.1.ebwt | |-- phix.2.ebwt | |-- phix.3.ebwt | |-- phix.4.ebwt | |-- phix.rev.1.ebwt | `-- phix.rev.2.ebwt |-- bowtie2 | |-- phix.1.bt2 | |-- phix.2.bt2 | |-- phix.3.bt2 | |-- phix.4.bt2 | |-- phix.rev.1.bt2 | `-- phix.rev.2.bt2 |-- bwa | |-- phix.fa.amb | |-- phix.fa.ann | |-- phix.fa.bwt | |-- phix.fa.pac | |-- phix.fa.rbwt | |-- phix.fa.rpac | |-- phix.fa.rsa | `-- phix.fa.sa |-- novoalign | `-- phix |-- seq | |-- phix.dict | |-- phix.fa | `-- phix.fa.fai `-- ucsc `-- phix.2bit ``` ## Maintain many bcbio installations It is often asked how to reproduce older bcbio analyses when every update changes a lot in tools and in bcbio code. One of the solutions is the use of modules in HPC environemnt: https://www.admin-magazine.com/HPC/Articles/Environment-Modules. You can have a bcbio/version module for every bcbio snapshot you need. They would consume <50G each, and a single large `genomes` folder could be symlinked to all of them. Data in genomes changes in a much slower pace compared to bcbio code and tools. bcbio-nextgen-1.2.9/docs/contents/internals.md000066400000000000000000000245641415626112400213720ustar00rootroot00000000000000# Internals ## Overview ![variant calling overview](images/variant-calling-overview.png) ## Parallel bcbio calculates callable regions following alignment using [goleft depth](https://github.com/brentp/goleft/tree/master/depth). These regions determine breakpoints for analysis, allowing [parallelization by genomic regions](http://bcb.io/2013/05/22/scaling-variant-detection-pipelines-for-whole-genome-sequencing-analysis/) during variant calling. Defining non-callable regions allows bcbio to select breakpoints for parallelization within chromosomes where we won't accidentally impact small variant detection. The callable regions also supplement the variant calls to define positions where not called bases are homozygous reference, as opposed to true no-calls with no evidence. The callable regions plus variant calls is an alternative to gVCF output which explicitly enumerates reference calls in the output variant file. ![Overview of cluster types during parallel execution](images/parallel-clustertypes.png) ## Somatic tumor only variant calling pipeline with UMIs step by step Minor steps (like tabix'ing of vcfs, indexing of bams) and details (full paths) are omitted. bcbio.yaml config: ```yaml details: - algorithm: aligner: bwa trim_ends: [2,0,2,0] min_allele_fraction: 0.01 correct_umis: /path/umi.whitelist.txt tools_off: - gemini umi_type: fastq_name variantcaller: - vardict coverage: target.bed variant_regions: target.bed analysis: variant2 description: samplex files: - /path/samplex_1.fq.gz - /path/samplex_2.fq.gz genome_build: hg38 metadata: phenotype: tumor resources: fgbio: options: [--min-reads, 3] ``` 1. trimming 2p from reads: trim_ends: [2,0,2,0], indexing: ```shell bgzip --threads 8 -c <(seqtk trimfq -b 2 -e 0 samplex_1.fq.gz) > samplex_1.fq.gz bgzip --threads 8 -c <(seqtk trimfq -b 2 -e 0 samplex_2.fq.gz) > samplex_2.fq.gz grabix index samplex_2.fq.gz grabix index samplex_1.fq.gz ``` 1. alignment with bwa mem, sort and mark duplicates, assign BAM tags (XS=sample, XC=cell, RX=UMI), input: fastq files, output: samplex-sort.bam: ```shell unset JAVA_HOME && \ bwa mem -c 250 -M -t 16 -R '@RG\tID:samplex\tPL:illumina\tPU:samplex\tSM:samplex' \ -v 1 /path/reference/genomes/Hsapiens/hg38/bwa/hg38.fa samplex_1.fq.gz samplex_2.fq.gz | \ bamsormadup tmpfile=samplex-sort-sorttmp-markdup inputformat=sam threads=16 \ outputformat=bam level=0 SO=coordinate | \ /path/bcbio/anaconda/envs/python2/bin/python /path/bin/umis bamtag - | \ samtools view -b > samplex-sort.bam ``` 1. correct UMIs with fgbio using the whitelist, input: samplex-sort.bam, output: samplex-sort-umis_corrected.bam: ```shell unset JAVA_HOME && \ fgbio -Xms750m -Xmx30g -XX:+UseSerialGC --tmp-dir . --async-io=true --compression=0 \ CorrectUmis \ -t XC -m 3 -d 1 -x -U /path/umi.whitelist.txt -i samplex-sort.bam \ -o samplex-sort-umis_corrected.bam ``` 1. calculate coverage with mosdepth: ```shell mosdepth -t 16 -F 1804 --no-per-base --by target.bed samplex-rawumi \ samplex-sort-umis_corrected.bam ``` 1. fgbio GroupReadsByUmi, CallDuplexConsensusReads, FilterConsensusReads with min-reads=3, bam2fastq: ```shell unset JAVA_HOME && \ fgbio -Xms750m -Xmx30g -XX:+UseSerialGC --tmp-dir . --async-io=true --compression=0 \ GroupReadsByUmi \ --edits=1 --min-map-q=1 -t XC -s paired -i samplex-sort-umis_corrected.bam | \ fgbio -Xms750m -Xmx30g -XX:+UseSerialGC --tmp-dir . --async-io=true --compression=0 \ CallDuplexConsensusReads \ --min-input-base-quality=2 --sort-order=:none: -i /dev/stdin -o /dev/stdout | \ fgbio -Xms750m -Xmx30g -XX:+UseSerialGC --tmp-dir . --async-io=true --compression=0 \ FilterConsensusReads --min-reads=3 --min-base-quality=13 --max-base-error-rate=0.1 \ -r /path/reference/genomes/Hsapiens/hg38/seq/hg38.fa -i /dev/stdin -o /dev/stdout | \ bamtofastq collate=1 T=samplex-sort-umis_corrected-cumi-1-bamtofastq-tmp \ F=samplex-sort-umis_corrected-cumi-1.fq.gz F2=samplex-sort-umis_corrected-cumi-2.fq.gz tags=cD,cM,cE gz=1 ``` 1. align consensus reads: ```shell unset JAVA_HOME && bwa mem -C -c 250 -M -t 16 -R '@RG\tID:samplex\tPL:illumina\tPU:samplex\tSM:samplex' \ -v 1 /projects/ngs/reference/genomes/Hsapiens/hg38/bwa/hg38.fa \ samplex-sort-umis_corrected-cumi-1.fq.gz samplex-sort-umis_corrected-cumi-2.fq.gz | \ samtools sort -@ 16 -m 1G -T samplex-sort-cumi-sorttmp -o samplex-sort-cumi.bam /dev/stdin samtools index -@ 16 samplex-sort-cumi.bam samplex-sort-cumi.bam.bai ``` 1. clean variant_regions bed file: ```shell cat target.bed | grep -v ^track | grep -v ^browser | grep -v ^@ | grep -v ^# | \ bcbio_python -c 'from bcbio.variation import bedutils; bedutils.remove_bad()' | \ sort -V -T . -k1,1 -k2,2n > cleaned-target.bed cat cleaned-target.bed | bgzip --threads 16 -c > cleaned-target.bed.gz tabix -f -p bed cleaned-target.bed.gz bedtools merge -i cleaned-target.bed> cleaned-target-merged.bed cat cleaned-target-merged.bed | bgzip --threads 16 -c > cleaned-target-merged.bed.gz ``` 1. clean coverage bed file (the same in our example): ```shell cat target.bed | grep -v ^track | grep -v ^browser | grep -v ^@ | grep -v ^# | \ iconv -c -f utf-8 -t ascii | sed 's/ //g' | \ bcbio_python -c 'from bcbio.variation import bedutils; bedutils.remove_bad()' | \ sort -V -T . -k1,1 -k2,2n > cov-target.bed cat cov-target.bed | bgzip --threads 16 -c > cov-target.bed.gz tabix -f -p bed cov-target.bed.gz bedtools merge -i cov-target.bed > cov-target-merged.bed cat cov-target-merged.bed | bgzip --threads 16 -c > cov-target-merged.bed.gz ``` 1. clean sv regions bed file: ```shell cat cleaned-target.bed | grep -v ^track | grep -v ^browser | grep -v ^@ | grep -v ^# | \ /home/kmhr378/local/bin/bcbio_python -c 'from bcbio.variation import bedutils; bedutils.remove_bad()' | \ sort -V -T . -k1,1 -k2,2n > \ svregions-cleaned-target.bed cat svregions-cleaned-target.bed | bgzip --threads 16 -c > svregions-cleaned-target.bed.gz ``` 1. calculate coverage for 3 bed files with MOSDEPTH: ```shell export MOSDEPTH_Q0=NO_COVERAGE && export MOSDEPTH_Q1=LOW_COVERAGE && \ export MOSDEPTH_Q2=CALLABLE && \ mosdepth -t 16 -F 1804 -Q 1 --no-per-base --by cleaned-target.bed \ --quantize 0:1:4: samplex-variant_regions samplex-sort-cumi.bam mosdepth -t 16 -F 1804 --no-per-base --by svregions-cleaned-target.bed \ samplex-sv_regions samplex-sort-cumi.bam mosdepth -t 16 -F 1804 --no-per-base --by cov-target.bed samplex-coverage \ samplex-sort-cumi.bam \ -T 1,5,10,20,50,100,200,500,1000,2000,5000,10000,20000,50000,100000,200000,500000 ``` 1. hts_nim counts: ```shell hts_nim_tools count-reads -t 16 -F 1804 /path/samplex/counts/fullgenome.bed samplex-sort-cumi.bam > fullgenome-1804-counts.txt hts_nim_tools count-reads -t 16 -F 1804 cleaned-target.bed samplex-sort-cumi.bam > cleaned-target-merged-1804-counts.txt ``` 1. samtools read statistics:: ```shell samtools stats -@ 16 samplex-sort-cumi.bam > samplex.txt samtools idxstats samplex-sort-cumi.bam > samplex-idxstats.txt ``` 1. variant calling with vardict (repeated for each alignment chunk): ```shell unset R_HOME && unset R_LIBS && unset JAVA_HOME && \ export VAR_DICT_OPTS='-Xms750m -Xmx3500m -XX:+UseSerialGC -Djava.io.tmpdir=.' && \ vardict-java -G /path/reference/genomes/Hsapiens/hg38/seq/hg38.fa \ -N samplex -b samplex-sort-cumi.bam -c 1 -S 2 -E 3 -g 4 --nosv --deldupvar -Q 10 -F 0x700 \ samplex-chr5_0_x-unmerged-regions-regionlimit.bed -f 0.0025 | \ teststrandbias.R | \ var2vcf_valid.pl -A -N samplex -E -f 0.0025 | grep -v ^##contig | \ bcftools annotate -h samplex-chr5_0_x-contig_header.txt | \ bcftools filter -i 'QUAL >= 0' | \ bcftools filter --soft-filter 'LowFreqBias' --mode '+' -e 'FORMAT/AF[0:0] < 0.02 && \ FORMAT/VD[0] < 30 && INFO/SBF < 0.1 && INFO/NM >= 2.0' | \ awk -F$'\t' -v OFS='\t' '{if ($0 !~ /^#/) gsub(/[KMRYSWBVHDXkmryswbvhdx]/, "N", $4) } {print}' | \ awk -F$'\t' -v OFS='\t' '{if ($0 !~ /^#/) gsub(/[KMRYSWBVHDXkmryswbvhdx]/, "N", $5) } {print}' | \ awk -F$'\t' -v OFS='\t' '$1!~/^#/ && $4 == $5 {next} {print}' | \ vcfstreamsort | bgzip -c > samplex-chr5_0_x.vcf.gz zgrep ^# samplex-chr5_0_x.vcf.gz > samplex-chr5_0_x-fixheader-header.vcf unset JAVA_HOME && \ picard FixVcfHeader HEADER=samplex-chr5_0_x-fixheader-header.vcf \ INPUT=samplex-chr5_0_x.vcf.gz \ OUTPUT=samplex-chr5_0_x-fixheader.vcf.gz ``` 1. gather vcfs: ```shell unset JAVA_HOME && \ gatk --java-options -Xms681m -Xmx3181m -XX:+UseSerialGC -Djava.io.tmpdir=. \ GatherVcfs -I samplex-files.list -O samplex.vcf.gz ``` 1. annotate with snpEff: ```shell unset JAVA_HOME && \ snpEff -Xms750m -Xmx29g -Djava.io.tmpdir=. eff \ -dataDir /path/reference/genomes/Hsapiens/hg38/snpeff \ -hgvs -cancer -noLog -i vcf -o vcf -csvStats samplex-effects-stats.csv \ -s samplex-effects-stats.html GRCh38.86 samplex.vcf.gz | \ bgzip --threads 16 -c > samplex-effects.vcf.gz ``` 1. annotate with vcfanno: ```shell vcfanno -p 16 dbsnp.conf samplex-effects.vcf.gz | \ bcftools reheader -h samplex-effects-annotated-sample_header.txt | \ bcftools view | bgzip -c > samplex-effects-annotated.vcf.gz tabix -f -p vcf samplex-effects-annotated.vcf.gz vcfanno -p 16 samplex-effects-annotated-annotated-somatic-combine.conf \ samplex-effects-annotated.vcf.gz | bgzip -c > samplex-effects-annotated-annotated-somatic.vcf.gz tabix -f -p vcf samplex-effects-annotated-annotated-somatic.vcf.gz cat samplex-effects-annotated-annotated-somatic-priority.tsv | bgzip --threads 16 -c > \ samplex-effects-annotated-annotated-somatic-priority.tsv.gz tabix -f -0 -c '#' -s 1 -b 2 -e 3 samplex-effects-annotated-annotated-somatic-priority.tsv.gz ``` ## Tests To run bcbio automated tests, install bcbio and clone bcbio master repository. You are testing your installation with tests provided in bcbio-nextgen/tests: ```shell which bcbio_nextgen.py cd bcbio-nextgen/tests ./run_tests.sh > tests.out ``` Tests are in `integration/*.py`. Each test has a set or marks. Marks are listed in pytest.ini. The mark defines how many tests to select. By default (just running plain ./run_tests.sh), it is speed1 = 11 tests. bcbio-nextgen-1.2.9/docs/contents/intro.md000066400000000000000000000117241415626112400205200ustar00rootroot00000000000000# Getting started ## Workflow This example calls variants using NA12878 exome data from [EdgeBio's](https://www.edgebio.com/) clinical sequencing pipeline, and compares them against reference materials from NIST's [Genome in a Bottle](https://www.nist.gov/programs-projects/genome-bottle) initiative. ### 1. Install bcbio python package and tools ```shell wget https://raw.github.com/bcbio/bcbio-nextgen/master/scripts/bcbio_nextgen_install.py python3 bcbio_nextgen_install.py [bcbio_path] --tooldir=[tools_path]/tools --nodata --mamba ``` ### 2. Install hg38 reference genome and bwa indices ```shell bcbio_nextgen.py upgrade -u skip --genomes hg38 --aligners bwa ``` See more detailed instructions in the installation user story. ### 3. Get the input configuration file, fastq reads, reference materials and analysis regions: ```shell mkdir -p NA12878-exome-eval cd NA12878-exome-eval wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-exome-methodcmp-getdata.sh bash NA12878-exome-methodcmp-getdata.sh ``` ### 4. Run the analysis, distributed on 8 local cores, with: Make sure that PATH variable contains paths to bcbio scripts and tools: ```shell $ which bcbio_nextgen.py /bcbio_installation/anaconda/bin/bcbio_nextgen.py $ which mosdepth /bcbio_installation/tools/bin/mosdepth $ echo $PATH /bcbio_installation/anaconda/bin:/bcbio_installation/tools/bin:[other-system-bin-dirs] ``` Run the project: ```shell cd work bcbio_nextgen.py ../config/NA12878-exome-methodcmp.yaml -n 8 ``` Parameters of the analysis are specified in the yaml configuration [file](https://github.com/bcbio/bcbio-nextgen/blob/master/config/examples/NA12878-exome-methodcmp.yaml): ```yaml upload: dir: ../final details: - files: [../input/NA12878-NGv3-LAB1360-A_1.fastq.gz, ../input/NA12878-NGv3-LAB1360-A_2.fastq.gz] description: NA12878 metadata: sex: female analysis: variant2 genome_build: hg38 algorithm: aligner: bwa variantcaller: gatk-haplotype validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed variant_regions: capture_regions/Exome-NGv3 ``` Running time is ~2h. ### 5. Explore results in `NA12878-exome-eval/final`: * `date_project/multiqc` - quality contol * `date_project/NA12878-gatk-haplotype-annotated.vcf.gz` - annotated variants * `NA12878/NA12878-callable.bed` - callable regions * `final/NA12878/NA12878-ready.bam` - bam file * `date_project/bcbio-nextgen-commands.log` - commands ran to produce results * `date_project/grading-summary-NA12878.csv` - validation results. False Discovery Rate (FDR) for SNPs here is 3% (i.e. 97% precision for SNPs), so the precision is quite low. One reason of low precision could be that NA12878-NGv3-LAB1360 WES dataset was sequenced in 2013 or earlier, so it could be of somewhat lower quality. We left it here for educational purpose. With a modern NA12878 dataset you can achieve >99% precision and >99% sensitivity using bcbio/gatk, see [germline variants user story](germline_variants.html#workflow1-validate-hg38-calls). Comparing QC and validations in the two NA12878 WES datasets illustrates how sequencing quality affects variant calling precision and sensitivity. Another point one could make when comparing the two validations is that NA12878-NGv3-LAB1360 has a larger target (133,288 SNPs vs 37,033), so the choice of `variant_regions` directly influences validation results. Including only regions with high coverage, excluding low complexity regions leads to increased precision. A larger bed file with more regions included is a more stressful test for combination of capture kit/sequencing instrument/aligner/variant caller/filters. ## What is next? Bcbio documentation is organized by user stories. We support 22 user stories (extended use cases): * 14 data processing user stories corresponding to different types of NGS data and biological questions * 8 infrastructural stories. ### Data processing stories 1. Somatic variants 2. Bulk RNA-seq expression 3. Single cell RNA-seq 4. HLA typing 5. Germline small variants 6. 3'prime digital gene expression 7. Structural variants 8. ChIP/ATAC-seq 9. Methylation 10. Bulk RNA-seq variants 11. Bulk RNA-seq fusion 12. Fast RNA-seq 13. Disambiguation 14. Small RNA-seq ### Infrastructural stories 1. Getting started 2. Installation 3. Configuration 4. Parallel execution 5. Outputs 6. Development 7. Cloud 8. CWL ### A typical user story contains: - `workflow` - step-by step description of how to run the pipeline with example data - `parameters` - describes yaml config file parameters relevant for the user story - `output` - describes output files - `steps` - outlines low level step the pipeline performs to process data - `validation` - validation results when available - `description` - `references` Try running bcbio with your own data, report [issues](https://github.com/bcbio/bcbio-nextgen/issues), contribute to the codebase and documentation on [github](https://github.com/bcbio/bcbio-nextgen/). bcbio-nextgen-1.2.9/docs/contents/methylation.md000066400000000000000000000341351415626112400217230ustar00rootroot00000000000000# Methylation Whole genome bisulfite sequencing is supported using the [bismark2](https://www.bioinformatics.babraham.ac.uk/projects/bismark/) pipeline. It can be turned on by setting `analysis` to `wgbs-seq`. ## Example run ### 1. (skip if installed) Install bismark and bowtie2 references ```bash bcbio_nextgen.py upgrade \ -u skip \ --genomes hg38 \ --aligners bowtie2 \ --aligners bismark ``` ### 2. Create bcbio project structure and download input fastq files This example run is based on data from [Encode](https://www.encodeproject.org/experiments/ENCSR890UQO/) ```bash mkdir wgbs_example cd wgbs_example mkdir config input final work cd input wget -c ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR423/008/SRR4235788/SRR4235788_1.fastq.gz wget -c ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR423/008/SRR4235788/SRR4235788_2.fastq.gz ``` ### 3. Create wgbs_example/config/bcbio.yaml ```yaml details: - algorithm: aligner: bismark analysis: wgbs-seq description: NA12878BS genome_build: hg38 files: - /path/to/wgbs_example/input/SRR4235788_1.fastq.gz - /path/to/wgbs_example/input/SRR4235788_2.fastq.gz resources: trim_galore: options: ["--clip_r1 4", "--clip_r2 4", "--three_prime_clip_r1 4", "--three_prime_clip_r2 4"] bismark: bismark_threads: 4 bowtie_threads: 2 upload: dir: ../final ``` ### 4. Create and launch bcbio start script wgbs_example/work/bcbio.sh (O2 slurm example) ```bash #!/bin/bash # https://slurm.schedmd.com/sbatch.html # https://wiki.rc.hms.harvard.edu/display/O2 #SBATCH --partition=priority # Partition (queue) priority #SBATCH --time=5-00:00 # Runtime in D-HH:MM format, 10:00:00 for hours #SBATCH --job-name=wgbs # Job name #SBATCH -c 32 # cores #SBATCH --mem=100G # Memory #SBATCH --output=project_%j.out # File to which STDOUT will be written, including job ID #SBATCH --error=project_%j.err # File to which STDERR will be written, including job ID #SBATCH --mail-type=NONE # Type of email notification (BEGIN, END, FAIL, ALL) date bcbio_nextgen.py ../config/bcbio.yaml -n 32 date ``` ## Parameters ### Supported Kits ```eval_rst +--------+------------+---------+---------+---------+---------+ |Name |directional?|TrimR1_5'|TrimR1_3'|TrimR2_5'|TrimR2_3'| +========+============+=========+=========+=========+=========+ |accelngs|yes | 10 nt | 10 nt | 19 nt | 5 | +--------+------------+---------+---------+---------+---------+ |nebemseq|yes | 5 nt | 5 | 11 | 5 | +--------+------------+---------+---------+---------+---------+ |truseq |no | 8 nt | 8 | 8 | 8 | +--------+------------+---------+---------+---------+---------+ ``` In the `algorithm` section of the yaml: - `aligner`: `bismark` - `kit`: `accelngs`, `nebemseq`, `truseq`; setting a kit automatically applies the proper trimming options. In the `resources` section of the yaml: - trim_galore trimming options: ```yaml resources: trim_galore: options: ["--clip_r1 8", "--clip_r2 8", "--three_prime_clip_r1 8", "--three_prime_clip_r2 8"] ``` - bismark `--non-directional` option (default is directional mode and you don't have to specify it) and threading options (use with caution, see benchmarking notes below; by default bcbio is trying to calculate the optimal number of bismark threads with this [function](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/ngsalign/bismark.py#L123); if you alter bismark_threads = X, request 5-7X cores for bcbio; some samples could be processed much faster, but some could fail, reduce threads then). By defaut, we are using `--local --maxins 1000` alignment options (after benchmarking using nebemseq kit). ```yaml resources: bismark: options: ["--non_directional"] bismark_threads: 4 bowtie_threads: 2 ``` - deduplicate_bismark options: ```yaml resources: deduplicate_bismark: options: ["--barcode"] ``` The following configs for the `truseq` kit are equivalent: ```yaml details: - analysis: wgbs-seq genome_build: hg38 algorithm: aligner: bismark kit: truseq ``` ```yaml details: - analysis: wgbs-seq genome_build: hg38 algorithm: aligner: bismark resources: trim_galore: options: ["--clip_r1 8", "--clip_r2 8", "--three_prime_clip_r1 8", "--three_prime_clip_r2 8"] bismark: options: ["--non_directional"] ``` ## Output ### Project directory - multiqc - QC report, including information from Bismark for all samples (alignment rates, deduplication, M-Bias) ### Sample directory - sample-bam_report.txt - bismark alignment report - sample-deduplication_report.txt - sample-ready.bam - **sorted** bam (even though we are using the unsorted bam throughout the pipeline). - bismark - Bismark output - bismark/sample.html - Bismark processing report ## Steps * = a step is repeated for every sample bcbio.yaml ```yaml details: - algorithm: aligner: bismark analysis: wgbs-seq description: rep1 files: - /path/to/ENCSR481JIW_rep1_R1.fastq.gz - /path/to/ENCSR481JIW_rep1_R2.fastq.gz genome_build: hg38 - algorithm: aligner: bismark analysis: wgbs-seq description: rep2 files: - /path/to/ENCSR481JIW_rep2_R1.fastq.gz - /path/to/ENCSR481JIW_rep2_R2.fastq.gz genome_build: hg38 upload: dir: ../final ``` 1. [wgbsseqpipeline function](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/main.py#L413) 2. \* [Read trimmming](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/wgbsseq/trimming.py#L15) ```bash trim_galore \ --cores 4 \ --length 30 \ --quality 30 \ --fastqc \ --paired \ -o /path/to/work/bcbiotx \ /path/to/ENCSR481JIW_rep1_R1.fastq.gz \ /path/to/ENCSR481JIW_rep1_R2.fastq.gz ``` 3. \* [Bismark align](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/ngsalign/bismark.py#L19) ```bash bismark \ --bowtie2 \ --temp_dir /path/to/work/bcbiotx/ \ --gzip \ --parallel 5 \ -o /path/to/work/bcbiotx \ --unmapped \ /path/to/genomes/Hsapiens/hg38/bismark/ \ -1 /path/to/work/trimmed/rep1/ENCSR481JIW_rep1_R1_val_1.fq.gz \ -2 /path/to/work/trimmed/rep1/ENCSR481JIW_rep1_R2_val_2.fq.gz ``` 4. \* [deduplicate bismark](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/wgbsseq/deduplication.py#L10) ```bash deduplicate_bismark \ --output_dir /path/to/work/dedup/rep1 \ /path/to/work/align/rep1/rep1.bam ``` 5. \* [bismark_calling](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/wgbsseq/cpg_caller.py#L58) [bismark_methylation_extractor](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/wgbsseq/cpg_caller.py#L26) ```bash bismark_methylation_extractor \ --no_overlap \ --comprehensive \ --cytosine_report \ --genome_folder /path/to/genomes/Hsapiens/hg38/bismark/ \ --merge_non_CpG \ --multicore 1 \ --buffer_size 5G \ --bedGraph \ --gzip /path/to/work/dedup/rep1/rep1.deduplicated.bam ``` 6. \* [bismark2report](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/wgbsseq/cpg_caller.py#L44) ```bash bismark2report \ --alignment_report /path/to/work/align/rep1/rep1_bismark/ENCSR481JIW_rep1_R1_val_1_bismark_bt2_PE_report.txt \ -o /path/to/work/cpg/rep1/bcbiotx/tmpypivttaa/rep1.html \ --mbias_report /path/to/work/cpg/rep1/rep1.deduplicated.M-bias.txt ``` 7. \* [generate QC metrics](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/qcsummary.py#L39); [samtools sort](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/pipeline/qcsummary.py#L67) ```bash samtools sort -@ 16 -m 3276M -O BAM \ -T /path/to/work/bcbiotx/tmpj82rrnlc/rep1.sorted-sort \ -o /path/to/work/bcbiotx/tmpj82rrnlc/rep1.sorted.bam \ /path/to/work/align/rep1/rep1.bam ``` 8. \* samtools index ```bash samtools \ index -@ 16 \ /path/to/work/align/rep1/rep1.sorted.bam \ /path/to/work/bcbiotx/tmpr02on2ol/rep1.sorted.bam.bai ``` 9. \* samtools stats ```bash samtools stats -@ 16 \ /path/to/work/align/rep1/rep1.sorted.bam > \ /path/to/work/bcbiotx/tmp5e6gerdb/rep1.txt ``` 10. \* downsample for fastqc ```bash samtools view -O BAM -@ 16 \ -o /path/to/work/bcbiotx/tmp3z8btzek/rep1.sorted-downsample.bam \ -s 42.735 \ /path/to/work/align/rep1/rep1.sorted.bam ``` 11. \* fastqc ```bash fastqc \ -d /path/to/work/qc/rep1/bcbiotx \ -t 16 \ --extract \ -o /path/to/work/qc/rep1/bcbiotx \ -f bam /path/to/work/qc/rep1/rep1.sorted-downsample.bam ``` 12. \* samtools idxstats ```bash samtools idxstats /path/to/work/align/rep1/rep1.sorted.bam > /path/to/work/bcbiotx/rep1-idxstats.txt ``` 13. \* [multiqc summary](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/qc/multiqc.py#L39) ```bash multiqc -c /path/to/work/qc/multiqc/multiqc_config.yaml \ -f -l \ /path/to/work/qc/multiqc/list_files.txt \ -o /path/to/work/bcbiotx/ ``` 14. [upload sample files to final](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/upload/__init__.py#L29); [also see here](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/upload/__init__.py#L128) 15. [upload project file to final](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/upload/__init__.py#L21); [also see here](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/upload/__init__.py#L777) ## Benchmarking There is an extensive discussion on Bismark and trim_galore performance, [Bismark github](https://github.com/FelixKrueger/Bismark/issues/96). We ran a test with NA12878 nebemseq data, 125 mln reads (72.5mln read pairs). We tested performance of bismark/bcbio using `--parallel` (bismark workers) and `-p` (bowtie threads) bismark settings. We measured the performance only of the alignment step using bcbio-nextgen-commands log timecodes. 16/2/100G RAM was an optimal parameters set, with other having 5X-10X longer runtimes. When running a cohort of samples ~50% passed with 16/2/100G, some processed broken bam files, re-running with 8/2/100G or 4/2/100G solved the issue, see more info [here](https://github.com/FelixKrueger/Bismark/issues/360). For Lambda Phage genome we re-used trimming step results and 4/2/30G settings. bcbio.yaml: ``` details: - algorithm: aligner: bismark kit: nebemseq analysis: wgbs-seq description: NA12878_1 files: - /path/to/NA12878_1.fq.gz - /path/to/NA12878_2.fq.gz genome_build: hg38 metadata: batch: NA12878_1-batch phenotype: tumor fc_name: bcbio resources: bismark: bismark_threads: 4 bowtie_threads: 2 upload: dir: ../final ``` Tests: ```eval_rst +--------+-----------------+----------------+----------+----------+-----+ | test_N | bismark_threads | bowtie_threads | time | bcbio -n | RAM | +========+=================+================+==========+==========+=====+ | 01 |1 |2 |14h 42min | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 02 |1 |4 |>3.5 days | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 03 |1 |8 |1d 21h | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 04 |1 |16 |1d 15h | 32 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 05 |1 |32 |>3day 14h | 64 | 100G| +--------+-----------------+----------------+----------+----------+-----+ | 06 |2 |2 |2days 4h | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | **07** |4 |2 |13h | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 08 |8 |2 |3h 34 min | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | **09** |16 |2 |2h 42 min | 32 | 100G| +--------+-----------------+----------------+----------+----------+-----+ | 10 |32 |2 |7h 40 min | 64 | 250G| +--------+-----------------+----------------+----------+----------+-----+ | 11 |2 |4 |1d 23h | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 12 |2 |8 |11h 30 min| 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 13 |2 |16 |11h 45 min| 32 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 14 |2 |32 |>3days 14h| 64 | 100G| +--------+-----------------+----------------+----------+----------+-----+ | 15 |4 |2 |4h 4 min | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 16 |4 |4 |15 h | 16 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 17 |4 |8 |6 h | 32 | 50G | +--------+-----------------+----------------+----------+----------+-----+ | 18 |4 |16 |15h | 64 | 100G| +--------+-----------------+----------------+----------+----------+-----+ | 19 |4 |32 |1d 2h | 128 | 200G| +--------+-----------------+----------------+----------+----------+-----+ | 20 |24 |2 |8h | 48 | 192G| +--------+-----------------+----------------+----------+----------+-----+ ``` ipython parallelization is not implemented for `wgbs-seq`, use 1 node / multicore jobs. ## References - [Bock.2012.Analysing and interpreting DNA methylation data](https://www.nature.com/articles/nrg3273) - [accelngs](https://swiftbiosci.com/accel-ngs-methyl-seq-dna-library-kit/) - [nebemseq](https://www.neb.com/products/e7120-nebnext-enzymatic-methyl-seq-kit) - [truseq](https://www.illumina.com/products/by-type/sequencing-kits/library-prep-kits/truseq-methyl-capture-epic.html) bcbio-nextgen-1.2.9/docs/contents/misc/000077500000000000000000000000001415626112400177715ustar00rootroot00000000000000bcbio-nextgen-1.2.9/docs/contents/misc/bcbio-smallrna.bib000066400000000000000000000717031415626112400233440ustar00rootroot00000000000000@misc{Andrews2010, abstract = {FastQC aims to provide a simple way to do some quality control checks on raw sequence data coming from high throughput sequencing pipelines. It provides a modular set of analyses which you can use to give a quick impression of whether your data has any problems of which you should be aware before doing any further analysis. The main functions of FastQC are Import of data from BAM, SAM or FastQ files (any variant) Providing a quick overview to tell you in which areas there may be problems Summary graphs and tables to quickly assess your data Export of results to an HTML based permanent report Offline operation to allow automated generation of reports without running the interactive application}, author = {Andrews, S.}, booktitle = {Bioinformatics}, doi = {citeulike-article-id:11583827}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, pages = {1}, title = {{FastQC: A quality control tool for high throughput sequence data}}, url = {http://scholar.google.com/scholar?hl=en{\&}btnG=Search{\&}q=intitle:FastQC+a+quality+control+tool+for+high+throughput+sequence+data.{\#}0}, year = {2010} } @article{Griffiths-Jones2004, abstract = {The miRNA Registry provides a service for the assignment of miRNA gene names prior to publication. A comprehensive and searchable database of published miRNA sequences is accessible via a web interface (http://www.sanger.ac.uk/Software/Rfam/mirna/), and all sequence and annotation data are freely available for download. Release 2.0 of the database contains 506 miRNA entries from six organisms.}, author = {Griffiths-Jones, Sam}, doi = {10.1093/nar/gkh023}, isbn = {1362-4962 (Electronic)$\backslash$r0305-1048 (Linking)}, issn = {1362-4962}, journal = {Nucleic acids research}, keywords = {Animals,Base Sequence,Computational Biology,Databases,Humans,Internet,MicroRNAs,MicroRNAs: chemistry,MicroRNAs: genetics,Nucleic Acid,Nucleic Acid Conformation,Registries,bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {Database issue}, pages = {D109--11}, pmid = {14681370}, title = {{The microRNA Registry.}}, url = {http://www.ncbi.nlm.nih.gov/pubmed/14681370}, volume = {32}, year = {2004} } @article{Griffiths-Jones2006, abstract = {The miRBase Sequence database is the primary repository for published microRNA (miRNA) sequence and annotation data. miRBase provides a user-friendly web interface for miRNA data, allowing the user to search using key words or sequences, trace links to the primary literature referencing the miRNA discoveries, analyze genomic coordinates and context, and mine relationships between miRNA sequences. miRBase also provides a confidential gene-naming service, assigning official miRNA names to novel genes before their publication. The methods outlined in this chapter describe these functions. miRBase is freely available to all at http://microrna.sanger.ac.uk/.}, author = {Griffiths-Jones, Sam}, doi = {10.1385/1-59745-123-1:129}, isbn = {1064-3745 (Print)}, issn = {1064-3745}, journal = {Methods in Molecular Biology (Clifton, N.J.)}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, pages = {129--38}, pmid = {16957372}, title = {{miRBase: the microRNA sequence database}}, url = {http://www.ncbi.nlm.nih.gov/pubmed/16957372$\backslash$nhttp://www.ncbi.nlm.nih.gov/pubmed/16957372?ordinalpos=2{\&}itool=EntrezSystem2.PEntrez.Pubmed.Pubmed{\_}ResultsPanel.Pubmed{\_}DefaultReportPanel.Pubmed{\_}RVDocSum}, volume = {342}, year = {2006} } @article{Griffiths-Jones2008, abstract = {miRBase is the central online repository for microRNA (miRNA) nomenclature, sequence data, annotation and target prediction. The current release (10.0) contains 5071 miRNA loci from 58 species, expressing 5922 distinct mature miRNA sequences: a growth of over 2000 sequences in the past 2 years. miRBase provides a range of data to facilitate studies of miRNA genomics: all miRNAs are mapped to their genomic coordinates. Clusters of miRNA sequences in the genome are highlighted, and can be defined and retrieved with any inter-miRNA distance. The overlap of miRNA sequences with annotated transcripts, both protein- and non-coding, are described. Finally, graphical views of the locations of a wide range of genomic features in model organisms allow for the first time the prediction of the likely boundaries of many miRNA primary transcripts. miRBase is available at http://microrna.sanger.ac.uk/.}, author = {Griffiths-Jones, Sam and Saini, Harpreet Kaur and {Van Dongen}, Stijn and Enright, Anton J.}, doi = {10.1093/nar/gkm952}, isbn = {1362-4962 (Electronic)$\backslash$r0305-1048 (Linking)}, issn = {03051048}, journal = {Nucleic Acids Research}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {SUPPL. 1}, pmid = {17991681}, title = {{miRBase: Tools for microRNA genomics}}, volume = {36}, year = {2008} } @article{Kozomara2011, abstract = {miRBase is the primary online repository for all microRNA sequences and annotation. The current release (miRBase 16) contains over 15,000 microRNA gene loci in over 140 species, and over 17,000 distinct mature microRNA sequences. Deep-sequencing technologies have delivered a sharp rise in the rate of novel microRNA discovery. We have mapped reads from short RNA deep-sequencing experiments to microRNAs in miRBase and developed web interfaces to view these mappings. The user can view all read data associated with a given microRNA annotation, filter reads by experiment and count, and search for microRNAs by tissue- and stage-specific expression. These data can be used as a proxy for relative expression levels of microRNA sequences, provide detailed evidence for microRNA annotations and alternative isoforms of mature microRNAs, and allow us to revisit previous annotations. miRBase is available online at: http://www.mirbase.org/.}, archivePrefix = {arXiv}, arxivId = {NIHMS150003}, author = {Kozomara, Ana and Griffiths-Jones, Sam}, doi = {10.1093/nar/gkq1027}, eprint = {NIHMS150003}, isbn = {1362-4962 (Electronic)$\backslash$r0305-1048 (Linking)}, issn = {03051048}, journal = {Nucleic Acids Research}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {SUPPL. 1}, pmid = {21037258}, title = {{MiRBase: Integrating microRNA annotation and deep-sequencing data}}, volume = {39}, year = {2011} } @article{Kozomara2014, abstract = {We describe an update of the miRBase database (http://www.mirbase.org/), the primary microRNA sequence repository. The latest miRBase release (v20, June 2013) contains 24 521 microRNA loci from 206 species, processed to produce 30 424 mature microRNA products. The rate of deposition of novel microRNAs and the number of researchers involved in their discovery continue to increase, driven largely by small RNA deep sequencing experiments. In the face of these increases, and a range of microRNA annotation methods and criteria, maintaining the quality of the microRNA sequence data set is a significant challenge. Here, we describe recent developments of the miRBase database to address this issue. In particular, we describe the collation and use of deep sequencing data sets to assign levels of confidence to miRBase entries. We now provide a high confidence subset of miRBase entries, based on the pattern of mapped reads. The high confidence microRNA data set is available alongside the complete microRNA collection at http://www.mirbase.org/. We also describe embedding microRNA-specific Wikipedia pages on the miRBase website to encourage the microRNA community to contribute and share textual and functional information.}, author = {Kozomara, Ana and Griffiths-Jones, Sam}, doi = {10.1093/nar/gkt1181}, isbn = {1362-4962 (Electronic)}, issn = {03051048}, journal = {Nucleic Acids Research}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {D1}, pmid = {24275495}, title = {{MiRBase: Annotating high confidence microRNAs using deep sequencing data}}, volume = {42}, year = {2014} } @misc{Heger2009, abstract = {Pysam is a python module for reading and manipulating Samfiles. It's a lightweight wrapper of the samtools C-API. Pysam also includes an interface for tabix.}, author = {Heger, Andreas}, booktitle = {github.com}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, title = {{Pysam}}, url = {https://github.com/pysam-developers/pysam}, year = {2009} } @article{Quinlan2010, abstract = {MOTIVATION: Testing for correlations between different sets of genomic features is a fundamental task in genomics research. However, searching for overlaps between features with existing web-based methods is complicated by the massive datasets that are routinely produced with current sequencing technologies. Fast and flexible tools are therefore required to ask complex questions of these data in an efficient manner.$\backslash$n$\backslash$nRESULTS: This article introduces a new software suite for the comparison, manipulation and annotation of genomic features in Browser Extensible Data (BED) and General Feature Format (GFF) format. BEDTools also supports the comparison of sequence alignments in BAM format to both BED and GFF features. The tools are extremely efficient and allow the user to compare large datasets (e.g. next-generation sequencing data) with both public and custom genome annotation tracks. BEDTools can be combined with one another as well as with standard UNIX commands, thus facilitating routine genomics tasks as well as pipelines that can quickly answer intricate questions of large genomic datasets.$\backslash$n$\backslash$nAVAILABILITY AND IMPLEMENTATION: BEDTools was written in C++. Source code and a comprehensive user manual are freely available at http://code.google.com/p/bedtools$\backslash$n$\backslash$nCONTACT: aaronquinlan@gmail.com; imh4y@virginia.edu$\backslash$n$\backslash$nSUPPLEMENTARY INFORMATION: Supplementary data are available at Bioinformatics online.}, author = {Quinlan, Aaron R. and Hall, Ira M.}, doi = {10.1093/bioinformatics/btq033}, isbn = {1367-4811 (Electronic)$\backslash$n1367-4803 (Linking)}, issn = {13674803}, journal = {Bioinformatics}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {6}, pages = {841--842}, pmid = {20110278}, title = {{BEDTools: A flexible suite of utilities for comparing genomic features}}, volume = {26}, year = {2010} } @article{Dale2011, abstract = {SUMMARY: pybedtools is a flexible Python software library for manipulating and exploring genomic datasets in many common formats. It provides an intuitive Python interface that extends upon the popular BEDTools genome arithmetic tools. The library is well documented and efficient, and allows researchers to quickly develop simple, yet powerful scripts that enable complex genomic analyses.$\backslash$n$\backslash$nAVAILABILITY: pybedtools is maintained under the GPL license. Stable versions of pybedtools as well as documentation are available on the Python Package Index at http://pypi.python.org/pypi/pybedtools.$\backslash$n$\backslash$nCONTACT: dalerr@niddk.nih.gov; arq5x@virginia.edu$\backslash$n$\backslash$nSUPPLEMENTARY INFORMATION: Supplementary data are available at Bioinformatics online.}, author = {Dale, Ryan K. and Pedersen, Brent S. and Quinlan, Aaron R.}, doi = {10.1093/bioinformatics/btr539}, isbn = {1367-4811 (Electronic)$\backslash$r1367-4803 (Linking)}, issn = {13674803}, journal = {Bioinformatics}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {24}, pages = {3423--3424}, pmid = {21949271}, title = {{Pybedtools: A flexible Python library for manipulating genomic datasets and annotations}}, volume = {27}, year = {2011} } @article{Langmead2009, abstract = {Bowtie is an ultrafast, memory-efficient alignment program for aligning short DNA sequence reads to large genomes. For the human genome, Burrows-Wheeler indexing allows Bowtie to align more than 25 million reads per CPU hour with a memory footprint of approximately 1.3 gigabytes. Bowtie extends previous Burrows-Wheeler techniques with a novel quality-aware backtracking algorithm that permits mismatches. Multiple processor cores can be used simultaneously to achieve even greater alignment speeds. Bowtie is open source (http://bowtie.cbcb.umd.edu).}, author = {Langmead, Ben and Trapnell, Cole and Pop, Mihai and Salzberg, Steven L}, doi = {10.1186/gb-2009-10-3-r25}, isbn = {1465-6914 (Electronic)$\backslash$r1465-6906 (Linking)}, issn = {1465-6906}, journal = {Genome Biol}, keywords = {Algorithms,Base Sequence,Genome: Human,Humans,Sequence Alignment,bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, pages = {R25}, pmid = {19261174}, title = {{Ultrafast and memory-efficient alignment of short DNA sequences to the human genome}}, volume = {10}, year = {2009} } @article{Dobin2013, abstract = {MOTIVATION: Accurate alignment of high-throughput RNA-seq data is a challenging and yet unsolved problem because of the non-contiguous transcript structure, relatively short read lengths and constantly increasing throughput of the sequencing technologies. Currently available RNA-seq aligners suffer from high mapping error rates, low mapping speed, read length limitation and mapping biases.$\backslash$n$\backslash$nRESULTS: To align our large (>80 billon reads) ENCODE Transcriptome RNA-seq dataset, we developed the Spliced Transcripts Alignment to a Reference (STAR) software based on a previously undescribed RNA-seq alignment algorithm that uses sequential maximum mappable seed search in uncompressed suffix arrays followed by seed clustering and stitching procedure. STAR outperforms other aligners by a factor of >50 in mapping speed, aligning to the human genome 550 million 2 × 76 bp paired-end reads per hour on a modest 12-core server, while at the same time improving alignment sensitivity and precision. In addition to unbiased de novo detection of canonical junctions, STAR can discover non-canonical splices and chimeric (fusion) transcripts, and is also capable of mapping full-length RNA sequences. Using Roche 454 sequencing of reverse transcription polymerase chain reaction amplicons, we experimentally validated 1960 novel intergenic splice junctions with an 80-90{\%} success rate, corroborating the high precision of the STAR mapping strategy.$\backslash$n$\backslash$nAVAILABILITY AND IMPLEMENTATION: STAR is implemented as a standalone C++ code. STAR is free open source software distributed under GPLv3 license and can be downloaded from http://code.google.com/p/rna-star/.}, author = {Dobin, Alexander and Davis, Carrie A. and Schlesinger, Felix and Drenkow, Jorg and Zaleski, Chris and Jha, Sonali and Batut, Philippe and Chaisson, Mark and Gingeras, Thomas R.}, doi = {10.1093/bioinformatics/bts635}, isbn = {1367-4811 (Electronic)$\backslash$n1367-4803 (Linking)}, issn = {13674803}, journal = {Bioinformatics}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {1}, pages = {15--21}, pmid = {23104886}, title = {{STAR: Ultrafast universal RNA-seq aligner}}, volume = {29}, year = {2013} } @article{Tarasov2015, abstract = {UNLABELLED: Sambamba is a high-performance robust tool and library for working with SAM, BAM and CRAM sequence alignment files; the most common file formats for aligned next generation sequencing data. Sambamba is a faster alternative to samtools that exploits multi-core processing and dramatically reduces processing time. Sambamba is being adopted at sequencing centers, not only because of its speed, but also because of additional functionality, including coverage analysis and powerful filtering capability. AVAILABILITY AND IMPLEMENTATION: Sambamba is free and open source software, available under a GPLv2 license. Sambamba can be downloaded and installed from http://www.open-bio.org/wiki/Sambamba.Sambamba v0.5.0 was released with doi:10.5281/zenodo.13200.}, author = {Tarasov, Artem and Vilella, Albert J. and Cuppen, Edwin and Nijman, Isaac J. and Prins, Pjotr}, doi = {10.1093/bioinformatics/btv098}, issn = {14602059}, journal = {Bioinformatics}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {12}, pages = {2032--2034}, pmid = {25697820}, title = {{Sambamba: Fast processing of NGS alignment formats}}, volume = {31}, year = {2015} } @article{Didion2017, abstract = {A key step in the transformation of raw sequencing reads into biological insights is the trimming of adapter sequences and low-quality bases. Read trimming has been shown to increase the quality and reliability while decreasing the computational requirements of downstream analyses. Many read trimming software tools are available; however, no tool simultaneously provides the accuracy, computational efficiency, and feature set required to handle the types and volumes of data generated in modern sequencing-based experiments. Here we introduce Atropos and show that it trims reads with high sensitivity and specificity while maintaining leading-edge speed. Compared to other state-of-the-art read trimming tools, Atropos achieves significant increases in trimming accuracy while remaining competitive in execution times. Furthermore, Atropos maintains high accuracy even when trimming data with elevated rates of sequencing errors. The accuracy, high performance, and broad feature set offered by Atropos makes it an appropriate choice for the pre-processing of Illumina, ABI SOLiD, and other current-generation short-read sequencing datasets. Availability. Atropos is open source and free software written in Python (3.3+) and available at https://github.com/jdidion/atropos.}, author = {Didion, John P and Martin, Marcel and Collins, Francis S}, doi = {10.7287/peerj.preprints.2452v4}, issn = {2167-9843}, keywords = {Adapter,Cutadapt,Illumina,NGS,Preprocessing,Read,Sequencing,Trimming}, mendeley-groups = {Bioinfo/rnaseq}, month = {jan}, publisher = {PeerJ Inc.}, title = {{Atropos: specific, sensitive, and speedy trimming of sequencing reads}}, url = {https://peerj.com/preprints/2452/}, year = {2017} } @article{Li2011, abstract = {MOTIVATION: Most existing methods for DNA sequence analysis rely on accurate sequences or genotypes. However, in applications of the next-generation sequencing (NGS), accurate genotypes may not be easily obtained (e.g. multi-sample low-coverage sequencing or somatic mutation discovery). These applications press for the development of new methods for analyzing sequence data with uncertainty.$\backslash$n$\backslash$nRESULTS: We present a statistical framework for calling SNPs, discovering somatic mutations, inferring population genetical parameters and performing association tests directly based on sequencing data without explicit genotyping or linkage-based imputation. On real data, we demonstrate that our method achieves comparable accuracy to alternative methods for estimating site allele count, for inferring allele frequency spectrum and for association mapping. We also highlight the necessity of using symmetric datasets for finding somatic mutations and confirm that for discovering rare events, mismapping is frequently the leading source of errors.$\backslash$n$\backslash$nAVAILABILITY: http://samtools.sourceforge.net.$\backslash$n$\backslash$nCONTACT: hengli@broadinstitute.org.}, archivePrefix = {arXiv}, arxivId = {1203.6372}, author = {Li, Heng}, doi = {10.1093/bioinformatics/btr509}, eprint = {1203.6372}, isbn = {1367-4811 (Electronic)$\backslash$r1367-4803 (Linking)}, issn = {13674803}, journal = {Bioinformatics}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {21}, pages = {2987--2993}, pmid = {21903627}, title = {{A statistical framework for SNP calling, mutation discovery, association mapping and population genetical parameter estimation from sequencing data}}, volume = {27}, year = {2011} } @article{Li2009, abstract = {SUMMARY: The Sequence Alignment/Map (SAM) format is a generic alignment format for storing read alignments against reference sequences, supporting short and long reads (up to 128 Mbp) produced by different sequencing platforms. It is flexible in style, compact in size, efficient in random access and is the format in which alignments from the 1000 Genomes Project are released. SAMtools implements various utilities for post-processing alignments in the SAM format, such as indexing, variant caller and alignment viewer, and thus provides universal tools for processing read alignments. AVAILABILITY: http://samtools.sourceforge.net.}, archivePrefix = {arXiv}, arxivId = {1006.1266v2}, author = {Li, Heng and Handsaker, Bob and Wysoker, Alec and Fennell, Tim and Ruan, Jue and Homer, Nils and Marth, Gabor and Abecasis, Goncalo and Durbin, Richard}, doi = {10.1093/bioinformatics/btp352}, eprint = {1006.1266v2}, isbn = {1367-4803$\backslash$r1460-2059}, issn = {13674803}, journal = {Bioinformatics}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {16}, pages = {2078--2079}, pmid = {19505943}, title = {{The Sequence Alignment/Map format and SAMtools}}, volume = {25}, year = {2009} } @article{Friedl??nder2012, abstract = {microRNAs (miRNAs) are a large class of small non-coding RNAs which post-transcriptionally regulate the expression of a large fraction of all animal genes and are important in a wide range of biological processes. Recent advances in high-throughput sequencing allow miRNA detection at unprecedented sensitivity, but the computational task of accurately identifying the miRNAs in the background of sequenced RNAs remains challenging. For this purpose, we have designed miRDeep2, a substantially improved algorithm which identifies canonical and non-canonical miRNAs such as those derived from transposable elements and informs on high-confidence candidates that are detected in multiple independent samples. Analyzing data from seven animal species representing the major animal clades, miRDeep2 identified miRNAs with an accuracy of 98.6-99.9{\%} and reported hundreds of novel miRNAs. To test the accuracy of miRDeep2, we knocked down the miRNA biogenesis pathway in a human cell line and sequenced small RNAs before and after. The vast majority of the >100 novel miRNAs expressed in this cell line were indeed specifically downregulated, validating most miRDeep2 predictions. Last, a new miRNA expression profiling routine, low time and memory usage and user-friendly interactive graphic output can make miRDeep2 useful to a wide range of researchers.}, author = {Friedl??nder, Marc R. and MacKowiak, Sebastian D. and Li, Na and Chen, Wei and Rajewsky, Nikolaus}, doi = {10.1093/nar/gkr688}, isbn = {1362-4962 (Electronic)$\backslash$r0305-1048 (Linking)}, issn = {03051048}, journal = {Nucleic Acids Research}, keywords = {bcbio-srnaseq}, mendeley-groups = {Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {1}, pages = {37--52}, pmid = {21911355}, title = {{MiRDeep2 accurately identifies known and hundreds of novel microRNA genes in seven animal clades}}, volume = {40}, year = {2012} } @article{Selitsky2015, abstract = {BACKGROUND: Small RNA-sequencing has revealed the diversity and high abundance of small RNAs derived from tRNAs, referred to as tRNA-derived RNAs. However, at present, there is no standardized nomenclature and there are no methods for accurate annotation and quantification of these small RNAs. tRNA-derived RNAs have unique features that limit the utility of conventional alignment tools and quantification methods. RESULTS: We describe here the challenges of mapping, naming, and quantifying tRNA-derived RNAs and present a novel method that addresses them, called tDRmapper. We then use tDRmapper to perform a comparative analysis of tRNA-derived RNA profiles across different human cell types and diseases. We found that (1) tRNA-derived RNA profiles can differ dramatically across different cell types and disease states, (2) that positions and types of chemical modifications of tRNA-derived RNAs vary by cell type and disease, and (3) that entirely different tRNA-derived RNA species can be produced from the same parental tRNA depending on the cell type. CONCLUSION: tDRmappernot only provides a standardized nomenclature and quantification scheme, but also includes graphical visualization that facilitates the discovery of novel tRNA and tRNA-derived RNA biology.}, author = {Selitsky, Sara R and Sethupathy, Praveen}, doi = {10.1186/s12859-015-0800-0}, isbn = {10.1186/s12859-015-0800-0}, issn = {1471-2105}, journal = {BMC bioinformatics}, keywords = {Bioinformatics,RNA modifications,Sequencing,bcbio-srnaseq,bioinformatics,rna modifications,sequencing,tDR,tRNA,tdr,trna}, mendeley-groups = {smallrna/others,Bioinfo/pipelines}, mendeley-tags = {bcbio-srnaseq}, number = {1}, pages = {354}, pmid = {26530785}, title = {{tDRmapper: challenges and solutions to mapping, naming, and quantifying tRNA-derived RNAs from human small RNA-sequencing data.}}, url = {http://www.biomedcentral.com/1471-2105/16/354}, volume = {16}, year = {2015} } @article{Pantano2015, abstract = {MOTIVATION: Most computational tools for small non-coding RNAs (sRNA) sequencing data analysis focus in microRNAs (miRNAs), overlooking other types of sRNAs that show multi-mapping hits. Here, we have developed a pipeline to non-redundantly quantify all types of sRNAs, and extract patterns of expression in biologically defined groups. We have used our tool to characterize and profile sRNAs in post-mortem brain samples of control individuals and Parkinson's disease (PD) cases at early-premotor and late-symptomatic stages. RESULTS: Clusters of co-expressed sRNAs mapping onto tRNAs significantly separated premotor and motor cases from controls. A similar result was obtained using a matrix of miRNAs slightly varying in sequence (isomiRs). The present framework revealed sRNA alterations at premotor stages of PD, which might reflect initial pathogenic perturbations. This tool may be useful to discover sRNA expression patterns linked to different biological conditions. AVAILABILITY AND IMPLEMENTATION: The full code is available at http://github.com/lpantano/seqbuster. CONTACT: lpantano@hsph.harvard.edu or eulalia.marti@crg.euSupplementary information: Supplementary data are available at Bioinformatics online.}, author = {Pantano, Lorena and Friedlander, Marc R and Escaramis, Georgia and Lizano, Esther and Pallares-Albanell, Joan and Ferrer, Isidre and Estivill, Xavier and Marti, Eulalia}, doi = {10.1093/bioinformatics/btv632}, issn = {1367-4811 (Electronic)}, journal = {Bioinformatics (Oxford, England)}, keywords = {bcbio-srnaseq}, mendeley-tags = {bcbio-srnaseq}, month = {nov}, pmid = {26530722}, title = {{Specific small-RNA signatures in the amygdala at premotor and motor stages of Parkinson's disease revealed by deep sequencing analysis.}}, url = {http://www.ncbi.nlm.nih.gov/pubmed/26530722}, year = {2015} } @article{Pantano2010, abstract = {High-throughput sequencing technologies enable direct approaches to catalog and analyze snapshots of the total small RNA content of living cells. Characterization of high-throughput sequencing data requires bioinformatic tools offering a wide perspective of the small RNA transcriptome. Here we present SeqBuster, a highly versatile and reliable web-based toolkit to process and analyze large-scale small RNA datasets. The high flexibility of this tool is illustrated by the multiple choices offered in the pre-analysis for mapping purposes and in the different analysis modules for data manipulation. To overcome the storage capacity limitations of the web-based tool, SeqBuster offers a stand-alone version that permits the annotation against any custom database. SeqBuster integrates multiple analyses modules in a unique platform and constitutes the first bioinformatic tool offering a deep characterization of miRNA variants (isomiRs). The application of SeqBuster to small-RNA datasets of human embryonic stem cells revealed that most miRNAs present different types of isomiRs, some of them being associated to stem cell differentiation. The exhaustive description of the isomiRs provided by SeqBuster could help to identify miRNA-variants that are relevant in physiological and pathological processes. SeqBuster is available at http://estivilllab.crg.es/seqbuster.}, author = {Pantano, Lorena and Estivill, Xavier and Mart{\'{\i}}, Eul{\`{a}}lia}, institution = {Genetic Causes of Disease Group, Genes and Disease Program, Centre for Genomic Regulation, Pompeu Fabra University, Barcelona, Catalonia, Spain.}, journal = {Nucleic Acids Research}, keywords = {bcbio-srnaseq,cell differentiation,computational biology,embryonic stem cells,embryonic stem cells cytology,embryonic stem cells metabolism,genetic variation,humans,micrornas,micrornas chemistry,micrornas metabolism,rna,sequence analysis,software}, mendeley-tags = {bcbio-srnaseq}, number = {5}, pages = {e34}, publisher = {Oxford University Press}, title = {{SeqBuster, a bioinformatic tool for the processing and analysis of small RNAs datasets, reveals ubiquitous miRNA modifications in human embryonic cells}}, url = {http://www.ncbi.nlm.nih.gov/pubmed/20008100}, volume = {38}, year = {2010} } bcbio-nextgen-1.2.9/docs/contents/outputs.md000066400000000000000000000141351415626112400211070ustar00rootroot00000000000000# Outputs bcbio-nextgen runs in a temporary work directory which contains a number of processing intermediates. Pipeline completion extracts the final useful output files into a separate directory, specified by the [Upload](contents/configuration:upload). This configuration allows upload to local directories, Galaxy, or Amazon S3. Once extracting and confirming the output files, you can delete the temporary directory to save space. The output directory contains sample specific output files labeled by sample name and a more general project directory. The sample directories contain all of the sample specific output files, while the project directory contains global files like project summaries or batched population level variant calls. See the [Teaching](teaching) documentation for a full variant calling example with additional details about configuration setting and resulting output files. ## Project directory: * `project-summary.yaml` -- Top level YAML format summary file with statistics on read alignments and duplications as well as analysis specific metrics. * `programs.txt` -- Program versions for bcbio-nextgen and software run in the pipeline. This enables reproduction of analyses. * `multiqc` -- [MultiQC](https://multiqc.info/) report. multiqc_report.html combines quality metrics from multiple tools (listed in multiqc_config.yaml). - General statistics/Dup - % of duplicates among mapped reads, calculated by [bcbio.qc.qualimap.py](https://github.com/bcbio/bcbio-nextgen/blob/69bc24d703d3a0166caabf833ddd9e514ff1d445/bcbio/qc/qualimap.py#L219) - General statistics/% Dups - duplication statistics from [fastqc](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/). It uses first 200k reads to generate % DUP, not a good proxy for RNA-seq data, [read more in fastqc docs](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/3%20Analysis%20Modules/8%20Duplicate%20Sequences.html) - Fastqc/Sequence counts/duplicates - same as General statistics/%Dups - `General statistics/ontarget_pct` = 100.0 * ontarget / mapped_unique, see [code](https://github.com/bcbio/bcbio-nextgen/blob/a3473775db06540c10b5f20ddc2043b8cc99d1f8/bcbio/qc/coverage.py#L63) - `General statistics/Usable_pct` = 100.0 * ontarget / total_reads * `metadata.csv` -- CSV with the metadata in the YAML file. * `data_versions.csv` -- Data versions for bcbio-nextgen and software ## Sample directories: * `SAMPLE/qc` -- Directory of quality control runs for the sample. These include charts and metrics for assessing quality of sequencing and analysis. * `SAMPLE-ready.bam` -- A prepared BAM file of the aligned reads. Depending on the analysis used, this may include trimmed, recalibrated and realigned reads following alignment. ## Why do I have so many coverage metrics? Which one should I use? ## Interpretation of ontarget_pct vs usable_pct Usually, `ontarget_pct` > `usable_pct` for WES without UMI because `mapped_unique < total_reads`, `ontarget_pct ~ usable_pct` for projects with UMI, because UMI consensus reads are mapped by definition. Sometimes `ontarget_pct` < `usable_pct`, the difference is <=0.2% for UMI projects, because `total_reads` is calculated by samtools, and `mapped_unique` by [readstats.py](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/bam/readstats.py#L37), which leads to a slight difference in `mapped_unique > total`. ## Interpretation of mosdepth median coverage vs qualimap median coverage `Mosdepth median coverage` < `Qualimap median coverage`. For example, mosdepth = 133, qualimap = 169. Mosdepth calculates the median over the average coverages of contigs (chromosomes), see `mosdepth/Average coverage per contig` figure. Most of the chromosomes have coverage 150-200X, but chromosomes are very few and additional chromosomes have coverage 20-30X, so the median is lowered by that fact. qualimap goes for a median over all exonic regions, see `Qualimap/Coverage Histogram` figure. Exonic regions are many and the median is higher. Use qualimap median coverage as a better estimate. Note that `tools_on: qualimap_full` should be used to get reliable estimates from qualimap. If you are subsetting bam for qualimap (default), use mosdepth median coverage. ## Interpretation of bcbio(mosdepth) average target coverage vs qualimap mean coverage First of all, these two should not be confused with median coverage from mosdepth and qualimap (mean vs median). `bcbio_average_target` is calculated by [get_average_coverage](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/variation/coverage.py#L154), in the end it is coverage from `mosdepth`: `NA12878-exome-eval/work/coverage/NA12878/NA12878-variant_regions.regions.bed.gz ` for NA12878 WES project. It is calculated **excluding** duplicated reads and reads with unmapped mate. See also statistics here in the `bcbio project/work/coverage/mapped_stats.txt`. Qualimap includes these reads, so usually for WES data with and without UMIs `bcbio_average_target < qualimap_mean_coverage`. However, we've seen some projects with UMIs and panels where `bcbio_average_target_coverage >> qualimap_mean_coverage`. Use `bcbio_average`. ## Why I am getting Ontarget_pct > 100? Try to show +-200 bp (Ontarget_padded_pct) column in multiqc. If it is < 100% that means the original bed file specified in the yaml `coverage: coverage.bed` is too fragmented. Some reads counted twice by hts_nim_tools (againts two overlapping baits) and the ontarget stats gets inflated. Solution: use variants.bed (padded 70bp) not coverage.bed in the yaml for `coverage`. ## Downstream analysis This section collects useful scripts and tools to do downstream analysis of bcbio-nextgen outputs. If you have pointers to useful tools, please add them to the documentation. * [Calculate and plot coverage](https://github.com/bcbio/bcbio-nextgen/issues/195#issuecomment-39071048) with matplolib, from Luca Beltrame. * [Another way](https://www.gettinggeneticsdone.com/2014/03/visualize-coverage-exome-targeted-ngs-bedtools.html) to visualize coverage for targeted NGS (exome) experiments with bedtools and R, from Stephen Turner * assess the efficiency of targeted enrichment sequencing with [ngscat](http://ngscat.clinbioinfosspa.es/start) bcbio-nextgen-1.2.9/docs/contents/parallel.md000066400000000000000000000503701415626112400211610ustar00rootroot00000000000000# Parallel execution The pipeline runs in parallel in two different ways: * multiple cores -- Analyses will run in parallel using multiple cores on a single machine. This requires only the `multiprocessing` Python library, included by default with most Python installations. * parallel messaging -- This allows scaling beyond the cores available on a single machine, and requires multiple machines with a shared filesystem like standard cluster environments. Machine to machine communication occurs via messaging, using the [IPython parallel](https://ipython.readthedocs.io/en/stable/) framework. ## Tuning core and memory usage bcbio has two ways to specify core usage, helping provide options for parallelizing different types of processes: * Total available cores: specified with `-n` on the commandline, this tells bcbio how many total cores to use. This applies either to a local multicore run or a distributed job. * Maximum cores to use for multicore processing of individual jobs. You specify this in the `resource` section of either a sample YAML file or `bcbio_system.yaml`. Ideally you specify this in the `default` section (along with memory usage). For example, this would specify that processes using multiple cores can get up to 16 cores with 2GB of memory per core: ```yaml resources: default: memory: 2G cores: 16 jvm_opts: ["-Xms750m", "-Xmx2000m"] ``` bcbio uses these settings, along with memory requests, to determine how to partition jobs. For example, if you had `-n 32` and `cores: 16` for a run on a single 32 core machine, this would run two simultaneous bwa mapping jobs using 16 cores each. Memory specifications (both in `memory` and `jvm_opts`) are per-core. bcbio takes care of adjusting this memory to match the cores used. In the example above, if bcbio was running a 16 core java process, it would use 32GB of memory for the JVM, adjusting `Xmx` and `Xms` to match cores used. Internally bcbio looks at the memory and CPU usage on a machine and matches your configuration options to the available system resources. It will scale down core requests if memory is limiting, avoiding over-scheduling resources during the run. You ideally want to set both `memory` and `jvm_opts` to match the average memory per core on the run machine and adjust upwards if this does not provide enough memory for some processes during the run. For single machine runs with a small number of samples, you generally want to set `cores` close to or equal the number of total cores you're allocating to the job with `-n`. This will allow individual samples to process as fast as possible and take advantage of multicore software. For distributed jobs, you want to set `cores` to match the available cores on a single node in your cluster, then use `-n` as a multiple of this to determine how many nodes to spin up. For example, `cores: 16` and `-n 64` would try to make four 16 core machines available for analysis. ## Multiple cores Running using multiple cores only requires setting the `-n` command line flag: ```shell bcbio_nextgen.py bcbio_sample.yaml -t local -n 12 ``` ## IPython parallel [IPython parallel](https://ipython.readthedocs.io/en/stable/) provides a distributed framework for performing parallel computation in standard cluster environments. The bcbio-nextgen setup script installs both IPython and [pyzmq](https://github.com/zeromq/pyzmq), which provides Python bindings for the [ZeroMQ](https://zeromq.org/) messaging library. The only additional requirement is that the work directory where you run the analysis is accessible to all processing nodes. This is typically accomplished with a distributed file system like [NFS](https://en.wikipedia.org/wiki/Network_File_System), [Gluster](https://www.gluster.org/) or [Lustre](http://wiki.lustre.org/Main_Page). Run an analysis using ipython for parallel execution: A typical SLURM batch script or [O2 cluster](https://wiki.rc.hms.harvard.edu/display/O2): `sbatch bcbio.sh`: ```bash #!/bin/bash # https://slurm.schedmd.com/sbatch.html #SBATCH --partition=priority # Partition (queue) #SBATCH --time=5-00:00:00 # Runtime in D-HH:MM format #SBATCH --job-name=bulkrnatest # Job name #SBATCH -c 1 #SBATCH --mem-per-cpu=10G # Memory needed per CPU #SBATCH --output=project_%j.out # File to which STDOUT will be written, including job ID #SBATCH --error=project_%j.err # File to which STDERR will be written, including job ID #SBATCH --mail-type=NONE # Type of email notification (BEGIN, END, FAIL, ALL) bcbio_nextgen.py ../config/project.yaml -n 72 -t ipython -s slurm -q medium -r t=0-72:00 -r conmem=20 --timeout 3000 --tag "rna" ``` - this is a launcher job which goes to priority partition (queue), requests 1CPU/10G RAM; it is not doing any calculations; - it submits a controller job to the medium partition with MEM=20G; - the controller job submits worker jobs to the medium; total cores for all workers = 72; cores/worker is configured in the bcbio system config; worker jobs walltime (72h) < launch job walltime (5days). LSF example: ```shell bcbio_nextgen.py bcbio_sample.yaml -t ipython -n 12 -s lsf -q queue ``` The `-s` flag specifies a type of scheduler to use `(lsf, sge, torque, slurm, pbspro)`. The `-q` flag specifies the queue to submit jobs to. The `-n` flag defines the total number of cores to use on the cluster during processing. The framework will select the appropriate number of cores and type of cluster (single core versus multi-core) to use based on the pipeline stage (see the `Parallel` section in the internals documentation for more details). For multiple core steps, the number of cores to use for programs like `bwa`, `novoalign` and `gatk` comes from the `Resources` section of the configuration. Ensure the `cores` specification matches the physical cores available on machines in your cluster, and the pipeline will divide the total cores specified by `-n` into the appropriate number of multicore jobs to run. The pipeline default parameters assume a system with minimal time to obtain processing cores and consistent file system accessibility. These defaults allow the system to fail fast in the case of cluster issues which need diagnosis. For running on shared systems with high resource usage and potential failures due to intermittent cluster issues, there are turning parameters that increase resiliency. The `--timeout` flag specifies the numbers of minutes to wait for a cluster to start up before timing out. This defaults to 15 minutes. The `--retries` flag specify the number of times to retry a job on failure. In systems with transient distributed file system hiccups like lock errors or disk availability, this will provide recoverability at the cost of resubmitting jobs that may have failed for reproducible reasons. Finally, the `-r resources` flag specifies resource options to pass along to the underlying queue scheduler. This currently supports SGE's `-l` parameter, Torque's `-l` parameter and LSF and SLURM native flags. This allows specification or resources to the scheduler (see the [qsub man page](http://gridscheduler.sourceforge.net/htmlman/htmlman1/qsub.html)). You may specify multiple resources, so `-r mem=4g -r ct=01:40:00` translates to `-l mem=4g -l ct=01:40:00` when passed to `qsub` or `-r "account=a2010002" -r "timelimit=04:00:00"` when using SLURM, for instance. SLURM and Torque support specification of an account parameter with `-r account=your_name`, which IPython transfers into `-A`. SGE supports special parameters passed using resources to help handle the heterogeneity of possible setups. Specify an [SGE parallel environment](https://docs.oracle.com/cd/E19957-01/820-0698/6ncdvjcmd/index.html) that supports using multiple cores on a single node with `-r pename=your_pe`. Since this setup is system specific it is hard to write general code for find a suitable environment. Specifically, when there are multiple usable parallel environments, it will select the first one which may not be correct. Manually specifying it with a `pename=` flag to resources will ensure correct selection of the right environment. If you're administering a grid engine cluster and not sure how to set this up you'd typically want a `smp` queue using `allocation_rule: $pe_slots` like in this [example pename configuration](https://github.com/WGLab/biocluster/blob/431a05f6dfd532205aacfc7477ac740b0e7b2a0a/03%20System%20customization.md#setting-up-parallel-environment) or [smp template](https://gist.github.com/dan-blanchard/6586533#file-smp_template). SGE has other specific flags you may want to tune, depending on your setup. To specify an advanced reservation with the `-ar` flag, use `-r ar=ar_id`. To specify an alternative memory management model instead of `mem_free` use `-r memtype=approach`. It is further recommended to configure `mem_free` (or any other chosen memory management model) as a consumable, requestable resource in SGE to prevent overfilling hosts that do not have sufficient memory per slot. This can be done in two steps. First, launch `qmon` as an admin, select `Complex Configuration` in qmon, click on `mem_free`, under the `Consumable` dialog select `JOB` (instead of `YES` or `NO`) and finally click `Modify` for the changes to take effect. Secondly, for each host in the queue, configure`mem_free` as a complex value. If a host called `myngshost` has 128GB of RAM, the corresponding command would be `qconf -mattr exechost complex_values mem_free=128G myngshost`. There are also special `-r`resources parameters to support pipeline configuration: * `-r conmem=4` -- Specify the memory for the controller process, in GB. This currently applies to SLURM processing and defaults to 4GB. * `-r minconcores=2` -- The minimum number of cores to use for the controller process. The controller one works on a single core but this can help in queues where you can only specify multicore jobs. * `-r mincores=16` -- Specify the minimum number of cores to batch together for parallel single core processes like variant calling. This will run multiple processes together under a single submission to allow sharing of resources like memory, which is helpful when a small percentage of the time a process like variant calling will use a lot of memory. By default, bcbio will calculate `mincores` based on specifications for multicore calling so this doesn't normally require a user to set. ## Troubleshooting ### Diagnosing job failures Parallel jobs can often terminate with rather generic failures like any of the following: * `joblib/parallel.py, ... TypeError: init() takes at least 3 arguments (2 given)` * `Multiprocessing exception:` * `CalledProcessError: Command ''` These errors unfortunately don't help diagnose the problem, and you'll likely see the actual error triggering this generic exception earlier in the run. This error can often be hard to find due to parallelization. If you run into a confusing failure like this, the best approach is to re-run with a single core: ```shell bcbio_nextgen.py your_input.yaml -n 1 ``` which should produce a more helpful debug message right above the failure. It's also worth re-trying the failed command line outside of bcbio to look for errors. You can find the failing command by cross-referencing the error message with command lines in `log/bcbio-nextgen-commands.log`. You may have to change temporary directories (`tx/tmp**`) in some of the job outputs. Reproducing the error outside of bcbio is a good first step to diagnosing and fixing the underlying issue. ### No parallelization where expected This may occur if the current execution is a re-run of a previous project: * Files in `checkpoints_parallel/*.done` tell bcbio not to parallelize already executed pipeline tasks. This makes restarts faster by avoiding re-starting a cluster (when using distributed runs) for finished stages. If that behaviour is not desired for a task, removing the checkpoint file will get things parallelizing again. * If the processing of a task is nearly finished the last jobs of this task will be running and bcbio will wait for those to finish. ### IPython parallelization problems Networking problems on clusters can prevent the IPython parallelization framework from working properly. Be sure that the compute nodes on your cluster are aware of IP addresses that they can use to communicate with each other (usually these will be local IP addresses). Running: ```shell python -c 'import socket; print socket.gethostbyname(socket.gethostname())' ``` Should return such an IP address (as opposed to localhost). This can be fixed by adding an entry to the hosts file. The line: ``` host-ip hostname ``` where `host-ip` is replaced by the actual IP address of the machine and `hostname` by the machine's own hostname, should be aded to `/etc/hosts` on each compute node. This will probably involve contacting your local cluster administrator. ## Memory management The memory information specified in the system configuration `Resources` enables scheduling of memory intensive processes. The values are specified on a *memory-per-core* basis and thus bcbio-nextgen handles memory scheduling by: * [Determining available cores and memory per machine](#determining-available-cores-and-memory-per-machine) * Calculating the memory and core usage. The system configuration `Resources` contains the expected core and memory usage of external programs. * Adjusting the specified number of total cores to avoid over-scheduling memory. This allows running programs with more than the available memory per core without getting out of memory system errors. * Passing total memory usage along to schedulers. The SLURM, SGE, Torque and PBSPro schedulers use this information to allocate memory to processes, avoiding issues with other scheduled programs using available memory on a shared machine. As a result of these calculations, the cores used during processing will not always correspond to the maximum cores provided in the input `-n` parameter. The goal is rather to intelligently maximize cores and memory while staying within system resources. Note that memory specifications are for a single core, and the pipeline takes care of adjusting this to actual cores used during processing. ## Determining available cores and memory per machine bcbio automatically tries to determine the total available memory and cores per machine for balancing resource usage. For multicore runs, it retrieves total memory from the current machine. For parallel runs, it spawns a job on the queue and extracts the system information from that machine. This expects a homogeneous set of machines within a cluster queue. You can see the determined cores and total memory in `provenance/system-ipython-queue.yaml`. For heterogeneous clusters or other cases where bcbio does not correctly identify available system resources, you can manually set the machine cores and total memory in the`resource` section of either a sample YAML file or `bcbio_system.yaml`: ```yaml resources: machine: memory: 48.0 cores: 16 ``` The memory usage is total available on the machine in GB, so this specifies that individual machines have 48GB of total memory and 16 cores. ## Tuning systems for scale bcbio-nextgen scales out on clusters including hundreds of cores and is stress tested on systems with 1000 simultaneous processes. Scaling up often requires system specific tuning to handle simultaneous processes. This section collects useful tips and tricks for managing scaling issues. ### Open file handles A common failure mode is having too many open file handles. This error report can come from the IPython infrastructure logs as ZeroMQ attempts to open sockets, or from the processing logs as third party software gets file handles. You can check your available file handles with`ulimit -a | grep open`. Setting open file handle limits is open system and cluster specific and below are tips for specific setups. In addition to open file handle limits (`ulimit -n`) large processes may also run into issues with available max user processes (`ulimit -u`). Some systems set a low soft limit (`ulimit -Su`) like 1024 but a higher hard limit (`ulimit -Hu`), allowing adjustment without root privileges. The IPython controllers and engines do this automatically, but the main `bcbio_nextgen.py` driver process cannot. If this scheduler puts this process on the same node as worker processes, you may run into open file handle limits due to work happening on the workers. To fix this, manually set `ulimit -u a_high_number` as part of the submission process for the main process. For a Ubuntu system, edit `/etc/security/limits.conf` to set the soft and hard `nofile`descriptors, and edit `/etc/pam.d/common-session` to add `pam_limits.so`. See [this blog post](https://viewsby.wordpress.com/2013/01/29/ubuntu-increase-number-of-open-files/) for more details. For CentOS/RedHat systems, edit `/etc/security/limits.conf` and `/etc/security/limits.d/90-nproc.conf` to [increase maximum open files and user limits](https://ithubinfo.blogspot.com/2013/07/how-to-increase-ulimit-open-file-and.html). SGE needs configuration at the qmaster level. Invoke `qconf -mconf` from a host with admin privileges, and edit `execd_params`: ``` execd_params S_DESCRIPTORS=20000 ``` ### IO and Network File Systems bcbio-nextgen makes use of distributed network file systems to manage sharing large files between compute nodes. While we strive to minimize disk-based processing by making use of pipes, the pipeline still has a major IO component. To help manage IO and network bottlenecks, this section contains pointers on deployments and benchmarking. Please contribute your tips and thoughts. Harvard and Dell: See the 'Distributed File Systems' section of our [post on scaling bcbio-nextgen](https://bcb.io/2013/05/22/scaling-variant-detection-pipelines-for-whole-genome-sequencing-analysis/) for details about the setup within [Harvard FAS Research Computing](https://www.rc.fas.harvard.edu/) and thoughts on scaling and hardware. We also collaborate with Dell to test the pipeline on Dell's Active Infrastructure for Life Sciences. We found the biggest initial factor limiting scaling was network bandwidth between compute and storage nodes. ### Spark Some GATK tools like recalibration use Apache Spark for parallelization. By default bcbio runs these with multicore parallelization on a single node, to fit in standard cluster and local compute environments. If you have a custom Spark cluster on your system you can use that for GATK by setting up the appropriate configuration in your `Sample or run specific resources`: ```yaml resources: gatk-spark: options: [--spark-master, 'spark://your-spark-cluster:6311'] ``` ## Profiling Profiling (tracking CPU, memory, IO usage) could help to optimize resource usage of bcbio, especially when running on a server or AWS instance. Sometimes running a bcbio project with 32 cores is just 10% more efficient than with 16 cores, because a particular configuration might have memory or IO related bottlenecks. IO bottlenecks are when you see low CPU utilization and high read/write values. 1. [Install and start sysstat deamon](http://www.leonardoborda.com/blog/how-to-configure-sysstatsar-on-ubuntudebian/). 1. Create a cron job to gather system statistics every minute or two. 1. Before bcbio start, drop system memory caches. Otherwise memory usage statistic might be misleading: ```shell # become root sudo su echo 1 > /proc/sys/vm/drop_caches ``` 1. Record bcbio project start and stop time (_date_) 1. Collect usage statistics: ```shell # CPU load sar -q -s $start -e $end | awk '{print $1","$4}' | sed 1d | sed 1d > cpu.csv # memory sar -r -s $start -e $end | awk '{print $5}' | sed 1d | sed 1d > mem.csv # IO sar -b -s $start -e $end | awk '{print $5","$6}' | sed 1d | sed 1d > io.csv paste -d "," cpu.csv mem.csv io.csv > usage.csv ``` ``` # Example of usage.csv 23:07:01,ldavg-1,%memused,bread/s,bwrtn/s 23:08:01,1.77,3.10,23238.66,20204.10 23:09:01,4.34,24.28,208650.45,26270.58 23:10:01,11.09,25.67,0.13,15.46 23:11:01,13.56,27.00,4.27,21.99 23:12:01,15.44,29.63,26.52,2749.22 23:13:01,15.16,29.75,42.93,27.06 23:14:01,16.94,30.54,205.26,2740.95 23:15:01,15.76,30.57,28.92,2751.62 23:16:01,15.77,30.88,6.13,33.59 ``` See [sar man page](https://linux.die.net/man/1/sar) for more fields and field definitions. 1. Overlap profiling results with bcbio-nextgen-commands.log to investigate the performance of particular steps. bcbio-nextgen-1.2.9/docs/contents/presentations.md000066400000000000000000000340401415626112400222570ustar00rootroot00000000000000# Presentations * Variant calling and bcbio training for the [Harvard Chan Bioinformatics Core In Depth NGS Data Analysis Course](https://hbctraining.github.io/In-depth-NGS-Data-Analysis-Course/) (10 October 2018): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/ngscourse2018_teaching/ngscourse2018_teaching.pdf) * Building a diverse set of validations; lightning talk at [the GCCBOSC2018 Bioinformatics Community Conference](https://gccbosc2018.sched.com/): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/bosc2018_bcbio_validate/chapman_bcbio_validate.pdf) * bcbio training at [the GCCBOSC2018 Bioinformatics Community Conference](https://gccbosc2018.sched.com/), focusing on bcbio CWL integration with examples of variant calling analyses on Personal Genome Project examples (26 June 2018): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/bosc2018_bcbio_training/bosc2018_bcbio_training.pdf); [video](https://www.youtube.com/watch?v=ukWhAetvNKE) * Description of bcbio and Common Workflow integration with a focus on parallelization strategies. From a bcbio discussion with [Peter Park's lab at Harvard Medical School](https://compbio.hms.harvard.edu/index) (26 January 2018): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/park2018_bcbio/park2018_bcbio.pdf) * In depth description of bcbio and Common Workflow Language integration, including motivation and practical examples of running on clusters, DNAnexus, SevenBridges and Arvados. From the [Boston Bioinformatics Interest Group meeting](https://gist.github.com/chapmanb/8ee026fd85d07518570ac5a0cd7239f5) (2 November 2017): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/big2017_bcbio_cwl/big2017_bcbio_cwl.pdf); [video](https://youtu.be/nJEDS9Qol8M) * bcbio practical interoperability with the Common Workflow Language at [BOSC 2017](https://www.open-bio.org/wiki/BOSC_2017) (22 July 2017): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/bosc2017_bcbio_interoperate/chapmanb_bcbio_interoperate.pdf); [video](https://youtu.be/S7bu17GQHqk) * [Teaching](contents/teaching:teaching) variant calling, bcbio and GATK4 validation at the [Summer 2017 NGS Data Analysis Course at Harvard Chan School](https://bioinformatics.sph.harvard.edu/training/) (6 July 2017): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/ngscourse2017_teaching/ngscourse2017_teaching.pdf) * Training course for the [Cancer Genomics Cloud](https://www.cancergenomicscloud.org/), describing how bcbio uses the Common Workflow Language to run in multiple infrastructures (1 May 2017): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/cgc2017_bcbio_cwl/cgc2017_bcbiocwl.pdf) * [MIT Bioinformatics Interest Group](https://openwetware.org/wiki/BioMicroCenter:BIG_meeting#2016-2017_academic_year) about how Common Workflow Language [enables interoperability with multiple workflow engines](https://gist.github.com/chapmanb/f1ccdd2e2e23b0383b6e6857b59a431b) (3 November 2016): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/big2016_bcbio_cwl/big2016_bcbiocwl.pdf) and [video](https://youtu.be/375QSYmaidk) * [Broad Institute](https://www.broadinstitute.org/) software engineering seminar about bcbio validation and integration with Common Workflow Language and Workflow Definition Language (28 September 2016): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/broad_engineering2016_bcbio/broad2016_bcbio.pdf) * Materials from [teaching](contents/teaching:teaching) at the [Summer 2016 NGS Data Analysis Course at Harvard Chan School](https://bioinformatics.sph.harvard.edu/training/) (11 August 2016): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/ngscourse2016b_teaching/ngscourse2016b_teaching.pdf) * [Bioinformatics Open Source Conference (BOSC) 2016](https://www.open-bio.org/wiki/BOSC_2016) lightning talk on bcbio and common workflow language (8 July 2016): [slides](https://f1000research.com/slides/5-1639) and [video](https://youtu.be/kMoAWjHhOVc). * Materials from [teaching](contents/teaching:teaching) from the [Spring 2016 NGS Data Analysis Course at Harvard Chan School](https://wiki.harvard.edu/confluence/display/hbctraining/NGS+Data+Analysis+Course+Application%2C+Spring+2016) (28 April 2016): [slides](https://github.com/chapmanb/bcbb/raw/master/talks/ngscourse2016_teaching/ngscourse2016_teaching.pdf) * Statistical Genetics and Network Science Meeting at [Channing Division of Network Medicine](https://www.brighamandwomens.org/research/departments/channing-division-of-network-medicine/overview) (23 March 2016): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/cdnm2016_bcbio/cdnm2016_bcbio.pdf) * Presentation at Curoverse Brown Bag Seminar on bcbio and in progress integration work with [Common Workflow Language](https://www.commonwl.org/) and [Arvados](https://arvados.org/) (11 January 2016): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/curoverse2016bb_bcbio/curoverse2016bb_bcbio.pdf) * Materials from [teaching](contents/teaching:teaching) oriented example at Cold Spring Harbor Laboratory's [Advanced Sequencing Technology and Applications course](https://meetings.cshl.edu/courses.aspx?course=C-SEQTEC&year=15). (18 November 2015): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/cshl2015_bcbio/cshl2015_bcbio.pdf) * Supporting the common workflow language and Docker in bcbio Bio in Docker symposium (9 November 2015): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/bioindocker2015_bcbio/chapman_bioindocker.pdf) * Validation on human build 38, HLA typing, low frequency cancer calling and structural variation for [Boston Bioinformatics Interest Group (BIG) meeting](https://openwetware.org/wiki/BioMicroCenter:BIG_meeting) (5 November 2015): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/big2015_bcbio/big2015_bcbio.pdf) * Presentation on Research Scientist Careers for [Iowa State Bioinformatics Course](https://bcbio.las.iastate.edu/) (23 September 2015): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/2015_iowast_career/chapman_career.pdf) * Prioritization of structural variants based on known biological information at [BOSC 2015](https://www.open-bio.org/wiki/BOSC_2015) (10 July 2015): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/bosc2015_bcbio_prioritize/bosc2015_bcbio_prioritize.pdf); [video](https://www.youtube.com/watch?v=JZnF_6UnajY&feature=youtu.be) * Overview of variant calling for [NGS Data Analysis Course at Harvard Medical School](https://wiki.harvard.edu/confluence/display/hbctraining/NGS+Data+Analysis+Course+Application%2C+Spring+2015) (19 May 2015): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/ngscourse2015_teaching/variant_ngscourse.pdf) * [NGS Glasgow](https://biotexcel.com/event/ngs-2015-glasgow/) (23 April 2015) * [Boston Computational Biology and Bioinformatics meetup](https://www.meetup.com/Boston-Computational-Biology-and-Bioinformatics-Meetup/events/220328870/) (1 April 2015): [slides](https://github.com/chapmanb/bcbb/blob/master/talks/bcbb2015_bcbio/chapman_bcbio.pdf) * [Program in Genetic Epidemiology and Statistical Genetics seminar series](https://www.hsph.harvard.edu/program-molecular-genetic-epidemiology/journal-club/) at Harvard Chan School (6 February 2015): [slides](https://github.com/chapmanb/bcbb/raw/master/talks/pgsg2015_bcbio/chapman_bcbio.pdf) * Talk at Good Start Genetics (23 January 2015): [slides](https://github.com/chapmanb/bcbb/raw/master/talks/gsg2015_bcbio_nextgen/chapman_bcbio.pdf) * Boston area [Bioinformatics Interest Group](https://openwetware.org/wiki/BioMicroCenter:BIG_meeting) (15 October 2014): [slides](https://github.com/chapmanb/bcbb/raw/master/talks/big2014_bcbio_val/chapman_bcbio.pdf) * University of Georgia [Institute of Bioinformatics](https://iob.uga.edu/) (12 September 2014): [slides](https://github.com/chapmanb/bcbb/raw/master/talks/uga2014_bcbio_open/chapman_bcbio.pdf) * Intel Life Sciences discussion (7 August 2014): [slides](https://github.com/chapmanb/bcbb/raw/master/talks/intel2014_bcbio/chapman_bcbio.pdf) * Bioinformatics Open Source Conference (BOSC) 2014: [slides](https://github.com/chapmanb/bcbb/raw/master/talks/bosc2014_bcbio/chapman_bcbio.pdf), [conference website](https://www.open-bio.org/wiki/BOSC_2014) * Galaxy Community Conference 2014: [slides](https://github.com/chapmanb/bcbb/raw/master/talks/gcc2014_bcbio/chapman_bcbio.pdf), [conference website](https://wiki.galaxyproject.org/Events/GCC2014) * [bcbio hackathon at Biogen](https://github.com/chapmanb/bcbb/raw/master/talks/biogen2014_bcbio_nextgen/chapman_bcbio.pdf) (3 June 2014) * [Harvard ABCD group slides](https://github.com/chapmanb/bcbb/raw/master/talks/abcd2014_bcbio_nextgen/chapman_bcbio.pdf) (17 April 2014) * [BIG meeting](https://github.com/roryk/spliced-blog/blob/master/talks/BIG-meeting-feb-2014.pdf) (February 2014) * [Novartis slides](https://github.com/chapmanb/bcbb/raw/master/talks/novartis2014_bcbio_nextgen/chapman_bcbio.pdf) (21 January 2014) * Mt Sinai: Strategies for accelerating the genomic sequencing pipeline: [Mt Sinai workshop slides](https://github.com/chapmanb/bcbb/raw/master/talks/mtsinai2013_bcbio_nextgen/chapman_mtsinai_bcbio.pdf), [Mt Sinai workshop website](https://www.hpcwire.com/event/strategies-accelerating-genomic-sequencing-pipeline/) * Genome Informatics 2013 * Bioinformatics Open Source Conference 2013: [BOSC 2013 Slides](https://chapmanb.github.io/bcbb/talks/bosc2013_bcbio_nextgen/chapmanb_bosc2013_bcbio.html#/), [BOSC 2013 Video](https://www.youtube.com/watch?v=dT5UEU0xF1Q), [BOSC 2013 Conference website](https://www.open-bio.org/wiki/BOSC_2013) * Arvados Summit 2013: [Arvados Summit Slides](https://github.com/chapmanb/bcbb/raw/master/talks/arvados2013_bcbio_nextgen/chapman_arvadossum_bcbio.pdf), [Arvados Summit website](https://dev.arvados.org/projects/arvados/wiki/Arvados_Summit_-_Fall_2013) * Scientific Python 2013: [SciPy 2013 Video](https://www.youtube.com/watch?v=qNMPh0pIpBE), [SciPy 2013 Conference website](https://conference.scipy.org/scipy2013/) Feel free to reuse any images or text from these talks. The [slides are on GitHub](https://github.com/chapmanb/bcbb/tree/master/talks). ## Abstract __Community Development of Validated Variant Calling Pipelines__ *Brad Chapman, Rory Kirchner, Oliver Hofmann and Winston Hide Harvard School of Public Health, Bioinformatics Core, Boston, MA, 02115* Translational research relies on accurate identification of genomic variants. However, rapidly changing best practice approaches in alignment and variant calling, coupled with large data sizes, make it a challenge to create reliable and reproducible variant calls. Coordinated community development can help overcome these challenges by sharing testing and updates across multiple groups. We describe bcbio-nextgen, a distributed multi-architecture pipeline that automates variant calling, validation and organization of results for query and visualization. It creates an easily installable, reliable infrastructure from best-practice open source tools with the following goals: * __Quantifiable:__ Validates variant calls against known reference materials developed by the [Genome in a Bottle](https://www.nist.gov/programs-projects/genome-bottle) consortium. The [bcbio.variation](https://github.com/chapmanb/bcbio.variation) toolkit automates scoring and assessment of calls to identify regressions in variant identification as calling pipelines evolve. Incorporation of multiple variant calling approaches from [Broad's GATK best practices](https://gatkforums.broadinstitute.org/gatk/discussion/1186/best-practice-variant-detection-with-the-gatk-v4-for-release-2-0) and the [Marth lab's gkno software](https://github.com/gkno/gkno_launcher) enables informed comparisons between current and future algorithms. * __Scalable:__ bcbio-nextgen handles large population studies with hundreds of whole genome samples by parallelizing on a wide variety of schedulers and multicore machines, setting up different ad hoc cluster configurations for each workflow step. Work in progress includes integration with virtual environments, including [Amazon Web Services](https://aws.amazon.com/) and [OpenStack](https://www.openstack.org/). * __Accessible:__ Results automatically feed into tools for query and investigation of variants. The [GEMINI framework](https://github.com/arq5x/gemini#readme) provides a queryable database associating variants with a wide variety of genome annotations. The [o8](https://github.com/chapmanb/o8#readme) web-based tool visualizes the work of variant prioritization and assessment. * __Community developed:__ bcbio-nextgen is widely used in multiple sequencing centers and research laboratories. We actively encourage contributors to the code base and make it easy to get started with a fully automated installer and updater that prepares all third party software and reference genomes. ## Links from the presentation * [HugeSeq](https://github.com/StanfordBioinformatics/HugeSeq) * [Genome Comparison & Analytic Testing](https://www.mybiosoftware.com/gcat-genome-comparison-and-analytic-testing-platform.html) at Bioplanet * [Peter Block's "Community" book](https://www.amazon.com/dp/1605092770) * [CloudBioLinux](https://cloudbiolinux.org/) and [Homebrew Science](https://github.com/Homebrew/homebrew-science) as installation frameworks; [Conda](https://docs.conda.io/en/latest/) as Python environment * [bcbio documentation at Read the Docs](https://bcbio-nextgen.readthedocs.io/en/latest/) * [Arvados framework](https://arvados.org/) for meta data tracking, NGS processing and data provenance * Notes on [improved scaling for NGS workflows](https://bcb.io/2013/05/22/scaling-variant-detection-pipelines-for-whole-genome-sequencing-analysis/) * Genomic Reference Materials from [Genome in a Bottle](https://www.nist.gov/programs-projects/genome-bottle) * Comparison of [aligners and callers](https://bcb.io/2013/05/06/framework-for-evaluating-variant-detection-methods-comparison-of-aligners-and-callers/) using NIST reference materials * Callers and [minimal BAM preparation workflows](https://bcb.io/2013/10/21/updated-comparison-of-variant-detection-methods-ensemble-freebayes-and-minimal-bam-preparation-pipelines/) * [Coverage assessment](https://github.com/chapmanb/bcbio.coverage) bcbio-nextgen-1.2.9/docs/contents/purecn.md000066400000000000000000000205341415626112400206600ustar00rootroot00000000000000# PureCN analysis of tumor-only samples PureCN by [Markus Riester](https://github.com/lima1/) is a reliable tool to estimate purity and ploidy in cancer samples sequenced with high coverage gene panels and exomes. It also provides segmentation, gene-level copy numbers, LOH, and classification of variants. The important aspect of running PureCN is a requirement to have process matched normals (as opposed to matched T/N). ## Normal DB (panel of normals) This step could be performed one time for every panel/cohort, and then a PON could be re-used to analyze many samples. ### 1. Create purecn_pon_template.yaml: ```yaml details: - analysis: variant2 genome_build: hg38 algorithm: aligner: false svcaller: purecn sv_regions: /path/to/panel.bed variantcaller: mutect2 ``` You can download the template to modify: ```bash wget -O purecn_pon_template.yaml https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/templates/purecn_pon.yaml ``` *If you are using bam files as input (aligner: false) make sure that bai indices are located in the same dir as input bam files. Bcbio generates indices on the fly, but PureCN follows a symlink to the original bam file and if there is no index, it crashes.* For better capture of the coverage panel.bed (or exome.bed) could be padded. To output gene-level CNA, gene names must be present in the bed file (4th column). If there are no gene names in the bed provided by the manufacturer: - generate a genes.bed file with gene names: https://github.com/naumenko-sa/bioscripts/blob/master/gene_panels/genes.R#L721 - annotate panel.no_names.bed with gene names: ```bash sort-bed genes.unsorted.bed > genes.sort-bed.bed bedmap \ --echo \ --echo-map-id \ --fraction-ref 1 \ panel.no_names.bed \ genes.sort-bed.bed | sed s/"|"/"\t"/ > panel.bed ``` Then expand and merge the intervals ```bash cat panel.bed | awk '{print $1"\t"$2-100"\t"$3+100"\t"$4}' > panel.padded100bp.bed bedtools merge -i panel.padded100bp.bed -c 4 -o distinct > panel.padded100bp.merged.bed ``` ### 2. Create a sample sheet pon.csv: You need a minimum of 3 samples for a PON. See the discussion about the number of sample in PureCN documentation. The optimal number could be 30 samples (the more the better). PureCN chooses which samples to include in the PON when provided many samples. `batch=pon_build` switches PON mode (which includes creating SNV PON with mutect2 matching PureCN requirements and PureCN Normal db). ``` samplename,description,batch,phenotype sample1__N_FFPE,sample1__N_FFPE,pon_build,normal sample2__N_FFPE,sample2__N_FFPE,pon_build,normal sample3__N_FFPE,sample3__N_FFPE,pon_build,normal ``` ### 3. Create bcbio project structure and a bcbio config pon.yaml: ```bash $ ls # place sample sheet and template in the current dir purecn_pon_template.yaml pon.csv # create bcbio project structure $ mkdir -p pon/input pon/config # copy or symlink bam or fastq files to pon/input $ ls pon/input sample1__N_FFPE.bam sample2__N_FFPE.bam sample3__N_FFPE.bam # create pon.yaml $ bcbio_nextgen.py -w template purecn_pon_template.yaml pon.csv pon/input/*.bam # run bcbio (or create a batch script for you job submission system) $ cd pon/work $ bcbio_nextgen.py ../config/pon.yaml -n 20 ``` ### 4. Collect and save Normal DB and SNV PON Upon successfull bcbio run you may find resulting files in `pon/final/[date]_pon` ```bash $ ls -1 pon/final/*_pon mapping_bias_hg38.rds normalDB_hg38.rds # SNV panel of normals pon_build-mutect2-annotated.vcf.gz pon_build-mutect2-annotated.vcf.gz.tbi ``` Also, in the folders of individual samples you may find purecn coverage files: ```bash $ ls -1 pon/final/sample1__N_FFPE/purecn ``` ## Tumor-only analysis ### 1. Create project structure ```bash mkdir -p ton/config ton/input # copy/link PON files: cp panel.bed pon_build-mutect2-annotated.vcf.gz normalDB_hg38.rds mapping_bias_hg38.rds ton/config # copy, move or symlink input files for tumor samples mv sample1_T_FFPE.bam sample2_T_FFPE ton/input/ ``` ### 2. Create purecn_ton_template.yaml: ```bash wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/templates/purecn_ton.yaml ``` ```yaml details: - analysis: variant2 genome_build: hg38 algorithm: aligner: false svcaller: purecn sv_regions: /path/ton/config/panel.bed variantcaller: mutect2 background: variant: /path/ton/config/pon_build-mutect2-annotated.vcf.gz cnv_reference: purecn_normaldb: /path/ton/config/normalDB_hg38.rds purecn_mapping_bias: /path/ton/config/mapping_bias_hg38.rds metadata: phenotype: tumor ``` ### 3. Create a sample sheet ton.csv: ``` samplename,description,batch,phenotype sample1_T_FFPE,sample1_T_FFPE,sample1_T_FFPE-batch,tumor sample2_T_FFPE,sample2_T_FFPE,sample2_T_FFPE-batch,tumor sample3_T_FFPE,sample3_T_FFPE,sample3_T_FFPE-batch,tumor sample4_T_FFPE,sample4_T_FFPE,sample4_T_FFPE-batch,tumor sample5_T_FFPE,sample5_T_FFPE,sample5_T_FFPE-batch,tumor sample6_T_FFPE,sample6_T_FFPE,sample6_T_FFPE-batch,tumor sample7_T_FFPE,sample7_T_FFPE,sample7_T_FFPE-batch,tumor sample8_T_FFPE,sample8_T_FFPE,sample8_T_FFPE-batch,tumor ``` ### 4. Create ton.yaml: ```bash $ ls -1 ton purecn_ton_template.yaml ton.csv $ bcbio_nextgen.py -w template purecn_ton_template.yaml ton/input/*.bam ``` ### 5. Run bcbio ```bash $ cd ton/work $ bcbio_nextgen.py ../config/ton.yaml -n 20 ``` ### 6. Collect PureCN results Upon successfull bcbio run PureCN results are saved in the folders of individual samples ``` $ ls -1 ton/final/sample1_T_FFPE/purecn sample1_T_FFPE_amplification_pvalues.csv sample1_T_FFPE_chromosomes.pdf sample1_T_FFPE.csv sample1_T_FFPE_dnacopy.seg sample1_T_FFPE_genes.csv sample1_T_FFPE_local_optima.pdf sample1_T_FFPE.log sample1_T_FFPE_loh.csv sample1_T_FFPE.pdf sample1_T_FFPE.rds sample1_T_FFPE-ready_coverage_loess.png sample1_T_FFPE-ready_coverage_loess_qc.txt sample1_T_FFPE-ready_coverage_loess.txt.gz sample1_T_FFPE-ready_coverage.txt.gz sample1_T_FFPE_segmentation.pdf sample1_T_FFPE_variants.csv ``` ## T/N analysis It is possible to run this analysis with T/N pairs (with PON and normal DB), but the main recommended mode is tumor-only. For T/N analysis use purecn_ton_template.yaml (with Normal db and SNV PON) and create a sample sheet similar to: ``` samplename,description,batch,phenotype sample1_N_FFPE,sample1_N_FFPE,sample1_T_FFPE-batch,normal sample1_T_FFPE,sample1_T_FFPE,sample1_T_FFPE-batch,tumor ``` PureCN results will be copied to the folder of the tumor sample in the final dir. ## Troubleshooting We found useful to adjust memory parameters when running large cohorts with ipython (149 samples): [see issue 3230](https://github.com/bcbio/bcbio-nextgen/issues/3230). To detect deletions in cfDNA samples we found useful to set PureCN parameters in the yaml: ```yaml resources: purecn: options: ["--funsegmentation", "PSCBS", "--minpurity", "0.1", "--minaf", "0.01", "--error", "0.0005"] ``` A patched implementation of PSCBS works better than the default, to install the patched version in bcbio: ```bash # run R from the base conda environment: /path/to/bcbio/anaconda/bin/R # install patched PSCBS: BiocManager::install("lima1/PSCBS", ref="add_dnacopy_weighting") ``` Capturing more SNP markers is also useful for PureCN analysis, the input bed file for the panel or exome capture kit is usually 100 bp padded on both sides of the probe (it is not padded by bcbio). In addition to that the mutect2 step uses 50bp interval_padding [option](https://github.com/bcbio/bcbio-nextgen/blob/master/bcbio/variation/mutect2.py#L126). The interval padding could be adjusted with: ```yaml resources: mutect2: options: ["interval_padding", "100"] ``` To update PureCN to the latest development: launch `bcbio/anaconda/bin/R`, run `BiocManager::install("lima1/PureCN")` PureCN 2.0.1 fails when the offarget coverage is low (happens to some older WES data), see this [discussion](https://github.com/lima1/PureCN/issues/209). To solve, use: ```yaml details: - algorithm: tools_off: - purecn_offtarget ``` The fault mode is with `--offtarget` assuming that the default use case is panel data. ## References - [PureCN publication](https://scfbm.biomedcentral.com/articles/10.1186/s13029-016-0060-z) - [PureCN github](https://github.com/lima1/PureCN) - [PureCN in Bioconductor](https://bioconductor.org/packages/release/bioc/html/PureCN.html) - [PureCN validation](https://ascopubs.org/doi/full/10.1200/CCI.19.00130) bcbio-nextgen-1.2.9/docs/contents/rnaseq_fusions.md000066400000000000000000000020201415626112400224110ustar00rootroot00000000000000# Detecting gene fusions with bulk RNA-seq data - `fusion_caller` - Specify a standalone fusion caller for fusion mode. Supports oncofuse for STAR/tophat runs, pizzly and ericscript for all runs. If a standalone caller is specified (i.e. pizzly or ericscript ), fusion detection will not be performed with aligner. oncofuse only supports human genome builds GRCh37 and hg19. ericscript supports human genome builds GRCh37, hg19 and hg38 after installing the associated fusion databases (Customizing data installation). - `known_fusions` A TAB-delimited file of the format gene1gene2, where gene1 and gene2 are identifiers of genes specified under gene_name in the attributes part of the GTF file. [Example config](https://github.com/bcbio/bcbio-nextgen/blob/master/config/templates/illumina-rnaseq.yaml) Validation: [article](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6802306/) * [code](https://github.com/fusiontranscripts/FusionBenchmarking) * [data](https://data.broadinstitute.org/Trinity/CTAT_FUSIONTRANS_BENCHMARKING/) bcbio-nextgen-1.2.9/docs/contents/rnaseq_variants.md000066400000000000000000000210071415626112400225600ustar00rootroot00000000000000# Variant calling using bulk RNA-seq data **2020-05-12: works for validation samples, fails for some random samples due to pybedtools [issue](https://github.com/bcbio/bcbio-nextgen/issues/3078).** To avoid HaplotypeCallerSpark issue, update to the latest development version. ## Workflow This workflow demonstrates how to call variants with GATK3.8 using bulk RNA-seq data of GM12878 cell line (blood). At least 3 RNA-seq datasets exist for NA12878: - `SRR307897` is of bad quality - don't use it; - [SRR307898](https://www.ncbi.nlm.nih.gov/sra/?term=SRR307898) is a bit old (Illumina GAII) but it was used in [Piskol2013](https://www.ncbi.nlm.nih.gov/pubmed/24075185) article, which is reliable work on RNA-seq variant calling validation; - [SRR5665260](https://www.ncbi.nlm.nih.gov/sra/?term=SRR5665260), NextSeq-500. GATK3.8 requires additional installation [step](https://bcbio-nextgen.readthedocs.io/en/latest/contents/installation.html#gatk-and-mutect-mutect2). ### 1. Project structure ``` mkdir NA12878_RNA-seq_validation cd NA12878_RNA-seq_validation mkdir config input final work ``` ### 2. Download input data (~6G total) ``` cd input wget -c -O NA12878_1.fq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR307/SRR307898/SRR307898_1.fastq.gz wget -c -O NA12878_2.fq.gz ftp://ftp.sra.ebi.ac.uk/vol1/fastq/SRR307/SRR307898/SRR307898_2.fastq.gz ``` or (if ebi is not online) ``` wget https://sra-downloadb.be-md.ncbi.nlm.nih.gov/sos1/sra-pub-run-1/SRR307898/SRR307898.3 fastq-dump --gzip --split-files SRR307898.3 ``` ### 3. Config file `input/NA12878.yaml` Note the use of `batch` even for a single sample. ``` details: - algorithm: aligner: star strandedness: unstranded variantcaller: gatk-haplotype jointcaller: gatk-haplotype-joint tools_off: - gatk4 analysis: RNA-seq description: NA12878_SRR307898 files: - /path/NA12878/input/NA12878_SRR307898_1.fq.gz - /path/NA12878/input/NA12878_SRR307898_2.fq.gz genome_build: hg38 metadata: batch: NA12878 fc_name: NA12878 resources: default: cores: 4 jvm_opts: - -Xms750m - -Xmx7000m memory: 15G upload: dir: ../final ``` ### 4. Run bcbio - assuming 60G/4cores machine or cluster node. ``` cd work bcbio_nextgen.py ../config/NA12878.yaml -n 4 ``` ## Parameters - `variantcaller`: gatk-haplotype or vardict. You can use just one variant caller for RNA-seq data in a bcbio project. If you want calls from two callers, run a separate project or edit variantcaller parameter and re-run. - `tools_off: [gatk4]`: when set, runs gatk3.8, which gives better precision. - `batch` is required: ``` metadata: batch: NA12878 ``` ## Validation ### How to validate calls from bcbio Use high quality variants (PASS filters, depth>=10 reads), remove potential RNA editing events. ``` bcftools view -f PASS -e "INFO/DP<10 | INFO/possible_rnaedit==1" NA12878-gatk-haplotype-annotated.vcf.gz | bgzip -c > NA12878.pass.vcf.gz tabix NA12878.pass.vcf.gz wget https://raw.githubusercontent.com/naumenko-sa/cre/master/data/intersect.hg38.bed wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878.validate.sh NA12878.validate.sh \ NA12878.pass.vcf.gz \ /path/bcbio/genomes/Hsapiens/hg38/validation/giab-NA12878/truth_small_variants.vcf.gz \ intersect.hg38.bed \ /path/bcbio/genomes/Hsapiens/hg38/rtg/hg38.sdf ``` Results will be in NA12878.pass.vcf.gz.stat: ``` snp tp-baseline 5720 indels tp-baseline 184 snp fp 1205 indels fp 2141 snp fn 29323 indels fn 2455 ``` ### Validation results, 2016-2019, GRCh37, SRR307898 ```eval_rst +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |date |type |bcbio|gatk |TP |FP |FN |FDR|FNR|Target|Total called| +==========+=====+=====+=======+=====+======+======+===+===+======+============+ |2016-12-08|SNP |1.0.0|3.6 |7,892|266 |30,851|3% |80%|38,743|8,158 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2016-12-08|INDEL|1.0.0|3.6 |256 |117 |2,788 |31%|92%|3,044 |373 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2018-06-06|SNP |1.0.9|4.0.1.2|6,817|2,575 |31,926|27%|82%|38,743|9,392 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2018-06-06|INDEL|1.0.9|4.0.1.2|228 |24,448|2,816 |99%|93%|3,044 |24,676 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2018-06-14|SNP |1.0.9|3.8 |7,936|315 |30,807|4% |80%|38,743|8,251 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2018-06-14|INDEL|1.0.9|3.8 |306 |280 |2,738 |48%|90%|3,044 |586 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2019-03-01|SNP |1.1.3|4.1.0.0|6,380|842 |32,363|12%|84%|38,743|7,222 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2019-03-01|INDEL|1.1.3|4.1.0.0|374 |3,131 |2,670 |89%|88%|3,044 |3,505 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2019-03-01|SNP |1.1.3|3.8 |6,244|558 |32,499|8% |84%|38,743|6,802 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ |2019-03-01|INDEL|1.1.3|3.8 |192 |1,951 |2,852 |91%|94%|3,044 |2,143 | +----------+-----+-----+-------+-----+------+------+---+---+------+------------+ ``` ### Validation results, 2020, hg38 ```eval_rst +----------+---------+-----+-----+------------------+-----+-----+------+---+---+------+------------+ |date |data |type |bcbio|caller |TP |FP |FN |FDR|FNR|Target|Total called| +==========+=========+=====+=====+==================+=====+=====+======+===+===+======+============+ |2020-05-12|SRR307898|SNP |1.2.3|gatk,4.1.6.0 |5,849|1,570|29,194|21%|83%|35,043|7,419 | +----------+---------+-----+-----+------------------+-----+-----+------+---+---+------+------------+ |2020-05-12|SRR307898|INDEL|1.2.3|gatk,4.1.6.0 |181 |2907 |2458 |94%|93%|2,639 |3,088 | +----------+---------+-----+-----+------------------+-----+-----+------+---+---+------+------------+ |2020-05-12|SRR307898|SNP |1.2.3|vardict-java,1.7.0|6,333|916 |28,710|13%|82%|35,043|7,249 | +----------+---------+-----+-----+------------------+-----+-----+------+---+---+------+------------+ |2020-05-12|SRR307898|INDEL|1.2.3|vardict-java,1.7.0|166 |580 |2,473 |78%|94%|2,639 |746 | +----------+---------+-----+-----+------------------+-----+-----+------+---+---+------+------------+ |2020-05-13|SRR307898|SNP |1.2.3|gatk3.8-1.0 |5720 |1205 |29,323|17%|83%|35043 |6925 | +----------+---------+-----+-----+------------------+-----+-----+------+---+---+------+------------+ |2020-05-13|SRR307898|INDEL|1.2.3|gatk3.8-1.0 |184 |2,141|2,455 |92%|93%|2,639 |2325 | +----------+---------+-----+-----+------------------+-----+-----+------+---+---+------+------------+ ``` ## Conclusions - It is not surprising to see high False Negative rate FN = FN/(FN+TP) in RNA-seq variant calling, i.e. that we are not calling 83% of variants. We validate against intersect.hg38.bed, which is based on exome capture regions and is representing all protein coding genes. Only a minor fraction of genes are expressed in blood, only these genes have read coverage that makes variant calling possible. - Indel calling is not reliable with RNA-seq data. - Current recommendation is to use gatk3.8 > vardict > gatk4 for better SNP calling precision in bcbio. - Annotation of RNA-editing sites and removal of variants around splice junctions improved precision in bcbio, but still more work is needed to achieve better precision at the level of Piskol2013 (<1% FDR). ## TODO - update gatk3.8 validation - validate with SRR5665260 - integrate validation into bcbio - improve post GATK4 filters for better precision - paired DNA/RNA-seq variant calling - somatic variant calling with RNA-seq, see [discusion](https://github.com/bcbio/bcbio-nextgen/issues/3023) - track pybedtools [release](https://github.com/bcbio/bcbio-nextgen/issues/3078). ## References - [Piskol2013](https://www.ncbi.nlm.nih.gov/pubmed/24075185) - [GATK best practices for RNA-seq data variant calling](https://gatk.broadinstitute.org/hc/en-us/articles/360035531192-RNAseq-short-variant-discovery-SNPs-Indels-) - [Variant calling and validation from Brian Haas using CTAT and SRR5665260](https://github.com/NCIP/ctat-mutations/wiki/Performance-Assessment) - [RTG vcfeval](https://cdn.rawgit.com/RealTimeGenomics/rtg-tools/master/installer/resources/tools/RTGOperationsManual/rtg_command_reference.html#vcfeval) bcbio-nextgen-1.2.9/docs/contents/single_cell.md000066400000000000000000000404031415626112400216410ustar00rootroot00000000000000# Counting cells and transcripts for inDrops3 data ## Workflow Bcbio installation paths in this workflow correspond to [O2 bcbio installation](https://wiki.rc.hms.harvard.edu/display/O2). Adjust to bcbio installation you are working with. ### 1. Check reference genome and transcriptome mouse project: - mm10 reference genome: /n/shared_db/bcbio/biodata/genomes/Mmusculus/mm10 - transcriptome_fasta: /n/shared_db/bcbio/biodata/genomes/Mmusculus/mm10/rnaseq/ref-transcripts.fa - transcriptome_gtf: /n/shared_db/bcbio/biodata/genomes/Mmusculus/mm10/rnaseq/ref-transcripts.gtf human project: - hg38 reference genome: /n/shared_db/bcbio/biodata/genomes/Hsapiens/hg38 - transcriptome_fasta: /n/shared_db/bcbio/biodata/genomes/Hsapiens/hg38/rnaseq/ref-transcripts.fa - transcriptome_gtf: /n/shared_db/bcbio/biodata/genomes/Hsapiens/hg38/rnaseq/ref-transcripts.gtf Those are *spliced* references. To prepare the unspliced reference, use: ```bash #!/bin/bash $1 = ref-transcripts.gtf bname=`basename $1 .gtf` awk 'BEGIN{FS="\t"; OFS="\t"} $3 == "transcript"{ $3="exon"; print}' $1 > $bname.premrna.gtf gffread -g /path/to/genome_reference/genome.fa $bname.premrna.gtf -w $bname.unspliced.fa ``` In some datasets using the unspliced reference allows to yield 1.5X more counts. ### 2. Create bcbio project structure in /scratch ``` mkdir sc_mouse cd sc_mouse mkdir config input final work ``` ### 3. Prepare fastq input in sc_mouse/input - if data comes in >1 lanes, merge lanes for every read: ``` cat lane1_r1.fq.gz lane2_r1.fq.gz > project_1.fq.gz cat lane1_r2.fq.gz lane2_r2.fq.gz > project_2.fq.gz ``` - some sequencing cores send bz2 files not gz ``` bunzip2 *.bz2 cat *R1.fastq | gzip > sample_1.fq.gz ``` - some cores produce R1,R2,R3,R4, others R1,R2,I1,I2, rename files ``` bcbio_R1 = R1 = 100 or 86 or 64 bp transcript read bcbio_R2 = I1 = 8 bp part 1 of cell barcode bcbio_R3 = I2 = 8 bp sample (library) barcode bcbio_R4 = R2 = 14 bp = 8 bp part 2 of cell barcode + 6 bp of transcript UMI ``` *Some 100 bp R1 libraries yield low count numbers, and trimming them to 61 bp improves counting*: ```bash #!/bin/bash # $1 = sample_1.fq.gz java -jar /path/to/Trimmomatic-0.39/trimmomatic-0.39.jar SE \ -threads 10 \ -phred33 \ $1 \ $1.trimmed.fq.gz \ CROP:61 ``` - files in sc_mouse/input should be (KM here is a project name): ``` KM_1.fq.gz KM_2.fq.gz KM_3.fq.gz KM_4.fq.gz ``` ### 4. Specify sample barcodes Sample barcodes should be in *sc_mouse/config/sample_barcodes.csv*. Check out if the sample barcodes provided match the actual barcodes in the data. ```shell gunzip -c FC_X_3.fq.gz | awk '{if(NR%4 == 2) print $0}' | head -n 400000 | sort | uniq -c | sort -k1,1rn | awk '{print $2","$1}' | head AGGCTTAG,112303 ATTAGACG,95212 TACTCCTT,94906 CGGAGAGA,62461 CGGAGATA,1116 CGGATAGA,944 GGGGGGGG,852 ATTAGACC,848 ATTAGCCG,840 ATTATACG,699 ``` Sometimes you need to reverse complement sample barcodes: ``` cat barcodes_original.csv | awk -F ',' '{print $1}' | tr ACGTacgt TGCAtgca | rev ``` sample_barcodes.csv ``` TCTCTCCG,S01 GCGTAAGA,S02 CCTAGAGT,S03 TCGACTAG,S04 TTCTAGAG,S05 ``` ### 5. Create bcbio yaml config file *sc_mouse/config/sc-mouse.yaml*: ``` details: - algorithm: cellular_barcode_correction: 1 minimum_barcode_depth: 1000 sample_barcodes: /full/path/sc_mouse/config/sample_barcodes.csv transcriptome_fasta: /n/shared_db/bcbio/biodata/genomes/Mmusculus/mm10/rnaseq/ref-transcripts.fa transcriptome_gtf: /n/shared_db/bcbio/biodata/genomes/Mmusculus/mm10/rnaseq/ref-transcripts.gtf umi_type: harvard-indrop-v3 analysis: scRNA-seq description: PI_name files: - /full/path/sc_mouse/input/KM_1.fq.gz - /full/path/sc_mouse/input/KM_2.fq.gz - /full/path/sc_mouse/input/KM_3.fq.gz - /full/path/sc_mouse/input/KM_4.fq.gz genome_build: mm10 metadata: {} fc_name: sc-mouse upload: dir: /full/path/sc_mouse/final ``` Use `cd sc_mouse/input; readlink -f *` to grab full path to each file and paste into yaml. ### 6. Create a batch script *sc_mouse/config/bcbio.sh*: ```shell #!/bin/bash # https://slurm.schedmd.com/sbatch.html #SBATCH --partition=priority # Partition (queue) #SBATCH --time=10-00:00 # Runtime in D-HH:MM format #SBATCH --job-name=km # Job name #SBATCH -c 20 #SBATCH --mem-per-cpu=5G # Memory needed per CPU #SBATCH --output=project_%j.out # File to which STDOUT will be written, including job ID #SBATCH --error=project_%j.err # File to which STDERR will be written, including job ID #SBATCH --mail-type=ALL # Type of email notification (BEGIN, END, FAIL, ALL) bcbio_nextgen.py ../config/sc-mouse.yaml -n 20 ``` - most projects take < 5days, but some large 4 lane could take more, like 7-8 ### 7. Run bcbio ```shell cd sc_mouse_work sbatch ../config/bcbio.sh ``` ### 8.1 Create Seurat object Reading matrices from bcbio and creating seurat objects might take a lot of RAM. If you can't fit your dataset on a laptop, create R conda environment on a cluster, as [described](https://github.com/hbc/knowledgebase/blob/master/scrnaseq/Single-Cell-conda.md) ``` # O2: use interactive job with 20G RAM # sometimes Rscript is not working but works from R # conda activate r # which R # Rscript 00_create_seurat_object.R # conda deactivate # should have 3 files from bcbio library(R.utils) file.rename("tagcounts.mtx", "matrix.mtx") file.rename("tagcounts.mtx.rownames", "features.tsv") file.rename("tagcounts.mtx.colnames", "barcodes.tsv") gzip("matrix.mtx") gzip("features.tsv") gzip("barcodes.tsv") library(Seurat) counts <- Read10X(data.dir = ".", gene.column = 1) seurat_object <- CreateSeuratObject(counts = counts, min.features = 100) saveRDS(seurat_object, "seurat.bcbio.RDS") ``` ### 8.2. Create SingleCellExperiment object You may convert Seurat object to SingleCellExperiment, but also you may choose to save duplicated matrices in SCE. ``` # run: # interactive session with 20G of RAM # cd to project/final/project # conda activate r # Rscript 01.bcbio2sse.R library(SingleCellExperiment) library(Matrix) library(AnnotationHub) library(tidyverse) species = "Mus musculus" counts = readMM(file.path("tagcounts.mtx")) dupcounts = readMM(file.path("tagcounts-dupes.mtx")) rownames = read.csv(file.path("tagcounts.mtx.rownames"), header = F)[["V1"]] rownames = as.character(rownames) colnames = read.csv(file.path("tagcounts.mtx.colnames"), header = F)[["V1"]] colnames = make.names(as.character(colnames)) reads = read.csv(file.path("cb-histogram.txt"), header = F, sep="\t", row.names = 1) rownames(reads) = make.names(rownames(reads)) counts = as(counts, "dgCMatrix") rownames(counts) = rownames colnames(counts) = colnames metadata = read.csv(file.path("tagcounts.mtx.metadata")) rownames(metadata) = colnames metadata[["nUMI"]] = colSums(counts) metadata[["nGenes"]] = colSums(counts>0) metadata[["log10GenesPerUMI"]] = log10(metadata$nGene) / log10(metadata$nUMI) metadata[["nReads"]] = reads[colnames,] metadata[["saturation_rate"]] = 1-(colSums(counts)/colSums(dupcounts)) metadata[["dupReads"]] = colSums(dupcounts) metadata[["dupMeanReads"]] = colMeans(dupcounts) # check if file is empty and skip if the case # annotation was download from ensembl biomart to match the version GRCh38.92 # AnnotationHub can be used. ## Load the annotation resource. ah <- AnnotationHub() ahDb <- query(ah, pattern= c(species, "EnsDb") ) ahEdb <- ahDb[[rev(names(ahDb))[1]]] # last one is chosen rows = genes(ahEdb) %>% as.data.frame() %>% janitor::clean_names() %>% dplyr::select(gene_id, gene_name, description, biotype = gene_biotype, entrezid, chrom = seqnames) %>% group_by(gene_id, biotype, chrom, description) %>% summarise(gene_name = paste(unique(gene_name), collapse = ","), entrezid = paste(unique(entrezid), collapse = ",")) %>% mutate(gene_name=ifelse(gene_name=="", gene_id, gene_name)) %>% as.data.frame() # mit rrna = rows %>% dplyr::filter(chrom == "MT") %>% .[["gene_id"]] %>% intersect(., rownames) metadata[["mtUMI"]] = colSums(counts[rrna,], na.rm = T) metadata[["mtUMI"]][is.na(metadata[["mtUMI"]])] = 0 metadata[["mitoRatio"]] = metadata$mtUMI/metadata$nUMI se = SingleCellExperiment(assays=list(raw = counts), colData = metadata) saveRDS(se, "se.RDS") ``` ### 1a. (Optional) Fresh transcriptome annotations are avaliable from [Gencode](https://www.gencodegenes.org/mouse/) The mouse gtf uses chrom names with chr matching mm10 assembly. ``` cd sc_mouse/input wget ftp://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_mouse/release_M23/gencode.vM23.annotation.gtf.gz gunzip gencode.vM23.annotation.gtf.gz gffread -g /n/shared_db/bcbio/biodata/genomes/Mmusculus/mm10/seq/mm10.fa gencode.vM23.annotation.gtf -x gencode.vM23.annotation.cds.fa ``` update sc_mouse/config/sc_mouse.yaml: ``` transcriptome_fasta: gencode.vM23.annotation.cds.fa transcriptome_gtf: gencode.vM23.annotation.gtf ``` ## Parameters * `umi_type` Single cell library type: [harvard-indrop, harvard-indrop-v2, 10x_v2, icell8, surecell]. * `minimum_barcode_depth=10000` Cellular barcodes with less reads are discarded. * `sample_barcodes` A file with one sample barcode per line. If the file contains sample name for each barcode, this will be used to create a `tagcounts.mtx.metadata` that match each cell with the sample name associated with the barcode. For inDrops3 protocol sample barcodes are in the fastq file for read3. Example of `sample_barcodes` file: ``` AATTCCGG,sample1 CCTTGGAA,sample2 ``` * `singlecell_quantifier=rapmap` Quantifier to use for single-cell RNA-sequencing. Supports `rapmap` or `kallisto`. * *optional* `cellular_barcodes` A file or a list [file1.txt, file2.txt] of valid cellular barcodes. * *optional* `cellular_barcode_correction=1` Number of errors to correct in identified cellular barcodes. Requires `cellular_barcodes` option set. Set to 0 to turn off error correction. * *optional* `transcriptome_fasta` alternative transcriptome reference. * *optional* `transcriptome_gtf` An optional GTF file of the transcriptome to quantitate, rather than the bcbio installed version. This is recommended for single-cell RNA-sequencing experiments. * `demultiplexed` If set to True, each file will be treated as a cell or well and not a collection of cells. Use this if your data has already been broken up into cells or wells. ## Output Project directory `bcbio_run/final/project`: * `tagcounts.mtx` -- count matrix compatible with dgCMatrix type in R. * `tagcounts-dupes.mtx` -- count matrix compatible with dgCMatrix type in R but with the duplicated reads counted. * `tagcounts.mtx.colnames` -- cell names that would be the columns for the matrix. * `tagcounts.mtx.rownames` -- gene names that would be the rows for the matrix. * `tagcounts.mtx.metadata` -- metadata that match the colnames for the matrix. This is coming from the barcode.csv file and the metadata given in the YAML config file. for the matrix. * `cb-histogram.txt` -- total number of dedup reads assigned to a cell. Comparing colSums(tagcounts.mtx) to this number can tell you how many reads mapped to genes. Sample directories `bcbio_run/final/sample`: * `SAMPLE-transcriptome.bam` -- BAM file aligned to transcriptome. * `SAMPLE-mtx.*` -- gene counts as explained in the project directory. ## Steps Minor steps and exact file locations are omitted. * = repeated for every sample in sample_barcodes.csv *bcbio.yaml config*: ```yaml details: - algorithm: cellular_barcode_correction: 1 minimum_barcode_depth: 1000 sample_barcodes: /path/project/config/barcodes.csv transcriptome_fasta: /path/genomes/Mmusculus/mm10/rnaseq/ref-transcripts.fa transcriptome_gtf: /path/genomes/Mmusculus/mm10/rnaseq/ref-transcripts.gtf umi_type: harvard-indrop-v3 analysis: scRNA-seq description: project files: - /path/project_1.fq.gz - /path/project_2.fq.gz - /path/project_3.fq.gz - /path/project_4.fq.gz genome_build: mm10 fc_name: sc-mouse upload: dir: /path/project/final ``` 1. parse barcode information from reads 2,3,4 to the fastq read name, [CELL]\_[value]:[UMI]\_[value]:[sample]\_[value]. umis supports many protocols, however, the downside is speed - this step can take up to 3-4 days: ```shell python umis fastqtransform \ --separate_cb umis/harvard-indrop-v3-transform.json --cores 16 \ project_1.fq.gz project_2.fq.gz project_3.fq.gz project_4.fq.gz | \ seqtk seq -L 20 - | gzip > project.umitransformed.fq.gz ``` 2. create a fastq file for each sample: ```shell python umis demultiplex_samples \ --nedit 1 --barcodes sample_barcodes.csv \ --out_dir demultiplexed project.umitransformed.fq.gz ``` 3. Cellular barcode filter ```shell python umis cb_filter \ --cores 16 --bc1 harvard-indrop-v3-cb1.txt.gz --nedit 1 \ --bc2 harvard-indrop-v3-cb2.txt.gz demultiplexed/[sample-barcodeAATTTTT].fq | \ gzip -c > project-sample_barcode.filtered.fq.gz ``` 4. \* create cellular barcode histogram, also creates cb-histogram-filtered.txt for cells with nreads > minimum_barcode_depth: ```shell python umis cb_histogram project-sample_barcode.filtered.fq.gz > cb-histogram.txt ``` 5. \* create index genome for rapmap: ```shell rapmap quasiindex -k 31 -i mm10 -t mm10/ref-transcripts.fa ``` 6. \* align reads with rapmap: ```shell rapmap quasimap -t 16 -i mm10 \ -r <(gzip -cd project-sample_barcode.filtered.fq.gz) | \ samtools sort -@ 16 -m 1G -T project-sample_barcode-sorttmp \ -o project-sample_barcode.bam /dev/stdin samtools index -@ 16 project-sample_barcode.bam project-sample_barcode.bam.bai ``` 7. \* count transcripts: ```shell python umis fasttagcount --cb_cutoff 1000 \ --genemap ref-transcripts-tx2gene.tsv --cb_histogram project-sample_barcode/cb-histogram.txt \ --umi_matrix project-sample_barcode-dupes.mtx.full \ project-sample_barcode.bam project-sample_barcode.mtx.full python umis sparse project-sample_barcode.mtx.full \ project-sample_barcode.mtx python umis sparse project-sample_barcode-dupes.mtx.full \ project-sample_barcode-dupes.mtx ``` 8. Concatenate all cb-histogram-filtered.txt files: ```shell cat project-[all-barcodes]/cb-histogram-filtered.txt > cb-histogram.txt ``` ## Description bcbio-nextgen supports universal molecular identifiers (UMI) based single-cell RNA-seq analyses. If your single-cell prep does not use universal molecular identifiers (UMI), you can most likely just run the standard RNA-seq pipeline and use the results from that. The UMI are used to discard reads which are possibly PCR duplicates and is very helpful for removing some of the PCR duplicate noise that can dominate single-cell experiments. Unlike the standard RNA-seq pipeline, the single-cell pipeline expects the FASTQ input files to not be separated by cellular barcode, so each file is a mix of cells identified by a cellular barcode (CB), and unique reads from a transcript are identified with a UMI. bcbio-nextgen inspects each read, identifies the cellular barcode and UMI and puts them in the read name. Then the reads are aligned to the transcriptome with [RapMap](https://github.com/COMBINE-lab/RapMap) and the number of reads aligning to each transcript is counted for each cellular barcode. The output is a table of counts with transcripts as the rows and columns as the cellular barcodes for each input FASTQ file. Optionally the reads can be quantitated with `kallisto` to output transcript compatibility counts rather than counts per gene ([TCC paper](https://doi.org/10.1186/s13059-016-0970-8)). To extract the UMI and cellular barcodes from the read, bcbio-nextgen needs to know where the UMI and the cellular barcode are expected to be in the read. Currently there is support for two schemes, the inDrop system from the Harvard single-cell core facility and CEL-seq. If bcbio-nextgen does not support your UMI and barcoding scheme, please open up an issue and we will help implement support for it. Most of the heavy lifting for this part of bcbio-nextgen is implemented in the [umis](https://github.com/vals/umis) repository. ## References - [Indrops3 library structure](https://singlecellcore.hms.harvard.edu/resources) - [Even shorter guide](https://github.com/bcbio/bcbio-nextgen/blob/master/config/templates/indrop-singlecell.yaml) - [Much more comprehensive guide](https://github.com/hbc/tutorials/blob/master/scRNAseq/scRNAseq_analysis_tutorial/lessons/01_bcbio_run.md) bcbio-nextgen-1.2.9/docs/contents/small_rnaseq.md000066400000000000000000000100111415626112400220320ustar00rootroot00000000000000# smallRNA-seq ## Overview bcbio supports configurable best-practices pipeline for smallRNA-seq quality controls, adapter trimming, miRNA/isomiR quantification and other small RNA detection. * Adapter trimming: * [atropos](https://atropos.readthedocs.io/en/latest/guide.html) * [dnapi](https://github.com/jnktsj/DNApi) for adapter de-novo detection * Sequence alignment: * [STAR](https://code.google.com/archive/p/rna-star) for genome annotation * bowtie, _bowtie2_ and [hisat2](https://daehwankimlab.github.io/hisat2/) for genome annotation as an option * Specific small RNAs quantification (miRNA/tRNAs...): * [seqbuster](https://github.com/lpantano/seqbuster) for miRNA annotation * [MINTmap](https://github.com/TJU-CMC-Org/MINTmap) for tRNA fragments annotation * [miRge2](https://github.com/mhalushka/miRge) for alternative small RNA quantification. To setup this tool, you need to install manually miRge2.0, and download the library data for your species. Read how to install and download the [data](https://github.com/mhalushka/miRge#download-libraries). If you have `human` folder at `/mnt/data/human` the option to pass to resources will be `/mnt/data`. Then setup `resources`: ```yaml resources: mirge: options: ["-lib $PATH_TO_PARENT_SPECIES_LIB"] ``` * Quality control: [FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) * Other small RNAs quantification: * [seqcluster](https://github.com/lpantano/seqcluster) * [mirDeep2](https://www.mdc-berlin.de/content/mirdeep2-documentation) for miRNA prediction The pipeline generates a _RMD_ template file inside `report` folder that can be rendered with knitr. An example of the report is [here](https://github.com/lpantano/mypubs/blob/master/srnaseq/mirqc/ready_report.md). Count table (`counts_mirna.tst`) from mirbase miRNAs will be inside `mirbase` or final project folder. Input files for [isomiRs](https://github.com/lpantano/isomiRs) package for isomiRs analysis will be inside each sample in `mirbase` folder. If mirdeep2 can run, count table (`counts_mirna_novel.tsv`) for novel miRNAs will be inside `mirdeep2` or final project folder. tdrmapper results will be inside each sample inside `tdrmapper` or final project folder. ## Parameters * `adapters` The 3' end adapter that needs to be remove. For NextFlex protocol you can add `adapters: ["4N", "$3PRIME_ADAPTER"]`. For any other options you can use resources: `atropos:options:["-u 4", "-u -4"]`. * `species` 3 letters code to indicate the species in mirbase classification (i.e. hsa for human). * `aligner` Currently STAR is the only one tested although bowtie can be used as well. * `expression_caller` A list of expression callers to turn on: trna, seqcluster, mirdeep2, mirge * `transcriptome_gtf` An optional GTF file of the transcriptome to for seqcluster. * `spikein_fasta` A FASTA file of spike in sequences to quantitate. * `umi_type: 'qiagen_smallRNA_umi'` Support of Qiagen UMI small RNAseq protocol. ## Output Project directory: * `counts_mirna.tsv` -- miRBase miRNA count matrix. * `counts.tsv` -- miRBase isomiRs count matrix. The ID is made of 5 tags: miRNA name, SNPs, additions, trimming at 5 and trimming at 3. Here there is detail explanation of the [naming](https://seqcluster.readthedocs.io/mirna_annotation.html). * `counts_mirna_novel.tsv` -- miRDeep2 miRNA count matrix. * `counts_novel.tsv` -- miRDeep2 isomiRs. See counts.tsv explanation for more detail. count matrix. * `seqcluster` -- output of [seqcluster](https://github.com/lpantano/seqcluster) tool. Inside this folder, counts.tsv has count matrix for all clusters found over the genome. * `seqclusterViz` -- input file for interactive browser at * `report` -- Rmd template to help with downstream analysis like QC metrics, differential expression, and clustering. Sample directories: * `SAMPLE-mirbase-ready.counts` -- counts for miRBase miRNAs. * `SAMPLE-novel-ready` -- counts for miRDeep2 novel miRNAs. * `tRNA` -- output for [tdrmapper](https://github.com/sararselitsky/tDRmapper). bcbio-nextgen-1.2.9/docs/contents/somatic_variants.md000066400000000000000000000563141415626112400227370ustar00rootroot00000000000000# Somatic (cancer) variants For small variants (SNV and indels), bcbio supports the following workflows: - tumor-normal calling; - tumor only calling; - UMIs, including duplex UMIs, which improve precision in many applications including cfDNA analysis; We recommend starting with `vardict` and `mutect2` as variant callers. bcbio also supports a majority voting ensemble approach to combine calls from multiple callers. For copy number (CNV) detection, bcbio supports T/N and T only calling with a panel of normals with `purecn`, `cnvkit`, `gatk-cnv` and `seq2c`. ## Workflow1 - T/N This [example](https://github.com/bcbio/bcbio-nextgen/blob/master/config/examples/cancer-dream-syn3.yaml) runs a tumor-normal calling with mutect2 and vardict. Supply a consistent batch for tumor/normal pairs and mark them with the phenotype: ```yaml - description: sample_tumor algorithm: variantcaller: [vardict, mutect2] metadata: batch: batch1 phenotype: tumor - description: sample_normal algorithm: variantcaller: [vardict, mutect2] metadata: batch: batch1 phenotype: normal ``` This example calls and validates variants using multiple approaches in a paired tumor/normal cancer sample from the [ICGC-TCGA DREAM challenge](https://www.synapse.org/#!Synapse:syn312572/wiki/58893). It uses [synthetic dataset 3](https://www.synapse.org/#!Synapse:syn312572/wiki/62018) which has multiple subclones, enabling detection of lower frequency variants. The configuration and data file has downloads for exome only and whole genome analyses. It enables exome by default, but you can use the larger whole genome evaluation by uncommenting the relevant parts of the configuration and retrieval script. ### 1. Get the data: ```shell mkdir -p cancer-dream-syn3/config cancer-dream-syn3/input cancer-dream-syn3/work cd cancer-dream-syn3/config wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/cancer-dream-syn3.yaml cd ../input wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/cancer-dream-syn3-getdata.sh bash cancer-dream-syn3-getdata.sh ``` ### 2. Review parameters in the yaml file: Modify variant_regions for both samples to point to your bcbio installation or copy NGv3.bed from there to project/input and reference it as ../input/NGv3.bed in the yaml. ```yaml # Cancer tumor/normal calling evaluation using synthetic dataset 3 # from the ICGC-TCGA DREAM challenge: # https://www.synapse.org/#!Synapse:syn312572/wiki/62018 --- details: - algorithm: aligner: bwa mark_duplicates: true remove_lcr: true variantcaller: [mutect2, vardict] variant_regions: /path/to/bcbio/genomes/Hsapiens/hg38/coverage/capture_regions/NGv3.bed analysis: variant2 description: syn3-normal files: - ../input/synthetic_challenge_set3_normal_NGv3_1.fq.gz - ../input/synthetic_challenge_set3_normal_NGv3_2.fq.gz genome_build: hg38 metadata: batch: syn3 phenotype: normal - algorithm: aligner: bwa mark_duplicates: true remove_lcr: true variantcaller: [mutect2, vardict] variant_regions: /path/to/bcbio/genomes/Hsapiens/hg38/coverage/capture_regions/NGv3.bed analysis: variant2 description: syn3-tumor files: - ../input/synthetic_challenge_set3_tumor_NGv3_1.fq.gz - ../input/synthetic_challenge_set3_tumor_NGv3_2.fq.gz genome_build: hg38 metadata: batch: syn3 phenotype: tumor upload: dir: ../final ``` Set `remove_lcr` parameter to `true` to remove low complexity regions from variant calling, both germline and somatic (additional information: https://www.ncbi.nlm.nih.gov/pubmed/24974202) ### 3. Run bcbio project ```shell cd ../work bcbio_nextgen.py ../config/cancer-dream-syn3.yaml -n 8 ``` Cancer calling handles both tumor-normal paired calls and tumor-only calling. To specify a tumor-only sample, provide a single sample labeled with `phenotype: tumor`. Otherwise the configuration and setup is the same as with paired analyses. For tumor-only samples, bcbio will try to remove likely germline variants present in the public databases like 1000 genomes and ExAC, and not in COSMIC. This runs as long as you have a local GEMINI data installation (`--datatarget gemini`) and marks likely germline variants with a `LowPriority` filter. [This post](http://bcb.io/2015/03/05/cancerval/) has more details on the approach and validation. The standard variant outputs (`sample-caller.vcf.gz`) for tumor calling emphasize somatic differences, those likely variants unique to the cancer. If you have a tumor-only sample and GEMINI data installed, it will also output `sample-caller-germline.vcf.gz`, which tries to identify germline background mutations based on presence in public databases. We're actively working on improving calling to better account for the heterogeneity and structural variability that define cancer genomes. ## Workflow2: Somatic and germline variants For tumor/normal somatic samples, bcbio can call both somatic (tumor-specific) and germline (pre-existing) variants. To option somatic and germline calls for your tumor/normal inputs, specify which callers to use for each step in the configuration: ```yaml description: your-normal variantcaller: somatic: vardict germline: gatk-haplotype ``` bcbio does a single alignment for the normal sample, then splits at the variant calling steps using this normal sample to do germline calling. In this example, the output files are: * `your-tumor/your-tumor-vardict.vcf.gz` -- Somatic calls from the tumor samples using the normal as background to subtract existing calls. * `your-normal/your-normal-freebayes.vcf.gz` -- Germline calls on the normal sample. Germline calling supports multiple callers, and other configuration options like ensemble and structural variant calling inherit from the remainder configuration. For example, to use 3 callers for somatic and germline calling, create ensemble calls for both and include germline and somatic events from two structural variant callers: ```yaml variantcaller: somatic: [vardict, strelka2, mutect2] germline: [freebayes, gatk-haplotype, strelka2] ensemble: numpass: 2 svcaller: [manta, cnvkit] ``` In addition to the somatic and germline outputs attached to the tumor and normal sample outputs as described above, you'll get: * `your-tumor/your-tumor-manta.vcf.gz` -- Somatic structural variant calls for each specified `svcaller`. These will have genotypes for both the tumor and normal samples, with somatic calls labeled as PASS variants. * `your-normal/your-normal-manta.vcf.gz` -- Germline structural variant calls for each specified `svcaller`. We expect these to be noisier than the somatic calls due to the lack of a reference sample to help remove technical noise. ## Workflow3: copy number variants See also [PureCN user story](https://bcbio-nextgen.readthedocs.io/en/latest/contents/purecn.html) which is a recommended option. The first bcbio run creates a panel of normals (PON), the second bcbio run uses the PON file to call copy number variants (CNV) in tumor/normal (gatk-cnv) or tumor only (cnvkit) samples. PON samples should use the same gene panel/sequencing technology as tumor only samples. While it is technically possible to call CNVs in T/N pairs without PON, PON approach is preferable. 3 tools support PON in bcbio: `gatk-cnv`,`CNVkit`,`seq2c`. To call CNVs with a PON, this PON file should be created by the same method (not possible to create PON with CNVkit and use it for gatk-cnv calling. It is possible to calculate two PON files simultaneously (for gatk-cnv and seq2c or CNVkit and seqc2). CNVkit and gatk-cnv cannot be run together, because they require different, incompatible normalization schemes. ### 1. Collect PON samples and create a project structure Put coverage.bed in pon/config/ and PON input files (bam, fq.gz) to pon/input. One test tumor sample is required to create a PON project, this tumor sample is not included in the PON. ```bash $ mkdir pon $ cd pon $ mkdir input config $ ls config coverage.bed $ ls -1 input S_1_N.bam S_2_N.bam S_3_N.bam S_1_T.bam ... ``` coverage.bed contains regions from WES or gene panel capture kit provider. ### 2. Create pon.csv Mark samples to build the PON with `svclass=control` ``` samplename,description,svclass,batch S_1_N.bam,S_1_N,control,pon_build S_2_N.bam,S_2_N,control,pon_build S_3_N.bam,S_3_N,control,pon_build S_1_T.bam,S_1_N,tumor,pon_build ``` To use fastq input: `S_2_N_R1.fq.gz;S_2_N_R2.fq.gz,S_2_N,control,pon_build` ### 3. Create pon_template.yaml: ```yaml details: - analysis: variant2 genome_build: hg38 algorithm: svcaller: [gatk-cnv, seq2c] variant_regions: /path/pon/config/coverage.bed ``` ### 4. Configure bcbio PON project Put `pon.csv`, `pon_template.yaml` in the same dir as `pon`. Run automatic sample configuration: ```bash $ ls -1 pon pon.csv pon_template.yaml $ bcbio_nextgen.py -w template pon_template.yaml pon.csv pon/input/*.bam ``` ### 5. Run bcbio PON project ```bash $ cd pon/work $ bcbio_nextgen.py ../config/pon.yaml -n 15 ``` ### 6. Collect PON file: * gatk-cnv: `final/project/gatkcnv-pon.hdf5` * seq2c doesn't have a default PON file format so we create a bcbio specific one as a concatenation of the read mapping file `final/date_project/seq2c-read_mapping.txt` and coverage file `final/date_project/seq2c-coverage.tsv` outputs for the background samples. When fed to future bcbio runs, it will correctly extract and re-use this file as background. ```bash cat seq2c-read_mapping.txt seq2c-coverage.tsv > seqc.pon.txt ``` * CNVkit: `final/testsample/testsample-cnvkit-background.cnn` Then use PON in a T/N project ### 7. Create pon_tn project structure Put coverage.bed, gatk-cnv.pon.hdf5,seq2c.pon.txt in `pon_tn/config/`, copy or symlink all input files (bam, fq.gz) to pon/input. ```bash mkdir pon_tn cd pon_tn mkdir config input cp /path/coverage.bed /path/gatk-cnv.pon.hdf5 /path/seq2c.pon.txt config # cp or symlink input files cp /path/*.bam input cd .. ``` ### 8. Prepare a sample sheet pon_tn.csv: ``` samplename,description,batch,phenotype S_1_T-ready.bam,S_1_T,S_1,tumor S_2_T-ready.bam,S_2_T,S_2,tumor S_3_T-ready.bam,S_3_T,S_3,tumor S_1_N-ready.bam,S_1_N,S_1,normal S_2_N-ready.bam,S_2_N,S_2,normal S_3_N-ready.bam,S_3_N,S_3,normal ``` ### 9. Premate a yaml template: pon_tn_template.yaml ```yaml details: - analysis: variant2 genome_build: hg38 algorithm: svcaller: [gatk-cnv, seq2c] variant_regions: /path/pon_tn/config/coverage.bed coverage_interval: regional background: cnv_reference: gatk-cnv: /path/pon_tn/config/gatk-cnv.pon.hdf5 seq2c: /path/pon_tn/config/seqc.pon.txt ``` ### 10. configure pon_tn project: ``` $ ls -1 pon_tn pon_tn.csv pon_tn_template.yaml $ bcbio_nextgen.py -w template pon_tn_template.yaml pon_tn.csv pon_tn/input/*.bam ``` ### 11. Run bcbio pon_tn project ```bash $ cd pon_tn/work $ bcbio_nextgen.py ../config/pon_tn.yaml -n 15 ``` ## Workflow4: Cancer-like mixture with Genome in a Bottle samples This example simulates somatic cancer calling using a mixture of two Genome in a Bottle samples, NA12878 as the "tumor" mixed with NA24385 as the background. The [Hartwig Medical Foundation](https://www.hartwigmedicalfoundation.nl/en/) and [Utrecht Medical Center](https://www.umcutrecht.nl/en/Research/Strategic-themes/Cancer) generated this "tumor/normal" pair by physical mixing of samples prior to sequencing. The GiaB FTP directory has [more details on the design and truth sets](ftp://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/use_cases/mixtures/UMCUTRECHT_NA12878_NA24385_mixture_10052016/README-NA12878_NA24385_mixture.txt). The sample has variants at 15% and 30%, providing the ability to look at lower frequency mutations. To get the data: ```shell wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/cancer-giab-na12878-na24385-getdata.sh bash cancer-giab-na12878-na24385-getdata.sh ``` Then run the analysis with: ```shell cd work bcbio_nextgen.py ../config/cancer-giab-na12878-na24385.yaml -n 16 ``` ## Parameters - `variantcaller`: should be consistent for T/N pairs - `min_allele_fraction` Minimum allele fraction to detect variants in heterogeneous tumor samples, set as the float or integer __percentage__ to resolve (i.e. 10 = alleles in 10% of the sample). Defaults to 10. Specify this in the tumor sample of a tumor/normal pair. It is percentage, not ratio, it is divided /100.0 when calling vardict! - `use_lowfreq_filter: false`. When set, forces vardict to report variants with low allelec frequency, useful to call variants in panels with high coverage (>1000x). The default (option is not set to false in the config) is to use low frequency filter, i.e. variants could be underreported (variant VAF is above min_allele_fraction but rejected by the filter). - to use panel of normals (PON) for small variants with mutect2, specify a vcf file as a background for T sample. ```yaml - algorithm: background: /path/to/input/1000g_pon.hg38.vcf.gz variantcaller: mutect2 metadata: batch: batch1 phenotype: tumor ``` bcbio does not support PON generation at the moment. You may create a PON outside of bcbio or use PONs from [Broad Institute](https://console.cloud.google.com/storage/browser/gatk-best-practices/somatic-hg38/) - also see more parameters in `germline_variants` user story. ### Ensemble variant calling A simple majority rule ensemble classifier builds a final callset based on the intersection of calls. It selects variants represented in at least a specified number of callers: ```yaml variantcaller: [mutect2, varscan, freebayes, vardict] ensemble: numpass: 2 use_filtered: false ``` This example selects variants present in 2 out of the 4 callers and does not use filtered calls (the default behavior). Because of the difficulties of producing a unified FORMAT/genotype field across callers, the ensemble outputs contains a mix of outputs from the different callers. It picks a representative sample in the order of specified caller, so in the example above would have a MuTect2 call if present, otherwise a VarScan call if present, otherwise a FreeBayes call. This may require custom normalization scripts during post-processing when using these calls. [bcbio.variation.recall](https://github.com/chapmanb/bcbio.variation.recall) implements this approach, which handles speed and file sorting limitations in the [bcbio.variation](https://github.com/chapmanb/bcbio.variation) approach. This older approach uses the [bcbio.variation](https://github.com/chapmanb/bcbio.variation) toolkit to perform the consolidation. An example configuration in the `algorithm` section is: ```yaml variantcaller: [gatk, freebayes, samtools, gatk-haplotype, varscan] ensemble: format-filters: [DP < 4] classifier-params: type: svm classifiers: balance: [AD, FS, Entropy] calling: [ReadPosEndDist, PL, PLratio, Entropy, NBQ] trusted-pct: 0.65 ``` The `ensemble` set of parameters configure how to combine calls from the multiple methods: * `format-filters` A set of filters to apply to variants before combining. The example removes all calls with a depth of less than 4. * `classifier-params` Parameters to configure the machine learning approaches used to consolidate calls. The example defines an SVM classifier. * `classifiers` Groups of classifiers to use for training and evaluating during machine learning. The example defines two set of criteria for distinguishing reads with allele balance issues and those with low calling support. * `trusted-pct` Define threshold of variants to include in final callset. In the example, variants called by more than 65% of the approaches (4 or more callers) pass without being requiring SVM filtering. ### UMIs Unique molecular identifiers (UMIs) are short random barcodes used to tag individual molecules and avoid amplification biased. Both single cell RNA-seq and variant calling support UMIs. For variant calling, [fgbio](https://github.com/fulcrumgenomics/fgbio) collapses sequencing duplicates for each UMI into a single consensus read prior to running re-alignment and variant calling. This requires `mark_duplicates: true` (the default) since it uses position based duplicates and UMI tags for collapsing duplicate reads into consensus sequences. To help with preparing fastq files with UMIs bcbio provides a script `bcbio_fastq_umi_prep.py`. This handles two kinds of UMI barcodes: * Separate UMIs: it converts reads output by an Illumina as 3 files (read 1, read 2, and UMIs). * Duplex barcodes with tags incorporated at the 5' end of read 1 and read 2 In both cases, these get converted into paired reads with UMIs in the fastq names, allowing specification of `umi_type: fastq_name` in your bcbio YAML configuration. The script runs on a single set of files or autopairs an entire directory of fastq files. To convert a directory with separate UMI files: ```shell bcbio_fastq_umi_prep.py autopair -c ``` To convert duplex barcodes present on the ends of read 1 and read 2: ```shell bcbio_fastq_umi_prep.py autopair -c --tag1 5 --tag2 5 ``` If you want to prepare your FASTQ files for use with the `umi_type: fastq_name` option and they don't follow the two barcode schemes listed you can pre-transform the FASTQ files yourself by putting `:UMI_yourumisequence` in the read name. Here is an example: ``` @A00574:89:HCLMTDRXX:1:2101:1425:1016:UMI_CGAACGTGTACACG 2:N:0:CTGAAGCT+GGCTCTGA GTGATATAATTTATTTTCTTAAAATAGCCATGCTGGCTGGAGCCACAGCAGTTTACTCCCAGTTCATTACTCAGCTAACAGACGAAAACCAGT + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ``` For more complex UMI schemes please open up an issue and we can help you write a transformation to prepare your files. We use to do these more complex transformations. Configuration options for UMIs: * `umi_type` The UMI/cellular barcode scheme used for your data. For variant analysis with UMI based consensus calling, supports `fastq_name` with UMIs in read names, the path to a fastq file with UMIs for each aligned read or `dragen` which accepts the pre-consensus BAM file from DRAGEN. * `correct_umis: [path/to/whitelist_umi.txt]`. For a restricted set of UMIs specify a text file (one UMI per line). UMIs will be corrected with You can adjust the [fgbio default options](https://github.com/bcbio/bcbio-nextgen/blob/8a76c9e546cb79621707082fd763bd643e0e9652/bcbio/ngsalign/postalign.py#L208) by adjusting `resources`. The most common change is modifying the minimum number of reads as input to consensus sequences. This default to 1 to avoid losing reads, 3 is recommended for high depth panels: ```yaml resources: fgbio: options: [--min-reads, 3] ``` Duplex UMI sequencing allows to reduce false positive rate compared to single UMIs, see implementations from [TwinStrand](https://twinstrandbio.com/technology/) or [IDT](https://www.idtdna.com/pages/products/next-generation-sequencing/adapters/xgen-dual-index-umi-adapters-tech-access). [Duplex UMI data processing example in bcbio](https://github.com/bcbio/bcbio-nextgen/blob/master/config/templates/somatic-duplex-umi.yaml) ## Output ### Project directory: * `grading-summary.csv` -- Grading details comparing each sample to a reference set of calls. This will only have information when providing a validation callset. * `BATCH-caller.vcf` -- Variants called for a population/batch of samples by a particular caller. * `BATCH-caller.db` -- A [GEMINI database](https://github.com/arq5x/gemini) associating variant calls with a wide variety of third party annotations. This provides a queryable framework for assessing variant quality statistics. ### Sample directories: * `SAMPLE-caller.vcf` -- Variants calls for an individual sample. * `SAMPLE-gdc-viral-completeness.txt` -- Optional viral contamination estimates. File is of the format **depth, 1x, 5x, 25x**. **depth** is the number of reads aligning to the virus. **1x, 5x, 25x** are percentage of the viral sequence covered by reads of 1x, 5x, 25x depth. Real viral contamination will have broad coverage across the entire genome, so high numbers for these values, depending on sequencing depth. High depth and low viral sequence coverage means a likely false positive. ## Validation bcbio pre-installs standard truth sets for performing validation, and also allows use of custom local files for assessing reliability of your runs: * `validate` A VCF file of expected variant calls to perform validation and grading of small variants (SNPs and indels) from the pipeline. This provides a mechanism to ensure consistency of calls against a known set of variants, supporting comparisons to genotyping array data or reference materials. * `validate_regions` A BED file of regions to evaluate small variant calls in. This defines specific regions covered by the `validate` VCF file. * `svvalidate` -- Dictionary of call types and pointer to BED file of known regions. For example: `DEL: known_deletions.bed` does deletion based validation of outputs against the BED file. Each option can be either the path to a local file, or a partial path to a file in the pre-installed truth sets. For instance, to validate an NA12878 run against the [Genome in a Bottle](https://github.com/genome-in-a-bottle) truth set: ```yaml validate: giab-NA12878/truth_small_variants.vcf.gz validate_regions: giab-NA12878/truth_regions.bed svvalidate: DEL: giab-NA12878/truth_DEL.bed ``` For cancer validations: * `giab-NA12878-NA24385-somatic` -- A [sequenced NA12878/NA24385 mixture](ftp://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/use_cases/mixtures/UMCUTRECHT_NA12878_NA24385_mixture_10052016/) providing a somatic-like truth set for detecting low frequency events. Build: Truth sets: small_variants, regions. Builds: GRCh37, hg38 * `dream-syn3` -- Synthetic dataset 3 from the [ICGC-TCGA DREAM mutation calling challenge](https://www.synapse.org/#!Synapse:syn312572/wiki/62018). Truth sets: small_variants, regions, DEL, DUP, INV, INS. Builds: GRCh37. * `dream-syn4` -- Synthetic dataset 4 from the [ICGC-TCGA DREAM mutation calling challenge](https://www.synapse.org/#!Synapse:syn312572/wiki/62018). Truth sets: small_variants, regions, DEL, DUP, INV. Builds: GRCh37. * `dream-syn3-crossmap` -- Synthetic dataset 3 from the [ICGC-TCGA DREAM mutation calling challenge](https://www.synapse.org/#!Synapse:syn312572/wiki/62018) converted to human build 38 coordinates with CrossMap. Truth sets: small_variants, regions, DEL, DUP, INV, INS. Builds: hg38. * `dream-syn4-crossmap` -- Synthetic dataset 4 from the [ICGC-TCGA DREAM mutation calling challenge](https://www.synapse.org/#!Synapse:syn312572/wiki/62018) converted to human build 38 coordinates with CrossMap. Truth sets: small_variants, regions, DEL, DUP, INV. Builds: hg38. A [full evaluation of cancer calling](http://bcb.io/2015/03/05/cancerval/) validates callers against [synthetic dataset 3 from the ICGC-TCGA DREAM challenge](https://www.synapse.org/#!Synapse:syn312572/wiki/62018). ## References - [PON at UMCCR](https://umccr.org/blog/panel-of-normals/) - [1000g mutect PON](https://storage.googleapis.com/gatk-best-practices/somatic-hg38/1000g_pon.hg38.vcf.gz) ### CNV calling - [gatk-cnv](https://gatk.broadinstitute.org/hc/en-us/articles/360035531092--How-to-part-I-Sensitively-detect-copy-ratio-alterations-and-allelic-segments) - [Oh et al.2020.Reliable Analysis of Clinical Tumor-Only Whole-Exome Sequencing Data](https://ascopubs.org/doi/suppl/10.1200/CCI.19.00130) bcbio-nextgen-1.2.9/docs/contents/structural_variants.md000066400000000000000000000132431415626112400235020ustar00rootroot00000000000000# Structural variant calling ## Overview bcbio can detect larger (>50bp) structural variants like deletions, insertions, inversions and copy number changes for both germline population and cancer variant calling To enable structural variant calling, specify `svcaller` options in the algorithm section of your configuration ```yaml - description: Sample algorithm: svcaller: [lumpy, manta, cnvkit] ``` Split read callers (primary use case - germline WGS sequencing): - [Lumpy](https://github.com/arq5x/lumpy-sv) - [Manta](https://github.com/Illumina/manta) - [WHAM](https://github.com/jewmanchue/wham) - [DELLY](https://github.com/tobiasrausch/delly) - we annotate split-read calls with coverage depth using [duphold](https://github.com/brentp/duphold). Read-depth based CNV callers (primary use case - T/N cancer CNV calling) - [gatkcnv](https://gatk.broadinstitute.org/hc/en-us/articles/360035531092?id=11682) - [CNVkit](https://cnvkit.readthedocs.io/en/latest/). 2020-05-13: temporarily off until new release 0.9.7. ## Workflow This example runs structural variant calling with multiple callers (Lumpy, Manta and CNVkit), providing a combined output summary file and validation metrics against NA12878 deletions. It uses the same NA12878 input as the whole genome trio example. To run the analysis do: ```shell mkdir -p NA12878-sv-eval cd NA12878-sv-eval wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/examples/NA12878-sv-getdata.sh bash NA12878-sv-getdata.sh cd work bcbio_nextgen.py ../config/NA12878-sv.yaml -n 16 ``` This is large whole genome analysis and the timing and disk space requirements for the NA12878 trio analysis above apply here as well. ## Paramaters * `svcaller` -- List of structural variant callers to use. [lumpy, manta, cnvkit, gatk-cnv, seq2c, purecn, titancna, delly, battenberg]. LUMPY and Manta require paired end reads. cnvkit and gatk-cnv should not be used on the same sample due to incompatible normalization approaches, please pick one or the other for CNV calling. * `svprioritize` -- Produce a tab separated summary file of structural variants in regions of interest. This complements the full VCF files of structural variant calls to highlight changes in known genes. See the [paper on cancer genome prioritization](https://peerj.com/articles/3166/) for the full details. This can be either the path to a BED file (with `chrom start end gene_name`, see [Input file preparation](#input-file-preparation)) or the name of one of the pre-installed prioritization files: * `cancer/civic` (hg19, GRCh37, hg38) -- Known cancer associated genes from [CIViC](https://civic.genome.wustl.edu). * `cancer/az300` (hg19, GRCh37, hg38) -- 300 cancer associated genes contributed by [AstraZeneca oncology](https://www.astrazeneca.com/our-focus-areas/oncology.html). * `cancer/az-cancer-panel` (hg19, GRCh37, hg38) -- A text file of genes in the AstraZeneca cancer panel. This is only usable for `svprioritize` which can take a list of gene names instead of a BED file. * `actionable/ACMG56` -- Medically actionable genes from the [The American College of Medical Genetics and Genomics](http://iobio.io/2016/03/29/acmg56/) * `coding/ccds` (hg38) -- [Consensus CDS (CCDS)](https://www.ncbi.nlm.nih.gov/projects/CCDS/CcdsBrowse.cgi) regions with 2bps added to internal introns to capture canonical splice acceptor/donor sites, and multiple transcripts from a single gene merged into a single all inclusive gene entry. * `fusion_mode` Enable fusion detection in RNA-seq when using STAR (recommended) or Tophat (not recommended) as the aligner. OncoFuse is used to summarise the fusions but currently only supports `hg19` and `GRCh37`. For explant samples `disambiguate` enables disambiguation of `STAR` output [false, true]. This option is deprecated in favor of `fusion_caller`. * `fusion_caller` Specify a standalone fusion caller for fusion mode. Supports `oncofuse` for STAR/tophat runs, `pizzly` and `ericscript` for all runs. If a standalone caller is specified (i.e. `pizzly` or `ericscript` ), fusion detection will not be performed with aligner. `oncofuse` only supports human genome builds GRCh37 and hg19. `ericscript` supports human genome builds GRCh37, hg19 and hg38 after installing the associated fusion databases ([Customizing data installation](contents/installation:customizing%20data%20installation)). * `known_fusions` A TAB-delimited file of the format `gene1gene2`, where `gene1` and `gene2` are identifiers of genes specified under `gene_name` in the attributes part of the GTF file. ## Validation - [Validation of germline structural variant detection](https://bcb.io/2014/08/12/validated-whole-genome-structural-variation-detection-using-multiple-callers/) using multiple calling methods to validate against deletions in NA12878. This implements a pipeline that works in tandem with SNP and indel calling to detect larger structural variations like deletions, duplications, inversions and copy number variants (CNVs). - [Validation of tumor/normal calling](https://bcb.io/2015/03/05/cancerval/) using the synthetic DREAM validation set. This includes validation of additional callers against duplications, insertions and inversions. - [validation of germline DEL with HuRef benchmark](https://github.com/bcbio/bcbio_validations/blob/master/huref_sv/README.md) ## References - [Sarwal et al 2020. A comprehensive benchmarking of WGS-based structural variant callers](https://www.biorxiv.org/content/10.1101/2020.04.16.045120v4.full.pdf) - [Kosugi et al 2019. Comprehensive evaluation of structural variation detection algorithms for whole genome sequencing](https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1720-5) - See references to invidivual tools on the citations page. bcbio-nextgen-1.2.9/docs/contents/teaching.md000066400000000000000000000164301415626112400211460ustar00rootroot00000000000000# Teaching # Single cell RNA-seq analysis [Setting up bcbio single cell RNA-seq analysis](https://github.com/hbc/tutorials/blob/master/scRNAseq/scRNAseq_analysis_tutorial/lessons/01_bcbio_run.md) tutorial outlines the steps needed to run bcbio in that use case. # Cancer tumor-normal variant calling This is a teaching orientated example of using bcbio from the Cold Spring Harbor Laboratory's [Advanced Sequencing Technology and Applications course](https://meetings.cshl.edu/courses.aspx?course=C-SEQTEC&year=15). This uses cancer tumor normal data from the [ICGC-TCGA DREAM synthetic 3 challenge](https://www.synapse.org/#!Synapse:syn312572/wiki/58893), subset to exomes on chromosome 6 to reduce runtimes. It demonstrates: * Running a cancer tumor/normal workflow through bcbio. * Analysis with human genome build 38. * SNP and indel detection, with 3 variant callers and an ensemble method. * Structural variant calling, with 2 callers. * Prioritization of structural variants for cancer associated genes in [CIViC](https://civicdb.org/home). * HLA typing. * Validation of both small and structural variants against truth sets. ## Loading pre-run analysis To save downloading the genome data and running the analysis, we have a pre-prepared AMI with the data and analysis run. Use the [AWS Console](https://console.aws.amazon.com/ec2) to launch the pre-built AMI -- search Community AMIs for ami-5e84fe34. Any small instance type is fine for exploring the configuration, run directory and output files. Make sure you associate a public IP and a security group that allows remote ssh. Once launched, ssh into the remote machine with `ssh -i your-keypair ubuntu@public.ip.address` to explore the inputs and outputs. The default PATH contains bcbio and third party programs in `/usr/local/bin`, with the biological data installed in `/usr/local/share/bcbio`. The run is in a `~/run/cancer-syn3-chr6`. ## Input configuration file To run bcbio, you prepare a small configuration file describing your analysis. You can [prepare it manually or use an automated configuration method](configuration). The example has a pre-written configuration file with tumor/normal data located in the `config` directory and this section walks through the settings. You define the type of analysis (variant calling) along with the input files and genome build: ```yaml analysis: variant2 files: [../input/cancer-syn3-chr6-tumor-1.fq.gz, ../input/cancer-syn3-chr6-tumor-2.fq.gz] genome_build: hg38 ``` Sample description and assignment as a tumor sample, called together with a matched normal: ```yaml description: syn3-tumor metadata: batch: syn3 phenotype: tumor sex: female ``` Next it defines parameters for running the analysis. First we pick our aligner (bwa mem): ```yaml algorithm: aligner: bwa ``` Post-alignment, we mark duplicates but do not perform recalibration and realignment: ```yaml mark_duplicates: true recalibrate: false realign: false ``` We call variants in exome regions on chromosome 6 using a BED file input, call variants as low as 2% in the tumor sample, and use 3 variant callers along with an ensemble method that combines results for any found in 2 out of 3: ```yaml variant_regions: ../input/NGv3-chr6-hg38.bed min_allele_fraction: 2 variantcaller: [vardict, freebayes, varscan] ensemble: numpass: 2 ``` For structural variant calling, we use two callers and prioritize variants to those found in the CIViC database: ```yaml svcaller: [lumpy, manta] svprioritize: cancer/civic ``` Call HLA types with OptiType: ```yaml hlacaller: optitype ``` Finally, we validate both the small variants and structural variants. These use pre-installed validation sets that come with bcbio. We limit validation regions to avoid low complexity regions, which cause bias in [validating indels](http://bcb.io/2014/05/12/wgs-trio-variant-evaluation/): ```yaml exclude_regions: [lcr] validate: dream-syn3-crossmap/truth_small_variants.vcf.gz validate_regions: dream-syn3-crossmap/truth_regions.bed svvalidate: DEL: dream-syn3-crossmap/truth_DEL.bed DUP: dream-syn3-crossmap/truth_DUP.bed INV: dream-syn3-crossmap/truth_INV.bed ``` ## Output files Output files are in `~/run/cancer-syn3-chr6/final`, extracted from the full work directory in `~/run/cancer-syn3-chr6/work`. The directories with sample information are in `syn3-tumor/`. Aligned BAMs include a `-ready.bam` file with all of the original reads (including split and discordants) and separate files with only the split (`-sr.bam`) and discordant (`-disc.bam`) reads: ``` syn3-tumor-ready.bam syn3-tumor-ready.bam.bai syn3-tumor-sr.bam syn3-tumor-sr.bam.bai syn3-tumor-disc.bam syn3-tumor-disc.bam.bai ``` SNP and indel calls for 3 callers, plus combined ensemble calls: ``` syn3-tumor-ensemble.vcf.gz syn3-tumor-ensemble.vcf.gz.tbi syn3-tumor-freebayes.vcf.gz syn3-tumor-freebayes.vcf.gz.tbi syn3-tumor-varscan.vcf.gz syn3-tumor-varscan.vcf.gz.tbi syn3-tumor-vardict.vcf.gz syn3-tumor-vardict.vcf.gz.tbi ``` Structural variant calls for 2 callers, plus a simplified list of structural variants in cancer genes of interest: ``` syn3-tumor-sv-prioritize.tsv syn3-tumor-lumpy.vcf.gz syn3-tumor-lumpy.vcf.gz.tbi syn3-tumor-manta.vcf.gz syn3-tumor-manta.vcf.gz.tbi ``` HLA typing results: ``` syn3-tumor-hla-optitype.csv ``` Validation results from comparisons against truth set, including plots: ``` syn3-tumor-sv-validate.csv syn3-tumor-sv-validate-DEL.png syn3-tumor-sv-validate-df.csv syn3-tumor-sv-validate-DUP.png syn3-tumor-sv-validate-INV.png syn3-tumor-validate.png ``` The top level directory for the project, `2015-11-18_syn3-cshl/` has files relevant to the entire run. There is a consolidated quality control report: ``` multiqc/multiqc_report.html ``` Povenance information, with log files of all commands run and program versions used: ``` bcbio-nextgen.log bcbio-nextgen-commands.log programs.txt data_versions.csv ``` A top level summary of metrics for alignment, variant calling and coverage that is useful downstream: ``` project-summary.yaml ``` ## Preparing and Running The steps to prepare an AMI from a bare machine and run the analysis. These are pre-done on the teaching AMI to save time: 1. Use the [AWS Console](https://console.aws.amazon.com/ec2) to launch a Ubuntu Server 14.04 (ami-d05e75b8). Start an m4.4xlarge instance with a 100GB SSD. Make sure you associate a public IP and can ssh in externally. 1. SSH to your instance: ```shell ssh -i ~/.ec2/your-key.pem ubuntu@public-ip ``` 1. Install bcbio with hg38 data: ```shell sudo apt-get update sudo apt-get install -y build-essential zlib1g-dev wget curl python-setuptools git \ openjdk-7-jdk openjdk-7-jre ruby libncurses5-dev libcurl4-openssl-dev \ libbz2-dev unzip pigz bsdmainutils wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/scripts/bcbio_nextgen_install.py python bcbio_nextgen_install.py /usr/local/share/bcbio --tooldir /usr/local \ --genomes hg38 --aligners bwa --sudo --isolate -u development ``` 1. Install the analysis data: ```shell mkdir -p run cd run wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/teaching/cancer-syn3-chr6-prep.sh bash cancer-syn3-chr6-prep.sh ``` 1. Run the analysis: ```shell cd cancer-syn3-chr6/work bcbio_nextgen.py ../config/cancer-syn3-chr6.yaml -n 16 ``` bcbio-nextgen-1.2.9/docs/contents/users.md000066400000000000000000000117111415626112400205220ustar00rootroot00000000000000# Users A sample of institutions using bcbio-nextgen for solving biological problems. Please [submit](https://github.com/bcbio/bcbio-nextgen/blob/master/docs/contents/users.md) your story if you're using the pipeline in your own research. * [Harvard School of Public Health](https://bioinformatics.sph.harvard.edu/): We use bcbio-nextgen within the bioinformatics core for variant calling on large population studies related to human health like Breast Cancer and Alzheimer's disease. Increasing scalability of the pipeline has been essential for handling study sizes of more than 1400 whole genomes. * [Massachusetts General Hospital](https://molbio.mgh.harvard.edu/): The Department of Molecular Biology uses the pipeline to automatically process samples coming off Illumina HiSeq instruments. Automated pipelines perform alignment and sample-specific analysis, with results directly uploaded into a local [Galaxy](https://galaxyproject.org/) instance. * [Science for Life Laboratory](https://www.scilifelab.se/): The genomics core platform in the Swedish National Genomics Infrastructure ([NGI](https://www.scilifelab.se/platforms/ngi/)) has crunched over 16TBp (terabasepairs) and processed almost 7000+ samples from the beginning of 2013 until the end of July. [UPPMAX](https://www.uppmax.uu.se/projects-and-collaborations/compute-and-storage/), our cluster located in Uppsala runs the pipeline in production since 2010. * [Institute of Human Genetics, UCSF](https://humangenetics.ucsf.edu/): The Genomics Core Facility utilizes bcbio-nextgen in processing more than 2000 whole genome, exome, RNA-seq, ChIP-seq on various projects. This pipeline tremendously lowers the barrier of getting access to next generation sequencing technology. The community engaged here is also very helpful in providing best practices advices and up-to-date solution to ease scientific discovery. * [IRCCS "Mario Negri" Institute for Pharmacological Research](https://www.marionegri.it/): The Translational Genomics Unit in the Department of Oncology uses bcbio-nextgen for targeted resequencing (using an Illumina MiSeq) to identify mutations and other variants in tumor samples to investigate their link to tumor progression, patient survival and drug sensitivity and resistance. A [poster from the 2014 European Society of Human Genetics meeting](https://github.com/chapmanb/bcbb/blob/master/posters/beltrame_ESHG_poster_05_2014.reduced.pdf) provides more details on usage in ovarian cancer. A paper on the study of longitudinal ovarian cancer biopsies, which makes extensive use of bcbio-nextgen, [was published in 2015 in Annals of Oncology](https://doi.org/10.1093/annonc/mdv164). * [The Translational Genomics Research Institute (TGen)](https://www.tgen.org/): Members of the [Huentelman lab](https://www.tgen.org/faculty-profiles/matt-huentelman/) at TGen apply bcbio-nextgen to a wide variety of studies of with a major focus in the neurobiology of aging and neurodegeneration in collaboration with the The Arizona Alzheimer's Consortium ([AAC](http://azalz.org)) and the [McKnight Brain Research Foundation](https://mcknightbrain.org/). We also use bcbio in studies of rare diseases in children through TGen's Center for Rare Childhood Disorders ([C4RCD](https://www.tgen.org/patients/center-for-rare-childhood-disorders/)), and other rare diseases such as Multiple System Atrophy ([MSA](https://www.tgen.org/research-forms/neurological-disorders/multiple-system-atrophy/)). bcbio-nextgen has also been instrumental in projects for TGen's Program for Canine Health & Performance ([PCHP](https://www.tgen.org/patients/canine/)) and numerous RNA-seq projects using rodent models. Our work with bcbio started with a partnership with [Dell](https://www.dell.com) and The Neuroblastoma and Medulloblastoma Translational Research Consortium (NMTRC), and TGen as part of a Phase I clinical trial in these rare childhood cancers. * [Computer Science and Artificial Intelligence Laboratory (CSAIL), MIT](https://www.csail.mit.edu/): The [Gifford lab](https://cgs.csail.mit.edu/) uses the bcbio-nextgen pipeline to analyze a variety of sequencing datasets for their research in genetics and regulatory genomics (including the SysCode and [Stem Cell to Neuron](http://stemcell.mit.edu/) projects). The pipeline applies collaboratively-developed best practices for analysis as well as computation, which enables the lab to run the pipeline on local clusters and Amazon EC2. * [Sheffield Bioinformatics Core, The University of Sheffield](https://sbc.shef.ac.uk/): The Sheffield Bioinformatics Core is a relatively new Core facility at The University of Sheffield, and bcbio has been instrumental in setting-up a best-practice Bioinformatics analysis service. We employ bcbio to automate the analyses of RNA-seq, small RNA and ChiP-Seq datasets for researchers at The University of Sheffield and NIHR Biomedical Research Centre. In conjunction with the bcbioRNASeq Bioconductor package, we deliver publication-quality reports to our researchers based on reproducible analyses. bcbio-nextgen-1.2.9/docs/index.md000066400000000000000000000026461415626112400166420ustar00rootroot00000000000000![bcbio banner](contents/images/banner.png) A python toolkit providing best-practice pipelines for fully automated high throughput sequencing analysis. You write a high level configuration file specifying your inputs and analysis parameters. This input drives a parallel pipeline that handles distributed execution, idempotent processing restarts and safe transactional steps. The goal is to provide a shared community resource that handles the data processing component of sequencing analysis, providing researchers with more time to focus on the downstream biology. # Contents ```{toctree} --- maxdepth: 2 --- contents/intro.md ``` ```{toctree} --- maxdepth: 2 caption: User stories --- contents/somatic_variants.md contents/bulk_rnaseq.md contents/single_cell.md contents/purecn.md contents/hla_typing.md contents/germline_variants.md contents/3prime_dge.md contents/structural_variants.md contents/atac.md contents/methylation.md contents/rnaseq_variants.md contents/rnaseq_fusions.md contents/fast_rnaseq.md contents/disambiguation.md contents/small_rnaseq.md ``` ```{toctree} --- maxdepth: 2 caption: Infrastructure --- contents/installation.md contents/configuration.md contents/parallel.md contents/outputs.md contents/cwl.md contents/cloud.md contents/development.md ``` ```{toctree} --- maxdepth: 2 caption: Misc --- contents/users.md contents/internals.md contents/presentations.md contents/teaching.md contents/citations.md ``` bcbio-nextgen-1.2.9/docs/requirements-local.txt000066400000000000000000000001331415626112400215520ustar00rootroot00000000000000# install dependencies used by Read the Docs locally sphinx==2.1.2 sphinx_rtd_theme==0.4.3 bcbio-nextgen-1.2.9/docs/requirements.txt000066400000000000000000000000241415626112400204610ustar00rootroot00000000000000myst-parser==0.14.0 bcbio-nextgen-1.2.9/docs/templates/000077500000000000000000000000001415626112400171775ustar00rootroot00000000000000bcbio-nextgen-1.2.9/docs/templates/sidebar-links.html000066400000000000000000000005731415626112400226210ustar00rootroot00000000000000

Links

bcbio-nextgen-1.2.9/requirements-conda.txt000066400000000000000000000000241415626112400206130ustar00rootroot00000000000000bcbio-nextgen=1.2.8 bcbio-nextgen-1.2.9/requirements-dev.txt000066400000000000000000000000161415626112400203060ustar00rootroot00000000000000flake8 pytest bcbio-nextgen-1.2.9/requirements.txt000066400000000000000000000000251415626112400175320ustar00rootroot00000000000000bcbio-nextgen==1.2.8 bcbio-nextgen-1.2.9/scripts/000077500000000000000000000000001415626112400157405ustar00rootroot00000000000000bcbio-nextgen-1.2.9/scripts/ansible/000077500000000000000000000000001415626112400173555ustar00rootroot00000000000000bcbio-nextgen-1.2.9/scripts/ansible/README.md000066400000000000000000000335371415626112400206470ustar00rootroot00000000000000# Simplified bcbio cloud usage Many bcbio analyses can run on a single machine. A powerful multicore instance can run smaller numbers of samples, targeted sequencing, or non-time critical processing tasks without the overhead of spinning up a cluster and shared filesystem. This guide describes a simplified approach to run bcbio on [Amazon Web Services](https://aws.amazon.com/), [Google Cloud](https://cloud.google.com/) and [Microsoft Azure](https://azure.microsoft.com): - Install bcbio and your analysis on a persistent data volume. - Use an ansible script to launch an instance with the data volume attached. - Run bcbio analyses on the instance, stopping and changing instance sizes as needed to complete the run. This assumes familiarity with the cloud platform you choose and offers minimal automation compared to other [Cloud integration](http://bcbio-nextgen.readthedocs.io/en/latest/contents/cloud.html) within bcbio. The additional control over managing resources allows researchers to reduce costs and use spot or preemptible instances at the cost of requiring more hands on attention during runs. If runs fail or need custom downstream analysis you can stop the larger run instances and work with a smaller, cheaper machine. ## Cloud provider setup ### Amazon Web Services Tools used on your local machine: - [Ansible](http://docs.ansible.com/ansible/intro_installation.html) with [Dependencies and environmental variables for AWS access](http://docs.ansible.com/ansible/guide_aws.html) -- automate starting up instances - [saws](https://github.com/donnemartin/saws) -- manage and query running instances. - [bcbio-vm](http://bcbio-nextgen.readthedocs.io/en/latest/contents/cloud.html#aws-setup) -- automates creation of AWS resources Install these into an isolated conda environment and setup with: wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p tools ./tools/bin/conda install -c conda-forge -c bioconda python=3 bcbio-nextgen-vm ./tools/bin/pip install ansible saws boto ./tools/bin/aws configure Provide AWS access for bcbio-vm, ansible and saws using [IAM to create (or find) your access keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html): export AWS_ACCESS_KEY_ID='AK123' export AWS_SECRET_ACCESS_KEY='abc123' bcbio-vm has an automated script to setup the AWS infrastructure from running: bcbio_vm.py aws ansible us-east-1d --keypair Replace `us-east-1d` with the AWS availability zone you'd like to run in. This creates a `project_vars.yaml` file with the following information: - An AWS image ID for your region, selected from [Ubuntu Amazon EC2 AMI Locator](http://cloud-images.ubuntu.com/locator/ec2/) using an option with Instance Type `hvm:ebs-ssd`. - An AWS Virtual Private Cloud (VPC) subnet. - A security group allowing port 22 ssh access to the machines. - The name of a [keypair](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#KeyPairs:sort=keyName) to use for ssh access, where you have the private key stored locally. If you used the bcbio-vm automated setup, you'll have a private keypair in `~/.bcbio/aws_keypairs/bcbio`. - An IAM role that allows access to S3 resources. This makes it easier to push/pull data to the instance. You can also use the [AWS console](https://aws.amazon.com/) or saws to create these manually. Create a volume that will contain the run and bcbio installation. It should be in the same availability zone as specified above. You can create this in the AWS console in the Volumes tab, or using saws/aws: aws ec2 create-volume --encrypted --volume-type gp2 --size 300 --availability-zone us-east-1d aws ec2 create-tags --resources vol-00df42a6 --tags Key=Name,Value=exome-validation Add your volume ID to the `project_vars.yaml` configuration file: instance_type: t2.small spot_price: null volume: vol-50ed15c1 keypair: bcbio image_id: ami-6edd3078 vpc_subnet: subnet-3628576d iam_role: bcbio_full_s3_access security_group: bcbio_cluster_sg region: us-east-1 zone: us-east-1d Edit `~/.ssh/config` to enable clean connections to AWS instances: Host *.amazonaws.com StrictHostKeyChecking no UserKnownHostsFile=/dev/null IdentityFile /path/to/aws_keypairs/bcbio IdentitiesOnly yes ControlPath ~/.ssh/%r@%h:%p With this in place you can launch your instance with: ansible-playbook -i 'localhost,' -vvv launch_aws.yaml This creates the instance, attaches the data volume, mounts the volume as `/mnt/work` and installs basic system tools. Get the Public DNS name of the created machine with: saws> aws ec2 describe-instances | grep Public Then ssh into your machine with: ssh ubuntu@ec2-XX-XXX-XXX-XXX.compute-1.amazonaws.com On the first run with a new data volume, install bcbio and setup a work directory for running following the instructions in 'Running bcbio.' Then you're ready to run an analysis. This on-machine setup is the same across all cloud providers. When finished, terminate the current instance with: saws> aws ec2 terminate-instances --instance-ids i-xxxxxxx Your bcbio installation and analysis is in the separate data volume. When finished you can snapshot this for long term storage. ### Google Compute Tools used on your local machine: - [Ansible](http://docs.ansible.com/ansible/intro_installation.html) with [dependencies and environmental variables for Google Compute access](http://docs.ansible.com/ansible/guide_gce.html) -- automate starting up instances - [gloud from the Google Cloud SDK](https://cloud.google.com/sdk/) -- command line interface to access and manage instances. You can install with `bcbio_conda install -c conda-forge -c bioconda google-cloud-sdk` - [Web based console](https://console.cloud.google.com) Use the console to create a project to hold your analysis , then add [ssh key access to your project](https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys#project-wide). Then locally, [log into gcloud](https://cloud.google.com/compute/docs/gcloud-compute/) and select your project: gcloud init Create a disk to store bcbio and associated data: gcloud compute disks create dv-bcbio-vol --size 250GB --type pd-ssd --zone us-east1-b Finally [create credentials](http://docs.ansible.com/ansible/latest/scenario_guides/guide_gce.html#credentials) for connecting to your instance. These are key pairs used to automatically authenticate to created instances. To create, go to "APIs and Services", "Credentials", "Create credentials" and finally "Service account key", then download the json file with key pairs after creating it. You'll need the e-mail associated with the service account, found under "IAM and Admin." Use this information to create a `project_vars.yaml` configuration file: instance_type: n1-standard-1 image_id: ubuntu-1604-xenial-v20180323 zone: us-east1-b service_account_email: 129107966647-compute@developer.gserviceaccount.com credentials_file: /home/chapmanb/.ssh/gce/deepvariant-trustedtester-d4f7663f4adf.json project_id: deepvariant-trustedtester volume: dv-bcbio-vol run_name: dv-bcbio Launch your instance with: ansible-playbook -vvv launch_gce.yaml Then access the machine using your run name: gcloud compute ssh ubuntu@dv-bcbio When finished, you can terminate the instance with: gcloud compute instances delete dv-bcbio ### Microsoft Azure Tools used on your local machine: - [Ansible](http://docs.ansible.com/ansible/intro_installation.html) with [dependencies and service principal based environmental variables for Azure access](https://docs.ansible.com/ansible/guide_azure.html). -- automate starting up instances - [azure cross platform command line interface](https://github.com/Azure/azure-xplat-cli#features) -- command line interface to access and manage instances. You can install with `bcbio_conda install -c bioconda azure-cli` Create a file with your instance and run information called `project_vars.yaml`: instance_type: Standard_DS1_v2 run_name: giab-val-work storage_account_name: giabvalidation resource_group: giab-validation volume: giab-val-data image_id: publisher: Canonical offer: UbuntuServer sku: 16.04.0-LTS version: latest ssh_public_keys: - path: '/home/ubuntu/.ssh/authorized_keys' key_data: 'ssh-rsa Add your public key for connecting here' Launch your instance with: ansible-playbook -vvv launch_azure.yaml Then access the machine by finding the IP address and using ssh to attach: azure vm show giab-validation giab-val-work | grep Public ssh -i /path/to/your/private.key ubuntu@52.186.126.145 When finished, you can terminate the instance with: azure vm delete giab-validation giab-val-work ## Running bcbio On the first run you'll need to create a project directory to work in: sudo mkdir /mnt/work/your-project sudo chown ubuntu /mnt/work/your-project and [install bcbio](http://bcbio-nextgen.readthedocs.io/en/latest/contents/installation.html) on the working volume with the genomes and aligner indices you need: wget https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/scripts/bcbio_nextgen_install.py python bcbio_nextgen_install.py /mnt/work/bcbio --tooldir=/mnt/work/bcbio --genomes GRCh37 --aligners bwa To run CWL, you'll also want to [install bcbio-vm](https://bcbio-nextgen.readthedocs.io/en/latest/contents/cwl.html#getting-started) with: export TARGETDIR=/mnt/work/bcbio/bcbio-vm export BINDIR=/mnt/work/bcbio/bin And you're ready to do an analysis in `/mnt/work/your-project`. Add your samples, create a [project configuration](http://bcbio-nextgen.readthedocs.io/en/latest/contents/configuration.html#automated-sample-configuration) and then run the analysis from a work directory. Practically you can do all the bcbio installation and project setup with a smaller instance, shutdown that instance and spin up a larger one that matches your project needs for the actual run. For runs, the ansible script adds the bcbio installation to your path so start an analysis with: cd /mnt/work/your-project/work bcbio_nextgen.py ../config/your-project.yaml -n 16 To optimize resource usage, especially for single sample projects, edit `/mnt/work/bcbio/galaxy/bcbio_system.yaml` so cores and memory match your instance: default: memory: 3G cores: 16 jvm_opts: ["-Xms750m", "-Xmx3500m"] # Running with Toil This in progress documentation describes running bcbio generated CWL using [Toil autoscaling on AWS](http://toil.readthedocs.io/en/latest/running/cloud.html). - Find a [Docker Toil tag](https://quay.io/repository/ucsc_cgl/toil?tag=latest&tab=tags) corresponding to the version you're running (if not a stable release): curl -s 'https://quay.io/api/v1/repository/ucsc_cgl/toil/tag/?limit=20' \ | jq '.tags[] | (.name)' - Pick a VPC subnet to run in. This subnet needs to enable auto-assign public IP addresses. - Launch the cluster export TOIL_AWS_ZONE=us-east-1d export TOIL_APPLIANCE_SELF='quay.io/ucsc_cgl/toil:3.7.0a1.dev375-587871c5f4f219877af7d8e4f0a1c9544c510e65' toil launch-cluster -p aws bcbio --nodeType=t2.small --keyPairName=bcbio \ --vpcSubnet subnet-3628576d - Find local IP of machine (for Mesos LEADER_PRIVATE_IP): aws ec2 describe-instances | grep PrivateIp - Attach to Docker container in head node: toil ssh-cluster toil-bcbio - Run bcbio CWL toil test mkdir /home/run && cd /home/run wget -O test_bcbio_cwl.tar.gz https://github.com/bcbio/test_bcbio_cwl/archive/master.tar.gz tar -xzvpf test_bcbio_cwl.tar.gz cd test_bcbio_cwl-master bash run_toil_aws.sh Current discussion topics: - Need to be able to specify root volume sizes. Current 50Gb hardcoded default will fail for larger WGS samples and some test samples. - How does file staging work for shared files used in multiple steps, like BAMs for variant calling? Are they staged once on an AWS machine and re-used or pulled down multiple times? I'm running into disk space errors during runs which indicate they get pulled down multiple times and potentially not removed, or we have two jobs on the same machine with larger files. Re-starting the pipeline allows these jobs to finish. - Restarting jobs with/without `--no-container` while reusing job store. In general, can we adjust Toil parameters without needing to re-setup the jobStore? - Can we scale down proceses that request too many cores (8 cores on 4 core machine)? - Similarly, how does passing files back to the S3 file store work? The pipeline current stalls on `batch_for_variantcall` which isn't doing much processing work but does aggressively split to run variant calls in parallel, so it return a large number of outputs each of which has the BAM file. I don't see these written to the filestore on S3 but am trying to brainstorm reason why this step takes a very long time to run. - Consider how to deal with input files already present in external S3 buckets. Could we avoid copying these into the Toil work bucket if in the right region? - cgcloud versioning, need development version of Toil: https://github.com/BD2KGenomics/toil/issues/1458 - Swap to using Ubuntu instead of relying on manual CoreOS Amazon approvals. ## Debugging tips - Look up an appropriate CoreOS AMI for [your zone](https://github.com/BD2KGenomics/toil/issues/1470). This is only necessary if Toil can't automatically find an image: aws ec2 describe-images \ --output table --query 'Images[*].{AMI:ImageId,Description:Description}' \ --filters Name=owner-id,Values=679593333241 Name=description,Values='*stable*' export TOIL_AWS_AMI=ami-61659e77 bcbio-nextgen-1.2.9/scripts/ansible/ansible.cfg000066400000000000000000000000721415626112400214520ustar00rootroot00000000000000[ssh_connection] control_path = %(directory)s/%%h-%%p-%%r bcbio-nextgen-1.2.9/scripts/ansible/launch_aws.yaml000066400000000000000000000117031415626112400223670ustar00rootroot00000000000000# Launch analysis environment on AWS with existing data volume. # For bcbio analyses, volume expected to contain bcbio installation # in /mnt/work/bcbio # Makes it easy to stop/start analyses that fit on a single node and EBS volume. --- - hosts: localhost connection: local gather_facts: false tasks: - include_vars: project_vars.yaml - name: Launch EC2 instance register: ec2 local_action: module: ec2 group: "{{ security_group }}" instance_type: "{{ instance_type }}" spot_price: "{{ spot_price }}" image: "{{ image_id }}" keypair: "{{ keypair }}" vpc_subnet_id: "{{ vpc_subnet }}" instance_profile_name: "{{ iam_role }}" region: "{{ region }}" zone: "{{ zone }}" volumes: - device_name: /dev/sda1 volume_type: gp2 volume_size: 30 delete_on_termination: true assign_public_ip: yes count: 1 wait: yes state: present - name: Attach working volume local_action: ec2_vol instance={{ item.id }} id={{ volume }} device_name=/dev/xvdf state=present region={{ region }} with_items: "{{ ec2.instances }}" - name: Add new instance to host group local_action: module: add_host hostname: "{{ item.public_dns_name }}" groupname: launched # Get rid of SSH "Are you sure you want to continue connecting (yes/no)?" query ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' with_items: "{{ ec2.instances }}" - name: Wait for SSH local_action: wait_for host={{ item.public_ip }} port=22 state=started with_items: "{{ ec2.instances }}" - hosts: launched remote_user: ubuntu gather_facts: no pre_tasks: - raw: test -e /usr/bin/python || (sudo apt-get update && sudo apt-get update && sudo apt install -y python2.7-minimal python-simplejson) - action: setup tasks: - include_vars: project_vars.yaml - name: Check for nvme filesystem (m5+) stat: path: /dev/nvme1n1 register: isnvme - name: Symlink for nvme filesystems (m5+) file: src: /dev/nvme1n1 dest: /dev/xvdf state: link when: isnvme.stat.exists become: true - name: Create ext4 filesystem if not present filesystem: fstype=ext4 dev=/dev/xvdf become: true - name: Mount work volume become: true mount: name=/mnt/work src=/dev/xvdf fstype=ext4 state=mounted - name: Create bcbio directory if missing file: path=/mnt/work/bcbio state=directory owner=ubuntu become: true - name: Add bcbio to path lineinfile: line="export PATH=/mnt/work/bcbio/bin:$PATH" dest=~/.bashrc - apt: update_cache=yes become: true - apt: name="{{ item }}" become: true with_items: [git, unzip, wget, tar, gzip, bzip2] ignore_errors: true - name: Download docker get_url: url: https://get.docker.com dest: /tmp/docker-install.sh - name: Install docker become: true shell: bash /tmp/docker-install.sh - name: Add to docker group become: true shell: usermod -aG docker ubuntu - name: htcondor | Set up deb configuration for unattended install become: true shell: "{{ item }}" with_items: - echo "htcondor condor/wantdebconf boolean true" | debconf-set-selections - echo "htcondor condor/personal boolean true" | debconf-set-selections - name: htcondor | install become: true apt: name="htcondor" - name: htcondor | paritionable configuration become: true lineinfile: path: /etc/condor/condor_config.local regexp: "{{ item.regexp }}" line: "{{ item.line }}" with_items: - { regexp: '^MAX_SLOTS_TYPE =', line: 'MAX_SLOTS_TYPE = 1' } - { regexp: '^SLOT_TYPE_1 =', line: 'SLOT_TYPE_1 = cpus=100%, ram=100%, disk=100%, swap=100%' } - { regexp: '^SLOT_TYPE_1_PARTITIONABLE =', line: 'SLOT_TYPE_1_PARTITIONABLE = True' } - { regexp: '^NUM_SLOTS_TYPE_1 =', line: 'NUM_SLOTS_TYPE_1 = 1' } - name: htcondor | Restart condor become: yes command: service condor restart - name: Install Microsoft key and register product repository become: true apt: deb: https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb - name: Install apt-transport-https become: true apt: name: apt-transport-https state: latest - name: Install dotnet core become: true apt: name: dotnet-runtime-2.1 state: latest update_cache: yes # Optional launching of MySQL instance # Requires `ansible-galaxy install geerlingguy.mysql` # and configuration in project_vars.yaml # https://github.com/geerlingguy/ansible-role-mysql # - hosts: launched # remote_user: ubuntu # become: yes # vars_files: # - project_vars.yaml # roles: # - { role: geerlingguy.mysql } bcbio-nextgen-1.2.9/scripts/ansible/launch_azure.yaml000066400000000000000000000057741415626112400227360ustar00rootroot00000000000000# Launch analysis environment on Google Cloud with existing data volume. # For bcbio analyses, volume expected to contain bcbio installation # in /mnt/work/bcbio # Makes it easy to stop/start analyses that fit on a single node and disk. # # Notes # Add login information: # https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/ # New portal: https://portal.azure.com # Classic portal: https://manage.windowsazure.com # CLI: azure role assignment create --objectId xxx -o Owner -c /subscriptions/xxx # # Use resource manager _rm_ versions of Ansible # https://docs.ansible.com/ansible/guide_azure.html # # Persistent storage # https://azure.microsoft.com/en-us/documentation/articles/storage-azure-cli/ # https://azure.microsoft.com/en-us/documentation/articles/storage-how-to-use-files-linux/ # Or create initial data disk # azure storage container create # # resize instance: azure vm set --vm-size Standard_A3 qr1hi qr1hi-lightning-dev3-shell # # Other ansible examples: # https://github.com/harishbagewadielluru/ansible-azure # # Permissions issues creating Compute VMs # https://social.msdn.microsoft.com/Forums/Windowsserver/en-US/3878c3ee-d59e-486f-ae17-bcbe2f071bf1/user-cant-create-new-vm-despite-owning-the-resource-group?forum=windowsazuremanagement --- - hosts: localhost connection: local gather_facts: false tasks: - include_vars: project_vars.yaml - name: Launch instance azure_rm_virtualmachine: image: '{{ image_id }}' vm_size: '{{ instance_type }}' name: '{{ run_name }}' resource_group: '{{ resource_group }}' storage_account_name: '{{ storage_account_name }}' admin_username: ubuntu ssh_password_enabled: false ssh_public_keys: '{{ ssh_public_keys }}' os_type: Linux register : azure - name: Find public IP of new machine shell: azure vm show {{ resource_group }} {{ run_name }} | grep 'Public IP address' | awk -F ':' '{print $3}' register: public_ip - name: Add new instance to host group local_action: add_host hostname={{ public_ip.stdout }} groupname=launched - name: Wait for SSH local_action: wait_for host={{ public_ip.stdout }} port=22 state=started - name: Attach working volume command: azure vm disk attach {{ resource_group }} {{ run_name }} https://{{ storage_account_name }}.blob.core.windows.net/vhds/{{ volume }}.vhd - name: Get rid of SSH "Are you sure you want to continue connecting (yes/no)?" query shell: ssh-keyscan {{ public_ip.stdout }} >> $HOME/.ssh/known_hosts - hosts: launched remote_user: ubuntu gather_facts: true tasks: - include_vars: project_vars.yaml - name: Mount work volume become: true mount: name=/disk/work src=/dev/sdc fstype=ext4 state=mounted - name: Add bcbio to path lineinfile: line="export PATH=/disk/work/bcbio/bin:$PATH" dest=~/.bashrc - apt: name="{{ item }}" update_cache=yes become: true with_items: [git, unzip, wget, tar, gzip, bzip2] bcbio-nextgen-1.2.9/scripts/ansible/launch_gce.yaml000066400000000000000000000104171415626112400223340ustar00rootroot00000000000000# Launch analysis environment on Google Cloud with existing data volume. # For bcbio analyses, volume expected to contain bcbio installation # in /mnt/work/bcbio # Makes it easy to stop/start analyses that fit on a single node and disk. --- - hosts: localhost connection: local gather_facts: false tasks: - include_vars: project_vars.yaml - name: Launch instance register: gce local_action: module: gce machine_type: "{{ instance_type }}" image: "{{ image_id }}" name: "{{ run_name }}" zone: "{{ zone }}" disk_size: 30 persistent_boot_disk: true service_account_email: "{{ service_account_email }}" credentials_file: "{{ credentials_file }}" project_id: "{{ project_id }}" state: present - name: Attach working volume local_action: module: gce_pd instance_name: "{{ item.name }}" name: "{{ volume }}" mode: "READ_WRITE" zone: "{{ zone }}" service_account_email: "{{ service_account_email }}" credentials_file: "{{ credentials_file }}" project_id: "{{ project_id }}" state: present with_items: "{{ gce.instance_data }}" - name: Wait for SSH local_action: wait_for host={{ item.public_ip }} port=22 state=started delay=30 timeout=900 search_regex=Ubuntu with_items: "{{ gce.instance_data }}" - name: Add new instance to host group local_action: module: add_host hostname: "{{ item.public_ip }}" groupname: launched # Get rid of SSH "Are you sure you want to continue connecting (yes/no)?" query ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' with_items: "{{ gce.instance_data }}" - hosts: launched remote_user: ubuntu gather_facts: true tasks: - include_vars: project_vars.yaml - name: Create ext4 filesystem if not present filesystem: fstype=ext4 dev=/dev/disk/by-id/google-{{ volume }} become: true - name: Mount work volume become: true mount: name=/mnt/work src=/dev/disk/by-id/google-{{ volume }} fstype=ext4 state=mounted - name: Create bcbio directory if missing file: path=/mnt/work/bcbio state=directory owner=ubuntu become: true - name: Add bcbio to path lineinfile: line="export PATH=/mnt/work/bcbio/bin:$PATH" dest=~/.bashrc - apt: update_cache=yes become: true - apt: name="{{ item }}" update_cache=yes become: true with_items: [git, unzip, wget, tar, gzip, bzip2] - name: Download docker get_url: url: https://get.docker.com dest: /tmp/docker-install.sh - name: Install docker become: true shell: bash /tmp/docker-install.sh - name: Add to docker group become: true shell: usermod -aG docker ubuntu - name: htcondor | Set up deb configuration for unattended install become: true shell: "{{ item }}" with_items: - echo "htcondor condor/wantdebconf boolean true" | debconf-set-selections - echo "htcondor condor/personal boolean true" | debconf-set-selections - name: htcondor | install become: true apt: name="htcondor" - name: htcondor | paritionable configuration become: true lineinfile: path: /etc/condor/condor_config.local regexp: "{{ item.regexp }}" line: "{{ item.line }}" with_items: - { regexp: '^MAX_SLOTS_TYPE =', line: 'MAX_SLOTS_TYPE = 1' } - { regexp: '^SLOT_TYPE_1 =', line: 'SLOT_TYPE_1 = cpus=100%, ram=100%, disk=100%, swap=100%' } - { regexp: '^SLOT_TYPE_1_PARTITIONABLE =', line: 'SLOT_TYPE_1_PARTITIONABLE = True' } - { regexp: '^NUM_SLOTS_TYPE_1 =', line: 'NUM_SLOTS_TYPE_1 = 1' } - name: htcondor | Restart condor become: yes command: service condor restart - name: Install Microsoft key and register product repository become: true apt: deb: https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb - name: Install apt-transport-https become: true apt: name: apt-transport-https state: latest - name: Install dotnet core become: true apt: name: dotnet-runtime-2.0.7 state: latest update_cache: yes bcbio-nextgen-1.2.9/scripts/bcbio_fastq_umi_prep.py000077500000000000000000000263651415626112400225050ustar00rootroot00000000000000#!/usr/bin/env python """Convert fastq inputs into paired inputs with UMIs in read names. Handles three cases: - Separate UMI read files (read 1, read 2, UMI) Usage: bcbio_fastq_umi_prep.py single or: bcbio_fastq_umi_prep.py autopair [ ] - Duplex barcodes where the tags are incorporated into read 1 and read 2 Usage: bcbio_fastq_umi_prep.py single --tag1 5 --tag2 5 or: bcbio_fastq_umi_prep.py autopair --tag1 5 --tag2 5 [ ] - Adds UMI_ to fastq line1 of Dragen's UMI output, input is R1.fq.gz and R2.fq.gz Creates two fastq files with embedded UMIs: _R1.fq.gz _R2.fq.gz or a directory of fastq files with UMIs added to the names. autopair assumes 3 sets of reads based on the way bcl2fastq exports index reads: - R1 -- The first read pair - R2 -- The UMI barcode reads - R3 -- The second read pair If you're using a different approach to generate the UMIs, please maintain the same R1/R2/R3 naming scheme. """ from __future__ import print_function import argparse import math import os import sys import gzip import itertools from bcbio import utils from bcbio.bam import fastq from bcbio.provenance import do from bcbio.distributed.multi import run_multicore, zeromq_aware_logging transform_json = r"""{ "read1": "(?P@.*)\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(?P@.*)\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read3": "(@.*)\\n(?P.*)\\n\\+(.*)\\n(.*)\\n" } """ duplex_transform = r"""{ "read1": "(?P@.*)\\n(?P.{%s})(?P.*)\\n\\+(.*)\\n(.{%s})(?P.*)\\n", "read2": "(?P@.*)\\n(?P.{%s})(?P.*)\\n\\+(.*)\\n(.{%s})(?P.*)\\n" }""" r1_transform = r"""{ "read1": "(?P@.*)\\n(?P.{%s})(?P.*)\\n\\+(.*)\\n(.{%s})(?P.*)\\n", "read2": "(?P@.*)\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", }""" r2_transform = r"""{ "read1": "(?P@.*)\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(?P@.*)\\n(?P.{%s})(?P.*)\\n\\+(.*)\\n(.{%s})(?P.*)\\n" }""" def run_single(args): tags = [args.tag1, args.tag2] if args.tag1 and args.tag2 else None if args.umi_fq and not tags: add_umis_to_fastq(args.out_base, args.read1_fq, None, args.umi_fq, tags, cores=args.cores) add_umis_to_fastq(args.out_base, None, args.read2_fq, args.umi_fq, tags, cores=args.cores) else: add_umis_to_fastq(args.out_base, args.read1_fq, args.read2_fq, args.umi_fq, tags, cores=args.cores) @utils.map_wrap @zeromq_aware_logging def add_umis_to_fastq_parallel(out_base, read1_fq, read2_fq, umi_fq, tags, cores, config): add_umis_to_fastq(out_base, read1_fq, read2_fq, umi_fq, tags, cores) def add_umis_to_fastq(out_base, read1_fq, read2_fq, umi_fq, tags=None, cores=1): print("Adding UMIs from", umi_fq, "to read headers in", " ".join([x for x in [read1_fq, read2_fq] if x])) out1_fq = out_base + "_R1.fq.gz" out2_fq = out_base + "_R2.fq.gz" if umi_fq and not tags: if read1_fq: assert not read2_fq return _add_umis_with_fastp(read1_fq, umi_fq, out1_fq, cores) else: assert read2_fq return _add_umis_with_fastp(read2_fq, umi_fq, out2_fq, cores) transform_json_file = out_base + "-transform.json" with open(transform_json_file, "w") as out_handle: if tags: tag1, tag2 = tags if tag1 and tag2: out_handle.write(duplex_transform % (tag1, tag1, tag2, tag2)) elif tag1: out_handle.write(r1_transform % (tag1, tag1)) else: out_handle.write(r2_transform % (tag2, tag2)) else: out_handle.write(transform_json) with utils.open_gzipsafe(read1_fq) as in_handle: ex_name = in_handle.readline().split(" ") fastq_tags_arg = "--keep_fastq_tags" if len(ex_name) == 2 else "" tag_arg = "--separate_cb" if tags else "" cmd = ("umis fastqtransform {fastq_tags_arg} {tag_arg} " "--fastq1out >(bgzip --threads {cores} -c > {out1_fq}) " "--fastq2out >(bgzip --threads {cores} -c > {out2_fq}) " "{transform_json_file} {read1_fq} " "{read2_fq}") if umi_fq: cmd += " {umi_fq}" do.run(cmd.format(**locals()), "Add UMIs to paired fastq files") os.remove(transform_json_file) def _add_umis_with_fastp(read_fq, umi_fq, out_fq, cores): """Add UMIs to reads from separate UMI file using fastp. """ with utils.open_gzipsafe(umi_fq) as in_handle: in_handle.readline() # name umi_size = len(in_handle.readline().strip()) cmd = ("fastp -Q -A -L -G -w 1 --in1 {read_fq} --in2 {umi_fq} " "--umi --umi_prefix UMI --umi_loc read2 --umi_len {umi_size} " "--out1 >(bgzip --threads {cores} -c > {out_fq}) --out2 /dev/null " "-j /dev/null -h /dev/null") do.run(cmd.format(**locals()), "Add UMIs to fastq file with fastp") def run_autopair(args): outdir = utils.safe_makedir(args.outdir) to_run = [] extras = [] for fnames in fastq.combine_pairs(sorted(args.files)): if len(fnames) == 2: to_run.append(fnames) elif len(fnames) == 3: r1, r2, r3 = sorted(fnames) to_run.append([r1, r2]) extras.append(r3) else: assert len(fnames) == 1, fnames extras.append(fnames[0]) ready_to_run = [] tags = [args.tag1, args.tag2] if args.tag1 and args.tag2 else None if not tags: # Aim for 2 or 3 simultaneous processes, each with multiple cores target_processes = 2 process_cores = max(1, (args.cores // target_processes) + (args.cores % target_processes)) overall_processes = max(1, int(math.ceil(args.cores / float(process_cores)))) else: process_cores = 1 overall_processes = args.cores for r1, r2 in to_run: target = _commonprefix([r1, r2]) if tags: base_name = os.path.join(outdir, os.path.basename(_commonprefix([r1, r2]))) umi = None else: r3 = None for test_r3 in extras: if (_commonprefix([r1, test_r3]) == target and _commonprefix([r2, test_r3]) == target): r3 = test_r3 break assert r3, (r1, r2, extras) base_name = os.path.join(outdir, os.path.basename(_commonprefix([r1, r2, r3]))) r1, r2, umi = _find_umi([r1, r2, r3]) # fastp handles a single pair of reads so we split processing to run on each if umi and not tags: ready_to_run.append([base_name, r1, None, umi, None, process_cores, {"algorithm": {}, "resources": {}}]) ready_to_run.append([base_name, None, r2, umi, None, process_cores, {"algorithm": {}, "resources": {}}]) else: ready_to_run.append([base_name, r1, r2, umi, tags, process_cores, {"algorithm": {}, "resources": {}}]) parallel = {"type": "local", "cores": overall_processes, "progs": []} run_multicore(add_umis_to_fastq_parallel, ready_to_run, {"algorithm": {}}, parallel) def _add_umi_str(fq_header): ar = fq_header.split(" ") ar1 = ar[0].split(":") prefix = ar1[:-1] suffix = ar1[-1] new_suffix = "UMI_" + suffix ending = ar[1].strip() new_header = ":".join(prefix) + ":" + new_suffix + " " + ending return new_header def run_dragen(args): to_run = [] outdir = utils.safe_makedir(args.outdir) for fnames in fastq.combine_pairs(sorted(args.files)): to_run.append(fnames) for r1, r2 in to_run: out1_fq = os.path.join(outdir, r1) out2_fq = os.path.join(outdir, r2) n = 0 with utils.open_gzipsafe(r1) as r1_handle, \ utils.open_gzipsafe(r2) as r2_handle, \ gzip.open(out1_fq, "wb") as out1_handle, \ gzip.open(out2_fq, "wb") as out2_handle: for line1, line2 in itertools.zip_longest(r1_handle, r2_handle): if line1 is not None: if n%4 == 0: # parse header line new_header1 = _add_umi_str(line1) + "\n" new_header2 = _add_umi_str(line2) + "\n" out1_handle.write(new_header1.encode()) out2_handle.write(new_header2.encode()) else: out1_handle.write(line1.encode()) out2_handle.write(line2.encode()) n += 1 def _find_umi(files): """Find UMI file using different naming schemes. R1/R2/R3 => R1/R3 with R2 UMI R1/R2/I1 => R1/R2 with I1 UMI """ base = os.path.basename(_commonprefix(files)) def _file_ext(f): exts = utils.splitext_plus(os.path.basename(f).replace(base, ""))[0].split("_") exts = [x for x in exts if x] return exts[0] exts = dict([(_file_ext(f), f) for f in files]) if "I1" in exts: return exts["R1"], exts["R2"], exts["I1"] else: assert "R3" in exts, exts return exts["R1"], exts["R3"], exts["R2"] def _commonprefix(files): """Retrieve a common prefix for files without extra _R1 _I1 extensions. Allows alternative naming schemes (R1/R2/R3) (R1/R2/I1). """ out = os.path.commonprefix(files) out = out.rstrip("_R") out = out.rstrip("_I") out = out.rstrip("_") return out if __name__ == "__main__": parser = argparse.ArgumentParser(description="Add UMIs to fastq read names") sp = parser.add_subparsers(title="[sub-commands]") p = sp.add_parser("autopair", help="Automatically pair R1/R2 (and maybe R3) fastq inputs") p.add_argument("-c", "--cores", default=1, type=int, help="Number of cores, allowing running samples in parallel") p.add_argument("--outdir", default="with_umis", help="Output directory to write UMI prepped fastqs") p.add_argument("--tag1", help="Duplex read 1 tag -- bases to trim from 5' end") p.add_argument("--tag2", help="Duplex read 2 tag -- bases to trim from 5' end") p.add_argument("files", nargs="*", help="All fastq files to pair and process") p.set_defaults(func=run_autopair) p = sp.add_parser("single", help="Run single set of fastq files with UMIs/duplexes") p.add_argument("-c", "--cores", default=1, type=int, help="Number of cores to use for parallel bgzip") p.add_argument("--tag1", help="Duplex read 1 tag -- bases to trim from 5' end", type=int) p.add_argument("--tag2", help="Duplex read 2 tag -- bases to trim from 5' end", type=int) p.add_argument("out_base", help="Base name for output files -- you get _R1.fq.gz") p.add_argument("read1_fq", help="Input fastq, read 1") p.add_argument("read2_fq", help="Input fastq, read 2") p.add_argument("umi_fq", help="Input fastq, UMIs", nargs="?") p.set_defaults(func=run_single) p = sp.add_parser("dragen", help="Make Dragen UMI input suitable for bcbio") p.add_argument("--outdir", default="with_umis", help="Output directory to write UMI prepped fastqs") p.add_argument("files", nargs="*", help="All fastq files to pair and process") p.set_defaults(func=run_dragen) if len(sys.argv) == 1: parser.print_help() args = parser.parse_args() args.func(args) bcbio-nextgen-1.2.9/scripts/bcbio_nextgen.py000077500000000000000000000256621415626112400211360ustar00rootroot00000000000000#!/usr/bin/env python -Es """Run an automated analysis pipeline for high throughput sequencing data. Handles runs in local or distributed mode based on the command line or configured parameters. The is a global YAML configuration file specifying details about the system. An example configuration file is in 'config/bcbio_system.yaml'. This is optional for automated installations. is an optional parameter specifying a directory of Illumina output or fastq files to process. If configured to connect to a Galaxy LIMS system, this can retrieve run information directly from Galaxy for processing. is an optional file that specifies details about the flowcell lanes, instead of retrieving it from Galaxy. An example configuration file is located in 'config/bcbio_sample.yaml' This allows running on files in arbitrary locations with no connection to Galaxy required. Usage: bcbio_nextgen.py [] [] -t type of parallelization to use: - local: Non-distributed, possibly multiple if n > 1 (default) - ipython: IPython distributed processing -n total number of processes to use -s scheduler for ipython parallelization (lsf, sge, slurm, torque, pbspro) -q queue to submit jobs for ipython parallelization """ from __future__ import print_function import os import argparse import sys from bcbio.setpath import prepend_bcbiopath prepend_bcbiopath() from bcbio import install, utils, workflow from bcbio.illumina import machine from bcbio.distributed import runfn, clargs from bcbio.pipeline.main import run_main from bcbio.graph import graph from bcbio.provenance import programs from bcbio.pipeline import version def main(**kwargs): run_main(**kwargs) def parse_cl_args(in_args): """Parse input commandline arguments, handling multiple cases. Returns the main config file and set of kwargs. """ sub_cmds = {"upgrade": install.add_subparser, "runfn": runfn.add_subparser, "graph": graph.add_subparser, "version": programs.add_subparser, "sequencer": machine.add_subparser} description = "Community developed high throughput sequencing analysis." parser = argparse.ArgumentParser(description=description) sub_cmd = None if len(in_args) > 0 and in_args[0] in sub_cmds: subparser_help = "bcbio-nextgen supplemental commands" subparsers = parser.add_subparsers(help=subparser_help) sub_cmds[in_args[0]](subparsers) sub_cmd = in_args[0] else: parser.add_argument("global_config", nargs="?", help=("Global YAML configuration file specifying " "details about the system (optional, " "defaults to installed bcbio_system.yaml)")) parser.add_argument("fc_dir", nargs="?", help=("A directory of Illumina output or fastq " "files to process (optional)")) parser.add_argument("run_config", nargs="*", help=("YAML file with details about samples to " "process (required, unless using Galaxy " "LIMS as input)")), parser.add_argument("-n", "--numcores", type=int, default=1, help="Total cores to use for processing") parser.add_argument("-t", "--paralleltype", choices=["local", "ipython"], default="local", help="Approach to parallelization") parser.add_argument("-s", "--scheduler", choices=["lsf", "sge", "torque", "slurm", "pbspro"], help="Scheduler to use for ipython parallel") parser.add_argument("--local_controller", default=False, action="store_true", help="run controller locally") parser.add_argument("-q", "--queue", help=("Scheduler queue to run jobs on, for " "ipython parallel")) parser.add_argument("-r", "--resources", help=("Cluster specific resources specifications. " "Can be specified multiple times.\n" "Supports SGE, Torque, LSF and SLURM " "parameters."), default=[], action="append") parser.add_argument("--timeout", default=15, type=int, help=("Number of minutes before cluster startup " "times out. Defaults to 15")) parser.add_argument("--retries", default=0, type=int, help=("Number of retries of failed tasks during " "distributed processing. Default 0 " "(no retries)")) parser.add_argument("-p", "--tag", help="Tag name to label jobs on the cluster", default="") parser.add_argument("-w", "--workflow", help=("Run a workflow with the given commandline " "arguments")) parser.add_argument("--workdir", default=os.getcwd(), help=("Directory to process in. Defaults to " "current working directory")) parser.add_argument("-v", "--version", help="Print current version", action="store_true") # Hidden arguments passed downstream parser.add_argument("--only-metadata", help=argparse.SUPPRESS, action="store_true", default=False) parser.add_argument("--force-single", help="Treat all files as single reads", action="store_true", default=False) parser.add_argument("--separators", help="comma separated list of separators that indicates paired files.", default="R,_,-,.") args = parser.parse_args(in_args) if hasattr(args, "workdir") and args.workdir: args.workdir = utils.safe_makedir(os.path.abspath(args.workdir)) if hasattr(args, "global_config"): error_msg = _sanity_check_args(args) if error_msg: parser.error(error_msg) kwargs = {"parallel": clargs.to_parallel(args), "workflow": args.workflow, "workdir": args.workdir} kwargs = _add_inputs_to_kwargs(args, kwargs, parser) error_msg = _sanity_check_kwargs(kwargs) if error_msg: parser.error(error_msg) else: assert sub_cmd is not None kwargs = {"args": args, "config_file": None, sub_cmd: True} return kwargs def _sanity_check_args(args): """Ensure dependent arguments are correctly specified """ if "scheduler" in args and "queue" in args: if args.scheduler and not args.queue: if args.scheduler != "sge": return "IPython parallel scheduler (-s) specified. This also requires a queue (-q)." elif args.queue and not args.scheduler: return "IPython parallel queue (-q) supplied. This also requires a scheduler (-s)." elif args.paralleltype == "ipython" and (not args.queue or not args.scheduler): return "IPython parallel requires queue (-q) and scheduler (-s) arguments." def _sanity_check_kwargs(args): """Sanity check after setting up input arguments, handling back compatibility """ if not args.get("workflow") and not args.get("run_info_yaml"): return ("Require a sample YAML file describing inputs: " "https://bcbio-nextgen.readthedocs.org/en/latest/contents/configuration.html") def _add_inputs_to_kwargs(args, kwargs, parser): """Convert input system config, flow cell directory and sample yaml to kwargs. Handles back compatibility with previous commandlines while allowing flexible specification of input parameters. """ inputs = [x for x in [args.global_config, args.fc_dir] + args.run_config if x is not None] global_config = "bcbio_system.yaml" # default configuration if not specified if kwargs.get("workflow", "") == "template": if args.only_metadata: inputs.append("--only-metadata") if args.force_single: inputs.append("--force-single") if args.separators: inputs.extend(["--separators", args.separators]) kwargs["inputs"] = inputs return kwargs elif len(inputs) == 1: if os.path.isfile(inputs[0]): fc_dir = None run_info_yaml = inputs[0] else: fc_dir = inputs[0] run_info_yaml = None elif len(inputs) == 2: if os.path.isfile(inputs[0]): global_config = inputs[0] if os.path.isfile(inputs[1]): fc_dir = None run_info_yaml = inputs[1] else: fc_dir = inputs[1] run_info_yaml = None else: fc_dir, run_info_yaml = inputs elif len(inputs) == 3: global_config, fc_dir, run_info_yaml = inputs elif args.version: print(version.__version__) sys.exit() else: print("Incorrect input arguments", inputs) parser.print_help() sys.exit() if fc_dir: fc_dir = os.path.abspath(fc_dir) if run_info_yaml: run_info_yaml = os.path.abspath(run_info_yaml) if kwargs.get("workflow"): kwargs["inputs"] = inputs kwargs["config_file"] = global_config kwargs["fc_dir"] = fc_dir kwargs["run_info_yaml"] = run_info_yaml print(f"Running bcbio version: {version.__version__}") if global_config: print(f"global config: {os.path.abspath(global_config)}") if fc_dir: print(f"flowcell directory: {os.path.abspath(fc_dir)}") if run_info_yaml: print(f"run info config: {os.path.abspath(run_info_yaml)}") return kwargs if __name__ == "__main__": kwargs = parse_cl_args(sys.argv[1:]) if "upgrade" in kwargs and kwargs["upgrade"]: install.upgrade_bcbio(kwargs["args"]) elif "runfn" in kwargs and kwargs["runfn"]: runfn.process(kwargs["args"]) elif "graph" in kwargs and kwargs["graph"]: graph.bootstrap(kwargs["args"]) elif "version" in kwargs and kwargs["version"]: programs.write_versions({"work": kwargs["args"].workdir}) elif "sequencer" in kwargs and kwargs["sequencer"]: machine.check_and_postprocess(kwargs["args"]) else: if kwargs.get("workflow"): setup_info = workflow.setup(kwargs["workflow"], kwargs.pop("inputs")) if setup_info is None: # no automated run after setup sys.exit(0) workdir, new_kwargs = setup_info os.chdir(workdir) kwargs.update(new_kwargs) main(**kwargs) bcbio-nextgen-1.2.9/scripts/bcbio_nextgen_install.py000077500000000000000000000333151415626112400226560ustar00rootroot00000000000000#!/usr/bin/env python """Automatically install required tools and data to run bcbio-nextgen pipelines. This automates the steps required for installation and setup to make it easier to get started with bcbio-nextgen. The defaults provide data files for human variant calling. Requires: git, wget, bgzip2, Python 3 or 2.7 """ from __future__ import print_function import argparse import collections import contextlib import datetime import os import platform import shutil import subprocess import sys try: import urllib2 as urllib_request except ImportError: import urllib.request as urllib_request REMOTES = { "requirements": "https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/requirements-conda.txt", "gitrepo": "https://github.com/bcbio/bcbio-nextgen.git", "system_config": "https://raw.githubusercontent.com/bcbio/bcbio-nextgen/master/config/bcbio_system.yaml", "anaconda": "https://repo.anaconda.com/miniconda/Miniconda3-py37_4.10.3-%s-x86_64.sh" } def main(args, sys_argv): check_arguments(args) check_dependencies() with bcbio_tmpdir(): setup_data_dir(args) print("Installing isolated base python installation") anaconda = install_anaconda_python(args) if args.use_mamba: conda_bin = "mamba" else: conda_bin = "conda" print(f"Installing {conda_bin}") anaconda = install_mamba(anaconda, args) print("Installing conda-build") subprocess.check_call([anaconda[conda_bin], "install", "--yes", "conda-build"]) print("Installing bcbio-nextgen") bcbio = install_conda_pkgs(anaconda, args) bootstrap_bcbionextgen(anaconda, args) print("Installing data and third party dependencies") system_config = write_system_config(REMOTES["system_config"], args.datadir, args.tooldir) setup_manifest(args.datadir) subprocess.check_call([bcbio, "upgrade"] + _clean_args(sys_argv, args)) print("Finished: bcbio-nextgen, tools and data installed") print(" Genome data installed in:\n %s" % args.datadir) if args.tooldir: print(" Tools installed in:\n %s" % args.tooldir) print(" Ready to use system configuration at:\n %s" % system_config) print(" Edit configuration file as needed to match your machine or cluster") def _clean_args(sys_argv, args): """Remove data directory from arguments to pass to upgrade function remove --mamba""" base = [x for x in sys_argv if x.startswith("-") or not args.datadir == os.path.abspath(os.path.expanduser(x))] # Remove installer only options we don't pass on base = [x for x in base if x not in set(["--minimize-disk"])] if "--nodata" in base: base.remove("--nodata") else: base.append("--data") if "--mamba" in base: base.remove("--mamba") return base def bootstrap_bcbionextgen(anaconda, args): if args.upgrade == "development": git_tag = "@%s" % args.revision if args.revision != "master" else "" subprocess.check_call([anaconda["pip"], "install", "--upgrade", "--no-deps", "git+%s%s#egg=bcbio-nextgen" % (REMOTES["gitrepo"], git_tag)]) def install_mamba(anaconda, args): """ Install conda or mamba""" if args.use_mamba: conda_bin = "mamba" else: conda_bin = "conda" anaconda_dir = os.path.join(args.datadir, "anaconda") bindir = os.path.join(anaconda_dir, "bin") mamba = os.path.join(bindir, conda_bin) subprocess.check_call([anaconda["conda"], "install", "--yes", conda_bin]) anaconda[conda_bin] = mamba return anaconda def install_conda_pkgs(anaconda, args): env = dict(os.environ) # Try to avoid user specific pkgs and envs directories # https://github.com/conda/conda/issues/6748 env["CONDA_PKGS_DIRS"] = os.path.join(anaconda["dir"], "pkgs") env["CONDA_ENVS_DIRS"] = os.path.join(anaconda["dir"], "envs") conda_bin = anaconda["conda"] if "mamba" in anaconda.keys(): mamba_bin = anaconda["mamba"] else: mamba_bin = anaconda["conda"] if not os.path.exists(os.path.basename(REMOTES["requirements"])): subprocess.check_call(["wget", "--no-check-certificate", REMOTES["requirements"]]) if args.minimize_disk: subprocess.check_call([mamba_bin, "install", "--yes", "nomkl"], env=env) subprocess.check_call([mamba_bin, "install", "--yes", "--only-deps", "bcbio-nextgen"], env=env) subprocess.check_call([conda_bin, "install", "--yes", "--file", os.path.basename(REMOTES["requirements"])], env=env) return os.path.join(anaconda["dir"], "bin", "bcbio_nextgen.py") def _guess_distribution(): """Simple approach to identify if we are on a MacOSX or Linux system for Anaconda""" if platform.mac_ver()[0]: return "macosx" else: return "linux" def install_anaconda_python(args): """Provide isolated installation of Anaconda python for running bcbio-nextgen. http://docs.continuum.io/anaconda/index.html """ anaconda_dir = os.path.join(args.datadir, "anaconda") bindir = os.path.join(anaconda_dir, "bin") conda = os.path.join(bindir, "conda") if not os.path.exists(anaconda_dir) or not os.path.exists(conda): if os.path.exists(anaconda_dir): shutil.rmtree(anaconda_dir) dist = args.distribution if args.distribution else _guess_distribution() url = REMOTES["anaconda"] % ("MacOSX" if dist.lower() == "macosx" else "Linux") if not os.path.exists(os.path.basename(url)): subprocess.check_call(['wget', '--progress=dot:giga', url]) subprocess.check_call(['bash', os.path.basename(url), '-b', '-p', anaconda_dir]) # conda-forge channel should have the highest priority # https://bioconda.github.io/user/install.html#set-up-channels subprocess.check_call([conda, 'config', '--add', 'channels', 'bioconda', '--file', os.path.join(anaconda_dir, '.condarc')]) subprocess.check_call([conda, 'config', '--add', 'channels', 'conda-forge', '--file', os.path.join(anaconda_dir, '.condarc')]) return {"conda": conda, "pip": os.path.join(bindir, "pip"), "dir": anaconda_dir} def setup_manifest(datadir): """Create barebones manifest to be filled in during update""" manifest_dir = os.path.join(datadir, "manifest") if not os.path.exists(manifest_dir): os.makedirs(manifest_dir) def write_system_config(base_url, datadir, tooldir): """Write a bcbio_system.yaml configuration file with tool information""" out_file = os.path.join(datadir, "galaxy", os.path.basename(base_url)) if not os.path.exists(os.path.dirname(out_file)): os.makedirs(os.path.dirname(out_file)) if os.path.exists(out_file): # if no tool directory and exists, do not overwrite if tooldir is None: return out_file else: bak_file = out_file + ".bak%s" % (datetime.datetime.now().strftime("%Y%M%d_%H%M")) shutil.copy(out_file, bak_file) if tooldir: java_basedir = os.path.join(tooldir, "share", "java") rewrite_ignore = ("log",) with contextlib.closing(urllib_request.urlopen(base_url)) as in_handle: with open(out_file, "w") as out_handle: in_resources = False in_prog = None for line in (l.decode("utf-8") for l in in_handle): if line[0] != " ": in_resources = line.startswith("resources") in_prog = None elif (in_resources and line[:2] == " " and line[2] != " " and not line.strip().startswith(rewrite_ignore)): in_prog = line.split(":")[0].strip() # Update java directories to point to install directory, avoid special cases elif line.strip().startswith("dir:") and in_prog and in_prog not in ["log", "tmp"]: final_dir = os.path.basename(line.split()[-1]) if tooldir: line = "%s: %s\n" % (line.split(":")[0], os.path.join(java_basedir, final_dir)) in_prog = None elif line.startswith("galaxy"): line = "# %s" % line out_handle.write(line) return out_file def setup_data_dir(args): if not os.path.exists(args.datadir): cmd = ["mkdir", "-p", args.datadir] subprocess.check_call(cmd) @contextlib.contextmanager def bcbio_tmpdir(): orig_dir = os.getcwd() work_dir = os.path.join(os.getcwd(), "tmpbcbio-install") if not os.path.exists(work_dir): os.makedirs(work_dir) os.chdir(work_dir) yield work_dir os.chdir(orig_dir) shutil.rmtree(work_dir) def check_arguments(args): """Ensure argruments are consistent and correct""" if args.toolplus and not args.tooldir: raise argparse.ArgumentTypeError("Cannot specify --toolplus without --tooldir") def check_dependencies(): """Ensure required tools for installation are present""" print("Checking required dependencies") for dep, msg in [(["git", "--version"], "Git (http://git-scm.com/)"), (["wget", "--version"], "wget"), (["bzip2", "-h"], "bzip2")]: try: p = subprocess.Popen(dep, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) out, code = p.communicate() except OSError: out = "Executable not found" code = 127 if code == 127: raise OSError("bcbio-nextgen installer requires %s\n%s" % (msg, out)) def _check_toolplus(x): """Parse options for adding non-standard/commercial tools like GATK and MuTecT""" import argparse Tool = collections.namedtuple("Tool", ["name", "fname"]) std_choices = set(["data", "dbnsfp", "ericscript"]) if x in std_choices: return Tool(x, None) elif "=" in x and len(x.split("=")) == 2: name, fname = x.split("=") fname = os.path.normpath(os.path.realpath(fname)) if not os.path.exists(fname): raise argparse.ArgumentTypeError("Unexpected --toolplus argument for %s. " "File does not exist: %s" % (name, fname)) return Tool(name, fname) else: raise argparse.ArgumentTypeError("Unexpected --toolplus argument. " "Expect toolname=filename.") if __name__ == "__main__": parser = argparse.ArgumentParser( description="Automatic installation for bcbio-nextgen pipelines") parser.add_argument("datadir", help="Directory to install genome data", type=lambda x: (os.path.abspath(os.path.expanduser(x)))) parser.add_argument("--cores", default=1, help="Number of cores to use if local indexing is necessary.") parser.add_argument("--tooldir", help="Directory to install 3rd party software tools. " "Leave unspecified for no tools", type=lambda x: (os.path.abspath(os.path.expanduser(x))), default=None) parser.add_argument("--toolplus", help="Specify additional tool categories to install", action="append", default=[], type=_check_toolplus) parser.add_argument("--datatarget", help="Data to install. Allows customization or install of extra data.", action="append", default=[], choices=["variation", "rnaseq", "smallrna", "gemini", "vep", "dbnsfp", "battenberg", "kraken", "ericscript", "gnomad"]) parser.add_argument("--genomes", help="Genomes to download", action="append", default=[], choices=["BDGP6", "canFam3", "dm3", "galGal4", "GRCh37", "GRCz10", "GRCz11", "hg19", "hg38", "hg38-noalt", "mm10", "mm9", "phix", "pseudomonas_aeruginosa_ucbpp_pa14", "rn5", "rn6", "sacCer3", "Sscrofa11.1", "TAIR10", "WBcel235", "xenTro3"]) parser.add_argument("--aligners", help="Aligner indexes to download", action="append", default=[], choices=["bbmap", "bowtie", "bowtie2", "bwa", "hisat2", "minimap2", "novoalign", "rtg", "snap", "star", "ucsc"]) parser.add_argument("--nodata", help="Do not install data dependencies", dest="install_data", action="store_false", default=True) parser.add_argument("--mamba", help="Use mamba instead of conda", dest="use_mamba", action="store_true", default=False) parser.add_argument("--isolate", help="Created an isolated installation without PATH updates", dest="isolate", action="store_true", default=False) parser.add_argument("--minimize-disk", help="Try to minimize disk usage (no MKL extensions)", dest="minimize_disk", action="store_true", default=False) parser.add_argument("-u", "--upgrade", help="Code version to install", choices=["stable", "development"], default="stable") parser.add_argument("--revision", help="Specify a git commit hash or tag to install", default="master") parser.add_argument("--cloudbiolinux", help="Specify a cloudbiolinux git commit hash or tag to install", default="master") parser.add_argument("--distribution", help="Operating system distribution", default="", choices=["ubuntu", "debian", "centos", "scientificlinux", "macosx"]) if len(sys.argv) == 1: parser.print_help() else: main(parser.parse_args(), sys.argv[1:]) bcbio-nextgen-1.2.9/scripts/bcbio_prepare_samples.py000077500000000000000000000213551415626112400226430ustar00rootroot00000000000000#!/usr/bin/env python -Es """ Script that creates bcbio-compatible inputs in case of multiple files samples """ import os import sys import yaml from collections import defaultdict from argparse import ArgumentParser from bcbio import log from bcbio.log import logger from bcbio.install import _get_data_dir from bcbio import utils from bcbio.bam import is_bam from bcbio.pipeline.sra import is_gsm, is_srr from bcbio.bam.fastq import is_fastq, combine_pairs from bcbio.distributed.transaction import file_transaction from bcbio.distributed import clargs, resources, prun from bcbio.provenance import system, profile def create_new_csv(samples, args): """create csv file that can be use with bcbio -w template""" out_fn = os.path.splitext(args.csv)[0] + "-merged.csv" logger.info("Preparing new csv: %s" % out_fn) with file_transaction(out_fn) as tx_out: with open(tx_out, 'w') as handle: handle.write(_header(args.csv)) for s in samples: sample_name = s['name'] if isinstance(s['out_file'], list) else os.path.basename(s['out_file']) handle.write("%s,%s,%s\n" % (sample_name, s['name'], ",".join(s['anno']))) def _header(fn): """read header of csv file""" l = open(fn).readline() return l def _get_samples_to_process(fn, out_dir, config, force_single, separators): """parse csv file with one line per file. It will merge all files that have the same description name""" out_dir = os.path.abspath(out_dir) samples = defaultdict(list) with open(fn) as handle: for l in handle: if l.find("description") > 0: logger.info("Skipping header.") continue cols = l.strip().split(",") if len(cols) > 0: if len(cols) < 2: raise ValueError("Line needs 2 values: file and name.") if utils.file_exists(cols[0]) or is_gsm(cols[0]) or is_srr(cols[0]): if cols[0].find(" ") > -1: new_name = os.path.abspath(cols[0].replace(" ", "_")) logger.warning("Space finds in %s. Linked to %s." % (cols[0], new_name)) logger.warning("Please, avoid names with spaces in the future.") utils.symlink_plus(os.path.abspath(cols[0]), new_name) cols[0] = new_name samples[cols[1]].append(cols) else: logger.info("skipping %s, File doesn't exist." % cols[0]) for sample, items in samples.items(): if is_fastq(items[0][0], True): fn = "fq_merge" ext = ".fastq.gz" elif is_bam(items[0][0]): fn = "bam_merge" ext = ".bam" elif is_gsm(items[0][0]): fn = "query_gsm" ext = ".fastq.gz" elif is_srr(items[0][0]): fn = "query_gsm" ext = ".fastq.gz" files = [os.path.abspath(fn_file[0]) if utils.file_exists(fn_file[0]) else fn_file[0] for fn_file in items] samples[sample] = [{'files': _check_paired(files, force_single, separators), 'out_file': os.path.join(out_dir, sample + ext), 'fn': fn, 'anno': items[0][2:], 'config': config, 'name': sample, 'out_dir': out_dir}] return [samples[sample] for sample in samples] def _check_stems(files): """check if stem names are the same and use full path then""" used = set() for fn in files: if os.path.basename(fn) in used: logger.warning("%s stem is multiple times in your file list, " "so we don't know " "how to assign it to the sample data in the CSV. " "We are gonna use full path to make a difference, " "that means paired files should be in the same folder. " "If this is a problem, you should rename the files you want " "to merge. Sorry, no possible magic here." % os.path.basename(fn) ) return True used.add(os.path.basename(fn)) return False def _check_paired(files, force_single, separators): """check if files are fastq(.gz) and paired""" full_name = _check_stems(files) if files[0].endswith(".bam"): return files elif is_gsm(files[0]): return files return combine_pairs(files, force_single, full_name, separators) def get_cluster_view(p): """get ipython running""" from cluster_helper import cluster as ipc return ipc.cluster_view(p['scheduler'], p['queue'], p['num_jobs'], p['cores_per_job'], start_wait=p['timeout'], extra_params={"resources": p['resources'], "mem": p['mem'], "tag": p['tag'], "run_local": False}) def wait_until_complete(jobs): """wait jobs finish""" return [j.get() for j in jobs] if __name__ == "__main__": description = ("Merge multiple files from the same sample to be compatible with bcbio BAM/FASTQ input files") parser = ArgumentParser(description="Merge fastq or bam files") parser.add_argument("--csv", required=True, help="csv file with metadata") parser.add_argument("--out", required=True, help="output dir") parser.add_argument("--force-single", action='store_true', default=False, help="Treat all files as single reads") parser.add_argument("--separators", nargs="*", default=["R", "_", "-", "."], help="Space separated list of separators that indicates paired files.") parser.add_argument("--remove-source", action='store_true', default=False, help="Remove original files.") parser.add_argument("-n", "--numcores", type=int, default=1, help="Number of concurrent jobs to process.") parser.add_argument("-c", "--cores-per-job", type=int, default=1, help="Number of cores to use.") parser.add_argument("-m", "--memory-per-job", default=2, help="Memory in GB to reserve per job.") parser.add_argument("--timeout", default=15, help="Time to wait before giving up starting.") parser.add_argument("--retries", default=0, type=int, help=("Number of retries of failed tasks during " "distributed processing. Default 0 " "(no retries)")) parser.add_argument("-s", "--scheduler", help="Type of scheduler to use.", choices=["lsf", "slurm", "torque", "sge", "pbspro"]) parser.add_argument("-r", "--resources", help="Extra scheduler resource flags.", default=[], action="append") parser.add_argument("-q", "--queue", help="Queue to submit jobs to.") parser.add_argument("-p", "--tag", help="Tag name to label jobs on the cluster", default="bcb-prep") parser.add_argument("-t", "--paralleltype", choices=["local", "ipython"], default="local", help="Run with iptyhon") args = parser.parse_args() out_dir = os.path.abspath(args.out) utils.safe_makedir(out_dir) try: system_config = os.path.join(_get_data_dir(), "galaxy", "bcbio_system.yaml") except ValueError as err: print(err) print("WARNING: Attempting to read bcbio_system.yaml in the current directory.") system_config = "bcbio_system.yaml" if utils.file_exists(system_config): with open(system_config) as in_handle: config = yaml.safe_load(in_handle) else: print("WARNING: bcbio_system.yaml not found, creating own resources.") config = {'resources': {}} res = {'cores': args.cores_per_job, 'memory': f"{args.memory_per_job}g"} config["algorithm"] = {"num_cores": args.cores_per_job} config["resources"].update({'sambamba': res, 'samtools': res}) config["log_dir"] = os.path.join(os.path.abspath(os.getcwd()), "log") parallel = clargs.to_parallel(args) parallel.update({'progs': ['samtools', 'sambamba']}) parallel = log.create_base_logger(config, parallel) log.setup_local_logging(config, parallel) dirs = {'work': os.path.abspath(os.getcwd())} system.write_info(dirs, parallel, config) sysinfo = system.machine_info()[0] config["remove_source"] = args.remove_source samples = _get_samples_to_process(args.csv, out_dir, config, args.force_single, args.separators) if not samples: print("No samples found.") sys.exit(0) parallel = resources.calculate(parallel, [samples], sysinfo, config) with prun.start(parallel, samples, config, dirs) as run_parallel: with profile.report("prepare bcbio samples", dirs): samples = run_parallel("prepare_bcbio_samples", samples) create_new_csv(samples, args) bcbio-nextgen-1.2.9/scripts/bcbio_setup_genome.py000077500000000000000000000356521415626112400221600ustar00rootroot00000000000000#!/usr/bin/env python -Es """ Script to set up a custom genome for bcbio-nextgen """ from __future__ import print_function from argparse import ArgumentParser import collections import gzip import os from Bio import SeqIO import toolz as tz from bcbio.utils import safe_makedir, file_exists, chdir, is_gzipped from bcbio.distributed.transaction import file_transaction from bcbio.provenance import do from bcbio.install import (REMOTES, get_cloudbiolinux, SUPPORTED_INDEXES, _get_data_dir) from bcbio.pipeline.run_info import ALLOWED_CONTIG_NAME_CHARS from bcbio.galaxy import loc from bcbio.log import logger import subprocess import sys import shutil import yaml import gffutils from gffutils.iterators import DataIterator import tempfile SEQ_DIR = "seq" RNASEQ_DIR = "rnaseq" SRNASEQ_DIR = "srnaseq" ERCC_BUCKET = "bcbio-data.s3.amazonaws.com/" def extract_if_gzipped(filename): stem, ext = os.path.splitext(filename) if ext == ".gz": subprocess.check_call("gzip -cd %s > %s" % (filename, stem), shell=True) return stem else: return filename def gff3_to_gtf(gff3_file): dialect = {'field separator': '; ', 'fmt': 'gtf', 'keyval separator': ' ', 'leading semicolon': False, 'multival separator': ',', 'quoted GFF2 values': True, 'order': ['gene_id', 'transcript_id'], 'repeated keys': False, 'trailing semicolon': True} out_file = os.path.splitext(gff3_file)[0] + ".gtf" if file_exists(out_file): return out_file logger.info("Converting %s to %s." % (gff3_file, out_file)) if _is_from_ncbi(gff3_file): logger.info("NCBI format detected by the presence of the %s key." % _is_from_ncbi(gff3_file)) _output_ncbi_gff3(gff3_file, out_file, dialect) else: _output_gff3(gff3_file, out_file, dialect) return out_file def _output_gff3(gff3_file, out_file, dialect): db = gffutils.create_db(gff3_file, ":memory:") with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for feature in DataIterator(db.features_of_type("exon"), dialect=dialect): transcript_id = feature["Parent"][0] gene_id = db[transcript_id]["Parent"][0] attr = {"transcript_id": transcript_id, "gene_id": gene_id} attributes = gffutils.attributes.Attributes(attr) feature.attributes = attributes print(feature, file=out_handle, end="") def _output_ncbi_gff3(gff3_file, out_file, dialect): gene_key = "gene" id_spec = {"gene": gene_key} db = gffutils.create_db(gff3_file, ":memory:", id_spec=id_spec) with file_transaction(out_file) as tx_out_file: with open(tx_out_file, "w") as out_handle: for feature in DataIterator(db.features_of_type("exon"), dialect=dialect): # Gnomon features are often missing a transcript id # some malformed features are also missing the gene key try: transcript_id = feature["transcript_id"] except KeyError: try: transcript_id = feature[gene_key] except KeyError: continue gene_id = feature[gene_key] try: biotype = feature["gene_biotype"] except KeyError: biotype = "unknown" attr = {"transcript_id": transcript_id, "gene_id": gene_id, "gene_biotype": biotype} attributes = gffutils.attributes.Attributes(attr) feature.attributes = attributes print(feature, file=out_handle, end="") def _is_from_ncbi(gff3_file): with open(gff3_file) as in_handle: for line in tz.take(10000, in_handle): if "Dbxref" in line: return "Dbxref" if "db_xref" in line: return "db_xref" return None def _index_w_command(env, dir_name, command, ref_file, pre=None, post=None, ext=None): index_name = os.path.splitext(os.path.basename(ref_file))[0] if ext is not None: index_name += ext build_path = os.path.join(os.path.dirname(ref_file), os.pardir) out_dir = os.path.join(build_path, dir_name) index_path = os.path.join(out_dir, index_name) safe_makedir(out_dir) subprocess.check_call(command.format(ref_file=ref_file, index_name=index_path), shell=True) return index_path def setup_base_directories(genome_dir, name, build, gtf=None): name_dir = os.path.join(genome_dir, name) safe_makedir(name_dir) build_dir = os.path.join(name_dir, build) safe_makedir(build_dir) seq_dir = os.path.join(build_dir, SEQ_DIR) safe_makedir(seq_dir) if gtf: gtf_dir = os.path.join(build_dir, RNASEQ_DIR) safe_makedir(gtf_dir) return build_dir def install_fasta_file(build_dir, fasta, build): out_file = os.path.join(build_dir, SEQ_DIR, build + ".fa") if not file_exists(out_file): recs = SeqIO.parse(fasta, "fasta") with open(out_file, "w") as out_handle: SeqIO.write((_clean_rec_name(rec) for rec in recs), out_handle, "fasta") return out_file def _clean_rec_name(rec): """Clean illegal characters in input fasta file which cause problems downstream. """ out_id = [] for char in list(rec.id): if char in ALLOWED_CONTIG_NAME_CHARS: out_id.append(char) else: out_id.append("_") rec.id = "".join(out_id) rec.description = "" return rec def install_gtf_file(build_dir, gtf, build): out_file = os.path.join(build_dir, RNASEQ_DIR, "ref-transcripts.gtf") if not file_exists(out_file): if is_gzipped(gtf): with gzip.open(gtf_file, 'rb') as in_handle: with open(out_file, 'wb') as out_handle: shutil.copyfileobj(in_handle, out_handle) else: shutil.copyfile(gtf, out_file) return out_file def install_srna(species, gtf): out_file = os.path.join(SRNASEQ_DIR, "srna-transcripts.gtf") safe_makedir(SRNASEQ_DIR) if gtf: if not file_exists(out_file): shutil.copyfile(gtf, out_file) try: from seqcluster import install except ImportError: raise ImportError("install seqcluster first, please.") with chdir(SRNASEQ_DIR): hairpin, miRNA = install._install_mirbase() cmd = ("cat %s | awk '{if ($0~/>%s/){name=$0; print name} else if ($0~/^>/){name=0};if (name!=0 && $0!~/^>/){print $0;}}' | sed 's/U/T/g' > hairpin.fa") do.run(cmd % (hairpin, species), "set precursor.") cmd = ("grep -A 1 {species} {miRNA} > miRNA.str") do.run(cmd.format(**locals()), "set miRNA.") shutil.rmtree("mirbase") return out_file def append_ercc(gtf_file, fasta_file): ercc_fa = ERCC_BUCKET + "ERCC92.fasta.gz" tmp_fa = tempfile.NamedTemporaryFile(delete=False, suffix=".gz").name append_fa_cmd = "wget {ercc_fa} -O {tmp_fa}; gzip -cd {tmp_fa} >> {fasta_file}" print(append_fa_cmd.format(**locals())) subprocess.check_call(append_fa_cmd.format(**locals()), shell=True) ercc_gtf = ERCC_BUCKET + "ERCC92.gtf.gz" tmp_gtf = tempfile.NamedTemporaryFile(delete=False, suffix=".gz").name append_gtf_cmd = "wget {ercc_gtf} -O {tmp_gtf}; gzip -cd {tmp_gtf} >> {gtf_file}" print(append_gtf_cmd.format(**locals())) subprocess.check_call(append_gtf_cmd.format(**locals()), shell=True) class MyParser(ArgumentParser): def error(self, message): self.print_help() galaxy_base = os.path.join(_get_data_dir(), "galaxy") print("\nCurrent genomes\n") print(open(loc.get_loc_file(galaxy_base, "samtools")).read()) sys.exit(0) if __name__ == "__main__": description = ("Set up a custom genome for bcbio-nextgen. This will " "place the genome under name/build in the genomes " "directory in your bcbio-nextgen installation.") parser = MyParser(description=description) parser.add_argument("-c", "--cores", default=1, help="number of cores to use") parser.add_argument("--gff3", default=False, action='store_true', help="File is a GFF3 file.") parser.add_argument("-i", "--indexes", choices=SUPPORTED_INDEXES, nargs="*", default=["seq"], help="Space separated list of indexes to make") parser.add_argument("--ercc", action='store_true', default=False, help="Add ERCC spike-ins.") parser.add_argument("--mirbase", help="species in mirbase for smallRNAseq data.") parser.add_argument("--srna_gtf", help="gtf to use for smallRNAseq data.") required = parser.add_argument_group('required named arguments') required.add_argument("--buildversion", required=True, help=("String describing build of genome used. Examples: " "Ensembl_94, EnsemblMetazoa_94, Flybase_21, etc")) required.add_argument("-f", "--fasta", required=True, help="FASTA file of the genome.") required.add_argument("-g", "--gtf", default=None, help="GTF file of the transcriptome") required.add_argument("-n", "--name", required=True, help="Name of organism, for example Hsapiens.") required.add_argument("-b", "--build", required=True, help="Build of genome, for example hg19.") args = parser.parse_args() # if not all([args.mirbase, args.srna_gtf]) and any([args.mirbase, args.srna_gtf]): # raise ValueError("--mirbase and --srna_gtf both need a value.") os.environ["PATH"] += os.pathsep + os.path.dirname(sys.executable) cbl = get_cloudbiolinux(args, REMOTES) sys.path.insert(0, cbl["dir"]) genomemod = __import__("cloudbio.biodata", fromlist=["genomes"]) # monkey patch cloudbiolinux to use this indexing command instead genomes = getattr(genomemod, 'genomes') genomes._index_w_command = _index_w_command genome_dir = os.path.abspath(os.path.join(_get_data_dir(), "genomes")) args.fasta = os.path.abspath(args.fasta) if not file_exists(args.fasta): print("%s does not exist, exiting." % args.fasta) sys.exit(1) args.gtf = os.path.abspath(args.gtf) if args.gtf else None if args.gtf and not file_exists(args.gtf): print("%s does not exist, exiting." % args.gtf) sys.exit(1) args.srna_gtf = os.path.abspath(args.srna_gtf) if args.srna_gtf else None gtf_file = args.gtf if args.gff3: gtf_file = extract_if_gzipped(gtf_file) gtf_file = gff3_to_gtf(gtf_file) # always make a sequence dictionary if "seq" not in args.indexes: args.indexes.append("seq") prepare_tx = os.path.join(cbl["dir"], "utils", "prepare_tx_gff.py") print("Creating directories using %s as the base." % (genome_dir)) build_dir = setup_base_directories(genome_dir, args.name, args.build, args.gtf) os.chdir(build_dir) print("Genomes will be installed into %s." % (build_dir)) fasta_file = extract_if_gzipped(args.fasta) fasta_file = install_fasta_file(build_dir, fasta_file, args.build) print("Installed genome as %s." % (fasta_file)) if args.gtf: if "bowtie2" not in args.indexes: args.indexes.append("bowtie2") gtf_file = install_gtf_file(build_dir, gtf_file, args.build) print("Installed GTF as %s." % (gtf_file)) if args.ercc: print("Appending ERCC sequences to %s and %s." % (gtf_file, fasta_file)) append_ercc(gtf_file, fasta_file) indexed = {} Env = collections.namedtuple("Env", "system_install, cores") env = Env(genome_dir, args.cores) for index in args.indexes: print("Creating the %s index." % (index)) index_fn = genomes.get_index_fn(index) if not index_fn: print("Do not know how to make the index %s, skipping." % (index)) continue indexed[index] = index_fn(env, fasta_file) indexed["samtools"] = fasta_file if args.gtf: "Preparing transcriptome." with chdir(os.path.join(build_dir, os.pardir)): cmd = ("{sys.executable} {prepare_tx} --buildversion {args.buildversion} --cores {args.cores} --genome-dir {genome_dir} " "--gtf {gtf_file} {args.name} {args.build}") subprocess.check_call(cmd.format(**locals()), shell=True) if args.mirbase: "Preparing smallRNA data." with chdir(os.path.join(build_dir)): install_srna(args.mirbase, args.srna_gtf) base_dir = os.path.normpath(os.path.dirname(fasta_file)) resource_file = os.path.join(base_dir, "%s-resources.yaml" % args.build) print("Dumping genome resources to %s." % resource_file) resource_dict = {"version": 1} if args.gtf: transcripts = ["rnaseq", "transcripts"] mask = ["rnaseq", "transcripts_mask"] index = ["rnaseq", "transcriptome_index", "tophat"] dexseq = ["rnaseq", "dexseq"] refflat = ["rnaseq", "refflat"] rRNA_fa = ["rnaseq", "rRNA_fa"] resource_dict = tz.update_in(resource_dict, transcripts, lambda x: "../rnaseq/ref-transcripts.gtf") resource_dict = tz.update_in(resource_dict, mask, lambda x: "../rnaseq/ref-transcripts-mask.gtf") resource_dict = tz.update_in(resource_dict, index, lambda x: "../rnaseq/tophat/%s_transcriptome.ver" % args.build) resource_dict = tz.update_in(resource_dict, refflat, lambda x: "../rnaseq/ref-transcripts.refFlat") resource_dict = tz.update_in(resource_dict, dexseq, lambda x: "../rnaseq/ref-transcripts.dexseq.gff3") resource_dict = tz.update_in(resource_dict, rRNA_fa, lambda x: "../rnaseq/rRNA.fa") if args.mirbase: srna_gtf = ["srnaseq", "srna_transcripts"] srna_mirbase = ["srnaseq", "mirbase_hairpin"] resource_dict = tz.update_in(resource_dict, srna_gtf, lambda x: "../srnaseq/srna-transcripts.gtf") resource_dict = tz.update_in(resource_dict, srna_mirbase, lambda x: "../srnaseq/hairpin.fa") # write out resource dictionarry with file_transaction(resource_file) as tx_resource_file: with open(tx_resource_file, "w") as out_handle: out_handle.write(yaml.dump(resource_dict, default_flow_style=False)) print("Updating Galaxy .loc files.") galaxy_base = os.path.join(_get_data_dir(), "galaxy") for index, index_file in indexed.items(): if index_file: loc.update_loc_file(galaxy_base, index, args.build, index_file) print("Genome installation complete.") bcbio-nextgen-1.2.9/scripts/cwl/000077500000000000000000000000001415626112400165255ustar00rootroot00000000000000bcbio-nextgen-1.2.9/scripts/cwl/arvados_bcbio_runtimes.py000066400000000000000000000077071415626112400236350ustar00rootroot00000000000000#!/usr/bin/env python """Summarize runtimes for bcbio Arvados CWL runs. Usage: arvados_bcbio_runtimes.py """ import csv import json import math import operator import os import pprint import sys import arrow def main(run_uuid): out_file = "%s-stats.csv" % run_uuid writer = csv.writer(open(out_file, "w")) client = _get_api_client() from arvados.collection import Collection req = client.container_requests().get(uuid=run_uuid).execute() jobs = client.container_requests().list( filters=[["requesting_container_uuid", "=", req["container_uuid"]]], limit=10000).execute()["items"] group_runtimes = {} writer.writerow(["group", "run", "time", "walltime", "cores", "memory"]) for job in jobs: try: j1, j2 = job["name"].rsplit("_", 1) int(j2) name = j1 except ValueError: name = job["name"] sample, vc = get_sample_variantcaller(job) name = "%s-%s" % (sample, name) if job["name"].startswith("variantcall_batch") and vc: name += "-%s" % vc print(name, job["uuid"], job["log_uuid"]) log = client.collections().get(uuid=job["log_uuid"]).execute() logc = Collection(log["portable_data_hash"]) machine_info = get_machine_info(logc) runtime = get_runtime(logc) writer.writerow([name, job["name"], str(runtime).rsplit(":", 1)[0], "", machine_info["cores"], machine_info["memory"]]) if name not in group_runtimes: group_runtimes[name] = [runtime] else: group_runtimes[name].append(runtime) for k in sorted(group_runtimes.keys()): writer.writerow([k, "", str(reduce(operator.add, group_runtimes[k])).rsplit(":", 1)[0], str(max(group_runtimes[k])).rsplit(":", 1)[0], "", ""]) def get_machine_info(logc): procs = [] mem = None with logc.open("node-info.txt") as in_handle: for line in in_handle: if line.startswith("node-info processor"): procs.append(int(line.strip().split()[-1])) elif line.startswith("node-info MemAvailable:"): mem = float(line.split()[-2]) / 1024.0 / 1024.0 return {"cores": max(procs) + 1, "memory": "%sG" % int(math.floor(mem))} def get_runtime(logc): with logc.open("crunchstat.txt") as in_handle: tstart = arrow.get(in_handle.readline().split()[0]) for line in in_handle: last = line tend = arrow.get(last.split()[0]) return tend - tstart def get_in_inputs(key, data): if isinstance(data, dict): for k, v in data.items(): if k == key: return v elif isinstance(v, (list, tuple, dict)): out = get_in_inputs(key, v) if out: return out elif isinstance(data, (list, tuple)): out = [get_in_inputs(key, x) for x in data] out = [x for x in out if x] if out: return out[0] def get_sample_variantcaller(job): from arvados.collection import Collection needs_json = job["name"].startswith("variantcall_batch") sample = None for f in job["mounts"]: if f.endswith("-sort.bam"): sample = os.path.basename(f).replace("-sort.bam", "") if not sample or needs_json: for k, v in job["mounts"].items(): if k.endswith("cwl.inputs.json"): c = Collection(v["portable_data_hash"]) with c.open("cwl.inputs.json", "r") as in_handle: inputs = json.load(in_handle) return [get_in_inputs("description", inputs), get_in_inputs("config__algorithm__variantcaller", inputs)] else: return sample, None return None, None def _get_api_client(): import arvados return arvados.api("v1") if __name__ == "__main__": main(*sys.argv[1:]) bcbio-nextgen-1.2.9/scripts/cwltool2wdl.py000077500000000000000000000335171415626112400206020ustar00rootroot00000000000000#!/bin/env python """Exploratory code to convert bcbio generated CWL into WDL. Uses cwltool parser to parse input CWL then, calls out to cwl2wdl for generation of WDL using this fork of cwl2wdl: https://github.com/chapmanb/cwl2wdl Current status: - Connected workflow, sub-workflow and tool output - Records -> Object - Dotproduct scatter parallelization Needed for WDL finalization to support bcbio: - structs to define attributes of an Object https://github.com/broadinstitute/cromwell/issues/2283 - Implement standard library function to dump input records in a JSON format ('write_struct') - Implement standard library function to read output of a struct/object with multiple levels of nesting (`read_struct`) - Associate secondary files (like `bai`, `tbi`) with primary file ('bam`, 'vcf.gz`) https://github.com/broadinstitute/cromwell/issues/2269 """ from __future__ import print_function import collections import os import subprocess import sys from cwl2wdl import generators from cwl2wdl import base_classes as cwl2wdl_classes import cwltool.load_tool import cwltool.workflow def main(wf_file, json_file): wf_file = os.path.abspath(wf_file) out_dir = os.path.dirname(wf_file).replace("-workflow", "-wdl") if not os.path.exists(out_dir): os.makedirs(out_dir) main_wf = cwltool.load_tool.load_tool(wf_file, cwltool.workflow.defaultMakeTool) records = {} main_wf_dict, records = _wf_to_dict(main_wf, records) main_wf_dict["structs"] = records main_wf_class = cwl2wdl_classes.Workflow(main_wf_dict) for wf_class in [x.task_definition for x in main_wf_class.subworkflows] + [main_wf_class]: wdl_file = os.path.join(out_dir, "%s.wdl" % wf_class.name) wdl_doc = generators.WdlWorkflowGenerator(wf_class).generate_wdl() with open(wdl_file, "w") as out_handle: out_handle.write(wdl_doc) _validate(wdl_file) def _validate(wdl_file): """Run validation on the generated WDL output using wdltool. """ start_dir = os.getcwd() os.chdir(os.path.dirname(wdl_file)) print("Validating", wdl_file) subprocess.check_call(["wdltool", "validate", wdl_file]) os.chdir(start_dir) def _wf_to_dict(wf, records): """Parse a workflow into cwl2wdl style dictionaries for base and sub-workflows. """ inputs, outputs, records = _get_wf_inout(wf, records) out = {"name": _id_to_name(_clean_id(wf.tool["id"])), "inputs": inputs, "outputs": outputs, "steps": [], "subworkflows": [], "requirements": []} for step in wf.steps: is_subworkflow = isinstance(step.embedded_tool, cwltool.workflow.Workflow) inputs, outputs, remapped, prescatter = _get_step_inout(step) inputs, scatter = _organize_step_scatter(step, inputs, remapped) if is_subworkflow: wf_def, records = _wf_to_dict(step.embedded_tool, records) out["subworkflows"].append({"id": "%s.%s" % (wf_def["name"], wf_def["name"]), "definition": wf_def, "inputs": inputs, "outputs": outputs, "scatter": scatter, "prescatter": prescatter}) else: task_def, records = _tool_to_dict(step.embedded_tool, records, remapped) out["steps"].append({"task_id": task_def["name"], "task_definition": task_def, "inputs": inputs, "outputs": outputs, "scatter": scatter, "prescatter": prescatter}) return out, records def _clean_id(x): """Replace non-allowed characters in WDL input """ return x.replace("wf-", "").replace("-", "_") def _get_step_inout(step): """Retrieve set of inputs and outputs connecting steps. """ inputs = [] outputs = [] prescatter = collections.defaultdict(list) remapped = {} assert step.outputs_record_schema["type"] == "record" output_names = set([]) for outp in step.outputs_record_schema["fields"]: outputs.append({"id": outp["name"]}) output_names.add(outp["name"]) assert step.inputs_record_schema["type"] == "record" for inp in step.inputs_record_schema["fields"]: source = inp["source"].split("#")[-1].replace("/", ".") # Check if we're unpacking from a record, and unpack from our object if "valueFrom" in inp: attr_access = "['%s']" % inp["name"] if inp["valueFrom"].find(attr_access) > 0: source += ".%s" % inp["name"] if isinstance(inp["type"], dict) and isinstance(inp["type"].get("items"), dict): if inp["type"]["items"].get("type") == "array" and "inputBinding" in inp["type"]: source, prescatter = _unpack_object_array(inp, source, prescatter) # Avoid clashing input and output names, WDL requires unique if inp["name"] in output_names: new_name = inp["name"] + "_input" remapped[inp["name"]] = new_name inp["name"] = new_name inputs.append({"id": inp["name"], "value": source}) return inputs, outputs, remapped, dict(prescatter) def _unpack_object_array(inp, source, prescatter): """Unpack Array[Object] with a scatter for referencing in input calls. There is no shorthand syntax for referencing all items in an array, so we explicitly unpack them with a scatter. """ raise NotImplementedError("Currently not used with record/struct/object improvements") base_rec, attr = source.rsplit(".", 1) new_name = "%s_%s_unpack" % (inp["name"], base_rec.replace(".", "_")) prescatter[base_rec].append((new_name, attr, _to_variable_type(inp["type"]["items"]))) return new_name, prescatter def _organize_step_scatter(step, inputs, remapped): """Add scattering information from inputs, remapping input variables. """ def extract_scatter_id(inp): _, ns_var = inp.split("#") _, var = ns_var.split("/") return var scatter_local = {} if "scatter" in step.tool: assert step.tool["scatterMethod"] == "dotproduct", \ "Only support dotproduct scattering in conversion to WDL" inp_val = collections.OrderedDict() for x in inputs: inp_val[x["id"]] = x["value"] for scatter_key in [extract_scatter_id(x) for x in step.tool["scatter"]]: scatter_key = remapped.get(scatter_key) or scatter_key val = inp_val[scatter_key] if len(val.split(".")) in [1, 2]: base_key = val attr = None elif len(val.split(".")) == 3: orig_location, record, attr = val.split(".") base_key = "%s.%s" % (orig_location, record) else: raise ValueError("Unexpected scatter input: %s" % val) local_ref = base_key.split(".")[-1] + "_local" scatter_local[base_key] = local_ref if attr: local_ref += ".%s" % attr inp_val[scatter_key] = local_ref inputs = [{"id": iid, "value": ival} for iid, ival in inp_val.items()] return inputs, [(v, k) for k, v in scatter_local.items()] def _get_wf_inout(wf, records): assert wf.inputs_record_schema["type"] == "record" assert wf.outputs_record_schema["type"] == "record" inputs = [] outputs = [] for inp in wf.inputs_record_schema["fields"]: cur_inp, records = _input_to_dict(inp, records) inputs.append(cur_inp) for outp in wf.outputs_record_schema["fields"]: cur_outp, records = _output_to_dict(outp, records) outputs.append(cur_outp) return inputs, outputs, records def _record_to_struct(cur_rec, records): """Convert a CWL record into a WDL struct/Object. Work in progress to support changes to WDL Objects to be defined in structs. """ def to_camel_case(x): def uppercase_word(w): return w[0].upper() + w[1:] return "".join(uppercase_word(w) for w in x.split("_")) struct_name = to_camel_case(cur_rec["name"].split("/")[-1]) if struct_name not in records: records[struct_name] = collections.OrderedDict() for field in cur_rec["fields"]: field_type, records = _to_variable_type(field["type"], records) records[struct_name][field["name"].split("/")[-1]] = field_type return struct_name, records def _to_variable_type(x, records): """Convert CWL variables to WDL variables, handling nested arrays. """ var_mapping = {"string": "String", "File": "File", "null": "String", "long": "Float", "double": "Float", "int": "Int"} if isinstance(x, dict): if x["type"] == "record": struct_name, records = _record_to_struct(x, records) return struct_name, records else: assert x["type"] == "array", x cur_type, records = _to_variable_type(x["items"], records) return "Array[%s]" % cur_type, records elif isinstance(x, (list, tuple)): vars = [v for v in x if v != "null"] return var_mapping[vars[0]], records else: return var_mapping[x], records def _variable_type_to_read_fn(vartype, records): """Convert variant types into corresponding WDL standard library functions. """ fn_map = {"String": "read_string", "Array[String]": "read_lines", "Array[Array[String]]": "read_tsv", "Object": "read_object", "Array[Object]": "read_objects", "Array[Array[Object]]": "read_objects", "Int": "read_int", "Float": "read_float"} for rec_name in records.keys(): fn_map["%s" % rec_name] = "read_struct" fn_map["Array[%s]" % rec_name] = "read_struct" fn_map["Array[Array[%s]]" % rec_name] = "read_struct" # Read in Files as Strings vartype = vartype.replace("File", "String") # Can't read arrays of Ints/Floats vartype = vartype.replace("Array[Int]", "Array[String]") vartype = vartype.replace("Array[Float]", "Array[String]") return fn_map[vartype] def _arg_to_dict(x, requirements): if isinstance(x, basestring): return {"prefix": "", "position": None, "value": x} elif isinstance(x, dict) and "valueFrom" in x and x["valueFrom"].startswith("sentinel_runtime"): for r in requirements: if r["requirement_type"] == "cpu": cores = r["value"] elif r["requirement_type"] == "memory": ram = "".join(r["value"].split()) return {"prefix": "", "position": None, "value": "sentinel_runtime=cores,%s,ram,%s" % (cores, ram)} else: raise NotImplementedError(x) def _input_to_dict(i, records, remapped=None): """Convert CWL input into dictionary required for a cwl2wdl Input object. """ if not remapped: remapped = {} var_type, records = _to_variable_type(i["type"], records) if var_type.startswith("Array") and "inputBinding" in i.get("type", {}): ib = i["type"]["inputBinding"] elif "inputBinding" in i: ib = i["inputBinding"] else: ib = {"prefix": None, "itemSeparator": ";;", "position": None} name = _id_to_localname(i["id"]) if "id" in i else i["name"] return {"name": remapped.get(name) or name, "variable_type": var_type, "prefix": ib["prefix"], "separator": ib["itemSeparator"], "position": ib["position"], "is_required": True, "default": i.get("default", None), "separate": ib.get("separate", True)}, records def _output_to_dict(o, records): if "outputSource" in o: name = o["outputSource"].split("#")[-1].replace("/", ".") elif "id" in o: name = _id_to_localname(o["id"]) else: name = o["name"] out_file = "wdl.output.%s.txt" % name vartype, records = _to_variable_type(o["type"], records) read_fn_name = _variable_type_to_read_fn(vartype, records) return {"name": name, "variable_type": vartype, "output": "%s('%s')" % (read_fn_name, out_file), "is_required": True}, records def _id_to_localname(input_id): return os.path.basename(input_id).split("#")[1] def _id_to_name(input_id): return os.path.splitext(os.path.basename(input_id))[0] def _tool_to_dict(tool, records, remapped): """Parse a tool definition into a cwl2wdl style dictionary. """ requirements = _requirements_to_dict(tool.requirements + tool.hints) inputs = [] outputs = [] for inp in tool.tool["inputs"]: ready_inp, records = _input_to_dict(inp, records, remapped) inputs.append(ready_inp) for outp in tool.tool["outputs"]: ready_outp, records = _output_to_dict(outp, records) outputs.append(ready_outp) out = {"name": _id_to_name(tool.tool["id"]), "baseCommand": " ".join(tool.tool["baseCommand"]), "arguments": [_arg_to_dict(a, requirements) for a in tool.tool["arguments"]], "inputs": inputs, "outputs": outputs, "requirements": requirements, "stdin": None, "stdout": None} return out, records def _requirements_to_dict(rs): """Convert supported requirements into dictionary for output. """ out = [] added = set([]) for r in rs: if r["class"] == "DockerRequirement" and "docker" not in added: added.add("docker") out.append({"requirement_type": "docker", "value": r["dockerImageId"]}) elif r["class"] == "ResourceRequirement": if "coresMin" in r and "cpu" not in added: added.add("cpu") out.append({"requirement_type": "cpu", "value": r["coresMin"]}) if "ramMin" in r and "memory" not in added: added.add("memory") out.append({"requirement_type": "memory", "value": "%s MB" % r["ramMin"]}) if "tmpdirMin" in r and "disks" not in added: added.add("disks") out.append({"requirement_type": "disks", "value": "local-disk %s HDD" % r["tmpdirMin"]}) return out if __name__ == "__main__": main(*sys.argv[1:]) bcbio-nextgen-1.2.9/scripts/vagrant.sh000077500000000000000000000010211415626112400177330ustar00rootroot00000000000000#!/bin/bash # Vagrant shell provisioning script https://www.vagrantup.com/docs/provisioning/shell.html set -e -x /usr/bin/apt-get -qq update /usr/bin/apt-get install -q -y build-essential docker.io python-setuptools /usr/bin/apt-get -y autoremove /usr/bin/apt-get clean /bin/systemctl start docker.service /usr/sbin/usermod -aG docker vagrant NEW_PATH='${HOME}/local/share/bcbio/anaconda/bin:${HOME}/local/bin:${PATH}' /bin/grep -qxF "PATH=${NEW_PATH}" ~vagrant/.profile || /bin/echo "PATH=${NEW_PATH}" >> ~vagrant/.profile bcbio-nextgen-1.2.9/setup.cfg000066400000000000000000000027661415626112400161050ustar00rootroot00000000000000[metadata] author = bcbio community author_email = biovalidation@googlegroups.com classifiers = Environment :: Console Intended Audience :: Education Intended Audience :: Healthcare Industry Intended Audience :: Science/Research License :: OSI Approved :: MIT License Natural Language :: English Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Topic :: Scientific/Engineering :: Bio-Informatics description = Best-practice pipelines for fully automated high throughput sequencing analysis keywords = ChIP-seq, DNA, genomics, pipeline, RNA, RNA-seq, sequencing, SNP, variant calling license = MIT license_file = LICENSE.txt long_description = file: README.md long_description_content_type = text/markdown name = bcbio-nextgen project_urls = Documentation = https://bcbio-nextgen.readthedocs.io/ Source = https://github.com/bcbio/bcbio-nextgen Tracker = https://github.com/bcbio/bcbio-nextgen/issues url = https://github.com/bcbio/bcbio-nextgen [options] include_package_data = True packages = find: python_requires = >=3.6 scripts = scripts/bcbio_nextgen.py scripts/bcbio_setup_genome.py scripts/bcbio_prepare_samples.py scripts/bcbio_fastq_umi_prep.py scripts/cwltool2wdl.py zip_safe = False [options.packages.find] include = bcbio, bcbio.* [flake8] max-line-length = 99 bcbio-nextgen-1.2.9/setup.py000077500000000000000000000016731415626112400157750ustar00rootroot00000000000000#!/usr/bin/env python """Setup file and install script for NextGen sequencing analysis scripts""" import os import subprocess import setuptools VERSION = '1.2.9' # add bcbio version number and git commit hash of the current revision to version.py try: git_run = subprocess.run(['git', 'rev-parse', '--short', 'HEAD'], stdout=subprocess.PIPE) git_run.check_returncode() except subprocess.SubprocessError: commit_hash = '' else: commit_hash = git_run.stdout.strip().decode() here = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(here, 'bcbio', 'pipeline', 'version.py'), 'w') as version_file: version_file.writelines([f'__version__ = "{VERSION}"\n', f'__git_revision__ = "{commit_hash}"\n']) # dependencies are installed via Conda from # https://github.com/chapmanb/cloudbiolinux/blob/master/contrib/flavor/ngs_pipeline_minimal/packages-conda.yaml setuptools.setup(version=VERSION) bcbio-nextgen-1.2.9/tests/000077500000000000000000000000001415626112400154135ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/__init__.py000066400000000000000000000000001415626112400175120ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/bcbio_vm/000077500000000000000000000000001415626112400171735ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/bcbio_vm/test_docker.py000066400000000000000000000074601415626112400220620ustar00rootroot00000000000000import os import shutil import subprocess import pytest from bcbio import utils from tests.conftest import install_cwl_test_files @pytest.mark.docker @pytest.mark.docker_multicore def test_docker(install_test_files, data_dir, global_config): """Run an analysis with code and tools inside a docker container Requires https://github.com/bcbio/bcbio-nextgen-vm """ fc_dir = os.path.join(data_dir, os.pardir, '100326_FC6107FAAXX') run_config = os.path.join(data_dir, 'run_info-bam.yaml') subprocess.check_call(['bcbio_vm.py', f'--datadir={data_dir}', 'run', '--image=quay.io/bcbio/bcbio-vc', f'--systemconfig={global_config}', f'--fcdir={fc_dir}', run_config]) @pytest.mark.docker @pytest.mark.docker_ipython def test_docker_ipython(install_test_files, data_dir, global_config): """Run an analysis with code and tools inside a docker container, driven via IPython Requires https://github.com/bcbio/bcbio-nextgen-vm """ fc_dir = os.path.join(data_dir, os.pardir, '100326_FC6107FAAXX') run_config = os.path.join(data_dir, 'run_info-bam.yaml') subprocess.check_call(['bcbio_vm.py', f'--datadir={data_dir}', 'ipython', f'--systemconfig={global_config}', f'--fcdir={fc_dir}', run_config, 'lsf', 'localrun']) class TestCWL: """ Run simple CWL workflows. Requires https://github.com/bcbio/bcbio-nextgen-vm """ @pytest.mark.cwl @pytest.mark.cwl_docker @pytest.mark.cwl_docker_somatic def test_cwl_docker_somatic_workflow(self): with install_cwl_test_files() as workdir: with utils.chdir(os.path.join(workdir, "somatic")): subprocess.check_call(["bash", "./run_generate_cwl.sh"]) if os.path.exists("cromwell_work"): shutil.rmtree("cromwell_work") subprocess.check_call(["bcbio_vm.py", "cwlrun", "cromwell", "somatic-workflow"]) @pytest.mark.cwl @pytest.mark.cwl_docker @pytest.mark.cwl_docker_joint def test_cwl_docker_joint_calling_workflow(self): with install_cwl_test_files() as workdir: with utils.chdir(os.path.join(workdir, "gvcf_joint")): subprocess.check_call(["bash", "./run_generate_cwl.sh"]) if os.path.exists("cromwell_work"): shutil.rmtree("cromwell_work") subprocess.check_call(["bash", "./run_cromwell.sh"]) @pytest.mark.cwl @pytest.mark.cwl_docker_rnaseq def test_cwl_rnaseq(self, install_test_files): with install_cwl_test_files() as work_dir: with utils.chdir(os.path.join(work_dir, "rnaseq")): if os.path.exists("cromwell_work"): shutil.rmtree("cromwell_work") subprocess.check_call(["bcbio_vm.py", "cwlrun", "cromwell", "rnaseq-workflow"]) @pytest.mark.cwl @pytest.mark.cwl_local @pytest.mark.install_required def test_cwl_local_somatic_workflow(self, install_test_files): with install_cwl_test_files() as workdir: with utils.chdir(os.path.join(workdir, "somatic")): subprocess.check_call(["bash", "./run_generate_cwl.sh"]) if os.path.exists("cwltool_work"): shutil.rmtree("cwltool_work") subprocess.check_call(["bash", "./run_cwltool.sh"]) @pytest.mark.cwl @pytest.mark.cwl_arvados def test_cwl_arvados_workflow(self, install_test_files): """Requires ARVADOS_API_HOST and ARVADOS_API_TOKEN set""" if os.environ.get("ARVADOS_API_HOST") and os.environ.get("ARVADOS_API_TOKEN"): with install_cwl_test_files() as workdir: with utils.chdir(os.path.join(workdir, "arvados")): subprocess.check_call(["bash", "./run_generate_cwl.sh"]) bcbio-nextgen-1.2.9/tests/conftest.py000077500000000000000000000134101415626112400176140ustar00rootroot00000000000000"""Pytest fixtures and test helper functions""" import collections import contextlib from datetime import datetime import io import os import shutil import subprocess import tarfile import tempfile import pytest import requests import yaml from bcbio.pipeline.config_utils import load_system_config if os.environ.get("BCBIO_TEST_DIR"): BCBIO_TEST_DIR = os.environ.get("BCBIO_TEST_DIR") else: BCBIO_TEST_DIR = tempfile.TemporaryDirectory(prefix="bcbio_").name # /tmp/bcbio def pytest_addoption(parser): parser.addoption('--keep-test-dir', action='store_true', default=False, help='Preserve test output directory after each test') @pytest.fixture(scope='session') def test_dir(pytestconfig): os.makedirs(BCBIO_TEST_DIR, exist_ok=True) yield if not pytestconfig.getoption('--keep-test-dir'): shutil.rmtree(BCBIO_TEST_DIR) @pytest.fixture(scope='session') def data_dir(test_dir): # workaround for hardcoded data file paths in test run config files test_data_dir = os.path.join(BCBIO_TEST_DIR, 'data') # /tmp/bcbio/data with contextlib.suppress(FileExistsError): os.symlink(os.path.join(os.path.dirname(__file__), 'data'), test_data_dir) return os.path.join(test_data_dir, 'automated') # /tmp/bcbio/data/automated @pytest.fixture def work_dir(pytestconfig): """Provide and manage output directory for tests""" test_output_dir = os.path.join(BCBIO_TEST_DIR, 'test_automated_output') os.makedirs(test_output_dir, exist_ok=True) original_dir = os.getcwd() os.chdir(test_output_dir) yield test_output_dir os.chdir(original_dir) if not pytestconfig.getoption('--keep-test-dir'): shutil.rmtree(test_output_dir) @pytest.fixture def global_config(data_dir, work_dir): """Prepare a bcbio_system YAML file pointing to test data""" system = _get_bcbio_system(work_dir, data_dir) # create local config pointing to reduced genomes test_system = os.path.join(work_dir, 'bcbio_system.yaml') with open(system) as in_handle: config = yaml.safe_load(in_handle) config["galaxy_config"] = os.path.join(data_dir, "universe_wsgi.ini") with open(test_system, "w") as out_handle: yaml.dump(config, out_handle) return test_system @contextlib.contextmanager def install_cwl_test_files(): orig_dir = os.getcwd() url = "https://github.com/bcbio/test_bcbio_cwl/archive/master.tar.gz" dirname = os.path.join(BCBIO_TEST_DIR, 'test_bcbio_cwl-master') if os.path.exists(dirname): # check for updated commits if the directory exists ctime = os.path.getctime(os.path.join(dirname, "README.md")) dtime = datetime.fromtimestamp(ctime).isoformat() r = requests.get("https://api.github.com/repos/bcbio/test_bcbio_cwl/commits?since=%s" % dtime).json() if len(r) > 0: shutil.rmtree(dirname) try: if not os.path.exists(dirname): print("Downloading CWL test directory: %s" % url) os.makedirs(dirname) os.chdir(os.path.dirname(dirname)) r = requests.get(url) tf = tarfile.open(fileobj=io.BytesIO(r.content), mode='r|gz') tf.extractall() os.chdir(dirname) yield dirname finally: os.chdir(orig_dir) def _get_bcbio_system(workdir, data_dir): system = _get_bcbiovm_config(data_dir) if _config_is_invalid(system): system = _get_system_config(workdir, system) if _config_is_invalid(system): system = os.path.join(data_dir, "post_process-sample.yaml") return system def _get_bcbiovm_config(data_dir): try: from bcbiovm.docker.defaults import get_datadir datadir = data_dir or get_datadir() sys_conf_file = os.path.join(datadir, "galaxy", "bcbio_system.yaml") system = sys_conf_file if datadir else None except ImportError: system = None return system def _config_is_invalid(config_fname): return config_fname is None or not os.path.exists(config_fname) def _get_system_config(work_dir, system): try: _, system = load_system_config( config_file="bcbio_system.yaml", work_dir=work_dir ) except ValueError: system = None return system @pytest.fixture def install_test_files(data_dir): """Download required sequence and reference files.""" DlInfo = collections.namedtuple("DlInfo", "fname dirname version") download_data = [ DlInfo("110106_FC70BUKAAXX.tar.gz", None, None), DlInfo("genomes_automated_test.tar.gz", "genomes", 34), DlInfo("110907_ERP000591.tar.gz", None, None), DlInfo("100326_FC6107FAAXX.tar.gz", None, 12), DlInfo("tcga_benchmark.tar.gz", None, 3), DlInfo("singlecell-rnaseq-test-data.tar.gz", "Harvard-inDrop", 1) ] for dl in download_data: url = f"https://bcbio-nextgen.s3.amazonaws.com/test_data/{dl.fname}" dirname = os.path.join( data_dir, os.pardir, dl.fname.replace(".tar.gz", "") if dl.dirname is None else dl.dirname ) if os.path.exists(dirname) and dl.version is not None: version_file = os.path.join(dirname, "VERSION") is_old = True if os.path.exists(version_file): with open(version_file) as in_handle: version = int(in_handle.read()) is_old = version < dl.version if is_old: shutil.rmtree(dirname) if not os.path.exists(dirname): _download_to_dir(url, dirname) def _download_to_dir(url, dirname): subprocess.check_call(['wget', '--progress=dot:giga', url]) subprocess.check_call(['tar', '-xzvpf', os.path.basename(url)]) shutil.move(os.path.basename(dirname), dirname) os.remove(os.path.basename(url)) bcbio-nextgen-1.2.9/tests/data/000077500000000000000000000000001415626112400163245ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/data/1_explant/000077500000000000000000000000001415626112400202175ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/data/1_explant/Hsapiens_Mmusculus_1.fq.gz000066400000000000000000000053171415626112400252430ustar00rootroot00000000000000h:SHsapiens_Mmusculus_1.fqZɒ:7[- RQļ9EZj;:Y[VV9q!e*$_A.^22kޥ)S>MN1Ho3wv) tcx兾y*$k*;Lx)Sěsv@u\4LMTΙ s#оŕ/n SgW7*`:GڿF& 00gaV :@tz^C:x/ɴ 9]dR׎]n?s?oئ`0<_DeS_Ůknz&y$0B[UڊtOT:ޖ4MܼK\p RHu+j˥6τ<W+W#ۨM3@Ӕ[*-ٺu% Umjc>J6?|FJJ g^hJT` 11[3jA?zun|z_6 KtSh4V/?ciV<eZ8Y^T*rT0a/3[)4$ v X?Π%>Ya 4Pv5 E4sam@XoL҂ _45_6fR V|[ :r;L L78]N1Asi!F+$}c9jBV>$ցAi綊(QQPNrcV5 w@+AA S߻} )UW![P4D]~@.V0=NT2+ܸcaeܲ7 !}Cl1 mnSBuZJbŽyخ*KR1ثøϽ:apPӹ7$  ޞk QP?tI(~:bxLSLU\%"e`)}R3|#0fШ3Tfd2Ps?Gf'YsX5#Q}X).uRcuFJ'y  \K6뺁N %W}HZKjPBeI]03:4su_~)mI,!xPފw9=,|XAJa}Ut.Dss_ܑ6(V9o!T\rv{`h_b`!}p jue(riqeIx<|n CLү>A)e xF"4ҥt.V[%dŇ^]WGY*+OÔw7c t>Ak"XIwxL;TU6H[ԗt=8h̻\hn 6`Qkԇf1P4٪q|}yK6t?@NT$um`,i͔WS]#&2M,mӯq1u`σ9cA"JFD 3irRIvcJ'pC@QλK`LR>Ŵ؞Ώ[3p2F-T$[I1Nӆ=&Ss|YL[*eL`uG.2~񵏇+ikc@MU5X"{Z,\",[ [ɓ'IŮ<]phi3ʐ"=;'ԝsOHT:H2XLs<a eoڈbpC}3抵<]Fq xã+\R`sVXxPBMki-Bkk"@ݐ(t|\Jx9e1T׎]n_s?o1up1Mukng6 }ƾϡih☇J*U*XAnkZc7 p|VDAd(.FRHc|Pmy+4Z4 FafhgkK&) dUV,Pfߴv 획I]PKZ+*Ƽ <E @<1ÏozI*UQ7nq,ٕ3Tx.h8\N!ЪNY0>i 6`v6E쐧4sm@XoL+>i7[l>,M`5T;I(cd^`Pqס@mfJ`cRŸe^ rMŶ8^Kќ땺A.tSuoL Y,@Qzhīyx[˜5[]/t\٢kN>"msg2q]cToYcwaej5S! Y MKL?P.vD@kOۑzwxSuU&-|2 JgEA~Ӱ3RN慓 zrs_z(U; a { RHStڔ!&n㴓$4E9g+/%|F@':d@ЯOxMY-lCj+%"١Dv.jNKJoѮ{9`Zt^rJǭWli~-NzQ)Xِ4|^Kխ>AQ"aIzwH{?{ǰ]hrgm"װwϢkiYNwDPRjfr:kj.+;s\Mr_y1vb6]+s43$ʞaR(#zaF:P*]n [92yw qc*Xާ6Vp |F! 2p簴$?d-ip8d^{j}J 2i77JQ-GUy|>4qrZ.՜TE_inU.U ZT.)IeZv'W?d镧fY{تc F dZ^ݠ hg577Sw|arE5.>ߝU"_uܺn^Wv|m SY.bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/000077500000000000000000000000001415626112400211445ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/VERSION000066400000000000000000000000021415626112400222040ustar00rootroot000000000000002 bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/harvard-indrop-v3-b1.txt000066400000000000000000000066001415626112400254550ustar00rootroot00000000000000AAACAAAC AAACACGG AAACACTA AAACCGCC AAACGATC AAACGTGA AAACTACA AAACTGTG AAAGAAAG AAAGAGGC AAAGCCCG AAAGTCAT AAATAGCA AAATTCCG AACAAATG AACAGAAC AACAGCGG AACGATTT AACGCCAA AACGGTAG AACGTTAC AACTCAGT AACTGCCT AAGAACAG AAGAAGGT AAGAGTAT AAGCCTTC AAGCTCCT AAGGATGA AAGGCGCT AAGGGACC AAGTATTG AAGTCCAA AAGTCGGG AAGTGAGA AAGTTGTC AATAAGGA AATACATC AATATGAC AATCCGGC AATCGAAG AATCGTTC AATGGCGT AATGTATG ACAAAGAT ACAAGTAG ACAATCTT ACACCAAG ACAGATAA ACAGGCCA ACATCTCG ACATGGAC ACCAACCC ACCAAGGG ACCACAGA ACCAGTTT ACCCATGC ACCCGATT ACCCTCAA ACCGTCGA ACCTGAAG ACCTTCCC ACGAATTC ACGACGAC ACGCTTAA ACGGAGCA ACGGCAGT ACGGGTTA ACGGTTGG ACGTAAAC ACTAATTG ACTACCCG ACTAGAGC ACTCATAC ACTCGGAA ACTGCTGG ACTGGTCA ACTTCGCT AGAAACCA AGAAAGTG AGAAGCTT AGAATCAA AGACCTCA AGACGAGG AGAGAGAC AGAGGTGC AGCAACGC AGCACGTA AGCATGCC AGCCATCT AGCGTGGT AGCTCCAC AGCTTCGA AGGACACA AGGAGTCG AGGCAATA AGGCCGAA AGGCGTTT AGGGACTG AGGGTAAA AGGTAAGC AGGTATAT AGGTTCCC AGTAATGG AGTAGTTA AGTCACAA AGTCCGTG AGTGCTTC AGTTGAAC AGTTGCGG AGTTTGTA ATAACAGG ATAAGCTA ATACACCC ATACTCTC ATAGATGT ATATGCAA ATATGGGT ATCAATCG ATCAGGGA ATCCCACC ATCCGCAT ATCCTAGT ATCGCGCT ATCGTAAC ATCTTGGC ATGACAAC ATGACTTG ATGCATAT ATGCGGAG ATGGGCTC ATGGTCTG ATGTGCCG ATTACCTT ATTATTCG ATTCTGAG ATTGAAGT ATTGGCCC ATTTCCAT ATTTGTTG CAAACATT CAACGCAG CAAGGAAT CAAGGGTT CAAGGTAC CAATCTAG CAATTCTC CACAACCT CACAAGTA CACTAACC CACTTGAT CAGACTCG CAGATGGG CAGGTTGC CAGTTTAA CATGACGA CATGCTGC CATTCATT CATTCGGG CATTTCTA CCACCTCT CCACGTTG CCAGACAG CCAGCGAA CCATATGA CCATCCAC CCATCGTC CCATGCAT CCCGTAAG CCCGTTCT CCCTCTTG CCCTGTTT CCCTTGCA CCGACTTT CCGAGATC CCGATACG CCGGAAAT CCGTAGCT CCGTCTTA CCTACGCT CCTATTTA CCTCATGA CCTTTACA CCTTTGTC CGAAACTC CGAACCGA CGAAGAAG CGACATTT CGAGGCTA CGATCCAA CGATGGCA CGGACTAA CGGCTGTA CGGTGAGT CGTACCGA CGTCGAAT CGTGCAAC CGTGGGAT CGTGTACA CGTGTGTT CGTTGCCT CGTTTCGT CTAACGCC CTACGGGA CTAGACTA CTAGCACG CTAGTAGG CTCAAACA CTCACATC CTCCCAAA CTCCTCCA CTCGGTGA CTCTATAG CTCTGCGT CTGAAGGG CTGAGCGT CTGCGATG CTGCTAGA CTGGAACA CTGGGTAT CTGTCGCA CTGTGACC CTGTTAAA CTGTTGTG CTGTTTCC CTTAGGCC CTTAGTGT CTTCTACG CTTTATCC CTTTCACT CTTTGGAC GAAAGACA GAAATACG GAAGATAT GAATCCCA GAATGCGC GACACAAA GACACCTG GACTAGCG GAGAAACC GAGCGGAA GAGGAGTG GAGGGTCA GAGTGTAC GATACGCA GATGCAGA GATGGTTA GATGTGGC GATTAAAG GATTACTT GATTGGGA GATTTCCC GCAAACTG GCACTCAG GCATCACT GCATCGAG GCCAAAGC GCCAACAT GCCTGGTA GCCTTGTG GCGCTGAT GCGGTAAC GCGTATTC GCGTGCAA GCTAAGTT GCTACCGT GCTATGGG GCTCGTAG GCTTCTCC GGAACGAA GGAAGTCC GGACTGGA GGACTTCT GGAGGTTT GGAGTAAG GGATTGTT GGCAAGGT GGCACTTC GGCCCAAT GGCGACAA GGCTATAA GGCTTTGC GGGAGATG GGGATTAC GGGCATCA GGGTCATT GGGTCTAG GGTAAATC GGTAGCCA GGTCCTAA GGTCTTTC GGTGTCGA GGTTACAC GGTTAGGG GGTTGAGA GTAAACAA GTAAGCCG GTAATCTG GTACGCTT GTACGGAC GTATACGT GTATTGAC GTCAAGAG GTCAGACC GTCAGGTT GTCCACTA GTCCGTCA GTCCTTGC GTCTAATC GTCTGGAA GTCTTCCT GTGAACTC GTGAGGCA GTGATAAA GTGCCCAT GTGCGAAG GTGGTGCT GTGTCACC GTGTCAGG GTTACTAG GTTCTGCT GTTGTCCG TAAACCGA TAACTTCT TAAGGGCC TAATCCAT TAATGTGG TACCCTGC TACCGCTC TACCTAAG TACCTCCC TACGCGAG TACGTTCG TACTGAAT TAGATCAA TAGCCACA TAGCGGAT TAGGCTTT TAGGTACG TAGTAGCC TAGTCTCT TATCCACG TATCTGTC TATGTGAA TATTAGCG TCAAATGG TCAAGGCG TCAGCCTC TCATACCA TCATAGCT TCATTTCA TCCAGAAG TCCCTGGA TCCGACAC TCCGCTGT TCCTATAT TCGACTGC TCGAGTTT TCGCAATC TCGGTCAT TCGTGGGT TCGTTCCC TCTAAACT TCTATTCC TCTGATTT TCTTTGAC TGAATAGG TGAATCCT TGACGTCG TGAGAGCG TGAGCACA TGCACCAG TGCCGGTA TGCGACTA TGCTGACG TGCTTCAT TGCTTGGG TGGAAAGC TGGACGGA TGGCTAGT TGGGAATT TGGTGTCT TGGTTAAC TGTTATCA bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/harvard-indrop-v3-b2.txt000066400000000000000000000066001415626112400254560ustar00rootroot00000000000000GTTTGTTT CCGTGTTT TAGTGTTT GGCGGTTT GATCGTTT TCACGTTT TGTAGTTT CACAGTTT CTTTCTTT GCCTCTTT CGGGCTTT ATGACTTT TGCTATTT CGGAATTT CATTTGTT GTTCTGTT CCGCTGTT AAATCGTT TTGGCGTT CTACCGTT GTAACGTT ACTGAGTT AGGCAGTT CTGTTCTT ACCTTCTT ATACTCTT GAAGGCTT AGGAGCTT TCATCCTT AGCGCCTT GGTCCCTT CAATACTT TTGGACTT CCCGACTT TCTCACTT GACAACTT TCCTTATT GATGTATT GTCATATT GCCGGATT CTTCGATT GAACGATT ACGCCATT CATACATT ATCTTTGT CTACTTGT AAGATTGT CTTGGTGT TTATCTGT TGGCCTGT CGAGATGT GTCCATGT GGGTTGGT CCCTTGGT TCTGTGGT AAACTGGT GCATGGGT AATCGGGT TTGAGGGT TCGACGGT CTTCAGGT GGGAAGGT GAATTCGT GTCGTCGT TTAAGCGT TGCTCCGT ACTGCCGT TAACCCGT CCAACCGT GTTTACGT CAATTAGT CGGGTAGT GCTCTAGT GTATGAGT TTCCGAGT CCAGCAGT TGACCAGT AGCGAAGT TGGTTTCT CACTTTCT AAGCTTCT TTGATTCT TGAGGTCT CCTCGTCT GTCTCTCT GCACCTCT GCGTTGCT TACGTGCT GGCATGCT AGATGGCT ACCACGCT GTGGAGCT TCGAAGCT TGTGTCCT CGACTCCT TATTGCCT TTCGGCCT AAACGCCT CAGTCCCT TTTACCCT GCTTACCT ATATACCT GGGAACCT CCATTACT TAACTACT TTGTGACT CACGGACT GAAGCACT GTTCAACT CCGCAACT TACAAACT CCTGTTAT TAGCTTAT GGGTGTAT GAGAGTAT ACATCTAT TTGCATAT ACCCATAT CGATTGAT TCCCTGAT GGTGGGAT ATGCGGAT ACTAGGAT AGCGCGAT GTTACGAT GCCAAGAT GTTGTCAT CAAGTCAT ATATGCAT CTCCGCAT GAGCCCAT CAGACCAT CGGCACAT AAGGTAAT CGAATAAT CTCAGAAT ACTTCAAT GGGCCAAT ATGGAAAT CAACAAAT AATGTTTG CTGCGTTG ATTCCTTG AACCCTTG GTACCTTG CTAGATTG GAGAATTG AGGTTGTG TACTTGTG GGTTAGTG ATCAAGTG CGAGTCTG CCCATCTG GCAACCTG TTAAACTG TCGTCATG GCAGCATG AATGAATG CCCGAATG TAGAAATG AGAGGTGG CAACGTGG CTGTCTGG TTCGCTGG TCATATGG GTGGATGG GACGATGG ATGCATGG CTTACGGG AGAACGGG CAAGAGGG AAACAGGG TGCAAGGG AAAGTCGG GATCTCGG CGTATCGG ATTTCCGG AGCTACGG TAAGACGG AGCGTAGG TAAATAGG TCATGAGG TGTAAAGG GACAAAGG GAGTTTCG TCGGTTCG CTTCTTCG AAATGTCG TAGCCTCG TTGGATCG TGCCATCG TTAGTCCG TACAGCCG ACTCACCG TCGGTACG ATTCGACG GTTGCACG ATCCCACG TGTACACG AACACACG AGGCAACG ACGAAACG GGCGTTAG TCCCGTAG TAGTCTAG CGTGCTAG CCTACTAG TGTTTGAG GATGTGAG TTTGGGAG TGGAGGAG TCACCGAG CTATAGAG ACGCAGAG CCCTTCAG ACGCTCAG CATCGCAG TCTAGCAG TGTTCCAG ATACCCAG TGCGACAG GGTCACAG TTTAACAG CACAACAG GGAAACAG GGCCTAAG ACACTAAG CGTAGAAG GGATAAAG AGTGAAAG GTCCAAAG TGTCTTTC CGTATTTC ATATCTTC TGGGATTC GCGCATTC TTTGTGTC CAGGTGTC CGCTAGTC GGTTTCTC TTCCGCTC CACTCCTC TGACCCTC GTACACTC TGCGTATC TCTGCATC TAACCATC GCCACATC CTTTAATC AAGTAATC TCCCAATC GGGAAATC CAGTTTGC CTGAGTGC AGTGATGC CTCGATGC GCTTTGGC ATGTTGGC TACCAGGC CACAAGGC ATCAGCGC GTTACCGC GAATACGC TTGCACGC AACTTAGC ACGGTAGC CCCATAGC CTACGAGC GGAGAAGC TTCGTTCC GGACTTCC TCCAGTCC AGAAGTCC AAACCTCC CTTACTCC AACAATCC ACCTTGCC GAAGTGCC ATTGGGCC TTGTCGCC TTATAGCC GCAAAGCC CATCTCCC GTAATCCC TGATGCCC AATGACCC CTAGACCC GATTTACC TGGCTACC TTAGGACC GAAAGACC TCGACACC GTGTAACC CCCTAACC TCTCAACC TTGTTTAC CGGCTTAC CAGATTAC AAGCGTAC GTCCGTAC ACGTATAC GTCAATAC CTCTTGAC GGTCTGAC AACCTGAC TAGTGGAC TGACGGAC GCAAGGAC GATTAGAC TTCCAGAC AGGAAGAC GAGTTCAC TGCCTCAC TTTATCAC ATGGGCAC CTTCGCAC AGCACCAC GGTGACAC CCTGACAC CTAGTAAC AGCAGAAC CGGACAAC TCGGTTTA AGAAGTTA GGCCCTTA ATGGATTA CCACATTA GCAGGGTA GAGCGGTA CTTAGGTA GGGAGGTA CTCGCGTA CGAACGTA ATTCAGTA TTGATCTA TGTGGCTA ATCCGCTA AAAGCCTA CGTACCTA GGCTACTA AGAGACTA CGTGGATA GACAGATA TTCACATA CGCTAATA CCATTTGA CGCCTTGA GAGGCTGA TGGTATGA AGCTATGA TGAAATGA CTTCTGGA TCCAGGGA GTGTCGGA ACAGCGGA ATATAGGA GCAGTCGA AAACTCGA GATTGCGA ATGACCGA ACCCACGA GGGAACGA AGTTTAGA GGAATAGA AAATCAGA GTCAAAGA CCTATTCA AGGATTCA CGACGTCA CGCTCTCA TGTGCTCA CTGGTGCA TACCGGCA TAGTCGCA CGTCAGCA ATGAAGCA CCCAAGCA GCTTTCCA TCCGTCCA ACTAGCCA AATTCCCA AGACACCA GTTAACCA TGATAACA bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/harvard-indrop-v3-sample_barcodes.txt000066400000000000000000000003301415626112400302700ustar00rootroot00000000000000ATAGAGAG AGAGGATA CTCCTTAC TATGCAGT TACTCCTT AGGCTTAG ATTAGACG CGGAGAGA CTAGTCGA AGCTAGAA ACTCTAGG TCTTACGC CTTAATAG ATAGCCTT TAAGGCTC TCGCATAA TTACCTCC CAGTTATG CCTTTACT GACGATTA GAGACGGA AGAAAGCT ACGCTCTT CGCATTCT bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/klein-v3_R1.fq.gz000066400000000000000000000012221415626112400241020ustar00rootroot00000000000000,mXklein-v3_R1.fq1 1~Oa/Hv]CpcecE'}S|>)zۥ4OS>|I3))r @mhI[lK",p1crok9&[mZ6ZzߎIև>f?Ǹ:fY3};'?˶W=KX8~lҗZc.Wlqĺ)G1P]>;՟uk^Nhme|NYﺯ6/mHB] >˾n7!d:e912I`:||'m@QUڬiN1e\L:kދi4D-N1!iQf?h|JM(79uiJS)>mX'T˚lIXëy|aYIJ~hjo /1;mL0N" Zg w!RrPe`]Nq!5{kMgU?1 |yJu#Dy:GbW|N 4ň~A/1]y.-CUqhnM1cD],&tI^ M\֩ b&:Zf1`ϻǕj(6z"q* C*G4+u X:j5YYW4m7kYsg-ke|WR`IM/ė$ƥ;fߏߓ%љ8ÈF}Muf%BBrkT&άZo${D.^B: ͵[ꑜ Iu[pxS@Y\+dwN;`EOtU?4t͂zXwJud-LL\@c>e$TcQ,\ۓh$o:L^OFHG${cTLJ WҞM+SuU4N拉ʒX vnRþ,Q>"(km(֫K_P`5C`X׫Ӽ kXw 嘃uEPT~N^"\{Զta!bb c8#J :}-?vRBAwqۄ-TTi=:sY+оJh.+:Ql:5nL ;g zцN%Ġ^4#xM^9G.f^yHsw rPSg-K՜|s|}L5VsB=]Tj$åbyB޴lg:A S#Ke4j_zq /5p 7FqMrȚiZ;uN;~*a&%fHN߉QXv?~3hfpR/pѝ4P–;iN$:i;UY|qN + zfᮘ qIs}VXcYC&[GD#}<;3$$=2~Css$fx ;F+>'~-4Bvxu%)\g34+,D-A3d7eRy1Wn|NLMPHcrvP H_@9\:+ǃ˙1>46),>~%krKotJ ]-GAHieu>> [ɡ9[M_֛sڇ|\ {׬\չ D 2c<"cv.nMF5OމXo)fhtMtpѝ{a?No#]s1;wDwZ=|ӟ@E]XCLQ w?X:)tmB}OKr`m=XKf} 4P ft}Z{os)anM?I4G!5s`tAk">V.#))y]v7=$jhhCis&]x\i=}n\塆}'uMpڴTOb? U =IA2{&YhiU أU##!qV.@_$aNqdb{u[!q#E;BBSA,Osvģ|#i6LE/6SW˄!Lc$\!&۹pGLNXsN݋TM+Fmy`9>)5|$." [0:g-MAZ*UQ AV"RCQ|\/fLDaXU+mFSD1'l]1rbJ;PȒ8^ȨGbsJXhƫE gWA2lZ`CAmFNC82jw6],~lZ,86kYW ,;Oh`f#a#* iVgQ.:1\Ϩ?"])@cKy4xެgFp#~H&#$Mt^d 1) W=sM.>7"Dﴳ7޶C T{t.9u 2pB ErEy2__$5,WYG޽HXZߟҧN&W[ZBlcE;g4|c6ZRszS#WLԜweH:2.q~ux`nqRzSVzf݇bRQT6ڃJ6yDV ;1ʃHg)s(&ٞkۯvn'\ܑio]+Vz:Ax.ͲӐ/D+!; |5o4!x+J'[i,E1Ќ1 N%>%'M_x-\0>…""-`0S)#AXP ܡt3;iqbsi 0靈> S[ij0dOw<_Ζ3:Ǯ"=>FHf:޺\/[ FC'εޓF7,[޴ڃJ悉@F_H`?5ڲXfryl/_R),u߇cz 8iPA./,q]ѭ+xi༖l,} 9dIGAAm 3b"U#,^_F1+ mn!2LBI۟f7vA6cy̩JҍDŽHI+(OyEǿ)4.>l "ps }}o#JBjZCK|Cmބ=؇h1"vL#yN@keG̣Zt;mB愗+8+_Jz6NùӠއBwAkI.~ )04&1wT I3s*1NijN}6nqCF1lܭkCEVN+eH ZXCXހe{Vp҂yn>#l3sγd_)(b/EjHdY8sIbz% 5F#{ShDUPH;l:HQ˽L" Eܰ4q '{(jY 6;}]+۰C2s.z O=h=^Dt&Hiݷ&s˶tX+fM{4+QKRX_C>Dڧ9&46RDAw߱^N$]î#!KG H[_`3kmm,2| |V,Ɏ[^6_p@Yֆ_ J\$K5;I/Q<zj2P9Eu4a/I= @h1>MIZ^Ebr/1.7*2aC5&=d{'{4,s{/ZPSZEte0z-V8jcI m ]Vba#qaN %s_Us,~2IM+dvY\\KaT޾V`!;h|Z~X'Q4xOY)˨4 M/$YOY5YEUG>j֨Kqn($N#ij"L#[I$o`ZӋT\]56xZ:)"L1']m rOVV+R+ 2W=@3a}!zu;;'c)YK Z_qQrA@(+zrWrPmQ-IZdUhn_۟g 8L2AB|w=$N9+ֳn]) t'\3)K t<`|$ay9`Svä z}js").rFXp *~Bs?z@ObO2l@^1+҃g>I9C7yRGo 7/o"t(TD7+_E@}&&z|̕=ȏy@Ы)H%MqoU'q,Y+@9#a ?N NIZͼ4yzH5Pbd(%m H[敠)_XJEDX$N>O?d;{p}e'7c%Bگν5Wm_)i ?_g@X= Ojr@\:pel1YnX_H#ilE۠e&N5Ky.f[*Qi4n {%IC`9%c߫OYx WʱB?tJ |AL+} wb'i$3L#O Lk ׳T+ x a&>{]νt`Z븓>6aycE 5^d.ӗMsiF}t 8X|q{oCXk s45IRys}U/޺*[6Ϭgj=}{HgYҧtpp/tFcPϠ QDуeT>NWD@XEٙϨ`"R=Iz:~{-hdeC>r>[d1͠qDK+Zi Qۦp*+Y|^979tD&n=w/c:] Fj?d֕L n$d4. tiBiNiJ?pP4eahe;^vYf IK=b'dL anZ=J~5`Ӟ r6}Ŕ遹z{#P씜:+茄$MߘºhR>J@)%_'cS5yu`'tɠ# J҃pۂNvЀ =Ј<$'p"@~'^o7 aեv2 fw; vT/Sx. 3d{OFKx^[a'$z{A^Gp\הH{J>PsM+(SLj7YîhXTN-?۵*bkgjp :۝W ^""PK *74OqJҔ3@c7@t<M~v҃C2;T3Meʪ6]y@@rU""@[@+x{_c 0c} 3Iӝ X=98r cY~N׆_{yxg[} 73\{ߵv2(eR(S6 p0ڸ>C&XN vOq=e|AbeȽUftl?8k´I: Dw* #!p÷WQAKF_M[M*x{1L;XB\9Mb!恸ԟJ~tEtǬ?98Eڇpz %}3ZMS{c=xN9oJI+1bUkK+d+qyAK-nF9Fyr]JoyE$C[_W˂byG]%qSVW nĝ+PKh3Yo=[xD>Pzs%j=璾S*%Mķɮ|KIrQ L:Fm|4SQMQeiws%\!{cX O fSk. ~7C'h&h"p^uΠH9FqEz}[4~\rlcmrR@mWz"057x]]Y2*cF)0<3~{>S=и /:sBc6o4(e٭pݜh>"KUAgԴYS&'{)"i{yDzL}슒&Hx4͓@e YF(enQT߾5!;\/O/NeчtP,i {Fr !5XZAXkIs7Os,A7РDYb*1k^H8kr O{B*88yA |j {֑\5<~F?P|z/9 jNQӀ jVn쾦$m*ӺF=} P7&v_( E; &ODC:rą :qB4$~r:\;%+ÉYHk=|.cj~nZkJa>%(ksSϴp.l ' !,1PeMX{l>?q'cfyy|lNp;YE}T_ϭkDк,z_nZoEBO^0t ! >]K)8U|P5 u9$b^7ʬ 7( ~:ԝ}rʥ .zN }"Ş! Y:c${66;v Էl { 5ZA3dH^= +4 za/ ,BJ m0?d{mi5[Ÿ8 yFɕ}zIf5rn oC'O:@XJh gZ\W26I tv wػB6h-<`Id.(}4" D琴._kuZ:x'wWb!,)u 8GA*x`vO/5N$np=mvn(`Q&AZ,iG6T_46k@yt"bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/klein-v3_R3.fq.gz000066400000000000000000000210331415626112400241060ustar00rootroot00000000000000mXklein-v3_R3.fq]ˎ8W~D-}_2צ,HT.2PEcsBm_DdrE?ܯ2z}}_ygd"9?&3>'c7'd~ q)2Z2Hx!3ʙ&5Z@ 57C-tnPD=2s!p33!:lQKt~`.fBJ4 `-]{)1,Ni@fu6 GÞJj#d`I9QzNfљ[2o'B3!8OLmÒ!%%d+D2'OX`O!WnmS6 X׆ 5JkB+uqF2QIQ뇙k63sD5!3x{mNC~N,l_/LZ2Ƹ8m[? ㊫q?d^_?-1#Fx1XweJ F{r^y%TvV i83[υsIV1S[ zq Q#f冑d`CHkx+Y[ybȚ|pO Kif@lԖp's9qP"v֎Y Be@ae- J|=Rs&Y f̄e6K܈/J;Pl<|׵ܩ}cjZfQO U$bsR&-yܷS7x[2%G8#D+5ѽJI -H'հauKkKd HWUj|oX !5̨|r"֡IX6{ȬDX$<1-Z_63zvy%HZ" Х)71%99=ք)1Zm8>oc0 Z,I>e-]zބ0W$x|`%iWMJ&j^mB!E -J(48wYŰcP]%`}>;D <swPHe klX Zg!a &t>T%پ! ZLPVrDb ZB ZylX; I|Yf-ְ<.|SxO@ij 7 ҲYw͡[ }.)} P\ Z?L#NDMDCc@'#Zs+@rV3 Y3SRM3}{5Ӽ?ڗ !ڠQ`0`BbhTPLLno ny`psVT= <3I%TK|ibOFKËJ}2rKPCv/G%kNч\Kd}we9iDZM!{ցXPtY{pñ͍źc7lc<ʑ쒒 ۔BVYq e8"Y@N+i SfTbCgj?zjFaL 0`ye#dԈN4dGc^,=:!8Sby y[7jCj(a@2>DkZsĚ?I? Y¨yÌjM~$&Q&Dy^ԥ/^𶬟]3J65t_fc) \-p<@*b䢀ɛLhfQGo6ug _$p5QHˆ\Mhɼu ItDVD||"ID6B}#dGґ3**0xWa}z'5.'8cb_42@D^iHF*-@ YӼmQ $LWCWUT׷Ժ=dݧku6M%k\7`%Q -[Bs1'0c">0b.˨O]A:e*su%m{c 0L X̬=75nVJ2J2Ni&dԇ9.3 %hԒF^3AdB*u_!Gc8A"#͡}| H2IS5YWwFiFWaѻzd\5ZTj7@e 8uiOiD}a8D#⦭ 7n(8CAӌ5{2ԛh?3%(?&K8qYPFL'6*db̕HH<egKӚyߣa2 Tkpc<8Tab#$@GeJO+oIF&\ }[`9mf>9& ux a,eqn}3~g86ZS ̦B'p5k7_k 'mȞLklPŘiS CX fBXrsTL9IV~E&&xXC jFc$O]*h*C2cɼ0Ɇ.3H% TidlC>Dj֚O#,Ԋ,r!MrBbC>TvJ!N)X4lN\䬜i|}]D!B9 CvRIX0H; ֖vh~\tKTB C" ꏡ&߱/sa2D֚ʿ V1Vșbͼ@\M U^ 9f)8tpy( e }{S!JIYQȳ 6t{ Wes ^bJ;r/>m5;-^h,R:bܜ1zׇM&}-,>~O$価'ךt|K{+O=$!`^k # f|'hd&Rݨ$үn拠.nΊQS7,PåA`& )_T^iZ0 ۩]u䋖(yo!7%?0Гs1&Ң]`e #@.}d:cM{g1DP+e vDe w;<(Jʈ9ɓ9p2w4ҙ:)nDzatpA%n6ׁ 3̒!X'kgu2S[7[G8卾ڎį}3 +$_5L?V1)՘<~U|e1M[q $2KB̶҈cY ;2 ]Y̻ +C=RN tN"> 6>e?n|އdEh3=q9O#gyUqHvh t fLdD"@C23B])pl˿r&%}dW#TG2A-!IKiSqp3 6c;qa/*3s [ s# KY#g dԂ{HS xrQ{&5a@F[̻tp$?2<NT+`F9wڃvTwY u5޿rPkco+])bI?τ/꫒ؗȤRW򁛾˂TWyw*n {u\O:=H'5SR b,GҏyFlcO88h7܊CIl̈%=.Ψ7AL>hk[+8˪#X'& ߲!0"9ܗ0u ]Z-#n}v] pKמI1 ſ-7x$\EAd$U8MTemP7cFTֹK xO}NЙ "us~8f}f֯O+5܇;CB(`܅"|7!3_z(n173Sh4%2h :%UHV_OQ~oS}Cu\"c*uRcdM ^k6ְw \qGGW:s<]n"@"N6KzmyuԃB꾧Vi{fU]$r϶9g@w0xYdJ>7%HPШ;yá%*# ˋ)"fkTY4 |=3c2g9 k7X7 ?A,(Z\c`7d6$ȳN10XMWB x[Oqz|YcfiBtȠY;&vsp|zP"Fnf=m [&mw iCƻ3}HUX&{A(ĊIK\(,왙~iַ{&q{P) Ɣ:92a|Ow%{aH)_rNRSP@ +Ȓ"0'V T u5nE>'Ce>8fY#y(ޒhx=IڶC2= =3( _rɜeo/{jDC}P=U>D>{.K=[$A揈6esßOcY7IKX=NHfM@k@x%ὯbcQB17*| A*{J&mM HeJbՔ 4MR$3Hj `e.@=F޷J,IMmLzCE,Q3 %N3c*H\bAyCf.|n;v&$U'Tg6mXL<B8/;RtV_!\-M&PY"O/[ZȌmov4غ %:= <-yε ȇi!Y>g40R&1"ߦ;S9ILC=v}f`{Z'zIgs |@IM FZEPn^1n!k>앳Gm *~≧d-fْ[3*uT(aH7__ J$HX"; Wak%{ڐփKo F"X J0]35/& ;ON*an^XwʾyWn pȾ*{xk?1 B:1hȓmdjGeiF m)CG3_jz%_O_Pi̍,)bO\3,BKN<q%yƌ5N;Y#Ȥ Z2Zk0fbFr@C8DZi?)-64|>Ƕ+x1:㻢ppT>XIjn> ize:>V"lrSB>VR+#JkҤِU+g5FHH|2F r&:mh@On-< 5&:坘S 6'd] -uut$$ 2[ї/1e81nZmUIfy:Ƶ{관Ba'}m]|^wҶ$_{ric"ͼ >ae urܼ}9azn>: qːiɍ)ֶ7?M?3˾@B+nO6|!ǥeUN} Q̍0͒[eلF~ '_VZ;k$| @BӺTDq. 3Ӏth+ \HҥXƶm3ʐC\b{IW!2Fn^q2>K蛑^5gr6kL!ZN7E=bO {ÉUb+9ijyo8j^tDu>yH%d"?N=LVz:dJK(&!LYo 21J:T* Rx Df=+8@Phn|d mu(e[b [jgUSdE> z-Щܐ)7sl|{u{cs LپHdo陀@Hlq+L[2>D&kȼ~hѺա3(N!wBwOS[^ A=6G] ]*B!H(r|M E#A5 %#@''M4}ۻ̸%82HC닺EFkͭ>M}2m.!Oqq,hq"-[gx{HfWbo]T Zot+C4LEtQTܫ)K-,ae/]i sfT, KR `Xs! Y_NSvG_+̈ }_ R>yKDMF`iKrC! NPv'`_ XK@W o(@*2`ˡiLgk){} *B{ r3h0 ?8@C/ $r|I>%#=H\fЮeo`U=9)!`\+OJ`$avyk4oϤ6!@NAR>jpd8W|ei ܘu+ ybkC]`/cAKk=ܥ^XЧi Lз% B$H{~| Yɇk_7 &d\i$& }à ڿ tF? )Qa ~s'3&A!68zU{X)bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/klein-v3_R4.fq.gz000066400000000000000000000334431415626112400241170ustar00rootroot00000000000000mXklein-v3_R4.fq]ɪ%9sSyhraY`"L)tN螾Mn 2/FcPZe뿔_/)~;_Ro毿_Lϯ?I/!$!d$%q|wJim$<m+ d2F)W}ypI>ezcWtT$Kֆ~2_$!d|9fHE8ŋE-NbN %KT A[.R_Aڧ RΓ]So%<ɗtn%W\iO.M"B!xb{˵Gk۫0 h(Wڅ*)/$DR1Oy[.Q9~rv'Kp蜜7”ӗ\1BVh0-}JkPZ2J9-+eQ~$O+n,%#EΓ{ۚӉAC@NHIml$N ^Jq% J]t:N rRQ-D//18z#O\!#}eе!+2@mF&B{/xZxj3oU%b9e,d7FMƒ|ʴ&S~ƓI>e$$]+j5ވ)Bt)WuA-qE2dpyV(JFӝ \XbDf/U6++I|g~F}ɓ&Rv$@=dQN8&НK(bQ7U*9bm3oW1`ҷ?噿A.tp$Սm^$ߘS 0;2u/@Me. .0ȓXs!l3V PuL)2F?YSu苢(o齿BV ʲ)"NJS` ^yk?ijJ'PA_΅TX~-_ٟ2q;G+P;WXGC J(-9e)N%Q7R&4C~i/X!!(s)aq2Hpwyy&g%UJIf>);iNؽ/)BY[*]QJՕT93|%~sb" 4ހ6dpp]o+0z[错k.ԇI]tM$K+k&`hMb)՘*p S^*im{OWkRN24 2Qr;T[_RqcA3wkҘI*Rd(J_-Ѵ"d3-"PvOyӇ%eT`t9˶ԋ߅&"y~ K;Ķ`tDZ3Ԛ_b5ߓPv 7SSKvRG>8e1-wr.Eh;7L}~WӒ d|6*iD&3V3$Jz|mjm_1[Nlek27hf ѿ; }[̝0Oamw*>Ƿk=mww#wxM,΅?f7@r>Q Q֢^,C"@ )e$TN&r0c.ёjA3"#,-CKF-6N31|w9Y6D̐t|IUpj~FX5i# YltZ_ vr;S 9Sȭ]܄& Yo4N)..El%%vo>'3VNǗ_)G1&'.1PMA _} R$a6@7Ka-B_d6rJ=B1!dRGO6'/!:+4nךg't=}|h.u\XW!#bSbw\4h)?^9Wki3N4|`Ƚp; NtmfX+a R*{>n [>OŶrf6J֑|7RVmwV!oJ(5}s+d'2YR̖RtN[@/It-pveDr[ˮa&gN?~’/i)S Tm%No0A- B#}P!׎寈C}CJᅚdKk7!}Po,µˀlHfĶ. 55j)}RIIhVE5!ԓL2uvm=VtȪB /Xˉd >G H;t{lW XGt$驸N{ȽAx-%rN\N?edb_{K(v~mA߻ĵBtoʝkc4.ҋhutuL|YQz稣r${ Ayz.Jhʳ-p\`H?,NɖtXpW!AuRR6po(^|J5w!I/_3"Aeht|L]!KИ:>ēAY-(xPfv=EL 9ۂEmig]v*RK`GlUW_[z0C?e)QU\0ZzH! Oٗl1#-9O;h;vr +9I#vi{ra7˹/0!B<"I:>s {>P,ny'18N4\oX?cPddtkmT՛/loBȕ 6uƽj- WJ; d&\U;"'d)ki $3~6ɳ)FyYirƜI.ZAK;5 Sd)Br{efpI ǙFvq ӭA[$Kj F>ߠLk^І,/O:&# c*m$0Ln%/DE]MSf]M `V^T_ |Ȋ* |}!b0>ݴ%_?(HFcrf(>JDнLw"~o@Q]ebNϰK:0ܛ俖2KJI*idw~)j&mUg|ePGۗ`մ#vgΨpL/A)4WUAB'գ.Ҵ st%vܤ1BJcf@+T5=V;+8*r\Bd^koʥDPgրõS1 WJ~Tⶦjű ;.p[3kVʉ;or,+q^oYTc ){WBy ]umňXʳ[;\m`)RzNGB}e~A"掇}NV]HOd}R.+/'[^p R* 8a-^=Rr)jXP.$~<#+vzRiGET3-,I-e\,) r+ d?e 9[!R 8ޕ)3OU#"9%P]0j^}a!C 2T(< <ayиv1*]c5 ~ilؖ*j~Ap-Wi4{ȷ&[%O8Iˤ\(@p;HNʚE&M,|PQ,41:%!gGKttS.ulG1jernI:w"I i`&}Bѭeͥ 0>ڂY>2a%yС$IZߟ;0o8 F;NrjX|Ja}Qxroҽ !w`|Rg|MZuXR[1QNw`APM"}렣f"B?X P-܄7|Tvݫ 1< J4#W}aA0}Ef݋{J%x/.I%nyqpڸ$eEԤt&t;d鳟8ޥKf֒ =QRZB//>1l 3Zg/|m=J ξ])uNHF[2!oH`AJ-A7 K28F.5UȤPqo|d;>$OUF-1V|v.:OC^H Y|LzåG?6H̗~& K V23fhE2u=pkW7,M3?0jZN2Y@R4H'U}rI/9>y3yIZ_p{~Ha˳qo:1{[8d e-! wg~w${*AL"[wwAJPP2Dz|<_mReM: .}(|8igss-n`l}s$΄5i?k&->3$ 6OfG4~ ֏zӻ !I$?mk0Z(l$(/vsO]b:b[zUUPzZxL*QӸ2Qn~Plĩauol9U$K]uOIGn5119;`"zڎ; jY86L2-x-6]~/\$o %w+# A@ؙ|:?YY~P?6 ' ~ !P9 ƖH) eMMqwX1 y)?m (OT[p8Vy*@8aPЊSBR&rEqB UDunax|ԎLOG]#Sv p{R6[3yp9aTD1$Zΰqp)!m>?|d3V/. l/ݽ? J+@( Q*B{IM,xQsYHfz( AT{;sȝg$FX@q?M 6ӝwc]HG%̗)8s0;4qb)iϪeY H%ޡ}1^ p%mH:qHJ"B2/\ =heoٹ:pFPhEuVo-ϳp>es<:PJ)Tzڪ6lfBRc-b4XXVB;=$BT>&[Z3f= Հso%XҰPzďƝ;潕݌=<: %Cڹ$&ϏEw8)I2s ^uƫ q7J%dp{(/-_BB;%LmLA}𢎩VO)1tvITܹ( |߁μ2SQӾe&=9%Ԁ)|6>'\10'1Fç,ðX}(Ǡ^& XQww2c e#ɺLiL m\h ai Rgj 6 ֒'+<5(=g "2[L =:px1[jCbw e¬Q,Y,w%0vAb Ĩ\318o,Yky%ں\*D T[HRTt)cqxyg1Vd>{)@/yg^+A q6 |(V`8 MB f[>IxZTh!.H$+QD%GJݍQlTo k=%XKPƂR B ι.3. }86琪npnXsS{aho\x7cK5H\P!y{d\j =nXOˉ 2[2RlhqC A, ń].P9t ! HaCnP౐1(x ۪qN}} 頃ˍK|矈K; C+"8 ,>e1L RگEv Á>rİ%9xwjw2aw7{gX^!esq=0lV qtgy*G z'(o[qڸ6<8/ OY]mƙ{2!R(JQK9niVU[_%*aٵX,!d vʺes˫(˃{ѹQbΦޮa('7kBA٠^,f!TÆJFd,;OW|]1כa7آOl^^;#|Ȅ _⓰D&8` qt|k)q&8[NJⓞ^ P fŨЫS3 /o=Rp/CJP}U}$,d2 Ss/ 1!)ݸZbIGcsNi I@ .Q<>sGH(!C8C @ƠX^VspKF f 2z;|tDJEFO0&):ìY=p֍MkJ-1NFs;j7S(&Gi0l6 @>eX=ñȐ.2םڈU8M7\7/VFsFYTIe;'6.um̜h$B=Bi+8 W݆8U*;t~淵X$wXk"P(r3 A;GU=%5#;1:u44}..YoHVK1q;n̚ͻ79n?Flz]Q|d"Aj=Ka'οKߟr^\F# >E$F<-&B5!'!]PjcP"1v}c䐼B05 fa(l0qq|a ^J`8S^ŮXw9n1F\k4 ta5U.90|Z]vG1 k-j)33a 7Wn'DG]ցdPlͪA /0Z9J25{>w!c,%:Z&й' + ʚPd|IgX{YAv1ݰ9 6֜y*H%fV!}\Z';L*,'68ϊ!O250aTѥ=E-[-/a7<йWi(q󳾱*μx2Ea-; $⾊跶wM:`8%gIKecȤN^a`2 F-cf$2 @`& e,JgoWa0@.ytC쬠zij15@S2 5T,eN$񽀻?څ/) ֎ [_j050>.i飥gq i/ψ@ )ɶiJ +qb|y8%Y>0CuRۋ@HՌѮs̚؜X "zOaK}.ް"^ձۮ].R?;ԉ~pmۂNjʄCGތkf}o-b^'V!r9Ql>So1.!$)QÜ{QoNB8H{! 9%^: j3kSfXΜ;,X9i/qvX/AqJٲD^OFO\-3xU){1J8B;lՐ㾍߸ b+CMFrQ]5 s9;\nvwb<;g|ј{x/@1^Sç 0p&Bq 5Q𙢍:NFqw!es#l="G 6^ ZA[k:%>7mE /bΧ_-8uIHxBQ lo'9V: 95I9,6,6& XfXlmkC_k+]iDۜI2C9"QݣQajmؿG?V%ujޒbܰ*.kp NAuEVCj>Iʱ5ksm/Ve 5O!RkK4'\VX9EUgGƒYҋ/QgZm5Aa ,%'u.?jrC%׆b#cSywu=61\c݃7|K9G#!DN{Q$T0ÞGlm8"ȑc[ "R3g[1a"S#2N^v4D 17~ޑm)#{'T%nK`1G*2₰ζ$ xh sfJJ2$?RH\F ^usrav߿CeV)ftOPtuS!')m$?;,ja52w}@)Dø5n߯w@ݪNuc8`>ư3 Cf0X@Kam?ϻaތ687 o@GMIp3wVAN)=?Q{Qwߓ d=TkN`'nA6<ǯ8XaS8|]>J%' oB5R^W¦; 0J=J9ZS>2Ze'sX$J=0U5@sm҄'싇'֖J9Y2Y$u-ZI[t8RM.' 1͙<$Ts{yݮW)Yu ?N?S*s Zwhu 9omk(86KKz$xv9SRBY5Lg9%$~2BtO/e v\bq8(0Y܏z֛~FdaZ?#lcD9{5Θu]hAy̝k?`_,n Gi8 ȇl `a|z.OSB1K='Q0?.8igs``%Ye#$-{]Jq['觬[W!@/NZo>K8@b'"5jrގ)W*Cڈi v֬f-|8rCAen~gU@ۭV0H<fu'=,yt؄|&`c5!yw)ȸ!*40AԨ9 (V,Ɩ=RI%v`'Ak@>_@0#tapI~6mjz#wGj Qw^CԞ e]1=]*l-¿ {{'5/TNﵒޓoQ[i:E} L+a*OvXA:|[X+!jA$=9Õ;M)Srֲy x0̐%uMDi5@"G^FHVAjbMd]R wZ4@b 4ȧLg}%~ ` Qhka.*#C-Nn.Bce 냄BwѪYդgTei(&M5ıȥo7NW+ChR/&$T;Ʒ 3l54+֠ѿXՁ^[7w s6_ ho.~ w/S hu&>X[(t,ȽBZRA?qK\D` Ŭ]|hp=ŏ !XS1;y?TyE[Ģ Bf%-<'&RQ w1L,^f Mר5J.{o$ll:;ON΂g ΢qtGH/qj`(k61dNHV"J=r pe mLTQFT? P_{b@сS*\H"L7EځrqxY^~Iut7ևjgyY|Swm]'/*N^"7Ɣ|r[GŚ 9f;Vv NoYt xTvpt):S[bv@^&ý9D}VGD]p{O:W=w+s;=BP:k6l6( []#2cK !O+ w{cF; aVA}w‡wNp[7uSv[-Jz$ԜłJ)ϺU[ĺS15=W}ܛ®X0e-BgUnb0 R-kL3a\;:z5Ӯtsxs#ZԓħAJ^b1bd1WI)1rzXaRc"AʕP`goiӰUƶ<| y@'ͻy[f- k{I?dngW_N͒k6UCYo0HQ(qWn(n?DXv3%$絎w>]5-ī7*wY؈fDZٓ$psR8Q~JlF?[8l|3^0ǫ(q >Ux9-ފkcYC]cz:Z=.Hs0Wi ) fuS316uSSGud}bdx}Fߘ8xZP؞^f6#Z1X1y))r @mhI[lK",p1crok9&[mZ6ZzߎIև>f?Ǹ:fY3};'?˶W=KX8~lҗZc.Wlqĺ)G1P]>;՟uk^Nhme|NYﺯ6/mHB] >˾n7!d:e912I`:||'m@QUڬiN1e\L:kދi4D-N1!iQf?h|JM(79uiJS)>mX'T˚lIXëy|aYIJ~hjo /1;mL0N" Zg w!RrPe`]Nq!5{kMgU?1 |yJu#Dy:GbW|N 4ň~A/1]y.-CUqhnM1cD],&tI^ M\֩ b&:Zf1`ϻǕj(6z"q* C*G4+u X:j5YYW4m7kYsg-ke|WR`IM/ė$ƥ;fߏߓ%љ8ÈF}Muf%BBrkT&άZo${D.^B: ͵[ꑜ Iu[pxS@Y\+dwN;`EOtU?4t͂zXwJud-LL\@c>e$TcQ,\ۓh$o:L^OFHG${cTLJ WҞM+SuU4N拉ʒX vnRþ,Q>"(km(֫K_P`5C`X׫Ӽ kXw 嘃uEPT~N^"\{Զta!bb c8#J :}-?vRBAwqۄ-TTi=:sY+оJh.+:Ql:5nL ;g zцN%Ġ^4#xM^9G.f^yHsw rPSg-K՜|s|}L5VsB=]Tj$åbyB޴lg:A S#Ke4j_zq /5p 7FqMrȚiZ;uN;~*a&%fHN߉QXv?~3hfpR/pѝ4P–;iN$:i;UY|qN + zfᮘ qIs}VXcYC&[GD#}<;3$$=2~Css$fx ;F+>'~-4Bvxu%)\g34+,D-A3d7eRy1Wn|NLMPHcrvP H_@9\:+ǃ˙1>46),>~%krKotJ ]-GAHieu>> [ɡ9[M_֛sڇ|\ {׬\չ D 2c<"cv.nMF5OމXo)fhtMtpѝ{a?No#]s1;wDwZ=|ӟ@E]XCLQ w?X:)tmB}OKr`m=XKf} 4P ft}Z{os)anM?I4G!5s`tAk">V.#))y]v7=$jhhCis&]x\i=}n\塆}'uMpڴTOb? U =IA2{&YhiU أU##!qV.@_$aNqdb{u[!q#E;BBSA,Osvģ|#i6LE/6SW˄!Lc$\!&۹pGLNXsN݋TM+Fmy`9>)5|$." [0:g-MAZ*UQ AV"RCQ|\/fLDaXU+mFSD1'l]1rbJ;PȒ8^ȨGbsJXhƫE gWA2lZ`CAmFNC82jw6],~lZ,86kYW ,;Oh`f#a#* iVgQ.:1\Ϩ?"])@cKy4xެgFp#~H&#$Mt^d 1) W=sM.>7"Dﴳ7޶C T{t.9u 2pB ErEy2__$5,WYG޽HXZߟҧN&W[ZBlcE;g4|c6ZRszS#WLԜweH:2.q~ux`nqRzSVzf݇bRQT6ڃJ6yDV ;1ʃHg)s(&ٞkۯvn'\ܑio]+Vz:Ax.ͲӐ/D+!; |5o4!x+J'[i,E1Ќ1 N%>%'M_x-\0>…""-`0S)#AXP ܡt3;iqbsi 0靈> S[ij0dOw<_Ζ3:Ǯ"=>FHf:޺\/[ FC'εޓF7,[޴ڃJ悉@F_H`?5ڲXfryl/_R),u߇cz 8iPA./,q]ѭ+xi༖l,} 9dIGAAm 3b"U#,^_F1+ mn!2LBI۟f7vA6cy̩JҍDŽHI+(OyEǿ)4.>l "ps }}o#JBjZCK|Cmބ=؇h1"vL#yN@keG̣Zt;mB愗+8+_Jz6NùӠއBwAkI.~ )04&1wT I3s*1NijN}6nqCF1lܭkCEVN+eH ZXCXހe{Vp҂yn>#l3sγd_)(b/EjHdY8sIbz% 5F#{ShDUPH;l:HQ˽L" Eܰ4q '{(jY 6;}]+۰C2s.z O=h=^Dt&Hiݷ&s˶tX+fM{4+QKRX_C>Dڧ9&46RDAw߱^N$]î#!KG H[_`3kmm,2| |V,Ɏ[^6_p@Yֆ_ J\$K5;I/Q<zj2P9Eu4a/I= @h1>MIZ^Ebr/1.7*2aC5&=d{'{4,s{/ZPSZEte0z-V8jcI m ]Vba#qaN %s_Us,~2IM+dvY\\KaT޾V`!;h|Z~X'Q4xOY)˨4 M/$YOY5YEUG>j֨Kqn($N#ij"L#[I$o`ZӋT\]56xZ:)"L1']m rOVV+R+ 2W=@3a}!zu;;'c)YK Z_qQrA@(+zrWrPmQ-IZdUhn_۟g 8L2AB|w=$N9+ֳn]) t'\3)K t<`|$ay9`Svä z}js").rFXp *~Bs?z@ObO2l@^1+҃g>I9C7yRGo 7/o"t(TD7+_E@}&&z|̕=ȏy@Ы)H%MqoU'q,Y+@9#a ?N NIZͼ4yzH5Pbd(%m H[敠)_XJEDX$N>O?d;{p}e'7c%Bگν5Wm_)i ?_g@X= Ojr@\:pel1YnX_H#ilE۠e&N5Ky.f[*Qi4n {%IC`9%c߫OYx WʱB?tJ |AL+} wb'i$3L#O Lk ׳T+ x a&>{]νt`Z븓>6aycE 5^d.ӗMsiF}t 8X|q{oCXk s45IRys}U/޺*[6Ϭgj=}{HgYҧtpp/tFcPϠ QDуeT>NWD@XEٙϨ`"R=Iz:~{-hdeC>r>[d1͠qDK+Zi Qۦp*+Y|^979tD&n=w/c:] Fj?d֕L n$d4. tiBiNiJ?pP4eahe;^vYf IK=b'dL anZ=J~5`Ӟ r6}Ŕ遹z{#P씜:+茄$MߘºhR>J@)%_'cS5yu`'tɠ# J҃pۂNvЀ =Ј<$'p"@~'^o7 aեv2 fw; vT/Sx. 3d{OFKx^[a'$z{A^Gp\הH{J>PsM+(SLj7YîhXTN-?۵*bkgjp :۝W ^""PK *74OqJҔ3@c7@t<M~v҃C2;T3Meʪ6]y@@rU""@[@+x{_c 0c} 3Iӝ X=98r cY~N׆_{yxg[} 73\{ߵv2(eR(S6 p0ڸ>C&XN vOq=e|AbeȽUftl?8k´I: Dw* #!p÷WQAKF_M[M*x{1L;XB\9Mb!恸ԟJ~tEtǬ?98Eڇpz %}3ZMS{c=xN9oJI+1bUkK+d+qyAK-nF9Fyr]JoyE$C[_W˂byG]%qSVW nĝ+PKh3Yo=[xD>Pzs%j=璾S*%Mķɮ|KIrQ L:Fm|4SQMQeiws%\!{cX O fSk. ~7C'h&h"p^uΠH9FqEz}[4~\rlcmrR@mWz"057x]]Y2*cF)0<3~{>S=и /:sBc6o4(e٭pݜh>"KUAgԴYS&'{)"i{yDzL}슒&Hx4͓@e YF(enQT߾5!;\/O/NeчtP,i {Fr !5XZAXkIs7Os,A7РDYb*1k^H8kr O{B*88yA |j {֑\5<~F?P|z/9 jNQӀ jVn쾦$m*ӺF=} P7&v_( E; &ODC:rą :qB4$~r:\;%+ÉYHk=|.cj~nZkJa>%(ksSϴp.l ' !,1PeMX{l>?q'cfyy|lNp;YE}T_ϭkDк,z_nZoEBO^0t ! >]K)8U|P5 u9$b^7ʬ 7( ~:ԝ}rʥ .zN }"Ş! Y:c${66;v Էl { 5ZA3dH^= +4 za/ ,BJ m0?d{mi5[Ÿ8 yFɕ}zIf5rn oC'O:@XJh gZ\W26I tv wػB6h-<`Id.(}4" D琴._kuZ:x'wWb!,)u 8GA*x`vO/5N$np=mvn(`Q&AZ,iG6T_46k@yt"bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/sample-index.txt000066400000000000000000000000221415626112400242650ustar00rootroot00000000000000AAAGCCAC TCGCATAA bcbio-nextgen-1.2.9/tests/data/Harvard-inDrop/transform.json000066400000000000000000000003711415626112400240530ustar00rootroot00000000000000{ "read1": "(?P[^\\s]+).*\\n(?P.*)\\n\\+(.*)\\n(?P.*)\\n", "read2": "(.*)\\n(?P.*)\\n(.*)\\n(.*)\\n", "read3": "(.*)\\n(?P.*)\\n(.*)\\n(.*)\\n", "read4": "(.*)\\n(?P.{8})(?P.{6})\\n(.*)\\n(.*)\\n" }bcbio-nextgen-1.2.9/tests/data/atac/000077500000000000000000000000001415626112400172345ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/data/atac/atac_1.fq000066400000000000000000013163601415626112400207260ustar00rootroot00000000000000@K00168:86:HFFF2BBXX:7:1101:1133:40280/1 CAGTAGGGCCAGGTGGGAGGGGCTTCTGGGTGACGTCATGTCAGGCAGGGT + AAF name, value, dbkey, species
value, dbkey, name, path
value, dbkey, name, path
value, dbkey, name, path
value, dbkey, name, path
value, dbkey, name, path
index, value, path
value, dbkey, name, path
value, dbkey, name, path
index, dbkey, value
dbkey, value
dbkey1, dbkey2, value
value, dbkey, name, path
value, dbkey, name, path
bcbio-nextgen-1.2.9/tests/data/automated/universe_wsgi.ini000077500000000000000000000004461415626112400237100ustar00rootroot00000000000000# Several scripts pull information from Galaxy's standard configuration # file. The post-processing scripts use the following variables. [app:main] enable_api = True library_import_dir = /source/galaxy/upload [galaxy_amqp] host = localhost port = 5672 userid = bionextgen password = tester bcbio-nextgen-1.2.9/tests/data/automated/variant_regions-bam.bed000077500000000000000000000002261415626112400247150ustar00rootroot00000000000000track name=target_region description="Target Regions" browser position chrM:100-1000 chrM 100 1000 name1 chrM 2000 5000 name2 chr22 14250 15500 name3 bcbio-nextgen-1.2.9/tests/data/automated/variant_regions-cancer.bed000077500000000000000000000001261415626112400254100ustar00rootroot00000000000000chr22 1 400 gene1 chr22 2000 12800 gene2 chr22 14000 20000 gene3 chrM 2000 4000 gene4 bcbio-nextgen-1.2.9/tests/data/automated/variant_regions-priority.bed000077500000000000000000000000351415626112400260350ustar00rootroot00000000000000# comment test chrM 100 5000 bcbio-nextgen-1.2.9/tests/data/automated/variant_regions-variantcall.bed000077500000000000000000000000371415626112400264560ustar00rootroot00000000000000chrM 100 5000 chr22 14250 15000bcbio-nextgen-1.2.9/tests/data/fusion/000077500000000000000000000000001415626112400176275ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/data/fusion/input/000077500000000000000000000000001415626112400207665ustar00rootroot00000000000000bcbio-nextgen-1.2.9/tests/data/fusion/input/1_1_Test1.trimmed.fq.gz000066400000000000000000056142141415626112400250520ustar00rootroot00000000000000,SXK8<_e08UٌڿuÏER~D&ge<uJ)K?SWMYv_.ϛ:veo};9rkq?ƱaG0zb|??x^?]]}gܼi4We;kdwK[\.4& xO˛F8ip_r.ӯ F]~>15NV+58i͙iDc;3˿c*;4/o]O y{ik#yHC?7D΋E̫}G+7"wvSF|6;"72 a~ϸc~t_?ɋ3J#ok*pKȿmۍr>YtWnFa>ޔN6s?|? EVʊ"3'wa9ӱiGO\ȢP2{ۮ k-&~p]G=|wO#ݚ 9EIBr~IrVe.:n.\-Fwy9^glQn>p]x^Ew;\vWpH)/qs,L:A X cQcޙ!3NEdTaz4JJ,)AgQ #BȻ3ߛ{gV:MBs,2wxˆϖm#y+Vy*V; x Nҋ,|pY+|z^ÓWfl?6Cq9W>(:};+ηk?R j0m&YǕt\6ߌSEqRQRphRSkA0fJS?=DaocH.x) YF$%,C`1"p/' FX.\D;$H.UI%2pL#hbΌ6]"K_ץ̹>8%=sCs6 824 QiISP b;gˊɜ;ߑr˚3`4`Ѳsz fô;N0v[rc{{uk(K.+;F>$6lf)■Rc;W*XsO~tR?钡5KFC*!e/_MEx.=ULwbL^nb;N2*bK^HzGtO;cW9l0m#SrB3\1%gzUMFYnqv ?47N`,P<74-N.*R$tuۋ{7' {njU+]kt/|v(yY3bs o/ۯ^%^CkrXahAP&TC_M۴ke͕+V߄HC9xA>Zj̙I]֎/HIYݒJ$ey*G7PYsݨSj mW9uy?;Z冀u'ip4g0Ao:KD*k00Z@]]_"Va5Wt褼fjAkVYM BǞ[f~$ 6AP,Lx $cSa}mzKD*)(k\ɦp,c jXlsR1JH֬؆^?}O0qdj: 5UK7{ؐZ=0|gPQl"70*>x#m vĉ rwڠDd2F/'P+} s c(Ȓw[P)^ hjPk>464r<}>T9K$-0sIRQJud5R"9(s8d-~|CE~[131Zٸ΃s"^e[i/SGKi  n]Nje[jeL1B-ZTV'+Cߦ&YUKbEAPC4F_ޝǀ/XTLNIuK]1-oo x=ɹkU{7\.JKcpӻ:ѻ }}ie"H6RD<.x|wn,щ,C8\⭬lGNd[F`y=Bg.!hHރzo-eN[N蛍Z|븍^/`Jǭ&7= b9'*XQ߹0~bu,' \n6k+x+>os$R"Nu/5$^B"9já]%g.;M1Guu!z~5/Q% 'e''!: 5f@/s0Bjځ>U͢eY))0'hP.SX(qUQ).!-_U\ 뜹z[tΔRW[zP|[K]aw *=iyŔr3mЧ%,CJL./; *VilZ|1Cߙ ]ԡ}dLyD@fH2ݜUzףcjT)k ==mYJA*><֣q6t׵^.#G^BTԽgB|i 괙K݉I(L7q8j_wQ\Sb8qy=ȹX{# %byɭ&zSE' ]6h?:=ų%Ճ0w&e׎%{9ʅ<&g !* i1Λ1x_P0.'wm7O_;qY xҒnA}çiPWǷQ@oAs]{} ׆Jm?/7R7kqBBPQ֩݅'wRb0 գ1}hFR??M%6|ըt}-u6 ]sah7r.s&02]o-N.qOS%ėWY*e`ϴeY^h2R˚`2A*?)H]mG: z Y05,U/VRI\VJ7E&nJNeo/sq8GjT2.')&5ZD˱J>.cU(pVkix.&T0-!?k؆˞o#롓oRdzw{.up'4\]dRȘY_p. )F>쾛b;:<ˋ9`vcƱ30jw͓-5<\!>e? 9dzds$pqta{).[}U6;S" ^~k,uI]i7]s3˹ryCuQћyX(4\ft2+uo'sѓcgHHDLLc'3X75Q(9^G̭ џg73,LM)z+a Ool[s46F,]pT`EƄ"8Ż9o7&4$OPpG"*38^[i",ir[YهTJ: HL%ڿ+2?h(E2U*ha62 tvpD߽5ˬD:A%d.U{ڰq:x1VxKo" r:; q]_ XyQ4$}{jaV$WXiGrST7J_ }{ȋ(,.nĴiQ4%W\@37NG^ڙ#uLBYQ ]5ۙḡ/W}0+ނhFhmvv~>z#Ȝk'8rZut4Fo ߹{:ۆW[SbƵ>4&.ӿgӲ0wBDFK{ECWHZ{HĘ*‡Tx3Xm8՝tr'FG]$vHz&Hi(i1\ht /qVE=T8;}| kCr\Uܕ >o}Y߿#Y⚌8 6?p>ZADܼ2ce#Yycy|˓Oz -Fa[-[) Av`CKJoT1"7Z/l pS/Mq$4殪ELsܟƤ# ~zn\OHK}z^C&j2Y^2tu<o4eqFѼܧALaEPMK%G4`/z43UpbT)ɤƼ4D[XVc },xGvSm`_7X;dͬa"$C%G#]vmm3YdIQG[ nAEYu$cB Yg$݈i\y+,+1]Ɖ)gL i1/r¤1Ǹ}W X*?z$?P?'5}dp)|a0Vf@e:_榉Or#Lt[d?"r|ϸ{xkN'K cqZC֘t]nUa(@]ӌ8Z26Gߙߵu emB\ 71ᶪ±5W6I5PKD}2Y=ۯ ҽPKKfѺ2G;D~;dv`:E |C*7AJmHt}}ȰLV 754[KfȐI]1J2O}@ښZghHړ2C=L-'L뱩ei=;E`Ja_;52pdBѭm8-*L?֤E=6]l}]`]EM d!% IiO !pY2GHIcg.WiOЪ|N*o/!6J{LON <~ti8,K'7]yp=b[\Ju A?49툘7@?c XQ{Z9>0,83CU^۲fMnxjMTh˱Cα ѴiS[܇ >8S;TJyezCFk2M8`GtooϝiZ'`k7ۓ6vlbu h"N74'er1i,bNFK4i4d:r\!4lpLCgcδ)Z:RÃk?y'S3; 4#e>H-~ f8!˒6SD6T˝TbWFNY kÚ=lJ\)eeZᏻ+y[}?H<=OsEL6ԭ\lr5|2'A_"aj;4y ]<E9TK5I=MX}–glsWZbW)BkxGqݮ++&DPWzO6OF^҃`2ryUu'˃: ǿ)=[D6Pѫ8H&X(K&o<3K@䮊$Sw !wP=$]݂%:[C ]v+6wϋ劣ofRZ|8BovM22\Pm>z,S2ːi dt-4Kp TXhaezW,?g*9$kA̠H/QE>D-ӓ?0y6]oMf@ sږ;I:!7΄'W㻏w7r`d YVdќp2v(@.Qo2O'AɌ {9w)B2~/U)#yЏޑ١\Dqf7~ LGʋ`}k&biUe./Ϡ˜369_c8Dt6}ޡxsbZ T$`yët0LO4 ȟ `++'rz'r$PІJ%Hmf0Q_QIxH{H1,-zp86zϋI;"z>ކ?վ=)ꉃ&ڨh=քLV)f2',Hp"^e ҉EډN0ώ/ 8ˠ@hTU/TK~}W/D;=D,L <i5vM<(!,˸ ݧ`&^J*h|Nrө(В6'p[%xTQO>@MG"$IXa {)5*N,J/ElUxIJ/KR_?\|:3Ä)ɼ]VmpJ?`}1DW.d!΋C)o-E!vY6̼^1.`-7}\ril>po|qoi@Sc{E%"PFMR9) OD WNWt LaU'SXٗy[i  nSݵv3ZzmC9G^C9GgM2_tW_'{QTa^BܥqxtP5]<ĈPAKt`%?ك/>`* LXh4O^(?%]/<5mӞ&;)\fyZUVMQe݆syJevjf?[Pw_ QŮ" \Vwi<+`1R~Y:O:hhވ>W6%\Yc9[,.pI=k(Na jE^a3߿ L?4r<l ֫t_aLr2M*B%BMݝ4By9\jhS-M)G̦Lz}& ٌA r4A5ÁW aR|ohiX`A[2܎ @Tv]uΫUguc֍䒕n˥QŴ}tr~ 6)el']+lkU$x3R=l}[Ƣ9Kx5ГG.Ͻ z{9f 5_’A/|0='Z9,%Pcpo-y} `}1?noUOGxd $/'a@F+z(ָ0ߺ7ԗ+8\@yȃ9037}zh-,iw|~LcOs!:瓍霼*&@kA/X|X'~ * ^#i%tR1^~BsV*bNjdsÌJ8q9>9xVshNiWrg\:5K wJ7}w'w-[z͹˧ě #}?Aw%7vmkӮ7,yi;`y^6yFɻrA, GaII";uV}SąeF'uk4ʖi_ Թ`(bM{4幀V%Qd┞,:+S"{|2S{g ׇ/ϰŎucB+0^a6a/,3L3 g@P!e_zIzU&9wKfX.T\:!Y~>mGCGCGGh*v9KGIq%sLa"}}h%7 }NhiahK]hcϳ4[/;? ap>vάyq4TQLbqƎYI3R#w?1VJckCh+܃ZRW4]^J'Sb"[uL!,2,}t3æm:QYӃZ)ynNUfhMQTePo>04-u 4BKo} S#h0|рQdIM1¹M182_JH/~y|:2T| VOY\zw|^Tj xH'濁F5\N:N*t$Qɂ0ji 5,M\2Ke.cH?Hfa$gۤǀ oΐe=/b >̨s̨B7+^_~0SMQ5K֊d(Ym%IкEuAwa? mf`9'b\Y"K|K5/r^ZR_9 Z<\T fKfP2ALi0+cZ&ȯ4K"l?jMe0e*`e01~@*T6V4GL12>bS8W?Ἴ pQe g`鋗&zS玕nr–]K"C)<2.'bĊ Ir_fE=z3 eH&%E]LL*Ɇ -iJ.G{ cqrۘy^.>$'v* SW47yo^_gfiUEtbmMSof!!3."X]U5;饞4QTLW7F9ULs;o lQE&$*y/2S7o)cy"#3`-Q^I$ZPW員GJ{_b~鈭]nS0Bev&c`+b+zsY=z.Ǐ'\EU_fZԔr}IQ1*q FL)Ept='FW fݬD{^Q f~`]C㏱k=Dz40RAt:Ck9^6+ѴY0*6{ݚQt㚎Ch;3%(z{aUdI gQpzp:nW<;fB9I*8y-mYo@7; EÞX#T X7u(pl4꧝8V*_o]ehmlUۤ`sU @u3֡).ǖ MDG^ڊk{ǰ *hZB85+QU! 䆝`"q:-.>ױ ,e]5f޾~T_;ɅZJ+CCf5߾hoLgca7py0PcN}g̠mNekTc2c2:Y$d.kq6TVOݹM̡ xȎ5Blvi+F9X]f1=`x =BncTˬeNq͉egG>rl`nX3Fܒ̩D3!\=A4%̲#ݑ[vF4!zG\EZ>A|"rPewOݱb9( gJ.\^n`%RL2}7u6?uHCͼ%1w9c< Xɹ- #9Qt'u6F2u/<ԺaǍrZNᵮyny;l["V m0+4sT[%Br@ˊPj >s z ͅ ;9EK:uz84qNy>ڻ q:1 hNZ 玧47 WRGLtl,˗d>~ԏ#(pͩAqq;hjs_ \}%W LG D`rw%UgB#l,^NGuXYtf烯O-)2Ӝܞ]4'"Lߟ{ۅYϽ !Gc^>ڝGxP08sܛnF§@@>#Г9I0lեMA]Zid#LtL3v^VfO֑_b\GO'<y`h@Ǽ&B;´ƄY9h^Az{ʠ>D4'sD$`z!Aa_yDcr'0XV`kiRgӏT۟Giލz: s[V&ʋ6]>I's2ugfgeK{HO4wXf'~yñ7#=3#3rhH?bN산Jp(#x?ա7ג~ qMg 9tTÎ*(-8a|)NѶuHY&Fg^IN.򞷄 ǘQ9!IMOPHCKZ5 ~S7})65t4*F3*3\+~Toiv_煐 FeToJ2lelK-34S HeDG[8vKxVp=<0:!*37e#mnԅAƻ鿮SO%ՠ8>SK{ քJGS{o#d*[ LFdS8f9^OE BJmI6@g#kP+/V=ڭj/wz'@7@_iyJ]TƗ4TГYϡ̖c8c̒r[ 阎]'ur3SY(ݍkxFNA~#G4Ks4"Vٌ@E>X)Vi9׸8zG,N)י&y,MQh 6Kl߻TNeIeһ.#KuK8zgf{D/S<1/<OQzYO7G=Yt:(I7 kQXRrWdbJN(*u0Z/S03/Mlݒa;=GwFN`%g{@^'Lae@*/q&%-Sy?1mO'( cd Z [iġ;Oyjn( %&h1lEЪ6#4)IsM|sUѰeyhؔxOX&ᔗw+5zЮ\V?9xQ*q6G;.7r*`ê}{Cj/k6^H+wP5Td*@#?@U+݈: bUmf>Uzl 93rj Xο);S(e#72#p2 ]1%s[,IQsUnȗ*s^ a^Voމ H*V֙LIO$C;K:SH}B|d]t2~~@a9=C%UѼՉqОoz>ސDă4V]#^IٚS7%%gZ橯YrK7ڎ¼]' 7d6yPǚ$9 bLǻԶK\\Gz'tÂk aS8,w줮a$aC5q!"_<L_7#Iv(S!Bu&\oVxkE87ҷJ4oaBϮû?[9J.,ok#$R_ GoO@]-&\R`?!jX7E2X&H_"i/5߻ߏ#czAߙ*vuƂMɻ\n7~ӸMK̖Dܿ@!-ʼ7r C-6R {WFUTLd0r䞮9[^3gɴ (;i}˹l̒ĹLlG|~Pjw$=s3cU> x/8Z1M0 /h-^r{mx&s7oMߥiѳxri v_ -/!rK Z>^$CuK&H_22Xrs&جaC?\6ksEm~#C!?ьU7$,n[c"8,/kW4Pw*~K+zU6yo147=ý+AM3aS&S!n5~k<7ԍ'Ptd7/ qAuBxHM鵰䌎ȕz33N4rN,kS=^Kꘌ9'Z^,Rc?MxңZ%LAʌS4;i|x"KXf.^B8<"(5 gfwqsi<J =k#vfI Ax6A~YP5z ys,c9!:xtD¾jIC,yb&TiR NO$/3(vA67oiXz؆_h̗--' RD Q'HSvH4&^Hq` ͛P3^bڇgaH><4*!8Prh+8oH+o|]ڴCqꊷF&@Jo W'IpjO}M ;QAY-~׳hLn P71Fd{֑/_M_"ϣuϣ>f>wH2bGI =g@w6:+qSB+*[,BfX #WZƝ*ECoZR&ӒYm#R,bB~DK<;e.IoZ*AUVnXK7͠$fBW-أ4<@:jϾlʌ[^`_sq, cwЫsb\w i4hQ|>OPK*i v_ gnUvpt32 m76n&sd5n1qd:>WЀ* '=ƿ46csI5n) oxE Q/ZOT4A/ˍDrtO4ﰫUEd^Of H)JW/jOb$楂bNNgE+ed*CLhƑg3{FbVϙ ,(Eh+zQO, Vj/)XsuHť)֌ `e Y0~K&*Zś(C5$?ЫCjus,+}nxfxe!bl&,e$EsV}xxMeeRz f\E9[BUq;AY~7q&D^:JO<58 \i=-ń{b.QE%qK|Ѽp2F=AI  ߊ2X>cݽoZTTJav'Lt HP%J%V8SOO K}a*p;]l\+Jkp TydeO xRf9\VO>n, LވCE7QM) Pޯw3Ek0EB̦X { @ftFLvS>y!&7AsN (+ebeӈZ{ŨQ54/"7̒Ffl-f#)|+M[O?7 v$9/c-K͆שưX6o&s{%Wߧ:}m&8E9JVIL(3;gmݖ3>AgFʧqWq`iPREiLVѨt{˹[ޘ&E!p["OJF0%C/\=;c3\ȥoT꧸hlb'咃RV8qs<Rκuy`O>%^XFwXfCϽɠ[RFQv;k2JҿO'#|v]K^nS,,@*Vd[U(ڐ7Q)_kk^ohpȮD$h{!:5֮RE~VgԿ,c63 LyDFb b拗y5Ew}¼qH nfAH߸M>vs"B͆VPMJC-TN4o,Q*ɣc8}(4F<̋$4J!ܪI;W+ V-^f-7od^וlֵ&u㑖lONOҚTPV9k~!U l-t4x̍)9G]2t==so;T׷x\9v ܳތ"S[f{?l0֋U\8hi]%%yg]yXj?О5 CU:9b#` ^ّ Q)0ֆ{{J͗f?9Pv.$kxϧ _Fcw'_N!A2 ϑتK @y3.!MhB%9ѝW'pֺf,w#f"fz4ɂ89û琯.Бwc/ϋa >Эt)%⑛_L)&|?eOXev+ [C>xϞmS"ϥ#tVg=d.jݩD[Ox{V)䃩a9aɋz.yWؾao#/P$^2s;BMTo:hyuC?;*ژ>45î7ۅvTʊw1dX]"2K!̈@8?kC. 4+MR>'Xo&[b^"d8~f^&ŒԬQ@#xթϜxGk@[qU̒k+A 8xYt@2a'R!C9'񬂒N}*l?cO^ܟav㤽?~e m(+3 ^! RNSK>;.=>R[ROUޤkUm^W;SF> ГBMz/o,Np[O)LOrH} _Rު(g$.T.)N!tcry{^YgW溟߸6]hHuI7]xh6 ::T?nlts6)LwbS8a,hkќÖ5ZOkO M\S"FEO%>PF zz^" ߿FmZO |(?^ACf]4+\Ҝع%Lx2nLvSEKQo2Œѵ!AIM);QG_eGP.Q"(h=g^?J;}] (zPxhl{W_J֛u:c}r0xȋ`Xn~ >M݊"'H/HPՅz2v/<0C÷!>GL?)x%t:́UG۪ |QM?GEΘ`Y=:9XIJuIE +SK;Ͻ2,/|X޹Т֣LJIE$2>cKorvmF7Iz:N2̒\}icezd}Ml,17)Ľ$U_8OK:kdI雍7p;2ZO@lYwӆ`?di8LM1B m&]4I?A<yC'o\S4`c"kؿo-TgcK :jEBqTZ&]^` Q-+MY]\Wh/ExX&>13#(r =ẕLԎrшmGxXf!Z= =q#}"ϊj7xgCJc%ֻɮDϸjFBw%GĽM9'/hOLXC=hz f^+&0D̻CTeGl'gD AhُqpI:ӎ*J]ƒ:yuIQ{LrW֋zwȠV EʶJrQONAH(~#9­t;ЧK&jLI*{ދM*#vߨI,l];j7yCx:oCV5yoX v~0@{yqK ƩO/_lB{:Ñ,- "8.kFY\z&þ {=z.)eإz3l"˰^&h[?&$x| A^M:2Tl>5k/Ia,NSVmʐD%b<'ǙRYRvi4V^UqG).1a8V% xm|h{p`j8N'vjY䕾x_ԵƠ' ˋ`dĪ\R+ [~dY4Ssօq?lJ:!m3nƥC);t5 %xEmUOa ~䇞0pbMhziE2͒g {j$aMaf\ Lg3BbúIjK 5[-=q:mqwԗƝk\,X]SVǧsg?6^24V?~" ʌ܉Y<gb:Qjnv wa(i t*~Zu|ug3Yfѷ֫ ڢCd:❨3n#b,fB'.WUQ),t.X&iEqmXu6›u1lZH#iA@ Wڧ)2'Cmf#sb | `fvwQelH*a]fࢗiWgEft;m"ѫxXCX=O4+EG#,5$z%;02A\9M ([ ̰LGUPVCOłhX_G ^yDԾuEAfYvֱ gadMLZ1MǏRF̰@)+R=d7%j6iEdidџ؈ >.QrQrXC`oh&j] h"Zbjy2DZ.2@ \ yX5i d2tSk1RHקE"4KkN#R=ܝyɪBۑ[c)]5=,K(3щzδKlKt&;cVes~z'4;N.2sPa^ 7`o'L.ుt]eEVN?J׽+QٰJ/8`(-7} 1dFhx -f66&O{ Hdp?ܞ. e lb~z5у[~W^AW{o%Pcf3k7+ՠۓ#TX{W<$2cN =+ɛD|&9et+R$6v.yȆnE5EN./ G/Gb8$)m;6g4$L!J.xQTv/u :CAoo~\>}$ y4C372dSRpO&`nGNhEb%~Xf.J|uG]mN,WHZl'b'Y6$6p3ೢ0HF]guCKb.2mPlL-3/"Y_*;cP?Khgb>Unn g #;ӈBNFkIպ}>\KEf%ެ-_}' ^`?+1k H RݒHɖ(XG:84O9@o涽\tTUWgz$hI?z*|TLY(?EX噕ӪB&U"چjsԏ zտǍy |(IСĻf#u`P߭WTȜvC&gۯk8zlz(]<_cϰu sz3IƍdFOQw4E}-RauVg~|DP~P5qF Aޒ^rz A2rd5O:6x&peFsVÝC`XU`×^~dG2MV)p6Cjy}3qx֧=*O[,/73Xa1S߼:gD|Xl2mIMQCb5=yBaaROj!b^~ | d̩Pӟ JpCqB2ק KL=pƟ) gy;VTʛ}EoG>yӇc2bW!/|T"U40,)QhcˇX`@ז L@E9yeҾgSp1݊٘}(OskKΦr܀>52mԆqP忮חLtD߮R*4ʧyQ&/J.OL[7hCm%ˬb7=VZ;}hWp}ļ aWgwxˀ}0K  DP8cpy2RpPaA\fC36ImRr2QA19flAuߧz<8P#h{Q'M%Fu&58`5/גډlwSP}ykY1ꜗyDj(6_!gP]|E&cn:sN.}* 03 =-鲌tסLK^rOdqQڡ7 K``'- zr\pły*H>yRM}%qĵO]x .ݠΖEGVD:4M$t/|Я?Q k h~:5wkiV獈C8ʯw20]Ag6lRT{ I$Y2p4.m:}+.!ق?n@۬e t$'TDvDrq"ڶAgXKfw% ?l#ԤDz`na׆egصX^P\htV/dJ10=`~S^Ԫ;>,KU02n2w'2s:)2M%`RM5fT݃+oM2⬞^*/5^쬒UZQ82~NO&X )-© y)vUbt W٭M_Ҍckb-ƭ8FhwzQgnWiw DEӚ77^\ g$[ҰRUꀨg:u7^|ךD?J}xedG(HZm%̯Uݺ/q?$XϋkMy#17}k9۝3#nTB:k˃8#o%vckd1?ڨ5o/itrBI=(ˤq@ U̝Kl6TEw.#axj\S5fq̢H =wQccحzfA9 >,xBVn卩&uڪhZl $ eE Er;kh>DH?zC@̚*͸\<%}p7`.F|2Mmv!Ed2;(aTC6?8SO}e~dB= e>Ґ%dF7o"ģG&ąOʊFJm|zyC} (~D;bPFX!Z>9!&D.T#ϙ3d MfkuoI%Qnh,JK/+C1|y٬ݠӬ^R|_[`1(+K2|<6H`?M`FTm:>fcjmfc)ObYҋ UY&Փ(Ţ(qQ czeR2T=8hZΰƌͷeDԫB1vD#x\n5[ Ch:nsԟ R@~<*#_?#ݝ%aYsJ`хJ#ᦺjCy26C0y׋Vꌵ1D M;n<4([Vm7"C}"srNVow!oO8}$7­<@M<~jTkۛMj"Sƀb%yE%Ej*2ya*o<6鰃!Oq {lUlL!^4Z\f@C=5srQJUvqer?eWAMң6dSǁ2%L,(A7JMmnj'(H9 \nbkr(7K\4ϣ[";++;69UoQO.j2I;EzXa [yR#SLڷg+;~:G3)sCH¦p5̃^tǟyH] $<I“}'=ըIaybQ9HIqk1yQӻ?L8IHFdϥI_^vx@;@Z5[P'0VUR8RS3aB/#;M8f}5]J43Uz<%N WYVߟ[6}9`-LhRm<+z0ZĎ冩\>5'pi!$D_`tx[~e6}w)Q`H_2$1xyNlOC')?CȊ5<]ME*"w5agCɘS;J:c˾ʹ_-u.'pD %,\"Z^=}2kOGz)d}V{Be+0im!O20YmՅʎ|ۂܓTE^zJ/zͽB7{PO)膿=ES{/$p_pm!s/-z4kt392{NЙ~dͦDIgҌZyl'73Y+rMj8F[:<18os]qA=!ܻٶAk.tV8I& :N^-?]Ѐ8v5=%*D cSr>X a׹L-6* R"q~bd~P0h}ĨfoHf5_GOjs7!V(A-hE ODVX`e^XZPkٰPuѨ=4_Cͧ<ȥ)4^F|v}W@5|Z@E/o DEV.nz lBL,\ulZ)yf Xf'[bỴkeea"튲lHz~ɝ4lryiz!2Tt=h 5OnD 3qq8 `ţ7s@)>Tk?eodtƶD* v;۸QVy~$o#[͆uL[M@&'}i01ţInC:$fc.<@-11I-M K/1cW+ פOy}sn9威#LPefM10(|ڌ0OFpCIBr*4+TK<4qBc=t#-Pˬr5I d9QWiM F}?Clt.t-C?;݈ itd."x2;,8y2v,{Xx%HQv?x. UV߮0ŷ{o]-]O81@+ƌXWNd܌>_mAKQpy!>t6Ѽj~TKz*bsVAk&xd}`h4[y(cwv3;@K\SЗ-= uen>Z eyTX)r P|OmeeiALsاYZ"}ҷ𹃝9dnAg^ϕk .UrXEF?-2J'yBL欂v.wE<,{8^&!v\8ʡIfIeM3? 7&D6:r^Y+ބ:29.2OF0zS d.MDŽ,5Ġ<psQyN}f$ד5ϽWuXO$:X f>|kX~\LJx.cY%UOj u}s\W%юMl?ZFؖg sL"s_ s4_~~GFJ._=藰*7 ٨;~_MncAUU5sP~8{Fلep+i6$&x"s[pkj3(a߶mM zwX =_E)=0;G2Ff/2&[qՋ}z\*Y42Jb3n ;KF8Xl;c I&Gvة_8"Z‰*BG"q.~#r~,dOf|g+̊qW'8I5Ӵ}hܓcn]pϑ0Wͯ(`)3ٸ3Fe<=w\;>]/'O$^^$$aֿļ՜5$^K7,~syųoyRROub%;˘jGb)A=Ȗh?ܖ`:fbr-@۪ ]&S{l3lpܛmj/K_kk5+hLQQl8r7v\: ҹX:s9L+%9BLl{\PPب|3 кLk)h|ά |-#!ӆ<j"(3מ cgjٟ '^P} AyykwU80:oP*]rdU/ 9=S'13beV+T8Eg;+)#Z+|Hb+NEޠ 2<q9J%}QXe(Xudm^sy,PY~2xARQa|A*XNMjM8!缢?JڑC>eX#T`gy2eϪx>eR@EGr cRhN%/0%i{BZ߼GЗZ?uI-d$"Sk]-4r\~crt䮯iY܊s#Zs{n nAiNg%csY3u(m{.I,SUyBY`bkL&\,rb ʠGf12z>"n6 jn©~koM2_l6"а̀ ʂd3L(lC.LfWLWw eu݌hќVm6StRTla L㓉@ToQU[hΚ9}p/W͋Wؒ=@huaߕɄ._%0fžEW'[BѼedEI.9C6Q Ǒ'p`%FxE~Pi֯TI&+~Vb[|ܣq@Uhv͗/6} F6\g_mK>Nh{̢ 3WI`lnpy@3oa`tIcdٶԷ?4F^I7j\ 5յ\p]݈>Ų[pc{N6)}j;|_ܴwkqLk$k޲?AT~fL}-fM;g@l^ˍ<kS$MGOb%nBTS٨8}ӎ2Mu2+xƓ#R~y5N 7k%6tbq8J۔V{>q^U(k/x&A!9J`7.b#^;W=iRN5El ܬz#(Z BnTM* C=;!ӕb2; [FvկKlTF)0Ǫ4kɮ!Is ^i'J^} j^g^y"{td֨ҺŇ=O`Vٙ[ubWzO΋Xi}ٽ"oݫ<3 {"~= v#Xg0o2<% J4\&#AߠTY(Uͦ'n6qm3{-JXi ، bIuwd}tR>*@Whβ*nLk|:HX{ƃnJbo@Op"a헶0WgyO6) m.eHZN\7W \rDeKMGa0/21CJI`*=5ӧ@Ao\zj6j?{_G!;*^Q){@ale +N&P)8C)f>T e YZ%TQV_qyIYwT'mnfE.uTrDؠ:Bo\K,0p8dX1R‚yefj?o\y?lg9O2-l#MdЍ:a?LI1H;W}ױ\W<菡4BYX"ǚ>~ؘFEH,HBRS+ˠS8?4k{X۴g43[<:y*oy-.ڧ+uljpC25ZCZOoH^ h46-?!Y!m GskP>}RV).H4O_3ǖHߘIY%`ip8eҗ2# L'm(VMpW$#'tTGe:Y"yi2H91ͲZ_dLAͪM*߬+B.%!Oq_.(|i:#R%AkRhE1gy"e7(d{]&֎.)LIwbHRtu˼}S IZx%>, pR|h$LqZ?ǜajxx&y9}\P?{a/H% +P %dfXdV;J6}Am(ݣoF1*>lpm"[\65!Gjmsgf Qe*Y>+{y>mҙ h2"f r!8[eab䎭y5c[EkM=nDc3 {fw.ս IO-&%!Ò@mjքcȈ3ڛ0VAв ͧ|2J׎%yՌx/ZJ0|)^utPoY~粏|<,R020;ߟ[6?vķ-:kE;䖕\wF%jfVmN k=Öjg>'Q}p^ *5eD, i:`CoPɭ}ZNzc2G4x%@<eD+t'w2KPUft2uD3/f9z3%ѼPbW55Vx^8w.YW3 N<\}t;ا?J죕IL3$wEK_uPP-쾋eLR)僔}qn<=эMw]MXR?j,#d?nz5MdH3im4LWAbbpʃ'^7W<{Cwu U+S"kSF!5gĹnB73:ABДŌIxy]ݼe3h ,r,G,qv<HqS sT$Ǣbu޿{qo9˩#'{bYK)Oa k e 9~OS65E ~O!LzSw=9B0]e}?w&o=fr(s@b6( FI}7hTmpɯ%Vb+[#S) д'ja4yqt́7cn% O<$0Ol[)fZcH獖T8*Kq`tjc?D2L&5jcsl>d0_gC0|*$6=)Ն, *&z­ d㴕Ёei{<.@y2[x&9X~꽼Gr¨:Eͺ[>/)&\g= _˗hූ?mb]p]="-?kDePVA6Uƭ44c9X0ؕX9aO6ʒU_#NIdꢑ_2S,NpZܪK( c% "c>viʉe9U! hfpn ݪ/𲠻]&O"TdiVEh*_0dvj${}3)G5{Y]*J4f QGzIUQ0ڑ!V([*h0/v36JuMF*Hu3Y;v"v ii V:ؤ݄6v7ֺF9_,pg,2o5AV06W<"EL`djW[0Ewz}:os|+YdEoN~-\L E*MUH֑qDX;&i5MGx(YҌ1} lvLB:nz0~ r܆ɺ' D9 w W_|3s[L#v>nTG>b`-[!~3e#Q5;M*cBHAkܖHiPV[-40`moM vu{=iaU`Wkh9>c|&[NzlEQ;|ScjO|ȌH$(Y>!{05ڙ>ܠ{oonNsgx)t!:$6ofg{vK,D?o ~LSnW<8@ws^~񮽿ܝ&n;6,;3.q'C;)|(~m0(gP6;a_:C?VQaC:/»aGդĎ;`[rz;L#H(|?2X?L,̈́Q|5[Y6y3e&F;NOәh3ࢥծii*=k+F. D#'(I )+Lh80 ȶKR8Ph֘3rO,{&r2Ǯх.%"ܛ8)\4q;$P^0駼g n~]Ne<ѻ+od/D .$cسYGWg%Ӂa'y!"߮0/v8L0ol"瓇S}}r3K-qV gffݫfs⑔o| ^X7ΣZ_ CW1y zwLyxI?<,GIhU6iRDj]MI _b6r!,2cR`oV K2vd\/{Ct~_2ȑ=oO&ĸI$]nXRpёJ\IF+X q+qG$Y0nX'w>SOQ|Kc|U{`NpCfs_wtU6-!p!» 47;_+ 8oBcٖ[9eT՜\8W4FN5DĞL.k5xϊ:a2^fv\!NJ-81Ug6 )wȤȓ4z_b OXf#1ˢX= u0ۏ~؄FZp574W AJJ"NngX7ay M>כ) y5na#K~`!PomFn^.Cd#-9vֹ^S~8r%I;$ vo;K_oΚK|7p2F ['shVG꧇F[ xք>k c˫O9lC'-L,]\^xg;AS͆=U阓fW∼ jf3ex%0C> Gyj죞%p􀛊Gy7D=rd@t(]o&xkQ#Y'DwkGjFqZ`;>ԣoy+:tT 5V97SSkMya H *lb܌pRr 8r#{(*ђ}AnT"}XkG#}̡$Wa}E9co0ș@s7ZF)ܡzx/{{xړ<%.= Ì'7cމ<5ӄі}=vcW._Paa H8fTMlBꟗZ+#{ш[}d;M!f_° cv/\q/W- hvY'ߋ[H&*,_ɛe4 1x)K B7nNDxTEVHs<#[9>Ɂ A0ia՞Wm*3/ճZevM;e䙟tK;K4Vvƅ˴IIa>"4^ur/َa_*2 $5=U_xHpZ#+if*"ĴSh 7&(q;~S ̷:+(9LYCdsʉ:Ϥ#c| v\Nۧ-4HWI%I9.l&zjҍ_jhdOV3L~׬."P받 '@f0p<xH^YΛY~-O'9FJ ڨů6s[bf&arځ7HcUyaz|υ}ν۲abqָ]C+n>E^?L\{{>7;bきKs}'J u&5jו o K|>?`NGk5bb EU eדah%}0Cߒ ozVi=[ׯkd?͛X*YCB zҚ2u86mԯAO*(fh2F!W䲹]B=> 1ի>:lXSqh6]Cy=W]V2|q"`zbrHs.7 ?;}0ӭ I|oj&-x?1FXxЍ.PK򞕻dt'Ilwa'KLقL  < dx|sd{[*"' e6%{-`1iveGdA[rبFF`ҼIf M磙Fd-wȧxϧ-,En0{&z$V}]yV4$c88 /؋†?Є@ᴍ'SQ?ot~K*xPlZ!]T.AQB.gf1t4}5[W4 ?,$CSPWm; LGN>iT10cdB8(~LᷮQk>.Vw,M۵Odc]g*MǞX:3bv7&[`O3(4Ŝ]g; SR E Sk` ~݅ql %9}"; ;X)zE .U|f%['>ف`ʏIjNoM^2Oy1<"7?uM$} 7ظF`Q?y㞩Qb;rDRQOdP E $U\TܜKA̴Hnֿν8kSG# k5SE>%%oe}̻A3 b:f%!rLC[Pu>F~[`IS=|0S=l?IM=Ղ]nB3F -u" ؙQR*x-v~Drv|Qaȷ Eks}2y.I[nӱSzTR>< +dvZ,BQ6oH2y$'ɳ^D4.O.hSΛFw;dQyr"4Q 7/ 1F- r sC'31"glL} 1}R9$nPaGL6^(U(^GC(|#4'\!iSwXf\r~,_hʾX? d;o3xPR̗N(({~U|E=2{p|_o^2oΉ汴k)'PA(^Hy郱~u7o.u}&Q^UmI!SF.PajqUCk3C'e1J͇3e,X釽(%_S7~H|jӮ!֍o_#1R>A$9H33CKO[&C z[=_-_YY; 6fzi5w%ۣD#d]2}}Xtש4hJXx%7THJ̪Y_wypj|͹񣷒-1/JCa~Ru<_@S4/G/Du=DS}g~-U UK?^Daa` fQQK^)\?H}ez=ܻH9 ')TxWw2Y-JKӹ2L|llm'<2Pn'FRra݅O=!tl%S}c9.,{u xdAtؤ,G]4h1A6m]պ} ;-}d5j(]DJf^b !#|u|Oof'Oͱq4/#wGnZoo*] C L6GoN PAt}|H6&{KlCq E#=5:؏g^9-}8-H L;v)8R|8MэompQ;7ȀULO`LѺF}8j|s%3׶`\x/j:FYsP9E@_" 7o%nK\6.V`ԒUm"W?(ɼq AtԄ/ dރn;Y@v~saS$TMg0)8Ȧ:felE>n]j*~7Å|Wx[nnpOuXJ-y+_C ce+Gх <*>Bx+V0 槱Md.eo'D:/'uhTǂ:ߚL?g=Òs}i| R`g)4ƴ̏ UdqV@*LǩG)MK(yyDA&ģ6x2!;-՟\2̍Hgu hb?7'3N'铕b W`VY+0O`ԐH!X&z(QMEwnk)(~ц |ј}C/qkhhʀa^.2M(TaVߐ7nX]m oJb $E*A*hUJ5ȉ Foli@^ׅTLjd`d'4'bgl7!?oBzƵM?C_~A4OkWW7r!U_l^^> _ٿҰRT(n-)xU>({Ө%SUY&IͩP%[VџJסvKN*Uo_~-V;zPݯ~l `dz _nq/ A/P>"!~M)K*" >\ Yz {2YtFK[@IјJ+i*s:L8nʝbBن^^y92X, ڇ4ڛ]71Z k5~Qc+Q"y}9L~ $FPjl[505hf0>Yd1Xy>c|y' $v w2bLPC3y,7Eg[cҔB+Ƕ(l&aB<([Y!!΄̦u>I~nmMQip4i{IrCht8kN^myuLo oBd6&io̇ Lmqf6z{ֲ4O/@heVUJV\& ~wGpAL+qn3i>tԋD^hnJ:1;~{D4Uk Բ9nddr\B=m}>᰿d%ul1YkY0I}h[I札枷)7h+ 鲭B>%FI֩e\|% 9i0hL0u)_zYuwSiȅ4?*䴕G"p♑9{{Xir>}=#2']@~rZfEJ9ik3CQok,[OZ_0?*yW(;|4AlK,%nŨ:e=(R&1őG2Ӹ=:Fx7B|nқdw+țw[抷*Ht!Q:RHq4*b'i64͈t#8Q}3x/wOQHFEyAɘ!o337Q$[һHrVsYA`%nތ}_# H*OG1<0Kbrgz 3#H*O yi\]).=T\"I%FgtSTsޒ I"˱`y/WZq UbWtL$1~R֨fhf1?ӹQPEi\>8^TM%O]yA0ȁKsli44Mt,*k\>Ť Jeˁ|{M;]yB0Fm唂o;?$w/9=;4 I)\/pz1%)6y-'n5EgQ !i^ ֕a2vFV BR$[{߼nNMR)|^n.~4)%}"\]unP6TG_bFGV @<`#'7S!u7 HL*5"^ZCқ~bzrQXOEL(fBy {e#=bL\]CFjqwq b϶>t7pKJһf̀v o(,v"H4vm\^8mpcwb0f9"k &@v +t‘!?>pM*-8HKcI^[m]&snސNWDȲ: e1l% )&lیnEO).h|gvKuUg.Ӹ<\ 3<d4)51=PjE2Aǁs#hDei69L_5FT3@0ؠY6Qa;o#٣6P9ۘvԉGost* gn0Ȉ^Z>6sr }P`]B-ouE~˻<]h\l }flGS*ݐ W]yNSjGaн!-$zgd;0.Ŏ3F]Q`PKѫϓbV}ȄJ -tZ^x甑aJ[dP{^&1 2dڱFOm]xZmb9^VfgWmrMHAuFi m{𽯞]wT.š;lpӡq۫zbإb +^8#luĬE3|qINIo7:f-RTˉCk-9 j7Iݬ)"ivw[[#XU[ydKP. ݏb\9NidnCB᜸9qLsbWe^E z`ےPʷ+:P.?+{gZ60I׌Fh;jia*+r3lNKwvm8_ ~l`TI麹pw Jϳz6֬ Fm\|fzX"kCgG|qwOV_VMN!主l`6mE<.-I|%' |Lk|ُ!8QHG=1"|ڝ4uB[##¶s΍ txCAĽb}\z{Yi~NS ZC\Y!9Qr'xNN6gaǀ_۳+'6)\Px]RlJqk./*k\0M'IP-Iz¡^wuU  8>!k~vδ_aHR=M U/%6sY- B3SmyNtTU_u½LX(^cxCL7;_hUpWG{]9hΆP?@'Rlnra5>9*>o̺2R7X6#q@ꪐ vW{c?wz%aΌ, ǃwB6F62e@K|qt=YOFiڝq_if2KhwāhG假ߍ6CbؔI:ܖ@&Bs[*oGl^Ƹ㐯NgBRXX}1J&Ovdļ\eF2b\xUU]tx}5ߖ;n3خ(7ҭ p/  [5ȿ֩AV;n0Ϲku;mrbqO.Jq'Y[`VB 8Ii$HyzExY+9>. ,㹡©FyM(u+(́ s贪w2S3''^ߍҨ}a/ }c\!["O7wY_Gh,OAߝ9 ?ϪZ\',%7&,4z" BZ:cYqQx@hڧn6Q2jǫ|.-% -jywj>>ỴRNwrW=Yյ3l] HznzfpKo] ܻfR_|ZObGihjNԴDwKvϚ+Yc^uȹdMO2,tV_/Y'ăi08hƈzs1HYNL;WEZc\m-ek;ǔwjTBfwQ빊/1ц?kD&>A/' ##^YӂrZQ֗_yf= bKÔuR?X2ևa#oeѪ0 A5F(0mˢ҇iqt:jxm$RAę6S91hmU@JX(w_ GzpXOȋH7{Sc=ǻx$|=C]>>+P\"OuKRޟ!wz,=\VL:M0)X,ú,p>AKߡu.[̨&Ojr0?x"WyV-͉ UxX٘B #q*K\"Cz͹f`3AcDzoշnkIaZPwȵL}blm30 ʵbrq)N%W 78 e~w>c `FF|XlfM~*[bh>g&AKGakl[1o%^8dTbmj|'M}s yh/Mi,2OQQ-Az>NSČOgGu;UF̉BY NǪE|NۖUZ+9?i_Mj|T6$*?Σ2 -%&]# @#gGL}vTOh.Eo z9t"QɼFU˚ES$phzzkcvT?N^*Ys 9Ʉ hžP2LS>dETiYG`-He.#\iFa"zHE[Tn%d3$&CLSWs|m0)x1G(5eWRLFf2[39'Mb}8Cm4gt4l5Qi $RԢ$2@ky<3S,:'yOwBY4gԘU#byV-ү/'dձs<|[zвc/=R=E"#vXL.S?: lB^>]q*V7~^gi,ݸ#њ̻ܰޘ~+1w>n~ɑ՟9"ߣ2:rtnP(nWB9ScP@d$!ooķdo Ս[LA [y*vg%42I\a\ZCH?ј<|*'kˋ`v̔ӆNLzC2)#6CkUlo`c*HYnF !*quM_.g6Q,h8'tf>& 3ܬޡ N-$Fi:4oY.Ybyh7<4NF̪5B&G?/P9 szHVv!>]m՚)$d O!_ח`ʛg!wh2JY[Ԙ%@ Ts Ҙ45m]W{x4(G>̴וڠfZSP ,ZgQy9 ˢwKɂB]YOkGa!,LδyD)|k}7˨)Lф"e1` t8j^T"?g+d&(~*Ͽ0s^f봢i57g鶪> rGי;W9Zx{MnZy+CB'\ѝ^8/B7^E0jXuC!-{L|{|zr%}4d?3D_QzdU}*BIThZDH6JVɉ7? ag5IYqjH <^U}IHC{u#_sjCn{yL;^:1g/~_RQM~H'g9JԵӾh423u}mHM/za+&}$›!EjIrY72=I#ĨZL"gǜ*yF/Q-4Iʛ&w,ˊ>C˜\|;3ƕT?os 曀t±"^0)FUliwyinqA"Yeo:?1B\wW]Ȉbg^)XBwӿFU - dMeQ~LudJ5M~vi#'Q:5#Ks-wUW( gEy]I|q/` 4-o/sduOm0 AF >%B f]15˜IB,/1 5ֺ H[12㾋^#v4c s!O˒[qnfUwfu\b~ܢP 7Q2"1|T1[{&@QO'Ɉ{Ґf/M>-Nz~[ Gw,?fA?q#h/_ # /1^^[w̥Q\øg^Mh0{_/ԅ&*-vV"mBIL$?T?wݘI<>&5&b^2m:,Q+a T h,dkg/-M:r|cLJ,or 39{6>frchIC N 6lچ1 cəta{k8"9tޛx(:gsn(I͝}A&M ri}0S{f&3a)az)6y pO͋+yS,QmQN%6clAƹL}<UwnKK&#C cWq2W5Dz%}b!]8`Vd[T|ƨMQ:mKy~y8pBy]4fȸH2btQX X,FX&lh-zc P?+5ZRHe Vlܑ a?[z! rXqm =]šMђxz|N>]FZ9l!nA-4ڇի< ym3M9K'pDzF׾ߤ^Bijj@.45ջ|ֳz}ǵz@sh˽ueٱt\eVG,$]܄qa8 ?k}2Ŧ<2OEbNfɯ%[ pԱH}G mXu&l#ۺ0(:!pn l+/÷lqbZg<0̮L ],[e&|) cwzqmƷcNVUfHq}@(\ QxoSz[&츃~N1uϘ !/-~ Kp65pes1d"B툂<v:in^J0'(~ RuZ$A RkJs+\`w<ΌiʍS]AS[NX줱mkuDUL264X3#"a=&уq7s*u5BA!G3^Lv$K3Ŭ+i5cPT >m!YS+,Lz!vaCQ`cĆ&絟ޘ'R@|i{`f8 !Df\<̲Eu2Iu26?؂-<@d ]Y^R\2j؅MΑJD qcaZ;yl}Ke3d~qABƌ{7zޮ޻O !Lğe3NL;ȃ[vVtS1;\(b~Mjy/i;tRdw)d'Й~5t۲ b.׾UQM btoD|1"*6F n2,=%r_TO %HGI:;2+"do(X E~z.~T~{Y_zpq>{]^B[^'p:_x/tѴ jų溇B}or7t i?"/Qɴ0zv6^pBp>\~Zs+±J+"㑳s+89:3KF;!H?FB.i~n!ms/xDR+[8As>VEtbt‹'I,<2<)YwIxb^^*9%#PfSM@ RøM6ۖUo`zGg!cdMѪi&6^g˒6qvx}W|K.R1iāCi"bkj٬I{6&1py8"(j -BˏFU>ӏV{z}%N̰8d[dh=u~bsOW&"}%FqfϘh,/>p,䓫ImP$N A8AfJaex&H T"wS<>Kp7fӋ*dGߢ{IM<͌кup#ڣɺ 1jyx@cޢMPL`O9eiQpwY]ίdO/tǚG OQ{V%S) dM*MR:0/ Uśkmh:!q08^srŶ'/dlv2ܖ`Y(I@ooQŢf@;/@k'f^}$wKϖ %I-MXuX'\|!95?RH¬&oWФC-TynZ-sH4IiFD:H&zp9J lS4S E)SrҰUCEtSd8'em fB*~TqxwL&C\cZ5`GlQg֗`iLhEi\[H)c,-U8L:Rlq.kK zˊMӀHCA$Z ւ;0x ^o¹0MWd/f L8*BVm FJρİ~K^OqF F-AXNa"1F#âJ24{`+O̻?Hb|Ҹpz:Fe1U;6uxMat4ZI#{ 6UVeU`-gk# zqE%}QvZ֐9ǯ*1Ik(j&4[f U"d1!_tSRw ENAkׯѠ7|iziۄ2+I-=X`v+ojKS,J1J@ŢSgdmz{udi~eO& m;.h T&s ?IQW5&VedXSH?a:.ԥ-MH ΠA=4!LX?9EŐZugvgW8b8C܎9Q0JQbB1hlUqU G(ft6K+Bxхk(>*LPIK͡,Ns-PP-p= nsI*sIEoLo~~B/U@Y(TؗKkYLmh۲u%ٱ8:aa6nin VU3yF$ߏHh3!b*x'.a%MibHf'CVMr(/m$G Q ¦vB|u1 6c xwG{TvmqXdT˖V^(9Ͽ 4E_)RGiUIp2${%O:2 P_:O4u4/PzmSVMSyУpשҌ˘R]΅F`6nws5Ocmr>$|I1¡'N-C%ԝ^B|+p)ÆKE| X4⑛?/X!Ep̀g-1He[w@9T Yix6epslh d[ Wqnɛ=BqLSO.? ۭE=s*#WGJVInTf܀ /&;ɀ:j*\K1$_ɨwUi#@;T S!]VZ($+wT*aPoó7NTOףWd.?6k=%, 5wQ^A0DX4ɣ'[/ A\&D1ny$+7Fb|o9 UâHݘ)H@"2FSkM[0LSB Iµ1.,TVБpt ku,aX8Yv*C|pkO@k ns#r 9*C78^Ea[Dž$7־;WG,~kTm{\Ŕ&L1{aPG8NVrK&zl:hvQo1 Q:[t/ClWv"x qҬw\i@ChATI-|X4(/ɢߚ,xd1^@)yߥu]}XQ/ȧF{.+*^(]ܤɣ;l B(SwV;+J.ͣ C'xox(li&)"V٫8ёq[F[$o ktx\@mHimFd“mJ?`g XeǰEpvadҭw|ޱ(qd;!&!Q1_)i#83#ֱbͷ|:k_(O!Y)9S<%revBȆʟ0o9E7y mh].׸`ʻܦ5̞(*_ ^ %|L1ul`KbB^ٔ^ct+ ZKykeI|?Ujӷ2]V`b)BC78/F:UyK6=C_ y5Ԝ<`ANњA!WH)1lfJD:F,vj4+_a#SȺs+^ UF04FhNMRe+'n^`>I^U'5 _? ʢsFrq23M5cTXݏ 翐|sE#׍M({f [}E#sγQaoqTo+]e*uWH*f31͟|($Qv<7Teg@zm7n7E5Q@_w3GotWq 3m`z&ZvƢM)DzSjXvs@6M Vg(2~DI.AnQr?nF 4k4Ǥlv4Regb8e0t؉$  cŋ#Y%%37Yd}W k>سBbɺRG+7j8ErdP cj,AH ݁mÖm'V/Ką&6׵LpLɠ2MK`7ҷ)|#27ܲVA cG=i4*qڰ/LCVʯS~JAv&- ל),÷p3}^\u%THJ1}̘o7nDfs4yZXg;FF>_rM~XX~@|ʜōv\~o:e"Ƴm>:Dľ<|K8|p&غI~i.\6|'"HƁ~p#v(:jd()l;)ES7&>lq6B?t@|YMJǩvH其py-̹ =¼)65;p!^يuiX2,Os W TU欶+(DbL>dDdeQj] _ P-R$[ˌ7m3t56ZCIHv>h(<ICŵ| iG>D%q.:ZvC9J]G.s2\`,R]TiGPPQLL#TQ ^9=%O!hv#NN\0:) %d`E0D&砐*,TX0V'XYN{I9fX)oKaYVڰ8, kJ^O~ey.MdZ.=O䷙}#1[;|zз^'7:MjםGÂ97QtH|:||,4/s 6ZFrd7Ц/d-Ϳ@˻"[ jÿ`hDIr=\ ]t|A1U*9l鴭"(eC<_oe:1U~]xYO05%}yOqe=h-ݛK8e ( 0` [ ,VD3S) duLkG&4FQSthIRbٲ%^8t.'ZZqrR'kRjP]?p×?|3/UWlFV5oh˥uSj4s=eT,T6KT/ F%&9/2́uZb #[ : ԖT ɖlf2\}SDacFeƿ1˖l6 ٞkMyD6d(EVyR.n^h,yIִscԺؽ|Gg]VU8,!6awO4pVҼ6,ÿfqŰe>hQY` ն(XPqyN)٘OȈL 7KaՂ\\g1\m ;)k/YL3׬qz.BCfq= Tu|+D_P;rh}%Zg&x+]mm[=h=X_ࣿ76LbئP%H&M&Q,\H#<Ƣ?=_ $a^pv|Fǣ(+JZD}- dCa|wS=?tA>OĐ+| Zs0Pe"[h()\:ISUo6Tƕ)=J%?tI mT+ ) iP%8CՍ#Ki ĢɌx/ ۙP@teɞ՛kbnJ>aU?又CljR.zCeХ%0<ăRJ.a3e*zY} 3DIblO/u6CCSE*,>j0ZN8h9;2. Vf D7|x+sH'i> Ax_ LP zl8gD//;4Eqv0H\?nHe"/qH]|oY&OkrMTۗ ޸XŰ(3r xvlŒd)KI8 z>KYaqi:MS.O9O<)!R֘TLІ7eHQ\1\Vn>S-EEv? :&¯{gdo*Q^vvO$P*|͝j 0,%2+5}WpΉv@iX[ ;Ubd +{rBkqY zRseD4Isi:\yM‘-TϮ5oa(&ݰW,,*IUs,KmWm;[c|ҸNWGS{t0)}/ԫU*Z%g8{=ݗ4Ta{ݒA~7~Ep"qMC[ptbё r]b@Gn4Xݻ>NTR%0i[4bZ7lgޗ)Kl†Z!} <"ˀՕcMH#[E7ڒۤȾ)zpZccXvߐne,KR"d2I@K^HEg"7Ouƕ@xVaЯ3GDcp7]dacn[.X"hG{0$cP:4[ hmcrֱMU珠lTFO8J" i&D8 JST:TвV\8e , 2,C8qVpZYA` d ;Ŗ,<63M2G+'&,ƞO.V}Bh2 }pׁ /-PvӖ~^ˋ뺒_b&,ET;:<%+8/ej_)y]o\eFGM?`%<kb6Ő>U$*ht)_թx;a8|&A,#A2EW"n#gyj~[`U9ݒ3h\$@#rtG7N T2ٱkr܍JÞe=SrY׭;1-%voE"w^Adaœ]d߀[&N8Cm,P#nIV &Nj.+QҥQ~OtJF&$8ÔEd2Ca*Ln{<^>XU/M~}*Nw# c&[pޗy$tik$d tS'Z5,Y'g_KI1c>{@VWF4d1Mwѕ(-jkJSӘBR35w!4P|<(ySI7 :dV8IO7 ,pyN O`kɫmsc[/ra'hĝg:q-:4=L3|G!sـHS|I3LEb`_vHapjRn5W=A;Zl|]_~sͶS pΚaզjs,>&ڄ̤2_Pg, 9wdm`>_82q )n< /~S6*-S )wu>" s%" r ţ8yXSZ;D0刾fv5E U9(%;59 ;g!۵]m(mjGNvyu/c%iS˗A&CԏUU54>e ѫvu?nRÞ|54Z\yX%Fo#ej3y%1.EtNJ*.qބ2idd=} ݩ_?i۹ K+̌ސŒTQzyOM+% B&[i3k͙LHL=:ܲIbE @v0.-{<NjTAYsL$x(E_޼psp2AC\ c5˼ lhXrUqCzŽm2P2#8`w!HMֵO8u' \)@p1/c3obc JdI}mb"ByD妐F@؂%u2a=k H3y_c`Cċ}?*?OmviHzL͍ h~Q`E҃ lɣ]}Uƪ1Vƹ^YC hk$e`"\n'a&̃dN9Ʃ H1owj·/jXyQۅbl[ϠuX,b K]FL 8dW9 %*(_,I(> a_-c۲-dd.=r (иX Ī\4Zq>:vx*S_>BnXOd7gM.ciq4C=9(]7r zˠf,&gu|m<푐TWIȇ$ 9@9(؟G]A;,ᠰ{H g e>.-Hx_#1=d՞?QdKpZFTղBax1zT4I|15a_X8%5ʏ.ygYG_:y-Ikj auH6hUvh_i2鞭σLkX:k; [%엍Kۆ辉=:/1x]2 ÿNze^JV ggfNL4@}j,zhŵ|ʀCė٩\2(B{]9Бs V@e @Rk ;EDՎj a^vՕc ք]T#6=̻ gty܄uUЖI2"m:=ol)85;BObH dedMLC5a~WMSlZz;~3y ow&Jc0'XƠRU;l&jU/q&5 ,ŭ~;xC3m-{ot].uIu>2a㷰}0 eS ooK/OdDogVxxmRzHA@l4+w(Ḟy$+?J?ߢ΅E,2@XQȧȤ ]n$WTf2DAԣm$[kHwnB5򘑼e@dƌHK*BM[2Ϸȃ'Rٔ|s?,-Alc6ʇ}飨]ϻ=i];!?t߲CAY^L>WTw(bv)LԡCh 'ym}%/J'گK SdaRwc3{E#w=I4*̝zKhi۔TMyܫWDD# q 0zYDB ɬx QkJ3-{/ҢUlu8Cj/xtaUn(oUuB}. l6] VɉVrik@*ceK0WQxKh-gZU ʧ DLbs,L#wU䛲}[qyg=[لL}FH%꘱h̘pcz`pVA<kإfHmE̳IQZ V,OnYsb3l!㪞Koso\jѠ;K7T2jBAL:8={PlRItJYZi͢稛?:v4B9GNZ,}B 2%rU)ٞZ}W]n&MS-<ͅt>EI1j]!lwR҈5-(OyWnI;jA8cy,oȰ7R={PB%2E y?ª\kV?nG?XR'd\ P<Ȣ U.쉂=^h Nj32aDe^qYZz)Nc6ą-*zYy}q0I#A 9v@[q 94:Y?*Pˢ3m[o5MZ,@}U/ e7ڶnԵ J'iۤ/ک'âfj9ZL~ HAWXJ.%HPȱrs֣Δ73%H7DmAKa;Q Љ~)ڳc=b]Gx8w3z~气$]AsI"#eykd &KT{Qq^Pkَh*PGEYW;ĎaSjCca? ik Nڍ:P/Bt$臁(X!<D_{rxŠQ|GE'pMKut$=V Bԑ2x9&"詍4v1hRbZوt`a2%NI B<N9+i lD~7O6}SK塰9ǚKgpZGmEstvUjY 7,Hq4ҦAu5FJ4$5)Pm^|:D6!ϥǭ~ɧI%(Mʠ pM7\6穴7(ydKBG-͢U|RUB@qҎŲ\>NHʀ׈ۄo,4nD mXDVk Ht{c*>sd9VS`Bbݺ61GG1,r~벙#y~6r ٫4̬J Pٵ%ڲ'8T)I Gg.G%f#;0}xhPuh=+Z<ʊhWaF-Qa}aޕs'ER2`7 (:q+ T؞Lh4X5$kE uhNN]՘ܬQΊds0Q._W`Ugt{X c-єd6Mуj7sl_閵1Ojik[,T4ao\d]nXO9<;8ꄵ#jء#*Wh\}׸9χ>Q{ȥV9.UP|pGsQid(U@+,cve"A>ql.Ox|ZP Ђa:' s=4'R2]T@Z<N_Rk'=_d?IQ$k#)YzT% /璈}QGK9сtJwثN'a m̸H:l%H& ؈'TMEj%ܼ%Fl1e`F,=`F(F:M6j3B_6e8M3uɝp[@ӰaV`sF0:; Sm0X5~A-#֗h('v26FhcDsV}`q3E'i2_0YD B!8QnNBI\"GҘ\6,Ii&:}{H-y΍[ ^8TT|-CtxC/a$kK1]/uИ('^$@% MÚW(yrĉ'|'%jvWpBf#[d(ƾHTg8w('hv0Bv4xFHLe1=~84% w0O/ߨ^ЉQ)'p?˯Lw»fCv]0Ciy{wg &U h< ٫fELQto0)txAd4¶Gc8JFzP;,(!$H؇Ei.sLށj62'ڳ"@v3}.j$u%c^w@j^7NLAds ny5(.y0'Yi=Ѯ>/ \GL)9KQuցn+ۆn8ݖwl~ ~QzH=+k?U|Ǽ{ /pOl&0#Cp v]9?28TX/A/Z5StjZ()Iiqhh~L5pְO Xt5]:>a 4OɎAOm+i>m )˄C4mcȏ[Z+z+=4Z}<.~ ڈr'1'c bWs"&ubf|d)gb6zm[U&G sIiYb3C?8legp,Cw%]PՋ>Om}8Db!H#i/cM³JGOޱHjw.G}ByGU I~r0Ac,Zg7='UD;ߡ#a,<84eswssYT)U|g֋3Լ8/*y4ͷ Y ._$Pl=ʛmѭ ĵg{i+Dnߜ '^fޑHyʩ& uMzMaOeh0Vר\*ۢB)zF)R%K$nr[\gv;(%`*G]0qX^y3cjl5<"[LdTTW.K) ѩ$f"x[X6Cb#+?)1ZK|zH/׀3WGPDA ǧ,k oMu7u~I6<2{U=,^ Ycǎ>M߸b'{\/.y ,ɿt&j.XQA긙QtWbqpRKyG8`vaB~HsJ"HKWg$ETgH 7/U :N̙D LB5)O0<TKxN9\(9M=՗;1iȢ * Mt*@6y&.Gt0Uв'OmDY})"z'StB&놎NruNՎ#/E=1g,I[m9NQWWɸEU}\;TW CyKexN}Q;wu@$zGM`uǰa;e4+a富+Og2qZ+A =XcAtMTtG|OXâ`gsυYvkP|=p+ޚ)%t& }6>7A(']'ġMcGw"F;,ȹ\ZrnّŴ@B#2|E/٦ϵiQU8@Y :k9QO99OYXAkIow]7Pdw#::"9yr˫ G& 2XR$!Iq} Mtml`@2IʒP OVARNwlZ@It'mlRҐ΢՘W7[)pIFCꢶ'Jx̱%}[~ʘd4<**jڂrn)OR7 maQc/B2k=nkWkۆƢ^<3Wމ·\`4>mψmQB7EV uQ\7TIy$\ ۔|hZf}`]ZnoUYjNf阉~Zô,)4gaӺp㣟 juv ˆ|2aO];o(H0kpkz,*,6,Q/R 5-l;RE6窵y!_/(xC27d8.UqsVNbQMq^fKNˈ"]F&pJtd @ s9A/aUѾy-nBۊ|#%bMn_ d1r{8I4nш׾G.mE2z6 ;J1̛" λțgPR8]SU}Ek-5;깇`.]H&2ùB=Ac|obWtY8\Z]\ gY<~QMnC"3~C^Y7vG#$K(Jv:ň;tt$8߁3>캚]h328rrm ' u+"#-^zk`) ͝/Iȅ'& ?R C\VnBmI6 &5= l jOp6sOd:pe9"ڮ_(weλݶL3~.@vǧpm Sq_Gu-/yk ޽FȽi4r%W7 BL|vl` gKGM3_EO򽖲9%7+&GPJh #|}Vi=Vg=g%t.C%KzTmd*bi^؋NZ7.TKQq Ws1Rrʦddm2$+]+&`@yd#s ;%‘&lXss7yN iy/1]%a9/#fʣg{[쾰XlҐ,3g݅APf_lh%l}"K-<Du-oHͯQᅔoELiQ[Jnʾ~SB4I|WNN7lזfr59CKxx/8As;((abʇU+1˕&TƺD,61K򳆶BsI?VI8l0gha\˜|ŋ^)o(aKvI20Oi9-\+ENyW3l{ԦT# FSyj}yrCNhˬ/jX;lV`QON3Y0Gg=1,xMy5[$i٩eBv$~Mxj#?zr:4͘LBgEF0ʺ Rچj:~Wd7P{" aUPgDz|Pf zfp0/O[l_$7jY$X.09}*$ِ= zy1;c4`"jg5PUKN =w (FbXg|p 2  h{Y,ꁬcX:Z,0Q'KXyjk|ٝD.`2T["q-/$;{(̡ Y5f|B}ԘQrz^BW/]ʢ\ ãSrOmb60tߍ!S "J5_hؐ[b}>U&e%A 4n&YR%ڬ|s}uk.]52-xμɒwAĸ_-Om_,Z's,/DySQ07C!򭃁q/I(4_ _\pcQqMiR[sHyf V O%E\1W45WBن} oN ,N~r>oKu2K^){c N؝$LCRyjȸBY8I$D) )i 9i*+Y]P`8SϣWLSӽ2|.C(ɑ\/)V{q wBٶm}]<."?D ,s|$ 6s* l3)myb;XxPqDVQ5i1_F,K/H}!wH>M7?MO&7@) )`Ym7d?L2+ ӣRjK*A:ȾPd=Wȭi U.cd[VDƭ9GtV.37eV?M7I|ΪeChSγeI4:O>Ќe&*dIz?+3?#K9^'K!rK&A컟son"*cE2`M";-4LW,f9%w[72BczN/Hz~.C)k>V#DD~c#&@i^$ΉIn. {_ l|t9<؁)J'\A^EdLBAIaOT&yB4u&EZs4M9d5"fWJViBFl7^GɊkt"@;_d@]f/g qrrڌc de$tP[l CiAE_hZ*#c[,YH_ATY \e;߹31!ٴOËo<`,5e0:36ʟ)U?xٹ#ة(rFEyqm ,:u ӌ }ОSoAHso,jFN[od5ZkIIZmM]Hשdk7 0#@6J/;K /VI45rN̥EY_c\@`0mi7Tr6y#uަݦd'mÙK.3M+QBAK 9 d@N,#L{` e4"r |y\ Pzm+&(7"rz .93 $LX!v:"ڔ -[%nD7_xw8)86RZxlFնL3^تocAK.9kM]}'kNO> }D:y74UYKvp;|\M7eo;#W 3Inz5O4m]`=5Nl_9n^; roTP){ ֤'_/=t6ތ})@Ռ!ٓNo8Cqt>H;ڤqU(ȬbhImco< 2Ma~52 ~8^/[)5C2%%T1q7o 犓vi: j#'4 8}ϲ\}͝,o)LL?U{!$mdw_GW!*0Cs.Vi8uS\,[`(<3Wp!e'sL#f!sHDN6M.6 .`Ue4z- Eo6v,CWcՌlY#:봑&KL]ŌdSa NvPp+TF6ZM3":*vWM<^J4( bF(&S,E@U&ݾ}.j6>[2Y58!h(_, ' "“%tz =x~#EX#/R/tMxn04`-KD/C6G@gO"=ςq7BJIt^HMKnSmW08'joqN\RBIM#;rQP }}'(>a>:=^+8MH2#_\PLO7l9&[6XA8a̗F_Hxr[D$F arY lsԏ!Kg'ڰX1k| cܤYVh,c%'dezF!h!w:ݪ QTә{U+*LHLW+,<|jY.+fk&ΈkN-F zTRy._aOY9՗cG⮐s3WRp$P[yjEOV1 esD^`=O] C Tv]vbJM7{-jhaW ?to%<%ZmV7kIJW=Bd-.s 96ˢpF7yӷncZ}iZh 2xNVWl횕bKȩv#e$0H 8 8 ynw6+Ӡ8I{"UI .u\T`9$iaF9z!ZBmfTyVo_I8c4{q Ul &߱v1@$PZl_$XV8E;&4`<Z/e0A)I0f)Τ5>@1[f܀6me6)?>yْfsO9KRzMܱ=K!EѮIEq KĄ~Ms|,7gM"+y0o˹O({_ZӰ8(OEzȶd4](`>hf~r?-su#y/,@\0Xka:y -Au;G^Czr>ߥ"\O_6Nvu~7HRmY7W#\ p*Tz*$@@po )S.N8ԁm}T3ųT/77,@D$[r]5998@T~?,fvE^<](7%DR,qyU ;r/K&ϘhdUܲ/KVJZ6 pgq:,l] 䲓}!L-M2J~aQ>* HEeš%"lI_O7i?7"wwhI phZxB_(9QV)sf/U/կVOYKh0Zx]H1y )zK0'@lѓ=C Ǿ >y ʺʒuGvDS 觿57 |dćJN-[셞b}mj 8Թi@ѥ rdIZVEA77q (gIzB" %Dz]C`:HktG`&59]J/z*8ةL)^̰SABIXuؕx_UD6l.; 19敆 ec)- TR-hi@6 &UkqtϥΟǙ͢N\?(ㄈnE^2GCi.rgu!a3y<,2tA% ')6p`x$1su&q(L _D_ɒAyXMгpvIIi I\ݪx,9¶[Z$wBShp[PBSx#uh%FG!Ġ N*t<#T'A䝓SNbPRk~LZ 5*S#"4VмҪ<:GHUy- դ`$b[g1Ie_z2jQn=Fe2:nDx ZZHj kDhyhS4_u: CC?te{,7hs,[vl($chE"F.'PX?rIojؠ_H*:W RuD/Y9HxɌ 8NkS`r0\b'[;l2UMYÿlʚ 5;B01g)2"Oј{UR!v Uk°_|vjYhcϝ6SWZj meJz1y(UuPtc3a ҰSiBho[w"9 :MN&2yggX?pÒ%|\CF\] Ӌ[tRŖIQ C.ul-_'/T6bB6$\Nu} {Cn}fSN x'T=Q[&QEKͥx[lr#G޺1X[7}-7/ހ66 s9(zΛa\vDo+gYC<ٍ)*Cj%[1Պxj.ږh[Rۺ*_?P68va9@0ռ\>ht̻;p^f]D;,:.!aC 4HC7&8 ^`n-Ѽ$5Ŗ 4\?#0C$Es3aB)P2I5!=y,|/>mLX* V'K[&=O(8K!9Th!+qnwxA/ 4qF4mVas iXnU[/;},͚05w<\m^2\-BTDg0~'*=ueYB^r9B[.żZ|6n0hAX:34YbIOY撊īJ~yyur*[m=ys5x/.*&۵[Xi('CKœ. $}ѡG͐o5kN=HPE%0[~o EdlקliF^G:o-Yv}ihdpȬCwCcn,5iie6S Τ|?h,Ruô̰00ᘇ~'1ItĚ#ѬvY 09 I.Ww̻rqHRrC-Q(P]?lRd Dy%j9C?$}jZ{q0|Yl۟1âRdF%Ax-5v.6f{r~i}ܽAd3e6x!# 4^(78lMnmHɩȇTJyI:)cu~0iBv'In{ A!դyl,$@o@*,UXR$:9m+ST`舦~9=lҙμehG Os~ w]6ɧe KpAnrDĊ:C YxD*8‹4n TnU8hL`xbec^Dn;lm^YT*Q~"vF;Q[/clwK R,ZȥĖ+xC$e:{ݱй~ Wl\.H9ryfk$цM?Tf&)`P);%G|Y2I_:2v`%mpf2n^@r0eܶ 0'}UA%f4iF㋊AL'$ L, 09) smJk]V渥HOX5+ s'd OOO +"Tw44*:{W 5HIRҙt:s))C Rf,1vv*Si K܏Vn)YtPFҾ~bÿZa3}B$~aYE@\1|nE@c.]Zh' y޳/8iA 9ܩzyӵNw!/d H i̽ddr} $ީD]jZYe_sa ۵lMDh1pK٤ i-Smp.@,BXe` 4}&uI=r祣U|D S 0Z֥Ȟ;=JՒ]2Q|s0OZ[ wbe3 ~ #*۰'džetd́7[vXmV?`:ĸ YpQU*fuJfOVKΟa6fzŷٱoS"&X'h@Du~.;f/W*~K:Y6Yn0r ͏m *{Ug5W[be(*4J񶩜$Vxyk4 J a=d4|E| DR,Iw,$oC{10/>$]}>/ITHcczGFTS T΢>d2NYi|dY/z%ߺ;{R"O5e圬r*!J3\0FeK42 '9t5I'C^VW, |)s M:K} /RoJ͛9em[tyu*bG@-}OCƺ>d,$ZIƃݿ"SCF:xŧߩ4VX6棯d]ld]z4Kih=zzzg7~rY8e L|hǢtOTCRjn&|Q زIhI$e4k%?Ydy3W$*Ѻ-e](0+iUp@PT9)ODAzxD0%I gg@=*BD15YH4\XU w`7ᜢ<.~XY~AP Dw2y!vŎW>4>D߮:aE[f.yUqǢd ]7<ٿXcD!ghҐbJȯdSy/őaׯ>wۆ]@E˜ lrx[2٭VrM*$-/K (Ȃ2:K}eRS:wHJ夗ϓYpq %#[tw줥)1)hs١ȴz.IQe|ң!x agc.K.&Uap?:jzv%.."=dNm'ʜEءj(KKJ4ͅ).c+Wr΋B'7Ol1 K,Yq]X|OsuYUl !?9D4yt=,ֱfrE&'h[d$iId-lj<2 u0 >-lYZVÖ7^Q qBz}?/r?&&xwcvOM h3/wݛ(g:Bt7NeM!I"{_#*`X4;/?WDt!\ UEJIJ{ }PEEFz,S:YfD<_GlHTYB21$e!}y?Ѽ &:<Xaw= 2l|ڣGL@អW xyO\$4 3yL)iC %Dy莝uN E@=t0[O`[ڟwU?Юγx^& ^C?8SpP'L<5u6Ձ0}k2 M'4Η!]+9ݻVxڳ7NS.|m5`uPVe"2.S!˂\Ow5 q9epަ,vŹLy\Kq;L-z۹~ok7ʃ'X?!/%nC:_PYlm,mU}%*b[SOHUG]Gh.s2P4-4@w>HD(Zu߲Wݹ0pc cIڦdĭ}b }mߚb}e|xk#]J(TLH;79?%R/-x2_Nu<$z&0Mu,xڑM9%̈F`P=[ a>:ŠӼ' Yc$XrՒK`\T>C 0.b̈́50%_A5&ZxZƉ)U+Ɨ&-'W4,6&Ycext0h9ͱ5M [(ƶOv/L z(,kH-/TS:,IZ;:TN;5f)0BlSf!t`0^ŝ!h%W|0.G-TITFYW_d P *P1l1ܒyÉuieQYLPiy/JKHhۖLE6ik}A{I uZg"q@LXZYAZݹ&4UR&s]h3i뽑2$WbS`L-q> NUTXjҶtdAvmeHMҝJ}Q0ŠeI5O'쳐w.vvU4%:Rjƌ&DFV-x:hf+eXk>^|)J>MO7̥tӣ5!FRvzS'{}@;oR?])n5v%v@;oW֢[Utw>1T *t8d+yوPpЍrnt Սѱ_х?;^;$7y4SHd /t%s %eȎG&?DC-o&6K5ˡ5&0amUr^0wi|Wiݧ#I_|dG%TTJ!ۋY_!fO0Վ&'wZ͛]WPY6,Fp0ӯ3i9܋GgP/"<]ȧ:ƩkLհ}?RG^}ν0MQh<+Dۮx%R'YB4s/r쉓cY7ߐQGw [K ]LG]5`i {&ѷg@G>C\#j 7>䨊L@YFJt+)ab&?r(#%8EpIYF}Cop?-O.4`}零Dwy\~Ѡy:(2_l4j91D͔sǀ'kЧ))Wx!-+ yr֪wMVJq" oSloݖƍg^I7m&1dtNV ǗumbYԞDO&m868P:KP:JkF7֓]=H0ܥxΊDD䍧NblAL\yI)Zħ 4VrX CR֯L*;KBGbu: ??%#]!2$mzW~$PuPPypD>ÞL/$i4*watgH,s">T{t6*|Fiw=D4AR pL>˃E"g>xnfƁN\,|*dtf D9x!RHXF2:{JAwdIB$Xב]LgLɃ$_mҜc5vߍ٨Ʌ4;MG}'ڄ6dZW>$/6ݎw~>R YjwWTMMƯucɼߌ;M=a7|fL'lR|lmb:8_Ji=^h|{\]AS<4O4KT1ۧn `#&,cӯDwxv]gf'ՙ\U%Qag{]X*E/H B*/4GI$WP^,ᇺ}:͂ud%4E>_@o8AOdc7ÿى>Q[HFﮓEW5J\I$ y9vX><%rxPз774m:[/]Fnͱ 6G O~}x( 5p(MR&(h=KY骯-dܡ3e7#J9P%UQ|RRrO~`ʽ`P*WhG#@gjd!XEѣ-KhzᘠlQ, $Z=Y k47M\tq ~=cS>8^WLl&,ͿNu0J2,l[GKJK+#*%D - +߻lXa: -bq#/~2=#Z}`@1Eos~,%'XV/ɝ&Jrs Nxc V(+'uIfylWq#ؕ],00.-P0h9Py 7-!ߚx6]GGn6, ոY/@x2] U Yc;.O醢WOqHg~||c w&^MDQ@@_;s*+ͣY`Γ^@wP ?(m($H%o1JnV~^ ͪu9CWA s2ufr( P__.2w隹>zeWͺ#dSsQ y>Ś\yQfHofoSC!I$blCO@ѩ/!'Z|N:&QtmA[-Xy_j佱# U;jTB$n"mu4\0@x@!W vbِd1*W*/ҢU/P;5vfm)I/v+=J9i*$={z@)zҞ?ḡlԢIiP-$< ޓ<ݷ=O5!b`z.sxo%ׁC(;Ks,C=?jIdu>M3;-𩮞깒+JPՋ J _(k` _D#,+y=ajʿhÕ5"oKRC$] pMTY3A/0B]qn1bf% C Pg0j:EB#= 3QrIaG Ψ\* ,T:0HcM@kqlqNi)Ay/uz-Ff^A 8 i|TGS v-}脱ɟeߢ֣,i:Yd+46Rbv>ӕe@L-@w*E$a7e`:J kܓL=[Z `8?z~K@O2m1%/fFt$.@74BB' eb( 1J,T= OѰ]|:lɗ>G_nS,|@XS2'eGM`~VYWM jc)k5}ZtmhB.?tD<Kۂ8Go,e^T'0Uoq*θ@]!B B[|TM9K(LtV݂*s(ә!"`m8S{NFOnhclz$ DZ3QQd䊍%ܹU) O?1ͷg^i!G%C{ٽFLg[LYIJ{}͋.RD2غ2thfe T'+b9I%kHHsX˯*Cu cX%,9rg1[.,;~F 6 3^[v<7*0{JvZO31[l,"b\A)2L ard˗e#`^8XE3X*L:b%'AD.T֩\́^mO _O r:u:ֵߥJޗn~lp}`T(փHnT ːzxTm^ U8);b^ @xfC-WXGON^I] _xU ::skhp\޸yDQ}[Juoa*:?a .uRIJKa-{fsԝ#+l7lÇ"1Kh0J9֛xU%G5)Av~P\ KemhP?LNP{wK^>1eY?pMʙU ~x3ioǪ]:m' ڰHEK[q+nFDɌ^(Nȼ Zh Yv&̩̃}~~K$C׿3/ҥQ(.GڒX!23XMy΍P t(Nt`C4W`?.b#N痶%#3ydhyd߈~T-,<tbo2 ByOHƸ]`$#&ZYv,٪ߧњUoOϷZݚhaܳPQ9oͨȋo!s({aj]Ɲ̓Mp;8C:Uó~.h*j%klx(O٬Zcƍ:Ţőtȥ<'h@b)т]x`wE7ofbt`j;l&}Yؕ㸪+kW2Dtȧv1`f)oVCa.A@/oGq!\p̃ז`ڙѓ=qFLӕM qm?`"Gq{bI,(1u3*FkK;0!'@n:rȮ\mnú0.i&GCJjB$]:Y].{A8L+-d_l sn $eȫ8yOLG3݉aQVbj^5ѐ])=3Y!EO,6YP0ˆnۘyz`,CL.O[e@e&Ys\@77(̹\'WNHż<-.;Z(u|";ԝGH}`-Nʱ1qˤh:jA0n2.P,>1{rcJscϳ "9OX 'YpoKMa+8e@YTӲ̩Yl΢M L/p DhWֲfv&{9 4-=\}i<* O2^*N9q'n 0~C(_,I3+/o#ws힊ΦHw݁| zцXj=P6p Ψ/q]erXe`~ZGzJB7֑ZTd7ұ>+|y>rj(!0ذF/s7yG#;bh-5pÑnYMܤ=K|b_ApA XSєH=E'> _٢*6QŒYguC4bl0GY&6.ߦk AyeHFaqyĢ[HR )her՚ IV…39|ʠ!@w sy0J*$ fcۧ[XGq\9}~[k}=ֹkw\ϣxAP οK :yB=[lbVƊX&@\ C?lD񒷑  ̞p=޳#0cl_f;mgoNZ"ټtA(G9SC./qU>/A~tJ>PocKͯ[}(L3틳uzn,]䫯YV[bwW(V'xXZ <^V!˖H~8K"':4v&Q~?16Ee}7,+X 5T"0aW5uZ5Dg/P6* X~1B6%"'je.{e䣮@ IQsyN?Ps+%srEWuHK\I %q&!LSj$Ox2ـGmN/мߘdmQ?VI*bPyjPq}  ʢmeJơ3Æ%Kg q'<^ؐ8]eD@a'fKc91ԭ-/Iҁq 姟 %Ɲe.+AK%*CyiUNw5BNV?DM"1"58я+ˡ[0SݡI" CP؊S~>.@ 9tlǗ7{t`k_*Gj6 @ &C3ٌlO}ό>A,ktؕ]0O?e7sSٲo&X|(bTCIn!7m\d[(T@1o6VPSMLSL4ƃDC8²E_zTx c@=V^D%BЏEu*LΤM3e\-էB?q,vcQ̡(4| ^Ih-Lݞ^P˴\)1ŪnB:Sf~KoEȁ$t“$SQmbfT< wfi;$M0o dH#2Џ|n'hdz :C PU Ì; vCK- ^00n,r/^5riVʎpZ}Q&qjK!iRnдoy۸,G_;X \#I <HEݳHF6+=40ilE7Q¶M˘6t.`;s,yv8Ŝ_v4  G+LϥgxiM_0ݠ׺ΡS0$FD|˂^oЫ;@qH.- 3Cv1MMjڔf%d ,{)0Kn-4?7|Gp,S 6lB 6>AO@Bf7m7PCt|4p;Ҽimdy?@aX:Nz ΪUqۉ$ݴS0r<(VVh<_Iه薷 84TRr~^2g-gGFiPH>cΰ$ szZ=c5pB!mV)WyuUvX,Z5հ 'zm*[̎Tw[4%hREBJ3i:6{6oN3"tyS2Ge$5ʰٵޫ(*$ze%hn擐<<>Zqh _E77i.A$<%BSsj: vwǯ+k^N,~~J>꙱#$7YM|LhU!u_&JZn^ VHwZ}"Ji yUPsv=;^4_$~=a<[p( >`eTAOoqhI|6+B,a@QZD6O&!ǒLvfff}98*PpkDA/+4SyzpbV6tw'},nBFHaZM(i&;³_n{4z2Kr_ya1?Sh5kmT5^|EA|?5Mdy:ᨹIɾwwf>~0A{!ͳ[FQ04طf :W48 JKtK$xRY6ub!`7KfW _`аs e7Z-I(&g`rY=Gci[vqƝT9 ''n +s'9 C@': c9yew{1p6{(<ҽ_KJaKa>|9ڀ N*PY'c'x(П p%|Cןn*OS(X_e_l;/KdC\jZ<iD4HʗIVKӶgVUȂDS969 ]Ȼpf,F *oP1YIM.=#xC_S.rF6OܦȢ(ƺ}t%rTLq(WMq"W񷚩G#8SGSb@ /CQ ]FAťSGɢdn$aBّUo#_s"N7l!Ug|Unܤ-K a:O߈YFGw+%X;ݦB0A0 v鹳ű ZxhP'ƭ&A͚T9t>t::?~YΜc-0O:5z82m,Z`6N@[_*HMe obJz3d_>Sie|̝EW!++d Qwa?#hmfda]fhC3$M=?ц!{F0QaKZnv=//{QApWy<'h LF xN!F3J pk;qYTY7D%P\ -go3ޥ؋9ܕs [s)'x'MV/ ",;?O`thŵs}ЮGBSw2~` _[gK"*4(?N W$65C}Z&S.󓋌|BV-yAXT: up_`(d4i\PV <+ y"N3e],"Vst&g',8$y|Y2JA, U̠#:bv&IHs/=p1̏SiQE ?Ҳ= IU ӭHLRUyIz Z7vEuNa.NŲG2#9Uw]!O 4/i0 w?,IFv߹)WH{h6?MR&xK]j/dfStҁsM )/xN\'`9޶a!S6j fpk>Zv*ym:[ D>Vն*c3987fWӈ'a;. Kg2}#J//%ɒDMs @NI<*D핒cM))T]c$¸J|-hI[o',0?ikxTc<˶tjT6$qx$6\ Et䕣OI FԌ~-ZΩ_W~01 ~o#d_f d=t ȶNMVecŀ ic}r:B0rDW7<!y. 0ȝ,Sgq>48Vwyx<-/\ \n3HQ />P0_ط(a=.0ĮcyCA,vLȄr^ΟRd$H9|Y4O҃;,l>Ɍ=ZŎ0rxgNB%"Չ$  * yI $YCKJoőDGY ɳηy䓓+Yݍ,QN%\gjg E@LwC/}yi|1Pr _SQOZҼ 1s #; ,t^&iȦ*7m $dm6*P=P[bBcjx|MEj ȧ*ldˋYβDgpo@Y\N]K-\5/NޱֶdKƅ͟}1=řpf16ncM}Hp;Ɏ])'d_>Q(7f6 "*`?O*s>,v%BE㧒b2nS_M,S ESpN`|`XNO[:J."2 P6&%qЭSB ^8>dG*:r 줒͡y5r1caZ^|2ةnU$}"œ%4!Ke3o7vQNJ UB>藩p"Ɯ"tA{!\/&Xȗ0iSW} ,R$q.j)@Mt ϖi q[R5+2?+o{d3 Nu3/7AX$;0ʶ/lCcYW/|Mm)Hf3"Ci&UV4Zkʨ%K=C{SgN[羳eb;i6e2B9`Q-W /sBȡѐλtlFK}a {lV}1<rg0n>Ѧ"N:n1}1U1$8ߓ&پt3Ȓ YHLM0y:':FͶpb=89gӌ GXA$h?TTӤނ!T @q  ᖉH "4$yͼ ˣ/!/[ddYr~#(kB9qOxC^;8}L~OQCAw~52$QW&l?dsѯK]'0ЭٛgDiWkD4nu <ӼvE]LAl7-ݩ e>gZ`-42RTtysp(Ӏ&2TuQ*hưP?iJeu(@ C-m]Y4@r6mJ5pڕ|)ִI>P~6bb,yZ~=8D |"j4"eO$q- xF $f]}زd17A+A.6z?Sr_- 1xabܩHs"_r7p3咗l˔1 ENvѐw{.HMsT'PGY8m-7er`C,~(z(3[wxbe+CgZ#AOxL`μ8nj6͊_&P/"Z6P”)[572 V!مFsG9.HEiI.\-f.39v* >A Z&icw"&>C2|{3c=̷ U0 lpr1[mqn(Ѽ=o2r^&NZK”.;"̉;^V?F;c2[h[L= jQ15pCW/'4{sp\ '6YK\XL⸍YEbϣ<6q&q,-#mP1[̸LߢD.')H𹒋qXˀ,2zC'+(7>e6yWKouǚqUB/mf' p{no5)ES#znqN UD}f -  =$Z#t K`R;,z_o&1)7pG#*@K%,NY݃3溘\ff=A!Yae53p'^;_hmdHs`T8"zQs`ЁcH$gg̸cRDmm>s ŠJ,y2FR},lw)3d[\X$I1K<:uy hh!^൫hJ{w=զp&~vo`aw$.2Df`3uֈ;a \#  j%,*ڴ\ 7[ cwI@~FnȵIG&;kGX^N&􁗇zMwoIHMi,x.KGp/:$d^8Mi wW$LL i(=ƻ{> 0lfьf K^B=)uƑ# .L?R֎ve ˤL8Т,PVC%|dcu& )h{~VZ}*զgjr!_h/f #<jlRN5\|<\+Mp ;]W|73ĺsv]um,ڤ뉖A}Ċ52PrVce$0- lF9(# q&=y @hVF(|(>"Os>cZɚtCtÍ%K45l>1 k{be01@f lK!|kj8EK߲Ј{lE #G&-WɻhU,<= &EN$lbLT`]R؅Wcjwi/K&jou.,٬X e˸c4[~ 2-?dB6w9"NS`;I9dLӣ1OtK1\ ٭2#jՙڢg|hyےFSaQO4jB dwG$Sc?#:Dkc_y%Z=6D(;Z*^j&f)]/W_ ́(&Ӏ[ [T`*# Xpy**!}3η4Qxd6S[&R,n5O38gYn4;@W%K6v Ef{>=JpO,Y*Ÿ \0"b.9һgn.p }lA % tL2"-GsLb2,q8>$њtEY6(3j%h 6"|r>IZkaƷ_་8/1A\,X$V6_]7̈A\A'5Cl F5MzxNl&z !].W9>+-:˶XEˁΩB%x|M3siOLq'8'l7>ߍMKo"Zλ&0`KTԳQ̟ _DjܹI#R+2hr'ڔ|&, Ȋ@KͭlSJNJ4"mεcS̈́9WT|}mJm-@bӠɸBȆ~\iqliE:0I˟=x 0Hj*=x~EH?@W S0"udf䬡SWv+R?="aHĖk`(mѷ-F~^dK2/,礣@_tm[bG=eK0f+hRLJf /ظidyto;'I/9W! Bg ^# lf-#G_iMFYDZ"0:,䝩F+~\#6bpn،|ed0LW3G|ujrQ_`YO>:RbӲ`ljU:Kt ,abeީ`6q_+H`󥧛IǜC_"TAR1?\_뗒8%wq -7`CPqgz~2%;%+bI&-~TVtAՑq'^v] L1R#qU T0C /8bD.ZҬ;&UGl^MfaLʌsz7@/F8;tif j#+b}ٰ4KǽgSi5(*9\e#= Dƣw,0m&=:!:0J8_o=kZ3'%#UAse WN Bhk}\U8&G#A6= Y m>}nYLd|; m$UC S+y$OlR JB|bm&KeI)}%y=da ?ˈ2\3z+ 尹׾֞Ņ"Ȁثs\u$'ݖLjF᐀aX#k^ЩPbc5Kv}.[N#k\UGC7ltOkh)~V|k>Hޑo٭f_Qw 5g/e,n0x2hM˿>qe"vx.}mXb#cs&gk:Stox7ٵzY Zg->>kݕi.1[UY Ngn=;wNe Ť R#gK5~ȥZK1N!4ib {=%qlAߥ%$RT˥'@&[xeX.GHw}OD/ˤ>RRQ-dNe'jf_h4DF0@j L[, EףN"3=IvW4}*WKtx'ҷ!ܗ,;L| zADGƓLOgcgdx\·44DΒ2By&ĵo|tLl փ&:d-.2<"Ia/rVc%w[GCYo.HPZվ Eƥ_d:bɓ/7($4wC#:n[\TypmM3V`Pϵ,VRplvzhȮߓ,6Q>CUR&lvU@&1>j<]GoK5_J1|\kR#Ybe@n1>ѫݦ&3z %&c}I`nuG{SZb?PPatN(PIt*Νn_}}E1)]!J+?kmP.`S@TO1v0b[ՀV݉[ǵxj޶IAg;])+v#RT!nKtEǹh,jQX̑ I*rMz ʃ'ǡ8q\n(vnI3vIs>@/Y%P9#/tmZ3#pGs’exT}hrAVf7o*^My/YKwћ\O"kڞN4ͤZH"HڗdFO2P}y7lc]Z9,7%0|']yzT _嚙xwPbPYQ~-Ә^1(ڇ(y9b )?o}/戯}O$y៉~Lhҝy[q9VkkhVWOԃBOlg+MHE9RR龰OWQb@ W;Bm,$rLR߃'b9т.Ũ[߲@.6yŽh@ f^&SPx5 V$ l4_ ՚a g/ P]NBv?s85Lk*NWqL6rJ ~ `sPFIny'鐇wPU9k)siW)lV1O4)ϡ`r/p}Lr mYqQRϳ` +FuR,Srmʣ;VEi3a_BGz+ DY#f2-Ć,ƕ ?DQ!“ܥ$E(~Գ3 q'jZ'Ms9ֻ#Zd͖ijC{? O6Щ5fW[pt:!r=>2e9CZOՍo 8~ۉȲ)& -ܐlzҺEE, aD)_<"|VE/4bhgjֻ=7Hhl ̩)i_g'5eOSS^JG^od9 \>^$d0w萺"z(=g? ֥V6$(?O^"O) G8wgS)9}i'}8m\,0Je"ݚva@V0\Y ;7X~WeV쨂 i.~d'638't%T[zPGJbL36#`J"K3ZXghJ"WULt&[}Y G9>D8H[W;sDRi-'6,* H̺tۭ 4a&@G'x#{I855 m_S,dS~vF'MO fQ@#rN܄T~h%~WJf gcDĒObY;='@ nvhO{2LƐX+#И@#lG?N֗\Y D}N_n.pȕ$g@<q_L]~:$y>'Z$''B ![YSw[z2߅8e(cbiq:d1=M-7 oä,U Dh>9̍ ?ʞn.55.gN|mlH^KbSpsQ}5fH'Fv KkTe)+2#to 6Sw1NT@@ONE*80 :ʚ<^]Dn"8A߳VJV|;^$/Le9ON3FWٮSdj;|_ F`V#=.aj~eq=Daq]B$^r&}5qybp8+0< 0ISL5{74ע6<=\-2kN c"ߘ @ڥgŻ'ro(c-͚D"'cHZ{rKYTӑ*51rbqVtJ'V|1&IKimR_HGg, HͽH'{{)Exd96)/H ɧ+~!z-bQ%8j![P;{ݧɡ9 ^~#}Fqf5)0ĊoLWL#[H@&#bcI6#*wKsۆ#x]nĸ#H>OμX/4Q3 N {p"ڄn-j% ȵ.,cmP+Ԩt;p#/ƺx5Iۣ5Yh*:TȳcfEtF#> P q},*.&Rfn7 x8CÀ FJ?dC7yɡ,Q.}.y e ְ7=Bōl"CBB^W7+P ?S}N`qROF$-3+S:^s}7Z'|hˢiV\H>M|yMɗ\]M|hV0g9\O/;O=wD*5gKөރB Vka'ٵˏ4 @EchNLiK Ջl d|d3w->"1%3n؇zV/޹N̐)e@na@Fe*#.ބ$h|bP׆)nj k *;;Υ[ 1﫦j=@ q a=8N%NQl/K=9d;p2hN"U).#YV[۵*ӏ eP i;,_$k֢$" 3:ŴvNk}G-G|ݜA":2>*UgXԐ`&Yt=1o%eGyc_=/yH GXߓAώaW܌izЫ#'#.1Qmf:)ԣ~(A Xi"!;( 4'`+? E6gD'.DisM*R2''w4j;0l>uCȽ!iP ;*^TJ)ơDp#2.S |qph/'Id|4̵(ug |.'Td|(3Y:?L9bg:!Tsڂv@6nÂ9N&t!9}^]J"I;Ee=D<oRYIu1٠ɳ³'X+Zx%].B! 7'%~B3k^R pdU2s-+is*E%o-ix*.M^%)LS\J?PI鋽% HdЙL4=feʒŒW|^AnڪIŪEܔH5_$(7Q˾QR N dSVuV&COAW Bz{ $69#E3 ֘$/Qlņ%I8O10qh2:GC 嗲w G`#1s+nuҠCo[D2xPoV9@8U &|tm7YOMΆ(Fnsqd߲}"NSaļCm!X ۀCCȗD$]}\.5/dEnk!C'tGX0HéQ<ƏSx.-r4כs34>݈Md_)Nܑ͐3%`2cƋ䱑*`Q\O$A>"J(^9 :>^z#sr Йfzi^дbxa+ԋ:rq=Xu䞘=Y+7ؽ~"M2S"soX bx>!7p61CSi},N^#gv/v8Z'ʹ&]=ʌ\r f gulVծ;'ЦgOӒ/K١giXӥÓ~c{9qgPΓ6{AC`櫽9<!{+|a.a=$IO$֒dzWt)wy;Yud7͍Jʁ CZa:/dH `'!ӈZcf l'RJΫL)X8rin*.Zypf梷g_<#mMIbW%g4yk+bHy:ɍ7L#\z.3II3"IXǧfpZo_霛' .R!Orbym7s,Dž:JML~nqweiJ sJmB7W]KP_xlq^"[Ir]ym1|}*J%,jUe~UH[*\9UPH²@X] 9[W15@'N6b8 V3A˄dVܸ6Q?نdJP:UW.40&CspN A,38yZ<$Ve+փ-P'-;-19ڸdl40S9ВڇAz}G9"XBZW{؂e}xBB0Vz4o@ͪc>J䮀»a\2XINgf > hmAO7 o)9򭪥4R+|x1o)d]xkBGb a]h*.pp2Awv:B3 ?̵D>xyAJgmBHzwuG<ؑ *|@}&sR`z;ўGUሉWo?[ MZta^ѳ 0'\$d'C- _cĪdXU%Ӌ44Pki=_T? Ve*xznp@VŏX―S:^ky@,T{k>!gswO;y/P: Ơk5ĘsK3y~0}sMkȝƥ2=-C"KD^j` N֋2]h WVi^f]"C7y nyL3K{&K婀9\DG,M*"lJRqӑ@q"&xw Ef NjqIq:2ZoS&XPCH~~]g͗:*S;Xs)$q3_fHa)3ňF82-nd{x$o<ϡ颮HP$*hB|@O6'+f*e!vc:AѪ,~x[L)тB^Q*4]|{L[\{~߾p)t˖z<1%j\s?AIHçSr⟈"x7.5f3QmdU}('~@nQW GuRjs‡!ЁGA@H_EqQDƃSɫK@JSE Pr6T# coE-ԾQG!_qYc*yuf N (T+`\9ueRt2uVp҈l1 $C\5@ێoDW9(+kcdv.RAù}G!F;R0uWѭ3ڡS&O U$w8S䛗D OKDJc<v$sϣu9=wPehO&fp~s5Y+ֽnb: $*vi9 WjIC)?q?I 8_+Y2!jr@V4r4 LeM׫\k~!)b->N.61s;L8u}Z%H_)X|%|raG5OAt7Ą~08f RJ^GIHRFCF$IOy О7w}~%3ZBv SBmlM''Q5gu8p!f97yєs.ܭz0e "UL ڱ|]*"Δ$u29s0VOґγ|#1|῝S&Vz< io Lty ΔF84/Gʊ$*rw.]{VX!x!-Y?%:97Lmٸ%NY'VXe0jU9>*U>@EȔ289߿5l$@L_Q@൬w6mWPy$`f(KHH=>n&u l)P5 "H&/^Cƌbjd1f%`)iI$0콪0;"xT TdcVR?\Pe:T6n}Lʏyn E]8sU=vZW@9]I4y[rڹ @دzlNh`uSІIY 9YpdEiI`Zr˯6SFJr._l$ |Nä ɶ9j4DHH}&h%2Bg243V"^*sI@m}%%j[Gp^!/1Һiq191U>Tx]L OӐCIj%!ʔ fDkم&k=_i L!9lUXi&Aup쌋e="@ʒ#\}Yɂnnqw_eg>hP^gxڅDx)G=:fPe]Ti+̜R,,+ q۶]!{w먟rt3CNg'YfNo4cRY^1|b"Wtn}GY@I%IKC<۟Y7O%|իJ0$j7"Esο"7(3`[+Σ=M PਨO.#:RʨScc.sn(Q:3$WeŒN9j 4;,˔̊bwbDwaۇ֚Z(*qװGst;ZC>/7z78$-ִ)~^UʨOj [Rme߶(|R35tS.q{+0Ȃ`:y5B %ܜ^[tm%4hqӤ# "s:/]S*//6pY1sJͤ/JLK:B<׬{} yܓQפul5؎-15 س-jn)MWƠhyv;'9wD88Yǰ:m}+Fp/ @w E2^fgaes"RUXuIզI~ %8W#"G뙔yjKtbS_R]Vk#b>B#z'ZI#3i$|Hj/3K%1JEa ;UG'0oKvhSFwtNH6:kDpr3pgt?%Ց[Q <}z^p {k+S5_iئǃpCiB vU-c6,?9Y*Sl* =SfY'Yt8AY9>{.t.*By*뷆arϻ^_k-/L1h_})@wtQoL^󄼤X[c*Fe,$z;z+PmŜϚ޺j'}mh͝wh}`tTd}]O܂<]hJ-FfB{ܻ=ۓk%bJ%66;[=RJ*` ' &ޛ,VsUHNF&I|ίs - 3)?ƕMe.#r)^DΫ *s9`_ȻMv u%ts ܅HGS&7%-:6 ~`8Urߙ!5SG!/g rUX:v#9U5>,8-͡m|$嚼nCRy~8H38cobY w&(cݘ"V5Q|n kߡ2En Y1pKJdo6U^xX+:?euCa:ly5UTz&YP]ͫ]d> U8i'L .p; Z^MT S:$z`k)yz)ȌLJD ҍcY&}T 9ws\u ̻cpyj[K.Od4JGowC!ɮ ('ڹcD^iVJ ٹlO 9 z‡vJ?@t;I6V7 "֬6my/y"&!?83r"w@imƤ?K\ՙlo/Y%6y kf5 (_ ^~n/B34^5CQY6 $1"yYz ! $'mݙa9T/Py eXe'=pΛʟ:-e"확 a^=|* !fGd:R-^W/z-dV6o3"$(NJB:W+ɸlz7ɏRyd{aA>9 .0h_$Zz3 UO 3#u&cӧnhuqf*ӌ֧r.+\'!IO0l[aƫut8X;'k熍pOy*7,75?LHtRx 1<)aE e;(Ce}!9;G\OqMB[Cb*6}qdB_4 "NEN)Z/a,oD-5MM=B_}^f2?z~l_ʍ0 +" 32ڤAx4ã`լIun#vJαS${}UW]QoVqJL-R`@٨͟2DҨ*ot0bJ3C :uV'̩SP`E`'Ƕ ;MuK|=X!#3ˡYphÚ{ۑ\}y[γu \ ѯG}u‡'|%ۜIřqN\yV~ z530%\;E^ٶwsUyIkQ.}`1yM渽>=4Ivj3 N(ǵڜw&hAu73vb3`Xf#7vz3hRwR;Q9[/ J y#ݻ@G*/s<] /'1[3Wrڵ۔,ğY)dNhwwkM腙:U9˽$>Y|[uC[呷2A^ &~}0yrgBNJ qq=#Q .\y?8l&u`B:sa`roHUuEs}^c yf߻8"-[]VkO8.OR>&th0±'\۵CN-mwAP\O}:^IGASyuHiڜ0)]iX ¬\_% 1̤"161nҞL?j/oYҾUJ$|5u }< Z;i(#ѡsP x9;P#Jn~ٞm'bı؄2V˥^/:WG6ؘ9:ql} yGVyo"s>ZAB QXכּ=˒>O8}pU9_<:5'dW@eQ Jo8tFVXm! 诬Fs_*,oRO#_^u3ǎT{[i+[r%FД:=|iFf#kiv8o} {v3pe"2~af6cϏ&%=8Ow\m^vO! &f']裦ߡ#1ouV<;i]}ѝn1 Wl_`\t`ܴG Ĺ C"X>v uڽ&EΩ ) NcDtgvJn`OEF4nM(xXl2+d]Gmy˹J\.5'LѼRsn9]Je鹔Nȴ(ψXN20rmWO]qwnfv%ӧ`!?9!X>VC]f;:bC)O0Υi_(V/Y/I5)2 v?#o)֝yiy"w 4*+U^;<xyZr/ (C1߸ۺ9Ϧ.zƘBQv=8v.oڃ40u,X؞cɺnsJ˙;h 0x#KrVi6v>@Z0P b̉1VLK?UIKkgZG~k>:O̓b;zJMM*Vx@ֳ)㉆el5,d630~A@p o}#?<9ONG |1>5wm,-r$t"NcG<E"Ӳkm5gs?B;>EīU8[FOueau8;m97`u ^^Aa籣vhwG;nwϻRJǻ;j)6-;J(Sw t <},Vtj h칍)DM*{ىO$Zj)gH.Fof5y (U%!f@9ɚ4n"P #Ij.g7h=%gPғYT&ב(T'|o|mK qqbZN:Pum 1#)39N)Vv9^GI(e3v}śBeM+"|s=_Xa8؆5q!AL})뎣+:$rt A!#}Dažb>@Ni"}{!㷮ᬵbQb; hDx敳KGS tǟ4mneAzXt\+GH$⠇|TJ+8&)-a'uoxR_sxbwTo =$IyxI }F | @R=ԟlu1mY]퇐l؇A1֤4^KR*?:Z³>lVMҍZ=WDDZ_?מFN]5Bًē۞O }̺m.)W'[2b>UѰp_7[g%m OГq* ʊ,2?rq4"7a6>1nRjX83 Fq-'Ղ<矾KT ;> 2%,22Sl.'@P_@uVz,:(!8\g%!C'}Q*F=R0;7:ǔuf~ZTUQ[=o$Sz0e=="T6m\ӻPٝB Qz>5xQo#Y뺄/*C%/;&)%10@> @oW 2~OztDCGW.?w;RycLJ){/S9#Y){ro='u^\A])$rox;tA@w/A- f7!y}N5~ٞ>+rs7&iy&rXc1>#8 &#w#gúnyKI4=Exjar:A@SV:nr$:]MRq2;`jͤ7!o̹ IC+:ֳF-KBh>GIxXK$ b$XkQ3$g\ ~ߊ7aYҖ!oΞMꬌq a ycLJT/DDrB[Qg=<}o9!v)pm>*l *%C Vxcfc}]~қw@9p X«{bDi !ś'X߼ίm"y#l³Vt)8G޴+}UW6i<{wDӫDtx|ى\҆]X VV0eH{\រ)Qnr;N~n?NF?~AV~R9&>v2EGIz~`0v 8O†`gG8e:C D )Cv:L9tҁ|Ywy(D?ɬ !7'ZԗPXrlR& `ޗ.E,![bW J#iq-]q'6-F.pUdV7 \A_Us]2+ϕ y4=?(WƣhאK F>۴DиYHFv>Q|nU_&iW B|謅Rr&HIv}%GJ*i*i3+N:_0#Uŝ|jK^SK=9E:{:Z Z&)(55kdg'h~V\(2(  _Fy.yg*и&ŴGͱ֡d-6IsHV}r!r>V;E 3|QZ(ʅX$M='yŮ~&J_4uo5 %8 T eDc$6@ }b; DY/0iE.yeKRr $-sEdP9vRs~Fj<Eʣd;sS:%;It Lwh'}qNLƐyڀbJ Ry֬sCo 嵔qdVJ0}`GMD묖VCX bپ2cdt {Hwj> ,$uhФa,k׈uZ إ8mn! "'v+-sF}{>Vs5*GUBw; 7M;趴?u=8D E|LxdF [Bg4nI*Zs4I![Li `eRݣ6u./,2BCˢ\ǙrWRNBׄ+DKȈ峅9)R*̧vh\c\x6WC[q^>Ѕc6vaJbC;dxk"w^#y՟RG?Emc,yt[Po3LVSDz$1ĕu'WQ4—Ko)"l1* s}u"p6aML<~=r/ bCij8 ;&/-ie5ZVu&)HKNv-&&Q[ +5' c5{/<$ %ڑ'g6%Jir+`ܲ'|{R̓HUs:xϷ4ʓ1+W1 yA9;*[#BsQBAӁp,om) &zV$,n 0ý'Y!X# SHp5*'f=h"@x671̻йBP~^\gS$]ިȡpLrs~܀t ;l-Փ /?r93U&F %}n!*y=ՊrOStB)CDvSaBv6Ic)9Tz^/B*BӴ+&>ҜqE!r{rV2Xi K6I@ˆc-g pV&n43΄ #Kgz㘕z wVڌп|nxB˛R,tdo{Z5:( ÁOw}n?P% .;;JтLBqߐJ*`uMM*&kl*=o'4҂&c8 ςm$e%RzM=ϓb"R*0/xW1÷/)p*AV:yQygа `@64_s;',O nw wﲫhE\/q 8Br>@J7nڦ:ZM^%T4#i"DBm^p2堇"d`X߹Eo[q3m|K~b+M3i,c_ZfN7 Xl" @gO]cbS4Z gţs/T*i4-B/,3Q~zGR_y#Paw9Bh^ c-KN_r8Ĩ/K#b A"U:ϲTF,V^+Mԕ*;f5i?O޾^J'3+NX~9q{*i~ o%vȦ.č ӜŇH[#9 'ϜlCv= S, P ;Ig׸Oi6H*dFKN> 9KWIcUpuqt*HH(/8#&hp{%|KI[Gqn.LPXֽKLဿ٨b Ixbr@B{p>9W)( 0Ŭ Z%3* pe ڄ7'_<Bx⨨ӃĆ:b1KkM9 _{516%g6PīUN 0ۚi:ԅ@ނa*J̌ʐ6}'Nf:h0xԗGK!N>[;t. $.&,&fP}\#q.i}bulk2VUTѺ2S?077$ gCtS0TQ| r~{z#%P : d.Y]>gHзq' f:M6mXfH9tjۡi$gR u:fXGm?RQOPF-Ϭ7ʊlUq`fiEH;9«: ,x1y0B teHMbuw4 #~}=ۓtb%kM^"ӸʰWY;ԴP˺3),$mmȅsnP` /{@E{* .G|"kˑRebWWި?z, g׶coD.1xym+IGrq*ZAЧ_|ԭEF ȝ1ļ ([v_"bNڄ?;󍭝=^ &\&]j.lI f'  pxeWy?? Z+k3l?54h@kSHf C_Pq{1".κT)K^8_[4}m&CiE~ipf07rÀPy >m`[IlZ~$|@QZllhJDO9Ϭ]'1*E`YTЫYʐreC,AY/M\k 7+OH1䍆j'T,KPvMH󾇿7\|&ʣEo>v>Al1l hH5=b|\UUwD^d?!E8#ce27sAukА4{LNxn77Εl/ԙ' N;'b&~:2OE4+"1Ih/>#=ZpVRL6(:9ɚD-]s.Pr 9AM2YjJ :ܪB9+PJX\aޠ4*XH^'|Q󅤛H(O8(}h֭Ab:~lVo ތf=9YeRuLY)ӋO@alky4\iMRBIgZї!?.|t\vX ᷖS#rY&x@Fĵ(&nҘ#D&bE i6yr=JNbX|A𐷱Ly=.;Mz(-fn@X, #Hg< ^b-:)UA PoM3dKlך0}yG Zw_K+w_):7AY;ŋʧz"҂?4,3M;7o؇tU^Iɮ01CuJKhU<H3-;!| ;J-o3LH)l!O  y)Sui|ȝoiḤ@in-Jɤ[ol\ne2WJ0sԕ9IbD[Q-_9sO+)}@)mazwHɋTɋq1s^FS'$fT=4JQ.//r@㗽*rStHxZ&kZs_̰AqNU^1i ѽ좡X<86V ì|Lar?ҌhQ/{KM's)Br c` L9hQ8%kd屰, <ܟ"5 sGLN|Okg`@vu#wjozK8aFG3d֏vr$A7T! ck ҫlsͯ\:Jk>ʹ~ ƙ͹ڀ{Sԗ^WF"e"6FwEZ) MDAަC鸍 !RfFqgI[@C[!Гd4 Pn|Pt*tYVwF-y ˸"=z99G&tn Ih!+pk&'idjÔZjl"N)a WnaId_$.s 7?sEy+:Lxvptӛg0bl+d$.'=&ȏpB7B̅' [.h  JlDNZ(3[y)N=zKed 7+F6O)@)s#O9MuHKyo\&K Ș]:*BH9PVNt&_~tJ2AZY\[s8P`]N>jE :u 1̻HyA:0toαK4UZ@Aoƒɺܔyv[HF 879CD㢛3Rr`>3,ޞ#"tgf#\9YkO߉:/Oߑ8>Jm k"c0U;g}J 7W*BgL;`?UKѹ$.!/M驊[K72(Dw9Bw xxg2],;wz wƕռVLvy{ȁ t1SX)jts.91wθμRJ۳i :HY;Jd)" eX !aR̉~FNjb3~r(.6j~Q>ֈ")R9?"@&UKӎ'MM?A ?v+'Hpe.^(wu@X]7!3e &{!P7fqgXvP =] ptɗÔebJԯL:׃(I9VFSICc|NK Sw jb'P$ A/'@)( rʾTŨTR.I<<8jby/uvneElAm.+EyNj'jP|QDf  ԑ/i5'Y+b Y{jM:hػYN7 O[!=?SKw|t(nbZd仌QJ?1nSS6Jɋ^GE3rS"YOe[=1@MX`JG{4K8]@m9{-p\]Wj"Y r}IaB\Q}ܡiJ BLA jf.Lv+E]"]9PXBIǔ:'gPE/pT'ŽsW#5Ft 9<` %)92h.κ.` \tf8&^0*svrnl&ٗJ̻PoGT6GОH=(@A5e}B#FX5.T&0hk5 54L^9z!6|n|ﲛF^`6 dRa-뼙\'y3Ĝ;77-Xd񥦋뚮f}:]qjmT$L՝Oy1E?`;UMZ/>ξ# :CI2J@]r.4eC]s? `b 퍵Nxxt[ ֎3MYvJ.B(Hƭv$hAz{kU!m#:VQGl(ˬ4ti9# {r*L̡WyL;蹔OP0 7$ 4U?`=/p@eV)1ri*yY znzin03lBf Fi7Ɯ}k&t_nޛIw > ia2Nx㸈Y s ?芈c|^>Yfv=y:lJ+4CnIR' 8Ic eN"]-2M'*h8ſk~rJ)IG1?l+Iv—.|IIcFљawXv[Scqk/mf^BtH{Rص9שuvta=7شۣ:jgv줅66 ]G@wӑMC8xr>mG("u:x́V+*zC UG# J_gWC>z~?aAH ,:wu.(s:j?lyǃ ʪV SJc!J Zb$R6n.h?~7Mhꖐזsp݉_'sޝ{;:#@[IQYLe U ^f*I яZE3yy{~p(xHh_..VvTA bK u;.mVɅss>x fJ*? hU1bڻI:C;J>1rs o R⚩-Yd 9%}ߗԑRX5P4x3֑8jׂj-?t:BX}|bR־:f2\dL?1.ʠfo1 b+W[@mƪh6 &x}ê#5`N 7鸽I9_|iK+]=*BU Mcc5O5IBXB~߱]?2\5u@nqWձVƚlGQtQ0d`˸&y$+U]!'7@kxII~NEkr:G#G# 1[PX߹1uv ]2uQC:&)XKh;#:w}m 0ݑsIutsJ=X۷ucyuJSd4`p~>LJBv eI#;$<q@s,k\yd]ܼ8gƨ95q-JM(Y`#ۛrsiw' =D4G{fdmP*ӄb7kl B9^5e]tЦR7eY\ kCHO_xCw{1.0դbZȂ\fpmkA*vaޏ@kM':t%n;PvBBkIyJ`p6}oF!Ycyx%vTt75ȼxGh+ S;.т7NY 2-!HA0pV\ݠx`## ޵Sb2p |K'n|^N"¹AQ#γxZ͛IO Ӻ0sm47=է}/5у)W{SQNWx f8ېX[Dvқm n"m7̀Nj =wJ(o_E|s!z\4xº|.Ī<(ES$hQLۈ>9o*V)AXypոhVgѾD۵T^'$hDg}%Oij35fio1J-xڊD;Ėv; 14` afJC&n2SJFeE+_M/Rm) 轹A =*_W'[ZU/1oj~vI v*5; 1 #N^^gp5#(̤W>?Oz,D .'Fُ' :VQHxi [̉5m'Iè5ktj?f1h4lqȮr Zs:f5rc U ;O A^ơhͿ>#=U%(:O 5*N7<ѫ* Cص5y`?X9kNFmyq@y_򯾙Y}uڬ`*J)k%[J *4prsD)*K.I D`cS+=(DcTZ7)K {l'Jր‹$S;(un-,!y)Qs6SU<;@;@|漗êK%F_R1Wk+¾eg0 5X藣 8{yqv&PZ$/2LV@aGYBz^$b:BYuT6HZ,fr= `&-&;R4ht$$hfLD7ݱ}5&[#aU.t}NQ-VSuo^RYy0ō9o2+%$BPJ]X9qoӉ%RW򀒁"O}ASiҧr~ \vMr$q9׈N_ĥR:Swoq~g]a):sK1RzglO#tx[UV}4ZS[EA%پdQ7+WMG{FVU#0Ȓuw,C>p!ʴVXU>"mmQx(3P7FuT;PU 3HO/0xfF acW9sFJӗ t:;^`7G1hЈBμݬR_?ksxc 6|8EX A ;]mAFo [ǣ thShv/R{ 7;k'cU2qM1i<5^4Q'|Cz˃R4$gz013KV[+LvYJ'wux]q^"@&yp2"M3 Kp]NKEȖۥ;[/'dRa5g#^gYK{?M?zYP#d=P7ѬTeV)<` qW |xQmy<^` ;.jhGzs&)Ez`@ S CXsSL#7| 0QV;wAQ%ix9z^\h9U" LF3 c^S5phy@^6Lo[^_ wL]^<9y;lOID0~+MA @o WeCIfB}KTCG-ȉ]-VpޜzXdьih^.mQZk-c@gСUHm*|kBLPһ2Aoݱ傗]7#R5E:ۼQ@ƺҹrΛ=XNPVhs6R_"ju$"ٽ/rVd>&Нvcē[ U)&h~BܝqjL&MD׮T༎%yYG7ćF-=`IDU6z#)y;4G&NϧayTubX/_&u3MANOnZ?Kf}%z=>b{zqsd3ըq)Q<YWxIx5ɵ( jҏY;Iyj*t`xӎŧE\4Ntyrf%105ڡlWY4~ M]e(q ǖ~kbӌYQjdrǪ 8|$ؓ4RSY$.ox5ƻ"p v/8tʏ3v/b;{ ^2gڭz$zn25YCFN۬BeՈ<c^ռ 3~ 4n؃|c=lrriRJDF{;CD*a^oYx6tp8?J_mܱTJRr_p~[>%FjKg!~-? w:(<5liכSg%B٣-; WPK%O.P$nG#WJ󫿨mKЎp.ydJ1,G?]>>}-犎~0rr?VrNJN>P0]$'ZŚ`lKrØ=Z.BJq6.CTw-4W趿c`:D|aO!IbSН |'ch ,<Ƹ:Ɯi+m::LwkOsZ"y!o #f:M8>rh74ͻh>;"Ń1?u|ZOSuU+gOAeltLo|>s И_/kQ^.ݝ&{Pj~lN֕ʄkAw{;!U2VU+{2]* }i%#VTJ S@؏R8ke„O_Ԫ%n(TK w/:8 ,SN6>!OT:r QY60Ik.)+7?NK"cwry1盟 ;+H;' NH䒯|1ةJ֭e{Pmbޭ$^JV`. m!2OCGߠ>G 9vFZ@9 [R;]3oj`p0=ibשxJ XOdeU"Kvrn:_|އf:>qsyLnWY)&u0L+*Z["+BdD1q:qS8>V1InKɎ$R}Kvw4NzeI')Ax])ٝ4;TI3[2Oےi1ġ*[YǼ𓧃ouuhzH0F^v՝<1@(bi3XSŤ| *hXB~C.3UIlz'k4*e:zV3't$Z˪zd;A9=L6q8.+"弁L)̺Vr5I(0al]V)c51mGPzcFaIh-,γۊ,˂@OUvE?h==GvNM;뇕Y ck14Ck\m%'h,gA>_/SNikV4.Kq,JV_u^L@:'js72ՙG`gk,l E"+gylDh}RY_`I68ӫ"2DJYz-丨 x3yr$& (}Q:0L!Psc9 Д)b֪18b9 h8*,';([E ^D@tbyZK9\XqPJ%=y5B Ayrؚ͵ kbIy&=F5F 991%M.t=ҹkZc$:*mG]E!ĄqNF14ӓ7C9r3_5"tTD!ά3Mw2Jеu h@I%+Ɣ~0鎀P ?/4otOvakH[*TIP!EN."quzb) %ȈcKUHH`ӗ/\~G=k&iIN@?z8z%iM?M`JIMNO#C)JB$pdP O푼fHP6:{~kJ5M|mRAk ,VLz.EZ:΀ X%:?Ӎtʺt?ˍ#86~ Xfr*(I`ȍˍy-E9 6oH&KŋDrsŚ$ nX.ٜ7! pQ6*`bDzo&,8Z:٬d_I:Gi \: UU[}ua"ps6> T f+ j 0N (f*o&z4-@*yՎ P]6t.b4΢jb8f\*&Pyk}İ;NTLOTXmΦ[6G#",poRyz9}X4`hm 1y4^@?0kA=CA天A)zA@y{'ė(W? sH~p/ky/: K6CORgꉿ+G{Q6^նqY:s0 95Cn?U0>d~JЪ u,eٙ;ڇعh y݉TeE_@z![D7`Á%1q jXf1+]uso"/2=#eD,QCAQpEѷ>r9/L}?cͽ7:>֡Xҁ:|# ;L@3zk_w٥J&x <pd<>0z]8 -ԉm;ZsS8c0#*g\~\;kjV}#GjX-4v~=:[wxŭ50vs93ڞҞy' /;MJΊ?CUeP' ۼMƚI@Y/VR3 x1K̙4`ԡ)ЊbeE>2`'rVu ̍¥j 3v& >$ݬ珲QQ.ʡ\"Uqri-.ݣ@Y N!k`άo4sr(y *6Q(ʄ.hZ4 g(sykP:@5i )#/r3$5C#mU%3;mbq]mȻd!C!6.A7ROIv< / ʅdTSYE6 4^-,.<:W2 0ڠ/H:W!&7yAnVD.:8iQw6EnɚLnG0~ID ZSyެ9m!!X;$HR} q5 +">+TNv'aX[㽚R7tvIWNld]˽rGC9҄6;^x6A sdjgxѷYkRhmI]谫ş';r?ou[?4R$sW U-b&V\<6 c:C4W ۆkm7hDzUa-HLOED>ӯCϘ2'3q$@ǁCduoglDx倬5QOV#1qFǒ2~EE-PuGvv9ҟƖ>Ue%A _:Qbl}V /P=},g ߝC%3G@h'b ;x =7|\ Y-:X|Vnaf=F%l1fP^.%E#R^iR1v~IT| X]ŋKOfcOs qט $O7)+}o}ȿYILP)&i2 vh/Ă h6*񿹮ǂM1'5\)6}p&Zmd/Y;Im PK >/Ly?$tG/%:BGWz>B%)?%69?zIw4sPFx/xҰ2ºMXϟP飐> K+X;A]]T!eÃܤڲt&ț7mtN[tjtw& c{ i(><揫r[Ǚ0FODO2Yn#gC7ߛoSs7+^1tv84DὛϧѹ DeVC=^ cհpvsE>#B:#gPZE{/h$BH$A#H6)}e:4GXѫx5,꥘$6N@Xל=#O'ȤpJ6-$ZΣagm9gIL I25$0M ,t eP&y{2tEj;qq7՟v{v[ ?!BwRT+'vCO497J$t ;wZ/'2P Xoc&=}f;Mm1w0)6K91>bt< |^)pDt߬ q񌮁;6b5ޮqwkN@X=4YreU߉4]EHY~~/&RUt<ɖ=}{8+w'oTvR[ Q#?{}eКy|+$bMPh,")PJ -䎇$7/\?Skze %=$F\)= S*8xѻ Y-FXr.L F8W "8{Z D5pԊIZIw=y+$ tkáoRvz@㯒.LW6.yqu1vyXÎv9NiF|`өId6k۵WF9~DPܚБXV.LNy._1t CWTDr =9OR&{2F^_;#/Bm S:o Ċ<@~6JiJֳ)TLG2ёo?qNt"`o2Ҽq%i'l (擞J0G'ʫCєuY4>bXf|UNa^I:KjNYBab(VP}^ tfik[$&y<_Ћވz-8+twZӅ)`/^$;;tuvq.*f]ᅵ+kL&xNcSfn|!ƒC]1G((a=6pܳf'*ſtI-ӸTLh浜OPy1)0gN\؂2zʽmWn YQ/4IZVV}+{P47iC:e/DW,]geB5PUPlOOy &]UZ"ɤ o~n]b49Q{xQ7 uXoԚܮ+u-As3qF֯}ZP9m" pI g;F_ym&+6AO3^M,(@e/n\?n@Jw M3rh:2eiW=-N#S:<=*;5ϵp93efX`iD oj֝&O5xj,uqH ci$~]a$ qH/G2fBLNhS04iJCV1|'tgJle,pB9g$'oᓩOsxbI*c+Ev )47COS1 ,9'FH`%\Aņ6eTS&ۅc!0?\VxkFr?jAkc>v,Bxַ <物TtO˱=-{ !zР-bLD.+} vT~ $HbUfBLj|W$;q!ճ9lt>{r6\0.12dfO_VrXO'is^>Sr3B [[P ;[ށWȫRhz_n"3JIW Ufvoqi~e;|39ka'Jlz5I`,= &Cd]5EY6b*jި#+図Iy*J=Zu5>O<_Q&֝d|AqGܝq*HV!h~c<?CšV`] 5%*Ivjm>XG"4Aޞ^'@0eh5[1Bz4vżهXٝcg~ɛؑ]C9ou:r0 .cʛvhϫ  p6II` Rً#dwIGsO0hrDjeuoFB>q{Zᕥ W=kPтi }76ssͤ{B2unga }i| sJ.@99JMJe.2tTC@( 2]Njn:ش(.ekdk#sp ?]L@歅!7q nβ$hф4E^Jսfpۧ*m2dqIMN'ZÏY~Ȳm=a{f;"}r҅{/ \`ul)7 JЕҿm&!?iqsU|4 z:#n^M 0gsl%b?胧jw]+ȁ0 4@﷭Gz]* JMHG׉Ncfkeϑ;9]zyAt dJzZԬ@[=3\QQ #wΉ{$31ͤ7c>?m9Z'L'o]jtۘKkեʍ+jU~on"fA&pݿ(lh6:)7J k+:Z/j@[ gǚ}]Jx$c鄋k8M(BTjlRHq/{̞H~ak/s'4qiRP{=d6D3Fi#5'|~ y ySn ՟P6hZfifh&#%k;HfG%w%}!I:ڭ#$9f: f/T&ldV\m?>R!QW,yc_0~i8UYwc,p ^g7M{,5j_&}~X$M|>^;N lE;V!ptDd"P ($2)ғg+!i(Fجr 2eDM5ϵ9߹דݾs-{ F&#mYawU<Ӄ7Œt-[~Ε2u`Bڭ0 tk0'G적[a*r`q2Mr(I:% M4g=dmĉGȜ_Ċ>o ٔpՇd]^y$%뤁297AkLq<3ɹ嵝H -Z9vcɇ # +/0vu C,뻽n\98!sW2yRԱntQSY>QDV~kpJmD +V΍}?М-*Jn ײzoTw_J96bD9/T+7A܈ Փ^EP}xͪL@!0 p[\vȄB>f)Ǫddh#2cy.!,E:cy 7S<5# H xbBJþ*ZiB=)칳#կvoīSd&N{Z·Dſm'^q4^~K$bej8/<c(0gAd7RHp24ԟw[ u բlW3rܬhOTbH ͼֱ'KC'zV >dhGVk2HY˺$HCțGtc# 9o85N&gv. Qa@˟k"ON eˑ79 K9dK1S*W@E1`4A&&9,F_O[݀byE/@X]TX|bPl2z?@ Tqx:{͛]Ȗ7ָ1A4#W%9Nզ/; $ gK*؍P@#vg%kpen$#Q/ra̔GӊNGFalH\,.ż~ȼ{H53mlŔdȹϓ T pM w̟y5," c7+Q۩?4iڄw48JBH:']u/'Sޗ挮WSYЧy;$xB@%M<}tg\H^2v*ek^e_AM$\ eG$Gy*>Qoi,&O#xҝv/F]B+H$Hjmw|^&/nE,2'_i6;(C .!J8~X&w2"@E"vN:Ka5 ʛ"(.*g%LXlbkP=g5#YV[T.S8wR 'vf36'N(a3O(]CXxɥ9!f>-%l@ßЎ]7'8*=ܽY?&۰:<gVA7yPW R_M*1 }\XHsx)8ajwqZVڦtCx瓓WfSDB]B}.،If-vt6$ή߹6Klg@u^% r´ٯ#+QO#qo)"7S7+l 4sg[$ (u¬ DQMɬOҩ?n %x/ҵ _T0[iǸN&E΃'tj.ԃ2:2JV4%4;)U]:[1o!ve]8fXA=J$Һ Zu4Ǝ9(СQ}VxƷvjd.s3lƊ*S=oM>WlUWg(Mb}duzBS@O*u:ȣ\X3d)PhA_Դ 9&U:M;odo }1{4SHj 7hzo-#kh9X 3lZ7׀'|3Gԝ;&7ڸ8/Oâ`ϋ l ʳnL,B͑Z}*tR/G+EIOF?JU炞u@dȊImSBahѐ|2!n6:z yf1MQK۞#iG8Ox/'1CWL; IYUpk,-a%|Spd5`=R T$* xmid/>/TP_q`׷'hoޒ,^gVVɿ6P51uOLŒCю;cy#׻9lpP.2?ߔS/9<P7Ļ'R9b BEϋ X^u;lWQ'vܞwn<47/Y(ܖtEx3^e,9`|)~gQ:gV̳?=>8sۭ0Ըq;ۑwE=uh"JPɡj?RK6#h(H+5kԟicHUnI XN20J.Aİ,0@e ϧ*'9N IJO-^xPwO;iK Xi<6LjV V\O=20Gohʹd'N2z6shv=VIIf?3YC'\|O#Ifn6 >yRpXY\4,gEt) *J<_p Mۣh;ps͕\!]NܳBgy̧)*:_EjO|ᷰ'0i|Խ s ( 0?b!t/At烬".ĵO/(;ll-^Egi+םخZ(5D `i5{;ocd伓M${D{, ,5M>˂aώdy$CY(XCg N}-‰˓O8!I~,/?/M`"CƍB+K ^OR(yv;PK8o@ li(5iAye^tS^z^@mY99 >Y+p[ok|(9qV)nCx_Γ,Z4ߘ$o/RF3E9:F\:]9モY%@ LgRm+##X[,k\'!w?`XȾj@t[ʎWn棞` /rt6MŲ -|XzUI=3a'GW0f"]:4C+ 0=dd-RYzAR~]|dL:給n\4u=n.=kg*R▎+E0;B+?Zphpjmm9שe ?YabJ8(}qKXW *)1ڂ¿Ÿk)lf}~e;(}rޙRNNvy*L\hj%]| ҶS/Ǝ#sn}/h>Z1Rޤ̾(,Q;&>(>c'U .y6B /< ~ZƙC^L:Er˒vybt0>Vk0\u85j\%]wr*AA c^v+յ+aT>\gP'#*VjG(5MK,rql)&ݑQu(q_NRlzl<=r(fxozJu e:~  +2A֩@r;maNs3m coq,ҬM\otZXŮ˼<ZJC/^.+sU+W >ǡ8!QȽg)n؄hω70u>|t;"n.]'g4a'y;9{9o9v0XQĬ*)=x^X$ÜOԦ^C7<E)S„"s0T$i$0~2"1ө͓oy܅D_:2ىOo20~wms. my۽$]Tdjrϊu~Tإ/ 87Sd|eV187pYjDo'qo΅n׶Ʉtx@fe$E@X}yw*&)z؛hDnWk éucq.^ZAGA~r&}~O ƽP?&Ϸwz>N>ICq?J֓0 X"N tǜu$"ߧPy.=Mt\NPZ0gES~;)KOwYGQvI*x`zv~)@=եƼJ{#R0wnR#/IC]c Y-IZr.7&}$TרQ'8-Y6]34= 7W-x=8VBrfOoy)_>3@2Μu43#+ <ž+9oU $o:{u$1_$]<1yXBx(H8ޑ˔^5+)HSZ7W)Źgv< R1L ) ! % Gs. _.)r}ylE(Z9缞Bj*VPL*N7褌qi&%Tfhn2%BʊΕ`_优|*PTUA'@+ܰc&Fg蛇j@{|I' @@C`ytݤH(yOiͳ%D-ؤM/3󺉄JJ 'edv.$=>ԏ# QЗלSЦX{a%i2I^M'*Iqѡye&PM :o#7y:~D}t>m='qJ)q"Q(.6ԓzԼх'M^X5kw 5҆now_1H} kEC :H97Pt^EeY'[WDl4PPB!:qd_E QoU 6J{4ƱhZV ̉y>ˎٹ9$8uFZz>B V|:Ypg&kUR y|WєFsR[ [*֋/X 1$w 1k\?t sB8×5wGrFxem'Yu@RFg9%&Tܚ9qfE(d'r,c8ӽJqQu"BPT>,ЉL엃aRJLwj~B7u;^KZ+;r4~BYϻ> Zم6򝞼{@h6g_L}Bz}ЋQ ѣzjiZ~X]HIa>wo.p748bZoh-ji9 ֛^On-a 9u*IF% F>vg Ϧv^݉IfZOq+Z!̆tx*<֡ e6]@^n "C34YsÀ؄pKv-1V=y4cK \D9Y?)A 87d)3Ys9o:ze>!py+q6:_xv"/B)Ylj$Hg6Gh=xzDHQy64uȬ5Hw7+y!Sc% +BWMp>WХNNcŦmMHXN:qѦde6dOJ[n WXֻaA>fh%x" Pᶗtf냊B9xapu"&_.P(K?@ T\vLr9ZS!9,tseXX39Y7'1 ͻ 4*5\>]V[$SEO;wG!c62&wHwUZzvs1HxPc0.Pg ]KBk?_+]CWo ]$x: $B4ID =ܟtGrP3?1ȹX/̄9*]{~Fu1hڏ{}|S+c1A?o"MmR/ 쓜|6NV4D%Q9b'D3Wv/U/?6tt,FMWŝ:I:?t ˹ue.dn;Ne@Jټ(L 兔t,)Rm2羛֟J2RJ_ _Yg[p qyhi+M[v~ob} 5E&m`6{tՇ?F֏B Qm4)zv߀o\V<5֓YSfUuחꎗK&Jc_ 7(9+)A&-Bߺȱ,k;C R)/vYY4,'C蛷RqebS XX' [%û yv"Dah)M|PLoacj}] -!}x<iWD1XcUXU^&IS0*xD:?i[VX I%=d-F d wKC*,`;t: t#YKySD-@?oeV'y$Md4j >Adm=>P^[II6#QŶ9V "FŚYXY5K+Ճ|PJ_@ib%@dER1( /daN2\u65gjJfDj|YjNmiy0hؙNc'# PҳtGqK+`s{Չ4ϫvwSG^4#OBo)F)1h>i~56lT>': s%e>wr>'x3AI_Q<"v+p,Do)z~!t%Pp.4f:AYeѲYyQ"? ۜLRޖ$&^Gu>'ݐ'jQUY,DEGBFB, ]u={yrzF/g}.@>\(I/F!,0Oua?n`:ȁVrяXQL>0c7l ?9Lb%=Gߠ߯Ǎ%o+tהKt? ;I.IlHov¯b[&sCw.:u/L3[f+T6xDuG"%hJi#IQ/{' ^ׯ놝𺑛QYRҷ11{j`#+w)=/3 |g4P .s);s.#2 K긊W7(DOZ8\+PH2JYYlH*em=ܓyG8pc磓xa}mKSFh1C"Fz<)?GYKgu{o|)RsK})Q\q}܈9Og~|hx|;LTL1:k9$yaFi4GhFOq5z7SI8l;]VŇ 'qwWV|S f<ҲO3AАR1<(iJ{ x6j}hŖcե "o:f8IPwu}OG w:,1f{ߡ(0c09thG\|@#z2۵IDz֣d[ yEQ kA[ꎥóO R1ѳ[N~jS ~&6@^chsE9}E`MTvU0- *R=|>LoXh:@M;eb9puIf;M+ A\g/n薼гo 'Mlz^p6%t' Oꉡ)QT Jw݋djYQmG}PB9~c5CtRFzpN F/4od@-u1+sFOy[a_7%X-ri˾.1;X`~t/o8օ?{av@dq;diHvq6#Zz25*M]5ӽsipÈ+V8MjCxXKY%&0}NI5cuW⼓Y|0TQVLӆZ[r?d{>!x km[i;2בק#:mtɔ:*7U:>qA 0m绔и^/Z!dF)T MkzY)0)o y֫ _w`H|;rcCJdԔ~7 MLMDT6}ַmN޶82/?U&17u˜}`}5|99-k=( ~lS:u,+0°?6oUfv78,Wd/"8Avݗ{,;W]zex@oT] +o`ѱRtl =YE߲]qaX;FIq3793=ʭg K2*|16E)bCd҄@sOoܶ2O[RV[[)N`ҳ[yvωb*P|xk['[g5![/-=&Ks5E]SnrJ9$1Hr3~u*Rv:rcZRF=7znb0r"*I+nt: wWM^ɒ:Ou6F49>|0RQH %rVy ”311\*]"]8#^몄  *O2G5ڲ(V3 EyW:q+.ytn no'V7D8e\1M:PisyPlVeJ73k?k_L<08 ힻ MxW@취Le: #((b()eeRqshBQ t9DnEf2i*5sgZAjŗPYONP4(o^jBG$v|e`&(h]iMqzt[ENb ־XyZO]emBJ35-*~QY*/۟yͦd&?uJ=ky'Re)PM8G{^:!SO5c4.a?(i_ÿ-8T89>%vVBljӀ;x[[_)vm}ft[|_lPfy#^]}°;4~z)G7:M!X'ק{bP7 ɰ(\'7~$LPx@|Jt-j?u2!siƍ`-_ncDM*mA=j6d K | KlOEtX&^owAQ D;/^\{\YRa'-~ %\~A|px;*R'=' ӽ Qa1f"c;PHaIv=2㝦Rotz4=Z|(vy&9אoH0 7Oș0@Mq*['+AáGRVy5[BTJOA o*@e9* jTܕT7Z$Hȹ OTћD/2gddJF)uϝbDH_M]l HSG 4_΁+)sD𢢉HS">_dC >7W%h5zѧJSM ׉cz?PƆ[M̕QaK^CK:;= Zz:ͩk7kҼbACݰQ\5ir,s>WLhOfDRFiaekR(t8H=bӎՃʮrjy.e Ēw0в~6W@LE lB!]a3gH+az%Rs@ {jp6$MPY}N$MH6>kjtoO j0ց* Q Ɖ:liөũk nΒIAX$b qvFN^OPt{Vp9pTuԕ⸤BX5d]OFh7huowV/dS ͦb%vtz*ێ]n--0 $@c̽Y娲%:a/ B͎'VI\}Lrz,G)aG!* wIJWzM XL M'+ $ ]XKä )+ȯ3 21VVmQW*])U~+ݴxp+Ti iGnY5l{\WK9JM !ZS{VQR-J*1SJ7,*h'zڄg4<[mEyYC Rr{~S7 ]S~:1Eo u8kHZth%.NC$9FDӞcW4gէiP q[ 'o:]Exu[(=XAX-# 9n2n*>8 aT* K" , 9wfxJ V4rӏTAqWy&wK>mB@wnr~DzkoJ/`݅}ɷ閙VK Sd:!lpuPP֣ L}?]L}8}gWkꎕȸD1IJ0۱rz:^S / }|[bE V¯_ 'Xف /:)ElRv3JX&UJ`wCh} AA#3p~fN9'Ws]g@z6'ɲR.sjr0_WN#XY/XLNVu}s⬛MxdDn7XVN4p>P)mGTDO#:]R~QҲP>Q8 8<רM.}rOC  qڟ1[K.zNJbҗӹSAtNyA`QK9-%zqOYrR2e-_n/TI VYYmvqNy P'.;*J0 $5m=7 rL 3VVӡ:nsO7.uV &5m-?i 赿@-#!@A$Fy-<$#t;ԍ ]>ħUwۄ b@t:wޗxѴ2u زҔcktnO ]̚0cn7t<5Hu zt;U^Tϟ5W\k凖VUi~5AKe,)Pw^{ڙN.o hv@Ȁ&q:#4pxbǦ,a|K5^h:<[pxMVK wyIf#hCH=75ǁrbPp{xz?lf|8G^賷jAX~8 5q*AO}%T͈.D9R?hy -` E2!EIl+ n;n4?^1QUg飮9?\˵emsEJ&47=9m H`=y#Sq0KFMZ<{&Ԝų ︵4{Fl4Qޯ4=B X&{ *l֦ӛ(EyWʬvV%שӁx&@uj9%->Uoj548AJ6m+m5m*(^žϵvqgo+9L*jpƫ u|/Hv m>fEo-|~!?gPyK =J<' 9ĈRkI/qS{q^v>Iץ|n~x׼0fwKߢ+J^^,۳,NT,b.zb:ZuWl~8yDk9GݛUgWi;ApeݦP4~W[dUƖo d"oI2':;d nb^NRQFfP3.B qTJhuwwO:h16l`F L~|cR}D%oIs1eYV*38!& vir\EmIx1T=` ɵBed '+T0vhLe=e5oS_󛌭5xYtǮÔb^n.mTJm} 7d弘R Jy'[-\X>'n3HNk!&0/@3U^ 2;|hiH=(ƔJ 008#7c_彿y81>dVu1!*ox<3fϖj!ehGB cSt1L.:(CO;Z\K Rfj}T-!k7tjJ?ِ6U?G8=Jw(L2#K;~@R0ʿBo4vL2TGRT[||~ s `mxϧM~6%/hwӳ~ʉ.%ԟ > =VLq3az$lxF)z~kN.cu2Mu$Az-%#"J"uK{2zv 88ȴqu@RXxgiAZT6a)p 3yn/(շBRdpäY߾7u_] VS1/<]EXd̯rgC}CvЦÙyYt&im#%ZMu_tĈcktr ,=>T̫Rqbn=pPBqw+Mv\8.tz=A@ݛ#“[ΞvpǞ`ĉy1v.FP9a4 ߻m=:_sۊyB'H Rdi3p"鳖=M5[Ѭ1lBhz?B3Gi<2] ~.'/>ЁҤJ(KoopS< &Yy`aae4Q sFh2T5h_v kt~&>Qt!>HT;8kV&9sJGYyb4!;OqCÄR@ RֳrxikɋL2U'6Cb v߸meV5΅F S*t@f7m*fwBMdX}9ׁbk{o)9zQ.oizYTw68u%tW0P1QU>/5]s_!QH)|'QBsq G[sjLrJpB,m/+ϴ]yG[N֓=)Ku.HٕCYo=8?8]g%JE|*zQ@YLxy,1g:Y|IоmJ?fG6gkC9߰VޓG_-_CI),'oRZdR-j[4f8Tn">A޻#dGHTkYWQn5{d@,ޚQWe]p8q,+xh17 {WYZහU42Kw 8^LB:~ n70e}ߠsvGk p]!wzî)s5󜵝D ;v|BlXK֠.sd?{G]sJ%i)]ֺY.PW !p(]аޜ] Rx{ &z˫Tg@YKmKIkgԃJ@FA^ lcJ $D1-ѱ]2R3k*rDr-s$E& 젽d vj>ЋڃLCyWE/g]mp>6%#ck:y %h/l@n[>`{Z$:U1ӼVG,V}YNFM'/!,5C4ca 018:tw8%HY_j֒Q=''o=-s>@JEf?biUp]DI_IimN!ٮ; y8[6JzP@bsdWZ`6]d.b4hKSmK;l>^=V$+;kŴv+JmO4GT+.Oby5^Lƾ +E-Vz`C5dgID@byᕶz9+5,].Xt2U|DՎV$v5B!##)d^(]Qj'b0Gji>A9)b6;Kn6Ϋ~x;eZ{:2% 0Q_7<>qCdkg3ݷ< ͢2-i1g"[i l[OmvԻaOK;̋nM>81eg'):쑦ܲ5=P {:1|"sɾ;'3iYcLˤ'8{uP {Q$M &%Ľ3cLeg  {Zv>- c*|w)`)쟄zH¨yl==r^Cxyi=f#y;|ѝ~XZNQF7G+(cf(M;`d2X&O4aS_0R{n<׽zݥP1d@!kJaq i &|y]̆*4C2Co(e`*üi}2/)s2ח9fkzI6L;uWjp8KT œ9׉eCcYQzb^xzVFvb,Vc>" _B#/bcU \^<X:ɗn>hF$ 7hbYN)nZ]Th 2x%;}MQRvzw!]7oյŹoEcʛt#fQn}Αif{(H2G!6gAR:yR+|pnՉUw#wB'^Qr6^o8O0PVUh(lqKȄG?$CC>-zd;4) [s=3.lnL12)\:S {>"gS|E -IZn|?Tq7}=Y$5~ecb.s5 a=fawQtnzÙ@o⽍RnO&R(iEfZпX&#@ Z:H#n:uOUbqPlu/m,UvE7ޘX tT (@܁Nd(:e(bn@n\2#!eehiЧv֗ya@ӫ٣Eı5,-iơJ.SϪuʌmb*>qWq8 lBS\ҩr>[ wO H%hB?[u0:U}&Z(&lY+µ׌2uiQ}kX C-=aP7q;?dGi1L|<;O0K >G+Ve4wv0JzwZH̞sw)x,=+d.!S_#&[&l36MGoo'[""/x*Xr6ZN!=WHWc}dO=@~B׳rKBZh:'8(-j!ghLcq9de{m:,^E:=(u YS~}SͥuE_vߙr 8!0af/l<:Q~2dV_W_ !c4E JT! JW+bcti萘2@V=s?'-#ΉR%NNCeZ6g>6WNجFϞHϮLU͎2vr[TD#qk*i1W=IQ)*3 XGF~ICMF:tʦȞ^qQ=i-y&Lԣv>M: `qKL gRq^9Y[Mh?tlv6$<L % x߹C-W3+2^+U) ѯWsgikvc@F x8 ֙a8EI+Tu6* eTOZS$?yQ4="dʧg ?=|tu@>fh3ew{P0V 7{Aoy#~ :|L~5{)YI,;^Ge_@G@v66&@F#mr^yo#BgFHzd'1-46nYs;[%:c< T1Wy+lzc|&Q I}Ps" >idB +y4%\`FRY1t7Afu 6R[A|2Σ#q {BV^>O\ځcR-VcHe {\…x;q$#wY!7Ut=/ɷPlY:J1H-YXyn)+WN[i4@MZ7EWאEĥ.XGi TYpUV[Q K푟 5GRԿVng*W)h'G~]hiz{ \8"I1*fT;ZEl8@)=D*qI?Mo!C΂)zzI%elk@॰% @ea52*q.t'Hn@޴N`nlyE(i;A{qT#<\0qBUS?ѭX#\4IN]ZDCKD$ @|fK_m|-ӻHb="骗Z\>XѤz65?k>; :#is%QBlt\z4=i`~,|o+Y\)Q|x$4MF3 lE"*S5<*oڍ圉Gf wdR`"J At-na$78r@3:-ih4H刮jbZ=Mө}Ӡg& W9o6R]Gi!ۨX(Pgv[tmSQ 763Tg1ۨa9Q^< O <7kgܝdB>-ޡmi$> SnyO A9}K=oqxqȩ݇ve$#ڳ:D'';C޿Y֩BUY'H޷p`< :yY`YgA>'j@K{$6t)g1tytx9AaƀM#3?|d)mΈ& >qX]2;.!uBjZ9#; i~`o7t48\~|ԝ9"8>Q46:78 =秶w*zCV%4C vo4r͙qi/t嵂A #\ugdS&; =(ƀaFJŹl2 x}hfnV~ԥz2 o%Ou^!,&񊳨\X-Gڣ^(&KCf؁ ]XO޸@gUhX`fVny6n<ؾsO^#I1r*1;P_RD]F4' hX% %DT5,Qսo yDoBu#NNSJtx`A/Tx(]0/6NhCOXi>Mp rKE9/exM"r9B)uoyrtF<5ܫ\!sn$\#OC^l?bzE T{G@_?cFnU73o^/PVWNV O0R5;HOمS)&zT|uX &6_釗%pV3j9Ks՞wJNJ^cLJ1ܰ`83x.{"Z݋oF'(H>>V?vc;agJ1bKQ6 &4?0hX*[#Yz8fUduHoY/h@ݯ/Ů:WhӔn.M﮸5wuz1tԷ-ʕ>IYQ uP=w6oA>37HҹѻK DV\>TiQO# N2NzKN:%5}ba 7^i|e4K9c=3QAI6Zm ZLȠ`xj2dÖB:3Q"si~9drZsfyv9r|{=a#sJfiс\;q>,j:T""̫5A.5o֚>6ZAhL?I\#+Z5~]<q}У\>oWFj:?HgGG%Uu)^}g KMAFTbyX+aν}{?#njZb-V{DwM Ɔ/s:&Z V~PդD1OVǏY20&<0隸TOIK\9:|V\9yy" TvNWQ4.E'` էm2x wFgu] u-Sӭ.N"Q+O]/G)b|a=z}o DC@NjvMF W;c4@O&Ӗ~(w&#KwOXR6@޲>[4Ùeax7mˈbUM~1'b/ ŋ i#&7wdQE[]4w>x]GACcjbQ#ng^yJHi"q`s(e%bt[IB:d<ϧ i况+%a֭).Zr>wR|_媟~h@W-]Jhg]Z_(SCa2;90lfb07]:2X|u TE>+oKn|u9WA4yZ&ڻ](!ÿ>??F;=%4ISO-``$pW*\Zbվ=Ca54`9R#MZ×YCg|jhy=<9Og1o;本hƴۆ]Gd4e+Eȑ5e36@rqQ:ї!d;,rյY%VڣtL_>M4WA4%%%z/&-HSxЀL<dGn 5 )8cS==,j3&WH!#&Bp[uBl'"ߐμMj2?pp,Am XO'%=(i{hN mG4ˇ KMSl 81v6I[ }/8Xŀ(XR<4I@h#Gn<5xIM&hd\'81yI =ǖvRi׼PXp(˔ 2++|Ε:9K闩d_gRD7X*ٿ1WudXaNҴ&jK0@ V{_=906ҦL7-趼*gn$~;U?QA~LaZF)yRT]"m,sǺb )Yw[\=fwk9mMg*rTJ厡/?:Tw9F{X+gYWXۙD7p' pG-TRWEaD?p,z ӹ+Z#iùPN=P≼nEÀf&Eknz&܋P)AɞFȥKO+uAt iCe1q:M ,aNfrZ>Ӂ ?pb##1?O4&?:+g2@ PZqߨAU Z)ATw-g`}g&R0w3 Qe,[~^M֩YSqKCPR-ё6 %U󾴂Zȡ(wh⽋f(T,IHrǕ+yEq'v8yL2P:+S=fny$z$ė^\8wqIGaR;MU-("_ `ZbF7=gUct_XqZ;lp-B7U:#k'gm\ +L@= jԠf%)fg!Lj*b!j'=6GؘhT^$eA4$_ǖ!l}$8{^RHPp:485y$$8FKI呺-ZhbաY@AovS>[Y5ѭŐ>%Jm?MInߍ \kE!ҙ7;50[9hVfK=oԜWjw"}7Zsca+=^wd:8PTcQg;nOFwy:%* 9ΕJCg=04z4l(>r H]F$ 5˅={%ɜáh1/fk٧2[C:3x>>vYKY9mmJw OI +j-{.(4o~Jž*wӲ2JvέT-RWGN]YQFj9r趴e_&ڭ̺`%𢮇7UtWYMuFBxu]Rb',h8. tc(8! DjȁZ>:+m}_oL^WM;;M^83b9+İa5b<5qrdOB5ITâWɔ"]>/C.#z*y3 n.NnCtv>3, |y\Kp'W"-ӹoHvg[9bdҐɿk{mp~.}Ծ2?{O#٫08Z.} X>|eg- K?BQu*KS ej>48]?Ad]nqgm떆 Oд퀦s<5}7]ͣGÐ6ْjs`,=2@52B/TH3TݙE} d ,ϵZ@9 [<%?v}:mׇ;b!q@E{ppju7EG};O%uKp 3&%RN9߲\G(6%a2 ׻kJ:k!F{HeSfK4Z-Y7L j='H),a'og7KloE7|˹KkT iWi6gGYHj*IM2r-ko`5[/;aBjȥW Ϊg<=.;cq 7r8|`N\?tOV {Gr3'+Kadݵj%G^څBLk#Ndh)2qIa]{e z}^JRϘu$'#)~ʫi9=c輲k8??HPN+;C@?W`d8ɞ7@&,Ļtr2CUheDZ4ϴ[)2} 3F $6?U?6fV:i~^H zpi,~?;eϼJT.?gSs>Ԅ?/NGk%n'\U&bӈQxKZj;};T޶3"N̽/Aǜa:0ɵ_DYc{~t_!h w̨#}X`_Qߐyy]u6}56MÁojn0ַ:[)00؟ʱ(rk xi#I찮~xWErf64oqC"5,>ux$rI$0GwoM9 rwv7ؕG[uIAg INj澈:%sٰBN6ѤwݟZ4ފ;r5SZ3KP'QNn%QF[8.^g_5o:<\N;ޡM< 9pMъK L!V~,׿0; uk:tnN4ӑlyWCp1yI *l iKe-ywuSk ʺ"'^~O2\3Oo xP+ƀx}w)x.^ݼn" LF< 5A>Wg7}o(/H 68 *'ޱRZxm8O WklRH  hqčΒs¤4K ុzXhd3Z[ebg /" -x_92*@ŋ0ѕfz;a E)A;Ҋ'>:.'yb6nuӪ^8#dǺ.qVL5t%gYjX%?nV=7CO9w{ aN7UV0̽tX-~N$ Km*D>}<ߨKPXRN-B4QvmR-e@+):KO/6sl>gB gs++0o vLmjIKDsN%5SzdF&Ob.Nv_,eil*`֞!M)/5Fvi50n2eßqadV2@!wkP5Mf[(I 5yv&Rag"Y>)}C:`]aK(kOdDd[B9zLoZC8?QG*c@װM1쪍]ܓfw&$i:;^s@z+rvj 8MZAH$j# y'!wa(v}Z{:Y:QXuU̶L~kSm]j5;21y8ILI uJ@%xG@%@NH PE|^IWK}6f:Z^ %Y9͌/hM7</駩20SRԵ FB+XMJӉFQ#N[&a bRg>z,H3g}+xC[`90F6)E+{3h#{M)AZ#MX:Ln&A O-KuA:D uVK͝eXVыw$\}W6K˲Tޱ\3nE;qr=dz:E @r4δMGJQšLaL}`2MΧ*+0r?) A-۱RRt?20GJ 舑;W |ߡa ꑟ+X"Ww|13*qenⳙuk)Ѓm$ED6oƛ>7q6S5j+VFu,V r0(ж2Ix 7ouD9 ʏ,ԗh Q>55vc[# ݝL,ے&;`ŻRPy{goS$'wZe*_лUb\SkOcXkRm77Z3A})TB koVZh^R9븿9~ ӓ7o @]hkTKV^:鷦թ1~(Jro҄L-c3wx[48R*d\+&( /եիmI<Hz{5rO;bbrrǬbYu31KsqKtBy{zZ0%5rh=Xڥ{hMo " S4HxJ)Z0{ΫMyec3 %Tra mX)XfOCrnN'{v.;|󷟬b bCҳUJ 6c0Su9 ,zi;(UݸVuCpbArt{"U&"\>/ j{% (dp[0ĘB84b:yLVE06Ʋ.H_ iSz^딠0qizNx)fs`b(yFg՜EUF+|%5F M.bHyK^=5bϱ?Xa`??S(w\5?/- P%~d;c7RCo$oek9TLQBvQWpPƛHhOwzLg)k9',G+gi:[*$WBc|eZyɣdFdT4=/ȸ=aw`w19O?jXOHG.7F0 ȱqGu=ypqu3hm9]roYd.$NJKflwL||`QŎlaã惽+Fbl ʢ+!ucdRh/2oXVƪl߽Q@wN ioӲF*VeD.|n9oQMڧ ^_>zAMςfQׅe+#a- $M>^jB4f+O߉I}hklOӧO-M}$'[t>dc0Gof˺Hb-`4=&Pem>oʏ)$bW'8ԷcC4eH0pGSnxȡ1v$!M PvR#9Q[`#@y zr&x3@|}94-q|\GX͈&eѼLZ 4XYᆶ4 EbDtQ{2y-qd:J-7 wXdRxZ%Ye[gGp' U# x[P[O`愹ef"{EwP*= `RKAu5c 0HD벣tw/C]3Y8wzr4hYjx͉(|pҞVi"[ͬ,pFM^cm[}0Luxmib("r'8'۰:]O,>rw斷<ZSכ$X>{`?UUoC`Sj'!lدXby T{裀-I/$g(9S~hhv>1 /c@2IA)uc{)4ݸе[Y!&lw*C:KZROZF4A#v@*B GVf1X5GyNxh>O (a뉺ft?/T8HmxXH>={qS[~c=?,sN9=QHd ok%u9|Qknbs-y~$H`KlT2J(ꦺh3&Oqg˕{IocfXۄȊ{Egѵ)+Ÿg#GNV[v{ITt6<ݾp Ar̃+3g2b>xMأU]O4  ~2|J34h6 /<_ ֋3te cvt|њ{'/wܲ*Zs %AԶf'E9z8olĴXR?E\VE돓M{Z| *3/.Zppgį y(y/:_ xͲq%3O# +4{?穀dPZty+"M> 졤?m Y {[>]CӕDs`Ìг)w|Y'h۩ mi\3yTX߼J' v,,?g%K)2?@{)/s\>>}GF %FW>ДM -:z>=o#n{d~L[OB!ԴLW*g֓K1|ZmϢCY ~䐍 iȜlB$ݾM)'8l*HZ#&ZA<޳ ueӳ^1$qzV*Icz~ѾFkUP\)fh^lblgh7C?BAuSIX߻ܪOQWwڽ%!!aLs3Ɇy+zvJPB;ah!kP{I&nN;̩Tt_Y@*Ryj8sRCߌT>J^VJfaL~⍤.hZPpVۓm>{n'x剂i<Np+UFFwK%P7~B6&<^@RT7o e~$JۗȌE}~[O )jɹ$ ~0t H88{ '/S/SCj4~J"0S@2/ŒAJU3iأe}vVIdr~K;&Xk^oweEwC @Ci|DDk`3;W/;jOw㿣,Fؑ|"iR`V'T/@H8\kq9᝹.`ޙy(8\=Ln+-f$=-܏\+/O:resozza4f6ʺi,YmktPgޤ&y̞1OM `V/z{#lS%_wnn=Hr yL{ȃ a>Bo߆lպ(Gg-ԧSO8vCZ; 8PyxPA)q:-rfo^>/?&jJ@f+;NـUZFȵx-DPsXm"#eRIC&+oUןwyJLX8ssK+\;1qA`s?I#.X@n/L2y=e ;#q9?#1z?˂/!Zepċ tW/rm{wJ+ÞJ3 Vj[OVr9WM$.j)F`Ny ||j'+OtC\C ҅>d4'K'؆&Bv;76*0.Wl<ퟜt,+gELLt ކ12˼HKGb> ٱ jdؤӞh#aldN%\2{C'C5wqn+VFbܭga\{>Y|*25*j:I`wὃ-]0-vY4mڥ)KSWJGJQN<ȬX˾fōueQE &\^GC?o)_\)~4[ iG.ZtajUXW#vtuFg޴xu䳰5dgdN;0i`w %&HlEy@TF 8s?cRc gPU-,hŷy6 9FיȞt} :ol凳/GJKM<~pp赤C˲tNy.T-eY⤳72>؊hC򴂞FqtF3VǶ3zGB4b;ڝ=}@-5f\ `4Э?R+4 t auc7;5+&oz2_8%`ژouP*S9IȞ55VeJ wuC%Pwm]>~4VBѶMeڃcSY%OcKN\eUBly +(by8f;Rns3˹NfS@̢ Jfr]k^MG-pݜо὇\s|ztOhxw0+}1'ͧ#˝@/8)T(MDi"ڮS98Bhd@=#։x7FKu5;Pڽ:L,-{č*ճ:F/NJ|˹NxG ;ٕ[u뮏)S@~NǪ@SV+5CfȲ4Bhٱqޑeٺiȓ]N(53Fs8WJȔt{\|${IP"C1 z'buf)7 6b΄?x*@vDQfYFؖ~^0o#p&?4]g/=s1jdW؈L 72(T8/zi7jqz ^-ґ0p6d,/@$B[GG0/@)SFkΆR-? m(Щad/ G:>ĦSTX_:L>6/v%O-u.yr8b"˒u yʬ@43 g]I~'TLW>?r!} M5 B!xIZt"!&X4=GSֹiD7*{lo6bH:yb!牱 qO G0Ñ kgLG=I,KIuQX>7j$(x4}#yfQNYf8W(k650`DO@:"-BQHodL3sܙ[gߜ弳!r},[D|l"M{m|gPXX&N@eHu0+e]jbΤZ="OռKF,Tw *JwX/1)Cц'?R$yt|'wBw4}wyؓ8|61[}¸=v+wi椢\rV^[,F:Cgb୦Yf6N< = 3D ?a[F=WRML=R9:|6\rr>>zSmӂ\/u%5COZ-5H$؇<$9x7Y>la*j慗"P?L6d5rԺYJa|:&ȌZrz;R@[2;U bs;=ߨ<$Ukk,fm(Y Ebrg}_,rg儺YYZ*:@~<$MKd3\ ۍl%Df٤%cQ6r'/HJfQ%.^ZBe_u? J,:jx&rwf,D:f-*[TKPy}mDZf}9%I"xaw>O+)wvp-[K;Kp(+j)sC54mշ.S)]"9P"gb}Bܺ\3zB>{,9u4K9]t(8jnvu&Ŋxl>ž]Ko]k9 ݝv%|qڞ[QŜݡ (Um7t &ێjM`o45RYt bnG:aFf =vE#S_g٭SCEz]1;[0e_#{a>J˪KJ.j{P1RH!خۢxj t4v/qByf rI1eɼ^CxM-g9QBW9p, |L_@@}Hivжěr^V^4mÎKqz}_@̮6 rǛoGC,s>g@HD!]:w+I֛y|0bJl q=$U| {I2ľ]SInHr78 +9- A*nZ$^]%x'sHr띹ρ39 SXA0W}Qy.1`w*dcHp#AΕ5KKf_"=TKG0^OH7M*"MTvi0Rr K1'jɹuz|!PkgŠyc._*r: l p 5}m )wqNz_f[2h8Xn4+w<ێ2ei+_rheDi!Dq28DŽ+oEbH1W){Ttwpf㍵;t˙n"sAx~=Ĭ5$v7&-}]J̜N nZ'7_=3pGK(3#V?Q4Q‡UI~|:)Y?R[c(4`o({߂wuڷXP+,zǝ9Ti I%]˴?iEsgU"쫇p rGp (*4 xu?W%shH$-ŧ-~0*HϞ!̀nV}GP -qn7ƳvcYL #O4ÿ[>P{z2B߻@iZARe<-pe:ASt"&kXGBվSAZu>]ѭuݙHbƀW%d!TaJv tiz2טK}\BEwŚfV}bǝ?sa2>SV>VwDCՐYm++;Αl>o{(b莪1疏=茂f.3x(8զ_rfzuծyዥ/]aHWkiQ3 v6-Gʜ͚_e/Eri fkZ")O ^$vӓӃf>*v]'ˬZno$EEiDZBREF/:]Bu/.-[iw4 @aJ8SB֫/W;dg*bO?R/%]o:n0aqW^^I5gГJpjhIXBZsMRϫ\yjcBFיĆ ,FcG q[4LwyG,H4nvR(-$dޏ`_*zAy-Wc /cT7{X_N&+(Rc@=o??f-DÌ%S-ܲ 8Q)- "̍N_BbFsLqmǹ)Ye)=5s{N@VIu&<=LAkH6.3XMBpsS_*W5: 0 I;N{&-F&wT#pO¡'&bR:AvqX^zLWtLz`);:.gdT̬> LUp|%5'c޼f/A Lz'pȸ V^:BHݕuwI}arTλ~ %L312ZT_=;P=Xǫh, 65gS*uI-Ҫ4dpo$MoXNYy@n֒7+WҚ'g]px*MVHa0Dqƌ쁧3JΒNvT/żE448er\H+f^i`R}"{0 23/g\~UO񘙉ąpn!>@#:AN+SÓDe0RF!kPRËk] ~*~ᘒJPADajUiB# A[^,1-uһ?\;͆sO50}m5bX BpZ?뷹TI~^(]?NS Fo$sB$ZyLbLF\STgpZPxEG3wu?\3\FÔnI6tpci~<R<#;_2qWt,:9-UE<)Qti$FثLS&a* zChaHMkMŐ<<#Oޏ@q "ZYC͇J9xs7xX4@,p0 0- ۳?5Se6BHJ|PB'HB '& #ycs;%1vw'̲}7nq*YEQ1=Hy-W1y~t4l:{7۞N@<h7:a3P ӏl碽kge못_Mr.Sm2 '!=Г KG jiں{b67p}RK5]Ɉ榳(hX{/3 汯Le(7!w8̗wo6V6\#ih# t L:.lV*TE땞ʉ0v0I4`Dmj9k+'Jx2mk`C,_"Fd2ZEoFNJ)GoųV"qۭ&;66U$fK+2|St zǿpR SF3)e5خ?{._a^2"6}TJXJV*UlYa4Zrz7;х64A;: l)S'NLW= WsܹǸ=76c/p*+Ӕ%PcA4>HX,Żx / Mv[ F`Q^m)s-z)ӕ'-+7E%Ȼǭt@F8lgSYFB6ab=3kD纅{-m܎,y[]C|~z0m4_wuOdރ^%+3Bd5 H2(CYj3e-yw킄}X5.4}RDfY`>+1;Wye?hhsNn,uFc|j*g6R"e \ e>JA iU7[Gq/Xi8${_udts֡%J4ZKԂ]@y "~#W^c(|P7&) Q(lD_8?Q)t^CJn$RCu!c-fe -aDā+x 0},$eN1繼wCӾ?hdBF #\Fv<`}GrV':]>Lhӎ>SQ]vaj53pR?/tQM_'ܶ,1ciTrFN MPGi()X=Fpͪ9vc.ͮE2o=b'",)+y!:6WV~ 0:!jґ)K"u; n5b])RָhϭfnˌNS:JmVҗ{ۤsԈ}&g>1ZyBBe(n\5DAV1L׏+M9gMM;ZX"}S/+}"& YF:Vp -t'[2rCnR#dZVjY;7;qpoyEzt}P23:\ݑŹ?ZcWcWnGvd*vFAV~l=.swVc8(!'7p ogV3!WY 8fyWӸ3@߀vp0`=5e1эxYIksg]i3И7Ր7Mߩ4X'B5eCbX}vR8w<ްO8[#}:_VB\kJ -r]*8oQmgռeT8D=:&@U}{SZJBwIW,qf+d'Q\tE'-OF;*ҟjǠ˺\H җ**'n6MRrTB =-dՄ1^.RIbU`t5 IyipQU×1VJ}{) 4Z48MZ% QQ>Բ ,}ָ1)cp6s4iFL+05yyHbgYJ?nKDDyIҕwtXڹN!Z-tGL]|:p=b,/ܠ3ZwиCYSLzz;gBꭞ9QTZ[rp킞LŊG̕4%-׳,T?'MsG08=Dj64 vv眽NJӯ,,}SvGBx1s e%*Y}>^)~<m{M|*F<灸ʼ1WLC:Vז\=[aj++!JGz",_fk%zLB#lCg5A֙4t:1C!`V2w\n.mfJ?9EsBX]|Խ,Ć-8Q:f!/wW޵' ;yW}:XbRՎLb~*սRS\mu򱂇o<,@=e((G e̪5ZfkH1,ˌDu贄픃dWMkq7]q:/ClLv ?޻nHh:njd{IlhܘbxPjw=.t CQiRBO +9 Qx78ޥg$:oq+P#S'I~^=MsltV U=yZlvM7T H̤Eޑ%i!3A448.5"P:3) | )-T\2֣St[Uy-c0CkY)%+d  *y CQI^(Xe`TqSl)9RYfVӞ8ywSg.h;>(%5*GvZSb]i<{OgՍĈhn:raY/XuQB9Rس>OY7tvg1 '+Be%O)Q'|ݳ(@ *L_g\lg C:'Nxh9ѸIaY7;@N7'425 vԶXJPBn r=h!g,!֝%׺ 1&#a?˼C.>M 0*B!(2{l::9 _ a^EQ0] ]3A3h87w '*z4%V=Sv ;B(wZυ* >LotO?{w3w|Kçi7;7K~ʾ|Z{\4mr;/ #iE6UOOy^!8ԪBQuښf 58[iҸ=7 02ϥwdLV eQ(߾zWx\wOq: B81W:5\TVfn-I۰)+Xh\'(axEUʒ]ISGMv q~NϾy w1SFvySWmȭ'l7N_xcPz7 ;ፐF(z*({y},"6 P~@Fsb޺Y']QFwẃȋQҍMLhN Gg,-# 6':Oc_F 6Hdu.6~( Th6EҰawĞl%68#3<CYoEQg ?Y[2۲N&'d0UU:> ?ڙreR2)Ig RdG`(NmҾWDlR0.:۵CjBS?Ndv_/3eBDȋ0]6Bv5*Dc[Lwv̒^U('Y@P!a .FY*+z6<ݧvt_2`&h{)xBEʑNN}!vKeg_42Dktm#Cy8<+%j]Z.ӊIHNgtԋ;x?͇YOKfdx_7Adc:Z (lxtr wX>XcLUNZtH*vTau$&{)I HTϚM1l ܰaĜP֕83RTp͓RiŸRGm&-j&gàP#y6-]nxz)A.&c,ؔ#a-9+;Y|8xPIxK ́!:8-z0$PW#C9bHI Bpp`Xh:~|`="Q9+/g#)K`1޶J*ւ>:Se>UZHp)0g-4oDkߑ)ƻ=Tn*x2Fhz4E*rt'oSBC|96=YI1I:}{Y^<4*QhEmRBYbYFT& cl m &⋬fo/βR #C@ &fYu2$rt4: Htv遧%MW މV-5~5Ǵ%+L0di'6Hg0{W`s)*ȵYP>_(? Canc%uO\g-tb$ P5{b v&˺X*G꟮=' nґMϧWWLÖ=0s>PXU1yTi$iQn.m/Y n6:}])F9u}g=D,wZߧ"L[mOw^{iܸ9\{fZLt9w1)/`-Z;EF~9E$wQ wس[n ͮmʞA\ZT_Oj )ְa8>;OeD{О5>^\dU1!#5oޛ/޿ [;qkGQ̲ ;l |w w7'f="F }8 }{o*s#f~]qh 2 )c4< vE;ea- c%*pQY#CiLk5hFPJd.tCd&$oE,ةJR9ہo9LԤxz^*{L_>h\>`tdHyBa/i>ʬ\;"!3@.%<`Гy)w0e }@ U]Y)wL7`;xB٥ۤ!o0zB豳ED1lİ=k i]ؚML6GTxraCDֹG?X6k"JDpʼ$.hX*1kEO΄^޴hB5>n^pn=vYb")=$mx\%[ AL+;nQ 髁 Q~LܝFÁ-xh",x=8֔uE}:cu6YVM*o'WLv@iyo䎳/4u47|e0E]}!LkT$U/@á5$k#[s~Źa8sn`-z~yr^{>6.zu$b,7B;ܲq;R-z8ٶtK/$|j bgxVx,}^)C8d갘jZ;C8}?ɤ\䲨z*:"{L =XAz?K*C>>ڲNr]]7-$R$Q,MPɨxwRgSuҋΡ v/^T9Y±]b9djY۬KwfYG4f o \z蔇:lyh-3JFΫy#36O5s>d/7PX;hMPHW.0'AuVqB@oO>e]EGPFMF̾'I Btg>#+xr'9ٓ$=98|Q|wg8ll9Ϧ^:T 4 . %]-RUzHeG>CM[fr:m! a >l(\r~9]E)/(#FP5#=2pE$^N-gVy#Oꑢ>Kn,wᲯ+Q=YWY>n2ݬ$A7L0g *= BoИ@5ͭA1(O!+oM byFoiEW0q3`䦎]Afi,m1).2Ǔ2=P> %ΐ5~0#c)YΝ"d__BPH p!rrK (@9}:v+m*㯔E$i3b%R\KfhVSrrGu=}J;X"d!1t p|l\?% ߟ}Ƴ ~`Gg]ً gОUμ$g/+xyA}KjyvAz/ԻW;{PqOAWQV\:zE?Q P^eTJRgGjQ ryuQ2Rg '9RRYQQ=PEoUr}.숄J՘ 5d$bv x:-Ug'H MĮ I(i<3Vb=j~X#\`9wv`TSr> ({Ny| I*XMTQB dPtjzz(:rIڱāwdi(_]+06%||9`5Ekt⨖J0ؐea,smjH: ͼR%)b}DN31ӏy#o+}!%.(VrYFс\;rhJi|{OV@, I SdiẼa0A.Wo8FX,XUW w -hxL50 ]6m,r$]gwow>J HgmW/_hM0aDv8 aXIo>q@a ! WKe6 ɌuפkmPV⅛* /YXwC-wEgC\ig5xM/9iGe^;]Ad xew‘RC;Z;D;*Fx8qw8ٗJ琭i>b]O19(XҔ[ڼQln{j_f1xsTmQ9&w妲^;N_8dg@ݗ荪WR85]CtqN4f׊6^c%+n1c"E]4v(ޙ5FWk΁s׫'< 6N w \`,]y4u^iכ5 ^w.!NWgL9 SR(B͂Υnv'ɐG:~Ѥ]"|ԗyĺGFC1.[K52]N=q2S(r1aFF=a}t򄹧==#A'&祩daA+~t*ܲNK7<2<+FEh2*'W?KJCtIԞCb.$}ItS=R6+n#,oJEǿio02 pڴtϬ`f?%X [Kho@jd`ޑlH{ eǖa> W~嗏8rK'+F#U`ndWv53 JHĉd/4z|Zxu1lsʽjCx9pB@CYl{k;Q CsRØ'!.!H;(djӞz [0E^K`(6.bA丹'Rg-j`0^L^-PO?fEN-d dB#gny>vXYZ}G_;71UNO}ߚYW#o9 i|a\V="P: ܾ%}Г=49缐"OFXIݱl<'nJfElcpy~Hk&'0CGqOCm9kDyy*>%1ό8 {u{[+,8wQ]Uf+iϳ$#Q+<šc~v3dM9#䲍,Y+cU´uik)b}o0- `pB;i"2/NY)Kz"ZܔݷƨMNu[Rw]U1AW.2+p6v,HPE6osmv?9yJfiS1c-E'R$~+Y߾oWd%o~`Udj-@@2cZnJtY Y4C #7̓v0䶾v$3/-&`SNΥ;3 UT4 3uO \O!gqc!gRq8N .O'$ }v|{WP:^ܡ4W*kJ6 ~z6-,5hc~/ԯAv0~爷)~.O~uKv<>2,s5讌%rrN-/#i'Vt)lx pα;#׆8Jwй1XyWH&Pv 1ّ7ԚnՋuS6iQW!:p67y@] 8!',6bn#W?W$~B M-VC.ISe 0D$[g/^g)H>PC-_tihXOh<~9{E׉)Éo#{fʐYҠJ\&(%2z%QTCk+e?W?%e^!J2Uga(k̳T{Nr`uH1z(& ˏ٩Qw4yiF0Y>|=i$1=m& ] Y8!,U=K=7f]LUQK&  5\ʬILKKj xuB.twJT^2Fnu\YJ ˠx2l}Z8w7MӮ+f۟M_0C/ܠ#>or;vX\e!(1bNhXuTb^j8m!=S,e^)تCvH~>{}BOVt`*uG& )?aDzUyp|"ν1k^k,5/ztbh=wd{^Zg'Ry`6 9޾AB.{7tX*\6b!~I4 5M? 5q/{-{-{P!Q66^>} /Of[jcVzMO}LcGh ?5]$ -7\ÎkcC9BMT(Gp7Q{8`#Xܱ#Dv!Nt2?&uhT E*F]M`ӄLV#Nj@] 7)Jpu<5N˕>RT_\ Hj٦X.P"G*@L ݤo$1í~OB2눯T&B@ Y:Aդ,L=Zb1CO Unc6#ϳt< p!d Z+N\fڳ"uCVNqFXS9Rt5!ia"[Uy ,VK刏QjN]˨YM:Yqı7y _|`7{zAYTCOʋĻ]SN伢6e/j BQҞxwa -pRihA5!jov7x#]oyj8߭Ӣ|3tYo-5߮vUG.[d֭G_zܜNR;ЃCHVH2xڋ}»1 cCIhU}ehY/wPa ?0?>~&ڠ?5!F-eIG =7#&XI:ɠ,@7Pl f%ti)[PgHF!x.; FtNwv)jjVV!מ c<XH FSS~w4K,A3LTC՚´b&՟HNW!ӯDb}^wqƉ-+zrziorp#kUKHVBOT' m +VX'`N|Re~26WE]rؽwߌ!aȣ&z++դ)nu)#;KHt.x_ e{?(Vo;ۥtDi⼙bP0W"Hῴt/ؖHIXP&m|63϶QZGōppk*2ut3d7\CSBoQIA[ ֠goKĹS Izk`NOJyr6egjdt3^K>;ui(q-&SBwv6mP$oց^7_(*&-\hҠ(a"&l&Ұ @ UGK'SNcߨ[ڐ=PSi3 XSsy.x_x#u@N(69b)F{wTMpe+d;' s3i|n @]"`3$8DEst"sHϬ:q6qFֳr6!n# jw6?xDڜFi+g=Ty>T0b_Љ8={Eo7Spe0og:!p#YoN7;e:*=ҕ9pb4A;#÷ =>`":>V.Jja-FÀ7L=5\_>M9G2DR8L(pևAjgh ME- [ A4:‘[+&1UW^;g[mk27#XO:>ެ{z<(O(.x.J7>T9vp&Ó3zS6ѣVJQO=:  ylj-jKP8lƽё}LZ\6MȝOķ̱ 1#3 ld'R߁UT=9x ( (yh˿{*@!c}!kBf#]'O嬚@2[|T^h?a+Uw%gƚXAQ%$AU^ͽ2qI)i!dBr[mʽzt0σa0'+bwNF/:.NiU+:osPϟ :qeDA{WfY*51iBX#H/<% 3EOdeZdDPd8uzB[aGOzkPΒqMzA ҹ)̰[?+Jn 67'7~k %neཥ)8DpK#R֞o!Iz-iTԽ2d>Ä9qW*y1:{SݡTooQ[5Zs//4ϚYn1HItc)do:h:`n C"zs_J2 +4RԀ'G[!,K8U ;o]i=eCsK+v[(OfoAq4m`%$irmQZ|zwGC.4`riq+yQGq00w)7x~}`p|{t`4a,:Y0z6]G )4LN xzvG>PLr1V(f%<}5ΪP~CP!od:4_%Lοy|<G~63ac6.zu<s\Et/ [hTG f磐w”kPYͺ>`4%H`#8pX)u7{}J9*#dVAc^l;}.mHIo4hoiRߚmt uY/G utJ>, H~Bh1ݰ;] *L?FѸn! Cfb<ephwYg|@}d׎Y|=٬f>]nǡx śՆZ1p/ cz'œ=K3 ~\_?PFޡb-{~7GShBɛ 2zmA1?Y)/tՀ(s5t3$}nej/wN5ȕP"y^JԔEVغBZbzӡREP-bB/O#hsȔ\8UZjDu>sc~Û~nNlK~ L3KoY/ߩ"a7zUpiOXUq|%ByNxN4& |Ш-3£=Й<ѡyL(;,5>SyăGWOh3ȥ-V vmX Dpw5q;}^ݗʋcJ]vn` 2}5y/,N<]P 4O5OLNYBY!_ֺ|^Mn\&^J)+%_ Lh' zBL97}"3݂JEFaJyay*x[q7 ;w0V|(!2TB}V6OdgM:'na~_ w;֕ 4ǮABy0L'ʸl5VSdylru oh^8q>. ∽Z/ŨfU7MB L豳BX%]F!\VF+Se{a@ \ԦVt Y{,!=}띧F֢$V]=Z˽ꞑ$ R4!UcL0ὑb~ |50"b>w+MAⳝ&M4 ,.]ii"gox%U[սJFQI& p? ŞvwdH%pOv{فoF,h,NvRυ6UٲS}d/%íFzDG#zM̘G8NAOP;Nőt]HbXڃa⮒u'RrVwB&3$'35l O(X/fc X]t}_~@6Q Mg<)UQ<03{"sy/#+I7~&b~O=QghW𩦏! ڊ'^7vel\hMXG[cS6eSZߗr$ lF۲ Y#!w5wYzv.EGV{G '~''l/ʪ\CܨvލXثgLaWgxa^ҩ8 U繤3+Sj)i_Ӊ~7.Fz.44T> HA w\O̔hteG!~t|qKk{9xJaZSqvL()&8…*Ǻlx^= ڏ YMex6zLHrk zl/1!E rCm{ goUUT:gG>5]tiRHaPJ߱MaC2&V|H9N@(Ls>AMEg b!g(y@ @p,`R^`aFGYԏ $hJmz¡lSb98UZ8uUb.nq?snY,KF`?wP !&m[E COU3q:7R(:&s9sfYhΠ. g!\H@YjXS58-L1`6+`~)wX'v}t@y4>vZlj]VxPszdy/sGx|'M|͸* /w &ݥ 3:^6/(Oؓ1߅b>6O?X^kBIBq.F@W<1yFzHe'k*NWTWa; y[u=DOp[7/:;tг7,,(o(6~`)6dV8)ff,|Wus{Bj8a 2~{M~W|^Xwql&R0D` "M?+Eͦ0Ær+U>/;4 4}i =@=n%H)*$\Ta*U[Vu'ډi¾|󹓳=t"QIO{N[Rw$Z<g*$RVz3X*gQ7)ws/H3Q."neLM~w |ЄaPG/Pδp)LeAQ n(NFUV")?݄κlʕ\&g֡/4. & 94?a*0I_n;83p~6ʑjā. %N3 ,VR5 ; "mt-9Mrv]BD5;4u =Y;Cő/eM.vo4OݏBॶZD ~T2FAy&%TF@ 4sNLzGN}o#4m7̻n8eZѠTy \8дhwmJD?mED P8Y (fX-ݣ/ċ)E7NR73/Q*C]\Bed˫1q2guW8!MW1Mӧ8>ht2ag.vP TGSN9 uaz Qk ozl16l=L q7 ؈tVb7]X:UVjQ,Xϥ$Sж=?-h=⭊.^3bnHM״/,>nZ'd[I"cP"e2s42=4ҰԢj6zw/}Mbo?dU&'0j4=ڍX#sʴ3@\(^7PS?ܖꀔjij:rUH81@9[x-u;"騁{V!&d}{~oj2mj{{%`SBoIbz9[Ip`ɓZڄ.͊P/Xbo76(İH>b*+}d-r΋^Y[:x<ͨAIryrHidAj nBaG.ߥKoqӖ7l8ryφ8X7:P&pq%vD'?oDL 6yL^+ȳ:ГHThe5sn6$ T+yyQVаѝMEwvB`L2: Rf:ԏ{N}%[ 3ggWPL.뉯cM[|> DQi~xy;;kA5/e0f)ա w%XxEKc0F":dХ$/3k4}Xx3IE;sĄ< XO+R 뮏:mRH>f+[ubO^m$}a\҆70y[/xk(N/+qqA9q`:jHb}@68頙u'/53o{9-$8f~y%l$ xe 2ő\Ze)zd| R)h*\z; k昉ÖxNGB/mQMCLCC-\|G1k7q7!C#G*n8Q-1 >46Vpc:e̎0Ns@mDlx̍4xJ]{J}Ш~"MZ&|o,&X'8ވ J斈>b,LC"(9[NͺS !хkRI7AΤ/i^4 :?<ϊ..CYwK#M s~Lˮr Bu5m!F÷OڽkZc 7yg_#Q/eqFxsOY*f! p(憶b1.K9@9k"=Ӑvq~Nh}%}|UHJbF|:(>ѻostq>SO6oMh@9mmrywq>Q)N!nΒު˞|^@{qH/{q؝HzkןO7(|""2ɅT4FOp4|˨uGoS3/̜nMtVRj9u_x]=fn=XO\BM\ZqӐC8;w(VE[$/B Zf+ QS+aVG5qb^ճ(?fMd mqf_~ }n&eu_Hӹl3Mzd$!sZ[ AJiNF8jG*w,"[ڎpϬӮBZn oc]IV] &zzCY/+'-@ :Xv=~!LV0qby;;Fg5 7:I{9he˼dȏ E3CIKnm u2n=]OܳYf3[g~C~SwԐʅ1^u5 :wZL6M3;#SuP(2aI{>A<< MZAz? &ҘgJ::Ama)^Jl?^}&sbo/MDUb8RׇӺGtK'uu h^(}0ߋ"Epؽw6.EfwX!+(z,E|^y)>( mĥ#J#,HlHݚ@ĩ'%% h E6Yo^ iGg+>:M:D;J 6xʗ#FB EHjRYA9:BG*[VC:`+׉C(bWY"gw*UOjme94&9M(jo8XnV)uYsq ~K9aC9#]d'gam:8x p=ȫ1 G Ж%应R0ٮjgOV -S|vU!y|u/m'7M}wnUGQT %sfzfu2t+AYҿAm8+!;Fd^o&4Sge_xxrvJCcdp}oDVGq䈖Kִ8K;cg-;M6 FґTht'H5veK2"dZ2v4ɷm+yb"\XwҼk {dUk*Y%f#':X,*X Vbx*BWq92w^w[c[8r4);67?'fXy_[^6OYW,Ӛ$7'!/ jJ)?]{n8BMY.Q8呾`j%WD #L!=˜^;?~ #>PJL~ [ʻT% 1lZ U}UNԲ.:ҰBkHIh=Ϡ~FR]lZbMmcc'^^u畆f@۾Y"YRg03fvKr> >KQ03uyfwU&a Yl(<> d;Df֎bUFXHhG (ov8Yjkz`.ꞧy[GiMy:R񸩌9+$!f'CXg.4(0S9t¸㬐{FYua#v!`LŻN*NC#;2eᬎ<8U w0WNA6nOi;dEujUr*\#7]Ft?{cpj<%F~#Ft0ޚ^H)gt`T]@4g@Yl&b X1~ӰMCƺܐjfL[M5Y߼p)Ex V2AtΪLB8DXaH%胁z7]:040yO֟jSSƚ) .1dWCBM4`:5Y?!,h~:&ePDnlU |;r܃ SL9̰ÿ9?ާz<~ |`=QPu7If9VO`P '"%*OK Iw;VP9oHoɕn0:#/Ͳ%5w&SjsPVjֽ&I>&xoDȨ2۰ bh}ɟۭﳁ+A'z.ξnjwAk"| k/;ېO5yhgV(m%e2{&[tG08種={v7Lۏ,֦#vx V6}j5X"R0=E2Hv]jfj@Y#\ǣCC#3d+918PD;ĝt[;rywtryn4=&3).K'3>uѾAfכwn)™?9!rڮqeR{Zzw*<©E`c*6y =SpQ֮=jTVg0fc=UH8 vOg 5܀UgbH߇飝{Dl|#K x?/'E GftX`^v|c]gd3xR9T2 AT"wj3WH |lyz^ɘ#|DЇj^`yzrA/ҴhTh\;3?Ka0 8b|~prwLwHb@eeM٬1{A}ռ.26H!3sN4gG\:B>m*['6ϥ.f_СV|+`AH1'4Zb8 Ԏ:DHJUv~1;]Jz$xǂiڵ-')@#T/XUre%H{1$!^'5\*6j jGNw]+IS5!yΡ`,=m؟jU_E")p`塺I<mts9iڅ]upYSutLL뵹ܘB$/x!YrQlzgQݭ=tv^GQG&z~ bynfnO:;z Ў@le7]~x:Of}qv w<$4'+̞ _6/ {Y%FO۴n .-g&`~FBu(ߒ,b΁Ny34ZV;J/`9 lH":jѵU`D1ޟ<6 V2ibG _-4fcn֗w魔J~0.$[k$bD (w]2^QQXXؘ ;05ۥYx_HmJL]fOMd6W"^ׅ^.B1^<+"AiνeN휍ʹ&wXR g ez]!o6*tgY.E9zlI>pK%z}8E֚Y) +D>T8!f!8.%"-ȴwjIǭ + *g=@pMZ} }fKMl([ 7OB0c(1&G$^Q]=N-l(x/kO[4Le&4 Y,p"yf}1Q7!} -r'葛\lJe%ЋtO#=q68W4zk8'E^嫊j{1-Fv{Q]i`_q|G lOVW7{vĤ0)u2Ȟ&%Xr멃Gck)C .Ӏ‹N`}cԖ r23g E Nyh0ר~& Q#Nr'G?`YSoq@:a5;CV0L$-o &[٨Ȟ$U ̬RIBQN U -'(ۗmtOaa~<l)_nތ{'^~G lLj)!5lYa;=hPHyc .p coFJE$/~%ܢ3Nh%4}첵fik |=8d6f J~# O90+=(I\ze\d%LQ$Ȱ"gdg+ٰŞX}wǽv_<2i@Zx0F¥-w[/XyN4z5sY7,N̓eD_LaP<O#¿dMK6V2abSQ?`+w{lp$ \MBhE $+J=H/2hے~]GO#rz ٍ#8zaqS?THSNj }[P5s3t$O/ÁimdC9$ݭ tkyP}ʎ~Oߥ.Q-;86]&^mliy@zr%4BֹܞDܴ;g>j5Lx+;e^d921M+&ESCI׉ [m^\itD:bŜRVgup"aE*"QOir*αQqnS!g+;gkb-=| n8mf<;^1pkE|B{6b}cHQ R0uCvdYӔI.~wHO 8MO$pᕣEݜSf}hd:\jf٤ș+͚=+9~:1;!Iԋ%Lw4}au󶦇龇m% 9^m%M\m%Ff.ZCM{8#unrx1/Xv]:{=d~c?TJ0";j%X,+?< +6NO>|og8Pq5W]mN_zpDOfKge}1NeJ ? 0=x/H8U0g)'PwT"=C#mf^JD#[tY;OhccUEXK ͞sX-ϼq9ϒ1h|sQQKuST+Q;\@GL|AsֽOyem:kT)iqT>?ӧؑM԰`K)5wJʹ& ;^yكjDמjݘ'}-hޠ8Xra%%l.O. C֣sBE # o9 ĦEYY[:U4 l&TR۳)PH L~ 1; % &$"6K<&cUƜĩ3OۙYdn$sxz?s3;@s'g]iRݙPlaad?xP#1f31Yzv׻e8eZ**8O]yq7,14%N_`@~EpC1Q sȄ&&\~xada+h '4 ĉ7.!r'Vkڡ(O *OfB*6=jDl3CX{Z]A74覼8wFn=",TpH챹`5(ܖaTxǣXKaI-|e-;z jX4†I>eMvv1o센9 )#.PuoQO]yԷuPP.#Tˆw_;-eM;f'G/IoJ4V=6فS 4RvĜ.:ݲT2E 7)ɓ`ׇ 5 sR|> 6)7dWxw"#dGigRnշ~H{'lpѯvax,(?0-32G$K>G뷇J^?F]/,wO=5M6`stU<1"yJy<4l`EH:Rz򖙩ЄPѹDTҾ|zG@GB>O:2gP#KNXS&k[^+{vlXfi/E+vʧxeSj޺^\㪏9^rX!n6"x ,c1A3ЋY*ʯ|J42XyY3vdi tEm [tn#?e#T}ppnı2m>~KzbE78I6E+'@3li3Tq6֪-(,t^gYzn *?}wV,kl7Rc6^DB&=ń'Ŭ->` /y];+Z7R}owri`V݀EIz?(b_5o[qc`v2Tu6X#IIt_9rL-kGr%qZ~G2{.BmRZ9a Hc)Gey0kt0 Za E.>zMb6p82i I>,.{vV]iz4 F20\| x` ~*z[KCfyJa]id90^j>*K$ր tl~1?mb>QJjx4v,~^7I@wdzP Ěo\W*SZl(̅׳4Ư%s/\KFJlu J@}Yب ohqFHdt<^$"fq I3@ڑ.M]dU6h6 iaCDFCvߖx9G`QPQ+]ۥa͊SjMlI'Jgm)GoM])^!VVj7bV/ep$d5 Ҵ{{zwzzCùHW f e2(ԌԼ? xH.Kl"6Ј/㘓鈲aPEJ[}8v&(1ZF/O6t SnuH*3wJ%gZP~R%ϕOQ9Ì$}Ɗ'<ȍ4i&Y!X~ʫ%lElvںvl-e-|RcHt46Åq p)7+AE='sA3@Gո20<3I`BKf"O88ۊ \/6Dv@8!9zseS HDή#IMt率Ő-8Os+o{fzpIO!so RX ]<;)#*d=*d*4]FfT=͘6λc'ΒaOnvp.tI9]pXgcx.`U95KoA'Ѱ2<˪bJ^TH;ޫc>J yIZQi SVcB<ʤ0ey1lw^e\gӸ+}_H=aWX.( ;tO^\أ:o֐Az(mkVjؾ_6"f"XH\y$#R5NaI:lnM ),dQAђ;Y KQ):{lB \ YU嶓˦SPh;ѸaL`et:&␆zCƵߒ;˗/Ά s%Gw0]jeHA4prCGq-Z}+SN#(0ԗy핟]E0-vâZ}u2zaR+%k9!k$ ~0¢#,TAZ[< K 3s^%+f4a3@JPF*Նѐ$њSlDlлs^won3T6c>ݒ8E[6\=P ܮ̗D>V<i0̖q|KC*[H ؠmd>NL轴l .6@\x 1𦟔-DxhA-yH{Kz8Q2"1H꾂 7쌪-;r.;@w#<]D2Z+\,ʺӁF{-`kWc%<8[O=c/{Cr]^R*Ĵr3Wāl1 BTzb{6v5RT\$dO@WsFF 3˼LԣrF`5=·z-7/1/k'1 sq#\g7vwt6 2TfYdP46Nkc3KFxa0H{PLd)?}G̶d'VWgǻ\U( !/ol}GwTf5a'3l; e9bd=QXzzHS+NB+qeJ|^ĂyŹLէ\f5y@t@ 6Vzzi㎆ùa5+lXN op&B# `> y-R0oFѾGo%'+Eٗe?‹Y$>HM(H4cL$ zH(X8Q6C=7cQW ;s3 }67YV(Z_w/riFdcť]|FDւ#⤦V%:/@XSrS?:i1! B+bFy?Dx_+~{Hnh5̧|#Ǥ</u~3\Vhww3\Z9"t ^I"4CDhyn+%syZ )aKV =-t]]B6Q L!-[R#n_R$<$u`tbPEOH ]H !i8h]bGQ=0sZO7{(7qw${yJIX;2"dhYKŹFxK=e.;dV+=U̐hh GI KЎ{\ݴs9ζ|wsZߖvs_N^ӠFXi6!_iƎZ~33=G+:uDuBz" ЄCO;yW06}h|1ʇG|ar%| :k;zXȣP&Ou6*vHǣ}Q7X"o#0nk.46>aC c,R g1 lrѝs^]fzͱ֌`1;KXdn8׫?!S G$JeE"_:?,ų|^wQKe\EZOzit/"鼿I`@NhҶS.[QIUY,>t&Co")kdri/Wl*먡Yq΄hbGrbC %EŮiq3W d?];J(s/h6ILHm"^hp7e$tJ{ReXhr(ܮϙ]^&}ޢ0=4H тn˜1cAM+(+7(Rq^i[#-7 2Rgh?7& ygtlweG*]wֲV5T@IKCCikwUp}4w}E:zֲf4%z-Ư ,m:Y*yW9EV]s58IrkF^ʚ;)Ma~B"BSiXAYoє/(橽/i!KXy& (rY^E-vs>?KjY;\wCo7nNhynJ'q. >t!U&_9Q;~dC)oK.A=fyŴxSUᨮ!U߆ zKnUPD-Nn86DBʾ5S{#}rxBH9%[N\ 3&֌>gFͺ,.;vXn#:yJ<?HmCrcAڦbFl2sC "#ۦY RCy}YWc*t?!|| 5|iی1C(m/kmF~!-'sJ(O} "R+V -Kdl 5$ Z]![X<ц4<:M6d}p^7eG @E_}kd hL4t .YrktjgΜYԳ5:@&C+/zA/o;kFJXHCȷ vm K|E/گzqBK+@p&IptL)f|z)(V:TmXg/LFNB*]AaMe2uaV0bvŴ|GQ~8m pO-^VNV{;@p35,*"N!X{6(!gtXy:o>OS*S{X<68,`T}uxL bYw@ŃdjI0o!/k^|dáF5 [>Hcȫ9ו_x@M&귨W†͹|0\nW r.[@@Y|b#l-nή >'B%],2Ʉd~l;착Y-EU]VO# ӰSX B"{ Jݠ}8+0UVma' yŸ.VO@mp~`Mܑ ϬB͔r=5ǽ^-0iM'XL.Rl ]gārY!QcLzHV<}(;Yup J)/ilCՊgJ-4~0gkiuvto {-Gf"@lUHU -M7cSrȪ{DbøYف@.߂f搇nb*m3y !5 ,%# e Zv4nJ>sQ9lGNd|βB5Q!%+ANM35u'-N {nk޳euԚӔ*xJ hb[מ7)+Q1e Apgjѣq;-)mQAmXgLz:T(cN'4ZY%+7(ӃQY ԩRøA6ae:d4iϙ&\D/ Nbm )JgB'Z\ճrl4aZ wݦż6:qf< Pjev`j@JJqjL͎tX]4MQ~G4-\~a782X>vf%*aMӄ=NX?b}RlkQްJWemDJ[#y07dw5R6(w.êi) 6N 9/nLlH-sa:w1k:m0xnL3ݸ>e -n\t}J$Gf7־湢1S 4C&v#Dv"fG>j˚h с&GCIU7ȑ|*5CWOǚjC#7 aut:%JlΫlejd:+lkcczbFVaIDxƣKNL* %ABYQfy%٪wii+#~6V!sttx]IQz*dV-]! p??UڸTмՇY^^wX1ui潝Mz6A!\ڇF)jRVgSuvN8 9%gr Aq&\A(Ekt]jvh&ά$%UTGhy@< rSl50F^ bջ;`ݰɒ'֤`39[IKE^#߲23 vvҎm=b\)hl{Vr^bt5c[dD1Y{M=kA!zCΥXmDuӻDv -= t@V2W?Q=c-'zIu:c!Y 9%Ya糧5Սq;LJ7_hĺ&9.1$SW2CYG;͉ۃ#ф},j`|!5_gิ*Ӝ֑ց|M UGOy *HƬzt4Ԁm<6NЩMtԸ@5wi;(Z2hK&ȭ@ZJ6( 1 It;k hup6sqOܢ>ognL-2ҽb*4g}1*7t?a0KY{FQޤ3)hpL zԬ Xu |ˣcnNؾs؊r1ā2~K{u{8$Gh^JzY(L&gC8+P4}mӎr#jK̽ 'PV|^O~gyk+6w(*q@q1\<c 鍡JCQr }@]@bZ}=؆cPIKSs Y&)v]P" +L3 h6+z[д]D6P˄9 re='Zv&ܨv V*b}4h[u3&'y.%9E]R.*TI* +g2bL9'Ϛ>&Q2+GB4Sos.ں;jС)l^S{5Zx&KOS9L~/O=7r"'p@"޲XM_!r+[1khyryuD}%ӆ^ѩyGrVJQW@P/x!!!EgRXTJɐ]O8/S\׃X NNre RFdg%H sϡ=20AG wpÁC\?Ƣ<o9,lƍ_5*!ߓhMm-6Y}+;xA3w=V7]!ekN(lRԹ#bh2#X+sx *K\B/KIo3a+L쥚Bo OusYb?lyeaڞ_#$Zuh‘ڵ8cN2KFǾwS!?92QgVGkձĬPHђSG-#jA.c1 dMr!,I@ O;" pJ`4f1Wlqa͉4ij%)9, 2֫\[mԕ?3q3&3RuxЃ UpEhM4{Jdd衩̒&YE9ۈ{vaS kVy|7)IPܘHz=ޟ0s+8:̲ϙ守{Lѡb"L[B怖)WO'T1( Lw,Ra+TRSE}d5ܒmjaFOc&7)>eylYƃuaH#ؼMGNߘdn]@iue#i-RP H>bnXwXiglNBc|(bĵL@ $7'L1_5+ x}pՌ;mD |G6Idw6n=%}d&/jp<rdXNO pWnh%?0đ!Nhߐ5ڽX|IGg)O~ u!h)IQrVםJiG;ц=/=BRy\H&+!g8p檻QsxN%L]p#GbVQ$XڐO~W(?Yx7wp#VΆNv$C)ڮdVrێ|9kG>O#ߛ%cvD:*ՙE+N:evN> g-/boT[5 Pn1j}8$yGf6yg<N#xs֟QooiHon~<+9N&[^p/"m&X\Rwό_^g#f'-}.&Mlj[ϫⴱtIgVU!F+3*VNX`"#fb,S|II(o=TmJ?qfS[YiJG,>WuLqu;AN(E#rtL]f.0O%i3K{3m}ZYA/RF8! W /;  .NuSv<6%6x)aӪ 3~8JN<;Z[cx11 Kt:v@K_N|RҙzϬ2~y:]}]P=%ք\ xߑt O?=@3O-N_zOWI 5 X|˴yX]glLs=*LZNye?o1 ٜ0|s |tJ#1#O=|Kw]xKʉpӑT!9]0Vi"J "uDe0E!֟ik+S4Z&(rt˦|7OSFe>6:v?0Kg+9 NnS*G*)/f\$akP 56;5^$R&\uK xM4֕zfnf>{gf>^(V+x# N2i.)-?$beqYReG<|鍊rƒ`T=/hkF᪦K34pK.ginap=tn.w]3Ѹ:mRREC7+24ˏC}"Wa$f-NW"w8ׄ۴:J" :z({d:1jk/ʵ't0$>oplê@L%QBM@|"ǺK[RxdKb\X?'.*h2б~Ywݏ t4IaΥ瞺g$V9H:t0' ɦPb֎'? \% H/@`]Vk,<:׈C{*6i!ǪSL>D{VIRGZ_lC0,*0B /i^@Ɛ|WΉuW^CǜU;=ӈ {~ƀAi*"5A|yB5=~Xj?=<>b`0|ղZxZ &6swiX{Qwm W3ǨNJMhRy¨y! ׅa?2uZCI T :iNblB(ÿKq (?:`Y;&SCЬ AΈ/{+|ҏev4`8(ϝX&f'_B@XhF3-Q"DbB%(+KJNG30@-k,//  '1iɗYH|jIEdE5J,>S&:Z:|XTA8Mtʊ^/eWe&36^O1{3~ξf<<%R-1ԝMf8^5ڔ={)hx~TY#O6KB#p5}PO] ?^wYdYL>= Rڮ6*:sIN؀άr rOEV@ m<~$}6IP |=ԗI{zlZOl_;7;TڟJѾg>*3%ՐR^R{ec{n4(\ U(۲tyO_mrm{9xB .7JRȉ ~Gg%p!L|@ p4f":{}a 79~ _aw$TMM_W7=^OϟQوYntuVuEՙj*_Z [9~aJ#FQ+woGE{|+ 56?3'/@>o/юS÷1Գ]M$b T{F"5N,/l<z5w0zXl&z 3XLc>h~-YІNJߌpݲΎmx К'Awe͘T5%()C2g! PYwmMLNLZ5PQ*F{HBl';䠆hߍ-́4?ŕ< Jn2ixOZsEaRpUf ܔ!b,VG}$q+GuOz In^upjgUqY5*⩂k-\dV 'jK=?z7ݏdlCatCл#`y#6?> /}JiqI [ɇC4S>Dt}z:peaye׉iQsjYbR>Ϝ!?o;>bav>{0C AĆcc.:1r:7W xR 8dޚDcs҉j a6҃d䪺-"nI p`7P/obK&q7i'$:"Mcj%^ڛt7A/ lY\VСF9V$*;Us)1}\A+EH_/Zl$5VXĺ$3'R2`2l?\BO#רp2 .bgE_j9ZcjkOiCK_,`A 9 9c94whka3 t [JB3FYI%WZihA(΅J}ՓPY]tu]ϗWRٴ]/1뽉Q_lWN} -Ed\NǘgW XO݌[^ ~ Yz@A|o. KKV -p&Bÿ́õV뎙f$'mZ7n70æ\$[8~rc.2)2f@OZZK&upY$lRFB%F,LM_W^$QMJV6ͧ1䲋Cio.2e^'&4Tc#!/@bA{O_꾐fH|GɎ _K+2 A5xx:SYAce +Kj3sgGfUO|{GOdTͩU>2ath(B1^š9׹dBӸnncnu~v@әP3(HDDq{ӆLly[wؼ@\̲R}Z~MK\˳wE?PzIse <8&^><7l6$IKc:%%w 7(wsr|'`}d6t$ζ?yt̩>\|c wNwI()?Ol[ (sՁ ;V+%;2!g@ >V|ZD?+EÑBV?Sc/R^Zo_ , <1z}'aekSN2M^51^}7s!@AWXE{ b|}Lmjfɵ2|slah*a,]ňy*%9Ҵ[LƬlFRQ54fVE4ZajqV&j\ݛ~Bv>NwD͵WN5VdBtCpU֫Ccàןz$_ k7r`QRE6@Untv֊+O{I׶qKN67d=/-#X7(}TW/+*6z;Rn%TɟK$f֔\(=-63{kZJ$*27挥7)K(Hʔ$gᦍ}6ɹ[6$#k wD1kz#lHNi-'ɵQFu}╓'^Y ?ꔼº~J [ /gؐ˙g2R4!\"gV' J0qb:mR-|٧kf.t௷ Qf@lwPE h}_^7zݩ^,;d`Ǯ޹9*܋0%E[* l"f"67;u[W:glӏ FqBJJTjzct[z֠d2to%NnF+z^+lfP8T"Mv'A@MtZq^%fGgy[/fV -qAaY8S.:\MsĚXQjl 3p= (SwGNȴMA*yBa@=]gLLLrOhDyhVx$(oRrV,dG=0dG#'ǜ0"c<2Pu] ,t.s:I-zRkcEzCPhS:Z;L)d*7{׻C  |JKu=[b ad\.=sD&K4;soHnd ZX>pZݹ}NݫY;BtկE YrbO,~gtL"(ex)Bud;6:L\=/~nyO`4JCr(KAljrSV~IY(Vf-].T>N*҅GM] @x_~NQcn XUA|3E&klvv||zIx7c&pTXDgp.6+P| #RiGTq }~r#Vɑ<~YKBW;<< ~c1b>8N9 ~F=n<8%8?񮟸,7D5n}h|AvVIV{]r~\Uߡ%S(@V_b~@y ȵ;WSYyv`é㌔; ' GQ KDMN',̺8f ;Rt.R(+fMhꎞ̤ ^U!ݣ,#RGZD:1 n: `ԈcuѹNJʨ|N$G Te5 92A dK6Z=[zb;~r|M H٣7H~I߽˔^r%1O%`X(Ҙ 22$/tTj̱VԘ%}(,6ۉd`-=xBe q [aMI&iOgV)r@&Ѓj 1xQgFFl\sW֗3 l^X fi_UVsv5B ~Vܜ2p3%T(}mpdi%fH;mry;Cg׷\z݁P^!t/4OKUAOz:2)mַ3zJ|K'n8t뜛]dER'nku?Um7 C03`%7^Q[jѰnx)e)Qw9ͤ3 ^۞};oNNLO@rB7 #߁HR W:^Ͻ$`PCV͡X_|?1SG#4 vgK,͔0o&[_ &oI]JXl >?<Ү5g,f.!s G,:D#\k^+D-C,A Նbx#&0WDi3|:bsȽT4>:ڲN<9?n#r i(db5Y;4HNE !mGj},VעQhrkIJ8l{wVs滓ZnvaGƑ@k;SWM cAs[*n0Vj E>5Fd6>Ҋdy:0dO ) d GNԬW)sZ&o (_yn804ى8HEI@_pMI ȞCkt<"|zI\vxHV7kɖjƩDeCjԐNxS 8fԈ~i@C{ƒ!Fz%Bʹ% ,/LL*t7I erTF;Z˄b{Gܮ}`Cɽ"ur5M/tl〺$jN(ohP1(]Q+^XA16ځdZأoT0z:ID ,?ݐ^uOTzτ][GBKnң!քRnunvב)l"NWg;]S$4q3 ^RXw4Qbn@rt])];iN9.r%Qyy9VA} 5ΤuOh wZ |JBS9ˤt.5tNd}_3GD~UO 6֝\*#EG'͔c5QgVCDaпslmU/f[NLƸgM`BuܸOa:}HK3NH"}| XRt0"d0P90 |#\o$P!L+|KZ.wѾ3td-5R}ɗ՗>շjQ2!"̲Jy%Q`;`1θ51Qm#Pu\Km䵣 b l T.uY*2G!p&VAgGGmCsd}#V]<-߁5S l6l6"/^ˈCJyO@*jL޲^g 9q񘲛I~H<,v@x\~28_MXҠ1|[!V@>mӎdt`ȜAZ6Ϛ8 ?1FY:g]ٕU| vK.K9VvcI%LLN^=/dУp]VR2賙P{Hu{3y^c#_ mnTS<}{RO&tI9Kg/Up̤r"oN/!)R&߻Ol3Z+PVe0 4B8CL e}ΐT^'{Xߚi.ch_*M2T=az,4u|W)d@Fj9 O aQ0lQ9+(;@ϴ>b e4rdt ̬j@Usϫe(7\UzTMPR[yrzZ Zj zK$2y+rN!dOLyQqD鉦4ΚoXvM̓>IU.u sZ %s@X*ִ _#K's\%#2Rt/|4˟xlXn^MgWsK&%[iYtN3pC]Ie(Z^F"{dQ1Ճ.ĜX:I{a^WXg&;T*Ǘ Y(kcep{!猟Kwe*v.zۄxP0;ROqa(the4π Vq:/wiyJYGzK L8ZLh`i[C7=

{@njw?wLi&M91{E áVi Y"Oڽ9l/*GRNP 9>Ȟ~ o0b׭n6Mh6N#mځ-أJ=ԅY޴P]iPM&3qmŽo y91VpZ$ {EkB8Jf{seǻT8o}V+LjR+"` $l¦|6$qEgp3bیtjz7+}BȊ6*8ʔp ;W`D'++څ:+kQ/RoDHa 8 9#kdRњEQÆ@xlNfAio!v0eٿ7r TTFPOJqU'"ʉH9K׬3<0#tnV ~<:)ng| m|<,Wє➳<ٓᰋxHژAϚֱ*z h6s.i,~Q }P)xvcT 4iAui+w-,F%ris{˹="AZrўF:9\fU\iT| z|wGv hy2F9=@T*+/ 䧀sz咑.S&~{hҬh{&d.q)0gc=OO "`o}7tSV'YcXDb'4w]& jWJl iQTsd̑gAD`юj(T:U FVKX+Sb*h+tzFH5>Cͻo4=T=pGvyj|CRY~[5޵cd 'kގB%_FqNaP YKO S0qoϹRo;D=^@mg2S;~ILt.aڌb%~wAI4c UfQ:K"@ngXrS4CMN ~F `c_Ѝv6mmeϹeeQeFS!adc(ݙVM-긪~Y#iڨaGm%:^\ M?9 $xyIq.z!܉W2pcǬ3_!W̲}{FV E\݋E7X_ ԽK9@@斷\R;7vpx˻I]u?u60gt8bkk`q!HNp->*-_v<)T'máx Yߢ Mw&f:kY7 %7QtF9JS8'aS2O=V%>aU$MEnAEVMlXS|fւ s)g镫칦8=qVB2l9ɑ֕4E3!ǹXVr> 'M}oO`Ƅ-n\1ϸ zAqb5?yv/;gҹ4_*脛{G_b\hd69%gկcn.gx{Dp o-W~klUF߂wӷ jpik$|(u^ 05Ѽ_(gTZxEú}Ѭ!^t3uh E9`0![`ʸRg/}˔Tֺ#R+`>maﲏHш<;H:CϚċ|v2GrM֢H͖|v=$hGSkrfWh23DžаBi`":O|1iẔZ(vdZϳ3TY,sLb2tj (?.|Kr`%9)"Ig'Dˡ{CV?(6LVmqWSjz$,RKI eLhH@lʿjlܬ+4`p+A$^zCg٘)J%_BC |ߞ:iy`(b=SЧl|ʆS>|{A>1-Ĵ= ; TP>}}S?u/t+: աy+Okg>ESk`b HR1*ABK4p;@-=S?yPzLY=>2-4ah7Z\^Pm%y=PeEU*:;`2Vx:4ytgFOk tGb܃8iݟ:Ӯ $ѕBNJ=^2z'/_&3˿ؘ2*J?9s7Ow&Q)^O}o9кAy<*9֦r:B x.c 'tmXTRB@; JYVCc n.^* DI@\jcieZ..ASxܗ[Y'O\vެa36ݤoV霮rl!D uņ.Ԛj ZfZht`0OTU ٩LKߴ+]zR^f'DpauYIh#պMtY y-a!fN#i!$qn`LqFH$vޡ +ŏ"/9h)ʹp9w4J+B} r|1;^G^8sZponr>dKIjt'mbEc]!vfBoT8!]RSg1kfN܄*Cf'ʕLEԃ =']Ql՚T-qxÎ0!((Qp|]`yنֹ@2=:9Γcr, E0e,I)w!6L-;6fMx9 C}fHBg٠2FscVafSL&s@R#M#U7]K*qڸTsfsj`u<JEds0kDvZT[od?txټe) uTJT<6}X{6ha gdBxCwꤟ\slV6=+[Y8F/}s&۾ Ժб4T{2<)d=EVh&PM z))/a+xb%pϧzeJ/!W_dQ' p?ba`_vd؛H{ʢ}JW-'ex.ISc}@TlԯЦ-m:DtJA#\Н&SʞgA%+Ȭi2yF,7-)"(|;MfhfyFci ӠS!L&9p!Ґlŧ؈@N'ip * Გj[Gm{L{&Eɳ=^b.`MYTv,T˨em-_ikA 7yEeDPэk̜+V/e?;K/h'3![)6狤 58y^8?%`Gl% <heOA1=!7{_l!mS3N /-Ӂ9VHqSю(M#nu=8mgui$*"HJzX^8PA<RǕ ra o}ڒՕ=H1F|>:1DrxZL> b L3W:!qQ0d",j'ю%>qd8Μyxzr솚cJ 6yKdke%o'x;u\QTGØ7D){L+NПq^$m}Z3OU̺;ml 糴=$f0,NQι' O$BqFuUs HR$-&# uipFDyR0ɰF9TT:ɟɤtsqק7Gn殫˲RzVUטPh'u88UFoL _̞Je=wlskӬB*1u>rYq.,\hzp"GG8R :p~݊Ƀ@2ӿEX8H|AJ"[%f_rF(,?f&ɧ/e)cJaŔ*]Euƹ,#HD;xǿi!͒IZNfjh(JZKRB?m̲lf h"3fy쵥*Jօ)Ҕn@|&r,;q>I13*kjf_,: E0k;0U /`2Gvk:(Rwy3 ?9}cYx eGa 867 ⍡uu9?rhHSdA5?Yɝg>=E'3І6晭% !#,Cx_PmR+QOZE%J rRr1@>Υ"'􉖋6CG̽RFFfB7ؖ YwoFs\oر̝Xj&j Sm@/Qj <y!6M-fڟ^lamwW3w_^gwDFM1M+.ڋ)+Bۑ ,,am,ľa#1(uepM=!<у L3!tbƹWF6M;P5a)浠Xͫ¼Pӱ|؉WÿTѴS i39ǻk!ItH2N.[+Jyz􊼭C34` 4:ZvlfٵR#P\P9 C8csg KrzsmDM"lj R >hqL "zHHzC=^OGFVP +cVTT*舄tR1qwo|>_=FBfg8ӿWy7lrۭ>/eIC 9#$\WBQ%u=*st0&OqxWMGb.e0iRFnFcNPE߆3if=~hȻ8h> 4};h2?0Oӡ]oh<©gC(qrRFSAAoxh),M !Ogܱbt&opg:lNc)l#PF#MwFfL1;i E,-HoLdox̖íJsjYgOqz9Azބ)$%*W'\m̪i,hQ@1cy70xy7  |'& -}Άj|oHܰ$z2' *Ѵv )G|OEptڧL+? `ezy"P"`~􌠶73qqzBnou܆K ^ML楥¾O&iL̂$}jHXqE;k%IZAeʩG)o.C8Ւz(GDЁ}PqBw *R8S%rr>mH=fj` AXh,2xwu*E&hKP[-2gYk'2pf ̖O3)ҡd'sx8%i ADv ]s!-2+am4%/2%k}i}1İ)=Y e&_M%:fX+"9:o%/LNۀêPǺ¡oU~e$ Xlʉé;jo/!FFX>6Y[ ʉy fW8E š~ [)4Cثf)Ʃ)УvljR/H1!ˊ3'~]G=p=a&Ǯ?}"=ku'QIĉx+1+A^╳JS^[?x{s/:v#ĪE$e)t1쬤#6<=^}C>^Ī<˔>GȜt&;K hTĚ҄=q{I0]jBi%mi疙Źd)u"98hc!OV.6F/VY{DzԀ^̾f-&o.u}xhGwhYTgڸpG vDEJ{L{m%:D dEzˉi@= zv *{`t*𷪃W:13XKqevDkO՝!f8͒q6&<#7@9? n^s) 8U(2~PHkzA:Jc+f[z&j,LjHAy6=j(ɶKj膇V7 `^*ef"/ Xo,%6y{YIrvЋ* qѳWl~K>Yu }kwm|eR.{ Cj fn`GD!_Dc]r/WZX3\oOn ґ/ҁJJs*͉[5V/[3'5ZuH5dp4 测HØ'KK)L+λuY|yjÐ%h@'.w^i S[tbE.!7vȘ̡a'MWbtP 3߳,(JZ(I- N&$fCQ蘨<%iD= 1Y55X쬋z;{7B O/??hjcΞ.7J;5P~CCx<[4{\C@,MX" ,=Xpj=͓x:?8ά7z9;(t!ء˹@ӽ&:pn*Sֈ'IHO0KG]cR^k) hTAc(K B`ަT-$?pM=ڦ/Fv$44Y":1hZ[nk쭥HL]ձQ%;nEUqua0S]b`Ol`QJYCޜ1 hE֓l% 0Z3{C.8 R70/Tq [ LlO4'dW^;ċ%i/Ɇlau{eyC u+."Ӈ-z TЄ}w:3R#(%7"ߗ0{9~#3o;tZܘ mHH=C:t˸RMϲ@W~%lX, n^8>XS =-O;I*%<7byhl7BHK 9(Y }y 6>)@5 l)[(:T 'gK,qrFn `k9J } A(ֺg]ƙ "z:RC6 [nZU3PJKOι=`aÜ lkЈwůxFo(.v}Leys:ЪYiFku/rnYz?{Gx \*d17(YJ0.\ ,TkCe)<+ ǦBÜ >:1 )>XMR$ gw(vu2 .}ؐXn ң!J}VȚ)Gto}thS!.}%u"ˀl('l 6ɓf=99snhD-e]=3 E˪{T ߜr1f<dRQ=\2}Us:.Au}$FJdB k!HO5mcg^E jy)7wPCuQ 9ڡ{@C",DH ,RLhy@ MvovPұ~{wU?- [(&l& 3L.*KteU(K˫I O_weqcyx\Q=-n݄>i <rT0NtxPs22O\@'䠷fYhozþf.ҭOwHRPW)O]!J1ݢ֘uLĽDFҔSZKk/ 9eŠ -&y' vXM!,f]UR9Ukzr_}WW(mY-/2M2>ߡ^3N~\Cw 1go0kOcz}"k;r@2Q}¿Pl{>v"j{d3DMHni+1L~^ l皎0yfh}^YaGya k{" ?=YHRK;;)--Z-7I!8_6f!uEר8U: ԏ+.pn2,ә_t'J (1v/ߴ9K hpUHK݌t:ux7"@Fq &/rבQNix;~bqپ>'qP ,~$,bh d7=d!m/r%=JOz嗢m *>Ik|HvFm?|4y$t>uEeSǪdKkmh[k -1Nx{Wg۳kEOowQl ިhaWW%ֱ̘yS-I 3V'Oڮǩ{s)ӊ qIrӽI7q̊u 쪇mi3^uۤoBdmn<x~)`]cEPㅷ<3ʰcX f 3;k-zc6qrs6ĕ=g7VAܔv' k颉”*8O5y(2갎@옕^Φ0=d ֮f\j_/LKb'$pLAtڬ~8'}Ik5Topnã]ىW]%z=3͛x;nH)ڕ^ T|޷k%LHk ty9ұ IBe)CYw4L$cM6NXS3@waFGՑIjD\PЦ8V[7&nyoi-mczj5"H}"h) lLz?yqa8Ǜ3 8xGL(6- _"1*_>%N ϧC"zddC2JarQgG5b0NLѓOߤCǀqWQKᩓ|hν s7us^R uGNíK6"BdmNjşV@kc;A! E'(- XertG- 熸y<13m;P8d=QW֧2tC=\op(eZd[~w^`e]cDXwxvlɉҮz{E*yP6E7x`%:' @s-TmG~Tό7EVO5$nj0sBQQǷN&n_X6s ]¨Qk}XCi(cD]N'!yɁ1JqKFK" vŒY~;"v135ѳS֛,/vqfz6ZSˆUi5Wh Xӧ#7t&^OPΚnGYAtC#oJ^'0Y8dqLqȻs[4KNߖxg<,N[#0q#nƬ5lnKĞR Aynל^!Kފ;;M**q^˥İm^*ӆTIgT,avDQ c rT+czhg%{搷^nhD&W8Mv4hS3>ǽ{7&|5g̉՞Hβ60yAHi7IDӕVOV;78K<qijy,uYgN[oGs`zEr\lnV^utr(7=9B9GtG{et@bި*LJ1|:Z4ZS 5|X[BVER+LM: D=bO,ޘVl0&*;%P1Zx'to !z2Fvf7qw5h4+}f^?D (&>pR11L;5Va}֬{܍`8uKnA76ro{[Bo΋)8VbTuه* $XnSҕu L{?7BS⒓6մ-I`hH|HǑd=$#>`KzW݁hWqB2Io@ɸ=>@FUT1^4?:s),I-*d &@;4g;lGaQRZ:_,ѭPճņ}ikřGgz/Pv8ȼHtdƒCITF`btVr<8Тܱcp@e:o*/PTPޝcYW Jr>;-7\n yڹm$uyUF4t0Kݸj4Y!EBiA^\<ֆ3S8ڊhT=/Ӥ!+?XFfv<sGQ^U ˥l'C^ N qUy9%xxwbNʌo$e?qȶʄFz>l{Z{)ݙFtV)iYFᦌ$vB@ %XY wLQO,8`29ݚ7g6uy|^Z*,=Haگ/FWm S{z:1̂RЗc$Uz>ESKϦonI<2 >7ӿ㔞΍{~Ǧh# 4H=$T3Bus x7%d'@*B̑_ߠW5V")KUeg۰.^ U+l\sqR Y'xod49ϜRwx zmMGJ,kۙOih5g0/E/4W:vF`0glϞ2^vV7=$>ڷSjb3s.9O%g WbBb)|"ݯߴW䈵ku tZ+~?<@hyOu{,$aX"!ӻۋw6n&%.&N فlz3o*$#[\@; iLXһ?oywrr>qu܄0 ho%0AㅂLHolO3M3]Ӂ X);zgܸW]Y_76>o Y ŷk M +@o(I{x {vZJYW:qUkDEǘHܘ)>]Tԝ4lZЅ ʹޛ N:B ONy3+w tC sm;4,ti˼RJ ; 2hNiĕe^1N3YVwa.8>(yo:AAp|+O[z=cnӀWlrfJ!t ӽZt+,}^'4VӘ[LAei *ˣh@퐾èiԴ0}MD]/_ C 3%P5GEP;ۀ.V{(66t׻.;XRЕJlK 5s4H*֙4s6vN_Q|}.8euYIIwtHUtAĪ'WcG`$v}|0E-J]͡pDa)TćN\YR%Evq'KEYuopdze%EE6DOHE4,OeF9/ȕij2{\D)U]wbb15 _aʎd"w[zG/wզC6em-avP繙p=1OJ-o}vtz,YNf dX?@fZyz# )9kIzgA5qLO59ǗJZDRz;I# p"PC&\t;sbfsT+z>-%xY'=΀]_xZNS6ax8HAYu#Qb&syĪ+ O#_x28Ms2IAXG6-obs2xDCqobQ˲$X_Xѓb&6=t 1mcr9}ZbE6 Y4!=TktOm!Y-1POҍA!#G|Q_qs?*yԍxJ,oRNHA S.2~B}-&Qx8 zV󲥀$OV 5:Rt= 峻> n³`6O%O> `ZK=[0I e2z%C'+] H|1нOܐ@yG2\\d\$`ImR2+r)D8w L0$a3;;[#kGyktX2Τ.j$SYԚʜZùq(s:(Ұu v;+m5z!ai%̅(r$F^#P>7A#xr"NJ~c7XS 1W8DViY}÷'+E#YhbyS.L46iHB*STM@t췪[LIU_0;V!V!lMKƴh%yb|6͞6]}CʷB -9p5pѥ0mi?aEp臽;4Q[N #+;>=Ђ=3[Bj 9>|+x#c% LbowN12Ɖe Y':$ 7ge Q\QQa|]Uaf':t[{eR-6ZqD]\mb1u *][р'ufґ #3j)>rˬ2g"Pcm|,y10hOpl ~kf+hl4LīHS&:B轚8sp8Q0X079[S2YzAOPª.Pa\ԣ$~V[ަ{\"޸4QBrc>i"òR}iWN0ƒ qwmfxF%PߢW07Ԝ/1bxQIF%>wxKV#OBag[gy-nyUg;@Y&ELi?Gp[*cկ#$k(`t y[L)+/j4tm49OASEO<ܦkB^8[Ҧ}Iܞ5ޕDUDj9Wܦ d!kYѓ!Od-F]DE֬(ds8P260ƨ^ӕcX[,L{\xCX& 5v`Qk鹷<tk;%=Tj]~0w4:U]XyZ*94^٫ H,nе m ʇ4?ixr{8 YpjlXifS& < L:(Ap}Ne傚Lxhy)uqJ_VLT Rs(ݷs m}G㒇'/.׉|%*=uư0&x>=LBK<&veT4T"# XsW5i!qo(wq{%Q֍} u[ n_eÏX޷n8ch/gh+w` T]pqsCՈߎhR/IH+"ߞsY!-[ihN{y 8KgBUD8! mP?:Kx-o [xCs~7p MG Ep!1{&1qUP(M eԉ;0yـ*jwD}c.v)^= >(w>@ g `4bQT%[)b^/dwfep-њȿЕ#a0]rdi 0os\YX7MigiMxq41b4\J.Cq( n6Mޱ1%Ư2vzu7d7dډ?$zAbr1kF1} _1hVhxAذ/of1CaT:% 95G'H#5Wics1RTcf6&:z VUgIaAzVX Us!@jaVL=?3+9ΦH#)3 !E86ǣ2oԿ4V- 2%>O:4-*Rxxi49RBT>[6ʬ7+'HxD`O{5/@vf7d(I1GoX#:)"]|vp.1*gSqkM_ucY$F AN+=;HnF@'Gպ"~H\iT;CzHOݥ8UӦ ρX^NvjEZs1|'"F2]M/(Qi!+vӭN}KّZP ik=fcK@LOA)tOIvAmyI4x>Y)]rd g+O:)V5,/ xz(״|)mỶ'u~#nESoH )kӔDv$hƓ! c&N/@<߬~vY47ށpk*Vbf9_.|FBgy #PQ6=WC q؎ar6,?xFkə.q ; 5Ά { Q|D+f|nKn8I9a *Ha?YŅ\/}U)O|@(V@Jh{6Le/29dqכvŬ5R:(eds;QdG"SJB}]F&1fm6go}ڧÚYzQgn&\xf^ξ}wxLokº<pڒN,;7+F阣ޡ\nv[Jc"Wza Kl^ڼP]24f~3j%M8 ggoڽ=Yal_Ő'esfI1曝ϒ6l /-cYP*on4/䫲ޔCb.#U0m._ڦ.@[1T-GAah'͏0rB!MS}-1IbL\^GmYi~ A9iu<~sܧ2l)̛T3#YUqϔw0] 9c(߿Ovf;&KbK_tr[XYD?6@WqtNՠ|&).@U[@[>r^H2kux†ÄL 9Dy).S~K0W ,e] p{?1s.L5r:}N4c9dig qo`kUЉY6jκqΙs㾝Q<^ѿY[v=<^g ƼRTL*vph7,@YE)hyƽX3tķԇN\F4G&\;yblmy& Wѕ-wF{3+*v/i%k-2xzvixĽ}V@y-h~b_5kgQWt9TVslPk2Suu? XwڒMU/5]@sCXoPҖ{.7}̍CG=og:ag(ˊD^]W*c捰xt/^,<ȰA2Wmdl霉VݤC.gc9^IR$it|d|h LǶeYxЏ4ij'\MX G<>er9&0o1UǤB/G8?|.)b=:pA! rDbD#6^'ڦ38'uDQN_ϑ7r:O@[qȻ0\򳕞^ 0Z΅e3peH]YB='D̾kJy`G-ѹGǚI$K3I Yr4 \IӞ@l8i@ӷҀ|ys,,>sD^I =4xm,k>brQ h^ R>d&OKf0 U rBZUhbxB =}72S.PV6XyDsZkY6^s( 0ԍXE{dbͫt { ^~ 8%%kB3y$fU{x/y%A!žDs`~θ.|81SC'VKY@l6W\ΎD"+0bk+2gAd4jdZ -d,tOϚup3 &͈ Y)X^i%T:5j@?˓b*ѻizDU\WTeg H Jჟ'ӛ2 H!~?G?69 $_l]Ą|ט!?zJ]r{ s#w \iB>v”N w%=UBN"gk")_UBD^X/e}e=׏{*;#SX(ǣ1g$]WNrѴEx:aƛ/)@^>A+qiK+J*DnxtX'=[EAeX8 >wЕzj7m~# W9Qc;jP_a$u>s)r$ڜ#gbLO*tT0GTJt9%ΈRMz_QY{_P)dF%ëkg}jn}/@I|ϣCF@X3z%PGN\Չ DVD^ǰ%|m Rɩ?{yw jn6cB)tm84h BijeUBs/ʎKzjذx&$<`Uղm%;{MYaf!*w_n*^|Dw`A}W> 2I-D8j$=t@7ʀ,6bKQtL3̑?ݎW s{ħ'u#w5&,T Z)4toE846iu07hNm&z/|r>m԰j&t 烱Y%K)[֙s"-TxM9%סχu">K! I bX"n6VVspkGnENl-?t0qdl.vA B|90c`U6N^T=U?2!#*RJxiS); A͜m0oLaCHE+Dbuˑ.u=> /)4[~i=!]WX(&^zڥl#X֘ JhKJH=y?o &Մ oZ0!)rlz&(#,LܬE`z59aF8zkO/v B#é&jv^mm4QTxR4|6տ( myI@i!Ә{רe8}.l >jJȈ(.՜AɻYgJGdVc`Ȅ9#{Okc!B-=؞ܾP{CzB/=0ƬMtҙr Ygżg0ft-_*X;{06 ^8B\NQ<i.2Y{ޕWjķ/tNbA,{:cY_戬t,4*<&rN4ms"`W=g\6 -=g: m,LV*Z o -xZMgo,:_%cha8Y^oDkNKzh果TZm@#-^E=.h%jHȻvXAOTn -0U%ylRgo)"|` K:uY=REtȨܸe&b͡[;:Vƺv9ѯF)!p[G):.mP1{>c^XTN.̋ϲk - ? f MQG_C ?^Y# 7ZZByw*D~gN=6S@7Cj&MdSH]<. s[qV(KLk'TTខ$T GZw -w QVk1C_ {0hm)rIbϟsFv8gDY%筘toY!PMyVhܿ&t $4 mh<$c/RԒЦG#jwkX3^GXUNJ| j%WX;lK6Y; Ⱦh:h;["q'E'Y5Uޚa:fxGd"hf+4q-3t8Ԅ.nHp-W+;pCxTyoo#:tM@Љ= o^zr@[ M*<^Fw7 .lR8<h>0gIe^s0oŇus/h{+#6N!םST3e|4{!mK1/k[O-jUw8 5cݬWtݎ#}x8XݱM1U6߫L)7| pnnnɡO1>w.64m.S^E4P(./Pw'r^w9V_FC`͜gכ DgߎS4dͭRĬ0{( JxK"t{ >ǫ̤( ^K7{^^,pTo;ܷi.6MlJhXMަEr[aB%1?ZxCiDkd֊ɤZ %p1 d"3SɳhVLg±HctFRs92A>4!R-U5$OhA&%6rh~2blhf4if|@򟕑m a*N2cC1̯IɎ\ȟ?N~UV YpP"([%N KSNwycXe]i4"Jz3gwz仒=;cISL16" /S+&ʮSSfe=+iiIg3vPû?BmFӡeGDKH7D&W\^ׁ^wIcs9C?2+ݖx:v)ĆZu'tحE4/[ ak3P{'ji0SNay+y;aV#l{ }@xuR;ԂvzF!P|yob MOAfSSEb0º]#Q5igSt;+I"oq^ao! P)IǨv\4'!<`2zTuOhm҆ɀu.Ht1/Q@xH+kMoo!DVpD`܄Gt߱cElexm2C:M B/0g9Jf0m+; 93PKa@u/I2N4n.o+drY)8Ȕ0I ~GfhO5J6e'J8岄4K bg%jȇU[Q;I3VccW´d%TZnѶTjMfXe^FS ڬW8kn-u~7]iGsbYǧhU3+@[4aLOiQHU'mRiMJH^|ľ.*'YͶM}unˤfeKΝ.`l;АfP.)lff:{itzjupzfj|I$ֺ%Uh#w+!TOk%if* х!O~AM|:{a>96L\d:NH܋p/` ]}^z@&hL{u DPGA[W&T2c#mRR2 bNv-n\G\EcCP|*3f+)][.툦) 7[[n C-g͚O>]MahBE߄}1`Zu5z5/ Ԁ, 6<+Jͮg/\'S!,X{C.}1H L/aֈTٺB_-3>mEѾLoh dOXmm]"28QTؓmVrPY~(l)dK̪9e-P>~rjN"agU;ڍWӒwp0)xÓ1dBwfDUf<(Eb«HIanml`GEmG;<ȫ &(A*pk$g+i+ޣF~fqTvihY qޥ,3WIu^`nu3ɿP@3 SkȔ8q~Y=KoI~R$6v9 N9p.4zu*SN }+EΨ!8\j;4 W^zɠѫMjta> sd6Z"D+N#G{Gr\+%{a鎪ځ^g+iz}[h,Yy-~w& T{y/%/o aNuۭ k"w2PQnD|ۥ ItZje@@[m;w:1ni5sui?lGe2O02zc~FdYtUV<7o$=ɻsJIg<5?j 92vA ur4쓣*̆r)iy^BhkO!񌄊8B2f ψM\tJyztk0 P:*RγwM k"7҄)|fmO "q('TW*]b|ˑ<Ē`GzvUkvq0&QQ9$.#O0,j!7Xi1gP1))k+;?J__joZXen|qCgbd0>}vNyYInrv[I-=3٠nYWLK>%Z?WV_: U^g#F FqP394exhZ nTRYOɒwHp/ p+?4YDFᤳҤ8)'IAD PcFt-=8|Dc@!:>= [wACnB8TҦ${AVїxA% clt0(qo]dKCnਸ਼/B!J]Ѻ X&yN9H8kasX͐"NFRU x%qu*1s)A>u 3P*'+!mlҪv"(b8e3(֠$6"2jhGf2Ջv E0BծSveUhKToW£ XQ؅=J$st;`Hvcgu o9r䬽"EW]!x䯰6b,WIãy[IuÉG fW_y(Q  "6 \.]bm M [UpHf}{Y:y3ȘbGD/"8;&"++PdF (mVwަ^ 2sWͬIB5c[] -Ivq$':hBɊSDI&A8t?af;qù3zFZXڅH$q2W*!ßV=ka逛Y[8gBgYe;=PTk$g/h!anQc}fN_0Aic?ȴ@4lx+JK? 톕ׄ0Ѐ8֑/.؜a/V'h{:)D0ʮMs{k!Uq76o D^o`q"sb GƑlF'l,:95]MB,y#TeT7&fS*%Y8.ZSC 2R9Ah)q N,.Qw*^-a?8 .`d J5{2`ymy^i|4- Jn{)PIY%gO?s4s,'Sǽ`gܤ2wYTyù*oQJ^{蟀PֶVb3Hhz[|Av79zpb;V.zp>JQ@ S?`qk>VqRa 7Tc/C)Z0 GM=m|(FeJPԆ@-+g%ķ4-㿠J@ɥW=֝D6Fa M.oKd8}6',mU wQ+$*ʶPφ͚%1t&ۀRUDY4b))F%Cύ5tmW % PXI1/'*nG=ҝau[_֙oeGsvIUl S"og :N<(!W8SB :uR7ʥ*9];=~?9i+Y'(̕a [Qſr &:]dAĒVwPޣmcYHJ\a8,'8 ф|y%3R`ϣn%%_`/5{\QE9~L-xGv˷oBw:p싘2q%=H$@WR'\BBxh?v6م+Ϩg ;3#+13TcV6YH F$i{pݵYiiT.^jY7)j5-EY}Y5< pIBZg#@{fy6KyE31y/}t[Z ˡ6Ng[S޵aςk\bV~OhG)aQ lp~K{2J' Oط_=Tf@Mn\ P/E0jd7j) b~6T1n=op+Ura̽Rٙ(/|Oh23:^Pejc sWT~{G@v7#Fu&,fCy B F<\*w@M<']/-!ѕQބW5u(厧=9aO/V RD`y s 613~ziW"[C?CP;IgX-Xϭ8մm=~cxlc_MLfXn5EoPCײ@N3[[B)twh9Ֆ{~A{ 3DƯh^xq`o}5s Xa½Q6m1[rqz(~h$"vo&ܥ /@aW:a``؉ॿS8VlNXLX'J{1/1TH3M9ՑDm;X[LoYSOtt؉#JPv;DgT.%aqG#Gg!:Ǥ6|)ǫ_AJe"uVyS{#'r3sCxC@ןW"=zt7s33ZС4Λ6WK >o2ֻKY{yHwmb}bCwILkŖerM|j(!f@7_dH{J~|:eԛcvk.7oRP lӢi9#RqD-Iy 0A gRg5UM PhbՂKDBKGg1!QV)wZ.Hv+'NPB;MV)~ ;-&^.ƺTb5 *8}P}O)$$e^W¿3rvݸ?wtNV],SGV?@zcbVB]7$Hѳc}AT$ƪi~9XZx|RH =E1z4vfP(Dr Om,?^s"7'`Zǧ1Vz-J-j~{X p衛nCxydz&|<$>6wTJ $H0>vh|}Xh Ifs4Qb)GBc>?_/ SONH[qc*kxDii7>q-ŌH(6HZЯ^j [9v=: \7`$yD$rv0%~?-77a"7߭={3H Ȏ>4J$U1v+XbfUZ6j抪>jT;qv3]G/Ljþ"g<% ~ĤSpC8J\2S7/RC+lKpi2y8QOP4]e_/% @"gw/ZiۤiQ/dn3A9 ,sٹ|t͹C;f~WЛ &]2wTv9>ԓx3d&F' h8slnd'su;6f s*zpYXh#wϼzEdQXo F&^J5 5=Ib6XjO Z*#Fg\JG x %49K?H,ޢ.=>st'r Hq@} DB99,WȻ(uQ@ל',E44FΕj^GzAOGKO@J{G wO7IG83):X}mGSmam }K!/TC~% 1ؗڕK ̍ m\ &9)zT\ul5AxaD&' +qD>ƪ="ʄؔu Ӆ|@&`) .:4SݡamX}'_wy'gQ(tُo @]ElQӼSEmyUfF盾t/A7<^.߻43cl>/*: GKpwdc넡IyO@ ch/ɝq +xY 'w^6DXL;O<,祚MPT Yܙy%`E#+L-b#6b$MvMT<Ɵ ߝdb0*>z(`WvJ)cʲ_vo4KeN҈q=|mON̏΃),}>Lb6c[><pJ8W:lO*k CJ1AUYq-;Mqb(Bwr<#Ȼɤ^C򉢴[7壳S{$S@9+45IJr~n*2Gp4VNF&̍[Be$z?I4_8q ┥_̀k#"`(JkE>Ot,E4t 2+)uh[.7 ෦y]ol:֢/rClG&+[\]L'[kƦ"WxN ՈDZ&')L_rp ӲMt^_Y= %!lOӴSÄ~NղZձ ujIt-s?neKmZwX &g$ :R0(Fg-4)T'JUUǕ$4HL#~^ͭ2O*pe:2:\oo$ tJH]|x?yRaѾ8Ux7AǹYmLb(ڣ JHb2KYe<0v_j_D՞Bt dG$m/j8Mb.=lgM?b`w2]5 aR-8s LE )85T ؃qs!d@qxCjo:o($+?(K/wXEz׾ sw=},(]T cD%^aTd&Uf~g:C[+035nߐG5{JǾRĘd)[KLv._-:옕4{"|/%# ΋;Vu*٨hF&5>EQJSg5tn0fW4ɹ,%6Mh+(HYK*S0FXN_tݯO-ciP;(w[A^qJceHYҭ2'%P]+<[iZr4|'Ck {Vwxyk_/6Wzpˆ')PVӸ[M8V`ٳ>]pBZ. p猡KVUO(8ҧ5Blm8=@n.$oEb"MVC"o5fT 1pϞ(Ҿ- լ@K hdoe%9z:G󕹉m`{745A6\K:Xff<>0F~yN($_>cO:p Y fّ )v~m ޓg :›nD8d`M8uSz3A:/C8AMcX s>]Jh[iA~)ki9+:/~G|.eP!H.|@5;p#|<"ɋ\HoKFg}D8s&!gS|O=][ix_$ Y̅g-оMv7&;bjbEbpu:(+M>KgM֕I~Es'I b\vOyMI C{$6`&S4?E{˺R>+ڣa׃8#R'kIN}g鈸$%Dt<7s yOz(ס݉8Ňk9_="BcUNNCf9w4wu_`'GsQ&x#FH{Ěw$z ]ȋǡn{@N#:``?2/d'*AAQW϶mbKj[ݻ!)2ӾtoK`+ QhhΫ?OlN\ʷ݇"<&XJE i&8a)4.^~Bc^zWId]g ʣI>'^/I\9 ! ,ՁiȳtY g6J/Ln#0N׆MwTU 3v˥6 :Vz}wE9ʋFm!}~Hr6-3LΓCxSYS֔\" -"EΈ*C9JcϦsY$'rf!2\i}҈NR7)7b S_CV,$:xo濬O`K´%3{YE0e\(V&ҫ 5$()NzE [~Dw#O{5UXb;yH]EFv3ly_ܖ}qs??恼PDN̋)kY%,'TrD߉B߬]Az`Spdę(2'o@î1lybU%3ԏg`CGEEpܷe7Ep?l,Mc6zH\2ťMj1F-ٝ#:1QC54z: "&|BzFڜ߽"T*6Dn߀]*I*=%}֚me=bxå80ϺM%i@xe͊ SRQh3X\\mQ=B`CUnAb[{6.NSf>-yxa9iq 6^-7=r ;&RlyoX3MjiJ%Mb=r2**1/gR'fV%[l[q¶o :S *#o[A`]tϝ+f'c؉>T7^rZB7> {Cqb`&z(gIqbMyk?z  CoNhI;TOp?@&"$go1MU$@?ԡ2llȻǡУ_89=);5fǤit5̮_;6IF+oHdNT}2UTG֟,hn+?H3cԅy%|Jq rc)v^ߢ,:n7ynSVVyFcX tO5͔#%ӑE\mjHh(`L*GȢ#%}JfShLbΤSF"Kw4[S;"@2m *̚%W*:\a`7Uꢗ^jˡ-g4/>zq/-=#y9'WlHW5.+q90}Uc\{<2יuy}4ۥUgO\͗$sOYsUSXf6#G7:~b%w'aEGWgy'.9:ٞ#I?BKR@?EyP<ߋAہ3.q+`17Eέ:VMZIZy>rW.>xCL, `#kWY!wXk$z`5vTdGb~Z؜z#)B{< !Ƞ >bTyhtamSy"逎Cg[nQLD+(o<[9镡'Ov*kf+૴qȽ: *6 ww>{%pާa%2yOwyFYiM h}^o&>Ŷve1ߋ/~m-[%$QH̛5fGC@S֩s1{)21Ul?P gS>)ɆQ&m/{L)X3&xJo4K݄LҗШX]ƈOe JqF@]cnv>ВI(LeuYR{U^,dNظniqĜ4c2a"1a0$؛Aۈrc]z"=S]R`Wg&$v$M˳$i$[&j~CaI3}C;{"=i0I"rOq^gte(}My-Lyyn@6H[{d-^8oآR/Y?:W&O$ݬHJޢIֻꞾJ=z|O樷 9E4r$Vua3'"AQOSl.н){-[̪Օ˳ qGq _|j,LEa}NUZ 5`35Mؼ8Ҡj) D>mooGږW-x q`'c0zg |C\G#_Q*;3[IN*^)F-mG<1>Rҕ²vNd;+іnlgά5rMpe9m>"\{:(W8uRZJSdpoV@7~b ǟ2/_2 ,w(O7hS;bsR4N@՛n-:'`\H: 3w{5v'BУv'!JnfяQj>: s ?o۝+êeOHl}7ԯO?9ecfUdh*VkY|Әzy1dH*[*i7h;Qɕ0t`2t*)?¶]ں\ц^|G1zA⩮*N*o"]>j4R[N|u ѳvRi'Y~kHozs77js>/Pc7,2rJGq!}5fzWʵz=̎j]+ 3*97lr4Ɵ'Z"yC|[({3J?&#J+VOP3%jt~vYDbd=rz\v.&eY.Ȋ ߀Zr +1ZWʢB#GXl~(I:ݛh$_{V6ؕNH"0gٹY$qCss8|i ԳymfF5I S!5ryA&tG 5שMu(L i8m.֢νt>u{kOW܍/`?]1;O7]S# ΒS0VFo9O&)XcSy:3'%*hI"14LcfcA+4GVХR;|.چRQ+]8 e7ӑ)`'&Y ;-&V@@PX]OD2^ ڛ׸CU P/$l;c^?9a& 0{;oX8 ANt VW9zYg!OgdzjNYzZ{x~1 b2;#P-&QKuL̙*qry^d{{@K 7p[йl= ??C?;{y >g^g-9wy~y9kM'x D.>{g[&>=!,GPܲr:Cu=# >"AE]&xw؛k4 6Ñى81&)fkiB矸N/ ^rnc?%p> }W4,2S%wrZSCe~UNj3b [֙BqBclϐfL8XyQ-a23)dRSsCͭy$C|ޗѺ9WP9S%|zY'@u[,}CX#Yv؅Br tIZkҘ>j4QL h jxL6oqr-o r۽ 70S O頊c?lf{Yq|neY2? P% N ekIO7z8OT%iS) ˼Ƒx",',TSb?&M!-oxA[@$hbNˬzB.PA+6 (o1:*D_(̺c`''ʠhjR & 6 G}Ҏ;+)L/ϙ7w~6f_cnjҝ`*.zH|E\Rh͕n԰:.: +!2Pt9|jzXy__!/Y̬$-1@zA[~1 LH% @ʡ;c:8ԝ)7]aQ5ItIGБwv ХzD+ ֹqz3:l$.53 d fb-@ts#֚ Wj +ht|7w,7wͫϺQRN(Rµ.b-m}鼲2ggyhzgEltr 17ϧ]#V-vcQ^7G)C<cMg5(kES /8֥SM~1 9BϼI9e@>r*ĮY|!\>=8 ̺N1#gГ6׿O+KwTg-Z6./ZJ#N[89#fh*Ή}F~g)cW۸y4ZuHN.?hBw:6ggV.> H*hl2j+t^(i9z XH ʗb,t;Tj}arXnD}LXtn&9kug mܯ `n˙rVK~Ta>ZF5~X7ak;y7Fv:C㑰]@J)dw%RzH+֐9u2hfNn;G'@֌YE3SAS:Iv Ɂ u& M8nw#`[L'bpfwOÒI{'9+oS1_f$MRLB$l VZ{~ =6c(Jiv Iĕ XXS'"#og*~`=8S/N G*봡eOӦC8ioU=?[$ʞ2k0 ЮVV4U&|դR22IW]n\5D3F ߀%Rړ]Bh3+x ks]nBxFʡTijcԫ8iuMݗ(Qs/T!gM꾻nxFuM>痏nTg0ن8|']yIRAU>rg. (;[,=@v> :6{㡊d%[$/|$5_:yU(f179Vc-r}! *uDӾ Z] /vДШY6҂CIY;&_yRHBITM:1蟉Y%kPMVk-XYk;O4^ V~2͈颫!d&Đwt@o_;L,+``)mdE3>4:-6Mr#ֱ@^wysKn WPO1@[\IQF# .6s%^/A4_/ihAf7t\AO-æ}pe4)Ex3a' ٖ]^^hDlɵQhFjUJF5|]29[ 7j#4#)^ P &̴olQֈ/Ꮌ&O~Z.kWwud?h8rV]"$;׈-1mOw1۞lEn%4MVIT"Ao:fO8}GiW#\Y𦠝Kmh_ݷ߼7$ۧI-=t&q""KS:R5'lZ>ai0p0G0*L0lmtC0ɛCtK8f"[]ߖЩ,pΘJמ'sow]:upj\ rUӞ3E!$U~qڹ5V,ɗ o𶵣VQԋ:7/~1&ޥR Zةˠa'qrtc^$rU[C}fhV+0;,YHMpٲA4o[B2=WA}Tǫ;ořM<<2Uts]8)tw?{B#sb}; a5{Tq!_b ^bUWvtKmq.xݣFzo}^Bu i &}ez)8MIE;жHcub^9,:DM: L,%M/]ZCP^3~.6,xRK=gWmY';Je V*&GL6 Paѕ\ >򔊖oh&t#uMyJly$0x[˹]B~جPg˚Nx@7Bߨ͎\&PP|G'GX} 0&wrDi.t]/tÁ:^~\<YؠQ>J)w}HM pZY-7o4]'䄮AʛFn^Ƚ2,E8>;tPԼC4Mc g~;BEK1s;=s,͔_t4TyZҳCTkxX' z#5mz<MZF*+`'ңȝǒ!z= gSӭ@z7/f *;o*|D2WdO54I77lV aW> % cp K,@vaJrV? ";:KC?~ո#J'@yJUzܲޣdSLz 2r-'SBrȾʼ.Gmd tm3l,NLYJTL<Տ2+C18vQ +'ۇ 1HWXk?vў )m.8!N$' RP7e93{M4/tc20õ]duޒ|%JvߴÉژU;f(#x?8ŜYYQ&z@#z,}?_!H5c^$)M=[RD֮]|%|ۆDǺяIKܼ Z㡿Px$4J=넱T˜s\GGN,*?xCl{8K' 5HJj:4p DohKwIcwʿZ?weQcА36roQ4o+W _m%#]N0{6o '3%Yzlp¸*+6cniκc/ȉ;ь~BC9,>3!YxoT&az6|Ӕ+ %:4Y3e)61K*|C&zCTF4օboe$m ^o'>P(8[;mn:J;#𠩅ۃ&T6!q1Sovޕr^'DI?oЭP;9R5w|ʜ- ˩଎c}ya1M&XܽxCgϭ0VX;ain L_Eg;cHlQ/J'm`=mmrƆg#[]PH١:qgI؏KIs)$IhwRtCq4eZόˋ30;nD BԝBCia, ol6n+ѝeNJIji\lMG> R:AH%f.9Iv.G.^ތumĹ{#PWmr Qdh;/"w^+YmV%^Xrډodp'eLV2km@ z8G hRT8v{i>y;3E:oB=\( #'s]ZZh)O_ngYX"r[Deȋ.@j00+uТdGVD+dM7Ǐ$~ J/0+6񦛢+:Ћp[.Yf-G "HJ=1!t١2Ҝu߄]V );8Wje2";sV 4L˜s iZx=jL4^)oVH PgL ӿ;?!L/~h^.g=l*iz^jvJD˩EJCiW;\uihi5,zoR264bԑrW\Ӵh Q)b&>"{Ad->RF›{$6 U|s?|Rg-,opo km(0=W 9a" A^x;ICS*'2hK?~N[Avhyٮ:bPSw,uva^G"Gt^ͳ '"`ڲRt T/&{Q)8JM DI;tU|բPDF?QeXh/ 8mHr;8'sWKjGu/ل'}lueKIHí2!'-54 a Hάٕ UθԛحSdm*_nހW%?)TG Rxhz )ɹY{kwutX{"b퀗_kKуN0cjt(2_Yf5?@a|srLbs+nLq!v`:fgJCx_HX0r&aҧ'|cRǕc(~WVf# .CO7lX3cqRLÑ־Fïz<7:^4ш]+m68gpNYV}HMn87]Τz-k0gSהKlIӝNcev)]Dq*\Mn2m]xWYYIZa;픷(vZA,?):zNc3DZGsCt\:e&sg=L1'du>_wH J!p.=tCnJf+&#܎U;R-rrz(һFH$Nt*dk4Kju7=d!4Յ&ScNv`Z gu;*0& NfXUD>,-p-IS3&im QxA8i1[jD⵭%)OJNlj7: \S-HrY!X.r#\5=8x*;Od_NlAFYzfC~L䭰q,2}Y*I"QvX 3I hN?g6kuh8ӚOm9y7_*kN= VJh|"7cB{GRC둘SiWz(0]Q&}sm6CN#Zv.8Yd$v+cTFlC#%N30+#8:W I,AxZ]+]#Ryg*~ /*N-]Qޢ΋e%ZEG MHΣXyQitPlNqAyQy])IUrWx"nBz*6y0kk>*$Rt 7}G:JxjZ4c8o{tѻ}yѧUǹ̪=K~ֱ'n`; /!W~&vHQ`+8i+JHO $f/wEZHL&҅# CTFBڄyY$O(ɩB˙UQy+h9WNjƲ:?F% 4 RoM+Ll -mA/Yޕ-P:0/C83dE?gY_V+u-2Ckz '%ZMc8-gF!R#D_iżl"qIZ=(4o@QgQXH~ur=[w2G|ꛈgvvl{ե# _ޡh%~:ZBj9B1 pQ6`8M'u,h'3W{-Y;"Mݡ i$WQ3# JsGV:] t f7[A t(1PձJRr&-@H!dlSs"mDcז{%h6prYK&~vY%GS&My JDW\o241wZ "fz*ulVCl ղ&ٲ ]&~6_l?>y*&vIPcgD3E4h\Js݆6[)@^FO'> %Ff:=—gQQk4ma&XO-o]E3}7=v$ɣ9V+;(|I;[V=izR"&) xV=;x&/'bbШ UrПvwCaLTLJoVitk)af ^nQ}]ISdEAf@(ԃ;/]%r'H#5۱ eyܶcA\: GjԊB3Y=:l>P: DRbMcZwē܆.P֜Di( `Z=Aa8ڽ%fĹϽ#hw_ !BOZ&HDf3Y8 )[@kc‰r3<4dȷݺNOz:p<MNʫڋ^S,n'{P'PsRu>`ԅ3F/|:\k3ij?;<,4y!174 ,aW!E[RK ֟ӝ!|Pf:j:7DRJ#d_ylsB"/'+O'd7阦m5-FQ[gEnQB !(-\o= 4"V4 HE1e GAhc+uh)m_|(@ C\̢C\x|9TGh7y(KDL [~/Ϩ'uB޵1޲-Ai֔KSܨChKyE=0c19L nmXIrݮ{~qO\h @NNUgfBG8%%>:jC%/ʐLqf萱rR%Q=Myxy*5gӼ/ Umzvh mv]X%-^[M8p>xW2L>\i Jz<T4x᳴# ϭ8C"9C.mU,q_mA xpN80^#GF DI8ؿo4 7sJΔH/VٜאTr"5I>K&^-  2v gM~G}}ɍ8Ju@ y7;mJ=T kb QQL)Di!/(K$J}% G^îK;Ef(@VH ؐ˺ڳl Tr +jgɫ \ [n` v ɩr%;^o\!c:s.F*vAn""+pF=PW4myWau,tQkK6oι{OC( ?*;y8Y9gkD*m˽ 4fr^-'dS8vyiIGUEs׆ S]tOGHDխvj$CalhVɛ mІ}ߛII#^*cW$@k<:y<(ykH4NGo ioJ"}RJz?:}m޸n-6ۺUxrs+sY#ܪu[a_IW6?O莺K-ul8%1Wnف)0[:KQCQjr@°1~~n7A̴ ?6~B& T闌I;2] }s>#wn< |?J&Cj |>"1Kqb" 8|S a5Ոk.V 7EaҴNGef.3pvyiGp"F~z}{t یIs~Y;WA5wӄ̓/Xs'm}<?n+KBOAW 衁ð=S9/Sd~m 'ЫY9Rٙ6ݦwc%_jgȭ7bdJŧz`c}@0mˎ'^nNU͊ MZۏZO 9> id6BJ;l6058|t*v>cR}xIƝL-\a٦gF!MO( $ 9)iR.)Ѧ{'#g$70YJ,r4&\$(3c['h0dn&acdۦiWm"*3"䁻6VÀ#/=0һvgz`8ktOFwBy; *4SH} =9oWZ.9Y(^$cy+cfgIf-]qLdws^ŔZH"7*?D2!t OmémhrT.®h{"|I/\'+_P8_`)"Ӎ.uԃu`y׏|% v: ЄVzš9/Qhրy3p> yFoehlyX3찼 >`_ s?xYϔdrWD2΁x圪Z.uIjVWR3pDl7f GO@N4 ub䌎$΃F&r!Jv5#yz@~UoPZ:HZo< $+k~hxZt΄4s0;[a@TN6(g\dvbyc%_t8p'V_TE:8YWLrz6Xq_iWhBjaR~8-݇_rMofG_”6F41wCqb1gK߽Ӗ/2뭗MKS9K"rsA!)ֈl`F(r ;dF9 QsX_&yRh+78Rƿkz^`W r%"kș((۾L{UͰ=jFAJ `&7#G)6V4 Ȗ6<&B+1dCwD{Yj4v\AofOظ\h$vN0ȱw@@D~>Ӳ%*V7G؉͜.6etOLg ^WdeK=E.`'ʪKnG9H@=&O{ϲ\)Y/A6if6w(a xnn5Lp u0ߞi!ldb[M(v Y-^yڜq:.dLt4 uItʱ]t֞$]FPvjCmZũ(|ڥNXR)IcK@7L=K |7m_;{TwqW9ʉ[M.yc]qX;r 6Fe?u&ܰ60qb6cGs(Kݗ-+24{2bKjA$~YmfavcF#NhOTql;]ңr"iIvy⽢^f %ƍx:t#Nh@SfO}<y/)ͿQ1smJol?^#m@k*88e pDv('Դdng$F 0 ׾:;Vtg잏xvuot'&Mug>[JY9cT 2e-+&? J oۣڰ) '6O{?>HTq!v #KhaC@/i}خU<ɟǭO m2e' ,'IO;8nL7l"RH}*@U͐3<řE|t `#:7g?\q(o؈R~r+0kq";OCđvZxKͲBtWMbS)]ņCJaV,{Ĥt,9,p%e|>"nICmD qLιKq m>!l he@''VꇃZ_Pwq(P:d70gsk[z:%rwp9L28ZTym 9 O~Z LSE`20zC2~a6ltbG/jm@0^-y`V.Z#UvAt TzB DKAe`'JLXCRhq2$$}@yl`xb,busčkdu{= [Fk%v^ItԴ?c-,^7ޏz1 t~Ka~0n;`23Nl +z;Mt/die0{:^W$`<_6`ZM9SvND)Ybwqjp@jMezx<{X+e'4󪊣iFnɊWS$mzc"z) ]d$TQR[]y_pjI=V(Aci /ldk{G\oژKPq1,X[~J'|㠣M8y˓G)6ny: Tc2æ5zƺCޤK3o FHih1W;yՙж {3η}R4/loz,kتVo=V4d?xWǽ!lR:,AYEM+wy}:n=MU:Stv-nM5D ]-vkMeh#t)"6Θn2?={ysa(xO+Ö-$5d|@qRқ.Y J e+?fc@"v`͚>ŋ~JW[eE'}p{"]du]KVOG~8|b= z]DRGvfk NB΋3MdCǫ.#hW, M89sz}A6  pS ȠR~*H%=Vj \q`8aMیNu^ [[ kj' įG@e!-Y8x Z`( DhOw?ogԗN^Eg]%P4Qw*u8LxgOskN{)wp/J“_ll#[PCRGa3lm똚9Ԯ et-O'?a;;z墭;V>S Qv@~k݆NLzzSK+E* ڑZV/]J hfC5e5h,M?x\]]\>}+p8#)>%ǿg:-1kX2n h4fV2LMDY_4y}G۽:OwmYS _;?[xüa~m` quo%6Q:'7 ).1斧HwoE 'X쬔e+BO;7SKA;+dIoNVzVZ-;;HC%7^wjXhŘ=\7Iפڻd^"xfvq\(#a‚1#qno2DQoP)Ƅyd&+UuPrBvҊ(HFijT]XiBKwW UKβ۽g0fN4' ?msІ(M*Szg˔ËD6pJehmȋ@}$*[# +r`C*'ڐ6I?ą=IV3dLhe%f3\_+jx"jTPfnz 6d-F6^]]q&KdG pNxuqrC?襛]j90e=1^=uDt£zg-շvt5J mY ߹%-'A \4Bwmz@t”"i_H( iB bn.OPM6͞$B}2Z>j<=(~,pgI,x;H@xƁ묄"iOy:g]׹Yy"5NGJufO=g w y%|GPFly *ֶrBUF U@zXOR[jAsvoC)Nq3i] tfOZȳ&PN[k4\Jg`|^gb'`^-W&ud~Ǘ}υ/t^VC;6 :}o5'B[LO; /8f),9_4Q9UٝL9̽CC}s ͎l[ 10ChVM'd\Oo né322Ri5\6ߪgJZи`~^S(YЯqcuMdE jS)G3pbpY8aO@׊'h~וp8ݢް 4~@:}^֔kNv3,t=m+A753]C1I*2 ܪG.%^8Z]mlYs=ib@領9DK6G ;ו׸4eGzө²vPoܓ!#`=39i#]wHFq/H0r[`I{x쨃gPftN]26pjd !Ќh_^860J Eb `v`<og(UA}uжwji0n>CQN"%n4[6ݴzWomĵ]$^4;8eC-5.:̦q.V?43wJkjoDWuwJwړteQusr*l0,#vֻ濑 WPjHunrK2OfM^5ǨLM$ ~ٴy*Vh CJ5Q q^C +X> j`R~ytVJr =E6 vчpXߖO1!K*Ee;\5mkJ9NLM1m-5'bcS 3+K|}Gq.dNƅPtCZ/ghZ2Lmi%d^XE!+^}ZnݒNA+F(뵦<˵1!+x#aF} q6g\7vY:s:U4xUF΢e ,J;㠨^O͓6jwMfwuTp@u-B/u,= gL6%e9Sy/tOk=; "`k}ɘ-lǥ% 7[Q|w%γ.:J>tiQ.[phOdhCw 3P1rK" 4-8aVryG,z{ a2R(m#n_8%:7 jVC|ޭXw 351)>dØB^{xV^/Eqlqp5BX YΘZ N0ŢI-\ O$t&V 1Aqc@ΚyDO:XJ$i?1 Ɛ*9MdϺxUtDh,չ>}GI V $>x> 8|Ǚł}7U [Th{\|a"Wpc'E؆u?Ͳ7 njB ɄNJQ}~)A,n:x}K|r#IGI78[)tޥW\(y X-!^`T>#9V.˔9ʟ7%AupfKv˖!ʙ,7>2/v;Cs~yKI,^ IA]qG܁wsT)+l<#DeV $nԡEGxO#fMNQ*`&r&⑃s9ld.=L@/H?ˍ=0O)zɖ(ϻ̪Lbe.{G6Cn|¯\MA^L<;ehf')zϼ_y-#DdP$S4ik+n$M$"*w7mBDG_kt0P^;?x'vx(æJ\O1ķ:&qaDZ]axuf wpe+ސt6qJ*u6kq9ݷGYmMJ~VE(ŋFQӻd~ rj p 5 y;,©-7FY=f6owMHZElި}?nrROh̨D- IUsPw)2 FKIdfL(gc)WBoI`{JһP iPa@f1/‰DPNk^Q궴JmfW1郝VR?I˱^Jz>;-cśHYcy(&! |X#SjmJv~p;M")OcY\ gРLZ<9}L^'Eh8yc=k3I^ܤ/fSP:ֶrUeIy@83>p5| |O6ŠmN_FSZO>f[uhCR?}6'ߛsNo=Gݖs4؈9؛yl-{2,,YiW]4c) nU1D퐎l`MGR@+v0Gn?%ZE BIp=9~.kł`{2'Ԧd5 鐃ə,'Iڟ n)!x), =lf4WJR>"f!+VuLt¶ٚFboKaS2s>˗wTG\4><8acx+H$"!t L_M<(|,dMF [ߔJiP* (fmט /HD` ^yl][?8s!)P$됻tW'L*d7Gfc8cdޢ4#"躺(.c$xw f Nw1gS_f촢_L/{# [Gx(s9b }N /31و c3j.ӕJ3Gw-8l(LA eq^#lG}7$2AY۩!hRІܐi#cA2~ԅϺBgg]9g CS+,%Aui3h-5r KH]NㅇR"qx aiw>G}ެ tٖvGvv uZk% ʍZ8Ե߼7ye(i),Df:ʜ;Ē“-NJ˧#iyk6GJNa31{-~||bPdXitl æ Y;AL Y@|4qtQ+;U/S𬯼k:ICli(P'a(V# i/)™pn7YO˛?8[Հ(`U!b}t-vYo} }ep$p-UEBzgij'=bT,SHUUE<]\;s1!"NF6d^(~4K/6 ݾQ:X4MV`;Jjx4:0kIo"Ӓר@ӥn 8Zz2}nق9Y./]^"5- 5ZCjTpbN 'V.1D$` _3 duԃ(!?`mÈx֞N:cRYQ:EՁ$;*K??&E*Nݱ⒎ Ƞ 5R1WN(k0‡ЕI3 iBQP֏R(/=dkF'"C2A|LI'6T6TpBpF [Nv&< 5 iI7W w[&ƕ(wLx33i,^vjۚ- -zRxͳ*1L ]fun2^JRbuѳSA[t-XJE$>u:­42V:HX ݬLF-n"zd FUڠk GEld/вC[`ZMCigFv?Lvj6RI1G4? @ڎ:`Hӏ-+K{i dEoى(8зD αٽLdW 'kwa cW., <}{'=ܒ>bߥ0iT\'-9Q mDq,S}yBVGx1鑠rH`;mx5aXdprhf7eyAB/L;' RywK$(38DXء&Q>D6 Jత5g<$MQpӉ`VJM ӑNy6vymeG^ g$|xP`=֫y0oFJw j >#/'[VGӿ0&oݶZe#"EPCG+[#@bxZv;*ŸdA S$[4MY="k۩l ~T8ƪS* xLD5˹x]bNB&9#Eg|l\uWf}3G6{Q Y̊H/A\CM)祏.pht2˞`[/rS#c{Ne3hAT"g_=lMPʮA' Cvmw9$t|H2jQ BoغI MF#v&1 Iujkl#:Iܸ}M:zMԙU $ճ9 n *Di( -GvۮaPeKYKZҹޕIB`,^F>9Ĝ%#Ȉ3hO;5!3ϻ0a0m$0ղFc79CϦXt(<5#P3K^2$:_ƹ<Ї%Ve͒b)Oڇ7<.pdbԥt4p/87dgۋǑq8#Y) w)yY/T>@٩ދO%,6n;oj<I|0;;^ =aFa mR4$?M|Ry_ Pf&AMv' MlmYwԒB+$aL`'k?7&}~AΏtaNZG4zzɖF9o53 x!DN am!]F@_9Yy {NMxbM7I4_3AꪢDwMBfj f':/Pu 9q Q\njfLGHJdž6M>^%>ltYӼL_Lβ"5w+s OVL y. +G=C)ͿOѱ4.}HHODSE]u6:=:e tCMX]jZp>`!uчy}"Z+ѺHSf\*z> Ѧ-9VRw:Gy~Q-)\MV:.uÈԥ1YK SyWyG^y'Z?>ǥ1?. ?@t0ju C`<.hw=۞QsQqGW|pJɍ znX͘|% .H2U:p!m+B2<G1v]|r4ۡO7 JşhX޵u/3[2T^ H~-^, iټ¯ddprFkk, 5(ߧAl:l<&2TOROd{>^geZyoqJRz_[xWjkښd/T!Hbܫa:o[FX&܅Z8-ϭ`>`.~tG`x{xJqRf)Rv囎.} H;nۥ콷25%Q &I A:l/XQ1/4wV\cӊ5~Qs })%K^ݣ)A&Q$d="ro;7Zc}M2NtI]v#^/[w~6 Y@!N M/q'u*uw.rgz`|f 8Th@dGվ1̤ CFJέ^r2%'Z{DJULP+R(< PL$k&$KHA7K`CZŖ °f8S9緮yo0jgL2 j lek+l,Nw aYC3kKIOg_d؜fȹmo+Ngn^-~jO?x;VSi&fSˈD||4 O wG!If=OKJGK{=@XmǍ#ezY)ef0)7[/Li^ o_}?N^{z Ki?5.23ke7t 5IK#JFmQ#/Ru`2ѝ%O].)t~JKf:%7KڹR;Y]mdUU|׃d`'c&\T9 LF:&W}M RE~m)|/22[}gA }e bZF:OMaj%RIߥn D.xy_Ƴ넑YdpI7RGPʗ~ڞ;ӿP@琒thǃ$uy]'L{#`;pJ7h8~EYJrvXH8&o]zCWUfqls'g3Ϯ)?Zd)ukLS%V6um!3sWcYLZ/LJBH'Le=Jry H1vrPЍ!sgnIC9A H֕F7ɨW#X:yhOa뗏v:Q\A7K#jK@p؈y&d͙LC+[Ɯ&"p5XoQ$`'#)԰b0!s4ҿ@:G<>effvBa ' g.lHS2wJY}򒯳y#@hXRu|w & `5}$'dl{K@km0y" <ڏ ΰ+8CjgsT#٣[%n5Ê=NWf ^] d_P"V.2=ɈmyY9{V8G@l2 l Gp%B߹e0"\̛NH\r[e$i_' sbf +F1\z4x;_\ !k("J^=6-+֣^aW8/FrP|%pGSk‘X3_9~3)\z\H2hc&7m[t%K>(`9 V8Ȱ;T!V3;GkltPg>eyu^+3 km4ѫuw&U繾xid5V>p-)f)4x CV=9J_j2l]O ̺g1qy7Βud[NGx#f R;9p]Reg>`k E8IlN(ȎOحhV-tm&$=J'6\EZJeev01zG09+: NUYzCCJΈՖ]ȡ2'Pw1ͦH3TT@{>r,%ԾT6őN/N!2͑ړPށ谦9Hy+Ǩr-+w7Vfy/=1&hۀhl;K _+ESfٸăUPO5n/?xAn ea(nmݢ'J'RBVi.'.Px{ NLg9T'"!#U]r7.\DuN]B9JJf횧fϚɹ|u|[ v1+#*) N̎*;kVw#;ð;s["άxڜI{h8jhI6=Aʲ1lcê["kPa,Yn;ªlav3>M#wڢUE~F%CeTs!_L(n+M4&Cv R,wug4aN{Is{~Ykߨ=@@TTnd4 R?t#+jxH<^',#> @`׏}w&rsiw DBG/"(e;ֺl4[ 䐳dvNӓh@ 53]3NG&tT] ٤1Xi~kn&V:Y9;e??H Xtd6Q*]Q~cg8VFɢ`>,KO DNjJ鏶))m/y~=)Dd n ʻ%R'.jFcM, Up@\3XhKxrԭmt1sG{AO =BLZxyϊ-Wޫ:!hT`GUOLCϘӞ-MCnalFP19@/lQdEvYi|f߇&nL o)=Km̏}/22{>pd)}a;th 2Y?] <Ӧ<+Y0FD^ 0ROMiKdE<J|i'cFtiܒ7 5g_2м/?$I2bbD4DXi"PЉp^`q>tDv%u/7wԭ- YnIqOq ?ޤ~zO 5/+_rx"쾻EXҶ;ީ AV8ߓ,'闇e15FYŒY},+OUT،Li$|B66l |x Dem"/buqT R7$fXq2mT7ΐb8عY$gju߹t"(^z|[|ݿBx j .#""ΏeY}ܪgah-^ڡ:i4z3Sc!-5K3*j\Τ}qZz6Ö{elx | $>=tޝ;ɋNߤ4;֤n*^ӹĤe%5,ɧ=I avqK9$KʷeKDV{ :y0ZP@7iT]DV\6B<^vBsdsxwA>1[ C*sK#,7 PA<m%QR6n%K׻JJف9'M9`Sdn/J|F?]Ѽ0p84s# [(ϧJgOG"bC%㴿]gC1פBgGAW<!Cp6:sHҰ0|&xsq֟V$qy?MņCA5 9E>Y~ =}:WU,Ƅ2z^5I8SwT5IXJCYWa>W2/%F`ON 7 C@MvW媕~ 4[ ˜)_Rt/q.TXDs9g=+ {Q8O]Yg"$(1Q]R|VPf`9&x:dga->+er ! 8OhLp|0p`Λ5_`8Hx٠+e |=m Z7\5b'膜܏5J3̉ iʰ楜rkwypvha[HU'|q;f 5Ȳdew%Lhԣ  |Y'{Zˋ8XѥZEGǸy=n.ܲj#\G2P(ޡ87T/ax H\Gr a+(NzB4j*jWRS~=Y72BBA,G4 5Rfh1CS]!YwЂXy3k.h&GXwȣCe&6({5(CδӖ3"*H?MBƋ=V"]h|!oI%mR-ҕ~o7J~/6),L'*4| +;9v?2!*S1q;q\-q)Ma'wb蕟JCB ]z$ͬh!zx;qUzš|E^N>5jo b<o}-y9^Y`% Nފ vhqڞTV²{C*ܿVk&:tj'cqLi gzCLɞXkHF}6`cƒfvjv=}'W'q?ch$^Ⱥ9 C88>и2&-v\4"}75W.N_gMMʬ9HTCb޷=ؔu#oUK$e&7炕DL{̄w0#.ƾVu U&-EQy Hyj{3{ 81eCM)8PO4woQ49ZekКHf+zYuR^hA;$&i"s J TF Z'0V։P$XbV!_u:٫d\U;ߒ/5wORVhHp,ԁ EPޟ x Us4vqy9qZ3K-%rH? +wu;$L*߽pfণ 3gs̒ʣ=Dt]ɔGAi[.2mH{5ћ5AHRu״LΪʙzmLb.uj ϬSvW͖+Wr \<-%¨Juz" H4\aqB(TE@VҰP#m.GO'jKf} "΄2Tizbmrdz~RJE ϡEٮG iAVḱOByo]*5O]8K$?,p'<0tgl ~N)"7uQ&p/ nJ=Z(Hީ*hR"EZ@wrK.TEb1h4CGM*: 0DB^#Ij;E赁y9qpDN9*&}{ߠ0chf;T官z,GH]~KG2GO?4!^έ E~lV]CxJa Ic;@ܑ 8c-53D'B4SN^vt%”DVvnG{/I^ffu@Eh,%<oVPj1t]%P*+@\-1^u:uW>5s5&`jIOyF. c ՘UǨ-#愆2M7_'Қ\&qyz09%5F rra6B|ǻͰ\dx1(Dw@yRlItb4\p@ME0`m;>sFͪ Ġjh[S"2ˑ}]:JqX-`Q\Uޭgfvsk :\(` @n@YL-Է{C;=`;@"qe H|U%2$=u`]eF!ݳz_\G yXǕsf %|g.Si y,UWL|V2S ̓Gd7/X.( 0>6sƲ&ǿ#_egfs$Z 2g~9_H|<*;pZfMY>W}{JR:GyF+ǒW xIȥoP%3<>Wuc] Cc#:ST\ x`Κꤱma"K{ ?(tF) TZE-\hIyqRTc9V IC=(XN~LSHHcyH*h}5rĞn VN&$98i?pMm^ p'R& gsZ'{1EuO(X.{BW,a8ͱPTu2r%熾jC+E3/yɧQκ{A '^PLUȉNw2]Uih;ί{sgJCU^gCSl8s>}ZS5ʁjTzQVH p r& =յK6`g M2#}t`ddboXѿF^.{4o6HǎX|LN:Ҽ,sѪCo |[e+(i#sW 3 "P>/wǧM蔀R n1jz[5H$wd<mΙz$yVoy|`Ul1xG}֊FD nnH=>Mj5UG 3~8eƳI;;B_2]{#r1`93c`v0/;ڣJ$uyAeFuNXk@kh7m&Ӻ 83`wu@<Я"y:x#Gg:A`f(M7!74@L95mڒ U4nbJcՆ.ikV 4xX]_e{*+;fD| e1Yb1y@9;J)Tn^UnWdmVg[cTf%E*۰ZIzրm KC:׀c@xVF?Զ(6/tc-ͬ<ˢozIX K9{6 74]]bjP>;u̾  k [J&o$<ҪcIbw^a5 ~tS]&&[O v . Q(ʃ{-N!Au_['F넕8ou|%Y?yOKA[ 5wQڑuo1jώoܻ:b>:>+ NY9J(m}4,9¼/P2gsP!W`i3v\\@ViE< Jb$8UUoB^@$Pf575e3/<[]00\\}cpJڰN=CceEO"+/Pг0hYC]_dUl>Uagn'AXRVanxN^h)g-H<7RBWڸ*k H(O]r}wd}d58Ww|u5VMC[a]MƖIl~'hK3YQX؊/o`BRF!b3CD%eΒtʞp \p_"?9;"+{&N4x~7mۥ9J/?24w+e |Mҟ +@ m<śqkK\B]|4 2Θ14 Rp'zV3ho+\շ##[ZrfY>?J 0Z6m`Yߞ'TmLrޡQH7=t0+VfM,^N>86wV`Ƀu~&ڂYR=1;S 6oϹ.ĒKbfx$:aͅ52JSIh/kucd5`j/-ש)G&U>0#V^dC/.yxaF;D儖a1|.MWo}7tҿXfGFhxp~ν\j ?sٲ#,9]z.(Ws;ύs눲W^-RJrZ̮&"]={Xt#U9VdQ1os6d6n t*zm@9?rޞmk폒3dKZYt>ל77 ok;z#8x'Lrڎ{uێ|6%s˱Kr\'EnЄ7_ouqW.#ʕ3[n2uHkfބg)6S >Hi<f_#9<_uV_諎ʧ[>7,*Оd\*ğ4qS6R6'kU u[-1~ eYr裲flpE_ftbY_ݞlyѾvM^"HmD=;7vY#Տ{Y!k5iD`l&爐fk~lӇԴwybZ6os*Rlh2F:Sqv D .sM:|LU)ǫkd[^ mN'2hN MD<1 2tZ̒;r6qǖ@)k9*$7TX#ۛdv|Q9Α~I(AsAgUFP״}{pzWcPVlOq)Lu%BS)S`hDԜMk~fpff+#`{z+(VV}GeN܆Z3rvO1|C%,w?~\%AG htǛ|h'+1JuM}hM[yt|x28uA G?G.z/+t=)c¬Pl81!'Mf=MwkV]϶wHr^AVZtg<] uRTz7dnc6fKb:YP֚3ѻ?8f PszrwE9>HeБXOGLpE#\g [=lӰ*|aGrWܞ2&8KJZ'$ٸzfޗ&/s':Z.[3hi-_d_dŜNW;?*N"B8G4{`wԶB٢cnz=kbe!VhL܍,Th܌h5bBS)t!8cӪIaE\jdJX&e){XeZD"krYxVq"B+OZq*7^BIF??YX:?ƉUXR'AIiAHlݤ׼2ʦLܨDϮ:̆ñiw8>jYQpreX,tD?]0F\b䐯og!J@~H2V֌Yj_R9"?bMޤhHxQ-z05q#*򚭹+2iJ6?\8B++=PC,L۽Vu4`ɒ;a~ᨷYazB0YsGFZh tDV8tI8*pqx('K 2g?Վ#iyjsVKFdu=&Xx}6&i1NPJ=b.bVfL pk :"k\nFl_=y'.KOxM 3gH {&=c5)&ޏn;U4tx۟'V/% V{?)fF!̱T򕯗ĚXcYZT˄7"! ;Ӣ_dUY[O 7T2G7M'dCe * s*Ӣq q߈uL]d2R](:y> (ȭ 8rf]zLJ# (@'xOalex-ţ]95hРa:N&^*KD^a(ǪZbE^-+>,@pDF^}|.qv~+[x=Y#TuYzZ iuG(񧣈b?UhR?@p c_}Xz9_1)`=]m^UB@4"a1˞4ݔ/[?.Dn pn`d{vz\>&~Ƒ,vSz5,ļ~X?e6 d0 ʰ6ZSy =+.JM pԻ߀cB$=bqeF˿R˯ꣽJ3x!X g$$ u 1&L7h {;喲HrI~f^(}7[e_P!'p 4TCƫ_6A/oɚdTD+y7?OjF;YʉM?ȺMd|K2YsB//~ü`B-Ty]Pj3p~Do#1?}FH6&muPB͚j,>*[X݄Ji4GUvM+U@6&P?0<x%4GFH2MX-/trD᎛k{ץ,  \֏fHT_0Z8z-n>Ks^ ]/o:5G۟h9?+䢃h3rdVu|мyifGŤj\淢O9Y ;=,/ZexVTlQPjx8qe-In~z!`ÀzaSs3LjJ%񃐊W;kQFN+;[h9Ӎ%t664L9L9c ^нYg=/Qv*w&6ZS `PB֌ف ɲ{ t#; xNՒFr{52hM٤t $@璹hKzvԏRXqy=Il8HUFLVĉz4RR9ͬ1#pO +ex~GxBU0m&SL@zd3MKgo|PÞ a%cuGlm45C&JUy.j,봎 ؙGArZ(cV+Q"6hʨ<\%%rұ ҳJϢ?'A#KԪ &^oCGku 6 2`y[@dlMA2/Q-Jiԓ$6;a\!cWn! 4cUfUFle{2?RH6wܡhu,xi>#`~ hǧ!y-㾋6o;e3{e3*poӢ2KR`vј"њ-Mo4>A(JGnTdDZJ 1t&Rƾ-% XP "T$Jٚ[0n}*MneB_DgI{'zD%3V>5Eٙ6j;Ԡ3 4'M"զW/͗r59I8:IOq`G/>:ү0tӾпlҟ5[Dn'cՓcQB@ +L N`n(=Kx bwS^bggW#tjXz8Vp*XZ)\x_;vou. +7[h< hTlib"9h^nlH~`o,2&I+vϜB t؋]b4T4~Ь,âW:>/r恓&Iy%åogKzO 4ᒽ7ży UovV4.96†!o!r;m6{Z ()klq6@qmvSftY&6i SIDS@FXHiv!mNĄrOUX{ Q,eaGTgQZsL6r(?iSU P$kb02Q' _YoMo6QYf@pL\İgV^⨞0E= u2@zAk]?q^t7_Ŕ\ax%@&po_3id0쭄@=OVIFwz*vk@܊SYRÁ_'Z&@ؼ_҆F,|#4sKe@sU,;-t0*^]Ф~ :J5Ld_5kblTaABZ-D\>E;J,5#沨F_ٹb#& C~OV ~Ɓ%%v`h2}e;f I9>Joؿί%dLPزBYpi\ʵ*Dï{5'iC!&;=Or}^tqG{XR_PL㻮X`RW;FiiX #|ryâ1Ig,9_49BfTev]ff3o3PpxZ&Nn7If=?sƝ߫4ղ C.lwc:D){̲tv6  y-txD<#Q5&zxɏ8zӦ ,OL$玷R?? OMM}{ٹjI;lRN8#)qoZYFc4+LKLTGWYuOg3yEђ\A|XAUٟW 0G-,XVl!LyDæJÿ:϶\s;O"4$H]GE!O/" ljM骫-4+Ki˜r5 u5°Ġ#\v&:7#2莻^;]MWzpԲL\T;uEMEYag eƕ'q'5oP*gF[{ݴNJ:(KhGM& nn?ŴI*lC'ȓLN3: :mQZAl *tj4*F#% ;v-00\,Um愓Tx=ݫ^)!^#O,&uAh#WAO( e'XBNmD3d'I>l>©n[f=@a֘<ΜqVEAE9FC:0UZ_0Z.JE;-*3gn Ws\Zk)Ӟ4$6bL[vɽ&9nr5иZ+yF7Mp!@~@+JLH3}YDr + $w35N'EMC]Temb'M B( "m9Yԋ䳇Ze,2E ],GΡYؖ5,~TJ7HNj΍1t^ɢ M>BF(LfYup8RUe*z[yxS|TLP ]ސ)fٍ:@٢kB0| 7^y0Zs5sym" X蠂<gBУCf dM y0 Q G(3Eߠ.ne`Gc#:ϕ jk6هR4Av'O,?x ŰZr$w|d?jA%KC؋|mq~v%&.<;31dg%2. )ꤋ+Ջ}ՋS#msl7G]шeE!T8&UdO3aO 6ԓF|{:<>?g_GP2tQ0束mkl(4sײ'.^m~Z۰n ܑ;J.T ҄lR'iq1 oZtP\qQ~;ۖ~a,0:^Fbx3-I_ Xndf48Sc8N̹)lYw3Sc8Q4h3x\OZ?<~+'H 0ERN$=mnW]_g)90{r!9?Pgd0Vtd_ćMzy,1a$1q{)B<̾1j]}扝Odbl" CyF6\'r~Ύ ېnT @"%Y2M%ZʎKGan&4É]!H$LuZAz,ڮ~,8n~H4h: ['7 Gܮ05!'-*ݩëde)Ckn ˔,, feXn-JCuQUuoH)[t'q b7]wJnח΀:n(}1Ravn-(,\/& &8Il&u6ر) E2kG:km]9,3)'w[ VAP:qc$a|TSXU&y Me'4m(j&^e!eU_̐-M2ve]x-*{y$ozLs O6U֖E*3qxh%3^Nv yɈ't-)cf.Uv,GC 鱧 A]Ȇu&tK+̙lNw@`=pxEml,LξSew7}uuis@ӣd٫ vF3ϤbP(҂Փh* +X >@?ɜa,%ӵUbdy" 9=&6NƏG"";nl1fq8-:`1y\\Ҡk@0~\dʎA)*ZL3$ 3]fgbiG`|6)_c{[g 7-LLA 1զOi`]̲VcP[ٯ 0ɅG+m3nƢ$M,z\ 6TkU+f[ǖ vc04WF7͆*4@MyУCG.=PG'+ܲ(6u-є=j([ SpMh5{\_G>YKRM]hae33A-`E=L'p6-.VOb\!#% wMq3ػ?˹/L$J" q>qq%s iT3W8k\[ѫfrSQ$1BJ7 4]~; s|()f3C!teu%d\f6书0he;HeQs@PY@ޞrYQJ݌ R$  nZ JT'Nض3$:fLN!m .gX''fČ(#Y4RЃRއb^YDo>#ؒƋ9t,z4)OLw$wu-뎯)N5* 噄sÒ17bϾ#v-hK0*_4B,Q3t}Xɱ_"27KM6C2J̄]ce~~g%Cg}@ڕ# ꢙ|wEj(Hy^ KCtǸ؝CzԴqm|yDel̴ {6N4%Н/QJQtX7o޿(K<^zߙNE}ѸY2ӶU4-"ɀԺ>{zU(̏uT;0RnE ] H>0-w-Trټâen[yV?boRy)q]I(bY"<@t߁ 7*nӬn=Ke<ʖhOS塡C}ګ{^g#à9dC3`h^TaR ~8mDg, sgun %P󵒭uu?{t%+s9с̹' LW=4:S(g)홳%.=3)sR%4ߦw=-j軓DDˡfցs7jiArP|0ΙH.LugCS>(Yl;D9I@ rE+l%ߡYT'CHSCIFYx`K2mvby Uqb`DBE4ܜ#0EgݎVDhTNCXUH̿ of;e:h2t/p%m_ŋY{ae܄iwӥ}o̘'6op$+͇Up^Jc3`Dzlž98#?i;:m.vYKIkW ꍌSb /x=KٗRcB+HJ$s BAI5@-Qչ_=e&Lev/SE]=U<'ז!y!m` L6H$d%D/4.Unrcq@/G$pu'9h\~Ee@ɥH鮊o"$6 F08p vxY?]4̭D;݉rŬ%B ;<|P,{{j$LPf7^g4Z3(e=6q*5֔)SQ:[cY.G˓)N- hĸO;Y2J=b_ ~'1Ok{+?;K}OeبwsB0B(cn5 8jOk,W ?LlMՇRoP>a^&iaN?!^u';V/(bm9M=>dȺeCH )`nz(ٱk3 (#[Δf8?AW ȰyɪkBΒcm|}je,T 7EyXSpf=vU QJR3 eJqX\d^I5Z!^$D(o,%&;OO(/cn,}|~ePouv"aP_n%TRR~;DwW j˓SZ$?Dfֆ8lۖbHp '7%>I>m;x7[xl,'9Q#,9\ d4Yxe_v@_5FjdJkH@MF6<,翃ocͱ :hR3 zqefb˄r_ $j85k&؋oNw}|l"vAPA;*l 3'o(g,Ar >ekTVT(]ܶ`Xm'y&8iEu !o=z͗|ȓ"Y`aL⛙w{yD+)>NqSc+Bv@m✨ű9Ńi:v`&PMyH=&aNɁZZ]Ym7X\ɔHwٵ~ ׇ:!5 {п\ޗKKӤJEu(: B@D&.f(*.:%!Zi#8[1wZc ) ~&{+sD-ˤ;&KG7HiI+g/a|(T^a'͔+V@?t~ C V1Wa  Sp Dnh_Jx:MQ%ӍĦ1l4)tuKED 5w5Գ4.R] / z>$ϾoRG< 7ɺPcv-Wbfi: [>΍N[0ha\v@K nyTץK胧Hr1JV(S9R՝!uIQ v~yg\ɖ #> 2?w w<6Nj:"8 VyψQtJ(`1elZEz>d-J21?e7~K&NCK̍˄6%"va_'t(UXy%?w,Ӹ4̜_6>FTwI9?lI"f KE~6Y\´Rƾfo-lP!aM2ǤZ>7`+z||;6 EmF)Xa3m~#7R Eid1cFWԘ!nh`X>^?[}d*υ.+D % 9s.$o`W5Esqh=Qo,fio$z YYIZ[Xe. HV]e7!:SDT$IZ\:mQʈX7W#L4q5k-晌ђ<7 qDZo/e ckõxo,VZ3f;ݒ&$4>>xG"܃6T!x} 0)ߵ]h'0Mn YT>Z{.>eY:cmS7UE%*<|fVtC =/bU1~&i{^KWXgmBԑ0l,p-{h8ADW$)`; ~k:5!;$w390%eVEf~mMCi.n0pWtMsLT`w fKʖ}  ʼn /#LhBcӀރ(.={'E6'ĺ1[oM]nξY nȂ8|t"dWdN(8B:e :׀ˡ}DK4;l'ހQÞTՊj5| Vb"m-B$3( M9&Q-dDߡFi(fֿ 5Wh+|q557Oɲv9V)ĸ7#"0d-~5uZ /yxe *Q.4*@6ZEӃiQiyT.ɘGlwP yV3w  c -f ˒z\d7S))ciaۉ/W.n}xt NtR.G~!.!J:;c-P<(%*XKaˈ,s|p,cƝ8|qoU .De;{.rb0RP$wlDJ?xt/Kny>t3vt\w!O26bOӳ֖2mkd7Y01k:@Ϭx= (*XFǚӝ,s9[Taܘd_ž7mn: 'k8 ݪ.ϛdnJ܈؋i=4!6nzh)暭lmh/kXtx( 0S{ ;>6S>4 -|qil,4OF!?2s{Em$ƫJB2~84x ' d%Vevx˕C˪xl*څT24|t>\o$壃Ģ9p2NQ".̖uyS՚}H x!uPE)>to|ws ,a2͸հaSe 3n2=;8b(9x:홥"p+]}U*㩀!qE,ai6*ϲSE4'rSLP}Lj~o!ƮeYz <>iJm${V"މ%wӥU$?wL1E"vw`6u>R[eƶ!-5R{_Ϭh+jMyff\"f'esNG[ J íq:0 1Xk&{x+Lg n TH6K5ɛ4sL.NLlLGLTV J4g7ɦ0\3aeT~ QHfPW5yB#+H"a |u5!JLVKbxG f*l|p9bBC/xB6 u%gJļ/`BKܘ$#^aט=Y(-"q~C(|\Q9LHOb6'qG ѴNTr8Clj+bV+P0F)"W*eǺ3 ؘ\om:F4~eMYZu@y* THWA-輦1nwRej#K7zNǦdHLUFdpSvѤ՝ѽ\g>pć}l&* & mP.ݿr@bHj׳lY\^p H4}Krc̝gwXh$ʏgd?7xCy[%z],s̋R|L ~B7-݂U"zܬE:+B,jAos5ɚC4ߟ" gkiRa*[gzZI7)q*_}Hnjj+lO+Wx tJUB6F"=;k76b!91GcG!1mL$oO|$}ÿCί a%\Vǒb0ÍEG+jd21FOM3E`&0aWã/*A ӠY;x,}([Y%A)e3fH_Jc'L8.we7+(3 mŷZHA|HbML8o]f fLN,F>2ۓt?_g* mt]]WoSD̩f5MZ4uB#}.AP/^73Zƛh> ob+Q'Р4JgZ֡Zh e& RJBwy<7)пBblAoԤfT/FkS@bKܱ E$Y'`/Bx o^B !9Qs ~-=ECfCi(T쾦|OT`Gbq40b}ŊAa'M5} 1b+GΌ3$ĐA_06Bp=5i#w̬q߼qY5m[z()>APT:j7 = if4iQànnwRs! J]_vӢ_ǝﰬV۹[f)\& 5[ԕ@L?\ ?fm=Z\6?1!lls/0KCa6,`CaUX4JXi5p% _ct/@Qګk ,΃+ Q0EdpǼgJ. jr5WZZvpLi7q̔kpȵc1kh40 0[A5@Ȗ6"C7h[IݤQ/sƉ9щ8D`6<2qt&~:ccFs77j8Q: T~jNM]6vްKŘcĒǍKwe:@U֌xou.Z)P:SW3nf-/oa+Z'bðd&1!ﷹKzPM7 4 %/׌I5_6lIsHԣx=Ie-e. ~/x)[[O1PS`=Vxg)iťqMTmA˿XYXiq~D/rG=2!)Ţ}S?eӜ300;~ѻ\Y-d-:Qt :LjRZvwзWQ<ة|as~bds2~K mݰwUy ?N'IMw'ծxtuU|%yͭr*(!7Q[E i\cI5e')緀m,*Lsn`Pm{dL,rFN^cd[hC "eM6˴X?9e'ș81!6$[LSL9\\/m~hN'(17x@ ^MD3vV&m5]K/-;~! j26Y~:ą*w MߪA\yvqԱF7B!icɂo!1oM;wt}wW05zL7]˺f]bJv8%ٌoPX_^E2qw)G8 m3琚8,Fv'7m^z0h?e[d=6+̀@p5cP@ĝbl::qTp ' a&KfFq#utͺaJ3,ޫv6AbumǦBZ:3+0r D -%i m$9Hrn5'Z4o?6GQ}+'F, p)GYiTþhmL&D W_粌P$i-&{܇i-]])K5Śd"Z9i {C)rCMlrImˆa;oZPE#Hww1&1iXԸ%8 gCEfs9(:jĩi\GsjILFN&@xoЄqAvGϥw9@S/1tY8&̚?A̻nn\QWZt_yJù|k;ʡ`GL83X8&F4 ݄we y U zvK_RQ?w ?{hHڴi)ىֱVPh;4ԗ =2U2dAiSzpĠQNw\JRE{*2 .u'b`UG(jI.o&SvDN=v&޻GE-@̈́f  4^vtrsW7;P{jz[gfPHbm쳏p54/v6{AWZ xW=(5e02& LZm`##c.Rc $c/Ѯ 0qp>w\*u `BU&PÆ 1Zcp]0Mm\Y&=g )cɔDA~t}q$qbAg! [2̔Q8t4s`'i;>QpLaӹv3uvDfSW[(f3ш^FZ:;k(Ձѕm̴-dE 3,gpv-e_w^N湵m q$ mb"E V*l4N p3Me]&7'k-|ɰͬj70&j8h-*1`Bf+$w3HMnOQWtMMeyy2Ƕn2ŗ\+?,"TB߅+QZH]ONwHк}s|\[4(O;,i=<:WBvh4ҞGppDxղY翱Eujf!<^Uq &b7+ղex'LN*%Xm`x|TpCOY d=xB :'SUFJ6xP X|eTL8b኉ jyx-}XA92A6GNIJ9a}I: 3ICJ5p׫܅VVTDc<:&:RT4IvU6Edm^lк׮)%Z'sj/<;*eϒl#հ_|O,L7!He'fNr'tqn_$݌Zр퍘h!Bۋ4ej v]w8ElN 4VKQ9eާNL4WU?y/鳼yL#j~ `cf/,Z)*g"k^z4UX%OچuRETc5on}.r腊)#t}s$zc/x`OzVYGM%I^@xcR^dn骖eNt0 P/*WG$VkI6%Aj'LJev%Xt&#h.~}#j[8Um fS ߪ.>yi7x}Lx{F>8jxXYݣidօX3[~q/pٛ5uZBlV5Lݠ,d< @\mXm!VȚW1{t?* ;@6B_U~գ4{S4T5rh7(I[:$۴2.Y\Qל(jj'y|fM>R&Ft1'gm J\5+icQo3̲JT&ӵ%+wA2DF8"|z* 﨨%9sF'*< scfqq|ߕG.M?Du6C&O&f"^Ds{eƚҰ N{i@moX@zA^a.ܗ'?}yбsH T_7$"k J T#+B*Pi&iPX^E;v c~?8e=~@ۖu 26LR!Wo飜XS M4ʲN_[oɚL;\&b1gůúvS4KI}Y# <}1JΛY)fI &f媒9ہ>D+l~p(ksUq2W1&Uwt%9Vִd WU?d&Fr NQL"15 PX~"Khr"@~Sa#D~VC_Iq+=[f0Cg)O7bzAo =-m&~{c~o")M.l2w{kDvaL|sGYI#/Hy6ualZ @MPyI'lF 3T)Hn)oc^lE&4@@fxשe4)rO ČI5OTʏE;-䒘Uoe =Ӻ0zU,z[BFKq~OtdÂ4ӯ9-dah09Z$u +9RT;/l# Ϙn&6C%yZG(A6 \lYP) FetZt?c{_ 2AzL- h /mOiAILkŨ" U 6q:jcR70(x02MMNϬQFè֤u|NIz4ҳ[fM,rDr-Ps3o<+ՒgOx[i,>͝l3`@5ED|c(zu 5`yBk8C$̈́jy-mʵewsbKT8 *6U(Ѣ3_ʎ,'F 'YX&#!cha[r1|7b^;"&ьKJ55/Gsɡ aw2"=sە$;|YEMz;ʂhCe)H븝ISژ -GӁwǖG:mމOV'lCn;xKf5@9gwr|_١B,y9v> J|[( kd"['o(GS"-KLCD\Y9se~:W{#~kdVB=x.3Kx|`?D L~QtkI4moR#wMOWLQCQ#1 "AYk}>POvLnJ$H͸aAnj 2ͦ4m;A|8F7sf)N;BJ5ϓ'Źd:]+D?xws@x0Fdzc1pˁWn-Z ڎ{Κg C .A\G (}Ҹ >qxJR'H t8.8D;: q͎nsIPAY9@IuL= ̽de9e@[2=2soXo=S)NĽb{6P3\x|[k Tt,V"iNv%WɮgNvL3';Ԑ{ em[&e4msZҰ[<&0ʡ<3ew&R]Jfyp9|]ZQ84 Yl_p|t4?& J`. n!@2n6 Dj } ̰\1Q"+˄yA4#RgHM|!fcw̓i[ 1GW-L̶ܾ/ cXhg֬Hp^T8 )dJĄ/qD*;cٓXVd|O,5,:X( Hd_oz6hs -~$ڹ, v}-y{W, t񡴌^߱MM$;>W4)H*m"}6aO4Mq/.MػMhCCes>Vj"2(G|k<(F&qnq *+Œ2,V \VC{ac/16E2>vЅ .XCXVG%hJ@umN6&Ub0l-QwN~D٠mȲNClgQ>ZlOOg<`4PNGc6}@"ggydq7AE1wOC8PY+\ƞ\ )a[su#ӂ':pvgxt'v[,}A{1l*я'ooD%%[BTLt3qF4Z&HZ uADϤql<;.nz-y4;&d:-?KLEJ2&7*w3yuBBlCG3gNK>!F ~/`ug3#Y9_DRQ,}2tKtНF=M ;](J< UQ@`!4up(HC&~tpJj؀fQ|<${JTS'}z DGq|PpmEv\Ǣ;06|$e%=~G2D+gY9- O<)Ql*$xFlVa ҳRʿ.Enz*4k|y(gsn5O-+M+լ|;HTW* *dl9GLNGz?p}LƔB;Nd3m=qO\3٦@A uj^j78}uv?P I2NG1IX*0#ҩxř_Bl*T^8B3V`cµ*_O@ {x锽1i.}MA zía3?zAsuF4Oʆ'T,sŇU4$0?}uvE[6[VkjEQ5sVX+(hҳ֘#Lm*E%s۱ gUu \bM^˷S3꫋ڹ똰 pޑkSKT s@]hcm- J>K4"^+슃5_0+UD~\:HV1YKJ=GI/H~!tM8h>qfJC %7Ok%,eex/3ҔFJaA#$|R-PIof-O֤Raz-$$1 M./S+4ŚxDwd{i ad|Hîf U %_G۞_RCֹj;{H~vκe=_Aޛ(k62_E@'cdh5>uòX me6k&?7N8 -t6 M>B8鈳4x1M*M<8>Cs (#>hΆ1cCKx y?W,р4@*v!$+Obfh,A 3jwJHw , #pˢM,?d<Ӹ[)s4I]/":Jdթ"\edsSN {hCo:BАT5>E5$ gwB.C}HgSӹG cQC0BH?L\`I:6sl!n_>I'"_=[ori]NNɦcɃ6طUs ]m \ǍưD2 )@pBN7iyj]kG L1x3[laKCDNIz/w J#&-;v[WԧvDw.42^PZPڼm(ȟu,յ){2!%Ps`QFdsOc2OUր^crɯ,U^(|8Mcߞ7pǨnIŐGH~08Fbr5N!@4"He*0A*{$3٢=tkJL%TG !VB|XpW ub!.]1` d8ن2orD,g@օⵧK~rfg0żb>T)q!'!l%BХlSyT`?pUhL6Vd9)ڕTn݆a{d.3 ńgM5ԛ=B5'w8Mn>D/hq9 J#4;/$#4ma W6qPA8wkEWOiAFƃ[9)?lW(:{. p5hu.2.,C7աjv@\E^K~W =R9L{.6R3(̱:8YzۅQp#K.T8˄fIJ\m]K&icLbp3$#uf&.@c ;yV(5!"n}]6YemS,[5k|HZ ['_4v(tZA kZt6ɐ2ݽ{7ydfLASJ]4B-)g"#xFq8˪&u*9~ռuo "{Aokd{E>WK1:WG3Qwdƪ ^ {8ȎcEov~ 53Vޔ3Ц"a&%c2o{< JQT&SM,QwQTٍ>"K~u3bzť ]|Ir'| 7wZ s ; \Yf Dܿ+y2 g$Ln)`9K:,_Zfց5=N A2DpGhv] 7S8Q S2/B@XT$'CYd㥉eGAa{̈";cQcd"!g"IZBb}ww#I?`[}kAdloc"ֽmJ- CݙF Bb97l4cOxT~?%=N yj[$XZj$"LЪn@tJ$q%,H֒*ՒtgXUFSVz/XixQ C f.35o2 AdQ̊CBP I /R%1Rv`[P KVkeB+DF-[d'ry:S@wH[6{4/!a s 銣晱^ ^i|UQPmRQKށ&dO É̘qs;a/eG#Lӳl1vH$Mz(g~Sqp$uX(^vK##[K]\fqe(q,"!yOIE)i |}ѯ ꒁ'9w*:(FdqipYD_$B^q \a&م"^vdz+wa~{'ҧi<"89H_Ɉ!uɔ3>]tKV~&J~v(zk϶Jj8U r$+ޟ 39fאOGr=b6OI%û3O0<:M M'[Ի'!K0t^*A}OO_|N)Cmܮnxr\i)*Do7GeH5+s= ‰tzF~ø3 y:S?i =,o pquliif^xo/ ̟$),-titĴxgDO_[;lזx?0r1BډjoBܛHCibTON5"oG^}}{#oNueMdD/xvtM&a _~]-&w66DL?|p2Ԅ8zG%O&T>g2_r 0ĉCPb0]h{ Cl7U¼ycYDʒt<.F PPo M^ŗt}` 9 نk(5 VXP$~*K&|EgumqOUOqEO̬<0ەč)YLPMgZnChư(lNnHTyt M8aIS!ޫ*ESx4]˜?"dSI2J`ސ{i핊U:`@ !+J޲[|r 4eX@ _ͻePH{in:,GNoMLי!M9(c J,~"LԂKj?pn|Dj6޲FvYK $|!ljC2k\iXiӓb)yfq,X[VS[ޡf:-]0b6L 5; Z[v6Lqj_Eݗ+܉k]STڛ5YdfjS28MuQd; lN"۰D\ebsjf) jl- mXh-ZD?n֍eúĎ&N*LF> KTeI=i'4POt$b~Qh{IȪkjytC&YҸE |"q V_.RI&"-8*doWcv ]/b0aϺh*٢];WwĢ(0oN {JB]"svnn x%f;iGfʇp5XD884&fa]! RPˤ*ԆᷛgZȖcufɆ< Ff rQrM*ήCrBXɜ(V0Rw\aE Ռf!_3TKuRQ?IElRo`o2{"Gd#V,U5}2?vGb"D#dʊG4/e`%ڂ+].P>C`22^Dl;w8ZpY?4xedrΡqG8A8#dx>,zmk_uT6at&Cƈ_/em<ܮ7v dzK.LY'OP˻# {x@Dr- BCۍ 9k4OXny- <͚7@-Rۨm|=>PhC/A,R tQoS5&}M3%H׵;v] GR(&S!,Uvθ婁^WCLߒ<,4(Mmy;ғ̇T.z.։5 A,$TK[9gp:cqOsFLE+ 'eӱ$π|,O!dr*mLɄCX3oƸ-$[\7Ǯ8U"[}愹BU(XWH+ȃiB3%ScDKev_t޸Q?򤿚@^jsx"G.\a~J%(_ 7&$䘈Xcpy4CG\tA"A{_PJ f-(gծNXlH-r$3Mbl }_q^J62i ȸ!# g|:]vL^Z ˠ߳ z8ݬ #߾pxa9Tgj/Rr6 :C\ G\pJ|)ykNL@͎0_o:c;7aɎO3x}AtvDQ]T&1_V5I6b,}M!d!9`wy5}+iKVkq Ax46e 0^c%ZXQ o `V (ѥY$0(*AIy:bڽ.&Sb#9%Lx_rhhr{P= ,g{FcZwzSקҩ|?%ku&񋚎ѻhp?s`]`bWϫ8Q-5 .k7j҆UqaUXcL29]#5Y RXڋQTΘs胟1;3q#@ud%Hx*O**S:QXߜ'e$Mze$5QedW1.D0^ԇ# >k3>Wӿ7:_u"yԆ62aGZ8h4MX#w)V2yc,=EEwS*,#]$Q-}CDg8S2[Ye~^(:,.TCWH)yٛ16c`llv?[WUGQ!Q䤻/4χ/2GXu],2~!PQOrg7s5}ُnJ~Dh1g= SA7rO MX f>4>7s5Ct ;nmP~G}O96Lrd3獩U(#^uˆW|ʾl܌ܸ-)rO{e]4IJX}$T%\aXхyG}bCq0E^t1Ƨ$'D4'Y6~ܓ 4Sx^KӴ4M>ŃK2BѧK pn˳4|_7I.OJy48GC%Dj͓hyKQdBN: NB%-ZY\6)uwL2$&QNKJMnߪx_+\ (odBJe& _(Ħ( -M[&|4v }Qp `˃-3Up`,Oj҈'֯$a'5PsĝD\&S2v[)0ce ,M[[|Qd[H/>Z`r)Ӫa lQmۼQõl 7C6 ZrV^Qnj6'ne ֔|-u--%Y[T'.m m,}uڜX%t.H-hsb_׮Dy[&3H8oU_jWs  q`Θ1ۥG~oʮ&ڬh xg "GP2Xj?&8ņ)e4,Xi.XO8JzL}}KǏSL Ja)̘1JǣIi6հ"2MG)ۍ|UZ.13j۴XPJLsT`˔4B c)go5,C9n҉%Ll4.Dm6n wWbƅ5Xx}Cz^xT5ndE5grE}Bv3Q@=GCy܎r~ =PvNL[49|XN2Xyi FC7]X1Jߚ5E8\n͔DCdjLP5D%DNئ؇^>DXգ^P2&\E b,  V3IEyo>yy1LJ~Q,e94}&D^0ɝA;+dr[D~Qوz k[&tkp$*Iɣ&}"5:d.ʭ)}M4rWY;k͗ fFGݧ#[),}Yc^oz 7*=Q_ut`C;@׷M Dȧis}s0g=$4ߴ΂.>>Z>t ~{875~qKj,;$^[v*`)@B&p[70g~yvY&Bm`;2kqEwMB{S.*3d rJ#4R ҇i,WN^VDrK5=,K:Q fnY(B#25:dI42s,mh8n.31lmvy$zciѰHuEc]n(&sv9h@tUaC-? Z~ɀGY2$t,C2ju싾!b١m ~'ks`>8eM # >,`Qr~5%m#Yya{}jf,-mYih,uP2:QXD( ܶun-$f W=ʨIѥP:q%aAnD;kэdA(LCewrZ4 Hٱv4I]~#3-=Z $e''v'=dz$ coէ4sP-n,wwC/3 }XKmOMuo))znvy؈ r;Їܪ(?u} M+m-e$n"(1 R^FKJ7latށ8ůh5..ղqna#Q"g(0xaOL#Ifg9X.6sZݞ %'5q3?Lq 6U:v^ paVhκeXXQz7hѨ`g3 8GsQ7]2 -j !ˠL߬ .Q\/K]3e%\NhE:um~xU8%J„͝b~+ӦLU TJ.Ǣ|"Y?t{w4ȸ{]ÊE sg;x:sfJEh6.,<55 Amh3qOe4xbx!̬arg~g/\\cun,3u~ B,jp8B$,[|"͒`aB`:l*biGٺ;_,v6N|z kpzޠ${pgs'HYֽ.5]mXneXTj `\Y&cɌ%f2EV0$qbH:E`a3s̛X tdn2EfOlR%iƥt Y}zڔL5u/(7Rl=̎Pv5Ey&)<}PELX9`U7HM=i71e/'VK~ucf:aXÒʳ/Ż20YRG郖2yY{T(XjЈ"W/<$s2?zbq# u-Tv %&+cjXY#e֬m-ԡ* [a 2#zZKTlM:va'#-6GbY7s3+hc8=>](FpxHMҀٶeeW*ޜN s2Y ;QQ9:R`= {{L ڲy#ⅰ l44%NA=2GTgg!zϡ~u\|D&qLT}N<Vo8z_E{LJY|Od_6 7TxP *TNg`a"{bUT`9cJINA<։:Wbm$`irĢG +T%!ahmUgg=>".۬!ٳ]YQW*ifM-Y}$pޠԳ`7 -V4u`M{jgٛٲ֏'dhzD axLPڜπwg@4_Os VL}_D'Y~bTϮRP- SMK(G閞0$G g٦3|B,n {a˓&dNEl$ox_ZV$ދvq-juMepum.2K-*f HsXŽ4lG\ϭK<^mA9²@{!p/xI2˴#TPiS?lv ̵㕳$ѴcciGP~s76|z r@4{rTAa˺< (D`:(~/Mfsq=q'Q2ݬg1Wޟ~{ j$JwR~,4dؒUO0B>zWd2L9,0B ;L&PпHg))7е9D6Oe%o'K譙;q֋Lj(FZ- q6zޥ8QĽE% [&L{iKO5?5K5YDV*VC z?zв-+ɘF1/U">˨KHdG!AS=7`J 3w* r_6ys.:K𫼴`ff{vVMI{t=U|>(TU(}&{LL<w|~{|b fu/עf,{-`$KOHt $#oWaБڏG'u:Hո7zŊ*DLSgr!!6E`%tמ4nwH4hUg3wJďΗ1pfҁVi[鹋VD/+Q=\Ruyk.MʝŕJP8ɓQdNrDek! 3H=bԮ_(S8_O#J/=~ ʂiNp'C6xɭfMka^Z栘 WJrs{6ଲV^etK.z!_ IF4LП_=gIGɾA!@tu; X-*\&V ,ϣ^&Nvֺ!7ٔL'S&Dve=j K2mFEpS䔌.w] (2L3}$6ĥ< a.T8p&-LhvM傝3lLU}Bȡw٩pMeG1u6&ʢ*0;<[Z>m2w&=.UH=8[r&QryTLg}LQGPdz#C u}MƖ;`5b|r~A/gZ $ߎD/tpлbViq\b( `|_  {ևʳ2=gCIఓ%F`O&w uQ39T0lVo{-g!GaqKR>S"Y~x>Yk?tcEulR Ru%+ǚ2Oqk&jߢc~M^ƥM$p8h&F%3ͼyw~m2d!}$J+4TTq^ # u2&O- .Æ{J~Ot C. -S"E Q #|' L I6՟ s&D9>&$"ioNHq2^ _$5z渇|a>`l7DZU73,/Ãn.]tDw32ZVeX40 _3=cLUn6+:A~Q ^͡, ܞmB(n6CxV~. N,MښqhT>w‡4n_&.3 H,(倄MHP)3t:4̸#ظ9[v6 odqd3T9T;QX.it yEMm/ dSűP|I0Ʊ}+_-e+te; *ut{eJ +*!,4KO˞GT)H$+<1ߡ,h LI_%b`!?2e%8Ky&m i64 D+=KaH]'4p>Ú*Gn\m6|krekvw,(җ5GӢ6oXLYZ2~Sv<{m2UaN GTiz1֔ :Ux;S9><śkYlB=s,V2r4Ai*%?!iwӿ(A,ܷ A05r`^p*ݕTtD}O7I5 sײܩRwt)G4d.y*?sh#Ε!BYyMG-]J5Bh-6֖ M\%-Yr;Ѵ|q]TbA={.2 ΆM(66|%@$4 ďnɯcu{, &AEy!nsR[XAq/*K z;f/&CWQV/?iRGfB H3g$͂aOd7(Q2X#3Gy7:> cUzd;d!O?cDgGUJ YLzӭQ:[oeO hǏ(Oώ!\$[;̼Q"WO$_pQ`"&AgL\[9Ж~:}*$cI*q<>lLK*}@76W }ȭc:Q #.%Ӎ-C1O$ U ӳG3tBf5ʋtD%@6 ?2*FJcF?P'l[SjT\*5cے g!7\BQ7 O4=bR]  /pEwg~۾;1%4/r;枨Ke‡fɔ+ 8R/'-UB۶Rw`y _!vfе`lu(sK痒]0A r#K<~u jr&e7[6tlJԔ' nIsd,u:YW2~3|u3xo.dE#˵K.5(a$ͻvkx+Y#F;IT.УpobIX2Q&i0X(4,m,DKdCK䓮TEfV0 Gg2]!hfAmEGDvo(y^~>/CK!᱌Ș&hyMޱ4yel?} ni{R2K:泜ʂi.E][Ȋ=ok ;Z&ydʍ ZcepEʐ_6VvI4!gEtB_aqƁ|mݻ}%:=a9o=ɸ\7O@uDDⱴYzi=6'l~%s2r"wd;p Z0mq;2}K)oN3ޟEYܳX7Odg*4I|Gl."KbOB Y:V>"*`SSvO ig=Y XcQR#:ʧnj3)21 :cG! |zDi} 7"( h[٦|t՗[u(%rC%L{)y`Y#[ikH#HD5 Eq1P\]rDo ߟ/QD=ߘ~ =^Jޗ}9`j $v)7762я@DBEKmYгwj !Z*;~hG5APLeX Y7 zAy#fS2D`Fί7`ϬymɃi">`u"L272 QLfn1__HiqC-V-1c 5و*AE͘L6 荎seaN=6q&tD滌Z=N;x5 ɅwR.y8ۘuXf/ib!>YaUpW o\r;JZy&Z%>3EAEcn0X"ε7$jc'}oWPrIc<{',k7oQrů{_Pr7M8z|P[ZqHm15FyxHJ^C@msU-l;|eX/梋.SŴOƅyl%%i72]+&80G%B&Hf *4wA,INOJ txx5CljM(-1P,N 4u!k?,CRItӜVTD# ͋Q%U)%O95$RqXş4Y7#qSnv Aݨ_(ך(D R9YYb~/.tf-k|ޅ}Ĕrx~hn~_IaG5vLsHG/*YnkHl[tbGL{v0- ^©2QZֶwfЮ7 PaMlL2]?7Xr2}|=ߡ~t4k༓bY#7V]!v(6-#Roh[!p7,9=;5kdvϐCm=uo|v4}} 6V2aW[#c?Y"iSHLyA~_e48K:}a9m0s)'L'ukd…3s$ӵѳLrzQ0_/zKW,͛)`~详-/nD=Kf&[gg- @gfXtxvvN1͆W 19ӻx9/9|җm1 y i;$|hطWi[uho_!`w5v]18LH<ֽ>fBÙ hbR ܳ\g\! kó.Vƍ-#ptNB}/%5f[Wen&Xxn8)Ba1tlPt'm]!R|qҺG 6,*hAR) i'ECKŀt g"+;9,HWD1&OIeLZtJT< [̵?PN32@Oq[L(S6.c7Nlf+Z-4L|Xw?rBǽ/f\KYrrNOB)|ړY5vmfF8/0VX$)XBᄖW4D!י=cEṗ+6I4J +)z09eP2YS U̙Xiv0<,̙I9ci(Wg\Zz0;n aC{{QY;QNJWRfc#~,ϥhd&4](W^iVCC&؆3C&5<9wq&'KitlyOlQ]6U 0bew8ʓ;YK +};Gy UDj:ߠdn Xv_;jpD͍R?Օd7 `ٗ74C62̣SY:+;(]ל2_0OM3JCO>G5zN45)>w]DZx~5Qmh$Ц;)W{{M-4 AV/ɣ:HBj!o?,^앦=ߗN6 &4n'iiQR Jj hIMWk` N%x*7h%7pCQ]-ܘx,2.?wD[2 n| F䣞zG,Pw/YO h~%3̽MB5b^PQQ&iȐ0)h#١7I>&DÒO?QeCf:1@-`qw)I5˼i?08aЊJ1'G{Ӱ(֩dt=J'7&=[07RR48Zt_ntUi[I?zD(0ˎq?epЅ3Xp[Lbpf׆zkj/mPl5oS mifVAFNGY۞wkV| -jk[7ȷMۘ-v\ۨ[|Rdi>"~̲#ψ>l:U_ڦ|vVk"td`[4#MhL3tX 2tbQɲi}ttaU_YJvGXFry=(I&հ 6i6fɴ_=8E =wE1_Q;& |Ѕ|;UВozfӰ 9g=O2gw;24CPnQx;=+}x{0ŜZ_;zh].\`@fA.6*W~ !e>"?Y)tפ|F9IxH*⃩Bߠf0X 3z.X}c fB=Ӳ[ 'o UyZ<3'5ۻ7!OQ@%Z'E%ڶ<ˀ ѷR]Ckw a3$֯h5KS7ȫwɳn;]qkmIJ;ֶe?j[&ُ 2ԿGD2uM%ūRzTUpؔfB1`G@f _ tǦ[UD}ULf[t bo^g9˨j2hYѾ`;]XM!&*yCAyXKlDž'x z0r\͠Άdy_Ȍˡo}^'oj,r`9TMY0m&Q<ڗU'X|+U{(IWІ>ux%fkhz#I/QoAq@~O;Jղ\r<2תDI`@AoMh<]6і΀.7우z$,d ]w1*g͔to@ڡ҆εN!xٻ&*Y5[K6^H_?dl|ܷzK潀/UP'z2tǃ:X~}*c%FYSФ H)[MvZa#ZD7PfzvNӛ[ w;9V=hR9[+XoeVo\xP')0צ8u\Gt7aJjwԵ|BJ||k|5wD[~lX=6]y!Բ"jX7|$,^3Hy:RʼnB*!牢yh:uJT' K _-@]wUTx2A{.i&/p&"{bZޡewTU;egɨ.E5p;K_,(PA]-,X3[}.ycit-ұ+}+RJ֩ "U }:T EMoqhGˈ~h2rO~ueZ,nc.[:m,:^CH CĊNȐlJKKぐ}m.Lv_k]R$XWta1NPk[Xb*v67^jiE`eo'gA+y2i9R.BYoNDc7_!i^2Clg(43t]q\3IH1d/PwO#L@ ka2t-o#X5^#݃o:cEN>04N8#VoJxeetI#(XpN0fh$<_--$,Lb3Ja (fO|+.g&4R5NOH嚶D$ɇ2Ybg҂3:߽b4Դm|&YQiѭb ^PQ|cŽ9.Ґ1o3Rq({8,]4=VdU6h"BԵ2~U>5W\3= X8R[G(fjցΈzfs8";g[NzV±b5zU!I˳H].rj jՏDbYqs$ܗ/9=av]xj_[4uϴ4T:'fĹzzM,/\FfȬn0ApO /ib\6̛sQd}~#gW79v(Wq8M+˟LUӅKKmoe/_HBьe`n|,0dr>LDTIr,Dl^7&ƍhmy<G;Zn\I9CVZh^?T1;7 bRS6#qt75$Ek M lh+̑Ih5i4^`kt gHsՈ.s>e){lg3/|tW\hFW(͔ѯ@+ jDcDFRݺЛAt7cz,4Hh-gXoP[GTSͺ6> ~{궿%t"Jr#N?b~dה~ 6#v ?_'A϶a`?]E !KHـکc*YM߽Mm ƫ. -K՝ϵ/*m H s}{4# +Ên䳞\M}9ޙ BD)<1tZfUjE zٛTQɼ`|WͥVojks2=ђdzKZ*0{/Ks(2 q_$71(YNx@m u fKt|&b:6Pb9,F,`󁊯:3}v~I>IŻ;~sDzEgC-4*SBēQ4$8s{+m8Cc@(#FLg2ѕIV6*Q4o=e0NOBk}`Ύ7&ZDH D=hFEs{q5U 9jl]QvNo0h&!XNr*G} rn Mދܬ:| 9Py c L;cGs9!~nw켪]sșyT [5Rc)]YoA%9Jr8Ȕe7l~ lbu`V'd=lX}3-'mb ݒ|eX..[Ý,$>|HVt]˦s)X(x>?my=|*W*;73|Չz+X+ݚ ;͡5$y--7 [X(Y(epƴ0xȲ3bJK?F*U*14=~):iq*fKz(p/=MQtTm&睄z?MEN9_Ax~7 abޅ^\+JP рipyw *þ?6 1iLB[ L!" v%GGOE&JL{8D!hE (C.s xD!h;=>CƳ@Uog)=pz$Ã%̅$y]tm$ <%,_\'8 ۫˵jE%rDcN(ֶܡRxI@Omw@iyoZv`9 gBmB4?Hk cj&!F,Mj%biOH>6aROuYQԕs-3"fs*v#JFLYDj3y4ƶd H"RkC@rLw-Pվn$m¢嶱i=X_P-g>m(PAcA?mW銏Ȓ|pYLz S$J%2ȁʹYiéhSS$ӾпAٹ.:mdT` ۹#'4羉ڜt޵ʛ$ ȦD'SnHX =.iՅf5c?yr7yBuxQ-m:_tFU('dt5!LDi@\&^tzW͕%?z~(AQGY] 撚@ޢC$<\S9:`!<`xddZv~!?ڗ|c?w^ ̯Ep~t \(,3_|EU~4VV l] d3u?@~ÈCv[42?:?rKEgX@h6L8[fe:xju- %rH{@LZmB}Dzc @綎K/p5I>tqGt#N%H~H]O >}U##LI`7a[Ҿ+%V#Ī_tpo;:NS<ܿhKu9!fmc0X/IJNXNS2k2_HK// EHE_&:{DQcոXYd 5d޴4uDF15$QcnR>ڄ5E gQǸ";7\yYHYZ E  5G$ :rc:p$DbTdN>8;wedE!yƚ'hr~-3est̎u {D4]򡪵gõs9\t._CTfSpz? ,qpssI_/=g|є3)HIƫV\L SKn1+fպ`ؔxf>313L6Ipdjpm>(u乖th#w[rMZiƛt__繵sL˖ϝ]i@=:` }$(az3 .1 ل5FJ'LM@# 2mo(MҖC ;P-LSh% 4xh͒HҳMT/㶭15~\͋uf 9gϙg+0{K]>1Ը|d_22(u0oqK@*)QRuǚN!O{?EkJ:Nu3{l'E ] m/ ~6*]w vv]P®Il fe9&qv0qa_piW]!R$Lz\ǂ2:}۸iE,j`5E1w6IEe渚̈́MdgQ09;cHp$p!h׬Kzoѳi3M? A#89Gg|i^G۰n/I(}#l ,&^AU>FvYb ,s\T dDBZ cf3=ٚHkצvMf-.SC7(߭ɕ_]^rf,c\F4LSf7,z^uv=.pQ,~'똵apUo6qeagwV*ڋy(Cݟe0DHqG&zt1ֺ[vG`^͆Rz.gskVJ(cK#(2m gJuG. oVAdm(d9D RU8r9& _5atK^g*y-ݤx7zK'cW{޲5靂mIBO&QnnzW9XN`&Hr[ R:0E3v֎;_9uKԳiR'n2CzI*;v QJb3]7HX /`滈+]MLvp [0P=G'9-U]LX0ac9x=}|ɻE! woP[՝#XVƐR&퐖ybiʾ *mH5PcUYqhJ{þE&+S~>Z|O ۯ$VBne$õQD{A&[s߶l+Iep ld|lUޱgWD31)w3Oz R|^(.Ju1efe ii9`f*J.[s&T(4MUwj$疕5$-p@hJˌWBy:sϕ\aL֕ڣlsE.=K8p ڧluCGh6|g8jk[3-qZ߈!z5O,k75|)l&2 2Xq+8_Y=v(܁2(Z- gv;jE)vwY٬20/S/^#.ѩXuCy *7|Hj˚P eꞶmك-sqwTNag7CJb;(EҊLez>\mw]ǻSƞd9oDss_h-0ƗZ|WY_.w#mX.KVٶ:&B{:Yb)b8 ~c }W^K1¿ XqC|GXo W_vN3Q!v<%gk9K^n^鑂 $ иcRb4Yήƴ;$#o."EGCԞ!N\6/&5 ݄WIM)r6ek؎s7fݜvv! i(2:9Oր2GĿnB|C)d{% R5sʖg,7GC^YLuĠd-9! nzKcwѱZuMz ~;|8'VLq#C>( tN_lHq8\6=8Cj7=hm$BRG|g=`;޳]5oXhoOb3YrRT~ ѼMs̆}~j8B߼qZ<9R*alKZ%Lb*<*O8YKOJOjQ粌JlvB!HDqE-* pY4_Yle~Q~,Foxґo6\ o$mn|YK4y|Gب\ GRR7YvW 3B:aŪ^/z174MCMtñgrI3m^yq욈}O FHT$f ue/z /o{Ap5E80 =Nh1kH҉rFC}舳ĺu?=_Z5eIZn#1MF 6]V> ޡoB!ܷTm[9?Zo' uhr_Kߟ+ie_~;1suC~i$JéJ :R=|GX =<0܍v/2Cf ǢEz< NGLH+\>Ռ2/\$Jr}+ۢmAz{4깇w-Ko"17zrd7p^5yqt7_h;p$M¤[RxVFvwro|{n3.A/Gݛ\:eF'oGNq2PG |`}BkJ e)'_u+8t(k+ԿF )q=++4T?W+`ƹԸ@\µ+5211' " N,I%iڝYq O\+fb\2xs3H., Xƴ-]2Sf k$Xʨ*4}4tVRZEmYs~a5OLK(2'D؍ev`[+WAv;G纱/Z]W[NeJzWI8?֬xXgB\Q& \IEsqkz#"dWȁI5$KW)`.P(5hgF%=tj`x63ʹ ׷@?|[Wc_LơsXMr*1D]8tSpz451Wjܯ"/,rv2MNcp hǭ>VEI{ ݳac@6eI&""xO]1>z-Z[Z4Ώ.ͼNVnù6#۶##ݾVAiY3JL*hoM3bj2I+"+6c|ea_9?wx|$钻OzbL_u,9oYTq7 1/O}3Ar|Lm}Pj_ %<ϯr؊}=̙IXEE9\s ) J;r6YРL]>fScg;t%R'aoOt1R\(̢NB=ADL=cRd, 6>b}AVsع;~gLVckC]gd#9Y4NJqDlOD8n|8VmS!7j |btLmU~!Mk,a}ntKq=& ۚ+%^{> \bD#~ iPzwNy0y%K"xa+o)'⢋}_fgfţ~_=8Yx%;<Ӛb~gF6JiLĬ-||dIGO8ӤY=& z9Y)*) ɶ+'6趭5d6Ն;xE 5C ;NJ7KO1ADRt!jNMG\Y+ J]kba ER_?LddMJ)m$':KF y~Eįރ敢dk3LIz)so&q6^k@")kᇬIƃK9@2P jգIQ[y2/5jf;Ez7 nm-Ja}J_dFwaN袴U}vY"\GۥVth Q{%Z۠ft~'iv,X>UFx":DV\XnzT>> 2G2 k[@($5ko)yXC-?^x]n͠X!pmپF5b1Gtc-P9GMHMR4I1+کw\goU$NnYuFvϬ2OxzO|TOdOlSQB6ؘz! xjDP4e8YmB8sI] ~ІlbDop0O0!G6Tc50*pv ]4Mp< SޅeP'd=A3QM;W9*|xx5Eߴpre_k_ׇmpn͙UIYQ(i<NP̝`mxʉ3]/o~Yi1~~PR}XiXAP9 <AQ at=vDe#ΨL+)Ofn*&y4˔аhU9 W 5鉛Im>M$謝JG#W Jʎ9 &KS[xAPW_ñs8:"[ԓSh 8o6isfLf;-LKOg%>3[c.>1խ,V3Ԩ"de-:-#0XI4SMms5^:FۏkЫgsM ,/oNsϻ3a]gD:By'3=DZ UA6YP]%fҸ~ Ki&etH;hY{U*gavw>̚?+ ѳ9mE4J3aϙ1n$ ~#~Xr1ΑȎ*ۊۗ;_ k!tA(|pA{w ,9lɑPzof^lw{¡=3a`@H~*8Tp@:Œ3Vg5;Uco, g5%uʹ6?ɶmlH74JV=7c<lF֗.6s&GѨΑ=J832X& Sp>!Ռ *_|}|&:P m֮ /zMybfC>peUt'ز;kʓU'mm[CX !uI%4~sdmE7_b)KDi#Q$eU j={y(S[O+# Aj3\y hQ={ҚR&0G:6kt]]tQo|>BX `~JIK`VECV:qB*g8r"ľ|mqHRċOV_}JҡoGD8;0m'M 57P肝b=EY7Ad=kyGTZ&%a?~;Y5_(YӢ>BX74o:hOr"#ɼ/4f4lY}*RKIW훳3EWWV %,S/{d}%.،ό- ong0RAƄPt[ $fqwnYDx{De4O W-[h^gΪƳ: WvPgU4.F}Wuj$ ;`{8=^52qPjusiټy0vU&BR,H}N hߥ%t~z=nL aac:sIJ` "^Erb:b-!$b}t6.k`rၗ*fr00~t,[:Y:ܔE6L_ѭ7m49^RW4x):$nuHTKB`y}uJ?SaeWgsh#:A>ncjF"N!W+ nG02t㔭1bn~}({+:92e1fX_MdDX&w{sGTouf ۈx"`MtyJS&H\BF'Ԗ1b>(]657 T0XX(N' c7du&3Mhe*%h'>$F.L2*b&pcY֩[!I+M3` ;$beI"Ed~<м0/)F+:9&u* _9  kW;1/@lY 4b|+@kie˺8uZh-[d>!$KNp&xj,]9fn !7nX!ڐ sX'pV4cywV6ߣϮ %fj:9X0HqOKVc>-%zxa3qg9:A~5nX5:VΓSu`]ZGɆ#hn#(:MXgHxW5 [5!:3)Kw.r'% WqҫXT u 2ڋiZa*[w/8㼌~|jG{vɅlZ1ҵjbL9v#ZYum59p ':ZO*PjBeeN,&SۄuȕX!T%ęYOXClXdsjܾ}maA0Wîh7W*hYGGB2P:HyXѐEhIw!jaTn̽ӲD`'ʩeF0(ڍE-#LەQoej4!0X}̮/-&UݬN<$3=LڇԴ3nZ~/<x:'q?qwWu-qX&):UrTٌy,%SNKxC`XFr'JkҔ1y~ؓi>c/q€ӕ'Q`X_"{U^浡%7's8Z|?!}JFOe<>o?.ubG 7 4 IL\3b"G3:+뢭j˳iѴSlQ~gӀ@on%5LI\=%ݢʶ, vPSfzxlTY *G49ӿw@>ȱDnUVc$Hz,AetB7S&ּ$by5My^;?̌OLGDY?HN3Z0"Uqpfɪ&Ջ2 _*JR"Jg:h_6xUnQJw`DXCuS8~~szGsfxI`0fڟԓw 7֛{0 GyƊ"`_{e{%cr1ꈽf;se^S~=5hirO+?{sOCx͠dOqz8Kc=Լd-E}dЧc}ō3H''e1ʈ|+dP!O"95w 7m)uQ㞀L|<2HɱpH&:S!6}V:s@YUߕw:{ عŞzú1dvd(GXDc"}lw^PV!|s" ai<|*SBѝL^ގykIF7hй@8Y0n}xX+nmno|BML bp ȿTu}jH=rc(`d/=w##s*cˆqqhG|x^xR6/S)žzwF8v%*Ww@l5uF0F}]wV /ܖ;Qxi2L]Adv+Y)zjxԦTImIBb =--mivh5ԂmX6?I84(AON#FE0ߕ4&C/RuRfn~JM5ԫd@ ~ Ⱥ6ex#FP ot3<гх  >tg%x['ȣڕ8\c ;rDT d΄YE>-m=rZ:Ývӄ Ee{BED, ohʽ>A7GyO0>7ëIH24@9WӀ&m1 2'"R^DnDL }cut4 mxOjV`z>q}ݿuq% 2|V_lOu#pLKOXCPl s?c^`yA&+RK$ӇuI>9ϛ; 2پWl}Phv'n v3=M5g/Dd+u1+S1Ÿ H 7>vцaz%я&O/{|'F:@\fer/}6N9!GlsKe?Jqsi`65.i Tpwna5j V$}~z; +Te,-^}qSųj\<䍚 IܴvKc;3@ZptN8*9:歑JOsRܐ٥ߩ{Rmt>I;:Rt˘&]m\j,+)Gb*|q=q\+4Qֻ4چh42ptl4.I2Bh'P%K짃` -(O,Ԇ Km7e5xNg7|/_xV'];]( ^q:y.Z c MIxtMۅW?+~6 I>(t$xh>[3eY~h=Z|:+8Yjj3m^e:i8q%m)7o\~}h-3_q*_>vd,e| =Z.UT& r~wޤ%~2 +3|>@\2!/u TM&m8o|9SƿS[|4kDT=9\듏Ds6})=L!:ʱZi"*Nݗw;҆2쪧-u}=}9v}{I7X`v3g|PO]HL dEoŗa9O 4YK$KT>(R[}]SY0HjN3$C~bae3:L0K DGBCwIa'M^gr^OuKz ֞m^&T=dQtiϜfb^g}1Q7#FWlrbBPʃ=JL@<)Ht@jT1sg/Ew3,nYW.9 RͱbE)q FGAa8u9T[!5!*>^9_xvRQa @ƴG&ękFs5J#:pYBH<*ـ3\ّTN$F!ۄG,ڱa-׻Ekg:rd9`Ӻ2*v B \S߱)J\yr&O|gp.;SnLHܦJu +Y9`&ؽf6?8iM͟ iV4X{v* B\׼@8K-y5E=mJs(漯4YA/בM<5:ߏ{^.&] ==WGʄx]\suI`JP(> zI򢣁j55tEE½|_'11#Hffg~ |6 {cB!R)Ѐ$|:!fa*Qm!Sd(i,OBQHȢ|O4(xμ*4;%9#t%!-Aݧ0_z:a_esgK^ÿpr&3&=Z%f6j )^5$i(w L0@•M!$LHSKOU$/^*:T7]7݁ i!mH#u{/:8 (ݧ kb|'ms?ni AAGDK|{G߄ K>Ϫ@ uJkz[sXp*HRBF ~s&u&*ТhEFT£)eW&K~RpgTo)3re]z798>+ڽr\vPܡgk[St$0P2о ʀ$qKچTDt^=-urn(ss@9+D:ި!|򴭖ya"UJVGoY.M'q) Aa0g77^ND鋰 IM-kY!>uBwؒÒx:3 YyM֙Iy:-4BǦ'H, ū3)@Vb#7G1iKOƂsy;Qjɝ19 gfV'o^IrqhZ]䊍T8ds'}Zsk!ji>s&/zEGZkntVȁuC'Տ~t,؏`YCg0MM\> y2%Nk R5]Pm`@J_Dm~{XY! vgw f$ԑ{d:;Ғs;є Sj!8.D(K&;.ղ"+5/P GFP3SWg8d=Е|yH> Zwvj: 7SHuM&$٤AdH7 fu5{GmGc=O1IAǮacϴW}Ni>|mvgkJjx6rMb%.>;Rg6aev1ԠRmYE2O'dzߔܾeVʘN]'a}SbSVKJk҅fuc[P1j Z{kljgFʬ ~!r2d\xGW΍u{(A N/.O:`/{Q!e̻hnyiU6+K=Y& 7xMGngÜ߮*,(0tdA1EhT8x΀ibt45 Gf83%-54x}"oT=M96F[)O+3(ra+8h?dPV=I5md>9[&CA7`ȷ?g{'j3PC}yhQ;4:lv<=]]5|m"3[0$OؠMCnx%w{!5fgX2jqy u >rʌaNWjj l3v~ca%ŗyAe#-\^gE\gVW{iGMHG^V}C <ƕ8ifP,r{`-۲4 Q]^̊X|^%ԔjwhOK/y88j߀ϝ\>-FNc["'p<3=n55tSԴ?A_$_J |_nKb) 'i{0X?P}LI6d'S?#B*ɈtYV"z9};[J ~tLxnHgаw'=K]u Qɇ[5Dhtsx Ftw ck驵#9) hca6󮕣\L$e #3qsv,"N IugFxl4hکJ `խ.J~x3}p7b<&)oH="qޡT?Ӧi6Sb).DSkcyƓ!,5z&! O ҪTgL88oV}<~lf̺eMɺuNjۓn2~{ۊw6+t%e`Vݫ/wonL:`u[eֿIY|Q v&ߤ+Kig ɒΌ.͔8؊L/T]r'b_2BqfC? é*PtE=T֟7)( 8y/41v_V;KЄW':r X7g*';MBK u/+۩Wt|KfFif^V9&:KA: )%E+G2=/ n^Ḫy,,ex,}|vc]g K>m.8Cj!rf=/0gW2$#tq,LcgeǑkO!A5Hq=k53i Y _cj]$NQ~L%5 erNLT]y/ˋ&RN؜YS@w$)YaxIo[@@mcXK 9s~ⷭ4-=t#&ZAxC۬<f(XzKnߠY3qTI_z)iEu6 A#OYx+=PϺ"Ɛd4}pFf*β/y8$ABk]y>k8_NQۏ<{jYn.l* ~MxNMf#(3j6+N_N"-O $,t0ʉ+ž&?s)8c>zm3;'HNKYI!q!/LB6nmXz'2+fC̐?Sf'Y;:F!RJ>CGa8nqdt;Y<#R2SL'3dJ}?xePx}c+!)Av< THɋ);?{ʕhI?~vsz4e|s\NzED.;pO]yclzzglf2mM eIі.p'H|nDrC([tbAJ=6]gl 9f*ooS[<ΕRl'XMevr#.2+ʓ(ˣ$4h, V|;\&(k!P{'! >B=ZGغ$=k)MKg8?uy@;R9Hp)@Q=nɹIDdj!G3#dWp3|wYl:5iI,4 9+AWWn`9 ޡo82 > & ;&?1sb -_@_E"|=ow㗟xCgԈ21ZF#9N-vH9s8BxhY_fHءbWmzXK=-Iz2٢R:=x&y&l5cۇ4'A- {[֖f3"zX ] 0Jg,!L_\)a>TɛPOؐ4uy N#a%wƷH\ϳ4:3kiÛi C#i6gYy2 D=6 %ֲH-Wt{|r1+NjYF'3PKJVF\|O0E)Yc>g5]x(:i玃k惰I<_Ȓ#f5EhMye~So;>i|__/xYq_gicҠ*Xv^?44oQ)Tחylzfqq8ezw< WUBٜ7B\ Mv4嬊=UhB«Ե{l)!t RW7s[Lf"j1:> w}&&ɗS];=u3hE$2&f.0`&R.V;^cT. C K)D^NPQk|ܰtv4ʄHX#LG.!UQ8[;S5ĹT`TN K1hǠ5v=R[(7|PV8[|G} A]-vm̴Z֦f(H<!8f`(G߄2C8@"=0k9n: M}$HKf&O;>ϕ[;n}m!HӽW:@X=mkZ"OP<ˑ}b& ;jJF0R:"%Q4{ȧօjm cCy2Ҵ ?yq6:6=~cRj:֌fFχ( a[i!/ܙ:22Ju%? dXSNRlTIZ9cRľ((4+`4+833NJ 7`!lvU$pI t@a[RVRbKH3vjHgىQN <;ȑnLy6| vHZ5vmle*q׋wdT|gN;i1oi]t$o\lr=[--!y? p[UhfyFgՎ/S'Hh4N$} gnt#2M؇ ;Q=q'4rB*W)I LD7Rg6< >.?b&Ի9}$L5MRMIXx@Yyq'j,5tHHy@_^xud ^tVܔ|viQWEΗ@Avڿ-h wA@g^rt++Vt`N9o,nXDF[N *A.oXư:kw0d-Ա1?yene_OX H :nzwXbGˎ'+'T\t:p4bz+gG+&f+˛WIU=m[V[ӥb}d {/2Ys&nc;bE|PUؐ!zW9#&azu:9SE~Z{ZHgS ~갟T=9xsyM=HoA3*?]P6.@[[.Huѻ>߼w=MHS5!c s2&shOyoHs֌ϼqA4'htdmnZڄ{AsŠ"(Q[D~`#X]G_.\UGEmӀp61RknGoƳ+@}f?Q{Ysy:SЏ+81mc/>FqHCO'k t>3W 7I}in5X0 R]QN7r4s0Ye<|GWdËEjJ<)sq%[`& q''4ڇ[]C)19Wo jxʽXoj'H= WzCw:l ]m㉕ XvvXq vy_tcBnvq?Zd!=>Uz/3)y:5 v(x*buȴһuYVzQ>_ Y~ 6t;]}RzmSJJrt]GlNgp$@"Pf>Ie >3"~)r[<3ŌZ~wfŬ}%2k A 7Bm6):c ~쪋 arGu%J(c?*A(Kw9M4 oFn?,ty) oNdk&xUbPsTIt f-ς'LiՁ-ƆZ FpW^u {fk֞^&SPqubytz;&_!4!լ窃·CqfɱI'6?.)ݏUיESg"g&2؝G:,Yu8?pP\LI'˭xbzC07BoX4UN&s!;SWX:J좎Dv-OIea-8;L4R:R5CH[qаư,g:83X!tK:ǚ!ŁnH3NvH/"ppHaZH.Oه@[\1DyV 3g;! DnSxpϰ~Y˽Mr1G"7Y3GUaY(l'W%^܎j^%/|oHK;Pd n1vtSXf]>Wҷ:5 _hn\>uz⋥_9dWwBu H~vcfH^T>fW3Kzӥ& >t23, JoC |`R+@V1̋zf0}h4:f`fIiT_ib˽yxD|Lx[PJO#'\0u.SyY JzujCy) TTZWk1/JJQ}u/ sh,dfjE/<-"!Gw|jړtK$OXݭ>@p-:NB<`Ga\Vֶ0ZÛy\ͤ#~j nJy>MLmOhgWhǜ#*VK }M;[J` $$9;Rn\_Y1iKQ9~ځ +`<c0iْPfJmHb:X>_5pt"*(eHDIB_}VӧTggXjbd2 $ݽzj2갇CVb1"5ƂcTV'(A$p7 %J;͊idCm/BJVDp)*8(Fg6M+%"=hV!M}$rzVoΣE3w#ErXx<- @"aE1 㱐b/_cĩѺ.,*/?/?/ z&2:X$!sj S?_6IYa<^mpLG3$> p,g?0eh KIbmйJuZZCdhsVDѝ̣ϣٛ3f+(J$==HJe@t fՍ^Bmu g]&C* S.G3Yl'H7_yl|a"k0}^pX|,b?j,qzJgnv䮣Nr8&^r'P^kȟxIV$Qz2tX K=&EìO'Pn}\)M 4YZdoYcP4fϊPTnߣ )3ePvdxnMR֞o ˌuKQFߣ[ Um5W 4C5;WTÞ nQuRpi5g=b-߰@Bw' C#(wAv_Ԕ֏.䴋Pvx<ٓViAT jCΡHj/%jZwH*x?7i:RQ:+@qDfhE+D.&'H7_(YPTjE m +tS' P qdSй4i:BNdARo?rYt-~v2ϼ|qڐtb@8j ""WnycG̓vZI­4'ar>5Jt:Sc/2HOųjuݥI&u"c+%(O~_23OvqxG==V6 Qi۰Od? ERʓu}ɭS0ĥg6ky0t?_“~4Oi &2dG߹ygFQhMXgLM/f^{1sՋb/FkXE'CxǬs*:S~ι9PU[T|d5nB㵎/P'8QF\#f*XzJL{iHK?m$ oT$Sg9pYzM0/pQeT2#7IÒc *Gy$b!>@WwR况C0͹NiI II>D/']j3)fR*!OS Jxv9KFiBn{bOgcjG(>Eoo὞nx3z:?% D><3sML T\t4,2bvgv#|+gbe-.3n)DݲcK%o`XHV\C e'EfM;4߈z8Ҁdž`Tj+GT0~w:]y|N=as}$9=$G=k_SHbEiB!w ւx?qciMR|@>kO?b7jߐvSy_˚Dv/_ CIAΙa7ig~:S6fds5zcq`O)x|(sltjsW*It#N{*V&h{a%QIGABB9eWхp{ jz?̋>VnOݓ"Xeacm,:~t7UdjfB_:5{Ud&" 4L'$͌,v`sd o{-PDyk?!EdY+"i#J i3T!,!!j_f#+I^ovt`fMW=uv+ -`?d)L MzTiaq>pqU"0huYfNLVte{ J)1@eԁcxɨ:J<|[j8ՙ;/wX9UXMkwwTdl]S`>ɳ Iv~r?Ca7)7MI\w5֌'k [,Gˡjl00u?"[ڎ]w,ldE>~NkF;\#Hw +-yݕ%2NWBi&nWtIn/78|$zEEL2)|MO$OiCa ػ:~dACfHXsFSw y,K}NJ!PXsV@l$?¦1^"ޜ W }A;qJT`cOgy1(]Z%KqT2񺨥9lT5Ueb2$rVux{OUJšM\nk~7ReÖ%Oy᥾K ๤+Y.N_5}rPW9?§߭7XГz[NY y /7A@v3 .0rV莢vMs1nP/*+O(WT|)r#H8P?ߛi)$-  V Q9W7as/QDkawt' perYB:Iiht;x2dVKhaI'v/XnPV8Kn((ء霒ʚ7~õ\c_`M" %$#:'gT7dnkޅ !n?m#JL"/MJ(It=1FUOf]z o%ENZ$h!z@ggNMݬIo[ $W y|Ow_<֙Ztb6cIH@e%J-9ija#rpڷ֋)ۙ GU*Ԙ=uY4M'P69hvo)ՠ#k@3ph?7YN 47ͥa6uM+A P0Ke]&h Thw7;dkddHq}2TIH앟Z׬tPOwrKK=s#H=Ȼ$]J8)}vnZre&(#Mg={8`ZZن]ɣaP46g8dcQFM1kvQ3:sc?2$^P*IIes΁vrNC.; Pa54VCCyӅX'J\mRjj V'vۍF`\V[ # ߠDu(}(!1tʗUډ6CvŁXP2 ._,u&7H9 ^LGSr,D"ShUILٵ'xbramڰNJ6M {@i5,WӼ)>Fk6o_L H*-c}ٍyYgej9.?d\5>Debv15sd]v̻Nd:ָ$ihd`*A6$*99?i`q(Pʻ fc6g%TuW'u j"teּ.Ξ Iuё7ONTY_P 8n&֮ M%  q XQyX7?nCzl1O(Z\C:4U&Rr9޴Va++1k9攮"̦ ];Qۼ^s"$QsSGu:&qVNHL{Z9?WfMpF;/9y%/zƑ 92xV;@ ic 9)6§KsT -l ')gᛛTzlj{>͔7ͦtYRY㥘5G2!ҡ]A_sִzG%.a K %*qMeqCrJ`p[e &{+&?[R^]?l AuO!vK/iq'*vVmi9 &QRV -|]1YcSB7;xcSz AN:Yu.+BA>l+ƙ(J6B}̤.R$[=q$d"?"ib9"hC$<( u{@zaDڋi/摬v#ڇ 2#IfҍsOvLQm8{LS _W}[5UW6Tz1<ߙquS\|Of,"UzJO|RH~j+-Vu&XnDOHخqSk4_P֫tJEZcn7 3 bzZ~R}_D$0Tld#Y<D4祩 lw&&,~Zxw#rF*TL7]Ma M4Ҽa0ScLVh 0sS4.jOdVx#wEaCCz$cGv91x[`Hggq>^:."?B(91Ϝ[f9_-DF _fkU' ufNd^bg][g]_š-E9jp.gՙ&V4&koC:P~\ Pq-b먄8B 㔀hӊPu#MN;g䠖뎏HV+qĹN򺝱G^Hcs> fuq\#JHμCԕV^̾sNw7@>DP/ rDuʓ{kE/uPûnѳr$mX*5OYBc 1=1)i4yY,\kࢱ*CR' s=ʼV锏63,:۝O~1 Mg?=Qzd #=z@%-f](6 Jp@ږB'dOWd&tSf{D6O 2fQRܶieOE{ʎ]OI6|-!]-aTD/e-kfĹ/N,щq4X_=/`|*Iq[wXE؎o_;OL3SnQ>O<8m@4ϴN |1H-5M{ERIRBR7:< *OV%E3ww05k#tX6[&ȽppUq*ۙU4ĝUɚ2Y煂ulm+&&VTib腖YHIUdmEj1F }f۬~39(¹†dd!}O".ĖHjXOdkh oI^N%& 4Ufd^iEB@}D ɧ6Jb$w)HLX.֩Ѭso9֌)v+()Mt4φIK_jN Koԟ3OΔ xAH8k9U@ ;7Yf&$Oɹ!zzIQEbn#܅w3ձ>6stD55iZ*-;UɊLwSw5.zCFc}Vy&*U@c72d6j.l* M -/=k!o9H|Xq^8eMzzDz|"'tO0fgs[{kr2l]7u2z-\OhiJӶEiS7 ֝яCa{1Dj(ElTbt<=kCKd;?hcu`jyQG )o\UaĒy!aiĜq)K$ 4+71q@jnH*˔`8y@ p ˢ Vp':V :5XةA9-%^h9Fw4r݅ԋtu:h@9@9omcqF{c > m$=t:I  ܋pLPH #~Ga82Ǒvm/`9"- ,j=WѩE\>kgJd/P.yPJ;RV\VĘ4|ILyHtzr5O<xw7ӐߌXXvo!Fu|m8 I/,J)LFd4#zC/㋱`"y4 I MmX[2=֮F+G?m 0ZmRM2SuzHv E-YڋTezȑx4A9p(;O ܯ \z*2Ox64 HU8#g鯍b ""#'hA2K?g )rӖA9r$sF}瘝 JɋQ-X/UtY`&Obflvoifvq6pN+]ZL߲ @At,Y\@4:@ˠkh[ &m!"V1oX(l 'L,R9!y|PQixD/uUs&!a/'/GʦY%@AIN:=4d7yF}Ms9*RB#in4*geLF)kTzdhH`"Gk >)j //N0az';koޙoH 8סtsnz)PR`QXkL HH$h YT8ZQXCcfruJJu:3W*xqXAPфƙbqw#E+%&e]j:`|N74Ac`=a6Cy٤`~w]`ѯ_[xÃdb̕iYȝ.CrsNwh jTm8,ˣ(%@0gޢ8*} \!^zwq8\ɒ wvo2#NpErÅ.%I'@_\;҂p:,f<6;f=|p/ y<öޅJ3zhS/u^̮;#+syļGĻDlw۾ؐemZ 4&|З3ZJeO7;}YdXf*2)@\ UܨI[fN!XbR?XPGR%)аTO@/#|z=ۘ3s@bgzz0ߍ[$Q`[CF˻ ^8AyHKh#?zdڭ"Sq} S퓎=:ّY}yk{)ٙ}/gAuWpm8#ȭz ܗj EH锃̖̘u?|ʶȎ h9*\Lƻa@=niO}>*xU\V yb^Cr i"dYV'rwsN(o Up4Hxa>fҳ%'N3$2ٵż2tStjvN#3w-ij|[jFVK,u>;8%Wp5߄d"̥≗'F)]vs+Nh|Nͱ驲Cʗݧn ыNy"ٺ#Wź:Hz < SqlE;_Fud}PyKyT/@;33xSh,QKM19yH5d*;5CǚPVIux/͈j[)x!36ab=I_ UqG)U/F*{˖Jq9+~t: lZ/RROW>?-xLc/RNs[(:oД z*RT;z7 '1c\gf'{Ŏְhͭ_^tjQ<94ɓ# YlZMyKPh/(gp?E톗>F!HEgۀ^-;c["9>J:1$ԉo;/քgIuha+xA%PϺ3t6"'`bb_鮲qzEŭ6$ ycyOOuGfJnIyV4Ҡ^e=Ԍ#^Sn$XX^!'Jy(־aUXx=u"Ȣw$Kr—(7C@ZΦvzAo;>$("jEjO\XApӋEQIWW:C2P 'N!* )k,<c=]Tq4nʳpjlDaj&d ՆG_sC9rK9ΪC@=xWtg8X*UÏ=98SѻzEh#AGfDֆ`i=ܿ_L~ù4ӯSMہ: =ۢK N@ c ym'QwISY!sThRu_L^&I~cڽGfGX!4] kz6*okz$~ Z;C V.}!+'S]b=Y5jKRb[v^ˊ s8AaU2pQ⽥XkSy&eeyG R=gܑ6cb8^,a3bD 4.}V'Q҄Yezv魡3)sbN7ْ9$)@݈XԽ33.#[=|6OvRѩC@?z>Q]̉+Ϋt;]UqZsD1}ޅkߎVGVXY(o.dewΚ=1'+:HYY"CVZ 7Lr# qfo5yzBc@7xzec F_^7!"]@0xbr| H@e̼/*⺽:I0ߤ$D>-SSg|`nGL8?_fC:_ ъ5OcCLS0D~KSĹBTkW@P Y.ŔX+p³dDnn] HFzt(#uG_CQd?X]o!ʪ݅uRH5/c }f9Oܾ V=:0uV V~vxh'^<^t1z 'GE N)*h6C3`F>ĔК?R4 'Ye3[?2aOV@l7GZoF!WL$OCY"(IGh@ oА}(`Ҳ×v:I`73D5r-)_+ށ#uݝCqv[<2crC rYEYc# Y @D3ʜOS_<+Uqus5̔Tɋ)]Zs5a:BgUGPt_eo7=Uİjb5_#S6k퐊|i=r%QnkA䞹TN&g/@A%ub}1m$o'8teO(]zO*:G 1:ahl-p?H ̎drQE\Jtzw[ 2n3q`ho,wQx ފǶxxӻfM$Yl,q jL1gQ/Lo0}؃oXL9w0h"Z~+!uD^k \%HoT8->Z\ڲB%Flg 5%ͬc m.-kqyb'*Jq^G>b{nWp=C&BYD1"hq3KJeXԑU]Xc[T[7/FnN?| nBU/6,p Xqh ^Aj^Sԫb:A#02AhdE ?Xy.$K76+?8˵f^q !eI͢W'sC& &vU!ON![Vx5ՕSWzeQ{Ks^.zP'qS2MEw5i?0ݱܜxG~y,kOIlZwcՑs[@[?niB6ԃ INi?Y;kn)A>ѵ^pbUlpAk c?JQ+heP7syͭLu5xFW]b>b C"TJY뫃[tO1w0T:/^OM.Ig$Ģ{MX/e'E:6}fjjh;_|bI5f&"OfE:(C^)<{hڂtizə hIrpb} ?9\Q+W;b %s 1Uii| \y D^bsD>AtGiүWɒsx3㽡덬S%:UEa31=H?٘IjݍiDA^_WR膚BkFg!S3dy}wբ?镬+7؇2pU~]rsT Wcp>rFPfoh0 ӹk(hs|t汭7j=t[UK{?kNfվAf ֮O%?N1<gW}Cso}d7}V_NiB("*kEM/=FF669J6|7%Ȭ=`h3&Ӧ#C VzrҲv0i*|a¹qhNɳ\>z2$qv? I]ŚE:5%O;>aAX ?&1(NmVVMnn|ZŽe~!~sDdE ~0l?s2f"C>VCLsnky5,LBIzf7viOPm97CEY[bqemYxŹ] Xr%(,bw T!%F-^@(äoJ<6l*'9i;YV_U3ÉCTq.hթ[??hޑi!0}Be"Nn?xZHlJr4xDkuClxKHuz;nmoC#{{eQ,Y78Qr(tMj5Qb4,Y-C)_/2qA7.嘼䣡_lu⠢aDئdq\"!͋(_$]u{ /7Tq־Ei]g!SesgC\xŹyUQqjMRuIhg ۈ*@ jަ)@ux!p3 hMKNtXw)Vg){aH].{.fC2i&/A˞9 C&̹bK[*ɠmTɳ֙ '-np=I hw3L*RY.<ħIiKkLSdz'Gեy8-URjq=h#GnO[" `b_`bR=#)㐯3juvsBօ) Z JǹP'A)n+>\њJUkXi]u޼(2ȭi r}:tz6hݙkN #lb ?bZ;z)qF:%]Y@<$n$ *j: T [2 y^q.w;Ka7h˓@'GP:TqgݟTi$Z K,Yhp/[b;Dw,e!LSxG&6o] T j8K5DqbM i_֌}D,ImES.%3~YU]HhiaXj6{r~v#v Һn73p]jB6N@ NܽV>tN@Aɫ?BEOCsJ]a;m:yq},"VWzgV]1Y7/u&cic.F TGi!;J9"52E? +9_| H@ʎHLr4pDinjЎ[ 8r/ ]7m8LCv=Q}/R(.Zu"=)yR{[Tmei\j]ljgl^.ޅҋ3CuF?בw؉G̊JhpոaC2-(t|>' jc!R1-SqNëZ;i '%Ҹm|s3G}Hk3ws* uY~T_ h1]\Q4F+ěe0 fc9l;m`W&P~vRp #w>m'jဣ85;hh@_KZCOkeQyOˆZYa/.D'L50O)rb}cEik˧=89W9v< cƌdzWΚ]dD.?gVQi]4U/RJcH^]F.>:Q)o}v wuM+ 0$ բ{ڽ!DYmof޹N?x/*^ufe{7d0cN[*+urk3-~X$cÕH{_ʏj5|y]s~>C4ws6| oՔh5%3211'< ij'YMqy>Û<%X8Ds},;U2$r8a sgmd|lt*1ԴAa?Oty_b"2=ѡ u :y&֘C:3+퓚=䱚.V.w:΄uX3.Pqt\h6ĥ%oHdz+v%hxʠtҤÙG0A0߰zEK: ' ަ>ီԅr@1uX;?դF 9IꞾm:$  +=hasڅW<2skln}1p9xif;dZQG`LMʍǧSN>aZ/̜.wXo'9p]C,37gK9R=az'K1%9ި )ܿ< ;nɱRb:揽-Vx(%N<˒ș'2f$2k&_BZ cxda,OQcw~#sQ&_mAN[h a< 7V-8Nu8)(&0hHKZo+MYS2) q1ہ E|]n<ޯZz|.{;9ΐiGGڼ0 ՜YۂM )}gV߃t"RGO>@L=ΔLآr(M)v&'=A+7p(Wpgmu,y?e1xn%8oRbhLx߾|hKoKy'̂a+.3!l[ Fsf:Wz"LIX}3m?=kұb2Ite%InX* 4hgKݜig#* 6+uOSn.SdS-$ft&ᬣ!}:XJͩaZkIk˩q3lli&m~#b \*1'a&\fw 7TWVB( ..߁j@ɴR Iܝ#߲ig^LۼN ]Sx.gu.7,r:\b8o^.:`{O=azcˋ3i#e^$VޑEL*$zwpX4u^6? Y$$/Tf}]r&1~o:GNc` >N~zk*3^I3CH*gYQOұm ߄{3O(+?eY0==zf2-_ dF&^4ri$Xx8i5O#5UhF,4U䎽zLF]1BUNջR- WzF7DTnmpyO#o~m1{i_0X1J5Cxݡ_ؕpa{%ҳb&ՅJŎ2lyݭ$Iy'L,~sf,u"?2AQU@DF1xmjJ6Ud֕Ů:w7ZW=!Zb},Z,! ??Xl<<ڣ֥'ոQs[f9Bt}E?ɛc+8Q-yCͳR2SB܌mv!Yܼ/XEb1rNߖ" +钤CnZP /Q/i@U(H-1ll np|pyBP4&`dL=֠GQuDIZڴ6 kLng *z Ou Y?IxcۥN pG>TJ΄N7 &k-m&q `dRޥɳkOPJ֙(g0HK6RNl!TFZQVI]R|ð&8Hb=Unn6f]?L\<‹EC+z?Xed߽HIϾǵV!熊E&ɱ \&;h(v ]/i|Z 9okX{dzM;V"ˏ/<-dXO ȑ>eؚsF9Kw{Ɍ{B .K0o-~v-|<3B>oiݺbHv`WEU ާay4:.t „ZJt۾3hY=_rk3c$ŷjUz&}s-ENcZ )~rCٹ@t1] &2^ZfہyZ]iGZY#-WnoRÕ\- }?F~VS*lZĄf<;1;'E0f#}d]p3ƥzdY~>]V1Hb:vv'f0kVFOf~C}y͌es';|+U_2򅴞Lc~$< ^ﹾz-gh %zu;+3ZQi{-_7֗h;+mǬ% iz'e#-A%,8BdAHxw^ACR7P]YЉWؔ-5X DOJ.^.ZvrON#a?)䳅߷ _{ge4Ϛ2w聽{ibdEuCi9/̒oH7 Xδ.\t)WaAɤ,f!zYR-{#lCUm8 J}pePW1vJ%^87OYη=:KUn,ԒgS3k NjԣUr~v#N ]Tqd넂 -AަeurT{z^U֫SѯK3=e}wl6fˉŁ*k{4=Ϝq癃̀RG=ory}^\PY(l=ibb)qqBfGL> d.eZ1uxPno\z[u_Oሒr$3bcD'CRDj"FVkk.,eyN#h_!S{@{3.E~i5ѸJ.Oz߿I v#R!1cME"{:aK>3%"-@RZXѱ#;Vp_d|eOχ;kJ}ѣ"bΫye#%y_ix,>|ǬZ( Y;I+KHAL&$0s 2֐4i# H`ِ~u>ATt'ߞPnLAO0~H}͹NM<'<ȹyYE1a婰qlJ֛SAx[O)Ɲ5eRӚs=EEzzw:HfՉιO70{ixZŬLO>kO6wE[cلdZ|^@FT/Eo:_BѳhaM7p}Ew?v i OPBY?"ҏ@ DOnɎ&7i =dR9ۈ yBcS:ί4ڸ%Pm?oZ𜹜Wv\_`"FVx)tC)%YiCV J^JM;2elXKfɻXeR͔t4 &fkYr,,4^|Gi/x^{+K+~̆enpWWhS.4^ 0Iu)uz)S Y1URTPzJ M+R*}{9TKyB-AQxV']!+&o!iZh583ć$^q'h ouqN1'RB>-e/?a0?$ROfiF [rC"61=Eh4a T,#k>'ac}4PnR #PDrA[4`۞7U:c|2H^;v)o&V_K;\tt(BUq>i`u>fG\vD\G.\pм:28=GmRm#>S;(OZoŠınE~x[ kr{|),($qُ.+`ùfxأ2ӣG3AUԬc&Ӹu{QJ&nEɑ$#;O W7Û- Ym2:+a/VSP_  aP&gyJ<|7Nwy) Ra~1l20 i0Xs*t_Pr>o/gHB橻Wb]4JTnah $wX9Q hލ-RbMO_Idvr+![A v2 h[`#ırhbyi9AɚtƁERP)뼑n'+q2 I=j.nY?1O>NGyތa ^=UH#:͏ 4pd@ဍWVOޅT/ڏSw5ɪ6u~m0y60"9Iv͝ ] rMG<]T #nVj ,w rik aE;R)p4Sيiy>nKyydf;v2BC 423b1 d3 R9T8kYCC#$BLع򐙧: f^haS%&Ey&6"+|GOp sOQsӅ$DhzlMXd*IrMJ:xJlV4thǾtϪoN7,nEw @}Jz>QN/iD8çXyP@Gm\ ZPjs^th|oǬH'^UqQY!L5:AaT k t?FWϖ•y>@$iiBcH'GhKHg#$L"SX|:VlXnHPX3Mk.uf7INd;J󶶼E_z?Hd0Sacx*GR6\OĽN*hq.ʶz=ʝJ Q5K6= `}Sd=JѐCdSOzf4ӻڃdu5^0Kb1-<8`Gseb>_x~o?l}H:$!f'_ \P6gOC,Wz:ix:u7?I:* ڶt愘XtGJMBn"&:&+U[Ǖ)%~vfNYgJ@wx 6ٮs@ %'g-;4Q5ΰb;DP*/=+&39E'[tj"D?-" kwKoî0| k-nc%VB^mM羏58oPHLG,LzF-?v(Z'Vz IvrX_`C uT(25{B@64[^\8t@XܥL[ F/H ~<6sMAV,Ĩbb{6òe|{kh(XȘ7 tVv6a $45"θӑ4#TrAst$({}\?nE*^x?yTf 5 hNDt^+iȆ&-Pa$V*K~>Q!se ڨ5KeKa@ Uq)!K#Y cC4 HG^?gMn}l~i!4a2ϵ%8ds$Ύ L"詮B^qIMǚ&uVN8rY#@Λ+dhda;?<41I~K%sNpĶ76؞؂WJF8Fs:<![Ҥ0( v3? /H;4gk>{Dѥ*kzU2gQ0^9^+ UF7vUy'Sd7JWPr&]Nu~25\CIYN:eHب LX%{dR\Zx0RDJhL$^) X%gVdZeOWϑE?i\PdXIûѰwogG"j$\O#&aW8qP]1nKܼg3n۞lW.;:Գ^Yz&eyi5ql6 ΆY EZ[9?]Ӆ5 'O5,`0jmBCF224ufѡ)]fy袛\N$ÎyJp6ˠ΋MLcM6BRJi. }yg_j2>葚dx;_ ]; Ҵ5Qۥ 򮤛ǍJ,J[-]H95O_R х@eeᄞ98F !`B-6]$uݓ6]Njo4]qMl'&뜕!ƺ7o3:ZK ݯ2YY]Bȣ뽞l9r@(yʃŚ(L 9+E_^Y!M%,~)?6-:xRO恾b+BrB^#N?HVhѤY}" /A"E%bk #mYz=kIJcgVⓏ8"nrNvtcc?w7[⤻5jeݓ:F:$엸PQIF=xhmJ=r}-{8'rɸ_dQGwU,w7s^$KQ s1+ {]dvrωK%celۍ!^܄|)&^KL xIO0v|dzt{ˌ/6'QVjйy(`7w} sqKXj[39:Oퟶ^ ;^huec|hh0!kkTA?y(Lr jrt|pK@#acm)?pMZ]5MzhԢbF /Mv%IoI^~Tj(Vm<:OvJ.ͩXxœ=Wq/^E<8sSȰNJzt90t5̑-L%>\{CShц#%?P ($cqwNM:?Ժho'W]*QȌp/gKS-{]"MN$SSo @WiVOʣGtxvOǬ$s8Mkln5mi)4P؝EX=*ZiKYgnadQ5{-U=JC@S%w'K\e3g&v^z?d6l/exś$O[*z'M?6Zgz㉳2S6TVY/i~_NK`S'x&u׍s6ԗZ3u*ڸ[P8a|]==kVҰEى@9]rW`=~΅x>~LŬY ۴h!"I[C>1_@SGWHFwh;fTq%P}s|&+dM@RӀ,S`1E|_`,^?HP#BZUtClfΤ[Y=;;?;&#zJx,1^Zٓ L I38ξ)3&QD[&pVlݟ.>|n.hvM5MBZ;K7J7Npi:8cSvlL)(m-f$Ӝ;_O>?%i?jo m ~":u3~ @2mw"v:6 \4:և\^k|^ȊfgIL66cI#jGkQZ£hpp,uJ\'ה ~20Q K7g{hq} <aPɜ)08>\g6Pcv)<%޿/Tm8m׊Z IDXln uu -H \:٨N~Yqi6V0Gb7.G'Uۣ cs 5~N+ ]e?SI̬fSU%-M]ݱ6Wui42@ ?vq?]r&@9?Q=%:Gh<)lF_ 1i )1AeeȐ=ӎ-FlIʆ- _L M_Gmu^ 3>&ɝ]g|cs aTI<~!T~{q6 iHOVOow#zEE}.:OxΧ3=3[u8 IiG`$_xڠc[24eC z>Amt>*8i^nfPu6+?[|'ETYUfz1hG*I@'IdvnXUf#؇!zM TF̢CHqh#9賂z̧%I>!lωWM6pqC6|5OuAA(>Z(s cg%Ɩ ]4>g9ɍ0a;B%,Y/J%QMƍwUE%=yH v@#704o[ty:$A_^ y-(ΓNZtY}Ī)Ct[P u1^,elb.þJĚ3u<=o5o'P'PsĤ`^j2V( =EbeM(IC㲓O4*7V/ʸJZN(ȏv鄵uowWb7]ùNX=TQK*+W9<}W"SéZ~P7I)m;a.Yv10n G@ ҧϊBCIlWl_U;R+v|ݢZxhl&L%{\H'h(0ׇYotR_h0e0RΘه/;,ǟuQISG$ NUxԴ\t?enhcC :{hOtm45@ත2Gm`y^5fmh:Lun*42@'xODי;L:ilfeEh"$~p(ôT$R(xN BuK]mAS&Nx0uGL:av{c>(Y|v=&-m$V OBfX ԭdq(G"RzKiJ!`mw$bM[|TǓgrdu[QTY_'Tt =}hT(V:xAMʬnwFn0V6MPxJtnoV3E6 'Yv-6U`(Ź=Zm;zX ͥ1mDH;Ż|2J` e&ut?5FߔR<ƐōHU-}x:kΧ[+dz͌_s?}zX ]zOfwpF>DzM$FW(Pwaa{ZCVh>¹!>:Ciln|DaRSy(>GNC v%gj[uJ$_CY*bNw8pb"Lx<=_I>M>58g$x~~ѐa$;TK:0D<`X˼-)A Dqq/Ksy'KQ|x p+аz0we Z1%r:1Ot.!aMkH]O`*Ӝ:dbYZU띹[;;3$gȆKfٵ|lsgW·uv:[r}6z dRȌvGR$=.RVN:MN~Fo}+gzm(m_2D&`m ֤ {$c-?fst;A=ʠ5i_l"ϛ|L1ۤƅ+ o٦Q Чxlgh{9Ը*#DNhCw`aH7M-s@ ,:S:k{bs"T@td<0y+.: ԳT5}!}wP<:90`za,>\-t.()Psy6uN:JWG\k @enzӥG*u8EME˹>z8 kZûq~)mLT0}̉\rEԞn3ss0AF[? kԒB ñr\ &߽@.cdE9ay}z߬Y-a[#S޹u@%#DuNFmEHG \~@ =%c r̀TOV%RUzY_x:﹭s}usqX[ZXE`e>L =geTיR.V35E_ڨݣ `%z):p n&U5H4Sq1t=8s>Ξ'?~9#A/ҘS =~v& !Iْ#'da1و@'a+ iqʑ?Su#t?`t@ |9mUn%'աwGVnnj4j$x"xkVL Ib޷l okIE(;δ;f2!ds 1\U#)@n_sa?;(}v9Qc|``PN3hʰ5hb5߫9ԢzjgTw{k$(.:>;+(%2)̙ Rzs!*ksDzDSO#"c̵{ JO .uS 0 ³]>_w= K)9ȫވi|@FJP5ıFzDf'+?+,|gG}y23 UAh@1# $evy4jB8'f.tV$x<[o+ĊEh*%rGsҴS0y@MX_-h*5CVڤ=TCIoX2}:Xvxe!o)+ ,B;ÀWn#;·SXffC?k s.l_޼>\sG!WiTj xF~H8LXUE=~EkWz@7as>k%gE)Ϳܣڹg Ź6tJ; !2<|pRAt:}OO[Olʔ}yD}R뻪:ΧLs*3FﮐX)DӁFSN!<;3)``Czv0͝D3vdEE/|wt U2kq1!h䶁rQVϜVr[5[ݑ*ͤoH`-#P7NkH_ڱ&diæDF%ygCc(G$3As]v3:! %~4}f+gΗoYjj@Zib;D RS-|tB eF/ߐԽ'fİ]`]?enV^r8=e|z,:g:P4Y") $KY4g =ɕ)G&\UY|q"Hv=qaaUƉTş[HTƬ,~2Z"AB87T5\x~,%MIQB7-zy󻑽_g׍u!嗢W B 4G_3 rc+F=z_j0~xI_}ʎQ\JbArdFm.eĞ [ogVN! "kWIbJ?Nb'GUolƜEgH=e|A>ԺGݯ 5\FT`"_hKCfگ[$/toWͣNlUf5"XKt(N P[{]UtugZׇ&ޏ3uߏaHMVU}=ف;* aZ鈎hnrzG!5RܳhO|() cajسsYP>+G|3eO|kyVp8'ma{`z\͡6' ~^a!s!Tems#WYu>#A_8p'4,X!O &T, Y ClG236jo|y-ˢJ%JlKS2f喈=l (aњkN&tcB!- Fr/yxiQ%cSg yP&gDTx(Pʟ<3'aut8Y Qfg]-XwqT'K Fݘ5ilv7&޹R/NI9q:|vZũ莨h&k))Vx"shXze"݉FnMVBUcu{gƆ#[m~0<ժfeTCv^fiHlӘ?toI  cxK.;rkiUgzdSK`ӝw]vb 6qQp8_8k5fi5c[PZw4OZ'Ƽ鉒?=' ߢXlj0o>:M IypD~!3 ]t/9"O#6CQ LИIl<crP+b2k.aD]'nee$sSG2ujg{sk/~g(b=e bȩ\oĀX"b~~t̍~ޮn;zUҼLY 40}F+"|G;F4q8 qR$ѡrp8h# zzߍ.6c=NadL!P%E%m8cZ+TOCa\:[ŜxYBEYisM'CU9F ѽ:D#Udz6@ʇ 5[ÖKBؠҨYfNTVk- 24p/Wi tXn~Džx"MvXevla6eNм9y5>_ln d >_lO~DMy"l'O/ 8r)˱YTbc\R)3=BM-TBytT:hV7~\o< |5|wAjCɶ#*y+xfb!SʅGGs`+$qRػ?IJԗIVRbJQ@ku/ S'isj=k;+QI2 . Zx^'mOXKБɿ ՒXqb 7f۰k"M8&o٦Iq춡%ߟ6r2{;w6~gݜa+<7z=*R3P'RY'e يrYx؈j[IE+a^I|f2M5reOcv+,gvwȀb*zw;d~o4nw x6gh&eUḌo*Js}?,:A~{<]WV)+Q! F1\Fmk?sR`UeW}uZQG {%*q%qA Z;BEsج9Y;.䞴쓬q\%25p~s|dϋDE*ӊvXfnOGN tUX$yCPԎ9y@Cn9χyq8H4 > =ɋsKnhBdJ$PsTyp HϿ1aB$)#r2Ku"M!크Ο%֝1@Bd?P[71 u8rx!*ÇhE6\Um4:C!MǞ⬼mϵޡf\g(mv$ +`>C\ L^Lq:$&CD'ń2v1: {x04 XKSl:5Ҏ'X ,= T?t84d!aG,ΧbWnIXѐ.y*|::!LeM)9ѐ>.PCIxn,4Y5"ܣ ԯ(ȯU^A*ϵ~TGByǪ4?@Os_Z?3Zg")/:lZ)iqS;iZ3 <6d@˻4dVY /XE1z]"5'{e5a+]/VKc q=>.jC(KNu5<̱ʴLLKAq-I=Y6 z^ |Y 7p$^Dxzu ƨ#nD['<.ͼviX3;N7)I}Y3hp\ݻB3V2ev[ $FEU2ViOj"%=Ir*٩;2:y=ow~"m3t·3jwjpYpnT'"t.ڲk4p{8a)ZaeD(Iᶄbv$[z{$ 2esKv;wEyr@,H3fgYg  7|.qieBHZ%`"Sc+L z7fqjN;P4E;j;n>"CÖ3 'uK{jJt f̐C},=-ꢋmo~D K0> ?l6|tcdyM"'g~w74Q(`iiQhlJ] n"gi ML=1$Z1|/㸥#^#s䔱ĴtH,x:ѳF$ jMPW,RsW6d;.}ҞE+d&ֻn5k> t* aGgI5}KuWΕ/*ݓbXSs2ah'o~"}Ab;8hرH&m>ZR֢Ꭱ__O$#P~~2do[ƕ%'vG1_>jq!#NQiH;i٘sZ7Lmn_JKݢ͟7<` lY-'L) Zѵq>-,h,$: M-k~љL;mmo7Tq>>ӿ=T1Bh,hՕ2KG K=QF)!)Tߜ}B*-E74-pK1IA˞Lv"|-6Zb!tQiI:ua' #$Q]VŠ;$ZQ%|3c8sh!_~ԨbN9 yGשsnӖrE:!~:B/Vh` r"}YʢWxwUbzmYCh_m͹i+{ߟ>z/P9JB}u=6k;i]_d{pˊyDQ˗r7(6MҀ-{Yt/F˛ⴈ87A4h\d/JխJfYv(-TpEXNNդӆ^K_>Ѯ#9(N|{,tKH +N#Ӹ\Nͻz>)Ε{Jq;m]_^"{NC,mi, +тܱ{F׀!TBRj]šUyl?5mʼnxrE$,;=(wxmHIP7 x ps:,% tVz^{ы|'3r6YWA + )ʬTVF7a 6șLXqF$rM1 ⤡(b,$L@6o{*r':$Iįbs>;PHa<2_2geqeDүJiHyۘ ;J7 s5֮'js9g@y}ҹ'WEp6b+M4YO\Cѳ`N3D9wT,=M N;SVm~.}>o+#[G<*nt(団 _HN±v^]EMfs+c$.:{lkfy)ޛq%S/kWfa=/dg[yT.:ռ'R㜲9[ SwP2CrG_M>Ӛ}ްrSu?9BhT^BGy;goˊLK<%(}$:Fti'b4+=H8IlG_VOeܫ:GǷ1j55"0Q9nKޚCP8Zz0~hd4Vq-ew5 BיMs3 cPa_!e.$dΛ\Y'Җ05ߚ)Z4v>D͐-ȓѥ8oXjC^$qA2>sFF0kyX|"hVE@Ly=}Z'Ougn|uGPPN!?E3FĿONb#f˝ЧY7tvFBx,cgQ}9F74/%FbVΧVlFxEsvaa}bA#Ciu\CvB#ʑE )9t r?mvY՞zBuv=V+j[쪱8$,TEH| &D:R%'I _L)Gݶ N@(r=Xr(sevhY;$QF[lr7se0'w!2k]" t)Uu|s7΄HS[5/QVv4(ys9`79gP&Mu%TG:5,4ѻnxx G_xWh:-R|}x Ϭ'Xt ibu 񡊧z>3ԘJcqT\ 34OIGOېqH(??u8E<7j%/+A-mt^ ;4v>4p>Jn]Fc^1nqd5=ҘNw0E6r!tx>7eұeCYjξX9d8a)\\!=, Vs@P93(v4|)\ll U g$EJ=C2ψL 97gSdbmŪu֙4^3 KD^ϖ% P[xJfdGM>EE>;|fǙDmz8mS>~9f?]?%+[p4r4TQP?3q;4h<]'7n emEYE7Uw:ssC}h(WTHMGtbmX,$BZ?D'|s~xghE@c:oIZ\wthrjsLB} =zn;7^]Lxʼnx.C8T&,:FiSp"cМj~4r,o/ yar*W'AǴ?mfV&ٶ~qFt#atL?9Wkl'cW*iw}I!̙{=RijC6f6I^skm1]>lRS/?իh5+JgO9{o{**@xȟM=-2";WS!%ѻ6'kd](COqGoYH1yENw.Q]88"ޚ=ǰ)+o%}z:Y3'mM/2Q:oo}D nΰJ").ZQ{[tY"wmYi=N;V$O0=.j`Cwt GL]x=JosaYQIT%e&)ȷ6 nZ -|T[#-񾕢¡솴ps"8y!K꽠ޔ -?z'Mf3 ֏@gh}25M?w2 7U7'nqB Dv$\lz5l^G.8h_v3b2\8H/ovgb:hj#Pknals `}RZipx: w<=Rt9U~wb#)愊ǙF#Lhwt;ӳf'D>WT KIbtwXPv g|3QGoWLzAYik'H~[%++"'@Lfn3HSsRyN;V> qS94!ShAɬten-F@S̯#hQnԞ('Q y辗 + ]F"wsZѥiCn=5'μ Db|{ppg(gIMe㓩6f! swPNj#:zeןʘKt$r6ūZ#:Rz#< qZZ 共:Wy4W8:vh[*MVii<fPׅkO?z@0p~VىYhO^NyENJ'Ei2=nq^|dyWSKJE;SP^;th[cj&C9/{> ;W|M976˹0>O% RDm,%OO'+-wX34 wS%~bj{k5<}M듕tƓyVpvqfPa4g#Z^5s;#Ɇ/T O{5}CAkgl! 5䖇NhSk4^7,5ut/z[#B6Q;+_.Rlt|%`LT$Baz2"3 uGf>ʮI S&k{89hgC]& J˵rH6p}OE Pxqi8@9 IƠ}Չ>aY*xLʼ0Yװ<'E73'OWnbFMgݚ1 L`f.vM~e]6f^慖n1B0} &{rXʃ'zZv YG>O j8`.Y Ȱ B\GOsK[2MuDs)jpKJL{d;,8G&8$lN`l h< ʚB$$.dbyӆ[&z,9mX?7ӆmɴ߷5n)al-K/k}#r.4N0Yd=;KZHEG'+ +ɋ%%ƤQH7ѓLy\O)KCmb "MGU(170gn*\GƺnX5*=Hd9NX a!L9_7a·TOtt)GӉ=rR(#~UtJ<*mhπS8NZǕUi[|O }7hBeyTXjܥsT_~9gH<{m.,8.G6o5*NMՁez Gd1KN%.Jᜩ]|KcZCiy?qR:\*@ML#՛ifJC{Qft#A81NuR{g0'+qeb9LgEsWٙs}kpD`TGZ?ښ.=|yo\TVk>8Xd!H`T0-gzRxk)ʣ-@1EVnndO % QqYX9_֤|&u'6:v|`"kCƄWއJaB-kIzg>FEǙ3i6y@zK7vH A/mr<Su|t`w?y;Kj|ޱ*)sNL^L)˼0 zwl~Ђj)H[##k iS^GO~͍`a޸ĪSeռ3X?;3v9Ò-xx,_Ԅ3SRn2Rso4 !ފ*6CI k-gӃD֙<(!Q+mBDŧufҰ`'Td H9>THS[+;I*Ul\ Ǯܞ3?5Hk]u^Kn.(+ztTD JnÓ'hcIe3xxS_hzx+蕼Ho&@7ܩ"fo"0Ms@-ו+S.@g{rF_YJk3^7Ar 32֙6KEىK?<3N'Ex>/_%R@yPZRS!S= C/nyVGZbVx\y.^^/L8+S;jtC~z3S.CzIbfyylkݵJU-:!箜5DE_/pdv(6$Z[pLd$f@6{RV _`3=f.&6>A'BL4Oruk*8 YĬwT*77g2/`Ɠ-AG) ~xʺ6K{gȎ~ei*$ aFK&j8b-b#"7*iD DŽm/iC$V=DXNvqI[Ƨg>g5ZDe+>Iq(DL!YVz8E7Nl?cָ uZdKȰևk{1߈4ܡ1(-[Yt `sÐf- OsBҧzmkDpTR>zu6f5)0mlEWH=t>0&e{͐_Caw`eru-&e9?&p5y9ul.9@;n;4YSX5+ yq>qXti32g(xT5'yNG&*'N}EFr&9 H]q3/ݫԞNd:8W鷍r^Fa_oJ.إpݣa  גoֱ0%Zg`_ʛcc7E]]b5M:kHK0ukcY[q9j9x_{.Y+=%|/mM"uKoiw 31o0%*KQݵ/r@N<[=;:ב!kѼhf]^y?rV7" "^n!uƅO#Rz*^&mxD<>]>/:~gbȹN'ӡ_珏:7w?xnkR zHYeStJ?ai$e%[7qg& 'If؉)D.c",cJ~N6#wWYҔ]*XŢ>< IG쎽F>B"`}[bV"vٱ@@V?qn G:9=Z sngg[x}݅Ͼc L§Y6ȴ"@q3Nf Kq"DՐub}eYB((\v7 :ۃyYh Ɔ\#8G9=[Ε% p?ަ~g}"{E7tk-uga%+dzz@yAwY;OW*ssk3IfI?5XKpX9 ;"6PlGZi`c3hK,LJQOiar6gMAwx#~E;QI]u1Û09 g*̫p6æeE *Y^_&lJdu.9<M8;S#/hut2NDYdnI~fNjg-g ig? r+7zlK K_\d) <,n'i-4et5\̽d(_d"vz?f+ 8ggc(ԯo[B$`y۞5cjWC< 6 {G! P>IAv) UsLh<"MIoO'sޜa{25Vh.Gw 5(tGԡkKnuhǒ5kUGQ>A 'Hg#<יa}q@W;p?A$AY㼉N^/*E3-wU~N{#f9<}Ze}3Zi]@ՙXbXh mֲ-:X|~4u2{Ygyk}GX쑛*;~7|kƊ+H?BY)F?%)Dd4[2Q)&ٛ H"#0ט䉷\7rfn)ai~AB--l2lι8کLǨrwt݀ U$2 IVX2#;oݮY^Ql</hhݼ@|ǏkRI)T8IOf\e3;,v9s̬ Sxz2c!=[=f- L6ﲒ9oga&¢7(BXڎN/ k< Yv0ndxMTo.jY<1cwf)y0An;fF) pЬӬIZ=(=6.E=Xig;6gxܝ}osu >NZR(Y t"~z !;{ ] 7.pKŋ9gWPֹehӴK~VB@,3̕= l"árBJx5TD6kOaN爽z]ly |Q hIoBMW6nwW,8-ޤ·a# Q*O2.ז@Xb5|Iߚ~k {Pޓ =Lߢ'f? B6ÄA: uj' bWVT.yPO7+'o"Wl+*i?ݎXtYqP8iq>espROԶGJiG.%qܦaQg@]SB䣏Ghu>N9OҤK*zRLj{t0'ѼMXk_^]`nֿwG؇IQa󗽤'M뚗p.i\/(b0vcͳK0M {^HABDK9 Oy)|ft[mJȒwxWtau^t=T8 h80=Ji|Ǧ(<`2oZ MwtEUOXƯKYBfyE 9$Y+Kǭ$@8ߌY N$ax7ѭӀO͹QJO'*ODWZG, v f\$V'tw󊄶%0W1={ƶ1Yv̋(=.U|~,[u:7,*+ tjbߺaZmwō)Z^ɠdܯk^WgщJh^ZW{c3dVqK僧 :Ncݤtu"ҙ:lɻi=I~18TbfD9H16#udQ+üNUu/9E&\e›#dz۳VC]=(<#>R(v$wEYcdjEiϼsQv0DzC?*-ygћ[E{*vA TcKYt"LexN?i:Q"vGGLJ#'x7LمXDE?`Ky7{ZY08eȵz3P hid͑ƀ@tۏ:,=ِI}Vj`>@cj'f`֙; 1s95(dBi<|<+AwC]΄lbWdrl"Y Z)3>eJ;I|$~Ě|T"8go(]݊F=X^bhMC.; Zљ_%J<2Uq͟:tMr#TF<,ѷ![ 5)mew^@{Kk nY&Ma)Rߵ?x'YV.jGGwJir]d:@g su*cC:: @ 4q%^ye4D9_b΁DVEo.)~anVG~#ۉ|0O& d(Wۡ=s!.5ogēS#&%>~w;|b$vݎ5-v c⺎M}ϚY~3'wyd,Wt$.Wwt~W>@ MR s&q DKWކX{A~uw5$u$!%HnڪVemE~~1) b[USHFַp?/0n;!S%ڊ.CJ⛟7"ILUjj͕WH;/]sHVlR~^QjhDR8';^CNR:Wr ܇{$kH&o,r!<7J&k"Sm^ )Y,^n6G.g.N:4o (Zp]tQ:T//^xUDzBPGiX#}+;a.N+dL3PM`zM ;V'jk2QBhZ Ԋ&=﯆Y7#KZu/RJe5djRћl6mlo{GЬK1uz1,t<ΡX" $cFmwBD ߽ϒ_$ 2qb>pJrs0hubFvƬQo"%{0 \:GMVMcƯ~Cvlj6 Fg[+ᅁD~1r~ZyU20ܚKSi[t]R= .4(c3-Nfo3vB"b$5>}w8b$6ҋ|Bsj~zO= 49wp>*+f k q)P_$6='memI~4,ᰟLWxj^\>%*ӣq_B#*={xv0ЍBcRhpyYXp`` Fn3"k] 4n&]]pAtx $ZRq3tj s6~[mcx9ϧUCo9| 0~w1Zp#:^Cr')M>,$HIi׭B@MIiu!@%U +{?qlze4ƀ!;|0_hB%W&CVExXs$ Y ZiJI:~QNvQK_>ІdFgP@ā׆*NXߐyAtX"I~Njڇ3eiounfU8\֩Qu?~2#`_hJ/G7,o[(Xם-7cA Z;TM6[*w^$G {ĻuHAv%g\8/|[ډsH%Τcu u]C?sV`eu4tNG:tsiX8cH1`Y2e.*>|w$}i÷wt؟ pPwwһ2vS:/02l b[}m/QyaAsrՐx[249*2;ڠVԡ3`Eæ?)*t؛1k.uXUF4N~lykTgީ=ό{^~αy|OI03=f8i")d|:yf0Yp}..sE+3p: z'э+5W/ΒQ_vpaӍ,30) }7f<~nM }7!Ga$@ p\fR&Zqޑ1gpMV^,%9c-Ǹ Z Xg{^R EfRA ;+ovG|V2=O~#>E <"'Z3LCX/Jc(2_k*ODU{/ܝ )ee0D:f0rٔ)"-?G;ͬ`/ 8"f*AXx&+=~Pg)!hy%Vpӹ_OD>'8SEnm% çi\](4:!)XP344CXç[H# }y~z \gvbv-35t9SDGʘ#(<'ꥏ;* 4 VX^wF/ \Hz^'QP;V`Ú'sn3NE*Nl#X%3=Go:ذ^.Vhr^xqP K{_y9@w۹뒳Z^g79 x+HByBG3(NYn-=l=Vc-[OyҀw4c^kZy"zOҏ~ydNa[5bք3U>xjNކ*IL8EX@x zYiktB_*mrD>jpoM~d)z CH*4šda{$=`.tMYo!*ijQȠ1-u/ ?X};Nlm'Xk`g(^M=[Ss3/9gG@xF #-*xDž8OI5oP ' mVC. o0lӎ5ϼf]w7w䕂6@dioQ w٬~zY։  Ps>4? XdЎ;7ڏ-J n6׺b i6 ~b2'F՞AwV!Uא; ~7LX39ÐԹyaa}b.x7xn# n<Д;iz؞:}D|ru%TO?\cd^Ϗc̼X -:r?Wy@ )#m-->t)CFVuX~v ._V:&hR3bRT[b*:sN'(z l'3:D(j.鑰𛪌5h4HQÛ9]*Sy8s;iפYB}^TK6q`7$ ,I&U,6|껑"}l[+; )RۡisF*-2/)wUj$J|@53xM ABj&Lt]a~'by1p3D+$5ō,'(MnJ ^0l>*㸒#ՇT *v2|lj7o>y!mߍSz<סґC'L-9 g d]WkG7<1}+'!mšt8B,TRFe %ج,^1_(t^` v!dx`Y$@Rhx;/;?#:v IXBnl1H"+kcΔq:7M\M}KQvñ7i(SsSu*21S#J{O g^.|kzPg  VMXLGD}y9cSօ: 938Xz=v:N !.oߢ1,CȆsw-F0&<_nI:ZoYƫlu /-Vll,>=Cyolp P,T%O9Cs>qriEϴqΒ~ ջ #Y;5y>ǘ(Bհq!h+.Jxj tL (~y*ڮa2|-ZK37=އP߻58_޵p>I0]S7hq /Eaʝc#z zE^OSi`fYzuI]t ubj'^Rکj=TWEJֆ*ul~!W9ar y!vZaz!a̞ǕxĪyPm6 1F R`uzPbML\K?k״gVlV'n1uDw=|tFZ ;ug;@ƚEl+Li7e8o/*QQ:HWɸULd,*W6@Ii|>lTڎP'_d}3"Jfm颰f{Z9+OdkJpKyn+0 >ȜaxԵه:m:fx"OӴʐVG4y:335<%6D`*e E1O:V^%*Óge YڧYOD?xӲlj+wfqed*Acɟ"(f#M` }:/ɋĺW ˍ5:q`-BW:E%H9ٻi?rxnF|VAHlqwly{= C:m@)V>xUӠkA~j+9f*ZI)`t-TY]zgHt.ľᳬH_Іo9S(p& _9{dIc#sȈۨr:MDan`v<+o%& eY9OI;> +[uCUhнN؜q$C"s('J^@RXсLe^:cR+Yq[{pM|ͯ]#)sn)% t_f^z~GӧD#f5٪ n'ϤwfGȠ)SU%yxYa4#4zVw4t#a Jd<8lN\I~u S5M (}eE |$t`&g 4*+gN=oST(s-ky.Y[t.XC;lCPfR瘈SV#66jvn|5ms<2.(+k?1 =g#}$vqv}~gՐ0 x0` 4K-/SOp6%58s; S-'J D ?mqVwH%:{<٬2.~dOZLr\ߡX8k&`b8E35ǽ 1?|Ru`c8HJ>zX}D1X&'V92@$H0XmHwjMG>e.x Lnu!0t'PExTtp"1 -GqT.-*qgb:$O vBoyY2ToEi_/OA%#+l*Rm|藶Ŏ9ѦZ^}@YDR?0yڶM7ʴOkPNT-SR5zvEA\ ˑ&^P\n- UWNO[X5f5*1z1[PKT5 {B ߂'䢐{EI@_4P/nrh&75aOVE97Iٳ gt R*jn'z\V J:= vy5ӑB< h?C#2v(؁ ⣙&JzmD0a!I[v8U$px~_@=YU!6̲7| 7CqpX3:HcDuccX66B1'qzsTT5bvLӰ)$*:ackF'Wu$:3(5S 'ֈN؜ȣlP&+':0TR^ 3qto$OjqYwq?LCFw4wq>+:K; 9'ȜgdLwĖ]t}6ń{M@W'5Fw|6nfZFIxU+V3 s2̐ KG/<-DpP΄)!i@!mO(,=g7wNTݧA]l7/9]SeсgECήSEC*8oR{Gc,D[L,upp p)SjP)P#_Ckx=5䢬yL#HP@h[t4,A/(2e KvVu)E3:/ZiҴ"IF{\zp HȄx4%#1 -%t 2d`HNtd.:<˚ț]^(SoLR+$pn"ýy):2Td nwx;EFLQ[π0ySkB؜q@[ۥt'URc ;%׊Lʚ6f)6+U);/5EDҮ.GMC2(IHD1,XiɪCZEμNcH; #4Dw9yp#_Foձ3P ݵ|) )6c2 Ě8Oc  8NՉ",+;.[(VK9h]+Ƭב " ;5צbhQ.8Po:jl ':+Ernq^+DJ8-ҸY:%p.k w=NU;9N ,*BBMl+<@yKh=ћ" 7Z5DeFtnćUq tRTe86h8iYFs: 7c>gj’ _ [f_7[F\и/$ez1)$ЋP f;~Su&Ϣ]| { kȞĺGg "ī.Q]FdB?_}7 P9#R4-ӠL^'NUbο~hvHw⇓nk;.WsfY}(Fc%GF};w5"as0ɡ="87͙mutu` lCXdEڭTb l `%҂HPּLY_>ƒdL8ŧ}nv֕v LaY)Qw\a\ჃpvjcY94$RSxր[f#o#JѨ8Z`˚ %"da1DZdA&;1P y! [8+·e! oU~?3ٰNIJ惞J1_39ӓ8 =I3_ad{ #YCyoTj*LvV~xS6 I2kHX׸MV'ëB=VqY*k'V$ &7Bm+l(;^'Two!bw͐Q[J‘9Ch$Ar&gߚ`s/PƂj4V|%V2HMBH hF7k.7e?P9{Cr-~Yhkq`:AXBZfjg+I/ĥ  ǵHE ,A?]\v6ˊs: 7m11e5'uOF6g]H47!PUlXV"ހ6f;2]hYrs+esP.C-gs UkV;a!{O=ldH{s&jQ"fPapnX#O3w(HH,bj"dŖauM-ܤPx̪.2Ox]٩Kun2{{okϱb2К@T'GF?%(08@4ks?c[;gGWftub%RE C fZntI^pJߑ,dYDYYz™LY͋/@ܐV܆FFJ2e>~hv`lju1SmCTfZjhv@~@y8k+}j Pk"_"u O8Of) X9t"153=x "cߞrDc)I񟹣!z#t wvs7g0qq" ,.کpǢwG0*ư@3"vѽ_]hU5n^CodVOdAz2l66oCNLgs+22pB\X&:w >k x/D//hAp/rt.:,9L$?/p`͹|gΝmK#ꯡt\ u/:IS>kԝajJ篼V~Ni;znLڍlmª _`~CV@^-R.+*'cp|+ߵ_b͌>}}G+XXKXK ~7 O6ܣ}p.{{t̴ "N݄wiUuyޏ޳jIE?u C:C'wfo P-@Rp6'[ 걶4b 5x=ᰧ9Xq+̌')m'9'dϳjbձU+A'żTnQۅ7 u~Kd1ae\i(KcEY ě;'njj@SښZqUJiub~yfɹ=ᮼ8E¯,t;B{"~V>rXJMʆi?^>gd cTFb*g5%˻(Gt,3E( ^[Ks,!VS-w>t镜iKJV?Ŧz;j3&)Ʋ}.<ӶBC; 0-+jӱ~@$Ykv \69` _1m|vW;zJJP"º<͎>)Kʳ"Ϣ{5bճT'iI ۏq2B_&䌂ƈBqSYMkiEo}Shn jJTZP GedZ's_z=" M6qsn^<8B'zgR& 9>y:Jdtp\Ev1K|iMZZ(\r)c &Jn[:YNhϮt?n HN3A{HK&^Lm&,$czOgūD#qY85-/JV;s\[WGut ROVm|Y@X/hMpoz?Uq` .〹(*ttv<F*ކP=ڽ"HJ,;? Uc-1ƹ(:-l+uӅ,\7nkK{S2T~xCm{Ջ@>%%Z7d 3(:2zvjPCSCt`Y@%I }+@ +4z3P 8dۍC?E*yYXTq)'lst]'e'A Ϥ0ɮ۩tRo9onўJӂ$]'@ǭR3f- ('#cpFq&ٵ%y”c4%5]#LAoO/R3\rzOm_a "5Gt>E+ ȦoY,qnL v/Ґ3s$0_>o7`~:V͊GB2E<{J"/Uh"h(iW[ "9Lmi.lCnGM/Mu#VHuJt+I4䤥=4 הqkOnOzn8S8.E/n4LI9Ժ^m@1b 4^Eq+"DPCq0^wE!ZV^= C|Іxu -t!642ycCFg 5UWS41amh} SDE;"M"_hiYR"yËiA#HFjt&P\a|TjQ4[,Etc*OPRC9,S6y%FjqZT@XkC'$vOFKF9 a~hj5Y`mG2yx%!3O-- 谓4"iӇdcc`4hӁTϒ :M3کYikW6rV.e,2%-tLӊŎ;,v.tQ(TGҾXu^(x%SK% dn36uFq7N+3qvXn`T ;!9~.VzE&Lou?Q GvJc< yF8Z֕wŏp9Ox|gy@y40{ƺ}"xL&QcIǶiڦq~/ 3ΛBܒcōCf:/`  8Zb+j*qidD}-̼j;=RzclP)od)C703>;dX9 )eMVboI>ǣ^ KZxM8RI nJ?87kĮddZ;kLR$"=qz/O9uM;}o$7 jk`SA\ <5] ۘ0b-{}g-OXyfqJ"]HS./w 9Ϙ01n2qf{1uc:6c)"NGJa+ -atkI0f2yC-H/$g&I;G+[ .0q~w2i<C\iJ:wC:yf 2ee(y4om7.+賈YhH64Zq 24 oP>LeE!SYoʎ PY`oO :PS`o:lPGRg,'j5;'gѐISx2%M/̶~SZ;ޝ6 DFpdBc6UI_/K qXRaJkJlC|߭Swo913)+T2Yv"LC\ڽ,Hb࿰y,6#ߍ5`t(Ð%ssEKEg/@VF `8g%~Ekt48QK_*Nިs#^w]:Y=  au#JW.{S) J,T/w MuK2W}bu=-+R/qB75#۸Zm;z{X`s}Hyf|@jtsNbH҅۾['6<]װSlxՉR#2 OGl*Ȗy=hŰ{q&y_hצB2ߤׯښPY#>P~ǶsHvtRߣDbxnr-vY iMs$(k<\y4Ƒt/lD q1b~ %t?qJ D)ŏa0g!7.ۏ1&":DP|$$Ewrc%\;]csi<㷦 y٭ TS7qfϟ\#$un#s[ZGoMCk!Ŧdָ/8/|\.]'ѡ؈ˇ b|+k~>;4"t"`n|QEO/WW c Y6_>3:l(eT U\rc]=v"g[An&eHӦiVjB$0=MigS[ ·^|چJ $] $X'v-kS&yb#WҪBR@WsU+zt'[m^a1a|8]ˬ\q>@4${E:UZ9)+ CD5&?)"CJb'[WnEwա L\Nڹ\W ׉ 5tZDrj^i'/B2ߑqEwoyѲCg '(S|ʢs Ɯ:WS;_^ȄL--:Ax9Z a<屎۝{*8%[g[!7kwoZeeuA/֖a4/Qt'Act zu*9zEŅn$Vv82 Y{|dJT" i_2UMttԔ/3K(#e&z[#z;3MY82hGE".K`7(A_k:keurovgJoӿ~KYR3?۹ JgKXu"|:1Ftp~P^FNTWyW2;~%F~dfpnNaŖVAtNckܪ4Y (jQ^Ѻ ؘ Ԍ`w'MDSͨy0Ƕ3H]L0oHQ:4[ ~{ϕm 5ܶX5g4ɝވJOlդ۫m_j`.L]j~%,VMzC9)nЬ];쇹Rz WW;$wӾ?w"v ޣGU@*K_*ͳаˠX)5>k-)n/uUeӡW޿3Dz3@UzZGTh3WDkjhŚD% k :n6aĿa2D.6$uIc39`toM/li>Oy;}e}ҝ>D T*mlgM:SDkK+EZz:MLNԒ+_74U_{M{`i%V 7нTg W_eƫbQkHRR,.ZLBUzS3%U  -k&ҌaB7fօ!ͪY'x]v\(oe8C-w=d< Jiν @'aʊ.q,/m a垚˞7F e o):wcUR+]53K F(hہ*$IȚΚ=9Si?M q~zm(܍|wCځyd KZpJ;ďݚ޸0`JU󅪵9i_2V(fet:N[$1{91sIH>{$_D<ٸaQdX-Ӓ 2yyH4 xAPy},g*%q Q1ܘҙJ<ׄ:4-VFn%^8[V>w ,~i9CyJ;,MIp̘Ӕ=I+"!SCaɁ>CZu@+Dָ<^I j…<:̦O0>\,\py~"N4VG+ sA9YeC~ddG mĵ6o M܏n٥Oܬڇ=ŬIUp5#يȆ0{l5{!Sw~$ThTsgrb3#hSfQul͝X3OɑЫm@'S) LC0t`v!8ھrc"%̞=SD| SD)7μNAq$ӮI;ŐM Vt^AIpqgJi3KtW"hbBU-kt1s!ɱ FbݰŃy> Y'-38 1d823%w tF"YptsSOOHs㏔c(<#M$4o9i?]={oundrYoTQ-\䠲F<$!o7WhP0(^Pd +a].ʩ9d?<}iP7 xf%-4,Jx,d`edPGO-2r)88=u>uռسCadV*l+qB}.k`?UY\YK22DJyz M݆BXIinmGamQ|eXOL& b|&MMɸjJUS ހxd,AUQ%kb닓El,^;(V-zG77YdWb`:ua5q))"܏8]ew{dk<`@)^5Z;:)W"U(9bıNyf#2xjM;dÍ=ӊ%sٺQh^7ew97]GNg@Xto|zyhF=OyUOY2_Hc8;`~\T,œ̭x?rLDgcsMX+"!q#[fܬ;PϨђ%2JWcF eXWUɱfGGXn;GJ{'e-fK'*qN?Cno }藖Su}gqLlqy@s4'4]u`sAFvMـ_/0C92OnwLs)YUE4t~:"Ԓf(9IR$n65Y^6 Vkrw@6Z*cpy[2㧁uQSљ֝cV9L(4!yNQ[%B NePV28ABCFu|'4QYJBwy?3xATK4ys IU9ZwzDvuA&.v/vSB;ɋ10TB9VI{=5G4Nk6ƃd7?O M'LuP]807V:_6n-GVO"ND,ix erss9kX)iAG $vJ mc-& -py`l̳yJSMox!4xy͟6+5}|2N(ʍȅ'd-V" jv9*ѓ^b-@bSd9$d< ۊ3I^fHggĴw,7XL{9?hwn>8z;0>1G!oo%Z9K4 'LT@K AE܆qpfaӀJ-<*(H3锻r ʚ7ke;#v%UcʵTNBw,Н@YǓ+t@ q<)IJO n0sՌLuU#>]qTr7Lb Mۆ3;rJ5zyP jXWټ}yyH=&d n;CT,MO\o~/:1uRyu' }tB5yW5ZoCЅ tR=$x0W.!xttUccVGCc}C9Dg;;eIJu˥n̥dmdtP·+c+fMgڈEIºz.8|w Ce#l{$ SJȴTVMzH99`"%m?wTߚÙWI㉓v Q~AQiJJ =8&Ě,vUQf4א 6>8oW\p>Y$CsDn#s=bO0/:IœaĬ쪨7sb]t #]N΄ǝOoN ڎ GS恅;jV@y>e80^}cl^!BEJAJCf JֺI <=iBo;A =Ѓt\kِ%q$Ԃn7CN!ՁH4:}}Z4ŹES" 'UNwwaת.vEzwGn1`OӒcx/RCzʚ~ B57;Ѫ^P8-?XVH>{IUoPKڌwmj}/╦_@"rN_xs"i FYYԘZpF)9%O2/ٔædN/RxwU5\$FXVj![|xmՆ PtRۈɾ'BHy&p4 L{5geٍ3TK?ʜ{(;5334&('x4߬-?@iQN-\.NW#5ґ[Et|@L_O-{}FȻ7tZ4'p)/'V_= 8MǦz?.,%/Y_=w, S?P $~dq80ce-=qۨ9GmbtL :ES+G!#V^j"d"':8/n7cb7 u'gw]"sE>; x΄EF)Rf|>kVe FAe~ nH@SBq̚pX'rߎ'ct@nxU3^"`bVĿfb}lY(nʛ4[ 쭚<`Exm]/ٙ{XI/vES۷82x#s_FG6˞|5?Nl_r_/Σ$d< 1'"s#M*"+Ő|p-If`sY`8jk^L<74%}? >9W?@ŗ|xPp'¦VHRyOI=9SPmN u(>Ətn}LseSJɨOݩ;L1T}cWyRNfƬ#dR@k ᘱC7T;eʘ"t5ؗ!IvYs"DH̳чn&3 ej.*k ʪr=1/x VPs<:ĩj3֨qڸځXc>xg&'3d:-@@V6ӦpbULTQal]mXi+: U}i@[]m [I#~>?@yPYuRW\y[8qh‰p)r}qtqVā.t}B<:'wviHCe0Ad0 WLJ#s18IpZ p](yުp1ʟyP:Vnqfi*JgBeN4|܂cRiG(*sjA4\Nc9p<&/vr?0b` Ig Á<H'}KuZ~CC_g9ph8FҞza5hM#_vd$V8AWx$ '2/ds]6tQYgtǯ(&b 8 h^t9lŰ2`TT3Q<>3b0nX-1Kr;E.|p++,e͖cQVp,vgMC6+XS %lib-\xE=NJUs`Sޡua%1w5=wYɭTa&E#pؠ<:@֥G1r'FPq3QzijD:>Ar@o^vKQ~٘@YK_<45BG]ZV"b^.儧h}:Y1}jmՑࢳhG&qk)+68ͼi8hS9{70'+o2'{ =)c3F~593B"7Yґ.[CF# mÊ>?04%3'EN≰6 º e\:a e9M9)x$CM>*NzQ=C`2i~ 7 c(LvcVx4% @y ~Z˰jX= pkFѨ u5ћd z(cjN 吤LnG㎮v +rɞgoDdu4CFS^ @N+2 @& bvN(`?LYf2XDoI*_d=LΫnC W{Y JK'r[[\.`V3?bQthEQfjZټ%/9ކz4齢J62m[k/kxP}C㥱)G:%AP8;FȊ;-b̜O-)+uS}xrvy&uB yyv㛇z|3 APV75>S Lgo)>9: U:y+9CUh`C=Lg/UMTn*=ДƓ鞼RTk* g`A=,oey3xrKɢ,N7@NMHy%=R1~r̉(8ԓ*yjMs>ՓIg6uXڥY@$(kQJj˙ 8vhڅ*D y3++ɖ|Ǽ G }/6_aI>e(1b\"YukIGXG^5upeP9A 07"VFSB四 HMab<5=;zcai4r8&cmZDHSk=v "T?qn!7==w]x+jQtL)I:Z^shϊaY[0ݦS։mK:WuH\IEt !H 66aXbŊF.%#0/(ɚ9gOC72i; >4t=ǟ-v4`zD'6B`2y߃'bi8rݐy s0#TaPS6~Z4@I/Z=sY0uiV^dMSW @Ef<ܝ0:4$Zhu*5H=K\nO 4)Q5nȔfO&~F#\e)52CBR$7r>AltW2ܕӤ|lE5i<ǝ,kG[y7nX+k -кVp{м$~IjL ٭d%-([.$=Aݎ7e:N܄ '8 !dlo֊#DOG_/hPlBRHr¶ BoMD{M/_`W_Bm_TױRg0#EK##/Igvfم2SX2foQ$8k;9' М3d7];7p+]|GY/uq۸EA898H@nKFg5G +OP"x wXR#0 !wVƱ^!ܣ3Z^o}m:DCC^ ϳ"v)A3oUoWa?w/:k6qO;kw.g(t$B@Q`a[uSssSMCSd#z#--z&B֮F?Z C wTLyh nfE$m/aAl=R"?"=lIN #l67foCvIF S?fenM}*HO׬M5~a{ИKx\jFQ_cJmD!s-ƉBM3/[ڛ(X5F7nϦ0 :TG$|~$Wg1rb)=2+kݮBS|?\Ar9] D%J ^DǔUvA뎏E:XQY7~@d />mHEh@G=9D`vq)*=eFFnXyO :bV!jhyqYdzlbtH<G'g ;& 7UIB. 4az| zcc ٿHO0;-+!M'rR@h#1jga |Q8ODZħpщa8ߠ/fMnXJyxOh䒰h^7>KYP GU"Uu φ 5 5s׵ m @OFGECJҸCSP.6tr!Qd0 H9? \J9HQ}v=P~}D|q0?"sM`ƛN; `ny5pEgj %Zk7 16*wJNcu1p!t%:Pݲ/Xf'|aN \# 7[TMK M'E6Yvn̢_hE.;M)piOZ0n>E]v &H]ΙP ƦHGtn!$rh?Ƽf-n֨J=p6DxlNƪUUf~?9PHBt!u>P[J3Q|u\ o`%iGMQ=yê"T-3.:&N!(RO-I']ܢ:Ј/t<Ґ CAuT_xgmkODǚ}t*[l{(8eqGf,)` ,w(L!,p!.SF[~kF.#'_6y  ]M-c" %%#mnƍΏ@w/ FĢC =OmSk+⵶gu$D?6>s>Wv7+"Y!;d.*& ;Ll)G Η3P(-_HRIH7/IF& hųv!JS56(Xep*U5N+9G2ZqXez2M1 "|"Z4b}?')NMQF)H*\EH>=0qR(4Lʠe6>|Xӥ,D6q/N3|9rHjc3[ɤTY$c9f!ܑaeE6. _ wӇLWDRO\M~\H4q5j^R>213';q+51sRʹjZzӗ \-xBm{@toƬxH~,!9 oȰi|Q`75. ߭qK9VD2ș|#c)kAa[1ll2뮦b^HGxBEeo|Vd [-S$'j?c|핕[G.Zx?/  PPuqRHczސnmlbQ>;Ug>QGlō;q>Lsp`pջƂdL-͜ t2dj1j#vH`E*&N6UM%(#㠑mű(&Gf;J0 `4afn7wĪKv /D _=ťwn?pYSd  ꢅMt>zA7I)-LfEi|%OHXp,SIƒЍ ]]PJ)5181-Zi]$0YsET*-ULJ _U@d"ڼGe?{p8hCN6BYBW6e{O;͗3 ) aĶW +)/Zƾ=2 +f,`^32!vm-WtBC%25:4So"dEƲ,G%'V60s"7XVffcה*fc! FGppJZGyTݼNf Kd hqL99 pZ^Ѹ%,8x՘.o?AgƙEvA.ͭa3W!jZxgIig13*%DDg?A) xwxV֬HEG)t<>S|!&xfޠ!iFltVd)DΞDvJ׺iKO`gLal'w OIzt-6T4ȴ㍴qďY="|Zkp{4Yr烛=2.O-Ft'Ulipܫ-jՅJvܼF,7/=Z)CyK男A%7KmJ*-213#W~bTu(?|/NW ,ˮzoQ/sBwHl9*M+^&QX3sKEg*ԣ!aGjUIEAt=5OΦ`R%{C3{s% !c36<È#&=7̕Ό6XmXOf d@ڌv@x2xUhTYFmj Cջ,?WlHk;x_/_Z԰=1`SұEHF><"p83,X!z1i G?\'é%a#Umu0yh LMthNB O_[+mSRV3R *uFE".d:8NNڈ(v 7yl#/{Y6T衢BOhěq,叿cysq8Tޟzip5ZaKWCg5s?Cjġ턘_*ta%Ȇײ$w^uf3: {xץU Czi:.5}8J \rOS{~,*`U;YDOяL-E(H4u?#uRfS9\JF8ӄ {|&7G JpCy؜nh`chO:{TV[ϮJJbwYZʎ=\Y/ 7h@@ܤA{>YγQ:V>D-Vѕ+Yx"9E0E c #j{ ҨY뢐%I s>Syp5\dJԼF#+i/<$7աTcKdNżJg7Mz pƣOH-^9bq #=M/:z/Q>43jʣYe/N/ =US5%%Ȍa̗uGKSLIDĻ.KCIe-XANhM To L;kzƒu$nh_u?]H8)BN=s֤Ou}+zmŪ[W?RD4Y'roǶ<ɚ ER/M?Y~14'tieݱzg"DKAs)yV8Gaw_SLiUeFƻ +VtJ{a:-f^Ֆ)q:0Ίou9Eo ѧ:YP$ZT~K,Py ]|[r{rY)T@>5r 3pGŏr+.;ֶ",#HZm8lɺ!Դrߥ-e7}ub͓6ڹ}}ʋv/G~D3׎s :-5%F{h 7)=Htпe+{J(rt/++h.ER\f65k_(}$W,#%濐{n?QkoX'c 1m?k9Fe(ӔnibՊi}=FQgMn+]2Yקa5 1v=ZK<k8h u#e*Ln_"dO@? ]fԱ&Kfp'I+|~^?(F )m8Ar_(1VĚ3o2L[]b2;սM9C|qoHvl;u~`yCsu.TyPCX!&>K: B9s g.W2m Cİ9z"#f3Hb⦆Tirϧq%ؙƦ`gXU1Ն*ŏgrX$"r}a5]Jvi[^ܨG%l@O6#y?XMdΈkG<|o883NEzCmKs3{ɶNXqC=`/cK订,Y'YΜ^hxB5xt*of\R 5V[&Swr-<7E=n\U7(S$DpE!W1o ̘h8JnClsЈ{ =j > :/Nj͘(@(%5=֬\ԽF V]:Y6> iz]VEJA]ٲJH1O]"]kG9N<{.S rtY2I é 2#?tw?$:o+zXX+YuO47~J,HDzmqj!-my,*q@Lߏvĉxy]G'@Y% bBrM~Au;5yBuW QG*yV{?jgt'S1Ӂơ™btMtk+"fEln9RTJz O]苩40N{W{)kUEqfG?eq"T[7)w syaU29(Gե~U36Z)N7<%2M7i$>dv^yF^ DL4ky}nc: h*6CWeLm4dey+EM$SXQr*sXa0DڼO+4 qoCV2pgx:Dx)}2u}{+VBK59@<g0&#j]}e*; $Χ3wSN`-4nq=[UWu~\giKSs(tÔ5Y[%*9=Uf6:;C:y*X;n:=(tVGlVx^IuD2 mPsC ܠȡ8ؙ&ZcmVL ")y%x0 ߉YznVɾ1b]™ :kh>ElHu+M aaz{lvvW}kmcS\Ѡ|5UqG[Wiэ7sbfZseG<, M6 o|O ]>TD.-24 {Gmڤu?@j,ɟzH},@w{yn&TubUnyPҭKg'VDنN6!~03xBDVE~A"t-+|@or-qsGAc3e>Ȗ@6r9ON @ccc&Ju<_v Y5b=8hߡo;9~Б#3i y/&h3w<o Y8ě'&,uw|"gRTIMnV (+$Bݟ.s߁ZyOG8QSz8#|-I8zoeʚEeLz68B7O6U:E8q0]/NHzӱ~Lk@\4m.` =<:BrI _MHvTu>瓢~fur"#Sy};/Q7bZ+'Kڅy=i1躡KhGfq^uڥm Aaܢ H/p% qG{xj콗P k򛰼56㫇qFHE|'b O`98Թ7H`߼sQp9`&2c\ku9<^-f@|pB[Ъ!s(6xNs&5xHBAhXLѕNA(6&QZ=٪foyOnu~FsR CVp̚_GFݭ]\9%ΖȌ{41Wmb$Oihs`ۡl3 m?m* Ff&5MMFװpp{hRF>SSMLĈ=Y.B+/B_hI9RmXHbWM͚~i'0V3oft#06Ib`r(vo]Ka\g! %ymoC+٥qudN;8PAܚyTXWGYVw+m4oy%0 {㓥w))(4V:`o Ol^ɶjRNrͭ%Fbj4D)oh1{onTpgė|z:)1EfD~5f#2BvFlӁkʍ'Izx05@T8 XEM>24 vK2aG3w:tG㈥6n. d?v?Ur~ >2th:yAM߽[ˎ4;Xs>oKgĀ=ړ adtJP8*\"xJDYi`᫯Hrh&ԬMy465 MC(< #\J&.1RQ70JmOsltv4.r$ }܎K5>EVNAeyk*vYALZJZ󎲒Baiq'"eK%Dʌ А7+5짢зy@m9{dͭ:x6 =%}5d8ąT5Oо Yf;(s?Œ荭C@[I9fLzI\BEmfi"2s8{`kBOPM?9*ٙZJI$q`nQ\rTՕU:u6a81i{@LyӻH5:VڏE77)3t?-!%+`A$/Z1zdUlɰwwV|XO,:./ uy^-k~K~l0L #Eߣ'41EO#nʲA3앺Mi1g客| ו.N5x6Jw7Λ~x X]TL+v*dap+M-.ofn]{#XΔ+ 5evg54E[09Q1[< D[@uUHjCB\=~ؕ`dnVO Ή9|ԅjC{7ETbE@ ;&qoYrdH1[jX !j^D1s/r }p;\|ds#acĨ&r>C1豈{zkNfp52jO[0o9{ T!wuRE*jNMY{YaFisG(~N.QY87H !:Brf 22!!Y2̹, !Tҫȝ̖A MwPML>i){(8tŀ;4r{ -ǙtH_~'rk;+YMqd:sɻkz`{5ܠ`4Jt bĺG3hX+QP M?(f^)!ݔ$x̪bEobʨRuY[QbEgОhJ֙}=۶ GM9V \Ndhtg%zuȻ^ºذ`*?֑cצ&c5ξ&¬"+)胔ϺzC|> l0Jeapd_#ϻrߤ_t:(z:YqɝD;6zNAϰ`8cS.%R@0Yvj`{Vcj"Mp t307f7U+I07 &VӞsБ_y}:_<(FtUޘ<΅cpiA$[&f᮱YLy>b ;xS:S>:G>17N&lۘPIcowK䀾p22n]Iɐ>H\@!i"EB}~44X#STt Pht k+yEntiv2rF&e)zAG? K@ /nzR$y|mds+cvŜי6l 0lMY)AfǵPY ̂{/5ނpG;MbE4[Mϸ$g͙bC!o>.jIə:hA}i{YB;Kg]9{4 iB\|/\P4:M/4rHDcPY743c Y{d\l e.5gΔqKXJW8XÁ)+hDz<T; +Qlz8,fnF`gv BNlxr*'MpPf]i9 /xnrև3Buߣ~XQ3Hm `@zvXPvQCŵia1i\R\8!̙i%r.C/ H슗Y+3< B E(XxXE{k ˳`lVSS~jڄpB i^ѓtF6 C+; 2I5ZdHӭ ӽq8u`aOR @Z!saŒ%m{c.Ifhm5Nנ$yO~iz{h ƻ9sά^' >h }ރ+Ն<r4ӿI'8H (μmĦB7j݃nSx4|Sf!7燐%TS3<ur<;/)pĦI F|9DՄOxQ!6jN{[ g8z[]hCY|5h5*ŦDjz`Q `Yb{y;eI`er,H9[QPf62{< p|~MϮ6 ʳ)?cyuWoji5Q%Hգ:>KLAesj;w"YZюed沨TbE@s-~R!ӎuw=m$*̹qѳB9\9@St|}Ҥ'Bg:Z߽*5+m‹ex'߯v̯0ML,]wws qiYt8Lu6 zv|()BMdvDzNN@3͖"NM@mADG$1́~+Qy|R禎p\o`G8Ywzfo!#X,S>A\sJjk>>ݽՁD}\V^ynQř_9 oT/Î, Ѳr5˩ɯV&(]I\t/ҿ_}fXy5*6.)&!˿I]jj^&**GZyen9@)TG]@6hxy08E|g"2hQRqN9QYn4:NMXݙ:Jcau9¿hV?p3=Or/A$<˅r$ÃJqˊ59296:7[nЛb4/9 c]?:Ib՞`'LC(G91XMGқ?mjlSoxe G82b-EE}sF Jm)"BÁc2Z/ߝ?hC,(pLZA`gzb8fdm&aJGMCtd$=]1ܐ94跕rfW2ݦCsVtϭab,θqל.K Hef3O2]|=0 6zE/ Vׯ<(mflfo2zJ*яXic7D'ȅv^J|Hnt*YP*GզTǰ+XcUu&Q8m8T}a3?prOHnvIb)}#tW`A{{wtiq1nR *? wƯuX!sΎJӥ?zHi(4 CWsIEk NIcԳˡ~Vm"uTq4ICf*<xhkzViAդ-X:"0vU#cm2eUO: yթ/xT=~d '$TPOnK41:K >{0^s"z|K5'C/sԬb[0sb:K *BOKE;7mɨU´0wh- F;׎JFԳhXezpu YŢbI tnmvڂOv#3qV[#M9Or A5kC&24U>,d-+w; e4_oSWl;}ͦVƅL߹ry6=rUE,Y)iS?ڋY缟&rmnnNV'Eq.r\HvJ4\i*CWyT}HwM&7h>dɭ\1$@S48ҭ) UdpFKN îÐ 6ﺚjCܶI(z@1skVִb9>;mRڱk zkz&!k!lnmM}\gx@A-GIMUmMy %)NpFbIJ<JKtIΌq 9@-J<z>甮):l/l8x| 8Ǚץ$-ʒb@q&ed*akB4Pq'ڸ[-wv~7ؘ4⻹qL st\l4Όs>g,"m%9E8 7 j"4=iȷ|.TS;ܭ*4_2s_IV]Æc#*zG QI\I3 5m8-2rh1Ne],vH2_1噐dAs7{C$ڥ_]_ D ظoɊoxU-9L㹡d3 .R)iJjnaI,ذoeX-_oĹN=x߇0vCBr$=blROj涵D>/cfLG8|cMp->1zkYUeОF1?GB4 ~@!\g_>RhiZZ=j$doƿPMpVb}ݐLR>i!j^`cAVR3 ȸ:ֽ~m,^ǿ{~j(#GjGw3V˲kJA@Ps 4W.W:nX"lf-MiD2#4f*0)g(w-Ј'__CԄ!cfi"gž"n9׿j4_Za" *_A\yh\2X{XpW YNjAtv4] ~؈>Y@cPՍFֹ'IW8(pNRH Irxi9t]'_\7!A<90Wl^WߐM$%≆Fh+d}74X&Lm0@/|E+gKƞkcn2m_v/.H8=jI{ʣPmV'IX2 _j@}\ sYkߪoM]g%v$%F$xxxVC/ɇu<56k_fUX:O[D~@Whe[M>"X8hT쵞U2+!l$$@<2A @|k13s7c„E\Q=N_Z괫2=WW.)5Jk 3yfj JwڮT$e< W\1嫻,VЊub*7QrÎG%ia"yav55c7*ށ6=eNC}eJ2{+lB_5@"]WaG 1X U/_44{p^:HX^S*;۞AI3P8d.ǃ˿{bm̬CQP{_I)̯. ZMp͎!E]{A(rh|B8 [Hp2F1շFw^:mf `ݑM\9n?p}+:ԲRǥ;gLF[/G{FPQ HO5*W}&+R(Ui8ޒ%kdrr&7ߝuT.ՔE;j%դ g4"^OuK;&m=ңkRsFu~t[$E<tr;?,٥=SiBFl=WyS / O|+h&%U;,/WL 41ZZ_#'s`uuyMz;pk7>*?rwQ etD!<=vV=n(K #*͙~0Փ:=YYI {W}!^6p4]w?w=xy!x`gχ2+$1# 9O=[[>8I`iөKJOGR#.IIHu*VG`b Z6al?y$#`v}*B3|\٩EƟ}ιc26lj}<1Ҿu/JAM ڵU,)ӋGiWqV[ :Ƒ3أ <s̪?MW]K6&tx EE~m74nӼ^~޶v - v. }۹{j%")ouY)px[wHBmb礩+ԇ]򑟃+u]r#,RYFcxrBU,NGm~bΚO# -#-҇EW=By>1K=2O;Uw~3lAnzHc8x' Aŋ!#b,$ց3!ak ysM3&l_6c'.8`V='fwz?t#L!/ yuf1 &(,Snfw~"}^]a گ'*z ԡtl]$G,kM( iU!׹X,m 1#(9x]Q'{DxX͜{aEByj+WN[zu"s\c*2l<)=RpweQyaDg^+-y 8" aBHoV4;G,[jvR U2uSWeN">Ova,5JC%M#\uv$$_rI?<Z =B$%9' ʄ9-ٛI JUʐ|V_.e/+.|F>FsRxք.5N4(7[3,~䩅jrR ~ԂsL[ͫ3Jʎ7.!,n6;=GN.kh;_ٯ9Vuʴ+)6:(S%PwżΉXT}/4@WzkФ;JQ^Kv9+(jo]p`@!І4V_ޚq|Mo# yִNEdF"{a2Y oR:raG@j )8ђ=ʞJDW`O)QZ4h懳U⁷O=;V`T|3c*ft0CVa9;֮N~uxbfpWUlbGƲ'IrKAs Ƒ!F5jz,ẒO6 Yþ:jYu+B]cEK5W=-WIgõˮ<:G^Jǩq/Rcm!T&#apl~- ,1sz\ci"zFFm5}eA y/ۚJ><0y3+Քۗlػu;̜rUgx6R3s5Xu}<^:]:dgc6^d&)c yDWC ;Gc3cXњlJG|.'9"tn{ sŌݭ-^狡prdD&oZ3B ͜3NZa̮7:&~=`nNt:CxS<19STG⹙¡QAQc.2;21J m[P]~c55 +wSt#ɋ9SvU%J^0i*9{> `sʴ,5o"G_;(}鴽BWE;kFj]sImfԡQ Y՝"V7YMi>DΫȬ&zUH@zlVuY=I6= ym5x½sT:G&SDy !vb"깤zoZ(~4pNϺR١kP_Xi22&23 XxEMy/Av^V\+_ȟQbL7&j簘 B_~0f|դ+:(7}VkbgM.͍I`P߼̮V,# bvB \ͫ؜3i4e;f}6rJ+:bMvns|Ϩ?J{?S+ ѧa) }ܽ}VQc: jr~0m[m.pE"|t:ߐ5¶|Qi1TpESVY,q~=2c#~U5Rjm jvBhX֥~ZJg<ֈC!nz?=c0|7)jij.ExE+OCwFoUC~nu8X)NwUխjjم~wlLItx~Y]Qʏ\\wi9;&wLGzvtxHb7t3F:z !E2.zX,@&L@dA3rR:?7Vazđr$f\=Nf%\UJM ܈zRbWdQ 8-SMoy,/Д;PNUw#gx 0u0OS.,Sޙj?swEhs^ggK}$.$O*:0yݦ9$-G`EJ[/ͣ+uKJe|C80Q%{{Hһӕz(bJirf D S R ?Km~I֣!i#|2{GEk#4yOBC1b.Z|uE[-TGIBCa!vߦt_Y[jߓ'F+̰h5ϽO^ mBs5L@ڕA/ 3"~\[m|>B5Lo?bJg"d%?VCqK.clಣthDI u՜/kgWcm3_)OGGYLf'ޔz[fAzHV51$"mC=EpͭW;8Fr.^YjW}Ł 9jH&nqqgo-WMTڅ-BаYas y'3! 9QtuDٲPei$2|/uܶeVx!+(U<GMw1l\B/APWCVg"ک2VU||̧ǼM$9^ߔk~Yw R\`Rm /d&nXN-7 2n7ovVvM#,hzu)a[h_Ue ~7lJh+^7_ Hו'lQ~1mR^Pˀ9Эw*#kQy| ڲYN})cLefAu> 0IBAh+{ KJPR.ؠWVO h:ǎ&(}?؁6;3邰qi=ꖦ`˧CJ!DJJL߽{%q {}>$/J|ar rT4sMxA4?u$:(h;/nR{`mBg\G8*ɝ$qRs5ɬohΧuF)5ZsFvzcNoez?TVW\hy(Ts+|ʩϓ8<p NO"OabJ=sarrsyV5mgvd 5-%BMi B7 .v? Mr0#2WM`ǫuBԺiqE"UuZƎCe٧q ۺ5C^~m5y|Bn|N#W;l'/PSbLSM{p38" AܚbINQ=o X3\ͭAheQ?O*m<^V+YsQ)7i gD? ۋҧR.xybҢDO(͇׷s%TǕ ߕ $m -*E?6dib$#P"QΑ{gGr RNQUH0&\{j+OpE*Ϩp MDOVwV*P&zI( t9O;E 5R,HȃEZa4#Je?⎮H"p2PwYؿ!.^Cs%O@,ZTA VYۓsiBvyϼH!ɋ3U ^(jo6WKיvK1D\{V Uš&AxpqFyq@DZ6\i }KvF^ Z\lx:0yRbb-d8}Fi &^mlr{%#rseKY"L !~Q"H5*CZ [K6LR -8+:0 !dlUz9nPaI%vu}'b , ՝#<"yJ7a 4 <ggXPG]E p t'Pl X096 e N#hEc$}m˾SyMWU7z .MJ\."ѣ6 <2ALГTA1IjX%=#hʞY r/PyU`&d}~C!v;*gL9TUvC쇈 :kC:6`K % s GRќ!C>̩hy<.vL]gSLy x@CAR1lr((?z,uJ&^VP%$L|&dJ-+9byvInMpr4cZV }UAi)QK2S|?􈮴w4 }B3suޞ; L/?>4׸5-Q;K3E+ߝ'1 Kȍ"W _z"į$E{d"x+yr/ݜI;sFN( #RZLΨ/͕vK饩 KYI)勴bPPʹXy-24[ģ+ˊ3L?T&/'lr>˄!^dŹZzSB4h-7OlܢQJjs/GX.gr[x{02Nn6J ֝u>7N`N-*LWLTN2Fek7'vjhf֍ v/mݮڋՓ4J!KDWaםkF+5t~mЫc='!u T+oMm朗36u8֚;I:"6z'*֐L}b+EyZF#rH圬)&|z\KȻSȺwJZZ91ka:<6yT;K蒡m< SM@e3Y٪~0k&"aRi'~m%|BKr~[InhCPP:ז `A!"3K AEh1|51$!L-#\"D[vRBS6! I4mߠ)8k~K4 PA!z~4Q+\!b;#4҂ng8F0 v"&yyݝ!RBtۀyjF޽i D8)>5瓹'N[EvL>>!PPBndE+ȥ@q5[9P}J,Ş+p o;XO[ҷ}r{|yc~}Ibu^iߑ( а)%rpY`*ZU44VLZ%{ZaN_"ڕܽpOnUdG$| nZQIrS"cv{*F&A"'Z8dQ)vP2DD2(c=;F^rwF%MoPώUwe\{?3gB4B?VIа͐?(f5t:1?`m6ǠY\{WʔE9P Y‹WU=/M|XqԽ#;S ?q{HaJ긑Ձ󶖌;PQCx'6-:c&Yk]z' 0tԼ) o<=P7NW]UBzo͋P/Z˺`O6 Uc,ۜ%h2:$)bE"<r"|;ХWd2DVk^ j+0埾ڨ;J'NNkF6Vn=*OIGT (T2?(51+#דlQW IOB~(|L1%.bׇ,m mwϕao.ȑl#ΗeSH_y'ҫ}|Xp3F%7kr ue FVdBi dG5k-D?_3-ѫy\PTB;i!ne ML~iBy+EԻfN+iuvmǶh&͉@ZX)XUϹE%Ejmх-VkF)1uzp2k mOd#ȃo:~v 7n&o6t+*5"ȃ}U!$>]C脭.r훘%)={iȼfʁޛn~P%@fOI}z?OI}B~~9Ux9s> W;Yre> %o.yb/snҤf4H<=4;3gl Y7g2&i9_+ >OS>7šZOfoRRL)nlh4hCN~;p{)׬L2|0П%@8;nҜţN|eA/ IANX oJEZ3'/i7% ޘK'|"F=?;lu oj@4Zhb @9&q&M!iZЫ3/S'&zxnL.$R`O`΂ /D0CIk,Yf RݥC- a8ʆ۹Hz5uLhѼJ5vX*0SO&:P>\.A(%Ne8l=/ReGۏ^$X2=y년JgWc?suZ0MA ^BV-|'^3?<"SO'T%Cn2r;#iaE@c ]3lH\+CZn5W8War8=Q{s̊`O>u?gH&X U=g3, h-U&ʥZx{ZǣpWtF眝 OX:`RT=Y'|3Y;аaK*xg>>UҌa[?= 񾋕8˖ׇ"AΪĒ[l6{c ò\` W&HeX2U.*pV\4Uhz t$:~1ʠtƹ"wV|[;/ +}UQ;|Tt&q'{Y$yx:vf.%az9a>?d~LZSaV:4;Sz4ğ.nީ6;FqC"˝So'^#`CE΀dm5eF9[ۊ]`&8eyfl"]7s>ƶr#Db*OkIg08nqkӇ DNKEK]r\ wj,"~_I'/nd= GPd45r2#*`Fnfy=o5=6SkB.r e@6̅%khG-u]Pʏ]̶[AoYdWt ar>4]~rܤl5BI0颢~-cDz#T^dGZ0,ׁS`9;%?Lk̜r9{smɜ9VZِjrO/ psRg\،x [ݴT^aNu"N~Lk7.~MR -Z!"n(̟. g n&uz8|plXӞFM{_Z.@TDMXMǯNY\@^0NO j 5V1qH#8j;(3ŠJr'/sTwҷ qݪч\mWtm\TjT9VDmRlpk=!zx1fٲQ0ú 6 2(>U+,C[gr~r\/$&I|[[6rضiy&f-jݭ""ԟ͓ Wuv5囩$/WfVSǭF)KfT(o_!w` G])2;ү'~$c2C$=} [~ʶf'zUrSU#N,|[ )@^'BҗڪR|:z`Ϸml ̛/94u;] )y^nOcgLm0+7Tu̮<3V .|E1]^&$97qQ#havݸA˜2|stU7~{PF]/s\v 3[yU1SP;B&bʬMsu\P4$- pݨ "մ&ȋbVEF̙0FU>2-RO3o\uԝ]r4bEKˉdJK󸏟uoq8?OR{WWhP .H¶6C-w3r+OYV""wqTkN-o*@ae26PWJ8x&;l %* ˻"95a8\H(ZgT]hٔʉޒ6_n721I"8Rd^yپO%nÆ )ba/WHā6Uʏde&?ߛXDJWA$]N;9Ytѯ8:`90*ϫ*SW.VjDك*7D#vЏ& n>CЕͲlMՈR݋cht,u8y8`[U(Fe FѳE:]~xD c1H|߅It4sg?11*C$@ u=I]$3 x>GDD}ѭ>.yLobL@wHs5qF^vz-src:F;σR8#Nݹ&+|.ߠעpnï+ʲ 32Y/xќ(y΃ʃ|?e+/Y0d=՗Oot' f[&ϒfгGM|a3PK" =}#jظ Bm eVdpdmrrN&HODAxhx5's5F~'_%#8CMhɛ^x9fC_K=%]qAs@qaz'oeno'KC~ ^daþ"6dYQpP28hDUr'a%#Q68 'weecR/ u |K$q\z/Cs_ta= (W}VDMWlYP+Ҳmym,w~9]@UU;y]jp"PJX6iBI*$H )mBkGg(}HN9X|C e&Ϟ'C2z*}"<޼0do s+Dtv ʼ؃ݩMEQ}&QB}0͙GƋ|y P*w4==W)q(*`M.eQ볉 { =׶sX \YP&DlAnyzˢ1 Mh$g&n0s(f̠[%T!֩SYq5V5eQӻUqiPZ.l;#ZbEZI_rIGOO9"D5+?=0+?K@g"+v34/i-ʏ?^8Mabl0ri!/z ,9\+V{K4}\击jp< λTe'~uXT'q4T(Wh'΂NԹsDl>{REe9dy|3e(h0_Zbq Lqqս hЬPj_&^oޠaAw ?)Iihogh+*W[2$) k)[ԡC-ÛW1? < WvP>X Gr[JYihaѯsh'SV*|mhM.M>27'$ |b7)3hVS??Vï[Rġ~͐i1X&`U,Ko }(_,~~Mzf[:96l/>=oޔcnyYnCus}lYք?X_ZN*?<`Nd"# }! ZP|*^҃e0/OUU?h867}Y^hNtv?Rfw&6)8khxtK6Lt_QۜK>4KPٵj48 WPASO/O8T@<_J?(Jb[hviGɱ낁G/ 3ϛo^OW&^g2y^% ,BKܹrSL{%V$Nƕҿ,tLI[% Zhf본hN_p\Rh ͢ɲTfhrgUnY5g;аi$Pg3d6 %J_Hz.rjw<ҪrYsdr { 2MN3aCm9RnP0'Jk $4VmON=JԑnSl&s/2[ۋ6hU_)Pkju=F wt0mְicE$qFj,V:1O>l"'sB 5WnL3FYdMtK5rmOckFfH-t1vb*5L9wTl(hniB=.&_Jf훑 ?>Av'-p8 EP̈́"312 cwf\#ʵ+%zfL|{Σv0$>!)'3UOs?@.B;W7+K~#;,tp%cm͓OGis_HlhZs2Uq=nf#"WzWvwT|4mѩ7~:<ʞy%nR)ct }DBwr̶)fuG' p6+ո为Oh:X9lFf: qDk=!%k="/g\L=yG}sb?ݣ'obǻ O͂ o{*?vlѭ97  C/s=hhc#}k@a z%2bK3r'G9X獉_`(\F wѫt ^GV$T#r#sz,nΩQݰGhIO6c3,1/ݐJTpkBjѣcS#Yj1.m(;E&6ȓ { sҫmhI'"(iVWg7W"NRJ'_O^6dg)qi:'79@=iߞqH7P۳$R֎mŰ#Efou0eœ<27/KMۧcCcV{<+@ =s4jij%٦7찿^՘n?/ N3:zi)ͤAp<7vovHRBM?s6XFpz>}݋"'?=H]fSfȁ/fzP>CdE}29~s2QOc_@pF%E_U,Qע3h/CB-ZB?u3/S5^ny>AH 9uo^`+CtKr;-c07E-WE Ƹ6KGuk2+S13veE tkȋ-Ͼ(L(*^-W=rOq/MS&Y맠,Z s! Qjm0&2l@]$^ߓr. ޠKUH~Ëf=(3u(Plg_~g.O)+*WRfwMIӧFXߠ hJ&7eZ _~E&L'oSȳ(Á0JJWo̵{uIQ.oL7ЎϦi9qd8tIdecd>-*UV(6O6Cum7OPّu`9Ȱ~k##w*wͿGh:Qv2V# d}se&$ 5&ȋ"Xw݄s>T*gugͭ*Uyp^CBXND)Vb hWs1{?XEL:_u:׉#PTּ'rPî_RIY͚7;T{sTI7P>v/}. -~[vc !oMAK}:ZO7 *A)7;iW70ބd>X,8nHBK^rI^tɱ(:(#@xJp 8V$>oeͳyMvC ޫw|[?VX|m[QSUFҨ-6K=պ1R"N|Lc=ߟhVM,f҉eRb*m܎[΁R%T̊ ݞ_Ƽ] >Gf\rZ3.die-8PWư l[i mVlm+%csʀ]^BU?V@lͬ=e^ rqń-Njaha Ֆ$7[ چWGW'xA6Qe>%Ui%->JZѯ*9'4'khpxD%mT4$Ϧ&6LE,9XZ) c(k klt<0)Vڄ)K.nqk{ܒcV}+1UJL>?[?Prϡ:C.X1m$f~xWv67>RNSOR\}xΡO(\$wMS^Q}A 0 9ך`:Xq[DZRNݩ6P\<** $E$OKFisN:{?$1[eKAUKJq pi$2w~yY',ߑcVF-bhf ӯX0~|ٲfVcAqlA /dVg$JO]` wzӇBIeGNJFge#.jNK YtO^\ ;,4tY(|E B'S>#X}=.sNݖ,~tR_](e _)G̛)ͫ4LHChV#yB-uMB*,[H׾hFߠ 9Z 0t29P cr8{cl`bm+ZfZ>T? K}S^)ݠ:Z=eT;صM]{AG2;֠P$ d5!ޣvb39Y q 8"lFRN]!V`^auْMqOFU \ǒN^|@YN5)`2X3M=q0Rq2ZWp/e3wŠϣdgjljU渒&9䊍4/{uE"6}6~#ȕG6&r5O $hMwT.(;FAi9&B2 1r GthTZT(D&G?epIwS>%k%==:;\spiҌ'r8ɝ6~uptOV%*B/<0Os ;;\FX@)_qL5{O vRcQE7*'zZ f-Vԕa G`WCU)L.SX#ʲ3hT-mM@I?SDڊ3_?]j|!u6tsDnQ  4N4cAޛ)_fWB!{7 E*sS;EJr B>{C 5A2r1 \ Z8@K_8Z}A9qT +:U0yjN,Ik+GKGI%,\^r=l`l5r =>/4xGPG~ d\M}_;[I0@ЮYSuh_WnNz[T$S[`-.ȆawU75>?O˼,:`9 ̪yfxG7'a%ADYЙ-Q$dyYsi7,4a+SY-3|mof: 4Ţlu KPi"fPJla4U.y/ȿB-`t(cxsɌpIaW$8ehlirX^]aÛ[U(X'Su>@vhB]6${oY锒SAPC&<"hK&_T ތOƣ-sy1qIPK)"8-Y%Zuc0 `Y yV'g+?&MYʼi5jmryXhfX#lK]l@{fuFK!9}];}eDȤ t/;+4'<ٕ !/3a;O'y0EΘ")Es%Yy:9K06sM)7bvI9ۢ)uJ6ʆs#2}JEp욤0~@/0E؟Jo*Of#aoTBέe1ٱ8T; i*Oʄ@aj,nHsn)FȆjfP2Tfrբ rݮ%ݛޜ b<@eX<~fS"1 -˼xs<טHJW!"Ùcvi}W0moK q>F:stO[<^Dݠ;AHt$_wʽXk0Pl/z=XͽOY}xa44?zdwG2ζjyn6ti8Ehy^ӲqygoƧ&^2s9ZUl-šEۉd7I6bH&vns^ϖY%(AV "i4'3ҖNM5M+_\ve~:E;'en(^L?qiSyLy=QyY2(f|i> !C&!vłPɊe(ݨ ]4 z1鼂4<S*#dz)zz1_?Xkeb*i ~}[5M'{Ŝ2<=>~D{Ltd3-w*&8j:uBie0X7aaԗ'2htȚbZ_yńUodɔ"ekPآUSCb?|M]_'9>CG.;j=INրnC/89NɏNLK*Zw7'w3y-vZpV|\["ŧ]+wAuwl86qQC~61G]jB@u`i9=w Q;ēC4|% "w?PC%~1^2srm0yۛf>&EM $߄afp[ڝ׶}eS"ִ$HBvo|o8i+6AU2'#.CۂYF^2B4R踪9.}1̖KߴoYqs!g+.հrUerd<4`+.'$pҐ^ec/Jof`Z1B+v+ZӇ'?ʼn 8~M.2M.wК%b8w9_b;[ \GF#n惐Q;z&JQP\Z!E'v.M4#!|wcgO\ !.<0pBM͕J&dXjܺ ͗"'vUĸ" >mrŧe9C] g)E~iWX Q|;}e@- \6eV`׎F&wh7W; 0\A斧s%QO}fO2;'nMu䁏GRX`Ze~j&NWllpv;:D_fM+]vbQCqf\m1:UuQ7t$hZH6r6J<@ccXgN-0y ԲÂN %X@;M0ϝdX#zU͎҄sSa*#]dl}$')PU/f6h"EFwĬs y~BԻ5 0ؾo 4eRTHohPI3xL0(׮kE.aE6C بRD{Xai @tc$P "+jhc )o`R6dJMvy`󊪔s\ӰN*7h_JQp2%ڡ/8۔lRcGN-ۏ7'/0Pz m `,κohTTBϬЀQկJټNK>>rUc a^E0šլ0|1o<.gn X/pH3jVM_iXk'l=׃NprKcMobARSVBE`BW%kP5YXPtYsr{# ^EӶ;C 7I"ޠh~a-huмUZ}*\iOԉc~\&ҝjNkْ芀'Բ}tU&`:p9k X-U`@k44mOTe |v${xfʯ}۞c]{1(~|$65 #RugǮbxKLxd?fvJm`]:/hNVmcþPC;sHot jbK*hUK#;gC6&l曐e)NY=NB| \R]^e80Ac?P;ϲr1H{ym=}<FHNFR#?E >?<^Nb Geg'rՐBe.0l2\LءxCNLC8Ŭ*PE,) MTl621H_O |L0|h'QH$}Ҁ ko'.&mǑ G1N(jٓ0}Qޜx9t8qQB'*%=v!iDiTV ;i=x yTA,Hz}ު+̭* A]rsCC vwsdcx}zn^7co]A=_ڹ=dPrJlk4^`K6(EI嵢z" 9ZhbC*aU⧌!!j&LN8BW wie"" 6UQe֋d$ce2m2jزF[uV+CPlf=+ncG| 8(c ]3o~H '۵*EL2mIF WT4Gq_O~'DhzhoOߜIBR' hzGL,4 YA%.\HKq-=],>!UVu'gp&2I4tb]2s)4 {n!vi.oq 󭩌]PR1i2(Ezrg ;jH#~rY{xʘ*лl}XrC]p'R^V0E oq6n{NzNoPvm ^` DJ~pKBAy\_E ˮP9rnC9e|,"vpjAFQonCk$R<lA,wChیj0aO":1.sݜy~ ;``[w>%2iH3켛Xcɜ;0^ky.~C\L?Dg6@(гIB59dO$d(B⟆{8{80Wh|6URQ%*EM*OGUU%O)mlj?Bw]n#\sN %C%2mA|?6+W}?L*'4Ƈq̙=YdC =1ٰYi% dhjZfU 3ofGl;yUʉ{Eq'-hۆd3BUQk/Ҫ*xrMZ  "^ XEQ)Vǀk$8Lu 0,JR2 2$0s]'{U<;-wΩHyaq Iu*S!̃ ʰO&Hk#R `:^9lԃ"eRWhI٩']isg7D 4Q/ovAIZ?AT A3`gUpvhޠM6̷)yDL ir{DB;uP>eGer}NB*N(W7?? -񌛚l~ c2<8~YFAak- ] ItkC1!^IiGPRL -˂ a^+ȷ|P4~z]}t`^k`s9Y ן#4 I$g}s ulW||$l~O=_\!GT%{4 ~)϶--wH;mbQD3(ǬQeq8ʣ*)3ě grkU |L!//MnWvU=QA%hV^UIY.^aFOM=YenQg[#L.Rl)Z.=~ְuߡ bqț:S>5s9=b7_oLw=9ܗwb.̪J}ngA Vצ9#"p( ?_UWpaZW^[ Qx\LpQ uTYpkme[/BB[L]*KeXým ܬ,l&jP#HuV@gԺ9mj Y`<UiDSR;3E3J.*c1̒|,Gm_!=^dJ`P9y#O N0+BI:6lua Tmr0`1wTuv] uiӒk\ao41pMqVbՆ-RvهY \'#sn\6i-*.ǯ$؁fMRLQ8%ڍA1dKQX5weӖ 6J9ell"J' [.Kn&G.ّ]0͒E67M*oQ\ tч>~Sώ ~>, Zԅ*߹hP~"Gʨ5y/8ߐOq7W,(E- IωoJ:| <*of%"ԜR^!VJZlNН[!zsmU(ͧ =s#s mXQ'{/4̬ۛoIE?W~ępWL'i GOik զ Sf~)y0Iw'"ҽvKW=ڱHMЁA/D Me)HoMiGi#xɼ 7g=#cf B6UjXP"?&+ui{f@$6Tl1GN.?x]1xI |d`ϧ}!{gs·;Ӧ7OHiK54 rG_z; D2vu$c|_ر8IfopImV#'ߩ({qăRNZׇkˌ\|.nKDG(-J˃ IJǏT\=/̛s#PO mFF-597;e=O5&*\+[۰ȅF|RZ1[Tw_BujgdBGuG3r20ʄEֆxr,}`WIjvY;^$Gg"%Yug-i5cnεERCPd*芓՚H~C?zQeQGrs̬丮*=s_3M#sq6fi6N:lnEcH7L6JHUܝ:ݖjbښTMo,k:Rv'OhLM6hN䥤' Dw·s@3|0:R*FH[hb4/Xޜù,t!%̖ȧB1ӽJD] (O!m_>z)W=VU,$scwan_8xZ2r 4mu<*љyQxif>ffº@Nmk=P0-LװwSC)aQHm=7K#֎M[PMSA1W['7 {ה|܆ G%9Nj& tDra;|6(P,ƂԌMV25gwR{߱?ljI$*zb9'3m=`J*{2Ayʇ-/]sTMbuM˘։rsQ5Y'DX$HyS6u|8 ӬK0uإ"G Aݜ)\.|B/kC[&xAW <ٓ)DgvyķAhߧmX2diG}!<8R&Ǘ"0e^D͟$;8@.||EQ_(^._D{Ѻ5SI|a =h?$L/w/f2,YO,HߍHUc>,Jmh&#F+>C Ɉˬ2hF*=YgQDBoy&= :8Ue[E'4hԘgR13oFHtFٞhe2%n&Gwh:#9i*UTsRdYjÁPoH`cHCH-> nװP 9y6)"n-I_ҷE5blr[5iE6㤻%gOP+yhGwMtEzmp`އ nJ 3Q5Zeb!S%j {XӶPJ(cjqDZ`󘺪_[^cQVf̏#Smn>9-E>(ci&Lg9)݋ K`g∅ 醌5G hh Ӄ<%9CMRʓڌQC M4 qZ*،A'-B.廤t&2 t m 9<76(ގM۔}0,#N$95tʍQ2MrGuj'=Cb! O[Iw}lr[l򢀸qWl; z\7Mw$q#"?&h\SO"3LaxK2f]*BX5>%ĮC!.1 '2qgTzqg ח~-rnV[59R͚pSU{i8Q̆p_.% +.]]+H~>Į<\sf0σ˯$%jW6V[xL-<.7zCX_lIpL "$XBU;.>ldm*Y2r \ѿ"vo$`X$f{/0RID?JzBԖ xdT~#ONjKƁ=pLl7}vak׶]Ư^}jp;8ʎ!Us8[eɵE L]]|l.wHUL/=0 7sn:LB+۔ODǼ4>9# goTaL(pkG1<$-& dUѲ$N* PKY.Ow>}aŘTfpNkDw.]*jYeYQ{01ZD&uI\U9[05Çu f.@Iק0|g6h-f]uҬ+bB[tٵMj.4A3+үeS̯=X䆞KmoR8sI`eV|7F3 unU!s< w I~׶XZWL`=/Ъ2).,aRږ?xխv 肛L =OB"^Z4 yu>NV6 >"'~ º+`+?7œ,ψthiΞ̸S!397byYeܢ2lo2߰5N_BM5?øg3 'Op8M+﫦q#4v:|ZovTeToߒmT&)WdtgAF>eX:XH{Gt6[:B7ftkI=n0U`7ӂ8ӗZ69'8nZIr56[%!XKcÈs;t<|-(E~UE&Ot-wPr^e -D҉L 62;rI[fHn54vhϷC=I\LLp80myΩ}|qqKl`\曢)x@ 8ǚ;mWJv1HcO$|Iw :`k?*L*ģz>~"B0ʣdoMI}LoLGD`Ugh*GQZEeOV#w J$L"]tT JUfU4̳W@m*Wm5q;N6)R9M9/.xTkæ BegՃ]!WHI m#_E[;uV_:iO[W/Π4]!}T,:n.k2 T5C&]r4P)o]d):Y|kÙaAz.G$4LnbL۵p76t(2\gѐHp(j427 ּ-Bo#wu>R5`ZU(~:|Q>4~XL]e#àynV$4JT`L7gNQ 'a~B61&|Q{eBYVϹf67Mm4($C͠8'C\F#MvGM@- !bI `.hfv"ֲM-â8\Zi\7Ё )P_a!gq7ixpF`}zvoH$fU>yw20mɠٔRST9iɤAzhgW̲_NHhǣN0sY5C71q̑+h{6<Yn у*|XN}ldel en)Z2E"_"7mn<(ڳ-CGM N+GTmt&yP8d~H٨,n?bDUPho*-}׳ `.g3ж :/]Cίu@OU43>oV'ֱ:$gg,䚃e~vU*'̝̿dۦUFt- L:/$@p4`N*P iU>~pOO ٷ)[ A)_#p~Z'׏͸W+—h 2'%3Jy+g>鍎;wW>Tv?($_fg v.+du)K!:m VkkXM (2g/7ioPf^)<<NuRL)dzG\Pnv@odid,gA)rxG>4*@^:j] 6#l:p4ECļ|fx Xmd-hExPAQSJsW 6G7^h6l>H“شC[X:Ѧ6)GSp< UuB9sS0!%(j8M#*Ȧ1T;TP-ɸ, _@ӍE~sQQ:Έd y'84J5-I/QT8DٶY61 h <-\fEvQ|yn;5z.P&fˤ?̴Szq7.@h>!ԮUT"{Bg}><&<A]%2;2Y/>2{+R5{AM|҂=^K KD e2!nhxIgl۱Zs^#GZ5FL")2QSuj `VcZN8g$ћt)`Ds~J5h~|uW0t5-:,16 &^RE"UlIuFt`(O kmpX{FX&()EtQbkɘ#@u\+'E^\;a#iG)ɉON~ϝS/ГHKb@qDy|'R Y'(gx2g~a0iHޝO,Gc%Z*5d>Dh s3|xmYcŐ/r%18)}Hwm`R' [&͸eo4n~b9w^0 ?0PR|S33[\@yn[62"Rf=a@HG~ar(%M5l>];ZFIVnϰz}L?C-"\Ɔo_?Gzje5c}F-sxܷf"챞Ю󐔬+O.V9̲JBj/wF>lo&N;r$'ouOjN۸WlS  -:EN(z8ZWl*莲-hc==]Q]l{ڋPWWFr-!EJ&Y0DCȿԈ!KTE`y2nH@. a/;o"]wo{^=DLD6ݓ},:{QP*?d>*iZ|S lw(M&XeRn(lFVGU!Ofo*y<rųCuwvX vTЌh^-rK-O1B;|h/u_GkG>HB_?#+i/ ea\fG=˴FCmY>7 phom-Gf\oRվOIƇ'i;mxBNqDeYg.c MW'M05D藘 z@?\/Yb7Rbz.ZUjÛ7R-h~[OxzЅޙѝHc_(͎OgQBk9? F;w!9XԠYCb+ YE"!!F*ouxGȔK)g30֩O>~5#DbOz;iIQn%̻YR297&lX ^|C)L[yo,qkCCa";Nx|NT ӫB%ߌg8._s+5S|21Zk]>/ByWĹ]fKق5М7QV'6POlo+V 40`ոm4ȀsV郑]$ݞs t wޖ.~\d.jqOqeHt;e'@r?sO}2)DVQIx ȃk@!=%)G ;AoYPTOɘ6F4GШ}ah` -?zܺډN/' !qeҋZ+lΫ@+Dy:5>L=mg(UKN?M.<۰Y·jI|ޜ>= !ԊF={w@;&&`.Õؖn\86%o0 tY f0],3u6 (AyEvKPG6=Go9)k 2),^!4ң-+ QO΄4*v}bEsf7*2j+zp 2Mr-:eM,,2 ,2?A2~m)V8 8 $y47vnD&̫WZ&}gm@`V Z^e5!!栙 /q4I]ߒ,@>ua,pFo~9Њ Gz4!FboLuDznm;q!ܵ @}[ ~k;yY=B-f@ 󱜸 IN9wD\2( ?2j^U_ f}s֨ŋ~vlt?.m!BA.2Ru;moglzMcx"YN"<}KthaQ<_Wu 5DӄVe![_oUD\f5xա[$={+YsxRO\I\\ 5w,g 5z3G2|9ʷ]4q*;i; mhKS,fh0(ۑ$ N"[%!ϑ & sTm+PؗL[")mٱ9>$ BhҍHXfЧlQ=mILizzw]FwY\;d-C[cJgL!/ "\ko^1nCn ^sA~{Nlt!bAڿ>S=9PϠ;ʓ4Ṭ^PhC$x6VڞdZiaj!fM}/ ۯԶqYFTxmJ^KOhf*~w0NUv'>Nؔsx>.ڊSz(Ԟ7d].l>m̼hLUnp}ǣdhˆUvM  dL%'`B7?6i!oPpv;C|<#F hN5\IL(r}:{)>[c״czQEt^5O5 &j"E[r }nM8lDN|6}#{(P&s}>/=d*&]P9k)ՇG̞|/wVLj'KLb EE! oz@9DJ7t3ۏQm=rf!GZcjò|7MAB=Ocf1t/2@5_ڬ E^@FG4vIpA%4V+.EBXI@iPS I~a!" HkY_mY$'TgDܴ{~9p%]ۦڞ6~ϔU%ڄaWHYf!`}Gr/e=񂑖Q0Vd 'FTRnD2u qTĒ-GꣷE4ڹd7ݦU!o}aygH-S/W~:ߠ&$o"T)O_@u0u?Ji¬t:{'_DSkV lnVt45,,)衇.oNvdzdBR?\ vneޒz{>a3pN=7G2B_P >dX=\wW9*>1gB/ Vgf`PqߡMI7~4Z|0uH$5Ϛߺdd nfg;יg2`0rwۑ @b'x;Ԛ?_`m$H8Ff#`^Ub<H@hPxQC.ƨdh/ 1q.AB"v]VT# xOTZm}.d5ـxh/C dNKX&xMq^SR 8 GWGv9$a]Z]@)/0@RT:mǃJދ`8YG9V2#suJս,?T9羭*$Oޘ(jX҆u*3s<3AWk3#g^qk`yiUt2QfYGtl_%ܺA*cse`QWĦw D%f3nn婓j@[4Jet_.B'JdjY  eUW$`jS[ݷ4:R6[j\Rfb399sy<5t쇕[G`Ș2]W֍zTl&LoW5#AiN~QZgACbbmZ4ľAh9QN&%=.)iV,) GՄe|5'DU֧cz}WIMiKZ"Rgvwb"7't6dIzCv|0dY4=;ܒ \Y{i3P_<n9VŹ)F:ri!`}~{=>OsT+ Uy]DAG7h°#QAd)yӊ+F5c9&|-se3aw൲~")M xtUԯ>"w4HVXjk ʮ)˯;! snZ/s )_(d#!@j좤ʪu _stFv#hgIfK0N'eS.\ rF&o3B(Rqq2 {5t ۹@$H=~h*e{ G_EPNOU "h'A}knF+ı̸ )\eۘL)E^K;@Ǯ$G/ɓI^H-j9TjeM2_x0_MH1Oϸ j5f(vVOGʷ ?yPhR/`b lLx*?l2ti+R|5)rғUC/ڏcm7gt|H ~qT} \O"C`V=ޝa#l潌YF"z`d=o8gCIJ lƑW~ w'(^*0O8[`yy^~7[v$ʝþJ*- 'jwE"S>U~"?ymIx (TeTSw5 4'GPz~|"+V/يea⹞:y'WV reW02hБB*p@;L%n8(pVՈUQ>H0l3.O̡ˬɤbsh4x銆zaP)_]}L+Z!e<<`Bq2 *E~;E\ e羮Qk+tKoXZ wEiX_u,&44ؿԧ3qrv,f*e3|3J12"\Cc*p8[ܖRк3lnJxbk.EB ٰ4uԷ0Tټ9atF='nmjдp< YϖkZ^Mvɨ[ :Z4VKgb H.Ki4S9o:j'S<Є)G1w/ Z.<+ξ)U-(GȖUJ RV^U.wdOZfX5VƪgUA%AKGk-,g FE4w +)#F9nef2S]Ej5KYumZJ.6PйqJ$ہ\S2Df?8{X2KXWҋdWG Yzx)}y!D*^r]ZB!rq;mg1?B 㼸B5IhVax$|Bhf^T%6Y%`Rn_eLrlXrxE$b 'lw_[?3d T՜x''on:WDzk*Bwmj+;|ѫ.Rn%wqN(୺3>ͺőLS::@WF-Iͩ9'XzT L;P s=mS_rVZN!Qx0FX<16|~#  _܏$Q@19[}_dmj'[|26?Z瞱w(Zלe3#مV2u&8ܚDJAl`"9k|/|o: nHuIfj,cMirkB43a"(4{U\K؎vlPs< J;~{x6bF^7q:auW܈t?N ?j֊ڞ QCokV&ήMPzktP[,5;ԀUͦJr-`,us"W7_!†r7K UbhjnUfe>e  n~Z*Cؔˬ ]3r2[sMMiJ;v:_7aR\&5Y=\M *(=: &2ݜnq7_M_RU {҅+T^.3X t "F2?0ܾJ0TrA&֌׆r+kR;(֬ah,]JqzCINmSh"k2cE֚3{ tM1ߤjHwZ2:ذ(;']܊k㍪c~ג|׍hfFp -lRR5.w\bb3t;N7Mێs&kmo[@kt8gnxQ#7'My'r)49)} 7\$®ШH`kݸoH`AsN;^C;( Iqӻ'\GX`>kFuc?{<\ei!!P)uGJ<QYQ⑗-?U2uFM{XH{*]S|JPȭ8+ɮe/p7~@[ͭZ? `v?6ɻViO;+/!p{WU=7h BM]ѪSIc{m{m[&%PcoaN{B:. `k!'z2_:\Uh @EoΝ@a*r B򿭝vN |g"Ӊ12>&FW1eA~s]ؽid~dZԎYGw|!-jA5/KQ❛ׄ)hѡզw"`^ {e7w\pussV*?;.0@q!)#ȴ&A%&{y-{䖭V֑nݘ/EV=U֧Ϸ+\";O(X5ǮAK.`(Q.P@߄*^^ `X3y4W{)BJnZJ.Jg)TlL6ؒō+Y\ve6l/Мf;Մ|,3 @&t!R^k:1-vHJ |zOLK6@.LKwAYib``kykj yy~rn BMqsy)j}1_D5 7!'d S *gS ~rs!&:= --i@'3F+ eZbeY|pUYqQ8^3ޅf)XfC2Eht6TMBfF9VJ.kx8(zXEs3DXYGS(R@jv9KL ,}O\CoUߠMGޠ[J TK$ٸW wpxCjy,_uN%eBD*9K9~ZJ߆thq6E'ˎTFe%uOzo^Z1ِHw{yz?CZ@C*Wv3c8v7^O.E.S+1x?(v)ܧ\nP4}SpЕ7W̌N՝^2(ՏcAGQlV,gC]>N8VXk`Lj\2OK'< PoTӲaʼn ,7|(Qa5撧V.%<:P&%+|SXGO*+3zğW82` Ѓa _:te|k punϢT 7 `KCpνmx'S8 9s> DD%ޛNI%)r͍Rr K*dY7PU:742.AHjU-ZWZJ{Q{ c9k\cn?F Mozٴs_:78/YIS Ɏ[6lmc!ɼ22;$#2y4 yD(KngGq=C$V4Wxl{sP3(; &e慰3pȯ`NiO JQ7I3ھBPnIC#MY2O"n\d,3w /&)þsl̒ !=Q c{l6@.U>X.xxzq~Cc 5?XZZK3&\ʽ(ocE\d-ذpXpC|HC*?.2!x8ͨیbup{tK2$Uj󽌃zY_>͂o3WV>T$`mzM dUɭh-%*,LQ܆rqqmBE|2[LK]aoJx:aeW 6tOm ՏƊoRAkٛ#4FqaÑ!匢fjX$'hE:l'Co@tj3[[YـW/TiF\qgmhbm0V$g^"ںhxGXzz"u!>S- Hs:ܨ-`J]CLr1$ 1ުH:mW'm9"{8b6qã%=J܃;| ; L=jd0ZMSff~ jb0\^GesmWeSˇ%YLN-7} &䡭\e+䈝9`B:pDE9Q1atRTUj3 7"ahqf>A7~gP24n쬓7c2оԼB:* DkCIQlF T?In:d~ŲeV]heL}L1u+E\&eWq&+Ѭ){ˬ(⏂JQZ"[=MnS,ʹaG";%JwK4CEEc4AoA'C!+&\ʜ!q5l-x3F'{~ 7G,JÂTpҚg2[" m;L勢5$%_});՟hZ?[fΠznoD2uo:.?)2Kyq5אsfOy\&[^j«Hiyuk&}vViܛ7Rz{&7VopYCs#">)-۸䳍mLmĠipElixϕgb5ת.Y\[ #nJO2GV9Υ CM%=YmԔ^) wOOY;J <rs {`P[v<PnoT(YK2Hy*_,Րwi 0 o^'%-e `@C. hG.͟;HE:pZh~ W<$aCD:)uF}.CYH.Α)ikx&;RtF YfMnS:aR^H$hr |EhzsXe3dHô${7EfzjDSDHAt&vǠ/L IgG=]ܳz)xA.2EsxЀܞbT(ol֟͐[}"-/6:*:!IM~lRKϿ,\hgWN]7ay K‚=g`L-7Ze耙< XǸJsIniҷ^hNF^%s/v~~T7n#O=F34Ce2*;.ӱ̆ogz#=Hy۽ЍFЗܿ?r'~G/הwJoCM.^{4#h酰 l2(VT%x6CyܔXUІCnBbEXjw=Dzw2O2!1XG6۔o+ h[oe$GL)1VMɼ]a rk7qR+MJw fćr%TzR7! u&&ƮtW┇5+69RMĈk6)1g/ZЪqe;(QȎ\)̓} \K y>dR翰U-P](Dm\V^;xCz,YC?kpjQ=b'tAzIDIҞ]ɪ2L(>^-sTX"?͔J 2? rK^qxBGO|#W au6#ÞPii}QS`.s\$ïy Vv! (ƾ20邛^D;yRZg[Mg:"Ά/ gZJ&efgY3GBAd{k7arH+?Edfin}|&Kܿ8N̈́N>UZv+fPnX<Oh?VJ!L_Xӡ*hz=nryK!gcb7K.z\fGQ=z V嗟$#>.)1/i:eǿ& UL|%ui;4,&Z+K_ .P7i;C9Tq!)#g2i>'}áA7!S,qQW0Q=Z[ ;uH!44MhN׋ƶꣷ"BioUanvLUc/]`:9LJ6O(nq?~l@(lTIO2/Guȣf&`IIԵ:0 L~<&?Ay0)~x%| p_i0EG)d)Ô? )[u\-{h{ohNDɌ8[_JQZ)R Htن=_"+0 3 h斘ŭlRa݇SHu20 }<MyN{C˰7Y1yNho b+E'S|] ȐP m1r3皢*kL)oAVn7[MpCGs1lސԢͣ,8Y)B]&QIL 5 ˛m%(i"<[[@;@QiqM8t?_g!ĒBN$^GA3= Td!cS|RdWXT*5r:w=?J.Ș$*P_<[(:;og-sK{g͙p<ח_DQK{1+䇷U'ɀrޙ&q/6_;Uvk]R(H:'f,٪#K]6 (0d:x X4rit#zsB u/aR̛99Zf6_!Cϗ#6}"4[kW|G:D'm ɸ,Cm&ۯUH[44y?w"c-dgMRLP Toѻn݃ @R}t2&Z ~PMB䠾׸[Yv'{}wsU!cj7{Iz4lZ4+rTeW6F0#3uuT_3p ; X J7D87vI9(! ~W;eĜ>UtBajs"Uqv=URw&mwߚ+laapT C ywXenlݩޱ{IcoE՝Kۂ\`,S;(ʫ| ߩGyZ~'>^]zT9Ra?:f;gV=fOp6!M-k^˿ыYluN;mYr3: ܕ%Y#$RۧLGhǣb2+͆A pw6Nt ' <U,WLe MOw4Yߞ07f^f;~IM/qf#Y tAN 4⪒hQEtnmU=R bPc.7Yp0:c~{~PeA [Ƴz'A3o,> %vٵd}63:ߍTiP _iǯdl{B1cd'R .kVԛ6ioMT\$zJ3lyz{81eSz\Khu[LeDm䜟d`EgOP]Z4dJ[Mw W䟣ZOTjZdxrF9X;{E~ +k: QF9X Y?"w+G̹kf2E/<ޫok5ƚ>j.O9Ktp.Z 7e\<9)Ԡ=[(>~p{P?G)`P:׷4EE80Êd`IldZ"%﷉u AEm d .j8Vs͕vfQnDñ hBcbF2.Ә u'T`y^0x6w5-mܾNPǭ5y}Bwǒh5>za>:\ΕD'pTCISQ%Zgc[n7<6x@SJZHg|WЦ8([f/BLCIa!]D"0 fQuS FZ[=Ѳ.6'^^&OAi4C-S/|p?J|va[h7ity{@mMDu.zT2t9nWL/|sVL6{Wt[]p2.;@騏iܵ@Hktg} 'r5.Ja$ =o?/0G3m^j r'- u{v[ûtÒw"ھ'VYcfD['Vc/, 8h eE\NfqTPz%C[}Y^1 ^M?ܫ?g&6q`#71rͻ L4XZ{{} P0 C%3$ Ҹe>m_;cJ.sޡ/S,, bckfBEޘXZ2jzGRp2 J= PϮgƢ!S[b풏>cS*ͯj1KI~LѨ1Gs cFnKꋇfwU>ƫ0)(/pq~T?N˃!RҜʚ4 o9fDW''B._qu) 5 R2QҵJ=t7Ǒ˴{Q?E] VCܑG,8psCZbO΄e?0lfAP)Mo]$Q1LU8z;vBe|nn\OZDb*\cwXl |*^nvCʛ̫w FR햆 IzLSVجٰ!{YpW;Kj$EmA o/7Im6dԬ*uWqӆӦU&#~ڤ;Bktz: hMȧx6vZLYpc0O&dSF CzSOatx?!y肜jS@:oyRZx&.6~`e~D;~I axn1Y_JGR=ʘ#tL?g٭4tO-F0>+u>DFT@]Pd|ĂS8K삫3h]SV@%Mc6KS8s 2/8zv}+ƴn h xX|ܿOpS.)[?m>y}]U1=QVPܢ jL-|.SZόk4p7*d'UΦӠiTfbAM?@ (,Ļ0nZ ww:G?^1g&Dk;BBʬ($B '+ܠ&.:amڸK^Ew1A%WX.0gSꔔŇdiֱ;b m|97+z砶1 X{{_}RIMzޜF#Pvw >zm΁nCYs Cʇڴk\^.։G6ӷ ^\oFy" ,466|\Vh@el9;A[$Gfb%T\X6 z222=NI*`9f3½XDl{Lzt[em31*&N9РMvLh]f5ۺf^VqPd!~sf76Ht]׳ Ӱ*5V: ZIZ*&l6JMiy9$4ۄb!77<+ ?~SV< Ѷt<hY/uVQȵf7E">1bEU?LngQs?t,nT1i/h$ CIB*TZTͬ0Z0rLv8v@)hzRLzT`8f*x492Wd$/lQ 6XnЌ@),M]Qpy} Rv3D&9?/cr$wr| rPT 8M|*Fߞq,UcOp۽Kv+d0{Y^kwzsZfchD6-<dΦ9*/r3 0k~0Q1Ee&܊:wԱWq`n4\N<!'$aqm}w*um+[wˡM!? SXݯ hF`h^ԓͩxԬէϣ0✔/t|nicwwԅַ\}8'vNʈЎiC02K\dBf ꕡWOv GԈfssJ89 ϧX.p֞זi>KOg01Q2K&d&maozֺ_VC~[x4YӱvkkohJ0OcKhdSQc ߁5fUre}sΰKʻayJ|왅y2W`]}ϸsE\%i!E\%^Ŀ)l |t4od^m \Ɣa'6~-46Y<Gb!E-26ՙl G\ʇng-o[U }_z0xoWLrvZE0[C?7F-S̴9pU*Y4:h_zCڍ6Qp72yic9˪07H/MkЋ^ߜm 3/;(ʞF{,M4߽PH$sJ:]iAcMsTq/s}jOî4)d}%s ^ >PbQc|Ed|0W&F)Xa(p(Di~ߋL|@1LMFvD^` /6Ũ]Cnm{Eu:)WH'k!1.sQ݆~%ҕ *lF8C }GSf0cwiIi{ Q  (4#Nˇ/:vl^#FUt=gtE6@ZS]mєUgǟ#Y< f Σ#eNd h`UMM} T*uu8ɊdnOxepǝilbP9_-e>Ac4*0s Z'e䤯8%ie& Z4S]$TxF,s/o{`1- Ul>s3 i;=vӃKg`+xn R=v&ATw ,|n% gV9; dڹz€孜eR#_MFޚAO(B?g[-ӠPP%*fK$Gʖ }>W!yrTg|F$(?(,'lWJ2 r>,u*wL H©^Dy卍BS^|E#x`e'E~%Bwi`뗌L_Hz6T^~|ߵvhÒ _eaIHաhQs+cSzG`it̜ZYO&ВbrӠzQ3<bgXmYnt^Q]@[QiQ!pfBNY-}|Xڎv1X)>:|r7?Sb\b?:vâ▛W

lMٰL>bݷ; 1f|g"Lಲ,4mg+1MʃH5@xsS_'OPFMyd;YN%jwƑ:պ1|G2MHG>Իa=W\ 3ۻawGc5Иkhg6&3c[\jzPgolq `SL@M~&C{UX[=ת G#hmKo̷1>Uٺ} >3zO4vSЌ$*>IlF=JV1) gNAf } fV䐤3XB[bіTt )%?\PnJ%4]nhM4`^f9X_ILߙaeMpRy̓xTob!}їC;QWan>ي ݮ`G%iC0&_aA봮畕V^a^>R ܪb|􊣻5c=g Sˬ%?꼥skjl2K})$O0g,CRЅ(/Fl5ML YnNK nP& "3ze/&T32?1ݒڭChW&Y[s7qQl̿0`ALB3bӔsM(ȟ3 E71%15!˿ӘnR,8q2/ϔDC2 6HW<@# LFT]=lDx0 ^ED[N/r}K$ jq.H(^hS3^%|ywmbR,. -޳ b˶n%聳}Y/"wgH2=UhsR6 7Fj9{5E&UUTyl.r:}^Ni]HgϥL;rSt=ԜM8a;dga}WoeBz<^84hn6슑˝=zlݣo>7**g^Ŀ C7FV7'lZɫ䋿#w3^2W2U_+ ONz3T_ۗ@Dr>އ^[R⡛r(נ"fcW"'=a-({^f=o2IR(C/K:&prb?ʀonv\ ur@[⒧a 0BSJTU&^>Ym%v^rȶDEٖ"SߠDsC@AW!ei[Џ#/xѰHY4؈v,gM7vn:(L.{b;%tQ&]jKNۼD-_{Ssf1Ynt]Fc) b ì\+l5_5 j׃<H֜H^qMF圲eU¤]=Ê; |WNUb}+7nz kf#Vk/ݔ}ddp^@Vq/>]"a^{u&߬&y NKn7WPґM6;?$ XAYej[LƗFFڄ *j\~j{qeSJ74U]_deV♲A?h=BӞ*mqsKJz E4ba.U@-u۶i_BA5`Z#~*8=xL7KV6 =9Aφ8Ar`綮47 LsX;qG2f䪬-[S./2n0׽И3#mrOPHolҝ#N4-x|ʔ-O繠>@_Θ`bgٛ>IgѨlv^q Y':$&ˏGɵ,p޾ Oŗr{$ͅMU{LH)\}d!Obڞo; }$4 XQLa<ڴr\Ŭ8kj{7jgfnNY'ynM }*p c&7.Y9乗' ވ |aU$ajշ me2o7ohK縏j2r{˖#DBi*; ^gzft@Pf2g?s J-MGBF*"ds0ty9ۚ^]STEpMJ 6܃NsyFN.*xPgWS' $Oȣ0r6\a=dYhCf?{_"KcHpB0C.Y9@IL|Uzd'&P R $ ?`,nKkJq+xp?phԉJ\8za1i'P|s}([N7Tѧd&8tx>brh]#Q^="} n<| &ͧE^u|6O[)ODa?ou_̊"u ȘTВPNv|gvyZ> B2Mo1_< `s rYܜa%G }~͸L? R E6?qFa@3]2j/#`Z:v?='8V|FǴ2-wFYo0 f*AM7RtA@KhC7-R`>9A"vHGG{9#W, p`:2À>Ao)-TWKpYWlX܂í֘L!C4/$S=i>K+a4w^ Eۑoe"<'E 9.y๩uɻKb:9;k@)jl;:"U Bʞ󝋹p >鞈zxP8X=9t;Jbpzh7207cGvI2xdGD׹p&` ĵw^1"<%n_&aL]}|I [TUfGń)aWFW|b%S?WE7}:3Y]7^ ŸvȗZNk\+HO7D ,@K чisd8Q^$Kv'$y%17a +R"͜BCs2W]7BSqE,24Egc>O[hfʿ'ӟRHaI׊zZU`Qp20k1SBh4rqdvo){~kLX.Z{㢵7 >@:1b0TZvlybyEC*S "ҴҬ D.3D,,ZL/5*3VgڴƼ5t\R$¢[ZH}!Zu%D#Pؘ]#7(\?*e1cSq}l `!Яȴ{˺#dΆ닯ԓ0BQ@UK:-ppeYm|tqoFS'Pv~zOnwM@@oYEfu2}&a7o2m->jB M pja&7ܻ8iYޛ}2%T~PjD 쒏Ci;^<2Mgʓ0&FŘ#! .ij3f-{w)Bo]jGul/s=5 (۷3wl\ORsAR޺gD|/Nf_cکxŦ(]\΅j''V"WӅ$r30dͭ&Nūg $%/3!lkÞ0 V)QKg༞>ϗ^R-Q{ Qzۛ+ \F (iU%dIe^DS(<颧,zGt-dgL넨fQaaXhР.}2uI<5h$.>b?5_' CP!rG9uti?& }=k0 1])dֈ x&9Z۷;$\Tҍ:'̘2mf%:t˦aB7F|2Fiq/$ixzɛ`H>DNtz"!3$ hGcn ']"hs%_7d^3+oI7?nBZ{z ֙G"?`Q|dmKr٥ bVlv$rZ`+ZZ-wIZ#-Ig3=(uI;Z+JA\8()'"}% Ikiڹm%|3XNKGlW4s-u[dz<9Д}XxwT/ˠˋ|l榻c%ŭdgxFBw3TwRV7 zHyaf$ !>?%G'ϹCިSMh|nrE5lk7-[TX2QpQBIt(" vvϘVVK= ]cwq4~9B: Ӓy#y #yK'J:g ^W`{gpeqF=5dx:$B?v> x߀7r0i0 3ñ3Ϯ5韛4j2٧ hҁό7.j yʌv'Aqѡ-),)C>6c1 F /VF&_ebVWD O#/&ז }~ *R/s<;z)x0Cl`r7󚈣T>L׏&ɕW%'#G< қ~N7d5Ш^ QZ~:u"e(M|?W\cګ(iGJj=ai>H:8kDK czbvGn;eNxm*O'*ybi&a)[ͅu+ OȯB Y1+Y2нB#{qkƳNE5\zhT兡Dңimm>d[f^N٥zu <-C3Ot˄GQoȜ-5YI36(;̪сf!|ǼzX-J˲Ų Z&}*D!td6фOAP%}u+3OdnnNq@db}?q-g [`X:c }!Xx&ky{/mPZ4ڟ-|ۓDa]!V@+zuEo|d'/ |tSMH ÑE\QGy/w1x)rorɍ$2za&a 57_kcKvC49 DUig٧Nh6?:}ŗIx4Sntֶh2ƄD[Ky3q1a(-*FUۯѡ)r:[&"\ 82dqOaD$fD]{%R(EA.Fqo M 22??i 9\8'|)WP4, !7y2GZ}|a\Rl\ ZC^TCd\-q}?!BFwr`<ԓͬL+rm#2JةI/D_uEH4iDaxآ-ACQT&?'Ӑ_lz}*=",hc[-{Gt̺ COe^F)tzpOҎ^ЄDZgKSS"gXM¸3 >GʞijC62h5o2 U<s=gСˬMռu+l?R0p Ca.Xv? СҸe[tc+ TXȑ[?A9o$u$s؏N$vC֪sd p{@GNvdz3gˢK`5s66E\S#J֪nn.yG-r9=Lq^ PީͨYE8r2ңci Pz-A>ċ1nLfq5GgEs7(l$5k3mBwJ&HՔ l~DIFTFk`U7ٟS9I|K3U_S+ق=ߝs$ݜ3!BTz̧3 =]4)c0O o[TMuQTOOj" Q\Qw#r!l՘-lV΅7tRyCE=.ɫ47|fμql^Af!6EtQ4N_ gn>X0P,^=tȌY.[9"R/3_& 6mC~bj `Ӵp"ZϜ+)F((-+Ee `ybXI>1voTMq}ky/[:P,(YF VokAWWZL.8c8]F7SF^и̻TK1sQHXxdNe?2w%ɽm5r1q>Euⲕp@M+I PkI,:'*,MOnDlwGDh=Wљfh~y[/Pp}%\`rS+O}vۊ;88}bLaBV'u/tRM gȡJ(vz$w+CS7j3_UvV_1@FKGRE(O]Pe D/x ENEO -xY1~5!H2+A-W3maqt&8 㲚H% 8( ̧_:7v*\kM f֎4{*!z`O4{ypLGI$@PBS{.@a~{DG)ڣ3E{:>&&ei=TERPf6xLSƕKןk:rz <` v[r`FgM,D&Y*1zg[2>G:xZ8 uyP缃?|#1vOU2Km7%9/3/MI qѯU:-PB! iP3 1;?+)'mr.j-R=^-s6W?%b-N7(f6Bn>.P[CJ<)r=|Fژ>teX;{[ʈD[?[=]L22C^f9pae04i%teZ)QN2%t,! !D痄* ׀'S!0̌Ì ff%O)X~1O.a^S`vim^"h\fy+"-5[CY,/mL,[TGf8[ZZö魳xKp63P g4Km㛅G~>+ L93٤Md7CGl&&+HzZ?h: c ǽ,yi)ЂB; Xhh]G(p=5䯠+tGp$q Nn9E?d)we$ Ȱ"ZOӧ?T:xaURc&o5|I X)e&1Ǥ2@zP~I}ߟDga A;zT锺?$VpX-(D<7/n7O!M pt:ʹ/|}7yze lä Cy/Ƣ#nTһ,Tˤ2&= xXA)2էnbb72Sݡvx]vKi1 Œ02I 9~1`vu Ǧo>s`ꖪa=fX%s\{4H7I ujq7GhrVܧڬ"'(uW9?lǣ>lTJVD3 Jӿu*9vw#~@W(t{4eZgsգ\f>=-` }8)0IDKn|n y-Vk:ҮsVq% 0YGzp$˸峧dO7#F;EA*'ydc|t+6n!4#ibmiwt: ֒]烵4'5JDE̴JV$ "3y@״8|gЯxF] b{./(OAs-']r.0g2bV4}#TyX8v2E6EfcZg5# -jB<cqР4uz&\''3C8rQf<.*T9Euc2ݦŰ)tAߠ (wgv1QI|ɳ1rr6njEC-W'`{Q7=YQΌHS"=[GG0 -^I,.-o4XwV$:%΅<4 d+L\l+ U2A#JkC|O6m ԣ3:, E`\7O5zeqkuhb]`s8ܿ&@}Ҳ`BQ$x 8FJCShe4 }DۇrLωo=f%IVOŸZO[#9κ5B\A5@ƣ^<$`Q>S:W 41Όcs8[$x6bHA={LȔZw8~:cO3x )ȗ6~ZgٺGjra>N^ӝaVv[x\T C4wxN[0vIוIambs7ҖH;  -Td+|y gFi<>&( 7y*Z[D3$C tĒ"(#QC !vӓ$BXnQ`Cz/Ұ|c"bƟe@\%K=wCzx>R>5+(xL=?JQUk\AY! S/}wI=P7&hg榺cr=B;nv e ,?=m ]!gA.[_aڠ5=guy+Yݡ.yxK& cH|<jǨT GSfS{kIKtͷ#ݎ8i[ zEOz([-Н pΈ?r$J(YYϒI3'qc\uT?K$|ZdwZBV|\^:=ݓ<.4$ce`[df߃Ŋo\2yAX3Rm%5?c?b Y E٬ sj*˕sR J9LEei]Z}mȦ'ua/M\nˡMөJ:+No+kyzss(oHFMqܭ(KpA"&7SC?CkUWYeLKQmes{(fm~]_),lfa4Q>.qYh1+ސ!ۧҕ<3=N an:.ȭN*iڌ&xYUbo,A7[U '0 Z8xlI@~+!KFj^,$S/lLuQZ|1~^#$mi}n(A',9WL T}5隡ɻ97/ؾPxv;}fa B9]ξt haY%zM6=67G]a!ilB/P&W2"x5n:~{C[B0drB*''?hWb @7ۡ"S#]u34iz #H:aJk>P%;M!ՖrXY 1v<>l{zt4)8󕉛gCmS-06@ܚOMuήstLu |Lqt؃^wl9+L#ݧیPdzfM hENGDb:v6,J@ Ab {ڤ0%en܇_-3 C7ܶL7fs^!cii3{4=t?T6qF0Xk!qބ`{ 5UРWGaAEdCKWӄR"SP|(L%g͕45":ҢP{2LG;IJs1Mnef=\[.8 <-y e ųãio6ĂgM@}[/r8cFBa@6j ?1v=c \M\[&/6Ƚn _[\*㸪9#hZtb[Mz+xS$haCfIY7{f[U9K¤ˁsinaz"ـvȸ$'중mM/x:B|E6yjMQOק5ϽV4uqM5Ef[zͯpէͦ󰵆m&Mw,zQEm-jek#fkqj9KL/ڥ*!SRˡK%Q>q[7"&93U9]|.A58˷=Н~8y/]e;l&´mm.#;·e8'bJ`qo'q$ geuefH{Ǭמq MD3txߓtp7 y埓}WUo]pQ j`jBtW=3FJȑ]M$dEp{jOI:VB?{:'JpA%Y'kN6?6ٮ#[CsAJ]?^|>-k09oҺ[ny @o'tUmV佩s!JRr6SfK'c ~XJQkG[jw]OsVt+XYִ|(}$WB7͂d9O_r,W֋,y0^"p y;)]M 45Llbz^3#y Z;2o3ꄎ |GngjZRz R (s?DqE-+-շn7vv< (Y8^ơ{#B%9;Fw b5֤kW&5Q$L@n++˳g͍A^(Pй2<$g>x9ΐD6(oJFbFp[[U(q,#,/myJ4Jr „Ɛ_쉴[rUމ j-a[]htA N傡aӻ0kr6nQZ!lnuQxh7*S\N׬( z%R2t,Y=mP.:io0T#ufosZbeMlWǸ}}B f >bt_xd54IάSHL*l);Ӊ `ls.%wijDʱ5ͷ6 ֫|X#7rFXl^$?4gn&/)c,%n@/mEc')8!8Aqg }+r0|h3>J};3ù݊zub%3s5_xu>B܅<+dӏD.>8}<PX/O-{>H|j <jY1X;͋E Yhۧ^hv0I>v$DzKک-oW!#[N.:2 j9>U}h. s-57ܜ ~:ًև Ῡ[r>:V V)HH2hZO9?,/E遴(@$q @k[mF{uw3YFYA=ri7s]~FaeZY {}" Errq {Ͷq&Y٪2X x2f晨NXNmL}&ͫlf Y49n>kug)fB} Vk{KTdcb<‹ooqB.UJg=b=tuLHeʳ̥H5 /cUwJ9T]6b[]N`o^&z:7dn̥Ot/gDSFG y% #y{1t|>ϊQ?Mlnη|zZ4E_th&q)/#-zk:Y<}~/ڷ%1P]j="ei)yric<'s[a~//1X6MNzNfZrFGn,b=6Z5_¨iBY]zP6mӸ d{8n~IjD36ZftQxvB)~rug^``ly&OsvXO1ZLVVZz^p'̠h|J74lUv_e%|**{^2} yYL1i 5i3/,is8bIAIK[N쐴ÎZMyG$`.[~[g;z(らkZ* qNØw;us*{3l9C"]A } Ur=+{Lk3Z͋~)POz s<}pTjmr.da~S&8os{0,w7*][8ev͑Ӱw>Tۊ,K9AZݶZ=,~+aRui'7/ aa8f_) M{z7Zj]Zr7WxݼfNKFqW 5tu3h:ʃAAp \۾(Lּ>[~~5Z=Ք󎓣d*{aa~FivݖjiLBԗG𗑮uW-zZg!$_/\gaE7=nN(|bv& I7 Y2rh;PE]DjG0gL9٩9gpI)-\ cl&%PO9OfC/c*Ly@e䥽oe0󡰢 ]նkV aL|c*j(~,sqo=KØP'ue  kģCu)\:ނB#$/dLPܘMuTRst]1Y12v$e)$\. MN,maqh[JEVRCv\gߣ~u +i V=W8pTw"Qnwz>qML4d1}mf[X gwHkܕղj.XA>WegE^Vn+{WʡxW:-*(CŠa֮B;4%p=N$ n'WG]TL߾FA"VT]ekx3#HR `Hވ4pL4NAAjWU/aNXժim|r_;2#93?b>lZh@ mC-QH]!USdҭ狝a<2'~!dPb}Pt/Ķ&x8@x 2Rͳ֗VRݾ1DgKF3g9LMb<x@2Γ‘NC'ȵq94pz%3cujjsS>x[ԣ~dϸR^Oк(#^u-yNdr|ndHg05vZy0[rx 'FDwLN\>j>z :xo+Tv'L̆H[wgpZi߁ ,9Gqlwפ9csݼNЋzwX׻ܳzNX9oҠh=ogɯPX:$&+$߃F8qkzTNݚ;UN.0MͰݼep3ɿ⧹Dq1vЛmiC}NƊ3ϥ=GPΛgŮVm>\Η }5,WU"Ovں vj?zPDЩ,zpv;GM`d V>>wq{O4qKqSzT}_Lݹ~ !* m+|weV{ 緲)=N:[L f(Cf|w0 #7 4(ؽߛxn-̽\w %0eݫ{ĺw;LӬ>д%mWH{oمVowg#s9 y6%S7 4?9ˈ6meҊ`C-s }~oo2R4V~7[PD~ՎO2rYtْfL.SQkլ'[n4eWd٤_we#ן%9wgd0;~nɬǻ-W^MYF1o'Pj<™[Mgjт[򺰟Ĕ޻ޮ^IߕiWw)jh̐Oo6uG ȒmȚ-vf{ En=c~`8eZUӛsCq=&_LuܜoyF^Ih6\ͣژ΅CJEрpP`rz{{}ڧc =pv> EuGB|Ț8K 28+SK,?==VZaIŬClbfns/VTFÓAsb5 ?_CS95-4xP+z8uymɮ&񼳥= :WQ9 ٪ԡbO'w-yqr:8o }+ &4h᷋z^ě@7j->agB458i 2s|4DʅGa{NO-c8dd/KNNQgWf*WRO=q_3RDh^u'2$z .zXԞMnY_T{p̘(<: 3FV3 hs1_!HQA9<9]v8y|Pc8=<0( pJ H\+.=a^'5i2M`LI/s5f7sI/Yy~J 23yhh&%3s|!G:y5/Z۵*ޤx%zf"KNXwX8g$lA٤.)rz5W72ˆ?P;a*:$4DI0шeAZwL`Rw<[MKͭ<^] ӱ J2YwȯNS?M('w,W&EZ|mR@ s2G db:]fɹeKA\[Yřf"׬:t:;KP!F|Yv(!L\.%_hERyuSmeYUFϔ=М89zT,3.NmWK0H=>z-DղיǫB!OJs_b=C/zNڔ?bԏx\!/z^<"?eՙ6wQ%{y;ߢo8IЮPhP6nr#= nNKhNкXu#s<|DE~$rg7ZriM3-(;ӯE5im\$Ha\s6#Mo8UK泗Һt^}UQ׽Dyo NDvgsO8XDrt_zߡL:w_QUN_n. v S0oc!w ⾭%f aZu߱{ywtk{UX2t-QMuaP U,7)}b5Uc,lW8[5ⷹ+`V*CnI-[WkBy<W\Ά]貨򦊶s7h<\a?{};;z@)*VPbg l9\-ѴQ /1S챗}9r3,W=tEICt <~Nl:ђiayrkl<⮶~b]kK6ajv-)cљ<8ӛY.OrWN\Fә6cﹰ\k ҟckseWPJ+и-S%v"b#!Xme\h%Ѧ;]8B4YGKʡKwf[\K2nw{7I+!IeO! R[H!:ꢵߝ'mI1|:hN2Z6*Cy[kxhoHKν0?|%7tu>b =(dyu1 (c;jg0*}ϸKdx R2'X.P^%v28Pudv2;[8<[';ow] A.NRS}~(KPy {܅y4Moeg.u*'#YNYǝ;r֑ 4)3;OK?;h LVuD!qfP\.cQsrgN8XUPq+)ة>Sjexh&z";6n4,.ADS{<2qۧ &t˧ʂ,MحÁ i#Ĉ?pI?ۼNHD@9~CSB}*1Ɍή_%]gY}kՇ0Y*ţ&Qj(!)̉M H)CIG+TE4n Rn 0 txDwNd~W× 8EkwŦme/vP9+5v2yvշGx)OI3/wP,XL*449hfOi_̎,5ԈӉI/MH0M.xUkK(~J=ƤR:.~s1=9T66~w:hD zN4lqZ>2V0aI %v2ђݮ`쓠}%!U^Lm)'5հ;r%qؙ8R*7 V] d:s&N[Nɓ>8) &~~+Zs>_22B㛑@;mfǯBT;lݑb̬ 'M8uNݵr/8jl*J_J3i@ѲQ~^VfljULk,ꃳ\(زl9҉+vUݖw,tS}-CNx28~rҜV5 P4YsndEa/Ux=x mA ag6]:_'L˅,ixy2^oXǾ>?+ow&hL@w*!Fޔm"}/|jmOӄ죇@ah o'|kt{}!˭ ~o.GAɆTKi.0Rto6|g5Rm4_ |#ߙtv){}|n56g3䵓, ٥(4%7WXIYd$Эw5z/V=hqi."]HhlmiCh]i9<3Sk%~-?%EiK=ue}yKR?M$ƞΠojO46†=O ]HŸValsN SǶAJqJJ% rڠ\{ӥ>\i)f?ySm;ťU0c*M%XtY&~e8㔑lfrOPžO]\9V6|z;3v2^߫.+t,}\晥4ȌnZWZ=_#"r^#/xJ}Le(ᴚgvע]5wwB 0g.k]LU;WT[~}M /d!X46&Q#YU^9cM kח*VGap[]$Ҹs$8IrqAnhF0/e7ȸGiSjqVFPOw2O.zNJ\q[;Q,$жqՂ2f^[G`1S^?̔b&m`䁕PĶULy ՄBĎt@*y?LQ4 !k M4Q*SCNZW\2Bn"MmBǥWx=uU,8<<03':ݓO APW?vpY+wi_#`9=讴G:aDS*v>4:$J}(iCkbg-iq+0]ca\&GꓻLc(2]AÜ'$x]kWlNݶj^q#7L8w St"Yd Þ`dž=ݯgO_dCB͜dpHgZnr7ؓeh;yn&3{}:9Q mGrmBta׿xjמI,#_ba}!a@RifyYNct4 νEUBGjQMOyptBcù B}:}, JYO'yd!x}!hiܫ+$j("iaE֞KMRZѰz" ]aݾ۲L?_oe^/9AGqh1lp/v i0 h~6;MA^\k,+o#p7 ؛G2<(u@՘܋ѺΑkI M/9Ϻ\K+BJɣEti߱#@甿5r(lD&K;/k+ |Ⱥ7ExِY :LږP{Kla}B@V ILXtEy-. 2 OzYBmuIRtɇHkS :m0UEQdčE7̝}KW.SKG,Z=W6U:<䧭\%Iλf "if;yN_|L*坔C֞4Y6,=%qrk'VEQ >#ُ@b7WMkQO9_k6͑NU6^Aa(l^MGl\ Dzbzf6ho9 %5W&p<8Λc*I=g9r-#5^N@XvT<=gFfRJ:BBZeZʖqMv\Ѥװ̎I~?}Էp6kT>n1$> R?z[ &R⭥Dqȝ cZ-?u)|$ƤǴH[^%+I/erz oK6c_/mk!G/R!%iY1} 5G"VeZ8' kyfʁ,ֺȚT:^^/ =D] :),q?nB6 F[pd$Q IF6t8[qi[j2Kݵz)jGlT0lOk6x3|kdO$V!?v%2qGHD Va`T׆U#=)jsYp):|m8@Sx0@]P^pï(:&|׵o;\>{pB.εߜx T)HZ^~Yieŝêp}MNi׬<[G|^_ֆz շ.C2ġ2E#俬0R$fk",i=!zqPbEqlFZկXB4hJu}2Ăƞ:)R\e,w`q_ێyƟP-XFs}(<0 ҌȘ󢾧0F b M)}QOYe*c]ўЖ7)qFNiԎ&_ 9t7nBA͔]hVx/Ap^JE9sqUfbcچGfX9)x &=!5b [Yb!Mvt0w\[x>%sMw08CgQ+d*ZϽv-1ޚF F]^,G0]Ipo ѓJ]i2԰pCVU)|sn(REiaN$KG'գrW"!_4䧱@H繁nF%Ov|ub|\$#m728Q\;J@#3:ڠ3zj"9jle;as=A=KCw07s//wA{R; %2-3o<3 qvሌڸZjŭ+ˠ 7HhEi 1l"lН;rH4˛CN"5BE:! !Χ!B2vJ;:Ԟ74נW4P $H-rBvnW83K e9;֢/օM υ9zCVe0z6Rhx^e>c"ZӓMh<;%'YPP*YӸR{y,V6:ƺp ˲6< Y%n A"yF3o|rgz̑粬 "ylv~ Z+)6PUg"mQĠt&͐#„C y.XdAtat,~iBoJws4#  ͚e !6F[S5R;:<3Ki:8^[|,]< [%4~rnMΐhcVA|,cT+ns̭CneVjg6袎r{}J@XspP?ͣW"UdYEl-̡MճsPY/"T"" @O1eP hɗnYx1An*3b\P&m3N{i%q܉* tŔfĜ<1g[8+LXo)~?z]@#2 kcݶ&Ju2GUr{49*mR1.(`rx䯡ʜb:E=~)9mD#w%BfctfdADBD%]2~o0J{sPÎctPXa3M$CUbL瞧EI1dXߔuJ&aܺbK_hq1[!zSuho_6Mz&TI֓Ut6fjBYkCW*6Y~~M֙C M2bUd ̦ vAdu]ո]qz~M-A 2,߆moO]⥽a/Ѐn}2z]k7-bR}YZϒIsؼjǹg8r^˚9IXNKuϩ&ZK Ec;kQZêk36s:hV,D"-cȻ[\VܷdBvz]wBp1ꇭWʖ5:Ϩ}\Iȯ˅߄$ iu=ۚu:3۟3:l7ԗ7jhX3>mR7t7:7v"B]fa<6俻 odAӛ㵾aNܼ>Ɍ 8E!?t6RC13n{@Vzn;)^CxsDVɬ4Q8cM0.kk0wK T۾nnB hĘ2ً_$mޥ7RhV[ʦ}4J̸ީba fBÚCo5ZH\m˖{𱜒[Ýctx%6S![)+1k[)9kHfrC Vtߚg`KU/R24OٯRZOvD5Tl°,X1i5cהH),ur5.0ʨ;`CNxq,X56}|1&3zGxCQɲ{aqTf$2HUB}蹬ȋkIN|e,*\ŢmoJJr?5=fe'UDclDSôN_kZWL!Ogoyd-wM.K3ڷ|_|*+˛Zhla5Z 4l|3_4q,gYv N_--; 6{N&1Z|ӣH_\ss&jazPR\p@ vX cs{;-¯Bip#M'j);| =^"FAs$ o2IpXdP<+eƷ|~Go@aIG6?dj_w K֣jŔU.yLT454Պy?8 E ΦG黎^z;PqAO=92z/CMeJ T}^XoGP| .Iz-AZ4E_kϟh|A\ '39%4twgdAXeky܏P #lHmewfeA ^{\Atj/QWmRr*v2=+ޔgSgrNCovS| /w}#sqhSV[}Hj7F4|vm3]q󄿥Av;uǑ>ӣh3Gg֊B1a5V]+4y|Fk7tY<+mrf-83fjNm5^yBYl%ճM{62Le+ugP\m{#i^,S&4fAkWZ4_.GofИ9 H Liq?uGAUR#'!+!HmSטT{^(%#d]/ɾ 3u;  Щ⏞.6؞J Wڬ%\3y`uUz}hN9r#Q쯥lY\&Q"73g0 %8UMovwV;A Ox>UPyb(|rhYʼ9;6ͦ\×LE)د%%w=*Gn0&דF7Gȋ* ȼa>UN z >Wh %qd=$a-LN7'8 BL%RGAI'휸Hj0"EĈK6 [\(zal"8޸ǥPN^0WʣOqQE2jN`8\8c>4nNlu//jm]@ 0̓^p|6FkUl}]=i/3s0kP0"fSOӏ<%]!ɟLInvVr|qkx]7M\ioI;3~W%[h~ک67܉Gem34;lWLr,+lx՜نV/2w.T;zLdzK3 A]$0sGFך,*T:c[n*f؛QzLƦD )h25ܒL[[ŢO=ݑɺ'ZG" $E~L MxTE/W &q ?1W+'(Q=;|Qѡqj:l%+S(yAΙehN3')>IA{DƟ4>YG&ҋj ^vŕ4 2oلI) :ҖyZ{^场=.7h_c~UCEU:<.FBcĝQBӿ\ XLmx| cno,L*EW0FsA&KPU|&{B|U?$ME**3g [ !pB-^JN2˖ƨקj税c@Q%&?JAx~Pz^)Ma.#"Їq*HIT/q2_;9:HP3@HZ'& P`yu6k-Nc/uBnf[{Cz>Xޟ,pS2F+{ʧQ;5dґR4ngiS῰wSYɼtaP8?ENi>>% fU״%8ST5kНS%j@ L32V#aC{%F+vF[;۫VHǣDOv!<зhdyҷ^ql!mT[nzm#}˰'鏂3Oҟ0sLnFS >fcSmAfsN4>KD_Ah3uB(r0%@˸Cyɕ_ސ.>FT'kSsQʃmʴ+0tSQV}y7CaǼMYLx5in/4Ӕ|q9\*С`\f<*=zNl[G/F/ڍ+//Yi!Ɏ^^dgיLݵZbyўQX|N۾A/v6j [-h6|(hG^N)Ui˾\?|vZFusޤ/6м87a TaӯܠnN^L\@apMOez}pT/颧 WI0/ fNMA\cN}fϨaT 60f3ߙ0LĽ WEu4vE/@aUʍyw܁̈V&qPFK5Y{>p7$ʖʷ܋^KL4D)>Egۛ0y9p6RJm4%jhzi|?EմT$W2rWIb_SsLh^:k~lA:g*̎Z1@[3ɣ'LSF'Pc$0%E>ls78Mܐ?Bܬq`E<ޟ䇞Cf`-<"P9|:0%4t"IxblX@EV1ea,ɬJVw$ z*+À2ܾ:`]1_I81?C `e46 sWH em¼9X<:ò] B/#~]-겘#77 Ytu-/>΋GIDZ:8mӲjS]^y")HZC0 Ώ_J]~l[AmȂ48x4K(>F3m1́ **F`~9M}u /wZ;᲌[E962E!q]/F>e.3%nA9 ZRn׎*]+ okR6GMhX=ד[`~ՓW:vujuvYDMh\Qy΢jxI>~Gp䲢zśCpe 5[cq:ָU:+5v G ;0 G,t)#4UVЀD :ʒo2yh[S\͊Q1ԼH ;8Jm ?Uk"2pAu rf3MDgf@U{y'myC8e%<3yYnډw"us0-ʼp/MCJ\fdcaÇ^/7|E3Hr.ă@Udq.㠖FURQZ{nM5Qݏao"1Bb:Ji8ͅ_4]g, _R~^[BudS$(vԾ%w)%O]G&tjĕt_?;>N5; xٟ#M2%FMK~lŚ|Rrz&cާUڋ~wc@*+9夘3ɞFa)( |17aNYMgٔЍJ 1`W'M*fx)r_ࠨSXZx)9 Hu L6peL6-{b17JɦUEòrQӭ*$hRRn>>WY KP +B:T<ĖQEeMIx fUc*c=RO#+hz#ۓuK)ђN8>jA/<no1ԝ6$>@Fy,4K>clY IB?s1$d޺oorÍvpM56d7ck% Xu);}P<2nH9d ^f>ͯh 2+IL䶶%€^b#nIwfP˖a!wQ̞`/F -{W(7ٖ3U*.38=NU-131Igd+^4 b0~o]ɱ7_ ʜEf^\,R cL_G)3=wز9<Ҭh Oq)eSX=aX_8͋) P gD]5M KVwv%ZoMyμ)W4+,PR1>CF90yDtx-۲YH0N{ʞEC oLS!iѡ t͟&~6r |ev5_G]:ߠ7w[ ?cVl ȸ׻3SK=PEoNSGPyFw[a P^Fn*l>s~' 9σB) `G$# zx%KHɁ`rdEnCM&nbftoj 7$ 3=n&ht69 hZ=Q ̚f*s v `^yk]]/ 3%zYùG%V/jI,L[Uݮ&/ k5~2\ǟ1_XZ##~%Q4sxYs"[\Vi@g. Kayњ0OqkF9Uh W,|>O࡬ܩXIFG܁N ?:avBU4LI!*eױ!>o6im$E63Tvvh:f`"O抍אM';) ,M}}RgLط|Bwu]%[ޛCKEф{x9pccޭ0ۿݔAepXfά>@vԪ)e7#82}Ҳ\Jꆊ2ܭ3$ ł#涿_Iwv50Ǜ͓.~ܭ333ϸj{Qps9.ql;#(}r}j$aYnӋ|S2yo Og33>>v)Μ@hG&i^ YeDi:x@F9@o~ɛi79;Jw)rhH8/%5aG{oe!z%Dg5RGOhd#5Y՚x4we8l8t@p1OIsbѴ2"|("C :0a/"k%2}^nhc^ dˊz*GwY!2ۡhܩxH̕gI,h^e'ۧK6hɼ  Ƥo9S\|}ASTjܱ+rcߙ {Dl+s_’6Pz@@0>.-.{.k6;QUn~:ȏ~M2v'$xL`!I2W- S(/2Bts o>3~"@k^o8?ފ$>{כFOrgZu$ V2­Bhd8s:Fb2٥}*bFZoRh 5Iy&+B%<:^6bZ= a3 ]ع{t&L (;efvٗ.w}^(Z/3zM҉BSI^&q lA+IlڟSZ`1~;(V#4' s-m>6G:2?"iO ٿy&ë,L7-/v9&M,h n 4ϞI+ `* b^T`e99'^J_H⎖ }#Ic)0q?|U AT1+`E׎'Z=ǕcA1AsV]C9*uLݦ#,k͡< E P,lN }*ۋ Lf7ջAnRsK~TjH΢% E{#C͓<(qz4xLIS% ųcq8W; `R<TM4Yq~-b75uĎN:z*- jX79(Зr:Ո<6ۀѤVk\T1nS(Ll< x;wFtS5/QW:M3KYRJ_!qα_jYs4)L~|>/˶p;RJB5HBKiw,OQxŦ_TKZ\%15ޜ]u-F9zݼd#GQ%^{#״*~fq< -|kN`&YԦԉhse0wvv<'22+Q'{6k_7EsVK|IPt6kߋO%\' .)52soEmK:g\~ w>ءQWIJR6srt t5Vv>Q0yȣ=ڦ`K;Dzŗh586u͆#(Z_0'q-ϝUn}|~qp!o;`ZsH!ϫ"P(+'d]A/'x/&PF1-әo*ٮo.Kr.# r'Q=1s?,ri4V&Sf]]A3a龠 #S3|gl~qEґɖJ".'FF |g⮷G,dQ@;|eFM~2[e=|87X`1JzQW!-dEql\f{cdw^yi'0/Lϡm#r<EfmۏY }h|2Q槺NhK`a<%#spb"T}XлLmddڽ7hYO)!n:~ g'';i(I lnsrӖzpfpRLQgaQ]w.PvK Ga8|rTyz V$%[ |<~<*Ŝ^4uU*9itYdnֻ$qtn* eI,as)9#2򜼕fRiʽZy[|iO[C{-I>G>Q˓먗f-E5sĭoyɒ Bh=^RNL6 fMm|rѬZzŒ\lx<*L ("pַM+l $;< m6+t&Z\f)tuyU}_.!%?u$q[Nj0aaz>MJOl8󔖧lIa&2I-|HgC9KQ7R/)OdP0 !6^9twtz35O.D;i1-fvJk\-2LɰFӆ˅7qd+JɦH3}VpoExdV4eU|>c XK>{tV"yqS:ULg(\geЂ%4 <s N0zsF˲R@j^-){1ˇ>S7 ,vʾN)R^hC2݅nq|yKiMj2yjչcPA,e:?%yK eL:Ϧ [6]͙|5ך 6f,L 󌫳4>V(FV[~%Qiu86S"-y渝-`S^s'ܓIJĒzZa܋zSQ<I^s˼d]yk}t)4O^qs&UPiN_y,ȬU!>ɨЎ =inCL"7kQ x.g9,(ǰݚ2#ڕŅ/jz/qJo?1WYel c_g+s=ojk7(̥2mv}0~l"r1&nf!(5I94etݻ3ZAtYbcg=g4ә mW4*_܇{q4i٬}6`7 @ s<7·>X&l%(lsncm(x̲*1|:SP^([": SϳFwŎmL7G/k W!LT~2M-7ZA'͒}C=f},ax$zc(1v2QʾKe4B #͜@$uʂAT鿱H @J4][7lW nU9JjzT\ ͂ys% =?ݝP uϩ3E"?}MavdDzBtn @+~gv l#SԥJ~sbf+[v٨*`|y<6-FKQuAɄNJ`J+f"NxlaK0dES2`L%s[4U2ҕR/ Cl2֤e:.}u(6ޫh z*ird6肭'Z2no W/8LPh9|yQR=P9<{f$/#ndqx` b׏> aeo^;9*aOT; 8^3kaL({M~ӏ[7vΣ5]J47vS괺voJ*7P(0L*3sG-JӦKnP_C 5=o~TKvh|M/C¦ߟ'K.&;bU8]RXQRn.u@Kt90˔M*9vFEfp V UWY5X0\(Z޽joo,倴Ռ _8eOqZ4{Y4FM sPdAvuN5(L>7ٔa~&n~Ї$6) J!b#X+U(j\>;аˇ&plǣO(Li(_1dצ\)~_-zsn0izQ{N?SP4mӔ`<1L v>׶jMksPxd>] yNB9!Vת[gQ<`y\6g6&Q$6`q؃IZJ% Ecb t bm&oɒ1efЬM*ɡH+S-]Y  iE)]x "tMo=?B\Y ;\x*[-7X%}r 촵TG 5\,mqkmCčbv4*RX.*iB;d8ҧgFTJKjcyOdH\\`ztt! ;aak)R/IX QVd$^~{+B%)ezvoDeFѰOy \YF0q!>Iý%~Ê)K3*{ARpuj x c ~Su轪 ڣ0K?6є(mGP+kc~Ȫ+ ~&no^6&<4"&K{dYfYA"A")CD9:!1~y,Nt>Jhoz$a= E݆ O۷Zj(0]e.c[P8߼y mqA!F^--yB&>[85Mg#6w_(8K>i=@'9:y HG/ mNN.dlһ\v5Y>R0DƵ=þ^3 @Mj gr%A.M`@rb,hAԭfw`@uys 1QM(#Vx š] ,h/3H>ZѼW|h`)ɩ d A n4h~}?}j/ nrڡKIGlujʌLm|GEdxtƍaJ ~xe.^: kSb}Ge,ž(rztmF4I&(?C@yM}iU_ c's7Ŝc ZxqЏirDS82d7ۜƯQVGJ才 wNg}_Nљk~#=b5l ٢Aqȇog[^}OoD:̼.w{93jy3|/|G)t) k\] ^t涬:v $S|6a<`_ǰ F:xJ:iMxEu_MBob=Cn.kӗz\('vsΦ\Oh8 ɻ@['B[LaBw6ҚØL?yGQ`BVn%E2ƭGW#/lܖOcnZ)ovyn*)BʳϝciW7S⠀[M3u|0~ 3NrCSBT}O+ A(fGJ݇]{ sUVfR=BSuQk2+x7%+62UAyG\B>ܖ*3|-3VcEeƓ"L JD079ĸݝF^Ƈf7yυ h"o鴽̄ykn;pnY$f{ }Y杅5IB _e3Bc̑`fs+7acF[2㉑GV%:V?]5-=a -ؚ +3WحANJ Z U3&_1K:?\N`>Ui*̙yޏ  NɦM8W)EVEU{̽-+?(+lQ2dscaɬ)t2kqۦev 8,El=MI]7B= M*s&f&{ӡn`dkWɼLLAJc9L1 BMv7zj9ɷ ZT9\RSjBl{iA0` ajb-KNM[V{4E f^C5(zQz9=AKm ̗x=&Is =S.Aߌ;{*Qzf`X لM b>Ë+nzXRԴ6%q1GhTz2vI/Oϵb ^\ٝwC)94O9&rl2mdE]*gB,ex\wgJZ љ},`3?-DI<=PXZ|(kZ (hI/8Ag.Q̓kf4K[[p⬢4|l'ZI}6sQCe=!)f(.=g_qC3͏Dr;s$ JX1G:AjO]Y-?YgJ4V/PU!#QEj?LIm㹪x@2u_^aj'H>QE}$eJG֫U?c""oLV/ Euid/(2q8ɠGVnoNQL;)J[wA[^\%nw4 DToi)w<փfQ\wvL{9I=VY0I]:YOn7_b=G!n9KTᱷRA +2 Qvi ꂛ}f&[ tOҗcZtI汍DֆU{!&r$Gg葼S""L7ҧiP”uT]^Ȇ[3ڡQXwzhz3 jj 3 c4䱬۟?6Ѡ5EEw(j@x̿ܣv;BxS܄g\+t)]s ̢`#~u?4|֘IyƝүO2l2o Z$52[bSLCa7m̂/5W!'*asPyC>Q/#D5#J(>\MCaEyC7oֽMo#2zk#UwNi>-?)|Ύ1ʔ ]%9L~Jw Ћ!6<.nty/t=Vw/ l?hsjsShwݠ7WvjqTY+$-OCTіUMd [eVƿdO[xe2* j=/otAܷm#/@Tm1ԥ&*;wv8޴+xPuM/eu'I%U77h[mbsj~mGָ5NU8Ce%iBtlgO3nd@~{QʀFX[#Tb6# f%#Hwr*J<3R ը+;B@.EbfÀ ,x|(hvP&?6{Ž:`\i8z ^zN.ȥ|mj_K_?xuh;[+76وKl?ݙwe8rJˠ)CL;\d S_(J$EaXgZ4# )My{@yGLo#䗷ޟP@ӯy/ʊM 7BQeƵ{gg3w~*<(*1SSQƉd^~aWHJޖ>f*5 h"֤_pqd~kT`̣]a>=xա`z;>E=/@I./D_֎yoZ0AW@Zf%z}%q٪w,an 5Ј^jsmټnj d>*$_,X28lxE8ҙz#(r)=^JBW9!YѱV_yk+ϑUgeg ߙ@$_$VϠCOn͇@/.Iy8ΖP- lYڱA 'wSA)OOb2;|1A3bQhSeCau'j So-`c| W%}t:3×gC2Xn %/n\ՄKJzTz*~ vnoʵ#5G 1 XsFBuC~z {w S4565rW#mOLG4AUsjt VD> GY\JJ S۫/O`0 g<^w&_*nzY+'fѭ_TpN[Opk46+!J:U͂` b"@&wP/.OT 4PﮚoF/*n nYϰq rv)}w%*;5t7cjۉ]:9aܷ=6҉EAH5Ut/p)jjYEr͡[x}_EQj͏ѡd@(L\gƭU-K[p* I&>jn^A|FsXrqt~\k)ϑ74Ϗa[\xMXO<.?K5iPr(!]Xi֝ʅ>E,!9h6IbЂ^B/BP`kH#"cWwvZZ:VHvR U%ӸFx<D+tr&Eg֏]f<U&edv@?-*][]S0*rLE7`nU&ȷRf$2,B)oM6nɀ˜63JN4M;ro.ta᭲a>KET1ջޙeJ^f) <縺^Ng%\e`8:`E1weI۸rI%qЇ6gH:4Quv:Y ̄Or..Q#7Z}sbbWEPȘGӲ\{y84^h>[!)XHK/,xTE*6 'GPLF5=*f gl!4=a Bd@qƪe6ЋqL73[s.k݃r!L7Noy`/3`[V87xcSTYyqO^ئeZ77}`,PN]ORE'XlE|.yta:?#\0d*[~]3{lKȯ8MC~LhX`$ƕ#b z-CvNKLBt%4|bk4hcך*T\ho֫lt@0L䬱UYDOhI@VʶgMrA7~433!~קpn߱.) oTD8e|Zg@7B_$T[좕MMzh'w͒jt;NPr I3 ۥTfQ\,s:O;r_r%pdb|  WAGoۣ)1fr{hVȀ9_ }[-`0Rbj\T=n7f "C2T#]LLR)6սz\G}nFZV\Tt~Pxݼy79wwvɑ 6LO{Hƌ]CAoo%oиcfYT{' ̓ӱP;aXez &@I:KDr4簝ˬe#yLSP{mY?OHP RhVi^&5 Z=/Bdt#yu2&)[_駁·iOJLBs++]UDɋ_ Qwz+3a \]jnU?Mgn G/oZџLxCzJUV`g=8'iCa?Ӹ8UD3 :s+<9"4;I U6ŋސ|+35Uղj 2E曤@L˴lX$7nS6L(2'Ê eg6kKLl6Hoȕ}Ӟ,o8v ߆j6ٝW714LUӵHb7iOmw'n6' نT3A\ᕐMl5JҐ\tц#(8@,F/߅h5o&6YkڮʵLCR}.5E!ђёf?'"qvJsujLՖg\n ʘ[J65 {7#({ae:WISܜy[gzp, au[OCJ-cTF<(»2rjƳ]wjVe぀b!E#܄֩k+ۖ+3v{GL9Fa;.AaRE[t7C1mÜOD˔S&ȋZ;oSAm°F_3 x_"ާe \ 6UfecC酔;)fK~=i EJtz?ߝ`<3:rhܟ  !9+j̽􍌘V2Y׌B́ =4W>ڝ9oP}T΃O%rPO 9&@M=Ne MDˈζ܁ƪgv4E *RzWٵZ !w]7_5ʊ*.σ,* m1G9y.K5O[޼WbMbSʌIuɛj+PN/*OW.'0lr~y6gXx!4 Q<6̀SB0wo!evtYEɞ}g @B)?O2<Vht}Da_[F峨_4:2z'azkGy$;񰗝|tv/ґS{ v®a/duϭn;E\ۧCEd:w 0 q oո3-d]+eUmBY1WdHAPi:"2ݝй#_;w' (W]XH#JS9Wkido>J\s^1Ŕ MM-2Kque%oNHA#r쌙M J]v5JvYFаnbjY=Bxˍ'[CHNjS  cPO}^:צN)i׬_tW~ӆjѠhuQDڴtщ*p zh'-J<ԝfi2\f fsNa\@SfT]n$̣\/:2ʹ1<☬7/Ja6`xPTpm9%r %58h秊Ik U#7ߪ:͚ӁxT {][Zf;*Vܕ|ߠ^ʡP6昙o ن5 jF$c~V \^& :*+D*dؒz(Ô5c]o |WӰ8C.Ūl|ƢSMHE 5 MsDޱ÷U[/ϊC cZt%Gi}; 2M){Lj_ºFT&ݶ_!pk%فW7ս:ϖdz 7YNuZ"cǢ3aD6MaƖ^?q(UEXDTuqz*y]2ќaW[~'IgPY=g;xb=47J hL +358mLEZۨgJ[~‘o[5k{niPM@aX`g+s{3Փ9$]ET}t_. ѧ*\ u2HԁVA7-ywF d'w)ޑbk]AzMW#jܾ[oF0 TVVukL pT.Aķ,ՐM=]" &XCԠnxL6wom5r)֬G'σa쁾p@VQҪιf+ !8 pybg.:a)f:Vo7S6b䨉Y F$,ui AvUlþwq)_'taU;,Ԭl/uXٿ,L9Q‹yB9?B sHz_2aNV)Yj~ ez2ꓡ鍿ŹD&ouU}WrQma32XVlظO:X6쎷`ʏ;藺kY!s)2[jK;;i‘%j:nkYZedf.Ey2 fm[ t/9q“9ZJ0]* Z.r^N1P>sSJ VW{*b"DmRFA:S1RW=lے92stkMl ?M;wH; v&t%ْ]t.nߜnw=hw}f|8Tbپj\ݾrmT,Up1qc+`}X ۽7] ])HY$9LCj `CCm]D@Kk:4 /)T͉{0{naC?M%ݷ:fCKՅS|T> P)/utj=TӮ'ܙw& .Fb-8،l(=N'Eׇ<kTFuvTKS*uG< e2YsQg G= *FDŽ^*}6?)̩/yDǼp ?#zje);yJE i銇xB0l!2fauf#nڔĝxɉ PI!MNcy|g+äݔGlsF/Xiq Ezź~#EwjhctzB:zePn)ݺUSm+WTS= 11+ۡnKarz+;3@:^?5LlW<=mt=4s{9eۛoг+ݜ ѳ䠙HGd,}o~o>Nڨߜ?i5ih'LeDI !a>ŘX):ȸJgŞ6GoN<ML<b`Q@uZeN=ed3 \"`R}JFo ߠ)= @,2HwMgzFh(D~n7O/BWܘ' 0 qԼ<(h) 3ZV fp`1L;jz=  m_4 ,ɻ7smW%_ <3. 2.Er @MQ):gzl,xt}U5FORd$H4~dp9Vk7/g <- F .#K^Fiph@U>2H2oDN͇Y+ =RGRO2P&&԰ד_+q֗ /J7#U^Ezsd㹅AMׇQVT85C]Pbauk5"DFzHMx<zm+窩^6Ջ{> WGS ?_Ggs(v^0Kl˙ aV eY"XbAKS^ 1kifp)2,UçIg߭шz"ЏlY&ߖqRk]e"ᩬNHq׃eF O㯡P }J"|_A^WŇDApR5='i^aivey4>||= r3I)XAvW8}w4EbjNvlxTpo 4sZ+"v\'r WF0[~t+K(s)ߠǓc.eZ?X+ǁP{u{~6"^iEDMVr @O|@GY)fq2R#7:4F]U *oLͅF)F-3*/*/$bDV/fp2 Xk2ae1p4$ɩ+M'f%B^Hl.|zQtKLf"JP2KUCSVs\N(=rXObE}S|Ejy4Kó/t-$fؔwtAzQ@oPЬeﰪ|!q&Ͳf*CKhGI~GW hL!Md/eݜG.7PD<ݼ5

ٗ4tZҀUi2%XA (ҥ$+,|D`nZ&yeY b>JLF.\k|àЙ-@5tc_xu6I #AQ͊\E aܠ^]a^s˳Leۆ<ֶ + OҠ{g$5opO-ϚE=p3!?z٬tqLgQթLA ņjT4z9 tQْ?CIpݪe~<v_~lČ>V5ltv:M۵w(xВPMK%cM'^w 76嗛x*mtrjc6C^؞I):lV-e^ `^}CS__$ 3kc#Nfӯ|LxBWfT9@:iþ)kCw(PAR9pX&hnaþo; 27@,@}#*ZfI55)rmeVWEHem܇epe ?Mq.l#[rhk?HfՓz޲~17ė᫽ZٚxfMyW ޠieZM*lIa*ws:z0eqHy}{F-oU 4O\ERϜLQRw1mzwڧ ('nv.R>~vR4dSdI_37' +Z懻{N)ButQJ mbWܠ$qaN75y4@5oe>܅Ya{&bxw"eZT9w.jKՖBՖ}RK*z\|M,X[J[M(e붱Q`@O rީ+b5o>qkǍZyom$yf*x%D1d^sY7\Ul}~sOLɃr]wb>LS+\?l-_LhP2?kuqqKBLK{2'bKGح9Xotm=姆eU(7Z tq29jKKx]x9uuY{ '5%qu8Yk,1SK>R@ģ&Ac+.m)iM2e?RZWxjE};CqR֖bzc$Egĸ)6QԢf-ڥ ;FnxPrcyNZL. j㦀)5 ]b/hb7s,as38DZ1^Cg)[7s&:M.NAo( s! UOWF[0o=[p ' [=ljK& AutK~48J}h䦃߁ZF--eE71^n%N-'rFCQ{ GG.@# }BVL x.s٩soΚM"D\͵bLf10d< nQV6XKY4gTAKՐ ï5$˪gq2IR#2]ZNl q:,S j;k'> ln֫AOw/:mG6Fn%[Nxē`,Mϻ7I_q ڝbRD[?'Wm S"99&!YP_|jWo+bSZ~'EdGym0_)Upͽjoh Vsa%UP2) m.*& 2& `D69b[\M04olUI*RijD3[_!-Ю cB_2zyL9ǒ->UjgbrQr:4sQ9/OR-(W£aBLo95j^6;^ zN5Bqg )|C[N|ݦnH^3wJ( #9#LJVn|8@0Xߋ ?Þ2[TgEsr\tZP~\ceXioCE?H W$>TG C ElNJiϵTJhmʺy0 y { w,å'=L7yUj&'1a0 ,M|39k,-VN3>TR tAl.WӜ><"y]D1vV @>҉ng8ɧi%ϝ:ikѥS.u~}3u ' -}cZfE9q$>] ?Lt/j7 C}>P>]^v[HF /y}=xblyj/jq00[yG_a>j阘1 !꧴Cw6<͈zvO'xjrADГIw]~8'C4~ 0&#_ T$C̰=0(2iVy&uyVKBTe6\^ˑ_n={6W.PN8S~;`31Cqz 3R-ǹIS.s NҳڒsW%E+#Z';mɮ"oo5-? RE cېqŠSvP- 7Aaw$x A$봮4 r)"q6eS|9%aR&嗻h0Imgw.!-ͲM3E$}"o9nHzCDfH@~T}T1R`cYZEWHJL[2Zt}zarn5wb[Pv:ŔVpË jUFGORNq vD fZus+&&:on2MȋfX1 AWR֒= 2մA)' }+1U)n"2Mft"tS^m_~@ڛ)I?T' Zq6T8@o[w',~vigIoUF7mi>,w7ooNF7Ї]]o&9jZr+] ukcH.3~[0a*퓪\ V &|QvQm4J GkTo?ئ>\-~Di:ꚏ=^*VFH6  MBb`2ahr w4YRV'D@[. 3q 5.24em7 UjZ9nҩ.0Ebٵr5ć0+?(.|wvr mˬs%oPd#B rb3ﬖԗsTr*0WQA[yQ pN&o9ts9 yq##GNq9J fKS[0UZU K?D$JZNUnPɘ$sZ!˚qشa@Hp~Q mX||{"NW[VjM˻_j2N**}⅏ک=3e|$l?I~5 ȸ71d|2aևu[0F #wO_x~7h]/4x97lPl󆩚Wp'O('6ͯX+ TVj$ .W#!g#r49okH3-BD6:#4OE5Ta㧀eKySE6ǥӀ\e0Jg2j`qD~b 6Fp\((u0?\]qH"=xuO S&nˤ[ю4q)[2j?W{AlePCRwRE,8-[Qw6 e)v|Vj ;b2PJumc˅2)nthcb:jbk֎ʘC>2J Fɗ00arL'ʹZy=)! wBymVdVT7| h'"adX2|ZhT)T|}mC*(> \sQ 2#*47Z(dOġn#7SU=^NP*&qqYMdދdm/ "/ Im+?q洟RXz/<s ,+[QSy/yn{bnWe6|-Qh 2i-\#I/o𽸓7ȸ/h'(TGzɏK"≠6ZZH>Yw G5a5~ YriL' )R7]ɽFFH5{=\_]Kp K"#o.f;_s扪&ʽ4ahOC R&dZKQbd2Ô^}r/8. ܖ/:s䘆ԞʥϽl(f.3ЂBɖDq| ƌ򐛱Uǔ/Ľe eQ^>u6O{ed@pXaa|/O2Ug EFr,m7PW՘)H?| ZVQھD$匎~hVƠ)@ÉeOuomЌ.f7{y(Р!)5Y,tZ_W*K7XmI`uS4zһ)SMaaV((4:*M6W|JDunȒhI3TPK(igGL$j6`y7 =Bޓ% ǿiEҊ! f?r8<nQ㯰}(ِ5g/M7*}3l5o-lV7+-YZ&H`z^ O *m,}:)[)cNu5(nPdw7b_]_1w먃ݼN`Ky]Jmun f*Ki& EE7 R9`&ihT }~\U+f#Gc+ӶS'NfkZ3ƈ3j7,WwK旧c{12=Y&uU&[ b=m'.FoUR?/%〴df)@ t>} 3 ́%h`o^*\j޽!8j ٛGwDWXd]+hL5"!BԼm"Q'R;3 2?WZn"!W:x;;ީLT!?yÜ~l0<[/iǯtVczT;f.k,kvS] <թ|]o<* ;TV]'*/HQ;} 7haR[`dhW;ʇ2/Rw@d}u6G2`n*+]4lI\BLoXwWkx-gP[u݌8漤qK򺡯r<~X6Prgf TU)j^y`\|#O Ak]SԤڻ[~4u‰S{lK5M{c*k&)=;~(a>601oh/t({7%AC#$GP:}ƽiP^ "Ajf&%y۪e :0nT7Q.AR&5O3L ٸSB9rRN'7.y7O$WH mj4lcII? sC9ۼա]:N@Oe1JA1¨ kTԼΎ©[EP8K=-󑸅CJ:n ,K۸N/d KU1͋ V{!4wFʯ!7ݮ0~֢|6St$>ª673t0Wm"!Ceާf%)8QRͶd8. r"}JC=*qⰫ,}Tsm9!~M$uBi;}LJˈ^7l2B >C P\s\*C!kcް(: 2vD;~P eFfV˯_^P89^'98j,@'n+K 8shBnV^"-n#IJ<֯^Ï;kR/gb<Hݲ'W m(S'<昣sv6t IOm8My[뾃wzC݊9%8<%i&ֻS.\+IIaN~nvPnsܼ`o?+BGW,)"=ki|,[ +{Tb}:Pڮq H-+췍lTy&,cq.'3nxҰ`iq_@!v*EP+' Bd@j)dVQUIǩr4|=[xHqY|L?Ht p- tZa8?M|;ưVY,q :k =o6<` +_ۘaL6>* k=Eiո<+' R$h|}v4Q\]_͂(~+D8XIMP{qy⥌d=h1-U+Ɏ23AU;e\fD['X e7Ȱ" ^5Jkzj6h*wVQym{@&JS߱2lNI\?8b.4n Zfbg$$៞Juޔivl,W(,nz~"鷧b 7P<,\q4dS3 OWC |]yySEvn9;jͷj:(!DP0LV ;O2{?XN ȫ3]n=Mk;"@ >b J|(0JޛR-Űr*C*?`6K=R-c))8E5 F2S.lmEb*>b&bMo׶,N2\whinB莘k6 vIY浸 LQA6gۨ͠-*z‰SSLj"nTbX\i>6I=wfFSǤ}l@5jWx,\0"ry|hν0} ˢCk̯ϓ/ `ob=d#v_/FOzxv-kdQGQ䋷o ~\%[яdgk":(SL4߉T<Þi{Qݴ$`bKz~l0,SL[tFFAF0n +&k]b {5~QԻ"XA3A"f@ԯttPuʃm.PK{,[ON;Uj* W珂 $0q촶/GAE7j85qEчfL^}",Bҵ&?vƔ+ C`n0 ZB,OJ>E&JGIc&Aj&A%dLUT+vf\ BM5P1i Ȱ >jer+lY#y9CKQ V'R̊-2Ho ]洛Ϊݬǀj*l4W=2uPcXpL[i(ۤS8snHӮlQމ:WbWb㡪zI#΃מrhfTG(EPphJ g]@jjNNȄ昡W!|RUMMLJ)RL|A2 $7g\ PQO{蕵;#=2ePeG_~ɡ} ?J\`=s"/xf2ǭ!JP}\hrW̳vbv&!Bf*zfHx OjhKl6{;}߾S~Ye]Q:;)Q s?! '}(Tc:ҵӵXQWx:1!VE4BSBԆHLT)KW2[P}tF=a;ZNT%Ql f5-4Fr6` |irf9Ի$[戅D4cAi(8J̢wcATwʾsP6u/:%kFM;3k'rKz,QB6^%a'P%tK6lN9m3Ù߷Wn Wi2#2\ܵԣ f8_2!dZ:OZ.w]Jt=)ut' W٦پCJ%dp)pG2:u67hD_7IsʍP0\J2)ټa)SJ{{Q@;,#@nw/OEe.)v 6FvyW"{ ݕf F>vW*(ǍZ 5ŵ{ֲx6t}? STć&>8j <#6oiǘ">e=çz*CTSv+ɦCu Y}(BچZ=cD ?@fc (A3M {>ieiw* mdy,&1-y R8RBfD|b."Fˏn)8eH!MgδLja[V2| 0LՄx~*5UۦT)FĔr8z ~ty܉=GytX'Տ㉿W/\c"\wK>4zVl$ܝwwuN_<; E+t2Y$:n`B?IU k'3ʶG:b"ѐrngB;Q^~SJ3l owO+1̍wuG5 UWY\bYPAE%]5 eqe{dqd Xsޞ>F<4L]6א7hz|ZU?D((J2{?Atgh՜;*Fh"-t 2 7(7ǔg8 L1<Oe^c 6Us쏹7uDE$e>X rPfT2+Q"ȾhՐh ?S )zJ[I:Pt4}M*Ey~_?GS+}I@w*[HHI^HU%bmW?o*UeZ'E=q鏵ܙ>~7ΕPpSnXxXbãf :m`h SV̆k0<ְ:6-ef2g*vTAQubW4Hݕ Sɣ6p#|_p= :a.մB/%s=E4&>)sW݃5~+OHGd) r#CQ QZg=uo(Ejսld͔sjh JMAf07.NꔟS̋PG?Ddn.B7a[;q) 9B&p3ʲYt"}$DSQ*% wez?%vF<j/2g:ܥ>%yf5EMeK,?luu=CԴ*=b7VoJpnZ?S~P6hTfy6_#Jһcxl=-MWh7>lAQl y5hJ-gIuFmwRzjqw7hZd-2* /~b3cՔgi|Wa"fM)OWj QPzF`[]ONst('}^ݱoy|'ˆXz_ͭ,+•-UrFan75sY(xC. @Wasߟ'39F`2<~gt-sSѫ;Wd#6π`$(G>M={h.i5}tu 5U@~){U4o:l1/$io~'׽j(:U4< huB*s Q tmNՀ)'ub7.̌oS^Sx(fӓ^I:4EU,-u)tQ̓г4 'vs_܌[Oh۪O\E|U@zC];͊+EӼȾ!LרVoK9nNonu8GOquĉEܴErػj;.>]гZ-;eZkEgˏnjv:U4~Z6&_OĠiqjXZO4޷Oi1iegoѫ 41M+4A5'peh&F_G4&V Oi*Rqz{rH뎕4LYIAӲ##XBKtmH&t'[AX1yZK6Mҟg_'L 4h t_B# ~{Ȧ[)TeҨɓ"iꌪpa+0)PSFQ\%El8@e∠Sv#?*:")>SD6=j?^;&o;t*OW37 G܃*Kt;Ŷ*5 9eȄ~=l-#)Z;ju6?*:^oU|S`gE21{08@ݓG&3ЎUxUuxZ%LdÑ`ok^v|,]&(%۫e/P!H|JbިݴnDzdOnU,Єx GBսg!|V;rΛMߓH2+F\>Kp4%2{63„J3TGVyOOҟ`˓fZ8I^G EE~rԊKzEky?X=wSmb)1=yk)ou,/rZpD,ckWBb"HoڏE[/=Z*FYUΪiPE-'VI#&)1 a#b =u:G"cMvA>+KĈwՐB*Eb4(Fκ# k GOEoN.]h@{䁈fU3tF$Z6UWIgh/lzV v7P֨·'no(Ԡf'UOt3˙N]*tŚcX_Gd ?̘VfSYS,T+}'l}!*Zcn ;nQqmxj3UgkX%^+8QT;wC3 k]hfoR<;%^ DQHrqS7gϢϝ'Lj;W۹6`Gj NEEƁ2v6_aO#y%wR_@1 &/+ھ `p'2KLJex'"s'B%}ffC|-11;o*[]o'L{)ebpNsjz+O &Wc4r7+;%ĕ鏒HG"c{LϐR? %q -8\Sk,EzHbkòDRO}Oc>"!OKm$Ypk%t[(jnڡG3vT,\pq3xy0[mey4hf$lk^6܏~4,qYA9P$w`MkSg~C?B!3h/lp:xYi|4j6ST5哧J-Fpa@HoA=zt;6^)"orIy=RR| \?9=h`v01qiсyc tVeWjmp"ƽ -zoZm#`rx/H(Vf=yyNU5t}=4YA3="R9Bwm7gӯ, UN)-JYID|<.GeC~09OG{ 5_Mh>ӣ{#FI#m$Tm@7T%9ON:KK%Л1HCHg#%7ӑ2&<]'z=ء'3 Xɰhg'*IR~`jsLf&^Ʌ 5Ȼe[ w'rwD1zaCݠ>s-sS>_CҫFIF6%k㻌{~жbJwzskDBYiO~C937UDn~PR0h':̽%!ˢ\^s3N%j} 7Ѧ;MTysc„E䐊+I3J'k_Y۾knba*1h"e/w95 P~M4޴$:mNr7zeO82D ,L"V-~y0}԰Let38.}+:gF4O ~3(QLQϛc"nH5';i\t]'6AE` ϫ fV:I=GKѫ0ܛW,R&yd."U ]f3ÕZ&/f7Xej(P;mR[myu_ r+'oLt?h(ϛVMxoԇnc߅W8xZtl|5WCdA=bOYqҖio\# v(Y#F 0C^eCĬSfk˖>EOft߹nG7"nm|p I)vkh)a"QT.MQK(uc:._ Ͷ!*C[ cM .Y \bOW^߾B_>LS|}#nu "~ dCB/u4!Y>N5YU Bː|VdmCk+|/~vM:Պd?UeW2v1 6Q~a@[>FsDb@[zv죥x|YyyHmbq̚c:P>_tG'VP/4ZaVp~1Z9e8 k:oD̖e!FH|˛nȁ ;Rxl8DXaK{9 ņPP݌rOk6bZ˒'H2(Q0GKvzV_[(Z`Vsyou |85y g\rxh$SeW̼@`vAQHGZA+ZgzRseZ>[|c9ќDS6bɈgqz4w>DXGnVM_ܪ~X -Ά}vc^D2\De5eo*\]=mfd;~~H(uH5"Β׶!j^8HȌ\j1-NR,v3L_&̐AofуXoy>&czHYc; @?Mȼګe|O-Vd|gKnls^!hb7+bd^ ؁c~}sn+axye'C'RN ,+ȣ-W5lY@PVDL1A2܎c zBlV~$[e,yPLwT#C 0Qo_!Ok "Iћ90$cJILs+JZ%3u,}6ʶ1mfWuOdDaw">\=~xgJYo:kAyϋ2l;7G҃ԱyK1vFP3f+$p876xhs#Z2ٰx6 :}ka:sar( ""$r%]¨s7L|ǽZBӻnѓ}W,>8jZ, רS;kf&kHܘ7U{ܼYs;3"D]tD6n1--5'Es\/QlާĎKo㖡Cܝl3fھ_5`Q*G:ceTJhZSʪax7q=5~c>rin$+ˤAtѕfnKo>"zSOV"'C!\Q%E%r?M=dQs;%>q ٲ GqO DMFei.n "#HТ"p[;[ǁE+BQh6͔uEWc`WBd{܁@@;pꊿ7'#K/èrC%~ˑ& 4P_C!t~+gci~ğK:wD@0QγLǼ>?g'jH{ p%}0'HiY'|,M@TQTaoX|׽(r]ir7|3Ui0QX̳e ".~^%DLq?lϽOu!-H3޹̗@W'sHeYOW[~&m2۸%|畧q9@ L|%ݪnIǗyEyn*ĕ֓˜vnh!y^//OFYB/ݜA[ *13 o++ y+f|w9F4Qn/737vkzAPbaC%;v6~xj"ry>D!PJ9ɏ^#Ê'h$q8[^p$RإLY3J"m׸+GhlKLt&Zɳ`Ǧxדz]Qe>Rڪb5߷gА\SLKUc,^oMz{zІ;y1gA'ShBYlCgs >Uj* {sGZ.%˱<1%7ib`B8a&kҝnČJjlIȆuB6"0ǁLoI?h|h|Rw8a*}gAݠK(_G_~bF+H7 x)ԱdzZJ5="Z 0`k4fXak9;l(ICʏuT˔S0mďFЎDPn~R#| fTlZ`Z?o?i$n6hFUsgH.3f< t3ݔeR|ܖzUh:+F.q N py9SԶ.XTi\ɮ^nN!2_HG*z#. >;X6*[U HgsͥKm~n$x 'VS+-MIRd;6QQ|ea|1X! /Ss1;(n׵%T. V<=7 ERI8.(<hw:l8,QC"l 2Zf]ZU1 ˬ0KXPC}Q;k3%R.ZX8d9: y^mJ^C.H>z#bOfyZ~SՈ˜9{Fn qa .M-wӀ:) fVl3qfevQݾ0A6No+{Txl[%5{M{mUDR~rV_ycu[zr7VKo8v1߭0LVo;NpyHۻjyiw$7u 0ȃ̊܉FUe.4Ʃeޓc%xaTKs]t rL)QGNiݩ|r.(a#d?k"Z*hReAܕ.DoSK㊕`Xk֕ ,ܟ'sBoĵ1]hNODӎB 66 Fp苏hzAh<5m\ s(f0ʞm<ђ\.̫diz\f4\pqUP$j| oksg21wc^.ؓȨeRy,TfbL|W5W(f1OR~ޢ¦ata3U0,,@wsSCt~\O(G 9yhtye܏`s%uNTPܜ2x[ҋXv|M/)eӜЁq_vwW95mAM sUflȹJg]R|*+zNѢhQuJjQVBmC-n[ARusFJ޶%ä3VОKŐvDF!hXҋJJ#A(-[uL6}ݚz2T7K+t6^jf4n67oTZl߄PV~Byr)YWl"{W~]`pCG{YJv%7WmN!7"$87e9ޯt2X[_ RyI 7śYUE| !BMWς#'/@Rp%Ky+,v-}{>L١tVQD/%.+hi,G XkLfZJcx<(/mP.%?d;t ?[r9p/?]sZǹY*vq4dиm8AYL_LON0y&0q')g-i )jﷳ2mf$/bY/se*ͽP_j W2,v" ءwM(|ϸ%\f7Z#pL!tnJ1Ǝ/~w;`d8ټ3s\"wӇloe:7%Fr?)w4yxW [>t[ 2-J۰4yrN<+nJS|s?W֊P  ?gڕ"9V5:Ձ++/3FAKE>q:2*ϟ{Sg[Qcvj'۪4+Y&fm-NM Bzr]V4r/o_fA)B_C:{#y6\ 5Q%? I4 PRW6˻v>e2-3ϱz`ɣ$t2;*ӣ{5* *{qa"r+D蓂9:p?|[RϤ;1.lU"ĺd[;{oX# z4?Wo>Uj]l0vK۞La`Ԫʢ9LvvUcR X+A S:r\YQ)k&dQqP9͈\N`PpcvkJ3s"̃ĒS.m׼hb6,v!##׆!%΅0Q jEu&CbҘoCJsƄDXYMH/hMؐ W0(pGqJթY%][p"nhs6xV4TvMnv8BiߝMxyP-RkP7}[>G㱹,4wOI|ڢߘ (F`k&Fr4oM\/%ТJ}sJ1Ab&Ev'Pz%mc*I1+owK;*БqҫUSnh5zݦ 5/WMăf> p;ܺuZ&rWv5m=}nL7rǍ֭oT,15Bz<Ĕ6ŝyiDZ89|OY=@ w-ݧ4hŠ|ϧ}Ԥ{g僈P<8}^sk owJMzr'03<BlV[;6 K^ <гod1}ZJ8FN8N5?dE_.Q$坬1Sn-s~SNy7[=rj) r0> Y+UՒz% k^0&Rペ P 剃0`Hвs0O]Ca:NˌB+¸B2XˊlN%9Y\{a: HsEU#}k%yċ*bfKu6II~AC!.LKg$HڰF|_*㞮PL.rugsJܽ}$;Nɬp,h4*W)[^$ϭ!ǛqGAuZF5F\GpC@Rӈ+T63Xr1l?Ί2OZPm5Ktmmavo #D4Hî닧c-u˻A%'.3C1ƎEXc߼kѬZ~ø ?9 =a(ׇMU;nU]ڣw *饀a>œUVyI恢WZ^|C4S,E)ȍ}mV6.RAbȵMD$"L~lǦ;E,,gt̲`-fŠP/ ^AG~ZAeJ0,/9 az/[?GZR9)nOKHKY.*\ƀd1љPMr24:#y[MӪe|htȶ+~|W,7';iyH,zUml} Gr3-5t\c 5gV2OɃ%O8G~G*y6_G>ӈY[8!y6mFX}*C}Qe~fY@svv1.t˜94idE:zSn(Ls^fݽ%QE47"Xc\gyhT:}fcF\!Ox|[|;F v@2*UMbcr4,ECa$88JR19\`Ž[d]%2j`!aoCTW/hSF=5o;/jxN:;`_pSL5y7E@A0)"`Ie #Q0Iف%ZWb Nd -R%Ϫ>|<PpL~~Vcw2v1x~2A?P-˥c62SƁY Q<υ#=Z nVWۦ 9>zM Lj,Њ )YQcoZnWdWxW3I=SCmMz}^|u6n}wV;AYmSڇ1nZ懊fDP4⣻*J;ЋvҨJVIjkZ wPpfhǙTMMJG%'sIƹ.'Tr qTVz@YHPf^pW})WG@h:תt5dr1;Du*M_;Ցy Y햎 qոЏ2Z213B7m'F:HuE3oyp^ozEN'fȿ{W(bT f\A/L_sۥs mMY:e}\3؇/_J꠹FN?fd/ڐ#{sm:FP pԍ!G \*zv)qCtPyIO%sa G>62ɓ=[i̹2$,*[Ư}!D#;Ք&~ŠLj5`#C FȄsGr`hwN<%ZƍMkwsNQ8<%msőt剅yX>lV ab8rh,Wej~܆iI݁[(v`i7-q8@Kj O槼V)c+3/"Ϧ7;IeVlvƄ'7$\Z}!}kމcn dɣJ[VfabTwOm㻁u|#WV?(fqCְbWD~~C [Ӫrj "@=xTVSO9;6'qV6ôS@7*SjHRìS[+unD69uIY⬎y/EР;531OU ʗ-xD/ 6h_-t쭴7i[+CQ$|QXpU"˚mr]a8"W.SPMOEV=5cVlIhr-RlaBo5KVߙ@n+M7Vͤt2sm+2 EMf>J ou%=5Y-]xF1m-8_rN C1%obd\]B0E\ͦ` J,ݠt*ZdnI.Q΅dFT*nPc6iN}-ը6&6RءT$A#ɬwlfw3SݓHa dExQ[~9ќmżF,(jʗ4Zm9wTݼjP5-<_]:PvmGne I3}n[wZOL!3/xbnӐiQ$`^9a8R7s3-䊄ʐ~O~L]Trec(Z}XiKMɃ^"ɶ#By9ӚMd FŷhYݺU=tl{0g7dhh/Oz+f6ǫ"R .Q97 Xux@D܀/#U Ar ӲՌ斌ؿ]dAɭSQId =Z JG>v; fW6ڜĽ}/^nk_hdBeq{jU}9Z;L_NVDNNFS\ L+tɫ,RMc'< wFlidfc2b;Nw]BeS\˖A{1~~e3tBhe O9ODyy=fGx v'^YQ2ܯNKy+yzRqwH^޼U{@)_&JДrM}s~\խЖo(~U2)͡[;S9aF)2`P ஦Dռj< UhA*/zEm}DEH/f8+=*Q X‰M`\ -h&QD6y{wyAPH+ק v627.1}:❂֕ud-K> o^ęi"AzrI"lMhFY =oX9]It>1m:JdTSd݉V.>zW5XfN;Z+[W<<0:D@zт|R"aVrx(tT/WB>}l^[k/]tUV)f^P~+TAؼwquΙ"tL ݼhRQW{@ + ay@5+REYbive;@K$qP/X@}n_O A_:$ICBJ2]gou %$1MrpZr/?e7ijOܨ R=2!{SBq %-2L:M5(ZA1oyTSGzҩY o}{CVtG"oPPXTdydu_"ZoN9澊rE=m\ޜcfuP)w1w Lkݴ "yd4Ulȁ&q1.j57z|'qbAwk5CsLdžf&NqIxt6: P$˽|D 47W*ahC&_Fvx|-P4˽4.㖋27r=OT:dj4UVYP1_wmqL~,s3oN=l~e89АYݜUOŽmW 2B6r5Uhp<\Lj{2.sf+tG\DeO:)#(d*c^D6AгD%gș2'P5x @bmPNSYh2AI12l)Qc>wfzjxo'6vN1وXB:yyD`_D8l^cdhS-S%}Z%`&^c *)v}l坈ĸ1+q qfZmNrJuI9fEr=IPna P7ușqmiąQb=gI)ԸE1JwGz Y,:}˙eX8rƾ#C}-yeIt?l"W4E>GoN:Jg6XY.NгyFՌ[#9C|̲dl bKm,cS]moCj72*,M-A`EXs)v2<{}`x>:vWL~f`&ssK7,L0GWQDLJi$Z㌂u:,yK̚O8Rdr' yV\yOxg3^GT;LQqy+#rbxHdZ=U!YWD>NV=*;Unp[#īBɭCu~bi=4(ӄVawKOd즤pn˚'(Dg]C"1ٿCk2Psᙨ! pf#ӄI{)5N?7*CsiM%}: ot#,c5 6h'r:V! V-d,6ҍ-RNۘIg9)_zbUAOy/oJL$ofi 9^_`?n.G.a#Jrp߸AU~eak؟-:g~ʔ,O *EkLWް5(b.B:дDԀ[uY-">UԪ).Y2|;{(,mD=xt znϔěJ% fÇPb5: |g-pl2o࿸ܤ:dyE֨W߬}k{'Je5>M4~|B_0 ԟɟ[}gvҧuUrcšT!svxB#{$B#s4vK8(têҕ_.>.Km's;[q?oJgg!H"J盎-j [b/mwd5guG3X,;=;)us`mr,+^ln $?{C2u[{kbCK"IRJv[Aϧ*[z 5(tY5&{Ց':Oʢ[%JKǨZ1m14gӛ٣d_?BݫN?qՕnox&yRD?8AMߠ5;eE{M5;(mT5]<@F4@_*jHkIо8!2:9_b*:etƨlUwGbT5̰.f %1Q8IdCɳb: ?OE./8]r{ulA*/^g*X2z  >4  O:ܪv򵪂+vVYtST[Y߽QAQG]ʱTx !taڵA:42bW\Fgg"iCNrnXZz\PSC=dφ{ 9: UDLWteN$Dk})L4p$H1W÷bdM|&ZR>k*7%Ϊ^LK:Hz(}wTbs2 7pB8bcaFKs@Æ\aÚs1uz޺$^ 0,dw ]]3kWQHZ$$Vқŷk߈o˶b>i+[Q~E7NhIl)<l]{4{곷e ȓoTo8-1h q(^a dio; ]XihT|ZJ$xQ^iϗ2 xxci5#M 1G>{[F҈yY27ӛ 9Ċ;vxdٶ˞0{}7)ĖV ʟnv>~Z х׺>ɑ(kFޕ!1\cu򛢼4-]+{Fo` UzJbȧuYnKt< {fJf,񑂬ɰiro@y+ݤ~.졂f$bKY"`bwrYqZUO|ec7c%|uym~띚A`~<D}ll(~LMU*r?\'+Q&{$ x{鲗QI|&$:,>Wgon?pQa\VǍu]|z}~uHZjmWq*wY'Jo<(ڐ#œ:``^Ŋh %rVZ4zJU[p(nY[v+CCX~MubMό[: 5QKX,*Թ{$yXTiuq #zXy,Ho]{I'2 U6EgɏqLF'OC} ʦhXQ֟Ղۥyd]SPXH䴼]i >+=ӧ_x˱f9G5eK%Mݓ|($~qR wB%1wE-9v%燲C⣝MSy?lw;m8h3d!{Ru@nw/t6[@{۬(Db!20wHD`wL>s 2SAO8DF̤~>\Ze(i}\SZLKѲfÝA?lauܥ/9\!y*lޓӥYdЎQNiA\5 yG=TvND@QOT#?ͭ)d3KfO*M% vHyӬr*oѧHI||l's= D\aCgɕ+}">V.RH\G,mwjL;S3'2LJǓ,f?23ΧsM>OneױS1uq|2^s~dޘAD>p=ڀ1/y ЧeK %ƅ=^|o'b30^yj|b]9ұ`\("0[ݡgsU]˚y]oo~*);>ѽ{ɍm1l3$Ƀ]|(KtqS&-de0h! eh PYn=w͙\NEEd< '"wkϞ^RHڨgE9 r +kiq/!DuW2̲GaL>`gT7O=l(c*2O&l~wuig6ЬD|ʘu^LSe SZgM}*G6t$`T04VLPfbq ]gQS=\މc284P>X2;{6 6E\naaćf+DÉ߼;cE^7⳩IhiDBt%:"uE)8M/;:))Bib.i1Q MR1zpʄdD%!l~PDž)O{JKt[7 ?? xq\\y:XҺ4lu J4TmȫSӑd|0  @,j_ʙS:i`( ˢF6fV̉͝Sy>x=qPJRVqc$Y:%GZľzwU&orN2goɌS1&j2ڻ~~p44(W.tw>-~Z Nҙ"{bGޣz1unψu^VAaL6-a#&8dePZ vFMZ%StUwSdֈEw3VYKKs03[B8)^69NҬWZ8wW}r jYP|u;۔nk zTՂDw6ΰѤy(5BOdfK,mɳJZ]w- HDl%zt3&o.ԋE~|.%3[M(\uYiC9҅noU Β$@fm,Z:nˆYsCI*Hwh!Tsϊּq/A#GN#z;jȮ#R' |ktڑ=|0) qV?Nɒ*xE Xp*tW=FSzonMJ+ -ZЂ# &m p} M:ٳ`ظPW)dO\GT@K5eӫ>C \#Qaњҏ@b LZ}Yn6< gMQ0gQs%Mk0#nL]/_|=MHD(OpQQ/1eG-8)^Eybv `l2o  x> ݚ-f{OΕdȁ8A `[cPTJI񨦖*G/n 4*|vkGsK\gNbӳzw _**0x~~Ncrd5[sTMNT@ݲ8]O?CszM*2ۂ"zʓROW~AIŠPKp! .F +E7#Ug˴8 2s1[ISpKhz.NLF~mFaA{0Nקa?ׇp3{{S7_%ʭ^ eߎ3~8j=}F˚GܟvAuy߃a6yO}ar0 b7` N!Ĩonn$`b;d RSM&3y-yo3;!awO'vRN)wfSJMLj"y֮\2Lg"̣y-&: ٷs.+0"&55dvLnl_4 s_e2I y`-TXP\:8,uІT{JCQac@^w?]VyE ?9 ܮݺ Ⱥi3u=v֯`pkv9t/yM k7g5<$`Q/;FZ:\Yl)\1WA ˽%ުwGN9a!iAs"lJ6v(S[y2Ra9ҼOq@h !3+fmuA96}:d[q>>8>=\|9\IJ[> EU/ 0}ǣǩFCzBF.}R4=%ζls?/sr_q)++m#]^1˫Ic 烬;Ͱ͌% (.Q|-OӔqʆ:':f/͐ ^cg=T se\yG`EL츫E+چ)@ݣ','r8pl |f?Te6s?"S?K.ݏfTuxny*_=.QHc*V<;iam Џ*2f>AZnƱ?#n-mɾǑ~k<b>ueơYu6u:,PJ;%lYq`"ILŀgt87 *)rS jU\z%~s>D-jjY#ўIиt3\jʒzN?_ YdOxgDm jw=¤ PPt<[~X~sX2OE!DZgtݶJ֕4*S^w:ʼn_|aN5SjE3O_rfқ3"u9UU x~VoQܼPnN/ 2EfKEMg~II*߆噋Ĩ;8Mv&C9UJH%)S"BmwS:ZUR90ݸPG jdH97,XcL:99`tn{PÞ6^į"P2$D ˼DS=<R-?eɚ&}qJ~RWQA%E>eA~?ĩYJО%?}r[>B>ߣem&hC9#/\J:e&CgáG:mj.Pq4)3Oģ=~>(P. &<3ǃ'  Kڂ37haY4˚^vOoGAP(wgkbҡn=k,/( FkƷOՀYSh]v$&yj9hiIOhu1c}*%-1ŝ .h[Iq59.S6٭7;h'ZIKLFc5ٺU06s5c;hQ9ˢM{f+XWs"l6.}Yi' Ux C!CDeɭe){''4g+֔' KM*{7 - @s4qR)o*T,9Dl!eB#@6MZA9S;V֫0TsI#"ԠVwaWq9~]O SL3̭nJw$-Xi`ѹ4wP~;Y6ь{eUF'LL߻re)rz ]m+nLLPX&OuT5V_D̕]\lXÉ&NsXXy4!،7"Og;}r=vGt p*1 S[۸, BmdjKðEg aa$/2ߖ$VEg}:whMASnU&y=+=dt724ڥ[k^)EjuId>Wk F bNg`N9N|1v^ѰAsKLdy2mNcZWV&&C8e*CYMdn9N=Nvei a5]ڶ$|6k)J#d<-q]7I!Ҕ|:ZOk3=Bfud~kT4$"i} #SG:-ͥ6k:WVJ@)X!XeFG:e NNc:ۖV UMJsxc9pfÚ̒'*bMnǾ uN$Aw>trW={Vh'G'"u7`< .)k`I&U1K7 eJ2bR-r@D대gkJ젚Kst+qAfI`,Kؗ!E*E8vFd`_ty/t4bn+sm;FrP ,Qs$ W#.qyBD;';8ϋ#hiTl532ᘐ̑y:C}w"vǽ; YE_ |,G, ;Mں_=%ԝ&hY;12ibl]DҽhAdBЙxz,_ ktyV~/Dnt;^T^ηXPJozx*r|;o%䃡ǂ #7o1ͣd Ď&cgwxe~0?7QڷOl1iY'zDm?; \r#wjçԈRw źMUp_GEAMzN0 v̍rH/e^qRM {4,  1i:[GK҂~FN'L nnx)83 V]ߌNGis-%(&;JdYsS*+ *<^>&5aj'hTD;&A6*U|gneĺnl-((snFς "c6:Cן_7r25i/*7| m]){LҊL#C}tGǡ;/:Šfzzӳ?7Qhr$-^VV4Z4ϟJxGMS!#t:k?ve>ioOҮfi?PKBU^\JӪdv=T~[|1N Dg$r.bdwn%9Yerf~9vVz2HUeJR<7Nmi*Urek"_l*(? :.oU_<~}'^E64XF?ȰI& zB,EV\}Lz}Cn:-xS='+wMI0]v)LO,TX`%Lo 곿7\yh77IDz ؅ ;/P? )+,GY}̔Ϥ~(Uevy(;ЬGeL8OHņv:Jh]t&x#eְ^No$$;Mlf~&d0?4m} :MXbjiiymݎ+5%꿏u7P?ChȀd :U;, Bt,[%?ͼ LVJ''"c.1NATqG LvU$ee.?6ZU%j|dUEDj$3U /r(SC VNEQ.EPgdUx0Qa܉? o8-OOPR~K/иTߜEs_3lm.\fp%wwk"->IqI|Cޢ,"xxʒߢKNИN=Ɩ&]NrZMDfBKFsiʹ Ė.s(i@Y/N?P*:.;[Pc&x'b%G# >;a/^tL~ݻ J1g8[µ&អ(#n+"!fʔud,Wy(7CKX7w+֐{'ݡAޡaX{)qݢZRGs§!xm|S(%L{3&T@yÅF դLwB*I˛S!]њWgwǵWh?f9f^'s=oM郱]Q\+_#(Vll._#눁~ѳ-MYHTqd=;|EK!Ld}Xi3eiFrlKܻoסe[EDYt8=a3L(Tbsull)R;]fꁠӐkXZO[ !AH\I|W7צFPRݔ]hbvkn?|uh[oFfFyW ~L(%>NP:P5y/)ugJ68Lr+Eh̗c0YFF? ztXr͏-eXM0m6W}z 6:PTiZ}}8ݪk9(roOL Giylk0]Fs݃n W! ) NFcvaK7\tP0PPZowp)3M>̈́Yƭw7eہ $0fUGkjTA},|e)?9Ɩ QMI )c\dfK[O7O )4/~/pQzo0y;L3\~4y??gm[(oķHD M>O϶v8piשF7WN5aRgf_0;cxYwXU&XyN*ZiKmQ6 /z^J71k8Lט4"UE͆ifMDʤ3 BIDTpK ~SwA5y`;4Kqzn07oȦ% %_cst%3{To:A Ka㖍2ܪ0,Vg}dT)M:r!f*6ȬSOgd^[ ח}> -TQ{˲$d'MGd~'e9Kzǃ K UH8uS?Th~2Ʃ3FeфV* ٳYoX[Ŗ||6kyoՃ$>¶*3$vY9l %x~)lw$xa0wȾwqygm^OMm8ZګQ=,-r*uI1)$j'("[ߜ='֗d 49|6T_KFȜe=[?5ݣB۞$>!}܏kx\AQ%'3tD&=_)Mʜ׃])of$mI"MB8Y=F"\LhPUV0湘'Eks*ɖ$֕.Ta2l/{SZZPMp}ɲ/S!G7 Ur9 }\(B^˗,~w۲U `*.&uz;J3Fu.w_15uM32_1 9-qh-|2uCwssvTxŢ ˈÜ" bV ÿ>wM̋3+SM:NYg} er6Mh^2s3B2fABcp^&+M`g>72zw/ qP~D,22|'8w)yQHt el9[)Ǡ[碑jn%S#u[e~:ԽZؤIoxȝlAѴISGQJ7w77{S;l/&u~Ix-4A@Fz퇏!zk׳se6 k܇ȝW#^aJV:53ju~}aTmVi?Sy񩫵ݞţ*-UZx>QUvo1"g^ޢB9$G7Wv-l_{f Tҧ%^%i-F_{^4Z,nf~8Ϛ4=A[[Y՟sm% . >ih?jN,ZJmV;*!PB`~x {f#^(ttEA5ǵN?$rW-$j^ʴ{"DeGFUYiV )aʌ&]bX'~9}1a} )2DĴLvN6Ж;_f%f%=#¢vkBi^-ḡ}{H)1y`oDhl@UUT9N.P^%7uvA*~ɠT~w>M ^Fs{LU=4oH6lcV1YA'Q.V]&oᢊV}ՔazDjI(*.j2c&eap6 W,iMKIVVR 4+4$ :+kf"C Z觲l~ϰVq Ds2:n18ls@DiNQ4N bvi+NyzY`oL37-w:?}y{P5cD&IzqپafyNf'_2Wj AoTeJugp8<`HWLPaJ1# ;am*~vzY|-Y uj2;r՜nI?*PgR ,N߃m,A=`bAXoTyH5D>Gb,'!4 ,/jϹ.)N,,"! j @EY(J@/+7nm"ŧgD1㺵C 4-=z Y.FvbsyGӨ)1|[53;j2#t QOW`ΥY%[Jj"ڑ:,4|-߽-ggyޜԱ.g>'ʨ&s=-t R[2MJ'ђ&)HEc:UrzΟ٤uXgl( `_{'z-7I:!@y Q[y9k=s3d| ϭƣ6k OJ.5QI: +\KC;$w=-&A{\6_0goՐQgMkkO,5f,Q֮Ml? yW-|o>YA "#= I0]0Κ͈$X*@) 0)ENMB%gԘ" çUrc%Qݟl;DssSYTvEO'j "46[mwZ`BY#g*:NYc=k7gЖ~t2(ģOq|˲G ́)!r L^FՈG2[<ϥ+@ l!烒MnQ霱Q3Nu'y<3aB-Lg/RQY1~T4uF?Ze%:Wo2=?1_aRkpG__HV:+wz,o eBz40\<^* cYN_ < xt .#K^7%n-)<1g9к<clgkjS9{]-+UN k2V;Š5JRCF/ 5q0_>22)i !+B/M;RMWMZ_IӏPr6i6Ŀ2nz շs&lrYr M'B .1լ2]U.|R=ɭ^:0Vb[$R]oj}EU9^TaY.z^ 7(e](+s %4F>~1&Y^Zjz '>j(8#6o:-nNKWN-0%3N9s',Orbо E16rLꘗI3Es)_4J:{f \mE^۪+9\4^{lf,PTwƔ8=c@r^LbBD\*4&ގ)I_|\%ݐFbޅ*G&e ދf0Ryŀ{W:z)mb.*ybw&D!S΅Y'OҖB [K YZ$4gʲ5KzwܧO0[ycy9#F5ezomWR .4Ds=nf-{ahoio{vm—bͳ-Y:+ay*eVA"(OX@n\:W"LPLJ?bD%֒W|UZ3P*Em;V߮2R*s4|ꠝ-t=MQe<ײ?7 ݿ2&iZlH(.Ssh`x1eg*7[[e?OjEǰCʫ 1{~[@n)x|jg=uC{>_p}C:#Yp}3Y*+ugzYPA8b\} ;K8 ŧI5Jw? M$%f2‚))!̇w1O TuV~e9BZ4HWϳ 7-糒^aKmZ9SoSl<5UU)f]&d5 ݳ z;*AhXɳVMBhh4P_b|nP.O|nUp7ta l7ҴKp |_#?;j4085`ʹ2o*,44. .MײzH;0JC9gly rM`i11/zqi a yD7S0sϕi!QcX:s4R.^_Klg{~ `׏B6uQ)}\„vtjX=yu:4Rw986IuI|+>t]WEZK+z(DPlJ>04s bSLiSEʼ-kdeN9M`)3-Ƒ;>IҬ[cr J;ɗ՜Ǘ븏[wdzik.$ ;U ҩޣJL=]4驱qThp70h ǃ4!ɸёF%/=RgiMh 4V&,5`C(z[!RSGXM0u% g׽a ^TA-1^ةॏQ>_wgf~\;(0?UIw?/=nU6z8q{rmc(dE:TAIKՆ6 Lf,X-A6]';vXp1N,[7 H LӫM|nS9BFLҽ~ol8<쟔fYBs|CfL%QE0ܸmm-^Ǧ hP!+Uu`҇{ I%O_)Ce$ר$<'pxr$a+44Ym-Y`|?#q6c}ͳ4OjaO4$BsQZ;&!AeVX9+͠RX|K$pMz}MXZ4";۫6 -DsԑCzewDe /%I-CKU8KfokMEg]۾Y]]';%7ZYejaY~JuUݷڀ^n5hRCyrE |r&2u@S +ﲳoW䱗1B wmoTss/Ä={sC 3.ZjB(.̤s]/bCāV(9BfJձK<A*2iɭOJ;e8mc7JP0֑K?GI74WD ]ljg5,{y3ZRjg[hIQsDPx1W-cυ~ztX—T*ˎ`vCu~;>ϸb`.D @{ױ+Qx6oci_x BVuO1ا&ĹrˠM|$'1yGZF^ںք.2yn}E!Vpk,~fQ>{̩~^Oc/-s秧ڟR9^:۝qP_91/;`\6c:3NM:B)X oeѺSxěg!^lSȝu^Zrdz8 &E o$Qcr])4]Gf1[AU :sH{{apᮊGXܧUn`lU5 s53Q~ZgVa!s}TB>?a9jΣrSϸX)4i*wB. qϻ9|fLhmT4c^w$' )B{Fsm)=dePi澳(M߰P97ʴ؃Ȟ'qEDƥ6N~<}qF"& gq <^.zӑ:溿R <~&1MgW.<0κ¡ ; |j{}:F: &4d5WT ~dQeg[Tm$AEGmbwU$մ*Hȳno &P˨7^Gf>K5=5maVq,d<9;sw6s ':[){xZ8=Hgs' ^ BJѬ-%ܘւC luDL=a?U~>Nsf0xһQ yk##c7]'h%}~)uVyRi\;vG@:Ӓy<jLw%)iO'lO|r[a*&!9D|hωn> ZzW4EnүF,` ޖ@^ xrU\g/=[ٻOq\MBA%guOeMm zЅ뱴3k"hIF{}ڹhJjaR^B HK~6Rʖ8\qO 糣,dz߷Ђy$kbwlC8[v]stRg?$5LLM=ZT6{py2o׭.Qłk׹B|7vZě<qf`PwmoFcBv*`6ٖ݊ྮ͕FkoɶƕvmO ,)}9)7GwdٲtpBeL П =#d 稜oًٍ(әr#3d=f1pڈb~a0EPnF@^^?(]gҌA%FWZ@Zi/׋.7НI8q}CBy@RHߔ+Z|Xd;l /Ol.74R M}{>aKLסH?ԒZpoȅJ̥.Mf@҅1@H?c#ɸ2_D*7v=?ʃ3xO\K 'ڞl㠷Ez' +o6rqO0ͧ(/ͰȽPqs1q2VCsɜꂓ6|2ӫ]' &foe\/!Te.;WDzc9L'96W3mG+Scg]&:Z 3ۂZcNtȇڎSЗŪz',F&Fի $MƊeW?EE"K: ߽(9P YeǸʇS:Zaӂ+y0emb)p~u3dՎJ,!zrO֏Cڑ{Y6řdk>-5bTp EBV.erXak$ vĮc/A{?<`Y+C84,1ؚc\K͑<$tzsxvN? 6Γ@Z̚1 [b>:*5uơ^Pk?\fN\'6Tecn8BƂ?.P\eVQVĐll+t/ٹ;@EvCB.ZEu.K8]H)2*8tO EEhCpTԂDE=|!C1cċsU?d8 *,7s]v/7k|Cs2Rt] 1.gptm4IA˚=Gvp9Ȇ mHVp[_\7&zc<69:$&/dlr#"m ^Y%sS8C\íGho4b@66Th,rl+1#!N }o*sNsѐC2"PS?Q\'.Ydƅ- Em?|r0* =5UVE$boi'75[mbsv ~Ɔ_Qq~*'_uӞН.r9e|I1r [=[Z4>c&7I#dz$¦р@yLeCWSkSF}Brջ)i±`XS"jV^a|e*{f+qpNXG4VpiNSX"ck0Pe1*=ۅ9dX=@ 4aJ%T}{uv2ؿb@ǖ ӯԭ~h+ϏhyՈh+ ϊČ۠h_2rJ-ԽBf.Bdh'h7U&Ot?ȴt3K˥v4(lpC>8Ԧc|l| O\TJ? H͔DgX"4]fj <,a iW8쐳F~ =^뫫: =ǧK". wPƃRʇH)gSg Z+Q 4i 4QMi°>-]7I" QTx(N2a)c]=JD@k&N^+.0;XhP/%c"<;k4?~Vl3޺;9lԃDntc/3%XQz)JmOE֯*24њ%sեvJ/[x*.'/8WG^0+rOQb"%znգ$st: %6RJ ƚNj$dFMELFZ|[j}XS1KF Se8i7M cxi*՛8'ij/Q$Sg>L G4dC$Вj_rUT7~sZeݤ6wa.{APw絲k)k(<'t\G4V^Ґ`)a޷a)y?Lpa=]Dᵶ2BB6`7^Vc˃ "2"[͔n/v H ގj IMi'TVT:Ot_ON eB#zn-S'7qa?1V'_e׶'ں)CƜx±,&t< ,_F<;u Mq݊>[mp^*y&֑kǍw@abh%У8l"槵k&;^d}@ ޥu/cCgv2d &{[mߛ1" RN]2l8Ǜ^͙K&TRGn6`3&Tƥ(P4ԛޘMdM1dѱyY(Vh F+~GWb;x*]@/ve_jC?>!hzB|cnpܬ J53ZUVgiBf a ZpEQ\thL@wiUX_e& hVΥ [,]+7nw(;ovQI+[٥QOlq1dt2-xv@|djϝ}.㼗NXnk#t%MۓS\xd[&nRLա9n`qcیEΝ{~Ʉ0=w)i;JA-%G$'"e. ,,ߘd^)ߡK}4&ZBceG]o,X2|k -mm3hV3 <'u7ћZDƻSS"TgRߙxA6A@ծ;BUbmwwO\zN/^I{eﵭWײʓKNN_X>ƅYZ0,{L0Nz |gCkl)RtDh:H`Epe+a@=0WXçO?ⰇUAM8(OGqd#~1+, 9M`b,q=+.ّ_&)oT+[%b%pU~&=nl&L6x"K$5T5.Ekڇ(qv C4HUPo~.U欙7 pΚ6zOċS'g[`Z1\sk?g.v@nEu" T|E)CgT S"pqKqK}JCuJĒ&y^|X]CѠX㟵nkT;>'2rlXq9=v~,HMQ-w/ޱDZwv i$WOQsUU3?j/#B҅X({>#+]e/bWyfo?rHjBwh0s~}e16"  |xZ/ķ ΋\f6"ЊpH>w27s'7V,exn"ϫێd5Q[|H|0r_$N}_<gjhu'IaS1mڽUl5T_ԥ.J5WV+Gb/{2G";fz=XbriՈկuu4Pn ui8>(,X^ 6# K5-}:v?w!=yCߢ:q:1rh=ǼwM:MOhlqKfɕx\6BysŐ*|u{8MZo(RLDҨT͘9~W[1~5OtMBU;h̢#Zdҟdv9(ꋃ\۶Y˃ӛzܻ,Z(zXʴ5o9d^`W7H~J;vJlO=\J%HF}.Ȱ6n2Wʼn0$q:ޠ{#~˝g^ SRGtj&m]߭ -bH yMenv+ =G$[ɑe>e*]X5س% dߙ74쵗Aslr׶P,=chy,Za p&ϑ3#-Ws0TmLk$n[NV,c.Mγ;{Wiz~v|fB#fw驦0} ]&p2u6)yGmf `˳C̆?I ͒ͳXst/e$RCyNq"OḦ!{3\ ViX#%2]:6ӌmih6 fzܩrôδq?7aΔsɵbwy.`,p5w&lz%꜂5X/eS\я!js6KnUxmأc=A>y}ZR*WYmܨa2ASU:-7xvVcp*J+޺ys Uj](ϊhrX-4*z΋Ekb+蠚iE=epE棎7ԋ{ÏFrLȘtR4|Rk@EDMc'o9Z=Zh9ꋷb~я֫y6y.S `$gx}Ecyw; @ly[%)ħͅlkǮ9t C4B6 5Ȭ2Y*`c^ܼJ4S{ k?wD R 4 d=4/UU hz ۷}rTߣD*=Pg~x„e٥ (@G[V;g7??& y˿BWi϶Rio&Z(̰ Y صyk.dtriQt/qJ;1%[؂zA;zaڟָO9X 7W fg 6h/uU ,~]`>p2y\x"r);{9 ֻst lVKveoB4tC mQTMh K0Cig\t E9!M+= w+k-L ޴=\y}:**^vE,gZo?Ч&gS#ao2țd8ƛSm[ߺ_g3oRY˦@ɍ${z79wMQK(} rbod6koQ\kWύL5j$o_7Q˼gw#Hx[:ݴ;mK ͇+:Tw/=֡}ЬΤKlC[95&&wgIzq @rǚ\y8K dd"|v(B_/A/%x02b{Ʌ`٣y 1R. b,~T|3 #ۊdOźlJfd2cTdIP*y3;m6]þs.'ȫR⯲GV{<=]{U*#ȹX= / U  Q0Yڄ(wk"C{v;cMׄZЖmG/%{ց?e>~w# .xq\ΰa@@*x nLOh#,Idߜi+ƃU}#坙)ɮJkg gXςK@(-i?s~[̿<|ni1>9=;Qnn*x^x BfE&E{6!B5 5Oz3Ys% ]fN$0(8Á; 4`6wX&ONN`@X7(BAyCTA|ȅ&P#;j=E"ޒP^ri>HSLN1srM{eTj͙pi"+Eٽ֯(O;Gv b.C>=4?wfh/q!KXv59i1'=FT!2n?,05_x֯E/?eCA?vN}QxZg=eznĴYa*:YvU }zHJw$%L&AO1_~i>|Esoa~,eςcX%gԕ ĬLigNfD Z03,\ 39m4j+L}WL.8+#LM%dES5[k_*ٰ4  })l>c~َ[Cߠv;;$wtvds.3}7,;X~}$Ue~"Kzwc4o͝@^z*~T2^92"i2#hd`jLI “WEw;]^?K4~%jg&~8­. Edm^ds:w6~mTq> _A7,j=:j ewÿ7»Uf=vYSHaN~'L>H6a9R7e>cA#{A4:?W42{kGVZk-VWG]axvBMry)fRdt9\̟ 8l/ (ɴݲ˝ |ʼ02f]B RޠH? 4yp^ q̻cSLùڑ`8uqR Aph5q3G0k}]o(K4fl]xܧA5Ud@y-NAbuko SrZy&t@#} _'q>h|qi~QD}hPN;lHz`8m;Rzռlڞ׾[$򡖤E˦11!3{طr,:ۡђV}&\0ݬ2k#ClՙГ[kkh}ަ]ۜkN:ǡHmƳ7\xyzMO'pH^FPWnPCDn0Lq='wW`d~wZ-:JV(b$UΗ$wg3FF *xPoa=\ᾶ|8z\x,u8=`B;1jCvߒBч& ļT$rYOpWjT nl5w;3pzڙh"W'Ǚv(I(ez Dfyg|I]&Gqޣ"㱰U#\+ȯ )fO$Eo/W{&o+3vp,G4[ģ2g"k~3u^:C=Ϫ *J?gv9;C*˯ᘢ1^b.zA/yhH{>sAXz E,S,&A+bԇV+FW< 2N2itZ$[͝ш`dezxI[t$Cn-אԆQ%B#Qܲ|y<4 nhƴ$e26hގeeޔyU!E~ rVgp_rkjdb6bg@ ;nߊ;ᲒzZ)I2M?Qqa{yjxҰUM07Տ̥g3x=n!?̥h^e'RK>~8Q29W]%LPmG@bR !niRכXxֲZS^ɕwhbΦ9PƜ*ѬLŊUB9 Tg;2B-aWs|kfȸ]@7RՅhtzjk~B=^hޑ_ju6s/\lif:x.Ab|9.K†H&)۰7)sns} >JafY:ٱ,ä{--|TL)wpܤFz25Rٰ=XM.хE //c~E5C~nLӔ]K\dUV86).ρKAb;pvyU6q`ʤFY qs8*fv?qEWp +zsR&ص܆ַ. g2YDf>ez,uy: UBw7/(*_g=jZ=I|kw٦$)K\*付1a=0A|گȠ"Db~ZɯZ+~tIIcOfNR_{4zA &əj][Gja G7JJЫ6/y@ߍ>R;'|S 2h3wX@YF> m6p_}]-gaP*S(%igX%i2m o8|]g(-w%(P@ɍynZ{q@p@Al˹˶ZTztxqPߊ&KDrs؎p[Vථ`&o݂ \9oѽҨRô=ߜg?}REQ8@v[~+O_hQU[Q% W fzfui]'Lm@)E7ܻTK59p?N*TdA };r>C$;c]<"?w^:rWf`7ɌvGjHRFfM,q)WW?7tZ K?Ühr  pOXÞmdAxS9(%,k{]њei.)@l̔ 3M9O[Ƀ3LfTᛢf\uo\?&sa?=ġK0eCCzl9tK.[wФӸM{x<}ĠokyWs*/x`uSLI](sGn-|q#o֌Ry}AП_BbR7b=]:"ꌈG=zi'~Bz~&7Y*W[TaIpN zӊGv=86+P>IQ(1"'ئ'p?`Gnf=e@XfL`mg *-ց1wVJj6=XҖFv_`,9mSR h_b޴aS/IE~f,ŃB_i<W_s^v4HĄei% b W@Gf xR?T2%oK^WFiA_aIQu9R.3f;%?Heyךe\>7Da(̛˸Mߟ1VLӋzso^yZO=r4En\ނb^!ݫ܆w-+ڨmo`WQ@?h&7ۛEKLkʉ DW)UbX+ç>+ @,hD} b3F~hAApOm=)?y ?a, [U1ԥ Vz$:y2:X EDLhetX;zwk]2xyc84Ð"dC\f7`M]}6ԥ-8p5_lFn޴~-uu@7Lh/" Mq~տ"2y8 Q^db?\aZ@ZS[7DSXqjhdK!/Sx(ä!S_4/]bU-9w?M>nGBn%Xlkt9={HKcZʯ͹P:=ҪϻmօFyO[i5e^Lf3n>U0zUl@QQ^2S*0Hn$#3 ayempr5|Ҥy'>5ɰLOވJuE!>hzcɻ>a&;ϲUyF=&mGmRSOɬ&ҝN m Gja~-6_6X>9\kP! s\w"jojuRILI60ܺZgD>pc;2,]!Ih$hȇM"hG$b>ДԮ@N V2_˳=c;6HH/?^ڙAs "oST Dzoc^.pw#7N)؅`_Y+֢(8Hc \(p+ ӝ(*)G35wJ/<ЏxWWfE$A9GG_< t|oi<FtJ3(/'ܤ ƃeMR%^^1cmdRU>'$ &Z^Oq*;Ѝ6R$i6JPXr\[G}Z:'0al|{ziʌIv'EZi%"g8@K:PYEf(2D+PaYpmW\X[b{NuJSne*g? "ZJ|NtUk FRiMe0JBf 0y)JjtEdn$*y _ݔץUßƜKt*+}p"9O$L8* ՂO2 2Ԫs_&8k 㯯:.7AqCEm_0U- a6]\չY&+^wUJ5 LH'VgnuVnu}Oi[,1-/8Y2-|pAG×dLvt=ǶX(e `;K \ѩy9췕~2;SiI#:t $p[Ȝ A^ǜ }[ahl4S-[*9;hX1 s_~AEqw^뻳#;wm^՛'cDrArƫE۔ ֮9L%a0XtS 0rf3ըɢ2+Ghl܀uL G7ſ凟en6Ҹ.d]M; NԿW:6ݨSfu~>nr?^u+ܚJJtEK>*a"ҡ"zU=Q3[26}QnݜgF\Y}Lm\?Mq_[Dof;ze"7<9]AczM ,h.q\OUCvbє8Öf* ܟDGc#6NL%wќB~_CʾwْWr1KVWQjl/0u`$ 'Fb+^sΔ)t|F@|4$g5A< ?#&tM޼$6yv hj a\w}JvS5/I RBz%/Znj ͶX7[) >2bhm-3)ELaҮe? SxĜ&]i``%§gL{2qP흭.2ޖ4A#lAOSdmOu݅|p2GC*Ϸy(O'`=#=PLz~s명(Z>9(ЈGlh5btjTFyڧ-@b#/FY/ |<'Nh~ pwʃX=4_ \*nzbb`i#53ց%N'3Zf+`ι֕Y[9 m5lmXޘ[Ye|Z4qC* d[ #`6y33uJn %ţBSKf,99aVQOBl 8+H}yӻ̹N[R.=O?"(hh\g!'?-FA,9`؟rZea)o5[y4u~?,OOQ eAqO=ZpD55'bQxܜ~9QEn_boa7`cEv.mU푃6&Uzo*¦¦>F :R{ٰ0"җq1TUn,ۙ.`h_'(VFByo[wro@u ycHR<`eX$}M™5cB+WX&SڞpRF@9MZyEIO7S%o Yƨ~EN}e_ۃl1;(b>N?yW,к6Y M^%?JzqP4Xey&4h[/oloM¬4Uk߼tsDFYZu s; %kWǸ\՟ӧ;@ae6[RS62YR^yFp%9!iR5>Z87!1$R:%VuAwd7rsissUȜMa[&]AFsRVqgk@Fș1-[$C*FrHT͈zyF" ['gN9dd\ק.b0MIt 5QNY&|-D?mit]rNŷ,Pw9걏c8^ Բ}E:$bUR7[:jZl Xё&ɜvN&<*(<=S8PS:PU2r,t=&@,|#ݎo"$a<_f;Krlx?/n;_a5(E~as'SԜRndڭu`m9(ssˀ:v:J)oAxjYJJitCr }eO/g]J1|N-* >}9ZK6zM)M"_Of{)AX2 W翃B=c~72bE/* ].m>8ھ5;K}Ȅb^5c[O Opa]d5bcsEvь9кE2[!K͖h%\p4.[*ֱZ_!vohA)]A>IvAX7(~ȳ{R<Յ 8 tMȎEcmڽ07}~< 7y7̴G2^:ɫ}9BlT j8ԩuIO-4ih$j aMݙ$"z<^ɦk\@R %:DrZF0gЙZ5@A P!ļo'1h\wk2X\Q2SJ֡ǓVy5Zbq$3t6[.dPʓZʸ@uѕ䞷.ЕTi~̓~Th8>:a=/t\Ztl*/UxQ/FeIمF͆eֿǰy1rphyb?TG@wm3@~WaCE)r.<+Ԙəv`ZmE`>;8kh˲ T OzD2yw~+>97r6oH:vή(atctEPAa8za.j}"ѨZ]hg7~|51up Cm]42,Sf@fR X'ne#ŪOq)3b@xI4K2},cfȜґwnR\bgsEH2Lk2;uOiߜ!>,j9&q~v: m2wQxpw|=J=ŻoPeA=y R{0-㴆opcyNFȯtyd~ix8ؔR ) Sa[-u5:V?[+Wo̳<=%!3:tUUԋԵxJyba#%<6+~pvZK,{;KEcDXϒdP%~ß)΢5m(z@v{E(HǓ|/ʑMV dRiڳBstL{9z/ZbNН%9'UPDE@UwIv\kxY%+U1ѡOP6u~ >>-5^}}|5^п}(f|YmY-&Ֆ dwQҴ+\n5E(T-D~]D24a6#y9LuHf (?g,> ݟLe< .4lI+TiN%umdF_ֵ@N,(ރAktwAFpa\`eӧAn3\&YʽT:} B 8'<*ҎJJnBV#S}{>Wdyp/*ZPX"u.!~]PJ ܒX _4Q=0r$3zCm{Ap?<ӎ\斳Ye}#ZRO;udf¢J7濍PR߭y~,1Z1sI1qIT}ro6v !}]a/<%˭hc=tgKny1rUwT (9kenPk^ʂD<:V:g&?y~;4260]k{|.pI*/k:P!I8dG>dIcXeJɎk|OVfL.q$eJʙ>ah8j3_ۃ <6X],"h^3ܻ=.&q5F*~n|}(J/2WWd>^ג[^;A񬂌TAjVmV7Ђ|^fft{/rIOᒰ%GwGPq\yn|N?L%i[,aWP-uҬ3!{b3V S |CAF='Z.Coc Q?jH\,o'h$[%G$s@Ѩ@E- 3hΟ3Ǵor%:䰭2xo6%2jQ( `q|W QfsW!Qt$E%:<d|CFQQX7㉤';8`!4Ӊ` 1Ru]xh/eؔ}Vi<,q B"y#o]M~-01*B#OCh3_5Q%S)՛a~v29w@򍀢Ey$ |S޽/B{ |~H&qc'Su3Bryy6SfT| mEBT>mEzƝ*ǽ;2n%Kpk&ՙ5g- mH t2g Y-zN& 嬢vCUU*. 9Pt.٬S@|0p *e ˤ3n~ദLUeAY6XYYxT*1LiȮ~(dߘ~q*,HGbrBK/۪s_a3l,Grjpo=@Cx_s=߬^>$i;{C%}%iNS:AK^|:KnPz>.^cX mɅ4lԧعǀ0eq,ݼȍ`\zR/S6=vY枳Ѷи AsfȓYOOZkÔB;ߦl}?vgfkN^}M[AsuvlR½>g2`eM-r&)`Q-Y~U#4XVߍ| o ֋I:gh0p$'̱ԛMj [`ʝ:16!3#p7uZh;FYNH"5r_AU^ INz+ iM wz9pkڋ*ekJMiuynwp1bϥT~¹|1>{,&|/"|찙o8'#hS qy{G5].Е7v\X폄ZIןe`j] vsT&x9Z'TDE3[U|Sv4Bi]bG,&V b Ѧ6Sepr v$ۖI}a:&yR .~Z5:0Ti @݅-. ;hK1#Jo=y+NVVsxmn9Ũt0=lThe~BBcƒl^47vL1MNIjDώ0nbO4wƺ_g v6\ZhV2ٝv[2q~x2z;{iFf@aTO /Vs⑍E} ls_ևo/UpkPIo5A"{eSʜa!#n]h;pB;ІCC }n /14g7J RH ?lSKP[y毯+#?y_7d>=fE_ =~A;rJ-* sFwvh3C`e4"lfWgOW~}cE8ՏR( 1Nt7g!/#+4u<ѨXf HpoλMr&&`,ս 1TUx"^\Pwʝq[U(jqggN{->>OXUh^Ϡ\#Aӭ/_ :ʬӿz:W"B0\&aA^\ soOtK V%74=JRTieg:`V=6vJkG`;=o)h[DCcѬѤhfNf7q㺢Z=O\u,wp73壣RBnA)1ڛ>qs 7] j17 YfN=I1y0UٜxYynڨhhޟL68  *hQ8k\ fz[Cs<&gV߮2O}:b!8/'l|PiLĞl>BcON+j k+ɄO?OGߞh߬)G>Oo鵙Zfk [9PLJH&AϛhX0jm`];*d.PYt3_2Sng0ϗj.C9|Jqܵ¡RWTCӰÞK?,HݞW.s?x.}wʎz[ ?d-Br%n%SG6cI=Xh š59 zT4(֤W1 -Zp{&uEnvy>N 3Cŭ~Ts .s f∾ QF"iOe:3_Nyg70-$2s]֋G=^h"{|9)2@GuĠ_(9RF7G5*i~࣐c6ߜa^t+|?(Qޤ30K/*qPp7aM!6ЌL :]FE.G\\zFw3HO+"= shG. 3e}JȲ8qLWߥեv-3F@0ڵ N +dGT~>/~%t C]мE'D2"*3M\AY'#@[:kÍ6:LP8RnPSo3 }'6Se>i OאZWg)Oƒ E%dXD6]3"dU ||Eǡ`>-TϧnFKr-_՝8lSf]&{[D^s>N]hMA ʑ׎Dk9'm8d⹤*+p"(k}ƟLՔ:3F~\ϴOR "fej0n͠:x-xʂscV2f~|7&yny)"Vv 6xFۉ18#?7N?%̓.ӑZ[ksۿ@uT?Dl& *GM|Ƭ2Z֗Od>'7EQUM7rr9U҅<F3aJ]T)Q4ԤPIsLLIJ|,Gd-HDwGl'.HAxu|Mg$Kzd[DwRz Bz ~AOr};ЈmVjyLwzt&!q˹6oZ6wVilˬ{R=6OdzD릐` i_(7f<'|˱`ksɺ?`m,.=sbe4W=>cۚ@@k*x} _|En|֫B$s@[Y>g}AƢ\*~="3BRG^%W6О y0и^*v׎u}=迸s^Cj&="/KC-)r6ɴyӯ0k(u XAg(`I:&>UӆKYKܞ;M_>z5:O6-ccm[R@^QgL,Kn^ ֻYN^^?D(8`e1?)P~!-e{N?߼EOee+r57s*s9|ޝc*rUz\alQO"1- BgnmA.Pwa6eOIc|.2 +`z+`Uzw4ZR"c&U=ܠiKά2W>Q }%}-aoWEx&gS OENUd<ʧ9[fJ97ݬsE k1\UFon~4dG?U#%o$3 %rRUِ݆D&y^k¥r+sr-Z խ1eduSiCGL},W FA^d)z~.*wm09Nn=_0Qذ>?CNf}rw_뢝>Zkt^E4WG49mz߈Iu]4 /9]˪LjYW~Y9@Se:yMl$??^_oG*PRCy~@&@-z;u\A#c$06] QzHL>$rGpّl#}fXe:~1\eQIy Jv+C\.銦LV"M0EtQUc:mJ^ηBͩ64w'Q _Rpv/~J(8~.7dwS&'`}>ܰo[S-6- SK0w 7El  Qqus_;l$dX^aK7I')r'wiƢXv.y_؞O4nR^:e;6NwTA)E'l$;z ڲeuЫɌ|3aͻ(:`tG: 'J^g/ YK~=/__8dpY8cڲչ#PmG*lYד׈@X^n+ EWScB/3^Ư#11gqks: ' ;ġgSZRWT7:gkyx*\d4I?K NIA}=NJf8-=^;uKcGG. Sf}جwF|96N\`ंG. L->5EY>W 20VjL|Ѕ}rmWE%xJmu=HN$RRF9K1v`6Gʈ:QS3F{Q>McVґ4 S}yܒ0kKhR_uϺLcR`O =C#btǂ1C>{ZP;vL%QS J2nH/^$ՠl]}[iۀ%x~M7n V}_9;q\y+JE~0olߣ!͘F_Ro}< F [uԾҌRlDr)xk|o@JDoMu{h`o3&Dۑ7@؂6Mo_~qk|.o`56%3F J3bx$`QM|l{mm k^ه@&I/7U3&żH]ZydX]qӓ@{uuT,&O#c =i̢G+5┑ZLʒ'z7rw:SH}ָWB3Z'+zZxACQCnN8{: E F@? q H5H4ǟ%ө3``+{.~KQĈPY ?h6л(eZ%2B2gI.uA,9_Ig:#zJ%f=yǟErX=h哝b(> NAV?e,#A8_S-  >S^ 9\:2}M ѺЀ+p/K&J`˾^"8C37V0H`n+܆lOۭE~@-URb!)),,1>ÆV(v#'?5"KƖ=\s2z>'EF*Iɓ؄ț/ykJr"C*_)uPr/3j\]$m8a_6zXfX:觭?bCz0Z4v%>^_ Vfƻ*gH X]̻d{K&*X^[;ͫ|r*4"UNM]YE白rωfܾ7?WO#S+@^*bJd̤.*MzDgNI*V#Sg?x?Z-?LhB5}8f3UhL\b@o9։>0&c=CPNyJ]dOeNʼv52If9ZWj 6 ߼_A[-}";<~s1fLFj.oU3~JfI۶65:2}}o_TK†t7wCw0i!G#3ˇ>4CͩI$c~B{9~V6KOrN Y= =O}oiLPnC{_1&":ؔWgbw3#޴ΉX4P+8뗍Cs%JJR_my J@|OM7/aW0L~K U65ojqF|-qd>A_=Zq_b͠qګˠ~cZGK$U4$տLkܓUP ˓]~LGh2W BzorY*L"zf]kb۵h` M} %_FU=ɤOybW,:?%oF p*I0U֟&o,́*v41r8@u63=-t#Szn>ZYӆGԋy^ Ƅ _y~X9'q܅%Ln_} a+<B/PG뜙yt{Rnb֎Ii]>tM%9;D}dբTLE#tGPTWooXn7n21.k5<1>.kJ "pTzdz{Fܢ KC FC#)m"^}[Y7;)Ÿ%~p]+L0+Rȣg1G/aas:4Ltɔ"VU뷩 ou^G$!(Zks{d8KetPE_΍Tm5e5ƅb|:?SSeV{|fljhR%Bk6Npo(M\&DŽuUoE*+B*U|҅ GʆWm*6v456KĎ|a,OY%HQ+F(|wDEE{-? #к#7-Kvf`ޠ9mkMrvyIea`\V;^ ʦmDNzͫ٨Ib#ͭFfvBˁReCQ}u{t2(UP{ZO+*[+/ˌHװF6/&r,<c>a3_l?uT3usX5HCqCX4BI.-]aàhD|.߉A㿊A *Bq!*uWJ?m4_ʿo¿V*+D CŖ'?V_.IFo,T"Wj]PL&eBPp?9NdV48\tls'X;4g;6}m6w) heR<.>#Z*!e o ^׵Xyk[Es^''4Vx[nRLLM1qKC<+oͨ> ^:NXzb:EJ EpK99JqLtu$S-_A"e Az]l}b~~ cCxwʻqʸм~,E͢nMaqc>za VrmYۅQ?pXC@Ds9977m`v/ s[a76L/; ͌evZ9ZlLo~Jh7QWF%uTe~_?&6AS-{_r ΆPj^*^2ȭo^ii[O 4 Lsofm0(t{oBqA9Z?]\Nst>RVJ*~g,6j+4v4M%۰@r̿߃c#vig~tF3.xoWu0tw`uޘ{o2j>_H5FIQ3o1W^CsA}]e907GvSFӧN'b#=Z^ԽRi!9frG3f*deNP]pbґ-p/ˑ*c[XQڴOhE'3|Ya+׉7ӘCe CqTd;}8dM Ag@¹( L'N)٧vU"'W'q|_u:=_˵A"Ij}4k&|ba"4̢aRR>G_p|eumV³[Hi 4Ly;~k;՝VG>ݝi;GEs4nc1"dV@G'8(EF} QMLǘ1Hׂ]˱oPSl8FNTμ/1\=J_~F9+l?uL2yzyzZ\$h0_ޤ2p)^h-D mll>kp䅮__Vp wخ/0Ci{wL+ we-8yXg<w4* $ĩL_\ng@XQkhyі[Vc]h0sOz#{ \d46˾1_i XSHEJ m;;n_"C1S ̉c&!z0@Q$=EC(RBR:{![(no=ѷͤ˖@bf1S߼k"2ZUr 8?;_#,3Ȟ{EБ$e2ZyMW L?' aWEh amҋw(+j]yc.Ƣh~+1Lk].vhk N zBdaGh|-$s|Vagӻ= ͫ4rq|UEL84QbO-QK/ 2r/K 2v~S `ʹuEF~]=k4BrWϷ5;?qWYgۺ>3 A9T9oNѨlf r#j>7ծ{}-h/ dS+ LL\=k,s\Xi'Zղ {[˥N3j!F8XKѐѥ?(]B$ 4;!>tdLed0w؂n{Ө\=ۅ:*_; m0NOhbS4En`z||7_rpjۯ3jȀEFk{7_V+AW'S4s20PF +LuƬ}w^:T7}\8f]ddaKۖ \U~;^bNBޖwIP`pZSyM蛣Qp`|JEYMb BmzfC/|6Dw.q);VddT,IPCq R}*_;lrtv?LYfj(C}+Uq"#shM m|r9АYP^UiOBvMDO7(7kTͯӐԥ A yJBUDy -1yZ/q0n1-D9o&T.TӤE&xQTO6uFFJ'\=8x/5x3v^V{Y1Vn!$8QξFՙ5cY$R.o eӵL$G's]YPݝ{RǢUV:%Ơe>/p*t&gi\65QpGH7Ж$m N\=&BwjN&8,,.߯!_G~ϸN)E9(PV?EzK[Kryڪҡ_W ==a'!W$X IC1  T1&nSؓFsðF1eoȋ+lבC=zޘ/^ĕBz%T׼) i0Sk^͏!78%9hEG7-ᰛ55m)hg> e,,f!1NR'B\m>z`L#sIZܜ 67 {;GUهƴS]4!Ӽ"oPT?Bܼ;B>B~Aba])ΰa:݌"3m_#@ ^dz= Jy)֡4N6h+$  3^@-7wWt&V##PPlsȣ|q ZTs!&Y3J]fKCTʠ(=͓>'-ʭCPnxw%Y]v"qkhed~b# nmڹp&u &1;>/KR+ժƍUU+I:ιXo]:X/8.ƅ{|WtI SE(U< l+pH \6֌yycf:J# HXB#\vď =Y6N"p6}*K;{i;rC?yQ8ߙB{Y"xN4uT2Xzw!o,4> \+Fam., *dh5&LnO8`Brm R?=E*hI oLR)4c~~~ƻ=ìXcUVɨZLD0#OqX)elU5[l;UW_F'43$gFġKv}7sy2gAb.(vXQ'~Y4|LO|h+]2>9<͏V!ږ؞!A$M$ e?+>+>wm~'MP[~Q=ĶL dc7qHNn;/Ldc:((z74'EN16eyN#Iq;tq{]i!OyOh涚Hd=63ןoT`I۲JI_% \/j׆M 4ϟtvrΠ&=lbXg֪E]z9=TF`3KRkzm>Fx q:{{ק!LIC-n;K8-(u)jɝ W>3 иH/+FO* 6z>ۘjGcU)%$8$,C_o@lAoE(㐓x*a:edaRwvkk03'" 84-EU,^+Wx(n-OJ\n[-9қYI=1ry_lL:a:) ^ *ݲd󁰦%_ ۀmd3S Oxk}ڽL'>H,κh3W:U|p7|p{=5 "3hj9gyKwCf~^Li% *j-9Q3Uo[Y8tcW Kx\Oģ]''uXONU_,P,C`wVnÞ'7B# '5(nNؘIV&vY+3:|C/1o~XbO7t3Gh쒑{CY@YF]p695" a!^杁Oxb^[nɇhGu_zщCBPVG6 -|뗡You%TD ؄:S(w@`iBwy2x`8'Evr։Bcv ?|u2s~`2A(/~[`ۘ\w8 3xw9S͒Cy\d4,,31<};um"QiەQෑlommTev#& ¬LJtMh0ɐ[gN˰kO{qçj8fghK%dgi"xGL AVU$~ '$1`"n7wa^e]\g\lihƽj;wK턓- jhRfvb y&e},U6+\j 9jrhusUafzX%e=!>c(6\z<:;n9: ;K/`lA2kqwaX=LLІss 3cPnؤ#α%L`KҠP9" juj+Yqry[#ã MۭUQWxE~a'=ޣ3oS^LѺt@w)/Y듬6jTeut충yݚTIL̝W|ڠ 3p < P_ڝ0vU+iϕο.]-rp{ Z*|].)#W]y r m(T~c㦝#tza60L jPSW푷|J|ˡOZBwK m * ΢&@nW⑷/9,1 sa#>ҽlmCīR[:HhasJFĮPEez1zɫ>y_J8UGlsflb8@Zyr]ǁm@f^wa}5$i~͠yo\r'V_wZu?&`V^ognjiŘ@.2ts.*,SF\8brt:1YNJ`>D͂LUQL79rqd̨VLJ 8R;J92r9Nr٪pR)'/>VEmyus֪،LVːȋ 2S֝hhMyTf1V}|Zb;6Ԓ5 ~Vix;6Ռcc9tѠ0{M.tx[.j3_q`qewƝyoUqg5Z?hpc <1- kH+'b7J7h}o_(zB+m5Xtvy3߹hOm'lnڍnD5Q2 e(IX7SDmTE؆?~҆ ̴$#q͟f(>,t0bW̫P<\+n_Ђ<#O^^OA狚d7S#xE꛷oICos!܄n["p(V\7'qDC˳|kryR 6EBcS\%2e[Y(Sd,U춬,ߎ_,-.p9e_x{]:gkLGpugv7 zb?ڻ iЧiAQIL'6{B,֒u_̋qmyk0+|V2ATE6)z>@2nv4|ȖJIM9ƭ% *iG̮+oTm,+HJg;*~gRI󓲇ͬ,8exxUU_2Ծ~.?APTFr߉qqt;N\*99jw`/F.](F`ː"3M.tq:lT0+y?sGHyOI08^M qWxmU;x -m,ӑT;xcע]p1|Q"o7FrtGkK|j ~$m iaI"̖xjd+ As<ύ]BGbJХzoh)%܀F:ΉR F+xUUPȡMс2;!^ B`~Nde7I$q8N,꽰ye&bs{0DWw ZޔTye>r)!KZIHӢ@c-~"OcPI'.> ^O1 xcF{.C˾؂ŭ>ҰJyɗCts)ۚΩ ܍a'mY,'soJdDC䪅E}lLMNtgJ{\%EϽǩ& А՝BwY=^vT.KM ,$6'&LN2/5~N)6X> 1&vo>4B?/ŁTj{[ S8G8i|d'I9|gVa=,;U@8l$1@"Q$A0?/Cp2`xЄeȸ㈎W)f L[;efǣJǬ\aQNc(ݣ Y:#E;" OI$/IIPcO8sЄ!Ya (z#(zvUt/%zO^2M&s3V缏ieIt^N SQN(o=7g;dO?\j@Sˊ "QI"[]M*cغM7|c_P$(TEa,i%7x%'Ĺ^Bo^ƕ{%!5 lؓg l<g+!=.C/cR{0B-q/PbM.J N]QKR||vqŵ Ciʣq)iexcCNv 3$%(G*WƴT Iuf9/.ZhL{-{xR:qy}ۓ,@`.h}VQBWsh=+ZO$WgL㐯dFVcYJڇmTc{ ,9Y_W.?eE(&1-cΓZ%YG(Oc̆nPXEN*{=iTHj|=k0|hLȏ3 vDQS/ϛB~pX/Yx5bG43lbSOSٓF/H>{._ ~ûSvh»eC1"mrIy+S+< `f^Y~AlkO<;¤W)B7]υ|߾6'eǵ+٘]^rj90e3eB 1' r(UWm^΄M%CLj-C[y(TxVX*NoY-1o^OVv_d9v vj"\0Jm8*˰HFU > ~m1Σz r3K/|@bܲFZ:>POZUiӛR5U&J:8o[vu|&MAq&3$g0Eԥt). Li'uSx&<V-{qqL%2NX oS^yEOBd&@i&5PNN%Zv+h^@<'e8ʋ}ʹTea>y)*H[U5uD0I3N/d.8C}tVR,fr<K̈́JrзsHdNu*N9X%ȯSG۟ty,JexZ=ӳ4>pL2CxDS| iw4[d_'hM4:v#R}Hu,i,+m:vsD$h["?, Z&Q_K(>ӝFYںP%I*tђWmŸcE`Lqk#qq0|mB'Y5 ʺɨо@ɫX9,JN:oo6ud,%YFcaV/^HM7:HjK &)tuzH2K*f(L5ok؇!? )ѣ%iPYPOw/Ls7*WeC zMF1<_ud2YG+/NɂT-5:[*{O ~h3EMb8˰VAqrF\x5)'TR9VtbvEL$ wS3_g" ?CL}I0RŠ2^7S/LTC!|L%fݜg)rK{to*W LL[u_fFCg/-~QPb+*l{Zn;=|^eΥ8T•.joDzd*dB\'ö5WҟH=yޒH/S0ˣDȊ,F0KҶdo"! K}wJ/'pW:Z'~vniq,'ٗ΄F6bUqsb5dḥaᲙ]&keR cUZ1naz4YYřڭaW{Th x k{ Xdr$R 謩uyهELwkt}LxpjT8CQݙڒ+r3;r]S۳` !Jkښ74STMcC I7СO1٧Tdf4Yldwl.e΅En9hS5&>D #ywR^B@7ȏ_U+ ~ɓ -%z%dPض O eT{Bl iZk^k~C# fPZ#?gk&a7ݗnOld(GhG-MǠN%R!;VV$uTYǣR7n/H18 vEci_*Π0QY":n~?B*eNجC C>VJ>m'BӏI8A`~{H[XӼK}YLU h0 #}p6Iһ 9bHlQjlﴴJS|fs8A),ץ1YS|_>GއLuW0fM#>#*D[=>Ki&?ptLi=ec80v/X)|ǠzA~$^q@AUg˦f+n# IٞtԀbP̛X35ߙ$IG{EWpv ѻc/8~)Á|Fm2 {p^Gꪼ'[QN!8yMb]QSC5W؝䧍y˹J4:J~C;L횩} odJqjao;B@7v/6g7<[W~:J\WDT w^jPJyQpr_zdgA9"pɊGU+wTD x=8w~|0͙ Z0ijCt1;K,W[>t۸j^L o^[\.tPޏ2כj'&[#U1 tKkQ,BiO¨F|Ioklg7][ j fNHP!FBCxC$,JAAW-""u=l-]߻cm{"ֵ1NHsmG=aʜww==v4p=fG4߈""/ӎ]iꉆ ~2I鏥NHYo_l/ltה[8޳L)CT>KYj<Eת,n |1_bpP^@S|UYvxԣ"R,g3<[xǢ=ϯ|zq4>{14 \ʜ,5TQQYyq3胛V̄q&HO°EK_"RYbH*ao#1ٝqh,xt;ehyAineX05~+`m* gd?ɐ,GEۦeWWa[:ֿpm_OI0PΆ#tEh-oԍi>/6蟟R{ht.ՃˇHc&pTRBֆWR>9==зG?V^@~4W[ ` _UUJK5-8W9艹o8^9 GPs^ff*Ɗ-S  KǼ"#I! _M8l~ס•4 #xAm"l~@nf~Iư ~~ SVȖ߲H7=T)ԲYxrm⹌IuJ-Np=P "cNS( <~7M4*_p.-'h&nb~Qn\?ٴ }Dpk2!3Hm|_6]I!QԜK^B 2jz{ʀa:_- f\CBop9LX:0.=$@ɀkF/9Wд-&dd0 |dZˉ|D/a\o(ft\3JҖ4vKg  J'm{Q LV~-Xԙ A:U#<4N':A{2b6:\_%gx IaxbM&Β)>'i6MEkR}5GiOUҝŇܛX,٥MASӽ fBMɔIq,m*)5qST_"(󱬍yIC a%"f= h=NN 4B7awr.B}΄WЗV-az);nL{!=z:W<{-3B̚`*Y4ơN4QY37yyg~zG[ yƧ&)'P莮YDLuZ yX5l2)zt%K[Y"̙Ң=W8=7綖V_2z wʿkcѲji&4{ކZnI!}\B:t78CxF;L7ȑL/nh S3ߊ*1K~`roRRi<U_(Qntkc,Xdfa'CDžE51vq6ZWO~_ϸbHem32!GBlS^β4|*kHӣ>aCTj{/F-ٛ(ebXN3z^{66Im '/ )e3nN4fccg|m<êFvGV*[)}˪qҾ!*un7%"2^$$*.o7C7%nInyMjs븫_S yF>de{ $~L\+C`njAuZT 2[0SL{@M#SiY7u4m=htw4f,(,V 鍖MM~g_}gmJJ#] sV{ .zB0jBqg" +!3s cֽ ȔxAOfC,3o"⧎{aim|r~G};!*縳Xׯh;KIm+'m.{_W6a G"O 5QA) Q?QPnY`7=,}v\eBXD:/C~:w@DZ 4Q˅ސP>jʇK\pqag< 7o 74^LpKcN˷1u1B1LG;VШW%}6'ǭqI/Co}Aq޸@~˜dg4A %W <3h~)/qڝrAO采nLjvhţϜ;)Fzl6mǧP}^n6`r`8auhb>/f5\KBGJgD*G_-3>Ϛ9%`c龭JNV Am qV:ˊKqL>}TЎ#7Tt%:T>Iڶ :bY3EOo3Gχ㰡5**)tˋز6Da q>oNlI3Hxy/?>j4kL.oܝQ l4ݧWǍxP !7L}Em%/' Qno'PQ*-O^1EǠ@K&2t0Ɉ:Y'LNkeF/NUEv_az8P%?tŐdd`zH*Zo?pFO eXMD0#+0 EXMyxx7_Kx9SPʵbXxPuik]h`Q`3Pz1{ڀhv^~\\\by,Z^rkB8lB& s@53 {B,]hH&qԞ3%؂IτkD*B ED}"P,T90F4` `\Ƙ"y(F[m׶*o̫!?e |<=1S@3=+]:3ofghnuah&ƽ孔<0wSkǎ\\d6Rff>Y4aC4&~OG726n5Reܴ FwcU@) wcmE~u,H[v9=n^jtr;! 0MDj}!8E霓J+tz_ml)vCX&N]4sT"T&63O0v/9I1RlA @r%C;WĂiSV|y=4Ǎf2s>TkkddD ̪N1,F!=f/ E4Mc^9E-ofP>R:N7İ&n_ I)byo7~eۢtL@+b.5ׯr\,K J͸(ĿhCv7΅{0LL)6A)u ^Ϝ睾1b~$r5b.gˆ3 #F@lJdu ҅bى09bZj%lq>m_Bw ʻm $*_FWpv[/JJc:hA˧n l!\1".B akM !N+gnN5w|w*0,wY +J% 3xElgJ4MKdcJ1:i[R/4j+͒Xy朒6MLܞy*um*&+qdtJޘͽO/w%M?YNvOZp>WEvrHvaF-z:Y#2/J}i;fZ%XBi-?' %QCIYꨇڹ. +9UkJp}$_p9U_X `=zX=˭=-7_b4흿Ӛjܲv  }?k' gR^(iG{!l?@u&dij>o-VFkqywZb,ohC "9nПChWZ9c1aefQVNߟVcYs4ӪjK u.Ly.#u{x#2\wicr?'3G4PqƏxMnj5%t5h٧w/_&Eu2[+utV/KO:uwd48+@ $@ҡ)ͱ Sc"_&Aշws|k o@jPĥ/|g6#8N6 _ A"s4wڥEE!.#D(=c3tn en.1`+S7۔*wICr:Uk*IՎA(7Gm8757?mUӄ/Ehbl8 R vi{N\8]$? 8Z{L(UsgYd|ݢ'\4Cʇ ŅH[5$b8 4cDu)c9SItJjȥys q$D&\P\D]d^+Ye.PBPBAA*G]%l}iVUR~"U'y{(4AE ׶b^sũ"ymݼS 5SߛJʐ.ZvucP+ rZi@#*=[CM(o(#mG]WĺƫˋS^@v^%S1 Bn|tm>3t2hFLo%*>V nE[y!\n2ǝ-80tiQTvD@=أ2]=.:"0sTw9ittL)޸6|o̷c}͇*woy+-GHlvΉ# hxt]Ns'3v8`^4;r{~ \gږ-q'`c#?; Ƕd=1=1"زLVm˅Ϝy:4p bl*t iSrn$NAwI5fTVHbKBHO/(Xmd6lBm, "{ޜ*9_4ȹ }le6(s͹#}v[ moHC ,yTlӝIlEJnðr5J rܦ2L<>Vh jV Am>nLp({*yE7AmDhvԽv %F 4P; pBl!ܺs.x!DXY/z77]ۡ\%鑒˻lolTo*% b(A)& X'Md\SSYHuLҍ.wIL[n,rq aN:[Y= Ȼ䎸p2ٳ`$vrXTV, moA7xvY;զsW~4~B9=ܫɉ-ZvY7lhk!/غ,3g2(>XF|]8D%VOr'̡6qeŖ^vŎ ;9w#K(Q$noޝK1[{RC|5/zHIlˑ8Q`乌cNg  %TrUR: 1ڙ ˧.9/3!clCvUTˠ c -qdfWY~' R&^xz^<ݜ6 T&dH7Bd/.i"jAaF)۰V"CG{t: [(b9Z`']ui[RNw f6xC&KL+1כ 0ѡE*_{}4ɗws.Jx{@]“c* fIל|͡qҤ/.#]ްt;tބXn%jP X4(WROdhh \LU&WIߟQ罤MC;=$'1X}m<_#xVx )Ct $٣X%ׅ1A&IqM&ō)7+x32ByWB9wn@9.K;@eޗ^ZB| f2 ɺy(d`LMhTc\F89JC n8)Xh6e|,gHӋ@'Z̚tGZHN4D|"|$ *X•[pehVGs,3;ږv"+}S?.E¿է~dnƚ/ 4ÖC[_!_' oLiw/G`Mie<ףHU52Ǧܺ)3飒}7pEt g8n' CpTA)LWl,(,ǰXq.?=LXybTR؏zx%É 0 wc/\Z֍.,\~g[`wɆq ^}/q0o)ݟ`(s4R_o-}ZUql#բOVJ)ϩ\BuA*К2 br+M dٕ;}-',lM+Naa8eC[u+DeXU/{cvд̋5xަ,X~uR'hW'dBF.ew28p(b^q# eQQOl+!. ǖgzq J+, ;T}T>#X4"?s^ݙo4&S+<50EtxEЈE hK.l)?|2["0tyX6^]d~ZT}θwHm*K8R̘.} s6TꛗԧN|uhܤ  _ڋgI0XnҤZ\f[N1S0OeiGEQl86m*#)6֜ 0@!S){ze:08^-ϐD^&—  1b HW8{K3Mf7DX֐mdGy\C~qAKFʛ)܂NjE5yJx|Q6QQƴVyfw*ĜKOW }Y~Jkr{JhY~Yu7nn2bmqn6j UAY:;j(I^KRI6'n-bUi‘x+Cg󲰣G[d),,+v M2B#ʪfv=72 %TWQ#KuL=›K&BGi)&W*΅e(ΝQW叾q \VcIعbԁ_dISC 9"+SWBwвs( j+8Kʽc^#(fɼ6>nʉEE% KJClLa#G]@K nTCB:!|eGҬ[X#֓3rK'QWCz (^eRNL:,^:4YKUM5%zHSP&I8mA5ߛ~l,-oe^f$a^(mT-Ư  Ue.M/{2Yܫ^or(e H=Y|Ky()grgZOT ϒQF 3,܌s@"ft3y-GoI;9$kLnF̏,uϗs\ǻIfU&:Iͳ\O]V4N>RtҍL(+7T{Uyn?̕scSrc+@#ݥ*n$pUVˬmqGrZfM5 bެydSteTV6*; O$"u,cفUd"㨳]%OG.3QL09xԘG݃/tЯ7#ifLjcR)G`΅63~yFNjwH<&Uve v =(_tvie>5o P|˄G])e35^B(~Ҷ j٤\`p;,C7k5YX nN"0ʵ,+.bvf+$ƸL>e3jw/.3vW<JG"=\([&:.!Q8R.VH75jsLd!3jqAB \9կrXh!r<ڴڵ?֔69e>f ݾׇb٨|7VP}f|^6yV T:lfkqZ\d>:/AeVq_;a(}؉Iz!4,4/rhN O+V=?q2~")߱%*լ:߈ 4݆\(ɚ$ FG RDi Vz5ss7 >6j̾txDeD2pG$rB9fU1Zud*ܚtmS"Ez*]&(/{f2* 2YnAeo7KB.3jTbB]f^?+ү.: BLs>`3@V;X!];yq[ǎ2k 9ݚui5s `S(TpÏ<1.+$5wSeɲ!LߓICyF=A g#םQPhP3]x&PCe9ѤrdUQ)zCFy U%bdy#Sq Dd$Ty>+r{ٰ3nl;]Bk7on̲M@?y^Eb19zyٜ+qݺb:rC Uw88)I- xAdj:oI5<^Mo571:_VUkiV J.+mI"AjkOhvehʇYġ_aB2dʣqK;Dz#Hu{[Ҟ_!ڪewV6{WU&ɫC%WČC64[uaQ=_I kDKvVQfJn0r7Ade~ӽ* S pƻ@{թRGX=cg j?H ^sCk4a@DwnB]u38?dno},,:ϻIEU19`0Wq3|p2NBSj+1+N Q#8_؎=gBdo$73̗bk)86>$HM*6&佲zhIޠRSc$soRajGaqfga7# ?vN֪|i~j&*S:)fI ﮨOǂ3C0]vːE(#^JCelXv3JnC h-f+ߘgIzs+"9nɳ zuK:s@w3$V=l$r viTS7Z͗FslϞk;B8?DߒT Ns%Js!ˍ4!)u$@/2h=dZdkM8zLȫ;FvT g `(I(x}͠ݟ63'/@ iR Ƀ'R~TJe/'gȯW3O/ G䷜3+ɔ@Ak)R'|J^]e߬KZ 7uiP#e^zqs;Hn8n!7ӖI\#ד0!k峄@!٨J>/M w ͣ"n>õ83ʩgJDXfJ+9,0ޅ,OEYe>rV"ñ!2_w1Ä=Qw{KHS)\XOؒ|*9ZlGxL4ur 菽bBqI&%Vٹp$U滦N.Trх\f)QlZIl) 5eݐr/ 'xZ QWEۓHϳ&FMtxدa 8p@ OZAϼ3':@7?7ߠUݤds5nhEpVHgs37'ߦBv'+q#r"ŲEЬeVuvP1}ʆ?f KM(a)7}uo^I?yЅw1!CQx!2eԯJ_ Ϩk^gĸ>N{-.O3qw: ᄦQ3dc2~pY8P1j7;6ոo5J]$;:/mʴL1_ܵ,V7+FQ4P D䇱=͆m 6LOrϗY;u @"=/͇L tE--˞HSt ~IV#2U+D'Mm@!]FX(f!T7T"ܛV |km#MuїǜsWD=-D2틲ˣ)%@mzݑOzH||YmvY7Y}` +6P`&԰Ak2N?4c vV7}4/@KIy˅t ܵہa*15G2T wtj?bݱ꺃ՀXŁ VYhVE; lh.{UT]f*ϐUr Zc8tz6D:i #Bf(u 5+ dZ=٦[~s ]f5JDUgՆe4PnO6vm[vxtu@Mdz9*]Q,jSJ^?!cE2_ҝE>LGHłZGHn{:d^UbIU\s&пP!]-(P|/LJyB{ZdA,_ZYL.<0 ˎbNZVer~88w?ՋŹHKi?5f8f6\=s@Qd%}-uZfƋĨtȳRgBȪ P[n6X*q RD@g }W2]caReF^ɯ=1TNl2_y7oNn ]N j dLQݘ̯P~Iz~}$zt_GYWۦK?zfO*ڧEUk=w+Yw7lU.-HpJ>:G?=h+hjYYWFTlQ z.C, &,D.DePE ΋خ^8\e֬L;*Ϭ Q=7`U,>"_5I$oyKF2OaDZ͵ꓓ|#(3AMC5VIJqy5d.lN%hķ&l+m*dErF Õ| [6i*tG l8ִAx6e\v8f:u6?oX[Zgl2g4;omÑ-h9AC%m:+6Ӗl_̽"Urܷ7| bͫfs^ m[57j7-D.y#39/ +[M7Z,k" f|4+ yD~vкЯ n.ԡ*ATjV׍Y;~%pS.ͮL ď[Le/|[SqeVeG"X6CJ5I ez61#JU_ qY^ޛ?Ǯ=:Ʒt&2 CԨܲnmY4p"+D,#_x@%UNel8$!&򜻿% J)Pn \˫&Pm)_m04-w+N` [P Uդ=?'D3,SZJ GcwcV{Rlfd& @kQwӆC@vQ?P\)(˱]8Fޤ9rqd4v3dK/92tȥ@xhϧat ~ѝ#X^m& 5eaQRG.R!Cϭp2q#n~hnPR^*/fRYd>W6;Cke(e'q'uk TLPݗ9kNWn$i$xzcmGWk'%|!hިvWƂ=/ǿm53.[)>#J"P.'eMUw3ev<4'SF͆'v="J"<皷hXliR3_^ omjV@5d4k+}y\=zW|1v`ś2Bx.=c8\A78+&0+巵 ZD Qc29ZaSXl5db$҈ko^{3PSUm &D^] ڒ/5'A9}l{$#jX#{ɘ;;16֙;VV6嚫;FS/eߤ{cg>S"6oeeQ3 #lL\f_SUˢ}/ye(@ƚ 7;}y1֜N/nY2{}c&S z|܈O/? tu=2lT+"/.@H"> jNs1ocK%zq>PhGo fVj>ۘ͢ˬV0\EAe]iEmԺGT0k7jwA7'D=+V3>tFCf.K̲֟ @.hwOjV3?<z2{=&צB( y:rh`֪ls:,^>OO 8k@.Q '7IIj"̩Qϖ=al2BAV}0xI4[yF"39(FL"ca5ɞ9B/u,5˜x2|!yWs4\.˜OeS1v}8h+` jbè@8Wd⮥ Z锚E~E,J (ױJ1/.Hs) Ned^e>6jڋKT 2l ex?+m豞 *|=e74[%3OolpMՓldOj$ZL"gKֱ݀aiلH4 hDi> r_jB[@nK/]9>O6;![9Wо_bh7q LWS$wq!8(X~s(և;PTQ}/=7r21>`[3TQUl2yI01YK7ǦǦ;kXg%ǡpy4؏M4 Yob`p5qn-dk}{3܃9ak$,ك~ qk%FZ~r/(59{~8t PD/A:Lʉ'/Gxc(șۿa]՝|/2eiN*ȥ)dx D.U7k[Ph .|ydf9P=tWGHRLArQt˂[nЏL/;*(6dÕZfEY}QhMѻi8q^U PqMUE+~jɑpHMyPVYd<|ou&k,-Z 'M䷕B% ,Dl8q^5@qNd Kteo'Z>>?rƅ.Ve&Wj7K=*N. ~V[*NkӈeʽLt̫rvPf)>ywWMd[jq_,}vgX41r* h͛YLc1΢#8PݖH&M\"iָ,mK2m2"1ў&\A}M2R+٤>ö(qSӼL&F nh9aM~t?s%S/jS #SJm+I&^-KkBh\*X|dNp5_kuJt 1C ֫ͅH΢Tz6z.x!G_U?D_3xaiF;*5:)2I5d}'UE!zKsa*9gg y&MbȀcWK!l%!V1hDwzJCS*I2 @hרU-`D*{ o5(z*?W=W: rT"ENAcjK^|Ǐc0u&&e+Hp<ĂWȺdF(sNB%4qi27uCӞ G[y6lZx|Jǿ̺u;T@*\d/ v(#M*DY\ۺF7\`KP]YpV-HS ![_S\! UʆK ĵ1) '6>YOea$9+MH)z-tE0^oFtF ̊䖋 p1.cz)t4dXաK yiFyMS]}k􇼰G6 {p 4٤'Qԏ(1/yw&2VE J*PB2%2}-O̶zy_IpV^ݞcHZP~@lCy:_ [d.!is3fXUߑp05Rg] yz0Q4Hri6:Dw? J%& ZGƆ@fE|2inZ7s wե )<~AVm䬪ef7_ 2YsOutʸRXI{q, {v L}rZAuN3xh'Hc&m:Tq8_RqMFvÑ_'?[uyhdE`u']oUMQGn:-`A9F:"ZԨS|69͂8e)7ejA Ljh*]kN2.ѽSը$vYu9CfU[&xU E.kuXW5)IwǖŰƺ:My4R6.7GÁtJQ? ut_6yjǤcS+xP(*q[x([ʅ Ã$PYl:\~fJ:CC?$|")\U Ѽ3 tA]wpkTǕ,ؗtJ*?4T;uˋY;CQ4T'+?yH5GuG##8@Ra7 2Kwh9_Y'26&o%FMӦ" v l̲];G7BbeH}L| Tscł:Y32eJJ݋0CeHq"7(fEVhFEPK| ^L?TO3$if|:]IŏOhev%\@79Dγ=)xE%)q707SiicÌPK]dQFK2t7ɭ>cKo,jVI5xy{e ELTOS> j9F*j@6gFU= ]]H=u#GrfSLV\5>e}HDKs4?;-Lο+39ǃbmq(08OEV{%ߙu<țrxiLe`MË^) % Aȷ F+y0ޚ]b؏V?|˫|+I)I^!-;Tz6M-I⡄HPM7[hf-[]f8ʝe[K%x ]3B5ՉQzW]|q~Uv8\/ރ'Ey.3ixGCTYsc*Uz7 L:>`&ש惥+fIPT>@ ]Hi^R(䏖ڀ7ld/5w-!ʣS?,JB˽_dlwE"pNjx=G}n͘VA.$HA{l|l7Nwj,PC~CRUR\(zk9I<t]V_b#9Lx}2S/CÃy+/v7ϝaDSj;ad 50Hzg hT/s#n!9Ώ!C]nGC "0]S- Uy|sZy;eeO΄qADE!xLI+F-|z [Y_%$cC"T{ɶz m_+;3:(H\DwR]2 lc,|$)3 A!ٿǛPBI+Ѷ9 d*Uq< ݡyߜ_b>,%߸8׸k l}qV~tk(-LnXrBѐ'9K@9Nnzhk&T='/ FWVtUP;C+=${ o^1gs*g%_/ (߀~ڐhU.6d&Y0V`aKtepBe=EK}o~:D!նu͝f*ӿ_mS^k;|iV*X" 2 O/BƳÌߠ4$V̻o$R8㕭CO])٦у1X'ȎEu&A5g@\2m=YJwc)ѕeVslwDfq6Uc Cg? < >xt0H>`9c2kO \_lR,WLҋnBbdyV$YfBۢa5&UUSvIݤs_@I!nu& ǜ=c'])(͇ȫpѭc{Ofö -Ϥz;\*B*+->ɽ*g'#(='ޥh"HP/dln6)Kh-y:`Pz$nh[⣗. f6淶[RGj^=o䤳+hS1/ypM&O,ξ&3gRA frTvي}n[ov]Dr=C hT$"#&9*7P7(-mv6mrYͽh؄ *r ȏ䔑i*Vy\ȷI^yNMKաo~*7PaDhWm%/~z1AѸzVdO.cxY!6RQm]تjf24NElf]fM>_ܴ.O]Ib2tmkʕVŮ}f|9yc8: 톪b u\.+~NhF7ŋݟ<_!EF'8m@䁅ZIb7 ٤ef]oB)!qVv6-4T?ẅ")6t$-Omu4 UFZIfvЦуsJ$Zy@Вn;;*XT54ozA6zM悽w0X5>wݠVCz4T**+/4E5t՟#c^dÜ%کv#̻`64= ٪Ԫ{3urbWSjA>%;B[ٺԣԵʴtQTF׭9Y\~%y 5~I.C h1([!G!t_.FP`cM0ꦞe!Y=R2MO=!/w"/Jѽ3tpfE3JH\wUDxZ//+uYܾWDICEl5+N·KiiHK9 {N÷1&Xb(soR,ܐyFa'o5ޗaM+F^de0,9GMQ4!kΑUz*x4HU73I;ۆG|K-R(EI/Ǟk<2pZ)&O?;eglmsHԹ,sW@[4iS픜 )o6ktSf2;fLݪT}rtǃ|$}e S&{WI[^5jmJKYz;ޤl6/(&,]jW@mxfИc΅aeTs$K#1ݨnF3' B1!qHWplgc|mXl~PҪ-q&YʻZc,{,j4sضU7z~Nih)^؀DN7:4DJ'??*mY^6'֙=BqӁ3}xJ>k>zd;!@ D\WOb,8ިT}C_r[=^;9ZEm:x{FWxqu9?'j-<% $*nڻL0D:5U#%ZIlSzy!5fD! yd~7%c,m~oH͑A=҄m%S&[?+,IVLuMg04PgzO(„sE8iYB޷ꣿ3G jNYҷTo7 )TZŦ|PlMu{9XAe>!JVwLsåzci|`̗/wA;U! 9+')}W Wl 4@_p4Qydej (/%?f`Mf^DȼWBc{E.cT7fBPlyrY7/w!5Ofbڿ]c:f6)FŸrRSFGMn@[:1P2fʋ0wFc~M}1-B><2rͩT'q%Q0XCe%)#B(gOc8L>*u}\H>EGNGƦ7KvUG`Д\.Oy\eFG/}E}^p:A1/aMCmƐͥԊMV$wjxWmT7I:-{q/:n, .TI#_!3/;1eUgH=,&-rrM=3Ei 8 zśT0SN(3yfʾR67*a ɩN;YdnM%ȿ+ NiU&(N9U4mUUaL$R)AgsHVy6`8Á\ZxU}b^3W0"5S;A Y.Pt[s"a; M@R!*`M\X+$(k=b> u fBE;+|t5~H3nXm>(ȇZ?mֽ FO]G~Gn;'dDbyEtVI"W9jgHem__. Uõѳ?28q Ӣ^v)$)6bn.Eھ4ÎmLe8_[;*99B'df[PJÐe[?T.+kв%x쉹[o;,3F PEyF_773~NGDS51WDSuES4 gE_axE$OaXd5:\xu,~+coP4sY M'9>F?zׁ umJ}KqgxCxfAivdleYj膃z˾#-. ^.+P%)B,dJt^\\ՐeEE|Х;gAw^¸[X[XFJGҧX۱f'6A%Yt?Yߚd0FdUz$z liTQ cg;oV w2܁`d  d_^x2\}4.^(Tny$"h?mFޠhh1Ō[R8DR$K VpJG5_9X$nUNy;_Z$ mB,OReL\ P:"bIZ6˛T *foԭ,;q2⪍eI[jR,7W7"zAo2 9. uXnfp2QI? %w; H0k ^̯E²~CV;#PQ]q)63. uI9+ąPԨr<2^**i} * 2xpdjkH2q+ n};qJfDяVgh&~R{κB?o=7Z%9PH2,?ѩ{:AmBVIin]~gN*o wǼ*2t챍t2[1DP1i^ ]*VUjt)Bƣ,nܘ"73ցNV"qr:(]0,r_HEU+D|nHBK5^5gt`P_e,Z=AÑyi\?7 Z ٤F|\k=EX( MD^e5!tŏ RDO~@WgsLYBPsaJn@-`KYB  &ܭEf_0Ō2 $9ԓn,կ8o'S9d@r@Y|q6ZS ڲ6KMou}яW?[o><=z,ӭRkX[GdeVM\ Ϧg6%OEjP^kX: _Yxt{\d^2G/E'hυêNo^B.6ɎY+7.RلS%H6 x[S< 7P[,̩xC87Y/]j'2T"i]̚d wH4nТNOt I#ٺf5\yH>tO&-6$\bis[:gKѤ y U6!w:w]V&Z[Mt%qCqz7gUmP|OXCb!A"e&/tIay.}(=rm|ҸIgmbU օxÛ/@á yKOM5^q wՒ7kDbg]3z([ϦQTrEaZ';3%)P%:ǶЇH}3 eFJ `2m GK%5LSTɳ٦ֹa8ɫqiu[1g|{L"F!Pkh7Ϧz 9CLˑ\&f$G)M[S{2r Hѥҕhבsd_+䫐̨i`mP^A=gV=KM6ԝ<2 fz_RoeocD=ueq6{M8JHfr0B!{%@oid>gtDKZjAO/5-4x+EޠlJӼ7 jc&HF/=4! K|%})Qa@,qCz\rPsxxta^Z@{Jn6.3Msghnnb+Qж_tn:.0N}̄RL(2Ttӗ}Eu Fm S ̤S`:h([y:Q<ݬ]SWCw`B.gV" W~dBfݪO!/zQ.|gv{~/SA6) Wm+-߬8pcJO}+.lT# rNR'M(jg9K\5A\")DLR0Һa E6[O2Tf&qna/zr:zZ&NgPTg /""qq\Y2t& ;`O?l[FO%b C.}B 7Ėĸzɞ|MpomuwhBvgJT~ndޓ&V2#yoHk3YjB"5i75抶ߧfvC`ӡ0,@?#Ԏo]ƮV b_?tgVW9;j HQjKUOH{>.n<Ӛ+>:T=w'J+RL_MeH-Zt'U#͢y'T_E$TM{mҾ?KȣْNZ&)γ!ܸa5frKJ/ޖfپ~LJ@pyXPb YF@3g|&\#~;&G@pmяa?{/)CY>$blĊcRl%fɪ?5jŐd)٫^8Ae;ԆxRG1$"g#,}^>PJˌ6|_Ι fB'& =srmtsb|9Z W{Hh¤/w36^BPyҷȥQtFqlWɀ-5o` Zw`/*o t7͏mאbqlg7K3qPBT 2L8w[t[Իr=I%n,I=PhdsNx178ճIl,DmCyŰmzW Ey Ȏv7=eXI3s !)vٗ;au hk5c%~̩|˻M Oc)"qbzÏ$蹂f-zOiW L;?,6M *'h2Lw?,ĄK;bzL&zxjhl!qM1ƨGc+UIVW~r22J7J?)($Ҡ*/ٖ}twDf˻6n4zMh-W 5o8#=BoP6Ԩe&%WF#Ƞ<[Grt+@<㦝Z?+E%*eAe@M2g}3{" ҈%,;p)8O XJ}tN6oAZE6%kkXOrpF'a*#,*cn(Q,К#\|]饤ΞGthK'9/_˓5h)HݪhԮ xw uZǟTI~'W)QQ=^!-c*K/)4'*nYsS|<7(~y5F/<{݉qnېXrhѽ*رl~)|XJcΕYNu]Jİ*g1K?({4zIzm̽U8'WNbh,)î3{;|+8vgP k,S^wopr7ꭈO2w cZ⥬[HP+8%EU mll+WU4Qt[ ʆTS(nQ>K _]fꕂ5+4Ň>:#zYDL}?NUEF㇮Ρ$m݌2P@7yE>MSdҡQP'\fw<L8`- '[Läe쎺~s~luȉuEnc^Z~hB80 TK^[, 3}8 es r|ns$L•@0yӑc6nV,aQa֫ 婕Jߙ=XNjPJ щ)&-6HD+eF̓Iy'G㤡 bk/a{v^Whk$#J5wۙ;U7kAt6S  ur E^hPTF|2m.ګ0i֭v]^'^ Ke+*Z Ϡ˴ Lfy<`!fhkGͫEBќ%3 OQ2zD džһKyo&AeT¶Õ2 ٠*}U:TK2M 3n%7N&bsߣ.&nH&eU48h*O$DȔGp-#j=Y/7(p'?KM2 L;+?rmP'%3y4W&fUڭ5`6216J3S4"Erm@|bk6ԻrP)4Kf4,#` 3 0/n✩Ck"Ԏ*7%$TlC(SLd'QE&' WzѱCMojߞ c0Y±ɓi8n65)L-zajR'R'E~tw2NJru4٢IWg<퓇*i9^hc>Sqis눢o%LDRɛRЗev,\hFهp85\L(PEAN7 zY<ԃ wsoT ajI\($PA]PI1䟬񪪸J- .D90<40Rr%8Lzu6NےиFNSS9s"aJjnF֓-+'ql!7ơ(M=nkzɗr[K&rbښg==ZG9% dLg7 }>:aK H)WeZR%\:[ɓL{>) ]Y'lCM0j7_l:9Sp/GP)[s-a]X{նխ G2˅2[i &.a\=Os7y?3r=nti.U3yeWnVK=?ql^֢z2[PY5hU1*;,A‰=/Ӟ=Zn4r 'dʯaΎ=ͨD<{BNWHme꽪^khsis v0<|?uQᆂd\]%_ԮE>jJ gUmH{b{씧xyJ+B3g[ݢe Tn* =yՂ(Ȣ"<;[/yq3GhgZpHO\gq5aCrMi|enF4_TE+zV\vpA3ǃF2wo#H1>[\gIw-?zC̏" AAL -Lc ?:wb(NNrO^ -iGG(ʊ%~q4emaǪOKٻHo/cܱu0gĎT+Kdm-#=hy y!/%溭2PZ~" ~ ǖT-iIG-`cvSԥƊޫ*C,'_(J٧fk !wJ Ztc3XL țIi=OG($N, J~n \D􏒢*YBu y'UUNL]0 -[ mY}N矫^6&fP?Bd+qmH&aE1"Z,2L0]vJ]tF1G‚6㺍 %0h9(zNyV-<Ͻ=!XdU0p~A6DQM+TH⬾*Xx,},ѧ)W%=z:JBo9 u\ޟ*raԔfA y_Ցb.9ūHoT_YPqVC*H)74,yyy-{\{ >{02!\ 62f\0/9Z0nfݷoĻPe!N];41J9ɿ(=gכ#@ ُmB+Q)s~IJicm^Ǭ}w+_ڒ-P_V ol Q"=3]FZ'cpc)mG,9e7npxr [kN/;V"ퟆܪ ؔPAȓRK便>Ww:8It8vlC!sN|锅mܰBPVUssYs] lybۋ|K~D;j&3)3yL8ت:c_Ӭ 546>y]cBi4ZW\m"n4@ʔ i tzEԷJˇ衤.#$ZnЯ݆\:&p`y~Z*Mʴe>"[93}Y7 N7 pDa޸)ü3yuK4VS*v18@cMT3#;I-HP+}:ב`TЦbYoVwQ{~,T;#?sXc4 D"cDDdOfd.VB!K VC.Ut47'Z5q^ԭY٭# r6K8e ;:Tq dYqot%°Mr/3`X+=/SB8OI5N2GŊ5Sݨʹ̫- [h9%V Zߧ)ԎLn=p*DW~zPL˅VoГMҁ<dzy4}*s^{?fZkJ7Wҫ+PN*?yrycV| C[mR䞹Bm[PZ,by}% zbTo{yf0e>YG  M]b'lp+S[jp)?C\\;rfDWU_7s`^hބ]a ý)5dm̖\"lo2:ԹFY'2ܭru/ȓ5ysnUMrO$gV<rKݦ,+пr|bh\lK;}lit]zspBRۜiF\{q\J{ uMIf<)_Յ HMEFzЯ~GufF3qGke f1,`G_Ku*&[(s@ Qe¶G3%yo}Wl#m"xB2Jcs_O[G9[\(֒jcHK(ɵlB8W]ɖeVm AV z벫ƍ7ot E'v~ u*=%W,t Bq插WOwS66tfl3|J 0W `M͝b{Ej[N sU2үw3aN_,Dx=3"$w;nQ[Snw(qjU9~[usa/HG`S#WŧB+ZI~ %Vs$N:՟fΕqk>6!48a2j@zwRSy{j+q_W=ҁb[!`Zfn#=!?zxga|\М#@@$r]]sj>MWɚf3^t&VG>*SMXMV2HƩyS+lSznT;;~`߿r4eVOչNK΃%m~X J>"|WNғ-!rmT[IS\5F[Ut11y{lܻf2=$l ev ˝a,wj&)7OTiI O0/CDt4T{ŽIH#w*Y['^2ݢ%oPJ4yөo H+M9yzy"\8;9)uԕCo~v$qCi'7>)n~%}3PÐ8QEO%BF(7-nЧd}BAU.$S^ ᛫IpWh-'pc&w.$D1<H*܇V}-EUACc{9+ۆTg~o'Yɓ]PO> %ctk嬨T6sΌdЍ8ѠRx}^f/Z|($=li9^B"2t˸subPBhBMdOCm[mT-_{<ӇȨN=?,>N"m'r'B3&qSFg\ƼwmwMgO{]y7E0s-y˩rMra.vՃ69l-ad9=0fpROWP6,SeE|\"nQv 9frF>T*,Y Ox8e3Olmy6)Ѽ]8U$n47wP\ rmhJOF"TZ%OqTOF7Q"K父DpuG%B^u6Ie!I;3(]2ٓW'>B4W 3Pe*KkLA= 4Gȯ!i]F/QuP̊!"7մ&Nʌ;PBFe+^cHt.iԭ q4w Nkuta\\5#2QX'vmo'i.J\ʶ8~y %u:A1䜑yз(XIPq2BI @Q:"MΙ!_䔧:PR\YK0.3m!@fmCx+]KU, 3:E%/3f'C3mc%vsF0tS~<˦EaBbܪS Skx<.NOz)Dn` 1q4P{  @lyjY}IiSPOodSA=Ӽ&{nKl ŎR0xJ47Fi zƒ;ʩYJB8\MG Jɑl'-uGofZ>噇-e* fda2C{&!SOZ?#8\.WܱO~$m͐ZeMJ? B-wW^ЙKwCҒ 7~@>>*s<1Xt`.JfC%<:gJJʆs nQ/Zp4[󔟽v]f X.{w4sШƸ\!mOO5yΊ*ZeY+qjgA~@~{WCHe(ˢ;@ 53JWڍg fFN/ݦy )f=!jؤ N-Ԧ/(u(Jhм6i䲧w2(}9n&ft :8.}ЁmA8m8^-Wtƹ)m!wӑSHZ&e^eq ES2ְt%7JZrmzTw[i.E{u}jfANnH9(kw}~&1R^& E޶3$|WA J>C鈲Df,WrREK}7mX3YZ2=3rFA;SHW nt{d$ hPfd^lErv{pFGύɩ5WXk2A}V;fB%JMXe3ؖ)ÖF jV1Hdyh"ȲT ̖vT~lS"(}n*ʣfH{f&Uy+u: s( QTȓPߣIҪJ>=H tdm$O¥r3?k 'eU^s|ϭdUS{>̦]h?^:tuQǛIg̎[Hdɕ^}1I+׫tV}93*CrL/LW~^>5ՆeIEbX7-3Ji&* QRfTHj3-Eh]DWf7?o l3`bvL|pbJllݴKlbaȫf.B1[b{hT JEʪ%_W~&=2 ֲDz35>y[/ЂAi\FQh6L^{=Y~n(M EfzQX?UV: Q=)3TdAYI: lR@WuE $\. 4P'QNo#y@p+E&}Wl݅S Uהo#[a͈Z&ܦjd4j3E}ӞkPo(P͠cPn1( o$yN1H,ϑ6\#w$l O@)Q$0;13J: CsxNjBDfjnQu]Ilcz39i;ș2My"#Q)Yyix5I+l9.݌s5St=xFl2?^fP H hI!uW1ERs.6DJ.OǏM(O'2 -32n?rCf:m䰓JaZfѤ󌈑d nY+m!с`F33T$12kM Egs#ikeS!'#6xV)ܞVqH?#qB0] |Mh<7JkMؘ _z)@^XCXz=ZE> ';2'Unt(f*xV|uJwL#5Nnl'tEx㛻{YAi;U$['-a?RpfNmk*R2c,? jPDܯ'8Tv%DZQh߆IZ22PzEs|u\nt"_;$/5TwKqbe ,?:"?h!9yF;[ L2Fљ=VH|D odr7-!w~E]rxI[-lQUѿJ.P ` fּLD`>a?70\"DMp fuxr-WWNPs6:"4k[Ǔ/4w' ԶmHhSiki%'% mM\.󝭂nIVA^uCFiFu![en Nn/j2k /ɶLNFGS@6]ؕT1L3Z$1]#Aڲ"$Ub֠-oRd."LJjqD1b7$Ck7(!m=q#(ڤi9&@ [>E2[>[Ph*jˆz]m6m;Ag4 xL~9a/IsѰA2NP_A¦{xN3ε_В7DZJڒM3|֩) :-70͸#$Жi7%#xD i|s2 Ϥu2ҺoBw'fN~ ݍMzGȄp%V.T"Wle4aitqXvkWin5d;I 2ջ[t#_P[&F;3!1_ա^7Պ#VIV~, !AsL3Y'%^mr=_'`~x]VS=yzˤgE45Ψ̍цö۱5%S冫q'?!4E3ɟs]t&Iob aml|2QCgmDh?V&̈́MenfE9u?Dٺ:;)j'߯w(mᨹ`oO+o(Fnу pJ6†ڻ"4d^BϸgC.RLV{ATA/c ^\ZGC1?m1!`TWr"UkU*kda˳7Ym1]K s#@2ષV$> X:=Eh"oDmh4Q[[s<䯲7ee:inpY5ّ F'J ]؏薳nQoct﬌:Vt3JE'{@]ndn!O#IRv8'PJEs1?^Bmȏ|xx$HTC!74}E>FBi̼x*+k<еouw Ҫ绦܊DX/ԂXN 񷓯0nkgjxM4):12`ۨ'_QeU[Nct̰cQ.˞Mfo\%}M[l.{ Mا4 lЛqH5!mMr uCW9u+l2SɈڌJJQ[xǓcipMc$Ϝ nT^7WhkY+gb%ӍǓ\&T`ZMS(+\ɣb@4]/zmU߱DZH#Q$ΜPM_Fh:ˆ$1`kTiDp\_{hY<8T G U|0WEsPEA_.aeJfUg%+|@ީUѴǴ~D!1dRm!lhW!7 ʈ#Cm꫌YkY0:"ȩ}FNH,)U}|~ENn"yb?bطn9DB8+:M[h]WT̖0(PZrj|GjȩQ:mʹ3ACe(%WuĀZ"k0v fr5mf yM'Sb%3FB3Eol:xETQ&gwrܵA~#}qqM#~ԓ/hd37̡fi9<2~APʴj_.үSpяPL6)GAt׻[@sbSKxd*ҲU#6uSH4^[&MC Xy"xLv7:(=ĢُGOzd97CI !}+eHY5/>>Mx|s7`(<\n2$-q#MxʥHI6ühbQ K2|<7: 4*P6snj>x CT6x2GU-pTdDV2Go~=n΋J2h Tna=HYFQ旓%my8uo%|fu B(>\$98H2% 4Xy}'UufhQ=)_hG( Ls*D*bazӡnZqp4y%oL Ho (z}Yk*gPxYR w݌rL$h.dNH )(Zқhw)XWi!;Cl٦1m!?9YmC * "sD8F3thv lU+}@ՋZ5[ޥ ^./Dw ܛ_l@alng݈X0F/dAJ4MI -aHb^7jQ+ps׫luÛu&_)O7q^Eo֫dʿW1GƓ_/^u0Us3)mzgW)P+bDMhZʟc~\]>+kszANKթ߼O|feܸ7N^aOʮe͉12Jq> [lR=pc 2VEh{ZժJue#^iЋH>Owm阒`f?Golۯy-)4_kB)&~x9UEVPEIř>4|K{M#5G'2ܗXW/wݘH Mm!T:ӄ2om"ScoT\Sgk{@L]r3qKi6ۭt~ybFL65&ɋrԳ#%'rd~RJǨ[Bɢf> C=cȻS©m4 )(? 썹"Gdf,tFґ(KSLD{QPyKLJDD_Iۣh\s˄\fT+GjXvݹd)e/YdF{4ixTMu*4~G2jf$/r]mtŇ`D5sl ?*)AlF[~//3w+GY0{jә(P-Ks =J0Uf̲_z׸4XD̲ZPoc2Pmkщy!2$6(gfw@_Pђ>!CJ-7-`=ά_Qӌr@!)ӣ$=sZT%V&06Ntb%zy+uE\[zͺ).?1irr!QL> GGlRZ= ԝ,TD*"E0& Q(G~łE6C`IQYrz!r 8RzxAރU{;9 /E hMX23wt+m - H_*ޭIMiLCmT NԠMlEx, Wi*L˚ c.Urߙ Mhۓw׼\x!ī0<>*YU~L6a7 c(ݴ[*"ϝq#-L %jUt[)h@egϟr~G4V<WFsqyŲB }y4atUi[l4ٻ &WZT$>_"E9'ј?yPe%Lh6U wߑFf1&ߠa54O~$ oA{ *T7t;F'`鏟i'y 1]@"w34~{ mxW ǢV[U~{Cf`x]2N7/S2 7ɩႏ)W2҃ U@vC}UzDVMM9/hk lU|?y9w P(xWiޙJ}pU#FD8gJ * 'L/"{ cI(y2g:TSi rŬî2|БtEt"U M3?7.D ۫d &4}Z#ίsyM&12?x!_t릺U~o[lrOi7);vU{Z}< q:#߉-؊CvMoa9:ȸDlI%PћUkVu9;3Y†HQC5"* "v`ÐvIeGlg~2{ $H;(+-G=wO>s'{`@K6[5 RƇRH^e Ѳ#oAKe8G>dw#Ȼi"yE.8_xTx*5N.d/ʍ~6?lmM>6M}Nhh$ 3sNBQ:PL^~ze9,^͍w;x'x}\Z,wT7`GR=ɫl(%hVIy./Ѓ8Q݉z,2orOR͜})Oy]$-4<%E,:Av[E6zS|4#ICZ .6 L#AB%ڞQmr3)TOKpOr͈ǞW/#t,}R;3{^+3ܘ@͎LU&56 <9ҏHu߲iG qi\w9LݼTJ N{˜GGeh(R/Q4C5Mܪ[O)3{nVBQ7!a)@I!mo5qgz,w5h\Iݿ_WHq/~gJ;p󋄭9%RB"g ͹ B`S_7h&0 0!So9E[ FX؆`T7jN!x{0 k5QR~,_\'C}+*?Ve;|UŻM!!Wm) tmR$UhBhծ$/&"c]܅AϢPUځDbx< iSʀ jT=6>bٸ#9hEof?&*6tR3W>%>.!H(YWoߣM-w,2XdgI$}@֧ƹ6KC[7< )giYcsO(ynv;+&9yI w䉻+EْyCOAjKB1S+gI DX"Slz e; ƪ E}Q`z!@󍐲F!J2q?:lekv 4WGJq˒HK&g iMFEeBjVȳ$sYS'R p2mzu^D3;/hH.b7+?%\мȅgR6̟o(mc)1B%/޳"vM7 dVfA^l^Y}펱ؔ @ah-PO^gib\E_/z3Up\6;I~&$[Ue+j^g+d3Sp.e;%'2~&FeƔ\V)f{׹[4Ux'{X]1swI\(ZO[PxH3jUycL,[QP+sَ.PCUMm44W/T{(w|4Sdb8UD;l@YnRyǒr+r2ɫ\ذq涿E[ `3#_T+՘k."ׁRxRy3[/IFޠ4I[&e!㟺4B&MtqÌ>TJ3mPH6tDn[YXՊ\SL}s \UA6a2=H ^ȼTfHhyOMMlBqB3mK0nѯP5E =qE@0|D~rkS\~rNr3ʬGpj-SVu.sEp?-oT UD`P_ ^5b9 WZ]>cǚw6²w&+KLX6W Ɇꊗ6S=+umG˿ѣ[TSmhAu6XF!?Zl0-RthFqsf'"(&ڣܛ))&/4jDl+ƶq)$n; eS:;]N(Y2Y_ߙ;VZkbL .3 GҲYYga tE$56Y]z7@[Th:{r|p\͑gi륭ľAQ_+{ܧ+/ %܏Dh8,rcIgnOgfåKffBk^?J[βs΀V y2lqlͪ8d{fߖVEz ZF#/ݢ`iy{gY]>nj6l&_*Y#THf4HvA2 OzsqX_L*e*3;PάaBy-Iud/Jer+ ~&Dv9MUjLΩv|3Žb1u9's:^TgBsiTS SM9&OڟJ[CHS.L>I{Д Bbj[nWlʵwa2]fkȚ6sT.3TlXŧq5;rIY򵞷;kZuLUoz-S4}p"{xS<\dA͠4r,ⳡ_۟#_:^s(5/f]ⱡnU:V(m4[N0 8(θՅzҖwYE]Ai9m '9B2i<_!=L+GX(IExqֺUHO1"fP*G8HDB$F>:QZD얹g$ |[Mܺ/ u?5D"S9Fpo79ի>+J[;U%:߼VMsH;kUٲNx:mE2eT%y+9<_24H2h-cˎ%r/]qS@"b޵H^dNČǭ?,H$ʊØ q#FT7 {۷Q# JI _\X~0xyTy̞L}r!kj<؊=w_jyUr\ܹa_:W>?V]Tr8 >OG9jR#/3waJu:5I#$ IʈyMVe=iddQfsM<+Ns"Kd |rXN˃j >m&\Wo>U/y7g !_n4ZlDڞ_vJe#?7ÖDV*~y///S^6O+W^?:{ -QpQ\n'I^~Y wT8Y__`oԷJ|e5" g+^A Z*u4K![Լ&L^˕Wўm skR.>uvP+{pn&u"FS՝.3FTGt*Jd\9,v˄ Es[k^5Gs?e<ѿQ Py9N69c8s5TE(#=dBCQ8ZՐvdI z}!q 73 6Us?^+۰L|=]=Y?|6_ܬxGϲ)w3*Ҋ]h[ׄR1_lqez̫ ZS_[LQo>ZQvx%ΘNɴF>??162ϸ򎇋Sɨh74@:Ui°m([W ME@O\";t7] pp89G`oGM+$a͵ so]?̇mws߲eD`X[GPcP6DVVomϦsc PhxW(iw+ ّ.or*R]fM=BD:ToBbʋV[/wv+pN7SOAi06˸)ܓ](R->+]?mTs@v`hx7R>їݩ!˴)t% z1?~ ?)OX!tlzH}{a4n^~ta?Y^?M^]]v=Fݢ14:9U}7E{p -Nq OK[qK%PjmЋ< 13T )6QwdPX3$e7{Qr(?ђ)ThHWQm9qXB}ʦR,^xu'GY?ګzJ#N.`J[ȄU=a1?(fT{ K=߭t]4QKWQсh\;.|X~}ьyN-n2ok8T4FB0.}K9UUDLe*rIk]=XO)q7OeO[\R!n-ɛBB4RF=;AVEH5[7Iq ג Hlhcg3 ͎B@$ 1bf,#l.=PȇX_eI]}ص➡I(E~,9nLBRUY NV$G6X|Hj lDA9ҒU ȌE\{i*Ycښ\832&fEL+Yx~Ct?5uL(&[ٰ \FH{8 zypɅ(NedW]'㩸*RC)YIҫJNF,^8 = vaXˊ,3)PRR~ؘdm!W[Uq{3#*IJPdxXP![1c.WWy JsFvlkp9Cv͍~DՋw~Ҋk[bKѽjsqq{chZWc^R:,X&,V|P?x1</ѯhҁਙ)^c-e6_bm8u.;*~ 6p'MT`|͵C*6ͩTrRd!wTf?<[e~BՓn򥴛}~oR&Yluf-*9e u+}3UPC2Juc.Nn̏uvtȏ^Ű5G1VrL^l?=ߖhx-se|&pC&Wзܥ6l%QBlSacUKani&̃TwΠ{賐./xT#M7i |>Ѭ8E'ӹV&Æșcv1 VWp=Oue 27ao7ڼ[Vh8"bLK{+HB6kΏ SƈY7V :eo]%-2Mݗĸa(RUu)Ry4Ji 13:nwF(z%tY )ۜ#q 4*7o0J3 idnaGX*m.WD i,TZetacMR2XJ6亂_t52_twZH?*2ỹLoʙ"~UƋPw6%l&u[E*BZuj`>ZAfH 9Ur,Ɏǔ"}H,V ӫdMeޒPR Ls`1C)S:HvlXdI zoWD1c3PQsΑ7Il<=mR^7G4ڊЋ^M2-BNDj NQA7rS@ӶFI {w%F8L|'vȃ9$ ~te&gȬCYO/K< 4sGtGkps#N*[\ 3& ɰӊDGF mW3( IY]ɽGVWgц~f2}kӸpsޠUۯ5/B"d;hn6eoEoH7y)Wj@ r-g5(?r-7ˤlsoǛ;NQ z~+KʏoNP(oU)m;gWP4K zy̨n#WHVZT~鉜Nd@*p> hˀe!FYh8vN*fIn~*2; R"w܊!n̹[I-e:7ƪΤasM}Vk0Dzmx\tO-_#jgV e)+'{#=*jH.򣿳!Ul]$Hn*\Cr'KZWq =Jq\:m6j ”bSΜKa\@6a]"7yQ4WFhKBЛ۾b=b+R_Hģ&i.9M뻽"Z'ݨGt ִ#|p_*Ʊ^0P'jwӤY,2 j;s;,_HWQbU Hq`"5-͛ uUNP̽,y\ҧ`e h͵t~USy!y@QQ)/z6Ӽ^X(eVVh֐wfHGG"(W[\4B\&ĥ2{F]# )6B֮7xt(5Ba٭y@v"fxny-v͚;nX}V@@yeC^$zȽp=+gQ4G7RհW,3 X"!bz[N5Z,ELX^G9gB՞.M/DxU].`LM„ent+; ('d<[`unSvsۯ_(NV{n9 c^(1wɔw8x+ArmD~L:BȳiLH/tGA[]hXi( mϥ;ؼeF@G%nU(M$il_P3n=j5a} .`L=ypۜE&yK%{?]GW+<߬dX x7rkRqrJ?˚j&399ܿ6IE|ye!ы6tx4lhu)_@2PnYJ=sM4J 3k[$Cb/|A[mh0ùHUxDTVj],\0t#CSԳe*m6Lȳل|$UHRˌZJ_V]ȦPޣ ^aL;ޠ*H=S#qBFlƱ{xg?|6 l#h?"ʁMU}g=g38'vr;iʰ?Ъͺʌq~߳Qyq92fuP|6 |*t+>k\9 hvΟ'627HP6M31Y[Sf㲆!Ȼc4D>f%n\j=y>~_04 okh}2U3e[wWUfML~2y^-. FګcYrY0eۄZOF"bоqXsJǸ@zxʭ"p}.qD,Bh@hQ;#(P-l:~̎W>Th Ot-5X.LO*_3T^ᐍ|C,rBov_q讚l>&$/MPκ-W5zhL4O`d+4|;cp;JzU!ӎP/d)raNr w=n)B vtVm!)dJTӄbMz -tKE]XPOySIcqXfkzw.k=,bqTG.b%B&dA,N-LQd\# YĆݔx {re+ܓNy7_(NEn['}k.ڷ1)zFeǜ(m.N vBoq`j bz)+w;*M^޿Kh/Efzjy,؈$?9CɪL8o3^m2ޒisA>m(HEfnf%`7GnJ##H-T^E!26(&Æ ÄquyjϪ5(CX4۪n])|&ܩu(ljUHDU`J7˗~j%Nѕ FQqnLF|_7 j{C7K2o@.R#o~@"N@wӄˊOn*WN0fRq@ceЂZKYi.6VGx>Xba0]vCBbrJφx(k̍*jakuЯD#zS޾;߃A'9 SHrcl+4oM?[&!o♬=㹅覱 jU`gmW,k͈l(n./"`grLa[zyhH@ߟZD, B&(۔Zb=/5)9M;Z\ C0w2)ϓ!1P±mZUU%>[2tˬ](ai?q34A&"4͟d ~'4Wë>Inu{b6Q`!w;=Ƅة+$;fĊhsyԘ\GTk-X4m`wB} f縄Vr2ګi8 Me7&wjmĿ$@?Vz=&@e-2}Qm%a68;D2\ۯBG!jAUPeUWC(`NQ!t,nY,EB TlLf8mAiTʌx|:]#J!z0Zh"D ȭ l3ݳޡds^Hk]~2gܓ`wt(90!hT-2iuk5.}9f3A{r9GNcOs81W::5Wa%@h\`suE.;.f\dev/Ak|˿2rXоE2}"Xv LH;(^ƃN5r7CSEq쑽uN>B(FL^}~e&q&Dlw:12s#sUBՙ$3*nv^^oOYoOǀπkT"[IPo4kr-Гjn~C/Cf]jq;Ir3O9Ʃw F5咃%BܕnFC5UԽsb]CUEÖgaaT^L+t}Ku #Aq&⏚>\W*Y% E=Q# 2Te6DXҵ"CB/dWvtQ\/zH`#df|M!==15z:@~ˌ-^֮ -Zo>cEa#i/ފr7lnʔ)˛fMUeMoֺE(pvl?\HhIWdL#|QZR#0\MH/B# _ѯ{~0wǚfrTl~abˑݥq8ܯ4.H~` J) T(SW@MA qF@Z4%s?f2Td,!/ӍQ`Gf_J&X{َXyknjI~x|$@#FQ>L=m poT9,éT|au-"_9,MK0qzsR@禪WM3MThw g9ڱWN}s2N a7ce:^F u4NRѺ_mTlxJ?4 phtIWeʠU=2#]yE6ܒa{zIBB7*P*0Z|_;2%h'o+lͩƸjA6s5YSzym7Xm]rNc*|t/K޶fS=HЖdcD)4ˇ̄4lznO~+DMKf~h@~{DcR[z% ^棘whP-bpPjD7AѢNr=2$Cl-Nj~"?ȊTHo}JlJu*PQA&m׸7G`g@n>}? =$zEDP !<+B:zR+1ł >RjӰL2z.j# <` 3 npfZQ]W4JTЏ^&kJA|{)>.\JK7!揻N=CPEoΧ<-O*Bf8j=}1D PVO2jw XμwhP&aE2yq w=UUgJ` $М?y6y&).PEbL5=q ^`sKZ >D߹#agPUYݺ%0Jx$9Gb(,3e~^lvB&ۉWZ<_)ʌT*頽e9M\'ǝ_(3DǔA~jb3ny[] }MJW)EMYt(2̤"sdE0)ɳT?/+Exxy~5%<wh-AR^bnQo Rg߹mq"5hܦ)> z&oc_OVܻ̹ۜ|"M5TL\netTiH7Mޚm!Gņ )fgwy'Iq Yp̥ߎ{@kEŤ,+v"}'n˕.[g &O$6yU9<ن$Nߏ? ti D!5#Y;8fH@ (r/ɔ}!Qn)q2Nx*QKjuCo %#]cAK37ll{!\qgsm?96,4U)b+!밃pG,w|7ғ|Vzɂ\ҳUH52Is!T?5PNnUN{iB?_(>&e~ ¯g_0'[YU5u Ppa!V֣J1bfE]%6ɐM"?< 0H$vʚ{>ۼ=k~ʦDu~j@=rmcLR3Znbq!/ 9t[Qz4Wvhr$/ɺE]RF u44׹pu(gQQ>!q,!@3V{uV1ZKz:8書LԶcS^2Z%BF\>[B}B#GL/>V17Hu84clLsGiStG;24u7jeTeR<11sgbN`/WoM)>4Q_~Mmx*qD}TBf@f1mitvCxD\~n::}E^!A r7MlJQ#EC߿犵> =! ߶Bo?M6/UkLu%>ih~t6ʶ9H'o2?:,8p5FfD`e %4n=[拔i#ȴpe]l.nv MK5q9*݁~uE?#ȒMp$A%](72,=?=BP:rF)ENؒ۱wG%k܃db,y?뻵vr ^E7 y; IM'Y,,YX|KGtZѰƊ [D%sl8Z?t5j-ݳ# ۿ/%ZӦ7BPtqnnԸߨqDxG:@k\bd'jՎ a:D^^iuTLQTlaDAҙrEblIH2-J'W$cTi4S1˄=NN)vSz6ڔXnC%^~${*vhly֚.ZR]ӖϏ? z-ݾs8c 7;k n'2;2wp&}K< ﯊⿤BCx?<1ag/lg8*07.?'4$xœ6()`6 s-$ڕR\j.~# Y(U>ވم1%bE(qգ?FtY$f}Tq^q#Dl._k-\s) dEm?Y` %r7)m*ݎ?mPtfi佴q bcژ t{Pl!GUǛFG4*rdtR0>`2Px{66)vУm`.iSQTBN:`[ paBa>PE3PɠZ|Z> 7-Xex?IidU#ʱ(Џ:3(\atK6ex}wpqB1Y ugMjȸkV*˲C$jO"G J[^n)AQV"Lm`[k(o /{pI}-\ 380CwS-ea(r8X#(CIfu40[vt6[7hL -{ȍ Eu[&} ͉- ˄Z+*pnYl8O 1dM>GSl?Ȗ&@7;jB<ώ*3}^?5ޏ+|;*Ikm¶/@ @T r񶈺VS?.U|~lp[jgŲ8dix QB CO]4-CJawLx :JYlrH#y&([ G-PWL"c׻S6y^+ʠr,JatVG_ Mِn!2|T/VHG2S'˗m̃7]9+̫,4#ޠ{>HjLcK/wӎ@A0^l}j}{ϸdЖT2KsϰoYF}`Pu[M5$4T,kȨ|dr]R$#@uC~;W2 Ȟtb6ҨSI߱BY2IHtt)z]'޵I5D<'AF(lk\ٔП.X9c *j_s+qd꟮lAtnvҏdo)A!u\m Nyg kZF>e@>@)`V9=Pح aLJ3m]jl@|( g sK[IL+q@t Y o$3K>+_0"ө0:> }] y< ƸӐbNJo2H&rU=H)MW8"=NnxjQ,ӓ @4Jirt3k^.S-ʰڅ"Ovg4#2 8*2բD3> #~׸*ܠK{g-/#w>4i*?8}Zc¤>( `;YRta*[NIqGrnu],1L: tg> `9zJw!*$ߔ j)5R%y{ FPݻ k*2pa *6?zDZNk,cG/?y57[6\tِI6k2Wˮ _K15#c^KhOڏf棏4KRǃY]Z ͉ (/:Odhw<^m"{"/y D^aRw&{|_6Kj/Te!Fwq `0DTʼn8lx]! f'j^M:3x&vf>'lJ>0eWIfUcmEo6tuχ9f|Odd+x>(f8<_E|*W/\‡ȇ68/53gx uGm$XJz! h~oYXTo}5ՌL֗o* ۤKPJQ9P~1Y+u氡0{LӒD8/y& Kr4s2%&%'_\ Qs)((= Si"9I=~ aO_6^鴽BA49>6ٝ&7ɹ\C[S_o/\%_BpE_!g2y"hk^_FnXo5i3_TLc0@a ;2r[;wfm{*i?4Ēt7BtwU+6:wAFdtؼ0 ʂU'ao5Ur.}z`9e_{ƃ[2)^wH2kȊ8\e[G/k#Q^Hmj]h/kbsOAcϛO8E Hoxe3w8|G_rww&rH{Ǚ>:I+zo_㿵4_±$]4ΑѽS.3+4ܛr<"ksX0㛲*c5J12S-hqG],K;A)XC[_(>4']^1ԕ-g~ͬZ'U1A׏LE?c; n%yFBWHYo$!̒x!ra~6^Ԇs^V/VKiDAFK[6!:{MID;N;I:|S,eg%9wBX7Ⱦ,<ܘ4m5BORIWrhx*GBytT@:ͯ=m )lAt~hsᒵB&|#r?趀qi ^旺we*YwZ:˹ߤ:d kph׺읝ͯc1\ˠ]Z_*<Pf""+^ w'k:gDO^ .X xj 3ϒ<<@E^4!] qH=OA)gt k^W-U([fAȷOwy޽%Ɖ^R6x)2xk֏;q;NO HDI̔2uH8!|<7ZVB2&72ɏW\x?[*z _DE<O}92DL@2 ʧp(YzSeBcpPo7AoEK88+h9NTamd3a/Ch*>yfKxÌwvl) G->{mh+6bo󎔎0v+g|Ariu'҆y<)Ͽ 3ڰ@K)33;عh|jGO7.Φw@Δ?Rf SnfIQP P6Ij~6ge/S.Sţg&>2svseT f3ȃ4nP2 + #މpcn 4o9v&G2CC^mStI=PZX.k~;v-B)TRsWOWH<f18 b:̖;^,gLTҾ+k~z&m MhKK}5 Zdv}>*{Ou^sOkݣ1.iv-Ky"LWVʉy0 -6MxDG3v$g:(i[lcK\SY3`@^tmnj")&*`jnal@KxU2v:}!0U0DSdx/*pd_WTkawkUm]!{!"PRt/PUmTj]ҰB^Whd$b-e)m4hN[vH'ڿ`q ЩѴ+Mˮ)+q;:<ŢچJ[`0^{IgkJ_o2Kpgb{iO0mTmc FV3O6hYo(}z\7&wł-DT%љEs z)Z&eܺoa}7n1YXN$ْ&  /h;jnPy?BU4r <|DNh9͊3iд  ' uꗃA%%ܫ,$[3vW좓!6@XԒm'7i=-HY b웡'ejSfGGӴ9ţ{s>P~%BԦN1,0xÍU5K&b=YExz=xn2 T-+~Mp.I–E݆rtwALd@7z\|)p!ֻtсr;i hѢ^QUu+GҝVR Ŵo\ *5 碻d9U9ѮQZ&11wb7Pn$$R9D H&P [Ȱ78: 躼S%nIa~uy)oC"?RI1W lZCz8Ky%)sݬ 2rJ,.lf 3#7W~\yQlǂd)&};ţYamlX8sp]6ί%8g+PAXM4M_:uUf2xT?WqȊfe<  k^]%(0:if6\> M8H5FiIf\nkU5U]Ы-[H->R1=ߥc weSWt܄vs/eYŦyKQp0_,CT%q]άByT]:ıMѭ+d5+(XsZ?u"Ԧgh"߃haܰ61,-zRWk0ԏ >9\3 W0)@$=V+Vg[Qvy|D7Zۄ*2*@[H >J [{8p ~dN'1i kè:ҕiyɗ> e}3n4|q-5 BU,zv@cnKHl6{\DQLXl#8|,Gh^Ys*bzo#&|Twh(Њܸ/f}{l 06ePF3 ׽I0_,c })d4|\c,gMϦhK!tg>v%E~ fPq>Kb`fxjJWYZ?vmHڠ*@Q짒C!EEmx˯b&r8(<2 W4cf&+Ll8W.ʇ"n2Px5L:mJ0tJNG$ϒKt k{E-Cdέ;#!mfGta3]"2l:jM[ԆY`>vR3^[aw/O/*ǃJqJ(S{CYM+n<6I.;&e%~tv1oOCg*L+q>U/%zغ<4ZR=΅;r7Go;6GL8x;pAl>'tœ2s$ .l,W)魤ōa<1`7S-۽SN$}MNx掔`?ot]@ϔl }(lpelf铟dITf<{ঃ,yeWnœ<+S~|lG CO-=TԹ[ZZT=A"BW>I]fINqoh(x듚wu^ 2l~΄[UP}PXƜ0'-@+ne5UL˅$m)> FmZ(љ[ٴTՌLUDi$ޒP{r_3߷wɜx-F )Ŭ G`P۫1f*Bs(*#Xj2S|ΠQL ݹ4SUDm49y^msdAcG GVTҵyQ>T5a /2l)ڄy?Nvפ]jh CCHE1{&{h*Y[DVM<$P3VG$v}cdO{)u-]h3DDܲZML ׮zdGl>pdEGyP-֧ &v2f.>N #_N^[HxUGǤ+: ]"dG+X'6j8<v/)㪑 -}?d?ɐ;H Ms*c{L/oޡZw~߱_q׽塝H@J0N[X0f xmB+L%]h-yYȗpDUΨ C=v[ D3ghvѤK5_oV:M'Stx{~IȥdNz/A8oyoBֈ7!ػHRs0z_LM}?cuO0ϐ‰P"䟽YI'o-C_VߟC!ۇ~|&,ٸ ;p 2\v9?=qP6d^TY>6QH&RYL<fּ7 5Է8.jC E%T攄`k[=%MF# ZcL|.#\2K63͵񂄡s֌xI$T"Xnzno^s^=xR:Ay@ɣmU/772ȧ!k+U~2_'3 ѯ=É P zxg^Pҡ<, )|RxMMDDݟQJ,nJX̧=lKc=~{ .*WF~wo?:lA hڨ`ߺ@Fm5s՘1bID(#(K6&%v糷onq~3e TnxB*.~f\)6LTlmqf,y\IFN34}=&f$7Y_5=Dw>c#0ZZeE/QONY1D85I(HU A6"0Z~>t8~~*c N>.6 nRV['G>H֌Udb(К7y6+X6jjmD>y4%Pv  &G64aTu&mθgv4MvgHR$4&c-m=ٻxL;],NG>wy !qﺱδ P9F眶帼}2BEgy}%n:fJJ.lJp-=nYK:.t0cŋvzN?'Bc\RŽ]'1:i.:# >NuK-xFIKӄn;bxR1&u9 #i&&j$[%>޻gT(+;nٙWщ$-'0t66^/ޠlfCEdq^o2zIjGOva@ һ =.zt2?ߠްw{rm5]9Ao}0d}xߠ&?]oн=|Ъ{ak!E74zޫ8F?n61\IG: Mp:]߇Rt[Erik̻{9aM_vQ/Db/;=9Ww*œ257&=`ehoi?SeyhQl 9Pf0쓥'2's 97h. e~OSކ3Y|=#:{{ Owox\z gCۮOLB`P`k Zsj!@w¿: <f}JZ1#`KT_-#yE短t:GCh^wҔRv,~\4L/Pw#οeC6CEzG|Pw?a쇦/ky hn>؆@pӼ>zdY߄~r3}8;U .65/X N(]qě|f#.ѻi^KB6ǟ k]>r;]@҂q'aW}>iI+8 #*A?Ht\Auzoa˰Q=:jaMK:CT i{ڿR1&9Y%[z~O Jw$#OW<h^[|Ze&{E;=k; nos3}<+ <UEP)7U;%帅/AtL3֍  )?{J7Y |a4hb:T!UGPIE&/Z|(*E.3=ﶿR `-&v `):uܢwT/?D\ϗ^ mbpN9+|,}6ػ^OD{+hMvuۏKFiQn8sh*?|0vߤxyE0;4Z(λ-{ŮTx/'cM ^dɧlgpC*/n o]٨u"/!ׯ8kLH{/B4l5w7^w%?.{yEKkwbhS!d_F뛔,x]mPo2F5# :՟ݡ&9&7FoMN_74x E7Ih- 5awoE`~5زONtp?tpsHΛlu5;}*"1E:ku5$gtcB73Ne͂v%lTfYgql9L caiJz %t7%(.͟790ۗ?_tB755w|w'ʯZ$p'<6U`uo綵{2Brٯs$@a&zoBר K_u5v6.W,䚼>P.9Z}?ɨx\gN0V[ tf?P곏J3Qf"VIx ee=?m힢dT\(vqcޝ;t50O .}_oTmV5cqdeK GN3Tm^(4Yo}?oT͗P?뫴􎸖Mb ɒo[nxZ`SU$R5X((9͸hX/>o{uc@4*YT8xЇm6L,+?{˦e}'pܘ}ӀYm$Rwb)?*i-WDc+Cj}HŸ)#ջN#vҒ}.4ߐʮ# 5G@ ]juy:fGH E]ޮ6+jvkMTibl;tTԌCT5MڒS 8tIqRg0o.Li{.:7wR@.m?hp~fBЬS}2 U)bk}Q9w X z^VN 7X͂Z"D7yӄJ_'˼MC6t:mMwh\S%!4!;fb}Gg߭e{7{df[^':K3ku&Ԯ%!j]ܢp;LXVEހI敦(Uia`6gD ?Tl\c!V]ٿʼ_WCWEjX)mѾ9hW?94}:N4qZJ{*fBѺe%DI0>j2s7TF%Bs"C-%LB:XZDBavi!C*q]ɇ $&(F֪tIگ5'0\RUG0MA[Ő?4I%- wɮyf"d j(3^ , )lyIu eL)$q=wZ7Ž&ty %i^3f51O%\NzBpcu-gخ{f;N_9^7NY=x]q+X{ UZTaC7uZ![FTGI.JQ@S-"E" EmaENJ\3iuRD=D[zFxx ; rVq^S}Y,'h zB]})55cnn )q'r".SgnVH9?2+mWC>ut@#uҔLN;0rwPxMS2, Neyޡ:`Z5S4M<56<0[ܳmjJa}k>B(!Ǎl}ᨺaVQjGrt4.,MXzfKI FaUhg fa NеNrt ire*rQִ'CҴi?ޥaպmSiS5*h, NV(뇄[沖Hn 1&2A)k}(`_aD򽴏dpB̍U}=b%ώPG?L*:3'}_^F*t:J}}& 4qPz%+q3GgI,4,LNi ^wTY iSOlOV%u0]")Ego+Ŋ<})hƷ;;{ZW/ B4.腮G B-׷t}ֈ`wM\Ep"'+ ͒eNN+Yu^h^'NxӎK˝ENMft4AYji$"ɧCt2Ŝ6^&] 'x}5t]m.Q'vOC,'cx醯SPPjRF^#+Vrdg̛N$ m0H9zA.VrCʘ3Pe[2(]VSdvKpvtJR}1.M3.i?_?}3jA0Lhpl=A=Y_ЈfjDw%! -"3&=#JUS-,WKs. Qj =y$%HĭfM_;<^fJDm\.@ȱؙzd^?bXA[*lEv.zD9tR%TJVá%K|&j95 qRľ<9u0'Sa))tE$ޠD0;§D˽q ՈZWgj~<-~cu(YZgڐ˳ǮճsBBNAAO̗[ʞ8%/,BKf|W;"1ٖE]lYGzNҤuqW.8-]ĭ$]_CMϵ~? ?2cͤo>2,Y|6$GP_TfLu ?$>;;8Muv>Sg>O 5# M =S0ap]F2컚a $HP7@a# iE[-_Q^=j=)m7]'̆;ڟe/|9=oX* EQq,4^re5R%{νCgmQn3Uxu( QeĢ//3q/rPA-4$ HWs/3FJODƠk""nkT4z] {ȝVc܂hO&rɧJ WחlK%6[E#ձ͉ʣY);d/797#-usf;zvpYږO#*Jzk3`"qP^=G-ť mHseFm4N]*4$~%C'`\vݢ{S-h[C4ZN*$,2/O8)ܖ J?{}3wrq[f(K%v/_]qguz>pJ`.*U$Rd\y73ޟ:o'qwT_x[?ŷK:4Q:|V'㥙S xgqZwIO #0"{,? =37GEuKU{ ?̠@iwNCԻ$>O=l#?)W7l$tƙҤJ iw&wz[_q&Sn/t߆\" @gwL6^LPܗӺhGnۖg_UZ>Hj"X;[ w]Ѳߖڇ(N;@ƥ.30RkwWhɕGpRgrX> \;;n;y*mU`<=ҋ#|FǪzKjgV.xCTQv_8 z] 9D$Du;g˸or gwn=.LGoP_!$w:iC y{ebJN9)B~uゞG?s2eZ' HH:JGܲ΋lf%\8X|Vlh(&}x!: 1̈N:P<, ?zܿ:c*[ܔwsx"ZxMVDM-Q2ݥ|\l/#k&Fϣ38w.{("a~%Q'Ykjlf&'UΞP_/2$I^E T岎3gHa@́JXV3M}E2&MVO|;.@ȇH-#A툁A#]5|i=e aUC Ͷ%E*pmQI+: 5+a.jvwJ<+Ăŏe3OkM]K{"\LKZEq9)d]p#@Z 9N2P:,K')(P HR4n2!X/ ɜ I\4^wƉ9d Ǜ NceKGu\Db l8h8)xf,CE^~v)=1*| .9`7<~m$L4/[-HO m όeHe?yZX۲Rq&CtD s`NFDN;|f5wQ;N:w2," 6PSދ 7&Pu0K-ggC=& % u~-eo7^YWkm ˶἟1RglI?%M[aU惇lBP޽=犲J IH%QW)%5*?𾠒Iv}nVVJHR( -~cb@qm ǏT=6cnOTi Q2ckl$M'@였X4r\[|FF&T@b-nBgV{Oogc6vkLg,R*×h`yD>]EޜϺ#']p^'Sv>nN)Oix񍴤= 9)P=sDAgJg\ܳS7))خaOAlb{P@\6Vhm٬<~2~~ 6s֙<*\4%yX!uL>#Cshii8CVSYa1iUPUmzHnq߿>azw-57-v"ެ3\OەbK&TMdԑm.U沇`8b4/u!{UP/0muf-w[SEdby/ -3'LoLgHO޵@ې *isiXx[XnObž#C_{U8VF=xn8$Q[EoݖI*O^9F]twܴQw_WǠŐZt̗5 _0NZtRSm9SZKD=,򖻳g[[ؾgf{4<&Qƹ.1?,/V4[#v*L7/BXBi}[*a-,%iCO7SsҶO:,#P^ԹjLO%ݭyL-=2d$Y| XsL2/1-?Ċx}%b^4f%5z6!eN=h!ߊ?P61.H r.dۗnr7El:Ցa9"jeh?Q!h_>mfd\5N[ɍ&gmЗ ˦Ȑ`sn#|d:շo>=R J뤌3 |.ȝS?8O*T/pZ vSqW E܃ncLk )~1(|hsǰ [hTmɵ.>^^okY-" o?=+h#_.(Y$w΋@~ӏf;IR8Zc dU$ID$&ד9Z8hXrHom}vk%tSqno%-)_|;;|nuFS%E>Gՙ+ %t2[zx"+ZۘC{^ʭ_ϘHJl `׵DII+`47]iG~ihkDʽ=ퟔF* %nv޳W#hE0,V}" 5<"1gma'DS\r Pb=C#^up5.q Mo ӫ:nnO2Khg7]3jslzY΀V뮳=gz}.%oq9rȦL7i(/HC2d6aY+a1`PqNw,x?Ԍ1 JVy/jxMZCﻫ$'ߑFu>kCQvOȊU{mf> v/0oVOGXR8O޹$ܤOӥ}.Ӱs]WD:=t03׋y6og==?D}#x\+]Α/~rn.M2!:3UXv(h?wksNwyeJ) zP:!bi 3y6o{}2.}ōucf)O\ k|qL\P܁KwPn/<벤_Ă!j5(ϫDnHջq>􈧲G /pk츓߷2g C~mKmZgۚ@w(>xF]/vVÏ\~Ԡ崕W65.VqCoϧnXYd!;nV=xZSjJ,O Hu"oJ?*emRUͽմAK(u%̹ZKJuU##>{'c32V~)ϧjTiWɨ#lF&y%zoouɕ٧{B:zj%NFk":W5ˮdP:;IXGH4PhRi4M;[Cl?l>PgFp.0=~'7ZyGBڅfZ(wF{6;hA.FXR7D1'fX@v;1E\4^&p&ZZ3%!ҋy \gBgJI)c(1 (AQ= Fj*;tYH񤚸\&_yBu.~<),s ^gpٜ%lt5NCVTfK:aZ!.5ͅJfgM(<ΕڛCxO2/Oj?I$$(oߜPYN>+Uuq Z+:=#$!y^Y:h >P`l8CbF,DDw -ڦ[j:[csgS?7:Y7<"Pܥj;4L8q\*ۜ? f6W; M7Y.Q2_5 :X6(ͬ.^.k` Z ^\Vo2Pb`GBaDO?p'=8q^/.΄*[|Tᢏx/XhφJWIfQ "eC|hM73z34a?= wA2TM",}z F4:(nԛ~GqȨ*թ^7eFPuD2F|1{,'z^=uC6j;Jk8έ\PۀϧW薰N}At|:ePm-.&tªnY\:%{dڙ:dS=gɚ&3pJv1P t6ϡ(>|vQ=¹ |[W}=!ǭa#'7q;ID|FJq) _gaTs :h,*MjFh;yI^{?DN'x׀MRLGʝ܏im֪Y66vXu[+ZdpP.ކ)!v|w3k@^|yK@.eaޞ%J3RCdêm$oʻ \vy?Mv_ lᳵ{p|:@Uv1Y{J4XN1nHp=ϬdyY'LϦRLMq<n"8OYdٸLIv#оI<~[2FSuaFl(}i*8`Yr&6\Rj@Vw,>|vAYM%(dD JY &6gK>y_Կ>sL9%?'K~9 qvtlTG hz,wGX6>\,םƶW{C/ot V-~Xz@m`˲S&z1&zƒoey??~7ʦq'QِsnwPɎ :s@DD6-jVo%Mk+-,9ه7L=:yPibw47ݳܨ*fƬf 0{ dʝ4wG^qWVn 6Ǯtuvdu3ۻO+~|hm7 hL;piwu$ưBġC:N(qI:o@JEݽ2ݘ`v^" !%~crd%$ Yk*Nř3J\$"燈"9t#Ar7L0=.i[/"ix?9f <3#yM 4ڭzEM4yyi: B70 V> L!nzhϖh P> ˼7k¾fه\s=ؼPs"W`O֝`,͇4\U$7ziT-*]Atu^g,2/ql0 MȆ}_5[~^W}q6:& L+|%>dwّ 2'ѐzԂG~ww6e{Ab!RO'9P>D9iS!#RoV3| I_e>l8ݰîAmr{vzƒEDbOů@ 9|2~T(4IǏ{:B$҅zv{~fjK76~Po}}l8摢/,=~+[6Rƃ 4~B㟂-04bC_w?=c1RO {LxdB%KdXYB0y4L)뮡5 Jk_Q9(8kԹ>U&=~p uTqsC~j af옖:pvH[_fD|!{%VS0dG3KIK1e+ W27EBncӻO;0h>oqi;nP$sMVĹi8&tZ.q J4 {AP76^y'`gZ n|Ҟ9 ;G쩵QB 8rɨ`NhG(;>ŝݔh_D4gjۯfuuG;p_Lٗ$>0^.a5$?Aө 'غ[gy}%qU{da6^4h_>n)GA%gK/KO "Ģ,w.xVN0f]iy:1 BТWY?HbE#[6'qʭXu1RIv>?/sf]c(FaU,-"cxN4EA+|>-@n8nđ ܊ixojR>: [R-T$Wa:Yy(_kJN~pufOFsnQ*},}{M o O<s ;iWV X胾NxuPc=!h $ U)C [a陼.aHlfnƝLۤaJ xlsaNn`Xo2?dUu?D7?y]OCM+6ivki=2Xq/2.4>s^RHTAOun"?P䡪GSVFg"ݛ6|CI5m5͛\I6g(\Su*°Gs_>HOCVgA?Lr+AMƤO3-n1^' QIJi/jb>Ob&r~'pRJ'N(%SIc;TLB,a蓒;>]^% =h}&ft}7)=6SN:M7ι-t+"kתfe)L@DEE NWeF|XE^/V瓀cz("|J O!j$-$}M_tHq= ijwgbF "v߻صIBoK@o& `3dGnֲ}FSwnR_8spqou-#Ú\ n9=aIuǓOOO'S˩^_jWLSV]d. \(WHS4EMt`lBp)w=c7,`Rc]ٕ'S7*0IYO8nh,ɼu7LQܨD74 slEw4McLΩ~v<{))^7lk!<4u:-HkxRh0nY{%HpG彞VP!UғѵzF׬3V,}%wgyNB*y~>+P 60n(}sX'wPػ.bsy/A"FBBf^;&B~מE*U(S3Un':UZ⨧c0"3&5~d9"]gJt_x{R-]0zkpx% x (E) w)BK'TQU2 G~JKs*7Z5K~k gk}4z4b4@~k}2M9M#W w{Z 8:xǴwlPGw89()2CJ.$(iIzwi%ALO[e]KC'_{W36[+jl2K<+7f>Z>M\y;tvL؆_P#?=yH]?1Nȶ<i#/1SO/h~4{>w|DgDbCi~v'1?qhI5 _1^ZwR4=_TQ.oZ Gfn\xgVd,T8N^ tIJAPtK Z";o+^y7C[Y0\]IZ<85q2E/?#/AVp*2Ἀ&&=27Ǔ|,$4~ (rQFd}P_˨/qed DUvNӨP<پpCFΝH#{6ú.h'q"kAJ ɍ Teñ k^{)A#;j5+up@#fU [+3z) )[f#QzRPߖ%Bwg`)k[*c1u6$2:;?VOM}8M<< }uC Sz~:?gvd{2{6lj(v^GMj҅9,vFSgĬ3K7x8:CLh6O3}9P{F]#7z. (.5pqW ^is\%и3+^RҩX=L/g:̪y2I7Vngk ū[rw4xԯ˼LaSfsϥ4KЪ˝n55VcBMŴ4n$eK-I=g~ھګlc(4e:?VNh=_GklP,6ZßB%{G%cLS5\[|l%ly0D@;R;Lh.\y-'] +adDˌig]?ej:n}Ϭ1lrݺi%@~F2&\PgB],V44?\W5sh(aW9p34s9:c&Avgqrq9PojC28L+F/ּat;U!5Dw/:Sw?&ˆ$I9p{(P(?Yӏ9iy2Yc,垣:{b0jJfA_|p~l(VS]NLNh{wE#ʁĉD5}7ND7֘ݢ̨P}l ϣV~(uo;WOMH4o%JBTEo4}RE½dYm?Gy >@#w;ޅ}0 : G,+Fg~K9e*ݩHha ^n'Q;ÙaZwgBjB{F/9&wyh!@[BK6a?$E:Pi]̆bcg%g?vmsX<@d}dp6/[6vnqW:EZ%6}ucv+iSy@IʥKs`_OO<X,K;k~ܐa9:#%wj$짃9 J44ѝ͙ :d]4;{5T_|p?'̴ +Yu2p"!K|^ bt?yLDk Nّo't7} oz0'ټݓ8tC9rLU[wE.‡mv}-$3柘*X@O+9 }s <&WH7ב(߉DޥtdW`VK(6ԛEn?#ԙ[CXZd}@KR<ﮢ5u{]!ӏưS%a4^;ϡ'9^J0"; 2B@-_ܳs&h\RK.6nvte$U'ר@쫯AhJ2d$kd:|y:JQ5.P破E(>IoA5ؤtzg=wS~d׈؜%{IkH+5^MTj1=6J/HEB,%뚄h,I/|j #hɳ:QFKk KG ^E.FF̋,n`5Kϻ/CscLAۮ>[~=x~yBܫL5nP\l˻ï? @ֽ-)meVKs2+'AsLU 5s̫H,u:]&L++W^z kV{3U^t-2CV} m4!uΏgF[\,۴B",~LhʹiiFa&z'8ώ FE$.{H IQH*E~o}mKFym]*quDYJ 6q>12bLcQ~TK滋>Tlq3ne3c= ?`^. >P`I/gF'TJEОrNVLlcܡq^I a2.x7kYND>2%IXtV O;-(ݫhQĶo2 ;Mm&&a( TklW̱DB@Ayۅ aZ6*˗f_Pn}uƔ撧 er7VzЬ܊{^Y&#vp>]- s§|:?KX _w%lU^mbձ[Ti_#A${\J=ZjE?tFkmc3B13K8"~cRcC*gv>ߑZy"wTVqCvwp. o?nW|$TLW*?e,?)2jTp (+"b7 .ۇD>.CLx)A_s|ƌMB7n:0XP)B@=?sVRBNQ_t5u(fV>{hB:s?bC ϭSvh`[e˚|ߟV%bcϗ stV: PA0`Y'ϚOn79iqc{T^MBjN[+(t)AjZA@UV6JHԋZImz.̖8&N"X u=" "qeD:md5;2aTP7EQܶbHIVՒKs>y oOe)$x#kFTږo$? : l4akv}$VLU#=S WrVf9ߤi H} `=iiF-+YfAfH=6Nm nBf^{IFGuаiQthMM>oWCG*ByOHh=5JO* 2 ]ʶ3yy>GPa&r љ6YsMFR wh iiF.~4F˒RZ8І+9tWZVDh a#4|2-)AZ?HޥUf}h6š`:ZVGM?xJ64 =UCg[j_ßA7`\IiWc͟4}pihZ2ߘ.ځ:xW6)Jׇ*Gm`,$;8]Rf(e-3QMk$>aPL.LKvJweЂ5, vmKs8hiBDWh-z  [y[B)*G©@ЃPLL8ńV65=Au9>8(gڏ~\*lDr]Ǐ7?df\Qq7]O/ΐXg L΋Zh@*.HO<7"$Zu!]k*LzP['9^LlɢQcno#=զ`3&jnE){5A«[7~*E YGM8)v^q2?.I ʐgK?O62hO<m[boHuZ'Ž$gei)PWŭz'Ϫ(GtCv;zEg37޼ mlx5}"- {DŇMVCf~;Mx//ϸ슉r\he nNc'pȫ>U L%v}ԿD` <3rv~1E^ +2 wKk8GO¢{_m'f\Uu5i睜.}#jB%&j1s'e=F5a^匿b\*Fh rgmML(4]Rh:v,XQ?^>Tõ7V6]KD=.q@Cp|C#O\БG{c.ԼzPpbG=ݟ85eZGo,f܊9 Da? Y0XQo8=yXg(؅7 ֝`q &d-4O-S&GwbrU dOhڄt\'[Ɖ%UKfċJ'in@'\:Ԕ]w2UBAn^CVA6ܱK"nѱ;sjߓ;-qeP_79 v\F(n} ϐtu¢R*n>,(q>tC-IgG?Y*«0O淽o5&ri d=d"ڃh߭5덻 wZZ'On_zXqEYI7:%r%bf zA`_q8Qd!O,!b Z>KEPo@2CzĊ=7c!bB}vAAlxCh@NSYE iOPˆincKp8= uKo ?{$ceb __O k0tm‹nXTu0d7tuU:pIGݼ^XGa9tPI.nHyt\@&H ޏ~DLKS^ZCyKUE?v2.)ܥaʖ|n ^ŊE(_MKLޱ^hPsw o"qkxtQҍ4Y!+wcٱt\q#a`;%ڥ JzUt)'P17.{rBw5c@t;wXMS@: S:OI~Ry#M@@./ѧZRjp ?Jw>CkMAޣnEO#wl C6=`}s{BsfHG&xGA zu&(i94^Y%XU7b)pYMZxl:!RA0'GsGl=:(~3te!_b|d(tT5{7 1gѱn^Wܒ;Dz:rR0@ {Xy:{*=^k9 Lm*?u!O}LɂbfE b?bǪb_ZU5̊/iob8i\ϧٴu{KND}8C"&PJ|kT_ox;&'hF<b d*ZPܳbb~yzkjj,#Z~yX d"|>w%uO? OCswXlmq_9?yNoF~;f<|?y&qz:r nWAξ;r iJ*q2"&F\Mкݽy?MCg`Xx9єR5iq&*SR.q v j/t+QۙcDġmW]˟w48!~˄¸'J.? Z/;L&ΦķiXMW-2!-[$(\w a0V,~mm=$uC =uV:A;?]9=:ѹMv7\!5m: BSJquRџʦrYֈvfΏh=bdJ.(M+$aQ3Zz*\G-Cq޿Ja?lIFpgB5aP1Y Lo{,Y~fMP1$ʳ0sIHs︼pcVJCz1hd^7R#PҏK)?7 ):o.k`f(;Io:O9eKމ{dʖw4&PbZln)I˾Vj܈OGHdSc^J+HGQXt^C;َΏLRyJ7]>P+IKf, K/ #Jssk>f$`? BƝM˃燺 *(O֫G90'S™Y>Kc=҄۩hVgBE&VDze4yG m^vEWc,O+[%T%.܋JǪq{H?hd XūMDh;7>(mbn'+_uZqD[kdEvڜx222Iuu=H^ Ӹz%]$g񔏞or*9ϿfY,+RqjI\N?T@+< z{y^.ؓuv,6lIOD/PmX3׏fݗJ0]$81nNaj]H,X(M\xxd6{=RXDž~x"ZD[J7v x3vS5mݳsJC T/mϹh\_/#?{2ieRߪ١iR\Jȫ׷(Im\+|s}R!C%m]omKN$X@^w'ް?zMd򭵑#{H"8Eӭğ6sODT"='Dž88 }]fuMA=6K6+ϖ594̇Lw*nBˣ'2?mvƢLƣV PȨ_#9ko2yy:@:oȻ&'=3eh_IQdCIn(ԠXyly^e3r?XYgKlK{ A4B% xZaR%zPpEϛ< Ѻ44v.'8ʶDkqqoL"vrp^VEj`MH;]TMM=yN-h/Nk,no/ VDNxlw[[?VF 9jKNY @}U-Bh/Ѵv{X ]&;gDzѣ=w&f& Z@%Ϳ\2 $s_Nv'>ܜ_|C%rlJ85ߤ$ϲX\iMg8+A8b֨3dst$w ٮ}:DN9sӂܡ,T `8e 7r#wϤ಍̓1*XCZw!2iT LpJ7qӡSTwwmZLGC:= (:% J5+1SW"Bgw4P1TϮWy; qu1^gyyufT#EY~6":y.sj^P2]OyUz.n?atQ~7 {0 g}uq05&XhObdEfj7,̿2 .Uj ON9p %Ttirx=i0MnДרqNtD1!۽eFг|/6֝NΝY)KT JǛ۞@*ۗ*0Į@1>Qi+%t )Dm!n&7,hv (Y{󫞾#(+NbyE;+"CkC/>ᄌlhLy&*5nY{I(_A/Zs `hnJzX.:w'#']5 jdݍ3gkzA)S  oqee%<*W|GG1_/aǃktBt =z-,y<m P(,+yuġU4~vAPVr7jgabsCqWo8>h,&=c5 b3!s-v0Auv :MMW%~c NyG -ŕ| ̓bRqše1BJϲ>{^If2.Fψv|^M͒ -mRg|ޖq8R8$WIOf:$)t Cv&E=(ͫHa"hl'uگgvЧ? `gT r{]ET4?$6kA|> ONuR8ݛ6x~H۬f^{ yͥr%8Tg(<L!51WSO;Hqy/:h4?:Tp¼"SXzѝba=9=B(LVkڗ7};G O^4\FD21A*!WoMfaL(z34J`xRʹ |2Z{Qak}e)/2N6RXCS$a𢄳zzEԠ@s}W:)6C]]1U4ҹ֦b<1~7qq8fHfE6Ta`v#z gJo տǫ5>,Ҫ_kT - \g[gg2t@RtxKnJ(P"Noф;bGđe8oCPbcSv *xuJvxť &lqb; \ MS˰G.|,bN2 Zՙ(smsRZ5?l+Ӎ9"uӡ?Qj*(4Cr}V<*LےZiYQ![i!gN6V| Kg\uKZhHs|KJ+RiaA0;6gX~ XҡOXT׏Mۆ=?:xK 7|BE'6QTc=6 rM$IliWk%S穢lAF zHOdCSΧH(gnNfzf 6~*"V1'Bg댲*_B&dZ&ሶ!Ν.UEDltZ%X Z"<)y$Œ:w ئK/e>4DICYF~HYvJ_̓l/8eHQ\]Mm|KcUP 'Ģa80e˹ fZB,FCAnGpŝIu(l5NB-VHQrp}oc/sN;iHۊOsK +9R"1>zP[R ExQN"^ݢdf]ok[|h#|1EsʼF_|̟ aN,ܟa~ӲKۅ^ʐ[Ύ<+f)dl;˝L)ъ8htqXѻ(7c툦?3vNj!7y};eyݕ˭xGL-mB~v˙ hyC&n(gKHž~eN'N)_ 7pM,XsX%9$cLS ]4+K^a@q6c.+֙6J7=`jm2--n9ֽmVf= O^htoEٯc2'VںuGa݄4X~>^pI HXmdz(#W%K@.$VFsxd~yxmV(#U},ɩ`bM/Џ<^Ăa~55N%/|4A <\SD0kwT#3##|ca]g'<^TVg]*IY=cE[|j|5*\qg*+"ụ홛URlg^nt2Vr U渚'*9e{DYC˿z; ׿LA H>jH[Z>=6DPW/skAJV2~U{8p%MZwAg.;>WC:T'V:?ٙv6|c^0޹kqhjˌԖ̢$g+x>#nViלq ⧘sZg "R^˻L?~I6+<}Q7FBow+f͝ #`"ȷ+]6b\}}cS ӇVd g^̰M4)F]e՞I/舡?ð z'w=A=]XCv*b&{Evڇv]8泲V v; ߈"%lXr1 ,.DZM@*O *W7mr:bRmZWl2W=W*vsbJ]6 GAQ_VkzO8n)G%eώp\Ӵ h&Egyrg* -æޡ FׇQ|vG- ^T}p%@X}}Ww֕l6n֪Q-qʋR7SZ)Vן4mOtW ƹ]$۔u|_qO9D%D4X>./}$ #d)u>\j2>D8u Bkv˰E kKPu hC#yK?Ϋ xhfy;M/ѭN']qiQ V3kYP%$B/x(?ްŭ.T)Y37+{[̈vrwکZ$'E~ ;hvy]Z&W eQC )DKP=un\DO賮܅Ŵ3bZ+7ӂj>29tft)#wܙJg*]fy:ڙaUVns5f57}^)gUimz6O'4 }*ɝs8S:cy] ųWP|J09?M(Ot2|S *Z\՛2SCMWqhh6uFSĜ ɷ֘q'( }ed؃!t& ׮g9rON.ThH=%%0&kw FYoHCE1YflOǐѺRA5lat5/tmЅ$ۤ~!"f=XhǾK>{.|s[2o!#1z(zPKQuS$w;Ƭ~8lĎ_u1VMhưKd"$"h AWD>nfY+Fh ?n7ǮM?KnMj(B2j Tc-=>fMdrfтS$ҥUμr녻I\]ߔCSlc=*!TeTzyoX4!{oy4\.LS^Cn*JQiIXRt^FOF4ԷpɌa s3\aTaBy :<=zt6zȭsx>S?c# VGI狞;LTÜ86UlbX3iw0OJ;}W0޻tUyX—jU8.O+,t:0[Plxu-{;ay $R4StߕMQP ?b:*~]v[f  :v/R4,r'' WzK,NCo\^&2+^szpXJu6geOȃ-`D[k,3s\z'TnWDihtIx}"jsEN6mD_HOiмs]uɦ&\m6l-nl)G2ѓ*?yr}&(M+>09.l\:JFo @RpN wlߘ xfCy?ډ\\<ߦfvv^Wp G4qO ]7K 9I J2oê􏉶+e,Af_Z2FD9a ?3ๆӑ ĵhCh虗SoS:"|Ȧ&ƣPyK(At+Nzf$pl&ɰs I\h($xH׏>LtbKLjʖ_u78UAWNuWDR߹iBfB]qc뤦?K*(;_%|0O1cʼႆ%sNҗΛ$4:t6&fgGX* =B/C)v~;תu_;SRfW39CSE%١6O4kds |-lMͿ/{[X*f:&ڈg[P͗?/'RyF=X -=~v 5O\vwʜ2.abfrD\W)(|EcJ^ov¶TrPӝO.#V vdtqvdu &.`X\h{JCd.DW 3T|tZ$'}7sм_MX^_D0,0!v/-E#{E9gÎg<艴l ֏mI>#[\`ߺwZ3Ӯ AgZ mg0YJW/ʍJ|x<ֳg/v1=L[5$J1g=O(@n5nq(KMt?eh 9h(`毯;H#~S$5bc~)] ES!S39?\^C#>yx6\[ȗ#%̻њ' ˅)vsɟLjTNfNN/:FpA}zэѧ >f5/)pjuMfqތt4ޜĝMR'4XdûJ Q:vG@i}r5 1S&*h`A=}zwיc}%G%y\Wu:{"'Z-Ex?թ\pf MԸl аuZr:8{|Yh:[$;"Mmx-k`-XE1_*f$vҬmm.;t<3nMm5_X7sP# eDԛ/VjJJF2*av(T,^9Dt`*|ߝIo;D cP:97p#Jb,Z?9]auתԴfLBi'~I;]˙yq\7lu3j]" S8͙q(}:aN^~b[[՘(Q &Jzn+ISn [Lam^2X3$ID=@MXCx@~u+VFO!eh:%U㤔)~(@cCC|.[]44Rz\54UCj8 dz[7_2aocS  bt zj&`Yt"M<`>. %C,^RyI~׏Z0+0OE"WA#е<؏y(P/Vp}gEh]%\5W)lޥBb}ufŶՃ^sivRQlϡ)T o*RrFkְGOI!®t֩pIP,u g "SC1%8I \=7)@ JN.7X"6sʂK˗ՐMA7ao~ݣsoSn/5?>  "p |γN "A>|)9>zŚM)ϣQLky [yBQY SR1@LuQLrw636[0C(.*IZyoF4qݺ5vVG6gJ#vx.,5>NS [7AEȤu6-x1@WHa}wG6UCh8r] ?@*of Iu`%ͿUn_g7,Km|R.JpN6-CAWC:ǙH<ɠ~P-nylFq< >?Q'Wm\mbIz("G j(_5TI, .8Ks&v8n _s/OL:'N_ܬSEK ps 2R9 eT]֫'@c$ v{3Mˑ&FEi7[AK /u-QhE 5.Wj7ܒ2!0 Wu1)"VƥiֽR* USFS{Byga0-1PRf\w[wdYyG5 &h ko\uO8hi{+U߯lUQQRƔƫ/TYi*bjwOa޳%[_pÓRyѽ$BzCro^g8o/śu9gR1+eē5H}괮*C! "*Ⱳ~NC(\,Z, ,oVP',֑*|Sasϧh38P s ]gH>޺ó*eflnJZ2E I~g'zj9 -$TaN֩"0B@ro+k"c$W(a^) NȍrHiPL9]h14,1WC?;bRС`m6.*q(GiC*"N=!1XsP2E'[}vt>EQC]W4e  L]YX-VCԸPN"y=5ZaKR m糩M+: XP+sT`>CYVG9j~kO%ZԱL4%!)u7?" qDZ-*gK19ZLB&شqiVf 4ĄZҞ3$vV-.vުuywXkt0s.&t~[/h_ȨRY^?ĈAUk)(+юSȐ%XL`+/{h4>D4>:Ff̂7^ P &oήl˴P ~W( K%/H<+]%.*w|Sf\:/|2ۀBn3#] Wlz?+$T mP _wպiYLD( rX>C9<2ɱ&! x,)!w qA}2\2|mu'ۦYl:iz(`  {($.Yg&LdݱzѬZpT@}U?]TkG9<jO K|-1GVǖu?CbbNZeu!>X8۰^4֟JӤ5wrUp4D:g7vJ%Ʉ >q Ö#7 ͼ<_rMvaCMq -BFpdWmgHZ1Sj9=K;I~i7.Reɗ<Kf?^Z*@S$|KuInY;j`eg7$yMU"x5U s*oҰ[u[rFia[BB]mplphF׆I9uZwKz$fgU1WNqrlȾ$, ZPwdG߄[paK}{ +̰t:l&] !3/sUzZV` 0VZ:/iW6JqE~\7DVATo}nEd|,)\)XHݤDuNct{v_sr)Eսߩ|?_ajBi:Ş8]jZ+ }sYz\*e~#䖎 ;[ ""Q 6eHwR\Ln_i܊ & iMHfU#aچNE  @~Fd{>Hw[s{&s%ɇl]QǓ$$I&k P8/́ԛeW^jp[uk0PW4=zG̹?@e-C宿ݡGVvf3c͹f[l"ZTZAwhë4y>tR e^"е+)a!8i/_MdCS [o {׍{S٦?q |#E:N{;>yMu,Twy>#uu₃*ԯZslh]WoHEݏ{" QaC>$p]jz7#Yhbi /|U]%;/hvHkX%X>wcE0C 38,&=y,Țܟ䣸 iݺ)$JStge\m:]n1^ saz{-Xs+y" .2^&7G2c1૴}]r@#ȸMGh2q6 ȇ MaNu816AD!a3aX@wtGdJ(PMNq:5J_Nݼ'}Y7C׬X>؝QY&tu;TRXS`җM.yoojrG>tr o"1ްYRk :CS6gea6{p3 ^يs̥ n QVFosJ1; -hS:%'E۶ou$@F͂ܖw58g}dO@3O-Pd7`z뻬%Z=h~ڄ=„)4sF  bdMPiҀ RJ]Pig~Sw&\N2DA5rz;^9Ϥ Qy>;ESg8ZŴ6H :'PI.Zϫ,һљPh^OQڗ[pz|MpouݨŎgGu1̧Z /ݎt껞=WCNh%{li&̠{obe<־؞Kx,=q y#:)ajX)}ț@ˑ # ¡5`yi.!64Ҹ}?A9X '*"ʅxb Ά'rLy[cڂ 21ie]#U .5})~Ɖp]ҩ˾o,|E`6Zf}zYRSt^m}+kp©7G_$՞P\ahtSdSX[?v%s_#t<ŷ7>wɷ{w-_g3`>xBg?YXaYDg>$%s*%(PײhpSj,χosT 2]4<yȜH5J}2Pi#;.'l"ǒ1s+?:p,GKNa *AhP }ٱy:֙> Umk~ ]v ysuyx;?rXzD4jO"Ԭ0ɂ_|2Pgo8/xӪ?^q\=Sx"W>yq@siy"ƾ`]As%b=}Bpw_ZC{&sC;%U0J+IjdCy~lr)1-1G"S5TOһ)ԙx|˜mrpKFGD%ޥEodN6Kk{AAU8]`^3u+=]P.߽\N)\l{2|Ɍ1N.XI"K8f`;p/$ xK'5n4DhJјІ43,M4V{=_y 2jNyhɰ *b* /י!gG+%t>XO wc4ݤI/ i]cKRuYB'/cֆ%/r?Dfh~Q+ͮɓ59?P쾿"yՂ ֦YI ou+٢PۣI zP l]LNsEx{@gTy.SjKʹfWH4DuDg *yεL)y jx ץ'2QWaSlu$٭Wx^5Y%L?OVyB?ahYI~O-%k4M Ϻn' b+5 @*9g{tzmElq fpf̷! PEgJHlBF_33 Md[DIv.EW qiwy2L;|حZf;'JT7=ʮCy~ʞD?\m/zSJbB(P׸AoTBY݃'uuf?]e^h5G)O=2r7ʰg9[#5+/ hMtXt۾<T\'5ЦfXϓ}lWKRTfCmLs>꽍fK2le9=)adtf:C&laq+C0+|? ND􁪎\s$0\vn̄?!O#o1$AT8`i~Eg: Aw9%>\i[>c*,qQ$5 h{'}]!in"E­Qai#`"m~( N SY>"}^/*rGrr7(7&Қv`Xh>F n(Q/M,X>@{ ͗ڕde '[gEn^gؐ*gdlL5Y\" N||n%ݝG:*Aj=h@^M$)YҔ#b/f57N(+:2B-;T׳r#fk:.Ÿ/u ׶Țw:d(r\'4Qopt)@O[a£VdVo4Ek` ?5GFEAwLPϒޥ,~>ME۹}YARt|ƔN\j(&ը򾛤/D^Gޣ[l+y\J5=) ?=&u E4\;J25~4}31/mF22Se|?&:ʅų68FF/8N_4C `A;BJ{rڽG*h>!?"#)$OYj6h$oڝ!) 8iBLE,bEБ#_}qmc=PO2%![SGS3lݣg#asކac•gu:)7ߡL% L_zWȺAY>g#2A1x> " ]Q\(SCQ֯;n?/ nR`"8PTEN݂=cyB"'_8)p;^6z>#bm:@B y,,PxP4x xAmVq%]rNctWGtJݿ])g+BinȬf֚.-?Ƅ3!1Y~ȇ5s|h: Y֙az<`Q^g5D7S\h"C ǶOdW^tE+ *pٹ>F:G3܇ ^4RJ&ԛ׊a-l<<ޥ,]B]ЕIȝv!4YҮWujGPͰ9j)\qt>8|V`$y-H@m2f",Ջ0rBe+1YCXQ* p-Oqj9+Ѽ` #If/|GOYL ޠr?4\Ӝ (Ħ9u0xq6l枩Ҷ"\W_z@.)z6v2Fl1? w+3t0m]ϮKfdkW) Y+BțӰmbi]UWлpk(p^v13B;2L{d47)CIuv 깇"cae|%"`%<{nP&3sK6}^; ڸ?DаdYHxN9)K JM]l':IkplC>Mذ\YG/Pυn5t4G/u siK.;`T6;bwP*eYE'Mr狥#p>$ KF"8PۭS#e5^-pQfP0/1L7vuI稳1|Sb},а$WSV:hUߺg`(;{J$B%o Y㻸+K_XQ,|v:guv` n/{Gǯ;,-ՙ*Ps5>Eo 2ʻd4kw_ҋO 4z[oP%yӤJb}{4LzNl ]~Rۮ]52IĪmuClYRlVI-@[h9 OZV@ۍσگ&:nA%΍[+W]TÜ@IAW>=z!vCB9璧qbfC蟙T mtAi96:5_7L9t!<#3h:ty*oxp y U]zdw=-( *b:7X}єAc1Oa/2HNIވN%j4x]X3Pnт#p- ) kZ`2P >3u~j}N(IE.@#t 1u9Z!Mpڠ *u׏l^,02sOQ?_JIt3 fq!gȈ?*xMY>^.4srXʅB:zyOIa /4!Mp."mz?;_jLm/xƚ lV|NrOZ v/l]"৥ѥF'hwm_]JB~};ErK/r3IBQJDa:\gG|ܟ{3ő+:Z>?`@h2Onl/8&4!9uhA< 77T-Z"EqN&V!Qj(@YS,>@-L\x)68^닠e )<[gKA9xWMDߏc<١jJ>Eh&Awþr}0`3yWS9 Lk뱑kOa6G1^MŽ^L}L%w[zFV;eax y>?!yܤ#{g1_ʾ9RDm `vw0cC T޺'lDoð#k{mTz;IӉ͍VaǛNzll<2O2wl񎧈4oQS?ߔk#Q Ls|A;ͧ!4 M#~q]mFujؼxAƛC;1IJ <$_sҭ5.Iѽ,x?c|gS`n:c}Gccy45NkS )nQ^'!bz[h;b??y}4.Fa#rGNZi}y5 qHi"{H0._["%AB9@|rqV1` f|,׍Z`V4ڍ-͇C7 :me)9+W!EJ3b0燔C.Frd[ݙy4OatWU')%ֲ(;.ɇԥڨ!3:y{ߠO|svΔ>KkbiQHX9H9߽_ɖwq>Ië8+m.I58őoJڅbI/Rw,jR1%o=qܰma?6lczLF4_1=}-Xˋ5rҥ𖓻4xcT5pB/* r}6dX ~COfmv,g8y?+L>3IsBZF6Mh q [F1xCyؤgC-r.c9) ّ$s$>}Hۍg62MU!x"ۂ_aʡg5M)09k Y`ѳ)ؼE;Xblq $: ۼN)ȓ3|9D+0S7dSh_婒DLrLy>S$H2pA<(z re4 3vMIlK`{v]`ow^vD "C7 N|GD00 r I|wDCہ.\vLߟaE ȂLlرV3TiQq莧d2U86CElqV.[^eH]5xdm,ɮ +?s &fsLr|8a*\=ԔIr &<M P"K^d)B|duӍp/Qdž>etHO@u+I@F)[Dc[DXӥ6Cd/ȋr*N9Od#~G M{6'n8I,$NIp9(HO~x_ki:nJ?Rzh\B\F~EX/P!$ 4Q.,('ܮoNWO:Uj2-_!-beĜ>FNC\}WhWeIh[1(G-5T\Yh Rɇ%zgab(νM"ѐޥSEz6Lp/7:t,Ģf]춥\}:>rا ɒP|:cGBf~ 7IO: JԡGTՌ AƢ sBg =ӱ)llh\7%{4ۇ;Y}9RcgRVU]^QöT4[;:8Eg\6Sx3Жns3DWlivdC9L wpF.цmM6}|zq rL Z'NCc]xHEY; IC I2$u\zNy ʃe~fW,Eu?zfUV*`L]BkcpM[;۹,yxPa@8|0N$uS&ɱՐbd(goTz%=`o._xJ 1sY+Jkh2N{N^H(-6<5a_\W}F+m"m'c}  UpO-(%o@lL*m\sun:c}3;f MJM .lDDԋh4&6"t)+eGtʱ}#gz!Vh)ij-yĴ5$NSU2وoDZaC+E3csؿxM\LE uwrD[uѸKˡW0i[p(ZeUK<%2+!hJb\Q"ySGl?a: ?DW,7a̼$hp%l͍t_@Es /DYH e[rpO.'&(|M];ݸ5$]ݳAAm7#R\"J/[=櫄(9.~Smb/ޥ/K{fo-bSzoC.줿{ F֞ԃ-6rGDBͧ͂{.ŇcKky 3Mn(˕bOEVMb-;}ȸUVn6)}_2`}c"paY3ڼQr4!Mڃw.4H&8c"r |Ç5zVq~("[^̎q\̉&uMaS$Vrr?drQ+)7hyMS%§r°tɬ/d)}0ZvjjYuV'.Ѿ`ˑػ˙ ?m+PEU+ji9,DsϜvmh!J*s#;A0t(i yBlwΊ\EX*=Cܱ=mNYJή<@\q{^궵עp6%O8$sG::sNpBoNwM \9F0T-4GQ%{00G8v. Z,'u&SF҃@%հgq_[މM1sC\%#"9!4-EWcve/zr )luxAP+7isϣ6/39W2Sy^g9ɢezm?Jy2)l遄s4DMhrXyNr;̅S4|NjFe>Qzō塕$ }Ѓ;D.}WN\óǻ VƗI2YrS{O3t م{cOU]S.|s*>+9OЖdû2m'X$}'h["nB4VѾzdXN?ٕӳoa/oy-?v-JU'o8\!s ŶDzI*,/F91)4=o=ݞ* Rl"J~\j:^K;g|0]Rꖧg:--iFBѫq baΫ9IfTWavҲ^H*ك\Uǩ_()Ϝmɰdd\PWS-ceI Mz<_Qk:m*gs|.,?@5:er.uZ$lq,Ҹ/Vw,g9cCb Zk9Ug }W K>Rp &rxo2"W3Eٰjrn@>T!wS^w t]2Ez^>dܩs!r>yn7]Rb U@{@NU:׌f3'Xbs&l™B@d]8NE3u~U[{$xR3޺NFXho$nQK% )- jX:L3&}ztTw0.u.lCab5%f6 Iv]h㒇T_t+g7 _Ҝ#{=ߔ>q 02c"4] x.H~SkN}YʚE")83 ΃f@m8OTn(h*nw19쫏MU|5BBY@(}'Ѵ}.TޡD纚+B { s*w7?[QNn*d}[ |0DeC-.QMk5EWO(e z'ް(h:#FWDx$0T~` _/,T6w L0?DhB">hXw{QyFc .‰U􃷓e|MVv4PF#T {7 y)?x)m-P bkZ':ARtUz'*H6yuEtfkdmq0iZgRl)OƱ]N<€L40_LS:yD~ra@QD ӉI[^Lr]L-p3%kF!p[uW^o >2qOEq޷jn8?c=3c;k~X+^hKDE6埫30OR)87ǒ ;@"blulte/Ӟ?Smsw_<j8u5y80M֮5C ChIW %ֻͤi@-6YHKlY~U\" t;}|?N# iCt딎+@ֆٜ 8IxtwźChbt(&dr JQ Iኇ s}Dv?Vu̠C!h[Z)ۋB`9T3LU~q粩mi-rZ|=ddS^^2a عaWe˧/da﨧`ՀT?lI(@N9mg#X` =%{(դ}wФhe˖?@:Aﴌ;!ȸ`]&BP9\Bl@3'rPIޛr$S}8Yy)>HG2lPG8O`_Ŀ)}yG<'K}0yAh<;P삋,sb%@Vwܝr]\-3gG/}O=;Br MI&N }B;x|#M*^8-NG0sݦi ^bV@C  ,TD7r{鹮 DBYc2p$VJ )Fzj?KwN SOj1 p]CkRhdBd]MFo>-I&=!Oьh5` mVwr$2kS2Hȣk(rezKF`0UA90S4=K r:-2"CG8$WȀ Аcz`b:/N7FD*Q"ÿvyW,n(sp;5ְ `H*ѹ&r!PX t~R7 >z4=[#+(K3s/WCEV`'p`zdE\1suY$U`h5W"ZnJΤQQl+ zGzO;~^sY !9C_<ޕ g蠺qy=,o4 %Uj4+lf׈u/e VܺOn`3KKb"@7"QJXZ5QBg=XBĂ3wO85>h]wsS񴸭\%PG8EhC恩5^"\|uV7sBcSF}SITku6 07édLنO șxo g3&-_$R {$ XlwI5%,}Yn+~?jd^M& I+iA˵,Rdp[{)Ńl;(Zvg''ˆe瀲V#Ej|,thh' hN7`] 堎D}}ʇ7q t$3<7=PwԸF hǗUKo L  L#:dW#gF[oШ೗ĢXjڌ^m6tj|Fo >NEKpAwUy:0 %|P[!G&A9?5G%*XVw_p$ 48v1 IS톜vK&YLV ؿ=nP=Ϫ9"6՞f}ՠ3e$vm[ƼjvEbbcX~ٹrODB(*.MF]o42,9y[p  ѦbSZ/Oʢ 5ζGh"_rf,Ց|\E_=򐠉C#*WK ˢ>yέiQz RZD@{yaOi+CM%4 oPcB.$MW;L64;B?X*o|rTzFƙC2vh?g*1qޣV#TQkg@]8`h׃jOy&e3)C܀ v_pͯPZqi?7ᖷqa+YO5.#SJ`[7 _*C5H[3: @Pd[KQb3iPfFr/u˖l,XK져Nʔ&&)UDtpߗEu$8hҗ$#/R Gl) I<~rlsiMH6gDѶbeє̓*ʐg0mQsA(VVV<&(\Jx:b YQ çלGgE)o$9]7odPn Z!fȥ-uhkGl* òJ(tz{3B!> da*gELEV4IO)bR S2+P:QzڇuIQ5`Z4;׷lQUE:e-D/pj!"֤FS9n$'w:;LUg٣dĽn$_Ek8^P8Ar%'{]Sik ǯc8BVhzJA.' $]` th1Fb;VlBp07]2_M)C RG'j![~hLA.V_i(٭B* *${o+Ɲ^hziRl˃,m\3^Dcw'H~|u"ͰEh7/;7$CQS<:ѢS4 hDI85B;k )`Ɩ::x`T(*r%/_Sw$Y^G_TFcCrڶ믱#Q-SqK3Ձ.j"|Dq2hVrV$ TO Kڕ鋓c=O;8UKߤW[2?5'8^؁I.+d9pG5˖^䞋T}-ϵ"*9!=9+UU w:0S۾@ܑ`ӷ,~? Q GFlfĬfMm9:?E> M7G;2 o+W5h[fycSA-Ed}Oq$!gHJa,"feP&Fp͇%2–.1Qs˿~@3ߤ\Ki>ܐ.|K.қvѢ#w:eH+MC9ս<)/|&ղo8oPqD;9X-1TˎWX9ؐ|[VU \eÛ.ɪtlx#;՝5|i$ޱyoo\D$!?A]ԲCГ2bFy:4d0!N+xD7Mƕ CM2 weҊK6֠.ӴLk ]cNRd޸LYę nXB+ﴦR|B:vs3or{SfXfY`׻P*CSqh p=%rt#RV&M 1+m9lEbÉ?aRYm>,n>K--pQƲ`ݐ5?i,p_r3>*F6ݫUc¨a2Z^ߐIƆDZw~ߞ{^Lۭr-ZAypv> (a&;D~/u[j% #DV@'3T =Z$og&fqdξdue%f?C/{.zuBJ-5I~5/v `73D<;l՞Xn1_?81,KAYQR7v,*e,Jq{"3A:9^`P OIM18ՂOab(vDU:z ҂Ȣ\ĺOOl3KS2 ,Dυo (nx_ܕ!KxB7`Yjr=3Z%m}u)lkd,-P .m@xp!QLPdCQz(:kM) ܰY-Xx E}?19)YwZ ?,Σ[5SІޣޑ-Rƅ^B;٤\ Gvn `봲? 2̂zղʳQMQqVG0/LQl.\#w(,\ɵthQᬃ/YSc~e,֡pzǫlw|qjtL,ew%"s#pԇPBVLMƭ(}sn$ˇt(EEܪ;IƱų))z0Аش6DAt[,/ }A]eJ287@ѽ7A$xXJi{9Z(Ic<! |*qFMyVHDKdP]xC;jK)ﵖVc/*eˍKyh,Ws8ڥI9!Juzߒ4!ޜGe8Q{DFa%݁i^RCA0;=Iizof(yV3jCJcQOmKUa?tX1l|m>V9lFatz억PB1Y_>Ox6`uʝ@QB}XWo h]9<\y+o# @*ΐ4nW,"\K,S^Hk7nB$8{PD9\kaP' OCײs _H? d'uD.%'`7X - *wF"=*eO`F(/8fCQ' ~>T(<@XH;nXUwr+CjTX2z"b4&R+!9 CDUFoU`w8T9_)1`HɆ]qwNNmGfɉ"+%g"Ȉ)h`q)bZ D$hS=KH2y9 XL4e[9P3Y77T-J$w3d#U-̦07Vp\|+2JU#eu״2]gMX:HS}eo es$ ѐNg&|HP ? j<]\GW@A@Qu~tVD hٴ|7QsC:!4XPwGZkSn2 -m%K1sZbAV*H2]bztO,۶Y}nԆWZ]D1c:8h;j", $C`))vYs ~) dFck[f6r 9mUp(|DM/wʔ(^* B̜`1w=&-xڽUm(kHґ2KٖREi.2@cVhQj@d,<}<]9lq~p^ *w$3|CvEM3}Q$1FR.wro7Uܔ6*D6qf!/ 9-ڹG1_+:t(ECFiE!tqW- =cC-S1R9juhg8=t!͢4Ho3u,76(Fw͒\f~Se׶C"}_(gn, Io}3!RVLk + KYp%Kw+ۻ6nã2RSgum?=q#ܿu  xij9?Ҫ's{!H 5CPьCC¸՘LM.*O-aO;V;qs২Y_h^'rUcXӰF.CX'Kߴ4z|}hH`˽Yv٥K pxˀvsߜ"ۢ./- @ UKCa%P,lTubW,u{2k3ref1T]e&VTXv{ 9 Ӟ1- +SrJ>KjAY -_^']+6Kv.B~A)~P< 얒WQ6zA3\D `KTȠ Qf $ǘY%D/.l#c2ol"e˘qcLh6]}HƣVMF*0},h J$wS+tlMcBLOOG$[ R4*9rQ1\x˦|kO DpӤPd<(J \a"])ѫ䜬>@ e)>>q~]W#%Z et dkh9Խ[/E;|tr*Cr 9N6?hCdN' }I{GDKmJ'` 90tW=Ev# 6P9U k=|pbF&n^7E2/ʎJCuuLi>s-:a%z"`H^tW2#0.5?2Ǜbn;hq{&SrYpxn}T֞$.Y-l n9G}0/lU3h>jGJnFNX8u{y(N_AO&;A2Sd3"Uݾ(!0[ {cyVZVeә8a 1w}= DՑ3w3Zd{dYsZ&IÖE09QuiA'XyH^/44J7xΰ ;Ȕ=VY&ŠQo@ˤq/tYfuMayRNēl̎o- A-SԄ2#an-ƪ~n!OuB= &>M&w0Km0NfA_PP#Ee2gd7V7ڟh#%3,,=txd>*K&Yy*X9J9NR}Jw[W@7eOM"}[_YfSI~?E ?l np6;_[bR1聍 ~AiEGZER}T5RZ>V~ꨂMLc$ NZ&myO%7Qu(4݀uhozLz\Ⱦ`m~IhUޠGs8.r#`~t>(^~ËBº^\vM( 9n]@"n:Z*iyYl} wn [fic$PzjRh|W0gf9-˟zag.UT ~s]XGvu.r zZ o~s߂A=%}í٪$ɲzDl"E./TyʘK}e;&;8㆗6_PO*YAmOsY6$Ls%bHfF'S4'zbn+UP'QBˀTNXPlgyOBG+ 3Vz5dT1ڡHQ:QTK?K}\ NNꯖ?;\^%SJQxⅇûIDT;,T({S˲dW-~Whg\6]fu9]!MR_+^^kz~R'ƧδjMՌ\ƸqBGBg/KE |L΄'Q=*G{lQE3" L]6Zjz|Qx&ntO(i#NaN78blW$4mU<36u;9-RI((3ϖ5Xh hp*V(x'4(ci[h^^k2b@py75Q)O;M_g3JW2PZ׿J!* \#r5\w]k\z5{7L>6sߑEY=7wƐ91 x;D0ncuLGL:?=T֯\h,ؕ:2}l7:L`X&J,lp %4񻢊T,67:YUy2ʵF|#w*D<$2ms}NJ )̢g3Ƃz6IyN\̶qc3Cajl%n2cۀ~V0ű.=׿օ;~Osmkq~] Nfpހ/R=\)ͮ*3dn{z$Qs2Y$`GJȶyzH\%73K9^p}Ϋ)47E\01bIBWx딶SUer3U. C* 9QH}b۩QMBCن)z6I>|$< D?~JÍM&HAʱ%FQ\[kWk۽(hd(+ { FtH{P ˘m+3a-soYяr~#$kQfh891OZ kHg"|mhB݄s_Eӳ>Lo"b,ipR-CZP_薍@QIzU.wDl#zE3<7QC4)$P4 deYJ4!帇\~pXobzKS'|KG$TD)Ym#Se" G`u엻cRJ=9~ m0lR6Lk);MQV}jhQ :Л5JwfW7\4(\N"9Qa1 anbPn0Z[s yN:˴!^IYۓ@t`>2Pk$ φgWa=P5N7}c}_}9ӡJx#ZvׁUCί.yu7s,anB(-rzo^} Ff͆k~F?-\~@[]$7 d9>@Ϣ(^!d #! iXѼAt13^}EV!Q*2GrK.3;^ERD΅Gq~}NXd(]tZSTz5z<~ݕmRbDRLȄ) ;.=wZH.xi Y"6,NVDM,*GEg2*jx̳?(G'%a901fɖa3|N ]:Ot?c,{0oJ1-. 2$(F3syQTo&o5V2?/q'<.ln_$ǛXkX`~C6t@Ek 5g2D4n Αk-vWyڝ;% iLUqKʘ0@ 5cnL ZOaXM#-ILw\7.JʳTƟ'<2UH҅Ez(UhiYZ `(Ix} ˁm{-ONchX; ƏKf'|jvGo5zE,oGAqOZMQB[zT!GL! $@pŇYP(mjNUzⷧE+tsjPW`sj q})Z\"sڟE/zi4q_EcekLkj,̭Ǧ^C2i f9@żi o592Gu5@COYaWȢEPjk^snk ',Sp Yqr2o&u>nenwbr$ŤQfgm`řMLPMi+eru:Q#eāUAq5~#Qyfe@ϧkD{:w,GGֆ6m.'Xl#+̘ek]4G6Tzl`$eg5֔fl^S2h">G"ӥ=aQn\dF}ɏ2# >df2ΏKܕshJ:K_`eyduk"7M`AeR;d/ c ,<0#Q rJ;:ϨLB$I~fމAC}0gİ&O HbZ2upNN<^v'[$~$%&RK[ G(vGm>M SGF*C0<z/AeZ^E1E0{S(* Jdh(oq|4A۝ST:`EsHKlOJOoxԴDY:OMVX0NÌPh~*lF(1ٶv DY_Q]}E0Ȇ> a,sL9V,-xf弊 c!{PT FOّ3![Ud ll׷ç.Mr72c[ّ7Ryft^bi^HcM ?a֭BIHxJP(6ZY{@y,K/\/r;JotJB(|/.k&m]291osX,^q(#YSk" }ԌG8?AN~X-(F%ѮY:m9B˸/KȟI8+;Kj$ĝkb~ 6qMh ZPAP-hiVH~%#;?o.j\>i,EϬwD*e}'x4˂Y+D}7"Hُv3&{-TzvxzrN:N1gG :4Cg}C)_-#βq!]eBuѧU4Y3 y%({ͧ)_blV7u\d,zyJJO=}PA2Q-<[QsZ/ =%S7-FYgfN^QlfQqŗэ t@vp:c[ Eg 0n8irlSwbX4Wq:Mƿ{=@ǵi2 e>[6 6eЈFK3yØXMu{I/Ƨ5~&em }Z4{$KJn+Qg?0ank@SClOm)|A8x*odva2:4?u.`qkhu'rR9٬f {&}tǼN(j}-!>S .L\=SiÐW7MtQ[aBQ>C[&WXU;ϢҾEFq]!s6H+t64xBցZmPKo uBU@ʸ7yWex,.KƨVMŮვEwRY~q59G1"O\Q@w)תEy4P!D~H= 2וd[ ? s!RXRL6D{ii O+L1F2v2C?Ϗr=#$qvGHFv6=Ct'jA?[4-Z&h9r.Hȵ&"] Xի~R9z4|ѷ"ݢ3ۘ;VU'z}I)̭ylv3gY݄>\!gY$uγ}p~*^ lgkӕ`/(۫jM=l[f_n(4kM4IFS[Q #[ %޶ Bܸ ĉiaK DTS?[Z_tۭrUbdypEDv;~ʜg@SIBz)!2ͩnc(>E,iXL:iYn;M9"}lzElN]ϰig~:":a湬1QN=+c1& r (3 &1@7J= }Ĝ"2Ťt‡-fA b9̊xMkI^NNh?Eڠ.ڨJMkSYi-MYvؚ"LS|Q,m㞿`VT&k)J9Inhf_ND9ԌMhlDȒ'37 Pμ/%ͼpU1i yCcIl, C;/Ƣ΢ss/{zed5s&k*4= ;>9]fBѭe$4E8%7ǷG];0i205V{ٻ4{jઽA׾iܠK^ `Wy}Y.+e:d_#.z2]cvV$цJ|ZH̝v[@b&k#fmwQ03f- ǕlF=Ӡ#.!%ԓgCTn N=yh13OO*VCo/.8ul@k䬮poLٻpqO*sQ EzJfh~i<l['`g^E7BĩՎV '(aHn0;#yHC][3#2h|U\pZ!JeNaԈh <;( ڔ3mEF*өˣc铟̊ y,cq,L/=FeƟ:.n] d}"oӎ2#p&gÎTW53W?DYI WCO)EbZ ;Ev2ϭ&){"@Ȋ70ƚn,nRohba&wT'`TmKYoYf츙+AL*z6U*8GDV84urDQRq, ﷕8;JަnYW@pt>Tz@9qcWtWTT4焢C-bAcxQ]1EF<`Wc%jѤe2nij2|Kv- 5aO/͋D?z*HE^؎`sq-W=-;)'J|ilγXk2/oᬌՁ&O!fUw͝^ldk.,̍]hG5pAvk d~:vWّUEpҖ9z+h"f&t K%c=oZU6^ kh,l6 h~jL^B 7L7'l g+a%"j&~ۢ}Q?N'#>>so鐌)r~\=q7_1Y*:yWlϭ^hE6 sjZ+eUo%4'B69)B^z{ħZ~4T4YBQW5YPq5eKTϸ'L>^o.P{Z"R<0`§a5n ߀ )#+nO 5UXf=8ec'k𵩫/]kD[yv# TS1;:T3CH14ᅞbLc0}69~EetwvSDI=|BʪՆ꭪/F^#Lne4h-dѻ 0uByj*N[FsEGUXΌ3;X}_v@/]P#JLW}aqPq=]'w#"fy./,uռ Qfj7p5s=yD{ՙX1q^4K@BF2"xfF9>]|}"t3Jq)l'?qg7(6f<>5cz@-r({G~%izǝIttgsh_8OIIaT+C)z M.R?snp{4cds$0ρ.4s" ip0h[ !xffnM6%@.q8AI Mn4Hp.R_ըOdx"jBV"Cwr@E2adInE?j9e )[J ]0!C#(+LvWlwa=U5w@\7>TĭF&'zh&M`LxYM78loG ϖָ6M,5ц_ s5{&h{1tt:@}\l>EQ gؿHZQ 6 #])2ZA9 hDX\6 . Zt QRbdbG@EF=چkD[a4+Grc~8)*ԼHۆkɱ'%YPb y:/xt NW:& ,K=39Kk3}drb*uo $HQnxڳxG\rNqYT}ӱF=䂱ɓ)z*O U?um %?US7n _g6՗͘52߀ !׃k icL z0.kw`U݈ubᑑ*,-kْ(3Ԓ&@]JdƦ间 $)J118DCNaSzK$JLjr-Dw=v;̊;D4d^eOrjۺJ-dԫ/)yj@74ƻ*+ zî:d5ӳOmZ ݀jAr-Ӌ漾TU1J,-g>4Yp ΅|JiAh^Ϳj|S{Qsҷ}{G.90$'rsOX6VB'XTg; S-dI0K.37)chhǃ{ъ0LTaRcS6GI@.=hr #[NƅN^w;ʤ{T}F; Wdq.mD-k犾/&=eq 鸗@7%)T@패ؓvJ3l7$qlоuQѾT'q:Ct[+򂂾OPK WQKmpW]II 2.<­M8@]:"08xd`f*u/x6ʼnOtO|ۉOmЙA :幖fn!k'r$"ڌ"i5ܱ3l$"ODDktHap ut /3[2>;k20[S`&y.uJjum o !Q Tt7a]u%[:T2wO;i";̭#fo5Yeg8E~0tR۟bMOgeh{C;Ir?moݲe:HGLJ[tKh&L0DJwߌ2$enQ6u(8TZC4"ѫlOQt׋g٫,vrםYqٻ?>8duBMMs(Qdˤ~u4b*[M]F_4GCmXLYlEQ4»38h\\0abax'5fvZZP4;!ZrB+y~ص6e ;;cd1m LˈhoyV.74HUUw4S>.aAl5 Yb7^ { 7؜&lJSs&^a<4m2Մng[KA”3= ~xQ|Sf,Λr0lʇTZvXHAq*IgU.>\=]BT…+O)ۢWȕ@q&Ƈ*faIF:>`I:kjuWb;'=O$Mj /Y)3~47ƿqaƖ҈@!ml w3QjɅĺlYeW /фV$̦̭)l寈mlye_;c =Hf FfaLŒ[H כ<0AuN1PPnf7H֩E OeDzrûMi|mܧ魥p=V+$ˊT. ,3}5@V,x#-mJ8 t971Ez H @Xqa2ɀԝq_-ʌ1fUmCpJ`2YC-zL+uKmK{Qu>{ߋL7YGqXm%~1DMi s.ZwS\.-,©&G5E'S*ܰj2Z޸_Q0NA1sthvZw|KRgE;-r09596Ā/߀De#c΂n͎H򣧢pO/js5iUG/oS`˙ q4H״'/1RX70׀NI/xx [sN)RV7uSP1QB4 LY&dD$ M#GbN﷥BNTm/Ƣi'2fKa h{<(2Eڭm"LQE֐K㱂'u] A䣇(dS(jqDŽ^7Ti g"jz Ysf2;W0\6ɺ3Xt7ov-9$vSf}6hx*e6F3?YcV?C…sB:'wo5BTK9g7<3zHǂ)`m$ۘ}(&seGy .^m ._m<-֔z*,b,u\XN>t2[oX͠'.66Y:i6  ns]%DmJhpCs*yӓf> *)_OFçZhէǒ' eHe>4=)mM,,jaCC#ơ~.D2zI&(pwN&-ݫD-cA|bt4+8$oOZQc =ZQkݴ|bw/|ϳre/lLk^(kЀYkN*q6)|^->? 5i={XiF$H x1փ5_VT=7vd#JuEi]1K~% ݜTl2IyK^`^ޫd,Ҫ%/P sJfh6EE0ƴs_7wE==7d]FG)|s&;'tVZ'mɵv(^0Z~pPխ9[ qWlolYwJEɷ*i~uЈI#RT'/ѻ0E*r%1}PV`&`a_}*@Z4; v6>ot VqRx[,3:ъN] P:KnDi`hbW}N%ͬso槼ngc6] N8%doX֣x4L7ioOI3:W@<.2اk7N[&!YTgGglY2_M`uBΦ-#`du*`RA 4!\v(WT\ӖmׁS|Rgl++W6c%!+a)u1iAGr1خWcn+.Lmm$qCW2xQq[hF.ubL֓ ֦5PhsncڞTH{۞4,P㈳u -8ocw=#5%d2ak e*d@* `Olm@O qGz^Gsg>%1T ["qjRAx 9C%kY=^MJBL)Bwm jcTC\s:صfזAm,ȵ!˼!kؓӚ)(: Y䃀X'ϐ(yd_8yeP-I˶O[fV/LֲZ $OD+0@BZ!ͷLCiPVıݖnHI>GY|Pg\ffF[fT\gTx9܄Zkg?kă"غFd#b5Ij1L *}=Hx$ "I1OW(7]{h~3@UzQe?Lf"&5}. G/ZOAG`q=k~+"Tw@NQܷHT 7S({BsƓ\h /J_1@3K㡏_Y 5>S fj]1gʡN:ϿA[ذk^xw裣e([u/([e!a0y/maY'ʀ|'qDYPVr/PO^}: E+s5aZyk4ļ1Ut3:xEa2m~ZV:޽-\QR=Zv rnS. h@j \ dKj1xx(i0=Md5Ue^ &팴`_T/C*M2j6$Z\:dYΦ:2P ;4={C%3vgx1plTlw91JXH"ghB<֥2)1)Ѹi+bf|³/\M֏@zI jTj$5 {'|;݅bh?LZ/y6m + h(ݭMYK!" 2sQͬ!Yvv LZh2 ~=#~u?NW dڶ_" TQ}(!t/ )U$/vpv#<|>5%8_;p/ۓbr G.+Gs%lSkd| aݛ E>0^D_y3/jlD{/:x7Oˣ&뙲I&06.Ry5;OZm<j Ikο,O4P6-SQ{ kbቓIY  x4Fކ eLF-u@E1d3wZ/w6o%G"t1F@/&M*$I+g@]3l\a!eEԷ9b񛥯䙗a-:3Ġcoh9moCiDi&`G 0cy|~ * G$t}K{/T.w[ĸ9L&m>꾮;wZ7m[@ mS)kIQ08}X@.{,Q8%%SF(2KRC%v+te z?M]8v b^xU;Qg_(`u95(͕Ǎh#ڦ12||t e-`Ztr #+:ab2y;sVQᬡ*GrOFjT>N2UxC;м"9# %=0Y3~hO(%yyG.KnODQ9K>7ф@z$`ƱLj l0zESIe_%K\?$<+$BR~lgdqfcy&Fh~䏹Ћ"0hIfa*d* h#\'cOvSfdo@,!Becҽ,WtE{> ox#!\.0"P#ώqh<s{D4ɗպԦW2eA %Nr.xIq+%Gӈ5qj-2N$0.٭ [@z&P~@وnA'(0ހy Yp0UYX6Ek) gTnVuVk0 !ۣwġmM|zqXޘПx٧IƆcB4-ns&\dQe[ޠ?]>el#=*$|Y˂*jO,# ?E~ n!_ӕi9,M)LnfCk79$#v 5wԗ&LfOwon_X@4hUbdD;PLqgL7 soMSF*8W2D2ܰh mad ))e7ϸbZ9?u~E_=Aֲd>ڣ#caBM͖遥hAw~og_EQC`Xmk%f8zU+YmVrmJSs%k ˮܘ"CF%ԩbLi̫K%zԴL}/h&.̞*턾O.l_(5<{DUei7J^, e`LHql`܏]".UNc؍tfh-5`G_S~?+0H&\X=u88K3cVyby2>Jj/\=@U~1fGID.Dlj#TJcqYh*leo]gD&_Yt|NϞF.Äs}}-s(uVWިCcL%[iW'ƵH\R'&>lɼd[Q'n5}4fCw ̋29&ݡ|ğEVMW< H.3k94>?ٍ#lS”$IRΟe5J&G0zm<Ɣ6&s yz|e-լde)@IF>jOct'8fC㩋HPZ${0tϠD5\cj<2nTq937|:2Wce;[HW$N˖%+b:B7[jhc;gG 1,;=>.&i*I4r2r쁠QОLB=8Ò)  F!gw>b i'swքB C>y-KQ"D7擤wI(afAaςZ/"moÔܣE% M7*H*T29x2arN_-a v2P b;VdyԜQl;p]T2 O0m׌FS/>pL#[CHi;F]AI~s4FГC_l#h#uFD_z zV*/xqDl~k\~ ^sנVЫŒEEEw%\0  Y&Hj(leCiάl?1>i5\P󈠪ZZ,\o'oh@rC$Ź&eO`Hg"<$Qpʈޙeb,!֋ w<讉e7,ᷰNaB)5\ű<\Lq_wՂ[I[(b^NW1 sgOK6XMݳ5&،khtbF[1#0H&tjTJޭ?XO e:R)/~GbXWu"w\nS 0"ZFwɐYfZU:~FWߔ=n˴U}Tr{,\M0[EB^ +Ӆ=mY|vL,+}KiN 5Q]MFv(#Gqm$q)kL4!! ;̨+7} py;Pw:ZiS(z*fT2E^wu"ڋvCKwdpO5Xg(LJ#]`Ova LFiuO eTU{ *0m;yO]&|VYź`+Vز j>˺\jO/M E+edғeZ6tkbZmsPou_/iK/ d 29s9B!̔W/zDr]}m/^lZ4}[V< hg4]U< f ˝ϒc[Y2!Xuf/3M,n>g5V5UdzEI=٬? Jܙl}('A!K n0}ߖ|tʜ e) O^ED)!IÖ٢u9(hWd-AMEgjخz vGϦ}Xʓiu.r`߸H0c3AwUqd9[F4/ԗEShxѬtz#S,2BM+ZM)9EbJ\a=@ɜ8b%LԒQ@bsq-J.'g|$LYm&.~{“xYvCY\%7Ula}E5G:}h%7BW?z+2W>HW5Zb9~5a4LZVKNH}^Q)8yg";Fv4ϡm\2œpva>l~MY(?ϧpihs(w, l_hԬCٕP Neel?e֦ڸꁒ;v| ,L ZO褒=Oi=z-we6̣:/5~w;dVbvwrb[;~H] /#\$jږu Su۲9.8Mi_HIԹʹJ<%畞ZUOJJۖXIv)DКJk_v7 et-3\xE fAug~:&yyaEp bm,$,P919@*cK'8ց ,̘V+KYQsrdb6u8g/B6Z${vwPsݪv:p7Z/UfX˟;wd#6!y8c(nr`dcؠHJjt]Z`؂p zx-95~lġXUi'f j[t5``/j.p2 j?s`KBtg̶WMHJ%&ְwkpOÿfMQŊKM % u2*ބ#v 3ɏesl~ ٤ *,?8z59dz˗C45dn>A+A%TϬv yJc(,3QT~L(MyJw:qi+<,XtX&J;mvD2z cQjxCk|>8Fn݁$ 8fg\fhA s֔,uc*(D4RIPݔqCw.jDֶ!7(}}^ dfpThIɍ!Аw=BU (PK|E>[U1KP 8DR4꺝bZHRnà ^)-kks(;7PIp'^s깔)K!pԈNv7M'Zo&!}IyfyeJz\E 2*"FK D'L&Y)ȍX mfR_TNDz=1r?O$.sS^_jJ6E`b^S󺓕y9oK9=fR;.}6زpfMjsY5' NMTOP5쒢Da@1Co%v;'g:0I; LX]Z:٭dRbw<{k.w(wiOw ikHk2sf/IE9ʤrF 2q#囒=)OW܋Fѝ?S 8t0Z'C-'2a0͜9(0ܖ -) S>3(&bbEIwo-]!l6冺rLS$`[|"fplͭ*n2=OC_fdpKʊJM~ΫT:P|P,nh$Ȕȣ%{3w,(%`ޝ\o(rn]rKye sכ, ;pprBsltøu|*q۽guiu{Հ[Lɫ\c|"c7H/]NeȢPV[00}*J;p)bm;}]n)Ii_5<>+ ٮv˺-[=֮B`&w7Γb Q66 _ jzH21#~\_Õ]k2LyߍuZ1S;KMk$*BC?tM,] k^E'G_۱N[NΥ{elj7G2]faSjK&()L!'89 WLv԰5>\̵X ;qeEIV> 6y"徤\1˧EU~j`YsF~E=I֙¥'Y`ˋU'>I>ݩPeݽ'}  ;JI`f5Z !尦,MYxݩ$$]M]R5<+ O/ydzEqտǞS?SHZ:ְ~)|{9IPNh#vO Daie@cZރ3G:a#U@fs IWpf|Gіh^&uI)Y\8yK;ysfF)Sī""rGOYWmz@Jb ]mFZ^FyZ'ęEO2aB:F2'Ai:vui e(ǰW%} }UQL OOf[3BL[WUs5!;Բ,u=< 8B;Yx~x ܓ|-n2٘2C&DHlV0J) E >fƳiͷMVF͋ 1BkhS*wd=joa$GQI]i-[!O詍,hK{ wlXJK x?U]Q?PSH-};GM$LX3Lt⹼[Ի,Yap["ِ@D|*,a[ 569ϖy ${%F_ɯ49U:\ށsqYKȽaF1zGy kh¬M&tK(!ç_8—QkXHzWmzԈ־ZsІ`xQhh Zea'{w( u[1}~-˒|<RR V]]WO=Sc;Púl\ῼBd/3־vC{W&~oa!CQQSfq-5ѫ'2IW=ݡb]T.O &?ur-v7_aXHju-os1s0ɪ~G5:yS}̦F5'e:K0V͡SO~-u\r^X 46Ao3z5Ih^@<#2c9~vY+nGs5s׏;%!hY$2E]dzP%EZq e^!-~2%j> c&L^4LC.2K\3 .~ۻ.YTAd7=]W7r׎KۊYZZQ-P:)kK( ̭[Wޟ?$tg;rȅ+QKb@u:kHN}[ L:4]['/y]Q:O qt<`3@l@L>mfD9?_ePTŦl5[CK"j~2HnCVCc(Ϭ-zSs e82izi+.ײnF:q8~e><%paW*hzdXQ]=<$z6%*-Agv@Q`S4uj.~zBPp(ÙR#)FzwM'ֹRNH6@؟B2Tkd0|W .+h[5,<'$f'2Ug%CwHEK{ej OR vXo7E[)P!Aln;$oz}vhmD;l:u\lb|‹%Z dx?㙕QX[Bmy`g:Dow, 6y=jzvvwF&ɺ<ݙ @8{8&J6ٛ[%h|PDa5PIf5 t*tfoo %0Oﵴ8ְ0+¬nj؂p=. [:~Gu#v會sW\xLkQ $; |D׉b#78d0]}ۻ)pyQt}>Z:p\r ?R}{*Q뭌s0?>"mUwh-"9Ma ݼ_[ȫdґM`Ae[n[7ݦZRV$y;<>b1,Ź_Pcu֥5e˞$d8uk`1JnZ$vIoZ2.QQB+Hɍn-!ot˻u\4P^?١%~GbNך_R}K7y 9`/nIw4 :Nq$)sz8#ڟ8u+p4duķEjV>^A0ltc $ q&ˎvǓ>w\sGeQ) ɶ4>FqԱ7_EoXAlsEM&o$༱!~[Oaqnj4Cq%{ɵqݍōm&9 S RE|[/%_ie>U`ϣ1 Kɦ(8s]{)̢Wpq쪗.-qYv pj+Yd; Ed[@Do>w+Zօ~`5vF%_FQ+ 9`Ą~>4}4{ΚxkP;i 9UX~fbѦϦFCy&e7D#TNFe$w=kbd@v o32Y&4̰&+T`3KdCܗ}Qh0T|`5R|dWh6,j7eB(60ˮf R <i~ J2 eRWs}R^T2ۆ}uN_|.*{'_me}%5ejdm,+_p;$jo'm y :,R7:@ݾBr>-3ⅼ̯?pI<2 6B;ɇT(Bޛ(yo_?yj~ٮ˜3=1ݘ9s? 9=맕S)ZG olӫf{v(ޠ_p G2g<&41!hAU^ʛ` lwG-tQYJO$ [[1A2 !r=b)sc5),aWgwioGhzN+{=~g<YE)w-шmfB;(kS~19sxjf)1dmZS*w։{}r=%Y[d-bދ4rmSCS", ׾h?e )+fͪ0B+[caRg͔|}ZF^S%wL#"⬮7}vtrk|%Q,طm;g|#w}!ߟbٳ4|;M3P_ ݌BS-k#kM蛟䲃(Ú/P0<aV}7l⨟;//l}˖ C% /D(1jT⽲%>ÜnZ/7( g"0nVɏ*|GǶ^jRZ(saNo:R31ΆS*r5M`/#`";:V%eU0L6F=jFqmbڊm#n.lf:3 gŵ2(;IԨT7f G)nz^Λ|ɷhA)XƕMzgS9ՠDRx;ZRIRl-_L5߱Y VWhA;8"%c>G`۴֯$4D72ɑtkRk ?ɘru:凉Yj0x̢,HDyQvf޳rN; wX JSVtդ0`ސLx2u2q δV_~h']KG_A]Uh|m~wqnXdnߊE_oy`[ٛ*Yqx]Јn O?)[FT JvL9C% ֮iW0"Y5Vm6vn\vf{~d>*SyR*u;G`y.&Opl=vΗIpxxK/c;:4klz3Y-胘(vKVAO:0̾;'h: Wp (i6,fΑesfG_cqӣCT;Nֲf!<5,$tfYd:N44Pp͖H-%+PҡLQ@km,,мG=.( +hΞ'F7l1[DǃV|p>E)'a2AG;U*޽^qs\n$Q~xWͤ*zPB}}UYN7EאCtGЀ /;DMA}to$QD3Nvh=ee~X(Ecd?ը[zDy_d:R;Fm)[qݴ̳`a~/)rU."^zmQ嵊ؓҌ@EFZΟ^`%Pr$a6 G iӷ5/1e'YK\ӗ@_uL4`^AN>6%Dα=+ [ǖʀf~3A6Y󝐓Lyay\}~ѮJw`GSt4Q H˶PO >PNL֊A4׏H<@pX׆ݢGRLfM%StBBlLjf ",\k\M߅E7Yn(#֡ W (Aן%/O*z\`Kzc$  `G{UgX&P䍌 X^tE/y8BcJպIGN7UݺQ%jj}< gɏ}\G|R70iCY԰8?mzw [fe%VU|n7fݡy"! PDFvo$ /%Xp="Q{"K00nN%!d?'2mn/ xF ߡ9{jT44?DU@u1woUx0ž$tH.4K taڶ۳&D~1u1ȭə fn%!@2\nm+Β Oʰʣۑx%z2U4INC3lxu;Ԣ/Oufo:ڋ܇'U# L(owԗEיqk> duIQ8Q` 7¾ ,} ;iK aHj(n-&${K$yޭpC" H:%ElyjySHKxWfC*:fz!z%`_m<_T{V?q anB6yVע/0k>O ρ!sGʒ #YYEws-:B*ia.uǵ=' P ̆,j7'-UTrhdMCΤLOf6bP&D0ԇ CJ5-x[biu6oCC<ߠd DH.&㸟ni uWj4_ R |OD1u!|[ {㝬jSF:f,s0cbv& +^<_ *m"uY.zWw )$1jư ΅=.3-C_-*R"iD˗ e<+ެRFF}| m(NsٺAl ^di)FEA \,WJ2@BZXL%F;Ļ< :R+T\0=vw17?W'+ԏ׭~לWGͭۺiߢ |ikԩ| yM9AteZnG^Xic8GLmW-kUb&N_`UxHi `([,O ny:l{}IDV-[4X7MFH$/b2 rߖ5$r{2\GC7]}x*!&k&ԇc+>UBfhX{wzfg/ y.MP\"QjFo}n%#:~Uq%RW!yL-&| z].-) O}X9-z6 el0DR$9݆|xҵϽCf> Q͖-E2;s| b 4N:?$^"'UZ; kd\צ-6R]$u-ocK'Ugs-ĩݾ4I<k}el<-yλ;fS׳ S/Y xQ.D \ƒ`O5㾆B-8i~@g)Zw)%e`mE#جw]*u[Ŗ ˣFc_ͫC;9l(r'Wm7\tH3#jCURa;d)J!\<{cMG>EKZe.؀;!#F+1󃆪 rmJ*y m'&I ̊~+oeIyE1RcؖU_߲x.60SRL$A8B 3j޹T%^MA8pՈ2croxV)Ex41 |4ƽ&&.l2_?8Kl_a!*HW TBєHI{J͉y-F=8R麙A9{/4$w3ϐVkkn5` Y254N U.o'̒a~Metd),_&*ح".<.5E{}(IAF Ve ߣ,I–Aڑ:B#Wp0mDg], 0|:?B/Ӳ[Y&yP1)MxR8FMl׊.4z4^r@eeަю?h$zLfU&?]{jc M U0-T׈FNo~:ΏAE솧4Bu|pѦ[ 4*YŒײ8H5BpFCu?w39GGQFxcVy4 ܩs4y AIy[,H:ϓlBe7&KуsF$UFԤ5& дT}h}ϲn CLg^oKfy;^!MOTM*c#Iasܨf7hFQN^ybL?){XxE-aH0#ؾUYJE2miÕhWO2UWܵ[(p^>涭pǸ#>܏pV~3lh"^yy$Wh-X |\l a暆rHp+u8L9&ܴ}t`Z$6bVj]s-#%< O7$E!o#)7|Y$ޤ/X ޠ3gzA)H&-͗BcR7 6r7t}tÁ#HѡCcf/8q^*-mZܵȑԬUh"46&eEH*BJtf]8sh$,`?Y8U%5$+}W6d¦5&~0wNmo(b^,m;h"fHDBc=';)dLgB?0%PHI2<ԔA>T^D/j'y6w3{g;܍fW|2_^E  A ([ GyN\&Z.8zj CThGgM龜v)Z? 2#=4H4 t6YlaS$rO ch.\4)=A-CS~Άa|8?yqh;,/h&g_`'Q70*^x5 3 D$^y,H6soj91|MlۓIFv˓Nw!g^6)?.]GPW)D}%Z%c1WX!L,lN= 7-ZJGT <Ϥq͘EdoLTqLiah&U1 "[@T:udҺ}ux^W7Q1.@$~/ ۢtT=:KCOl(l`ԍ~%ȭԢ+3v0Y;#bt^E0H!EXo}!TԕdrqnI/" }zszEb*0k,E0H?!#h~19&9&FhHE//?TӀh=[&#oHKr,;]niw4ST CX5:.KY3|r]j^twsɶd)XSpj9ζq A4;6hbt]$QMdXbT>3YjjF߳/vQEB`oЭA zaMJ F abE!֥~tL=n`3"fA,\ 7.yw&4Jc~ɕ<=96/nH.j~zo"M5{5;7\)p$#]nIE$C+=+o%iQP-#=JS| 8n0Ҕ8]YS|[O cCl5Lwkv5%|L0cYTsD.HA~_XViˤfER<ۘ aΏv|գ=jK7pwlpNv!e+ݬ\y8;,&+t}EXYbehS}q`+ܭV/Ս}_tsӷ6< ݑfX቉d,Ov&͹dM=6&w{y2dMg3r6#DR~1P?8Z^JVhS-:|%"v~PKn~e)~$p>vybvK11bmFT6»,C^E;fgੳ).q1fL!(Ԡ `'yQ>!(18ґTKN[O?nXC^,g.'+ԛ~LF".:뤈|/^Um:@K憨]L_9lids$0VۼFjkbY]שsc\v\<)6t>:[kֽRKOi= t>MNFŐ'<޻W2ۡVjfrֻٙNY{ˆ[#ZiLRqL7y3f`洲`C(oh9i ^FI |zxeڌK :+2<2aZ/[-`.ZV~Z"{7F*W2,@!e-s~*fB6Cr)=/QI:(kK'٫A,U=/H/ʍ@9R< }_*]L/S 2|4No1Zv &ߔR]P 8TN$Ū0;z LcLL_]{0 |'݊e_fva漣L1UTj#LUS8dhRz8.T'2wv V<~ijo$qRYBP jNCΦ>fTܗv1..0GҠAcVVI@|zҳi#,Iimz(Xtk嶷)\e#|n3ͭv&ugL/K/&{Uz0I46+goBpp#n`\DO=ؐlnk|pDkv",2e ^L6GB~)%ɣ7Ѓl +P%ӎ<ǴkzS8g;ٰ)?{M)(@Z{Ϗp^4o*㮔t^PFD",&b%יe |S|){\vy;zzB(4Pb^tV=D;Y2; _=v$c\20 Q@;7krGIZ`6hB^`A։Mi fmhw+)RQb:en,[ADƹE-4M$Oe%2ZH//fCI=@:``omWn6ݳ,-Md<,:Æ!o-J|lj$Lj?ʾv+EOnj 뫴`]c|QYJ{}.EI-{`>$oyxfzϙ־!;1V;g+k5H7dAOf)wT}0EfNE\T!`+iBQBќWͩO$z{2Aڠ͕3"OÙ|ȖigxMHd5Tj֧~*ɽESeTyIW G k<`5 Ia CCXc[*5fh=UmluIrɵKҮEUjVm=\Dr!yPumHo:s06JxzunY)rvZws5^P =^-Ȱ+jl}zΊZ/=* 2E/=,S7zAfwM+yи2}2IStCGX jzgEuqHLa5.(;N/m%8?J^3ޟa 3>-ֽ,g,D4wHشi/Hˀ{Fl i{iGYo+$*teH'fyK2Z(C 68Ue5ݯ* QÆHJnT=ÁN+8=9'^jj>Ϫh1X!_e.pNkj)>-]}UQS#r̨)$p哂yey,9&vFTNb`2jdnj P@W^v~\\dyDr9n,O_C`M,\]|fw_WlЮ*;* XKD(h$; y3 W3 f;[ 61ALpf<8BDܒLbǷtF Cm:gRM2"0 ]ة1ED%oCުӐvRL1FOֳr$&sKQzA,3moob-2B{dZw!"E]%z3Q'f6E) -e=~S]"2t:ɦ0O0dOd-ǹʜRElOػI]hEiϴp M緅RřhSX --tFoWx]6vwХDyr՚v3r^7=D:vxK\Kfu "GYfX(Mˣj-* f(#I~ahZNe%>ݞQSFCT҇g3/c<Զ5*gyt!mRMc8ˡ).ox i:T#T,*Mg~C؛BADTl3@yIaS+g5ܑ'wl&Fy;PHʿJ :ivt<{x;yo |hhQut Br$ЛS!E-lˎ't3?2]WO<2wهe:$>{lK^ J/YuN)I.%{E'٬ת7s6Y;~zuKcfLdO4Pj݋1)Gr"|e3$G"]$,;5EPsbf`~OQ/=Te o%_2 ^͇kƞ|1S;{>\Dr_W 1u#*xrrֿf/ L}@"a[Ne_m%M l׏n!L]-"X9oG)Zr|0nۑEC^~k|C(j~vJY]>l ^^2R^4"taZN@s H*wyyQew@8grj-b̬sm~z+ʓjkfhzV: S#sL,:V^X+dRH\heˊs١U<81@&@ÒaÑZ9 To_DES<YCloyNeB)ڿG=}RQDTI2&P): Nu q79B3?Ӄi{CDݱ",ހ+k,Ykbw?딙Azҷo|7Gt )6(6l7Bjvu<&NѶlK~PRԹ-O{걝l ^1PAK/;W(šm xw&z6$WA  ^O)Db`ȵ̐r=%Όh7l̽/i3(?9أҠ) *5٣k 8"Dˮ 3D雩 n 7ak=%.T>\eG[:r&hk9YʠnD_M9j?&lf;,B w*)pYwƵ2bX/4~Bl*QBJKv+z佸/*OytԿCfDz^ь"R}W3_g3K]M*ou;9;d xܴ.B&ՐB}h ~_|z~%ĝ[+ꉎIYHzir)g[3FjE(6UITdX\f ge}7/:]<8DVaz<9̮3iٶ3:AڨQG]Vw-T9r6 T~;~Z9S,`8/R\ і;@ *#;Qc4MҖj#Y^:/r";l/Ei~GXiPAdHYѷZh7^3'hjd [i_tBQ%݈X>MnW>v ![pܣd&*0Lsph#]MnPy7pitSްi8IAtLGD2u>^CG2t*X2AtPhRf2SCNg"/0W"5Tv{C( y ]:cLWSCj2]W/sfO\Ag؈MQ_tAʾ6gv<=U nr5K$Z$?J/u`h@~' wV(絝*b>f-eQA<)rL,Z;MQ֖)M )o:tNH%kC2 <."+uM9}êd)&TAк~:E 77- \OJKY^ ˖x65MfZpOjBj-PԩR$s0{ËyB ֦j;L#ݪ)& f׶hKܔ>to{~C95yO#xhRs2N# cbіZZ=+JUu7CѕV>ow)JǼ*lR"vZt7vh֝8:|۩Bk׻@z0U 7?v@PLuj[Vh8^uE ě2~uyZ1(b` ?vˉq5 qT:lP2u-̻KL>X~ZBD)Z@!8*$H }7J~#gl1uE1GcF|mS)MW6%N+9=҄#(2XUN_9)mi7z>cdR0<|%^ĈtbK-mN _Â{:I5SɹO$#ZpXB L+ަ7#jdSAT:=-e:Ul~K\ suSuuu* 4tmziC:Wh/-jbht/KE]R>e/w$BÍՖm$W<>Di`=>γDjk!Ǩ@%G#iH=o:۩G}=UIjA",#SŖ7O q Fm};VG6΃@$ߔy+Ȁ v΃lsigyJPo縬6{D#Gwc0Db$G0 9Y*V;9k:?G ;6fND8"X6-8+/SQAD,W7o(Z5Tm?X;bqSA){vrn>B}@o,8{[VYXQg|t_IBcnkC ncI . Ou_=IC;ʤ8pH ag!α^&&_hAs-,wmih Xkm-cnbUl_ϝX#L$G<FEه=κIЪo>U^;TY6ixqzSz/V[RqlÆ.] yaLBs:0)b\Tim#ö`O(fsyO>91aF?Ź"*0[^e^Nt7ݟR?8ڌ>-K Stq&{}'1%E[㦢c}7pYoIUŸ_u'crY峄LdֶPD4(87 $/ %%k|AizM>UznuYgI Ǩ ֎".QWPG}HXoJ/]}\[ָYv$0ph( ?k(dH<q<,13"珞6OOCI]7a?[YPJ<2YM7Qh= pn&שnJxkRQZb.MV1WbisHE Mܢ,;1[[RדCy]>"]EIxd/Q\3GQ;~#ͯ?/oܨipnepޕJϖξ{v}˿2Da(%GfzB$]) =S / 17=+kv%ҌCO`_%;HQZf=)>jkzRiy59!IL$"'rb 2x -f1/zJVm^#s撔VN.3iuMe?8i<+&„'Ȋ}#h|AC[Hrʤ?7N|bdTc.iM?wY'/ tKYR!a*^HW:'(h*S|~<JJyQz+s]T8VNYޟ+ T&2h%bAY/<W tum9X¨5Zm`s7ڌ(/ߦCmt<-Xi%M(5Ӛ~w*JA£[Jb*҈r:@ɭwX[_RGOT_cX6ˬ^%dB^R8nUV& Q' )#s:Onω[ԡ ^o%\ VetIøȲz?zDxfrwgEW?g/Ĭi[Ꮭ_$ȯ1q!fryFL?6GC!RnixsM2zM j-Ҩ})^5Vmx dx}2s9͜7QKׇ@vH (o4 "+TN[.+stLdx}Pp%9@e ˤ Lxʏ!–҄J7p:Vh*P8,~!gnS0% (;%P< ~1h=oJ\qUsx-ziF )ʨ #yeS監3#)+s/\,ō'_d8  >0Vߠ\y*ܴ#;'jm?eJQ hP5ws8b% B "U%2l$mRq|x 9Vb֦:!M:y(uܗ7_9Wm@|cg|$C^3[7b3U*bƅ$տL7r&ɤ x^RU^^9kb2bΦ ФXUqC9-^- IgGfNYh"$SL(& Dn!-Vd(94/+]%pgDsˈYy9;]D;j\Ed?-:qGn!psDŬ6"5Tc 0z)yl@Y?^׶58Xf(SZbuoLǦo>6<=^^B`1ݳZ M./L3N )8e>䩾h4E: ϸt>t>,,i07r_o}|Y.ꆕ?%/@ݰ闉LerVɝ*(hH1EQ|sBY&`{sV&wf4-LL$^'R 8اUV&i=/ bװ&] 3lxXM}iiV*4¬.>E|29Uӡۋ wӀb/5c9 ΐnMiDGk6P(-X!J8C`-GpϬ+ - EDLx?p”͊j|i`kB:T䬥#Qxu2VMDpbJ=vcBҫp`'XM.>أ <ܴ"Tb9C рIV(Y4-4pdl"8;$j&LjVWwi֨9C·Xa|H rdt9ӢB܌D}m: wJ 2zy# nZǒM[cVOlVM5s0upv w!/`c>2#e\S>᩼!r>Bc^#@?v ȝ5I<1MMuVr<|axͥHӆ!$yeo_uZ9Q":zj$J0_5wI ' ":ԓ2 x'$.Yxz,b׏@L2]]YyUUj>:&;_0OxYv+J,^o~qӲS52#ůi/~qF2+g>@o8rSsm8#bI?gzmQa e.pN5#l+$ l٦ 2Ǽ7[ci-]&0|a%7wnP6sHh;t#9-3Xo$|@LHGƙ^L N><5 A9w xCcE{I HrG<`>Kd.iqVJ*8/金%q1pf'yI.g6t_A\b*AyZ@L]m)9櫲]j'=9E):5 񝬝wN~ܢH?7&8k_}G}2liD07+D2SOXpdv&(Ѿ2(^fys7_qq".ѐH jaQ>Ґ9>w5l)=c ^C^Y}%}+#L"J,D|{n@ʬTlNf-;I0_g M"G_Xn_]6CԸ LoIʖl I.⼟㐃ulX*n^➢UP3Y՗_[{$ϥ|S-na!X, +FW dZ&0icDl{,[e9Kpcֻ31'|!"Cy3NUŁ?} vئx3Ʉ _?+2VU~P |:8y,ۇi}v]: jDxwHA#͚M* BR#sd׻@؞U &<7I:ґw{.:mk#4Je3.|mM7~4ݙ}K+9 OJHlɻ(&Ԝ'3d G2ҋHwǓ8qpNenC?Me%U|2݁e|[p4N|XuI] =Apr,w7z` 1ly*ݡgsjqʂ/ܲNjL۞4foс*OYՀϏ'ھ@}y1`8CQC)A7ơKpY-(nD [t8f~\ ڃa2EqRO&e3PZ# 4бb.lq:}XuGf+ڣ;"˖lμ^Cկ(< I{!z!=J׬nyCHQ3WT}X(F5n}\~pѶo-r9O %>46B%K!%x9wQ>_h/Κ(⫫Zm[uA+2`9d z*T-a~eO>$(~ʡ%3:-% kw'o*DJ'R!3XEOqN^p_ªڈ"SCưdmlI|[y4裯uo JB9r5.!5uH2;rJ7\+j`+y lxtDj["Z;Gֲ|`zI޹y_8s'CI4Fccss7l9";ױ |YtܬIn[3߉@F.Af=!jbKqc$on:?$%2Qo F۳jLl:B)VG'j@Sp-jIJNr!kS[RìoyY^/>}Z/%+Plv_' T{+) $ioy[|HcoiP{j2abۍ `oC5_ײT.3J`2],34D-b|k+9o}ִ$XP>h8FF/*0EׁXzTTޤ'9[ +5?qTRZZ9cwN >[ BNָ%U;ou]t,P&6rkv#Z<΂8>֑ufUvk_nLk37UocFKĺI(x6t&^<3?憨=ẋc],]hW qbžH؍ (f-Մ?#xo f]\wjVu٦73gFUtloYJX bm MN78e:?GNSAڗRId:[t/}Xԛf] j!+2V4PS6iY4֏uZzl!(c`P Z{"3M!(V9_id#D~1%bCrLG~leuCt/q*Z+ywظsaGj19w0XՁv{ue5W% 1/,ɠ}]B%(~HёC,bPe+YwXX!\ ` Aj>-ptXEf3b@hST,$â9o=a鬨yp*Iy&vTw$Eznvԧ-aYtXgۆw '/i%0Y/0hKs%ĊTY~3,.$w =[J[qb/`l9e3d$n62|ܜJYxA'P?K:GmȕCڍa/th7\`ߖ=)իʴi/,z6H1Hd7k, )\jqC oKe"&lZ"mjuW=Շ %,X;NGLhV&@D7™wMֶ+Λz2fӯԓxO'$}l3j@iGoԿ }c\W_;ԗ7 #p[BDO &~MYD+$!NY ֘,*vޖms~/O$Zf K\ +W|b,0BēMUa^,6bA) [=ݐr~i!yFO2}Q~*-}ԑ}`و!#pd7@SxKYzXn;2A$`#~0̡b}­I6U2iEpA}Ǎ@J)ZO։TIb1b(wmgLcslZ+A :oOK$*Gx}|m%byW?RT iUزz}6ջ}t$5SHh=Imѳ #TF(rTNMt<>oH,i`VSrNXgy=?aZ£~Xb8=9{Tl aތ; > I #c%Z\g+3E:1T~rH$a^)n~qyJ }3=$2yg-*γXUjp)R\3띏ǜ &xcA8ɭ+ TnGX9tqnFw~[}ܺHX)@X4COMVGUj0 ˷_ +[X14 \f6IB;?ʏ{H#Q<Ԅ}^@dƆzF`Z]Uq܆cz]HJwۣ'bf%,?hWy7ύ1(w0}ly?eRXԛpau7 x0VV-?-del>֟1qsnED2+u@@e T8J!giɕ1)h#.xXO } ?e^dr/-#vқ\œLbs5$QD1TaY$yfkĦ^gX5EV>z%ʄk؅'y~ ĵx7|X gl-O5124g;bgMuUW֤ !Uɽh_91kR.XXMpj6k YN[N>Mc?]WBjg;Huk?n#.̮t8^oNO!2|:b6%+ jY>㡇3 Yuz~?x r tlԕ[NYdDsQu`49oا9'y;+ΚObp;/)$䀩? pi b}0tKD.7.|pTz=*E8ӘAPN%Jt֏Γ_է$ru\]J7܋:#NybuM}@yeM|L ]D!CqtFŊ%:6%bRZ|d8d_Ў#kA (Nxɇe++Y^no$$ϯ*C]HBl6,Y_'t¸R f͑57j9*Qj6$5#hFXn9"Y<$|V&T:,kê uF ˷Y~74lWA8p!سHrOc@/`KdWPTC⼌'\(g6NJ09OoYrhs5}Wڍ#T\'M0kSGjf7l'Ǫx]:s4j桂YaBOBp~9,ul;K)?_o6)@?mӴgY4[T1I=Fb Ըl1/-q#UkGX;FUxJc9B/यBE^ ? V_dXT;>`;gK4K>kA5[zR]zoD3<ՆL0]=U$G?xÌwIPSK#AQfino~? fCdk[U䍟x[1ˎ|ZNhqG|UFs3pΜI 0wSQ6zɦޗy$!E:yiHD#l|Gv=@G#ۜQM:<.7pO3N0: Ш*ci[}nfF XCZ?\7,TϜp~>*buUW>{h^a _l֐BJrgу6u*rlS!95yHVG@PULPaRa[Aj3XSܚYZ{]q1z  IZY1BQ@.O4m͙Ө7FX w_r䱡5}f4չ'#0IW"*L٘P7XJnϏ!Sj>Ƣ극ܺڞeQC[l(:21̗Pu^{3,>*b+GmPX1kYG$~pw^C8]G9E%Gy#Ӳ>U>؁?M~xQ+WO0[(TMQ?FY- ~9;_51= :`cAyd}pw2{Vw <ⷧM̵Frtui6r玃 .u׬sT'"|5nz6teDw3`B~`%5+E:!V掲fYf9OV_+\Ą4UAٽ4s%Q0㚼`%P;<(\M)2p?3c<>=Hޯ)Zn8VˌcʫoƔ!x>9 arnxnֵ"<$=j^ YWiʯ3|bKm3@4P^4kHYuZN Xa{&B<?|7Z5JVV8w5/CG@})wmH~vK\VY{E:݂97ksSul^0cq؍$; f _y{UP{ 7n$op :2e1<Ԙ ` L`FF%7/uϮ9G'LE7:)y)e?'Z_lֻ]yK2aGM{1ނ8(T-.< m5AJFMj)0NUx=d[-';4 حNfE PaKDYE&^ZG=Ӕ^?:*BN)`zL,gDǾa+ Eax :ri?T!*ߡPmXai&fX%q[39w3~k[,!o`_(\T'bmvpN, pF9_]qDT4~yJdt^YK>375Kzzč"SdWqOwCzExmqrM%Ƽ2*;28? zn񌓐¾*cX0@ܤT^^uW9N4k\ӘЖpJRSfD} }`8oW.ߣ ux[uDt^1LgHB?Ȑ~b z , {:Yj1M5Z|JD3Rz_;/TOF|^hf_#:.29I0y2`3YAX]}> ci釈.p0\eX']:?dťc{K۾'[Wv*̶#‡-eU^DۯZm2tR 2 _TC 2ഔV"d|g$ް05׺0;O$-X)+Jٚp`h玻¬hz7,N}k,:wVخ9MM*jd gkЊ'腠p o)qY@8 ,ֳcCFbYk7fotU=h$Ǖ.QS\_+9z䲄7T]ƧG)|кϦ&k.oF l5EaBy3<3MfFNkG6eo ֢xCcDk7fg+@/ϙeK8aggH7&E\ i?.K V MnJ O `]#_ }.Z`[Ћ>pL 6ЅP5RCx.馲:;R~)ڗZ<,ތwBL-i171 v7&9.CE؁u?Գ a9+ rPf췤jV;szb:v>82tबY* ~v[Yԉ0jWB5V5>rKsD,nU=opS֝Uf8->5Knuԏ&$v T>rXE9%fM3ʂUódr>myZΡ#xjuz&˔X7TnX]]09^6,9WyՁ)G mokBCeBb|}o-*%/6V'`sS9Dt!>Gtb 9S%<ϝ%c㨆b- }k,0ZK6]dUGv!{ dq_8M+@ET5lMb>~:\c X>@\^<!z +۝$0&rCґGRZgb_BgV w`Rf !;L4!l {ѸJ  ДYU.;q[][ZM;tʰ&V\Dt ]gXUI\?}*lۂ2!SV:` P<Ӏ|"/(o /S8BenMr(" 6K9FM0Vp  װxX"3kA.SML2 ]9kVI~%zwA^"o /lR0۟3Κ3VH^PPz}Ϲiă$um-ʚ;PmF?E* ƻY+VCρd*}-foy(q.3$XW%۳"8tZz̗`;l% {~;9zm>jMXܚcg"B(uf]+!&V{?6a} }|]ڮo,$8 pMvi %?͆.ُ[H6I#Cuݗ[y׵Օ\4f"XÓ[bvPւWfPd+~WCN-GUP88]޼fwcN lՊCIG( OGJ.bZIJ;"se"$r㽈hfuGpNVh!.Ju*H=:ɖߘĤ)MW8sǞ;{{ED:Y :aIpBlj4/ Hш56l'!-ϭ̦u2w EU&$:)KEii Y)TcD[ȕF]H9] .Dx(iVg߼5h8$2+ ӭLvOPL҅YiRug"c {1?!1i] (ǸCDأbLt4s$4_?|:Q _K{ɘx۵ح CFnܰzieU0Vkz*- |P־9(;ʒf}E;0Хz o7~}*YUa֊XkF鬻)c$͖?+=X u~ֆ I[׉"&\YdV/Ӂj?LY!?MQϘ~"dUx<껉k:6S$M}emI{<.쀖h> d^%Zm?o䄯bb 2_ꁅ%Է%n4uU|Px#s(4佫5Q^ž܋ ڶYV~2S+;dʼnLƉ) ^]5m/~ܑ`&?S"姞Y$ROg#KLA9;X*lD/Ԉ 㡇|fwuՉ-QtѴ0+fpF;9ssWt㇆g~d.Ě-! Rݢ}Y4!6  _ r8?+)j `&x8M@Tr$|Bs,*h*nDzxGɅ-_lixM H *~Aj(';ҔTI EwU9luQ{fu?hm#VMaG˄@B$z`7_k7y0dQe_4.x7Xj1Gd?oM Gyï6,&pdʥzhtNj8kxc O${o_rn'/12ټ @p/Qs'w][7>βؼ8EmXRX51ɚg0ۼLDrL,ᬜ-@'3NY_;`Iȥ}'ȷixRT"epb8؁A2*OnϨʷ<4]s q ri?x>E 1,6Ƒ]Ė4HSz]n jd:œ v gwL|=9\iFH>Ouw+8AܲVMۆI @)yhMS@ :~^%@b l-X9K!JSL[h:?M4IFƩDnRX52UJo6?۴&(6aִXk6n.N\¡KO:B_,hcX~ gibf {ՠOύTlXt4- zh?] _fMpqrCWJ^0WtFptTU/ys1[BkgH ȖG¬vǥȼLt.W3O |r:&wb .̲[$Vkls96ξol{/$={؎rVZFD c=MBZM#CL}c7l(_]g=CqslZ?6 t2}塖]̢~;L+7K:vwىTkhfKu'!9}}dVEw%d>59W&TfY-l\G 7,}2cEl୸/Mxs\],ȬuFK—#ag~ g961 QRD9;>^KBGZz_wIS"aqUKOOg[:)3/dIFIeL3nƼ6Ȫҩ_ev}}YQ~HN X9 ύJs0u0=Bkh `Y~Gl,3#ɳ>*.Fj k_ً %f*ZSY2֮=}YHu~]6C5tA0+ $VYS01Ey詛UW]K F;*NfK&t@=zpӳ_Yǰ] {.'HjLs)U͑tufsPb,] ,9G"au3s~RWv􎫼/@屼dGq? Fm6\(5<5JeEz6( dP" b2krS@@ m^bX_ ~\]xc![c]Ȍ[s>? j턡g!,"kMG{#[xls^S>J]edŤIIr4;٨#S E~9/l…%Y쵅a: NAt~R\a ˼pPR:;꣮ &Hr,zIF\L ygĪhS%"s'(Ju|VgqlT95] #<9D#"89J%7\o+V֗V\HXsfΧ/AYӡt]=7^z/ E2$YC|Gm&*h8x`]:{-eu,<.JSdMeLݡ.L'|Aoұêq"N]8I}&q"s"ICyU丂$e]RZxRi؜aVh*\{T>KP0B7r'gVy@ug07Ŷ t-WdN&q3T$+&')%tXway|Wu|= Y^n#c?[BSH?A9L;{w&wǐHоR^ _wѸ֤ϸIlAV=jpy-q4va=8Yn`E u6ֿ0|N|7#Z4Paf&r'gVR5;*A1`DI8/26'PQO0l!VE %1Q_=NCEKR;'z/ŒXut3B2s/ܨӛY.HyO-7 "!A _UU\)QҔk+2)*4KrCЄ5]J9'f ܟG`:)1yCO|N0e󈎲/ Hϰ "IOAQ^ ~+fu_1k*I~I ꎻ~u]r6SGjr]گ5+Y gO&u蝋hʳ[""w n3Әֹ& $qVub=`iJy ~-r_xYdwg9xO!Z گ:^O! LsH1^J ,Lwy7jw-3=^ -ug"gYؿ\ap\k7nZ8y5:g5I_ UN=6K؂hJr2q.4u'ĥF'>ID/n6%el<b]!gh; 4ߧܻp`nfi Y9m5+C9C/1mkاr#Z[ AHI5w$r^o ,OB9{4K3PcQie!*ZǂIEڋ"Vϡ/4/!ə,C'T#(x%,]0_. ɀs%ӳ:z`MV%x/u/VDkYיigt{)iJǶHјv2c{PVp3 Sz=!ElwSr,G,Fן}VPןhPEr6g2'` >07"Wy&R"֔agAҜz;RgUhc& /=KܟĜQ0'䫟W/Or _0HB⬏WScqd?a__yx5O|?MG#sIҮS꿢0C! .@_>,77Qp\כp:%\t,w}䋲wQ>ZM>J5ה1x8pl}X|!F/qWdQ {gL,<(wƍT1{Ɯ廄&MU^Yy~? ;;ʯ_%< \g+90|15gGAi?wU07+-(fvЗ +tDWj*BR¹ӡͩ"VIfȗz>P}um9S#Kz_Z7{CT?U1܀f}=Čy.I9ͳ{9<t 9?ykdV|r]){RGǃU+ ءefUr$ 2U%aRf8BN4䛡+Y@SL먞 ZZj =dl{ 6puH(ͫ=,CW$Ul;p>odueO='^-k6ƮPUKꝘ1ukMc =P>[=6fw~r9+-M`5 9Qi5J.sN-OW#Yqwv)? HGPD'Te|ռb>4 ݣ()e@:}׺_Q\gTpnh\mnUR8/X!{~$-:\I83>x@7r=0ЉŜޠ߅u1ۊEqʸfW7vYLB 9#f9Q9X!0')zsΡtdM Yo\#lN_' Y*ǯ3MsǥZ.>{P6M|yNA<6Ğuj~um-'nD ]\ D+dIEArc+ Y~^s#xߍAZ}WqHlbo3I|P#Eټ[ǒ#COk7g@E>gd*L=#G#Z1S- 6VJhdF.~\=QV:1 ۅ$l"5Bz=/u[uЫ3oOVEJRBp,R<*-3X 'V}ƚis^oEX!- VC;Zqjr,)iɛ(rNwTA;\7gid@4)ۥQp*_fClVtJ : ի "VU^ iȁO@2*/<Ԝeðhǿ19<ܥ.t@x})fEE,D,pVE34}lOm y/`(?!m[5)g$!PӖ>.r7n(֝ eڄ(#ބk8}n>Y;@܈4?@:edd\ 7lM9>F~Znf@D ׍SBoi cUY4Q_Nj$O6qBs!%j ypqdlVOs@=(~d4b(Gd`5WGCG^9'M$e]%'jbOR 窋}J4?U Ւ%!A'Y¼CjIxf$Xj^m: xYX2zF̬7XaĪHk4IZϥY Vl#?ƶ7vH,Rیsnt:uE/r-0l~D40γf 2n]fGiĆ6GN'_k~::KXQBPVץ鷄 5;0V#GdtG[G.牏o=wu!9ONNPxvA !,[ _Z#渂x&r'鸥5G*?]hML0@MΔEI;Y~d vЉ@JY)OC9gbl|H z?rnzաe3R{$tf^k3Pbؕ᧡h@~p~vPk%2Sz-8P^:X o t_(>$ScJ0؉BJߋ@ $xȗs9-==-C&e-iwaIYT>G~^Rot$"mt 1e0](qt`+lN)!R:kUzK*rP(kXxKhyme 7SWx1>4^#uC,{OLC_R09xͮ~`@Rؗi1I^N뷇=0 U#'gQ93Gmyw < ,6EsΪ=5}sy1aF"1Jpܡ4|$(Zi<<@ypb.Pbk|1mwD`HiS3͚zsuz3)]"ߧ4}Gn[Qx!y^56apH MegŮ|jK,lӱթ6 004Y .:H!BFJckeT2[) <@5}vvZmmnNu(U׫nTxzW1Xjg}˶-d:ɭƿK:^<׼Ĭ'+z74sz0臣!^#F9d G^E:g~ғ:4dʹ>mK j{ D~ <lks)B_Q|88y2U/HבPGsɶ\/f|6~Vל=!%"/ĺKR"vaǡn7BD\1e,%S_Lf02~kTI&;L$a%7IϞni͘ѩ-X<+5U7 >E֯Ve'ݒ9uitեǫTISF % XS [RviőY%Ŋ3L_s'#}0k*DUFf( ~KS%ǿ@oăzq%JcwO>[h:jlJ>!zȿɟMJshR44VSCVJ}?0} M_hkabN#3>p`šVf%׎%z| pX* TFI uAjՄtIAyy~83rԔ*y~ЏC.M_V4# R?6f ѲP.zxCeVb#m"`Rx^,,O}p[yz/8Z^إL+R0^0^Z^J~hCQ d"O18=ZaJX?}X Ȥ)tRHhzړ=Qʳe F_涙0q3cϫ.Xϛx7KN7`O{(@r a%-S#I// \Yecn&F[*RPLUAqas< lv:%t;l`Y-vq`jh7#&ٮt:4ߛZ\O[;8?Cú0KE; Z(%IjF[{[7:ln1^D>[ﺊ~Q{!|u䆗O& m^˩L9jĄ^{dIdF]td3;:L~إI!k[v|t=Y3E(XNw4bY|b h4יm €P>1١Q'CyTp{\G0PqCM璋z AW~2eҨ ف7%8Z"tj/,g*nTqְQP_v[2#.vyF1/Z7S 9ҳD+ϟ2PksS8ϑSʔR,+ecp@RtC)F7h45Q9) Yw3]B_7Ī2)T :7Ĭ V,L mVᥩx:PO}#D_>쁾J~pu,*乆u\|u7uP:7U/fb<;y]iP)4m <:2lL7q6(XsF(BE[] pe8*Yƶyg*>?ʃ͆h95 ('qW$V0I˥z%q6㚖='dX|i'+n>F;A/x8NYd 7i6GBQ(7 %),op!Nbv=A͞r=aρ8};d]HW:I͕R;)Uˢ.H㉋UX*e#t)e=d84^vօԻCd:ڻҰZHtS5 _. au\՗ve?< غ~uO(_EgܽD9MNޥdcS0+!~z$]hYua\㎗])~.4Š3zUv>H6<)c2M~_.`-s1ϓ{r!$K4.tR:uodb~[){{?WEEr5CwאfL; #R׹hm, ,C_˥Ћ>f=Ic'!AB PSk& fh7e*i'B+SAMAH]gu:e 7R05s'H=eV3X4%ak)3D>LI'>֨hV8Qf0}N$'ޛ3XH;8w{煤Sj  ;TQYO.{fhYCEӛ)^p5] ۍ yk],7F= V֨ [*a}"yXޡ༚bCv!$ [iAqя́5Gex=7:1^Pm˯lLsp NȻZFG:pGa<ѮF_h~w{CI#r42T0h =/6U“_rA=ZE Y}iҥA\L˟LOXN#$W=>|],nq-;R*O9)3CƓ*@>}XiV8®>PY lp+r Ae9OM-y=/Rʲv'wr$eP|sd-˼=8Oz.&59OOGM9)k }%L 3ƆfO_#}HPGW$4x yG^zt\ d ֣R ןK2+%+'뚼[G^ Gn1_Ih`dĬor .<. 3ig$ϻ >%\z Kk,sTh|30GvRy} g ٭K^ 9&Ý'VOLz?WIƿ54.=HvXb;:1Uj5wF삩sG\zZ!O g2z/T2{JQfe%^{9hqJyO%c|z+Uد*ĝHv#j*>:8wrIwT>ˏ3>vyN."YTDt?߅ >b}6|Vxr>pO!qg6`%oY;xI[O8X: z6?dϻ1JT$|9$> dO#[pOa}Ś\ Pۑ  (<.Gsx"/̗13" bPLh{k 'tcՆs_]\#0656>F4) 2661VxS/Y`Ђf%`iV;@ey8bF*p~"}e' 7~ՅE=J&v%F^i jlvOb-+ ?oHxBv3%wvT"/roFz~PfSy+fUKh{ނf<խ>?=#NWdd-gGrx<99ϑK=#HyYx*\iuq>)دϩy: ix ex'綺C},A;rk>θH?)Ҟ\ ;y`>H"i4eNXw+k`LMr~QOvR+[6tYU fԬNfUn[MuEӣ~ؐb&X NpPfGۥ~>GQȊ1%bgv?<+m>MaZ A@2{S/a? YTb\<ᐾ`Mm^+V(k~4l8A c wt2լW*DVvI0_|m2l_S,Z/-xǪU񷧪/N-hJJM)RR6*ȼm '߱$ Z(lI}xqV7uEÖc8h98M"GOubA7s?sX&r*7+yb]utp`RƕMx_w5]A'߼$.dSiޗ4N$2Z-rvj)8OTթ:,=Z ïYԳ=ww;B?)Zҥ"x?Pml,!.fBXu ɴU?9rFql:dO@hhhk<3=weo9Kb yX՝וkkdyߝ#ym >`- vu~k`qY$UyvэAxX7[K+:Qtz*c}6UFz?1PX"*yv}9BTS?.} ளۡ&~EVJR4``a´(Ҟa5荔ay1I>}{8^/yn:S<~xיeOtuHj_exu z%޳9jMIKWZX#fQZgWhJ`7TKkx<{?fVe}GJvpT P==-OO\JKM)y̿ Wi֫ShԔ莹1,K;*K"~?0ݼ{Y+"QR/dGa˛;ApeO`CVhG]R|4 E,lVO8яXj@{sbx8ȳ:tu)Qy2y2! d7}]34E"Lk' 9s-Ngg+uBMmT|{|y5#_2(&!q8'Nl?x6KnD(c=I&$J/Dx8+.NۗrFZSY] =:s')K,'Q#kbI: (nrHLe:P *=N%qrcw]G%9K0auC9(Mӂ Pӕ)tsHa]٩ym'hvG9z*ekll/?87@ie%rwƶ=̬70dNxa,wK(h:b\,8峄08YME^CUB É%Snܛyf6\<^QRè̟bydyRԏ=ޢ?21<*,*?yYn; y&vl 7@Ax1=Y5*ud /:ɅcTb`MC.;}ILû[@4A%r`v9kYx8;e+WMд@7a#Q$(g:O$m VXsDjj  m7 S)*E1w# *}wY~಼b2U9+Nai085 0$⥮ zMz G0dE<6ISFE=ݺx}NUF=G(~eyꐌӌhaDsHh%* p:|k)L&Gt7'Z$iNCpNs-pvOdơWbz71阼 xOʰ܉vrdm,`pXʭ&.,XFyKX[2yFv'dUTfE4YYWJLWo<ʑ] nn2o0h ՞B}oPBsK=)͓)~~pm6=kS:n0RN,k=874v!1gnӀXAp,ۖNf<馣^:&2`IR~V%vSjש錬g/iah9Q0H`T o-rylfZvt?hBTSq }Y>p2Oy#$SE}~Vq='d#LɁ{q$cg}$Y7UrlJʾAS59۬q ɢ );yC.OURevʰ\zoNHҒ H5:e쪵x74Oy9ҝ創^&ۇه}HJ1KG) U p3ҹ<ՆΖ]Űۭ I˗6Rs=A5k(Ԥ>vR'q%9ci[x'`5ria`:U(F =e+O# KZngb`< qӄ5L` ZwlOxڶ~bu)E•o?;+|Whyt9ޕX&QxӋ?4Jy1{K9/)MbYxeZMBmUK4~<t\S~r6D`cdR!-aXm'Z&{^N7(ExseP˻c+וԂTGNPpU@Z\gX𻳲sC}Й8h1I9A!E?K DS:`VH W/`/Nms0Yg4-\7EsX5fks+e=Gܪ-P=m6v7UrCnpcq}rXk!*`htr7<Ύ4鋝 u 7R*X+P;z?3v t.z5bLrV :Or[{GCApƜ<܈JbFB$Ḕv [ۊq"7S:㢢zC^[<8+J'm/92iGce驟2y_Fǚ(Rȏ? :h@g=T)B@/DModvY_$?w %b)zjL1ئgU$`; JBLl}}S^HOzKzZ89E!q:d8,ljm.`u 6==nu  XUJ ~"e z"'rb"Nˎg7Bݾs^ARDe(R1>Ba:-!ެ-ͼVoʡF`|>x{/ ^cw# $/{Wڴ% ^KL箢N O4M4%0? Dgy]Ƚ$gq2c)O/A[?|)+DA^H_tj@X-0&kK\ jOh'pl M|9HK{okS2g*"Y1q84: Yk9Ps 3qE.;-c`/vqf:f._0c%p kNc}o3yOkF !-;贐,(h?X\,w.GƮ>Y-{Ek Dlvc*Hw> n* 3~@Y4t'Qyy6|% `Z*Ѯ~@sյݬCcxߚdܪJ&nJDޠ͢*-+A28 (:F'\5"!]* Ӳ,p߮pl->煞wΦ/L g$1mNO5ح5߇KRi"fXVY, @_Plr NiM-héWUgQs7g|d3(U@p)gXMZM!u}@lKFI,4}_? 'VRH #]@̶0fmӨ|_4vS@wҤ/ R|fڵWusHx zU+:Im)'g+Iߨ;0oQ zg9.SPelwq,rAg욬SC?鯃yJ2H?괌U$G6>R,ز%U[I9b8H"kWHFxY]0g "Uj̧Xp ;ag#Hn,ƅb jdIc}Dyh[.D'o[W ]-7PgTx_;W~Roh+9U^K--t ǁl(~]:Wᰞ!v"bhzazg+hy1@f_~cQeB֡Nv:3ؿATr r?7jX)sdwdČY3Y^MRV;s^Q̊rJENL݈q3Fx'рVBȱa`HӮ☪#HzNxw/H:u8V(:uw佂mY)~z֐N[P佮u9/&VċB }Y`_Nuu|ô9/Pr }] { H$e2߰*4L<8TL#$ր8]wa|;~cϪҹф4eȮ7S㢞v)u;^9#Y4G?{@-߇ɛ?4ı 198ZʺcE9o-'ZF,=deL~<Uȸ%(6ᬂW/pm%r9(IJeR٨W2.Vq9.9|;P$9)+)A) lL&34۴+4 Ԙe`zF:tΖe>M>$[mp?}Ob*7+OE_F~.[CC9Ӧb~-a.RVRC`}8tvK~.~z|!&4ߙohz=~RKR_AL+9.4.u7aϲ_.C<MK[~(e^K Y[qx/fnLL<eEf<HWYc}&X'5 N64u OZ# `iS p]NgI# ,v"%+6>NQ b;>>Co +"bOb-'ٰZ2IdAj,0UB9;*y7Oa`1+90 WDk(abH@dլXzR{kNFAL'1 mPtZWHN!&XeUiZJ11:^L6o)CwlY;oxgQD`"VQm'=m[ Η(ebyH%N'h"E.{/ Y  -yJ3i,0OpL›{hk`-eڶYwTh'V+-gw/V>4% 9d0I'(T|?63]Dj" MlɜOv/K_ /?{we0@.g}:9):~.7(, :3Nᬿ"ũ8|7N 1{mx 1jh0:3&:y-B gݥtU}PΪ@\_fkit_:wj05 >M!|A4"l6E=k2 }$Whoa5le2'e?e*R%y,n],a>t`r4`au<j! ׀q%b,P U;68pVפA(ɽ#JJ>w;w1A#m;yt~RSTn0֟[ƻF<vVcvWo +%=%eIDSjҪD6\Js5 P qTl R:V=ҽQ$Vח4`f>QF-PDגD5뼝 7?ݣfv%ObҸ8m~ xpyDz, ed;BJJ{=M5~:}=m<݆BtVvK~6]U+ 5Y}'Oyl;y4kNSf^eДB 5t4s3_w<W2J4GȊ}_8klg0tnK$9bzwJNY/L)`wB^gS q]OYrYtrBU[UsIs{Ӏ̱]oaPqf\*'Vo?=|;+&YtZtjjMO9uqؕfQU;Թ }hMϑoA}>abMl!t>6 ZO'zl%',:1/ Jsbg c'"wj`^oaꢙ?0sU-2uC|K^P!r'|~1gvy̪Y F:/Q^*DH;pCy̜$I`bŽLVKeH KA +_e݊3xi㴜i/YbuV *RYwY)BQ^1%( _nUіϳ !_#"LNA\1ډ_8}`3ߜ 4s1z=ѐIl[YNQ|^06%?%fW'2Ѷ['S%q &k^O%.?>t~zx9"5!ҧ7E}m~qKJ/&hZzķ `6m68~ ~~6Gb2R4$zdW2r^zf)VL^Waqj6괞N] |g&**TNm;j-gGj|mi9ǨG9Ow q ӝ˂[Y'0S q Ғ.ԠOstQd]7֫rUec~EvZsytt4U-t|o1=ҰkM\hi"Mn=ϬuJl)y4BӃ;qe9X'~836_}Vߓ7RaF"X E4n'2oA:ۙ/zg~](KoM4G^u).>GD.3thU>SY(W~p^wdyФ-Vvphanb3Jb^! k# 윦c pyl:#:Eٷ^d6N2aw=apӋ9?6ferMd&hS3fUS3^G5?& 2OyxѤw1nF|Y-N@Q# W BM5Pͩ>K2~Ns݌ĪpmPtԬpE7h _vuPYL7UlRVEAi.PݝHP[j8.ZQVK;rIdv0:ӳ]-9JW _C%cxF~a'|T=3Ŭ%AUii>8Ogc(ȦT'ĪNLHOLAJpnflʿd@ORTNzr={4]d))b{u?&(Sk[; e5pEΞZr@8 #-+bs,~zHȼd3X:HSA= V^a?$]ҩ긆ː!ě^:<3LS#5rCr( y w-y,U#fH m` ~B w U*@Vϑ"E 8Ծ")k5xjeVT-4]Q=uE%wn(7P8]LTT^J%V ͒/p㸍.cS5ㆵk~yN"9M% *;IDlrLmY'lCUwHa:|?1044 tLh`]2̹ݙ5|C4 x9K'`U2|nwLu4'ӹ٘~bga]*j26v+G/.vt161>,ep8[k"d$ ,nV}}3]vTRgܷOر@-js\J&soz033xMyyPyOȽEʸlr/&bϧ#k jf)4%}1Lq#4wÁ"fvjJZ.M3RNQtۋ w̰Rm6?9J!~wqd|inx;%7\a5߳~Ed}~A_l-''Ƴy%3Ё,we?s0԰&߁>G~.9Ra'uY'R#[#1GoOwȸybx$vzuгPvwAڹwis1 K 0jݗ 8H`o Mqt_RW>ـbc'g xoň>fDȳ֟ngU+g; O5*w+:序Ru/Ű1Yg` >,Ϋs Xi2R"saZsxG=N!r;R,σHȕ&+Y|G`b(XV*nFC qXO?;y/QhIOBKkۈ(݇x>ܸ #98/KH'hn$:Ik3Ap?MZa M'K;o*7d-1eqhOcGCuT|, *5gO!tTDbo]):ݒowL>TեJNo||*d%h`!b%u^S^go)4\Jw%-Vq⼐DJHDe̎efQ՟tsv6¬tU8@tPnCLrK>^y w+ ȮNwS{󾳲W(Edgiʻa-ǹJne :T:SdBqw g}FE@AHѰZl6S~>oyZL=KOUHWz+`8ėuji]gO o̥'cC}/*vu:tv9wԅx(@Bѯi:=Nؿb1i݇94J.>n9?]54D7Ϛ~BnnE&?iy_*w؟P4F鉣گ:C- 5>wqVJѱOH7|"1{AWqd?l"ν,Ē=#xaWJ/D?޼g #:lxmjx1pt;rwe?e٨aM)BvַqV9(dJӡΗE B325*harHMg"?V]2(_$ڪ![!p$*?ZV3͹Dv^glhNVAoRQ+/HQu Rз;ieܷٷYzaʥF?ݜ4֩7 c0HOVǫR P=ʁ8 b)x{a˙4ݕqR咄768Bj/+V8! @TEbVOnyOYF ?PEY} Rosy.ai>ƴ|ӘVɺ*EF73.CuvFBWˏ+W`铧1P;@W?V2~Gl1)E L$e6?Q<6xW⩂ߕuoM0gPpE\IԿłr[7<%G4^`wj v[+wk)RS1r߰GbMϤyl|5_֬WR͡lGcL-]f MEa?=O}f}cSg5vt[[ >rF64V={soxsg ~T#(s@kr֟!XPK )Y eUAzMS8qB_igyܱYǟd&἖:=n}x dTP#ڭ.ɽQ-[(KcUOQįҟyct67x5?]4H_CX(K*jl3+36fHsHZCQ7s_@Pᤝ_~_^[}AY A!wuXQ;,хxn1uzt d |z'#bؽdk|˴"(}<ޱDaM9@j *d,D^[;oۊ7j5Y ]#߂~/8 +07& ,dhc!azӫLSyh>T7(1@"oq=S=m¡Ck/ K$vݢ4^P_}b xR$!a$E%$ MReCrHd:G?P~,@/gY.AJ:1HfK6/#104+ Y&)z2I/62=li7PA?]CSю 5Ŕ2fUi!yjY8M'1ɧa;rD}jXx~ҳӘP{M -o_3g%c%b=}ῈeoN.L sgHImEeWZb]ӰnVƛKMKw[vUcIYuK dOrHqSlV3 P(xYCI} v_ISBsEhEp4y'2x*5O4'Yå15pc3GN˩Y0Ydp3u iI帳>:CUYb[c5d7$z[ /q\7g7) VؚٹJC,(sZZ~Oi360 $:9Gis+kk %fjOzA<Zx/ gjmיt*6xTlDf;n$|~l26ҨoHb$Tt7HwY))jjl(T3U &6  0g*&u1_.7P+:l{k,^EK: Q]|}qevRE6f 5BDߠid~L0ZV,1#[& ~0toyU;]I! I@GF@wѿ+9J\'T~7OPf~%Q(֓4.OҸ{8كƖZnBpx|Kԡ|W)nZ8;s/b\>5cˑoSG>e>iO*+ͼYo:qwJdO澨CURA1Z+T=׼I&V8"QPvZD'(֠H.wGprXBSAR&S]0|/9qb+MDJ٭Yb nD2k܂ɃRľz߆:ރԷX9N2E 58ge8$ 0%uȡlLGґgtj3yt]ҹn"e?.qP+~~й8HdUčLMP+~y߰Q+i{yW 8>] O՗fO[U j< KN?iApR:]Z`Gtډޜ~a:8Nօvxpd)U:Wq:b?@C*gQhd a~&꬐ޝB{حE_[yx/e}iARQʛؤ\T3҈[-vR|Lr=rauuQFć*iA0m=y~k\OւSP؆a|WTA5\G0Eq8=L)Wr[! lt+'Xl9`g F2K%!sx߻Tܙ/--/&(ꂌB},M^iTsٌZc+Q2lrY'wOQXSJ8B;6gqٺL[ W 9v_d]cK>ɍ)%w\gSר A"8&p8zXP#±F.ȰDA@n4?yY\^q \r <Bm•5$  ,"i<YY-k-T=m}x2ˆلB1MH )%4c)~Fcݝ_uj^#鰫StnJYE^J YC&!PVq1|RC^GqAYê9Ƽ_ 0y9wS5J<0Ag罣TàUš5ՖBdPM<up/W'-BG!UK?Z<w#I Ϫ7hBQ(ң !Dۺ vQ&qy==vvWVQt 8<|k[,%?Ps֘xkS\shVV+Q9{}i;̓TMUN2U^#g# G."jr٧AWŖDT2nD? `k 5'^CMkN]Sj~Z}:(J8ZȲWxy*Tqy)hu-f͂ӆfq\A/)^#A(] )w[ftb D}h@Eyk#Ajgj6v-n>ND*;΋95h"#|ni0t Ez\K`ƹϹ4Kaj sÍ.ְY,sU|c.4%B:CVjAz5| N i:0:;V3ⶬ|KOwN]+ʾ#cq" ތL[VҖ{0D!JEܯ؉-Pe 3e@T h,Z`_e?mkuR.~Nvf)"olܻo9)M ^KTG<~u8^z7L'«{KSQu;sXT@Z78NI'`]Z4m?Y4]/WA??Y;D[3V:e-PjmU>VaZw5g㉄Bo\Hj}Cحtڸ6` "YW o;oɜ%HSXnd9`r e;k$z?jQy/UccQG*Clx3$.S9?kՑ];gojYO]cx3X*Lzl[:LjSOUtFFO=i#+sz6ByNXb~&NCu-HG)#h8ϥ \J=C9࿨y'o4>/ld#<7Tq=uh6d7!U9ՅxJ>v~v DϞ"D2xV$~ϹmGˣDKr)0@)ZIkz޿g^{4k1 IM_Qw8 kFS+s^aC{ mxGx}H)C/L<żI[+`栩k@wdzֺ̘ͣJzBg|1rw"^V#~0. wHY ^^)bIGmr3 -egrh L?UVJ"6 GƷ|1u@Q T3̼uQ)wM,6;)`>b^~K4<8F:MSi6 QɈ;s,MdvdqgRKT#UcG=Hk=yd?1)~gmDxr˸cg S6Nm^B΀LbGLɝOY08NtHdlOu 鼓CqABYу%xif߆Z PY? \&켠O8ʄzSԏ]R[UY/půJ)y"Hظ( Jwǵr{lGFHzo/Ӛxœ`/AnRzSbIƏi(r9'gL#VeZ>YUOAEK%U/*ӞJyɕ$Nt5,k&/ jR ~cXMdzts\Wi+4Hf%3S-DN\+B}4p"5_VIzAN]m[GHL%0CX.MK7_74gq>'ӹk +Th',PT`5Y͢Ĭ:(=2,CzڨקF~6>]\5I|r뉄q;I6ך&dTr,7W^JXuHj4 ̦~LTrFOrYtR_gg=F2JdfQTLnhh+fGbyR@>dL;WǴO45Kx,ΒYr_ p-YTgyY7 X etp=XRuPeNJۙ: κEIdһ-\Vz#Ba:QEӳO"RINP=7ҊS5'SZ|NQD@_# 'nu&5u35B=iIS+!֤MsB*0@ǫe: O5eC'ty#Lձb)vdدc ,VFe>f/eb}MCccz:q.A~}(52 22)1&eE*KXEa{6M?+8$ "fμՒ ?z"^O:(OG⿞Txdz !vuRAn|HG&κG*?q}A¬-Y&j+]R7oݙ؏8w׏%g isBί<~ăӕ''GU3+Nui \9u//t\g*#/'+=>DOJ޴9A!0i8嬟tʒMsX N2D+FEǯFO~!Uߜ>og;;i_}?~Ic}7|_2_9w4X)5/OQ^9J4tA@)Kn7de̦i7|mDj6*y}J%xEJ =&W4~=`:[ahvo"):ܶ,℧_LG+YM=6UřCC=gZ%V(cdJ8LL Xlyc{} 6ƦaVN]6Ի/r7zŔN!ʒyY}[i(ks-οȂ~-WJCo,t`k&=(ag_Ѹ+` ʊ.ohQjxuyGcH͌˟ muв.7S$бG>˼ҡ_z Vo>9:ALڀ ǚS;h LϸFoi7.Iu+ O#(ޟ+ KV *;>ŝ̌Ľi.lI)FVYեmMaUѼ2v<+qN2QʎNr9ߒ#l?g_Xg ]#1З5_($|٠FCQ1v͛!^ ~_ÿd}[6Z =hzWuK8$DR??{vİ)MZM/qwgL#ւC/23% e=4b'Viv'_wL⏠]1[RljM]a_N=*ss'zWZsoL&d`~.j )ݨ4$vo(6ΆNt ;qk\ EfcL9jQGT4Q~g3egrkz p_aep ڠ =6O[]tQKcaXwywo޶ggr34) ~ECsyc19ltj=a+Ҍ~Cyޕlœ]'nzلuSH%#oH@/;6|9``]RC!w@!C|n9cٍZ]i +I0᰹6sm@>Q.1!!շaCpP9ܙK6;sSZ!} YiAbK Cvc**WM*ӱG!PNxb'_^CG3zS#` E_|EoG0a+n*,\&Po=2ڍ;WsC 9!RhY#Ҵ2ŧ363tPK~dm%wCLBrVPPw' gT3vx3š.Xtm8SIL;(~bfZ(4vG=>Ŏ#E /;3H{IWoɇqХWdEҍFRz KD.1+(a9J(~ZgΌl$NQ?-;~I5IKwRZ4jXuU?'|2fs8r"z:qf6R$%=8˲Rgd')ư!`Yj 9G* k.8v,C-Ń:+9-wa_7RVUB ]js"ЁM$7~d|GLcrGvBUg;%9 JM@wvf hsf VЅ4uNA:2񌣿? %N 9.E 8">K8g(0֞`fRXU6u`zv3vQk2 ^>cM?@ֺ;L;?5UE_I{vr(m+r!E'z.o@FC\;Te'f]0zgE_ʈcw 3\iʂ,N^]=gQ( 6#sQ;;ͤ_ݭ\ig+ R$U:gs# H ,C mo Ls)%Cb}J 'sV}A}+b9#@D8ě/d^V<uپB#@\/SL@>|Ieb+ ɀbMTX\]]vNL! 4;ppkL )L P38gw%Έ{P!kj'kmiYG~FGEDBsA&E]+ÐJM$^'[ ^?c#l^&fVOv=h̻tC9[1^F1k3>h7X&zX@ld5y/c7 t=1Y%V9` ĪS!C*N8H]kH]X4HÇSY&Ld6e~enS J5̐޸?8aA +>ŀXY881ݟ{VVlgal4lv4e]$'#E/|X(S !|(I3X7wF2D8[`2 [ECTɇ3;6quyF*-{:WQ}e(^F}#eO};)b[mOUf:dD T]7Y>yܸ)%v x:@y yꬎ#}۵ꉡFqݭVPy C^-yeԈ5ȇچUT^#GrϽEѳ]bm~fhM` +]'K /R8C8ϧR5D.3d>'pc>GYO[ زXÞR-I!*VyJtKWĄ/QϚ ?Qix+z3,O(3MM\ɖ(Cկ1rR2;NЧAl=l ;S &!']rO) f䣢X.g5PV.@H DN͚$%V{x߾ G+f _} J؄5_ͯ lLdC!ltm^8Y\Zׇu^' ƈΌ4%/'3EYCs ^V): ۮtqlrq'ɱ :iϽ3:5'4Rsgp\dEaEL+<Bɽkj L7@!F7V^˙Y5QLV9!OVF 'ki}-G˥_M)9?6 :&иU(WϥK! >.*)tƿI TXS/ `nC :ǧ*ѯ~ݭ(yMT˶kyCpIE{wH-8wrIAN#s?^|V~On페K{?]K?*F8RLҾ3- &"jtLh&'ke>N3o0Z0ZKFGI\=!&8A!fȸ4"hyOjIlQ A[PxM OWA~5~{yߚA>l&jA9e|))k0"5ŋNkץd;vHn9_s;[b I:?-jqv*bynlVRJ%wNwAK]"E$"et_3!y}R?-4XQbI^t SX:PdOxO6cB|Jj)v}}ƚHQ*%ҷ]וMp-7Ҳ \:A_nX8Nb \=:[ Z Y.Y6!9ᱯ T89mjp % p; foតt}^R3hG0J`y&O1Խq9ISifK(䜚6YZnF2,#L?lmm BN8򻮮z9/ J?{ x+yG(_%;W֙hߛi{ 5cLCO[{PZDoVSBA׌S θ8qdhx{-x Zo&JGﻬmr* hI@ytm|),Q>EGأUq)ܡ{L ՈTt/ir(;5Ox"yEt˓9i6yr8p" K& e.-341N8Ut^ς3XU8vcB: \zY 9ET3 7z$} >ȝIi:,GcV&@.^J ^k83Zzm5%Dŀהib)|#尝$P΃ĪQȅlJ(dRlf̗cTP*-O۽1'o4V2 .넶5}C8m64KYaDM# 7wzμXM 2h"vB Ҕ6ñ|umozzin.cG85IvRy`F:Dy툼m)bCr<$Y *ߓc}# v_ސu~nu $x@#Y#@&9j#EzLEO#}6@ 3SwF};Vlr %󹹫pdbIX?nQ"ؤ9,S^&fgv3ʉgg:MSU7!iHn@C$H(v맣Ͳxsc1MZ 4I:AKaW5fa2T&fgv,`.0+/&̩g!_^P NяLMLrqwN>ŀ<ۉ01:9;" Oo 3i(CLݤNž]8><̫Grrv庫-_ ;9RG/PcCmLgrO婮⬔)uR%3d&<{_+J"bruFr̥ϕk 'sqg>4/Zyɐlh(|O$ܧceƏTL`x!fNY=d9T'IsuEp͟Sޟk_uomvXk"VxK\un4a ZZ5]+Ic TO9X1h,C z:MNnzC}>XI="TRt&_xlVlj%Ƅ : <3# K^9&sǁYUqj68H /Ɯz[ysO9PI(tz:dO6TesFx[o'gcoa5yw) !zl]_XYMftBX~B?bM@lH(! NA{gC(|wa)jv3ʚ&ȡʻN攥@<]ysRɬN;9AXIJ2tdm+R A.l.amO[xid!TG ŬD8}Pʑx5{:tv214w:RTg hi(OSpk=(ux˛uNz]p+iBJHu]d F}ӥl5w9 w.I61yMxy%긡^Fo׋O*x<.z8r 㹜B4bPڦQjHZ$0Eˏ,:Yp: 焎kdViJxj#ЄPd(ّQNt08YY3ft 1/njnU`䂈Cg aj6''"pg4>wR9|Nsj;s&L@e5Bbwn+Z_sEV|¥RIe6"Rk +|`~K4C|^Lc`JUW{QZ1e-=fŷZ#!p^qQdq9)Ż2!54}eES7yqmv8s_?@&@!lRSƬј :NALqY0MS^a)BnN?]owZl K a2X3皝9WXwzBk|$TZA}|l&"Pm\FhnRC9Qޑ8ٔ`mG.:bE]qrZ>a]$8i˘Ggu'P!EXd"]}d=&s+CsNڡDVT,w41rb!jӖ*,Xrd㐤>OlhB%1J_fq&Hqzu:lu87mj;L%3S.G)V@i~|zi 5j҆tn$OU;'4g`VƱd~j⊜x$T),$ 2qPp!wk.g!uœ|%R2 uA\Y)ѱmrΫ}X|)NS)daOL.#wS?T3XqmWQ xb:U|qH=Ik۟h1 (吂+(k# M&(:q:u*OڒvV@RY\bɔ| }QFk%>4Krs~ A284 s-hpSY" Oη<{û8SKBwP?Dau(Es&+3?ZgPrBݦlso@IIRo]OsڣOBځu9wV޴!,ߛ-Kwr.OXÆځ䞕m;ip7lε@$ e|׌'!?*Ny;o#ڌ(pZJ|5Q8/џ6[etk[U,%>kϑY o uv|"ҴUr2X)EXY>//dtNRPQs~`^:fv('6zA} )tRA¶K *\Nu8h2LlJڍpݡhx)%|HԿ*[faz㤝+ /V!}"4ezؾ$7٤wV jP Hb͖Yg9/ ݬۜ9,}ePK6C-ӃC+iJv?Dk`T;n<T^ϥٔ^rKsO'O_ڽ~"^H1kt(weyަƇj/3A?XӴ)CG>,ҵO/e $?/VZg*6s8KhSȏ(l,;e@eL1?ZwG>^a3"6`Ƚ!':-Muֈ`}Lxۼ$1j5]~(Ofd1RA (n9g.>탥Sd\5 gU FY`p,V(xшs.EK=]VLOO'~2!鐝߸7-̣.]>7i>#oN}X?-J8W¼F.BOwL?acN$ [\wemD5;H~εB0\0Qd6LI34a2]<+"$|ЪI:3\o O]:Xr#ݯ866!%~0dpد :K߼ouyk!tvBZ & S$џk|YVq(8Dvڻyb8<9xZ؍MsXm":s- NЅ:}t8X%z4إ6{x&|Xq:*wIZH/}iOò~6yMxm/9OOoq>$I#*;-{w `!+KSbݬ[j X?q}cĶw/Q$9QT-nڜ)GN}~4e갢J0ڹ.z+TϬf+0|f|ׯ c6ZI򏷁jcp9S#ɣJr|[e=i9z?Qz}CޙwAVHFEAue9kNޣv~5Wd1b=q1Vy?yO_mXP/kuR4Cp.IȦ&At=$/xsaڱՍ0`oP܂Pzf5e @m?7tL?t_'3CIک!S7y`E=C@XTIuWݜ ^bb-yd22C" =mp:ơ:k~YAqtmB}GˬvZn[ɘVk8u>vݫcVϳJݡ~6G`鎱b2iW3znZ#/u=QYЅÂ(6B-$/MhrVV6R6H־`ķsBq IH _YlS1Vۈ)g/枬$˔u 'k_whA7Sslq®Vxjt~߱^1d? Dje/9si H7Ĭp"XF;mI8]I"7}jHM = t&5[IXy K_  u;7TNOz<9̬6 M4H7!#iܬ$oP8;|]swH=tPkK.$p15{^7 Ǖ|.RH4hwwHX oS=m% <e'<@ Կp\ԧq#meyUǔU,Nń {r4 lކ7YF L>W-_. =( $pVH gacN3M 'n_l(KN\>i40_B?8߄U4fjNv&t%Ӕ!Exl(B`23KANNP;+Gld?]ӴKF2ht> r 6i,`-2lHh_Pz`b`PBcH63P=r$ns>d Af2kņI.9"DNWE'e*tMV,Fh$%LS~;c4cR7)pU93HG3RoB4LUМ'FV&0ޤAƆ1&FMdVb94v! >ᒱz^%*͎d/-sX&Y#6P.ԗ_#Kb}ڬ#jSV 7"N =e̠ ~ )Oy~m4PtqÒ94j[g!›R$?yǑy0ȄC4l\׍OL.KuI9V(cŹĸYABjqX_t LisI9W&gaTX@Nw ;4hc-bKF݌$'H"lRWz/.r1t-a_.Vhy TL~0+{˛Gf9, /bu2v~&+D5z$hXk]IE 7W$k$wȪ?BӚC#)7cB^L3GNgXv(v.9[yD#bIMP֞a)IڡƌdؑDyѧv2 i>~Йrq^ #+pv2R8H'6+z6&1LËyC5  e+xmZt  }њ̉+뾋nM`%uD.%X`Weem@&ܬĨEO#znxQ3/q7Bl-[X_scyQB z<@+hpC*oE*QYOTޣ !^P >MnYE#zq __ \,Αnt*[ 1un.RVpI5ㆦ1͔G胶=ǣ*̟FoUNlS#@NV8Bi=M :ݶZL %arr]"\HuBP۰apCFL)ј{ڔg̕uvsB췄fvbJM)Ws1͟m m$E o;5UH[3On jRP8>WjrSbW"t)i靈#>oRlϏ14N$-;h;dk>Ґ ]B fogr m31E7$#J*n} 'M~+/Z6q\o.g5\=Qrѣ wG>W,_!}ޘ6mF{CfHוta$(_=?+g"ZR}wTkagwSsؼcI! bg}-}5i htg;YaZG%2HrQdؕR눬Macέ'nr=MѓeO/=F$5 nwƅ +XK݄vE|Q!Jnb9VL~@xMPIRqL%d#8൮}0[68HȺHk3Χs9yf72a/9U_U k⺩9>HsBmJ-:>f܌V1 O/1"oM`DŽb/D+<_8*R[MiKs()P8Q=Sxgf b|@nY3<<8d2q8"]cpKvֺs]/kDxawMb}EZ/8g ń7`gw<E2kd^'2s[wF[sgF [:N+Aw6{8PacSRaԊݩ: Ԃnb_}OK 4Ҷ>_Z#uFu|-:7k"K>5Hm-J/ԉiF3F+0<}Z*_:ENY}u᧬5 iPھ"M2ǣWj}|]c(Ϝͩ*^"3ڈyD$)Qs7`\7~Xoc2sWyk".Cwx3k֨P- ^\18VIljWW NOtb&t&놊ί0jl6cJ|;ÞY.9$ r>5׋[jJ6F׫t<Pw:cEo7zQcv΋&gJFzFq{n[P=V\pv(]ӹm/R- IRp3CF䍞ÜC^!ZAoL;i{dDr!T 9N*}k\goR9!7g^3ݭ,W.n[iIAv40Sޫ횥 ;cpt{5f`lmS/Du(D>o%=<Tnrw}@kB/txSx&I{Wauڒ>hʰ;Ҥu UW T4ȗD$Qkulu0D͍ 31%rϫims5BA&]$"!5ȏZ2?sۨI><3 ՞׷#3,y @;lkOQ G껥|/W soXZWDdZH1M\}or\1Z%~q>E( QGsB!ӕ f yF/f2D-3mƌt?%u#c%X%2Cđ>?ٻWͽ+LRB); 3(we33B wSV;9h>.:⊹FFt'-*~3b&IjH6 =NRC s 5e:&voR ua,XGp;%.vPM4Ɇ Ȟ_ u]z^iAy8y MFDhy10j]$MfǭG|! -Ød^'iKnZ5uzJBoZX=b'L3hnhnF"qn*EYN"jJk.tnf1zEJ:qK9a|`mLɚ~8׍5!eɖ*>w 6ZXG{⼂'UHS(3VZM; H<{Sdհx S=0hQ&W.lo~tKey~FwroPMԵG=H?TC9 }@PVG9 {(!DΈZ`em4Ďg.ݭf=.HZJY'S%EVI o%ȪPNTI $bgWږyqƹfB4sF 1k MB2?JҊ9 ut𱏵Li۱|fTPKKtO$qyӋg4X'X16m$EUً4g&2M(_C+}sﻅl"А荖mݞrbFӦ-~W0  |{Je8ɉ„JSi&.f4PO1Ra߆p]eJ4) VI5Y~#&C:;tMJ*cSwgTU9̅2@+h6m6Y-~ڐ|BtfGeK#:!/Bo| ɮ\&i\A{:U{k=- Ĝ3$VPnCѯ܋ \Xr<{.lM@}XI'ڥR=ìh]EՄ}w7̈fJ䳺JCّVhsJ|j[\.DK=641!M miET T;}m9 Pom<ģo{Ric8<'TC3sd˙R̅SXأQ@, wIT^[<׾wFY:1ww6U >uFcL \ ; {ú;4x²G)kmT \ D?0%~e#[HW H9?|R-\Y, T*>{,^\r6r.B+') ʛν?nGdm^MɁ"@wF)~ kIG=+KLPf^sT8B`OX_vb~a?5["ll)l5nrHvמReuZgSGDŽ9fC1Tp5gTKuY3IspρbL9c VSlRgW΂|Vcd@j>PrFP'7-hKe~y9)<)Y N![}YsPnN⿒8P]A\LcƟwX>&^u |e4/s]nܜ~Yl_HGK-%Xқ*)Ƅ͐3rvхR {+˅o?t#:xXWz>$e8Ш_RV1 5itH>cv݁yˬqn6LZ4׿,jZ'3ru\64y[EM.NW0V봝V?r"EQvs-RyXVux3g6_uwpB;%X`f*k>C D:q"rT$O8;!Zn=h-/&Qj^YxĮ&:KퟆSzw:-}p7:a}p@&I.-AםkJ@M}i .D!GWnm~u|ǎF|nOpeHySA`2ƥsKמe(Vf Kz.%2d*E`7LRO>r#PR0u=9va)lجkL_Ԅհ)TE66ןITᅤag&w0I¼؜Eeuru9*9XSviCGh~զ: so|Hv3Q$Cu!RK'E s_ZBF..?? ͺfCy`w4%x g3Q2{%sLyXػ)HZ(Ԍ [hq#w@Hws WNK޿|ZZq\(pR&ECw93n7h{sE9B~:,x( RD}%̝g8"e3RNNH-??q^=?U/OُA/ 0$uQ e X6ҶVސ$us =p3&D7, x7$)߄AjQ`֫י_t)Ө7p&74E8|z?zb枼4E>L3>E{JG@5+enH'꽮whT(ޯ-sT)~5BRJ‘[ 8ct31@~R\S#+mo:Xc|,Qc_P^¦ꌴǁjk:᥮'=f%zP41HUFa͈֌0R qdhit'O5T 3<1迸CEzsO_KIJ ]gyXo]:.>Hѡ`nˋgGⰕS &<ʏּ-]\!sJ/ ̪l͑![{lpx#R 8VInz24=1g?2U"_ |q|p@!yp>N-6!|(`6 Syçs8#8uE{%4Zj+仃e:8P4ˈ蜝h#pCJ%*'6F3͈Fllo /)L?h0L!춗${4twtљ=̕'3%r_qyN!if?y p~b: oP9 n%(\O*tiW^j?1ULƢ<ۭ 6H`mb0na'1 (3(̙آ"ǔ+T];Pe$$Kq+N0bmq1y}]wetW8納NN-=O8V+pE',Z+3J$fHs3Wg(s"):߹rkni9;ҪûlH?NB(HAw1PPFaIlD%G[1o%dvD,U8ED ̲ZFѬS"+jBAn4#,5^#ptCT'҅ц0ofpBR)zZn6}S'{Cn'1uvԦD*#C$#VMLYO*-P-#9t.aKY>JdsaB*LK cwٟ H'%P T)\Du|⢏M:U0!ѣamEbTK A_&-: &q3i.KzvH%R؏2 +'Ҕ:m 74t*wWsh _~wY!wE`+6x̊ҠZq] |2Y):ԱV}~^#* Ovk˹!=Po Guˬ% Ey]9IsXє㙰SB.2v3$MK {Gj3'y!1>K8!!z)F؆1{ 8o)#Pڹ4,H #;RzAo3c V [|'h5DPFE y5Jd3rs#%v_bsANwǡ4~kC9mB듇R M<`#SlKC a+[ +7tSbl9\eJAJesOj^D4»=pU?nz fu΂^//Rkic@ݻ?(W|83Dwi)]} KӅ9v1j#H#9Oq%9_|gY#LhU Ѱv H"̳R#rmT" 1, hioih"M1m=fqݎGr1mf#rBihq`UK[0qQMp$m Iv18 2_a9IXz)=L4r&-s45_+G,%dv죾k+l4=E2)(rH|X4H`GE2R{Χ> u;"فAm=>Q>.Fu97Dv91 D#k0!8J0s[;jCQq> \*Oci#{PۙT9JMkA!C0bEǙ( bHLAv>V6q}E2W2"i8S4QАy,`Meӊ<X}l^L޼ ]&|2Ѵ$$H<[2z KSC>l+ԯ)HM8;=mX$Sے{]P %wBýNG4GF*MG賞+῾Ntiu m4|վ/rf!0ȧGV..;?ڸLòBVmgMX*>C~cﳪf.XD/(Y×Ϲn80bY g͐wd]g$<ށU^]MVg$˹HnwNFbeFlABo\Y3ľ RH0 i oIݍ(Byzd2Wz{n6)ڃsyb=8  vmӓRִ(fX9͙Ajny*khuGU'GYQ* ' ϚVAa !Ѳ >B`aEY` }D }vi6㨂fQxWa^};v:)U頟")@it&Z?,X7F;ZU&}Xa>DO=#RY:#U&+$=e#m^g'xR&֌+UNpg(8NRD!%J5k>iftec /|SOSVdt>oAK3~ Pu_)?-w^)xD[g ~T w;t$ڜ1]ĵR]#.i5 T,kWSVV)a퓦fTw 135V 6B{zx\47AyC: }TҺ+r,7LfQܓMK{]j?1w 𑈾tPȜyPUwwPu?88wc2wLrw;-5<"FXLYip[}Y;4xG.Gi 3K cʄzr$k:PzK`?9<I}:h>J=IISM@ä^tk(Y aA~w x;V$'W}pVjaBS &A̬[2I Nkc  !' &~C3\*) O\pLQ>-4\+u4觮3."owyq۝H.mm_mj)+_7g y(]f6/W쌔qh&P=^}}]P~t 3XOF+u._wkk^z\x?B/$b񙎵+A}9sD^SEwU}`]  l\VRƭuǹN3 Ӑ ,lv^C+7by9dmMIſ42ϻr^</ @=i ;36Ziۃ\IG[/̄Lռd>IU˯_j^q;ƿYshګ˾Z5WI5[D(7QJKB2Ҏ‚myd-ҩ-X'5A[w&h!dVP=`ܹY3%IC3W.ޗA%ZOt{Ba5ӱl|h l#$xF8K63Q6͒1fI VΔZ~s 48mR]SϝK?JN}49ג'VmH,mzVw(b ͍v$늰YN)I}8Úk*WYVk|8}߁_NV6;)%yw ך9rXhxy?toG^vYY.&ؽIkl "e5@ÓC2ʐ9 Me>iVjb  eҭL:2~_y!_ ]v~Tk[J![9aY:򍵈bzW I -PέDO[r q5C4Ajva'U Z@ӟksY/O<8}`TZ*n՜o>mS+O(5 ]& +ϥicyJLcnLiě YѳFc%YM8B~jGR>VSitsx"ݟYpױ:cͶ*FWaVtv2: 77{^o8 v(-ILJuDLGd\j=y)z1O8K{vaNX E#4ݿ蓧I,b@ pkPEXh.jtz%tRcJ2MfK# 2d4+r>=g26bC4N4n:f0?\dGuE/ uΧ:] Ij8SqFTEK'$rC9$ }'@ 6T$AEYLu6jÌs?m5ke\IM9 (◥|xPY1|yz'Ft,[J_whכGpFbAhE2n-ƦaVV%eL6S+ڌŞPET5?%a曛nYw_M#m=Lefp[vJE L`\\bMe##sN`#T|pGUiwm/ HF!wy-b·șMIK(Ba-R$u{[ YajqP ?? ta5U6~V6V5 `l-f^mz +7nVRҌH,ΚymZ(*1 ;˾i2&'w!Gc7?;:&UmP{]ԋ;iCD:4 3Jv NDOwө&J3n&ȎIif~XgjZgJPyjO3d)AD-Iɜ:MֲNZ?sc&-I?!j)}\-O(/|r֍M(m(mgdT"M`4A.yJN]짅^'Q*<溯ʪ Q^4f"y N-N]W);nXk̫hWKuOh]9?| OH9NN<%_YYٜYwS">oPoҢw5 |^Y=UiծZ3v pKIޡrSRH׉ԧ$+"u@+:VP)xGE @W%w][r%%*wFv X㑱NO4ɯ`NTrz0uHhUY_dV$B&畮;1wSf|*0MfųJ!Y[n^suGa=gѤīLEDuιIK=7}{YExv++Cg◝jM7l&%x~ԮI" ujT]&%-~Dlj;doL}6N GԑCOSc/ƚ%您DZt>@y̮6s8/ MXCI k[+40G6ys +`NSNx9jmL/]S:6%>#:gz\U;{Β(΂Tgm6%9}Y(1+":"Ag׆pMhaeN4m|7hm=`uuY.%G{{$\jkPM/ ;4fK z<1h=ʬ&j)xw.)ueUd])IរC.ALbz:qPfQAsfŒ ,r=m)3&q@8w= ɜ;7I\FzM?T;Y8\>LK\Ϝ'K[y?#1@gP7gi3{’[5bf@#s6޹M+(=Ks2sd?N(k~g¤eN'-|e#$yK:Uk? (@[ޡOzB! IĥBgxb>S aOxrЛԆ,I =jH)u4|<`)IRR]HT ,QJj8!dd׵z-}ٌ)$GCcB76^P?W+WxU⽍6^r28QIo`F <@ Ԓa)BVSHlW/oL2$"w\zkTJHȎZEy㸺c˲.D#i|я&@S|Kbd*HhUԯ'痏FYNT\aewz^m̟d3vN{ p9KOa(ZzQ QA`/)&!;Rh' _JYY+"*" ռaÒX,RNmXG5!oQ&ljSqfO}";] Iq$T,/du-9G:0K`~,OF탯} X%B SR?o,t|ӎp&-WOfM>38.{) lo3 k#iaך0 p&&g&&p~x9r{صVz):0@v0r_ªFC}zOȝdfwAiz_G:Ԕ^C7\~a龆`j8Qt+/4LRMOI|rAB um,@f5} 1q>?VߵfRsFp4TY(R|˔8 Ϲ#A+II3%W~b}).6ߦ:D1rg'KG&6N_|3Y!.YTo4}~Y Oc/y[ ?=lO @[y!Bz',]FB!8l=嬇l4֖oTߞ3r i*j{  "fGCwA۲GBX1w$-L[+Sje}BnI+C"KGϏe,R{S"W,4/L: fZ#wM峿rV]i!X]Tm7?ra2OT!ICA9;n. kPr@rG>)Cن1SN`I Ő4)~+zƑR>KPZ FU4IH*\2][ 4%A3wݘKT=yC'< fXÞ)ҷ%|uV;,):% -tj8f舶gqwH9yvF^ ~&{߃ChV^gJ ܔg; ί !*\R']r>_b^.,_-/a6o<$ZCS܉kd6Ulkv^^ t|jc #dHJ鏏p8=D+'Sij~I+i9+ G P֖K u9|)pD:1LKԗrRNFp%9?\U*0DQ51hIݐ^Bfʇ8vj"ZŞEs\C|Sѩc.ԑзCIXS9):HD;.=2/#))1q^[]EaN4ԓn{myqVHc:뗼| IՂk$t> B)ܔ::K%rFRbf&ɐ"ͩ3C%*EzcrPܱwS;U*+!grPby'-뎅6,dVI3H\2Ϙs6RZż,"k \9-1cΉv K;H.KXAI~$[/q+X/fԕY,!`m<89Ect5`y ||tOcҐ "3Ɉvky~=wf*/f7eyvy΢Ys&˼zj. m=$)9RlZR181:V~L{Z6᜵YEةOY2eşVeù#i%T >/βRPV,a-r ;0,ROQ|F71ma$L 灬5d+Đld-2NOύU#k Ǻ,E Q8J@,~;(;::m35a׌e]_qL;g%ᘿ&3 cAc`>jǦ 52Dv22e_ٚ 1&L+7M9&U=] 7d OJ,֔(\N1+I$"cΨ坛UWS]f2@r0j#I4Qfid|~;"n8rMOֶkjA9 %"$9]]f4sӵ 5͜gs O DT]% oC\.~Lِ57)O !hVNua#U!1ґL~xYv&K#H묠ufo;8>#'s gZi*:5%ƕlje[^Li/9qL 7i$f{>5 tT?bYe$I8T뷜x^ oF ybXhKclfKXwG`:{'5Cp3!qlkU;*L΂f+!6eiHz@O*`}5-RpI7ېzYn\H,nԖJ&SHBA~6*rpDi)^;:ut?NjH1n4hqEQEs:c|j1dZh}+׺ (H*C_lIJ:quĐeŽT"!7whV#Қ$ =CElhyC_*ː<U߭ w9<' +8҃RQz8@RK,Yfp&yu-"2i=y.%k;n'/tPxŭ1kYfϔbYvK Vw=A'ߴޜ)G2Tglyb'o7N9]O߼>S|UXDX' Yߣ3qNVO:uzWDhc!|fpk~ ZK3Wyzwdl*^:,piB<_~sfD˶W7ęKǍl0Wj"Ma'o~3h9lgwxV^ y9xZűb$~Q_ ιʥ|;q e͉h_wds5סOs׷i!o('(}3;!ӷWgψ2.G0jQs;VG4/n3Nf ?L /_u8שf%~&\sPr!C&2]>{T{jO1煯yL7} YOA?ty|͘c#߿G@8%K@>88?C^ Հ@ [,ZY1FY^Ȫ iT}Ԕu'g͕8/R(bV4s%pX r] p:-ROGNZo<'O}6'ʕ1{6\ 8̅4!;i:,|BUؑF_SLrA0Ě\R[T(J!G<ꒉ[ݑе"u{+P=2.hPF6>1Y=;>?;+}v8h6Pz92MVVD9dN2pаڶ-9m`4ixd EjCu5?O?~|s&omvkRNMЮCYʊ< ,|B}J8 W+DT(+[fڔ$i6@Y&\ 7`SMJYygLriqmX6,+YV<]`6NJaʼ/ap5$a| P4zP`kv-jUW~ V7rc6(A&֓z8PY~ =6mJݴ/L~lB:_#3 ӌ+Ou蹒psp􄚄j9e͊!zB#%nG\xAo<6C-Џ3VKQCaf> Y,~e:٣x?$/[o sG9);dr#fY7}\H5t)9u {z ̌QG6,<'3if68߫ܗ8s=Ms/k  qnP~ +?根-|/2BlpF(hjhf%Ѩ4 YfnWwe@jsF}^@MӺ,g~ e7UvczɣK?˾o 3uB|/&B(0z˜qℜG,T&։Sn<@_~º#n/k ~]N [IADfgYCC,&q6W $opvT\* L> E!E?uCEP)P>C2ζzFKC͖)g2 >3ZXiӡ'&*umV3_XgDz;*á ql~Ν4aI02}}ݟgȬUƸ)I;:ъji>);*KozIY<mcX͑fUpHJ 픅.7I꒒n#~oHz" p я ;+yUѸ͒::˞st=\&qw%Ort(M;:lkdR\.̿5yH'beN[9m+pXX*`=@z҇lS֛nCf2wσ1x.9j#6wgcΎzi.<A$ 2r83I5`VyKV d0W./[$i̇@8C8 7%X׳J[/J(:`uHh_YѦ\aTlѪOl&NkM)pPxY 1&07!n?T&Wm ].PV4MVmg_V:&KGUMa 6TC5yX n\럀s>WUKjۤp#bN B:x uꯑ5ȆׄG-3*٪-5?\Τc5nD)8js?bKQ֩,ܥ>Py>CޡKg C|6T]i :sM41Q</()Y+0zhY.M2" e=Ltf N"y Y܈X6MH^g@f*TFjb7B+ t!\I$Q Y"! uUM+5OP >IP"g^'dF_,/N+-tz]"Dzߣ-vC*GbwI=K2֜ L#kñ7Js}90O1|x@2oղߣ o [!>r_6a?M3fI%kVL9Aݎ@ odsm\M^I.v$q/熪! &CSU83e咶 Y_x lqI/MLmtN3LL|tY%,}+~ /QtUNY&I/ Յ4~BsY1Ȝ2U9_FvGw>Y+3k2sģx*4 LIdH"*w'wX'9{l=M93͉zQX4/bz&Cu)S_H/huej2z|}λ +z` %xe/YQhdZL2%gA/|c-4]+ĹFvOЕhػҍ*eeY!Zr֞ki7G,N:a8(O'6@D1a,]j䒍 EH:afG:T.VmMXЙ(/J\ϕ;#3XNf'Vϟ}j/˩‡*ѱ侏#50wq|Ƴ)GI5_rƥXUCa'wGs b=ĚzɱNBF:O40۷)PcSo;+li4/z\Ɗ8`h_0 hQu:hm'+O}`},yGeə3opt7`ߖ01T{I9.%776>Y:3Ie5G!:!cC8ߡ=0$9Βy{hgtW!|ϧ e g痞ބՍ&:Z]%.vÓnA&'.EŴ) O0h,J# 4Oê`FqP~e3 CP}h͹F& ʧoN@ap]g=bmdh#*&@X-0ZmpdW6,gd&E Ds)[ծNuīm+TdZ|5VChhN[j cO"A ޗro9鱯 )N&db(F<#˹N'a1xYy$D<"؁rZUߝhH|>~>pjNK$!Atn%7r5hb m#} ˴Ь 7"NAMivn`lJ׉vd4[77VChalW|/gC8ueUT1RŰЩ8LTL$m/dJ(6M~ Ds=%|L׌ 2 #I {漊g5QE*9(KPo6!>1Kl׍pn`hH tK0M-]D+7YaڜmΦoh++F4kËm_ZYEki75Q4(1倣xCY v L yejL"lE$E'"z >GmM0Rw;"d׫X,~{8ÚBInakuI\Xg8Qg/^!QJb<~91{B+|=>gLFUo@`k|Ɛ,MP{MB>[-e>ͺڲ7Bug5j#TnDIy'XUB}YŐٕJ4Y︇2H!|t y+䋝WFXh(hcQ~?U?:HdY黁| L .16 #mbi'tՆ5eՓِ ٲ8+`)b SHys׈NVI nY*~F~93NYeNPcD]-N㫾;'!Y>HI`tm)#7~(Ҕ E='C=Z".8I YD9Q9ir't~Vz =!gfbj&0ݓeQúވ~xH#`ҹ!rP95}DD).X+XTxrWYuɠ, lgIɖD cսbޣK! -E&@쿹fr38Y6LOe2|w)pzK޵$gqG6kBGݖl$Ϛ6Qkzr2ƻPk,d|{K,Cø N xb=|E2$Eq~G4x$3HQ^v[چ R)<#xKEd&n-*xV[-9E;d&XIQ9ч 9ku׵-3q: ~'aMs&Гvz TS 4C}k-].VŦhg4YdUYqJ,7oX.&*n }Ohmbe' ͡ tslP4LU/&2P uyc Š֋J.6&oS4A$Zs)mh]# n|3zy睻r;aOAL P%> L`tcu$kn;\7޿Ph3& Yptȝ;GZ+(~Dg-صm[(he ,9#]OEق.Ҫ,y/CF/mlcbk94OM sBnoo7rBYMItɳ9^aP68C9/P|dJ+)\3"[WAጦTr9!|*%NQHIq;se A8c _%iry8$=_pH4X)I>FY># K@؅=f'2qpN|hYec  ke.}DsΪ'ji)D -Ez왲B]S9֯.7k5=lqLHHZ(,f4䕂Y?8fuc ۍ33Nac"g@I8'bȼ!pXo剣ٱTcP#^1X]u?8W!g6qΎn$YW{c9:ʼ.U#ĿJ{.23Fin"Y|x;s  fy_v'ebs/uJ E ˑO|Y8DG(OJ^99d?{~aݍuSx,ӼYDŽrx1(VVی%qDg{kQwq"-F j>l-9d~$G \nU6 !ZiovD9eCl̖;H! WIM!3Cq&q 6)j_oM$:m4t--uOg="oG[Ǣ)s('u55)e-@QHq±DV˫{ۿ\8i4> w.e^Q$i7`ze2+c-~m(~ MޅLDV-l<&bȁ<.N9;g Ig*r>{}!C^|:B'PQ?v:kjs $@_0tx3 YGס':!`0vհDn@wT^%9-&RI7CXV) 6& 4x%l!?s􈅊0LH = +9IsQ2+,l)}Ůw~y!rFjBFIsg+{anuY'hZyi$s6Z&_  KmvfOfRoܞ[օLHK#-ܣƒ\H j.|+KVKH6Y磸\>+p[(Z,5w}Z_E^$ȵӉڣ#>jYWJ1IV _yB2cTNx#3s&~ʳ/O&t%|dys)7X=8NTlyS`(S_+駆Lsg F(4|klL_ݳqX+ ƵYJsJ?IyLLSj]MPԞ]wni,Re:& "?U74\pAW<,YaK-cL3'f!ݘ]'@CHs-R_(6t Y|/GmZ&kЁ\z@mejWP<ʜ \TGHN6_J!8ժ **Qs>>ME֪6 W.30p?J؉3!Ƒ% jK,vbKEgiIua9#h٦K2M.,~85.rlΎI1W|u4O'75V/o?ݦ /u7E{s;K@$ -|ovtjӨiGv3RN4Οׯx $5A M;͂|[>)ClN~o,!ّ mWg |*h3$S(4|NTfDi *V=2gؐ֍47 Q"(dVوM2:,$n(DV6MfĹoRl9sl3 (Y0|3~dS컞\8LQ{Y!~QJ=/k;S#f[.+X+TE$f=;E32FyvQgi^W?$J 7&A sI;D%S4Y[D9cJ}#j*+>ʆˆ_^wTFhj{g ݺӕM+MH.CK5f2 t>ӂrƐOmN=cFPrdƂ;dKbzpDdͩK\;;qgt( ʤe`,gu\*>Mְry|w"FbzpF3WVuޑ3Yu\49s- a4GX:3Ztyo`/^k&k=(c-̒њؾlsВ!{ z;R9Ld:pI-YZ+T$vZ}2݈ %FΑ:!Df?JȦL Q5c})Y=7tNv3}*:Da: .'2u$ ){<}o &/u;Jlt65'/gD T:$8's XhFe KLRCy鿹t2Xur30}oFRR@O <3/_?,n۔ٲF}]2/MT%{A`;0z.3{-W`tvYA.2A@I!ު `J77Юx? ? 3 i7&s3c']?CKYM@y7ªr - ʡZGb C?N❗!Ґ7_g72b{ y#ί9 La7%eVˎcJ0,eP\VO^8nL/wΐ}ro?\YšsYv@ׅΥ'KEj;G4\,;wHMgRzД6![rb>`k[6V6}Jg/x6gtGc<|3swcڹY6C؜ʞ{gK- BnRw?u#6XipXwp )/| `i^Z ԛni L8b&FhJS8_BΊ Ma?iqD^e eF?Mi.k#t`y)Lt\  hfΆ|x .sMli}qBYrX8FgB?R_nkv DKhGIQi9,?oխ1$n^xCTdħtJC˽CX)&wk ȵfJ+{y<?HloBkfխlpS'ɠùjӨ74ICggmF??kD9~BQ^l5Q&ܠ'%u:wg3Z㰉"fӊ*<%RMOmh߻frp aur3\Jz "D ErBd'ћAOvEZ.:9E;}Z]C5sۀQ[I'%lD{X'VIF]-k0#=X c6Ahɧq8ĉ7Hty d&g7w*~[e;Q<ڼf0\ %u=chƀ4Go 64Fh[yH = =bVT< ][2j]P`=:}yˋCV̑Xᛛ6|, [5I%/W;Ϧ$sa뚦đ/<x9Ly0XbnMK9s\ ۮ(Ugܦf JFh>u`2_d?5H{DC:0O'dȬE%P#:Ch8Sȍ-P蒨zǀqa^Rۙ7 ߫nFS[S˛ORa͑N4r1;Φ{jQqHir$;aȇ)# :/ *|.tIahv48Ò! ͫ mgOuhzJXM3b ` 倢1W9UAC>ZdD# A~l_}E?s_NƜeǀ_΀k: T,/x?`%3΋D' WǒSl(#PD@ֆgH`l  TT3 S&* "gdc]٧'#:Ĕ3̏Y)T(D҅NuBY:s ,IP9?8nn c?AK[nFW$g=0_⻃ XRqsJN~x  <*ʎNhY[voy fNNhWm'n>CS`G/ !ws$-yϙ𲫁ޠ}{:]@$O<d&̔Bn1Ҙ! FA`䳚˩M b7<Zb%iLJBF17go™mXaY(*sF#^ݬpPbbbp೩<9y/aUc"M(؊OSjP4֦N3}&Hޫf˲k±12)]HY,e]774hOqCpmD8ch>7A>dS|.Hӈ4?Ubǚ§F+}&c2$ M!ܤZ c3V8t.d@֊ ϨHz>oT$ a&VE#PI|n#Yt$;:?Io6QYg?~q]=~FQ?|T @[Bώmk|rN};Dx&ɝ~!QSRZYXTyo&)@[-c#aů,.NKE&!,$ x]^Q\@xcwiG93mOu!p9q O_Ʉ܍NL.83ۯZ!v# ێn"\ލD]*RRUY7ȈI%/hf՚n(Ό<Ķ~C134OR}K#k_h]JiS$=gkI*YwvYOǕer~K 8'LezpϹDjg:|ɻ?xY]$%s [`& DoE%҉ZY k{Q,VU9;F1eue'02„(׮w98Ԙ,?h2Xscg ѪOj;kx>nG6T#FJJiaǒc֤;j&{[ʬfJ`URIm\?;1T~@~3!?cAoF]f0nuwٹI.c,vNη) #W-ux4:F B<OT~/i\WQg^4—~O r^'A}Ʌћ,?Aְͥr5d`HB;nKԗgزZM:a6ri5q⪶yn>0 +8.y\_`/V# #T/p"iJ$ZBŬNXL֠)}%DS}Iy?vxJ>v '!M:e,w2T@ؚ?&Ĭ6&&iH8? 1 [.t p(# "fw7NFX1(FZ@#@;}ԩQgs0Nn(ISXP);POs>W 6]ӖR}q4M?.ꭱ0/Vxg0K3A{y#9,&dFNܖ ]jE}~ ~ZO,MUz&`ִC7=QWhoVWL*5H3)bm{Hz:6S+_xqu:iթ˶g+-ftD\P6%T qHXv2NZSN_t6J="~2Q|8CN6VV,ɦL:/X$!uZG º?N'Z\ZS$0e8H,lZV¹~^RUu`}t뙒jD( t{zϺ(i- |c% =fH}ݬ4bH*Ő5m_93">#ۛkj=#sZQ(]hI ж\m>mvBAlhF^!.̪dBa4 0rJQ$zLbBH_x'P=1. W3>Ta|.'v d? j3;AxHW`h#:u6gf{+!MrLA9SuG;dԖ"cCQYu]`9yЬCLFS|hs@!%kF{@3]x#^s۞Ht~H:9Kg.-2|peZg kZ;0܉,E0;g~|nԙ*G:|9-H4/"Ѥ&&4B\JIJm^ oĝI[ MD &~o8WcxS1OL0`eZv?Qm$*a7};-y黓Y.xGwUf쵛Cr=jLa69PcWLHtG3V&5B\U3V ٸf;{Gke+ < _{nN%ˬ"NWi󇘙.+<쥣ۻ\$}AYs4АG%w>^H][ĺ1q "g2jG*uq͎ßϨV52xwt?tǑx+t $?$ʠٯ']%cFđwGOp$Wfd⊶ZE~搀 gkLvWExchxG1J0|^t82[,u>0还`.cmtOС(}ř{c-e_Hҿ妱~]Q%g\9c@kuIԞ+2:1<~'6dF" u2}L ?<Ö294mT$2=D&3Si;$M5.MCOJ'6  f9U-beʝwF<̹sIG(1~@ʓ:/V FquN'Z>*-D>hSGOq\k]oJP ἞i뫙Wކyn3PgpPwls*dCTr&T7h6)J|"]T6ؔ<:7M;92+ ґYe:Sۮ 2ЫS9vVPu0oQ}y/g2t!WVe.=U&Hc~w÷<'>!j(6;5)wb<J =wWɥ 2_i呆d˧\"ʼnh5J)h'"SS*TYnNS}e=k,vfkBtɜ`n1y9w;2W}}mtn6>SMs̬N|=giRKRfVoizlfesfԅght{JNa,VfJ_h ż9F9Lܤw`’;\'_]G̕.QSdU tt{qN?_Ϊ5SsҾtnIScTj-1%x1ud͑t>Vym> ̜d&͑ԹmA5cgpb @ .yzg mYx!dlMIvtVSo?8I*y߱:= 'mTqs)sP*(?HsI0r-Ҏ+aSЯS`^UI*0@w)\bԶeTO:>jLbGUS9V ^t@=Ysi"cH=f'V8o}< t`F'3бOmS9@g506dӢHaßY}"`"9ORZV(bc=,6-6&I~Byӛ+F9Ês^lӆV;wO|ZٞYy+.:47>xyaPqL}=PBT8RȱReYߣqHt]7Y1lĘ| w71c=Y|pO5$*%Y'R>[a_N*VYmn l1R$sZhP|4Hˮ^6o7H bL^lpr֚Ci\̜)MQt<"z`bAa·ߘ'~)1:V9oi.8:oR|fv&ِuvV2tT(HiZen֘bxl7PO;/͋i1Q ROt"{,/"iAf!0`%Ρ./ĩ0g}*T/,_ H)rʙbdm#\2Yv)2Y!/Mm *Z1z".ߙ ydH։Z] I3M6` [y5({|SnRz1R' k;9RxG3Q=L렋{''SG1> ;\7;?y18Ռq~Q0Sy8I.n8kdILSі阗i%u掞L ΀fxqzEݦT  ߐء&s𒗔b!%oto.Ŧ }ϟ:w"۲N{?Fq$r(ٻ9.?RbCkx7zs=_u*2<煗\>GG!Gc"oMVH_}.W3bZ@"nyL~D&O2KXpi;m[zp@ &t*ȞFV+$FPtԵH }$hy>=60#vH iN̬XM*|cANc/?keLtz[ua6Mf~lDž~^Z]QCxnhAA@ܬ Y'( @8A{3XzSeWNA#y "k_PYq:vlx|:(izÎʁa?c[HFZZ9WȦNAęEcɕoTZMOtsM dO  8C_g}zVޱQ,{AR3v[>{cG;kbH(o 6 )wSwA^"i"4΢Ew=%:)^.'!GLy IM:~sCs)wжorc-Bfl;qӗC>?/mBP-F&-?+Bf7'lVdG%mx& AC> O#f,壦-V@C3U#{1Ųn0rύ2ן"ۼ\mT#C/T;`kڣ t: 7hiR\i.JQ5tɀ|rOܞ:Ǭ!ټ emA!1TyG#B-+ȃv.]"u< ?;pg\ :UZK5X p! } IWh'VOFƗihN-MWv7gL{uۚ3zF0Q5=73&u21\ԭ/N/'pƩӐc<`dmfRW"qTG|CX3T놪3/,.$KљorAͷބ>yaYABc5:#M#埄?gFPiECC@9t '|j!㪉^u; v*wСeX&3`I(TAHsw1R+:'4Hg)Ar,F.F\gܾ`j4É|:]ܐwtH!eeypzJ7r0KA/~y0¡.Kଝa=vZJG_1d"Cs2kpEÚ;!_'LN0#U 37}>S/Q"&wٕ(X.42ԡ|w )#or);fvX ShTϏ: r&:GzMJXiB\?:zfQKGu B\XqMS쳨һ"ߧ-ʫN:i=WYlbufз-󏉎}>PT{KtE܌vO Ɇuiܬ N~I#wVXLINb;'pƭ; ]kH!j'_t;e6d? k^i^\}^ytJ;wH8IGY|/Q|q>蹴gMY2ld'y 0c͎Oذ3deNFwvU $WG)^hh]/RYF.6YGt䛨#_ccAX<45} g{aR k.vDÇodL;VC4ֿ/L7wࠧe1>8l-Bs:|76XΈ}B&@ $LxΆf*4('#Er ʚ_ϲPyȓb32EKϽlڋ3ҙk:)=~O|)Ǧ UboJJxaMp@m6(y/ 0=J02ۻyX9a?;) 55ڶ~?pA+x^^Qw*\>Dm`~c/K+Ƈgl`šR~q'["'gv8&(T80_/,mx'!cgkYQ^X:rk C sP"l>_Pbf@{ɱ=tf3#I˚sLD" _LVYɄ{ G~,Y / W팟Fv9Xcx =bqЛP _^ Y Hg|Wϯk%9T_ }@80KMx "G NB=8`/^: 3ݱ2/Nޑw.^uIpE"#k=I@ɚE&ÀC(s&POG2_° E65XL7 M ĉ'̺YXp hPNtz\浐D|+8m-!'Yl**1ftіfw߿x!A C%,B?l:Odemc98 e'֦K;(tVc>+9%sh尩RC\Oeh ;|&YS[Zv䠳;ݦsQ݄ԈVSJ3V 홒nXO C1pR㚗`7I ڥ M ZWvxR/.wU>'&#1B3 ÉE#AX@0M5b[fFJsҿWޗ5.#'TKm1+S 63膲|G6'ѻAh6cc&;Q 59~~JYSB+%;P>Jn;ki*BJ u(ݎ%9Qi\eRqWA ?Cl4E5/VYYa-D̉Ȍu/$AYFSJCU @&lڔ W*au\v@g24RLFp^x%ҀJeGP9!u;awͨp/(>內/LN09+)a|mpߤ&RM&}VujI{ ̖f8ť ķ.ĸM#LtJ:Ձk=>u|)$v:DžJwMPj)L6#!_DeOyb'@ԙ{:ΚH։+Oms3qNAdz!esųҹ5' |Z4gi~6y(˖㋅/grlztzaKy%zHoe5cF*-]:,68oQSڦ @el9QQmP2JI篭kV9b1w%YrIziasvKx2(Ws]ueВ>RU2PiU tDO68Pv>sִ[h)L,tRVŐ3t:aQ񮺋]ld\0^S6mV9b5k>:ށ3ՔY & ˯M7<^BN>tˆw9I/dhYV4\-v,UqOtTnm;IF^MKHȓ Z$]\䮶9TBV d jhA*qXDZfM*KgeMbaÖvqPL%1tvgxcLO}b-\zS :[;R8ɲ#-kKu@!H(eb&F=mqwQffV&om01Kb- t@!2R 8 T&Vۥf>jmyl\i:T''B8n*Z-EGZJl.~\0;/d"n->|oLƃϜqaqY2lL/g˷6XJqsVN@mKyJGo>5]8l< rj'sb9nbN-g6VN ǻKY|*)cNA"^XXb Ɯ&΂N YŌ&k@F1ttܡuFͱ0.hrNE=@rrdnVᶁR!Yt&GFB]ݴ{Yv(9ۍfpsx÷mT}xg :VȻj-%V‡$Lx\t Ԃ`_q& [\}q|./W8nDZg(+ߗeXV2Ol|u Wtߑ&ZQ ϓmm.tyأ%w z0?:٧5meƚ)c o~ DC|fl_{)=lJ?p=9uS4ByiLY+$3@CDb%҆?J(8ζ#Kӵ.$ЀJJͮ?s.+( ߨ]K6J+7[M=)'qp`G 9{ xI+ 3tuxWbVzaO&wNA" e,%(MAi97$zvP^u|3pƀePl8) 2Ol)*9LPFP=\hw=Ҏ⌜i|%vH?:$`s6ZdGUK\Pס86LiZJzTo*ͺ tq eN+eH?s%"]ks=4Ż77ֺqy@ܸ7i|z5!xʬ7 P|N ֲ+fől'ԮC*C.㤍CR8UVbu|p)t+ (hdmFg 8'zb{fk%<|Œ&_7fc?BIt 5}-ƙe!ĔT%(MZhDk IV=ITG[]gW Ű*3J)+_Dք9V)ˁ㙩)Jny渒kb앜j;;wp|9.aW;>ukvU|P _ fS-=v0ϰ(nk7lsS(2Xo66T4uh˾?ogv{Vep~џUϔp$O]F n-6ZV$Ig+,9Ȓci;6jPr%WibIuki}Ģc:YŴ9A][U؄MΖpŁs3FtYJkA=6GIzzLqi:; ӝ̫ȇ8(3\f0=kkuO]80bmtfOmH4W G_?\(u\"WOu<$E9_ݬX>9IW~Q'tM4VoR]M;9#f~'>02 N&Zx +Kl@r%`ă YD2MY5Xo^y鰍$wg*as/r;@gS3=yBE(+d *J&uto@8-ghbIAcDo\Z)4_YBk,BC=V~-pt#f-M/\H#DA$&Z Ejv)/=kfkhf}pI/FhFkem/9͊i!d>!2a~C_y4}a%@_RYț.6kbvw2FnɲB^&ȸܕ~wm)q}wV Ds8N;pf#ހRæ?ںilbWLaPe\t xM-68(֠Rp`*WN'qS7fB jPTN`$~ə 0+m4ڐ]{/u| g+@|$fS(VzZI⌝g0~vH=C?MCskͩ+&vY➮9ٌsnQ&uޮJ'=)|l ,S7LZM%/1BY$&+mWjqfb;Su5,xwΔAe.CUDs.fsFY*R- b8%tyOJik:40\7YY*IQOڌ x: 4Ck٧`xGի3*%'i%ݬf21QYF`|tdm7zw7KƇbQ"!uTTϚf;R0}=:հnѦDE{s'pEf6ZB$&xwcf`#+gTaǙPR/JVKN?QZi@/z_̙S-4xND@!Š2( 3җN.רTMal ^]Ήh|/dn[jbZatٱM;$s:%ZGp$EWeh.:uVRWl^]sY6VZ+iZ6Ei(JMqHKH,i>\ɭjNj/tk }Udo1\ʯ]>M/cFxlղ/;1O{`Z+MYdB1bJx ?IG_^W[I~n֝ sMc@.Lso,`.$u7oȚ? V4H91,zdŊ%03b& Q2mtj5aS)xY ҡFA,B9S,v$5X4m%}=(o.X-ug5[?Yzb ;cv7+2E!ϛb!ױb56v*ܰ?A5Q >yփDU(('$Sr>On:[ B澷:6p-xK:x䭅#_HTFz=4R)+"#Rbŝ'b mMxc16;z9{aذdM0EOdR}i/~9:KrB^(J^{v6EɑXR,Cz9L wnsdYPu$Tک5hڬ!$W*Ԕԟx9&uGE#.ܳg2gvסriJrRmB`e-7Ih3nPK6c9BKr8!S o;Xzy@EHs1@ {NY%||3,qYœlDX 򜵫P6{61g4E?/_!ۻVȁU!@y̴SH`Y 2<'?b U瑽`@U'g)h}F=gm-E:v,dEXsV*PIEA}ZŧUy+O[aX){R{?Vn.u%jr/.P? 'kz"*bq?籑CG/fOGcR4> Gq~qH8sώX1k Zyz v^Q~z2㌜@وv T< (q(gc\j˫Q 4V9M<))G(1g"mSƤCP7kd\7ef8CZN,d`m\^#&oKrS;oSX}ޙ96<ОrM>>/v֨ASRq0eٹFindckE`bc|7tSkEYbOIO&W<~.X.8<-UFM|O؄YL.Kb-o [0cH*hfikc~P=oؗEq\dZH,"cH|fU`wС􅠑 ,_tG :*g}>q:U#fP /o4;Ud&CE@1w =Fz(6hX.l.R%zs΀rNΌ0! nM- ?[IMWb/kJObzH]sBuv+&`M,FR۶e+Α;sX$-t a/4uHave vְYw acdZv`.ob%R³Gux(bVncr/>M7)Q{hQ&S 0d4OJ}al)[ 1tR^13~f gv|bxQCn%jߚyIR2 aT@[*ܧQJ+r!\%L1-U<֬E#d`˵4}.ӿW{dӅ[2p$evs9A~9 ,^XSӡBa;?fsΖ"1MnHYuogi-Do:uҢAZ Y> IpMSupdAsamcZ$ T)Z'2ղ68s3f)RWJ5?͗)kP:d:0yJ1wq]X!FyyCeL2~l409rݠwAfh9ϙ:|@u/쩭xZ>֝E Ik/cKIjG5~3{ _,LC/+Qm{{11^ h!y@g`;:fw/Yi&M)/k`Mo3? VK\{_ׯWvi9ww qfyX+EǑp[= 62o@^%65qsto_t\})6ڠ3Z'kO5 *ԪY.6Ov}qN%D:Y(sF)CѧZk:+$~K昕59X8}8 =m#vylB7I*)E]8#-eہ|.2rw&nS@xΪybNp"TH=g\}Ϲh>gC2dݚb;D8<͍kRj[s"QnCa!U҅rp*.`mcU,v1L~Nv|8!'kk"1 HR8&ɵ OY1c?Ƭr/ƥj" ߼$Hٶ({r*.yo|IP%=(jՉةqd%@a+LZ)eI7|9?pH*/"'NHB%xwTGT^߶LKc9-@523ÆMS|\!bbCOC1ZQMUGJ?uB['HI}Ԁ_v9\|I}LP=.YrScW?PPxyi!3}`tE<;FxR7( 7. fe "½ Uf rN\m /aEݬ ao[)P)ā=HW=M?S[bjPoIFJp?dNyKh) G9M3m."!Ң&]n1+++tX|FRbLRKf%U툸]dVe>:fVOU;71P(jMB-B/_CDޝs޵:_O-֋~s?ap=2Vp8Z*]|čbCE\}YM1+m:pvԛ=7Ƅ"3@A,v\̳2eMDR`e:ar4ԾX6aNo‡3Z8@T8Wy^ƪtZ\lf責B"4﷝<)Ir|^nOa5n6~I {E:΁Λ*j &5F#wP}[,}ui$c'*8n9XCM¸t N*&>MޠAZF]x_TZ|p6wE1rrYiE.4pϤ|4 Inxg埂ٞ,LJQt[j GZ ֱuZJ:h>TfEuZ {jmjc¼iiՑs:]gcBj +7nDګʸPxh,-=C#eebATH.z܅LU>π6 vk$p,NF:-yGg+70Tsg VC4.ج͗&?k2@w33.=u)==+FA:j]̜u: kS1(bƽR;м)tW(w3߰8Y#LC{9_|m\0~)X޴*6̟'~.h,=z%8 IyG#n61ǖ7<7`4q3͈cW}&3,0!B(7ϜFQC0 XAɈiG*@B;7b&NvQe1VRQ8p汵]`N 2b/ ѱ:iXSv46gy 6ͪ[YTu(^$٬CmO2  ig}E3g:RIJ4 n,-ZY㧜da0i1~nv,!x$wkwvnK-k{ѮJ %a+8>K{Ec%S9!de]Y4oȧ\-U3>S> +-:z^0ZwndcOݧ}wyϙ_=͏-ʷXs9{M9׉DÆtbi9@zsN} x%Nu| to /t$i];0lCjVi8횺K:‚uFf=wsqMgfGZg@3vHlSX:3k*sj+/sHѝd,@ OOL.ۂ5I+?9M+SLBhzz7V'/?K9&x yc\dBZ3X-}TN>|$ᐛ:r_N%C/X->y__4SwerBs|Tc#o]ނJ,]m fJy2SWw)KK*AW/$x8 xyrEA`ܓ #oQzww?4\9!-;, ,TromРA'Ca~t_T~[i'a*Me04y3cze\%{>|"#θ.Xo1,o2YT\(8m?tl'dKæUf(w Ӂ2S; CQ7 6 C@GK<ǏUV{? !]ƾx+ä:z9mB\^ n'c{x2t^(S3Y="O_W/N-}@o4rucRfZrm:wPB/s0@X9Jo\y>:p<:Ձ>{kJ,8U?~`Gi1 vCq G@Jx%#,Z"?}}=GS:cuE0vĻ`)1j+\gȯjaQ״hhlؚKcNt (5UϴQn:VQ/_٪msF^דfg]>qm98dԱQCb}e=|J̓2G<۷iS=oֆ$}NpX+8lH~kVT=09>5g2T xOτr]piCKYi9R[b)9Rxrzf, "3mƔe5JgFPٙ=ti2:j#pyMM,7@p 55Pe:#8YW@v2꨿fأiį4 X-͆i|RSHBP̉uROޅ>՛=盱Υj&Cu>A? Iѕ]ņdƋ٫hj/^Ō-' W$`H% ã(oY"kudzK9#,,K/ N8 pOV6[7U*E:d/Lmk5Χo{9pj:Mכ &Iw wi0͒G9_vԆ zې4n`BBf#7>nzd6:6+Jl3XXE/mok`uU_(Go{ {6%̜؍,_GC'2zzn%7H5e3%,S;)u2{ qrk'dθg0zLGᲦ87'979?K$W|;˒!;9(>Kfe Q81m^MjC7tQS+${lX(ޙ%= y, ++FMMoD*z bФQ(?7?j>F$Z eF;DaYq%XuG>O@hXvk;% [~A/U0q8IZpϟv^yzA %ľȉ[:ktЅn#ߧ+]uq*L0k@v5k)DG1p~Gd@^"i=kD|:7Bnun#\4weO()NL fF4֬+7/0I}+2Kmj<9_ 0I`kXeEzCƺcTTjg>~:gu#2C*ONjAOTs\7[ vy|:)+-닷֍T (ç%&󐀜 YG`xW7XǒYL̎I05Btz NNu:/i8%m`O (,:0Uw8:f΢9fqKvej : DՌ8POVdVff(эkb%1}9J;MG-/rE \LieNXz$[>xěqeB,*j80@{ kWݺK.yldQꌚvE(2-ԣ jqN8,_*iΞ؉yz ȴ?2tuݹ'nG+͊X(ӮX> rFŬO4-0I`|MEyAjqѓn-jmI_mdՈTuϟ⼐R Ƥ/R-uEYSU59747%@I׮ʂDqN7\^ZC]sS>pmk!gR̶lyΊ..475•i8g'gkw}`§  ұW_f햎#p7u+0C{1+:Hd_SPz6˞ⴹ yNy%S=7b)CDbyez Vs 5dQϢuX BX{ʫQq74r AwnXBXa d=ofOvJ޸)M?ʰ*fkRutB w,>Y2M^+\L-`tKe8)i=p [zfg+soYw\| d̘%r̮5;#k\!̪=@poo1Vc|AkuPOEK.NLWw;;Em!ח \ 0:}5rv<oi'h.+J>t=99ziI_8{v(g| H헨ٳ"t!K@*lR H( i 5D_,@rc{~LeR[M9̬C9v(T_nv 'FE-Hۍbmm}ϋ'8 yk_X01 H:x:afXxz][ BMAH(:k7-7n9_(߼Aɀ|M]lI#Xd@ *c;Yja2wy~cqXIj6HXPr- %Ȃ#):-;8_+/[QXCyGV;Gm Lt3ּ|9k3%V/XNfiCşðy՟6b8Y` !nRwQpxfh=dvxZ= Oqj`#ZmJyC_:衒0突_&WgN,/Bd?c@tXrHo>~]6$ 3Ə{ &7D^L4B45t:AOњx r3M&XGA`XM!kX< 2"Rҁ ЬCLJG%V]1mc!(hLIG+F gLz¢p+&)Syp`s\$JҖ7'|L# Έ~{GC{^3 ş 87 b+_ ʄ';Mm A^irkL^CCvl-N9+YD-wT~?2帴Gl(MОA2C~y.x=XmLcV]ޅB<-7l:1ӵʏyd)0E"nbq*jbtHvn831nл [Z>M7!3P󾊑1|t1"u {ɢEO=;8yH3#5Sg&VH熊pgTӢfTE+!XyH!$ESa<cbv*{hx9qeTݼi:f>-kuD~5ky._&Xr'ՙga ![=ZG d:{K;'VP7'}C:yLCJYބG,nG{pu;QrE']'X8:yN#yoxk.3^'ꐩ=W۴%3p7ۑ5 9e[} ĽzX!󜁳/=P.+k56 .ϕb3A8V/ 2 z3$,[Я2c{}FVoR$ea\}YϙL(B7ɹ0e=…ʨ_QsPaߵ3+\LόZM&rD\f[ҵV'9ba֒^Y.*D9J}b_Ps us|,͎9 9YPZr[o<[4RdĉuDmg(}׋1sܴ~7.dWS}Y9%qycՍ :qy @9,Q.Ϋ``{-GɘoH'Z"I MX)y #`ۙʼ|R?$"aVj,ZMkM SM Ch]Bl?Rwo0D:b X9H:Wty] ;j4TY\H`z%(~]ÿ tl.YzCBkzn0:\Yg~wz@[ѓgf~2ys ָy;`CW|Fa6DJTHͧ/"9۫ O+5YJA,}KЃ3.=]1.wڎ{OֺPVusѴ%pr;GCž5KςGw>UQO@Q|ыMrvpZywD5Q!~86+) '^#Vp~^0wsLʛ ٢D7q 7^ޕH/CX= tTkpBs;>_t99DqCJcƒHvtAƷr4{/ K%Julo.3AJJ҃~_ eJi?RRvsRcз7bL:$e@bNkyQD,_h[_MsyO"עIXCo&rOe}4#ljamEHX!Q,O- g͑<$EҩbUiXu:wzXQ3sf(6I/n{̬Y]|oC)lSMg[߼>s/~5ȥ{%5 uPT AЫݜݥss_lɯU>2 s?JR)*eQaz˶p.[3%;)q́]D;4ݼYɍXNΖ^ _HM.a;sF䥽 z,[xuxu' Ngn'(+Iʳq> )>I|bl2f0dsub;ʷ_^{$EuzT [=m<wZoZiw"F:k#RNݺ6xuc1kT -V`[>>S X:\lafw6IkFU{j@0(-W0JmDk8lXoP‹O^ܛc x.A_7*f˳ /SцZڤęMD 5^)m޵afZSJzX9 !=c#2NCNШiЍL 0q^H,ڽFoi0\|n`F>T-{.~':WAu8\*oRRf»0N^C):+ ѳc2{pXAwf%*Yp<m>܁~7Wf64#>NZNbW^CI&$+]8%Tϰ?2.>\1lCB|lUбRf!hm@'t(ʽL؇2agᓀ@/fƲ ki+_yJٵy 9gn aNʅ\ysA8a^ѯ$Gg.Fа; TsV:-H 뽽j|GĮ6FwPkgSƩmwMuL"d lYIᰁc$@)U0:,fSeq^#.Έ}|AǒʠhUkԙkVGN{,O}QyyTDz@#ߥ]uuጢmEAɾ%UbXz` 7Wqs>[ܧo4% YN@]) 7:y9g :E[m9CNٹkgz:5&v0fe%se>m+ l2{b{O?0>O<&pk X '@]jV G@[c<׉mH GS y\2Ԙ2Hڑ> 7iq|2=SGω+ӫz`28%rLw)Ya4v ғ XCcPn퀣܎ɴގ1fG {+e+U9="}X.XwnI73٤n:uVqdHu&RfkN)}s:]6^<]G,\"JH7 O5.99_yH< )1gJY Dߨf:;z4w6Ӑ 1Q;nakD 1lq% j҇U.fgghUx &N)JAydcpFas)8²U2-].@mHiXmlHc@d+_ S [ 0\&ST?+vq])@:&=t0sRLgבaS1ZN;+֞yThf{C"D e$toX#o=m: tiN=7.BeqK.+V+99O WҷA;_ȋ&Dv/>`p~|*?]h+x ^r;[ֻXE=ž}c͛ɩOݱ`og9?Є“ WpFХmOt* tH"Rs^mu ;fiRٽ`YGq7qDGK :el݋WeXPzR\b:sؙDP9g'yeUC̐+zI¯2`/bUJ7)ڰyмXP8ˈ~ZѪ$!&žGe`er;6+Oחi+G N yXe"^6sPg-i%濰lu*e.k f(40eP m:7HHa,\5,nӔ=UB3?K3 ^׶moT !0mv#y7Lh v-V7V]>+( fv’ 3xj|RRLJr1g{tNzF>)aJ6+cכBj;"w<xH QVS g l'ľ9Ng%(F1|r@T4T5D8¡Y㱲dU5q箿ٳ zk< zpKtfFfVJ?])An5뎎g۩]L`E&)^w $4?Y'*Vt_Gn!(TƳiKȇOuu n/?]nOzf`<Afм|9/\-ᇹ81nyܻO )"ڴZGxb`Fv7* R}`+Qɔx8*@Rո?']O@3iJF .KAθrgn {..~mm*cv10Ѣ&`:zĄdT+Nk;(zfwZSkp/~&kDC_k#DX׎15ػ]HN0,fU/*P BVmn}.ϑe-lYKPk/:PLę#jPYhg7Y9s&M*y&(h-eUU'?s`}9>f}Pv`1c 3++$U;[^z}5b8̑6|( ZFU+thB?SPلBQQz'SOK MWSg`67YdC}7UaZJ=,=|۹D1ΏѧMۋn6.>LeP^(f8a &6hi}Z[Wݯ{\lC:/cީ7}c6o #_ai?FJhRڼjh'w5=8C{pXAORDה17E2L \q xyLO|us xzs ?f>c0U]"'r\\[> w$zsl^`i 2 jTbQS@{*մ# 7^`'{f>?\m@^7toLkǁfv^-,a^~8|%#wK7N2#%KP(DJ-+U@+ z`± ȏ y |#aZ>NHÇQZU""-ai*jĄ >4y܇^#a5r_].4568/W Rp6 ,H AxC>˛Uo q /3a?%>jMraU!$<>Vgx\qmc.3۷:J@]̚WTua] eJw:ᴟ5*` 0aW0iF^,&1u5/7 kK#]#HJ#=mD] >y9`̈U]f,gCt+ޅx5W a`: 0LBtYnF*9#U*℄C'\yYCʬoH$Q~@x4lJ"a'MJ4!UD@1 |K {+,p@*c&u' ve@Aލ1bM 7Ӓ"w6f0;fs jg\I.Fc{rdBtܠ 0{_P pnXzAԅQ,"CP蠋pp 6ᔆ[ѿt#`du0P"xq0;"(_dfo pO#VA@_I-o"Y'/)JEfʰN;W  H/P%,Ź$28 +wga#u 묃P1;W;HoCG HGZ\^d英LkX9N<77'! ABl9B !+f$Tɻq+~ >r}P@9.'}bUd5Vg7dm0,<`Y:fy6R*=X\vzxjڱHEšwҮ^jB516B\㝌£RpRu5,|)Fd+lD]mc2@`c(g)|LAIXl*VX+xδJU5ri\2zrq>X$KHnS(c`"::i~~}49T/[-UMjs^mt iji ykGֈ7Xj3S&tXfYLLk`A9 i$%xT'P-XZ7SC~¹40y?sZ25f}>6=Yϥ$. RJQP; Tipق<Y٭D9Jk;\lϓʄK6Tq[h2J K Pte2tұS‡i |aJ~#oVPWnl.8vTq+ Yof/8ک،]"*یZ4B/<WigW. 9\AA)'Q7blblCA'Ҡ:.{tQ&<)P1b8xpsXYX댤jҝvu -5Wi-R%sߞW D c;<=Kl95mP1(4q.Q6YPqL~fƟx3/R@jя#+Ѝ\ӱ U$r*ߓv|dNĊMTW*d']nVÕ!pt @L#p Vyӕ05k'au EOrt*k78ŊL'ڃUV|&.:ƱE78?,/dAՉh"HcJ7U(oW<&^1Who: cu3dxŸ+Ϋ6\$to3+`ոD/k]TII $+ŷh;Â6:AqIXBrew#{ H&c(xb٘' ޡvL+Xmև9K2w<7Q ;)R2urysbwVHp͆8]>E[܁0`@Jwck&lw6Mbw诤y&>@$&0(8O$1[];< 8ςm;utaYIG8+[nx a^4?]'MSWmU MВ5#BT=FVOGܦvqL^(_& l0dZ[e:O}uA;eN F왲}C}ǰ:^]ϭ,=TL/QS*y=.}utqrN仾M^١&paųlwU?!2Y(xaH^fKnC3(l@zuKIGoo=~K< Q8O{pf:^)Oih{xYͿzZe/S^DEА-íV}Ц?Maȃb7?/!taG&0!Kذ\'HV2`yЁyؗ"{[j_Sd TP?QXٍ[rI23C>O@tb Q K|FM=5htChMXGGir_ WNCc7: ?AqU\l) 8sGS-IHvuӟ%=1$@t)Yëçqw o+ґ7EPsl=(UKᘁ`bC%P6Co'}{oY͐z skL :XFM\?a% Q >ZYd ')wuz@_ʏ?Jˇ~Ʒ*ISB燆oC"YttVCn@\§_߱rn$>- !dZP n>E:џ0r~Ń\aa;ֱdPR-p_!6ĈȵAh4xcZ"Or[+ wfC&b̈#xjKz3Ǹ~Gߪ7 r|O_"@Ev-ᇦU*e}c^PTByx%=8c/ AX$B MY' U $SC?. 6<^n/^ 0Di{y L7)q[S;O`)9/O.k'*oᨵ`ĬE-I5al;ͷP[ ڠm&PeX9q~c0U]ˢ6psPl6~A!Q˾oyctŪg,R9-"M|Y13%G# {S}o!>w͍c͆80ba"2cG<үT oyQSgqr.2?CNdMl}2l·,<浝8@û;6ltƽB:t$$ۄ^P+ e |j_9ϙM-|vc-m0pm\}Zqk.Һv :%8Xr+`n3nݨX$/LɲFL2QUWu idm/}YZSkW#qKV e|]& jwT e5Оz3׾iU9~ʲa.oyld(18Z{_CTb>LK0BU0+ Om  SXтYId{, 5Yh%|:z^שRe(PsG/khHzBg`A?fqmѕ⧣؏uJ*:m {:GxLϴZ6ݐNSj+An8bS?e9\ 'c.$Y'kFTިP|ۤ٫Y$lj{5[g1SK(Ŭ2c!ˋS*=t]m.K|iˏn3_RDNDž95 i%<<,?4]!x=tRr8bZW!V|J+rި}-rh:OL2)BVߤ,c<` x ѽ##ryU,s*:ET4Ii1Ix>RV1a:KDRXNmAiBXrKblL%1ԊBBӳ2cR#l$&9f=7r=酅&CcB>iBi}BVYυ{!-yPnf<ǒ'AޜbZK@bZ6xYPۯ?CJs>g',Rсѭ}>htx)8GQsM-a_rrfje!rY.@5_I$)F }.yiuec;!:EX_$!P\@<S 6T4R.W(딀ہs@r\"0vސ<$ :vms̊mRPcvډM!R. ~]]wHŻs[}';,8d9Nxr3y?O?kmI,,s3-DND#l)+3_:ٿ!| h\*uB 6g4FO :tec iC0W; [$ڍ.kL^f?yM8c3m}O9ok/Q/P5k˸o$=SϙE(4=ki׫[9 9y?::h>O vd+X'xL?j}HYjez#"G+ ȑLȈMa*p"Ag}&JF=fnp(!Xi?l֪ EK+|6*H|NTS M{ka h7u0L)5 e 65SK`^9-ܝY^?M2ѸJToƱ]Xhf)ȫ힥Y|Xm M'(j3)Pm|lΠd&t6uDl1xϼ%yމf%(D 䜹,ͷ) V#H @-'~Vqsbg/Xb1P+҅l6lE_4>䥿 )v*(fyPhA r$x\903)O}ΛԳm0#4Z\ Bf BWv;YGNQ0̓44/]m6j_aiVʼj݅F<ԦaryV+Rk (uD"hK@J̉P -} $V1TisyPRi)ҧb~j82@on~N@(B->2'(@ni@*,n :s],7URdxf3"' + /;匌Hu0 Q u]ErfUL"qw`>J^K_76 =YCMy JAZiB`V @VbzjL}AE#y.-h&-hnqӘYD%`nvvi ̪O[ѽ^vfΪJ\70(A~‹tb囆Oy$fkw,og4P8ڥY_.gNA{rLB:?΂(RSW0U%n6?b5\7se8:51q8!u S鈵p"_L(ii$H h2׳W^ (B/'&]W{ th.ӣA L=D@407[Y 7[J"rUrnY% $s!ej}@aw@4nX8^"W^QxavZ@I8Ȁ5Һj HZ:9oPl%"/g]Еѭ\dȎ=՗eix*`vLcvldc%,K @ƍ3Ȓrdgwγ_tI +ZgZʑ2 {b7T$Zj3nr>Gag+*}aDngY5H=Z1g>eS&=o w0.(wg쀑ϭo5/Ȯu֨5qe*%JҒlYŮy(P8NiP@9#h~+`pO@фn Z3[EF,A \H%֬>3@: A0*BsVRԝ̎-ҿٛ~?)dE0H_,tCp]ȴ$nB nHHc/Ǻq`XYjI|-bPLԊwI Z!@u s%$iWn!hIK $ֶF=Ro eRvҦCs=߿뤝KM'7{lҖ]2X}:Z|EFWx1t:k:WHyq qKU}U=V8\ITyegI9?> 68b6 (o &,)3p?GI|.Rw>4D#*pq^vz:? zPs,tP^sm*#6>7=ґ=zcr샭"/~C"@_Cnz8}.?L؀Ia>%>عdHOl2WR'o9xrsZ!{~wM7K*Xbam|=MN"Y.)RU  gmi$%J[$_eu-(׋ ݃J4DYR.>DyN}mitM90_+%iI280hom*=M^+ם$GZnU#s0Q\vg ޷~ >cmu܅ lW ө;d歎[uē,]-%5/ܲi+ lB|!u 5FoabF} 3g^PZy>p̝|߃L|},tfc4o m}X61&}BĘo\8Ir>Q81e)5@n H(Qwl~/+/*(~yA&D:qKQ@@O<]ۢEӁoAyo\VA J eܞm~$e:s?Xaʙ͝=aPU:>,u_w"l ڼNli ۣ~ &ͪ+Io07qa^ U"$nTl)mC#q@:Y*o~ߟ!P;eHȅ/OD: :OPQO*jcu t|UE#;e:MQ_ϲV*SiVFG"Zj7xZf'KIL/a^:i+|p5ϳfבqb ]5;j}#mvt35օyX|d2""T-Y=J8{pxK?/-# Rd kC΃&Wk2oc҂4T3J`f TL7ee2:N1.Q|p{h*8CQNS8g|>oYޮּЍ~C}7cYp,/v##7k5 <5ZL`=Hp̶3ҪŴɮB侹lRNw>CN˯y}&f)jd xG#5=64R=sHJa I![:k+!?m#.&ׯ/jҠb(B~-Ț2JQQ7 |59_zƛ}bAX߬ n,d]%q4%(>Q5 b~2g)_󛎉3{9+G̅qٓce%wdL݋)mֺRmbf ģ]v,Ī1]mʮ+e2^EiQBcC 6`}B";С[&2 _̷Tq]vW~`ݾw;tbڛA JZ:pؗMqYpΫCN  hWh1Mp^+9- \*^tK+s)p_SUC4ոRjsU Yմdfa)UbnbKZ#*t0oWK|\lۡj)lArѨYI x'Iy1زlWה N|bSO:N=A%B5p=pVqFd8U# .T'!l,c싦{$CX*,2Ig#< uBn)1+ǨD ,bQO~]42_ebYzMdEmz  ?̢c -cjͮ'bӃ,gLOTj_2E@f- ~F0;68KksM#\˙%EZyKnv_ Gnnv#~c` !tꄱ-}rݓj\i+A&g'&HЫ7e: JS_7rwq&vg4:Wj6q+[U&'RAqaФt7A"`9I"6rٕ͒/S|p6 qUah;^v@73@25PN.ɌvLhŏ<]X+dXZZT +/ C4@ʍ!uYel:MC-֏S="JR!YS n2+"8ru|XR–ʻzQ"+|~d^)PZXԐȣo`&'Xm>*rLJNHRka޶+Sؼ2< : 6g+ϣM&ZBQzVUxr^+j5@ۜ m)&SbO;V}%gwKCHs/_u}N'7 :I2QnBYP @(CX] ;pW$ YI.+CϦ3l0kٰ:9|=*JuyyzY$2\6JC]t3qiOcnBt; J|G(N ؃cjI^:k^sr3'7m2c'Yh ?27'mI|yolj'aVT%8FsW>˕8-Bu. ӼiSYVs5UkFM0/0]8{QlEjm:Vk'[<3@yABUvu / B^Ij0D 8lQ#'6JӆZ ,iF}*op~vky<n䵬Z0=;A&H'xDbʺ\+ ޕ|\{WMӿ]%޻ Ds/U3`(ċnZ|;P5t(Mΐû֖d7 kQ&Rؘ1A@<~`Aea!YT]a[^XP[3>݈wnd9޴kymg}htL:'<$8P}#\v@ 尗jiPzh@?\/-NU #Zm-9PCЮUh|~T{V#+"Z{cSǖ_tlIeM oXp&p0Ά:q$3dJfWWIEX-cd=|e!Q̗?Ëōkmx|5K)-a$]"!"ӋK BΧ&`šoGgTƚ#> 3/a )m KMrz!%3Ow`igH|^5f}VO<~0d' wKkIƗ~8<=8T =9b6-6 ggR=*WE=*y* _A36JʇNOߵ5%fN<gϝ͜)~o b}))c)̙utj<`04I@ztb .B `^@խyJ|wMxi 'R'"%Lo-nֻ^Q^ <è6!,%KZN{ΠNdhVʼcti{AX)96 bh[j2dwdA |Ԭgլh6*K~D,+xO֚dpRh7왉gJ O5Sa3}t$ValVX'Lյv=|-g"Tb1Pc`3UZ^(B1%%hJlr#;@NZʦ-]4/،dPP%! >ey@VB-.Ne=hJG)qڧ5欑bRΝQNY;} 7+d^9u()m@xsoҵ:qU.f]n&ma + uy;pt]u1޾9zM,' 敇H2g-yx_ƽ#*MV&Ԛ4zKMF?ԝO͜bnR~:ߨaۙZgX LWWoP bTAQMqioԡ?Ƃ@y i.U]c݅:9_G+{"̜*#m ~n>p#{EYHGk]9z!V ].>h~f0Xk6F"DOUw$^؁ko]QBErd+22ɫ{?8@/){qB́RH}h$Q_G  _3Ah;+Y:iFޜOKkS!/.D!}$Aٿcuj5 It_(5/+v?Kʴ&f Hps/E84dQՕ;nIC(Ay{X|A4(׷A8l uٙm?g6؆xb|xw,ODw O!gT3R+ t,+)sIu~PӚ-~GH J_GEiƝUdr۵Xz6쏴蜜3լ:@cqZs%C1%2a[yf=h\$)݅iد>Q֥*ߖ܀gϴܰ iGnAC{"o|iI!I쮮]o]D!HE˺3=+E! # ("MwBlyZGf8=YhGV2\l+=Q+B˽Sdt]FW%X ڢIz*|A>CЎ;[im1fbķN^Ձ% )*1N񘝑6k{Bh~,EE<=UGuO!a~~b(MeF@'JuuX7KccL qMk:R 5P)u;養tsӭJt>"ccR4䧈cX^Gek7]1ej]YJެ O"H*2 ̊aJ]^^G7F+1iC1Ci R@|\j0/AъD0ΣƜFSòXm K/T FHM)$ y˘p<dX{ɤOu s!~ǰJ);W*۫zSw8>:6MnXojQђUaL Up/nZɼ\6Bi{KX ز9QUDy"El8{&i?-)_ȫ3k}\dR=>{;V.[Vеv;+PX.K uX6P"+%iR!$<3r̵& O2-wk8_INOT"_:/U$f It~䝰VęSM~ĪCVsp|l/6:Ytًk!diu\J G?#iI4 `}Bd|jw0q>(ϡ0vh &PvTM5oO\c툒d@'֨qGY{!qA*yC\#]zŎ=tdfm3csOyo{\Yk*U_ 87\k6g/UX V"u2 v{ e&N=cDZXᔯS#u&3r =`}sUj0[IȫIItl-Dvq6쑄bsj˫FVF͆jcn# #,UBuZ\PɛS cyAvLV3^I;ruS HY:g, ](0*4ikRlZ@9ob68U d VQK} PH#KK9(xb-;X\=N' ޒRۍڎꑌ:R9$p6Udb֬I9][z+u*EE`%{cJQ3†*rɫJn4V_\ڿ]Dͻ*~y?ru 9bT70W'Pft<ۢl$aKWO]l9Fb1\@%pD sɰǐ 3K\RHVuTJE3_ًmi`5W\+)u թ,ۯ{9Ӌ[1zA3jB^}(mE?}X&bd<ȹo n O[1/$MЩ4CYNՎce=hB @3Ǽ]a굾?>& ^7o׹x5Z|Nr0ݯ)guaժ,Sq4 V=fGr%oiJI]Ai9okf2{Ԗ(5J(o\bºcfJ;r$=Jq%-,nYq[Vp*Uk&PPۅmt6Cø iL<̝`e^!($ Om^yŜqȥd@"#59_YF&Ҭ:F'hY'"Sr}>m}J3ǴQ=n:QI'dpb+W*fE"jO^(ɪsjˊd I46OM ҨSuwPmO~q˕`.h(Ug8Z\YR,r :Y1Yﶆqc؎llx}7ۜߥOná%[+_+/%Hhԗ7^XxXx9* %C!@h kI܉^fjyH{q"YVLEkfB}]9A1op[L^K/OS'ZQһ(WݺYZw|< ?JD0Y2X{vHpE NaZ%e=4_ӄ>Y\O5ZD:&̌g Κ1w$VOrΏӹW|NOSV֣MVVpU,ҸU;XMG4x5U!6#_twlK bxS^ "vzMHE+qf+qk?o_,L }4@4/L,.EǦ11L_4(x(?x(&I#F/>CvxugjOu_H)H*e;WE#V-O W#֝/]8)y=[U@ K +Obo<(VkDj +vv잿a|ޗXR||aw&tzĎ}O+_ZU%SnN:3".|<Ҹz 1KE;k?lPg>šy D_<"!^t, Ei5]Czn}aVkOꐑH4%ɪa +a73f&c厴Bo gMC/5*eQ)cz4W0ZkfGڽ8}k}Vk:quXl͟q2g=qVqd{[]M8: ˨0W|W=BjY*D ٩Y|jӉ R[U3T1EWabSΉ+͒"!0-gq1iBv4x.,`WiU9(V=g<9pCoqMdRնNœozoҎ4\H(Itdr ts"f3BG{s}tdyb]S]Y(K6^}٤xHϚ&Nqw-܉ !P>0EoYyy )*-,~FV)έ= H这Ù;*vr^;Oʤo ]w4kה/jMV0>j Cǫ'ʔ"-H6 }у)Fn.4M9}&޷ڻr-Ptux)}tsx{-08m:IX_gq`a,OpB ]?!^#C&߲r"' ?XUNFDB8( )VmFOB>8=a:s13z<`}Wv̪Uw4 kn^ced }aMy@m\ȂL5Twefʄ((;r}]j"^Rw~"'mL@#T L?A;k15*Ss˝H$wP2Q.\~^i"vqӝ-]U3mVvl8%ҝ~]cVl\2ԫGt7_\f?sUW[M HQN'O5Ϋ٨\\qAA^b"y̼)w1@& A!ilNH)vQ)39B*o gE5NEWn+֌>ڳ8ZNH)iY6ܬNUQ^أ,Y2H_#OUQ荦Ux 쩦*5Ur.QA/t/wJͣdaȫo$=hyx|8P*O!xkœƕ|U.PMF|.uG.V͢#73ᆓ9qUL;!vmZ2ҡ<1Ι@,vxݰ}rP߁:}lv wg-o An8"/|^lbk;-;?h+ydQTU歎Eԩ 6c㗭 )/@1>ܦb$"g$ufU5ry?3oLJ MXYT[/$x(/-L6#`&PЭ{EfxnW.JG k#ӭT坖aV$8,Uܡr]zAZPG-DeB/TM#ݵH*Rs>(d|&I.aЙ}EOMC:ݑs~q,vrq+d4)[O ZihsE7m  3ǖ\k,J섭$ C 4%~9sHZV8`fIiDi[q>%]kA~Uz7/WH!(}ɦ{ƫ Im$ZAyX=Ws"!*v|D)e̬-[8MەƩq,ӞMפbt:ԑ 3-Pv+`=ATu*6oeNJYz%#,Wd8Bx:e'spvǸ&YQ$#I_dEUl r:JR3mNM֫b&:OR\,j[%rsѥ(K}ͅWvdYI=*V S?'+)7ƾM^)u{mpIVj 'ζ^NYGhv9H:uk#zucm=3.³rdd<z(0WjYXfވ5am2Et!Wĩ_YRrk-t9$HbPj.R8G>{ÑgM^: cM;PNFC>Nf%jH}Gh< 48KnTbd_]iP>AgbDG{az YM 4taJ;36k'*DW*;\-{qIcPLz_^O3nvjvY`5cC 8'DvD)d7쵱:~ fm>-}C`o^(gUB؜ wE[ힾx qu(YY1Kz>pe1deIEY>:Vű_fLcPیlH92;;@V#XC8>rUnHNXb|+g "0h=;+6\R 9[AJ@7Sل2bb6R +c=1}_ {}ǩ;bU(ĨaQI㩩 s`~!nsʭLv5Ij@O޼+JBnX 9֚3-R_(Loeg'Y0=8m2^MDiqPJ;^csDkXԜIWd8o8AXK.__ː=֚,N2&0o#6n 0ȓ?O<`y_4EEy;OT@R5paF  xJ%)_XHk,kk#,VyMK&5I )H)ыz?sxDH q 鬷(Y6O<3K57S|# TlgyÅ*tb6"Tʋw8͙Ms9v/ 9kp&\e&k즶 kgىZM~ղ2 4r.?#R7VV.^s{`( !msX{V&!i}6g]eVnƔY 4mKPrL>ᡑ24srVT@36??R) ۄNSHjـTE,׉IUb/~X謱$5 5g Gx 2zL^Ѱː" KOT84Aq^"3֟b!\C.6+wiJR \x^|Ļר!vƁ ._T@dDB]= Ρf 7jޙ!=-4``?8yyI<|9n|.?$}2ѳ`BVZx-RqDOX3i-lϧWK}hIXn 5D/ CyC:m!vK^Xf*Ri% I kq&sҎXm9O<+dvDZFJ/ȱ irC!Q]5kXz>^ك?זKKKKk=I]Mr$TAg,!λ̬,:5vf5 OA;*j '*~Xľ,rix0,~ ʅv1ǫ b묜T (h%Mmfr^5$ rp`2RΉPt_O,Q(YEL.Ӊ P|tH.iGdK+4u>&ej Ip&`W,D>&]0S/*q?t ; uc$|R[m~ GvP6X'ԝJyfxX<-y+GxbE2[hC}}:d_sʷ"//rٙgR8l <^0.{KopF,8+NV;/|r_[]oY_{RbIKd7[ȅu=E7]+Tꢪ+muŢ=s6oxfegn 8`@VCNmZݜmlc c8qtn e 麾=U-G9z٣7|`w%o"XoZ^S, y{ e,I)V31tR*-A!!pvNV2:J=̱R-L.Js:X>l\Ur@:!m[#wk9'{ '=9&ԙ[; ^OF@]uP K D5XIyZdѵ`^| \2$gGF3:OyдTcf zVgb> 0jl[B16aoH*7]YY{.k~ɯ'NU7XsBXӽwDړ>XaPF7g4aTe&$akRcԬ.Bcڤ.kqĆxݛoeW#5ØᎩKa4ߗ*LiSM!@ ]x}`lZ);j%O)T8#mz4DnqUXo!@=nB$yw:\lBap(M7̦AF8\{>WΐB:rLۙЋ0؎*[TgSIDO(ם ‘(wX%;lbr[yyl[|[?E!a#Y {Yݨsx@FkA5Ա\F+ 8fFYR}stָ5'lA6ٕORVb[Hż_z`}뾝yKDY5O 胳Zn6je1 yH,JJfS\鱮5"v[ך24 u댵ٍO%uY&F,-B )=%վM(^!zVoݣ,CJ6.L y[!;_Z6֎MƆ6OEK4}[(OIđ{lR:AÅc dzد/{Q|".#A q"kbƷUHIظW`o"F"A nYjU?m`ot\QlΚU56]QWJ! zxEt X 1A~ R~Ky<\P?skCKx-(}aG4:"ΧӐ@ȽjX9 K=ӎᜦ[@?,xua6 SW-=\MCRcVNYac1k:WѦnN-TfؽFA8ڽ&1O~dҗJ4s1!H`B6Eiۮ $Bа&}5lU8.y@..&hk dU=iӲצ녿kɊΈѬ*>n +P;,Ö FEuר :D9 C %H;bcdN]Z9*]fsRD,!6+.+r8}/>ܔKE&D\ۍZ2G :yWfjK ^ozNlc{J~/T$#vsDl*L ƢG8+\kphm|~ vB:.2t@g0p`x^A!^k4MWڊ⯈A93* c=CHFal gOgFKI\b.`qB&UU}LVmkΦκCrL8 7*'tQxSFl2kO5ٜ(; ߘ ZL^rZoU8f+D3Tg*K;cM%\*5:(=|Ak9x'H9;7Ӯd2h1?eyeUD$eǻ\uXs}xy26,Gz?$N愘0b+9A#4q72%fiEh`z3xxp2:<}ا}e1*'I>GdTOt"+ү4u~8pnqd5Kd2)VY`1j 捈Ǥ(Oѝ&Dݫ=ʶ95UfAiHD39AMY+M񭇎 Xg l2 U?WVhu .3{^_,*G@"d^ 7HyDe/#rLLh :{l:ݒP1{xSLi3mjX\SdVTyuo6fwyr׃fPiTqըdz9ܨJ/ߧ)imWy!4^0|Q .+Z`rqknvhɀy9bn, ~V:K=GK(;a8UWBfu7;Evо1ФMѽs.R.d4k)۾19ϧ~HFH"V{wN6Klghk?cc" Yk\Z ŔfkbO.9 ,:-$kJzIp/+g)z#_4UfjM%7<9o؁ޱ:x,lS6r >Rl4ϖL @ް6nxLS a3Zwb͏ \#?s?Ȉwجg}:Zq>';a(*7sdsP9o@:So |OÝs2'Ohz`֘ C33X-mŸAl(3 -Han[ո9J$CR|Qg[tyNiI/͞YJSrj.Yu63WŠilcWs<`XX.F\Mzt8m0ʡ a(qO~A_ ?F!Ik]1qCfE%ޔcyfMH| GCQHCb;c$bEk .O9Tu.4 +K8I>N07ʷ@ҺO "Kn@;yӾ{9z|.x-tjV-謍Kt# Ph͇20d.3<㏧)-+.fK44F!i^@~ȝF2 kbVI_}qCقER=&eȶ;ԁv!3g+|v gT@ñ0&1>#8y=%HV}VtP' |~3y,ճx!>+:YN]y5iR5µ0{m&!OWYpg5sߜVO15<뜑J_JqXt_Yt́'B!2$  ]yOzƛWܒ0)\Z ׺$2*,gQL: i<-мhӓ2m8䊇< AejV* )8NBZrs qGU.-(GV;|QZ wYAō ޴cf yʭt@0D9;rHx'؜Hty,XzKc%,`5sͪ,.Av^ӑƜQi_~$TiݯL6˃u65-TGJJ SH"K沪f\G޻|~i0P8;C%1o23NRdKf<Qj>lE8/ cϋlԴ#O-i-)jWbvP)ŴuN!W)|]9[֗n“' L.%ӄ%$Z(`+gȁחI:>ꅘN G[ÆmJzlh,jH?Kf)wɹJo</glT- M\3ٮvrA\]qH&<جX#{ XrP],# -,^f!hYP1Ew}Z D8q{،_^YrL L/eo^s-zn\5y36 ?vO=8 j2/t \YWG訷0f}"&|nWuϱ)IFkCV8Aa[+gArCP>MO"q⼺Hdє7GzLJ¨8z„;bn)Vk+>,W|j.}ѠIЯ!@K~6`hkŮmı„ =|Lmc9F/l nH3>FLVcO,,c`> q͸|YeUBZrǺrf[7PƣG ^: XѾE6~\X뙡UH"r]z;P!1$Ouh^ظAwŦH9w*qQyȆI/5Mv['AHeP:2[z yNb USDm';SҷN 7̘"a:_7/- պ1D?l]kz6C$q(?;b/nHR7wHm+˒-34>ldC;l90kY_LgkDRKw/ueWHxԎkJ:U2ȕ{8\XKd\G4N8VWkG:?YKju]7U MToӋE?yk@ ĺC_D %!HM;8+0Ki+C753H,>!OS%FY|Cv^ <"G,1y" ;ݢx-L<χ>"#НHyZeW2CI筢h:RZ)9Hy0lKaަ+18,Ӣ?H* ۡ /( g $M8G1F6|?b.ဢɋxpO; XEF$&!iBCUtS4zX@P$z=!bO! %6k4A@h:dB\X'^хa?Tf~B(^AcŗGx"unCǰJ yb3{nȠ% q1X'*']&B1 3V#e#]9rWR~ZB|"h/iKLe%(_hg%r~/[嫔9R,w 5.1pgkO{!)Zz=ztE͙:ǧ0kǭ}1|!= Eu0m,qc{*sJpDjC$bZ+gX)\-|VJa2nͱbi[}e_PIrjD8:D=^ WatG\z.$IF7_PhvQ=ԽX5[igיun_Zv&)X8VOWo Џ+Yg}voHE }!YzիǦ-MB)- A "zy.FXi15 ގךX{WmOcm[>W^(*yfLr6ڊD2˩s"&Ugsķ;S (0+]8YWn\G>]zKlFewPA~(*aZ>1u"|!T3x1C(}Opټ\kK,}~0@MYSDmS8Yf.@#S7V3v6}Aꁵ]/Ц79BPZ]Hl{z4Gcl(9k#c2TB1 {8h}TUZgϦO/¡˒-T??5lL. ;OKBb9طul6Q5+L9ο.6n.w^xzxu7͎QwXyN#n505~x5Li[*Z.Os9/6?g\-n%b#Vtˊkς.N~qv$kW텝!c7@CàO&9EVGg-#m m|eCAۓ>LV{4?|Nƽ>ViIN>,;g8b82dQ%cF=W2V F"h5b?y] <${ #WwGUWeܜr| &ON3&ЗOU2)?hN~#c\M2nr}`O%l8 '%(j $G˄tUOb4"o2-4[P( W"N~`kyP{` M  p[%7qrUׯĉKNGÊ9PS}آ|i߮hj ky5u1B{$*xY8ÿ (,\lV?MQ!">n=߷m;1Ռ#(WL~̂;efoF/nښqxvf E&"R-t>9jB$?~`|:5yZRyʼn\c(./&rh n&hPb'7|s$\D$3Y}w|Op8^䦰fL(u1ەX:ܬ;2[ miT~j_AB4Z,2w)-vo4m<ͣI7S]r+/YFJXՉuМW[% V!g7vӹ*cΰ6ړ3DA 3#tyoD_Us_~Y 쒓\b8.|3 J"٤z}UPd~\-l8w=;#ߤ+(ҭiG7:}/d8"y9 jܸ5=r6^g*=^aBZ^H΅@f-?p͘ q4v~>;ޘ4FL_b8w%}qd3xLgD$%q޿ԬJNsDjJu-js{!(gebe%gNig.D8y.S(t2 v5q}ϱ漩Cq{MQy^7Y_e;7ӣX@U*,DshZ>͐ S⢞t`tz1$fD^\aW>Kzg%ٓkNQlX_ˈp^.}eڥsAq DDSϲ@Pv\ XOe;~Zˎ5Ynmx^I2QŠqo@{\`( SQ {OLc|ҭ#o]c!<վb^ӵjA'jq3ޕ\ʣvpbAtј}g82fT3]8Criz[+@CoClR[i04;^\+~:`ŀ*C*VC? Q3)Ӌ®y1Yf*dH9%RLْk+, Acv K$imGy .}SzjRig$NT2| GVX#jS8 H'}PS2uIMjc1>Hq6 Zlq@6W.rbsBC M]S{H/"rfwfK;;k`AQHѸiM䳰DPRs,4S1QHs$ũJ9㡔 kLx7(/sr<wn`#2RAEP۾;T }[ {~:OP?(3Q ']i"bѠEp[ O\RrX6xmj<\nr\#yPl7{%Ju$YIha<ckOH+x>Ǫ*wR ᫜ڃa3b|e1x#ksyFȏk:]>eHFkE1^lOxHNTᙩIӋ'0Uj ͏rvX[x%@_ E>Vk$9-"ZyQ,10P7avf41V嬹(ӊ,܌,w{e6iL C[ 2VqO^Vz@ەkh /\{Nxeǩ LC^'Kҷۣg{S,3*v8w`ZBt2:3 UR 96P)ʹBbD'Xϟ HF6u=7*;uQ~Ǘ7[q;YJw֍#oSGXS@ ۼ_+SjM6y`"@2qI!]Zcndϼ[;s=+q+w.r)@΍GRSh"K2:AHmAg >m2/ EA6䏑X5>Abȗ|,-Őʤ:oM?HoV8%{ߙ b)|f |ݰ^:1I t,{DtGD- ͍kţUcm"y0PLmx0[>}-.KbD^=gBAa$_DG͑'QXK%AC}$U+F.Geq5{(#ڋNf8k8Q>hʪKǃGaYFP#iBmXJvvMHXH8u`{#)~Ac.g5c6BIS&DqV:tDsލD9s4“I,/jz 4/D~-=HdI~`Pv@WHPb%ŽZdD~h6ŽqCazqVxdp EůG{p`m(]O _wY#k6;J'?vV\VD~wHˇgWy|q^^0v>I hc ٭LdS^UlRo3 Aʹ PDB4ĄbK;T EywY8Gnw3mtWÏyfk֥cAx5KZ8|^?v>,8'8^?k̔m@>gaG> CݗKDN=~JXU)D*1LU|ktm@ 4C\X_r7ZU42B*Vv2pƩ|3q\] %/89o-ߔ罇c z.yҪ}RJ(([(SiwtMe(_xCiS=ss>- eUvMky3 ?S4dE;5OBzcːߺ5u4 զ-v6WL1]c15k%ڵ6%2*^KyJaiESo΍j"L^fN2T84(VO)BRؕu[<+T+])]ZMZ#Ur8\D{w}[‚W^{/eӘZC>3w,Pf[+'ر6d:t9l^:U&𽣦9P##5ԐZ(j[ Ezb`KYR1@n9Hj,t!LBTE0Mm7p!UZyrrxE^}SDAcj}G!TP^em-kǴL):%05;["AY :RAfF5"O80VWJI[ܦgG wyCq.>AJtʈ[P5ZrdA/7<ỤTfVLZS*s3%ǎm(*'X2iJ+(#!$xƼ(wAs%oR>[^⭅oqkd֚#TX>,8$[_,ZBx4 o[^PJÊԚ4* C)FŒhףiPa+9.W]m/LFSń .MmstL)3(xbEPf:-8W>˼!<$yFYS%6r)LM2.o|\AGhMˀx5ąa6͊)rc~oA! sHA@=i9)r-! h<J2 ,;ov73s gT^X붡|\=3=Ҥ 62&& l⮯rR5:2Q  Hٻ׭%Xbk%:U@1Mx<{ ÐK\jJ… u, Cfff&QJ({aNbf٩A/ }1e#dFmEϬ9--3 lT0 pTph#z C;ι_d~>Z2s*9ѰeVxlsedJ@0lrkH՟)pL WӬyj8J˹O;̓uK@rȪ#~լ^kB~@ To i;6|V">rݣreYOݪYq:Bgl67q2ݦk2?Fc4\x]ّXːiY:dɥ7W95~ڲcgyg4\Q=1ywLg Q^],d0mJg`ռkrBi,YqjKHV(1S^Gr\~46/,;VR$B$9 TهuU}gV Nne_;뤡e7KrψCg&j*" Wڇ˂sR!a B^rEpKuF)pQ-JXp\ihB%,tX;JnY%E6tnmPztbj/;-\dVMe-&ι)zXʼnղ" U2OO:yTȇ?v<؅ IbNOHmh b൐_Ttvs4?Z튷@Bz‡l0qC%lؤ#peLMaӋ~uEүn)OԔx_[[{t‚?xhdP%zMdLX2LX!FXW{! }yƞ"_w|F AWH\ȎBz(r -p|–EV1Μy}yڹ==#R&sGO%ZG̨[ 8s <x6`;8U#0;Xwv}5xBd_Ǚ|w1QZj-Tu?ugʤ:j'GUf*N3ctN;$*"p: RTĴ ~+?aAyFjO%(Hݸo KDCʑ@|잻gڥZܚ!!_N\r:Rˤ IJP0Z/ǃkC 8`HjxrM uS-'kKtBs &F乽D-3 {TxgDjB]eܔc, ɶhP!Lqᙁ5717+.>oCg41m($“y޷zVRʡ5J1!ߡamc}ܰm\|Y7Sel{ii&7=[y]OGb)NMc B~QXieKR=ñg8km b_!#G뭐h0"uNϰ.Pcp+.IeL wt hh9G]'$/7#%bZ?₰jAhctuQd% :otKwnYk)We|Y_vedB򦦫A/֯=IUв3y]y%cGj&:Tr70-X;6'1)1tdWY~F Ͳ= HnqC|L=V6_A]RRS'Y|Yoy,F)6ΚN~sΉ[{,pW|P"Iݓv»hG{ȋqtGv" ay~:Or.5/?C~LO2Jhj#~0ϳ6*=fX `{,c~.>Ţk܍,i&!9{ޝ bA6fSMb#~?y-qnmdLi˂Y>\8쉼љ"&4'@,D /q ?s)l)sSOX[W{\k sRyԬt]_Gؓ-k١\>zbK₡v G¯P$O]v߆\wNk_p(h_P z߱ќfާW])6'O<M99! iN~Dʖ]Ɨ Q0wA Gf~y~hYߔwN~5oAu:d5Jc*v&],J i6LfH 5 U{]=<񰣾*qh*57dΩuIn*2L Y0rT_I5kڢGe>IRZzSy0'˯FRwٛ1E6954؟:.#eTVE|!&xv6~Ap$3 +J:ɃP ȏ*e"&}P 14eU MFkJoFϣc[~K惦DEhJs ѼE&U*2b,J%2tGt*?yD5Tٙub˜$@IA;{`G8tBašLLN"T(`s(dxpYJo↖e"m{=TŹe4fkcylm/#\hH^w==OYy-1h/bw0w]"3bԲoȘP. j>&o.T1hW-tLM+{G)7 5/P?(& sŘ~ D>l >jO6 $G,]Ba.5M>h2Q.{NF8 ka~1۟,7Jihleil2a 맿?Tۤ1oyWq?x‰MI+k̃ '_Zp$w-<& λT|ț/<ATJ<%՝iB8RJVfc\Y7r.4J BZ .iV |s./mng|=ֺp쾙C"]:42ZlAV^4Z>cKRSSqyJRO?3☆u~n?#ٗIr@qەe0D+O5рT񸶴K/Z &b %e{^z$.h9yuhD6{6$" 9t{xd/T֢t5瞖o={7ܷ0B>&cP,/7 Q.葙|ݼ"8Ǐ|^7"T:ũAS.g-3nlϚRQiqs -Bw#Asu w >G4)Uи'Ea=\YU,6'7Wns7( +JM)5y0F6 Ŏ-KN! <&#d*JB/*/of~&L3aܡ̔؍!υ!M>WsPYT4HALDĤ6Aaj7u&G<(#~,k*@|#R';͂&gl*#]0 ԋiT^D#_3Kh}* O4kYk1/3BйTc]MY K9c `D,oBv=9ȁ.em$,_PCЉZbXBC>c>f'5)q πiLs̤?o[fQ-U}Y׬;;@aJ5lt7E_xih-6A͇*]0/K-,%QY!]i}J/XlFɸۋQdc!@1؈SҾ ̂22uiO>d']MDʇ!) hDO'GM?M_OcMmսnv ^S&&>0 +JE%M␖+ +8[XRE󪵏*+v1ߧzyeǃGNz7s@4ד ߃֓9mh%AN4PEz,7,MǢ@frރ,AƢj 㛝Fo'@>:d9Ev3cruLm#ā:!<69}FO;!Z6Ƣ>zHPKIn6}12e:ў_<ѵ.ZQ#޹ 2338KGП]A3̖3õpMg7aӄ҄m-O^liPNzJXi CQe$_;):ܫG{ENwm.9c>D掬oђN͙n}D/%|pv^G1騕-K^9@#!cQi1~9P+;ΕPt5j!Kz|%\!zb; W͍oT׏eGMk.k; O gY|L'ZӮij;wdWǚ^;˿̼>4]^+6/ xWxɾjκ;BѫP.ex?l;*  ֐HyPgqUCgIZ* >W۬BQש ےjELcE-^ :_(TBp s ]Uڊ0W|D/g=5Enhݾ]ă*#ޏ TG~rdhwR%]jo✯B:?\lO\y(5vxXFKeĤZC lQ!wd0u睴n[-T*9>4QY{%=8oCF?;S^~HvNܝ8{Zxa6^}j`ӟ;@~D>ecs=OH+ XEդ2N4B73ztϝ8TZ Hvf(ǣ>Pqq~C2urhmJ͒v ٱaJǕ`}>YJ8PkaLS ^uQy?DSUK#D-_ 5n2l%{ =Сrjl גaO6vc׋– f zGCCE_71)^.ۺ+'uСLmCoD(7IzP٭_nNdR$o 19d}$6.%e#tB]/;юD 킿}_' -ތAk|F,dc\X7TSfE/b-]'Tc;tqJl^:&vQL4 b坔?2ΐ?xTUvY*vQy[BR&.^m;xT*Wl1QJ7\\*\q_:U:(ѻTw3簿$ɸ&;9`3e\sgT|vvazA#0zTutJ^b ŌQ֋Cigq n.ɵ7WJGE:lߧh#* Q%Ma$<͠ޚbD@bH.)t,ZaRy˅'L. TQ}8Y.,6myT,<[:pcR'P,| um n'4/JA3ۦABR٥?>O#7?al; ahtƋ۬I` !BZT*Zané74G~3#rٲr ZԹ_ \S`mMzzKo0.,('P(%_RK$ߋ?WqPB/RvR "=_f8#=F @*kSYq0F%(`2J"YL'21W/4B3UDDzwٶCaNL'7[g;4Ȩ8%^lVĥrY Of%2ck?)u }; YtECj=e<,z:heCk&fyEN5AMZ_&"є.MCtZs ٹW#P>+bv#y?4WZ?pbV^" ^ڧ wY{q(̎XneAZt45ʼmnMZsxto0ⱉPŨ's5/vx*5_ v*Y *QLD} rɯN\(o3n6+.3Ss@̈́UjI:%Mzu߫1Ϥ'j^3 <c4Cӱэ&˞v IJG7dHþÕ0r{(4?>t3!u'$P/'Ь^MY݈bӰfE!. H! lP0M~[;< Y4XoF!̲|o^9Y٭fGF?21=)f5dowRftsmu[aUe|eZfyPOIlM?;$x zF=2{¼3OrϢVZ|PaX-˹k~)KB{OȅڔYu{n?DnY7xkֲJPJ(c TfA,_X1>ЊڔUf$.aR7{! Q6iW~/n|,"Yf&eo,w{UPI ݕ]P}P1=L=ʣQoG1MmŌ#Ѿ'cba3Qމچ*,(Vl/:)SѤYCHWWX1K>qb"6lf𴮌 Z+a7PY2teWaBIj#>-s8v0y2bh 9r1Xl Uې]4'}!:%aj! L\}&T F|^@Zr<[֞0=k݊;eRxeˤ;4tz1yt~fbF`B8Q¿0|Ha#g`;,Wə4×̼73U-n!P5m>[@=AiWO|qHxCXuw?9@5p1Oi rO h7-%.kq@:+LY4ER YF;IV,rkqj.>r*D>GK&AU7dA֐3qGC |>;O) uAY %PuKX^aAQ~wlᦆM''9Hrݩ1h/yZx5T5or ;_cT8Wvةy+,Z8YbscZJ.vE14vɫ|D$bINm.NOsnYum8tqM'2 c&j*~ΈN;Pe?2 f\:XG4Rtʩׅۤ 7]@A׸qIO3]f+̍|OZzSsN T '9UmI~zBOe[$E2'ՙ Q Gny}f^].;FEaoE})&.~> 0i ն{#(2LUN}2MtGQNTkM,:˔i7=i%͞YLIGO=Q#XCG;0SdSz*~<=9mw:Gۂͨe% ӑޚ9i^M+;g{lL‡72wT SVfZԑ[Tt"G^gtث Y;!n;3+qE( mv0}\T!'ЙrJOE]=v:f U?z ]å.В3xn3_nL3N- ÞsCAr"3ʫRm|#(QĽi^t7 )1~pV+h-!._S1y{g23FqE=Ge>i)9h*M/=?zVw$80V:F1C-@Ï!>YfoLE~٣ݍ>jC]#&>rĢ]o~bs#.\c`#,?NUхKsSZ"v龑[O\ԭ17lAmjԮ)AOCv9+DUП$%:v\w>ЃFZ+5wt턿r"ZM%fa/vqdʙ갚 Iѳ|DY@= ø0i

qӤa U/P_J4/%- NѢ@ZAibRJIT^W ~i;jUu;S e$^T?ur uI)|*K(VPdV;gqb~??yw=W{هd@ZLoLlZp2…q,POfMO)}J_/xQn^*?C8U Pԯ=]ѽۉ3-6K}+~CGlj Ki10l6j̏x̰48}Qֹi[zl-\m((IfxJԢ#\OaѺ;kʘ,dܼ(=XQ &Ϛ*ɱ\СwD8ҵͻЉM 1<(#;sC՚/rC 3čk*;37|d)N.NWe{d{d"JAhcPC0֕`Hdv4upuNaIҠqlT?Z=7*s@Z"scM O("1ibY%y5Px.%SwK:VT"LܢySK$fv& y\b5搕R4[Cl_29D Rb/kbmbXr<Οe#6RmLf®: ~FDN|vg MF3Q7"۴2]K<'ૼͰh?O\OwlwCMD95NgB{Y ݔ?Ԛ !MS 챿гo'v/"AXq:z?S }?jz?$fKprh ,68Vs>Odao -hL]\(/+aҺJ~!vC4Xkģqe!M5Z(XԦJS5M8e C: \y@aC7$v5gIJykxa#7@lnkEk^ SO;Tա:Oݖ/]pޑ1(nBhtalqi0V_(H<ݨnJ5,劂 mg}!%E1ډ+ [Z >MP[WͧϹj[pa{zC%/!NnBkұRNU*jUIٜӉQwl9qxCt,t-BGV(=lPcUXnj/gH4r=7rPݝ )&": J/NOEe<u.)dzR贗7 d>t˿)RZ,?Zq?qЈ9UpsI{o)%##um82>:mY%*`Yn|*6EwqwM_^[Oͫz4AǞSS,PWSm. uz*z,ƒu#"*8:0)]gX ltG +w;N˅@yEg|/CU:ܨB|*J #P zv ̯(?w.Zly iOd Z 1J Ɉso,ma?39 G'Iz?e^,pd!W OwRe.+;xa)=sȟ{z<vV X{/B7H5i_j?? 2?ҜKɎ6(=*(yٵR+.cO_g(W=51ĎjC *D3ά)(3d}!8UB`Uƃ/e])ŮF]Pǜo@"6Zui U/VqlUPpzf'q523ȃT/V u*US)/SO3}wKSz.D+$} i1ɥ<))[5H[)neb"px4D6M2Y_qQ|?Ϥdkw'"Oz]!tbLӢJzDZ:a$ei(4ڵ#=x$TkOJĪ[ʨ*(k>!Ȉ-o ,xlwz Hbi͔ߨP[*Inav/ڹTП=n>yR7~ d*&P*"{V(q >hĩw5bӣTt3ٗJ%Ԃc˝C/Z&?rA]Nإ{6ŶwU߄Fp}Ք4ɤcMuW)5Ɩ2lw Ӿ&FjD%\/^I+55tPW݈jj0ţ_#P}I6B ~/M&ϟ)e5'F.U/4Bo6DsԪ f/}زu0 8TE(BA~D/9$9D_k Z"}[9AGXгߊf >7Rͷ&W RqH国f1:Έuiv`NYrGhջk\6ڶ(ѣi:. T&_2|>DܛuG:P,T:mLߊS#X+ [ h2SA\/fI=Np8(\F5ZحPbH'sjOhS0%f碸 #!A[vfv@Iþ7P eL]>\iŶMB7eZ0㛃7ȻQɖ$LC]M4׮P]% ^[Ő!O딋U4]m;{b=דPO-5nW@֎M']A8GNsRYxGbj,EG׽lx:nyP WM޿ͼMJ\R7!Ma'* NՆ[Q̗z'_C k$2XQ濁1#3}&fwLldb7poX:^{Ib&ZI%6CgtE¾BU5Ąϫmrqan+(عy;N3 SAg̡˚L!4'ﯪʝOg<3pf*^ХfZMa)&^QaM4Ă\\o#ZWe4*+<21Fv ܫq֖p\3}G %CU٬\8|Ψ:n8cҝٺEPK 6┞[P_E7(\*ZLYV= 7v ;&qrbF?+:9 ;n%]Eap)OyFxUOEmtJvVJ+T91_zݥEf؉ZÎ8(k]2FWډ4ܙV'(Nq *lg*c*SJf[k#A L\Tc*-X+/ESc3|)z)z^at@]iq-qHXO[ VOw)nӴiB<]TkiͲ]C+w"ԱcG>ɐUK1 |)83щyLZU+R.É2<" )x bQ̢ȫ#[3+ߦ5f+vYp[|iM幠J:@eС"Oʋ>/f$]cݔs):lvPFJox:s^3Wt蠃Q4TUEM9Щe,^K_+72[ tKvW|X('pwm(Ԋ-UKktDRݙ jژ:*[49~~r-a x|\h$7֞]AT|g,e=kdC'^7dI"1NށIAaѽ -0N< Q;iKrmf2 sϚDqNHDpPr¼̈E]2AiVv(R'g}{ܟ$)^G1wA컀jxQ%vȚJ8 g̴ny&*#>7B-\Əݏ{mԇZu(`pgb(|=u?Zh݇nsU_7>1(ko H q0Jz5H|im@~SPbSy>E e~$`Z|Oc+%˥:EÁ$ffMjczK+] S ڍы(JM$q/ L I"s`l"E;(oG5[q1)C'"5lqam nj0"+z[sm6ƋomPz{POa;j%p ;_% vh- Ro6OWt]&S$?Kˊt?L=z+(#ܒp  ɀ羊кcʓVԚ|ewch֕2]^ H 3LT"Pn5cNGCVh2˥@?pDާ<_I_,sY[@ *dC|'A\!GNHP3z#QA[%+%wA6ax_FL[wҺlN-}/R I)wvĎwirG^r6$`Vc؎Ԕ "J̋-\io:N~+A{F [# 2JYX#pm ;Rd2yC 1W)jXvEtg8L>v|2Au~[2q%gesg?.t'׋7|V>(qT, lE]P.n~Dټ́$!WW&/%.y~?ly@܃W;- x|:`Q?u|4<+ghK28~u-o .GYE kl[/6*Z5 I&7g5ibv_Vowvկc&GЕ9•)[g'\7=2(ƥ8E;3SU\;,X]o9C[AG-Q(zw=, jgF339־wE;qRY9!{-N"o΄yŽx uy[v(B5z#Y6r!ъmcgBGk~ts>d?+nԳ Ǣ&̝C&gsU:? <TҼ3CMmWJZ.CJ)jq$ilR͹cŻn#/Zmh|$q=>%> Cgm>)=. t;C#c<"n[o&bJL3k֧r{>ꕊ1 >Okh߼t Q><]Ƴ "[KKK&.:vAj7Sg<>\o^*ikR0ξ<@?=tm\)2t\XT~MpڣٿDA9$~Ͼ$w}6vb Ɨ7ݜg:t#9+5԰)I8PU}7,a 眠JPyehz8R v+43&ǂHQ6XT1EK:W408&W3 1 * *R|S@& ^w8doja6J~HH'x }`#mїw"3Eg2ͨFRe9_SLt39|WZ2g@1*Bg:uS$P>fZ$] H,W]YEW5amUUʂHװd8(ohF͔a~)U ECDm&0 Q8&C>`wXb[!(!a|C5BJMN'3:}!T5UFr|qW&(@:&5>nRUS/ U5IHҜZV%M*v:U*5mR 1^!f,xAGaCfRKGa >@1CZPӰ݌Wxa0ofǬ`ʍ@ǴglدF0W2U,c=:Ib]$e\EluzNCRn[ m*jNFU<tt@R/O-?ЂPR,} ߊLonjVVFF8oE{ыJsmt/(q"^X%Q6Vv$iw)mv5M'atʋ{vFcj,{O*ښO%0mi BIG낉sə w? c#X2o L?%NGy@:v}NJO*>MŇD 6yf^{${PMΕ󀷦be u 4kt kڎvAsnpr=V+ZDd0&i"X-oeK|fua~Ys!%C!SI#;bEL#.}޵f-/e@ %G4,Z2d!y5K>gM۳D=|S ߵeo<r ]| eVˁYxB kn\g:z pcu#Dֺԛ'Vl101)`O`SY9y׏?Yz?gjdF킈hO} "k؉; p`;Z-LgO1}զ`V#Ȕ=Ǿ2v]Y5D޸*G>1Yl< s/IՊi~af7:kأUFx2=cl&nk⠷Hk=__lt­wȲP->-Z\1 𼑲~Z -1 ڰLq7`Dw3qW}0X~3QLQ)T,߿aƳBΩV.;B4[q %LKAgý&7Ju$HP0uvUJ܅hk gn+r _,>TѓL8 ۿ~qR!Fyldy̡6*% ;甄\.24.x 'P23vטZ*M @.Ftmv[`)||Ef?f0DX~dW*>*'|S #@6GuZ5?s2W4֕u=:%g m;h!BC 4[x(uY50`J'xh UZPcb[wWKBJVMxt?B6[ݺe[l6`A٪Sl( I ;8ב' GbR^GP_tCmK +g/vR?9Q)T 9, G6iul5Jۃ̓P(ۍ쫗'+=瀶arbU0ͯz߆)LZ.ČA+%*!~5|>6yȔCcI_4Ti/Y,Q}ZG/ zϊ46q>[mr,~CХA~"Q=O߬nJ+Qze0tyf!iieEB)j4x/vqQXc>WwL 2֍ͼ>'CG>˭X/%镥BCv>]Q`chs^r JJ͟Bre _U \3J<=W ;h"wŵ XP`/;Wfv vg4WOdM)ݞ6{=IpFPhw"+'_|GX @,b۔iNcù0e~/L5q]? F9Z8\+*.- Kjk)oV73*qHdtT\)A0J@oŪɨkTJqyۖ͆̚`x$mo|N!&u[uC>!oLY].w%6r]@)Y~GZ a2:'k-w3~ zPbnfjR''Qyp`{'ˣ ;l81#aY=.H.O*z*1t-}q|a˨0|8v-TG.?/(h6d[0 1ډAbdNbP*jΏZ3Sk:JG1|rė~PIוiHJJHߗ#J]>5f9|0( }/PK0.dhSMG+jm>aN9lXP]Mv6KVlI{Ǩi4Jsqh6uN^z|9ډ18RЊQXZY~lք@{W+Zf-,2BAWq}j@*Kt[|"p}-`od4Рg{OpSw<(jzHVx~ &R9BOpTGfEشuZi_@:_`@Gf7Bu4`gpݪBDMKeez1˰n9FqUjp wL$e(qрO'f@1b֌9  US!j#ϸ}GP~r}W\>@Kb^,Ffm_θr¯2Zl7`ȴ."yp^{[(gt0T 5E9By[ ti$hXVHEЀ_f'uv9W-eWuV.?=B}]t:jTeް; E_b9ˡ:?gV(w ;1D☁nkM7wSoH(jOE~f}NT0Q?]gZUdt.OE3x}eLO揮39K EP'%y{6K"TS<_)Vy*nȎ Uk.J$ sgrREĢ%uޫ8(s4m M3҂"+,W\@:M˯܁`y{/Z&bpٕPQCؔV sEX4!ꔝa,| #&`(CG[D>qhZj\:};'O3՜Oߎ{ !qh"hxBٱI#(G*iD|-nrgY.T>7QH6[޵]Z`(8#la.͊ %k[8]9If6loK᫒ъ}^YwrdQ%s}n\ KEn4 !qsԴyz͋vD2^䃒{.s=AyS>ٜu6˼k v?P?KŕV#TH1]O_ZstwhY4 y0WioB5יzUwk"حL$|TIN4FOrX[ 2G;??:Ƀ3Ȩn,!LUfX*yokpjS'rv>6,U>G,?".3NC#4Y3$Z@ 4G>=%r'RJVǐ<(\ys tPq2/(Cnl;f%fMԘ1L?v145SnfF,ݚ0zl0{v) EƼV҉ݳ #6iO1lt0/!7>j ك=\Л4S֩roǰ0DAyO8VGXv[}P7:c8 #[d;f٨'`{l~GM=913 "~pp4_=yDYيt|'JpSoaϰ]{@P. bz\;hpQ%oqQ:߳EzXE @j3ITʐІ"(ռ˲UYY,=CwENbDzQ :LmX=IYl$PfomӘ|LA{wLP"$}G`ޛC~p!S-Wm]6=;sh.]o;DO:D%]y#*s' sdъ8â$康Jx*i3H+t4qp08/ѱZĥE_u[_0@2M,F g--cnT.ڄjybN܊~*~,x\vKޢ;(UMVK$ 33$+X@CU~û0jjq<"?t%(zg")A !msc ~oNIگ $I|bLP/O&E% bUjU3*#*=\n'ݼ5\׺Ҹ\~cʰ^3RZ}tB,vc9Mhɢ}uy15QQ3ËI/MNO,(2FPB8fOb8=|[Vn# |` C ߗRj}e(9 Ωp~)\У +},Ye*)d^ U`'+PjGVrQ3X1v3A ϳ.~,@Z4$sdmi@ c t3_ڥao3 rXgeǻݎwU 1ZA)ZLacdEݜs57>}5")@hqcdvlo:HSU{SQ +|O6ӰxKBube-F: }0u-Ì=zoVjaw~ynaUc3Φ-lm5/io|y@e`eW 6ˌZ$#?M2Lھ%~=;}X8*bFvݔ֐ܰ䠗O%M2{1~Am@wHX\7ɗ}(?aJEFByqsc2(ۢMs~'F-͇cd 8y&>W4iԳ#fc9ã"o+qWÂuX~SoćSJX= A|Tv9X a<٪P۵j;ZɃ}U'm\h''6^I|7Z.WSU:~]Zx(NtH2g|.d_4}qh4_57f.Z6W+NEYQw|"ģz k9*V)A1,W>YfQ_~Ç~-{.>"3FpgyP3G$b"؈+8"2ZZUG'} }r&&PTx''4ԯ 'YqW*91TUYĿ+"XClaj3UՠoEҽpq;p򇆣[fEk>GwlTs䙀*=:AD{Ok(θSa˾-w[rdOg׺)EohFVo =Iqn8ޞ\:RLOUHeÉrNtދCISQ;aW DDRZ6. }Yz ;;<矝 ct I #^4hL`^O^bvݘmkl DKMC)а-\؅AK8mveϟ'䞽ٱq($CW *bd2Zƍ&*$ɍ<;zBK$|k$*Ͽ%ʕR1?pOr/OV5;^mЗx.I3_Zmq 2k`VbNEI L Hsb/SnXu4^M! M )Gyzjͭ`r}}tN92Rj ;0av#K.떎9(jk%þ ѣN(_b'`DS>1u8uyY`d!F_*0phψ|I} kxOhŔU7e-m4qUc8nmqی`!=Ϟ$"PoP[a:uV\o"L? bhYRu4~9c~PNO=^p2z itڇ1T5!ѓHfsv_}j-"f;6_qz hmV \51JT}+5p$@#7) 2ZJѳXvJZdmԪ׾Uӵjz b^|dDHV3зp(t |<U<7&~)".v H8,–șLw*~+R pv֡;됁>DLYn_Uώw[?UgűfS_e !~P簤7&bx]T4TS)%>OOCbr s3~[|_B?xʥ Մ5WesamDgUr>STJ"+CҼ,ᆅ1*n.Gm_pp/ˀc0Trφc?2ԣwAov·u؇ V1Udzk+JNoI8@3\}u"q]4-KL9#j}.YICҋsT)I˶56iw _g (@LSPKjłIH#r=@ڵ!yJ\z kZjy_J 71u5FO+Ha4рt:m+u' [Fj%ڕ56 Ƈ9 }6ooF䜲ϲ"c^j_(lH> ذ=I 6IFM6<.&\F Ui^:=ylrl5d#xkP9 ;cDV(!ِ6v0}1vy@ ]J~2mScz֭<4mMFtf}pD3TSiԈcbW,]b/2KN/ǩ҇kH1t,4Frt A÷r__d7HONUGԾE.tڣR)y/RU(U(qGxCu:>~.ܨc5,x}Rɮ{09l+2(մ̼:&H M]sy3)Z`n;ѐ읰Xδ*PnֆSTjďD%c{el&%[i[ K&ECKT4~Ďs+-|A83׬IBt(i*a&@SWJD]43FuL噯삆"=6[?&t[w'AdlvkRet+VJZ"G'"қ=v*TYV6E>g D`OSk& JEKnej?j+8S+ 2f(n)p݌X{yĊhMZZj+uuNފݾ Z(/d5i-*uSM9}Ц+r<Ψgg ~:.7= x{bxm,멱%"S2pDU,GjBdrp4``S F*JwǥJؼ1+:>+#`Sg5^G:4saIrѝBۅV.,*<Ǻ҃G^ą B&!hyL*3{=xNLJ$1ǩhW9@ӷagΖ'К[6\hh"oB0&nG ٹ L*w|}(t bZerqd+WZWӸ^2[/R(GƠ'HZ:- hЭx%BD@(#/NmzsOjvK~0~ `x3At{h];+rnj[Dy~J*}TV;<?IbJb ZSB\'NFVMp*`#ʕl7†/\OS 7쩻cMEUHc @XtX:ż7$ͻ JGU#M˼NQгp=mI2B#r@bae6^j ),&WC'IёO^K\kMVb,!SL$mWݲ<˒k^\tV}mU੒;^鯠Ll.R@}k(1.F^3Now-QFum>8Q&\T7Tki4yzM/-}Wg窓;x,Iۓrx3$Z^J-zqSb1T:?)&[Pk+6%(k >cTJDbH./ʉ wB>Գ/|>Ss{FP b $/r´wfpc ՘L}׋xJ45[;Z =hWq Y7_=#v kiR[T虎XAI,.c<}n@̾;XR{x7בW?:q6oN,4To^ЃrJo(*^m3%3Qz%ۛ*,3ngyuĊ[` g @vK=yҝ}3 ͌ bx|7̸]q<Qw.2YZ{BT q9h1q? j=ukr䡙Eq\Sݡ?t1zlj)?ƍ&Hj)5uFf:#֏8XQaQܶN>QTWXTv̡JnBxypHp*YїO<@npMĖ`7ZEMy@Me VERᙒPiKzT$bXPDߙj#' ݷ``(o#C-ug9ENCHH Q RzegogiU$*-> \ mnnfT&FŽ=i\8yyTZaf,3M,,JC -hIj+J'`h++NHm*}(#KDMl~C-ߌ2ʗfč{7~e8 l/32`aj.ĤU1C:@|qe6P}Yr YGl&D"O{.nҏxJPeNyKE+0 wW &Ej{TNk&ٯlot!N j9]VM-E~HK*?l}S9DICS~tHl5Q{,Or:^]* 05bsyFmXpsdԻ:M򭉼49;o<[1P(෾3,+LSrM%1or,֮s[ s}eQ<E1mKdx- wCX<(Ġt́۝݌r $οGHIy:sc++ ^Gc{2kѼ]_m]i-Iߟ\oOl|Bq_tVe,% =ζk=5򇟊٣OI'n"*x8a 8};Rrtl؅!jXA)״qch@Ie)-jF>duʢG)CeX;1p{{?)㧢hWj :?.GndU뙑`hsm8:jķdFGp?n6Q]#O`0}\z"c)WlY{Kz^s 1+k ľuhriғk{ŏH蓽5 |E8)(\lޤµM6c;ˤ9w9C+\[ev-/֧4q͊6puz2ϿK} :m<]pEfy%.AuӾ -K}Z/ϰ|n<),7ezzON}*In5˵+⼢tˀm|ң"5J񵁷"7^DC)4G,mT1%inx:2La=Ś.%CC_yB@SyvP,IE)[#ҥE%(4psfM#Kd_Ώ|TET 79 XznZ`+"?5M1 \NIMԊ41 PUɉ=៥ܗGݿb}b N﹒_s FPtBGt4_EmY#/ dB6ml:#:Mh)[Q"|(W.j̀O3 yе2)G)=z\2@e_ "K bLNnX]Pw=LX/; "=ߙh-sjddz8;n7Y= cpF jȤh8uPZ]z׮|]d&s&xd*&H3UiėiaYjtD4IPtnl|Bel ˡU+JOLMJetmW mI381CWY՜ÐJ>4TvpS2jC_N@OIw_*I}'L3%i:j+i(/] %V$^0i}~v92ɑIhwON8-#Rf{ '_5=zfN|;|i7Sdr&ϪڭOgw& ־& vtN W2]ǰ:+NXm ZMf؜aKGh";mޜ5SC%C{_ߣe"tG̨ǔ3yy׍s[My9HR`$s)~Zѷ9_жk@9`qV7~wmn"!,B#7L=gb't2 [gWaZ١]ԓ0X9'[`gPXSyѰYXE/h݉ s'u1q}==-03"S08&H综_Ҍ8tl]Iц{˺M{~:SayGl)N )8A+~c/5^ib[ L&V\5gVks ^Fʼn&>GIEY^L =h_ `]Xy-%(ߡʑHdd4s{C()(:kJW0ϮKײ-D=^fTr%cs(xE:ÎoNM2(&~{JhK;8 ifKOl JUTk7m es}^ !,YqVz?~x'_#?${+GBFN)I!V"%K=B-FwٞxiN?\ SqenA5?>n:F^$ZW]YqҘͯRSE_0fnI8 #Ȥ/ٟ}毒ʥX27VV$wt':VAmlϹ2##Z&F"l2zLrW 4)ET{9l DHOjJ Å4T`I譪nmxN?{l᭚p9AyN;ӖKtszKAjkT^*@_(%YyY4UYy"FeO;o|q:4=Aī͋O3hOsCi' bH:ӲoxH؎jdS^藘;ãW-z>E2>*Ĵ*iěF6Ȭ_}n m#{χߞ)7f{St9a%v.z_ RVN"=jV?{Wzt>81d6 T9 5rݎfGfs?'׵<<3Mo.f{dgc햧H+T{?,(*f䪳G`MVc=M*=DRDߧsSs>_w潁6rg;Z&'~ܱO>\cөbw92~$?7XSml~F^4% )JpIs1+hnh<>KTw&MDF鍎ԛgvaFTXMXэiFʍ*e1Ӌ;ubDa `^f'nYA~t5#O@voTKA 4ϤI:p"Ulއ͟*Aeth]9_y7鬳fv82@գQr&jfeLB D.Pɭѯnj,߲Xd -=S Qgtl=%ZXvaBhSS:dFlӇcofX)7_GY'΍FK7wŪcmE&l*nװw=%yY NM )ly?,̡2^5֕+y7j^0Mגsq9r/y4[u y$ _jU:O 9e'G DvZ/ސo>$Ii2у+|:?jF>W-YvL_j"~U-/V?оiYtmN>$*=wݧhclZegf* :Bi4` YsFd`T{62FFt-v4ddwPw|HS$~kzMXєc/F ͶÒE;NWEJ&i!OMmTj)vŢ7X.uǜup;By v? ^-D9׋CVޜБt'dof 1X% OúKsˡ,Xb|H=djo)KfOb=V7I)+>oP=|x̜oEn*y d&^h"9f+oHݮYsA]޼vii M_|D[.B~q+Rhpmi"x/ů&-eЩiЙ%}?15|k[\j`M;ciĀ%TY:ɢ;!>rVuC/2a+;~F_Ko# Vtqq# TYLXY_D +{ewWtw@3z>KsoZ.8 #Qmᾼ~;0y-nC6|P D[HZ^m4G}*j.WLjͨU>'W\gV)qE*ϩyy";%\:?TeH|vefgTaǚ_G.AU5׎]-4գSA%˘R*zqyqW+˻<:;)?@s޵Uهv|__9 eTU^yԀ#*y,ugp JDTn."<nN`_(iГuB!^s>bp2%Lr(~FD:_YKCJ0T#.[vً:[od1 4~):茶-|YeDDHӱĨC/4J|犡iU+ڽyt' BT,& w,h.ȠȠw/O2&}TW%|b(ޠ= Vő^ʗ>%?.ui( %k _Ұ@3: hU9wny9E!-[YEke6­+?ʒ3 56XWiPOg= AWj}blՇ~4 B~WjB6I,r9ATXiv=0jP^V<\:n2T,gKƁ2)՛t[*M͐ǜb|tycRrr-VFm䧄JiϊڽYQmy@i+!s< j)@ZDz ;j&M1nLS&KNm}:8} Ԑ fij jrc0όíU /X")o͞&wVD܈bEJvIݖH8l>*5F/mCL4vL;-Z8o;G4^+ة0Un!buSҾcrVLqP%߼Yֿ\[,k9UiיN[ԜW5bP@4S:])NfAL4elHntV\V6a9K4GUy@Xv K`RZvo\zδjc&.e>s@IWaY9n]d/Cos䟼MY=fn *) cв}5st|`5MoJ**U+WFUog]wx#e#m nѰ}W4]>@mGyLB?nY5!Y鱱_ MgM'Gi̽H?Q R#qOM{#e&h{QigL:J+%liѝMv:؜L+WOl~?mA~~LEƴ ܂1lEeh3rx Onft5⡇?5 C KO_}1l#J~^iF{d;ȂSMҙdǹ[ PO?$[U R~s)={Y'%gG_^ґ_u\m6,&}v *(cLO^ƎeҰ5nt^N1ӸCoIB#_bz/ӫ1RltpB%Zp#k XַvɳM$:.=cBJ}u$vج9T%FsTaBeQ:%vtJLD ;(jckIA5Hl+Q9ڭ9d7pt|I$S<.KQMd)#ѱ`2 ĕWήdrR{|SMP"-_э1%$d5mC(w+_''OV;HԻQ#L[m7e9t&<ťƊRƁ8v.l}Y3fs~|q=TjRt!SNy?{Bɽ!-~t-gw&?iCy_Or>Jlb9_m><_Sx&W30ɇBC SԉQ˳jޜsFCˊn6g[5 8%pԢ%F-":sV* Ӹ!>2*!T<ƍg {K^)qFq*F:1˾vB]h8[Fϙ}fR׵;<$~[A#T9Yf6>ۈ4lK63ya.g.cd\pTR:KH@!d|/_;y( ;1zMRڋd" 'W J?܈nÔmHNӿ 1?K6]д֡O!ZV<!T֔-,ێfy#$iC KJ$?uHp !9)=mX؟Wk mʯ^V4?y(~vMUz:ċD[ŋqX ޖ𪞯*T3Id^ "U<䅲M3!?Q7x*~sCڌ".{ o=TJ;6J>W#IP{(+BӋ*хz 8+q|,I$ܼ&Lߦ\7lXOR`4k,>/wX4t 'k2uF6$(+ݛ%]U)IfÍp# PW{F O>߉cO/q=w'7Rܽ H_7`3[d|膕R7PʟF}_`Ri KʵIw&S)_Kks$BV)Z}] gtɽ!Qv˗f Ban"N}ꀍ\ \+h m;l=todCzcוKj+GĖ!iA?bE4&안+)wpCSNre37QRWztoblQ"z}$zHX~wޙ#'65П^%GSvI N8[FW+y&C<~*>Bs)N(j;=L4?="iӯ+c~F JNįt5 ~R>[c@v 7X=Gy /hsx>a}MZaB"[>vAFk3n3&?z[՝WY>v|:9UwF.՛ %7=@Wfu8?aNgt K:6?q[vb'hE[4w眊^Dfz arJHEs1YX!:ɾ>?a[ 6iE g=p(^a4{=fmt2RZ7+z(=RS]TI[$%0`Q7j*I,ϤgER&w30TŮ83jֵ(,Be! btլ5 3Da9fMHfY⠋ Xwax%ml1h qc7*<}rR<Q/?%19i]u,hwi0-4J'~M͟Wb&;=˜a U^ꏬہ䎗@3pC<.@ṙ::bǀbX覉 eCҟl'?YTYԕYÜvڙn7BxMAO>=2#\8șvi-^i\yΨX]?(oa{yz"tn7Bg,L0L zJ@CpЧ 5Zu]"N̠-UMVKVS G+݁88ws:2\`??٦Z25DȰٰDEu`/*v74|qYT5^yXy\Nk1Ө3@ zN?}MF3 2N[Xx-"Xceĺ~-1&KO͕P;]F2'G0j9uD[>֙F훖,yٟ9S*7Q Qm(~M2'fNepU,LZֻ1`o3֛sjf-lW݉grRs"#/ z&zn4>5K i:=9ut):gjLߡumMif8ӰNL_,2:1s؁4!U@wZ;DRbdؔ̀tZKm0\J $Glzx~X{Ǚ ?GP E|&E.,4m?Qlj[٥1X-<2ZA=xrS1{Vz|,e%ria<'Q(u!*˻):T{ZNeFֿ/K ӺʲAv Xvd)+HlffVlvڔ9ʓ+Juj%1\"'JՎF/*cI*<[\Nk$;zgtL F\9{9SN%h.@zcP/;OdO;GDI (t{r4.tdV EXn/f@w72:;RY|,i8s\Hhd I2#5RI B%Jةik$8&8t װGEnEh =vIMmko"Im>Ҽ.&(6[{y-S77=J/ǻY{|*T:,2zyisfu@۷0sJԜ>ЯG}1`zтLB!&pdpw\-W(ENPXyy%_5EeЬmy8 7ލTo>|z[ XKA\-1[ntrXB ˯]v uεSdBκTrd'+>3 Lwiu\ go(ak k5ML !.v]ѷ颊|edncZ: QD%hOMVuOd\_QCB"FTvV].5)s F\l5F\5+4ϙ*S1sҾƦh6.zvY:zW\}gCT:jEQp"oT'l+;QJB܃!Dtxt ~nOY‡Bvx {,Uo~k)> ]n`Uj7yk/2׆ZLh9>Mʏ(N$$t ZC4&$'4iHoB)2ǫ*Xbi"CHHt^Ab>;*KԶpN]硿JU%9ㄼQӬ/fck4@-چ|>?%Z:#g-s^IIRi%!CңMZN LÒD9!}&_\\ ^7ɞUl:L$$dCRpg^`Bc!Oy  yThzԨ tkl[n=2>9ΖQQ'wTxnI$Q~޺Ү|YLRZ ͼՄDʌM%#od~.02bߌx9)@6RWrA ~†c^W%Lw* yyXq^Cݸ(߲P"=ֹm:TWrڃH?þe':WY 8,Xs7y||F.y^aק *zi͙˺{6!Pn_ft~* {:0ך|-wơMz~I֧Ξ a7%1Gи쁟=vNX,HSI8xv6c^k6a@}@<1OW(Ogg? -L)i3|‹OK<ؿsfϲu;[vީC=yyTm J,E`Fu <7[ QG| u!--%3N)[䠓`F*i7#f3B|rxCܹ}ۂ-`K+9ie/l/#G&kYϽԖ5%,n*b:&V@6 Yv OǿL*z9nwGC@zzOFtֲAN[8e<^S{| :{^IpF9Zhv)o4lrc`3-SU.CRdw\(8$2}'1O qD:aӋֵ@O'(M 7/EG+NhPR,Jx'I]a[MegZ% CYxfB:Za`b}aCjZ /"vY00i3* MKױ Ӳ24 Nd8&)0=x[2 Ie%mJpk3D %r;Us$ICG!V1P.TNs }nUT TtY Qa,? h.R"'[$ϧl8!qb;N]?z\;.!#"G/ušBٍ}D]̏=&nZ9߳YI`je`B#4eZ^\?$v;f/͟\]O8Vco(&>?[l1N&},"W_(MCψhRΗWtuî;%CNU~ m+Wnоðt0{|BZ!ɟ]. xƦ+??c;(n6ٓ@#=QҒIJ|E\s% צǺFșK'Mף7ιPPuMeMOYBK!%;jI2-ڍ 4鱑ZS]ԟK >nQx"L2w^6Uæ6gkE#ؐl'?yh9_A0TOj;CegH^*BO5/O[.ϡ?t^7).Acr9'2dLۿ)Y{2ve3xLvi[ F2yav2ԥ^1Q*I;HgD,kt)RɃj+pe̘ZMMoEЧ-fPTf +'_Wg_wװ,$Zٱ)2-8=Qb'QGCHQX.Vg(p\E32*Tk&߃7gj2dTuGTg[R;ۯIiN#%ی6 gg%Hٰ[VW8aۡ8qJ&r"=o؟;Uh4JhA_U{LH6j1=LW*ek0]5fF+f8K2bOO5;VtM\r qף3`c4yϪK/t $Vct͎\;jlF쇥 ?5Ҏپɍ]κ~c!9&L)sc>!lX^mU2Tzg d-ή -vFYVAG*D?(*eR$lޠ!&%2ȺJW̜ʧ3UnٳEtBd4`"PEC t:IOBc4IyXYF 1hYX״R,כOZ3^<Ľeܺ*v3/~2ȅ=HG\;#5*/Ѻ"#caߞoFm2'Tw4=ɜ|v4|:[z2]ļ%- ؉٫DjC¹haɨ['Tn KJTOF}CfETSRXn&v]Oɨ3)JS.[O LB5 :6>R_'4sP< S5e_[p+9d}<Ny4fk{GX fSo!zJrey.ߪIۿx9|&}?>+hjߔWoh0a$rvU =\e^؀euN$00FUlťRv[ka呑i:ws@o dk82Ѱ}̈:&ҕPXô kgӆIѹ*#?NWJc. ?s΅+Ҏ2YZ[~iVzl[dɗ?<A9no*Ʌōss·y m_mI0xsÉs59R\g O`d|CfJ7.zǻKOU}OcX.b=V&sb'v^v̝FI8~x w&<6Y.j*w9w+ N^*ґX'{[AY_~tNyGŧ5]|Kq\AQa#kI>w ,$f 4bql02)k65o~OJOfL%}9vDIAQA#?I}h pwWZ{R6s.aÕ[T<%qSi/vd9{KNdv!i ˦Q/|aj㼒+k^oz-[tҮ^Oi޴nQQ3H=deVqyS_C=щ+N,ݗ  &v؍]Mi_A- ?c.XwGثÐyLȟݍ:DIat2`O=m4#y5`na .4sFi8iYh6 2H(E綁4uܓy鎟Еy_ˆ;m~E H𠬇Eo4ry{iroGX7)tMoNG;7/ Pp}\]q5n3F:l3y-q/ɺ]ř15nz $:y3V!"B;#X[Y,Lh(ߔ6Gȿ RVG;SYcEDb`.ho^ʽ}I|)c,s+/):Xԗr7=SWU?1~{v7@\.JlӇ[4(SM(Y!.ʣܥratq*O 8 B^\f G 0H^;4EjcN<0o'̢Z'{^E^nH"E,x; >kGg7vXoAt+J/Zi-Dl&$ dyuRQגCJoo]wtO~4\y};3|,,{ʉ}qqPvYj)rxdwu弎ƹQd c:wL\zx- N[ b>?:ʇi* A)K}GL;62GB!tN9JQjt ˺JGs`AreWġ֌N K9jށ =l{NվYcmw-A`xhbr<9@UuGK^0*1 k.ҫ7)Z,H}#VhvEGз};BofG'23uz{U:7Vkfh^y5j@:x+j V۳6CNO)5-nKO]9U ;~ W׼( WCU͞\GNCPVALtN+76kWF/S|Od%G'-s7_AnB!OD]tS?)Q ieNC;3Ҟ9?R5.W¶" .9znv~0z}kT>ȟވ` wۨ6H# wܧrO`[}-~ڼߪ9Ǣs&^#erJKy߻kdvOh P'ydn{)~N姦'o@&A!O\ ,n;ڠy~Pp+-yZqVFhε9G MNG WA_q槮Һ% 8oF`IhI_us8;9]gkd(RPELp53=J4d85# XS-d2IFVb@wj yEsc;WZ_<8 ח]f$xl^%V~s}&C#طx F纎ξ&LO:k#/&Z&s=6BH2I>QN  w/:Y%o[Z]IBàkp:Z~yY x} Q*K_;3;+; plxE䔾%n6wR8V$5Ck,%s3J$,#'L;׼'} Pi1og6mg5I}ЙMrZ*%M{[x?v-IϕqfO.'l/rNP& P5ĬUo8"!E; Xi#ʑdW0Tl1Gzax4a VnSg}wʮN;vdI~wh"3"N" b%M5x*?V!m=[4h jɊÀΔ.Z:z>8hbeҴ4Yb5ڐA% r [LO[>ahJo"ޚNNz <Űv8~l4lOGM!I!Oi>7|Uz|ZhR'j6[1THYA{iC2Bf%JhAyށض|u &}k~ܼ؜koLto Z g/jf.0W] wGqίBao8?rZMM CeX &SY7a-BpJ &y:acFx:h xWF|*3^w0R ԬpSl X\^$m:ANdqk'II~~8"6DxMs3!e|[+:EkoИ.MxZ~bZOlgN|q Xv@~ztKoFN-½_d_pך=9K?a'08-RWxy/ tj#l:dґuB{GL:)Y䥚^; ~(x+7yY$/Vs\˴NԲ\$C#(EZ+flqh=E?MzIԃ6+Usr`*!L^R 6)E.].S,t9RfWOM4g]%c<뙃c|K̜J8)vຮLybiqH$AHjӷ6h-5Ggiu3AԊGNI":nn2L'u|iB{Mj=Yiz7B1M!0ͦ>N gȯ ȜXsyd smhp= ֔.MA/LR9&Ƥ2fo 'MH@"8{^7J}Rg(`tdӑ3slmkr(1ߦಠ/{GZᴝ9&ukIA ؇`%KhVHĵxbt:Nb{t> ÎqB`bAYPw(~|; G#r?j#VE Oe c4!9LZ8RdHdxTƚ4Yds+IЯz8a--DGxRY~]4fN&ʍԉS#2!+Y$Yy[#Q]ZF\ּ#O ely8KBҥ tJjn'A(^vAyc_C;SE 6y=i!:״lws 2J׸d)-yt r &U!EaT^ytJ -:@[!IGhmf2NxtJ9>1o})ô>] t[TgRE暘PQdrqk7+h;# f^' 3$It(/ҥ|1 ft(̌uwNuۮ4*w`h_KVθb KV>z/sA be'*#WdjE0(-Ro*\t97]o W@$mj[>Ar_k1J:14t$S^QrVI6ng,gbaoku5TF\g-hYERB;*͞im_I!"fKEqD xq~-h#dNǬR; }}&T#ސ)VgѮu@X,aXaYn峮 Gz7.$W_)¨)$pf;(@bXDQđT9EL]"{B3WzF iCI;Qara_~M0ю}$dShZhIݽL i$dD/,o%(zWoۼPb%إdhv01's^8[vxhF$@oi}Js "tD=vhg}÷WZCZȀR|FHySw?Z.T`؞Äۦ5I=@Q 6Nm4ംL!ނNi}dz~@ܙDFV%  ni We{-5A.ڍ[DG2~Jjgչyoi䣥R|hrށ "c%1TR_kݪHKf}୤#^؄ީODEݥS{"fqb=n _%-zb#Aǝ妃y賴ioо9\%50 !`Y9wc}ND4؉1p ҨxX׹f'H ޖ9c9vRYKL˟ΨE9(<([iwfZgEu,d/!q,^ =ҿ|E0Ha$54Tcy i,y`nMRF׿܀* Ǜ ݤwdɜyAfRyeR?rf"x(@ӇAUV w>&cwܛ@[O_w04dMBK.qzX>J(dY>E)\$7 2I3VG԰J9eP:O"?Иc|-O = i ^bct9m.y[>O4qN1baz4}wĥ Sj7|>o8#牤ݳv8kWR|c1Z[# |{:xO FLjuOCCF{"~ Ftk~|Kwb"&UĚj"pjVVVod `mESG뱢߽V[x,Ѿ2/աR/ʉf:VTa vYCءi;n.X4G*h(,JS2 5ۀtkcMt+& 2+3J%a$MiRwl.}^l4a𖟋$}`jϼɇզѡtޗC{ivOHF4wbx}CCSGtS79n͙|N^z.\+u'dD@3'23K]QQ>Uw&*7ZdBVu8լA iyl=/J]xY&@wcZaHm_o40/L,Z l7Cxz`BJh O?9yر&nM~W2}ksgfDiz@.jp]!(I~uuXbjۼxzy l!0P(N|J9yDmZHzHyeD;f[8ʔ݁2h#ms+ A%jMiC4uPRHKil'pP\hSf#qmy|8Иv(!'V]M`: #8+XYхІ  P_1LƧ6GuUͪ HPNiGME&`CJ]RO` os7WaiLΰ)Y ̎z|sBcw➼ŦP{9Gl^Ț݅fJt!Οrփ3.p5 i^eJM]t},q1Ja {Wiszk7?0B^ݫ.h4 0< 0g~њa2*@6:1ϵ ]Ox+~KɊ~ET/%Y1\h* xx"0ݡ rNYgRkTp^]%>$0֊حɒ%=B#ڤSi#SVr.aVŹrb  N[+qb-*^݁_8A般 z|l+|@ZCZYo-:k 5Ԅ8Wj: *)36񈗸 stt RJT0^ T#F#y)ã;:,u&lH(6ty@NgHn=G'Ô=p%b}T>OQsm" '^^^( y/u`a[x)cM5զl%/(h3U DUXalz 8+JFR/3 Ь:N|=[G)cv\~4z?Kt^L NKJ 18m3{0IM1 O_{{r>vBF=4X#aFB2Upw _-^RZ9-1Yu%dz1?Z9Dr纶ShrK2<12{/ oX{fQVAkg(lp>MZ\6a}w ;(Ag5gXc3,-P?/xK3i|bk=[]!Y30RHTD b938c藇uJ9|ux@ jW/#R ]_C9&xRe|2̅W1#RVbef)ȗ.J)^;g%iHE A 7VJʑY(v}|]| 8?|nk 68Vtvzx-ȹ] Pnљ#w휙LGwb{ r0~ǫkQrL5nB&3?'d" _Kqż$P['JПfnD)iYtZ)?69YN699X|oW|þV܅aW ] _bSqZkoH"gQ޼\0B="5ƓU_]E}MN VcUMZ )q.Hy9k֩;Oɫ#*ۙO(X-]*'%icNΧyd012鄦54 Y,e<~^  K ިg?zuc-"H#cՙhZVp?kЁWc6&M+u^Lݺ.MͫxQًr`3TPWϹL*K=> u۬5^/>KV;YښF> 9R@ȱA !mnˋڃg>=@(< xfkr)a)䴓zY WhcYʃk"odz+9\zjpN]yZ7-2q&d`X&lbgzYFΧ{yO8y0;<ޔO^D={t+CED) BR'|7\zCQW|C/ <̏tաv/܀Qɬ" ;ݢ%P,"fV$D8*;VSz" rnpZ`w~+k j+a]&4hʄH̪iSOݏ[*LjNx=!Y"}7|~E !^kXceXfM x7rF@"/-_jy.(}vAxR`%dV_T~E𘹥g[sx.͊#7*- w,I^ϊ2eD3Sy0b iЀw x:oMILɹrBJv[gnZ Ч;1J>-'X`HV жfxZApRng꒔֏a w y[-aƬ嶺.=J+@ksA\-;OG㕙su2 Ŋ/Yb~ZݢE@ hpqb `6'pr#ZClWZ|G( ,A(~sɵ~֏57͇iq*껿 1xX&9jN.#|@XA"9 bRf^S¡o&T_ $#A)EVX}af2_UpIВ*b?s6HfL3Xwi_u0vtV⺋: |#$z8\=}>r.3S,Ӧٟ5FQ#3gvҴ}p@?Ds s_HA/%c"] KHm/ˢ<ȍ3vk!HjOW3%'bf(2TlZL\NgjX^2V$6A?\Ywx3۰| l8Әg5̊:$یdÇCJ߶(I 24p^řGMc|1ۻ6Mxhk;G$Ü\D%+jKUBKZ\yxijDk;}lD炍b2iDtakڈ--cv >Lс޲2k}a:|]nt ^n 5OwGy]/R zhx'kX⚼{:v0h>ps@ R[0|~=q ϠyV)lr8}hcs*̽ѭiϋ׎{d .mY{ItZǼ jfWس[!+깎iyߥ]<_k$؍7kuy ?6%v]\RX: 2i#cխr RSavbj 4\#칟w& &q~wsat]X"D6m. i3N-!.ӊ}W >D4$L"thͰGkX]4!0e|s>HMyq#nX&" aI "k:Bqr/8Al81H Ϣ=}5LUPv4ҽ^_)lp|=`ָ$OV>SZoFV͡<y}MܨQRBsK*b-;N}ddh'#, ّ2a\VAAc!'ү'ҕ9 ˤ'2-ƪ9NI m)k[MVT8YxH)EV=T,aZd%-r^)|s5]j6 7XQP*]}W1O7əOp[3m ~V^KGk]5޵XjUb}?bY6I!-9 kGV\{=ڭF4fQyhLWRk`W:%]6FW]'c c!`g}9d_T.!M_'f#Sɵ?9 x =;O>r|xյ2JrfB!@伤AuNu]˵%_@-(llk@R,W֯zsN`2aDݩm&/jݪ=t=_>?1A6lj3gVA/'nlIu%ȄORʡuXߩ:|RH )=)7,ej_Sj[#OXzJ-,ʼnFT#nλIB+]nb3ꙧF:'ivl,tm [j)Cָ䭰#^8CmּRDk~6EĝI*o (af w֨s*(ʚ䚇(# ֠D|yN2')cLy%Fm6.Op(a >O.(|džN=˹2(5zINr}Bd9)HI9Mn3aʞsz,&wn:Αb9IpxTQ蚇SI!IVN5I4:CѨ}٦hd?}b}JNИL kWGN>h$H #jmL>QFg2"6Ug" n0a@>ͯLZe5{,:0 zlrY d:EE&!jYMI^1+j괜@4xqPWޮGFP$'c-T߃Sw1j$ 1޸̛3/F->Mfh=6[֝\͎rvhM:ZL(ͻ9A'RbW襔!MM2:nz#vk o<9f6Gd0ڙhgF;Y4L[>MDshǹ%3)Ly)K!\x`8@ɪɄJ3瞥sl1Oެ:bԐ`}HZ4q<-66AsJ;*.jZZߡZs4S\aA$a qѥG0HdQ:*j231"ބ^UPS7ޏy+xbW*M,J1m7vғޛ䘖1o;Qj?뾾RC?o]x 3c/x; {ʉ6MY;G)C{jnj~bZԨ;s8c׳5Z;|+; ONޘG\s_Ycu-;PP:;");ʋLAB=Lq?EaC3,&ДL<ܐ b Mz/΍mV$ ξ󒮶s`6 n"K}RA9=tg0}"/g ڴQX6UŪ# s˪`(|(Vmkh^lb6"{D{iȰz:?ee9d#-Goy]ÑԃҘZBl3ѽPaƼr4>RM ޯYd{4?aє< _5:4ahgM/hguS!O =O'ii̲$듙R[nDRfI /,90šP]GxQ8ޟBj.:SMl20WaFGA뮝X]ɺ//CT,i;mu9rp*"2o^dNY\NN<8>Ѳv] o:j%֌`ͦLDXʓamnN.:BXw8'HupP5ݳBU=ϛO c='ZH>[ΧÉ#`I3!O!MYirKX )Dߪ&'|XӐFuG㵑T49/Vyoӟ̭>| Ehyu nDbg#VuT-NQքi MFR˷gZSCMxLbvR5cy 8[hhczźe%3n77ȼt8+ί՜'OpORWϩ s>^@$8Lfs6]P\FO t-<-J%́9Fb4H׍rpO)*QW\c3qKO8wt}E_z WSyXuteQXG&]@C6)g1 br,2yF:D\f%`R= /lL [8V:f[E~Ӱ& n1o;jt3EЋЊqɓPyD1j$TʣL w,8k9pq"m&Iwt<;חVQ,C\o輟4t &]VTޤ)d%NL(ّGm2j:ypxFRϷ@D݊(Fe.pg0d Y/Mz9y?Wm:yY"ûng_qψ(]:wUm.ȪdLvNQڎ ĄGM嬖ɱ gSW|t8e-,3ImJ(NٝXD658 )fkQW $ֱQL}>}?X]z-hnnט]Cn4#1XOrL`5/z2](蓜H) eAERKs}@T4q3M#ȝxz8 L.;=COYT)oPAmJ~bz  ]6DCS5sz3ބ{3\XaGt.,ެr3e;80S Dc7'VTYD2J4d94 u(aCM@U J}\JmRj˿י?46qJܳJrOșxugl/<GxXOfw%4 0z6&Xod@m/&,UzbYNҋiF)Gfӯ6yH?ŬAP/~.v2%<][[ļDmt:Uup<>`L{ ru/tlxby `g XJd@i*sNu͋9R(0=Eʍeaڢ==:59e0fѝq 'mQCbgPPuR#~D49Ǥ* PsHﻲϑIro5Z ;NlgJw,tYj}nUڽ:ZM4C}g1 ژUlߖxfk6 g@.#@;[#gYsudހ"nx~\SPw܉:*k( I`<2t^EQUi kIJBZC}*R=㝦!a71,t?=A׌Un&8',ZDŜu\_Yzisr->c5A@ݙ624(~t$u8ǩȔ)FJ7ůYX_Ob{$ܤ||Rb :0{Eewar 8hL˃tw]zC&iUm>HGpcggNH2I!P4FA_!sC͉ Gwoo@t{&Y%:VxWy)+iɠU'@?F1n>!^n6'cCnRe7IcF#|_f0%DИ k{Bkq l.i`R5VVRaDg *舿zjM%T%E3W'6I=YݩneSc/ݜܮ{O<^hƍMInE &8Js+y"w&H'$љmNAPsBLJ z6} -Mya$3,Į{0Ű2 e+U@ `h!5E07sGԅ#I6dT<]h􀇫䬼f$:IW֐Gя ajƻoUkG^-lBCfĠɻ`d:\gGm-\ 95ԹiRy<r%I~⽱􋃶ྐྵxI+ZUgRcDo8ܟ`{Ӹ'w-rĭUfEI1K&1'$53pKڑuwIIS [5akcӰ&"GZ no0hc{&? Xu, ޱ[yPOtL|OdeFEK/_"Rf&껣dDXab|Nm+q,xˀ4qaʧT( hZ{[z@В)iΦL%e~{:!9踷Iӡ#kG-JӤY^lnlec JX"a΁O^Zlg`1$%' +8# }1_)9ar~5PZѐ􆫞+]d'MW nIodv6Bf{s_p9_?oI$Ck6oXwIiG=NyUc0vL [棜񋯄n^qkP=gXACZ>4Ynn-{N {nRY[P ]V QS0%!sGCKONF#BÇjql3@H^zH*N _^EJ)!؂+wϚFvXVuR(N`d? ? LbEDcLm*6!Y(˫tNܮ4]wԬǮzl7lgRe9}r窑9ULַ(ei^:_,YkAϖ h*AwD1wX nі ]^Tܘ5ln/iR>6rWQB-9S$׋TOA&},`&S$9TF:{4nK; a?O5 k[/zސwwamkxk ~F=+.uTzd"V>YLѬ?ZMFoL v5כ$kZl}oy6Zob7ŷNM-7Q{@B=b(t ;#7%W;4 tP0xĺѰzCdU;{=]$fcE\$%('n6]5׭.V,Ѯ)"g0 cy "'1>Iel;+cFv4'jՑ^5+A GNXmD]pI3O.d~^~Q \Yrn& F pYzl5vIv}#7n/2QiEE;w _XTk+WX6?·) |’Cg2Knq|5;MteɛO5Ț=f$2w{3o?cfha]%2.s_9!g@g%_y ) Ih۟48>+%~E ص׬kʓ V.c]8P)IxU*>̻O9`ܼI:*{@dh aP͘=/*x`V1`֯@8 ~}ey} LݟaWǀR5&N ~*'VRR#N}s8#k.\n]J%%4Aϐo%CEgŪlLRa;BX1tlX a#a-;$@ފ MC2w?k7\M=K]= AadX!SiV $}"s2429!]v!Qv+yyuO=ѐX|qn~+XINLR9o"PҼ! mআ&6q]g]Nƨ8&BJj2tC֗dH^^DŽƢ]H1D.TZ //;&2.w8ޓjm3x9.P8By8\띷hx4 M$F<y/`l\{o0e~'d~ՋeUD ʋҪ۞SVU鎾!c>&KyI`ѻY|~1FƔS;ng 5jqҐu5(W݄qoEJ^eWy?# !aN!k7ft|xr4*nߪ?vzN*cnC $w˒?<Z@b#>+N?#1&3~p:m] YVjM,^Rar6kf^w InYS󻻐,$T91&IhgHl48m}D)FMOZ)zb`LC!B 8l=ƴyH*`R =ߤܴ7>3wgh r4V ]MC SZ RS![̫Yש*%$g+$4P(gynPfDq>2 4oWR:G+JnP:g/ʕJŌ5}=m+( Ė=wC\;xU$i<{rF0tIʡ7DAe١:n" zaTӦbC31F~>J Ö*(ζ ^ʫ|,cu4rb#~}Hc{Cc%E2fk=# }ڔ-ipE;EwR"!jG6܍mhUqQ<2$̗]X*/x×^_"]IDaz7lma7!Dսh 5K<d|M||zVD m! ^s5;&qW^^v)ԑLi?#)WhrRWgճ Γ66U3,c艚=zU0ToMr#BXb7PΒKsm3q5i kA/{N&U-NLdhsw!:>hMV`óyLcwVJlxuVј4Hu0Լ5Y>H^cQ`_F5>=(N8r0 ^ep wuig:qX>mʱzE{J>v!IaDIP}@VO!Z%K;MR־d͚}08[Qő}zivp8{&NXA5\nz'Kfz Nhy!~@#׫)DtfVdB Hʜ{b}h\28*V%OȔh ˟ # qOYS5 @tٿKy)b}HP AphYHLt{jHMV+SlMei&aGGOY53RX6r?%wt<ι?t7;dӃƁSz"8zt{̘s֡+m</e10v7x}bwB ĐsS()u=88ļ?<øs{ [qBdKwe*+[{Ӵa辟+jU,HJqg{Nፊ4O,#$E45PX[qvA)u]?VR(iVDǥw~l(6#3ZMNz.}F\)6̮ a3X]TdNCx5PUK;> U=}gQE8G¨B <6b v1e?niCƨZJ{> 9e E>]|O0Iz]̗UHC޶om_eCsR 3n\pX;GfR6dc^?AD ɟ_IqM+ o>\IUG::%QL>_wZd? UyPXW6/5dL.E;BgΆ Gf$峞Q#C&B dP\W~{B&B_E GLqµ]żf3IX<+/ xH;4 4տ/sf5j8jBkЁoр=$V%(`K4sS%Oݑ#4hPS XFvg}Rf>g`R'Hzsy./ &n3U8οQpufDÆaK=N h D$?<ǒU $:JLh sK+NgS&=ƈO55.m) s2ga )bPmyΦbz?3:do~N܅sAw$(X'{>ȺNK5K]t3p{V!B31CވM}^xwt#|o  u~qH9*sm@4=:AgK I?% ߼.yDkGf}QWTw,mVapQOW_yW4QyjHmtk>YzRuF ަjWPU_BI9Fxr|,M FjihNu}p΂c&TnkIz!ih6 aͬNb)Ȟ IĞ#KiHQ\v@<?:9V7(Z9@+.՜xJ`m/}.q֜ k Ko(E =[{-F#d=GE2@~.("i{(wI)ʬ NW (ᵏWu]$}ѽ51(2dRߩ,h&K\%V20N/O, /_rBQbD:k߱~Nn{KiA7BqGL6l# hBAw(-xIf5іDM-'[k{koeEi Oc5Qe=>t m=Pow84Q=4m!`9YW]"A^w.b TVM18_?pTR;y_NĮnCf kJ-,ֻ.$v^ȽϦ^'$"YzRǙrqA 4:c:Y3%ů ŢrB < +erMאHhx1یYf͊]W}uy$s4/fh^X h8)4Zօk̾/Eq&PR vHxX8vSπʑJ7Ǫ% `;"{p 57/k lε\)`'S KvPӈ s[6p;$SbJAc.f"%]*AG,{y'{y\6A9(TOY/"^+x[!爗N/ 71;udZ/C>{YInL/EbQww3͝ZsNo,=S"}!ì3"P4ɌlF1leLyչ"ۡб>@TӗK^GԸ6D )&kY:mjn 13:o$.Gegr|k+:u>LRMF4|bbJ^>F_:%R9CX@5R~ HaEӡ2vڷh+%y|l"TPj8KBQR$ܽXK19 G3#i+d_~CW$dRl.נHם:V2u=i4'xst/UYK54es|>yx>0.X[ݫ}C9ÉEfmNcrnhHIa;=1c<ʡTfD֒Ci:IIrgmEY_Zf`JVu*H8nHXAGq0iF6bHz]&/ӈ,RM'Ʈ4ӊn)f+ͬ5i8|n s:R'Pa*8Qd^Я"WD9Mb'S˫w؟qwby$d9kjgtG) }K6bQIyj `ENNCXoNY"y ki$֞Z8_/AԸ,Y$6kdQKA=`f=0F< R3uZ#s]5͕℺,n sGؽ k\iI* zO& Z:֚-NVG>{'0 &K(a |i>9Cъ\yda>N\";Կ׃ͨ}CXOz2tNr^S4&kͰ?.U wtD@vkn/ {q. SlȵcuP FwrjX'&ٺpbl! 9Ժ"tRhuEpʮT2;tk)y&j#VQY1}/z_w^y?ah'ٮ"~S{M=+5įCC?k[ͺ:ɛUc 8v7Ք٣'E][gZj]er=At4> e}U_8|z%CIjB(]L|h #|x/S3w918sJ]N CX*p$6Ō'3 A٦2hr}޹oerJ=Y>G%6;3ڦñq'ȋ{{bNwzvӮm ??iAGsX5c>1\4}̓N Hom V' &=cꄌȕC=M1I`İiN9Wڛ3e͙4XjVһ xť6~6!WdI0$Ԏ{F,6" +V-SO`MFUQl櫑uh}=řC%+[>xg&SuR8df"#cjjTnx;ݞ?]j!Y n%%z>^Ђ{ ~/c׋T{2f]^zOEy^AH? (z@UOCkgR׹X ڱx67Vxs`-kdw9J&Hu*K;'{Χ_~}xtYMH3:-P챒h}Ϥt3k&>c`VV_:>-=Ssps4E7fvuF{^'܏{J4d}]=rӆ)!16tPrjpf n*3ly7 gqFv-';f˞g:[Js:bH8y.C@lO'xd-atӫһ9Y+@k{%EGnhmd8_>֛e' CLF>U={I3C=n'tzvc84dejK(u\ D 3*! ؼ`yMT/})/vw^g{;7:Ysy~Gaw77_SkԙWau'mrHN NCŶ^;(z=l\(q6Yuzſr"ՙRJ?CN7Ko;F Lչn3WTə-q͆J֦k|;jBaߜN1\ՀywxBKkkb!aYwT43I+*憯%ޢ3q|TG棼SA6'1phIyfȨγ9ZfcΦKZiOW*`HoG-.A 0늼)T&j$EGNd8 /%tCg}[Q& yiUdn^YcA wstԩk+-09a`8pǦ@2՟b֕kOPB̵U:÷HVzC>9R7"7yܸɼRF@>]DőB+2UAFt,ҝ0cOV!p;"Ҙ 4~?j1 |]NO"G'j1c@(TiEF\H{bC-tI.>x.ؼiHVGEoek^0T/6pGYq0^QIؤѲGf}~hh+ΣhڞPY_XzMǤp1}Ș\`2UO0-if#)cRC[J<(.7Oĭcˏ[.{o'ˆoJdLs o!G723ћ|DtJUHU<_Fpk QRA>GaLN_й7Ȧ:5<]=GC7fkXrqvel JB&"kJS'd]WVbP*M _SVNI՞[utO?&['(O }νqw)_g}l,{N_{n@W;1\Sg~H딙'J-te1CJ?:ÁCd'KʏGgP)n-*gꚐ9GڤڙdM݃wti ׸vΔhf2 iQJˣ[Y8DyJqOs+;8k s:J)j?:95r7;O¬}t@r0@@Acԇg`W)蔆G~AugoJ }盄r'XǟFP3<>$f!h J ,99<ń J5uhn|o<5@x0Ҳ_tfĢ=vQ̛ >2KN>Li:ӡڌvoFJ`Tɺ|! Mxƚ-^EcZ{8wBY_OnY"8U^[ɚ0ɓddO6吩CA_Uz%c+XpN\p}]O4؄ѯV1az8CkihB̞iMQ1 LrKPe8#P@y "L. ؁tvDgș";3J'TJX4RlKRͣNCí8%ʝ,R#Wn )8`c] s+)Lƻi^yN P'9CKw I"c;3Zy pubY$م&AY$v5}zLsp%덷;EL,4w<38/{O 2CIm|en.RXO(D4=oJ OmY=(0?Nŀ3V";]¼U\C M,X2j{ib=\ZޭTh{h7Pz# [̉/]Uk);!ER!)~aАCYEyӾKWxzX-w؂×X1~B C;ldӹ8itx:J 8eVhunԶA~eZA~ʄwu>Gy2j&VC:c}&n4dDK ?Dt4w]j/``s*st-hKQ {x VZ ZN]*Q4g ?Wg`#?pǐʗtb'^+ Z{M%% 42I/r.Z !4L}7*ts' "bgTC>mŌf/jy(8o 'p}V,j=A? ;9'\/8`Z w9݈en,KK\&;rT7S%R]-^h6! 2B8wpE"z,À#XJcUb'tzJO, 3-H9 O-4DVӥ!28(/;+7PS cCrÛ/2N. o]~I~P;4f8ݚ)yC-1pVyχە;μs;Kr@ǒݕU<7=.KȢ-+ q+ʫ]!#h)hf7]8[/S:pJB ԋw>u2Bs(fո\x8U#)ws ]Ew 9lO3!fsV&xGÑt%4)*뎩MBlYüQrFkЈCV1"#'݄Xol=GM|+/gF&({Zp7tJ$+ւXcR/i_<`b.8.}BQtƂC{xMf<|i|e\qҖş%4`Ĝ̇); ]wyG=/H*3=UXjM0A^kt*p8μޚ5[\γo*\sPW% _2f6QWfAH QJ =%)ܞC?*}55&`X+0t>OFfb&3L*~οK6T_1]sF %gTZ2-)xU4cOrS7YzE@dZ|f2n'rC|gﶛ*Ħl?:q F#8oDf }4[BJ}[ I {]+$Oh콷|xٲn;{Z$vbCjh02L[m'x(@̜y=imY@8TV=p-Xv鉥̕+4{ߣab3Ê#fR#YV8D,>vO kk[eJq&B95QS&L=>75ܽգ04)8{ ~3+?t`M>K6cT_4:rgmuD>3u"jiy%G!mhlWeg pQFχAѫ .⒆ {wjy!AryO5ΎdfLd>~AY!;(E>9)&.j.?y,Bn#J'X".hrv߹%fu7{D/3 [$U֕9 r,8(AIG|w \=< ?[_&׆fi4҈yޢVn]SkabL(2PT O^8]RX=TO =+H>ʌfOjeS'.5VQzuio\ N(` leA Cih_L'8 / yOP\I(8O_s͞gK/X8dP_O97GW00\':M _ )M*5ZAG7Ur^,)e[} |B8* |jz3 8f"A.W'Czo^0類KOob#J:u qZrkDqΜκo-Wd~QGΑ 8YϦmMC@B#K1Yqb&^*λa  x٤)o:ЦL>'{YPNˡ9Աd3wN^YH}L~捛630`N%dhx^F mgZWu~n)LL=N,Dtst1ܘrƔ85DSMaIVA769]sٙzoȯkM|wBslw}F> #d׳ϊoüj\Cy\~?٬\|E z+@ic*z4k^9 kpX%hEorƏ[[2;5ў/mRED>PԖ3W cIڮKلg&<@bhL~~$Cv^FVzyhûo?x!o\7YZC6gr``:tRT~c/acbUy F6IVphg` }qqEfe-x9؃r&ӡN3~ڸ(^uu?y O+CRϏCxEc13q`JG{T>N((. r]B@>XT>O$ 0 k$g5 \=[\d|ss:h0}6:YStt%eZ !MO<-:rYdI^T>BԛX&=Vofw_BM{b#c0%$cZB|SJ"L9iu~QؑIl(c@~fKs<;u\cuIUɸN;*ό_k\LI,Ba\xcZr7 :IWv869bsSNa]VODTG ;Lͫ7[։iDbhK$ s)ώ9|TqLdpTy\qVrztK/XCNvYk5] օ?wy4g`ZwvIa :ʚ.9`߆ -VYTƖg^:$.'~52پl2,;4 D)) x9I3sd̘eʜ8ٛHKd\ӮJ̘9μMeĚ3S(lFH@ q| n s*Ww7-6Q, od5&X<ŽG>!bB=8,6&ĘaxU/P0c3Q?Lp/; o"!@4=t HH+gS6ϒj'͡yҹglXBU\ pxjRݘnJ,5@f>9+0&Nf*6Tv6q +FE+){wu-$r6ëvW)]kֲ]ﮁIKh YsH$IMi4X]xV ;%螂%8=02'ޥ}(T%s=ߙ%?}oNh'uiC8=̋LQw ;PjVkuM뵧@;%АFqwkt4`8^\^;Q cWq|棞+V+""R<4);l>cm#EJ'kL2ɸ""!:yzB}Ic}9DAz"~j@ш&ϩ*Nq?osb*r6:=5z9js$`fPF ?:Sjqf}8+o_XaE ,DO ّCQ"[R-:+iltw7~2#=q(&&<3LVGFB^k7c <0֔&O=s,{fIF0OsZjgP`ZFP7>8l{iKkּHil\eyz($SGԆݨ v`@x6Ba7/+L(Kc 1CsQbD bգw=:VG7UA )d2U#XbZ9EP(ʸ2$:kCܭy*3`;c+bm (mɶT]jm'WݟD.4:RiťI1Z̭rGPȞFv ޣhV꩞&bsFPdvVC_j0#MYH6%nW|1i6Y/L+$4D)\ ì]b ]>Qə eY>nx؍K1iW_XsEvTgAm'X8ZMEG={|zEӹO704D}TM/:?}4Y銲"Ͻyޥh?HZ@@#>fZ*͙g3j$范DAHޱ18qY{C!;B-YodƁ17Mᘽ Wt&Y|vZ<vKNnPDQDL`V6a+!.4w9=kc.*OϭCfe |?!OC7nf>q-Wiz6um7" 95vZ|PshGM+Zc1@b ».&F{^v t^_#3܇:>=#R!`*-t?DICw87^9OK^$;iά @X/Qi:b?~1(f528P\Jr{SbχY5x$A>W͹!wjQ<}?6)sxߕϣ7objZ¥*Pk s:=oNBCKYy"({p-Km>i}؇H[0kG[va%Rц L-ʫ=NM4Д WVԘz)b]䧂%GjzVn()ߠ8NTGklbSAEKk3͍jxJ_xRth\( -J8/WķRw(5g~ԬԵEXjK&\,^Aq&{n eEyeQX7E2*`?7ΛJ!n1=U}&XFyw`ZtGm%oHORz=Yѥ@v4{P-`?f=dzYS&+YuP}N*fM<]kӋuXZ&mo?1^96!-Û-^0IQ#-ॢGH& =FBT 1u$Iz|1y1]RFCbhN@18oj__f;hTvug8ٝ]G<7$_f5 ǦXz͗$a-=I/1dzDi)(ZU;7_lX *zUJdMmg/ h$8{\u/.Rெx/kjMT_( `L3o,u"DFD +(sўh?Ufx?YٵbW*PI`(*7ח@bm/K^]M_.=ܵLV^hbE bs-7M,!=t+b4jr]οpwґ7k{,k0,5oX }* }y.gSG7D7|=1k@5~) gg\Ķ˼H D>#)i^znԩBu Us0ڜΪ]mKKmw2+BҴIS݋a6&<D? )Ҽz@L40y|5m@N;$s:ޠs.'o8KJ*2o s6ZUCYU%=?!~͖xRdTe8'3ueW); )ӨK l(lډS ,*2 P}\a~S޻&|`= a=ATe9횟>gmn@J?IU}1mzZ` :!3s([@Y&#{ɗ+0곦zya:_ yg;#ߩnp oiVUhrnz`+(G_0vk,na,kM5HkV_`0c6)NԢ -bFV:J26 IlӞXӲz&¾6$EYBpƃ[>|+YYsQ` HFA cs}矉toPm+ vR}<⍰vBtX!s8ZQC hq-wLL]e6%1R>4v:(dC^]ECweZ (˷$|sƝ8;_kMGw4fX {r΀1肾+O+ӟЩGŢ9_o/ NA7F#k|ek|zt+i"^j@4ApOy D:^5[֔ݫ{eO%BңJt0kI#.:.c4p=m:= ݛЎ -IY?~1 cDԔs-w}ډ?Ê8+S6^B\Cx}TleyO;TYv}%oՐUt75Pqpz%΅?H%dF\z>y-c/X:m2gi 4f;]ܭO⩴B&e#UaAaR:qѵcYt>\%"1z7+ev԰%@q8TiYlh&5-]cLgJ v",qX{ _U E:Pf*$$C n`iXG|d3N }ܼIH\pVD:e=KNKy,5`O_R"n-b5t5 (*R9'/.E2Kj`͉)@D-y$t_vgEteuƙ{h)1"vE 0JzK5;_v_Cl:+X 5v {0b'HٻƂ`x̱I*poP:ߜ( kw/Ҿ S3`ҋ֚Ii&8uWR'K~ )BSSD$M_5ĂO3ړ/{̴όZ?ښ& _*"7,n&tC/vf:}1֦Z&tŗpꮻ9]v79s9{A^!eP2jspk'`^9؂^R U})R=nxv5fVUz$T:}m-Rv?pp@C3p~p*SNmxx' `1#7y& ;9溙Gq^5]5Ȑd<FrZAKcń%'ftL;7 l4W~yԃ׳ VAa(qyY@ڻXuFv5Qj4jZ\*xEz{>uFl\hکپLgns7;L:W9*'WɺάSW7Ma/Z7bhfA vFʴnIYIAdIaЁ~dU\!#!MW[d~AG.6ҷ7p?)m g^E#e@r4w/`&RAvKIs(tK)I^Q*89pk͂@ٚ1t"C [rLad6Eq%QQEF&|WeqS h˻2 B:7V{ 1պh.bǮ: gm?\j^xUY?-xnZ$=T;[2;R*860Wg3>{n]8o~ '@5NyUeUXɳpkn=WS$p'S {Q>3FeJnQVFZ9ħ/a껠GB0\V bvsqyI 8^OehT|n }Yc{N`r, YTn++ds7iI3DaJQ^@J3~{`"~~-zFUt?ie TY׏ ϭ sdOt?BM{tSJtϧsv)u›,۳2><~)a/`@okZR(h'MP=oV[friJu8q^5-%>$ج6YUwܥɑϡ0anio]hLcϩ|npt7$5÷H0maAhiY?7f9޼jBLn2<7epoiBF-O&UGr{ I+{=y@J"adԐȊ,̍*R〧@(|׊8Q=3 LAzZz*Pi`:ET=τx㫫d̬hTy:K4cv~ɆKU=c2 Ox7 ʆ8JytI2hǹuxIko-(>=.U)"+kg+Z$Y{>OXtFvI mIgdK$E*2aΆ5H]#7)_k`ZϥVDd$fi,Kb'>&X61k#tnrGz'. YO'Bg SĹA4OU@݆gn"ƿTr2A|'Yc\ F7"M԰b#/c;O^BGfsTr= bNaV4C\S"+E5Hr`meJ3/1,fH :ʼРv]G+U>24^;]6AO'w|o-]|Mi)oGЋ|Ϫzy8M; o1 )"XuoZp2[`eY%Ir G&5U-['.l~K3E[2/2e%9#FӸTXH |rs)1 VyZ#G7fM*fA>о=Pƅ|&mB-&H;T臟~'\({ʨ4'݄(VJt((~bM\7{ˀmaNOyYZ2 yǡF~<]`PQp1)n}9l'vf=͚;IKo8d$TO]| ܲ-խM;7iƠ ˪M% _w"z0Ɵ \*ǣl{ʆ)<|}zx7XH+x$_'#)83b)wa v4'Cmt3+Z?y%*}m^N8uwȥOE7 ֋EjP~=frH^yH$ۅ0'/P5s"1·w2Td~ga5_ClF]=hf19 s 6X<.=P&~J-ЦuBPT:(;z %\g3k+>vs"J|h$+d-"Ĕ)IlgixDcZSY$\(v$!ywqkEV^$5Ȼc-N&-9~~q'S@*c*f`RۣJ f5ɿ;H{Xv#/_CޝE{5Yv1To%HR@&xR~Ҁ)]VZ< Ezݼ1&=28!)C?ןƻG &H Ag{0D18pay`9{_i=g3_>7\xe4;WM^zIu$YG820}4۩BoY1J6 Aos1︮LYd]#,tGҒlS[hZ ը-g 0jf:ɜttٞt2q>.$]ķ@4rh ,ᣬI 3U;AW @CRSpЍE2ӚMpևT4(A? [X=ρZ yAx'x#urJ6m2vQ\A>{A&8~Y-*#<7M1I {N8.хL^vEs8zI{3Kt,[ lrTz4#)B.xes?7:rqrEh\j:+%$u >Ҳ;K@yxK/o%kAqZN ĞBuC,m'\"l}1ʷA=Z7(:8_uGN:*O 06 0J ^eFL<9qPv%EDK2J+Pxe[[ZFuj_g<~!/54IP~Q| p ^ƓZF'bjߪ[˷[&/`6tBל;P㛒gKXϧ^%JRA.xqkY+n[ill^Zs? 'HcSw:Ex8GeQ+* 8kuϓQA },oMŘ4 LMwTLa::V='֙xBh!ҷzx L5оL R5(kO G%M|,wHC{$P}  E֞y*f$Xch%i3aIߧ\C Ig tQqq>8hr>ul^W+&=ì^Pjd!+DPuN4>* 7~C8sEg 떆n >ryygOI➏s> [jQN'X3\蕰:Èw0DA rXANE&O1 z^ЧɤUr饦w>d.#?d=BӴހ 7usS䦲vs ERCGK{ o V&l1WJibSY3פg@t! Sɟ!K(8`/8*Syqp6[Azr :K.Q2U2exyfnċtY67g5'ު?iBH6>f I/KyPuSؼsCmiZ uG餗|qO|,9x6Z#Ǣ'Ӿ-x ŭ?~߷yXI&ku>bHG-Fu-ca{Vߏ4(dB,نôi*2ĥ'sDXo\ d)O;AZɿ-.G+plsGGوOϻQ(Euߋtw*ov/[A6TBVhHeS0g]ONnK%s֜c-}rlH9ƿI9nl-W?7i۹:qC'VjLm*-4vq6 qdX]ֽ4v_o0: u_T{*nܴb=S@*ItLZvjaj ocEYBzdtޣNMK/XثM ~vwj+$:j싉*yV@%K1JXlQ; u/)DttN@8Oh0Dv+o />eyyz;NGN2{dP츙&+Z MږYt`S|?Ai9דˇ%f5og5c1 {=f=)syL0IDė0s 9ɗ>)Q2u5m=)[cvźVc2z#8T($4mVFɤbNE<\doN`}TdPҘ^WY-qUy{; | "(eh3Ct"NS̻ۜvکs9eTHփR>AJ>"+qJ®gtE5U/E}׶fm a?vM t0GsF`nV`ur݇҄ C hʢ/s1YƧ`M&)m83t\~8"?`=Yǧ4*'^v0"}L 3[#Y0T5}e@^'!L|&D؎Fч Kn(y`G("Hᠵ4 `H ֫ԋ4~hQ5gư5h9s|B JjE$?^$Tz%{=0EWhX3sFPm!HkDy'8$rwbQޒwOxV L.zm}-BEg]v p5 fw,zBy@XZs`{NR|u԰ ~?"`@ntaEK` 3X$~u\(ͅga;I/lHnx#A!ز=%3P99vLWS/݁zn+S4BH +J@T*Z/<} 2_8İ\ τi׺+kn'B^v*5v5lfu?{kNS23Ө띯'`hTs$ y=Q=C2CB +z?r-8m$Ĵ|83=Cr6Co?^dLz:t^6_7֫Uw0QhnW,;oK\o&]$|`Ԯk0F7v3+B#Zvv{O1#8kx BVjKڏ+٦ۑm9 S+ 8SvjM7d q:\즞pq^5(|sӼq 6e-5iʭ[xwHt2 y?A/D0J|pO_{Yx!;Yy$ j~#U.d os7\yEB 6 o@o[{$g.N.ӡ&vo"$!:N;)w󃞞yxk`+`4y7?7\sn#A UH@TECk6G*|3£ qOЏJW"";m'F 75t'?uG xb(%*fH bxx |Z'|4E&GG) 'ati yܰ[ώ&baj<.F=#z@d6\Wݬf~^s%jbj;MmzKT Kw!fF//jݏ 5@fI҈K#)Y wܚΛ[@]jŵ+h }$á" '_vQy^S-Le(iEqg9`#s@Ƿs_1QYxXlMXf>9|i*~d_Q$-)ʝL~`1>kNY`y?a;xG`e5 wSN[]J) o*͛秕E"7U(Oy_r #[tw^ 3!$V 6;Jd33l adZ\|8V~V/.R9\!h8D9e$4j$=Q-[nlN`"Pc6E\-sR l;B6pN`Tٟ6Q-xbz.Z :mA -^s+xgwmty p< E7i_(#XaabVz`V^*/j6x2#$DqgUh( Nf((vc͉r/JnMAjҨ ЛoeP %+VpXD iV(j}hxOft"6rE>8mTU˪(OC#sf-CB\GOx̑NSxGEO{Rr^͌TdXju9Oq{F^=~8A=8SbzbBoz>ڬbֱH:QE71O])3zo|d [@M/xuKt-r;)q`'D9EkNhFG.SjLAM ZJ{ٜiQ:>nG'MZ Ξ Lpy {v.9Qbr.r: iLBcbIHeyZ0'0o*#^37xWxWvҾf}"D]>3<q$k3)LvqxS5V,~ ^_-HS[h/:.ѷ KbjcBZLwTdwC;33v}}(@,!J<3'-Q"dX\c/&gp3)"74^_؜y O`u b !T:2sM{;(lET +6QcA+\GwSZ R٨Qeiȑ²[^2urufq,le6=="aNYhN@pgJgG kucQ"s k7*Pr6P߱A~tt <e5WsT3;|@+Q*Eeܷmӫ j0lb]"lVxm ~>(!R0y>$h-'W$8Vʮdf+㕈%M(6ùk&/- 9un1%g㎆̚Յy k߱' ;διeWx~Sq(mi4T71rfXs:=s<&y*Ņc2]ҁfCZ vAp/hAkB@*Gf] CJ*4oSb*|>M=@K/=^]\KވT}VB2Ҕ"#5#MYȀLq3Tnќ(tQ^t`OܻШe/y zJM7\μ RM%2Ƣc=oM9o\$A >7t?EЖ~nm8yGpD?<6L֤L$TB Y,eجKĢ^ ^ѻSӦca#}BA+Ҟ:H= zt ײ4dJ Nx&u숙V}W2jX3$;#dz:Cծ:IwԠ !^9Nx tzqϗ򇜀 ~D7t!/$JzMOb#L49~[Mi}|1'9&1k ҎhPxCW+s}{K/)wQCp[b}y쑫pד4^*?I*iҡ} pYD~K^ʦ /3B^c9& ;C̥9sG% npiŹ){y u(+X 穂+4$<.;y*Taf, kyV/o~: @y;؎B 4 F=*vhb¬)tGgSjUd=m@sšE{ˎf:׹&X^@JЬpLz 8 FLfh*z07PI xz9H 4oK".ŅkBOG|;Y9[//S֟B Doѻuhz ;0..R󌚚`~uR9C/u'@2>vw~ƻn0.xGf5=Kl\TVJ҉yVӞ&ƽe,< <1RK愺re52KhާN$ M`k܁\+S:a =vZGȈwB{]${pX* ᚂΉd0p,u/Bs6}zC_ؼ` %ㇳrq%;FV83εbubPseXQ>ݍA+H3qq֛=-CAxΓ{1 GlPRQi[޾t|ʈS,P+S9kC.XT'ԠT MkLq+ҩXk^ZrP /&]z )c)+66J[&빌^JRoFG>+ɺk>x Y`L2!%JR&~iP E#5HngEy,]XJ v3rw| Ngd>hrx0O Ԍ̙AXёOOsoK\dG%X n 9*q"QJ}^|n0 <+ I,FP+oKcop@QL$$Io_;;"P8S;RKz' VV3Yl -ujTfVWhգ97 v尡O0#)NŶAO3 wm f!A};'hl]!\e(|z }JVZI>C{&3wnQ1^vrasXښ~p(C(zB{+7(&9ڳ41~%ΣdneDz&N aRQz!rV̐R7enXs5#7 u|àvYQCM".kWGoyÔM5!R 5p.OTJ ֜.ِ{wiÒ{F.M;@cҰFEobb |ȵ`{?9.WTtֆ1gr}%|_)#7eYEy0,j3C /SOcvgshk HYaqy t^)yu H)Q#R~3bde&)]OgGOJ=zs++LUFQ+>:<9)>:60u14XI!l'LUEm pO!ε\ #~r@1.0ff+0{ eTKڽhZk65+vM̵5%?35n9MXMft Ȭ_wQ 4h0SW1țT{/[$}Kd&# #s=9zaM%uDBp1x6bSRl%+ɎjXx>[UFOghK0-/*n_iCVp9 0@)'wA47Д#^5<;q& @+C/uC2ޙ%ZOo6Ciƚ5SJodwDy&8Qf sq*$i_s}vuT<}ڂD TK7T.gO+p0}i椫!DK8w gt'=c*X^+$(}H;#+X5AW$t~mZ#>uC|V?\̉[ֽ$};' g+QV.N tR\=:ep) ҷy?o1%dY%}og .}*x ,j@:tC-*Zv40DsCTlO*C{3 EaO X8paD$ivI[tWPV&==TfRrX`=TPhڅ0ل ׆i]yB\[y{v@=h4?9sN)Vw;·S(,Ò .O(وd&L%YeoDƚ*GS& 9@6Ś0) SY4R XÆ'OwF(KxBH:oN i=|dFpL*M7p7lGoO\鬀9ovRg|2orT<]aRaG8X='M =dSn48YAzkz_HFlh+fAz1–Q0 sH3 FQ@ [W ̝zNgnqޮ߽H_lā6kNRyBeZ3ke-3"t誄]'73m:hCw)yqVE?ua qՎ*"V/}ț$>۱}IHp*7+7(`ѴP;Go~/–9ϟ98"21s50 32բTh {+n3$$CתNTs.2e]i,'en0k7,^W 6CtC6)qKܹ\)M&nrhǯRFKd$69h%o`׉-F&~Cz ,z8(hP&%W"E-ħ隩0ۗLN*.Xtpͫfyl8(0t"(2S=CWӯGH͹8N =Z@N߀2Ŝz&=%XZFNف,o Mb({ΙyĔ:䠂}qyOS cWQy鎲-0EUnlC\@!"a3*B!IlF5om3!~ut\h{c5kA윹^!- WIVhJ^NE?|nx4^+X5®gٽ݁á?C 9G sڷc(tIXuGО%íZSKYdW{O)˹a؆hd.0s|wX}-^8+,&R"#3 ǎBdDl pu1̓/H=yQn>k|)ɷj 0mjXMa+}JcWwLCT6o7W9yöZ^m =X$JbOeb@yTR)no-l5x_əH2EW=aF:Z2̺B}b|=.Y?z0̕m`)wjnFg9ͳmkig!Q`/e f'<O8Ӏę™#ؿBn^z'~1Vm%∣}:7@XSy8:(^ej1L#]jFD'4@ɾ7Htz44WGo3HCXc婭X OJjń$v c-6z;PsùƃZM1ze/@g?ZGM|.N(©r0hn5)@v;3;,!IPSle[xO@~Bj@!ޛ*@:Xurֲ8Ug3Bh8 J.fy\ze~ ߩ7oδTs?!K?JuaEҁAuqXqn{ ';?o㶦,++}W0)gZOkX:A'ef#@tGB;:'ҬEK2dAp' rvE7ɶFbMZI:?sfipWI`cSCfcpvI΄.IØM2՘R4+C6Nr<<Ɵ}A ^\:,9wfdw=O n}k]g]G[^3swugm)Eť>!ExEuSI$9n8{ =l8-0888j7jU-??OmmHÿ.r0y!Tj "bW$Zm({5c9`VCьO>754H10MxNQdgwjPfr_t x~K-M\m"?g^)jƿ/> 2[MRلG(JZY,X K*`&}W햾~s ywu/41^MF8pKC~4CO4f* thQgoY% ֫?9zҀ k>L8,,ݕIN)bd*Ü /GF[ϰqp4lȔނjV:u{FVYZ*=tDZ6\P8qO& wӖJґH?~+#4{"oOUJN'J3:"2.fc=74ۡ w^_琿Ι*'x9р%nMGw@d=e(饡70nFouPw$yu:xdVLF JU!-][-7RwFDsx{:Wx`-CiP9Í#ߥoROq9REsZz~PLbnACO٧R{5{.Y)Pd$a1ȫo_nN+0,EM KvCbН huef8X M@ftdfn|r~Bq$y?ps_SsHbDPǂWeaepZs96 kpyڦ Uњ-*1{@Ѹ)] sҢXZ9 ߧ74`:tpޛfPIϭrV"WgB&;`]&URz4:b3sj阽Lo$9M|?%+"UEX= Z21dIfb(x.&G[ ##uKMy3O-vaѲnz37[e~ggBw5DU.|މyfnݠ$ PG_J^;XXJ};/H&^khD+Ǻ)ӆ %w>W! 9Cu07}̯܄h,ux?D3QGsnP8GTdƣ'pyVy)P:+a"Ϣ92 ^4;R.u~fM8t/ɕ2ao@<6JVvL/">|7t|xg TOq?WlPLjaھ֦۬ͫm}j\%ByPO xIm]֕ &/4P[ HKܧRHac퇻7HY 2o:7!ޖ=Xa.ey[&\4;ay%9)?? om|Iɱю6X{n8^ xX)>4F#ZUn:ND֞M.>k8/,#돬 Ƒ)@f4 R'.2}AQ4%|#Y^'i&Y'Xzc4ĢK;FvwȂy*pZ=U28ḣEc֫TE ֕ƌb 9ZOb܄{6OqK{!R5UI|A\t)" gP+|ot^LX'.,Mg@ e1kIyO[3|gcWb=u>qlTNnBkݕ2 7w 3>򢣎72az0r'Cd.6_Bx14Rb:\V-)hhr~^.a9L0|Sj ؇'u^+"t[.W]dIﳫy='bX6l5{QRէu>9㫯i2Q%b; <7!ljO:cQXC; sޛ2=hz?e.ߌR]z |%}`9IÉt'4I-ATtxLrXT^(Zoffɀb i'`2olq-.3fv9UeLyV_(7"rX4% :!Ā#5[iCk黾 P~C$ !MgWqh"QTU_wHQ>ªJ.w:wޢb'G0'y~9kퟭ?\J>Qt Pl!piĊtEOh[S?R9걾!8 #&IW& ^~ѩa^T^ ZiP)%n#0`JtchC)IA4̐Yla_NL(>$;8S6<|5*5:OM];o;MܮiVW*Iw:UM0+"i!ZgAazoHi x:rzqۂ"#,g|a2qZ&Ͱ$o4= z%8&*FqgܟOr#"g%MQ!B}$?G"Ƴq7Йj+9sML4+նicy38>y :Co =KL`4^h$>SzyjT]0)wuz1#s.-sBMAq;R ZplOV ~67S6w>EG15@~XBO`ze9-NĠ!-%i7#݆cKJ^96\8}CXZ(kDAyh&1UHhȔxYD*tJ 㴗/Yu&T(D *F !Ҿ `/˝U[&=/[ɸ'T]q=zÛwsnᆟÜsj(VmJ<@Q)_i_Lxyb?, DBt; 3S>D^-摙8yL$p{3B]{Kc&EG:4D ?J*Ջ{I?矜竏Ӎ\dSLӘeM5;;[ͦ"%xO p"ۉkC#o}V[zG98#ov"y1b+Дzd.2j]odmsu/E\ebmiiZ(O-X 1 9k/ӠqsvL+]\5d_ @v L7y44yf'('4;cQisIJF;oFet)w"+=(Nto.G v\+ -ug|#+DcuqX_7Kou"a*u9 o+N6BvKO,eUu-KyfXxw!1(ApHi8W:]tǦFK#bhBAOAt#A븰*Fv,7ZӅ,|.K`8Nmv^/XEeR,FRӡkkg7n]vx}aaSVZHQ0B2ѽS;ԗTCӂぬZ/ 2]nn!㠬Z|O-H=x. 7'd0,4GBݾ(&N3UOWG S^OVP2f3QpV.҉O(gcLw6 K?OUȔH`u'[2vN=k'~c4Uo}==d^j@LfkD|>n^tpC+<+`X, J%vC՛BKDԉrE*{7OoB^TcEZۧl5j;m@6nqW(A 猵qj&eW9_>3G83Ǽ:sΙ#Jzj'pI5Gj@b̀XS:-rd@e}s븕8v3ٞ]lGCT)-JAA8tNJYt-Ou7j 젛+FӵQ ޅ7wSoKc\B)0$H?8od" SrbD)loKCCisvqU6 QJ3>Dep#7LHD.e}e>A;yK?7p`*ezZ3 m_{@F_b?aCɰB)ۺȬ?fC)B7C=JȩS)|RqN5{koz{><_`vqrtѤR6{wߘ.x݅=>a;r{>hUtxxx1d8sK;l *Uh ,Ι#08"%OAqR/+_aB~q]Ak_2iqM,!/'zk +q1tq_~'ӸA8Ke8A-^8?mʻp-#)gO6RqT66ιܾ;P3c3ގD<6c"''50J r˩Z|ĵ2_3m:kwzceGGO~ss`[&˵E} s~u@;y_yCd2 `b*lǣ J%v"z K*/=srF <˛\eJXB7a'n̩vkDt7дxԙRbڔTq:L˷``2E ^&ǙjyN0V]7z3x5EcW_/R)fXKO Z[>K^G'D<t,e4W.]Bs ̳Ngn:ŰvN4_?Q#B .|t;N^:s͏s5wus,}`Q&fwvLRN!LJRRO7LsJr$qfc׺RnІNSX2F̫#P p =rq>A>tDfbZ|y_PV[tG_X)=btOh^C=Dn+?twO1nEDfxĬBU>W^YzG?Hʟ(p z^AjJWL:u>W+&:"Amc6[E'gev/Mܔ2`oC}B5&svzQV+:ܡrjG=m$d,3LZ& W#W~d ?)M =.fSƹL)~-r ]AQλN-SP(j_]52"}=)Vc<7Npԇuu 7G3KM0d(6t(Z>Ң3OW͒Қ4Dޚ e*?x7rт{~A`t-1te^tiv0ߙvORNRb= B 4ZM+;blCv~;C\躬Ѭ4صc镹#o\tjc*,4ب]U^Fu0N se߀ԡIM/>VQ^&`+}H} 0$ʩB#{o 3MVl\H]`wn)Ҭ3Y^#nj7t(z Q ߂6j& EO2ipK\_(izil}CsʑͭT$ N-ǦrP,&')N߁C `G*%JsY`^1%!:sC8M8 *aU͕ D)]l,efy_+ G>!eHB4Ghǧز6GFŊyz\g^p#)ґc\ڹΥʼnd RZu)FD39'f:s-4YfpZ?ѶZa􃉞[{^l',.v=}oNPʞli/*!,~ϭu'^K_Do1OL(Nj0"8Ѥ-8߼MZ*mn>(`7L7kc=@bqDԟu]R 3x8E%4}PVԾ].m+Xؔ/ɏd0$EIZzLs"Z?9?pz: dʹXbY[j/|ct[lG+!Q><awfmT*k"8enpoTuP ͵N. ^V!L%ڊ/.s@ %)p3p]@8&R[P_̕OȈ>! .~k4pPhܩPx `9â3se`Ez; b#W#Baag(d}_nSI$T뤶cO}R#lwM1(sڻGF(EH)\EhcIǹCo,m*&-d'Lv?S~I&Ak꛻)O G'hpt:/i!I$X }k 8:sBIʰp"Tw=iubz|P[ q dxtKT.=JPd~rUBuW \ZEj;mNkaD#PR|;`O79N X7m! :.t$; 8+H?u`uP'ǹt@oJPOLV>odZHሔJJ9FY8Jm~tOV"'=-b˝Rxhhs]?.:E8~3T",WGEX)zpPˆx] ^H[%at'W!kun}[P7WTaJQig"ժS>P&WVVm^bbQysLGL٨>l!E9A6r(qKe%We %XyN@AP/Ncm36Ri3`6 \_X5S9G{TE(X1.y5}ieBF )G}(DPXeKxg퍣wLG%g:&'P^\בwHrKq~,[| = g5^_P^L3[>u$\]2qOU Ùz9`JUҼ zpu ɩW:m$=42&O066)% rл4m'=ԽN8 gDP^t)f~UE(7OӋ64řWe /kh̻w2bTʉJ IK|/獤3[n,%xTܴ0A**x>v,&MR3/EV2|z>WPJKkpN,y")wL[H)ŴzceGCHhmDuz:2d,(!f^ PWW6&wɝ~/!L\p6,C\ ($DR&ʇ.o[hZzF5Y{$(-65\Y1={zbEoTr|Bc3@ki%T}qnW6u8M>ʹl=XwJ{*+IK1+jLE \6+T4&=86J '6 {ţWxg5ʩW.jjDzpY)\<'S~F dU"[#t ˰,'|UI{rtbvQqlrEyD~-⇖\=!zS]fbP{>3 ڰy(Q+3S&trJ-Sҷ)sl]4бz~$}O V4rfT$1,%%B\L*.&?uxB -q%r*ю i$NƔEhXz2+:<[:x~kX I/1jS{*D8*l^]l$,f7 +)K]ZJ0:<|I|"8>e/)r3/i<@.`gW;cB:jB Z| \xj4O;?ཌྷzh@q{ӋeWpz.tuw9^ LGoO2{=ŀ>3GL߼gnf: ̺#Q 'F4/T5GӻBǫ~ N_`K<_02Y KXBp9wRAu{_-zםńɓ݃-#FVivPH}Ј~Bv@e'80ރss,_(q՘fq!gS/3{Wy.0Z@/Q0N毸޷$)ׅȧ1^ڽ"4ppA[Ov&7>klRn}aV;L?/үRpTv)ƘHPjB[.IPvA~(>bC(0 >ÅCquCL>V@!+_ŸN>*8(tn c)qQ>I}q0ȧt+ b91ѽS`)JW'T4QEWV &[4u8dP--/β gȅ9۵o>7w_ٱTRiG _,ݷuZ2^0xo_7s;EN6qyhc (n} PHh'ah7't"ILJ=]U3RcF\z3sR4 5sF,+pՅ'rpiAu_  1bb1|G_tՌeߦ$!RNc&Qx}I] lN,|w(`gh )ANDe i+SEpb'~i⾯`xGqq#*f6y"9a>p#kuA͹#J1~jm2'ӗ֭9?o%RQA pGNX-,bTӠN\gBWJ|69ԚsO&Npg[-WaNRpTL(/3zF>xWAUD;Q@ͤ -Dr-0!/,WS(r1Q~}1(M@'3McCPhAU1@i?bzXӓI 9j1vUT "3sts4~7"Ky୔I .%Q1(ǞڼiZ;-kM]52@=>DFV]ertůJpO#Gz U/N+z)S}הnjQU#y[Ky1(=}0o0yI&UX)sh2*뮏eRĴJ787dZ8WTSJ?@!'"Nɪf%{1&2nt'2ԢWJ=ÖɢEYUI#W+ʑeYtG6w`AJ];"f;%B>cµԘо9#+5i8]p- g)T练;"`oY\}8/fP)91jOYy(>,K3UQP1k޵g=_ /}-tAOIJNghbOѓH&gꐡpVqHLzI;áp!R(uO`~c~ k-AIܯ|ڟ%#ؠNQ|cIV}ZTgN-ubq 'oj~Od7hy 8'R^/T"qѫ{",R*=%>8cf.uf%PyQ4T G fj>+?@-F&աm% 3KF%tQybS)zP!K9y6lc#v__ B&$rz-+T^x<lbt?1GW h4?_T7GxMb"3zwKK 𰪬kܻY΍EX%ZGC>:NfTM79Sj/Ehᖏ=%|P@~Se&*x;sf^Ɨe-Uo / |X'u6UX3^vEUt4zQY] ⊌Suz8$pxqb 6ŻHt)y#e?vK>`ΫEz(EpsOmx)o yf+ndFX*B 7HBEWM"Ib ߰rb%BaKw~,2ZLWM|>4,8~͜/?lސ T q\"uU^>PG p 'MʺbW Wx\יXePT5bԴeǁ[C~NT:W)/n&lLՄ_雷PxO4S?Ȇ(D"NL2;z'+D Ar'<8SysӼR[ΞR,1se*UqqCI c$H/| uXhȵ>[u[pMW} ehs]EqS3j6M4y0:iц>PCHE'u}CnqzӜͽ2i1,<Nqf D)[ xNU:JB i--{hh||3%k9t{NT!{[N\ U$$'0b͹CmOH̎PohYJS<_Jovk B`iNގ\զH9,E5(µ=zĬ|R\:mHCu"q3֡1 F'TMK3F<gD3#]'e@PV*FYoD gW8E! %G<[/:7 ,ejKI5Pc_ nt7dyItӿApqW_;/08=g97X|/!`_ܭBmGc;bl8׈V^~< 麬)EMS+{& p֙ZȅL%gL8 KvaHi)փMyhyD: x's~98_0H1VbVk&B }aȏm5gΕi(GUwt#MP^= ﲙ-KIVיEv2O{*ᰪgKSٝx\3⍲1+=5p Aֽ:@#pqjz{}' M gA"\x 0jfոTX/zzbê/V u(y:mx4KMO~;I*64tsz&s`3]N2o1aϳN/#\@5s%D7f77uSʫUUu/H+_6ιU:ppcŅs],d[!X ٠Ӌ$qZ$݋Lrn!~;XM٣52GKË}V;T Pu޳tmq2NL='նdKtt geƝ̀sֆKz?:ÁtIfnA 9:uiz-ܞLA8S)dW>T5JTaJc#-u5@c8ҽKi:7F#8kP놪p[fn<4`eҙh=/'F|GrTX'1Kv$U=LkOw5㉄j'U0:I %zok#Cz%FV=>\=0D@m k)of!#{v^-I~{O0P!܍"#]B㟒B]22Bd3UO@OP&p?5XܽoDRL <-gz"U"1m+P!i*z:qegaDx~b5f2Y}hϳG;ߜ9Qm238aJ}ݢP1VW]D_Nex&K۷gRdFehTz̶{VT6#Z-ZOڟiҎ_%cK2nq(ϒ#z=N8R5 (yeqoc5 ~ ^7.[W$ԛmx! E$FCBJf4vAn#;=ܘ5BKFoyؑ_8IXEc!0fxM!Wt^[v.NR$aڵ6-5'}#2oUTF ^oo]%Fgq>oбGz$6lkW|T `r0k 8ڻ&< uoY$)ImpM5so$ 6QsVV,VQ A Q3-F` $} @`~8ٓ~ójφls87RTE$lAYt:Cb>)bAMdd,S8_+xItUwÁD]gnBWfI(blMn,!Fq#М ŗ7gwU-N9'о^w xȭӄK@Wo^j (_sayeu<]aTVDLfM(+@;&HH\JdR9P1Y!fflF[++nq$hsDacVxO:=pp \UB)d;D@o0aeTF-j٫^؟m[̖'DYQoE`qu$Џ.- h=fulb p`oGE^!zqv]% J2o'+f;=M R_W#ńrF1צ*?gR5%ҴpgBb]J+(B5x+Tff([-v#~Z`.Y5+a-zNy2j4/uS4]ENϛ!7'bK4I+ xK!<{8-,J[؎d􁢑|n{cC֣)zZbQWZ%QY}n2!ɲKں'po:8CT.F@!#G9Nc ?"{PD|JZQF8yդoDe*Aky.f:ؐ-%uaե2 Ꙍ ivyaPD8/N%^PH f}bK7hǪcF }B8|l~賴}C92 rhJ J'dݳEH'9K&'IOZzqVN oBs.E$`FPFX': H$$;[c#fGWצthꋦ*VtPC$@}꙱, pћ']Z#$&`>3HɎ{}>+*U{+C@.TVP|g m E|2L\MN:R'5𥐻2C)\s_8O3oj61;ئjM?tlEzItY{dj26]6jRF <ΤQnA<'u^imt *q-~PWQGf1D]O^K7-7e>Y*ƸQMuJZRL`Ү_exjoM3ad"&k޴H. ҽXp,vfz+iܑ;PtȜ=9$e^)j4rg9m7$,VB_fZl`~Ǭr]|G5zc =:+&2;tj 'dxeә~BMu |(Ez׶@iJ|b5mK+nRk1fn%:4Dp .DC `ȭTICe~Npz:zzC6COgnrdXIE6?w|kA)\C]wmf a7&?C@Fe7Oq d=ynifO}̬>UzR޴'7w]Ht@oӎbTq>of?-ayf` {^`f8})hUߨw&Qț'?5V@^t߅ƪY![bCk'I uFv=C֑Lj hόv:9XGFnq֒m7C.V gpu'Hil3Xш ܙr :ԢNȩh'].xbrALBw CmAn=wq/lyᄄ*$@M yȹvX\dҲu^ Ը]EO(@g۳Z)b(u>Q̱]8n[PiN^jZ@0}-x|O{ü]Ix֋sHӡHۜxi*zz*O-ӹXky>b.v/ٻ!HOdnI*⬒EaaL3HkU~S|K@#^Ұ~y6'PKYz#.Ӭ}DDZhsMBX7J٥p6{e"Nz6pכ苇ҎԜ3Ofױ{cH=dJP )7e`?n^.g:U̓iXm5۽W4_쪶z!;;\Et{::=; nv=lƋ@rZG1v U!h:6tƺ7QI+/HRo#k2lęFtfRTLڷ(rHV!ly_8n"7T-v4H҉?e*:\I:V8N~U<~`9F7te,IARY.Tq쏊/xc;g=:Bn1ν2?2&(ګ%uX|dåMq9˘^._yM̅/u/%Ejj$d"4sub|'p"/QK`-7=cZM.z)ÂRes>iO'Tٸ&yt0uʄSqى+Xa>Ê+J:9S/kA7Mntpɶ=yX'3hO_5Cg TKqlt8?cSEޖ97s׳ZUnEҀ|Tb`&\CT|c/[d>4dvѹT3Xk)& p/ mXr. ɫӥB)C3sʤH5)Lӭ漎b ;?~-?Է<7Qgh갏r46S\m Gur4hcqRY:F'*alN8Ll&>YBឃf^5kM' k TEZ@@@̓U=)޳ƱpǪY/(;rcg-;{'StfV)73<}%6*wï6}v?P,qo Xjx=kraa@f+;R%_ep]RO$ 8J7˟h]w.xwK<&ɤ#6VW8~LVa-@th÷1 P=d-@"x5b 1Wkr/_iwfia:Z̻N/vo ;"0TJR7/|fFrż=<Ћ̊Ŏs K'D?+; tP!3^x9/y-YOBZ2PEfF-Y<>[6L#i<s~o`ǃ6V/JhM-dհALz }XCf|lf!AiE6+,Z^h'??g+*~2Փ  z@}#> =j ﹆yUVts t7>o|%jLC)1:W!D7馝3XW'U8P^n-kOg|kˤ ߥuFF6H]>}3V̉u3/"͂qGs*(GJJu_D İKMNt17!vCcPV$g(d 3iEfۤ 4hMoNwG|`[{4o?=Z| o7&_!)~>76Vopw=E\UW=]=GFO_Yrv*h9_)Je8(OƓ|Ŝx8t\)RL׍O)rm_drDJ^$ջRM!5Rz,dFm1JhM' 5CFk-^w葢ȓѡ$ZǑ^Tmv 4;BV;Ϲ6JkppFgeEˎӠ^[ 74Ij9hR~0}58 tEs4 Ѯ[ D==N:L|Xzȴzs3 7E*)(f'C  V jwO֎e8]5g\ Ms/A(TK:/N-iUf5}TVDovslƹB9?()<ڲN-JG wɚ?Y+d#CDXF֝H81.d )RrcMiG/<ZMrcŽ߼R~d28qvv0$*'\شF _:&l^ s]2#@ѶxC}xS:VX*)5w%OњNQ@*nmȕ\sȜNtݬ=FZ}DΘ5qYmYڸ|Cp桅XuQoUPjΩYZRFEOS0WwV$ǧJO-T`nZRYDg*݁1Bmt+߅JP%2[ t|譕^g886 cOI)bfu-jKx~ސn f8bYA;d2Ehμ֨^[D~0[}vi̹C҉J. 7Zz1$٨-ĭγzd}:\5iKu }ǘ鯋߿Iۿ;CjIYB4#F-e8X5&CpeB@ Q_4΄ge(ޣQ.>JtL ٪.:^ļԕދ

Ɓ|qjy⦷hUoYAx³*xeE'%خӠT= "Uڒ黶a -7m͞KV6Ź.O45ĄvL[qQi{r96s=,]@5qnܟO㕾(ڥlt 9`up.k '^ 0~':H gdRF&\zx)<=o2]HvhkN4N}Gq${.ld:O)po6Ϟ,#I л)+sZ.xujIx 7\e6b3d Vԥ|ݞ a@GbM#iCO2VCV)Y˰2"-H/t |"TlKWj~d<`\g]:+56ٝ WRi8WMi`z&N&^!FA7cF-wfk!S[)]=wSt z2}Ooڮ"4/n]}Z]W4O%GZ*Uψbn^٪wT_lNΙYv:qj&aFԱo!31u-Nӹc;KOhgW#H=0z%7l $'S}ߡ-!ǔ)1 ۊF'i_7ʣlBJR0Ծs?w[M|G`9p:?v®%x+ N"_"E);h΄({2kJL B*ō(u* 7Jg|vp]pCrց4USE"9C 8ow%-i@/hYMօww&DBebDj, l#<(;/ı/w9z;bb&.ce z1[Csܢz#[TC=?x0dśizJ8Vvt ~`w2 ñjV'3P;6uau~гnr Q M,6.~cO=DF ;,ڦ6ppMLaEҰUaz![!)L瓈X&{װNI1LzZy XTZͽ9ϫ{dU_A>dV'?峺G&* b@J~eB.ҚRA_=>8)ir2cfmkgw L Yw ͠\󁍚)w"*vəTP-Gh/ m}ȒB\ʅ"^BɃdplt``PK >_X}yӋ"WӘ}H+A}VgU}4+[i2&^#B=2N!k;9(ȶTЀx^|T8gW>;d}w]}u_YMb)" ( csJ,*<׺H ^NuZ,%1l'{6im[2k,hϝ'JTAddLR'Z˾"R:z:UR0bnN!oM'D[ӣpnfcuiG':|A c8V[,xkPk4G(TˮyHN8X)AOhMɪpSy1+4ŢrGr0|o8h^3:qayȬF:ꈆFQu>@Us,gEukIdw]ztE:_0FF8(hYUKr7[ΑT:F /TGi mۄ-׌ttEעmù qDT8|.KԕGt %=ux{:BH4s8~q%w<Ϝɉ:t<9 &䮄yrS onJ%GOfohj!zC .yVJ̆*h gI1Fv6"[ϟ[+Ջp<`Zu#_dHt}vԤVMMRrt e5Xd뢫$y3`t1>X߽KZcA(Ҕqw١.OxξX'ꉙ"U'|pאS$4C$)x̜UHhWk?\}UyopnzCٴ_=/yTulnLOLzòZdkT7ckRסC~;Pai[}}>ؘ2lHz]r}7^ ̻8v|A~̀{<3Us0=a{ K aNPm˛k-?+k>wiQw$umTywjK' 9>>«9``v] qUmV[^tmE։K9bC)m4mwa봋dhh;;NKZ~:MשWձgCl`EOEj}'#3?&xqlUVjQP+˵irWHxb;0o+O90ld"')[HcmHpEl^uE"9L9)$BC|pVxɶpq C$r^ll|G ӆ7hXwӞm3's:O(k{iY^|;<Č>4i?(aL BP>k;v>;#;.F(XBD0 uRd%RYB:M/bpx"u+itzX jqv }sHMb룁"@hMaQeV^%ے@3M5D6a2k{7Ÿdo+ior?g hƓĖ N$H*erMm*>ڱӫbi@u޵tHǜMPQ(۱x9<}O$-Q{-7Vڜ'}xJ)> xs=AmcDG*.sa3G<>#dg>CmO2cօF9 $Aڛt[q5֚ȶqg=Vy`*3VF8/FqL.@vix? {X'N'*nU#͊Q+ #}tcttw6y p?b XtNv~-/L~Z'U-z>`fAvĔvzX >nhsa V34Y3N{j;V=(M6#clBG#MbDE Z2[@Bg~\,Ke9 L4 h4mm*dOK-aW}NHܥ=)72[F?&බaҏS3>`<˓OD ݮ'o'2K0!CaeĊSQ[27u#@pfUGBH4=6#,3;mVWqV^ xKWɼpM2DDewDr{1^Mc\&q4r y;xJE[s@=Y$(?ȃӌ1GfJfuQQ +J'zW=\L8I=j}RC6~dV!9B-Ajw.*Sf:;z8n16|f?0CJef,JӦb}H×J-71[ylfV$'l#IE E90,UxZSװ#} T=VϴQO Gx̥SnfE6|3x `E]'P[t𺰉jA07~坷ffs9++I=""{%_wzTEk @҅7Kr)f3ΑjR,][yi3}9'+rn$Su +g8ͮcQxXK5Ts0aYqEqPcMZƼd93^8nqd=?VO%j+[L1w sYw6pqvlUR4IRÈlxk^[SF dv%Nj})*|  4f\B呙z:rӊySPl*zy5PJ{rge~D2@N/o%$1. ;MTةk +?" =lސt?뫏l¯O Cs=t{gs(r^% Ҷ.gEzZL۬wgYz֥N g2cnDsFDN)|6y ,n6[c|kP4yK߄T!nBӞ2N4}/M# n,y5 ?iVcPI1?83okqhe:={;_dly(C+0ŧY'b^?'2|C5?21p#%.+u:`5Ux`ַ 3V:"x]Ir*%FSDg[u:]aZEY:<-x&6<~'2'* ovpU}piK=>9齡gȔ)VRGI.E}>JAǶ'2b ]+ʂVRMdLRසAq`&TSJ<} i>Un]:%8U .}yń+ s9j$)`I3`IC%1cV5_ucG$QWjṡ2Naȓ=GX$A ]D}vxؘ744o45WI}yH {tf] (I $"N{9esG|rvE"): ]j '-!esxCLr;'I̪g]'+R21pD_xتق̅7IiB*da'*k6Ieu J+g흄 3fo^tVֽ|pPښ 'm:P׾,6p<Ǫ|\Mt0"|+ռ란)"I0hȇ)Ȑ*Sw'0DL!<~~6ކ=l۳7p&yX*~Od@`o]Y5l7Yɳ2:2#K_z@|rLe9!y.G"6Yj7oFnI"z0ui"Yvy=+g:MO1HH#p oe-3*ydrpWSks2V6^! '0[ XEP}'Ӆ-G}Yrr6Nd Ӳ~):d!}gt/ꔃh9>Y9>ґuzX},ɶaNT[[_WQSB*Nьu#G 0wm5wf`=L |fсTS*QᾭۆV1Ryq%w%%6a%(PCO=4hǕK-~o}b뱤i#1Bܹ9PSj`_=Ms Ȟ/ZoOg:tcm <=/A Iֹ2jJYPEHP”j* :=F2MdŹ.sh22ƯXp.ByZK^xJ6i,򹠟]"%e"J3B.D("DjM R8|-+Qo5=y~e1yܡ~H zi$ʞ W<}퇢 <ϸƼml+GԝcQO<? 3qK8K@wt_v T|&Q~Ӥ҂ҕpEC)3ϲ#a΂hh);\`oN)Bf* ,a@K 7L#N7P+;4'?]MHߓ&OyY+s_Iuj}&ٔi'M+=f)oج2rCU%.;mf{7 #mjA,+"*(Vga~#qK]x=eO\@eb}wf^f΢'L>/YaYjn>+bh9[MdATt (39G[ >x}YXBI_o&l+Gv I d*NTfȔ,s &[=PDdAh738&<,VAc*A{67k?C΋^Sjq8Pkl7|yi@qs: =ΰ7bUDԿFV cv) tߥ%shTCÕ0N)ЄN6۶'_M(V}BcB޽uͤ cuZʚ6.p؎XM}ua{c7&-aJeY UnC64*|/<$&7/|.@`{H2 >ъv372sjdx#5WX1{yJ!7#ou xovfRL35T]$RwO+<,f9;`_ t؂aPT;k  `6!'cgHe=Tb7qO+NHh9GDt79IWp*&oĽgאRdYz T`=AŘ)}dHij&$N2kEbҹ^<?`NU HI'ae8~PBi9wa =:)A O qQ*]!5}޽⇶98_+*O&OkBT`ca{_t+}sMRk>aMQ^(h=5)L8G4Yqbdl,3 7=#Oul^z<HAyCFD'HNE;缎ϧP b};=.ݷ'phLOOf(x"Sӡt x&xH (\SؾygZjfX*y -?h AXD1VBfnD'Siyr)kG[d,Op&ܦP Z6{0zj%_(z5ݞwG@aUB% <#ז)3+kգ8ajjxWjdK|pv&pJt׎Z̿@~޿ Mzaƨ!W;|`-w.Ԭ^sG|syi8k^ REg 7(姿0`'NGM#ǻ+6y+PMhL(1^|Vr" 'z$N脸GΏyT'[&oOÊ1d` іʛG-\7HoA)`To4F6HJ{[D.0Zb-z4UԂs z!V-HM1<+xkO >At0m?Hޞ@5~?7,O)e<`pd}>Ad|p[V|Qm߼*~Y.j:D|ij's)87Jb}!ykѨ-a":TiӐOt )+l$zhÄb#5c-ClldӅ Y-kY} (NۼPΉB}܂|4 lڅY]@3O.RON+<$CJ& ?W y9"j8M8wJy?8G2!G$Ės)XA m* o 5&5gx5 (dÔzyr 8R#GNF\*6T`],·$mMYᐘK>EWՋvhqCNqQE䕦sw>- 0y~)^L䰂ʱ3T*s!+{RV~84鿺tTw^e7C~>2pߡo#VX1i}-"f|Z.Q|QԚ{YOzLJF}=K^3 /u=܇RNkeVg3+/K \J .~mm9_v '"K.z[4/x2Yh-..MF袙͒ӑR]= ut6k4C"̕7G]3G%#;<㴷%^U|$w٢d*Ԩ}FE,RO2Fݩ{|g}.aۋ}k荌yWEQn%W)),i5"C*SKwu;5?,O;3'EMLSk@֛-Nř]!qFsh.V{PIC8M Gя rǭL+p 7La/#=6"gζo}c z<R2Y){Lb_I݃x9:h~<4|e^& OW?Q/l<2[LH嚝:yn*/ aVTo" jN Ӎhi(Ebzs 3K̦C!!Ԇ/z'la_zFRKD0BS畢Y:zr7n"?=s#VHj/ṱ)km5cDP1ђ==h d$ 517[]XdBcC|UB 0dRM@<3cXPdI  9U?uU?Fk[J/Aߎ&f|uݥ$"^,CGt_&raҺ_kBV*xG SϪSXB=a񴰡#/z42vL6"~4<-4+>c'.0i)gG->|!xϪd Ϻ90%芆ԨcyM$ ȜP1^ ;_ho Ol}6k=]ir5N-VC]s0灻00׶jM.BMP($MIa&2:'l8MG#F)28u[HMKǍ ;"4DΒJofhz u;l4kuo uG ]&Gf Yaz&* OLnf`}+0ڏj!Vӣvpo&xd]j9 ֜cdRsuZ.'O3 W-iD ]"٫6)d* _2m樱-ݓV,  /ޛ;{$!8hU0>xOl*A{{>taRoLo!RsJKpA<#8iL%9\o`|d!a)Ja-ABi/^AE72 Y\O VhHt-#dMffh7?qWU!a/«uNf1׸htBڦb!.i'Ī!>XDrP*ȜfcJ ;YgÍ$塧%vU&0ِW!~r?t'} ԥyq"\Ocq!FGp,;9xgTϡqqyGɋOg χ:)zv͍>đW=ƸH fحAp9NunLܘ0lOٞCOY[X_Y(L/dwg^~;qdcSڳV/c BO~ [9迣7CkJQ01]VPl+dV 7;ToT|2!Mޣ$hoo8{~UgƽHKǼNSGs }֋ȇޜKqu=k)b k{]; <%L PUZ=c+4%zOf[}9Km*OqM%Ia~RWdtT>zzzⷝ5pFR-Y=(mި^n<QדڥFIH!@lE'D1u&BӼ}V*κ Z1T͍Kky@2 7'IIhZ'o:މvX*%?ZU x|fi{rhV E-<HPwNw9X7b;O:]-}(|/0w s+ր7ǹ,6ÐViJu2t2W, A_"WžgШp{>^V9bnR2TR&'_(p@'(*[`ND2$]Y_a#YV4iFꨓ2 q<.oԡp->! m6ʈoXf+xW?hڳ1J3hTj ipBRpus^4hDpGVOژYk~j_/r^yÏ賖g#%ۈ^P [oޛe^Qa~AOz)bp\8zwEO'^PݣgĠS̬rLO wlVyBɴLKmWZS]*8gV;Ag2W{C5g$oZKN*\o^zFNp L }sܺˡjCji鐷tvG:/jf2D#M$P>g8a۩FKWI )$qs^5Gg{:O ׋:g}*OxЀXj[N}odcjdPIő>; )v2ڕi:1V!hwj)vɹ[e |YQ 4<6,kMk8Np̐+`GT@ƻ;ȥdr*6 et7$ W}hmXz 7o_pmHzlF"i&W@|B3d.dV8֚4l/]\ٜ%PaԥK!AVxZV^Kgy߻)W&s+έ>gPhEYP| 4Ҝ Ǒu;:(wZ^S g)+5M"=Șq/Ռmo<4p; ]ЩW3x0RʏPT7*"uB7T nbT"&-1@GL1Aw ҥ[7)y}x563&~l|ؓ:(K/>R?xtbu,dI&/zks35*Z*g7Scف9{hZ`s0~gES|>\H=w*%ִORkw0dpwjp qwˡì"Bh|4x<X ! Uɡ[|tUEۻgùL^3? G7h[長Ҧ}4cciV)Ȏ-11bvbE:X ;,eY;wUˆfwF^/^"u Ap}HGCoْ973`Gѩ Aa4Mͣw.)~0_WspCae~eJH+:e|}j%4C[d9A -@{NKTҬhDT]VC%˷Q:c8ʹDܫcX_jy8]όlǰ]BhrTEJ$a/)CA-t9%Nf]xrmhꈚ]))+ .z#O`ʑp(EO ;Z:Xd2&8Ɨiи3VH&|Ai .K!ݛ\ i?nvڽ[|C2YWxgֳ4Y4:۷\bsb4 \e347mĮ 7]섛o +O[0"-?CA ڰz7~qkKG=q '[iް;Q3]{zä}F.tp ^*YZ$Q6$ 1L7RfzNsKe 6tH(^3}e|tRRJ  iC Әm6maP)9z3}an)J/_Md6_)ԡ`tWI֡jQ³\tVޠ&6Pb}0Jd=(ʫ" lA^db?]} `W^IuzQjaęev|X+};rSMaDs jXxgf :=}I3:9I{[Ie}7|vqta[6 [d@}BOPzV/Xc ?'ɜX n%7&{euqam|,@NXejҒ""vC޸!ōIɖF>Ȱc 5i:XkOLJK 'ôO9ؒ-\zAf߰IeF{u*K1xzrnxk-ilj'S޵c>m1%,88dإ]qS1g]X]|3 h~4̌Xyp\tNGԁv%}Jr_" Ĺ[Hy.h{&Ÿf/ci\AB|KrNڕ1})9I.%sRFE_F n^$ާ|\U9aWHނ5H5p \+tĢ<bw67'+@;R%y;qQ(Kn.O"TJ>:@Q1OeO3 =Gzr\nEd?ş!716&0;"37A:oP^{hTSy,̜qȭ'nJwN7mhAg ̌@-+(5}v~!a-iz<ɳˬ|8,8{Sbc[ c^.NfWPDǖ걓;jCV֦`U"Dەf+?9-r)97%qo 7q!(,߻mh05vbH}ԯ FIGfua GڎM*&HY+O9,m`qD$wD✩Tzi>|tcGI:yJH|-}`H:b̈́+3]+ku1[$󪭍@Y""FRe_0fВgTG_Uľ(նL-I>y?9t e%4[OP99YgHtc*(4R DaȿX~ 6$D Эxe--j/> ӎsZCi3Ǫ֋ԾTBVə9*?;{>~{ `vX.90γj|kl9~:ccp98FPf(ad5GL^ է[ n<9&K34$u*M$n͉g"8qN˺Mt)DM~A_Oɔȅy+MJfrCs|T&fQ֜pG ` t{`.J,1}?$cwpKbYr62 &-$ǃȋAz`%wM=߶q4gz~nSaB|9߻Y趙ȴSt|= ޛ1EI|}buĢaAВs*Bn!0#Gy]<2lzg k4m}oɆ'u 74T-<`6t%r' s{܈:\yx-}דʷF۪4l=VkSzkF!f\U]Xu|[ \`VFtzvr" <]/Iz *6[G=I7/KBe#e:y~n)? 5YQ( Ě|py!%'9ޭ چ+!rh5?ؿoT!0h2r؎_/Bo8ӡl_Q̶[M`!Y?䜐u)OsOrփMDstn|_6*YGX& thS9 &ץ 1ۋ{Uۓ'2ܓ?vƞ1x]ԜGxZRP籰yܵd5|3eN DcZO:M5VMR.N.T30Ǝ\I6JK%Vk${.n+8?pkhe1V_.+#M_X44ne3/X+mqAƣ%-d+&}S*CלDiL.8zhլ0*mzɰNM/*Qww"Gҷ /q;yUfzY~-+[Rgr6&F= 2(={޸zs-=So [ v+˪L-|8h"?FWwYST6́YtA@zȂuJmoĺUT *_Yq!pôby,iޝ$70֍3o753Sz%ؕb"_Gj8t䵔ѯa"=U;'.ݜ[tol0 b+]>j7=:ڼem0kVхI'2,k/+} )QY ^v6Ij7 e&n!8eZ;}lv`+?de%5*#E1` KqA+i6*GShTL^)DJ귒X}y6lzM(cHS&|-tt?9'n3N6ㄩu q}o;Vnqq"ϋxED+yzИuB!fr"wOWke.C+԰OEaͩKr6SR#udܕ'Aq*Z9', ^iJz EFY 5SCzĀbAK+77[y=TO믇0Ċ\Q'3,mD{ڧVbntӰ gǼ=UwTRwd6!=oĩ!RyÔy19'D߇x@gd? X\ *GIt2is'tKW -XJI˥:f~kCӯuÛESC|`,w iK fVjfl)ɬ%Zv5Wo s:Gw{}K+MN8gl t U3/;HieCm;ʼHtd&*{˳d"#`ρss? }E7E Y!8'"wI S|rnhP6i e'P#DjK% '5^O[*-Mzh5)r{eSSbvq:IyS7 h*A< o&EUG8e)s Ӧ\xts,NX_6*Y ҵ"{s!qII꓋N`'?}J%O28/M*H\7[^QyHCp&-E}Uk\a5/%s^FZ2ZeTw߭dW>aqMy6 }AJqDzȍS޺IG?MHtvGVBXu:Q[b3ABu G7dcjc>58j͡,1y <5+ɦY7]8r>`5RS=џet0ckyܷI c^LBLҸROÏ$5D}C9"a0b5^C{8j.>2h@PO{fEGE0j7 K?5:;hS*+Xñ>zYdv16^؀'Viva{Z )PX?E<.'.M@Lem Zl9#uQ=G3eYҴ}$iV>͹Y,ջ?یS#6CqcóTgM[j<@tRVӦlg_Y qhi{{INF2?YΰNA!DΞ՜'lT9E9V\li;&cE?d+PbVw ҙME`jxQÂl8|(=]OPBJ%-۰xgZrB 456Ӵz!H}0i[!(s'[5)pî ΄fTtO3<40*}TrBXծ"H23ȼf6{rm:@7gꗹirq5sȦװS{_/Df:O/~NވFMS-;mN*tVa^Bhi 1oGE=kȦ{!=v]@j97+ԴDQ+ N^قwT>Y3Wt֚nPP±L]{Ixxh7Ɵ+bу6f49e]u`KHV*qB#TίԇPW@E%br*ӡj b Yw}B56|*Ӫˆo$n8GDY*0l4L>5.BmG?l3{M*BJ;rܱ)rМl#=`8Vl ©2ڄ{  4atxr>>5[>$5 *IL EC:y?ppÊ0ۤhq } OV2%b⿯:"%!Wcf,x+PoCg,hgv% wӃ pDy pWBy{ kZYbDdd3tnHzDt՛ӛ3Y{I mTzn ǴCx鈳@ܴy!˰+GWJK+q q2GrJ<.R<uT`f3f/Kf+{gC#OQi{h|m@ֲl$eSe4_^^f1{4sCхIfUtpr>z73Q.Z>`3<UQc'GkV^ϓ(;=?y[ mhwc("z }BN}f/*$+*L3hY=#LvJE9V MMмݲ-R[Z')jqY"#)5(lD+]CmbytܨT̖%9̻.tw8sT|w# nZC:O(6e,c|$q0 `X(.|gSK"V"UPfkqPO(mN=:/ ik_=?r$%kkCƴwVX͔Բ2'˛fBv*eRq(J_`!ߐ8O^$̗ܰ 1y1άOt0nVgWūM&. Έbi=Y2aix[t^Ӽ L4`[LxzY琿*mB`>6Oo:b09p0A`n\u-VHG[ߘ=cM'd˓0 qf(uP:M^n @J)ڇ5yp8UJ.BqO$[E\na8R1L_ym ;Z \\>"]fŲVG6ܱm2!tFwqe=|0˽='z11pZ$rd.}rQyМrlݭo>y [ϜXk&~Poo!ߚޭɮď)GҌ>:MXe!`s{V2F:s1|țbq.3kHi^#_Vwne:0G…ƒIOtzS4FrgSBE^=;n*PSmXKNu?BGګW!%y鍈ӘmҌgg`<,`F+:]ևш~z8.sbnv2>Gi-/#)>Y@t˕:`5T\Gr2=K,Oqos~woV<Y ^D ܝļ3IP Ucm0S qI֗@++Oe5KfBG3k\8x jlї/dan-P5psT"U~Qlh$t<7MS:\Ӡ_W*G؜ aʟŌ}PXkpUQ j8P弚Ku(y-m? LZ%'Y@~F˥[%Oу*mަ&g7#¹:]P"Ǐ4G W6ðm .la•:S3? 'o 5x}m>ћէH'_Da*bewSvE2@I"M'BLMgݖyhC铄j\n?rwH)4τl F&5Ɣh5r?oŮf*5s"+쨙Y649/TWPaPvВ+H?wJq)!}reqg␠'lvT|M||z{MҎWX]+j@Z0giD‚. ɷB럊5]qp(Y(絽8=oq$+m;E: L'mʎ!cw{ N,SuuQL ̃IצrZP7wxWm6T]~q[=}2sfI4,/){s EC`"L VXhT$(SD5,RP#$N"`d* =3b$|oڷ|Q]Lv+' zv̌3A֋]3!?tԥ8km39ENl[ȧd Sqv̘Zo=(ƩƹQՏCUϳonGJ:?-'^ݭбA-I~]w&}kXQ% G%y<<9\|<ҷ)7DިW*)׵93椲"_9=BCj؞Pzк;=58xޠs0x8E 0׈{0[Km`WO 4qފQGfJ߅SxV{Pǵz/y}1KY}l= 50+śU8Ut|+ D[a3k jy]vSƦ~Iۨ,_ƈah]e(d>xJ> 3 P"OO ~\S.2PoMB3'Y(U$]򕭯L##]G uלߨBAIg[:W\KV>iԟbu~;z5އ+ɓ@8f[@x?1Ta ^#Hl-ۖ"ϓ dWdKE5&ppcQrT ߦ 1zn t^`'ԌaWJx "vrWJ86`6<-͈*IIn,J]3?..,EGc BȱFmH:b'Ul(U)mfYz4 $ř}xQn[b9?c ) vCS_N%x-R^3^;BN'~{t-]YN`őY\pqi0o-RY|>tOk`6\ł*Bm]nqY{e:Ќm 3l4MVaY|iHe=*a teU@<6%]*#ǵ% $R'Q%FˊɆKB_thU5F5,P<XFXHAO X% 7:go#Gʺ#@AVԕlo ܁<]ҧ[x}Q aߘm/knbKPqp9/3+$>daW;btŃ77Vgh nuTmG;34ȆB^,'{gZ"ŭّ·hDZ e\g2$&~ 'dӻM;Deki?(3| ^ UYOQEFFvo:d} $IsgH!N.'DB{VXweueY3( }{)x:>v+m5j&{t~A&s6v3Ci\Sy0{㟴Bju,:iZQڹ:Pkܳjl(8C(gҥӸA2 mAiPߌ/#HF>eͅK4<4>|r<h3!Թˎ4.ܖ+ .ys ODO1(\xMm(SmQw@,0y jUB7}ha kRdüJӯ?*Hy ځJZajjW :( }u+/+n=6b8Bj= N@/FPr)釸H^2YI|֝>:l5뒎dyzq! Q'7aVIݞ'sgt>25Rާ_pbȭIԿ)s!LO; &f{__83w# аl:Vw:I9f/E:q-3+]-JׯJ::HKq8&qmu`kẜ #p~X!YӋ G2w,Tu.I1o`:06d>jcȀҐS/4GrEI<{|Yʱ w;l ڇq}-G z>1 `|G9@:7/C c;f; ثx= J Yp9Ŀy95r'vȻЮM<".eTԬ1;dScɎJK>B;ZxHjmZnf!-;T2P= r>F8gk(قyV- CX&m7nJDYV.K%+“Dt O|Ć[k A~sEDJdJR@h`Lr,VݾdP.PW( 0[v~0JMԛJi|(\#j=KpmN$3P׼N#/MD kbU\ nh ;9v{%iGÑ <3`' M/WibgͧsY֩4.E27ͼNk[u~{g:}cO8G& evXj4+t9?Gh$Fo(TMu-'>+ʖrYD %`ō(ޕCY3gҼM\"%]VJ6K7m-R]NLZ/>&Jvޔ1no`~N@Vz"mk+!f14:N&.D_8+g= 9hG1@M☺}ld)>EG@|fz⫇² [,wÎypL"@9WGGTG 6P6\=0i|a_C'bi ȟte4M~ϲ{`椮OE]=XϠ҂4^*>5"`5I;=Pfѧ!%;TC b-59E.*ƟG`lKU I#C< y8V,EU)Gћ -]G]E}!ΟwͪBkf3!>!Z9Ҝ ⶖ$gfPՓm0pA>ްQAՄd7K34a:\F_MvFX+º*ͥpu`+ѥR6U&`;Lltd3NT*݇ѷ"Uj+tC)G/WJ 2(,d-mE7&=,ύ]/j?fr G1dra2~AK]O4oZ8 3D{A^,>LrjF~OzYJ ̠ڧpSPYScիgH֛tꯙ(! {4n{XC*E l+.%i\&m]U5wYY;2dKw( %^El=XH4oYÁq(OSxADl/xҋ[@JMV yTϰ|iJKg$S'CPeަ0Iк'c/r sYx^= 4[=m)oyu^}  |d~}v"]*u١ u B~{˺793#+W6=fjiM*W:^9gI~3ZyNIN>g13W~4:$&i|U);!XZ˜VRF?sy1@O'+ZY6lGD{YjPRB@wx*dM6I /MHhR}ŭFwTg-^7T3\xNyj4ߎ[Xk>'lA#܎!+>a5S$frҫ{3aAԾy9iCv?<@pX^0F}ɩoȈ"ЫG=/,Qⲥyl#8t`o* &B?e. :`qwL}7n6?=a_ R'G )Jn -_N%ɠd| ?׳'q U#'U N>j}+}$&if5\K$k)C6edRs'?oB#]e/7.xތy4KѬI#ꢼ\~!VC f>feX5}ؠ*D""Xꠉ:+-\eO%\AFPą1PdIs ,V?)Ea?`Y#"#|U EIJ1-Tۛ,xa^j#ѣs8MЊ+/߼T9z*;6(z~ P4зOeC 3"91Ua f~W*DZ,AoSkָ!6U$FǓфĹgޟ( 0RÔ1TN/[]fs_UsҤ.ʠ=o7fQȘ Z8FU?˜ a/Ϊ eb gX'21? ,J&G lˀ&(^v''hllV%/|҇E̪1|U56_zZ ! 'q(OATESQntnF%7Ѧԍ_ˍJHZ#FojyjE_0 gLx^w%j6p͞as `KDwμb&[eGw֣ j3#vx(#E9_5>3/Ϛz1?_){|z)ml$|&*5D;e ˎAZk{TN6I}%)ʁe\?BƁ M]ޥ#Us<s} BaxW 9i'EpkkWNJ7֋w_6;8- ^MA_ Icc#Qt\Ұ'ih~  J\Q.E@1 t2ajhQF/H=JvjVjJ2ɞg-6 op AGG/ͅ䀆-%utwd)2*5ڟϴk|q2S0(=Zeqi,O\-S`+Ez8YH|O#w\hȤ,2_L?^o}^#h7s.6[i|>sA)4戮<ʆ~Bj.KrvS4-ؽ*0$}2ׅJh\\`&(h}4}'th)3¨e%_I G͞BE^tva}۾l7S:ii\ՃC:Ik\-a e-O_#SȫEY&񻄌E[Č#zo(!QZ37m%q=o>A1z24j۠g!WsAZ#9 r=fCji}Z'JnkX1eK%担;8rA- T*hmؓQצ;b!YFZiҐ3` SYJ\J~XVBݝޱ%ӛ(Q]?sh4EGhD&غ0u 䜞GsrEoGa?.Muѯ#dCO3&A gndCdf=@Ot[_HףnVF1 aq\iJ?ȃr;f5G޻sfW./ta-o>՜sFɒAl蝞PwڭUZ?=$kqOM.{?MĞjs,4/+&Фa^u}=(ȽX~V*JBo% zf_nYRS?5TjY= `oPڜXt` STE~S; Uje$Sz7T*w_k5ZNFrţ$Ӿ0ӳ6&m>5کF%Å<-mJi۱xk%>1T&nM>n8jBۄM?X6-Vx؟0x(8MfsO^eENJۢ'zP*aBPh閝|11pWaeQe{",Yd!ߕM@!egp_2_BNh .ӛޟ=`P2sy, /S!sƀRk]?N5ҩC#!U]BF%mfiTkF/ .C.e|L5yfIR"畱2Y12Dd++ٰ2tLƦ ZsNaW'_K-Q {VS݄qhvL`i$f̈́eόfBڷcV,UIJ6N#[LtP7 _S`{L/y ~Za\|J&/g( >{i̾q?V;'rVB_orblY jII盺w1N{@:L~B#7@µlm~ rO- "ԌGbkl=Ȁ?w\qٝ*XzDM'86tfcٹ)XFNQ;:ua{P[Aj_#wKke&6Ph9'!rA(vUw(MPϡ^ˎ>Wtv+%'>pD}EѰEEFʗ7Yd cmDC:k#Ma&Tv! I\;MK٢ܤ#T(2 qgJz~N`5wyU9k\_h`Ok 'ɍcݱy@ o懲D,-55_CJR>Ma6i+D'g8H[y>4_DBKEsHTHD5S[HO2%9HUެOCǩCŶʹ@A}\{)XɅ6`[A zFgOK&XhD>O$ܣ@_O㍫6{ I|g'MNHM,e obCL4άoݖ\/swv~oxtGé" ey~@y+*{5/sjC눥Ķ"2WXpA~)J֓mk9 A'pNA>($GDsTm_f4ˠcVHBhv5b\,A=Ffߚ[G}>cdOk+{Y;+; lt/<֊ѷe=O&u{iRIPl_2WSrn9,iOZn)4,>48Pc~_dsChF R7aNDDewlu 14e\-K/F՝m/ll7=qveY={YTв.ޔ͙ MsjOWOV2߅"yqLׁǰ\B<}7(̡ͩT*Z){RC)6΅:ڄ=YlJKt`?U׽ۗ\/HwH@Əu^K]08 7 ޻x3vcԸ ^=Fx ߊ_ cw&8O|#wqe.KI7ުX?dLip\v{i/AL_ߊgPc4vVyt ,uֆqXϥf RNeQ"IP\1ҰLq EsL(loE^LWIz[+fjZDwUa575@tڵ6+#ٟ~%&6>F 0xI'ӐEm>Yצj6ު%yy/;Ԭ}A%\ =qj|7lO\'|SGMuׇ:>*Kɪ6Ջ/jo}HNa(ޡl_;L5kio&[:o8t!A~2u_uwrjT)שY_=e9AlJ.[oMf5qo  }UB Nz`ZYkZ겼4W 2.Ԥ@ P&OEf8^ kv!)JIs]zaUϙ\59-8daU\hdH&Bn οNA!B=}P [d8BdzG㢐SE]*(%JjY~Ov{yW~= X>vĺq;SenFAb՜ܼe\)M9mvzbUyz=Js0cyU:Id#$o<@8!1Wr+5cd|}Laj66<&|=QԔEȮ6a;qZ-WZqL%pz3F&L[q?6)팸io-:`+kZxޓ"SU2?gE\sq*NhM #Ã<JԐ:I2Y+O[H8|?=߂T K[s!6T>L!T0Uñ-#Чnkre) q>#}5-P4]n|"7!" _MdIhr^95po[Q2:2?t-%@a?>pQ EUIK;_x2e5Ӗ b ͼz(t@|cs 5m /8%IaWVC]r}66фN*䚧Fj7s-uyG-+ZHuGiF\ifR ` +_W#wEHgmj@1ZŢ3ĈBOPG-dWuYz|GNIxqw)Z;rf%OO1wR{#&|^4\Z!LSSjO: \Ip`ZY?[lzR hW mMu%V:g$>u#jG4{A972n~}@9jԔ*?S@o2\EsC#H;8ߛZ6v׊';">nN~Za<_5LS b>bdd ֻB0x.MVt\O Qj{X(I?*JM .IdzH'!]w6']HYH5 8 ]X@l#2/Y]Űe$Z wSSt?vQ7Ĵ >Q膪ɺ66t8pT4Pq=&$ ?&w$o~AMgfY:2,"&y;boq<~%>3Z1@<節9 sZ1kh*$Ҧl̖v{Pn]MA;fCc N(SVt6w?m hU.蠘ȃ(};R{.2x0O5)Udz QsJk2J MIsp 0NvKn9$?M#nGFJzv"}Bzoj"ur ،QHEl.kfjL^r0{6X=!&`Ӧy]ͪ@#| [M bEC3`El=F y3!Hb\(¬'FjUcY:r0bE驦r }OpK$ M Epi W ^QCz|qVJ>jYh7)$$3Vȝ;BSUs=/߭%GH/e;s-cOOBޏ\]K쵯Zum͝ɨRN𞍑8mz6vB:-{KJT(EB>M+븊DQjC_½爞KQ\Wo}.:tͱO .W͙^ȕ6vP T3( RGŢzV?Ixc N$P^cm=-: =4쥧!Lr4=)\dZyf=k߇#O%m7uo滓(Ecx*1e,[J\xևn,;z(X#*(:X#TuLJHi|-2ò^J̣9=ݹl;d4gz 2eE}!RIHC""=V>i*VT2ʿ_=T01葵SxF^$bx?Il)OdLKؽiS6sX_&p z+pדr5ʗyH/{SOxX&yY~ʸ2sܡI)(W V @†2tNGMN"ߩ8V髭r55.@w}cpe _ȥ!Sqgo%2 uRɠiwЛIrwQ^q [cO4}W?C\8e>ecEI9LSDlCEN-jě+LF/RY>#h|YEGYIIHȮF{@1ş'$#|ߍ'meh+#:CG7h#z.z?toq3M H 51lfMx NC$${SNs \]Le+ۙt zC!S?{Z7p _NvޤiQVG'0R3i%붏8~]LE@1Von:[>72XJJm䧦.WV]Hd8$i0$Đ*BӤM KMv#AwK },"C]Hڇ@)s.HđX6дPYSs[[Om+'w'"ox<h\NPedKvotIuAalKpn{oٹ>_9Ƴ빂3K(T_B 󻓂 ;_t1LNM5#iG->U$LHK:;A9J#=u52z;y|zjV{j8vn %#ޏU(΂> 34SU˶$3vh霓D3؄KU RZ"_-,O=<{5])9KJn2=k=t#}&,!@w}[{2 Z|Y`[X~_3v9OA"A\>^_&l` ٽm;8s31xu{}j`uӬ,7/t:f'YZ6_UA{ij .*Zv)\v&VEGx-7Bguu{ JU:>ŇM-(U✄bJSYy-ߗ}pBt_U-"ұqɮ/.Ќ7T*~%YSP(aKȧ^!`Ut(m-j*y?qꪧK> ܖcԓ_YW=,U ;ZS`:K_}TB1=vJ?eMV!*,;9T-N`U.^:ԓI+#>Īϭ7i4()z2.IH댈zHg˸n]:{' 0=NTX= k'f!Y4j~= Q"iE}.VjGd!b3Usu\7@4?mXUݪ3EFhCUuRLףe-Q׬|&1ν QhU8[y4(I>zq1[vvskZ:*RMy({H"s\IxQH1),!*z.+Z)ҋZt/]RbUjQ8WiOGwj\#cǝ!{hؙܹ+ w<_C3`ەwӦl+i'3+TiM"X<&0h:<Y:w*)@O7Dӡ4[@jIn5gc M$#lSuuQE&dz2P@:$Y1X@-9ڗl@ZͼN 1i' J6\ECJ@E~UsΞЅkWP_k 5uam"}xe *羰׍`h'̆>ȴnBJ#͓%7M{9UV!͋ ѲͲ|ZIAВٶkDܼtn1Mcl[ j'C~!+B j_}~~ý:ɹRK#zH&x95 u*Az+ qcKQ DlI>Rw da uXږr@ov_0j2*m~UC_{툹ٟϧ:N:JQhZrXv;@v.OڠзqUjvhrN&rЧt}[p5Fo$jnG1DA k`EJɭmc1d"'k,4y)<( a8uDBMKðy]~7, -@ym<$!f9̗-sU`)v|xw10 lFjEm Կ;iݢDc2+TeI|P)^x7h*qOnHTfhFCl=*zeBeC?2͵ Q#=C^{DyxF9W:s2-שQqLY 0)Qڧ @OQ>=RiXZfM1Ud?Uw=_^Z\SNޡSaGSOˢEMinJ h~ 4a3&GnE! (l"DűuB5T14ϤΕhp0YFW0XwIxsgjrPAr;Lq"=-ε4!IF=sfzg9@>`SUJ]'}n]sYJ]Qr]p$@O!'2q,~}4WLyܛ6uVSJNһ  [?#Fc9뜴dy%D2jjI5{h\AI܅oV"!u\Gb&Wbgm? Y5SaDJ̥}Ǚ37%fl﹜mWMLJ 1ӮtҧdQ<| 7D̢!?:Kih e|>@Z3,@4ͪ1c~x@-h wښK[oLBdJIL:ЀC2O;Tqմfy19-LN8o[W~4 o;SBROm!uDS#z}T"_*qf%<Afj+IMy3&J" Eǝ!s~.Z4J:? Rm'Qk ù`w7fsܼ?4ZHu*:7y~P{vJ= 12vkUGh(gCd1O|Zu"HF/vJC]÷,oq~~هώLjCK-ǀc2zQMm<Ւv!j:Z}ɾ3>gr3lJխ> H"P$Y SQz.x#2⶿Tedx,b=4,ҨM_* jǎV16 Kx`J(V%Z(7K}Cgțr^(s,h4qIL*YY7M/toAx~k@m[Bi>PB5o_釷\a;9LƎnJ\fұ5>UQ+c߂gcq2,őԋrDyQsOcGSQlY ӃG+gKg1@SdY%W As (<[M2>)_:9-4;3J8ȁ֮jIo"͞/6[jiN-XYRwfc^wO89Maxo6˫$W2~ E۷b=^huڕV-CJsqpyB篾N 'T-Y%c:'0P~4WDžU%pDGp[CF~'2~ !%#E&~=PZ&o}$_m+r.AľzJДOkA͵2m (^%_$ &D&EƠV?4SRtߘ-f?1A~vM+o9ك)bPJ9\vgҁ}B0;J_VGd`x7U-[>}8=w񘈎V;zFJIjPT 5<ʯ6!S{cO4e9OgY1øF: NrD'mU3E;>Bwk(eꇚӿ4 sIIm$ dm~HFr?iȳą{=9}@ $,rcTE&IF>0ܝB(S#샎+pw8XӚi EA:bXI  KN%e_hnk I#1KE{,Kq fs܊[lBAI _SQ\6D6d2kͭkFpbRg8yqh8{Ws)ۯ\vpLFƣE/yjf,wva xn݁zHzݔ\0fsruS9h@[Wny0ҽ{7*M+Әo R@hLAWveĄ-|ӈ 6XBk~헄?yh뭠y)m5[:|cW-kIS48A?\i+>EAmIKSQMVTq`7ᾜ9k=LGk$`Qy4bz%j,6w(e'kۗ2L=H;Z{i}cEwWLPO䰒ac[Xo8H!ԮgY'9wż}T,W)6]ّGG{|$8F-_`I \42)61}Y QhG^gYЋ+/<6COUNvIu*nJ:tckNyy~,51' t+e{i*LXS(12wflwkY͗%9)jCyltpQ{hK/m~DN==@&e]b]3=d*2GP益~E'h2)A@Jeʖmv*' ^y.00ڲ뤙jA6Le+6l2WݦKVVu/B ݂]@ !@ n O2Lݙ/GfS;` E\3Tes|$yHoiBHFk]Șu`bT-Rv{Ûͭ4q`vcPwR2#4!;NI} BaP3U#^̕9)TR:[ίݘ~Ƥl:R-Y/%T˗ mR7rGgXjMxZW I"ƱPR= NϔBp Sn&o{GƧsķaNg7[bˠ]h7Nb3[I 7D3vC$Z}c%H wێ.[]w `60r7m˩l&t^K>F*ݐvjEG)\\j?NSטcN^U4|JOq'?3uk&HM͞Fc@y8XG^+ <;,N;YDjzf8V'&K9v+uuMMϛ(lV77$bW*+M[ʋeվE9Rcqzȷ ,V1 FE9G Yo+M3pGij7Z=ݎa ߢvBn'EY{H˃lBElŸC@>T|!()1?j8Pc6<^f4J&W;Tr5B ie,*.yȻT yIuGy''.Ԓ"֡QGN5M#qٛh̍op e/MMK3X_1i3RCSK4<`w0N56NqXos,D!"y4 Y)- AuL%ymIKc\c9EpHO)?E}ti+9]hȵo06/s s! X3{Z6~hÄB].J97DY#+DZ⎹xo'9phSu6%;$axp&֖ñJ3r}Y֒xf4t\ʵ]5,v@KSeP S)Oѷ 4u6+G<  4&m٫ !9/iHrG!3,đ|?>rll[=i"n iu5-Ov[b/Y,UsUrP&(,Pkd)U?r$#φ ,57H -B'0 0qO8Ez>Xjj4JS"sQǶ*iOA}pmywGˠǪ{_@-|]kn7C/G=NoaTLc3u:+55JV!Ύok=9D8|@ hw+?<]obF!V;?y Оvg}X{CDIźPåϛx$^ָʙp@?E|cX|<"c lR^H42 ~ބ !d\D&QpZ;}Nc'_Gm<;я3Tc x# ~Vi_efѧn rX#n0Lӑ:"1t`9TM㥤}X~5.JI o,WX^yW83E|~h&${ YA:JSρxϋ(]<KXc$oac:жFO\.rm*`_(̤묈q=WM HBʼ#Ƭ!suvU KGR+Yըn8}I{1Ҩژcsld4M_zQDO&X|QM*Ӕͭ=[ȕc\\9<В I0.Å,U ĭgIJd975uCntjԼ6SHKb*ҋT =SIl︔MPKjFӄthƱ0"8;)5/ <[ry\ u3n^'uSF7uYuGJ &D\0{g Ʀ:dCh,,w!6/ZKKGdQ{֓^(:ib0ߧ*(^ov33x/%!q觚WpP\n<IqpcL7I:,ֆPAjju)ЇrE"! q 1Cs;ryox""ToKZFkKP24d`x0.f*p6mX>Bv'M!4~G57eD%YگZ Yt#h}^3JKҺjJ㕖=3,A;ٺyGiD,@ 7$)v;k+Qb*M^/~^hm bF|ĐC ͫ[,:۟09+A϶MɮHҷt{!{ 9uQ\yOpuBc|0_Au.y+zL_`C~,J:79lZ-%9nJ#.{1f1 ?v٦|tJ|z kP (Ԟu*rW Ké U݈Ckr;.&!P ;֗;zl]/wԙmj?49:d#74SQ[Ycjϖq!#\42Y G.| e5SX6oiCsG{2upw`L묞ْ0Wbr„".3+fyt'3=i}oJ^)iG_IcʰK_AHnEF]!ۇ@t.PL sE8!|A B.k9 貆`RJ;Y7zpwyH/i%bv[\OL+Bqԋ 3ӒOCoMbG;II+2<]LU)PKsC)uڹ+۪ʞnEq>}pE\e+ўDVlݪI-\Vf=DčЎЬ,*^?4w.e3ГH >*4JM2ZbYQ^Fﭚj% I% {=u8r]U-# Cg7hěTt=hbH4[Y1Mu5UFBbeb3?,?xOԎCO|I/+moJ@q󵯗˗g/8?7vRYz&ŇX?`5(q̗K< -=EJcbžߝ(KΏ9^鹠{p> MTF!zPܥE'І?J= !:tSZ|7]aN%ޓ>pxpF+O ]%=T.#RcATi} a B^N "F 22Ǘ)ɿܖ4ӫ|w/mqЧ,EHXJMUŬg' FO0~f wiuc{ЂHjqu5z'`]NuAQ1$hWՓ)7sůNLhѭL ʴXd4oj?C84aN7io DቌJ߾q)HGp' AwI)iqkww+ 'DŽ&t`:Δ\:6/PIcτulq6\$@ԍGF CЭNgPM6A,TޝQPg[[2LcSKNq/ԫPy6[|1cdTU%.RZ &"a&k Ow&~sQ'rm- Z@C/; QkWKZ[w客?*_s"b{~k`'!*αH6<#WpV4I9HT@y$F&sGW͕\W(Y,G:C:>(z>RJ4/(v]D!螺 {|}A%jj6TM.d}cA vXMGD Ɋ*klt[c RVa)>]JzxIC x:8CLY:U5ٲ ӗ>촪u{B<(`];5QBʉJTdFQL|MrM\y>O? eAÒC2j:A-jx}~4{aCq FK-7Ž@_'VKaDYMCޜ~ys7HZ^<Ȃ*w]4qknk}ְ"Wq2ͭYYG m\r4cVS燉`^/QK qE#̀3uZT1S k6W?})Tof=y-Lb]ל&zL{a+J;&GiJs59isLYS0ChzAp&2W? 鳸{IXj;ڑW^Eǂrf!YZzaybM ԶLWU.=OwLAŅUɖ}n xr £0RIɣ "b$ӽ<"sNo`b,;k`M-dzڳ\6e&V P<k7nv@Y )NIY)|69͜a47%"'Iʄ\g]>(C9?l 4kd>)X3 M(ALu-룏jøPXr=Œ)X66X迾aòP}D+nLz8QL5elƿ˷ÞɅY5dLЛyOO1.0hdڤ\v* BOFFG%˥B/< &՞broM5#ӗsj&̏[iyYBG T%|,4V)Q7yH$S@]e~Vp@:B%rv͗>؇Nq$ $d)\F,aUW\.LU-/jdL2d}x‡t.2Yn܀|0I+oRh_=Yݗ1`_6렐07}ʐhR3Յb\䯲o8n!̌輧G式PKEE( 63'4bGߦTuW>;Ů ߲Ϋc͞i{f8hwjထVî~^?!68͏RY\ %xZa,jQ§; P:,ߝfȱձЦl-t;LɌڝb2O d7,n>m.uOkBaԴVFPѸ 5+dw#U)I攲u!:DsgZ/BE_pjYU\tHYb`G[szͬKiȉC+&p)4;zFJ]>z@wvTD)O މYocΛ9##h{J*,w)?rNۮ&WZȸUlekj4 FY#`k7QmB6ev609cC*}J{福V)ՊY3E\aao=!Ԑ(eK7kzJ#FFF1JJtN=㴕(YȁC##5apCҘd, pKoa ޹.K RAɞ3z[$AGB&cn8#:"G+uRO;v@~ cR-[<ɜxG/8zC\uȆ}r\65?z=g72 S2t];$G#l+BaUxdM'lmbęU;H(ǜD9>f>B"KT{|T)v~Xl~ Jm/ Vx߭ Gis}N"Yv´㄰Z|zrAUFLOW!e7_4[SKe-Qrl{XGR[ݷb9yIՑS\<.8R[wY?A5 SʗR [w$j}hkLe:g0}L⹀L{WSl)d9sZV$XN4rRE_Y4R}JEV[q\- x7MoJ.q"ƏUCٴf.KCSm N~LQS+Jb(6 "DV{yhwDŽ\}YQ͜91 tOohPgۄmɯ}L=,Ծ$n%FMrZ|DBT>Hq%KB0ɓn,ةTFQVçCa;!Pʋ9Epz3(Lxd[faG>?a]EF]\RT~ܑ٘$ LzVm[`wh{`t z<!wN! ;묦/*D PyW 7wXcJ3U'0ػ=xH#}EÐ#*5vhшP_Qc!~d 2/aCmXgN8cOF/C2Rլ1K\Q`ou|5U K+ź垙*UuD } +W;/ch`rH) ;=<,"{dE(>SHGS 1EbM*՛S>BX$@m6{d$\}Wo!D8?,S]I>N  O&M2 s_$!+RH@I 3IꏦެS1^oqC;0kM;*9߶;JpogR>WBpHǖ3tD֊xrhc@@Dp%Xi,Fzܺ)2;rܔq> =NHN^AX4xgKdD$kX`'~O5_saHgEJx:bɧƧ hSs]܏ź. 1d\u$R(_@eUbjȞi?@ycU15cjݴX7M,kiGu]NetNӐSMX力:ܻ͛J!H_!q(4u-}07+0~2bWXg[w@=E%g~HZ*SZ߉3Lז\V3D{N<Vdr NAcUBq_K/Ѱaֶ%yrSR+݌.$d͇Jfϛcj!Dr\]Ij*Yi$ rM G*?6$_7eٵl#-%uS{(=K=Kz+9PXjR{ʤ `i@*do=~!\k-yY-ߛ@Ϟ8I+ <-zH~~L8+K`9o:2FSxuP 8IE$AuRsF' (ݥ^g6A'q6(maJs͇3ͪU% }ҬHyJ㖧70Q`}GsLIX{?7Cxps1̃:{=#)n. Yfwݗ/tW|lRw>`%`@?lm(LG*|dxŰa:YB,TG<ބ"uDjay"@%mT=c'23~t,犲ްӞpn Q#s}^)x W6Ϛ2u׋m)'zqm<7sWQf C~|@J>}S}eb' XBgp*LW$mEs[ѝd50^S5nQ#OUmI)uU{rGw4㻽BhSHy֜OO)]gx<6P+NkWF|{E&#;~'bT'6p܆'&Q -tV#c;Jc"e#6݀eTвNL ^,쭐B7e=VH u3'!K`a0h27] kFTNeel ^{co%2Y7՜or7Q6&F߱ *ԔsY `{!l9ڮ|YGDmW3%˚Nk;rhf9U} {|H"o|1u!I#cEK|>-tkqE.TS?$:$vІfVᇚ뗶C"2jOMGԉ{%'A-!.u2_mtí?bVO)9e݁ȼ%qrY9/دs1I\V~n)?rC`ɒ r@2C{_Ia78&SYCǚV~xg%_A^k=oy=5S]nb\n6ۉ&oѷf"1i"6q?:B\KoF+%J띈6AAc7д97KRk=+;BY.[uy˧':푟޵ U)Oo$jhЇitt+}Tnf}͏%K)t_@h8ֱ*pb"U.n37: *H*8vM_n&[[:Б4b=d՜8. 7o8vb*oidB͎lA.26|2s)Sj6/Udͬ%A%nf;i<9)w5r d|+.# Ri6|5o;20y[zWB>o9,nzav8j#"Qc&J$L S!f,ǃ٧nN{3c"VTu+5qgȔS=p*d vu P;v + U B9g6q&rX0+7ȌX1EΩr])z*f-]d-dV]ayFλIUbڟV|sُ(:,@z.@of]OԻjųw2C8d! #l>yWGI# 2٩myDiz{8. yS93%s+gfוYz C~W+khp|4(tQS fbB1J> Е*Ǻ*6;A]KQvSy.:pzt:qc{ PMœ׵Bu~#S][35m-Ψm9&BцvΜ"Nr&Ver>= k v)V[O(廳/<$?zLU+J?a+OhlPmZ+MR ?Ckr;:MA aq#,1qW ڎ\ 6:0 *N,3A &s]RTb3H[/sSĭOK|KeU;O!@7ӬS[B(,|:JɎ%m<3hva͹i Mm+fQDvq:^"; P53N :6=P}(o) ͳ[!+9ksGd{Lɀf`YC @3W7II|?Oh,P/Z,Z)2FjKvdخ3k˦L^DgT4AHY<ő(HåEUF!IRQE_R\|@r@]Ɩ P:tylA gR8I-ZSTҲkQ?0+$sC HeC6T˲==> J2VvKxtN Sl![ؖ  L,PNwUbe˩Ek;a`'ږ?>lU["+yp>uYOx2ƔS8<9[m;=Ac%pU#'7ksx.PzZvJ@=NÐC.%NZiWt*/HJf.I#R*wRRT)-MXy{ Dk1QNm+Sʫ{uf0}ڀv3 R n4iTy_Dr:IN ړUSR* ;o&W.0@'c rȇة]t˗ U^:*$۸ Pw=55raPd:~)̫"J`Z M8'c & ~6U٭rVZ;'t9Ox,=K ڸQ. |ͤ~_5<3^ uV{u뼴&M5ӲJj NKکq?dv0#y굉_N|wu76JTvl+"z0s*eǸ.s3c.F6{ܠqe6[AKy:ɕ._iM)rWOhF12ܐDBqn5龍h|#zs|N}G-:B) +5M? %ƥv0qJ[YR/z|l2sŤERo6WHD0v-.(4 V6cRo LoXV Wډ"qMx*RpJ UYZBG sjejߡcha&jn`0Z(WUgmlisx+Hu6& ⧎OjQP/nJF8]'uѪkz,}rORPrdestD,>1@p>=<,@͒rd L(s&p眷wFliyWb^ 6NA ݖ5'9r➎&l< gྰXD43'L4:WZLmdLCsP ð0%?꛸Sc~H 9νTॏ+ձq^F)<<,!Pלl 6Q㹕35ZjL>jiUWT̠ B#5R&iV>7IzjKY cfHs4ur>[6(ka~0_יijxɏom\-|1vߞl)E~#0p#Xe-Lbu$b5s5\4X:]Fw@b< QvI| dĕ4=Ǥnh١Fj&캑[w`e&ާeSczATV'?԰^eݼIe yJ.>VUg]37J֣a:K?Pbt>uzɶ \LGM4;_9Un^}s;([Ci$ʛ(ךB8 Ǝ5Y8%U}N]`j= 16~?ǎ ّ=EC7({>ga\`:"}šSOK(w|u2lF9tڲs2ג U8o:mbjMS QxۇF.I[&t)f3"С%mrs|qjq 4c6 ܃GۑJjkMsSbG7}ϥ 歛>,!}_ vUI>XPNAtb;|KOƝn젛$|sZA'?uT7|?0Ag*ۦ,݅ޓ|w~4b~YrAGgp19ɻ,|;B ̨! v=G~V7~l[G,C;,ޜUr9H<|+ib$Vix%#Jr8awin-*CBxhGi0p]Gp݉m\4*jrӋ)ΥP/^b6s}gW|xP\\:R12y.9oiH/PdhdmZ(" ׀I Ҙ3rTмx伿l1^}H{*Ssfvɽ[\)駷m|k$SS]Xفϥc>0KrۯDDqigG {RU֕O)D!;g|֨$iv)>'|.>2QJGww|e|wq@NC٦s|4uo[,6Wb?8FII8X"=1/7F/A,hL<-5ucwx͡Q-yľlynUή4q(aqnZOh"q~h3Wr=|ئ9({M~pA y.5E||dWs~NJT~{w6:'vJz*~9W \+;6~n( NzcA7zN򁦯溈BW]4)/rfQ/Euw t =to[ۍ᳃ ޔ5&AngEzA"4 OZ(`-~ȖHm ATڭacBX\(Jrt;HEaMg*\Q#V_e JT4p2ɱȋ&-csf{WǛM7utj_>lo9NTj$FŤԦchOkwmL -[l\DUmJCr.,4A-7 &,؁ *=wLmsn@q*˨;k2?뎸A:E8s Zl;MJ>Tn[U!K(yVEbji+K/:ڔS6kbO'Qn'ݨ<ݥZloMQCʎLA /M-n<`(.ys$J9rhgڋ,Nc4dps6Nȱj놸 O}D2)}&9疶HG(9eC8 d5Bcz;L !_!֘-qNa'_GAKMu9а IB맒 "~ָ˔Ri( SVXOLaxŹ!3X">Lxh kHM_Xui .Nj(\eD[I*˂8CǍńZ)cI_ DPk_:$%,1Kt:'dœ6ٴR/$<2~ǜP4vB-rm Z}ؓPomG!/(s9'Zl\r j\#!ʗaN<9Ùp U0A?Z$PReV Kn{FK7(}t2:(o ~P^ k?HNC% yʡqVAaP&{IҜgB!iǏN9ӊu;4$-]#YPf C\8¨}9/J@@PEx4,YNʫ*bmaH2%TYZ* |P;A3pEFKĹز WE_A${6S6۸N(nRNjsmpwvUxLc1a8㯔,؀*ݼ͛pqFo꓆eȊT?l֞o2g)'ݦ4ϧ!h*-;ϜfBW8u:>YR0lSFvꔓT_v/^)ֺFGU[ܼ& 97頔YP^[_M0nird9|ɖ: U>=Q"y%b¦s_41Eڴ{G|_XFJ64_]v@|I'`|E&eJ+Gꕌ4h&|ϓVGYi |?XCD0%`\c9Mo:xJzVM ʻ}=6Λɣ,r3s⩕s8+e4O MI_>@P72OnvMe )zVr,C?z hlr֜rO&!B$ ~Xhl ^|h&/9823WP\hY\FMytw_Yʺ*m4Ce\~P? 4 (.OŜh]64e*nz` 8hf+yvByd%# Eg oMΒtBcm:um*~sW!hQy$,78PzT -,Q,;񧏐4svq5;3وݬg"⏨2[*ށTmHಥ=T ed- 8n3 ۋUWN4|4 2$Ax8I9j*QV.N;J56O+!]=VX֑ I͖îtE) Ruo,Nyc, ~RRϼ`To^E|X䨺t%y%^D%V"MrXv_;fCFЇWJi7DDPo)~YsXx}%RS+TsW!P=6WUEk2[ˈza0e MqhVWi_Re;3U5wMF]l LaQ|EC9-#iV* ݙR7,Mt[a/lIr$(GبDcM3|zƤ7&׺gnV%&l0VȄ>M۲ 5N'Psy1Il;OZ` /C XOH(íʇ%p24!ed֞(~mZ?oEٛ˅FԏՃ'fi;ciX&uҴ$-'*19DŽm)o]9qYAAI0햟 4h<{#ߟuٶ0$&`r̊a BW{%f:=X7+rkl.lG{0Q{wL%x0X,n6?UM)]pt"Ofᢦ >Ora:IbV!Is=EVY=ڿH ^Dݐ ^mGW- tͺM,tc*&dVQ?Y Ġ~ije6w0%n=`U*l>|U=n(\n.! /s/@vJ[b.D9؄2R)TXItD_Ɛ]*̲ 7YWyFPu7SɆ `X .ЦhMOW9µ ջX7i/3&S4#.4ֲ{o}ʱ_Js;o~˻L"k7?"ߜAKS {>IT soNqI*KaH;2"h zXu̴pp(])fU =-w Y.I)dg5gh,0L{a?3dpS&y[썝ryvZeZq!JG7elo8FqI Ŷ YOx֯~>'DIe4-'z eޚZ+vSezA>yMgf(v1.ŜWD֒=^Yi?ZX2'ϜAWLmzeAEj;f V_6cXW:@ݿ1cЪ('XISRvD^ ]ee?/4 x8AN}iȷh7 10hpwm 17Ѱ T1 hq^x÷zI?g]| Jo#MlݣCwڮ<vyVM*ym嶧Nh@*yLl#! NbojUy8B(#ȣ[u k/T; ]O5/LAQB¥W%,2ot_Y. tEA9K"$&"y3Zpß5FO~@+z #<Еtg'nww7A(SJdgpjTk'#'>_ B[sN(kzB6}9ݣqېw@\>99hISr|POZI;7#ҳyy=BYuԜ=}^=3tS?95@'yf/ny36`933"zY~3|n9qn8"4`xVRb[ h6Uw͜{Zw0Mb+rzo\r~ogMK^^ڳ S)L=05TS`E22R%1~Tg`ܺ`$"W Q%cPGe~NǍ|(b8*.5&YM߿}Nzu欝lyU]ZkPPG[MyC{a[<^l67E#ZӀ*-#~+ f@)A\}%c, ja q8L՛i8"[a QSd w%rr73(ݒRw)==+¹ q@s9i_anK>V""|9r2qy~)/Gu?% 삹pMp6nREW04^uOAH;ditIkQV mR&oG罔?{)U^uƳOnV7,Ӳ$^#j&kDCܠ4UPێ1 ׭QaE<7wF*=.4>͂ =mf#ܢ?-=p~ FI mFA̸-cCuKXZK4̠uNb2}6!9kjQ%M^=9y90 qEw@k ՟P654Lo+ȷ۞)jY(Bat^lZz؎M#",:o`Jx-| k?ْ`|stQ[,?\-ӺP\-9``ݔ K's)~;dOػI#-"b"Y~VM»ibᆬDt+%NOD#] "Cgr["E 颦& A ]S'+ ]Jge_vQIH[Er?lH+K۟ wn2_{̱| o,tXߛht+ n'>>T,DsR;c^m.ІC6)Ru7wp]_ಏdi=;fyoNE] |l}|K;(mJʰ?=%ޙVWvႣB8Ц*UD^=h=\܊ǍPTzSh I]%ƳJ#oSш8ܳ6Mᦦ[΂L(E7&J-6gtlmDLrkzWH~}<ݱ6yXI<չlr  s8It_֑nS;}4#TRw]{4zZuigs iAnҚ!8΅O#oΤF6j=M|5SH]ZC.G^>)>t`D]K&_Pi']u淓vf#"[GVke z)Nk7&xbL4莋_ͳ!s #Q Wȓc{;ƈ{pyJON/gon_Ch|:_jW^?t<뗌J.3ZM׼X2WOi. ŕsԌ) uDVkz>J$kk:DVpQy ZOBH!ްλ&+J[7D&FS]U3.j~,Szm5húl{^zct3 O|8`5Sdrk%;0$R=|0 GP&.yG(ʄ3FV M|: u4?bbå"mCV|g=mK"ku@91jEeadC7:LޓfaIݲ'#h13r֤6Zڒ)汝E? ai"y7j5E^~Bʞ[ 8d24HЭj.rXZy7˂KI@HJ[TtY%miuv7' OK!=ƭTZɪԔY4|һN:nRYdw|1Q[U{EʒכQi-=2Zo0)jS'޸Ϧ'c_F;X~hԺu^gGИn+]}kb6$:Zԓz-JA(}LOMw9P9~KE!:/SO.ǺI7**(<'NQW*93 pְ;λ(y|*ͼk9l IQezpeQJZMP!W5Q\fl` )+qi$dnF2D^aU`Hx~\z2+hgtNYDTmpsam[UU IB'NRKtʫR]]=ݾC Fj9%cu&-xJ>T?Q28(}l^f+"jtl ?uǤ2hXw!"GdtWcm:A:8oQ=_m~DDs>* rԹT<~+opmuќrPvm^W,c1WN4ى:䷖!ni$ߺd? ?DAf!278eyXI=14qH=gI?ؐN*Hm]('44B#Wj<SvE_TlV:֐1fX_>DЖO凈z|Jq44L 6bn 5a7A.d;)BKgIْA1d zcfe2Օpj< ZAAݞtFn@0dB7@s7NNŴŋlT[K[ x6"q]i`lZ.wUPeLҰZNzĪKS<Ʉo&f7}e^tEG0{=KsɖpMQ&3 o;'Hvw˝R^]/}4*(Q_F3X4=mӋpרU흎0$(#\'I3ݽN0ߝ\ \F"hH䍇z2c߼Fwoi|yHl홌S۵ 41?L|E&q6M$IϮ!_{+.8+gr]f+rz>™s{΃TS zj+O/ELs P jKxF I?BYzb}$QULg8;=ØHmλfHj?<@-)tГ̈nH{txN-Uɰ%B_6= nYRy '! ?;!e:f]峑rR~| 9393lʔl&?@3Yt5~3,V?aR^ї՘5m!BjNi~cw,=,7]R%Zb˞ }(:XZ\:x_O M $ N$^$. G/<픀sfS#F߽4ݟq#Mΐ-3irauH4P\gy-]q!1W*OƎ Ӧϫb;^ipH頛Z z:l/'ޕmC/W ɳS8̫~ő {Gk;gh#4S/Vql[œ2z˲ 0W ! gD- uóneGF|XgzO#zh/vˇ5"]^M/p s"ߊL.[_sDz:wd|V] `shk4fqP23 B-ΈR.$8 [C}e0O}WL';$oNZJ 2}4ͼ8[/Nsɷͩ \;IRPYw2MB1w]MB3r?~2>\,2 e؅oDH2+NOkm.$W &3= cG1]B VE;]]Ȯ Q{F[qPRj&ǥ,<뤌'x,<>pӾ?>:uu%7 <܈-R:VYvzUr)KO}|< X[o`Wu{S+Ok<_́_+qBZg'ҍ<ÛCk5N:j?G os= gI:YOcg/ץFń "k";i K&kDHu,Ù.D}_>__|ޅ{ وa_bbߒV6 H:;Ni aޕ*76R(]%Ϸ&_vOt}R#V_啹k+[@z9,imR"}̗qr ιZKP4-K9[ 4YyƗa{.z6.7Z㇭<ڀ'Ԃ e)f\j2U pY;z`N@$ Pߟyvnt66d\6xb},s2bBzS(4,\`,[]m V,qO:okҙu(D*M5LAm~a{4}-j]P"ccĘQ4+xE!i4' hS9TT~k&z'9;v&:Y&<>8Mמ4A\0ϛj$4.MntW5#tk#D#"; K4ns9}_L*=J?Y CtkC(Zp}.]m]54cnk4"-߱J_'K }}lf[;llM:hKeՓR̐T |ONC?ޠaA; ]yzx"9?Ѩlxd?l @L_^ׇ<."f&vuox& \b8V!k^7޻IZT#h&/J]hٙ0172G{@S̚dw|]hFΈ:_v5*aDwioxbQr6 O'oڹb$[#rSNT0Ɛjs1=F3 Yv& 3Xw-5-bmכRX$cZĘj5/9ȅV&rI`75ɢin& I#fC vEtIfZ&J )f"aR%yмBrľ]OIdqv-#7ob3׮fBŤh7í[[aAELT9V{.f1C)'ڏ[wϜ5BNQRg|JG<2ރU+QevZu]^spэ6Jj3999& $g+;Xn|-ꔌWu18Mҩ;^6ۦ$ Ӡ$2'"9Q6KhYQ7tdzjFr3uVAo*O-&;(M<>q=&6`&P+PzW#}EA00OfU'u4hJ*JqewRN8Vœ"380=)ЇxJxPVqa \6ᛳzīR} ,̽NKLEwEe !qˬ_?Д8TwglK%L7g4kGة('J0)#?ͼ$}r&%!+УY;nU/r:k i'pb/Yyo\ɓͬ<&;KΝZ&;㘅ᜟlI5Y$,p,*M0Њe[p8[JK.6 {Y@DQ9,gJ|*g7;f.)`+5;ߠ߼(Myan>EZ69OHM{vzsu%V'\V;7&|չ M/‹SO&D,sl<)DL31;`~d3?pk>r/V ;5/o8`nT4)\X(F8.\|kthM&x!:h|fi (/o9}K]6 @ D/eS++Z>r׼a9ܝM,FMWloQ  g pv{@ݜ_K4[ 754Hm{<؏ϸFN oIj+ISh ˡhkgV>kOeΌQh94ߥ/yh]C$FE>o}C{sA4}nhDpv`hk#7~<.f(djD aAm-Q˲~hGG]J[.?L[nuY0Y ^)1, =:&#LU>mx22Pvf&7@zȄX{S{Ō=1}] Xj_vp0`C2z)|/e}N_.D+U?*gnm)6c(hrn>HT~sCذNW .AP#E5:`gfC56E4sUx5pe6 _w;B4)%{K\~sI={./7=i IqZT6~NL/+&e8BG)%y㵘Pk:U<޻%qi8vX-.i1 %-L,%aglx$JrZ6l4!/P5G#ј~Q׍gF/ܧ7f%9VO$<3e*mY3YQRU E]YVv2xl[o?yYeGXeWiϖ`y"ԓZO]zi }" (Iޞ~8m# izZR'7ʓ66xkwْ}ndX@GiQ6Jx fp7paQi|^*PƯԲCd=0yiƌ8G'xEC;VbÓ;Y@)/3c@MHu(A K՚x`B{;|մ|9rK!{6^λيfګ 8>_zz詜1#$bb קt7BH&_̳<+ Uzk4#k1#U9Uw!a6T$w[ɆE]!wj4($u:~dJ}~zNyW:; ^[G͊qdQMhhFHƤh曽3w%;͎hWB;K =~p-3C 68l]< sT@yS~ ;jL@]|ְ7cl!ɌI²TY.oR^==s'^vKٜ#H<^ZlŜ+`l~f[m((|^[]ܞ+-W§adž\䍾>rQo ?=b,^OA[TTz$2qD?&L6wJv!n'#qEc{nH9>%gF'GrܖoPH{ vz2kenN>5%ޝnᴣJ7|GƜڃ._ke!aZ vao[* Q 2^"Ƥ'T?Dc8Bn/se x_SiTpP0KeVlBCmؾT.@wE1e}>i+5* =\Xc QBS1gV{`uuĊ#U4|9![7|NԵ[%hso6?٢d{f-ɟBO i,F4v[0nIUj鉘7&xh#"=~xr-GBpE?56(_lɘۯ:Iܰb7 6'ȃKR&,K=8ˬ[7)rs0"@d ta7H5&Z:`vĴJ01K&ffb:U cM<#j !-seH}s>a&s ↄUWUߠ~ glQ\&9/cRWjIH>Fhg#2J4پ(Rx,+ HnC Y.[CA!Ӗ"L5@r Uu\ʹhlEmlj_^bMݷpg.^Sq]"296ULw<|B.m9A3'ةɮ&=I}KlDќ?Y?T9}hNitƜ5z ,ح.3."EvXfp#bR\TK>@oDҦkDx[RB1VN!{T@sb7AuKv|uho^5yj&Mҏ *zQ:Y% U=VnH;ϽX= v8n/DM0,0S B  ăY͘u@P]_xdQ{}B˛yahQz-]&M;8M6nfEE|377zGfOf6(M$~5T˛nG$GBId>:GQ{D#ç%=AfsL/2- -J$3Bi_fޠ5),zj_.+΄+ ?#6XVgD~t·ekEǛK[oGxn*k! m`U¶Y*CqBl7j'Nhw/k'26y!"5WhZ\@Yi[ )pѦ}3yzwz|;ςR?_Ӈ'2kOuݨӓOqA,`˹2)_$}ƒBÿv3] ]BכM5OjoK?& 4L}('Ӳw1GailKb`ض }#z ?4eO';@?FYLe/x/O^`ؚӗ); _$-.a Nb&eKrd* +IE-^$1)ǦHqH:(|Y-j}*o*\tGO ,'t; 2U7U |tp;VI\J/Nd[iʼ'hi B"W\8oM.&X[.\N#ҍ#]!{~7\'U2G&sJ^VN{tGT(u&P`.[jW7e'0G\-;eWIXs/GA;Gr[ l TT7j)W}vwqش~"m}DZr/ jc̕<1?R.cOn-UZ$ m8 8P$p^2x#ViwpSsUjlik6ZnxjtI#]e7TfKJ};)ǃ1>㉊$~ew䯻XZ/HCQ˄M?d%p%_vڸNIIM]Ȱ[ εq<͙kҧ4 C?n sFiOR`kEPКiB/;dLhMЃvst!jX١ an5-sm'Iޠ90]젫\93-pȈ(SLJM1rwI+Nl<6.]>=Mm -;oQ@7Nw7̳e!CחI{7͒B \fClt3B^qN?:XJaʣ ,]]a~$(Dae>ĵey[?'%bv űis2N9ef˕vV_t{;@Amr4_\ݰU5X2Ho"g#[BV#/g|,aҘ'?IofY$>6l91S^*l([T<5u} <~0ͫ{xpL#Φo r vRrœs|8d4}- '^)•یr~ !gܷ]Po-jO*ǎ ~B?IDn>T1$P<}nv0+8IOP"-.jbU ' ]b} zSXCŲp"+x|q_GKM${γ74)^/W>]Da|yUTUE4UwLD؁#r,'ïyJ})Qe`$q։88eEX_Ew[cU(e8'k&p}AE 6hH^M0.EŸi}'w:XX.#^?6.G˯;ԬDv0pzFjfayoz"QE׊y]ѽ -%p=?CvY{.$o7%w-,с%/(G̳RNxs~ &Wނ%o`[ ~rR>yKe"7MlLwuȡAnHޤ;8ɇ^0l }-Cuyy2$1z?Bow1K GohTy P}u=CJ曾IP9z,npξ@WtQ_C!+:FxMKrV?;q.nCqڃQ,=W^{ѕz?:O3!yxaF)py>8o"k4?%|5DJ 'Y0p9w() ly~1:VDMNKM#kѴBAylY7UU,:yaA=@12KOLc]ws~fƝ#>BQQ3mF6#4= l } ?ٺYƂn#Q:o^$+^N?S͝蕤K8 ˯^C) &U6f2U sqʛEYS YA,t(|iw`z]lO0pˈفݮb[2-E^)> ÓEeA̜֙yМyeIُ833Cxjv6HwH`%\$Mq)#:8lzFG~KҖP;u%]ytxv)Uge-l삅VD27j}rs.][q=yS8MO"&:mNjXǐAOwN [K[<ʫ78$QۭORVtʌ->4eMЕ%+*|1t-T*+2ݹ*D\wA8%8Ggct/_du]]BKRof]Xe1{zƍN^qP4 y Зیp+Vˮ̇ %4ιfp4׊IYWҡ`=dRuP{lfWꜬŐ_jK4\n(Ѵu=]fp`v3ɾ&䗺}׳Ws s 3JI J 0ǧR7 eJ<Jb2pX&('ah @X&9ݩsb py/{~1ygw.Oc \ aP3 5E+ae~J ]1VEҰQ;n@A*K2yBneߔ!#RyI5ciB)&e*܌ٛrMgoryz'14$qp}`䌁7_|+LWI<rJS}3vSFxLzf _,rStLKzvB&8fj[!:9^I~-Hj jB'kgn8ݟLeaFGKW2xsۧ;e$ RAe=8X'y7K);flNi?66խJjL̨_>XMw$O_|6ۍ䰴_ JYߙD#[i$o}Y^*4%o v*]Je}r̀A5sz?>\FK[QyG_`))o 2#B*Th6O*g[kG6b/x|@!#g]0D2ȑzt76nfs8,S̽v3F&r^%}s0("ΰL͂[}^CVG7nq;2}nRbGy'I`.E$F7+иY{*=ϽE"O亮ƼcE@j~nvX[nj1B+Gt߼r(Isf ?I=A\'M.[V'cE[B S9᛿WT`ڴf@s:916b!Mz84}K 1 <ܭ_fN(ŏrs[Tx<0ntg&BkBBV?`/O 7!qOeA#МOM[!( K¦mJ*w`HS<"as^PN71ӓU2ՠ~FQ˷LlMA "#C1P_!7 :"ԉ17C|0+9,oY:}ڀ Pn=Hdžcũp adӔB M5cy K3 8ɋhq60j1  nM mtm]^6J_BmӤ2 vX]9}D߁r!o\4b)A$Gy.MWdzX!O\!bލ(πAum [\7,dCo_K+i+!k=byA'v2eg4N}ǡYS mi?wUvTxAR4Xq 7-[v.WeD[Cٶ$|23h)6w͜v4hЂ;6 ~)hEУY#ԶHl\);fds6l3SOFJ7q1[?XʓշJX-XwGsGl#׏x9'nKnoP0Gh=ԯ߯‘ 6BiPTmL9ck0>4^αLj1ðϱVoI1y k W";$U!Ni 4X󂁗Z^62s q@९ʒD6;֎HXa-vmwU=-\&=WcDSa>RCBLYIUPe=)2$/B/v2)4/[=X .M%kbI/on' Ү.IIE &ElShxK~ #4M֕6ˬκѮ"q7;R*xcZ 8n Ft^ KOv_n{?sߖd9n3D]7WC@7j>mODE L@+evy&g&rYn1x>EP¥71o3L!OH(?#8+TY ?4͝ڞuiP"LX_#rܳ,H\l?x\#,k˄&kmd]  ^}#T%'oiȢ̧6zf~x En=Rܓ~@ڡO.^%27͗>a7+L7gZܲ% GB\TCﱝ-/&@1W_WnpvI߰*{*,1]*w=k\*٪<\W).>KK$ilU7D9D#Qn6K( )XNP$QI @,yFnPOޠMbL>ta?о-, ჾ{5}ɾzn89n_'s'Ʀ$']T- ejw7iy67 l;_~ RB1U/1Nroko857w\R~kgoֈga Kh3rc .Kʬs$s_oqnY7"I$apרPsQB(At?pC7oܟJ١ߺ3÷T.ShhʕF.77+"(6Wmnv)ΧVձmA8#kEJٽաz_d[(Iԣs,(Y@e2'9\I٬'g6lƆvcq厯ؖÞ\+W:+2/(٬>~KUdY\^OGoX^x|cV&X-Ma;n|G;Y'7XBٰܵ擳rV2"#=揟AWz~ЕcÊJ^\ v$2A}R#STg0􈚸!h@o,nuNސ<:yCcRZuӨA e8[C<3y3ܞnFBhzV8-{n_sNo#$K7UuJ3 \>pmB&2x7??ȫRh6_ǣ6ϴ'ch~wri0zעeXȕZH|4'`@E2FH!ߠy7˲jQX#h5#> .ڄ͠zݬ+:EQMAj^: ߋ0[kbjRQ~ FZ&} $mVXfJ#ZxQQJkZR3E낒3n^o4qED\8'sTWT?d* RG7z*U]l<"|vYޟh.L&&5Ts^CLFYbkB!y;=.,ٌ3rv9cɎzb]UtnNaLO):#vkʗ p ^jh`Jf{X'O$T98E'h3᷉^0iT8N0Sg'dFf hM0aCjyk-)5nV!?)B hedjCIТb>F<>[ Ph MFNt?hX1ê?qzՎd1 %lĄ7Dzv|u&A"V൓{yxAGULLV6P= teJxTPчWYXN ?ibµʌ:UO3p+^.Br #dƞ1Uג'7{02T,YGfSѿdyhU<>ɺ-*ڌETOa8tjvK*8 k]ނl'q_C&jX$,I]).0t: pLj!fI7-ՠ ZGIֆSk?4FXc|ăR/"smDv(ldI` yg4^'+"kagtO7璐Z}I~!&՗7L~Yz|f[kWW 0n!s|@;`wWoUnMg&c{)mazӂtXT槠:E;YuUKɓ`89* U l j<]~٠1F/ o#_*(y_&"Ή{~[.T- k$3U+~!LlM _eِɤ+sL0l #`*J1/ RA1kLN1t{)?\fToe$|O>k]gQL_ABF-s"Oz™WL-Ҝ5<Ě90YQkP)R Rf'foLSf4|1a1yǩP? +3s٤<+^¦- 0q}P.d,eT2 ^QGeF-ck $I: 6N`X5?5N E1ZM2cPhV4) Xi2gӻ9϶̄~jeDqC 9u+nrݛ!hݺ Ja(!Bv3>y@e"nHW4EKE?m/ ;U$)2wJr7jz^ D9f:JtBNU4-V}J@\c'XQ, '9Qg}1XY6-,"a\ߓBUD WjC@͹il4bӇ V~Ռ>f"IOfѺB9Z5y~U2y(M٠Boioٺ%(KS|k6ug޺E[f@1Ԗܥ:?qXQ[I>fs#J< b.frw0GymܠZ\\;-.sxfvڀ-L_o;13I=|#sƦ:yI{E*'ūV^<8f}ȳ&R: }b(O815@ڼ-ar}SE/4x䗪ޟMï9 }2zs"ii  y$]j#A)5\`2P ݎ'gI|]Q IZ * h[m+; ~y'<Zw`y2FuD~cen41Mk3ݥ^Yل,1xHУcSBy.pg f4Ze@_N(~M$ qk>6hun)D65&%?/͐oQ󕛸]ԃ6Ł2GR64`ӃMå\ mmJ==/|m'>$̚7L4obþhE~/3#00<;d|}\JecD0R2ONwLTNiU17.gvsyxOԁ6j[ ):Y؉9J/>q{(cs߲4{v3Skmf]hvP hjwzPTXLf2ycz0GӑWCߘi`'dd<`N0PH#QF%L'q|/TSNLߔL[gF=b;4e`L⹧`a~`"q3z(ͰwaoSUexOb?h-1GJ μ揚{I `WFi}Azqftڃ9&l_G SECR$@ap\߃f+By/ W3>`/)m\ N'շGDT'2ɰo&%;n 1'!,Y'LPR72DL.&4'~]f<ʑpQ",SDcSL0OG~ J﹟L}OIV? WP iQٰ^a)aI%5wg11fy ӳw?x]$mQ by5 sq\CAt~0ž&(_rQ[kЭuIG/3~bpS-J(waPFq,PF?P42^+jۀZ%yCsK]}V(v|>Uc &cU^ :,J-YfWzy̚!}5jNm]s:h^$cM\8)p#&[\.M4=ؓ)if?1$v5ŸNqA5]Ejo Xh}TF>9I$ᩒ'+ M7*G!à (QOin>Ep܁4B/y,Mu {΅cثvl!<^m\LsF4  jR N60Bf(AQ9+̠5P̭Xpβ}|?fsH*JQ|fTTdcPfLR/O%-[цtfNpS4KczkDҼ1}kZ,lÚ=WK2UPЍy}L}`L0|{`}n8o(dyr ӔaL޹6%]}tϼ,,ݠ9Qӧ\!moԂ$O%>uLɎ*R䯔2uTP_|XfG< dtͻʆe8-JGE'knUomm콗Pw2OmΘ,YQ7r5?Ë}қf'SG6r2kJ1bL ) b=5oIi2yO X4EK*)ɌCϘB>A©Y7sF#;i&a݊8e9v*'d&c;]i"4ΘM}KQfax.Y sҰߜMc%Bo-BS(FmDyJZQ]c &XEX`5Q|Z!0zyM>ZI}ý #SApFSK=i q\U oaߪqf(NKhk/-V~IsɕIAϜfGKw''i݆O.E&}AD "I(&PYBtװO$3 R8;#fṅe^jc]i]@PI[w8tV;s$Z 4켑(gYByI!hjFKj9 v8"z 'ڄez՜qlYJFrMSu19ay~nj/rU,wiGyFRg5TЫV n7B:$qI2@hyp9bv;h\Am)N!J X›T|tn6TANI!\޸<IYJ{T8}.y}o"3$ik<[$4 5/xmʟZLBi*4틕:8Ngه)PmseRhސJL׈`Gg^]m3^$݅n&+HfGsby(~.fia]b ڤK4$k:q[NLGhzW.*h~>|&>T5Rn 6 D3ƌzUvi7gmS]z)U8'儶k2pTYQG0_PT]HtJG*2*Itu!й_5N l-ȔdcHV@({q*6H}736 [1JoyJ- ih08nL/Uu^ҷh Ge/tic { MGY&4o6y 8L< z]WiX]-v2Θ@7&kȍgUArwN5* ݂%X7U.U wΙ~^rdht.u=C{ -/ny̷"H+08~}>0<QUP?ֺ1_#3bQ1;ʯҶN\)B97գM ZRt;3Կ?wdt8Ɂ㓋@_jNJ XFF |VE՚Z@c(TQD&)M!(`ÃGE ۅ%'tt=:,# Bqm_:~OG(g}0],̤;=GUpD_늲^8Uaܟi(5Ki\GMqْ= `hj'/;Ky$U6u2]EBu2;߭~lQoex'(D͹QXuP[Y>9 HKrBGl40Ga4۟!P$z8rJh4jɬL5}vd,n1Dф`P~3G{ggyBs҃2w8}hZA#}4CX&MJtڢl=4EI<4zfCP+ 姫XGИyMe‘L,UGrXhYUfGKBZ =YP@u nM~R^> GXYUCYuџŎdطY+l#.r/zL1XZ A&"MH6FCoV4E~+q~=0^x铘 wgpoiZLW2H\I*w{?;b{]#owCMd^ced8&~{m*4_31cü6([+dD~qkՋX!* UĞjDw̴ʍՅ̠-O>y' &hIʣrWvq1Aofz6TPhp`PA3TEC2ٰ@: իLƷĘ* xYVLҾNǥ6zǚ IWL+G7lemN=siv[JI?,A\?(;ΕL`H,Lw%˛hN~͟<3AҶˇ\{le/+D#/)J\au_ Xm_iQ^pɞ>UVԐè%Wl]t! &Z/$gzoMEL-bڪF6m0%IB2Ϳ+^j _" {L[F%Uڕ{[Im@[lcsN1&#]ͪGWPTF=*ڿ֣IiVLɼiθB$S2 !Ww~hFc #) .2$h7MïTsnr1@/Pr:ዑPURVШ6:FEs^A_UϬſhi#7QF>9 Upu4y {Z^%ydbumuvnjm9Ǽ>=5"}"ټBMkfU8t\Hlʛ~N7Nr "p# B[Ȋ+|Bdt3Qhql#/bh~lEӋP11 (\??єˁzEeVZ{:ft%Y Vvzer2;( j@Eoy?3?M&iJ4?sX&s2/xjJYQc<9 4a8'5|c8VM )}QlX[o&Wi5#+k zΛVrj%q toGZEZfVXVfs 6ziΨÈf5yWDmscdt&UIs t0z Yj:Y֩6SINCzWXSUԼDtMQ}Xeዿ\M*k3KjbUz9 )@癹9Z3`[5yw: hq| ]wbz2x`a֘CY- 8$57~,3~ R?a7Cm 3Ly{mp l?Z-۰'O[D6Ƌ!:V2/\jM}y~Z4}5ϱ3>,SWS9m,#L߲0Y-41w'҃nƫ̋\2(-%~]ΚTvdG_0lvDNk ب]SPA{hs ZͻdP6 e nnW?2!ϙFcd*]o9QkY 7[q&k똊yZ: uH%FnYkZ.^ D2 `Gj;Orp\hnϟ9cc4ۋ}Go>\9WɣW!=FJ~X@Twz4KW:bÐڸυEa`{9o$E8öCׅl>{k2K&%# .) M^!dj[ҍ{- ںwr7dP#2~xƠ/wLhL_P mWE1;;'g~!3iOB( y?Ducc"S=o)+DgKuh.vN#>("(Au#|mOV:Wm*?#N>`) qld6C2y4BΣT`~n-҉qBcEzR%W`&C3S#Sjc1xQ^Ty6L$j=P.\CslFs?)_&P 2͆2kG2?BVTPe=*aJ{ `J5,LT8C~r7d=]YVAAق!6>| DFQ?'TI!*xLEy^0owv|0ppV y;x3B;uyPe J \3ue}u)M"tAg(=GYgNB^2<ѣ>-z:Q W_A+-63\ i ϸK: ,>V7HqY ͝5XGeW{̱`2upb%_1r'WYY;oPP >]Bwovv'2W-'xE JM5ŅAZly@Ӭ? aUxɏֹe z/럤 SG(шFhY[惷OQaMDS,QنnEvY'ƥd:i'=Qz׫(Ldc/ץI墾EMsja3HcFo^\>%KuY&CWIpc.#`3l.ϸs1Cܔri; 6r7a(TOyDiOOS=w€2G E[:moe8&r&}+T.Yi6n 2Dfx-f*n6I:AZ7ݼ઄7}k3 T&3{t0v9KP=O>]΃?q8lJN?38 dr8 #%Y|]iz"&(#۰b48-48Iar;'ލqM Kƺot&ss՞FTh@O&ka:,rwgfIO[UG)]TfO @?UP:ht2gJe"r1 27K+vw T{"7Ίn2tlCumuK'kvQ|%پ=r}ˁ!Yf|X1=B&r4Kcײ#hoPb'`,{2!gW'Y; |Bk {l/g4T*))šY7%2+TǴd(sMә}b8+[dVB"v&},e7;I:v5lz7('Fʛ. 'pu]Z:ʑ{hZt7 =l ̍:bxG~ՑB: SJQ}xuGo>JѓU~SU"I fEWW,£a C̆z<8rdJ-Hox6ּM4^yUVu1~z}kJE&ٟ%e ņy`zWF\0a.G}k/CogG'MsPhj'|zהC<XΛMU-:τM#)2&RTrv߰Ӧ\[t1:ԭb3Hck7Ų5lgӲ;h}qN1 7*2U-]C b[7vΓ8lp`ĈɴlW_օ/^ Ze`e7Q|Ϋ LR䕁_^+&m )2w'MkPcFj9JҍG,{ۋ榛R\K[}Rd8o<Е,ɧP,N(}@yYLR .z: sͣ'?wmɝ;}M28IQx~vo]A3"B<|˸v2oIsFT9nQPBM Irs:9)vwU!#@4ڒ>]S'> v[O>;ISZ!mbٯA"yd/Q6dkhhgitm%F&Z7^F35Ok^8zYM`=]!ccl[aXe F>OR[Kb$DJKZS`[Lq ;-uw5TCɮئ%km2?C%vVn9A!h#vd T^y)}'tl)=#EW) npG]ݝSL+d'fq[t`?:EbʸS~L ;UQk_A\' 7z}uSLkFwpRt\IKuBocTel{@_39 iw80-$Ӑ'3hѶ*lXs-]!KPO?0ʅ[:ɭsQbOViܭA ؍{~J#Ξ ]fABIFjtǣ 4"=, 9 O3o 7(:{]Q˰9n7ŵ.x= +Yp5i?oVܚ.*56zv3EsI2_\T^A6aRI;o ]j?m0ꉼg,_(`wXZw$s-pMdt`4KXkWQ}1\⹙bp'@ӦY odazd^Qՠ =ڽbal_~ 0@)׌nmEq++ s #@&UhqV7`#~hLo[0wZ-ێe1-,LCQ < "7%{ǃDkJ^^2dR okthHOf{ '[#0VJ#=y(̖aL̎uA=co`}m-}N( dmB qlzEmS-_1w>:iO-jXe!kl/HӰH`vͯNeheaFDM_@6|yQ:ߞ & . }- OfGIUB>+T`t?g~i>ϒcv n8XR^W'*> FҒFcOU~!뷂x+ng5 ]A`RyjbL4 FNw/e퓿QzswzyPHR6 ݓT1 Ʃ!i=2.ĸCG$z9t}>_+7_O0FTVk=hAy[C fx{:7h~5_(F%:ꘪ%iФV !zޙn儫sF%j9 m„Ufޞ'UCme0xp2ǭE?³MREc%o{:^2U*%uzrM6X]閨>o+**W4qGdxD$ \_Zo=<T(e}4_;KkV x2^,0Ǧ!\wi`zbCU2ܟuQɰ[󖿋`xjhо72715ju52#W!t[AB**U&mhԜeDo/䴣GbYs!ٙUybJ͙v3saCDJc=Eͱ0O`o0Aa}@YtN1aR3-Ͳ߽Fd#cOKhOR$Ǹ!ͫtmO<@q9k-̲AԚ\4:&t[hWYr0pAu%v1/ݡ~+ L>ppiXO2ʗԻ[Tg+ƒMZ| u>+6߸sjNQWߑK}Fy"P헇6Q2XИ]#) ElH` ]&݊Sd;Jq_%SĞ~Uq'ApU94K;0.&rXزIŚaf"(A/"i{L#*U8yKr[XuC_/4Vr/9_ƛ7&$o!6D;CpOfMG(2!"$'iG}șl4KK`dhdheh̢&7Y1ݍ]3^W>2GƦr @Av|]:mp+ ܲ^& ~[0_clh7wy)|V>uZ9WjS[æOP{9,UO6]ӿ_4@2*Gpctۡۜq/wM~T>mkc.z1`k],[2{~5Nt VҐ⊜F9קy"`Ԥϫ1#0]WݬsDХ10uc 1v6-.7(3eoΐ;BeunYP4)YUn(4FUt+{;F n>I67seޘ3 [q"8Eog?SI][]IaJi[-ɯJƑˋp2FeSOeT `(,i.: Ky,9|qvP' P8O(ޙDS vK4$P$ hG(K#*4L2*2@+K _5  |IgFEBkRaO]czon?vhz! *yfN  ,hB;ߠ_)"b{n8.jL>\B;~&_aCw ̊DXp| M ԑHk&tlŁ͒^ uŻ(ܧ%~99rwyHw{l D ''XYA݌AgGP\?Oݟ7 6_m|8ԕlt&n Y_vǡôm b[~MAl,>sP/j;v\@Z*p4#I]˨'2̝S਴>WBLGdJy{!]rCG L}lpA -iaUԼi@B* Vh;k_gRDݝ*mM/oiMQ >ke,?c"&dG{)罂ٷQu$ E\F2{-Au#؍,b~{j=vL&/|+]}i;m,;9-U~T<(?֧,m sSˣ9YJtyQ8-/6: x5 REɤ/ d@(͏37St@2wLjpD%tVꪥ=}[ 8Gf|jRGK퀖gLUyL}>~}nGzOvu'4y{#Ш&TY=⏊PXa>:_Cd3ƃG^9i~tl-S;F NPCޔrE {(V]A bsVf];g1`{󵡄|?(L">9-V x5C5ϝ+~e( ZxTfCf)ʣh%4-IN3ZӠOJ/S[`HֿV,9q .샞8b,(,IhLd[g:|0r4p%WXƳ6Ò&jsٰסZ$LcZ=P\;c>섕uJ"R}0inyrrydEЬ2"ۣ8mspA[`24\QpY“,c:# z2B|O:\ψp4IK~,4ۈevUnDOqVG*0Au_VWL(|bio* Nï0=YG(qݺ$$'}}^_{}R䦅by $ 6eve :<r#($Nw-76&+]=ow7lo T5BWȳei{% ZZϲJ!*`[)bk4m+V{e ӛT>YI,G,+Q7wT| ~DQ;8Z;z+% q6>OlXwJYv+yerwڗоJVffz2eA~:5)гޭx~L quܠNnи\䈅^˨WycO1QШّKkXcRyy4+o:Eh~@ 2I.! t滞b9^X*[5'S+fh\̟\sYRN{H`BYKx}L;ȴf"RQ3En`В"S E\̒?%%_x|k։= ͳ]E̋tY<޳部q+{v]B铴>P7ksedR(`Ec2$ՏKlj^5-^,VTq7MaO"ֳ Fc u{ 6mH!@zI(\IWe)/y}qw|YQf!%קĚl6PhN_ 3SrjVxJ^& eC %M}ۿv4ȫV^vG  sy/n;DBjIYU>pU1%d)+1;%jЀzU:"9-C v(L*Yfȸ{;A3&$ܘO@ûMc2̈́`Qk'D4WuZwwG<7%9߼9Nf7HjkOKe^ڜo o&Pzq-;,AL@5 %EzkǢCT8QEy [91ZpwO)Wе|'2-Kvw/} o F)_r'a͒Kzhy.TYi~.}IW6f7/yt֗s-]-oJtu^UWGٜL0GcDJ} ^tJ2/N1C%)E,!LjļViG95/2 U d.!XQJ:}aGmv/YU觵P:y[Fw}e^cle>?"   2љ|1 5)0l2nj|=fhAߵ2@CIہh!\i8` yz3P K T߲*{+$bg0@Q]D<(z4 iVUP9V}¾Bᶌ*Eꅽq ZN ZJ Z2flЇX&|DZR ԅ2%V. 4>m͊9F=VxyM] FuX"?cVc^aɷ`0pp%![c]1̔<ƸI<˜o7E! 7\ZAĄ_3vҝJ;ǁ6=q')q-7{8ϑl9ͺ9aM3Urٯ1/]gi^f!|h،UȦ休cmxV~! ypWE-}h{e‘&lDr+Dz5w:lrԃ m_oEЏi$7eX)RC[<\%MEe.:жL" ==F9H[^#5& K쵙/ܯ :bo)!|CE5k:yM~p\aGU&Ko3Q~pc36zevKer47zj>L}N$D\L7;`2z{TlK%r )yUҏx4;~\^MYŬ6h5^\"L*)`HkҾ.-c?*憐o<7;lޤU?)g #ps̍}p'mv|<7ena7NB¤+nPf8rW4?Br\p]ؚDk^)@ǩ0+w'l49\c9\op^Tua%hv֮ ʤgJBW2){⍀ k($E5+%mՄΐ$VX؇U4KԘIKz9\Z3Z3@5EM.$%aLD,&||(G"'#O1 .}ujtw簨tU#cLs3<׺IuU:](hXtMVo^3\xlJ ,Am2ke3`ETgcpOo6KuD#E[҄4n,/dÙe m:]N /Z:5"V Aw^VZL꠼@b."s̀LknAam+j`/?e;ZĨB_+-6o<sfN9A^oo>Uqg-pIM3852+3EEw#tK&5Mp^AfA@Jq{}m.ր̽dTZDWQ.rfxo+wl8ن7lP^L\4d8ӘE4]c>ByI8-3BYQmpsn{'*)d/,v*әjKHͫjheFXRj0k=YO%W]r͈1&o=$[R0a ߮2 HZ=kc5?kGf>ǔry,p*?zȔsax",p*F$H?y, Q((Pݠu!`Q!6 9r V?&?U~0Aba]N o' h)$6%u z<adZ6Jɼr DP:|.M]x ?W ƗNgW͟%g\4[*94Y"SJ9O2mޟh"1}H7hۈ&V{"7'O1߻1Nj0>.H% ~rlЖh~flݼ毆}ѽ1}ބj_?eS?L}"Os} GpOr'[t KyN*.Av>4NG?2'>GKl`_Wm+yVFt{V֌{Y5Y_^^lc{h0*x}a/#.^ uM@}sj2SU^2{أq7 BYZ_2þ! rs} z5g./1%^U+WuC1 623Յ<#ވE<$7J׍Ofq)i1sUx(%_t+TZk<{CO9&j|t ~j,[/# f%)Eš::h0JިhғZ[$)Lz#uB;o=)Ip䋪H2o<6q*+z;<|4[,I8C̆ qQ[TP{ T~ʹmUI7~: ;_7]ڑ!_x$XgswH5qA}nϰ xo|Z束^ g cƶĈ&n89:k3GH%ŕ㘸d4ͱ6c,gWp)}ߜlpg^ wҤG,i;<$fo=W[>%^Bƛ8a=F+>tvPzQы^&|Ft/ *#2b"~9#.̨t*Y-:dC LŜWmNBa^8CͫlM,bW ,R:yٰӈƏzܼd"r `[V `GGTtfʈGeL uwћ:ÇrTRU!Vc@3yrCYDs}|ryhrV!HpA jO^ Es7G8@ii\?T4s ;.tZȗ8$(Ir<` VL~!GW8t&+/#2#O̴k`ne6үj! v٧MhjM*kƲHq}4ŒtBZ/9mТt&s[m$mNù~([fޠ6 "7d7 Y~19v7]'fӁ^|tKuEMq`?39{?gY,I^i<I͢ԙGO<ȗl1^T,)h%m5TUλ鍏եTT|H9 +[q@QܼX'9օB]J6Nm0Qk||nrBNp+^׻ K]'{I~62o2 *ꘐy N[ bt!=&rvf?ܢI";2ğ+jD(Po+wS߸x%z)o6E ­#v~Fʃyf7o~xΧ %25B%HM" ߣF4sY4f3%rhqr ^wۼ@ÿ@}ll~]E,VIkc |*/3pPA͚Mexyj[NVěy(ߢK&nfC jeӗ!Q^BȬ.hnʈK\a+ 7t?2EƓ#4 M,9!L]:XT;*]T4lt*@NEj[008O,V8QlV. ps##W4}cy>?oisƍʋfe^ߡ!(9?6iJZYzOV$F̪(1%Ԩ ̨ K91[:'#/qTYa_Pw1>Gr.w+1w6,̨+ <3Rq _ѴGMʻ_7?%SII'lѴxhSAXWk%QU8yX7l YQaFMeJ=Q=qXqb1UqePխC/ei`^GQSڇ0SRc:I;yirkƸ@ MH3#h6<窗'ڛkr*G@/@i͜w!3Q/g~>SK3$iBޘ AuMwIZ"o:n?lخK钒ZQ f6F̺I6TcL$G0idض?TUF&0x !@?ڤHD?qhǔԤG ic;턖y_3=k:<5^!߁rZ'WFtږ+96!$r ߊAwXLV څ`wyjwbΊjٶp$xh~}kr-B=~&3jȼP?iZ\Q8gʞL DL(Zk XW,9c s.'S|wX^4E 斣= MwN=o XHԕLaEț}ob!<=.%eLvj%*ӾN343 vdJy (IK4B1V$3мѮeZitIceKb%9 Yoc>&r X9}79(ygݽ%{++L,m|qo3.bUZWkV3l{Lny-pkkޝ$vb=ðWlH4#pV~#O2RR(SoIgA~'f˼p:_]Q07N5g ܽ@ZX ]^bvTSP-·2,[l<48@m}Q }*S[ 4GkxE}x`^dVS&O0ąF޽m#I *oFS(#RMpw] C^+JeˬDr}aJ{&gGo2TN봲Bz7_G@P\9SEt@7Jv{Av9NzD2^:5o dV;e^ڱ?>3^ w.r>MorltPh,H`&5GO6pu9 Z63P7d|ۄ k?C'JY8|f z/H-hGG*̻كa͍=ѽn`v7R0.ӛ]Tff-rSwBq" hXz9hڱ:,m9nU`Myt?dzx4n8mUrekr zHqgBB>VREH]υn 6)'HĤY{nYm=GX e5jbDUPKp ye*㕹; @heE%ȁ,-Αc@ra2$|D{5CQ*/*7ɺ]N}f1 *Hg^aaEN>)3$c>.LXlx5v3b4O/jhV_R $ y .#D%gt3(|o-IìS]]]CU,y6x}='yc?}25|d̉`|氟g;P^=_̸dfTf08Kӛ@c}oAu /%yĂEWΉɃ#lpY~j7~n-aGqs"+ h|7?!bq`|+;ԧ7F<y)!*{wbbce+\oТ 􋂘}xev\֎z3e~d2NęDN.=A'4d~]87Nqxߢ=tg<'.ޫ8O:gGedn~ݪ܄Fka-){oVuѲ&@^sYJG7px?|J-U\Ղ}ࡔ.-rK2Sae ,"@晵Maុa-ݾ!JC ;so1W%V[{17fcuWΗ24RCÑ7??5M|k=2i=BnzY(mgF_1bF-ɥ 5XF!u ysO uxa9ygلJIϜ_:Kޮ 2y"5,zLQn0t1=V0-yΕߘ#/}Z Rv3PN] p[87\f'wT#7*=?vtsJ& łot<7 .2Yfd>,e:3QjdzY^ݝ!z֑EKYfБ#wK,܏x^2:ljOgAi}KxTϢmWxԨY GYҩY4\K<$&qt sQ 7uzTtkBQ9im8bDZIUE]IMCwCz^,i~o`+s&;bf2ZM(̉{k>:;a.;^W>Bb*L8Sf!V2ZYB+f#@|#>@E?0M2&M%ZpU+Rx,n~2U5gG"hG8qm'nT j U-.Ȩc0^&Ar͎e^G7Zs-|5 ŕfaLhO&;۟v, =ycZՋSk۽{%B:|cL)vD%3kdR8qF&AYѧ YHJ+7OtA)ByMT.]G>k,]H͒ՄfI$n)+ 2RYQ-pEkCO0| ;Cv[!l>#5wK-S*C*LLdXj?`NxfT[G(>_lǾ qr  ,V|/ Z0eFT>xQ l"Λ>| gj&˽b{-T#^G^a9fʁ!hC}`}FJMU86N$ʔamD,ũ*XxAݠ\UKҼmwKQ4*K^``sd+6飆FpNcrm8m (jowwlx?54CM~.P^?{ 3$U74,G9`L._*Hyخ{:;=ذ0A}mݎ|t\yuɠjl෹EW 4H 8|2ݯ ?ef no1Pڄl]2]0!>phz:`b0F C,jivWhNv[t!B6\" )W>Bz.˝~л O@?#-f?w0:-l@A6wK3Ez7 +6r )MC;=ޙnt1&kv:-xiok[5izU2o9{lF %;[ŏύ08r'TFS>/ѣW7Sv)4wk[#ŦCųI<7|*ߪ^z}PM5G55EPh9j[nz3WRN46ۮ5yэ薗{kJ4o=I;\$Cr>6g=Z&*~ϟJ&(,v 8׿Xzqğ}bڪ]p{,8KCͼ943sB-,SK>}va>U+ z PY3#c|w,O̲ 1{y _YGuCǛK-#OڙJnܛ%=0x377:[D],{\rL`Z|-s:xϭ~Kj:N{ cYew0w4"s1ż6AJ<[=d̥Vaw[P#HƇu 9am:( 4rX0̥+|gg||+J46am _b~.IpM*!zU|͌(P |?G4wɹC̣oF1!>$-r>X;su,mI?'aԨ6v o0tg㒈śyDݏmPocN]{3h;7i^Bc=`Á[HK+[u$эZ }^ٝdkX乹6#\ Z<-/ -||` Ku̍Y/`D/H*5jlj\ QRW.J[}^O42[e9ۯy{Z]?Tt)v#EJ>E63׆K[7n|2Ɉ^9;a-+D;zQWfr& %X%usy&d2hȽwp"J6= ͞fOøyYSJ2K _d2T_7RW"Ud'1jN@ QnY^r٥{bO;.mg7VGbZh*RA3BwR] &_EZB{՝ AU6YkChZ7.BN XO8Yfw) k]Izċ ǵF@z Uټd$3mpp,JyMEFzwMg' e]GG΢s gK=y=eYJ\ñǏ6)-bD3\UO$u $qrzYrA3ǝ [79fZ5x XC[&Te^C *WBHvY13]Ԫ__̟&F<3Dn&]C˞y O#վBs̵&ݾ48,~NDZ1*ujT9 |>!ۚfQÛ x~Ç7}J+('ՌRG"I |z)oJ>]4l!QFR!@P4N&¡JvSЯnG|lᵰz˿fAFJy3\c3hZCsJ3)O7&dZj5,gF["3ƈNKRfJ.S45e} ̧П}pҽ"@;k1tkFz*OQ_i!+B͑S9plu1 v@?zF3Kv*ݚ̕,Ps" 9׵i7Yy-%6zz5ȺNyc*IFVYדݐ'miQ<>%*n;;9.]BK&[,/arofť">LI9Q+eH˓|.șUq6y<e4P&"O_X]%C'E&fTD-XUc;Coq1}CoiTwLV<׻y e܇d ?2;_I{Q ٭d7'G2[DEAYMzyxhQ"cJyģq*)vsLMh bNV>/d‰XB\P"^C &j@v/7Y(Q IQD35晔mxVl9 E9tuyr~;c rFE'᪷76J#lꙺaJ8rg籔e>Ÿz:Q6Q/6UNsb+Ihx%AE;!f\Pg4q/ UWXp 7ٶf+]!8@_'eOwl,B(ȭs_,)6 |=fݭa.eJ2.M*Չ;XCꖆ/'#E6k̸f`N)˲KX&ÖUlMQ 3nEy< ?pSO{u? O߂L_B1 K?S|%֥O)w"&ƒC4C".yu"Cc0cDv-Ӊ hH{"eBV xI3Kn%ZX谙j2˱"[!}|Hݠb[~{!nX|+w @;ߪgU-%ț-wa3wC#.1SzrwѤp6T=YWz]7;ޝ&C #**tn+DA!p$G~K9&5Ζ$}}=f/81wq@˹)MF).4ս~|jq'kUla҈2 ROkK^ݒN1İIph.良{z\h 4' jϯ( ވj}Mȅd[wF)\Xy 7ڷP-G5s Mkh9D1|yg F4:X޹>ohjpD 5&u=mZY,(+V"h~c`!* ;\؏rv .brwbh{  ].ָDp8h@̴܍|vTe(VF@zAͲSwN< :lP!nѸaܣmYEk8jj }qc=]G!lΘp>̾;6?/鄞K+?^AJM R2Q0_m[Zi]&{Ki>F 8gTtIȿB=`4E7t'{1Vk=ȥgݠU{jkOa&pQ $2ieޞМT3u@Pidzi Ѯ>6|$C2{ .Sz!ڴ+7&na.~#MwAw im6ɃEqyX$&4mMIϝ\rCP1Wm.0r+KBajC <*i{e|./*;oY|̙R=ɯ"8iYv͂?:CB\b=t7 "kr% <-(Q^ϳߐEE_C*#pӚ'21u'ٰ:bjB4s) I#c}6c֙dIeFRed8X|0C f0u4|癶sE@fZZ" besWndbt6zG.yR@oF2xۜc9d{7&^D%c4nϬ mtSGj̜S~BϹe%ʉww.:9ʼo']<܊}~Mq"O:Mfl#7ǢkjKnvv}Jz${4J'o#{UyUVS )hQp; m i:cy4HwDDvi},Kḽe + 97,{յ4fz^3Mң3n]`Y;;Q‚\$9}|g,Op(O;c83:oKlН! ׼4YĜkCwAκ(,yJfhݮ.]6Vv:.xFXe-o//3^o].Y!_cN6g&XFuۨf^uӰC2"n2>U7Ϊ#yyB<┄HB}.M\}9ǷR FwuK pyʚc&RKNyt'T"&āQ:ϹF但t?!;ivaGa%CE7, e;fLB^=Vn8@1{Y1yZ@ǪC]2a¥UbyAV:3m[k.&:p_#9IJ~TTNEVߢ;]|^/?0oJ~Z>ӧ.^.LrRM}hxX%#\- c$ Ԅ=?X bT\~}L^$y|nw0IrKN(C|WVpVj6ruHe]hX\l yI-$utg2 ;cʻ:N>fC#FBПkKyFntO놘ԟV ZdQƠ@B59ͤ9P~F噪{LThܼR]⼫ZsQ-ĵ-mV5me>~_#:j#bۆDlVݏ,hIҀ!ETnR ]f=вvM,~UM<$/!,uQieWw.DC B+P|S˻b%+3Yz}[J+K9hѳو)XV:  בfeLD· -ܯleh9~4om4^Ѩp69<p m-UOjbA䤪$va4Ru>ٲԗЄlCn8epѴqDp7BB6j #Q.K &si@ZŞѾ 5P8cGmasg,)hK=ɴeAs2\h^nɠ5*ʎɐIFń&q%oQ(L8oiHg6Y g&Ou7nqm;{&aYsC9%6\ a fSCc f8<'HetQ va4GO }GMlP$:N-|:3Y !Otz$ Tffr5EF4wˍ8B##GD˭M:suOnyNs aT|[5Tҋz&~A-sqr;]Sb~|lTo3y| mu&ք˖\;Ny@ y#%&eo y:G`bG-Ryc*%0)xb % Ҽ3+#Ud u,MqQ́F I>s9)3":wȅ93@ӚIydzѼ0+ޟ5z8Wb2GVHwV%k$bNMvy„%WVĈj\e:H~B巊7NoUAoYw?FA@FʊV[#B%RS3ZsKZ4RrN,cԪ7䴺xߘSȹU̍*&lϻ}.|^p n W:fj/H%unE" g4jW͇8@ڜ ܏,Z?x|r<&:>pq;<kd^u{HC[Yԣh7Xia;n;.jz`cPipF@(U΋(Zw*O~%#*Xr\FV}+L\|W֬YMqlZe=dy:"TI~f)RQr%C79ёW':A*? ;' JD5>脊g@Bܩ'dL|Rs|CkA9k,A ˬ"yh XNፄKZq4wzļ;φY^| ;uTlUb%f>Z5ҳR甮nn;go#>X#=wbY=ohw|nh 2_96*zEe>6_VrHE-"A2Isї "y语 ` ]m W\+"4dp(&5Jv )–~Asjv.ϹWzJ̡h. ˼1ˣsɍ^2"Z75M0品bߟp s~{(7o~W{ Kf`8q,β!Eo3Y>~.7÷dFG/ uP^Cʯá'*Lw斨_pK$Px%{9o1c爘oc9~bFbN0C\T79ڳ/? 4je[iH>fZ^&hc!Lxw?lq$Ǩ_5Pؘܻ niBh,47B]s'uVhѬ hN*~l}ː-^AГgb@4k݌7#"s-꧿= 0w@bEZ;03Q :() k"zu)0D Ws9/}ՎMp@[3u؟9-tY:p0OX9[ @FedD%V\"a\UZ 0/ _eLfe'=k~:LyKyE'ɦ(l<AyL%BfYCt nc@/zCTs /,A9! _0zН㨜}B;XۿRP%jEl {R/Rۂfajk0OY:y>(o>KXѼLiStڐBM@]Y%Fk hw:F.w h-߱鏦kΎc:V|:o5-IZۥ!zW}13.{, !2I-:$Yհ,Vw,)[ G$7;#l?{* YaI_{$LP>`sV``zv7 k"!Oeayz\:*=D9 ZPu|[7a7% j:_+>|+ByBjב~z@L•Bu4t~ kOz%hdYfN3 (+q˼N"q^D^#;n'LqZ2ȉQrJ.1eFc:4;\aV"5[gϥdIdB:uȹ};;ϥ 'P›! @aN?a9Hg]AF*I %4sDq3!S?SxA^57,yV!o(1#k}K1qSgY}*OO, _Rn(_QSgY:lrꭴ{)(/ Q)M>IR\g,ll<妳ۄ൹>K6sNƟt?][^M Cz16WYkCU{UGE@K.P҂/Cձ;RFWn/=Ъ%B̗i:kxg,fCiz| i{&5,B,9o`2cLĀߑ6WٵS\J~L+Xl M=:O2H;Nswrt:81k$΍BN֨$ll-j៤i#dJ2IFO"i5Ult X=EG2φoKJf017 2M1jO2A/ϼa6“?~ܯV-r|b^>3dͼYAxrsd:QX [_ 2b3y>c!i!Jч,E.r^ǫ]ov9B !Nn}&./mr7W'[4;>z;Ҵ_t\v O K~Wa{C&yiҩսa4X4$TB{(ؾ؈dF":9Y} 79t'Ц~ΡK(R[ݝT6$ xFONaqoq}[$ nY#JbU:v 0KhQidT. >#PGp n͋=Kdn6Eh2:\ܙ aUv3gosAų|]2&ޘ8'/7JNu.[ifV8SF6RKسfӋp'xbR&.LdQ!i[RvH"rJK'."o:)ͪ@5uw1ةaӈ4c78=Cޙ ٥nԑ\PʇK PV;.1p8! %sw㪐4G}&qfԌ1 Yލ:B><;9 &=s4+F>Yvy28?Y6P@[(@WU9K U6I0IВ%:OMs؄>\>^:vX /60Ld1?ᙾ"I ە&(ND!~oiMV$7ls$_ALAܧxBCP=CY|Z^l *C TI *_sM:Ϻu=0\o7>XBitQ N 6 O:o"S1䔆lY [6,?NJ[mmW/cnC&eBh2 fPEM(.! &ua'R|w0|LJCꆿ/C5Dҩ:sr at ?/њ͜6S9hd+Ԏ~dJQyۍn0qi[|7N'xKZRg]"sߎ4qf4U'KMltآGB~<˭[~[H,/~qyǰ!Z ݏ AO<|M܄bIXD/?UU[DBA$Y6_@6H(_!f=!*SI"WM9$hC?VsHΏ9sV=9uYA5 Z:Ɇ&ucqdgM qοzl.mV_47zL hߦk:ugKan#邠]N˨Cc*۠3m4Ẅ6+Ҟ+2ۚ2Q2$;38!ڴȺƑ4; @ ONd͍T@ 2hb2Ce+#3}! fW#!-aONc>S CO gۚg6K/4ڷMG.\ٮ.kYS>r7*6AX?W ڛ+r$>nUk,5+ h=DT+$pEJ]1TN}(kJ?]#Zv׻h#fĠ@ pZsHh]ѣ-[I{j-6tdf?y. kwl{{܀E"}"F7^!l/(5ɘD0J^hM?GJˠw* 0~  N\T󗰧 hN\F|LD+||2Ts9)߻^in  q tcgd`ü Y(^Bxou*[a18MfIOi^j^(W\))VowH ?tn#VЎ*EZ$ݗ#wr^dt1듦J${f(˴ } Vȥ8ܳSgKŋ<]I.}^k]x-JGu'EM*yr]_H#gtX- /^qMklR`QM"$ ƌ11ϭQvQߛ L0%R2R Mu&*EXd9 `3UD[wShÍF96A8 D;znq\0ZghO96aȒ9fNYd^Z\r'6yoJ <~|?'WNsQZG3m$7lMK/]yY3jߣ\ۤvGu^dc$+Ϛc}H-lB~iܑo&6 4"i"Ӌ9e|6;qDRNvE4\>w7|!{p/邫sSM{ɵ/Tcc"x)"ҪtNx.V W( ՗~ID}ztw.ZŌ<>n.=/u3 vCGgZGzwOJ"w{6,l w+b?Yq@_@cXr 'T4GvsrL+ҹI΍A) ńg΋Otak-v#/&j/Z 3/{ak?WS_|-}ch$Ϸ0c9:Gu/qZ4'5Xk\r^ՉW~MbhOon`o_9z$ 1A%V!ž?'@``(2?9ҋXzsaˈ~=kI{ ̯u(Fz*hx,c\aAx'k-ꋐɐlӗ|o'&S(_PN D{ 8x0'J1C^wi;HZSȪlUzp~qfzaϟe@G1igV\%<;1dy3[ Ȼ]S9@L_Q_d:n koΛ5i\%^,>109wHQ"'81`|gGɆkxwTuH,]{m@c#"<:7ZSqK8WFnzDBE_ӪlZM%!UvyPߤZӵSݜ/rO*K^x4}88Aqnw^$9+u994~3s)ݫ1eq'5FOɳW^b@_Gy< n޶_h<>AHy!4$glt8ۜ &Jiy3҇nNYKq!Cy-<6q{<"Q5CkœL{~>Tg`P\2k=G( =1T<1+~V|~}t r!WvEU-yF-!NF嗝x^!]ޛ>!@n#/j^n~Kt̢,[_x"Q.J <$&NAVDmlՒ8rP"bxl)-\=E'e%D;EX.]yr:<g6EZ^f٫lԵauO/Ģ6-C[2=.LBUyT-#Ӹ Y+"p+5Nx$T:눉D2ҥ/\WwV(Җ}ZN+!B39Z& k jtvpk VEeLD1yl"󰗅IZ>2dsk,#*w:c^x NXSw{&yTY Nb",΁]`OSv >[s՗F7?Dsqd׼t݂-/ʁU~߹wI]/[;7f*UAUݓFZTc -ƽQ&.P-pcDH^:M2kƢ%\uKݟ^{ oQxYH78@3J)=J8A 5F/EijB/$>h{‡$…鉗lJ_GU߷?a7`q"_QcG%ewh3UlHPrkT`בiBg*gQ1Uޟ'+]M2|Iq q5HD\T%#a&4ZD B7va\8`V꼨"QOGĂ1EG=͏n&ίMBe4=,3/AFйnUTLy]|Qrˊ;Iw4j8gJqըnUd7cn*m:7Z{&|a#}LPQ8i) mnƼǫΘXQBxֹxNV YfvIυ.Lcmc ^6J(\ВE^eh2<`j5nKhDمȜ:*m>ގYq Ki"hMf_p &,Un,qo~:c2&-+ |MqnH萁}4Lk\+yEE\I"CV4(XκJ}F>"QI,LGd0{vU׺IO|g5X&WtGAK]46,]D8*Tg4c@al ]Rf /vMP<.op0e5)+DnFZ*vq4C|ŧx+=?h"Qe}vH4"Q9uT6?2w]yњү{7=#{f4į\ 5JM jbr.y_q$#>ϛЀӈCQҀ̴LhI86m 0Vg`n;7qQ?G6qp%KwpCRT"eŎ`2x&rΈR_XZLR9-[?ZKq,`Z^\^6c ]_A6ve@/BIpnn㧼Y#k2f|I6[@(E$oykdStaykeKtpăAg`v)f"3.sۦ"w(h6Y (6t÷_ י+"JVȻ73~k%'roO_z P8f05JR%]=cf5{'( SZe.Kodhb)GΦ2Ĭ LXˋ& zx~/8 q M3]֝d=5R+ ; UU:M+_DPBXaFH#gt?g+Qa O?~ *#-,-e?jE Ves%g9o0`HVXbNZUEH2X=h<+k7u?Ulk7o3sy7@5=vʝm_qnn;z2]^ 7S24 "ߊp{D~'ky[lhV"8u¨xI%*ZHXdυ0!!wIxi^8m -|[_+. -kI3Imi .O% D%pOs>e '皶/N]ڲ~F~$"s,2yUI"K~Gǭju 9u4eqN}6g$!/Of<]0O94tnmm5].rl*Qkpt 菿p*&皼:N^Nx.w™np0{hṭ^+ ˏwoNAОRTʏS"g|\gNhMCIX w{Gy҄BF=&B\Y"/vMU3]oy*.Wܢ#%&\]pP^?i:ےT`YRyH^!Ec\ua,d]7&;N<+fsia\Z"Ƕz-;\/@ḊЅv?)M ȅ&Sܺ skMxuWwP/ә&,=:7ӱ9A_,hqkFte20'yxq64|XFCqݏӦ5ͱ+\k@\lғUqpk#(B"ʜ@$hpޘ#وRxLGZm(]fM}Nt~K1?1'rXxk(:NAzh:D s X1E&R2h$X8O_k?nnfP >XK"3{_$sH#YxYf?)VvSB24+%:rBFޙ|,A\dcXE4װ'A|]~K2ar%lhrSIIyϑ~2wWQ6)'&K 2-Gd5bu^Xfy";xϯmEJ(yQL%%nfK=qoAtd[e:jpQ ْRtf 2lAPzJC!swz|fQCO _QS4E٦nt[`iU| rWC]/`%q gfNk,{&z~y#u=A( Ǥ9 #UgowNS-P@4K8 r.}+)a`>iԣ 7V\O~zZnZCGfh)xG^K4j0IazPk08k:+("հE>{8Y@|Wed.G2ܜ [{T#54XK{|u/%^"zShmMx|liyfr; =VR| mRrO㫮6SƉ_TA7N:>e/p7I\+̎ bRE ^?GCjtd4ʩ7я<f<0`OJs$3 9w\S쯵Sn&?fTviۜ牟6lYHPkzMJͅ,קi>#^VdHZWq9PM/Vh mGpћЧ8c`~ړ([bUzCp)I?$𱙆yTGfnp ~c{8lTw%O>QunңqVb?yQaO,GTZՑ{mcrJȞnKt|f^#{fm>Y]ͻ#OfMu-πdt?IX{.#".eKM {Y&'ȸN^l Ĝ8Tp#R~)W\zi[!u*V^SUmWgXG4kL{/JCo`{}|Hz6!ux} Tg1Z>E2u~@Viz:$,d xLK1- G/&8f|]׈cU$yr=LգHekؙh'{.UKAWWXz=])ҙKKt37JLtaQ%\JȞ=D. ±l,\ɡln.Ϻ}TVY~ܽcQhw ~hxuwNڦuݺ zfdȐYm rĺ#,L߹cC+%<#iM(Iw" ~ݜXvzgq f}#x`4%-,V7^({qGq6&:e &+2UaVC$}Tu>CPJönG5%xIY^H%M [_m{JEmI޳- DӰggV7-ƝdQJyC 6+1JՔ/G}Cp*s('ex3>4 3뼸7 F. 2-#J=ry& 4H4{w$z[^eLOܷh+7q>k !eG>媎:xi 6<A.uf3pVM>T T/M2hrMt~5 maO MuϤ?";a=~rhN]+Fy<6{G3m -t1B撢1 3nbg\uIV)πƇ)mqsj0FOL]0Z KcZtr$R"q"GX) }0+a~_Xrkw>ۣݨ'P}W\4Hed]LC]/#m-:jlP 8 2r O&TF\ O761SڟO!\>"e*qG<9D |[/T}iM2 N.*`! LH!UU&Vbzc~-o/G;4*Ųl 0[F cN-emS#ki>QL-MX†Uj|ɐQEa4B6WxA1շ{U$Z,y8!ZC{aH#ņsG\t' [36X>~v4BC|BO Of{@ +tnuz:kNΉtJ&0W6mw(BLȸez#'@k K*͉t4 rd`M8:.5 _83[%_y;,C/9Gf^ Ρ 6G z~cGVWas jy?e>R4߯ NÒ5lA"\gyI]qe.J(E֩e̹;E:u[m`4Q0r.E桿,{+2ٕ/Z.W*ū*|mSt$ Z2f~HniNfB|@v}ej̖fd$1Y2|(dW<5n扔$=v_B`-|r4~~C;45J%diϠZEnױ}UYJ|}EdRJ&uc; Ѯ.=˭s Y4Iny^powEvlQ^?Is1RyV]Ye=eO/vnͱ)xPVQI9 "az^8g2ށ'XzX@I;Q\j`TNҊ/t32S ry*KsR/|0R]N01,?!Ȗ4`9o/4yP!90`y.h VxFrmiX'5ldQRdWEEz ݍ$u{m"'m]ӳ@7}0˿y_Ykg,>rah:vS/?L,w+|ދf܈gL;$A*rݖ(MnuJ 5S[4垗__q7Ӏwң]Ym NAdq[tt)n|3g&5>Y] >|4M\H~FR1D[bF2Lp=`:ÑW!Y@LӧIaϑQM.=dr?>(XAyCNO(yj|!\@6}w^ Ȧ~d#xi?;"=U$D'mTYמH(íU.[2mcnr}թ6%ʊ*_kD%)xKYd)dip  Jmо* 6xV׈N6r{t&iUgIq.4\F\79 S?nljU]O)᳣4) CzSz%v7$\#ГR t:ؖ}(b2V LPw!ss9-6 8u ,a?T&sYe?T-D"^Z:MCQ킁kXoް⻡ G@eM:2FeyoG^4/Z ?urҀp*MxGf~< 25Gm!7\r,2֩V'EZi+)\ta'oadB<29h,^]p̗hì/J'@]eU˧<(cXU.@.7 ?O~hJfYxy|e: EX͏%w [^*mF(.Vs]]S>_љаԶWq|9%tfvUKFM)]n9 9P-W{:TI@<+6ez€aVTFi4w aBllv<+  zNOSPdK5*|sӹu/1/W. RBbu~哷 $S-D)|9ր+ʅUʘt ҋ,W23#LGC6ugJv ,˂@/MڡPAEz*A^&dԒ>B]8 :(k-sKPJIjl.29oIǡPG$GءF#y346~ofRvy7 [R#:]`S`NK:{H}w ܫ}iG ?SF@ ~茳n,PN)c@ϨwXҲ 4oV躀X&şo6ygD|8,xwwI]I3zLx#xo-L,vRR-B&ftM˺hݰw/mh]6J"u7re5m $,{ ;>c.JГ xg:~3n]. _aRXQP%W1}2IbғZ̗4ycֱr碅Yf9LrXd[wVEDߋdB2ݟ_|uVz\^ONk_~wUxGEoO`sMJwJՙ',(\{_P[7Sz?{_̽Ӟ0X|v">LGa}b8tL)֖?gmIHAoI]+sS㑱n3O>a<'|"[8Dg}㳉>1-h}ߐtb^Qq)ɴ{Hy#qmZi!C{!g|6x顫e%{Lchx.R 6F70c#XeZ./xe,#o)w!cQ赙]aÖmgf)yD"4@N9a7N'Xv)P3M$)ɓI=J0Svo!jFcdžz Zzgksէ'YnͰ}^y ƨhXOxMrw#Wf JN) 4kIٞ{}Lzˋhlb>ny7ڧXL5mDpuIƣ}پ@0R]זfdɬ굦~o@)ecidfG\N%VRGӐ#F/$F{ <92s A`K /q#McBހN@\dGIW;U~tc8,[By"ñ@6Kj),?MTZ{,۟rq4 2;DǍw˥f Q<5O'>P#j6ryƧg|ZG^T(IV`@N@[ưaJ+ZS6`vy_7qyyc/! vW7sggm~sv!֪>͆|FDv'-h6ZIff~ޚiߘO.9oaeX:J*kr.d6G̸iyiou46HFtoоsF?xJG(7`vDK0}J!7ԫmYO^v4uKԭ7w-ɲ:pI6o^Y&7nDSL%$[LQdY 46qx_x2֟dJ$f"Ll&g"PsםH4k0q!EE(ޭFo< I=AeT(o90J_L\l"x_˒!*Fl:Y[צfiP[yep[}%cQrw&nZy49/u[ֹLk^g yz9.θ )%!kmu=l* OP4ʻZNo}c:Wwr!?bu"{AZZ"7+,jy֫O%4P['ea v:Oc]<z^*ҡ TR J{>*h?ܟ;ej- ;y";0QZUF2_!>®lTMomOkD"V({7No&Uen.:ܾ|SkͯF6*A*F,pH* _{pɋo JmjNikgv9}ZU4P<+N Y9 y'ZTbjET %Uͷ\k=!jWѩy?wvCutp˂n=P@ˇp}5bOb9{:Gp,A|g/v&4Uėy IPZ:5ܬY#X* /; ?/3m=wHWb3}x~sG#2=jYUiTT(Q?vlh?CE6qh~zܟ}Ɠ+K[26ϷMvfVD& xLUvѾ&3mz4iwLХCXvu 'N]0-hj 7Ah Vd ԭ#'5veDmC&~?~]Wg z\}nxvAбus)G/ VGvz0[9p>o#p%+81C>D_/wNlG<^.8a[K ݡww)}[Qq>Nfg-Ӌ&VJ<(;ưk*JNpGDnx\q]t ڇϒSV!jGſtaY\lHَo3tLNHVoQ;Mc66#ȿx0:#kOdL,S#>3&훰!WI2Zg 'Dݍ:v(< 7伾N莙 A8^atGke`e2Ty2Aor$e+I2-T]o]zww"!OqΣ&FB5v߲矺%?,EraCAMAK+Sy<&/Uu'%ߩA$ȹ5i81s*.StHehw%7*%UŪV ͛gY̢e<}B9 >=?b=oSFNv vW_EZSD$:ֻe1 "5 f^xzeAzA8[}6E"Eƪl8]Uwɭ[d!%*!˜*i|4v) V ;dV O+נ7"4D3x.Bf?F4Uz“y*@ud E^Fh0 0>揕1M㉖ DI,(7Q Tͭxr~y7w:梓&UnB^i7KD C897m•^3-3O2.ac,jȎL_X Kd{[f>H{>SEYКQVߗ0|ssAZ`KpBDG˕\ٰlxmbY ł7ByR;?0·nHyyx~>AR0/O$s!@(J{tvg{VQC:$hT]ex眉NMGmTє#p&P淜 Wq&+ /fbݦkuȲſ$-n7:oTUk!Q9 >A˶\*.'bԦ|^]!\Fnf놢ҋJswn);&8G  Nbp٨b'^=UHB vZx؏*U?a&jѠ2#*mxv eXBPo07d[?! 7=O;771q` D`r5q4㪀DsFT͛O7+S)t {':͗؎#+ Pi'AY!Iƕ ##_;٩xֶem=|eƊ; ݆A6u^s(^/ĺgĺzbI:b-Ė;nf QC..vr{+ ҘDdŹwy*#AOv>s>By'xwC~j;X5Sa }рoiÈPqBaX.US+:;'ګdTr=Z d ڵD`I L3:0&_o[I1=2,wH9 |T\ %D] 3thE0*phRbEG/FO}szA7t/ʣx2&N ;طIԇ$VSH#tXKDV>6mBg&BX(`ox2U2T65-Wۈ&̷ *{% ?苐,pQvÅ>< 0"`w2x4?61ǒ=oS'n\-uԺzbkWG+:uJ|ckyHKY\aLb7Dfܥ̟n90L/ֺNV/T|0f8TB旌 w\7VU)g! zaoc]EiFN@ƙǰ|ot-!ܻ٪%x;|6u&$jrⳎ_h%{{0<L͆ vdyD۟սv)ydD}=8{((w٨/[i,M%bⷾ$MtWn@D ^ }q:ϥMu- NذK˿Ŧ go3YWӟʕ$mt-cv/P`6/3/QchHGʮwvW{|>yʬw}\&/ @u*hױfw~yÓ׻5U w-Eq~;+>,慦Bk'e6ep;AZq`e {vwg=?)a~&iON7\7j.Tݖ4I;qg^V7K^y%Uoqxx~aVEz]̗G&nC?v}_eAL]Eo"wu: )L1@c\f|Bo*ݼ;7 |FPuKr^g<4/ }Qѽ>tfAt>Fe!݈CM0潑ȋC84眛H_ܦ7.=eFsUbuIeY:2kYZ;MqXǘa̫ cӮ 9&t:r/Z:ZejcD iKL@D51#kzCJoOm<LItoµ1jsqʧA;∄4CDWu{!3B'kiy8v.zdB55Cm3iBfґH^m3Iw12mt4aM+gFI/+`g97GQ/Rd.v_ٙ+E<7Zzai1o]l?q)8_B][OJ#l`%/'IBLR;`i4*kXr\_%柲 dc!d'TP2=ŽmϒCST~ 6x}ȽtTKv|8d㾰` ȅH,Ű;Њ{eiM3a_5K{#q.c ǻiū%"< S4b$',wHb3(e] ef:Vbw:h^l¾>a1X\S(wM }uo&hr!C{z걠wWyY- T>65^7Nf+Pv@Ὓ"Ha}̎NC};T+J !%\!؀${?> s ASiNBѝ6}ҩ` ĩ,#_|]9njn_9`>PbZ>u}T~@V@X͡ 8I7hjK( دdeƀ+B9Ħ slT+KҴ4fTk7ҋ"h1рv<]KCM>;$}Ɣ'dF՟zxD9K|/ݲY̷{?=;,X_mLbwܛ.}Obp~Xm֔Jx2ÀWg<,/`9RBΏgJ\at`-ԏ˃ N\‡rh>%=k.+C7 ӽP&vkq/ ,g8_ISSCC_గ?d;u~ ;ר{60&hym p&Ǖ<^۟cM*+a{֫~%E!fF#AAm4LJ&Y jrxWXDP)_OtHOĽBu1-Z~&@иn+~J:o+3Bnf$k[d Yԭ6WH_6⑼Ցa*(jhYv@fAE1{VѺ8l^VւI2S~k*)%>!s+cXXu2&'Õ1n±ɗl&plF{)ј,zN J,mF0Ql+!y 3K =tR"WY'd׼nP(NLcQhB0zq ޘ, D_q_YQ' `-zf ^nȇu,++;udIyGVƊd7V40)9"ߡe[\Bc~|g =bifYRtMLhd|b6F)_i7oiStGg^@Le!ߙԍΦ8}΃eBSfB>:+~Wq !:ݞ-:]SSN[y&Qޟܹ)SֵB<9$qܾG6r 4j׃%:T*šu)R>jx40?x&gЃ\Lmz3Cpq }/,}h0vU|?VQ=J)ڕ![vłlV%ܸʾ`G4!^Fԃ˭\rmޭz6JrIL1Zi~v?` Cn,T+aL'cz EDWyO yJ T#P55;3$4zLx[z*h=]*&n*2. BK:* lL Vlw:Va+nٵj>TQ]#veyree}q#H%յ92Dw(\i C^tEeftsȈHr7wzӝ1>'zy,iα<,וog2H޿JN Ogw^ X-\!y.ڬSӤPQ6񶌻lf )ܢaKh IFe,dB|J̺^by!̍Qycr׊c^B܇_(Ɖ !A96;t/ 5|^C-PBac:8\mtPw L#O-,[^XQb]}0Pm`:nhdy.H/92$&]_CK,2:D,IO=g%7M1 Nc[-kz.}1FL,DȂ5zIUHC샫:7ĥ2b7R|۴2}jm@cpQ=[gQB"E8ζ(v&X gbhE3sSRB1ֲz]y5(#NO+##^>Q.>ݬ 4щfn ev1J ukG_%kOlݶGJ6p}#t)7ЙU^ۡmƇ x6,vܩKsģ~vde> ώˆZfϐ=pn<#-#[XFuU}w'Y?[deh4kVX@9㊤]=/i ߞO`oO*O9yUfEΐ!"T+jS]8atQ20fgq%k3!n%"ZF;םdDXwR fxZ%ߝ[iK a?Qp+':s^MC'a,]U `/%{~5zRVc@LJGnA']t\z)> ȉ#~fU?Φ2 u ռ2tf=6[ྡྷy-+\MC#}Y,J0xIa5=m|dfs/wytō_JMM)yi`ܷ}ܼ}l2Jx$!شŻMhQ^1lPZ|X)C#:ÇU4_ϵbX0dIX_ ojj"OAn*I3yLUBG %[ e.PNN': xԬmpǀ}3؋qJ$Iϙ̙!R\Xt6KbS=֡W'q ܒf;i ӣ^gR>OF$M^$t3 jH;E4C*-cO˲iAX 7g/h}Ry#+F֐]bW툢XGԏ}$5ny,Šq+}}\Β^wOy9odo(/l%B{h7eKˠjc#0;+JQQIZFԘ>w.SyL{HJM_e>`WƷSuA d˳t!݈qy!TyO#|+)<)gF"~kY~LN( $ ]XfU8l~{{z2wȯt:e?Wz{3˛oӾق(Q{ 6"^p"a},z\P8[f<ڣ<`rxgE-`7Ͱf`N&^`sK; ۔@qӄgT)OF Bx@oO@$V XᑫάCh'`HD7Jhl979y99)f6tP<05#x N1n EJ2'>YIQ| YP,WY5A݃m~bʓ$V2EffZ|ࡾkbp l `~FϘErX:tE$M\eCcj)sy; o+?RNe>B7,C) + ]$:X oZ`^ *!Բyzp+Ap!`>ȒHPK&2;]ᗇ&+j'[ yD²k[1uDc{4L=x\}ޓzDWh<oΛ:t~˼Z>|=e3LiP!O)l^TKB9A'EdIJ<PhAj ƌb.+kgu#TI?38ep2[&$Ϡ'd?2[ƒ ?aNOF[G_/ ]D %m%=˄1Avi}M2;~exw>t77nOGw#t7h??{Jcl+)xy eO"sSO[8*|*=lɔUb+v>Vw>a:|YJ@; 6B|l8 q6~enk<|R:p) e*97qϴgzF6$PT+UXR.M Lxaλ V cݜFݧ䜂oCa:GPenR4g72} V:Sjun,f~"\r״ 80ulTEx@gne삽ʹv~ݡޡp ExCZcIrѧI2E zSFyf}ݑވ&W bDu`0L&ϯǧM[n6:!kbώZ 3m~1WV; n1[TM )`HH`TO2.!K$q^Ma}8:HĠLRK}oJ)C˨fiTb>&lu )FE˜p vOj/Q#?lb>cT Y4c'pC侌Gpo^x*.Sc UҴ$cu14M,n3KFzA5om<ۣ&L[sir]ΰxFehIoh7t 9NjVP?*ǐƐrpK\UVܝWiB+qW~)@%=7r/9 SzӮU&%o uV y83RuS|CzYC+ZբI֒z6m$ڹMܙVwYB.A. 6rB!tsZjIڱ17dv**q>fm:s6붓|Q G,4Z{#SaC\Jrs@1/Nm }[+l?n([/J C{c*osoҡqyA3bXʵ{a&ו:?-+1239a^!ҙ,w&7]]P1u(]cVd1 OLGCX+3@j-Ԯ@ꘓ`tB<6GzU n0r{CoHG٦NXKFD$W$mp4CojWl`ߔ*dy" H)6\)LIo׍J<9;b.=Mw y=nrx&lbN61br|?YL 2@x9 C-dV#ߛhN M*lZ 毽5I)sEmo-:lKCM%pBPb%̼si/rr\@{b!`U֑(*GGkJH9KF؄Ol+N&9 哼.Dq3{ &=w#&Z4wݱﯚjo8i؃Vg3/"K;&wz$"yF"񳌂˝6"h~Rކ -rLgD[Y> Ø:m7^'hи'4cTЫI~>D!W=*tS(\04NOǗ{A(w̫O5&%J^h|}s0zqR86@$H'khֽ"8qS ;փLƺNy.Sؼm4󢳗gP^"h0gعSNO),4wZ2^:3F0̂dn.J_hGp`<Ȁ5.M8*`y&7;7nWo^y$!&?orRWp5ZEdEGW &%Ax&e)/'4;)X4dX$',َyR8xȃYdYX6kH3/Y-^8AH(^cNNT> "݄VFffR팛]rqq i?.mr׺K&/~'D12nZcLH%3|FFh7NTBv[5qDj{%^Vfa"e\'f:=079P!S3XĘ!Ap,8񀂋77HϷ7Z!lDBKy$H/`_]7r9<'ӕ5/o/Aɓ84. \ ̃q8: <ۋ1ΚI#?'>bjӊJw\e?#SY[2ˍ9}^:y'X ˃ÅX.+J˳kD&FE%K2$@4ԓ,'vlaD*+E6X@ 6<*8ݨ4}iSFu<]e;(0pI1Ꙅm*?G4acOv\^I$ONГ2$ $> "3 ba0tڬv`M5Uf;aJF}Y'W)tG{`,Hf5m8o CQ]iN=1UjoO!N7bdjO]d~s<;I綾|_r? iI85ܹ~O2-)rܴ5iDp?qdNTaaU' GUrhA|4?4^lȷl) QV g ?" 3 Ax;ꞇavs^Vcen/p~V UzgvQ(SdLdF,ޟ/ނ]z Sv Zɛzi L:L"[Uzr<}n>n~#eSPp+s!`"Xb{>M0yE6IFGezf\̸ \mX_iz qsh_~uu>XЎr<;=!QVAI&J@'^ɐih#~r|N7=FH<~0)%It-;CQ[8«y kcٸ$trYt=o1ZCR^܏m7?M}x^Sh>s4ymnYr]f>VUeGnL"TbK0Jjxc+FۍcA=*,3Krܘɩ~w++쫨V]lL)lo`i9Vgt-(b2{3uGӼ_oId͐'ny5cTW 2'/mB{y}vW3gU7\8؊$=94iF /BsڎP+`ŗ=-{4]leBӊag;F\ZsF}w-̺,e:ojZf'wS\b۴[-ܛ[[!~A|)||`۲aG@厛ʰ9&Xw 9g{lc>:/ʈiB7 T[==O/Oul.oN3 r RkpLMxq DW7;3(&+vanDS-dB ?t_{$&\ވo`\5~ kO&#O.Xc߲*V?|דD١pŲJmYwȾZ幹'hlŞBm \N_; = KdgA|8Z Jd'Im^'O $-L>Q6.OO:ءKogo~l8LXN+΀UQ^d3]?݉MdVDI:~k Uȿ t H/K.O:f~xُ~ܰEPNvmPLULboO ԛW@|ԅm(Xf뀡 } ÿuh{3G ̵q:7 ߧ5x(t NM3),8~xOen9ʧ;? iB;S=y8&^A;' [ѻ} ~3,P">6o@rS,+qr'e9\hq=2YfJ U[L yw27 q57OR6A=m$!tۈs*φǬ6uG Yf kh0a֑p,}$MbXD(#LiXqXzÈ\fOL2󍀬OމdŒ2> {h>,$T# tr9q3r/_ypgn<kjͽ6m;}QE/BdO`:Ym8X ׄ6w@\ S{푂'e{Ɛ[@ǚ$ Y___rzE[IXw!hm Ud(r=\n;R %0֊A֕33jrs*ɾ2:6_|d3qU,VIL^r('xgVh;H,5yo>*4z(}u4IwR,xXe"-L~](jT\ǃ4V_TpUrg7 $dIGeiu7gme_cmkA~ 41C(aJX/7a)~Ud.6y<$`"\"}9)h WF\G [pP?^CZ\NDWgD>a8ķGxlS(vr]ii*bs±NfslR٫#Ɗ !YMflhA4z5H.Ҏb} 1 K }!__lzF;F*㴱zSʞZMԵʑ_Q# 1Y>?PtE~u7y[iiĔt sˈS 43O$ZsVu= U{f(t/mksAf$:G6CI%x%مW7Wr5ܶdv_2҈iwU#|;ijiO+d`>l6KD>t v_+[E[#umѶY u,#Cnoa"3ґDk),@'>MO#أ$OKbK:'2p+k^ q}upi,3z-p$[ ;qh}*8ņGTq}HJGh;OSF6pʜ NW^B.hމe;) l`NZj2ԎJ=3Xxrs~NjmI=*V]#fޯoǻ+٪i>/:S'G>g7nGv-oGcHJa)mSkvISֿwk KKvБ X K𧰁N본J8Nhmƃ9``Lfh^x,zߦw]V5Tx4QXL1kyr=\HiB1p@&aȰ8m¯a)ؽCrŇ卂;,Jч<%2u2sٿxx""?dS)Bra+ vxu1v(pXVj¬iOK¼ʷ<ϞZedtgO >LpԱZ lӇ%L1l鼳?)%l3Y R'Q,sxwa||[މ[/g@Lzm+jyu0R<#˥c廯g)O`hloR2}wp:Uru>а12䣟'geOCevnSW:9ghXD2YӾ!s.Q6<w9ф 1\?<еlHO#+4K ۠pYM_]cr4δ> (ILp );qUs>V"tJl&Y0gcQ1Qzabg\=4Ǔ8^>*ȲsrO'Us)spM2\9b_.K h~,3Rdq9aU/;Oq xQ&UćA3-ȿYS|cti7䝞3R/ Nn^R<3csZ%V4߆9Jp 폸x&0ۈu}B}Բ?e93i(aⵜN4֊Zq3,VʽIYps^fn$) b&C(u/z Ys`w8˫Ϡ1Ko7dH^G/KF#n[.^ 87>ՙoLQ{%J]lߙ&]AI?qlC_|'[FX+\}Kڢ|!$~5_&IŷbnH3lE2ul7mie {nP`-/o;3N;z]XoXO ?RD9},Zt"Flju4H<}ձ }.b7ۅ2|Ͷi=ǟ=:]46Ğx.!^%m&nK(7Ǭ%+#Oufl d2M4duYh_W'~wJ" X67qk'8kZ:׏z4MgLKYfXCKj8%rvH3^b.=⚒t->ɭ))6s^)GSOzWX]rWR7_rncn`F`rN2X.xUG2ac+헽KJCL9O.y._Lsi)yh/%_fȟ*B!6cC=3[C>WZ=~P,շ/t"٧EHd_ AJ|Vw`Iu\ \GN?&\G/|B!$NquaQ5;UNrS2睰lT0`FeE&e\p7"iKC")%BSC3F|pf7~ZU>>U׀sF-9{fg87;7Ly"_t䋻<-39EO +QrRES `w`QKHvjf~4h M3P<hlo<g'ARD)ý7E۾,(s]8~}t|՞;Ǚ_s ^8eOzP:tg{rBe4YBRqSͶSUBux}"T2 +mpOG ̑^:)@7g7xuuѨϥ+Tӏ+\o%+| CʷF57/x<[JoE\P4,øKQG=<%\WơM&JX37_kIdPQs3s3 jl=ޟ%#9W$8~nDb Iz|DuF,wS+K\G2t#e A  eP'S.=o޲xy tXDTޓ>אaB_Ҧ.<,3ߜhC/9{=,kH/OxcPCf82p"7ȹPǍLcƸq 8*mx|N3!d1DksbSzh{J^b6rX㳍B uH.o=TzvnkQ,k>F4r[y'^ 9 8Z|L9*Ya*z`o.z*;|]U&o5s)i,_s#TQ%na0Jxbia-2[?`+5(ߺ(VN۸ԵÎ: ɼxm1|ݑ?pnQb-b%%xAZkA#ef&. A!UB&ˣ+E>̐'өĈ[ݔ!'[t.+pFt:mpzeKi>e;-1>RX S귖Lh1 zW )fae6'`T"`z !ϤNƇě ɐuo~ӭ_BydV^ Qw ?$kr(ΐ^{?To|E¶amaN|ZcxeXgaDc33cW"a!gF>Ef};k=-/E >a:m i]k7m"i}XoX6aX8r#}"G 9F T"}Ob䍾ֱ߆oȝ,#eHýCccc}o= Ns?N~Bt@1|Zp{9rZYw~}ҫ}]L¼BOycħkMkh l-pT2yhCvX5[)>rȄ{ݩ{\e9Ş{9=ZZC#i=.{59˼V+(?ۇLeH%wjOGS*)wBRK57\N @=7!KЇ^oT[;Mȗnӭ(8+!-- Gy$}Mz)P.&;=ڹw:ݩJwֳȽBd3Uܸ]A-r,_ØXR*ٟ^e21\pJ(W *5%5T-}oo~9$9~/HV̓to|gToZ ArDg~mρ/XKϸ|n U¦z&;'r{1f:ӣ|p|Ρ\"d~89~riy-k-$-bZV ?"<8zp|ixсb@S/s%܎3wÂr/k.j!I>h|F4RH,uE RZBvcvӲi߸vHA:aYy6ݗUE~P> 8&aZTAy2qE$͞vU\I_L׌/0}>w>۸$Ş=j7ӝiHN&G.856HTS'A;q/G充)P8a[w`$3Ա)$B.S|,k9=IM)QqzKLm۫>bv9. Jd{⏆w J^%[WY3ac8bVf0\I"K(huIЉmO.7vN83Rg.PDp,\,(:sM,߅>| !J2t_;<{f˙61=t ttw2DzdDKHݠdi6&ey"P@'jRy$ ǫU T.Hn8l6/Q8ҴerQVs459u#fb{&R&6VNmJ'Kr[N`>ɭ+,ҟݼ2=7-{{X4zO^^]_KOg(>c,&fAɂ@8Z@sM3I TOuFwd,1V78{<-9ChQ3e4 2F7$eL<vvFt+Юݩr/ t?X@F &2|jSw h!4+*cqhFK舕nxťWl ڵ aU֢;NP*B%DpGPA$g8G0_q$W0-̹v,7's YT.kWOq _Ҙ{͕^Qd x`8z+߿(dB{YgKȇs9} :mR.2RMGٙpPi1=Its彆8mhkVl]pj!hJ(+tӎH6s iH#q Sl%]]ַO?DW`@n7åb"c#9mFC+~Ӆ@YB6ܬyOZrFMΧ`ȭZ ܗL^= H(AOʘNN6<v+T,q6Un Sz/W繒Ye72 xiLG$48%Pi(74˴*i,66"cuErudL|qaA|>zW^O\4.?8O9 Xv{hsh~iq~C5s"ȝJQ5uT 6rD$RNߢne^Uu2[>X8t Vm[uIvh*3_w^"ஒku@o%<6h.xk@@rWٛK7Z:l ܽu3m%4/7&փUo .f/m:O@+w?S{" Wf#kI_BW2 {sA4$AVʋb(LO1Zq4FhSkLOb;X?M ( Mt0@Yi}i4ev2+H?:˙=%ǵ%~. e2d 'V߷+ok45cvƔ晅z}Cae7p'Ώ#Ulǽ;BxUNɯq ,*ǡYoiV-LY0se,[1LZ А|[vdM2*q<֢ZaT-˭ar720I-ӵ]uGȕZ%醱%1rO.2zdҔ[k\LdLJr0WeU:Rm;4nNw^xq{&/T/Wq{~&bb0);Yp['"WreXл=L^qcPT^ !ճTOh 48}cQXRjYLܣd:dCg'p^~S4_<}Q~Ʒ荙Nֶ4$R):c(v]W .}3"X2noq0yܥ}EZڞ[vJڇ,C1!I$'c*[o/o*2BAiuT& xIvm:XphY#çIxϵ{ܵQ`NYY [sGQ%9)ĬӶXhg=N _i6#VP R|(] v`֮neEn5F%ϯy9<7/vwۊIP$eNxs_uq,N sAow:_+jnEz-Q F%@Ov(dzInxϳ=5Z(oon1)EOY3u{5͞]Aov Č*b\>O;+_G:}KJǃ'RVSJԩ;4lUJQyi# LfZLxI{Y2X\(\YۉzDq7儒o(]v1ܛ,bse#.AC|[UlR662.A>G*5]V?ë%iȕAQs^"w6e1&Lrf|ʢLO{'ӛR;.KNr\UZᲇ02ǝ[(5gLJ(0z|.iCQA ҫ Nyo9U9U沘bDJanMŴαU_+l\F!g;n oYMVT@r}/!:S,Pxfq$ة)%5o^|| /xɉTalE4G'o'QKb 4rVeD*5s`01#$i0]s39.ݚ`\ūV4xqN<.P{pg#,K8"Yl/Yo|Y\kDTu e斿gjӕu[LNuelʤλh-cwm *S{ooizL r!Y_)̣xnCaF:/uN@b VS>L|2+vx0H,ۥS]]T72&=p/l鉣 ݦo}ym)-K%3X^Fny+2AfF'TEмn+vvsԧ\@ ,`n+whV-ʟ_q곍AO+pkB>4h > E9ԨQ,Ruέ=4y$[ Σ&.Ѥ7z-|?tָELK #Q* 1XS m״Lr2L.Xs:nXu?1m>s^rK3+Nkb bnV>>Uj?} ;NޣmD竅vszu2_^*_{*^-rgap0JQuF½<\;۵cTfx!fS<5VO$ReJ1#mx/]bvvd]V\+y2(IXY ]M0)<ٿqgB#0Bf_s@kUT_r`ˡsdh$mK2O*t332PTѢ [-e< ڠ>_{vڜZix+LsVvcapp֋gr_wn`0كYMG/IL9s2,,y GKG+c<sɻpvJۜ#ÈR#etp E96;6ȠZf!ͳx7s^&ޥ/ޘJ{|CF'd!cPY1'/g`#NS Ӈ -__6L9H'ZR9PUWxMSr_Ǔ}uQ\k1#B'D~nKT/8!~0!"NaoГ]NsI CDSG!'^`f&6신\fnh?/#zܩH[[q7 Ry͋})]kx]TpUmp0J>O]f`1<ѳbJk1ˬ?`h>|Ehʫ+ \͟JۨMHD2IVVS 0W&'K VEm{v{Trh?wiW|4od^rb sw STy-u>Ej[7ig|G?/Aw[)q,98.;;kJ=<-M.;?4ݜ',(wԪ"]Q]~GAZ殪EQw z`;2Q:>u팼VkEBݲ&vE9D O٬chX^ KkD]mn ؂|fU34M~F~+_׍Њ\lSO.4 UajԩDta gmM&PcwDE+Kf1V% û}MY<2Xa 0CÓÏ/5Y'i [V|\MK7&`A72.YˀPQju5>Z2'o /s3$/cͫFc#x@%`,:3W&YoꍟHt% HGqn2?]1\|ṯܝ渓C!sNMotWhLj<hޢ:,uz{d8޴,>[`AZ*OwC1\+伶1!{Mis!f c{U(ĮnKf[@%;æCД282 @or63 oh\]`"]ҴMwFCvW2eKyUkPI,nPo ]e :⾺`ԫ&H7@4|0B+W?v0|DvsRa ]F05DAG< &$j*jy# D:К S~"2FB'xmmh)0ne)n(D=#nD} tB@e6F":7Po*B\% @ (*nD>.vmv߾CV_2"(1о_H2B¡e`t F[ ˡ \iۋ/; NOc/xatawP^!?@<@w,4Z]?*Ptqg.QEc)Ǫj6*S,ϽX`oXhߙaQ ~1?>\iJeQ m9 W1N锲;Vh// G!.h]y.=_DecȤ&_o(YPRx1 w/Pɇ$O2s?GBPT9iR˹Dʹz/F"dhӦ 2vQ!~חLhY71d~#mAҟ7bt%/sQ-Sv(D\:d2W%vqW.xnԏt}Gm BeRlX@F{ea6M܋LyљfN!̫=uA)y!lT('}\л83lzy΄/ !yC~|CzBoC˼>0M~I? LUd_*!pBJyWM6+pj,YEޔWuOXXOTCM$v $Is`' "|wBg5uȯT*A=:ag#cɾ0^}~'g OƦnZ/Z]߾{5؍W@OfI"c{gujA+E Ȁ*[ llib:o%8@Sٜq Y:8v@RŻeZG( 8]g{e VM}pa JÛ~ ³>e$vTIƻ?O̅֓߭4Byf p<% 0.CC/.=ٸQcѫ;#>ޏ%{zzz8D5@~g\< Vw%nEW^%j3m͕Y˜|!ݮ`. q.yso 6 9O |d𙾱>cή)j ;-VF3>+~ьassY~Jyw_n+plf8Ϫ][ol/ӻ1~Ց"v<$Z5X,yq-{l(?{m?ɧAiL8G7^j!_rG{=8x}sx">>6lk48])zZ VϤ_3E)&ݶ^L C+}396BSC2T(tY,N_߯7 `58'/):؀ww\V.Ux:z6{W)ctJ0oѾRpxW΢.썲2FFSj`}z~o/Zx? o(Æl1f;nyTy~q(!ww(Ɓl0GUBANm8ACMi0D哗NZ;)k4*ʛ^ʰ|\X\L3:YvgS 3d]WY:RNZaM2H.?9ʯFX{Ii>$CC{(f3[='v"Ŷ5/5U"q1n P{k~eqVv@-]  )y\6|q)g/Dkm{ch)̽ۺ}/X7B!p#R$xnDpS7Sŧfn rr}nWѝTrn^:˰iW5]$}@$J.VF 2a8YE]6#K^.px}XpD+'^SZ> äp:Y#D>g?4k$ En$Ile \e|rq<<hG71c9ÄH,urKZ'ƛ}ɊJoPvdNjyܘAӐ Hze8Q_*p^˓dc ֫U挬.$)POxS\44|QLo;5%c&ZHF^e;\h~;G7(KK*!IJ`)w\G-3\3 R|,l,)j4+va(yޠ7Y%> 1y:nZ*Z,7U#7M[ƙxMhi%osCG//GQ[Gyc.cS<-|0Rz y bR0v(C{UrS|iwcP*cC^XDBJT t NugX5hsh)Up%EuUFqa .[7oг9mߵQK=;o_imQ~K뗍 )V 3l{!V2CS~cgQ`zBx*6Y]W/^:]&Jd E?CzUk Z WYF:o52tӋ\4Z2o2rT[;^ Iz(ōhF D tSeQ猳[%QX Ddȋvt&EyT4`dMnoD?A Ro22+/4"_,IXdk]BlOMD[M4WUځ}ÝK{`_kiN]\*) qSݯM&`rml~yڄ2+ Pм!c8r3+dz=R(Iǹ˩8+4`pDpuB/t0^ D5hCIzX0U/MՆ\}VwZd]!KU ppCIe62{(E0M>쯑̝Gr8!* ¢SVȮHRf l~l"~+DBD WUK*T a/?/;u8;|#YH=O@ܬGW8O`QI#ZU 4k?[} 8pBvĚΤ淉5iumL$O:OxPL=PLnD1Z]ӐR\hD9t* /8as+#!~GcftQ RcLm-)d?y Q-%dygg5I/fgP-''q:eS|ξb"2.p^#BZai>?9e $pϤgt;_lD@KBݳ3p<̣bM.hjCpQ=WYv F\)gɟl&ᘉUIޠ/3^cB)6\u0;oة/e85@,R&5LZWno}F;ךԃdg`c`8^@'~AϽFIdW FN'3ٛ$(Ò[ت6Ȣi#w PQB-]To̠QWT1Yx6Ho-l-4șQړYh#nrs2 ѡe)?2b- "̼~Q1s QxRRx#z~Ya5+v_vdѐPy ,/tR= Tc!~;8VTK 2R,F,yOƈr5;/_`YMj̴ 6LTKCPZ5?Ra"͕yG7-wXpI{)3i$溲`˗<߹t. \\(oHv)Iʄnө7͈tJ+B (zgNeL67`m7/E8p,46R y *eyHh}wSȖ7{Q0bU+S6)J":vLעß [#肬2 gj In;J8@#C῔O9'8Z*Х7zl+ MdJb썎F:J> Pۀ9n7i\V4+V?@qևy5Õ*@v'! nL/u^%M*y pe2 BU=lv ׿J^-\$l mܴ7~$Z,~s>EnV> 9O=aDiȶ./YM" {_ot *B1/=VS{Y y܌6"eAnº\9s*IdR.،q蹔a5d^iMf ?]^1j0 m0Q\`5DÅjK T ~O%~,+ h%>Et)f5 xAczU-7R%'eƿSOt>_Vi̞YpQWv洑)7KCc/dzVRX+ä\kP܀tpM͆f437. 54wD _9>}RS[O4@9V^7շ4oay޲`6&JS r3+SͼI;U9&#j|tcuMB}kmxSikm#,x#hyO+5,%[7.1Eq~w6ձs=jP)f }F bƓMYyas w nd3{,HmsX6޲^{:ynd\70N8$7?3Ж5/ύKF X Q|t~c?tuc&8k<-GT0^[8Nw,tl˷ܵJsʵ{m߼jVy' !ʌZ%OQ[q{}2>?y'38~v44 IoL4N\.Z%Y2%KM>٩I]z vŜj U L&DY w D$Flqz;]ձ~%yfRMّ9Hf2}gܙk84SB|칗s;Wڣ1IUP<^6t$A{I-rgFtW)!4rl9X~S}DnGׇ, 21_-wtXy t{gE-RJ,/?XZu* ~'=ϩѢུ[X)g|ruQ+Їzs\'2~}q 0nX~SSү@ 6oθw ҄,L1aKi#ܦYL_$/́=Sј4!i5&+Vo_DW^bGj&~%mbG6Ӳ2of-I{>lt"#h)zC Зly `<`c̣OUIњ\YD>l%аBR2Dxj b~=Zfszd4qd?ze):=IrKt q_S̋!y7%>̣ h0z2[R+v֓B6&hG>O)hl и׾!H!HzTF| P5@c{c2~{v2n@` rL׸1%C}jEgu&_Ȁ2ISubgS0w m^JEW 7c  lLU,`N)^0a]I\x1a,AfIP:[@nDޥ$%oBQ|۰~%ٕ5ە}XBήoKh( (͉^_^ѿbxTYR;u\r ݯİЅ[׺?[l?rs.i2Cޘ?Q|%ȓYM)%Rl  BR_\Hoq0{:]GO%_cfSllbg9 }v֎ l#z=~nvS?nܮȧ-"s'U9qybC-iEb 㦪4OtLg__pPD0R_\Rxm&Y$QQt}=o^CEvPqQ?gܽ_>>E1#gg"'\h֨qWEG:A"EVG"ceϱ;:iª,FTd#ꓙЭ ]˱8jXT>לlh ~.L1V[[d_~ ILyCz:9vB,R؞Ka\"{p劏~GnGfsީ;[ÎYꎻL0Bi1@H" s}i,W|t4?h|\nZf΁(ʧUqjf ;aTcRl @Rw->~3H셇%ĶLt(qs4cp*PɫH߇Q? ǠBda+N6 M)c,dQ *5S$J!Gs쥴Ӈ L%֡<]^5 NDZ+ÓR[y 7?b*}"hV"/%vLBN ͆S/w..D 6pDRvZ+9=2o,"*r]/VVPd DH(I3ONIXz/)dJ+* 3MF?IOV`]M"ǡo\!z>2E~$^]Ek< &)=('@)>5-/tH3BGoM,< EMI28*c/HOOˍX'Ǽ)GQ>7Ҳຮ(VWO` YGkclphZf[e<ouV\l motKn- ؍1@Q_{.DHV V,ZW6yoN_gkڻZVRJE{iS`l{'P^sy3ѡ([?b`w̛U%q`~S4~ jO vQmD߹2n܇^Jw|Au,&v&/7Ǣމ%"%iUĬD3ޑΔUsm8s2( kI=ޟjUC˞uϫ 4C(NTѴ\LV;azqhy 9}8q{LXhu|f?ڌN'Cg>h QcPSYėE bifr4с23yo[A\CtC*N+ezc Z*pUBX게B!oȭP|1&$"JNhK~2Yͳ8fR ؽ sOMF6gkr92iy1 1߻;=B~itjYwn3Oҩ чaw+kgrCJ+LlZ6PRJqU: V:rS[eP?w䙮L.MlB 8ta l̒5QT(!txѝq_` eC8ީ~\uZnIw%;Y(ih?$lB;a"k<>aq=\ W/^okq%(v=l7d&? AWlwmF٬eaL(>&=w?nwí#o"N{o^ҀB %<$1XeTpt|'r;AwuCޝpo FYŎanP0=\=&Y)[7>0ź=D#-aͲ,LE0x}KKx= ۜL5 [%xNOau>h4 ΙWv>W* nSЃˈ^=lԘ[ u(AiʺTKL_;7@8]!d\E`\%bpa~#ZB#weJK|]MhB =? tXp|dKEg }hDŽxc*3~COvLĈ&%|<pp)H3yN8.h1-$zp){РPa@gQ}gXiWGY>>[:EmͺMT$;`|-(r}f闆fiC,}_47t}L(Fv hu[Fץb6\ϵ_?QfՎD$>w}>oilP1+6Ѵ^75I`{VHӅ/.pi+c \'#W|u_W+*uD5}HjƋ'd1' SUJl@m&/)hY$>ws+yyҎ@7} h% {Z u|Z3 un7|Bub<=G>Ee#~=~7{<`k_ot Uߓ3m=k;g0v|\LBZ`cO^-(zMU7 ӧy@ "3>boGY̎[rSYk"o/if/rpNӧ"gBb?M,;1U;B˲x zs_Yx-7wsu? ofRw+LR>$p!op%`ׯc"Amcfd\Qiɫm|v:e#]2@d=x_fڧRu~~3M,Me7TGʌg:b:>ze|S+NC&ZK6hS'rg Ld+;e6kvzcH~ eAח  9졬"n?K_h2ݓ(3\s{*jAlrLqM>RXO޲L2q$}7^(@մ|UfwZcB~Pv3aջ9*M|MES+ i]SU2\qWˊg>VV kxA쐛v1]1CM||tHNq{->NDشSsovVaksXTf\t7q L5Hob7=)'o7[jUv !@73_yA3~eF7ٌ)y0X^Vڬ{@sqfs{.)r~ϔ{-]{qXK2Ժy_(/9ịB|荳Ks[w1QNvahw|+ӫ0 &JԠI @psʼ #)=oe^E U.SdXY`s#Csl:KsI!SOǴ .Sؖ{ĂNS,7x~c2ױ:8W^IX! !oO99Y{m2&Y.8  gxGOv:U^ ˨SHz_w[o&s ?X '?HdYZ&9* W[^,.Gcd- *'M9ifJ}sx(AY Kє,r\T۔P==?qVB,Wv$?I6^̓g²+,=4ܪx}Nb9W#_Ċ4*-\DH'рEYD-Tzd*OJ¡ }yJl$䟬ye3ߊ;C& YcdiX |R.|>&_i7[SHYЈ{U|NahAAvѯwn̈ .Wbe9-ba3wy4Rׁ;:ꃪld΅Jޥ>ٚR><vnMdN_>K7̍QЎRIslQ*C+U^%dfB{Ѵ*/4(EwOU.{ ?ɓnSݚ)a?$ t ̀%5&F~{7YE΢:YPV7_L;T+yio섞<2BZ0YݴzknwvA_].XR`wFܗW'6wy=цmTeHq)Cp{|ۚd@'ҼLEMn:w(w*W*[׊E˒)7 s'B?z2L'#qV3jgf=|^P Ι>`<q]j&Դ>f` h:u $2Vʚd:<C2(gUFwI6rfbrQ\CYײLhN4Pr~QTBwd7+KФ&s KS;߇ ~.ݺ"oxM/e\ҹA:4.t/{BwB8r0NsA;08T`%[EK݁894&N< ۘp 'ZH aU@_pȡox(l괿3DDϼ7>G;1peO`*<1t43A#Cia`Z&JG3V9c"T g60*qQAd/k_kOL~͉̌z  yu';-RɋuJ4ZЈOFޖ\:n6J390 -Bqr@i&oNs?vՂ S\&{ %䠬|~@3 w6Sn0wzїV,nA4uc7ü?Ga.zb?9v4h)#SQUyݡFN]Hxc\Vi6txّ97x=]J7v0.SjzMܹq?꣈ Z 7OfhV~> o\ϯ n,招 17OKx\֌VoVPVpvZG#ޑ- rce*d ]9f@\n*Z?PUZu{߼e%8k~v'#`4eko!qYET {gY=|qg<ʀsfe#N)LedcqU4]Bo7/Qy;Y1 vm {x 7g-t6D{-Ld=!%zP<,]or\sI3$L*lLs+p ̉;! C/wᅦ D]~Xn ma3vgqo~?C2D0%#.3c܂1r8l}I4A;q;tp;C;n;#Ocn+{ _52g\,GL#]pV ҕP ^6&G7zOAgj̸< L ic1Y"'oC(iz%҇& 2^A{ۍze`(Ṓp@ƖLf2r7YWJcDxQgt !+U}3;>`W"U_ٖ׾9)plVߴ[: 3n 4vڜ0\heOLj VߠgM?980v^eXpO?q㌃.!Is>b jPνy^%]s@j17D>q{Lpp4|&^L¨HB^9SH䐩SxnAuUF1؁cM& zBʼnZϠ_~aM2zѬ9ս~ۥ\3&9Y?1 &;Cg}<ךD3 =e:_hNrnbI$!py ]b3w8"Šs%y4!FRKsM+ !})zPta2 GwƯ׷;B79|nNdyoX#U\s^9Rjz%ݴ9bͯ+N5"yU1r١wUB`XH+[0^D㲚;6͜_e~>B)<(S,D{mx_Er_EBUfֹdJHs?(Ͽ݊VZSe8tmmĎH2_"Bm2\e헲Oϑdhiب؞h? LH2e^59.CR3SqɑA[`>>E~ 3 Z @UkH1)3$bE -+Mq?Ƌ:[##w9.˳ ^o3H2ElY c^#:,\<+ח\ 3̸3qKc+F, @TP>9.&=[ SΦ__MEM,p/gf93n.KRfC)&9t[|/p%y#.|&L^dDH>c ׹ ܟY)dO9Tל] f'9 .FAޝ5>i'~p d;yb ʗ[A3v@%[Hd^eVkP#4* 7?c 8QxTyi'C, #Ʉ ៓LBupUIb2~gDw,W6!cGҨ?J.v1(dO%a gbolu@ɪIOu?՟2BU4X&=\j`pՍjݎ'TPWL}yfW+BShĬm}Z bJ> 2!cPFNvĄ!)_#h@w^͛ß RI9ySg"GZSoW)f]n7pBtn#YsZT/R#4T*J9뺒Ox7&Sj1.Cb]⊏੗ɬĈti˴ 56fGJOvfw^}_fl0z-',Z9Юifo\}$WygvDzW"'r,at4z0z bP?|Lv +`,'Hwp!)+;| %Z>z62%lZ9̏O'측y(EYpi)~C>7XB7QښYZ^&2=Lr7$)d #˰Mш'9$T#.uj\6r?\%U=0?R՚uVt ShZR` 3yLp9?8u.  lnHf?߹h?7Y|O.>Pf뚬uB*І}튛kdMt ?uۘ>rFXf^E}$.v0rɆT` :I Fngm=Q/ã=n6Q}ٜh(QW%O۲iVE_Ч*Z=ȐEJE~D7z̜ˇehK@Z> v2 2UQ0KypD^ ",Nn+֗raa=0D # &lKYMT=vs~Uf}cQϵыjbGfJ3#PITFtdj\.fkw+b~;tۙ;8ی|v$$ZԕVe tx~&R32~DGq,KY[۪|mHmZB7q$JI|2BcLmwM+UcI?(#.2_t'AB)eɐlXn8h\#l2?ϡMt3 ݴ5=Nf LÎ"2͋f;RNLlb `݋:s;g7'|a"} zaARMm 6v?4[4/,Mz[z&#H[*tIf\e@Șݻ20ZzPـXor D19hNxK1{M΃շrzd @[}{:G]1`Z5 iFl"oдqGք ;˜^0+k" dI1EMWoCt{*w ̵[yT<*ŵ[oI$߹Cǚ,'9e6SgbG5 ےjI'@Sibz]*6YЂvh wI8=׼qvz4h aLpk}xCa@icʴgewO:LBtZae}\T NYl1-!.3RΤFB$)|իm3@᳜sϽ?k᳊<>=aٰfu\PHOe,$ґߋ^e^\6қs}68|B_JGvz:UJO<"q n>x0,#J@?' 8{i+h1ᑯ2 +CI}iJ!w\K]^ 3Nx0*,_ v\ XGi7U [;~->%?SB1^'p~' Hxs Jzlu7Jȫ7RK: 8&1c#cxh(9*]|fyC?ƨ#9狼.mPw/*%hֽk|hyW͍Z&C췵hLnou>OyR.%ڙqhDžG ޣG' ʂ94ض~FsvyXRnBqg9ƪpIJ߿~٨S/s ma\ekG#ǯJNE'%-'kd=T: brjkqXm&-٦_Kem]h;}̙k$8Hn4R_Aa{fkFO\M?{O,8E,GCs5]\t0gL4ٟЄ=MH*Hu PR|5c/d[~7ZVQ{2t k@^4THsH0 LN!f3sӎEo]eN&D? A/ȃֲ}ˬToE6`~]-! ;Jl.VH}ضqu<(7<.pwg7d3B:)_h&w/#yPIt u0)L3Co8,#n+A|1+x[,W7hiDSۃj9u@_u|*~>*Ve^%a >PI`fBҁYj~s60: :X,Fs/ZNۀ zTޟgޟ)y `咸ߌ(y9?cVX_4CzjQ>OE2͵hS"ӳ̗kw)_ܙLcҿҊkbi7 _ edU}pTV23J@hHryuVROBeEȓ/>.f!2A nowI=C.*-ޢ:X $uQ3sh`E3T%F9}]=4sH+ YMsJ} Q̼dHɻ<e>˛^CuR$"bl`\&7-tf46Pu}l {F#f h7M_t'QD- :kκt?KJ?d6{*4(z D uTZRԹToH)PY}K;3h,,w 0ºkjXyܕcn (Z)дX(Pz8͡}cZNs6[mTD GK&r3h ]"z\4(I EOiBiDABPY\G¯{<%tjSRVJ#{⑌%kBEGSO&%bUv"Q0%zkЄ[ޑRϱOPcf {^g_iuz ƫ #ެt.ȱ}zx\skkĎSnR5bPL5'R8cRB0f!u)tQp[~X ʊ(kZ?GWӖJm_$Gp0|6ci^?jgoޖya}bp@TCq9*ńC_gZފf21'D@;T¨H.P+\Lڹ!|zσSk_{+#JF S}2K;f 70ÿˬ"c Z1QyP`쪡G z)[\Oh-q#0ʗjmTxPwчã oqwfpOO2~†Ml Z+g*{4pcs-l0\=>6D.5j_;:uzo~)q;K|j IhWX1uM0vod^2ҏ@7B2u$&VH# owS7/ fY!aႆV0r ZQ1ChUݚʭҊ}hC`,#[OXT5/m^L +] ]n n#E h Mlʼ<A\Ozl#n/!xЙ9]5󮯈AA>_q{[D< &]YL`NfI#ls>Ts~}͉6ӯ_8vXtGk|,፛)OX*eֺSԘk~/8oږ*)S\`AkSY+ad}9@&[F({\ǯ%21ΪP3+LV$1V=]7Ze*sV>vYLfTI>Hj(w-OQHhoIoS:>;nCZT,3ɗp 欫H atAmi"f߼^8%=98(hԔ̇?52ԾyȣϵZ`4ڜ ,?%@>-PYF{.,,}Y:BB<+gr6Hq#/EK-H}4k~װywwƃ)軭CIگ6 |&+c9fj]g _vXEi=~f3ߡ~HoL=IڨN#o+x!pJT4U݂>eO,s_%'cAI |UqgH\>, ^=^6b]z:<|,Ɍ^-oKrc=VoÔsكXrrWup~VJczD6h_O! J[^ӊhdp[COIS2ҠX\D~{oY˗ Z7S$>o*6#&thZn쭇gouKYzD wg)o2YO+h$[j;1 ZRۃmՆT&N[%GQzל_ءWN3ލXXÎp/)ZG6FL{oPͼ l9[IhE)q8Hh"ܬ)nǯM)Qm@<.8KH+`iزYsH״K ە6xc)vih0W gB!WV2wcz3},Nٝ3 z'5y.֌iƑ1Fae\'"[κen%`PVx]WL`7hX ߼A|X0^-?׳] Ay@Z+s4F[PؙD [=y0*(Ьem&_3eҏYlM.'-vqG xV>O|:LNryro_g\2DCBs.=)6,GA*#Ey*?J L3*㠵d3Gȿ˶p< 4*CE=;Et)J.-N!Qy4VWrs_Pd젔eL)}?qv|inUS=Ǐ透|U2vUO4@2'ڭ?Bs=kfHCo[q׺ٚ3(b,",L?7G^ySf}%4, 2SJ ̳u2\f(?NLu.y6ZK^M"s}2ttl)yjCViU^6BWl.Xnn쳚/'0vkd`orRRuyyɎQp^|Š<ج(+we&=}zk@}gu?OK><A-G|IZĞ`٩{oL4Кd%VI]7M1[St&d4 >N2'I>}A茦b3dtЂ2ZU9tj=x6I>I^DѬti.V|3sTarmM 㴸L*;LmQ6$T!%K2 >jiug5~$JΙFp1J BLBnZilt]1{PFЇ+z+Px'8PC•'KL֊i/`SHqDLC+h3O06qM١0bj)OG9XUw@WY6m΋q6ӈ㚆Ƹ6AӍzp& ##CĶ45Ds?^ wSswnt$sl y;ytN *X:1/sFt[S66V+PĦԮ' hu[%:F{kBE'4IWh:Jڭt'=c!7Z [P0$"X_k0~j9 ?ŻqMjKͯ@tdاw}{mC}DU-%ršN9ȧ"I: Wߗ,_ЄQU2TSV!}zx\n݈Q[ [xsBq/.[{m/VP҈'C3R_h?p}z^~'ڈMPBu»M[1e@i RW7,üL ^9P+ExN-wܹ;3#7/W3ך[!5y;,4OzfR[I`vaf*^B+faCzL̊uaܚ8M+2S#xQ1V:++^X7+YyP3gkƺKCF!} ̖vcX t;i$hE`ݣz^4blȝD&wE,+C<'yA=[?X2=}4qŬ|KaYiht9=m7MB9PˬIYTU;:VG>@^:;#ׇ 7Ƚmkw-) -o)tp0 j{}3f ѷ!UQBԉb7I$֮8ϯ$A",]nK:겹w?sv:l Ec#qY55ܜ_G0H^u cCUqy56 MHYb5P46IfB|FoCu|L9Eؚ'2qXOW06 ݋r'"$wk7][e7 2}vS^i%;Uy㈟-LM z~MM w, Zce+2m}4W :>3C:X[O' >#Oˋ <~r?{J‚X8Љ^^aj򸛬DbLL0c~}cg5t9uIy;HY^'* S@<(l()2@] `^Q9Èn-y m&Aۚq\ϻKhT>qRF>Cީ%-o%`|͔2Yq T(%>า@.I-N(ӓ8jXDƭ5nfˉ! ~rq[+*#y"`g:}(銫Up2tبL˝q_Qݓ;gxͫkGD q3/1=73`zy^ s?/ghq6 `^@%%ݕ{Rv_.j+ҫ1DFEglCP7aI6 Q SE5ړY2 |A=;œj++cגf$dȾV%mKFNL*)滍q\c #+ ?[BͶitw-nD}dQ~?EsZ@~\?S\>6rS_{ z63$7}ܭd r+ϵ{e\?gZDf\NmN `1REOCh\]a|AIjr{b]4Poc)f]i}zM3p6zVUWeblCXP(`-k@P.6 MTiޮA'3<:>WNI 8 :n S fMی;Qf6%=9FT&Q7iAB*}c^q"[^h&32y|n}<zdOb(ZQc35vy$kRgo;}5SRPh%A.\^}7'gB^%?S{{DУk/<%i<"#! |C4˼1 O Ѽo}E.PG79B|(G!eT;jLl? ~˥vkO?<#+Ær14g3X&t;z6%bvb ]u PTQ!Ϯ=`K1R[;³h.4!v侫./z~rauYNjz+bx%~sԕb$~?8%49NI9 ey+b]?{:۩=~L>,;Uvz2 П}vh{|Lsl$鸙 = o6`yg6AB*Wd8Y1g _UN{졅hҰ͝R%Gef4gJAJR6/4T\BreTxD.+j+Y%C`fX^. FG}.іca6:rWy~6Gh} U:NujP[B/yFr)/KEdˆM{Y dbZWC82p>ٌG㎟ h+2Զn_͚\-qr3AgbX?Dl N4l `t2#"߶7[1ݪ`f۽E!ѼsO;yx}8oT3Y%: :G&|S/ >`me&W~~;Q2g&SF^|WRafl#mY |*׺军\њhd'22ɣ0A?8ǯT[Z|&-Ys`l26LFY^Ѡi ɂʻX{ݫ\}lOZ͂7 Us\ᆆ ]mưPHAY L [`N/N#qg+z]mU`a'EbM_6iJ\(%J,m(ʥw6z YfC۪o>Gc<Y~-"qlN?܅d`:Oc-#_UprvSlb aJΣ?7H/b*( zqZDMr3"n 5hF(2RJ\ry,=7:?7Xef&dE6{3_)usR7L%".ӳh [/:l0m 2dT$!:$)Tewu0$ VS)ũ>`wѻ$Lց]kJ6S)Nj bm4U(;Vjc:ρ8}J d˛lo6Vٚ[Zε]`g2xHqC7Tc틹gq_xG-s-6,v4t2uk )?ڏ́?|7yv>4jS|rASdHXU[%ex| eBI^~ЦcKjv*/Y4wUV:ƿ4O׼ju`ND/ahCF){kkmOpm3£y'b 3 O6Kz.ȆLGv/+o3 ?DГhySp'MNĶiOR k`m <=MΰfBf DvwA7Jהo8rUgh` au[ EʱH29(Yc a^aGεz΃!GtNj Y~B !m3{-* J QH̀{#o5Qt+G%MNV~SHD],6Vr>=Mdg2, &z|F?Kv Hə'V^Cy6.1'O>]=%(fL&X\^U6H4 =8ԻO;/W!{1n ȍӣ0pQC|ԍ?RU cĞ{V0 9)_+"I>?K40+Ί^S?PIJFuh=O^d?9{.ֺPeu"_BT\ B/=5돬,Vx.**}_C? URUɌfLJ|J,cU]:G4(T4ָƾؐ(yd)=a(1(djlGdzY56*Mre%M eT^2q|3w#ddσ6E{9_Av ,dB<أ?Yciso<~^Ϩ5ܦtu }T|qq;z3wt0I.}|<+(ZSGuߎF ȷ" L:gfm3IyԹo~,B[%/'qpQN@<"&Oٞc? 8 cYwuh9o`=8l%s̄ 2UֻO~bli Zy(My/k3sj`c E1klԓD9[}n *F I:~1麱M>"HN1wa n7e>L[e ![~XD>/KAymrXE~0``0+T,#ul֨gj7Š hzE/Ln_sW(ӟq..s .#|JO;Aۖ`Вwv@2C/f:|=-VQ[&׀0yƫ_3I+d^il(N~@B*n?Oc'ǀ2phyf# hܭ3GXE ~݀)"RwZ?f~{c.+y;8zQT?[V7W =^AzGpl}$W֛k~­]&g3ݟo[ݟSL_f7tpi! 돯8 GlYXɮH8s:Ξ?>R t[~I9,q`*4%E=>^ܠ^;,*I+~{'b4+KKKMYmu L:hz+\t8So./b~Qaa`_)U!~w"i~Ɣ`$9_"\9s"$OT^0Ԛ %o&s);{yVibrKĚS"HL3I˿gsAI( a|&:UQO145l=^oC73/xyE?B~Gҳxx 3TywέN-E"!@hN& ϑe4d\zUT8iox7fMW./yMCKb;tC(rcTogp ~|]/jsBYf`ߺ {/Z}!M3\\x42KV,fƓ`"Nf[4-r4ciXs+8Ec=$\-Ei%r Vxi-S }Cڮ B0Wջ ;% V`AwVa G[_3w`h`iw?͓3=>j;4odS =@Vp ^(V,"XW? T0Cm$2*8l6 +z-gs' nM^<A8/f>sbM8ߞȸ:}| P8e%fά߻5rX߆qlucVcLav1 ~qsz7Ab䲜]e)s&㠉vCWd8cO+} O}ϛl^>RlEWYؘAw*L4M1y=Aw+ҸU@PuDkR_| gY犁\Q-_[Ag5A1K0;p3JVӌd p̊-0O+i\Um[$khwjHecHƁ38cy 䌂Aoz~3Qr] u>*Ъ}jFdG"f:U3{U¹y&rt7"#G["h7ZCe޾g:1.ȝ>y'Ĝ&Te9]tq7L=Vq|=› F/Cbm@_}ToJ'0b~{vgՒb&@~;\k;גb*x`QrDAS̥\\&$fZ4W7DvTOP]Dc7q3|mo5|JWQj,[-&|uIAn(NND^lp=i B!s#y[v8iRf`>YnjvY$ aAf誃nf>m3On7T+3dd/##?_LEzH[6f|- yRnx\k̩Ŷ3x`VtF'E?`d 73(@n`:fQec*(tBo;)8Fz]X)bPk\B FO$WEsW/zRZ4ͳ\zǁYJӬ,{~΢tH%M{I uhiTo3hδӠ˟H<~dh?[Fkm*д2_c @oz7,eO SV [qj:i3H&:AazQv)DVf%Ϳ摵,녇h\&5h%C/P5m ,+:. >hN Lӊ߼Ŵ2@`MXP91#d1m}.haZXoC2 `dB[8SVR@jԙ,jwQFo^~ 9yo(@Ʀ{RdN@r17[M z?(Rߜ@WL]`)EHTveB%bVL=} ZLd ŷ2*}N }aR[%D3BVNԭ&+"9Uo‹3KE|[͠eQ! MI|4e80VߍowC9Չt -q{|LU TP~Fvaa¿k\e%<׺VTۛ6_+m"gùn噑],R*(=1].ur(mfKA+ag|nJssXy_ti?y5 ' dK;V*޼p "p:iJdw hғm%=IјAv:Fw(*aՒ%=vCcam_ZCPv\!=䫓)2W^:w16 r(DQd]C5~8iB\<81n/q"(#9*;sїa0,8 ("Ϯ;fB}JDgYG>J/ڑlIެOL\8;^XCs|qѻegѨ9R)\d*6c:h_3[Fޠh7+p.tިc0 U<׊=d8_xqxzDgh^0^~}}u8'0ۓgOVbBY.DbWϚ1XevfgЯs[ ӿC>q/}.s9=m= v~f!|0 y~i) 9ba2<}X/6R"/x󭔅kkBײ8WDFѓJ-ZDqSBώun) PcWH-vf^b5Bqt~548g~%m+:$ߖzPɼ˸\0&k{A7cݰկkc#fs˴yk=Laf3eq&yȄpBT»U&-t ![t8?Enf5_mޏ_>ق3H/#G5͗FW@b-+O)\{?")\ɽb{ ;{yϞd5q\^o|I(Pxf tC֛5ggy y=+>ǃҬA*Sf3˯NކL}HëbOCwKQO\fEE2V! \LVl9hK裓ӆz"7z0tVrg_G.Aכ⺪1 nnCw}n]%3Zy)`E.Um2x \<3[T2S2-dC.ٖ 5/V℻s_}. lSwu;_7V Htj]pHߔm=(^Iy3.s^{Xkl4(LKe2yB5i)V J'vG-K'_f7YDnzy"1Ju$~յYZ Loƅ]Г+LjJ뚒ڔ^m(1x6_0Z8-m]^YN7Xfb-$oBc}v ' )b2B3D}rDLVֹUYF_Ϝq+Z`_G)eGJqUQ`{"OW?'\/z2Hu L]g,%4NTerry ̖MeR=D|f"/k.?PSInT&TRf%{U#q[0ZyǖPȂ&[>E5Osx*hӘl"%,i/&.IXW'o0݋ۮuwCM 4%5v56l&Ē2`{XO:X>?f[q0oS/A~5jgDlRd:xhڄ2p~|m>,ϻlf)z큽v2~K?N@< ey_%lVmj>V&%S ܞU͜( 5gqm} q@ =yAF)dI0:I::n$`AW@^?oK|4{S.]‡[`:~dWT42[Fzld !fo晎H<s[X:=PK1hVsg0Jsl!|$r34 '=}Yِ:"9CPIkN2dPhhz>-]TM-16:@!{MG u[ 6簃郍|û伢D͆giC.py*{-WimpN@ 3'b$b4ֶ:"3@ me^Gy mclX4cL'\= 0;wi$2A,#1gu1 ޫY/xu˭?PZcH٧ٗt,1!^kq沺U|3cB:V e}mPuIqnEgSV2[oG5'rMxd1Udf4ʭxQoT ƂodRhҩd ͠[&PT);ލl~ys'Iǐ˺̄UVALy#Ǫ+s0ٛ(SqqէkXic&{"?Kv7NFQ|bИYTAfK,^VL,3Sˬi,FEB2rQIѝ~c wLҳ}4=bD͉m}/>Pޞv=|VRVr\GbE m|2'k 0 s23tP4KMo;3>,gYhI{.j<`ZwIIDc\%3|{l+CK8-lr)6XCK πeZ|O - oWmV 4w."|dDeEM%wg@e1oo_^j '#F})#Id,u}WaLN"BCQFH5@Gzw:̠JZ&jppNg2~r2;DVagǓGMBs0gt|f?;8k7Ԗx ؆Vd{}fMݒ~B KDwR^SyG>^')Y\O3JUly]_]|AFW{LnM0:%7FN!-w۫I82UJq=e!IPz9^׍Dq?h1. `}1227 )9յh_STiܹH*X3N{v$c;+\Y{2-ޠʦv@ E _2ߑ~ж M9E%.3Y ~N !h 3ݣRȖ;}nbC~V.n9:b骜&eUej"72w#O fnwWjLݲk'B̜K~;/~ܸȻTYzPt0>(33egSǜy롯[~?EN|9fK }H+vqe-s? ZG6BHcr38ᑹLx@K*F/2U*{J0;2ܝ@~d09.`A/d(y9nj-FqˇHH|߯bE7T;kK~WFY'ahT]u崈23^t},+ޝa-rmp"1{Ø#faF*s~xz-t~{9F})5][ͣ_-u|t& Kt/ǦkEyAU\A5us I9+)0B^z& QTh{ǑC*fIf~_SDiŅ>9C/=o8L]56Ґ25)[ry2Ё. n\Jbwq4%gsAC'em]8r3͎kýfB=t{RwчxiǷa&P7Y2"r۝|ˑ<q^v"0{A(XTZ'\QWwY_jKL;X0cs__9Fƨ Z x Ay9d,k۞/ITRZ/AƩbl n%Kzϣ<Q czP !'$+k@!4$"l#@wsJٜ4JP=f:dZuFDnd C U<_1o|fYazF{SA EGӝll:r]6kn "= \s/nFؑHP4e,;p q[_s+{H:9#2gE"=CDtYWNAI#dC|#ߕdA>:$#͞7g 5id+TunF-"NT~"9M_#ȭƌBxM$Uk7ېdmwp;T2RP \z c寈oхע[ ve,;Ρ[ν%y0ƒkkx} wV'/`V k!8Z=du4T7 xkW?а@+u{x#`0a/ oQψvW/ulΗyD~|>=TyKe|uJcQ(BÞ!kd*|m`]#Ņc8`Knb6D:"g2a3= x`K_gŭQ^2лÌL;toK)yLJU|Isl8opr![4&o^ƆGM'J ,"*XRobʓ99^c {>-Նsl۝:FDGEX~2u#$Ʉߠg:Q' K%.]t2uyVJktvSyg(<`3CP?Z3*v(bK .rhG PWk*m ~o?8h6r+?. 'n*1ņw7rٱ9V6& $"b݊bJ@e舭 >T~MufEHZkH٭SB؈$F#(.\+=E,u.ȌW!0:RG5{$cЁ.He@[#uC,zy^[ F!qo•V'?egz.gSJ\ݔNy ,7n9ČWڬK?~7PJ\=Fx2!E$[Y\@X50Z#vU hbq~l)x/(hwYwXޞ:{El/i-^"A*ެ6(x'ZrÖZxZ\xgekkزֈA^C=^7BY,,+V_2+uçeRow=`%o6 /܉F"/̤y=e!{=3Գʛ bZ5>w],Iel>*?i.d:R|,}bY+װ%ֲ^%w zU߅4=2DT0ZVdc4ãaPtdB#c,7N5Fc/KiXó!v+>:1J՘l !*`]Y¤=#W]&JT)sH׆3KѶ-H`\pdyT"i8zw`*Z%(Yiզx}6*5VMëAcH@i.aKݞMp<שe#o"SK$,2)N-I-#}dL@Sˀ>{<=,εEJPh6<6lC Fr:$<̯$9ΫvܣEcDzUɠZn{e+Y[%|dYUTV. vcEק6J`јd%[p4XCfY0 weem!f L2 m2ڶ2ww_~I_*>eW#Fi<}MwW^t kI)IGiO")jé.6:m h27 wVK d(&*|2gQnt JPT!4N$pwM"ONGB !OM#Ա|%OQG,K&|KqBLfI,@˲7ˈy˾d`n|۱7N1#a}hIF fڄ /S^RdJ4UR@s6HG4^ f&6B x7 tTe.&.jcG(Ul! !b~I[B%j5h6;iTCs]5NM5e:cWaC-[Έ6ysKRVzMRݟ7R9*"O:tVK5=:,Sv4a{yU>EҼQ@+ R6RqSϫc<@:Sef ϓS4=_Qa j?lz]]zzmʦ? -yw/*WZ,p`*#|wI-࠭>Ԩ?>*\^{ c)6ƺQz!@B5Fm?ao,r+ױ-5'^{y`bmsHf^j`D3;s;e?ry9IB͢v}>b Gܝ4bKi2C4@I;gˡLO_*s_NdQL 3KH'G@Ej-eŞcY!O%vWvQ{=TSw  >VP=I8זc-e xL\nftPws7( CѽWjA s3|Rr~)FBrf30JuIxLNp!Fd+h {NwWԜR׼U*Oj^)2^:ՙzt_^cjFr}2ZǙM؁ ,w>:X`e-P`b617XQ.@$W)쬽6)]!ɏ?(d j/H[,Ua=q(S3 Rexg}<6플U>3٧K&?J5#NGb~,4'ӹ0i5J{ cjܓ ;Ի$W}PF6dbJt(5V?ͧ'bF mbWq>+NP׏is!粖ִL͓a Ά*ܕ7\!0<[|ƍ|%oVixYc],C>"!{ޥ"u723u_* dKq*Suxp;4&SLCO.ȃX\:WEg7ْZ:oi% ;FW?7sEQ`*lJO[| s۲d7c#2 ~bNn*E"0!jjKoF}^ eIUp>p؁ d|гCc^xw;LAFNfz^2r\f|P vEިU3ymuڂK},ٰ(tdSTԫ6_ⱼGCH"T5^+w_9ڧUcT(A(qfEϴVK+ڣ8}('`aPzp*<47!#*2N8Waf+ZS]k㋽݋uz,\9\k֝6~gQ IiZB[mV5T' Ԟ+o/%>yn}vdzM`m줮Vud 2픵i.g4`@M֭w%ޢ/LsG}C3<|AJUoRӬGM' pi[V[8RxH}iG ?8b7 /Q aslPmlft8g-Clܻ.l5 ͔Ϲ6҈,@iQ8m{hTj+n\]]z 6g+ nz@ߣONFaioJl {#6D n̙$͍d+?BwUqԟnѭkFexL\n Oz)Щ*l0ј8.p&K3sCzG|le-fOe0O4+&m=r۰Yh)2ϘF {M ]h I7wΟ`Ԟ,x=Y -E21xlS5yB=g}ĐoXb%Ն?DQr6>e@!011ql%k0 Y&ڗtfaPԔz&ȅhs.ߡ=((j}䎓"-0 ,Jgyڟe&|Vd9QszlH#)2-_syl.ų['w/RZ$<(~ךZl\he+ xto[~+W!3G^wz\rZf㴒iMJZb߶5V Pb͡|.r{iT27io [o\.6ď,[H,tDUlyU-Eoa.ohupTWϞ2j1=B$BD{aS$'ʠE/9v&YXbfS*Xzlt} 7 ,y%UD[a ?R5]0 DYW5FQ\OE?U$|աt}fXQ@]|w '˽wl6~@Nˁdf g#xkU DBXu!YfogiW?<7J1Q`$9Ձ0SOe|,?<?Y_ȷFW?>{0:,Y-q?\#cB=Q@ 3z*?b,/5sB]̌W<ܭ*o/ *lDZɲ@Ȋ([cW> b*)$ARd89ONzy3bb eNe7&t:bz,aW?{3(|zBFet$u+^>#__w먁čHzהxn68^Ϧ\В;~-3=l ]g*tN^g"ـ3aI W{KewZ5 k2R(2WH7 ,K|zw,\ߢDoț>mb3Gv| 9}$r$wش,wK>&wZwӘcxJ%>*`e0VeRAGt,>}WT]F]0ș렞O(ϋ Ȇ ^!`[4IBs0LMɻP~8db2ra2,ő"2%Qv؜|r q?!wu2DBO,Y@$ g| x!cֹŁ֢[hզiЈ+3]?ҰzQPV;s:ُs43 p]nw1;gOi[OD>+v6؁ٕFװH_-a=[Nw bo]_^:ݩʬZ˷>J wW3`6Urs=~Ot0,;')ēX9n@k6SᨕgS T]y@SĬf?x4+f$ XX*.>rAbjèhb|K : S )g3m[Y3B~XѶȮACa,*]ge&|=RʄbN*Xu yc+ZM#}K(:UIg״mG)-;~c Ah8% @sGUflSnvi'UܶFG>0̨ n2F8u]h:vD~O5\]y67ٻ&_Ԃ)2[N@V8H1% *B KvC/a@ԯ =R͓)&)~ y`fHJYX$EsQ>&|bzKc=#]+ :3tqcZ wI$PTߕ7 -T9Є>u 24r m{NJs'd$G/n.X~GZݡPRHX687ƈ[oW:HBSy'i9sV'ԉ(^sÈ؉h_d p޷ ÿc+AZzt{C>f?so9)DѴx#<%=FTUgeeY3" |2euPsZvd %+{ǎRQv n+1TY-}Q phI ~^eDt@t:FlKYDocf<5;R9;iw#W(+ɉ1̻֝\Bdb|/YLoxҶ3Xa~4eT_hYx\w̜c,+Dޠ卵,5VjTKo$o)tAjF߲9G"4^.!]~]Xwd# Թf'?W-Z^Eͺ(ΆV)7h`:4C=Ȝa"oxUgS>#ތ$ nn.j SBZˏpƊN3{)-0Ԟ^@9uu˙_elh= g=W(џ=GdY^}lu6ưi?vBw~ : aNwR1HVsi>0;ㅊ~ż"[' S/o0բr'VaI^Ra['snNtZs9e8oi }h@Lܳт^2~ 2i%?L4@n$ڤB7CM֑L&@@NJljsꈦz1jjylL0Ţ싔a{Ko}:nw/Ư:hD9Nuq=? w3K@/?Z йO(SK`'OC0~8]-K~uZ!\N!I~\D ǎm.a*~E ;Ycz._E\ß: uqcfSe g<$2]"S/&qxa03k9[ fPbw>QuAhV~(B DGHww0LgvS;.yPtށp_/)nVuZrҤgf1HJf:ҭU'oyҢsjR_U,Uu6*EXLE-LE$QֹJ\]' ,6pRNDA]զLdP* UYpߜMTupԱgKQKgmli'R#h*bղ ׸Ax:@&d$3tje|4sw6(' Ʋ {'y[nx!݊IMlsdK6Nw*eMԺq+T[H.ݼ9NˀѶ-tuk>T2X=PZ]8jpVB[E5\cZZ)Q*QT@JfH`G<5[Zl^44LҪE n֋4Xp2R.5NVMAbҎT{,˷)Fn%GӀn [G$}Z?5r s: e&˄V"goֱ݌x7]! v\Ƹl5'}ҐŖ7gn;ꀒ\e@<_X!ѕެK6k A0a5t4Z+Kn6"JEU_ڬၳ) j WJ_4IOGlSǤ@ g1lhldEb?՜E5N`q7](iRkކj5/dJߵ6U 6aɷr4tsVqԮ[aĆ"GݶT:{LS0!;$M(h O398Ie#6u Aэ5mVrl7#wU*:ƭD9mX2E B)nB?+(:eX[`+n.vEHzb#VY?:EeZC$]jm%"pY'" (p~'T1c 6 U,7 [UQͬmR}B3kgn!Qݞ԰R8:AmIB]WmXN'idv 7b/\#B6 )ε4>%"9P 4COWkJrJC_fuݢf>DDlL-I6TmaAmUsu@[(; ta@nwI{F<`=WF}Ae)3fy'f彩+ޕ] .=Fy#b7:]$' ˾&LNT˖Y NXd E붢6AnaifJGdh/5:Jb. -Op([e!m:wl=6 ֨V"d5ں&8rXү/F&Ovj\AK$ƖI4@OB! ~PûW:uPR=fmx,=1fQXi7zI^udB >hHIA jơ*؆qwim*Ϣ!)Mz8ΕFӅ  =e3&7/4[_ ^fK2Gf~th _8pzU;<{y-Y B9 PP@y#£p^c9}%74ɛiW }iQ{Q'VTͲ!eF䬮,x,!/C^K)/ozl)X,;6DH[ [{JjwْA+#[ tknC3z̜Z9{tNK$49֒-ApQB%>OQ |M` E/;9;ZhNӬ2]VK>UB ҂Evˏ VRaĿ9 cs2UD>}c|{򐉋0?zuޟJSXI($!>?K„m#'\t-Ƭ3F)"VœxՄ@\sMi+6\̀ d,3hJVI  y}])rKޑ-+5kW %h28Th0vѰiE@`#.;\r8]:MAG:B J6Mv?Cw50ei"O1WP[BG/ ʳ{́dhe=lj'JFgL5ݏ 'ҳkMbǂeNV7$аAh8|Hj:g ; *d#fC|Q[ *享W?1˕zicMXSWDi+n:E6!eA<ö3Vv }F`7K"mu6p1nKgc |Nj|FKV7v) /z HKֻZx+i?Jo>*mtgMlFWl=?ѳˆ%IB`IBMX^ew_IYNV>UqQ\DMйnd}N6)|iϳgh”h__87h#\7a)u'xdׁAJ )kB^bKRMoTPn ~^49!=Ṕ2W|h~(i:t(uWaбC6E>3oD_eD_URv;c fq~huCA}u.F5 ؍'M6 '̴<`(q ,:3dxTORQJp|Mog|`[ǒ3C !˦SѥYMԱmJM:5iCդ,+8D,9T[,Av?kF7;B]n@?iwz-ܯȾg~V!Q0Ob]Sa|2Wo>CIʶA~(29TY6ѴL `&2 c-:vHiC p}v>1ȡf bpcqF zPvЫCqʩS)ʓĬgu%l>@c4yvDmR<ըQh>ݒZjL C;oOwhnL9!{YZ6zeB '3xDYs^?OL|"(e_qdve~ii0[orhrNwiGxXD뢨F 룫}䄵Lt0\ű>-J0Κ@1Nԩ쿋O%>%jpjFX|P:9ɞ2亝%|CN:29}|E~2 *c[N-lZf^ IYc)>ϙqXbFlV2|b}6<7>Z֮}pɀ&HYBX岳O7L!dLy(+N ʫ~TVڊ2QV"rM֝D@jT!mnsOJ튥<|i^_3b 䇙'5 51viŏ4ң骄fw 5VEljI7U,Fޟ/fgPpv&8塛Nhp/)6Bqz:k/;t֐U[ΰ✭ШM *{uQG=88{eNmaA9bM̮F#O޶!A6ATsˡ:.PĨKmN? (sSJTKA9e.+ٳ*MANҶ]/>ÆN41's9sj+,[=zا ig0^ 'Rv7*+LDےeT.RuDcBzq9jԺX/&~ [sCw:IԴ>m&{t:/M'4LC=**6u<i b.־۵~lQ\!ODt|Zg"h^_ o5b'׮Ht ^ÿ!-*`黮]5i,G5gNe:!~VLV\:C5@. gBE{ZQSjB,1-@t"x5::į6Ʃh\jg6F:[p*)l}FUdJ嘞;$֏!hvCubQ@y-y*ۦ*o w5-"GC>Vn1҂99cu86@&-JpԤgQ-pдȑج^o3 9Oʕ#)fINӶԡ9ih%!2|1[6@:KMM7HU`,k[Xk}#T{XlarWnI6i:E sZJ6"n؛ [ |ԫGƶX@8腠-A2! cg[] r~V0՞nk;WB4a6J~938d|O{֍}\T y6n#lYY:8,pkAYAt ?,d-P&Yd^nD5ʹhZMtSӆҽsѣӖ4rMD hDhem1·O#<% "8I{9R F:v5OMN=U%d?si Mꢦ陌,:5Z. GO)e&7ѧةc)ll. -f j,<Аuq .!6I6Q. |[K_Pѓr1qTɂu(?p>+fؓTF3Pvaz6_m00GXK_}aye/JFL ϥJs;LYTJ̵VW5d[P  &9H^RMdR 906\j;HϞ#5OInߛcv QW _#Yd.4l?.* ->iXKBHD𚕝3.v#[5P8\OW)>ȎA?-e#cs%z97ବ)Gc(RmEv{)Qqoj=Vc\+%^ڐ ySfR\g4: NfwfD  <B6'8.rI R*'I>olxGY=~K+,{KvQww$ !.)n059{ QYEZv_Ͳ5{ p0GvZ^.b4pJns`N`}!GuYޱ42H`ޘN"LcGYۀC$/T:MTFL9AK9A%bg׹U[+$z:x}]/a.? dxG&W3}ڛq R)lS:"B6ӥT?x: S]{^JTsK.ѶVquY~~eq?{L\v -A`AÎbBT3-U3Y~՚ռz!=N63ƁY.ěMsOh/DIb!2j*:*! ~7 Z': zT>n.ӌky#d)HB :.36  k0 xAg};gGieXb30y\u")x{,So&x'RE{kcC_h97(ZR[Ή@dt1LcAIvҬNT Rrާ4O٘OѬw HwpD.:m6HGchřAYQY?(_ uJ3[E̙m/, aC*mۚd!]U5ݝ"7֞x4{$sD/dE bdW*t?#G*B1fK=* ͓XUxN)>ўmuy@^^aޏD #.Y5g}t|Afuhkԑ?(j[3>s(Y`Xl#$xfhi6R&' DzAܐt+oh, OafpEF+*z0'vS rvjXove(v+NQq0c'eV Ɛ1lXGD)bmOsVIBG% JVx͜ޣ/D8YC g9Uadi<-rkZ=;Wl\A7gt> 8 0]z6i2#[)smOWML?̓ZݡYWw>2ϳs7Tg~2>|>wOxS޿˅luF83 Yvr:s{Vos͝Y&DO|-d'^D0,wDnSĐ'i֥b*o)Bl޳iuC Ҩ+GTKI>&ErƳqfp?>AfL受jQfjirBm~&9$/i#o^T+Q=dŽV]2Gk1W0ɺ©Vg!=I]!>_"e rųgAO OGNrnX+bNRQkdC^rs꬗FtD(M :&iLM] 컄IU }-w}3[n^@z?v, 0~w1MC:WGq6q`wb5ٝ\xi(T&0$5y: mʾ9g{4T|0'd9toWM]ϙ1)c`Yk_cJm?יYXYJE&ʷ[FV|`>9S@~nv7:ةO$Vc $5DTZ#YǧpлW,"]~M<1u3Jvj6N)J?/LЎ*Fx.r&uT1uШҲ wm*O WLS;7$S*JMc/hRÏGNӀ!uy,=.CoBϡ,[wkeA "> BG^۫u+a7'm@(C f4 ;L$sc8^Ay$n.$&iG7J[|f K%$8:_f$ FHpXmx}:('$K[ PU*-WTM)EvZ%}RH[$ D To(}cL?4Vj_Scޔ~)[&Lsm20ՙvŮeο}ur2gvu73qNF5fg2ݻqvWTK3]G~Z;MV˨~x4u {Kwhy. l0P,,VL`ez: 3Hafb|^;jS/Ze%JcWɨעX2dw )["yӃ^C5ܘ7lQ? $}OR4TBETo2i*1zTj@5fis9BxgS6?9+{\CsVU=1g 5}Ck׍ C1,ޤQQgriHs? O=h2dѷM_6]:r846Bae˴_!Kt3 Ț eO_Y{:-Mve ,w2Tgt e@ivۈ9yʷ^4sOa zD˩ αeh49߈sl6 5GYB䟅t|@V{OMGF-,s:\h2qb%@÷aQABvfĝ,m"^ Mۡ!,;g`ez&´Upi` Ŋ߱JK`ض]L#B )(THmrnv]h$4T$22| S"b#> RNl,Gx7{q5|}gO=KRd ڭ,1L':s KG3H³V9n@T6д8(}֛ 'ow_%ޖPmb3-6& ;NNk)N{$[v(;. WB 6yh<}M_s$ s " har ,e͟E͂k!gDj[(\G}@JskB$цҖu^wPeR3}/_f"؝l9$:pR3JVzyV?`\c` 9%]rZEv{ o:YIWnՂg?\+J0͔`'˟2ӊޘ0k86j F~&~yBT Yo(V=jmyDEJ;/⪢%ͣHC31 rXfiH $n/S)ۑ&ϡ,sώ%C:\3Xw&reOPw/ZSjVe1%M׳P-`ƒT6G2I )Y'z+V@0e^E;AH!W~ |lD(sۃȴ$d,z8)ZHڌ&`s. 0D,dNKVGrG@;p9vSY3h 1`臺Q޻pP<%0+%S۱4-l/ўF0**D(#gIQhQxv?e82 V=аD,0hﶙV)?f|)/3&W(]3ϙ_~aCZ*c~Ə Y&Onypwx$ 6%UMP]n.Ǩ]!zfʪ4B}qF t&7yil>p-"oa-v4eWZ3TeX[Q'ZOvNjBRϊL< 1BK::^rE6E ;Q2\ (.UlڝI/9t:yJ糦WfD`AZc;ʻQֹwW^[3ۊ'pK-Ϧ{:$M[1U"Z &y`v˸RKn x7q?_gvJ7Pc$͜qCQ+;*KHf Ww^e:f 'fL`oyxnج,W _}(۷0-' $ft/$\*M*[g̕a_0xG-xfSTr43[-85P_V7=Aa/ 7/<#f(Zi$ndIuz0>2>""hT;TPDzį|^?sф 1B7荮%L~;O!v-u4;I1 XY!Ӱ }Eu]&g^mw=1 m(}W}Ue/TqQʼn`1V{plzfry~!A N[Ǝ62a +(V])vMK_ɯEogǼЧz:I&fG;>!R8=Lz^Å8NXRض0ԼQYv$+1ӕi k+ӁOE}$ʙJᅬG$AGsP"}2-pwf SAye8ak})QT&_3%u{#0-.s~h 0Vzn8kZ&}~ߏkIdo}k;Q)|yj`Elq$lɮ!! U;|.E\ [KئEQB<}up@z gia2nlVj*w$LTQ69[1q8Y&LwwRsE|6ݝZ44"L̏,ؙ3uiUn MoFDԣM8Ovξ䥤R4;q:M>8ԫ_"xzeڕ=GGQ {~l3a ejaRP?N6&g iԭg$A@Eϐ1-.MJ1 Մ"$_Tu2.d}wj~##!unKPwkEİlA!]ԗ`m1LhJ'P3j@CЙ+ptZZAz|WL8$%ύϟede7-I{W,44_ސ.ظ4Kem(Q l)mJ>*XRU ˔~ΌIC$N4- )'F~) }ѵcjdL,jTjĝP11BJz+[ϗ`#`xHc1=-8?_-+Y70Q-UNgBpMՅm9*')Rl? g(ٚζfyV="Z2T QnL:֣4kNuo2 ʶ0h˓aˆXi.;X*׀y2i+$8(y!jZ=-hGB}hKHw3~Wa޷SS"+wUR]BM d-H[~ foT+i.Z*h@s6GU>,=8n#dEuպ ykzMSxswTϢ=M<7ڲD^gnn5.j>+XN{wMJJEvwE&ry9SU}}$q# Pѯd2 H-RĢK S`?&s!NZc'{Z߲^ BV5P*a ܝ+ˢBq ]Hߧ"˽ s2iPkVJ k|SCdڹ}sh<ӿM ε~~h2׬{aY']aft;/ Ojc#>&tP\ JDY&Fd8J9jxqq#d7QnYVsz {NI~haG?[lj.aLfј [9U .ks5A4x%*SF(  $(^1slQ݊CP "k+ rr_^PJ4DV#lOwI5A {wÅ=4䥎&/oko:$kNƒߧghg*VI`4iUq@{Iİ0QX9;9Fv5Zܓ0Ұh7E\`l3oc+-(rBi)nRYxۆEXyC#D]*}Ò$h8=xNgZ|iD)[ πkj!*$0AdG9iˣ~d:z. {-wvE1<̩zu7?0e%6cX\Փ2O_m;Ǜy]$#hf%q= O= N{,.$@`>%;Grl esibwZsWl3,:1c,ΪFN(XTfM.3Tn'ճ߄m>&]7Ӆ,=Gi](x̷{[ݣZҬ~d4Vpq [F9lmNa6^S ZD0w]w0BX1u07V~8?GĠbQJWj GŞJobg{$t[ABk٨ 5ג7&D) +)Pj4lIfw9 rf&=H5;a D٣59ߺz%JUU;U'e=n2j&g3ILQ56/f|` )ʂsqz7~bV~&6\yfr )Pcplfyd0v:~5|@ôsV75xnT3+4@\>uj,({gGG=sk/u%g3gL5X,Ef' v*.2g _-t޵^4̦Vs\:JӐ՚y`N{1酸$QEr:1d.`z hy#ΐ~8j؅f&%"MnItؒCo'3zM '˨@B¥iAUO罆hL3A ?YG6666g0³i n6aWI˼Tg7yjP(rhI\':iWwBZ0]Q.| \kE nhFc?u i":-Ԣ|b g5eCḺjOPLuu'YM˜myP9>6ɦ2(>*Xrj:3V)"mK\% R:JKkg 3[Yg#ޟ3t²ؔ_6轒 Y0m(v75YKáo @2}ץkJ/nbVD+c;=@9}h<(;X&:} WEƈZ<9,3z(ox,YE] <@`]?T8%8Gq*ڄCT8,AEHgNřzcEqR螒;wdJmU X"ZǍ*8|aލlF0 [m.~'y) L@JJ *lѸc$G!ExvMl4WIN9pȰ?EяٌAx$C*!|͏L`K9}{FTWtJ_vTIS9Z}5ߖm4Ԯ̲cO@oz476URmqvf]H7OjsUG<З2NJOgٓ@nkaoi@Yp $0ک ,Z~/duK$#>h-P7o "ʄ޵7 CユGOka"[֔{n2O]UcuK!TX/Xx1@j4.*7[ݑuTLp&J!ܶ8 akIb{8t@h*SDlȿP 6R&鞢mKb$[0"vh1)o1W.kah~qM/z3(cZ6EHRS91KjӖvC iwhu|>HE7T &z6B~;)Z6{"= پ?8}-/8nw,d)H?O?ehhU@^~Y5wk5Lp0a‰!˞>׉1l&Ϻ͓DR]S8 O_qwS_Rk,HyWV Ys~0 a|͒A37 V&@{QHN&۸3<1zXܢNYz.cq(b7A~Q ,d*YfHd [^}.R}?,Eow3Tp[uK:F2)CBC]=vU jFo|;__h%r!TGp&d?le]y,);>Ope>_n*NHovv<+8Аe>ߠ2i9`B%9x9n1f3X@[CaNȡӼiǪAhYY׮-+I1 fE uN=\Ddh Թǀ1cWM%1Z2}mkp݂byVPl:8 OPn'ٶOiQV83L!=[I!SN?k̭bsG ~fgvMG'ƥKVuebe"Jg/fDХ*'e#9EZDۭ2P$+MBtj@ KLz?z:} kGi;fD+PB:~k*zb$@15YÞMcm,yLeά+/qm`DmʭFez1+Ltܙt$Ⱦο xC _!YϺ9 ?Dj?ia]ޗrRM-OF꘩ e^HP˺%bD)5gq*j0PcQ\!eB\b`xc.L$yUHaYMPa6#LKe `MW׮HTeL=@.砮)Mt҄n'!-aX=L2ĠR.iwȩo I|,䢟 ju77:3O!3zf MxaҾV.J6%;` q7DOQf UJ$ d{(kmqW_)e!_^v馀tЄBe֌Xuw)KIxe)<LxҭTVc؃n(A f1R޴U+PQ<=yԩ+NLh6;Lt6-;0d謧 K~1LGZt2 ȑ~nρk ;'ϝR˿s g.Vdomti_e("*M/Ţr2;ԣ$ flL[nz 9:j`(d,`LeQz0,# 3y/,Q9fS3Ls{:(>LzKc #~!st,V-6|,ño02S?hݺ }PG9 y;w17P|UϹrV$lfzTwӒ`+Dc:o0jÿ(ZvDѐf4sl?s d)/t/EnZJC[ DNqȡS]h%bB_I8ŎBYD.V/pK>>;49 /)\tVgyITIMHh(G6Xl8v f S`Ò/X qHUZ~I?\) 4:ɰDTynPrޖlZceF0{ YV%g(Nけ#$juBJ-)KTљ]WGR6D޺2&[5틧~oJ1oz "!?#9@)N,2BTDSI[-ʳFp {r)RMEֆq/R9e;0 MPBh*vJZ LɫU FMblU쨁hMUa>4n4S_LI/i"ds"[ }I/'~BT4{>/QU_qN vl,XRVsk'.()UyW>:>^Fݦ˖sd:dˁa%9k3. :uI<Ю%p% Z/jXe4v",HLv:țFӖCCy2h!LhjTܑ8q-ᦥC!EtR]+VF1쇇d|^!Icx<ڊՈfDVis/g!LSeM auKTʁNX@cx}ǷWc^E:hü~= tdIcN>$xB\I:rzu}Źi'eY#ñֱ݊qheayy=P(ۦIsf=_י}i+7̙Ъ_uxy۠xm9p%*F|:|i Ѩ6͸Ogo\Vڿ=\g?n䴾;z2v Z)pSGT%vo\vZ G<9c>ۉ8.I S;"?\ۚQD]_BT(͠g_ָzzE٪am0g? iljN(ctūHMK4lHev_K,mұK>V, /e@cK3܋%} sl؛I -/}*|eסX!4jQ1[`-g81mN৬[WDka[o{5D74?zSy?jU{_Y_'1^O4˞VFc~a4ю*z3eqXzH>$:w~%PpLPRd?5nn*@#Qt"84478yPm)͏5OtĆo,gR:y'*+*jӭ?#ޥ ]|Z=ˠ~wĢS9~ȾI1OSk{dr)E~]eG`,G.UJZ$A47O:D i75?믪)=qSS=.Jt9s*[v06I([ޟ{R;*^AA +#pά`o^㴆qhԻ ^5]A cw͟{b+u%9VƠyԹ' gz#cCVvYݡ zYav(kg˴v W4+੎Pe5Iz;C+*m #ˑssjA=T~!=oir%A)fSjSFP+D;y<(JL Ā-_ПX7$N=RzU5p$EqLͪ,kB٪NK-Ce34s a gݸ,6g"W úXaޢN) CY(@c3FQl 0t8 1j\25 +㬒v̪ռ=eo^YA@Nxr4܄#J?ݺeUvߡwX@fu`͕Τq2Uy1GsϤ Ykݮ $F 2/h:E]4.xu_ |] ж%^P@p b?iXѷ{$ibFi(NXQTao$YBC뾣(BVq:B `_;Kԏ&»:12j;>} qHCEw"s R:~sFfy<Ӵ}rKj4GhED0 XN~AD7A5g[`ۆ#]hGQ+;?mi =UW"/XÃLԘy5Z7[@^Quq]с OOIUiyc+ֲӋ7n m-;E?=l~zЉK$;["DKXCDBLHh*Q~F>o$/I L\*ܯQaɗ|3@_r~Iv踬 npP-' 淈u sdpn;vZgoU2FXp|rݛ2jFH=Y Ӱqȣv  ٪8* }h*P™>PڥH1kTa( [){s![Zc(,Nɱ.V9DzT5Fhٮ "etHMp3oaeJݮQ 6`T%lTʩ!`}_{=MˤE 'e'ҧei/2W@YH>%/1a-2/rVKNa˳,$Y bw-5Q7;pȴ4fN-é4g},sѮrΡɆfvC#W*Km^tlrU0%&PP|h{0͕e8ZZZڇusxmw_$MdX3x sY0 WDZSlPN=ð8T=ybQ 4J+T}AI ڟsLi86s1 {,}5#8}$@/1&#er,g:$i-eG:=!+0x"n-P.|K +#y^/ +T(intzu>`^,h(S$91\ C&jKyzYsP* Wv&ls p](Dn mK7g DV4=c]:Gje8| zށdKU9az7bThO9&V̎s ҥyhX5نd"5tCu;5Oa\j\hukY!Q#Fsќsxaꕚ 5h%pBY>SpG`ufP0r76wm\)Ί)]A$_ɹӟ1Z5^j]'~f;>qZ,'-`-vbPfP e}yV!:+*J*Fq7̘Wn87S"SI;EݿMp1~m?Kd ̣iڳ `^AD\ݥ U55-%B/l_߲ cK[$ tEzx\WS&E,UTwyc Gsy2CoQWAXM*{cV^Z?bvlB1 G2;Td{z􈠹؞t|څ9X@HoSfLp̎,Iy4 h%oxktaTVrYB@g dMT,mQ}F+uͰQT1: r&Qdӛhk_@%5vTɢg(_ldD?mNV/Mgk AA23U:\]ABSC DM"jDQU:+syOud<͏|B`ucТ/fͤ u`__W^=Hjl .|`2Ţ,-PwC0:J1`~@9N7|͈gĤ;ѐ2Y'&o};b->#<BL/&ᱟ/6Nm:^4S'O2\ʥ/A5 oY#>Ш_ # Dr=FQ$ ,c7{ScU?8{.M3:ܬ[핵畩||ikXVڛV*@bW a"W$$zG5=K\6_c_0;} ǿ=+e% RyjDI^?~ZgAjAb lE/4:<î n+qAA"}_Hg^ܾ"QN|䛟&,B  %'X}"jdOu(uO@C9"{{3])2Gh8l˦>5^ N18[ڸ /wU+قOu x7 ҹĜCǏ60ݻ[U-;lE)lU,=1r'ÿu9!,#g͚rnPT\$,H2`g@k8YnB*o?ש" Q5%C.$ҲqV1G/zM6rɄk&|P$mF-IC_%Ozsݕ+g 0eTLJd ZڭA%i$a$x`vwxDz[Sz;Nfl?Ȧ5o£sȤ$YPӟ ř74Q x[`DE*xmđ#Q֢@~J܉^:L2':iN~ԜK <>J$||A G{,Ta>BQOE?µ;%[ۈw>v+) $ 'DѭQEkPQiT~=$c$hNdtw2*{t h١c˂E'!WldwW9s˙C)݌6ac,}L5 2r_G.;IVc8*u' X7~^e A#iY1_ا4Q}iNj/l2(/gi톦9.d΍0/'(HgpE%F~5NBூ[iǚȑa$ئ<FAo<AA-KIf +WAԭ$Q~xx+㘼aAPpm>t8ٞ(OoY03w/Hu lʨqwÉNW^ֲ?_ Աr=N֋fE#}Q( :dTfhp}9/snI.YD֏7s;a]'جlԸ;J|?U76[g틉>v\cQeBWz%k<ɶۙdIyR.CU1nH_MIVyNJ|@YP5,NW%pM-(kU|rR|41 VlW{5M6 W^]}tJyD" gd9)i mn!1/ 5%h3X [ouPf?QJߪZ=]{{ U&VcC|;]α2KG;rʇ39+U1敮q>"- VR-"Y WUwvi%K9ݮJ s)ꭄ2E)W2-NUq~P8v+:ioS$آ6Zv0VA+[Bݟ`{?OkJ _<+%HVHq !MȀ(:u_D'ѰS%ŀJ~VR7dmi ٟp1b>")\SDO]v.59Ʋ$~M,r7=aPz$# ? ^9J?2tA}h_N=$^z^MA8EH2AGp3/ Xol܈5&{y#PdzMOĂ6pFimT|z2ӴB6EEiۡR]\#* ciBhqz+dܗ[i/iϮPi'sH|v\C϶$HZPӒ$ά- OCa5S#ʳz@Z8֯~o0 Z)C3 B;gA^? 񼅶x;]ۚNٜY8of~&Q͞fB{}zf t9Rsij|N-R"zy6#)4O?JGZYs y=oZBWGv`l,,bZ4F231Plu+\_u+0mώB3uՎH)]X:@0@⧳UE>OgVѡ,+O\P^MK{M'eVhvcˤj&qU2J0:MT4%{P,Z2 rmOW\iH>kh`^x-wI&O׼ʖLe[iwS,?3X~١5fSED&/%1ݴvPkĨB7 m;K\?T-cuqyNm$Z~RP` JxImtcK˚`0&0}8]/^QcR~>C'֡ra@=݅Nd ] ȫG82dyemYFwgcvULdacꞝK?,UQn{te4\ B<\hFۺ&`K]!k-Ξ;5aZ?.v/ iF6Kb5K-#Sh l7?Õh`ps.R=7Y'V~Zk)<*Dc"du:չ;ӵ*9vMg̬JG3KbGr>W VUwblYP\IGXp YMf'V2sb0:;cNa[@R @Zl"!ohAyCݸw0Ȱ5DKܗt;qzeEsC)0j!ըtL(Ǟ'87]yH(ߌ&2+Ρά)jPͽ#E6xcR0-6-sDkd|FYZPJM^Âj8E$<Ep$E-}.CV?ALBZt?3S@9,+!\KQEXm9װJ0JZr 2Nc!(\ XTJFgmϧ!mX>u7[ g >#M5^0;)ѿ-EvGN>q jCjg cCTARci]"S4KL14 ;:X$RTlv#Z}AB'ѻQUY:Fcru(!\xXxc`6~ k[|U"l^pvoz6a'ɲX龊6ly[;VpZP8.Zly#}-kQ!xiII^Y|;7ڧǙ?/f:Dd-Uң}fΈvzl Sh2;}UO(TGqB-].g/6őYx K@jhi:K))"pw洬GfH2ʰ焦%m\d#%C03T7WɽemF'm_46EsZ kNR@%)z"iRRT͔V*?21"%`phvTĢ^i5.NLs=Ў/*T2PU0*E3`LWB3 IVrMt2ae{N=Qr|F°3Py9KGMG fڳt唳vĽw}}d@?xq.F{BNa.(HT{z{%\i'0F}˨ֈ2šlÞ}_=S]O+hys6+Ù.9˖}1u.FrlПWқǚyV'=+h{NS4 ky^g5DQ֍Z6([Jm:0' qcd4s9])Ψ,dI-hYuY&z* P´J>LDRftްej0 o*`X5ͪE5I#S5R΋t[oijЮ/U cNo:;|(_r>L+?*0M(kwIeѱG' Js&" -<P*%p},QN[-yyⰬ2n5x, (Gx' Z3;kJB!/Ds K4GYWF ~.!Nz[tvJd_4sQϽzZEŠ"힐uT{<ͳJ/_4Rz53Uc(o,i搖$ɋOUZr_%iU^f& |gyI ^0KZ M#?Ltsv;~8պU.RdtycӤ^ ŒvLE0>w&s8rWh $KSĈ 34Z"dD?ܱkzvn~+I%sH-{$t C&0gK]ed7_??E<0 q3FC]]o3]@0pûA> \ՙvw;%8zB'(hz,xV*"!Bv^ZNd _f6:g2( )C6պڥ'-4 Bi10NXB?%lH1 }@ Q C!>ޝ㛲Xe+(A>?٣8'KnJ;*az+!~җ.FMt{Cyu=f^YZd^}c h[eB91]$m L*!F:G? Fs7@&ۂ^e.>"C? rǚ)6 mF`:u FXOoבoR4KMM|G %BFɟ~pؗ]$h4k+?ܼOiDkƦP~"GIW] ޠ>&Nj?3T4}2ʙ&S]KQKyḆzybS̳FC+E)5S+/eNT*eI^-x nWn Q+r΁nCGSdq[i&>NSSwR+qF(\ʥ"N$QTg6Avlk~dg'$DL;Ȯ|963𖵅 _^͕kXw"zip1UO5JIgi; ׮ T)Z1#ObͬӫkԴ㭗G2ZO^4_C%ؒ%ws|YVlԟ 8?}Sxl@yޥoFӔ<M~/^C17ʹônV&}4{qUt[ZD|qR"=6Tg-|}o= A Yg4=rOWyf % t[6j=5W&"lX ,A}Jf_\Ig ze*wm.t;vC ْ|;&$74@ZtzNj2˚,JҔ!#[:hTd"Y"QLDڵ%.i4<Iݓ}^S(Bw^Vo>rsMdG3窓eSDk |eI,EbH2–-مj"e'yX]C󰊅~$Vwԁa&#yvl03h"փ}H% z FX"2e+»>̈Mn=e( hǮ&E=n>Q-:V% eC ,G/3u*7"3*TwSbeL8~4ul a9P;=Hr^_X u~"J<]?d:'zAHkɁ[?|7?ӺgD&Z60* 7t™,&s;3Ai~_ZI5pjcsTW5fdF;0$hHzZg?@/<yj cZgUGN?"-ю4ݚ%o92mau~O 0OzhCzzٸsO X7tB+7a!{MD"c <6Tn T?ws=P jqT:t<\L$j 13X_uv*טSosvDRbZXO$YtCMATf^.NQR2hg_ yS}E;O #PQ8]e@.B4pDy?n:`PnLy@ƤEX8R-P,=Dgݒu>W :t"%hfgoHNP  &P.q(@G '%-_=1V!yأCB ˄}̽[cÜR+Md`#:'/bXҢFnZoWGjH9vҘnBС!ezU2<>Ҽ;;,DҝpgoӎKGTwD޺ÏS~ưqPly/Fnu2wُiY;#5ex p9e$Y{;F>NrZdt7̠͟:viR]琵79" x;: %r! Dn8af\btqFBI4:jE,NM[]޹YoN]^Ȣ"{jNC$F0ZosElÁMC w\4qɗ R ~'e ߒ](9<⚇K]tSugOگ5ZkBS"-= Z-NKÚE) dHK C3B;UmF4_X7AP)`W湔ACd- *Ъ]i-$%0BЂlVэ{/s5yߢFReKuuv-e1*2GbwJ+zLt[5vG1j; A $}ߧ2B.&ԣ>X4ŕ z#YrDm/GA1|B@ޟ9٦ #;nnh낁zΑuFDRiO$V͊(B]ٓ؁-ˢ YA}&n8 hsHź/xź,֨ uH +G;:#S&c`*`3Nc_Ӭ䈬+C25FKӡ$Z_ΐm/^iPo /`Z"iD11tĥ3~+ e"T(`E:ɻQ`6,$w x{)J%/rב^D+,r0\N^'INg'oP̥Ӊ9NӑYL7FH\R}㛚f_SCƋlb6'+kd9=Ji= Znԝex;i1v>l ulH&)붌 r3WJ-ev]+c1 HQ8ɉ,ͺ0+7H'VYUZM&x9;1{=eѧRe* -=0U[.!\i ,0̈F?%Ot;˘(R5 \g4j{Q_*uf]Rb_-7?/zM5GyMM|t,%eA`\#*i-*] |J">@/d!fL.)ur^m.ڲ{N,ɟ|ѳo gj$Ptq ~=|5ipj,Lwy{`M?\܉MMa!}2E(OZ u|1?m|$UEl_ կfeb%Ԙr=iDzE`y9hEk 1& i/!=IhLƺJ ;CDwSOv,>ѕsȪP:bGi(:8Kёv?oHE:Cu/]{[PBn6v|g[ޚx6B$S.I#9^]|/"=Qk݌ֱ ] fL"XR?IG#q1'8w;[W1n%qN'J nB4Q3:.~P\f˰dbMґ#T𘄘E/*ʀQ=P;Xy֟Yl Î{`zhSzOS(_=ft($Tͼ`RYb]ڍPj*0j׃̧ůi`s@ѫ(+ui/FR9z$O1̞<%pFJ.͈#>OӹDՄicWFv?o}+y|!qG$GEvdҭa$Q?A;n E`wz5>l@9/.pKP1Y nPBӥy Mnr&Do&>M%ήQHȘ2L"?_\<6 GߕMדDé=c(CeB_ p5HcnR/F|[x`m4QV篩(7R{#j쀧~a6*ztU=”;kDɰ Rㅾ30OcP{s}1BzNU,Z(յDz[}c s>Út!1z3ʓ̮yu{GHޟma H_(;o?k~U#a̗!|#t퐑){/>}ίWRp7n< 7-Ni{t}4h:bW|AMhpr^^q:imC G63@D%[0i͛ aE>LFB/@{45ksHG ЦS̀q-[Czl+]OQSFckGDۍ~#eM4`B,,sڶ!yOuo=O(;Os{(ׄ+ViSDMQl1hm_G`E5ae{hN⩎.VrcX/eKI#*TN1O/tRnHF,YnN_g6JJg*W8)7H>3j.p<*lٞiE303ܱV.UdCœ [k vnJ>M5(K$;9QLvF vkL"QyИ~5Zl՘(-Rv݋ʇv-1;BN+r/яSM?d̲l?AY$NV#?,T .t.iCQ#;xz<>ta9,өG-s8~`~~Fs4i&~Emف-?Eo:T0 F(L3I~+QE,<8%Ib)+FXe"2蹣rk?@HD:l& OP CU2}~{n`Je lM #kChlϕBd~b~A ܑC]ԽGj_:9]f 1 :1>FYdhg,,La%@_v@U_NϞ!9qFsikj+ 6kU5vS#ylJaxt;0u(ZʷI9bn.OYa֑I/2Bqjw}z!,z 5Ay@}^ln_buE{ 7m&p_6Ewhnm|*/UAlU.ųW) Re1hٿ Vǵ;k4rDt7:[c@~"䂅ׄ,4o "Y3#( 03<"E}w #\R*}GStЖjȠqia-;w5ϔ{S-yڛĀl/2mF-CP?фp]Ϸht>ONPadp u1g dŚlJgcߴpڨ{Py4di{h@y-zh*R#Fn2a7{P2A[~bmٓ46lMK~%+NDش+edK3P7YZ%DjQY`.&(]r?v(e:81jd{2Fr=?--WE#頻93`x͢AL$7HC*IP&CpLӢw֬ y#tGlV{? }8tw{d*ҷ1IPPtc)z3<{bSÜ#[+:/P#It`dhb1ۑ)4d7lZM:tkyEϨK2]AsL\3Iu|D:O҉Δy,7o[Skk˩NU]P_D/|֝1T{yxa|Jr:L%)7W eb %)^) Əq?@h[4h˞3"Cc~VȬO?aH|ɷ m/|5΃\]wkw?*@H*5ɺl!]p8ARh2d!~I+om}4*A/&.vq>;ə LY Kug=~RE 縔8QYIE}5};ed_VIѻv@'D͠J>.yNlڸ=21 Λ*`*zj~+a[3&,D霛YWJt@-f뽈̟FfJb[7unLt(S=d *fyy٣Wp+>#4&g@YPStH#Tq.#!* &yy*YsU]i!{D!9r!Ygp.24'8IhCþI+2}tf>G{Z=];,iB$F͒nkJ"4y%f"~x-r)ʱAr/hy<6af3Rpf  jcϳKC ޣ%;&ְkU߯=E!RM˒^z0{ey`FǙtsK[_E9)[6cgCyTy؋hGm3< بC *zا7(0g]nrvܻq lhd}E|nj}*^O5䞌C ËZCO 3:aXuq)x_8١@ؘPЋ>Z2 lC.ۭu[ PlI0yt^_j}١lޡvgNn=d]<ӫ oqH,\fE1G~"DAƐbӆ-J$) PXkkmntmiRmѤ|ԯ%.˞5oWT*UH赔K~1dvu&h֌1;w=dt{)b[QKذiror1KEdlN9? yW ZNzJtQM|o@:}ǪI.mXɿ!,!]#]8!)$kو7X؏F;t6̍ڳ7֝ *' :Mc4,yIg ~"MEcXGs!S1I6Ru'Vi:^1ktDT= |D;}JA/zt;Ű [ ۦڈ?vb>i6'bAcbw4s`>1 A84BnG$'h X~ENc /Y}}B`2D|»`#p#n ofĩd7+1\!4C3J$rgXaG Dn2rYǵJw?$t3&46OR_;EucퟶfEZ@rjHBڎ1($XP1 ʦ>Bc 4 eݽe&hV۳1nHH%)l,)C:VE9UžZ2j+DA8"s#LD9E8ߒ,gzҩa Q<5COHp=S?G%.D0l9(uP?ѣ_gGx@% _hz<H&d`]~? 6dCu^¨u`C4fϦFKoǺ6ݑKZPDȥ@)sMUv_U,J?B {i.x ^G; xxDm=WWSf-Cvx'3k%9YLx*\?) ?-3LYA #7g*JaesE ƐŧrP÷H8Gevt;T& S9 U zW3:&I\!uqE[]ZׅFt/=?(y?0g߱oPeeDtwkG(H^`,=Qjْe<˪Vg!3cHV+.GG/>hY=7J5~* ݄,춄$LTr t)(Ild"X[Πw9C{9?ZCGyrQRf} WNsyjmBI]v2{DqB[JuX=dzҽbO|%JwSds̖}I(o=E B=u@N&d'Nkv@]ѹȎPD>0Å"{yPYSaeIg9-䷩uAߠ>-E-׬},O&p'մч7ʱgv"j Ę5Q;;Ÿ5a g D2WI>3v;((E,(7| Z\e*B`Tg[C7/Ou2m3UJ Al }>ˈzsf~K_h(mҿEfl'gkfE6%j̻(]ƝYlmͳ挌#Z-Z"]T=ehhzhחӈ.sTy'#[Ʃ? S Vm^ܿjjLuBֳ rv^$g3K@k Ͻ:켿<l۲ s|~#3p|sVu˃ 'Pu4 D( =춁he\O(0B 8q? SAJc?3{SDeǶL!גw5ыt*-CKhqTlȂa1ZYV#GAhXwދɢιdĵ&N&}, ٣s;96<69AT:5V nUR5sIhÞc;O4{Z%B#JX[FU5:+Mߓi-r~$:8xef(͇}(ӭ1+ݬ\u9EiРw}`7Q/qU$ rVo3J:*UtAg{hEA-[x:St^st9%3@=ms랣$Z : }{ږ=YkDIj:'ǽ>K(EA|x56g{PC/\{faN#.70p{(<.K 4-fD?'8rskHٓ_"EJ}Y`U; |0Y)ա/ܘJ?gɛk?>B u*JП,ʡ! ȵJЎ&8j|>̀U](d% Yy)qrMO EB$A)4m'Kꨬ̷ wkPC}†[ ?𮢈gdFD]%Aĉ*ɕnꂩnE\jvW%3w< V*v+D⮌?#\HC0XKVJ_7eGy% PNz,:]eRqpEL+3& BhjI0`q Vx__MBZ8nӖU de]u(PeqXhgkuKχ `g ZAek6rf\ʶ$l)7j%z@Lmu3ӊ,YcmPzky*//ROBvaw/nl_mgZ)h9Tĭ*RIߧ*8CxݱLq9R۝9GZ7a^Y(fn )J7xdz%߸;pJhfߞ?;"=6k4 P)da\O=Mi =$ ˄Q <%oyeS,uo)^6@}s;a{dp;?ʧCWAeu)ٔ[ <1*i3OsbFPuwJtdKbf>OvI'LRdOZn?t$J*T'*,вFC% ~QrQMMiמy@T5'jNc,覗= &_AVW[!A(YLz)J~Zws%?B*~i%r 7. "<3+'ۀ~hF, 2!zID_!&;ÿJVd'(YwD,lBވ2n#c0Qm+Hx%<^HU{^QoY5N2Iv~:}&z~ݻDU|j }t _n('O,ޡ Jm.#Ys#ئ%*kAȖ^|yjفBDm9}_l!w z ,7l?AAni^o??7z=+gHL?:UbaNT[>͠zC.)mE臘ak}X?1?-Ln gwZNQL6ao߮:]' *Zvy$%كüJ j,yڪgGikW# y:=e'(Jļo~ip:; d9a1&8`QB1?g+y[=&H{.!ql8<էzf ^ibΟ 4V^M+Go30]=^ya/s4 $ϻo.&դ~ׁޣHd°hv(}?@O1|bJK$ =O| kܢo6:PfQH19ʹ *K.^&6`ߖJi$\U3¥iIG"Șt˶Q?OTpQ}oѳwG A %r^CKnf2u,7)L>.}I|X{=SK^E>K=m6ݒubT$;}9"ɀYT)#ŀ3-BF3W˷١nkmH+LY%]G$ lcj UZ8>[-W1fY:+Yi[zH!8*O˛̤9^$M)l+Y7޾ҿT Sz;\ æW]!uplSN :3tTcEHzwdp9tZF;&:vKOxPA°$BDKXm1i$>GdSEdE< ||~քu?{weM&lr13Yr dEr%yw.UYj v=벹M9wƶĿ?q IƼKB!ioݎ׿ gN_Wv 9KbCS\YgU"d9]JI|^G~e;`:2`9S`N0ۛ2(tjРN,U8(q[&dp.Q[\9V9Dw[w(L,!|A#L3DIk;@f^3{|&_*(Q(Cī١J<ь>P|!\/Vٴ.;2ry)/u? Ѻctx)t p: ^V?]E|շ)+@}w/բiUuo<[1'73Ty˽~ѩ蛮ʛN w*^n6?ìng?iW ⭄(R lG oCn@3r^-@ x"{3e1wloGbiɾcjكVl4t8?F+&jp=2wyL/Ӡ~0{ $ H6eTYY4Y5פ(AA7`)7$dݺmHNO1S7 +/=i $LHC0 ; l;# U*Q:'_݁l@Xt2$_M;%$d&v T*3T٠9J)18PDn xe:;Rՙy%eȖK%`D]9:ׂ.39v+q뷞7qog{'~֔8 &0fn=IS 3_?f{$ic odGOUH-K9|PQQ0Ɍ(gVW#ľ)2ha,NriQ~) wTe ^՝'u(M6~Z@>kQ8#,!RGͥQs2CÂ,Ui:2q.]mٮz{BP)Ω,lKʉw# | =dICg}!GWWeʣ}}WN7{dA<i^|a06uP a@B_(Z+v#{"~:`—Ir? 4X..$$(KMC;^40~'L >z 9`KXԨڄI%3(Lx`˘W? tQ*ٻOGGC:m]|_M"'vo|ܻQmWgװ_DQtMv^L/MZwB X'ʖ\K^P,D/IEfdgcER|ǎkliw6/iiwdA%K?O$ 3;W:˒ye h0z 1!g/S>:C:Md-f.4c)rpWP7$+dWb PGYR3kl<Wy,=` ]_oyOz%[4O eR\?̀yB}oߨMf==S{̋3bD|cૹXic=&/E!ԗTV5feYar_,$$mO Eo+^`Ivܺ_.#\eͩmzh)s@?$#_&c1pVgox(@d0d/91wCد.TU4!uׁEQ5&N_W10-PoQ^yp](xΏP_ٿ|3}9q,kXtx  Ǿp~QV'Oz&U DjXMaӉ^NWh1HE S2{ ]hTkux ~A@p*[̕D e^-l CL[39U GΨ:<=yf@YEgUΫR-#ȼ:X+2dw4jB 6oE>3&H'zŧ-1u]/5H2,ij tN!.9"-ڶ;Wogdw0Infl7,oMOƒ4LqFDlIvƎV3l!B[;W|~ݵgU=;crׇhBE=+1|Y?qCE§%9=>6-]ܯ,W4"&L;|[0aΆ9.\\t0y ,f- (&jUdX3 yM{0iڣ PQ.x̣_ ?[vt 1Y3z_M蝩MY5SQO[!hݒOF, ^4O^c6@V Gn]pȩ/Jr)+eىgy ' pMx<p*xnskv0Fǘ';ہS-l>vώ0⎈Fz.%EVڴ'{ܳu0d#t K7tuOˆ5ٓɞt>H)&fg6wa$j9JtC:ƊKlX';B䰗!I_MbziD N r)_^-ӹkCkƪ]،20eqGOu M@Rk<FQ ,+fD#J#%-Of!ݲH=_3o;'Wr'N>>Kߎml.fYz!1beN)_ol0RهHӰC%_rE.ka9yЈ>9 Bkֻ<|**FfM)ڗ_so;|kx4g;*ϺM`\6̩g>a"Myt]9} ˢSo B \t~T@;ߛP7\)~YVvt_*_W(o"fTvC a 2jriP:cȢK0iXhYa3cBe$"2ʱe,-e?'Y??G6Y%, w)ԉV|Xǃ˥"1>7`9DxC?a;Јj\\!} tJ/*ʍ0GKKq֏]|p^~:D#42MqHI6b7]vzIupþ^_me[Xwy_y-20PH9axd\-5@·Va :6Тq5FգWW7 Wm e*,ڎh[FW[Kq|gBe+^/+d-^Wvt# 2mu8>=Fv,Iu PM>Qwg$ D?jrXcӲ0뷙:˗g`9^߈'6$U$74/I"=u4?DӲfWzQԹC`խ ,Y;wq -@opck}W%IE銾uWXW4/"K&9~'-qZĢWEMZ4*G=::{7zwED2@r;cNDSA/j~"[hfAXZ5"o3mMGRe컁\۠\+N4 5ߍ"n\[Yϊޒ&} >l,גeΕsz7B,Q@gFiP67tαFyD,\Dl+yaҝ]T+AB/3٤k'x MC_$8=AGHlUz4|V8Ryln(9wlnJǭChA@HV,_l[lw qQ1E.:)Vy> / ]9N2ΌyiLLI%\"_,Z U2UqYlGID9P*0~'Flk[\Cި% /Dnk\WY`N@޻<_w͋8@X`D M;9Y̚aC唭KV)d8ikU·;b.%f3ebbwUEf1n;-P%GD.hx GVO|<94rFЧMkV c3<>YO^#NxS@j:e7‹vt!UX;]mt0DC&5 -C4{܃1!rLm'D~BVZEfԯ?3$=IԐ`ja tZΒ,e1ږ P#0j&%2U5_0L˾M0GlƻQZ ٛBB4 sI_]`TcF dӣsHoq]ʯ嚛j^N{[ʹ^PYVnݤw;N3mST[G[hpV [NF }Vi)Mk;ЛU68lmkVՄ+Ē}٪ t]vJVv_kľXW*ȴE26ƻ-&!$nGmkfaёDoa1rl!1pJӹ?8ځJI0 mkm):;Q6LŇbP@Il‰>@0YeDHwnCb!ڸSz~$L=y(,YK3sUl+&هU }Ilqo1z G)N2%OYiw+xGO! iOh(::Ƽ٧E[|\A ~LBGks͌LdK^$.#&1 ׼@F=ѐ0iHok|q턵ŶAtTO\jM]DϤ307h'; %c6<яk]VY5S=xJNͺ0: 1$;H5G&q!KbCO:^4+G[߲}ʼGWVe02R?2pa˭5սYxwہo)G,Ъ*;:?:8n lD>__DA2ѩ6;?F1aTDL6#oh" ;]kj]c7}г 1SsG.d2iC r%&謝(|G %зݙKV{m r;ƕgM61^p8n,7Pf:'r<\.EKVJM˄*Ο ZbC*Yzbxy 8 }Y6JG+rHL/ݶ.G4?I$3_+!dꉆ-a^ yBhҬ3lV'8@b;z i^pQ~s9"煞̨A0& \ bi=!xH?ϣQL-@@ߴnAG+f,>W{}S ,fp ."hm.J>I

4W,,I笓^'P8Ьmit +\r9]?Rja c$O 6hM<%zD*W8safNYM߶IDDR4E 3r>ϵ||$|R5*ܯ&E8$HP}~.m ͋P$hy.e<όT Y_!|Ip`X0C*'mXGY&zVˏx}joHn ZjYp~2 FŹqAZ|!!ùVZf 2tGȞdZ'd ;=_Ll"fIE8Xux)6C=m=ݩwSdzv͠9ݟ؀9Ѐ]s?!’b#>:3\dN/by-ʿuh=O0줯"&wwѰޘ5,3@9xhh]$(uB gJX Yg^uV#Pt݁f)StHH=Q%fz or6#̹:rV0,<_8>fXj8/t k7k4xiaȜ^I?t9 8߹1{E$ry2y)؞J/Z[$H񂨡<$M36#RC .%Ak^C/S$O jոAu|Y|d[5Y9ͰBݗFFLW[s88"p7ClIesdX yxe<-$#z~Y 8&u];ȬEZ' \ŏ$v9T)ꁀ/3N4nA?Lv۬K:wn]3i3ӈxzS[D>QV7×'oO;WpXJz\U;/ r&5xu͸7kg%( ·Q-5\\gܓ@3z`mcom3<=Zz& wh0Qjw49J!rY̆8x6bu&1}W~pTYHF3#=8k9%ֲ)ޏ*wc>vxqޘv1 #S-kHIY'"i99F{qDdÄqDB,ؒ Hhx돴]_;?Vd a6=?D"jנP.z&ae)\aA֎J4ՐʏNUgsxS}z=d^whji5bg´ߦw06e.h {(6 C̉~ Px,;RR$'ȟbm1S+ʬF 7>&T<5 ʐ7ކa“Ч$`5Ys/lpy$M͜mnT>Y)Y$līBIm8ciفIUc¼XKȡ]dA9玛g#)k2͉)Q~u/L}lu/4/ˊ$&~q,z=%[Λ# CRM;K| `MBzMGʒ ׍-qMՃ#WVpJmѭ `6vRʭ6H|˾;$byC <8_@ۛ8gXg#]5.6/8%9?9WņmI럒vh/%F14 o>KrZ^AR;=2z-miv[iKy8Lu@GbInSW Lzj$ʉ$A\mM|PGej%o2`9_)XzMvNRP'|w`.! X><,x>Ce/i9Ц@>/+ {)|]ĨR~M+t {ȹf;;V8a/[T Sϖ#;4HB%b:ԴL͌i8Al` >T"VeďQm!"0S^,H|ONU 7Lى!8?8 xhY=&zvZՊG!/މ$u`B]&+QC=Rѐ7)J) x4h0@Y{6xWf &nȔ:H6/I*BiO"XԬIdn"bAivŹZI} +>Bn` d_E[+Uey^8'w\ YSt )Y--a,fm0*Ҭ#Aڲ!qG\֋tݱ }XKcΧ2`qL㍇/f8S$L$)ŗ *Ty4Bi J)s?HB7^tj68 A3ΙBݔ7 *yrJbq* *a M% .'$p#~z3`>?aژ B%@aB>"⬖\ uҋCis?4]vexA+PXY2L_&TP}}7r8L(Ety3#\E8$%RCZe`l Q:/[D$̎GmDʇ zű빻. Ⱥӧo;]a^B&4 K&(xCGwdM\ErvioTۻ!J+;XUvG.M`agO:Np Kf_^zMǪbꈹ# a%q )ogR m2{'U,.NEv=pkADv_ \=3zƝ&?!%(&c. q=J(vbτEe81M8ׂ`YoE#AaV !=${=|c9XH(=!%2&KAe)Khq6.=$+ůEa줅leILX9n'm~ 8@_4R9<->Ut=$Xπpx=]@ʺ'q1Ip#c W* I >B~/c΍"vOU? YДaUXfYw !?܍Mf6^%PӢrHHi\.U`k0 `Z@5O<ۄicM/ɐv` TҤ)N0 trLۡz7ċL^}wgyO䑰~&H<rmoNd?P'ɇDpb.AHy|!܌v9R ]'X(s~* ͳ Ϩ2~gvH:z PF=vo֦-O <쐷9^K=K,1P4I쥐lB~$԰[K $ITXMBi\.eNٛ(FPv7!Ř!{7#(աG O/_nL0+sd-s~N,cϰHoo XsYNs-RܴHTIhG)mks>rG xjv'&Oӯ 9oFrئJ!ۣ3 -; BK&og(F{w\[o߯!'#Tf[o(>p 5[d9sl[wa~ɴ$a*y1$e*Ru` (vtdƖkS= ī'jrjj\h֮' Ʀd [jוRq=JxM{Y:7/B=(v]IJ +rNj֚񂤄w^ʷ{h5G,V~OIK@K;z'Nl|X~!?7:** #Z=l h][h&$6!Ḣ7kcU˼]*U!x!-YfOx.ɦ͑eftsj6 tr6lI3hADCkFAaC,&G%2qF+rWS_=-$G}NnNVMk͜mbO\Y7zr ȱ1;#GC5![Rs<$)8$4yG_&IIK #aD $ VJP$`OqU`b]2mS6@r Uܷ)*V|lMl,-Hh.&eẃ?cm}]KFEfj|ā _|%hC"U`)LݡW"wJ/@טIB +-ꗹcWCt+ʬ$St&Y6#SEVDĴl·P$MRLn2aQ]<5<U_oC[\H.M%xd>슙%4 9AbBQ#^3ː_v-5VE_u@1kL !hڎ!voA^ eZ5% 0k !gaH"$R/Έ b!%u(L{қI<\\VXOyA~Dƣ&O[>AmB JL:_G⩇_^;L&u使~̈R8Jqs)r P 6a[wNƖ l]*Gġwc#̰;&dU5*͝ݣ[ >Yy@DACǩenF&9,_hOoFG #lw7?Ja%$EMK#{+ @u,㡤Uv,R6+=az8<@d<.]dz}LPt2!ѴV~ϓwhi2Y#:aaI5oZTNBQ9 1d̲@,; c>eiy@[ T(|xܗ*XpM4Χ߂љ8·[4j!*tz=oϢBʌkm|H[ 1ZlRFsKZ/g֖DYf&eV졣{B-a 2KfB1ىkX$G)[uF*eߋ<Tk#HIl  up)C_ 5j#/LV$ά;/ʷ6o'@mVpmH =)?A T@#z!ba}ٜH8n|kc=NTjkw1u=TVlw cpi w*x]!:Ƣ.3G@jVxf Z"9MwNb0},En UZ˽E8O͐X`Zz?Q% @:@'ZF} ;@Xo!yK Sy)\yCcy(ՇC[;z6 l>4Ê?9}rSw 8 /4J w{viJNA*`%'ɤ>Ѽ-t_lu< _+^ǛTuwo\SV ɜyQ;i^%(q:YoYbo.1%xtM8z[_Vv72KmAx*⽁ ^/}ׅ&*A:/[aJOԤ~2ǻе+jT_SZLhd"R1l8)@rFcm2+ cA>]؅W됝&Ih(wp)2ǻ7v #E5*G 'r@>'TF|8cy$*R^/~3Bs.C5Fr4w.BOK8}°c@XY]XqdDXԱl#?1Gt,W{˪@Jhn8(-r||=XeV-PwՌ*ϳHP O8˥T%KJ;!DOHt/aQz\̴ha M#sgs̠?3z1&R,ؠR%b'2e%S$r_+׆zK"S8ɒ/Jʹ f.*qaB5GKv.ٍUEMVWȰV RYS\ml^ * rZjLoaz 2P c-|ϕOv-@pw:i*kO`<t'U_=b}+Wߧc;R%SFaNnud6IV[&V>sZcGx[am7eZ a4}QU/J*NlmQeĉ3&*|H\{Um_+\Za H(Asql}s=HH2˞fgS$)Bi{6zD?'Z ̹ut0_yόAVܺ8{l}qr{ Hrfe q2~n>fqܑSm5ҼQQ@蓻R[ :gcpG:(l51Ţ5Y;CNi&)EၶC~ .< pmY*EB[OPc~(V3 K;`$BUl=ɡ'k1,ړi՘Y>o64&KQ`<͛@{Fl"V! l$a8?!ncڗKp%^/[TUҞֹ.YXg[MW#Jʅ"&v/[c [{KzhaAs,Y9wtIe煙ᒔbKInp5"b ,|l0tzH;='xbtodyItb%9L;$.ݯMFTK%KC[!RK{ &Z̃,OmB:Pn~ Ѓy*>SށI%|O=+"~;}aRba8 {#Wy4&BxȗA̪g9ޑ21CX_ ōPf6ֳ9I27mm7d诐LN*{]}b}ı!-a1C5ںؘ2Ѕ Ma'ڋgo%2~=#ƶ#E{Q(h/g+aZ[$`&Ww-s+ֺz>`rޙnq;W*9g}@Q F>_v7ˋN ڜF~p||uWE  P-ƛ\_[Jp2@k惰aw ŜӉkx)WR,5LyE_ߙ^t,q/> 5A _7 'ZxEz%y_&v@$8pe#cUҡ#BYe>"k)'QͿr (c; )_$!V-#=e_IAbVwQ_5GXkv`^٢3 IAʎye\&Ff)V[[xFܘzQUYמ|{JӼw ĨLP5|pͨZsk.c-c{#cV`f:澛2ᚔy`qf\^vQǮe鰂b΢X뤬 S9˯SFع/bŵ虶5^jϐ5Cq+aKflG>o*Ype ܐ>}OPpU:<Ņ:׋ڲC#f-PP z|oƐ32b&Svm#U-Kb5o9z@CS^2\X݅䢂!M3z@GkX7V£N,\STJHOIKd" .dVq4^oTJC7Qc*q_Jb@7-DX<{xr2!ZWz;6{)(q7f}FnE>yw] iSWqX]=6B]D \2;g/p޳VElJq!XC[u:^@^FHf7}(䶃kUVF.57pN5jY(ʍ$`~mGyHjauϷ8*Y]#s,xgW&1`mD}0SBi^@aAZ;t h'N;'sGk*Dp6u[ηs#l8)6Bo,Qm9q7ɶGLCt*h\^!R,FJ: *-nwu*/_F38{)Z.}Jby$%PvXb @4!eXHH'h+&5hgoϛMI~CFld y55Q KSYG Ў]ZީRmޝSQ[+25p0jWG P7n# &Fa_]#XW>^si$wX%f;G`wF4h=NrC$%];ÿ|tf;E2̍::Q]0Wf 7CXT<Ym%E^284q; bsU{ s5 EL+c`:4W1:;^1ǰx wɤ(6L8yI>}` 1E̍U6n7Np}]:8_pr>F46Px^͛>rfQqyt 5C_ÂtΦ'j}#pj)qK/ 1N {6`V-_=!EB,bq*w=BkX+zn#e 7sC׿B4g*ͬ):PƢ:eg a'Գ7iz>EZv/vOT$ڴ &,4GT<`2QDZO48r-=pds!z6%![= r8 [ᰣyYpWïP:9^& 5'C^~4v=;]?' ($N6NlMuf!6OHTP]=5~_(3Jl<_l|-ggx r3,+ʠq"șD:˪Nt2Cσr!Sb^?0 ~ jqEJѺR^EBMU|;ouw5[[4Oqk |\I䞸`|H.7&Yk%hmiO™JCؾv)8`%r{Hk3|YJPJqcޱ*4fzB>Jy8"#=.81}. AG'Xȳ%ϲޛjr<ʉ ͣ)k\UwgV@V)Mʑc9![qxh#]z(z*`\n e~v}Ŗ꛿C1%ta!-o~ } 6J6Lt#ᠳ,"Ol"HŮ0y4C܋G}l,p! Aw`_1]R|{!rT^~Vi&ռGu#:?x jz$pSb2B j &!IHɫ08,Xefك+'+uZz\=_Hx6y @ Gˮ:ԴCOVXPH!s\J Coot!9ʇT+sNέdtmv`t͇u/鵅h(F? |O4,ut7NEqm6ephG?-@o?*8됵AuGfnU?P{BO֚6n5Z93촚7SjMGGd؁DgG,:+Jeڈ#~R̐lj64;͑7k, ?Y`YH\~AJT>"+m!&jyJ7' K IƎvGQ|@>ZH7DT~}Om| Ƿ :,oL)hBwDw"ͷydØi,? 3ymл@ïSbpu\.Q.e)fxՏ)Kugz/W}`9Iz0xd ׅ a'ti=P۟vy(=~+P䋱XM0OUw@ufG̻ú5eCB>ltf`n8E'ߖ JxZu1蠣MGz3>Fr&u3Y#FhP%Pd[3wLY0Α8uLQPg>|ƆScxI~b|Qin9c9#k1~㦲Vr ETMMp@Oxld"%X<$.(#;SȤU![phkjXP^K܅w#ܯ̊ {X40[.F8EW9>u>Xa#|FuD[3__kw|8z6F#aQ@ dm-? y)"gͮX,50.} g̣֕"YExe&TtO8A f/JZVDv5E:bϚEqsIZTygk S5Y?Ig7CvbՙEY\A柀yeQee%+m5JHndq;23i VήdOxEr6f\R\v{?3a#)\|ټq)eC 5%|Fus?ȉm3W#=.g[vψ )#QFTžq+ *%q : ≒`McIcd?뵔 mO#gig7gDӧ d;$_ 0D׶A[ m.X7yh "s<`R= s͡U8/ˬeͣO%s!,N}YvⱧx'ڕtSpţ Os: ھ)Y߻0Vzr_wi^ï\ǩM'/,*E Gp}/A3:i;B RWev3ENT+C_<&OE 9%^+MZ^|q[N/4jz3?{ֹ%r#AdRҔ]I/{[koՌ;^_([oTZ^<&Ujh[t Qyd!zr^ulvTGeʴV2"#A~Eue*bu{g3/.M]^?P ~A𾳤;t"'0jpUXK{w2{aG"C, It}G%q9hCY龩$İqx2@\L] r,=DbXN?#: 5М ˒kwu}sn$gX"?JDwRA_E1@Av8c\oMZ8΍yύ4~?Y1otN(kU>XLo'c|b4!td-SanQSۉ-*v%R" 3JU4]:pfuc_)X>n,?uY8d_bپ{t]eAE^T@RIr;((n?&n ̠un\^MLHD"uO<$~w#=`3o@缕~N;`ҙB|xT0 #@7&s / x=;jnmS +e= QTFfϢS 򱿨k`'lE;0#xU3!*X:fX?5 o3,VSHDzBzMt=)rt؉!`M\RB9ȋ>q3H = k}tnUO8޲$rN {9[߼}ύM>/ts4>2 P0k9딐ԥ9=qEP yڣˎ쬫HX3`f.&fP mu&{}-D~Wt;Y<{sf1}Ygz#Y::Tr"r * &KaU[o_@Ɓ݀MS+HΦikS@7?pY'i'W hF?DYm!z+V(3Pf esfe\EVB?n|8Dv֘P刎Bh(>+=uS`ؼ8/s׃ H_l<`fݮ~ uP-+ȄLmedU1`tcRdm9MR V#Gd#̋0wѬ+U `Th R8fB֊D%5G_|CDL=>) zΝ"g㹶v!Pf$5a wCKS7_~a}S_K{c'nx\RdIA~ƣ:WKW/t -.n>(2h]O+q287@V-@Wcc/ךlRi`:O஝;򑿽Y x{^ؔKY6MY{tL ;(Xu>{H`/uiΉ_3NFb++Y:῵%hZ,4ae]NNa}s#Fs\DPE!9m^e -zM`QJG4PNsS|k#jf`GBAxL+$uU2L .yXS bl~mMKB"kP E :X[VX@ &I?K*3I)K=T? h5=Zw^k^FH f8qI^7?kWޜ]Z9A-Y@[6O,YlM<9o?8Zk+)zhҁ-"8x`I\aF>3RP Z>tm1v:h%7jp'/΢>fw7b]lXfVϏC;7c(n G$^3ەAfŇ!2x#{ŤF#Qtδo]Kª3QV#m@/uV׃BR@ԏI.|k(Pϱu#}ej:ү֊>piE@M'JU&,3^+A%wÃoSĩ PuAXpElb-HCE]MܐWߗ,mj]])p~+R<#:n*UX吵B[4aX]%d2ML GT5}t^rL=(y1&ȉl~@$ نe<6oa8XvwD?jeeua3"uH. q|H"qtL 2L 4J;Jg=yޓ^P 0#zfJRI.T}7uF{ wꔇ(*D&igc]ivfI1XlfjL?fZS]x1U\3 qG8;r*h7s$ t0Xj6w7PfJ {" >⏏ 27Yu{FkUP~U+6|H=ME }ϳ zf:ikSwPlY{TK莊lkvfBrv9B}^nfvUW+L\yuڮuy{@#=!4}3Tex lSRz2oũtY ̜ʘk쎹x+20X*zȋgyȹ# ?1 W_b^O>aVpM)*=_QfzEIu`ErV y'ؔ/EE/ranik35FѪY$Gwe,myv&MG}9訓8r"yoz$t1NEH^,sKB@ 0Ƶr0[Zuyؙ>0h"ӎx),G"*@^fDJCž= wT8_WA6Gř4II։=UHh:z ()2,S|Uj1I"S+@_w/ug;9^|)^بsG'i>99snLy}`^Qr!Ujr@ FEjcB)pq`7uŒ[oKo)GSU_Mu4+r}nhSJN%xA995=[+Um@aEoDN $;>+rFr$p QEI ;#|H @zc% ѴΕl7]j8;TJ| @i ww v;ju5;t+jwpMyV By U[*; SH5}M 590vU&PɻwYvՆr灂.RIUq}T,i_1^@qX[UeN@7DmV 0>6}f-lʑ^ؔߺ;Jg-6W-YOPXԃX>Ҥ)V=J]jYE&4g;GkL6rs$ouc$a .W]~Vu :+뛗\hD$MZqR,6(N;Mpsoh tF-o1+YBHP v)}?])kuO^=. 0H4@kC]bI0t4t(ܳ#.GCX[@I@Af&\, Q w8Yוb(':;zAJ;=r<)1#OV'~:4!.F߬W]#rxPosO[}d&{`@ Kb(Ɗ˘πfGvtбqz]f+I@*ܪ396b:rF'^*yhAOu1YѰM f#iTz9^y'n)mSq,R&b/ԡ]L |ƣsɬL f)|IfCuA7 ?g]i 4I [k ҭ8(Њv]8Tne ::X58zidN{d^I`)$Vi !D:eC~>i*OKesla$!ʛ%qU [58ɚ})fbsBnkh޼DN sq)H3';^*:+g.G S#у^fQ刱"j}:(B$ETLyQROȁRZTD k;Ĵv=|ƺ!g]FLW ޗulJx[mzGCĚd !Pc 8(.lQYQdv``}޴~$ fڸI9Iv-u@'<ЩizU(ףɴL`)_@(`+Fd>hDدNbi%,6o pXk[/(Ⱦ8 {r"cD/CBZ*^>O%qMQl*ofsJR)tB Kv]S,:(s밑RH\穰|]3KTYlPd\]q{RT\O*30vwUJBLH=4Jn8;ySyc#hHo9- p[PjrA;`h}Q/M"A4drvΩ4qJ닗'fxڀ{SW_WBK\)ȗ\45{WgVjG>nV̪Ic3(# Ey5|Ѓ%U[5ʏ-T,*gy'-&K3]5nRI)c嶮3 P/hd/QfqF&#6$Xm%q,")cz Z6/u wjF֞Cl d2Ry*_ST}VZ,NRӱ z& {KX1vj5w=*6%U`rF?c,BxRD^#Ke$ 7{Yl ("b^EJhJZ T/ndB5cXיP#-&fKHNg!EyV: 5Yu$AZ EW߰I.T' [Uv]1|GO `EBCC:S55EIB\b)KpK "t;Wdp3nA3vX)c)b<"0O$ &) ܂AS#K%Je"1k#[{&p,FHO;c{/S-4bw/|UtrJsj~ 208holHn $WxG :q9ãi7 " ېE[޷+vLǂRow/wCN|Wͩ H7'8/0\P0p`Ko|6/ĉ`IK`%gviֽs<wV4+}@85ćz&EJbdWUGr$62CQ9{H?Uv l h1X'4am9ikǮԔr0R뺍~Op{ȾٖN|}Ŗba?Ptfy,FXw{b^II-KŞ笕RSw' ۟YƥX'*e < Y  5=f\QI:-?ns1=7 2r& )vma# *3K:^qc& 3;H )S58yWZ.Qqs@X j"hWt"_X߻[O'IgQ7PHaM)%iSu ibT)Y)Yrʾ8ߌ KE" 55{j8BaP?b>QM"+FB[aӺ.Gi>|I~uuux%>wjs#:pm~xm0 Ǧw,d(ʑa hi _wmJA~񊒮w*4lͲӖ2,7T#Жcȶft+hlS6$?W^}njde%y].cC_&disA}/ɟxUI!Ư-^m.D͹ﵴ/ rxN z 9˔Hh>_z+LZ[N%ipV43">u\4Q2;"qu<%0, Y%nqz \"<%Vfq]`UaFNĢiQ5;sR"48YD؜ylwo |],ki0 PVz>9r> b*gk[=oqdߋ*D֪/i' `\bqҘcQs)y欧Ņ~/`AdlDb#/Ԋt݊b/ób+W@uA+70"P#@%Pj:MO(w |}"MX\ ȩOYNd)ޘXN@CiCz (!I~oLRnp*]2Ho.ݧ9毛 C+aPr5~nsm[\KQd+~i ߆ *׭GE]u5&QJEkOw č.fΌ-#b hD?Gxг'62)%n-X'Hk' Xc+F78~ˬu'NIJ]e֕JL]Of7mzz5iE-ڦJ`H-l,AI>)vRv‹}&֒%s˟I +Fp4mqcp/!qQhh߽qguۀb$"AISjy0TۣAjfd7o~a:$U˲V嶗H-­y'sLF.^PLDz8p!H Sn"%KGcÇ >HC[ŭs8'4~QytHaoy/V-j:qb>{PJ$GӣGAb4oI&CP,<ܷakH C6R,~ \bI=F[\Q7vf_BaZ^ h̹219QMuajHr>)o^ qrV#")JdUVp꣧SAxdd4ŕ@VS|J8ѵq.uk>~@{'܉hJ+sqM1MUvf6B8A]T2#gSŔ#׋_͎X9<\?%hUngmeIO`yxgcOV)[_RA9n_?*Xmj扳LɒGyQԩY sDvʦ/p(<@zWR/xjlΌ3/$*ӕ$蛇BvбB|kQ~ a]OI5ߠu<%5K\WyyF= \ySuuJ[Kz*J~Uj"泿9ҕj.DuL+=)F2em@4zo:o̭RT$B[h0ϛ1g'^sZB4{{p8Cl&s5\u :e&Ǜ@JJBt|Loˬh}]߽檊q/ky ja!@E?Ԉ#]eIgxlUSeVg HDVn=ؽ~Vsg lnAi$^i~_$t2mD;v#p}l7o 38ABtC?0OTaT1f7_/έ;j2h=˘~ >wN=YGU@29 jp|t!'̸c!FZM'Mre]%~'XtP_3wzR`hi_栛EY$!]L!mF}9&3mo*n\۳SiֵR1{"ٛe=^cқ4P9`B^ (|a/\A+ʬO4%\26UTa&5)GU<1)]k.3HQ"$,X]RI3z rTw')M{فޟ^m¦#*uyuXqKc*1Ġ&fj2XRz)\^ԕGܴ8ؔ '"w@@3@xW uuz=WÆkWq,'csvk&rx e&'[@P@|n>+&^o 8ȑGt+} dL/ i𱹫 9](xbrW}>G;[% bB2˯=|>u%gd<5ی0w[dqi7 :Mmz\t8Qz0@- Sh*t CKߞ/W^Gv}BŜ N2V3<<1wg'u @:WU7tuJX/N %g7N kY 苿"4> sڄ̨'x kNb͈0a-<3YPVXxʴC>Ʊ6Ie*YR%u,\fUCTB-9 |`nޅ,'d5Ig $I?~&`UI"%g[A f'9WY,WvSpoЬ ̓DA(H/r@>T`m0ߠ mk;ʸ&!ܹaԽKZ`#*sc|qab[h.nTM\HVaԣ s~:Y0]"윃nc.6V0 dwsD knL)憳]>x0ϹK&_O _8"A*Qw1W*cĺ鿅?o/(NNǦHj],*=rĠ+R)ॳbkit3ay1RsD%}w]bv󷳉 gӱ^A*rݡk"VxBOͺۍ ;$ß_Gju&!"G8zX} RI-:XΑLTEiOtǹ\ύ_RJQ y\RQ+Ow8] eCδ%|ٵvsFs,%f6Q(5i>L=/d]LesL] q=S 1)Y$pxX n"X4͒x+yd&d,PgrE>$X4;鸕YΓC z ӧ:U(89(!9q%  }ouّNqW;qxk/(w#笎.| Mv'BeޜH͊9A;AO}3tŝtK֛3/M13=K=9dz߱@A n\eWtm? t:oHzcB* B2.f9#q w^,Y_kS$9{DihdKYA$="}G@,,{o!L}BÝɬM\-TX OHWEE,b*> E:by2b>g~"ˠNF#_Y%b ʏ [)m;Vm[yOWӗ!̮VZ3 'EAd,T9DIjQ]}Y9ivFO$T>V 5E9&=c~1 u\K;!^X$ 30d]YM 4=цӜy֓#(' z&kSeS> ˺ԣLVDgL!EhzScCbzzrg]Q&:8}Z#ғXgӸE |)m^(7YOm^d[+"TP~°xoJ)eʍb͐,e`LU %40naёr<)7er5՘kNXT/<\tPq6 Yk +ZI$Md3{f 阗C^ uF;Lj!T1= +ۂ,޿Q=[se֒nHN)'t'r)i$! Imu;{@cN =kv+}9gs%2+Ld{hS*EZ*q`xGi'& 8K)E7!w"z+[*iJ;q*$a /fk)28j 6s6(]'R$,At,FLv W_g<ք v1hvAt97*x"NevXλh=;"<0跴s(OrzXZTufh^@=M`Έ?n"?8z~z9is/kU/z/PJeB굠{Qf]Y>N&Jd1ϸTxgiakО#P<}% AȀV] x-$I^l8<'6 d@?BzbviKEFAO` SPVUJX$ג@+A5 K b *4ЙŪ3: PBr@Om.4"Q/[bGxl%a'X/©۠!Q/ހ!O+Xl!eCelp[81]:+`*#V^J3$ڪEhC/'זi}"ǃ|9ەXE@S+]?,v Z-^y}3qAmTzz6vk[Ϩyr-auG1.V>JD%~[LⳞJ:%-$NKHKPr9i<;eUŗE|4c2@ַ%uRcSw87K17n_< @aߛs|NmY}XB }-- }vh639w˜^zh-) 맹`c-cԗ{rc:?(y"-s뀰b=Xtt7D] ' T0|$]OQ>ɣ)@9đs5 Y'8W*j(줟+إ/*R_l25%_ ZyҴ'Dd[pν:JR4Sk3cC*KM@6f\1ˆs^,ăH)KVOz|\5!2iһ+v/:s>3=41}ϵ^bv 6[cTB;p(i]74pSũ|u+S!L}]!8Q g4(KB:3Yszfw"٠_I\MAXdJsT lЭ4S)Yq,ӼyO:s#iӔ'S:~2'T))G~.…tޖHHo s8P}`"-i3[g4']%*8L?0o E"%591ToP,)HүBiy?!9 m4ĒG2ea"kii {:V` nֺx}jQLa!?Rzq<- ۄmU#مǨԬSb}qxYBNGϬ?>xCF  \\!lܐXfk̳ cEL8ϥH/؞0􁱓>06^f U)KѼxrkxq^H)wb =y}D%YRP"W O6lAʜ ke^M7}~8a(,Yy3FavpQuĥpoS -o ,?QA<`} fCcAY+Ya7D .xH/|qܱ$_Hot c;ΫIXj>߆%MU˛%끥iz'nc-ϋV cWOd =SCNoX7x%3LG憓N;h.N*ҟ޾&5sgr4r}Jydmص۠h B1A -.] A-r UpOG 1*. PElc0~0ٝØjv`4"g٬ƴN7\6Lk?z4]$#fFd& %>2Yхt,@[tFG NޣwX.BJ^BCVfl]kxCt#Px_[tO%_άW-_ȼ.IeN'feܺĝ*fn,X)JJO$yo\yF)F.ՁKIEa |ƷggJh$+Ez.z+k:%'a0 &癨u*ľ v1;X zUǥΥ|-^˓`c!񸓡Z{'PfvXw)vcPַ`+uʵ>PHt瘬].{&XG 3$?C(WT壼 3\C`1~0=2 f z(t ȁD̅ie\M 2Zg4/Rл4^̬3M2p}n2c ;b\4?:ũK.msä}_ 49P*B%ϬCqJH ꬾEWjtd`ttSMdJ|ȥܹ$6.R@7Žy ]Y?i.+uc. IPsOǞq.ފ>15AO % f[ru#IU%-$KeG$u]7u*{â0Nʸ[VsâzjH$e&;B0نke's;k!21B&,1I:1 P'!3|>  ~Qo{GϺBX,)HB \qlzwX+fXM>%ԞxxŮXFͤ}[=YMԛϰV"WO!|3xiƣƎxw@F7$X yUf^eqhڿ2뵃@^ko(lVjIWj8hEma aIWS[hvzjB60KRRI}9*DyC?q玛;8!rnOeb;ziLF2 c Im)k|-q*g"$ӞksX Bwӝ OPSgMG)Ţ<̼>=d{B)J2ĝa* )SN/F _"%#>{TJم?Y(HPtxt:@E'wg?IB4a@+8 'b9}9Ȗ[ZЍSg+n-wOfmF&ʼl@1$l~&?1hk+!@̓0=\{"^[vO6x(r æɶx0H>;:2|Ɲcu9Sxx=O4l!^YrG'tod.3y;CXFE$ fqAgr/'FlhXϤd)$*?_>id]i ʔĔM27ܺ{^q#'U@!@C+0R Y(l%<-?–bE9*:{ ksm{0;:'{:Uz#Cco졤$ }CsĉfmĒvJRFd[9d2^x؆VxnQD*ƈVB,Y ܭO4 >)Үxb-<¨Ol"=^8 E/B9֬W[ IcjxaBX6 % !Rv aBN/Ih?ǫ+:]<ϟĴ̝OU(Kyj\dc*ݝ؞/E_E*+KU~U É?NUkYo5}0 Z)F0'Ͽ7ޛf7]ުg>ϕ?Q|'%fLfcn) Χm9oxi p{8?S2휅xTqv/=tTUZ@ /kq+3<]r(1%A8FՎbM /$=~\:zpw3vIV#8{/_2]@EW·԰ kx,g[rQM}o7nPG[޹S(&жykdj %`,Cg rDߨGuv^Iz%ʻjD9x 5}XJ} gΖ.?QO w(b*x Q<7p(3;TU+MQ"L\{Y%8z# :{?_+s{>д 4ߘլ{ˎgd/*3=w>#t~^n?#Ȕ&%}H̀nȄ=ZX%9Am=h%v [@, JH K#wp3svJ so3:,NxU$ ޽2yޔcgCN펷ȿbpGLxlZ'y.2#;e 8Y47n,-tZ33wHe=}y8_r̩ʹFGo;2ێ|![VްjY#쑍Xl|bU#b'2.J$,E^ c'FLGr;WvV`I  zd[b+mĖu?G?\A2P,IMӁ /A*JHBNǪJ)&8N`n)^ /D[u977? +~#̼l=#='c}O+Q<*I& +bV]uh>wŕoŜh.Y`o]Wfn)SoKWZB)-#4fpO;uukO'҇#҇Y@r=O7OM(Z+#p @Y&h1e@?A{n"߄4Yݹ3H*fߐJDI}"!̥4\uoUdiW9Ab2rS,a|>sZD`9crKܞjz`T=tqJ9XIТ"ߛfۦR= `c0)1DmL"l;xޖ=ez:S mzmr0&QGX;yhCNYI?]Cepw}X5U6!,+z,o˪Oi"Lדx6z"DX%(tP|fY?8l@6T/'VYC7l16/gf̉Gwv{yUG1 ǝkHnANtVFtS[-7@rkέ`x'& V/UtqdZ ~I$QY,Yw_+$*ry瞲핢PHqDv%ΩzzOS˲.7v.VcHImv\s7Ƕqs\6&NjK gڍYzKv3eNKC9X͔$YSM9r#f1TI4Qgs^#-0<{DNTi Ŵ"9c`JNə_Kf(Q(힂ܕ Eya=A] 7dR3qȘO-T0c: |b}cK<>eVL)39{cOiv/aefBFjNأϕXutamd#R)RR@;0e a[`#Gu;)cld7L}kv_<>En7/j@}_n o-΍䦍#H׏$+is)^>lPk>Kif'ڔOdefy,%@ {vgP Ytu>Gnmoˑwi=f:/yn?2wo!y.|̺Pܼlٰ%N"c#դwRPà_q;|{1{'3B'BEufo9Y \$ԷsTr(6`D3 7ڈLؼ !yhҡ 8"d ,0TKG#& ߙh_\7C_-lSހհI cr;lbVd}s{D:č~#o|:°"X[y~] kAܖRС(g+x Ɛ~ fܙk;(UbrDBuhjwwHs'my49eRт OPG4sk~9FbĝKFo-tw-kйԠqWBbkdS/dӱM',]y Y:v|0V@A>B^gLXyGeUU;CT#d$OWptx>ͼv % R?Qsf buϻfUN~ϋ%eW 4PK/jr?Iחؽq>O\! YL>ڵcG^mkL"nWa͡?ʹtsr!ŭfR!'g@'}hc:q>ѵޞ Zu}Չ#1p9,gdX5RX5yC4ǖMzLI煏\v3#uy/n܄av Ԫf>t8G1yjkwgJJppBޓx`tgU֊D&n+RZ&jk4kur yo,O2ƃBXW!z SwJ3DF5Ķs>EvıXFZpǟdb0v2NT'sP1qyB x(Y5[WFPC!;7].jm>[/C-CRG+xpCbRk1gzy^}BHu`(LcP)%<'E^?qz:7@܎VʼnD8)ĖU9 m 皜IpUjᵧi,/n5󀱘|vn7EؽOHمѾ^5!T$Go6! k^Pֲ3A&.p߲zF$͐ȜX7( ʬ)kKS|.EqyJzϭTK)bv_{QEJ='ikU ('e\5ѻϹ[k s{AƯPnKUhHˑ^LYS$bR4Fӗƈ8Noiz.ຬex)5JzeLw]ϩY)X1TRge0@hGU;'V@=0jQn\ٔ%D^/fm7tgz\΍y CFkcx0:)ы]B]$j'.JSYguX&!bxvam;0 RCzmL$k '7+˼qea*GTS$Yf1q.vڜc@hq,\!9K~z}|AkVR֯RձjoTB'|Uf!$Ϳ 3YP(鵄YGHk+47X V]rVn=HmEdw/^ t ʎxR*Sذ8AV)^ɹχ}CVJekSX):R(MӝU\0Y bk}O}ȖO6hsIuO\ 'ި͜CoyFepG!ǴV 6<l~^ھkMZ-> 蝛dDu,}ic9, }wGahGVgϬE]"& q[= g0~ 3Zʯ09C5HO,Sn^V!l:K6wlԺTA:>sG1gq䍃gqګ9g v43oр¹KbĈ@?ttP{yU #x:A .T::v$:M=4Qwj.ˉU[n@{{ٸ8T;νQrhgg)T9߻N|x9H9v ~Ϗ)Jd8sʹ9A:Y)D]oϤ S}=4O5HvU?mi:"U: 6 `|6EhkzoEyЙ ZP;InV5UQz5q)lt3vU]GWZħ`)X. h4m cmIJw.7# -.|zь^u6{ Ù''jͽ*P&[ݦ(xEh~>Tg-F _S=K[ w#^뭗2F/L>Z߇؀pDBFkQ~pҔvpݱԊHtG`nX1;a%! Ա;c`q"8 ۭt8egr|(MJk-2N/k*-]? e$~Aal&佽xCfףS~?5.wU~#x>ϵ%O9  kz VoIdЖWfQ+_9 _txbx}k1OOׁC Eu|Ra۞r2d o+'X')'ckvágx(|F, yyu$pF4%B0Әltn4GCOXgio5Sag]9n @) zHٔWny3| mWBsG|׵$ksVE%sR^JwP3[LznG,|.^ZἠEt+fֽd²^>*;tImQ2ECK;)r{a!{c_FhZz9@kW>v F()Q 4 '76o锊!k Q5mD31B!ި2ZT*Rף}f33)9Ėʩb}FEChʹN-..ȱqD_OfT)h444Toٶ].I㟱qx3\$O6OjY][>{5{)eIU|naeʓ :Lh0klRͿFz8yH ͆c4KG 4zB*U4h6xE7~_Ou=gA'Ţ.ꆌ{(^:5TYQ { Xz~oDMK,5ƈd8ӧ8͈|w轐F%;֝^v`vСm;W,-*yM۽$$T3;+N7iSA{㪝*Ni& ՕT a G++ %v_t k ض{ND E *k`0#ie/S`6c5XĮpme(CD)ӆĉ-&% B骕Ve<#Bu@ K>!T|wѿo^~U ׯɫBj5fhLCzڧ4Eh~Wq2v!V H`pL7 KWLI5վ7ڃ|So1f>%&/+UflwdڳIB<&`-LP,=%ʐS(sQ$_`ǭ~__|iOz 0hgg%c7(A5' dH{sm˘IK޽-^PK3,]XoO+ITw^{2Fph̰/7 bxƊ"crp*͕{ւYX \ v Yg:?}hc9-g,ayϫHyF2hb~4lCb'T $ 2b`<ufwUż_"be,r N3',ÀS&.99 !*$#^Jzګ]R:L2zTűFT}L|VMb4(7Ҕ\**EU&]$2)pW(؅+bJ@aQ>kzٵ5#*$)1H3黦u7vԌLn5e̅(@m'Ǯc l#欏4e+G (Ve#gڵxC,Ҿto&'|kII0tf:NF9y:8?/ eR#YEN/x FlKR9kFx+T[k]ӱ<-9kcR2Q7>zpG-`ysh>'"C_ qA:jl~m"'O7^VXOZiRPf h0ssZdL&S)>! ИܰʏS(Aq,z]^^Omsac֕>:߈YXFŊ"`|-J{F ~>8˧ 5UTXYj^ >T.o5dprhi=ǣd> kфCN 5[wޕx̚2Xlx#,H]:6sU0!5晇)PP$2! ц1o!21-2r {x&bb]iJ$P(y$JAXuBeO軻=^LnYb81:`g"cFlKS9z:](KgeZo2߻)hיzn* dPkl4~wV[fj66WiO qa&|܈Y9%\=A9ȻL6L52rx^ysFF݂2 Ρ2v>L vt3E<@2UOq%5GKTf2eua|<㚓U+Irs ㄆ߀Yi wk&x]i'uyi(Jq3Қ}dc?,,PJX98psZҪyeC[rN6}XV.Aaϔn @ `sj3;Ҁ]gD>|B_Rx  Qt +?74%8Ȇ &t|'.`wwQ_قר$Z_K4CTLh=ڭ{Z9P]MI(%ޖ8e8!ճ4;Mcg9C:3IQ׮/*;"y\Pz(M86d_.ro둾 Fq4HS;';:9uh_.)bA9,ac %f ho}\ P7uCMlE$3\t^sT5:v-@/Nepufpg֬o^/j'9.UPU21$}# ْ?īV7zц{TmxTsYwt*'|z:iKtTz'Caj֗-Y.ԧIBG BV|dsiT˫-ඨ}+/`UdŐdNoˠD"GܓjCP;qVP{"p"i݊w;ݖ!X&/@O`zĨ] zGp_dKj=uba@V4 @-])B<@\r0l;TD]n7 hT̺N@=B8/O&6 AcL#Bfe&s߼>g6 ;ZK֣)}f~ /$}3'uh=M/񡬔 Fiߨoj#o~Sl&eKAOށ'o9iVy F`-I\܌>̔2pjkDywh[tjЭXRdM7و3Vz4Rd'-h𨁴v7 بt6hXM vҭ CkYT:)O}o%ڼgWShI5Gh$nF7#z#7Y$REDt# n(-p{TDgken?Z8R:`9㾔)(Y kD3#-9HAWFo1SbJS6`QI_\^f>`;f^ykU딀uGHߜPsS)tV@qy<2* +M^[W\^&stӔGjKJIR,E/%:aXbs"=`#,ַddEe,vkff. 9=էwTy!Y@yW[~>y!t&+}N9PKd愗}`-T20ttb4^Ŝ0yBVQx"Zfls>1E; YD|%ӦȏE>ϚЙvѹ!8|mgK|l\;iu&قe0#eZ$3{ arsu: }ø wJvɫh1p1ټ10mpfɤZԧ%^nE wۆ0,{yq`3ޞI/k,b?h>)0<rHW y ~+BV8q҆x`r~yGuRy: _66>N^}=y^GR!A$n.pmi(gW'ˈ#uQFu/, mn >[&D]'v9]g>Yz"֦0~9 F2/$xs1~̥J 7< ]fhx>CR_}@9Afwkхsr6 S=Ĉ߲`E^\` N< ]Xґ)l5d88q"8};s/Y߼ ײ~um=Z+v}.BM yz6 Vԉ.'5$ďI`zL-]*i13])BLj:;z $̲w7ԟȨYvpC>^ !0y>ϔveDR}8:Sx-=MsJ;c*z٬CiY?(d9mO^9>Q }>x#`6B``BhE AB9{A{8?أn:qpbhnhpBY'z &uq*3j])g@JNΑO:褁מ(apǼ"a-u{{avޟHf: [ꛝPVja{F-nXsuH@&u-J|#1FR\[vG#qB3qi-kWrƶxCgχ|%aAyÑN7 B#+e̗ba#Hw}z=eOWt˒zހƽ`7H5sx Ғ i tu1]trY'9FK \1·tɱ$ز{5'J[&q+A֨u7_(GӍ*cEjCŘc?imWkUW&'.i%ԜfxrEn+x%K8\XYww@wE_O>4f;*o ZQo~>uSVpbBYZ&u3Hl<6gRcl;BSըbpu>}Mo,AS`X(}MQfH+ܙ6c#\ @bx#mEMV kVyzۀ)ylK>:#8kN)!;[t&*g :\*o("ʿy`a66ldGM}(<{DMn%J/JQT鏀~s=ɐ\G_]b_7w"?J4u7icA~{m_*-M (~ufo<8xo7ӅkƓanMni!K{U%rIi3bǪdmV圻lV4nz{S^EIJZq FRD*g;p{#`vd˄)a V{D3 CoK@3&0ß=%E]7gJ@z*aY6{v%Q{-{sW"7㵬_<\Y3~񻱫K1xuetA Xg~;0:7j}_/{/RYV"\(NS<3yp2h/(uA.U/ώ,}C*}C&p^οb:ROe)\rŷDW)4tt;pIh2Yf?#xhX}2 QZ,9r (<-kH8"=H{/⦿hr8[uoyº$2h-Dr()(]鈨Zv,ii@R%Z,>P /9rya :8EKjxp󒩂@^tZhH@]@6YoWVXd'7rJ)Icy>Q.剂] jEnGRx!J5Fe2n`yf:͵aگӡp|EqXģܭ3=#Q롲}7%Bѓ~}HoX{Pآu:[w]7X%23鞻Yi:v&4oMz)Rmn/ . uTF$7:Gd(|* '3YVjJLʥ\WurbK"#C sUE hV)N}A1r'~Hش' >O4e kS`$gI*i|w7?Pvu\x04Sn{heC'QkE欮ՉJ/T@Vн-C:(s t˨,|j=ڢ 8@^K)ɹs?Dy y&+QWžv`Ay S>o{ ;EWE]'8#Ǯii⅙;qp )TiyK2 s u:%$rzԵ-`ޗQb(k`sB 4+z@QZ+b>ĈxsnA9ÀU"|-Q[@z U-m})e1**x#by&``,U$|L:D IBef?95H]CӅJ%& a 'r?5D:1y 9Tz֕Pd'Aܟ|O|*Ob >1Zs|\MF^' ix?'O oȔ3ˎ' @}z#$Wei4PUS 3EpyeOA?g0;ԘPV8u柇}-iB"> R

CRsޠ74Eod\c=V[nG>'RđU]bg (,2#q.ekAw^)*|BWj-8w_HSa'oU1ёM,ft ZcBC*Q/|e1LWM.oМ=\14Rvf u󊋓'+p&6x-fcIpؠRkld.$LJ'BuCtbmݽCacCFRʀiR^~6xM]q*[b՛0պ7>J3`'};|*qhyrjϝ"+{NH;C&%e%synx| Jł3kNxي~w, GP>%дCްS6u*ڔN9s?VJ 1"1 N W֯HpEPH0Bg}" a8\+^-yjH̬+ yt[hC6+C O/9:jT&;cmVG`L Hn" ?{7`wm7}g:|}ҙM;uEuiA<>>: 0o0)BȦ81kIz0Q(;{+81XW|T#i1ќ[ǐ =gɬml?Q9 }PC1ĊC /=O QYtI--.xg SEBm΂T JG mz&g@tY% 6調djWQiJ7bӥ 2SvO +xXq funN^5~|st偣p\tt#Lo;'&T$@VtD2Ifh.pڊN UMb~:>'֫3\حߗjʾ*9O@J|s2Qj[Ve˒4+JXhL* H(7Bpa`(̓cڑgz52t܄3zcz|r im!+ "pɷ6xϨ1>r262ޓS[~1h +.FӉN} ܛe]j#kCJ$wZ\0Y~ fw"u)% )(67M*kA tsJ9@"ưY8<޽3êRrݴGa*Ѭ;febX~jz=Cvp&̝\WK JLU6ACh4_h̵TكL:%梧`8mf]Rܛ_Sm\S~۝a7矞Bu>g-@oAgƏi+cfDE9FnEL'nz%lS5f .5 IZe- PAӅjLd`hT3)͡Iib}[jf'||˞4RmEq9iMvIN `g܆҆Dd"V{5M*Q'Z[> ogIwEv _)M%$Q[2&RFlfv{]|_) 2u/E5 gS5ggf 9/"QS̀끳Uiޒ<&olQRý6uǽHTGm/6cT]ϘP˜)=CX3cm LD:Df4FmiNl;+wV{ګGCˊ$Ζmۍst?piSGZxfiv?kd'#N]Y8-θlcd'FV$p­r7H,/hCr~ Ǔ%] gw Ȝo 0*acA X5 WRL,;Q`H1?8y9gP,>PZ8Tu؅ڙ)%Π֜~Ǫ)c\+|Jh 6RD8 T~Ѓyl7o`߾/Ok_]ف4aZa=rA.)f kA|vCs~f.1ÐP|ιJ?W4zgS|}Ɂ,+8d^K B#ƀwm$G+Qg:v7/XȞOOxj!La3KQ=lbN(HBUD=ζ97iw?9I9{_Áule}3_E l8h؇&M6)/2ԇBJ&K$=葦n\~4e6u /Ym;7?Ynn/xUIjw$Bb(|圭],qe%LY֔*z6gf38`F$pJ0i#81(! 3tQF]`ô OZ#m['y& LqRVlè5LuVy4[:׏F\>嬧uyFXcbu.{8vOt2d(kZGxWG PBLĀ2bϬHRYKR&<d:#a{bXHs:ԃ '^T&PV&Xr[N=h/cLGsoebktqtry+=vDygEg |K5/Yu~bhBBxMg_z_c5aUiӮg5,՝uy|T3LDmh>JN>Va;<8~+OZOʺ{Բ{hp>m5 VYKω&d6ekUHuox$ 7kgx6Ik9Qo-R#n/WMujT>tх|nrx.פjC+M?L(_OH^:9x3JYdOCP|B=L©aac&-Gh{B0C3)k aӁߋ+`t? ?ؾ IA)-&JGJ*ֶ&;鉮agĻQvVe&SYUO>7syx2騜0KԮpBb)5;{8s'B]5Lg$?yL~W=_kqB$}{&3͢Wk>?yQQFy{<7DO:"k*]KJpϷd=ޛ\E>j_1XnN{On +My伇\&ǔ 7bXh$fy}jYRu!^~]mHݒ fx:p$L ̥=xƜ5]]G9r+qhp#w22&3oLpܙPZ-^1^:*(Xy7#!Fwuk蓠m{lN-axMM]EzA5oW>_\qR}7zHܜ)>:BZba ߈} s swM]3ԲwވxElfoDzx4>7b6%V0$@k0?9 B%7ko7d}z֖ҭo>3Q=zb]rk \P kgklYZ554Ǎ^aGdGO1!|| 3kᓳf! >e% c}Q͑HjJtOx.z5b1X#`ysDq.cQdk0~g ;I[Y._[Go6oVJ::Ŗ!PΥ'DgowԘwa5>!ԑ Kq ޘ-a6ZXԻEPZAiBY2DP ZY=IYswSJY|临D[S&jڌ|K.ϯDsk;s0^0LJ: N,sDઞf IR;qa;dUxG p&]C^d^xK23_AisKk1:v+DzP|vB+h4d\~1|iGwxo%"n7=@QO|zJR~3z38.~=RWخ^9cuéPKL/m_1Y2 7.ŃZǫ?̫[~|/nx9萃g~8@IϏN :ՙ%$3E-g*[9Nq!|Qڻ|tlʶ3Bfۓ.͡kЇptO*n{6:6x1ƨ.B.D}c^FbvP!sq)H|2tJ}m-Q'W>4E@A x{@.WtK{!h1s{/藸B%ߑ048ίiV} Fq&\XX$.>Z6l':a"&=,›[jm w"s;_@4 rjVdNN@tHC `X!?Z !Ra5$"0F {d!_k'lF=2`ѺRX bkmSƞ+z~&ۼ|y,5nTrL2 &#l5Io\xEr;D閦jj5!>zlRT(@t޳NI<1Z ɛ娗:nX,{A*훞Zjq@s jϳsԗQg2 T '}kHhT{!xϒ&J@tp0usv|k19d ^ғ[WoTfi9?XVQs̏x 2ngJ!Ԋ֟ 33C6r~fwg4 wӴ8VPB \` G/^[pאHE>#@LP\rɚr1Ps"XO:9Nf_h6 U2m)Dr2%ED@^h"\dr0gw] pR(. 5XCB-4ht,H5 z|+E͏*7jQ3ƥR $,#qB~CC5𚴜f =k/g(iF~c :y\lrF(rQء0[9ȿt6e|p#eC#^콄dSIр]bqzStm$rp9K4qZ52f12+ddړ:l_z#0J!mGHB ΀_(RVW5LwfȪ5TTԫ:<+Y'2mu"L de|N#{1wEJ5Є0=eysK1Ga!->\(My 7{Zr2ܑN,/㴔ź7YQ6 ޸3Zg?a*v}9/ه~w6iA.#􃅇bQE.Kjt"zo+nʞ l$CX:=>MνYj|e>Ƌ Y+ <L%f3UB'gcܟ0+V1\~S$g 2x4,9J>B:aaeK`NqlKr/^lH#[\%{% ?E*lC|ϼ vj6&N6:Yh](&8oy ]]Z1|AJnVrorW:kl^Cdi @F wҩ[3+S\3cu/`Oie}{wwEqMk'+|NZ,rivRe:cU3/HW KoLwKI /{ ԨP({3)~PtV="_Cub=/z8%3)aSrv(ػJຍs[k h, 6?bEUL L!dWy9C=ύ=4(U~)@ AIAsiY\ZCVh&V QUMIhhc##v5N˙Py$&T EGNauZs~r6dE<' Ѳ6k\2#eW$ %էM+1 4 4d>:hD$Gj1gk*%ՠЖE pX?N8ugOtY9dpHki:zDJp< l1 8!w>T`43koS3e˿r`]񙭌7f!=eQh#hؘn٩A?H>d:-r.^9WЃl$k^Oa#Ha'49yޥ!\d~|xs=@OR*I+fۣx"nYNpYJ}}l +k=F%l,B҅p.kױ[gCf| JjDHHMз@JJ(!g舖CTJύ.jEOw\E8k?>e-90af/l9:_iQA4Yj|#H7ܲX2V}O'|s|mUq fWlŚ0}snU=~?;yӑ42i)ɧ^ռjAyHuXi&~ژٓ< ?;qcp{W߳ә 553;9G+ |vH 9aP1U%r9&CvÄ RH1{xF(D=0V9y$%t AMYO?[MdZ&wu1Sͳ t5EJ}:d[J!GARB7-4 ꟧DNbYcvXZJ X)(ϻ8֕>Hi?xJ(69 PlgّAO 0s3lK$?9{{RJ^l:r0Gy8:zDWB֬XR?7T5+4Bғ&OK /vϓtvJu}ȘBFGۻ+o$UQggW5u~ #@>eG=*.Jً}m{d#/}2 _;o4\⌡b! PimSbo΀"LmK*K Ud X@D=};;@2PV.R2r'W˷&=P>ޡ|#~`}#Z;-QiUΰ-.+Y-\-w=[pm7eQ(U2bN:x mp2%;+)zV(wXIq~ T0sgEńOHَ\hJ;=i#Ȩ3E Ø-q\Y[c5[~GXTQSe=Qs1?DӋIwhc.+gZ_0{r5ݼ&cZwx>vgS`mq;4Du?BQ}  YyA FLTaV&z!A2z3^hzn'sMB1l Cu29%鑵/p&KIYjY'QcT(gm3:Ew3TQ٧VȠ+S6AFSK3`lPOXS]l ^ԠwYt^s P:!|܇V21ftt=xGD&J1;|;VHks+M'mconfO8N/e:yDѢʒgK=Cqeޚ䄎mX(T*uhǬFYC5c1OqVbݘ\b X)xI(Id3ؚ*e3Cnw={+% #%$@C8*: ?߇(Ei1j= * bm"'C*֐u䢡t@a |!n%+*v6'b oBodx)ö#aElBz(A+~ɼ6NeP?Q^ %WZ*Ԍ;ZnMKfG>;wqGf|aܼৄD^}I?a'FW,tYá~=^cMeIP_NN@_r@ > _֩BUY'VMs ͢h:KS:@gcs!svNy̌܍kV|a] tιZe[9Sj`i7$]S:|yJ]I+<=+ `FSގtDx/}W}t9/Z9.M,iԅu;A{bе*?+?樎(14FۡKbaRNvL0%Ӫ0/>)N5x(:|G`U@L]0{Uo%O^{?g"t7z e{By=F$Qc*($h  e&ӱOyb^< f+b*GŠw%Zf%x㙶/km!OA,C̄M%D=A!`QNa< RN9%gibrK5X8}bP Tth $`l7)g٤RR @$Ϲ14ĒOh;c &c}t&y4ɩ1Tw Pp𪷆8㸳д*gފGgm:'T@ff4)h-|^Ѷ¼KAÄU7] GDqƕ+ {{cYeDxJ'F<=[]>-fjYΦ8Z\ d\SOƿб\0`>8_xah.F"s\6!+xtlq8B &5,qHByw^{ZeM(*yz*yi$b/ǭMgiPYA:KВN5dsoh AIØlfvMitp Z݋SzZi m_}bq;Ύ|)Q{u|%kHx;Y8xbE?(QjjK_]ײtgЦ̘ŸC+P= m֠k=Ԙ@) $ɥ:S:\.;HT;_7kMGKߙz"Xw|L-UDlF&bY$){G~Y8MC.*534~3/=[VZ8зG}#:myh;|4AbNС`cA̜ۚuB8}m~o/}283WhrKU]sv߸fyB)2 3 9׹J{y돬RU%PEK3DVF!ѹdz'uᒚ:oͻg]NqrmN/v5-Brh}C= uBL蔫wQ=)8]uL>8ESE 9& ܸMBG:ozm9re? ;bw$, GPyfo`Jx2 Js}0~uVڸ'=êNObBvj;VO|tu"7A^ p KM}Ҏ㱋Uj>>_P+*PGT6V{DwLk AB?FlևNt5Q ѠX3Lm ! lYK楗pi^aj>GG`~@ zpN9AGQXDW +oD wԠֳ1[@:ȫRwt+}bnYUz9JiՠQŕK7N@jv#hclX'pQ]67Zd)Y_;n4XR6eDl^fY* (Lҹh/|țQ™A:D‰L.-gLnϪ,9 \&_ԹɬE!hY0m/ƔTҹ_5>PkPKXl?z4xM !*0鈝 ibx0n= ]RC {'8KO|q.'<#މPXOeᅋH8ɮa5`,|e6&s0jj&]tC̭YtuhG CX]J WN M;MF]t4ԀD+ <ɩ5OUhgG޽J0je%}yDfEu}2{VS'VOh479%J"1V/Ia a:9{E@/ޘ=04RL?,F˗|lB,W狏vΓLjtȮێ v J+)jIo.{~eX+;0GuO > ?a_ͼ,:,M_MjDoX`v~=-&TicEm;5KM;Oc89OjW_@Pokʉ s5Z4lQkji@x"Q\]_ C6en4$z[#^$z墡6WcIJ3'00i@|ˊwiT]8E(O%gp C=orjbUJY +)OP0`;Wy;cbH׿{?qpVΪw?MӅ.7cEtlnBzAЫ͋rVHKu9:gC4:R-𥀡%Wu1X]k21P(BCm=ZV;Zv5*O 'cF= k*P ~e? gKFK:3$S:!1eF:dw֐ h̹8BEQN%b(>O4N0[:5f Fi(E4iܐzRę(ר߼3ÿOQN͚__%Yxwc`K&+M puBefQsR4%wb 'H8~h6#xNz:S\ٌ] ..k . Ek)re3pFR}VTVi[90mf)(ve)V֙&vy7<ް3;h (k|eTОr:tl %7sp* F%)wBJt9`eYi,଒8_wI|n(j(I* -V^^< yS-89{Þ M>#lOWxwG/uG5DQuh}! Tv鬚P yz)/⁀kx.R46?8zL&0ͨ!湚 TԹ< u󑼣ءc})5K("HBA79B.Gx61m;W!Mw59kCy+rET|yjs˳F5YIYSP"bjg@_8O/ E5ʹ}l-× )֟-W@[nqI!k {7ʼnʌԥc1u:=^B{fz|lw,ECOE8[)֘t|$9;*H)=agc6X|ˋv!a1'0՟@2x>PhfHB=T7NJw A;pt.bCBVeԐ$Lzbl޳w!p\gh! WPE/̖{o#.KoORϽp $+N@zΣԠ؀\3YW{ eNj-q^*,s|(=A_ՊqZ+*u 3+hf=@iR^D5 ~Id( 5-^Mzt!ͥJt |KnX*vXQ&j tN_m > /id E9vv`@jt3BaFgzܾ4?V(2 !BG8QTwzb2I}#3M*!^@L-Mh%UDݝAĞ4sˍ>FrquZt@oдuQ*YKo˳l7>W(hl[e_D\PNQy>crߢk3X *YFgȗdt0SçB 9^R67z(U%DWҔn(Ώԥy46?$b5Z43} PF9lgf.S$ 11~.Fjr1aXR|PgCQHE48Qn7ѣf^YܬZZ:|d_9|y)Z>4l2Aae\~NƋtxÖN>0% Sa1<$:[6;?`.RRD<t@;G.C=RS'"Gy+Vd`6囥q{Gy+7}ПO34ypL^ y6y1yGoV 43 &3v<;Әb4}Oe\DQyѽ<Q*섓~6JO )e-ƈEH. X1(S(b6w;RYۏ$[?0Q5g缧 ϝ4kwlb;ɞFFl###odWi퐟.gF@9 ?8YK/ӣbʹ˷ ڎ|,1qP::@{E-R'piwc$fmC S 9f:Z VS%Pzo [_,>BSu`y`jd9bnSX}g#ŊyZA:!Q2{L|3+1^ӥݛdex괁#v1^w#I{xF!C98L,g;!C!syy )m61L7w{ěgRŃزDC7ؐp=764ⰎK.;6^o&NU2i/ĕ W|C]L,B25zDb~8gS'r6|jN>9|*W^D>ɖ7VPc%YVsb%5M6|7 8^7)|[!91boE/ i2m<=ɗ樬Y2\_da'{*Ok1"{(~#2R9[&Nu'&s^hYVU 7dnz'Xڙ>~g%,(\q'`Y),꽤JΕjiai }?9߽TjK MekeQRl%Jfsvz$=r#.|8kEAb}PĊwӎkh_Cd.N!rI8!!4.Yf;So?wn$ mj0ÚK!g@J(4"x{_LhΩɭkMW$7rSꓮ^2qe/gċ~&UxͭƬr *8^; m爠Q1S~׻yJ*ο8{ a\JD%_\,wPy)e7K:0LP|(9kɅFkk[PARI0rSLBihy/0->$-y]BEѸS7w4Z畠ɬ79SS$3ocv$kY!]F}{Z  ?\r̐%4.FC TKRZ~ܬ4Q3㰋aC)33(xr.n tNY13R]ʙ2n*XOw_?oV6R?zC/|0'wl:&EaeP ރ\v)̬h[`SImÎȪ!K ނCD& ZhK}wˉ7{ .;&WɞR7JM"K1"x8SԶn h@ H ;i+ܖFKZB5 pB-ᬓz>u!JW+Em:7<nȈ"&(e(LjU9Ո#|dB{N<&)mWFzГߡԱZ%;;˘~Dr=@~PpHVJ윱)5#P9ѤBLgXLrO#5T&a;}MLH Zt>PjvI2$(h6R`<wcndx YapwCJy/*c+=)mlLqu&~Q=bKкx z00)*[[ 4Sda.h As8dשDQNF*1:k+[<}O.޳qԔD_YslNe4BۚʹNpwɚ 6w_M+YgOȸ@{%>AꙶW&G*VěrG3b](GRS26{ذ(5vǝFnKHM/"@p-G$t\aLӈqv9WCRxy,%N`G1P|Xp/'EI-chPsQr(ڱk&Q 3nڛ8 :j%E0Xˏ\G99ҝϪ# ":[5'6m_ 7+8\nMmR4pPJtyn9{R+dⷰ\/ubw%x+NL|0kN\}KykkI\Ha”[*FDR1A< u*YĸM-Z v^S I1oPB郱E*+}W= zk[TW'Q=BDޑoPtփ'?/-ES|>F3ǭ=+[L5>LKSUJ<`J#u'zPC@ǣq='Pq"fP h0DCeܮ.EY9 TѤ#bZ޹R\5ZG=Ь MUЖ´~V d36yuW:Ƙ;\1w.γ%M_ DEƣDߨM@dզq?LmL$m4]yFo>KPЋ6}y2%ol;O& <-Hy2ާFqLфVjxyL&%)C oCYxdPѲs xwNR6<8U6G}r}W[|q2i`J纕/2YN;K=h[QK8嘏Q5h㜎a~) ӓ7o Kidr,Űl^9X9sTueAZutἣ7" Ғo Ѧi^mu57ǽEE(>2^ TV3Q<4Ӟ*Q숨 q#bx).7oe4.+ P=eByϖk"K梅B*S#ThzY/R`Rz0"*+}4_Jc3B0n^3ܬyPF t<\PkqNg#L^=8?h<#\tγ(ܸy M{kw|!Βc9>D>3 r2M\C[*^xgXdkp@H;xCbh=+mT@x՞,p?8<l,d>oآ^j+P_2x>f(K F&U=򭔍!3 ̝eu4S);mذUO*[;N_T#Ã2 * Ǩ]vSFP.TN",Aͺy gK$ g N!Fv Qa;%ab.IP ij㝋}{̚f- Y}|rB`hǵ3֫Ib0i=a?Xhqd锡g*PcTn}*Is$a$ĜQ6VmiwM%,vl³ںT74LT,"/Jah~@6 }4 FE2벼urf@YExӀg ^ k3{Rj37dh~ Of P֙>7f9UT'0o&r D B@: ~ /tYWbGxȻ2'#"/qu_7ݰn8R ܽ`ieY{9MV/ZMz]8ȃܪYe Pێ$En>]GY^qȦx- (tY1Sa5٬XO;6㽎b |jc\gG8"*CB+R)NiҾˈr3=Q) ʰrjEt&d pr29:mGtޮG9hZwD:#T3MblFuEv7Er3Sڥ59~ɡch>c9(EهW6Okuz-g-ͬ5ϼHoT3r 55O*qxyi y )ި9opڱّP$Fmp9BPYDA؍k 7-7a*?I:d F[EBs^ͽOA+N`bJ>H|QT8‰4AwsW/xbh!%e9.ʁO v+-ٌV(+ƴlJ? P|+64;<LI~zӈRP牠6Ϣ&6M[RY_2q@a(%17&3c=?,KO9=?Mߙd-dž%%o~aK&4[d6UӬRc1Rζ j%(0 9=E-`8^'ؒ}g, `/%%i3'3t^̊2ҵ)+UڥE1[v{pYHP& &xݻx. 6ڞr"uDHD"lϱ> U͗'-C EN:KŴ_[5ojޙPO6^~q܄Ԗ/\E*BaQxoJ|(UX:D[6*u+UY,e_e)t$*4AɹW 'CBNUd_GForKXO1LLVwۧR#agF66Ji֧SYj-@X {[pNc_zГU5kOϦeP~&s xGgCI8tXXֳy*MC9Di7@"s(&m2H@wBtL@M1+'Q3UBEQ=kU"gCdv~v!h|# Ku;?m:Yϧ. !#Au}H~{pwWl|!yPr%QF·>.iȩGZ:Y/T I& A:OJ%{ڀϸh0}Z3W PJEz4t8~T-m+%UB_׉/-40༏z=;A#@762yԥ^)n97+V35=5Ih7TC|@ _R/T.U&C?BqޞʧID#<PXLzETL~Ɣ](#qwV\#@h/JŒr{G$8Snh3ܖ'=CKdI~Hc0ҹSYPF׷3Sw3NQVr7[VH ]N(n~0sJ :omfH!U0q xeMTǐJiC86pIK,S4!0H;+YɕMӁ5HT%:KM=;=Z)* h,=5LʟsW{ YylA.1&\|]d\cYR+zJLʉv|Bs$F$) \VhZ̀N~MOO4 5 4w CIbyۚ""=?qyaZ\,Hk{Nt=ɨL :  CJ٣w*+3-(|zI\è?Q`ot/4RFpcE5SW{Fz QWQwPO%|133g>=ltSyq>Ak)++7d=JF~0K6 ! ٩7 ʘ-RIC'9itq%o pxK餍|"}+#xT a:1w:HúUi 7kN YѼ>cQFeGrEcȌWxC|jaO{y%WWr+o\Hg֣ąr!*R*+W#Gfb3 s{2^8fWwU-; {u(XzЌcP%|Mu&-7h yߵAev@֞}t 6 llP9W# sedfFn,Z-aD۩Pvfy2P}S[Ld֏V}a3a8y4ī]|S~c+]O;9mð$2C"YXKXDSOkwB2rAb8x[Q9R}П3X6ׯRp|)^d2jBA?UFqb']W+}}} Jj0$QL|3s p ='=J24&2))馇Hz>ȭdvν,}Lh?>r=cJIgIdjA 2 JZP+ioseyʇAOuYF1V.ɨ87"Xy;sl4H ZϔԠD8/(3nkX̀*|Og?A DcQ zО0U|)Gr} ޜ+/^aPz*tQH(O7+0> Z'j[ኝ ļez' Y^8ɶ&'gy`ꩪŠ,4lՃ< .-wuڄ|f(ePЍW#$c+FDP^B4H6 <9?OCnyZy-xopE5 N1'ةY9+Q#mAH6Z[4>3d;h_' .hU9i`e?۪,fRy0FR0Mwg}szOEW֬qUsnc|XGwMǦ8dg#]3AZ~Y4G`%&Øt)|F4u.kzhjz/cÆF}D,S_Si[4jlA-YoiH`f Dhǣ .[fR^FRFZI.4G~B{}YKxgU/קa = CyP;6/trҦH&99UlWxe=lDەɩb /_j8cJmUtiMCb3mM 2 mճ:= HWS,\:* fq24,L!H;) kD>";x)$ ;u`9?-5;Ss9c_) "Tr_7mrK$ }G(9|J_k"W7;OCe= b"^3dlꡤkϟ2rŘj! w pD3jazS?ִ@YӞy^p~1E:r}z?h6C2zIo b Uuw ==,{Ͳa'k:=yBG*V'tD 4p4|7@—v 袽#Qԩ I^k~'?|Е=oovZ|~tLVx]kk<1k@EeU:ױb_1nm;tZuK_T Q,&rZ~DbfLǬ]qd:zO>gnq1A|Υ uAP[<'"7yn֣ɫ?J lʉ0 8~Xx74+ɋ(hCUp,,Myy:Hw r5Wi<17a)xf f{늳2vQLn_\]c##(Pxxt p-EPRb gX;cRX,EJڬ Z'Iawg #>l"d,gQGJ{^L/f+yT~6_ '5'RO :,;0 R b5xD͚׳ڥ0eW[Z)9FP~ MkG)CX68L$,`c7Qr 7_n>>Sb<>M0{_&6pn:8̵rI]>=@{^ZĀë|,ꋰ8Wj,%q| JTs``GVBh.X][1UXU|J8]9fmŬ )>?%z0XYA_U;6k* c$vaK̹iEBn'.c`'SϺ|w?Weje(]^gHYLbmdwe٬i}9QhCB?x9/"Mu:8:8efnECC$xڥ鴎JHM\Z8o@XR*KO5@&4Ϋϻ$aMJa5#1->ofHF:?Lvx`߷qVFOo' w`:E8P-RN_;ᆏ_$NeܡU*dଇ!1["olxv ̓a'sE;|Dގ 16&;PBQئ ++dbID0v)7Ig3e*s;.zV~-n'l͑9Z/9k:\PqЈyP6=,7|H_a_ :bUzKOJ @L Ou]i@( l9^H\f|$DL^+r^4M=3/G pCSאEvkUWmg-}0S.⇶?#EDM;x*Ј>#=/biU pj'z NMVuI *O4[)ต&6W\ŝr)\HƣRwg R)'I|G% E=svJZY(D>3藀)'a+tWByOx˂csԧO@ l/֖k{$'C݊`U]ݞO\+'f'7t+}sDE z ڧ/~|i+~'f7ẄrQ(==''yM^ʊPfX,`yb fi  ejG2m% J0.\Zzx.ռs)oϥr"'aUcI 0vrn@cx7Iӫ߆^77uǖ's䔽p>yF2Bn+I!|!֐rnhx)bLG|e2%ABuިh4D~´᧋Q0W"or0Qd[jeJ}*l-Jv(%;i9AۭS#sg3RDJQ@tұTf14} ^/)o*BW_=8Ϊ$o.֓ʛCJO iLR4N;$|p$7d^>@[X)Hh8v0&EzZpI*qjAol&*Wu-#k-7sksskWr.IO8+WND_㐺O1!cy+hdطY7\}f%}Tn3˨/d^Pǝe^8.5T ^BҲI`-AakcU}TWZT1ŒJ\Y2!d$?984duϹ"ԖtDј4}~k +fw Eh݄+|7M4wC/vq ==ld0тvű k&Uŀd,Wy7W)t-d=eZu&< \by`_+US/LhØݳ>c},(*Yⷱ+m0ձacY%bXW_)@aXԸN?7k7vy-q "K\5gWwPSUm\]8_cv<R響Gb\=R)'LD9Aa]˳mmCTFk;`CX*O"x`YZpw4ki 1WD*NVWL%<rR+)#ōMl*==9AywbYno} 1j20QgyPP3<#r7-fwӸ m8'2%Nq0\ߠ;.KBCe򒤋>#V#Yxkb/GkB?@#0{# >r*eC֖kRy ǩ岇,&v6A`PUfv B5 W5dи! 佼mR r4]42t- [fvJ$kL΄3fB)#0;wO[p9hmZ4&P7xVw)POA* + `8ZE縡gy9 Y,rꦽ|;] TzvLB9_,j}vʄ:߻OɈ}憳}6)dZrH~6O$S5w|I֨ʗn FTG /VEUQ&S gqU1b.[JV>3)*ȠgB50XO~Ti(wn͛3uĻl/{&樝^5,d~~ch9bagYrƿ!E~ |+ef;: b90na3戫sqD{0}bN>`ҀPpVx;@͸ <"(úŅJdx ɩ-vˑָͻ,XЪC0fe=S4n4A( ZXMp|BzٕZ=f: 1z8"Ej=I\^5>VVOy(R2N8؋$_ֆç6F]GƹNarwb>8 nLyy,koG[(0QUfM(i6a+g}m[N$@;~ ES;;lX1dS?k#(c4Y};o~;8euL+C/;#Vo*4dawFvNnZ:MZ2p3 +pf[c_ɢN3`X]\f֒վlB!ȊkjZLNҀ V3330,('cyPkxgAt4ig΀؞Q.y|/2㎎ 4;wyvj+$蜜.s.~_:⎢߄vr[ů @8 Zj\1ʻo)֜ X7#O;KVl2tm$^V*s~ƳNɜџfHb7)+Kn#o୒j[̲NLMRpdzr.R4{8n^j[qt]!L5.DayuchY)O9.p#RUϹR#xaaG9b∏0 i2RCBՖeeS@ǘqFz{I8e ѡhv NSX5_x2ɤ)UOyrj5[WֲN?BFTk8KwE8OqLyV.`EfXcnHvCUQ)D:!Snx8LrΓ.-Ԛ?-/BS$kQY =o:hv74ٕڑ]<5jj׳r,넩2bEBjsG6%.CID' u~` =^Hrf4ܳ@2Y *X~r$5'x'OqalO %eMbYP,>67"mcK/羣xEV` !;טAZvvFt7({mI&`0JjwJO(^hSWMO!*g+5j'QNHs ݤL%s\)R> m\)eNԆ;GhIT =Y[Gbewi!F9Yq87Hu޴L`E#̠#6ӰPYLSc k]dpjr!~Ԏ7j6wJ 51tD\:z"둉?ňܮ܌ w*Y5kٓ M6){k n^|؟H]F%g),͊.IUG\.VNΤ9TΓ)[AJt[Uy@ڈ@#\U%R02ZS^q)(xdظEQ!RKTRoIΌ$qIKdԔ6ԐtlMM]>s+}}=o*iݿPqPٰw=ȩzV)z#0nb/Lʊ9ɊauƲN)1ݳ\wg3ѵuFj^ hByGD-ᯓk' g˖5.rԦMƊ#%?})=Q X&1 ^%ӈab>u7?̬KuIbpѦQ;2<[л'j*iPQN͆x _(?Jb  ݱ %7*z4=1(=˒S)hM]:I 7G){o؞ ⽻?D<ěnڃB-ay`gjHSQr '?S iw)dpU4#E,C#yj>a؁BB$"`@x#r{R^gaKYķۺl&P»G7kExka¥ kM#$1[^gftC="n !s暎$?U:=E, 9~w!op\]BgZP؄jm*=fY1q~x#4ľj|UwJ\{K;T)^)\wE ߙ".i 5aVTπtT/Y ۜ.]cߠ棴:6#6ǀ8dJ@v9[O]N!9W 'PXm>f dq]tXx"1Y(PXj:-xYޭDIYQs-R6\]I Y &%:}_Tic;= S eGbS)9y_7L 6*Q׻ؽPY?}.*eoIa\,&44!L30%S9rf]Њ Cc҃:p4\AdT6wP] ?txutï@{y1;M߻HGqg&h!aqy=[`kkYyMy/(?Ȏ였;77J2TMFw$ 4ƸNMPP^ϒm\^h G7<^?D/xV ^I[ۼ\Z0ڐz?Bo͙Ѕ^EIq}])Y_x30z9Iw봳oe8ρeuGve|c٬,<2k/B '469یw>G97Vp X7#PMqs[TB|0FtvxS,{Dq/%=}ք-GHQCAPXㇳJ,y|qq{ MjL#i 0ab&\gR;ab*3j(dxR: kAt"wgt !'pMlV*><|NUN|>HO05/+VA   ,`Q ]HIǻh|@Ƀs~]4S,qi.T_cl$S>Ɲ-jҔz;r2wDC~&_}#WS*?1_`վbuO.ߞ(/~#3ŁmC6uH2@]/7a83Jp:*_32\TG[:<1<>^'4n*q|%99[&kFlW:]YM7˝rM}"#<0<]4pRX9 Jg̃es}7e;&oFb"k$itH:¶760\ ynXN7] dOpAP\ g]фTBh (|l8^0 $"s)~wt!,+c-Tf ^;>*סexݓHv7Cs*@"wو kf*T+6},蔣[*u!6fEs*xDg{R*XطBޞj4IU[pq2FM1[mQ&9'u1SQm;6x[$WDo!絾FLoneA Lfyw|19ޏ IC%{Lfard`HT&&KrnMP1EFDJPGe*߇\sx%fhyl|^(}{ǒ/'F¹n,Es N_3{ y-kn}O")Uawvr9ٓ]$~˴;sS۽Gwt(M}_pJK nsBJč8Dō8()j& lҨקШZnmǹΥ)-+<_%G Kp*Cn'־T"3M>p=+ԻF—Sc9d*/ᲯkPԵQp$^٪4ݬ$ -0$jkZu$C#d!b?赖]!T`WuHB` K<+k<SW->YDXd斋]) h[#5d/jAM27g'^@CIFO{ >ijJc%\U9xzDOONCh^A 8Xz6C8;l)k>W9ӪuC$>FTvpM"П&H rǫ^я3՟GBGYo?ֳTYyZ .( G'}~syqD}Хuș0̲̿#(!ndL抳)Po=UĉuvVuBg|;/L=skxM14ae35pKlc^#O5x+삷x_ ]G( ! WI rp'5tI'yM0$]31Ybu QM ;)k7Pp.${Tޕv(ڪhbŠsFr}c`!ZahkY+-BNAge4wLfzr|* p\LO׉aXX̀a *H8Oeui62eeIWy.MP9 "Z oXr먙rOOʹA葫q315DWazQMb}QC:8Qגwn^YFźR!)r/ܭ~hog+-RR֤2Vy,<.]lB+|NVQ$^{<pJb=Te51g|mXNZKLfTtpk@W(&F̫ӳQzIyWvV=ޡ& mg[5޽b.@KCtm*9ߙ\žL ѩ`k&}ūg qxm$:lR@ WU((gõ5P~NkIIL:XUF1$PzKnc?7 .i,jZ5ǖ`FLɜ=o/0YNk:=ddR@݁\`~g=RYzKt% oVRϪXlJC꽌d-G|Ҧ PƟaBMtf`mܟ[8rTŔtR;+ *⼻3j@yѰE+cQ欉&ԣ6v`"y%{O[4etnllhxP:$djPoR9Y-MnMYig1sOT޼ty-Ot&yVw)l᧑ڋ8ߟLh< %k{ΎauAFZO;AvHow|ovÁOpK2Ր2}|& ɮVLPЕz@2P89{TZ~=[~{rGq"2͹;p!{+0bS^9Cǡ}$>,bzmpt&.;r-\ɫky=Q Φ\ $.FX1]R qDr{h _:5hU[@z4Q/yt"dums`UVv ©Ng$=X&m-t.kjV>w#3Q}4  CNUǎrZS&n<4RIȑj0ܲNK7 _',w#mkʭZ PjFrGq?,`aϣ*{.Rm3y/sߛUpXC :"Y;2'RF#= q{T9m|C=NlHϏ3mw]cː,:?$k꧅_ГܕLؕo66u4!ʻvRf=l(+60VagѸ7i8x?LŸ$BbCyƆ0G%͘uFrtܚ838R(K7xpckPDMN*- #QmsoNДP&4uA?w Fvq|t>ӁQ'j,7 \}T'O9^vF+ .WG0wH0t=0p>]bs Z^P\%kN( +n~7dXwEoGIvϸ=aǛeE@iUVjj@{ "'´fpȷ|OaFh#stza uVO4 A%YQr8=88@bLQA{ 2h:yUAYd ACe=R&Q̆Cٰr6@ Fw>ǣ1# xXVN)ZCͧIódH!%oU?f"ޗԣ01P64]xv:彋0 xCSX)^C7R\BIP3%Ar2b6>x#i8G;`8Q ?#Эi3I?!m̶$hת2T)K-xx^qKFͦHҳ#]0^9@u")՜\hRU_GkZò_,6'E+|lac85KD~T~th5-˒}Gk!^Ú"c&'fAcM(f->cU'GXR6Oc 9^P*z P~#Tzh Vgv|BO<Tͫk{N@9`t3|TZ,?onECeK#fK y)A:f]ʳ܀1T`T0-ϊtBI/ x2}Cو> ꔿ-}> ^q9Q S c޷z&C/UvpG%8/t. sD|GrvD; }&O/ZsqѮׂu-=l"pl-CɪY:&kK,C9}fZ+_#!w_zP\1hL4mg΃ă|uVOwRM/2t7߇.z덨R9r?KO]Qj׆猪zTDaǧc>&mg g|OcnDG҈r"u.CDZ#^aar8(A|$7eg}ۄCٌO2W S+4Y+^$[Jv׵1b9 ,]&G*K)svǺWT g9c =Df|#y-vvnw:b8Uvl?0o.L 41>>nN+=e!2BT$ 1 TR#mPsv1t3P,KcLdFaX6(M'ڄ|<և5dϦ2IH +qgm]x-Y2.'OHDt 'Eqmi}}CSrR2eqh7|J}7$KW>^](OHFN\ +fZͤՠ!I: 6+`hO'.fw8/4(ЧW:V6$6d?g1+2xBC2 =$ $[ޟ<&nQRR<0%iX3IKSG$HjNI=+{EיSi/Fq@o*Zy'E1#lI[z M 4R|LP-pNi5dUյR z=^LJmF&JZ6q -p[*>$?fVߌFBRpZ,g(/B4DՐKplf,է/^cdti&)xs9RwD0i1G_cbYfT<40R99Dq+=%pJEYy/#x 58 Ȫ>^ H3^h-Yv~ѓ BeYKd#LwW {{~buE҂yp" NHGL4A N2vFA27}S|g%?9 gTΑBC%z,NX`'Åd/ kWT'e j,,'b9,gO4bO/FTdHt0 =΂a7h34d(C\R!_ <+7 A;Ŋ 'jڑ'j7R\.蠺3y,+8fJ/tD-{]R-J[W9Hd.zpŦ&vZ3䵨= 4fe<ىO/͕i =k|Csͅ="r:7tt߭8@z6%GR_WD* CnK(z(Z+Y :t+N{o=}= ea؇rs˾Q{tF#IOT B]P+77*]Gr2h7!tӈ7 `"R0;.WTL)D|rPg= Ev)v]f FblL*7x,]y@yζuҕfsuN'N &~+*}(: eUو4XJ>7}TpmcXK#3%9{u=1!َ.|q'G@f1ZVnĬæ7N4jmTDUAyqؾu.tbLWzc Au7-9ʀқb3$ '憒57RdzEl8]tY/T:# ['8&e9ĞwFl]-5΀X\jں΅nO!)#sQz9_Z&)+bDDž\VޜFMbٸ (WP@1\4Lwፎtݔ8db9|aPZJj\hQRA{b*-ͺ>Lr鑖kڕF`ͭd) i$tDŽ '>w8KOcS<ͻkYYͻwsͼ1NƼ+Бhi 8@#,eiO즳 ;f93bBt?zW=(;Ѹ?)bplg,kB|8zhDKI0'U%lXZbL$"9_G0 ;TgTa aLĖ~%$L`v9!rĪ«Zsss⎼d;4<UHG8[e kluV4|K+y<pj&QTo{tMG A Fv(U yZ"0x25j y Nw$?FRl1[K Z )$`b"B@-84F&m(["ݙix%)O]gJ\N 6rs<e-v6mj'tS2RjV/ dO^`ϺEH k0C,t+$yHrx1}qyXЂ Os6Xt{Lx[ܚ4EyXea,h"l&[ ȥԊcOtz{o` ﱂq=?!p8#+%'JS6 -IĪ T"CxYF0:&`t̴d-=lzA?Tz{'S~Ve`yߒvs#qk 3j0.fK u!k)/gp[Aur.r^ m:r JP<SYumoIҢWҟSŪmY֥rsO&ѕ2*kjɋ Aw :Ƹdskc! tk%  ]g]zOo|YCy֛MeM 0,%=~fGP'V;O&2O'v59`==xIbB2, jw*Ȼ5ns1SU,Tق9={EOo?h Yu~ڑ EPwtX}# Mp==fNX1' Yʙ̶ 7`QVV9Wt.[|dmW7IfTZ902oY#^`T!H:'64A:f@Z dγH)ض %㕨.}4BG'Zg0,/SつsOg<%Op7B-2*P0B>T)xeƨGNJSЄ'pc5+S[ЪWicT>(޼=W/? GY' {7_Ydj(*k:o?gjPmX8&TRλyx Vl& 'e-FbN|{cо1_8hV>裱y~ei{ JU=ΒҾ$(ؘQ0V7^F پj!K*=ȭ&_=gqp+WTWO ʺ9gKNCn/VK亣{#6]z?L#x"k{H5"_h{7U̺&O "D g9AM=o *&Ќ;TcbOJ(TH1+Jp Q5Ϊ\~c\N| {ӡ2dδxO'KQN9+a&*m?8ȮEҵ;uϫr +2f[Vx'Ŏ]p'M6ujNC)pM;]_#zݧoq{X):^iC9&+;*!.V8 &M`!nx:'4"I+ĥ;4X(a=@g?YgeDQQtY+, ݹ>/pcEVF{<uEhY|OAPb7IABbdfd` v4eihD}6,Œ646+vpTwPOY7QBz9|g~%j7[GdӖC=z rXyv'TL&&`sBHy \X]lH'.py؍Ln^nkJͭ4#$yuj* Z6ou'zΫjUQȮ1m섈`Ylz8GUUk7Fe|OY#$akb3Ad^dzYI/ԮG@5(mܣ/4VuBKZ(tSˀת/!~ }NuP,}}!z[qQѾC47PVVϪw8 N9)Ajw entbBGcpDi~XMl$+hKn)55Dy"lBY;{he#a;JT׊3:6OƛZF2[_tO(= IL."V»=zݤO8/i&#)H6q߽Q"ًU &? Y*:CcDqdT!_MchG74]?M9*˳X:lSdԄL]3}"B +Hw;FCs1Ll/L qQ u qQe .cHOhOxwk+fzq9\aFE^ {^U#IJ\/'4Q-ʎK! f'驢BWʪ_ii!^Q?]-[RmyFtWS=q"D#ɏa`du!W,R%per|npO&Rޯ'! MG f)R:U eY"^J2 փl2$M3. o*;=Cǖ3v&4i$4#F^rJ J2NiMIk1$@@01 aw ]:I(E,I[ qbm?h"!mfOxY7\/<VA"Hs+8B g>]̅u^c3yw[YE !:5I,ÜR5=eyf#MT*)5 =|'z).={gfe-M.(i06F1I'' =ܾ4Vi*9NNZvK'?'^$LҐ4$gk eF9OeFț}ŕҺ!f܀$XjW։ ~*.]“7Z8\Q9&+~F- {G;+ܵ}sټ;?۞ pFyDJYbe@W7z{,yǓgˆ'.^nκ'V~C6|rr52 _93e/ 7x1hʓ ؘlgvv=qJʡ}`Y/&V{G a-n6{^,TȺB&݈!YzMTiVvjdUmY|Ƒ^RTp!Rٸ;='*sWļHT+Iz%YNׁ?E)qXw Afdǀ#;F8# xUzMONKH.Ηn+9kVqzUSܛu6f`ܬu" KBqJ8exoPw}n d;Lz{Ȩeo pIFMRql#_ +ruOQ^D+#)yP~2ޒ u%$HlvQ,(Lb>giRs4I`3B L@ӓCX!fER͒ >09bMha; @ϺX}BCn)ӫsUzǶh[3pJ85F9RL"E"w]\Kd(`P{Wdq1˄Vg)(')樮$}B "Bj)[$5۽YYZCɎ 4'1`K(H|f׈[⹂bFOiL mc=`ڍD+]`Ī[*w:uw_-6*E }Z(@fjYI^ +20 l[J=2kT+`[S;Q{;09QKgi W 5Zc&ԵH2Gg`t~zp!ю10Q[g7 nǴiwpoǽw@n̪*Vib7 -#Ӫ!RS!"Tqp6cH+}{CN~KFn%$4M l ȤAY`WGr,lFP!ZݽٞYw\8G&IڸrE ]M[W;!n};L̹N*r<$p"J#Yt剦%xYΝ FMh\nR2QCv`m=3KwvY <o4]Q{y8.9tѤMz~.}^.ˊ,#h0?#jܫ2Ta!XCc6k<#%v¿g ަlN Ϋy9^ M-9"JSP͞vsš;:Re75jSXϥXvTTpp!BZ=):: $\]-R zϴF;4|hgVNh"teaJF` kar%yf:04K^VFoEm +j;2s1y>sCEmQ֘ϢWkҐJa H&V|MY8W9J>|# {&c"-/*HoI@I 9 8oygg-Y.qTPF3N> d7/x y ;XlϥV#/7I\GN᭛DǫGa<-OouGjN:zϿJЅ/^ĭ$}\|c;WR[G vz,WѥNgfRͦa/Ѐ5:Pl痚N`{d@~x5n +a]{:-Ųlz!&-{~i{"K=wJVRq`vTHz g1E -quA@z^Fg "O,po_wf{z}Xր~f5`H=Zw;q0'k:?-0ĶT;Tp!G#d^F 2B\cpfKB.tȌ;vC 6rX4w-zc٬׎%ζH-mA6~ҧ9 (Y⨛}[8lZGDqO4Oׄf؎b䅽ݝyHX֑ 4NO5 lJJg4X T8]HZFGbEGT󆓫ܤ#;>*8':w|V7>D5(S)rFtߟ:rVۥX]O@Y`u4U=I;L f-±I+"Ng`SN[^{Mi>oku16"jEObcRLi7!ݝ$Vj0 PhV bJr-QglV [i"+d0|{AĬ䫟GWxʻ[5S YSʛ@gOw2deGK_\Oط^[b”b~[vH|.uy %>^@Q6qHuy0{;c$M,QAl)SZoi;_>})0JM 0tJs;*do؊VYahɕ =T:t~n@^@O/^uxuƋIJ.::HL-M&Ӳe^`lZ]n3;O#{HuIyqvԑ27C~NPfB7<=h8JzUW`Ө{w<:.JE~&PFy"Él8tp w^Зz:^ *8l%:yQulV 뛏~OL>yckQR7Z-3M^KZوݛG-w( Q(i~`F|d)B:϶pr,)@# 2e{80+\&JP%:/ԕń4qk旗SYKypq/߼[GV[=mu6& IUx-ǕJّcT(̰93{/RO4(Cܷ&^QNOYH(h U-yÔ{R9l$ҨBFDl(Jd1hD'd~Ilzw$0L y>p0OfFң/4A߱ <$YW^ '`PpK5Qcc4=BC+RbDJp f)lwu(&5K؋ Epj2uIPno9+{ׁ;e ?M=4sNz)Zݕ'?:9ǘPטIV6˜'gTH~ 5ö b2?jGR4{a5{qvZvt5)LY\}FRFZT-cT;\3lrʗ|JP 1ĕRbV{ (+Q2<2ilKkAGt2 (=׿A;p߇ȝ+n(Ky'F#,™vIV /<\(q4ҮԜJ%U}UNVGx$@Aʚq&ċ$!ez|gl-V лiW𞡽u㏴ w_? "R'onj/KI'yaM;,t%{׹lOyL284FA=003Wha%iWt=߾.3-uNt`>Z,9JQ afxx2KBBL yz( b`#JѿknJQ%_GCET,9#iZ'${5Jrm&ܳ-!a p^GKa:߫> 2MXײNM{LAurs!kf+nW¤p$R.;Vh 805WQAzD^?|j!ه\huc#:Gȡ?uAA+cS`Qؑ@09OUO'yst2S i{"}2oh&ՐJlq\wt1i V Q.|؎5-N&P1 T@8ғJ˾z)])O}6$X=]d0F>`-CH$g gF"gdH$-C,$CL9|Zon5lU;JJ;=fӂs@i*_޺l(D?ng!,iqghaS H~dli;xϓly_q_ ̅E-uǬ>@A^9c9yqvu}&[Gh{ S f:0 _35<|R19:ZO}ڠJ{\jyUWh +N9x#f/h ~=n05wϘel'1ޙ˽ZGZ`v\W)98]}"tT!pEvnLRsċ., Hȃ3ǀ"]l>B> Ec!k/Bxx\o%9sʗ'<zO蔏Ҵ %p0e1װC?,#0egw{85oKCRkZ-gG3(ь  l{}>ȑ\.֓)'@OU/9dG U^pp! }nprs~Kdg_']*ʧبZB'| 9HfƭtqE{$" v|P7S:Q氖uQH-Yxh (J N(1"SV(ʉ8W*z4#5r \kfN_ + Exe 4JۥYx_0`81y@tJ[ܱ4h1V7![/7FGj1ɪHQ6voRB4HgK4u9C*J2\ܳcLh~+xioc:?d.!uASzG ֨.h]oi,0)9³My Vlf@cjXDJݪAIV{^̾c\Gu_6M[3+**gir0#ymS剖p[֩|lqMj7էA f /*w/ҁ^E2XoM ~l=~,%e"CYd6pYf}qko:B-}:LUT/M_?a"C#Lu9WtNG:/ )UqC<$ ;hɛ"e|"T{fˮ foq^`tbjUb;fO7L=)rMLa2:d;JI`~xt0Pr4$CiJJ}__wNA%e% E'BM7H$pLT-{R~+6gYЬQIBQ獖"[a-IHA&N斾!0[{'B\4e*YZ*B$p3[>c`qyw:=PM@s0 F>FJE.~!Yiײ>쨈[ƿIDMak :ЛEگGɍtWy#ȹao(ۉHkkV:plW uF./`[ va9!u}4u'%\;:HƘ)\F^[ gB|ʯ|Xt睒w33n G6ߓҸmQC*򨑺ȰW_j4fؔCX<)v 6oदù7Ÿ\;]QQ ̔H/X%u>trox9f`Ib%YDC]^2`q`v:J+Gj枑'Hv*̡0W81T$H8Ze;tG׉˜ϒl^k1ëDX֩vevY8EN oYj`ge s* 5m#/1Bee=븳 igC#2Nvht r&bQ=8G!3d"zQ;Nɕ鲖`Pt"b͌'4V3qr}c#'p.:4 ۜt`nSi W?ktA:zJuE#ZNV_ wv#*F1!>V$^m__uܠ(m% h Ng ^3aSm{$QOdD&\Ɩ b-O>QkiLy`];΃JuhS t>(v$]KUr`VqpD :"5c';f=M'IEt#)-"lSbLSmTͺ~ 4c8^|mf0&Zْ&щKKҊϊ7=:S_o $J~p!]4uL rfat@=YIbMO(v znP~ygLv"VoæqsHn}\c5lSVMC늣 Ubs0 3cdf Qo]ح9_4J k/՜7)%֓O$ ;f[uzpa[BDilخmldx2Jr*$fAs$NVnVa 頭|q -.QhIV=+hֿ3Vy {KC1^JAihs'[Ko3:I4u` hyh,LK Hwz?g)zuZ#9×'/0:)5YYfSY'䢇N&'/yU0y;XY=f .:hYa:K1VrtG%z G76ټD*2JPz]pʮvC:)* Vӷ| 7!rkEGjqʶԬn֥͙s&m0T0cbLZ6)^/8Y+hGsXB&Y@̄3K;kT:T&`ϐ8CS4&s\ o-G--ߟ ޟ?.᭑:5PQy2rޢ%IلQW6g^V){+> fB+o8Nvb&Rj r=m&zoYډ5hhȌrT J=;S3S>Fbˌ߭o>碋ɛ#p/wŇ/F딢uueY57tøMܧ&qqJ;޴#d˞Bg=ť${Ʉfk;?C&T&rQ"(jtl"aKoU@g +'^<#GJq]RrZ},ae/YSPɜ-Ж}6Gm$΀NR"}fS"ϰ‰u:o_fVPX9ٖnrB)ξA|=߱*z2q 0 aN!+'Ď+)klNR>"2q0n) t, $h N;[AN' 'o9 gmpbπ`<$/>J^ߒ2 %_$E?mJæZ3&>F6 aeYEnoi;a2at5qdvv@"inɪyz;shW|ZXW +w# ͫv@qVz{CMT6k̘솜Mc2NϮdzvY#TAiRcyJ募a|wYC7?*<;Fr%ى0kdk0xM8'&O Z|֊g5X.]Y4P"I3qӫb-D/DMuCsS]OP$;͋9JxCk+l! fh^htCWΠ@XSk3o7Tru0sEecSŽ嵑z1vM7q~~M?yBsa,V֛}c lyzXŜ.*Go|TƒfV4ʖP2>Vn`/9 N7mpMF^C~D8Sr%gj/4!tQ X,XE,;8<^xOЗsi3w\u;Ί>9+n<Fly{Y ׏Oj4;+<ΧѴSD?X/_]ԗY,9YKrg MLtKO[,e_>Qt{* {s}njU]}BھЧv{%+NFSq\p @)"1{4j^ o;Ihy8dk=-(Lˣ7CR֝\h]4ȂtіӤ)-sXQ݉Y;Zr<_(E{ol|.<6=s?\p:9̩Y&;ǥJ;E`#; l? .֯K[{mP꛿$Pkh4h́ueM}hfo6i#cvڋ(yʶkol#u'L-Ӂ܌jegD.^h Ut?趴Vt|E1/.k&Mo =Q\ sit.M՚_ Gsg~.o6BG/"tWncnjI**ezЦ[z@fAB@ qWj^g[a 9geܬ\^#Wʟ'(\PN(±u̇1 +44'd3GrBS l.w{\2ҒzD/\`ьmJB9Os+/V`A9$]׾u;s΄;:m+{ ].uX̠|_1*c4jرḥ9DB=,۶1;8:oiF(d`hp.tI׹\|?{sƵK7Ksjoݖ>앮]T)0V!iZ6%1__RlVCe|˳ZD|ŽKļf>L?N+CyѸ˨{=q *\YlЬXȧal>8s5 79q;'\d-|V ǻ%["ޥFtR$V\,t7K ښΫ6xwU0Tt#ګe]7Bd8nQR~\_@Di{.lw>1˧|t&$ 촽N+}VZ^fwo4`WX0ŁJʷfռ~1qNt7Qݲ1; EE1(X3Kҗ5AqB}5 #g 3D | &txw4žtrW«i'H)3&E#`*^G}ZT#^| a5%t>Btto#%#ϰbEkAz2B 6c2)k/%S$ rtMp A٭+GhB>Kvp~sLMk1г ,:#3AHCG@uX}lEy}dFV<:#[%˙B<菱Kb T?c?v8 m&.4 EN;[Gץ='9(:Gl[1v6rgvˮg8/ǚ-==3=UrvɔsOh&n!݌dd%Y#SISJ&VMH!˦K5CH==\C$+udSYEy-Bq@3=O.޺3i\c"GSCҒy Huuw`ME$]J*7}uG b6*+Gfn*,Oi3u# M(g'͗P@ aQU#}{&aԢxǚdo g(.ӓ >NKL{޽QT5}4v3 QNc6}V5Xq()ބ&XC ADLCu9|Y<}ĢaKOG4/:\ L̊@M2q*I -Sd;U]sX5\;dB*Ԅ=1 ԇU(w@<&N) M%IJa?g]l~ G1Lӹ כnl]o52=a>k?1ZQ]fpW(!8V{4Djj%67C#SR5|S'C׉UH󔁧56X*6b-9ҿP[Hs^p4dqp[7V!0xb('] ;Ϋdl&,'=qް a$H  d40>1.\M;GN':{dY-9SqaHg#S)xs' Ѭ,:MF4MtK'SxI+tK!C & HZ$imWP!9]l]ɫe,WyCk̋F^G:m?M·oré[ hBdDbԽap6n*äٹ}u2#Ծ:og) 3#8r$bN_@4[V*I_5B nXuTTt6Raާr2^^Q*Ґ޳!X8^.$:wo!r5;uN.[&)/ ,KIh[ưei`inO_FbZۦo{z>; 9+Y[UtĀk(qЀ8yAH3z~l)JXƀ+v,?=* äF2{n+mnܟꔠ֦]C{2Ib.J"++C$l2 Wr`v뽟y`3|ªTOp$MŬE܄%Z~l41/NfX {c \ 2: rVͺ4#@I p&nr`0 xlR"ʻ^OQ>Iwlqo%n"'Ԃ}nבwp| O7j;y_rdy ̉(&15x=D%T+ o/LjevVgu8r^xg( c--d/c(%nE7}Dtk4KK^eS$ (SJ֣-ҽάOI.5tga?<[Z'"%𐃦$4qXHm%hг:UDz#jv_K _J`)ɲ ]&N.-'dD"㐔[;CȲhܝ%+렟5C!f  MNdzzv}"GzzX7 {{=Gjf"6SռI5ѳlJXtZ1w7O'ִ=Ia9+ל&jyʨ!V ztix\v^Xqe͒uj<* Dhv>A%<"ĐH->$5}o#Yw Ґ5X&repO8}.e*F,5h'.)m`r,NQ6JcaԪ^k{uOdDRA>7EIXV=] Μ$u7\*wKY }&Bh䨜|Dl.y(vÔ/kqRS0c ~ HJDсT&)߳v}E~4J0Bڪ{y-\x\b 3V8e> phwptVνC^*Wl$E3D6PZ9odrz=;,V/4ތH2Y@ cÍcg_^$t2i% %LrN['M1D(g "p*auBJ-!Y\n|/'̓?Aǝu,ue;HD`Hny}WE-g4=3tX*lNYiuuvɗ;^0yb͗gS%o:|^ȟ4{N^r*#}s~Lu yvuwFoN/ȷi_mS&fLD֧=UG@?D:RS3a:?{CM6? ÅPO l'0$6":rsQqBDjU·!TpchCU|[N1 &/VS8 ft_ 2 TMkhoWXc}uE!Č#?+.:pQW^Ο'kG3=ٟU"xV)<^Lc7Č^Мk16$8^|b:n4Bx] (Z=XQFQwA\WT?r4$R9xo'iXvI.7~6 Bno8vMV}cVO^)tI~F.gG~ܥq3DX/9ZfM?TVڌ]QxTt17e^'JΩd}BN]pN+ ǡ: )!&=]gTPOެHT!EdEh*źK8 < N>K\ KNsHO\~],؄G uxL [Ic6ڞ=7S-و_ޣWckDOg2"h9*=3r$q3ZȱxM&귨*q'k#& }gJMj^ nӎ&-_>u~!emس%+lgWr|BEyלeFl5d{^Wk:.+$:T ]c)Ɗ9-bDO^;gM)Vm1!THݮ,qyA@ =tV©}c$h@g}SC+,: c,;q/l㧧HWPO"E hh uhbD1"Y@bjsVl-=O vDmɕٳjh7aR_𛚙:;N?qlhP;|@ݷBu~74p:~9%-Jd%02NBHb`e6d!'Wf2?O>~ۘA6Y[-ëP !+s21a&uu(?֜JUaS? Pj+a1ɮp5(N7) /{2ѠҖ +p 뙌):CoF)YLvVzʭcufhham'u>~).~s0I9ߧMW颌B2[oO$lxAfLlH E ΢Xbt̝]dszQVY)>xn 1gcP;;[KLNld*vrӽK>ΚΎABZ˨&Sv*D6GqRgڛšӛjC#A[ ZYg)=oG2Ub_f48O-*%,mxg)V,)[՗s?SFԀKd:qcBz9vxɿ]=V?8z*');-Valin@?]i,:9sfo0{~;/$`w+`Ang-‹*;dY;nqN:í +N//OYeCk#JUX`%L;dH`X#'ාxsfV KzqU*6V-y$.m#woݡ o^}q.ZmAY34شt0-{ܶ[THNe(lGӑ-*9M}sRkn e*/fͮkm-%dVms`i))7/@f;8FNa$^پl fkD[$AZXOX[ % bYRC;+LaVk"R{ٳjIsA)c>GT?@)+a9?4#s%Ƈ_.2NyuˍorF /.=jtrdR֋T*R}$9Z"52?YK 9>N%C y[Ψ%>B/W!Oۙ,ӿZZ&jm]A98UvdZdD6OdDt1/#HOӠU?4=x.&$ }b@:MԤa*2[xeNct6kfeW~P&zD4twe9 C18y,ez4]JO4P1r.u*7rҰ1]J1]=$^e^SW/3IFV":O+pgze1b9@(gðqƋH .lrB⁻W଴QZdA̝8!+xx!<Zҧ -}SBl3ZM f(XI}/}?2 Vġ ~(\'ӾIfnYhzA!ֵ2+-mQNp=8Rl2VNvE"TCC^j8ɀD# tOcY1hBNrG9vaZ4LG4~QP<!*ʼn"1T'a7UaƧH=a=RuJ6<z^\RP{^p'E*"o~nI㉺hƌ͘J5vVWf*^TAt.N)’Ϧ2vcHeLaV]ђͪc?e+F׭O?CrЕM鴱)Awb:Rob9}vʧ}yWr::t`k:d^5% 9o~ޙ ݝ^*E=8rH1f6_Mc ),K^w| vUʹqwAnߴ'IbD- v&+RϺ&uhytǑWbͪ[eQzS$qZjS*X49!Bb&s/w?g.5]s<4^. jSv28xw}OZ֪#2a HehY'tׇrC.OeMGN05[ˋ) L?X&tqҷ$! A i =`0Tf<"]=۞x4 gU X#MCX[wWt~⣲ŒQfGt)Ĵn=%}׎è/P_4jgJME'p[;@3&]Ke!KI]TRN??wL;=js;j )Fс0 ]}󜅆U^F7<-Z~qDGSGWJq9͒Ev9ͭORj31r6=UB~@^ر;nadzs?U IN;\SM^UNH]cyc-( jbnF&eJtρ;>Kn)I?_H㕥+(ڮ’?ñ5P}U-מ4\bҴZ)鋢jI[ -D[bW'Ck6(9cR4J5.'42ZDkN2@BRޑs^wq7O1agvUD}>Eܰ^ Z}&_K. _OҵtxMWT_}VRøs%^$CfGKsVEXȬ;olc 痏hCL~~rZCvϹPsyR&o`BI\\ס&Nh %pfwN%L]' c;Sw̪#)uNuI=\g":\oX9:u =J1Ş^l1*m{|}[$wPo\Y ɣ9sh)Q'ˮ٨2@ݾs>^% R7疚$l>/ԃr3 1AQ:6M&Vϭ/eCqѩVBFϨ]=w5U;$,7kvbL%8P \ A41^_]tLwgfo_A7ef'-}r+Q gP3ӕ" 1)^=n萟^ˁ:*Ó yt9@%cSY&9g?ŵG-+Cn89 $xkB&AN(LNg8Ӕ71KܬSgx9n̟qF~x thw"Yۆw?4nRx_-Q:̰m  R-LJi#Gq:sypVK%s'Кz,}S,mg4ou,;E7]Y߭#WK :'rŒ&jMs Ӆh1{4z:QeB~4`ɧ+񲋢A]N桛{MxFtsRdoR$0lҳ8}883ʨ/=;a̙H3Jvǿ &?N>&-kzV$`ĦFZ֎HT3”k%NM&839+cwc8D \Q&k9#;p1Q#zfs@;N}7Rꣽt(LcZ>Qy"[`B1J*97% "9-r`Pq>}9eBꢊV=Ъy \i.?@M?l=TeP&sD3QMOuYN"6V =ᆸ^@Z<1Yy.iq.II[}~R *e<)bFD7C}w+acG\lȁeޗ1ߗlY7stu=@xÓ HG4.ɜ5q\M:Th.VkqjGt0`+`O6l-F4W  GsRڼβOXgzkx𩄆˿rzŸ3ef7u|eӀR@DC%\2~WVᙛi%RSg@I6;^Ʃ@B(]P2?"^ h ]-KhOBciPU0Bбl#'TaY6'| hODPt)Mrf$٪L-]ؒQdz1g*RV\xNP }b[(NA*VG8xqL%S<=A;UB;77}gIf[b};vsc,LX96>,;z׫3Gbނ / Ҏ ,PVV8REDCWStUHÚGlD ЕGi٠w)άht+xH_UwXy8(5\izm7^;M3=]\1%p{IJVI `vЎAøo*>K'Zî9GƬJ uL~a* 5;5 U^)2>nq)}+HiS6C+6;q79Ol0܊qF3ۥtO|t=]z9Y쩋`9=]jqhBjd=toГKSh g!/){2uU{"sV!ʳir̉r-AY1rѦtf6-i)~Z{ٸvk ûiDcU nc y?E}$׈}"'5+qKzדɮvEoD `@;!wu,tZ 4(E:Mxˍ%r y*~3h>CSh6H-48|%I5_q$g eiC`eſ$Ihq%| V?Ji\1]>w[1"~OK׵ ̎`vD yGWZd: hjºKKy7 ɓ^y+v8F49}1.F+$MW;>d:ȝx%>~Fe>24 ]`=+ {|;/v܈7BɣO~Ը7GNhqYzl$ع+EK-i~~h͆myUyɗ,_yMbbCW+i> i0YyzNAe?ftlf_ea"3K=?CW.cf2S;ÿguMQHt#l?FfTA T|Z:h{rO4r3[jP1$V _#cu q8W9h87&)g5#r* 01+IÏ}E1 GslCrƤ%_Zgdƻp 9F{M;'w Nb=8L7]0㞚B!%k~c9n ٨5*JӔ37 w-i?HSG'o56]o)umfU,qsP"9 u21:?ȩzK4ssM-_5iƬ£|se=f{L< f${)$vV1JӳԾ# dqm4XO6K'=as 9+]`GEj3԰Vgoڮ^[]L v[o١Ub3ux&SzFBdm$s ~¼;q mܝ0Y308V#Y!'K<VLZfCai0hcx>Qõ[-+}Gkx v!OpC9`|m"4 ih?L'QRTfRrIt4 *;r6~^qMz#ӫX*)!:~Gg% #Sgbn t=p5/oىuR4V0sfCtVԖ`#/m40Ӕ͗o y&Z R#BgBHVI/-LXeRՅP-X-5gaȄҲɩRQ|~ęKH_`F?M9K8qn}X%83&YK',sG_`zjiv K`I;҉_~VVA@.J٫Z%hR(!~s>:e~f͊>K@]JFz5)4ZNY{~cT v ćq Q:F{Nxʢvj_"`9#< M/.d<&ΏV>fbIj'~,n8q:GgK!ajt]-xR& qҮ:>f@lV̄Z}q?!q/kb$.1B*$ `o^'Sp4SVCgƏsVKf婋Y*Jp<8)#&i`PHcqQ'f]hoaКf\33&Qfn7g S [=%'٫.c%ЮM7f(s 1ra_=ѢL#FIj/ȑR,\&X;4~&C;>trV>E NM~,ZR8iͳrĖ> i,1dO>Ѥ5/nx` E"ްuMX(4$Nwoz_P&Uyzq>[)U|=t+v\Ldߠ#+(pپ0s;EgclȊN}}f Fh|ޔ92X.W~_(ELl^ 8RY$U#A t}D髄3"0%0e]Eߜk*ZS1vk]6G6fFF EpH.~.Urd:Qc =,y3a Gې=%T~qc.4[Vږ_dK)Z <9Fpb 5\y3zCf;:BgI19eTY)sx4 sEڳBMK9בĈLCa[㻺ɰ-IR]v}̚= MhW|)!)%cpX|j]`.R;+zvWCM\h;zF 7 \vؤqGC=5JbX/:tP dqiNNBwP(8Vز0a ?809ۺC71va˰W56͖6P׋:FQ ڤ p's>I*&O(xLD,n.)t14;t^F"Y5댨MrX-m cNjtQt.M[j`N$[.fYTȮ'Ǫu5qqI+Ś`tu;Ɛa~*(TML}QD% dXG9Dl#+:E':ոGCnbwsk6Ul޺Nˁ$Ǧ{ڽh@ 86啉}4a{<ݒ"ipsԽrgpyi4,g7`CozmV{Om;tքDDLN [v^8b5r駋K[kh|m0q?qQ&Gһɥ7QerY+DR#IA/:iާT4҄t6}P R*zvaȮq~atN4|+=%LU/A.Q$,jeQ{Zp /<p7QKJ [c7dM :&,.b C6Se/DtO&׬̺VqAKYykI=a{tn緍Vo&@W1'lT>)S AZ@MH7yi$c('caFgb|mF),;-M/b&]0ޢi M#zj` 9;"_q:*]GZ)~)7xo/a P\\k8ݷ-]=k*=ꈯ zJq!Eл86aColoEdcZ횅Bn{rS^cZӆ=ajQIÌWP @ʣ8#_ޟ 3'D70H:2y2cf$uuKaV^$Gro!x"5;rۄ{ i'yQdh/f~Ϫg#B̦"i"•wI(Ao(n r7dF)ma6 LۛYk.dx>Pʽ0y}-̄.æf- O6Afܷ.PO p~wV`qfbM稱YsYZn%9\tA!zhVMu,F3.Q9Z~8&E^~>Ul<~.D#W;Tvs=V"&rUdOYcI΂u}Ny(/"s8vuXZH +gx:8@ڬFf$wO^ܨTwݑRGg˚lS?B:$f,4J瘧3Dl/&{{YH4˞ m4ȯj֎ 8T>u23vDn~,~w)/_κLM4InZ2M>q}~nrCJ(1%Lm(1tr,NBxI0Ya ]lM]q@u?Ga7KyʎRAgоP.ҏyP+0b{VO"y=@GD9NPOT!oСY^tK'zDϩHc#]وu~졳 qLK.QM, P#91E>8o,QԛR,C<6[QnVv]WLh{>!qxr%Efd>Y%UT9L8P] >zlܽ 6mw*x[q"5֤D|yIEt$/p;YϦeîxX(z;M1=@Yt# C,]dw }$"H?_QS&YnDf\Q> dAc%F,G?^gow a%_*(0 e5`6g ]^Mev٭|*k7/CΤB?U!T=)yJ2( 0EfQKvGĮ0ꗔI)OabWhLFO@1:yC7z3Ae024K~<2Uz&wQ^D:-ZE+ߝ! O?QSf"8a9r:IUOYodɳ Hîk!gG _U{1F;?]5tt5SnhOۆpd›Ej(SLONsיHw%MK9=0ҿ,mA/e^DTz <;pv7#P c4"G*sU9]{2&W11y;8rݬ^g`XNy $ғ&/]w%VNْ>+u㏐ ڜ (8s=r Xy5yI&|Ca|.Q}(9U Ҍ_v>1C֛$j֗3l ^߷OH#+:H9[3<)3'&y>`PA#̌8/|aT_48a;p௖5^yg-k*2]l3qj~ 3GQX(E=K_)Vs7˴n*f¢R&\tCCsOC;S`6ߒ]sEpYSd-5~7=Zv|G8 +A:Fx+c4B* iyþpKE䵣_k+x x\FY*2E!>ǗV1^RNoyee %H m%6 UM7Rd霸cF穦G`BӰ_FVR)ǻѸNRuC̦vU=e˜+􅔩ՎwB#$r|Ja5]R(zH aڇ喰(ȇV ȑNP8=78U}lq[u'&,NuQ+ j634܂geՙ9֖>/iugtF4ҿ@ w1&E c i$ߘAQϚ]с{sHG 6뾈to)WnVF~=[T_|I$xbu,MX62{:nJe~ Iq2@o]U g+ك5\J4 sL e~. 5C .KGklVzٿ1ڻǜ_Z3u6h׭Oht㪓MZM=wϪXdV&/Dh/&cTO:`iNjv_ r: 6~{ġ0|Df͒"5T׎Nu^ѩY:ϫ"0*6!:[ȣwzTI㦯؀BTXmbyv䝾(Gώؿ1Xa8JSЀVxufZ%t[l(_fZ=M,< y7A"gGݸqQgj,5!^%zcr.w 9?o&:Ma-dس2,!i\iC|Q_ӫŋGf]Qx}f,Kɳ얿3woiĖihn>*loMb[Vwrwk0;DPj]'=Mlx 2u3~_yBćS?ch %o k1H+[ONDYfNfe#u'L!g2Tx]2򰨪:$x6T~qV"#{~>tk5Ï-dUҙ9h)Dh֧ wId!V͏Gf |ChL1%㉚ !'ui{(\I(u.Df-<g\m2akY*s/h6#ND@q>xG'5+Ү5c'?J$iS)Е/lPԯI5ͅj%\l23qNMhu/VES3sD" oɜ<՟?#z?WNsXk am"ި%=zw70+%:Rwgjo.PS@s˷"qy&\qIخ#a/= x24#1PXOwz?cqbb.RSlB-jvyj|qJO;L-ngijGlB7A.dC6 ruq6t@bMk\Mng/$Xl|l)R0(rp 1]"d r ;sk;J{)ʟ[-AeOihox0)Ajohg0 J ]˺scpˢ%@'plHe"Y#QtU=XsnV={y`\SD-W-H@Psc{Gas`&jjxPCpڊ_^#WRϲNwTJe ĵ띅[F@t鸧=ur?@#s`΁ dM$.< ,BE+zEjvJ& } 0hgCՍ L7TfF;9X[?n*o3k.ExY*c7)kjfQt-"ˋ!9~z}xs!l~ m7Qm}ӇM2@ YD0͊e]z푣~پRb({>La;Zl:56TUVB#Ś}l|&;-ȼs$pwG؏)?|- שx_=ԒHMpbUX/jRoO`E㣓T+Wq.ԢNW"·3?~ se7ry*}FƶCd}> ~#׺uc)2/_hedQF9Kt\^b@W&npC0˫I>+˸mѨ>0>?/j|.aŜ+^ζD{Smψw"wR 9ީA 4W jj\d1r8Ӛpfup>p)wXgijV&Ͳ&w},{l̅Υu\xRcwRnmd~4?xzT:E~%3͌mfLmzӿ^^&[Q#S7u^z\l͍>!`@_PU6!=j|A?5n(_#|qCK=XE}-W"JG=C_*:+q,0QV7UR=x{YL(k 8 \p?`b"yЬ|&L^7Q(,?&^_d!w͝ h gSJ2RY*~ѽr͙Jb|UyDKG@_H?Sjg٥tuy͚ kx)Fg'2 h:h\ى|v~@B<`(GjtqdHϹ]˼NbSG>-Z2A zn"͙`2t6C [V9 8͹$,@܈w> [>V9$N/|t"7Η0_7jO^m]=._wrwr;90qI)5=vֆ9L(0=N8[xM 64W`գow7)a$FӦ偳DVK Xȃr".bPBZ'g'[kDzOϰez&o=!nM4KԺUApb/(`3\;A)Pi1 :b"Gz"ڧ9NfduD Q>Eb}f;<euGmwS[I/=O_,)REQ0C1H`Df@%1kɠQvJ 1ym &˄vVmΜ7v~g497PTw <^2z'/Lq-nMe.EU땦H'a5(83zetQe0jDm.W#Du2hJ-@=9;B '3Gf*PJq"ҹ)Դ':i}FzAYly ң'@?J 4:5X\ܤ؜Y6ڢͶ6mh-$"xF<$*.8^̎uxJlr_Y,Yuvv*~$Y8Ba!Or9B5r O~B`jdKGKGO3.M\^ϑL϶W-T8 %d)m.h}G3qSO6~iGts'"g )@~RȋuL;66n:7v9D~YAك֏X8g]R3g _QjHxxIWgo]Xxx% ^穡I(&a16ce Dj6!Xh\u'MK$q_~b.5-6u017.fR/ ;1}zER /TZAB>ki$]'=Z.͢X,K\}tij=TYkئOi L{jeAeKSIOsc]R&ʝxKC!EdH" {7YR%=;]:/#BҮ8qVQ@@W#j2GB7.E)s̟e`!rb6"rk e~GYiQ$Jnb?Ğ56j]Riљ %0'V:  }*yͬ|ϨtB cK:,$$Tlm;|l-mtF+3pu.4HMtfHRN7+!t]O,C}Zu C5jU|P_E*+![]i)~|ɬpz\wPqJ&2{3'dx$)e*?I7Ofiw= ttfΖN_|jpG}37kӐzҠmW~:CӳFno)s.匶:4yL+|8Gy5}h,++T+c-#cQ#`PHvЉZ,Emʞ(4G4wtc6ݮqZ g>Wd= nCmR)w'Ҏ%`FvoM'$xڝ30WEVP{|2/HsfZ=Ύ:5ӦS?FQq&j'cG{2سfZ}O5YsGY%M_hB)YW }G#13};$fӰl"^u>h~JR@{PZ` =6嵚{Mѭb0o3QJiVܲP&֓u6wҗboF=:x#.LDcLlJ-X $g }Y+xI Ze/d`ny|hBz$ݪ7O.F`NڌڹwI#52NP\Y&Ei>efmDqmiB%ڞj!X(=$>}rqw7gtW&fMX}e8@ :u7N>O|ҖEwz- MnȤ5iv UkS1s\I(!=ŧG%-twʜpqbci+8piJޥgRUD*BYz@5B?hx-pDUfY9x7lɻdN.Cxþkoiy8{29t6-cYP3KcI&z&D[Ol9/|AT1]r6Ϩ2sBJ% k1x/JAtV~6 Ktcӥa/]Qk~yJ<In-U^P>d%β.^nn%T;w,"_O;9u|P!_lpx򻾾G*a܄ H׳$?M=<#+ljG* e"TJ0zVDD{\$>FFѪ"3q3ۧg.!=DcnyQ NwTrYj%iѹ:o~ԙ?U@JKTT4 8Řgnl)ߣMʟ7?R}xG+j\?@/.ux q&Ns6EuR+ɝcsm49NqxϾ+m+w3%Rp9}eӹ*$)·@R>~bQQvj1_'SsHK_2r ¢=c4{d˦ =a3DlYbե! Šmg.&+Mh/ImX#j22bV, , G)M/Z{+v}K}>z<}(Q5g) /h5B,@ftեem(~a#oGgh_ e3X16:3Q}/M ~{6xSe"̊gVƦ 'N?tlx+h)jһ+dtZHR?.4;2-[+Jyz#0j6[|]=@xi2. >5u˷FTCݦ#IƚL\^n\(RZ9TG` Nr#zÔ*dǛ\\fSa3^PZVclH|kw}CêMUD/Be#͜cs#f+l+S6]OE/yXEDz`}8}|k,ĺN7/me}6#GHkJhzg=do<s;-Tn3C)-rX#xlfi8MSѻb;tdy-siv XgӝԅejeʄMsm:۾@(Fqǐv-1W$ ᝿h1e9zW糄ZK딛/eX  ;Aq7FnGc@Wn%W"Z##8Ḿ8doad(E76_eR#UAt[A4'z6;}gg CRѴ鍌$:%BӱmS4 }\Z _.bY7mII v\`4 PgP6{@^Ob ~joacF?2)`e  .Wf_4^[3biptfC@ U@U;A& mBVq&$.NXȍN }‡>RߧbTXdKGeCtUbvJ$s#܋rԮo){!Cg/-&~B~78jhtGP_C阂?eڦZ[g6@OWT?e?Q bֲY'ߵ1΀+ENuW(p8;+>ft_2xkH t" M+S#|W-:6mZ4^]_\oH#\BZ3eN(+q' ^We7^XZ B ShM!cn:10:䤚x@y6Mz@Sa O=y2;h5ɿ'֙'TȵE›wy҂^ }Eºp8ww\^4K>8FZ=lǩǐ)z?Kiyv_>Z+2#Cr䆗H; jpS* 7T.ki^&f9PO&9ޖ]R-I[v<^~KXIqs>C٫f)`rg8Jvel7n2gNܻF?ܿѡ g?+FZt,K;fL<=č%^+审!Gx]y̽ cJ[|6Zy~3~Jf u:eS2uԖdD_MR4f!:[Df\bd$GeBRYҾ 5A _ZgT9ue=b=q |ɜ(@/qd6‰sQK(رWG(D9ϕɉSNdj_(7Kf&AI~ArRz1ȗLl~UXaf qUx4 |yИ&E3:L%4{ T!}d 5aqxw>5x-'t-#_.r쌃~Hf%x=]09Ie uX| -~Jw`%^Q`IJ=p Ir)(SGi4JSLpJ^*Mt6Rm$^Et{0; tAݴ? 5U]ie"+VpK`Ip92Zyp,CM^nWdڪ{ˢQgPHt MQm֮/!7}Fc 2] R jp90 Є/;!xKmE?uoG[ĸ+0l&ƃo"/,!@A şSQ7gzv G'NbUou e؋-ޟZe~`(Ou];o8D}g9͒s6_Q0v΀rQV9eAˬQkΙ_%%rr?%tq+ V7b03C"СSl*J.bRV:lΤ@δ@,\*#)J.;;CD| KZ* g HU =3_r8יЪZۼ\~gK=Dr>v'c!H9n o ESh)q^ Z7_7znӳ6< N9Pq9>rW1tb(k hO;45.26։ZruS(Q@;^~DV AQ,4D5h8GFfJC'ڞs7VSVA:zJ th1C:K0Vco4~4%~j lzTū&M4>3^QH'ެ^ęS(0!u񦀊,.:xJ 3%/ԋc4/j$S^d7cȎdƖ:)ۖUG%ӊ3ɤu𘷳OThP=rxIP#ULv&XL yΡۆ.WEQ5%4HVBh*|{INW:~VS6fN(!@IV\H5YB+ܙNH<%;ʲ85lO/#$_䩗DMgA#\ *pɝдxi1/z?4buX$hYp֜e-q`e}2U 1uSǍѕSd kya%ػWn))d$$'-=.g`_fW~]\8,~b9e{-Mr1-ه,N%〚 q" mxgFRգգ ^Ϫ{[}V%ϹK汲1 XZ3t d#n` pKad!EP4pHZ!( (Ӯ k#ڙ{x`Ci4G T̞WRRb'BRv='XZ <2%[Ja@J )߱ r1MiI*T“/dBđp8:Fο46 yY-2M {A'NS_nҕ~PYU1EV=Jz.9`_+mϺHe~$szpcnL55'YL,riE =MW /oHcYy8DҜҔ~M;G.R~Bϰh>` :7{\2(#ɣ9(/Muo.sNIxg8~kgUrJ9$o ?uE[7^u|>K:njlᕙuxˢxsHG 03Cʛu(/vގr>fsR|L23zVM._9e9߬Y6zKe%UY:pt$yyTF++be2€X*HSY)arN{:Apt[rJ04S>А?:y-n y^eCaa{&(H-jXN Y8Z-7I8<,pRq*Ku<.ds`f7I_`}VG1E9_wh}ާ;kY':Xf%+]Gb tzZ4Y"6C=`[tokסke5e%uN9Vɞ y6}fX;Jf p:kUl4:fC^QBӊ5Uv^-?u;{ TxhǹNӠ*%ywxhC2} /TqDRJcsO .y0oXgX}BT\nP6xpΪ: ̀p+:02USޝd4 s]ޝ)2dא hτ:O,[#c@4mOw瀱>HDz?=vtܢ=x*z>ХArP3n1+'3MN[4_OX)yCtAWm8W+mW։fH굏H oE*h^K̖%gEY 6 4 tB)LLH7)m;!4j?+|5kx ~W.[զ"WcE03ntků&YS2%,P]sHZ:m(4^^}ABC Bc*sKfi+GޫY̑xiV 6MW<WCVȀwPPya˥&u"{beε¹#:/>N/Fak-odV:jd^҄pru3YRHl qL!/HbY' Hg,c0miNrpf}B(9Дz(u=(?y:%ˆ䜙KtDl (AlB [{pN+3vCx9MT9[˨|S8.Qu<@Ha%97;M%P=?`TB$SmKwTM d^A!Ѓr5l$o$Q`j봦eWv@塸->q$[3TY[+n"POV%c&UzٹxhX+h.І䄷(WfeDi-3Ӌ=u6ŧw.8~pTm0V ̀^z7HN֐oݡvf_m`Q̣Jy>^~}t5)k ‡ܱI*o߾[̺)0g$0 ahߢyռPL@X}B~LM&wal$^\FbJ>GPO^u $k榣\ÉxoM=@If8՞[D%+|hq[=}Fio2XzMKSikY1(@T29TJoqiZ=ӔXi:x-o\o\f'V@T8D%'J~'9P001psw' bƔMpQޚSD؁R-e''Wl&!nn>hS1Yw*O| Y6$EvjT2 'bN q1"s R;?l5F@$Mucn[pz*;MAQpD,8f]'̄&Ӯ.:ȧ]hfQI'Qndl@ Ȓp)R36;5l3AG"E藷"W펪LMU`%Z56,c;sf+O\޶/Nӎ? Von#V!y;hԠ5HG}$\45 /ҧ}m-8#s7I.0d]6!t]Xަ8So!-T@L Sal)jGq5q'KXʧTSWڧlO)L+HKGƣO?!ߌ U%@ҬJK t$&F"aryOq \s^r>®S@OX4 Ï֔$pfR<@uGM ^_xdKydd i$3P)/NbȔ׉3 D JCZ +@K☞֍/0/; UJUdMleeDgJzGHk;{Ê8oR^=[Kc`֪DNSc^5 t87_@E !f[˦&eq|LL\``>Fm?us8V4 k+x&ŽlSʋopf#Ґ#^ :rh]ihjhY80z X]r}4[%wt|ج Vo*b4iNsLr)OjuZi2^$8x&%5H<~Z`lwJ@Keg2޻]!P>!HQ z0lS"k򍫡H'lu_l*t2lt1tIV at<ې틥e MQے'-yTD@eHROD$(&7 6s#nFg rFXA弄KOZI? N]&#">"2uADX]uiHI.3[WNuKIT^g@:JʁG|iTqW#sb%dxBIg Рf3r)8`o+=Gx|(YZ'=eV|kwXPF׳V@ub=NSebVnv6eF,)Ä3e KRVd` :/=lK6ަ26c.N< p^ykf߰l`zAj U"*HIxh9앛Is5q%j}>H]Y/j$J{T `~G)-+v 5%Ӕ׮q/ 1G@}^E4 ضζabT'Jhmn7g.D8kS#D@l" kg7 uG9mVwk:⅔Эix=đ?!gjBTL HtBT{Olv/9 }^ x)FMsp64E-VVS'{]m%?n[C:[r=\̎b߯7|.X"(Cʮ.Hh tF(5:#M<+|oF8?RCs4EƐTa&;o J@52-U>oDBɕƲ_- B# B[I-zHq/Rˀr2 pZ.!M8mC) {?=op Vn5\XʷeY o\:ݟlZ=㋁⋼Ig54"kͱhe(H-X^RYϨ]bʳ|R^ ZD0t;?XIn]gNUL3״#Z, /_v|K K' ?wKz;Jy׸a5eV(K7IYGyBɒx4ݑ0k+NzKO"YZN :Ōxj3?)x î3c3WW7e7Ѥ ;?@adu'DT5*;b9g l2"MQRQggSa #OiɥX)qC#ߙH|2tS&cTly^j7=ZINc''+ZȅB`ƜB_;SѓG#N8$Zߟ/DP'B *fFQM&"}! ʹa"*qX/I5Ux$˝ w;KG_OxmRAtR4Ird$ ërG)@_ $@@bRJ"1qVK% i4~ g< YhR=K#fy41>ӥ^rhwK*x"pQ kiR}a3GUs+\NwE MmYs6snmځ"r j9 ~,N~o0}2j͎̔I;zإZЅ L~2;鄧 8YK(? wy|>ХY,J6nlZt)~: K?>M~o^&s-`tvM%7 eGSN[z~GDzP+Ec+`]e1:a.<Ҁce尖Zr~8:t/%OڭhIq*.>vڽ`n<%ĭFoϲ։t_Ue̝V{ v[(ڒ^!Y@Qp58Y#Ekus=-Y\>Jqϝ YVbZTjC\YǴ_8wt.0T ߝ Zώ'8QZ70'qĦ t\?B!.?H&|~ԶbIoObݗn;z8vTQP=98svsoĢ}iTJܲ BŎpD1n<}/t+Ǣeř$)9kI Csnv8K'TYvobβZDj2;9 tHJ{HaFWM7A0= .q3CKeNYǩ&Z-iHEzW%Bӧ$IS´N<25o'*|fh g#!={(/bCQN&ѹ}XǺP5{#0MѰi=)ǕR!/` *^>5_#*b@KrH{ӽ!O>jQGvՀǀrh{Kћ[B̖A`4F'иbe.M> )̩@@ 07avE=!mB&^R+ddd(H@eIʾ=L(M!yMu3MG>mO,'d,jާ!+̞;oV u.0P7O0]r&nәej"[J]ȔRuXN(Q*4p:D&kIR W2I3# oG:`^# }:-؁ɤtR0]j^wbu8f{R|H'ȅ7dGy A#<\s~?y~0HLZ^46K &@l;WaR+fĉ37'| 3&)6SPz!5Ncg F/6궢IS$i\Jߥyem;U#NJ(tvLb3i+YAI 0RW5ǽ-!_;g"?Z!GE4uکt"J$#ddlĀтd!uxӸ4>T"^6 9υ5i!qijM:byJtY7vGoӨIC8oN68#!m+h0w䂁lssC`yJ(KBlDLF& @Ξ粕wH\5؄W&)P%LOXSr_i,Bԁl9ܜ ;כnA-/Yb,ӝZ͛x-v#А|FE/ea؏D ( N[T4;[̏ u{TV ,9"n z8m_g)?T><~֎ЯH~vJH\1kPK=;-3{3lO {XV*,Ke43!Ѳ¡^!DU\!, F-QYQį|~kF& OG*>zۏy3][$;Lyw1u2g>/y6V=ܦu Z;'[F.; /G8\ChVE7O~B jx^&a˖KFyNw"hn~0rpLҎ0" EFUn)\^.*Yyd٬gKf6hP95,vk):t7oApn7XYn֒≯/rVYd2YJ2 :UV}d@\?`LjsYA9zYN!@=b_RtISWaֿWsf;3:^}Bz9״Bz+*mg`r5}Pܳ{j&6(?&̈́iͼ)2Jmfq`3pih,Ёmm%h7@Aೝ}H(:,Y3hR7$(\IE!6u jǢDc˺R|{jq>QN|TpVNSzȸN` kU1_7૱]e0e_D{&ih"~Z$CXq^O?T}CS/2njiM@9J(>%ݙP+e{M6LӿV&9piRAGM?vӬ5R:>UPtHb-;D#)FNֈ$f84¸hjEl^uTh!XyHI]Z"a7%GѰ{xr֥'Iϻ1܏h߬UHߧw o*ﰩ%w=uvWB@fwfu+==|ʗ20n2;^d 4~9Ϧ5*3tǷ83ÆY=fTAX'ƚ$2Stn͙1ŬSۛDڱ6"Ձ׮b-oi RV~Kimnq 76ykQ)"mȔh@7',4bߣ1L20V)vpjJ:&>P"KH]MLJH^O0)~9rX^YߌˣΈ>%{iD6lyG(EBiإRZtTMQ|>ݠ kY'-,%x~3BjPٞ~dvK} };SjgY?R ]^.:WRgaNf^S愐FN+J`'JǙ, H})d`I}4$X;I:oۡU=!7!8kζ'ZogIzCCC7׭!NHdL]FPɒ_gw(j#AE َ50E3)]lǙwjfgZH{ίCe"eo5my::~o֖RabfVT^xBIdJ8kk{pݷ{cǫ3ѫM"#}t jʥԒ/zqdQm2㆞-tT]>\"F'!ļ0%{OXa_!t{2/gENӕ/'Ԧ lC#f wSo>VU̾~;A3<)flh\iH|51ݼpflVW {?nfC_π*W=q,0AzgS-:0UHy9;C~=^4\kN! Z⁙'l2.5D hо<S`Y8E?<̙≻<^_nSG_"6ut 6pgHSYI'ܠpdFxYؓ_ τoОsv?$Q˥x؂&Ld%Y-_ČpV*~οM=qy'? G~ӳӰRgd¾56dQ+z@ 4e%)I:/i(;p$EbB5hiw{M!n;ԩYWeAhsu[Cz0;;xs )g`}c"&Ityd]J+LΔg8 !CX-?c;I>h;bH:`$<5eH ڣKz//JucI_/xws cȑDOPѢ,x *Q@nM/oMgduK G<^nxG$[xu){(Z`}% bj±h(OXtJa?U^.‘}<;RZbM柟*GBeEks);ͳKjȱcͤB`O|/ e;Et_rd緇[1kvvXwEh6Motx \P]z ͻYwd^}T>}{uH"Lo~<.'ēގ*ROoJR [V'AmD#?s5'^uCMWwS:*JFU;OQ)$eiP!Y[|SL9R=!,:2 6*7(ޥvP^vGKQ>i:Av?!!_WDEUZ66a}ݲ^НX8k9HR,"cDf w^F;4J= OŔ1#YfҾiC0YzMNfe l dW-}!{3}^^D3w-vw'u?5)'e~*n{]'".+Îf6W3.ṐqFf!:]687nNҩ_絶 dz%IQiu  ޢHDcI~D(+)8fnG'Tig*4$'*71"tϒƏi|eZyl~8A8^QyEcىSC1fl~B07fX~a ] ሻƹNg+=Jzbnh`teqaUY;f]t~sAo;I#_D^1l.P.*J{%KIgvR Ӊe]f8ipӷ?8X|#dYu uYB=CD_X&ZCʦ3y&x,kU<4֨^1 #H d~)UX.r;LGa;'Jl:Zü=]{^un VXy ZIvWtxMakf>,׏]#5/7laJ. JKbN+w,~y##|OaX4epQ{Qf N>o?lm!י5,l])#qɂ8RnƿY. Z6*]]' V3dA˞*W4sR6'JG)GLJsҹuS'Qqz};Z%Zw<-yޝs2bÛzEZB'gGy霦{FX>o #bT5^_CxWnsl%t[ll>':EizfA{5C. WXWtSC{xC1$,.x#'o8l$&:V2bt˯lȤt[4{v˶Ԧn7`^}Za"PO!|f`5Rs:̹ #h,AP2V/ǣZԎp҅ʣYttnVtOh":])ᰖce@B@>P;Tf5Pn'Þ43IkbviS>q|;#s~u3;jc1jw9{qfGuOhŠ53u:g~Ku|"Δa@&f~;:Px'SiX1&AmHY﬜d8@5oQ+ SPwZǩ|%e:KyO? {plܵ%GslK?Մ~2xQLt?|j|,?B"r>=v<<-Cqo2%چ6?(̠y^frʧ pXry]Cr9-4kJYp40|/R.?WA`/SىN2clMX]vvuJtJE]|L!<GSm@}!> /|/T(-kkoz##8z\iYf> J5b'/+5@mʱ5=ڰc"|t ju vhL`Ykb=NU ݲNrȤp>aE6d :cFFgV' 3[/xY'.]zIK"Og笥3{n;S'X8 H?v>8!.ȫΐ}.sSĉ=1XV 7 =;[)t5f+zDzZ1s8a):dFΓmNoJ/b 9"e-a8kD=޼ct|\LzwmK`u Do )ul-hy(T + ປ]Oc8oXZmIoO}TZ@& ЃX>o\֚N̊uzDm4,cKz~ 'ޠu&b2zs]+L}'~'f.Ci8L?l`>.ε'OJ9s|\Vw ^Y)RZ4a S_XA3җL[z][K,@\'Drb-FJOw4+kPhTVec Jv/S%s -礂/sYRN}ԥ; >d'EH: Da0rYYÛ+CKDeqK&.id`Ɨ"~zd0sů gzIW]>oMMZGxiX^V ,.Expc8XEJ2j(6e6,2*.LedJs=~Gq^ݍjCh|իx~AEhgr-%<_nnnRA''C.64m*>ЦĻ<20iQT3:I7{۔`P乬X Z5l6)/`WN=:gfW W&ަ2D(Mehzr,ig ÅE]Q^)nDHex0z/?hpɛ#'}cWh8#qX}5ETW;=OI+dO 7HINLNu$XJG#$H{@Ѕ0qwܒ8cIS= DK)5TieGBJxrelU#4v~ VOY3RNz_us&^M);Dc/$M#SgyT\#st8˷_ٙ[ekVL4-Q?`A'56% q>8#fFr`yg_y9pZw)ͅTj[,q"MͫY@ -|^7~ !t(BmMqYc/ةEt-rn+}u agm=p }pDu4 QYGge1Fb/v ݀ /ĤMOAe,'.LTٙbyqP%0LQDL`0aX(#^3:$? iBSߚIK=_4to % e2 e `Bwi2P=k*Pͼhm(/or_v[=3pω`_$@,1K VTYΖ[։Cb޸>8^T Jc!C6 o'uR?QlY 櫹IS y>{d/?ΥS.|aҪ&>>#mL^YOd!i _$X@Y Gny؝$6eiG=RKQ?ȤK)!6,˜uAa##$wTZ?'pi}D JgSY;qd)ӕB( X'cuLLY/{i5UZ GpOxLOsckMcFJ1mZCn-u#wdĭיJXF^O$>JށNLsJQ=R1Ezy]/hb_8 Xˌ!K|gm w.bELPdi Mm,^ՈR"E}>rQӳTי;wgI$%5˚c115B4ilDZ|ۣ(Iağ4U2YY7Q\}^zc;=uo-G`PMc)oxR@u dֲvlUNy,fŒjr>=wyR]sw9-)7R/EΌL[NfWZ"cn2׺72/6Q0̣F4,LXNKMlKN*Gozڎq_lo0PV|>8e4?i3e+Y SL3,-VuB[|B:,RΦҍ}b%ȅxozc% wAH+ I *Yz{8\e^N8ZvxMMl%m{WyqEaf>b5y"܄4["jo2YgnIu+ɿ0|]IDAey RއW~g /8tah {+N$/ :L.ȼI\JvJy H7Q (̓Id#N n³&v,L0Wɛ)Grsq/|5a  ɆcTFkn7޸,z~kWcIǂn<7kOD.JՌ_M>O,C1Ap yk }^9]1ՆCP fPp< (ޟF 8ăٹٽ~pQhVm%wb3ݪ|/% KͰĪ{)_D` ]=S X\;v.7xCZeQs%Wh4C+1; Rx 8P{EʏBG$;[^:UBJCQd~rPtuH_$+ҹD979Űy|9pƄU!k] %uȌ&@ mk5Ǽ.NIo&u<tMFP=GØcSC“q4Ciaq8Nea2f̬}ٔWt.IuƜ~\tnI'c=[Z.#"h?l$ID|XߤH0Z zre2>T* =onmJ!-4NB~mN.[o^KW19E ( Tuj[t]M[7x.63IkE_c.5'u0۵;+\͖V󷖶(*4֫Vѐ#iRqVG># I!TC hYfYH7e; ݲ# 'd+ o8/l4g#3f+_VgtV |:X wY& 9{k.0gN<ާHH L 1(fmt KƝ,ݢ1{bH#&']ICB_YIv>!$UtVPɇg=4]ArsFv9y$D?-)p)Bf`6uM;Vc#dKDo$&m؊FE,6XAo1rXN#"M'me\yɊ%# E@H^T? t+ߵcYQ;~w:]>DrOdn;i )4s>QSniFZE E6\iO*Xbv7;~L;,Kgl;yQ|)ّ5c,};KO"M?' v{mKK8enԇF}Ɏ|to(5j^*4B~zʡCx+M*Sw/7 #3%1TNN,8y;(:?El4h8 olMWSD/PQDCAT~E8AdF%^S4 î%+裱$=TiP :ҝavWë_`5%=/OXϧT'cO[ǧҠdmoRKF%/h-%4]o uysNM^דb)g@Vv h qM\0A$(t!}f}I8hL9|nũl3qRa $sw jw-!'LδHd]iTl:ñ~VґN]NN3&Eevb'^e/Л'9ETh"RċK?t$SF-SU_+v ')>+=,Fv Y N^B[2\?yxΦ2 hR?q!eh:/李޿B'륊g5{zrS9Zh_@Ɩ둪=YuC7K;ba%,W0!tŰ~;1Ӡz6tVXnx"`~P(<'y՚Օ~KVBS:i/@{?52Php4,tw  PU 7B0!6:ye'p"7v"DFRۤt\v4L<z,S'gWf:KjT^tu"Lb&{+w!&nʩYƣ~i>ݮJxxB;J 32*O@Z&>w ,ap,N7lq0l823bW1YlQC ."l0op,|>YouqbrCyg==0)WoihŴϼ\.>vPo0 1[?#Ԣ Ѡ `RU[әD& "al c 0Ԭ;tK20fF,@S9 aGN($PSOg=uXh.RXmD6j 13~z:f*AHyey9rA`"Ӫ7ܺSMCtڑۃfi(!|tfd*uEb :iSRXifk{z! ͬ!pě4Ezm1υr ^QV'vʭ#^C|xu2zJ;vN.UTiF=fO+,t]gQP%@Vg."JbMR`8p :D`TPUSY59aW;/1 )(,X#xs"'#XD lkdw g!NF\sD;09[SNPъu:φ{j˺ɜzPTPR$,sJNZ. tgz|oz'$Phʥn5?NP-+혨d)ʊ$IDH8JXlgg\yۧDi' SC8~f-h3m:ȱ~|'(4^#vvI% @=,vuuss40+(\.Sb>-+,qg]4yb%<_Bj)JVXay=;K=ƃ?`+c3Su v!|~9sJQӛ$ >EHpg;h*E=]v ړvNUogc37&Dfڍx>|v`旚]Ӎ|S u;o=$+7릿 %.)?ą1X._&rƾ5f @ZXΤ[%- lYT,VǘdWTJ ghR:%+*%}:3XyְTUCcKWWsjWf-.BNCַ8$FR,_8LOqlyNRQZҊㅒkc!k G^;iyFu}D yT;v"VF; M3LK>g;z^grndj&8Ql˼l s+|gg33 5s$&uLH|aLgn >G;ڒywʠkGw6c}ck5} w:qt[s.Ex$pʨ-ݭg:Y?5Sevy+4ҥcpo Y>kS-5G˒}HP·Sy›8:g2⍉')ه CV-+ɔ  gfpZESw6lK4kfg> \]FU ;nTTʩ-X}hNAzl:;[AeWIFXv8}XSߗ\Nfv)JsOtov`!#OC$%A/_u*V$~֏!H\W_@΅n=IG5"+ (c~-Tf;X}!͈bv$g~xOR^X`(Z$H*H4 2֔zTؠFxĖ+³V],ڢ}j>eç7̍9ƩI.kMSRY8jN]̢b6miwFhY-v ?`<eTqkx_Թ^VylTQog8tx3k2G"r{9;Az_N5xijVc,=E/ v^`_| w3ҌܕBw s ^GɄ~:~鴉Yq*?;Oi_zNs? yf;]X^ML|a{C۰]iy{[‽>ʤ>Xvf>ᾟGYNLErMf')g}3%|.s x:kv Y>:‚!=CjY!QαZyʮ6̛'0/G%"nd'2ܑG#w=g53u٣lc1= աe򹫑dPzМv.5>iBVIaA869ngEV,1*vU2 cPs2rKfs:I]G?cCU=>lHHi6K@3tGQ~i76Wڑ8uX6}z#f) 26 }t!C)g-9>؉`Vj?H{G&+!!k%k %m\ ?ֳ>[X[CR$y1Օn~M>V]-m_KձMsRǝvN׽ R6ma:uX"bqUQWtBa,yiB”niXW0y3;w( ԇw(>:4z֘eQD5B/ k<.Ki[) i3*~^lYo K&/ۘ|U'N6V _D.:𛍟'Rv 0#ڂ+!9qvfY X)zy dH:K~\NKOV"ɪ /L5#%Pd2RCTeMVx$-K"4j >m>H9?éyIlt-'g5jyCq"ri Zb(:b<dҽnDk&]p&weD)eB򕐸WjDX Ր踁Dy2])a{ӽGѴQ,2jH=! $NqgcZ&dX^d1*i;&ΦDT #.sՒcP\ݎM Uu*4(kҜ@VD|:N ;t!VWF[ 7Ȯrׄg%{W<\֞.w r2\ L ȯߴk9kO2ڑ;j:D7{~^7 +V0'e1N`rD%=a2*uQJx :D`}9r$ J>jMŲ3[L݆9?ݭX~̔ne [s'^…H  siyd .xj FN'(2"?6<=iYCYKCqf>)rӰh!AR$G ~i/U,RpDYoQV]tz )6^pnh]}^i0n 5㑡v?/Ѣ(dq<[L䎵MR.VB5zIѤvب'UeˎґLRmp0/XEzu>?8y wTv&Gh7؜hLI|ZLcn3:&~7EXaZq-lMlN8m> )s^?ΛX(+Ѐo8Fq--ZQ:hgpuޗciP $raYtܱwh7bRլ%diX' &o~ j'2IG:+PTx&Q$ջ\Z{R#@5xKDeƬVobv)76QeXfO$ ve9P.LlR\+[3HJ%ϼ>bou]%DP ƞ(dCٛ&L{ oc;9멙43IRXlsBZ.%U5?Z \jZ0Dhk3Z =={%fFYW5tyvk8RkIE.~njupd]{"V Ad.w/6aȭ0V9HNbKj[$UcU3Ko7tK.;rnifMo<1;q)m6Y=+<j}4jiӢg)6gs<3C*zC/Q/ ݬ49{->rx=Hӵ=Ujz]WT0NF\9x'絗zDZح,8j)匦44 O_?Bqϕh)z\57ߤQegY)<430$`3˹d~ ѺDsđ AoND6y&--(vSFd2hef| p݂ߧj+ϫ݌®oi$5UAs9pC;B=JtZOYO$6yJ%멷Vj@A+ѳp:NAl(I7 mBy4Aff((l/ tkV9P6m;H9Ϩ2O9&i27%suFS|byCy96\IJ=ܧ,pAD8x:yEOvt*\ C T-7:J̾3q i(5ܩ8ykLv1 :̊:+xHfk]zD}yFe\aO躯LZ pO": vXiIdG@1tdH_gcT7+z^.KB԰PQVӊJjn@1r,,)$|~y8Wh- Ep@=Ka޳vn֚0zg~ID|Yy3M~F{5mΎ%ob9kr.3s;w/u&2Yz4dC]R[-Bՠ4i{}a߳Bv4KU,26z,KHB'L쏤z|%;jaSMVKdX,D$C Br֮Nml(B'f(F/}2x})WqE~Vô 9S")0᫿|qcb@6d KAbo IZ n; *_E7o==@?a Z*Li\I`{w~83bf߃H [Rz Lm ܑG>/-zZ%Ic N0zK{VLǃz cGB wZݤ@k`"_HAdt%X;q>xBY^VϪ.6quGjxAiUbn꿕˳ eOjrkM hlLfx;qPw ͎]wi%N΀3}CcyGv3xDR4ۗa 0͂nf7gIF_ nPpd4[t?mD8oR;n s0M8;7*LBW*6|my8sᾙB1y q'3zUQN4[%ߙJZ* jsu(U5]Ot ܎7_ߕo7?NΒ¬d? )b]{:HW` z (+޸\z*h9x=ԻUa9閺:,{(*:2!2J`|0٠A%B 3j6l5}u2/Rlx@P ;JCiʼn,m9jY{?kvfuzLբ^'Rh<47?di`:CƊX=+2w}YEz=Ogmw%RJƆ'MwqYTbs_?! ПWytRzLF,dxlGO@xNnCK1E$Es4ě9՛keFٱ)J6Wj7\2nH}ŸJϾ,3d\b㎮~ #Q;GeBG8 ̮|7(H7I2:qFFAMUf JeGa#;jyb<d~[p?V@%HenmGH"JS*Vy_NYbԴkY*?d)(b[Q!]@X@L[]/uz0-R bu])#ۙ6Ak[$J|E%;M;r,B_uG\Xu~yb_qrx8kV"삖LVy&ftuN{E:0Ody&͕xf)ځ QqOBCAduIwhqT]2w$$h4˒&80dN|A~1!f߲-[jag˦Ӆkqʪ!gEQwݠv=XrHYxB=VXn=͸|)N˙ Ê*ƖvZRiެ,h+w=S=d)<ɟ@&hb &fH ze8X,vw/܉;Na~mkh}VNyA˭q|j;v1RWkΪMYzZc.AG0B2;;#?w*̑=|7{'{π e^;[c=9D7Nf-먃HwmZ57 F\LdwyQ R9jRP[E6, 2fz1MM^RcB+Q=q+5 5@ ZX4gu Û x4p.Mx]9!`i zAnt44(΀ZFЅBZ5'f|@q6,m_@Pw[FC q6e'j9Zr6{Gp\jpg"MeOҝd>zLB nqZSI#~r3iVײNю; ((EY5YWGюJqѢաFӮKB w)KZNU{|\UyķӬd/ {ҥ ϊDHf#/"8cC_T!8و2$ʿL |eQ35 C{Bd$eNQ^o)@:iHJbNʉ/^urC{: UqXB'- r"n|$&t$q+#vX5 Riĺ(5I} ywn~(Jahx}E8͔MdrJƇnX/{7kA3wzt]8gq>7H rnBra˥N QA z1T`JڨSc"o?uNFG5"G *æyߵب`:!lq:|NJ WjGЍ!(+qߠ;J&u=J])R mm bZx?v>8~Hl ; = lF'Oy`2zk76=YVWoy &sQYʠ\]]qt5Cmrq`Qm]΀z]}@ܞ"E~Ī>PF޼@CJ c(E RArЛ+uxl4r5P N&S^ǡ/Hܯ%&c\I%mk:m cʜJVZtZ[~=f41Yy"M9!wQ{3щ}lE%4x(eoPHF'ް'T( ؖIwYcO_L8K\p3޷<MmD៵Yެ+522IW]F+ZB j֞ 04tϬ^ut23eɜ's`-2UX廙Iefؗ}55Bu(tpO/ċO1;WM/O)eԨd.}}Λ$;%ƥ*RNPs@:YMC 3Eg"|spYڶ{Y$Aaam'/ >5wYmBu'tYéHnr<;.zSm{l;>K\?cO U޾Q"j#YٿL+^CJҺTaF ˚ 4cf<~H*,ׂ"WCYvx94ebJiYK&!@r"_@˚uY&cԉ7bI QE ]$-DǬ8ψЅ"mw@_iS6/? %nXr]7YLJrR|hGNTF-=KHgIi>4CV "P҂sJQ%ﳝ/ {3ߖxt!Q3;6WTd%]Y[O75E?/]HG$WH+?[ASdB}7tejPUTG$sc:9lڜ5t?13՜5{] b.ӌgR:juQ(UJoN0O P\=Tx"9fs䮑ub}sk6d@։g ;7dEWC^!* [D-a4Qp`V (%qzOG~5Q'{]5q?QEiG4ӤSM4 iv89&!qRJt z}mXz:S#pƭA7W=9O0g@gYoW"R}zaDy ,y>5Qv$qQﺲ~ϬHLeOO)dJzC ~wcWW+{o~I]gFuؙ+ ~ R@ۂyMU=u'fECbC.zԑEԭC8_-34N-?9q0ՒO(PR, fY*-R/4 _3b% b2{GPw W!}%x J60T@_<s ʸXvүn$u#O \{H/L\vypesWMFe?`MJюڴHϬ=Q7Vkx+ '\:>׊0ʹ}7Ұ QP4؞obŦq"IO1'1,ML%M`MWPsYfD(`RznG0 :Ũ@|вc#?stqyo7\DyKP"Tc0Unan }rv3874Ѧ35^I"h ZC0@0Y#EmC1ۣUøv8k`f*ڮcn2 㝗JmB_)xBT^a2Ӱi#4P9{: cvgQQtuB5,b'1: x(/,Y=&g-=,N~gN4*гE{ٳجÖ/;/aSwbGĎ{ճg\}^5Pr(4 [~2ÙARj?l"s8J"8^2ΔC`v s+ș98""b3SWCRn""G“ :H;L%w8IюeuVfw!qD_OI go7V#o~b\̬XbcU&&pJQ`-ͬPO1뷐5 dzh#\^ LSr:VVZI1 r6ClyP0bxqHj{Έ|0KnՉ}>S0S5onF^ştGmq{SAyhMPIo߯5 o1KK*Vp豘ZNC9 z열N ZPtȜ<'Ɲ8v•ǁy鏘=}Hd"h&ӔG2>phd,xA ('aVd"r=;J332m\$h7tIw@ӛ+M?lI "iRAL<.R!Oig+՝+|"z^c)x!0ꖺUlf/)E69$`bvΏO#+ЊgDkYM$͑:)uDT]4.{hyiMOQ"b /ڥtOuq,QnK~7 K0*Le޷:aWSP " 9=՘ھm&U\7giDxO[/T3aaJrV>-^ g7sq&O0?hliVA,vEӣ-{hOFz , z^YZ:=DHQ#4:WB}/g^Uj?s(-d2T)~ K:)J_gNbuU'emOO\J܈܄%tT"^x 3?C1f  1Μi^SQK D?4Jd"/>1{Uf( BO&+:ҿʶc׿؁e-1^:r;-`oҺ_Y~0'4a|%$MJ 6lHiW~KZཎ'":aqQd(ԼN%\WJ찛)(Q̉ȼyg5bI$!1c%cpE,IFlWO(ˬ+M&u>X&. nyht2#8oʅI Ya)ӥHUcSUYxrY8VoY VKnr$hbx߽_t#Ι5Y=[EG} _h4s`7E:tޚBV قJaD<0o9-Yh|M8co\0>o\Y[_z_p Gmm),g /ͣ~'07"Mou猶VSF^&NK)tc;ⵠw)%rAH{'3_/?HitLrn}H %*2Pw)-p0ţĬa`ozY8N! z@;emZR% 5Y6Jq(J U^ET$gÚqgv\dNN;(/#]~³ToY2ț> |"@Pۗo9%F#UjΤ^5IxM_76O٪]PݔG5dnPkHKᬦ 70D^֙{ˍؓ{ĔIqu@Z yovZ"SUDiȻ.zi [bH5X "EɏOQ7_ք3~8GB}m,xA/ǕF~eEB;ls5!`euD飅ͬڊF'34D͚=4¹R+Q.FFf[{% bi?*W].~>3M )ɠ%u/ɒ}^`tvG4LN.g=o3Tb5"]buju%9JZNzX|QOܦ b/9J]s#nom z1sz 11)P;3qlY1bv,qPC #r4b7+VOU" 䅗ԛ׾fSl#V*F&:Oh P6,}]|°>ɱv }< ⹹#dHD(6aD4|oE[P-q^ rmyBd/+<'}i'4JW4~*{_ G WKGu<>e}2J<$pAb5$ ByjK Rh D;eIKN\Rvkmv"G %đ=Y{WOӃ[p~`GwiÜ[ײd^g =ߕ} $.nu+ /}\ @: ajWva)%;MZIldN~v>5kA6 ^SRx>QI&p \_^uS҇PsJAOEdA7heՖ{CLeQˤ,XhF-4M1]<~ pɋe.ei3E|^G.[)_G+RMv:3PXMe:g@/q@rc,oW{s8ROBwD`p6|HտG`##is7h]kya9a y0ÊM&Y'{pmș Źvݎ %Ms8ݭq6<Cc [7\y "r=2S{P8V&gzD]^.&qt2:W60SZ-IO3:ρPֆ{L@w՜ACq3 q/(Rg^Sx3Nq^^?M}DSͬ݃:bVGN(9v4dl=;M쐵z`P\9!h(OEtu? ~ _ u}]/M:Zĕᰙ9$Y?q7BDpmh{Hn3q%MmH`~heQ;G/Cm$[r/<'Y; Z [ V_\n(Z]``o( j.<]`lO`EAgYZHQuVBxy!HS-[bZZ-'Fr̋Cym3c%S&eщwR3γwK2{*P-{cU|/gsK?s: _u۲ZήDrum nt|yRR H/,p"ͧant@8V P_Wq @RXn E=9׉Rr2IxC{ð% u$s S3'3cMedJv`ml%w0>v~JX6cQ !ř0,6_F,NeeE#z*u/@) B+#\ZEeR }X⦅ilthXPb"aâjsN YS3km:f%"b-9 , yaSEIY?#3cB e7jt6h#@*'#ܨR}<ƌ& [s-=>Td~65`E?=/%r'C"@ 쩁Pӱ2؏zG! a5+7oV@'I}nŚ(ᡱwΚ8g(9<9pGjV>Amc.o:ݰR?Ll3qM{HjVț6'Bly'e-u9<]/?PxhؐoSδ;"Ozt<`%1=x5E/ xׂ^ڝ@J y|@5 8pD[ Y:y6t4*Zkd5(^/Y~hf)楎L)w(貛YNbL7ժRήFOE,*`<'t3gܳ蕧3Y3џYBFQӰwȅ=Zo 4"bbL[a_8$#)ZA|N+VqR{zKa7KQMM SETD&!=p^ @g3utO|66b_2yhRR' wǛ9hxrh)zϞ֔qSL=Sú\v_i'Y/`/|K]j :]웤޺hjYSgM*~O3d;[E]^H㰝A)xsXᜰ)FSWQ /CYc1\SIf˫[<7 9Cw9zL"`{^4kc*-`"ڐn]/Esh>beV&"KQ:iAT<֕Z%B"g"^p %w֋4F]1Ez2Cj5BQmIZ-uz\;Cl7=yi87Fb(]b0kcLL@ 4ܲJK![kFEf(35d op u{Prm7CճJ;h;Sʱ \`:ї .8r&]o>aR%nh#;alwԣR6Rw)#z0 ؖ β.IˏWWC•aB%yBv~YUBg"{o]a 53(j)=wjJD]~%-EIU'>]r 43 V7 -p8LwZܼeKHpA9SHig/'>>㪟FθԹ8Eښȏ9'ڕY#獵J𯲦A;ff SڅJ/봈.]݄i4-8or"JvfRp{bgLJ0sB[>9Xwb<FZvH2TȬKA( 0Ǥ$u9aK18c0ky]"cyMZvuK?1 w1i,_v%=M\Xa TsFEy3.% 3ҍpeV8?tΊx9 ;#/ϒIrc8 ;er1Ř,4v5x5FYKEr 3}݊)(4TSH"%)׃v 9GS3+Q6klVȲ̈́}]4(Vd\52p # 0cixܥPÿ'i+nRjё}"+-|Bߤ~ 'ЫY9Rٙp:rK vyN<4JV, gu4tg4dTvՒܩ4(@t(}GÆ|P(UDžZeNh4ڈHsUi(h:] kO R %vLCLAH88U;\,yHFL&i~Wp=4=Ot"@N)Qc>8Lc̍6ti:,$UܽNIJ.G&t$VjƄ ַ=HIS2m$,= vUIc\֩NΈ$\i/xcvF@?~rSZvT?i,$~{. ZyȋrD򟂙\nFQ3;K:5˿LQҀ5nRhĀBLf) Am WsXN yI[4΋8N!ҋ4 X)֧KT0?˶+=Mnwvtg83MfG8 7NQR)')s,ywh(:P/I\nU4wor/ذ3gdKG'"!dLIȸRohm''tlY"5_LOE+cy7)_) z ++)ve-ev7uÃQQ1a/u@?\.X9C*!: vNXĘ4^:-]CƖ"߉hQ#]ϔaTݥn5jS}YϨ#I/<5{ظqFјw{,;Т Td|52׫\Wvv7[Dui !\ nr[?{徇supXN[ocA/oT:Dܲ-JC:6}^aXr֒G@-8kyǪĊyr) SSxΪX|[9\vBC-+[Y;gמS$dE{-17!gJm'ԭ'8ds=*j+Ern#@ΦH4e;ͯyy1y2|j|,bu]U~Ḍ,=xȓ^Zd=}{$;*6LnF:ȤZP+ݖU?NvLFP)MA;G.Nh ^?kG M dʁ.[ 15V [b8)2OU2Jg$(%XeOz^6ʓIFA検aoy8ʇT=-$[(8Z}R|×YROgQwqQ.wO(8h@h~yDis&^IF9hwᤝYOu OB׆Fj *fhX-];z>,n߲.36+"nw|F~u@>*MXߣ.Mq7wV|S#>KX pSĮ}67,\I2N %S%gdZv^xW9)#IĖ*o8?#T(66%0۴8\$P"⸒$7m[JN/pS\4 {q.FQC3I=YzC%m)e0j+K&Wl4$Mc*kf,.'DԼn-ئFA\ׇ RRMlīq6`[%6δ<[{쬦!>go1(bRЯLQ'حKIlE20׼Q2~UGי:Xs!,&G$#I:f,ʼq)rE$탘>K%ŷ8#9r:n {E9 FoehltQqẊ;Ik8pF ND =K0C#8"3ZivlSp.4R;Odu18!YϨS;h\CBq`>)g$#RSPUfp`#IgOL=Pr>Vs֛Π[]AhitõJ%+r0 %םf#\~fk+.C9Oo$@NFqKW&2#)8aJENw) ˜_oI`{AlrkMrNf-^yڒq1Λ3:nV&ؠF#CYm/YkOPaKf;g`T{tvs^NJ55I}Zeim#O[Qr` / _t buSWWw8g.C6GE*H9>Zx179+44{ʐ*(M cw@ *WDȹy9e.'1nQ@1;,֪ rч0XʢXK7KI=b7)#1Zt8Ǐܩ&{_.X}h 7ҁpV%|:G<,Z903!o{2$Lە*C8a89,#O4;*b>@p˵IZ\= zsM^~^ԅO! 6ØAn"u=D#>[yr8I>>PtvةNUFWjNmRjiW3NuiZ=;~yIBiVDY3g"J'䟹1 ףg@Y$`.ʻIcvdiX 9;D'ȐxLG5_NBCQPSZ43HU;\(>$kJ=5Be+2=煟˧C"NyA§?tdijtX.oAJ D2z4ƘeO="0sE!RN(l ^R>A:aGv.3u@|2D%o" QH|eSvM ; G9A@*D! 'GSGvZOSGPC嗴w#w_rbU%R~þMtlrR+e = 3VkbUl|8 H,2*Δ:"zc9Q7`_AiKhy\LḒ/Hϼv,R gEghݰ{"0wGqBL˳ve; /!`: =i#~=bK; KTC+>q@7">T;04xۈbўhJC{zG >"gm,|ADÕW5 -B( `T9?HAXyeʓW$r궗R~ 3 1ud#BE>Xk;$桑QY]I'ONB.PWu'ԤkmiG^k;1wOH5(xDG:RJuFGp+v/vT ౺FE]lpv6O*8 C xHT3 y9!l|>2%Q\ 7c ^p!3 i~ uU~\7Igdž gˉzST6ڡk'RƊF2Yavy=jvKd**>A=CN񱜎+Qt9rѶq.UsrB`suCU#rVZiv> {uV띥'oPt^bK*۹ nDtB!70W&Ju*RW>Mjh &fS&!D|8qJ+!7>8SȔGK.,JmÊ8'ILƹVоwKD8VS#z'D+?ǜŽ4V9MKR焳KdG`d;zBM@]xq"D&үBOC<%Z4ahh#l#"f^>;B=]2;6=3$lL'* 4i_śk:-h$ߨRc$4+yzOG'ޔ{Nٓs&>Kg[_׏JHQ.](u]_kj1κsD2m{1S@=Vҭ&֛PG>Wx4!qPnX[ V˶WЎZG>R/8sʝif}1ؕOgoQ AXd^ 봽sb {"`G)u:!ܰcM5lX]:=RT]OWe`zlj uROb;DG=2 V=(k#N TP^#^J$C(&PIfg!ǯ 7/]]8!p/%A.`'{zMae~*7{`%1dTc*M_YnL=:6rt1u5pY2dHm$y82k6e+Π=W)V=Ә=WOv0;,w6ے;7:]O js"1IEf[@|/̈́uF:4kWR^嗢-k|:%D8UL:7tNU/!SÅ[p+=,Laczwٜ{ա%WVќem'PCDIV}3k[~3pNc :$*n`ˬĩjH;SЄrtfuCS:)-fBtޔy ,2ف+$/<ݙvV&4;h+0)S3b+ 6+J'MN@f`q>M> L y>)C|]64⏇y4۲8dD+ROL \H+ h6IwE!*cOіώ6V1PJ (_T>Z?s` ,LXw^9N V&X|NepB @d !d9jK0bZ^NO?R$Oo{r-VO>Ac Jh:C:Ùx3ٲ6$٘FBCf-tO`kU&?egXvS[pzfA=#FDW\#;^-E,orK}.,p'(㠖NPWN Pm-tUdskO$o }/妢)}e噰4=k8%f-ӷhvsێ79&os 3ar8AaGXt]fNbyXf͕uu011M-1CT?,gHuĦܺT:JDAkUj [FtUsxIaSo!>pF%{Co.E)ELU&9^"f{" c̢廐s/{Cr`ǴaT!di v|w~h @\\9Y];g&k2)lE[!G8do(6Vg4K,́%JϻaٖiJLOt8&E;QóS͍ mpI;ݲ9|2,+EY0ekm_H?kc=I=gqacu4[ 9%:{Jc "C<j ZS{ H~1oue+cg({h'jD]81ͼ+'oOzA3<9SB{iiޣRZLFfpSّ/*K PÅ3g7ݬ_WG CBgs BU q4~^E2'(Iqq?Ievפ2u4 Y-JcjB$rG_Ubr|Mٴ)``/tpf],8OIQ'եөvR\gmm=2^drSF#0yX^fLp*:J|Ӊ7 +5J>?@P !nU9>l\ZpM}VKō 1;%=T\՞ K{+tJs=jlm`kT\$<`$OrH~a$] <(JɜsA =X8O,JfȽcsvӋ O~L|䌤6UJ҉{v}ӦqVpnvz2b+Xnl +C&2%@󙕫(jB}V1u!MCn:c}CӰb[V_=r ;2Y`Tx<6sFxw4Dcz ,i _sVcEu%L]eG!2Qeӯx-+J_<cd,wSOx@Gtc MY)7E9ן2(>|:fMN !tp@Wg% %C]\f(! _2!*wngUɩZ^(2'V6wy=ЖXu.!TR6"޲*:-I6(APBD ř^~m:ly6,I LPLɿke'M5;,6}04ɶ#}]¦"cv5Uʓ*$`ڍ$c%.釧[nP1a.MXt]aK !+ީ'噎*q5O {5^iMOJ~̬Fkcm6SdTw EF̙CMMDuEw(b[P틆և=rU@̃EeRc0q!5U%~Nkd͐"!eў>JKk7ұ=e,iM*Io~ʼnޖ67>@˲0Lq` Wu_R< -#QG9Ӗȫ݋d1bR>5/T.΀E҄L6aa%y!?* ?:8{kdf<(|&Q,ڽO9V;u I~fk*ϸ)!^̦>I S8nvv)!>DR>˗wTb9/ k%" OLԢMXN yٴ9M&1moCwv^nm|г5F~U)Ew̲Hrﺮm<]㤘#u8G1G&2F!! m@W8suف 9,`E^z)Țвᡬh7;w {B{#U[P n8[t.g׉s˰u ^SJAc gD}Ych,={;(Gxa F+86%=2a'1\SOw41]L %3s8Rξ#ɽmRn{YLMM^W5Fq{LH5 Z-kZ@Fqs_##g$2YM\ Z}V&:o4 xp\ S& bNNwuJТ0Mnm1%~R}X/ U)y> zcX P.P(e `h^Y_rك0=87]@y!mL$UR!&-9a(J#!J <׎5ˮ:\3;^KhÐ%/hHMDn8)]y KS34KtwtCog`zfQ[n%F?-g/!#,KM/ He< esFh/=NyN ȦC5UK`ZӤYd8iYN+c$9zݑіRYRyT{/ w;{O=2@I+ӈhSwz/! 4e$m9ɞ;K!GQr F~!ciI?yPXQ0r3[Mkpn5WM~Z){_uHM9K}| b&% dVu٥2r(g6e3Q )3q )?'pV};z׋O@otX+}u$m6_ ZzNC kVll?_ز:Ɉ!=9t>XO*'Fԥ]-3}X{:7HVCu*֣; + p 2 ?OQ(bDI$UQ)ѲXc-@j2)hc_: HhcF^('KR!9)G&,=uH st$JBKn(.:T]L%Z2Hj21<1N=&B{Ț4W'pUn\2?`n5М|iWk/n}兽/>D%0JҀ=CʋfeD&O?sKLvҡyA9!nI52E/~nYOsq\`L :XhcK*Xnv;cB7Eʙc{^XCLM  ˫W%XͧLV ׮2Z+KD<4ks&ݷ}=8*ƃR- /˛OfyN>J!-9?'le9?"\ɥ=EJ5[xlL٫;.M6"0akdT!6tn8R xCny) ":(GwPr M-7L$Y&dY SA#;?& SfL+'&,ɈÒ DNv`VHNV3Y 8\tMޮ(!F PsJΦ 8ÿjb cDjv 2sbNHZ34[s+*}G|iS5Tzd;X[5\S$ء>f6i1NT$[:0Kpd:}t;͊_<b*m~ٔrRR ?7y -!:z p vkz4Mg63_{C6]6Õb[~ րQ0sN`)n[/뗒#zUBIreo:s 똮'(cT z*¾aw}l>7XBi+5=,ҟPBk맏PCFdɭ,֊[PvQGI0u0~nW@Aj,ӑ@8/ix(=X\Nc^KZ9GRIQc])+95kP`3JOHگ'3OKi2 RvL$5Z֨w<'0yT(gYrYny&I, Z=~a;x-y @P9.5iVEyZkXDGweQ\WE JzFy0 ocdER:iL_S[G Ӄh:}}WH>l85"BX)^ Ќʖ- n_^̕! S`V6Y>fm‰ Hxh `ks|p&%7kMiPm3>+@ۦ@j#>3ɢV܀!VbwGJ;;sʳCQEȖ JK:xRwf %,b[~l.ֶWhO#le^|h c|v(ّ}d~9|¼SVWryj)k|Ґ]"Y/PV[O@7o!V6񔑧F'p=xUְuĒn]eIy,u}+vy)݂Xh"4;lP凶1STf8eiJji.3x%/o:%gnk]ʘJT{/yX' zc_v%a//u/lUg;Pv䅑rѓI~pb,w1/`N 5hp PvdT s}%6m{ .=z 6 QD?8"7iDOV dFkL$ 9JC.#΂X%#Qx}z@АK3/s)gRF.y.T:epθY'ph?v 7fmeS9w_ҏCA67h6|fuj<_SccNyޠiuOx; O#fS7k i8'q>qʄ!FctD-0`ԸY,?pQNޏu~ҝNΦ27Fp^`ù;>'CZ{C{uϽ"w~S6x'-BXN5;CtaKC!V<9z[:T[Zn Z*Xp7m!a_V+]>`_t, Qjz.Gb .^+R(x46}z8L8cEo3%o oG/MkvujM?H|YOS3'2 jŬy7cK?Eh`6h`@E# ?hy(a>&䓊>} +al,w* ZCr?O图W*LgߵM:' I.IU*ڣWY'u`7s"t8'EnP_f'T4]aظ+dVrq"/ |qvYkAOldF%'7trY4F*~JTڷC#ɗc]LyKJ$P|yH~=5d6xC8KoA_na2fDlK^sw#ӏa'-IߟdQTl7XOitӒҾ#4&oateJF){Xy*> |ŏ]B}8tk7LXPo&!?̬,f*<_k2bCuJ9TۻKD6ѥqB+Μ~ NL\`}%wt2s\ x,dh%H4"GK݌:ڙ|r\tX2kyTl8}4 T1LG֧mi>9sd(3-`;S,K`RD*Tʻo2eNO<+ [=-#Vq+:Т{̒.dR.lBKD]8dn>ȍA֟Ɠ! >J' ށW##W^׉&X)Krvј '5/0$ǻnN]d\A)&qxvBNvׅ'Fd"Z"MSӃXeX)dn¤2D"1n~r^H 8Xf- Beti~ GܯqB*8{/[5ۘx~n^X87${*c%~{QA6K -ڤ1370ya Yk(2 6yHTjMo^.'+ ]TP4Ԋc+4bZ¾Qbp􁋏VRKznt3j]OߠZo|/^.C:Ю-$T\&czDp4詪mEn56vLH\hxmsAjFq4v]. T3\z:}#D eO=3 Se۰VG"S.&POJR#>%#|kV8GoZ2폭"0(~g6ɍ3{ߗ63[Dz$xM>vb8)#L +2V_eW)/i֤yjW8 oD?Op ݕ0!"&z %fPxs%)3݀b5O~J5Q?~3\zSȨGѵ9QC[*\C&f+z4fJ|c[ti5zCAqtj_-.E&KYB yVn4Opab@Y.5C2]mXS%V l<RiLa3qEtѯtG3U~G5*Ö"v02+Щ%Xh EuZ^Ś;N:^F9wUݙ隁Λ8z 1ZMli M!!'kJ {eyIP`_ Xc}'9ZiQIpYϘ1o"JrH#vF ( x22nT=;67$$ H!Ѿی(|tpF$[Y?glZ].{9x 4v4kov0 !9)Lu"^ V'Y :Lb%K}UOw !tuI %:v *~62Vٱx}|pl8qGOX/CWMg_l'nOv90uv`:glN~ VN"('Yx+pCxyּx} JȗG(o*8jx8JQtvfÔoG]N#g͇1`qemZ.U9fдs{*g޾R 2덂xHdɛGQ=㋽M%(`/RL~ԝ%twb*ؒWT}@_(;ۜN.S'fid m jBJ~e$;Pfhhvweu)#DeaElA#2!rzg#(&yz e7P+D 3=>I*l-Mf4JқdL6-5y9*vkSSFDnjF>?zOoekr :0B5["ߌIKԑ\By&^2k_QuM qhyМ$Kl>ӭ:TbRȫ}Z%^h3_#r>ꪛ-K2?zHF'Xf>*)2'H+,!C!ݡq]0 (7P9 3KEN"e^5/ f\rArNgb6h1xnKAySBTY7C{2;; dVBUnrIj36pʎⴣjͲ6 wF:Ɏ´ %̲hl;#r<#2vzO9lvԑDU4}w$G#\jfwV-tRDnBoӳ>NNRNK 1}bO|}'}ؑan)N^ EJq 4j#s\nra'ao;:z_Wxş<@n̼K̎A[dxߜI,ܠ]FBLk] I^+uuBY"DgOK+LsWW"vUPA zu0rϑIpuޡ|x_PM `f䓣(Cl<J1;4ǾTD=6SVsr%I]JϯS£=̡#54 !SQʻ%b'vܷSOyӱ"Buτ}fNfJT@}ԖSW&9 sG{AO_:rP+n8=vwڃn;l7 /f4 }9S#jp-kQ՞T>oX]";G|>S|Xc@: τ} N?>Mē]n b'`gD!\"6}]u*.mY6T|~37m"We3Q(ϫ~$}C!bٗ<4KpŷLC1/.^S.S7 tŬ+gR@rȖׇ~܍RsXfZGr}_͢jH9Hh]"V$} QzRrޘ.5i7(7 j '(YS x+NH\:)Ŧ1E"*"A tKh- WLRCw~X7{4 wD=Wp^*sOHt[ PT .lQ^Ʀ ;m.j:8STj`h?bI>IJFQ1 cZ+Ye'T=$J+"eڛcUV:uƩ賈 g|$UE ,-Y*!)]/iaBwLiX%`|D3千7StVU=^M`|0pKOM;Cd)Ç.ܘ[3js Ks )4R B&jɞϏBS<= ud>=~qo{ 챔Ȋ^Y}ūyqThEaFs4N ԊLJ3/ #;NRzSJ d籫Ppdi%Mk0 !q GV{Xd?<ܽ`yߡ(1t=Z؟xR':|fB(h[Gv,'Sr1F ;Qs>y#(ǁJ?Y8^ dx% rL@2TU+v`eswVdد@0Yu0:a :γ)RW֙E}6A_(?f)D^Z}P&vWc{sk[X9Vͨ+כ1^ #}CC@ Лn}&5T_@lcJx67V\/BD"TX24c]_y3u?UFYi'^%dpᅷ-s74^OcWأ=jUmڣj\w)Q(pFLG7E6N+/ be~BetlV1ѡSv=vDp3!8741;w$i3&&r} vb(,Ambp>G"P8#'.,Sܽ"Gඏ4@+<:oVεi%VN :` ӻ"sGʘXK/yh$_2(^XA=֠db zPğ!y &؊"bY{I U+x+͊4T: $,y?.}OUP qֺ $kj\6soH)rzV#gE +jׇH4 m)H()dTY^9v4-+J+&$aꇍɔ|rA(̚ߩ! 099U ==i$^*6gIh (k-I> yR{C|iG֤Uao'# O0{ܔu N-;2O$HuA[ʇz>9+9H)Q^t^Vj k!loSY(\[a7n،c5\؎ca1\ZI"KyGVDž }AoJ;F؍ NHVOT?dZGU;kËYQ_ׇDU{{YKzL4^E ݮ2;4-m(xn YRbji`bvЙZΩ x+sN-E?P9C{5&Nmz3KRV, Y|y(W+u+wGsߙɬ9%B=z }ۣ$8% њyN#>Bj/TC؍%؏inXDeXI`=Uisjmz-L+4e{;p_ZglD^BL! s04.N %9FU{>I4#5ޅNy36;V\,f\ZH 0BZ$>Nw{q+48u^?)^O@>wAC6JxE.'/ VPg+V 9@0ɕs;#foH/2 Շ6? N.+`X[B2I\dhjǠW?.;zz@<CEvcPA,P'[ '0RPGXL )_VhU.+L5}1yELP閻bO,Pc7xAtD&G'A#dd\dzm*>j*H{'H?An>Ը3iv'?p7ǝ\Z8bgqxՀ1x1גzѡ5k' _<"1['g_ F> ΀pjWMvDwZmU0"}[:^ZG ??]tVB9W:fvagA# 2'Hя @Rg2V ņՆ%Ns7w< ŀ]`!ιJ5FHd  c.< %5)&Q(pfftKD3`x˚]4 Z=aюZS?xk 70V&oM8H2z\岗Ծo_ϞFװ\pVBϪXo"Mgо U.4w[iuHhooXBBxfP,!U\ G%$ovɁ3c ƻMnቒM6җݿoYB"2Uѣ;ˌsmѧh`j8S)0 XK~6@Cd8C*L"dcgsBZ"zYo"v3; V|΃iS!7ԵA7Ki31\#S~jDSǢ(D\@Lr6}KV]#Vk3EP:6r\}q+ HвgBUNoI|w"## 4?HCG^HlM8M^] U7jW:PE֧E:{dS! LX!4.2^=bLtR>Ű?X;b6RU_R`ϖ"Uh:1mmVM#2 obUQh:ręVfCcE*B2@YVTfx^Pէ-h0T5qqPΈ\ːu6]GJ<Fk>씳v\A+Ju$@_Gֆ *?KٚлKGW^%\>>x?8%5e`j1eL XBέ\𾫛Pyd"oNe@m=񹂐[^ʺ=60YEKj:EήwS(h[SY;ч: ){lk >GP[Y$&[ -Մu싖 5z SO`E*ϰ<VYCeg$[ Ă:߀YIQۣX_iHZYy}Ki\c,,ۜtK:S*!*Yϣf=2P/j[fS]Utw ׸(fRXC f9V7{fv,[ֽ,O\J,mF_e }J|K|; <:<:p8t0bdRJrv՝)1}H 5Yɺrr~#nճɺvjqhV q9tuYК/V)ؕ+}:r( wzQ[M2im̿;tѥ {չ>xm o#W@EZ|u&rux>Ʉ⹳ЬurD^+';;%X`Wi;&)sYKpu)l X=Hd*a(z{^ckw.w|4XfD Yl~Iѻ:~@Nq6^,n[Ќf|mȬ;FTBuoZ7fl<6#4dF&u6Jz{y^ak?y}U&V)>+dZYeJݰec1˦x izo8ӡ8$%cGJgEcrQ<MRV6dK^j`NdUFݛ -Q&nf㓃)TN턏TWpD?vj7)+G,:.Xv8LǠ++PEãUAmzNX S4jh;ۮv}$9Yug!_\[ 22{ V$WSL"[z5ne%R v)>M{v/_ɞZUz :)ļyr͐M3sKʹledXA,oEy(J#"<2JE͟bD+)?/'pSz"\r.#2gno *|`@Jņ1ہJ69^fP 4[FhWGݱM\ .`6.׆`xo{3#l=i0?? l6!c<_Гj#45!Vo?8  Wi7Jkv ~Xߜ'TmBuL61jO26 3?Q|Q1 ? ƱOZU,uq3a%qq0Fh͚)flptŅbKcc )܄U_Z0F? {?*nI, IɚkehVcmJ,W[j8X HA ei@?n$Y}MVoUCQheGwr<|MPoEԂ#P uSW##__4R#Z}8rV(375^m>[\GEܾ5 ~)j[ބ3ax /P6] WEƼ!LlFт.sݼm6% BåY-kޥsu},pddO5 #o8(@>9ah䭺m<lWq*h2]zuR|}}{%]ܩh\.oČb¬j~n?" -$fb,uwMgSD{bԮ3_~!5j?"51IM٩ZAS- IyGAݺ{OOJSg˥&#t( X&*K#~q95w.\ҺGVG/.A•M1ƚa4HKliY3~|e 7p:sTdغ<垽|Y e>KUsKjCw6}trê2iKw.vV DOκAXj5}s^Ʌ> U_] v)kv;@ u&Yo/KD~>_ I _25XT[{?R9Wl-z0и#RTęP[Q OnIIX%!/R.S~dwIb qNZpH_wlMimGXu{[?_~>HY>?]W}}p# E+Z.դVY!/S=feȭ^UF%n9pٿlUt,~}$DԞp|˱ꅁXݟ72ƜJg՞OpH䌘KE!/>4޲|fy}_}q;mzɗPdu N j'֓tT6аm` B Y"a[@;FpHˎGE γvȗHT%cTBMr*l+؄p 1onY[*s+ʢmOY%*,ԗ<)/p wpYQV['4`ͅ{Bp<%:2̒;r6`Ce-RQDIД<_d\[n:G lJ7=>7쾦{&*+/ElX)D5zCwIo"g獏@z9Ldy=B&/ |FSlG>7zrJg0*X~.,`wm=]OHDj踱bX.3C|-Z[m4s7zV#$Np2Y!5 I;'WU3JGRC̸SB?i& 0qs"r"C>.12|}:D:~ɍ"W)o$|\RN/|Aڭ SS 6fk+O6n2_X(?8eʊ:ʊX>}r/dznvIkB~gPniY4[k 軶y +cf'=4Oth'fgb[őW'\BXoz7nf[Jpyv&k@hZt@2$< sc7bqc`¦`iǣY+Dee\ڬA|^YO)e:+h$[ԑYM)s*d^EAkX^|l XW3)8KJZ'7[\)nA]W EA39`p/[خ 8  0J 6 J"}wL2U|5*͇l| hg5;29Y(ݰ6+!-7 0M_>zlZWHN ֕Tܯ-*/dE ?|qwf%dsVȿJtu@:8<<ˆL΄eÞOO~o.Cí =e9>Ia/iJQ&_L( qʔqqDqY1d]UO %N)6 Z(љ ^ U U}!]H8ke2" "]L6Ex8;fPdq~"ku9DDE@\־DT( ymϮ?$B3cFMe2z5گPN܎rYbsXl2ox[;!eFNjaDaꟄl&QO?$M` qK$HX% G n735NȘPDFsNޑ\6%>8L^0,u+Us)txДS~{1Y?}=L9E~:k?OgxfTEW^{ɚ!22C O%c]¢&}I> i;'Xs$Y6&W+Zɳk#NtH +/!092l[;霥#\|_7+٧nKW$W8%pFu)e lتg}koB^ֳԅ1)H8$3R|,6I E $h3ړ'a7XRAxǹi!f#|5D5'kGy:#ZYL&Jbl,jKKe|8o$.x)>P[yxkVv)\ߓFCHpfM #Y (_8 lݬ &Pۺik[G?Y KMZC-:@]qq}T'Ƹz $ ͈nΦáEs{v)z@ ;5yR$p: N+{,50).~aIbLLM;ogHt"jEO64 z3HJppimzuwnyyl팗4|9Cm8"Y$s,V:u4(%u/E0a ,dȒXBXx_K$j[)fiLzy˙xc%pܧ[tJ͚G?4oBaX?zrnV(P+Gځ^t7/e.Yha ISD?496B7=SV 5%S> Y !v&!2>"\ux9>Z/ԧz&5_EI#zѯ7WY2am6;9&+o&҉#dX3R`ёVNL:IhWq^ -3 /%ڬ-[ӂZDZvB80L#%fkv}yENKIKPGNv߀Gx4.SK =eBGK0]5$ФJ@O17Yp<3>lu|ݿ?tizU =sЅ VH`Yr2\1+G2\tvQ@wxS dd{vh`QȺqX֧N.t>ՙúvOL~+kե#A#`~HԷ驲iګh;}>AN]…" %AiݩK18?-\fB kzrMt{jVCnu c*vp0jJ> aahiT{G5_MMMԟ0r*(e|G'`,x+YN=,6&*OyTN6n]d70)Soa/eZ1kE/"%(/~uܵ ͚J;tKjLؑ/;* f{0 kfS챵C RmΚϻE̖:q5d;?ᔳ@ 2_HqP"*SmIpDIp~i"$W4o)o|rx\#` uC?5 x֕Ol#̫Kt Hc-rq9@ 3W.߶VIno[e SLceW dO;g‘X]D| "5g \К\S6$8GJ2sAL4p<`$ڻmVr^n;O4j+>CM3ْL3yLPy\GEf閖/349 AKͿp@yY:}eGL׊V&Yuu> Yׇ0`?"Wyz@D8oqUp5?0vƆ斬5U^|&nu3!) MRՄ[(VmL=e PTc3R5uij,6yo7C';qڬRezsTux8y856hM_&Wd73Q&~e&gDPN7Ǫ)9]9?>-Èt@K *֫& A?k~,.{nx.q5@uSsM7%vlwM$(ZIo#<ȟJuW'#^8s"wlp6n ~[R7 W"ZuOs% (H3A_v3*H<=QM윇\jLŬXUUрR6Yr:뙚Rtt Mrղ_RYD EƑg!=[3gK  y҅ܣt}Obic%yDaU7@]}ܓjdr]n]#3lz|\&YaNP;t5Dx_m|9cx3!p%w\6Tn YG3L;Pv̷NǖQˈ~`FN)XJY2O#2_ud56x*Yq7՝yH7^KA(-ۜH,ɥ(Wdl:#eʮ(&q=* ǴZGs1"%t-oآi4ąL){l"?kh]7l4T=$Dd?WhMcj bsiT"Lf'V ߨ=Ahj*Th+Ϣ #:Xa6 " (k~n6V%g<2$b>j3:e 0L ~2֗\J^MRvY,;"E]fb>Dmk ]Gs8V~20ՓeѫA #xY ܬziq˳6ZF,ѓf-ML3+S4MI־g}VG xRCj'{P7ɠ5ְ-){%\ BM +T@T"76D1aK_gz}5[8 mY] c&+X[%]Нq; $Hq]%#qKmK&0$YWgq\&mKߤ'*Z[$|.6 LJ _nSa=@1%"5—{,&@[,6fDȱ1Oh#xi_$^V] ybu 5/ 3ʒDXvX»0[((j dP!R1=[.7֠miEu\YIwT(i3@M4r`Q΂{Y0}D8N{3g&&QAע8<$흽UBez|U%\.䨌bJIqc} mQզK:SRsϩANTܥ# W B|V/K+Hl,rҚP0A h{Zt:g)}t(QZ<{pDЏ7Hk/SD-12){c9Ux8rv}59}?NMӌ`)f>=C^}yxP $ecDFA,K~!r좤_|l7ޤpl~q"4]1]pƌ:(Oߜ G~l ^i*g|( ÚPJI!XS_ ZEsy;3ۂ /d j²ȃ5#P?0L9zWa Q%#cMi8{Z,i wg Wh 3׿:XZňȣ+i/7kѶ7t3C16k̡ K=VM3$L;&dыfNjs(?&FI}H[h•O;K5h5zBi,噞w@0 KYŽѭPBS> %;1㯳5Ҥ]vobK=K٩DT,]7-${E3Q!ZbA7OZ?i!۟*7exiW |<~MT(]Wwև~Bz{9Q/*.`7 C#$ɦoMʮ5~o{&buGs;J[$҇gmz>p0h)q^ЌS.R`ѿ~k4#Yb!սEAܙy@6碇ǧO=zlVPC"K; 5l0MqW,FY\?1 ENe Etm !A/$HAuWjHd/gķvD<JGsza; 1;"0NG6KѴ35Ą6D a"A6]b_Σ{&WiOShqD 07rgRlnQUj$9-ŭqkܾdO[x]sS'?扜ۈ2M&_ls $yQvpH=S!U<2Da;ȕ6WVe'̆FxX;WL*aFe%;ޢcU MLCc㡈pVͳ.2\D+;t|XTh኷@ÿv^-2+XR8IG*Qf& ԋhʓLy"Zx(6y<.9(l/՛JT~ 0 VS"C3Ǫeƈ1a%>a(:lP^"Q=`p] &.1jͯ4F^I!ߥ^ap34Hf.]f * >8$ד($X% EMޗbzcXdq.NMt7ମ:ԋޘ,LpC F4'n&"|l o J%_e!;W!q+_8'f4m j`M=699 \ MW ăQ:"j=#Qy{} /0["3TQjS:RĈW8|heGV:C2M疽 3dzXZlߺH|4Pg  J>XbY:i<;/p"*RsB1Ҫ/?VIEW dv%VR.;ŶVkކe]صyQ:I>]WvA+4 ҄7i D6uZGՐ/jGU{VG0P$V'4t< _3Dt,irt&9B+ tt#;ibp&.4ii:"\Ň}t9IU#MiP/TgۏgySE:-MAm!Ԩ<%,rD? ~ЪlnB[&Jg)WNedEiˇi[(-\8C_K$|8d]HwHoDt7 tG6=.&9ZyʢMۢzž9iпlGf#XÂ@)54Nv \̝EI5LȹZjU\bFqɪL:1W yy/K$9<(FF.m77/ })RAG}>^k9mM˄( ]&PZ;=~ 'C4ȥ}xuүFD jZL.2cqpM(Y}LsӔ!z2QnF!UdU%LG>pE 1s,$V;'/Eű9qJסȓ&ƏK 5j^AzaQ@Lmf%4jgiWۙZfE6l@+ZSYԧ)+~@48]+C~ZU |tNC?,\IxX6¥[Cv?u͹?~&?WQ5cHЄqQ N{u&#iaM3u!PS_ dEm p>D\g߲ɁEQ-q2^7$,IF"A==ߡWlֺ,V >?Utݬ^#y{cE|-7@ Hi,Ui W/sBF:^ԇEu7ѧafP2oGL&ɐhEey/^KcFrDF#U͸4xEF«Mm!%YƃC&>#U\zUxw)*Rw>lUڣpY - s5.`gnEe*CЙ dؚ@oDz*s+D'HegR3{Iy7m-(J=x`Q4w[(~(aPGBK~fg ɿ^dbaY\:ӌ83:2? _ps^jVF֪4p(Z|%ON0e8.gE) fb=?$ONħ cQŅ0LwIq[-yEJ.,^r8\-QT` q+7!/1^r66P_J RV㿡T:C޳ݼC=|i/)K>"-,wPcWf`6A:-5#U޳I6mnY`8:s+| (&-3^2wK=4V^Mʷ9g,"BګD o>nƄ/z(nFm7K+Vwr3R&Z`%iGWYrÊjW{, {MuWh&49=-M¦^%瀣S,Seu[BMyq{_v,-7po~c>f Bϸ@Nz0Iƿir,[fq]@1߳V2Ӽ;eLuL6jI5uZ}\+-V.'QT|#Ξo.KD˔\]~7obEU3aHаuDeXZ18CH[ڦ>P|7jnG0{maǪJ.3e:D~ϣXz~FȖr&fqKyRgX{`QJ3fa \SJ]YS\zӱu\'ɋzC:B;;7(W;7*EvNjA$Pl95.-fDMcyz8ձUofH~̱t5Ud(paJONoQG{4MW^yE/4{Cj| c3zU ðNbA7a͔Wr^]ճlJ!Dj.3Dz[TOgIyQ &t<?)tvMyla_Gc2\֔rP49Ă"~P|4w4Ylhuq+H!V=V@&D~֣ZH87g=@M~% #&4r`3pUp0 A(U{+4ZCDXh*K9+(4[JFjX@԰ QK5%R%e4;w 7ʲOmRuEWlNYÄEwH,V+Bɑj׺ry7}y΀WiԲ¬-cF^:pGƼb+5pP4 yxe?ļFg5쎖d.u-~_e6b}=X+qx>qswCm]* ^,j*C;F}3Rnҏ@_SW4$wK b?Q5O8q>ꍀ9LypVriSy7W>R16Aތ[+%P-$Z~if{(й5DaESDlAȯx!i6ukAF$E Wn=3vip%Ph;vqݬ`[Y VYm9T."r>75_wyhaEW \LJTaa5sw`?hLL#ӑH8X'Dh&Lk3p~0f$b% &nD溨4@n sEr˳b $M!_6tc h0D۵}Fb]ߝYOp f K VYM@=XzvoK8WԦ[r?ȴ`Iu~)ƃkǀ5HV K|xo?,8 u{ H?V9wÄڳ.c\@g@@ ZdMWbf:-t e+EZ|%JT%|5_/+Uj3Pe+Bőƪpp$ɟf4sDWi4u-Z3}pFy7E-Mlǫ{e͌iV xoGIWwt<H9ҫul\J7T1 8[єnn[pd< A ie-b[X7G>@H2:V x6Ouΰ] @/VKE4I^Hk G; ?ai,짨{_-N$w?yͬN{]T2qy&ޛh+Qy\g*\l|Z)?  Ej ud)yG~V1_~=J87@߫ Ij6Ea9.Kw/#cXMC桘SM~|)oH\ͤO%V|AO(hb3=)S_4OA,)OS($%J>]D{dhzRzs eXLj^+V$|PO*u1 ZzqVQO8ʣͬt İʼd ybQgf،,r@5q|!=NknFM&D;`בCԣ_J❞uǢmw+jYV[skv0T 1 apd+[Gg:ud#TOh oZ)s#riK'rTQQXZB6dmo򰫍D;iW:zM_Q0w\gXe} J#p &JeTJ|K~fwl%+=ţD?.&; Kt\ 3=.#6űaS-lo'@Ae׼ {Ŧ.:` h 6C?bs1%/|RPW@&8X.3ӧ/U:b@4ϧ{/iEoNH55s7d{<ǟt]I<, '2G!>SӇB_͆DNGo}T,ߤsm>Fx+J6bF ʞlх k!UA3'` +J oejxNW8B(K)S/ZXGK{GU܅h#+db3*!E?Ӌ~` /zv<[&ZY|QVͣUH5'ù,CK6k7E雳ؖr~ol &ؼecR8Bʒ i S2"Fߦe]o" !hO&id+,|VZz>X52dLg;zË_H1aTpQez Lymfv6Q"NPҧ-RYe)Jc 5CDH5iq~8 O(ґ>uJW| vW"-\pbOvrv6C "Q/I 3 ORї'O.9d;up g.\E6\F_+hޛiQiFbB ] ,#??PeDƳ4)x$W%V6[@#=ˡ^TG=KGoEpSo#~ىߊqNbyG^ڈR^Ik}_'fίvGJgE m'9ܕg%\?n5qZLyCYmCWVwJWfj攽\u ΜwwEZGi+GlZ)ΔzjB~kIDkt9ޚF'0cک!L\Nxa'F O pUTfCDz\r ]3-vg8?i-8DЋj"n5ӳjG nqyY_PZCTD/w 1EU#NE\Ǹknq8hIf̝ɢـ]>h\?%Ѐ8#(QEϡvWr@p-C (7|'t:϶Y/D/cm&aj@n1p'?@¨fc"Uܭ4bZ: T9Ѵʮc! љdeq׳鎥r𺋪'Q -=؟;8ǒT@_3" vPZRuWSYr0i񫃵f8GڞY~=Qv-0P!8(TW&`aG=?q. *-L ]f͌Mk(ix`D+*tJg1zDg ™7l;(ȍ9s%oSKk־ bJbUүD!o6Q/._L%GVN]Dhx/u@Fd=np*yvW^wW6IK _?oNdԪYò,,nxBhHI? FWZ5zSGE68iu]E.g0#dѥ(jz?"hD0?w38A4ߔˬx-N40]G2(7{~H9< =+`b.CSc:󃾾BhxB&Z0y)%֣n\->Fkf(eFFћ=FQ%#cj')* y{Y~)-l(a"gYw\;8H(ġ>>OS)ӯuLL_퉲Lp b:nr[msG5h-E;EiV_>a 劾(Cev̭T|7$SOPXzP$Q-C rЕK<]JFҚQm"eHh)Vira/oO<\xSaNϫΟ$ _!I38E^Eȧ6EOC%(6et;v ¼ݙe/;$ݝ.Cr^L55x#H9꜖/-荄1ڒBoMt HT߱9FxQ6V2LkT[C`A2>@| M>$A|u"NvқVyd%@5NH.#{֘̄5EәY<^"O硾/ jRO*A#$[,zCȅy  O X;5Z +>YyOOTB1o ;kޠX6oDE>l绺J`ʔ:;:J7 [pb߇(Qs/yb> Q{cBU5~ԕ[GwYr*pMI "SʒS} L%S-/5Kb(*op\Q,հ(qjc(W;I3DǨ D1&>-n<RLFO;3<:3棇]}!U˸~yB<{D-%MUGX#Tzޱ$Б7<ufP)nQ^Qv /c0kHp+A݆14F׳GT>A.8( M:l̑>}ULJ22, (Pxf<ڎ-.8&֬!3/X QJ*&6HVX=,s`%)yfdqi`gPTF&Dwi WnĬ䏳ٽ$ ]fWY*NG Au~61_?Sɏ Pk/]}D͞u5 yƻZD4NĦ3D:}K!QW*l0Sl[Hhi MUNal7Iei6bc. ql7iũ' U; ) iYT.CWhDoӣb)s\UwlF;"}UTC5-IH~ry+(¬] d<iEM*t'؃t彪$>4Mܩ>6J龑"ؒc~g'^-9LT뺟b񓣵J#7, Ax% ӗ*_U+AԪw{hh%jdA cEE&>U4.i̾La~'8BkZ'UkXSFp~S1Dhɪ;[}[iޑӼTjC7% Uq}`$_ Bw`7i-͢RܰĎnz']Y1QJEꌋ3.ΔDβuB0wmT KЋo=SyG!y,n>tb0.zر3j:faM)~#=,xO1oz']|pq˹UL*Ҧ߫#$2 4Dqqhh*4t#"yj $HR،r@v%m0gJ4)*Q2,Xywtl"GSQC3NTÖL<%hYg}ۊ$gC@g1 HrB&Ę @)09t-yڽ+UvQp<IQ݌ ߆S)b5_}5DS}%VulZ菭mj~3q|UyGOyFB8-Nej},RH2ӓhiq$!*LYa MR6KT$6t8s*ЍxN(TQwW7WC 3VV"S罆(WKr-H3l3Dg Ϳflq1W:;&2tlq",Mν0u߰0|.0pBhi^}oИ -a)nQnb^&=2Y/ YVoZ4UT:Yf?G@s(Y>ʤ!u@Y`@{=DH.pUv^sFZTHpaq}Uj9w׭ހ!p gZ?꜂.ArnrNy}d n~k(.uGs3' R3fnZԎ6%J&jv51mCjXJySpZe2ӰF) {u%=Il%K^..˳GSvD^Lu'>f UlƕpJ҄Fҁ$YkNOWE9axQF1 Xc0rZ#d̈́ג2t[PET%-^mԸc1I Tii/$w3%4&<wY_2MwWӹF>JLAy-#՞&:3tǯ~kaݢ=.b\KS/JI2гCnQ܌v%v]M+SNeCCtblJL0Rs8ͭU'^K>zP ?|p_ҙEYpNghLQl`ߛ᷁z+\1`1#n Œ>"z}*c4Vpx%EG}سʃu,?z`cN\#]NA4e.f݌ e0Bz"8[aVpC$01ԆIQ;=@6NGȰj*uNQ+]³BJ&BvS[  Gȗi@F&8 3x]**-g?0wB?4̓Y:mcQl=:2cwݔX[`c^yXisKF"kFǏ[4gƈv& ƷD[3 :pܕYEj(e,N ֜5na8 L;z8]Elbܿ y)gJ*/b1 5祂JjQ']s%-cyNqAMz5{4*g0%գ/Rt BaTr7+1?7oE=n~#jIoFz$&{6(a :U6=ΒRseƴ 8>Q{1W(<] ͚1z |-P=y6;>=#{5[ec66Q!W[|.V`[6 VY|'Jm;#&jgZb>7LZ&l>!#{}^"GzlBP0q+W@ 6HL_}D#cl1/v."0Vxs2K}>O!PS{*5sZˎNUK@C&]FC{-{ggXi>rɶ.,=g(n&ow ԚWx~&",ڲWpXY[r4nkDoT::GAq:r:eVOu^#R\ hjRn6vс'_Hg{ZbWcw`:8;C ۣEe>5N_^6Q:Io/~]|kEL(v!e&<^ G, C!vsj|Av@F-fIX-HGqU?6WYm7^Ϻ Ës4sqޤrSIe4oDXv7J/1OkMQƻ=3' ;Vtg֕{;;컏mqp/'j|$#Hٙ/8W%$ZFQy^ MD2vp0G8-հ :Ub,@D/Byq94aS\Wt,w~$9dz!7U1M\Qv:u>јT9|*թlNF:բ;69̫WYWj#?7,-} E_ W$dyBJ7h⯼t$Zzzz tP(nc'!E =On~(2L>ղ-}`zg\M^;$!8g"2lOڅs]feY6udUQHG=(,y,RY^*٘_H&[( W9v)Ӊ:\4,A>`I"FhNM2Ҿ zay9Vӧ:_X_: 4, 7WQd_ܰ;(s激 =/pC1tCB{S~8n%3!BOB(y 7]l`ݜ4N/͈lb8Φn|bE]iK^=_4)՝i8*(d؋LՒ9U^yz׮ _(uSIޜz31.ݫ&h%R{2E6.}?]Gi׷_V-FZ(G!#J޾¥4UI@,D LނJ\bdǷdn$I Zt`'t^t+^}0[L}M? Q,.LX_ ]N-n7-!sC`pt|"%xR71U00]sQk㶔|zrTd?Mq~%n} bEgKL.kEK̐ta䊶@')TGH!:o0LLCP4 5 TMB,N;p!3Nmy4d75\1ƒMy$,Ho%eH 4S95JHX MRCԦg 4u߀9 Rf5hZՈޕoF~탄D] &J4 bXifRnN f̖_n_37u(ߒtnagRP깔0= ԡOOuˌp yL)y ~W4LYՙ^94FZ<"/s(c7A:p*eɲG߫eҶh^jIeGxvo.epax!G Y8!CAuQ_04,LdBmJ_ ƐiED|܀LQ._ 1l }.a,Б=g㗖RTW US23WAu7o&夝A3Œs4ŀF#[eKDM;WA\d%R.]=? ԝ!/)o{[4Rt8跬vobe'zVIw6у>3O$*ωxi M&*]qww8$69|CxNo%6N}hJ(.o;l5xHr^e!G: !<<1cVQ~zT9mD~CHu>̢4,6^(dbDJIr+t8K$k'y[/N,Gj>x܀&-2++,5> ϼ"lO-gs\iin{נMMaS@|w *y#H .Ш!s D!X!KaGeˤ}eA\&xyP'fP;TlA蘬d,w滶 wH rH6[GY4Q6,5_J|6.A[g NTsD$1DV)eL ٛ<(RL͚4;k~"<(C?/…XY\唼Fz](n}9E,3#A֦g?}Zb5{L+5[㽡9(UfiykyJ$Y +;~)Q}"C@S/mp.eʹL;1iN$e{ NaB!Zz&(uouve-v2ΑCF dř >z6SƿO ղ&օ=bLF2m'䨋}";ېxDH{ҕg6k2a'wh!s[*?EF1{P vӈuZ5HװT3^9nt}Vp< v2 lkJڧۈO0k8dUA1'M~KfPl[ 'ŎЅD +مp'As&YX?Bo;4`Qϧ+=9mHrW0۹*>X=ޡP0lYV?qaE$V'SQOLwi|짬_Q=]#0lYnE叞Jk8Q!}zUyjb8bF0sK)߯#R2Y; 4_5kwk|'{9==GɧF1b_c5)ww}) wiـId[zZ Q(=DA1B6R$;-Yu5K}e6$iHβbA B`X6Mˌ q 3zLE96s<  Ȏ€钆K,2%v4jk%k 004׎Շ(zt1eh,ZWyQf Ҵz&<*XRn燴JI<8i cΘq 3dnsTx:q M$1Xu 7G2]5- 7V7W-q&qhLVk.$ b~G?v6Yf"nAɻGw9-ga-hҁdc=qn:\E\cU?5[[-aY,_0gM'[&N bQRqT1'7;=7x%$]GN~Ϗ>j#_bv"أyWxlV aoG6+ɗG_GC)AGSGGƝdͣbP^6rP[Vl*)qf9(X1LG -vIc w2mDkPDY4"Q}ܛ/;| 옇x$l]*&G5f| Af# pypYq/o(PvL)tG9\h޾G'Kt|rz;mϑLr7Sm_B*暠9$hn ZMsrمŜӈE5jq<^⎞3&ث%wre>ּԽ!k͇Bv]q6 hL0e/VrdN .!LV3ƂF[QFe).HBq?hDU9cB4G#QΞ9uzvAMS,aV:=Tז¯߻(v-#B@y$T*֞CcIʣG_Cd&N3@%+Z 9TuQ둺qXjr&u|uM0˴e )}xw9ɏGW25C4c/hF@a-dOzF5џ i=gqFPk% )Sr׺BS.*v6BڙS |T8T@f',ԒuqBO'DH.yM>]PhiU8 4u~HyƶK>=BomYQn5N >e(mLCRp!%72S V#u%֫\ؚ>SחE7A&m e_ E>_zjݔmص'4?2a[[); z{Qk^P. 0 CHH_=d~30s֕Ȅz|@— z7-%:KxW7işhci؅:)u_=>;ֹa z\EgZXt!.'YaU}^mQ:Oi=F'{Y6u Q^-cҷ܌P V4)jQkbȌc2,MN|G`RkNQ(ѝ>Qs?(:m;}nb${g oO/3&RYyjDaJ>D<,R~ U) vњҾַOL.??xL"&/y{4~~>v8-LtL}Mj2/fJ$DRtz@H~^A<-RsN?7 ]Nu'?B<-ep"Wњ<0SQ^HjZBfk(G7Ro"~CWjp9P+:y6tu\G ʷ5LvIl{YiM~ۈso~q&Q]"+CBe9ǁQx|xqL1 Ƞ:|}ȧl})h~jPj1l!W J#wnTШ (O29D L6Dd6AxZ 47@ cs(jzQWe&e u2߻B sEׇ_b+%yb3Q{XSpn.No3V6@1C5U/&rS&lQY2

.IF`)~6&2+Tʟcx~}-,wHMpC]4=e}:vڮ8׸D+t;V;WEEׂ [HE %Aʹ5{]<rjo:Nʈ)[mo!L;g_ ΟF'ѴNBu j1Tc:F5BZa̚E56dy@HH d߼Z*a ]U`nW [B}դO3Bi& < )J$YIώ 4"x˼&^!BQ4#cςWFpīƐl1;2_\ѠfuI"92٘k9;mp_a/sI&@M9՚R Jw2wT(Y < ~܎YDt{"|D}SfG(d 1)2U77g1̥{=N2E1hh/&Io!"s&ŠE9|S{Fu9'u^lO>DX%TJ0AζE=j.yP2Tz`5ᒻu':D*I. ~@EzO}ir"긦]d%VK_]-;sx82fJC l! I,Aa*P\]3Z@ː-SY;(/\(C H$59#jxu͞ST/J^ك>x{v?G[A7ڕJBshO2٢eVIg1g9RvbNeiap[cYq*ggQG'y7a#6kIJ Gw',^C fxʼn8C؋›Oxn֡5A( n P>5~{#(PӛYjM4"úQ){V?+jJhnN><9)|0QZ(mU_)hZRա*UbH_⪆Sf϶D'?cE_j Nv@m35;*3#; "cY B=@Wr"ri3bU_ }y<#>n{?6Gh (|}{b?b=^e_A+%o!KSA'$O;]A6ix_8[4٬qi7PCx S40.βЋ <᜛(2ß:okDɌ eƕ!C2H-S"E/@10n@صEGjyr9_HEJk;-8Q>;Om{ J\2LEXRv v] O\(.B16+3lkC16S+/1:ƯQAfRGNC.a ߣ:~Tx;4k `8i$_.Od5[$)-gaVosY>9{nE=a9Ռ(hk =]I?8gYBZ|9gLe$ vypk R./|CA<"[Lk3Bt ÀBf^VQPOb8xuneޡh=>v 4GMl:,gȲ Iבc7#;w}h˴3UE/b̑Vܜ+8aW>!7ASCH/;UkƮ߅,^Fٹ<X qh):]&4)CT1XV \gﴽC7/i4ؕKp%r1,vODvD6_&Qү WXnMb$J(~oPK{OQZtdH.cί~BGbӱGi.+ݏiyotE1z3۾6%L~}C掵ẀFdAbc%~K=\=RfW%(]$0hD(eJr7 P'H[7cKm/ ¾1z7>JŋtrQ4/ˋ{Q*]/y|ʯ&R՟!; oy<̩qX7Zy$Q.P+_xuj"tBd/zܣVPqLK-;7eEusُp{p,}MH?I؍tǎ  b[Y#]a4e<Ό(Y>'L3֖Tz_FnhZd`U %FI~<ǦS=CrJ_Kw[R?Uh̙mɳ@X C`!v4 e IM!{ a 47'waTq=pS2ZƜ)=+z!yN 2Rzy š`XkڥY*uxwk 4+4?48LF$o -p[P(3\h{,WmtnMXvytO {6ŋG`*,'Z[IXBffi%::'^J^fZuB% *=Cs~YPWD9ŝ9D([>Nu8UQ2,Ʊ,Zvvlq1:GA#&JZvKok Voi(k~v5m6Bg􋨎~w9g0]dl ~gvš*t]%ސ(]%td.Ss{МZ5(s٫Ҩ9 ԯP2d~`q#Bl{ &U]<>_L"DxTg!9b8HUn"@g7B<!Ģ; =Iug3~ŋ%/51=~xa ;¶+[;1oPEH9鶦9!*әXS+J 9D=j3[<fl#EఏQ|"/Ӄ4m56\ED-5хE/TGfoO:KQifȪ"5P"[23O~5QÍ ǵ.[/beσD;P!WhNK>Lۿ#:E]Bz~'ZdU]\gG-m UD_rk:12V; ϼbE+?;x߸?>'ҾYFy''3ѝb8İ26Đў*iāFHZ~o &OβDsN,|NQڱ#}QuYa< f4 OokME]9bm&:W6sl] 0M^4./@%_hG]U_\[UD};9/1r]J-^Ǘc=KElL ȲLM*lbϼzEJ>ďeHS/yRͽzgͰsIu)__z%m5&<p# E&ULdf9,Ne&ٽBMO,&KJr/U//ͻt'u|Aq2I̬o`.Yϴ3k J̓R%2GY4[[:2)*Kcq^[ ;_O᰺<7h4Q8< 1.R2ʱP׷C3&C8,X:One˄".—}ƒTP 8I)L sϹ|dۛvC="Ev bNrt9Yx̘YSEIk cz{˼GR;X`( )F:v#R]5]o.e5W3a@:: CQ(ESdulП vqFK^\nM;P" G(ǒ:]1NtfXRR.'',4@S-vmy'D}PpHCgdU ; =1b5 %.` l4VϜ`,;,jvP6ɲ#W;Opt&wM;.zDꌎRTwP\6zs+{Nr*B zԟ+v:ɃǪ3K0X#ψSg3m B?*Gj՛eg^apٌ eUE5{P+̋wg &GN 9O׉ L7 0]I^J v``6=.:ڞuԉ6r;ϊNU\j)%*^'>CuJ.ӂ<*-OQLj]lg&sܦ("Uejb#}3} D!tujhS3 NQLH'k,:GdE˺j{VHwDCҏ^po% EE39ތ L{@ωaV4m$"C ]36A7סuIK nF,Vlca|6bvgMi+=;%]s\C0&ԗ~ ɐ<1㰆}m8e۸2A9pR5f 2NܠQv3*(Ed*"t%{>"b:DPӟDrh:t6p@ F637$ AҙS^ 3U]#ތi6ee19UPoA;B2M/Vw2>B НܛSR@fG|++;+c093shHgY(Tӎ-_TSZ sCEu3g;Aw$,[y7vL->8SGS~i·z>QEߎ0͆Es(z½/_.V:( j8F1`j(YɒiZL?:pwQBy.V4ۧ "z}8EKMD3m(4tyfj<%WIm^SB9c:PRԉ A` W$I=.==~ nTGz"WXϮpyVɔh_Z5af!gӔa$MCXCi̠o.ŋ%{hY -jЋ  KIR{ i& ҝZfcŦ}e9ע J!-A3=CбêL=CشtYvD14hwk9 8DD>KBɤޡ+P:7mܲY8mW?Xgrrfg0drBmփ2]#ݿ4o*;Qny6}t? e$̀'^(K04\I:Uu<K+ʂ3 GaŢ͐]bGPA~k6=hu$ahIqZB$* Q-~IgeGs!ԔtIznEUtUa ^@r0<ۇLa2dmWUljxMuI-iR$iu@Ph&*o;kqR,%z^LW]P2䋐[=o"3F|UNEt[9 VU#ẍ́we;7D/&ƏR 6X=! 10@KxɖR̕!LKsQUL1gaJJ',r8+4x#5m/G]ǒK̾pjuQΪ"=Np chPVG9euHB}xX^B9*M \t뽷52kV#xKq@,׎f摅!p9Z+d3ߚ] -[saӥ[fdo{ dRdI]HwFSvJ>GvgBs<2jr`%+ԣg!͒z4w[B`*R藠uGBCu_\((NJMR,wik (o ,WhĊ%xg+Gݖ'WYj2z9+&O|%9 ÷B?H{2=?=K֋_yɛHgC(c&f`O,n\m[Vdb~ĝ<<7tXCUE1}@sn7 Q[ֿaCHT k(Ǝط{MUpC0nZ~m@k Q8Ɨğ'oMǼc 4; x&fKe7%m0NR̳w-tNJ;wLÄYآɭʨ6@LwұKftzTo[:#x$=`SUQOQ]|`^ԧc%\'eC{ǿ26ggo~G..yB6m Br>ʬ_Yuk_5"O3s)c ԅ ƒgݼ^_Lɷ'u@3歓2A$|5+,Xi"TK} q5F]w@ |XS68x"axrL|=͝4iɊ%k>ʱUrync'o7A$8}}1T4:f陔po (lSb,/4Bh;G.{r(zT6zڣl@eix^͜N3/I]3? %.{B?{1᷌i"YWa`/l⭨? ~Jw aÆ%?z;&w}Cё`4nWbGPj8%,W=-@Me): ޳byJQ=ZPŭzMѴ98Cq)*HGݱA}teEUvĪϒWxZ[,b5nt6>Bu*|cىkwC0x@Wc7 z,Z6 QG5@C2!}< ‰"OYoY dp/>[4z$$ޝzhM7w%y] `29nbvy׳&ZyweQ[M#ĽcevHbzWvOHJ`'Mw(~msdk@7{H(U*/,u# f 52CG 5M[34>+.E8QKJ1rU[P8L. оsI8N|D}kߞMI()ŊA4:WG]!ޫY{ˏz~Ѡe Y3tQ~*=')qq.Ӫ9ovMvnAXxZK46.xxiL U-lexOLb;Z74kQ\zЃ&7B>/XK#+OpL}8?GIBQ-'R~/ : *@lPk~ XaA"aIHC%԰_Ik ~.zrtt1|uPo ѧ<.ְ8ИHF$(OތǠrzlUIoO"1X}(ЕF=ouz 2볺x2S&ԙM2#6Sc;GW8 r8cịc9͟BP;T.*#22^*3Tfأ2Ontq`DxQCzL?Ȥt;c pӼ7 *(X"jt fl7nW(<&0*٨6CF~HGg-!Kh?pp#k#8x`tuXӯpygϴB|SGQ=͂/} Ε.+/ٞF6#eyAdhޙ=bFf)nxՍ\f2jsE^X2+: ,ZjM$گCx-h#B $s} TWjϹ#18Mi1|S=[<;E#r]À?/ s 9Uq+43Bi\uQ_*%PL>0F iO1~$EuOk|,n>Aaj&?zsmKU4U7߈s|"M߲֯WoUD:\#|4lGB /a 稣oWP#SӢʘX2[ʜav5#d(+?߰f7K/X?:eD;Gg>/7Gi}t`WRZܪ7'3ԙk&ΔŌOEa%p膑v6oԤ<=BR$ƣ%T;m l .S+=;@侵ɫ(fO(=ZW&Z:SMEoZqB~^zy7(ݘ;rsh[hT\j3ʜ7mӾiuե2U:A4 zUji-h-]m!yD~5Ro5VT +9BrݯQd2^ǠMH B4U@),Xƥw=}BStFMNԨ2"5隐~W 3zI^wᰣ -hkeco,}Uht)QLIg)H@fM.vTURX8F;9ƙy /(T0 y7hڔn -n·l?fYms")oKyDjN$NzvcEpN(LIט]`QcyQ1 0|vp,(YGzKf{7񴅚-}?|E܍[LiisQFi%m*昡^-zABEty 8:v&{ 8j ΰfg>U) Av1<83λLq\!yn8j^Ìf+wMZ}y~r#܇ϟ{<[eΖF| .0USTU!¨wFP: E8"8Ep%ENSbHqCc7`ŭ1Jt(N'՝.lF펑fx`q({c%ӷVPod*:|bq\EV` f?~lac(=v"~|W|4zz*+/ӕʋEHvtE8%êʞHcv(i'A ITYaMgrY-ȾaI~IUDŐqPLz_4clP͓ueD'=bC }%Ř!6ghȉ Er>Nl{9sI?zUE62hc!G9:rEV]UGE:ځXdw+ܨݯ|[ބ,4!υucgٺD ~麨Ң4+=ȡ(V0NQdCv0֞ar] t( q#0`EA jq%x<,Y&A'Rpjfvw4 i||TL˂|x aIod-}$!C;p3-e!o#ܣ#S,>>ẕi"Rme7G1+Gw(;&f&w0Ƅ*5;>v93п\?G}2sz~wPGqǴZ}̱{ڱ/ɐbcKAqϡylr䜑2mhٹe9g^oߺL Mh9fSQ/zY}۱̑(9m(|Kceg8>:_f^,yv egr7BIwWON3qXrjQWÆy #%g*lj7>NX|}c/h+!>sSw@lWIr;â /V]ɴ#Qi^fnqg"$`ݻO#\Oצ|qO+LU:&uQJytlܔgм?G5Qq0}t, &EQ9$F.j\J0UF1כ~U JnQ-t;"@fBZjcX^:>CHư LZs2]7l7#|Xܴ%ks[߻&^ I_c$?z7ê,b͹(}T*yihwwHC9~p&hҾX_yI&h8l0V:Ro;p<39I=2_t348K{FY/L.]UiAKDr}׷Im|] 800 e8ΌT\5j-[fS#'wyԕhkV%Qt\BG !͏h"?m%G=~OXPP:r#H ?uUud)UuUg ­ _V+=*?ZN!|(/+Y9bnh BZc#bk}iR\SZt.3mvf^0tdZrh͠`d51!ջ+ȳ[ ټM4 hӑw>NrE C*{"ݹkzf>6r@-n\Uܵ+BV.Zŭu8kqA³Ŝh$Pl2b`F_JL)ʛ\Z&H7Fʈ=KXeO!l tX|vهYƋFykD,"j;Kҷgź^#-EJV{7@6|.YD8stz FRWYG>"?jd7&Gt(6ìPf(2fv4|ŽD%eVs 0X5pNR7951?o_յ%*fL5%_rSqS(КE>?gK5Ln"cUU#_ `T,|70tZDԄptø͡ |EÎ}s_L䖡EQAu7KF aI4Bc~>q[=$”Z^hfz$!5F~Jf>rO=>IW˼:n&ln=9Qu]I`ٓaK,2] = I ޜ@F׸@E#]eb =z$*0˕C;5CnN~V!C%̧?NJ.y^]&h4w Ӝe:Oc:ր$j#(Br k1"C Œg]ug6wo@l]OuW2;YDT}􌱲Ob)yqX,%'@1$f(=C=C HFLj$ d6!a9U 1-:ͣ燐35ٶ~ao1X]ך"j4Df aW:b+)G!Qw?*EmA1x;}"/^p3BLxMneXL"c1 6n P1~@ wfjm:)sM؃/Zg\L TOVv33 4P|t.AYth°| <#`{DjF u8$aQr8e-[hA^pŌ+&&饬e"‰:M|1$7OD:S]@o^ӼL~ܪ:ov0X|XOD͟=+iw߸v+% > "HLuW([eR\zźt_% eS3<Σns؍=8D5)aE(2D _H}uWJ Or5JTh߄`[0l(2gS` n+hN,3CDθ ګ|.+2q_=7]6M@Eե1o D Z@:1sIiSfT% 9<}d;\H r.4G9QuG_3.:Tdwե2wA{M ~1Aڡ8No&XK*. J|V@^8$یg0@\`bZ$'(`x[8Bf"wL,*)+)t@f@I7 4 UɅ 1 h&B9PW^֦"wZo}񴥣 1[]vр:JH E}n3Pr 8P%rQOӃrWUKgq1XZQqT.=80(#F,R3:[ᰫd{ Dֳ邫C*k]&EsBa)vuTr Ӄ<}Ƽϐ#=A ?|.}]ø :`m)zLs%.e;hNޑҽ/Ku79 c=S}% ||j*|܆n~Ygƙ5j)yq(0ͣشy8l`hSsYx|hO,ZC"I9-C+\dPɊ,$:^3GxwRpD{=y_t{'ofpqlF_;WFנd8qݞ(p9Y)zifQ-|\eβ6o?S^Oe:?{7C94K!F ׊rȳeVg>aX}jĢ 4u(3祅-w _Ie&QGOa 1 D,1G*nk{LL;Ð0V F]&D]E~pyQY>ȭzz ra!'N`Y&gL@y{骘ƝAwP9}5ܪnT*2͙N1bZcEWR`gU`@CGldKwע1}uW/|t=IT1͇1q5I4g+骻L2(_TO;z< x½pI :sFzؚ&u!j^1fA8DeH2 W_II9* *OF&Mv%6&nCHOp٩yKTqTo8t~0fZ$:"uzts%:"§'3\@!ڨe?D\ڟ=(ˌq!nq[O#>h69u?WsQ7dig;j{ǁ4 fd;h|/K_3ٕCCSlSr7Ge}-@^c=Vڸ|7?g_p0_Rrj yu5mC#ܰX:N ~PD4amfAejD¼uqL2hS~CHvKuZ"|T$3GXxNwO/!B3*4P zxIVgMM݌px_I.3VJlޯapw|[ TLpǔį*'kM3l(vg27DNL[I4Ж!z!=k)BKP^y=ѸW{]2 ?<44^<XF䶯QYIk(cF~`H^.9}&oM)U)I=tSkuG6(.&fGѢ>AH1.bKm$hÎК^*zZ}YJ zb>i :m(-:ҽ^gw{Gxcԑ"Ç!o_+UyD r@$]jYOK|45aWPAv, 䞇MiVnq*$2,Zi|DovT~?dYuɸBӣ5D\u'Q#l lj= p]Ut;L p4sUgBࡠ=L -?SoyZ)Hn)UV;#%[Eݕ!t8i䒝@Nggu%uH61,ΰ) HKp_2f vf^i! ]HPVk:}.҈~sXaV$}/Ҙ$.$it #hlG]\\٭1)@JMl,HD6Wu:`sNϓMV@ 7Ln(QۜN?Q61Ivht(;Yz@:*(Brʂ?"<⊕G]HհOE8mCZSʋNw/}]oSI'<z~p^#lEYi ϔhsaC8pGUB8JO]WTj5VyXXM}ElhcDxQOy6xe,_F먟A s2(0|yQcY絑 )"x sޅHQר `zGa̩L3&2샮FNb^1x׋#REqEy橉Pf^8hd)Y[{(gVAD:YD^ p/Ȧ6#nQfyOaa%0PZ5Q01W>2%>!t]r\o*݌Zfnfnzm>-]G።j-ױ&գQm0%*E ɷكWNDm+Ywz{ wW\H= ԟQ#Tv!xR$P&׃ uzo䎓x30uat6Q9SXGjSsZ ϣ{zPИ6Oc.}wU>&כ!07 <q1*i6Lx3>Cz8ê7]:3e\9 s|񍈖 ,\~H(W5!bA->0&Ky KbϮX+sֵK^Ai'CGr>n=@_ASZ41ϕl7Cw|}ŪMq,XwiQx܀KJHu7u{=l2uR|'4WW4mcAj7Pdrb_ ׳%s}PQɛKw-9;[dq+;w!Q!ʑouP!D^bλY#Pȥ=+\1+aB^GY6<Ȁ8>1b/œfE$&V%r:B o@YQX+3̝x>+Jrý'{fSXa Cd7 YZ7Gg%ӽgQWdj뫖g7V5~oE`D?O!SC+dMLH^eQRoHՅ,m(x ntiR(;P9Lu @%R (OhLY~hA&hM1e+!PQ@p; WbMD{Ew,+f}RSԹI| YDEEtgU>.\@tu>jT97wd2|O$Tqͅe︳`qs:Ý>:ON{ xa߶ձIPsMݾ4y*Haُa~wt9gjƪho"lg&j,Y_#z#x#nPcՓ-_TUv22 Y d,-|t2,BM{ԟð^M͜&Dc^V%ˮLfGιLuR`U xJ,}nhپ\#av?O$5dzΓlCgpS˄HL%={Y;>踞7g<`] !ӌ]ܹ"t,4ƐA;VO֩r6Ձfb,4O})~u@8%NlS/d^ʆAPX2ZV Jx.$*•/ 0ɺ+Bi+%; ,sњF%塳#3a ?[ !}4pEV*Z~ёUgTί;&]LW%H y=PG難Skلf04]M% 2&,|Pk4I>2h>,00\vJ=(u l;~ g!uۤ⣏S؟WDT3O#KNs9Q[ Qа+Vi=kkv%ym1;  5G %i^#~7GBmQGeez(w3&M$'D]"O0 yh'-1sXc7p 203xo}H !xxJc 'pealQUɣIo:>9 oYM\¥f$ أfp{ϻ^>̂"3vQ2*S /<*g/KV}t`T8$ڑf7ϧkJ&+7aIaѼ ^rVe: ڼfW|rjt EK?CxdcHJ$k$$RME(Fz9V6\/N3]nNlSƥyV ӗ*;2i޼JxhdYj=_f3tW7 VpKɚS\´y#^$O!1uCopg~%ƩJ4$~;q<JTt94[&6M̈́2_'b_ bBv Y[_RynT\54 O-Ϟ#^BV A,DH :k,#q8G_#%~NF:_vf t#Z#]0I]a)$tm~q3$QL:C\ݰ[݊ ^_ew77cQUGı3;NΗ{lq+%lQkx4Myp<(,hn1we!KjEXnzggx~6-Iջ͈pŲ=YL(ͽp뒿` Doc]%?:*wy8oqu/q3{U O R{cbZɡECsf.LAB[-#Br$$H?ps,$ݓ#Ñv]g9p> {]]nBٔX\DL/˴5Pl5E{KWr {slH2e]f)8 >YK>z>\hE! LO'5RQ $ 49Shӆ1.EmWDMl^aj c#dU$w{`N!3TpAL8 NT銦~'4GW]T1#f& Ns*ߛG-Jf4y{8P:dܑP߹kl `XyWNo4[HYtN=jyUY>=o:N__m olc$O>nB}!mhy'*NдfPifù0D#U"qgڜMe1\wyt'%4aDw[o?p)A,NUlܼ(:(-Dz!IHN-cΫ-bPV kKp~ssrg(}nqk^o,/jzSNO&xt(.=-4I.SYYPl>=Plzvp_ xRjRrH,K*}?8F vӜ_gX8!=}5OyNC(unmӱpd!>4|hj-9@wZu1Hmkwm`s~u+嘌Ͼ+8{ܪ[?NvUz‰ %͋*җ粉qs%шt5=$>%ZRkj׊CEtzY v < A> KxrE{Egc (Sz76KYJS<>W ;ҽ-[f.OzYpfYw\:FtMW?JWVD1&>XʘS4[w=! kbI ]԰V?#Y|rɣ`7%j\gQv/g_@)̠;SI=~CE{K>۾ɅÚC&+*$O qyBfr'6cfgx$b" y+yE1&Ufp>40 Z|e*"#o\uQWI{^u2IICe݄Txcn^0jtw yYn>O<4' ID܆ ^xw -[`*ƹ@5Dy X&aW#\Е!:c$y<7a8e }.mI˼=Ōl]ĊC*?NiUE_%2Gw%4.Q1D`F!8Y Q .E k5|'$"aÇ ބم (څ;?oi| vePkaa6E0-\+_>p8vٴ鹿,=".|zğH,lfsO /jYbl*;`ؘNWRQֵ=c,=Fy4 y'vYeӷU 7"0r \5YU;0ȬrՅS#I:5~@o16D2nQM-ePt 1fᄌ,H EaVR}ϻF!wi՗!ۓ)": _Dm`CQLf#^BBhj5VT 2vVG}LG^HTHf B#uSY7ЈQ3(2ȣ̫sՙ3y._Aʁ?d{9KyoT% soX;`՛׸4Tg WDalW.}y}D:m;zwud2`h1DEf< QѢ3׈I Vy67AZԸRmv|h[ &)ëF6D<-H SCĤ.FR0(ģ8b4\;Md9~)7wBa8q aLRgpm\H~!p pž<&vcJm.{>=_&W1l^lK=j@GtѩiȼF鉆6XK!\%J{b P'SQIOӥ*NӃ Q.op%?zmUPZY΋:QqOXoQ/u]&~{0EK.rtKNRZRI 9i #'νʒozvuڳcѠDKΜ ,uܽ K( J ~/,.$M?;h.%[><!]&-!EVrhzB@T_!P.zw}'\}%&Eskgvk~MUnBJ ij͗Qphkk?Dzh\V"w 6lN)>u0xAhK}Qe?8b~eEGvig':ϰ.(dO^hQN0ͰɺM{nzVXBu|XIa@Y y%SᏴcHF gц遹6b rTqѲo@I7^*ѷ<SOogB4d0 1ªs 386*'hgcDFG.ƵE|Գ0?0ҖBҖdWM򽭮HO/sS>Rƭ:\FT3v;i!yL56.QOzudK lW@i%4E囙AeKw(8PpqZfjbv?D 4$e!t(ܼ@kDitC._qį uxC o`#0A}ך}ɞ1迵oO qWBRM jdgQsM#;< @۴I_rk^9ʏ A*9&8rݯRQX*3fhH˩O/qB<يxnLSXh!RuYq>h[UeZ<MS2#9\Ҟ2}U_@owzPUҏ9QVys\w+[菉r*_ sf밸?To(\=i;4ݣ%Cv2bz-rYhӂؽ8! =[x|@&YŸGS^ܝu$SV8˄Pd̰0nV0WRQH#8on҃n h~E.k l&#LWAmFi3&l3鸖To©yHuGomèI A'qL.~f"/S|Ջ<-n'Tr|egNɣi$~ܒ"Bn@ ìAvȄ6f1l^#^O KJņG6(`TH]T̨wT (V%17rսC&v tfe og(ҬD3|F34Ҝ%GǢaΰ݌RX[0jsqv"=d0@f`,%Ozȶdap垟dm(ߦ+6d2(SA[}~Y;Tǘ)#{uGn(gF1oZћ=(j@.XgrI֚ -3A+~90_J$OOj's8]eа,dyԘѩ~k2}JNRs/#Llpj P#ZjfVEDWzua*LD.ltmVGy. 2 (Z,|,p͝]FPrIHb~ V7B9uX"E;(OPP 6pj C뾰 x.vfg͙jS=E0O{f!D>&8z?ڈ<{/}aGχ(f-vu8eZL#ɂK^f^FZh^oT@pdͣ[qFMOSidoBYef,%E9HvFajN(%(ȵ !R[tCE?7cQ4̼=9k:V9{џ6@SH 7mX{idȇ垇(6-x0]ȵg{WSP8~>ڢ A+I-Lʃ5w Baco }M*AM}&9} rvU8 =eowEK5A_ZEemQti;?9ַK3?e⨠c+w!b &ehj#EcBixC 4R+ kߠ D?!M;z)H :#:kBp &qGS FCh$ҡ 2 |h!5OL4[&Θ-: <˴HiY{rњȬOxO~gefRcW$u#`9mbc>3)f7sh@5' @&2l_q3[`k@ڌO]_<A' 6v{Κl~Ѡ9Uk^&FOVM I=01'f#6wTǠ>U[e $%z+TgL`\W:"A~sF07qoM[C]yDe-U!&Gf{2ȴQ[NɊ{ TJμ.] }^ 1M#fG*}Myw H,-?Hk癟lR!/0YӎȜKGU];+UV,Dͯsa"G8Q~eN%0;&.lnXB!R'H2 *C ij Y  8]CpV8q$=?y1inX3 haZ C?y{lj:%<ZEXK6HkDyNJ~f󁄽k"e(p M=gsZX Y/[9QnW*\uMQ/G#5$D:#$sQCwGs?=9kMk1߮Co+;]Wз4<֪(07ۖܬg1&}@ޒ2X)9ˡ> e(/ 9*6BQfiVgGLU+\CZdEdY3cC}Y Ŧ^ ғo6+g8F,Go^E`n+n>Q̬5n&jN?[]].H|#'ejXei$O!RnS.Ao.̓sۑ):KfĶ2M+D0XPbؚ2]'odlt)kL+ 2YbݻTB#\x>j\fn!Fw+,OB9* m9W$v GciTqGMXfYkeĹ6ʅ|kHNfiBC^hCp9PV[g3[@Jy@99ΰiSSY,kn9oe^Ĥ{>x^GZHށ c<0XM\mVAs''_iJ~͔F. *aF~Ol-@.=0L;tIS+P(3& Es 9ɥH)Mog(>MĨiܓ>]}vQ#C Jy?XzqkaCkj}%7uZR'LمW|e;9 Vo;}%&,@μY)aJmޚo ?M(2}U2#vMj?yrK_I3l)ưFp̧̙Kz{q)ʣQ$7Y;'SjZiUĪ\Em=T;P|;P$g2[cz!DujKT!>4$V$tz^y8w hH|鸯P1$jů~a>^Upӳl-8('LZ:uzxsbX;HI:EC.632K1_l1ؚ7S=:F/A7?6֚7F;Hk4Wڗ]e#o(»~HwOxRŹ<G7@ t$B'"|CT6,ɸUzfK-l=)lMn߰2X j/ݯz NiQФyh\CﬦGpyJU>qPupsᢪΑݼ@[e3G_$yǹP[ P\zHµg4c|$cv<B {"(A !dW Va~q~tmf~G%τUKt2kqvP=o2ң$N k:T1㬁g]"56r` wfvOzV[HJJ(A|麢dų.H JqX{"a &nd78'W_E&|-k`L39jЍ,'F"59,s9G&17}?ucxWUcY٤!{0ѼRVJT*pݟ^L6O=T~ހQ.%3 0Y񎨝ف$h?:(˜3s!4p rXJ (XֈRչ u<9gH%Z3 N ):xsi 2#;3$(Cv3A#~FvU7Ot]f-2~?k&|tv "k 1wX!yMc71&x Ck|0@ݣg]K蝕3ww s"37@Bˎj%zu4n7# n;\MQNų^5OZN.ktIoz1aǦj>znz K H`u4f0% \Ӥ=>YfR&Tx''s /-5ls7-@AWL55YzW9) )Z|GZj_b"ЍaflrRModa<ER N̛95Vv )KM U/6{;PpOZ"W_ \nWĝc/=|EfneTJ\LW"q=<ㅌ da*9bncߏG'j]j97nsw{@qu'gө\g"/=h8eQY>n#1NY9'>M[\ip'*@BwD w{ q>WCc,xK~"D\vaU?)-K F cz& `kETMKyf_XQ@<^g90ޓX[*:WYCzZAy fO$dޅe l=A|~j$튍/‡'3kR)i]WܲHk.l _%tƖ :4{f!#2&3zDش8d.c]YAP9:]gf=_a84@UXgsL#9U.tzb/RxkV/SPQ8_iJw~SKP-V-9# 37lXi>YF=sUÀgЛ,z^Yt>O%9|d#2C3ml!\xApkᒪ˱v8:)ց^Tp+z ֭LhY ich8d]Z^޺vޜ/eT{zByd%A˒U+aV|5d: ~$Qγ#T &&ըm̺ΈuV"5%QϪ:\/:ڕBiLw oS\naZ2kf`^p66+, ʠ9.r¬<pb-3jSgYvi`Yh%Hb~`4CV[ڍGv `H|OgnE$+,'^(&;9аst!uXϦH{Җ<P.=MY{Y~h: $ ?  ۜM)Qt->|C5r̉܁҄8؂cmeؐt'6ZjtɩŪC!AΑ)1LW^^X& E-s·<$^n2F*zH< tF] .7z}= q?><>nlt d VeLԣy^s Ry>/7q㆞;^ZvDQW5tk&"O4}xMAh?_(|v 6~1IԈ {.@|Q[{\ [ceeESe?Ҳ9ҀEU23Bq&L2e5tiiU~qFFȉ&hZ4f{yd!ỴYd uTzi⁗bMqQMoLÑc fqcc`:rG,Tl|<jDQ)cfD8dW{Ågb`kIA8{!4ԼI`i|?.fz@QrJ.3rj{ʝs!!fFM(gE l8;1©AJ,GXhX06?gΪF:U-77KՐUC{`F83HqbG9ڦ'pEs玾KОDxӳC:ŧ:Q0]qg=&;)yFM ?+H(Fu*JILOb=u"=ZY#ggQ{ot0 2(8C-V2\",B7fsPQӣt0Pjr6"6HfO[QbyJ&H\fG0םK"1U'jUͧ# P8+5?1*L2bsx{6NB66"&a[U-J2N|ON&QFGC i30d"RҪSv-|kdGa7I*ɓTD?M}rO{c8,)F+{5pV |µ6ʲ" nIǴ^X;T~::r."6'5lP3"MUts[3$+G; s/)W m+ۈzYZ]*= ꩽG5-䚐;sE"o|OӢqd8:2= F! ecxm#5B=Uӫ$ր$3X,?OYQ Nr!&)#DOfn g-{A3`2͛Fb}EeE;Hs+2p\?m/v6l$k1kfU4^2ՔN7gO-;>FV琝߫zr5=7 Qz7G"e׌H̤ #1447瘢j"/sx-[褍v}605u54.7Ncnƾ6/+e0!E\*9l7e]")M!Ê,BKRk@=)͝^Fմ'Z 6>Z4|tG =toUJ -P謶㾻j(f#SÅ Y+j#`U7۳Ѕ]uE{1n)I%'ޮ4j\ndN49BU+ Qat3gSbt/ uB95gfJ֢\.9L^)JL B XejZһng*zy/浡$%<:"Rş3w 7<ӘA1 sG)$lK3jt..{Xi詀$hrGafщŠ{,Β> VbFÎ8DVL|w`yǦ%c˄Մ.ΉbJ?ΛcȘ[RcZBK7)!,)6K /K aƄB ց~'1ϱqCJP=٧! <{g7>1 "1$=?h,۰xke(1:gGVΔN:Ѿr# 7u/UZ! .ҹec)ϳK¾~L/ =wtH7 XϬv\6VU, G%VbU|iPr .:[Sug[g 0<ѤDΧ[T -[Txrަsd{Ƴ{lVmrЄFng>09p9Y.uF~ ok9s0]JUD:xEY;IGJ1q_;lّ9VKҏi $Ջ2:@Oo(u$I >4MvQ9HBkӁ#/l蹞Y:/g%ߎef҅ϐgދ?y SWa9RI޻lB` VXz8KcnhIrQgIܓ"~Uvٖ"Ne|>vH_.B-'ޤKJƙ1yÿr6ks ?<վ,ON|^tԺ|WT̙v@g"M'[T ȼ`5YKo. ;9g߷=0OK:;2#,TB+U@S+S¶G3m3vdlR~H}eP<|H848G|E n(;Vb)ݣ́#VhERn9S=P_< YY9?|t3d}8J}ړ=4J{nۡېyO9!}$6q2PK;nRCA:6<9fҕ&Pws3 Tʸ$Y16=$|@?W@?utt(.nlӅXhgB?}l܆Y/CfM.>W#"|1{e~R37ەԚYK\gpRcn\ֺd@~ώZ3kXK1ݽ)+|n)T PN ga['iǣ_th!#8Ay99o &,ḕ畳B44"Z2$(\|#Ń}mudTF"GCsD?jZ0]j^î6t 뤑 J?-7j%<׳t۱n\=VZptxhn9pXSyh6dC~l32űnÕe۝[hd K'Sm ヨn1_.yvf>LnǮhp^%N'@rhБさxtKChӍ6a6E ߇ύzj yd6ՑLxl+7%;Kzіj?v'+?M-ў?7{ Ky5wUAqJb>fpG'0ph2w_C0 w&tVX6~~E/vB9שLHi+x2kZxy}N)mQ @k9׹GGqZk)'gr ܓS2k} QVbXd)O&EBN}}v۫ o=Tr"=~!~hiE[ R{_|>qA/R Z{]SiX]5V 7;HjAגVy>boډ ߃7Ԧ&IJᙂ8?Oy:1H FLzWߣPn^%r^ᖈhbDL^{/+[a VAfmJ&T=RQt॔],TE Bei.EI5Qi}bBCPCr/j'%iHEQ h<23ا. F#V$/(4.6׊C^w󉶓7IGrVFRDxC3}E¼NYcqm. XO]jFtytuќ%BTqӈVFxZw 9Sh&i]WVsCB4g ఊCeN%;n(E8Bo- e7%:Ƨ< rb 5QN8 ůc}x]gB?W=xgǶؽ-0(!3ahbxX9PgpC[%x7b-7u*Bl`C_\ʥ" e"\G8@K+ DWôB<7ĥ_R2!^>&Oͽ M3 F?Ka?imNjl Ci p+.)9$) <\w,2:,Uߠ )*q5 }ÐY$L:!Q~ p*~e- 5I~EuRңg2"%!A~mȬhٌ-?:VqgK^pre mP~@y^TwPjjJS;Iʃ{ֆIZ'֘/!eE:I8{f|$Ě)7A8A:LL 8#@Sr.5]ʬ7 knJ/]U7}[ғ w~7}o5tуJ]d|bjL7o$W?DM 󂇽 fD7OBXdk3P9jaEz舂*zrihM0\qd&j Z4sqZ۝? mpNӒ o%8O]Í53Bt;Sy+GOr::w &2љ+UwI;SlD8r/񂮏#k;ؤQE5oݟ:/AU& |t^ވ0}'nA1 21S"} O;ʬ-548}˙NzBb4eX{4e`F-.TW\Lq2?Jʚh]`q+$KILryn^#Ogo0eḃd!c(&b?(k:U']t..A `4JckSXz0sCIwMg= #@ƷV}:/)iENJGxu;_ؑPdtDpEL+)¢D 2Q"X20UM3Lgh| yazI't]f-qz B<+:%C:N_̑U~-=~(d[VFVʸN:V`rHF,S!I!On {CPdk$LSg;MR/8 Ҧ('d> gJ`EkX2&~⌢G CKٞ ELCw1k">~&hYi~Q!6b ǏK2>Y9'Z߾K5Upe>_`WlT^3gV5c'dmG'_AAͻu~sge*"wx-u|Ͼ]xuX TbeHN9$g}jYYZ[4f"%ytLShJUKUahoh 6UXzKMqj73&V_z)iPyύWX#4!Wq;`$)OdM -P\q#xxM9!/źF>0}Ǵ`糏Q=0kVSn s<7ɴ_O7: )kfW"CKOl#d8'C=DAfʉ1N'?=:Q=OK06\Xv1>OزdBx:}7yڗ.U[_C'&y6Ao4b6vDRG([+bCD m>_&c+m~v'~1q/v~!VM,+^I? <5jvUinj}>tjmĊӆ2)_ 2t2ΣjpCw8O:ZXJ.]7~}qaR ֖\xC}(=oBa-nۜW؎UA@ }]xh1>7ͱD$38 M A7B"u4dnn+>?)!l@!cT*3n7lSsbTQOR\x ,;lN 5hޫJy7[VGF#8UohjQmOjR{lg"s2FU]eɴ%H*p{K54\XY3nݓ2*TA:&iKO]Xo]u,<ڽ) ]ZN.E徏SxD )l28,F`eZś*x877]͠" ݒg`(Xra_ "6~Dins&4h)'P.Rl#>.DFBOw_uj.RR`^T/Č _ဧڍ΢'T?yXm=,/&dD6'f7˛"/ZYцXGo RGcqraEA!2 Vb>[1i9G1-:eK" .w/Hsc-z-%LAS /k1gr4 ֙]QVF6ǦGrjxzkE5$Y<Pϊ, XiuѷLPXv1$R֙Y7 '5*堷%H U/gݵI +!{T=2ER3đZ|~.{턱rQKDBoJV"`0*u@s/kce<ć 4U?yX17y0!rKV &Mfh.pYrm!f1}S >hCMyo,( T @4 I&:gåM,|^"RқOΌ)vKK $6L$9ĺWURNOsxIiY/N[DdZuFV@]E[ΔIƼ85L@mL$o#I )] _%8^Nk='poR]T g )|~WqWpDeG]Hj|{ .(!/ʚ !87 87p.EiUO7õ?y>]xɰ;i8#Y$*ko;oP ?0pMTzC%zbL ! ft֭QYr\Ecf~㝠} 57p٤H^AU7pݍX&(E\H[2f (!J}]/ci?`m2+[sO YTt?g"M!4!A ts+;㫹s}x$]R)k6=0o #gվ/ՕGnI , n\FBF9cRD(x`5RJ$8/&DBk'tPþa93sSD\J/bs"fOށ-qF$ </}.F65Eڪq'荚Ii6a͐*r}] ќN|*& vٔ.ٞ+F3&֚v;Ti2kKbF1O ͭzsJBRjz?8iphLVgmOHX HKTJg1B*4x)r>LY6KxBzyZ2-48s yE3}:5CPz0Ѩ0_qF:I֙p48ҁF:W4=Y>n Ijƹΐ ҫnai6z>4Ԩ" @L}3y %6gQ/FVK[ˋ9$YB늣@{Tkk5ݠƢe5Z}keP؊ iʀėaŊřT!߸6f 0fHu!m@#cv`E_A3H.ʨYfx[[,^Qr6ҧz%JkKoL>uWDWv`)orr=E7_/8Pd\ 8#&Ѷ7~OWv qU)谟ʼΫhYEE"r:L{f6a+%O yjٻ9ϧ~TVHKrط$i^4$RE~5O၀Ζ\x(QslX4Cg.*NW ,A̅x/Lr!k+K̷;΃%PR\bɪ# rtOQ+u+il21}בeiDBgrQ:\#L.|Ҟ%odӶg_xROf$!_v@x6_#tVm7t6hljǭflU;R%pʟG&i=\ Ӑ]P) g6k˂w~M'b2gjcC:" KMQqCO2N:_8pn~frxM.;yFcTn? X%΋;G !>C'zXY0 \tZY^ ԔydnJ LQ7>Ou;eR]>)g﷬t mRP:؎9: , 3TNr3\Kt_$HS!{a&+.^;(\c/vH?HO3*V.PH Je5ЇùClԴМ(mgujh/KCRK_O9>n cqQe y;=95 D9sا gm(]obƱ?ŭu#䆕b}3.5-d:DCܺ,2Am 0Z5R@d]9NB/k8y MR(y+x–Vx{j8eOh2o]W^u>^Q2Ѿa[{zF JѬ0 ZE-ye8̢ cfP[SUBgcދIL:Hu95:{'3I3|9<9?{CUgqg,SΥyQzfa?xh?Y=|~s|{F7X;U~΃o>o>!6G#υbѲJlBwN釬sdzt*ѭ4 6?qBtm.䯬"tG ̈́[8hXcX IBȊiɫ_IHcX:[e^ǩmcWGo^+ieqNrH/щ RKNt|moΠ)äCkpwﳍ7F4y>~=z`w['^[MD{\sC6 IU]NnEq;ǏI,9)߼9du~ɠ=0s'CTF[z⋅_3dxϹNׅuj<ܙZ(4Y"4 nen'`JMm dSdi(FYlTkF*Qj64vZѫC1fnghI8x(75g&Ucl)+C d=\Vߺ%G%l8LgviSBs%Xxw͹rR^Msn svy"JAy-9!\3ܢc ˩MjaKF*: 'V=Gb"z pK|7)kFprZFPޝa?uc5|UþȎ R$2Z(0Yæ6m[,Et=]G^ך[z'Nxh3a%І#OHj maa靤~95b&-BΓilboxy{/.Dfm!+AE.j_~g}/6oJJa_nAT_ POY8*fWy`:hjܣ} hPZJmHaPD E}U8xd01gE9}J@oҜU('rNB?y1G\qJ87Tw & 洉IIw 9hH["p]j.&xjӏyAE,J2 #bG3;#1Ji)f_h03g]d|qtEqf76cs_m 5ݷys4|yuٻrp@nX[sG^/WptBW,nKX*AԈu>la9\ƤkT&t_m]AGQ5r~h7}{EͳJc(&s,PP+ ̏{jsoʹis52T2'ursdr=SSJZ%kr<Aw*s z:TH˴\sL<@;mi^s*c uf'!@[됼5O@>1sMXg!{f?tԣy`ԕNIgeRhy9.gw?jnH% wF(6 |> ~̆f!=x)*+/)}Vh^Iz>{T?vyAR|zf/BB*kSKMH-Oy9.K~燊+S&:/1smIm =dWn?j `yl#VK/RDB<%x?_(Ǘ{ $; ˣ=p‘>Si f̷[* y>_b[25JQ΋_h#_S #a'bow^5X2dǒQ |Aӵ/-ơUR`SK]ӴYӞMX`jqwMYzMU1/H5L2#L(sUD$ Iuh4!CN|z?G=M-[dGBzlj[ZVnIS+ zr 塨 +/xʽ^HKgLS<55~0S?x})Ub-cBW`<0s(6.4u"%;I;#EZz#bNoԚ;gr͔8^.o] 9QKJۘg?YhXMlm Uix=o/n,x]S;0}K(zXMҗ$U{f) nHk"߅jCM5|a[Y{?0+/־[P% dRaڸ{!K%ן2RH-e}Mo1p+x92U%ʼ>R-l&S%)#6iS(ˌ,܄KYQ(/!#3Df`QGڹAUӖrǹ>\yE 3L`r|0o \Al>HY1zz0YW1gBtmE7 N*gXW|:쇒ѹfY;`8)vsd:2ﳸq:vOH[lƢ{iQ[ͶnؼB)uH),={ݣ53TӢʳJ9iBwkBt÷_p$Ei噊F_Pܛ>쉵jӏ^@tlKZqDBq=mF"4CdUDxGޢƷ72?+5r-+3e7aO5=gz&K;S봍0BBss{F4>bt|aBнA^`w)uXM>v8Ҧ:;5Քxi4-i1n>#șp@+K=rgRs#*+X.\1SI ~N t&b"7/P͢2ênh]=]uj7Y;#k 5kO0z<<"&?fE% ,fdy$dmfYkRlF LS]}R1HƇ8GE9W\ ;5pVi4, |4ȉ8:D4pJ[L. Hkr'Cgq(YH6{ $V&G9Qz˷zp" #%y̧^Zz#wGxh5U2"dɎ&I#L6AMLD;l. 'ޭ1(O;d9yٕ=W-*L:u9U.X=DJntA80cuN~BJŌȫ(q(@^Q3aM)[ ;37\uUD۹*+1RsذKӋ%B|Aܦ/ XJTG"tHqPf'UʐW?|fN_۲A:>,V gv4k/Fuj5Q`C>|pͮZL{S xtKFkMY{b vo iqJIΧUUN/_݉Cުӱ+\rrϚY|GŽe^ a$JN,yP܉|O #gDNowL\ۑLAy~*isp;Gj\Ϻ5_6jN|D!07B-|w+m:G;%g3'~V_ 1w1<Ŭ=Jٔ}<Ol_ .r-< }"nsu]w :S; th2=&Zm@M wI5$hBi9GYZu-?8v}~nhXY*i*@BK6((>F!}O ^T~PBud8:sğKğ6wqB ex)>"OiլFʊ˵;,~ZV`Jc_ ph!fEiAWJQ~ 5H;W3s3N$g<<+΃QĜɥEkȀ4f0*;O w`cbon'7I^c,Ȳa5)ESWd3* {w>&ո!; ݋d7AvX2^IrP5Q/i+n60uD*CCJ56.p68aM1 ހƒz֤j:\qƮD{9f'\X:|<+d[Sx4Hd˽$½bZ LgPn[vq;Y).]L̯$+ *afe/҈TuRB}zCK/hԿ {V?Eb2?F2sna*fa?c!%}L@e2ެX"ԑ\ K33Vʢ\D'h+DWiD' )J[{5@3Sf $'1MN{èDRqB&Sg?E =3gS||OԜ/ ǒrWaL'@M-Yu@~5Kנrc}:#ky r Qc8 i>̗ouI"Wev1ߒ M%Q?yބVGJu'ߩr/oZ"|$.bpܼAoXɈ:euHXnAlE5G$x?&;-9lӧ5 \&%Hu~:5 _wfVC,v#s7nG"P{\) Xa|K3y)Y鉳>T~Z66o9vQ}G:l39b`sR/8)ݐC ^qc27!{T{ݸe隩j?S72:%BQq :7 LZ*'* I4qBM碗~`ƒRl\bx4oȫaF) U76#ONbI)۾=ʙ1QT DTnQ#Gv}KF!c};mE[G LOئmv"gtf.:@PY!U҂l͢J9ߑ)OM¥*o;Z(TgV"b ~W* ?hUd@Eӌz-i^ނ]g֯A~*^?+=7'Pp2Y>3дuhfY8Hʃd}6:=e]ɜSzC 9Sw~Y u~=|e`ZjCӋC4|#ENN1kU>`8Cf LD!o 9<6JbQ* E s C"u'd lZ{kaCk:fnw74i:*-+U" aXn.(ԯ(}WZJ)>}= )CxIFᔢ!KQ<7pz J$s> S+%f.URQM*$iЏ9R&== <7uni\< kmnj/ FOlYQX9o5 ;B X\OIO Yp^JJEzfJ ue֐ÿ f.:gب-ߙ8e0%֎4s̐7_x9tZ]yqAÒy`nlq)G"9eØRR JPŒ5ys'wV^c<V:pTR4^Fa)Bm.x>wnX3ya\Kg;'niZx˲m) CN'OD1gh1eȈ[jl#?hJ>`hĕe9_~eknĸFoʦRy'$ÕAʚ.yP*e?30MlVbLzzŧ+{ʦ&ꇣYak5pP Q?cG~rlK)#R=*[f+YuʚI$-h#ˁqLiael]9s!۷qwpI~3JʚGnty8<ƴa]4Pल?݆Rvjs^f8:/^As1V3$-`)[XOupͥ$ w/tqO^aE(Gr|Y w̯ޤ N>BXgN0^Cϲt#O9#ӫC;s/LG#;1:8j$z_N_Vȭ6D͞~q譏ڞ틇XǼV}lnw0=ҐqM~fubi{DO/S%1hE] Rz7v8 PgACA|+`"mNԉACfe JYDDis=k;[kvӨ=6Dn7/A}p׹Dw/͓Zs ^#%z?+iԄ) G9 8>= (144Nt.pyIF$ra^Hi5&ռ>Źt~AoQu?|2ꇉHԸEv8X64Y4i`k{F ssO{Jϗh>͞ .DyձNJn*Lgu[yT"vXcNXUIڿ0?FĦrCY3yҖ7N&Tј垱nh;ݻ}[ǣ ж!3{EM[9+Eݹ/}N Ɣvu{ƝߡZӏ`Yȳ%E;Z=tƷsw3[5P z J}-ǒޒ}Gr.V"zv>)8Ԑ숞{>{GټhNOzM[ уr".9G$_V2MXco5Jm>(4bQ:=- jΖZ 'Rqjˢ"4WК7%L;UJ;6&ް@Z_u@_WFS%md7Xu>3)C7/ޡ0-_s:iA꫐)[+@TC; 9*=jrop>r% my&b'*2X _H/Ғ5O^ o4 Y "GvӖC:_w*Ӈ]Sg鈧.`5 5WEZq`HirΝK]b~4^hf=Q|M1ki&268qukv:M9ܓ~EJCwqꤢޝOy̡Ⱥ,[=m&מ,'Gciv~<BN=>`/n²(Wؔ"/LmKYbǺ#+; |rowCqljL $1wUSzN4OSi7zhRTGOfI4/$#b>)lg㱅=26٩GhS%J (ꇸv :% #&I 5\1HK=0"mb`2ʜi϶ xg!!\\==5~? {MJDzQitWg굗|榓[Y5jKcۥbŕwlB9m}1^['9'u8|di8MeY9uj#=x?JE]Qzg&`w-LBJ%E^22w#/ =#1qƍ:$(_JXvθpHnEݼ;lwTE8o)u{d63l<].Zn|-`0~>"!;Ք8i{R!3Vvw\ءlm/H8DOX-"ݯ_)24+= ҽPgds|;/H_8W a0xxI hb+^p*7BtF Q+}fwZYn9 UϣKX 2@wE vBy3W׋*VU1fFN*+D1 CH)oDtiKjp<}8u&*o&B>&RbiK&1 ըYGbʦ2K'J?_d833C8'u/1m//Mp),'HU}!?M8?|?~Z|}qsnoRu!v!pLQNx?UgtknUo6Ues 3kʇ&!+9b^37P \+qf;HbUVJ85V/슉N/JФ^V,vj=붲nD) 01SVL٥8ʨI1ؘj'U|N;dyVæ2HI)3:OJXrq2jS5N)K3/I)<,R^{NlL d[B0A^FEOfiRs{C9-{UvK9`ss897 C@ܱ5!nz+zc|_։gMs8V"B- 4rCZGfOY_|+yf**:#sq5?RH}BuRsLٕsnFZ eٗDcfZb ``֌TzVf|͂1XP3tnjGOڊr6q~v6^ H&9!|mxmpN l8wQ57HbwQʀn) .DpqN2='^Juy #2ۦE>@{h:Ev(Y8` vG >/F y>+@9bXF]G/;քbϑfu)ib:hMm-yjj6@6_*#Mæx"V" Q)cJKR9/7GnFWEK2FdF@~{<`EZd`{c{bzlrN#݂)D} /;FwJISg (Gݬ"$ie4C vב*Ē6]L5G K*·ܩ҉+%'[YE:Ļ}ּ#'DEsY&~*h #DuC4H()E[t+VFĮ:^bM$N0K{:Gd+~vu?WZ UVsvkr9#9Q}A k@ X =ڮNMXKu`p\v`gU@n$H4NI^Yl8I!ow-rA9t8989]̝_}w$.y@6obZj!:.yЫWOGȖ\C.?{],#[))g~RXQp1y 3hF=;6\ҹMvXQM8I͛`8rX+̐|X?y<*e5c OI|aX x U7gíDZ\pf$i{H;mJI ~lY ]}&X=$㐩T(84V.pC![5+.. TBzϨѯ^AB,[IT_ϩ=jկ&s=tѥ.{QVz CoID\g4\7Ľt eQXc[T[F!ˁڈ%Hߣ*IPYgB`T ˧5g6n}tYYDyf睺4I4SzZpćS[kiږ#ع@e51v^/\`,<߅3ЇD)&\uN~! opIF&k,"<92=RnU\ε΃nypT9٩EjtϫɫIʛu}~&F4EF|ND|c;k ?)FJHw|u>Vzx6~3xq[|OiB5$Jdž2XԹ΄ޔ y4R&٦V?f0^vKIҏw1kpAnrq8 cշK_DȨG5O2yjYȳCέ.\ pۥ"Sd %gžd__gj L!xJEYH}ΟXӬi͈@GV+㖾2UvdH꨹EE1Nލ׼78\$/|FU ݪZ=k &!tn`T Di6EXDgi <5nT~r?8dN}%Kcސ[fq-3DСpoڋUVq!\M ę$ sg+MAe M4{t%G4P6gx / 2ץWGښ !x;9CKj}uy OٚfcE|BM8KE?Xr~w!k¿xڒFjғ/ړ{%Q84adfڣ#o( `(v ^8`[gwd/s&.tsڔDjzh9%P$yW16'4+j {d@֜=:yApF-`Ԗ/䩪M1׻؉yJ98LG92ew(8yۛ>xo( zaZuϟ0Zjqѧh W ؞FSQ(1-u}bF2Y0ܙ=m/$^ɺzKTϻٳA t'o]"=_Z=k=Xos&bΈ*^М ?QљLu7% mUŚÉClŊt=кV L$ gU M*5fcBT.5qKxi{% -p+^l ] Osu$E IgC(C#K*:)Kfes8H\wǓ"d|^jr82pREvIP3SU8J{=멿:բA ٖs$5NzT%Ǟ+y/^ NLV '%sDדQN>V$ ^B^H3/-!gHǹFv: jPje b8d H]cRp 0O'+n4VyGsX&D;M4\s_ᶯ}f N姭0~ %:%ߡC>z<xta'W %ȏ{k ڳGF?pfɀڳ;/  I=$+ i'V*몧zs`- - y:asXtqC;JMt_EܫsZ&Y'pO}SH6R,5O #Oر3P;t @{6c%NzVбպt]wu]]J$)L *VRU::5LҼ1:moQPK'=YvQ8-픉A[O W 3 i3*rΓnDjn]"X$uZpndg55M"\4I;d78yM% e5y*yك vH<EЅg5@s&MgXrPwԠ1F;@Xu;Ęllnc+L{TH CgKO}N~J4 /DVtI?;Zquܙ:T;ܖȊ1̬[ 1`r5pd@{>I#|ܔ ^aS`]#>(1i2x @&'Ty )kdቧ*tSʹOtO5mg'g*bb+z@Xhn_cw"Hxh2x[fID(ln_"T''nw/z{3'CMi eF94*Mo` p:;]:DxNp ..,e6 pFPņ\ gX#SQN9D$&B9{Cn"MZȁLt?frqP~O?{,SXi̒r=y{;R>`=5Q:S?<;Ʃ%$NAF:D/Rz s]3aOӐ.DXIzq|&6 woYpW$&'^"Mh-+{1|xydu*/|w }+:6؄g~[YǦ *= )/SD>y'#_ Kc;`Zhp#>`2ʺX6怾LwZ#;*z8xO$J培pkRXIv :tߐχ&`Џ6}Dㅦ-FKGת&<6NxuFN< CY+aF;TU38PwwfתY?NcEjC^“ֶAlX[-Ĺʠ tNv͜ t&. ,0sa[NQXR޽x>/l:6c `*+uHn+ ֙ZQ}i8-wgsNoC071.RLI^KGotoT!1)=a6*܆QmW,@^-p,1Anщm՝Ym~xO+gI#r2ꯜn"-n}Fy焩HFןߪIN4͇{SN, ySIs518֋)s=B5+K?]zNX0|BG}9 w3Ksv~> pGJWX+#wj2sOl!kMX[w3nBr:3VyYgU: bȿUib"B*OoBMޖXΚ f?W3y'+Ȏ}Gl]3R>V釜I {7f7r9 !]ݜ]',m?ɓPgK51oD?/C|7P3@P ^:R=?w]OA2*"diCJ궋r _)Vx(>3O%M}ҡmAyLn0~)A K~+^P22akO&"7/ Qޱ"an+uˆML\oCL5P8)(-g ?MXV8u`#P?jР^[%|t./nI@}< g+ :K%ywt,c-c&?%viI fR\m-"Ȫ)$>V7g% qH)ד6."~6=9Oyi躗I++UNJ(HR6R|RU/73eB1Dpw񉸩wNqn.G {kM;`Lx(E7o919.|sonK8} cH:)@HncguJZPװ#^zVNfuI.'>ڳ^42Wis/KˀG(BTwn{1^#"M3o4 X#V#_ befx _nϴj^pJ˪4K2..ڃHf;dY٧Y{u%GLDRrʚ)nVO2 [v7|o.`.NV4o0ؤhf2B|UJo |!m,T4{>P 8hgF螬5fIBHbf6]|Rᇾ9(7ś"JbrJb!PN!dR6nQṊja;8{ʀգ Z$/)~Y\zM;o_Gm :An%Oo6Zӕ!BMw'- ) gy^"D``ϰrV! J@meBŴ!TPPs?ՑwUTõg%.}")pܣ oEEHFSCu+^{*_4Z:*Q+xe6\P9zRy|@~oLm8NDO4EIZ͇a}30qG;PfnqFUx't.K+M:|ǘm7̫֟fǝ?Mw1*m'N@cHP_r8D<_(ߛJlv Cj":kO婒xRfϷ]K~`;xM*-!S0搱#?J1w"Z׌0,ve{i/Nd7^jN׆s{&:{G{V^h7z Z7\by4 öC)!8V+щwDLLRt7ARt" ["+_%y`%bSςpWpK.jGMj=۵Z$8h)#wk{gJ@7\Y.+[8fOΗ&dg2>] pR)X(t̑"AY#I݀s4ΐcHX[jeu2Y`vY#Qў`P8[3/_IZ6񇜅a^VhxL"Td(kʩR+N 8)ƤJXD<`\qǏj%fmoox+y&Ldϴ]Qck->Ltܬ<8PiEȞ2tFFlzd'D3[ D-7K~Xe2~M,@~J6On6. 2OEf(Y+p[4j1 'c#ETmYj|.dJo-0De8|2yK{A&@9AfZig=$JÍ$>E% gЉB'7*,R:EگF7z>m!|wC=did_Xp]|50͌cebDoaS!)fSzAciɰfQys4ݍ&ui/Mޙ.]~JB.3UYP|ow onϻ͢vxfLqiYgecں'ǕU,عNQDՅ"ig~)~-/H_zVL҉jdֆLv6]5w{13FS੼$(yCHsa ΂VG0Nޣ'2pxܘ-e"uVT:"wVE+~܃2N;0H .)~~s>m~C,8Qɋ!YF[X&Q{ܚvY8Ԉk#2( i.ABd]@`pBo_،3䔔-zPfVnd֋d/w ][ Ab_D!|&`%NQ! /.'{QZwQqBY|e9m7)qD;vipLh 9?ɥlxtH'YqꯣE'85uvT_N ָi) w ?Q8ѹ8Tev~z  MpRGaIьNt*G߳:Nط9jh+ȍ Uՠf@L5)EF ,D[S^a0Tۿs{{3D̺cK]l]}P5ЈNLhGK,DѴ̡,k)dա,JIq_m"Y n?Ƴ=0xR#ص˒^svYE;`XPPS2蹫mFޞz I_;h2,v~2lzi|;oXlǦluٓu7xt MY!M fE/E!Xp e=c*^k0y0ˀ*)RO/^Ubq=e*=!UG-_}?ok"WRVtq&[)H!2ZzE{zB@ic'.BDg ;RVUC A>BD3Ch`/AxOULT;_:Ε5%zC$&Le玼YSKEsHGr eGS|[GBHO:/dz;+!Y{r~uv/0$oM3 kfK9;;󊎲2g-^8^ƺcUVҙ{mx+a[M; gȍ™uj1 /U9߽7Q#=iX̤a!wi<}M2KN]x=@s˕`UJ{+w!J _uixft/Rt;?E{doPծeyHI`Br9Z\M 4!{9GՄ${xM?+ oYz{k:4`e~z]*??YhEģhYChlQiVzUgP7n?i8au>NHmOŬ$^_0L*Ձ,du~CۛWdEb'td78YKn?Sy=M~'l13tO-l @a/wPᢱNafxأ.~}J^)TQ'5ڋt@Ç,m<Ք5·3 O6?֠$+gyJA|p sVk%|T߄uޙQ33j4vdBB5{؍Тg~͔+BR"d^< ư:UD?=TDéU^f Mo8,RC: =P 3#0 "pm3'^:e9n0L˟50-x"Ir+iCM)0K-UU(B'U륂~o5'X'SHz(^(IPJ/c6\uC_ %%0W:i^|$0Fq=gYl%8*eVe]5K= hw|3d=JѠC$4L&By@:h}hPGԁ]XLG Sn2QW]~p=7!0>fCfƎ< fuOԋ1jWw_3aSxpf$L:]$+-UR,#S{% ?`m pbM=uJ]W8GiGϮ)@ka_Ssd_t.Z+10$ :)gPb;2P4Dd[0rl;#Fe*%k'S/6#٣^o$%nf[zCt~2ekB(r+/?H.-mbW&gpUhCI,Lz0'CKi$Cb]ߡ;'/9V`UvI"Q~a\;v٤3z-2OA`u͓ixbj9Wz7tf8ۤBd!sױw R`I@8w/;43Kߢ֕GZ'D ` uԕtjS4;\upoV=mihZ6;gVߣʕ~!ɇ+y?{|n}Yw.M#; iO`P^_6نKdj\ш^m>@|%n#>yi_盩$gMn&ZÉ/qNHIJӅ+h{|:0 Q4ַJ)9S3lju&e(^ 'ddy4u:&]bFu~!nb8=1w+PI$/]&nL'moR`2jKV٠J,0f϶ R esj_d>&du2ԧP8&AI? ]aZt(]YP(j#[^/$S)pC䰺'v Jtf2ULJKZPmz7CX]Vۀ*1̈zdYkYvC =JdN}m50tVj@lF;/4'{{4sf_{odx 5 oFR1H[8g82.C7BU\cUDYFAyoo>Zz?(_%W> w #hY;J8(7A^a O{Oڮ^d]0gd^"->YVAts3WxÁ%[00JSXSXi8`:REJOk+[F}HQ64}1V;r"r`D q*.J^e/&75s|B!jeݓy; &[ac!2Tn!%έ@]+ο@p] teLj 0!2](r=SuzQk|SE^e yCR_yqʻW7PRm7{:yTȭ!>5֨BAeGFHiWn}kկf3Â/R_38^> ނcZx㣕E͙>'Κd;DVpñ X#|X3669;VOn'ڕ71(n"8V;v&k/"'AIFIqi =L3:P`;a ?lT3oP:hw6VeFbG,I/}d[EH,O*$u IU4"ŵrqn&E0:|k+bOOU !;$)} <D4s԰nA2-_b%:?z -e@wN1S*_%{T6-/,7Iax]?Gai'~yhƌiryPb{Z >jg{Fw{Kǧ/Da^ctn 'p0xbhs@H4T|˶O\TOsQWKrQ4nI@*G U<|.Ik[ kvG3' A'V5p,:E`pgmO]";[͑:m5&x8ղ>i|]==6bΞ}VN4,52en|:{[ t>1*gRm>(CX-SDnZ@X8Tׯ>_zI"7Uh(ص[d]1SjYԄkOV FöDfHSlc2'<#pαJ݁ND=o>% G?k_~ц;`龤ȋfˑ_8h#Yԏ+EDtZ B^4~fkuHD ~>ʘWa@U(:K gf 7H&ݭ,+]e)'d1Icۖ c+[^gH/x9rMz$5!XbHnM( {d{NQǼx}L=l~~Ubnq:b61#2E;^z\eg=#3/jE բ^vo/˹$Mns3}?JS1Ecf1k Hwbwďi}bmu9E tuLUeɚ8.=)+7ǾFGFEqDmicb5!W5B Z|}RY5;Q+P)-b=FEĥ#,+E)EGk`T{d@ Hrt@IJț0YUO:?>ay@]# >Sb8Js?]F Uy^TD$ 2yoy '%-J@&[42YY&!p) ܺsԛ?"&c tHy2p⬔$7È+}V"³&q6Pi蓘Hj(6u"L '7V{uؕ&lᜓOq,}#M&!w7LB`ȷ&frK :[8[uiA}ӿ~VZǪQ!߭SΤ͞%qs'=:ם26!S5FfA4A#h6³G{Q;lf̘݊&T'^Ou:V7fJ؄2^vU7 NlǏ<޹|y?Čh!<ZiMᐋĭJ횢5OĹަ15`gjه﮻?8emck?T·SI!S%-=)q+Ųҧ墵)' u=4>^V٬.y5Ň4.Gϩ`#VVIKC.YٳRhRcU;DBf s v`L0 r@{ࣟz9?kX~u~Bjb-}?)zU/g> bqW=od]qӶ.S^WCt  |ҝծ&q6}:7ww^"4? ޓ{F4/Iy$s }SU98Nmdպ7;7XMzN0_h?EVA-}ceQOG)Nzi l!<#03z'XLu7P*p mzɐs}0Q/]D;MԐ6 y4Hg-7xV5U>Og;?@U)g_UP<}`9#h"u7Qkc9; &=XHB/w;u 4Y')yK0x[|nF;b19_E_~T#qSDe2vDHP_@[t`zWD'VNN'Pԛv0T'Ɗ*YߢM|ieF5ùq"$wo\]buK9N0“[\6>ƜKM<$|ߥɐ'Q@6񋲇^,Pi3{2 mG+K5$v</bJTqE^^aqXAj"2dMvi8-\"7==ʽ%`'SI I<@+ ضʺNi}޴_.(uP0D&?\/0"u(`%r潤UեQG@>K}Y뼻;1UFwVq`PΪy"56=Zk{=7bxcG6Ύ)ۻS)aۥ *\*#tH94k>reVXYuBXrߍY-wn3TcJͬ,=аx}ذN2=y{EETu0=\qXظ| ˵#j;M{$ sWhwP N*}'W 8jzt &j*1|fmIYoQa2*:[؍nt83[ 0]j*6'欎NL:|he96iYL-B '~FL:cRϋ1k5AD]O5ޢDZuZ{dVx5FUt֣Ez 36硼O#dS-zxÅs ?r ڎX{ ~Fz&s̋2$"2#YSX3PEϟ<˰G4u4~1Sm' ]+F\P0m`rҶk_u?͢5u,{3E)˿e [JV.μW%  !2خ !7yp5aޱ)L 0]&Xq.\>1+@-~vvQ6?9{r|:C{&+3Zzr@~9e'kL:?@ij4(Ӭ5Hk%A:J8Ɲ,#Jb:2}:~x1X(O=R? Vu!QmcGE$sH;{ۖˇ soy{6WOUJ–\NCɨI pZnq@aIC@fZ1{!-|n ƭN\Z. u|J8X~iZ.$buhW fm)ヺcx D * 8ehIze ²v* 3NU$쓠6Leˆs-VݛH?u)35n ,~]#j Kͦ%':Ŋ(YxX}qFP~~~ ٳ=/BS/d#J ,3sX!.諲CC ]OYI_]:h0wfEiƒ.i FJwbI( !qqI A25i<=g˰JtUHg=YCJQrPO 77浛N}b1k!=C4xZզH.NL:|qЌBU~0|u /^E:JByDC] %8E AY+yv{7Sz SFų+TpnS€Kij"N랟vKZ(P@(U!}'ggН%_zVXulvѺfsXt*o-i2K ! YIj<6~rJdM|3y5][ݩZFv:QD44ȬYISsu8(Ƞ#+?mQ`Vro|J3vxMFPʵ":C$w%Lg.0ԞN49G1L& U=@>wXyܱMpO>@'h"Te.5:UMa^OO֩kE^)6 ';5Eqlk #f*:f;'W/%j~3`zTn o}ݽK/YNtvKy`M!PFXMw`ThNrBkh*OX('1|XAyF4]@7T#VI#~Zݳ"˗Btt?T#;ff:^_/Ӆ/%akC$Qf'VK15(Y@P6 3^1!Sy8`j?6E>1seRKj"(Y'snھ#V LT;_*o1X~Sup%`vI@ZCJ@—y"DI."ΝuS2pt!Iy?n.?mrTW;?2lժQgwfbR*3{dbS_c&[p7b$ vVT]X=kzMF J.%MzJqYDIg$Kn~6æэx YGa8kzBS=xXhg,G%Yd׉dQWGz9z|Պ3uySFo0k*@\&N 4px SIOAb+WA /Dw3vD 4݊+LK]$/v+"|G;FbYR@8 R(G\4 1N݀hk픈9&,NcdLVpLk(ThbI̕Tz@4sIeLO[$Ua=seʜk|f쳤pcµ}8XupaS|x09'q;^SE[Py+ 2YBXp.`)ߒ gFE-IFתU5^zd] ջ {Nc^ř1(J_.;󀝑^4Vc ±h5^Y'Sw5'xX}B\%'Ki c'f^}bC|e^gp%#eCъLUEŻ"|z(;c+ˊ3|uF7:,9MτBnM:fʗY[ zq"vG?JX5tTzm`gK;_g!meՎkr۽FOx5G$"^,Gv\4b"22+/?xY9:N<ޅN\^y>SVvuh;Txo2x9 S|<{,lv"!輆 h5%sCm(v%ow4AN4z[r33 E#}CWB47!U']M;%X= ku:J2c^TޣeY3`BG.ԿK`3}I J_:W7})?)q#A}|0f-;D{"84EPffy@oz i7EKtrH9%VHMhPFpiki&glh ufnwpicb4#&u #7<"C!4V;iq]Uh\Mi~w2A ݂_(8XusGkێfaA;EPG?@5ͭbD \Z70Ȣ*/-DmJ}1D>!$OCnw782PZo0Zٳy 8GG Ԩ0ǺLI4/)d K蓌D #jP$i:H]PVZ $|FS 8#vf'rN|>4P ki&‡udt.ia5Zg1S$U?g9]ȓ$=<Q>0M"U 0dK0Ku 6ϙޤ69visS6%$GUgVϓ(s.hzLأ7:g-ʫvjSWd&p&P=V^ [n|$ yP28י(J y|vՑ]gotG8pP4=]<3L^ is~dh0LoZH[mSSȉ.25ybN͟ż 9a|n;ܼw\ҏsOXѐ.y*|\s3%pG %gGkj[%.iY"ܣi#ưU~*O ~ZYqOt:}B<\@HJ|к֍[kB)GKKڰm|p&vG膬fpgmD VAYm',|eKz"5/{uY JgZ$V΅K#]DmҖqt ×DǘÎVS*2XK/1-Ց#N(冬HpAz%OJFAR#^X0#Hf0_8TBy+hvt-[&z/9IoRVkĻhSxz$ПN,y]L]iz`tRbB%=̰Mv1!_Y{Y5X\gXyzzO|86x}2k3w/J}"EG;C =wG<rAb* K喙41ZxAio^ 狻ԥ5z+ #)5 {_Lgפ0$J'ڌ5f *n|_bv^J}Yk8jmD[{+^ɖ`vF8Pa-?1 }/p?:0ᝋ[zC w_5 oib)yP_m_bbԂ ܳ6|>\Y8R[_H;DP/Q+wb}瞺W"ct.Ha9w2IJ= 6jx[E5fkgbu~T㝲NJs[$ohQY6 _Kg#VN\.ͽθw9Ome#l͇#6!]C-;Ҏg_XbZ:4u-tK^ ՠ$ سIiLb~ <H_f5r8)(saBlapg}2A:g3‡SAeT~p[V.[.|[TGroW,mVm{=բ_ :pt&L}3ŚԞ+0;DX82xQ cUʄlX{;@P}5MVZ~RdC6O/Lzof9ϧ3XЯ;)DZtf!_k~JWYo=|kTBHX8s1I76nעV>"<~aPG;Cs#ۅvq3'qH[aqXEGXAG`!ܧr$p0ގ>ʼnhFIl~!QiIry܄vex#|:MGN+\fWBZLyu{VhT\H)].&p M;\dtBzu0hkzĐ5"pIFlnFNTzG#VVl泔4@cZSjNO:,oqsH'rHWBtL%)wp-+ }MDD_3K,0g0fǻY[tPXw4NdHoLWXWH {Y9^m+, 8:ˑ% 3~靪 6/!]~Ɏf_>Ѯ#".9f@'^@hk:%YvjLv:UΔ/|J3JnSgLB#=ƼPV*"fv7 ci bi qfVAt؀ a53 raЪN~KTX#Cv s"~xcxoS'ҵtZPK/X[1֚{ыW4`-Ud}R'AG?;\A$>.anhɐ^$`ڎhSYfOdnquj_$\LR"d3;yQlǗT(gEH\5/ \p 1{J6TFtKNx=M"uүn{FmDV ;J7rrbh9Ӑ{z~IR g+ U=<%@tIƄir Y\6νKOd 6}<0]: wa6dTH.u4g:pJNfzGcr|=UaSYܪ+b52>{$1J=9k7x/%WLjߡ}gH̼dPS:)?{/Pdmf.H D~}>֗.$^ܗJ~}+{9{9z)Zz:j*8hϬXg8Btʣʡ+ʮ1gP?_mߎ5mpI^X=~0)v m&*n )lQNj5LyK9xŖ!Dƣct*ڧ> +x,5dGx7iDDb+wmc5҉XU?GN|.-ͪ|r2y-ћ2Yn{|uh_&9,Q=sv?ǁ jX)/=P:1Єkוd0nBrg4Qb"ԏZFv +0ouJ QNܭe^U#9=:犵;o:)YEK/<)l01Pβ/櫁Fw 5xERyCqw-G[-PY2_ld>8x};'S|";GsÂ(r& 7ޗ{M[$5mٙw,ɆveRYH`4]jσ0x  E/k:P+hzZiEB =|m$ܜhGH+d1P+]i{D\%s $:y#mj:Xj J`DM"u!H `ITԐE&c[*>7]ۼ}P6Fn*tfqY]B;q(#ݎ^^c:kNyr; A-y'ηQL a =RŵiVEoNA.u`Sb|GLٞiL;[9:M+5u~L5U Ȯ4^+i⬏Er ]> 4^Ss!S[_[Q~Db ~.BS+5i*1=mxAÑO'[r GڤyuJ~8jn\ƕtt]:gGk+ 9xWh:1?tL&nJfX=A|ߩ"v '-6JWqTJ UM\K:t#7Ɍގr=v&n U4: 8@o q>Jn[)'Rڧ1Bwۏ| ~!-Ό٦Է# `$2dnS``S#~ȕ8pգr .npM4Jh%>2ק'GL0%.4DwblUI#s@Ǽ7V&f%;PR4%E3dBlhvQ͞UHvԃ}0g:ʫ}ϱԀtH{œkE9Wo 5pTe6m 鐩#4h*]zlM{kv֛\UtC_P{*4z(Z2,տs<[7hж lOgM9?i"J_|5[ylYS$Γ(3oZMBv™r;M&u2x?d3If!T&!{BFeO /KUMMKBVykZrU4cE$ݖ`py#aLL?0qk:3OcYka8I ~^6W3~1vA~O~ FP44 d8Ctjh0U4X5$f7zDx~bV7%gE2qkOy&P|@$i;SW6y4Mdu\z_yH:-vjh:?Xl= )HɆwh 6YkN~1ޒCʶtM>1MalˤX.Ԝt6U96 T/ ѥ ?!GMxl)pnN+-a{ 5%1|r xtn띥\]ݿdq ^uqmWi>-N L*%±EW k(*cvPIG„7]ҋ5~H2,wuJO& Vq/&Y ,R``Kw2<`l8"D,/6n˲nS(! }x|Ƌ;BS/(@PᜧpV}hM o2bUsClƋm0}e . y-]h\p>QeT{oDAd3|]S\-Lg+7 [Qެ^{:_ ,P`R9Q14T5 wnoj46qb_؞V'[n=|" J)󻇽o b[3I5p+e\xyaRhbzİZjL;QZM;}RP=3QbȎktUİ7wZ}$Kw ŵ>fEnbu4(TssN6gq2ᗗ=rEȍ7N܅hVMhϺNDjH@zjÜ)mju~A| 8Y k2CRvϯE{XV[Phlu:pKr'P3'mQYf1;TG "q׀I:AjjROs*sOQ/gjBe٢g&Xf=O#gUJ%]l8[4mvX-X_6e-G 82U:i7Β^M\ԞTGpDmu]^6c) w rR 9uj4le@q]"d ݡ[+u t_kޝ]o]Kʠwt|SZ\dkbd#J{xn,aW勰{`p&dibwe}4iJ{0XIc86ud;JXַS{!@w͍6V!-ERߢ?֕{!cZdIޓ\){ϰ.wtA]tȜ8@XUz&B#iszX}LRlo 34s)ca4m$V~?-o!%rC{AѶhh=93SRS*i,iT 7{XsOMS$Ʉ=eUgڐwjz_%΄3]la%03ב/( >HVI(NcɅoq>~1mWu-1Zscʦ+#`aXd I4 Ȟ(| ȟL_@̼gJ#_+ 1 qFvt@&a+[62o J̺ c|h HgbwMh-{)Ӂ8%#$ h_d7\ lj~S0>36 +ލ?)IogЛϽUUuK3sDM;:mQZxD- lVS |{˅=b_]e%S}eZi)b}@[kN`2x7 sq"9p٩izߣs|GG" ~ň3KEr8֖Zm7'Vml 7eUED 0ew[:3BJ+(yTA" jC4'S:&0O&0b%E'Ug.V2"y9h:FӑSf41$4^k̰!- &43R}"s*`UŖ8_ScyeVK,qg2 BY0[^9FtX\YpTSB[אA4N;:*MdtyӼ7gdoULW7g,t*u w,UP/ ,O7;ᶬ$yOK`f}^uvޙA8NuRћ{tf+hζl\oeXA\hE̓]zyܓMv$GZ}"(q:ѩf@YbŸ`o@{Fs8㐼[KT^!v``NPiVQ͔;Q㫒;$" C`Ց{RR oW@hʜzUIzʠK[d( q'E+꠆KZmr&f+RP[L[=Nx G?CmQN{GrZ׾>ĭ <kߪ^~\j8ܱ#(Mu^Y~:yED]&-EMf-D/Ny@A|UʱP 0PZ4mT'.eV@[]9?F*:b"$z%) yۻUř;w^e3sr>L:h:9z+b#A~z[4ە@?fX=اe=T~{4O1~Tð:KIA9r5WP;%~^ i]5RTۃhGN,oL(76)qOR CSz GJ%m> +{$gX];pE/is~Ȳ Z[.x4`˄3u l6@O g@ұOuObT頦f"52ja]((i7%(Td H9>qQwx\Ӱ NU M Nϗf09N4!<Ļ}Gϊę1>ixZ{r؀MxbI2Xp%!3x7}Y菼BoTs~e8IB2y{P!+a{7~&U[5o ^TimV 2bR]VnHx!r:2>$x>/Yz?oټ^/A,j,ҧ8ۮ -7_{&QDO_0?󅊣¼0o-iY!Wr=y_.+`q*P7V|KU|d62[ uHeإ.kq'rzn@ebk& GO<ͩIA6̜d$~2GmQ _(x?I:֏UBMty!U+\#+R4 xV2rr>].ή9z ֛N-+,ߥQup<eE$xLzӲVp 7h 5_W˳~7-G xQ[yeq.vTv{;Ra*"ﰼYY!m$+5M׀l'[:5!>UO+s!\gі c8W2%86lߺ@LBy,E7:DOC^X{[zMVGٰ4H݃Fy q$/~*#Hܢ+e+ž'g$oVyjdvꥒmNf"j8"{m[Z06`wTIy'fDc##jR4?J93&T 1VdTdȞd9b͖xwOP,*ػ ")S,LpUl#-1"Yʥ9+H"ҩ7yã 9ta:f詟n?whӊˤE4唴"XyXE)l 4C̤Wj-u٢0F_hlH9or>@QC(~> r!USm, a4Ib 7Tt0oE3zԥf 4; .tz*vaB80FuPkPf:@r =;8IF& _"t2nD9mE F̜;OC}:=`ϭnM N~ݹV =׋~u榯Ί{EyO==-f Jn50 !㞒,:b:~=~sJ\i "C(ޓbhC =hSZDW]~7IP CʺŘT^5 Xj&w ƥ (٥6U#`xWPP~yH>\nhW7_kQ6X{x : :52na3@ŹIE̾jя .C%c`%xEp~E;xtWJ9!?tH,̻ C& h%8dQC6tk*In̹Nn{ny:b`[xGxA'&C%X#R0]7PfػkQX)5zD|MVRoHr37Eb GJ"v-1~I9H|pǰS3<|Cs%aQ^jP&Gו5Ҳ{sSsTVDb O2rř3jE敀 \ (scS *L7pa*-՜RYq@FkS9||wʩŒ +{dutbNHo7;.EEyD|D Ϝ$Cq^a6MRA(q-7et5zF+:ɸLFNt!7_s^qlIݿY?|BVBDd*MyZ=Ulkyǧ};>1-Tu[]?>A:OuB}7dǚ5HR(DG0 O[4a w(`QIAN.z/k;Zt?$Mus4n/=hb ce}4.X>;7e-:G?(y|{4 k8)ז> QfeEum! tz@I'67ٔs&srʧuQx>l. Dd4[2]F"u: @Zx PXʹȈ*u ]íR|84wĆoYindnv;Uq4wHR4<S D5Jʔ\g?j0P>#Vd 7of㺤rIT>Ža@f'5ioXqPmr'Atj螕 U$2F#VQX#EG-].;SfK扞j\+NvϰDC&~GqVi'd%͐:&csy9h$I;'vXL 5QT8@\=;sJ6|2|z2cSҹw֐J㦡koh0 $uy˭_? ϟVD9GR ^6(šL8{w~+3j9 '3e vIO[6T Rl8P~xH7鴁>! IZۜnai\xz%nlsxc< 5V;Eq `g1̉ӤeW6WJz>OpOjL'H'0ЖSD1|VE82vtzK (@PxD=ȯ-3W5w!4N#ad7aM؀tX-b,c~q[)&ۿNPئ_Tc l X_8֒ldf&N^Vvyhv7h] )׫zh6<:~䈳:.Q YYwψЄDU'hΥ9#]9;@:Xh K%o 'W>!Q1, ^|be'<(D~)n!RJrO`mM.`Xo]CI\ ɳaMBiI|#]킅pPCL> VLC^vP7Lhȝ9Pޓ[ocQd|3*xԉtf짝3SW:H rSyg=K+1+>H7p{\z71[S~ˊ%hZ{X9,cw`2}ǚk݀G++MTXVV kH۷Rrl[NTxjsMThI@\y-{Ux\Լm'֪X, ^(.!!ERTz=}UєFJ.;icY밣Y}l|6t,DtLeN]XqKVO yБ7=Uk#?/sƆ%g^gyg](J !ϧY`Ys2MfBwD=:[)+ѥ%0{>AzѥWSs!ƣ$olqGHN54?oQ2VXz:Y7`ʼnpth  B'|LGTN\0}t!! cO$A1FFU#|~2LI-NIv/ '1P]l m¼:D*SY{b1;j 2$4/{(/=R5x4w:lA1\T&MWQ@]eƁJp5M#!Q_6F&AZ 3B)GX*#w]TPsC5lTP@c52:Ŀ-q*|9hgS?D<9a$1Wi!c.Z|W˷XI):JgNB$tSډg5IwP'Koˢ\Ρ{&8Of ٔ(uJ $ezD2ܤYK7,q܄dіֻI"$u[ >H#g +E2nI~;$:}z|ȖK<8R $e n֪æN?&ޭtX91L*INϪt=p:Pt?? rWQm8e?)w߸iR}^,"DzCm?iUԢ=C}R0楤]2}~܋#.\"_ƐCa`tk3N3_w?h,/gمDI?=qi+tF^8灬 Xc;APJ~FXi6Fu||*؏^Z{D!0݀B:|Sjr~}OyF w@ogf]0~P7 {%fkYD Q>5S9!w*4bzix~(UK^24-g8+B^Co;UnSJ6WވXJ|2K9V_N Kstw! !e: B,+{q\ ^5Q2uӣY2misÑT{ѫ/`\w-z0D&WF&_'HG&?p|İ&!x~\[tVEps=ӑPgt'{ߴYYzQJU꺸DPhjaVc#cmnĴ!3~Xi>~wĐkSm;w^-F+og7] }fq]GﻃFgkg%Ie?}QaM@F]X:a߀ҳ]N0Gh.Ĺ8IU)z6T8/LRMRa |!qmSKo۽);J= ᮇ{u}]n~/usP=*Q%",wq4="rүj#u]\+/qcj2+(S OSCɜi'VYEBFv[ۼK8 6 wԄ{y" 6O5] :+~E~#oBI3Gf&W ѧ ܎f4~#--VŪCW2F+pPzc{=6g`e.=*ΔC Xz>anб+Ys@J82*'͜%,+[O9ܯe)K7>|𤐪)@DSɠ9{GQZlJ Vc9Gd)Z¯TCHA}lޙuOI_x?xWf_i_N,8lKz>-&f}&o"ܖ!=ќ} iUʬȅ_ g&еF\+wtJW>-u |L˲ KOB7F 4Y8BSesO~V. wz2f݃ h]OՃq~\+p"`v ba=h,^@.q2<{7&9|*hضY.üBLtMJ:UQU {\rc9.<Ӗi0K֛@IdL2|54)^c3;R:S0.Ϳ98kQn#L\"ֈ)hS=Jaobws^ɁY(tSh Xk\5QM"@z峳JNM8~{='4gߊjrOwz;;Sܽx` u!;eBvR{ J:w]bF2ce CX@Z: wƿZ2Q" 1]_=lXc5p'3j4]+F &5ꋮѺ6ȳp^nEntVñS/e?JM {]仟$S !!|w9|̛gŻdȐWf}tx~"WzϪ"ôn((7:mёbcsҐz~/bhEj`x$OnӤqMFX7JC:c-m"i>F`! 5) 8ALjuzE{38)F{N\i)k( sHf;,"͜~PF8nn{Aü1Ȯ(5 S¬(( S7&QGm7JrȗN) %yǞ0e{xv Tx;Lc)XשRwD|Vd~Z* @ c\הo^ gkrlS0 -%EL X?Ot>$ouMoMcٱdvcR<le1;:I~[]~BlIxrš ɊΦXgI a6 %_'0;SL%VսH<iwXLD.wJ2C2% ӱU*.GrD9gŊkU"gP{'29\mTcJ❠`0dUڑ!ؑ$Mw=L8/|[wsw5ӋFjKڧզ/VHG$і2 IVЋ3n"1fڅs MܧH7UGyJf8<*|"υ,R(-<58#h6dgT%V2V݃E{jM%MJ)ވ>VHk"FE3P%f v4H9+EEP :nqC+z,hr)[sn.GZ̑3bx}0z#)dEY>l VZșm!)ma4]f4L0><낢k(\HOȑM#Ԇ*NXGaZsWf|0y|ZgCSm연ڝWZzOE|ظSۛf(7݄\‰Iq^(o2&=ݔ3dzq zH=+x Lʅԓh=/:hq &gv>pO@FQG q"nVgo4/4ld3RHMPdsƥ(,XRSV$=voY'tޛ`{<$0΋d"2j@_Pm>z]p%ґO}HDu.tJgzz0 y~q<{rb㐘+͇Ζi$3RI6+ SzVk:.ߤqȏ?y)P?OSn,'?=C3OtcF(ϰR:cInszjrfV2)YVFHCAvnU8W+*$|a6a^/ID@[s[WtNr&oQ<lZQ҇n|vhtǷfdg8] `+cXYon<֞y }Ο ǰK8ƂҳVlө_OOVvuNW`rğLEqGJlu/%(p5̃t 4۞IIp45h2ϧr~bֹ>6.cmC(o#e?H<K~,0 s _?s|h8[|vיeeח&<@2SϏ̽vZN͔r:?@Qh[:EUjE_ TRy;/+K5"`b&WAWu힊!iH{_bKC X1.9/KbϪT  '' 9Kdd $tw#bc 2#~uMRM.q35g_DI`wQV>N:!~9yGb6P Sg|v//@" ߡWH<ɕXi^ksm윲(l>D{6h$k']-}Oq97cV7JݣF!4{} /̫2- VsyHfeH.bodk;4wx ++u;XC1H|˜)y[{0g:S[e/ |SwIXϬx썶1=Xgp9 ^l5C\X/z;bSo<0:JOq1[ XaKхVFoz͝Xc%GAJ<¬tP湽SܽB^6 ~!Зz/IKKuO_h=qPAzffB;O?>09 #e2ay-:r?ln|VMF1.~]`wLcZ3bS ]>BӆΊ)P9*~<$L*P4")@i *Ý3leEM~~ZܴQFxh}$sn I0L%O=88?hp ڑxe6S狀"{I.&(yLl(+jaaб J _&k?G+k9Pi!NEkSҜl|zPotC y>mHw#Ӿ>ɘ[e( -_x̣U4޾1ȧ>e:|2-Ě8仒+_ɦK_t܋gPu3*u~" M''PE_PfN0^wr{;"o |m^0\RX9Ot4 32j2RA9vՋsƙwpε-0m M-h󼰱pjR^sGuTqS~jvl}!{{me".Ǽ.`=zaqܞ/M4rN77Q/Ʋn;L^?qi?9ɲ:{JZgطIuYK:EY?Nb:%XuUEO?KTF65Ev-yƄn؞zsY; )OhQNM68J`Zh[gbVb0gfNKD!D 31Cxΰ.yORe'o5OD:o 28];<^>pGs9Ti$AVy7&@v?;oƇw{AU0YxqX,|vӹ$]Hsf-Ss4gBDi!AX3 "v![" b`8ʑuEDp, _>NuThd[kX{#B67BXd6ߍSRb2 *FIid;P]2J,xNFB P(ŧ1hgp_9::SQ;rmcM}H]L»^q㧲hȕuR%sG!y@ )㌖yhì#!_IB|!yxCҢt!e"RAfZwi)iO1O;yWdEj{)H:l@:(wuټ aC".~mO nJLrYqM9DXzq&2qR,r'jH9X+ LR-ެQ!t?>% ܦ%==5L&:3y/f"-g z{Ec؁XsR8I N yl_/f9D_9A֩^gAi'KYw_첀{.-WVkBH8`rV3۪𭕣G3oǡqWMm,I8uT 㷮>I':gXyr6UyhC8x2kLԗP_w,Cg׸[ޅ oiht@Sl!T9wFnG-I~ '?9={[lONa^+g7i6 o rp0f;c/Klfh|#si)VcPeD&_d@ J^ʍحq:}zΐ:D=wM2І`΃ 6=K5unܼPnX {c4++g `]ǁuCUhнXEs<Y-DxýlsJ@~:aMdC.ME'RF?RhDI"~^RSVVH@dntɧ7ōyqvq)k0: r>Ăi8횆ȇt+#{Tw펤%J'+">ͼN?GkIy10ՑФ m P,i>#a*x"zPzT헍B%r SێgH@yM= )k$!)bSyd79%@mMn{OS:,qZwlӰ-BhO6[V6<M<݁]GTm=DX%p6$t2(߆ g V>9)famj:D/n+ȟߡg&4aK#h[m8i V~q '=>y2=Lq^c7%uÖG9#)1ϣhsùJ"gHLf65s;;&wn |(4WgMI L̝G"#kᓌXT{ߣ+?μ3"ܝ$SysNIYyF-F 6Tb0k qMhv̝?]&Yz Hot!l1)eM;tD9XX3$JXlfJ]\>:_X[N_$?}X?va=$%h4:ae$4p9󫦕2@C?1~|onn{U*bMw|ZH.@D٭Eɰ5CqXwvZ2&?VVtRGhZ=z%2 _2нTxO8b _BLΧȥQcڵ'W^JO7b8EidɘE)=SV_RpvüٝKsʣӝ-z:CEQŢLP~yVSItuJ, xG?q:+~ KU^ sڷZZKW5&BgX6[e>_bNOo1&9Qkݕ!H0q>R{p<RYz "?g57(rAy>e@_hw;̏0^uKfXy+ /)+mQ ^ -[lrƔ/U 󔇉Fh& ͙^|oNK\!¡ *܃9~(7 fhMo )S w;t慽benpclZ9ry:'ܤs74gr^ZG6=qvv̏CM{u=Ƌ5KvX d>yeE7([sؚQ;­0:mO?d8RqGE!LY@lԚʞaO,+sFٹׅw~o7i vtnq,htׇR!v7hSy~o /N@rOpS:`3L?Rs QQ8șH?Ϊ# mapfe )j"_r<@$Zǿ>"K/|)'+:^#L<4&iZm'ju==̳Vδ~Yh"}9 B7QL$Z 190S=aqYAy EO.eZd~df6bN0UJko \ߗu=ϯ2aKv"e}]D{r̦}pqPnw/y,鎘c`̔pݰ>*=$ħtJ23`Jr4hqae,KG +u>;D$@3= vw[<"ЉjϦcxpxL£a%a->dP0Zqޞ.vdXMQ"H$ٮ^&], VP*UcHBH8Ha (A:! aX]ay æ#mܢ)$?8] O<$[e1hp^S"k!:i'`feJ%瓞$u"'ye]x',O!Eޯ؇58uHh2=ԼR5pZV09 ZT*{^ٲs#cy񑧱I w|9Ő.g:S"+;Qn_P}xL'po6 )]CToA{ O&Dg&19h m"9)浰(BͲ"t1N90ҢYL.Gt1?9A ! gTi UB=ܛbvH-kyOęWGHK 7]Hs.k 7N ъU]WH+({q 9f%Vܔᣁ5iY' 螋I _q:MY3XaEz-_9 Mw2$+Z33Xg`]K^։a:ll`2XVg#o^5j2"kB#ɸnzjhUCٕ,-le:a*4' %\rBRN(+]"gg/mK!'<9-^=cW%o`M=Q {Wӵ:vέ:zZdJ&iҰ(tm`$ZmC[#>yp:H։f(&Ea'r8kZ\hw&9eXo$4ZK@bOYsWб*E#5+Ljg7é2sKC2/5fO^pӝ'y9]SsKٔ?Hbbyh7򐆞[;V(-_[.G R-se æaZ9y9kMхz'=lEd2=lل*q;-\Cy_;!ɬqa% ~<:sfqpxk*TH 7ӂ5OS8 i`#xIIUݶ]S6IMWrP-ZPZEl䤄3dhRTMD9δ3R?<ɢUΡ8;W'b EmNz\x7s+_HmBPяxnf!zc0]ągn~p+<7VgZiNg:jAXtQAĺNX=Ip̂$xCgZd"[_ eDlCU Z𪏧F$R8[zpއ(*pc88d9O XaQC:awA /R*у[ە_ff wfC3*?T75BB$Tja֖r9'wĦrf6_@AeL hIy1pp>NTEO24^$& ؠ'qքɻ$uqU/gbB %2v %&]_7k[({uER(v/sd5B{RfdŪV%OYY\O-:%cSr56x?&0h#ٰ.2Cc#Fyi{zLۯrQ=2y溗|n}!s9ur>F.= G\qOiەYeCUNsՓ&[O-Ij`$n~q*2Ns42;}!6$SMYw!y*zH2iW57f,y/@ a{ʄo~Ŕ6f2eբ5xڂleX#OSs(,'-m2ىٙj2n.I-pW5nX[xB&“KAdWs:wL aWnK)ƋZ{to8a>r)/CmO=s?c;;NkfVY0׿tLc 2xb5]+GԘ޼݅wtLOG.$$;/TC^CER@؂!w9J1{FO|/~5{A|6[?p/>X]Luȟ1c)z6NI/Ibm'enKUsa6}mPY46zaߑguQϻ޴۬ }x:wx/n~)R`eIZ2YtYbjBY/1/9-;L}n{1AJy/p\ck6Um"Kyǯ>)NjsUot2B uC@ qsZ9Td"SA5 %YeVJYg劜 =Ad`y2'):[V.P+F2͞.`2k')m 2kgU c'&z\͙|:oǾc>\s#tVZk֤X:(Moo>C{Xc!Px2`]{Xky}ttݺ W֨ jG>hC…lOOB滜8'\0-&C'l//v7(.vVqXNǃ*gd D{tEїry7?9\SH5'N#k#uBƬB)Sa%[?`}w|Vj1hF<|^+^Rr>6%6w[ ~0g(~ht"6?r^?5 ƪX<"I-3kd-7l8lcD4+$`3WcͲp׋)%'^.Os:iouufVt[QU]Z[T=g3$pklK׫YÆ {͹l,u~;47\͠.'Q)WdPB mYy"IWY47Rޡ}xw_~yW͎&ְc㠧b/6B*4Y'X3Q<̒yPLkpa5"(k/u[[.ʹNoS}nf-kX HN3u obyCzÁRUOɮ-zʬjx.Nju,vB4$n Yv 〝]&/%!iԐ"C^g KnhMdoeP:=T?P}y֎LeqQصo-\3|SN(.ڤ3YɊy>c~$2דPm'7rϩ=h8p+d6t03' %('#r8,ŧW޻#L90^\ib~BQr "vokLunCNT$b(\$džJCP#; /ꎘ1[ :ʊ)XH}vUL10EBzA.Gn5c$y:ws"kإY'W+܃wwZs&,lsX'ՉRH 5Ptw4JpkvIMՐN`]?ew)uFv7ƳJw%36D,=ym 1[.B5 S=U!beFB"+R= jf@dI?@'=bY!*+/.֦H9(90Q_WsRIV仃'fv-* t9 yûi iW5WVPmuִˤXI,Hh+z"=`Mp7iIwR{ t@ǺݓRkh"\Π91z#6w.B:$w:$EsΝұ ;UpyNX"ۆ`i21OgT?5 fV&e,2%-t6YH,lJV. hPٜDQ-%w'^"rË*&n6pC.^ǙYUQÌ!CŬDWz|ba'k xR?*rxɏu0Ew7!'b8iv8zZr3*2bd2 kzZ">)嬇"yƁ 'jPxWú]:-*R|DQZm ݱ#yC#X'P.6מ5g'M9V5qSԋqZ7,%>n@uNJI%H<)lXOO ?|ƨ{J2mT#*~Qtd4BP<b4\nO]8Ǯ+Mo>DY _"ya@vH7 hg.Ȑ)17(딈Νr5)w7 14n' hb+X;霥Tv2QgY]#[ JkQZ ,Ck;U҂^z͟X {% #2WV]Dxu xF h$s+"s$_ jp`̹{,cd\ <5h5 j`-{J}B{ tI73D)I!߆G9(Y)9XE{)HOY3uYs o>)"ZG&JFҭqEetBm7 16dZl9;CLvVNgA 6;~L[S=b%_ݥqd'&/bGnrw*g+.VQMՈc:~=lv6=wuV9e Zq&mqv&hb'Ŧ!zcBN}a\" Ie{xi;xѰR]y/wFQ\_mPVNN)ۋ#jG@oH,-ɄbVRjPY V}IL:o?P$c,ojL{pF"Y*{XS{<#(T& nho҅;[ZY?H2{Mį:Q_os&# _>u6v_ sG,,Ȗ@iz0oǬ"r/h+7 ka!Koңka1m-jBYd)ٵ1yi K}do7چ5#nά Αܳ(rh$x}çw{$5gupDbmDֹ 62 9~N;4z7g!7ZC&z$Yݴt|$u~C 2%{1.׽S [j{1SvAB茝ll) [)NӜmR699|g/(uOߝpVd~}bӌ fʚDVy:w#y16\[GG[_HWא/9xɳ-( cF~\MC U6_w`[jH(v\*)[cVkh!.K-DՐ*)j!v!kli&`|(eOK˧(!nWj6t8:PYΈƒTKG}{pyoiPHOgjPȸ N@JE5Zel9.N0y"_ G 2O%ז'D+7skd^\t5ˊ)P Q]SjH ?)wA8yVWu1cjEF 5iBpTXvlX^MCV З}8hy29hxv˜鞤+ LY{' 2OS]թ(:n,^0I^ʹxF-Y8e8dK{ľ Z8NDFaY[1܀QL'g i>:]Hl^`2#4&Ϋùzܐk!TH.v&$gA) [}NFDa3M@_8<ϔZj[}5WQRsϙ/EsK3JL~fę)m204>[‡o`󪫈x գbgfрO>y)+iΦ1閗 vZTN+ͭ^qvZ.$tPy+Ԍ%dh%Zy?s߈c,gpXnUL/:rSY (HSMBkBy]8g:QUskޯSg4`/Gz^SD4g^kCo_v [U-PmuFDw2aPwmIv7l,K]@ql&s; eew'/-$'!+Z\BY i1mm4AQdK͟Q+kaYR`Ī4 (qҙDlZZ g)"<锻ܧG%HqN~Li=bXI'rk$$2S|D=ĞU͡%hJI|p>LNP5-A6T/584!;;47$VQ +&I{W9׉3kg[)dK0Tybm YĖfu߼ji"OTuݟL%*iHP_Ba+!U Zɚ,u[:A” }jNa5݆źM[["5 Iw:5Dllq8UgLMۖ 5\ojF|ؐRh*ꭴ&zohi/t vb(oftWʱSflc e0ʝs\"KKK.;lvŞHVvY|phzk׃5(q}JczP>Ê22?+.$K<&7bzݧ*7%@t+Hu[F!{#_\54ZdJDjfDL`rpKd$i8Π~^?BpC3UnGJ>9J M9+,J9'8O_^sL xт&IGݨ'#V7AgW)jаn $X݀\N$gg.+􄂺0zN 'iݳ)7μBաΕ@S>C󈲖C62X (˫Uq}@FXlfRDh.f憵RFS+cRtH3#Eo>A9ϧs!2>'K5?l-s6ނ9ש§'uoȜ/Qx}GX^Jy[ N6^C4O0TJέʰO ~>gǖuup%'ex D/~f~׵Dk;*h974Dm(y޷O=u+uioK$h3h\^*d5Q, YDY+ I>M2 uoMAj}NE3T@\+V{,1BUCY UƜ Q'i3l.XsJe8ݢwre녆p=Փ#S%e3~۴ N ڴ61+I?N\w@8/xfu+J<>gىujߣs˶3W1+KƲucмVWJ1xQ޶LBOy]gTB4[-ke#IW+(ßd'5E;ZnTuKeÿgT]q SC#L ѿqc]jVhICUyGkdnsoWb5ʧ-Rq\nADC3WȬ97wRkNghݺ _giy?u^'dw}*g|ߴx-9eȜfP5[榤9[ v Ohay\WǬjXqz:(6P JK G~=)f݊ੜ5q("s#ځ|u|  &ސlމ›L/M^XҢi;x6DG'3뤈Hˠ&%9L+ O$4}V.Z7,8OhXtVSeرz,i4O׉)(-rߐbh*:J9?2*ʵEQ(<; n t݇y-ZW5S~ a:0FjJGS;33 W3fjߣ2aO,!_wΆ)8SS4j ìjz>YU2 8$&QF ]y8Tx4[ePJGx {:֛y+e1Ja3ŧ[ n:5%ӆ2;b%)UPpJNH1z$?;E{ q᎑Y F6K}uO y0>\Q۲'$u)`^w\pLNfi$sZ崦FH,P.SJPӺI <}6<9`dܽX}5`j!y>f撌fDDj;I]/ Iv/(v!Q':?pamvi?߈1Lgu`.Zs<}?1AOlLf~]xD"zJS|?ٍ(nXmlʒjN˞eIc%Bw3of~1|yWւ|_l`&BaGក Zp9Z:gx [f6bdبFBX>M% azoéӅՁH:|%MJ_c%׈4T7Xi,ZͬSHlz,=$OS!NL~g2 !gK5n  I ڛ1{ JV={IToF's.4B>[+q8cfgY╦_4WB5OWWHSo7xҾPQDNo|>81N/RѨnH- Ygsۿ20H%R ;ͩ{3`'=m?wY~vUvGSL 9Pj;k}"/p|^~c`ĸD7›?v -tOo-V֖Kvß$2YڧU6.'{AxN+c3^GujpE=>v|{6$ ;Y"$yBYd[@vqCtE۞aa4(oIb-=Τ|^%N:gNt6E(Zc}v?OsI>/jEOKS xC~f{"W"^)7>%l" 2Ȇ&΍~:V3TˬHuZ]wO T0Tv>uZP7=93]_łSn:Ml{MC_ @a^N_5h ɋOz#>jfN5LT8X!$:法V|S|eOuw[6*"T-M%.!O@L6y8E.00? (ۙl~*-@.ՆMXPuCSfWБԬ wZ៺I/Ȅ\2T>ğBUX_D/,^dgj Y}bWy4ύ0򀓤$(/c)zJ ړ!]q𖸡"|Yؐ5XpRPaejmz?݆ |gMT]x|x%K%]@8խ >a=9ݼ=YVƋ~urXe7Dcv=fg` }哶D=m~K )CƿN Ij;O?;0>M`>wIOz ZtMZ:֛^Sz+WxޜovYF4и9l&~ S"Bn9 X}BÓp3UY:48Vs-4i6dW{ȇhŦ;}-9STYSȰ.PZ((Af 鬬nj~kQﶲT=K՗P$ ;=DB=jR :+-LPSu&u)pQ& I\mLJfŸ8No`s vs֜b`ʣ3:0IJXP £SYkn,);h'YvZ?eƬlAؐo咗UN{q>!4d!Z9z@ '5ǚEԾߝP`( aŢv L~rvq0lpVĚI y}B~pTmhv?!nn?2BW{۰n蛹΢Pceʺ zҷV<J։GlLm40f,eh:kCy1DHjV _@̮"':N+!]#vر>vVi~5:= +js:B7OF` J"e^+jҤQ>>` *xWRY-1pZib([ky0c)*鳋Gvwߟy?3=gω/`e7rXp+(OkbJ`hɢy{}XJ҅~QY~UO進Zik\ 7ZJ6 =:cxfJ)쀜HEUWqF{pL04dU$՜4#.+2 К^ʹ&V{c>P>AI2kL:rђÕY4j7lV7VY6wOQ694Δjʣ=)f&/Su!~Rzyu:X{`M/edU!q^wL5H .5fae-HR`;k1gN3Ǯ)˅vΆ[YXKw ndĎڝ}`PV$F*boY-6 nTYHy@m"40F1CQ )qH3 7jzlhRC3V$BtHRT!v3g()ᄡ[\=:f˚·$(aⰣM.LlTeGZL*yoe;p 7[mw3H$} xjVC!wpHRpQsT㘹Cס}^Dž|jb30: tw_Ypw^XxMө5Ar6OpSts*@!xҮ3Xߘ1)9Rl{j: ;,X׍u`"Ggqo,Օtv{熟\Cͬ]4lgla\s*jiǁRݳ165W O'eL<D!]ZyICYe.2#dU:b:sPzXHQ|)e4[F>rbAlɧ̓4շ1ʞ)J[iz'ٕv/`D 3# 2ra*ueUl4PVִY~q.c: V`>vV`|yG*6c\rv}:U^wX>n2׼[ Ǽ6Trl4@Y٢yC~4#J2v cN+c-CD/ݼ@۴c:~l4} v6iyHWRaCDF49wӜQ'V6 u)IPsF3짡φKwGƑ!nψr!ΰFSL/GNjURFCz0lle o, ɗyyL˓yX2/ϽUޥu!lvaƃ{.;PVRLft]Sa!S++1 gu>m,;- ,[`V>5ަ:JKoH6(+ &c<ΑLfTfIg<@9*2Cv<ŇHW͉ڄӇKO>|Zj"]>2K^M.h92vX?<քʇF¶>Ve Hp2lC=D><7gv?H %O=(8d5T }ApTW:t37_d1~,2Bԙ^$Ip h,+^i1xРbUr֧u[;D|ː Ig{|;G^/J=;4 7Erb2.ߣ'}hu#/79xȡ>R< ~6[elgTr|9㼐T1_J[gfɮ o)|ߟ͌auT»y[I'fc$+8r> a['iRk>}XFB3nǀR_UVꒀ^d/76)e=>i:HXWr"օx|w;@xBdH!/\R:"Jn8~rf :B{D_8ՇRO+6nGy} o>:X;*}6M{0覩kX;!g2xLiUW,-Ab +t+"'F,x). Zduf,mɥ k##GoD[?t;*1{uΰqz7yBO<39OޘR2#K>@! =xԥݠwC>36(z7ӆ~bI|DŽc,{ $_قc h(/!9#OBh)od8:ctu]K``C.㰭6MqlqV&!>6Z+ˉTmk-q4&'w# P#>?`S9m,0i`&ҔIJ<ÆZߏΞpO(3R>gFStO(&P Zq|R{ڬADěrg?)vJB!ic!N<ޒ%Z/܂\g(zO)tnǍb-}Nx&(>$ fRy~:cCLxVmg]XRrC?<ȜXEXA?;Jڂ{/dbdhZm.yp'cb }]W-8VC w b$x =lsO: JwOh  FoM_W)X \D aAnu.׮1gaB cbɹNvӁv8C1~wT:7mg}cKsW Cid:x޳Y"V .$`145ͫXBI4hZ6h8XZ"=QzL6zGMUvG( eM:}d-(T-NhE珄~u$hbm=Nd!'+@i6,{J/}nk86K2~w܁IPkoD u޿.4{@CWRU}密o8ktxRt`QHicyN KשL)m2THcޚӴʏ T|jk˷k}:D?ldH׌]YboK<N]j-qKΊ45wMf*N<lY(3:fϚp+,N;Ro^xaH CUy4JƖF;'Y y=tN,4 ph `‘E';.aIU4v2]Ja$f)] 9/C9ܑKFJ8kf+oTedj\ ĬhO{ڢJ۸7#&o?Y_ ,iO۬ņH~ GH {*Cvd~^/Vǁ{lRV$Pѡ\gt$\pp%ky:Xr,":/H)pq ͑F̪I#()obx mQ[P>Gf\$vI׉4+s9#9]􉠭#G߳V J{/pDd'"=p+53U6AXњ~cS<6s<3يgyZȲgVFT9R()lɁ"Êr!0݇י.MI<N\l:y2wis{O;\*s&if=Ç琢(5:,*zy;)0s\T@>х{(wQ֠Pgo ZڜeUmWDROQ>{^܀"qdLh/Nߍ߱C)h/v1O4ߦsmȖ`IziOXP%QR[ϕl  ZUa 2gHG' N* $=?<3*a*@`6C=UӶ9Nd6T|p ~ͰUH*C¤xoxfl m'# bf4-F'{+Cۉ3_A@BĤ)Au(rf @XjPϓ9Nbܲ_M{x4}rkpْRX+˱ɉ:լcU"DTG|`wA{]]ӫLGZ)7V\N,lSmlP#K8˃Vӷ*F&(FX1zp<:i jcm ̬DYh9DEv @x{13ګ jr`QcY㙑_lyt" uн_j%-ϼ+ 詯{cugEB{s0EdMQ:vc뎜rsw(wا0Dd<>I\E0e9oCIɋ$MkKxG9֤s.RHvU=AU0Sk<u&8OtΚ=^)ۃFۭ{Ty{ li6 T~WEʹmv~.)j§95UIE{;ww@R g{#Qhʽ o\YX"ށ%񸺚Rhw4y8{֝}mAEwafQL6R^+x䆖p@_'sL(7oU |WvsO)Qo|Bsq5#1Rxӑ|GS:+khh^H>i5$]7LeU{}tݪPM;=,92dmQ!?0Q6 G^EQ/Ȏpڳ|9/RSQ2V40r8j y(m?aͤV&P+8Fi ~|S ?ަTڸ'sƥpqa72 ʔ?W;ZrOѪPqBZ*/RBA  X欒LT[r@J54%w/; RJ /gOɔZLBu .=O1GR䬑>#N(%'|>!ݟԥ3j"OMF$ܱg$zSSe4ls?M`ȧ.q~fo')?OJ͜2xhYz8PH=m٬u0g*zb}vO&3n$hϛ3 =8hRgI&2CcJNK d~ޞ^'Uu0T !V6e!h%0ޟk0 U*dL76!SeZȚ.SDY}C8 J^#5)A(e^OtܤW`g\Z̑W#ߤ Ǽck|%~*:z/f=Ozh@>j(LF?8:ϼq!\[y2aMg~~0[,owP@JvUs4no\yHBoH0eRkx/?(uӣz77|։ Cs j%0F6aCb |5W."؛2p\VTV8 !M'7k̉C Yy2Beّg,8O y& 3em5z}?Zun7>\I?3 .=(I&B}! ɋm+q@x(>]B%I>ULaB$Sh_CqJPX;> MA /6 c<5wY6Po I6M@AΊ[f'3X%p 9k "Fc4"2D)8-z/ضL 8nEuD%#lI>u1맓zXvobcuTv$x*Lcs= 3t^7!_L]1#m;ϒSSQɄ}!2a<x3늲eX0*ۭH)8TA`ƕ,%Z!mBΗp3}u*hhJL nftCuI$|11bAd"0@GmO:pH!cqȶ"57M&JM+pȾgt V3Zk CsPᑠH*!bjn@Rیg$#φĚ@Lmi.R:܉t4wl-ʵWI44=!YYf&?P袻Vļ^iA%gk>S6̎h 8-zSJz }Aݎ LTtF4L:L t~Ϋjb˂i) &%L!wa_'P|Ւuäte?a͊ڨxz:!Twu+3)E:W!So<:~G7urnw\#g1ɑàOsو F'i򗟡Bw yyTWƋ{cd|"fK4a Zm)gǙ+ѪĥO\5Z|#JXS818tyWBM};bؗAp!reVu!к>3z\]YQAO;"D#}w̹n>@ۉH$eV P_Hi"%z [ؐ9Kxitfe2DL4rϪ bz 7Xpɼ[PFCpgD<*CΉb-OGYa0Ly\r{h#f 'IrO7w2<}ikf~MkӪm=K9O$zL:vU׉Ѹ|xpM{: sbYP-*:Axt,cXLIɧL.Ku4 DMy2F~+TȬ(:4kG|kEf6Y3ӓi~!vs ̫4HOkˆLs.Im50Bn|*#UL.Obz^ӑv3h:h<5{ ݼ=L׫ugێ՝ޅM(zzX$ho네 fYadOԜVqnhȌ]ODʎE8Wm6yQ'WLefY᧲}ߦf`ûSAu6@UDڮD͸m G%J;h ^@YddY )TlcvTib!Dє~ӡ +rl{/>8:cqI&(6tyݑZSwj ]gYp:aYxnV׺ũ;ָ$ aӣ-CdM;6iܱ2wQB =M?9׹b*=MNG-ȶ/H3iwKlps%QrOIg-Y5e`г# '`?(? woҗ9*.vtZ! )_j?'*MK^Ϻ$bZm32i@: A>M-JwOnя=-^Q<ؙO r͙ȆsGpp+Zete:l#3,EOOu>29s1qaCѪ,wimQ.1l儾LW ;ܢzJEvot(h()Xb=%H2]GM{Ƥ"E?5K X!ie[_ijNBI,iZ2+?$< < )&Z%NQ# 9t&}̒'yOH>FB9|-ID)VzQry%Y =-Xo4- E'Bg= ]50rNHzHTa~6}AaZ븧T|9a]ZeYđunYdVUgu Jܘq J8X:Aّ)}O7w!DkJbE0ziYgG^WXX+A>y+T0B1?4rYxhCzиWɅUk(Og[7qpŤG y`ǁuԭkz !طZW8/|gRZ++SoD@ʊظE$2JYсeZI:4+pk’RRe--dk՛$oAGo2gd&,gr:E{oczB1LHR^Olwv tj#D53sk^syp(S_U}8ox<.~3 pXs!ن%:|xSD-sy_)j1;/39 ǟ5rky<1Gtsb%+7tYGp6M|{+Cϡ2+ Ű+/fY'Lo+2rKuHDOMGq+.0*Zޗ[AO4TJi:A+#3X穲} v iy5qԙSu?Ig((kcsLg*_j"ÊIѹoOJ:9${-y^A7'jBw {{riʶ$m3YEl Yl%HN̔.{f~#)U[ĔJ6gpYYEB8lLlsy q/PqC {htgx7xV7̪%j\*vec9; T;C?ahyiB.r.~tTF^ZzRz qOdg&*: F19w! mNs]dLSJ@$_]|rv s"*xX'xv:g<]RȐ4E^j?*xҍo2e s|G|Y&~5UleuZhf=9] *%O^\4)EG:[㞲\xnVe`QgIo {GD X2i0zR]񣴥,+E]p3C:I[qo lgҲ" 3}hmXL7ʹ8CJ~[ZhO`U|(waH>IݔAܤ`º:qվQ=l .x53YpqEC(j 4 5ݬ2 XE>23C~XnO^;^M:pQnsXP!ǠE5`*X*YxY*Igxg*T? NLSYXwAis'S I\3BŠzjCx+;%}RY+x3gyx9k`eόz$VLQqFM3` /e>3Ϟ> wgfk2?n4ӡs᫯r_$) IfP?y\xʷHc7˜NR2*cY dϪ)ӌ:&{ure$<$'A髳pZ`|Wv u +(}@mJNS%KRf姆T9Z#QIY8b75 JMԐOwDC~ 돽ՙrF/_i{1ı5 p^ӌ3'q yt9,;9㼋u]f)fҔu{=V0DTS)sՒo ~kAL)] (X[" ׁ<ҍkYº|Yg?\9Ų糋yYKK3 U,i,T 9<^l~:$Ze{dO]ZeXWO;fj(ƹ>˺s]b،0RѸgiNӿg}tx}jFù=!鴍9p]]U7dDaG1z4\Hӛv*[cǂEu==_3] 1Í)ZH=ԍgo#j6ph WVL)Dký=s-qv1Kt"rN /1@xh&1u@+F'ﶰnsrO#lΑ=y1״cJ.f6.<SlVI t⁹\vܝxvm˿2j}x|B!m!"?]PYȎIDs rض yN!gn?F%r9;e;廊`*Qo~&sK?Ȧ)]3:3n"ֳNҁ gB0Թ#?'cMCx Uq2mG_N"B86ЎNĊr<%Dn+ΖPgb=GH#q3sO9K7NrJh23{ *GJ;s2aD/GxUB>ʽUK$<ǨH(HTkYmv 㫒5hgNoP<^/ y_%V[==EYK/2HC܆6!eSli 6TϹz6ZƸ9?J@w7\>!NI^J76s~wѧ1[T (}CK8USOygE\W( ~ *r6OTQ +yTeuC~}{7G@콎p|9#ScO;GGj㡮}|V 2t8^='VILI 48_LǢn8z6aDH}:?YHiĪ'A^oFyjY)?р t1+SƎEn`ΤdZ%[,t]:P0$wMTxNxoy4tҒ}]gXZk(gxwh~Nud$Ǹ#Nhh3䇕 p&]uas3bݵ ӶF3KMV0b9'Uq!lδ^%{@-=OH?"^#f'tO(BO&}ov\ pJ却 Akg=L^QˀWvf΂)H4ZVÈ.L <ӻ8Ȯ둿܊E8b^̖3{fJ̐g4ש!% 6Ғ)-1+R&Esfï4t$s0JǪ) )hO\.P'~s8HJoNEO:Sھb 8#S(<¿ ~I|MY:'fkGsbSz Ja dqE|S*$T㕣= %M8;Rfjw@ZyEnx):p6 h#]5O8Rck)3:츢vԨd { ',6~IZn=XN-+O.z'#@S?>^~>taD$wB ua_Iw~#Nu0} :}>Plk.-^y-U%K%Vd%g hԉ@dp㤌8~BB*b܁藶Yp L4 C Nfj&Ey:gVh\ND3ϫAY[<f.Mޥu Σ;U^8J%:d-À (f1enJtuti`50ML1y`&Gq"#dW-؉4B}G{g@ʼn2 }8F#w$lռd֘[}&]ҷ͘=f[%캚hy[JjI,SC}?< ;Μ`b'W@L+s=a"{d 8 3xtۚq Rmg hx6WTy?P<+1Y.^x <$ӀtnunZXUȧ<9m4s?_zi\[sxtɊ׿N/ѱz m*P[Ya0TԊܳQ o+u 6g4bM}VyBş2s*ӇGd^Ӻ:Cyfx7UGxg>_wnD8)$!gά&Dzʬ-쌾4RxO..?9 h:R7vښ Q (CߢTkb)g);ƌ1s ֥,Cky3jjcO9:xP+R ";C'cg o#3M~%1/Rd]{~}xXi9 ,! z mo3Og"OF<<.Ch!`.S~ݳDcr^y?R@IeAxIf RrPp&s#Q匛MV;'j iN33c[_Ɔh6k8~d VO3F'AsQ`짌KX 51'mp.m"s~@v2VڱUm@R@: r㨳@3 $SqG;1ǯ}:K[ꟼfBw/a!5NO~%"i_T;Rd9u8ϛsB~--}{,Ur܉Y`LGOym"Һ n/ e#k[U|<\Jfz^]ysd Kd ;/{4؝S\P;ńIT%d;a2=sm^J+:vf9D.Z:*,K%N8LnmӁe.5.32J,we$iHqtne'D$>ǒ,긠TeR[3\Rf б^oEgJ0ۢ)kxH9zb2 Y|N\ɫ-h_bnˠӗ.B7@ω n.V'SINOv\.~&"8q~Ev7;i5D 'fXާ1ik[Ҍ=sȡg^ז"{7zI%S((_[]Pl̽Q[Ү-Nz53;A}-}YNss1 }6Fe@CE ^ 9) mْ } X$'κR[bAŹ6/-mԴ`_\9?ȏt`&@Q9vME_g|&@>+t+ϰ-x Ϣ&u x9(ܙ7ۜ'; ,b9hFm ŭsZӚ|Vvn-f8 Ãፕ[`'= h<%0~Y4YɬøVxq4Z}F*_6- C>TnUxCN/#=je}6SʗL$t6>t#u8Ӓ%N}bC'gៀu3!`[86to*怮C烁n6 wzӓ$;UX;uk^Wp?XAdD,ăs[]jvjCDp:[S6 '?'m؟{7Us7% _Zm + tPi}GL=5JRӔ4V7FO2lky2mM6Wڟ)N%EBBDbimrEc Y;E\S'W|4pK}>R#3S|ۉQJݠp Uu$$62L_Lg}TR־A[!DM)!Ћ:9?ɇcHiwצj_z#54uuNOosHn2Av!+K ճgNȢNfP7Ȩ n/e_EOGetlL% m4¸ϓ-$9*C5jvDV}:/@^c/O>P_Zl҃P-;AgYR3/ˢ Kߗo+:NBڙ3|^=/x7jC\"xƾd8_q#Nx0:}E!#gj9: fKB*"S7Ʌ!6q0'IGd pWdFLDZ(]{VD̨LDskYTTzAZ@oLV.ZdeJ^S[k6"z?$:eKg}̟wQ;jmul-0F Ukh[?{JV& &6|RyQI]{e}ϴ9Wda[S¨v&J`wГۿJۭ<4@(>,&!BV؊<:s}$/*:m59 |4Al+d]9/ZBX{6ՆD s֮SFM/w[Jhnw_|N^@Cs'Ԗ* 1x`XZ<,/^cuMVtEXuVy(Aer` j&&FI3+D zךb{%xcB'Cϖ IuupSdΣ$VPl2zEV7S&'FkˌҟPz=<b隿@,8{[X>9~9 0erъ |S VhW)F1fL%dѸpQoIY/O6PS hlTUk6tM> e&_b S8jX~b9dtOH}h: JXWmܭn4Zܰhh!sàsrխ3jB xAf4]T^P}!i<>/-b!a׍\itl*[c ꌦԡbAvnܴ5V"Lko}7M]Uʇx?ͮ҇&9A"-=7K:Scٖl|QmEhF ]0c,Hf'(n\νV )FA OQ¼dN$9H^G)7+ښJo+~붽 *| WC VW'E&3:%gq0m8|AcORF{e& 7n 0a3nn7~PZDg4N's |r[UXܗ=l<)h17dON4ٸ\ Yς% {X.p|>s\Q3%VfGvL`DFL=-kWgv žԅl$ wzFь&IoﭶM}tbϲrY%l)+o^9S/#j:29adp/uLm 3vgR1_Iu-Mbks; swτ"ÃjZvzhQT~4SF'X ,^%'!ٍф.9y6o% k$[mнs$ ~O*E>]['F{ڇ.3եS|Q}UЊFA {eUKw4Kܣ)<$siUscFǥ;WWǾ-㪂o+nMNwO_{ڲG~h,W͓unsUt8,̥ZQEm*twd1_BZ}o}#8 5BT{8k`~v?"tV 軙kFj؛rٕ#$'1eP⹮OTЇnnU? -Db-dBRnYj`ZPh @Kl2V;e|5~V߷]v˰}yJAIŀhs֫`ot wC&QEkrI \ 6s5*4h؞s)b :mמrF&P.8cWνh?ѥ^XOSE 99l9ө^EC ~#zx v{5FJ[AY*ig5w׋ljqM 7"'nWb|]4*"= -\"zK̰S'iSi 8ȂhbE^ilQ~0*{jS)EkiD^R(B+Z&5U 47n.Bo.5_#Xmb`ȼ #J1&M^3enuE"whlj=8kW'uqqiZb~BT&]pa%/ޱNoyˋOH"uV3dݖ8v +_/욲cyar;TA'1ݑ?g@@c>$ {SPco68%zJ].`+$!Jw`5ިTɞTX@KP,u\"d cOso7!mem9T3ӎ[_f=e*Z>~MXq:Y%SdX"os}sq|UBHk.He!gx;n 2OWPzΧe4>OG`Y7ߥ^0Dn>lCBXiq"&h7WϝM\IR8 KV(5o͸6l)FSpc;*BpF}oHjʋCۉ2\1{\lZxA =qry*ns*V@NMf!spk٢d'ЮR;J; VߤFWhhޚjiࡢTUsZ ʧo*lWBx8'4&`"l羝3qS]r MKv5iI$$pR6-/欤p"yRƏ}d|ت>+\UWS}ZvŃB(em[(FƚĀj35Ѣ+}Lc'Σ]!nNo^k P)su @6*w~XoiM8a͚ 0,~n˾iYJ2T"= 7kהThN^/:4 Oq^Ty4[*>HWhdSNGu 1$^P4 hFKn-u*̳RogTWd'u 5=8kE+iֳشMh6H$|{CK>cV/3e jYsx葦5Yv,HR[nW^w:H^PB=ɚW碭g zފPv0 լ/bs\$Oyk74,yFgw*2gB'ĞۭjM炲4fA[]w3Dhvڅf槯Goa7iE<uR~d4ќo|<uKǺv5!>]B!nnՊqyڹK6өA{Lf%&[1 P,ZSsFs͌{ТU}FҐi!AW=+JgO@W i;A&*ګ2W"3D۸Qht[y(qmA-(/R6eŜ7PWg˗~{|UEP9ݠ^{%*. ]ղX${IHw! jфy:'EY%PxݸwDegIP6jp[ ok nu>gb^h Yedbk1N3'L[A6KIufnkU;e|SD%{d>?Js M7LoS!NCixVPZ✎=v~b&N#%#wpV T3 Y,tT徤9AN=hBUS/+`ֵiQWP;vX{kZjACˌd6W\w#Pk9gv'&瘎5 Y5f2Q}B@?NaJO"[r&:A:Ơ'EѭQC$=MަdrsYi$!CC2R VUYaa{3/EڳSHK%g?j=)Dʲ ƞ) OzѨ+#֐#jY5s+["ҒFSQu,ͼщn,7[i@ `X-G>gdܲg exY!϶<Sz4Bn[]}`ܯ[AcqG+;bL[C$殮'W87oNmpZS}VsV_s;G'ʎJ2]fu\"i{˂<Rz U=֎]ͯ__Vbta UvFu~p]d幦Pmly{yZn&yqf@;}۱o(jij#mї ۟?#'1g<3%3­OC;;nUEK.Ҿ(iJIt;3D%1ؐ7Lyι%sEWMs4?w}_=~BںCGJ((b ='W帻-h=WtI6]=D&Mo,] 0]-3^Kiˑa]h2*pBJP ͜5K}$*ʗS@}V;-lgh٤@! [[h2b|,'8&*N<>x<{SEBG:Gw%k 焴ÖGv[nHa~'RR:쾣_<+ÝVQ4lJ9Flj=,:EG-Wv>I;%a=jڡ:~Toh.({Ιs~E>ހ27 ? 6xz_g:e:miU1k?fbhzp1~/LԴO UV񜴻Hl I~j<UoDշR: a?j<@cK>3}<_1/EL>Z'UK~a֪٩Yzpcw;wZ>q񝤋/k{KG4 ͯj$E!]z*>__HEg0x?8Fi([~_#lk_hio]]P w@=@~jnܲe7W,TmJ0I[3"Je|Ic!&PwEE;'IϰU?CS**S_uT,+(&_ߺbyH,q<o@~@ ϸ8KшL~v]nvnnVH]4֙O;myZmsO)oz RD6yҟNjCsǼ¡Dfx"t%)\e,Px)- n頵_\.|F– G 뮚+e*a|"f[*#R&MD12&*42@wKgm\͎ ;I^d,ٛ[/>=o϶F@۸.1^Y3)`Rac< +狜6{#2Zvzjirtjb E`>/"{ݖ?r臆zt'&_A!S\.yzH5F1mԦ lY~xu# ͽ>_v@ϟP7~GPuNR2x_hvB/?Pg3){G6[]%٦knUw0M2C3+zpw$ /wFX{[Om%-n,0v.sB 6]1}`0a˹ȵњ/_F5>Nͭ21GݰF^ w"F@|T΍#9;ˎqK +=6z{&&<Β5߁X Bq|t,rG"0Ggg6y֛9t E˰'Be_~{A Ef\xF9O'XeVoӮ QȪhҧ4][iPZt*Xʾ'G.@4?ez25rZǧT,+R wm!P-Y;}GIc{ttXl@3 tT0۩nCufԏ 'ni1LA8CZv_#: C?O\F"O_b7WjΧ#*-+/E@ fV[nrP[\p9?lxM(% 3Ӣ/2}3kW"vzE3ɩ 6]Jgo>JԷѦQQ[Xذ k|{K9EZ{/G5(3]箖?6 ][v}"Aʍ`V"(j|):# tpp!bÖR8HVҏ'HV&iXBPm֯y ^RrF6:cH4+Qx;Q[BgS/ ]ZlTM?H< n(Կ{Vz Y'J)b(4`[9;b(G9weAhȅ\SMߚlwI0TajZNOS|)mxJ$SW) 1-$Zp)eHQ(^ѱ+1>bh CC6%Ұ緗.,d*o.kFn ]+:PG bj{EbE _ܭ¥,JJ`͗_9DmTuQ' "{Z-Nrؓm{Pkffnt`dXYE UeMk|zk;}s' 󷯰+8O&g(@hty.?}~t/G;R?B;0[z'nӇ ~Uf%3ĦdD\X[!BDRi E'ގ- oIٮ5JMЙ[S[!_)HkӠ_T17*%)>[mv!{i&gy\^H@lmCcY6t&^$eF$?L ˖ْmqoH#(W|VuhC-4!1a$;eӟt:PH4'"X>Kw%*{k)c.C DK{10Lm\ !-ܾm,oG1]XyUXK,Y X۰!e;F"€=NMAxjd%aR` ,}&34] ;I2;Ip,73 ;GKzx+h̬B E)ܧ)}IA2d5iw ktyܝ-<Ӿ| 8 wbBYmmzǎz5ntp$%QExXbǢދhey@x$2UW05Jr/c>}XPr؜t:IudsswrH: 5 LMCzk)d BI$ARDrJOE cwBX>2:mO{Ic)ռd(YMVw!O96">$B/uF^x5[л9ӽ |ѡJlUê<]t~KA!%؆m<uEBЯ`J=jkOycwٖs打f!O4,X$'4?jX=#n/nAl^̖1^<_]the2EiIqE. 6#b)W~=IBr]J1z&dGWiht{-{LS.5 }EȷS;m!opxǜ_hwsJT?x|5:Xw+j0z 'a}c- 1IdwC~wH#ʋfNּ#Ɉ+(zCğ'mccAEX~]f{S{=ehxmGw8d'FiqѴO~pEXVX$Z8 ZCЉr\2RAh 8 "Vd4f$_)(ڳfaNe>d.M\%Z2R[yvػ@f/: o.OCc`<nm%~sֱx$(O1Cf%EXCX9gpof̈́2}F2b4 4Ș*І_\eüKqX"P)rxG.W9Pow*WA\pG.8 ִ,8qJhsWڝW؉#x_?9>q*o\ uo%OЪ|Zx=L7O9PYV͸;)$PnC4J; ڸ~w !C)c7,6٫ Z^zͲZHgp $x$W,ҩ`\{ ;|qq@E's !4{__9{>_@6?;|Q6w,$~S/:)ߣHlh_DNjkoWn͆&:4@ΟˇF>[VމQ5*u}f)esL0usI;s,wzG`T).miZ i] 10yD>0"ÿ/ȅպ LͰ&sA-59ߒN6]+ yY臤²XyX2|`c k@HG BZ ވssnks=$;N{Z<~/FϤxqν4%O`jgO,/u#'#1YsєZׂB@le:w~黼&"ꆚe ~7`&o%,8&u!oemxTeܣT ⋬@֢}(W%-4䮶h"Ê&2meYq~Iwc1L'i\r|g$oHh: =k.턟qLө{Qw!^A)l34=N+A6Olpyoo |HuvƳ M)$^F5 Ɋr)ن R*mw&'> [ inO8PƱS1%%M$OB}ӈi3@[Ig׍gͤAid>y(9)6MU+QYOJX1>RE;{/Aë'  y5nRR i2GVrg^ 9k6X~)*UC0UC^]Dƈ'vu7?i9x /g5 Z*&3ltH(\ %zÚ-g(Ӧu3m MxRc zS|==}U%'6R";k f΄LwrǍsC]rGtri; ?Z]R2&ރ"5Jߪ4],!Mf劐{H>M ȷk4NZ֕3͟JdMxEf%sJaOM#ʑ;I&f[!m`A2R Iq7HFPBP*ELpa j s&FyΛTϗ}頖s\UT2{Kp-H&Nbg3&i!hA9SO.0S~r=LD>BLU9džGUIEt ;p$DI?rq<zJ)w|M5Ԝ B^ɔ>}⟊(?5KrgђRn4M2fفwH߿wX38.cmc5hϑH=?'0neuyhWt6VZ?}x"lB,k._g0c?nEu ld3$.BB?V֕s@٦YVDepvijZ0J<*/~p%K0ɩ5-ðb`e,5m,e؆avlX*mӶ.1^iCd)( xs\rP& FoNo8c|Ku$# >&\ ڢT ^}vK:6윴Î)r`Y=k[ W>eMNPZ /HdECfzШV b~ȥMؑRJS_xd' vYج j ..L}ԗ{rAWv]YEHIMɃ[ERo%jFi_b+ov,y2)6 _%2.Bys?E,WXVUmxܘєЌ.VfH͘"RJ~?^STҖQ;^=DU_]]_^&Q.>gyJ*eL| vM.L[M Y9n ~mr A 5˄iOթekvR$ӧ0|LxCҡ2aqnw~y>ԷaʛZYG"8|Ayn F.<@W35M> 4a*SҾ4cy;_c/P GHi_}>g y_ZZ^K6ӤX·բ\O+P4j9a].C9yfS'I`S6ᎩEwLʢYf.S%qSɋrMSzjLgۛ[gd' #]оVH*GZI^zdh/UH=7Ck;(ZGLv\QNzܝy{홺 f'RĢ,~YJY"Vg4ȥVcêPekeH.U ŲbÇM:&hjNQ651ێSÂx A>OdY},hC&kj:.6r9%\o@|}i@Xi4]@a̜O4= Fx|Fx>D͛lPơnΑJΐp!]Mv-[pz3Q@|y֋iX vm ߲ P65H1s:=9 _W_D"x^.6"jv5=<r^?R]!c:5 O9LAZn&c `,kLRo`4<a|*w127>PvUw~ @n2NCn^xzBNpwּ *p͹vQ1:OAu c ڬm:p2?-0UˬwJQ_|@Hmju})RЍGvx櫈C7Uj^*#yZz^'vy6Lg0L'fqhŁ֭`Cbˡ[IPsFטDj{5~_M;#(7}Zj/5yrS*ӫckZDuosY  Z/Pێ^.fUh+7PXF Rߣ~@!.eّ6ox|hI=99W!EO6ʼn/;6;UY+buSYR[>jJg`8$]8Xnr+ |^cVi݇Ng|jPxr.t)khp㗽ՃC ;oYx'l uj`N77:ew9ohVU #U1 *e%tN}$YW_!)j4hބSc1t56aշٲcKFMwݚBmn>eM(qN1KDd>wN皸D;F;I;_dtSdk;'Mas!I0%[Ȕ@e,@XV? $HWۼYC~ԨDyw`5֗. GoIzS]*1P,MF+ 6mHAneSpv%wSC9el Z)3%/y\}A~ekѐ#t:'c,;&__u1x9HC! E"$ߎwnAݔ?p.ީ*(lPA-T1gL+;6O77S7e9Wnס+{g5+H8F`S9k3ʘe/Oδbv;GqeĂl1k3^#{n$jYw Κ튕c㔕ouЯyc>&tXАvrS! !킐,%tF0 )t%χv_͊JmlAR|ǩAu1o'y(bh1?!Ftk16i-pog58K15jܛ G~/7Qa-CQ̓ON5mnɰǼ~616D4VXid=iYtMFPl7HDp2W_U8=L3m|'LHfG0&n*] JŝF#^4~>+R շPu#Xݬ22U>Zn<\(H1+3pS WҭѸC̝~ZX9Ht%-yz[)}X~x "UD:sa朂᪸rw!e@KrTdg)uSY-B맛sQ?2-p.n%&6U^Jd S &"TvsWAZQyCS$Ci1]E޲ʐeW_ȍ68VneVpV} ՗o|cF]eŨc)z1\k1_G50WAE#ϏI/=%N֕(vM fO4)|)G}XA@}V],M94`m܍ QRmo\:.tnJL.Eަ3.2Z,&JW{Ag]Ԉrnؑ|HzPճb$n) ekr. m. lri/rPmVFtsQZ\=zN fdEU/@10V0*qTNߥJ@9:5~Ho_5+Vͦ9d !cfɇD57lr֏|c=T(sp!X~D]wWө_cVa#<|)mqW[о!qL20ړGR-.hE&5Lotp ]!+t0 %h:.66c*(5jiEw_PRk}$ygXZ܄23V[U.D 3͕ J6T"6h "7SAeO*/'˷FۥҼ`^x5ʾ5,>]Gz:h62mpi?K*9tȔ;L1An1f?JV v|L1 A;ӆAU=vVhRվڰW%K\W/'ы],CW.0|P}SwBC#BAN*Zvb?4^[V}cwL.7懀 RE#5[eIg ӞK]=1nǤSO`A% hZ4O\BYh"sdGcrL*7}dh4]rT8㝀b^t|L2,t2$bҍn 6ѼwA9Z݉qq/Ʒ5QzE ݓyMu5~ hx[2 30 :GG'ð\VqG5ej9rܤBAWʭ^0t঳v>rֽSx'F0PXˠls7+ND00s+$~UO))k(`*`yr*_<=FހC weC{dϼ=VĘ V9i)W(u~'wC=hX`)Pw*/ȕNk{WhlpTa I)6y}{~۝ 9(~3`ׯz T6Fp<[H̅7/j) Z%z 1a@`F}OUtWNVm g<0 6m i=))|~>xr{%>N$"#8~hՊjܘ3&rB&ze u^|0dWX=Z-Dz^|OV^;5!-lϑ#?'@K_3` * NjU벑 Ep$<< VF-%;'4Gd_0ɰӾ“#ۈV\ReV1y|t?! `LS~O`^+8Ymڎz7u۲,^&/!+{me,Ds,hf/|o1Ĉ5`_d*w\(UB3ЕQw.q-͐4c <,W%1KCήl7d+E}0#V z[:fC򾐕\vC:fMvcf ,&E7ǚ:LCb5}3fPz:y,da|~{wǬ+$ETj|-9=vb=Zhd(͇m@Dz f8Ἠ߾f׃*(g;*?$@MΚ[eT+PE3S**xٸ##4VڂkCFuS:.[r9:F |&c5UL5mOժDRp1|Y f 7ƈ83d2GS-%mo!u] <<faXZRobմ~8Z@$ɖťq?Ȳ)4l16҇ZZڰYpxkM*PV[1<J3: mt~⮶Ggg~vM*1mIgXدiO-iΎo򀦞.@Z"mt̃vs he\J?ԏNO2],p|H|f3ߖ%CN!yϥ= ^DX9ns>֯zm&({R( \vY4ZYF! OH@D&n=Nk=δAFJ$J;Q2嶒f'tlM/8]qk̭2:fE`p>E:I&^|5h^2>&kg ϯ.Ko̥䰁iZXHB5~H9PЀT%k213 zAfe=>})" ڞHO>'uM4B1 `nAV*A>/2{ҘşC5tG*TڂXcaD [iͧ,lc<ZP >A@N r;&Rch dƫ1' PpvxbV}f>Y6m2Iښ)E \8=s߬yi+2%!1'lk,5;(W:&ï٬biޠvwޗhtE-viz`lð` M"[,D=cHR`ϖ̌UF {hЬ S>V0| Mʄv0XCmϧ\ Q$DŖMW-ߵOZA.YݤX&`jk(K`8(8m6 #[~* 0l%#]V0O"mv|.s"ݭRՑcl.nPN#FNH?m6*՚Hr)4Qεf􎬼fK1 = Iyw%%'O?UQ^Dy]#.N.3t# ž\K1IWyB!#HS{~|;+8+}d_'Y/L6gЖm]R橆X,08108:Fuă–*얯i>~ŧc/fLu+۟ h`WƆI8,3D>C򹘜Sy#;hd+έoQ3܉g=/|/^\G;.qu˩pZj V{]O>n9<j "IxʴP$C 4ai :/b.~s\cq?-}h$ Z֌DkO/.7m vKKh*YuIء} M>9al 9 kۃF&9߳1NQڞs<kf F=LCºހ*{N&k`' MT\kRd-,~a'N݈ޔ)tJf` ,o%`Jںc۟#> LX`lS'HKE॥(aQ bx 'ϟ,U#+`"8mz"2 \uyos_6i~@~m%B: 4YwDή!khe9lR]74>HR:j߆ h+%@sή+mKW{__t3Myra?vO >m44Bw7!pv"a5? 6l}YŇGTTdý]7ͽ7\`W6Vս͂UfD`0ī 2?wM~KM% 6=q6\QDz-mnjhSF+vܪB*, eI[B=KxjH4-a.&EP&$IQn&]ޞOƣ.Ԍ>֘!Ay&ōso5Q%[ͫv, ;'%yhsP'6YEԫ d$dsBeG xb kXgOTx"E=`#A `'I4 qzc=;B)hgnV4B-^ajI.CF"AG#vXһOqH?>tn"ˮdQ~A MbBev_m'㭵5̓ϑ";㽝df{yX;2PS30^PnD7P9R\X~?wPvqsUǤ 9uacZ4?eft9lT^uY9W$Sx 91\3r[zCȟohN[U(gǾ_hԤ's79AtsLB1oCH ^6y:ċoBs 3Edj\#no`Sh*J9;nBFObfܽAq":^qWs?oWϫ$Mo3`#^ϰz@bβz,^TcRɛoŭI1A{9%:\ Y?EXbëIGCC6_w*4Li1̐^cn'j9ƪ[Oe0a$~q]o?ݫkVٳ$a.-mϛ|"(:\ jzz’VR" em05B? kV6tі˿iNȬo?8AutiHA6 g}3 02G:RP#w9{ O'6nedT)QA6MCuX#2T5 2UyD 4f.|?zyg*?i -=~4%O:{eg9HL}WO r^b>;FިUyFEX'܇ëdWF<^ (9^xB.a:fCBI8PJr,wt-B9~#wt]bH|O 녀{H&Pnţ8"gȑ3&_"^j71ɳ֣/>0B;u+ӇsxWprbc]?}m.kyHݯPVtu:eޙcG0 ߹:_ٔ7sϓ=z|Cg)2_DVo":eHOt;α1J~o()cJ( :2[&3*=a\Q2x mzj+H壮W9h"єs y"^t)8׹4L_B8&TYe# W ^ r/DG[y4SVK}v4$(MԢl$]ѱ$( mZ>!Zsu\7699⠙J<-ԩc~ 6>%k;v|)y17q:At*T|gUCK"Smr )r HW #hBtFV%ӫuDCY0JÄ>"t(Z"&K_KbW:fYoi(|5mtʊ.o-@;0tue L:*UNCEPnj JV'):e`f"?vnsAMBS_18ݟ͉ǩq- {EP}iDjzCW>W'Q,\):P`;z5t)nֱrCddϵ 4|P>|ʙ2 2 _n0rgT{Ǵ.sǴ,JWxXYNUDEr֨YnL>qn "u!qpw(Vzwpq4"c^~W@O酆%e/H:ikκ.ٱ"_zLms]gHE: xU€ 564l7#m0ݏyveLpX5 ]0@ò M6MVJ}fh(}+&Xlକ-RghE\(mzS 2JyƂ!οyZ kaq6| "xi췎7VɞSȍCg,y{1ulUTAlüࣆwX=-6jh4:!PO8 }; "h҄X2 #/a=ǀZsx7 %/|  89Ɵ_HB@B9Zvaf`wEǛL7Vr,xg?jF.01]ț~eMJG&nnx;sf!RC{` 'y>KJIY=1t o!'}I"!K@Uh fʔ` ֺ k ܢcB{4imNmhNm%H5s]8⫎Ua}R?CzA?޹Q8Dʳscި0FPɻ_Wߢ  ma Α恲tXP&(h]T*Y*ĖuQ^h-"wFdܺ1,P۬ʟӁW >b%yNE8on5/V<)V "iAo >X=mWՏ imt=?XJ]USo\Ƒ% 6RItU, ep|4aN !N+a1c3lxT2U\E.599*_JX 4zF $'gpSlU'8[ Lwߊt^MR6)@."EA~+taWͺ$l?!m$F[B%C\02l4D(lIٓM Ն|QBGfT'U.`kZrc)ByC[D 0b+eY9hiY%nБ<ߐ 8ȗ]Aufч̓سD6a@`MWȁC.FN鍑Sypu~(MQ0-5fYUy}B3!"CQv|<{٩# M$(# ̯%1|s&4'xJ(:i9hw+,,A:f]a.iǬ}]ToO|&pQo&z<'Wy{<My2_pVe|O !M*?&^T)ړjL.wREV=٣(Aʷuw=WJȗt\*g}H|`xypJ"^0U?udVPD' /ɳFQW!n>9[`/[Ngsoy]n _,/ZF>"C?~WI/9r_eSe`߽~^Onm駑j_Ґ"Wr*͊M#|^9x}51^~<_y@b5)48д87dnT-VجXo/fghoZzxxeyB*= o B]b/,J9Jd j"r7~t44vCٓAC.V>?#DjX-}7ё;İa2ռ]r&.\%#ml&NgzLKmx<=:gusd8)\8]PEx V2G,m,ݐ?Z Vs.xln:jjLMjoeQTxfog-Mh [DI~1Nvȶo?vCK`nU~5FoJ1QӚ/BhQݳMrVϿG"YSJU魆rJ՟V`n=er(EQ %k6'Xߘ H A ao '8 ?^hA<>U;k"6r!;sQ\?M$/̶1~HC&;o['cTЌ^ t䰓K&/ :ů~G]v?sngbYË!/J5!i/h; O82`;IJmV#~s#(b\^϶syhhmyPbO*`}1NLAfcvrjZ䂹<:5xBU"BCsq_o@:X-z*`LglYg$PMPa5P.|6n/)gV+*Zi2nfV@oUtD< d<,uɸykN#VŃ*d㛳F'OLUnܫKx^9Hn3cGAb:CrUGdǮtU9Aqk-.0)`4z=pwJY S@m؁%ci~,lBFR8St_.gLs94ꫬz{9Zy#ޔsנ\v>G*#s mDb49 )omh*D,iZ~*cތuF 6CB%v_ckiM>9`ְ$O]A>hKcN1]oy1|NMVVu2ǀ*pfy2@NZ\.hv3(=w _涏3kNBp)۵;t>B#3בf!NwOy_.3衇< XIe<~Ƣ?n,ub fpSs4:% 9 Fp<푏O[M4QRFkW馡~1bNۛc=\ryUDc2m!AU~MV*G0;,<RL*%j?Yp`2(+JLs 4G4ҾrqLǤM4,=%,$1/)5hI|5렯7͢ Q Úbxh"ʺbR_Ϡ^Ԇ. EJ`]Dz`mrumc6A%/3]ZwjTVyp$l;^;\V u1> wD݅/.6(cZ C1O$6T spHP&WLFO'nP&!cVldJ DkC=3J[K1: #u&jA?|@ A-3&FƝCU>s,ז5+i6:vloRÈ. ٳ TPM۱PNjݪPQ.3lwL6$KL{-lL$jg<0V.ri.s:O^;Aer]ls\; ]#Ɇf.I*D\6Fq چMM_vT5\Ն-tM o1Mc7f=kYxe:e 33jz/6Ў?4{2cp7j y7 =7?] ߹rE:y)O^Rk舼]3A}2Ax4g*:޽^xnkVhlà6iϕ=F/&p ; ڬ~WC̖5(~|3Wdq|pK5x~eaSBܟ$BҘvI'ck.׸0sK;)|:lO1P`wjvYkHBkQ٪{K*ePޫA|b]tԀaXI+~ǐ;ǜT[4j❳%ܓ1H_][ñ)K<,hUT$[9X>'_8ͻA4ΩZڴQGCja=ڿ5?颖,GÆЇH u o#WK} é'U#)mw|_@EI.3o\H[㲽MԪh{0 7V.uAT st_.mC=u tL hR2PlL$ [! c<!'mYq:xXeXyZfwa]{D:˒xjq-Θ% L7m ၟP{h)%* DL,Y'.gw8mф5zz2`  vړ6CZh-$K[erYyj/s&AO_‘S/: |nt{ӸE$f2NUT]+J+1)8lΠlU~`EeeKݼLkQkު/^pEީ=r2c)n عbP1W[W:n?;u܀]5Ze򪅻ƐAzc%j-HCK[zA7q;__-Q0t7\ uCi=OFdCro%+4р9&A o{YnIúwkAfAoZ_fʶI&w_F:6<[.?zoL?v2S~گ>iRg2d xH]򬚖EK##4x`̣bPh$xDKti g Ӻ.Լmv~jQ ]W]<D*EUB3eiVf<] 6ᔅ8%ϑc1?\\0Y6>) ң ~PlkZ2*HNkѷf":dO"Ԛfu2ܭ2RmXd|תf")&9hx0q@:9YloNm'o;G}[i:]K(})zڑp8-W8ȚP,:%mGPO9GVT9m!OhBT6y!$5Q`t`(V=sfC\cN'/hw ͓TO芫Iި|9`^< Cs*|4'bߵ hq!O(;.h&#4|(=' 5cT|[)Pm<6>pT/KTmV?kl8HA:F-Vԑ5tq *W2;x I&g!C4kf~и_W|AYl̾/hpΫ`{PL̃\(o>2Y_~ |_q<+I&Ӟ 4UP͊ߜe@k%8{B Gd"X6iYK}mm6 yWD Iv KiRh"`}(ݨ fG>;f ؏ƽ"Iږ)r?(֛Z=q4ϬO0 2ʌǼ/_Z;+ E7%~+1ow҅5B5itrb߉F6tk,m4~NqCݣOU °~HC; WQ;M7p4h.s) C54J=rGc>tˬlJ#ZS+"Niuy v7 MRl*VF}-~E*ܞ1*.mS_ ՎjLtu.X3 tl.&gF6ؠޚuN拍6^yUt 0x{WG8lae8P: iR\fCUVeUSo{/UsDRmU3V JX Y(ADB@mļ&pYV.4˺Jfy̚Q};3JggU;~TdX𳹥)~CT $CDxkGug[Y#MZ Pbey(?СY:2G>>NNՋ( ShM%{{~DX,YZ^w#qSTY'O&=Y!#|N5Coe"6 fciM^1;|v \1&e{j,Z=$5>JLpo = k38yl$'}uCV @1sfSxL>mqghS5RAM 6 )AMkCgXc~V\eʋ~twݰS*M~/yW̙G&Jb0j"hJ66H@B0߼!p VVZJMjUUIӪGXLkXP0hӅxt1Q:;vJԐ%*U4QFoϣD -~/Ѵ(s29ќ#2&T hS38;?-mv8iupd^5\?eHG(2?Т IU4O&rY@0.& ˇH;kh6oX~o5s{*K,oXm'-Zs]6[_I[sJMZg3(j\Niڴ je:IR 5[U( 8Eh>a=*\[3~2R0`?fDxѲ',kkѽ+%umX񶆝.cjTf+eDž {mZ3(ĴT=ܚ* pզZnaj!AG9A(ITȇ)"޹<B D~/.,a(fWE_~u]'2h֤߰5!}t\eA󘻢܃/~(aU"yO=} :蘲Ml>R˔r 3Rlņ5P`R&hoTy;R`I9=3!{,6T_;T*ܨLV8bt4Po Z{U_BH jDhwmq8Y!3|ZlfaQڍNz?103PE8=J³O#4@^Ԋ5huxڰx}ۂ:zbq=H݋/za~WB_x(B/k:0s@Lj҇& /Tzh 2 u+'!#nBEҞn%C4>rMHX\sjI*nM0 Nj)zBk P{x@f a< o0f泠 g 56<#>˯bo'q&s847w`.|-V)gؔ@ePщx?}qڟ'')=ӱmLtD9ƻY֟A¹ue>y41zd۔3WFO_4z?:f擯 b~պ=y&S5;3a'Oyguw1Em}d3i M \߅+t*?j!C:;YcV?t}Δ/t2?x23s}*Y񡽖%kaNAWAП̭/JN=6eArߟ5}ѹ>{R-}hc?Ԡ4E36@ LJ^Ag~bnA z4:TAS+XX$"B4`dNid_|` MH@b(a\pslRaw ,˒kwt2}&)8f\}`e}XDwK<-'9Ez;SZf⁻k)۪=f _d y. LE-fؠٜ[ GOʏ[$aG\y ~Ȅ^@MӈN>|3~SsA)NC-&!ԄZoxw SyIBM8<\\t0r7JÁ}8۩EZ)NSpQ4km?նɅB99A&f+lz$@AԺ(ºȳXODp"g|CީN;̧^5}h+u7sArE;B#CyT#ckBѕ2)OTA[4~^C+~ŏNmcOE7bPY:SpmsMozvn.d$_Cg ЩnSx0 _SMeQ$FӤ!5z&2E\S^fs± "`BP"YY6Y_bQW6 f~;փM'hN(b96=(9{-̡~ 4^B6$ag0y۰)6M4'SȌfU Q`4œRb !s0Wc`%+ϥiDoY 3} J:TUf^"&,'S_,Wv Ȫz˒+$4xNOUN4TaWj;C,yw4In.߄SZsJ^UW&'=O+H)kfaE8A)k ӶBה )121|~4VlYMz v׿-2xgxa"Ǧ_(ܾ-((5o+(wu>T>GH}3Ŝr7"{ )of۞ oVy ˜dl"atP֋?q>9Cq ZRq֒3-)ʐ#\i3qꨗ3({~pa3yz܄Gn1Ňyg8 ůx0P5a;m4M_&&(B il/{5:YQe a,43l,t[ުBEjlA*<[z`GEd.p//N%4wMɦTL9G1n-K]+G~Σ" %iDzVţKzrLk(pX8spnL2J(؆ܰ Ђɏ޹0"iG/0z xp]WA_zcQA Jsk,; ܵ*dy%8+14VgO% S;$lrMZlli;FulrDt %zJ vW.]b=gCG)3 cFO7j|_{GO9&|*%0|^aS2̆8C9ǝkV9fwmmȗ2|,(:&oAVtPJ_InRCal܀L#Lׄy0/ p`cn8?Zؕpz#Ј?//$4@Kmp"̒sn> zcoL46]1УG- 7MU6ndʹL, n^٣iQE&>ʒ3[ ybuhH@sA⢈~@&xjwΘ"4T+з9zg %^@P)"2='gnМ_-e(p<0DT"t.7x} QX*N[KUkSqyy!x0@E6ՃX٫,4%Y0_fR-n*xnvt ; *aeg.31VSh nx@n;8jEK+E,u6 pW$c Qdr-Wgssa7ԎLx5$7X9+к9eС;dYJ"1H$J8(O.4[i)CF/R3=SUFK\6+/0/ ŐR?9!ld,mɪkTyה=^T,֚e+JR ؾ_$04eFBryHjS 7jTN^ꢰEqq~1k7JQ_d+HxȮ/46""0cヤvgAoyTYY3vY|Rv\,{r{^MKR;NS()Et+dLa@ٚ; @;>KNMvJ){grTy2o>S=%_"`GhO1y(¬F/xQ=݈a g|U7ChK AսM"ޚ?Gi7,Z˘jsb(ˬPZGog啱>&|&xձ$suIf뷉(X[g<ձ^x2(z:}98I_ak0ʰO"Hw|52;"s[:H}<-}jd1> ذQ4먀iG 6ηYmJ8i,¿s07N1Bfy -;'-+ԫC{QP,gP9oPtS6˶wpنo}qW2Phh.['nkͩ"U0-ڣT79` }nNQE4#:YjpX q/6]rr);Z?}?f ps9jzGSTU{kU*v[_4 &1E݀|B%3UӓB65IbpscC58DU^`%Oh~FׅEu'.ۂoO;%@Qs+YO#+q!y&9a'%1ŸmM{x76[IMz~T~2WN)7w*џߺrb2o1Es䕎Y"oEZ@xL_= 5~uj5:aB4g.8ZK"tP5 +2hʩޠ=x6^ozZXD/'r:dX,]Ae ׸(̈́%rEcȼaN!W]b9*ְ+oK8_f͗yR"[Ud6,kڟajOM^>[f/6c2^emVWzXZGd~CA.9^dAt 7ޣ{¨׋[<`rWݪoxL=Τ"*11{tt杒^FT,EU!PߥAs0(U֫Bo07Q 57of[^.:dZmd(L,8yW\]ZDŽZ~~p|˅_0+T7VQ.KRe">6"[RYUewܖ}<䝘 ٸ!VMX'#RD!)\kCiI0F1/{#xk TAQCeyAET61|uHSDw#4T5GYAt\#ċV柂cȂkCIP|e%{Ӷ *_} WdI -6=AĀ70,,f(6j~mkkDE͊Y9Pwn?%[l0/{-(rϵ]h`&ݦL0?:نzHGن}U .9FOԒϓڮʤ6 ZaNkE|v1bb;IV\WS:a1WMe#3z[z`I1C)> 4 `իmQ۴.) 6I\[8s ns=%UpjSc[=юn/mb^Qs. ƹ}jEC/Jyp Sy[d~|v-[C"%h4aǼ/o;_tXrZmo2 >hw6;$i|& ΏSb6>uطQ|'E؄^$䧶 G KTr x'q0*KMU=mI=gꘖz#ov11ю~(ړQʊF~ PLm#p,'u@UGDMV"22E `##$ sv"XRHsܝ9U(p܁)cߴ YUwߍ״[ TBzeC1Sj-„~QŮ:9C~ Q Ury"0ố16D~{ewCu3GfQmmâ'#0S"y,ߋiLa.M Z{g#\kߠ=AJa|d ǤGQq:𾑃nZ.@*Fgqt}p@!&Eƛ Ǐ{P4ٔ?܅] X[A DqOl[{ |ӽFoJ b.[ۅylb> H@ٯZ G~;T~s 4)P>,\b}^K/ZW-$wikEjx< "5KE=EikN]D DѺ׏\Ir,ڛ$ؐ"E/>KNA)=HYz*|K(eYKH*&Mn8b{;o+Ga gJ0a36˩D*Z߱?t/'N<Lp Qb8MZc LbU¾ZV˪2,MT#NU=?=ǓtO2e\),-1saQ$fLh]kF2>R̯/ٓSK}(C y Ԡ_FakqerTmk)5 TV~@שc;Rd] QVmkժki9JL:T'ȇ3]׮Vu Qn?5!𾚊m^W4+9BrVgə>1YhpYð=@ Ž3҂,7J[QU\A|đG \Y8)xH# 'xńƼ "ߎg Z5K,ɧQ;/Cr}UA6pȷD]NH U@B UOuO&" $ ~f osao&, *&T>21_XxͧS4KGEWb%j:62 JZ<15mz,St@݇[caq8`ͨb^p8[^ 1%.flPM|+&s7 3:w昀,}'1ܸՍI)'#ѓ8&G!AutN&'p\?VU0O,YW`b= j$v}{UMi51xk<m>G@v (=ñT35/` {3F5Nj5&T(ʅ&i..')T6fZEtHhmߏ2NOc=j; Vsɠ[o q ,"h6ig:03#(lZZ ա?L# ܘ[|[v&a-IDU;C/ZY[bg,夬C1:C &ͳIA\eSA,?M"[~6V>q<|{mѴ? P0|hӱB?fj['~1 ("A4}RJl"Dh땲hqK|©Ron!I8oJl=r#ynž+3JYDK{6چ7m&aeh]{~֪ț3"8YhoHgQ=hw*ɻ"XR~Us+~MXxP ؑ,C+ONWU op"~2;Zd8N]Z__ [)Xu|R8Z|?Iw aec HN+ۛ: H Ov m\3Jwa٨P׿\׻Md&2mϧ\\6*c0rǠ`P!iVQP9C/ T{koU Amô9#yEH*+OڈIRfXc]/aL0ŧuCd\G>k3gd|:v6M&X6ȧsO|gYC͚N}޴aՅJ5!2s~4SrI"}2Fi)oU6ZK(_~Vo+ůC"st2wE2M#)t^4[]o(snݡ[H*1JCї*BӗDTmànt7\Z-),ؤp8u5SHklKziMָ~q+uEtxI_mrOXl-K%#%W]<`.5w mgR>%TA՛)=NEB&x윎7<PDKIK,GUe*&|fP0EM0i>dx| ~mD~rO.rx%Rh) G$R;3"MJ#/dGa 6 󇩣Q,~@Z1ξ&Z<~:E$?mPm{] tMn)3sJ WOP );!d7$Zт$[aUr H@yK0xo4WQ|TDqW$GHa΅o++JW]Ƈ<1L!5&"*tx;iju\UْI•6PD:ts61ȅɉRt;xV܏mÎTQK.9ց& ؠɞu |e_L| ȝ6Iv;GK1(|X#r΄f 5̫ @5\Gi* =(NjS%ܹ($UaII6boP,y sZVYȖki񥢼^-M㛁Ar4#FlZ~UgDϰk)[yѣamdhk1\Vy*B(m07Rm.1W1` lEzIcM:&%DAT_R osɖΖ,ʭV4YHFƐ'NkQS}*S2St-MΎDS/4`J YMz~]r J9 kǹ73=*c˦m@"_)%а݀* Ok׾:KUyj֧uVٚ? Uo{8u~ϱlTzd}ӹf 6ZEa:5rbaiPY;Kua(f6͊|k#NMxnOJEtSX.ߟ۩䣍%x!Ax0t9^[ 5Lk>Q/藗dua|AnɂUȂvu4Y=ĭ_T^^ +qf;ceD70`;Y\ RU)Nɩ&S\%\b9'w0`ni1xsZ6- 'DGKOp8z{>i#>>gAzagؒ^& 5^>&&q,I:i# " " !'*m0OҔ[7f'kP jբ? 3"8r{̭zs,JZ{ׇ-)z:H9w?߉t֗*Ż$PGa@2,%"ra mO$d3j~ݻC ?x@/:"c6oa_cö:rN&\ ^DܙFiJQ…ъ*^ DvG7LI/,0 b)4Wnn 2hV̝d#],ݠb]*o{`3u]R?J|m5? Srk6oY_CvE*fҦmu/B,<Ԗy瑭} |kv_G }|w-+ &tzڄ# 7ՖSOCrRq<%5䴊 _:-"-{fT"9p R)dӊ rHD\b\_PE"2fHP?1WPѻf:=Řô1E[ L 1V0JL2߯`%"m\ӱdo.†ZӜ|~oS.eqdHVEm<+tt*caP;)7H:fO4۬Y>> NYd#&*wƝbo'O1;P ssj>ǺOT4ʭv%΍ 7-V_xmZQ$זgڕCdWTUWC]>[E,KÙJ%Ba>`l1 _wrA04+: 8Z˴Wc "?s:_0cV>>T$Ҿ>GFfͤkDLdt.)m!f!|`恻]ӴGo $}jUsNE#+ۊz/&`thڦՁ#?͸;GnuLMw$(h$[}/^tߺ{ƅ;0JBobr9W0ҟ&MwO)MDM̲؏+g҄$)p/KF\m d٩c.EQ̵ Gݠ2Tfhp^pcf>v2"0S ^,>#BF[ٙxJ) `?2=أ_0TJUzBO,hgcaa^6%-H0Wk'x+:*fmt܂6m$niٸ 25Pc2@Y3jOj,Ȭ!G ֈgJ2z g( aFЁDԊ,s.8ڋ Eu&纽VzW57h( F&jMR e- a/¬(VH2%$^{>z/V<1NqkX:ErwNy =&bNFnGԇ_xK.l91 N|qԼ$PN:턡 j>$xNhs1vT^61!~d9i:R@`S{!CĢ4`E2 XDŽ-w򘎑 T%x~3zMUmd&i 9WMBت5^sw8>l<.ieFW >{eQ`<&Qa+VE*ڊ*ȇseК6^UEX. ZiLJ^vf\ aKlBP&SԘxd~8Y I|Bco0 #{]aF 0N5O[qձA1EQÓYXIaٶA_t4(B0ǬG?@6R&,Y!dYRC480ACh[_s׆j=vw?O"~m1?Ƴ./ {PeV Gz^4\qdW̟R/`60`jo)Np2ZsC1ݼ Q耹B",̶i,+!WE-*Nx[bH;4e,6>ΕoliCS1OKLp'^Dc+_8ML0oqq{f-`' 4>=9ܯkH F/nRLZ eϕe +|."қaAPzsnݘOhRxT06:6u~[OLOFFfړyoT͛c@+Epl>)q_'8Jam:Ʒ:Q'hOncQ>Dlm,Sp{gVPm;kuv6e=TG$$o]:NSvG[xIrt>̕mCoРR-9썙d;}=BֆԶ5F=J 'Z쐧!"2J(F76kabFimV%3s)FsM_MVq5p܈E<қ-ίlJ24[}H>o= aCG.Q%y3J/o7 JfW۶FΰG͸HK3i)j.-E5UnCswו#4UV]O_2tl4=oZ~Glj%Z@E41ߤkTx>)zAR9 ݣe'Oon\c$ 4Y+4{g$K9~P>.hG:-?V!mBl3\̢~e-{jV?A{ _jKc:2͑wé<8 HM 1Ґ3Icc:D]9-6O FtQy8x:g 5@[vrH9߆]{hܴcMB4xNϽUt<~QuJ~=BnB"G;O&τX'ܖ qF٬OoהId4Jw5=,շ Y+Nkzx0;ʳ(HЩY=J:B-JmAp(I 3,Dw0a)0ۣl!uX&mkVp7Z|eؗLآ 1XO[-EbZQ9*SafۭF3w]V]+v^󰝽gq$Fzp)5uEKxbf"@|AJb Uak 2qj4 b~?F]zyLWT;Q'ky9JxjwoYYPCvMkٰ[, {d+␄II"iTF3kf[?ɑU|H;ro&N:d~U@d /#f( +x|#LՅ,:>}b5Z\P߽Uʍe`idCf8~_^K8Ɋe)ͲJ.)TJFKz( ЋM1V>J2 F. z6U=^kˡoOU| c7^%>/v$is & p,/YJrmeُ0%\8#NI_5۷-<֬/:rvfS&(Ƨ {{a4dH`%fՆEC"G:E- V=n(:+ |.[R>yP>  \=Zߟ1h}9זzcgon5 N!0/; a6(xz[Xq]06 8 {߁x)v 2N7ߴSȽDK( m$fN^ mt䴰1"'l;oRV=Υsд7z┘ sqMT۟{J-訠h[֖2*o_ڻ_=΋,e"i|2_5{3p9X"޽ |ɦ:oNWCOtsF=a>}n{7{1.DLs*yBWTP~k'8lRʠtىSsCL:қSw!e?_*0[+W_5qsRX,I}}&S:xS>2v]oBՆLY0BVGPx^;iɕ77%O;cߜ*c،UUQSï-XJtn>4_~OyL"PI6H4RI|^ +֑9)xMH:j|>?g:(<6w[ڵ_=z,:Dp~)ՏCްAꞞ01DUư`EQкK&,kWQ?:U'TM {ʰK.Ϊ_UުTI C~u"|4|qRX41*2;1GmCRs6Q%~M]k ~+..0!i9~ipDe~4A3FT\w7Ey 4 u| FN[:1-]YɓwdU^:yc<T?:W#ZB|bxiWs.0;Xy`.IB_]@ybWqX.2J҈%b+.o@WMH- NSfi r +Sʔ#sl*_$͟Q!; U|e`8[a)7 ?ZԡÐ+ʘ~Ca.,č<=eXkCssf/I)J#c rrmFDF"xXa݅ݤ!|k3nBUN%ch@0-{kp@z6Z" nxpPQu"&#wDꍠc66>y(cSd3vN˛Tf^(HkC[ASxmxm}~W }>nGhG?a zv=f+1˟Y$=Ҿ^%7k"`1נZCos4i-#ZG(M+ov!ܱ9$8&'[ЮKDۧR6\?2 JELck:!gh͉y!⼜l$:[~ Q Y˚F NFT®[FA99(uӱO\`[3ߤU}}-:*ns).sLҗ5Gf8<ݶ79lՈg˟.WR~j}A8Ra.(yNtϼ>^BsrYf+a9IiȭB|$Yگps6Rfh-ymܕeh9jq`.[NP^=Fd<$0Fz@ ahBuN1\mGpl9,<"> c j6ۚ_AK9kwX.k.X|+ry$ZSP}T'<0!K@/`*Q ÀO? $$~7zգz,٧o]wyQE/˽2ce41x෬eQ6͋Lzj4 Lf?l]IA6hLeWa!bO` /,s^ڦ^_%I`C|;zqow 煌ah~z hSGt8+ ӟ;%6p*`X$~ EJ3Z0O`|sV6[o[yn\kG}o0ݠpp6gL n[WdSȥrLտ1qaflY'Tѩdk潙MA=z^J8f엎Y35T]*ٝAtPq0^O7,}]\ 8p7{'ϒHO_[*_/ C o֐o7 PƝ. v,!cS[bt/))ELG %"JiV&8Oh̡|8!%A-!(g[xv! qx0V;~fLGPKh 7[2u)')'C'NX[+\A*?q<4Z\^B"Y+=*v.r0ThZPafy>^Byă=itJF5: k֖͂37sv~! ][i9 BS).f3ڕ',fzrvAƣyX%nx:&\~CѪv~6.4=F?>7YP{!_#* %.a~<͓ >gy #* K>_̼-#wӷtb\}qXЮmF$t]ҪuǮr7ېYܓhf-COYej9n D6 =<83`4.d |w4m7ć3»QriϘl^B{Mc3oBThB^93)гBIfNТN[$RS]qHI]̗(BU[Kw2r,71ɯ,c{Ťk0+ǗW͎/mɝ{Ǘmd6?"&@äv{Fi|ͼ߹z_`eq^嗯Dq7 C i$.q m˽raґ7/V_+˱}mzMe/#G}?BX3C'hJԶ.P s6 NӉW6n(w<7}(cXrZoR+7,+0w,sX:VI Hٌ!~jC<kMf;3n VwWޔd&}?𰹰[Lۋltˉ$;QlHfJINӬ]!v r܀!) H@FzzRo6\$2VMX.ȟFB8y &oV9͜y S''bp‘~rΎNDńM I !xd"Xe 锢_axnvW?#t #_Qݫe#ZƃgtO?$6>n!6~(żÆgy0?F =-ݐoOA(}s~8((ڇ`($Oiyb4C,ʌ2#g[[:}^NG,@&wq ?UlM]|1ڥ"?TAM,6s{١FAzl~]e]dyg&Ni-, %@\.O3B3K hk7(f؟m |qPE|°i-yf\+ٻ/+_3=t* S ZGK +:د( Gse^D]N[hzfTNT\\fx'4 !DwTc,wv3W\^Dar;S 7S.<ܮNނn]\UwJ3l؃ȼVEps9[[At"A-3gή }3ŊfӏRW$r$CVGHrbd^I~A`ZE?EܾMn24  /QAji9_Z'#SљyFv5—?ǿVNdԑ. DŽg s0_Jw,ݩX;Y [%þr/+fGU~b/^ݽaNz2G)On3ps]AY#gܝ Ra^Fp0o-BVTo9.5n#[gr)+ /:E&-OfKs|Zrʍ\kvS'&}6xB1l1|1gobw/2Y(j %ċ2N#xaB%GE+RcZ\V00R}&ゅ4.#iP Fk+3x(E\a |˫:*,^6$zed /̷ZҹdNfiBchk fjz/ږCɦZ;F2Pԭۙ ri/m Hd7hӹZoCo\P߭f/|P>|t7Hf'Qg*:42Cp<rϧ!hBElr!WGyJĩCD ՠk~; 5!R䑧k#5{e@[>ͭs͇qw1 4a7dnr<9elH'cEVϖh{N"aS>3a9=E[h' Mð `t`0n%#!vsylv ㋟lbV_15}U<=wʡRnNN;Hҋ<3Ƌ?ڷ5[F}ͺpֆ.fH򚈭.SS7U߳WӔm O#2Ѷ&RIJ0Y=i5XTP?%n &PN:/m]f+>2#ZD䀫eI5 S<=$nhe[*r ꕡ[afssJo׌I( 3fd8cY4n>K`8&PFq+3C,K.ڬ|ֽ5FY_Sژ ţYϜcm䌳t%k -l; p*Yr+۟4LᘔY$p`U¹)J٫(o@Lu3NϒSm֦]%ROW\9so."wP2~/ {sC2M" k2ȳ\#h7l ֖+wg9IuoB ,N{$*:-+'DkkKߊJxVGbT EX X,?DwShJޓk 4t!8T4F</NPˌ21Ų7u|RI7ͭen٨-F+YiKX5<0?8f<>H3]ӟ*t^NhC͇<r񵇞 7M6,i3mYuUq2JKQ}؋dS4쾏H% cJ9yP.2saJ/nf` tTT8Esei{x5Hj'Z:EL4;~?=܆W3ra$$s QjQ/tMUl5;0@B!-qg]Xzl~fcm7hB^|F[4[ԛ 7UP32 9AڵYe"УTevxGOIQa5tV扌GRzI .yS+ 4<R Pí]ښ\k֮nY]TKz.zTs15:"5>|\ERKD643 w rlBY^$C4JPý+>b`QF9iֻ7kG<^@w@Ϧ uꢼy|o6'Wƴ!7KrbJ}YhU`1/i;ovJ88 d~6efDCG r -zt6q'p2}Bti[\ Uah֜ͶxD0KZԶMDU /2]<&,I'* Ul ֊0gnIJF(IoQ1/-/5΢lI)ĪF~d:;Bl1MuJHv%C+_YfR3KېB)FZ*X˓cFbKkd?h 4 7}υi@gp:Ua'$Ȗ^,Xr8b"']:wv_BkAِ-{!H5-׷`Z+vG]$Wу?97^5y ^ 0Bؕs{KI>T Fx[/U(&{#vp<:6ɗ2gnq+ Ә1'e] ζy+x&6?eBmcm^p~¡pk!2.Hb6?O1qU"_0#Y.247Ip a@?)Ug9"#yAT|81^{׶,#DU=XsrUdӫmLt6JF6(ߤ<`fPͣQT)'A' Fx{*.Gͩv<2tBW* <"lsK)&Uĉěq\# I6T.'e΢19y<];F[:C24a)Tafo6ڠטG_{N>NXHV[S]u3c"˒9`g^ɉgLNZ/MM9_2.%~؞znK}$ٜ'S<ѹ3')%KX8xhd5‹˫a~>S)֚ψP@;dAa{6mm^8PjP0*G3ɖ Ŗ;-|HU6TP'vVh;UzF]=Idʕׁ^y**Xλ/VFeYiX$lWpXb)^~6ǿ?ފr^@)o nZy_Y8f jZ_!{иP Al8  GdHn/RXw51oϫe\;ty̜J6RG[_2brӀz5R;ҝj jT,,&g/}h:/ђ͚͇ %o~^h.:Oty^L*nʁ ރĵWzfawƵI ћ4ܵ,3ONU%cWd\J|2[g[}t໘&WJ] @8Vۅ]n͛OL;V%%r,]}.Gz*X}M SRyG+qf6k{9@TD\S ޭ|9uҶ^d;+m/yi+h\INWN()O&6K2SL?9W^F%7&~g |gʛiG~'KjpO,$5*>0h :t4XEO1c5Uy' T-fVv.G\D_pS-ɇ0A)N;#T˴h@@9Dzض|qK@2B~"r31.[NӘG}o@X} :\BWӣH==.ÚOc(<ݠRGWE] he{$z fPShA봞畕6SnfW\_ޠ0v50Zf=?Z>,rBLEM=M"ܕjYCw6R, ^?+}u\Pbz3-UKP^كݔ x"L>Lj|P@ڻE^Dϳ][pVhWY˓Qa3ݔqZ(ck\EvHUrV|qqjhJW7?72 ^ֈs=m>sԉeB4BBĬ=.8exs=y;[kfOHr̊5/8W2}5]o.kpAa֌*)ʛM>̽qU8iP}:ro<(l[Z^PA, 0n[X`^5rB_{1*0`R ^K+v#(A=D\g[, h/G_C 3lA7"_(# 2䒰Ye\<4XB,δڅS2lv;$՛gd5$AٗS$r,8L.f N01vEPMG3S˜Mt÷S jbƾهC[N2`W"ZNS7mm4X9̧W>_yimaVID ıopSoCYHd" ԄeL=pK+dιzH\Ui[ɏ:=06y3 ,Ml8L5\6$J\X;Na ߜLWu?B,9 yYfTk NۨI-j]񄉢 |dK] hsܓ+]Ŷhׄi!e2*/GUƁHZPǾyz윞4diGYgscX.K)}e^ Tfhqe? lT*s"Ic[-ͥvEIT1bD-ϒKX&N=h<mt*`qdq}h9J-a22j7(*ֽP),r}Kf`&J85Uz!΁4SR|S0^/\?BoM 9Bz㼐ă&F]n4v5}Tkm hƦ^JC*D w3P_2WDL^ԹH'eMW6 ^|~t+_mϲП /P>GML&ev!eLca%UL{<8މ:h Z!ꛛ]D%O3E=nSsjY%OyƗa3 ĨLd 츮9vdZ#csӂ~I}[\bA#P 7WW,{B^aayx$Jj ھU e?#uI+kN+%f],(H* md*th,&9=9Toflǚ"6Q?caA9lCeEO{K# cl+m/qf{`2g=w_ ~j r7qc!m[$ ,8c*ϽB6|8afH Mpn]V +(7ˌH%-O %eKF' *\4:ДnSGv_P Mtk;wL5MJb΁ظ#rhTC^F(f\ILG3ʬ=5,4QpnqC*S,QDSǶVEGuLpSba+4* %<PH}BN |W)˔wrI, UL5)^ ?1X+#f^&s,UޟWk&EI rD;Ŏ т3買5ĉa1Մ6MommmIҮR,^³dpxohbnQ ~nǹb\ʢ!_IŔ F9&0#Il% $1ͱ$rPrke~N/5'7䶷,/NC网sa0Z1BM9>N+ g˫&j!;x~P)\o/׻;)}4FW7@b~䬦挴]6^k SnAL(>=GwB۝vwꖷƹzb2mVilY9>9uH3L"7.ngyR#dSM+jOK-YkC9 kowV*LfKu:+Ȇ#qtd/I27 'k6$P/TGTP0V84c%T=P|fdeCZS42F/n jA7F>) 27/m6[c6X*EXڡkZ=S[J{+IpyI<A?zpd5OL3'9*e :pM5M}T@kMF},ځ^~ &?~%UAt?fY++O>wgP>9WywqxOb &nΊO! %_hXV`G:>3/LUO>bH͸L/Pc8ed]L)T%Tԟv}2`j/+Yf?W K` )G_:r"]*8EBb7捠0Gubd ;ACP/]i?b~uykv`;u|I]j]),tff " ʇ ѻ!̭ۭ~Gq wZjhS<4T*x!3 dsf`v8wpc&ls5|O M,2a0hQDs'W6ڃ馮x*)C這 m4R*];6;&M}=QҸ7hW~,h{ DKTM7SݮD`Gƛo/:hG7$kàE}TWУ%>:rLw6!17̤fA-)cmKR1ï"DW]R$ۧo~B3c]t4KE’Zs L@~i/-̻x /gQ(е#&& ǁ=m"pZ|k(S) Nx;8~s1&`|a wA ry04A&%[Ek KXkiη+5S:K*q;vaM%eZ|sɈP`cv)E|jLZs%tVio.ӮowNvy˚)qh h*G&)deYͤf'&)$DH7&h[kZ䗵}۫5dL|,Aߋ0th~N*54TS//vLyРY- {LuF:q08 P,+8{kk8?Q Mu‡>!y2M֟D@ wemPSի,kUoGQj߹o;Qp˰hpֺ nObya~ɐDDAcFTO11e=~j7}?hUQ|qbev| [Fbj5/  vbTX9(?‘P=eA VQI$U4yAG{r˂>?bC/z{sKP9#ᎂWUT,-obòւAt,Kˠ/Zf c)y:9*+6}:Y{gMԼ!]4ͺ;eY,[Onw*aF{OtwɊyNA=">hFc nEGEޒ͗\@VͷЮ`jcF >ϪwfAzL bQyp~*Yg'`Zk2٘VXJ-Dxݾ$Ckjskyl鞷&hǔ=nƓ@V26s$ C4ܶ|v|xe[qЎn;cJg pxE taoi,ؾ=M7Ȋۻ\ z`@wcl2K^0.ҤESY8A2nMlqԝwBso']1D ]"Qטٝ9EŮ1{df0IV{!7js7oWd3W o_; |}Gs\ 3ݞ0"$nYB#(,- wwZx.:aB~tRª52;:{У OUόGLwI V%C~;30/SPmȢrXޟQ@_h؂"}ŗ<. 4}ab >~ޚ?e,WK)@ꆋ` 0uKor"N|xU` _t?vXT|CL|ۼ:'l9֯K!n6US~cSzX6Yp_7mwwǃuO(3o ?L٭丰TpA#?v B-Le*s8dUˑX7q"l_U&0<ڃ% j\甯}f`ZӺ}׃䈨*4dGkQ0 i<sW]l-$\>QuAS_$;ch[!e=~%'GSA}qkS<+.1} [!<5%)`kXl9Apw "N >2U|YޞrCd0Ş̤>8F`|;~Q?MW%N{۶B)4T4xp2V*Ϗ]<{eDVQ.ɵ?WTˌ^32 Z@Ky}|f|40WiݯWit"kSOɪ:kw/5oاZH^ʗ LɈfv-h̨5k<eň\)AJp2eپZvJ7Mj=U)CXPS{P+mptozRg̉2,ݩ(g6_`9xRssz!ٵ@7_0WS'\cbD& 2jHw&Х~w ^i&JNö͍vU-z>}9Cn*w-)q4\fQHgT=e'Cԍ"Kf' -IMXsxyTo]R}aUPӂlsڻ_'p'7ʀ7!M=$5lȡ\Gu3Tu; %*#-{?ωx@SQ?'^Ba(9m._r==k/xɜv3I2?J88/ljVjҍOgV=F `l/MIY亼8AO{ b4h U%nkE,񣳐gmŅF{f{ݗeM22+Gfyp`K%K;id7òd16C_ 3~D0C3Mkhb _D>%aa]Y2(R"RMޓAmT?Pqye]e>Ã.8F t֫XɊ2jGnf9Yz\ɸۡk;2@,X'cIϾSL.sOV5clp(_c:Mm/]^Ze2-73#i/w~~'cY%9u^Ludud?ub;0F6r"4{ǣQ}a8Y%Pg0Y}L7Ū rK9Gra 6tF) q v8Gfl"ҿ5sg6ɪA? }*\ՂEhߡ`EP,``h˧V)DdE[`3lS,:#Ar1z ;svJ4 bʃO[k$OIdJZy%m'tӱԖ/BP5F}%wogp{'ZL0jl2:/SE'rѯ,$S6NuCa/'Su#CUcKdjl*s*k8z ak[s4_ѣ3~C&RV\:ʶXV8|zoE)l@M7+ry*1qd_pJ^҆3D~e,ȧ+3{HuY7uŞr$6ɧBMN,7X\By'i-^L1nO4<LhZͺ;g>pWWwV 7nQp5\O;_׏.d ۷heQNfV&os]ӹ|١䜚2z/Y/ WtSݟF i$l;Z לDQhr}#ܓBfMټeɵg7jlqiG$Gll+SO|fA?"hܜ7<@,1mfQUR =nia6:SEZzT4*9ܢ-5Ch kjT!c-Ld/ٷ-u~C3 S@D]jYX.UO飣-(_0󵸃mHB UꠎM}kAʲg>lBZлUjڧlS3@k.gMo2 q џO R)-ղ3eTˆ.wd8 Ȝ: 9EYYD  1 nAtLBM5,#ccN**R\&d:MX% K-ٍXix^{]4VI/2 =&2$:J2 <"BJ a+VPF5ՋeD!~q`h 2w;UUoKٚqƯe^׏]5)Ex;Be<9ɷnrj:B[cxoȔ˄RP7)FWč%XѵWo]։EЂv, eNbSzE̊T[<%sq<Wm5O՘#7b\fC-|'A_`Lssk B ""Ճ2݂IRէz]҆ٔx<;/`$՘̚!GPVy`٤SimԭdΌu8JݼyPPFN3TRT?fUD-џ\_,Ѡ[FMљ|Sh3g|(gSȗq‰&YqCHLr;'bÌK w'\"(sMkr eBc9g&NolO%MO6D |m۔ܟtt9H(mF5u^)+ph" gt;8~0c=jfͽf0 vQG.@! c{K*yҜ u{\擏q\^L7.K_&еFȠk-4(VWH "&46nzk<v)2c1ֲy 1"R/3ԡlmܺcMtZa8?OVjXIqJRt[K$[]\nh 2V<&} mq}g~g=6nef 6NAsAT͊q[#';d3eL ˼dzy*Xt* /5>ִ!v]̅vTM,qKh@/s;oB{tyw܁h6|PX&K#b*G-Ryg Oܑ7 Y;*(4ޑ0z!m}G 3x>FavHu @i T dׇU}1Rg$[^ +ͳ8T^hVc#.js)O;ڭ)L$f.scdN.U%%-/L-t'YGz[NQi&sLtz3[!f5}0,w!aIz|kCȿ{,\fk|rYy v&|<̢[,;U݁yߝy ;iZ3LSn1K}VrONcZ˯<A!}(n/!F6y֫u{i%TWo#;Z^U!dF <&r뵾Y~v tryj-=ȍ/ɫ,(3O) Dˋ5ھ+9ۨb_de٦ b;sms8vXKkzkk׆ih^R0 hj^/!i&k&Dov=skV,-~jdbCEZQTK-Fֶ9MRw\%U{^}xI("뜖TV- POb['٪R:x8PF{YwimEwsk o86s}=*eR^CͰBykо[69*zuej#~23兽Ws9V$K|@!_"PYF>e&AG!>ga~ߺSXΖ5SS'J.ޝ- ʱ V_O#._?Z^,B[~+w#C }xXcT솠qS庴7COYщi١=U1 8tR;ƪ "b}vh͞,Ԁ怕SFŒuxwRt燧,"bpnG։rݝmM OU4Ωs`,YIs$}Ԋ$f;N}zl0?eK)s!TюTTϷ>_U42iO.&&,./6ų'pw2F&]u5CxJ>دI+TLɼ\fI$= 혏z_a >PMՏ}mì1h܍f>)o:pr`oލg*.k *I:->iUιHWF[] PHrޘ)DߺmBC|M\{/xj;enB,:ִ;WtGktx 9~M]g(V]d?}t83kZ'~nr9[2'Jy͈c&`:C rw"z} 6| uRGjutoԺ/#Ea3 $3g+%LfZg>S L-4 %U4@S|o۪;y~NNQJ'^i\#rz/.svCX*aN_ oWoնQ>ɜjoiY" 4< ;A  e~7&<𸝍@oQq"!i'CoQ~󵳷HWr(OxߝN,dm)g죜q9KP"x <3G;x"g)y4_`et<8G}/5=VU]݉24Atcϕ*+E6&܂2;oP+q.-~&K֖x2 msMxBQxuO_-߷DdQ%zf*'U(+dW6Q̔`VԢTOs:V֞-T/m ¼RkhEْnCcFu ZOqu91A3v5W= m r? $޳ݯMݔՖ~X9*]1O~vQ~|" l{L%e&ML6uck;~֏"uή÷+bQBqBPcm\5|֧nP܊>P\KP6koRxit'dc:f6=)kt-~-s7썔u;]gܠ][._V{pfCQԙ SՄ6Z3Ts(t K=k7x[ s-`B1PZ=Fkw655n=NCӷ0ɦm)zM. weXpYّl P^Hmr޾ZMmX̶fjEy>Cco C`NpA4ę.m!c:ǰh^C*w]P+leCެ'ov%ƦZ_EjMtQ 4 CPl.NHC 2Kp_ ?Mw4S@ͥ0 eS!yvdž SH5?o&YP[Q95:|]sӊtK]?ikqfi6MBAC0!ڛv8Jl3cAGE.|>Y"]oz3Un`{ ә_ޕx|>OH(9+gz:yRDLup[Ma,\;[DF2/hNn4v((0bZOy! ' :ƇdÎb@N[mrYh4Pj~o'wV: (rf8Ra%z./: \qG-fPM?C5Д"KZRof͌z>"t™g5K|Eg ܼJV]+|B-hVjlUpv"ɢǿfS/fϫ|. AZKJki(,pP.5]vZ*]O)BlI 藽M3-O=4cc.UI ]g"]J$~5LMA Uy^LLquޟ[2m Z/ #y, g=oR ,(2IrkWI'”5ON46}|ݾȋLCb^(([uXb\R^[iy#A($l,r=/f}V]>UѤ } NqH(n|cg]a2 aA/hWgsgޛMFdҩf75zM62CB%M$53?Y'ݚL쇝_BҖ/N-ԦNe zoylzd_6P|Y:mA-܎L'ci CشF uvce6g#fT&vp+̮]J"HRl4uzmٙgTf]cmüO*Z ş))[P".Tu/Q}ʃx*nvo!%NU&/RO zjg;LWBthY|5}}.7j~Dҝlּ=^,W[9kaQ(J"p^y0 2́{ K ԨpK! %AN\-$ J&.-s28ڼYv󅷟,tr"{M:6[^u=<!Ϸ6V${F4˹3 PKC=P8OAy/6H9F^- E=0t*crY!c^2ĽӸ~E2ߋnCK#/j꤮,ľBǾEɣ?u \2_sMv5ӑ *J5SuGʯIΕJjH;K 5lI1br͜x<@B@J %fFf Ou2y+WzmLmͻ/iPkW6VIfŐ%iU)YgDݺ!S ī Q,VX(J\̄"A9w`a'adaf<6lHkUHWw^ _Y\g~u֣?}iK;, @eW?@<.yޡWK\rOeWZҷAUe\T%_ % 0Tձ,l ^ߌȫnudolIR;})p5L\ʮVXrR+hjfN]v%293`?d2e8A1BVL XQT`EJ:/Ʒ/9WꑈWs.߸E'S/k>$ 2R0gRK}QC9}tY1QJK[^P0#[2.ڇ KA5NjquCPb#mNkd (sLS )ү52ցgok,Ksu<3REA: HۤL,Ú|ݙËlÃJa94'Dy@(#ܨ9CS =ͬ Akyu TSba狻%)v|^YEZa23'4sߙys2s>A%T=gGWcEюUhd OMl:8m0F ^/}% e@=FOʡoy6 \rē\44h2(|d.p?r7PlWu5Դ?;dX6VCZ6s3EbIMt^3Ɂ61KRu> ,r`cƻxT2y`9PbMֽ5{(B36Kr[(PM{c #Y<` ʙs/H;#mTޙϞw~(E@MK;[GRanFWb=Vb@s|K1詵ZV8U sީ7qMH_{ɤgg|x\(҃߇~3ۻxs~nj͍#} jt"uPΛ7ydf.*t|\'+fa[Y_ 9,Y^ѐ*< u3wź(0ŝ, L΋)k/Wԣjw%#>e9retETM//0JŶy-_?v̜M9c,:oVjzy4Ux㻾|Q7[5#g{Ƌ< (bDM~׉ȑG<'y>-:|>?68]iH}`yl7eB Jsr3ff#vrz:Yz4bW G!K7BEΛFʥt z۩̴) r3\5WwfX&P2;onp8daȏr'ENj;(WꭩoYG 6AM) -ä k])BHdus2O󣕩u34>„u{[q{ڡA,]X3_KTYCBv\)t?or"061ݕKri"1=}t*2(@}chy d:7rv6z+}U$/: ä3ipГ9=?a'n@~w[NsL1GdENFG݆+dk,埄2͎ל&BwUkûLсǎ],\Pۂgq?lcef?BW &z_}PZ \Jr;%{%2Pߊ?{[mENēL+sy~`Z7z`P2ʼy!.ɑ)*(=EKy. )P"Te̓]\'+Uѯ(WCuv{IGI%Gu}+FFz,t[eCt6cG1KGmuy uuAv=t4p|ft(,ȟ"3y5W2TUD?b,cr hbuyfYdl9$%&Sq5*r)66 ]Xzv/:Et쉱رCK @*tz]a[Yg&xQbIp=G΂΁nf CRBL`Sjɣ^2|hJ"})K`chLʨ&Wg뼳Gʈ6h|x&:v"xK/F}0y.JSnr22st(FzpЭD~1.ٚS;|SڮEzQ+ӏs1=>uFOePlVv/Fd39nOA}/lldS۠$t:g}&4-B^#|2=ӓ7F\H\1v{] EĚO9Y{t5όT ~^ Zh-m%(lWOz MaיGob4.8G]  ͪU񽤄3)E6}^~ÖN XIP6TU(9Hdـۀ0ʨe͙ȖuAOdz󐎱tK M;> cx/'L(4DQ0Ϭ'dY\0iw•H!gPr"Rzj[ececYrLmSfZE2|V͡|q!se=Bp2h1F3 _,UXQ,\'hwV\l`ZOMBŧ̔J.iVVT-$uV?AI aj?y nL]-(W%ғj94@町y[SV;NR 4}BSZЎ6n9"gfZiscRV*hERWL_T]:ե-rN(M!6PLK\nQ'x.0B R/pZVZL l@Iz@EK W]֒Hb9 `D/j?Lݙ,e/2 7I3%[HK\[ǯxZuDGBD'z;kP$:- x=L*wMWSTׯu@'ժPrWm1$GHmm9Q9Ej4߬RKoTJ 쪎&-Ζȣ%ds\-b!*ƱJrT8i\l-?2[PIV\䫜q 3TƯg Ae6UBLǁ԰3|\ AWNnRl%4Īsݫ76,'DH Ԓ;r a Fy%`.F*`4s]KѮ]qHad[@?~9JS7Fa1.Li:V'fB|t"F! $~6_B /Wpq[[כYwC&:qӣ+`iL6hɄͤ}ӫnIpmT &[>.]ˏ*k֑~p|6S\jwoE}4>jiB|Ôs5hjHhK6JoEJᖛ2۳(DS҆OF72qݼn[`y=E˚ SXٝG6_uK5V2D s َh?ҫH7Dޖ|仏2p&xr;w:YnP&BZp!:p %ï[Π:}6Ö7H{q|2i;,Y;0kbjj^_PFR~+)+w'yN`]B]*21)f )rA^qdsᐥ-/Y2ţ5A}(%)̇>?eYג !iW=fm9XvTE7BfoOd~Wc2ÒqړfB²hnry:TP*5vt) hg7~GGn=+줮춺F\:>:4M[cuw82UBҡrEءF|AM+9^`S(~J@$ ϒoyûqZK*N;~lu:yPaG~Zu{6MV'G &,]Ytޮs;yg˷'ܸzQ%KOy>oeӌBSpDittkr?]QsݒR+4/+hȇps) 3nu҅9/>lb>vkm*Lkv'<4;ҏuf%O/rmwzlmgLj~ҽ )ImT/66&ΫlIfl2t\όxiN7^LMP_Ǟˋɛt0˛g$Ӑ]C8~5K׃9][]n?U.Kx=y lujHw\6>C)kol%vÆJ*7`_՗ߐ=@<%}ޔen#Fow.sgAjETXs^1MlAC0Tmdac,[u.Lb*gv|knAUf]%Ee:֭wͭؓkr3ǯ9rmͶ㡠[-"{%&82(-?;B7VޏTBW5)V7 ϸ_]bjibtg:.ВgJKow 5T,DSY~Omx hEMO<#°.A=}"BW{ؠFc42f=ӋQ$p&yʊ0 ZR7ÈeMqP\JpUbohz %(܄FΠ`Zp4h8`c>mD vNA ?w~`UnFп\?)?xu'ޘ$yo]Bj4|uZ )";ȯ(kj?]q}e2RIʩ&\eTᓺU:SE"o|.sTW;yѡhqwBejJ+S%_H#GwΊI's֡j:/^Kȓ绬a/b0"esA'|r=ewapݝ!@>%*:ꜦORonC&G-]֚a~&7(Ac#㲷?iOcoP!y+Yw[|_ݿ3vrNntDnr5ʩC>~|Ǹ(B4,5r5MO^M(F˞;u7p. l&SdLŊhI \]^FND\oeμtYB`Ը֟ieŃ P.tsVR.)YjЈFy;"`K"fڛuW:I#*n}/<%Jߙ~>z615Q,F|EI@\?gꅰf^'OhE+O;P)/@Gyfb*br kZ_uSGTT%RQ0RM06|>(3صn{Fj6/wh}u칫R\vC%}WHP=-Z{. NU M9]'[8.L e^ٯ^EJf &JBZ{L9LP.]}dut38\ZmԮNȃٴ7, 䅱X[;rRN6v `o6_JtOI~јWD$Je9,aá.uDao*{^:!A39groZBk=.Z=W6ȇ}ջ^R݆E*V].CYfZwil \vY_KVvx}De3GнȦVXg6qkgSE﫞>x TL_KC]^(g`Э&D02ղUp sQȐUk1o&}p>!eka6|0y I Cn?FZ[˦T s2 VIRߊ`o.lnU%v,zߝp;a"k^cu~Ԏ` tuY齼.ͬ 1D-a$@f`ESܘ픖kڤoLI>AVV#3RZƸ(j)BB|Jr cl&ݞ!0#é7K)tD><pt|2*|UUSe 7[w8T( 1@I% Gd M \CY5ί8c7\:,ЇΈ(zΌҽ (I$j$UD,A4t:.(?)g2{G.)QtDfΊwSwcdCKcjyYڃiOD1y(C=ÔUȌ "7s @Mo7YYK$l36Ѩ+123n^Yie5hv`|K SzYG*MNk׬ɘI̶?'4O|Qf+ȪZ'8Tfhm8484RjY;'kyGbalMkd27m h@Cc36xAq4hJu} <ڂxGN{X4qчpU͂.g? @JL緛 L`?Z4Sʔ3~ ,y84s6rI vNr/zz*sr0%#!#_) rFOɇcL$awޒ*A˱ZDq#8 ) ,-Ns1sT-9pPx)CWF"cjDcĉ`tLȃc SϲޅֶФ'- ݭ,uo8:HUs|F#us M:I"ԣmb3QWHgIˌI}5ҧ&wҊ-8i,JCt 鞌IHLx!׍eX hሖ8fV~=FC+H#r Oa!5O9[y3_T MvאNyyAjǣ,"A(d2|7:ʠq.x:u Łd 2ZR+n,v&zN2ChBwA2xZ6G|QaF),QK"ֺW|NjxTM/U*<여(x˓Sy챱$vIݰQG԰C}CB&$9giǻ;Xltl\v7TS *UdhjqH[i#o AyF/q1x>ChYQkTVXy8Gv\OF+LCTm:f\i(LzLi!O$0d8t'(`ҽHd|_FhCIy6jT eNmB)@24Wcg=Gޜvz /s)t s=1!1{y[r ܫh\>d\}DneVj϶ d:zψ9оrKjG_# M'˩ݔR  chKJ*);X0QI۵w4Q|v? []HhcMe(y Ν v0TiMD\2Vٓr]1%:A'-T~+ P/!KTHrCCbթ;QPŝ_lfx槯tkBcg[d"d-#t߆ j/53P=u2ٸI;}dԅ6GwT/.M8p={&v%rst{;7ũLh8i[I幼Gw<Aj5r] 4dy`17IYe~ͨo2 #Obk>zd!9"w+7"[)۫&It4tl'@)t} 9M} + Q;/!ʃ hJ̙*O@:abΈޤkC/p̈́4˴՝GNEחQu|&v#mE8@ȹJ"<ͼBu ,O~l:/~}\w@]BZA{(#iYM-4 -vI¯`c)K>xg9)@{S;d+hhr7d.3tX-$$X+ 1JS]=b$Vx<};! 0(iR+Ih%[&Zqx3yz'tӅ-9|;2|4-2y-'oLk}cyol<} y2= n3}ujsLϟk}uAmW䍣z}H P h`^/?gMbLg5؆JWF0V,3ϫUlyldnkY(el5CHb< P%_ 딽$Cb_ʱ `T>?qNn cÂw~T>8G[KBe=d#khFT2>BK,;蹬ȣkIX|e~Ow-pH+.vA |ًYM^AsNemЭ/ L`@m%T/F*@-B~[> 5BtH7\>/sUf7,{f3#i.sڦSW;+ӜxBVumD +GM}Ljh.RΚ.9cRzE[HsǿA+g[|R^8tVix/,D'k|gl~L&UaB3ʚen 4ppLwQ9?ť1簄)\K?tE<W9eCj+ѯ^2Ij/۟賈mmCTj/Y(i TdzHRVCvN[ƯNu+[m-Fcmf --ᄋA1=:6*VJGvuF+M5oθ0F.4yK{R aʟg2<+x 4o41Stsq&49ϼ\k830 &18-t.9}t SM|BmRox9y{sj^ +KU*f#ͭ,Y{~ƪ;m@2YLo惏˔Kk+C>T~QЛn1>Z0Aû flsmLD|.s^"Q79nX@ӷvSoEB&SI13^?2sjX߳;hLLek{ȤS0g{dCy|(^ !Չ6EP\+֤*w 6WP 2[ˋZ$[Ű;3{WI/.ʯِCQƬVJ5Ic4{0\4w*gf.vp}aa6)^$;t'η\'P^qȔ5Fǣ?G c = 7wfh7F)Msy&HmxBQCt|Eh^9gfnF'9>]?Wi}9$[ye]eVzKg v iCVƁX-г'rBяٲ7f?pY""B.6~}ɔ+vg㔱ic*M`CB)oQӋig}> ɠ(QvȁGE7:.AjBUГF1qU^j)(GVV6<9ف"0:6u o \O 8Ir6,\fBxXnkTP9t6sˌ۳wAa(9|2&҉>7^e ꇿmP[ӘE2%1>h(<L'p<]/+EV@QɝKr,0Yk%m\0̃ g}%] %l;~ty*;4Q _%ʖ'VUø׭.ڏ̂h@<ǖbe O OFcQWխt6x&>Ud9Z%OYSևân?ITG X"Yf:"3e^cM'HCYfɠE}U2W"藧rQe|u˶ SVmh"X~6_UJoj7L$JvPy丧>H3_Is 7=k>%sEmCj+T*f̀#f bVueΒK9OpQ=1LPU=1WBY5zStuo Z|ذ}bfF6S VL; tTP)g*eCMzi,繏9ϝl,yٲ1RrѢ' \ H5Ǘ塪0mަ}o՟F/y 2g "(%|ݼ y}5WU⧭0Lޣ>aPУ%Mip*QpA qΥlCh`zW|s%Q\hi>G<.a#e^$U}Ӗ!J  ytAk6gQ@|Zۻ5[+eh:8PhźHBz:$Sb*xԖ8x%|bPrjD _ Asg'L' Tc$o8<<-S砄DN0VT4xM1Dj5>2Lg37fZY\䴅߇/ėWRWl!:=FWd`5y4u4Z}{tmtEppU= o: *|;ow&ATVF}ɅCgѧ-j(ڑ|Ww1/;2Xyt7=G/%_ΡB m+G+p'DT8Mֽ}̆W-pyͱd53=/dɠQzd'={*sqqÛ%q5AB}L Bɹw'mЏMG@!_s%Ϝs&r3ôU<<AH*?c~0+83QoA'%=j{8!əg3T]9Jbtf@ ]pD>*,kqK@e돚w3A5,TAUk~vnS哹6l|E`uhO7D_Ӡ0攧VH<(]hN@=hn癉 EYj03~x)9-OpJ,95OL)k{~>KSWLaFh4yFG+d9^òr>Qy݂g;̈́ ʩZܦvЇ({2ry;%›ɦ`@[y&>6n> SxO#5uҍZS{n  hOMpg_t /N#{sdT(X76MK^~6LW!glKkɨYZf 9YdU$X쬥rЖ6eXFQ\ !K"9tj}ʪ1Ee M JTG͖Eۃ\ TZe!ogD"B0M8CdPfCҩlم|{nmkwYPBAI]S~)י[&TXE*1Q*:t Dlի&(7p"(gp 08] -Ld"Z9m=DPyd=?2$i)hux?1 1_rOHgŨԗӭ3޺!{a+c+zM Df, r,VpA%Yu 0NSiBX ~*CǢeǮX߰v&ǴԵ4(6&,#R1ۼ6KsaϼyݹΏdju1K$#4}0~!cv575d󢢡z MhtX'sք7'>#IE"1)5ri\SCy?/p8hMy zf۠j'o5FSxR:0õ71l 6(!~I&˨3i`˷ :]ƚY%tLns%K%P5#ڛ^FmSѯNI/雩VU.\dDo{j(s؍cEmFFe6">L`D&'QfzX8Wz` U2{ wu/; }ym^|p+rն(2nu3e 4OJN1S#:repqK;i26Qdβm7A#:WWU g&t MyGcVY~e2l4O]qα-=R@Yzؔ-X.F1D9,u֞|PT W leTo^EcpÐ~y%ùkV&gnLSI7QyM:hqs5>yĭc~^Vy*iKxx>eDVF Ʌf/ R {Y.'=#uq+ Zw)ex\PVp,{1w؛ C/SEF ̼9oB懽B,(~@Owe+6y浽:N!)͔_[#fAmjGL{jf1)MipҙFf *(l2<B^h3T0Kn˔h`OL[x8PX ϵJߊ;a[KᐠE칞Z\Z@i_Yf!"+>Xo`yhJQDklZiY[i˧;Uf$kQ|Kp1xETߑZT̊p>(dM* f(t qgRڻüM+?IǍZ6GSB¢2 ~ӫُT>o,5Z7>wf\:voЫ^oV=sس΃ Ȗգ=XQIގϲ[iφJw@(.EۢE.߽48#g)H,4,[g(- G> -M>Q *3"\٧!o1r8_Q¸Ey0 EzyfIe g, _~fAW( heݬ?gG'|&RN-d)x܋\KR%p֊; /wTlU\9&o~a7߄ yVLD_B_TPI֦ߘngL+MNb$wDߴI*h2 ׸ c;~"w lL'eZ5Jh}VMv# O`1^ҦET9&NhQNe7EEܔxjAd`WOW6[Y^ِ̮?v7,"_^sRԾ@ 4All~6;IPXSLJ&c^Lsm?lPq_Imci9n>\␢8 C5)_&,+&,1#o1F*|Gܳk <u_+*|*I̷;6tC䆃LO,4]WL |:^Qfvfwm&Snlċ5?|B~U̬xd+V020BU~"H@C{^T;wznzYfk>@AX{ W|OsmgBtr*^G;oSXoiף|8 vU0 FTVFݯ”@q(ܦ+Tj>lNPTlbןa(vT64/GPiהm.cT~[g5噧uhhބu-d3Y-l8.rJi&uĘ4HOQba)goZ]׍30ӭnáZ)Tp3 +ͯ'ꎇi: [DH207[&B<]92*> fHf`mN fn59$A ^ߔ`:Z?Šꗞ:/⽵l2oa/.zr{䬧f\fu3ESp4(ҁcFYyN}v+Xj+0's/Rgj7Oi d_`@~%0ʮrPxlwU@%f ejYޚ p[0 ۊlT  ЄRxdfj(Uܹc*!Co-hjRn>iC?zE9$k݄+ oUAZ9 릖zYѼTC-,#^ 7O+CBۧG4,6AA {KЛTᨕúd:ͳnN@Sl Ѩe~f:|^.<2I tŮP$2nd ̞Ss,xaH8>WdBM 70W؈,"5]4V_!sĵR\cezrmxn: 8fg#c4|'POFP$i_>ét<{NK4ڏo・'2&lUA79}49ڵ@[%)C~2wD͟]yH6iQA/Ks5 "4-㡅fors$4l X ^ aR|#&߆2rCPaLc>)se,SIFUh*v`! ¨)hPJ#Yu㵅BV:}T\dFDB1Cf|lV@1ijYLEWY)]ڭ wf_m4ݾ7&p?Ro+be>56k[}-n8C}/>FShwmm?>̇9%92M10=2S͸A!WU >n:24HɌLKOah[,|>## C\eH@ ib]eQKHJ/*0uvtW(E.*h>ypvJ9n&B۬=l_Nu.lŬL,ߺ-˷q"y=I.ΑdA L}}.jYc|ϧM>yAl2v.Cq(RҨ9h>hfuZmw2u38a4K^G-w|k^荿j9&qzH[| hk^uaSioxUV%6Fvy rSy^EE>&IoecL$^,ٟW=큻zY+W1^bP3}AVœߘ+#|Q/AXH>|2S $hu>}҈y=fw@.Z㞚 eFUM& id,݌zE K&+vbKxͯ ѫ0ɜM53q-E.ìYf)7ڥT'(Ǣjw%7]i]#4ߵwףKP3MLVmU5[#YlU'+ľy?}jJ؍7134&U3dZ'{s&p|+u;f'#G#<^NfjEU|fƒ~ۣ{W_Ў JGљ' gS#dkY""'TLo:τgfmjk%5 *}dϙbZB0 l1*3~;6Ѩ?>a7>n hH/r+vtݾκB >Y$ diTpqߞp_{lhQZy(F w}k^^wwb Akf#a !M,&U;4FJ;*Πbhk I}hnAŕTBŵoz}Ӈޡ#4n]~Ȱ!N2rS RFFi:TVfK(5dŹ%Ek c66`\E2g9*@J, W{-ǧ;]^/˔9?t'L ^ȧjsWSNBI |칬A{~Ev ӻp@abpfvB} ̂zدH#ްm&e^=3N9ޛ>zV-Өgde'"ؿ ѷrM~5խ5ЋE XpY9:H&:B16%^-P>K&Y2 0Hg̵:{T|SYE ϸEj M# 9G7\4ArOexY7VfBkHlB 7~;'vIo53 >;=#6<0~h\`@ɂ=eNu{*]xeC C"-<~%An2bԍnC䔨>wɭdt>fsu6vvn@Q1hW:m\W8z+=wr/=< #)KvyKvT.s陹q U RrvC7CԈrP] * :t;ZWaYOe$ cI+!Hހ'v7yZix3K<Ҁ,\_*<= f &$?ٶq A;)ɨ Ӊ4eV }g)$+[~!XC?4(SGBPEWr`NWSUR|hGJXbz.;'#}_UMHL8-T~ue xxO;|QP6 U%Yr/H]'7?pQպ#?|}J'3o2/aPh{Ώ`OOnq=ڹ%V.bP=fuN%lі{ VO2l:gm8uY ܊4G̡~H7rײ*L&V$ynzN|;Nehlp^̏O^oΏ쏹Y%^ c]eYC3}ԫSC2C.s;f@=PiI2;7.pz!We#2YWIа]÷T?To5;Z9PAZB"(kf#a-*wݠoM,/ C K& y[,e|‡`+-??Bl |5aÀodKTl5 .{ivv+>@Cb+,ְS70(ISygB9:yLԦWM&pYG ӧG zG._ p d4mV~)$fAZ6ia˻;Qqy0i;y4BJ1+Gf5foM7զyJg}~@Wje}˳1>{6,c<{@%]tWkdHIݡܑY:R#ї&C ²5F'|{[F*w-;ԟXZO<>2oM94(\K)h\/T?)zFQa>3ל1 42if&E+yEaDu)zg̐9U+E=!QeVwNem;+/ZA+ސI llh8)K}O]gYp~/)HL/fπ ysj~P5+'=`]}h"RK5kQ UȣU^zz^׋Ģ*?kt-Ř,a :T]Q@һIQ+r3=bk2IoL8¤mN>B1creo6`dEU,ِ D׏g9/UZ9 zȰ$k_󦘖7f1A-zg?i}~m>YlR‘b""os"c!B2 =Íx+/TدB*kUt܂L^T2F\/ k(vQ(d;~t2OO l%) :S768 Q&lۏ$/cww`O*e1v ULKmMil4Pwj1"~t'& A+/u.nr0{H/UO7@{} 1xU17_uj}Oe)ˬ*^_pHP 5פ#\H&)j[Џ^Nqp^lg-Pl9p+:s\i=yu毧8"E_)tGu~K݌O{1wːrRmY6&7tMCx{KѻfO+f]Xzo6<%7оEQ!Fgvoo@ʠuθ=:.&rHpDUtwLKdB~Wd3ةtYfpjHt of&X} /X_$@fƁFg h25sidOOkZVo(CrrZ -;>YyѱޙϮ_YBs #d_l}}~A)mmO>Wx㡗g*/ЅOãm#pg_zhV\a 73/ߦx沧fD@-[jql̾>kqyz)$P|7m\Ƕ{ˆ*gQb@jSi5V;X2ڋ=cMԛybvaM[h7";fjzn]mMd1? Rc)1/1[kIkLJ88|^RTP+2,Ky6iMC|3M hVN57Wd +TPab{p̩N?,ZrZ}΃L89V6˴Cp"A[nx|.`fJ @fE\UlgtXՋS$*nJw Amr}#$!qj4q3c[Z23j9i7{%ޘOinzEcw2b\2gT`F2s * ؂YB0tmd#Jډ ^UBsOm+,~l 衴0d"D.7]ЅZe j2oj^yJ%]q/ ]f0*̊5Ig ?cfPj~/ s)ajsF&nf -䩒\!{e汬s{hy^ߜvUzg/Tj3e䁉Va^w%^&LJMƥB;5BLVy|+"hLaN44yNfMf*dPް#eRqd=ffh>G5Z'Ԣ) De$PQS/+ҴRlif]5KS*Zͭf7 i~j1$" ) 5h )DZ$rS -=ڰGQl >E\;3 # =}E;H C 9ћo~_tY@f,Q_[{; s- Y3+~n.P`9\im\U 6(;Z3((0k(yro ZWe݋\aCc'Pt,o^Ep(hP\cӊ }|Hv4'm6Ζ۝\n LL݈+"/鱱=L*K3F~h-eB-wW؅<4ad!bb%JEX931ECTtCfAՉ)r\HNO+.r%z7(&{d3w0>}5~E ys^eVe0 ϥ9p_obH{-`jjP&0;sN0t}IR :򏋋nAaHJS8PƠ֮8qXyg},/ȇܑOVʶSN^a\e;nL9A KˤyB WW$9fi"fx%W$sD&^u"[f2oc,COn Uq$oy= v~gS 5 hmxS&M 2Л>6=7//SDo.?abłw#Z+HmޝO&HAg%!̦i}8fÌ5\o#I>2tS͠Φh/4 t@x-Ϸ[LYN+)Ca^ww~v"wB͚9`V@[i~flaeNdn(kkI"TD9Aq {S,Ve6- t*Hgơ)%2eZҫ+m4`,hhM?q ه(@y+J= شĄnuh*LV[Fؐ)bjZ Y{rYtPfѴh):l2EozȊRBe&E+ sGXqQyIyjUA֞(EURtz;,5>L25Xy9AltB rV7Lˬ!z?r3nEMԟ́nAdKDY<$ j6yOq̻؅>>+2, Ptģ7E) +mZ=P<21gય5h2\E931a¢s[U$3/d<*dڄIo$3UkӔhFS0iQKnnBwn 3ˆBe^MuT#^lzunYsUڔWfabppFx00)LݡcYe J[82֫$OuzReN,}cpl?Mvy`d^@P-*/>ivs@B;hL)2_O UXf^M̼ò҂VxpIO _`Dt˯}sN~,F^5*Bu)r6 wQ.裫4G>̖5Z_`~@htݩp‘ hirK{8L~3+gE#}`nή^vLΗKf@/OE#:eq7q3.]R@kiuҙo[Ĩ*`^fOz`5wia$"O*Q?Fy0ѱ>`RgC!`/qy]Aoz`ZhZ<& 6y>7RK~c*ZT|JnGi3jd Me>7/F>wnVv^M/Ymj׾dcWK|d.`"ceV3Ky7WfˊҵQ 'olPUyQaG'ndi)Y[ g Rk[ ֈuenm!ݟ 뗰ZzE- ʄs{߉pkpVy ךshgBgNLB;USous#)mJ}*Φ/~鸝a(4-e:8gm,=PrxN|uWhHƀ\&[d7Mav'"9g <@,Ͳ5Qk2?O^}l]ܷ[/\I: 2^J *wkyF%eŻy3JG W'i7X|"nnR$Ϊpxȗ[\)6PaD_kVيfK:яò#mz]A/ Gi@UBSK}&?q] ֈSA[_TO$pmmN&,tf@d2Iut7az|+<Ч.㷼U@+_a j(Uڅr_CO>%ER SvF_sXV!USʙ<1lIgV "-^8ktGpaKݿʊ"9Vo .РmCWu$9d T YT5?2STe<^ gS4˼3vqN! OQV\t ob>4ٔlftƨiߝ^:7K4C9Tl.O#c_溳[Ef8f*`vS4Bf-E+m=+2QibߦFw#}!w}4O'6lڳ*nx TAS']l SQy]y@"i]2:מw.!39l)vK3jcZcLQ|:#+4GP̻Z|kx)EE%6G 2]mr'0֊./ W7 c8fbAƄ͏hY.Qq/&OKm2xR\:}Af~SH+r_:3xĪ;8<Ԭ~bcrRa"f/eӗDc}څ@mz8jcuű5m9I7@D(u9s]4dPY*Z9zd+ʔkLV(KǓdWGI\O!Jy !6~mfYwl Z7_dwD CP[nG6l안lPc䎏ϸlCC[4Rb2f=l/b)H˹qm)/62{U٩z24l{=9_6& @kkǓuU;>Dv #>Gi8|WVRt$n=x>5 ,oXs;9]2q^5_^Lڠaz8سVTa0>¨ >/NTzhd>Lu5-TM)!Tp#qqV+&Gn_3%1c8h*3ZI)eO0Q2s4X&L|7 +`;e&+?N{7I!Sy&omc㓤;[Z]Ki w14q3V|`B+gg#c).}ݜAva~)J^֖P9Ucf=Y~ȧXSdw>W<ADZT4:~`P`-:-J2faHa2pl 0m\dJGA7GRM}uhDOk_ 5& { TsfD e &=5E)܁ݨXKP=h:(PF R x\kmnǹg\72j|')m -IhbJfG߳Tn3)6$C<*Yv4ÁcY& ٷ60݊tUAl93nGzS=_i\'#3aj FZf\9>[/`c4iJ9liEifW3 W6zR3w%IH!qаi h? PO&*{TUuWeY3(y 3ۥaEio֫zg߇ Ve>v,#:+qe̠jGL[ Eܧp'֢? eDEflHw /i]42bDFZ67~r7߳Z&7~rI͘l^dƢrřxG\f\fÓdt  9 LGceItVCNȸ?oc&fj#M珙3or7+f-@̠:-DjHTd)ZBdv1wX-+T89[ͻwswwOӈfkLP;ꡏG6WMt,2SM{hEfȂC4w} Lp;5]PǛT y('Ƹ2lR "5U'7]`n BӸ`ha$.ɭACoR_H+ 9nW*=¸z@ CURviRBj{O#|cÖMW9%Ơc!#_'v+mÕ6Ó3;TVXw3<82hxmt7H 6pq;؇?}+}xelOɇaw(]ܼU(O#~+>A;S=YHVW`"oޫG"+,3(~½~)wj3 c-o|Qyc k0m%We^ fOKtMTZ7GP#{HEwUĄRw$)26S;6BM0dIWNFuB-&e??! ^[_K=PxvD7[@Ipb{ltwuyמ'TE~jh536sadєjFؼcGUusp(B\VV۪zc6o0:QwNT?$@=pު~M֝~fU^-^i2](SP޴RUq湟yb=FJ7'A"7J@Va"&$l^oNHPx*bEoc#ۜ ZV ɃuA_һ|ti'y&-4ۜ2M|zGQs{J/CCllOC!v!Idj~#߆j6ʚ{م/s5-1xa3<IfK<$Cw=y4t㪦 ̓` {#T 5J0_S:!~d!lΤ>ϖZC4ؚw2YâLŪL+r*$0|رeNIfSE;F9lE(me-z1O jUdt= 54a124{VӑA7+ֱܤc(ݭOݪmp_- d@,&P:3ɶc<9k}y+hdVfm&(yHmQ@ٚ%J2R័7mOV ltD:QPEQqW0r31m&M/z_t  5!`ѩHzcB[k)' W4urߎvLI][]nHK{x8Yq~4nlfmit0KꮘɡNU/?D.szˍW${p^J`pm%{*iJ\WɎڽsM܅Ј =וS{Krlm,rS4{f##ݷPBCM6}xEaW7Q)-S*\)YНV5O rJi n"hC-G> !(!wh:kݲ=EtPWQp1淤a`έ >ص]4-;{%_y\xrO+2òg4eNҩ3lwܷm g]ZAb%4CJ*T=,?\$fJJ"7J/C]JD]:>2| NӢ6RQL-8䜠^8ڢR#)̏>CMQeW]2h,FCӵ* ΃~XT(0vy6?T\e8#]~g\N6RMŖ²ʈ *rֳV9Ⅷ.侪}j\c%S2i9[ᑉ/2`0sߧ#RxG oc0Zb6K|C$/g$ưQµ<,Vco2y6F0 &mrO6F~} pZd;k*Իӧ|eNfc>,y,;QFFOjl'P񔋬pl`D Ⱥ٩P3M7_bU~-ᅜ>U gUb=ŭm"mQ~7PMϖ}LŧN(*vK^F&`5 wmRPkBS*J򕌌2YS>IykۺUGLm3j~6GF6>J$a4 yLЋ;utӽbY)"׉e>/q7s&h|]s<:~O.b=|b%A9Vmo/`n|acwcCӷ.T-pbK^OFޜ0P7Ø[?bJ jSLfF`ߥn@BΝ4.֊Oj>'t-MM-c1z.-)T|+7JqcTMbɧ6,P.Pb{^fc\ŏQY?9@/*].B4E}QmA74WFdgGz6#yhv{~oXn:r{]7 MẀ/dqX?[8W7= ~+[JpBl[q 4[e)X. P>e d؆tN?q??)j]|)J.\̝@7->ņ9MŦ8ߓC[m.ny Ly(ЧfpDUAr(J槡d(S)Yċ;ñoM,2j'OrLOw($@ES&o?ؔK3J(3IRH3Ol Wc?/rVS&6|SƱv{U#OBȼ"ft](B]Q`+ʒl ,e"DecFt|s;9.(ˌ!1mY'ߛgo ء M3 !eC&ږ\q5 SE_]ÁA 2+jLjUIwq8hytiq#Kw5'UַP1O7VҪEVD7A+R%˗%?GNP@xzZuwXr.?N(8HtJq0Wn&un 6S]36<_.Vq}GXktA/2ex^C ZxV0:c/?l{0l$4DDW ĿS(uÙ//3º{F]H2˃4}SQ'yҋeRf +4מ.y%JD44¼ 7XL^_M-)7PrEl ]e; X8ͫ IWV\;UC?zj^WX;P'iCkʆe%dhU"[ՂSU^2oZJ$JC^EN"YyM^1˼@ttU|Rz_)ٔ&;\[mS Y+/TU\~cPwK}S?d!^5U>P=> =-?TJ|OlIJ 2%j[-)5dث h8OtVY|u*[p[O/@7u?e1m>OUC46HP:r7d}W83l?9Ч^k##oMwjjNOBlCfX %m=b0 ˼'-R#> <'7oQAI7eW~dc2w ٨]ln l~3ضXvȫE{#Z<[iƹ[<5~pRԀ\fIPeۮGv:ƍ`ϔmT=6usID@+⹇+] `RM,g*PC3:!U;)¬/^#VAłS}Hwc<%<2 .Us L@tRP xo\&O92ݸe4nuU1l@"EجjFNeFaa`]~sH5;Ptwx`d8CĹDݨS74ިO@?)F+(֠u݉Br4wR@%6&qw(LYIUW.IvC¡HuA+! "!yIW!" Lك\*wF08fܱ ?]RkK/ytɠ-h3)fIfWuwŖ,Èpp8=6k݉z|P8ip "b޸IGX2 %ȅ'E-᨞ҎJ-/ag 76y` w7nPnp`hHFNQCrE ԡJI)qGUi!Dq wPE)_Tu1CaU7U''L]4p&B>G{9Ƚ #[NQoCrТN]8k(^)uC̭2P{:iPwJ| 2nhϵLa\We$:Raty?"wkz @SR$a .&AIZh̖,&* mhH{\do!4c}oډҚujG,'2\Fq')!WsvTپTj~Qp6E#Wį_V"|Jے fhBNBإ11͎{'@2q.xʐt89O̎F`4[nG.ӒˤrB )Tmzwݴ?MP4߇/U?^Qpg"pWPr9`AU 6DԼ\woZH])7ObwSU}H,^~4̈́.ҚZ2όm vPK8L2j/ߎqՠBUTɏ HÎ CPus> #_UXe> r` =Jֻ_D<,A@fl;>ZBWyE s&_T,cA9=ܬǺ1G\SPI̅ݘVYtC6·Y֏4ЗA$|Ue6d^sL^a4Pvc;2I]֓`O2띶?Mh=̫{N"v %*HKp&lGCwszJi۷$ VF*4+2AbΘCyiw'.3;!p{s z#:UF'cjB<P5h,Qynz1fVzz ^Qh<-2-%6]$jDd|sa应A &&|և^G.sW,a/??uоR}]`횉|(drCxx&`a{蘛Rh^ a=AgEMz>ckk1) ]aā52s">5[b.%S.JS?YA)PK5^Ō]2[.a뽖.qF.C[¹([f eRG,*׼}͡92}qwZ{`47U+@7~\v}U Ch:zzd~3lsjXYݼ"gz'KC%oT/P5*I##CX̠ 5RF/pc45 FFTTlv$zz/2_,~U\E)/RTP)dm'Hn|9ܦxZ2qj2ֻ UnFшp.37o5xjB_U@s(hmSzowƪv/UMeG ZxgE~&lM}UwEfZ<`e&r!N[ ;ۦ{4(hP ]Xe9]G@ӊ ٫(1JОil>|:Q^G'ZNwE46Q]a^M& 8 PÞ6OK&; ~ʤ¦ -ᬔC=fn/nʚrU}hvڿ՘Df`s6~1iJk}<0'jw@re%/zk4rĢyֽꃪXPˮlcg|D0 2R3>Ǥm<cAvX[sK\>*}\f[Wح]lF~7<5'FyiC|X7Sf$P} 'RQnˌ)bEؘ=;q؛Ua)fRevJC#5H%–y@W)<%DyG,՘e"gM1'gܫCˢ'g;ibSJ.3f*,ӭ\?&/iUНruZEK/7n mtH(pt5j49" Z&E*q춼v$pgX&EߕR<8;>l9d p֦,=nYYWrShʒ*ݭzgتwB9񕔫4H&Vw#ྏ(jy4KTnnVd)[/$>ؔ4@2{?T,Thi%&&xK&̒e[\5X>zW{$RBsb h毩߃Goffqf4*Fz7Iӷs%: =őa"A?&ẓVf-zZ&._r*x.'%5'xFY4,s]Oaiۙ(blZܘbVBY=h4P|/ڐӡ{enșh.ۘf&Zx֜J "X)MjL0JwA 22=Hlb.m*N{p/:4^֋^zсjm }(+8+fĝ6Wr6MZfff䷍H a bo^7 YdJ.fw$Nh6_{*˲Y) LW+&[}_+xHJc t*}y_TrazȏlyE?0 U?{m V5,)wy p_!iK;JiǪ:l(zlT,pqŮ(ȴwyὼ7a7WmA XWQms9i[6IOz響q$@` b_ZaUnyo:a`^ǔ@V} ch7~1c:Q幃M'mcn9Q"(=4VJLRApme wzOBc4;Ҥ gL ޽n d)v~?SԴݓ%inA?~C@FX52Nָg2۔tŻ⏲Dwj:uG ^tHsƫU~t[eO\>qL7rOߓEWvB_-+q:{8{ UExz>ٰ_o?z>ٰ^A_r?i7sH/H(QZ?K;QXW.zEh>td-)[295?_#2r7W*ңoBAnCE2^4{аhht/oU5O6d ֗W#/: ")qKm?볃 %5{h玨=ؾ9E04l'!֠!2:'YğL@u@>U%2𝒣`u.*Ph?KhnQkEH楏Z`2!Sؗ8Q0J'ٌQ͒_Wj7M,y"{-h{ҳB&,4UM1rӫ-a(u0=|+_?dv ʱw1G-R Tk#Y^;t38Sr7i,lDĬ0iQ |.D9#ͳ OKĦz#/Qr VȊK1*դsunPs%QAԖYIy:[$*֤0 ]ՅL_9Ѹonn(bC+EXrѬ)x .=5239VdX.@7w Ĵ1 ~ -p1Ea. L|͵e< IL'9Km7ѵ_00~{{J)-m)ߍ[i{_d晽7/{1Ob[YM,},bt^E"jp}o;tldAi؞(!_`.Z2$_T='P37J9PiTpAYxfb7kh%P{4|G6( ƨ) &~` [ {я`[EYn"JC"|(L=l^%-ɜ0„ҚX#N[u,X7H]q&㹐0l0LinU!ZK(FwMvmMZ2~ 1GGK{b o?ZH`o[ -_SGykWlu(`z"|lFʶer]G+RVd9aIw^!2QFp4Pr I,~(ZvàUGu /vO@U$喧Elu߀u}nQ4"aDr 梛^&oq8M@?yUŦ8wC/P{h#DUfw5dˇK 2p= 5IS }N="(~ܬW#OlNqP_3^rw5=꧘wJ:Γ;>HdTZ&|ă.SyS)qi?iWֻ\՝q{gE:£b?ȍ|n*W.X7INDgJ(0'kent~Ƭr߹X$A<' t毥kr*ExN*mc1*8W(&`/oyAt (m/6A'.nz*UJ<UNZ~}C˱krlST7S)Fѳ%g 9=4zE}-Z,,ϔF=BM6Aރ{4+<'//>XJ7Vc72yPZ;Lh{G:Xϗ)=r{ bq XfQ̅4 v4BzA)Ze.vE7s~A֋wE-o"SiZ54L֑sf0_{Y7zjMJ^iP dy9Niv{N^>1 3cX_!/X"|I!&Fu3=C:}O,#u>"/zC:A뎄P˛3"s 5Ca©ټ7V=QdhRXu65 G@ KpPV>P:n{'цb*|.|(ޣ[>WxobhvF1^SFsX~G$8ͬ^\3("3'%ggS)9`b1a"9 }O2T\.R%AJX|żF}|k`LBS񖿫!$ha]fsiNV!Sw9I)Pv*ʖ|nDFf?4'S1y Leeb~0䚲7q:\fkrW1o8&⓳ f-#=xV2$REv"~o8M"2)ӛ/-Ԡ>y"Y!c׃9Z'$-v~ww3?N >.q[w m[߼W3>$WBB+-ȋmcZ\)Ѳ{]C>~ש=p\-Xgnn6LDض^X4&vyqXW_~hfYՑ f$O f:jHQken3O8]f*.E \#S92u}OgHDC"R f!bۂgDB2M.me%*򂾫4v/`mBcR" "6MZ&wˬV\GUv'bd"PS\bhu[ԩ$>-HՍ&tQ[]Jꆝ;,ڢeLضĨ2Uwf͝/RLσ̿h&_zhH2=8@/b{mn:XeF]!&em9b4OV= LzۢS0ZN4lKd֧7!Ť(Jljv6ܯBQ'螩Ǵp|t8@,+CISF\jlƊ#`f'o^+H=l#[|M)0b F!Ff>U?%e>2$I-iϙLB:AiKT`H};jJE[cQ^ AHxMsBSf-CMk. A,ƼfeL̅ĩ4쾞 '$4ln,>:"h.3oR[+$ءu}M3"}sHsJ)qH KSD(#zaeNEoMT)# <"?Rrښ:hkadk{Q@A у)2kS!]tɚBnnvJܼ8.HMȋ>'SRwѾ&7_I!Zk>02ɴA)ƒ'C`fo&NmȖvT`}A]Ihݚ{[֌ܡڹGRMZ̮yc-z8MDw~x\ey Лֽ>^nȢbOL0jmG жbkSy/F>1Օ,;TWYU)R%sE=n2C|lz cT%iL~糆FfnM'WGL=˅Bi-)ru0eF"A^YP'$J+d (c~w0'È9)m*B Sb;pg@"YNZF= 5_ jZ&yc3a92kPDi!>حk0=Nlg=2~m6 ]TTx&ycn$lΆD͟ D`JW~9aJcd ħ`TɏOnAER8}N!Ej~ix>(|w@B'Oh&q4Zrh){OˤT3O5FRB>&&p܄\Z$]3ia [l#kM#:pjDP:O$50=,zͧd*^ogk)b7(ԇ0\Bupʢ_U`WtZ&C 40݇ V=/E9W4tS"]UP.n Ejt&ʐ(PĦQ̪ \]s47W4W%?WF-WffIߣV\S*Kp+=uG1;S e]*B4co7WlSUmw.:kp:\8Njn@weqXQߪ:~Qw: ^2,7a2<M{>]lE2I`qi\ z(#JskT7gzvI5$ohP84NrSpjU6- +nkpp`&\t62n2a{6$PlW{*cΠ~rk5քǓ}q]MB{hӡlU{j-|"&iw@]I5M Z.f֤7]5C=^yq $ɉ/xT"y CH/ +_R<L08PuM-sg*MQ %r2 ț8C'Ǽ;<Z{_{U洖zП gӇjn1|@%M V@`c0iSٔ?bxvCKg72!zb\Yț>J|h_bX27,~vs\yxGUv0o]qnv3Sx<҇.IzaNd>A=Z&Whص!ϕ<]4:0?זw3 M(z-eߜHo ˼$I~2VI~H ZRZͪ`F<# i%mk|dAyG/ .GKr B ĕ~:mQ`9/Q7Gzc:xQ,v~AAdtok&d-yӛͪa,^7 `wBn[?x+VYKo;GKոhV y(mP,<əMU6n琵P)4J4h͛t$ڞZ%9 T5enTL.FuR9ziаYE"g^c'4bWZfra߀~.o)Ihw$ya%f^*;k@ ݁s^Ge/{'Bf~Aث*]P@H7`AUe~o< FV~mLyj,9d]x`+3UN!5.!fpvUvyǞqqce["D&-=^msc|{iЀdGͦq/K8B^}z[y|ro˂aNV?xmPW*ňaX?t,4^=thf-}L#p[20m&4{Kڲ>B!&liYny@PLRd:th/ \a˝~z4lc&6[e{8G->v2v 2,ONd/Ƃ sȄotAV[#YhT1/W]N$'H$ǙȱÎe?vFhnsZs>LGݡ2D z(-u5"xIrH Tj!Vd ';vE);O2_6SJS^ 8bB.Ϯ{u' sӍc7gOIf]!ʲQl8} |j&!lxB.zps>=n=--Q_ÄSh[QSPOR=vI0GUMG)c/29%R2U1|'VQ2Cд-%:=? (:@A6 d+mLf~1:eB*ٞa1r_$N_3,T:LcB=/&#xq@Y66E\9ʂN{::Y+ʵCHwF@vKKc"/Ru9**hk@I(w"On^1vv%cpWW{)m[5Pfgpr D9OPҘw$e [̵J4тE(f mD"acOamNh$* >\g A}[bؿ r且bb+ Pi .UEQMPx^T&Q̂ oDo6b#+ s}u[3r[&ĀߞL 㨛lu>uUME9o-_WlrS6U;N2{WP.iw]D:|F {?s^v$B) o忟Iu"mtlSѣrRL#-pVw{y0:#!zL꤈_ƒA$2?ÃB l˷K1ç !u>dO552)훥LIK6;,UA&nq_% 0?|&=륞y V=JP 2Uϋkt'}rPʊ0xà"Q=y!3rArދ"z.I_;Lʒg'My2\STW^Le9@ ʚɼ AZQ Yt?ݼw~M)3/1-wX mqՒwyt-0ۼt{QϾE4ehUj BC?ڗN>4ȴ̖8:kRFw$'^sl)M yըsz,3.I:PJ,KI |o3OWh+̐t /W*fInd'쫫S9"PeYxv4 &D+s4CT5QeO}`C}1|cLoYAiU䢛(c}/Isk4F^}r^n5pKY<}틷ѻ _.%|aӊc䇾m /ɦhgㆽV4v'F LQņ2ە=B Z˳vؿOҹ=R=_mE(*d.Mu 0>v5J^!b ^x$0XD;ש7ΉZ>p\7^UhHFgV'Kfne 4IGMnŐfnv1睯!m϶S@dMRkq!EPW*[7>y}b5#nRYz7ҧVg-kG߈ 77KiɿT]F|}I{el5c\^-| m 9.n"y3ٯq$ CF%p&|2_gyeeq7<@4p",!-ZPkZP.m29ۼRM@uRymfrPZz#(8lɏ-"h mHu$X^xiRm>;uf*KcȉP2Nr$KHG uZ8VʆI&x>zvv2ۂ^5GN1-mw,EF0Q'[ H୞GUW8.66z3p$CU_ۀC'2١q]<47$)ŶlԀC+0D kt$>uIئș3y-3J8g:2٫h-bsB.CrZ+xt;2[>D3bSk6۬O(ttu[,M5(izX;E&^BCsޜ8cnk#ݒZO4f!Z3u4nT!r3ׇ0rwCIDnZ1V/g u_*/B$pMbA[/IC7A-|fN[vt.ߟ ;ʪh[mdzOgoTa@.|g^i m*0חZS4 LyɋN~A*iMɰ_{wvq{7:hdL6Ci2 3KS}R*}2[ߘN vыT_r-(. 0򚿩 6PHb_&G7̺[m4JW.zT-p?릌Xp+MSzRVj@k!BM\X1%s/t"K# H{JooT^yjonPJ27TUE좋0`-n{p4@yǃsfV$YǽqЏmq\+J32 r %B\IVwN;M*!h9SUE~ߑ=7k}qL|ɨ(ޙ^h~-{TZHWǜ LRJ_LM}LkjtIsV][mR v%3ݶ m)#rͽ6L-bZc;^UƪG-imjv6J۴l|{YM6j Ӱ^&aj;nmV<eNE={/Wҭ7\~г9ţ)<-3bukZFqɻ+E3p"d7)]33 #0]&Fi\;*n#&m) /,zXʀD@mTIc<c P "Aj nP"4nz]cB{i_Ѫe{p  87*yo ʋ}<' M7J ym"G8W2֘ fƭpu٬범IgJ<{G~i#ZPv2|Pz):sK)>k ڇC46-w.Ѵkt}ww:|5(ޥ+3 <2 N|Rvl|(,U4<<_|LGY9$5m,b糙GwSv_ꦄia̮(w"G|밠C*Ύq%,`c9UR| aVBfT̀ygQxϤuɳrDB/6sL{1Չ3߯ޭuzĒ"=j (\Gy(i*lI _$onS[q̫رrn!Hl %\$ H+JICC/ ZyE{;r!Ӿ 3|l жdhۈNA-{d76.Py Ta@{~V{Ɇ77}w|/}&2WnH5w ћisnN=FjaP~ڟl@kEq}~I84}6a8<6 _@ ="^Z#f.oF"d9ڼ^*{U啕Oe V~' $Jmx~Z \0}pt^9ܟ la*iy0nU?cH:"Wy'ZnQG7}V@"PdaX:i5PMBX rHTϦ9a[}z:ʠq*db U^7W` 4|8):NG脽TSHػ?i,S{oTMyx)5 ~RDξScJYc_"PAt 03sO M';Ѭy<8@FIXgρC;WMVMٳ1f&PԒd4Xr S('a͕ˎ)ci.`.lUE_i7L Sɔym&tc67;p,-Sŏy?so6^H!h?z^5/#R'o2?y)Fsr}Y:2[?X(-^.=@=.__>=Fvi`WEg6 w "rL &4 T&ȯ"Y\]__#JjJګ#2_Kh1-U5Lُ:i[|F ^ *̢0()_O"\Zn+q~9!~t(MDҋ%h,3˴x q|Sہ SWśrn %wЉ(4n ~Z&O$5[[AJu +FaW(MFGVGq^ ߔj滣JC(#_\wD5/΢;2#NQˇ]~=QȎ,;Hͷj;#mf ' .dT'mD@=*/ 4]q=Lp\Gq}Ed/PerAgU|m^ 3Wi;D]#ӽ2۫F.S<+69/^?%سj&A/8Xu`^J Z>Q t-GHT{!%דLa3L[jkʝw,7aVD~9;YFċ!3}dM1] I¥"ltǤ}l);׃dtŽz?4$@Pt{y*y7}\6Pl ?$K\f0j7Qj+6ো^ɦ28c]Gsۍ*{?4|Oz6觻>RQmGQ9&G=e(s3Aګ=-2 Iֲ]LФleQv7˛ScL4?C{:{ 7fao4)B}qPE^i{7ɛe"fv1X N9-yAf\|)\5"I Ӏ[g<>˔Q<Zn t3˨R"EA'Q*J$]7G}xo'JS'7/˨.2٧}wwևك QFTS& lQOK}n[Aͷb]n&157˲q%ODnT4ɀ ;ridnt"_)~xh%5B>UTTXjke^〞NmR]WJ4)I D1箤Qޕ ;A<@)K{[?'9n'4B%t hZj{NFó14 mJMVwT8ry-(5%;B2*P6hi'|njh|lhMiC+8e+86=& ؃) z!0~ӸhQ`w U.z4;RT)$u[W Z]*RD26aP=^ۆ9S焩 nJN7qϦgwlb_Ǻ[R 7r)Kd3˃ɠ0s⬕'$8[ruq=Ȃǝ9T[`- ҽR^N1*D㸼NSeX523p`z o@63NUzh\;CSlL8sVG$,vjr6uDl&pHڃ,\qCapũfm(9e4F>|UEQE,cby`Amr9"Zjn] {h>'(P>`֚ߞSQP!Cћ s8ЊmwU~k]kC=(y=6S9 |`BAxek+t%E>4Ѽˤ?^~$ : "W^FއRjr?baM4JGܲ[wW(&*ĭRgwǖa1sR>&ijtPOykB屑 قv +UpjR8^"^BN:FVwپE_aԠicz$u_k#SиnIu"U4[%\%&(͔G=ߠUP]Շ8Z|r:poKՌenmtR`G37 `wҩ]&F)t8k?7}&F-hv2uPVI sl}"y-Q ɳ(3cJMJqXkh&=~ N:ٰoDuIבėFB3|{B{[ԩ_ wQ˯W-?(>X\k%ZTlIi3xڎ.3G:1#C 4U7~h|#'MIh]Gzv*%}dS!N^0rq "IˏNz%gB,ti; cf,XE"dWf%Cذ7rOx -%c#M!I_4sw7TaltpoḲ'P^tmhB-.灷$ۨ4clTQ$畧]:ze޼~qt!Ov''9O\y(,&*@-88f5|RӴ%5( \c$l(vkE?\<4u?9S:VᩬnzRϙ_C1eT:d3;3c Ui'8hF<\17RQ(~4^YZ"gUƱEA)o3&,n, GLfO- :AuJi~5_lrʻQwduPfܚ%0c)0oXpTvr/Hql _x^?+Pټ :*ͼ⫷<D~ՂpSqn~Tpъ幭^PPȯ{w׻X%o.eEfl\bJa,7 VwgFm|J3{ˤ ;esP2+yR)an(hTE3\id7 `f**waM=u|p\9cOԝ.ewڥDޠiUa~<傲H ^HZ"[TkVl棜 y%ѱHK0_BzUW)^pF{&ۂbcou2|b9)k;zن/ :ӗur,x:0Ϟ:53 /Ks!\B"=|u/qn5\(p~41;G蚢V"7^=VËVe;s;4^071r{n d~wneO yGmC&Ns?g/2bo JIW>5ORJ(:Mޠ-D~{o)ZRtV1po3CT3|uv=zd^YmU\H:4fC=  r>f:Xwh'?O2Oeb10WM{yNGnv1u|P< @Yxd N RE"fI>ZO)l= %@ށ*h<#jF' F+!}E437-&~A$L4~+q8ʒ2ޟރ+U eZ@⢿ݠ+4RlQSkwxD+K { W^r7+Oz搾9sg$OoZ6xTimby̼MkyN*m&pR`Bk5wEF6q6?Y|rS-PTSG "4(V7V `EZ {fHS|EO-,m+_.KL6jϻ83e-[XfΘއڧGZnwo*7hB͒ZO,2iy2-"Nˏ^SPd.{i#CGz3Pd@ #=RR|k{Cy.}Qg"83ev!y5f AMgwʏNG6iaex*к:غ6 Ar7)< vX>=P ,3eYu^(X]qb$܈ų(A>svGݶtׅM7yYϭ,#hiE8::u ^KQd< 77ͫ\\߰l2)ߌrLjdlaCw3PKHEûyGZdj/g2 AoXpCjʨYܩغͣČEV$N!jZI}.8ݴEf?`B8YM4^&64J= nn2s*"&:pb`;+[Wy/ϲ`M0.oԳdgqR!S8Pi-m\LBj峴d t^Zެ))ϟQPIs647VэgykI_{h^}|'ˆ;>wQ;~+JpeˆE`75Yk\8/dBa@&>X`u H?='7cf!"s+)$[yH0:٢d(#3"-@aCZiW7G9ri(n0PM]]tS2x3l#?֪eb["G1H ~4'^_pF`y"i?J;C7;Xbf{GC͓?sM6ķ') :ue0J!q#7^ץ|M^2oNP8;ÂFݢլOcD/3$ N"*Fۊ$fś+EP\4}#׵z߹xREM[Ogө>E &{Dx퍾V[+]?^薧~u6milG KPȍ`kmD;FOHเ+όIpjXZX1Y9egoѫDzv㯒BӪDӀ2y40/zCu{Ug&0TJT˂`VIj `)0:`.aV$*QV1lZJ@fM<}$ՃU=|e6F~% u8@SS ͕]Ea].NUꌪw9j=2:*- txp+r3xD8r:kaށlJ?i b\j k;txIZcb[>Gء/jA?FF}n2pK0Zʈb.g/=XR^Oǽ22{>Ym;,1v77 oZe1ʪy gѳLn&O4 W4"l+Jͽx&`.~wef(dE9ye,D4&E/8)1@kH3s^Y2@r7}/͆94QuhP>AuIxU*͗b)K#єx( 9Yy&2Cj5(i䞏ɞJZ/c\eCtk¦,lO..ʸ v{h\(\g[ϿV͒>"ufLX#ʺ-^ѝ})s̆$#ɨ5]B ?Z) lwbˉUL3iPѬÉ8a[_t̃UPnfRR fˋeT.6;mf}t8mEː ^|Qˬeer,@Ua)=څ(^Ž:M9kjjY^eAI!nJWgl55X֨·@7 85>CS&NA ?%-%VT1J,0E+ycv}S$9('IԢE?7!Ay46 PZ9wDˢnݛp2Q Q9gme[5G#ˬoo\P/yhŪB#2vc18MS.9b`g+qe"8'GPRYpOS@k=|imΨU ɼJݱP֝j6Y~ ia4Р-ag;Xkt#-9jsˬB.P=%agoT>ڟazkD{;/`Z\Dԡx4T]k_Sܠ{9VDݶvē1PX̬HYow\lJykk^7Wmrv92h iN1[r/'d1=w7W*{]bb*J皚PrIfzaњ -8\娞#%6Wdz-c tWzP{VlA`[ʈ~|U5Ϩ1eF ~Ƅ~BEîB)o3eoԴ54͵JL"pbZe9=#Z3p#+N0͹c5uJEp~=x 0Īd[_M%k'_<|Co}'X(c,'OyU+oJ5kyXG>PdU"1n@6ZefP3B>@eYhEȓlfI3VxP\ft l{.gMcWi[iUnRћ̋941הdE ~ y-%~[Ț"Dtkۥ^jtonvJwlNmJ'%ٝaK]K3B5~p-&RW$k*(Y?pd#h?OA~[Wڑ0k Jn .nj}hv{7FGGp+vn.-/:s/ K*QK`&=#Bi~qa-5V!thh*G15imxȧfAN48q tk6aKNt\LMlYW J>1Q/wy.H4mݻe*ssV $\]hI u|^L;CF 5!w:bU퍾cwЩ\ 6&H.z.WWaF3q4ET݌ɢTT dҲRˤ!@ǔanj@ XswP뭶V׼JV<_j1\}$L/^5?54:8sslG_^#8vb3D9l20zPy(<7WUj7c -*_mz-{.Fp4 #LF6a"MZa_2X 뒻NWGup_+}ի,{x_,j.*ʚj+RnpÄI{M!0z񲣝JU-wT(!tGnG˅6s%(R6I m@%|rZm%uLSn)۞AmyK9Ul',1+/?~~,ڃݴ*#6mZ0*(hT,Ƽ'(aM68Bw6 (=/APG8' ?N Eڳ[48&L8Xh''5PzL19Vs|(Q2YK {{fnu_.IZ %ed IN<4"PFq) qgkp#gts No(ffB4 jR>jy ASר}ia"-ٶ=fl4`ꌑ}VEl XuGs{U)!s! ZUwj<E (̒f SWͮ/C[e|D8ݜ?цP:kK;&<@S/@KuyK~ r2𜫮gދ>P 6{+j]*cxa_HפYM{ѺMz(x+G?]Uʑ4qم&12ͯD!lTYHk-ktT?I@5ԐG3epW|\3 b=xBKZq4mC+dLMfUP[+T 9y5*) &V%g<{"Q((g^Z&ەBfVW &Ehs0<"Lwfӫ-D ɪIA[H(=5E\ t0a[}+6~¾(Q8âDlD 4yӋDQ[_J|~3T@W׼jO} ?S1O׺k} ^Syt(jD(r3>nD ]MՉU3ڑ] IgYꊎUaP2zM&@@b Jj^wfrzpEnm<|EFJnuAQ?13A&JRG00fS-L\dJȳ C>MW`x]2(V`+&!$vRD#lWcb[MbDznLJS*UlCTTע+* ɛh[S'aL6!?7 #ۡ}˛lѴZ߭am`医7(fgjvk^dWjAb5R6)GvT2u!D5,%hUj"y4bA+^* Y?č)u[=X~M} l=Cڂ荙ܗ\w*ƴ {[B};X4 Fd-& ?Dr"`JZuRrgmU)lu5 >Ԁ00ede89(c3M7ŵo"&BA%`J'~:gAݾL1T,M sD>= zZiΞ&[ Xc)H> @]J#MlB{Ё6gj_>mU6V?yzfo9[Wqv͊>Blƪ sȯ) .sjӛD;U. Ood#=b {WkEwPmSonۦ!=)CFg~c*UB&r~K_GOL>Y_t࡫TT !as%OıA]P:ѐHυ)v-QDKcQlV>/fnš>R)|(z8[@-Zf`l8ԝ dKТLa6']lx vUu]-3wQ.O[$T.L"jVA왭~؊ 魝2"٬ozCjhbwy .*q0-"}л u~G~uKE4L-/QPu`L[P̈z&"Y8ДKǻ:${|1 J]zy0 )`R 3!PW%]J';~ɶxBEĀ2_mPmq)8 75儗 .s;>O;LV(.N>KT1SѸ@ 2(ݠ}-!mV%%yŔ2~mcyc۸.mVWEK9(.m]Ɔ͘\^xgvĴީeVqs,R"nD )J|Zk]65nшO)ȴ-̧hTEQrvX22duCǦ0L)0*e+X,+Lp nXK14OdA;e‚R$[*\H"]_ mI>;l ]U6d)npne:Q+Y2 QhVB0Nac#+R)LhoocxlȶJP6ըqTYVݞ~7Ly{y\.ٴ4},Yr<2YeUP$ kZz(R!o!vj`"In֧lA 0Hke^q<9ϰ~Z: NŃ:Y.|\'cXިބP:Ĺ#{Zȯ $7' KFTa-ꃦCa8tyےyаk/ٳ$7K,ޖN~Ǹ(O)Hac*nNHz[ske)Ū>)O>V Je];e6zݳ%y/c//uUl˛N^Ee:BRusF ޖS0rpCfz,+g̓b4ț^(MHV&{L쭺BO6tu6*t [)|&=sh/ qo]SHH/ϷO嵠ˠ@*-wϖT Jn> <˂9X[;^̮}hJJSMƺy*ƀ 2տpȠ [H-/xUF8ա̕ˤx޻tnIetX6&2dl1kCM&V9d%9)1cߞ|suq}ΣAPο^uܿD -XPX݌n9" ltq7EvTr7~7ØZvSAp2ĭ(U49fEcɳ:^ heFYdpCwT4>pfʆk'ު:5챷<\yUh%3NLLZ.{&9>mS7W`>S =U-5}/~ }һW 4\.m0fdty6h:/ܸ_ʍd -|sc,ؑ_:N>O5q Y1CɛiGఎjl4AS>e"\cS[69[^#*VMwm홋B)-U^9/9͊}&OlR;ކqm SPbQM]=Ѝԛs1CTIGwY-!2(2˽۽QRo#jFjҐ DrƵ#tMym^K($dff ?#R~ˮPz.VߎQ~] .?/~Cds_Mjqff Y ݘԈcˍJPƭ/ں=Ekh r`Ltg=]h4l[w3tSK(rFknz=ΒScFN^rvYB[ԷP;wdacsI-;g{ʌ{0"),)P^dC@-`L5fݽw1Z.uŚ09o+!ֱ,y4PNr[O/?u0D~(iI;Ѯ7,˰QL;Yj4XP6e4 l:d<g\y[v0PhҫU8-y3@ndtE ͤY*Cqq W2QHu".>U%*B۹͕~|% h11oUq/ޝmfAKe0A)-?l&OׂTevWkxǡ f wG | {=E<yK"Hj"s|u"B1@6P{z~d7|aD(|{C6GqB?Tprջceu\ 4T N4 w'pҙL;]>ZН( TM2?*jzyO#"7-&G3AŔ)6ޝ`̣*p{}M/:]*jM= [(eDbiNW'<CIL~@ck'oe:o^[PL;Yg{P\v=UIw# EHߚQ/ȞlNesX(#dJ\R=;^fh??ʨߤ$nBHZ;5pB^׏ ίSǓ&2V&:4`h(*WJ)qP+Nۉ8@j<>k̕3"5oY$h#kwsw'kt;AA),;`4sYNapvmvf5캚x::e)1%\'*okUn@!><"QHfZDp/i"c[L{I9 a֝*sKa"DwۣcACGM/ IO=xeSEo_1Cay\d&Bt% }68*"ghC0ͨ*Sm>:ȏn$_OcrPhVNKUZ/Vyk 'sh,q3^Eۍa畇9MlfE\fAΧd0yxB}iu#E(l,=HCk q}[' əP)E+,.t=wl LKӔȕp0kt8Nz} u59w>?sϹt0)Iuno~E㑟(y vJ:e*k No#؆ή >8I-m\ )F} DIe~=OWZ唨McaC%f }"z:xi[ xn644ћUL\@Z]>fZCS/ 9&4٨ p+Ms3tp`>jɀ=#!Cix}Jr۪ dX/PY^%=V/WNk4uaUv9cqrR)U_L$qddKvX=ѬX}2۫JIE&E7 ylJO~~V/7'hyڟ q}s:c8ygj{- 7*^>H}\/Pì}2&N$6]waRRUSb`̆N\? p>@TI` G2TZ&s1FP0Mt3WFbZS)gӔQ[SuUeNiH4AK) ymR]jzE\!j)]pT:}4sVh=X?V9~Lcy7,a "/V m$Bѭ~ 9-EKFL{_ކN@85&hPZQGD3&ӁeD(GVU'qQv`Ц©oF {.K y/2%,J5VlB23Apk-ˣ$Z 4 s4XȄg㲪DU U#Iҟ<B:2 rXGB!9NPzLf+䉑{Q ]Rvl> 4nUe:g\&_Sa# MͰh ӌk "̑5fkV>K>ݱR'IƘ>u.e- 7n6 r=l9AecV͹@ڠ0̭PLfg漺\dvS;"fE5FHu#w%8.sqOً88^PY63 )8ΦV~C-Ds>1=4* 9Z@\vkߪ @ fW(7!\f^W)W8&(>UV%PEWcvxnsQ}aRIym({G[-Ӹ߆5gETMʏIҴ[ .ﴼ!GwO94Fȍiƛ0Wb.[@#=Ybbu&I(B#S{|7dZP+z厔x)47HjY;1|3c@xPym֬Q{Ox喃enުWTl @qdZt ^e\p\iGR}ad+R0we*o[ ؅_M2[?lm`-|r SltU+|2:-3fۼ *;B>&BKOUkHiy $$ȪZ毬&pVEZրe֊R=uo?eVmFHwf+nM77+ U * hinT`(2]~Mʠ`.<(:4N2Mn2M:ȿ.Y&w ID(nPMDvPG|'kF1sf- !hO-&Yn0_8 j2=ʀT{ hֽiR pѝʍꚣ*6zѧUEP0Cta8A&a2IOhhՕ/B ՘\%ۀR Q fR}7/3b_1pbjXls,a@B53K `]E{LmT4.yh Rޠ-jR M4}OOc[' MuڬEԐ^GiC-4N}tN4ecb8M}t̊XیG_n -@4zzօvNՔ'i㭼yըjxc͸x2X2;v $o?M0` nӰ#fhu hIFq*{38ʐ~Gq]ʃ*0AKǼf9Iha:-EuhׯmDQBh39/gZd̈́*-==V]ZUT9.kXX>ypNd.ku6Anu6ej|䧭(sGj_N\0w  m*b_V6$~$/$ZM.hyϩ0=m{TPl )l5){KJ%?rk] LoӢ4)T־e,*âY}|7!̟3ʧ+eq/XW5fNB|*Kv95Ͽtr !Mw迾 \'8i'M!OyNedrpwDM_TB>l,+vb۵/b,~QT\[綉Gs}㰧+ɽ!Aq%7oQ&OK|'s؉x4_ZF&rEKQym R4E<,S%(3E1}te>F2f |>&9jVFx?N˒ N=al5=Iv`g0np9H=/1 op.זD6N5VϧaQv^ydJv[?-uørX+tg  |2yf+@. UTs r`Q*Xtu&Y9Ѻ$F31ڔ+9UO|2u /+Nbb^J(NI>G|@=4gXuҬg8V m 2˂ջi|[sЖt1]Vϒ"vzPiUgi؎pG`BeV|pE3h VycA=~n@efOh D^#wtWڅ`e\gE34ׁr&شdgn`Od(u e|-yɄ$.Ik;/+{7J;1/(:,d@ʨ?ە~ EEZx&jf4,٪ZEYc:_T]@yN|,( ^ {=p6-#4(SV);~<`1Zd$(+3dC3/qvzmF90 DpNó1i*~f`^'qe@͑u6`Mdy 9@#ՇŤ{M혋n(XNuye;Ϥj#2y$jبޡYcN L[(g3;u/OS"KP0UO&utP@q}L~36ppM|" hVb-fvX2Aj=|ɒ*W7NlMBj'eh\zݛE: ܴ{) [ Ė5Joy#ygxĞTتn)YjRm^3yrƆ~L@[i*~X>Km!Ӹ2p2UQYv m/z:ڭҹs6D/GGYb/mw/eֆ fNEOskMl3g]Rc-o'@=5r%1%lZ[sEc5lo%3uc}r:0*HմiDB﨓}$~cx&T:w/5:!mAϧ*[zK4=fTfָv^B:ݢD-4#عцu ;(' ҉/ ]{/m SǠ$Loa?)2?c;;T' #M_wibӠU'g莅r) ֹĒs2zz~.L{Pw7lUbZGpCSgʐ<\q㡾Z2J+(""vstkSh/EՃ\;<ՆɛII524|Vn KUU);$r*<|: YstǓZlTw7Wk0iC|Bkb?]FuI] PaЁeXk0 (_`Eb)PF`;3If7f5ȱD?(T+;ݒ#zmYO^CuM S/Y6X7?[1 bUסuɄMI1Q38'XmTBj2/eFnFE3'- :N/FL|YRڟ3~`DF0Uι/s2ZQk&Yɫ J23n<0|TTo$uFKjfFqc~Noۡ)R;uZ-*;|>_a/,&;Wx3^Z*,CoM| ̆F*E_-y/rc2$뤤ke歈~w]Y$Vn %e;&;jqGRLl_˚=^K1YZ'~wٞaªR^|14֘Ӻjv3=^vibfo=QcB"d[˛xEq؈=sqA9%!>R'þA="֔;8N!Ԥh eb##g("3>6}#Dg)@5z>N] ~8㹵0pl SG: 9UEQ烵Etx*ͭRGL=/BRU)qE%6H`.iW! ]v4rp$$화޹Cx:<8 (Iȃ;Z(0bO{?aAVde{?\~ ]p5x0  %sByutnV~ݫh ?|? K 3.8V\3A0nU[Y-^٧4;ȠTE{%=E}l0+k<)[Ұҳy(0F ުԇ44qbOhqQ ,MAy^;v`NGZpհV_safU|.5R)_sڻ\ֈ>+h';G5/Ic3qa~L/fhKGuQhӢMlmvFul|n;ynQ@z%؏RxYc袦c5>GfցR?8]8g6-{.y? vW?,yEzuE_Zas7C~xsd+i]7sM'잗~c2݋mvӣm8t'}U'd(~-ڟtwcrNfh)aR~&̹0`XJ7!5vn]M7Z6z.Q0R 盆]З. R>O&|m4҇.Ta"ҋPbڭ)|}v\ZĊiU6Me'&rgSPEf=[-PyvgR?KT]ze2i (X~1 ) PzQE1 OYdC]CBhfp: hnPPYrGH4//@2FuXHK(B>y׼1܅zJ3K1biӗEDÇ{Cv=$,ZZE4(o)+ hVʧxڣVj֎D`:K), 6G"Lu= @ 2ntiJsPZT`7|lJ]J0 ퟔq@yb6AG.(#ϲ~=m`:M`|˒raXʎY4TxZ':EN,uSԲ,kSEI uKh: /e\ZT),IeY3F_quL6y[vܳp~a5o8+zw;Ţ%(VǾPfpAIFGA|K 9lp+K1 hNE ߁8B=m?]ZASl •1\Yp.?07gCS)ۄg#Q3JKCH+Ow,=2䉔rDo=ȥu:ۣ: `y9ĥd4M,eVM\ yٽVejb9 5DzvޱNJhMiڟIN:hIN'c3kr P,ᨎ|M+H6CϰCDD](L6j3{CBEA"T+ذ!lh u$T *UĞK"S9;pii$97^̖wR5 @2崖fgcd ePZy9P' H+Tz??5߶q7cLUrS|9!;e/O[sFR?uGvS+mCxfR15!(nﺥ@{Q^ ,FUR^ZCnDhϦPOg~mn2_$ي72;(h<h80 E;SA"ddu;tj|rPɃzuڢG bdhV3WvLㆁ :9u6,g|tmʮxgV$ɧ4զf1?ň.8^EyJ>sMS1&.vɚ@u{Zbk}<M|$D $%2((on\':WK;ZOf,;c"*B.NRY'?]2u*_Ѹ|%kdOB6UJ>t+"JMY?sM8:3jJ{gL 1z`5q̺:cŮBszN*OM[[:HܰOR=eK)''x c|(cH#!gIe݄B ђ8ρfh\&'LY~&eU}#p;$E{=?a؂Ch_hˠV;Y!@:}@UTaeMNYf % uhnig:!ŢfCQ߉קQ=2?M4w ԃ3[+9} wh[j a-uN|N4PJMTjجsAX93eyki?b [=:A)A'v Z3Aϵuu5l 2V!hrxٲ}2l 8%S 3*AYє6&c jYgwɼxOn-iyz^yʕs4{ם'Ϧy&$-;wu\ v2< ܁J[F;O$Le Fo{{"[u>uݭbL69v~n .V:[ $+ڇy~-eH^y/?͞-m Ou^d]ppO׽t;ï`"Ongn4 ҸiKu=v/BXh3}Z<[-3D4A4ݨtDjZWL9 pШˢ^siPP!*Ldqa[4߇hXUuHW!dq#Y|q )OOLFt>FgX+Fa˜)|Rtv$+2$Btx$YB|D@joE K7':x_TOzm``(^qI@U6^g6Ls?,& Eq}u3a?*>Bpr粒HTצNu6(APhQTz>3>Xc-rZM|{Ab\ P&vN>~x09 C[-Ey枅N;7V{<^l#!a2P5٘xs/IBsׇ;j39ݱiY)2n>Oeʌ"ow5b|: c\(x#9^y|*kvym GdِžuvmoQ2Zebn-wX%jQ7|=B(bTDaZ烞K*,Ch t.]ά9kJ:הU>֋R=Käm)ρ&΄WX)/9O߶ V.Q>(pPIku>_Go?tAHJb;`X/hc q̢ ܔ|Z^xp`2mCS{N9^AeJq>Xj >d h{SWCXY /z06x͉y?mq``:|El3&ЄGKj^s*4S^'T Ǭc0RVc 5)OLm76'hNҼ-s1 ΪZC\+>,Mw!O8~O !)Z^wRVɳ ͫ T6%MfJ6U-U_U4rS՝~ӣ˽ nmd:Z۪Uzև s ^\_32/zϮB reZ&qUm:ݢ6_gÊT'Zf&D"@ ChqӐK(,%. JN;.AWTc}?q/ܙv7{qbõ()U1v iD&fÿu7>B>#M&bSP]@x~ѼJ_S2'N8\~!8Wnw *^Q=,(`pN-k&h__&ꭆ_pM㜴S,Z,fCCGwfmk֧! 37l)3':*ڇ{tgk_f ƑŒy3eH4 x׷si 5۱2P_8̫6vqq~ 4K<о:2?Ϸo9hW@[ih((k`lC1TCLH='HNzbqjmC:B}үDzuKLvVȦ Zy<,_!W~g h6tjy%"{8jegGe|$.E&8W+`֔dps-V'$t6ej1@G#7eǾ*T,-b4KSs*+|s1Il JU;& jD /U;0iuk0A-Ֆ -]\DuN2,m!gvBwseUF*LdO$Jf{R i%hl/6M<ꖿlxnbӀQekl_Vٖ[lĞ꿃;X(tcu)'pp1c Sv/ʦ t*1Vq Q7cOMo2pc ajK!Y1 N;zm8uX>7!o8a)s%N PKӲnsۯ8(.XMN/̝\kwVBfl@lI%~:-֘'il) jZNRKg84(Qݼӵynj`|=jλ1$J ݃WV^sˀrɛ/ݖH&zWW&LߝP@ۓĎϥ%wy2$FL6!qf;N#'u_ 8[].=ԚJdlM'#2BӤ2J@<_22+L{ڒVH޺)*Yin쓏~yk2Kpe_lAѭ~oVM,ÌNEkvz}tR5/yp\]A2@fR;3}`PusWV[G[؟_?]qV[ cZC q—0NOʠ8+6 e궃m)=l.|VA,n=e*J[ᤪ Yv&IgHOpUAz x'Xג1Y2nnAPz<2ĞHB :3<ѳL7xI w@gyUݞIBEe 8Tv&D?FdΞZy(q?ݡ)toZ Կk ٶ ̕YFugC ކ)ءz6k P{ۧ#PN]W]ăH5g )gB|hn`q })Y*U^hw$ar?뒽2K7Vkd6zuHo2,cvCN @Rkr+0{TӶeS'jgVԜ/2|Fuu v& Yt$n;UOy@9S| Eyy>oenq `1U&|wu.>5b;IH'mcV:PC=fC,_ALp;l<rU%j?.2 U }{&˪'' EdwZDԤA_%O=5}nƼB[lThVl#3I *L?Ʊ/WN02q2.CQ7n OXv t *Tm@LH#rr"*m P!P\%~p?}>i:t8/ϩ%n ?` CA)|Ώ|>_O/3p.GoyEև[R2S- د>{^R yЯ~ku5.Z"YY-GRr^3ZbR8KA&e[]ҊbEmZ~6{:Rӊ8KpmÅ)xr?ۡw-4";Im+I+կPr.9NuoP ]p)Axy ҩզ}PgM6֮-qJ2aCr H,)veǢ;s͊~l=Qت;c"Vnz?eJ/A`>m/H"YMeZe8Vw24u͟;:)ˎ>!Sm6}/:.@gsy}knc3`o9k<ҝ{sw}ݛ]=m7xIں;jE6Qa]4Oi.{ACgEdnXtE&A5ַ\=OnmRaB=!VT("}W3Y%]sU2RbvP {a ФXt\~>*Z%7ڒQ&HkRTnX> 2ټr8i:-;*t;a3j:Ct$;IڶZ\s^QX΀/}lj;PA=0z7fBMb]z&v-eh ފgqrӻ3͹`G]ߌӖN2T/A)U<ys>#75r`E,XfC0;poevv;AJQ+{jiJ\v> :_2Kz m^MՆV?wz<@ik4b`T3BnI|d{NHLdST$s'*A+)i3t&= dI_W= Ft:5~6,>,-TZB#B?ۤ83Ro4l睁>W#أgYD$I<)}M.'|jy/V%_VUdtEy34q'FgySp 6NtU? sjrWDDO nBÕ.-^1u$@ oݖWKT6LyFY\E6tm>hr F^)$I.?,Y*&י1,c{@O1:j[<7U+ !j#_L4_o&)dN-}t>BeQu٭Nh=on9qq7ղ57`6Ź_/`; Z}N,Xh zG2\PeyasgԛGW!u~YS ) )+FY}wuT%Lѳ~~|T-(Isk?%R}X\(:J] _+:`bucC`=ذo槞țob3%KuIBFȂ>LLqPc]3̷"1{CI`9_HvGMGTEg,5H:|6:$?wL wR 2<;V:ϛҤ^y tߡiVw>!:Cx7 El.cH7VVj-N7rо.fץ?2+n [8]֡(8L![8b^ت͔q/ Lg0LE2Oמ/"} JPx6]%Blv J1+6o~[Utaȿ<6m[/9ÄE#2T5h8 Og˱6Syh\oNxm"B\=cxXi[SlPN D" yʂ_\ek ]b [ҩ_ haf) 'wiӇ-yen8tbIq%x;\61;)cof =L׷q㆒׸}˗C;}ERL쓴+f֤K㧠x\AЃJZUwZIǑ~[YPaЇ4ry]UKhDy`꼨|5k@6Nΰ;Օ, ,@N9' h1^3T Ѐz@]jW?Ԣ`[kA:PΓe{ n#7w+8(G,Ϥk\i*ү^]b$z?kjbKM}Q[=?SlFx깂ִTKv}Fk_fǜ9 { D3[4ekw)YUQ).bZ7 O{Z{Yeڳc kfUPVL9bf\ð1gd6ZH6a6b.v۳m3Mӭw=Ko O՗x<%* Fc(ؼnUSaqsPRЯ'#X])aF3#1dXB wFZD|*Y*'=tN=H.9fy2pojmv|Q}3_cqѸ!.B$nDɑ3.~ ۹yOUq 0e%7;K0#1L%my]alֺpvb7(t\D"ޟQ&G2OEĊn1LGT`|$x^VB[Z*|ҠK,l2%9߲9AGe\k]eGr y(;^C^Lo)mDy&d*")QCLm:9 @dA0:+_RどaSӟ ~2sϕpEa8M@M쟣r_&Jg[e38wQ* ‚ ]UUelh!oiS(gd#Ȧ{ZWi]y*,uZ_D~`ut|3b⁂vmeLVBKJ zV_SpmQߜ}g5F4N3гy}m;h=ۿϙp -q{ީEآ>MxnjP\TάsaM3.eT>9Qk4i5k96*fD<ܠ*E*u77;|f;i|lQrUii?jf"عnu-b>tٗeBFvD$2-qFfe:ƸOl*ݖf!Ho K'ӈ%Ï_ղ$ξI^Ff4.pT:G4з}KnjSUA@څqwy`FlQl\:훫d Ծs'C4qR+^@]#-F}{ah;'Io3Nnȿ>.eGROC"Ye 3t M#:m#fHQG\ 8RS(r^on/(4][Q-d9)x;}`'x:W:Q^]w/f_ɥ~ԚWVcuc֙14kʅ~^gÌ| ¾fe 8n5&u/]e~]_ZؤiJo?У&xƇޣi/:vx %V{?58yHDNJ?wJnT}*us;6R:x.5zHާd_[8t2(Շ6 k6ǰ fSrv!B|B|- Q/tz,J.tTmVi?SyY9%(/}k9TqL="[Ts+bx躌  fk}>k& ~Z.Y 7#WH,vva')3WiZ (pI _N8CQ,[Lo(G(۰kEmdqdGgW{P+Tj\Z{_7C#|YMSᝮ!6=ZQ ؈9bwIgMRKsS?KTEFޣ8|A Hrڭ,+ Id>;>G7J5q|?:$0T 2ywn d'.fqN%k'2) [-yg+yӋēxXrZ)r׉t(}ԭ-(s$6䀌"je4Gk2}}EjE̓*˕w~dv9 B[}yVr[g,Yɮqe=fDIJU1=I꺓}} a^I"ݬvr减ge L4D>v)WNq{CõRvgJ^bP_r&3McۻͿ--uicl<˩noYhsI%qSC6NŽg{S^ uV[;<Ȑ^/%hBWP&̷<[(~`G1wm9rEiOހLp-\]F)K6yXoLU:yUJ_m'ivjgT>=ج;JWf_^*Xg GZ{'~ -ﲲ|!.Ap0wH9d4Eˬi܆2|#f=*x<4Ͳ4F˂G]J.= $9dVA 3,2fY&,l:I:ЀBEF4I%"J[Ѳ^ӶlVWMn_V(]:$-54~~~(^gD2((۷{U(Tų<|Y=0coG;~ޢ-Θe,RNHQ1,jΕ0,DzΈREۓv=Xj,%dR0-o)= ,ܤybA ɕu5u%<쐖kf5U=/Cr{2h^/-`vi6|8k0,>X;m 4덼I1\ї`;wVvb๰=!ZYX:+y{ƝZNhg w2LunYɃ}i:)$0=8>tsOe-ISnPl웖$~3ڪ-(W{o'}_&VhwwX3[q/qJcʅWd5wNqd`=%(!uB9Y2>UgJ 32wRi,ˆ͓6{0иٔ1~<]]N:٭3q©fN9N C ku6B܈.'+Hlي]%nh:zN0} 5<4]7y~~G5qTee6.R^3U؉n yE۷a:e#6{rni@r4ü8)YufBيlH#W(p%i+q1gPB)݊:Hㅁ*k9!mZкґ~ZƞwlŢؑ$fXc4fMY#I ,˴c*"5,ub2㸱*qwG-# Ds<$CꞪ`4-gNS0'Jgn9]ʮ5ߝ6紊 qu>>CI~wݛbu>tѼ\k%s϶MDb}3p /ۺu⹂(Q]u?[*,,2nv+̐U/s.4}Ugt]s)v DV})Qs{n0D~v?Z]w~d3k&"ERKfld eeaTΐ,<bۋ>9m1Cڬ L#²n=3=2<F, KD-+NUʢpLę:s+Mؘ3W.BeD9Cy/<ڃ:ќE6ʍcI M=ܘc{aT@gG3Gں _,8'.18͏OX,-Es*F!qcܝ"N103E'FY[+,DhY?:{Py3IԞДc^c=J&~\P^Z9sjaph1x GHG% 熦 a^fa`qU;TZZϤ-}5c*w s!<ǃR Z?'C8ԒDW`fSD JxCe|W*fpjZX;e g/A,yl@T):r8= 68`gn~+ ˣ'yeoHۍ ʏ8"wӗj5uy~K5K#;3tLjc(it MʣX] ^)GL-h^~Wm <));ǣcYo͟k嫙%i?SS# [dWA<v_X%X)cK1]5Wh+YW&^}/*\93<[Lg;.Dz ^ ѫ6q=*'UI<^[G.Ffyc]V4ҡr 7?vits7?/sڵ TT(d&3L:RU^Npw f{?R7it+:VeYuI.4LÎS , ;?6)s;r[eҝN(kȜQc3BiQ} r| ,v~$Ɨ`N6A]~LeFx{lPl:‚Z$G?oS"֜;XhMXWk.ߵ- Tekr%9J_*IAk!b9LEJ93}*g gbe'pj7p&0܄JiG=+w/H(ɩfP@RN吋{U^1/QQ*j CQl&1L?AZ3<bK:Po ɻnRh&r QNuam,CI͆E[.՞vNa&U ঢ়V?i%f9MASp*>hX;ԬӉQkc.ͷkmďSo/kBwr9N?+~eg6FU hT_< NY6w4AZ؁$YZp1s|jPckl炈(,?X\:#hNhuʀh4ږ鼝š *!m|0rIR֌P\>G!3{ɭ>G1w؏.4Hw۷DcD]fYɎ[>t\ 6Dbf7FsUI]L?,1;*EOtvZsaIt%]SαB kC.yκ-T,y@vK"hZa$s^'|gK-û9xP3[@3I rI6Z/FemwQY9Om5I9S#/fj!5hZ4YcWU2f}d&mcȸGUc߅ l?zǟx SⵯFUh'PI6) U9w_~(W=m.3$ ;l?4䭡&fkpB^:COb#>&YQ ; 7ImUs✶)2=ְ@F8dH9DVkSsa>0l&LI9SZ)KQYiA]lোy45盚s^U4ZO|.{]QnXx.3VbnV e²aʥ+~=@N-4sag/ǔ&~*\$i6/AciI*"+=(N vܯWė겾3te846zJ;x'd!"KWK sY':BQCņy^48,!(kE[^B=( ZP"Mh~P"oMO n*vW8a˃ |S^zag׽)R*2[2f6߽b-|ݝ-:v[CʸDvʀ)Ye'gi >26sx9X5]B2_zF#Tm(uoSִvjOX `^-ݛG[HP``BmmK&^A u4\:^w227[O9Yf\6\>lyj[mm2ylA!d2%+Uܓm!9HG?k z5ny~:KΒTv\+pv{`(<}",8AIg[<ֱ*E;?c*xUTufgilmv'0\ YGidۛ<62(L*ķwVeqSO4-o6=$d5&|'h"_9-}LYPys;?CYaqO‰\ nNנN;L惿{Yv>pT}ygיZFPoPi˴.@1) ]—$| f4]질֓G8|q.זyw\%t A‰_+9x{]ǃ*蝹{ŦT B%7WrGMPq2E'`fIvj],;޹x/cL b>v_}&3yrFk4=qw oX{ f% N( B} ytzSŤZ2IY .sx,TڐѬ3u}n&%$KvR6b~&=J%{祭孏5F/S_j΃DgTФAG# nd'L؉>3K{_a.ţ4w~٘{^dtcnoJPi߿GmӺ2\oiC(K;;.d\j鴜3GMF*=@Ayh!|ꀖo4l\w}n BÔẔ%5.^Vr$i&K`9@/Q^FaASR ;y NhX)_eKo&$r1j=u_wgrlv.GBtΎƒގ]wQi <0Y.اh4;~tK(1\B'FMuK,<iႆ!sNx׌*mw-*ށ27kNe XAnf0;7hҞBc/lͣќB`J)};VjCj:0ݙbt=E!PKFyn{tNYEh76~zmuy脕AᤜKNsYFεMs2E$n^ak:uW}2a uU3BTYPSGO:[ ;t:hiNt7 e9+jNh*nYոҮ^w@EA$SיP;'u(EX'w^f1@vﱼ6 *nu&S IePdͧ3%FXhNg{"׼uX'wbC/:[Um?siߋN@WxnjA-ZiӤ3iyX<3+TIUtm,߬=_V/4t&̥uө=qG*ݴ\GFPw[د^rt&42aTUVum)Ʋjt?z&%alA2/2;m%]njLR61BwxTI) =[5MlO |ٯU%@ߚ`7:5Ks#qEvEdB$IfX[9p7qK\uڃH:wZ(=p.N5هO}) H&8!ϼL} ;܍p&V*s8orGnq+Z܆9&H9EՠL9\QxH6r'}3M" K._ll^@zP0/|ЈJ[&r~8R%2֖z9ZJbAӱX=EߜNGGflgy$F2Og6l^WDy~fM^Y*zb -7T"ǰ_@_ŜF5 e-5n{ _ {a伕 sTr<<kb-mꈄEy?_Y_yPQKMo4%g>>$dl'n}m'Jzl8^\VQ;ظw.zvMb*8 r0H-vN.h(!Ý<(cSd8ǡ+~3߀flԹ,83JڦU6~ ᲌$K0'[W튊Є\T[Ck\dI2EZq?- ΅Dh;&A9~n@AN|z:J>Rܤ !I$yHm{ڐ.!,ԈP#?кcx~-MO64 8/"WV:{7qͥQpZd5Ƭ|rҋk2sbCD΁j/*vaza,$Yd^̇OhƱǙΦcI j88T}]myup@\s>}k<c@C h<'_uʖSb3MG]tʈoٱdcVK?K֊s4״]ogGr.n wVd+vjm* Tp@r)\:DA?"jV YZǫ|*=XάT5i2q:*B$۝|n.nwCWpv;,wTS*װ$:ʒQ$u/~yX:o^f: 1qT`Э,飫ca/u\v&^Qabӆ|0O99 )h|i4*dTi~Mu,w`ràq]їjO~J=^qq3DKOKQtYSAeq{5܇u6P]Qbĵ3ՕpmlB”f/k^Yqk*nWM:?J jJ**[&x s}~2̩yĚȤX o:XdWBoϼjKD͖I߽IܞraݡБTcImO_BUQ~BsIEܽԸMlgPH5'֧sƳFiÈIΗG;=}~ix粥tH/J=Pv hx? f]v,A%q4;l襒"W@"*'s9d@#~̫6?ea ɩlr'y8]G61i܊IְCh!^ 2?E7a ]cg`ˏ,('~""a40kjY *=N4 &4{ͼ^Ӷ[5ߢ $FSgubػvy`s+2xɑ }l;e}I9 Y*aR8R塨qƌ7Y u(~bհ>#g:_|fE6bz@oN=Oxmj&k.I??MTEaK8AM* ߷ZP :P|UBFɔNs]*e|KlL4(䑌iY2-sNuU ٬ȉ7 tt]VZ -YH|xr.9o%BODNJ 'UfdldC>"Y7:QonLɏo~l=P 6 erKd+jɪ|3R [k3/Oȷ`qa=X~UTt<2qB6;>N-3Dw FȃY߭ % 5Zc۽,"!Kd9f@0oXqgU8Aj$IAZ[E8c7_W-3dhy,PU U#-{oBbCJJ&t%g7Q j6"tHnfshbt9mu4AYb~L(v/{~Z%#q2u*E Bm`<{Iw4LXbFd͎)*q Y9X҅f/st* j9Oh`LCm%nS,'\p8<蓵nye$o#SO@L]d4LNe©ܵ H%? Ú*~cw-pPe ]]&qyEr{݋hm(itC62:uBI"3-D^xh-UY&spSʋ u4_MEOOP֙$arhwGwYd#5Em$.ZM9h6反7r.Fbba_Y(/KiG}5/ImLAO\. <4jz1Y!Vmk,s'h"^yʓoٕɟ;\R`E!ӑ]D m5W?28'Nk^|trLws'b,1L:HB4 }T[ ˊI}s*OtU"g < {I9ӂvo&7Mf2#DȂ>"%#+ʆԙ,ri>`p?]kC%ט<8 BNM4~iY~p֕?Yᴷs֗F&r(Zz̜Zgp.-ۆ~IWX3I I /1"3Nm446|Ε9 ة<&4vJ޺h؞]1.B3{=ϋ89=-`"cнMr.ua:VWRS9@ (Y0'o!l4-"\e25V0L:j,FQdʥ򡒩ֈ}3n=PY0x1#0hߑ&J yRZ j#*Eʼn-,k9 S|:|ie..aKs<~r,If|84yB4&jM}3ݘ)Yц n ŁK]bcolCdmu75V>vrs73wjqQW=0Hcɦ> ziD3ociW9eN6, gSH {N YJZ#md<î6wU^aaM?=Ǝ6_'~J<4U /n]o׫Y rJ=/k$X*=:3N[^vp'PԅIU:YXnKq AF}Q8y=iLBLB;8٤z[8mDJ( ZoKɗVLp[L_Zjhfx21?$u&'س[n]ڝ_QR R~[ї]Wf~u]QT~w\uxf1jA\~p#ޫ;=dtỡO|c ;g/S$;$Xy@ ,Ks{\UgP ?,amلҔ֓`ZXP ɾ׈}ҥǦ(y cbc9jGZߑU̚vGٶ M)]B0lͣ.ἕ\6<;;6ŹHxlbM0js6䜃*ƃ1 * 1߻YB%N>c!F9-]\[eȣ_m)lǷWz|޾ߑ}ղt4 @˞0Hna;!/T Gv;[V*A$X~3[ɋC@z^3/_wDvSd7Fγ[uWҸlT\zm~LbdtQ&ޙPOuu;\ʁJѧ%a 4±) \1~ms* 7xcpt'~a\|<|z͈?>,"QO-PZ{mA#CI+mE'F6߲/;lWNAAtꄪ|Ox-%yo<_n r#_[!{:"4;f^Zg\nnoРo`\["|Z%sLݖcrLޚ/qOzGĈ|Etl#_aހԱʫ<1u F88l^!0Y/-"~UJat$ӻLkQJ!Zxnw􂜸?1s3j$%iqHcX/N׺9\&S9%aZ=lP; ឋ^B7N7*"H&i]V=1r̈́+8Tvgel(ss>ʘLl/!;L؋x+_jC"nC3D(8H/3d=8X[V'ζ $`^ied[wxɇE8(mѼ?ðu+-~̜Gtud8Ѓ 'Jn?7ML?HkE3y}Di8f77˻di<, zl' \sG&3"Ēzt )x|҈I>)BCf_lW a&L)__&?qzm,ʸU_tJ9o /M-犼F~hoMhqCN#i#p(|󖩵S`je*GwX-<0@ӌoZ>UGMQ jAl 2yKK|s~;a4케TSdqO6_IYS1@0ggzi½ @  #[) U4UE,>?c0.9 t7"]ZϠ ޔ/%^d>>BfE'E{6 Z^T C]j7SF# ]ӏ5}Vş,1t&r\R㴋eB)kzH4@{М4U=Ô{ 4Vۓ瀆fO/aX}$)O,[8P{a&ὲl! & 2T64l(w;q ݶPTܖWqJuقtMh*_e ^ 7U׹~_)z[C @`Y'r`yLNfj  Fslb y9g(N/À9U%:L`bsr"{Zϔ;4#0/&z=: ;*^ex&_ Nw,/$kev+q;V2QA+ܖ&~;K4`a{L*׼W9ܰW82yL7# zHY~Zh?hML}CVmf5SuٻGaVgݰZK"]RW$!@g잻j4_qlNYy߅ k"beOs7Z\^``;pY7B8D-з@̒?y[fFs!O7feYe= O  }ܜko~Œ7̃u#B8qSo:% @{hIt8?j9wVߥe;z, ^yBTaHJڟ80cfU|-sW^sn7fwe]i+Wq/0aa~# IǏ p%,ф[Wҧ~*%۸}=>Ze4Ǟq3nUC]A#H\Q_A" +^&B̄1~ߑWdf/ŶdgYȓ{2 Q1,3H~UrɠQCh*Š,# p Lސl]kO qb7}囜L&ڳt";Z7p'nQ.#d"^NhܧK)9:b֭aw=Mh1^\>i37/vhH﹬Y|a lx7c@:$zWLz""  V+FWv_lV`hH1(Q~ܴ@P襡nWE}+LW>|plQק6̍=m^wPXzT:,_)yhltLmFI0YTo H'Wk7rbpվ 'u0yQ^ԷSkۚ*$%3*>8ʶˤ\gbuŅ-Kʪ1|.PgN}+_}H7GI7KF@lսBDi2^e'-`6$冻\Qg<R[ Mxx ܢJE4P*\&Qi1;bV$9t &.lLUX p\W ffEL{Jwԙ= )S4 ӌ&v!a@j|)f~|l5Q8~O .)WӼ2 'Ց _huuN9lib:R^]`zg/lR&e CY[gHI)?5ԘAm= BYOeSA=:YU6t,( RO vTmDudҤZuA4nq0¶r݂^r3c=Rö&v2b?_h"-AZe#h2 nP5hVQC2"d zpwwK2|tt*;e@ts :xؙN/ξB~t tx s ]TFxr~RIP2pI6*dpO4 <צl;<Ǩo<rؑ; js t31.< eyF +a̦LKy,{੎A& s Ѳ>m~QX*#5yt\O$yTfփ]-S CYO/5Qd4_M12Yc$l49f>{ Ș#}v3 wU>֏Ýmjҏ|fM?橳V2#`o--+81a=(WF듲Cn7!š9@qչˌߓʫCP.VLYٵ( ~vVݧb =2 dCōZ4;/4t",Uf"1ִP1]d܅xtM ` \k!TNtƟ2mBbwn0KUǑ#΂ax@z~ YjWLύǥ4rx$UPa9KؑlJIwy7?R_k|Z/QZ=e@XfgP<࣪?z&U⫣Qb#u0jR"`z(Ei!4=mW'/i2_,0j'jM*bF|^v4H?,Jz]@ql:)j*oy}`GPH7buM@-{$\3zٵf9GǜQz?Hū>&uiOBo)o@ofãc"K{0v=hȍлbVNJ/ݫ͜7㖶p8:%ʐ cr30i0Hߠ ٮM%6( xUyM?w)*yLd{R(LR;=OIc{^»Fi&KM~^: ?Wi^ Yd4| ;vԇV" 0-Q@L'd'f`$Fo8jq|x/}dH!Sq-w"(FԹj!a]Oe:O }ږi<ȚZsi[޴~iӚV„6~!67ƕ<ug2̻V ]&{fGz=X`Eo4EL[B!z0y  #W|Ye,u4] ##/Rjj_lU7i&XU1.4aVEΌK)[ ~ED-( lεQ<@D ߷"8.t0 my`l2GܑU5h 檋\~Dw83 YsaqaA܊g3.M?c3RNgh0++GoYZb@k oju8Y^Y*Z:72"?cD$%׾>BF71xlI"}({ zσL|`[U/r!D8!7[7ZxY7WG,󊮋 M9:|E.(GL<6VE0 goj(?ް AR؍:`=_a:Uٟ6R}!</3[CcFxWfE#Z?YcH-W;8JkJF]eKpud^Y( /y'ְ %p\$^Z^8%:JmV`hA^<$cn5X]J 6e|ilp+Ƞ0}>ܡ_\mNLXdOR{YҀGk[{Jud.'4 D;PdY0W8NҔfe)N:`2ͪuc~[c.#݌oe-r&b &9|Y6+FKjA[Rh6yQEݻ<fO̠ 4?Ô-U^S*>{C DC ]s@4GxIyDɟQ'Jhaij`>0 tFO/XJ(砋"IxZ2&ROwqQDi pw2sB],W*ݟW@s:_7HboyYV4dAu2#8zU;\ ezcR'kUe&E&d eC) ~ox$mqUD 'M~UyW,窝^16D9|nmgib)Ԥ芶6bFt5(zxM`:n”~B|LrMƿk${L!pV$),'WYsBd@q\U?A%uOYq [|v|8!TAqSE#~}u<@iRu%0PrW$s$5^NT{;99^X5eεK(vrHvh.̿K MnC:9w ]>@OSe~ջxOU}eIq?~CE-~Ci@7᪄b:sF~©ΩZ颹ˈԋ35b5]`b\]nL0D0^eKt@F?eBW#Ͷ`o# UlЩ^Ml\iȶm2'ݨh}]-4涑"CV[o_$w-VZ⿇ɟrG6BmSY)P}DMH͝nPz~s*NB$mHA`M;o;U#L4MMofgᮕ  ?GcrsVaQS =xԛ*mZw1O|uh<. #֨{.$w` $FOO^9ݛU>δoaccF-[ F@qs'ќ[Zy L tܚ0i*ec )oaXsrC%ln ٷݼ '*(w<ϥ &ڝ%h<O$@ޞ6O1\GhAI KZ+qaVij?KjqN\()TpGÛ'})v`շ7Gߜ&*?>wΓCބp n% ^qʈ;.`'69ۜod^r3Dz$ \k>ޫ|BI}ש#aH?>_UʿxS:URA̲U,iڰFi2鏠'"@oMqsLǞLWk g8-FC2q(HY+:)MkNe:\<46ma7_G6m[۴ܾK='][7\qNߠp0C,T_SSg:/,3(z7).N]C$ =" rH^p>}0lhZYu@ٍ57od­S8i=e8+2NcT]ƐucXx/$RܨwD[ { 2s}:-ƸI.za<#wԯ#ۧJaN~fg `^kDC-sW߷a30 G>Y4Nϳ`T@/ZʍY2AboMw1\(d878g};U1~,-Ώ{4=_2]KzBj`eWs~;;ޚ?SwFI)}B4JoTT'8W@;jYd #0Ssv#0ENs?҉CU`b" ̓Qks85 [K)#&+J*hTdLϥ9/^/S?/v$3ci̩?I Ze¯rm` up\VZZ䥮&_e$0-8ӻSymPeI؏u|p_O&_RCsu:#z0T.%!TrGv"' xՂL0jQMַjT7|p7/ؘSlGv)9WMqXivN8Vl*9"1{п嘀wV0 qEp:R|$wK2hqjUU㛥"twfc{!$^&!`쥰{)cԠwp^]`:cњ!?iePW(fˡf햢2}N1$T;%IzD ե&25F*cۗ G ^+zӮD/17}A8.u37᣹4cH20ÜpEP[`_!cu8xMN3zUނQXQr I{ d:tM$䔣!)[l`nU* >4_8 V>#Ƣ17[ CH!/pBX(R9_p31l$2  `3- j!W]Yl,Wew/ʹ. ̹ocM\kV5uW_yi&4hLNhVc~sIY^6-S]v;[fvs1J7Gf7bg jؚ߭2<@BSkD!͖ON5-NÚpm{oˠXnla:kJ: (H^QXWf&-9OyU~큗Iy>T hw9>zr읆3gdE z[@JYU`Lږ>ky;6.`@-+jO/I zʈ;ىWֆ1Ed5_Ɯ P03 $=03]gK⁕ڗ=axiА ʢe,x73xoƉ8y~:&[^}~ ⴩oi~9#zή}3X:Nаu'S"Dj?ª,?uL4Ut~[:ymqQj.AUVD4PҮp/}dНE)2ń?$ ?8{^uI5[ 卙eMEU:2t䒤/]| ˮlDe>\vk8o_`gyրacCsM)̳vɺFYO ~euQ!}0h$WG>9YׯGxZ0"=8u_s++m ЫS N* F``Z +Xn0HVIqv1"1xJ玹RƲr;1 $#K5}"^lgj1 Uz(ay{>L%~ƔaMю^oCy#TT?m,}{;n\ 4'g&zegI/AJ6TQO6nJx (uh4{)H @r2xBC{}p4塝V36OymYe`B&ќc2\^;{Y=lV}@eFp8LYi:oxdo&oޖ$7/%Zj1dqfª0t{B!yJvt)cO(P%/̸?Bhx!ߚ7s/vZ_#h'0bͰo3Kk(=y-qQQ^GZ9\ƞ-BcQCg*?*6'Ԩ"E$FM V | }2Z}7syUR -}< !aP#u.;8nCFY{@︛73Լq<8L~x,3)P0#x+Cn{PB 7CJm xnわ#`tJ&B}w0Qt\S@I*?uX,D)Q6.cgy~y_9Ɩyg|C:As.I '{x c[>0bDEwH,ac}?`*pO H> Jt#LZEeA+E/u_Gwd㝼jM~NrIJ6ɟw2Ӝ؀3Ud2d̓qu*=mLǭQr^5vk+<L{R[X^kwlo$kac3 ?9P툆#=xg:@QW"33n|R8~$=a:z/V[YdAWPvY?Dֲ͑ٳ15*W6023{},IhpФ})#yqS\yąȠiT:aQê@s4/_ =l YM錙M9B-=z{ue)Ds*y U*9z*uTj_7{*JSw+v\O$X{tk[HV )W]rֱȄ~>ucѺ>/majAVYfx(2:ws 7&ӲOM/*c *eKբ{cO}m~ :{XZ%oKB`0AIy룁!: ڬ$+XzP](.'r7S?.?zWt¿OPdzr~ A{uk+WI"=N Z`e.\7BQ%%?(ȽFk@UWaNjZ m;zmCw4d$ ;b̫5 c\q#ĭRٲ#.܇Cz.gHVM}=}(#=95 bQjhJK+'=34ƐIJ*d#+&`,YfY9'~e~n9rlMڹ| rshVv$* ̮璭wi4D6Le4+J.`%O 'NUUTb9XN2|ZCg1VRvy"On:w DZLrekOLe{Ƈ*e"WӐT}_F9pvuO d7 ` _bRUӯ= lbCP[VU!8o+ "oPU^sn~BBiGDd8rS>{ЧìNa֯ZЌ|aMZτ$,žU6ݻ|3yB/J:r?,- lڌX8ECq̂\ۯe]uCz{D>ʌƅLf[]W\O32 cW s7{$q/-%KL #|sgum]R Rd d:>=Jxdh*٬iNu1SsVəvwF,9t.m}ͨɬKLu2D0f[r@lk,ZQ#dŨ7Em R 4ļR7ThR!h.w5zθ*<ڸe<[-,{ qZVabGZҿ jqZF]m1|Ɣ~qq KZw93oo5p觧sjHҗү6%rۡ=҄9-2\G[d(¨ bw ֤S׼(xE:*Kb4fOQ6gz=fM#{S9..r3+^t2jZ_ፁ4θ4 u9*u+*F}on=Q6fg5G^ ޅ-DlF=Edɇ5)P2-o[s45\;|ȵ\#㐋jwx/uhPϨr6 ݼde,RGsqeUMwҷA?Gt;#)m l$G/lRQ[2 4h9 {Nx39,B U8aM5sE{FPDV<ëŃRz</6{e>qP:2kk,a6MfFmx{y{0ɾNB3? l;륺o<r#=jKh6f^+t%}<2فA$#`~ϙ,sB/h&ElUq/lC_roe:O9X )`fh! HKeZҢ3MvcGb."vo{d~eH'ge3} EݙQ'7ls硱GH0?;UMґS4L쨡ѿz3]t'3i$@g4rU2ح_+ }فrK&&j {龭CL]ӎ'XxMsU=s#VvRRQFC9?ݾyi<(L2![>ZQ~~Bbp@##7T Gm8~60s,WTG{lC4FlB#!"81ZB:*'SB 9~jHd=Da3&UZAzkJu4\L'87fa*353S_[㵈cm6ECfG^ "OLDoK Io2g.~h>Y}ʘ<ٲ6N'IbP]}BmϪG@CZe),f gSdci?>IsU幕dݧg۬iF>2%r# oNX&;>!eh+γ;oO,DMH姈}%[zԹ)a Xn/xW}=>7J_`Sui(4er Y&\#z҆J._?#؋Bj;EC=~=ϥS[1X/`3,%,cOe)d Y*W10F&Cر(AB%̆&dp]j"{zGP8<]5snX ǐ/A QF, 16ktfZf`,,z^ijz:Y1⹡cs*( 1]h;cw.Tux;(iv"?V邍kk绸 pOd%$f?dPrPwezP`Bg u2c.K|+Jv-JzLQIlGew;m(|pk GKf叝~dS(*3saN]#৞/{!kqz#oXϡG> ژUu`1*|{_*bkk8GYLjz /`n.g%E6P#B%A HMF>^MWɚhc#r?U2|0;4;`Uny(ޗ7`k\&TZOΐ'׏61S9WgU'*p 6kA6j" X b'a4P$veiw睆.ӧ>R<[9۷VjR/lyY0ʤno6҅CWOo^ryyqi9p=vbPB]FE$Naib;[ERR(=Nn^Gy5RkFֽY}:[7U<*kV2_a܁zm20@8`_TN]a1)/)/V)Z<4W䬫RT,꒯(^SB󻼔gPX9Qdӑ~lݕl$,MMSRJiZY{%(k)9gafJpSI*n5&Wז;.i|A qXlht+K^D<͕ ]XR4,^weGh<nVxV.Ǣ_&=AaㇻnhC'5NMU5ߪ2Ie]}8isGnf2+bw-kR\:9L]e'?@|r-;~ѡ2 O2DT>jq/cRR^,|ϊ Nx|& UzTl !ez2ֻ)nNnjJ(#mƶklPT U*{Ғ|RcP<.2#nx*awt^V7ޥuB ˫ֹPXH. 68[F =i`ٯ x!Uf/?x!2VVѼ"~s]t.n]A^.P.i.=OA#lEQh_],8∾c@;_i'~~O<~ԗ3v-u%^2hT=@UيbGc+mM2"r}&ۚz7&&`> $tP}A!>O!-bs=3r.c=y(]Eo h ~ɝ(ŌyA_H_I11Xd YB82)< |~%!v~-ޠ6y9*fgb|5*[@Np͜#fe$Z](@GT(#nM*(ږPԱPcBz=/ Ef-vPݪWĨo+4x/мX7wF%B_8e5UR֮>-gx0im-;Et\S~53Z̛Hw=ZfQ&üp/7 Mh"svUAwnj ׷Ίb xk.*f(6:D.ꩄsܮT<6Ѝ=ҏ(x)qczc^Ln:WҸSVwHؠJH k+6ю//J8>#[>]K,2byZN͹:w'ԝمwQ{]ȋ3hV B}0|A y'Mk ,x.Qs|կPl`{#JaLC5W<7.mZٴ$^C߉NDy0;M7˼ b:g ; 1uPw(.q 7ւ}Ÿ e$ח/M%T%DX]qL?7W͏OHd<2:>\wU!e7OY{z7oOͤH)[h,w#"@Ҟ5U/Qo}i;-+(̬p<*n=_7**x|Gۦw|0 +0{^fOg_nnyt?\ 27_qKJkS>xc8bCbE#h G"Eqs~qs03V(5*|a3A܃›W晥+ #` yK.\ <6 ,_;C~!ׇWϛ' a6ZfZOVFX~xYqlHnȘBg@[ n1ɐX35^6!]z')Gʋ-ɂP6Δ P:HȴK3=o^ I?1)=h!s G2Mdc=ˈWkW0 z<3/<[ʉs8C R%n0#.4@?^-iv#4#Z"'X/ V0{8XێUJ۱_ ]bU}N}9Eb^pdҙ¯漿ӇPDlZý{Bax'aUs7+__S^˲,U !h_Eb}$e-pž%јdD3BUzP+/}rO[~ЮTvcM;Chz盞?dhc˔YDéfqxz~!hT1zߥpYNU׮1PUWH)CY~Y .?f H6~ 3Vye5!=n VeoJ'SKj V塟']} ?K *,Ɯ8sړI# wҴeo.tu\25h~77ug54, hjģgˎ*Xl逆h;3mggn"2n-<,q|v)V&iuJDN4SDAk`b"%t'C޼/섎BNy27|6&qzNEƢsH޵(Sċ]RcR^n&U>LNr(Mġ,T_k>ȨzAA g,Ws/J~<1r(Ɂ]E3H7-7(7@dž'n*<&W0;n˯NG9}6 ]v{Kbmt\'lyXPaCo2;lOzy>'֠չ~sN-wQ~%ۈ-13|V-RXd#!O.MkBXG0I]>uπ~rG#3Knz'|eUMB9LtdM] (Y='kmjp?o\&GO؃:t۵qv2^SCe\! ']]BSUǐNBT"eܷ?w7ـQ3M#h*pU/bQáe:2!.HWʇ#.ʨ'~-ǭƱr'Ml WP ' Ep#\S8h%1aLY>r!_P8qwEkvpiG~`{3zL>|o99,E:kB9ڢ?z3~7ڗ &97 i*&P3VQ|6'o'ZfiT1PDDEGIJQyհ5CW=Xa]ϙq4*-4 QL2;<,ziԹ* -#(pHyiZt⾑ ^e4?ھ!=.MQ[H8K*)ܜ$p$l4NʒugxXeɹUgt~꓋5YdzЇ#2*{JJ};u@퇠~vizىW5!.2E[ - V$/VQx!Q(X&f_֠`l-orlbyX5jHڡWə%Ν+hąJ+ug/A},*V%#0b*]}(=h:_lP(AU@f{ڴSABvɅ*P.LPʺ"j 5{ I^5FcxX0 , ]$<>[ŃXd^&4us`7*8W:!K2}Q L];}~B}]'u\<͝~בK8O69xPjfZ^)Gl\gr:1^{(A[' :R7t: wS4=dvH*M>\swJˌ?Ztz$5_abe0z\Iu5`]*lsg;ͯ Გ1|I iQ.d˼K9mG3UΤO=*i G3 D^ G9drOl懃 J~:ѐL~gZdCbY4ѐ !6N 1nӾ'R#F8){g8}FDq29 })`ZۃebLXeŚb@H.+B0UKB=҅Ğ9R ''/l^t`CI?PU{E=WBpR&h+фnfͮj7/ܽrc[GIB{wL#J+M|옜ɛri->-3ּV<1 y2;"y(|ya|`?56[J4P<҉eYve;uvL+'@Ժ 0Ugp\fs *Z-kY'qUGmH.jiUgT9u~ךIs. $We]kM݁hze62+~FmPާo/yF]h(yXA4Z uM} 3]ӊ*ĨskU4lB_s6NEn) h'@[|5fryi+6d՘f\xy`$g"d"L(8:'Jt$|(?/$yz2E* ~R\(nz&ďo {&4 ( Qܬp̠*kRf*c:͆-ۈƦџS#q 7.?W얱)o^O~c3ݳŽX8 %"LF3B.F bmsqf[^rC[sc+u&T++("rIXff{ ~YP_H}kb)϶[CV?ֱ֔[PTC)ǁqZ aO؂77͓ۓK )𨰒F ׸B̽yK+-`4m4J3 eI$U}@}N؂wK@<"W\\WkMܽic{m4947ry؟/XrW):ȟyfaxHǔt1QCzF pb{Drxl XC/+ ǧ-"hh%AqrݶSB{/6/ϼ܏ps. oWPʀ ]^b::o;?0?Ϝrs{[[:W5T#[0$#K I?n)oS4Ykڛ~[j>6M+xM2/˴ ery_36LܠlzA"~#NGY,F= |t}lnlW:m}s4.dRGѽN ʺ+<-iQ)de޾~$&'t}\VrdRXU<FofmZPoL_Bت!:0lEpKc^rL_H7xЍwayim;\|h<@l.dFheJ`/GC[T|ၵGM15RkcS[,9M. {INçZm6sV3?ɊqUEܻ+&\=9tr!%պgힲ~}~iv #ؗkUyǴ~Ē#^Vq>)9\-/M8]jw8H[sd/#£B'2>/B-U_}hh_]0|L,u}q&IMώ$r$p*H1=Q1:b[+^2Q<|CeC/: *]Zh!G[Y}"aI",03ߗWk \v&|YsS 3n7{|v ;5H ctZ.ϻؒ[Ǒrk\eSP_B8P}#; <0_oKTk9Rez[FKs&O}[Yp'54D|2 &$#7|@q2"9M_$9hS oLCPzŸltNH Kt.4,~/UBsl ?2OM(w8D v~mtfy;ǂ@9`_?hvQ;(>BMmƝD3 &o=ͪp+oΈoΝk8XUڬk0MP׭6kQcjӛ٭}Ď$G􃹉 \VÕE493,.\Th h3ք' f:|^>ޟQZJg6k)U0ǙqT lmNʳ&dypCosvL"ʵcvs+|?Y9Z.xXvq+oNU!ȶBA@?d$9[ ]qtb3XX%W'ǀHtc?$ y=9N\=ROgG`Ţ3!zLk&Fek$(MRU"ەVTñ 3TeVxBBdA#}ɷ^t #[*n5-%y _}8SA#{C=\ ;N[lWiV!᥄4. L1L2g`َZiӘK +-Ƥq?DO-2mkrX9hΰWhӟЋ>ͪ3=Wfba*wfPio Au T_rUl;Den:"$ !SAZUfoU~VBL 2 j׼ٶA"Zu E$EPdo ݨ/2X8ݪ!/PI}:Dax,l4VeoaT||m2ԏ?(*a^!xK @ibf0>?01?Vƪ/}d[$Rԑ~Iub XKQ.~-E%]2 `]]B6+?]Y_fYpVc拳jГCS|^aՕPKJr i&8=9\oNnDiA/'yI[zx]~2Q[' @ % uu@K%  ϖb䛍ܯ<~.ݱ`P/Pԫ|Y5t?94/.uDl/&ZgSJ=e4Odo&lNu`>D%ȢSxۏ?EkldCTjC+@8[Ta7~,1ͅ&VKF\m>z`.MJ:7Z67xAs|_͝ vqMߊG,%wSb ρ|4O;!*;c|ؼ%DrVy3 m ~M of* 9fI2Lx=7o4OBquwE(lhΡ]4+mn;2_^6ymnɶD#3=ozz;W}wn5>#t7[e%QnH^NKf=Z/i׶h):+5r˭JD^tSO:yAҠ0 /\{ھAi=]V{ޓ(4 udNoP>bq8Bs_,D#cip8yYWfWU0 z-|d3)\G}klT4VZ+xD${ TxZܺ^nw(dFP)&92ȥ(E v(93N1>ү(\$Ί=IO|`GFʊ }xZˁ#y51bi6qܻH#'Xg NdE 7/Lg{o3ڨNDsG=i Hw0Ĉ[H1w,ˎgj/]R٢ǯT<mlBjUP3Kj#ƽ>D-lLxDy7wQQ8GZkLc.ʠFpkbQE~t?6czEpǂ\lY݃3K+\,1Z tSƟa}}.UqIl绢Ui<_`9jy)ZdzTy<8!R[5Pn\4m~/ӿi:>^O'3p03ա" Y}"|5=t5yFCyᅵ`Z4= e 5dxLV=죥*xB]fs8 Ip'ngb,ƪH"_dz\_'{t~'Cnٰn~lhg5)4wksr՛y;{;*"+4U[+\(p@;Y{眜) JP&|Sy#m&M1}l5)cSc_HfF-tm(s+urvU3͗3>|Ұ ZJ<|-YUf7d̈c W)p5Clquzպ>C)z_o}X7Wz9lSnOKEiUx'y}h Sm 6^tdͬ6]L}|nį\ \zppk<-;ZJ4M3P2)\&y͗٘ms3*D& l}Jg&#r:zy@,y87nFEdXxyy}n_EIa"@8"L?2D_Ad޲Qld|/x:ʃ1r'vu-)ʴ+^ᨕ2dRwzx;ANP<u(ʋx<$ǸD9Dl%?K;X!3wy%xEFS"yx 6^HԈ`UӴb0yQΚi#K~qyV4- ;Jq<4zwR;<(2)Dޘߌir[=]TȞj8c rA?H»7%HyEv'H [{$| gC4 w)ITV I9a(^8e.v.}>gyc8 [|,BrnOoo|rhu߬sU[Q9zX% #9F!8sdXMf?E)_:_7EV4b=Fr&@#is0Fn]gB#eLgѼW⼎!PQBJNtϥ%~Je{;Рސ?J "ZÏ73wYϴeWD{snv\^wg^"dޟhJuŝ)5fz zQuGb-ߍM7^,+WS`י^#/x :mҕjYC@p֘+sI6}ud"'ְJ'- Ppѻ 6/ ƃ Q1ȏ/Z?e)>;30Q dRayKY7߭=N?S$O)wQ'oC["۹I->᭴vWv[c޽j͵AQ =^im(@2IFCya6[Űw\ZbJUn3h~Iy0c:5t3]RYe7ws- 3nW-~[ܰHX* Un<yG1ʌOAxذjU)XX}# RWqbV*muPK^՗ZN+U^iЃ^Q{bf5ESrf}Wu|.Lp bǴOɆvhGo*2S5D-F|\o4VYu"o{tLa~e2zXAƆMj3L.08ᡢ"~d+n37*m}dEoU 4P[w॰olDPސmqF|ϡ\ݖ gH:Y]ݟj&\"h"`mej%D!U=~*r&hlFGlz헚0qtfq[{6F^!;7 Bؼ5T0QX`|JRe>dᬵq r2Єn6]z^BnJ+nv`&%HAPGTbx!w?J33}+Q=A&zT1Է?݅u< h 2qϢut!ռc2(qY=-||7jkmt c2RFvb!Z^4p22+XxF~ƌj \;O1-W#Npn$TK\!RdzjpkHyuCjoOI%4cvhfk(@ݍGւ_h[!MsRI#9 ^+oDtțZ*)O)* 5Գx[@c5%Zn%7uDd1UYyeP^Sf/,-./`fs{DԬT>aIu^K#_@Ѣ7qLN<'_s4q&$=WLCQ9`\捻}9FQWiXmU7yE0"L2dy $z+^(#o+Wwohy`Rބ>T:RU,Hnhw{%R[n=`Ƅ/~DpNǜQhYfPuƤ$R\ociLnxOEѝt>! ޑy~&R5 '۟zl.ӑ/e:5F,p2c^A<;*<{C!=$^7*߶O3B:^R+}hGL6LC@!PKN:G| ٓrQ|1 rr uf9Ld??߫/%ù?g [nhyQ 4f5ʒe>^IA벊R` ؐ茒>h#TƦt fd9ůEW}ⓕծ'x-Ӕaf6p?]$2i :TW˓^_pEz9b=%Kҽaak@&I$ %d4pyg34ΌFxkƸ<Þ2cifb 妳3^fE$[?y}C](;(].TN]}0{"7λaѡjoN[J:szb؈Pr%>PD@4SyΝug[bVZz1c ]h%hXIN<;`MCsTĜʳyAcojᠴ@v[z]O" Jf9a.LS0J __0Ȋ]fASudg/+v]&;\nJa"? y$k!59lхaa/J`1^iӱô3+h"@,9X/:GN oAM WYѸWdklI2WpYQM0Su&1u悬m |=7geڠՇ d3B.XW ]M.nU//b%0~ %_:JTe$?r쾪f'$BO#IM{w8AkIq8@#Vgc ';cܨ7{#=iMEM 5wN|ό]>q#V|fr8џiִ̔:s(rg/[L?!V{6+m֛C ]&OR6L 3Ӕh$qB^AR[|H/[a(O?Gzixz ےaKfeV}.Lyokĺ"ڵhiE\ ُ bQ4d ҟ@neFQW{85 Ϗ? `'i‰!YUQY{9mFEyرhI#ѓ(:kB#Ѽ̺3|ISD7W/{s6fc2[/SXr~"W7~E~An"치AaZѭ`+, TLUO?@4iZ嘷Jkޑ"ͻT„ݬ}K@@.&eoFj>qB숟^5vuNyKhD(0m}o׌{8'@3t՛x_!=q[?(IosQ aI14U|}&GiIeM7r.*ϜlFužFY*!7~b] Hs@Cv% I;\U6Cj2rWÝk%l,?u5w+UE;B eU{=njUxji4} Mac?\IᥭVﭔ]p[\1jzc^~?+.ᚋJ!PQ&lyD[4w w6":eC 0/Oэ'Ln$\0LvӠ \}0FZ#L#(uMjw2j2%U;$_fH8z庾]|I {%4P|a:JT|TkKuuE"Hu<&k[hkf!a܇^/4&ړo#YogHXe(Bhí=HvKޔXgrw8w08 -νCF?~^SOf6DS Tun!yK}z]"'$EC?/>l%OdU*^3^.a\W1G?lL8tbxOQ >"MsY-I''mM,yOv` M2eҷh|6ê~|agZڹ|z_~robk?۰FZ``ȃL Kml## Iߞ-PsPneayv!X̓lկNfEIXep,l7F%\W2wwJCr7P-o w2<̧_c*uD8Uύ|L[+Hv>bsh/TQ};&<оT2pe ȿv2Cz^<.V⼶t]JGF"oubAOz;ЫFܰ2RУ)y^j\ZVeiō 6SYò"qR.p 10π-gRz$'ݟ9~jGkh/Д>Q2As^<̃Sݼ0:w&ysrJyBe7 q;R;Mg0'c4CxDw룖Y,-rUI呪pv&zW쯱MkOXCo6OM~DQzS˫`%Qe n U6T7'h}\DҞҸTk`݌Iَh 99.# ߏ_-":IODׂ2(]w&4^Vן<ïrB;P9O=6m$XSӘE!):6xjaV~Bo>eHkX%Umf*t3Uzi"=ڏK >|m/!h8+_}i\gvOv^缡Y+!ॊk-: yxG61ԔTHZR<R!BG L{k&3e^Q8=x~#v]!>h x;,!3GCb4)TiB=i]l9D>|4JI?v\NL203{72.=eK g ];=]Wx:@3vl[dYLPtwLmRiYH6ٗ+=t bCߜ0u],/ΰ`-0ix$G\1x8.}%*[:rוz0Lhǃ3I'К!#; cs;G4 G\K8%~'V}!l9};͝ -=Aٸ͆@^c09@ -, zS[ثڶ~[m#2alEp~*+WHtPh*&sw{KvAC'\ۦg2iL)|q>] gIUTfۆ" ;2IԪw@SƖDwϣCWoi?+MF\ͦ>ˤ6WKN*˚g8P#_ox~k#Z fԅ09; M[ ps_Hײh&HGv74/ѧ2#xݑ/8vEe3x_ABu+Ə2ݽlNr)[^s2Fj2 <0CBa`Q+ g%Y}0>&AuC?B7lq%%";%`jG<::XDžT\M69V*R] oղm&4΢B$T{k%)}ԎaЇ2!BTbݪ!ڈ{:_dd>ijuwt4&= :myo8*,m3ͩxua4 :d{WƗܻSC;e-z¯~^4Vlݘv^ʘ lPF>U[ϢW  vGݛLu?:^_dzΘέ1=n3U Z߭[d^AG6{,6s{WnSf$-+plC5i,U1V,ZR1׏i1;wm/چLh[2uh< 6^*2yjCVA瑒#|{`waZcA_ آ~!v. o#BLPs{\oɎ0Lʃ&@wޞ="zdXRbZ 21) )Qe|!Kz2bdW3`<6G=},Js;*ۑ0a5O..ú=XRn K,wV%7X7ϰ7$S<>%K1,H菜xUUnmYpp(Ļy+J98A[.bO-Fɣژ,&:jtB1G#Ne&?L%o;Lpя^--}܄qT/o8?BNGOi\.yI$ >OnDo>lC0̃{m8#-w|呌RG M,zf̡װ;j|l<&h1ڴS`$=#2l4ćk..yT,4`YN3Ң9ѳbp9kˌS<&"WYox6wgz{>(VUvv@iϵeI =oZѱ4yCZ(u wүyBs9U&}>_IoPFEZ<7]+63d%aO~v\8B{_xaBޟ(/-)/Oxw=t^T؉̑[&EX?hbg'e|c* ^מ jRW!C&3/%wٿEfA Ko8[,Y:x5vStۡly TE}[¯x,St;ivˏ]76R~qY`c<^!G1Ӟ=VߵI_i9Ju{QF_ݰ̴J0m2z+!*uo k]֏ct@%{ϫe%r3=Ӳ3ۛBCvL'I|t?buC27W7rw]G'H|FU9üRXZrj ;^4#aG4a*< \lÓf;#dh]_}Zuəa-aN;tTdR2zhbiJASG_Zfujo{9n'$d܃<=3t8 \ WG^#KiizæZ^]9 I]ƌ@p)2Ec=?tQkAn!w痛:d`@1#,y"{~k7V4Z]AtEVӖpH߷ NS')bbbMHk;6[Gtګ@WeB%0ωC:&ֹWr.qP!40&<=)R<UE980N5F7xY}7^ceLXɮ =%A -*r hyE0}.NARܟ|gJԡl ^hh})8tӁ臔Ȏz~y?fUy,/%d'ĴG ?v֊G \,adɟ 猓*2 AUj)\d@fqg@~]dQ$*lc!Z^oX pո8ElLa1No:țxmȜQ֠-ѿEy^/eq%Z%&@,ZG]]N00ْSqACM7vȉ=‡K Z Uܧ& u\Ai2:.wjy~Lm$ S@}@=C. v`Z\g :=Hh)\(N*]>4e ]GkKѯdJ"E羛%땿$ M/L(3Up*!v"ᆱ_^U2mD!.u&.uJQ:s8)&djmc? KX&t)hM_3K 6++D?Ae{"{3}ؿCȯ?Laf"0|ܹv",*k )8Qx6]H!Y^bٜzk?ӟc҄q]p! ;JD"H&UƭLt<{"9Ze[_{~U`KM D}-\:u X);: Fی viZE:"S}˄u$9!4Kڽx0 "ӳKkDr w,0M yf~\d܀ J]_UmF91R0( lncS8-qK,#Z43ZKJ:9Xo%3BR=f/s %4ps2gKN|1FR.z&Vlz χI!d % @+b.5ׯ>/㪻=HӼH1݋ J;(u`tr ֹPA6\C~^41+ںԵw8gǹ/kW}N; Nn/i\>=%߾Pxȗh@4?sސu ͅmeF8WgJg%jen@TS ʜKT~l}N#VNAb cHe)#6ߗ Z8Ptm΀dYUx vXi-dq_ Q'K#(睾;bb`b-(Ppϛb.oK,lLЮXM##"dDŽHkOhJeG1[;vkbjnN ߵ6J(l[V-Qi0|i 1Ѹ_La`nmu_>dqzrޘP RțtsKes`V̥l c>w5[@_}Lp(].O%& }g^zWbiY  h]U"y9#%ͯ( MJ.тͱ$o+m}(yI~s>̺7*uݧLyT;T7>Sd-D愭)5ߡsi78}EMcKFEy~S^)r=qmePg5qu+h"A_Əg+\<(x;ǡ: dN'n*-@ XtMOCr=詮ͽd}ʇÊLucPp]wZXlagOrNGJGSߍ0\ٹiy{62]ScZ[&RH偖w(d&>RtdGiYB˂RskF[zqsxDsY|7 jW2fIx?"aUvi4X,*0T`qg۵'g4M&(- '(dN{5FgtHP85?msŠA3?=[):~vIp=ư~,GQT&rNܚJ'T8٘ѷAk)9Tj;Z#YM#_|7eEFeP~MYw)%P|uN/ AQ%ZPxvwR&mM.H b$D:Nup b=me.(J/-vkL9ݱ bɠ)PXѧ.3eмE2 Oh M/]x^2&Dgᄒzd9AkRs(^j*a'XWHHm;sPhZ[JTʝK h)~o+7Rqj(:l5,a ef in2!8{ϥwݘĤJSޔEJ㼼>NpUz6ڛ|zI ˽jo}$7*zt]\%_ݷ d(:GWbPq0 4)19Tvjz,\4qj[)GѢMwTJ`?T 4.iޣ)M's!Y Z$hV|WSEWnmJذ2Ni*w͖/^%nvբk@Qh4vTn䑓#@?(%XuGg.: wX]kByUmV5fKM.zFI]8y1H` ʵj~ǣ!|kX`KK㭸tӑB'3 H/V̹g %ʽSBSʈ :6yQb>v:eDyOSLm5c ;E9>ij@"YJBF{-[0VJ0SvA{ V֍&ͮ8iw} ʷF:KЀ620^yMDཊ#{Jt*kUixS/2!bsiXs^x2p5m-*k_tiW۝UX9\vAqd6]et7q\tWˈÜʷ_\n/f$GtШΫ|r..J,hD|Pj>¸r7PB҃;y\cvbBKٻc"K] N@Q{ GKw.JO,&zcӨw.% (7:a-@)dnvɸȈ+s+0Ck#wȸ~hM97Z Œ2ei<~φ|dltU+B#EDPc㠤 PG8 ٬$mr<{ڱ6߄aĪ.RW SP"A%)yԡCsb ?+UVLpA>L)F*EB]]6h.ʰLY(Jy{eI!:O`’~x>[Մ7KUJte<[C#*S{*O/Кre껛s8 5"|Un(Iá-MO>WMT99{zdQMz5k| ;ѩN nŠÚjM5Me"Rkd86uNWk*۬{([e ݸq3;HЋ|as.w[$Z8D'.7j}QmT(hѻ8ġE")om-CcGlt/nvcs ۇbAX@& g-Ir){'5sL~ -G*Ͳ\TrΆ0Z(o|WҎ]ey.[Ru PZeM7Ki7-Rڠc(iO"i|:x{q슭_1ЪҼ5nyg,kTW%]:7nP50ɫ./6mX+ś4JcKx֩BѴo~Y[<º~U~υO}d(JsXޏ9,ؐ^G' stkE r-HD526oӍiڸRz}mx+'55;kn7TdOv0o*a(Tb^,4? )= 4DZ)V|R_Ђ'5|1ܕ+% +p2Kܕ \wά+%5xw)B,Ƚuk9.(TGYt_.b,ڠ5Yj2(,P-cᨕOU$Q==亭۽^%L7g79iR\A36@mS^d7#]/ ؇`. m>쳔RrC&.$JY1¾LY0᱑) ; W]OvtFO2zBQN _K@60ޢ 7uSI'2߉SEҬJ]uHh+ ?|pbZ;ܝRwT9o8:Q 0hSQGn9 Rv%.,#[% OD•^'mzr(V'ňevu}ݭZ6\(-9)ʡOMa:!-GJot5QDgD0; }}/zVW9_vwGb'"EZ/)hk3r8482,i n̦oJvs'mڨTdSs]r(%5^7̶<uj"7zvA e($ 66$33@ 盩Xd)hZlB}(UcdGMWߦJecI+@m{bŦ{CB{^u(ѝQWe׍j,{ gGWΰ4_O]f њ>ZwM"ot=):ρcZz\#lܡZY+Mi(rWɼagr:>$ X6Z;|`nmzVE{h>ozttz,)<1*J]vG/ `ǯvXNK;5bGƥ֚YaQz`OȊ#M8l 3Ѕ_b ]fnQ~+2oq~KyLf546i,`WKAk=g ,*U Y[l'2lۖܜ~]`a8rs$`'ŀ4oaəPX.VLδ>{cdjSqHlM< h#[?yvyybX=e~dS}b``Bkda}l]% OsVᬷQ Q  ӥeW"%&N `S+#>5-],%f$[n|͖ykr8 +ռL #Ҏ uTS§e (Faѡedx^%M"hYE^ d{0")I-hA;}jG DJl7ڑMTW/9]kUze-uOD*r9ISλ" (pmWf^Mgs.mRo^NXF)\zai2*ǎ;.0G5 xr7?Y{=]!q'\_ɂUODPxz}+ !i/ ^fCy7:Z eA:H< aL m։~-,2ar_ ޠ#/_d.ek%-hkCgo+3/*? .МLz(ּE*ZTiS0X:&/2{~/=UUS,Soe I*(>iQUA+OJzTT/Jg҂ \/׎[qLjӸS _fETbr;k^hzh)b1v~2FO;Ho[rH *soBW"p̐_fC)2SQo¸"Ƕݝ/:ZGZU=9>ߙq4e}: rN]Dh#J{>F}z7%sOwf:ts/^ ZU2'+˻A^<(Jf_/˼&7' qw}ԭ3f6 ""~&BD5ۥ]ہHx"[ի ) փ)V55<=v!.XRqۦX fؚ4#;rtr_V {\& ֆZKtsѩdfږ,, W%ږ[|m0PB~sDf75fԐ,b΅p;w`5l>:5}38UqONFӖ;p R{-p(qن]+96/;۱w%j*BeXIvqhj2i1fETw%"oGců9_! )ݓrPo^ܯ1g:JA^qq%gcEV13r];L4GN?L,׺A~L-*e>SlUw@/yie!)ڳIxXV [^rk`p' q'̍OX2mDL2W, baF %5S=uX:#aoM0&.)_a*]='Kf1V4^RZthLFW"BM|% 0'E26{QFUFŋd>ju\ݰTwGߦ@r&=QdݳkNH}v4PΨ}o6Yy-e8DtUD,=rjѤθDw vR$2?]NG@>!)rYe$In:iVx0CTJ}. `Ϛfsӟn.tsmF1Ȅ?/HF 碑 kMeW$f_\JmR6 |n׊=ey١iWˬig֒#ALEToARzߌM̫4D4aUdL@4 |~s݆ {e$$ͷMG]sỷ6jF>5C"N=Ldcވ$8$Ci!V&)|5sZj^l;u9}SS8PBQ5TϬ\q>QڦHϏ2v8>8izdV#Ҏ_aYAƁK~{ZW ٠1}l]m!ˬ 9Xum:_ݼ&M0 ['ɍMi')BEn:˻LܯtꬭD3f_:XLfAZշygU+-+`{T\ݩeH>qs;,R .|45'MGwcnfy^*^% (QMY "F' JVtA 7g_Cy.AV,G ~Ӛ:-8lV|+Jk<۔zTp=дS`fC ])PQ&q}U%}MRbsLLQ-@.6ePX5욧_.:TkV Yp*)atL.weޕNJ۠ qDI4}p~3w:"vu4ůy NuD/C~ 6D6̣EH/sEnMQb w|Cwo\Uha&M2fu)6!&ʣMUW 3CAkUSv]? xy!Ny.^C~;i^ ·2 oEwke^ّoZ7FpW V22>sG33ovt`J.qGmB/) ViB1#8.U(U Z<7Y4Vje)꙳o }+vJ`Gm"l/-`1{$Y3rk^3cK3_hy/fJſ𘽍phZN}ɵE)qm]*ܰ44zo;e\sYsѧ;Tۧb3m,Wj\.!r*J q*Oηn-n!2j`c-7O[ԡ"ss^Z86\t[*G:q+kBڈ$=QZeO)ڨX1wVt){HK \fW~2ń8D &z.Maf;MP1Tx]'^Cɷ&dz&V_5F8y!kY^拒ygWW~D۠mrjNigޗ# z \G"ޞ2sRx$UHȲg(ȄK|f3i>pOLm^fhL$,˫fOksXVܼhږWTwЕcl G7hU?ep]Ok^*]괻LrbZL'/793/-F(+PֆJ7w+CjP xeࣽPʹb]3d |ɇڀ/H! ͅPu %  }:\!:' ۥLٺd|+pW_o-;vuL_&6k2vT7KT=Gҥ<DמPrwkW bL+KZ9tpJjoM:vMv!a{ݪ~xc=H ׉!W5u@-ȫ$;b]tAt"HC}u?t*u&V-pߤICXrđh|TBhoF =*BuDc u?Tx#&egǏ: @: x%&4]A^Զ{z]*#W&+5۠enۙ3\T&r)j0R?& mRAU#"nAEnAYInWkZ̓vwIXu(y6t=(]H>,kuџ|4X ̐(LFy^;v B==DuV!ޑrc4LyQ3M 3VۀDQFBumt 4j 썧c)Es/՝ K$kv -ezQjSlf`JfKh;݌Soc6GІ|ɧ>=vDӷڙvuFa}G] $lK=鰙&E^̢V'zr_]JN epInk"<8 U*{&o~`+^oxɨ8WVP@3QЋ֯ ڴHDQxK~l;+DX'2JhpС2Q_J#H%@if5I,/nJ; *7W[&qX CQoWn&3mkXണSoeE 6*ptWo|=UmTĤIoZEW<5BsuӰ~ѢnD` ՘I$sG@!n 'V!Skd +r_ajِZMyh-9$>İȂ06.uv?$,oJJ|duM͇Q4Yon$f1'O7}(A[)o6MͤahBl]sa/ QY{~,|m;WMefJ8c>fcce4榻d9 EIMf Yk$𭇶+BEz44 /su1 2h1Tp#QBe 9?BQL?-)i MmE']64l7:~É];4(0b`-~iCF*y{SFxRxBi5◷H|ϩZ2J Ue%nxJBȥFGb*B2/w6CegT5C%LjqWł<9q>ɫ#?[h;w0hީ4ă/yCtXWnP*tMk"*j;tIS|%J,i6:9.,7m+(w5Jk>)O|t迴\[dYDJ'\Ψ;FdS+iIJ7X67;{<&Pv)^î2?,YD{#_*Qu/GHHש`chX'^|j&.uݰXW޷2>Y Lk)0;&I z 6y%trXQ=Yzr uik=&줭TRbUGZ%PCpv+Rd'^i%M: n'|a6O|ϛiVm&mNjVf4 H?ꢡ$l&m\y,ӆ1v+ɽ.L?(K"* Ho&s8ecŞPxW\+A1m`!'_KJ,ZȚՎt_iPnsf!f&球e r!`n:4fBcl-Z M*5t49ޢŐ\6 #[D6oA5_]2\k!J晚\b;K y{nK*K>ЗgM˼kj3~+P7.=4dca?p{꺕6<1#XxdG,ɭ;*[ȷ2ݾ6^%[f~x[t'Pwz-,t5IG=|qe dkvgc<!sOfsߜĐ xu3#!tƚ?<FUR)e%`˨&Pt۲o@p M"IkߍȼW\&6AwˌZMr2:2t)1vkк|V̞bϐApQѝgV \Tڲ8c.~d TP(@p桙{Rk_p3h46.1]4{h", }$4ڴmŦ/ڊ2HLn>&PDn@2oesNC=lrgn<*Z)T0Ki/3wCX1閑;/((\{ЖUM¦kYr=wu4iq,_%NҾRB_?p>4䁀*MdؑƜU- RI WЛ6?ܝ[ (4&Ę5]L_]~`bCQIgVZWq"_.zCΙO>3]|%et$ٲ2!oY4W3tvZ{ H.,86}Rcs%Ui0H<}Ydᖭ&WMF_&o2YD;NFUEZi,]Oˑ#ry `N^F]B1 9)3t a¿PhHm~|`^!DٍxBAˊ>dFrc&7jb*l/43b!1}X](KުvEsWri2G Cyz6 g<^%nJA9jFXMҴVoe]fF{pGt4K'#';n&dIG1}7] 26k> ;܇>HmqP5|&e]~)\Mj2ُB%vE\!!+D kդ0rf(nxіRTO Bv5RR/7p ߬6׻cu-_MBX?<(4c|?iŸn*YjQ7Nw}!<zI-2=ٳQ3y~(~&C'ЉEzS%(ؿ<& qY} *o̯o%ړǍd (^[sgH>Xӻq'g+g5Z8?>w< @UAO| P*mxG%_ÊeU͢ЦFhtP I7)w1utM`ƽI=Ù}xٺK /T{ZkzkfZ<I<&8 Uwj~H_w{YJB6|9j-?.$Vb.` s8WmYTPr֤3Y)~=\D'l}Um =5Q rey,FSV-#;ˇg 2]tqftk|2Y)bx+L+*hApEېiW͇/UÿXUU= [:̈́'͇ދvoھ%T@}bq+t_'A(^/$N=*}?3xA 3e(QX>g2F/ _@p+6trcm}3SZTYqղ>Y >yy~35Dl_ą"ZPo@ռzɰP^ӑ\}z"C$9_Gn/r.ʅ .2^5 ~f} 9QR_<hT rgBTHK^S6é6~ljgxR|:f} :ֶ2ֶۼ8smVS^;/L_R`m% 8^bgrOϵei/pi|@Xz[e8pTp`Ҫd/.gFRAa(p?,:pnfۊC![oZ\mUS#@ `>BɄ/Ue6ٟr{uN?52P΋Ge0c*b` P1j퟽53&+2Vv*+ίA?{hyي'QKxu"h[u$e*(kd)Ce5ye( d];S7,G|(ɇȫPe!Ј[}2,6ohM@I)F8*jT7bs[ͩӳ\PhsU7C7./n&+:W*-J5(=&5uv9e3n٧fȭPf ˔B[B  -6[[& /]UDN=5Z>n:o"7DZja?g'x#C9gHI+RhPǍnO E nl[y{8n3;tN=}y9,ˤI|%n&cѢ8ffwD楪/іMO_!2-?8*Ы4B.g3b8pm÷ա*W\V͆3ŘzV@Dpm󀮹 y6 Y*Ԛ&{ZLS 4[JLMv C3ݴ N:pZMX>JTrgA~]p88% Bhmd6ע$(Y"nhnP6мIA޷ɓE>u,.̆OX~Q=7T}T% S6XP!|Xf׫$9QX<F˽|q+(ĝG|sh'0(:MF;؜!],ӰE/_=nG:M2Pz"Ȧ iH f=rmԡ'i"q̥BWpPffv 64urMȒ!# Jnjm=lyHM=s$̫@fAZejm7O1K@#GN#[K/"L%96|b2V/%U诪kn>u֒Q;aFLĉ[z.cTgnIe~sD U{;yW)۴W3fWZ#G2XP_$9G6jORz*LIf/^S$@fnozݤDs>tio5N*݋[{gl DZ3Jtޙ Kי t CU>l#I XDe+'vi#{%G[gu50ձO&+UN7mꚛq* 4˼,ؕjuojwUSx6ٹV jwao:uO5U+\ >ȯ{R.U&(3y > ֞b=4ȫXtE:5"3?%\&w|/:19{7&K`EWQ{HV{k/xseÅ?4Sd,dyPI%Ca[ȧ*MѴ:,Ɏ 5]n;3tu3dҸ Uv { 3"mRAGT̫ $ey*Zw8_Wܵlȱm69g;v2z>}5m2hɖ{=VJ v}Nj+~(m>X4qn:j>oc*Ak얺C~^'.1 7x^/Uh&()oӇColt?yYACOa6덺Bj WL!=6h~‘WhLeq)>J*0uo/s⾣e>Iz=҆m#Í/㸺̲6NgL!҆C!yD`m4, W^z6شY">)mpOSԴU.;וۦV(ZؖBEb z~-q,_8t}J*5_;uix١<Ȏbc4\qR<;?dovwLcBtRz>& e6u}Et_oM>iSJ\k1gH:j ^gdNjU A0ޮxW=㊷Qsxf}d{v^ <̼r:chӪIS<*mЦ1ݯxy5eI*<.:ff hdV'BÐ]I&.")͛M [>y!XW+AMp40T9HezOK|DsGC>\!q=?Y&vZ<]{դ|c1ȿ}ZYBe/YBMʆbWɀ.I nP}7ڱ YYX<^ܙmX #ٖ 7^lŝy3lChϚ&2Oy™Kn^NE]((@خFyumFwFM1,ʀhTM 70n4~NnB͇nRP]|'iwU6hd=I̯'ImaLj>ɋN&Ra#ࢲKSES^~Bo);LQlTd\SC ynh^n_2? d-27bMvE7|аޤM>_NMK3`O~P:< UM 켱XVuft`#Ůouï ?Q⇖Vc^&. 6Kl"9 P T$-MB1/ t!iUQr_5h UĘsTLXV2H$u16l(sN͓}>f̛Sם٘<'Ba/,Mc)OfIkMS&i;vӄǧ*H22 PN\Cѷ.즪_4`LLwQ LJ)U/qgz8S3Wvzo̼ˏ&ߌWeڻ^Ak(b$R+?u4Юu|31ʽ:y |U橧D䭜{BS!Հ7Nx y։DoRcdK9[d+ߞ=DCwjlcX+ݏu';Kr|8tef'9G=Ӯq;])?搫jxFzs=qۣq~^r<.zpk>z疽?n~vB|\f_)Bt?WMuV7>5uNGJm75 ctD%T0+c F|^. P3I8lD ԕ@Ie|÷;Kq@&}['2A?MQe͛Ԛ;Y)}:f|0m>h[ :Ju*\LjJrZa4\b4[XY~XWM`If畈?*M1/ʉY{s'΀|{тn4\-и&@hQB(Znd_[TXoZ.I}r.Jm {rȿjylUZk IS:EVW`;$7 l tRƅjDg[sV# kę%rS[9K>>9XCgy\nP2RXV(2@W`4V*]$~'n3*t00 shs*>璾)oB5 q! uГ|7wbr7O3EEyVs<-s#P~pf=U~(|RK5fVB@ D4n1ܑC$QԀFLXc-1g٨t=TuZB]9uuUTCSg5@6UaBbG}ZYμ>/E[v'cC}om;];ʑt6U7Cq>n.Ohx˔"֒*O>mJVBYT7F=ְXFIJ|5GljNڄ~&6#qG~H2stNlcyEԉ`O♭/fܓ4T($z~|>9s0ĄͶ͎ w#E!:]Ys~$#E߱wR]$:s*'0ڹnMif;8B"`"C.@`^ \07)~0MXnK~3aI4W,ȡPG3[.aʤlfx0iB!н }i[H2ڥ%}!ߴywLeN\|/a&33wh{mzÛؼL;J3g^.گ[6z\)Q0Բ&$pK[wOP?uvx/a2l.X q$Ӗ8B#QW#?{]<%` m0v2^F:eϗ8cyKlt7ly$Vn$SBDroϯ_Pw9m{ r2$ (& u,MR/"?@د2(,cmS$ PDnlM:v`?ykcűQKGdVD&=LGͺWLo| EmtHN ĘQcZil6CȼQ@Հoq%F!PoszB)BI)O2 ]r4˴v.N2 ig_A&,vT 8}ȂPa f/A$bɻI٦&'W2gp.WW#f}QQ?hUg4mqϮIƨo[JMZ76Z5AhuaK#EHB9Y v\%"ЎE^"u{4[c(+&jB~+ )Cn%D//D9K,'qwU486TT<daT4; n6ʆl8A֫!JW9~SA;W q% w>$epK )'uRB DZ 0jijn& ]%nګY=f@=)n_PxlDZ2:,GgV9Qړcd̒xߚNq/Gy Yv̻p:ٕcONldd7=Qh;W*딯ګîғ:CU~ִ(M/+jZ4l50 7=2;d`vZXWAkJfQOh[KrĒq6# Nw&tU\$J4]%oj.i<ˬ9յz7v1Cp}dw"hFɱX24Q o)i/`Yk佈5?@>P"OR( }[i$lk xx-R[&igJ4r7=Y o/ʽӑˍuH3"$q7%ħDCŸ$L =oW<qo;VZ-z,p]6'1)}~uŒ*C E3S|/x_SMv E:{"'jOO|*)4 e?}U1CB}b|ƑыMa^fK 6Vkg0z7hd7Y,{@^.Mo &[h8:4A;?X sg 047>"9X'|Ya$pǷLP!D"5PKVD5EdģN :[\p2C̣ A}RelyYodil 5`aJ.[]F2!8I =}hiUQnM49:w%BUr$O'͸lmbyӣNO/m8bؐi?߉^zdpJLA d_T*JiBΡ_ɯ1ݴI=6fVHD+hF dhaɛ8̓ ~TuA]š^_j5iۙ77}27bXuqN:io3lJsf4V/6eښ#thfnVE:oғޮo5 NxF6I.z9t[Nݓ-|hmnn^Sm|*Fu%gr g*~CqIFZz U†ѻqiNMpZ AeTR[: itd94&C^җ7{U+ZTĿH_ ︪),{y,h"*$H$Q7Iw)ߥ0,M(&m=):m&e]enQYBZjR`܈JeTq |3MZ]sk>EA6$xZ֑˴!vVh= htd*8t j;=b&B*JEoM_Lp>1gha㵼4VG~(m+~ڲ 03qfReN&W~ZEG}-P0U3N'/ka2Xsy7OTRi,bK"tYCOu?!X¼L&gѹ Zs,HUgYc.h&{h 4KtCY]H&B*lIv]7>fyjkVwN#*u-GCP+[^*s-YçoCا4sT`9\5ND-!jYt( b_y?gH[cD!)}L^#=呜tO|8ǃ](qT6!4ZPKF:T(*mlTq3WCߠpӻVe繳)&5ZͮS=_K}y``ڱE6iq^b˧C{Ji,kӥ/0YhqUi0r؝ %ݚZI;_ڟnM˻4yFFno iʜX3zh6<+urKts>w'>jԞAp:2t((j0wƘf0sfbfuWݑ)ELd( O*zs5foU&ɜdȫcGWusE m4蟄mN&;,T6C\Gn1>I>!})пz"o*ܨ h7g!iIT?^ePqDVMה zC*kROܠ{[ЗٷkBfeNnP&Cz^fbb^i« \W@̝ƒ G <]8tO~E%`(H;MWGp֒@"$67zY;߾e͠UZC_P=hNs^F]QL2y0EQ!oMI7q.O"]їqR)?"V/3K}.Dl$5(RK剥wIfj^:5xlf%_7abᖅr$2fp5N|J_uj>oYa&sE?hk۞K?jvQ$:pb}:ؑ%Nœk2N#iZ}Pݥy.iI*pS3ßd܌_ gJߥ?1bQ,բȩa|0Ϩ^PtjPh'̯8]P=\R1\_pF)tfj.|wvBPJt3Rևڤj,QjɎR??NK1w atPdO_"F[aTVxwl#Wb1Aʀ3$-/𭮔0C 0+ө1۟ƎJЄ.ZyNi]yQZ$E9q7ߩZ!a'+`ODD"˿5w0J;Ԥ!.K6,?g`<9@UEޑfhŏW4g82 ;EPEDgx<+- \UKoA =F|Ec56-b M X̰㦜!w3\'2_u,־EEGUGњ޶qhz#nP q/^t_<ɲͼ B "$ ~F>Px;تCg\sa(GיQbg^i b.J} @$n sg,f61 /84ifVNaa>D}>xgPYL5J= (bT61fWlhuޤȋj24yܧq|5 (DEǝslK)̟tt̏@^*QOhj_ 6ՌL,( F۪QquUxJ!Ciaԧda]enEU\@$@9#s3ުԂǁZm!՝6?IIA@Ho3G{ '?عX!C6J}S~!7o3z:kTڽqJoǹ? {'װe 񏫻J>l,b8\H ?HwT,O$T`#]i*d<74F(7/vۏɶ.[ס}Y1e0iyXA ^Z|EЬ2bB 떛d*.4Zh5Op{;!:}:2CWM=0eTlLXHP4m>y72"o6mME\KrovɪNtSgDz!&Le5q w^aNA[ϧmyiv2ݖsV E#?Y|w}w"c*װ-d4TV] c?^e{in- d\Jr47G`r[swaƅ9ܟkͽ#y({Z I\ "hs[b75N n>,?;lu5}]Q=3K$|ԀP<wd!9-k4-ɷ}*M}*M䊼mͦjG9MK@&š4tmtBуz刜+t(ŜWڟ ڰ֠gއ\{E6fFU: O;#&A zm̽%%z4.U1=wP.LLʶgcBIr7vJpLɍ'C>uDޒc 1hڔFek1=|f:Xl-yix`@~NBw.Qn:\J!tW2kê͏Gɼ\q4HPLb3.*t}Rw$]'  2i\fw)s] T:e!ຨ;UZ{#p!7]rQLfJGhD'5Pt2_Uv{もN1 [QPϏ'lrHq+WW8J!o'(~WE+WH~mBQtc/9dVi>*;4'{O w]PIyJl>ekPfE d菺*VJ9b\AV6N&rq.iDvZ:rh^.zH;%z~sl֔b VO:23hP`ӷOzkthUe*{2PJZR]Wƌ v(d3ooܟ0,Uvf9Dnf7sLnR<Nשr5!R+dmQ9 (SY0G9BwN=?xYQM~D Vp|ӏ H.NrSF}O3 p}FU=ʾ~R %FtXy5J.@6ۨB(<\I@JxyN̝]BgN:vi 0̞{V|@ ewa jH>>۱П}>|cx٤*g)7N_}!/bzUbΏ~L a2r͇-|6ss N9aJխ[XI?G5'֭trw9n3x68齢ߩe~ VU0nvKڥ#*{N"8K̈YYxgk1~tX)kҼeE|[?Wtg1q-EԄ{5/b|PZ9yh(x쳇P;0?6, AS!e.3$QrGg#G=ݍTrf H\4i96dfuy,kf L!}> iGUXL6F);XQõڢ Ÿq*xߌ~[ҤR3=4ɽWuȞ1Q4x=32U 32T2*7[+'ٰE\ ~]u%4\{OZ.tMq>jK)wh \fHXOS")i{m'♕=iyPaX^<;f}*!|X`i4;;O.<_|dS)4Hd2rܳ AiNѮH$>?ty?cQOOUCu iyV#j9u#?c lB.Mn{B--#)OerX[@1謤zS#ok$f`h^FNۦ8rcTHR/<újʉD&Ew6Y ҉s9R͒Bl*erd:+g&)WeK۰-xҽXU cxڗ@S*^=0e}%Vu-{'|)7Yj44(kSN@hRdq>KK՗9=*7w+B5%W|R(dwJ8hVԶ*IM뚥Td:%ItmLx(?7;'g4WT3WS߆-VԗDZ^D|1&c(-10VI-w#7ξ[&ЛW1}T_h}чTݟ7ٰ[$j.h%;~kL Gy$[h*/6YOJ;Q?n*4uTr7/\Ptetx YhV=Q"ꄰEoՙ?`!ߜUJbxZ>WCr]ASĭ3SNw׹ܖYy/YL.h@L$枘bڣ@[跺S/!,sآ2Y#OFזca*eqԼp#PPag-LSOY]:ԪVt*:P؄஦'}h/Clws|-a'qES؊h kޅ67(I܎GFM 23=PIny5!UeXh's.lC{@WQ ]]y/4!aWt~̈W8y{W56 ZzWȅ,U&wJ. P)qWY>K K:u_o QZ%r]8qֺ:^ DtҮ)*ՇH>]eHk?UvptUϴ+7曽A3L"IGz-*A/ݮzPU Z9Q綩C2P(O&(l`MpdKh0!Eʢ ظV&u/kgB䤵9Ɨkh81`"!QP jӇeWns躾)ؠɔf5t}y8)J09ק<:A>ܖ&/ƒV! EyQ(_)e)G΃%]ۦ6f.]S[ABYX ԣd_C&oJ wnƜŰ)7Tn@ј&582?AMЃF' b|R4u:Esel.=wPY:HM/-x/ ,j,ʟb\1:,bPC̲bvd;NrH\ϕ[?P+k9k̋"Ji*u4礇"%`kj9VL CܠMq͋(T [k||70(c7șɃmGeuL0kXy衇خ&F>P2.g 7wZ~'}BF\\ "C]B8Z2y _@@QW1e5(9y/"'35S T^=l (%lM.+m rGm,CƮ.\^qfLg=Cxm6/9h=zmeд^95<*L(ruG&Y4ǺKs:4NyB:4,q477:OHyr<'}iHvo9-3wP.# 3Nou)B os#4f+ *K>_@{i.dk-fhOq ˑ`@ݱYGͻi(YPVkAP뎍?oW-Ul7RS@nf`si:G>24PD9MALևF4N]K“XAlڑ,T]rr3WԈ]+Yk3^3.~uJT/;wp,Ϩ^H47eim<% WүY 3r=VPqb}DS\dº^qq!%F(U-ѦkM,thMʐ, J$LL vgkAU?PH{bGZiV"e$0F'նӴs8d:l2ԈJMzE2|ܢSGy9{TbVpe"ЦEusVݜGL^*WQN>Hq~A jm̍KCKpF}1_Ul:n77+ԲX)@CH<wŴa݁MdLs9"?.*k'NuT 𣣪 dR܈[Q?Cii߇jgD^rkWtA.?TJsIn헆18L}$ԡN%"PS:)2}ɲJ2U Pπqן Iⶂ+S2gcceF7Vj':OJ15$\x)_TRcF͞?`}x6@T?OkqagAQ[{tlvrh:cUi%c3M#:*3HDt͟k^G%a Xʛ[w_1b;=ӌV>,rBМy=I}F."?z.m"pt |I RcUqzN<slv:귻l1%o=2vΟPpW\Pj-|:}̡OER_͈2R[ oSnXP /mLR.Y@e}l9/K2|Q/^<@P*PS2$e{wV_D< k`h2Df?Ҽ??on!E{= 7:^W29e=y[w'Pp4%(Uc iܕXGj7np?[es*ۻs%]~(!φkbN7֌DnY1S%E(u䒹lݪ$MPȷeywݏF>!|Li{"(7Y ٓm픰P{^ތ^ lhdžfU4[xSdrIsh;));}ȻC%U;z^cHVѽɷD3t&H@[HK$׈#oԀ =j}4!㺻ۼʚk_lp^9~(<8'PzcK%YcJ)]e^r|GEiy&EIY78\PX Xr N Օ"~h?5OD_4WD%Ԫ$qJC܋i!:i~\\C2ܟiZ=;ӿKcnc(h r(7/ܜ5e"4^?ed$-}ا H؟c,b&K Ee_U ?k5/!'C_QDCAkUZ,7>jz?b(GC_h!wRX;S帒jkxn~QBIFp '4ѳJ˵O`f0ezⵊpdQӶ<*AD$樧+a(%\fb^-(䡇J}wnU}QQzhN*NsJ97VVmLtIRmTA\.Yoe&ގQ/ ܾ$Ӆ4ns?\3ilc*/ȾYٱҫ^;}Ic ǀ50q32JEr}訆8cnZ*BjMH_m2' IPȵKc+q= IM)t`/}Jd?ʤbq2g#k|뛧xM@>Zn kw*= ĄJao=9r2ơ*er7?">elDATY'/:E/{S 8:mo~ 3Fhhn4ii}ÿU54~%"ԭ; eDnnQׂ&2b7ISKL>|) wl@ok]@G]vf8R 2VSs S6Gk*u\CΆ[yP$.p<3 s,RMZ2׏6BA8jħn30 ˌ:ZN͇qEf^Lxzl$zesr#?Д"[-p UGUCYUomb=͇vP'qIǸ'NF#zJ,v ' Q;~A0v} {/#u젖Ug*<<VBl:u=OSaA>щv+=3DŽnԧI$3̪r3h':dzxNM dԴM2_%QܜLq8C&m $“ʴ ߆vm;_3\`;-F\VXsYςU+XTU~{:UvWi%V|Pľ G6 zbzۚ؎#4WA0VrAߦŪ nA{'|SAEqΩ7tݤYWŮо~ȁm͖;=5/X鎛t„z]LBI=oIa9,J$_M, s2B.,P㓽bf:ٚ9յXg'ukSթp&`ԡ.ZSy}%҄Dfߐx޸\.L6)4D1cc w,vxHv)3k\&!:(~_,i9\nb j5w-=$zxF>RttEǔIE|hK*(3*Men .7*: ygP8WV k^4#USB4{Wn0y"G d#Y!n!)Ѽ&F.D%IPqu[@h~3gBVi|3g>dp*sJFxC/P"h2<%G vu4`Dq:7O}L{#ܣ;hy?lŨ]z?oGBջwqr{ʇa=>jO}Pxr}EƓ8hDUA): ]ydz/10^UKO_c& 'OъdE.64b+*fOg7[T:ӷY?sfH7.{zhO:zRŴNΦ{v.L$"=Bf=OMr7=SPOoS̋0񮖸Wn׍zԉ.wp/STp䇘YdCfAVڛDu͞8VFFp-fj L]bV1{APH-9;u+:4S3_ꆿjSGly#1P$։#wdAN(d2M~A~RC,Z|ɸ)'rE:6n,ns֖RKb=6̡==H@*<3H[VʱUa  <nq!R~>;䕐Wig~³6$O7<ie&7 k\kc+RᘏU?ubV;ygV;eԇ[e~ST: {ndy3N>L5o^͞5ZJ!JaON~y=^K[qsgA1t#QΧhJSN/ad[r9NjlN38Ca`R!R'GF9+.V&OV_qCx5w5>`$2i\yKG(<*)NѫbA ӼʘQT=W2|U; T@EFfiD +*{Ew9ea֦OC4alWC{/h $Ҡ:-1DE]4~/d~5:qc>ASV/r':{UCnIyumf&Es"\D^iD&wr(*P%Sht_u Cz.N~hPQFGtSnzU^LvF&*{wr~J9* WR0TbmMRW ju>n " Pg@O+ hYʇMRr3, [}*+wjKî#՗=Fk4\⼳DA {dljnA+]O^!o; mM:ٺG>@!^pE[CQիy;=q-ӈ½hbClOZQmThׅBM}1y38r&l"{\lpڍl!5??bلXOEϯ&p(Rn~_o DiBTчLr9Fߜy[^CM%|/z,{JF75stM6uW4ffz5$o\=Qо_ HnjBFMN2iv sP`ܝI\3GqKow]@ZCЗ<!i}˧[hŽ֌bUEW:r!u^9~|B^5Wٹ: %z^a݆ Ŕri| #&* +̖8tJÿL7!l}#*[YbPY4f0vhM5ɁWuZ̨WjԓC򁶧CsS;s5L ]%Q{)۶NVogV&hZm#% eMq,J[-V`<9ڗ{M<݇#5ptyZO"l^8 X͚缼,AI>oV}~cɩpk5eR9Լ*r{Ƚ 5AW[ ~1;xQG EՒnw:Dx s1O2 4# J1nbkTQwՃ^'N<KمH&-;oqdH)7@Mޱ@.6Mi!fs9O*%N|9פ4nphNvt[r:ߛLR;" !&eWf -}ot7M^ HM͒gEA vMHn TbniL2d4 FF C#MLCk/Qm:MF[()PB&Mo3[#ihQ85?[p .J+a_VI7UPXPWdߌbSM?/~$7kJޚOuJ*V%<Eu-7;AvV~h[.^*1ר(3Gy.eНHrN'iCxp hܧ1ir7IuE9Qތ5jyϗ5]gzF|èw`!=3o4RXn3; bV(z>ͦ?'E4AVυƛjHXfLYu*Vr:ݮ@;n# ifkU:Ŕb'19}i:w۰1edjEM:xZf\4zR۞?\ݫ* ';`.>2 _Cݠ&?šP$GX+׸PBϦI]zW#̋ѴG.İb) -(N-졒t(pW:yӟX=!tAl_L&'t9[YEw^xז-Q͐\gH%X~XŲžkȊM6Eǿ#44V #n)ǿNK)\ۇH"BKsqR]rfh@ өͤa3CI *]ZF[296fAv#x\(SǖEAxXoiz+x|o~ u3~.Qu. U1 h ͜'%O@*uD~r'domd>P%mNw"Q/M4bWZDiY0y>sF2hkt+QU?ͯP8;XՐn4z'nu# Gyɑ!(RB$df:]Rpvoߘ_P/[])K@fAP̘[u*i؄*f8V`)'.:d8궞PTߜQsqRpJG~ A~ R_@]"4-0&bۄ_e>YXÑU$gMV!/P8VEg^}Zw;rH~vf<Ȍ`UxH017+=2Bk$& ꛅD!wߐ*p7-i80t f_:r_z{pð1GnZz~3W*i_-h4:6GK^z&$2gx`]% NLJRoHQr<0ur]J~/5N0&"&SDdR(a\-ݑ- \ Rg7uvSb?eA ETS9+>a ũ^wK})7j8̽^ʀR?x`MV_L?QCHt^>OQW!w܀{g$?䃫4 [%X}UώEm}hVcki̕t6BJ oH?yڎ}[h7ʞJ:'/ uQeX%ڜ,r b?*['!)s- o*`wg oīov4er=Otлm N{'zJ,L#"Rن*ܩaEW'ĺz+c奮^ӡ7<=>́(^aB~!K3j@޽Oee򒇾q7SˬO2dj޽o2~j7#Seo$5vmcg6,dFN~^|H{ZAjؽo 1(%#{/& /vjL87"e7Am'4qd{{n; ? U[D w&GR ŭyO' w,ǡL`}JEu)9C.ӖD㯩=")sI݆R<%[fycoHQqrPXd87_ù&;ǺetNݟ<36e)D :fWj`]5U'q>O v\s3UU>+x WSecB=VBڡ[g?Yw8$4VPO%xȟymv7 f݄QrŢcȊi K[q2QH^Kʳ*{{|[ƻR_gu.L.G< -nUPg5 41 5B=1gyb4#نɞhUPx /QC~%谣WS&}4^'P !Oqm2Y}Wt\!n z^ Q6|F(Mb'TwO(CsCXąoޘOx[e&_ BuO6!]l{([M;Z;fp$j|@7+?O;z|$.kCcFMUT,;D 634iUt+_nȶjLJ̊ә,^LD緃}>Yd_XOoF>42rBcN呻5+`I( !$rF@"y>W[🎪]k(Ў 9b2 "Cwk;5sg2^ΑPYжyD1yOJ q8ϳ]Ȳg͡]@m)8&։~r^ Um~> T$}dMU2=*RPH1-χ]_GEi\jAoU GP[,5'= ;n3gRf f7*fZ̓N(y{7k6S ;c^b|#EO܌DƫD[78:嶣?e>)q֘ $Ԋ6|O1%Z+L2G})0?\Y#ZhA-ߢ05cnln4Ѵr7Ϝ;|!RcոGͪJMX"ìG(g'~| $ 82*e)WRtU7-.XwdJgOҟ5Wczܡ(Q9$3 EiX4a¡+GM)f"|9ׄhgI:cktnWLy8`(,$SAF,{q|'C֨|fGr (&84@* B M5 չS2hhTvTfS1 |X`Fyhƒ)叆H;@ a}›^I?GM ,$|[?e6ptהWh-e9i;hC&f}/:Fp,|蛩{?EۄzXi0Z^go({IꟴIRNC*ɓ-Z_P&ax';Ua[ ZuɴLL=*/O iSfUNåq*QШemOPې97I!"- x.P&2/ùpy|4Se[_X~oqBn𭍕 ߊ֪\4lx$7Il¡+cnF %FEg)#4I[%9m^o0i׽Ml :(/ӌ6L}q0<M[Uvx!sZU4Ls%yK*NI3ȋ |b=yo"1aV,/aFXsZM/ӚM([@a lvY˻Y2?-Vd~-}2m,?no,}_Wtev vLӹtI7 9-5 q~ ʹ= Ҡ.dJ^^;zR 6y+ђWI)C2A|?y]C㺲DaC1al?2 $ڨ2k|l<(ͤY4nu Zj&$ jI#S~ ICW_)BE;sh;maV'Mm(7P WtgL(&Eəb0Ɉ^N7өvg#uO@_!@cF :IpܼխRn.%).9!t:jꏯP .LU{nNU;ݩK>r3jB3'^^䘠1Md^̾ l%w33 6?kN,g<\#:JjM#G!>,}^|!Bzhv-Pb^Ͷdg'md#Ϗ<,'浸][^QkUYꔥMG {ajht]+еHlZknV]O.ŞU/;إ}2`Ry0,4"QcdJtfwG;IY$EϮ[雜 &uf=' ty*ؑۡ*JWE6m8VmbrmBsdxp[7S0DN|$3d sI\]z6d|5?-e"^f%;ɾ` " A-:q9:^=O⭏JoGE~yҩFGeCQ>BuxrP~@| 7)sCImn: $p}GʠV',ᓦA>BwE3ͷIs7 d).qUs}.wuz]>UwǫwۇwǪKCޑ*a'4Q<;!bdR&#j hB|']y4;iC1^@BVKu@:TE؄Re˱TP7rY&( N)rEǕ{Vt'sUn+Bw[ev9Շޓ,`Zಀ(Tq~M;n͢{Ӈm_Knfj,Di#FlQ3n1vژ;͏8d<{ȏb=!âxq,jii^&pϊY?֓]*q?k.ķt nV $z6 B Dz}4\+f'4l"a~k) BḭW6OHNlH2QSy s0%⾪NxyL'ef>[N) hevB d#4ꕊIͼ+cTC((/Uaקd~l`R˸IzI'@ |жEwrs)FᇇhZC1UھW׆JYc1x4aoQ[}M9] *yCl4VbI92%pa@Rm{[$ThonϪZTGd)ZePSE0S_IJ,%@$Y]r׳KU@Kā[m'(ʟ\G "16ЁPTܼCĈ\ A[SUH2{1_l U%fUK|o9y-PDGIP9E!Zq2fߠ+ڭX15ʋ]m8+(XCB,YϺf^1oEMLrܬ:1MGiU;ϚqLA, F8$ݗnD꥔H J*Գf)/U[û\;;+tB* g枸bA5^-:0 yCng),(Vt7[륭ڳ [Akʘ!b~,Y<{K|p m UOЋ1j Y~1B'Ľ;w_RRZu=r5I/TFꕞME2iP%a41g:B\E(u h Yzqb%I"8:x P\l 27eWndUWy{S4泾pSqM۪eR\8=uo]g&4d6u NJ[Оk M5ە\ nYuT|us&Iz(mf//?:|B>p*LuM1iIw4}or!{6G)k29r/g.6P!(@{ A1]#9RΩ|l/;Mnjx}͖݂]U~<L['E5_Ѐ[ia]6Ȇy\>Te IQEC!Z!"ٖ?LhNhBٺ\ 4p‡S!o6噗Q@igL=Z]ű%,mˬaxsܕ>y\Ћ])ɲ9%ҭS.wUVԝeF渒϶Z_иJ+z$4?.;Lϥ+IOǿGZm5P>G(){v$Z2 s?EOllUl,`C~^ ^\[ttd ddyY`gt`Q]:q'G~A/xsk%^Uxy:;&Da zj"Be_Ze>Y_߄tz7_$ZnIK6ije KOr6O`b" ]#nN}.t(Q@[~p&S§kXkeې ;JtN<>e."9lƵ_=Ȯ%v(2Әpsh&ʥyPϥ)'W qoHK6NPTE}KLW9VvpR;X\ 0;/E͎, =!E5Qq@f{Nz}/GǞ0Oe( yH @>1y>,p8fH6}7JWP4á緒[>%WX! noOW4}Kzz"jJc M/M)d@uTm HuO6"hO M" gn:3uR{ Hdk#R"W܊CHHÉe:wU&A_rq; uWq^Sd^ ר7?VFP'*eŢUVD:EDE+ohWS^7;7!OROmGfv#f;JBw0aPDS<>9ӋN&[˰ 2!%e׫I[c;ŎB֮7a7D ;2x qӫ3WUE՚XvGBw ]4I(cʼny/3,Hitb7Tg{qg_S4`f8J BEł6 Sn)8"瓬<3cB&\iWKzReD#O4|ָ[ F=&;L|C(yӛ6ɁD2|'ʹν)ĕ6[~NiW% EϭVy[Sq6HÒ#'V¿,bRBy+S'2er7C^}%!;噗*7Bɗ=@W _2,Rsy/TA9ʼ;o?8Vc\O*%P2|*8x͕: Q]F^JROxDK_(F?Q"hdDN`U HK`GgUL;Dx"*E&t`GC;(kTsXTTB.IBg}7ABSx듼toO fpV7EGnFeyh5GwKHTXS=>ZZLg*ž;oI.|q3f2w.QmG,SoZK\/!>\E(hBh2Qɚ╼4xy(!Ƈ'35e{J)A3 쾻ʓ'y/ L'j1TbVK>~el(e㶳w<>.DmokoK?4(%u赚4!?#4bvX+fBnY]}`y0Z&M;BZE+'a!BX:}mtͶ޺?j=0Cf (~$ssؑ4l85UU!քL_p vj˔x52& O25vtQ2<Ϊ4\S^N 44XFfŽ~iPڮr+E>tRo5^Z㵁5Oa"6ӳu_:apZ}qx.:{h4I}OٌnQzذBUdkt*_$PRGr̻"^t &"s? L'،V?oz\qPC *w@L*B7skY_ꊅ+R\IDwU~%f.!ywY7 O dV/?F4slpoMK1SRswW&.KȎ\v3h k ђ*q)f6Lx(7W(?ʣE}VzO[?DiQ~+sNnVX $Z oz ?݀e\̜eX(e a(WbD8ykV z5#!ƀPfsCbKrr^]H:>Tw@ڄஞɆm Z!FĔvBm%ƦPyL[^M4 WacBι dwJbeWTK1lۥA_"j\2{ĎߝM|qE|?kC3>掮ȐS筽lDo%}5ID= je&~%]p6,Kt64 &-Bi&*KWea* oB,:PWEF6yC7[$@vuɛT?rtPOxxwLEQNyںb7MLfV 6M[vdrd.0uܩMf-p6yd^ƣGOIu#&5o}`7= ;+$]Vq$|@$;[Z@y^NLE2f+ܷ ^׎ SWAys\h7cnR[@>k!ҭT&<] ?[I˺Lyxჺn=OzK^k91Qk%ayؒ}g0vg(8@\J4df[|?<;v.*ćª (2z鏡Ph Mxy'R4ֳP~ Jc_lͼ]@۷kS~?fX KvgVJtyTЧ1-$b rz-v&nzd;^nF ]ɽ9P+kR$Ur×hmI][ --<%Ҷ2|x[Z֑ݫ8ʼRq\Qc@dyf+ܲՋ~IѬV%-ANDCjݻ6}9!lsg9a~SBm -Dop6NU6TN'B |?o XA;ƠyR_5oLH;j  BEq ƥ/ؠJF,Pb~ eTGpzOajPJ 4ʯ&(Γ8rGEDOPl%g9߈P]wdmXf1w9~S] e8HuL/4YsEiPr̃yry:- }2qZ{2lgY K ym:uV.O:BQUa7AIw3^ZMCJ ^Mt,tajUt/_+؝"v"g+{](M+2#2 ;DlYc'0PAH:jXxo͘T(\=>f27*wH7*U0?6wyy.TVо>gאBhyood'xz_S\O] ܈pskE@JBf+6 u7W)L\#Y2Q"x)3/KW >DѺ*_ I:~Q3-~hSW@KNj};wKEEWg&(+(q܌nCw 5M6uGpLɯTn6껔$)FYQ uc[Ŷt}CݾLgtQXe?ZjM7Eyw`2:|u~J`]eF%Fǒ<5)sN ^&*?&e}˛N|G8^VP!\x:t2I6~$߿Fp*S_&֙7rוcH_ۏCN¤:š5-,p;J8&DxwJ7Ϭv?U",1k3e&-Ut2N28 6ߧ6yhwA&|j=,?d CJ@ޠGGB~53/`E2=A*tǏw์] QbU<ܙ5]-*1ʂY=!Fgd@˟ve泦t)]'E%Tz2/:(]- igg'浖}yr5$QɫyaBjI瓓˵`\ b홮 |^WU 򶏴Ձ~z&>$7\=9.+:!b6?{NB6oo}^ƾIpR?h%PD>Lli*ۜ M63l%f,1xm1k&Rl@[6`̬br0hmU6[鼙,r[br_!2&l':˖X@K(BS_oGhSE.昪`}5Yʼ4;8W *f>̧{۶I$ˢaRߴ٥|K8N'n8O.Y2Γ@_6γMH72_L,.]ݭSE]7B71 |XExOIbS"/؄oCҞ×FYf|ӰՎYChCӪocHu5L do!̏e4GHduʖlF$:=S*p5I7M hCƘ0eBSl :֗2V ]QT|zF S@$ϜW 9)Fޠ葨؂gD:Myf$k5b-TffF=& ±hhծ@wN|9ͼ(H (@}F0)"C} jE:b7{>ujuT"jx5U\ kC ',EYs3qaOO:n+֑S= Zȵҗ]Yv" %:,'ofy-RcԚr7]~7q#:2{W9<3OG-پnDw=#\"IT]l Rr۳x C:M&NG6̻H2Gҫ$*,W |.Raw`zqԱ\_jN}"ݬnIssBAY}Xdz^=w]D}xy੫R.yu\A4n]7c(uلDC >޵!%К'x'MߵeHP81@"[B].bI"׷ꊓHhY8=֞ D֔ _^iSckΈݙ[::; ͊<$qZ&  iv}㶡;mЌJIr==6I!FPy~䙷1tgAذ|O,G쾛'ETn2c!3ڄՀUpXJh*<7K<_Qw5cmE搎>|p lIQ8uVWߪdFFD~Z rfТ۸&e&ms !]@j2wj4D(vC~yIQ*Tb8lw ޲^RF{3$49\7 lж]6ƸnsKWK=XG@~99 vM.{I+'?/j)~/FS1X+|RNHɰ{A2"Uz/'TwHݼۧuȧOiea@|\)ogt7b; 㠤h e@W"[;\e4m4&wo= "S# _H>^xRXUhܑuXHK^,4'v~R2vqGFfqbD6i*.@?=Ri$WUR}1ojzƇQc$?B[TXQH+rV+ʝ#LaL(}$tNӹ9Ӊ<6է$x/, cr^:Xb-kDO'hp3 DaR$KN1,A^@q &9yHK}g{M㳷SF{jmCL ']c`,3*-\Ou$N"HߡgdܨP IBڏq"QAAh͍//ȓLl^{M[>K U8+]G8\lǦ߸\$BkH4+-z:UxdK捃DmrC9VU& U(/+@7dz'% i6-x$Nk-%_'ŇZ?հqw/C%EQcFrZתgM6hp`7cF7Ab&TDŽx1rC^&Y, hhn/`D?׷RO?'fmPT3)Зr/%Ko$5?n4'J TV^X4 nt ;n!&!K+R=#C&X`[V=n/Ԫ k'd^ޡw_N`0ND#X toc0-k;tf'qY7C'3e.T m)?(K*Pvyq0V@+xf/Ͻ#.;ވM<̬Iز:he{PWzO{}Zl7ڴ2/:\ȗ9 $\=~#C0.ּS0@v72pț]÷gs1xNX3;M+(vhAȏ3LGEŴS` Eˤ57'UuPF`a}G0=~hl+ CУ 2OtI="1iC\l!zGl>BG)IlA'$cȗI [ANʐ̫㍟JJ|lifL&*&V~P7-0)7q4i SI{*s:c% Hl&h9]#lίM=p)׮eZ .?e@$8Imf>'kְdVa;4l#cKI IFƍ}"9fL̈Gy3;gǂm˦zY4z6Ag@;2g@;r}v s³LLOFjl';^ʧ`^ؾC57b5=4:hϫmR3u5?Q_S$u xL72ʗNfmTWmFxƏ>JTշN; l7T:瘅9n瓵͟Yi9[)mtg&kϐl^4RsG)F{|>lf'ѡ/_a(vcT&MŦWW 0.o`ޞ/B3 1@חWhOhɗ$&s 9Ы7y?3]<І <^a9*KFzY%n (NF!0ΙYE?4ɉ1nz+Z]uǪ8zn-WnwuJwۂm)vEYS,B2lfhlSB},[ @%J1\߸BZiIEoF-gabכ8 !c@wCó|7|ULi?:7m̿PB+*)3x^cwv633kdZl ~JVmev^wK<^.+b^ .}~) AY&!1]ʵW$i˵ۑTFla[32;2bBw Hp o4_1]z}ӥa?XbcN'T'|oR'|ܰ`؇v+E2䷟6HЀs}{s~j G:PL}K!hY/[S GYؾ|] {OˆQO xgmw`ʏv)VK594w\X6@3#{*NeԞc&Yx3 02^V: .cgޭ3Zx+|&m@E/95Pw}p,ń"L/^%rV'H$=E'.hs7iX$l%bPf:BMz풍+1%L떂JrSYrپ(q0_;rddBpv0C|A(26r\0/pǪ%OV@ aU:SP*[1cJ!f,Y(*ty?-(3$Ё!IZ;"On^ĬKFFL\ CV8\'M,n/D=CҭTX )p4 B6;l"lhId #CN^e71A]A 4y@T^LԉUC>"xgUٸT !n_McrRPrI$G2ܬpӱ[#(/P^esAzݚRDVbfN~2RѡA* IFKwԸn4Ti=Wk]$A$Ks@IP¾=S[ͫXP)z _=HCxbynHf̊d->J69-@l@I;BЋn3&7{|Kn3rQsgCf9-/Lx@Y?#~];PG9@z ͙i_wRpɤ7J"Dqz2IdeJ[b^o$뭢PL'OB7kV)_s䠮b7SN鎇- Hvȟ>m ByK|3*ӎQeZGcf;ųM噌&hPu<0̠<`|2 }GؓNܰ Ag`"n&֪EԢ]gNWn4BDVu4v0hi4oUl~pkUzJ=)@B22T c H ]POyRl3ɠ=YO[N!8hw|d^nvzT(k* fӦ6]Pn*&D6 yQ4-o.?({ϵTط#@}դE<%6XUг-ӊzûΧmmP:p3+e7݃WA LZAA{C|dgwPq!ZayA]z>n~4}5hdPMZqG˼pw"ͪ;dY ̆z.N?"I7xIy͹ =brU`w Q[v/aڹ#i"^P ͝ Λsb4sbcqCMsJMԥl2rQ㵖~{&Ya$ hfc8u8·Cڐ}g#mZOSđ2D ,1ذ:&(&7>6'+5С v` W /=r7bc[:AW͸Jj!y n@OʚPfy-|tbeo7Ǩұ9IF^tÖƾE2*fGH;zAhG[RcKB^L߽L~˥q](:ve=I}F:4؆J>8Q12! n^`&ߌ Ǻ>6f5D d?9h8,%9FktPBO~K̲!b Z& %-ȥ *-+wGЂte?j%_3?0eA4;q\EZ.H-Hy}!miІKud"e y+e hf 9=1IF,"}|5yt5x2;j\Y$<@Cj9FP";u>#$ ׶x!xo)ç1A$ϒa96_Ì[@CC ^U9~#!CޜY(BsbDs]Ϧԥ=*#z &vB:Y{%fe5/]]mxT !@^RX),eH2c.Y~#A9! \ڒYD|)(;MLǚPwm5kނڧiN@Wi6کܺwE cp7ESL~F*qxtBXv z | S qO[?dPYs\ODMl1]|vy^ʱ;z8#v/m$t*RӶ:UI?e.ӽ߂i:q'2bqA.`. blR mSȌL U){KYP Zv<þUR<..ljW< g 5w$Q2l":&4%.$ a!7Ӿ6Drhu"WFU/=v#s M#H~ɸ: 5֮c"@L *ӴxKeΉteC5).rVA:]看Nq8}N.O6P3( <|FLO-vX jrմ82.ӅwPn5J6w^Tq M@3Hq g>yؤq&qaV 8!oEJnsV^YXBn7(_qU/g@@rJ,︛q  hOx7?=y&yK\phCBڸL a mρF"ז`OSSnaueCSٜǴΐ {;M4Cs-8.eI/SFzs5,mzTpOa/n[{|}<ؿ7An،q7Dc; U,5zA{LX ?ɦ+-4 +xߛ& - l3(N&4 ؔx;&6(؀$v󙳉<^#Wǻl.aqMy.iɮЋ|0ZؐzBٍ/.궦%odhr/ɔRwhK1m)-Y*/`?zʏGHu@5pA\ܷ_:x.{:P2i^/xDGwɿyOK5'BM #C?ezM_7ppH_[߹i A4M*V2$fRMX*UunjCb}Αe̿11YF8ۻ!_ګg(&~v;:4a9}~N׌ܴ6 v2vx N>@f&9:=;pVB3  ۗK$×qo"M*fAޮșA}h. 6r&}#F.^!0c.L 0HuN2o؅P,e*@wnrt|((De>~rc%7=qp5j%7A ܃x9]U/@ iڙMDzmCQŌj;Id ]0) G*0iỖ̿M؞s.R&&usܥPw:U \;n2dh׶wm]d Ml]Xi'Ԉ( =]h~:E(訅aOf -]iw4Y{ǰJNF sl8R07*>m'[gh#0= Ju zE)˵/]$=NfM2poސMƊ*$~չ^Lg)ֈ9 -C4F#zT b1}*uJu~HXcUH7e$T0'())W͂s8jێ׶-p֮τ.H3Z٧{BhV#GW)57jw46 #B!GoW^Ip4⠩sPzP!*s뤁_g]h?"G9EX^+Stȵ/~^ToƤ]b|_f>CkJ}e1 @,o:[_Cٰ۫M xC)hsIJµC%T&׍Ӊ댸TDNQ%:;ݿ(ЮQnXlI'Ԗ`ˆۆ5ӥ)ecA7o)^О0#fXcjB GE~*W0|ӹw٦o&"7%4~:]4 _B#]_p#v@wڶssx" DŽΝe:A=ы2y{ߴν) OЪMxM^&oj4V0@΢Vf1Tdiġ{2 ^N!p*MtcDR2uV ;֐;O"Yq9Q:,Yf3bm.E Kv3WtPi2Iϻvex=Uv{{xK$u=W*p~!NPCa0JmF̦gJx*bZ.;S@0J/u5C;#X!$>*=y2Xl?K7<1)u"i{M&a+wcN +6'iQ!PZ_^<Ac]Ub3ЮkXqё{M[JwN9Gw]@)zIgB&wr!wĽιT;{Ο0 DJe[9sv + B7dȆ)g'ۊ% l;Vފ ;A8y=I@t#8nh\W(_tNcҼefwf!y' 33BK<@Zu&O=M,[;7'-eQA`3M9_%NCƜ4K0)NhX^ 3͍Ùfo.r]N>5j+[ɁeK4}XCM@y<$iR>u;'ɚWrx{ وs8) &p:&VZၹچ }CJHuל8u@c ^䚞m@y瘖7{ BcB:Il*X?DjtJ2W(fξ ą IENsk^[Ĉ8%0Гh{"AM4aB)'EW{F $̆2Ƃ^ r  ^F4{{śo|oo7d'daP$w W蟱ap/Go ^tqNI;X"Ub3'@VI[K#6@AsEf0'}[Djgt墩's7hD-g5v}PDfB(|}{ ~4o Q49_XSހx9MFlT&b:GYhny}ѹvr?eS ?6Z)T<.=~>>q9P::ҽKT|X>/haQ(_ >ܾSuXeEČ+\(AP*jv=/om / _qMc98_8|Kk(dt'py}vUZ7E߽d7fa`܆h^'<ꙿ7&Mif+8룛~?ŞzncXI=YX2ep)E7b˞P>FF9]2:vq#-^^A6 ynQ[-`^IWa,Bb[póG1\sD:saOOo  k=Fmݍݘ-+|7XP1?@6wй7́Ajn.sf uE"NPnYs(I@#S'-Gt)-pSq#;u~NỾa%=fRxK$c0>Gj*P$K4s>^`P̓^>uN5=cs7_>\޾ 2e&MA%gyu{Kwj= @|TsPYY8Xܱ9ҩNr1.1SÏ*n:=^#ğ}[sC;7`$3o#ϧ}MYcL~jn(s>2>ӎpJtJ9' OL<|lĹJ0;u>Yed*%u`ч&T6`Bu϶ȫG}:'A;pVrk r.w>{}L@wKTH<6gO5zfr}Չ)i%P<c sN`) euʞLJ$;Es e?x{ ՛(wʠyh:ޞ$isB!Ji^atJ(wFw) Ux&eV5V$\ͱ.| ͂;%_,@;E% F& <TBK$G_^U X 椴&_'mKKvM:%q/lmR:'ڌo#*i0Y T|/IΣs9@.OgмL4'Ufc6$ߖ y":)q#v0f|e:oTXlPD͎s(iβW;GؼC҃,ݑwn?wtڼn0n4tY{:-7C!Pv}7x߂.{ؾ;0{Kc*%w:^f3da&f[A)>Q?.H!9UvM3am( 4ITAiaZ~RA7'eG(G_Tn*SV{g N1lTP۵Fh؃ %y+mcBz/[P= ?@bKH{'i6|4{aN4ʮ+cAOa-_J5PLfr9UPVYx}LG,՛<|̂rdʎ;uKҳ׋p)@öhކiE:*6cԠ 34g<ޒw*JpdWOg+IHt3& ufl[E#dj`뷎m>.l@zWHv~=Mqg7 9;#b4ASozub< s71 ɯ~5II9L\\$aM;vz{ ԄVC|ժB c\6tȡ1ƂN=Ȗ:AD7+H=):v*źlX)ߜeV#g'D p}-bH01*+@1Vd`pΪSX vbGQItQf>k%Oz~Y7PBVX>̲.^M>VW0|9Aٵ8@uTgB2~DCӆFt#;%б,kIޣam5Gb (D#hܯR=}68.|I+tf\cvqhoAfhXrAe$6M&јR+`Y7(Q{:x+۠$*c)C;fc<쮏Wwz<]ugsEh (FK|zNiPmsYsԷKf_+ͳyIbӲ)=hMz|'1َd[@qVcsg0uJ鹽yu$s3TӮrWA`_uN釼N=Dɍ'wk{~I&U$AZƒ P8~Biۓdf ? Rd>؇M'-z=Ȳ&/%ˤZ?d"H$%(fnrN@yAwe ~f)$CS wZ+irB+ࡀë  :9 &9y}ue 2|i?ܞgIܟBulxV 'VE]TRNmR K˾ð.1B=Z !EO672+$'9D s`[lzDm#بѶkU:}s{n|O8G]Kj>eSPd[=U W!=~@9 lvu;6M'Hqܛ)AZPݵn]h]0\ՐriXHx%# :ʼJZΧHJs]VnvqPBr<>-n/\7{o1+広%?qT O}Zӏ~3o;L:FP'z]c`ÑS%/̖b>gJCnLjwChcRm US8&1>LOP+Z2;nO6:2>רnlC׍9 Uj{^X5%{<#|5Q`]sVy|/Ƣǎ:ZlOBXV^"4C*7_& w"oϐvִ7lshN>y7AT@ލOf1Ff?<^7"t9j *dReg~P֗&p v0r50~[ pD^pj~jw8ڥ;׮Y`Mg6/uI^W֜.G9`ᥡk]!"3kH(e3K>h.,:ڊBXjs}O+{g룈$C&:l avQSP^;_F;4^|ewsT׹1Kا@!iNph北m(?`!/Iq@=V#8MaP 7E踜y w/dZvv gB'λ=?ys︡+qif '} P!3ouK./Br؂WPg P~=nrn0¢mf02d)x9g +e 亮-9h 98FzЄ֭;LJmɭ /S|xF6| (4r8f-6afF̤)zSayEwd尶W}w{G'cn_ڧTnUx)u\3@˲.B o6OC7 1ag`fk'LKO=aP!1{.Ej#Aa N~EÒrAew9/mr\\}'u.0cɑ;=?40C/'ԃf{`; dXg=#N!B ںˊ[)܃r=tݘ{Ȁ6[?]ᣰfUxҴ:ȵK3 /AO\>#dwrHI7'@kkTkݩ֑DHn0w%'B{  })h, 7ƸG}F%^T|ڿd#?"ƥ)1N+Ͽ;|>$qwxcމA#'&*P?OhS! E wytKæM?ph7,w<'%.`MkymTWccݦ= yؼ u lO<}|,#f?yhl/~U=cƠbI Ԟwi")y옰-#tyYK%n:}=b\$qo/y|5ﻻG\`DC֝z`!X)8UV*_.YR;tuB+ϵ:uϕ)63`PLv,,WhXzpi*KP*ˏ;}nBk15h`I X1M%6}cDC5drp*^v9;h,V}|J bn>hݫlY~'iDg(3eGQo,tUY/ˮlO(=1|A~[c$#gqj˺T!wCXj:c'iG3㝳|Rk{СY ׿Ķ'{>S۬} #  ?n#k6t291? 8"x8+[ Zs IMg]-%Z8Y;g-BrOB#8Xc; 弣/ֿJ/Q۴ugxN!s0^ekPm P'xR\/CsSxD>8Ev֯(g/n!{z&v&aHx 2U߳Bmv ǒ$w&4n>Hi Tom#rΘ11{k!%~c's )2ݖ}d5xRjv(B<6/{0&=៛2e.ۗvsB>Ovɋl9%?=,={@1 HL@[G {dHrg̨3DN4iL .''25ҎHc}Fց*hS YNj[,Tm|ː+w*R(aP9eoa6GLrH:GQ}_lcz۵Su?#ɿ(Oܩ%s-`ZyxwPVZUGpls^ NhmrgC/x*jbr4h*%G#uNZ2ݻ&;is<>k)Zszѵa?tD6糣V~-똇H+1/Kc?ԟFy%:: b~0CΕ驤~|`)؍ݠ8"Ndߢ#Kt.sK4Rdh iYT ClWR4W']P|`;oEr8vrV]B{sSS2ER~$8+8;Z[Urcw  Wn?o |9.%cU@;7~uD5H.qtl8%|S$l+"ziՆ]_rJ& 5XԄZ`o/Β4"#g`!pV2V)ǦKB0HS6t2U1.OLg~8ÉϫO{u7i?=™\KlGPټC bY(\nCRl!N}Il5 p ؼť!ܣ@YP\l7:G187Rx7R5&XJ7v5}(y"`qXY\E 8I~P eT43'RDr<4-_1]1PfIG1LvpE6j'+MXu:NײĊ-RS5* ڻ%粗0 X7m_T-Xyf7tacP7FEeAu\\=\#˰#j|*GCkI%\GUDar}t:5eڴ10Ps|2dQoδ6ʋ7 p~œ]oow\*H_)Ag8Ajy}I`'s@ j, |^y5鸍 |7a</^u 7k Ss9Bc?k"8rΧ/'l-NZ|j uh;#_ӹqڳaIJP,A5êz߈IHB>)54h/=Вc 7O%;\ ȜÆnHuL [ZI7p2}:~@DsrTk\g2 gykCN~QNrA?yT}"aӶLTҵ7švA.2|_ oް)Y)AϺOP]BC^X>Q>F ĦȾM >l'ukmVB<J/Tnz`da3MP?BLƻ|ċڹ=ȃ9U?C:߲󁇲 z${HztØ8Ȁd/;Цffb|(ԬXP_[R9#.ww **aUC$l)Y|HSM9q'=T4u<>WcG.̵Di2O# 㩃ޖo< Pa*dHY[;9 ==7-bM#x[1DsǪ#4h!% 4Həjí:)+!Fl?\`| #?" ŃEҾyFfY)kF">gNrG8WqلT/heVyDzAsS_άnt >E`S|aߺ^m6u >i O0Wg3tኴ0D +iݹ:H-uǁ&}vZN[\1~[!:|dQ 뮒)g|= 4i91$lᮑ ρTYnk{f5;$Rν:T3= w@nwJVVԗi;3Лn+7*'掐zUvuhL^nlw^jc<ôm$|&ҋfqr%"w] j_#<%K%qBrx:^iKmtڽSPd<|u;We$Vs\婝-hAbi#}IM%r~n؜sM% {$GtE-4IW|y|C>} 5?1VgFS'*wpꃍN;Ml^gG %_9险)G \NG\ }.kt) dC癃/ T+~ -44b*nM!MAK =58 l(njƈPsRf=ǴLFss`u B(*SNQ+_t:/ .XlXAy);zʜb.=T eP_=䴲SM4Ҷy9)%CEhQq}`~۪c8vu[9}Y|eݶ*s0-0ϲs٨7 &r%lAMch^m~<Ѧq/C֌ʞ?$`? irҏWd~!I }~l?(x;~̺,au@0h߯Zv|)xGp /3E4OԹ,oCO!6Tva`]qcL# 4q¥H935jX)tq_3$ϋ$& :s:jWWSDߤ tasf~My 'ᲦH&F ;+0 jȔ^:ݜgх":.anR_ [Y ܌ B2$͋1-'GPaKO SR9&gJEbxـ]4%IڗHCUr')i(ѦR!jd^9UU m|B#nR~ T./헠,]@_#n⿣ϧ氒s,nhtRm/sk7Y} KtE4EaD\~=2NaOD gJG[\;SXس٧lf|μXJƶE!\!B# 7VN*N)[ZAdeJ$vWîԽ(7 8]Ook1$U< g eGGaCdҔJP7Kމ^w 2'op%}pH+eޖ NķJ@Tqo%:&]54/ C>M,NCUeJ䁳/z9_?P}Yuһ(pS@Yrm{-;jX"Ne[{ny[獀%g(Rwfy=6ph2) 0B#qbwC8d~݋")4%8}d[t6  d. , tIbCAE5lU˚OGUYa_<]ieG6'}>KP/uJ/gۄ3<*ST7+L-+lh>X].M>Pc=//K,(9n-n4ú0%TI8A+ 'kѭܰU]'~jz?6ofq"DH6RX\z0Y%!p*aÃkC~7d€B6Qv_:›=yc͋\,PQbI \'?7_x߂5grTl~z&c)M5&E;x&o2+O \݄r!muίMds].RRs(%.%ٙmtr 9/kdKT1B JtL rD-KocVMt([wnɸ=HKDsb嘵(DYeMLmt϶y /j/C,lzDV?#$<^qe c r<g"|>fSKlџ{Q.Kv~%yoɭkFnM;w r!' }yzJrLNm7# ;]$[򍢗?b*ɼkmՆum|xd]kϲ9zdO[;$žP\!bY׵Jq,謹TR[+T91PգϽK^pb&!N&n yn3E[¨momuX_Qޯ$ hBOP٫cjWUD˖H^C`{h{L V 8_@:-1vSh?遚 [ڍ}yPC /|Lxbs,4, +ۻ2I;3<{źg^=ZH#Cu6.S(;L^Kv2aV#N MCu;\ =Ct#0MچJojm5=7wVI7P!v-Lbanh.:L<Ƽ l~,ym9GUEǻѳ:L,ҼU' dXޡXaR,paߤi63 M's ٻLˣ&8&cS)gUKpwk,SC~mr oYo8_sLNn*N@HaS?wm:'LZMT.ER鈲)J[k'[ɵD B$]` !$^4 v;2-i'D;f8^ϼY(|앷 )s)Jb-٫!~MJ:%Twv>)=wJ\ٷ6YbSJĹzVA)|vwц~@vs;u]s:Ժ{dPx'h93QQ# E ufPuQkr+ܴM5nȇ*o+CZ7u)[3&vwtRCpü͠:bJ nLXznJE`^.B ]YMóyo ~s, k玡G=X`w[G%/09nMw}I"4n~ dTKRw?l6mi9FsYm3дS{aGA\Tu~rS(:z%OrRVR&h>G M@ vG~EuCS*{cZm"vCQoϥAX4f9cnth?%˓J~J>=瓓jBTGm΄ ᯴P_AJL̊<{lй-(VkgYJ2Y)sӪRfZOM c-n`,* dD/R x8*"^^䜝aJtyLlJ芍Xut4E wvGom)tA,EU*˛Dj5oxPzIKԻGN3LBG鷔]%I*Pkhq:*9Ezy%`NIgĤSѐuJ+MZym^Iogg_睂J!\_L<!)G~ͣ`AS +Gix-6e35:NEpWQĪ;wT L;?0)祃 ŷT'u,%f,WZ+](}uEl"gbvK]Zgp1d6~؍= hU*J=V wBN '%Q4<>G xǓ5v!sn]>/.pz i#-03 rA , K339B}@D#2w2);O8xJZQ=wfz M7 3g߆PGר<!ӜN=,eFK{O_}:` =^E2!p'nf<¹r6gOPN'No3I=bh9Z{ՂMvS =˃N! j@w쩧>q մzB5/rߝ 4y#l,wnCYOM6dY),,8(>>y#>z} >n~މr=-[hnp#R\n:" Y~r (j-` D (˾;Mż< Whwgxmi5< -Eel ݖE~iR*:*d{ !qaUn*>)MX6<9 Õ:'IR;u$ HH>U ?Y6!:(PnUQo.'OPJsخW}1E{ W7CwF*̪n(7[YC]xح+zWp!zv{'NݞDLE qcT1 }[?ZW4'YzNX mVyq{v pd}\ YqEY9}fwrqb]&SMqGsy'*瞧u0Na{G:T!tpD眪=BBcMeF>XTԓތ ;\s~Œ)y =SoD3tN:3 ]nEߡ0s& $h;W।* V9cLoTgOv|wX[x"ZLE4; ;t@VhGf=r{`tN/܈Fq#`j9;!Cr>x"igG.p'<=Z;}*8AT8cHz# lP*HXo.5`:=}HPr*b"oexY<1/]2aͷsJ O ,v/'Biihu$̑@yKw6вȍM y4IiWQ*[Ƚ)|ۑ Pf=P"uvyzL. i'.7ُ0hAr~u<&@`>*iWmL''ԋi/Ѱ~9qBvWD[ UOe<KFC&Oojd+ q)t7~[,5)'[BIChiL! ;m:G*NM_˖\+y`^03N\௥M22.}xzo)BLg@e8 J K) $ 6;R˾ od5w9og]*b@[.|/?הSR"r(AI}`@K℺~H@d7^^#6SBv0[JJ>^'ۋZu! YŜ!`fV_kY6OziAO's5<A:vMCs]#M^E2'²l\(*9\]uʹnv=]FGx~Nb݄y^S5Q]Sͣ`]3|O,6Ń m^ľc탙m^]smeATʞF\32O6$bqI@ݩu=@L5*3_M9nʗ쳿~0pbǪ04|Um^umCx!lJf0cmo)<&sPS/ ̲VEDžPSl,l}ݲ\p,NP>Y wOZs@F%W3ko8wBy RTh$M_K,G}x=-=@(Q]P"%;)u-diqsPw]gnFG8,R.W5zm3;q{`rNB{ @y׾;`6th{iY N+Y$,P! +M900Y="148$r-3¬%䪸h'TT|e /uivQ;fi;:S=Y\hA"i"/ mMK=0AvyWDp Vu:]31sFũ9ĩ#yXz~3d?O3"'^?qȚI ';N$=X) \@4Ih\3%(=~XM3TICXD|cR,3 &vSI3d'҉ ^kupY\H`mG2<+GLNc1 ;2:mlvKsΪB'^Z8plUqBv's/,(%F9%979jLh~m}Eʢ[3K.$y_j&p: ! AJ29zs֤| 1/Q~T6lyM5/8ҷFMg8 "Gԙ,y R:ٷf|Ay4; |r&@-S\J1/9ˆ̻SR٧} 7x vSyF_OOj{k9ST}Բ $ V>!Ⱕ㑭nnZÿnGɘ&;(7B^GgJ?ݖi?/$ 2dEMJ?w9v^ZX U0§gT^wya]k6j5;B FKL8 `' Nc1ee% NZ8s6\>ZInBEPu 7PBy1ӡ|;f%8ìWh0ay^Pѽ\vn@_Olnj؅j*54֖-Vr K7`ҹZ +~nĘ)z>b<>SjWquξ;)>{N2yU&Gk7Uo i|#O{4d캉&m=O53sL>}dI&:g&rio(PhT2~`=594nMuYE׊Tg.I򝤹Dg II*^@$Ί Z|SC,^sVB`߻L ?h#{uʆ4ukڱG/}-ϊE دw^OlT<3-UZ="7p;uA"ы}b:!>$'&^r0q~8nq;$}g3:MHyL{vP\eq@1*94-"[d>7L# IF#Brbi|AdjWINEdmRShsW"F# }o.솔_r样hh}3}.|tz`o/gH{, 5+} :8hgՐLPe$><^DFM"Ʋeޒb}$=RLdH>d!&=k@Ąx4,x|_ç&9 ܞ7PA{D9 ѼCv-پ7>{LW1Z&(x% Yke+ѬFLI=P^zIsQ*@2mLTO4j̨ ЬӖ;iQ?xI$.[N"Lͳk^|ٗy"^ٛDCVg+G+{K: ۶d(`It߽ha+FaB<7Qq1 juۏ !tźmw/H;DZN9~ +-u<<{Ow2B"e*YTT'Ճ6"Ou]+jO(oͦ K IߝoV]L*7Ψ 3q" Ub$"~[^ y(gbc0-/3ȉq9D ,v2%{~@?e-ZS  P&ޝO1<"*ss% f4' U yBy9Wk7;ĥr<+wgL3I g[ S~(O5=Z \{S;hJӳ~#ۤi+)sI &@~6niHQPYUGĜt6wf*;9rT eBvj`0ݭߝP霽4|p eٲD;JhT7g* nmNi}cudثs6:"aRH}?=Lzȟ0MxZkگYm_ g60{O g3`R=^cӝ]oyBA[VX:R%h'*aN}L(e$|$wAJ .ꠃ,^E@93ΨUk>㪿>o .*j:xI$4uWު 2MT0l1pO+Y>BQ$ [,&[%Vl6ss,;\@g^#c)p/1G O8Hc q)hb+,l(.Gηla)m$ӧNaG r? Cd&R1:ee4= ?+x&]^^C5zV}(êbKmKPxjiW* g<9A~㆏5R>Ob뼅U"1.u,Rsk^C**<+|wGC(Ԯb5i1,T%-go|JK$QcauE/hO]ZqN&%KXîwĩwhi#@_w~ <8kT02Kv4vn27 ܌z{0Y`ږ0r&xU`4m^ ;5 oyŃ9\u8;bv<جN(F`tfWp❃Gw_X%{mR!qjֿd~o&4?vc Դ$_t.!3:gN#|ma-ZՈ,=Iк]zi8/H/S U][j싙3Y7M$o-RCl;/%M`}Nu튺;>fJbnhe#<e(i{'r{d" ?saAPAwY&Y5F?5:ucAޛu:Q:k;bՆ _~cOc6Kvc"6!5FI19F^ںMHDBlg{B9 ))9 .[ڳ #u*uR]' C[mS͎a(Qd.Ǵ k}%uN> /9QӆL\U{W=Q4,gֺms5&)svY̗D'YB<hC(h#שhZ FM+͊emuk7gN3,oЊߠz0'sG1=lu: XG{-{rŏX"G7lkS95P~fKPѢ >{ AF|zWNm-mx. U~9kj!>#w,9G~EH7sa0nۼ=taIQ:[n ^KߍL-jDǿDžj(DCir5- [κgá &KDeG~nG9j%| #ݣ!gde'ϱy;rVNh┓;){\J!=}XXzD70't; FcZ{`*Z݅._| sS.% э*PM򲁞pB#璤yT>fͶ"f۴Of5ykE~%[WP(INv T~./[^y)OeTm4vԱ yT&6sz-䨂ꃧSm/L9l;K:0tQu\[؈+fTtisch_XgAԔSȸ_xwiu޵Tʰpdgbg^VZOYV]"{m"n.z%c9AF΍e*[݉,O-)'':@W'CA ̅J|-&#­~FER :SHuX\IOkF{ 6/:s0y$0lX\uv/-4y`OK?R`Fy#`NA 6xqw68UglڄX{L.;LJ5G)SdhgwϨg, Jã{TrUH߰`e/T%dTrQS7|뾶l*˅ܽtFEH/e{]a5'ucQB(Cyu3>j ;^h LdM[g0ǃ؉n਒/z$35l{ß#M/N)4w+'K' >_=+|Lq@¨/q:)84':=ƃ݅#dt߯:li?OjQQrJ94%z6ivRsSU$Unv6l尿 4ǝoiY㶦sr?diCQRq7"5[vp#}siGs}]LC_bti Q|aɧ[!Rg n@As Jwy^iܽ﮽K'AޡӧG;X@Ӧs̐7_sM-s dIlT.0 𛏺TFx_(w, iidG~/k{48C8VEƧ_ҺvЪH{-.NbN47s#f7VrMZCu;-`wOgৌ|:Pv뤖N- = -P!˾?2|ML$g mG# bm`׽H)ڃϮ6i;, t6V~uiK+Dٴz@O! dStO%w@3vFLjc`M`=2Dx9qa/v'EM{5 vT=2imh/j`PCZ}o.'@9U1;Qٽ  Q\tlv"po2 >X5WPRAv(m7x=tojyu!z{-#Jv.%'( W ѸA.Ymjja{?E]簼 $9w'}oæ %-nATbODt7p۝Yf/G T(z)6a9{/(3ۓtrY"  nXzlplwnrLG<0hJUλU0n{2w鹝Q)ym-NBDxɄBd+40.L$2%1g-ܟ)'4 u۷kXq'EEO!3;eI$N鰅9 d^#!whA:R,way{p/XAZU/YXzQehv+pX=(<]F 5ura<{t?_5? ۉ~4 C`NL^7(q7aY.r=}r/` t׍vM$">h{L(==62}[a?R {0it"!D(\##5ϟct:w]dEC?r[)U8P)"A 1<1~6BdYϖ**_Oll'i4Qo}<lK!?%O@]VԲ]sKxwS)OjQYOQ~͟D,U d%s픜ԡڟ3+vZ&P`\E1A9s^1{lW_¦}^a} &;JmEi vŬ2mB+{y|F,Pcde ++QIt!ayTs!7\hcϚa>ȼ)D|F%[qTZ'6rMYNBlٴWn`D\(tDD蝵L8?I$[i̯@%,Qz?;l6ws:dqCdݮB흟C)rH<[G< '3qs!s㦫9]ͯX>D "MQ /%4{FuNCaIVӉTOdfTN@њ0&H{"<Ѭ$”sF l5'N$c1R>vp-l&9Ry& -IPz'i,Jcj如 }~ɘ2 `nVT'M͗xF XԙXa&vpvs/-ݣ/[t910m^1gm_VQA >1W)z'/KncȞMۥ~nRC%1mWթ;tPn\M[ŏ B)16|Z/O?>>2뵖 ýx5{hn<ϡW6žD}((+VmZEbBo(0 iA~9t,AMAx*~ޤ;ʎQ:ܸ{Sphgh#?ؿ1؀]\٧$JK .5wCYhw5ԗ: U'P >TKNma#_-=ţ@m ?]2+x0#Bzu5`S';{wr޷1N=U9M9pv6W߲o\Axf\ZZg_] y.IIcUW)8gA5}G|K9Q-Z n;V)8P(yhs| ԉH8+nXpn:KN`0ѬeyFєTYqS1;~>~zQ%g^0 ԧS>h?tU Jӽ2p j'3[g .8)fH?4{z{H?2g|C[`zZA-ӤZ 1\.4KΰD~"{^wɹڈy((hMAKFbWu$5lsݠ݆N mTFc6nP抛{Ή]Z^ő{kwN9s9ez'so}44.|㯆|k!BAE-`D~"qMtxˠU6l!t^`[R9]#nj&kJ?H_NdCɸ6_%|t󜻢INLK-*ȵX:e09w<Z4)UzpJMM&A luZgIEXJgfϑ6?a ]5G;F 2>[?wgyztvީyN;][4|*RdAuʦ*cCys>;G0lL;|/`m`~1ܠW +~^v8W ~-w4:r .1M5O4K6r!;PG(h\l"sF0!Ij:[ a`{%~z-imlw]ږ<xO[JVGVkFDYy֥ݣud}xI~G 24"a]0v2m #+M1Rw VoZga3RKoZ߄_^\4 Ds3':#:q^"_|@)׮|fbݵ8Ͱv^^*`BOIdP%=z+g"w&Pia;列uo6ҬCG׮^1z9[BA–l(c̎,+~RY͂u/Ԋݣ[tc>^Hw6ֆ{[Zp/Y'U+lj pÿb4/X> F0 zk8u*6 00[-a{ĮDgH/. >Lo<'IhB*k;?[Oڜc 00Ǹina7 F v<4.v~礃4*K_#qѤdo?cúAfX;YзWt95Z!R yjw2Oޅ~4yoCqI;pQR8KõwpQI)*ƛ/JT W#]* 9^|Sᬈ̩3^AnEs25CZbݤ:3{scL}]iv;SZ ~¸O9r3TM:[dIٺvHouanv`2Dc3ȵk^=?XSV.g}V7JVJ$GpL*Ro.yxD>1oD綊|xV|"G`gS:OU& 2f:OTSL,"ۉĂnΕu?fP/7]%"Q<0V'Kk߷4>ԪiG)1 ͘PG-4GkM}9DD__\/n8iI#?`tDJ~g m ~gG#:Hw|ɠC'M,FcFQ+$7~zZPg%n|sBg.|g4q>e7z/=$_8!7%ȴ'{9Q?,⹪cϊK5r;&neV;Q睹tBޢ~I㶑u8╢Tʍwc9Y S<*6ͼpO帡E{Ed%hiסO{b=Z% ~ ЯݐKXy«7 lot8W CX3džiVi@ϖ A]1ӾE#~ ] ]+O`h7ѦC#D"#scY_"m:Bq{y5F3n')|0BZFhÉN3mڃ;Ҏ$C]Q9Tk@%7qOAuLC7ɲV=DudjUQۅrLKEOjҷ:u91pX k2H,lH>qBU(C!c3w^A}Bt$ %Љp}εh\QZF}KS KH9*.~pJG:b;2|;ԁcHP83/Eu1DhlW70j/ZL1<Dn;v݅H< iII.$֜7 G(!)E?:A KU f]F&av/[Ř.&@Xف!Q,7aLJE͵C[-.¬aBy+zmI = EӔ: UДF0MO4K&aL.QO_t\AW1Vtm?qȒZ Bn[%ݧV(~iKXD%p>{5O(h*9fQ4fhxCOg丙ôN/%3<{)Q]RO.+Eǻ-UhWerbçz|E8בnb#Nye( gx/JbhYU20F1 ;zvKH :: 9صrdXiGD9t9Y`Uq?}'d̪*e*(Su mԹFj@%ޡkȰZ7ogvڡ䵞 Hc ߼ȟN x59FNR;ũ$4tS5 EydQ' 7B/8c#8\r7K:tdL=4Omĕ̑Yxl|ƫ=KupGC<`!CK|й<`,])(KN>d>C汃a [Nza.C//\f֙r= t!oP*w;45+3A65caڍ6򺲄seU|# =3 9eԆh8 Df;2F5GƮ 44q(`Eds;hZ+@:SІλc n`'w7dGh3;I fHϦ2p9r !:}TV Y}[p:Nؤ>ې&vU+!jR,h<Ȏu4Lp!'ίDXv#M^C;p<q Ӵx2%TkK ްzX^q?4\ #V!v$ /y\SL+/?}GJOaЗGvqh:\p|vlq<@D:]ln J'RX8r?a+Mc3nw"}*a0Ls]'˫zM:#"]R 2vg684/lf}PiGhVcv󅦈 ?{e𥁦gh@(cYj "fD@/,a1D*'I)>z&ojjb %!:0.wCWyba%f;9IyG3M4?cWq@C1}'j ; ;Gi8% )oW,*ߙ0"3ƥ'ȝq)elnNTjۻ${١$ 9CPqf:A97Y }BLTꝔ& j?ΫRE%E Cñ7AE"ݵj:ġcx3Y*l ϖWG7A H> .KH4%x6 Zv8iOn^Lh]̾ki./n}O;]+J\ ;21GغHS7;/Ys@loL#_#aavۓ>uh~,W#yz; P66EJF_`GPT ;`Be杼sEg8KI:4x1Go0I.O/!5w1dkF߽\-[[N om|(]oLP>FyD9Tv?. b;r͐|L'͂>{WK|(H7e7'{2-A%$wd[E$әB{) /w׽Zh?"7 G6Ɇ6iWaf)3=_wyE">`nfز|FD:5Rd@IQT<~Tȴ'9ͿCDEW4h:Yǀ9j.ajK吏9ժ={S,b5; $5CwqHS^Y糕6I^p p']=˜)vbֱBˡeǰZiC&.~zpDclZ̢;:LG'H_]Gگa&#/#ۏ!DU=|ۡ4}w]6Ikm;VZ>C}Ӧѷ34E?c(-ha=fI eNEig4ȩEAUܵ_)@ Djh[۫=>=2:OXoaEɘgNW6AsxgTk]]|y[qP;1կ8t+e[+8~Z8i_gۋ 93<|9I^C[nVŜ9P^/E:*HY+J×N z$,vh K{h: Վ\}6QdQ3,cG ";!i f.dMAPګ#a{(f95i -`_3(nR)GZ+JMiPCnpǞ4 "*ra\xH\DIhN_V;l6V^iS+~GSZ9'U~ؼNP}Km1YOo, ,oͼ,˧pcY(Bz`2K[PTzUWn DXp}z FKGJBDE &J=a J|,0$k = e40Avde BճSZiEeWzj+i])mjUnjfluM1H8m@/dNҁ{͑W!~1|[a\ͼ PIg}II>eˇs> ÒnGs^X?u p-b#RDE8"mh.cө^͢q9 fH=TG{̗*+l/{'8ƍ{Xl"ü0E (vq Kph{sl;w;a 6VEfbgA4Z 4NV"4QV™^"R=9WT8k,TӯZsB_qBnK ҴVzm$.]a{4L2G7*BkL7 "I :!EweSVc}j\#ǭP]c.uPteAAxٵ=bp6ϏL'SܟN(gQ?肊4_NhGK٦:*ffxrT;|Yi?&(_,"bI~~IM&H޸ȯӯ+C>rN|@ MA4u}ߔCa -HhWLCe H=?YeotX!"MB 9!73W@XlN݆6ytt ZJ%Cy7`AKZxN/; a܈~9:"$ш[oc!MIzO9nRO(o<;5c`/ C Q+@4t*`mmd~鴗 'Z !g;Xߩz=s% FhBC72Ʊ e^a q4c 0Caǥ5ťis]+ij9ż?6 (Gd0CB4) 'Dg}hHP3b#tDFNQ9]ah:;  O0ދshץ<%T?~ up@_Zl㧆 詻Hu\R;ↂЍRl29& knlbf*Cx4 i)eHЖt'Nɨk-lsٱI:ptRs](6pcI:zgCzC),H]Ƒnjvõj`uX|o8u^=AE[zR4,s`]+wx;`HJEWziDh}:ݡx<_d%gxկ粵WK, d__"m 'uf-ꯀl^X mXq7LXn3l$ƣWroذQM'cρ:;_4F0W!h CR='Mv%wbYk 1|{@ -Zt@v'~݃U~G:6vW,_v V\z4w8 nGk"O㡢*j<I#Tc}3^񉰯w*-BӁϐ4#ݵvpnJNGlh OAs/DxXJG6lhW!oR `$&h#cS~{)|R.RqЖ>5!%S 6g$(`MfF`3XkMb$Q=ij=ݣ -X7^zMοd5aL5mdxԀ`a`ɺ4OϨ?wVhp@;Ʊ DHgM2Ѡ&~Ǻ;Zd>kT?= _5mЫĚD,pAYBP=MH)˜Pߑ,fx,UFtrv'3EJ\W۲A) jsV<ӯR= ٺ|1륢uQX:t/ڕ%R k< iIBTmƂ`vT%o ْ-1 >-Vմy'/|H5y!?CءDl Po[CS[mmSP-u([NF7m,%?3P/$h'k5?^B:4lך9#/G02t64&oxth+_tvXOpz"O-2r:ރ4|8wr[xDeړF r]AvWzOwݫ0oDi3OO<ImJ Syx2wנhy.h[F@f zeg- lR ڏ#?a, Wʳaϼ8ՎPWoݸOkd:۶ y6&(< rAg덂~ 9+TP̬g47,;sLϖF,;kIWwtim[6&& % { e$%Jխ-SQR`:p]_zAaشN7]a)ɣcXmJ[y%\}2fH8{uAzB)&B[^eu>{yT~~p$=_HFi|RǍ>6IvS*}<*~PwF&:Bi2j̹!^<+Hu% R(u\m@h ])lk̈́s-BmJ+TpD[ "@mhb_kބS]TEqْ8m-hlk#S:^ /xjMxsBIb4d;[UpR:tH+6ВvY 5lI̵7u Iw;yC#VأI+,~vM_wLci)'`ʒӸqF m^[ƮkJ5oj˔-:>iofiQdzj[߈˟ qOBg4G wR .d%vtq_VD H"Bsyߩ`ʲ)S Wi{[H]~~B:?gqC@SΦBOu48iU MY^gĖ9@%| ][,0مBrgv}MOWffGeϛXÜr*l:A\Q舧uyC)]g`pV?b$VAawGA<tPM;ERBD2 M}!씮 yuaF$)X*In+<ڡ~cE 9}aQ10aPY8NP} vd6&,BkxSYLo:=t{~  9gQV`" %P3O=zyK$(mW${Lh.|V@AIm默`~T ,Gfj'P^<}xRƛOo kӈ|>qjhH=딷fߝL;c aquޢ@+i$8)_=/tVP.g#zTQ[;;^ŶfD5MGS=sȇd¿XՂ%-qgy\虑zG(ڀ齒*T@Aƫ5]:T:]3LU)BM92P u Vi4oM&գ<&E7J>nQQIHٰuƬXȦM>>p7s/b(>~ZT* t, kZ`4aqy94JV9@{ӡzVl(i(n%RD;R9'O01h.YZdzxFR1c㛗,r\tƆk_nfHpc ||뾗nyKRpU2ωe}c'dQ₃Jw=yvSځ\%c۟0oVpf! ڎm9b"\Q׬32zE+ Ka(fgsfw[+ sۦZ:+^|i(9l 3pA>ğ񇬢/Gw 0s#7Ek uvě@ynIkBchZ璏|>KLLC0A>ICsV|?!WN@{Fu=n-G³/:pǝ̱|铇nWr_:c,Mp6&DW@{m٦гi_;b01>Bඝkh{~M9wi?EH@ /jhXdΤd' ZI~,v8'IG 8I-c'4 mŧ dB[(%*#2+qgDį[ s3@􄂌u){[KQ:\Dtizh, c rALׇ~%{`nzd}>c{{[4$cuSxK9ٰ9iaPl8_'$8Chy:[*6iXWTz>_O@fwR/^2{plѲ %c:8ۅRuZ^jkʽH^n~7˜*nIG*&.bMKbkt k@T+ \ߩV} }'!=Xhv4X2='hۢsŒ@t.xA[@f{ֱm.=@ܨSN0}uFYҬN5 ξ{|=ضB z7TPEQDGmstDqb*xS`Ĉ1wSUjF3"[[W~d[h9S7q[FO%#-k27XHͼìKc1sIjgy[Q-hlfw姜6hue+^ vsƷ<[# 'Rp»Rp[ :a8*4u}U\8]>:}ӧ3{ o6Ǎ#li"ѲTިts{B1Vp,U74z!а$[ghş$ ʩP4?&j`/hˁYߛ_z$qÖ[sԤYM3~ "%h hkC͝hΜD[vm.:1|tt_ w7OАPJ%Y$'^`n;~ݣd}m+p6R;fzUb{KgʓN&nH̖:4Wo 'Jhm`{σs>,AĘTq4(Aڤ!c9B/&*쮣REʇEyoYgz3]a|{MZ84#}m OZt)H1LׄL~oFҾGA -ݑT6P}ãgW""yLy5z\kDO 0!pP}{ܪ.^mB4{fpot@{  Mh hr}>CJK9ȓcAS0kf,{<lE,IY4m0ڶ̧.d080:hȡ̆B+-6~$F(i.6My r?[fw´/%EPFo&'u߅@~x:HPo发x7v8KԳ!wܒ|n="](L?:iSgޟȳCsN'UfMgz8@>@eg"q?V ?o :qp.cv/i6q;eZD]̑FP͏Z&KPN+oXS@4,^fbp%]ZYD>wN+|~bO9GfS/[vphBO{LϟwIÈҨ(s=3p/{"{e?sbDfUIbvIgn;F~5? |}S'qg}{.V(w0:G0'ȃML\_}t8"gΚ"=0ܽS^V^nvqa3R{^ᒳa(GBT@!aG~a+'sNȩhHH*ÆW cfFj5L"܁PTJ[gOj`!K{WYy-Ӄ>lǜB3J2[O:haM֕ 幰zDZWTN:`k {}B o; TKMK_pI, y/xb؂D"|xH. \7ȸ;ыfQCˎBWnK%_́;Lㅊ G˨JUnS2M~A|+.׿߱~`QygRAN[ 1-X\Ef![oRG<2̛PA8#6`!サcn:`s49fp(,*cQ{ʿwL:I+Ӣ u~H+;ěUݳr*1WnL%P<4f}>N}\J*qdhue#uSN@^#'̱аٛ־Ey޾~+퉅2ZwAvnm( KNC` _K<_(dvd5٦ Χ*d=/avt$d_Iv;*C{a$n׮݅[b$(okW"k'E0w^N'M +=.K3$@_WobRM9Kp˴R\q L95iJ}G4ec Zi2΃i,Q{Hi"$$OXO P1I?Ca3+)ӓ8φ Υ%t~WLGS .X9v*;*0A4T=&%hѯU|&},LҾDj'j3>GULOJb||fYDdiEѓ[-h Ҷ& i;ɹx\/yiI' >gijn:=[>Kj{}{~H4޼W6})g,!S_FuuS%Sc?-irWzEx'zK9n1(ء{1 iFQF(qVNEwֺZ͖Luf9 wǭh%*b-zANww6 *}p3KMRzfl{ziq,E _eE0 D܊&I&'IQ~"{),k.ns4)n}XB T1Ⱦsi 6=m Ss $k_1U7 |Xd ,2&i_>χ*fJ9HRA{`dE{:Icvj-=HO s̟AbP:;?G}u{B'32Br@7Ii:Ò]\}d.f:{,r [?mBFyZNjѽ'0TlAҭ:+UzKJo/:5_◌z o'lcʜ{iewJB!љxGp-JF; [U}WszEi5о}`'㑾 >)xiqÜʒOÞ~3ǺXo/.O7 Z+zBx ONݟ*u2#qUxgfoo_@+LqޭEW5נ29~-CN8 >$*9':#AT/L`pk&LbVNKq~_=cϊbrܬPx;Ǎ^4*˜b7/Ġ~̉l;,[Erȴ\ssr܅MDFqtc]Iu9U>LeMYޱ~:G_#N]a+Ő;ȈakTCz[%/^*gl;}{я 6НҸ|ϐi3GV%lֿx)ldz e%K+u[]sĝ7tW|\5,@jgZ0ߟ"w? oKD'}\`DDe\bÂ\Q_εdtF:_a΁ʢt׽iDž栬X1XŸP^r1/f(T+/e 2 KeV4̾#5of;;.{zܛPeh_-a ~ ZPe-Hs ϊ2jB'>^ n@^sKfPQsϥ:1Av&QB΍{ \驰kw,U/! 3 \ d:miROiӆQ%Śz0pqdr"4qu;/si¬S|x2Ӗc'vjCYyO|KScqC{H-_@7'ZԜ ?PcKN#"w`*8rW0ތ-BY(#V>r%:M3^w[')XI/ㄤWsJ[CGxFOvwЉo˾Jb\YlID=AF"L7)^^?8%`MWپfeeFǾ@{~gDC[5EeA惩P1OU (@',LS6H-O_),k^v$Q0(okvgih8=w(*C;.pw̸du~q&K߇/I?|WǤfVB"[1}[/i*^s<}G9j i6l=6(sZԁdӉ=1mpzrA ~Du/>R>x(-ZCQGׁU44VI4w"_CD4/:h:qoɼVSSEE{}wET!ni:^#"[r`18>'0|sf8nI[8z83y/Ϥ,_(6#@F_cP!u=:wC]g﮳֗~>ozy9#UtX'T/iK'_6LQXdFs|(>ċI0uj`.k,swz(;w:Bbѯҹk:'h iˢ[YQWD`%mxu{_G9|`:c#x--jDa.=D|gP7HirR9QJ,[5~us9IlCA}^C E\bbvJJ.lBШb%Ź`93k$3?]k1McZϱΎ]ϺVUzN寮yt(wx9sxh4rψXrk.(W%0}CۥZb lgߢ|8hYpN~t{4_, EWX=gOD2q[J>W㡫iO困~-7U*fQP)`{C.z@\9X}sѡ-$aO d]H$MݬX &ddXv6̋'QvE> кTEo.K˸F},&̎a:}-4(˧`>2} G +2O$z.wf,<3/,2^m?۹4ˣ@kxxӊ4⻱I+3"aS<[E4<۷9œIZ8]E3[4mo4vbXS%&05Ij-|CpKBٸⓟSo99R_hN3M-?5ڗ`> #6^TLlZg-<[# |تg|&'':*˓.Wbi;شKKҺk)m`z뇻!w*)Gp8hg/%?@En]R+wxuR=ZCd^gRuΓ?ĹY x—Xܯ E+A hBF=*(Q@1O ^u.84pid"8 ` E@c:UP)ɇ֝ t 1]E;k`p/\Od+hh"kN)1#^i1$'
o4P!y}25a>kغP]yxD"(.:0*FQs"6;X$@o^wK m| D а+d*| +KV=o:S/r@|[)%E@o@i *\ym^L2!\eg*Ha_fT\VU*mW%@﬚L E${}Ygox41J2-ұvJgD,&axŋ"tL8:0,qw]RZIPc(o_iK_D/yyw5_X-!&=^70P]Kיcê-ʈ/A h{*I~p3J:8p"`p 3NN{YCxijEĄfH]6wKOu Vz#gjX;ж#r2{ W+zM{+I~VR+_ ﶗ?D<>g0 Rg"78].Rυ}Z1:E* (SF/$Ϗ7(rB3тIm -e1 XۮLԓpKaGhCyL[‰d@ו#- γ Ka-bѿ'AXS?\|E>>W*^Bm?^Qu^7g].)H+_5Ʉ/X @ GwZU8:@1Gh^/%ÞV[%~SGPmwfQ @2a1PYi6]x r4Pt xJ [؀>M;&d^7[Z/:KbqsE&Oڼ:|o _p=3)s4vjHtIr 0 MTU_s붒|D\͡Ou'kRwJ!ǣo>QHlj.Ç-KN)]x@_þKL[u&)њ#d!*XjwmOlj=1IN@GH7']s Pl==;u{*oKUF=V[VQXc5c;v)r}kHe70HpD_ES!TFVE?x*޽$wxX3Ir9Y3w ֿb3tœ YW{`ыsJiH{Y8*o˻ʳ&_ףOm d(7k>"KsekD4vg9و!}Ib-cK:envG-|y/c{~ǾZd,t"[T:p A=vGf(pc6P57q>{Vn[v_ZӉ-Kv Qr;UN/?M+3^ pX{Ttep {%X_+$9-?6ln U|mJHKmgdۗ?S!!~SL g(HitO{sMLG NT~)=z+b~ȟxdAas czNGxR@}qc9Q' +1Cu#ݹc'#Y`ƥ^h6T4dž (AoHjb=_aMzgެ-6}S[ckۼI|A쨿԰](*z:@wW3]Mu֖D|K|B$Z=Ǥy;HꢒVԥYsIGS%rN-~a威@Yy%|JV](;8\%JPR6ߜEq?5@]_5~}EsWg/ ' nȸB|7"%m1V(r*m"u1(a}arE(g #{ԓ\9izV |==޼h>j^_ 2X#]iskVQEdPHMl^?l |֚j/MOe_Z jP-Q`:)Wg̺qZbe)J& +T(򭕦l䷅vFYVz?_m/{[\: 博ؕlU.)%;h A}[un* T$d(\Z bT'RZBS a`D%:UDtV(]fZOuB;I1,n( /Z}'ziɇƄ0'2+7CCgXA,N_sJa?6<@ék_VQ-uɷ rީٿUp#( 㱤EEs&M&"-d7AMӁ(=W*pȅwpy.jvсRy2&a!+"(_&[y&`=DBN2A;od(jruKsK%v Z;EnHR-u0S2B|GW>-k@Kw8}C;ƉQwn#DV_m9Sk Hica@I o|h O;nX#ƢЦ:ϭTۦ}7$/jQC?BrB5( Id@nѤIr7󩌑 \*/7^;<+=UdsC1Ƣ $:*k$\>Gn׶]3QML's!bG{=bK>9ks/M4tB;/ (>(*9LXR^fpsEѬ\;ϖ|_*E C)0CcXɺ P ü8f怨 6y-F)/̐qM`) ûwodMY]AOEEJ?mPFkpDX,k:̆窭UD:{*,\GL[,<]2n^;J@Ѕ:HYJT=H8@b?HCKtKuh/8VmkGR6NN ]'ʼ.Tڽ]0u9VP($K MEfJߛVrRhXcx>Ew]ۼJVgxӐe) OMIU͝c! ?B2WtXZWGɀ6oIvwWDEs`',n@ǎt‰@+jiyWL;v19+ kΏA~QONqXSnd능} 鱜j:| ȭ/CPOak|oؠteg>M;Cr5YP6 wl >Y!J'` 왁Y;'V|^$P[.|J̻@*Q;ݜЀr9VbeBޡAjK UΜ߶~ITRjٴ%/Q+tn6^th|z2'q5tg82Gs@Qɩ_Yl5[fLSQ/Tʘ=ǒ̕$)arFxik%rTOՋ7iNzU)9핿pGaRSz ~:WVs DM$v^!*>V3exef)0ՍDTaX9hb%(NKg+%uUkLw3!Ʊl-nʃ?$ce9VZZp yp)ZJY~Egm݉&`RH^+3,?|iBZƉt}W!-ɅE2҃gEotYBGvlw(G5T] I¥a6*(Hd?5Qa'viio%*FG5`q > ,"М($h!ƌ#:olv~v_لPGB'EgN6^Rtޙ k!#(7^z UXW:eX₼^#t*+B<?e$4f˵sle=N=mXtس&"& E'騩#{џɴO{S*ƅm^`TU,2bvi_j`VE>壓;\oQ֖,'[4/tmهHZsPF^(\(FtS *1ѓ9D]{U?#R߯x.ͱcM@}^I8 یTM麩/}FuV|ʼ%M,*F'efҖ 5tYBqS̏'⤟uح`Ǿoh:i)^#z‰?ɧU6D _Cn/V?#'e'wwQ e+A2N! ٣f@YǪ0J=mgSKRez)eT,}6G~L,iLoP6ìdwO*LAw/`XG˯|jkQ*J1a7i^H;rBp5 y*=.Z"MQ>lûf_r"- 2|+G<7$^2`ު9:&L$/b[fj^ D» @MˤEϥ ͅ7*[S2,+.v:s7?F3aK[3H䳒2k+m<K8jeG[rl#:墍\Rx۬=[@p/78lk %=ER(>2~ٽkFSU,G%Ѱ']AX?fC3zs1:NwEMJl}7m`Mk號S[6whdeM-J1K\PŲNC,+̘|O`~acWXOdj3F{h# ]S{WwR ^6)fF?JgG$j#WƊM2,1)|n }d\Q@!w6:aD.. ,=ܫSD"w͊4_uUZ!avgvbSZJ.H#Hx.ᗮˀyim{-*Jz@EO(>zf~izK9ьF`g~&Nf^k(A)|S൞ =>FԛȆ?mv3lbArpG2?Hؗ@) 5͏[&0cb-eaMM͜wS=`歛>}e ^h6ޠBM&x.sE56~/{q-DFdRCsE-2(gߨp ?W:L,=D^,Of)hJ,+ҟC4pW.)o2mb@ӡs<77e9kK?=dq+׷xn&htt*&NϗLĢ"$\y>Y@m^<%Ϥxdotw;|Y|^pݣ09_1;W7qmRJEIG^S~<0XA3N4Gn7EعH7aEz'0D6sbc^ 4uߣa=_sYrHɽe&^fDcr_4c QwXX^]@`#(/tv#{Q6iUzeVai7~ ^X kFj(y33R8_؛L^7VIUz=5E 8k͌BN;X ܨˍD eGUz`{ b& Jޑ$pCGy'¡_ K%w3?3j֊_@#4E i|kpKÎTԊ5˔[%Q5&`u4G Z #ONQ$!AnmO]1we1w9#IGxU͍/ } 8R]pܩN"i;b_m ~׽EaV~'E7؋&2=7_LMD́[%5:!ހiP$o3oMQ^ I;弣I z;W h(@G[e6&1zvС3xIY埯qNa"PT#]Z,_;-6_+T6SM>VjpdWZzLWY;jg}Ui>\;4?@5h'(Q|3+$'6#LQʈ ;Z~(|g)c\'\pu}_v[Rђu,3ԯy'[EKG*]5KH%z7B;؋n#6hioÿB{ ]G~r&g\c-d!jVMGJq#LkFV0=cؠ6iS_s"l{ h^JWiDz:|dPYNr8 懤>Pae)۷lP&u$\_\e<;f+E3Xfvra׉w|u$T!y6rs s7xeYJ"J7u@3M M!~V́O-?zE̻< x[M9mjʁ#QIܴ5r*^KRh؊i'n;dH֣פLQ:QwlwYޠZ pdǮp>ze뵟aɢ4;M ;JMtX^]~,w);\F30$>-3*m%>$ΊSmeqW5Dm*EjuFY&)Wpjs]Ky9BQ֣34r:ՒbܧQHMVSXnj0bA p^FcL z#RZhV-.@nGJcB(|:Ɋz 4|źz"P->ɬ5GĎv*S#󔇋T5o\2l3e*aCNs.*S1H͕\/G\&)BրX(84Ӽ413H2+XkGkXȼj 3+wdԺ^΋ "^eeT.&gb'^0W5뤄:n?P5–0 ?SM?\zQx-S 3Gp-v./cAJre/߈øT}쒦x*f S䈪MO7LЬj![]t 'E၈uхx&Tr;ўr ~7ETg!ŅڳL,ZO*Iw?h7&Qa&w:{ʄ=5^B} e3Suݫ0atam4PTn.-oE DD&:Vܚ/tK*+80=jښE㐟CRl3oX̮h5(}rɄk"#БtbzhSLք$e'ꈠBoyKBɏ n#, >HTt?Bq5˼`aJ0Nvv'ʽϾ}P-D㦭.2ҪC I70oJQerN7:Mᡒnbhp3cJBu,L QDpBl!yCJBM%ĩf{+ 'QJp5I?8jdd]$`Y;i&ACEQ%'fQ!ʶ>ˌ%dh`UF4m_Y]<$Mu^?Cm Q<!i=2_X/7&5ë8s"wW4o 2Rw) D[>p83Duuh y&Te'7E34Ņ3yM~܇dظpÚ G{N䌘7w˟DWnOIYm}` c ɬ݄[I%#2 5!ٜ M?h11׭4~((VA&s%K\ˬ ݡI~rXyjq΃=lu=JQb,c蕾FdoRJyXޡIw?7lq+w4kn6+d&ɘ <5wo޸M 2K$l/ыDf/=n(-mi!Y( d:Vjz:٘@Ev=F"$ &SI0|40Lgzxiaڀ;?ўYwD<ݱA,!}+H+3C1DNGh!^{SF]e HZ*Z֍|Q>l% n}be_HGv5s智ᚈ".Q.Ti)pLLMѯyrchҙZg8v/ pTl](WU iH>臅.rF6eόhj!fsEŀ%oN(e{:lnO0֩x<0A7h*A/Ԉ'rw8h=(i'QFZg-:;mz=d$;AF@=Xe~&?8[p]l(*hwKt(sF<ӻT;}$xϞDfӁ~Z d{zE͂1qibPjswȁ}Vs~DV?#4w.5шÂ'@𰩅%X?zb2EBB7l`y4sugdB||eN62߷# / r; \ں="=MsDzq|y*؇K.ɸW>]7?vvӚJ.taK3yDxytLG͗ir|=%Jڼv -e`xN3d4*-dvTS"K6/W _'SxLQZ|\͛fUJ&q }}U/t2[/05L C]̯9{"_7<;d@<|7# =nR4gh&< \Wb/^׵42 |燈^⫖^Zn5) $T'@׌mDՇ-@0 hOn8l挋6UlBNᮆq2[#j=:gjJZ_]=29疬x[tk>*,!D y;6wQLֲHID1-SGڰ󑎬0XJ1_bCPSbCwV+x޿֥.|,!XRc>`K}-$Rܪ޶{V1%ć(3Gb@{ts"us͍&sk[dzWn eTMW+Z~ K.3Q)J1x~n0a]4g ̭΢8vt.̢L[1_[95m']zĔitñ r{M4ICcV 垭(hWj1 ڂQ(Y )۳̓2=&ޞWŁÒ:t9|qM[QqE0,hn`NExm%m(RsȵAl~׻H"W9ްk@׍hvhyv/4hW#!#"}F͡cd%c'hΏT;vUp %?FybՋdΖfRAsKfޜ~1 snя?8O g~@jY>i+8ʁ%kS;+ў6'fL<0bI bQвhx8$ӵB" aH2 ?<}o6#̜ۅ5`xR ð*Jwe5Q&I(K!WuNBNCC`$츆hD#*It8g5q-(ee΂KCCsdZ\튖>-}ȍe䒕d.v37vBO[-R鋶aPK-[ܜvщW5%4GsXCq0PzW3]4^nw`QƢ}5l7Au:oXbl J^ҼOZ$W;pܗ Kl\2X6E^UlX:aOdzHT=x x`^ÏZ̯ A8)6D%b2r7,3D2mnv٩%uHi$k;a60en3$Gv9wґ)DQQsqPl-,jEgA{'L$Z\؎o2ƈ3za,-Y-Xd|g@3$Yt+M0#O| &p"*JUՄG /mh΅vA_52R{>bSj)V2]YI4:7+fYZ%@s5(IG3n>]0f]?[]m4[ٸpvO;{sEŕ7RVPLΘau3#-:k?E;6NL3c^V?xd`2Yplof!M\iTT*dIbggh}ò;gjd dߵ7i !=Bw/1flx ΃]y?k*Ë9bbW]{-G7i 'Z5o;F72XQnud*B%G3v([+ NٖoU^:Gٴ5mSiܬyԨضCts sXewZm>豺onTqE%Un\):HW|bRHY$f 4D:!_v7Js2qQ (SeZ,݉` ԣK<+%Wucw@?eq17|ΥTVK̗qyb NuE+l1'/*gz=sOx\ф~ m_ߙfNL0+(5wf]vN:~;WY{XkU(%vo,战UrsDYU@ 1ߗľ}wk՗2UV"? .ۭ6t8F$H|,%>(_U*Dnu9 fz)1&1ZK磛j{zs\E%fAis\X:NeGz/M;HlCģi7-G@T2#n?ҠYjH0|;l:CA)Jм|b~!t=8F[wiim5dt#yE㺟c[~.\xˎT6uE7 gn DsSXeE9{K1iºb:+S2簅GĚAvpKSbn^a!zy1 L.LK֦`·\;}-/MP[VWDY/g[їcS֩%`5WaJ6[bw2Kׄ0v(D7p+z8Kι\Dܪ:WVJ;p>Vn /lJ^ 2 ]Mv̏*߱# MU&Z\ WrO2O5=+M`p5Fr0w,1@FsGi'%Ƣ9cƝfâJ J\dmsB1-R= "g:6(n >䥲9On8m9JXiT_N'Z9@"7J?  \FLL΀jlfz"K. !qQ??֡溣 6Rq9gʏ#/(\A ]_vx%g?0x@;5UtV1/`-.[tsH;?//"CF>pỰ<k~y>X /ʻRK+(t*?3'&jN&^*fz,B8E\gsh`#tN/;2! i2u9|sp_ aVBlUTįh2|h}ә*IӉFy91l ^̌Nh;gϚ/(Q2+8%0l#thBUֺ&$!.aTATߟٳmDrr,*+Qou[%J Ba BH3Y[Z,)! .9hOd bjrIi`Fi$'^t\ m=[@{/6!)V?JtkYȎ4suT~oC.ɯWr& :^M] tM~v<{qЊ3LY$YZ44M,3`:KTe48Ñ|)Ϗ:5j+scV(+u)wGw@;OB\>A!9L9]{Xt2*aqsW25mC:Ӊ.V7EaSH n4Oߴx]M! X{ 3qpLj&wymՅJdwz+YL7ix" $?p&@E_mr:ldߍ s}N'f[lַcXcQ Tسq8׽=Jf*t U ϊJ򩌼Hs9,D[biO·޹_6t:&LSI ELWVkLpdsxgPւG(sW#!b $äPsq)(lz-i/֖vᮛ9qU "_:|)U,tVUwTq]2"I[gVVRGA# ?G&r^Phg6O@Z cC)Wv&Lfg2ۙX9G2ٺR ݷS|pP2%?vsdÂmm!dJB*0I{$ڊ#i6}sm񙔣fdS#Ꙗr;#zb%9 b{/-7*J"ԟHICCBet'Il"m#Gk95I(&T0t攍Kk|ؒ7%t9Th"#/ jrWLБy:bL37{XqhĩP?Ueש]N6,{c _ٗC4Be˓*r4:lHl!@欝]bexNpa)T ]^&kE0ZQ,sm­0;~vX,G$e:?;OGjۤ{r"pT!˕RO]XZ- m7Qݳnjy۸-$}]7x)*D[9Xݘie㹖9*F_N?i3FGC<+${Eyp~m%ʻTg#hl.=@v-w&@F#}dҌ\:4ϩz6KJeEghU(| ңvw󟉛'TĨgX1Ձ; []"2%оi3>jJ.I/{`;U%iJ$l?]piE*8wHԕ~so'>ayH4X%|WαQʈM~,>ߋ~UTz4oM;jBvnòq}&UUu6O.UK{E|l'Y]=q`DscDAlЋ,üݠ~ojÌO};P .8>?n(1>ΉO\$aM1XYָ6hӅ<%1*j1k& )DRZy;C68(w+SF({Y#<\z;2F0h%/Uf_V⃶&?udC 0[Ǟ;LQbqΡh^#[6s2ѣf{ v[UMfƩGlGEtQsapO~hN1D )u -wruhk/;=JłH~,xl(^Ra1?}Ac0Aj-ٺ9ѫC8̍Sq(L0ⴤp(Efz.Kòb @LSxO@~*,s/-b^*ś/枑*tWf ;@^<ƘBCπ'vPE.a/ϣ.8P0gjf|$>a)%SRIfmG3PcLRV*ƿ__Xd2B>!w C٭4ɰdQ}x^&s$=gR\S.Hz/ò .Ṅw(/*|5y#nXn[*wu;i,ML_̈́q(z>`Ǚ\B Jdq0h)41Êq"zG/4kH<̍Še-闅V,J0;9 @_Lz>jfA/ NӪFAنK^IPH -y*cQ%Z"T3ߠd1WB dU:1jC:vѼ(~b|3桽ps0{ipL H4\jNQ n "$4 U+JU97}v)1{S9NQ݂Do0+ZA|kҹԚ ܇-ld ;Șo*Av(^0s:p؇\CIb.ڲCun/;]w]CRPfc ̮cAF9,s紊6N+ C$kRN P;l#S;g6AuOdCq7sLю_O5^tR__>+ݱU6ur+5sAyަNCPNTJ劷}ʕk m^²- W>o\ GٺY2L!P!9 2!S V,uS*Sew j Maw+1 HK)WFGDəq^@t_?cqfc e1#K Ǯ jXXN}މvVh'oD:'GfS͡siQFozR\e:q1iKC2ĎZ9F ?932toY׈s\ugB+a-%a_\/M od}E3̙=XaMBIЯP{n( LRrڣ+)z9r-6~ -Fכ,으"G![ D%5 ]u1ra[LH3Ύ|&8Țsk;GE8},N\ 19'o7IS-qLh.+V_-αn~-}}Sjj0#,ȼԔP^fGPt{zVwT2 >BFTv6s*QiruyҍFhWeh^p@`I7$)6@\ mHIQq-rf])*IQ@d`Vul-V^򖛀au'b5J`gX:lpV9퉏H2TsH$6$Lgmsk Y_!6V1 bmssx:L5e#Q!A9V[3L3Ed# 06,TJ)/Y?x֮ P]DeMNb, ҌL`+ (y59fR# gF5~"5>EɈ2Ca8n}{)*(~&cXNP췎Eւ =÷ᗢ85gȺf}p=Fw#N'ƙ04Ӵ?:3P#]&ɮ_H.̲fqE}/(>Wj; X[^2owe ]D>+' jGR8*c5Ei2awe91}b.VHdY|&ڰEÓeb[TF-hSBqV<7zւM {$Ĵ颃f ҺfQ"ΙK}la)dQTPYKN}-m h^=ك{(}mQVZ1(o ִZ^tIt*wЁVl,Bm! I(G,4S~}Wl<4S؅]j7H ˁOm 9%N'5yG9Hv^0b=4?a_Hh&WPW(D2D73ߡpP"@))-:vFZm1Iw~MggG';&]\jXadrJ'%@d'eye, dynm%l2 y<ɗ6*%2O@0qsGaW$ks"v$52tCTѳMKrL<%'y64k17~-C̯Pe7iddfNoFQ@I26-Ӣ̆|xUT. ځj0|ItkF|Ӡn aPC: +!; ߯ QQZOk[/o0ؼ4C5gfhVyqK;b#zQi5nξ:w Փ2KV`o܌vQdk} ZtNm"m4Qs29,QtWl#uˉ&pD暥cYe)JTF.l@i <IR,M mi^G XlЍ_ZOj˄5%B5& [P^cMÖYM߷ZiQ#oQunl&fcFwi> ;{wvjP=?79v޵EM3~݄5\xJ~2L}iG, = XZ\v Eb2q;opPFilS}2qL\d~ݏ晞sڒEn֑c%yKUmh^a#oiqxP0]1pu x`ҺMݺmLuå8/:=z@\-k,Q_Va<@g>!o:ygJa?"hi =|R+^ZAhw80,D*9Pzx%~*,|9ц=vYOJ[gDvT2'V⩖|;٫*h)zY>+XbS#7[|sdو2siHHgU=~o&#iUN3oray4%So8~w@r7uM طh_;[TRzE?G2xVX=>sR62oKrgiS:t\U)xek64OIıod1W9zBD']鼗^ 8U%"r=GNxY@\7.]x7eC_m7M~ub upܩ,Z4^0lFNJ*G(@/T\cMa$lqQtcn Nɼ-2/ ]¸H)8d3zydؓR |Ҭ{zY͇h (-Z[Neu.:t=^I),1y%Xe ߀{" f{| C:&ڄ_:GhƔ`HiSN*,nxtdˎңu1^/dӮJ/mCd/s0ݠ$f?#ώk4!p#ߊ#@51bWuhvZ $S"JSONu?[PG&Om8lkQ a1[q%oݽX>/}$&#QV~SԆfF7[c)DNo>:6!OYа(ZNL;|;O,D;>o[ %/.X5^IIwqK sIܿh^ a|(bǹ%%-Zy5㈣Q=SYˢmDK4":*TĚdJz6)Sb^)?cYnhX:ɀY'[ZMzeL;2YxNKK-܋/KIT$-ʅ1pzcJ FK-6L͈~T# d92f$̠)-«x3ǽc0 Ll]b2v)StQ8m7 ]M]0?*Gh#CzaG6eȈb&?-kFRxѳ[&e#nF/~L,˱,lj҄DblrD@/x֭&4Dgz::k`_~#s4N2j{#}SD<: MHETC **eG~$rlM6oGtb <߬DL>yW bd4[@ӷikM˥YH,n´<1DBܺN\z't%;76{Z0 y`ӵwv#QQ\eH.,) AV+HdZLx^q 5=(†ilBw-m|eѳi׬TBIK7댈Zb@wӣ o ѶO^{]mhm|$M0RWLYW\s rY1xAekf Oi5t$|Ց̃{QaԚі tY2y\]zS(:wp~Y/eN`QlxiumI*`cgg =?&oA4-߁2V#q-vT+`a~"[JI~=Q|;:[Dg%l&11}grr"Iϣô|^jsd?1W3֣3zȉm@ԗU_HO>)2,Ny_R"3Y)mBp@gs(O6~|oȱ0ELj@.3gP*2<>PiU-fO쿍jz۰MQ/ r3NrX kzL%n]h?F$cnp,9D+Oi.ڒu,9I\k_+ޅ D= ZUM(ԲlMj˖D'>I\/M>GΆ S&(K~21 ؐ/84~o-7.g+"宯æ]ju1>uS:w7\{MT!'(l~i4tQm$ٜg #.٬Jq϶D2̕X`:5ˎK l0:~= Q15M奉+1nz1Q:źH@><~Gݶ+ SImmAgoiqpDr)4H o6ې31D:t*pHf9\Q|6n#0`28Zɳ6` 2"!+6Hj!,s?5.y8S?ȺqcXqsRO{Du>B^yLPyŨޡPuvxŤk(6c{"L::W53 r 6.*aU?Jt  {*$Wu9ejLOǏUN2eOV7g_|Q h˭1^̈}|7ѕl Manb"VM`~\6@=#$Oj G}\X2G[Ix+U(VNaIy(/%+`:fČ-V$w9@)oa`ےQbC'6%w)k"S`vF /tNG4[8j1@ *AA~O3lŒ%oʅÅsMhaEq !#ګPO:zn8Rk_iVZb:HLEaW]-9_WxU^g1@B9zkT(HAy!{roYH@r.*ńeE1*[Tcʊi>UbVjL ӊIIJo{b )_s5((y*J+%jYbf5[ \5(T`1~A`E; ̾"ez1]E1h~MgtZ^k~iUf$;*,x[Ez6+_OQf2#<7h;6ZMsȆIdqQa^Xn ,#-ӎE/v,/ 07'{TȰJ($ރƃ :ٰ  =bS Ge}+SM1W=~/~n%LDF6Ii٧`rl)nتy2mQ&Mw7ZRJ%K ^Dj.a[&xBd q.3A0jhN?]2r /vnբh{rګ+E+B/ >m[XTJեH5*7 :=ءG2:*h@*¤7_&DEt;~=kÕy84C$7 !Ȟ Tj0WpjSrzP I|P b-@HVӷxLȏ㉀[2!I%vCx<aⵚWr7} /5l{OEx&y 0B&مօQ }BMjfhtf=ׅ1|Yy'yrk-?otK#,~W/ID;)v.ݢYg.ӕ3 k@ߩ[p-E݊T~b;U]2(.%O0*:pv(N<9V n\LFI+ʟmrBxmeMip5yfMM)nuȱռOy[Q B8Q˧C^u²~xSY#.^t3iM-3Qusw|Neّؓ ̫2WJi{&] e \gt 3x"|]>}d—̸O\,v [Y6& vAĈ$*TSKC K] ;-,*Wy9S3;)Ȫ#G3k7 @=<6aE=ס!c1[ .-u}ٰDGikBҴdcj!LhWPVubɅ >?T/wXEnwGC'j44ď#hq+3˄=T8(ɴ "%ضU*OPDڂNػ?02R%@,2owש~)1d+FS,Z.nF :_{`Y|Xتhͣ:'[՞«RLӯBFoգ( w,!#w9y5Ot7M2x-C- lؓW>V$xW8H\cC+Ee^! {dbk@gBx2O2.  V*;31|2 Q|j,jPCf{I鍢j4liG 2KX̢e,+e5b}llDuܚ!y]w޸,z͞;2ԁS=rM 'V 5;Pw5 \^Q+vSʷ( >[㎑ *${pʲ;F-iJL_3i;x&W4[pEqt~b1mh\/W,:wg\ޝ@M*YN%Z.5=SI8+dO\"(mh L9D˞"$ ^'~s%2f:{q oJV*3\5FAǸb߆l"( ²Fqv%X7jm);Bbvy{Eبn%Fxg}W/y]쫿>/Ǖ!D)DMj4Iib42;հwpݒG#x- !R[@:y4~^rք+ ?81?m#\3 >ВYF096GlɣsRUpM\ f $j!9\R#lP_Yhb;WSȯ# ^šqHeތeE6Х7}ŹDc3o 0eLGݳU-f_A>^~qŢَW}*a1#Q8Jfh9b#rBe;W`7'I*]g|B_R])Q0Uo ' dÈ4*]/Hn\wa6m\96N/X,yfFb/{4pWs( #iSG:(hsO߃fa( RPHևqҠɿ; sȔy8M34'ϴz4ƽdآN&x@n Msu=J-G|tn!B;sB+rN~e&ίfO.-љT!qbԟl #ʢJ̍3*?FcDwb=@61Ȼb.f&Ae& V^WBQ.a [a1_1ƓNdrby, P0]VPze  Hs@}s(76Dݔď$g,m5HcM+ _^rҷeZdGE+8p$o8MņKh~N9EF[6VHyLf8cb#vբ].oˍa5Q;Tub˷^H+M"9p]% ֛ d]&T;ҵk(bJw 'l Cۂ ?%DYgEp$U. s'Ե(/e9OhDJyy Nl3ײtS C\FvaX[o+אဌ'V Yӓ'î(:q S20vy}~@Ьao4YO=ק˷#|NBludFYPSjyD#?ԧ|"qB" wl^/lnۺ|cG&h\uۜߚ٪쪥qKT^,k$;Cb`OPI8ݛr$/{Y20%&!)DBR}EHsk~K[@YZE"׸c_)ls,@ R= o-n#o,epOE D5r g`6r;| O4/O!疠ۼBal=K*o7A)(A<M ^:,envG\a -8f:|7p04T:8nE" {HM9;g手=&GO%|$Pi\@]5ߒ,L@k;O^&v% ⟮%9`ޑ}yް%Dj;ZcӞC1a|}$ae?]&Xל6D%6y+e@[&2XPtw _2,aup۫bh q¾6v  bfm.Q]MQ7l &ϞJ@^ZYHE[X䗻h蕩}݁LFldy ߑvyubld hi| ꌾmE6U ]R>:13'ͩf53JCH((B*P]{䡛XBcNuHsb^őhuw2uBTUjr?`N7Ȟ sRݶkSLG'aLg -\f] nP~W*wHH|C2u|v@tXdLKށs]wEJ'$ǁo_MD =,6Tr@叠DL͒' ٦9T&9vӡC2ٶh"ԽgfO2d#;?#޻9b]UufNL kJ~,( Qg&^=1xl,a= rBRˇT*.T|d(+o%/s,D_p0O0Zٸ/wHG|gmu))W1L.3֙vd7_`u!<*町cM9#ɢ,1W]"]1HE;<>HE*^'ij16E?#Bocd= $1>EŮ0I45;&1~߱xZ .t3u܃dt(XGع;m{V rwM(j RNǒ=Q +LfQ.e=hF"N'&~tpy3<$ϥЇKo v,<mbqljxix2"-s3斲dXQ]~+ Ё={4bN+8ˀ:桲f[;20iEtTf:}ّu^$ ) )}'Կ<*7AF!611VNsV>::/e -M%GK(ػRubiu4Dml`.khhORp,!9-zڷ.~Q3PUaoZ_b&ӏyl7CYƀWe)/e9Y>Ǻ},ia:%Ř]@T`]=_6hJRw`{Ip Qmj\jP\u]tgOl?ky͹q N+hhza*2z9iQ7K̚^\`5CQ9%cq^M͖yFG /> p8XL:ÓNa1hmPlSCޅmwO?@Yq6UY/%mCꡈ"q:N,Dw3ClnJolթ83}]& ArwLVc hF` 5`nbnGOQy4G=~L9 iOc ),M9,ɦd#?W4hI,Dpø{?t.Y@T]9js4=t*mp>SǪ"VUl:: g3`I)ܤ(zbxCCdl1z2 cסvu B*i:ާ5%joQJ\GEitj  BIE"ҙ \>5~J DW)moej>PiLw89s=ͽdJU12Z3S\Q#2C3bDڅiH}5 uvXDi>_tf]'Uu}aK~/XI l t`R?Y_S;Y.ꀟ]֩|o_G 'ӂ`T0X#02Gar#]eh5 ǿ#^ mkrQ2yǮ~O';hx0c#c yv'=Cq(LlslnN?v}\֥{Ė f]Ν(I͡|Np2RM;ؠgz۬4VD+]ї# {Ng%K:"95ߴ 4V#OB_ֲUI:gᙖ}ifdyO_}@p< I"CLKשoDhrɌSՓ_Qp!33?TG\SML{xk0=VQcT2Cc~K^\Ȉi5wpsEj8aNyCN7BU?ڎ&ey#SC#-nFOgԴ_} D:MbkzΊco97El =\XƄH4"ҏL̃ёQ@&o(8cӋxN'P\2&[zL3;MAQD%tò"}v(;ɰ[yH\:FbU4߇J}ѱZv"d.>(_Ow0ʌVHipx$mRo~6n7v9 [UZp&h =Pv*WgxuYe>(\frTbcnlе'R߈ v=QW6b.*2QZעb4ig7kpQ"c;Ҕ~e3|hhwV!O+dR5e qz( >oקK4ɯw-M7A!}:؀4Ѥ]礝<@/=Fn! 9 .#G6AYeϓEYpl>_U~z9 q#.~D(&l\f1f)#!n~{j!?uH7,|T섇ܒ=VFAxܱscu$ʜ"_ޟR%yFG}:hnǧhD6r{/(l%uQHמOZrF_=;PY~h7'oZl%00OH6?*~yy?3|SrTM4θ0My >]3MXeo*BM˦S2Q*$1z>>ଋ62i,7Q{b/h19yOMNFޥ79 E"꯮|uU_ݳaW@. ŃW%hr5P86';T)/|}'n-,b^|&]>s[t%ueItd <%L]q^E]4uE!M"{c%;q")2wuB@834sD}vNe>jmsʪ/ *T}xr&QEѢ0ȿ~dc갳@*V')J ڧ]?jpnʱ]Ԑmz E{eEG1țiFVo5L+-!8[RZ*^TԷ*)"]a\^ϊ) {[ܻX63 UR$a%L[ۉn!?5jzN$o?aTDYr@C"bqjyNs;G_Lol̅j/:č^~KƏR[0sWYo]+"H>cPf2 VM뚉MZ&d(#4L,U$"-6m'mPyzγUZ|׌7ŕI!qpZ_f5Ä#%]V[Ts̓|?e|Ĉ9ql6FN+J|›~k=wzYM .Btv2/n3T *eFV;9}Az*1vUr\6f ;g<_$<"D €t'#;f9~e IdTЛ5Wq~+/y ؿ7y徘2Iw /_̎] nj#ZSf Mk$Z bf~<]R.h5*Ϛd66ndŮ4?m\Mcu ?mY+V'.tsS40z:TORCu\1&QN^}v6LX?#*(})a[$_CgUCD%c]vkZ#(^?N/TL=;߿}ƋW'hA' &sM'L/U&C˿ 2[Ge ӮlE&r[GXK"Gze\cd苠KQYp8륋XS [٠Ng6TuyMTּ~UM*U!23}D{/[?yM!)Ҿ|N5%G,dsƷ2RG<Qo SE\$GaҢdu|DI/)f8b [^JT(2`EY8Ѵ[xi!iE_ǼL- emT8Po+ׅ9ƇE^hkɪ;&1|I36[U{[y`+$@g<-k},[𓄷H$s]N +^gfYJ2~P;:wo ׾#EM+n2`;l{L6H eĉI^!{ Պ.r[X-.MkWDBMV364۩)3ux_+tLD_7qm01 ֯q6kX7Y&PICYtQ`bhsӞyj\ߌ}dT{dhh.|M3C-w 0ezj_i7Bffn|mli޴]+jKvCa/LYo%Gfj͂W*+cX)X X4.E508^Q|Gi$Hd]T1^QEMy4#F}kE%Ol6rw Дye%Dz.- Rwzc< I*uk ſ'kH({_@_xz̒d(hvj ->"En;>릢Y7 )̚3./4Q)Tg=F#6?9h?Jgi!:V=7{.q{ac* 0SDc[ jL-~N>9 f|cˇحv{ QH3kY~^xda ɠˌQR&**(D<"A5Ii )&G GeHx$Ϧ[Jh757"kdM07GHjv9-u1UrIBfԱSTԶV~m>E"=O~q͈APNl5< lhfgoMBK4@HL>,t Hʻ􉶖! ,$?pG:n H2`ϑzFhBs3|_Rc3Ξ0`H5!RAt7,<SQnc)hg=S(4ΰ$> Q6O#*(/K>Ҽ#Crdڽ|-l8BhS"ҕ aװ\GspաsIEXg2y |n([ߨM/fpZ$m?h; TiF^#Q 7~-lEB~~j"ĪAa9Z 6.՘ ^ܫq%rj#F\ f ͯ(!$,Siyk-0RdAD/4O oe4fGO|<ª%[;..d8ǐP:^kH&#oBպf4/]b,9`/wű$C59fvsSEj<7v̞ LuN:~qh\f4Ӭ-$s`ǟΫʹv0nc_2ql*>QVR]kK 1F? JBxA<ĉ =Uc`5o*nJLsd^f^D'9-bno_L{Cs$&{cE]UCN%9]O,&USSs[1D!M,nC ׇNJ̻p7!$xYl!lVsFF/^Y uϺFuF@&pNbrp a KᤤjŻ~+onj]aZh d(,Ljs6iE:ICѭ;k[3r:r*]󺠟 [FҫQgmk~EÚNuuO}Y.nPzrܺD~HcxLʦ1'=Ȏs|"-# 4+sz1L\|_?bѧ):cLSl[[?Iri_ f3k%+cD[O{Ҟl/-~uFYk G٬:_L7sffvwSji2u2F jntϮ-WEwl5M7AmVZX+ -U4. K,/ne•ӣF7[a^?#LҒ G_9=;Zb#K-C+7i_U3"o(~S,;i$}1>yCd!\Ig,2MRanE_$f4P7/2yQ(.$'@.1ݪE$T?+Uɟͅf"䴎uFݖob{##wÔM"ɛAT\gNH9<dzXQFe f5,] QJMCyXJ n@ kɵi\[47]}:rqAN4%ܿO~M&Qn K N'Ȭwv\` [gBҒ| ]i\M-$^ iT= 쭃idIN󚄤6xr} q%.ƅ-&q'ܓ0:)P]uoq:i6;E\dCg7,lP ~?OqGș+DP:I+ۜM_oRY؈ }A(/S8 AwڨwjN, 䀱*|siͅ){mO_La6!BAS}ݬ0Jx.jJW=̾cG?mSnU/f-}iqPщT^&Cݣ-{L3Ư&b&$NzӉLv0$u}vVF36WJA4Nڭǰc9.eUfeݟ㿆su-lT/CN /Lu+RQw4H\b(f0x$u}b~ttEщccܣ¹wCc:I沗N`yϏm_7sd=P&&IܷWc^Q&Z1L'@UB98w2($#ziU)r Q1{@ɱh/K$yu0.~9\`"cŋ2-PZ0C+Jl=\Mp!Cq:O. ~S,n<&+TPر2G÷A ]b2jw%ҕl[.51܃c0(|--vM3>~fRKenD@&fYX];0 u qIK;qWUF2;w3*'Y|M5?LT+f脭[)/¢Q~I3Htu{(m+@L7:֐`:rTҫQ-՘Vl"MN8$J& y:kq_0xu'??bM]`"!Do"m?d2#;F~ǫSy| o\oZ?$>4w黿rDx-v耏Τ?@b cڰUk=—^r& 7gs؝t MCȲɤy[DBגa<2M)UIqM4I3'4DI9ˌ-'y %\!=5 g'ez%}B_fWQ[^2(g̼e :a{XoԹG}ݟSwB\y/ǻZDI4Hҁѷ;[^*#a'5,lvl)^R&0OKT)׏ @RK` H:"SE7Y\;,Ά8;chok_AuF,6uL4yt荹 D%wωJήz.exvlIemJZ5 p^Kǂ^= EBі6ρAx=\474xKrԂlR+LJ꙰p4<#&ZG*5 !xmd[acOs:hjB MH>#iCTOrM'ITf\ׯ[U&)L fӱWߊ<5v7!#!^oH13'?!~oFb:i<`\m!CdCԤ7K:Ko#H85Y!>b}ֳ R @'Ug;E0bD@VF/ӡEz=;O € 1r_diAtfT2iv<=gW&(*ןԺ"Vن u$6twyP!VzRSN :CT1$)zހC&Dpz`{a!461a=2!46(!hg؞7$XE)J/N y=%/OC:25*몹O ;S=Q"ԡbsEmY//_m2e.tϺТiGP?B p& z-pk+)^Ks|]Iz6~-˟(0b[}:CkraRl7>(1+>y/K:5ޠx7;<3}y% US'Y0fVwud÷c72'1y--K=vLEt?-E׊,N'Z>ElO_hUJ@DU* bяRH#'D5"j[kXBG*6 HUcJ;Y2?ώES2f[r5 c36p5#w #|={R( \.ZLpa08}Fc(/ <|c$<Rtk ℅h`%,Q$;ˆ&TD̅կ|%]_QVeXzTL2&`WfjC ,؋EFGvQ}DB}dmciLJtŽ#Jeᖭ4~PNL7q'4pdؿ_Wm%@4=ҳ}o5uu=LO~޻AMfxYs)496vl$AcVS;\fmaᢸfȣ⚧# M$1wM G&}gӦ99͖ZQ9: %"~@Q$ܴLH.L򌧷B9/Z+ŖlcO*=+2U&g{Ng a[ KkRA;65ZՌm zh #{CysҊ+ *X5[oأoqӢO=\=/t9)knm:qmbW{(N)~a; U CO[Bw<2DI2;RL5[ga<[}(ːFU8ޮEb>_o(%d*E]tr3bA2'(8B"eg/<仝؄껊\.&zbEC^jp[GvקiL*uUWal]\Z08~.6,$SR'{Sc ("uu/&MB"j4!?p:>Dy[;$Rkӑhr݌ !8Χ18-t\!8r6AuR 7|9Q%C ڡu!C/rN7Co-Y2~Ȱ @2 J18_38)0#.dB k z.hj,[IfgIBqD5Hp>Yb $_iژ]?1+HjjLՐ kMJ!6+or\>d : -cF;ȟ&DF|譪aLR:\0_uL蓟{nks07AXg Ru8T&}I&DbNXsGx\fk\\9n rFׇʟM^XTg?ľ6N$?~{J5,=W kXVev(l]d\79وvL00)(Ua1y@ /LDó- >_x%Ҳ@Ӣ^ca%ZPy# aI^t]^ ˷56&:ebF x9,jZD1ޕOW-'-1/8=Y7ș9L~etC-nz27oݢXo kE(UM~Ts}ޱD:f-~\cjoy -(t='^MKj\m:.3A9\8@TD0UTsZ̸ B)y$fH,رƮ}1ԅgC,V >>\dIvA+D* PbΞUZVڙ6n,FHJ &w(&+_QW-s;䵮i_.ʯ N׼5g/3Gxϟyƍ4"-"Xks;q)eFrEUt0MW TO[Y+S:0ɇ]E!;#4A h$ 9\:2ei|CD>51b8ᑗlFԾ*V7.˱TmРF%1\jI\11&VGk90d\O!2vf2ߨo#DHp>pϘ}oBIȔi< DhJ0  0-3ME!? Ca! ;7Bhag !pS'=hNdꑿS>VSNyҺp#}9ffJ R6forBOH4Cycw zKpˑHn爞5)%3,oo鷱:29d*(g_49bp j4g$ E_U\Op605zE\L8; +IڪA-I=?+j]hk he @/>R$M ϕgb oy('D@ H9&@Ci + dHTzh5oNZ~2RaT;oI8ܦXQ}in;.w7>W 6Oܲ%zvjLIE:X;e5l=Q5t}aC[5NgX+'^c>F#Y$ΥhE ּ/u#+ CE_|ɓf4HFA@TN'G orP?s_4+Hm_}G8ճ={"R)^(3l/g-FdaRtdizj)^mXSd\ho8k+.г@'}Ϙh6z6բhVk'h=L PrZ>`܍z6 V1YVmlPIBS㙳Idv=~7+ylj]PTQڴLᙴŕ970^?&bm^Y;yQ9lZ7 3{uf g/v:<7sJ-k 'A*y&^,{wMz`Uz]t]&x}kiEf.}!Vox(˄ɨYVf r˼£<:-n̬4y%oᬮ5f}1\OҳI|fgygQFԩgtId%:>.%xbC]xS !Hg1@ܓ?XGTNP$!Vѵ9m|䱆H"$[IӡU?jj^vn_InipJ.m Ĭ>Av%` t·"3n:DJ<0%wi#:A>}-85eQ9Wt? <(ZN/[x/+rAw}J$3؉DFNnsMHk,#ݦOt>^=ꂾq͔ @~E g/JES;vOo4#~z Z珻 .R$ʞUF 'hOd s3 K;0nV, >ox\2J$!dQ=yVvlVcG$Ge+΅ ASU5 kfOo_Տ磮miY4﫤S19TC5+vFL]&k>\hN7z{0d=P45QFƢLW*ܘ屲2mp@F^^W<#+U /5s{~VBA5 z{}n,X*x戝 @‘ Y֒)/Zt[^;NX2̰*ޱ/?MHnle^d@QagN+߯6M_OZo "T$I-j=wQ$Bq4dXan2Ū6yq;}G˪c]Cx@=Ppk͊cP+έ@֊x]bJ~a|Vv͂hoCyI1z6턏|];p6;6zw8ad"- k{ an4vϩX3&Ǡ0L^SǑ߹kk`2W(xGEz8уL{-^nx]"}]bJwYyiC18pY7rSR gȡE y+ymY0+L2Kbۈ!dvrJ1@k@.5ЯttCw81BJѸk_)Q7juގDJ))̈A6"G;:&PL9ۇ1Ϲ*G}DG_yvc-Xk{^cOya@%Sc$6  j @m;. <3`dnaV{s&^p3!5HJ7#-M~tWw ;n !e-!aՎ[VmI#mmx̶j_0ی tC ZYqMO}8?z[L Y2-rY9>Zgj9pڒEc^^Es.НM4ÙS.FgU;:} OUB/AW9`Kk/o?͔~Wv5TLmtWVL9Gnd)_}h[FdmȪ9 M qV=l:D`-ihΆ\}*z۪S8Y䕼WAܗ.䶣›Ym7`b (8<Ùsd$`>*y@z3^1!OޥrL@岗;tSuڥG(sVDZQ<Ŵi6,fF}hm+&Ǟ`f 0[}U)k,n-,fDsC5 (2{qD!O@bUEKG. |$zRm&$ (x7+ uA>7xa/ sa>u\ԑrߦҐGiaqV@L;  r2mv3#|skn0Lj*EuZd]Xe e` <#Ί6UdZ4NN+n`ZS|s~XM.iPLA{jx %Tӯrztϵ*?G| xXߎzq3R0|aqQ+&Ij{$+<HZgTyNx,'GY% "NR0 e*Yf~˄hGs(-9x2cŰD{hS#}slO:n>dVָG?iRs>f?acmS~)e_*ȬZƠ4j)p7 2sۗf~2E^ Q~P9'l0 )$" #-*򋷵\ V]Z=lG+n@G2SOny2X<ɖ.S+aiۂb^ۙqöâNeE;rYg::8b*CPRN0h  *A\I6Vp`ތ ? MWn:q/:󣮥NipG '8S8Y'M5l&8ftՆ S3"\cbw=gQ:l;cefjxNW3,4)nmt70wQ 7&0LzEQ}3x-yȍo'n]Jm[5W4}nҼΕ`&AN@7_yՄ wCsy9LD;{ssgdGӸBr_>7:2N?`s\:/Yf1'#8n6TFl4(c.󎢿 &X \*Qy+sw*Fjg;쀭(9w+pfyhՈ}\:ܺ6L6 5A'L 3|ݰҞ i>pn笩pW N6/qGQ}FV3}4~wt qT8KTTyɜH4yC\Q3WgL|Z5u2v%޼2dLJX{8xլ1S U=_^#ә6MqDgհEɭճ'ꍚj]4zAAcۡq*zEJH#蔱wG|s|b9F#6QO4ZzߛT:r$`FT.Ý%z*γn$#dX*ER>5rzs2SӠAvmxiߧRv}p>ItU+Q 5dme͚:Y8eMx zʊn &CI~\S*l֞ǟ 2OҔYZ4.{TKR8R<_ !v7+ <棣 %Q@;_G%}`-㋗#ʚ Evy0_=>]״;ɓ_~սAX1TUzz"09ˠJ Sz6V!|6~+6ѕ'N/!I |XmœscN';Gu By0Clc`CA"MϲTf7Ap>7\NϱvW4u$i691 ޑ!i6g;5'Zl8֝-/ F/d_qr.9/[zݜir7!GsGG6%z7̃J剓AC雯wgޝ8~NIXɎ/97/ITGhKh{WlVh{V*SmV}{_g;eM֞G0 yE(_#tg[-H3;΀RGHC|Fft~R;Vzh[gzC܂?5J1{X6͂*^ӪM  d]]Zabf4y<8:ٔZdMvSzjm`”$=uf^,(-ik2*PB03&`ߏNAfW jЌyVED'ҞG=9O@B#Бc+>msC+/XTR)P!AH }IW"^7< +?u39nfb|J1 9ǵEol#}aWǸjZFrrP@ij2 Mсy7n`3~iذ B{ܐ E޺ގ-1_cA7#ʽFlwȬMřv$4`Y*G VT{VbٌE &|Ռ %<2cڸ=f/1s, <R5 >`ӓ ?+LƦ8guH6uF,";j^K*k6p@y}juQt DeM}[[^q:kvJޚ'؀3ȌO܉ZT5CC`-kR1՟WxH)E,oodֶtZɲ"iC])'ջʩUWx/>Du݈L) '#Jf7F5Nm&S7{C4f+мmƇCz:8<Ҥ>c;"'O"Nw Y5g*̥t/WE{Ү T|Nf+(v} !~#tyy\N1׸Kߛjb+ViGQ.;t 51OɳĴ". "@`|vi:[BU)9]frq`8 TwsrZr@= D<+ >@+@1gR Hp6Hf(Q?`(oF b143~4e+C}yCIЈFLYnqUH~23\˼ZAd sĈ9rgΐLz{=P/WǤ0*2C!7(ڳ"Ay KU<@+2+AD{6tDǕmDz4x͜dedXQO?$m:G3;fןc9DcsXeB|ظ3e]iyK'dj, 9esy8yDP6'?\ɛʛT@aD3O9hһ}B'?yÃuь7h{7v|v3w;\?-ןR ^ f q{:闠yM9?z.,VgI1pXޤH$i?D-8 0}SG*.VNB~WJ}W rp&9$D)^k3Ԉ(a~S:C`L eֲֻf15TǕᄳbFi7%lc<ݜY_aZʓ m}' ٲK\AyӝOA_eFQ؅\%Ux8KO`;b1|Y(}[zѱ sb6[kC\`gUrSI^#QY|<gŭdz4{D #!H3(O ;om/z_@Vi=iQʰ&#2L4Xۂ믪㙮XGl:t w<ɶXOo.;ޢVʣ=, ah;"=Y <ɶ% n%zm2o]T#؟)w IzJ~ )%0 7>a,u#DdEhbvFb9XtD泩dʅ!=se0n8IМ(&&[V4=pgtRyX{֐S$`_!X)&-jHIJ #kg )M'ͳ;c cYyd-l "Q2s/ӄㅔ AV8/Qpe.T "n]k`0$mv^ "OmiA_+u2c*i'f Anyl 'yU:gr4EU db?&MϕyQ V ar>tYy0XGTqyMs!l ҩfuɾnkLDUB:v̭e=Bj<˧3Gf?7cM/Uś9r:( El&թq÷b(fSH47U:R Ds*$Λ(i|e:oVT„HO߄9{faC*0,Y `^ p|n9Cfnկpd)kA1a6D˗(9A(G<7+^2y2K|ՠ!U8痰џ+3Q GOܯzy^ȋrr;ZȚC "OX#@ljxz- ƸtӇHhΚ-8ŐRJPs»WPbF'@ֻcR۪9_R!:͟lE=YSu'M %BVF2·leΐM!~y%ذ HBlnJΊxxKKOr7eш+S8,uiXȚmӶ_TAPVy.QS+p0:uXV48wm`i>:#Q-決᫳ kTW_Z|~tص[ 7ww/jD]+[8X>񔩷 lb;YMp|B[j3~tk dUSS-f ɓ|Dw{11ZG:,4JqC]@ȁ>gfڀ7iXD%3FXڴPuIUXPśN_Pō0e^k׀6)"LҶJ$HhAv:쓩3/5$7VCwUs) yXjǫ48dżY!MӬʯQ~1_VlJIbvV y;U6i ~CRDU5DS̑{ƶ32gvH/.she1&wH?$5L%".3xm4݋aCVVl o3`\07]20YS0s`\] C&Ҽ iASâss"hYf}}.lmJpK 2L!2^GI h{T/VxTjq^B/L?wj/I!ԁ{0Pvw#^&G^ᓬC67࿴/~qڲ6)GP9X,ay[<^ 6UzϥބUϬ`/V66i0g9e%PK.[vܲ}InAI>wX&973j5:~6#:ְUd,0=VH]qeuT2(&iO-`Dp/rKra778Jyղ8G+4݉HhLMBlB6gT (lbc;+3@tCjRHk&JB&sUD _p36Q'*`]dfgTCo4YZD*t^e~>k8R>OEsrX0_zg12eۢ@tN) m'4Đ.vi?5޻fxdcujvNftEbY럢RhRagj*/#>5ǴքtgQ!fĎUM6gU2 8yNB8,E5Y{`xL֙O"ԢhOUkm¹,F\vvՃA,F.{AenYqvr.ӤixAyU@ vϦ cy?7Ϻڇ֜3}p3@.jhPmV5.3Rlڂ,h6S UhA`+B/Z ZNZX[)RIS"}aBQ߇3MEWp4{w*V˟e ~PU !oeBדͼA+pTVG0<҇}/Tpr L`:`FöAQR^~vSYJe>7TKkZ( /hC>+y6@` 쬢TQtga0]͋~r;65Scaoʔ{M"yo%jM[DSWIV>]""ʾ\r mtaJ: 7׹$hhvGZ p̏B涱_}j#gpf1.N'?{q>a?bL6Uv#RG`# `D2@q#+ s`~)E5̫@]$.{UQjV5t`K?lk?%#k3B^uO>qPYfձw{UkND^Ô9p>EI bƜӈk4/F68!.1Z:!6w8,k̂) %W[Ae*Ctg]h .-?ƦD3SU;0U+)4y :3DuA]&liqӸ?V;n6 FY3=,/w3OA hL4O݆x7`ŀUQ_=9OF%=1d&zq 䙾u/f%` Rʫjv:B@ͨ'VӞ[ZҦ%^d_`z2&_XЌՇJ.VF}ot#1U_*xic@ H"'Lzm!*8[Ͳ2(6AVA-.OzI)|Ld2"=dT&A叾 >T2aU/f37*V(P-VhえcZ}1g'y8Tij%P6II9nуiGX!5\|­Y?s?(;Ӫa/dB{EK">rMd/{IY[F:7x e@F*yD/D`VMs҉a 87f20сO`e̹oeTO0#^daZ"^MGFTLsU[Y@jܠxN!̎դD-Z 7t ! _7_&vO`W`c g#`l0gṖSڐRafPkrM^휩K$}ް景 "ҭ˼C p̊[X~x/k\,&O0{~܍"yU]-ڬ"Z vQmUm~Bi&(w~x0Dz z?;ʞK8e"N ^ 5٫j 31ba1J_O\ `ܵ 2rZ)"k™6#ptVd"h^E*7 Vt 4$f/TNMd}2nɤP0ADjSX&o YV2 J^opPs~basי+֕DL6sS]U",=ڇ&N2~$5 W6\od8#!<xE5I-;S /3$.Xn' a jVի_|ţ`+QW9';ɲ Aַ.UDt0m ygmEQ7 ?c< TsC"` []vae>ԩkH;5COj۝`mr<9L~?kRtfUP3RNjB4o@2i̢͔JM7ouZD$%L'D\yfU _ۏĉRȋ[#At>DCDUVJKmKPu?;xEК [c7Xoxʐ3i^s`3v%BGhz&]mzI:ꮓj]AV?Ϋ\ڱ_ =ھ1Vєa`ݹA "j8v)&JճthYW\-^DWGHa `eDgMrͶMdwI %f==2QqҮ8[( f~sXbTOܺみFtnG0鄍NdOY8rpۻ}BeXOgz||vʤFɔYlL ( }0B``VA]hn>w[*Hc$濑2 -d YCP#VW ~n<" +Z'xnɅ6!GGv.^LBWsV?O>ʊY%c%c8X%s~׿@ ĸ% D2d-f}Q!؂dָF]BIXnNS+)sFUDH~x?\nN1H6L(grٴu7wy8vie_iwWGHM0jzV$gJRJjzŖ_srF Ƒ̮DޜM'a-Ț{cEM q(nFʟ@XT洲"AHwL0"yd4'P`Pl;Ct|u\d75 ;.OkYHQDS=;$íf+&k[IɧE:™UiԌcqFdu.Pĸ4]6Fg;SU* ;X~ޟ1= ¦Ƕb/foI}Xiܩ[QXZa֫!q[᭟+2G˅A\.&TZ>#B ʶߡu8}wmמ?TȹP:II3`eynb繙3I5Cm8mdy`.w'd@v_շ5eU4UԵq330vюtƂ.Ah1#L`lMeZ ˴Ȓi9ELMm#҈N$SSŐm|*Gjg;IG9ӌuXjQ%luf$2~ *dɥԋm0^sOaPI]]`g PfjbI)Z.qHxhAP,S.peYTh^XdDnA^" M[VOF-0,c=%X$mDcm4±Wui7 *@D:QK"VT\m5&íxN4.ƻ`BT8茊U(1^Jz[VFs YCX֡o`k;'œppsH'Q 5!.12xB%:J)m R#o<1ۜ?MHLh Ny޷9kE(Bmj7S1"}3VOq-['73kk;@94wqȣ,/pp}WMء`h(^Gn@,9uaΜ-U떫plL}Y8w3iDvJ_ЊdzGЂ-1@ bc)XYm-H\w$.rxbvO3qy䙤9PֹL,Řut9l^H06:+M#ȡ#Q7eGmnɊ yLT?SᲖA$QowNƦz)+i,AyqwD^.1rV֜H[DpoS ILTֳ^19R[>J^fk:f5wo d 6}/.~jB^v q ,>ЩS&6c.60ob50e{:}uQ>במ5$aiyZ?~Zdڇä_0̃Dlu oC ۼCAM̟A3BƬP|x2hq<ȹ<*A T呃ٗ[4nFrpF 2g<>_$Xs\BqBlGn[Qk9 ܝ=.Bg=2h^ ϔLe VɘabXWH.u;Y^&VkN9˿<<)8'8QlV!J{ A^HNXBسGbXiHlYa(O?e^؟א*7/&SϗELDjr Tk[g]vIz xҢj?v%c^0~؜!繊4}g}o `V?8$}:.,J,#~XB~d5"ҙG#C08-cx2%7PÙR`MCiwMީ7_zW" ݆tf 2[Ci4};&iWw77~5V0l2ЙD](qOLTʊ_1J jݔm|zg:|6*6;Qc$,+s}.q>A'`g j;}j',7):ܽ?TF_&.?eexwÏ+'W)+sNw\OۡJqV)#Ệy̭!@wdkncsl0Yy&AǦkoꉒyg>1#_Awt;ep=lCEGͫꚐJt0!UJ󋒢;E#6Qq%ypH%!;#J3<:68 k'4C'V#ѩD#GEr e,[] k|@ ?@ф44o>zxVt}#R- gnL,5)C"_Io| P_M|򯹉 ʌz?՗ 5IԪymcàhMJ6A`6:鍩gFR$8V b5P+:ҋzZ U}! qǏ~2kڗuY)"]&qx`mЯ-KfA\t1;&L D(~tPɝ@̣ M܄KzBjuQ,{ۉ>er 2]&Hba e"c#~[bMg@}7z`,-?CDQ geN <;~رu)r>3+z3q>F|UGVlTduwԋ,dR69S5+2! f RKL(_Q~ ēJ6 )PPy6(Bv+_6,2!)` BKmOeȭV1=B3Cm:GG3F뤈RRHoC#@T(<_YP<i|/zyc,[3]4Tdiҙl[6Ԥ >95L‰yy-o-]uyz>9+nR9A/L,]y ԒXwi}EyoקħHP]Y!Djmz#:TI,ߐXOxQMZF.&"(s5{SL&"mZqaqE\7 WJ%=dZ|0M.v7 ŀ(KmNĠO{: tV\دUl].&x@Q^3^^X1U]P}VxY\1of,Uܢ*`Ruj?5z` ,Zߺgm3vW?ճ:[EiE`~ZӲ;xOߨ(3hh@L!74g^׳۞-緖loNZgI(/v3SKŜQITSݣwޤ|!YXfX mssٗ{t`^k6|W}6Bs3\3*IxvΤp7 DGHv*}&#Bx@>V~&糴ȿ. R?~]/VU_ژ-G/)<3miO;kjwz>_ntu<)/N7VZ'7B\Z̲tT`_mgVk)nz01 jmREyRD;28Tk;syh=:*[pXJ/VF|PŃ(O;{inV8%״Mbr#xY+48\s3LQcM8Kg7]L`vV3n<>9!xDX){%bPvMVQtJ:I|yhvQ >Fpl+a^8dmZkPͺΰ(˔@@1d0uWYʹN7-/=s[r_Ӳ"A(bm冖/4.G h/8x?;?6c'73@EB=Sp-HoLYӠ^ߘԃ(3諾ړsSa$]l"%',֍.VkT( P G VK6ͯDʹ:ay&7DֵE^tekҿ<=oNh'iBnquLS6] Sx֤8+)}JնW2dCamRuھlR]8!1 w|,ʉiՊlOGۋZ|](h:u >V58?h[=A_L eK@1Cqi1"fXV[L HSiIl+!Oygx) M5^+ -Zx$i8VZ/BR#\F2*P;MVK .֧KE`BB OksN/P:\{7Z3Xvdc.}V+#LdU؅O,zooaem˔nJpY<*ʂ=7+0;m QXKtJ@]9@d/%Iόop+ق;E~w3Y/c]407|VS%YO a FUf >W_2@$SkRM5M%ИҵltdW5.^u:geKߙ/q3AQ)/"C ׫;ƅ5)5p*ҌQ#..b-6c }kq՚NM[A햐ȉf1ЎyAg/4 y'*d ǟUeP +#MnT:N8oUy^SrfTsަq+`*tjL'Fz~0F逨_[׬x29&aDB cU[^8+-ۘ Wٜ)?.uBv'Ԯ~ Y5]'3*puјnOIvfVD|:ȋs<9PR}D+ʯqWpƥTwP޾ PyBnLUv-J%ĻfQS4ʓ%G`U=;Zޫlpn>HGVn(-:WOXS#Cp$wt{/o|צδd!"xOYgQTt] XͨDiá$Gk4)S(n:'/dM n(b4c*eqJЩ JGu8)(:.Ȕ5w>ۼާmlX.O\gp8~fA 4gr0w9q3άj@P.%YI~"з9\KgHJ%$_ ?'(A S͒m:v=a7%~vբ zdyp=bTHN7` E ɼU|rfZ̑~ k"{N׼TUgݧTIY,Z6 5dM&=<⭑Ač:/W*hw|.NӠw3yI뺙(ۉkhhwV`mHQfT䗻9\ٜZLEu±BF19){c<#0C_ne!Al=L+j=W{f8bGۡX]T*13sgJWxHJ qA1@WeFRSydyJ-pyHN vݮ:}W^Zh1j8_ TWT#Tч|G{֛.KP/2}g槈 t|ݱ?){t"!&s>Y?S{-)%ӧc-S$Acói^u Dz$`7&ǭbV+za/w̄^MT%k:7~w; q߾:oZbF >Nc]nylE}Blk<|A4Zh}oY+q#/6 یfV\\2$_ZO<@^*}"V^J'἟F=x"-5 oxFNj]> `Gwfc jNVC#M.?.e(x{V|s?嶍0*nj0|Cm/bws7 'Rk܇5~vD;;ɬml{;P&]T59!∬LE8%i6ZD.Mq3a-- gmkīoGZsv]ǎհ~7@0?6.LKjlʇxN6OVa&qޛTzO;BVx/1y95R:M҈ڼA&ftH{G`Rb<}9e"#^kr3?k(>3VhBbQ qݟ~q0 ~hCj! sE~8YX6 _~pYXJ"rkGk~RK.U"OWع>$ +IߞZV L`AǽP(d-ix̐yļ]r[[jƬ_=4ߪvWHѣYLW9Ad#P\5sR?yaQJ0OTTgjSX/BbQHJd?Iu%pk 0S\F[sJ&ŵo_:c=T<%IxЬI<\§-Ew,O#!yY$w ' 6? 0E_VO=ʏq& ţ0i>~u`d%@=dlO[2:!lcQ*ҙOۮ/:ThR5P eiX*ƭbZͲJ9MvH MBd2{n<|^^ Pऋ1f_n_` w^?aUיKՙ<1xLM(Ŀ%aDb{sS0}0뎎s?iC"ڱ_/ /s=N+7b6zbQR_[ie_pApl%k~Q_%\ Ce#ȎfAWxoyr>ogg uխE&+#O xX"ǹr_9_|̓]&^b4kS-uڲr&M+sRҫ}_ !(e^jOudW'|&S{+ឍ')e3(Y̎IO&sHD9-(}6xD|n&y4j7(g" ܝ CawGIJ\!TI ,x|/Ekd=*: ToW8ΩLDgJ0Xh MX=%m)Ԑ}ø#mAYvHxGOc/D$6mYҼ^tGD&6W*ddx(coF͎ &b>WaVOI]i0o`^ i77)~EhQx βU"H/mb*"gEEJD,8n\g]2f^<8ekL@?8dny7Jxgy$rlQ辋%/U8鼁g.CeTHDBQ&2b7W Qgm#ώءrVIׇrWΨw ZM(g@IvVΊS %:ņ#0~8I `1`&rvQ2=EOJG"m̹!dSM/*&?CVAX-|RX@s hzh+&G]5Ğk0PAK 揂3$ ls$sGς¢q3s3r21$OBKO/ؙ6P; Vce<`;4־"!9%$S-b dzhGRSñ!FqBr!+\fIEb/2nT)?a-›\23!hE_:CҢ>sMKGަ[VL:4gm)Od[3h ȕNEUvnϜ3{\;(|)#~Eb7_~"%[c0ٽ*z}w3M؝Bl[+_XVLJű?X Wt2_Hnt{"3\+nv M 9nEKtsjXrrsșI< Ok[xf`MAwUY4?(-Qm·r/P8[U2(hqW35ҸX~v{6:o!x,9R"V ^Y;%u}u`c{iVؖ$l>_BnCQv!!/nIbu;~0>JVͺ (ZED-L> 뚾) },@=}eX XAwĞ}~& Mr+0}ɕRNq.aEY?e%d4 ¬VoC`Ց>#t|?uT*,z76IR8y\lE5d= +=:9t&owh_oaPcegВ;Ma)^/te{}̏<]$ozy)juTwu/Wcu@Q<-y/O˧{UWߞT=e0k_Z?=gM57)}},ZTPR!"6Y"&huyVhHdS*ICY?,m8I։] c^F" =,6OTVF+8%!@ ௺-9]N/Qãﭡ嬈\JIByKÙY4XHcHtKBTOHR=~g.Qfw+ɸ9PJ䵣)ݾcYsjkF&awxvz&n,5X߲J-'x_&yOCA`O7Λ$D>H։s /2|]ooSOgq}AJ O_m濲>h3w486`&GH; x*nO}T8|лL8ͬB]Yc;U?~RC3ۿZ+G/Qo?}f L¤i$+cw<¬b}Pn08R(]k===3~|6J7ek!Vo͞ou1C@ou?8)||LUbV4F]Ǚ 4f Vs;%h/#hv^C77.w엙 ]-n7@獺ylq:Cwt^,#nbr&Fn(L^;cTHEk78_dΟ|||&Ѣ *úNX['4ֱ0CtkyYaw_$xCӶ|!a,g!`XSV8Wr5w{8j]jbؾ&Qݿ$*$.+N8 =:Z ]'tRH,R̖vu/FQ vfCK׉zcQ0/Y)#jP]WFcr@z;Cs͒T~zu4m"ܒ(<\[Æ6K%+s,gDDu:̃@C;"]@-p[w@,:eǙ r^qz=KN;=ҋ+ _2P&s#RȔ=]~4& )hMxUYCI!*|K*%~w!~O5qɪ2?T  *xi ^0< lv?52=\X0>`V S朶ST>S+1adZ$GRV̉!FX-$C8 Ńe >=+a0:GP<ȡ .s!8' 0] C`#_{%=H[!mx2v4?x=r Z{Vu~2XY7ɱx] pi,T {ߘ{Gpd6FSyhjz02="BṄhxd;U'fFf# 4œ5dI0FWNlXLthT;˪^+#oΙCt!g%ѭȮaL62+x׶tm{mLxXk QHl0#/VT@]ܤ MoTWoOM;0 x]s_@_u%\ @d}U(3,IAsv$7T FC=:sD2];\Tk/βN>[79~wd˯_feiϴ}K3Տ;c>MGGh+򞎝9_g(8)Ϋ pRb3$\A}laV U,!Nw_ߡfj7[guȃ8w?zt ~pgNys DM6GRӆ <0Pإ7_'= *JIN)\"H%RWЩV kO=-vUM(OtӖzBaa*~:W[AVz"BRqEB V.l6SKZ#qAV*R̔ ͹ǚڭ o%B/oJ=!Flp;Ih!uC[5)v]}Cm`s~zcSqD8}GۡX{G SqdhաqEW V;Ou!z<*Ϫ7KYcheuRDA ԰3Uh9?n{kcJsef_{-Axx9GOSξwu&P9$fnqyNtݍsG07?bjrc%hlTC_9sX+7QNm 2pYE@aQJc)y~b>k2!Ki,TkYjs27A3~1j\E@NxBi=O/j!H9sʻÈCtY1۶(`Y>Nz>Vц+;cpާy>}]Im>0!W44hقF+:J EYc@ka^{WI2~L)0:/VGh(-9cb( fq>GV@"5&k&9VM})h%V\( h_ScV&;PuP_8|?r=[V+9-宒ji@h6,0\۽bbO .ji#ϰ"Z4w/|~ꩍ UoH̝ndUѷC óF& |c^O%'~pT>qƦO/*?-gKTf|iNhAT "bQ h0W^)ԽHv43}* %X5vz.L4mG/UUg7o  bC2T<t]+0|,! F,߶ 'I Y딺Jx:(~YDYGxz`D^>Q|-2"!hw#YC! d- >JqFv; #Ë7SL!{=^=؇-W)a PR6SWf>vT 9I Gu;k. -pv6byY~ce[&Wj6V-ށmL:iBM('QhPݷ6< V귢:+.9NNJӽ͋y}'.f_c`ɖvWГ~"d#gd1;7:5CS@av UU{l@MO:ٲaސ^^>p@7C\)-ܢ.h>>3Us) @fn<+ 3Z $7ۆP!*#E_7Z;=?7O,/]@ 0ǚR܁( FM21T M-1 -3Z[Ҹj"Fħ=D7wH5O'^bH~7`x?rcfE8U! v)JLW^ G"a6xMUXt*V^ou'rn /^G RPᎤ\ObYbߣ)g57>=>}zAOOfћ: \c~]Bjtj'3eez$AIJX-$?O'X/"k%R~G'<ӹ18`Z =-BB,,c52Ր'&"DOJLzOΉ7!aOih|>2[$/RPu搲Qxp:r?XchEsG4ky142YiY׉𗌥V%E!Q}s>/8יt< 缮 S)⥤ BXYe=zVW8 LGCߺN>K9_x) 1;Fs+5Tܘ 59D?]hDc^Ϛl2ٖ/}cuȀ|?u*-~<{jvM.l^SJgn*Si@Uz,0y\$si8CgD6=`[qOVTax.qM7SlYOr A? Ȅ|%֝gkcx66n[1a-n5!Z qԢj{|`\N0n ÝW@tPkK8x<񒐉\7=glBI𘯑ϖ}'dM}Ap8jS!IKHZ L{Y0|hy# _}Ry9|1OX#eųDJݤ/)]O-kRtaT;fQ !B<&fv].YY{!NACWp[(gHʊZ-ZO>v'_ϟ|BTfBf)Ff Qp%^@>ÐG32Z 8`@+TH_k\ !x |Zf<8!M<<֧ECF=켪MFՂgZcix؟1]f-4 gB_Ʃ&k572oX&d;bK;xq_xZg%h:/BlYVkRYbeE S|}l>m\~-$Zך ct-d7qT]B++XV53ܑѬD٫X.]>u0dDZRc ;u0Զ'>dWKʄL}\e(nMMMt8NG$B^yу^T4 ȳĚm-]J |gLHlw49$ `4NXep>t9V;~R QG@6v(g[,ӰcÖdRdwʜo֖Ulɩ_{2ʔvn<)B QK-)FF Rx}6TƬܹZ sʚϹ2StQ*XYPl0`Е.^gEMϻüOg}t X0mQֺHe :hS6lYZ3d[;%H̾\Ñ1 .U5U\gݬs-7Ib2QFu.c L]J5Pn1&O={Ȉ'ȘgMᩉ{1r q >ۓC}k[ŹW}6| TN[ظi q3P)b Zuy%Ӄ΋ie%Ļ2Q y>tȇ3+6K:ᘕJ_= rKj#Zͻ{zٴN.yq$-mm$pjlx9I}oˋt# :]Ȥ-(N')~'Z_NMȉ)vfԦB 'HbfZ:ovXpJ8Ю6rõΉ%h{$tRLrVAAt6{ހ_Rm>ie|N=rg!WU(/lfYJtNl_YfTkT3<7.4InvهgE;+7Oa55W!|%IʊzjBpJk@ 2af@}ux: >@<Pfrv^!@hnY~V9ҁJgy}hv`jJʠrZ`41\[~t\LVkZ>Ew뼤̫2V.jBLsjݸ5NҜOL?]DNH>Eitɓ[h>p>8(~c;oܲX R߫ٳ0s odS+3hK/t zV3 B,~vCEhUi1K '^XSNw (mW %k`#Ydw^EsR~~Y3OfT%4a7; "S$.6{HHfƨ,1eL= #v n魔s`u=56F6*Vv38Of5;~XG-lYscb u|_(xٵ3d?/vکuMg֩*sNU43'qyOaѱ914 Ƨ0{L,a;Y>KTSmb ݍӏ|>e-/`(As*3=zo۶&k4eO.s>t5tMؔH>DI)CEڞg_fMI JtgU?lnSQ1+@W8 Î4`vXm2Jӎ"7OYfMx:dA%X{JnH91:VgAbE;u zwnŮR&i Oe>7?0hエ5~tl2j RܪDih'zz-9c}zٯ$2n w1Y{n(>'vޓQ-J/,ܛsC]N@$E^kKyJaèuC Td7_cbyԇeFZ0JeQ9Ỉ~m>*ŬwڱДF~@B?AGo=l G%{h9+Wg>T~Wuvc2Vfsf_@ۨ^k ^Iår~=$5t`R&F@8æ.;T/&묾Jd\<8k9o%d^o}2ewwlwH+XĪ,[w-Stqb"1/-2h>G7uᒆt*ST&6x_`n7|)Tfw2﵂;HS #6zxTwS2;ƫ\C\XWX< |%$%i7yVqJ'3od',dVUZ7toh(d})âijiFgdAnd8_p.d}.?2Đ@ k_wZǃth ݹsx@ >kor|V3U–_Z#]jG(Qo+l6Mkd^ 7IP(羍Bnyh>YWp9A9 _>3L f[,wdyǺft7Ӹјrzkk|tҋFP {5= &Я~@1ǣs5fdMj#VN4JY )c2a?/xTMH/!X^[׌=k@kM)oqӍXM %c)>},Ǎ8kN_ tG~C9יb?P[j9*oRy[z "֜Ҁ'݈Aeu]-ۭ`e+W6P$z67 4JB ȾB>^Iުs[U}ʝ '-cXM'S`W DJXα`AZa0"KG+GRexGg>@k̉D]I.@R(?d<|'Yi3>9~b4Kb$TIAB%w*`%9y0bvUu[~NDE+kB:/@&ZU2|:HXP-:wg!UI@~*:vn)!ouR"<KQlITd b"őkLdKQSrdP nBXrܮCDf]H)ڱZ n7C ?oo5cuFH}k2?@/*qu?Nd,..%l u ie,,Yיbr{T7xqE9iwGp!epJJL.V(IA+iCv2|J朻_WűFvpVт4KPiJPŹdCI^2g+NE٥@399VΰGK*2i߇k |t>$\m65Ž7n "X SnQ:sS[T8fc⚥غ.J1I u[yc_ůó֓>C~|+敋@oGۢ5R[x0㌤⮷wH^oΚf&!E"A30ʶ6+́޴ipEɏvPU*'2`(sUHv`ѹf5K9*Xy=c ղqrd&6]͑Y4-mKj)hʨ[+^#!ںv 2;L/dN(# fH)0Vx[.R։!iZ2ZPrQL€#;w?Enuc)=ֶhW?džpwFRVKJ9g!3yk_ m e}:i*:qf76[֑}H{PgZϤ5:k2hAA58 qZ@]G^l lBP(33(gU XCV0Vw؇g[H,a<?v}BqWz< MQxi1+<kD}ֈ-U5s|0$K 4=x`2NZ~Yoˌ1 e9qB>܇t<)-ԬZ`34DIJ.2{/`}^'g64uK/\qη ҌM޴vCu:oGS0[_MCbԡ2^j'i|6޷QIEooj_nMùB'2=dDxjeՄg 3%~D&a4R1BvOl uBgw Pgۻ\q8G NδF]#d[ӷzE4Bw=~yyM9fcr])NQ7^?Fy;DQۿ7c^gcܟ5yM/@G;|rG񼿑eiӒc@| #W/W3F:ճ̇DkJMa3H:xyOCJCɐ eG0$V=>Bv;Vݳ@gIE= fz)h٤9g(K  !V; TcD ZW:LJJ):Kr\N歬TlhaCٷ|n9`6"tǣB]+Rgg;c.nfq0uWk6hI[`ȝ~pt3@6_HEL7ezM7Uu?0g;J6$ qȧm,!zpdYN'|iaAMҦH[wMho bTVVUֺ2_L/+*vT]jck{9c/Y\g=iI3uOdU]m[>SvKCD-ksښƍ)+Ag³ԃ+'ztI!7z.qu*Y*VHbmUh[/VuJe/%<=XY#P+u* 8'Q3B yf.u~C0 pnSK cw;v&gjrm0 F2=G'6._Oxg<಺@ElVpab[/rG~1V^`DE3u%MaWSi9qo#2(=SX#fJn'Hgy[qX' rPQ0R&I oCu"*}3jl"U5|ߠ{ѓ=`V_7gc!RlD뾶|3ь f'tXz>q:R"o 13%!I6:s|lT N3 @:l+LYVǾHE&:Auظ(l Y !A?Zw6F|XoQiAa4JܝY,3Hs&̈tZgЕcV g4cf'N:|/%L]oM3dajJ_a:qe>+6dum0x O0+4 B[7IE\cV" *&wY3#\4^+ު1WmUW1'S -}w`>A3JXFH4{W5rز#]PZE[d(k\تn^;@rޣ9w7ͱzs`z?p:|8?$01l7ì#`0̚ń Pv4\T/؈i8#w.qCK52^.]# \ӅMڌxLu|r1HbjDoN]6}d.dJfY^d <9#q]bFS{2D|>>f& 1R*T_qTo%Jy,Q@6W]I^Y~? <*wlr#9[.)&M`aLg'ԧ^ҡeMCԣH6eC:1h?:ظmqvl~+ H 퇓*Y%rB]+CchE{Wjl : OSMϬ)X)|y.xkxk @3 BxG.bђNf}r8OQDgg ;hb+kv+@P ]2r p}`*EhXLW]i<גȟCJCn:2zt^gOx P,v6 rI"OewF+:ꍜ[R,~50ͬX"Z)?MOA$yt7B6^m\U:g,_B{$8O:/)I.%JHTS=ѶNyn(T4"i4νyLF_`0Xg"Gn?irRXCnq5&XDj h1t_OiL@&".emwSGd ٻxL{.b^ʦU1Wj5,L=ڮ.mz)Zʕ+YBNw lw;J/h2x֖J"!JV=};P7~Ž5&ք-z7Ds$I4t9?2> ~+Sp"F^gw:z] }'V]l7'eWF͜]{ls!vwKQ=pM,3`͆EiX|B>=Prg~&P]Fx8si?b9Lv~ {0p^r83!-_xTIEosm&Æγ"䜤$nfмٴrdjƙ:POjh9q.;l1>6f1vZ+F=~FKkS|tŹ,1j96.o@RQ{B;N8M`l1Ϟm 0pP˅;[& ?u@o0UhIV4tQ }gYsmq_C?&h&?tcI8itYnS~?y)4'5Vwn_̪TN]Ԁඎ`#'G%ʎoT{噕9]@oYѐ]w4:OʻZZTug~ r~⤡+#2'Uarf^8YJqWąXBH>ok6ͪwBj3[y4b\s1F^?!6y  >~W24"+DlJm>orٸͿ\t*W OR33+6S4FߦRD2qjC4 f/>KA8j?E T>SvEĩSd%Q[th\uYUp^ ~ɚөIeM'25}^rr4.G*qoo{#Xų^'y#,w(V"sc62 ~ 9kg/;4#oZg]ػ| "P*3ylҼ*MMʔ}=jkx#˚?{QV*:ϵ4F^°[d6^1kGnBhGvT>$GiRhRgq4Z")!(Aь*<2Ǟ* 9Е*&#&uJ%I5Wk9h !uA=PÞS㾷%[A\BJLUFtXfqkr]Ծ'xD@rʐtKFoTӈ'/L[(/}ǫN'ORm".bBn708'xOuv(t+ߥN`\?*{)>Ig.h>3{l}sAٽ4 mM? K*wjr;&FaU3єt;U^<+t3aມ $yDX6[RycDXj hyEF5seoK@?(zܝא%&OvͥW]&vyֻ :k"+|K l/+OjN087ZpGR\91 Uyl8 -aj_1trs8SBءLs܌ϙٔK#]s5~ʯk%_"-bs#+VH.EN1 toF"cUB=jC@Ijt X)RfъYVw;<'4lZN MBԻ10Rig>qIYz1zh)Vx 7L~рq>X› =ք7~ZzNV@>7Pؑm$n˟pvgdeJD];5:*1-@n<3ЈWl ! ¹&cʛu>ַHՅPF@@Sq۬e] 4)Nk<%-3e &9Ly:F*Tu8BRVq (^\)[BiZr0贖Lbm86Z'GHq{UyN1ʙyul%/"3"{ȭVM eS") ]}( nM AJ Θ!H]>%zuB^鬮k }DkOL:/%_~c͹^xsX5xGݶƊxB $:$Sa=} Y,W now_7.^Uyg.wIɆɆ$8v ~ar8ݰˇ#ya>j>aڡpGi7mvӑK!]UaWgnXg@VAk';1g )Ht < Ԣw(smVg. ʎ+t#|.#PU{A>L@rX?|V_iG[qW!`~0@_0|W7GbD`~QIF[o5lJ9mک?8;mf@fB,[xJRei%r-!霆D!m"s3QZZ˶BL~yZPC^)}Ȇ i:2bӳ-x#,n42F{x@皧H{@w4q7; :MZ\'V̢YV5`\{y*[Z~Rv}磮g2좼' ;I\{y7ʘVrKҹ*Ok_c<|2~zCN I#eWӂȔ3^J752)2tTlGl!K pOLIb; Dg:z/D/nO%C)<$kNϚi*LMxc90Z'iү+:{k@J- )@"SOGF CA}Vs]AN Ucx!o,>2]Da5[]W֦uw}s=)Vm )JI*z(s>y&m5[OcplKB6B[Qqo'2\b$3vZRS>ګcmڻ:[^G朿Cuajпb=yUkpce\[ ۟xLYu6gcYrRuli4qWkInCц"Ѳ0M:Kyѵr=8i ?] {y 1V|](p,/6oì9*Ük{>&mlqL:*ƴR*×{T '8gܬ]_ }x>eW8:`E+ДןJ!ҡU.¿QU}=/%-’uMߘ-͓?=5ء/-o< 8#|F5СTmHa`6 ,~'^UҌ\ԮxH1E;9+ֵTػ֎M>!-ngzOʉ;Q2!`O,zmgNs<6!5Wl0~B-5@@;_fM1z>H+ 5,H=gF4?!ݲXELN&!Ukn^nb>r2vG۶lIbr%c{I/Ĭ:E: Ifcū`\0]\(qo~}m?SsǾTհikczu2Kf)&] ^!+5 \Q#NӬeuZI]CkhlGI7M"x^zzt㹋pǍ%w+iyTtws:VZތ=[ytӌ{ "G9Tem?th?F㡟+]*=:)[0!ׅ?RciYy3卯WB`z5hXI65EŞpQO.&J^XbP kgzc]g*(-uZR̻ x?8l;ot" eLMLטʙwXtDj[TNnmg1Æ9/NY)Χ]뢽#;)JGiq s* .<+9# <h4$i'sDt5srdscq✡7|ܛ<s;뫾e #ȸװTx֭nKoQj 7bys\vniy-R9ܵ:Y1O\=Ӓ fq Z 5;/Ϛ\)v*7| AF40 Զ4Bv6k'Bbh?meY鼩hp%ۄ/Nǚv?SFYÒJkt`u.LVAPk`8ayp98d(>+ڕ_tJ9 ~1Ù"%Gzbfi.3"S?ЁYnQ>ZqTs8#^:r&^Ib%Xg LӖBP9K4^3jdF/Hfn o#='"t*qYmr= A9yV&(:>(x6C@mugQnMxdu՟d'8Wudƺfwzv#k[!:d=E8co[\zC NL|&{Tˏq)#RŃV=yf7F<7cӖ>mqGsSGrLZm3V#ls~xAΪVNeI{<ӊs2K[ o v]M_oĚyE/gT[')poC";g M+Bf]Fmx9Nh`SrD'/=ȇ5w*pf]hK=T#BqIpwLcSPt!ϱ֝]a{Je`rg>7tzgP`?gXS>n(9-'ZWk;TuEur83b~L֖#ĉCTMhEõnm܎-]>k7]vX޼@E16T!XsxߒRR)p s!0S֊bH!:T1}b6k-%>Qv\Sfo_=嘆ڬ[jΗodG | ĩ{(=J 282v]tϴFoi|U9R*6hԎ H+>r_>X7dN&+"u,tڛgצE/wl!﬛g1PD9nȫb &|)()]62ޡCJlWRus˖c`Hәnrgh Б9ƻj!j&6mY+ʰhoIHBrBrItUzU*窝'أt^.rv,_wx*d/XqtN!@W׉MGWq5\Ľ3G۾s%`t1*'|!q@ɱX{Ԧ7$!;9-\m7t ܙӿZ 2.4-~KA8YD N4;eFr.K]g' ڝLpC}(#͙K/wa٪;b0ii f?.M} ԸT+c2ÕYozSm[ym:WԉYbN?M44Q67(|֙ f-H rECgy{8u_(g| Vo6v+&#%=w[̅,΅8}H ۷MMiɵז|DoRhipxlymy@mJ%7 HkW9CӘ0껻aFtiDY.Ŕ‡O!qfg={ތ ݠIa Ievv9ܝx'Sc0/"Ij 62#GvNظ\2;] *)G_Z֧]%PwP״gs.7sWϻ}:*Y#tSy.Sxt}~'+W(\)VCۮjٵidlt ~LjLfߘ#K0}\'ղK%apEqa}=s=7h:GT_ﺭ|Q$ߋU&F I1VH;*0άl'> sS5%O<;mnqvșrؽph8kvi70 m@Zˏ3t*zz+|KЂÞg7YGhSǪ~k9ng1g!*Χ?0'F2 '3emS5ˍ&f'|CbD`pwiB3϶1TLbq1ߗa}D#]g"t.k(scb]q 8ۏ%Of%e8:yKyI9+]Bi$@ qd,5y`QF$ (ֵoɪzER9[bǹ:dJ0Jw?v̆:̄hh :!, (e4Fy۔9bPw]ybƓ1.csHd 9+]4+B'n'׈W79 c ^KdFͪ.-̼)~Uyq]D>I&|qN ]I9muДieP .K4}R'nO2w , oj0RC?txL5 dzgԇU& 2 .봗>Iec' 뜥R-D0>lȁHf8ّw!kzYQH(mJ d\Jq%Lba}šZWdD g xj>}QH,ryŬ1+N3Ms$˘|b~s7޹=c"6iZ )%1k?"f*$éT^ IG]_(yB̑nՄua?%FSwv4[ ')M A1C %ʩ  O;}15YƔK[{'BlN@qu8Q>e,xq 9' Rry7y(?$N,[-yө:ǂ&c^P+z\[vB&F[ty5O;@L"+r=zVE8enZ"3ٴG@g.wwS&[mg63"‚RӮ_$PZo͎ RSȩosӴhʹK"ù,yY3A;Wڣ!2sMoe(/-tJ;iA ߻$J ǖd]NLJt[\"9 Y'(ں2S߽zm˓߯u@3#q"5z5ѫl*m |ϗFέòA4tTN4(]mՌ:s %)O-II'Bʛɍ֒nDdn>0w98wݔ:EWDzᛏ#b]J/Y73ldO(<:Aʖ H(=VSl #IwVܞ8Zlq^O4 {ѫ>@GuH:8Ϣ֩%D ?YvԶ lL`}u2#BS)tqSeTSN L1u=W2o6!ypț;7_omAJTMgdCQBܕj5di?&.ww5Ènm\~S Ȩ9[vLn?XP+AkpWUV+qS'UsGE9~l 18{:9@p1xHE'6'M/e9^bj?,g?v.ܳ:{z0= {\?Y:0/22ǽA?$$nͱqIty-&. _8FRj@r~[6OR:Z:Q3g홴/)d&2Bu/ 邃>ob'(Za:6p+fԐs"!VJ~Xjol^W Bؚä[ϙ%eA==EH_uvpi`f}ɇ xP%oVY4#84}ʌ(=3xqjY`WkL좎cs_S;U`w3g~{/3* I I~mVGl#d4 E_cLZ_Jad"'u_>B]tV>6|ߨMkx+|9ϐQWARY4g~A^;GZihnPWz[b4Z`bQVثлzBz X۔ND$w tT({AoNM39>PYx*bbL\Q%9:?B 917mnl^'p/ NP6kқey% $prޚҰ#3Cj.~E"1 PǥLZ07͵8IzjF[J6 86CVhf?p:VfU8^o'$⮕-ݒhZ4Y[eweGܶ+ U+9a v<2=c:<%^Jťr !C*'^"r-)o>]4b+WoڼW .!qalS9Spk"\{z6:Aa2KŘң:ռ>kt>NUE^ANc# b}e=pcEᗿ=3SXrX}=X%g,25|yy3/duTyOINlP @"u}8Qdhx!WWSohKMVp&%OW t>j95F=y;e8RC詰 |zM^ƨ)5Jxj0$sʾR i4)4ߜ%f@%OQXm}QOsEME+ ^2z7cÚ19qbf O;áڰnVŢM*}JL-ױE{$yBfGGfU_>:pʺ%\epI򍲑y6XUbU ª)jP^k@3QV)o eQ*^+\S.ݚѳ0ɭ˽>/фKa(NUHS ۜo_ ޜj_L>,†v#2]h !{kNpXaXe696+ u^$fHw?C'2/hTa9fӍgȦڱFB4kx2KSEWp&jsgHstwIvuԹ@Z̹\JGS/hӈh.xdWB[jV4wf3$!%a2yGCO)CF5V?T9MI MߡԐ5$HsX!$j6ANzBNGKZ6Ă7:cV~ɚ&zme;-6L„n<3̠u_ #&ְV!%Q\F{ZvG??ozzNwwҐ7l8!р96z*~?@huk ~^$;:Z|p |xj\~]‘}T 0K58{äa7, Vn*pȼ1$<?RO9g1Zy ~YQn!)B }"c{r6y0 Ū6t <RϜW;`T"9(.Gajr,̹zxV*O4? ^{YD&P_pE@octAAy?.NX#h# L%Ձ}&bZ3 Gv+!uʉˊ9 gaR\Oimg>rN `9M_ /}MIHe#q J|ʢU_G~v=^|bmq$|`?:9S$F,~52 ĚD8蛚|c 楃đdO#I!d?¼+k %}c{& c]}8@J p{U-ؤnjs!ɥ 4„;2$u=O Ls^RewO 껫>j#$] }LN*8iԆlb>-U"ДXy lO#iWbDfC6Ռ/6^ uDFRf-5 XYQQwlrCHR/ta ӄ]]t9o@C$IYRqO@ԾH/E妎.kOtR-t. ⦬%:۩01ar)'k SBRaj'^Sc:?Kc׆x5`V) mk6zfջ"Qt>a _=g ,1@/&ٷbn}+XF5`+>Q8ʣ9 VHӕ 7S"Bqg*5~DX?ܼx~E6R>S5FSQB謞}V>ݤz~`_ 68&$zo̩i˧>ܼzvBa Ȋ-:g(+3oZDy=`G3=Nt*(g4 4Q#&m s8V*`<;3V7a4$F(i&ipsbeEadVy2#BXVqY'$;6l:cM|Ӝv͆}'{3pThkoisݢuґ^CQJV6֐Ö\[5"FPr,=3F7:a/Ƀi籂Bai5ǜԤ)\5锣~Ypx0牗GN8˚D8XKx!? _Tq^RA7"+MGG8K؜IY~>t874HJS{fG 8+Ϳw$V@籘%?då:(/Eo>L&Dj߅.s X{#*DwͮijY]V%KΒĊ(KNt{oX;1񁧹8hƬ&oy`w (] V/kdGIrW8&RL^Ҿw>W1Lظ6]Ԣ`L*KOkulM患]'T=a=[^c棍O&D!(GA`sKju-R+f 'F_ռ^ P*+xHY=I'G %ֶ QۀTMCP3'QyKXr YSa!Ԯ&b?nv.M3oZ`{#ӴpR:%u=?S=MZ/ir'3%K4%beƊafA6E~,+7)VXL۠Pu{`; vdZH-tc@\z6K*{"oyP~9y;0҆\^S3 ~4s'p~H)r^]@4aq noMIn+dt3&ф#@ )dFҪ>@x'nC+Ĵ~s R) a|<=װ#ScǕbai~+9 P^Έ̍>Ǔזm?2:(@w!A 9Ew4ly]yͬQU/LIGu?D$,~ ϵU1{Ұ" ㍃Jc4= K ?Pٱ6ZI) w=O譛pD؋6O3r*V}5w^ߞwjSMysamY҃Tԟ*WG+d݌-}gf#+'$zgG30u \OǏC}q: s*%ZyP~\K6b͌ݴI羾tb")MQ +ڗn3yVƭaUT)s?شe 5:Xye^hG喸6`ʁhl&f:k I}@Ⱥ<*vOM#@o}DyU;RHfW8Hībh)hiSU=!Z{g3#G}A9Ĵ{974[t+i*Ka4c)k;±^%:&g4u;ݗ27ynWpt|hz4'3kYXX~_ŝS \S$|ˉNベ>߸X@g&&Gz_CVNSFgL6ecV+"ˀ%~@ j"^[A0놊K L$*- a.aNYI(q(頹Bw šE!Ϝ]t'@Gد95ZLN~MRǂa N'@C=.(I*Zxcìr. x^d6.B;\J5 IZE/>Dr>y0ɋ 5^Ty=~Y|HF:u/>x]bYMhO ]A2G#zK-Ia~ \ʩcj P4e,A1Z4a%pΏYԦMmnZV3͆ 7 |HIA#%C4>DV9΋[Ƀ-[x^j"e̕9omVvAP͠۷)$_H FH]ss D92oy0ƞ>y-N@mQh~Xن2EPAa +)6' GɡSL@wV_̐ Vz*"_`$.9r&iɳ r}?<;z*h wH>w1dC JZJ rlA@nm5I|:x@LubٚДJ[Bl>Nv G4UoCF=v1Fk G:ڦ~-CA7λ hB.ְ*j 6pS8o.P:Snk-Ѭ>UwW^2i~';Tecajl6lBԂ}Y r7EsކT|D?\q3j'=pI';YGf-Ϙ-~HM=ܞB؁fEț)Yԑ]b~EBmEI]qG 8+|)GX\-!1:о|IX nCqb>!Y:.,w]whlo#=pKgM&̼$XNv+zէ880V#LZJP#+%2dtmoXE&ui}WF,yu2*DAN9?>)6|gY!Gõh=)-I"WOhVױfmyk^R4 cf8^~C:|h=зjde&%IqiО;)v9%JR1u# E2k` S3V4;쐮&ۊpnBW:tC ~@Y`3s=N0h)ȧiWY92Dz a骸I&&*6u.M'iܜ"#o9v}{L Otd;RH+(HC1Ē_L8AZ0N/֌eI1.ah!Kqe`}8gl2i; q0$KO+lRgM!?yT[O4E+|LNKAJU#]>kFU;9=:_>JǒdКgFŰ%~7 Y85/aS ZRn=+ e}HsN -i7)ZoP XoL,n)lֽ߹/fnd'uĜ> {I@;(Rp!4 m&k;Pq밟:=ܞn2'NSt>*8)If1Zg4VF ѓ^j}}GQ+Jx%`= 7Q!WI١$>>T%3v/5"yS h ?1O)OX4*Md>'E8wVF#g"dVXdkxS0+8nެ#|r舵:uҴv&nS’H(~ `%-+͑ zy 먐g|ڥI}jIMGoX6QM87:UmnuB:}uZ3ҜcF3`e?Ǒj*:/vz"[.|g~2u<&Fbez.u)k.6qHvJ6"WilcynjytwpgR2NifW/pOVZAS4T0 ե@h9~j\[,&eT Q$VT}ۖ)FGbڂꗟ˳Jd4;/kgf1|K&- Iӷ]rbwEoCdžŜ)l&y%a:N1$c .tetͪ u7⊠qF4&~7#O+1u8Ur%♓xе$%hN\nCgj^U''rʱ4{/ߔCWlsnNVZ7}(gfơؙu`yk^#dpِav}=R/r=t̫\ym!s<Mib {(5rKm$g./F:fӑqf!Iլ)柼o,XDԭxd\V^ hTeuOSd#Fa37') d&7AKz>m3Cęmf 'DeơІYHfY(gauXUI4Z,5ASRMoޓآp@~V5(2zb&=!sN> mg yBV[kr_vsݤ7t7^gμ.X82t sin΃,뚯FZtLXInUΔ^DСPO>/JN;έ״ƋGB 2н̾CM\iĚ0a~wˡ`yI'"u>2qEV]u1,̢8RVWFJY qq~R{{&00yAhnܜ733lXii;^)c ;*q %,Mo0ixAb/@=LNq9L|ǨgM oQwS-A 7X caVfLa;]Gf/Iq6*X‹ei Պ˄"#[j@65P(>5Q)"q;4gMoehfh90;tR8:BO_ bYrb3v$wKYt|:v24Z̍qiY# W> -WMS. 0CFIJ c/ryCKңd 0ߣ΍ ~v\'$Δkw:u0 "^86i,GA^ԣ d2>]S6Akc~c'ܟdD*xVԯY9Ɂwn֧r9]ZlB9H~O}Эm,4 ?zI(H{ju8JgEeh*> ) ɺ^4'(kcםsRo0)X 1Yg:jBW<ޡ]W@3& ܢ%]^H/Y_b$M+Aߗx6ӱrcNѱs滣()./r̸hWĄ<)NM/*y2Gǧ3u_I̜3sa̰z͖Fjw$.GvY24AN8õBqG^@?mw8Wƌ.>:-H@F drIvP9N8i'Igk$U[wރuqvt2\stCS Vөޫual6wd#dR2D'J0{?@ٷDhffxj 8y;n`k{Ul9jP%,I1O[ʔ˞@RQɪv03z6QŦ4'׸sUu?]R :6-㄰!kU$w*߇} *!*~3$|#d`g )"}@f>zt䠰> :M/=oD ֎_HFG'#E =?`4P"xFB;B3P` N"ktCoSǧz<*뼃0yKL^sAP_ǹm4p(afkZ@Ηz  G| 8|'g&!G:B*H8p>DOo=<*1fFuGi2|谬2bv t+#%wUBEDjLڱD׃@3BBn莺,dcCI7IB[?zV'@Y3 Lm "&07)҇xFb;rSZSͫYmf@Cя YZ MVdyvu?:yfs H|fpx>%ͻ`؈ B+֜j8Ow1"LH2=.B4evi~1n"^#.!+`$dû==N] a 5PhCpYXsPLhh8ɒdNM A5 75Z5pwgD ktfw᠋/S8\85A3M~X !;Fwqӳeݡ= Li)arw"P2sgp.4&#zG94eOc]I64yoD}UP_ܥw.`n恗ß#ӿ?y8aM*O dT3[ 8LHBypĵ2sH͚~8Odx)~KXaP@6$VlT~;RI)WvJY"YO܁p:5`6 $'{HpƮz`Djqe_3g ?(DVd*w]O0D}3Jú3ZSB\@8eC{a4Z*ɽc:uBFI @Mn²yOZ$/VMc~ lfwfF(!nWIӨɪIU'H 7 n8wpCfmVL۵]Vmbg1_ yGt&?7+80\1dZ H.$H֔c@fEڌCPBkeiBAŷOGo ԎQ\SASLf=6!LrK^z\Fz6Ϲ% Ix^]vRqGum_]fKdfToAk4 ;TAuS'L4H;ka2#IuhR=O1V!b5үVV!p_IA ^}pqlNQa6=~DŽ=)klBX`M4r: Y Xjs?]HMs>?f> πSy4#zOZ4bn;axv7+ 1g,HS@TIlRsVX`>u1^Aq3v44ϿWf5>ڱTCh]m:kW.ЮdCD:s3`Igӿ"f^1:=+i"MU)_bzà9(_)@A򚑌!m7Y(ܹҴ~/"'B!aݘ@4fJl(/ X ]G˛9w| Mݍ.cW,g 4YLwvG:@:'IJzDs$> Υ ˡ Tv☖G`GOHVgR u ;8BR&ϗ=: #1(CӤE_Õ0bB69֦9u0-@P)OԿ~v"θCNxg5q>Ϥw2 9/x<kO5Ϋd8T5P,3uXlRujHeOuDv"%w>C]ȡY}ԦᾖsnM{֊fea9фpm?P^$NԵB9VVE~;+V5ݔ.cbBAaEN5b楣 6d?ё"wUOC6g=6r~s~',+*:sј3h. VO #x\w(tIlXQNIG=A?j2={rYCE<ƊCNlN^mFE~m9pqlg񾓂<%YLyAmḠ, Vkmش0 GaMѴ󁭡ñ ci,˲,LZy.׽ buYmbGl (y_kð c#䇌)UhVv~ Gtzd=frT<#ulp3(ԅ34C=OÁ$:}MVҏjǴݽB k!f\WPxr~wa9`t:ki¬(r~hA<3UܺvF(e*_`yvMY~AYj%] w)yf&7VP>Nq*VG:%!򒆦GN=L]\JF %`Ywn\eIM393cB!cw:uixp2V.0 XTxg|+[γι*C0b}BU*"im&_2whCwKұ"~s#CM5>tCeg8X6QK1 R:\b'?4#ʽs#/V=ʉt󴃞F> 8raEpNdH$)Y45Fũ|yϘӳ 6fmY'vtvVF.yz6*QHE-5^\֣ p]̷ܜca~fQsM+o5Z d=Tt'NfskYT/ndBɳ>O+=d#ɱ)ح}}BDȭg0-+I-ܞm*#s.SdE։3Z 8xZ?-" صT$֋K>]Vk@TCA*V{N}*33J*!@?s(spk@):Ӽ{Jߠ?NjÛK Au:UK^]xmIZ.+=&Vns :c~Os yXM:N"ř[)Nbw03?Roo \`ՓHXi*f/h{:Ґ\{&Wh:B3#`p<78w) u ߷~b{9CY|~qěj~q3"G/A?B)0\qb[G9Jz4ޥo>}CSY*(c.)%Bv5fpWot/Nx <-OTT1ar9]0~ #MDj3(̆m=X0'F Q`"$'N_bY|wnIrzTE!iNuΝ4n#`=VՁ{N1͒(@s |N4VM.c hbдӞ™ɐQ1jT˥&-s%:Gm= 4ݝNl9-a9E&es$g9Ӊ>i!'Ɍ#k‰č MsMs?+d o*=+raz0 &#"b/=ۗk`O։׼ ߓ3vJE3D$:mC23:U6=͍GUZr:E9Y##u 9eh=eXEbo^\~nFc1XOT@ t+s5-,ty )ӑܧsQ3s W^$/'p!? ⻻.Q4 6zMӔs~MPwꗟ/ewZmuq|{Mx9$SY1+ tt`X_P~@xTr~w3YOSX\+'<&.2s~*KUX3dy,Q*vap>쵧hl:ǰNc.n^uß )/Bݵ'a}(($@0;FwVϔp&I w $( Niq.M 6VbFJ O%ӫ^JDHJFU/a/Q׮=um͙t;=Gb3?trng*w#=̚ىSCaW::2~ 4U ! 0-($B$L ՐX-4j!f(.~:< Xk~Bƫ.x@/tȽxifVc1U^ө;4HJso+u[ }&8imdŁ)Y[~eT8o_/Nur<椤v{n467G T(wh@OB`r6) *b DW̲φ5rAce(H^įvwkG}.H<>+qJͰ3b.{jˊ& {w򺵩8b蜃QCd6++<" W }R_`8C4KSÑƿQ>HĘ/[Go#~DMV<^oB(;[t9(FG7TBࠃ.Owbc)3+ դ|Mo<D$^i0q`2@GҰ : 5W*S~|v6 Z-!|EԞUCj7q!sjy;^r4i;' @1b%4d%Ć5>=5sRQ3j]ua'iY M_5^> 7K ẁ\.:hZ$1U6۾ D& k$`}otIEENhKotNuGeϏڱD/<$V-^62*UxFaߠ~JcXe憁%a/ݖ CXDHV9$uS&pTsz."=KP `}`YZ?r'톞m4wn-agͨ.=Nϣ9}sYwl `R_*Nӡs?etȫ~aQ(kYaWhtGo)O"v. }pFӅfY=?`~1d[asv=^V/c|*"NT7A|׉3˸VʔlZ7LY{@ 7=WYun-SwF[= FO{'Mu\'Ip cB{ V )r(Y~L >$t(I'ƾ-jlP yEeG儉dT1w_À7PD7aPU:z;n.WsTat(+<*2Ca<,A-۱ H?!&Vҳ|gSpy$<$jkyq N*}L &$rz`c-'ESlq|izT,|S\eP:|H6uv$'uB?fuYX4ԜMx$I\R^4klr-sp8V!4#@nQI$Q`Maan;k*bUqߧq:!rk@Xm%LV۬iz˫Z9yBT s:)75Ӄkuw*y[S<7Q^qǪh:RIۛ~G3IÜ$ 4:W72ݼEl DRy EJC3]:ibZ;qgxAi%=_H<zkjoY]oFZ? ~j &־,C"&D6fCh=zIZ^\;yqmv %-Qd 8+:y|Yfӊ/l7(|JᬁۜxYe]" uҜVOkK"=mjdC_u#GTs7eοvX8(4 셝_lfxatN% }i;yy`en0xY-^oh@?pz#3"|$b"5r4|v/Čt8[wt7JuT7viof/gY!fexLivKzIY/f˿ @|pg9G -D3M5#!2$7Дmǰ\ݩ#@c]g[i N-\PpM;Cl:vh2qr'ճ iҺRUV~&=R4TFKW4t61#P()HBY~෩z׳ Yrb9`GcYK%;A7&bhE:ȕBۜ_B_LFXMp P?A}fD!gKsS*?@8(;xWްݏ)[}uQڿOZTCwN`H^ѱet3:XH2sC |̏,?.6Q w:W_*4Yi}> B#vMʪ" m:`&wlCaRMzB~hk5JCWlxOtW=ڝ|4ݜ1^ F]%]16ӏ@|o`_qK4;(+y.;=1UC$fF1) Qa)+ }2ki:ʏ-OYQOY~=Gl;s.{LxQtjZjF.O3[3F^R$lˇM\@lu9⓵QwlE0Ǒrkzƥ\-"Lx^I>> 9HaerVa(ofJ<|SoӴi Gn|n-.YuIL.;Ŝq|bb2EL7/.Bc]en};:4$@QF @ \׬) u%}~ ЅnYU~wr^4ì6恄4s6T5Qoj5)|]j8f.pb+37&]<[Jp)tXgvvSe.D s>e7-,ԒO9 ' >X6ru")+\m4XaZÿ?W)D~h)yp$Ϫ`Z)켒sJR+i7H Nc`eCMf\HbfDjn&S"2\t5q[k%Hl;3[YE'>S2'z7*+ۇ9_16rCux칼2>3?7#uL5DN>%rS'ɑSB[TJ=xVqS;6GaR A <גUBBJ:4yYf?V1,~eQC`}ɨ7h@Lu^K鴊 ͳ'2]/Wm5@wD hNP=UVy׼O*TF~mt;h< /Dw\ ArsnU'I XI/'zᓗ]x5a)q+[y$)\*Ζfvf]S4ȩ(~FYn"^Gj !#[̵iGhf֟x7choP E څaT֔hSyTSX=ih"%bÆ"ZCҟp(feuF6=Lx. .DI[A 0/^ mjTOl~Xe9(O{4uP]m:u=OJc>qd 2yP:?$D֔-s)QC$f7lw" ΕH"ɥ)035[xJ0b 'twTQm6:T=CD&38tF4E(^fNjsjpzTodk*(0PʒqB4?pO1ZZ#(8v4XQSndHw<ڤP'y*lgG{%0+b7i,s0HldLU7fNOLP5dp(rh_\Rtw5 ES|t^&w$)`'f6C@Pk5/-qbs y:*s51Fz/92ug6(te t5h=S8,N[wӁ IbUs>5Wp{hC%5 RW{-s8Nh/GKX! Es0eG '|'kC]ʶ;^1~6}GICdƐWjM(߆!iF>#x鲊n~I]s:ZHWi§76\htpB?fYPPH9i=yo1c)b{Hd})MVΤ8l|p~.d}Ƙ)p*s32Q~t 9ۼC–*wڅEY0C4 B $݆?rG#c6^=Y[fM6?ʯqh5W_>9LL*5(:sgyN1Snԣέ!i8}'\hi}A{OȡXQc)G.7zߝ۴d!.nxj&tEP8N"S;:"}GZ3, 3Cz KHA# fq mX1&;^׿Ŏ/&rl0^|u F^eə ͥIs~cU i:H昽 xDZa򙫑mglz{g6ҹ 9ø9M11$004 G10%IC_vr1T i{mnc)g D{{N+݇2MD:'G&U|:ĩ8:|w|.T%H!=RB<8 y_qpBIJ=4Av|A Mb--C $^S)N,rRҹfj_7%l QWc+X b4((2L&MPW / ?lά$:H^2:68S)|}Q^ѓHY|>'kuCuD<HgC~ǹO,7LuvӂNx tdK]TY>mUтWx 歰Y0sx @!b;Eq{rB>\'VH1/OM6(Tr" yw1#)+&uWw&.HZ˽=.18 7x Gt[Z g2oBNfEu'b%Yq~r%B B?G=>tpGvkqr@& eRꍃOgb[Q}8@;k lВ2Δ⒅c߶4q _ҰXAxaB]䝤 Tp>x6ܦl%&{(®[@Ӭ!b -1G:PGz>~k{V}x=q?} 8Qʛ[L~Z}8WJXSLBFQޯGBzx㔄h_{ <2[;U[\np<=7nBᝦ˼΄|. H(C.O&A' 0v_}(H`,їLKdfl**:!̳Rw]nCׇ a?B_y m0+p3 5AΧF xVlI@h:31?HZ9&Zud-6C:kVkSm.Λ0IY6Nx379uܞ:tkP͙p H0H/k(Vx)2}k;6WKeuC/G*ӑ5L U}ѕ]٘YNd$u}$eH R]DE`A,4!)Ptf9Ȭo9+8Ąurxh'S?yxRH+)H}_%6I{8R|S)e.y6+d4<˺7އ]l q-X"Ws1!z̗dsro2MY7DTpZvtKzIys95dͅbsԭr:fwI9yi:xV?$$=e:<ї R9$9A+#`+AXJ,z|Uo~ O䦿uaeJm)<`4 i)L*A[mz,mؼqFPө-/;fEb&hfP -zotҐLI+xjkeI?0bN tVR)TߵA)}nOpn`xr/m1T[|DzBѠ]SyiSzV ESՠi+s˨4IHPb' VԚyjZ!MD8Fz 51jRF/s N7-=]!;9guee"u6'1\[6v'h@"_y(,>yrqHcḟ;s҃33̏*e 9#{Ǫ'epS^QP VNNOK#Cq h~H6fp;&!I봿KJ=k9l20=>`w iUqj \bU4%W J?bVg)vlB߹cYrU2s̏J׎T2^h7E;_c[W VT|q* s%M`)`Z>$TXԠwt]/O7/hiY )i&Kэsv@l#msܖqd8ĮeGX)..4=9Z/+ ?1ubՅGn>=*NsQ6+yݭB_DV8^zҺjB- N|81!dE*mɒ1uϜY¡,V H9ڴV[Ԏ _i}ʓB ސKu$ˬ5#)CŜs~V)L̞ Gᚳis}.;T^TY2Ae_P违qef,_xs^+wYrg(j@F{>VV\~L{ZN 8D ܗZx8eyDڅ))oҥ? M~8 ]#lnK6XQmls@6wͭa$gnߓBZ` rHM8'itE"k9 %L^ $$)ݰkFgo.lH' j7f4i3/@ǯGW1*hz}c"]lhw_!Γ1+/ʢ )#NI@;|!s?&-&K!1J瓈+AVx8jC[,i,^^~$阚%iQhQU˲Ҽ'&Kңtpmh-zv̉kCkl'gχx+)&gb/}ޜ#F̄83D#2aպEK{?6Z|ظ܀({:hamdZTFTf}PBȈp$3#"gb* Qܐy 8w2dSMg1 /xڊJv32)jQ, 7X9&yfig#!}96o/az}9CNlF9\J*+s*lGsznYItjㆸo$8z-PJ*`ą6%IE}n<}9.Krqy+{B2cSK![g#\~hrɹN٬3:/mGeM U㞐}x_>=U6o5]'9;UN%F1r]qWs}c("U:ScQ57)i=vG sw1zm)]}z8SP+fCș}zm5KSaf]k $=H}s=0dEC"\М~TP@:C[w=Ă4F(8|青BgZ篍klYc pרG%9#WqF:#NΈZM;=k݌H 0s޸~ƞ1k6L~hmyT&1ql*3H{U0gL$ߔ䔇y7X< [:~~KY(uŸ)۬ho'}ak1nZIF;iBE@G^;0rstT^yvRp"_:9Ru&"g>gD$VGj_W}Az%uioSq^Fxe6WҢqMȹ?cϘYKBYTe TR+vOƞ#GRֱ;ݲ"ݦ3տ$aBc=%S|3 CVBtxRV`|JPgfpRFy_5Ō?(AiKE$K*|g?"h@Ծ皂|Հcm E^>txGT͹^`t͖evOgh!YNr& "]#s wR''&搐McI2<' 9<>PbZDH|"+ls'e7f 1OcЇ0X!YHk똕듎h]^KW]*+§kFF(<'*(5ː~9| ^͙3U^$*/kӪ9w4Y/c0MN׈YiD }BΦx jP엁!!=sYo {~v fi 4{th0M.d-|(ܨ_g/.c{$Ɇ_~5wML ɐ7D׳/ID 2BG/ڧo.}[>XWWԸwvARmVQ{1xiq=g`aۺd}C@<᣾k&4Y~?:j.K ˽Aږkv7;[c6w&iYq,6mMZ:π$NԊ1o'輓f}g3]1eCͽ$G@c`;)a\]}`NVΕkǖ$NlPdؑ{w l_Ȝ`igGOzI  ^ ĝp<XR)'o/;nN *apq.MPvfSk&|LKc ]\<`/߃@{ Jt+cXIjKGAZJkft/OL9LIG"){Шb9?|Ht ??')(+)Z:-\sy8o.j zrzUl9h֯3A z\5nGnHݳy:@O3,d:i{3f}#֥Wñ ~wr_eԘ|`Xi<8SHD\2^ޒ`4߸\=* {Zn9qe^S֫mkjkEpiaG cMȍf8A/Tr_ºE:..Ln"BxJ7^fA&sr[z=I~C5!C}C}< |Yx 7>N:%ntwHL6bSa/◖Fq)ҥ`[XƧR KKh FwoӥY~stn[ B~o25g 9L|Y}(I-l[hiYq@Dg?@Zڤ\u&>yFNI[IoMBGǬgb۠M $\ :|nB/~ @3ɷxF]=|=g4rJ~d2?۟j~M@]h@5WJO==%wC}[ tA TrW*Nx2_3%:*詺-q>::XItNkxYV5N=)!Ӝ*%G>!IIE&}%>O)A ygxi\HKxf./g>eG廃&2 qǟ3nz9:]-WytHy8m&J,v|^Zr}Y:S(x(&ygu.F* ryӤ^ۄ|yw;Eݹm WEScR(-Aolrh nsv6GQRCJk0ZYiN +$J=tVz11nz+xQS֛.oz; `uG Zљu!t[$O.ɿYap>Cje DVQ$;6N|u撚Lty:;1,#cMq!cR&]!cs^Pu(2ϸI &gN>K͉6k= L8r/=N@&8եm 3')wb;b°KaviT}s2jj@?58X|zir,xSD7O*롥񐭇&)ONx$v.G!kkwGON$}:aI<fOeSD6͚ҍ4.9Dh*{IVRi?S{c#hqAq6$raE21z;?=xc? z. i$ hmD^[9pIUpSЧg$h z0H !S8k`姪 5~3s~s!Ԉ6}dHRS?n76rhؤz7,S!Q,|qں^'z%A5.Y%^"޴W$0:tғCge 1:cYlrзA6y:QʹI=ĵ&r~x/7i+?8#r gj#MmJo bx2B>BfǾ ֿb  ۘs їʋFiipAs#['HVn y6/h~Y7):w&JS}XDO:6[x:iynF)XpʷuQ ΐi䦭'Dmr{rQҹhA^TfbaёkubiBcrHNe(ֈN$L+ ܾʚdWi(}ʁ%R5 e} n̚rn'Eu;]W{v9+o.pdoX̦NRbC",4na3pNᗣno6~p&xO4cّfyA1} ea&όwh$m@ne%4 92BR5'̵&]Hڨ/Qx{N!Y'rrj<^n5Y'SגX*=KVNۥ|?}O2XzEw1)ږD"r #NԲb$, b<-k.ਲ਼`ze7 :$7讲i.ACa]Lx0Ѕ-_G|C\7(VЍ萓 4zDoú̱E_YAS6cWѫ\Uz"BtAWu6K xkkT3厮H s:G݇G} #!#d[QZE 5)#Z:zd9; |2 MdYo@+"Y6XAPaUý|2fF%#aLeasEE0R d<,rO=eN~d5r%Fm>|)^uqHúi @`\"5Kw$]d3fNK_:͉紷b<ӛP^{@w”%y G u1Uq+'vG8S,Q}ڵVgB>s*z仧"JM+Oh\wŦv 7) ~8_1SǑy"rp|mI#LNF䳃{گR8/`OH7iA%ʙ҆s`6S(:azկrϐ}*[L( f,C~5+US5I/w{_[V9ؤ^0jv3ድ^5} KZ(fơ۰ml%-n-.YA&RGTQS99)Q_sI k*0TCux}:1X: NdFbn)F7f]<r2X!SKjowO8·SX\B\7q$t/]е雐 O!Hf>< LOGCV{ VxCb|Hئ]J7^}lC떾]g> mO7(NQ^عZہD~gگRdop7kt{\)g^}s="_XLE$:lt#{2exT(u>sٛD`PM h`UH>DO|A?f i|Ԍ{vn[LdK٪_gASV Զv s;cT8M }A X4u ։.%l^:P1b>֗OH7KM3ffX jyNe@Am@YdFs&,<yi9eƁsp޼BٿP\zn/14LnRR1<ܑ;k6OLL:Q-FM(k*zYt0G+KnèkpY 8O"8I2ao_|(xJ5؝4=23Աibu}q=vvxlJO(t q)r5V5QX(t8̔qb=e?o-Vɣ9-ygM:OP'!c}J $lĦC k6-̸.#afCSo.fϺ̨~BV'7 oٍ"9Cg@Y 'Tqm#SЎ3)gs6`iDFh_9fL.쟍CڡGt cVŒ)hsHJ<~8n5&<U`=nlo !{F&jy8{y4 gsM. 2 &g-B)uʛR8C ;e%(7k`-J@| A,CB3SjgD^VؼkΦ LvXQwO6W5/k{Un*|8G}3 kTD馷]c]_y;n^)/4:+bsj98R^&BO,nffr:5i;P2=lYZ`5dHԜJ8zx"m#qҐp~gc4*meCLsj 'i3+ܳ65l2.'#cO>GV!?#= $Km`ۄl1DoM4NpDiU E@jMiīip]LC}SS6Y#6|)ח}Z{EZ!Y!\Ύ&$ <99!7{ﲳ#h+Y9s2%՟ `Ј-k^@njh o8MdoK s^zvI(k5&|xC2l(0}=X%AWdY9q^${_),Y5! Cy1P2et_opfn JǪ.%W*!,t~rcYɧ_*+T`,^Stxl[|P4{Fs,wq(dlPoNk݅3%ޥ D9o_'!IH[3-7e9|~e-֨)aSyb=waV {J" -/\>\gČinnǎ*KX5/vs:ؔe6ͿX7 Yh7B/˹Kx$TYiSocP;nJ J `fpEG̬N4!v C t|L9GcmzJ[ߟwߔ)'܎)۪~yHjWYK,` $h";TӹLh8_1$IdAe%oֻa ֏~9՛iG pWǔ0\iq]㤩`B(*su#*7T)':3DEeޣ2DuN}?YYh)(V ݕ*Cg4ɐ 8Ey^-%kZb9H8k\68ptpknz\KuVŘ $]+Pz.Nu}dSd:.;Ǐ& ^9_sU#sFnZ6J*/b/z<1jsb嫼\<':b}\/3eWm43g+U[-*=\ "Zn*I0TO.ۥ  >quS{x7{ܜk.3:]04Wahx#)OkZ+sy7gr@"v}YI^\~ѱuCE)鱧,N-2#T3/Hq4unXSbYIMbp-ȑZuW ߴN7D7!S%doc$sn: v}- l`=wQӡ'&Nf)N,ukMbDZS -Ar$[p: 1}%Ä{st5'c7Z/ɴ5iI&SR^NR;N74ث@Rۭlc>jsJBu`t'^ x 1KZDOYJYrTT]1/x4YѸP+ޞP 8A369^H^N8Q,8hry.=]X'}1̽EjJ:Hq}u3?ڵHJ;U AhNCC`r6wWkwZu[#8 5ʝC29<ƒ*c{7S6 w[>dH?hC=ig n*ɸ{S42g*2M.LqA!pdغv{u>\9 %IGGy"c+}ʆ (3~_ەSV;{:z0 sn_`pTr(;1uZ׉M:R}p XNjN$+'M!GQh;[ ,Gt;3f|9ơ~Q!_US9C?4VOF28zȁ82w{!IZ : oa%HsA Y%jӍ3SsNj1R`"c]*[7>X% 3%3H 4[K.rxw,&>ڔmִ§^AL>؝(M4_+>x\ 0X[ͬO~\uԕo͞O \@1~IaJ9]ep|=ժ=!<[Kz /_\ q"| xX>@JcCye Y}pjΖns^Od͏M M n $Ju|Lm3e*+G?$B 1 (dh82(zC z\yVp&Tp@NYv+SS>X8nBshz8 w5W`hcs`?ژ(-kB!og?%POz.6& )}PܲlKiUbDкFz[lE̼%#:'xZ>;+ C~>[UwH z%K>LYs;w9~ר6e)~xV-[#ž+d*3e:1 x*x=T*dKo?nM#Ocڊ*G^͐ +6[Ϋ$spuB;(XRzݦI)@!lΈ?<6X<*L,gnlgq *!Id ^vM6l{_!w:봹(gsAHyA/wvu_.~ZGZ%33!_tBS` j{6kR%V1=7' MY],ZK lr5 ksiLT2̃1&l|wv95NTv;#s/Y(/2=8"LH?L}Kh>:m'`.儖 Up- 1^7 qtٚɠ8Oh46D> ݏBqX{6Nr@'v.YҾ 3(VD+2w+b)*Z4!ҌC==N&/"oGqnm.2&Iy5wΔt^:sŹq:Өh@'"2dW?tY6O /$_"3)\(-MR2CZQ4JBR+tCO[޳Rl*ӱXgګX䎮St>ӈfU8Z>BT)k[2_E6+Po9+S! /gAg~,{V`qH>e޹z;WGZq{f*0H֪䅳ovGSWDmVX:&ݠ)‚#SV(2˩Hi}9-Vyu>rw?E*n8zf+VExHЋ?|ҍ#A@v*WVxoƐ5h֯IXƋW'f =F y5SyBlZoih]f=EoC!>J84\B qH})v7ּIVȟ4ci;ޝbmgϽXapl; OZbälu.sɪ\L~x5C9NDJ B7C 8UI2"q Q$H?*/)3gJdF0' 9C{lkm-nV4ryaպJŠzChGQp`*h%-/$$;!I2JF #QwJ)|3S:1,s븹իxB>{yait#0,:ƙ"oH݇b/zNP`ؖ~֣XO2._O*gaEK&Bl} ։5h|G4TV 0u00E雎;+ȭ.5 : s>1awѵ% =Rk)pTi2_?`u92w70@=[|1`- #yL DɖǹIX]FX Z? neFmĜo0|hO; Vsז+6o͊lL>jp !#YPe"״'r#0c!}`%dؐ4s'$uWE$. d ZZ = o*Iў7/<-830#mo\n;+eyV]փ:#M>ǾΚrǼ3{=7+s35Дn#A|(yH1&}g`('Q^?!iC6I{7Z$n32Y1ɰHȰK6V5]OHvbOUYS'b>RYvcwfeCrQbÖE|{B*ҋO*7Ex=^› t)PM?}JSc$Ĝ;^殆%ƛ3X/fr?nP,#x 8 ~*4Ay9_0H )0^D)g\2 83(]Y%IAYh7oμNϏys #żR"!oТHe7MGR"dA*M3y*SΐA7Pp*Vc QE.8=;kƆ125MzᣉL)E8oR2͇/WI3sB~<Ղut6b3Ak1|3C}9Cpl%DPM˚|4 aJr;}sP6(v.!5B‹d@qII=+2~?&#txفztޡ~x?;ZG}Q:Ipy Ik{pyHܱ,8QtĐs96HKQ<_? g)1\[cΊjc7))5,r@T׈t#笰ɁRx_ʷs! b>+5oV6KShEAԐN5^J/ ݌[w/ Dn 4ׯ cT cD`ې)5aӁyrKQQ cWpw֥>#U^̑PtڬyVFB4'?x;"$ D8@eflUN e5D3NIK]Mνjrw9 4~ޕhzdG@$ ϨӶS[VVrcY95gn\sX3Ԋ歠R_ _X f JzC'pL')a͑oTD:d㐬 6˼1ft+@Dx2*YzQ`N&)4,-`UugXr&"e]Й`5Ԉ-- e/dt3`Fŭ3eg8)A8!өXK"+5:=| XnSO 7H.B@:L~1#nSS?w%}1| s>;9& Quߕa5" =ȳ;{9c~3}auZNC Z?w%օ)G)I 8b\5u=w,D8(,2WgqEc[e*+ǭk{q>tè*{]ULɁi@.,+f-~m@Vy>+7c:3;Pup 6&^Vf,FyC3iAnp\ۤDO6gUuqNuPY.v^յQm>eui3B @WWަj2|c%3{b` Y]d?H^3/I4ϧOs#OfbMMM\FMw2(u.-u*,v?o+S8owKձU`u 24" }uZ^*x,.L, 8LBMꦚf gG_ZV 2EP[Ie4$)5Qp4UzpvCҳ4fZ_ć p;TYR;ULx_|0}_0?.vz1΃8$c";SCFb%eTXRt]/zrٖ>/\cISߒ5eכ7, )@@jU-VUXCR }y1+0  KS lͼ ظ25Pn Hfbugtn 9iMpbc)s뱶t\6eL.9o:&j1쇷 ڗaRT$  n"gMsC%D"*SQubf:MJ@f}V:)kMCʛ-[!zGl2d,E[j~9ߜ8N y(MTɑ\Jc;g/ê;%~:̐дs9٩ -/6kFZʸah jޡ˄/GpH!v?դnj,4 4/IFk޳l'g];'l]s&\F˕bVWV^ M<&b-d6Uyoq-5|hH #gb:y!Ýϓu4!߬,#PiiiFH} @P^"| jҩ}ՠI$/zCx# ؔ BZ4?X߾*CkH7zM}xyJ> õ9r_Δ#d^#a [`9L֬H%dRc܋s/& qWsO#c728+p˕3th#ԙs})vL:(A{L XC o"GZuf˭[QO >=ECrF.3 XNt2JqBɣHA*nn-š^Ra>Zv5vnn@J1,@;'Ҏ+҆0A*.v߅F"׏=9JϪMGEsgGI:,_ɪI 1 WqEmjx"C|w IWn*Wt{-A+k@k깇`z'=]7:M$9E$`%9#ϐHߡ1s3wlMmZǂY/Ԉ.M83)>;FxW9#F\EsmyaW 1 ZZmU۩me#Fa17r(};hk/:)0񊖼O~s#le?:kޮCIUKQMSSp9d(kI7;)s^D;)J,ƁjB=^%XKFujү{ft=PΑY);Ӟ$gr>DشZ b 6,^@6k, ^foxˌcnޠ/=F56ǣ{\ \>J6 YQ#V*JdUܣ X+]gLO{))/i| kZ7Zh؝3?D'į=cE(VoJNMwxv@`xKfA pHc2!71LD҉YW_xCw?U6 ǃiG6YPfb{-]fi؟r9SL|vշn9=,>}@bJVLYc o-%(qda1gI`|qY2> :cPH Hռ҄JBPDWQey8S(vڹb+GW2[kiYnBt4| A^3͎6?RcnK1Rd{mKebJ@g>Moݐ15HFuy9LL~H;m㏳eM''!zz5k: .j ̯.Mf3-P r*%ub^Tqk=x<%/:wW1Assa*{2I5Kth#k|F% X&A9bA"ZbsMD&e,N\s}@ -w*/<~c:%jw.`1\}x@9u+Է:|*xbؼ> g {_.(;FY2j0g*gAZG'@٪9gcK{Z$@^Q}*{^fzGgjL'klZR3R-Go z]HޛG=[ǃU̬-K S@,oh@әYCyuބ$'dE`D'|:T&\OٯUl#Av}>_( Wh>1ۄ& s~]u~thM/c%%foχUvޮe'o;>фSD [X+=9jRA ̎ l:PZVc]/C9rFOC (/6`ѤCZ?E/ƊfZKWIc`8񯙹':NwiEGX>{OPWL5u0Y" /L}*k^oizř/ {i†zs2|2^kRTzw˂)[RLjA(r>8g k+#)yԎU7ouU 1FVUP2QkA5\kYY!s$UڑG_5;|C)/xCL3~&YPu_eC9c6c鷅I" Z(?^0gGj8qEū6+;WՈoܴHߘǬY6owh^رdi278awfѐd3; q$%M4͋Qɢ9_8]4Jqz])O#`UX[vڥh5'*;ÈPn< 5cWCh`zנ$Dq!CRJX~&֮F$y0H:ܤMbKp%9hd Y~Dc9vGъ2ϡ>蚦SoVˑh!&:xYBiw+zVOΑ^u~K2sT}QyS/ łٳjݦ *fIą5;3^xlϰ w~'J/e-3}Xn.+y/dXU?7A+922/^iUhy:>6d ^GV% nU  GqAU2KUI)dyNzߓkMԡm}ЛZ z{黣kiB# x(xci0]y `uԛ=="Tͻ / 'y%k g?tjB%zQ] sNm)cZЮ}mC WZH!WBwI`%WCgvs?,Q$Y'N]ɗ_/l8Ohz>qov m.o(Y˹Ψn3ыo-Zp< H)AiDZPq)S: S'.  ly.:u`^p4gG}yINlxh ̟xSmXzџ )9vX[aGJ ?yqcnzR'KA9*KL7MA BmkJcz?—rs/ЌOݕJ w,fۑ ǛTO1yɊ%1/Y!&Ig_B2=Y m-%x\b cF酇띶iϺi,+9O}u?ȡUW0tN͚!gW_U9&2ynb-e(;;fȗLbNud7϶CmଉK:U@/ųrsMI}.'6ڰMdz @IO_N=dE)qVNkȃ8^'O.9Sv==; ץ/YCi A 2s;[ZhxL=tQ>ʼ髝 i`EԀ{y393YUM&(Im J3EV#(kD;cջv9bgf;_Une?}lIc9#7Y3dFmLj 9ف2-Un,=#G &:pcoW]NY}ᙜ@k<ߨ%9f5,y78_O"sH #0Zoߞ@X6BSȀ/ne+/ӆ($Ul$ nU$D٣@U*ʎ(mp.f>!q,fg9^12QA秗}i*C)HkDЪn "B:VPM+b33v2YLw,D`a4;f.݉.*OLj'^gU$^y'`3mȣ aPB)1,-2T\Вܐܴz4dJV;ED yJ}i os'c_{J+1z-]Q+KZVw7.L_d{Q%ii:,FZh5|͊3GXQ^ȟ$-.V殫6:ub)-,c}c8ָpY_w~y=GXa#rd-XAn?liЅ%3_}_]]~ǟPC$h>Uܘ t/7D1-JLW`Tmz"5’0th2K4ϧKD5ʵzIω,=瀯XU rOjv}Fz\q2tb/S `bkewӛ?a/Vc%)E!/J:}hc<n1 6؝"#H]Tr!-,,% խR ƅiPکOD;`WH6Ĺ +>O"Ȏh~䲢 ˈe>rA( $0k\y. i%ܞ̿2?kx>B0לL{ԴťAЙtwlYf#ؖ|&z첍+ >ǔ!05 XS*;V,;@x' /KDLD17VtçOf[y;׿^9nl6Jֿ̨e.FPSaxygu@6vk7sD-μD[4([O,y>[ڬߌEC[KؖldVqb99sP[o;YQU&Թ$jj5E x?$+u.#kD ps[eٵU%u*xߊi1!t~@~N)R)PɤsKh:V3 kp%+>`1TvsݜwpnTk֬\_y^D瑱l jnhL{ gbKɛŬ$X^sfy+D]5}J.W͖^N}0F|³Ig0_cKa+p3J'd. p+UYZ4* B?F}S|ϼ/71ƼD*8iG-kRu7}h/1Da'|h4k[KVd?Aޡ.xcf&y}bTGGyܬ>雿 ꘤p<ЯH#s"N7 KȊNq없b?wBԙY:wJKk,uCdh.b^)Cz!saTa] 1F} o+(6ܙo'k@2%[5kp ,)] SO'2aV6:*y*~g"NDʓqI̅\xrAUgFO+xVy JXYF«"#Olg݄SJe6CiO0섻7W30#b[QG2ZNAmA}><`լEP4꼩і#y~)R)ʾ\3w"IXz}DKd[׀}|]>둔%׻F Er/&m^oS>K:+_ITl^k(]Xk.|_\u21?q.ĕaj(%X87(C9\hZfёOP=#Dxi,Y = }%C$x@&OC5P麟ᱴ}AymTB΅&s˦8=U!?EӇ{n3q^p4ӉxXWq8oPƿVv6nɓyqܑ?ّpoR<*`l5S[B׿#,YpYP rdwyeŠɁvl^btd14D':I9qz'PϲD7!d 1\ae|ב2*@MM-L?AJ) sUƨ~7ƁbF9KFr~kfeyl.z_0Y NʑOtv/#kC@BޝX zp;+0k^咛q_1ꗬ7ǔ$%[R-84G>]6E8kbQ*3)!.C\X})^?49p7У˜Ml«Xs3A-j0iI'9iMזF$P 8zuخk/C$g4Z. ~yzd7hdžZn_W'I/|7ٴW.}vβWĶ W7yB9#hdz"-oɶ"5,N.~L3.Ykʨhrw3J8A27*9!B<|bYjӣ$8}ɴtc e-sTylg;P@(b*c`:R 'HGĢ5Au1B3}΄Ob!`usDsLټD꙲I 'J(Nx~s.im)8A:N$̷GH35/ҏ>'kcճs[sN ~$|y'u:'{Tje#=OL+A5ѕ6ўC`PN}|!!z儵'4{SsS'payt:y=ݬsHJNZwzag Ia*!V2I]vL>T=rmh)³q#lG׉slFi>9I/'Vٖ6fORUgRpf;"tٍ':&>%}zX7&yzue <e?*ߤwlg&LlgH*.:c6$M2᪲/`RVRfMIcJd33"ӷ6oe:^%qP<Ƭ5P;fMLr3k=o5i0DY(ĕ9N&NN?8\ZfZrU [qMy2&7;乐dDҍN$A,c#Kyi!~. %NċoK i7jhI+u`%H H/tC4&yE$]h! D$t~mlJӰ7(,t^bk( Q~Q_J?;hY'LV8N{Fe|>ofqFQH 򽾘2MPV0ZO:.7Y9*!9!^' ~pކu=a%,TlLGq$AbiQߜTIY^HD~^޹ڔt1Alݥ}lS~5kPfމ&#r=*++.ӣpt[kAx7}@#ccJZIsʚ*H |LʏT>LE|2“u|=e߷Xg(O3/|YGE_Wa'6ܰ9O9p"0D񈼋F=wKY͢Qz/ŰgPKF<͉uJ`!/^ޜͣ/[U9ole}_0,$-H3[ŷE9uӠ&;ch2oQ;9q:I z.aS[Fy|6kŊGJ216pnViL/rٹ-;4=tEO–&b ׬Vt.eu5ajJ6[8<`YCXΘ")Zje{%J_=M;u/X (K3p3w^PA̠(a>$T =cdw(z, VA<ьVqK 6Ll,ODPIČ1ĭOFGs.GsGsG{fmt&!'{T›.2Hvv3b"P Bc/P{jgm\J2ZIewީG&97t«cJ@Gܑ6qS&G_ ɜפn3^[r>\#qoh+g/r6yE}|e1wmIrIe7ww a_: TfjqY^tlmJbv j\<&";Mg"qH5]Rke2DIOYIv<'^?pO4)Obuy &È{5\ XXb Na yf%&t WOYX᙮_uxIцpɓc}`3:b ZM?ufAtrIkH6ZSڴ%THIq&!JήszߦIp.3TUg2R`mPtn}.T5n>^|KeJR DP]`:͆g@yJ뉅%w} cm_xd6tɛcVI9&;+e)Fs?=<)9+A~^ r8U02e-.r1rΜ{,~jcakdf(af0g2? +P8PpfPu-nW0 >7Nſe|p~rf7Z?PQitor{>9lh ^ /xeŖeg9emUbV:dL02ws4y{4\$seSY]DϚ ;ؿ<{psVfF?ؘmņWv f mCb(T7fœl'$ou߲sr4h oEw^>[o?1i=2q>hYM bY>`/$ɑ-NަNQ 㹧K_SX1yK aWhta j>S$/T!5dhPC/ÄԆWSs@ na}ئ˂5aA+}")/_d ы-\^D 5cK9KgRSj\O6X3>@߼o !+e#Tٶ#KXlu$ ʐ}8p\6ũs'μ9+ ƕYaպH2eH:$-\!wt(,l2Z?VMRv ~`iVAR|1m+/Оasab%I[S=Ujm} Am1bi65DXjmӧ<{``IZR>?k}@%cv"'(H:>JKu lbԱ gzv/'õx 3Q msE}|R ĹNgkiRo7LtT6Vʻ|A=9F{t!S .C2tSΤO# _t܃챹tMhNR:ƀZ#Y>! /V?YXDv!Cp' ^4(6XI2q4`f%[_Kk-|xPF&kM__0Zh(rŇBI~);g|ZU1m7^&d+:ߨټC|:GzwEHУᴉŹ PPlo}A C95ׁuWI4:>ܬ6m1ii%K8nùMoTSJyk5.gl0O6Y)dG(f3[_Y sCuз7X{lDvW~{(/voTw:\}*]jtl)e WU GGv|oV#%i3s , Ry{kI{0&HzeT|@ˣɀRXC{Z+?I5:1 k2Aޜ5a!c urpqM;V&[SJǣf[ݲWll΁.&uTk<e`o XQDdz^<14IfwJ#$yߣ=ɑtE[8]ੑ> &<'B~׸K;dlwoWĴkޯuxaO xՌن4i#a?btH =D߬eT9Ǔt1?_f(3jĹ=Hosdغz s;Ó7I#Ey_We uE|uR :7@8,P0̵avVs7&L9$|19F|r [[|^ȃpjc-kB ?"vH.t]I b&n<5y+w8o exLG>qLTJt so՞@902;;)/vEY)бʐ`t ~;%tUB63N"<8efx XE $$-7rh}numgWgЌm&ϐu~F\/ \SV;1$MtD5={YO;C;_/=+f/4ތx1p9*'5ZS`KbD \8e=l^t9#'(WHbx߷^Hydk[#;5'y eo;6 ^JM.FciHvv9NU(]%Q(4L:uۇ֖&6hJ(7@Y9pY\;貓ϹGyKCOG|sfIӖeޠ$o/ϜT²W}DIP>1bBh0lEL:jhԫpF` 9֒=1w&` DAIdXΗ<&0eU:`I~ѯm,੻EZrߩhraHMki jkpGk /dTa*xu/i6A%ݑ=r\DӿPYĴh|tȹJn9.(:u,ZHAk{,ʭcjmu ߏ܄4Pc|xTាM黧P>g?gO& KYj `|+@m\Q۹@B3/oh8S& v^ts6g|ڨ(g!)r!!5(mMt,dl,H{h]@C}W!B 8^T K$ I<֗ L"j T([_cy9]|r"90 lcvp]|%(-2K3 C0 Ù}_AwM`Fו}L~Y}2|v-_b:%(鼎FuvTGfp 'js${kVĺid*Iҭ-E{ gpnhyYYb6[VuΉap-:).s2(f3#VRPOxG$L6vݫG(]<3$Ǵ%Ђn-|Zl~$Sa=S{<cu ?Pgv]3|jtwn^8: |8g:7IbsoEj.={_b3t:S`isu+R)% h 7H]6F|>v-d[,Vu#Q|F9呱IQCuy„,Xݼ'leC#VNS V4{2AS" HGærhַPkecf5lnIУ23W2Xy:3 -p1gzj{B|-v Dp~bc*଼3DOu `ڶxBX=o.2u5 k\&a 82;O|]7^%=v^$-j6ĤCX 7gMVvtKylK*sfE>R`g0ˍK5Ifˎ:9LmkE&+#6Fe-m6HٰcrxBMk^ l|3@ɺs*R^>;ب4/]~Va'B DMW"lHrw^'8,%V[d?D^-`_͂'JtB~zd&Ři-,MX"-A;|wu:7ǯ. oHU-xWŨ7d1Xa5b662ž <0>҄R#fN _ A :4Ta[ h<leb,SN>e,v+c J5LgnBo霬fftK/<|C}u]&YPz:| Q.EGy 'TZgS|xkIbC kG orޠFjC7Gv{`M;~c?_C07w|OG8dmO5lvW&̽i+S6;yt뷳4G`Iy^+kƞҌreq9$RadCmSiNiGc`7q"J䋑SSBǡÕz@IˏG+8}ɖVxBi])H9&gut,rK sx-O7(lLVfN&͚yE)ҙNi}7ו|5'괔_n}yx94mgB {음 ¹θq_hΫlՏ׳7D~!<ԇ}8Xu"zf_p$G—fzGT_*t5=~I=^6E(^d}~w[{=,.vtEe6fJi7gɊY}K*b'rO6M<}(#M^#Iai3$nVjCf,DrY-3O&}(mkF$g&òr%ND83XJP̎|g~DycngH i;pڼW+}& o;PS3d~z?&uwPCGTҡʶˈ晑] J@שg5ZacCjZUA a .ir )}u)cݦd9 6!o!.3֮Ii;nb|s"Ova_جC* :t>f& X!ʹ繩ôGb% IgS4-zAα S eNCخz0-h;.W)6?вL^O&cINͶǪ|Z3.^]}\;V$ђ.A;ʋQMu)9SyeOlG3p4+fOs5Wtȷב-f)tY' K+X ; fYZ$➒$en! 7*L=j@5VBi:ܲhϨøei3IGKve${?ÒUBI/H$ ˄PeCOG&/vV)BP#@mCf|C"lT-wKxK+Jlͻ:0qYoa_ʊ!YwS }+Vi]aSb)+Vfm/J栽ΙmlDCޒIHGN {g $Tb%J mk*]3үt;'>f\D fMVV%tme[CjԲXˡCh PLҸ`׌<SNI=~s1"-eOI5yƊvxz^?v kڡuh .1߄=;uʛowx f+_tD&?u.+8+iVĚcYiC0WyyT֋cX AM6܀%G"m11Iɢ =bȪNIkUh0lKʥFKt*VazN3= VÞ =Œ3f(yBu\pݖQy>e<%??,wW~?}6T_=ní;(Q->ǻָxϐO͑ISiR=EU|8E4rOLs0T_{|@=[ @.|y9Z,#(NckޞJ54N4`e9 , M׼D.SֆPų5KܓozIZ_)g "yG5Vz%k065ĞtCcNLmReDD;Ԫ3PVW{<) H 7Z˚/PhQ6a=aLOH`jt$"f"gYUmCӖfFHPO e#tsU;qDŵG: Fi< GG 1<2.5T}̳5C8G5(4aCZStʳ5Uv=N"\u,KRwq40\}zPR^ FzG7mo_! ZB6ܲLz:ll/-KkZ'w21R'l'xlGX~q"+~Tq"IOPA> $H󆘍OT4,AybD0XrP4 {} |Y* (7s.D>3e0󼚸FX_M,?;AC3\Pt 4+a<6gy+um͗KfHaNj`:Ӱ>GI"IgsY?A7pDn}mW|TRR2PhտO9k)HcZK2A3'$nxЗII2Z~Aǃn4W619瓕o96\6wfH~}}Sr{:븸QAjGa%9XGFH^60'}C]s1vX6\E,=x7L =Z0%y}T/yrA}ջz3vK'I JT2yO|4MS&Z5+O3r^X_ϻ0E\n'j^tfvt u8\*5K#f( :GŬ.6 d9ˇ n/;Is9 Jpa䞃d~3G ,Ys:.SӋ E'&csԔ+Xs;cvX%\N] hN &8RNu6dĬ荾ǕpP8/V_9gm  G껱{YM?/x\jYʪc,Zύ3سo[s~UO/LsO+*+Vh<,<^F^AG,qXI +&1\ l$1ɪ4=4\ÅY_TBw%!AblwVf?"XoxYhBO Y\)n293a%uZErw 夒V_Z˫emwUA%^_x2V4V!uчcY]LbQFm4q&GAv)=>mYKˀ6έ'zov!BuZha:Lrw6<C(M@PaC< -iSjLaP̓*GyYLDWrzk3P.\~p;0Sc=uF`xN͙-pOY$siR5P\iU𰭂f n';z>-D܄ Q=^;Ƭ,^"#{d3Yb"/ D"h_9O};&*ԳbC9Y6J7JXx'v2 s힏XǪh6 @B"2V.UB::U|׻efŲ"%:Y2|V'4gJ_ItCKgsVx)rWǤHOuz9c,,H"'8-*AV W7VwC{G0Pi.g"c̗[dW&y TwTo/IJN 1Ut㆞`C7W?vItx9aEksE~02D]mDVΗHiz½Ƃ0_14^7Rv꛰0VӮKɧ`R##Sf@B1*Yܓgq4-1o]ƕ0+'>AEc[Bkx+}PEύ6w+v:?KpےXZ0Dl|f|T HA;G -:r5O J{{Цq6JSӶ;ok]s^$'΀'ԓӮg_4)*zM:]l:1+- #~獼K6UFP@LRut}`Oi}if%˽g[3aM7g0ZqׇUyV#}l4xp, C*Gz*|h@%?̃ LphCd?[4+G!*dΜݟ"̚.2>0}}B>2G ')4<m(A5󃻐)䢃h%(\ .DΉYWŮ.kb|JJ $8`1zu&B_ y\˚ƚYYWol+ȓ/]Tu*xjgH^/xJMeVЙZ/g,A YwFQ-D^.Kjm$83tyAGR#%l?ӁLN9̇ E_S#sA>PKcuĊmk!I{9A7fIoʲjp(+~?[ki'4.Sޢ`e"J5p~&R{a׉xU5I/Hb !UV8yP/4/=}5MUD[\)藞m]r8]Ԛ(]Cm *=JiвDotL]0`󍙱qcLkFޒJuB?7\/ΊR,nQWN܉hL >1O πרݼ\XQ̊2CcY'ǡ>f: +FKGO)dNGSX)Љm$=9܊nخ'dɲ~xH.7hkg%%#ygQې;+Sײ41,yRN98l;{ @#bIiIiDE@0o|:9X;I|Cx&CcYiYY;mc8{3AZR$I]35US NS`)8ՔuQp¢ց5AAL 9I`$ k2,]ff| $* DN q}%?pV@,fִ"Y'J_JHA5DzۥhuEf?x:RluYKK9b,sB1ek]kˌZ2%}'!롇QI`+TZwRF ZIH#ij3?>w)-scC=SبR]Ȯ]u.-h)Jmt]%4$XCOY`'b ::@3vaxZumCs k~PY[VԘ27o()L%91v;^;IM(Z# U&rnh6wI Z5՚&+B鋘q.G$e?U8+fW+aO(#RdY{.!)a?å3eg5}Z!vI_s9<ǹݭBoPؒxfmisHY Hw{X, %\$ɭts5Vp` +dS&/&w(> 5#\rwH:5R7;% =D^y볢^){B\Q$uLʑDIoS<%Y?% T%c}M_/I9 f1 eR[tcz*U 939<g]nv6 :wԉB'y3_(y:/Ǡ>k9׆5&eYSn]s>94j$gx@O)J z}vC@ٖQؓѵP]lpdQAk i vM1?QhVkA1^|9a:+7Ӊ*Az!:5~'e6yް(?83xmG{\(-Np鴢Li'9*w[ 9Ӟ3ͺ * n"XKMYSSI9Hߞ^˼8lJy, "MOl,B?f"jӟ6uEIKiuy`~ʞ;IyFdCCt6y6&th/ָU3ل]I*~j %廻 =x- n `upøv'JkGʊxǷ(~N8Ƥp 9 0g6Yu& ]qa@S`$:1n)w}[XpMOog[eGI&'pBݸ8tfT {6NtL[?rs~kⷦ( 莶GmDu` ի$1vw4E8a70 ZmAjY|~py2>JYr}U,)+}%~~K ڼG\JuAư>dBxg&licϪ{cI45Sݭ{JS#Љw3t%ٱ YZ{Pj-O%4>t衴uP@\l k nw0[EkK?/~ L! t~JOLņwֲh4X!4+6/) <IV[iieo̘%p+&O%Ae2Yd1@WiM 0\^hr LL.0:A~CXkt 0hDg!)ȺȽ &j!1z}+)')Ȣ_Vr]TPGn`RTƸ5HkM0'~;EP][/Ŭ2u }Нi&%ᤥCVȵo,-vr:H+9 a uH1Jsy07ٓ,'<ojHXr>" LŊh%bm J _i|/[ۭzhgez:uy$/pQpm]%^Y;sv+2e`D'jorw@bԘ&KhO꼟uS- 9,X^WxR> .T dgIv= YT[B: 7HTrG-e9V@V@icU,%-iX5~v;E[ˬw= ȱ)OS0*hq;cKe5}rJfp]K>ξm cc^z G3,vPBf>6TMJiX3?e2mD{| e1m㤝8dDySZ2#Mk[Ojq$ U2ﻡ'?*FxG!&EֺRe{}q[.Wr=%rZv۷OX!jnj$1Ւe?;A^(e"'*)P/bff% PYxElҗI߾pn7Q SU(6*'` |1Z3AG8`:L_qD㒵~y:G}:q-Xsz穐/Mx9^|u(mG$nbR/h<r1ɸ1&?,lOugq.~@Y]*Y0esG0 kuKc}tv TlEy5]-Y%K-}Yי(/4V 5I*~ypwl|f݋ `G⻤f[_4%ZSZNɆYKzAZDWwjZ :s)$?~2c:pk2PR ˸u]B~:d/zaW7"gf̄( ڋy DBn H̛!yCBshgg !|vX"84++ШP];ϼ> y&9gnZ *uy[$U%~(EPZq&`SY9t]#kّi ̪i9#vۺ_;PqFP1VDxDHpLI,S2Wo[ASn ymNF[<rP 0ߟ+};@БamhEF!Myi2lv^ZݶȈQʕU>:]g$)Ije"j[K-cU6F#aхU$a},%e.}2\ڈ{ݓ$A3Lyn" e䀓S89%aEc7)?딠f>6e <)q瓑)8ǔX|9hh$p;#5>O|{U‹}$ϫ`ĕE+&ds-0WVx,?"/"adE&F9yy)sV8hLdGGj|ԫ?*אJu1y4_ XX2&~R-.5 fw[;*љH։朧$YJmwI YOC +=L_h7>py^V扌_|ʦztpuM%cDq/8uõDa^Z[/Nt th yFhr&Og2MyLm\4 qLY4^Hqh5,.Xb*iU}YjXB5Bc $q6S=󫆠mw2uC}&t}L&zϳ8/xn1 Y/x N*=tPaAK%Qqa18XX--Mp_ 8hjwq]0 1ꃳ !8xyC:X|{ÐN]7!ܽ9. /`ݶjgQub{:jdGd/2@ӠQS&^IC^f@&BfZ)e+7!Ĥˤ,yS-c4i=!(`L6 unV/Mȁ/M cٮ58cZH%9Bcߟ Leu>q"Ti!>S#:'~T "e V+?n(t@ tN"4 %w!:cӚb|x_f cM"b:뜋O F{f_D]bfqV-U%*V]oʡ藙#2P>L"ɔaWWNpKU92(n¢k8{“>9N Ҩ!Ek+wI $GzjpOebT^>j[ =,ڄQ{,1~)I2X=ء3gIVƒ h2pYoPjSpЦэ݂Y:d>"w.ﲓ P> X*vOwL˙4l Z c ) șY<5 $4=&|ɑ Z GN*P~.f}z}dfhƖMuVqO;z,d 4¡C듩3M%Op0'~=ņl?FQ5A8JlK;nvgcW3׏}KJMx56QVv"Βy SύB}.CWSKy߭vId^]?H 6wigؠE҅`bR2IF E9h VBh]l/g7Fޚ'=ATK8xN82Ϗ#3xKr4^ ~ X㥳ٲ9J#qoe$'Y9E kM@9o%+ztrn/_ʟzj(Vy;$ͳGV@=Kڑ> h~ j2|C#]>Dwp= A[*ZXS],w2&^M[4Q2gnޠ (#[{l4լDorp'/>1{ R :luf=me#YoGw1wZ Ķ4 2O* [*x85VH.G4_emKcπrl0hjGl!f<=7)P@]̂V4?p=t' tfd؀?XweW컰 _YGܰGܐ ֲ87^m{9 Kȭ2cMSFR*M}4}`#lH?x#"Yd;lmXbɲOiq P6k{2:O3#Fh6MB$2Q%$II)YᩍݘjݬwsmiRCtL"wYf!eCY&kr:Q%vpJ:-7c!_0+o3[}3XȁN vAys7ؘܱ'SҦ{޲s2&ɝcfG{-b<ȞU)"y^E'FC!q]gŐ ޗ>-'\&y3gɛB$M?^9l%tzF aJ0 iwu? IyԌBc_+ N!n^:k?HB#t;[˺N9y{? pX{1 g{6~//eFxtSҿdjQ!cWh u\D!|(iuVݡICٸsxE7̦^aj1O{ʸsOa8K:~0e[Z| 쯎X|>mJ2yUgU:rNBX3ΧP&-jv-JS3+P6S_8DHB(*pK+ 묷GĘZLԘs?uԳ+6xm\7 80s"~4>$` [[c{,S1yȜXY2s/>-u¥RuӒ(7 ^y :tؓQܲ6 D:@8gP|bWbM-X^)P>y9(<`PsVq[Θ&w勗8rEھmN2XɾsoqUx2nGE 8CjHQPV\8g}܄-zfrrA.T3sj;;CdzpҳvQQ =3BRhfa);OT]NM2|le^B_zy %fqHYD긺2[m&hSZTCԋl&w"PElv3#|87T ݅]M-ٴ,*km\,-|wwhjYDA@;b34a䀾Q08LYZU\+CG=?X|=&ux)r_Y{`8 Xi^9hG`ȎNU:뷠b20 yL@lMy"wpN^rz:Ƹ oqw=)ۖghY'o@9@٢}SS2l5% Ӏ_n3yO݋:z $~{|$uӚ~SB É'/C2j7İT-hkK*fGPN і*{SZz#Ga̶֌3Χ`Ef]'/|6SrX v;wi5Fpk jyb!ֵx<zܦ>=ݠUbyuUR?Yl1Ed,WZ# €Mаff2s> ԍujKKLPq+/p<bS]B~@*f[HMn5?OB$\굾GxSgN2gX!`кx,@ ^wz <h…ҀN8[#nk)^^K`}AQ$dC(Q"O*btI*PXW(iJ7!cm2g4rnN}(@!phǺ]vUb8TB)Y_K4ͩ$ٮ\3Ŋk L_Yx]-LbjoSgVn~_0D~T6yNG>GkljC}氝@_H://Y3$nbO)?ͽirYoGM {V:9߰sǕjk\n>qkM8'_}Zlߣl^_"Y$W(4_ H%1cA&|Oef&(q!hZ-grSΓ@_h.2쿩\#&7""7a5%Js HMXS=*}h |gޡedpS$44\K_" RIo鼌/P=}9{==G0){ÅO!DYB24%!`4b̀.Wʹ24 U&ԲҢ Q ltAJ(E@^gD2|ޖ<xCjB!1*85YmBXCmP6YwS$Ua&$ZR&h6gް.fD}6 8Bf x,#(OZqGp$%Al1΀chu=XJO\xhO$5[AYTn{h4tR@7J 8Z RٚkTG@pJ! X^Av־W.PxΗ%Ժb&` pcu+e _8'hxE8{B`t6D"> ra s7{-ŷSgkqqBٓhF_&2ks3 ̎puCDuXET2J_R%F(mm}A&Ґ>xg[*Q+@#rpR 2_v'0b˪0 IкS(6g (fቄq[.)X:~#G*XdX{!R!  /ǹuIzQK$"(9G۾ud8nqZaA\dgmٹ\lyf׆5DHZ@PlbC |Q/_QF `E#Q@نy3NΥƆc F3ʠkƭ2+4"l8?메dbaF,m#B (rPLpN\4WZGDekʖFPGы57?+g#lC1G ALTzW@zkj:XJ/kNl]* ezD C^Pֽo0<K6vK1ȵXJ cp0iؼ 9D˚$ >zWt}uۺxCҵ]P숦'ȨXŧ`yByvF?聗w#U8U1%_Zg|QB .4`mI2s\f¬Ųmny{q fFm|' U Ayϔfn,I)jb:`\X+:p0N~[Zƒ]`a,EP:/@x}͝حƂ+;V=tI:t2:\F4>_ww[.)- R7wGܝ0LAH;+}ZvVxy>ṣsד'7KȲ0 L:gL@'Q Ba㐁w^t4\!\cѣ%ov>:Oe= <.tڨ k)]=/ nkOjzЍopT)]:uA ?k=oJ_.} K9yρ_)I\Fzyw<һ2Ú˜uϲx5+`̄;kmfaض0;otN2X{JHrsV_(<$`} enK|qe6uʗ@gnm(7h "^߭K>K΋׶h>{joK⇎;߼wϤ􅐜 TIfVxЋz ;vI?T]xTI᜷ C>JWÓW))F-J.ɨp"5"m<Y0 t;SD>84)e(zluXOgI]=O~ ڣlV p#:$g}lK2~ Ov>iUHj#k[l0/D7n0qd!K3 v[, ׉ѓn vR"_XW72{/9LffF.BBd_{-v@yx(sw7Mw#@xL(9Rx`QZU\-(XSp{u;oiMٰͦH :Xh?YyH Kl>@0Uc#YVO>?pꆸygMXRg?p_Y []?\T4&]?^#Fy, E0V G^̀Jkgk>#` tƫT̮OWMMǫ!BUx7̨m]ǮB+/cX#KÌ{thpDUm֋i<<=)Nrxvhģ@w5IIm= (}+2Ϋ\w,V3u7P{T+e}{^X CZ ܺƞo;r~ 7ye+Cq3sB*p @e|PXӚu1W}WLSu}Na+ˣX J7sc]^eG9<\:%*K 9br:LZf[LJz{9Ԇ*m[1ܝx=cad.erڈZB];:eS^%lSY2`Z2ide/oF4wn?22_`|DCӅ@J9M hyQMVW+^/4[P 5*yÍⷀ|yDv+g֙XEg0$ `S6)ZJ3\緔}O:WZޮNRo5 ]}wE4qk;1nӳ'S:&'Ra*:2 lHr$n?`Oz6cL55|ewx-#fU@7,׈3L$uWnQ"x~*k(0QVCD4ѱ])ma, N~JTo YKvY~DHιQq ܈+KZe-0`FYt[X.&}Ԃ5P&Zx2B P" <<6KrYd56L)ߗG5d}בDrgJxA[/$& S>߭TWȁkM8[[:(HH+n+$JM.oyws$ٻ:b[5pDlmPCJz׶yb=cK/dj_.XOS.%&/ò >o7$u&gmS?Y#3au=̘6`-pPt}!͜VלMFD[v_һߖ#oY댊pMn\W]┞k> d+KC*}-/jʋggFYzxOq&tFVNImj WU {Kn G`E2,^&paj~#ޘ'i Fo(6%K8vW&mIFG9LVʉ(o:V b+j/{Q'2;XqYRM@O閅N=ԢSFKgd.PU~9YLNHٺ)=ła]oXr&d4P:8x|m+щtQp9\} av;RϹH}+H5*eB8bR+:*V哮C%L;>4LYٶIWWA+ RWof,Y[Z.Cֱ(:s+tm.Xd]9E(|'XL*ymT}a5̵gp-aeHёWa=z@L5Yn\__"!2-%ڸ|y=@2D1ْՊ\rS`%JwY>;();Tb9) ȖLVde˸h<s=\نnYO.ﺩʚ%yXPH17N OCK{.adO@!/V󋤓3ڒ8]c%Og艔 H!)!D nAkݬbfo;$RY. ix`3 ի.5ϋڸM1D2r P ٳ#0V*$g.,jK_ڇ=3KrzƓێnEh{0יp?3.Px5znWQNstWН=JyRGH֔ Υ^!m +irXz1` i\% lw1# ^.|w1g˷6`pɧVj\:0wKd%sL}V=# jV)߹M l*}LՁb<@vR'*PE0V*|;?kEj8%v@7tk6ƗTYm? .9XLC:}y'@WX=2: XvK=ID83VFFΨB9Wn $& "ӃXʉ0]m #t_2rvP71^{Gh:pZ11(FsDԒdz\YCjIzm~ /X&Fz/W\Cd%yWc ꃝbm)Mbmڥɰ. 5UMs7BwE3m˩-g(2Ae:9QiXeu`k$C{lQ1:g%&D dJ/_)fmHGVFMmdz~l/PxV \kt9!ibG155$}@@ZݛZO'>PWꝝ5(Yloth~r$- _81 ~s(VZxQw+24! Ǽѷzϑ۸[돬sFY(rQ89בEܭ{dB<(A(fdR}{}=yYxB<1Fsgm,$n/0A|o,9au̙(AoI%ByHmMy24+R').|6vмbڸ@yu_iʏVʠQ_ ?V.ocRyF|xqSY%F+9j8vG`jC %QOirfqn%H)R+/GtE`nO0a?@X8U41i'EfŻF9SN>&4hue,79RbSsxtE]Ye6_=֣ijtɦ=g$L^K_6 yAdf gcK{Dߵ2$ϲ5HQIXXei2)-S`9B"š4f־#Ɣ[,UßDzY+~[`jN Awhь7ΣtBJ(1Dn$ 9sIڛlNYnKX9525>kAd}}b:9X~cn8u t6:ww!5TdDD΁Z ޾rS S݈Q5{PSm2 3{ID<օs7X D©V9) ڲ[' Yh Mٚ?>d

.q#;{Gxe@C;EɊ:q f6^6 yU>ViMe`Є̭J]ĹV8r6q zUU)Ӵ|Ҩ*SiۑۧCS=OOu]q& '= ~B74$6ƒ =%ˤ{rHnQo_FBCs}d=ɣEJKLPM-BQV$sKLa/yX9#h=Z+&Ɉ{=sP0VJϊkҬ=3@s20sˍVY Y`jfg񛙝p;F 0y4Ibۭ"iԑ1خB\ne{l$a'G*C#kcJ2fD g+HIY!Bφ{u?m-xH6di N`}Ŭq':6m4h˾&:,͕| '+G]G3 hߗ12ctNׄEF̭e{!;Z'N^vj1[:<4wo_J69FFvO},vPn Vuchor zr.3qH`S~6t7?Y5k7 >F֡a_xkVNm.p%hxPuS@%/wvJ><"9;:>vies涳rƺIb3EHÏzx)W~v?^1ʍ;>((bx3ti4$)<BY翦 -r ^ 'M8!O. &~vYELVrN=_g#>aɡ_c:dh7׉=jj85Ix ܓ*Az* ׈x csV[V/}bQg/;Asq {BM{huQ_/lr~XyI\9vMt0.ꫛb䊱yzd"'ayX.N~Neܥq`_%cmď$yt;]Nx[f6f=CAMUKq"iE?_ֱC<{_&jTI+d=sAcS{k C:ZZ מ̺I5nLI34Y!ݬN Ɲ`{}d I*ߗDb/4^bX9) *y HͅN~\<6㈂[ȧ'I12#fhjy"W8O@< jxz8v{Qe ]0^U+SAxI`Ps/)MiU,*@`Erb6Y[S'3p $CyX%Bu&N:grV}߅)S`V[nTG.y$=辤b쁗yw[Zhgc<ʮ4BJ[oV@Ĩb jفW]'V&\d.;2ɨN>n0v{kЊW3orѴ*ڤ+.m P8$wn$;g6}sXxu@݇Fܼik <\- $@>.Q*ˮ̠b"HU>;2GWqLsU6ԜPi4X(nޚrR< Ќr*l!WvN0WD~_jra m_iSyD#\n ~X ;_Y$HR6I)X!RZVMK); Y;a?%+ NH*Z#jna^s-<픔`xR`JCX9ьr]=FSJv{fPeIa$1ƙT,@I٤&cX>GvQ{;3+GIV(Mv I|M榒Ms!ŹZD%;~-KdSy8{rbw/g>VgiR~PqUWA鄚퉥rބ逛Š%4W8)t Ge*,$rep$r ;P_Ayb4f6ۓ9CTY2fJy;S*p^}rHZ;QwOCgo(D\~)'1 xk`t )Jq@M^CfIrpvd; b̔|Xtnyu[P,Iޜ3;nSt'#ХzWhbɍv9+E- ̺5 "=yWVZ^hS(`ߣndwKثyq^DP9@/ݴu|vI#>`HX"ApvñF˹**w$_x`Ew(i\u<@F |F`SMj J55e+/+MXR{ibqkrOo+N;ê XV :0;.*-gDhq3s$}7/P*_oxe8I"<ȅ=@ذǨ:[Gbd~uޏ5*CpԶK<~f ٜXg6ρ$|i2I*Z 70 BJT]%IZkڸl̍PLi{/Lp `&z |ZmgM$5]oO!fݬAl>:dBLXoFբѭgqlV}2QJ Sˆcl\j>\8f* uk@k& (EȮ9%RPhcuj;,R[bYuͪOF Ks>vGukw''ȹ.cA̪Hd\r,t ϳ$Ӊ"W~/QYG'WVْ]9jvͨ?|bk l8VIHTXo+jgәpzyYU8b&Q)H+loѦ(z+Mnشp>E]M@=@"LW ~+SN$8n8xΒ8VQbIՏePC{鈷4tmQ@=|)#6ӆZn`^_y԰JJE/E5ꍞ`<1~vWʵsnֶ(zv_$3a/JI+8t_`;ݝz'h Fszrw܎/M"a1IZ{8i+ys59Q Z[V3T5eR]:y'e:\J.y6̛g '.-~¬-ܢ_jD,N6t%?r+eroh P<3Ba i\GG7O=3Q2q~(H8f˟WqbE*F6CA[U=gK=)$]t;o?.*_7v$\?5!սqkBDz[|#)=A`ZV v{r;ҵ,>A EOErbC+'J+g}g'z "*'Pe-Ce8Pe~ {BH[OH;Y0΅3N4گJ|+ vC(e]r? Wn];REd%AN7!zqYB'LQ^6xޡ7V".qݹ4I(Ȉ{*U }ccAMFpr)q|pOK6z7P>f&k_چlXĜ˔&CqnhBQk]b}=K~c:}yޑmB8cHsFMm7y~Io'@P(2MLH#[)j# *Q !? M)Poo;]RV yDpo쟯&L#^9bfe.p'5o^z9xk`,CqH6M^x MZ|wahWcauJmWm飡 uyGwָ*Ev`R#1$|PyUt绸^m94ÍRt?y^_]Q@^|CWrZc\ջ)=e\ܸKRB1d}N}rnI Qb (Zy`5e$AMk)0% e ߷XIeȢ+wAWg‰ڜ8۫B z͍O-ppi*WKř@Qf#ЎYwSi'(h]1uG4Z3yRK E7y|TR}e/QHiM= D*V5CY;mT{:PiU'!"}P{U-&}2Nq̌se"(3Cw3TK;x&ט5Pusa^Ir"nqb150;[7[_sfTG r'TAɘh U%A$uZ(2CŠOVl]$iǬCeXeN1kv"H tp9+ ӃڂnzB} F#(8\(*{'e. r,CI= qk$I.Hu=!EM AWij~hy=TV:R gbol9L_Hm2J_q>X̕.aP~͹kR's2 ߝ/lekr*F@'Ju\W]M>U)PRvV6~,{FvG^0emNلU\c^X6+*EWVi;WʍM6A'_@yջ X6}[we1ejT]Y@^F䵎ݬO"H*

>ˑhN u4O0ftLpNd42hq,Mc:Y835$,.Ǭ0UķY f kiuXǣ2G6sf4= CДߑnLn|/}7a`d}G̚%\,Ii^E1s@XkeCS`ػPvǀI6Ml&7Zr5:'hpcng$ߡ#g!A4_#:\\"fnz\NL8U ֫<:}~!ɅV{Iw4D/6tj`asգn 롂ƄZRY 8i^zuCK[ڛ$krK:>7l)FIO"An h,\%RϐֳtieԀ,K@]rgA]t1ec5I9gܬV.UAd5?>nG,&Vә"7ԣa@cpD%I\$H(#QLj]v+50YqR(6Fq@=TAԗ覜a_(Z`3\eAFĦ9wOf?AhZܙB4FhX8ߟ1}ρ[˷$aJWT@CԈ[4-VûdcGqPQ*s r:E8R$?q|$W 3[KioSFⳲaBnB__kBx1Dmؙe!P'7.2\-l\rN^M ; #?օƛ.<`հ% SU^baI %-b(9o^@+L=n,̸dOc㙋.e5ћeGWC?iƺfֲ6W?Ȃȉn Iix$|-7Բ? V:^y,pTi>*}}_xS&j< 9:czwDT'B 8+֑]ԹX/k)'YYڤv3ĢlN;34FVR^vZh}B-K\~i5kE)Sh{CQyTĵz 93g.ɴCUΆܜɛճ$>#zq.S%! jqX4HWB񖛎iVݾ_ #wQqNd=|1mTz|I)-Znd[e-ON[Yx*1goa(7bv Et!+v:2-"abeZl> *s 5LKH77PJL70gY9  ;t̲LYՓTu22K)'6I gOV-WU# 3e4=IЙzz&K9n0=9әfSdݲirVNz!!`lM]b_cԩx(ƏM(hٻӉR nn :L +]b-)aׅR͍g;2c<{lpZnX׈c`wxVPL? }|Su[M+ jw}j1#O}:Ai3!FړY0ܔML7'BIK rV_U,b~L;$T&ʤcK|O}k@ܬNnvf =g62 !Mg&fwL+Jq( Mthhl78$R ̧,@xOk+n}V9 Ҥd" >Gzbe* P')*VQ UZ0Pu=adQҭBK nLUfyzTeJZnUvv^p@æj x8Pr}(ybyTvq&8h G ܤę 63Y>t+ȏ9-+2sywB]xDo-`l *8ރe4 CY&ǚBx p_ޏ].aV3Uo"~[<6ԄE7E_~0eD`g!}Γ [':J̊vfa:0gVr|*/ D畲J6Xw7eCMa2O䍞I{yC;X"M}[^;xE)t&eLmPfcƙų$a}=4ǹ[ [`RȐ7 kq@Īoٱ$/N0aePfᇷUi1hfgx4cȜupz3_XcN{ӇXΌ:OX77j]Q"}.3k-# x)$Dݶ+l,),bkg5.wa}/ XrYqwԝbWm|BG9ΙTu`쬅& xE$Y(jޝMՅl!\tj^^nemd.,הJ*sJ2ԣGtB+ӛ,iա~CtfFLՆS{yQ^4f:r_$E2K]#oJde" /7[3:*ac}Žm.,o]Ѣ5pi0[>O, XEZXNmYNc3ɌԽ s7JVrϿB~'Z=([ ]{lLHfi>#$Lp:~v^adƒ[n4SK\fXNg>9fKe;fB ZWo2HeNު"3[ e-Yu.M=.~>WHY:G>#Kg5f䣿q( {D)9]-HN!nl6\{ĎkltB됄#ξf-S;Xr~2& @aEc쀶Mzsʉ&(s^#U'(VqFDo$^ǵm0&C$Q6!J%C.t H)3pS㩻;cYnCy]!\Vץ'ѳF ˕CH!aӯ&>Te5fIRSA $xɀw`&YIRK#Aa\ϙ%LY'Z}3)啷exZCJfۉ,A4+wU@Y'$} h0"y|yΤ.DJפc1h:))-4O1w6Ie=7U7/WH"-JYhÑuذD+0IK S52$WawrMzHAg0s481ReZ@i) U}fq?'Pm(,Ύu|fҭbw( UՆ <l#豞eT/9^w1*13^;Xnl_@L-4( 'w(}qM9i-,Z]sc:U;Ni}hXX1GҢx t^k ]Lj%SsGOGcab--Ӹ䭾U`j͡CpOyK49#V. =TX$&=I[Y duV >IW[l/]2R,{)֥azu=YYp.˕JOb,d3\H05ޥy7*V&g#i(|b:6W,djk tryPp6 8VM!r isg2\"HPjF2tcDȴ[F / |tÙWfڜB/~BnϏ`XySn?<"%Pnr_x] A=YgM;PM| V?NP; ijId&Eu*c 2H4dvg4K=)>KI]TgTp+^Y/|9#^S l:!5ܕKkl?7ү3nvjvկ7)*JQa`ݬQGfc?pg Vo 'f4m`o%g\;Olneh^uVi|%FT.+Yן棳uh/$%Go3.We6#ڶ|y,5:;@V /e+@VVqVO{mO2ݭB)+U}C3VCfc||` O@l>-9ζUhkXhךi",+uP:w(^Bsi` o(;2"VdFVۃÆFu1)H| tZ?aqFXgǩSP UӉ xLyMRt-(rGTƁ5EfLtdC&\8New$YP=f<Zi8jg̪tI bA$4.iuםfܩC{vPjTwմe4W7+C./Hr)4.^$oBҏ6n뇦}=n&8n633/x-˾\Ou8հ6ՓV ~j-z@rH;DY1ɧym\wE+vѢgO<lC0} xl7k`3Q]r۲-9 {)uK̒})>NA$[Q)10Cn8\snIW'!4gL_  &8X}tH$;6k9eEM6'a [^NKleJYmt -.ómM[kC%1I@ӱy=nq hW2`osA%GUz)ct>(a\lxssQ'ίy2^W;A"z Ϋ!ơl ,VexT@T>6A_xIὯ7 2N|*ֺ(5UX\<.uF&'yElvJZcOjCg)D?I5xE1Mb\h2Nqe'7MoYssKB5"yjkL֯?PD>nz:52?8'ykfl8Zeǜ1) Of& "8ꎕƔ' pְ:aM0և/ 5UJuA%0 _ qY+iCyb7hɁ[י}ԟIf,"赟) 17L5r6GxX$HmiBș'u[aMl;Y-32E3Un{~{Xqm%欏ZJM;I#?`qtW3o/֫=3HSO" G9/WmOWR.7\SoxY- K.SgTx4ր-`H+0VX-̍u[yPcyF;g#0w_HƉ$)gׇGF Gwy3Uf?1*D"~7|ۚSDS|ީS@jZ>:խo?YD/1-UҨ gjGҪ\I8Pة5tKdջGc#G}s"qo6x?@V0T앭Q 6bݬ0:s.L| ",.+%27$-{<6}f)2$ QeC2 Q0Ҵ4P Teأ8hV.v[t!}9NgpZ8ݐӄ mH,}W g oG3;lfGZP^7"]LAQ?];Fײ2&$GX;J_*!nj:S ~]n U@!PqHͭ ?`QTH,/& GsV32G?b}oA-܅m%Xsr$s-8з{ԝ26)?o6u)K/A MH5cTf_gaK8F(ίm!7&}lr˺dsMw (eGey-Ft;hC0S,%a L5^!gnO*B`՞ , _2A`PT39k#QЖ^4vS%ڳO@S-",;HzS3?rcتK;J3y=r > bAL8'!އS,-i}*r *AqpX g'Mؔ]r/:H_832G~. M+Ύ9c07V+ڑeT߈Q ]љB\|4(`t6t2I#Ə v`rn> fԄ;ƚ'Dא S`%[7 !|esY(=?;orfFY%}K$CL0HHzd挑( gU?3Zwr7H0?dynSptZhε!W"Un$P:$JFħ9Dchb>Z" 3/J[kE21f.gY[dt{ :/'o ?`/;YdmlYnNYh<@|9YXC"sM9ͻ%ΊY{ "%7Gגy#sN ɥ bmǏ@ "́P ߖ_5ךmyb(raEER]!욾ӑ#=A]bUmδ2f{҃e)w?hB1X!oW ]6)zYIפ;L Fʟ\=M("*Gt$k{%tL8pЎ?ùҡhFdarvA `-so-YMM>Ջ@,t"I Rc:MV=Nlwi* >lz.dIO YӾʙ$^>kӨ" :i&ϋdMZ*?Ї&'6[8_$xy'+?AC̡|Ng7#oi+.DZHsRMr~ xk{gS1m:\ ^eUyS2f=ypjJ=\g M"cUEB^`>IgE|},<[ˇ/' +2Ox:id6'hs *ev[_xL2t؜qn۸KYzȂk|'%ԕ{i*H$-5Aq^aE+jY3a%Wڒ}O-ec&δpӾ{!e}cM"kҨ}my/Y,Tdܨ42΂Ϧ7ȹBftȹ ^Q&@\Qj I '0gSHu"7=sSSHxZȁ=[wYT͆8vܛ샫g`H7꤭>G=t{'v]M™p~Sv5jZ29`^=E| Ѣܠ{Ϳ$t/O nS|VٻِYP%'w ;^bq/;A i.}yK5wRN i^Ly#,^ШEZ3o92?]Wr {Byӣ,^gJU㋣n\-<X*ٸ#SFS +=kVۧt [o\@ &jo_KCd^/7\hLF4 }Y[UIDETLOM;g"wE=-x̙Z` ` ac[tZ /M~;kGhC9v* J:ljxZ;. k i8"佡܋ q:1gl:]HNkG2Uú̿,3~bM I$}0䟬W~9 i2oy%NI]%lE{Мս ̄ qF)}M!S3f-$O )=Mc:Ycc4*1gDxfnnL)){ٻ4xs(C* gF:,i%5 e%E$V|/t2r&LMS M*K;0ĈYfsco?֣(0HcG90Yțs_︙egO Mʚ6V &-\~0+wb\067L/ iyctQyZ#~Бf ikza fܭY͙'L!-oIﻱk~<;<~Lせ7ьNs$Ĺc` DLɛO*6&3֐1o?A3m6COJCh`UL4Ĥ&uKOfϭ51iOg`.[&2~!p/=8UnO\ -q՚g?7iz{ښA}Dat&٥'O4C: Qh#9ێ`I'ZQqD|kĪə;:dy%*1 !ܳ?(MIYvsf :dΖ7ЫKRvL}<X )ӬFv|%:I70W̔i<8?Sl̶L1,%kkĤ@ 5ePmimP@[h7k1[BzAx[KZp,JR>=lg7v|/N2f&O A4p^ʽ@~j/%gu\e;!q/o*>*W~WwCc~Ϩ!7EG~hP0i8C{9r_Ȑa^Y@=g#-ɸJ`5_Zne_pm+qywۖs[߬EI'[a|s@Фcjv[8› HGfqD.ϲa^\h6rsc<-M.WqX۸X>8dbSQ^'~Cc}W1A$ a`cs9HS{6'l t{D[b]h x?!zWs\>ժMjq[e}:,h q E&mG 6݋\&!,МPFwK-'cO/"/VLЌ%>d ek #G7NQrȫ<D:[ӎɭ$?D6,Zє֐T/F TW>.%gam,Kq"XG%~\&`senK2$Oɹ:Y)(a,&#"R! ݹ+7sd-gސ*8g7Aᕛ5< {5Z;>`ӹ,#bRP6̺IL.IA7tn@z,jtX4'-m)|H'>ږhgQZRM~}riwVMJ<+aNZ2=/[5-5_yyf1z7ZK<:_l P-L-! ]tiZ Sck-ݫ!pN.x[԰#\"cKtu?}r<#:Y|*(v1;]RNY%3l NHU֬3$z:8;_ِyUWY^ڒZ{Q(Y mB7K2A9w~@{ 88mVݷZcOiUהOd\74?8heG8/uFL+I|-S9&9CglЫ>Sf=j6KH{3#OeYI';^1ߠŊO2bq;Axo:R i`$Q𪓅Le3$,Zr~|& 4n^%KnI87V7Ϥ:ա5 \ua rV]⁒vXN>Zrc@um kžPb*0r9CS 2YU\i ̮XA1'/ jq +!fߑEas\Z_tyD-ŴuLۛjçTUo97 bEEOGHJ&@f_X.YJwozdX!F9or0$iyVH\"5 OuymT|.)%Ce vZ*K`vs,Ӵ#6xL_]Fa;{ *n]CL6yyL>QKF̚[r'Dn_}]ߍMiP-chq} ֻ*|jP3.U.zAw5x]9[g*doJxK$?R0IJE9[/+0yS eB}JQφ(Xc%] BQ۫i{;6Pu8"QJ6NYz.R r?$>& bSٵ=av-kR&n+Ф1;㉻r*?-)t;:rfFR!7\ f.Ӂ7quuyeRPƒRoq> `] 2AC|'yiq8.:Z߱+SK hD8Q}oԱd ,Y&"')C뾕Ή9`4mC}KTdM7G#:zgﱆJBtc}Qmec ihټ$W鲖'x ^wG94 _5 UìGL#+kgH=pdLRgYfH i&C1CbV.!eē{FwYXZnMm$Òr6IVIʠeӷg^7O0)SW_3D>J9BWR׿ˡ%#:4 LL[6Q)T<+9Ak.Ҫ 'OYasLjN:v\ɰ7`GZZYz:%I1k.ȣ|u[BS <|sye%ÈFa;ܓRW2͟2Ť7;J/6ÀsB?py,+EEYfna: Q2`VGbi䜪v&͝-Uߢ j'.b cm <5`\-Q9,$gck:$OnC1myr knw 7@tP kCnڀe3ms&člx(+xn򖓉]aE8nrdOv&EBt3gGLɭ`c #7Kylc[R{+Y.yBrk,77GFfp~t m9Bǥvz!eyчCP^qAMf #8+k/kY$Ֆ>C9Q+pfu5P/t)ĺ? rz~|5RjPr֕BglzN=g0KXf/6Gm%+0>)WK/k)MFL>!}pj30L̉gxecqcIXErMoZxlNe!; 9[ kRJ a_pL.AGpo^ /֕^#]9t{{ka^[=$%9p\>pI)|ܓَ^˫]k"'oH>.q-D7j\A,k9,Bd>"6l$a{=ϡqWp]\k(wm AUBlsN!U&[)^a`MPPx/Ӣ nU;pkoU9§9ԐUvën֐{掜{Adl\l|ଢ&^mXYz_OXfc5H>n&A]]^{I2AYWu/cFʐܾ=aľ>t @ }ճӾz_Y~b#o.qHTh3e|ܕuVKa< S6}7nƊe9Hb,IB0?3H]vvtg"441pԫ "jTO,=y8{lb =_ bz,0oB[4Om(;\Y.6܊_aj@85w[15ӬU\v 9yſDW|`jߝ~{wXQYЁlyƶh)\. ur4u+F}l@fq"hy8!Z&3^uFs3' 5ycqe@wb&@4U\g&h9#7G,L-w:D&eN^M4˓%|0mz1h6*rH %fGHӦ"7Ku!Lm]zȴa57ƷK7S]!Hu/CZ9Z9:8J #=f?eFAS(q+y,bDv2O~ЌX[(D@- muG$1U~2UJD-X=:#'<5os,H E"jjn^᫔oxI#~N]!> TjID8veՇU<Lu$=!'咻Ԃp8\BgW_Vds A:?O)ូ3 ]tL{@A ^th ϹP88H/7N?vb}y,-,nV7.?#֙"-s{*S*H3rbAor9sfmC aewce%͏XwD"i!њ,!)j79o8öY0`vPI u%AP~CLAL(3@>#07 =|@BHӅlU%_.^̍bX 41 |t{ǎfzxX}MwvʼnOvIp,BUݴSy4[`5M5x[IfNsi6 Y/OĵrBռ|χ)fj#PvבrXjlWx&++5+x[~0ߤ'͟\! #Ka 0>6żޠM%t+gx/EebG#;2:01\!\e'92LlıA9kO5bDc ?RK;G$@mFq=.v!qq4f 28a]h6p[bi11 )97t}IJF*LJ*TU1,"+5m<8CYT_Ό8ČXף̜'8=rf296d8sf¡#gfSssbI?C(gpkRDNpM%>\O:9K=s#CedsR@ԄU*5C>6tԁ unetnʙ$xIS.bC/ ]ճ'՜zc'8;ͼ%Z jb*C|)qk4ݲ"C G2dVH^A[@XLe*cjé]f׍2ԭ\4 #bVZ%dOh"x$޻u[kpB$𚬥rW ot;hy;# j'2~+Se92gTg1R7&"GTR诲6L*y2 .3tR[z^gb[yPL=66a/PLۭ$yH3'%&P6 ș=k ]m&`gv3UN<0gR%#_[: 6Q EB픺Ѯr[^L*AfL!T.TP7sn.25p~XYKC#!_,VPkOh@{bVd BA0#H2e #a54F~ f TBPB*Gk/lרԍ+PW)P^v~H7l=8'ֶ ox=zihpfU{3Q ֯j0vHzb?x`8oћ拯ƅ~YXP]sZ&U᠍Au|x(㙕#3CT #Od>^ ^"FG:bͅ!S81{y?{O74.el8eCqR JcM(m%So@\q/H՜?刲]e<" |X `rwUG7ĞT 9an>Lv'UoBW\gҕ:adTcp:pk_Yi_blEǥKVM:tlҝi=XXzxG%ǁҼL3itݻxogV rqt.;T"MHǸo4|LX Z>/8&ch-& %lv܂|!;ϫˎɐ4p99l g;mǬ#,*|`cxF=_/R^z=YABZ\h!M"O赛qf32.Dys؜.խΪQ-"ڔög)peL8F]9j>sޗ-֒ ٚ6yXlxߦ_ ~x%7˰'Xf*Ka&"k; T1_''Xf^cNXdMDKNy51SXTIke9U?LN<j ꛗ2WaDr{~E[tx @XT01`fTE ݓ#pZA'>B{0+VMƆ[A.C»ICpNlɴDs.0M LC+ZI:^ vwR82b=V9]َ< _c5a}TQeI޳C(&qu)y>퓚YRS2wNqU>y{n{8j] iA$w2guW5GCJ r&!l>Mۛd&ڄðqlqXm6Tw؆lARlC:Xx ~jbY>Ph~)=p'MJa\5;!犄}"d#CD,7b mxށ{ɹYdAHb<Dc| @fݘ/NiI̫9rqz~בȂ6rj{%OA3&C^<L6a͹̈ɺ._ ळ58lSԱ":&)9_8"kcPdtֻkꉱWw xD!*{GȖz.3CY;~ ib7һ||?fްYw3ZYo /KQ_rkS C+w8Ay̕S&\E~?%;QTt`s^qn3MZeyz8Sf++_ k⍡HYzkwQ׼059~5B)6EpscG]wD sݘq5Cb`Mhͯ;]]RlW/G3̈́|39Zye)Λ=|=u|,Ji):.'p-B2y}L_auZ.g[b;;%;kKҐt=bdq> Uo&uF['EvV`_"?d|^hg8yc;ֺaajfY=y$bmڅUkſ(ymdC­h$ooT^d%kZ!l|*Owwc5}X_ RRGJTNp5: /7ffðzm>=M 9?mPV!TdM y5JTeD>]UXljM2qJ}0wdhc0%__b(G:n8ҙ0*bzSC_~ Yhpu3}uyHIBIx ( %i{3Pހ,$T* ^!/֙u\ad!]J/j޷+%Ds/KV }H11o]y_TM;gm8o܍qF!Єƻ8/k,w eppf8ʙ)N홬G]$9!sO2Su;Ӽgڃm5; . kiSwhd6x BU1`W5t.7nԔgLHnÐ64@dE5ު8¦:ksÆem͢8u~*) 5|0l޼jaH˔jŁ Ōj|:CPh`TGޚ(4$o|S aQGxUhgl~DUs)/KH0r鍬)/pdmHd"]N.WkxF9A db4_z"C伉HIS+2Bʚ_ i8XYĢ%yE?68 ~Pnv|d~+u4ìJ2יD7At h :' [:nr?}dsy~9'X:E\!  _yE&sJvv%P+K(5*y/1v`BXnN!+;0B=VKHFqJz!ފ8F1K_x 'T5ͻܺ S7^[e&y'E4::dYbfQΐܖXJ4_ 4\,K䰩Kmyq!v&X%~ӥT)OyK8FKO$CC=7y ~e#3C$UA2G`Xz1AQs ?-,Տ产?}"0K.o_zK.XMw숔t.ʐu4xµg5s):CםfaXM"\u72;Ԥ<7Ɓe%@%&{2Snk.%25ɌܥpGEC^)fh",ƠaФfj3E'FE'ҼW_gݡh5 /`y%u7=xBwy8*5u7D S&e7|x1P@ncږ<O x:Ns`}M|cg H|<} uFD D^2ʬcHQOT$X'nCM?jcUT. V?K.iS <*x1d#ew84lZrOtKo.RuԄǴ$jmf:Y눁TmZ[_@9IS=6'djYW`Ra힗ye "Hgۄap1`u3?l&\w#3}Bf^Ot5~|c|"a`b LߟJ*nSʪq*$Q.:PΉ+ߧ'5UTW@LfpRÆ_\ɸ˻ͽO̧Fe>4>A5LdL;HW@weN^l e'wzi2Y=WzÜPGXbxZSq5E~`ra `JeL /LB  [8!;/$ gv'8s?(2ݯ`>h@ +}EF4𫮁9nuG˪>)..-5'(*37p/rþSaߡpXjVa&:#F/()nhcqDQEa;Ffq"??7fPf-+ݏ%qLhoW5}K#Zš^w%aLPPtkgTY8":<2ȧ1A \\hN%LqAĹ:')e]uC\{Wi42l3X#LQM~tExsŋbf6QA@9Uۀ?v`zzYhL+ _%sJ˝]Ҋ/)?|~NEƧ+1#1GH2z%{2[Yi㨧)R̐c ɭkNf$24#㨻m'2yZ6qn3BFFWb[anP,m57|⭼?Uƪ>H;>rDgFqB'-9EpgYd{k Fz5n5%sμ"/LO u?щO -OL=qyu@ֆRE3j1lل,PFUٿ?0'jatjq“ڢϺƓ_x)&Ybc~UY9x0=ߖP.G9oK+y)(鈠!7xj$Z78Cl:8"Vߒ UxR2*9W,JPS$*.2|д={t)[@@ 10 HuN£OlЗZl?gq܋X{bVS zUs*}k&X~= )Z~8<@yUNGyD5cyCۀހTq栉t!2p+|[~#fx \Aũk~9ѹG V]#Tɗ 0k =pWh=D7<;l(7fa2M1Iz[ݴiYQXc` 0D*:.5h |-~*RO Q";?RѡtM 9 #3 g܇ ud a#ZmԻ:YOiqua|b噪˱!1R`g6Mv!J[@?^O/'TPy^_h̚ZJ?(z,pBD k?;HXt;?Sٙ߱NT[/8JQ?q^/# AkΙEKd5C}ʭFQ]u@ZNjr*VJO ės^ .I2h>dʴaRڤcRB!@U_ `N&]e6߮xy~c6!epSDj]6Mg]f6ռL6Rv0(~ҋr9G ^p1:^A"ǩZ򽝩9WXY%"Sе2~X!XI4@TZXN۳C;^/0YGg=GRؓ\}5_rz"t ]$:Z^i9`>bi ߀=K }#։겻kzZL'cЭs+QHƛ jx*,9gcdOti^8n˞o4},7d6U'yי`_NR ,͞De>DQᆹIaHPW ̖bQnN/ b nH7G{Y`F 1>9X^oD80Vx8Gjp j`©@"x\kDFXj\tyvQ3ߐ#^p #ʲiVR4AOg8;xV ʜS-AΆhz'Sfqr".$SI?f2>&}CXa%J#a->* omu m]us i cۛeC;o2%/I6-i@K?4*D7UPVb[ VWQA[!|-:bԴ̸p<);RqL֣,c=P?0r`kaV Ūd[5tɧh㒟.r :LtXa:=$؎X>,Grְ8$[}>@Yih iۓuoY ʥ'Fn3֧(FQľCV XAv S̭'9x$ V]9½l*^l[^mBjsPm2$Mc}~~9;mOb M9³+Hd.8RIr|@ j= +AśBԕ <=Yh:E18&ΜfR'+.N4T>V"P/D6Ϭ3:~(ߣC̤ү)dW xs*]Ҙz?5\ME2}0r7Dʵ&^loEշt*YyP7( /g貓^z :|}?x(3uef>*M|SȮN2yĶpm>7 9CcYвq !ϙ**&؆-5ʀYDOm)3Q"7J^:) "O_j}s]N⛱fkT@frKjIW/{fMl5EaGja)nj;6T+\^RA1>\%Ȫ2QuX/5oΥQ 'IZKdu)ߌzڬ#iQ>sL0gM_$y, v0HV;}̥)_cz[[UczXI ZfM36^X !g#b(μ1 Xpijۑ}|R(s[@!"x },шZ%W])OD7%2IGvGGS#dTyӕiRhXu2>Ҹ<>ԕXW˴ل2%6[|YspUXWD^AX)2rr^J.RBe8HiʧՂ\b&  }yfoPh4ӽb4LD:'3I>=&TC7򌶜X~T%Q 뮿0` lV"+k\7{HMIS7t" s( GcxFh`99/anVdet 'צۆ?L g5V=lmU:Gwۨ6r`,S!Ǽ}1cL-ipn*K/:\雘3*f.w苭DŽ&jp(8o0H0lsk>+),S>NNKa5t4t*Y٪wSJNuلo>㡟 ~1VuUdec m׃^iYHsbl#"-{ &Vǯ (D&DC>btL(1>8BYh(7mˇnY8]Q}㿋 < &SPNԘ"Кm`g4zB1vql@KUXEPNxJZl8gܦj7KFi IX]HՓĨ+G rєHsf6|ToVG: aHvV-'ZZdQICdYf a<<ֆt #a7~ed-U^F d2Mk7GBgYo[>glǹq{6 /t*G \=sLfb,\r#3-x8(=X0d +a.MIXy667##Gʡ&.'藕XX&U=?.nXXz2λw/4a\e[V]/#QB[H} ŊB߫(>|IJ!~0N5 % x wc&EMm.)e 07aYY t\8>_e(4\w ѣ#rUO^tdO)7 J60M }3$ -%$0Mfdg l=U(,Ng®M#q>E@9R7+=I=p0\k M*4[Ԗ5,A7g[V1t3n>\Er*ѼLj0 ǮPo$xVif|md})Í`'CWϩ*Mx@>]7A[ 52p<a9oM^cʓiB7, [2eD~DyנR9хr.Pﳽ~fܘC >yܪXo#-%~fUBAfC8"};h{Ә>KVI6$M&d6?(r,3L~*wIB !3V2 _(X5.4M*Df z[fe6@U "r$Hdt};=gɲ>0ļQFX,.DĜeoaK$"='ǚU٥3>>}Hp͠rVڇ:ܛ~? 6I zoΒKrMD` -AzkƳ6yXϐK2=lS)Y'5i&Bw0oۦB.E M#~]h f}3CzQ6o*L-vpdgw}ͯ=g0mON׋z1 2z:d}4L{ua3jms9gzeU k˔Y@2I|Fd5JTq]YiXUT~&3И1<5{gBuL*A~z.怫JbGoA$NiJGR&2ٙ(]8 |:eJ%8ҷ{AGC܇mPU>AOM 'U G~*]D⼒LGk|0cb Yi@XIrbyг fmRE?;ZϏ<2/oP@^-#EԎtX! kIܫ?T`; ͌G' SȰa} Aqovr4^Db`q~KG]$ }i4eNLlGkPlaA*IoBs` ÞGL]̗q{uNpuWg<_ߧ$]Kɣ|>B3>z)#[h13!a CL?nNJʐiAЫ zb!92d=C):LHO6=53jeD|As!noșѿ hs^t U6n\ ]P5sJ.F ovM;8!yMozX#BeQmo[a״[52sz.[aTQuJ6Si3{7$ޕXTGoJT+\Ū*7I ZĴg̪1z³9tؔ!#)C*IBz?}lԓ/{ oy_y8Szwɺ"eqv2y#a\Rp|IMj+[0ޞ4u@m!Ig䥧 <*nlM "Jl,'Ÿ3^*M q9Bky-QGUxr2?.< ƃ%Nvn3QH(f +y-|lFA`5cFnEO m2/¿Y|>5ȅ)=y?@_8/G0q.3d(=MM I{3@]n(`刕ZiydyKDszbUOdtEO GIcہzőGi{:n3.K_qӏf#r1 73ZhD:vV(+ҒKEq?ՖlUC&@PjJBX!03uĚՕeB\ܵ ˌx re"с (\(@m6eTY,e Q[ uqJH;=>k8ɏ-~|ш ߦU&@,!$s֧LU!,&rw'tQn!9W ֌̶ h\*-p7^qʍ)`)aGh&`EC(fLg%Ou=p8$;\Ɍ԰"6j`B]A#okJ*dnQX *_5-ٜ3g% @L r/Q@6x&XM]nCy 6&0f:s+x5 )ԠԦd̔kt6e vGc2u:cCMgɇc;̸` 9"' Ο]pߐruB$ Y٣ NCb69\F Iʪk ;QcC a=qг$.!CxØfZ溃njh-@NxHӈ\*#,|ڑYN^ ('_ߖ=EgD6=Xa_lxǣ|d7bEӷ&!2Wl Nt|:B[2ʊY(:Q ;:z7喻ZIHTK ʚ7HJ~δɑ^rϗ.ܥ n^($CC:vkqR=?ibV6Jrc?:ѯ&ou0S*M"AW"(ӍwUWTQcÓ3q+S?H:p y$j?=JwӡHX:}XKk (듓$eF}%)2[;V^_WrT@zt6KuHtJne`5xl^(,3ϞTY!59@Hߴ$8smlS75=6#7TDШ~h4'xk9+M /ޅ=h=VYf_u7_ 2Sv?;B#ɧF֗GJef=mF0퍇Ø]ɚ-bA+@< 1ӅH_4x CymhcӇL&m9oLW\Ru <:7aSDcSKIEGmucXu'=,V?*2v{y}qƀSumt&ȳ(uDH w_^ȼ4Eb(3_>߰#1(Ç]kNe&'vj@譙{3G@Wf$izxp:F*4 <^|Ә wGN^#jڝg pg"~5^4O9/O)p~zB$dUc҅ͦ2|77}XYVwb|UlWh"N"ЋPm~>*,*f51# .ۋ%sVY!#(c9-`7%`cтn`aA9,).OkD?.6;Dʄߝ@.ՙU[{ƹ%DwwP\yu{aY4hcMK#D*t$ݰJe䘮v'BV^dM4Y~q^ef9/cn,S8-$1kC; !X:x6Q iY,0a%)sZYSC>LH JۍQ=#r0kG񺧣>Čhhl2`!x X =6/^QV ) U24a8kXtX.:,JXp MFH&}إϮKiUXܶ'5lei ]fy"2xC]y'l1r5(J;hjXfmvkUN!WtWE92S"Xy5-Bӌ/.zE3LB s25w~Y&օ^(/E/īQ80}+ò ]xbebU4Ax5' 3T'w+ [٧`"ݡy㮉=i1zNJ}t'$+^I9Z!+kL-T)}^M-Kf,])#IyZ]C-T#ȡ:2J8lu8F-[x ;hzU%ض 0M&E,2AڃP `*J8p¹OSgwgs\ƜªsZ$M̀U| )I{YD /(HK=ZIu;vYn8sy;?3C]"°"`@\\t@GL٦zV2!=?I#wd077!4,\/fWadUzY\̡zXH ƉiDÙx|@@:_ d~Bi뤊z|1"c\NT^ ixj`~&3% S X0֖(ܚ^IOĮCvoDd.IX8O ȶjoe& VGڊA TXIl@hKe6I]ܧV`4TUT={ջlCֺ=IA==xvބ B>&yQpRcn#s/X~#,CwY~_Qٛg4)ƹ#ѪOtV %q-R/i.9miR.a֞$4/H~Be9*DZ0Oby aVYK<ܯ4K(IZG*57CeydM|`Rފ?H`dž{A*M`xKTzXA2h2FoIfD}qng2Ӟ_MܑK/~tU!kڪ៩*R`1/Lڼj'd$b61X4}ol=2{ rcX{=&#;lWOm*rJ`%)]Owf]ݓZ FSIGC;3D@ͰÉBnkvg6*U( lAMkdfx#~ r+]V'Ƿ'}e eV1>9a(n20xW%`IuTwNAd02wEڪ٘KL=ƌ"|;O\U> EuG\+a+B(h띠̟G摟))Li l ʬ?п23kF~/9f8͢:K7x=V\ 5DsDJ3Q6YM cU H]缡!L8I,sf&g4o$# +?&$VBh>Grٮ8 `IԭBEWl<.i^; q]W7F6$ncjyndBD 4'X(>{!bO~:Ts B'?j^vvBkA3 EDAaޡ֜4Ͱ|˱t{ևhׅOqrR x%-Bdgb*>_G{xn~en7f1E?/@Ӱ,{ ؤJ7[HKf )7b"y;2}TmW+Z}Vp7 e (YqLY) ;4@ViMcTezr|'0UBdE` !ܭܛol!g6TG#3 h3T.yX`)f'm4g zun3Cÿa“N;Pf/J7υf;viHɅ~k섋4]y/B]6i!T)KM_VZi{ufmBqrnʋa,K ǓZw$EJ!Iٖ g&f37ZWs$xIsB0OFz)7/rGPIQ oƅ{_8SЂF ҅ʍD Tm*qoJ4Yhl/I, MsB|h͂jT[Y~oεӵ);XkU[j9FEs(sd<"&*?rWexJ?yJM%sQrLTڐ<ڰabhCVr6G7xThҥΗjiѓ4ϝ[.4^dKc!*S#>\;Y$LM5~TkݓbNaќi86Iȫԋ+|rM#NNGj8(m78M(= r9ƣSI^_G0| =r`낢s(zõ~;ydOg5 τ}.5 lx'WV]/]Vrl*O<:xiAEe=ߙ@$Bnt VnЖ/{x>k9kpYoKFn(oSbwtYÇwe?0 ʗQB]r߼B6B^ydze>X/czZJ;>V &]HSD7<&JH'i99Z 0qIdSw04FW[ܭasL5혭],pGW*/i.ͤugib[aMRpKo=7⼐tE6E7`.+|håDVcќsNuYd (~~bw*Z|LqV@Ҿ$ܼzI<0A qe< } wYC 9oP9ArpםhȪF"gto8Dtuo_hG.S-A45.Ty7t7'Ne'FdP3(b7E:Դ@0;j2o6HS ƃT$9"> uY0K$xCӼVC/ڒõ2yO|:VIoa,KO֞GoAeFHbphsO#+uDr{*R-\\*7k7^~0QhHG=[ j>ֵcד'i6nK\xxC0Vbi!+,#TT r|&+%IJՠOn)3H`xKZ3n]ݪf8{PvlLJ<̣?WβÇ=~{(X 1Fcݝ6WDè ;L1ȑE8r|X!MO.&P6=LǦVi^l~v󐔄 븋Hיo^*=Y!>:D0@ 3\ @>|YZ=ϥteSb<BI]቉(&%O6o$UX$]_JMkfk+9?cUF&FZG1=zexaO)]D]n1)tY92YyjcRj*&(3o9˸X[by:m gJ8+I}諽ot$ CA?z'8U9M}Ogq=%Q  |WrhqJWl+(NҚF[VkR}1\NNsY"dĩ'UI``3ҙR@g5a]hSHZ}uf 53XYGA/E^bwݜ\NR(;mo~%O }9r"*gy\jKR֨èK"y/\t9w3D2u 2j{8ڲX-qx,2[ӲX`/,Fr-VeiΚ6I_"~ *)#7tějUiRRESQq˳RB'[q^GH-%  h9v6|DYvc_YɘӤ9IB鴤ACȡKNOȑ$t>[8YSD IKnͲ3 *7y2ܚpoD17pTMhXb͕򩂙>]} H?Qğ]}z>9ygZ?9sh)*5 ;ٻZQ`d`8ޏ:3\;ihvpZ/|RVdAh~PL@gN -/US Ț˾cHxW" *HskjsU;P28T,7^ͧ,nU o}#;+0cB`in'g-9_ -[ĨT WaYܴ mUcjTQ$$Vנ:$wD` ljGw3tp&/2d yuZ忐yS;ysYcTڿ=lذA̔>JL˚D<$& ٤_A0ȫ`q4cgf9w3o̻. RsĻأY$!yiS6tjJgdZ8ˢpO_]dɡW*L_qN!Y&,%`E)Nkd@euwoJ} 1ϔڮd%r{uahYgzMZ @\Z\?9R J6Q-"c*^l;EV *tڍ,EƅBH+uFÄr2}z:(Qh#q7.8tSsGS F@2G%"c/^*OWYj*G RL"59VǬRU-CZ,`-ULҖS^{ڲX5&u#\A9G SN^[ap:%bRj 9w3poS`F?V[\t(1(4_BbE|lXmT/#Z{a /wv>jTB46h}dߊ.nџ;Nc"ar="s$pnnFړkȡlk7COv~]u\-v\l_Ù/ѣ75!>hd,Ɠ ":W'U ϙv5ŭV-^HI Џ"E$ftȻjP`Xh2vɕAGtSmɫAސ~sP I9 |h~R2K{6%E)-] k ŗHVʐ5i P7f ,I 6lK7l 2 ;Lk^Rbkͻ"\+v1h~?{C8r kAk: 1Do? .ZOnŵ f&*L|8>+1_rymϯ~#xM Q,Y%BQG_n4vDt7Q/vϒ3݈dJ:7GqQYu.⭊UlH !:5g Qb빺Z8ڏ>p2{ KZ]8c{B4d/ՁA2`>0DŽXzPK Tmpb탐l݌3 9J>:]9jLVi;rXRe%4 ['}M+Ym`4ϹJE+85qo*!4aTUÈzWV7D@L:JJ')z:|FH9bir;S#AEiVXt#H_Ǘ蕍UGB4@|3kI#g?Ru4 u 9ci&N^ R3//g]׊.@'?zrEʟiX#X(`gR&OŗJuU'ØadӉG Pjfw)]Ӥ[-őPslM7ft>.D8,V3\Mjqj(9簌9*O mPmrLYVI8Z׺69>aH$yJv[4K/ubkn?iμ횲}::= [YTDeSYL\lKJP8RB&2P *+t2uaRWg⽤ͯr3֧H.ҬTfo0h>TL(Xn[hZVPU ;~nOJ##b N,..Uvy~JdpCë;0 ~{Xv12 d=_F2oLHtc>ys d/S^O+~4[]Ɓ$/YV9YdA1t+)Vӳޣ*NNWIxWHq7ePֱ)^ Q'8Oe{-'mbJ"yeen#"[S%WsGH:|I12o!/ej>Hޱ43HȚ VF11zI*U_)ҙ4Kk% +>ְ VsN̽ (vM$VzQo;+ycC gvW_k5#>ǓFI,p|'7,ӄ›=/WcgQ ~^V.fg݁x$vcxXL"Ukq H@-+E9R9H m^rBHK%?D[ _ &M# d%b4,:oCzðO27$m‚frEO[WI]|VP;B8- fzs}J&M&~IgPKBatY22~&΂_P_P~byeUsN\:oo%qOWe*+!t `Ad;XQ v5Ry_IMbe.v3K; ي}3XU.Üg/ u"8q: #9?w69o%@jgɁ!XzF[^j2ٙěe ryrF29l GIe^>1荝(5!<>^P9us\_Oί2n| dB@-Y r˖oܺ6CrA$g'oQ|gULL9G_#q:֞3D'2&>iIkw6ZkŭvBOqA~Iy$GG>oOiO?፼r)<_6` si05 o/ZDzDdqޅ?daݚ"J {">hh VFyѓ%}: g6P G1~>ƭ&/ $<;7ESx-ކFTH>S1OR ؠ}n[~7.VQ 'RadnG$#lu_F7&= 9cvwѫZ}_˜P")X%JD3!DX s_FdՏ7.#MTLWzq̒Fæ制4i>nKk;ZVJq7KVe7wS'REwDb2?(vX  ?yaR7#H79‚KhӻlwD-{2B+CԱ;z胿&qq-JNʬ$8px{e[9\09j$n֑Y+Du!w<6}Xu@mdS<HtN^} T'2^uxO`{o*u@ZLp]G-gT&k逽Ύ2Setz)K)̪[}2(m_'KVo>n0o;sΡ+xb2$cu6gq0jK~ *XI>$eܕ b+]f)TQ{Γ'1V24xqc}#Yb{]P^Mlk~q8)_ \V{8ET3K4-*f!ә_Cd@4sxyE߽k4m?wgYrUxeHkTsMy+WQXUEpU"*Ȁ0bȍkMČh(TU@p jϏ3i.>Yd5fAw$r|w6voʻL &2@dd_[fe{S8SO8p}Ox,4؋Vư]=31iLXNȍ1 IX=N[\|?Q~c[\10&BW:->߬7Yc|& QYdKUh%m?m0+É1"rT?WHFVn F1eR!z^s2hH| `b=DUEV<} RLt$.DWwC_ yGzg'&O f~ipjjܷJ{6kk&|my1%&BR'q'>r|}IcpW|(SϪ.c}6uX+C}Sʼno|{2g~ug5Y;҆{Vqf0{A}?]&ͻiQCX`Α> R㖦E螬R9aUEBߝ%Tt8ޝ . I˰ΆIbp8# ј#f46uZݻ3He\J&b # DgpײgTG\P72%#-o_wWqY q#-o=Yf:+fO * q~kfclݐؾ-țR%Hff*UUyXw]ȷ R P VXg,a:xjgz8*}R"~(Bau "1^2NaAQΛA[$\|kBS%Ľ ƻ{OYD{P/SAt%@9s>>?c$4D(W.#]u$J/xR*|]$T{Va`$ֻ)c,:`;]TTd[ |X EZ 0& c `-|+4V1zg"o'Qcy;7z6GB2?M.d?Q97R Ay'$Ѱl >QW ;zIPEh])޲C0Gݙ'*Lf/iqZ6s&iuJ󝚎vy I:w_ߔ?V?\ck.Zl/kXf3g*0mϹpc"HZ4Y}!ԝ7%??=:W iSnyKAU.}׬6'ʢɨUqO0._{.! 9Ƚ/XZuQ3򉆶{JWw5[(Gn!B"0%GUwf1*yâBҫ2Ay`]*c T/g'/:/ӂM =,.PXuP+DVإ`ŭs%q1=r$Py¦ $n*8O^F2py raĪ4a| 1"zR)06dQJ3}!cwV fpa\Q־Mg١E2SD3$>u0#5y7ydY zP"͉"tj3BNgS?gaT:J120P< 7 7h6Wz)Ƅ7 ?Ʊ#غ?_ۑ[,cÎ熘DzDNP+P <ՕOyΛ+Lj(|4f_b§@Y'X);r3pxH?z K鉜\e&P-0XcBo1)Vֳn]%4Xl 'Hǝww5thǵ <ͪ(L5k0SRHYNxSOx0NV-jeHXM B%9E_]d{ Ni"o㲝,.}'Bk e<6r.~ Ejrc&Җ+f<':Hv?0dUd[:%VN݊& q Lg$-EFt ?ÅD<4f[z±7GRvz)$ΑgBk-#Oץ 58HwFKOq9R9Z"͕=qZLHrތ4;hڏ}ۣI兢* g@AIŖN"+B8czHǺ|fQO,T*ݹMrޛۤST0 0>$Ǟ"K54MO,nA"eбF}]{6F%&Ϳԇ 'hlۆmkJзP}xo'r̨t \9M뒕zD7'ߙ83d'zF5^ebmIspo2_$;ӓF5՛&[!)`8}z6]dsl8rwq.! jN#vχ2A]6!FwP'>u֤8G&n%Ǻf^cXPm:qڄr3RsKP M[L>)|ɝ41TX/P%Hި޽ȦWӇw}Mq"A6EaިZ vEO :x߲{9󌁡Ig<@V0tFb,ģ3D{Qw$C~mr(׎ yB #w, 0+}j1 8+Q=?<%k7'9#66E$ߧ9^'s<34U.q5G5z^7 :2kぜZC!J칥fټK_25 Gֆ'1Y2&5q*6~!; < )|˜5?e3%;_;~Y>M1ߡ/1e̔SEk ,c'g03ZcRre?1`ZcSd"'UMm*扙,"* ŽVg!fӘ3R @$F -]0nH ˧tyS3 Bm^My/dQٸQzkD6>ߺ&t&>Hyuʒ c!pb1BF*kyw"q7l9HQ9d /ıFU'L[8YImA[㖢-*8.㭷(rV :WzpM`,Һ*fiIܱG _"*z袻Kњt&8}oPuD\2$V\.'(eѤ@m#f}2uqtM s7XDYkcdbbl~s*(EYyJ~>ﳔllB};pBi#>E\X&WoTW nN/| l8ZtTYK,mw2Ϟ2хjh 92I8 Hw_ɘ,%hxaH$ Xsee\H\O|ӏ\-nWH[B|^خb+WJa`duBY%Ɗw~{W_8>H[>f>ExfXcEbv2~;OqòYZAp8 gKr,;rڿ\Gڔ)&ivCJ u gyiَ컼Lp† :†bi5ܾSwˎfcak3}d~Ԥ4w+nᆾ0 PGa Dx,\4@} W)}:! 6ujqƝmfVJJ; o-w/$Q|:~0JΟY/Nt$R{;tI-tBl6`7& O0MpnWNVQ99o<5])vQA5?0h}A3/❫3?7*Il< 6`\8ɨPIG&#bBH4#A YAPXI$rdd;Hxmr5 "Fd.ԟ:#L_g.-9D9nu1n0pPHRXɥs ?‚2 E3>6_v^ z˜+ uj(̛J R No$!ªC×c<ͳfv[ D2TjSIā[wzw T$Afx@jh aG=;_0cވ=X2@SP}t<9U@TF1JEX.vn A#B G40ԭ&=#mxU,ypw#N.=>і.T*G7L֌P+ɔ(.:\n%Ԙrp&;y1nBa ˜ 8 D^-1N~Y]5s <%93(f*B?2j Yoh/?_!t{K֊P/t=a}zZG@KG[>PM\MsNsX>`T}x)2/SGͰTy{|ecXINwu I`]->Z_B<|l =+OM֎r/}OZ/$Zm(insq7UhNqskB0d]$< !8bdƄ4zWX?Jax2kc~~T%/ N:@XG 8oDr=*ޚ~EEVZvB< NVh<ۊC8ktfTh~`DʗlDU^ V> 3s1* DYX2[Ɯb1Sa/='ܞzM^;9/{^Qo7ٵ (†fO}JֽP=>f gJ#했ʌЎ>8%KwZ~JzXD8msÿ."pg:i ùV690bRi? gыuP]C`Z+".U^A i؇!c oϛ᷎H,J8C\9 i(n!Ե{Bzz!,4' ۶-\>u?cg L7`xNJeE.;}"G>nݪFTiޞr5C@J$2#OU_MӡlMVMw'Տn8).O)YKؾ')wT|o>Ss.34}HQ?H䩲B]iZiތOӿ&A:'Eiߑ yn5(W'q qW@g9nd寳G?kJ g̝Bm85DЦ8.=МEx&Ěyf.bp<cSŧo׭"_epht$3 3Up;k,xFh.Ȣo{TXqpXWF9)x E#6yo>PV-e ńq,$ G[wuwGCG5)9yR7v4qX AB6m:)Qu>&HTybBkmpM`!C5mZ n+8a}0}cmzZtf%1b`KbbVCLЬG6IN1-0n z֋45>ۊX%nx*B$T5oP`Wū6;KI" @;TAcZYzM4gEGh喝rK/m]=Ojze+<(͟r@ws2W$S⏞3IYYD"N+PKR!1rRءN3Z7t w'&'Nr6axBYe O5GC'W)Ԥo':~8CW5F'2SÜ`·(*Tg_@VyuN'3xh(l:/?{>1.h$D^vk\ {YGO9G5p>]_ y}͋}F$Ó󃂨{H;Fftn"~t䰬mÈg:o6Wq6EQ=pmmWf!y+9Th"-PUN(|qhLog~N0rBr(ҬA]Z]yK"z?m :ӹ7b8r9}<6š/+^KS)‰DU3=f^*ǺZ|OO;?6 ;& ažwVy ez~ҘORPG]r1@Y6eL O -Aqڳ&o0 /^B f;hKgM { iGja)ʼnT!ήz֠rcѯ643krؔ&K,AQ K2fH^fx~@a}x.J;P07}'%당HE7Ez>UBD^k|X8zuH3&^RRklN̥(}fuC;YD_ʋVo[ZseU%9\ B`0`kEN3Xa[Do qdDB áe܍`ET.1Nvo@ߞ;ׇ;/H@I1%Q4nFۯt]٩ Ob}`H9?СӕXu@pУo/o]wƾX :i$$kϪѡ vdPi=zmgNzHgC+$Lum~;t.UV+]bdB'sAcL+9oAlsDYɉi>=C~?zٟ!'Ԯ׾8G|H: {5bj&\g݆܉Oy^3 iR휇OI̓HW]UW8өx ?]^kKRt߿!]ĩ K)V O HEx1yO;v߂dԲ M]wiTvlWtRib- v3;+vE(RJIM*Qt;#ådHmh}cWwIھB#Te'sCduglJ$N-`MږՉ֖@NyBOHw>~B3a Xmܭ?yA˚ o 4a>8/_Ы;x*P`e[db7~D ,Vs5qɗփԋܗyV7?V R_es5+x ᇼF-! >a2iīs>}3YC_ ֡M帱jW#U_rBa0zVJt[3ĎBՕ#w1m_i`L;NdH!z$DǦ];[ɺѐ.75Y97cҲ[4 '<-W&Z]:r|Z4_-hoMk.PmeVGNzO~>MɠjRNY{2_Y۰Rư%-m7nݖ|}>ӍLnoȻE%y<׳!伫bUλZW<0;`TbW|sn]ڇ88BTes; v3OE札F|$H`p~*IPݝ*ppM@pT,˄[NHeZȻ#o|zpVU.;tO:}ʤ,tS?. NJ:s&%^Y$c4-ŪI˨Կ Z1mIL0)%I[.N:Npi_ trVn m1mCx+8C ;jxqSrqpDTjJ澘_x^ya㗒#_C>GJ5 *:Tq7ho߻ru,>s#[!(V>t66ƀj7+Quyc k?׼6q$С`eVX!y4w>o+4ļ FmIBiKN f̔/^[[Dm Xխ)%tɟcdt}|V WVZX=5󦙜?9_ vlTQU[5}ڲ9PiYuwZ PG"{O%B#Uy5e+PsoAM~tڜtQG(u0ҩ2f6yU32Y<[M#"WrAjf}1Ilc['&#HP\A%EoL~BҌ㼛:VO;̂%_7AǰZ=1erp}/! tKLTkwVI6z_p4̉ V?"p~%B͌e-ܙq"fb렻$DRRk!*օpz&),AN9l+CfFZHujFYW6Ng?ޑ@{SQ\fo/l^­qoO54k󖰯a`-BM%AJW8xuĂ)TC]iB:s3Mh,8f6å?K4WPn=8߼^xˌSHX5sa$*yaýZA&Λ}$ѤZ>LgىEynL?֋Re _c: T·I58yQ(7yɏN_͍~szuG>zixm&nj* ';M7/8`f՜qr}[@v*K̳MT)gvZ|c1H83.c[iy=`xqBivUޏ3ezAv" Ҽϐ$? zܫ$y8b7?BJheF9#]UDY|׉Qc_>qbΙ(;;ˉ3g|. |5BPSIAɸOg>mj>}}BR\`68R]ҏC(Xrvȧz8F$LG+mY%q;Hu(unps&gX{([EyC aO%$u 'Gz8o:PƼдD uP=MeΒӋ'gu%\?u]r8сZ?&4HMO3Dzw,'fj\3ԏyBiF$?7|.JбzGL\/-i ƨ+جm 񩐯GCQDmjsPX}C&Rg^xTƷeX:7<PV\8z(ttԙQ$ւQǍ97e= `^W#9wU9jקQp[e3l#P֬Y"CjΚLHVv%=x6lvr( ;-cn擤;o3[ c;8#D-RG'd6w+΅Ƅ2 %v +3ĺ&(N˓= " .udW[L&m#M]'"u9s6]h{by>QBю ;BXO{:*_s ORNrqBZڰ1sb`& =?P؜ޛqxvG'Ԝs(acdjīY~QES7@w yLir_<&=VsQ YY\8ble*Irh^jEdиJϹ·v/t<չ,zlz 8h$keW/3,X`Cy\2Mqb hAdԑs)Mx/}zuڻ˯@ 1ς&-?? { \a\1uUl6TO|l 8IzSkHm 1 !iY|i˹acTg dcWsN k{^>`S/IUphY8 ɷ1U,8c߱щCO>{ƌ%?Oy,櫵oXh,:k&dyG(?Dw"rӦJ*K=E0Sȩe*]^-c>)ѪU'J B u j_4lf<~wN)|+v\]W|q9E(<1A<@1ӥ kn…n eC4XrQCCB Dם0oh议>3؁*Ex8 C%wjI(8_֧$ۊXݾEY fц3~Aɉ`V3ILY#cپW6w][KxKEso)?$Nb}SFNyVӥٶ$K@#G0nI$]uG? "a=LVڳWջ֩QÝ bE;Y|ne;~T>14]:x| fEE_3Ԅ+f:b?k:^:wXyY%[B;4@:e<5$ / AΎ/XluzvVN`e֓˿j®!ۊn9؋XTa?WWs;| GKbmސ{^>0GѕʚrK*HBTQX'PpR9cHwSSt m<_ 27j}%mo=y6EʄdAlA2L*6I}L #](!:,Z@an`6[9gnZ+ _FBq0$$2QtÎfjj]{/zwbU2+5/%Hя8Vc«gב.!NW7%J/F Tj|6N1#l1)ZI$OU_oyqrGqyÈADeLr 'St  Eqt7+Ց)9igϝFm5 w΅npς:)UlāvƱ%-lyb:T}wfD4x i{oXx*!U '37pG 鶞,Lۜ651PQNy;3'9+t<8p )J0TiDd- Ux!E:dȅPy@W9XX0mZ+yIW)9SqniL'u_)H̝Ri: ߠEI{v)6y<{]j8nʐC֕:׿9֚ !XcyV^/sOќgȅ.z,<ԖVI6|z"!hZ.GPg.1?B&f _H'5)Pt.68\ hHQ_L#- :;#qݭQCcxƴ\xgi]\h!%mIygl7B _о2jыӊ8!l;r3i [Dnl"rE)Ջ# `K!9 zZiE/bc^1ghؽzc~1cvpZ/Qc/,ړjVTMxnѶ;DP /u"/$nD+P䘼l<ѲBیA~Q#ðTRG+8Y0V`RxhfN tSfP긡Xu3:Z$E:3R ti5n3f5>J7 rM< Nγd;r "sX] |a3]: a=%6dq"vTb,meҵ> kpN ;M!)Îʥ &B=t8 ޜ_g罕^UD]|ŋ47^zMR^D$UD"+|_> ,6|b-},wn`[oe8E_" )ǰFS|Ju³Y*0B,Ru94ɜZFCT̓Q Ն)]GNsn_Y+:^MIJ@X׳VJ0;Org] !=}|#a_PǛW~Mb7qY'8Nw)ݲnċZ.6{2F.+CՉO["f2#ZEĻ/* (8(_e̶<"u76Ԩ]`]?tF=ƌvtg8,1=gv/Ʊ_ "F"T_6ܶ'!Tbsb^9_\ V%_ݝ=Fǧlڜ^N6:q$%=WOVZdcv26C$U0.[9+dc&*Y=*cPIB֙2c"Us2iƗKoe go)V|nWl+-q/H!C~<6q阤&Цd<"OJ5A>fU#K+4oNi83e|@/4(^хI?g qI ,R[ԊpRqm]2'yEkBkzYO'<uzGro4ԊP*y~ W2kz4tO|8ar:hc{z- {p6W8}Z>7>MXd7$dvT>ӡ63V+P?W< :]TOӇš-4,%~JsrQD@fOP=C~F[jRwgtr9֝GAJ7&lkgٽf/LjhcW.+)OYc ۬z]%GWkvs:dtБe;i#k؏{W+q$]fv@TG'c E?^ Ie[k@a?Gf6L@"Tߐ[|)Mm'8xK1}3A5SZw#aг{Iag81o>cѻ``D]4xG7fa"dO-K?&&/W Kh"^pN[mDxX>P>b{MGo1ĬHw]>Sny0#i p(SV.tTKFԹiG껧8G@0fr4e̮~ԯ~{͊{w}&hѰ9c(G~#[. nX&H䅮 y]x \g8FybDzIyTqg'o*gX^ /'N)¿`}>8wa?eГ!狄E6qJӻ8uDXrI(f~_t-1_+ޕsg-Q?(uZ(AyWXp !+իm}Я8'uNUOpVu26T*C)X_wL ;+(NW죑M >9 #=~@Lot[\%uW,hڥ;ՙ,[P~Z,,!tW2;I }e:874j,Y5&JteY.ߣ\ӿ={8cj,bV@& \&|ДÔ5[~:;쟈#-{?݇Ä+N*|'?'pmq̬lh!V7pumGÐum{$'%$Ϋ^f.AoP EmT~vt]^LެYm$Mv;fwjyB%}=ly Ssdt9:~`کE>4>lnHb}P X\C-`}Q `"2(2 V};d?"Y;Qju;=7./R||Jgq69x%Έ&5Ҳǿ 8XztB$aos:Rq&Ńǂ&b3x =t}i@7!3Bѫe4gg>[Coo!Ω) "UJnY熆:/ ܟsk _ &R3IȐ\=DvwTSG)C '3/F 2U)XozNioc>|\+G T2/[WĔ۸cǹKbG>bzX͘L/L:-ŋ%}{ Rt3d :} _@QKyи~1aoi~ 7})ŋag Qd62ơ0Q!⶛Ƙ|-]Jt{gz"6-T#Spn@MmH5"Aty,(9Uҋ%SΤHiAEi =e7C]/ ,: mLsf΄f@WF=2#pGwtG{d";Ԡ7!/tu`%+40 yJwqv  F;'MܷȟS2D @ Q  ћ7W^"sNW%\wD ,rwl(>5+3e뒚n@Q㚈HArIB%hC/Kf@C(_yawvq 浴esN GOujK =!zX y۹Ek9#s1VSo֐(䦗PfܒTQtOxN!{iHwiÚy0c##KnGj7 МƈlT^tXP:6(zPK֮xFVf%hnvfM VWv CK@עvaU:%,%Ur;BI@/.*VYbZiS7vǨH8.R[#| 磩τ9&߆R\{@s lx%SFJ ݘt 1?q!XtPYP(&Ju\g)|6b7spޙ ݮ >'BƎkv?uGX[9<-OCrm%2{f6  ۼk:WdyW ]q[ixY'T*5R,5шV?88%ynPW^}=Snzr+pB -?к,?[:GU|ujǢA73/^F]KT֜$ϔQ|기0U3A𾳞m SI+; Lpl; "@09ˊ B/U=Th~Wo DhϜ7N Zk•)X!uҏG|ּ9WiR^ʹ.r,V|"n|3%o Go0y+4ԝ3#^-UYnzKd\zC o\ yc|su#҇;ocj32ǭ{̖)gd<4= |8qQ?͜Q 5Ͻ2rM\jy*ΊRc,Fk ?oKYT2 >lJ<{r~nI{i,0pp&VĒf2|fH{:G80Á}ah4 a5LF.dۀ s*D w?#4mG6´860iݩM}e:XD~v@6\QÛ+IJ!DFZfĹ~Iy6.rur}QJ]dqa=-mN'}:BΗ5.2&bD-i帨^[TaeVߟƵBkzȴ@dew8[Pu6T&kS =:nM1d}c\~X:ouB$x *I8 )18nǨn5 Ŭiz'ccj}4udΖO6Ud<2SK :w%4< O& G9D-4ͦV@1)P~eJ@XZPH-}O68hĹΘQv~_xBn t`L@#)MbA7,*>s6p ALpzC&^xUY!g;w9=SCkԺ$5ˆd?"@t~õf8q~ҧ!d9t>Hy%tnf0 qܩ:x)c| %E}sO 2ln=B8R)iRqI]6%WZzP$ٽ$sm4u7"~h}-ܒS9`y_sHvTHْI}f'145AsS'"'⭩30 34h-67`sL\։I]}$Bgiٻ^Ic9 k֨{Q^#_YEaKe;{|Ї;i7ϝ)e m+z ZfsO4*AiLI_Ma=vn9vnEr>&5\Sv "R5!p8/Nˌ#ttS[wn*;Kx$̘VgV[G8Kt3(4&>H@:=p~E'Ii2N<ʓWΞNTU:q]՗dE f1ht5VWQY!֝z8ZċB;$n0莹` `^mhCƭ@vhUx(!kUj܈D~d^dE9n=fI~<#3sy\2◚^';7!Ð_cj&IeOodȂ1@9 Ǜ@kEٍ?<%DP ɝ-k|̚{K~:<3+j3Pї JƂM;QڳbURli@:뒙 tC!-̀3i];hs~:&*{鸬I+:NżJr5rbUPd0^epg3߄>Jtt.LFHzvS|e'ugQ -HhYBGO$m9m%?Yj U =zAgR.H %~h$1os|fdGIyY JP@P+[ۏ67&'x ˨y `^ :?.:(MXc(] /A<čI¹>]d;VFDxw]8*uoXh{k)e$eBMBAWΓE"hQ E:Ë$S63/qE3j-T jssq/'9 Jtƃ- !v 9|75s^RWfsz sM/^Syg JyrJug3|@)s,Obi τtX39O|WtFr&o"J.r7qeL?KU+%04Cw1fd^W N"g,S \]j Uȕ0_r!m>b#1oKM~2~4ImU(Yh3"EG TK3tw"㾲LpfJ "6;%C`0](!WGV֮H/pnfo!8?yR0AtAوXkpy@RRNy^wԱXE`̔4].%dى<->/hj9+V67J[.l*,)+Y9r5}vtg;*SԄ:(kacf,vrhO KaUnv|%ؔt0] l`3{: )󣳘rOyq; +jQJw|͟[T7#6 ,%ZXМpC#Y'\՟j4 s0^S`}<ݲW | tA*÷ٻ܏TI'8V ,1+A ky42_nt#m.C''7ZKwҖnO_U}? ] ˨!k[޻>v«tL<̞Qw1,e,]?ʈ7疚%YrHfEJ~Tu$Z&tCݼՂh6_#Fqh שGW>-aȐ6@o|!sY_'qXR q6J-f}qc=N8$GTp81 `;lwMndףWtR~ᙷwS̻g~5SLN6ê rOK;0$]xTV A# TI};3T(tO). r%29BfOgEډX]l ڍ~Pk.:q{ OdLAqPY,lR1 ޡ9ۻ`PÔ1z2zO'tZ6C%lE~bf1k/gRGWrp.+봀{lǪ\gO+ϿEn>+JFn@W@фSnzG/>AnW>F2՚0L5Q":]xw џ?p$zAK cޯ+5i=ГΙ?a[B){h>W31j+PAAݐMSPSKt;Z cBibDj, m9['sVh50_u]d,]BZ I0DxwUL)h1;)"7rƸpqq8N:NuD {9c ;c,G[M ܄E8T=-w? NxT'ʅ7SCfT .2|dbU#Gu|j$ҝ?\L Ƈ*u$n{'sxgNÐ3_fɑC{|NN]jȈmi`tlivzz"'׀ڬ M㕴$pR 䃩O*pIжqFr h;8ie[E,aP\50>/m|sR&S"6DdL3;tq hhĽNE.xS5f@$3qQZ "w; _N%W&\O*1̨k1MED"[,;+ӯ,A8oNkh6!gפc- [*;_]EUIN-ZAOt(1p1ɗsLBqʣ tY/+sp ^╿C7=ڑK)`sMcXd* [HUS9!0~ VB9(sKVmOws ׋'|ڒ񬿻HU$ΰ ;CMivx,t[ȑ{ z=P-&wkؚ g\~Ґ֦VHh#u9Uě##{dLbIᵕ72r}P }y9y9AGKG.0I]z>?%aP _Wa>D21/-Q7 $uʐN-}G_D0Q]\XDs-~g7{ʰ]x@ӆn^Neb.cqOApX8!vsd}ky9_MwTKpsW`4@dd] ^.W645_[֦'?כi4m|uxeΥ4r(?4ݴ)5i#Y'0510vdl:1F#bKX™ڤԴ{sLk"P]K6@;B&U);OqA*iu8G`v/*E~piGҸLhVv@׼#4So&/g)RW"15Q4lGw(ٵ6}D٧>Xaǝ"Tt)'IIKWz]#{L<#1caMKg^g#X@ώ.~:DAQAhS¥U=G%1 O#|7DnQ=e>Pׯx 4! JϹOqe:$̢-m")+v'T,@ɸPpAw=0罥J*m*!t 9F/H7V?VS |I37X[i=iA/ibdϯQt8ע5W杦LC%w4FXBޡ/ԜWIر sDuUVL':w/3Na'0R5Թ[,qFzr6l0lgoD\Lgj>?rsni`>/N _-#vPE3tĐVAbzz^rpQͲ4[D(Ug8XUUn1=:i ɥY!~8%fh2Oc 1$|>~W@Ū1v;RbҀʈ:=%Ӆ"ΒC8%@454iN2k)LD`Jf]uD7Qm_ Ix0U)+ibRxsi7Y%Ь5Ӆٛ7KPˌ𖢜YS/Yaag쐎.3<ϰJ *K/˺Xl:Sy4+wl\hW(9.؄G ^e! 2L |>$k'7.8E I%Rob36j]k$F2=9f 8d46VnZ&/ +"8s${.:V~bZ QfoC+iz;yxej888k{ {̝LD}J|*Lxg7d/<% 6\f3Q1ɨ2%BRh-ȹZEJK35zez9c38>d<M-J\xr~>)%IZޣ⽡am/b7cSE|<]~5 yUm8SXcyW iFՇ̜R8E=30ucOݚl D}߳^Hrqt@8hI0B! 8w+vl&B]]}(Z+xI_n5'-E'Wй9`h-4C@r"3 էKSw}N"*P  cTJBq !8e11FѡR ib++,,uZɈ+-RS2/y96"Y.-H-VtYsX?I)WRps, 5iӡr1 Ge} wE8Zu|9q'Cu"๛0Na`-͢J^ZO Z? O{#,ЪUhY:ơȆrR"e i i~cDMΪܟ$>53#qfjh]Ϸ~wGؿ8p"r7"wvп-͆jI>Ng\I |VJKl ٚg ^,@9iMhy}:-Wڔu,Ha [FŧTK_9yHVLSd5xU kopPt -6S/ qۚ[B~?Tn^> `K{h/&+=lWԎYZ5ųJ@ |F^mC-]7Ƌh}$+u;vI@WhR7pć&3@8};47g2+JRm(M ؘ_4wgh +F5=;'qvSkEѵlq&ޢipPb ?v:rXM-hϏ~Q]D3\iaY,I90լN0.ғlDwsMw{aDqUW_;>5*w̛9pA;u6cq[0I.T`EՋFg[.Guf捛^nx{p yZdUeB!]¼d3b0ΜPsu0ϰ0>Pg-ק.O+-&5{oϗ =ur;1:~q{p0+4ڃ9/Rڂ{w[ج-#u"1;=Ȇ@ard~ ËSFSv]" kd7+>_K&g cWDkġ SCѹyzў׉ZfuƼn 1}~{0c`q"pͬv=}ҽ=ePmC\Q.mV2@olz&6D(ГS4eld#YE # L)R==洗Md;vaR*KO&j$?Ą2cB)7bDJ \/OskcO֌ͅ4,a,4MO۫(8pS L`&̚';Iw|8Pvqu l`gDУxldDD{DZ|;-qHXͽuN5>. ^$9kY-h`t{.8:w@),[obJ3棁5cztx~H{ʛtRa$S[ǘr!8̡*we3{L!V53 y $=9X|.JuH9Q"#Sm ψG:ƫiyF{l`W R z ~?+T+Ifz5%SJFy8v?;-) WT5iMY}*z/k:aj\GY jkhILG(N?IRP$ T>mRvDgsEoD/.)!c6Oemv8Gv'-Vf;yO6kCهftpRkꌔ?`{ ?gnV٭_${>e؇ʪKS'c| &b'A"*t9.H=o30ha3!M'cbwO·Sk]YKl7}`N&4*-/^$U6w&H~xK`LpNӦdOhI_IG4]nc:u*CqJ(7jux g7ZVR9oގɫ]$#y8e6Щ Rv/Io $=ՋWf|wP:g17IY}$~[n3Ӹ}YѷvftSہsAN'Q4b-<$6HفG9R>T$qU'4[ Fz#ЖۙI"kmq q[F0o4P=pkk-;"Ο'/2*E\]0 LƭAT7-i:h "{ Cr^R=ۨx4Q.FЇsrfj&Q9-⬏IkrI5zgz:#l37 ~,Fɟ^><ID7W*GU>>Cuo+pU?#ۍZ @a';l9YkZ%ytxDr= ̞6!cmIh]}eQzM[{ran&\k G/Xw޶+^oO cy> 9U_ x&\wXyLw/i5/jTn|DfuF4uԙ\ "+q6APwr+:.ۻSbF|^0B(cwy`֌UxҷGBPeRަMIIy~|5aoT^ӌDz^p]We]J "=ט̍z,0螑`=&8Q~6E+&~e{3~vj12iD8mN\cȟLyL~?{SnZ@gpM@7՛kzOש?{>)_i5ӈxjX,vݙ?hO(IXl.eZ'fmRPPPiٓt7q@-?K߀,G}~ӏҡ^AXz:cyfݴ kd_hVe=}PW镬  "56g`J>߿R(gf [b 0(7 :$ފENI~!57)b-ؼudFNt/-4>FxW*N@ ץul[l_c’K<3`-0ԭXaMMS5f4Qp8&Ƥ2Gα3L  uEQgBK0:AeVºR͔l XT~4DjiY-dΑ3 cl׏z)x.(ˎ=^3l4D%RyRȚԭő&m->nY:ڨq-HWnhu'JdEC r uIYTOGܪ}b$x1qubVA3PY8RtHH@0w֍#$| qw}스wR|Z Ox."z =mB^pƫj@BTm#0ukuFi!: PC /zD=L̜1u8bw^k`37Jk`Xm6ϑyeԠ[~E>WbHuHl()œWrͨ=iNYw(GZHjjws3ԛOk4Jz6̔!ZfOM)^ym gsQE;( 'dg֜ί%tɈ,# h)?@1^!w9 x8EL(3o[ngO̬p^vPehr/P$VcqwMҼ@62l\VueL<ģU`k'Uii:l{Cxñ52'l1ռ%= k5LX@kRل8M2BKڂs] /7 @l\I ֹ)q(?Za&5y㼅O\㧣# R[yX|S =etO0. ާs'`'Mwc6 lx Dyu*PtOHc9J N+.&㫴#iͯ]ʉີ|'jEp,=ǧIWVG|Sknx$sJ x<ڥ@^jnЗ\(L5~{Zqʞ[xp2`sRTEKsۼ+ H SJXSz"UOLZl*o }A1\cF쥩dCQ؟ 5d~kd-"#ywi5{K#'Tsœ +)`)j[TsL v%+>VR֣ب|'x=ST'|l vO{=o5&;kE=\ ^} [dODZF;AI3ɆQ4sdI?r]b'&==oaRNb=Elz* X0UR>Y}fP4yK#79gۏn;N%5=@z =ugZޮY5[cQh*3T^Q(G1>0ӓ JY'L@o1Jj]{$z%d[v6``6f|- Z7[[#J\(%Eg_X&E{N-:g8a4oB49W3M"xxs<:˷Z,G""+jZazVDz̉2쌀 }*4&kȋcdV#n-}!83̯VzEʸA'B84+ 9+ǁĶ"SFg "U|:C̦ٚ!JMO=\,ETǹ!RQж2+âXfmњ>݂ʯOEext fs 1"Y)VL3aG;xOG <u(wgE;Cx7T)g͆iW8ZojC-^+9CJ8њ|hb) )ƒJ6v<0b`MHK ↪Rh⦿gK09?qL,#f8rdmQOcH5C9VMQvg(N< Y`f&0QF=Z浠[dŕ)zm!chYnѕ+3;!SP]ڬw)_ht*,:'X3S"B,g+c+:ci^;^ƥl"DU'/rNF$?K\^5> mA,t.P;OIio._l75_oIp=pOP$~9R5GLM|+Yo 됹[J{ǹ6".b]5Oc10=tusK:p|N*o dԴ3tM֗( tXȻGP )wLZ$7=O+voIZ=^NpTŘ-:)^)23P] ҥFk-N{#DmqO'(sAmPD9E*x~?eݸ^ YrҧqN<]΋aTF1@SK?_D}`nt`yn֥A"u4S#5՘iϕm*~H40} !iF1r6Mz "ٵ403bb}F.EҔAPݚ0G=՟LjY+bD5<~zP*Z)Y@oNj;jC(Ǔ,>OHN3OƋ^ٲ$ mNnz>>Z7w|ꝖXykF1!XUFk6oTG %N9 fd"#.:wn+pMCpymWq&:ФlKk01T]=tJ&w ;Te 5ԻYƦ FE3yZ6v>% Pd)nݏ+5kG!// bkRR{= o:tYdZoT5C9Ħpae|+TFW0|+d`DsL9׼i}cOoH4(Li<4CŧUdt%=jGsxa:Q3ɠ8 tkpێE1ԚZ͙Nbt?G҂'2Đ E:oo8-WQ9N%@B5-.\tC&#Kbe:g7yC06g# FJvT#tSyiE9QLS0\|[Kn|GVCxxw*O,N{   zCw؈_b=/NAy8fMt O|T.?qy6t %0ޠ7J^Ǚ77!⍼?UjLͫ靰Ә򖙋]"}}"mmw֘ÎjS\PCH4'M V=!!!P?ο4Y%;E,!/O*g[s\-`jϷXq-z2 :ԁ%pGSQ:&Qtd*4uZX/oYUסupB?Kkؔ_XA>C[ V)\U-WwG rx<ѲjĢ!ϺOOL.E!R~<`y퍈|˝n= /4Ѫk{4 4=o:voCm:drS|~~vd͚wXbjl]{8=yMl!+ z@<1QKQR?.S?k厑ţ2D>}mw?IF*;^s-gPOI> ]]X[Eqt"adꭷńӁs2QTxL#3\y_:^Kp.NI!Klu"7r/<Ħa ƦXzx]OaMp$R

UU!Ɏl(kO^P9DQI V%f Ę]lkhjqojvN-`YgIH,4orAQk^&aP(Yp|RB^ѣ4 AIerg=j'" ڋ 0ɣFQ%Ա[61FyS꿅9G{3B㦑7Er|wPu*,yu4/-a<0ӕ:@vщe}'>V'@Y4 u^C 25Rzpɀ4̼PxHK;>XXaE Az N "r#ICcʡr~rp.J rNڹ 7[[t&U@2Xߋ);!7֜&j{pj>&4sVGf<@/{ckxV]<z2aE]^XQϪa>>cEbS)*1lZl.6!4o0By\湬<8t@ lZ\lzY6-$,ή;蔥'c2wZP пZɕGP]zTG%l8F:}ǐ",;c9nI3<&+__x4㴉$^[t%Nr~ko,"{`2k悿0@v*8knL Oroo9SܛEwwvs?_B 8Z(J&cnrRPAd JB¼P4q;̵(iq )/b{?fF`Nm}6iA1qibM7m+ڿK~OִJ419rg(ԕI]ݩ2{>RfOq2R~G{7f@wa +ϨhI;l]V:#r d;Ӟ;00ntG˥x3+df5] _up(~93{znO|t7{nHnE}|EP8YV*&曎μi|Buz;M,icOΧܴ6ٚ-z0<2O/9R褥EÀ//"3;6,5Ӕ4IhAsp֮߻2dx"xcүɧ#ӧN WR *h*fa%mw皲=-J PX9tRi\Xv B}Q92sO7T tO84 Y#Sb%]%AF cu`R>I/t?u)6<Ԣ{:Ϣm4F(Ë0~wHV# f}l?it Bsw ncJGUUOz=lYgh#TSz^Ђs܇0mfMB!i+&?hIyB}''xz ďIxONWҬu^yy*Ey +xC;k驪8vײqcqv׌>ޱ  Ch]yRz=;{CLy;ȬZ_&:[-? HQw󓢻ȺNxx:ouMo;׾qgM86a="mR A̅7y0aA;H WEEy;HH=se w S Pb $ uե!؟Rsk<F0f?6(~o{A>2lX!ƓMwҩE&$G~=b甃N0V! \;] 93H3MWU|%]Tf 3}DI{}|ϚvNWik`_b_Y~I]^ZLJg>^wkB&)17#Ёw򑁁%. ݨQqeeFMG>(F:d&3. Z !P#%vXUG*hSl8ϑcFs퉠y5/δ[_%U}wC[4o<`֬j|w4h4"; 鈡p>l!Wh kuƖOZF9}ՌN +ԁEUsVʲ[!+`83ύ2q&.ͯ{~Ǧ.Vv@iq]'W[9}D[- Uo IVl8<匳ֲ3($G0Q@nw.,y.5 Iq8=PiCtK%BtfGزhP+]-+9 /p&az9$ԍ(W@flpDy]4!3M٬oJ*V1-Z!:cyOa؂WzO_#ykl0')4w_ FRVFsN2 o&4eD?!=\yg06Yϊk||(GnK[Uݗն@BJfϱɆ%XoObi29۳ޞࠪ2 W #9+ S?%%yZ1 )*5B+.|4c6wINw-[u>2~|C*%V%G-; ٱ| wHa 8 ą>-Qz Ԁf!SKt:/3&,wЁhrݞF6NY˥23^.1͛o?0g2nGjg(JThjJ](MJ ۧ) SH*3+@epW2YߘfбVmk,rg:iR94G? oH!jU`.*n@APTtwLXShuĕZ*gX!/R6 KDK|q͵֕9b?v8^θRnd9yxPʌ+[y }g5kS/'L)װꉀ-7B[`EP9{cC^: &H'AjjXUݚut?~ZVV^KPͳ(#/Q}E6VyLjpH,o M6B3Z戴K㦓4nd~fq٭V!.3 &174 ֎ev0FhxhV}V1pFR"̠.uA=笥nD>'=֖[p%>/K #n);lF`E#qaeоNQ~F2 /iw2-,E 2:=%Hu*qA1cA<Sg0yRIG JE/Svm3ך%Yjhߜ1}P5=lN/yk3褲~`~p(¥i 5PF34yTSr_/C=g.'cLϟbA&A ,]`%Q&<LĹ'Y{&!sF "h_2i51!-:)`:{g$\ol:3):[giȼ(}h6&1;@I :1O!k_.YЉf$x!*;>C8^pALȈXXB4f(@gُ159/R eGǼR),4iأI 8X_0?2,v/2,;:јޝ?-7b$1ȳ2_ W[ˮ:ˉv'8qoiKaIJa_: T䡯Ævy3YA/g9Hښ>e;m :ZLf`q !ؾR(]Y4i8Zyyΐ߬Y; w&s6yg9'rOYZ_8wb&,;z@AЎǯҾcx:ߨxT&x̢9.آ>+ƪw\&7GXqBL{T}Mbq;HFeC$a=LEx}9#Q567aW%Xy~c'RVt1 Rks~'y0c/=I}LB1DȻaWdldeWyH?+g#2iDiLDqVfNvy3ϥ5*^c9~^'v׷5fZ+ӒMK@*13u>Qͼ8 E+OsLA 9ѰXrf1(&]TFft[+xOBL<c~Xm'I̦uopF^ &)ԣ}硓\d@LY3?r:m~ҩq'.VQq Kat)VIj3”7ɺ1PRd2wgT"PIZ)?'ޡZb7lv1Q6 =:z2=5gËle4c]@EZ #}9ϨIF'v{n@vɈ1fYJ/L<K}^&p|,NLj:zT Ź )NE|eBaI"+'M3@_"u_^E:I]b|8#zp-zZ(a r-+j<*%=a;rW)&:9,r޷;9wt}EezG'I{:(%uqo+dGʎS 2,D/41; @_")+Sٌg'o7KۭC({Q^op(4f[?hqQիihL̦ ጹеmw1_d$Ĥy,N8{?Y=~潧 2ς3ϗ}9V&Χ+Ԟ"i-̌$4/Zn Νpe5Ϧ/7%D% ܰRldԒ }ѩg.T,q&3Y~&{k麋|E6.꜊CX+"BO/PQ!^fHh8za`C V~YTn昄[LıA^/~2"(=qɖ`[d)LK7ܤG ?6zK rٴe/s5XӐӑ,5Q:Qޤ7076 HU_vv4G1zMH(К@fhS^@ޤ7GX(*4{`]Ļ7Qp^,:u>Ҕv6X%뛤vķ3=OI5396 6@@"aF/Ԯ V )qVw!.m_nboΛXs:?]je_ɤe0d@H<%{}"P7y5{+ `=?  <_+N'bA9%|^XV{Z}ỉzF1SqJ|lH3p!g"ۓ|yszP$괋ĘqPsX *Ӄ5syXkT[y$51miz6]LWkl|TƳ"Ψs>/hK&ֺ-TU՗ɓ0@>8yN9>o*J'Ctl Jp54Lx*ajiSa{{ \U"P|z^#{1|}2^|%RT<Hܷ}#1\SκR純/4c ֣x˸td<ˈ5Khgϱ⌜f/OZ3lYSEy7D 5Ȅ0dg/œ7zoX}iM(. VY/{`|@P* x_9!,x(਑hghEO YJE&?ZЎ3k)JTМ6+/gN(BTy^&_?{2%.qn]+KIPMׁHX/ix \'t:ߒHBW9uPl8+U /b^iP*s]K_h2kK'2{jeEO&KKig9nҎi*4IQώS-u .0Uv"%*w֧ȃԼ ͙$ )Յ]K!j/ԑG._#|_3ޤ\RSB@QT׽B93 qr1Rg2 3o_fh'k-$tt.:$:'4'_J I)&J2Q~ƳJpCU$TR 9=[LXr;BN']8P=ptPYdzs‚p7G%&{,,=w)7eb5Ai@|PX_nHZdQQNhۊL|qfwUJ7s1-K8$/\@O$Hэ$GX ʒtz&C( hVixCZ9/{0('Qy穼ԧbV, 6R{'`Q \h0:>y%8dߏb\/$r2:CH NvM1{nQTI KuttNd%uR!(unr~w&y:58K[8.'X9pFJj#-:h]5E1RW't[vX^=/^ᓲQWޜ= (  OwG=H]4nȜ3XJv1Zu>0C>Y`N1u:XΒaNBy D/3o&4ڽgl0E“fJc3ϕ 60V{tJo8`chxbu>8H:_ '4*-mDo ~QlT%0GP%r_Y՘ iݮs{YwƏdrnKYɲ뽩pn&0y횽ĭ)^{y!6$82" h=$?/˻ qi-h _ Iu!h%=br;f{y¢Hz?vi҅#I3cBa p]h҆B]o898Nr'$])no c{8ufWc7Z ʜT0~aVL߭M5:wfXBk(yfOђ sB]kTnޔ71+n鍥=:'ɱ&FʵhΧN#exCwU)M|[s1w2N*`:jF-;oq `d?Ci&ͻf1~Z,,Q"i:G\ML ?0w'=-~l*7Q"oJ/.xkbr4X/E]T4.7>wT_(ԻCJߧns?:-ԡN{4 )|e`Zt4Ue‚#m/䤄fC\?;,8Tu°0mbW&O"cBhɎsyF.^v=3LYEv3\PʜmM)(m_4'xՊO-2n:wݘD 03 _0 Xv@goYS7(I[ F&$2sσu}S-XfۀO7IE ;wY\v(It̻aW5: -#a?,0|471BGz[6ު:Y{Z4%1Yg56;09P9Ck+*(MSPcEhT< JSTsm:걮΁Bqdp (7L()+bWP9?(hHQ=;(G+Ι=\FV:Eʽۈd|ēfI&Ǚ̾^LH;ꣲ(%rmkT.)PVMӞOS2[GDo^ah>3b ls^ U"l NI½4a7 ^H865C})5=j y͞Cq#6 ڡ\G:|GPkƁ~J2mff4=fҌe&o|n:h8d>NdGسIt 8,t |6(tAB0G s "Ŗ󓔹Šܕ 0T]9V[}//M&- !=5DD?pJ$hnI 7:kt p^a_VS9{Ѓ/7l:hy/|=Dxߥ5'tkLRf^/pp f?<ӿffE*CfwV  .l:V9 }> &:pfDv.&(p2'LnCoY]֪YIgr?KZu?i=Pp`t؋!b8_ hGүc*kDRVxBӨf'M`/Xpr:9%@϶ ި3)Kc4GR/vZ.tmtj(Zn<'y޶lr|Yf^CObϷa孋;d#V,Z>iᐞ8e󄊮3}^ҕ\6fт<#@t5D$f7qĬf_ldi?JsC{pq& 뜰1@#7ؗlH=, ]̹5KA[~645fMQlKo 얆ȥ`6lnޜ)XX :%;Į me8q^ ݼS ztЬpż鯈KwE~ Tu@QNXIք)j F7BNN,zR"l9HAg ="gYO-7 J>a йMfp^,D:{>!SsO-}4z<::^z\q1zo!v@!D獤GU 5:ܢ-ż:ES`BH,0(+J Йw֋Ti ҺX MZ'FP 9h@7 Z@4n|dƫ_LE%)VnA7Ekh5XS58)fgu~ZTP;4]ڎ iAv]5gI0Iִ|Ǯs*gMC`}dcN䚦(HGm ԕްEP; BPrMzʬOK.G7H-0A!V2cqfcՏ'ԯO#=m I_o`wt+iLGfq>n1ϻzPS= TYRTQ=hv{"48f*~?9 ^.^tNC<1F߰$b~ѷ>!qp=ϒYߤ0HӴ" SB <1 _1Wx6z}(Q.u{eIJ :0CR/JN5%;፣jaѯ ns= &e,H,+TXΥr53eMH_HGp)˞`asc{YS$_WxSU_I4Å8+l(a g")9<'ImXLOEߨmָfZrSB V&26!9AY~PQg؜nW4#?>6 +/k(!ER S2پ밗qlyp]c"9EP#u{!iG#,^ɤnCHdi⇐;TmnDr! .J߻\xK(I31hJL'܇-Vcrl͔udemx~:ѝEJ :w,Q {Fo]х-\i'^b(lhl4:yl*{ 8y'$מdȎTo \'=׏Q+;2ޠo5 b<+Jv+sPBK"A^/Pqrgָn@3ش>KmKushArKV]zY|y!ﷆvTOV'lB>5Z_5N_vz"pO-{auG ( fJJ4P Y<1:̕8P 6:EQt懗 y_کS#9`GH*\]Ry(`GGaу"@qD&z/`F-zhpaX^ Sfp(o* WEPg&LXtӰF;Hǔ q/Kyܽԇ Ș }(#WG|6 F-NB8!u^,R`'tXdS}i")y;~0L-dShR{ѽJh*ԉ.OX3!ƛh+#]Q_;dqF.:YM #ƣ0:00b%vфC<ިY;~Q`z< i1M7%u^SGt3T?O^*[&h :f_' ;龗=3-eIG Y1}.U/1"Tʔ.yFPKrOS ʌApih&mé$V"}TjlYJC +R+Vx e%AeCQ X~HmV<$ t X.tͼ  PF?8u/ P\\(5;nRJs!q@R=m8f:aƭ^9* ]X2GgFIw4T0%HaOYr(HpέƸnp^ 9a4M+ܻEWiЙɦT`lɄatrLeWR?6ݝq±ޠnq}O#P%䍜[zq@ y{\3i JxADzbsiȐ4Ŗȵk!" ;ESB^\z/ |*Ziҋ˕IOZ#gA640Y ~<˳ue8 cmt7Gn 4K ֔}sByu<\5/&Ù~9s8 S!jS$Èk'@$-1Cx4BfWܰۆS{D2#PԺ&mb4I!K+YϤ,>K5lgjT".#c&KSy:vԓk JnU˦2D (үq%yB_w:GT8 \4[.d^xN`Kۍiq8nlӱ1' )xfMmңB״f  ~M7zj-*؁V&͂ƒUkg)*4Ӄg42?*4{~)~6rJi(>˦l=+6#DckøP}{ v%;IM09OPEfV͊gnulnƧ=8op?G:Fg(q!aE`w&y=|~&:3dgYNd#M  ^"^"$z1FU Ѵg5=]Nܒ*Dx">t]$7r?_+Ēz~X2؉\ЛHޕZtFzn]~ϚңYÔ:E`hY5 G?3 hK!f`Wy@2=?OV~]n2Y{;i \qǵ=(5 c~hh&*hOIZcfc FFU'"n3W|;O#sh3O&@F5{⬈{G&&MԪxvqmo=>p[PX;au5Sکsǃ)gFR)>z<\g0 Ϙ/ 9_|i(I}`h}JLe%/˜8y@fDf$Egd;S>}5hᠥ.e~y'+ݳFBd,'%?^V`i2AM#$@n=p3o ZE:zkC޻d?K'>#C9OHG(9bkf;@mwR3M*S#>sЂ_6o2mCy:GS8ߺIْ:ut[{Ujp.ԄbyoLR`A>TsD.lnGYoy}K= nzEB*ІQ_ 5֦ H$2ؗTg:~~aJ EGйJLi|0%S)؊WqU߯D3Ȁӱy~!Q@ N5P)- d ˌ ș1$G,{;!ٱvΐŜx8caM8sMue/.Pw0䯌Dy/.6kĔqĻ'f+#["4蜦#[ŝR?h4f`HeO϶4U Pf. #>ܡN _+ˏ^Ƶ`PX uo禳ww~qK(n?õ ]i7D/yaEN;b!]I浆pKDYI_Ow$Nӫ#މr6JM|ty^jRC"P⥢H:0L M`#P5xekZpt| 8ƇCX3yVR5$}jiSEN뛸.At4XI 7g_ v/ixC8ªOvaZ=,>C.%\RGQk } |R[pkkPu.}\|O&cJ{dFjrLIp~2! #}^x L)ҁ3vH͈ΰVf܍6;0k m\pgSHV^c)nDmpԆo"/}ߠ)ñ1?ŮI넡P*Lq|Y8m5I3P,FA?j)duX"^[tk饀4¾`=}x ^륄Oygzw^*ޮQB)4 M kObf~r vVV:Hʎ|"ᡠLJb.C! F\K7'&ZOy=}2ǾLT8sc=G"RdڟP^z u>m8㤉qb4/济4hq/ jcagXJ & A A9H6ü5p~LGI0QfSQ*àgT$Su{n/Zq!Z,AyAw0V[.'^A؋+&^,y͏@Wk9eg{G)Galm";^i$ܚ^3:#lsޛ"N@+UdarKPp)ҏQ0ҽd^uYZ.+]'iʫk-L@Gin?HC9?_?yȳ{N Y}v#|zv<8;(`rr:<㒫guඨTV#bwvA)A3!44Lr`Me%]a&3qD0lrz-`Bo r֔sB]S[ҿy A8^AIZY~ A?jMiuF#x{ FdCa'fjӽ=CxXћA)Zk DBŒɰЅA{,m,=:3@O<^tKOkx{pf֘*ZQz7m z=)Kye[_[?5z_3W=]'t? hy3'|6b 'C{VZuý{G Pt6Ǎ6G,2wӆZc`qhUnto}w~c{7.hd! #Dkv;& ~EZXPNXhU ZJQ?EGm'hz'zx ׮ ) k'R#Plm65]@ +M&!d8H8Cъ\w;L\r:"=@[$(E2ZWN _yKؾ|V̯K:+ '0\>h^ : Pk|8rȗaվýnOP(.(e:$B1VGge!"drX0]U0~Ƥz5m uǿ}ꢟ.K<#P2ÛjJ 8o@W}eSx[H$2kCamd:xS˛>eqmQxutl2 FQC>SAFª3v1_@4lBgi%f-k53;'G7yJ6{p?75*5a&D}ly╔{|JaiċŁ,1"2\_b&Q\=O1պ\G^Nb3zZ0^C͠"J?dgbl!2qdFcw" ! J{,H<3p(Z.E.+g M|u,L?#~|3Hg NnͰg={>"#T< "%EPFiۻr僇f=uZ'""zњNd2! |KJ| ;fʊ,RFK>_O{~|݉hd@Z` Ir?H]b!_^'tw!3ӓ4EvCUZįf-c_ɔ0=a|@P{$ܡ0"i}ˉO6 ry";0ja WV_:>mr :~1вO)ft;>ӹu׉WfNq!{%S#;%r/&(swEz@ɱy>Ir|IWU",|Xɏ|Xi|װ0yrt :@AY/:MPW5\RwtpxaV,ǪLE^@<`H#FKxh={쨁O'WL|֕gKz HpOi #M/@:v&3SB ŏX7!os&(D!~fpZtD¨pǙN0ms8שOMqnFYyD[&Bzeq7aJ݄)S9qhDz5;˘z42"ʔJS#꾿G%XӀXkgrA+R͸}]E3:O mHj|[1Fϝ:h.RaG"M7Gt{o%Ĥ6d8Uߘkb}?vk%.-;Q/mPWm ⰥVCE*k7a<6J4ő4|{wgmz){6:_ωMuUHzU?|:a'D~"+,E<GMG0h_Qg:2aH0ũaJ06MАsy̓Y/D JxB>{T/ B8J=N !+tU@H QwA棠 RОG4GQȬNv} =o}RPn\|GF?0OB ޹'~w"rrqUq]!7qGl |#vFC%0Go5^W}q{c7'\O8aNxS\wb5y̭ "7LR9.+}i?uFǥSh* u![Jz`c}|Y0Po]sa,5l ۩ܐ0ҧp32 dU<rF WiKbsXjTSa҆f{AmA&WASBMuD9Se -V躌 Sr2wk:EbwΘg^C ԙ/:?Ў`PT|(gteTf% ؘ>CKtKLX%ǣ3ǧ3\04ZkH\g3P+tp2)ԞD͑sGç!ځuvH2޹/ף39$~YB`+UrNTI#'egM̬9#cweg-}._hLzMׇنw+`ͫ ҼW1rD‚}tڜf*-uK]=y鴅G8F| κk$Ct8o'o~.k{һzwCokDĊ&&$rq X&-N$U*ߓ'13c w'K,H!L7Vqn#k$-Z\'3q*`&9>SudIrӄY XIj1Y;z asvΜ8ӎ^EkY$ >4ֲ '-hַx>ϊZADDxB5CIi ^URF0PM_ M̉sQvtE⌣'% ?F!@ [zdZmxA^ Wg*\FeCoP \SJEӥ}N啗}ʖl)^6Ϋ0+P pݓ=0 gr t4H"_6=OĚ.q7>$vҁOj^ я 2n07^!̆A${rU46 cvdzȑP͛_yN@^v˄?)פ]e{z66pRӓGK^t]:u/`ojC&P|1+pO%GEלPJ`G7gi}4(N{bѲv)vC)0iЌ~hL#q Lj=KW邡cP +j6ckMJMbPhJXh Y%)eGm#ʷ@i= 3^߫UwBJbPq@.6N$i~:!H<aTc-N"uA֌9hTDĮ5*~r_)}V26CGxJ>(8KWzl 4쬄1Jb-y_s(j%*mNa^{v~|nwVs݃)Ӽfb b{:~Ls*Hg =OT>70x03C5%tB+L Z~C0;02Œ6H׽#īAf711_^t1e4E*?T~`N{d66i#v)wl,'n37(`"sjLx{NjhY꜡4L70:sr>1h  70QVt=Ӏw.J&"lStºgta@ptGtМWI/8 Ԣ53/iq]#ƃrCKCZxV*xiAp;I d6N|`asSYpCO()Ƽ ,#2yQ;ʸ"+tt.LsFDc g:^$oeXoK g ^h0w`3f(d2N#5c G5Am&O_S8jؑ/po"=z.LGlp6<)F HTg}X*CQ< O!!ǰϬW.vXyX@&y$SAQ;Sv`?ŇsIrr,1Üdr: ځ =\scIMBdwp8P|':E}Eys:ІDTsİ{Z Pw4hndA͇a0pjoqfR.G eԃSjڰzY&gdz͡6߼гRCz`lnj}7bMݿ 3māY&919v^ Hy"( D D2> _''Sxc(HܠZnj^Hm\S"oob tw?\cSyVƹn;) ݘUYa&Nc4pM"8J(Pxzsےo%d%KBnlfvDsBkF N0Q( ρDGG&A_Rt->̜l2sz$Q%ϪLʡU;NTZ*uCItӶ̶Zu.Ou>;< i/"@Z?At ru*D\BPP"|̉h46O}ĝ,g7;zƭO=zj@Zr3.K J+HOmleY?z^~ODRlO7#9,ktڳ}ϓ #4W#8$F.; )i)-|u&=I׵YA5HO 夻sc6ENʒ$`iPs![iN_*HKPtC_ /|SSHIX ?D^ʸRkF=㟋y#^WI'$BJnnyvܵ2_~D2cl6H"9xM/B!ɢYuHkD<^Ƈ4 iV1ޒ,vh(;%ďkzYۜadw =D NV\BvL|lwT ^6 y@ zʣ8ZH蘌juibs5jހdZU,2fhrmyg_#cH0ꅙIߺTzJ pAf BPM&N33< CiW ]jyu +_`*sy΀9s 2]x7<n\lU#c%$ĕx/Eqksʄ w}NP;?c֓O zv>)Ny2a Bg'vW7OvQYm}SC)tJ) f59rd(:$]!@ot e eqJ'~jV@q[nP~u̧?vAfcH"p ?%qVq$\ =Jga?N?$d^$!F!g`Zmv)z,[xܐJB/:!鼩4CkdR,*hfhezD%U5I⋏W_0XЇ妀 #?3QPg#՛HKtd\DH7;RF!?EF/oVc}Ia9wr=WR'ܽz1S),Aj1IeUȬez.E$~*;#hpvH6]բ TGhAI!ufmå Nw4q.ߠP)5[$ddNbx)`O:5J\Z^9Ir\b5{z:afl.A9Ni)~~P\iU65ӀH^04K7|2wY k.'ԃ!/,*23d"=7?5F*w)-vVˈo:.DtG& ODtEGd(i~N*bևr{9/ /SG_c,qj޼<)ԙYlChun}"rZb`s6~HҰw%(jXajJ#ߧQG=|2G \Q/2IPIt3^QEiPS,k+FE+:L׆3ӼHQl6y EcCWnD댇mǰQ ,M~0@yD3@pzyw}Qby޽xV0:^9t0Sa 'ozfuPG5'ۉO;0\t6_TPT\ͬv~{1acЮD[ԧŴ3X58okzff5)zԲ y@EDcp3*; ߆+S D$;zOW#c!v - l K{ځ 'eYlٺ65&:?{>A5cZdGz 0PZJ 9M>̆z'"5Z1esD&.|8M;4I'0B e#Qgr"o,"GEJjE<ź]nJ1>xGˆHDrtzckŜ)sc&2N&r-)$_7t Uxuo6d2E'$nVTP@:wUs}+uܢf6 ۏ^%Xܟ纝5_O YgxGG<1-}77}DkLFWrm@Ef#>or8SGvсAqu$n5>3@_a!Dk==x![ngL7Qp79q}*좟#lB~;zPQ'ŨG>jiʎUZ U PUHA {̱bz Ee1kw|LV&gW09h)l8eN@0J*߹m#V^&IJ;{ |dm O|OG!9VE0ߠj/+w(DFy!ka4@^9`]ϋz; ad6aNS'pы|7e{*xZ@Hx62S μ.8uz8?!nN4<i-uOɊ`Y1R[3%v1^]cgֽ4 g@'tiS#]|4;xA<;&8hM&S% sH67^՚*CxXTzCWڣMΌ$X;4^')iM򓟤rі ^d'RâG s G9ґ!#^(3_ռ5n늱s}n`&j X^"bm/!it@$EXgBa$k!2AuTb1 &7eJZ)XP<%pĄ*,0їG )$z8crl*Bv /gg\Dj$PK<-͔.RLnA1F;,ڌ8j{fKQ6h#]4ꏠD٣\|IZBS^ٙYT~ 7&FW1m<ω \O˛v(~CI&<H '@c }3ExU"~Rӎ&ϙҥp>u;@/paKZh(Qdz8&fXYxtpGYМrqiG]1>U\I.t>h2iL~>oвjmE] ގprUrCQM$†Y;ޢr!L?yd,8 xPՐO;# ?;mʈЏү]o!C[z>CC.f5'ቇ \Ph&M!rJ7 M}d\ёʳr72YAQܿ_tYfQ5ݜ!uQhZ(Q^]ɳq[Au)&v㞺a%$ii:3*UJ7 aý<7 蒵tGZtgnY7Q3xPaCS9ZՙTkۙb2]TɬwɋE+Rc: jMQX)#416xC#Ҝqf'*{ߡ+ܖSڐt=6 ,g,^>|XܺL^>j{VOV2YKNByu>k7n#t;zB? QiT/48}ls-|}J#wL|^!Dh wUCR/yOg|g|@駧Rn-|Cuhd{6?z4W2 [ƾ#1/<Ü Qd|<TQ ʛS—x~&1Ɇ>fnn85V60KY_vٻZOmrsuJ-KDcӹ'B^\ݱޤTX.&/W(A>d9AY=「駴n몃(Ez 9 '׻ްF&/{/ J>Ei|"s>@nwc/M=ʝX $pdP: T}Qoڗ|!׷1W 5}@p(5/)*](Ӑ͖_P2OT_ xn&~\}UdK%jէa\?K~qz} ∗RTj&v*4!%R;o+ s?\Qi1扼yMw\EӅF6m7*v ^~5C;R~i.T骧G#P_+⪜]="Fi[d[~B{b t,B<O2唆oϝ>ah*\'<ٗJΞ#\0|Xl6Et}_G9Eo:E/ݡwISu~R#/-Pc&tl꺰>#W^K,~ylr麋fe֩Oil w6, 0UW>+ u، O6#4i2SU-0m!e!Eo藇1@?7`w~#g ;j䳣 Fi;b@RA`h Λm_k'1|s>I&J4 Oxo''v>/*YX'w'Z8b5בgPobV.ӳM\J8XALIa:cHTҷ72w|w|++e`o,^2&S)?hS^%jqc얙:z0KZ"lGk(p⭦7 nj zt!3C`8r殣ģeRo腟҅LX|“?{쯃->_* Yu!Mt~!"[>0Og)>4Je;"JIҁpMxn'zVYzOFG,GN&9o1:U1Nw(clK :k7r8kqd^%ZJ./k (Ҧ̨W dGԦP2c}ڴY۰" Zmuǟ ֪hRDQ;(ឤwUȪܰ=w\o S{\w5ڄnj!.Ied_7) 09Q@ @o ff㚾'Ìp hςn_@7/ {̊B:庻sʵp;.P.9*M;Yۏm` hҗ@S[:nW{x0dD6 C ~8iMdƗզ!FXwQGGԒ Db~i"\Vɗ)9p~4qD`#-) ٝ `F8Ƞt$0&]xg8IItizR%{,2'udNhf#"_ܢ4,!AS& SFtB4IjVZn*2q&xh7_f\/Pu2pm{԰S[7{c_SB{/ywSn++ǴWc>›BCx,JU}z%ÀT90w;ˊFԞ1 a v-Bf:*۵敾2^vӞR?Jo ܬE jS̲1\`}ND wXhDoH.RC_xAD Dz%`IDc58C=s /X9*Ho)!AqơA3(B3gV;G#w顐.}m:ZoEԊK/CCs݀ }7Zf)u|,-X]fY5ǟWQӑMrO~k)Ɠ[^CaPһ3BN)KNh5uGԨ)! :Zpщp%3^oFuZ%wg> -e1 mӈ>[#R|F֚C/SC'C_h/i-m ~(y[VF[O rie՚/IV>7OyzIߤ7䟙MF6plܒy& f~[]"J cOV_!G؁*jZ,^ʷʦ4QG"f:5W\3bQwC~;) t((~b"k&4|y1Yʞ2x'{S 9[ds.0CD9~K ʒ>9(: I[zA̅:yɼ5 }B:ӥ1V=ep8hUiGN9|N<8hw;O ۻڗqF\6Ϋf1[g쯹6Fh5Z|4*tcM=X%I) u?by7cʢV6$D25,QLexoO= rh%<}zd\b> J?n'Z@|~bwDLcɿ̘ZbRgz3Y?q9IrU> ?*/H]8Pi4)wq^'7wE ~ev7fǚ)f "W}S-Y_u]htco13]ghYjU8~Jz#ƪfRHľ$КTƊS}Tf/֜_t+9o݀.'wTv~q0]Q 3/!Hz&IC12;J//l7z"^@C3#pQCaǖL@.RDY|ʎR¾L١5DGYA BbnŪP()Sl'[S椩)SExM;0Sׂv$!yw]6'0XIjw';!(ǦG㴹ĺ~q2TZ'?7L1aOEjHm XPߝAg8+\$)`AoCE,uzHBoaZ$wɣ{e.=Shqd{E w0Uu 7ey0MzDP*,1E 3T1F#4!y?!ÙyDl̜=D*o){lRweU ~LEМmk'7 '=U~sAb,ǐO/k p.+[]&R!HqW^]W`"?WD@!i!8S|w0Ь8yl/zMG׉w^0]+4>!Gcf盤ݢ{)}Bܥal@-X5ۃlYWj<<40. _ݍ26 {$??+ .QF1⃗^|,o zX OϦGO[%-숯[h{ A!bҷʳ!5>ᔵ℣Q GGf ) (܏[# +X7Bᛇ\M4 lAɭyh]CW*)QbaF0Bs۸$Nr2`N- ~ \/s{k&hty6t_ͳ1:m+ʘw3DXsO ܞEAwdR婚yKT':떆n~yB0=7mfs] A6δ1Z46!w q7ق}120O~ᐢn>9_˧8_Nku33j\z=imY47~/sr28̀||njpPbه C̡ I/`5">3K@ \>&I"~:JZ':&6YݦV^te\a'n}z ?~3^JW챒M4$DC3`n'VbTGZ1٢>@x|9GPlDnƄVf_,eعϲ.V~xVj? %Ǒ%`9 m*iN(Pv-R`;\miVifH $fv/;P+l,έ{;@>OOm2E<*PmS;At*wfs?)j<%oCO~7kS|wMb6p;"xwafLu}^Jֈ$hDzX@ d-5r衔SHA L.ܥ h>}NȑN#|&} 몰49v_䢞I5R(lV53=(U?6^F*vLZm)qaQZep@}_s^POcI߱ m(oЩ`%'R/MfBj,Ek< 2Iʝt@ +┎r`fQ =r2%kwSm6&ܚs&s|$O2{P\1Pۓ9q2I4L 1Dd?+%Oy׉rOQO,sle}:s*PQytS4h~Je_jǙɞq&^'dcy kXk^`$Jɪ!Gɫ)/(tn̟qZUHB^+:joY-9xP9i#yV͞Yެ/ҲA`: ? $dIaW @.KbLQrw'iʹED1nCXk80rF5`pQ'Fv̐])IJqQbVGAj -$d /!Hv=:p( O^Q'_zn >cvjS9Ah}f!;BGQ{*9fπ=Ͷlny^CC.ykэ 9)tĕ|*qzĕa=^tG_HWd,̄&"QSz@x8,tOxz|IbQޒ\Pv\fņznSB4"%9&crUc-ރ.+h_@{BC{Hp}͖6}:t3|&{5wz.1QSŧ?ybt21JaUÜEs0gw q*/@/mvjC6[ʘI*' |NDS-fMDCf{KBN_[]PF)(]=mL Mv8I)/q1CÝ"Q~W6Q70(AS2=!Y0zKQ[#0p6Q iDZ,װ+ϽzqyWNX4 jυ2Βg_JjV'@"d/$6։ۻbbZd ѡxb^?zJ~쀐tOi2UuЖhhF?f߈7pv"e-3y;@V'IơosXa,FoxaJP݃IՂ5 \@ !+ŌVfl&yK 6c&@1XK7Osb^79Y[vњo'>xD_1AkIqwZc[+d}MVKmú#M+˗I=g1cM|wpO=$pnn.#H\S^=A&I+RͺOťe0(?]*314M`5؉N-~6ȗkhJ~$J=J$O϶Fn&"7%PjGWƛZ`tIOCG[:1ьx84gr3WeAqpx/MV4a ڭ|Z#c~O:u=>Ԓ^sS^4ꆔgfAn48V/pxisNXs>Շ4ج_;Njigy6.Ɇo65O`A#8?(ymʛWe >G0P4{Epf%Ur;Ƚ඀plڹ/gв znh}Vw>QTf̞hsb a*)eu~)Vs2`MATA_ۯ^x (M'SD]n0|^ϓI-3 $V;C 3 P;rnFs d @H?3zw{]ܘP'.>RGjALF0l +b%=Q~M1;Yg.Rӹ$$=,_6Fpa#ԣQ,n@z&/&oZC6*yhX~D*?բ󉬘ڵX]z%**CTc^ڒ2{w ȏ%"HOIܯP2Caߤu~KGAH /˲gEVG@뽤N@XbY9ndZG;r->:{~8@B ce}Om6K0jKK%0hͥlbeͨAi[,8 ƚ*U#󽌔.'Z3jNfH|x>|LM3.o/:N@͹㼙5 r=fp0 .-"toSDMP-kNjGʤ匮5C~y֒T*P68#R ?|ŸxO݉EvG?i{Yn냴,=桙' O$U4&%q  HȼN䉤K3^lGx+iv:T)1k+}1>f},i2/a{0 .k4ɇ|A.|9/k4XuagvMdM$f£;[!IHDJgdyBAW+ Gr k7 G@>'o +E{14KS/!F|f|ZQݥ@?#$9>IQQyG4oqRA?傞_sdmhPKOVbz2 Y%HVݯbx4~`("YF)z3kX|t(Qmc f\K^10fg,0^F=I~KԠEs6kh^ݜ.LhX{` 4I5*I?Oc~(q,mimtsftz;0i7A2O_W`9D[ :^-H7ՠ|rbFYfABO"cǣ*u2yGkk"֕ | !lGm>FB(p&;f-h.o6y=jbLzYdz_|TР)s[P@M$9(TdQ?ܳza֤T cUSzqv RX jQk쑪z,UYSiK?Oxm#i)+2%/Omx[Y R/~rO%dKYv Y g2utKaZ¼SF ς{lǦtW",e!{`SSEHs Iu!oVKJԃ;`=d1e>ĜY/>|jG JJ%iإf-~'js1\aytݗoUO^)c3%w솣͜B/ΤdMOsfףᐲ$k Niק>0.gSPXMNFKT?jLC]|sν\rǏ&iNgǙהעy/ GX[0y-c&dG ^~LY35dnV'+U\Yyb?'3(vtPc T= ![w%'ׁ*Qc8I$jd=nv0 gJ.S Zdqgy1STzLfkM{!01`PEY?5 \#r cK9Dޖ4=LڼC4g VI;5hوQ~1rNp>p#1Ś.PCQjP)fϦL-C/k@N?bNd2w 'RSK^fݯql>K>1z~E k/S\ecfh2ukiR܃hʬU ^J@Vbyq;O3V+0VC\ȡy}#B9$cP,-\{ڲwW]+q$W#Ӆ$N8f~b};)k 2]%,X)]-^8\PoœL8ދ$C9}xt|P1@ 7TxEd|>u;zngq~:jIՎa^ ETK, MI^7VcA[bmoH2[\\u)N(Í]X[}8p~)Sہ,6J|°D 4Dd 2|y9¹2iDg矲Y |m{aַh430kjlGN `Z'OMZn) ՞x~ :Ttx2)5=2;==yR^;E y`6˅Q2P",?s`2nf;L|7C [3W6VFN SKc'6on㲵v,3O}?] N)tnu.ʫ2[dG[/Իom5V6™D,u z?ik;9Q9UkiȨfnj-/Oh yJ$@Ѧak(st/dWy2*nDZqLgi k0P摷F~ MmwᏵ 6yŔ$(}Nb%Y ;k_$ѫ"4YQ5}o\e(c C "%e]|&;ƻ=~|:k:ewΉìk(Aa;{͸ç`Sqyw> eb@kkUdL<㬰+B zqfA䊱h"zi R7Z=V4ԍ Cj:NdBy[zBP+Ŧ7x{ 6"s^@ŁC<})CMɵKy4vÀ ;.AWl:Bӡ}B$ŀgb @QC-ͮ#'I7v|%i嵖ArM.װrmI_ubqyVrRB|8|F6+#93I26P7ygEm ,y@eL*jy%o|cN50%Ӈ6?ة&|a_w*NZR~<׬Wu1d b_^7%$3sy1}^I(gdM "du vbޔo9qWduD.שB6ǔ9eą\DSVl#Uv *vX9׼#AkvgȜ_|t5 s25fdO!%ZOo:8%AJѶ՜A5Co;bceN5uA~(r:+lQtqA{qsnq D#N iH5e,|BӰD馐ܳVa$]vV*qOD/Qj&EG$ RB_@80 -´azWPTHv\=T=L3Hdb_y8[;O7 E\VM(,@"),v!p rWXvROdYĚ*)z ױd#QȀ/H0 mb

yh0g.5&tciv&L)P~G sri`;z=MG-fy׵d'{.([ڼֿxv ptOo:?x@9t~m^[^LYJ`uηh+˱r'喏[N $ 㫸sͧv;+LBO(@_j% qV̑Ϳ:87hmH.e/3fd) 1Q OqK;ɘuf\5wDtY{rۥAaɕ?N H y^ֿX| Σ 1C͕wsAgɄXc`ytAf7ilN=u+XM IЪb KNaKlk:W_SnZ;So99ӌXW#'>Cϩ|rMgNچwL{pX2֒s.bTڻP[D$(ӹӕF{l"dp;}OdW{X%oe,sq>ڭВN~B29~Bvr[p3^o@l=e'mhݨ~Wj;e:v(ACj 8ٰؖ>{W|@?+X<㧐6t&^8@/ed:`ТSHJ#]|{r [w27k$JB̈'3o9pFR^(s cmuPhht6.|mNd4M&UWEO5F.8,bʘ\չ9t9fr‰:p(i⠢CBÆsEN;6S8yU#o|wStf7"`/R< i,`$*J%Xm@wrEB2B 1l9 ϻd)c9g椪N딻!>n5yx"H]22 H i&]Z2-Jean؜t`PQz2kL ӈmBP@Y7EGOѓU}fkifmRlsir0ZLx,KNj?R][K;ViM6_%XWj_v2gM⤣E?;McŮ@>SCNH56:rkNzɗZ{xnGSֶ2MScxLJw|ƬLoKAx ~V+KY^¹i6[f4(D 9d.N(ªr"q $~.)MMBQƼKIVpbb-5Z{2y5|)^0Uq<{̏FL$יMtIa=J>ogJK5=lbS!Ycw~0XYu?4qc֑q#V*{dqitI!ԛ44vKx"R"H5'QYfu wBvo[ǿr?wkA5M" ,,yAz^ 9Mwԏy|ļX vqbVBE`vͭrf4; z`]fE %*8<"Yp.40fC0bh!?} ;[eYJQ9HN:$!  Rx=-l.8o{b $HnZyr̟򍢘]w'oAsOI8]SO'xOC~%&+k4[=/ r ,#yy~w(&KU8_t9 |8b`5 oƥ*{ _Va2qZxٴ~l!6>m'6j8h`ڄXۦ9Cm؛.R +bsj>j[FWzC4q&K!ӠKfIOqԓe g"@%Z% GwO1k!4d,nFS$5(!FNy\ZA2o`+]/Vu$WoQ*U!Ƣ u-Ӫk[BOE[3+=,RN7ݦ&r'үN5hz0YT:);v 1pjNr ~$f_{v"z2ۃ}GZ]qZ\O=ӼHǿN¿~J +wϝq|)@d^8t8) #TA"x;nF5_62jB_ik)Q{Zz?قS aPǩyw.I]?YP:@x!S5KbhΒҤY:FmlX+MmT3vQ}'/B+y.<&(=/ >4aN Dg*KV5[J\zy>חT,lx$;Blz:#|'8 ESydG/ӼCRYYaؖ0] ==$Oljxz*}3\??yqM~i]nBne"~'t Zl-!iBZKI' 0 M^ ~ z{Dϟ{<7Ddh ѨS3&j@Ιذ䶿Ͱs-gг45 %]3=`RIЦKBT:5s1`t.( a HKg׊Oi8?QXH>'-6$TY:1Z Tr;!MhĐyLo,ڗ W+a5Mҙ4'cP!@&^X9hJ M<:c",9EQGe'.gMmffR.{૔p(U do*5ghC ˱?Bt^7zTG/t*/ ~`)7 (s[o$Mav[ib_pŎe1Xn;<&hD.>;)9NzaYy0Kf!ᬨJoU|{dQɭwLD(H#YȷFKM<̖uGcfb)pES9>) );S 8ݚ2 ֿ{d^@3sQr NKT1^*9Ep>&{#Dtʯ)s~˷ĹU NPJw GiuPhtBkEt)F?< ܬH<&pn1<'<`j*򉆞rI*G\^Od$-iaqޢ5KgWڌ\T3* YʅYgfWc> hOF ~ \>Az%~u߉3$/4!-m ɭ юtr~ ʘ;w>=p}/>_MCsO _l)%ХS ~@q+3E%Y^.P k'hy*糴eu~!ѓN8X/i KV樳Zq($댙nN#EwV|lm,SxX-*>yM|AZzIUtuaom8E=yùVI|_`d4oM_mCNw/ę-wz͘錰/hާ&v $"d]H;)1ҨPQcmG^_\87C/{Z}U̵rb-?lwe<1!anxy]xEG.oﰅL f"S~907zr4+J)Y:foPzܳZxbr71{X*u `ɀC++~ЄW0~Arjbe݅T#Jڵnam%r1=@ʋ~xa;ZjQ`\)lj h]ir_ mbeIRQ)#@ 1YJ?Q},r&+/*{bˉȓ}",TWDgzi:p۱.J EOgD* Q,0! OͅQ"4c34O0n h~&>P(5t2. u+ Y-?.;!v =&]L̰On `MY7X6ͮިC3Mf5(i":qѝB9cfP2$ PЎ-1-zd+nG6/S LT^Fv5L@s w.Xڔ[鑼WL*π/ ճ:\ő{:{ڤϣ\iGST>~QvH]1zBz‰mZr6p&^~@=[ S6G䷣'.RWWP"FܓTSC{)k8>̎OgZ=345)dLxWKpl3JVޯX6UO}xB}݃?Mki*C*4N-UQ g:* (i:w4Xi 6=msVpVn1~,(ZJjCg|Ș(bOh~V&0U=*$o=f +"'v篯'+7:Γk9tB8 c ~k4hy K4UQD^t~8ˊ1G1nB}o :e9CbșA-jɝ4YV@ӘwsVs*hw;TB3:jr}4UwVxc ud3-liz$$V"2-Z4uc#ˋhzsc-r,83ʐ!Ԙ6U)@@Spk ]\l&h,LE5]G:]Z$˵r.vl/ۯ7a2Yop~>DLa'&ě*%F4ڽ}aXK_:D 8_s9Z<#Yms:Q Vǚl)IK tt ;i#'%ukUԭ%hTͥąl+|3_oej3ǰ]$!S~$KkiEbmj-]W]욃 4:L,yF!Ԋ~7f UA72)뤒 1fH+Zizŧ#=V9pL6`CHzD hYxop#dL5i*3'S"j㺏;Z$&:A^ФχL7,&dPN7r).ʎ1Il3S2<0)83ڳoٕpUи#Aԩ3ʯ/W52q:@zw3]كINnnߜл:z!Kt5Y?Xp>{4+y!s匓Hҳ-Z4|̆C?3A :y#@720}? sYne.YmXw?(֑RsGe?)& 6CV4JQttNwЈgK}ݑL٢Y.6i$3_F 7ɎZHs7:3eZG6\1j|@i+'1du 1qTbAt y tdy ,0UA# Gb|C~CaYo2ڭݝ"c@e:_iaEfY4z iꖽQRU}Ф/m=KB^c,|ܣ@K`pfI qݩ9;[/׸$4K^ppuq6S'v@uv 7h;M@7H;W:?Q|f+>#+D{elqG{=Oj}ZsO~m:w8TحL $$pUn$pEe^14̿﷩+A;aHwy6M:S~}0 pp ,+;>EwUõ|j9|Z`t2?Ԗr4Fifiu]]Xqg&;Vq˴+9ίS5T5TnYUaĊ5Ht}myXC# dWY'+1E"s;+/]_AQHU9vĜƳE'Wѹׄ>JҀ;R+ @y):x`XhKX73kcTZA8ɳ:-iOR{ *YQ*`֧&M0 ΣAO(%f/=%Cl6E%A (`fy 5eRT\Ӱ+jIkũMgvmgo7UtT`fq:z߯ʯU3d:˰:k\I= 7:`kR/dt\fR*Ծ*:;,s7-}Gzx$"L7;rDZmpDo}Rd]ZQXzɾPy:Tιjx+ =RU/G;'Wfw+x=Uc0φt8޻u=ЩU謏T̮0G/G|C0alnx(y S ۉ]9x}PZO}q+sG *z~扚,hәLUj1EkT ,4D] qh7Ts-8V#X`:03C#9ʾKbG@'аa]g_H!MbdeќHtQϣ- /ycb҆ Th4G^ZRk&i!}@;Dh5?x\ux[1FxMۑo|W7쳣 |=?͎fE9g%t녨gOQf5ihqo\b)RR=ɓ@Z'c~FFmBV5㍠kYCfG-J H ͏q/o.7]/5G ; )֯-}@O-|]VJ 2lo< o} \i8tJ.?ӘW9WI.1AFDk8 (0xO,pd[#~w:i ~ Lm:~l"*^`<3Ph }'0 }HnJW`Xf 4@enzA9 !G-FGʳ D mL?b7'ƯgW)AGW.?@KGjJUع9SnbH<}BiqX-bu|QP:)8qETőm˟^HG 5/Ɣf?oQZi d,3 Wy7&Ij)o<Þ3ſM\OQz1bt;䉵!hbUP־zx ED9a_$~gsAh7J.uc{红0o%m8I$kYzM'|BtJ-+Ѫ5c2rт~~aD՛]G7u?yg(<]˾,גSUF,__JT㮦'\A0k\_OhsQeiC3w]@b0bUi@H<|Hl36SͰpL^/@t 0 8^hz:k%f1j};%b#hm͞/C$R0/e3KH#<ҋ^]oImoWrl&)a;'g!l䇐|`jkΕނ\OAͬ mp#$_z qHnt^%j%d5W:qyuv:;_@*ԎBSQaf#6ݯt|X6Ux'`7_ D>s(G-RICr?P);"[ch^ans(R!Ȭh}#/űRde5`~BaQM[]4%h-թKP0hW[8b(yKᜪs 'feaN }11yO8"Qt)Z1ti.bX>B&o[]-[OJM#YGk[`a"rIY싟NNU~h`ֆ c7 1 Xi$97Vbҍ,>!41wP'+I~5efBUXA%Oy|hlԸl=ͮeds4yj%n7߾y&yf]!k|Xa ?@_+8MQ%ؙz-W{4kC}VR@/w`:q3XSzc=) *ݑD ,NZlh[FzۥRҭnʑWrX_Q<)ȉZU,P A80UkXc7HQIw{s=C}ib+Ax7s- ǘIYN澓56el8ZMm×*`~c4n%_ 4}7CV .wZncEWq iRO, CXG#Ժ]usLuBbZ7dEX65b\$GyͰ9MU{?H{'ΓȝGZxq=276jx:Ӈ)QV|l'Ӵt,YR^ 'ѤPॖN::D')`%c̪![{K fin_\e1rSysI{LF4mޙq5: g_[y><Fء]UG}XEE 6V.E_58 vva9Q9^Q{`6u+ab UHzDфz*0W@(m_n|!0^/UXp詔ܼdOlGu:DdQй3؇Dyv4d(PZ?GVX.:ystJ#&"p@D`*ae4͊?̓`Gwaz45U¬z{:M#W(|miGԵ'XVG>T]&],(X'b&ɧ ~pd *H" Ԝw=Z/sTuQ^X2םqO52eԴ;ɏx/ F/põMvڿ޴6EАR?\6ƔmQՆ+k:8 F'Ξqg͎^l*JЍ>8*kn\&di9a3sIߣ^a?}.DVJ'0Ԓ{V&J&2ͮ/0ά|6H9;9N!Um`bDm8mVjV2TO睒jk{mkxF=O/(L"/Cf826* +5HDhZbZ\KxAY+ (b<}QU!\(鳃oesEd*"#ujyAOژ˙7G u yb#>ㅠ)\$%͚:ѺU۶,9R;KД{ b@2}b]Dדцt*wՙkbiҵۀ.8S%ˢs'* Z'>=v3ɚ&bnW Ak 4E M >=wv!q1EӤJ$wDI3oqє$΂sMX74ӽ. $b Ӣ,BDɍFG3#Go~Sxbe"G&hAVkt*{c+*H*/YaoPhx7~,fM<=8 a]9^EUhoK8T~e@Q-/5P:6 vCahμA,tp \P~} ~}YfG'8:LR鷙Q? L 5XFaMC(S(?N1gF'@V-jᕧt\|ѓzqni(?&a@Me||]M'U,=F>},bN &x*+TGV5,|e7CxSSY#]B͊iY11\0DE|MIS!ŽżYXXʸ}'3JߘndY}3zn}#K.vJTgLvMļP:Ės!,U_M^9p`shQk>- ȷ<`h)fwCK9L6Hp0im|h&8Yn4$> 3뢮6J/=5 ^"U9*D25LVH^C q܏miϘ1.KykxݪhSK( ɚ~on^vhVZBۣ\Xyoǖ8S2ljbY^%?@;40Џ S[RA𭟰~@8DERw7WkT"8)y,nግàMl!2`^KcB$yωNFV*^!Ssn\G+bo^iLccǹR^'^ Q>E-6&IyiJYK2eONwDnj0NCa?\HԖ򅝄)eSLִ(֬LL(P !!_v6}: bN.'CcT8x?QI 54Sɔb~!Wr^p8;M%>K372VGڋfxj;qn2Q%T ;`y|H^YBE+~</ŧ;00hN]j$4F*9?h)2/)Wz)B> j;%WWH,VjRj.Ws]LHo?ɋy 72Q*; 5Ss*Iw 40ʚ{ NʣEn.|Ev$SGp*2zN\]!+5 \<:;zGՓcפYK6L3zegv\P矕o{"Yܤ9̙F pX 冰jOZ{DB{2wa&atc:V9\d( UGop H&k\X[}qԼEo)g w: Xz}J|hBd(fMI|$#!ljZMzAԯާF*#TF'#Y#_t?{`+nZ.ɰG iN=m U;uG}1cFTʳ̿kT2o(i_3Tj:*|doq՜j&+_HDcʞ5#˳pp oP56\N9(enߟH-80:Wȩi9Ux;S,~@"(k%/*J=A{ Z>MC:K=]"ޖXR$ᘛ ]RŢ{ #cb6n2VnI}G2M3m#ah1:F1BQFO4]&SU)hGI;}uV\PSh!5F֐iC_~ ~e".HݫkR #EX+biorw҄gϜ[-\MTrV_`c4G>C}GC];!GeG<rknM`nF'=%!C47zJ@*#;nٚ'&VƢ'&5ZQ'sPZuIݞ&ssؠ'#BBT܏%$P*o~ / 9ZT٧G3q7/{κN8k%,,|D'+} o]K9B.u,( WDJ{zom]SX G;Xn 5{L@R-|5wԛjb$-^."4!~Ğ.:ֈK%?k/khpt}?5GWlQ5g^? T֜n^eRvRNrt`z v57|v_M";GZ3spne  ))qӨL54T5֜R(D%V+ؒIѓSMqLPd~ZcO3.rZٞ@ kCuYX*!,wP8 oJ'z4N#+}#~CX:0,H*C;`vrh#_x%Ùa:iFW.!{'OMδ}Lx~Ƙݕ%&#^%3~z8s}C[db"׺vpXi eK>(wRHv +o6wH*G$-w,XQ(TQt<:W(Sz eHչ@9~yއ^r^VBFl=x(˿Dc$A ); !ZSo鑆~5zܩgG5GGw_:2K-b-swKMƶ|Mk-d};wA`kV9~Y*c6!)0%-g~/BLi#ߔCe*7)ʢRSgYwcpݢ-KIЙd6k,ݐ/x1Џy8A)37Ƴ,wI;ѼRlk/[V{k; `$g/uԨ F4S۰+x&a|#Ct t;uQ4`61t VhN~jxKy!Bb/|D;EP=瓛s ݋' {fkPV Ie@u* 1RªщZ?rNW^,$`a GTuc8-8),C(jiq.kFf*?CpWV^=M@)W% x9yK3rN'sY桒^TDwL,+M-B"{QT|_h@Be ΠG }'eb)g5X̓|shixY0Rz8z~l ATkiڻ ?-I$@"e/WHΨ2_ǼNI.P^#\sŧ'Sh`1oKQ?mސGS1%(4$5R J&c%1,8:jTիxtsfu-NH/T_hn0uv&Hrhu|l+xQ,?bH*iIdVMlzQ"wWtΊ(.m)#uXE[ikkBQ 87p*r: U0Go :#跷@dyPϙU8jN 5| P)Ά;dVAm q. gL妟ȁ+Lh~g&B~SCz^mxj\_)BQ_RQ#;@zŌ/;yg(nɽ^%B}Ѣ+24q}wq]v=2 kK&PYh}"/tؗ MnLqvq3W&߉DsΦY,=EZCRiQE~[}m)Dd8?ī%h-\ o8 \ySb̚ PLɊ$.,d /1S&MWDZl#:4w"\SC-UPX% ƊxJ}WdEgW^+ƘXd.ϵl슮5wU6Q uJI6\rGiTK X8vR)?<}@/Xc-л6HkwZ2 I({Z4t|}.zVvW lnhQi;`9ˠ0g<#szQሲvS!~ kQ0LMt\Nd䢬"c|vi:dOC 9=K73ӫ0+0X+ITO~!fQ&eeȹI)}\ |xksԊ)jb&H)%ټvzNFGFnԒ /= `Jb;|7{bbbxzY!kݕb~쏝87^IS,5Aġ4`l[HV#C񤌛j~{%MA->S <{a:AdtP*0nFL"4UjEXT5-;7Lp-5`Uf#)=xF^o ftyV^ӻ|;đe%o'$\ .9, 6\+4oZlt `\0OfK4\YLDrO wӬYviT=PO !'VVǹ|dCǾYt4 'M5X\2etT?8qAk2mw8T9TفiO Ԣ ek 3Esmk)Y"!ɽ&'q NppnZzTj>w:r^0QF]p3yZKj[ۼ8]3 \p[=~:&MjbkKFQ}ڟ A:$ΕPo(GU{FͰ3li[s>֙Gvu.6eY+I ]|߱Fnӏ+[V&PH>U~Lzlfs[ΓS2@/}(Iv˸I1]Ln*%!ޢ`dJ ʓqWk&O_(JU6_YKw~weeӸ߿ԕ;/N,4j a8Zf٬ h7=Rr)UtNP}<yutW,1^I >`<8, ߜMbgM5z80X/>渏<1.G-%Vz8ȹ9#[#/{/ё^B՜֒H[A~@Ys`9\ =f 4]9dDڸ*Cyi0;IS$P΀n2.nZQ@",>ϷيmFvzM롘NJt%\rQC^!sV0=*'*)+lCY8sx;?; ąhaiB{Zu]^GiȎɌc<>>(4COjavu %bY31c@,cPrOwV -}Oe V!MXm Qs>yk;d S;ގbÉi/)Pئ^rJ1~jqsB@=?rfR/G43kƵ/i͋~DOumܶf'Tj*z:[߹c[_)fUX >t 36Y,YUhzIҐ+#ބ9KՎB^+x-}W *= Nq--ﴣ嫬gTE] sLW  He'qܛ8THu6y<5%:hYҙ0챣/=XGn`rXl^gK VZ[95m ^ ;֒|+[qKã~l]4vr~4:&K{RtI2} %iIJV!\_ +cP,!zb3tT}JAWt'sE,V |W~:-=OSA=a,6Wy=Qv<5W&j\OU1u& mC-$j_0Zpg k )@氯{#Æ.NR'97'WOd^/jG#Z+1kf0SUjudP"uH8zdu%1 -t/O(K>vW xklq5 %F)em#s$;bg}1 u(zۜQoVmV3d2 :`5[ot?n-P[8$r VL;!@p;,]oGp& J$c>(tì!n17~#ϲBV>Ǹ>1iAF~YU<)|BS@sG6U!)D$8>;%Fka<5ɷVn=%hw_V,B|>@-ٕ G2IU8A'zj"۩\`W)o8"3o/ĩ17Ո ]knfMyjWJbiW^g}׈Z|͗5QW%ldbƬIlK>h !Ŝ[u/DP2M6nHnc~oCҊ(8 k.Z_z43QV^H>9FBy>K\Mu.ܨșXXEMbcn6Ej'6C 3g̪.(:P4eSj95cB.P[JňhGSa" D+%a7At_d>EP *=} &[sUYW*VwKi { a;t{J}TBOD&3Wn1 uE6AC7@Ԁ .s%*Sޥc Ri!ENiƬ ) 7}XulʧRļ l14bBb]u6i34{1B/-w##,\M]G_I8jԠ$}*VPrv7wPY:&7G/Wh}-&vJƪB׋ӂ 2@63netCP|%2z "[F3\3Y4;]y]qmB'D-`~a* hO<|t w|y`!=SJ"_)%Zr<WˬcNuN:m"\:\_ԛr՘fZyp1hT%Ai!ȅ3^-V8H .>YVb^蘜:|+ĉE+CUps& :ź6ٓEV :'\܌*% 7V6<3Q}ٵ 3V\e.ߞhxE.bZ.kZ)2E+J)Jdnrcɘ=Xg#E5c+f7*NK+NPZt@V/W֔33z*xG\NLd}M`HP*4_(j0ڛ+bkGZwUF׈/QTǦmwBc*ZK8wre"֛W$~*NJ>2vEzˈ6űG 2k)p3f߽LRk hHCC=jh/AP$9Қa#_(JKجp +A,:_.'X;Y0ٮz(I5Q\"ytgElju%,+$URQ{_rcӘ BK;em8XT{M(/bzqpo6I(s?.̧ګ7 R{zc=.;fm`#4h?83{i-O$@5Fk28|)h_q7^ ug&Ҕȗ4%l[u~N Ű$t +D 2V;н%B2_+#djb- -Z:+P9sVk>>Bt*yen8ܜąu&:5*lH<(XML -ڙS#z4rVg ;?=P95.g,=<nZT5[ms!uפ`I^NޢNԬOxz½8x! -/Qq 7kNMmLL @^^h4O- ܿ֋sWh$o3Bz݂FN\"БY4g)"yK!üsjf^!S0'GS1+4 vmuAmW2<3̄ŚU-M L7mb-=4ѨzI (oߣП&&IQ.xXK$uFdD*%%g*9@//;p,? H0GY_= >^1%Mpי{x[|U{q]b)?XT6Vޫs]P "qx*aQ}5k,4LS'G澛Ʌ੄iݐiZ ņۮ/f|9]eLmtPsA jDLu>!%x%֋vs҃Ґ=EF0Ҩ~HQE 7d sٿSatL6#׫ȋcs#K+zGE-„nZL թEA#:\Ew%bB8rNLЮӔ/:Px q鼧vR6ZsY8Jw)o?z] `)5h!n xF<+ 'ZPܧIiʻK jpXbg͐]ttL^Ox=Mn}!F0,XHs<,^u4g":+> v:G .U/܋Lcz848 6؉E\I)AI-RHEg +WØ d75kW ]z@ùӞOC{sڷ7̋/wɬ\GQgpxjn+ \dBi|4+ F#ӠʡkPԀvgԉ?x# !8=kgCHtDRyϳɵSDާO6+.²hʢdF8'Zy*߉,'+@kgLt$#Lh`DNTQ~~hvxl <_ i2k\OFqj熸0f r()8ۦs>D!)_"_134|usE>KpH+i2Fy8O+'}#Q 󌮄^dU1/(lbך^8ؘ<(Sepq֚<5wWKYdUI6,fgU,Q+闃L t^@3Tg0uB!P}T aSÙn(t̺A7ߑXjx!ss,6K_-{y|8[0#Y8BqL95+O?/t?]g"l'pE]O#C G3.V#!L_YF 'y@뇝#)0X )ľf2 rFȝo@]B#NvMҤ$I+&|P;|3Q.TyuC4*1  aΚg.4HY *#O5+q_B-go*^}i?JHhu"U+lZT+t71eau|jC_CwTE95h8j JC۱R{qFv%DfS ,7b!`nf9qWU9oL[JYVGhE4$p|'=Xfr <ڼNԵ0(l_ K->蒥pnZq>FSq}t |Y MnDCr0;QZѻ(9Q9gX3'J|jF"pb{M Ë!NxGAQU~{y&7wZwxa'>P %(Hybl;4m԰F-^N*cYciYV'n8SVfM@L-U-c/xoTOfiMРU>+sZCfxvzdKwFĬ͵fѹw:31A= |,)A< 6zCm2 N5R E1iR0pVqk]Ts*jX[wgEz wOY//a `㐱^[S-`]g`uFNSxQf z*aBkϖAcB46a?))`|dz&rH:{yy2'MSy\Opk$ $:<#.)<+Egy' + VfcJxs/E]I*fO7q,IP3dzT@ NIGҝ;/$`jǫrP8]g|.^'ܣYO NywtWΣF6!M Hz>.lǦ aPeF@ Q_`1l8jp}XhCFCI'>P= /`ΓL^Gkě^;yCA>$'6#ӗjåhPQW֌)fX]Ə;:j~&1~RgA-k`9(w놪Z\|Ѵwl>Fk՞Gvo!:BXY!Kȧ%2}.ggZzWr>Ѩҍ=aVf"8F`E.k +v .d| VÙW!AJ?鑿ZГ' eg!q.M$8XyhB{;X$$#&K~FoRCle~rژrwo8@t]vI؂I>/َ)y^WzC&iqyE@E^J=PW^-:b b&ʦ/n`(u}n1uCPS u? ٞCgF["=íq8q F5*É@cG ɊJh_pksFO`{NN4[OZgE Y'FXȩ"w(AADbEkM41wC}|G+ā=%ܐpWx3U{E3ZlD4̌.p뾋Zj%›ΰ԰:UHwifc3]<MgI,ft 1v~y9yK= gh=kt05@8ש icxT2}zMIqݐЪݶ:{?|vȫ)[ V-F $"c]OC6fhL5J&`Rf" Il\?#X8""n$? I #,|Lw n)6Zpk [v+ $BXvt1 M Sӫ bM*(U_EYWuQ\S#!2irA\ }N$U4*F'y8ǽ=ج.wdCQ @&pP]z5&3s.3Lz}ΫMOt:h&.Ѽ#1y]ȏF,ϠJVz\+zTg:DF% 3Jʏ87s!4qʭ&ɑA9Gvs:"C]/TSsXPS5zRGmэye汢WaCrnv՜aJP]{9g{3q-_5"Wt7e6xhC;}_wP F3ppUE-Z{%DoDTXfrʻZFdLcc.^U 3|)O4'*UT=ڋXҰÒXI j7M/g2(5ϤqRixLcjEƗ95_=5q?x1ˊEUJjlP1 8"[v5f8Zf:S!T7c9?Ӫ vc~(r{nRK{1|uqc ?~w$.-ޑT9שKf>wa=fT0-PXz좽a:%+`CӀ= 85-o&'06p&*\"Ix~B@őɱ mOѣ핛+yfQ⫕5snib[z@yO56oWtG& oA چ} lEe&!TZ@9۾W?kby*Yؚ5/i4dDIQ3ÐmN!s -rnd[V>M(^nWV#랠nV9xNFB逅|Κ[ys`͙¬-Q<=BVfmRX߼Ew늴#y39z>4`'6Ɨ*tZGy?.wX}[-]'|n/à2 ~<rzAᷝZ<{ɂfTN 騚IP| # Έ^/VvH7kkC. ȝGhp`Mܢ%-jCXH8{~e/- 7Et4?󨕱/IL!҅T+-ӄ:^O5*!^irѱ[|˚VS5_ooM͝Q5\͗CjZ!MGJbXQD!'(A]@$ciaLN <Ȭx; xpY9r62Z\xLyV2n>k4U>lkL٨/S zaF.^BW$Τk"c2ИSÅ9ھRcPT_'î!5&fc;||f [+K+|7j?,əXbJm/MfDeRb;Sb/$G%S2>|8O<56(@6kYEieN&jY̐ N*0v\n*Y::D9M e/Y{EDŽh6%ڈk+CK@@ڗ&;yGH oC]mӲ ꎸ欦}hDU"0M|۱5a_gߝ& 6Yhf@qB^tGK8 6hf ;~ H:7wqD}+)Vhge~EA/JyDWw&~qy6bIԛ901S5nj Ѱ_်LR5:$i2/2ȸsnD:dLEVB}\cL>`?f ރ5& t ||-z/a/ (8y=J>qjO58 S&}U:,>$)c8v>Q,}pb/FRa>Š{Ż5RM=XgnsN/VVg?kh_;s*v 80tC?@iHGɈHsCgA#`AUФCrjv&Y(Xe-TBI?8{}5}cL=n]&T#T'E啂tކw)ĥN2@M@'h' YN3 E9 wRB*Bݞi=C#8 dRanr/Lh]:dF_`ֱ Xf3 1wP^V'nX;ǐЄfjŪ뢛Y k+>&E Ti:4H}/ː(+!=KFę.ub1{X0W^vltt´~TMիfM?[Le˜'xW`10ԃudMhC3f0#,)Ji$#8\SWzCXiQ3C2Hat Nk06V}=1g"\cCOkdjZㄲ Jכe){PbG"cԺ# x SXXњ=TuI1w)B9kP%:C *ʑ~JD[|Khzr~zR,?H\0#iZ!WɮO#2+a\&~5ψ-.ݧ:XP2gR&=R@1dW8 <*%t>?@ުk-S Jٙ9@Em,J ro9^uCm '`N#;ˠ 3=GzT_Tf6&+6Ɵ[0{^dr|NLO>4JJzO# XqЂ׽TJT<3srh.;yLOXӽ;V\!X8=0$L!U^Ap:u`4fv =k2֊}ܽuxD2*E*Px qg䘸~U c7kh xITRm ,9ҺN'L@|KRJ8JAW^K112skizKpKk,=gufK[yי.`[p<`#?[Ə;[ X_0TOAN1*Pa>ňxQZ#1⹜C{.@}OwTtiV^O:6 Ͷ !uAȀ3JyYk"Ҷ5GCy ],k5׋~Z4ۀ4yA@q4;ϙbVq?r1nG.fFu gz8A)#n+:?s 1VO@uhьlu+I j_O86䆯9t%q*$a?sAւgÆYs.T9HþEPm/NOC]O'WZ[K'kϘ>g嵨Hz6|f UhjܬK9#9yy|ݜQJ@_J=Բlgu5<.>қE+ 38H=& lzYeGz1#-/ʸ@㪙bTx IUSN.Ӄ/Y'ȏhPJ&Y3 lz]'hA;kx]ڪU,t)eLC.Ivoǥ22ޓ /84$9ʁfa-Rj~K!񧣥8VM$)vy,f^եf1SolÐmvr*q.Jyݽ ?쇶L- N3x{54ʴkkpٱ"fM)È͆p:95]Ҋ2k?7i 2&~VE Ȳ`/PĮMq(`;# '#!M:u*î8PKlMGnY+VOb&jO&V8.:ջ͍6- !}]w5LtEz @ tn 钷kudinScL> 邭 B?/8/ë Ϟ}~]khhm>詤Gs̵X[ȻtET A17+0&1H{3s}>̝+,M5o:,~`Ϫ`UƳZ>̴+ PoNʜX}bU"/j4 F /Pi^ow4$~F#%,vbQO㭞0Jh( ަXr42UN+kq [Vt `fW͆܆mX v4{r邂VEP> AX bYb& IZZLx8p#0+=""4$6DzcdDMJ AD:'e!2QI1^l2Q'rA ̃ #^9?NB8SQEv>89Ad&5dA9_i:-0*'EК0Rk|=Q~5iq.16P\{I^Lڔȍ` C %u?U><}.ztrK*xQ13tv"ONF'c%zEy?Yy?v¸<'qLX<Vs IpO\Tۘ'O#hz"_=Ilhtx[VxȆ&!OөP籒VkOgR **dJwbwדOH\'?հ) E!gvMfN=K$hz<EW6LXrjAQKw?W?NeGz2"nz?5~K}w WEs[t|l3 B& d\2Գb#=E/x#u0^̈́AjS:Ą-xBw?zژ.u-ꑠHR!sf=;l&9 -zZYw{GF>T+8IR7tRd)f !'Vq#ia}QXq0`Iz?rSv{ռP{ԔN̺x w6s㜽5wK-"4I(XV)ClAW6Ž^/REJ~äͪ̌M5Q^z &31'Naʣd6@c_ua4l.$fM$EH-^Zws?tc"ʧP?y6z:S0'S@*m=#\b̨E*ڄȬ[8E[f(2 Qd i`zshZר-%~4Y)@EzS2 HF23¢Z @l`x:ڊXn CU Yq^CHc 9N3Z\qU4kv&ocncUSQ=.RQSDHmzʮeE,}  ڤ|_pS' ̔5|5|RW_w2ZFm cGf68)GH}>tɜ7/۬'I`=\;VKVMWR,=ʞ-*u'%"^qÆ՜-Kx^w1윝ٙ5ktWKQ' +Չ#pUi?NP:8X0+K[&5؈X9HU61i/Nvf֓;'t 2G>3GWϨȜ&k0`ljY>DY օܷQC/ =aW~[̎/LzxtuN$$~=@ xŬcǐqL&bm*A1^gִF&I_guF>(/ʄVuBztms># un=ɭX4N`kcSetd>FG8#9)w|RnqMuA%wP?,Q!NNwT]Ǯ9:g SymNB^'LjΠ2)!>l/%w;4N\&Cd\4;AO} ͙r/=4fR0 T;6ZEޣ"\*5~^9*mk+ -.3yAD`Ƴ.򕽂ቐ=F4G;A )ԭۋٛiu9y~U7UQ1XLGXgSDsubgPWS\ai^|^Z1QDx[!J'祙 Ēe2ݺFʘ=4=@ T均$ʹ~M:( /0Sւ!K בyЬ UYbQtM*q~T*I [OHiשɢgMm,cvDŽzω՜+酗<̆e*jKpNjX'h~^ 9+$A't~@ffQ@ƙM\Lj_x; 0ҧ16~Oz}7\Jl?!)=X9 mBb^ʬ.MkYқ=1TR/+NynE^!#90_r#xЅRdAPklN9,hD#y]:=ʴǤ5^sv~b7kzr,4hК!iA;p;F3f!4G{ҽV 罰8Zcm9L):Vb1O9U =S9E4Ԥ3L Qp MVYvYz7DI+@n@q.8R4m(躂g2֌fb[ œY莄S(o#aޟػLĀjrĚkA۬:x(QR+ZFS.NH; SzI/.NbdHaź.ʛcQx:|uD S-!CŒ͚eONo-f$3-z5Z6z̀(MEjMݪ~EG E~y8JP|$Gf, 3@_njm8=-'SX >= tbyҏ_)-E~ъ8}:ӡ; J8 x$+賲 0% .΂6Lw"uOítL$NXlL.Фoetvw``OtlVYIFQPBmK9~3o*dž2;,釁l{E1Y[ex.+ #CJEl S۩y4ꇊen%~F R%lZn HӐDq۫J @ <УiId9Ld!Ùj bC|'C9ikjb7sbH) Ez /¯-\v26z:ХK%;E3k/{n-^1pe-l8%ϊC{?d>xiX)[W4~f2 d`vZYѡ5=xpJ{4I|K3ZZ_=QfNZ|,ore ǧha]#q3"&[&6)طh'Gc6+)<8cRиQsg{t}9?v 4|=eEv+Kķ~g̉r.tU¡= 98j\`A'}hvyMOg*Q@ MMv- FTHZ@ؔSRb+>:̌;Ch PD&Fc~k:J)h6W֪ȯ' PTL+ݽjq~8N. /G0t Y\޸&$^4! nHnB׭چ1cu瑲2(3 R9Ig:tq`ٹ3㩥wR$!qD|ÔIKJz=0;_>yI*2e{2tZtp]f1׉34# #3ƭөs3GBhp1J C: b! v7>5 )udmIMXҺ# 4iܛ&!= -$%Nj_TcBJX_>X-̓<ypsf65</jm`5)xs.Q) ;%[Z@';;AX ڤ&^j5c2" >;dG?1!q3?_|;Ζ{A[F>;L1kT2T6s^bkmu i]N博2J4 FL\;<yN4%/k]]Df2P e2ÈMp^H7U5g])zyܴ#M{ܼ/^v-(m|Y{MB!W 0IU[ײj5Sg6^1[D$&cĺ>jpHږ½> 5Tу_̖XK˵6[C tTʩś I?bq 5B%y~ &jurgW&՚Y E]Č Tk|H޿:OSub4u2(Z?N-P)Ub3Q (J+|&A~h99TI3jr?a&>?-~wy(?rʝVXxשǏMBYҏ,hrr*"{&a Pi4Z`¼nzݽRiC`S45y;=l MuFlg ʴ}Ho)xDl7Ma ǴaLLXɽx (~LeE: '4zFC f9L$$,/Rs24'|L8GQ7!< {1=Ct-:<m_~~}Bx:9هOtSAL{MBfK;YJ0q'0b}i0z,v|I5Lr6.y|eE@"ϳ'CE+G0A$"l)^zkc;)s>F.ɎRDJZSNEqglkXXzF)zH ? MB%{"s;39FӼxByE?AXM!G4AmDe%Ȉ BЉ.g&=/g /fGV|hS$JQ@Dyz6-j:O>ǢSB͟8nyǫ&Oߙ/l%0qoh^P:̻ #9f c"yh;BH/KTrsQA kx}<6x)Q&3=jQs2SQ3:P 6JZgoH/@d\k!ȗ lbc:2teX}=ʎ__0/A24J rD=G,"]@ŚoӁa>Jaܼ؇De $yx[+$ AKī6e6|+r0zARJ=aXTcHX7^鱫YeC+;Qy T+Cg4VB1 o ^Xt>̔'Ç3V8;CT6K6|V$Q@vF]lufVF ,8 XlPTW[Ɋ}n+*8O<+Gzp:9㮳>]r3{'g[skLQwnjr +#7G\xKBmk$rR, bHG#E.1+"3o9lde{Gfֿ$Mf!n@e  8ϧ^CZ-FRa_9ÒsqPo}Vؓ\ft=<גJr?=u! +z)~^hTu!ܫ8cV# .hx-r;>%̺l!~}2w` '2ӉE9ZJLwigû*V:cPJ!yGӾdD"߁-ipgL(gѳltEJ<hYIKdsb̽i,뵉=1W`hw)lkfR>*2XY] d8ynppaUt7i,~PrRL)y*SKwe;f4LyߜNj}5tGFxGȓcyQyYgT{r,aeI7UjKwAbm!vs;3N WWZ5]|:0ё)[?zD5DOr4=3 UaZOƫ^sI`nKJT~6'nf|@:V a1[LH"Acb!gu<~Zz#PvTcW  B,룔|M u Mb5 6, Eso `5 +;H,ƥG)o)"C@7Xdf*#%W̓ak@;߬Gt kh*JdLJiaMyBM2]8ؽP 6M^ ӽKf˙ϯ{duwUtH 8z?؃&$uqUq/Ѓ[gV̈́jSq/QKGDxO%uxO3o$+yPo_HESO'q?d<3ROҹ<0go?nYO$Dij/{ڈi&U!B{Vm"4dvWSL>/n==0(R 6ym@)z{ NGjCb{Yb7wUPԏ6ιxE̹EU!Y ʷ{{陒 o7t.5D'lMCeE$ljYbQkWN3ƠqpCLYJk"o4Uj>~2!sM0NX00:oj-[]S?>XOg^+_UTQUVooefӑvAOX:I99+h}%f0mVjPSnaj7coL+s ϧBt:TUMk:ov 4vץR:$xv  E;5_:)ԎO&%N˦4 w yĐcDBZS-g`7uqts;ؑ~] D<39ev&)e<_@3[0udf2#*.;W͊Җ)1oi6\_IдG#ˆS1!;Eƫ;'+Xw%Z?/5gE{ Mh,*)Dp#uZpfڔqͣ;'4a8Cy G;2/E1l9ݬ\`r+:i϶Ɛ4&6AYK ΣR>8̘C0Sp~y7{vƣl_3{K$$Opf&:AAϷf|^ׇ*zyRYtQvQt"-|8瓇3$_|;>(VS7)s&}Of˛ܢ ݽQd4R>Rݤ8κ *,.5 ۢLKriQvt-76h2̥dɐ_FRv\F<ڦ}舰'yQe2|{|U] .QDUKkOlD@~ュ22O9B1h4.^P#tW>K۩Y(7B +Z,z&F08kUu[CZ\G~p{QvLGeǐ./W1q>0ڨ&1nx"6G(#r6}x8 zbe+Ӵh7oI _P !5E?t[9Kg]W-n 3|OhjV^y3.9K&ԍP|s\L^ fYYp,4cG3i App"Ed3p8 edV퐝]6k Ӊ,__-! Ykb<_Wvșz}Ƽ8V+ bH#!r$xH]_pW"(͎ 998E C9%/Rx͝:Vī|_$O׉ Όڭ5}򕺨JuYVw*17\a6e}GLO &!H r?ȇ ɘ Պhs= ̖*3m8xYdA94ӅYEvѾ:>p XmUhH6-K`.tCsF-Z9]r.SAlDLX?| ]y^\v# 85Qv%w4">>k pHZM݋M]0&^/^,u dl%8!n`U4r} F[*bbx8)XRBkиox8u*j  S F"N-?JnRmƻzc;cRSӛ?R/씕 މ]aHݛ5=}C Jw((G]C! t3`=t)DŦ4аU x+Գ0qGvOic|ԥF6sVk֯.AY![,2SbJ_hhEmt$,ש:u?{JRϜno{Y)AQ#^ʯhCچ N+;`5A tPSj@8|;*RIhrkSGXo:t1-;#r4³3HfDJqtY{@T4ӽYs.b6d?w0- C3c׼qb!B,vtV~cvʝqSZܬ*#̯# pु88~7-h|Qv[C؀ 7]7A,9qKP #!3gM}Oy fPLmwv4E:)òkoV$l=5 ܿ!qX$xKqO_#O:Egmff/hQIMxƮ P 7dh2b{^%ODzYj0ҒCJ@tBbb84bQgw]@rpaNϬ|lcC>%isC_!AINE8By@Z?Q sdQSμ^V@˴C gEw>Fo[΃ iy- JX5FzQjԺ2SfbѳSJ=fJwSNւD" ^y'}Rx9PfR>5_0e=kzM?}r?:ma@B# v~C5c4hb&z8d5'(}axzӢ1{t ?՜+y7c3uK.Am8h_EO#YvzxiIB}DֶK#MV>H`%["w5!\Uv7GU~{8V$wabUǙ55_hS-JK+U*z%VTȡ4 tjJM2BzlH=qs-RV/-RK+wEדǟ5.Ɋ?ѻ Q`YaB}`*Mffi`je•F 0@G֕Q"Wl]7J=!O,/RT9F+U0aѬej1՜s>c38O O֏kX;IlcbdPXo[\klky H!GՠpELVYe6xz5 ]A6Ԣ]->5z8mD9#l-|8 j]]$p1A$`SdAЋj*Z66֊N@GW^!7%疪dG$N-DAΠ~$<௡mN(95qd0?p=SM&O׹$4 1?·"iRvר#j%5s^$9IX{6"=cKtPP5 PcTtOj"԰ Mp*iPhLX*}bQccLn/4_S`'t flj+ljGg[{OM;l ӧߜu4W,Nh?a|isQtCҼ IGڅD䌠]P'ዶ|C΋¥qBMzbtJ#a5 H_M-|.>#*\ӫNL?j|B.M L>d'5o h]lK୿_D6 $3F0+oÒ$'BdݡW ч+eI!ye}_ۤPa(5Mx|Fu8ST/L?͜nijq!9xȰa Y_S tbM< 3|z4!? ƏBRi gYf՟cMB'T8/jÞr؎^/ PŤI\MN9R#D/>f-/ v|0s"njI1Gtpn Y⚀ru'ȭImh?* L\Z>lV%,Psl>[ݮPdSP{'[Y$N/b$fP ȲTҤ-Qko&SNc i0:Y|PU;_0]î60쯊B̮ZU댠r]WCCW$} E1Sѵϟt^ET_s 20&C=$8>+}b*EuoWg5kP%G bP9掐ST0}@v(3ucu/MG ܙ5${TMf~yWXa ;*亣tAƓJ;Uy|? I4=Y+rUOE\nN¸o ?`F7LX$G{f1 kB' Xݜ:^/=ztrAl:Ce;tQKaGN F*k\qz(שoc7,jw:^dgy.uifk1a>Ky Hsoxe X"Zm5ՇǧIbRDɤ&*d `5tG(tֳHс;pDNbm7~y@Gl٪nqog#pOJ2NpVZѧl EVA aa.:YZ#])۶kzAq*/k V1 }4V:AI{A2?n&Ma<1əD`bA:ҲVi笐\  3a˲$͡^\-BäK$JuJi/bu/Y_wihIhL46plwÔ=U~o-v3j_w8K}nfC̅aJvO(3t 8 эauZ#/Ăv?igF 4e5xJ|p1Cxx (h|eMa)t I2hEuwZfFU=zMǎ'0PiM /LfBf-5U4V);'6!יCAcMCB/R9+NAu#\)IΤaNt1+ACՄv4W8H M%>yA\6W[4Ǹ :hs5S2O f e͑x̧|hr mfbl92AL3tCa-jxZ2gnqjР}ɳR/tCюN gHK}G<5הJcǣ<=ѹe q7+"i= OdƔ=ȔwkIݸ*'nVTI/ΐ4䤲B٫!ϝIAc<-Dg, CKu>f S5=뙔E%\] Ys:1Jq&QDLߠYn8"2mai2ZAz™Gfg|nV<qoآቬ9]pAr-cb^sOy=1Ԕ奬Gt.us\J3F W%%~ˠlՊ:{5s<$B`,&x+Uc 2Fk~V>Vƙ£?X&z4kqF}t]@(nKE~)c?jkn<#Nq(񴐀(>Sñb!2:y(H:Pv,6I]yX8ҷe8Pb#fVDM'$U]$LqQAhrw^u7-癐0:Q\wփViruhE<ƉUU4 `+" zp G( 8P 3 `g O13E7_'Mc(VL9`og&<]vU]4Xe}ph(ЇaS4{)~! !qX7bz*v wclaq֛VV,γCª1_JY20\t?W8dp0j@zJ9] tUܟۓ|w{Y|GOKVu4%"++*ZJIw= dîg.<<96UcJH*_i R>kr#͇{%6gjZF@qF.R L];ᑽ/ wT6lXb{7f{"0@%I= n@odtmǨ TV0К̕1'nZ6d)l|6sӯŇL@SYY?*%f8NƆq =_OG 4I/^ Qi<4`M|2ާpBF,XWsjyWsrJN.$1c`&pYXsabmmB=uɮGt]bK_e)'rkbo+-_V`dTP׳~xiGG}z><::EDa3o:{/hhNƿ]9]B L*(yrjgb7,'ҩe!F'XbVrPϲP_= VrPI)ď )&=JJ>Xo ,Iҍo&GU)_ziG|NF"Ñ0dnyO<4+dEBv odrCfD8H#wbNAmdzB (귉a+E)#l3 Ӫ0r>z#[p~ΛޒaGb aRA=XxeSZ>N5mQBxQGȨQȀ*ohhz C̫G/`7̨GbF=$bf3फ; =gPrU|Ia<>P"_hT*>\Oq~ҐY YC"pY ʨI|jn '@yKEA) OND}J!tctSaf^(fD'PE8qRo VqQk{L$}#{YkdiHjZ76g9= Ow;N7 /_U53v768Qc,PN9|T0Jġ(#@3qO?{kBd)]|aq|ծA6U> um``=?ܞi)Z6e?K}yTUi +}u XDB3Sx>[څxڏ{ tRMJ}H&SnVe2ʀCce5UMsüCr^ -bJ7 ȹ[ oFK ҏw'4H)/[@耕g\Gut2x+g)f(!@pݩsy|:bɆm1Xxp~q)w$@jx~@z2͒?ݡ8LpDLp6BPQ'm£5B;%g-1PGpoS8? j!_,kӠfjhg!yh2hV5ZnPeqD9Q~YSctUkѾ ߡMMp(~n4m"9NyRj|}+ZS.Y+?Ǽ kAd5Z7$KaHµ i}~IJ}Y8üe=#zo8n*24gC#s,k//< YyUb}cN@vS:]qc]{zv=l)[$Yg/]I9)0Ѐ2!9P$8jBv`&hs7 qSe+ΎV;h;ʟWVal`>;{=`>j&q~=tFC硙^^Ɍ0y(Lty'ZY{v8Y6kX"v!ϮU d03#{݁eǙLs= t&> p<ro3znp̐HKxl_p&jb,iYu} labר0'ϳ) 1FJHta=RY-APhQIG?@np+ݻ ׋4Ω^'|֕v*Ih|[jң{4clZs4WKm@H7yYMM\ޕg&R,6<4y(]C~:GBa:0Eu>k5&wٲ{91rU7n&oA>E}Yq;m,:}4UH1̖[%I) FL{DA \]zheݝ\~L )g)Zi]2)>ؗKx2hK[-`-|d8^|9XYe3XٟE~);>+O@ZS @~rN ]fo(bX74d$a( tJֹVKdTy612hI@>MAq>p20إ.G2lѰaG'*3$!?a>JH-rh!OnݣyH`4}T+Nvv5}տPbޞWmE AIE!$kEV$GQIfqDZKTDQTu+Cؿ9&&J/r} V]8-}Q=%˫\}zj`zn"hlzf}sg q xjb;vT0Jkr5"d1],XY&Bue@Q|oZjx jw /zzga>T3=_9< FWq.D<z7ͻKF|X{X ܪԙ- \F67krܑO4Jo!]" 4D%y )ob,N9"ldwbmVYnƌ36+tj4 {Zߩ sdt2ͼӅ˔ ^Ol rhÉ*T" -[8eodDJ7}'Qf^ٞA,՝-{Tr&M)u!FX >q0=#$(-OXhy"y"tXWJ,ZWSR{IoiF‘]DE2 F`˘Wm&|DH!#6F,Bc>W \0ggDY83 gΖvgx`{exLl)Fo;rIᷙyq"@l'7mx|g)$ 5/edU>V D] .m8Y ¸{(b蚏Eg=jz̝ +}ɮ-E3N]bӓ &fr*$7]-ѫO~i|!)9?mL?ΥoV@mq4]&+^&u^swm jpe/TAfcuX|J>,Fqou7A~]Ac5bGλ[+] b)ɸ\z&m>MHv1ƾV&^)db&hb dF-wܗdY.N͟h h~m/DBTsyz̨) fQj\vhVNfI 93:@ǒVAAs46_&KÁB Yf4\f4MlHg'uz0'FI<mONvQɻ0.[t%bZTB)sZܵr'1b阉L6笸siM@:w\f }dFcM? :UoW4{R}}O;RS'[˟9b>kO3'4fPZxOӿ(ڊ~3,6Ax4(@s'e6BӍ}[4\rX냚уfm"i5? wd^\'Æ%?ERS/IM`L݊;}YX =JZqEA\Ѿ%3!£6*1G@;p;F,_$Sו\$Pj7DGRj^"7WD;B=Dy=>ZRfmCs|haLrt']$t\+z S1 SÄmQF>zOG/]ɪ}|B`W; +yo|SFO)2q/gZ779OB?@b^} *wM}ӕ <5bz0d:_[Ӑ\{Oki2):ݼxe)2N^VmV/3bS [/#]dmf$ TuH\kP945zy"*,B3~.+&l+yVFo/\NHn6uʻ뤃]?=Y"M/D<I F|-[1(ݺ8Zroް를z{W2˞ߤOpb 23rĽG'poy*PKT33^7M;5cʇ km(d?i-hWQ2ajNj:x)M ҩXP 2\}nldTenI$cIc(`A#Nd>݁Y41.OwR]V-/E‹%M(?"B0h-3򥉄Sh[#M"? @_s ahͭ݌mx;K#r#hcs.FCvf[;PN OV;/zdLO{!듊'J8x?Qhb+VP6e4}}%Z]~,p 3spÃFMXZ>?D>y (e%#(rp?g"aW ˕r ^sdM8s@Y-G(t2V-}UP "NDy7c}B9xf1V6J2,築dbMm7Gh?4Hsmwme)Dth ˱ClhT#$@ !*_bL10M{ w_Nrzʇh@3ᠮʼX;+E2Y0^S΄KK">+r=`8VqXIRGTahOR {i!QBPz@5?G6o=5-~n-7GDH޳ivcĬ\NwӋC}è;ġ`Y[ȅD+CPn QN:d]ݬL0&.M\M-lem/w루57,%IrrxќR8"1X{Es[Tv~P&Twb$9oku&>mioW5rGC^|#1sߜQ^$L^x ^:UPF$:#:ExٛP“*N[qBuEC<@|Q-~꘍Ja62k6V5ۃEw cĔ6XL%gE^ooI;MOFnvsWusC߷"͑y%i>:f쏞8R)mq%kc^WuKoY zuPһDfWm+[]H+-noJ9s>,fOM3їljAUp9$N?r.`UqmVn_UX;- ~Gܐ3w3(.I0fd衶J-SL\槝w%KzQci a,yo/ۛUY-{IK_yX*8D02R-Gd u0i&tFyS9o.!:,4M{sUlx-gt/zI@<#Z%lv?{&VhZS=b^s5i=տу 2ԷZu7Wɕ}*Nac]g$JKиd٥\yk󭸂4 %]B/Gy,cct>{dCRF%R #U\q:7X@XnjYٸ̀LƤUb{>&gLɂF[fNtxSZt'K*xug}xKa-dBy[ ~SqˆOp9dϔwf&ޒbb 2ZEI`6켥Vwe~یwשHLȑYOPy:4N iVi_?Pm)&-Ҟ4F9ۥ%*_h]WԣC߬th>WߺV~yG hT|.^LǮK0"o]GRPr`Rr3Ҍ,7RR1 e(GDV|svABl8w0Ow7#>f*eY':W\r`^% = `=0ĜJt5]K&'b &HqWX^孳"Gv|NAsڴe]U;׵Y;WJ}PX5xW{`!N1 e-eB!䄳{R~O*t%r`qyQl7N9v8vʒ{IM4Y+\;|hrA9kZ1Y}<՛G.`}qfϚgm = w{.{̍& [h\ pR™R&Km]6j}YezCM/ۋyo4qiLec|@5lnFU7ė_UJy,\a9&G)u0'jZN$fXgVp{h7@[QTYӨZd+C_8W/W?Kll=x6gJZ1'0CO`_nP6_ !0 giJP>kgYK7S$!sHdz{+ĦbxzeXbJQv0 AޥF1dZa?Z|6D,8C:0ZZG4ْC>nϛѽ!<ȁFu. _/.K2Jཁ糩]+|6 _e% nS˷,m: jˎeGh3nm7IԳf ,pOٍ7$$tҁKt0"'ZÑToi*`l^/b,%ّVJ<7E{QZV% 8~FSf[׼M'¢L襨fq[EI\逗6U?!;O:.dį\HTռ(BNGfyBmK j\'"#T;sZ&Ori^tB<ݭUbݳ%(Oe<\KOhsgZ~V$[my+͝NK@0\!oR+r>6i8om#ziRKP}?M0yS{\ʼn'q2_Ot1DނE~8c1l}UMtqOJ$))rO%JաjVoY;?`6ʳ;iھ9p%9#AIA~*ɩl?NLwӈ$R#܄Ϙdyt9i_- RpDQgVi%ӓCԣ mBMԭuH:Y; q߼f6K i] yhTb"fC$3h)sMB[_Z nk)bKT#]pi(Kkԙ[g$C#3ZX*4R~M!/lV-tvj|QyQB9Ƚ!b9klJÏZtd˷iLYzΒZ%K;82 B_#Vi u_FWh*p7+6:2ߒ{9z1ϐWW1b8z/ރ|b'B1ts^7T6=,0 f6m9̋ue([AmӲ{^w *Uv3A%}YD^t?ȇ(rn5<]gΗÐAL4 ɴ2|&,qMlڿ#0m$p'j] +J`'%p6| d天֣Lo+MF=nΥ?`11x|"$yi+uGsB4uf+zpo6HA]+\UN|{n|d` .g/LDd4GJWI+Ǜue)>=vgz[#<)igNjUHzӳ~.ye!]U[n]KЫnu+5&E_t Lm =2璳 X́'Omxsb&imfO|<9,f\S"Zu@;+uI6i.L6_hۈ۹>6ȇCg 7I4 K׵ް?`],NZǢϽ|}jYt Zݴ2 4N(-:Pmmk/lyn\Y)6c ,Z+zG'N.Q?00?^vf]Vu&M#7dOD`C5G%)+Hͫ >lR4H??~܏iZR<bLJƹab綺ns?(Oc F][ߚs`kCX!]sKpV5Tgt2Lۛ$si,6 /\>͚r*ZaĻ?g.Q\'Pg@[55wV~`t&2Hg.GsrlU1cmߦW,Z/jw''de%hTcZ;J)8G+Wꕏ5ޙwcX;MWZQJ=gc婝i 2M?+]"n5活T&z"{U*Y^P|FJ?~7ߍA,zUt2 9c, h8^ՇwtVhKUmÝ]i9wFLcou+ܺ_Js2] q\sX!EA͎Z"Z]2z._F]{)G]V/cUJ %ڦQ^Ք%ܹ6~#:훚eb7+5HkVY7[e8qA07^) k,lBN/ PN^tn~-jI:fVuyXh$nXQwU2IR/֘toBg.>S(`na۩%#e\S_'3\!O:KB w'ϏٮS1U-8=Puj2/<pzin_e![Zy4s?WS,fvt.@E,)R7"&޺&S$;Dc"Y1%v4jKq+|E tuR;iBiZ94h˘ˌym~$Ͽ4p"ovaZy31Ȁ].*9))|?c2@|fM'eG/=\p> NިNKK)r\BPE FlG KחFgTdy*HQQ祑F&xhKi|O1$=`so>[;nlߗ6sڴ`v}? I}-`qtZ-WZsx~Mu2e2 1{Jh幝 2~リaͭ/^#z rZϵA!*mћ!Ba<>ssy udX+㊦ximeXt4:;De Esi+ Ѐ讶RԱ5҉,/C#5ٟR.n kf^PO;GP~YO̍g !{]/8Bo"#\i3?NXU%Χ55%ҍ m?ȢD?|C(uƼsgOBKĪwtʄ ͼ/u;n}ETiznw4 ރeXgN D7[KZ}qǀ y 6Xf%K J][yF)vMV:۳*]LK-P,[{ UoWniŋD{):Q[y"FfONrCs|meؙM9gDHT&x+% &qg- 0XjVN0O<2C63c}+AI˵kϹƓQu7);"]B2>TI^|t,kɄl9ͅ6Nu)6uYs-婀x:=Y=-ƫ^;J1!t8+sio6 2PEĿ#>*eK>Uzup|Ϫ;W P4Qķ󊾮(SN H#汽jE/Tsk̲p:֝T ˶,Ÿa M̖H`fʙsU*GY>9á_Ln}Sj+#u_Ar5oNI:k>P\5R]7,D%&莟رȷ3.S+xl!orw*5=H"!}2 Z0[ ~![) 5|cTeDsj%{`TS#[wDz Z{#%sG.p7 !Ն<( „=*4p"e[s'} 2}̴O2S,.a*9X0ȐIA@ c=H M11܏yj-%) 5俱1ɶup]=`X;@l+2Hk;"հTH3-ż QAó~1X"iI@C7SJLаX A7T^⵹LJ쩂7a4NBZʠ Ul2;<"T*G`/]NO$?*nrYU)([Pu !93X,f\-Ngl켄2L 3k؁F[bGu֪JZ!&v`ϞQڂUZͅ z8܆ޒhTd^ϣG=S2gR4fWLM]?Gi#-{0]Ϧaᔐ0oiaX2UAw̉}Tb븛'ƨ|rss({bjIX,y{}GrT7ge ג $,'Ȅ캊}/FٕOq^t;mY+wQ%㛄SbBO@W,듐T\KwG hADh(Oݛ\mDѝ#0](@/*lj˕Hb\:c}Iղv9)vB }#q:ɟѽc!:Xmt}sȑ>}y P*h=|'ڬs%u1/!KVf 1{-}ùAy%݋-,L,SCPpv.T>H)E=778Q*’e,W|M\+~#"/Tfh^őBcG3L9k@Y3zrCCFѓf|afA?`Z[Shl!L(tB^U9z 1^ =aHbKI{M>CU'0 ;NyBk7@kX˕f^&OLƿN"g\@S $]M~1ʮ2sܞ7m$tYĚMDg9|H>9/=r͒1cFJV.XH[xb:snR,.`8/tYi]ƖCF XRHϱy;lO2Fr^4q0E6DX2w,WcRْ57[uHPYo6M>kOED+2$;;$M6ڡi%k%7&0J6@KҲ~>a8? .+•* ֜wR&5sq9HLd<$ncbwS4.ݴNVo?z~/ږ"~2n}R1Q~RLK1x ە䭽96Whɖsi6QɅu4;]E\/ͭ&hqՙi oOݽhQC}~opYZPfZ6>,1lLJyJ6b‚!vm B.;[.M*Bs;mg搖H}V"iM<7LFe5q6f'U^x%ڛ5Lӫ9M ϧO>}f==Z#GB98S}}ħ8^Ғc2Սlr}~O|ehgko[~c'iIr'vLB>At"[Ú4@OM}jytvߨ#{.n';a wR&Km64zJB F e9\U`&tI |yYoخ\о79.ͅ_|9eJ֚"z7Yz]6f+]괙5RձcᲗ!klc뢡*}u:5U+o{N#611`) J9]q ̬Nt]"w'xaKC8Se]q~=Tvdz7 d:i@WQaQ͜׋]2lY0{5Z/+y5a7S7AaLhJsŷbY=~I;z`xґbCS`LaVF FjD4R:.fJ5bXm#* KW&Q 3j[YW5w E:_mJ$|ė{͛[:7y.,6yzgެ<ƹ؈3 ueHO݅}ݜK7z0_G.wOd#q1 L0Z(8qN9nFY8XZZuӿ-*4D`#)0nN eyؿ GCZhC{[*oW1߷gh2M^ SV2"UID_؜`p^s0A=a\O`nk|Gr0Szɇd+:wTiE159|pK:5zg!r5 //>2p*9/& #;jكZ]nP yv8qco%ͳߎg!]!k/ |8K%a"1߼'PjH*(NW[ "x(,leOTw4RƾI%I7}u!$SA)^#,NdNg~+U_b]+;=L6&:QnajH<@\-RMH/%(B{OhI%X|] k qIl ՠǻGC77`QV 91+vG[R|qmm[$'H>ۃbM!B6=^)Y4JsJiGuҷK slrp8PYy,<۱`gÝADJdEF7u\exl?ģJ˝s<JS wîM$TӀ=fhb E ̔kxO#7:F\'wcnL-kxhbQ2_%7Ӷ|p qsX6W h1Ԅ'H;bM5Am9;yB@rGЮ)φOWA[ gqs@YDXd3}'F|q깉rP(F'h7-1Ғd3[Z~Wתa@7Ts \,V "k1aJf -C7{XZilyEl}h_k/-jy& x -[iY~Խ %?2k-3wd1nֆ̈́l*4K-u:ӓ)턠ܜJ; i%ߍ/Vn( ?bUjr(<~z(֕e$b3kCa wx 9ۈs6⌤Ѷ4)mR_eĄwt}rx:tS>ۺkDܾw~q[o;7'oĦ$を@ýY]/tw/A]RWQF?0? "]u*v3+Dh wDh^VK'.X'W͗ -CeTxҵ\iaA_&8)EnW<ЕzQu51 <Ԭ<áOD&<_Ml7ؾ]HEq:;zɊaћ:z-'.B-oԡtԂqI蟼'u޳Zȯ^7Vn:@Mqi||˄a]Nl]Nkg/S};. Sw mw[]EqAϋ]x'#%"A*P@w xQ1= u^ezџSR y*PFr6Xw֢,P}7DJ7=$5eOZ7fm.<y6ݜw2_w$I8~KJJYk˅EI8 MXY'yW;/wAݭczio]QauxTșJȫ8(iNql̼}DM:Al)L;WnAxM阐+?gLP< 9\߽M#H?#.m/G>BzY nSZ폖[F{n!քY n[pTI^%fya Z r C>wwU+e &D<xva(/&M~ yĩG?DYXM/jscqnHRUrnzNT2=2sW,^<5ƒUl-L z< yZ[rJhwMpo3(/Q3 %|ҽ@% C]lǢS,["OmD͋{=ce5$ φ*KWcngód6[QlUVKqٓC ]p<ngK#gn[M-]3+=ܢM H^ZETD7iBgu*@>cJvrGӈ|U=( tq  ^R+^Lφ/]h-n9ųwe'D9sTvvT?/X[$eH/=4 O'1B4 b5jX uhZ%Xҷq"{/ZF{:[I+t؉ǜi`xH4-iHh B;E^֯̆.o2x>خlS,Z% ( J|/ Jd=P}HQ(y6J^{C=4@~ёLzƃE$O&PFPi<\J@uCӻ"kJKNg` 9: _쨯;*ӔBcYD`0_f򱄠VV!譹LOnu+0L8";_{׼@~  2v8I~ГNo8Q R]Qgnz0nj&dݺ;4aO NߺJ*4(#uKZj>B\ 2ZƤ*k5-`4RH~?O!GweH^)e4DU㡑՞p79dV ky|~uC78J`ڂi%!ϝ>kya+ fzqlUAHL>yJ pjo >)'6cD^#Knzb1EȩD%#B>;\՜xLSgH{ `Mцf!zgq]s%6C>ASĻ5\呍5|>x|{r={ͼ3W~DI}=eIb7e yuFb+J&'#N^ O Ҁs' h'fNLTWhʯPxEoPx;GqcuՆFvxK: W ֱkU+?}mŌSW-zҁ .jn} $}Jyyz1Y'=ll@*/v{gdX:ղJNםp˽ (,[tee|wsgJr{T;ZY$rQ:譽58^l$CXr-e|7sO&v8"JvqF??̳5ֵ˫*RTҋx2]r_NEl@x{B_EVo Q}q B U'a N5VPK=/D*q%s|#wB= "w5P6 L ML2798\Iʭ2_y껇C C  y-|ǎ&r'S@އ&Na]wWvSSe(#RR9t4ϛԓtѐQ !!~w^y(\vMUԐ(Wx]2OrYGn2 HiGS&%(:-)(#ؼ@uk:bHт.')AZUmMҝH⽭gαH_Ìkh!Wo&)q婊 D]ΏfWO~Շ+: S>F?dG[e$$nY-!td;2^qf# պmDw&#~G mr߼Q0;VD;:\o|O>g>#/7ѝO~J4[wj Ii[^ C#q(JɘXAuӵ|LE5&]FRUh$i$mیHZlF3pEeC"*wG w&G&cb_)挌Lt:'R;V㱯ltGee)CA#>aFPv<:;XӘ\&.M=̮|Hm)nQ< AuՅ5n*}T6cM@?x muﻓs>KO+:>Nz/U/i"_΋Rr"is>律PK[!!=#q"1#$Ќr?_w96}Yh3 <5o.G.kxMhd6tc A3} T4LJ'ʈi<Cާ¸dk^Tcn=${eі"Ka*y{[M؋Ο36-l$uђF=n桞KyD-ym,Y.<;z/Wo\{*K'gݜȁu '̷S^/ƀ~l˺CӕCp*u؈JMke?-Qh)潴J}qX] 4Vro샙u: B7|R!7VbP䥒} o s_(TLJ#wi"knh%YF0T5vIu*~/ziN$ fNT,PHڷdV WJ Bko| %nB>M;;=ī1=-|qKpS)} Ȕ5=w.KDdm/-_HRB:.NmDg6}q3(9w\->ix,q u2sOrr~K!=hsһ7(FPo Y3i(4PsAXȹz ۋMnF Ѥ)ʇ(J.}伄? b8tZ1|K ǚIln}#CL渳-СW E`+s;kJA3̛CYs݉Λ$!1?hsU%Xh)6sNqIwib33&;>fi/7&6D ylwF]u=K7, [0(|gU[;EDVj+͋$oR+PUtv.N>M32Iy<6!kxҏ]G/P>%.[lnSlpk2Xu4ڀ0L)zY#t ](hmn{^PR;ҧ?~)-J<ϺK uzZf(P)'G;b{e^n,Xҍoۥ'=p:)jJQi2nx^|B3oi>q#f]|65q|'^2bp%c}sf'sq3-=XGq?"Ò}.+Z()ЯBq#Ϲȱݓr+GDA_V0?Dv"cs~;Ntݴ<'ɊhIcX25rEPv]/c=fh*J%Ϲ+ʭϥOr'-'lK^;Yp2?paf|H~:H~fZfGCB.J׋)=o̥{ѲJDnVKס#]1C|_&JVUh˄D̕>B﷣9y9t=eS$^ѻۧ# Pw3M7~9й/0 &=Z׃y3khӊEڳ%a Z>X4sVx|w6-nކ.^zVn;Ư7RZ5R_yj[-˨'^ 0-+TP.Mf7G&)]8r2 ۡ^Ez[DFP+$,BK7s.W=`YfNѻd9#dc$y"f5Qx NKIA{wo"Z4vC^x!F;gUoh6DwHA (ȩdP%2NbH- jKOc_?>v;2o3ЮF7z$1c: gw;pt&qnzTr_EW~MS%GsڔЄ6: YPbej cY5b 5"L&,*7`ue5a}ay}24-3\Hafsq$cz Vݚ҇;}W fCe~0 l'b{{soƫC7v+wCK4di=UhBmҏ*%K+zi4yЅ:nvd܇]ήH xz )jmnnL;%.F Ȩy]9k^g謗>g]$\̫\xVf? 2ko򈒚ۂ[َ\}Gm; M[]kH_aI_z9&@|tso6,4߭u*pQHƘU(^ܨVd ZGnc$U/0ui|B8oPuRv(ΪcD{;YejӏtF"OhekVЩFI F4[h"HЌ ro-(scF!72RPx۷渣"VWb)=:OWtCΜ_U0gNZ/ݬ葿B#i n4-^z]?S{iӖ H%mXV4d/|Cenȗs_9(ML 76:DH %þlgP8d\sL|1X1u 1Re&QL;=MAd)Hcyh6uk6LGD+IJM4:oJi*Q&3h؋]i=UD2ox"?vi\]iM@O ;~yor'L68uyto"_ q~I@0RZgD1$ imL#^%Krvum5bFFnYsX._ƒ7+ly2Ic8JXVgssdښE0嬃juM+kX)X>}r û` ]j'NK}}|$G!iiyûhڵZ/j_(Fy|6E' &4N;֢b*|Q[$lߠT7m'xdQ%vf)KI)ydܜt֍)қ8\gn2bYᝧezv( uNwGTdt@ _.ŎsVŢh7[]hś4 rr3`y8_DަF`mƙJ0OjEI!j>4!/.0;Q@Mo9˗<4i\pC~^]-s:84> Dt= =.V1 ))v|J}%T="g sq@VK~ >tp2ogĽx&O5(bnMge6k"\3-8Uy%>Qw0XQk"};$Y<(`F;V+I11)X&+Wq=U遝#Ѱ?Pҹ_DRRL<85Ԅ?wƴDAVs\%+zGcJX1/$ſ!h9e8HA.=GRU9dXC_n/NcOF!`wdq޺A11}kj-;ts>2qjĤ&w:Cu4HAbW6XHCdH54x/Vao{,TSS?5ٳtNS7֡W6'?̖ف${h _Z%MДyxd`2HojI`k8 --mJ?p^tdn"`7Vi+/W ;sMUE/0{G)՝ %%0tGB E)0%#m3.a1Ggnڬx1k %(4Om֐l빤3Lf7> X@ZhsLt=Z=<<`^qEJ߼Q&kOoCb|4q@yWJJ MK2BR΃g'пSrK`sK A9cI#*ZzOHㅁ=u!yMϖ W8w ]mDRc>Ӹ5#0q̓"̝Wo=kC9^vRX2+cSG5dx9_uhWSNq3?ÊA!H:M)ݪ ;kaPGb(1MS>xD@ϭ@}k4^ld EFXfVz :_K["!uM3'!i`~ܩH6<ڝNێbwj躊5)TD3խ! ;4;HLCrG4?}8dݿ@ਧ҃Z Kj"*6M\1D`RvC^(:CSiҴ00YSs嫿Y6qkoᐈweoa`HYC^q(}E(F"wŤڳk22cU߬Njnj^)vl rKU:sgJ'Z5,vvC[&1H2u|Z-|.,H]"T.!3h6Fr-4hZX3f2Ώ LZv>scyZ_dm{M`U)A=|@ƥg02Neʻm9C*uvG[܃ct_y=6T JΏxh KecWV5r#X(;V覶-?u|6#/6ǤR$bƯrNUzuȎ1=WaႻ8 |wkZ'GЏ*3=Ɲ*b&@8ۃ$Gy uZSa%;z.6\;^'octP~*[ٲ~Z.bh4 jThn+$yɬ ϐd=\Lzf OG2iȪӲ*z6L*6 X+)svQGe~(ba,;E"^{*uG[jIN޾[lIuF;;r~d F(7I;>əbޠ~硺l&#Cgyуffm0[!fOXFzWPEӗk^4ڈF]9XM9ɩx'G6"MP=f%J̗fSp&)cZE׳nݩ~l%57AGZIy,.oNllMZqZԍaʰUè(%>:FRNYXz ML(?no>חf+^i>Y@H=uɎkGBz"t`C}kj)^X^:C}q1X~p(z" OSrܱd2-m(ѯelMiM iǻGEAGb])oQxP- ~Ma JS'[moMxr:A/ am-L9a7 3rM3J2{ݹrAvM24ketmhB4"zRiŎ7(}Sc+.a\e]*$&ۏ>!|w?W;GP(9g T8Py;穀|XEs1(pŖmJpl/o7^ @To~5㙣 C հIS{leaz b5 t3f8a@DB}='se'ʊv!'U6tf|V̝,Uˆe?<1攤>PՍ>w9TNSϑIH}&ND#S& H.ȇ R~u=>OƓ/([Nfb1{4h먽5?o:`6Iv56S>d&O/Ъ ;G.dI m&UUd('I‰5r] ZoPR/u3vew^Uq )CK`ʅ$B_# ??ZAx$/3Cs̀uXi ׈T>۸r=\ӈzXU5G0G(:,߽!O q{9Z۬*NwymEq^vE oV|YJAr2^DB$(7rr?$;nM-K>ljK䌘Q7W}ؾLsj:uȍ֕o~˽ty* jT~E^_Э]m6Z5޵qz( zIr'.ZT1Lj7xwii<khO87db$ho^Q.2 ZEQgB'k=mPo&{6UCxlR=ϗ/ YUiClC}Jnj3%ms pߧLi+}4"I)2{N#k2Q02-TɄf"0/94ibp5+Ʒ^SˬY'hʞ\a]gnvI\"{bkmoFFPuk[?dq/7Tɐ/z`'"&w*3=!'h͖< ҲR2VJ KhtJ9: _3]K^9b_?W5 sMf}k1&ƔK:뮕o'7SsϤN +Q$#c;\ JQ T)"I1c6@~d8M_pF"wgjIS nv<%5i*L~g2̜1ebper ]i%3{WG8%8DA~4ԵD-<ȴ?7#spqGVBoGD %w_5c"փ0Nt%QtAi,攑g\#l9` f.?dSftbo]cwIj|hghuΥ#!D\՝ <ѝAMʿ{]эπ)ř؂Λ=bh8d^f-NP1*՚ھ(Ž6Ρ8rOJW^j9SmX1H`84G!kC0ǞP됆gk*d 2/qCm\g`.w?KPYF]aBBxŢb-U9T7Ĵjgn:)%2.hr̂\|C.h)6ܚ3S`אuMƘp@&>|ewSJxȘ)Q x,C&p ;1uM'0>9sH-L!Fm05۩ص`4i uhiUշd olרSGMhɈ Kakt( \d -8YdE y>-O^T{Rd6-1vAS {pu^E.CljyȽa# #9g`W_=:(VzQ{uvli)h2vjuܕ'V8i|[r:ch{CbOIkr+aa36έLɇn#(8` q[i5mǕG(5vM-e]K3l[\gWώb{#?7J;:'ҩ khAD:sMk<ej=7R<,Kt/{y?5P,Cf@ACŝ>SruZ%v ίDHĩjg,?LVSukxF#)k'.ܠ9˓ 2:uRN Xh MxnqBHV(YoԖ?lwUOuD,$a9ͅ;DJLo!!榜,g%R,}{LG"sor(8*{I;1Lk;/_)xv`J`nU VBwĜi(r١i;$ifLI,ATW_l5sɦ|-A[ u|sOiCH8иoq,t~KGgdX_ﴌ*JvCִЫ3D]&8y iPY)G}%y,Lf &6Jufz<6]${&C~{ r|K]h^Gѐn>=ON x P&|^wÕŒCaGΖcXSX-mPx$pd'劊<GؤVG;5e"$R%f +ʼni`k ;OϼYK0rh-+gR.M) j.}*Θʞ- 4蟚^|@c裔z1K88Fg&EZdiGϦ1I9 ~yf N5⍂jf}!)zQ]I{NN'I8c{~IR-_1n`=44|211س'cJdbO7"9'Ԉ;BR'j4Ą ,>v1MgR O-S,)4nCrxRyP mo UvFZ\>eÃv,;cduodj}4 k^Ć'vDnkB? E_V*"^M!3$ d݄^4(iUrN#ssPrvrj}-{Imyfws^cv/CjU co!D:-KSJD(欮RÃ+pihư *PHMKsz@e贓h5ghߞ ~P#wsdzeӾpj(49H= \LY9JfXnܜּ#T}Ǯ}/Kx{fmrR>"P+[y qWyQ' ަЂsH_/rRD7rp]*1M*:?qmyJC异we\h\g"u*Θ.r %.6s$17N*Bl!pmk%qmb—E7IOSpO7 n7P8TrNyќݛfJh\0qiZOG*y7忛V|8u5憱YƱC4\m([&I٘q3mªΕx9Νj'?WIf3`)vIc@PGH9~/%zPeDBԂgk* J"rDoM?VtC} iLO+p#s2"Y՟Rw#gIF&#s EF(_˛ *PZt ZR>])Gԫs謽uo ^x O|9 m%UR:YTp [D֊H8B~92muhï5@ޣKy~x Uqc:C| w2 M@g-|&B}r*Oz nD}Q9a?>^;yw _(nDvˑT%BiGQOS%銄ˬEYs4Q`M'oڛmPM dJJ?4fdGfZ͉pcv;Y6ڗoJwު`iD_lnfsD-ydl#{M ;)ۼT몦3B@F,x?l^J mGY#W.$L@;7_Z$B[ 0fw-e ]vuGt扶`ÎIC>CqN&@7X&JìZsGY+tM2Àq&Z 4g-br^ tQb€U`oxZż3F="#\7LJE@ǎgPM}3slҺX0<`?9MBj̭znoMĻB}dJHݦ&f23' VZQY {dR݋;kEu2k2!Lj`uĆw_'%AI?1 ([׵hRʙ ȇC5 h[/-,c7xAkVZ#Phl&I.VO]ÌLS/y)F? Ҟd8QH}_^As8U%'Qp2p蹾EoY_-@h6O ֊QFޣڮgTk~_8Ĥq5zB1nΑ<$ kw(ľ䋐{ݗ1.$QW* )BiU/QޗsswW6Z39r2Z^SCOB=,3 wt7ZU%'*(rUdd*l%`aYaY+MV";Mou0XB45hO9M.<\ҡJhÒ)vN'wnRedv0&8H?ua6MTiyD];\~*jӚ6\,CϐA&Ga X?^c:1OjcxiD8 9Z2"ΆosGĀD>WzE}>8~e0H <~x`jĆ<8rO=n%tB_5y($ Ó3!w>k-9ZQW[4z0q朠^h)nzΚs> PNg}$)Pظ0=݁)t]Qb\zO"WZ^5G# zf#4lAs Yl4G-<[-q( (L,L)w{sڑI4g/B*h"5_NF>޺EO|&^YE K?e|7֢*xM>-p H(8[fyޔ6d5s@{uu*>7q}D%$qw zAfD>JFn铽WVeY?>֡[, Ww2\1 LӿBu6H2w/n!dzЍmM(j!"omZZVIӏv:m/Z8hx/h 9#ӄ:О f$712>ֳtؘ3QԄ, 9=8du 󞳨[q?E55 xggo Ԏ;>'<{.[1d{lY8߱؁"rR-跚S7͝" 2]UJJPn!`m}̐-9?˴Eg6˔aR%"9Gr*+暈XD:iXfG) 졖 J $!sW^ؕZŗؖ W]5dj{ΩƱWlM%.&6n 5:k7Y ,Hþ 2k3O>ZJ;SB ظ~wȞuzGls`Bf<95yZtHz_U#޾EM4UK΀z{CV n_Tz<yv,繤+^1ߖ?Bw\&V mBb_G&Z^d㛌B7Xlu`TIR[|v̙:j< (.rmA"RkY,va|oI9W 湫omF>H皸jFb3TsQ,'s0;pC /!OnVKlNy(ۄjYk\ JP<P˶SRZ2i\G.iw)(v*OEWfmt:⣧Vky1vJ+\gL~8M[,%_a\#uzPX!v0t bJ1k"Ɠ|PYyˋ$O:V*\GqeιsmOn`]&K5jm+:!7Ru=\F+ }l'+ry6՗bH3,B{Ṕ81O./w۾ۄoyҝ W†.GpNvjS>XuM3CNN5mpQϽ@BCW笳}X^FnpRC!,N$?}",\9o[6f[F萒LaEz[e_Xd]HZt@I|QF~,|{*8.Kς~n?uY6j]T5m:krHk_[hChBϸ8rM ݎ`Mz˼q'173I>s9P*μ咂;y8p>Ź @# 9QZL(^^_Sd(Z3d~SiN4J˾1 9S[ g39=SFE8vrҚkywh0g/4uLb,äҡ6-LzbQk"<=.4c aʾ*t+̈w&D$!#WY{#Nq\M2Izl˩ mGAtHg-jgo;{F}^v"ױ]N6+׀оZij0զ] N*!YjW%7m\Ijuf)ٱEr.*[&ޔո`GT11 s, hꟶs[ pwrU6sv]vPsD#~^OvM:ʬ*fꆐ'pP:nm>[ǾTװ5*}̴\Ali;u?V~:(,!{WRͱ `iF , &˺&ȉBsGO$s.Аp4K+DvN qG&'3H`(cru,r4&R1LHvZf[TASz^epM8v@}*qU'p/epֳuPd2 ̑^ @o`N06/c|bays=9^&EgH:٧o%br s^f1-P|,4}J.~\iqY YUXbԉT4 ^ TmKbՐzHmF2z_Ct9yo$ >+bV^s-;#XBbEQNSBEy~^e [%4]Fk]/d-:=bs3(YdE\?~M,o]o(n,47ﴕ}pr_ ;SC!^ߒmDui4#7z(Z0L.@[{8_!ȫt2l|W{#Cor~Zcv5/094%TքJ_Mw9ٝ.7oyMJ7 YLOn}0z0J! ߦF9aJgyPX"8l~w$)`E4ȯZ̠@e5w*hDoH*94B/Wv2KJ-7yxF C{vt OvJ׷Y|7sElN9Z|x.R+2oJF "p6>мNX"|sh<ΎGgV4 .9ce(b5Π_hDoDg9n̡ JmhC5%ߚ#σN R .w\v(ۜx+h* Vhuw M[}YWM۴{Th/$?/T0{>4gl2d}]N|K,wP-oٍxؿЍuN{\ϱPsQG!Ҧ6r"eb.a [--n^dkuשBzȎ:SKIyhV8;1E(Wߧ?~}a/ ֓+WIS~SvGtT.? ,?,4),T^1ϐS~ !.G(iXj`Es 󻔋H!먵(4.Cj*׺|=&= (␮RcQ9E0n: ^ u:2CRC6L%*g~WQ;3U:$ ~2iyl;B!0^dԹd{xZ .ORM*Mߔ~qUUYGy?? emڋ>CR^lk,q&=ƸLs(zX:ENh~Y*N'9vPlB{꫘}B:`m:>ض76l7[D@8`m8BLP+Աwʑ~EwMݽri2WTePtˬTc +4oW+7B۞r(wO-UQُq0" ֑Y&dkBׄd^zimTTqwG4'1hSK&lGWꠌx3' ,0E-RGN*KnVaBmf3/0~UU9̍Jr1)G&W #䂬u:8dels .jrR$9, Tn6H.* XN!a l6KSޫ-'}q^7MHh`g\L2?$:G2CׁzJ)M(Y2̈́4O6t@dz{ڰ2,m hFa ;>!#P36Yxvbg `ЯB YDmliE\eGؤ]0tE嗎doGj &(_Uz=A.r,vԝJ>Gsm b%.n˓:|o$@?W5E :/ڨJ&;D|v0LѡjK+v~C{M5C-oXT /lpkB}L|QUfm^~Xe^^0Ob;y,/ڪ'_v:NEJp \B=Eì^\Maky@"&C_^ǝ`K[I7/28pa '4ĸSvaAS+HyNOY^:;=:h{V?VڬJMV(?VuXw3]qڐ`D_MTEo)ܧ'422ìȽ3筥ptS-2 +|Hv"j;V Off|@TU[E:7o|4=}׼ek1A?r]45llsBmMuAߓsbWPL,RLj5Xo~5iM#+g]0[+` I}T~;rܑ!^#?dqSHr<$:r]6K 7Z*ͦo_q't 1P ie3yS+e6?~Qõ4؉LKf@el:V`D0ċ$Lk4ә\4u(a[R+:AC nZ+v30nci~4w -+|T.:].)Bޠ€#Cqt07SL1z.1̋5/ 6!&e^-WX' zѻ$qHAXC_?*]ً~'=C!5 )ȀK*t~4qzwSݑe E{vK[v5vQfm9ViѠ f&epYX'Yu\i c6nۿZo?,t&Y<' d( m׈Cr'dϏs*˸o$+ ,S򭉏d<1N<{=6=ZTr֍Zp΃Wbu$вNY0CSׂ h7NOdXah^ :C a ˓Dk|\X(Dvx,oXЇތ_x)ޔ7T" Y".Ta:=ےg@Z> >y33YAN5m'{fSS cᄆ): ~vF<5{g]5I(7;tΈiNcxPRre&H+jVʚ{=y|5 RVٳ!K4+--"C۳Rdlj>ʿٞ'c$?x02Y\ Q,laF7%鴮av( b,*-DGnАydavsk_X<5t֙~xiwHvbS:Ȓ:5_ߗM'Uڿ7!~%/G:]QSP CؔEX"_>{oAC J1$Mѩ_C'U%ոG\&2i zxbJQu(Ekzss+[(3÷ٌK:Bl/TKW7`鼙[ ( ~ߴ?oŲװOy7I2#DoR|g` n/{*:oERe]xnY#c,D: vYU?|Yz.Hhisqڸx^Իg[9[p~w0waA#QG 7L2 & . dD{|u[y4;&wLp87ɮ266Si~Y8T鵓_;_HYdEN؛$a}tBUU=9=^ ni8~bZ9Nlt &q,KWӏ1(Cu"ϋ I=94h>&#rhD+\%7?eLxOlŸm\׸f(;|2 J\ߟ'_9(visMe#/&x:嗜 #:T_ R0?N?ez4&ǩuaT}BR 0s!ĨaŘPɆQf7! .QK;YG e3-a8 BeSeqHWz'1| Ec|q]txYq-umZu%ݸס9*uZ7pIw72>^B])#YH.@Uv(äC*d# w2խXMxPe@wAq.8M7t7YGvOXznpݐ}&x(iɦE7s2`ۜWȘ ]]$Im:ҷx8_'4~@ F#+kIݸ% A™Tscv A{imKvYڐ_=s6Ec|=yssL>I}nЧH6T"x1h?+Ъ$SɌe*OoTk 3Ƹ2O:WQ߬|-[~eJKJEcdXGZ܆^[0' |3 7v7_dr#Z e3uhe:^"@%Iqu5#Y֖䔕d鐗5c^,hZ9?=U>VQۖJ\]@ uưn[7jdsZԉZ?KNv0P͚3Bt( 훺ee}R:M,-7]jb\=(ڞlb/dڷG^ ;Mv2?ŸXB j^tՎ7D魜ɰWi]۝"W5 ftݜ~pyβ ZUv~d!c %ّNW  S7AE!Gn4+ QҢӋ#Ȏ-GtGfDwf8'N$ǿ3$Xdñ-ThU@̣J3t\2)aH 1=*+6yn?_/ː0Ǐ &#laXg2e8%]=nl|3*._a7V!50w[e\xw5SO#ڦD)D؊uQʘY|OdȽ0;嵋*9fx5?q.Zz=X^bݐ М2-! *- +Ѧ,&n)&JńוΛlNpmإOUk,=S$- ,7|F|r乮_s7٢PGNh>7LxPWBc2;AdYC";PF&pmfl>"Y7UR6sD$"9ҕ>\ut0 6K"nxtX~q|%maQ4l707K+60O^?8XGM1I7~ 40`Ȟ\Bz ʗDfGAhe^.0` o/&LʸJE 嬽<38tO:d,0Vkyg8j!viw4֐ P~> o57<4[ab&LusY!DHa~5 Z0=K[G9clfRrS<xy}mߔnX"@_JMuZ„/ˏ(i\u6<#:\)2ۚO'ʟ`c[&SެD@Q%vj& _ f M߉U% mIB闅C8O,i389!X7HP26(2mY6y|*2f:ƴnlTlGQN\OQ?@#XiF̟]hsД N1#|hv/uPefhDbrRCpUQڨQ炲'P['M1QIqtg?ɃbL5bLzֵkT$6w 0 THCf;j夭Q<BJIcwTsEw!ί<76]H.Gt"yٽ":i`Uvtµb)C7|pZ@{8A8TQEZ7{gPB1e_4)UQavmv4:GJ9fr ]X=10)Fޠ9d^͎drr#蚼@6_yS 9'^Ǐ;? ʉ|<~2c]/n횮v'tk׹@)7S.hvk/Λ;*HH/ݴb07)pC򖅡 4L֊xO<CI#u 6#Gˮe^΁,ymQot6y j1?cnh@?ۨW96`*w쾰[X `~Xa~>VU< -.Ӹfq9ʷY}gqKnPx]m-R1 _fpǼ29%K}rᩡD W)| &p@Y#հ-ö>+D38ۈ/3QD Bp\&/+^lM=r3L̈<\%:H2 G_$?ս 0 3q6).sC48+G͊~ ۛy/Mb/%PP`csUw kd7eҕzmyY؇ 9TP:Ȍ3sڰE8Ld;H_;2=QoǢ^ /_t:ӯ).)+a 2'{&,{P]u(# |^a2c#$s]oZeS3K13UB{n;3)4JhOݾA*v0 i6 vKY~&2Ln +jvhfԂ&mrntTa*snd$ICpn ֢̽8&C7"G\-X-e{qA ~=o~`.@Ё_J Ôܰ@᜻u[{?$Iz\n~/.0*PG̴AќYw|YAb3wqϵҢZCC 3bk1RAÑ`|hg$v8EIuf1&'4y[ܜe*vdqJHPGPƉ mRKr<*MC.#ףn[d=y )lY77uv?'2b R9LA׊ ZRz@.6R@?k|7輘̻YNU4ۨ4X{x<]dC]sf}xĨeLŚ (B΃x4'ș@w3&i'ůW6GS@zr?<"xŠ`&i6>UJHuZĺ!ax PkM@vLrq0P]zY(B4@iZv[wU96Ff3n&|D2d0[yscIWJ$ BUQY|ީp.Dгi-(Kil|0Ń9Wg*K nP& @^ oĹ|,=Ӄ* ws_?<|(h6fˤ@2ԋpG(Əkx/Q3MX2"Q?r7@ (G4jC9:.|6n*X%ڃ2\g03W@O;ǡsW͏\7/kD%wPnTjnJAC.\q<w-cLoig iM&Q4'-E̋ACv@Df:.wbDPGs'n/$UWӡ:fl4;}VئFq}5(]wl%x4$7.#SkmX='JOѿa!ORǐ'6CDƉU$\%VA$cbmH0l GbٟC&Q1a N߼,;VP-ٱby;;2Sn̳.pB,4jmUsbي0qqIj"v8B./в plچAd=ބR%/cl,a vxd`~/bM7kz2x7 y@}ò5k^~Ȇhc{_WX"%Q(d]cbw$(`m1M/8*SykV,|hhynϜBZ,CW<V=ůFfL~4wQLd'1DxRFiBIvFr-K/09Yc&'湎#ñPZtKs9@d^Ef,[w>\4+3a[o2Lm>5[fR5"2 xfZEWp`ϼ̀V3 0kJwaC35Nu .{oj^S %tԾ-뷠'4@ȽR̓E>چE ̶lX"!^9:W߿;`Ǎe~&eAezUbm`ȑāp4Ӵp;z-]dɐ>+,Lk,`m7 H&§}UhGz.(/͎id4_NK4:oE R5_D$MY1EKJ.Qע9<'M4A"2 $ i`Y63/݆e]<6e=]v]$GYC9e ޠ;pxPb blMɘ} { i@C2Vp";[ E]RƣILX*]t"hȸmĭub3Yp~ X txtnޫGZ?'+.4S :0Ǵ~n=d{Fjl+^wy~7%= 60Fإan }*?ԍ%oɻk_~F|7lOy|Cso iS`y`oĽ[(di8yG6Ǣ/p:d|ᒤf=P \Xݗɔ *LKnZ|GHx]ZAÈ.)E!%5y :FP:h+*hF?4Ov@)puBoi_x100)Sל/+cKf}8aE?8;eK~"COr1.!lf1Oj.^ (Ri~N(9jJyZE[)Q<kɽͬ#+8g_>i~%8[|Kђi_ـѺmg¤s0J(ߟ =4BЮ'DWkHn/s&4nBW7+(^oCܠgs"a= $\ lI؊yh'_3Ǡ[Kx _dq/#B,\d˗}y|VTé$i|W?3wT/@ Lig\m6L73`_Cd#(~<%G+oGƁ,/-P{Y[4,Ci:ЫYw^ok:{7nB.ӾFpߝ9%AF7f}~į\g~)mP$32?gέ`uW)䡈1" W=\_V*IƳZiY#[cl=ŲI!&+^0\TE|Z>iscmߠ+DAA$yүd,y΅gFqPID IУo~qT1OR3S q"k9bZlf 5d8jۛ5,xf"UңOG 9Z[4aO~L,:*Z kFo ϒk~C\%:L~2_8Ύ|_Rx75%R*MxfYP'*Ǟ$(y &ucF#Vy@$$>ɜkOU(lxV]]vT2z9e(]_6C1;0Zo٪7#8!E /sӂѸ!Opkn ߭Rm-q/v:3*OF 81c|uNM*d0 GwCh66˗5wi+ =7ѬI[d nOh_լ1 /p2vZHMDƏa&w lN,VͶ%<4_c0.3:3l9kVRXF"wyAK嗬j `3*K"Mf٧ֺŦ~Om5O]̂쿌p-rۤw!/0t0G-oN "`/K#:$AgxAw@yg/k'g"QVUFeZǎINOުˋK)D g(B`z;l %AW%I& ;Ї\=K퇩X9C(~b9siv°|$kH8>Pļ$O:ӵ#89{5eX.Ls22Wn clȌ<_0*JrkR 'EiNe ճяmbUTW _v Rof=رƋD k M;྘ "(Yx 9Roar҅,bC)Esѥ|zp[W6 s8=>JQl]Dc+EdL%ZRQ<)$&a qv0kMPA#W9Q}QȺbH e@{xx;7s_-;\'u3:,\h9/fѝge,aYBkgOلcE.܃3 δu2MDOgҞy~A4^M*r W8P6d~1`&5|?'t/-SW0TŞi`I64ZϴҨ'Xjât=ĝ!1\!l&볆WcvEt6nӯҒL˴LLVB\ca.3xl䫌dcrU XU gEfEdp,E@%R[Ctp\Yk/rqe2j=D̓xŴ/j0sc]}"aZevZƓy6?_qWpd\Q,/.kSb(A[.X=#_Ih|MG'l-oXaU'raRB ?Hwf"Ϥ3℆q' r}K $?6~˟ T-ܵ`0l͡_j߰P5,d%σݠ&%&OKT2gI*f:DDL WT<;G$'봬>ǣNT8~gŴ*;RMYQy$fDhwiȓi[u!<'+cG'~`rwIYn~(gXIk6lŘgh 4!B$ ) @jO{:h[ e s4 " ϳ|3ÑV&`0L-Mde1)Z=OaDF͎bAQ})hଝH8ksp<|_c+Ͼ\F:^Qs ǘ v͜2ԠDx^:Xd,/AegMi/GR<TlL (<`_0L$p/R\JMNui{_P|. v{h89X ם6sy[@d†feGMݩjQ h|8L|Ȳ}nro[q(qgK_}wW+P-wX;AؾYE].s@T;?3o #CFv\.{w}V8B$n>"}j̡G+S ,.5pB=!'}Fޜ:"\Ɛ꽛6UO^~sE7%m~sV:F ]~ht43R2}1 /$w#QU,_tMjmؓqo~V VY9c6Ig d*PMX`ڈTr~qLlt-I$n ;e͍\_68 zu6' -}($Ƚ4:خ9F\^MK//ή_``tܑ;oL0ɿ>/|ń^!'m<Ħb𯉴}sгR`YF1Cϛr/!(2H}\ƫQj|rmfsWXL8-(\fBPvtԿb٫jQ(gثMlǰ\ew.^Qi_#:ԫl;|5j]=!#"O}3"/- J||.# pa(DP0NQLS_cHOjަ,Ffmn&H$ET(N$ݱ0τJ{18g&Fu;㢳ƥ-0D* L`1$p gπ?(.gv"LKOВ uv6o|#{AG] a(.y*h/.ŘFu2k֓d=*Tyt~_N7QsH5BG@Uw-[DMww(evX"̞:d[k!UvqxlhH.M57ŭ|̓Sntayk$!/c!RL7>v**x*Z_#(oy^ " Y6hЅO+Ds <>Oɬ*a#R$>l S.2a8YZZ*ˏ#jl~ eS@m*[:%uKGwVh!(566)w<9d{07A:^D ꋌ=B֐| dL 1DДh~#P{ 7/:@s6?>6;_^mG. W 0%j07yG[^%Hi[-d('O߬z>mW% S(l$'AB)Qf7a^|*jf*&[;S_My8|Hļďž@-.JLkMWf,\^pT]͟ٴm8 >)H qk[.K0ŀܵdLՠ.0?.>qwm9KC1maa?;B9K''TkK60LT^ԙҙcDm | b%I{en-r]e2:қF*?]/Haʩ1W meeVmIYɋ Lϲl#IJ 2"lLk aemxPk-70cL;*O;"I޵ Tӵg/e1M(gPױ>?'TB$n5AKt3/&Uo$AnHM~uJM6Zo׿NՁ8./V; sb[w y2xj#wPk^ێ6EaՎkBe̻>,m%Us.wC_b"*d`bZdw>SGrfr fee]av1@ K/r*,yK4dGV\eIkwNh%6^B9.S%ӿnwfȠ$=38ZNEBwʉ; [QU?IZڠ<_ϩD漓AA; -_0;ggwޕX4FbdAyX"W~.D뺲{Id~*G M* ZKd: G-yd2Ony>gpOf3ՈqWb !_J*=]9#9BҊԜfUpnpO?OXF ɿT,2 / U2Z }Y:R" ?-/ >ﵕs̚A pw$ŪX95_*r0G~s61: D\&~a"? qI@k*RSoT(T+K̤uL S#ES I,C:5ʓXMЍˬ>ﱏ}Nx%Ѱ"x UGT>yB1a\&&ש4=i2WƃU?J=3*1QۛE|FF? 5c6f{mA|r9TXe2"^Ug%/(ja rȏ(Γ hh.Ō,?dlebSFtO!VkK{Z_h;|\XwΛU[>+lYq>i'?#4&ߥUړJXJU$b1F #s2uUnj)uDlvħ`sӋHXA^(ughBc- cxƮ%  ľ>a=I[N@pY_Rm܍Ό nݿ\fpɠ®۔d\cD )-xqfy}Rcp6Ȕ 7mAkǎ41lyK2,(zQO+}άA^D43_ug?A .\ fi)b9tխQ:X^/hWT 6,qI,j"*2רf޻ wK!,wںMkv"^84}sΕUc2~9ntETgXGsԏ&TS}Ks%?֎i܇\,HLf*HVHpH6%<7-i)I*VF] ;>:l;@\`8n*njF(6WmvIBlYtؖAߥ7ETT7ur7%lrn]C72p]2}z'(1g.x5e367ׅ%o~gGEymVNuEu.[]ZvUߖˬAq&\ w4|&y}mT%Am~!K` }LΉO]"oĀ6񓿿g@R]z8UcƍVksk%P2Ku9hKi=%LR: [MK`fFݠ{p̰g 5X0'[Q qpl/)<-z֔6xR't7Ӑ9ȝ&hT2oLz܌^:>?Z~{ќ~hzcj&e>r' 0T*l>7>qE _k]ˢ\e5 EK?687Gm2{$;D CUn$6&yXv H[ &g9ֆHqk08"1[sЃz)ƙ-\LHGTWRVJ‹ZxE. ȫS߻]#b_E^˪3 ? #)1㺾0>HBUy;9ԩ6wv0q\K,z2cmDKoɌ&|2qOK ~ ukׇu q K:1x9l+-\Cz<+<[ T瓧?|KXim:a脕W5,fsL`M *ɪhłMP XfN&5ir74xC%G9HdmkB/pnU4jvek~ 7>9%GqE`% ۑF"n7ļ[ז@MSzM4=97OזeR&?9)YVfTLI9iX FbPy K;gr3єZ/~θg@Y%eTo]v!i<&̹oO]LpN5{ q =٭zC5Pז)De'v]&x* 5P$F | }d|[^.51Z3MPفW*7SiX"a^Z)1O}2m6ŒF2G=|ܤ(C;%shlSDFW}{A35ٟ %6kfxv(di5z?jǀmYs4Vspʤ未9ћ+N8S[=e%ר J_ja ,9L2lQwB׍VO>hu"VL 6UV_G45K%rO airka݋3EӴDa-!ìxE%;MP6>ohpg?ڤ3f1V?j-GPkTmCH/RyD$]<',`(J<nD~U+7еa ] k-.q/ߜ|s> m$9-Oƿ"6UVY 7߻yy:wlp갉 RQ+;⭍(<Ra@] Y'$aOd"` <"E =ֽޠ.|_h\2RBucy}-t=-Tļ-@ oVҴ)~EXP (!ێkIЮ^ UĔ&i>M`}o_p/]`G ;ϳB.sG~xɱd0>+Rޜw%`!. {˴:6]-J)ozG}q‡-vI㡻92Ug$Hպ`ڕN-kyYĄl3b>^ "tҗvii oe}]s {z~n;l,$WwwnQpp -s;8oe~kbVGf]w1\a?1vN5mHZA"RvSKƺ܉;hvb3ɻh  &MbG[ !?!3哝|Mxdn 5B4XobvLFczqPD9sسs} L)?Cmv  ݤ>&f`?oKʱ?;ݩI^<] pI].SU߮H9s{TѳS̊]^aDN?U_Xh"M~͑-iQitUC:cdK$n趁q b^ɟ-ϴ,' ͏+u߶P|vQ'tݵ. ~X]IdY݌Eު@hԳ*2K9a,!E*+%.ZmK /3w$^RJ;_RO\7.pMf:oVأA όP̋8{^M2$K[ͅ<ȩ޲O@=gѨW Ѭ:۹R>/fmA)a.pg ҈+WE1PH 274<}=vDZ8t2Sc:L1r'ȕ䎆 Vc$3V# fep#ӲLGE.|4m<.d6"ߌ_׺8e7Ӫm?[ioJI&;X_~;廫-Wѓp`ٱV_zh|.**ž},Ó9BS#JM=N9q9F[-ەK ޔY$ߔdN%rpKLR 7I~2~qߡZNwnXݦsr_IaS)p$Wۊf.ɋ̜ Fii-0XvY&5$ o] uT+:t҆),u NhGohQ7=y0aoS4aPҪ|-ϧh 4j< رE(3h7q('hh4t'9{~S,~9-}uJÁ(Llۋ;?A#$XRà. I? Ԕ.o\q4J>kS*qY:M׫wutnofsBdĞA1 br] |Pݴj䍹G" p[#N˔.4wMD4khݤ go0Z鳠J|RYN:`-E]~*v)|44'@N&%<=ϊN؛r,ZH<o޵H81i T‘W 笃O݅9 "fLvL˜77w$|g/ɧ|;NJ4q/ 9Kѹs ~}y?ܘ.hU\iU*]e29<_' b"򣳑㘎tUP2O$m@.M/YG:6/<+2Ib~>Aub'_'h^$oLiQl46A+_k2+w~ bzmʈj ZQʼnY[D+-|º!rAu{ذglel?留Ni'@[gؼI:fn^RHȵ~}x'{miCRrukj[ʸj^fC &8s:/ ȡT6%IUyGOvr|[Ә pa.FזyVfMCd}/^j8BX*+1k}.hR47H}D_NqvV?N hrT< d1<$(R.NX.gDxDCnS,NTVLk9Ig3W:&B<6fSa-1C [,8J̓f'RAfA nNl}wHW*һy|jyn]fCyOuDxfE'd j9R-"kC{j7 6[;tԒfVltː[S- 'R>J冽\ Djiϕ681/kZbt N$G%4ѨJ:FLV~E}!?:&mOz/S3tfMe ?pi&Wm.Y_(̼9Um(^fxDT%vcQ(ذ}I SZ+׹> eY.YXyuWV%O͈LY1yh6M5[iYP~jz:89!-/PkYM0Ipʯ8m+Efxs8`}N)虗[Qޛ1{lchadh-9H֏\B.$⌙%sǚb[;:ySOAcW.#*UBo>dd`B3<;FPCLfkR8mh] Cs>ܶ Q3\'Avj sx#Zƣ~_m&PGJ tT #ܦ~z5/QD%r q2%qc"*:A%Vw{jE+6EwaQl[8r tT,h5Pzk7Wd<ms)b'95B}bj\}O~D@#BpJז tvJB9> QńV~4y:dBς6Uz,El 4~:> ;"ww"6jH2'&L\9Wj9ܝAT`v$՞+&Ǩ}tߕb1?kӧuJB\t\<=4?k=Ξ9D&l2;s:~mKLš-pm fA3Ne8nGAXe?1sn|~xXdг]:gհk2?B_sfʧM~eU0 M%+^K? H8L;0 5+AS:xCiv;`j&?O^ӖGO``_y{rL5xr;`^\?:{mvLٱv&͇l'A.n_7ueuDJY-wV5׾4T=W;N^4&2sT@!2عvnN>4%Y@V+#]p*kx\9_O1pi.I&9LV"KٳM$M3M6#:ҧzӻ0ZJ26oV~~5j6. V+}SVl.KM*\'j!JΛyӠHz^Vʭ8&(3Ԯwwos$aQтR_P?)tO!tv&>P5>cNڞOv:mWw RypO܂g*Ŭ}HD1##)9]h: 0& dLxpk_i"fhôR~()[xFVL30ӷ]>9)zzgIʛ0E.EBP4lUxe EEBq/Y6@x϶9@ '@̶J%PFVl,f Y~N`fGyPZt &1Y 'E&ܡ4LDcyk9Ϙ~ oyƩ/XaJ j_(12Ik"ٶlC{h5|GV[҄- \ :ش$3̼**_^Bٳc0Z:3pu#z&x?59h˨9X6sZ^&è:TPYُe?e6j+ "u_ǒ\n؊(-ok:cJu7TEMN 7V{`#[ D(Ifp`Yχ%f%2d˳ n8LV{$Cd>u\7VCg/7(n~=sOezQ K)>=60dPۓ:6`)reF1>PC2)vy7- 9O&9bm$mUcLrKj^oHT$=vn UeV PtNPhS n:в!,Wj@H"否SA0ΊҹƂʐ* b#*|UO(ܾoLkljF襰RBӺJNQ]relN9;vzГ9@ie給>ϵSq:Ш}m!{'ݤ ) "{_ڑȖGff9 V̰Ɋ^ O T4zRB(dk', 7h:hNJY 0hbxEs|vi;xB=紣bQy&={sFôߎ'kӄ]~}rw~*}+RO+{V!߭h_,Mv4ʼ%BS%Qg!VjV]dn~kGlu#'! :]6^ݿxŇ0&vYFcBcX'{hLS*G ( .KHɃqkr|I?8@mBr ɚZ9aL$Yg%b~0 SG^qXeY}aٹ&FU,^""f j+,WѨs9>pl 5}F&uK1Ak#IPM"IP0T7Ҫsg.هP? B >#Ϣ Q?XqV#\ U!wSU$}?7gc|!+&h}2e_ȃ9ژN$r#6xP L/e&7jV s!Qe~~k;Pq.msǯA+ Cj*U)nc*3EZ*rP=ǜ5 b!$ydt@%d%=nKR凉ˇEDlHEFq 2_݉aCmsgvp]/&7zSLvP&7f> `eNrh3 H#l %:2b'ǾDa@\7L_b\fDd̚|r\z_t}Q,0֬apBOݷ3,kLsF/ܔ#UWл?1%=*x'_9KaK>qZA 9Ep';WHM`27bSwM !8H[6ѫg?|#%ED(]4W$dT[Go6AM\Ӵ%CMhlv4f'ҽy7+Nnhd 8\ʽLc+A.LA=qyz:C{Uײધ{KӐ'DB劵n!8 lf۴ fU/oet{X휿uJ6q)$P jƺqyщ L0NL%㶇6 3)Fc|d6Ȣt[uxH& a$@n [)8._}8\7494"F#`eM /QX̍׬//;r72>ۉ9Qc4ථ%Ivt=Do`VCk SMrݞ9[ F;9UϷWPtMJ5WGjd"dInB2%#\EwaXh>F54uSޚ I#Y |רe:6٨*es|erlHaЮH:LŌ ! M0ܐ[ :e=*L=q]ffT>ѽ ޯK`W:r:U|Es)7 S P'σR,{d/P GO 5#G?/mba@dB١!h.vNwy5aA:E>:a+).@10[c$㱧#䔟XJgd,_Q5c#D.:SI<&*hgDyvf<΄>3Y5!Q1jU.KHhsw݅ryx_On~P3eeZ۰zӖ MǪS8%ڏr^.Y-fsJ\1X:*rVbwp|5bw6ȞK,!)qu2NF{3c !"Ȝ :Lވtھkg;|J9xe"^J>L׃:>𐼖P-5ʻdSo5zF];/~?ASFb07O6f@kHn-Ē,|(lOtFKa Ãh%0sރo&^RDfJGd rޮ&u&gU5zM->)4rTw!3*]~} C҇EIД oY~Pau>۪ D1b9eVA&{2ٵ  5 (l6.̈́96A ӲW7]}('NԙnY敄Z[:ܵ7ے6q߷=`㥆E菏&lڹhՋd7@x$9k҅+4W&63<7ޠ2H#d)^ǽT mՁeRݖL>Cd )kp@.q4lt_ w[i)T9{O168>aYb4@$XύNeq6JFo(QԤ=$%'f<8}r4 6}Vf`afՓ}[ jٴf~'I__qm*ց}EnP(y"$Sr\uҐ(!dAnz{-XLOJ8V\p* T {sh.ܐXV.g/Ӆq׆ M1hp?X97o؝ꮣ@C䧀]ts+Iw΅k.@>iŖ~\,y3IC.f:in=tUDԑf~Вit΅0ucI'|h&*,wj"oPesؗ\aFW>Sk4!}E9D C8eh|<rѷ<<#̆]@3/ {V|GŸO, }'mG\U8rUU'7$6\Oʐe^ ce0sTEA^y9-DiNoКIf5/Jb[1k~N^'(*LC>kꨇ͂H,g;$8gG>юBŌ椨i$P&)rShĞ9S mDY_ѩlW&ˤA>ۼS66]y; MTl~W}g1lZ-l$4먂hUhE_#8V+>X1Rb&)L&}&A>  Z (skLWmTxnYk%;A;'Y-Z+ &%L\ep;UKݰ~ƈ<tR.B>'+m4_jVY~u|]gi)8":hrb ZX ɶHE.HԼnj'(g0(\yS <[j#XҦ !7-Ƀ!v-W+\Dך3bR4&9twjW&Lk{ nݴ͡HNڊD?сҪc y~ .4V"lCv)s 'oc*iOӯDv>Є5饽}%?)#:(Ѵʚ}ЉbH@km*,POd`bk"%&>!ҩƛwWFf`q,;Ջhx0.h0BG(EZb ZݦBy^R {vihfOOy=r=([o+i272+4?(,fX|KZĨjZ0o-"NTIvDOڡyh"U,wde=NyBI\, \AVh=.l! ~g;(9I 59n]mQ8vmwջ8s4_dLɟz,G %@fc LK5n\_Jw.W>^f>jK2zܛYq 4^~7 ļ_Yc7J|{*bmi\5B{Jdw13 Uʷs )К Ё4pi& } 0&|Ʒp1((K lKJ](:>oco[ϛ l1|.pٯ:\z҆dzɺ8-g_eG\&M uDD ˴ *VK9sBbmRWȴ_b;7 b|y2S~5%wk^3?\0S,Q3OZrZQ7.[\=Hv Y> 7< C8 o꾝$`["&~e T)*3.12܄GHY0s BxB,9 LvA)JȧR&[-eƒy(z>/ʩe>)!Zf~o$4IYhpQ gٌ(DoφO<6[#/ `r@eJ%j"w1j|>ac@h Hnt ͵_Q >d7mtZc'aYM GraY$Q3~t'[ J/r)5&8 3D">,p\Z|Mhz}$ZPh"23 HꮝauEknA!Q`^3 Eʩ >{S*%wZKsțv:^1EmmxWI3eU#7Y\,cL~%DBYs٩$j{Y5(7;WF% :Ѳ:ٞolݱm.#[)o?*;P0s~sh9iCMxS|DUCiB.$oe PjųL#q*XbN- TwSέK[V(gVQY|e9T7_F-0+O̯wEHLDiңmv&hMn:_a>\oEǰf5oC OS@to /mo}tq;#fdLbi6|'0 =V1-n7 Gdq>+K.wk 3bCiAjLluZ%/:Gw~)tpL ;=T!61@Y$s6phG$2i% =:2 }ڼfSSpw0_Ҳb 7^ґ6_& OoeY'e>u408Ԛӡb Ѕ1S" .;QBʑUF}6,`$x@Ѣ9K$-w])z0Qq7:+"̴m2۬\nyrځ㣠I&'!7o3ԃ^5P|qՓ>4M\|o2%z]jJpLD1s:jl]c*9fh 7g$8hKep?ɀUg<  V}@tds١ot3!)o)<45ҮaNqͮ2 r2HJ!A4NP*e(GxPr7C阍c4in_<vO/3Rz*fyvI.fd $t~3!9d-@>iW;͜dcHhXEnb@ޞXUV؂aȼ\ΆX[rvw}9F9Ŵy}mtv1im\?x^Awn&7떦OL4VtL &:G1!(lM9$N/ '$W4a+ <]ͶƑkK^e~JUYN4t֒GG^͈|*,a{ʳDJ$L'4-jże?> ޸*(@u>% JKxN*$is=hVyr#&j[7\$LEOxõL.*&n[@qҐ393NV(olP{윐"mmwhwS_ع%߹/jJ-S6Z.`^٩{^/hmRѩHD `usI{{2u%ỷͽwLdQa+oF좂3LMYBvAFUɽ|"b)( 8В"WȑcPD!>P-dFT9^BPfG*hVɻ k9xۯRg8iQ^mb jbO__?w l >I3ɺ]UU u u"ؑ3".:`9;# t+b{GVkR8$o UD'3 ǽ|(ߠ WshKSD0㰡 rs퀒ib ` GҜV$y+rI|x*l0 $q>@~P74|uK-$cTA-WygVxUxV))\ ^t_`BieEM7_T R˴{ r`*ɖJ^e!@Ϧg A2e{fN'+w6~~@#Ņ}\ۆ5f.+ӱ%G]ox쨔n8qbD!b5ޘ|/=Qݚ0yA`|P͸A.iYeОd_|FL[{5m_q aG1Lx rG\d90k_~95w$9 $ DMhV:&s}}'+uS84h6s`9k&$EUv+W=Ŷ xhS-_IZ)1=Xu#2)XέM동4{cgC;AYVm4 %vا1X,q.L'׆R]蓏xٸi/кusTA+o[+ h Oy#OvYE2Ɯ Oc6A-^Z|Lf(ɫo` RZP~z=[fԭ= bɧ@!M`扈~koe?vBGNo-3c?PTíg7|qNF)_^sh92oGZ_h9]5gJ[~s8'J2MFc74YbxE=1jZ)vn ,ea< mPNJy/"a.4m_l[Ӫ_:P%Z.\kMM#-C<\D"ipc b Ɔ\Ls͸<S9{ïS mHq~}e|oX8H{Z J0nPtavDmTu :Ac~v,;[Fk{ ӰaLv0'Kx2Rn6͆ cl+RGNo^ hFQ+3?EtM-eY|lGdM^w@Z&ЙSﳝAo.t7 R^t,i! ogUWzT 67??Tpa=*wطPI~)hOB;#gRx(u\'ǧr@Zo {P';#[ W> d^poy1DaUo9ZLNU>uқ9o8~~n!z}f%B}ag+SuN<14&!X+pX#EiCzF7lQp w}WdAL'}r3ߩ(6]hi8z 5xvD}3?86cC6Qx`&@J!ZVa\©^!@QK ~;-_OWaWJ Ks{[IöFU1b^i䪕r"s0$2%jr<@2s:b5ȄF6Urm]<¶RlhKy)bN־qNyC]ɔpNGl#E~vqNCf7R&qt*>jG .'dIk6G{'gMBn*Ѹ$,(Ubp7D"H6n[qe:'Y}|,S G8.swp#,; bePD*EEP.'l&͒2TfK HYd;"yE'}pcjuvq/n/ŐP,kuD^ <*q~&QUZ"!V$Dz&x[&vڍ`Hދ_HJ8+̸煆Jg%Wː&t'0^e4e^ZR,/;m^XˁWlbh-hKˊ{++N 辝ԡAvPкk4}WY.]j%%rv&I[ÐQw4APo%^&&q~ q &KS.jxCR޸7a6@8L8~am d3gE :(DfVM]\^n$ß6OgH,CLd%7qO܃|y7E$l$+r6Iظ2E۲KGdEFƘ?!8u04''6ptċc)1kL\3"&@v<$lO@5#/t|Pe MĒlm 2dp4=gK̓ gPG4A"|PݲܜׅƄs/ԊP. բDDFWw#Ў95o;s ZxֲZM`%) Z:{r`Hhݴa~Aq@\uD@\uBrNM k'-sCC/[L[zz!GWTTdem6n+F H&> nbndTa}\1Z8['dNCe-znIۓ鱱v7œU+vL]6N% g4-r7DсɁ֤(0ⓟ5n{ 2gh،i.YPخHa>YoMY|;'rImxȡ(!{$t4ӈ2Cg!LW =<ب4u8Yrs"l*{#vŲc?tunr_svl!{ήZ6syy& C_h%:tA%/zC['VdrݵlE6\j@_Нrb+(Q/l0m.ZGB+hX >]^vhe-_fKqw Hk#wf{LhI9xJ9ylM4{x%`Hj+ 1HØ`PV N_v4X9+;EżUKԨpّ © %RZݍZDZp\)13}* Kf9gCy"/u=٫!m>"P|ݷNh}CcL/\4'c vo]]92K[IQ>Tԃu[efҟs"Z'1Kȗ_J+/Ѝ[oeѝ\&ѭ QB3eApA5-sYBh}ц)[Nx'XRn\Z]lEn7$dkn9Q$J6s,1y c$/+AH 15>4=C!?z蘧zn]L@WUѝ33uxb*Pt^Qr࿳{f&(Jՠ)q52K}Xp@W0.&b\ֳpOkpH62;N.+ְ}au"jޣ9,5F D8GɕQ5:2M6QKo_~9Ϛ&'4,_\&ϕ\lC۽.Xʏ]VukLZ_4)ˌ&D׊5> fVO,ޑi洟4zN/]PZab7jz0q#}J#$[ݪQ`QdFX?ɫlG^,dWx*F wJnS+#dx7šOԇB n 3|T de ]bJg_(+bԑkƃ6ߍI._$q4{a )y'!+~2w|4yqyjy8cg%NwOgW)Qf~ z$V݀"k<>reeR$_WL3X%rgQd*6NCGyD;9Ԫ' +R.IMлĈOPsqjc2/sE+jv:ptQ uՂnjHfUY6Ug˅v'^//^yF2á_%wv-S[.$/Q 춍Ԗ}}BoovL{d_D]*Oynz r7+{FTۇ1P^_ἓd]L}VO;r' Cuby |82[7g뢬xp> 5YuV_ednHgI&{W-NʗY'lq^46Ic0'JNWy"T16| b}U5x ;L: #}@ŹjgPlyʰO:dx*WK,LGko0Q/$eO)u#c)Nbu7!K.bJ bw60s3k|qVὯWH,.>0w ,ɓ/lPjF9e *83N1>ǣwSõ#Kp,/A. tc>L>OR( 6٬fP/3Ԯa!7[Q&蛬iA^|ptyZ9!R!A!?aLY6;T+q(E^ӯ~yqsl2g8m,І9g3Pjcecn5s h܏b(sc4yV)ޯ/W}V3*yov͢qRy`KiTz(~=vq1Lg0io!HO!%0hoXGrmu.V,PKGqyy11GQT]5z.[Q? &Uڇ HGѰt J;U%4kО:m-J.[xaR%ߎQ0IGqKzxK3msyPȅŐU[oW*X&3ɇ|\RQ<°ckqN#7˽a"WYLDt\Ue0( f%o-o5<-K]>9?O&hs Rt[E0 =[' =n X}G'g`saܟn^"A-q7O*c5gQIŸeҨe,Pa`=aoQG6Z٠UO%'*6>b/!:foV~) MǏ-r:kH>k\XnY|Q7Sa͎Mp_t$9DkȵG}` ;Js"мBm&ھS0B;/)Z_bN:>{7s"$`߅:Ote8d^"VF-v<|֑|UFJ }xos@fVy?inP s~mnSg"9@՜,>JsKY!)M`YF`R>0$~J%XkNQWԨ8Lx&p>r.p+ꖋ3cP. TFS#W)aH ^LeYulm@a(xt*!p YPڅ@缈ATPYejO{gǴD7 I奮xҝ[aƫ|7ȣt\] nN>zuWXFkNZ/ބf~G% 6o\/ϘRIlqGGI1{my܂:DJQzWoQk#W 3oZd v.;OX昷\1n2af*gb(>VMwOp@la H%k)33N?bٶR`JjRޚHրX˵0fySd@n֫cs' L˺eN.>oPfN287+cp@(r~*y(ϾeFx`aJzĽ2& -t{wDf3Dn&f>.;!2yC7uX?BSPSR]z.͡4`MQblc{;hOSlp3yڿЦ * _ȬE掗͸J=$c$nUפɏM\ a儌G>`6}7?C U5sơ&-3)}{˳#+ B~vBҘ&?CӦv YMck]3TjJK[T&|5;_"`nJڵ2l3XHJ^ywX3l"{3 |*%P;aKuuj2KO9Զ:HӏmAvwZ|-_{Hꡉ cޞ%}g=_UPE0&!d\%WQŋa |xQ kP.ˬ׀A# $͖Ey wsΊjٶH%Lͦo.zUQK!3WPnm*Z dL?9òb 9ec.4eFsֲ+53|Y~xdrBB֓P2sǒ{)$߅Q 6z6a4OٽSoe"9[LCvdt.@wӓhQLs TT9 f=oMykw\?ؖq w)ѭ#Y[jT ͈<_]>dI޸~ Xk?YLVo0QDl?Ȇe\B@]r 9Bp؅9A^$Cd]C,7yu\lFasWyVf>xpW'u|}Da8X]m|f뤽7_t(f"BX7$aOm2K;P*,%c]A9)FL* voP1hFLnoA4Ft>j X4t|>/ 5nM\ I]@ED=kzpִߺc1W06eoّZb*Pֿ|ƹ0UlѸ:ϝqDm+]me˴<.MԂRP>p㯕f2.eV1߸Ā>6Bzs8-l)?#}dZaa3h1k3{c{6C>O JnA){1,h4AH#拈%?+ٜY8O>l.#G[o=/P7 tydmk#?=/L0r j^4-2OIJ]|E|بSdT]wYQ㏞FE~t[ݬ3+36kA7#D`!2BOts Źlde;q7~ fٲGGڮ^c06P^Rv~NJB<>C֥_My?#vTvL ݩ7-͜3keZM|;Ml:Nj9=>CK )6-JZV>&h E/Yie12r{R'7SǨ/ѴDJ\O* v5W"6E4zZqPf*C`[aw\J $~6L#~;Rjyͮ+4T#zfSij_9P*\?|_&Pz9ŪδY{EL3kI4( Ž#SL9M^x5F>`LvkDWM 5$2p]@]_:ZOPwLdlYR3^GGFq^?E-d}Mz̮5_ɛ@oYFRNB]'Pw4N@& ܻώbG +xft1:`g S}d:+|.H.f~K@Bxl@A]/P8m%!MNj=DhNIzC߼'YᑇfUE#.e] 6Pm׭x̟!؅4b> R7 y}0MKDziC;+]VߜϖBI 3(}Doy.Wlb?:nB V@.d`rdmk=?01MYL"i2"al@ yMy%?$qfo~rvIL=Q=k3m* *rɋHq~6dE Gܦֳ$Hamo׼Va䙒xւ2j=Km?vՃw#?K'! )|<|m6$>D,+F]Lߖώ[9Y/svQOto,I$2i:UA/y2|44P/9UIo߰-|ש{~:hqh7#NNP>~`ׁ`WhwL='!P"΁G*DV2;ЗEpoӜZ[| S~mR_YQYe>M5ўNA&luZZscbmxvFMj{\upn>aiB>=㏡m~nlD?MϑQx? D`X'⥉a,|(>!WgL &/R%̅Fnz5ku6|9}+lZ>5b/,8ؿ)ZSByr+~`Y`xn_z>qK>{OgW sahz1´9S-9 Q Z6@Gym :""_!ԏ8tE_I} WS7PLzʇq{a Erg wE>󢬪{u*)B:qwt▩ J2 Oj"ˌ ox" 0楆O5Mr>3<wZ+ۣq̂q3XɺV &\l(<0VjhzJ kZdj(Ǹzߡț̖?9Ś;zK%_3whsdc٫ A,+!:#{,,|ur6OvԌF,9@4;F*6iHAioIUà|IAPl 2%KlX^ˀ2hEiy*)/o[' csa }m[*6xAsRvOvs/ ݜ~ۚbz~w"1.q9d9X,{d6T%j@1G&7# rLxۑqħ*kp8/4UqdfY`LV.,TF=;Gʣ'_x$պ t+f NX؝9PhRYx.3eeZ'1T4 ||QHW!(D+j߶V`9 J9M0߼3l`!OpX%eBS6QĒ>ϸ-Mˮ l` nM8]M3XPT&-xZ&>PTKq+a@@21)["C ˁ|n.+t9Ny wuZ I-stM\'nҘ_fąE)l*rVgJ%ƢCIVT|/=SHwTZRmZg۷.vtmU\VRJ<(m6+OPxEݢmQ]k|KFe}bop,GvmOv ?&LV1f}E/L yo?c&`Ge]"f,,7>L!JP[:Jvh뾭UPYy\($U ( s]ߎ;f2ocfr[>9V1?^"o^hNo/6n9= ޼ƭ k9@D)"+F3EdQ?p']⧆.[\`yy(Lì'EH~ЪV1K!High\wG|(˅.E |.3[%<%6J)Tl:ϭyZ :۩{<G$2(v]*ӊ{ПU9ZAoANl⌂uՅ87r(M zuH5y֙:I8!k:0xsvU|*-~IW]p?;yE=oBuz eT@/mq+〾9s:{; y(8Q(&&bW\AV6'Y$e.d' F_ bn6݌pR|T=*ߓdI䞶,Ҍa\cZ5V?qFC|2*U-/ x PmQtf#Pdd Su1g~W>َ=ARk5r:gWPL C)v/߉5ZYFONN.3d"ߍُhY2Æ.#Q/3K=^"D%uRM*2Mc;&vDl<†1bl` ƵaC!2]qV yAM1SNr"9Ȁ^jq,D(@ Y˴'f32eoU8&^h7cMVY8hKo7磺8ݜHYаZĆ-9"F>"`ҵ ɭ+F8{yL8E\#k{b}B08&%=Y'4TvG.pHGP1 /j4_M1*oܨe#6EdЏ>Wf(,iˬ {idކɴF/%~gj* u;o89#'Wiبmyk#E QNtr";:N_e_J# j~:֙~NI\Wٜ;%m\.OKK/S)]9Uqk77S}^{E[LCƧ&Z;F%t.+˲~>Pu~T_4G#^&V0d04W@Si[h""5Fàv}3m켴+e >#3!J>Y6*ܹ$so5De2<^' NQT ACyJ|X enttaUcXsLY)|gs&9˰;]Io;4ߗ-\S3X~sPDf ?=zг9NMkFqm>n;y=p!ˬW<7nBmc N"eʉI񰦀neGmfA'n*z F˄~}vAp̓l`o[~Fj 粓/Kt2=@nt{foP$R91cx_RKrLs\i(8czҴɍh\{/qw\qTVмUп+Nx!K.?Js{s Ŋ){9.'U7r:݉e:C9nA.ы`[7nJQr EbFBDhq4 o3!QA®c s`ʏN6WnP[OvJ1͕]0Ga?"tG%Ǽ}/4/Yp.Wt~ALUpsye,6wZLXgc ҏ䡬~_[5=tAhVǬUa=X9-l΅+2w;&TQ]n {MmueĈ1d:֙]P`3΃Z$T!d,cí{-UWa쭪c'`8#m WU]*da{ wYjɆ*h1P Z[٨P v_Q'4w]-Ӭn sCG6ɔr"ٔ(l|_chld赂 D|`ԪdN ES/ }8.*^T _d Yf?\N- >y͒YlU0F?yM@>x¢7MU4TdYw[.nZƮ7~?omx#k2j6N*+DT)ԿBsaI١9GJ5vsSc uffDےuQgBTsĺuA.F 5;(sMCVCiͷmUY(\ylk V}G\GKXe[dkL'2ɭIrdfbj0WA?6׶]<&S+}B3k4o"yyMq-#o-Mkn,f".oyME;b/`t4ija vfl);J*mp VTh 4F<)GO4|56Ћk%i 1Zʎgԝ^iIcG7o.e+JyyG^KN2ۂRH YJcǮ\fT*k eFK#r*Is^І|r^c_sM}ʽѭwQg'J\b˫#QyD9-Crw.r;l[.*dr~;e(ӽSNq[Z?ű +r1kKt*/3W8,8.g-B5)PLz \*#&ec|FMnz Hݛ>l.h{].`xHM6bʥrotkyl31 `#$F@oS6Tc~{_A)1#S$>fHn v9YRz$0,SQGF!}Ī{-Bt(t݆!)h% d׸6YX|Ќ^UUl㾝kّy^tݾ,$82\Sxڣ[1U۟v{:QԼȞO"7ОB(qʆ`1ӡcw`U{2d}[E*BEԺS98*6@0Ѻd2nBwRv4=r엠3®4 2&)062XnoY[PW ֺPAMk ~H@%vAKrvW9P|ͻq_d? -"mU*|f-懧Pj%׸Ќ ȁx|De>I?Ra.ј MP #=E98 D>FO7HGtgFjR ޗé D+ ZVJ.̌ J6t:x<:nEqU2DT.oyƠLq5H<<*·tL)]Î,yP uGUZ E[`9+c+6P!QCh&`_{wQU7ZyQ>PV_`qBbTWtskv(*1 ipi]ߞ̓\&}h&V Ҹidzo.T(4h-gZ@ƾr~vrm;:mUyc׿77ypR=>3۪;epI+PMLN7(3ɤyE{-G0!<_q̉8*Rf٘b 5娾YF3s?_21uߕMPG8K @v2=QO\ 2Sf؜bGJr?p2Dr"Y"ۋjKfeQWK3 X*W> t(ꠊB#ty@oꞏHò-1鎛XjR*)/w+l͛}R|?7FtUa,IswޙI)4n$Pf=9&;{#UZ^~y{1B{B{{to-YCٙO 2"cM'xy'2Jh|>j?WZѥgiCfp`(/&CwQ^+$ :_.hzaEfNm"KJ^%ǩEC!y.Bh>Wlto⧴1 <6pesK@3-ltT_#~$ 0T>*䔗?{/eA@/237ZFQߊⴜ}Wo2wa8u=jbRJϨK۔[s*x-81۠ۙ.ez mmW$'/ӱ8f]#&e&㉬sGel9[K)$~7yx"Sе!Slm 7&!񝇽>Z[%Vq7 CVᘪ\FrFMiwez"w†%M}89Izȍ>{kTFfpEckdΜ*"|#*o3"jۂvhC…-kiJJ5x:9o ocna:c,oX^"})VrDKAճL \(x!x2[f2ǔPd[~ E$Q٬o$jrlJ'[ td:E _K2Z&Bq!/۩*ȽvNuyh_yӯqɫ4^Ƥ!B_iM6(*VZEn^tNMuв2`#q8F h2b`UlKl?8ʚ3J JJ[z Mx m <3MY" l6tM=Uܖ1ڈpFN^!HowWE3Djg5ț{ .nl_~1d`JB]> zVh/&`j ]̪A8-cmWaE~*fwM_8AX=eA7vhOt^fkYbͧ\fsQsտQ<ѿKᖙqK0?ܲ#oM[e).'>~AQTkVrV9r<5u}?]t̛䟏Kd< `ѠyKߩICŶ~ĄJ-DK2CVWk(WB5 ,k2c$։)ul34b<@?k[XpH+#gz4o~ȬWߦqh /SaOCɖfNUv#eUx]p/Kν>o:XeG">~t[7o甓­&<5T`%!fV*ۥ]l#1el֍zoP?R~r;>`qe}Ў5W1xcS"\$rxt7yjfcx< +.n2N;0#7'û3k^,&Wj h2lmZ჻2(4} řfb)@ˣiwJFAOh%z}w3M^cqB +&_S@yd{gAO|&"Pf1p1RGT'MheMffXYLZ6<]=;SMs`vQh8`$"^s)ͯ D@ &~&? G` l\m (m4gְ o'm͹L?AO5xYT׭h8*ؠp犳<g"pgҴ=D|dΤ[꣒pua~0HnD-O |CR^2"ʞI<ڨOsQ3~qS(΃!BulZq;l&٬ϝ SڪsEJِ#DXK"`aу\=ri[J/铎GĬТby/?;e}S"6=;!*6yS23š *"?up hyWr1NP̵k:v([5Eh>2 s4.缝ha,?щUn O_Lhb^fJgCSd?߄(s-eDCcTtZ(_TCsfY !߸4aMl|$BNıU׼S9kޒTm!"Ua|_ܼEw/ "qrܔeO8yVY]|t)]2^W[ T y pl9?~F9َ~ҫ4~~N026z2j<ʆ^mdh5ƛ.'S^ϭ'$ 57slVs8ov&vGł"lSDvq۰?z{˴L.!&E4vQ.7^~@Y'q7<&6~ >!r3&MW։4!YFkb{0辣2u\毽ot;0@{笥ҋ$a֊~|r}m"I>6^KY&>>$W>=qj*'Oc5M1ds9RJY:M1ɋ> /3v8y:'։9/3Wa5MDzlE8-ޑbwP3ǥqWzv%"84%+|\bD&7%߼f*)If?++'0o6ߢ1XU9:o) LhgctTi>g8P}4TW?^&4U/&g `E[sXu r~XA6æ~yd#>n_ML鋯fY쾚6WV]%]5:;nfBlS+pcQޗ]]{Ԉ\Z) nGE&BZ2:+jeU bB;/aLKg= p^/p?0ɨZ카S0A]IzWF$U|73.Mh:ZplTUdJWӒf`ldY&uُ&U#zJ2Ӑew4zv5 Hװu>D~voY[d r+SD[KPgv#!1h\3uj^=DYOgE;C@eby#܃Ph6ѴJ㾄hORt w4R#rĨScgK)]M ú:qu/DyT&AyX묻yFG致D.礫Zז*t4B!)iX.^z)q.|;XܣW֡OFBl6!i!#7_ zcy^~,X( .QOE0(,KU}v yB٨*Skcv4Nov]6`2W?֟}iM\(d\TsuP| R+V]im`i0crȇ? iHyJUkhn^8ͬt^!cDjI.s$G͋.A;S]$`$*z&A'?U2jӽE/IѢZ̕|''2ӶeζquLH戊"C_atч8MA2EV/QҨGI!X2Vȍyu 9goQkm2IxxI:-EH`m%٣rvz#Y$SFhbiv(}C4~~QE4$B*vƒ"V9^ZBQ:p6q^tt+M6rlyetl:b4-#94BO_ h<)5|6N<9%"r+}Vi ZV,a{)s/=98Φ߮W5欇X=6PZo(-3m1̼>"Ow%-3rB b-i7HdMN"dyQȶei'A!rs_kNc7"j.D٩QIڼگ$DBA6x#wY&@s]T2}z B&wYK5(v2 %a\JmMD8jVo*hO=ުSw욓 tAǜ?AHـ"an2.$r>b~ y5-˨++I >v'5tt4f6FI:^8(SC8c{{ZT5}6ߛb$ʹ4g\F,7 TWs>t*rGv~i=8RCΑkM<4F)7.W J?v!E"R{O|`ij+!,OkBC6XBi6|;c3Vl I97Xi/Vޮ=-ZʐYC7Z8A|Pt =Y3#/Ir: &q5h_;># %  I0s+Lp*ӄ.RnFj>kRﵤ!P||D3B1K2INm)b+l(?*GT4Df]ХWCRjoiL; ?C-J*_\B͍{yY' [5G憤l8/xd>!ǩjrسZ]Ri'`ot +Ja͹c>C;s^ܱ~'SrY&V :d'v&{*AqLvo"UU+ ˁ }oo 滖0~Y. '!I0~ V9GP(>~<U:{e =YcUTWYl1 :}&vmƧ?oe?=XOSfv?;2nvG߻^)n, /p*$8}%NنQ fs'X6Z:1u4V1v? C6o͇GY}lO6s 9P-Kn_.Bl Oah~cVoξD^ЏB6ԈK,[7jBDb5{v}] z"ޡ svg;{S}/##{SX#5&鐳HtNԝFGY U <|&yma*ӯ$/.9-^ouA& L=>9O]qAuAk8~IʡnLy?&q]!&ā@37{v@KOehh=a].2wcNmjMil)O?8kS?!z* Yd lyoN!mA$̾:0X_V8$ayo\Ԕi0K|9]F0ﵱ=︣kSH$7ם8 9%O0Kfqnȩ`-L?!ٓ:袦ճ#îjz塮r91.R};@Pqp_l4Zp,v.}*~>s%U"ŀm߿5B&YI|~ ʟX&$^H#//c͈JiiUR.o8-PW|_~Aza^k{:bEV(B^aǠ0VK dW:75BU ‹jj6 pjԛZAm{p+!S*W( ~jVci^bȼ` w[ z݉ &RV$Ǧ݆Wfq]P} _jyЭNnM;cfۍ Y64>7|% ^;ZjC;U KMy9`NIH,L"dm#ڕ~Qi_{4`nLyCEhH&.9^bHk݆:VdQ$h>ZX.u .n 7I/jW'je'5or9SL,H;w*~h~Pyeli{gh~b.5E$X* YĻLP%qӲr Fέ)_cdEV=M{z2iEFz;OSBeAk.`X85hVn&g$TЄTe͎Y4][y0-.PU-9a5wDXցRl>DuoZ8l2?@hW Y A6Ug/Xtitn)Ο_ *E9x]`ٽo+t"eP dvIg"\2/E>Pʫ Rϐ!MA"q*9%~"f︲)ˊU$HAٞmT'^r=+@$WH\_= bCcXeˋvf}f‹dEF:`.̀~uw3ʒZ⹟:^,3m%tP>>=#§ 6F6/Ϧ؅oua^W`Da6f#Iĵ߯R 41udZ#*KXN\Y1a6ݎ6pYYi2L2?pKV5_]JSqާG:f/h ,ʼn~ݤ iz$ハVʩ}%@,*VVy߁V>v5e)[p,+ec"ՙ`+ʱ!~e;qEGbmEP/!6P]bmESby31T&9\Zs>PVC;NKxeGM*ҚwRw H6yK~k8HTs0q,-O|C/",*  ibk.N1 {lUofJZK2 ?;$n-g2ebBjݏ.'s$Ga3*E RFax^i!*ޤ@ZKfBEPه?rxUYtuJ\=Fe|r5w<2k-̩~ro1Դtf+\Jzč͌t՟{QqWf^TJ:I5ׁ\547iXa #a%F>ߙq]#0XݍR 30CFV. 2?<BG !YAy&L!I?xJsZhYy{_}QGm*Ң.yV FFޤ'4d64YO~߇dmV&eE$̍3n#r? D]hS[uszhݪNE5)UL.4Azuzlb[bIȫ22Nc$_(#."nduE N6<*sҏ/szPXguRJ~Lr;z`>Ө1h{r5WP.(?u*;ˋM vٵ^&7ٱ✷LG::L{Q#ϵ{#[,!yޑ%xK*璕0l޶حULgV;N.⠯f?КϼjOJ62P:kTZ_kY j7s`WwNLUeSD3a8Ƚ$g`qś/ ]6jJٰ'' x*G$SMwaE3 0E$cy 7D)VN!cҡt\T5QNANR`7M^=@_64hh 8p%c=np4qR?MKIY@A\MǍbϙ>nIq웾AJZ*@Il/>e !{w$ay^*0L)_y`=s|mSFIy9odyM߷B̶;JϡL6T7|[rN&ö\ `/'S̷W5uc]<<D>SU[Ez_Z |w-C{v4CԳ-ků I mF02P/UeGgHdf7n a2[Esi2brJ{z)/%o 6]^'>Bcups0L5J^T>5moK x7*rw%6;sw+aFN2olqyi&~z{XvT܄3QMsJ&td}|Z?Xg\ײ]CfC{ {L0wu”JGr9^@'{6uV#c^*L!\Chfmp/8uqrdlhIbG I -*=?C/oÄ'2x miuSub;neyE+YG$C䇍 xᘣ~D6)5ڄ Hw+5$vjKj5B3'*_Իp[H2o\X ݳ2*e,h1Sk,;甸CwLORd1ݠ6qۊ˼cyC$D~syq|6&z\δu Mr>L1d>7N%1ŎC,k^Ų!l0./b3&Xr[\щ4IN_~)~Ԇo2OiFخl ކ=<%=PToH{랅$[coe=|`Cpc}2/РYHQ6Y;jNMMH =j[PɳB]hXpDRf5M'~L &~)[~6Ƥ&4FEnӇ틥]4YV6?Lj7 rPO+o!) |:~H+s%Xu{+s,_ ņCsbl-^SCN G1A0'kڠ9}! طl u,9N=fO<}=Hy[Y)lSe0$~/}3TP,w3ȚvIGu͊^dhWpjkSyBCž\K)v/`Chiu"@5j\>zd&qJ4"EMY2vtk^~m]0;ۥ]n~`%ߞ.7'bCK nJPd:!EW/+lQB˲mz#?﷏9XGC~0ngy]L|J!A[@~۴48Hjlgg6U('˽dVQFͲ?^kkAQ;76"!xB6яᳵC5P) *tűmMc? c(X?\[S`SдYܧCX{X1Ƹ& 1C_~)2 2])v%`йh|"LhoGi|=Qͩ7[ZPmxP-&J{_tJkkw*D"!BQso4ZZ:1/9w<]]S}٫9V[hy x^YZвV5*kMb ǒm:aQew&処;RI,g<>NPR3 M n,[^ aC|]4b>HZLF(c$!Kh_c]˼5c$gejofjDr<[ɾ~2&rgsHLu$mrЊ6"^baeR Ї02o\I |+E٩\Fo7.ߟeJk\k^cU7Um3Ui$-Ct<~2q䡾vřbzyMj&zqs`"] dtd2/5ɦ_h6tNxO QS醍VѽBH ]#2Q;Q2K6-i{祖’7߸umh*z;>Ueb" օZ%=Cnn62qDV.1p 0-[9B;Sَ!n bT6%Bf!UFAHI9-5/amezjOTceXA+dٴB+|3Rog4Q0ܠһUD4/G.֥o%"?< Bd m=YXU[&36rE,U[%I', tWG9lJJWUSMm|f5k^%%2H2.l [X/N5p եefј_WKftK|1In؀Fw ,zQNM^C(U{yZ}M 0߳1[D_ K/RCQhlˀ"e7|~폐v6E`ߑ{ΩMxXݒݬ&n.i NݭQT ^7d0N1iK<K4?m?>Hqn5: 㗯OCxvtJeE,b~Mv;`^w;ˬ #^Sn/9s/w94BIWcwU&QLf87A~)ی'P] ,P+&oHY4~,ưTzy?9Pr#4mfɈ pxV--Z{IUJؖgȻXzfa5\b֦~BRA[`%Ȗ˵'ۍPqqe+3|;"wk6n܆o֊jm!^\y='ڎ.@ UJpBt)֠wO/% υ!CE"/I.Ca+Pk*"E[քA1liXjzb#>Gow!9| /ް}?-tQi\fod,7Rw 5,RQx !eV)w0#Ԕj]!ZAPBNxu=(N,@47&.+~kͼ6M/b-ޝ,Ӳb7s>9N)rj]\!(8`CLl㦣ԄߺPZ ߴ 1}O3a؀^\6vI}-0? PK*o`##gCxef%dc|p m~6 A;;a!h$j s[~q/P5t*?*& Jd$<2>Az?Yzn$&hiڠ|S<:w*}3>WkݣcqQ2ABo9U~,,Cz\~#1 d]&vMn IexDJa\p>aѫ1n;Ie/<䣛gA w_N7@|'Od"ӒdJg02#\r0E`cdnHdKs QDBL,%bɭRl32~tB=h(3/\HDO n^6:u?J8F^B.%>q Z(41.e|ÿ%$|FK92\V "k+)>mH^όyn!Ä~⃿ ^dvO<\P)VYFR ׉~?ːԣ&fY^qd5{Ǧwi^Vp4(_bcemGh=yR0[$vEqOvUbW\q.Fػo~gAqB"r(F͐d^s9AMpxA>9ǜ2?x&'LRM.o>ϼ`+N_L"tV10OMVoRV0}@/~,ힷ! -Q{1:S O"TtG1e8ޙkSwPV Jyꎿk;&) ۀa@Ԝjd^#(?7A;%fy(*\x/6 o2NhL8y_a:Wk>lJrr(!_g(qqX5neaCeɅe"74 S{%;%hŴ]N!} k1UqUWfgvXATsy,umO+ْʫ2YrlbyVތiN)Ӌ A>݂ ]{ysh#}g#cS솮QQ/b.zio` Z9! 3!-Đa4 Vjp窦i$~Q{e*Aye2^Wi ;|`,֔fx<…H. CK뵪e M:HyMt +c*X*dJ-h$*\\fE&ͣzYyV7 iB[~E# v`iǔ_H%V*_EO~kU?BR v25`Ty$]S!d:":^:XʗbVG2Y^}n)|B xzk n=VYf^l0{Bڤ>hBLw '~pGi)@-N}e,z֒Ǐ0[ypav6]=֪~%sdQdNw/s)e މ^eo!Ɓ2iQT[ " J&{.7I4\$^M %IoߛI=}#d%ߝ*fs,ېWe.mCvbV,TЁi}5zLU$ԩ6"Y£4ZR(&V? Ɠ,JU~~XuRsnթeq@Z,UR~ص,wCb.%o 1CPL7 g},%H߱M"_F˜/Vvm@n|!d-eW}Q "Oo\i0C㏷#w:43?l"C4𨄈e%̬ 7*%N^\\%";:21Vs?l,!k"X9:}- eH '>9Y=vBLCDUv!Ch[UPދ]p!B&@mPL#xSQ8[<֙ϨٓX.9_ ]L'=yL|x<|QKr3%KV >5A ¹lp$m|'c˥ޭɆ&Áu+A >σD?rO4e=P}9%&ݞay2DgWY}trJ`?ч7]D:xŋH)a,*l`<~ GvrɼVKvZ0*Kl=xu麆}zA*\dA$^`mpyE[ !:iF=@F"`ǹ>K[HxP,X3D+rm9$ ª}\Wx ~@:߾W$# |lcܔ!oVj# ů=¢X?v~Q)eF4L;iѱG_hǶ(6[ƾXsӞcBmGz9(%la]+ Hy^PbcS2Qĵ2$ux鰪%spNWV%Ϗp0BFrk `ZU"eZjS]qd|B[>^ #s5YI-S*|G$RS0'S(%Nxyy "+Vep1GwhZ%nώ^oL(ff=]X,uD/ԃ<1  |\ [?Cml[Ofa#08T?92Ul㒱;;^&9G\fys s4e'U~/]ܗ[ԮyB)ZZF|l&ʈ[Fxwq}sM@ېG77[./XF7X7wm9rIeٟ?/H)/DV0Lw% F/_gPW$-u-7+2b{m1_Yor}Yšs #k {݁bAe\,%{?mq5Y,G=_ Qg.xq 2 xBdfFe0M5cmzߜn TW@R,ga,by|`w_#Kpd %m3d#oMi3 ?3ֽ*#wcKҎ5qrZzȽi ן]݃{ɔ< +h/ 'y, RifGџO!u4pyeuQ@F4Qwvzk]0R;J,q( ?Y1@كרt ҐLJn&[[6vu9K[.!Wr, |}hdj6|9t*8d#w6Ѵ+!`eJvA;`.C 9<:ض-X%S,Sʰ! BPIgV~{ƣ v]1.nL]gP:кr}{m-be$ c1񥳄Uj]<= 塁w1)2c]qס~rp 6ᔄyu7Щ[`3g;Θs#*[lF4q92?vC(}̆mݸ*E2ۘE-/P<$5c0X>P۲z|PKJ.x9Czxm:o/WkL܎1yM +[xN;C~۱ fM~sG52'C.?RȊ=’nxΠ&UF%V jD.4o yeXd"Tծ Ugp]ɾӎNHzI,庆d G ͒QhrGXK'Iȇ+ճ)>ʓ {W ]?޶<&_o>ӿe %h+ftgL1XG\i2?rp]UR|o^vxo~?u7n=%j|xܝ:DcJduՒ^W$a[18&!u?u:YlA")zD]d[Yy׵6/}u#`Gpd_$wfXZ֤9~ZVO&H*59n΄%DIVw` )d)"?|;) d!ɔQedD}[zpDV_dQ'v*u&d̒tY!4WjޜPcyy0uM,rQ7 ٪?.+f_3yw72w)ŚјDUgl$iЫ]`b#u;&;> \77C=k@)a[nx96hxzfLF̒Hi;Օ{].7|-MDQ+cԧQ,MRv 8s>NX3 ]Bf۶ևB]*a(_ENu[0Oؙ4Q,zeLJdOْY\C`/x.Ok)Qܺ'e25lԴD=aCjN+)by۰$o{HvMV'ęĨ2ؖ֬'$hwbe6q,sIstjerv9ȁ)^pSA\J]ͼcCE0e?rS:ħ+Ƞ$ʻGғI#fge!%uCN:Ƚ|)IbHNN$-:.5qona-].^{opBݨ[n+q%q<6U!hEW*مhgqܿIOޑ9]NaEi2TDMZ{")y,LReU(e0 !_<7?[; ͳ>=ʠ#['-=B#cٓ qJs`;XzP#7Ӑ鏟ꐨr <2?œՔ%PE Oj6~&`q)ܟs ܫc_3 3g"_]mZɽdV9$PAqd :OocQַ"(P> 1؅؎wfx`2̶dr!1.@KŬљQ';Ma"E@Z8 ] Γ-EZf e'˦mʬ{F #I 7PާٽOA7g˜L pn &` v_1i2DfauIJ~^I5nL/|}BjAy F_a3:!/0KD T ._R3}*\iY/ymOO0@Z^X(w M}Ld#"b]tN;\&ҥUZ/{Tz`o\Vhw9mq.rb{_=)FꯏY>MZLfZ qP|[pY+BPkۍ!6;Tz͜T QvxJqoնO|"׻q_ eFneP&vQLɸGѮG3U<}2Kf;Tw)Рt͞x5gNUOn'̻zŔT?exsݬ2o̐\ˆ".!ghc6J"(pZ3takɨ~=b%y޲8bLޞy u ~F5\o罻+k5E=Grz(v֖yE8^uԐ3ߦ0 )QAzF 훢yF١H e)j/}p!>χU12L'O?mFNZ]l˜u4ONUas)!p+xB:.6r )n^MO:)xxrL5`)%gV:e3%;B̂\+!c0UNҔI =<}XǞ>;YPsV -Om${SV+¢=n2Nؔ<'yXEoJsV .TJ9< < P(*K2lk6hebf'z]\!Α%Qz q1N=ƣM+&SV+pSޤoN}n܏رn3/S%VAJ ϟ]{F.YMIUߍ)PC..dx nez%G=Yȷ>W䱬kSBXO}ӻ}fz/pJ8UW'̐OK[|&QTըͬDQ Yud WY3\}ՍV :=PI 06QQjpyoam\)?'궬_4N4Ǐ6wǓ\h ҡd.# p^>x3TL< i"I[~לm5`u8'G褭-*^ 糠) d,VnmM6Cs f8BΐijOgPDz8Ѭ,޻.uMvs.ҙ(=.ۋo[&恏vkE.f;ZxND 'tؒ*ZN@gC> wcu/T8'ʄ/~QerhiVf5Pק!m<쨩yƷvq|FD*$# 7Y$|x{p|^LO <#*ͳl0JTɛrQqM%5Ht lRaMCƖ):Q0G&W2]o@L& `[EojƲ"&]`:+T*moc]n(3~hݥAC5tߧad4L t*FVsHsC^Pg%ũ#]^os. !6 xӚ2=|q?'ÖzsZ.'r/2gϛV3ִ _E1.x) M|G2\!TEVߖr8 *wLRfQG9&WEOۜ g A:֥QM.iQPӐMv8bD+4h{K.~]qύ@^NyUf/ j:h-UO^s6, ekMjoI_-f{g;,(t)G~z+P_ܺM7[o9eF mtR|';^F%ȶ^?(J+sB.m)Mz6-WftvֳIx4SuԇT D}hس@x!rf״9(7P/<1NNa[yD4{ڼ!.bPz>2 ;Ip3X/hYY_˴08@A~* >5ⶊf8;N2u7|ξkGJ°ݦxL lS{k(ra}RP+rpXCc]C3*1o't,e*.w&qU38Zde{5}H+(E&malΒ,0NѯT Zv^\T19/XVHܳw?W/y/"e4z=yBY^t'"Q!3ˣ5,(m+ڣ=+Q@c@53DuLZ>4f2)YK\I VANq#f_ UC<4W,*zv hSW䂫g\& D^קT-Wdywz$ot"(^Xv3~7-t շ."+O܂Wk)וaga30VC42۟ȣ|㑱S^r GfjO_7hO?Cjܼ#͍F>&^w\e^NxB&Q3 Iϧm Gr3|}|#⥟x.֙i@x 3s3*{+;O,20,R!Ba9@5aLp`]e^1%47r3Ў[&2fJw~M>աGMvE5x, ќd8zTns,pP-;  +"/s i=!en6h}ÿrRNǟ'unkV]g/:0CT^Đ# &ꦤ6{ZvH)ȂU8Qɮ;>5ƪgyoL}LXտZxMXlb&4j2eJs &\QNW{}>&U޿n.# Dbb_F ͛F%a{ʶ(NJ|͡ -_i}iVXj3ќZ#WY{&DdRMK{yThٓט<̣cHK*bGЇ#LG +K+r$ նėYK3OsBy,4Y<<,o{m@N&3${Xj X" @F$ 'Z!: MBsZtVeN[;,sUgu;S:N8cճĦZI&e+H1k6r ܔ|}iXi"߰e6`YbLT{P-ܻu"dz܌4\j'O2P,!ZkF1$?9O.7cKÿ$5 =q'lsZzu5g>O*cO( WnCd,Ц`ZXiNlGͫn؄CKOZø9NQ[msdb|X8֧'.q0+N1?U aO{x0% |8ۊ٧ۦVnֹjLT]&LțS rV+WNa##Nx玉mGxJVĂW>frceYT ZH,*J#^!z/v۩eR6au]KFe6; %V2Ed$В5XFTtut|~2x8,yw)yg: Bo:%ѩ tC_).Iދ2:w86$^&3)F8DL1a5Rms[hDȪmݾ.Ǐ)\˴9.kCˆνiG"ܻKu4 9% aJ|1RGZc(*XPi8*-#k gXJǮVmlQ]6` fd hi+BLQp@C%.XfF_An:6E۔ }I"+44ގ免1wٜSg`vL#(/ 1WAiZu-g{8l!KܾE1φO,#HNOx?ˋn2h/ 01m,r7C> 7mGFyHc d$WZ-Iz2oQ5'e"V/v>0; %΀US@_WSI֖$, *2]E'o|͛ dIVM2 Xll9FKtek[^f'B[d +Of1{2bƻS/D*g5_t(6`yBH0Q[{î^]{H:Rm:Ҋhʃd`cy;?867=鞱OK.jOcIrc?pL٨U)~w)2yx2fer7<|_BU^A\s2(bѸ&t0r\기iHeaR+1,谑QJjW%I̱3ALNB)5墝vͯi^d\Qs %L,s-i_R斤~N[z xUW;QquZիՙXH"sܾM[֓/^ؓ蜩*>0/6oEFr)$RB9bb@LCÑsQY&rŰMJc~Jf >:|J+s<ܖ6C?0 ވU֡$WIt`"w6r~;%zyJ%/sy=ܫD1?J4Jz1O)Yl땬g(k (PĔzrFN7}4Zlvz׹sw0Ŗ/̷5z?<;; nB޻֋3›`ƷcuAoĤh@D y"C\[Y'TXn%gune/0ڰ_7YfjHˬwlC!hy֯coO;vѡJ&skK#`$MsEvyOW?Raw;Ӷbz{^yi~}e<-a2P^w9l>sii |돷ߪG/zN{nuށ 2-KݴW'P'/R\#_$O,R!g iD/5Jq"ENNP|jѥcJNZ\d?y :O5[_j\ju杤ro<* ukݛL)ؤGVe nVol`9ʦ,eyءg8D-ɽ"0W+-7evA~1M;@fsDsD28]7,(RN~OdIj/K薇fҫG{qv;YvL>6Դ^(}1Z0raUӅْd g?PNRv?׃ '(͇GaO lb 2ӄ -mz/*GX^' $VC4$&̱̜0ἆd$-hP Y][ |]#2}齬|䑬"V.gPa)}x{VHF<E#0{ŐX6+҉?soϸMa?-ZӰ{6#l屬͇ϵzelqgS}$==6 _;16k.6tZ6j(?{1g7|VΓ=,+(~Cxny6QmDsoP}-^_KAf 6Tp $=,4-/iϟ z zT-B;Gj743٢|9 ~fݬ(Řxx*ddh Ic& Tۢ PKrC! Z[lM+;6Dσ^5zcJO(I^Y;EQB1j3fo_y/Bj͈("&^lS-P> 7=o6h̴(ƮՑdcbM틉r~Q%bRc3bZrpd=n[ﺖH 3m?|?V3cca^LmˆZu /:v*0,P,\1TsVi{4qzw8{Yk@K SOaQdlhE>xO\P  "W*#N7cή]>ֽLgeevn;Qx?G=2T̀%ر%1轗1luJطwgLT SecMS1o7P=qxdXw̠`? -zCnr j в>igFy:Z"_pjy0z؊h,J=ۘ]#%X-5T^{HL8q>XǻM"5N.U75`:Lldh>NMG{3Dyn:9ʊ>X@3)K39-Ra=@?1\vA1n|(:mŝ鏙4Imc.qnc0ׂ٘?%_Gضj|uMIoKUeLeኟVq[Ljk/+fB_ ikM+m(VUTq6J9{O86̘W jܶ6^lFZ2?B &lKU:uYb5-yJ&+߽V[;i/L>5Ze\zeLYboG47w>-Z,V$H~in?_69H^$P"/YE9΅"0O kZ'YX[z_~iN:xx])N4ĨUR 7ԝ&-?altrUfdUrV$}6<3抩a` g8hvԘϡ\P ;٬7BO &6z j"+zE"$l54.!rK{ Sg)rRl,{slo_k؇p4p} Ɯ8 B-EAё\ Ï^aMwº߭}df%](Y0'KMH:DϘ*GSKQUAfce#ޟ.}\<ue1~,wMz$U$y+@5/7}IFlq4dz6ԬϲWuw[Di<>sDlXћz˰1Q>δN&!<̮#} |tY+GVT-)Qo饏 ݰ*ܛuHC:Vj4T3J8ӘfN?.|fod=l&ǥQ5j%BY/_wȺ8_l}Tw#ZbȮ WdspJQA 'V_C6ْ O7s`&V1uoSU~Rj 7eO h: FlF?=gi4NQ.c/QB^;X)“D>E^*E¥ݞL tSs&DY\M$⊒Mtn)K {\n9`dj䂻y 7M\kgbT 9\Y8A8F5Lvyz@Q~ }ݻDYШW=מXuF+PkRe^{.r,^ z}{Y8HU͟u$¨iYy9DFޙwsH|7۩/rSksdZt}~(,®'񠞄mYIZ@6d(eJO;Qs&24ny f^tD΍܉2_,נ'4X^iU ߼I1QUʐֲ vw]fXry7eONo/tH<;Rj8$%ga}ޟ.>N%O1^O$RM@caʙr7_olHE풅xV]q"jM;)=7rUȜu*F=ŰqEvF2I=ga$bASpp+i͝LPfMS2il1Ѵ,Uڽ]02!tPyQW nAàX7ev<|;9 /]H/B!͊"^;L{ˇ>%qf^/A1|ńĆFn2΍w_ rnz!'E `z-`e3(p[Mz!VUk 2<>gpq(]qM G*.ԇz':gȽlA!?z<%K.~F)݀d==|q>3Ҳ={^n5e%\phl0)⬺ex*L`AW,ˈq Fl[SI|u5p%o\teDq_~9jDAWr`Qu-"ue~1붡ues4>n'̈́c)>1}K#"XQ s%hl"A}P'@EFt":3FqNQuf^s:|:|Y t 5t nXSа.ydA6{󃥯> "CNMm0~(3!\#v)Mԓr:#Dg*tSy>^ / aL,ahsJ_δ|\ bK֗") *{9~h/{>.72lmAoЙ%$&v]oۨK~c n'C=J'ՙ{Nj^Oyl Ƥ26ȼF)Wbl~%By6]Ux r }ūWHЌ*z?+ w(d׮f,W @FLjN\+o>O/3(bU쬞I==?" .Κ%mYe _m.pA龹4d*B.h<h`-}vc 9AWGm,4֝Н9se8N~n@c/WoMų8%\!m5۶c29w)i`}0]J XU H*?؀ O?z7\Oa)ʧמq?r,9@:-Y1LkiL F[z|X&%wz[8x4i+_IP fyϱU`e[/j r;Paͺ@J>6t l ~Zn|lB3^QDY}f9cH/mcθ"YDd]LSWO\&'"ao i&&h{̢5޶kP{`c;r%) 5Vn}腜8YWYFzkDK>̜0OY,,MsȋCmgξQhYFf&To6sy}goVpHv1Sl(١]GZm{r;hNc*:B0 NDw|3ee⇋w<sS5ђ5cq{:]fq f8acIW>'=K@Dweg[)?6 g^vC=nյuE_If[Lf Gd˼]5K/}ϓ 4.Z? Ѫ02Ke';ʝQz qfh6֎.xfkQ?9 4rY*hؓFmWDKkQyzw ͽeQl>w}lC8@?ӝ*d9ry7~gR~>}0?oH#u;2mLsJt{el -b/|Qu,LAEiB@ 7RRГْb\n}Je9fDv9aWN8T`^́°lh#X\+Bq<-Sc~'uFy'qԒFWrL;rӹgڰBޮv[>neEVasrKHUׇ.i}(\-qPZ%%&p˜vTD2UlFu6g6gpKeM8I>]8W9ƒ^q/tc6hv^2oOo6,Is.Ob-/ޛaZtCb}y=tNDSv%4'(ZɭQ{c(㈥H)(n͞ ,kX)($0{'o,mIPd7fD&?יUo-Mͮ~h^cx[RND42xS ?{7T>So>]w'yP:Z)Ϝ;3&@ox;s=[,Ҁmm8Ȋ赾#z=E<#_n ݛb=uDkδ>8E~2^%0QXƽI4CwWemD1W Ƅ,W>?4ݪ~c?Cz vs`ᓳH<we+< {e2-{~<>CAZ>J (Y gJsG3Bͯƣ|;=m'}~ ߆Uᛩ9X~3-3j3On\V.R2jFy?:'5O<񧝻E}or)`:\/DžfIn ˆ2'Iu1Ƶ8љvEqK|!ޘ$/Aqy`cDsVDϐo<WXCٶ@{CB3Yh=֓(h\gGȎ]=M.x^<;0>`jP'wvbա!AuMdq~:uŧzb7%t"e|]j`^hE+F`Q#ʾėgi|"{Yy j/O{ :"ˬ'ZoiN X/2CmʖGa2@I$hѣ=m#ʾhbU}Vpk_xO^ցt \37ȉ'tp=) 5ͯM6IEr/{Ys/*hQLRs`n {iaenN3\|xIvUfc}4^t~Op;WEa$/K50B%DƋ pL(޽L5%nQĪb\8BQޕs(7p=u򈇱lޒc#cl )o&Gx{V5o9s"_tRO|hHw$ %)Yb; WG#;h}y!mN"R+h28>x?z&39ℤHB/@;ak۾U SҫS N_>[Css_U]o2_IF_e.OQ5VZgǰ>࿝Me7U7+AoKʅ9nJu.{K4Z'gi\({ͭny~X@iJO`+N 1;9f0&2`F[F$VEHNF`lc CQغasVZ[r3 _dhFKrHkf_n6 Zh^ˀd&6%d,Y{O׉\vu+]_wtVڲ#B0߶\4mtȃr"7g}YɗrR?ԙ`G %kшSqϸ%׷Jhy("Q/π9Bd\md0lec`yzRQ`zzEDo _PuL._[م._Wyܺ+Z#F0kj⯈^|s*v wx#Ț8i*@ L1(6D8ET*Fifa7CYL<> L ,|f{ta}}@[ 7$RX ͯ+:%gzn?C 6{Z5.9z{ۗ :Ncs{cuR@뤲`VIoPM a*krV1iTNS rWy?rWiO9&N9o"nkfoqJ"56L~֤QٍC #  fޫ3}wqViWt$DVTFٱ_M_VL"%9ervyd!_ A(OsW">d쌔f/qxLH{dI1uF?wobcd0n(9s0vN*aO<sk$b]c YyUzwK5Duhfi6喭S,<$iw=z7S5a+Խ spzfxC3 eM5rHViw!>XM g'aN*c|o_Y|7U9c}a7}eg_QNJKdMXnUw\A |%G^M0#) ī`}yՃ&ӹW#UP`U=cؑ+ +?({B#B0e'iK x3[j9~t捂6.5[!H<̵LDp< "tƗ}U>yq,̗]/͠Ny}P <(Aq֒<Eqdc{e~aWۢlнxW6+;C5aiGX/ِ .tv\ 4'rZ/"/Wp%z鵐$3:G{TTVe^F?+jfܙ?S8u+_%ةiNEA>'nAX;mN-PEa֚g0F`" 269n%&N:W㧸g5)ڐd26l׹*~"] $hY>vrj%{%TO>77ɭ T"ɽ|pLտIa▃>U ',шa|+ŧC5yjpGirKԞ[áXj[ezto+;ηƿQXNo p}1N-$і*ח6;w}TXe{}Uܻz_|\J=rp!b.ߨ5>:w滅L +5Hf,;ǩԠ-fiCcfi'qy,Pr%=MJȥNޞh㴥Ɩs/e#w.NzKo"3H.FޞY곳6׹秣es29}d==?(e#&PsP8Jmp/q1>?-#LF0J{]sl)ܻo$r'{OdN|v|vZ< 9*`GOu\pgAp"Ĺa[5v{_HUz2"2*;G/ڻ]$\dbsg}O#KrhԐA-' (Ӵht Y{fچ^N75y'[fyr#jXeoXjY)KGV%Ej|Dfw!@1nH" wk jBɱ6=2pڋI' \կɋ8:v*?=e !'sVZ*(D$225L dqpa+py^jCvS.Z4r !@i15[D Lk (e մ2gjee:J>cOFp]&8px'V[%nPdwgNo4AU&BEBS4{8Wf wAeFgQW!:qSv~;iPr1o8c]g閻} Zثg*5GXNջׇg~K+㋟Oe+uk2'HM)mƥ"sp 5R=d kT͏p|*y* Sˊl1q'U}"8K 9ݢFvB8EaTwZm2}EO' Iۿ/U0L_"ÊJ1[qlsX_Gddq U?@rbcbio-nextgen-1.2.9/tests/data/fusion/input/Test1.nsorted.human.sorted.bam000066400000000000000000206021711415626112400265430ustar00rootroot00000000000000BC]Uێ0M+uh "@ l '1*qTh?1ۅvWۇ8\Ό'$_Ze5!]֎F~R*5vJ>}vOg^@g:kpYVbg{cTxM[{VЧV4+Qb8EQ| K.),)dh,$59z]rR!qw -r<iʀ*FҽtE@>l9+q8(a]%ԝYl#B ̻vjs&S088B %uls}#HI  bzSeVAaYJUȠ8`-%}M\ZI^*}i&LHNB nvt(v> *(3X'ٖSH޴Q+Wdo(nƠ%֠%,\\mS2 Ar2=f `5o:C9^\kGv"x POD_)g>iGʿ5$ۥ5) (&k䮽,^ajZM E{0\n5~{iwx?_+pO"hо=5E+tVv>R9韁m"!mȱ}r\.l_CxR >|2:Nkٚ7[vujbt_$tJJKkwE hp;tp;pۍv'nE.l}Aparg+^]q'j4(xf0d6Ejmm;vk^4qlu;?p,Pe_i`p(롡z`H.sk'~V{,ao7vsnmuw[ cN%9Zk8R,ey x|}I_0}=7̓ވq߮SAvz ll{ωg-O@w9QF댄oֲ=['rQeEj ·,I婂^ 0 t#0%̙0_@!Fs1c(zHeBEo",3AG|ݯ`ڬOpny{N۵P2kz*S?6tgی]my@F8@,+ڢQxV bmBN} ` !\OۨlYCKȎۆ!6:L`+T^;BhڑbO<=}{%]gK3Xrc/ʭxz>B6F"P(BhiI>G9#Q)LSr#dwHD_DIi{^pԶ'&Pމ%(ϕ#fHmX!9Z|i4$@j@`}$ gnM8Y/}~P8;,_om<ɖ %ςWgAVN2n*&}>2KSgO:M!ݛaGA*L=M8GAi˶yMXpn:= `|h5P Ӥ0 ӲCN/  $smo۝L˙ldyvw煐ZTOHJ`ĸΤnWMPTJwʽ[Wŏ8 FPRbEbmw"Pl0ԧVO>  ﮃ%ϻ9,d2ܢtMH>/ 0MDoQo{4A|jAg (F:mҵo3Rc88iAwι8oLG96wxmȇ7!x Do'Z6?RsJtg[P_yo:rW<tP`iY6㒩>Z˻eKJ$sqҤGnM:$YMҤGUJIPsΦDٌ; %nƭVJڠt"̃W.\5 @˽gxRoۮGBS xZ5YTY,ڰdF+XBme(]*;'ܰٮ̒] RrP%o?:|aG6ip$ٱIؼ ᘓ?6`mDdou9!Qf2SwLǂl\7BNi~M{ E?FfR;j87.tԽc 8xiM\pl8n)8POܞc-Ӈ{ ìr|K Ǜ)/U/Utk@ҒMqI <%SyV9ZGst?-A8ʻC)y"o턁BecGR-oA1Lsd⌜;F]z?wȺZu='_YED[& <# Ad 9r0' ίkNwmesb #^o,DԐa(5tNDyA>z?/槍lww9N\ 'dǒSI*om7HY  N!εИ8״2MT8yK|v>p,XESU8(b#jMwj-ص SlA@n*; ֞# m2NN$t-8 cc:PɄ-}f~Wڙ+PF0bN;Q۽6 *ܭY` sˣqV+l7ZrY:pcd%ebddϵ4Mi%sܪpHAYĂ<4H_a2v A.1 Cp|7'|6J `/ D猁W\7p 9Ftw 5I(,{LlRX#g,66 񴬈'p)JU,GLPN7q)X󥻓!Hd,tT6s|1?/>Lo{H m۲E.vsrtӊXoՊN 0d)B_ldM:r^S([ C.@V]i.[ag8=!x!mڻ_& e0shf0G5s6hO)DԶX9+!G9M8]Tո1lɖ G k >3.Ouu[57 2n!}nZ/ik HesN)οo2 9'OY7,a}䄪$Dn5 5HnM[pf\Y{$k]!%g OфgX׺0s~z =! U:f@uu,, b$=oK(Yvf8ţA%Y/"| 36zF|DWv0oO%M1IDpsSضoǴYPH҉AֹAذy|z$tn!e`z cn['q + ~.qQ1%U W_8xV(neHN:mD ~p8So#&Wrb52ccc3gRj(ŝM&P {>qz/u'=>dNEC^x7̦6ӫmK>c #^kDVV멛5\I7[}U)sՊf)*m{_Pw਍/p:]k;8bwIGBMrz_{eq7y1 cDS˅lTEi U$B___"B@bae؋ T92*|פt !RSԹ'?i׮9ʩ +;?k3n)tߢmaN ۅ=pkA/kHoS$ ?{y~ qj8*YA6J,.&#4eToQI/vJ?[\:yH9FfAZsNK4އ=݀/_OiY׸EPep.p>l8wABa_nteb*X+„ e7Rz0Oahie }Vي,\c<:v\O_(NTEܶl1yyI.%< ,)Oyf_s3ّ!^I ti(m&P.9k~"n]uvg“oϼ)\et$IPx΀_ p\k;6x rǔ n{8 mx< `*PCA\DH_R)W \hP:/<%1J&L p\x3n\QI-LhV4Ǵh.2B 4ARGC}NZ^S9?T;5ެ!c~pPEڃIPXrvmDLs`ȋ @vխ<[ ᪳BEg.LV{^%+&!) [F |vGHIUw G*|2yPRbelbc@1ѽo1C 1뚪e%AVB nW d }73OcK@ wy8[ׄ"_a'6 $%%. GYՇ{hah]MjBQݱW2`,Gcxt@8͈G^lӤz@a߅Fh}]A'%0 KDP}/1}.mD6t/v KOs*ndžb{TED2 Q͈ƥfW>#V'HvݺdzӔ|lrv£^/\{": td\l E\R ygBKq>x%4vm MVɁJ+GڅxaB+V5E T\l]b#KuyHTܨm[s-h2󆾰9M#roqW,їdZ0m]gդ]q 8I5!84ã ? A5i5tL8=ֹć7mیJWxs'+E&^h\NrVUAճ?%NIH0֋M  u6}xe }b/5[tu>(^&T$H*$v:ħko@iAo tծ"$eJZv:GiQc(D (9};qڍV+Ke4J\+wQٰ7q8A?ӋGvb:1I4.S0|"O^@vqN.*񁞡C| .c<Ka>ba [g@yIDL ]y?aĩ\˪ճ;#i)IJ== B 2)K%)T4oaBHPaݵ !ss ܜ|Sg9Ј6?4|SO̙9}0BR~MÊvA",=+km9_(@]7˦5n~h~3oPUqc>`syEj[zَUMnSw֛݊&p6,~F;nPZQf i40D+@)D[7&z$^ۂ>ͬT(=: [$Tw@gQ[leMvtT"ç3q%d#ޭ_1› 09FԵo4 zOk@t́Um4iA`a-h6mɇ%Ol's} 8"u+ڸٷMofWikg`" ˏ(\{L\9҆!^NDy 975oǔZ5EL*Sۋ5'$`NMJdm~)1c-}¿4jt$;o&Mz?Dk?>x#R+?Ց$LZ.SmmsP{E#Up$PfӴS|2>sRiQDLDݝ{.½t>]qBKJqEpa̤ ! 0M1V Xl?|[E;8üUD4 1SǾ83<9O]HNg-6yJ޷wO1ivQIHx?+@寝ta0'G IBO?~`3?aV ͫg>Ү#q&>U_=8[USdqPP 4RR U9aZ2iX58Dpz}}c z,Hօz&j}x>'{:6X-C8{Dz~#HxHB7BiYQ)֕H1!sfTF-o} 6FUFL>FOz~8?@!k8uS2)F kČC36gr^g$y  ?K 4y$U"I0h:LR,Ji`(M&Q7RɹN^@ZK*yVgIJ>y8].p^xR4lKBC!͝ eWY{ UZ R,K@n눉s![\T(En "B6d"[$ oAp%PXϹ˻g{wΙ{ޫLz*gW9?m,,W-6 0_ _>z5AA@mo˜˜`,<%;K[hjW[+VvՊ/b{v'ۉ.oiۗڝ=v\ڸ*uPg!΁d ] *q@A.P L> U(; lwIGK&k/NXgsQp7HNIS 4Y4wz@WAӲq|0}WJ 9fyFgo+Nֶ \Xݙc$3L&ko6`\^i; m!R1}(Qԟ9ګN~|0aqft=RX)0)LC7>:@niP6O!iG{=vk/vgo{O7&\Wr/nǭV}E%8{PMhIդ){rH$-Nλq]vu+1S "&-EnvB)}ד7\ۦƆwQCj@;rag5B/qΏ6% jE48- sѠMFM&+Y&=3Qպ[t4"ZUР>4`o%Fz@CM}nysl G5 ~ady 7[kuqgq9Z6 Vs,^`0b8dyн@E{ #V'Q-prblUv}Հ AΚGؚذ`bhPHBM ;o3:M .5ni>ڈ]=?QO ݤȥ5 !o^ -!Qە^!u&vNYĄ2p oF !' @E%xtIs]g ?`>O~0As^ dM`|Α93=-&ki݅ޜa10b`d0nv{2vAդ[$BH"kc$ ԶK`ymuL+!}r@؏aKWd &`B kVꄭw):ipM&<>JЦ8RJ8S5j$V`N>zW3ɷk1z9+* /yTBk<0$W9ą1ic>]\ c)Zҕ Cd+o38z`%#;K|,CAcpD5}) @M>T(MIAo R)!{r :+ȡHAeEZ¾[]YY(&"KZAEH>&v哴bKJ*{ڇtc˧TqEu3,4\INBiɊDzYsM$"qiUh9S;bOV8B-d8!h:+Dv**[ԃXO@}|I@N @)0O~,T- }a y=̈́]"u:&PE8 7)Q]DcTlt~nk[ LȍkEnbhGqX`&"%U}LS/ !iTȆ Lk.Ge&r"Y{ PvI<4  bRv4-kA0¾ q[&@ Pݢb Y#RE %P(H@ӍQB1(U|؛zlkǦ14@CþuiT-ڒCz)(>ER9aBE;0뒁w zbUzn<]l|u3- 4J}I2 ЕL[W9v>"LKoǎԻ@]?u|ܤ HMjpa)#13!"&O;<>cvT2R2fQg[ʜ`h;OMHqP3ӅSGU FM ^G4nX&}c,$pn)UߎQ;:VnZ14]XK&'z;,I>QsiuɼNPlԮҡ/|'b}%Stn%Ώo' ĺ ϩz=8(pWɧE>D|~^+!m)qHRbV 7@Un{$Xa&; p0P8Y h.4! BsF<4o@> T,d$.;8S!!k#>i}8x֬fWvBWf+5…{üe֛m"hv/գ4 iYº4*%97 szu $_r yȝfNӲCL)wӋ|V b0ج0rJm 'HAbݞ:,s Lt .lsŭO0`nWX8`34yǺ)}KZf[br* kxѰeՂE˧/#7' <.T-Zd8vEfp\ޮay[_ (|W/ϧOdSҷ+ vr~4*h|;LhB.BFӬ344s6DU)JKϑ(Tp'BB6sX0(OA@U7K&֧6%lYd֮#}-(cgai̪P(3seQSO6Ovb,,T8x>@֐X3&Y Na 18I:LxvWYjD[O)kWI8YY$E*r+ $bIIDz]o/f֪ 95 8逾D5B$n7 /`>OOyvĽFgXLݼPw{yV&?;%!}];g4)e|uiHwIYފ gYF? t͕wqg/딚XnH`gC@xTE0di)ɜ3kڮ' x`KX)#D7d~mbgQ%d!3 i9/i<*a>گA~4D1L3R,zU& AX%uħMH,Icplԏ` c DT0:*WMıH}dbu$5ɍQ*G*`hM`k`8tfd?=-6>Eit=+wZbaDhqsB2| ?>/U;2TTe>Ayo &;)p4\ 5!]{gi}dizdy~ɋdeK~rP4&{UѬף*,YrIOmFn-P Ø0k]b]@K|,eM?ٚ¶)>D fNhb0Oԓ֬1. Pi 7(jhr͖ZmI1)rg/(AW5(;ЈIϛD%8oյCZP5$ܯhi`ByCg1;EM7mMVLS]l__  },2qLtTXpwܘ^E|8 ;'cq@VsڥSn 0yDJ#1[)\W![ vVM3hvB# D? Ü3*g(aZcWѩdm.jz-UQ)±2 ZDWdM㮚!D;t %MXt2ݴ#c'aVz(%q[Td;rZ9T4Yz 1rb)x+&No3c e*D\`Y?VP FJwLsk ~s~jWkdM̺P t? 0WV X;hJU#&t_QHp6ygMR^: Pi O@aEm utR̷ܛLVeC(Sd k4up <,ДFhrwùT!&Ggs C wh`8fYs 9iunӱsf #9jL3r"zmray({2kV@WQp s06+/#E} t ϗsbEKJo7DJܭh>IS97y3pc)ftriW "l͖\|ͥ S7BA"LeПAKi `ǙrV6vj0(CWP|I/;B!x5 a!3-ELKw򭥈jmZYu($D$a9f|4`ƺd!(jwz%’]YX&Z:,f(髯'kw.d#տRҖ",u ~A C, 5YҴ%">RwEaכtN0,IL'aFHFSo/.od.ľW XқtY49#?>+1ËAB6lk۸f6#/_+i# }oӺ(4<zW\_F0}TDT>iάtCwQGEdiN<9YU!kA@‰RDb4j b#Kh ԗ(H)E@ d6lerw |[ f-.:A5yZ;4%o23= ĥ<"yjK _} }g^%DSN1@Cݩ=/ӄLqj[m()8 n(Σ0j3kxDaO=[$@sf2њ6gުhä7N 2tV7Z6r}sI# '|4GUιdf ##G|> BG4c4e/* &*1<  aY Ai`)45Ro4 ¼s>Eb/vrJs|1$i֙hiRg4*ǀ)xAF$LKϱ5 ъN?8aqJ_ Ip磶0( ?$kjZ^`\ź&ߧ%˻L"Ԟ. Ü/??R4FQ¬ZI p:H{b( $t<:LjIB>_Ͳr߁{̛{ Rl;QC!udG~]*p}1v>pj~Q8>x&߫0GOP 4[V$kj-T9M~K\#'GKR:Oaڎ?3IFj_n?0X[}8gӒh}MJQ]_f$<)vfQ:YpDzd IT~8!Vkw_(r"HG+U#:NT>A1ZeU7 W),tc>iST@4xK@&}J5sàC>  ~`"-x1 wޫM_oA5{Z:ݹs!δu*Mfʲb% D07 w_C~Fi71r\m)/,"?/M͏M<^0&jZb:N0LsO6piY`-Io'X[(kkE@H:6K/:>r}DUS!n&۲iذs;VOJJM7]}8̒EE, * eDS&) h ͪUiET5`g`,p.+t'L,k:5SɈ\ӗԚJ:thdBG1sg`\t,oElg o尪ZnZc$E ,ө3"JU91Xv]H!eE#oF(y xGQ.e 6C=ӑ  KývUR _31Em:T]{w')ҋ%gNN^f"aVgpaǠRs-nW:cU<(R9/ir*IΟ_4ª-!d?G*c5BVemlIFӆ`:1FԉK é{" A՝yA" š[hk42M`bU@M D<)RmШoɤ»;ڱ}_5?E֟S3\c^\',n/OsD?(-g na/.K6,$_c% /N(=0)o1t! !-h\4q$B:Xsڊ8ruZt~ ÿ @A6#fiq8eyBkSqh66m`9uT] 鯙) hla(- 2?TP[1yINĴJ>f} SD@;s9ErKn7 R-kc,d=Tmu5wGpCh+ *7ڝZ? .% }D=]nъk0=M8dbz*K,S4Ȗ>rӎhYn;K;hHVie*^=hb45nen4gmf]T贇M.B4d=w|Ͼ#H$!O !BNUwuwkf;y-Y,%>_\^:Q~xx`_\zn.`l{&?N}+KKoj6[Fll7fg{lwz޵^P`ڰ(7?n׻۽q#:/wzKhuKHwⵏVEB)OK^ay3-̳VǶ€༼p.8v."3t#4};2%8k*ؐt wm jY\wBmZ:X}+B>OS-/3moQ amb:א{n7]w0Lt^=;q1nܗ"0@.EROgjTfP{ S^mow׎vVwV;V kv3,?P9B૷ <_kVRjm #ț'KA6^+=`*훝aB 6܅>Q'D\vf, "b}%:C}=Z ٛ5cgRsr,9<]=}9pjÔ:p`@ 'dz8(uRl҃4>(bZQD;zW<_k7Wk<>>KݡCofB*s +oWj8?Y +J-6^{Mll5cʖ9Hq]:^5<.7"; tP殔lsou"hndY<pH ZWl9@o=44=78{4r=sG%m; JStM\Ul4kfi )}\ܩwr MZ4ZvQo1~v"tE͎Rjx yawuSp> |?Ya )TC@l΃Oҿ࿢ V8c`{j3 ;}5@plyn HNQԳ=7MEv tz ٔr)2cnѠAs iQq@*>"ʡn׀-N;.X.АgS'd 4ki@ a \+^%  qtL(Kp]ZQ:G*N?qtr=̟jfibǟ@a h%40h)ν:S QJRs vj^4ᫍ5 Mm9! ܟU@ɿϛ9{mɿn$i)dG'!3 v="`ѫ̷9֭U?], ;zK !m5m@Hヺ]IԹx5Nfj3"$U}^kk =c .f$8hAZ(``B(B{ +[.㵩/X<^ 'wt,xفkՠq! gr6^%F O[Dc$ " m!]OzނUx{;^PEǍrm9фec"}]ެ]6`}g $"kfgAB͔j~O%|9߭r>qO_t]ҸтG/*+]"_4OS: *$pBaOh8׎O&OÐIJg >ל0Kp2,f,N(}аq;46M?p#vJ CpR,juZ&e!{YB5NܡD`PA2v$urlSe ݽiF"v;2|~$b2%MRBZş ⳋ#Qٺ6NDŽu@`C/iD{(!9V+ۗi;JܹU};0T>.-a%Es6v$㵇&KQ-J*͕[> +twx'sZeGs B e.gw! y6 ȬYz,6wFIݔ:l5$#p"[%SQt18NSeN8VCDI4(yݠ-.#$1X*!4`ŝ=Ui Ďoⵟ׀q'wа)ni^ڬ` jMchG=Qkߋ~Wu-Ci0)Қ,ȋdKQ]c䈲NFXҁ=X)RBgh){8%MR'' 40R$G%cS-pf& 1ov߶BoUhY G$9nimJzV`d1kkH.:gY~\74&І%{(Oi@;m$k4"ylBd߬$JSvXi!HU3^f/E+ܘX^;AdzdM*NBjF4b s pd/gqlj הScq Ē'܈w& @ m|SN;nO!ج%h5?kﭚ̉@`bQ mVFӇ80tAmxފDdq 7ɉ)A 'dD.B ̻G1 m^!vmv!s{Ps+ !%dέ\n٠ɜ'8s&# \YCL=,v+V׳pфfMlAϺ (s(m7!qUarv18,gB-@8KHt IB $^{q^ۘ)PgQ;G*Y- ŮWy[;J~;th|ΐL>uiHua4ۓ%Bz_M/>vF]QZ Ds(1h׀j$gEeX\. sNޑ7ÞHxdː2=V\@9y(_m9 gGq6v1FM8D!;/=P5˺s4Cgmdͣ&CgODBNiM 7H٩DTȟ;ܫFxl+ QIE1vjB:b%֍oq:avq4e[g4~XͺHKsR'PA。Gc[P"zS[f ѣ~XRIFnuœFt&#S򗛡֖j1ش."=p; my; \)aLouHiQ3{DqϺ-iJҌG>dH>] 8M1A(zX'Aŋdž{HǸ#:vZ'3TJvNQ]шtPuNg`oIy?'_7O j/ `e%PliW@:w_Ac HDs)4$t%0xɘ M>biW:Ey(XVW!Ij}2ƿ%Ge:ݮ?DpriazN15T>5*4+[e0djrgsl8,QΗ篗?Hc :oahxmA)4s0Sdh[0Ӏq.aY#ZuiV⛲ d}%LA񗔀L{D- si<"tiv1i CDK?.~|5+"2Us¥f ]h9?Q)u$~@*VM8s72障Υ \g╕EHG~4?VsWyIe0ם[LhL'?]v&/>y;>o34Z ug&FM5J [* SM6ΠA(i(/j݄]bһ ~Qp8b`Zs0[l-4^eat'rJ@?R Z;0YˉꇶP*=?1ōBJ΂+pr4"{;kwJ8M7<"#wj+|g<ّ L+|:ohUǓxF5ăFT~[|uDُTIUēzg:t́Sw/W ms%Mh֍$ނ‹*OX9L@BSv`ә `4*%}6:u0Gc O1\` x4Xx:rE Og%ͺ% I<KqE!Ƚi^19==&ѩ D6}s^J"eIU`?s|ރ&p1 $.$A++r&AN$NT% 4X®]p>6 g0a@6@}[|YRs.yW EƉV^B H,#"s9o \@&Pˏ'"WxLWtnmmŏ !2WB]a# $"UX:NH@.Oop.].f4.ߡS!=_$*+ e :KR@y`jD wrO(,Sxڪq&L &szst-{ E Ii[=q)*RG:8|=έz !O= EҊNjǁ7s i6BK%<:5mkߚ</H1o=ixrD픨iBBq$aO/)E9 W " 01u~ǽz@j(UVc!{*>T= ͦ0#˞+[;?`hnSrOWM pyڡPE0 />` ۷^^?;m yЖ/XQF"gUL㵏U ##@c<7r#xSUi|IBp>O4Hn&bO.k\dLA٥է90َ:pNq`9R YwJj&y~>h8aL h:hb`?Nxb>&P@+BjlΗ䳻_zcá\&gRے8(DŒU? IIMEC?Acg* Sbd^M8  Has7_Y>-C >I.AkC  "lUD4³@hٺ>i|R4Yus"$4\fĬR}f1m 鬧s fW=qtg"?.hLunYx49d,51!IY|Dk:A,"v @u.aQ9R("< v%P;r y %Dt'{ Qcma+8^(qU>Ǒ eC-9)Fj"Vnf=?_`(pVDOojh$j&DdPjO%bWh,cVlsm5V'\yjU|$TB k^m@\E&O$r0> 4>2u..fŔ9@Q7zn?K WYe htۃ- w<`p!yʾ]S%v|DDo`;,;RI~V?ӷU8ohhtx94k㨋4O9c[Ձ#UlgYBbK -i}UU 7n#ȵyCe;^ͭs^%^*yVQ^{Eb2?q:8v~BC!͝{eWY)(x{=X:3=SFCSڙԨRȽ^…RH)R"DD,v:δe $(DDR{{߽fspL5d[[k}߉ë++{澕 dk"kBo8A=w8>GG_GAs0ڃH`/s{^=t^@~wátߡ}70]ya$c/Ox9X9[]v #GSR%0Hϑ~YAv b0 ¥h89_BcKQ$60d@4j ')ԑ9_"t:"cL"j>@"Ў9.Y{ÓO>Y IuA|^s||w{sM;/_wvN۽c˝,y=Y{cE$Q!Vm*%,27{*K\ J8>gYDE&2L6*#'uq!}}"u0 )&uM`UuPVבg4k;kfcnnZۍNmu Dh0:Wz^lD Aof@[s%PP>?U)[~ۂ'̊cÕQAH2S6Pg(4}:;-i:S MxdDMS L21PLⶣf[QPvm?v N3}n,b Ag,r]QNۍ+(ԃqOnlt7Y{SE /Nv&P>R IzY{[U ܏,1'4dSUш+KV ];SuU[@_ :@<0RV;(HPf(bQ5Ev S1Jf\} 3L< k-xP(v1$)S=H}Ir`ahl4?:Pi5]¬GQvܤ Ȃ(Pnɧ8|1S psKoUՊ3K^mt&cc'̓#l=Ƹq(rۢYWрyRhF5B{nUցq$Ϗs+ 7Za#ݤ!avdaE2~pټ +F&z8t! A:]d/6m70KnegH?n"$[g8KѝSdoD `45.\ 0ajLI؃^x>v`L$~DS6:[FDmôdn)Ɲ6:ڵ<)nHGO/hC~݂EE'˺L<4g@[.pvN _2$١`83QS?a\U;@#L x):f<@q&WlWL@-Kip.Э1z`x[mձhCo2~Oр읚y}yl80U!qùp+ "ڇ!•ʒ?PTD[Q}Irا- 9K>R^)Y=p r(VC@伍)^C+"aù^ RhChd4K4[h.h0\4K0 YSYk쬷6j<>"OKq˙S6|Ƶ!eɬ+Ue'[؂' }tI@"H>Rܭh&KNXЄ`Q6f4g 4gmLB qJŊnA—qڐ&A<aZZe]zv>NoMMT!,ݧpًUǠ5I<7-B_89=zӌb)̢H4П$:Z((L%LHL@a*)=)Œ-w5-`rZL#1md@rv= S@ÿGO F,p(mPS^sx748~ #s, L$u 75&eU BЫɷ|Ɨ'm Csvk|~~bW+ḻ-#>`Vi޵q~:ߺ;.htvܦyqqG^(΀$; @[ 7 rz bH%k署$1K:Z ,#Wڜшib4AK)39 1P3u T\=ߓW}(W, m9Sb%EHJt&R9NoX̹s671 N+҂ Y0Al@,9dg$+8)Kdv @yw?b4WYSP&0/F/XЬmH@R &CxV3zPIt!ч R PsM1~] B”SMHm:"J_cue,g4ʛ! B34j[I%kAa!T7]esccXy6h%P摝5$;mY8KQn[s$ŲvBÑ[*_]FsAs}\?d.+Yq+9P$ʤm귒Tuy{T|[T8# g=#ሷ:5l\a/.vQܞ^_@J<0`ezQcfKbWpV=N$d6arhJne'`%zb$UuM=%ŚBr2nJ`r,Yl+Y4ZDdz؃ss.DQ+) -x|9{5i8ƁViK}vO   ֿ}0J^ɏ6PR>ݮygR:{0Q$}\8Oy@q"y.N|f%jLSY(O 1{"x Wvpǧ==ńJwꇇ<|-h@ Ig⡥ &ٞKOmpBٺP<EJg2m1W @Tb]a{i+oQ:P-`Č ;dU:PdUf&ؔZGtK+n4#ke#wU:I^󢒳y}j2g'f `&MnqǮ7Y# p5y"%oz"ĀC {Eҽf]0lB45ƀ =,H*3$`D[C (ܪ; 58(P5+ g>Bb]?&l֔''Rv^hMH{%h=`Ҙ&Tl Th7PtTY|q&ˑNWJaщRh[@64U:k(sFwZ!e|D\*M"z+B. G 2U7u>8ͮIý|ΣHD#91P< <#zbǢʗj=,7u&?P\7 f,;\Ep@]q|*ճN# sUV{P-y^l]5V}ϛPP&].[Wv¬ZxGm,E־civ\1ïZkpbΦ+|^c 6Rv36%=e96ЉtsCs%oQr%3,'f{ͻP?B%o6]QdU-]̦28xBLk?s ͪxjPcm7҇q&yg,Bh^v]$R±9Vf8l9=s`bM5!yF7?J#Ne;6PSٙѬz4d8Ufӳl1=hĮ*ĉ2s c L@rMhSEj4m+'+,f]>l'V-:GTI8W*PGKYiyJ,2z"d `igDY bQMHi9r`o E5紥6G}~z@ +m\&5'@9ab:=t+lxA%L}z&z}udlh:NLw2z XslsQl-4]tt|h{,hU;Kn5ћmvb&_Y'P}+@k +F&'54>ftn+IJ_LJJ/HI{8@Ji3E) /Yt{<v]C~ب͓%YA "86 ó>;mVg~&@S9} 'Nǰ[?]PXӬbqm87ϗ|Ϧ* liD8dP3?ݚ4>{S{T+Qu(/IUIlwry̐m_c-Dyh~EZږM[?M #hP0yp UgffxBp^RKЗ y춑4ζIQvY{wU }AF@g{9m7qX?-ۭ &_|}}*O(0[{kgGO8h59k4R%dzi1C[!LU& w$gZn $o"(yȗ)ku9?zXvcpS9g'q`K77ڿ.Hțvٛ>q0Yb'x(`S \ 1U%A ׹`BV&^`v[aA N _j7J ,Ѭuvʀ-Y(oY@JSkǓqOF[ۅcA 9Z-KrqtwDߢSΐO(hˁxab rz+{= +E0d=Qu+p1*2V!0yr<.-PknV#^Uʝu<&6 .v¶UMrf Z'i e "DJsaYaAnѷ²8Im;CG5ynGZ;x\}߬LۍI_S>>)kTWtcb=.n5]ԳfaU}pMMOnW`Lh,ۼF]|a}qpՇ]<1<+ޒi{md4`4CgTOw)x#l%ˆHn p豃6䁰ۘ0[ &ؙcY@l9 4LH kb )}d;F2xI'~0qrwv^VΓ<7$.Պ$v-$QLҹlQ+}@jR+ @q^]oַFÞ2Z? %ƞs'W' (ƽz}IB R Xn$Ij5I2gɗF.\Fd{WmHh R2@LS #_r +"^XX&#i @)jz.~pK>gAYZEx<`7=];r5vv dSqcv?֞+UE}#W(d} L1qCWϔ@ )40k#XTg-FU5S^ $LAfYN4y!ǚ"Hf8B{&,.y4h媿I~-Wg\8@؇JI4!mSu1 "p0e7NM+R3$#ʘ3љ70AILc51mo8tH6iMЃ"͞a`0HM(0^njZEJ e8:sD{QEspȀ6ܻ+nΓڸ@t6Bå(n$;ȗNsS_?hZZ7 Y{RMMgo=tƦA @[{:V8n2;vk+A_Y]^][wvW;~ߏC肃dćd08wp?HIN.0>p_.vV_׃kssR 5h-O? R 8Jz ރɠ} 948?7JňAtCwh0~q| rK|nv"-B~֬uK@p1 .ƸW8VcMU.0q}Fk5=,zc}( &Œ \\+)s W|>kqvt!0e$cڔdp~ :E.AKYh1 (D"""Z>O} h[iK<_ +ΡܫCW'i4Qc|JP'+TL!Y5/o^ʃōC=}+P6eMRcyWG}1nE)'J.N]q(cu>=ll]Xǃ4Ra ?R sd8"29b8=l1J!\njA÷s[ yH7O}zҞ5:% 786p1U?J#ׄ%R~q|Td4ZsŦp ? ZF.;5X}45ݟNaO4T6,Il:N!u* }ϊIԻI[>Aw4^‰)ua%LIa]H v:XNbs5Gu6ҸD `m,fk/c 2g\vvLഌ0 Q u)Oi@\3 E=]!e 7A_E Hdf4`h4Ǫg凇lCm6 Ղvjʰ&A[T!ggN%ַS'RD-=tri.k ,yn۸suuk\ F\e ]A't Ip?&(u1:x~!CQj] F:̙f8/=yД%}gD`A;LrE^du\.l%yf` %B3+r :@h$OgCW N&ǼWdž{z >jנqI$4h̪A.-›l7[08&c [ˁw%"~XrF؛4a *bѴ^'&ZU**{B#d46FR&E4+V ָ0 ,pʡ8!=Up;7_.+I CVszNɽR1zKj|?B#>yLI,nȆX0ryurXU?Xf2(:M.ЏiR0lz k aW'rFB &2 {ږ7Yʉ)2|۵CާWn.bJڄ~ }kԑvQ,D@W* KH evijFvD 9sޭٴ &AkhM48h8Ǐ!+S<; 3 ΂ɑv3n.^ ,/NVt>t뭂hJuK.Uz@|<24njJ'nN4Z;y-({%Z|T@~ F0m'>Z4 8IxN >a p7&|á/1NF8WYjؚVq 8[f徆nVUmMB?l$?U&B,֊ݎgd9 Y[4Y{UDgΫDM#Zj-<. kd䰔µ9,:G@RxD8YH.tb8YTunhWx>%]ͽK!F5xJ1SV]A GĴ ǼI@.Y*,[C`4uʆߢCQd04;wd̎JnN: qtv1ÕJϾqH'8 7So H%1n@̸{"/"}έ:HU1/rF]ުX0MiSܬmKhF'q ƅ# #\۶NJ%hR[ ǧB\BB$$hpik=z9Tg9ҵkACފ3duIlUqti[oχNj".yBkԱi[HRV6[lxٝx6CS6(E߭J ?[x5'ј}&Nm۴S+`1t-7H<6>lָgHn*z܆W!/E3Gy!_3~?F%Jdz 9:L. Zo5Wc BhL6З\Ac!O30GMH&Ɖ. Wtz-hEM_O ɻs|&p4VsCgTDYwz ḅFz@I)nfi9b.wZvk:]l<}+Өd{jo߭|nAbUJrpJmс`JފA3$0ܘL9eۉ/U傐wN zeTnϢUB (S໔ E^*FDd2rVކG8dQԸR@_(u-`!!陷p!q=ĝDk_RMa Jm(ڕNGu{Dwڢp6tr X_d`:ƕ-vpS^p'vJ=Z.10UlWv3`ʬS:8=&cd0adA?Nrɬ 'j.lbUlZɃ/9[6-D֭$ikLD0^^W,hٜY%4>) WnRXhJK4h 2 <`W,1jv[leo-2yI m4)Nϴpdv eF 6! :d З|]&`ÜxH`Vpdێپ4_TsPS QE,yL~@(o9pXBsN|B'4pRw;xP,Rr܄: ݦSTRLD\[AevFbɂ>{rO:5IB;9ȇNUp`b8t1ܲKtR?mxb! 5il#qAԑU.8;\)A>%~yNXH%5jgpg T_CsͩGK[}`l̛L玢WŦ>XsfxU:>OS{6@fپ\hJ}h&[w%:1SV!Rue(Ll.r^i+_"]W}@iiIY5E&ϵէgxtz`|ݦs! } (B^z3FCz:ߡ^٢aqL]+xD|ݮj`"tRxj}"(xs`՛hy=jv͊geD.FLBVwܧUK@4k͊%6$ީ8F&5^" r[@CuPaCZ2ǒFkqKAEނ&MpEQĩNJQd?8>L~:dF! ^,Mlm@7Nɳt 98[p#ͮTȘot簏lbEGtoyNQSWtxꦨ\gh퍪g+ufnI]mwŘHV.Xp~rY|}oXJc^V'cYG,&&f'\4' q8hL6'L7aurab[S`,6eY'uLW32p}FNaL"Fvɴjs+qşH%E/ّ֠ r35Ue//D&`+.2CC.A(?_eHAsT)䦔YX2* zANl&G]XQ:;O׸B.X:-0@90aK*c7U1` # M{4.[R}7-[ X6&{gB&}t=vюs$UK\;}Ւ3v)AUsy꜅R<D D0'IQ@+涑C'/huxJ"5"Іe0OB@4s8WܮS, l(paĞ'$لo[T{lA2pօw8CwϨҸTn$[dYdۆ#N(X舒(s@GI!Ŧ%M)$طu^x8I T2%j9=WiL G5}eg~wj8-xR=hA݈<-^tScm`҈n)yot?@H2QVCӐ(Faj/ĩA'atE\84CZJG5 siPj[ ų3_YjKITxV}[vXB# ٻVi'ˌvT盧T[=N-5: nyqB T>2-q[eLBZ<=O+ψvI3-pq|ةdQv~ Xk!S4 gSbz  Lq9 kϟDv7kTfG+ "WSmMّ7!s|ȫ;b- 9ࠂ'>dx "T}[ wriwbDߐwe1z8?XPf4òilFf6hM8ш*v4E ۍ,$N=8!)(U[#YV zP0P1tcApI0*옔t7r`ɄlCM4W*=tpUz K|AJ-ge_S4OvҔܨ8=#8%ѥm#ܑ{{wZ)m#DnWD@)/٣ )yHJlI}iJ1l![NJ\&|j#}jd)Yh<,  % S ɾ7$QQJ-PK`y I>Ϝ~sLH%Ώ믿W}JwVWV.|殕+Okk=/L_}apC琓"g#qk5ktzgmhvz^{Qӹ(Mzޥxϥ{/xot:%].Kv]dYݫ`%ޟxn/+Օ+m QA++Jf{v s ҵs S_MA'HH JVIjm8T8MC)UsU|Uep3q24p\=8Qen2-ÊnN0km"7^Gx?9&ɥMOy sf@$l*B1orT.O%T]59QmۍHuC͋SIMħA@R[Ljd{Ĝ=xv1`X >Dlt1FnufƾZT$a)W:= 5&DSS h>Pa&3 tl@. X4:pGMH> _2*҄G.o]sj~G'&1~^{#QùB^0gߛeWrC>.RqF'[҉{P)1fD4l@YJF~o1vn*Ҥsgt㵛uaVf3iwN1k&lIgt:I8:Be4۴%#BP1TwwOB2p֒{sϮp~DN!tĚϐ&Ht$Ctx%kPw tC}آU(L J@Z@5vASV >RZ "'}b8\zh͚rD[8An(TPTH_3Brw ͳTX85MpBh&5NFB0Ί:Fc"@`:bʄT?Fr#6cDFjݮ4tTrk+LwqZnrimҤnj#~OQ,^{&I @AAx>2Ru=U򸬅 ;X8Kvu D|$@F`,fE-vn5ct&M38Lq`"-G6úNiN[U;GkKNNsNa3=1 eQ]Ӓ6hX: M]lZIӋ0^?H93Q3QsQ6T@}s(i]c0[ yօ%!wN AGș\sm#% dA)R]?&L]hʩk4r㉎WH"11!BR. p/y ˷_‘SnlÛv/=Ujj;Ku7a=(T,}Cxm[W2@a4^2|4k7z'hkҤ}N P,4ƞжO$ؽUȧaM>Y;}OVʿݤUcZˀ.K*ON\BQ,NC'U+6L8Ӄ&J/k) iX]l[i·nY!J/ԹqdEE3i\^^vi! Ƕ0<3L`)a(CpH8p,C59~+t)[^h❹!Zv|h`uxm "zoL\O8h# 92q/y?vhY>`; z6덈 65'pK>iz=u}Kp'״ _(,So o6HzgX ctz"]" Ұɒu$ˆО[JQlBds"*p'IwKړ nOzB8^5J! )q֔ !-R&MP:.nnS@MuCڊ v cr!6@ wX﷬;d <{S[gadvn$'a"ڴp8JS-Ӿ; C0mH* :;NN0.Vҋ6hҋZD;! &])H8<}~[\?Pv?0JM(Pܙz0HxC@*4]bB%6NqWvf鮆")U ah EAq8ZF2m/yP]I' w0\2)G,Fo?4 a€ 4軴o$gVUa },NMpĉK Jpf F檶Ї| !ySg)*%$:1˧G7'Ҵ7)M9sțk+BdH 2A bVጤs9Gߥ~0zcc\Q&@Ȝϒ!e_5ベ"~/Yɣٌmɚlly¡0z?Yd!1rܞCY¬ӂIJ0-"$Q[(9}TI|5gH"OBn EcRitG#vd:.R}SdhD{Qi2$;S28],ax+#4>)J\l՟OWА{ߺC{߁6g)mr&.vAU[#mM«Ka'zGLEhT0(k9v>ArO %dbqޒ#Yxf`21}v꺱Ь H<~I2 |n&<:˳V'C}0x˻@$9Ok%΢r|: r(FZED6! #N&5HsAKFs? =8֖ cHu2p)0(hȗ0!IMˎ Tl=FGxMiqLQكy WXl/Uu+D. R`$d"A|/y _\ei|TG/>W!gUoyPW" pQ%g p=B~$HL'&۰DBh0oQ/b!|u-ΜqZ_tia/{˷%$(8LNBfp}!=WxP,$FȤE jʵ6iq]FmWUH^2#(FCtXk+'a lEsVW?ss"#7'lFz^p4R_FJzW@|xğtԄ !X|5eUKWdR]t_-]!/'t8@MӦ&T*p1b,"gP-1lrv[j;ʼnm⬦+%Oa3riNv,೵I} cwW#,pL&ܧ`R$DTDKB">/ru(PrQU gGO0qSNራ:kZލ#/dvaQ$(@(eɹGiݼ`$E\"_L83ǜ@/y 񇣥UJ&`'`SJ'Ja>Oὑ0,V"k&{u:_D3qG-Uꨇ*<CoqgY_B4}Ғ_T2I_cq}K*#?3(i`02rʱ͙YR5ʍMFAbVD=sunWVU_1< y/}Fzcz= ݅QE[D"H:ռy?\fn/h^\ n OȓS f->ccq,s>`Y-MTr~EzQb Š\,MdYxF2ܰy"(zEtY~O|LdH ~P;BR2uZK\WWA-/2PMDlU5lz% p <ͺuÆdw랲>c3z;qi\ Wgu4c{KAr&0p YdTE $GFa Rr:mNmXF5ycxM,GtQq!7 8; BI@(OD#ҁGN%&Rpx T-5X /< hZNӱtm*oy xKj F70uAgu O"ᏹ΄s#X& FaWljs\OW=ӨM'ryg\ráL:ߣBz.7 yG !X-X䡆*Kwn)SOHr \TIKd@&0X-\Qf;E>v9=:Cž){Pڗ4">A?*ih؛rX" "3'̜;t((݌օCA+OK*;ڇu[7: %DM D^ПY / #Xe*k/ Fѿ)wf0b[E BayS{@JIBf貳 Y+[Pi$18'C1t9`}H)l "ķp)VARJy=>Os,(unzTDkt|*giP"!Rcm7A5I?N鹇Wڻt3ӓ%zvi &4MGJzMu52)- Uugh}A4d)4VA| qڌ6ZS%N3 76 pY2pӶ:ΫO-* {<ħOQ׍>=^tnr,99$:[dpDODD2qehK8+cz#{ -=4_}Oj va""b"a^"Q"QʼnJQz Nwt)4%@ECnIk?s\o8A|>;4G RU*PAxBAHMB*"rȏ# c}<ʬv\F򤯟( eSfnY;F?EF >ɄwlL#*e#E0KƹK)4m=&8~4sdW9R8Kz( .^uN' WN'9X)*#Oo'-Y28ۿkS]AI^\SL>W=1>@Iտ$U 9`HoBͳq뼈OGS'8 9}M'˕m(Y6`.|љU7nVyl\FaluҦ$qHb&w|f05b< z vsHVkHؑd}ȅyy:f6_zˆS hɔMx:xfiWrU+NWٞ6ߓ5p+DTHV$F1I pHcMp" }Rp~%GpNgNgfwAKڛS ?5!bZAZ%H~ašJ7p7`(k^\;?+I0Tḱu!JxDꜘI#IțVhܦ %e+<㵷z΍@s$R_5^ C$ egЦ%YWvn/:d=áj4C#^:OaM,>ʣ|T`j)šZ|}I{q&|R8ydȼg4fM~A.3 '+\rlĊdžֺ *]^*kp .3Y?T:Qxm4s!%&8!?/ 0k&)OHd#$l VέRXʏɇ Wn` u{Qu>5m>LQDA;n K$ Yl!+pgǎӟA1-p~YM [XfCZkM^"P|j4n8.{ bY.,/6a!q;aZlDebV!2%&4r]%S &=uKu%IuaMGCo(+5JQx {FJ\gnҞqMp?SntKVynaro&y;0\<$A%n,/_4kGѬfǕI6&%2$${6*Mq^5hЈ=G Hs9yauHApJ)pqڈ,ELK}%p<'&UuqH pW̹h,PBC$"͝{eIY{}#VH :}{AvA'OA,0lYB̢C3; j1F4JUuzӧԽ$W}Rn|Y}K.AL=xۡ-$? Ncz λ;_$S?]muW7ڭVwwsnw:J۽v{gt-Y?7f~vse!޾gvko߭ J\J??;5y/D &>(6ъ@6&ڏ^B!nPmdBB7IF"QBF>Et1-o B8ac8.i,%xth 7_rҊ&d4sۭp""!l/yy3CCnUl7/(@o2D[j|.TǜlG@ jcs Vԃq]G͘v?x-c L$x+\[a=ܽ10-o9x3n߿UD1qN 8+8k/} Bz5hXq^{e] t͆ es}N~A8k˃ [kQ٦QNR&rp ^{}M mc$Pa]vc!)1ӑ ͅgxm5BO @Sg[?,*g'u-EJLF{iY+ (]n`Ҕ¬62P{gLkG+g6^\m@W;L;uv R"wDNzHhRdNwO9Su@F 9]GFM}.}(|E>- KS#*یmȩ8#.ĨXGEZ)3ֿ҆A΍(ͶFs%2#Wy>^۱ l FpcĭK6@Q8"z "Y@C%AIDk߰ B>}IwJW+l"/i<#JsVwE%j~֌"!14 TG#:g$C(31bݠ`c}b#DՄ6q?f X"w:]:؜POnrߜ O1}u-CӡvB'OR*I.O|h4vNRwaHC r) _Jţ\[; 8 BMeMM6UQ9L!eDNu@^Vb3@Vgr1u\j =|=Ԉ*;WX}$|]Kf!dJW^u o k# Y8A3"M-;<sva~^{  Dz"| =WD8ʣՎq'D4$ߤv#"-4ˣ؄9Mw.r!uM/kcC>(&uG2@ Ғg&5f &ɖxS7."~ [iB$gXֹΦL8t2iiZHBzCM(P(15VKUϙN:y&!݁dAHp8)pR8&+ٹsxFoEh"5CwFz^ P;=7N(\|I~|n4FA*Z%2mJ<[}Y0W޺@p1gnꅥn6O+3r[8\۾lsk6a+n 8i [uaB .gGYsa @Q|]75Gy5q"l#j*¬ d</G|Y#@ I/5m u] žU.%8Hdt%>Ҙ)]>!4'&Aֳ!Jy2њm$~|̭DSF  m5 ygg" І"j  S2ߜbAXw3KM1鸐P~U H/G4)qxU6P(X+Dk)L+3x56L|_мzxV4㦥Wp[\D#!ci Q8X7Er9QrMD輤ah>iv5iѠ?ζcEH8cs o:a!I?2tSn51?(݊+1 N @j}_a mb潉)$\: I- eDA`n D'*<`FjC3P2j$l,mluێv49SVf1Лm*2 `I-8R]nlӼ.M@iPdm704Ǯl:>ioGxJue ]|Xp#p{B7A]nGy⾰ W+҄9{Sqך0Lm]aH:^:OQJ5tBDu%8NBD9\Dk }ԃ 9R!'Nx&Dz rjVжO,' \˺-JMx=ӷO/ی!<N'S6vm#?ʬG4p"c%('#W]U@8]E& TPF@z unx>Pnh4zSi ^ M"Djo٦Lƒi&mМ39 okdE%i^aYEޫm.dzADq{ {1IgȮ)nså#ϊyͬX#n0sf6QٕBc:ɳ+3=j+U@:z׃uuG#p;:1G66FtsԴmOcuYb]2)XM{TQp䥗?z%2<0fUX gp ]="3</G8o!힅ZzRxΪHX ߞ۝{V $\ejY)Y)z;IK"-gEԍ]v^mX2,2Z46!¯4sO(mD.Y zY"i85MP#!8zI^;l CHEx %FEs!8'Ы0R6H/p6A݂^arAnmO3^մ^oȏ1{򥤟!S>s6SgΊRR7RfC/iȚ-;HRR6ֽ=`|\lt|#}} c!\(]fvtK]/y+ q䠚 ]ލi>mU4 ߛysAԛi(uwG?'2MmsL$6ϽLJD~YD=cE"2EVS)z)Iध~떎CdmPx1+2sak#dڎph!dcSFأ&8Ty&!bm00e@'Z@sOϔ$?T?U*&:oHL/" &[Eઙ{P A]de`N',ՙ]aǽ^ea$_{`-Qe0'/^ХЈ) 4 "* )̰>UH&u܂‰QFNdDW*xlB>6- v^e> Nk]J-"'Gl^FZmȬs3r0"sun1WWmz͙FL)+@S(*hͺS'?Ym~]k,h_9`iMVOR t3wR:j_<[)4l7ӡF@ZR'<>滈 -H9) <T5\m8Ȼ6<Bp5'Z@((D넨8BvѢu^lBi.YL}95CI/Ix$2I'R$^ ^ȘLb")mX4awaMC=%Ш-}^9j9fT8cF~M/^o/FѼ&ь(섍5Ѭ4ɓYyT/d2xo1S5[&8rP:Tl8Vh;A lC:4RM)s/e cEb,?H*,8S18`rxFT/#y2SH/jۇUmђ.J^i֙̊v y+3;)v.%s^NUt;HfZgL}8\?m#7ȡf/RY,15V!89^9bTVOzOc""QoE$z&,r=bJD+x-ɐ=f}΀JAIxm˂upj$r#&n#wIpSڝ68ГRIrtoC'R2 _I6dwq L_Jpjr 'B)hT(2]Drjxzc镚&}b2 gO3qUH NÅ!IȜM"LŘz[Ex~+~@SX7&൯X5$N_6-!QX}8NvΊJOCqx&Դ5~Eq %0a 7pua" tpw^9ԄFi9ajF=LHߴ&3b( [@z Nwui@)?isV #Hb꿭FBNAY ͍hCI"AF$wyܩހi𞀋m2}WpHO>ah8Uh"z產<3Rb̭~ ? m1J7 'oJ2Ng_.EʼG""ڦ~Ga0 h5L ,Hz^Xמe u`VSy*FRBC ֵ7mzg.Ã?Z2Lb+^87"Z`ַLH5JK+^^ҸUD\KmfṴ%愰hS'a"( 9h\QWndfi޻V`N.pklj>^R!wjo"IM-&˪ ?9Vu(YP|2 1D0 r!T6Yi1xG:?B K(8ZWpjOd+((Ю<4oVm#[Vi@Ȳֆ6s4?lIdssƍiν|x֭$M(J7 ` v lZxNwG>?מkE#.@Y$gm:,By;68I,_lJS֘VIg w}‚ ju뻴P~{;} .-O58jij@'rl.f-MŊuBbk62YKm֫SH~f94. fIkx|3SP\c~4y Gvm :Ȅ6šI+/M2%xN@RVRY4u@I>K8PKWx ZH2{2QR <}5VlBʹV..'Zsu9vך k-LbRR,G46dE9ښcBCQ!͝{GUgJ(dL8cY3q|\l} aEHPH@Db$"A1&M)(-PKQ2v~&[MM_>}ɹO6~g/ۘ]ss/yoOn޷_(ywQtyAv.'\]l-,,,trk{{)^X;ėnsytu.o퍻N W}Nt.k?g\sFv_Z0` 0MD,)zͪDssxS%404i|>݁,lY! cҵS%ScD r 8# !*b@@whEay֢q4 Ϳb5inT>9W犑+#NN0]Hfǹ-@@dm::xhudqev ʑVNjw:.lǝ+0G{_7ۺkucҮ+A؆ZDͩ D?׮0 N -%k@ue"nB;hŞHʩDMLPq@+feĕ bz$$|j$7r GW!% Q{3^'OUo2K6À1r[UI^ /2k5`Bړfⵯx?@8-8qU0vi crX{n(ԋY7'0\rxqh s?Q|#ݮ||j;>g*N☢#l*kǵ=mH-e;*`uAbIFnA"m#<.5bU9vX\\Y;XB~ϋMtt -(N2 XS:`RFwՐTCOg&8@ȁk$ðQk4qCN:?qkΉkV#.L6tbŪ4n ܁׾d#i@< PgJ@U,M|㖊 #pX@InO'&B1aiM6J.1tid@'\ɋMHB>KZ2P҈1uiBF.GHK44Kc ܈9*AbXq8lMB%/F~vct܏Ƕ<6 ?v w\;5$M&qcrP;wi>tMa`^4s ;dyПrP1>(\0T &{\IĝF%|T M;>)AS mT`jX7 L۶46P+hbOQ5b9PPr*5ȩﴽ.@7yW6lYh6,a d]Eg憹 0OkiWx2БK(4GCsȸq^a0S/ 8at 1ek6ty+KQ'eŪ(( RZHLnx9eY?!DKT颂k3rҏA]06/9=oKnhxo q*$9Y|u]eCwŖHq>"3wNw8pZeZRkVTs:?% Gr(*-( fD+xvMnAr$ۅud-LPlk7`B_5ʢfmhr{'^ˈ&> 8iXC7!P*;>iBŽ`HraJL iPia'E=Rӽx8 9`dvҊ).SeKS$0_j:ɹ^T8g=Mb*jDE]+-2Q!Jd0ISYQ p JYhl'9Y 2KA r˜ХVnmkIvQ H׮7⋍ Z9j7|ז<͊E(*72g=G)%{?Z ł#n?Gse:g* I(0 u]Ɍ[=MTWMW! ztApBiލT2̢&w6/i8ä )G(ZX;RiHDI>FܜY÷jV7rZp1#EL2iGe4h;qH>S'ة~(#Nd(Ӵ'RA×ZCg*W+E"y6$D%u%OTJDUh$_YkDLEd O1]{LS&&4P|?-2kd ѓZv Gr0O8Uڛpfȫt x8 /dSd$\p8;*{ }߄ >S lX ٶ' ovF@(LEޯ%*WynłHݔ[r*ñ@V6 B#:+ & WURDgeK/?Hx6Qל0 s,E*n8 +B#mѰoLYfk]AT&:]W}נRxD@P7jQbmC#/Q);lD÷|dVTlnk7t y颀iYIb:G(nk1WhC^oi(-vI'أ [ ɟL GYg"QjE&rIU_;^$g)"p0tnm.x GQʩz3N;b+MILlʻ ]_rR1h Yʍ@ ۮ dLꄩ^II<{S %"Rny!LVݎ|!C]-m(zxΤI(jˢpҞ6]G]FƊ(:rkSbX0 *Sr>bb8YFޖpZ&a8ZPaţ-{QW=[*=ur,RgUkiլ> mЋk%D/k&DwcB< YRlUI9&oA79Rg+$ iO#0-9Y E, xmN*- F^( ;DDuNv By\Vq-8rqa <Bo4X hN 'M1 w9 ZhgOGY樮24B4^; ٘A廔ci{܈avOme³mK@Ծ1Y+z{4 (Cw0p380iӰj߱FUQkD@G9{ >Q=FNN׫ԍtM: 4yt4}<]RKFw]FY{pV%P=KCqk?k C|W0$o>^ BqCb[@i_,V/4 f YAG!-^{ N@$),8k=Gx2g# Ww`$da>JGBXkBBX//Ip_Ιcpsi^K\,Zh68ye&Xn)ỒIP(D|`ɳyxo0Ig1kQs Rbx*G9KP{F.&y2f%$tAV *?y] H΂%1D34]25aUi9 %hCWxgm)"UxUF D'tE(%LU\0yN`©E5R>51rb8O[Lpg/5-1DԲWk$C/億B.#7G2ʚ"ۍn途R⵻ xQ1']CM 8ϝ*&X&)ʧ'r-49xoST肌hmY#JJხMh"naӄ)> e(Mp#2MJn֬<ųb٤B̬l}&T#xS0) o5fwܴw0m pIrgGr D4nsze !e졽8_3r¤ ^ʝdhvCÿ@u|g&NQ;"&%8v|@A9Otu&8>'4䃂^z*)} t&?KdT%B>-Zp{fgДk$g#᠖$7R-&4`3m94 }>cGZpKSpvÆBlf*MzAZ>"-:vRx-ZaAJ%C!q W0֢rrrށ>l@@5NT(9Q6\Abށ#n'P'̒n'RZ~(xAb}ՠ,6_d7I[Th<=0&rȇĒe8YmPlBQw=cXeq|{ Anٚ-!!t{i̛!9;@Ec&"U+ցӗr$*};(Gc6aquJnNi]eg*!톪<0s!8+<$sߕn^mqDt p6Z-&8P ?jgSp%|$?+MݴU7#h6ʐ`/Q6m"+.T8/iJ'V{ 5kj|E\?p ׄYZWvQ2^Th@fdZyyo,XٓTϻNIFycԙ+Wb:cxV,6+ێvrz\F%;A g.!FOԅgʹ~,dĄS&͞Q3aN:32 dHD+JhikcA{p&j˵Ce7m/uzT sR H떺TlO'J*bNUĨ g4GlyQ.1Mbzܿ@__`Q-x0RJ6(pOljnUI bad, 2,^ ~$r2ky8.n5{qSpc8rJ84 rhNA ĕ)K%!v /t.'Q7 fqI`\ UW#x h3YN>sG |}Ƅ17QPeۈ!y+l ؑss/-z_~hufr Iu|/p>OeLu] =n\9j8MIߧuc _6i2#n.ܕ|qR92m]&&I.0Mm[W<j@z5"'>1/̈1DBPRPd0$T(r@ ByR8]?kF8;&%!݆ BB=` ;e&(?89\7 .4'(ӑMiQ)ʊb2|%!Fn7Sy 9L 8l_k0 A'T] IH5 Bl&dl̋ʳv))2ffSc@}BͲaeU]#%<.';=a,4V ς=#NA.Tqޮ.J.SFd*o`[u}j4/rvY)˃h`* 0XhF(fwx3G%COr`h4z մITv5 LXS;m'K݅Ė05NDϸ4Vq-KUbnTU\T 61Aޠp?UTY|3/4пL8CIN"Rbl+ LhjQX&e [)+ƔH~ t쫛M@~-*Wf}9g$wLvb_}٤}(峑O~3Ћ QP/t9,//4 ˂ Fm"hEF%m2$ -Z/a߻Gdpo]g՚ʞR k8lpXc䧦V,$v=]-5kɵA% Vg%4oBC!͝ eWY{R~eki肋t2&sr7u@2/dVTkl"ˀU ,(ؑM& Qв\*qJ,9zo3 CN?.e=veiGlXs EG:_(Ȼs8>ځx#a?!q7V6NO{kFuyt>WI:Wt;nr֑nsYV{vWml_>pՓKO{Kɱiz<,/^3d(4'0 f6B!H_1$Z."Xr r쨍 )Oֵi 3WG09{Pe=m|ă3֢s Dqv-68DA3FsӍNP|.sCr<+ 'M' MW[s %ՑE7axKmxnw7jۡy %n^F^oGa-w+,pN&4-0 eܯ󼖜ӊI<+.svy2Da=+)v#AGtvl]t __q't[[[[D9[玒Q2^9m'1zTN༧4 =]A8peq`qN`pmE~7>; iYpI^l04~ CQ .\k5kTzKCQs\jjntVkdo7Zn9ϥq#p|6ƲSNI@gϔ57V7Q^Mեġ#6P ȨtR°q D:6@HY$[tRsߔ'gϴ ,Z:sS9iV:.& URcE iPJ^na ;G gkA/_ n'gЁaFrHxcx9DӝtJ9}#aK#^_֭rp$: SӑUS``dq[lj>OQ$f/($ՑR.E)"ݲ@ Q9+PSeStMt $<Gx^U9v}mG¹^~qa~}5@ b,طTe ;MOh+>R'\B׸MF`1J iϗƉuL~pZVQhNV9Q?>UqhV/͙G2p՞_|HRD>Lξ`p(NPZw^~WM|@uё[KSH(,bi)UK@7[&(0Wϳo/yY0/Z مf[KFFA-4;ZjוpO`pqX{Ps@> YCicfU7fz REzw.d}y]Չ`+cArAO0UHՀ)a;6{ k]Hήb>νG B( V&!yJp-vNo 1-68P.BqvݙJ\'rC "?"0|V7 -7c3IO.j\䕟@l8!C>Y:\͈D'n4_eFL4kϬoU>n̈~}NKO+6,RsDiǝ|W[t%ީS{6 &{5Qp,Z# 2CgXE72^B&giCB 7J':9&u##}i,,γ ,j_2 uN@ju,+9li" ȆQ<]G@ۙ{&oT RkQ7NM1)RUL>ڹsVYOq$Wt4- Mc*w^ʪ*[7u۷C.ߟ`\MwT}J|=„QO0a8_c,,5 DU<*)O[uF,51T| FP̒ixӍi5wt%B]gc0ȪPLP 6?W* 2}>9۲ݘm/K"TT}@<4J} 8k: IZ6Y=ꑳl| ĊĽ+$^;^KLp5JW0f[4u$5.-/.GzrѤt!gi#w ?nGs{^cL|Fj²bs_„)h f=BӨJIn`.nq".٩ DM~hە|u]znѪUi R$) >H\l)J3u@~]Mh^@i9-FJZsr(jg9&|UK[lrNf'UO:RџUf|cz9A*.Xᓏ3k=bf"rJ[4\~=)gie-pxe5scnLt'mp4 ̛CPQ%SKV#I80suSy41K\_Q T,TBc562)"B.=M6GStS*x$ g4OBS9&| PĘ~Bu[7߀VoVtQOكl.e|c6i*WT" uD) ч~!XE92r e~ց3}*_d:,{oJ AFsvKcO#A:A,Ymi-k'~*]1zʡhIAHVad2긕Q&9HtbL(e?C0M J[} 7HH8d\ծl}oTKj܅6]1ٞma/41s:8g7Iߪ)E{I8ߓ8-53|ܦU xd}~s5&*;Bh(a y"G6 F-"^h2.ž4XeiM si6+ӈCf~E\:3 rxH'HЪl*6[{b ́V>߳h=O+A̵]4߷h;Oc5X}휚HnX^;B2Dvkݟ(}*bP`7K3M$-畭!g4l;G)jw}X/؇䖘xPyu; .[R`2Xكs\pd3+2W˕= u 7wXLϩf]1!7 }"Um׫vKYYdb`9;=Ub]ZQekR%gYsCJ|\._#g_,]40q-jo\@[" [|@<0tMa(qVqb 1鯉\lH*\lUB/)=aomV*C{36ͭDW,^IU׺\g}(}cX:t(ĵ\(Nm#&5$YxtxnچuH?(rm' zhz0'4-lc-41䎫0C-wp )8S8i`8ѥ̷" dl>pT68K']ՆOhDHyP(=#z`j2&gDPNDhXAs<>%>{2faU,T:?n34YU+Ѽ[$j@ӵj`&E^[ɅBusI l,@-2F{ ͳD)؉q 9ͦ9Lv"xݸMls'Po,.+jFf(;] HR[ؘ*O1L1Ղ7p!8*= 69ɟᬻ^=J8Ir2aʰ4CQB#7VMfWJ7ƅ!Y.MT:T5>J ^#vbNt¹,~@%|]!ZY:v@$w+}XtՁt{Y ᷡc%EG3 _+צ|E8%WXX׈]8ܼ¦st>:Qga믯śPIdeԼrq<}FQ$t\n}ʃD[@ E;W@Rjː7mVOP'S Gٓb)|%|,x& =io}4q-8\.S5687/-1{ 7iq6MG8J}n%l2q]k T؋ƵPLiM\ﬡ&qգeLFA>+¡S)aHU/dߋ_A0iV "%#}0 MMb hRLm ݹ6ع6aK h6 M M%Arr!E5r?bJ;Sf& v^-qra+],:e8K$6k#TYlI_b0WX9>( k2B-"uݥI\& 6@\ŃxTЍF w9۱ <(*YdBq l4 E@)&uGB[6 àfu͜x,zXQ\Ys%YF-m"j/ؼqޠ` MU9AEHA0Jlr9]i](8~*Sg(az廹s*Zta^7V7G쵥?RVЇii"WH9`Bz9H!L"tG pd:zm+D<$c^́q5[{+zAV4lFIԂwqzjh/*sxlfjѧn-+6O4-/͛4mO4^2ݡSTȓWLœ;JW:(';O)FLǩVsZL>/؋ z@%̶hhIj3\ԭNjP/>|ٸԟ$ȠjNdZ}dF$`fu&6u Tp ӎ3Wθ6\6^UwiboS@"s[ӭvEYwMS>)P%X# @$i)T]6aArl,b8 wGގ}ˢ*I_R$kk.$'nmSD#]ㅋ愖J~ }mUV-F=ۦd3_Ҩ'8 ]>˕ζԏ'frah"yR=PﳪwI_D>ppJ?fb¬~"Mi8b裶* P??i9*GlBC ͝ $Gyv J(b%%!d7@ǝ|3Y+`׶ϻyZrB,^g8$H>g( ((JJgvm׌9rY:OW_߿R ~dkc6!|xrωO8@ǧA!8 {0 .mҿ=kk;t{e:]jno_nowǮ9q{m%GwOݣn ]9s]z~INvnyQt|k ! 5X*NC3_@*46Z"@أ4Z44F!4+h>:d @OEӜh*hC1aևBp38}6 Ber g5 KPLne FH|CZTr +X7ۥd#8Ƨo`ifc&~yܩM Y SnQ}MWu-Vq-.؁~zFzD: ]KKy'`E7PT]z?n ?~w{|h;!hג|kv;5j`RU !}<ˉ`7R# 0:Q懄ui@ 'w=0)O{l3uCw JL 9=ܝa/6V$>,}GVTp+=Ap>Tz' Nj9Su~}.4>Vy" :?)E48пAK8{AapMDVhk@~rosRz.~L]o!/ 8 )ZOLzR&0sTЉ̺55ӯCw$u cXmG5QՇgFh~i ߟیh&r|6 זʍnl$_!.hFH~$$6!˺B7:W[BQlMLAG!6N%pj;0%Iꁎ#"kō`!L4?I>^[?Cˋ<{莊,AVlf"wq퓕:?e8t nÊxpRR.(Y%] fдdUF SNJJV}q Js 8ȐeV[eC Wʴf]KUfiy!Y{ .">@0K{ʐ#iSd&+h%P>|m six=j!4A,ф(^0%Fj!4!>ζA! p8q2SzUo a,Eȷ0^ Z+P2]t 5WfaVtnZ+H>*Boz.YZ!OI4Ե=PnY+"$5 3x4/ͳIf?qvF${MP0Ӹ|<5od*ux μXue< yZCD1҅ [JnêC#5n̪@edHoC)|Msg2X;du0cC@#4kp,iDmoC8Z#k*bC9v (3ˉڃ_+RCټE{ QUY[K 3z+eօҪyM8i'CYtH.f TRG$D°) +"8-JH}9:F'kXd%N @7)}=dC"yD ;NW641\0y'WӰoT1ko8Mg!/77HӵTw`OZLv ErvG .i8|*Y;aC v F$vRk6Lؗ5:3Q8Dȭ"2k188vB) H&ZjEJ6q4Dm(x?pODPm%_t;Mlz Qg(bShh&iEÇdgaCvW& PP2e8IcZ8-řI9j )܆±I '$kZHMA tY4,DmڻsH(6(m@!Y9 8;N):Ǜ5;lUJ;,m%>G1D,7?JPK]-6 d9Lקr"yWІ)`a8DcDYޢjKG18I6ZqOT4U-뇄( j&A()_0Z6N,k QargN+wP &+c-+O<hFWf(S A0\P N@>c75N: 2{&?"k"R-$*wxyx"q؍5:BӼ;zy~lB$)8;e*%Bsg]e a``Id!J!(q}.P3b\ T*gw`x0"^ҤG9^kwH^qI%\tMk#+YIvs(+}e(}߲VHhv O]:9]7!]4 Lv| !=U,,W‡?DAv%\ `< H +N<&֟ؐ050PN0WrzIbsd YEpGr#o:WMGq=HG8.؁qt5&xY1ɏ@LԌJDln#k7D:M`9 7v/CfYP@0);44c/bpDy" u <}SEMa2ڰ ] +h ,`S/W_lŵ_uDR/ :.Ӡ>JX( 1ue#~x<}\=OՃh2*xD{5)Ov@=o]d:bURXAKTJmVtw+Fަk6]]π6.ݎ lR6EJLדkm|31^\̄`(5"ylfHN\@7[`@cK\alhB! v@TLMLwUoB"C d@;:vSѯAaG9V ޯk#HW)ҀݔM2xGK]/LNG'3b!QaP kQYf| C~$Jy"6HHnT~<ʬtӵvdUwh6ZOjY /g\ncea!ӣKزFxp8qI)":S䱼[65ߣ3xCpǑ*?Dh+R_L 31laXe8?7ԽXg,^Gc"~g߳x xP?pڎpA2D>G[qF@웈Z8 k->BmEEљp~jAS)4:v-YsOYf8Ve|=eq{pOfL+D% V}A8NpX0kh $Z-9FSp*$[+.LD۠;y1wWۈMb]0̽(yLPnud M''Fӻ]}_`3fD]&^e3۸}dqdžY&1YdA$yMZj>^eCYiNNԛ.@+@HyHtn(U;靖~}ȆHH`81l &AW1=!!m@ ^3RKtW6DPQdͭ؀0}9NӕiLtƁ6ZO`- Uqx+d(Ñ3Tq!vZ,n"ٴۗW6ܹzd@M]u0oǁpNʶk$۞7G _Vwek2c)= Ѐ^\(/V0mU9HnCh257QɛǺɓ<0. pE q:]71]_C85Pͻ U=y=a#4 f U $4BhE9vcER";bLUF~MXMѦ;"v3<ǬS]gcWa'w(F,6:fz-gDzFRzI*Uʮ&8\|?0-74Lfz7wEI)g5K9 P=Y*OILGD0x) C`NLBpε-)Wd3Ԓ q+yl\kuc~Q>u6@X~\yCI1ùk N >{LYwebn.Cν I*тfj6w#†&.&Q9q%koA9_MC羿݊F`8^TOKY{ ,aW7qm !LpLgKK/YXc;\R cߏqO*y89pA#XUNfFGOke[nN:%͌1c"Cׯ㔝,u*SS%7v6We)k ")+5ϞQ &9~`";0s΋HBC0"ŝ{eIY{1Fܶc:*DN=k윾K\1 ąE ݶ" 6 Ĩξ5JZuέ9}jNq7[Lo^KkZKKW=sjh [??i4J@; ;0LwNp qCn{rr|uywy}yMv^pYdl7OtzݭnDE{7nwlN=d/e;g^;ӟu:$ځ9a8r.Au4B 9ӭ3G A?cԉ)4( Ү AQSC2e`v*A\ÜI;&@%YE$f<-|m,%IATASaЄx\lb4"^(1 yYTmCqdsmj5mgl@rQ"Ori2\F}SD6! !"@RN(ݪn6&:Ɣd1kv;cpufHNnXrP0'F` ݍC9o`j?:\jmPn#덹eYԼ3cG\(P C1= 6@eSU|ajY[=*+zd-r!@Ɋ h QjHO7ۘh5x¤Ui6j͛Q8+^yꤵ$dc#mHG!%Lߵ@Dw)$,4 ȆCoGIXsC@"5{Ut րP;}d-D#xEp,!vHDz\AtPо<(Lٕ$$$#<SMBj0b|QYβA=𙝤- f)NI"nCC5+lmg}v469`UaGVl7'2;#m,'v@_ɫ O?JWgGC'q Dzszt3zWa% -wvW] w)2!V1 zQ?77Vx͸ʢUHahϭv-w)@ `j\lS$ ?hFF~HZ.Cǚô&U5pdgp r-NٳR)͋yqq炧R ^F8s9;$c(Y{ ZfAX @0rf;=D~߅(JŘ/F)/3f-.F, D@{qO>Ti܏jIyN9Mv#Aҋ39FKMO)IFQ)Zv* Z]?[wPZSN֓%K2 rWJ+ '{ܮRx](Kㄢ: VIb=KhCː^4$#pha.8X8">Fab4Wiz)Z5q B$ cL|ȝu+tIUɠҼJ(pmiP(ߔ38ʷ ~m(';dPOh,whuVq\ʓ !^2G ) ޖ$л$-,M@mDJqYzA?l<syT Jg@sGIK2T}NA\* B Yݧ t,9YwJs0ʛT{B=8JL2 Bb D=v'Ŭ-FO~RqHYtቑa|ᨖC8MqXYGkϛZORTܲk?Vy9]›[s!}8R@f6vZ"Mdc>11`Cc`Uɾ1[m8ڧ]pbp5(+vU&1Y'&u Ahً̜MHOќ PF#;ЪmBZgH DQw6y'%<Vj¨mFmf'*Ixt0MOa̗]$d0f9 +/Yy})=zY10IeÚܔ+L7kO$q/;ﭶ =0OU!o;}bcL-pv:!5j" ->φW+1=/6 k&B]@`lV})TuԹg2b!x].\mbgjԇ a ehۓN$c3vtB 20]a0 K qrp%EcSh0tM@>\BzhbE.%N7.Jg.gBh>2~ MV7Y'K8J ih;h ,Y;Y+i3~)%X5x7$juЏ36ȼdS:D]dt:~:Xҙ z>rI51Q ~ʧ$4hJ@L%C"Q1(a{&"i~$+GC6ߪm^gQk^/&\(0F#̐>lg)KT̤yk=큨g.J@zJ_Ej~< J$䃧*6UdV(vyq7qzp [X9jj9+Jѻ7iG8[TZI7֮U`8Pܾf.H<=o;=U { M׎J0WҠv"0`Dm69eA@ݿpi/9Os_=`_8m8fBZKB~*ybLye)9:~y=ZˡzS<ĐԌ=bigdQi[ICH*QJAD7`25*$G8%_rgB++huYTNyf=c:MO]PywW>'k1J>/i9̡@1R2Z jjQH;%1 'qZD@!i< 8}SܨTD۞ lidv'"- y"ZK0VJ"`USD۞wJ4!ΖK4!‘vȮyHu_4䤾YE2JK)^Zt>FD hV~HiMB0#̒ 0ه?"kq 򔝃t [dK88Pl%2,(m$\UUʯPO˧GbaNzxC,sp6<- r^gTJj V'jR/*GQ4A}Cst_.| 42O!3u:d=Buh&k nN8e !!IDhk!S{q='ѳp:ф- kېҁd[ura-ll/wB!lq̩"Ǧ"sޚhu 2&1 yk׵̔N! Dn,ހƻ e@.Z$H1<ϭiUKX#vJ>GW$LM$31$ޑ1-UQM/τյ#&ӽѠ6|G{@+4=qboNMPuI8}$, E4l)lJh: k6 ?&]4DVG(;l Pe 󈊐)2Ct "%5[%kT ZeRDUFddq#xQ`Ol .\'\+bFLtSħF*z'6}F.a4vmzdPj_TUUYGnQ{4׆m JL^?u OGN>"2Cʤ 6'i5}gQ>DGV|Fa/3'EzՒ_%kw-AS:9S4_4VNeOL+~},^ԳFK]֚RjyXj- $cY;+Q t=Ɉ-k8.0BFcYN7G OE69>yE=JBZ/J8z[NY8)-4\0ͣ4_f܁kPQTJ\p7cߦpcm͆Zf \Tjcş:0{__2&EjIių7 %$,Gkt,Ogq?AиpGqr U5TRk ;;\R:ӈm;1Jţ鸬}ݦڗPpk$V0M- (%#QUYp#1VIM y}mo逃&8,n)$D25ɯ(!Й4̏Z w>HTGbryRQt/X.U- 0yf\T4Իq:Zro= ((P4Hgv9-:1̱>R pvR86m݆W@+cP2R|ıϫސ 0;Xo>ftb'kIm#%H*|?U%=6uAXbNQ4n*G2 `ņ( :r^2Γ91>?n1θ<׫ ‚Bde0ŝ``8FM;DXuZ,% P*HB-@۞d ps'pjrHU1{rB_BCBC"͝ydGy& (d6 3$(WUu!kzݧiD`@8 &pqw 䟜(O"Du74ғ]+﫯pO]bakY\Xe2u[,N'Ae@az.x.<K{KK퍥^wgiogss^=붏tv{GW#^w-k\#nvi\=sӻ¨.[;՟bpct%^ۭ # dh4M3K@xmuP&Ia42  /'/%J2SD]D%'k] 1 ȁw#朡p3ѐ5uh`f3PMgeo{y{ejwswsZ}Mnw#Oȵs_>=9iw{1g/QA-ᵣ.DJ D3m?D(i z>^(-FZ*"PBVxm C P!ZYRnQ(] 0:3xmB0paЮxkH/ʃ80݁^@i`dɴ[Hj{XXt_{031ip OL(9ҩZb0^{ UDP :lǙջkyN&|2i];?!1V/E@ODIroBVvlr^ Urc&_W 1+to0}х)-L;R AO) ;N7Y}=ovS?O ƓRI2ٝ"=zq] W$$ѽ =)5%?Uz^{cPR( (K p@@U~ZkJ%q(B_H-7VjLHWi`\Z]yhv[f="}gQ:㵬1DS QR8t ' o޲58i. G2C,? Fe@!aZ*P,Ydh ]0d$b'PIC ˨ݔɶTF8Dʁ0]dàq g08ϪʳA<$sU)I]dx>Jg?6]$iV}4dǶ.H2$-OЅ>*q 78 HD0 C^ҍC<>L#t≽6b0+臒,^ҁnd Ij@Q<..Z"lHv!oMEyFڎ:/Q陓O?t bGd6J.ⵏ$PպBg+T*!=}n{v5#̓@ iEƳm:Bi9fFLƿS&3 4tmYNF=V'¹ɓ@I8L8/c; @zaf ĿDMVHm'9[aτHA]9M!&b_ K&5iHu2 f}ȰRhz(M#k' 8ȌxO#pF17c~xnR܈xֱjM@ץdۆ#:d۶=nf۸st;^+};xu)T"n,'9;"_P<>S J(duI%:@m MzqU>ӝ:Rzr:xSIr5<ðbcM&1uGk! ъɖ _pHno{Kku2=xE U:5 <{->H=$'ޞsaƥ!; ޒܼM\3VA驄gⵧ%!7Ly{kj7ݡC6ٌ,ɝ ;oڍ.\ilp<\\o ;ZwDIFxK-`%5N(;f&X LF1` l""]쐫!yȚv:<х o]HH6oy,43{> .^bشx#NTtFel2ǙgX'sTK`%{C?~Z-DW൓.DPLNKv<UY|v؁ d)Jƥ8^N*=U^{P &Hf ؤF'oѣUDL잮wPA\>f+3,6Mx.H@H[hN gɕAgݟQ`BA*$DŊC0)X{% WN*)(t=7#l6+x.'HJNh٫xhU2ɑvzF]LfT* ?& 2pʣ³jwۓX\j{y΄[8.4Nv%<ն0qF lɅhQ"&zemT/NLѬg>Om95\NI"8F irhpXs}5ן3\>FܹfYA<:dx(cFḱԭ'È+S!#'fQp68L>l"!vAE613]S5$RR>ӕ*Rs&* و^rيR4KsFsjFrO8Rs!w(ΒoZ (gmDk#"w%ysVѲ>~D-{ ^{ \4-w^nXKށnu) ?)a0^6j Ld^;f˽ÅHc]F"6CڤtS=3ʼn Ɠl#3%\W.,|'FN]tںfda#Z$DԼj? 80^վP8z%8KV=a!"V36'2 !ƿd;1}zvPbg tsdcdʶkU u#s_2_}47qڮkE-@˔C:b7dU8(uMsOpM#uhQRYm"* @`MwѼe9HYcVTՕ?wyuEf9I :PmlaȤ/LL r3WkU'R"}Q*ytЂ;O@iyj&nC>.5uyޞU7uy[%PuMoA*P˭&bjD6h:*DZ99H:쒊MFk׺%aOGdD^׹hvr%pyG'@Ԣz 9\2%0r2nP{Ҽ< h^;$Ls$sP<3co2u"JT xwIYSFKxn5ƻ0u 4L> TPz+R0YS@]? lk*ukh92ymR`@ ~D$tw@hC2 DUH\$PDD|Q65N}N)}NrUz ^| B7pAm8%\=baEt]N\O6cgSG̜: !KwuV6n(E4EoӕhϢdβ<_׹vߐ:6h a ?ur-MNf²& j L:ᄊ1kKu1>碄גfChkDDЃ~2{鶖˸, xhqUFij *MFom9&(Y޽92|llf83Υ O7ڻ*p@AjHDz?P8g襒xr|6.}KP=L1 ߎv_ksJĆt~?$]ci9cT,l@#u'Y}3Mn;f:U AR^'T! qJVHg]>$O y:i|ȏMI2 &:&ZP+{kjq+CG=/^ @`\P*U?"zjGSj2S/gFҿ*N7j2yӟ`{[~Z$odvӏ9~ ζHN.-RYJ;%v'GI}o(mK?}@H+Wk'2C@8Dg9{ ӂW^.8]y)fӎ' 44ņHqwȨHIRڋ:VK>jjaN<#x`hϲpl +ZsMݝ湮8GHHRnk Qމp(D|_CZz.8I; ddCG'y7DkW}UgEIRK0dm\ro!JBB2!y'2wBDN)vv!F ,8% I4?PPe*c4;g|〃C"4M9lE:хt䳝ґ1tC,$A$B$Xi^%#{Jw`Elev{IDq)+F ζzv`~ڀWW,11 t@BH~Gajh4W!r@YOc=⡣sq%7mF!sJq&I)+Xm i҈˝PX0@$B%-yf SFJfN8E5½AAhQyѤv>ڮCJUI4 z61*ШZCtŞjl zLB/NvܜD']rԉȊVVu2,Ku CE)uQJS)^*2 3QV=eA/6) PZ8܏sҬ+..%wekgPDS~.H4J^$tx 73ʨN*Lne]beU! >Bq3gJk/q*;wgg #$+ 7IZ JxfIAH'7=MclF7݉L7`F,,0 UHk邔[ (wsBǭH!^{)wO|+ȑp:2v5A7 uVi0PCqr't R]lPmL-%PS=GќqdNO(x_gaT쩱ɇ(耒vl":oM̀h%]ZWܵ:5kv-!4KUukn%OXm/q)Y\ 1`vhjY{@kx@RJ3aJslψioXR' ZD1amz+Tfb4̬*rxͨlK] NDC#Ɇ%z w,ug^ivAJ$ hFjdl+u%W{Z)"ɘ?V2 Ń@CZ{åŁ6cbz'u,7w0I%^P)hsvv2]\2.ǹ̗ON. f&>&&׺[0(9|)g~-S~!J9#@ 9r.}Á(aq,1ŋy.$bO}GRs }w̌{ oŷ0s\VI(Bs1b_k= *8r@ Fq5 m3(H} .ŁqH\d6o6y.tvOqɇ= {`@R\*.#(1zPi޷i{BZpSn (TmΪaz^{um (ɇJ@@t`vD=nJ^[Bޓ+TLAA'K#&djVLàΗ~|im+!:ЭG|dNqٲe(N e,aɀ1P}v~JJCQ8St-$h ^d6DۘN;%rhP@<1_;kC#V,"yZy~wO`0V3X_HZ &[#)"ѧ@>:plZ^Drm*өqIٹQVhYb1%9Dlo1ivaJفĪĪvk|m1A= sVKɷ']f3ixC 1y=vK,vy "ᐯ_OHqKI&yH@_F U o  '-A)Q'A g?}3 ^{] !1 EŁt2 ! A4. h^,C.|BK&PжC+Yj"2=:1O;G<8h3}L^vXYL6g-YZ%!Bԧ;jqr5{dGc>었4وx֐h6B$npaB-; Ӛ)U8ӱ[C:Op2垏geS#[Qbh %@A]yCQ^Sc+G-'~ jӬd+fP-yd42٠A&j%2+W}u}Z@"FVYZk oXy՞1(PaDM zZ~N>ԩSWn鬬\VN@>#8 cA${ B{0D{=x?zw{y}x]lm`_=N'WL'Ap ל'͎^YS_IOf7lpj8{իE>aJ' 􃤢Zϩ8 K2T"k s*xO^TǨV9^EB Dea:tk4g33T'HbGuVoU~'^pՉkN` wu\a!I%dUw@x"0)d^5q"YAn{7UT7PkWPES썖/PaxT@k P + FPCωv[D btb:Zv S#H|CxZOq_hDJ+&F:KAt>N~"&ܭZ7'|'@+ Km8D(>U3|c ci<٧{hjA/GSXSM~c'Zyֱ]|IUv)DT$)i`9d4;VDoN8G*+TS)Nυ@>Fb@? x3@I 8˛FV J'@$:&k3fr&!Hk)uÄ$zӍx틦IuubL7m06pIp?d[W~{p@*="[9?S0?Ol RD=!vKvGG eϓ  ǿ]CB>k X9be~\dM$gbA Y s9SQS6v[CQoAj^,cON_筦H™`Mג%>jeٸN!4 ]fr/c%mKD;.64.6ݞUg"U@?T~g4Op4ETJ {sx$aԇλ*W*ʂ4Nkrw[]`X<ڄ!ꡜ(CP.pLrB[*\D:4>R9: ڍHmKLDeP㤖u8kw@DxRp y7qep^h N4^.H ZF7+s ;$X2F> q?l ^PDQ<ckM MUt!@g@r$M tiWJ@YPug~ *tIJj!Dhv@f P=Srwךr!}Kp$W%"lE,uC1kLHq~M$Pzpe.: m(W}aX'7x3 AB6a]*C놆n 8(*wr};(bR{FVI_W=4о(h|pkS+H8?(e.)JA=d v ?/Ze9*mfdY`R3n:yP=@uR@AoաO/ /0oz QհRi vD,}#z~ g5 ϋ"gW} aʙBb~U^QF{[[=ɵ` |PFX%XU#Od_~,"Sڃymu|<nMG 59;9 .S*2 *uPD[N$~8[8 "ڠDDJ ]:(rV#̀k,{pRWtL1~ Q]B&h^yڭJ8OX( }retty-7"ϳ%@C,kVUbG;Hʴ,+@\~l!@e_j*9/*<4]EַC+ ʿ*<~KE*WX!^Z %~L] s9D_ Эfr+ DrTX Z$oIW$# )<_6DX 2( ō^{ In+[-UӇ/X1Iǁ8вNpvi#نo(oavSɭjMN#_gńnv 5c:9?:ֱ鱃9*,H+%[4Ȅ"59݃:;paw0^{qLx"=`uU.0tq> kN|/K5|3ko1 rk %MQ;7b0Ա"6Z+RפW)y5BA PHz)^qp8~?S;@oBM˸NgPZsOF IJVyoZ}X$G4#@A7 ivb˕zԴFd r;H'f#Zjb"RDVD˧ųrfKŀ@K^RX Rw֎)I#'fH D"5~36 CPӮ#cs !RƼq<*Ox HdYIwỵX3'*#z#ca^8FI*OV5*y5<2Pj9ti2}oocl HΔށN[C0%zxC{ 䇻ގn 2L) T/w#z Rc{¦(@G |E00jP{]ϐJ#PtآiԏοhgemƯNko! 0u\B5q P$JP"[$EȇBa@ HY 9?_oI)Ʃq?Ѡ7ڧ-|OŌlԝNG㹛%W+&BmM/$Ӏ cwP,v V( "J^?M^R Ld,2 7hFV2md:^(䲪e }ÿ6#yOJž,>נ6^{YT㌍pk7$F*L3m2G3t܄8>s 3jF3>gg\w|y;炄#1?nuƬi]%y}an_+iYYrL}/rRvy84M1_!mǭՐL0+68qyǹ́CR6 ?U&H{V@87V A#BjdBQܠnzSb%C^,!^}^R)yjBU)nlCg}iI+GZjUzs،nL0k2a0E!_6׆Iu3N)u'^%W*wD]1j8#b",bΓHsItxyc̎qRR9y:Z@b&wx6Dq,C0M"ڄpX8PŸ侎0i}/#d<)op8Mq>D#V%t mOD7(˿kB\K8(&^6Z4.F$8%meYhAZ5u_UID!k>!1Ԉ߄x gJHN5*d\ݑYWht 횈n:Fj8ÚSjn"5}rҩF$ *zt&*G dB) ë+6.lf+ays+6Y-R>!M /W2%Q *tPܷtbr{^j^oU^o^&86 d'K1MZ1 &@ҭ#&E؋\jx/^ jmH՜H /ux&ȽE)%YmkoA őp<)ocn<<1kv9NH| LˢKjUĞxfJ'^.vAN:8ourvq_˖;Imt]߰Xx헍"5Q'z~SMIğivWhB4vA& xZAbVc>Q]9}t} mktyCoXTRN):k;t%*|ƙކZ.0 bR1geu' ns}:UHvVm ~ SF^U`P'49SQ105UgxEP/f{4B1 2.- #DW4F,h @Jથ=RRP8I$8[A!Pj`J:6œԗGcܚkr*3IE[,MwqL1]Ď{#ԦBN;CN(iknd\(j{$K*Ki*\cYMz$0Ώ^PDu%qWQ}j}$98>hjM3"Cxҡ,":]!v b"M38! Sʪ2a%p.H$cvBRT-<ֱy3I=x0-Jp;5( @T/fH:QX5P\kT@9m\/O9x9(^QBh^P)*4Tٸ;D}6Tx y60ǚVI W$C_a v38A" 2B TN}ү :zGSEVGeoG;Hvl"1- )XeI)_2N&DDwXG =xKH=Ly!vBD~4q_s'n %C}w&*% )ɸ](&w&X<V6F0FA^{ȕ>H϶"O%kR辎DG*7\л^[\‡R{qD,KAb8>wR$u@T@4]:k5.A=WdT=IX UMMTs>WGҖrmM.rZG|ҠP[ÄvǕBQ^*mTnW(>[m|~y6Gx8 3*֤ߧ8&%heHb*$ԏxH )7p Xᩍ:_k`F%8@a&w84.[&(=j ܯ+`8HaϊSZE˲;u8;T;) Z;\0~+'JG V%&k'B }Y*J:Ho'-HopTDT؍Kn%RMƃK|gVzR!b71ic#ѐ7+rÝov @PSJ jT@"܋X*9M5VCpC~{ju3,T}U+ _Go-ZWCS dzc uq@]pbF%xcc<,ޚzi|"8go4HYs4/GDr!r4bF'ɟ;_=G#&Q5i:G'-Oj;xLW Lњ&n(o+i>3R\C0[Iڧi@9ϰ:T(N/3sOBC#͝y%GygEȌFdr(MF&$OۯlblξA`{=d@$Q@O@!!%Q"ޮz?gi5?}_}] ٟ״xڥ= 7.@Nv瞻c27:am@l p.KSg%^olmo-.k+KX^vtv{;WƽIۻk\}Ձn7tݫ;ד=&{.i]=8=.7&G^;ܟ,<\Bm8(v,{v *ʂpqdgUY08C^`-qP2YθJ{ ?s}w5A᫑"T$QJ"ji4a[  |6s 񪘗AXg* qa{DQ ;6uڈͿAPokV`! T| ^oD; p֚eb{a$ b#A}n1LӑP *N"чjgL[(t;XFdCGUu:Ks%Oq _Y8[CHdM˵|ju\(yõ52[aGs GA}a߄eW|a!9K4LM 8؍ZEI>tXwh;8bY^Vy50PprٕOD+ h@I,bd1ij)цR_eb@`1pQC]D§auFY,{8u !* } ^kJp.4{ùL9 XFw΅FMt4 mJ5z\N֤fyڱjQ)5ý7BM氧XPN*M橃A1Q?>L=m,{C]"R ]7Tuď 0_!]HBOCԶ" U]e=83L`X.xc}v&)r;gN@jj;Dw5 @C@ʳ}vUy:/F7LC^hm*kZ{Ԯi}8Gp8J3=WĬXvHDg{@%Qc7 췍| l}XJ#|Ut us$3rlnul\@vqBZƨp|QX XNAo(]DzY!)0:d:+'h)H63-- H `vZEE lT6\'|xyzj8.SfAD`N>ЏOL#63/'f:_da&@~~nTr%mt8F=(5r8+ӉлSÛO@ u/],Z%%@D4^u Y^2R7ܥ:NFDx">}}bswi=-g(kAwit́ETa<"!ZΜxԆ }6LxD@}PWǢu"n3!r#^5nӝ >/"KYEΙ-XߌZ'878' G(Aߔ}s *5(Hh@Qca@,5,ګ$$N @{S FC"+i;4@s9Cjpf[koeg(R8-'(.~_5 8Q\6,k 1 ђQ8└އ-EZd"2-yO罯òOnO,tAZm\]_IJ%cΎ~]3g`8J8{9%R;".U9ͲKR#O~V:Xazgܵ>sWQS6.ZȽB{êl_Ji ٨(7jxrly!}Huz'[jwҨj)2 Vؒ{ #"_2+@l(u6i54`LZ\BF@RY ͉TCk CdӃAVneypEr~Y bq EE`Fbx.c@7˷m^ W)髪)Т;_yV,R9,6N #Q?”MM屇H.ҝ/ԄMC) Ğ&W#o沛xO٘$ ADb ^ؾP;A;?VUCc \☾.Y8S5&6ɩd,dȯ.$މpD(ݺ%;Ú!縮?2|CL_Cϫ²4*h[9Ru`FPR6cH$n v|irlFt#Y4k+42N&'G)PmcUPȁBn0**9@$)y 7qCY1!m[Lh` AVVXߒhmФ{ҕ@:sq?oC$p0F|I^Ų{;8i8Cn}e4ቀ8"ȟ"jmZ=$5O4A2ز\63@PĪaP_IHܞ4E{^єZC&\Hpn0';V+dx1:ok(sȠ:;ŲuqTizvR-9$}?2|%",wse٥揿"v '.*?p w]$jx7\d0X*4% k Q/-Q%4M#ƌ3yu2?$n,&~u\)/߆P?K 3oN#&uQ3"GPq`JgN%~ܤ%}VRb /You{K4#m*9J;Mi7&ur$ǘ^QNkK h$ݬ- ɛvs8BxFpBFi2n _Q(6p f(t̐*[EH QMQx ]em׭Wq9P٨F3c*Cˀlnh2+m98H=kL䉮{0bpQ#  n ҇ Nnr"N&/Niu=S|]0Sj5XDte'iIa?.,\W{U4J=?0 (Ɗu_?CծtyN4>Jַ}<\.EX i(z˻q6iepnZe)e'kp9*\Fg4!pѨ%)R=-5W~]jT  8@J4{P2YO@Š4vf+u燔>hTbY G8KCGC:ۢ;AdIgLDK^{HWyi* >WWO= gնz@/ u燌dtH!h{VP(=$m$xJ29\rv=+?C,:ꌪ,.$o;14c21F4$M`XTVn`v';CժQa79B71ɭ9 %N[݋eB8@W8IO*в0ֹ|G {%?2;!J*>vQ;T?~ ~k4uRי5bKCA@}&@8_}TdCAѩ- _,3":0DW;NN,Ytr'l (@,P1L'7b^.H,d#0J]oȠfQs(EypOQtd 2M8}d,ؙɘn7Xվ7+w:*eslS>e/7@BGB\iZ^rTDۃpXFb1qkIEGc%Lkd3NC:2Y-LR@\,_]7{ZHƲ&H(/ sCR!.4le t2Vg{t+ =X锘@hz?wCN7=hBG0=DBK9Y1U/}Sow!6x8Z5´o9Y DQ6j|e j%٬Q2Oa#2K/0cŅVn0G\PP##$>c[(٨f.dw2(\Ɯo`l !H00>{لDQDJI@"wtmռ&av?Ҩ}o)sSci邧.m6`.;Bd{ꩧnOn:|vϣP<Dq|zQã ( ~A~Џ.-zl&{k+;de$nsq:ܹ\ܺ nw;Kȷ/9|х;v\j]>uie/ixIjU^M` Gv }є P+fJD~VF5Q-gTTTWϨNHT8k TP^+[z6! ZDK(`sFg3$Mqd /[0 ZӪs@ n@1=1T"{)N"4-DChNWl7LiҤhCyLpD!=(-7HQ2ː.:<,WP5GFق;jBd .DpZNVDxeǘJd2a` =A~zscckmmcu\_Z[]6Z[ՄtMVbLTvƘ);<~+pa[lQ)c$;!,ߝuG;bQM*Ӷ3&ϴL 8e~;H`(2gL1"((ӭj]ZNs !i&.&t:݋ k7 jϤFBd @Α1 _l4Nh. ES҇6H00%^C-g6 3Dv BKaKz#1]mE Ϻc,HP T~Ddae8JVIf@OhbAlK,Zi@О#5j.bw~"=,0v;A#2k.Xd Adbbb;ن&А~9NDžm-9'+C"<h#O!8u;Q",*\`15Fyy$a}4;C-z|)8{piiq,ڙv6P,2yZm?ָEW;~%V} "L">݊gS:l2'晠8%Áf'uRDWUGBg#m*~ zUbppɹ@/eLj ;Z,EINNHw%龏^d`q@QR@Cp6 QrNBE#[q<K*jLz*Jwvغh=@d7`s_r*A Kn82B5P5hlUFynA %L8<¡6ΣD+ rg$kChc,q'*8bB^pf;F}#h"cjILd}S'BO&IZVKZUSFP0/R%׉썦89X0JDea]bJўr]b)R!_((qP*+Ed5B'/C4ဦPⵑR^Jd3nm;4hץ`@7.ƥWڧ)V;D8|0<$$LY,>ݢ;*ilnuigyyy}oke| ]<$(e>IdKQΊLcFA$lO߬I nń#I 5{MDOV4Ār"Ο˶V̸uF4'V4b1\ l#";nAk#-GMܬi,9MӳMS0u0@\S$tƂq"ȩ*bL?%LBXZE[Ϊp.!{Mqb\Jd7)xG(^x3pnl48,gJә5eդI=a/Ho=9OYu\~(.Ԓhˑ*.1R}8qw8|cNV( B D3] Dq{ŮR Hl>JV\ r }|*ZsҝP43`ybBuEa^Sib6L1_yE< u7͹EYWM>nTR/Ju'jBqt#}Dt̪b?#PIl©$v&H$ M5n&6i>;Oq0]|prBpw:xwم8!s: ֈDR( C3Pl[j $^k1q]⤶ĜDvdG WIق$ z ٙNN"_IrOѬU墵>[g^c$HX ghn Pqj@r)Kdd\)`WM=$*3I@&+ ,Yo+fYm2Ėz5}8@b);G0Rgj+qxdz9Ow9@w=qIك 7i]@v'zqOHL96" ` YI6fG6,qP*(0z%H#YE1hbCu5]0j]j֎JD_;n39eU0c~^l\JI@Gi;*q~^i\J 8kWcX='D$%_h-LE&}r:D~tmC`";f/X;}n5Ɖ{0@@hU.ڪ Do =/,~x\ab&2"qL, 䨒.<b<'o?F煃HTRr 1}8ƒ a^+\-gD3GO+Pqy`TGln wQHzߢIbteKeJIFn ͪ# 0IAJDkT?MB'J/} EW(N"; >*׽66֝-;,}mVbqZUY)!x![i;{,o!LEq2{cV>Md6H8Ff91up:+P+Dn%JjĔס /z@Q\:q0T3wU3͜fá[Ҷ|UQTBK DTU.V eq 1_`G,M"{q+wDHG,Dvc_ l8! BpXi'yf:>e\ W7E?(?*isoT.T{L=Bk7L2tX <Ͱ442uH57+Id@z'ρώz i"']kt@4I+ iRxh5Y`v i0H oa4,H #A(?ao MO`Pr +\ǀПzc=O Ub!|%t~~>(I-c Y%P>,H8M"EO*p6@q***Er8)<gW%b[%UASD0AՉ\5~۬4~(Ȁ2#j~h[> h^M, +elNV }ȶl` ĝpqn.-w@Fd^( ^rC- S" [ރ|ϓ)[Z sLJVcv! F6?!Wb s6c啝lS+h Mvb-\|9lj΋ožLD]4Eѭ:Z|7%J Y?n ܺw= Ґsr *q@Vy+ :m9Q:gLǯZ.*]T"Go XO5 Ԣ)[umBئ P?vMGGI{N||r)i{g6 IќPuc%XÀRRZ~VqtZOY~>e)NDR(S@O#m>C 6~9JiSuh7)@P>b7sl=o.2ؓ3H,|1hD*STѳGO,tHּ iiJFw="hD/}C]-|1r vA>h%6$PǑ@{>}8B*Fr -' Y2owB{ ^{ F(vg]e6HK6"DQ f{(/d SV?B!pvJ%yDqݳ={LSBa/ݳqi+sLau8e4C-F]v sφ;aatm Nn w5ա: ]Ld2E&F 5s m9@ V~Oz~t.̸j%ʆJJVmB hJV*[r{V@\]E=,u~=Ner#w9!_v}0\89jgt x  !=DtRc:)0LI]tsr qAUqˍ80弬aY iqWS}q[h V̛=FlV+ъ3 }'3/'hCP>ްN]807V@|.@Hp8bͿ* Zo6k! ;EbH1 |K[J4>1sIq_h,#HHV\uZaH} 篈=}"Ն Зj*" 5 BS3RUF veE cY  Y`OzهWC /6H|B4ST|v?Zb {+O( ̏:аiK&j( J?;st8F֍V7aޢWrߧ&Nzz * |VvF4C~:nPZrԩ |%pE Yqj+aiYUBn.g\(jTGD5 zѰXr[DCőWݶϛ0gk?h!jS㜬yUb܊+ g9 S3lk@`԰*>BcaU.L,G5m\QɌ-H!ɗ)K9rJS.bpp;=ns)hmx#eYq|uVUTM +Qǩ"S@ 0/d-t8 68![`7pV~5q`IիJbI"{ U$ 6, |m7tatDzR5&ڰ?)(nC\NjōKc]違*s_`N8lE#n5A}[{5K稷ߦO^O`Ui*iXTJ=5XSꛦ)bD]"8 #@YztiӒ~J#D!! *n!m:+^fKn[T}9'TbwQQ\f<.I0=:I$Cn,4J6N͡z3>T'쏲1r$;ړף#ĝ  m̸?!.Rb}J#Za7n˦<47 6Px Zb p@+{u[vcP ԡfOL:O$}aтNc8wҬ B u4O:Sb?e0 ^S}vf],͒~BG?$;-x ~(֮>O]AͿ6,4T B:ә,">@ay ¿bC}lvv!6Sj7kL,pHB-;dՆ\%l_HdnjUR`8m-7uZ18ĈhIt`MZLA}J^:x"rBE^$0]'*QždTk'M@|q0{wi{7vH>p"u絯f~Zc捣zP~4qVqJh@[8aUW|1Tm8tL[HN6kP@g$INsLr@3~۝2EEOt[H;d}$DDlՕ֭-6H3HV0vut 1gAZq;)줩-ygZAW>b%RDEo5p&\q$gV/Je). (?%lw:ܟmVؚYitQXoM w(Do!I|aqK!}ޚ2Q"6[VJW`` =భ7D68Q1ix y>m~R7H~tBKqc6X4dGZj0%R$RHBC!͝kdW];kr-d)B1<+!ݛXmBveO!@ GȒMxYBPyJI A)*U{ng9g|$goh<㉫[56 ;69{͓Ǯ9?(I$x:$i#`\\RJ~Tgd͍lmmof{vnt.UWfݫz^X/}eX۽{]z5۝\tͳ:={20nd;/xnd[@ :`px'47hh.ihOw  b#FfWF=S_붏;ֽ}Y;!\W߾v;v{EesDFfK90.j"ک9=y9{% &ha8'gwZ$ Kg[3tly er9[ )&|C Te Bξf b@ Y aCšcW H&z"\8,HjYB/#܁F$!mH*!#w`w*\U&?"hCPk4Ņ˳\X_[moW76}*qVj∯*@iLAΞ„@8D qZ7Jd-8ɾϣlBI$ L/,.#r*9{Uī4LN!jS%ʕ kENPׁ)Jݥ]?ʇ>PB"S.Di 9Ba2^qГ>&w9 ˆ0+4 mIvlS$!X<qZ%N晈uZ!< sIV {䛚逜}:003h!u V-$j@!-OmP,1I`I)ޛWr)!2)0$v}NP!p[WH &hߓ+_*x-9bUg?ms9FtcI@I4mc$^s?,9΅'TrZ){\tε b=mI',90 f8[ Q$\ \ Ŝg]٭C i0q"t0q^,D"+r6q lph<rTDQG۞ ОXI sJ&IK k> e)^ҩbLr]AFe?Y=# ,boǹ^BК+@v魭{i_o׼l.*ޗ6OT!"-b!%4LsOZiܽhnnmg]rpA> Z)/2`?svo;a`85 UԚ{F! ]BW*؋{.8B^[.Lڰ~@D-Z^BTzs?AsD(K0dx&5RUbt鈫U'I~ʅ)6+K) !MGG5~i\Cy^ˮ?Bt`ʌz( 00(e$݃4RmQBAQKH97&lٽk`N v`ǡ:~V0>JV: t]:3ܭMژE+t{:oh5ɇOoTE͚O©mh4?2Z% >Q;Z1w3dH^ъqgzNQ;ո|w NrEGHIԄs'HGb:r!b9蛞6}M]K˜CCq-7{67EN(G_<4NRZ9h|P׸7i e%nzq=0}х)q H? j0Jz)!L0%jx[eJ_"gCXX#O?foa*N;+lj 歗0HV8rqeN}W-X4Nqb^H(Y2cv̥ C,ljɿI?`"<-&fNGXBr1 mmcQ`05&go]T{aaM7֐?TCN”}AGw;Es˩uδY2LaO;A\睸 Zʞ2م>2_; .8 U4__@9[F|ҡD梢c%T,=@IOëޅEU aax),R:)(ݪ6-IaOb&i xHl'WDgRx@,響3|= yh}y .y'0aU/+RkGRģoe4瑦CGSNSVVXcd8-/D,sfXۊa !qKԯW!g〄e3&myRAID\HABd#NKqU4tذ&aLnDJGTÊPu}~q\B4|Ç.G *$eϒYfE¤J(p5Z>BeS$9 TpB0=Er^ct-N+ PLF? C2˓vp_⹜zi= 0d3QxGr(~N#LSh tǜoω@R~ &}v 8[_Xϩ`& p)"w8+ ؍lB<-K-iR"%BG$J}:mZѿKiՏi@IT.CrW~'.3=^ "q4'ʬit?Ctaδ/eHJ<^ D)CnSkE*a}n[m|_47ҞE<낑.LfoќdO )h.r9q?i:lP86DÙLUzr2U)N(OA u8yz(2g{#Inp!䯮`)c<7S&+ͪw|yxs7M/<6`t6 (~8%.NM(9lv)Q[Pԃֻ^+oY@:"zAL膁3]Mv{b2TՒֈ A0M놀a83ʩ^tYQHjbAE IOpןY{ADc/u}Y^܇М011}֚)ΙE0I#:"W ZsH(q2" ; b{믯0u!j*EH6=gBCBEW4Dzw:E. 3l {(6'48uN~ Sށ-""q֙mg Q޹ԉNej| lcswʦZ-B*J0)=lɑ+f$euΤtW#8 3-mzPfN{GH S$kF1VCSN u\8ԏi4><1/u^B}݃=u~ KQZ֤(o˥֯DG։__rr=fFWZ[,Car7ϤOw`2O>PQ?~UEjr)HsBVG:.e>a -d"DB uJ2b (аoqaPcB CsLBx|x+]Hs!>rܣ\E¼ɺ? ?~]BtGEm<d(\-$?ӅH)$,E@3d¡v\p" sU@U8 uρPV92ўwKt4n2 #gos!ڐ,Zit4X8 t+rIҊ^."Up u;h5‰}r%!"tc4}GNteCD " ݨeJ*8Dpa!^kW vBrPWSL/Ok@2$Cs~]B)L`)8Cpԡ N,gH@TIQ'NqdTѽRoq@IM‰2Y@n@`J[ǫpEsn>2t W[uS¾}:W*F!wB&sPn(Vk{"f<_3S|F⤨yp:)rrj&{Jy'RVb4VqHKEj:|Jq} wPz7.s(7O"Unݫ~CܛE;'HDHDv8Tk w+eo/GOۛnN8oPWך=_W0(ܘ2y%72&}6jUmP`*0V:3qipH&!Hc#ήBG"q=]RmPljw^=Ԏ~._ͩ1WVV=\%J{䐦TT٧<ݤb$}A%yKB](:Mbn &#r/ie,Gw3f!BLH)Zr xq!0ВqJ=j(Uh&]Ҙ~PȆV{vpf(kW6'9М$Ûy]p" I,EߥQoO~J9 |!qz/~hا-R"2IN ƒBiIɳ6<{⡞AojDU=s"0NξR_B25%)rv #8f8[-@({i,Z,bTNFlz.8$~--G 6)|؅)0qֽ}un7}b/${$&&a&总t`MBN%ZjtR>bJ@oܘ9Ej]Ѿ oB.&Nk:M&t D1U"CTklj[ 7 ^#&yk"9Vq i<@=GqۜFlJ:EKq6]v`!K֧"ML#,P.NLD7if h*[ksgC뛅g02耜}њ)֞"0&{5JY7)/פTH*4"t.2c\7}0c,`@$>5 H1a{ېK"AA!@^ի~gzƲ<}T#O'/jk\ހ٩'|_zyߣ(" --pwtuCryt;iWzPuzݍ݃npw.$lltll\ٷyQgߥt]ҽ  坭zW'o4a-h1j<}]LY(B>d,#xu,5k啕ݣGWګkk֖߽qAv % Kp/9q{^pH j"Skg8}c33X'" (a$)ɺHaɒt{{Qt9; Ųx g.9  f@J>M:6@hّ(УDWΈ." p?xR,@)Ͱ$4!g=+Hs~rR&N8NLw"tM%3 6LqlB0OP*o7[!ҧ3sк*$85sWUF!gžK'\*|Olq/1ܓ[%gU䀏SGA49N30ڸVU h2]uD8~lt7K\rvCU0\9䡰HDA@qx2~WW%@.autUBwVʼns_pA_Jv%9@3D wξPV%MުD\H?@bov RjSALuDLNTဋi͵֥bz(nn){x"W췿U)DqNʮB"&LZid=˔,V)BM(`Ze')b`hx:+gXJ"Vc6䫔l &gI@j9=o؇JAʮH Xyьhw]'zc %t]gB)$REkI> 'C#k\p$ ] N'LBpTyN,Gzx!8zdhb8ؓAͶs[B*yy&S`Rhܒ@Kq#ߠX8Huh`*(4AكMIF] t}D}r[9S" <R~Gzǹ&8@A48VhuM>] IJYp K,͒]="24ncHmh`ci@jսO P|ً;P~m6PDN)L"ɘYخ_DYgQ9Aΰ ҇S  P[H-JӨa/AlLB:nۥLJ1/fiQ7 #tDDpb%̛3ߢ¦X"!hϦ+ ;EK"gGlec$K`؁%6e{=iHG"I8%Z*ij#!-tef?ٻ,pHf0\[0L8!qI'wX2~wSOAJ_pT??B?yvU8,~PiI?B~Ὦ'jфiU"kWΡp{4gJh9r!Qj1mx(җ(#WM29ҊFFcT 68r`k!8 gNZu yDhM6TpGQX;5c w ` {@_ 9N_N:8iRI,+ +M6HГ& e`,qzM% ~+nbk+eV.#ulr-_s\Bѧrdz.Ѵ, YE&"r/#g)P;I/ͣ;fZkF` W+4o_)&i9Q,DnnwU D40$KD rUqyys:S dk` ( zRG^ iCm|b$lV(~n.#Xֲ(Hh@ R g"ufiGe,C^d( Y]]{3&v *B|$l0fYʺ,4 ٶ ?, Bݴ؀@9|a՜I14`E8% ۩רEDҬ@2pVPہ02Rha kTxa-.&jurxYӮ>hҺ7U%B݀pb. nE>^9ADp4O(~GmuM3qv}e+VOsD!c|oO^@SH&Ž}5s(6H_壎ڎY;ՖW4X1foiTs3 CdJG,=,jCOl< @A;=U"g64Ɂh h3chxRB "ߓ $ p}L.BҴ '!pZp'Qzq J.6L;PZ]!pEu&*= QʅIS/`z@ĸ=ܦMjbrAHq<&N۝H90&H+A:P/h!ʪu2f8<›dӽT> i"*Sד[*x{,MV!#e}IMJ*8un%݁"c6;Ɣ[@[\>"giխ0Jp:Pr|YAfQ]"sTrzT=}wβ%TW좆M U~"FH0U{bl1ĝVA+rYLr$[Jl¡BpxTMl@XVh2JSu+Bڬ +OHDg-Ғ2qsN XyKm$ȹQ8QNX~oWMnkӳܤ2ɇ>*X^)3stm4h3c)Ǒgcq ѳ#&ʛf͙F/m0h;bTv}(ΝV8JyotYUN,,hhm6Oqkàg~АуQ|Zʪ^ǔЙfαD9o\LX'Hqbf.pAI?GCrvS8%SWHM'Zu% )Sf8o+'bv9TNϗT쳕3=6@ ]z8DFVF!g[yE>*J`-JuGDf4sPGtYJT^UNֲ@lEM]=M6M8zOWHz@s+)e')^kQ?@A܄a'@ +oXޡȋ rl-X`O( ճaUnԇ(Ksb KwlX԰t2 t˲j R3$8#K. (G@Ь=^oP}UlD}Ae TY3ɇ2e5ȬЌӅmU,;iΟXap-G8e,b;c0+^PpA-8k E)݆LV25n +)@MI8#8,`!8u359۴#獣oߥ685m4i9f?_%g/BRVE Z).!pE(NnPg T7п@&<޴٫E"u[gQ)JFή"^!{8'Zv>;EA_v@:xAv[_b2t'g@( 4 um]zXCGMm o邿Deflh$ ⬸ɢN?f}*Kh9& TNHXY&۝ʥD\@Łx4F3>)C3 %\r6Ww`<-^^6GlL1TBvA EM'dG)É`%z8w)zu9{ke("C[tF +`vN*dq男DD{'/c{/mZA p`byi 8`䘋ꏘ+qZNB:T :i`n`pXp1[@D;8C< =7~un=;8zBºL}&R_L=zH#G7}-9l+s[^<`USQ)C=Eޥq֬rKYeI;RQ%}8Ƥv⦢>WHCB {8c*\mлL8%g3 -g> s4190Er?\=ǑgL~Ϙ13펯#>x/ǐDUt $=Er_A85[L\\uj]i(Cp6L=/&rĬxJ@h]- jה$ton6kV,OwaUg|bL¢ҽVR(;v~T};5jN|s[<t+9{ ڗو$*7Ο/8fUpvt.[7x ǭ8% V=ݭ^sJ:rҟ9n~kCɀ&hy~X;f.R:fFYBNfMϊoD2Xp gC+@'5$P-XaOy }29'%Y7t{h ae 7}Bd2@YF8v^9 >/g=4ѝ۷|13M´0 FsJVd6h*VaFRy_0)E*`M6jÝ+ٻ*&= %׷PC+e0r稖m[D-wC~GI|Uelh:P\+O< sƗc,GLŦK'=_>hlV4#.N8e8glp@ `!8!rTMu qVe;]BVD\ ̋"Dku|氮HHBL&oWk^6op4O ܟP_^)Z-#OyU޹Jx}R4n=kPX VAP(94J0b JᘔCqc!ky*]~%8DOàE&Ns>,YJ[ zTT#,g$]%0%2#ZۈMY^[MRzͪS{ݡb<Lpc0 {yɣuBȀGخݘM$8Bs\QѺ(b ί) b%S&<+?:6-]R""gѷ6Iu00 v R@糳ZAy-?G% ,AtI;lX|e)[2R0z19{CE4/$5TP 9ZOdtӦ888nP{ohѺHN 8?)ח*?aFBe>%1 _OL/[t 38P` $"&uBt܆(7o2~ g`¹Ī&$#4(њ8,^ f0 #gqe` P*EN$|xx.@BCi#ŝy\GyG;#$ṴI&$̲$z63IlklɖliNn,HRgY`!an!G caò+ !)+G%*#B9>{_XRJU[_WdnV*{r]x }h|+tˍ rM(88Q"(H?aWrR'f}-Z_n龤}ii${w=ξv З;Wlvm\u|h\ep.NqSU&8aH@2 pYu4 ZMI@EA.3YD p1ё)GkGB"B4_qtZ'4f-'Uh Pp[zS4]Ͻ@?Ak7yN 5-('*B?Ck2!B`z B<6MpO6q lg)P7h虻+/@q؏"%f=fV!RAw2h4aSNLOiո ꂸdZw`'Q9GkrYL@Pmj$/q;I6TT72y @h[LaZK' L4Nr7޲;Q?cS: Jh4!#nsLW"}"7$٬l4Zma= `4\tKOLh|Fq|(|qBEΪ%nwTrzTnB@[O Zp~F!9FG]vpƄWfP+\˨FM" q|o0q3YYZm'^B %Ak/4c6 =0SDVvb@ty@>Co!:'GT88,J#>p =8[-]r^,7!좌(Tdb,›vytHZ{[/ҝp~}w>w\Rt::d E&@ W65@ջn@Do,RvH|F`h @v!jN&DB#o(B+Kt܊T G9T$RfծT5諣>^į]vr_c^Tu~mRݬbPyw]&'AD/6 c퐽 L4U^$nAb XuAkЎ5zց}? ZNy]!Hu'_^k:7X>>m e0X]qe%r<3h](zLؤi]0P.59hyӂE! t](wD@սܐO2OA|;Ӻ}dLhզ")2aV~bv4 šBZkY~j8LC$^&5 b" Iqfuñ?2 <ǚ}A*ᬗW q$P;?*3 c/GHy8e4NP^C>Ϛn1+63aB.5 $PJh)OLOˌ^zR}\YYvR]=b:# Ƌ2@x&^ޖOr] ]/A[b0Z{6 d+ʠ?H"/9J)V\\.7k\# xXK "d=EiDħnQT%%8 4<(ilXFw!Q9DaP<sV+1Dko.l'ł<^{ $ Dh>'[c~7mq++ǣ( VX5c]3D*xRNE9v,E٦Mp%P$D=L">+tZ{vCv=U20菸ݲjc+ j,7hd'<׃W_> 0Q"׉*7#ĝe.^ A#kށg6M^.1Q_/Ī W܅+JPa(3B+Ien"LjCkl }Jw9k U,˛ڧ9T.!COL"כиK9P]>3 JǍ;1L¬HhH!k#3?/Á}}hNT(ۀagzI&N?#SFm!o,HSaڬJ\<-a!7+RojsDA0窶h-no/9LMѯF5T0X_+ Whnm9 :8Fd@v E`ZG4z[sW,E]qA) 5;r~ ݯ㦲ff{VmZů֊  IlIi] K]= DNk @)aX걲%Fy6 I&wPӣ3M`AiLD-W!5!#OG|SӮ9ؕ]۲cT az]Z-AO ?th]ͭd,>C2XYW05LCkWa/fn-?B:PV;JhT#\L|ʜNP"< F81&"0R )M]ܒ; bĦ\I?7! t1ULh :F=(! n!Z$_1Qa_:[ ! 9A]!]i +eBHw0ah{Bۇr/Cko&-9xX/Fk Țb 2u8 `u/tR }Eɕg$sR6oHKׯHyAo:{敏)seW#- B6RbA~Gq-}8=/fJ;TȝUa &n(#3q7߹qroZ6?[:(PSM (k0Ѓ@wKL@  qq/&(bIVJ]X9֞o9P*Ʃ[L5g59EI'n  CA@]+6;Gɫ`o(Hk  uEIɼgW&]4ȡNz~VbehX0{mpP7r-R_^[?l?,/bB(Z{ O60oͲ-;bK  F.†@^.9YsdFlY"cޤhJ]-r $Ț9${He`<;Hީ[7!<xi{kn<^,K`Nr0|8 2e5T( ;)3Z̗C~Z9bkR+L}BiyI0|k{MZs|,c2VΉ+sh.h'"a!JBJh]!qN%zGՠ$`aB _$?]@t+ZvaƃJH>qUDMRN 3 5ǐg VѬڡ|2 KdT>sd6V(- $E3) `!W+EIE?a*4gOC:n"FynAkюbqn'HҋH/b(:[l+F'wALdϜ`1F[.=Wƀ;Lzڃڕ72YY~s\IY1YgͺMaE4 v,KTˉ6$=mAI9,H7ZdD 67h4RFwc*7ߏ |-׈$5]8Y ѢNjW*M"h4vDii#e>caQHKBph@V^Y$ q&B4,N WYHj(Cݹ]]\0ΑJF1[^2YDv JوÙIE+i"ZHsվ_f92mOq/YjYTOe۟*YXO;K#g/QkkC 9@aJ#3:E&z D"ZF/I0.j2M2{ ɜye9]bFkhDdS Ll[1-s3z.# 8ܬM&Vi/9[_Ê%2ʗ8q9Qlb U*4oTCƏ!} 69o~h{vR$ \OyZO.h b|QJNaBHv؃|R]Ԟː|DŽD:!Ӳҷ%kh_1PND"'<>Itn99 2J,F3+Ifift 8r܅\SUZўজLpBI0-FnU GUA=&Aq'2W  J"_sx{0$Ӓm(KPwV;S{w: sPvZ#V/!M#( V@ q*zP$$^~ofmTrrZńg݄9!YdsyNZ;`LVm1p*ͻA2{+Z%4.)(W? xA{/<#Ї!Su\Z'23e 6:E2y;x5(N/8DlU2ΑnH=.:*yFjX!YUqı.4R(/jV%.GKUT[2kZp!H~dvR3_Bn\[O1cP8f,R:c2qgn".$&DB ?R'- d=rksm>kt|jWdS5ie(f;9Gs#ΤYrzN'"h}({t? ATC2 Q<(Oilo#r]taͿV49dVjFV۬'ZH&; -d>t y,0W QXy u*|}-MHrb*Y|袦) A} ]5y 3ߥ fpv%AZx~OΣQV/>ʿ:uФy@ :lDśV2ͬ˧jek$!k\.:Rmq0oS8tWimtfت /3Gμh7ʠ[猀/Zy'W86a<<߄`~ *ZvlPj̜^u8& ! Y %\1,1O9#K`Z94lr# ܉ GVnD8JEC{?d.AWݕ 4ttpg :A*+ٽ +] >V}hj+ZXj)н/U硵&j0 PYQփH18H_8Pj/T8| |ށ?+ \h眢T8 QV8iM:3xh7.n=ЏCa[禙h6<6".*]Ҩm#ڝA[ L er )wXK NeAʇ~ه[MNтCs8 WM89ttt:n@6{6/hy ۍv^#9Ծʫ@㸀svSζN@G4{ P:U"km0n'KP HΘИo<:9;h I'{ uAtvlt ;`tP ekrh&DA   t[ '>m8G*@8L&Ol qֆ 1eli/ѶڪL&PmLD}DV3K:)X-%j E(kهK QJE6 \Zbtq%49jUiL!ӍOv q3Hn *SJ%cلLLDm$dK9pHD?(C_!?)~-̫6Pe3\[^k.//vVv7߭vpD.!=V'w,|r3I42#mBJ!N'*2YVIXVDD/.h$]vSԖ QDL"HD=O.\$cWfΜ *GU::R4O Jw)@'> ΅Vyk !8[م68xup\W$(:q#gc "L Gp!hϭ3[|]oRL:o+`Bs M4blA wM9kWM2;@5Tm8rM:jFtqnqRS=SNt99r$d_S8\vNS .(a-)׺)9rrĨƑ"4׬ u&{+9L0eD JGKpA>\'qiAp^VI:%g1q@>SAobsr٪8!У 4}6Pc0:@!g_i 5uR7K8%gTƉ5pstyW9i Q`Rӳq"nq2".p 2"+뫎m d@ ) hgs>RZGAeMfQb6((ҵ6CNLh$ qζ('Ilb,俹U!οdHqjN٫l@rY\4ݡ!g!!+i@+Dp(wѯk4gC2Q0ҕmS:+ٛzr0dM%`v0Q^Z[926^Mή܃[neŧ-,2N 90ΩI:o!g琢#Bp.$+r8őC/(@m6iלMMmg-sOj=7w zm]?@[` 351mPKiܰ[Ab^}n7|S#7@R9BC-)5,%jҩ h0F)߫np]|Uޑ+l /$i -QPB=˪p'gWZAHQegze4zBk /4eM/0a,wbE3oNQ.8E˄Ol| @x71wg񐗀tlj'DŁ$%L/҆ ͋ڱ6u 7S88мTJ6 q\ RKWyxj@뢵 I1у  ^h@h(qER :S n8;l&b-a?OJ5%Lz ʳ*`?6|rwq0-#Ynʠ& LɇɅP$Lyǒ>{U:A@>  xץ>-&z8YYOvjzFz7IBw3 sZs&l(ɲ&GJ z!z:nu.u~6fw$o r3ܢKElp%+#rv+,1gL'rv ۸,G/p~LΎZr3` 8jM_V8^h1_ g_q }eξlz J:,^.?P? |,1(< (RpVꈨQM6Dj\pTObOc13hkV8=%X)^pP^@~i}fOYcxƠBFC7Kq!C:]uO/>iJS f2ջ6VvŇG_>WHQRϚ58j$ f+ &[Ĝ1m%d}m)_rj \ bS6#/tƆ+}Aq{&< GY3pp_$4>{Hpn猣L8tV8x8'Jp&8pk}gӽe hՌ+ ,|Ui:upsRHT^c n @)P)j{ĩ^Jζ*,o|{9{ Q,`c \>\&/#<05}k9QcN= } g! XچVt~=H ;^i$gQx!&AL&}Dӑ?Z8\6 mpbyI5[]" Ν8oba2ȯZ+I~Ö ']¶ /ɪ*C^+2yԐaK8O7ً+ By?ꊷ]o5:5tđ \ %VM8Jrsr0,|$&g_yڻ0c/7s{ V!khkrF&CmѷJUzT3~,]v]vhôJM\Vt1E/[%!)ҫV]dk)^=S%ꡂljhbE$M;b4 * >W}=nIӬA<3'1郺&Ebdo-$8O'8o N|Pa D& mz+o)Ihj3rġ ̣HޥW'wY̶51ɈNۊH6r`BP͖>xk}}`ָѨn(_r$4088-B:C~MPt A:f_INw MBo@ HA<+*Dcqc`;_oK;a0178YvF#XDM'\>K[قLۤU`9Mw8iVHS*~jU?0#9 /+da!qXeMKV|-c cjd==^ O=l5WKt  }mI:3ysYZD=C{ nϿ[{- uAb+.:{aVȻL=lRDDԏІ.uѱV[""1 LXrO(^oVdTkNbpln,bTo rcpiEj;SI_oHIଛkl^<e838P̱ Wx[q +qNسγT*LL.dLVkz$rH6bդu7/WfS(\m *侶9xPuCUGVmN *Vpe$T >C+*q3 )HbLS  or!Јv6pC0]x *ÙZ.qX?BV7,^. }V:U\sYyI gg3[s_%~s 4W0ǭ?c:1XMPfm28ў==L땥Dε.jO5"9r(R ' Fe'GwXE08윾@C̱$|6|6EyO89r-G@G̩kΤB鑏ks暚pMHhx"4k)!󁹰E3cIjhYX٦v cX2ʦCDڊ2:qKnPM*E/c r5:_yڄ ('|y}%4aSNiiԓL`+D.X5 EkBpBGV~$@evs2,5>[y>זS9 GαF&0e7|ד ʕ6(K-nM,Ú;u +V=I?v1zՋ1ް%pa[1KFr6<{1I!v|xtTQ4xCVji@bp]^_Y+ᘚ=$+H(^ץpF:GPbt1?FNbiccJ`}W$:mxxkO Y߆,`dE}9lПk!?{<+kpӁZ= ޔޯFk{m}om&+hC N$|<ʙ'T}xL p~ri (鐖ry)CuT ~lR 9Zp64eKńkY1 'kۦH]l!QP>nҞ}64 J)h=CZ~:Y k 7 lpf#̟h!4G5(W 80B1R;h~P2} , )\+Мܱhڳ=@8E4 } yMk "*ݻ*\rL,-W|YHf#g{)T0Ь}LܽGQ0`2,ỉ:}?LD\J2ї ?fRa1}3~!+y2"d+2J'ojJ=aB+($CcUqJ2f4.iR.N!Mg*GNE)3kw*s;ƑCzEQݲNlcQ͏BCU"͝{dWY{gt;Z#(0ScHsktozb&&~RD @zXu" Y0(QHSPɾ˲O-P {n{ӭdlդuFrqɳW4 ֞$kǓ[_u(Ȼ>Q vPxA~+x1&͕fssmvj}e/Y[klm]lm;×^vCIn>M.:9t.tu:n@{vW]n\9{HګG{7g5{g8J~'v`} f8Kg+-0w@J , ":@p|Jt1be=`+H"К=G#s y Œ$ IC4,s p|e_^͍iP&^ MFe@iوG'&y+bD8 m6D8?l"Ɏ82kG$YmL$.ćsw;.IۄrǗÝN{kӹlkKQm0L@*NDdƊHth3 zt㜘@-8P Bp dy5Y80pe0 %582!Y@}B.[GEM\>Sg@˩u 2 ɒCGS(Ll4nP6{R1Lo#{ڝU48A~DA(;>RH4&9Ѫ{@Cy@\Dw|]CLD͹mh%@'*EK61j펣K*uSL )ucD:5ˏdSUb$#&.&-YteY !4gFNÅY4vp1E4H 8G qp8Ea+Y_8MgP <-SvK aJiՅ( ɇ Ǭbr^U4QVF>.|z5"11{)Ъ h `rh&'{ܪPE,\NZ@Nb1PA 0ҒEy""F6R< <ц1bҝ+1߳²`_wYnrqJcAď='PVPoRV QDq/w HdZ=5}Jx>! QKD'm9,gREtW- 'jrB.#@o"9:ʮ#zBƸDQjTģ oR`sCzI%kS98R7:4p/da0.ͅsU a*58iFJD'twY}h׭$ǀL2(Y*Q h/dT:AڙI.X!Ǭ g~#wTDŽOCd_ia:TG4Y@uA4047ژWZTDE, K͊?vPtQ!,SU &}IqAf*S7l5EwjY7C#QpV㤦Bo!#96DN|q=wY`J-膶I8/'P@BpSg]N~SbPp P=irn^E^Z%N+"XbU%Qn'kבֿ o (BiNk,eF%TTg}VW>%Sa< 2F˸S}YAP3:bY,Nd$Yv=]Ffu\ |ݠs}}r=nDvU~j'VW*>B͛*Iahp[>}Ɵҝ*A9iYCM3Getjϼv~1Q+f}\5GGu}ka8Qj)|}thƽr+_h<|5Nb8ZI LpCͧɿ@#{nF vwWZ[+ ajoo& .\'HriN LBVA$7DUW9+ƢA 3"%r.-? "hV&_jo,/O31}r*oh!nLj5WRnwk-i+%ԓ8KT4 \?g.%o0ۀTP\8Q飧$gOQuPK\L%!uB=sAon~]3p ̆}ƪ2&PB9HC5UV$!M4Vs.MOPWvj4bKgZw!t5dюuߖmF;ؓ_:!=1Ut 2; H"r:lӎr+HѬ4OQ OD/v̆Ē!G`( eH:=L3#ڪ;(m,`!n}bs-"ס7iI87Ne⡑wJ`.X-Z[QH.aP3u =2'z%QT1q䛁\RcF[A6!߆(x4#Z!D+NwR9!`JJ haPm)G[5m֭t /Vi]S984={inТ&TzQ"6A4U8bh \YDŽ0S= $ZuNוn޷l1QzDQbDwY+>(sS'DKbs1MrHU \>l䓗kMS6& X MmʅC;`}ުZ}*+- le+d˕i"]pV YpAn1/"ڭWܹ*9;{P{%+R@4˔}{~P4]_hr5&[£lIwq'\lN7j1ݾKb,oY" 3Xq!YCdID, qP íN+"K# oYuV;]tQ9Gt!+4pBmh2:y ]XbuY#^HE%LD7^i)qO*Hϑ6XuƋH' h-G%LJ NIJ.hapV4=.mW&NZ0kc9S߭\BWOY0v lbZv)P=(Ja4 V Oj2k>nQKX`'Ss5evZ/V>Pj?:Gb>U-V9q[#3Y&+1O'Z5[bє=vDPʷ@/]J֒=խM[zy2Aѹd[!)Y>fO|& , IY>8@|"G̾ΆD^NdO4C& @M6@XnoE̺3ش8:Vd 58>QrXfʔqN6'Aݸ $yAO)\BxNS/k0迭YJH䤀z[K/F&uoQ to7OIm6Hnle4\Ǚ7ނքBmP~0we e* $DohG ( %Lkd ]+˅e0.G4{%ZH#ܯ8F9>| (Er$N+#!-)m5%TWc! rKB0?QcJQ:QNk(ZU C.CQVy=}͕ؼ技l^"oh"j# P"kmZ/e>jq:?W:`1=d+?Fe~ҭ-C4u!'=L~B;O \jI-ل"(1v3 GW5>8o"g^D}b<@++N)hDPD+> Њ%Uiiw?Q,[t?# _8&iveP O˅$,w3k:}d*kŽ"ѲF־Z92 %=w$z!ӃV[´,?Dj1mmI`Ca[٫:OUt{PzVw꛵ēUq=:OiǙ+:RGgf#OX!YiZ.hb.Z$ЩoKmbuZ@Ym\)^}#}ж` rz΄sVҎCgm‰:L'6D y HjEg) (o0%8?q Y 8[kCVv[ŵ VBX-'T¯شa8DWq0n+A.٣B&%/ V8 $ā*E;>Pv(PZo7'lzx 9ʚ#wRN L گUD &J5MB'hWXaxz~(9F֎V( 7 |ҫʫhXj!'~@:*͌gh^G^[#?`4PXjИ*e(t4[F*(h@GvVҒH6k^aDwt3+? kC~ؚ3qDoɉЈuŸ#N2ng;N@&8ZxMTo  a͛|L6yrpA0jFsB!4b ':HDJq#MǗ*l y=m3g,_qE+31i@Z@Ύ&ZN"bdMy/&); 2LXاs)Y1胗ʳ J7>\;S3G~<p18\:OH9[pܔ=&J<^orI/ihmh|y:ÅS Z'4ﴡ &@ oAC zGOsCW}b}6r=OTtI(x)Y+U^U:/"cJL{\(k+9=\@kCD՘?,F+ت^yhyC6qio_em4T{ N&Y%YC?*,y kr2o!;Տ'1Й?a6] 김XωZH}9j$\&VϳdCߗ_UAGfwzф$i gBZt&/W͇q鱠 Az#*v'Bl~&(:h/ʻ%WjC XE2 {KV-O "֒t;Spl(<?[B|؄Wxh2R62q(Y06x&_"Lobr$Xݼ7Op6λlp3!8Bm2woZ&ML@Y^Q;NUNxL^8 s,!Wrq2,Ri'-J*iA'$&86 ;C9xHK0Pφu_7_=-;J\X&ko˙s=UNn Bb3ج)F@VӔ ~+L{٦5I("V.|`08SguׇDH>hDR!B^ (eܽyܽ][.ŊRȭo̅+@!e]i\Yg>y]l:#sCr&QEd<ΰ qvΆ b9LDMNJ~Ѫ%aa!T̈́i|OΈ=`{rj;P5AڌWlaAߴk&!÷ڥ'$4K(HpJy%yϩmAxM (`򂭘M]er4S%Rz%Yr7B̘sMש/%ΪIBCa"͝y%GyggLE{Ȁ6bx{[1kNy&C<i$Kl|5$`.D8U]gvM<+={k絛|{an)\7wl kzG^6^wC}AQDޓ pwᥟ`0w6+ۋ;Vkueq'Y^n--7z@uzݵNۻƒ<`Y[v/X[doξK.]ܽC.O̝`Oa077ׅ a29>>>B[(00 S SWO%fD#yJ~SBJd5t)´pRS ;I־^F)B؅~ͿSV5h 7@G~Joo.[vjm&]][][tz $ D`/9@ <{p;@0{qOY 4KźJSjDZ]b/F!jQuƵҜ+3wIf׈FgA(o$/Q9%IDO>knn(> (vDD8 d!ݣ1qk|Qׂ0M\].#pqQ0/7vt{ssw+'ZjL3);ڍ`J$*1E9NסR끨#ÁQ7gsWB 2Lp |}6xf 7Fj qov&p&$pSl2.l4 (0HDU&t&n%ĝooЂLn]+ˀ`aTXq K%"ZWU]%׻dK픨̍;\!"~}6tNNZ\w-"}}6Q)S]3Ldi7 O"vD33Zѷc1PUi̡~g| 'K$*Zl.!NV,BF(g8ԳQ܁ZԢz.*kv}aImh7fJU4G; #%mU؁ +zUIՠtж,3C}wR#niH~3] i^W&LS@ 0H~o)S5;{.j+aP9Fih#6JTLp 6fHƬܒs,K\i8f,C^tHbOj9gc EnlHӼ ːlNvy=9Vo};OIl;Fq$YKfRٔTws^M14r+.\SSu ,1qoog^e/Tr_+Q:BP'Sn'/f}J؋ q o/:O3nrN 86;F ΋pTslf PPAb$PoE6@(eg@':]AFaCC+%hQ?Ґ(ǝͲziXQErdK ,|ϗ G}IM g|-%#6RMT yK64PnC03)8 pms$ Бv$kϫ v@) X&TFͯ垜^vbDב&un4yMb#q7.ZG_ϩ8T9έdڷIhF9Φ{Go^@r V)`E>`2-5t|oʏt ֚c&vU@YdIhy ?0x IIerm FhcEV4r>UହٗF[V6InX"Z"Z^( PM6^J̵Ćf(j:*0<$'J4)E<'*MBpB,ud8,<Bl"ZqC $"΄ VL|A0stM׵JI)͆{B(?7gSD>KxfdxMHC~LEE*x đpNP*wRu1"kCv" oX40 uyP CZcGQ<;6:ʱ6Xy~;~EP^A֞_;6He3DяCRj[- Q]y~yUd]Kh &Q!9%rWv_L8G'8.h6WX5,FIX!]\x_7QgBRMSVqd"L&=k-9;5iOvzw[ !y$ߨ?%Xgr͙eTsu,fHquJJs ȯo kMk A?0 GgZ,p#nīƜ9TUVЊ"N۵7L몽bXbU7Z@j?4$~hGUNnx6c({EU/7o;Hw\jڣ)@!2Mre{ICkt$ =X2ˈZl= -I3&Sk ѱB8H~[ϓi7[}P:4!r3}%-c@(m'5"q*'"AAk\.;(LlOUw Kl|_c Ew!avZLgkpW4y: A`bV*zK& M68Q,sco,$9κC;dԝ+<[xaIP8qoEJE<4s / ~0Y,ՃѻϲQcGAT&E7D(gu';fB6%^G@"в Q'@1:Ʌ4k+nfXzw[#$SXc'{Ʌ`(s&KG/o07VE!:,.%ѮڷhW_e0xx(εdmX.LqKvU1*ncvN+ ]O^VNl"cS@zvDN[og2wsiy.(i!*(Cj^W͝8l_L8oz&/yiMBUۼZW5İy\2tݗYp(UW,yO! _hI]h*,[;Hy^Lxj@MOK`}ADYkf)T7҃VuS؄/ w\[v;x+m<[4N`v|G]xm~G4{hAJ6[rt@vޖe8B!C]8x9dC 3gUH$[<ۆVsKڃMG:d#8eǖ\MA׳[&4Ԇ T5g)sĵ:/Ox& !y7M#4;7{Yã>d8]_Mv'͵~Fa mUM۸cSErz!u[y<4ԓөV{yV F}@vKOjLXXŌmO$S˴GBB`\d|"$J=-YeC.ȣA8 JP^*Bn*#8 4{@#6I<6 eG>١8m8K6=i"Vc#Fsp ݨ?6˸цDĺ7[{uiv.Jw\Q/6<P,lq]ag:fCPy_^]Xq'J@?1H߭wkevZ Efy[:=#OiCӧxI;]342*Lc6l|#ZlJmN`vM"z*@0@2 Gț >3܄;V)2:&WC:d2o+Vz8 Lp&߷lHqty}-N"IA%CMVI"EtBDˆr>{^Я.oV|*{ҋීc3^H>d"Fcj~CS8ԕt4ʕD Ώ4n@pg+fЗq'Edi^EO }z6P8d7AWu2ew[ )zrqqm7'aGlz[ vC)jPDL`vU&yC2dJM]l4MBt†X汖-dXCldrb»HԪ4ޣr.jܫ4;I$LX )y N, !V|ZF++ y+ȕhե|eRI@u|7ק%w%q3 ZU<7m/6i O$k;ҹz`MޱpW!QAk^*Vگ´|HDՒ(%'Tq-@}%k͵2yoNED{k"bDdOFmFո[Giay hq0php!1T-ohnh$TS`~E06f켱nm^ϡFD=eSUv_Âw5Mnis -@g8 隔"Bg;*ϺbD.ě19I0G܃\c!D[Pm앒SssJG6sF1v#^GFwqkoKBrG8< Yvf!HqĂ+( γI:,G|ُ[q8ܶ*qϐwfR&)ㅓkn8i3@Ɗg^]s5bI>_׆ ZF;fTʉDMoտVr YB~v]p OW#t%r+ƶW.Ph k .< 9dђ)3 ꠏݯi7F[ak`Cb 祖}B,F01-wU5<ʪ7qD)Aq)lNZ&ٷ3AAu TH~r#8iJL88yˣQ_흚gX#P7@)7qlђCs,ρh,J@mlև>Ȥvo#YEmm *ٜ=T_D/ya+]Ğ$p""_76cC+S{9y(c(M6@A$u"ohֹ-ux#^6GT{JljrjRܠ5\(x(e4<#jjd\4_@ey'KSIJi'f>(=$Y'wᾡ P%Qz "/)7P2w+okfcI&p:ҶFʲ۴ͶJ +j1y)K{qg]giDu'`dאj#8F%[qd*#\CD6j糳)8pu3Ag 8 oPB2 :J9U(BxCJ1 g7:qG*2 d%uQL*R'KlQFQraS }ymX3#O<,[-64v`ue?Y &Z~a~\fv]@/  5/)Vers:`TJ$2hʦ>󅇗w6J翍m =Š)pi亀]FkL]D1H%;v|f=vZ1;ڟ[h]Ŕtm& lӄ8dG+-7%k;i dLhM*+!>F-$AA˾};GG4̺ͧݮq-\,93t17& u`Uݪ'YzVɊ# j,[ Q00~1* >@ B{n"2;PȪ,ǭH2FE@ʢOiK2wX=8ID۔fa,Y"{ ]1%rlIU?Ig(-`xI/ZM4 t>~QW6)[nhk-Z &Yg[g93v ;*_w0gdv.+zpPly%{B'Ǔô,h|ZSxo# "Y`m@Ăo;6Ak%(@bI {'@vMBC!ŝy%Gy;?"EhDFQM&a"st}o{7NCk 8/ 1&`p0"@BOlg%BI$1cũ~uvotfmJWU_ݳŅ x鬅 }q2}K=EqyO@GGz瑿1X8!˻I{ZZZYYOz@uzݍ  NۻE/|n^qf͋;g]zIKW`!99vYiЌdD(%b,'Yڔh%N"R#3 LOaRz[ Ype&|cdO '!B3 I+HM9CU4c۝!ntAٞ$kXB"$ Xrdb ' %#Ӆ bS8<q.+(}QdFIw=Gqs}2Nx"J8[`j{pp/bWpny2[;M>SC~bP;\;Cgñ|}* B)(VPvKL4J־TDѸA('fQԘ!ѣ4GYqh̀X_+AY* SCo"Rٮ[;0.+H"(.`n( F}eAG>|<(T}jS$c byIAή]ˍO &Ja$hP|y0}C-tXq[3e7 耸hVY4><~0]~rX,uʎ~5 xښ gLBxj< ٕy0no,-Z[R[;ƅF= ^t ^D8:{ ݃B o=+9)|L<dͷ $O&#ͦ)Td-s07"f~0;x|ڿ68Pi;{1;xVkX.P4W e6DX؁:Pv\FYKB\~]n$kܤ!0,9P̅9 S4s KA7mX:empP2Éi]Ӥ(H6m™[2Ph"ȧ-y(@$>@]Im$lJLUY h EJTNsfEɂ+i9-d0Ixs]%CdUy_ȳ3*rʦAZh#zeTn'vLz'Yۭ Fz04c6SW<~Y{Ue8U1"bܪ d#dUb,t8U6˦ $z_6á>MY5T}ƣ3xoLpYvKePȄ0AyYv5&$9eU]ѠP@KNJN=5Ü;gf'wNV[Wrd>{C3Y%d f.w߂9{#h)λVz@JOIWO,L7@൅BI-9HE+EI VC<qr"GUs}؁g%H1ET3$+뎝\s܊G0E]y k]@^nyu&9ЊS ta2A&D-+"2]̫V<|ԂƇrk Qqy uP,繄6DJ~>ϰjss64HV18 ǭ 1 3$\Di6ФEbᙌ[ڋ*KV<4.i! `>WM{E6@X8pKzZ('8-#Nm'`x&pRv* {`qnOȇV#_iQ8r{'Mt 쀂" \DwU)ϗ;' g2`;ﵺˮv85rÒ3лYo!ge]i֍3*P#lbԼ),?^ߐ3oL\|*DǴdЯC6<ؓ q^<Ϊe.@&w!ԚйVuP;0Ayy9Y`zz P(5cЈqмĊ&S Ya4ix;rC?$Ng7*1 rq6X'u!h5mm+r a&+"y |h MDh׆(oAĒ$(t02XM{tWBADz؁`Dlcv,*p"9ªOoI! `[a¹Fx(\@'L`x&8Y2QE <HoQ*o~7ned啓${IKv Y۪ynTA)ܠ k$H2jܪ-8I2/;d3_4 PѸUD`d76WRr}[H#OJתwR!9%]q=a4pahh/&x,NMD@.e6.ꠂA?2dZ˾† 7nPv bM$ŭһ&49]MG=Ū4r P< q:rK1b(>J#9JF`8@:d.1m2 4{Fv=oMew K)DN0($}x΅d,?emcҸEbCu=)YUnEEIv esX*[HM2zU!GF|8_gTk)0vfI .p }NYrS&񼏬2?6ܫp=Y;Qc$p@}n9jlGJYu T6ט]WIouHƆƈ vR7$A*3ct&.UaeGp&K`܋}1&-ٔ㼹-:h9 bLBk^hˑI9=ˏZ5"*""!"É"JJD Tf3D璵W3 IDm'D)ct;$ew]o.F@zY>PIdX qe^'PA4eˈʫ~sל!L|]G2Bk *&OUh*VIz*ՄElӬdDMpt;BaXYY@(D_%kL .h{@z?`u= 6[ b}_Qrr'kUnO J^M%wZ5<%0oSS ξ. #ϞLuh]B'\CuNKlǜ:VFX'pqK@Y85q{{&o4o&:,)hDDe)7V3ؔљ jT@'koj87cZН[}pZȝbO|^;L z_ xa-{hqy}'ų⊂mG+Dݸl I0F( .mծxE 2'N!ڋьW3e"DNKEH{A ܈$AaS)<.ͦh+RRQ=@l%Lq|)k GRqTI~<'@t|vI9[BDBg64!Bhچw=y}hT ԋl"x8TdPFҵHL^EªGDB5НVӚe6Uc|;p!Տ#>=`^A֮\7@LY &dq"x!ki@p3  _T4 Ǣu*>&s_b3QL>p_I+'bאsXиh UHRxKe҈+Ɗ\>$ru"в;ljT4Q#k\8W-Xp nzK׸mwqܰ7d8Wkj]L[x>fO&52%j%ZLb: eU?QzI}5d d8;pl}DM_X0+xʞyPJ-WGy>t ڳ*emCB#Pծ dBҏ#Aoyqnb :KLO_a3tF 8-78Ylxjs7)27,%*G^o?`xg4d]Xѷ&!ZOQ+EBrСT(E!*n uHae6o. ed=h":f\`JKj$,$"sĴh 6@!H!ZvH/#" *;h l"4BlH*K&S, bW6Pr媷hn+AʣCg/L*~f q vqalPqw8٬TtNv腋0HfTGStdmP]3 Eq#wU ]i(/ p1Nk&NZC/trvq"IGZ$GIFZ9{ʱo4rQZ>;; #}#Im%pٺlj^pD{zM'0I_j4"F{G*4= 9Ý&!'HIwVT:oKm-s_4`d~bS}3)mrcJU Nb2gQs@/W}e$|~ѹYP5(,iYY[p6z DBPvNP& U Ǭ`VkSeO%9Yǁ'({0 "bJuqbyj"![,hS7A5\] )ADn Vh."tZD{fufn!@ߵJ h#ҩ@7?g_F֮`$w fvW[P%o=yrVai GMϮXם<: y<T6a>zتL&Xa_FdJpnuȋѯ=<ժ')xE'闌6 {'>}8PP>YDƝo5za8!"ңU."D![,8OMCh ]Ipj+{0fim64H!1boG9Bւ)@^ eqk˦kMɘő׉F}r@@jBs^as܊$|80u,%kPa[gL^+vTw'q t}}*F\&z*xnn;1[Pc'"5kBB-c>{) $=$KlV}S E:P@@^NsC^j(wp~fH$6@1Ӏl <-Gnzꬥ LC"A~ P~਩( OG %ecwf-i5u;Hlb_5"2nm)2zͨAnbz'>ZX4lc4-frW?j죆=dgPLD3h)q0O+{BFo |Ԡse6<85MqdZu6oKʨx{&[gA,P6 yٖLZ{͝{tQ/cG=((Ů߇gPn7({ =7/+±aQ)3]F3%WPr^k m'JFvM-Ǖk 1Z`821& ʕ $ؐr5zh(GK9}Y;^|(h6;5;gO\4A$<.;= .rpL8wV8Rip:qVw3kdW: J4P\羳h! dH7_/NlnH&S xrJA="GסB*uZU:` R݉*BqݑBmMAR NR[2bibhQYfDŽЗp4iGJv?{6sХU4Jn:qW7 7ilIAPDssA7a#퐽4lIC孁S xn/gX fEBvI5{*{t8E 9=s`9zVw@?Vv]P@dN`]#U +()̊E܎!y N4NfpF_!y N,0hX8*1B6 rO :ٟ62>,cHnBC"ŝi$GugwV/"1Lfͮ\?9tYtw:nDuk{JS:@t.;ھŷS5@!@_t G)~ 4G€lNh{[-?ކ$`Hù8XIsp%|Y?B>=9~e=&Ht#N{}ӹz}]!=o[4d$`B2N5@reNrba7[@ITll *%{8 hCHM1Mrֳe0!bgpx\ dȍ_ T]v-H ìZ=[g1]ˉdzג۬i0 @ &8Es?5L$;5b :v Q0  Q\&@`+2-Pʄn|@a1Қ mq"[3q p^x2fH0?2תZ)Ł &a23{MCYP[d(l0Ȅ|$Ad[l 8kOt/Y5Sq"хC,w@C`?+dDj'DV[jOp#kF6v&cSK8<9<=H>g晧@̦H<-I8MT,jC%X;YbN [B\n.Jd]}&у`(FoZ.C5=Y- Q4Xx\tm~sR|щ"Ιh2^$.Z=Su?/[q'QS(pUڽ Qo4Ȇ_<0/QuDb n.g0橱`)G3ƺ~{bz s4/lꙿzhns(ġnNf4Dk-.lwֲB&NdM{P R!z,!m[")NtnHDBLBR6iiędH̩gYkBFנ50ZC1=l>ETb1BDGX$Z)V IJos!@#d(bh TvAH>xKYug0[N D6Z$DOv!Jf"[#_s1&7E`q,v̢cF$U@+ R$^4'*D2G&x4vAA<DkY).30L$ 0"gf0OD\Aκ0ő)DDU:vbdzrh֮qLSC:v̺3"dD\!^S"zaE&:)O.wDl@ ثHr .XA?a O:GCd8HзIE1 mV8_!ko+FoLpn=\h-.eRu!9S7Z)CJ{>q'Kdn/Ь5!8 ū#TWEG=TRxDK ͞#$=d@ z0tT sYt`D#GNGIy2jѺ#B_׹ K>„Bpp]x Nen D >=4S.шF@NJfXRc 1ܣroRje.R&Eo|W5 1;`y֛]A ~ы&ܝЖ'`ƲH_8%p].b2R>mD#2A;prwl=É1p s!4Sn8߹4  0*qV99[#4b,(\EEOMWjSX+JMZgA1YkPBnPX?z8d& 8DRB aֶ%L',MqJV43M& 5 N g(҉E 0YlwS`6#:txi}Q@>#Vg Y"$āC\k]|{LV2 ЄH ȀQ&I5;RBtQ"۷~h"4$$q4#t"5@O"@@aXEBX"jMZ۫M=bCOKz .T pLт9Ia0If% \p }ZrW>Vs}_u XB7; J {MgX̰ 8Q^ Iz$ow\^WD@Eqwj"B`~K;| l %ew0CaQn壔h[l;LD(i Zİ@+圈f/e]:pfN=8!EraToݳ΋r]i.0W>K`PUnsY+ ]`H  ++wOr n 44a V?c]57;\Ptr.:L7Z̀мӅ#A03 =B)fz0`cA A SR}pA!p.6(o'(']PNs*< =6yW'; LX[UHZw y7Y{;zli ZAА&кH-:)Z!OX#ʗg?bpNl-[h40Y/ 6@E#c<ĄB]2oWw)ńdc8 QYvէ,ԇɩ4aM$jq9eg}e.YDژx?Y5QI<ٹ\DrzSy[wީчHBn UzkﭞpO(vA.-6F<%fDf()Տò SPBDϡK̷LLAnsagp&RgN.xT:NYNL;)%PuJI 80S=@96 Ix ;ÁH`@!lM,g(P.֐RϊO"gjknx q'Y{um9̏#~$HJǰazy∕ߌ>#JqvZ1!{@.O8j(|$sqkh|ϩX.?R6=gRm4fʯe0,tw'ܺ`欢`4IUIFݑDƶ NJ|Qȁ@VPց;o@'[hu*!b:Em sWp&[o¡/d_N0x4 ^82 YG$à 7P=݊'s@`峅u*'b,6ܡKybCdџ @g﫷U.&kɜmob$Rh<R3-Zl>J- ["64WRL"К(M`JDQfeMX_hÊPb. ("kKW 2КOԔ{jMYH\9]ɉ7Cܕ,oj 4'LD!kr!Ffg#^`q=rLpfN=^4ȳ4-'QCAI>$k%S*$5sw5pn|e}3Q\֑,׫UνY^j6r.) #8Y&~C͙8T :_Lo(,oUr}V(ļxT|>(7 2i)DEccc!p2kO)yktj\N \jC/‹lpJz3=B\JnDrxe;59XDNZm&:Tu4[h.i2xWktnDկM[LL3_Oq8j3_*1{b =5P>G[x!BpD N7P.S5"!ӀFlwjLiHmsk4i}pQt$03EzdR:=,.`EXロ^A>I>Oty^Y=,/r[zIBO&kr ( NOph.8HdXY+3@&{ӠtB^03^3Ἂ}'!kV@ m`?qck 5m^@\S㣆A`O8<#_'7]L9%yN P3DUɗߺ47Civ! t z|`?흨4z&DD3 ֯@0崌DԚp-`1)ݿ5+^IH{XqI)Xnw %lh"k !Z@0a}Ӿ! ~)@݄DoCT蜜Yd{%̩H60O0m=߅i2Oiѷi(6Rfց O*ՓoҺ2O:6JbEc tIln3d e[NCzos;7*Eexߝ^6Oq)ImpS9;P3IQI;Q&\Bܹ;K]ZFzptp:8͘F?_ѯ߰ ^]~LDn3NqIWFvF}^"f{[8&CNąݞpF}B ڽ8]>UE)-=}\DM.p\xU=Esv51=`7Mq#, l溫sa l LʴODyb{?DO k7ŊUጕt`ˊp64zdm.4Pn[FUm{ NBv e';ފ6du6NEZ>\saoZ3QDަˑgP NNB3*CRf W!"#-I>NH^b=6"IB0(@:v!q W!=ۨ"#g"(4'I%QJ: ,Ty[V$nF!d [gjV;q+ !Pp2CAϸ C((F(y9}0)^^k3i}SNz84JJ5.WLCHݩԄ;tK^W^( $Y"9CTKipy:)=uFBOQ-D$JʨbCb';0(ڸJOlA~.m *jbCRRv THEAAןBI; Y:ع)#֪]e'ur&ڌ9vIW&x&8$2U8Tk2ͮ'%ݠ +&r qu)U%  j0(Ba"6eB֚rހ`F#y@bV|96z1Kߙ6g.L| f/A^-|ѾڐO6 d.P D̦x"7@u Fa=°f .C0Ǒ+'\6Pށ '|=bX,$J_qcs^`T(DRˣ9{nѧɛ* k f%^ygm|XhR{Ԑv $9 Ju5~ls7VU; e5bwJR.vbmc>Q/1xu8ETܐ ͞%2u)\ulphi#p9͎oi0GUBC!͝ydGyǻnF$Q.ׯ=؀f}pCl< ,`"!p"VAB吢\HQwtMվꆕ5k絛N,~y }=KXCd&ߙLzʫ8d(ax\]?Z`RwHkuk{NV[rsI/9p٥I^%u.uutK^/ ݻr3=m+HO{DKMW'7Np@I@}v (0L:VA՜}HnS$4]G‡M֞mA iv\l {lOH<{x!꧟~ڄRs@!4ZZ2頖zҠG>^st{v.JzRw\rn7tK:ieR춅Q|݆Tń TO\'%s g4*[|7MiB&gNfd&PQ`Z31a0 h!Hڣ8V Lw1qhFFiLqT4- h.ty^vY M䍖~gisdiۭr{nyHf ztu+a m`0,' Ն4{r% u3jli\r RR?tm+I.!k!&-Ҡl4Gqz<(V@j/"ko=(8 Uqf3kCCmYP@0Aa"kA}!>@ЛaRyLAa']x/PیEsٔPVؑ}|4b4aTgϺ &%1Aş>]O|Lb/c0"L) 1*孛||8^yW*\(.VFs-cHxTl;H:)܃[k y7FSg^q'lI@COa97FR Dfn9^(@LW/ qXsJ .\n  p)rg }:EcwJ*,ǹL蝄%%iH!LsUv _r2NHADV瑵kl@BO8|, Ry/H@  `a2_ dU9n0Y d 6qT\ 8 UlSMߑo)0Z±%_Ss8E6PJqh(4ѿ1TA`p3JSl&"4\|V$-=P> rp"34RgY!A D/g۸dޕ3 MԩH}Cg%iyyVGtU5a VuvI$  w>]jjq' Qm ZUnTd eugA(CA^b[:"dU640/8L8{,p|8a`58w/P<:N݃<rh%kk9xţVu@cVMRsDihT{aʽ:ScδhLUѸPCv$! aΪCLD^)'T8dR-uLAb:}Sd  vn0vt[ ;瓵lXF'ۅ7[bOq/\Cjp*M7AqTv:묮DY;Ge֖K+n v!"7DcSly5Y;j#5@{ 1_Y^,Hoss>g#U"E~%󬢊p_"_r1Nz=a}ssH apm%p.%e7N8pZκ}Kq࠾m!qQCq<$I^Q{wT0P K'GueEXCOhݙVH.e"MG"ڛU »:}*Tw6t*kG J=L@e ?V*͐D)iu&$Oj4}$vUd% ˰ */q@r, i4˚X$ yt5v тqUpp~'p6T'9"Yݺd6Da ʁ'L@)m$=.Z!I]2oz $[o nn'Ī]1Β>|"=_T˝\|RS>YJ#19a餃jilpt{PzJܩNmU"8tg sI}dV8(D=i*$f&kPE.`!BbCNKVLs%Y(NLHgfeqf(O0=u \V` {1 fE I If S QJhbS$ bօ]7CY,gțܒ$:uICVI`jpuk9; PE47wF*MHq4n-lJ]sB&c. c#,||8U+ZoPc\]G' >QiҝHVKE>iSNY̧iXѱ)4S!JFu:v*tZ2ty|&32k,̏FCxKf#4ڏ2eg9N9{8P\TĮ[A"T8,eh9kx R(] ƃJr!' O~@HL.%kcX|:N H;YƊFf2-5\M>aZ7zeWf~ޕ'P"YׂRk[wOvS+Rst˝oj3gh8HL }`eq/=B),;Nq8tYFTxu=X{-}V8b \ddAPn7FAdxjͳS= 9sc{{{>dÜ=+*V^~[](N>ySV&Zut[m M$$RH+mBVM1}u@?k17 IMBzIKb87]iC#Ӹ;sɪ)8Mp-1nBIE >}ɮ0b,\#]GyեM=A=NW Q bP߱)bhK?IBL(RTw)ZqF$H:Z۔hÑe.DV 56T%kc8%έiV\NS:&!Zl} waWJQjaoR(%_n4#1vq JG+YurA[uV})O [}nS:#I:Wx؆&fDž8]S >HEBΑ+Xm QwL#Vz#6׾g8E7`$Ӭ:#HF'9w#Ŋ T);SHw|̟g"EFÉ_@F$sX~F>kƷpqՇn9DCWzŴDʘ)T..vw!s0Kw' C5gz?>b[4#&a\TtY>>#:e5>ӜJx"N ɟZΟpsỲxRH¶5ϯYp@=E[wHDBB־fI!NB."#j[*&;IG߽֙"Fy} >A,zBňeQ3VƟLz*qe`&~KdK`.[4*v[8#eS-k]3~:㱖f MDʇ ( |0& zsE"|Vq|V8+.qLCU9@Xy(2Z@DP:@z 쉮`SǛ4ҙ< V:!N gͱ ϱ>dVDI@,D@ndH6{ʲQQӏ:]A^e{b#ăxQfns1!gW{(ݪmA7)G@gc|І)Qv`êNh!+_+{mgړ?X91ч†):ԭ;9\Q*ݚ4 P$u76zÑ[MCyprpQQhV,=BӼ{ N+3$>JOS| ^@_Q9iu-h#&zh7Su@ ?1m"o?O/x&P@{u=& F$AE@] #:}%w }햫npPW) ƣ@apH8yp0!,lhܕA1aAMd?{mfOE,\6Yx'a[r ۆAM^fO=~oq *P3MOɗkLiPGm;tV݃Ǔu8N>VŔS;?!m=|IK9/_QJB>*y$ʒ3aZ]k&>= @V4n~ݫx6AfhϳoCKx\-D:GNZ pD &54<W։:F H3G!\xԋL< ]yQt!t4Yu/Q\M&C\F>`܃w uDtT'bII?Ӹ:묟 guRF;Q9GC78"9nxKLsU WtWgn4~ɗ8C*'*rl6J #U) +;xpfD? sԘ(V{,v%Wn ?2N_:VJҋGV8UGs~1ܨ4꿐oc;ǀOĵdeO@psVL+D玸RvP3tbjq]땼6}m;m0E.p*նc4oa? "zEelNs˒>-6,'}]lk?b:5}Б=˪1& ow HMgmgM>2&0x$9أSF6Hx.H d%H*íZqhQ $L=]m9S(il5H4@ R8W+_\w*w!A'qa׭䃐iXAvՐ8J_/z&3y+a$g$>A%˟&8SkadD0 Тb$:dBf?'Z$0=iL@ ֱƂݔkX",/4fRޕ,mJF [ 9l Qx(q6b`ل/8ghY Q){ǼfI"HBms3. =y8f&+l>(ue35)Bn6y$ԼQdUr1JǑlжܠ'.}1ilb_<7W&Gi7:5͘+c `y$Kw@6A"5)oY'BqevdT\aם;&s1Q!aA[t2Щ#b2zh3(')X qO$ؼ7]ccaL8?J{A-7 ŕ @PgNFt&N}Cg[bP=$tO;LOXJ@S)hHMIk /OaV GhPe)Ldɠ/UKǭg x9Y>[c eI+imŨYЃRN6f1Vb ,FS xYuuxΞQ;bu f 6'\f;BC6!͝ eWY{zZK-xV:LH:YLyL[قDnlDd*vbYT(@$5PHXBs=ݳ=aR障TuW\+oڷ/,Gyhz/A=!Dq|8w98~XŅ^6[v{e3\]oN}nn_nw5L:[vvrW_un5u}׶]־'oQÅH:7vG/,|U$=V,>c~B4ϳf`rd/僦(~@N,p(\r[\MaT|)L8d0pAs˔dh|ڔ&D Mb%۪ aEU2!a1 Nw?d PvݿHPx]09ѳ4)lg4UiS 舑A{k pV)߇37h7'k7E<ƃm53(P<4$w2Y;g yh Ϙܯ\m%l֭S3%d$  (J 5b hA@Nk fND/1%'D /:!^ϮtԂRM1LS(Fl=jb~a Uk4VWkjNvkJsټn6[᫮>|͡} ai$W6+ۇ!B HP!qasrzLwOv SfR_M*3΍׊)mSJ kOӳi=WLNg ξcXtY;fEgysmF k8db#PJ@A4#kwX@< DMJ0AP$*3r/&ko!nM+QJ$9НdV@=yrWl Tp9͛GlhXT絅ʈLn'saz ra?* ʈ*?FD&k9gbzz'*Wu@`N1nL+D085uU&ݬBNE1/1%(%2$ * t'4/y1Mɇ*)3 yDDJSǢ g'="'q)D0G_P,B©o IA{BbwвD^YF4$n\vIDQJxh^V7?2NfQ83shVk| ΆC8^qJ$&k_6N.skݵ|RVA=Ws!k_1Nfy2` +RsRs -OdnyuE@k.6Wn ʭhT#8}OCS"}j{{}Qܗ Z`ECh4 FqC܅Е\.#kWPsJdeEyӾ*YШiMJ dcC13iVI\.Դ)%B kbE$f"\,-<%&a"kO ? jEֹFHU;1ܷR,HڮwQ?Sr9L^lAH,FGړƈ6-%%LqR&(2 4;h(!Cpv% =0Z*&_a8A$!1QqefVu+ѻ^=7 U'Cm 2rY-iL_&Rc2zxAB۴zwP=LwMqH0xha"{62A'Ax7PO>ƉT^ 3KsTKe\ !2EJ8=}8CtԷۜY$K S#ʿ6s'qX@;UĻ޷#kD D C a'Yq%稓ъU ,_v/}t^ݐBa hC0 J͝:H+FMĝ,uTIh Z.Hfaz¾>z~UP (sN djpDrz "@@q' zխK֞gefDBQ yr䟪i 4cݦI:@sQu<@x+Η*|gsyXსK^aɀw D|%eZuBi)S,¤;Dk%FAOTleM53N)P ݊CK957gIjGL4׆C򹺗,xӬ–︊h22nS(#m$"5Z7 ,U*hQ.Ϻ&%(@~\L{gJbU;U0Ye"Qγ"L]W\iLgM.CWx"Zӊfdָ?nj-84d 8nď dH'ڎTN ~ۆFѹ%8yJVY#ե~8jLùm ,wp05)۷}F(/JMc4*j[dh{eXpR(b ,<]!Y(lj`Ӹj|mz2 6|2"sHٞeuOpA/i;=a s: GHȂQ0Qpsa,x1A(lI8냉k *jo&s1QEl864Yq}t"*TY GQ$v:,蘾C>mƩ{Kq/E/]{rh(΁`,8B23 {VwES:vy9z %GP# Lq&.'!N>ڟf 3+Z=.jі4ZMj/ (5#8VCub;:*TwzM+~4(i@:3Hn{C:( >WHcbVEDWzR{ k! AoCYXL0J UG@JhA4ҦJ)G.ClH̕Dq!Mۉx0hI/T$K6sbO,>@Ԇ) ۰W! 'Nf%G|o4 cC6իwÁ6Ty#pMnrU9ΩU8nqJg21o04NQ fЅ /"9JG]Ў9׭,Vy edժ{)Mwa'è}K׋4/]]y\Mc qcS IO؋r{KY8]ԷUq$ќq,@꣰g:Nֳ+חS3Dď٤-MRk*P:>A^%p,%eNj i7RvOd 7ՂK{ tn0\ysLj6p`NA tn 6,#VyP9G6Pݵd3b\pԸH:> /㬺)x#-d6DPZv)¤U("bt+{)4`RF JCIAcNF_!s1ͱ̣7.F[D6 XO ׼8Վu ,4tK2x م k1n?{sV1Mַ$-$Rr YI !Ev.6R)E%Qqp9ӽ%mf~&#pct",]FN()vUXwDB$>,S]LZ ^9ۺӎ54D@t#1p^Qnԝ'}͟0 ZY+gLJ܂= )Q+ǔ#bMv]4I6fe)TuŚAְ1}*Ϋ~]j,,תG^ 19Q*H4.:>{Ц]\DtԪ.#JkrՀtZ`!8`8+и4H{Hmϗ0߆)p/"g~0:.I>fݴ8ک4 %I"Z143{q&UTh FsQ'k)*^b3?X+GP_RSA bù i|(H/SZ7H|ӫAI|s\Yr w`AjM Z))|5 W<3U %kK"(_JpPhNT{]O4o/HsXe)ռ lPѴl H\&(C7_)A8gKpIܚu?-A$! HY4ջ,}:Y-̤RaXsXgKhSǓ+lhJ8"qOT4 "llZ_@|0iRr*4Y.utWKn%kϷ@Ե-:us 46~堤kt틭PċagNrD(9 mR+t%'(tvy @ QI~KMW` o%[d6(RS.ԯ gLHQ/.ѸfgH903eplzJM%OK#t!f5Q'uPK/ߦGza6@7 Ձ|ɂ:W14|zi:tpA,Aw"?bժQzsK=#C~}ڸqԮ[òɾOc~>3&La>H ;ʬ۲Un T5mǙhNLEsՕpAيFrDsHA =#?pt NR]&Shw!;m6$6PلlL@/6l2[X8q ʮPqv3.eg8j+ Y%Ys6j w@l0M#M7<(: "kŞZ\N,iTDoᑚs2ps~Y{M,>x<5pV*d|N$e;dm6PưT漃G'`TFSw.uB0OZ0 .(qmo)OgWĪ:+-赭;'Y HYCqj.`؂%'KKV| } :ғ-ՉyNo (P al$4)6jW@|%Q^v>B  \htI7-V %{@o߯izM@}M?[l8uE/8PZtȩs:dƙD5P#isI6I ǨcLU3.VNIc`5u-9e*yP$fɞ`}$|ctphU}K 03K%{\${ Rk Ъ&{j"gk @1{ʲ;rbApK˱6=ɓXu2J҂k?f{U?&AOر9f_v'i7`uАNJ+h##+qr fDi:F0jA`.גw6pޜQP* Rrdn+$Xm5`ѻ=6D4 QA1kVrp}ӂ(3-!vrzɕ/"_24N2u<^` !ewRz=hMUo ٰ_6E''nt P8mz.Vp`d+?/yq&tD؛ kfφp҇QqiF@W-r_o4bz hsI:X:_DK{@ ##(Mb!kemы! )pknեU .U.wt CURahm  9G){B&t)UQ!0ǂuh i*U;Dw8 ϒyqpMY{i9{;\qL($^ :)SJQ sxG8s3w%6 Gl>:"ᐧz=E@j!`UF7[J"L$kړloW%Y!5ѥV^JƃT}(+xhZ엟vV#^:_P3`E%˘OxAj.Hi6患> [K^m|5m +i';CƗY'g?dwʗ|o9wmbAggsáel^R'0-;C\bZ A>=D9[d IEh4%G1P 0㬹R7wAA;bњUt] hӅfvch/@rPl#RR#:0AH^^*ΦY*N8fO] _CJ@cU^D<\/">SX>tsr"L0@o̦6\#IUı6L/y>ް@0z$@ϻ\BC"͝ydGy{g' q)z2ؽk:6uxq@!0  D\!"a1H r PPpޫׯռ+{.KWU_%Z]zIq k Pzs$warw >yڣjhUo֚쭭vӹt'^~+ޕ^{]ֹw];}՛ݕ'u\}Uwqt!EǺ_?>Etgz#~V4L͙~,:r/uÔsY$k2t$?'(UVEy@γڋp-C'^oζU( H>:bkEEHuս0}Rs{8'HDo'k7! DsE[=d#F0aH/gTsl3$_ȇ~ s8'8^t'_}E9J?ڻsY?%\W|˟xv:坎tNq>DXY8 lq,ΧȗK psl-۰8@H~j|-eQ%NQF'|A+ hz,Pq۰wUdٚ cn+KCNHgy hQ>œrfP!P`.3.-:d&Y4isC7iE )ϰt~uiH' Hg<9S@CΖ!,+'ю="xx "T d"CPFSpV6|]P7ЩJ@3 xgsdje=m&`&-8kzc܎ۻNH<~Ɉ\ A TC3N ը BJ(Eg"NLM#Ot}Uudv"!x( ly'@4 3R|?x:1r$lTYUԅ;<@hEQiP}|K{ڈ3i^ z^AP: yAI4D'=uF[o;ۍfԮ6ڕx  }WiXK;tBl,kyS5<3Cź_q.gK'q% g*t_-I(t":B&&IE'@:w$WO֎G)gE"d헌`H}8+\XI 7D7 |A<,Y>Fg@Gj"MۦA"(H 1LB1xojCz7 1 PT09Xz@.눾B>Ukb#b\h(C&4(sǿFd4A4Mf Dďs#* Q9OI˻h1:\)8o) UrZ-o.,W)I"EIOmMBUp#E"Q˰}u]n=&ܙ5)uOoRb߆>^e=&)dM˱`˧.ח-<a?-P^N^c"]ens'sRڨ J>hP2ג;Ldl~Po6ISi}l {LLqNx XttY{ /|x8^+:$k0} xN( -ohdMK#!k^1LD]楪]&oϹtȉ|iLv}/|JAx5v kDT?]Fc^_sDpm7ЮrUnzDx|_eʶҿyCi&War84{qh`b"LN hs쒟!Wӕo.`D蚨{z*ӽrDFh4!u` iCFuF ӵh#}J;Ú+{M-q&8o'il%Lj9W}"Y4;Fe^hLp"Nm:n:ºHÔɩSQN&-&8.,NgVÚoDh-'E5HnQ(^En3ۄ3J֔"]v!'he'҇<J $5i/<.Gut8_7* ظUkb2D,FM*n̫XYI.dQdKCS7"̺ PO#z5 j߼ RnLC$( ۶aPDԜ@Hw9V$PlX%_T]w?][hȕ Jݫt _HBcI$f4_)pUov嶟0RdGuj@@0C,jӢ@UA -d&P(mf"IjWVl -6Y3r^uzlC5Q霻87xP gDM8IV=p/D2i"Dh( (L. K!6Y/c6JqV)ujb-ז͈PB6W'Q@("3g=ƙPzȦB\ӫH$I}k|o&|(nQt@>vN:ssIJ QVhgrG/nGІm`YӨ1Sx P˺xVS5poyO<}`Hh"VDd#PX[ Zj~^\GD?2 cC1G]Yx&9|IO.;ba/^Xfx]YxƓ?LoxqB>6ѽ@a# (WP:[='WW S㈱Dٱ+"*lY6 rR:q:x#.bh툑=fL:ͽsRq縏Z(kupXLVEd5ѧR!YMv S/ C?{@T'>Y[|Wc\#uw,W Wx Y{ /6(iڦ9ONn@9짏-,X<ݼ#˽v4 ABퟻ 4YMA@VB>1%ZqI&"7 c<9_χR=%b,E}q;ZE*4$M >\J֮0 Y?4,iΜ*LhL6 JS&ñSeI~ =)di4#zArY%b =0@ Z f ^#N=ICL% Pn&k'ՒNuw>tYvC);@=ÈGzhZVL4}B<\y.fk'kfBBG)K(r"4 H&`q&Ce:>Td3,Xz2q0u0I 'Bo@(_4Z1QIfZiW[?(؀0`>?)q4즓zXGM+`wȈ8e4{u2_-eC<8-{btOfuD'DP,:hj M DDB7kM\ 8:L&ô}2jmOD-Qw140-[;dwJ2]B BgĥzS_۬klV.胠 8(9[&`bIʵkQI : vi?CUN9dKI2[pN#ȑqzF Mt>8M\ڍ#{?j27d,Ϯ]\B]Đ]o`.)|gguxmA?)xQ9H?xcd)]? 7rCШk~ ]bij23T%reY}`?ʙ3Q@7j65{dIcB#w54S=wy+DY&?Հ |O@RluW&bJ~$M;Wtѭ 7 (3vU!uOdžb$A6oUu:ţWn2a_eHDdI&SJb3 ȆtPf8^S) V ^UTT8XIáoʗ~x 0d竄Sg3R>horJJ3|v.opK/94 oXLcgȗėE䎗B3TҊƛQ4B*MdFpRxh یZS3c)?&_h%v4IobCsAL$O#۷E>jNNGD_(=1BHZ6BQcVgii͏|t~UdKH=2 mGb.f}=@sF?/)xPY@E@IFg dtQ?c' U k*Drk*u&D@2uJװҗNDJp)"aiӊMUwA'αtȾStyx@q))D@:@HV<NvUw6[DN&|δA=̧չͦ$ 0z_h|9<Tڴ'sd w({sJ߳ .7J"";!GBp(]e}:<=C;~f`'iwY\ Kxι쭓+ Ü8~}UQ97^ʩ6N|MOfD6.-B2LlPIU?_3ϨfyՀ֌scRAs.0Uۉ`r:fuUY #ݽ?1tT%2Qx.Dj)/iƚY'Xi?bJЕ IWY}.gwp SXsPz1Y{ M7hCER!\%DJJ"ח=Vy&MDJ+Iքh^ddɞV' #,یjHLجQXÃduv 8yD$T4%&ܙ|$kwK;/ӰU5.× њS;M-Ȓ˭^˶P.-AG38Y B/Sh͎*oS2}ɅQB{i`08ˤT_5#[=(S|ܨ%1(SOg;6nv)әe7{ҋPxW.]%&k1zC)ݦ}/DX*OidTq $/QLKT;[~2V ,$H+iӲAa$U2 b?,+W0>[bWD9ID=Jv#VdD_NԄ(d*DJTq:00Y\Hsch]'Q TnG&LPLOR,eƄ; Ru "C-D4SrԼy'% w!Y(EHN(UB!l<}ٺ&dRZ~oغ~8+;vvLj0=QyVG gNzDnco)e8b/KzS'e:ZQyV0D& bMMeT=h0ރ1puhaO ho<"H^~^Ɇew$Wo[<}`)Mra{ب>YCt@z+t)L2A\58J<}TvU-CH=Zj  φm\[[ݣK~&:?u;%W#A.tց6|̨DZmCJiT~S]L v)!&/`ժ۲ީ>~[;]i5j- g] g5~#%$nPք(E}H0I"#]^ߩx' @J}zpuGYx6}EpLFYz YC!W[ 0ʝ kMpƥ0VMml}V+!br"mI(5"pфH9:ײ` :pYv=Iy-I(.#'gV2pY L d2wuJ% 怍Cg0Td/όnM%ǫЪqN_Ь;W&.z|sJ76!_tֈFCj(%t3=MӖ|KRXnL>F 1˖DMDjϰ:dԲG@ .Sǐ,a9=4-gBaag$J\͑jԾh1pl[ "9Cj ŧn HNШ GD=PD0e~ҡ3ku&#ML:Yxיt0P#5/ɍ~՛˄ Y ࢙xM@ae}Rv"MDply"~#=`Lt % YDazMtnP oEY!<+i$sQj;1,W'vw{#qo=\G>~zt:NGPG8#:].3$BГ = }J( ez?>j'ѱ x틚8.@q\03spmCx. $pچ*0FSm$7䑪 !@Q8 f4__3~ܥ 79Ft{ Jss{mXj76 8Q0>|ɮFFҮMo坃D ٽ\wXӖ_ٙgCm4o8 $H$B a]מc8jFp[zvǡ #By^ل!δAg8aQvSO縖i{^Մi+Μ2( (kkEU{b(H_ކl#>F~ZT2)ڇLhB;tJʜ:iȩ%apXі݋1YpPM'͖E0}>KSoM7{1W+m[Hn㸌C@9N.=.sB<_rv 0~#QfAf NlO畮&7Rdl t=S)TGK~_'q g q>  ET5 ZhO6@qGOO|,NIc8UFm78bclF|pZb\>W?Y ~5D8D rkE-$p1}—+hx]nOi]Ӥ6 Ga+[Ј~Nd Lhs(%Hx&DON"'zM݆^k|Xd'8YMxs E9(i"})XcS&OPKo+P>o|p3=V*x >v|Z8:[c2ϕSJ}پvS6*5[npP_;K](Lq2 p;R1D=4N$0`g=C; 0Xt8GmQJ˵K% A&>[ .{BQ=rNAV Y{eׇ+ 1=?z)(A0KD-kڷ/@H6?(^%2lCm8(O U8{(TsU"鎻L#YM j?F<й D!q-uH hSSX"B] h^TPZ r,#1{^{SOfpg+XF8&-n.d\k6 6sbh\ΖW’PYalTD7k <rV GZ #ErWⵗ.EI+.bڌVjCA7H}2qwNj*r8Rw k&4_eRm;:Pk>l4R .op'j3ַ=+6\  88¡o|B/wX `( ˭MɅ8{BFۨ^.p6-4HH1sT9Y$;J4_BmO mYɖP!o௹U] J MCۜ$]j& cݞ했U[JacB=DTXy6 ȎTŗU8jc`P" 8'p"R8C2F '*ٶ8;epB%ܩ  n_g^{6NX8z,0l7Ajqھtp@ -M+nш+,wR)5$,P8>b@8%ݶ@U(Z78\hd6^{ rp@5͠]x NW/}~9'<^+x5`,IoءIʣ,+p:ڗ#U|]AE$p;.|xugy^QEg.c]?MVIdcߡT+|F_զ Rn8gv0fY' ؏AG@ީ}:4!9 {CN\? a;u;3VsawB}B`IɣLT R)Iɮ0*Px26#8 -xW PD9SzYTe=j{<+F^;xFDNO?-WR180epɿ S4H`-Q2qJ d+7-0!0}n{x{<)3 YRz 1(iғ ܴR\ a>s&> WOf:ג'G~PHOkĚZ0O~Fwq|D ~d>tZƮҽFm4PGydIz+zmK#FFED74(/KO@E%ppvl' b>a){ÔaJ{:D([ǕLb4{,І*qmR5\'YS΄) ;v+e €ݳ hHkDRߜƃiöuH/]:ETDkWL\P = 'D)د38 Mp]*lovxRJLok7#g.bD%0NgO ys:кwi88.8; qWl`M .H[R.BuBHs>bB s6V܍>i;wTA0pr3նb3WvaO_1ei. &aGTشP`;wYZH RH{H<7*QN|B}  h7Q EP'vQsK2* 2a F}~&LFM.!CCiPI]#&NL~|PTOoDe("۲s%F,*4ZVf6>Wk=ݧv.n8/i㸌ݦW g.74L5[ނ4Вn. ȝvqaKS8unKv6dˍAg iAq,Rz2E!Z߯3Gv?ߍ}$J*P݁vLAN4D٬$+{,H4ţ^dLhB15%⡋b|Ae;!'X 9TۃخPkxˆp2p/Ufh|\}Pq>d2)W (7Eu<$ϷJ;b)|Ci4VMtDtIP9z_7x9ʇM.ke4!,יL݄kRGYYeיCuf5QA]WH!ER %4ǧvgj)(|npx8uq;{{턔@`2)J},f x&({\'✷*"rv٫t @S.}( ]&(A"tӾ!bW;}ANR8BdܑٸPJMݞ;:8*[WpU:8r!@&Y&Y ß!4!6޽Ƒ+Sl_6p|v W"IF>U<}L{&'s6ArQsȧEQYIҰUW\*"RF#l#hQ(+Sڽ%ϑ|:3dw vԲ\ Qt hkӚ|s;u.1sy=:r,'gK+Ÿp٫!*qVp:,Z=nkOM}"D\3H$-ePe},س D5GEs3V'sL #8q3nK۩Y_^72/0)&L>BP-&";=!vCIi%Vbbf%xxa!>e4{xjSHЧoUI1PEQr~B#mZg悔B3 Ν;ֈT_*pE/J|ƴ۰bg1-V=72Rޑ+W]w{$~AxL)n{s>]AC ۨ]<\ئٗDžPp?d0:=ژ0jJߒ?lk*txD~`8;.5:f6Est *UJw$֊^ lq*/ZmG8KGs7HIw@(c= f Jub1 96fC߲Te?+9(gFDt@FI®*}F)3^2x@e9gŊ|\' h .OoS=j9旰"wЋ( *l(?W [ Fc^nsNa޸d02gB1 %8iG^/W9lQ(IFdU}}#8<C(r8qײ3{Z~!# &;ʁ Gl}cmR[h}M Ϥgl޷dXҸ {^=9N蔦OlQHnWY6^v0]vgD[ku&-|N kO5ezVѷeyWP=? QиR[LtQ9IE0ygFY$g%1SKsy RWh&1}lA_de7 I2kR?)5vm ԭ/$m꾩BFz/vp<5@zVjlBhMFFlțr4[)ͦ%;=Y"> li7M)b3S.AKBKxo%p(.Z$IdCǿ?֗\VD偒,$+_kwkPGLb#"7u;U겸6k+ug30z<֫kA=V:^>EBn(%ބn5~/6^xĽJ;0P'1 +dy`HY9UIFo "- UT!Co3 xa$X7jQ}Ĩ ިz1x5Q}$*4=E._' e[d=+grxL~߶ g*3{L>֋|Ji)M}.Jʞ(ܺG= !eX7\8'"Ѿ)b`,~U=l%JC O2Tiri0*Ӻ%NVnUMD DԵu+>=(D>ӉSjV\/t:Wh }V;ޓE4$ 52>ITyKHCUD롿^1.@Vcܶڬ 9%Ð"2|$h<:ԛ撩  دU]׎y0#cEі2[W(F=H0Qs.L`O͓  PBiB`Ǜ34 ((y?l}NQY@I<^qN bG$o40JXC3uejײTl6t_3>^ hن\E鲌 ./ Ha$wª"63b/do$/A:]яHSl.L*n"Q@?&Foh&h~qd<%p(T>|Pl"Ғa:OmqTր4ϧtekM`Nۆ' gݨ 7[fa`kDvܬ,^$Q "MXW<˨?9;Z=e3sҩm#nj۫ hfy|{Om+p2ĵ/KPI-$3.%YK8x4r1N H#t1LuqҎ9=AIko1a nZDϐVۡ & J\"">fGDL ]9D}TK&cl* O¹#9`=pz}َ*}Sn\uTjbI|${6ԩi'F0f="0^?zKz`:,:bV>y'5?z @*cܩ43\n9- ~ ^ ~x3SS?PD_TА7xwA)ZɚgQmW|!Cb[>pTIykrgThOV DYs._!2jw@ 8;zHv؅1_%]&L@urڰo+= a!\El{yy3,ZE~#rJBC)"͝ $Gyo!$(aF%Qfx ]G_ӳw},^ۻsr`X83 p & NDQCȩꮞ:_zC[oO__Fkh\%# ־85#CBAΥ88Yγ0l<#ݍfkjZ[봚͍vZ~ ~@~pwE48__ug^߿;_y0C[ ׈ķ8e8{Ab E17U%aBS+Ѻ}B˘nY01]0^05Ue8'%', iA\Ҍ4IZ|g4@4BvCԬw ED\T A~^DkvEDF$YdU¼֥HrLDMHN&w\~}2S:dx2$[L %!k_CW1`g"Q˦Q"#]NiU"+ڲm91 D ͅ& $FZ0L(&L[Vln5fzlzW^x"(AtEo'@k'%8YA`,e0kJgKqz8t a/F%yYȅqw&~mGb(MӉ^v EK UK,!(uef]d헍Bp[}@&8' hs8-8QTf>J5"6"].Gf  'PGӲ'C'瑒 9y !(biw,:!OwDNE0͑,)r#h.(W *pe`7,=cך:RNT>q kVN4 LS$3w=oTaJ7P#j1$+醙Q!S=$OTh{HeN%!Nt)Y\jjy0 2qZN  ve Q`|"8Xg:OɗHKb@8\% )թq5ds*];_i7oK:W>b gܷuoYNQT>mZ1ګ>7+`ؾ\j9dʆA @!5\0wX'7{4ekvˋ9&.uĤ1pfXQ-> whJF&u-7h&JhNZٗӟPM)q;D<,Abjߙ9e)%*P#w7ˌqvi(1w)Rp&&c$f"C8]"1pQ!v4!"D>12G>R82q)=߄E)=i-t=L@7*ȝpΙN;T\fc{%7LOKLY(GBxl7VpVR%XI=X9+:7F;Pdža8\ʳ$k{r P] @. ('MAEKwQѺ#T-ɿز"Q*M^;&k'GeA|xrԣ޻RUW딬][$|@Y.jJDrDrdf"$Zq`9HșQ3VJJbtY DM9)DImL!!EHa 3h;NYnƞOI|3+:D~nSTd$M2'w|͉E)Q`X/tw~}r+z}X:J:+J(!Jc^0 -ԫk ‚ʖWa#ں|ݺp&# Y,L8C)8jI5Wa78s5C-ͶƠL}ыL\i8V<&/J#G D>C\Pd&@>9B=%22z5 A!pE%kIFaBmZmB$΀.^S-6wx| *r` P9lpoɗ2RpJQVpld)QIQ! %}1"'%B Noʽ5u'D[)fm"Z808J%ۈKނLFl)umtʥN#uEnȨhs jx&C |'k_ӥF[R|v2 m@A_=w4n&4H4-hNu4TۂaM#0 X:GsxU@N>Hu.ROs.j.#f7-wVN?Jo"T9ϋʹ 'Ommul$]j@UHWMZyj7Kb=BRdp~֨d-+DpA$&He _,NAaY<OО,1"8ql7@<iT9jҖS\WY @-K@ceJ GG<`8BV_T8 ֨~7yF8e©cp-s]3gKJh-M} % xNjkuvGf@!B4q!6NZ{xZ{<[Cj#C(6;sѲtℙn'Ij؉6[E92n"N޶D+p@p 鄂t6aSMX]gNhˍpĭktD:t*a90eS1-2ezYń#!K!:r6#O4pv%̖ἕiec{ݶpkHw+I*6 #I,KM8"VHu㣐uW-U5=O6Rg 8qQ&t Ef͂p*ZLba#&ipmȉ9(ydt(qOx+]ѺdJb )$;cO_`MfZ;9|4ש-$~ޤx : ݳj5x@)kLP Bg" 9 8[6;)=_D7sjgj.NB{V<,Yr(Y /1ϻE4azU<89 `ڳ:@Y%V<Ѹg>CMmqFdn#f>MNHMBU?&O=rOvI9j݆1aImC.ғ\ք59$[ֳ_-_5œ10; {6K{?\HUaNÈ ۆ 6tѤc@zZ<Ek~`&7&6jڒp$uZr~:lNDJnYVR99C$[(z]9 cEZKi)^ަ4 N4 #fEEhykFqܽ]9{¢ ڽ^׍bxUIτLHD!\s%8._4tНg1Dkp.tF.7.Z@ӷĚ귐nR֫\|..!39"]{LY,et9K>e@!GĔ,(s:[ybu̦ hM+a(T qQD; n"<'P$mh1uIDI}'fWneMeY6PYrA,߭SToW07-LM7h7dͭ| V[CO7h|ӗ R:/Gt8qj)Bfmgꏠ4ܽd&@2kNZObJLH.+L|#pj^p%k[&4'&<`jqw::8t 31h '{ Y{GRtwшh5x@Fnĩ~[J˘|frYwwTs ֬c lqjL茢5Q$  @Տ]jwΪ$N *&k_܎'TBm] EQc*Id,Οl&vz-b2^z$m}:]z֣F~)b ֦ )W:)N(\FWM"OGD'h^KVB'GgLpP4Ti_Xmh :=s$1~^Ϥx)Rk}tF.M \SpGhK \d5'wڽ&@a #G7p:Ζ]7Fh[&unH(y߅fFT"!rcg^l9;Dcٱwxk>5~Sc1,8@z3tVw.iRsxec"ӲcZaPF 1Y(,e=0mUWL\΋do7qdDoTJͷw <o%ǃHT>㉸$}ӗiz4'#L]T+ D T_f^USZ<+/_eZ̨3dmq l-"8O%\5y+bQPyywD]:V_3j*lR), %*ȷ)f` U//pk}b(QSGLZ=j)1IRpslBܧwPrZ4نX":q3Hd J:}kI}!Sfq v ]!N3o) i܄h\kĂco tqb[FtBf$B|toin0uJ T|?ڗ*?vs&"xZv@r+Z5p4sP ( )hݲ}̦t4ZttQV"9\VB XfsoQVٳsG5QL\,0 ̆ .M =LBBݱjБ6NF[&sGJKd#$ Y.X -&8.BwZN{uCUY +O'NǾ"DF Ok 1x9ΎLT&̘nM97Wf &(lvӺ &zD>cL6[2a1elekr*8_U|̤*pD M%/uXI|nÇ &2Y 'K~v88&2M9Ύ"VM4pqw[%zǠ$kU^q%/DXldOd\=2 #kV(LF JE@tT&&uU&+\jhDVY"YɩG>_)P#0HGl˦%P#qt=Y{2Q4 n!mḎzH93sYbeqpjF_-8H>l%v,EV.RG:\)N*5~FH6>_Nf'k/?\U}AֶLh\$`Dpb/ЖIce9bj!L u"Y ?e _L‘h㨐v ɏ^ޮ=G5п9U9fM-ܞ=͘V}TjԎ9rA>y.gںAd=/>7T5;tBs\{ɡ VTy4n4h&HGgH_6R- 0z^J!# G1#TEv(-EWvr vʃ֩D:Xm%@:i#mtԨ0^ްk!C/l-"_u&o[1y4dAaVEr Y%ኀt^Bp&~6R+\[|rInШN8EF-AxYMqvk9sNB #…H.м Lh<1. }FӶNC-v@4[dS<bW8 8De@IXc˱㊌6>O>'v q2ƿ/j=jq5BʥcX7Gf0oi/9Vj+8 \0j Ϳ/T=e.'٬Gz}S koZ4svJ uTS: c} Ey~@ Q7v~|1 nnA:Y]ꅎŘa ؙprgt`jRtoh`0t]8B-}r!Wm,F@jwFق ۧ޴ ބ:^bu SAOKZQJy`&Z4qY̅P!1pbTnj=^; 9{=rhoxTBj~6.[^+]($'+~ҭ٪{ 9YٖSٗKp$k/7 +:pjYIӣ.qqXu2ǔrFLЛ9:HS~D>}̄Sp:J` O0:Y{ '^Co(J䶦~/Y% 4İ5f8JSBʝ.)E@L'ko1 <ak (\-<@j#BT^Wْ@.(a[ Fjmء44!!G99+g]4 _Tl_Tü.ՠFbDT}|MN$f̱*$ YZ :Ƃ֬jm8}3r D jvTgW+" ˛0 Ie{;ѽi%< >ţSیbgF>e /֪qTGrZ*ޫ\:Ug:i[9Fg((A|Eծ UE1+.M&X"(6Lq抚a{m{&O5rX,Gڽ&//3ʩ<ǧ/q4^rj$ ~vQg'o phC]DUt)NB%8$kdOLP dFXӺ2FDŒڧMH'dX4GK5&}rUVXZ݂GPDsڛ*75iQ]A svRCBNN)c`CL<9Mѐ!Rh X0MU >pV,ՈSm[F>jA FQ= %Q5e(/2=t ɈB=qM@:g*-x3(\&JX,D9'8wgGww6L4GzI 'k BpxA>z`<΅9Cdnl6vBh!Ǜj'گxر;nWд$I^%y}ĄُYUg͆tpŎkܞ'ʕ @Q8 C,!3^Ҿ蒶 h@$P?D+ו?RCE6%D.zl&6MfcNljg[Sj)]Zg^B>XNTw8Pw ǡ 8b (3ٱS0J=T$k`Nr m)>ゎÜOЙo5  $`SmҭXbV :v$2ک'tda}:p(TOdhӛO&H\h6g{UM%k5LXMA&A29z~(͓2 8 T 'o_ c׆^ ܾT;'aɷͫg䶹KwPQ#+/K[Zư]MIeu6!b:wVܜȗ<KQ,N2"^ ҪlMQo(Sѡ="g" pO+ǴnY 7eMdݻ~WC'} h!Y91@յ.h<\R7AiPt0bb?c4h]OM!ҩN>njR%sQY!Z>3Ap(?Gj?+GX >˽0[;e I(J(6>Nnݢ\|c?/,{^0MZ_ Ɓx<&WAL.mfmrI JA^1xJ^m!=sj[#t>xFү6 kH fݕE vҘMf)kMP<`x 3}&t6A|v@:3I Su i"񑣼vS&WOzAy4mI#9c$&I)1 N[HC}h;_7H*?lDw[j(>'/zǎD/>/-5>mցȭkjJ9G:^KS5q#|m@؃i?Lq2&B+BY$d/Xi5H 0 u;-:BKܙt¤4Uk?[pU%w,X up ;ٱGj{i?Uht$d-E5Z4G;FEB ٰCz{J|M2Bqg"Q>zD<~Hz"%tt+)ֹUR0汨<720<ʋv.$gϑ "]@̨$tDwI̩-|:K47ARyAOF>l#^fyyU&qPkjHDAǤS$,QC)wp u6ѸD6l6Kީ6vCUs8>Bn@gx տҔ8ktT4} !%8Zg}zPG t!5+';2%/K*Һ}r:!XYS:I/}om8ղJ S56D&C6KWu9[F-`(H֢BDzDtɽ&0YqVdJGtLZ߄ɕp!"b%ɝ{xYe?Pxl A:#>&KVIW7 { G[LBo0 Q,q@k";0ɅKx>WU. q+~Z!y=(5ɔ5MS-PMKD3*-2kMYq2l4$ %$@9]Rj)~q9,6o0mC?f2?tm8dMDdC^ZL{1䌣jg+Ht.ӊ%fn# Jnjˢ%ۉaݳӕh4x$#\皷—Z-P?Ս>n4<}U_G!+?_jǂp0?>HՍ"$ $zuztt9U,o.f[tŦ&BŔ yiz8̇>O0&E6|)W%w֭2AzGH{d&L4T``ڭc;BO}(8"@4@eG3Ա 0F8cdHD {~&U2ʛs':;l$%F~Y3wjw73b?5ph6,1N5;Α A1'- 5gͷ.F,>IF}VX gW٥8+pv '@1/ʥpuWd92#Lj~G #ɤ\.Cb7r@Lhun`0uLC8pa_j)6zF=Dmh,D>'*i"kP'PmM7y['C7V&zLAa4]^S97zYySi OwXu`@{i?Wn<3'{l4Mg*jn{^MְRRV= ͍4]FS%t~v yIF| F4#b ?P6lN2wLp\$⌲뭋)At/fFnB:瑵{+ ? L4OېO؇A?>U-5}:!s( (!¡.W}HbhrF^*mTzg\]YiiKP>(N/7ZQ$T<؇[R"@F" =o kQ;,AӬI^DK˔N Θ&8"HSLu崜ҮL:PcISY/qT+tQB4 I+Xk\ʤ\{:6M!D!0x KyvbrgHLH&k$_5/^d Y)Bu`XҜ]fц7LqZXԺ$4LNm\\nZ^,w{$KoɺU/0@-AcI<3GHP$"!Xu+mb2呚J`! v&m3󼳮I8;gd7oPLF&o.(ī8䗋v2JBK߶B*X]}BKյ^ٰz5LIjY |y8& MaqhHWBlkǺ8~x)NI8S^eT Rf 3z;r0^Ѽ9"y7(~ $>bq*"f!QҎQ)LOCD(TJi]"o3}Ɖ':pc>v 3wEҲ~:'6BC!͝ydGy{gב%3HH!.}ݽm>v]p3Ðlb! r`xwm H @B$rޫׯj^ujJWW_kdL4?}Q2/ًL_y#}8g(0>л;ߑ6X^Xo47Vv>\lۗtv=K>tΡ^rq`P۽{v{qξw]vigߥݣOn$G:^;ڟ8 *Bdmœch#j!Bqx*Fdc+蘗d0D2":j"?pUp|^cx~nl@QULEGgL9JLOٽ6L('!vJC z߁HtSj"{1RtX:F{LVVW[+[+˫IHt U }vl@aX%f1%C'tVASNM3өh-i¨PnWa 3bPZpwG+p ^h8l? #!8ǵn;ljkh4 4"M t D"wf3$ƞFAN:(A}!x-N XDMEbjv$W頾Bdﱀ 0 8H>m"q71i;QKIUёӷ\O0!W6#裨ZEnr0O?nP`wC?>|v;v{I;x"' H|h63N&Ni DOT"2p :G82 hn.9DVS"S"#栞4a_t|d* ]8We#D6 $Kd 4q!D")ƊKxcFD4~:(/,U>/&?1 ҇+uD)MCt3NЍˉ0 EI#1l8zOY~tzT_}5Yx]a@ pf;8+N b/=d$']=^b@UQ++M |D|ɴֺ렃u5[пo9j @B0:ĥ@[TEvp\Ym>"8=8 緤mAVZ)DmfZOQ-Q[+':&ayv)̜C}->ʝi6S9oWûk@q WB/Adh@(bv>Sц3">(u*<00=`*L`a# [ΘCJRŤ6I yyҚ'F7"+"{M$%FlSj-Vű |&b!$ (nBQی<3Lc^Bp n0X3&3VC֐+'Nx NI&{,艧ԪOuQ%rc\]X1LSVuW ِR_w !tLeAiJCb0h|cEt}^k) H3Z넥k̂S-9>[#_r񙷗j`!I3N4FRF-aD${;~6;^9q${W ]&dþ}STS%†J {,K *z#sqՇ_:W<r@˜m9JSD2 g-LaU 8&ǃrBK%%J:$r1PSo9|'˷8n|r);#srX  Bd/5=ne{8^\,9e"{1NpykNQҒu3h3Gc|e5>AY(kTQl^]&eQWZa䖕aLY ШSCf!ъerdDjc(kѦermRecVMb0]&FJ5WIn\mjuys_J؜PEYW10S<172_A(*> 3NV.r/jDD|([EG?4[bb=9V~K4iח;,UPx "US*ADhAYE5b[{_MǨ,d^s'3n Id6>݉S ÅnMzP 7jɳX9G[+ռC%^iV$v@ԓWLX=3{PSn)^{^0A"c7 w3)-.q(G3(!CF`M@bk7ݯ~/$KK[l%f"^ndgS0V70ngbdNt$2T3q?Pn#yyg^w՞FFq*wZ5G7[X@Kgd}{n&&X=JwLA)\o%J>:~"g8@$Pa(XdԴ\_MU}:BplPNsȎ"p0hiR:0~ ktCyG8t Tomh| "N)ξ6=n2U s[Q艛 wPeg%['#z5wUVA¯/6Wl H~ES-%HW]XS4/Qwق_6U]\Ӳ%q1 As\In$t!Ӹa*WϡiTS7"jgE2qY'H#tE]RG^9),?#)_B:ȌIhM^uU9- ]T7UQu=gn8jTMTp.4 0I"/ $NtFzsZR1d@ZkU8#RLq+NBpSH(EνV8,00-i,Zk&,^}}5Qgq!;m6+^BTT#v69v:ϪK,vz n\yCe%,&4`O TnGjy]j{{΋{u p#S؜Ǥ Og$wrp,_^"//7@<]ߞ[T]WַhR[멫B !`[ VoTF8ǂJppN$>ъ%6@Xw֖(qdqjQCd X ty:X@?@\dWJT~>dU!@q,qqDUA'{H}D?L3!DgH A']\T]8t¼C'ĽhRZN /9PmP(4^B0 H# _+c I5重fJJ)| F`2s8Q{} -LV6Y<n0 q%SBAFDCp_XvBAG.nEvl[FB, ///$bԮyjz9* j_|A39^ FI<"j4 `00K ( nnHbrbqER^wZJgAOi!7oCeœ*ʂ3ƭ`VB mz= `xnKEt[wv0;^< rqE lPҥa|IV[N\eT>W {Fa*4Dv S(buG@W^[ ݊:Nd2'8ǐ5~g_lz&*YKB0ܦ o _<`ʫî^p.uq~`srDϒ`18pe[l6UU}yƕ~F֡z;I{EcZcLwM Ma΀+(C;PA7g+u76PXlmOjy+RB({Uz7,5p 66<‚nٗ=ӂJ vlӊ(7\ԧ t8_#wYXO 'x\JM}u?3Aph4Z#=z0uu/XJEDDvIX ?R N_ ?əsr!ejhhiۍ;G'Ki3YZ ?lH,}Z%8js8PQhUA7</EGBNWq#(hsAƲc}YJu+nNh|~R >AxyB@n/;qE."!&8Y\JDr6llDw@tmx@nV@Y/bm؇~#ʙE6LF7ZK-G\USۉ++=jrjwiչOw V7hv˱ RGŸ?ҭaVЄ>uqx/ V83"ln=Nԁ6OD!@z".?wh"o/4nܤ"av9`t4iڞ\9GK{D^!ⴓ< Jۺ 5XdގXFk[JcS҃CIHr}{oU`'ֶi]H-'DewٮQ:gD\4nmooɊ((AlSiS_X bɶzNM Z"Klx|1Bz@ݺ@Uw$P0Y4q]gQT3(?BN43Dv 3 66u: ;{2ۼqX;nV.h℞TYv,];00Dp"A̘ߞ$98[TߒE;kHMsSf,:JyDYAkiƇN?m_OݓjjIڗ%HXp/7U ji6AoW+E_y=2@4oSsbGcrv,M.#++h @"2~>D$XsQ|LmuS\*^@d3N_v-tkh9z=D}Ksfϴ(n{Q3&qMҨPDtwY% =%(;X]NjI(gϗ!?J|O(l2eYQUӜNA4,L檅r/FQ$^Q%{)DvM$cXlI Oɞ$(U<}D6 %Zj:RvUue{llC>BNm/s3E㜭+㗙 N0*EVl77U>O6@@>Erj[<7 O<ʼhWМ'7Yш @1fAu@@[goMd @Tyq!OU4 6w{XЄ@Dtl"ÿ kS@neStl4-TRDsE8B pZٚ 5.y*nkXP>[| k9Pˁ`ܷxhOmzgǂn6#L9܇^/-.4u1U^4ϚK#߻P#qqvZ6YC~}f]* p)Z"ڍayEiie^,`ۥ,׃a/uuB3pqxƸ._^s1Z\ (~PcԬER QNhT1HL&(|4jV+gy7RHZ'n !-;-pI7GHt0B@6}B(AlBQT,u6H }UҺG*>GdgϹ<6'6/O$81[\$׹m]@vɢtoċcmH},&'~ǰg}^RR3.?NWt#aК  ؝řb/':UEfrNOhҡD.cPXhTc+hg#ԹX*&:wp9=`scİp!Qu8WǍK#3|f7IS՟3%`n. V[M].}:$L^NXvͿ%uIM9U9}Ϙ׻z (n&;Q;f (Pn*r #-QkÙ` ݾNIr"~}j"]"0fRce@D.6HT9ENI+j D@XG ._O_hU'u*7_bot䏵*q?S ꈲy:@$OQ۝N?ɞ _%<F@@iDcND6,Vbv]J5h&|L0R'A,$M;~_"Jso/#.Jh:EztTI^4!?3nȆ SeyUlf"{иZ=2UG~;Iys {#Z+gYGyL;қj$&yf4I$y[:ZН*fTT~N;є~w\,"P,~0J?-"'[jnMzU9 s/afsE)Op_/ͭBB#)c h!Ptt~kU\' SOi:O86`-DAꝛ܊~t H9{}4jQG";eC pTд]d>2\>Į8=9ƿ`?/UVT\ :u\ݚ %2͇J7!̛gn3qIW)?sp.%76!y Jbnp7 XKT,nduS P-ngq&$|fdɻQmgWǤ-8_lEZBC!͝ydGy{w !`:d3L!$U;u9`zwm'szqpD̙q@`@ )E?(rޫuyX.?}_}5޾h\UC;#~h|DZ I{;qT x>hi/ok;GN'sVvh/} Et;뽢s;z[AQ_. >{ OS G昨< j {3qv: z lD)82D*>n"(_p# *VjaL3kL8$0%  i!'#fdz!%)l|m57(7 =vm`(Z0XS;d8U >C7q'uj@ 3N^O0.UrLvz4~nαiXcWXZd`B(  |T6\R; @Rm7ӳMP7)z [ڋT[JQCsLyR.^H΀$!1oEQNDqEl]0sC7/LOѶ5ߡH )\s9Yn,뻭zd(OoPB5D0qDMhp? &6@'80)PKr"8ޓyj>NX1k]ͣs}.VV{ >Tq6ΖSu OAU|f ЋE.=jў(t!O;"_㳷@$\$?6wܛ(Eh~AXx4[ IzȖGAa=r,СKc Fx6P F)MkMC(ο'js]Pp'+#<0:ֆErGDHT&&|v1S3Ai(1Mgq nnNNW0*>{1S0Q\k;{@z'n:>4S&!.&ֆI778*!_MB"yY%A2%'2f ]_@y>`nC|P7 QSQi|5Tk3g߲ʑ/!Z\o$Uʧp|_pN}SoT&IVDuW?eڴOvħIa:ȣݢnJK ¬Ԝx>ܢɓGl*8W %"僄bx@VZjm#䛚 ^7::ngU"|W(;Yۆ&Q0EpH>,ȅ 9>@%"ohh UC)6>1}΂)J ѻ->{ `[0yI89Kw?>݊Lew CLҘQuگl A f^8A1q A|6~8\#> !>聾[5n/q.ҧ~tfaFn?y= FHMg;NCȤfnxN4$[^WuT?f>m㴰uԻ)2(To&Б"=aBL j٪ *&:1mLC}1nѹYeIϙqJ qG9 o0ϋLi uD6Y *R|v)Qj=t-#EƩ>*I|S0dTj\9ϾbՂAG Ϊ[ R1{#>)Qs&~dhD88"3[A) tBJXe @;)fsP=>6;?yTū'$}*Hr<Pdt&8k—) *9f)̐`t&UgI<PįTr&BKG"N0/G6sc$mgl֥)zKHGӶ%I+P>;kׅxJs gmBaAMwt.QO[58%"y{7yy 0V9)!a`/ϙ0)̀䇢VC; oB@+5T~?7>3m<q} :|v1N^ 0 y8ܙy](I.>{//sIq,^ c ʖf"v% ERӲцXףنB: 0[n>:(~+h[;h|> }h梙ԥ9RSȰ=lU'HXYkV%g&OpW>3PqeC-4XT8HlÜ~%<l ybe<&03 њM궺ȆEl?Vf#+ս>}j7-qo  iQoT{ UL~7iAJ&mMSv&IߞtYM(C**'JEtg}R & ūx=1)P rZu*' R|GOQB5=m8IzR*|gmb3﫤>8͋G}=fi&5i>m(5jL!BDtj?[>q/B{<榎tniĢT}Dy45c м%u8yC5+ۄsU~Fw;!ާZ(E?:Ùf{s.܃QZ8J—Igw@d`͕(*A-VNRƈ.*DTNIj wvDt\Fܙi.;CD Ga^g<,VMXv }S]ڰH0$Rkԍ6<8$?gWـDPsPx3\gW[qB]a4yU#@*ǕN*g$Sl(M1bmőTfP*Ug<°b'+E=$/weHBf2h"vF`d h1E׍r V?3S-tWyLj(P|v D#WEɃDDYip20 ba4?g`Y,V|V/]h|$A[9+cT`H,=H۫AΝ:Y&}*ζ3`8+pNMqb~ŴD۫;2^ Ri $'iv)LMq@aѐUJj]w~5~ $ G)˩;.no8skUIDyCr1ni 044;hTJ/H@|> GdphVDU=gI29qI6v%"$أ#$ԝ4{uT"fFVRjϸE.:&7Xu$荦7i Zuht3NnQwaO6uIϙAg">/!d'}* W:&wq,;ԇ~k$0<)]ssOG]EtRgT(E`@h'֥A+3OQ`$+m"OwI4PI"+qMz 9Dtʆ?=- (箺ə,TɆ,{ L, ]'*OY8 CQ/<^9|v G 7b8y|Xo3m_*("q WS6;X$zrZ$YHdDD^]v/2# 3qZ4HP!TAnAK#܏ٻmh|Op:6Am9>`CH> ƹP!g j(Q?Őض+@|ƆQoÔbܷ: X {@o97J}E"4Hw[ (moo$G3#0>{ Q GLjBqHd̑Sb kKk\ɨj*IxU$bΘN@7Z!ҩ/cZ=Z>ʁM@A7fV2$;2̴BDnC iWPl}Qٱ [7h Yghyw,Š;ဧEs+ď "c:?j33!MiV)]i5u,}}u { X:w T|aƳG#)DWmW%hЫ7)Wx󓀼G*yZQlկ>q)R77 oBQ{}׼(CҶ h[ͫ*՞ 'Ϡ4;Jwr~1c 8ЫÍF^QY[L69KH #ySp8SW|:04m}eHr}Wa`"UƔ0 w?,4ȐJDuNlߋX;. $Q֓\qa+P|lP%n6IU7,H˥`mPYlL 02OtφE' oҐu+$EqUT,6 8ϔc49nt?Hc6yZ]v?i!Pڠ{L>}Hܩ[Ř%RW֖δ~L>ļSgy *0@m=D͝8tivsz44OCm.;5NqḺqH2KUqeMY a"}IwH軌|@vmwh#"1}[U'&jC:"is @Q8.u@/g6N>!$ZxԶXs`D׏!yMeDoNYŀt~8)ǎ4ͪyrUA0>AUVD?{- 6V(>yvIXHО; 21g]Hh+nDk.Q>)LQꎺsRuUŗ@/@ (,5bisrOޅ^hb;bf]pPjC  Qu8d,pBDp٘&i|.P_dJfN^riwXyX:dTfZ(G2:T@{Jvhw#?}8Ҁ|T0 ΠO:8*4n_`pIW6d8 o7-s0я," ky[DUNW%FHuCmθKKS_*@WX|fTp=h1P5ΐt VoMWQHn@%]ĩMbP>Ǹ6|ϕޕt/ouԕޑ>o_W0& !VRH+JBMUǭJ,|đ% kU3yRCtOa?d1J:*tE 8Ky;0UHa}8qW6/8+5VJjUE MVU U3_p}Yc!4߱LFp4`;:Pz:BOhla,lÖbt>rp:C8YK522'#SO/=ƻ !|wȽ%*ghg iR6G֟ᗂ ˛:fkd HhJYL T<P +xjK%aREHr! ū+8_!T. %념ihɵ)>bPB)@%@0̀r!#!ï&&KϯZ@lHIN ,G L:d=V8WNcxYkTGlBc5h2RLϖl!?4)%GA\z 08խ M@4(>@`݊=e8O#M W5=U:pAwyНjX<|vr>#^t .QaTYUu/yO:HwV-NTdԳJA Ni)4L8c~$ΦYuq|XW(ʙؾE }ݨO]yJmACŽnE vON(ѫܞ#p. JHIifoW8لqIwR>Q덷 qLʤ` ɑMpԀ>uρJ4]>qH^X:ԻJZp F<r)RݶarTh^]*_AwH ij!h<5kJW|-xBO aOْ\+n7r HC2)Gw1BZ'᳷0A1m jBL@v+ qT {'j5 3*sAz׍a@ O:ws(jolߛzjgG]c 8"uQT!,6G;u ;ਕΛ7qѕ3p6\LH_"Ie@$r}*r` _CRIl yhdIy<=Z<"U(u!RW4m>:n\bt4d35P"ڏ:hVźPd, }鉲HD{t0|Y+TLLds8"zt1k]-xVpHN_yHb>* :Rh׉h{:Zwd;XBZɈ{7kblҗ ~`4-4y8d@/^h|݆)W"H'Pu":gָuϴyJUNup37lJrW"9a HMGQ~q3%H]R|]ۡp+Njҵ{(DBG 9hgv.1+L:0Zts*G]nnQ{u87⳯j``wU ^|S5G{r 3EWDy瞕_]MkO,Dy HWJyDɣ {>Ϯ!b C$m#J6.ɷ]<5]>Y^ @gǩN*^+l`EI\#FOfr(I%>Y1%o cYJk..w.)@uBC!ݝk%GugCEQČ2ʏL$^o߾iw&k++q1VÐz?Gt9Ƃg(5I݃mx^mm  ؆:w@msZOƓF͆Ճ)m> x 9Xxuq@2uS)ĢGk#v^@CoEԚh3-7cxsQDIffؔqJp۔ >׎,hzR_m.:wotQ^$D?HWI|؀ʵ\r-a\ 쁐/0} &IV6PPAz) s5^DN$̄X+75"6d"&bO=Zxe@0r`Y!M )s$J[^M1T"g0N W2v 2N1 Թ1 h|^>Q8 BOiٔP=OɊR@@} vC֠߃"< `':[ʽx&8m0ڮY@{yj/B%P)wHPS62aTX*xZh T =.]^{ Pp' im c (s@ufF„"cn899R|l; OD%NKoVn8龟8&LNȋ" _kи7rnW[4r0ZfڝFDB +J y)" \ =CpmRRBhTOU}#.(p _6IL]Spcdqx.;amg N"ʩ0TD1klrTNɩ4F$_qk *#&?w|vPsvMyC$=MlBdtiY*PXY &P=Pq?J\jg&lQG5%b 7!WC{,@GGKcXJ1p EF<|hDI7Zm8pS%0].0}(Lgb Om`oZ\\![4iUL}_%$KH~s'm ]tnT} Uا8,YuMo QV1А(M8HpA+RNU8GhjnP N<<ޠ}( K+]LT(ΫyNw).$ "@'tؽ-m pI@t7G4݈JgKB\؏"P)Q(E(2kL€;bQ1plҢϨll*u#>jψ&F| ݥphUmON6ɃXB T*x&LHgIs`Ӎt@yXXE'|Qh'`.4r퉊f;r1 !w7u]Hw)\k- 4U8 yUCDKU!5vqh{,UrI 5* jTJXkI8#:r~4uS iLҢASs@q"=2cAMPIv!Z$?pU niS*ku CBlȨ^[D>}~)Mx8;+՜gTM'б)T$sD D$2ZZͽD-$Bg6jnK;n[J*: nU6+4=3e3qyj? K[ R1N݊a 9!B8e]l7*mBEnrW*#5 Xhu4nhq&tph.24bi4@|M-8p2=X1Jn׶gmoՋȺ-g^{6N 0pEApb>M0kVUګqޭNrDPB$d YH+qRRM`qh Tr[Y?ܴ}@]KS l`V8sB+uc 0gm?֞2)dw,52"#ʨ-,l%|Ya3u"E_2i@=zğa%TDCf_0yJ*ekG_rO*\8)v6LaP̏! 9*Nf ;_#\4y'AʽZXʂjA%0pT.C8#u[#\"u5kY%ҜN?{&p&eɈ`AQda:D=_k?^{>moMQ !üF%JCߦu"Ln `Mж7vJ!7*F3B.kJm/]꿩aEos}OcMYY+r$ ~>lfiR?j) 2J8g9k)|Fh;KwikX/rפgLdxufL^MKpϙJB0e w;5eaIlςUN~/F]~F./@FqI3x*snQOxTg %.<`(Ϫ"!&VGڙ( H}l57$ /XDEXϬxcvXeZl3YrZ+ 6d+Y+M3+`K~AF6kզl+(t.ҡxT>{K֙4e4/R1Ao,eh0F}N1sHdXwpll,잝 R3*6ܥJpZ=%U`(aT@~zN uY m6 kE#=<=FiuBdRUw;3я.?c' '>Z, ']ͻ{MqȓaA(XKXez/H'NvIiŶR&Iy;",}ЄhڳԛFG4l30=ŇUDͧRPdKWE?׶32Ki7DY=s]<\*ǑXqc`, z X!0Rhن2K0X kP[eA\f7xm[XC%nŞ)#'ŔDA2p"t7 <wsg1Nވի(?xעoit7?ѐ7Д%T;'@%Qv1b\] WxRHg@kD/Xjo~U;:a>3GlK4expk}C 6;m=yJL␰ۏ I@m>ph{o~ᲊ}t+2-\fz) wtY IGy-Oݘ|sVC|X^'ߝ kwk<4#CQp)%}sIZöS}.Gö}Rd[@>%"7(X Mk5dyl !~L 6|,@9c"#ܗՈ? ^/$RFg )&LD Zs/qz9L^$m&g@96q,7Ũx7"mOR>{Du*]mFY)+֮ؕП |@h.Tx&#`.4[C&o~ tem|Axx J&.񢂩hdq5HH@/H~@Hn.un4ղ&* Ο3@*Q &Haě7m?q3>*THY|^UJ@OD1 1 p/t O .HDe,NO O ]Yn MfiEku]AB4C>}06 @%kfUi{bgTTg z D-Į )䫼 l\_)@uoVkwx8,W\~5H&޴{ c9HRE; ysJ&Erlyd t  TDuEXD)@0HWEK|zp0}<,[>a$ڒ )x6+' 6Ѽ #TN$@BiÇ.USZO+ʸ#g;* wzy(+*I4^Q1KAXo-]McU^N9`.COӲ& DZO%jhG"kiq# lWz\qx@ ;qrۺ :hjw\0Z&sIƒO׶l )OIQ -x ڭw3 i3d#\[L|N$/4&a#_idX|V8r,pja 0Ymn w(3Fy#s p0\F߰=зFH.@eVxog9Ri E ?6M"(CQۑLO/eE0'U;͑zRD"z 3AzgAH$pv]zSxOT@CۣXfL?i!38,П ܽFp.Σk) (WB4Z9ӈUF=g-/7ݜ3vz_( B)j M)i٣r}I Tʧޫ=ȕG~{^,),w(*řɼ7^ "u|BokӎP[(IYR:X%#r=4J'IÞ#ԱNLgB {Vbm(|n"=O=u(+F\q?Uklse9pAqqf Dh=_nrB .8RB;2N -AvDѲE˶Q k"^ETA3EGl#&Ue>׮1m@ [vT[{Q/:kU"~N0i?(yr9B5|*^{N$Tԏn1rAWЕ@2@m^{ gy+[^Ƌ1Ѱ47ǝTL#Q S <ԟ#w֭@k2''9 o&~р|31gMҬ8~p$Ο6Onb:Z ?YQӬz)|Pb)gi'Үa'7 rJXEfoi8(E=L4v6LtN;'NaŽ;0ؑ26 yS X/F+r[k4XX4!uz]W38p<ʞU=h5Qi"4o6 ![ֳhm$Lխyv,;>Tmϖ|`@z4A;ۺ`Hk&Mjkг܍6Mvc?zZP2-- n[9|ڔ;kK} &yAdoՊyHSn!r {&@x ` f~Uעpހ>}]0V6Pj];bԶGٰMo\sSG}((VgVkNhUIuyc \,B&+یnK#V a.k} sgrG/I2?wTθW_1rBBinX=Iyzl.&kf5*\ NMLqdU$x]̑x &"VPg Kǁ4A5 |X  }Gg $dxg@;'sV| (קYCtUAv @N:a,dږB}J\kbƒ\Ye -A2D'MN&Dm6l ʓKn:a=fsSÛ&O LѸf9M{TL9pHQZxy= S\ 1ԑDCWy#"۪=DFQdvw Vaﭮ({t00h,oe^Y[58=ݥ%> #p  $I1Gc!:l`:ǢU^5ًRl i1-zIQṭcہOBIl7Ҟ $>_|ApF ||܉%Gz1EG O?p);BC!͝k%Gug Fф( 3(EWU?ko߾;@l0{^'!ر0 fx/~w P^ !@x].D"Ey((S]ֳ{^},Y:usNko4x{{g2u;I{A$G "t{1(~ㅗ5jk{}kyyu}}i)molmo./-[n[}V@ks_>[UWhfպټv#۳lϵds״md^}U`gx$s@r ăh Cj`#8 η3xdXv:(qzhFX\omvV6V6Vl^j5Yuʫ\?m]It_sf:lcvs[ : ;<XX;6`A@m_J`Mlg> 6 jGEdИ*Su6ַZKymn"u 2@@UXbRBaԆBK`G#t@Ų,B/VGU4 132 T3Alq6k s@B&ђ3(ԁ^;_=,  j]0gy>)/%"eo4 |\4@4@AH4s]?i G ^?-WDWJTJ,{)QP$%4蘎òFqDq-(GUtKT4IJS@Q̩h|PSpaC8bq7ⴜ(X4#X)Pz9^tgqR#z3}ҘWQG4h9/'OR%0ybtvC$8o/nm!'²?67x@Q A/IX5S")D~K]#}Ī$TKhѝ Db:_$ZBL$%nj\ ݫI!vAOYN VMR48-j"*P*2tH-2pbmpC~8E'aAJ%[,M(' :Zmy:U%e ĥXC7%Lewe@E@HBjY#S鈾oU "D!A?6AH .JDs-D,|NnCI. U/9ո yXnݫ ~xqxՋr*^O[ r59Jdo:}J) 8wΒSE꽚b٭:QU)h>R*b@-,{q.P-nٱ4D,mc"J^ V+:o:q,?FÄTcUS Io4u@)n2sAK ˈ\J[S+Dɥ>eg3YOq05e)s5M:&~nRYG7l(^ %S)а7K&^sqĝ'9wwZƨÑB"~P~ǹޘ,Xb11 k >^`UK^?9в'E8yH* $>#oTz5䬂Ni_x Ծ@,HM5PRqMa@_k(;usH doXnN$KNzyZ pbhvE iwOD%^V6Gn~+a!}Vw)K[~QCNꥱx\4-XٜY=6aE7Ҩhe< &YD=k̎Lhr ͮW17`U_Ht**p6k!*.r@WHoò.z)Q8)֓7,-X8Iocx!cDMS >FmziVxʪYAV6dU)k7,5;V 3p(DĨglR=TOruI(u F+P: l)GCFUOQ!C% ;D7a90%$]geg]cy9zݙ0p[Iw8Lp6:J]o Y٠7ExARGaS}LS'2d"҄\G)۵~$Β]Ե>Mr$K Q01 t  h6wbNm}^az8*@d$,cE7^~M2侄e$06Tw &7WQ4yZ#3'Uh(XԆZ qZ=dm>AMZUXvԊGF(NaDUF6Dm`&wXXv񠾟 s)@i{)yIar=4#=κ+ |7nLFJ |2(6g]xx?GdMyJU[lA#w@w)qMsܦ%A|w~֦qv\G(7#g-K]; "؋ ZpB4^U…>I8gũoyK,;_#زAJ ]h~ 5Z]uj"SZ0}{ES jXF.'4 i2DD:#jC 6 (H)NQ|Ed_;fbsj[NCyC68 5Piq<]AOuWo#_L[0ERp.,WŽĂcMgzMdmC7 +,)y?A=ELAe?1 zzQ ZG47^SI*m\8&Vm.'>ȚCEzMUkcƅP YwɴUgo' 8P3 /qNV$qkK8s%/,T1ݎe0 zRȫhHOUVGΞi8+Λթy:wܦ}nWM n78UvTVIz8ɔi>DS$n& h艏f-X%EGU,ц*Ѷ+"] 2g`Eǰ5n ř N,64UYq 8-Y٨Hgo;gYgp m.'y N`%;@j:u `x'4auƣq6_Ŋ7ЊjuXd~ MmL+WLBe\yt+܃e_5.!/PÄiZq#rayGm!ᐇY_%b=]h]l:qrd <~rr'T}0kGj|^$hƒeweG`#>d5)DePVTm%?o-O' l@E0CBTR@|{8d5S*:rtH=6D'ŲmwskCAJ,1N!5Lr.H4ǃVQ>qlRXqH]b8j?m %<;qWqm0<{$j t*.t. ?yAA ,UƏ.Vr(+YzRBE^peX@-XYsSHUD:oDTD9'2?DzW[Iۃh05DMM!_𔩈]FIJZ1IAw&*R?p~'x_Qj:p *IHl.@O!J%Ɋ2m׏S"qmkmMUZ qEAһHmT8I$Vs{SIjtև*ۗԥl:5lby <` Æ5DQ %UW_ò7CGO(uu5Nh>+(gсƮN;B11d7Ks>e_Zgbof8Y}+yGUn =҄ڧUrx1 e8d@jz.8hj pCڑx<_Be\@XG7's*SVXC-"dxW2*vR<8&;0?[CDxPx5lV=>+ɂNIwJ p%S7p'3sG+i8'hޠYw炶VOiƿ˪~%RL~kǣKAsHp908K.pDo SVqHG]=qYs$C4*«+,2]p$7F< vT$tJLV+&R![ۘ*7I=P1Y,oAET=ƣO@thr8rDC$Nul)Y}I-묎Lh2IaT?M'D%?H4]ʘ<~ɇx=hÔ`&LkΕ!jbHH@QGe rT~PubL @3~XDM?Ew Q }Y*MWQZ2סcq,{"qOXA߭Vފ: QWZBV#NA gBxZ]e{%Ne0 ay_ s }8P*@nuԓ;*6;@,]ccd` k b.w4͋ |Z0d㥀"ҢCdm?jeu67YLyVO%Lhn ez5 Q5ԾpHV]"}23߻tx67M"m-d0ko#85P`\Y̫i N5-:USEHȤ3<}y~,CP4Ǭ[[GT Ra*5iU- s(! 6WWj*yދe7*j;M5uiE[4>0o-ε72IZr| hXܱ^DŽռujh[=8+ڞ>S97chΏLhãSnhĭ9)ZS$m>[ADލz Q(lD.L~c Bp5їA&{[,EΡpA039FV#>t $PwPǩ wu!9)IG?%7u8sL;?i3q"O\P2Δ9dX`Ǭ%ÙWXX>$<'x4y8۩ȕO` 7Vܬ,,G:̌w ƪvAkSX#pUq!n֤e`tz[RpsS{M@TT$ E?9͒3 D_X:Tj3Gz=ғ٨G}HނeW8 1†[R :ufBB?A/~n2:>IJOE^_Yv8C% um ~(@@$ZsNtPI_}˾`SP Frŵ^A>]xfQ.4}~HaS4l|w(*=r煖qD:3K0dY F~jv0hU qD**VV El(qMI&y}Dbi;H(J1J^͊ull_r0/`Hz(:Եr@1^AB@yVwl^rP Qʻ V(xeǾଠd33 M(Uh>L sòmH"ErH4|VHλhekZs6ۀ$@Ycedb]╀ "/W>蟼26ye,Wv!6#J(+㏈L{mP-&?Lq}#ɉt(uCJ??BC%"ŝ lEy]4I%;-f* "eV`#S&*xcibJcW.Ѫ"<.peUԤ0h*sלgb گJ͋ʋ|IuW gWⳏ>Wp?Psv>hÍ99 t3wW*[͸\>X[ڌ7xki{Ni7k;{{ŝNs={Vnl^ڵ֮ _S[s;@8t^n a'j-D "=(" }L%D) BF*p&mPָTV^@nЂ;'׸M Y0JKޏϾ{BnmQ7*9sHS^/TҳoW3 N:~XY*h!:Y78ܩJs`Bs@8OinMgB~ 1vR*l[|Y`+\)'?sk ץ117C5(͔T"%7c9qUgJ>nu8[u]}򇩶Qoҳ*"ra OOT[KZ6׍vVն6bU\wat8-E}B6?lB%rߣJ%6Rِ"WY|фzSqq̩Ӎx 1sz>ȇx td?A%29htl Q|adB\p T&8.ChO:)w8R Ns*{DMA]yR? }(pl^,ē@<|҈-s6n#>g{u$vRY6::0rb™s>] 1պ`(g|ikZ""ҷK!5lΎ%o`z>.NȺnydf/otގkgojjIp-c"mݦ2!7Y"sN|98'ac;%m9'T w(Z}&ZH;LAIKZJi|vS&`~h+"`#(qH31Ruf~H$э>h#>prKl.nT It5$?(ȉuOKMÇB^ S1yrTג Td2Jow-BҶE;E]! hH?&P/#EFM5 ,Mp&a* WefT5@A, TJ*O(h8%Z,}C-_S ۝bZ""Z&@րHlv.p>' >*x1y;.5mɅ@]MQvcf4Xf  f8JB!Wc/h~hEYl GT[xƄOCQQAt]#"vScw闍*<Νed$uQ8 Ogg$t'lh"ڪ|it\!q93Kj|. blJ@K,Iī#lѤ#PqR*а) iJnQP)܋Y_ k8ѐ ^=ӕE v2p3[ y >{vۑqYrdn8HeB^,˦kM؃t]6׷([ZK9LhVܫ=H+wO ιp؏ا0+3I:;ivOLc&S@@hZ L$Ar7pi\ݎPi2Qa(CB>a)CKW\&nQbr>F^3b@I날BXԽ"(r1!stjt ҝ w"N2sӐ-5SP*^ ˷.2 vRoЈ|ΪNdRhd fpj5lY:uOURo| > "UٶPEw%T>{ M8it94]"$&hϚ:ߢ]gT*2MXjs&:>J%{@r@D5[@Kء&*]N5"E72'l&Oe=-xva /Sȼ*t#Dx(ۍb|tEި=kw],*Jz,D NĶMʘ˫DQq=eDv=Qv& O^קFceʗ:` "*/x86ډQNc ǩcV$:iה|hM _P)ݝ ~j\J5y2P/Rz{ Vlg& ԠH:d$@ W9Ś#+_2ڼ` bt.!;jZ9Ǔ]=Wb42ߴ%"ۿ,E 2ȪE=)BsFJHWk(v >DT\aivb̾ kG0[M[g,*[Ry !#&>{#%EߣV:!][t&EDJi>$>w Vt@r&ʵFL77'%nSxg@~}:ҬVMU=; qQqb3qia3Ƒr4 ...{I%rFSU%~  (yt}n,Wi%BOR(# ೷iWIF0t'24BivJ*"gTߠ\sKϴ;Ɯ'ǔ!41qh`@QJ(iXPu@hEs0!+߾q+̷\C/ܣ~CTC۳0ܩ;#)&}.oX2E6i~?\sO3=3yoɎYYZRY2)@LB b*T82l]삊mMO6hMx:ߠٚ t y&AٴShz|W0>[7AD`3l3 [`P㳮  iAMS/KWG4{~DŽ]s_f9 YD#'JQjGt|! %Wgo5B 9P4S2(snxdrܰJhMc vJZ?BWG}"s0c&,>3x<7%+֯co7fNH XKƑ(JKSY԰P=3|6{1]pٛ\lQBV N捝M6x }8LRygd&F.a̋> @c.789A8KwIv7i&(. {iS^=T~b3He7|$oy=Y8KMp '-7BRtc~lR ,#ē٧%sj#^zca0#ͲD&A :4Sfe-?mN2zIQٷ%Wn~y2y`+ٲo~AѠu|>{@mSz63Sטx|Md9U[8{TiQ}A!7ND{g- y_g*N:i' *gd@8| 8t1G}6>>p84y$f0&4 [WGD8kvn*HI'vvXh>p 26IOG*$Mim=@dC R3Ŋg-9~OvͰ#IvPHH=\ Kٛ\(xM$h\D9mi p7!$ ]m2W e2"S>G* POGխ$RzhGSFY*6-JCJ$O!uY''EIqBorxf HQs?0*"=D=RU7ABč`\, [F181JV\htTv9>Fqu6 _YIp6pRh(ѸWFPr*"$p."K|,D?g6N:ДTZGδ̝8{v] 2sU= 7-P18.poM,58hA?FEi]ܱhc4_|`aULޙ6@N'I߈(b0[fʿ 0Tݷh0BJ`? G~&!ȩVVNEQQѷ%&TBKh4F<,(׼g2qn]C4g]ra.{*#5}7Ȼ3Tw|FSY}8g-hcH~hލ0>{pV/&!EHx۹9=x+g3=eg֒g; rdٚY"^1td}F3}>_#R;]´'.r=> y=";2T $iA|HG״Hޔ`,iE|.颯`%zS.[Mbi(@ AO'̎!olZ`tQIq?Cr Ä KWq>Y.l&,b4`Ew:R89w%GW|:1IR_c-I~4#g(EW% i^%7&hO^h"J'oNY)8vmɥR|Ǣ\|:ޢr2)pH{% P[N_-@r% |`+JoMDB#2΍pT{?hWu }|vv@ J4S\/dRS`ڴV_' B!݄Ͼ8h| !- BR nbs}Eu3>K HniZne Ѩߢ2-YJ X>e2:5VKuGeE|)KJ袺_ $@Bdҭ倊ޱR|ĩ&8@xe@`5Ud˿JΌp}Kmm4G-2N/l4fym3EWr(N4uzt@PV& Z҅U%*o8mY"};h ExHM} #aB#{*qn7Akw=TCz,kK*|5|6nLJk#T,$=E8%R@{@g#GЫuhpQ8Q;Ϋ:te,8UdH@8U4gL#lV5Z@]ІP[d917{&aQFOVm[j5n@]IJ|m$rqd?Ӛ>4+Npj(7uڝ=uieɆ ]~JygRAV3ϑ% V }'Tb >6'}@0!F0If%0z k(sTiN:>/R82|Ӂ.h5H!ES[EڝvQcÐLݝS2ZIF <@i֑Q7uNUt\vV3JTyTqɞ=L=ТѴD9^;췍:aizp,ͦ5t⯓69wzYi6ǐŰxM_F&@P9fpHuHnh#~0g C|z >qE]w;* # 55YGЩy>8\G#oֺ[zR[ \!`#~`  ^?,!.y^@|]FpOo"ɬC g;G85;v8d#{b|軍-} 7 ù'CUO(/; Ɠ"}Iu-W=";o18@*?%жg@Cu]ww^\h =|E P3G֥,J޾sg0PIfŒdɐ,WBC!՝{$WYgX*p*eƱ RTNP!Err@6#gVlR l6dS#N0 r銄a87](r\>8Evv9;V#Rqq8=,sRA8&W)W(u3졲$!&P#W%9;^Up`9Wekè;}4 U1$>=b`_4ذcQr(#.9ɣ3__"gʒaa M~e +zF U0x\ WHDDQ̔F 8Q*AӪE$ 4X@G)4+ЬP#)Oԧ+diO`_1>+p88~8@j/دw( R"իA JNAH\vyR`2uۇ77ZkfkQo7v{t.v;=x%/=u/%,^tQ@ {dP{v9=BFa腉TInP 89:-BZNvNJ<uߠPT32Kr7A"qoT5J2Za4(Jõ,~FC}EVtPW̡<[d LzGx)z)9ڻLp,ާje g_*(!ň(>ASZ湵kߤ $!D1pN*nPa#>pޠ M:_#@L<$ p)ap9}OȇoIlT_LsF᳹r8.`Ѷv"V"J1 > ƭp;Gef6qb(Gj&mrDL| I%f:dm&U &EDzaO˘>MΎ"]omJM3e⥸5gNrp]1/>jZ/-^BF%dp~N]Mp6;q]SpFF_,M\fIX6ʠHlXո$'GLxr% :/ꦒAmVL1۾>u~B@шUrՈtٹ' p'g=(4g{[~VQ!B){ :- ^vA'!gW a1#VX5`Blq iK ncrYIH|"F֛Lt,?)CrD%RgrL2pblcw$uh.b#pw@Ż4z|woYwj^D./Ȧ20[*vF*J^M 1g节/m },U%TAzDK>373: G^/]V 2LZLYrzO:^ IԇR%H@'go4!T]p)REMF8Xyð&TIi7j}o7c1=Gj$%,EDirb'PZ6iDI 3I$@H2 \40& ч | h:yV@V#A'#D4!C ,({14 7L\\c^ ~Y,๎'Uq%78ܧB#n٪1BT~ ft|:哶F0Їilڮj",Nt`qOsN(Tsg4YD4e YrvuEO "$S|MhF΂ѷ8?d^OvGXUeZGp*KJTD(BRVN!2KOHa5 텅r $tm&3lshnS+8TX.$g-8ci[l쬏ޜVhnbaxq']tm]#0H4 gl´KUQ vzAnVn\lei6"že:+ 1jFGLuXvky,5Cw&"[1,̸?ͷ}T[HHk if`)8%l>p<8*LD$[lqQ}԰'jx/Uf ̕USü5"Z(׌`Ohd QȦ 4@B{a&\B%ԪCIEN#0y2EjfDsft5<{¥\#5:]#zfy'-F>KQ:\Sr/5i0 L:M;ȩ9~JXKNC+ܮJEnrB[z4ܔsL5 { {!T5pH>PW͚FF$4ɇ.E<'Ӹ!݀jc a]$%j2ri"Np胥wGЅ+t)^Rj{s}80muN>Gr D; +Q. +!p~׈laZ8~@ѬO sޥjx8Ч~rfm(0u~:ls>hM Tg4[ƶ4ig97gM>p:m|3 d=+SW$4,4ay=Dbk|"`4h[lރEIkMJp &8R'`ϊ6ґ5p) 1BXtLd_"&8X8 &KQp5 rzZaEf|9&@!g4[ن~] ~0߀wPPejZzD Y:EFD h |:V/J% :MJ$$].Hzј %C{K6t*N&K &8عpv81 Kɒ=JwCx @88KiEYv'Ҵ搃tKWj#YtK!G(僡_{vEFiP>F<}u9{WHO T v(}Bɒ%;?#0lқٻK׷ w}X9+Rnj;Ցh`Lї9c6!UkXPI--#Q%dsmU$OaU23[g{t?eGO@ws`O2Sj˹N8#v&eGVp麁 ҾkpQ15|j>tsLݾBξ^(OɏB}>lY>-{;ˁu ^I;tJܩ"PT'Pμ5왷} W^iQ wXcK"qv/Y9"]#iXtGqrmͮ 6y&F΍B[RzeS {-֥4][Bru z45j~5,SVn9!](!]j+|҈փjA 1u`襥<~Ⰶ;q54MK4I'`ΐN>x9y0H>D؋4rFs4 y+/=9„G2 HO*} eUus%]d60K*@}凸>>ZUKk0rrT}¯:1VL tGBo!=f,nnSȦ [<_lqp:T?YrKtו}c0XY&":7w1ƙx6u@+I9TR5.QLe0战9X,?p4-ZDӧ_3J<mXDȋVPUNr(%z@>{ц; QvjR(}v&HO#99=~g.s1؋iKGD!=eL|y` jDE?膋0.s HڝpRPr/ hۄ( DފvN5z?C_4 i5nB} G$!C"$5. .ݪ{^?{Pݺ47~]'lAXl7_2ʼ$ĬeJf64ٞɊ4&]A\]`23Yx2jTJ@eWh1'<ۛ;Rv>ۏWDuVn]|%I,-ptj?_E^m+FB噸DξZqs3n-]ۤި[l C7Y_`_Yaee<zQ?mkO> [@xp۪36e:N41{Ţ3I71781 #XHI5iq=Θ}R)ӄtld4c8 sh֫ )]$C}YIsN7` F4eTA=y7x-z1Hx8 h__8aQbCF*zz&L2/&^2R;պTH1D,=-tL%g-pLl9԰GPJW'o:N9Vg9&2}Ƥ ơ(-^JU/S= NW(Q1C'ҩ~ȩSŹyjTEn:cF"Oh8jÚ\IrvIORxC@$AׇkM7Au>4зi5KOs$jc^k\5yMRk*QѦ'&8k6a aЛ75b {ǣ#WKuȠ^I@ZpױiCm:dNyx N\Z\`ᴂ}^U5(22pP'}:8=$U2QM0҉hS>˶aEј"y?OsM~P=$uToRzMS1 r :;l_# qucӦG$g{ĸQE H]}`3OaU}pꦺu9Li_U3ljḽNI>fɀH/ eOݺx=qWmݞ{ZT0 ůO_T(3G@YgΧʳF'?AyF!MxDp9B.3fնL쩌HNh=(ʄL4Y/Վ,"6B:(>"q_c剫*E+)^o#6M48,c1FOpDU~}h~`Jh|KBä́&tmC3si%fKl ~݈Gܡ!g M"V#!>w1AYS(2w:tE]-3ukAB>✂ɚJ'Q:diXp@ x_ù]ҭDӃB3ɣ&`bi\jk^lb`9Y + } IU/7m+ڇquQ#Ph`Lܑ:wZ\o R8Ay88IA2G4ٍW=b X^@kKO/zLE$T)V˒ƥՕ>CC{VX-83 p:o?9WoYE}JVMOOI[!HkFUN| FEs:ٳwY-E y'f @H N0ԧk"&m>8A1V uԜj'I57 s NMdÖQ.fU% #/׸Cm#LXʬBd[^".@?[ Mp з$m7imdϤAָ!B6q8JjIkjeOP0 g*P2QÜ1 WnrHicbd5sRJwdLDHG\< 53!yie<7 P)<5/oylN^_yJs5tdǹ=F<# ^4phL6)7+X2( <89E"`&DILY~ "# Qv^h؉,~:r Qfre}oP #8jgװ#&q {PWmCuʨUK,, և>TvI5 &Xqk?1BC"y]WyIժļQ43T=8o!,~ĉ㼵bk!Hf0h,HATر6PV"Z.VUzν{{}y/~9=ͅ|Nkܡ9ζ?wwPף(" 㣾 8 =;e`ssˋյjk}J{}yHƁF5$igs=^wظݾi3ݷtMK瞷qC/^s\#ѼgJf(CYq\s'@܁])'j>H71f,ӊ|=h'ߏfBsۄf4~ 'Ь9Gh߅nDΚ08chݱx(@ (Pot5{P˽Q H)s03f<@Ɠ"l-&ۋۭj{eݾncN76^{$`'}` !f`{sv:jwgsdsV68dWsH*/ h-D) D+9ņ(e4 U4P)_bnn("# Zs@߳P0 k;jpJ =y٘l~T>/* pid8Nc70^ɝd(9{)U'@_-VS((5ͦ<3=gӕ2t!Q(HΎsF>E"#58-z9{qqD`&8f"g2 0km 8y9{)ȥyY]*ÜfyPQ?e vS*wƿ増P"o+Tr8[V8 y:bG{5Z|^iI.Κj߈ܣ;1oJދaZ_ViKד-c@y?1;*S&n^czĶU=vL BJ\ )ƆD/1 rv>ʈ<T= Smn|Usx "mgS'EHYhd!9P-.Iz5BYbpGŗ5SH/GuJ<9qw#TUࢶ[i e` N#s3wª$axO_\\ԤNZ&%0Og,Mڼ)NxiSCo$F⋎PrGIMp]kCBFDDD4LcQNsH}תdDFިBF.-Lp68r7~RKpZr^ոRF?CqqDDj ?F+PYHhCWlFw"iRsJEtS,ޢ7Qثy*yNbG5-PV;MCgV^D^m^Bo::uR㽁cS9 UyzJ7YdHG_^|#5~q!=bޱ8nq R͇5vO F$c!",k4OY_W1<)(~bՒfݛA jD˄hсt!]o)֮or6dCU+׾mB4oLTP Z"V-\'NꍉbqΈIאF0{Mp.x0C5,:&0gÄ|ƃp&یp"8@zA&8^S~'8P6LtH@/"DR3`Fz 2MP\ =* ?XyVٺi.KB"EN|x (⅓g!~ -3pRm[؈Gy!9;lq3z"`Gٞtg%MQOP eE(@:B+ +#kƫW woXL6 츈L,]&2iS ©[;bǬwKWfRg B"#KNir;jv42pR*NnΦC@?E6HHb=+7CIhgD(`T}1jP("ԅ||o*:"@cIKa­H+ :gZ0%CU,0YH̽q֝&ҚYEԜ9%Ru2HH[1R[Rga^'{AόF᤿gqjM֋3H^hGEbkR[O&-XQXm5\1֮zU z8shu@$ RDo[(r7M^' x=[M+>0N=A8N>hD *235XǬ`4cg~(mZ5w.R3Q\ywVPTg J1N.F.%9{'3tckgCau4L5R7}WOY|L$ko#i. N/o9~LM|5. P* ?1Tߑ;3)U6]Mu%83ƹ:AAi3E'44EOlM EXH")ߛ`e[!:S'R,~FVa *a3<5ѓlh"]`< ڍY^m=X\lc"u@= H:Ys*a:S8*}$v6$j*}Jp$.Ѐ^"忽_8$W'J<Wߠԉ.|HKXk y+D(ida^+191PGMaB+ܬ+AgsS59m]^g8n>y .EtA?uRub8 MQ3'Xas3Wq5":'g)eMx&8꺘OMqbi$#VBZm>)~HSs6K2$_nz̐9$yr'VL*͈ DqzV>nh%0=aE}i-7%!JnJSPԙZ:?B^`uk J붳7MKը{7Iq3I\$v<ō;lHR!Z&&fLdq*=- h!a4 2)eOyԥ >٠-?pJ"q6 ^ fA#W֊XMqxLGHEJHP1 >lqrj0-2%B{br%N1@3=|fA̯Y%EpB,f@1yM@S'lIQ _l]{tQ[%8qX̂g4 ًy7~J7ٿfTOt8[; q/Z?$gw{[=mԷ]y1RmyUԭyUlpa*z"18B3#rq k:u[L\ ]i/jMVld:;cG}ŕնӛM1}GA PvWmYU@ qy٭|c![pbK=1Ro LD~|K43t%%F]/ҧTÇ6H( M] t{qNנ/9%PyMw(QQ-.Yfq"Bi|鄳ܐi@LvB:ąxVkZ`iss# /v `F]H|_ 8:Zҡ%R=OZo7wQ'Obcvp4$ry"1]CJ/k(^VؓʊlW㹽ΪG NƪH_ޱ`3G3޽gf,5a]?G_AIrľZ4cS±+4+{#".5'~u@[Yfs*n98ΗlTu CMgdNʸs8R/lV7u$)^%]=snQ>ɘVTm9yi-մ&~Db8myn*,]6wVSaC&v ^p~8q 'cDl+4X~*)UDT2V} I\"Zv* ,[fv.!͆έ}$ԉ/&HAP7pRjS'F=YEb]pkf鑳q03)F3Q+:;aK>\_.aiuLp&Q;O nϟ/g?]7ҾӺ !P$< Es~g̜8$D@-m%@z/wWAHC#狗h&[ ׬S)^=68vR™Ħ2 ٔP3l%z8Q9XՀp?sDbv:0Oi|6Da ;Ć+ũj[HjIhq9PS;qKmCL+4P}:Ez@>zF^P!%Du>]ivW[+!AB'4Ox sak.MdO;h&FaPs\G.'ppS\yuƮM A<CYZ'7qjj׶ hjDtǞYw}^^ظѴO>*:M*#<@1qOv(y_JBjCBFAhmNCws Vo*5n Hn~b6<ygbμׂ&by O%u!&\IDC0ЉhB^ *J:)=jDA OBi+]×%8`,dCZ* LpO0 jc7^9ٸ,+@YpD]y])3 >cMt.'lxPP4) E |,\V*`P}ٟ!Smj7yMYr1UQ忘=Py"U理yЪn2>CcNnX!/PU~9P6 qX-;2 (H*zȦ."*ְ7 ؋K=ITgdM,\'N:;ot@|ۭaȺ.NWtr*cq?7@t_ЄF tS:ii2 +Jn4rP%>jV1U 7%uVM',VwE4UgMU>m;E3n!T lԭ8LՌ&_N\3{ӱv߲E 9@O!:@x>l7!๼T;^5ORJnm-쬷Wɿ@8:dn>< Om+WJ| L /^؋̝g|ڦ=|ĈٛFYJ "YnCϾR`,Ԋ2(K NGX{YKF3"R_&@@/aDFLh ͫhyVNZVFkx$lvY+Fԡ$ۭz /fsPt:^Xey ҩ4=n#MOjWF'ߊGz8ZEg! W".jX:!PO(k7/֙#DaF$ %7y"qXV*|Xpnm+;?B6N7 ¬Q?[\!+G0V' gD4rwm+<| KUy Bi+eBC~!͝idG}{gljg2H5Ixf}ݽ1Cm^{=ۧ 9 0@D8@p8H"1^{/kv$RET_]Mռ&Ԓk%kw%ܷ\z`zv'9Os?(yfp-[9s-"ŵ՚jӬW7Z}ьv:֑ΡN{su(iw;+_yˏt:Vӹպz}`_>qaXOnxo[@"zvF(b"8/#O jZ$"qLsc;jb(NHpN@. k-jzcۚ5tZYmZWt:V9rG<u$#Pp<9tȮ'J&l\?C9(d~Z%&(!L!_a,Un,;f4䏻r{S%]ˉ3&!zaeD6r]'eC&88) Bp3s%ҹ|'ȮN&>#ug*Nv|ܡ3k 5dxd2"n6Dҝ \Nt0J7;:g\HΎ a7 X(M4'ulVimoLtD>wp39H,%򹅜\&D|`_Ҷ]BbO>E^u%.h#I(cq{PFt+9{C did#]3#h6V<0Dtu&Êڨ @ZfNvt+}@bNjy w@WV;Xaݴv\~r.m"_"B`Xh.;]509{.( \Zqmx;]tI>   ]{Mma<&9.J(l.F)uNARdU A,ܛ/RZbYM7#j:]\۠'BU>iާzv{wB])_/~B;U}g(c)Ι& K r57tS&&8>tG r*.N8ǃQJ8 I#7Kq44'(A' y /I(G944B 0{}S"F&NUeumGL(׼_&\4.ޜJV {0(h6,Ѥ(3 vAF@! ;״%ADK QHoBDm.jVtJc{xD]B)"_|ʾE/"8_4xG|w8Jp7Mp|9I;or`bc~ |dw9+^,#.7BTfrwh3-טߠ8.fbDqoOeժ4q(B~׿E""hg}[,d,iݰ=ASQXB%||uR #$]TR%pgWax9%8; K im2;9{ ; "Por"?D ͪԉU&)tzbi)]crU/8 J(6^!zDH=tr'$'5, h|0 8+C Ys%DO"D2"BBe?H-"LJNЄ MtSRB.Y Dx"B/H=GH]X@q]&@iI\c.Q=uVNt r18aH$n]yp^ b p98 p m+S=D(pLΞTa젲%[Njz~V瓳.$N)Ύ]9rAK,C.C)"e,K@^.].7[[/ B4nuFζ;|E_ 6`Lʽ$+''mYl4פ  ܅XBkG:dM9[;(Z> Pn6[-8R=&˼\@'gFuK+@%m r8~2nmu!q)vhWFd^&֌pZgI^٤K$TML[ˊ+I8J8\'ѐ,I|*Kf&">'S 0m *$3߈nurERu?&g-8Y=(e b/%Dkb!Vo .h! 1a:-Թ*B /Ą(D|;Y=m7 Dˉ]7(JZ>{%0~pO >Aj3׼f2WNy[auR%+՟PaB0Y}U8'8uPXѾd-U6y7ٯ馳!P!ʧ/|u1]a(!`X?Zn9Wi-1h ǎF< 1YS1k(@*ݨA Jو<9v"%PDhj,9!p`6'oкO9|}FΑp4#Z6Cf״2V-oQIK&c-jGoH,.\^o(cÒ=tb!D7s5"ސ&[Ď_2Qk?I뭏ej?8Jk'J5Te(N]) DDMmgCŚLi gX Gqv}'3,0X`%;i+2!r} a<$4a+w(W g&D+aFܡ~KygP*93urA ?N1@Ѥu&@3,D:>KmO5~pqʲդSZP<쇊nGo}_SWTX<~y%*-vpŕ́TPl@y>_H&_܅h '1,]R]o`3Q)NNF T@2Jk- K' 5,' Qb-*"̈́9q l +Dvn7@/l28bCp>j3[>@tάx"MHPH5K&H'ݾIhm>*2 U r2B3m)Z K~n"g7hYH]oܞR(877=gN'='[ ^!J t$]4ҟ. ҁ!\ұvNFY; T :G7ߢ%F>&go˝JF?P"TBPO|693,!s.l+Us=ڵw,ҞTQzvV;-q5đŖ, $gUvFqNGvZr/Jc wQ K3GW\V9l2C3N_J3\TvwìsXhXIvYlI΃ ee(ϵCKΒJ%(([w} ӐK\eͩĈFv.v| Jhqo]B0%n7f+-݂+U.sa%ߧX_,q]n22ܒKۖDs$۽NѺNJįSE/ɝyDpaxuLsZ nTDaGfϾi[.#Fi! Y.0,fN\ Bp/W<8lXG4OQf@K#&kK~C潂{XHB-'[qk9=nn/~\TDN]뤩AN8Y08-d;28⻵6.}CxaDtKmf\0A03 Ю]d;!H$gSmPj.Tڻ Bxvրak%w~Uw: :'"QQgf԰Kn ]X I;MvuM3}Xa- rso|" |&-՗Qq?ɹM)Oέ3IS$OneYu˦rڸ8C"'YVRIq~J'?4qq~:aƭͭ)#qtC o+P:ZV06в:%<&%%䜤)P}&iDZ$O&LP#w<3 3՘0"l#a6LJte(_,%: XJ^;e)S |8̓p,H{3n t! ,JNC&LvɏA:\d1\P| d!8yz ηLplU*En'@= n>b)˿Jsw@9)" e[Bs iE^F<@;٭Y]r9AYw4-̛{;uO 7pf`_d Vt 6ߴm CL$\:!"v.u%LȨEhaŇ1Ar<'gbj)Yn=ߢ]6RN|)h DvT6N¡ Lpyt&x { `!T4?5j g⹮Q-I= $_~]eH\WB#WPgNf>c1@~Rn4yz'"ɽ]2SM}ұBu-yOěD/,F:vy7ImΆEۖ$tT r9ӍV((T3{q2*฼=?2W;LpSv%+T)眞=T 덦.. sqr29v1q ݲ  ;r?GóHz,ZC.MZ +eχo^V2[ȿcIFd(y[.vhm9#1Fu1j0Ml[G~ܧ~ 2=#k#E\4i}ntr 88 ~aU}Ӱmc+ՙJo%t<] eֿMfQDA ;yJ̪!J{CܛQ0}09Ш$ΊUq{n]<9Hb#+fBkE`ʼnӒ{N&綡7qJToZ*#F{¸ru#h5ڶca؆_+A*!gMfJAҪKd0}s!MrF&4g;A`d#;/%gi F\lc(}C Y}b[{y cS.Ys#t8>pb4KIN?W w 6[BrJBlB ނiΕgdDo| JffG$N@<0ф "18~aź!JB B*Qy c,$41t̼5oPyᾜG\3 3Hh܆6] ~&L.W2-* Lhk\88p84y(B_$DD L@v&3slACs@B>w=_#ЉGvM&jݥˮKܵRy9j3sdgS֭g8ەq ~CGM&trZGhQ?\.kx$/$&AΒ<˧X r[NN&,<#0STN>l|Drhy^_BiYAɾ3VWJ)xkHZm5A=KxhT{s^.=aLntm4{%ք>jFaS>E@]Z4GܯJ%:5Bsp(1&!͢82q5iVCڎR$Y=K*=2.Fyg=3͹39;9=Y ~4.3fu[\'P(cO 횒q,pD_x+B]N18bW.9{oa:ȴ8pr7hӸ}'bq6$sY=ڀg}O;ޡY"#=ϑhx2_s79HQ3`8Q\4pS='THV]{ٷ|+u"&qlr8!-D,C:Z$1Qh2J7g@K;6 sLe1TAaIɷ[DB(}Tȅ[$g Xc?v/2u8qo!YDmF.3ޏ+7ʄC36J+ZDSq}qNA%9A(~ ؎:I\or-)IV9/ S(7IQT)yQ(dކM4լO@笺o#Ԯxb &Ax؄zj7f33 ֈi@hC2P>c…r|ۤ\\5vҲt66j%TB~)TsֺgQ!T&D+4Wswf&80l6Lw8 {+|g'f bKTCPtV#]/]%#" Fb`Һ%d{WZV1x1h&BOTDC}vBj7@E.2quƆtB%.h^毺Y gp/͓2AhφnҔt BC ͝y%WYL^, -w}V=C g-aw_,ܬD|7e% ZdB Rd6xgsmJ&3ܹҮ'.kX:-O< \$Pz=!<;;w ^肥f{cmZۘ6WZJww^wn{OwWn=%wϥvnvΎ:;.~gk]g)׹+^ ,<9.83ep+|}VwRxȫ栖pA>mH8Zp-7696;t~NU}f%8Arp 8NZv&y8$ۖ$g q2k߇guF2YFs {@' s(jp9?əCp,Υt5jJ.j/vNyٻ;%8=qiw8v JFMx^(ܽs΅Am(@nQ²%4W6 in|qnf̏\k.Zhk 9 hw ѵD Yr)3 gZg'zȋ<S ͬM$ScMB-ݙK!S =M[H5s%2 &fUܶr)ABb+0=0€>DŽݐEQvkW@`*3tFL3ӐpPrMUZw>4:i 'A+ эFDe:7@+N"ʁv[L0}!EA)Q+L$;.ٮ83rK}2!:dB;A-:(Uz*yM̼@iU, b/Ktw~@ P#qS&jؒ4i#iӍ&8 Yk2ژk޺%$oB>NdTULM^gys3d\m\넊۴jI@QVM.#D5!r]N@aPhkOmGIsL83o([orDmN@wG~ 0dFV;$(DP4T4h9OuZ`~b{0ȼk'&NEKJUԾҨ.+wzg'LYbz󣋥>WCQ]P.F8 x74-aj>E<6wh&4p~&8`>U=k6OHuO@=8)8RI0'{ܳ3nYeNq;bq"r,o05q7%DB\unAN;Y_)LJq<[5Z \.9M3VwPe^7:%+/hwo̧5x0LiNUwAЃB$#?ke~_Hh<*HUpMw€o%=>zxESbq gX u aΦ=c񁓖ĵ7W"jRV&Bk)I&Lв5FismmպҥL :q6A ЪN?EG׭IYG09E J.Q 8/4p@Tgsˢ֫ ~I&G%Ss^7 rgr"|S9A3L͌ɨ]\ꐿpBK5n S~6c¹A1$c>&r{9{68@3 s)YՌ|Hvr }ިef!q#xgD$~Eh绁zNWgW@|A) ;C 9|K8WioOa g(*p>8!Dwc i* j13{@=>m?;HYC]TU s txgj'KYϣlPT0!3"'Fޠf,Ir3qCAs4Y4"@TL7L@HhJ" LȋVϯ<.9{vt.x3!1m1U0ђKP8=&gݸ@@ JUզc%4`zxPhZiy)'rҷAИ5ZSq}H'|:Lm (aA 9v9:uSKQCv( efgvmc *o6'!JytBuxgNI=hO}']Q /lق]A@:hCGAs>8\l,ͦ]YBXv1`u@{FCD&H!?d4!b<[}K,aaC@GΎMjs< y=`(7#gNfa9 8wM!9.Q%!{ҰF@;PXLYfDξ̈́G[ /sq~<Өs%*gHY倶@=E!/# ËP9nϕЪ&Oγn8x@g3Li&|Ne}acC(i)Fs*2 ^qV3`e ,0e6U셴y[N.Y'"z PpDHsYf]dxBQzWHӰ" @?W$xF$ u[xdǹi,HQ9š(${vm|zyAx9{6N;`i6drerݨ@Z#/Pu4AmX Mlp4ki4I,(2ZP"~8 pr}C;J7GϦ+@mS!XÀj6qP'9!uD"g&hR ]-(n$ƪI6~hshc J8?Q @% p%QGK?1iP~X  ǔ} JR'E¶%^!Zei;=_ʉr%~ׄh*UV,FIOb~p(5[Pq# *x ʒIVM0ߠ(FFF@ߠ brIp7h$]zy eq%44q%@a q|wzr|LOT0d}î':lpV+ͫ$.r*YPءJ^OӞRCC ߓwiWe? 1E7|~WhHnܢtH U(9;KTvU6t0Tw'_#vR+Z7)}+!ڈVVgb"0:mxis`Rl;S?UC8>,2iE=YS3e0ZDW$1Mr|LJ\F0ikmrZ Mͅ`NjPEa'ɹME-AjX pXJ[DJ.+R^LqYē,]z%nQ@+7*ӤjOLxK`xxhXel/Tʮ7ǵg4wM"XuugqBɲAPDȩL[mw/,%mqݦ8#}!c 耀YI_|^iYp sոh6? O;^uyjnE57=QN0y zxH>dA"']QQjk Ma8 '5/9K|#ELF9N6N ve94!hh$g2!/ Eۅ`x5M$PV.g䁛o2L~j{EX.n-vau?1OaϐOh.@,Z>?g GCE8vpIDIMFR#P4ܜZՉ/>r\f $mSqPy6D#$;$'UduYw CWkE(MGsJ}01ap23i);D`㐧^NiarJÆ8ȍ) gWj&pV9fqAۂ zUZ@npFE8dQk\4eSa!Ʉ/xaK3mVJGTp ">33_7+0[V4~XŽ) CB#+7i$ZpKJJ^1 Nfl|e&]h5FB')ID}Q{Z^N%"jo2N[ zE"+Kv.ٛKe CA\E5YٌhjSL#t綜?U}ݬM%"H~Qh!!r; 4ec7ϱ.ɽ*Muȶz>ErzD<8$i>ñkm"ٌEL. ْ/Wᑂ*Ft*+rEi-cX$8/6Fs>GӴJ*!@9FB| VcQ( :xm#xbB&"whHΜ%%฀xܺ% a$>|n@b9(0:/68=%|B0߄f0+ҽu}JS7J$?Aml4VĔ(AHDX TpOCf:xD]FΞ/Iu=af2KHSUbu^EEYO"m_y ^YQ?L()@i`v\#c-PP-H-2(50m0raa%=ΗUX8;$[EL¿,!F:hY z(7G$"X@|kLJb{ ts'LLǍG%"Q3pmYCpHW&g6j(cmۏ*""qR΀⩓>v\ͶyG^vܽmIeiccQLTDj V8Eɯ"02C |U4qR 8cԻK[LpOOKגmJ(;@'+]U((6(2Uru!)ҽb$(Ƀk?D(Jey1@\(y/M޼>C$ī#aCQHtl8dDM԰-$s})iW7mlN9.CCoh6P"g&$Gn:G!e󥂶Awn7rm_2 e\FJyř{6 VκhTS۝11ZNlܣFP=Kc/M+xp4U6nˡ2Q̩OMe5(UxL=f' IB^;] 3XLhw0jP[a_6#7۵ޞ-N =SB q0xts={jYaZNBȉc\S.Ộ@8Vj^ V٧ˁr- 7ѰT& &/]>ych"4YAx3@mE TT@IX4AAW,C2rdںBi/9]"&ϗ&DHs0o`z ˷5Q-4r_%[Mh<0G^N&8>?yn/Tg?H(F^-SX Η poCz.\l~}&4_,ۓgEΞLIa]2ϻ-BfD 1 !}Oju&ð#dMdӐu%gS.~8'(`./F@%z%j7 yh{.-DF~;_衽$]`/-=§g<ϑ^YR:ET Wf\fO\2D5kJRxş$UCP$>قp r 2wڹ9W%*srKh0Pٶj.L>hi1"D_YnaނN,|\ZC;a$BJA "(,Cf(%jYeidCӏ=}$?ܽߥ.lYd&~{S^9qEdN[.B[x[llgˉ~E`<^3V6WkFgX..OVpv;}Nkgov/y;vj]޳ya{E/l/s,{eoW8n, :!$= Ft͌~\-e "@L#'lV:ABzA# Q`NK2.8.'g8kX}~4I'tm*"0Dm${ $}%8 XB0l7Vm2Apw. RjǾ- |ApsXQ;{8W3Mz Y\Ȍ3,: eߟEZyDNtw (H{7OQv:}Kow%"zAPDga8#z~sKџ#n͵C+rklZZ ^q"=O||2 =LyF6 1% r# 7 b j9BW+Wdy D•ڇZh27$J}6Έ[mC@qZ%!Ҏt!eXPM06ףrz lR &fǚE@ <$א= c,۵qP":^@t % G`(9G- ZH6-]p-e/JiNRyJCAD? DM.TI LWH)czvYY&&)"I CHiStpFAUDY겹Ǎx &6XG@jDYF.ӅQzYAiݍ۠,|73  t+Ч距҉A2ǰh6>F1a4vSL7TQs1 @IT#b=gus+twA+^Pڲs^}~{OY"S|""w!2qpx-4l ^zSw&v[Y&)g> >UwU&$✠>]4.3 vqVjWf\*4P%os\~ztzΑ<zXٰƣ`t`!lztD=Jt !q#E@vXHMNP߄K3%Y!,k\$"F/K)M|1QnZ֪;]BO gBʘDb;mA-fAUsjx6u 13G nR*S)Q9FD< nR(bDޘRՁt" yF@8Z"K"ҹ?pSLp8u~Mv*)@C:Hv\ (A!mtBzʘpzYmvguDSJ7&D(!jNZU!?*9$"e`(xL^J r@ܡiQ`œ4փ9)NCpJkۛf4쁠+[ӻ!)zIQTB(Zҹ{HcϠ:OuǚGg*Ξ8ӈd穔B 6a2rjڍϚE4D F\[J8M#~-4Wd9ˤ0U&w}v-S+ h<'Hoi*Nx!nj3E:`A@ m N*ŹphR3MճNiF4b 't Җ[+Ɉ.3SY%RӻN>kj@,߃N܇~t ez '&&`vu.p7NPr:4E@#@RChbweG[=JYr)ۊspjR3e^G] SzWqQl SkjDg$І]On~,$MBAޘXrjcטLKcD q4*68ui'SXHs C'OZ E[ۇKy@= нN<ƚooUz<.ec|a+%wƴT|(FP#ٟ1^Ú.=8?[MA4LܸnrzG' &qZ?Ck u3԰Qڲ}Ta_4J KǨ?(LQ~S.:^"Z%\yc&/jQA?NRkd :^ IQpDrޤ*6WmcrxΦ<6 F9G Oۭv/0d44-@ {8EyŹHn7"1=w `#DٞNq6ޯ09.+йoho,,L3 d=WMvöMMyj@Pe8q3I/n&Q3?_oo-=BX?BF,7wL"et?S$DrGZ[k5:Eߪr:{d# h1Q6»EY`q)F=2py9:ǟ"'9KyrjD'&$ q-ɖ0}3?}+샣RB4ZŅw*[7N燪?A& i#4lss8FX.اlZIԍ1suJD=Mh|":%[C@tg4|(M4^JbD4J_3hΕD8?4ԟIF3Uo#_ܣd9w3-[MYv5 z PR5-%f "6&Q絪(DNF#F})̪cCB,0S? sm$4K/70BOsw4l,|^&TUCYm(#˵VM7_BW6O;[#lxCVE0b˫:]XIiSƲ"%;iܣCO`MT-[9$.8P|~{]iQ]`7!}Cs$@^~N NlFU; -K+& =+%n*H^hVKǍ kYfXu9#"k:_;0,^z7 45gݢyf7+&U3ӳ/o7^jp9q|lhjZA*YaB܃R*|idܵtZwa6|N2[K Φ9is=O}zPiaW(S#/'/hV<4P`7m@Q@p -Ԝ9EU3fwR՘0fp&5fH}t!pfrKsFcǘ(ij#;93(GEoI5g$iVQJ y~=GD*_+Iaɗ4Ӕf-EYBadwt_*$6Oj>ՒawC#[UP.W)φ*ӿ}i =hĒaLpA$YQe:]oƧΑNH' <v,^0DOvr٪ulR,e~]2:;ƓdwNcDzɡ Jq~sG=?T}}"vH6{FHӇ@Rtu՚VC(uLj}Qc=$ܦxdL L1 /$#F!XJ9[U-2 .%#"Wp40Ph'Aq0hpV- aR"CԡDo6!rŨL\$DRY*o1rJ¡I|֨KGMaLJ]'TR/[; ?X,8ƴj]DMrGԶ;* {A#TMi<'$9زJxtfR1H'iÂ|<ҫQj]DS:!:LLC"5l*,ҷB aVV}d=͝ܓxQ5޶4/q>'SEj$b#pNO'9s'QYS%Ē#t#=JU=+z"̬$2i|M8X`0T:NaIC]'=w+2ʨM8)G3,]VSù)%8ח72pn3juNzn\ 5JjYj~-)۰-%xT0.ji.y0Qxdd'Q~ G5т)[5C3KS:k9#+ +D_w?f$I=9(\bWh4ڋ&>$ȗ|.{-n㱫Y'2uK ['5:2;?҄3ENyYIxل褦VWiҏVSOc0n* uP=ĉxtYƒ0ũKjΗ=54<UPjxX%F8ir8R[gD͊!BI[ΐ2 ާH>:p-Rhn45nR?6D!$9HQ6`dN@>(ܖaqdE=,.ɔ (MSk rZNj" cn-:>1#l=| è,^oFXa9ZnncN"a|Fy8M;FpN@'Z0s\mX8IM`Whfk0~WIct ^i?">Rz"U[/>KEc`k+~^h?zzN| p4M4K!"ĈE+j,f"ml,x-d5g;}-βPH;W bF~`BAq fגNF嵊A/|]ıynۀ~{Jِ=NUSLfb|/y=,m=^.?FM"Z^DE&m" '`p똘z:CN*K;/#4l aЖn4pJ:ˤ+w/f 3ohnc9u$a;"ae<[+)ͅL,aU!?vZpU'lh[ə?_DW#fgQ&4P:=[)R (Mp\(spva y-6nI~τ@)~HiU(=PWzI>AMz;V.ɚ:])ل KDKށS{tD/5BUy 眦vF"*\0{zI*>|i]j2e[qE#=<1UBqK&Y w-{ {XUd|kP,kP#z`%ņ[iH<VI) JOAIx)6M4lHS飾g P)Vu:_2y$qe7 ?@flȸߟ5]H-E0g^PW:)=~2;Kݛwv&{f>r_0c\v!^HWNùb &sAi*MJH4[ܨHLw,]%=.WW 'ӹSCqGX^[8T(OIHYgBa|<@G YuvQϸfu;\"D_FAUO|ukTY ]}%m%K0۪Ei~d/ֽts5nj" ? l bAwHԱ)$J:"rR&}+wѝuT8{T,Ū!! pf^mk]}w&no-@lkv'f6MӖ`s@gK@MEM@(_86p0@:<~шۯEԎ8 vq?րC3(E,>u%5,=xQшH$qa PI*=J",/z䣶/2ygٸFlɐ^D`$X#7[ᡖt@#' $sH->$QQMxA@p$5'e~k_)ub8'W-}h)%3X% B&w!v_d'M'Dh0.RAijung@l~uF[)PRS+Fs5`Fbڨ\ 8A[~&(=BC@!ݝ{%WYggw ;Nh%3y+!w cofC2O+(!+HfPDA PP@ `IV(RGAOw=}P&UlUj~}}ڳnǞgg77c:~=' 8W@lxW:W:'t&`{֢nZ\\]^\Y^lE;q7:q{(wvCp'G9|𙇻NlYYVg5yn8aw.:ڹ3܉)g [*y @{"]NrknV[ ZPs T mLN+22BBG B*m^F dH^\BĴ˄DU"U|w<%DI~2FF۹G DJ~U9)JN*/N3?UWsi"f=3$dU L@Kx֬ ?nw *#Q7.Qmwo 0DMzE@DHȏ-*3 {YC$ț 秷h8IΒ8 ~J +婟 [ntyCQۇ n|`㘣ٛHm SS )*ލАRzTLF7)*7?U9FtrvM ޢ5Ty&8*G`p+:"0NHP. ! Jp>Bξa BhаΝU sn!_V$ bf.x.GS;8=c0vS P{܃q­`JCWB2T] z?;x!Ap6+(wW;*G!u)ACp>X'ɹp^3 )-QoAyPYF+\a qfn-7 v #liE"wRNC!ru*?aj[CiWJ^W(K`/RQlɫ+a^MZ#&Si_Mݡ~MjQT"YE@O#&D'88*F.,Y1rž/wHR=w.7 S׉Xg չY7X_'#@\S?U@"Pd(`R_ }"R0킥 <"=Jh>_5v8Yg5YYiGpW!"j׽F1n*a~%Pݶo_$;@<5 P,U'ID]{7V.W=ZAi}FO<*&j ?&Z 8Ou_Jή2 s0nJY"gG h|G 4akD,$Zj4]4iB|Ir4^*"g}$Ĝ0/ȮRgu:璳D ޠSueRڙp\(&nLNʍOd=H)ܫIOehڱȺd%01 ALGC>a@['1ݲ~҄I/K}IL*Ǯsu.vzm;s' +׏';.BZ}و͵ lIh[@=ԁ*S¿%XU\>3-mͬ+\H  #YX"1ݠ?F B{a~r )phgk}ie:!'gO./Bʹ. oaBJ΍1VNyJ|3z h&о4=nk}5q`Ln>X U!3MSKAJq@9[S(8`!ZD30{H&pl8g,$qCSB>3ISď*9Syb/Hp8EfU_c䒮uՉ4 a89$+T4;26քɊ=OqϿ?LpD4Rqm/bs5@A>[Q)ķj@+v4n>ggEmɆI36{X KqB(@w5WiPRv+*;<>5EU$$nHHZ4]K.Pq.$U"͖Ml7zj=ٖ|D+'ͪb)J]i1ѷ*ӷ5r3HґqgŪx tDW5!@p@̾1G<QGqt _ A:IgҘFpn$ͨo5 iCb09Np^WU q#8>[h^WYʥylY:Kҋa^⠾_,ȊmN/ԧt@goUn*ЊUZPcLtQ} &p*-JŪ;ǀ}rKvt*X/1Bb6taq)99É@{b$ /E GNw>!d~W'3g=})͈,-WO8Ei:gP_hgLB eD./nzakEoS̄) i%=H^` ڠ/įO6i'H>6t\OY” |Naq` =)ՍΉƗlps.Mq{hW^gB! twv#!M8 nQ]G6ou7kI@}X8"p9{ Q(¸Te2B@hI3pΎ A X2 * v\5K7%bar"Eҩ$UtLo#LUn\ K/@,P zۃo S +ި_ dm ;pӨ).*Le 's^JEeD#DQ(P5nȖ!ТMr: M*a eĂ"MMi캪;{9}Ӟ][GJT[w IP*gY^H ]C~sD14-dD%u}A%k9<ɰcQL0<4K;MBG&<ْRq|^`5 Op}>kMpjisI2V;J,211N/[Iw\U/|>jb8t@׬^D2\ {Ę@\EEF2 ]kJ*{#*X@ɃL>xhËhI)QĂUMC&AhdBN! m2_ /Q&p[:}ۂXc/6wC#6* l4N{DW6u@b$r&b(IhASk7X& A,f'$Ajٔ{GwC5/24-D GcZ|Pf%6]פe8!H͈<:(9ED 9UF@R[7ڭDk6pcb96FJ?C^`TiJ.ibRCHʒ=5YSdћM`ۍ2 %% *ݸ`($пb#5y~#_WuZg_fP,H6۳QtٻhԻ`e8Ek1[E 0g4"|&^}q+Vԗb;=»"F &D7WyXoyR[({px7~tL LTnUpQߩ:QGx4x#o6ʏH8p`}0BNp[M>@!MapIh}?HAz[ertglNʴl&,6{PCx~0W>,=ZoQ*XKGYIiFu%X}nzDEMu )yO8vO0j!0"ȘR֗Vpp>]*,ɔ.~'OHӮz VGnt{!œ Tu@v?`:ցh-R3:'.A8Ѹ%p_k WL~N;w3:$L\)3YGݸOWMpq' n9sG3Uy7h>~UΕ@CȠ&pHif@ 8}HÇ{ݔrQhNY mJ)ӎGNR%gWXynPum;rBa,/=1A}mW& jMtEN,=-~]'y*bݶ"$u$GW[]-)Љ FC3[ 3 S%HdM6>t؍%קC}^rm?.}3ݝLG߷f;4WcK4%Fk7'zY(mkcQ{PلFXYy'ΨStJwˆǞ+ ,X8FCsgKE1 ˆ}Hn[q!IyӒ?7J+8gUh={ ԮPr3 D@qFa%ލ^FaD(bGv bͰ2jK>ݚ8i|쵁%bLw*65#2}c4Fh~rGu=ms4_n^|^8$Cn\n b,@/=$` ]$>bI3Zb%Ӻ;+j4i>g FQgFx~>ܡ_mA< $>V{+y妾O zsJ_"Gٳ y3y!/PW5t }]PY1x%s<!EkIHat눾K>Qycȹ?yҠ%Zv(wǪk<< y -5.@< Yk̥eUp/- _T@=azW_* g=38tp0joٳ`ā<0 fx$g&w7xP.sڒ~gӻSi8QlZg2:Ė20;gzÑ3!i4{U>$s@lNPe$(-h⺍H31۷󴞟4byдFl9hFI~}Agfsר]jTo1,9t&Q4~eF1!~F{^e?.pAy OvԞz[D|ӷ{t;׷7`n`^2KKTl^:%Wmt8?A" <ùhOW&S.Nָ ;PSɄ Qx@;7 9& &g/7qsKG=t'r+6-]e[N)yM&D~(PѨ)Ъm }Dww2 rX5+y+v&xHqq6&_[$8nqCS%yN>ɻn:JVcQj;-׶RvA \#n@t‚󕵺Ebh),x44K J.Rce3CgR)!ԵK?rCR϶+0 } 2R" sΘ,KhOƄݼ9&pNh$> j;zLB&<<ոzI\߲u0"2Ε0}h!IE\7ݤ-&nt ݕ[Hr+0v1pwU_0Z%=tvYP:&GM!T,Ƣβ# =?ӕ<4LiieʌڔLŴ~#(E)a<Ș0I; P0u䋴cɏ3erv)b==[۠@ &8Kɷ\g8arvAłaI0}?`j4; l78NWS`z.\ˍ$%m(KAK SE/$8n[I x = CMD0}$?J 6""?Ssp\1D@Y,izRIv&1 SFH0`%g/2aBb S߹(F p"zl8fq\fsLQu8WMp6Pc̈?$@ʽuDÀ:Ak ږTh_"8A|vc Nnܽ\bߚ"&9LRk;F!Ed|fXtѢW_I2%޶UD}NT xQrkDp_s8r{s2NT'_؏;xDMLzL>bD) d `RX/3p҆"OW^E`a/7j:y⾥L[&9?2@QkKi}eۊ;TfZGL {LBͨnd7RBC!͝y%GyǻEJ$y̲cwMJCїwq 8}wr$€m dpa.@AN`zcBQTuW{5Y,Y]fҿfgfyE3.#gȟ߼zѮCBAU{ uu}'Xw&'`33ˋKsʵJY}ᵫ:ŝG׬Ɲ5ՕN|ӉcEk׷/%홗tLt~c|;.0t >rv'\G H ~/Yp&8N1( Yp "g7`!1'9NHvQ*؅(20*On2b3!?!Ѽ'8vrzY$#赁(;IdC&6O)"i^E0 |k9XqVp."8{-9{ Q1w8sncec0\;Fm3pVT%Mr'`mrCXxт˄A%:>!:šV!¡?y#ڢDDRq':?wVVɯ߉W;GV6AV}j^Yt]YC ɂHIz8Awj1,jr VUKpRK8qy HiBDA1.4"~|;oB4Ս{#gѮ|p ]&<''}*RqP>+@%v[<@ʃ1}FmygOUq54.4s-+l' S4@I@kRkmnٜlm,-D{G}[M@S9h v{(bq&! K(Wnrh mH'7?@q T 'N)M8zW(!8žVwNpx {mGy; *$fH`肙إl8 ꐘz\##4GÄ3¡f6  O a(MPDBMZ];b5lH|n刔a`:3H[R/'з5v;AڬR/8-8Wֱ^1)"$IR ѵZMg.RCݩۀ[KHrsvr OR'ѩMxl#@ynv<\8_-? j ʧ*@Cd37i$k{BQ6J~jхicTXQ5n`#P}|r:7 *lƗki$jmu1KdŮM8P|肠A''3ji(H#OD|, fI>(3M#ڵ]6^tI*9{+xEDtQ\e&8 fz<ƍШ9OprvG09'<דWฮTb)\5lN9]KZMFA^m%e>>tNqa'\n!go4 2,YcAc8 ӄ'Db$¦>jҴ=hD4(*< 4rz9{'Wa€ |/߄e7;'(>9G u?9(y8IUk#Q1!:Q(PlêM:ĩ!CNqBԫ\B ײVprQ.LxࠀR2)s張ԭ@̓Pɟ RkW \rgL =>sle@4AtFY7uA7͎={F)EW1p8M]=J`sbQ(7 Wsٷ*gsaZؚK( ۝=}2 hv*EѝuSa]R'Ugw ܅m*1Q!gZZΔf;CV$H34S5$F Y- OX^:i-)~]o]pL˭H*giq:nFLbr3ITZ"is| 멃Q(޶5! CjrNt3Pf]EKΝhtWиnfӫ4fSӒөC7 ^LB@)3w/#gwPyZ\HK+&#[J$3()L|QR ǘ%EZVm#2oRoSNN54?Π۴ j$Ǽ[+]אw@Pl:Q۲&*' iU[ه  .PCL89  /4p W{&r,q@=<(|g1/řhƼ&x༪r9LpwP61Or8$/Un4w>o20svaFX<5Qia! J,v=a@@0ڂVhw"$Ae( 4#kE%R:$8| y-iY:'ܦu@?!@8 a"ŀ:C΋mʛzpX/5B:1ԙiŒQ;0EK.1r#ކu Di&Bgi> i$@ SLC.GtHO9$T늲&)qў)Vٰz$/𪉓&"si9Li3 (f F4@VPvOEfM$ `]dCNiuJĩ[07΄=ٹH<sG֍hNͰVېD{48^iIL;| ͩBFod)=J" &nAKHI8!:L&kHtCh3cft@'@ ċ(D o?ug@[XT2$ۻZh!1T_ G+CaдXvOm y0Iv^oܰڕtrI-v8J*(w N]Rnԫ-\^>Z@1 p$Tx'֖&81p&;rrv댁%`4 a!\kBU^0Mv, Ě+B鞹#46Qg ^MfR KQ"KIyNePw@I䖉l(T˪).|iQ6 ÉuWW(ltJ*wUU\7h*=bN@L:WWU0B uҍY&О#LTf\; q"V 4<*[FZMb[z/%ca[vT/)#dZ#F> .b{EJ9W4ـ\:vc-XRCke-h̩;I!.NY("E)^ꊄf'ݕZ)_Xv  D`0*МUu_tìɆ09,i\3,@Btk@`8:F%Y2 mLVVׅIƿ؏QmM=y bg@#R n}r)=)\{Hksl6BfPBv Ż D\;e]$-3) {zeJֺ< #zle/7&>2[x808.`ӂ]ݭ.0\Zॕ?9 8y@,N%K5.]Ln7qZC-6M^2Vh8 JB"h#JFFlKթy /nEqk=&TFs9MįQ+ 9{؄ Ke&xD6N9 @ٳ+ODxwoGWnqqj'}.NⶕGK5ܣFG[oT@^aʉdo0xz'xo4ܑʇnaN{my?MD`M4Nx-ݳ&Ox 2f80HcDZI eOeFSbxiǞ>zeBpx H٤Iհ &!r'j]Ehɺx;/בLx\q Q#Q]בMpB Q#8jNm[C8bḙ,O44®$GF.)ABb1Ǵ1mۑPR܇X}H]*9{ʗv=xՎ]% C^'8\OV}' 3Ћn&:T-fty&Y_8UY7Zx/V%Fp-ݗi! a7'8j?z]۪&Lu@1yaMM0uxԌ|ԩcM:r(C"HdT1tOp)Ho{نa,XЙ3z]T.[ l+^6,Db4+6zN6[ h8DMGk>g&kPj]ШuwY?ջ3r\jlfcVC_Uѫ {B@&;˼у8NW+eɸ4$dK׼sV 'noc>Mܽ$ 0 ٲz~c>M Y5 uR=,mowjJ$q\:" F}Ѥ)iT $gLGMp U_F~G ktIEr7`=e,"%Cqs%Do5|J@p%!-*uzD }0|>B+Aq֎i+ jj> sr+8p?w\:7ܘ1ÁN&8{+FRe&s]_ -8MP3 :3FSXP4-%8Cp^9Ճ냲a4<ֱCM\vdT=((pBbjl4 .n}r~Qo봵 3 %áAcFA4{v6r9uw isi7Oze^ |vPP?6tfEF1 !#UI_qRbK.|EĮ&J}<'m^D3p^`@Bqhza4MBq9cg$LHLdPr{QDP\y$yD(B"W CMnվ-Чs'VS%y)9wd7H\v1Kܢt&r&8† ?u[']Oqk}&4GXwo6 iIɯ[C4^}N66@Rs2%9qe3G?W ݩ H:kZ1!q]=~,o[uevbg]KEJ{Vd}[9*60m&_f@u3N:{gg"7.$@N'ԒIRn Brv'IFz8mO <n83+К8 CQ/9%B 5K@YE>y@}-9`Wʂ,V`,+Pg`>erE3^#RRDш 7pe87i ڪ8>3Ԋ"5ߠ$8!#Q=t~lM͵]MiOtAޠÍ:琳Wn!!Ļf' .qDk'K#Ւpc$5휓C3K vr֔< wtaTeGcQJXkW/]'Znmkb66m{'~s9YlB}/чvVMyjj#(.P'i%(y;f"P b w/}]͸T>t /54\WR"go1A *<QʤEζMPB~-$>q/9{J C]%SӪSO]Ó&~Jl(f?6xÑGG@p~_p>Q7 &sq5iv !%QG[Jx^.-S[@Ңqk%K3b'%veZtH^_vujǰ-Rt8=LSd 9 E^|D1, m@W8\rNpa6{&3 :VtsĵHT.wClPNw6BJv'tP{0w&ʦeie$_ExTVQ,opc7MuB(ɼ8y5:"E\j~B"(6'D򆜃G+ut% IbG/h"Q 1O(@yU+6 q*Vt\A6MhBh R4 K.j^%yBFPu8O>h|*D>m41/{]s,Jl ӹղn.]',^$9 Ϊ)`܈/žWprįMSLiٌ̘C!8Ga PHBRwNBUނ8TT#)"dͧͭ@>1c%iӨ/n}dp4LB#I\Q٘CUBE߮{k(tuVoM 58p8t~`aTmUá-#1jAbFpԴ>BS1Ak@5#NE1wH[[55@jD>AgbQqC9hM<E@j/S+$S '}6NU^Wj+$4;'CكEy-;yCpxwua)9 Mp s5#u_Nِ|4/#a!fm4zT'$T &@ ]ˢ|h AF.J6J(Fn)hTb` (^I2p9 _UĊӾEjMkD^#8jOnt o#V%s%8x`uDYE)Q a7" u)N^Ed#;@}q'cU!g T A:v>D]P淬|P`}h6@,Udr 3,xNIUBY.8;Vn$Ȋ>mq~Oˑ rj$H#d"7YMʽ()G9>Sqњ/S%5. TkI};[Bo&VtdBԑf.rK͕W*~4L!Z 8l2~ΪXbÂ='t(cDV:hn@ qJ@{V݊A?]-S S=B!ꞺBݱ[tr:pht}GL>A f. [a*(ѹɺ xge zhn.s9yO?ܹ+VBC"͝ %Gyzr* 3Q3~cc{g̱kwBpG8< &C"00>29(AAI"%NUwuٽ]\+_]Z?˭Ӟ~@g]j<wLg?zñCAa}F /rN;<Ng ⿻kZKz?Iz#Iswu\'GI/uGhtzk;nxF3zJߊuoNr|0}+AtZ‾_Z-nL݈ܐ,b{Ae?D/]+"4ChFajӠq4pVss]>Ǚ avg5.pa fI?jlǽJ\u:^5Hܻt&՝#N/9Yq|nW$YH!3X)SFkIh\!@'Z-Uo.=j77.lvl)j7 ͤt#> hsfSh~ք& =U]LӷAs@?qA\ Dt>1d0 ,S ; pBm6 AXlZ!\@lx}%9z`[i Da )ncF\cgX7t*TP[i;7A+|S!b0aׇ nF JɈzc 0Q8N uT'Y)99ɩˉo(  2>^'q#@`:ZOZKopot<{9DjS(lm 1j,&F8`  QcA]5g0 COCib~C@g&@|\?ϝ4!pw|JhC]qU<܃>mDp9WA3&4.Ʉ4Az{% 45 4z_ /! /"LrjB}??KB?DzY6  'ǴmT[&yLM# O8v_DӺDBdVgnx[&54sB8c;k7x'9 'm/H|ʨcq@4|E Dm+!W$K=!YH$Q0.za4"*n SܱFDHۖ.t#"}6 U\C6\"EA.Ԏ}Efi[S:ZWu]6R"VHM>޻J/N10V,wl&Yt~}.q< I0-~~}6%c"%}n!T 2cY H~.ihsyurm^3i-1P:Uu>{ KF*Zױ+$yj;z>ȇe4(,UEy:tq\Tj~87㳩 NW;Yt>{m|!}gC|#cs{)Q㉎)Y؋U,詆{,dkυ Z׷!ö[ { RFH7r1r rQR's^.vS;{շB좮w%tj|7H ɣɨ[7ewz]1rU(qd8XDcg0y@0IHj Ē}N CL ,$(QW$o.$ݬ;dB@H|oZ*]+RIt_"} 3w#HTӶuۍקuzCCD(ozHù}\WϜiH˙ I!:|D9,ݟ YmЊ*E%M9tf}_͉:1t8&KPon: g'POULJ}hNWTn:){VrdçPI&ii4cԪF隗WfvlM-JV.a7Cx{(DzųtKNO?]bɌ7|[:\G[_ғJ,ũE*"mt kl4ԥU)l뵻=N[傊 6j%+uTU$jh>-߽ec@Tj!C%룓ϖQHwhZ~AJt_~Q|%tB}.ոrt$DA61w,U7eЁT<\kԱ\OhPTˉ PN W'EO7bv21O6d:@Wt=>{ D[Kzcz&>لE$|NvT:]C&8_;QqtB)NR`aWr=AɱبgMT (Ѷ)j @g aNbH8q=:F]1o;xu:@q-6Y:byU1{LS; s."!q"i9Nc]>Dl}nTʳaKH %ĂoV{ᡓt.qYrQ-֗rAD>N7F#}2#|ùyvDr 7@&M8U‰ ' ^֞ʹ#WaF ź4rg;nL}me۰q-nu0*GYj^D`V$n֒(y7HHAM*9⍪3p@ pb 'ۉ G}Q"N6!핛ͣ.}3_́afˆ&٧B]&M4, ;+YD-+5r`N]_GFAEe"ޛ&.y3S&NCãčdKk_ Arۛʥu,ק1o[BOB9kRhΑg1i,&Ga^:ף:$@NWJh ƾ) z1,)~hi)i3Q,7&Pm@v3zb 4*ȣL\h `Օrf4OZ6Yqƛ *#Uy$$=pVetQv$Ri][X0%Cz(CzdI$ݾx'=(8bÕReuGdȋ-sf:D.gx&}]Ne (ήԛU' M8T@'x_#BnB|vK(;4_킮4n[% 9iH<^@d x4]uc-2}V[,A4Xf,h>c!+eߢ%?&`1 :*|M8٦O҂FسBUD |}΄sJ'2 Yu֫iB`Gډ gyU6U()gG&v"$L?)DYnQ|äg$%iUVx_jեCl%i0C!фu ͖‚IHTzQT*&ct=*}(B1ou&!9#@qtkll:/U9dDn:zDn*Ye@MzErp4H#816d@֔ΎY=UA'.Z Ȧ ⡒Ks y>(Vm[Q:Y0Pg+Dk0[oJfCb(=!$Oc &LǎB\֬hmW˗Y-53#= 6Ҿ?,!""OyhTC&Sg#@xg6NjN1L؈HjqlAZ4Hj, @V @ bHO϶wlǚsgC:]|6" ,zQA۱!L=8s`pFΝЮ4RGSpc=(VG!LuvJ\sMMܶp㼹vE&$~ yyC^{ɋwP|C3g!8=M+\Bg8|Pʀ~ڨGp|q }v1ybmYOy–2mfFT:?,Q;vtEeI]ɾ"1t(usDj DSV蘐7 :o՚(V芒PbR =ۻʒu+>k80>#-qz34HG3g7*vq@ 4OZ7j:&KD.W2e5]I|&D/ݰTK)뼈j |#|o:@vh)͌S[tL㳳La(|7ZSE/=$dWpWAٛjs7+iX)J&HFK- j\t"U0jۀNg8,7۲# TE &IT5bwTDgLpBON]Cq6hqtd 8bltM9| U$>8sBQF=2/P͝F{=M &=OM`ȻRU<D OinnN@1Kj8apC=MMx3u 词2 .1P=GFp&8@0fWAE %D;Ĕ= @vÒm_:KsF!y|Jc⾤s4HQ\T!" \$Ho=RuQ 9nC*8&G 5㽞]sS|?"U>5a5$O$2VHayc8Ȫ`j .D!%DmKDA7BT%wQDe%DQMql sv^sf@ː :&j;"||*Չ7RS(MEF=ԎTFBa%Ͳ^Ns&ߒ?X{o~Y6*zXsEo7Z.:BpԦ }d~Ix#gg߱eLZ5|1y뻍E3]ƩӸ_gZS/pU4lRU ѼiVG5U|4nJ# cԗt8MmC*p18~pGqJT]ڋQ0ȡR[* YP,]os%}dUiFE̎:jJ@diDQm3eA%g{Dx&t@j"Ѩ3z i>ȀXg+D3.D<0<|F+pԄƍgDSYɴlPݢOڍ?#7^Y;-cߑ8 _{#AP+5/PVUا\|60!at STn RfP*kw+>̈́)T!՚N锎tcHpz+fTVŖ5+8ijaE:|:ЁB'O"#u|Wr\6؀HhMp:.G ̵{(`\oZk`Ӽoa@DɘXfQڕ@yQ cj .Dƽ*(RI_`jsP0!;JN:~(MrGXv2{uE''$**ۺrC40hFQ-A-hHG߶?y싇>aDpݯglZɂs?( ʧ_7JH=)J׷+$Biio<~iIԺeH"6t-EHL^~I 1r̴ݘ邴.v]hvFBCr ͝yeYYk.1*2nT+xrzna,L[A SE2l !;ʰ (0== â1 *Fh2s=u{dgw<? C^F䥧o>_(9v Q嘆 OxVwmw7nvO8ySIvN==4 ȿNoܰ 7?sSgh!99Kz7~ ]r "% '80!Z DGqS+΍85V8P3##͞;N#*}6@J&!#ژ|(NO.Lj@o%goBJp`8շg" R%2W$ge 7DsCwպC$gr!Vij) e]ّs>h ?C(~dO€nr*H}*O߾jOBv7>ytiݓj蚦pg@_%@ϫ E'Hy@!D5"\!}=1q!}0&SDi]vŔ]Bx=R!rD8- [@uPp8ϐ/ }]DP Z젰>MD˝2 A Jt[ĉ~=X(ȅ_K@8[P:V9z0tr?u =h¡}(l:Yܱ̍>$ C;( dݡAgGb:DݽjoJwsyuwgKw% L:6.AȊ+p0αZ#~Zwܱă6@IM@@@rv p8W+p~=' ?*i5E]##UUHqx$).T?V@rg4y֜i\.,,IXԺd[]}$ʉ;@q=9x;@"DQCsC_4 ˒5bz #} ETtרLH@ '~rcW,}YavEYr09x]f4bd2Q†HP(~O *TZU.aJ$ H2E$.ŝ cZ>rjCBey]w>C}@. T'VrT*| 5GNF'M4 z 3{;mp0qQ4m*pOeSmp8F3ҁs]ΆR9" i\4/"¯hUF޸T(Oc_{XtvQ r*ܥr][Bڮh$;`Ί#n !zMJ.aa"6&%LU:uBM碡?g?BuiN8#"EE>V쩨pA8Yؠ!J< Y KO2H0t`."ڮr8͆>F[8*GXYY\XhKBDX)L{< Nl3_=h-'k e;H{ *DPR0!k++8pBr[ry2炣W[M819 pdWξ#Is(`C}Vl\SE!gM,}ph{=6i-i64l @Ås9'TgPk\:cr6ҏ\γ؊gSu bRq<^<򾣖(3bQp=߆&kQpEPOQt{Ћ -"ϓ*Лzm:B z0NZpgH;6HH3n٥P Q9#gN1Erf+XAZwlpP$K\p=Hmp"$]rۃaO *ύ\>B\h\-G} DCGc5* 6diVQu JQy61Ё&rﺔOք3/!v!n9W8ݼq|Ϻ܀b?: ppހ~B84x*X}4Yh  NE) W?_ZduDEC 0Yw煳E(+z^2O i f0" 8 kG5BCsF,˝="Na75DXʆRmh@@k' g 'P]8lֵWf %P Ҭ7"`]h^B^dAyj[ Q|IB=W=q[4 ;BblH˒Fy4l7QHI)H (lWp=@uba8ZSwrQ:(Q5yU]NG55X6}6|7.,!2A3Pu̓<_!A޳jgB`2d@Vv@I7ۄŵpO Vaͬ-0Dh8#?3ε 9}9{y?&a>uok^vFA^\U1I.?JEa(O8T] HU7B,: 6LDUhglEX )f#i\ ګ[qM R;MH@ inP "HU)Vzdu!I=K84%R=R"b9rխ}Se)Lv:4T{VM}&Pv: X N{m?tg4:8u܃D+X鉽AYoDJsؤl L(Fԟt{I㒹*k Řf`\4=S蘘= 4p 8!\n2{v[C\_ek.Pf.m-ȅA3iua+1KgF{ UUVWl|XIď0SP"{ pb]$$ܘE7>4GuUkGP'8CyO[m` 쏣\6XY(PO UvtGe)%}a\!b Yu⇬ĆUr|({2@i4f!*DKwI${TqLat6] U(#!/FS]2ҳA{gY@UTX$/ۣbhͫ:g̨ޡU#%^h!vdD|& ̂4A8Qŧ,_r9q%Cdi{*Q+HjZ6`y/z,(tF\~u9 410Ѭ;oP>4sUH*g@}鮯8O6hihpq-J9ީ/ךhhTK64!h{u4m2,R3}=feW?qЍVY4D;.63#\)DYx]D_w<4@`* L-zޒ1RnC-7(_&4t?9{Tp=榁>tqcviqg'G ݵcX bR &^fV23٩b+`>8Sq{Ĉ?k;!3Ɍ2U=DI^Wk6@8>@^{_6&É~ڃNvҶ$gMjyezVM 0%X{N$}[o_XI.l9C0ʵ՚SXspkB~1C\t*@7l1'Znihn-10@R„b Kt;h'e |BL4SԌ If/ ѾZPLtv [yrםKo[R0_T&8ϳ'e=cvqrB+"~E@z4aҷ{ًmp pnx9 )UcVFCg%3W.rOu4vn:<\eeFnJ.mSVLqU?b9W8aƨmGuuēaIӆ)#0 DnΔk];MvJ2GW㣃NNG}W\lޗp ,h4.3c]KHG:LHGI! G@8pqMu5?Ο<DOhKs5?IbjRJ,j>aVCvZ&j(CN"ܪ%O⺗-"/R>D\]l{5*5$VZlcv=%8@pc.mBȕ}cEn"!\3' skgy< 'ɾ.ZwыkE3G|]Gj3WtVnP%$!밁=ϰUk9bݕPfLh X0\n898sty"F_6,*fIwFTҚDEIM?PA 21 =$5ż/(^eKV)OOeYUIK¯v26Yhf# d5q#rT{yIU_̉]fFx.Wpn!gpd?O^uX¥Hҽ̪>= `."M8{K6 TR |,>5׸K6S7O`.4v<64H[opp}Ĭ_oBC ݝymGYa0›sw呗\HxY&we)PHdF,\@ P`IYJHRKЊs{N+Ts- =t1j@zv>k6l #?t(#'4iΎ `rm/WZ>۝nw'6Onݓnًmot7{vz>ޙαScg{5O4b(EIjUD L9<΃|p>yU?:8Mz;.#dRN~^zh_6;$듛'vnDiFsIsfKƇ M?#0p"N2 !AD@9yt.R$րʬ'3L3եXQt.86y&1xf nnЃ\(cٯ#܆`Զ.\A߮X_ I47sfx*<~zKΖH)׺"YJNPbDMRrQTc@mCz^ ﹈:\d|Y]e(#ZC'Zw7>6ǘhL[6>Lt8gKz50Z{tP{&2( 隄(׻gೋD!r9C2q0jw͸]_j.7Kquh '|E0/8*j)NC=`IDTw-F7ucQ.MW<mh@1yP3 hbFtbMkBh:@[5hz˗H$toY|vڄ'\$|sЄ6 yDg=*Ѽ혠D+`E`.v)zc܉F4k3,9.>'mQ8Ku127W<ڶ2oN| &D04TnQg0D2z>{ ]? hF0q R 1x\.!>{ T@VRO ` 2 |a#̈hkODw&DOY:𘱢`EKVuMn.RϟuRP"6m~R)V-cMT@ \h➜{{ 0,8C >vygp&XivS4Q8֣_9BmWqG)I)˹msI>@X\u!;V Q4".4E5X!tÅكh*ZIA^*|aBn TCj<##pg"x1 y}a᳛MB;>NPےΡ|Ps'|4]pMx׆`jGI᳷"!Wr)4YSUUHg紑")st.*W:%"#K4Y "`L8 =h 2U*GeYƯ>`4~sq#4C]#%SS0QtjL&n.\@+D@tURAq׵|+%y*͋Bnu?Ѽ];}کԵQL})+.> gLJ<gmaǥ{~8>D\3FJ$< 4#HɁv &@i`ZJutzz%P PF#;DoITeR|v UķNXdIKt/Q9Pކ^kB15dxGaI1%\BkauխVcP0K rCJ/S@ZʒE>jЙ\g7@ M$*YgaPתw(>J63Rslτjvc-&p&)UJQMRB I?Aל'(Y~ 2e|i܉JZꖄ76HtDlѭ5R <"\mrç>8`.8P.}^Hp\2Op֞'E GF79< s\G?CەRqBSVJ/HU ]~Q`xMҚ#͵hφ N4/t]WhϞesLxwYAC?]EJ|61@ EC7PksQùrwdE EYP)QG{Lp<0P!Rܬ(IwA^H"ʝq䳩M<;,Ǚa~@YU {~/Ca|AIPyj=lB4%ͫ]mMHrϤO9Q[:\pV$Fs۴zmIY8qv)\.Ǚ4)ILUHuJa <໵iRAO@]hӋQ7kQYB[&Kf!V9WX“}4aB3}JG3-#gQwKڔɗ2cr?KvzF/Y (bVܣIt Rs<6i5+$)E؁OdME?5 7^4+6ZC9}ӭRB{!>{6IhQ 0>ٯ-_JO1m*ҿM* DW`4I\EeuC2?]L A0gV߮s-&2;a`e 0iV/#ݍ&HQy;j[PUF1Z-,Xz >{Pܚ"׍=uRHF@o,p6 :̎"Z*@T3rCn3o7'[QN)\Vu$ eì(Ҩ1~;R"@LTvN}Yй@/"׍B'Vlr"7&r=cbm(aE G` ;)/Jږ @%wF ,kqoʈBMVd,+O6{$܀^M%J8xEc ~+\̷0ka ,9Łz{ 1k@\a/,(<$c,y6NPiI}':`G%$r@tXc!$Y;"N$;"g~V|$yi7'Ѵ8کmYW=+SzbҴ./ ٰwlB?(@8x }<ٽ_6@CseOګ^Z)/޵4EztT.מ.#`JH/7j"ᦀZGY:c1'g0 +Q8.(x4_gmB{HiWY@aW21W#D('_L72p( yeLI4TgK$S]TӾ,)K ɎvgTUo!] WU1#fzva$a&V Ɣ<2 yo5<o;6UyI e@dO>@xqtҩ/o上@h__?no']A "uTeC?~]_IIJ^4  RM N^J4*iZ,NF@&:]s5Q]cYnU [xB!E_/ND^ [ƕw@J@NJ>/r_@뇙/fGa 8 Z؞vH;%InBkIT-*pB&/ۀW\SLM6La K~ƱbGxyg-"~+7}Δ^.3tp^ۋT~,~WơRH" HE>_, d-&L`.f$7YTJGӀ&*ݐus52܄ ~n}GMh"MS/dm$qz`ѸU{IbucsZ/d!cȍBDaCQDAW, Mvۇ`02խm ;f==d=1ZiWLB)5CAgȍwεǍ .cIY/k&Kh >v$y:2)9"׉Ǩ b&ŅSVY,٦ᾬiPxTUpB8r1aKQ2*˹1BQEń-EXztl.Gֵ'u5Zt.H4>pb4PXI_ڡ yRSowzri8Ѵ-Pv WQULjDMȤ&g‘n_ئyA`bo λ+*tg6q_\h4긞[[ LpZnDوr8w;9M6MzQm+w &۪A<ؒK<yqj CtaSWM@-b!Hc]gwS&)EwK>r )ERk|'d$҄Cڮ =Lhh#C*e|8(ҡl%V8NC%nYJj% y J]7(i[IrA ^Sw\Ao.C%{g?g3 զp)Us!!;.H(ɽv l89SX,ˋ#l~$f  h䯤TJ.!훕1{dAM1/]VN*A {`Ka!XeH|ި\0S7HSDqgqX3Y? @ȝ N$qf#ew[kVnO]MN/uFu0b]hv҆ Use4|/N4qqR?m,6 K.)[>rWHmg{8!-¹1iED骚Є|@0ql#L?6 "ُ=eӊiKiԧKo ij{)":xӜUg/*ߥn=]ZƖk*'yJJC>-Fʔ~zلrE*bYd܄dt)rh>6T=ͥx%uk~r!`nu&FeC4TSQe[D8aB@=sAeYZ!dt?C$i3E~>yW@a;+ +pڇv%n+^A=_">@/ZZ%yӋzߢ 70mɆ%ǀp9͗`FCD1W+4-᳛Ḥ̑ct7( a#k/[nr{$aJܪ;=m%\މ^iO Fdzܴ%4,|K-'"#}?gBWԯ]nlʇLP\5|(E jZ|pyG$϶4b|K&LJ eٷ+{)ӵGQ\ѸAsNQ]_Z &OiԾ$4}g.8'\iNVg2NK*m#ouL>'2=rEsÉʟҜq-Mz$;(%{:Ұˬ[ۊp*$N!"ΊeeS;c*"]2Zms|^BUP綍#U@拓M :;|cwYfuVVYH#5zE,>;a/ F#J*VR>$\DwM#' :܈['r[RĤC" ]\|pnB pBؙ !!ؗ@>WGú7 !'>8ز7u7+3&L/! 9uo}}xtEmǻ:BPqP>]݄? qF>}[[>WP"74hg{!Z>S;@91|vE衄3*"UW-3 p(9/4L&uM~pg!Nӵ3Ln+!od7!.́+!>5%AngE\2Z=EZv㡺zF,<B~Tu$ZHT"[ hHǎ{0q2] b#Ϙ0A~%D'0-t:PVG/U8T:j9YDy= pɻo͍ }!DdCaF&?2z3%Քh_ GP|BEtHJ rOguIam.|f7"$*"+B %Z4YH!YBe&DFd?]fqu`q5P6]ros1vQH!wmlhܳq`!A7H[i)Ѯ5uԹ=5 aM&eiu6*[[A|!Iqq{8_"K.J8<~'K"TDm Gtp Bzd%!Pw f&PSEW4WxL^eAeSYF1K!lizj%Dd_ЈT"@NbC>BqAܠbzQ3!nxN^y7>1MW[qC*knPdS}&L!:)1D.9#EbjN{|)Tn?,ŰM;1ګ L4wm͖lriGb:XXL&bz ୈ%+ M4m%4\l$ G~pYX|F]+s{pC1:m57մ]k!}2QCMDt`F&z[[xVKhIzEܫeȥ?֞BC!ݝyeYY_/!2,RY6c}~t}Q61A n 00[o3H151*(AP#9s ddN%w|F9KƁ'qϐ{'^1-G{8(!>w}}j5]\^_KӍՕNsyInsit:[vӽC7piZ΍-[=[lvIk$Gۃ#ݓ+_(8Gg8 Y'\`sɯ~=۸gs YMpBAHA`Ǎ t}}\NդjZN 7`ҹpuC@P=HHqW:=e)4B2 n-iI4Z8{QDtYkNF4BPY\K.)e"v R A0n]$1Y{NM4tѝTFtnPANr+"_rx`=\~\Ә-4b\h| P#Їڎ g147kZ$Zmb>=_e{ڛ|fP`sdiG4nBli9>fy8akUTS BFSS@ / 2de>"UdS&sLl(#eIv)NehvȮ=}Иr2츱kHueUf}Ę(~ުu|T =9Eƒ]gH:x?G>nLrDEC.mUg oA@:5.#kl+iq<+"1M (pδ&>&N⋙-,C}ɘ*sGEg26sZVXuFhƛy<=dzaNFh6͎CF=越A,1TXnR8"1;_eS ȃs?U\r3Yh;pϝ*}}T(e sXS_C  ~"CoVk Uʎ/$k[D qB'u@U| y*3&H%bЕ<%&>vتJkHP 6nVʃ!=[*#5@HY=T'uq6E㍃=Mna a_+uPiYpJ tR_!$k]m ]"f -h" %&Ywp1}(@bm؃G V|}'dH( ZL]`D M* ,Q$@-KyF{C־`uȸ"-d/hd~cE]`uD3Ez*pPhͽmX(7uGf!Bl;8M`o!/x4,(BdӦH "7aQ52 ^`[q~&m6yKU @ڟeƎV֭A~`QB$^3o  цS A($Pȵ^!H;YPU/HABBrn+* +$AJ%0T_D 6P(^x&YHvZ~RI5a0kɱlܖ x/._ w"Y6yvϬn]2@a!eߡ"ZπD/QH]͞Pods9`E@PIP.XUJ>^1iZQ O^h:CDG?< ߖ[W=u!BmG:R.Oo)8[ӝ8~:_$k,"OAoS}}Ng^gDbb`:ZE^jCrA@qȶPs8zr߳ Td6@Hv  Hz6@;ƙmFE6з J$E=PrQ *Oo46L?lB\bs9v;y:`M\4I-DZtYqN=, uM^KJrxbEBNùG:}I [!]8] !ZzN[?WO-( [0̺LԊDqugv+{ӷ@6, 2t=zlfvF˭έ+ Y@WYe2 $61Z[N>5~-OUzUJP ,Ӳ14ӵ r0*LҜVE XnzͰX.` p]ʗZPʙ\'[m|GzlN #ڠDΈX6JԅJ`:YS Lq<hiiS_7RO@Sۇ8 H֪A(ӗl:ǪAD;1avPh.T{0KwЪ;UG-4+M.Zǂs*OqryM\7P*t5d'4Sվz|؉1afʲY[++U8Ϸ*F\mx> &u8wgP,NvYpjsvAByEI.Qϳ`y&?!4ڨ$%|&zYӊ(jѼ6T'jN8!kS,eK8npR @R Q!OZEGT@+N0hGs:=H~(܄͏`@3mW& +.7s$:bL(C}$.3b*'DG;ihлU'DـGYTtvPJ&ƗXx1 9چnD\c0aΪ~"es@r5Sw=eAv}eڜx]Ԗ>Y(xX@0Ml"_HX`(A "Gv-"/R/謂X*> jcwaxdia" 3YU2%* ]8 =% {JJEIYq8j.+W(7 8S~OЅa"uc3Pܯ^O x05Yrc~H . TAE#חYPEw%yEi=uHP*C ,PVTvYijd-ĉ,!^m< \hb1Å8%]W!i[ls0^iC\m}*եaâ3iˆ'ʫ>IYs AJiuHhf!\7 QXp5-W(\}۪ 968RiImTr+ﲚ,^*u'>wkM$  8QqjN\Ħ)44B"{c~O 7h!9]N~'T ' ֶ4}8 R x&`J3=nDO'mӹ&(FHnA@;6\$%!7 ^D wN.KH;wM?z]& (s—;[.jD$f?Rt6L8j 6k,RǤ˓\yC7s+8pKY~&xӒEjH pT<!/-G t8o[Hq8fQ5x+/ Q92(H9+W@o$)Eo h @Wdm6L,yZҹ=YwHë! l eҦsJ@5H|q{U[d64/V"QUR֦V[.]V$TB`/8c(k*NB@dF+6 9qoU1Rg[XpVxs044ٰJDDߪ^z6[i6SvC'MA=(^Ab5@*ql_D `PsMtN.n T_0ZU^xo g;(ԌBR`쵳%r\s F!GH:.`T!#6D ͂pǰ#ocІ0G*nsa"f f@3+v9"+m9Bpk5* gQ$kYMȍZd5V@~yB>t />w<37YgiN)3yUi}Fd$,ƸݡTrm;.Dq~dp<9iNL.{%YuC,b$ C0.Қ#%ԫ5댟"AgГr+SCڸ6@'7(Q 46WSt@߱j'*d4TT!}YNUf:4W1uZXh} x!4Un\AC]f܅n2tՑU贍~mc.m9SrAee[ӷd+#}nt4hܤr1A2p[d/q|M \=gL*7x]*$i^"N)% \9<>lU=PBeF,]%y1 _vQy%JwՅO"2N}&'4 ,"]q,'l U}}5Gj/ @0Ƭ'41+js U$J&i*P܏NL/Bb!qfvWa܏/@b{YHn/ܩe:eUL8bb5Ù68X>a AGgh.' zB'$:xR0# |t; yK2}P,@cIomJQ&F'}Leۆxm۸tNH_P< bZF4EQ@'gsQD eѠ7岶yj `BR/s-"/W;v$^+ja7_8 aHn 0\ҩᓚdoCQ ѴVP!j$;y:{U`V V@-gvM:"цBb Dff slqD*ő^| Ĕ?3oʻ.6Pئf[Z1Z-!su8|-{V4|&YsO%v}θG!VY$^α4"q3YЯPCvzkAV1Qqw+LMLnG_{}x'5_[GJvcW*9`aR7SY[`}9$ݛpf8sJ,CǑV1YO4`i6]dOwQI)́tEfJD4aD[~*#@4z ,NA4Y͜!Y{ Nk YznN6 \q+^峇gy n (\0~?X<xA&}ufvt h`:3W2㧏+Mlt"G6 DET5qKZPu@ZDāg7-RPm lؙ5C|)Vm}| mF8:!l]6TR=a\Г]V~?}ӈ&Ĵ,iԉy]jR*0PmRj97q$k"%? 6тmCnNkvk-4 %O{zgg8 S@tFx`|%k"`4c\ 'U!<   t"kBxBN%G(K,^' +pj⤮N|zZsYP,x'a] @BHM *6LHLQԽY)u|Xz!hl7O5FdE/^FxܔJSńtt~fz'\SD! 4X"GE)B_ř\X a\"fMT=uS&(g E974IIܐ͞0pWp %ёU~~AX銎ymndzgINVZnwAOzVj'!z1RoAxfӥhj1-dOؼjdKrhf<%Jo,٠-ws7dEQIK6/yʎ}/͆4PXe k0;ef)2)N@'3wۥF+Z'^f'G~ eR6;~4yeJAg,X2pa^fYCl|#ff M`6H[+dC4M~F{އ FSŹsdncP9' >/V@6_x(1Nqd WK~j^/A@{9 3M _.u?ʳϫu}_4ҪǍqHk\֠[9K#Ne#]j֌תe`QW2W*/3a '}IwnΝ}?@$! Jt;BРMXIG5_v>øQ\ 2kޑA1v! JnOZ̜&doY}S:L6 i J3b\Fa棕5@WMе41S;|Lt6(ljt4d^l ) .p!=OTjtp)Bb#sJaE/4`yjNhx׊FCo8UYZD4W]Z4YȾd[a8rݓY(~d舖J6 Ҍ*Q$wLR^ Čͻ_P ﶑U$ޯ1DVݫ^IR8wBӔ8CVrƃ`ƥNE/I/AvVS$ h;m(]1Իϻ!~*"VHcBWnaM^ȳĜs$8`R`SBC!͝i$Gu{W;=1a{̬+B[=fv=Af`lds l.c Ba|Î>3̭)Czgx^+_^nXh{ًZ ]Kd|^6nC=b d( Oz D/@zURZNۋ3V7&4vݍun=q]nvnz6fvظyoٝ}7ԹQ襨` `+9yӣֵ&}+r,XJ6VwWԒ =B@NqDϔ)8Ew x36EJ!H~ ԟ]T,\E H$ψz(SIٹ`9%AH_Ƣ[-A؁%: DTFی(&DcaƇGAFזַwڋZll\nltg]y{luF7=HPӐq*E;)ѩ+&.# h5v )Љ) P;c}3'Z 7j4 eDiE !kpR_<QJ{{ d{熣\s!n D0sr w\9tD%7M0.K-:"QB=TD.&AE-4,\h-?G%7VD8Zh%JN@l}6T1dzbx-˾}<у؆/ӓDKV DWa0ɃEz(z/O<'l 6'D57堮ND6P ( &G+)Sã矈<xbbGzTpahR 0$| Q8w]yGQ,.:VqDj1BY_jB?8p8EYa)N2$d+\',oD" -(MCY5y Ӕ'򸌜b/R]@sͫ&a"1}:jǾh.'JTct<\2 C)ӈ4> {{Ԯ&,7QuD58e; ġZop.8ǵvB"#c,;_jT3"OA!U(;~@^RG41f`.&wJLdeڃ@19cZMvvh9LdT<. e<BQ>1趓Ok>ibw#OiQuP-@5]֎\^[wˍP |y_+D0W@4mF6#L㇢QTT⼞Ȟk{i }Յէ4+mpPHkpi\r>Jd)l @ge6&>'.§6@'A?mv:a/&ɶxLrpoZNB#iF`"yEO% )c&11xf.AeׁX_>!A;t=LAWٯ GpWY#g!SF* |Y(ȇ '{Ϋ,]Rͱg9Y)qЩ(AYJv?Kd;TF+D7wFKO"MyBjLvϪ#QCڪRs**bh8HmOd6._[(A@޲s05'F@9c#Zas ПgtB#&"qStVpf0dj2^B=Ⱦj DZEF4X-8sUL>'{+/7s+PpFWqvQAt)+=k&HJ$Ȼ?5h}"e10v:ғQ=$/rTroSF^VG LMOW#m^ |FX2M}L+79fP4GS#V:Qp6=߂*@t|(DԞD3*]~Ñ Dv鹪|e3%ͮÃ@~V%!VHҴτڮ94 "{ Pfrku"]#3}CBd_`@j*q9*JgT5/<)o0AR]݁VF$^rqh*Z\\F /QRSU;Wb!n`uG+~nhl9IJXEZmJզT+ejw` NkλT1B3+t2?*#8w!h&wXT V w5q$r}RUwy{FΝwHd_6 Ee8j!xΪ1Z.-e\JݳD]p=1mx*+a(iU<>Dj`Ixe7('pZ^cޖ(8\r '3/'F+`` Vx)ɫl˂$:֨gNRVHH蜰ʕ$ fr4)(5Q+gkPaU()V3m}/mx@{B؟fN}/#Wې49\P}4)AB92[nW4iC)sl܂* M0lmɥ[,P;u0ߥI (`GkʢǍ600d%h5"{8&"qtAB*Lcƞt#bINE9T㐊 4¡ڌ/x4gs =piAW75J%HΩV>xvZmʓI'MF7ԴV $P@>VU٣9]#W{8hiqN>Nh`qg5Bt>zVr-6 R_P' jϞf7Z@)A8S!. G>Ed ;5qgC|R'J䛞k`Ք2͡x h׭c(t`9PS XsQC.y\JyUТPtVgr>3S Cq'FyW CMZWp爖vuqD/AXMxTAN\|8F"I~Ngi |O%f_"*__,_I% hud#i(L3BuGF5erV*'Ff(R%/D +/Mj|aP}C%?3 I0mmH{:~*CM6'T".`>a]Uy\YExj&5AD>ʳ v] c ;?#w`ܫX* Hx8,]p2_^{IAj'+oxqCDHTչ݇4*tQD5tv8Z4)Ȫ.2X*fL\h紸` /gLo$.a8tL9eujUi4]^܆bɁݖ9HJTfXx(#`nOP9=TCG>"{QsCՑt&G~Ml/HU뀾Ldo jkLZ=|\l@ꂨ՝WCMOyi^=vɗӪ eYe{w8uhx(H<&~ Gqѷ4P Gw GJRlY'%bîNA_#m"$ \dMgx4g{,^Ť8t[u8vԊ!F'+/ {RKu Iig<\BI6^ 'D5ʈfqf5!"{qq bUBu:szZ> 98=-)xکsWS,gHB'b|#3u:kfLxM ⭑K 6B@f@~$6~/VV #1$@HLJl%'hcbO(L\ !0/YD!y -]D0IwA\]5ґ:s>Q#DvTzN7c#W2 7zGؓ>Iy}s[!Ux9muWoL4ImV5 FY*U?Lg9 yYE8<9OZ+Tw٭<1[!WÈ~VU8ژ5s8A/r:ъxKذ5G67 {J-! #_K+B$]d@C/D|ʔq hWT\ jD{Xi<nci*p%0o3DP~Xۮk(0^QyS$(.G=T;sgFX a ^<4ҶC)ג)i6^.+%h4f˟i<%[iYSZ1^7FY WRB`1졊pHG&"{Q p")1s58i[lp !f,p :b$wӻjmOQ!VTX(lhj )SDv /1c_*+=Gd*sUG+wzZZ,.8Sv5$JT(PmP@QsTR/(X+hή3l# 3y;)F:sVFEe"}FhZۚYUR^uZX_fB֥uݛkFpuP op  ^` 4b0CD @$Es΃?gUo 8!+]>y-uF oBC^>ߍ:áo}|{k mѝ_C^O gwmP̍l`FVVAԼ{D[HGoLgDC<m&טb K2yfJִ3Aʏh zazAL0:񧅭HUG%3,tHðі9ʨ xOrd+0Bsǰql]z)0 6Ɋà'tEռKsu"Jr0-+HߏE,֜/!H~Nš@${ D/(Tf{ GS[llSHC:CϱҎ0%u:]~2Ax<ph}gc81[Wqh0J^y XjA::z07$NkN[ GfjNL^5%q X$Qu'٫z #0-&-5_~{H_֩Md4~S8fv&L{ d@t`<5H=]%߅sQhmn{oP Nie^.SM|#X#ٙ PȋM>dIլt8D ͚oC`.8lη2H9v8K[ za"KACg'k&sE= ;ӨN\BxmTLsM e9>k\-l?Q<9 j#=0fyK+P`s`:<oSϺ)6JY,Ul'PU3+uCY^a"i"0s3SƝ`Nw:eM(LD.6V6ԖZP_)[X[L9;}6wkg(9 &ou!4{qVfWHhv gY'1DfVہ٬Miz9'8jZ 2F?scJXv;7dT̈́lPXP's$;:?` 3#>~8=l|!IOԂJB`Wnn 󕞇L|^cXYrud,{u8?jŜtk8Лc赫Pla8{F%ZA7rƔ(kA jh/\ MUǕ`6$"6$XT̞|Rw/K}u.$g8 #0ԶiD6cH患N8@/s9T "$w N;ŮM/(V!Zofpϳ*#l G>q|MDo0A[_Xxp:YR:ZnNz0xȣ]U:b-ymjUq.Z({"yjH+l-Ӑpb1,øi}ElI5-ܓ߮!z dC"6 %A/^Jё5_UN^⹮^n M)k?I?uRVDn=\}NCFY/AU<^i}l}DkR0ߓaGA8 iME9d?4k/(ƭpy&]oܢrSDv,+ԒԲL-  χ^t6ӹWyGRAkDfrpC l97%&Pڵ^ `$쉠~dn1NnBQd%쨇RicO aOMl/޷8䐴n'Nn6gO~ GlVTnӌ;Q'O%|/]P"EXX僶{jhg?F I^BC!͝y%Gy 2Ad6~X&>x} Gڻ׆7pP 0 !ӐpkaCb%" )TuWTMkb5.Kb#F㊧^ɵW\{M5o?%ǻםǘtFHޖd`pd5ʴTφ&8nn2(شa \r^o䇼9-r~EWGS<p9/<4 &<(Fuq%8Nqpܧ~Z@ߏqN|O>tZwΑ֕q\G>qK6:v\js^9698>rLp"Q7zt} <Zz<ȳXOj@P}A\@z1>{.!HQ<K w$>+m@O8f٢|Cg/W\k٧5H6j e&:|9mg4B 1|ym_gb @` l }}I(-t~_+rvAF7Dhb;Aa>@})AƁ<>;-/f.5?2N:fg}wiesas@NP R:IV+|ۍ  r3Yœ.!TNukg֞HtN ~r.+'kDy e:|4"ZyUE4g&D@0HRL!J=:`qIGM`ݣ;EZmZ'Ǭ>·kgi[ "׹ ⳻LxHECk~7xcBV[݈ mi/Lp"AOE˖EACӭ Ow +JO52/k`4RPBK@g5"ryY@"ل"x&>];3Q /]rN:KYݴ6S @쵱z}y(E,.';B6eXȪz%YLU}EXNqIr6C!G' eGuz"Κ=>o/}A;͈8` ڴ,SE1ycH6|5]"DlXѸ~ ̓\hzxt8a4 p@ _&|vu0B|Tv|2Ǯ2L5+:q4\.!|3r,*ٵ'Y(Di|v k@$B@2qp0 |$_f:L8kC$0܈Ͼ:  Aϛ)rE!\ 'A˻A%QPCw lpҾM_e:aDF/SO¹Ca>>A !j2 K:9ʻCU fKõ ;ވY+pv+qG$B Lf&!.؇RDiSƢ &c8yZ,W3s@-i]t$!-nj (OQċ*q"3eК-YP; j _WLg1\Hާ}36vrJK%(„iЯK$׾T8 A_t u|61 0QۤT{ Vȧ(є+Ky8}`>0H,r+B[( j\h|ӈ*:? & !UVSDEKlrۡ^ͭPANh2.:%8qyΉ+$uQ>o Dt8K A[1T"z>W;"g\-1eZ4-P0zрUQuys*y>KmH kݼ2&.Rz%{&UyeMH]O }JWXR~ Qbd,BI*Q"ʹBD[@3¢%$@S/F9a-{Z|^ :ƥӖ=}C "zZDE uqNm^j*OI?gي|<};鋘3/^ZݟQN9~Z2J߀Yި 쐹q:!P芒J(i JI{ MEjE۶Ae4Oͨ`(h}&tm.xM{R)>7Nkc-4@lb٬)<\n8,Ht ^>Tٟ7m%eT|Cr-Wi\2ΛZi8i7 Sw[tkTyBEi6"ݦ pFm8i)F"|>wŻFVBRRYG%7^H>Ȅ=p4jAJSu]9Rp)lT(~{pa}'rLpB~!q.'ID180@.A-f) ٛuq0B!/YBwiFthmˁIp6dwq(Mߕg{~6A֬q$/=><sP_ ld ʏO%}hNs-KDYc&k/;gL9_SDl <~¥;ӕr2GN8E*M1Nq&glT0Pշut(#;Ɓ[%TZG}h  ZNNR8BH֘JN'_AggKrN)BpAҐڦU> V"RIdb;7U;BVm0m[;"""OnК m?8tƮȼLdG%ҕjCNϭE<6ODϛ؝>?c& .*64&|y_x&,UfJC؅2)> kQ<9Q|Jpql-=gMĩ^$ eA M1B F3dݕoQ!E~p ᖻEӹM:WPw)LHE-Y-$ ig,-[Dt%r [t[Zmjg CY@yn"PlCa~圄TܦQ e:ԣrze&-J*|7K2*"U_0^lK8}GQB˝*SF{$ $ N+,ڽB%tX!v{?L%VFOV.}I$V !ESs|R~%J_Im&ۑKTȧ݃|GX  I Q{m+TLdeÄ (gZQlxnNwh,$HHb=[nKJȍB") ?܋FV'S~${(_oCBAxFQEe?iu-!yǦ mw&+qRwtmCg7a i >Khb [*EkD`{TM6hbKH: -I!x(a qdLp43)^%54Y_I'g:)\Ȩ[sAq/FA`s9(ȿM X0 K6qBF3P>Cȗ~$>QS`(EjTŨ,R~ 8AY*FS$EyQjsCdDn\<mU@У͚eY;!f\9a7`Rv}2Ib+c geMS$|C݌{̙~ l'|.j|`!fce%R @%`D@!3@iF 6%(_g'MP|~-(re*ʁt;=3D9 ?>򢹋 vM`zRG RnAsf<8Y"DuiR}zTΎ*^Ͼ)7\k\Ku/u＀ĺw}tfiR!N7utZ9m݁;t ’+ja }+S.ȡ]u]Rk$\9JE _DY&"cB4}N )&?-E]Q=*]gwn>Ed HU4y0*hz8fbEm LcP5{v${8rQ%cL^>ڂ!bXd\1Œ sW g -Zz\.8$t(7RJP! V!w\E"&jh(fГ̏\\%C xc)ڦ|N5/ cdoc^/3Qa*w׌-sp)6Z`%*0`@ j)?8xg{Fg!g7qS}d.]T/?I@Nv[*?|3 8R7 #4,׾QG'ڕ//῰AY1Wg N (\nI$ Jmц|\j/Uu}faxyU-T<[Y:i$&"uzFӵ_hGE*;7}f @sI"*DYҟ$!qDXb3}}D;)݆i7 +;o 6Ľ!nQQ)%'gU֮oS{{rB]qJM"=y1~ ]rI|}8`B|AxJE<7Cy Yy_`I7 y:};O5,KqR^rTQԍo |$֧f% _vY`D#QŁOqTPWL] {3>kMWI SUVw8+<($4xP Ak\Vwv(т-t_p%%!6_q={WZ;Qz~AB7]pgY[s8dI٪'r}il7iExtiF0&BT6 ֿc8|-[Hc 3!3mBtbu 4QDwjl+]ޛ>TI?K$RY@$ȥY;$h77 њK槣.ғ%"~b5}?\ ٖ\&6$E vҁVt+>v ]']oXuK! MqQ'sNk>ΊYQ EO^Jiͦ9uHEDǍ~3Zz [D4n{FU2b!\iLt.+J{EQ7񅐉viU Et tIg8̉Dʪ l c2&z&"R–]SWy[?n1arm%`N4YU7Ƀ*!}mDM׵&E*cYvL;Ч5tQm|H #W8/svgW]{L{ jOID5iȣ8ܷh NjCKti, ssːM_nɆ$dQϚ //A(nMJsQ%9HR)߿S$dcV]zB):h\݁S?.(g[ t,ꗛ]@Q AWs">"{OM/b j ؅WpswD(w"ZW7 KՈ${pFLLC޷CZ_Ԯw=7JΐLbO$6XK* S*-`dF|iYC[ӡπIa%ĕl&+nD-|vht%hmX RJ~>h@ ݡy89{x#+t<2C܆p*| RP4t2TzDFAngyȳFP)X|LWTwZ=rktiS DP9ksk9oY8jT:dT-⤶ /FFBL@{*W\'FqH˖7i] >5c#F m! jWi3HN$Kg=rc "6ѥ h ߬ Q֒Ǐ].&UO7M^V<(g#w6اXD>čEnl 2f hF=g2PQz8 , 6KNQX%Zg 8iZn$)P;.SHG^ݦq^=8 !hrPyt^4|D:#i~"m{8s,k׵9A'ef,NV(IWK:QH-J= oXc\_GHJxٝ܈=Yă$^)U:S4߯HNlE W4t`z=Eh\?_3A mP'a9Gu&8Hx>Z,uƏЈ3wk9/ ?]G;s~:"f>vtQb Я{ 6#Yv&0JR{+l:>G;B/ iעT*Z{@BC!͝{WUO̭QbdnW!;UA^ҡs-:Sδ'e ;0a~[kP ""=ZDic$ A iխé׆2ݬeOћ)Bi7Ҫ+$H>Li8[1SH,k- rg'Y.n[,/o'EP鶩}`>";BiD98דH\,ol\ll;Cϻ55}(Ml":6:A™?vs~S `Q"Ɇ/ 2osLk38W+mPq/&:kDxb$q*IIOd*7+v8偸 }=h=BdE䊈 L?k ?81r8+308R BtۅὭ3 F{C(ZO,T*莆^;jkC1 !"05G1*+i׉Vg#~/bjHNOIh2Vd\t`ϜXia$Ϧ̘$TIp&%M>fi F9,򟫭@!ɶ拣L9=1580ug4Y'ySy }8g6YQ"{ʔ!@pYrli! D1c"oNme2FT< sϪ1") F!\`յGKQ,Y-~kê*GNKd/! xzþD$64'^ cX @ ږ͉ȷA1d8f_#7X%չ9^$ 9V!8j GHQo1#[܆HUDqz{D6D1@q8Q$O qŬ\qF0@H@<4mMl۸Up1™4ɢ(@4GkٽƑ6➂ X!宾-OO+V)cP@s1Ϫس!#ԶG~9ũsr%hc/bH8.q(.N 5 z9}֘(|(`Nne͵zvHX, хESdV))ώ&sC P8 qF|jL`\\`Lqk8v$aAcJIa~O}5!ƕVSv@WnPDvP$a04Ic^kGUڱi,s9Kj[ B6gW dX]?0@$DQ%A웁O(PiDvÀ|^[fͯ'FwWE4PB+酫dzRWzQDM`G7MٍqP_Ey p؃2κ;j辋컘Z]!F): ړ oGŐњxULb*.s6;5c4'q22v\g4gV`nFNL} ($ 4@^cP sAEWXMNT4ךQ QFЪ>C%-8'HOi6w3}hs)ûA9K'4*!졒jɽa  : f* (wҍOλ68(Y'4FI(u5~ {хDN)qಧmX$#Z.W]Ggzztb)ŊΙ0, %bqgWIdyݼoLC?w͝%ފ h%Neb@4?׷~ff'4*8BWXw'{H6ePjNM3#Ux(LT/wZSͯZL\9F[(vM#/bL&yW-% h>G|3-I-5 o&4%6@PܞU@N4wYjCE`Ts5|O&GsQtGvm`RzsQ[L&+ PPԕp~Ddx\0DsK/QS33/' q_YhQQ@ϏUDDYu#}QaOp6 [r,!wH>n<9E30z ]SjLna DLMkhL$Xz ,= ,!*a;"MXBGiyDqtiQQ- ()?MnIQv;juDKd7ZIOHzECFUڌNMU4֠RE[HAql) 羡QP',ن( DtOzn di xz_|]2h ͕3]˯n&S96] ߔ1gm+[VYc>PѰdt3nSE}18>2 %857^XݩI!^Kdg΍4 c-Vf8 Yl7ɻQcH~O`ɵаnt+6fV  aeZ!U\30y0W/yݥ.CdzySzbx4EsJ+c< SFsUB] Xj?kuDzH0eeBbc6b]̢;‚S 'A:Q>X%V =~5Ժ賫ƫC)8+&C1jI{B?ķ~O3~{vԊW93>[CD3.rG ߫ MdPWZbp,D'W(|HۜzV->~߾JYMXx:ڜdz^Ddi<>gZB9jlfy3^XUגwk>w['P@ J[;C58 lpZf1, . YЈ=&Ag R :"mp/F be֬qu?:Zi4Jc8 :j8#D bchNϱ鋍"DOOkrCN(Ի5A 2 lݚo/Z,u *3sQt8Ldc`c@:p SjÈ'_9s+cFA0N*޿ѩ'[@ш z&-NTD1?cCT1fV-?@ΊcM:V_nֹl:Emf@WE?+`J9,ZZ=%q@^Xv\aJ: ԧl"@;B\ЭDU㾥PN?{ uUt]mR]Mdk|bvH 2Dsܟ^hJ4$L-?PcD>O#ZkN } }I^D6XC/\.(1Dkd5F rTj|8n^.ɭNGcP\$)Wu@"q) ;bp^ozg{l{Vvxb5rP`8'qEH-cwDH#SWLoF<\S5͛5kx3ùIލ^|J8qOmKf8Y00N2g{lj-{Xlr=gvurjsOEqe!g!#u0 G3DzKVQSaG8]_ܬiCDݸf!/mABbVFAX%HDGrC=6 Il`˪͇-]P,> 8qB BoIKY^Dy(+dAѣ%hcd_ Y(΀ư,Q*NI"NҥEw(O Ŭ?IRiu_lbA{&n=%ta{.mKqw"3&9oU:;j-vgeXl,8ͳ"{nPJLK,RU.TB2"Ga:FS1!ukoqppJ qDrwk|ŏQ~Wk>A o>rGwupNzBJup畋sԘO!kNAxq#@g>mkaE:?ǔћu9) 1ʮ""zmXu) 9G%V+)`x)g܇ 13f@ es^B ؊p/^5wܫ:LVG_7"+1]E"-JgAe.wj2Ux)QvO3X CȢیVGRP1Α8nMBx{q`>爙c΂lp'sAbW"=rI~+,$X>.'uglJh 271Ql#WƻOOΒk|#ͧ;tokHl+ 6aDŝtO J4s1~ 8rfZE}4aa<c(ę9>]z [ 67SˍԽ-֒4ߡ Y:eLqXXܒ R{1 UWln4 ~ylyMf:Ew^Gd1 8P) z:NDY!ʃ5cz#}c`(1ݶ-˾AlqG{`仟:eYP;?IM"AFL2^o1SE0o&'ժI b|K[Кl4_52jBhJ ] *QotPWf TE(PycmUl_Jе6DaJ1wwL'5/'IN7t1&<دq{5b@L;?P<y/~1:O1Tnj\WZ0! Bg1./uR20=gGq%wށ>fLsb-jTzub-VD>JzB8Fj{>(#6ZM4jK=e{jZ bNs+;X,"_$dBMv{D]A;o49|*}겒@j͹PaL]#zJ=Md1|GBުo|l *0^#Ji Jiq'z?& @z֚-gkC>>h0?=5:ZvdqDRB ?Y(G }Hܙ(NkYSˋ6>(7F@: }^eQN#8ɾD(A~CKVi96%h0W:Dv'PI^nV4uF9v 85)dymΞԅ LEe?h +b-ʓ cR/{^nܝ2( WmxM/`Ȧ_= 0!:&&nXJxQmP`4Ni)5Zjly:n.q=\p~\a9j3Ȓkɗ~d+8ʜ8RE:<_ ث6? ra,~VL_jxDCV-A/׆2DekrOAhd;?| Pۢs '쟌9XM9_?)vBC*"͝ eWYVM^pZk?}Ι@[pv<*ha[ytkZ (gQ3C!#AcDA"k^ϽZ9iL:4lgպKv ˞|g^?<0^~8IG:Cx;}&akl/n..]^J7rwm#{,vfn}adǗ}nv/n/ڼ:˺ ~1;t3h=IBLȿȧ, 0NNҤnv]tKK0Eg_^݇9/kw3 g. DqhX6]jCG` FO3"#8ח8jp>e/ICNA0)c'ʂ:3E, EjaڎRE'8 $%}VDeACo";DKa~@+(pxwd ͿcV4`q\,΂&?o=?y.w~Գ(O@g8$jC7' fyCh˩C=e0 PjD[9Vd-J>mEPޢƮBq؄%18* C0Ų9!7MEe72$#XXE3g%9r6 QDDK0H{Tgb}L.7:Hu8² ^E's] ;q7`'Lq|Cg4syJ܈e`sL?Zg#-)HƗ(PZ7cM@=th,:t+CnJ*gO/P^ZHV⻫mlJJB埡ӜY`L,(],†)\?L+\0A+ʠSX6D ]ԙ@=^E"wY@H|꧎JgS,*S59@]hYg8]T@Ϝòn Nxؗ5'Rj.%#iDѭRNԥGn9y,d@@U1Weo7&TU÷VUA}#zfJxUQq2qcKHw?U.䣎tTO]7agT?BP)~QǶ0S5@Yy;v뼂֝S/=g੮C3:Zluzv"xxSpuk0T( *C.]g=LQC16ăXdԳiq஭b0]b @~$VS$}a,{ w4!@ S²h0g8LA}k9t'=΂\j9ew`MPQXqp|#ue#@!W:>HB[x'oAL|*m"^7=Rk+,Vu 3dUs$q.Rud>cC~0o?V,1M3T0[싦8IOdMnDVuD[%&HAuyf8UyծsK=&O}h{wdޅAEjE{,˔j W⼯ll>vױ=q ;Eb(kuQui^Khh<6o{YtG=`{JqtLby6L(Q?R&fZj΄,*OV o$UHGxgE5"M4RwF<5=e7RWz gIԸIcs&~ a$H`rp `J} i8O4eo6nЀ\`_͜jqW(TtFMt1Va}5d]&C GupvsbTbfA1 -A}:1lhB(9c#בj"/%04]i$yC?TmRQE=XatDDzVD *ݐh)&.Z!=jUNH1n? Xk68XEќi(a4eaAxR^S YqC{)Փ5*b%z WԽ򖙞wrJ6<@w\ΜSY1(+nК+ ?Xf[Z/2L~Ti׫KͅX&c?Wh( Mۣ=hUɓ> )qVrU8%)oŞ>0].ПaaOP$F YV-;|"sX1r4FM6+&M3} N*1rjy^e P_Yw#lPB:%@?t "~pbٜ⤎pQX|ZJܑ1U u:?T4 30OIM񬸾D@I]" 0sDW*CSKdZ("8E m:DXA XS7u,p&>Pbh8B/IJMݺ~,G ;ŮkczWzRWHEOw)IXe9A4@(iÙvJBP;vBNE4EX_)Z>t;˨.E&Ԋ[큩$ݹ4(|SCvt)PQ)oy 2L% U5G-`NMV] h0ӹSK,{Gzoy(}ɸ ůIC;dFYqǖܟ-!438kf([ha0nA30D]:SQPH^;5}hK"L>i{ sv+ͪF|m=eLv\Wڭr]"DlM: I RCkSu8>2>ѭR^iHCgݝdX!5A0tĝJ92;!*zD%#mF'WI0 }mYGlbEڲ rOI,+Xtr: uH,޶"C׼1 k4 C??GB&i5CtF9pbRMRQ)cR/@]A'95YMV# "mJZj&)+Ԅ4P yT[Xc9j 4 _a&\̅^,{q(Y{M*M06k$НcA'ʾ j ^4=h+ J!JAŐNCdV#q%< 5QHJkh^ewώ+ /O#<3J's$Q}PfIJmHv&;89}Oi`1u{D ^` t3ƲJ =2ݨݚ: )~* 'WN!Nѳ%qը1KZ,=c;p-CFyۂłOۑeə~`D V, <00>,p O8eGw7BN^ ~;gu>~R9h賢:%q9ѩ+}&qU||xqFE/VUqksf94г::ݥt;Eے:}G~$,X "_1kLg#!c N -xEKB{}-R_nxFbP22roc$΁]&K(}FK2*jZFK.PTY?^ob-Ŝh:5̶8msG2sQ4>*4͸ang8ΓM`>]cq8D9­n3:@ږ~Zi{M_ U PG(iJvʝ/kq(6dFw`nsovt)1NjS%mH(L}IGcdza-u4NBeXqDpשMb֔U ⹫FrDD:2W|WRt:k|\+Ļ6o#zƠgm}Y~[=~l˕#zF@ nQ?2Nջ <7.J*Ń6mq+l|Ոk"1h/\SyMʻggHxe IHHD7ZWXc6q%gte3 [ F* " c fDnI:O`>@Hq0uTvHNi3XrPO~D,vȒVPBOJ iW('ofij3elL5Ge ;KOp}ᒾƳ%}EBhܺe,{3()Iqpj@ DYg$^e 7tP75MsZ}W%>l m#Z+Rq1P^H?=D>b3wD6y%-c :0P N7cǍ <7LuYv3Q;X?!zK+:hB5VDGsZq8rOƗ,!8 $AsQܠY$@zfL߫5jUXXI+iV>"_pEA*O~{Ey?qnXBkJBnn=G% #^[e TyIK).6b4= S`/QOѝΗeܱ4-JhBq.Ҩy5#_o`IG>C0u,p8p+T~$ߡn3{П4V !/b@]Qr5%K?g4I{=o.N}Om,1NHNx:(fˀqMbw ނ)f{eQ9Y[vuµּj+[8uD@0ƲXZ'gfpʷ]S:Za 顎(j|s@:Xv 2G0r6 " VْH²%BS[:PřLo&8q{;}ڸ8HͅoՊZaN_1'4)X6hYbqp\95K3!'@IF V |R[`1N(C5nDE@AB}S_Zu cHw}m9TAGDmDn:?cpj89 !p=sX% " #UA+N\] $?V݄HlթkiWg#tVLiY_"5zBSqZx9\HU54?serX]=~BX61-ו%NQGiU4~B^e3.9}@Цc|˰hS8CknP{߲Z=.D.u4'y[JH<(W?۹ 3H4_֙)x8ȫY8k~eߞV1k}}H9pЂͫl!GS(Yh`b{B(fRA#BhRG4_#צS﫣o蛱HD}<:4tġ]&Ts͔E|t>ej)4p:Q! 1pLMWa Tttр%x=+Mz1 5uIٕPuޖuDZxg'"g駴7F3JYH)Ket#H몃9(kNNc:Ty,Żyf#?u<nPx*k#8SSq1g᷹j4 |p#(-J&9 K"S(2Q2dPnȸ~L^~(M,{TG` 1ɽ+(4ؑ[64rU!MtzvOYVPh[ns[i^4)jE$5)\?|n%(& pkF2ҏaρƹ 0'Y JxUJ1i|%Q85+m|i<Κca!ZaD,##ٌlH|Λm%݈e7N]4``K1BC#͝ dGy{g=ӌUA vl'>۶>X$B/|`lsvm08DQ"%$)"qޫׯj^uj5n:~r8s;7 ]{=^駟~x=9:/a

|0n.[kJt~tn{On7>3Ntnr9{>kOiݳ ;;Ύ \yQryoׂ 0Bcmx틺De,0 Ш@ ۜBCSbz^km@+MԲ#&%!DWO bb>% IL1b@^ϋa 鐄Ts&1g_'J808pn|]`GZÜf}rąf;R!~ D0rx160~>Z_D;tù\%ko2A\O WH?چ ArDrz8DU"Z8 h#;c8aS6?ثqR. HM퍟b ƺ qj. SxJM"R@R4W ̑j;aJx1Tq}txMnl!;N>KuZ=kx(aj#kaANFa2֮Lrn;na41?uʐڵܐax&HQ]b'y9ˌpB{pp.8s2_y<0Y—״/!ޭp2PgWZhlG5踄\Zhݥ"eVʮڎ$9eV(Qv[-^P k:jmwb]G$HHhպ;8Cן3QaC :J4؈:WOoT]nz6{!n<^W)*8)eiOF0bP%Dq 4č {;8;q Vse ak]:D9yxu"']]6 qjs{=^&W5+ݯ7)6x-Җw  CF1uv!<9&1 Iv & k G}id` }J1wMu(2#hWNԵFttj݈)u^Y(bR鼣8݊D m'fA˵/;@.B[u$a'].t|(&\Ŝ$޵W4fE,R[(v}~x 'Ni4~[7 InЇH.L WRW^]?3nRgt>xDB;EYkjG5EYB+@~BD}@n ĝ@6ejkWh4DRȺ4ˈ )3iTڛu-mR2(8py`mQ]HA{L{^. #Es@:.T^nF ßGE`(r+ <^M|7_P)r&*{K1NC}6gN:Ug b=׆&DQb0vZIoUᵗEpD+V\ɨuk4" 8]ԇ(EOjC$2"μU"Z@E$>$!񥳯7AB_<E7Т!a@x\hMjGUQ "@s*TlxjȈn$*zJ8 e̅:f{8 T~A\y&I$smi/XJ\ - oy&Lo0uWU=4 c(LG&@!_>p-$R鄣850Nު4kihD2-'K3v*⵷DPHAG'tpxpV*R1cD?1u!D_J Զx\ !wAp#uﹴ P7).]KOFYFA9C@!Fy6/1Ád6HV"W姘y T^|KץqQzQL~h~ 0Zo\jBlJ{Rߣsb'AX /6.U0lcɩwn|usڋ!2!ܨd88Ac(S`ɅW;㡲GkH9$~XCݖ^v mn1Qc<`/]ę-3Xb;L[pwFqp@qjބnn}hLT >Ψ@aLBxNr (Vj ' rO.g2N؎|i.., aj˹jm ey"%tfE).pL Y>SMe aum$6KuM ^kFH>Ӵ"H@4@ WG`yj@'AJ:L H8f=Yezz֑eShJQ:iG[';MV{ѐaʫ砕ЧPcC4,F֤zHJO(`ĵ>LU:^mٷqұ;sln(|Jx $Hx B^0t\:KH}4g6r8޶pht44[Sro%cFyυpk=Ph<^qt,/kW,H&pr 88CN'qr%'*LJJr1-@LiΪ'!PG*_i44 "7Q 3bdDj]2g}HqO).ueUqG%8G'Y ^.9Ukk+;yBnL[J ; % ˌ1Db൮ /yce*|j`>8ݪn4z#E&8!? ?g*e@Gi'{˪2i)G"2^{Q` bgnmJ@81pJőst˗HE滌jG*oaں7Q/\>zH܍F5sR0He0J:F\ݻ CXC֫poRxqDsJy+LNFZت4eg)m ߖ3.ۧz0KLځLKOY1,9yn=izk %ՠ[bkUK}"vtdԅ]F ,:%UD {A8C2^`{bI=*ce$o&R Rq-e3)0 $S`?r-޴FC=? I!g[ !TV~P IS < I-фܰ ;jKP FyrAZV\ub}|ീ0VNæe,3\ _+~DAEey몕U.R"TE%!^ZiZUڳ@uԘ%TŊ+#UXaX؀nIɳi;HPl7BfM? wUI%`qiن΄x|9)79}x\"mF5h\4 *Pq>ꀞg{DV=b|L G~Gb2"(|#ّ DK Pg}%某Yo^ 4^{ jK6i+@A<+hHWPj>}❍U qbfpը.{Ԅ)KП_D E1.F]0,8m6\W%$(AY:ڣ%I2!h\)3qN1wȅMLF LtKOkcU X'fUfʱDk͍I A@L0cQXtiMx;rfgQ1W|Xe}9ˈKÖ#@'+|K'*xm P0#@mYui-_Kkl˱A}9q~[Ak HhV i6R4[ŶŽ.y6F 9x"#*}w$_j f8-5nҸ-R|II?9>5/gU, FaVˏxm@1ը!L\zfba-:34G`t~ Iҁ@pfOdH!?sʲg$TдDs9^!̞~#4JQ0 (.gp^Q ?v&!#EԪ˔E c_]S{ wԇ\zQo '-N2KN <(n\TKqDDKr,nI!uɗ%C>;lUU%k.HqX'{NrG%4EG#68] .j+b]n"֦:Gڮ:c%XEg_%OUUF!n*dgۥrr:YܚuBqvQvאycڂQBjKJNJi\-Ysw*9=N=)gRjkA·*El4` ZDUoʨqqifzݝ #CbWq iz} CL6(d׆з}ZSϠG:EgNIZD$aLG[ ?k& ./vAR P݄ZO%DF 5c(qMba(yj F:P\I\koqLzyns'cF֞ЌAzOf$;({[h\]zfs‹f;9vhP7QFH FR6^!+"rIԌ:A 'p.6tACU냹^t FEȞFt`x 4zh^B5!^3Mr}j(5-<z /S .G,dEfla:(H>|5^6UX'g.GmCf\S%EjR4*j=EM8 BYlEGhÒVxsUAߟYtQ1l)F3h-6=!sBBa,uBa@-ՇX(ZF K OAX"FrBS+bvMKPi;/*Uɖzj-%ꐃ -yt"zQM1,[ n{)츀`Razv @r{k@{eOhPL )jG)Qi@׆@r@p"un;:WUDdL nӀ$h hvPn3Ɔ|Uw>-DmnS.Qng3EWKd"뱓W5A *׮&?$4X ]$ DQLwۥ)|,dD|yFiY!oabUB)ɪmi@I%`s_hP>*nYCkmUTKDwyH'&f)9ɋh8:fvq8u|~BٸsԌ}Ǝ_՘BI*LF{ȣ`<=7`|u3`84M gM#kp0e44Ycq JjVx-6 6\ux1fz42kRHݞkWDt/(۪u4@g:9]RE͉'xN[&8'2>m,hһ'%>ޣ|K"(Hob!`ZVfVn*J*v( C>hAK){gaŜSufL.s|n֋7( bP `NIrM; %;'Q|dйx=]>cC Aa#:Jmܕl9GZbR Xh'7S܊О1D՜rGA:h 'Ї9DxR#A:M.Re[8Y)SxMc xFP?=<߀E &Q `Igv c:vv䔽&(M3R!7ANh.I3GaExm0l>geMKM DTuBf'G`xKW"j3/9BCF"͝{\Gy׹E]]$Tjv%V33g:{S q8>P %)$֔Z"JjCi+$q'qԔ< AAUΜ3gϼι3nt(ޟooL#urKw4 ]eo}6Ξ+ :(0 ?iᕵnuxYo6V{عƻ^vtwu=ݝ]qoO.}ɞ/&N{qszmd'.GF7ᵽͿ 3D7`فk@A _[j47Y;#k$k`2!X7ΰ_qRR-XG`P'PVێ I)4u+}ROq 3…PShX9]ߗ s ΅gΧa]08>]A(ǍUyLtH\vۇZJkgkc&~ uRMR{%} hr\˟NzZ>8Nke2./Zh+8A,瀄hs?w=ƖaCP\,tw:wN=쎻`dO/݃9wutݘm38_Dz NC5Nl'>pm)fzԄ)"p22- 5]hei.ckDz7؉qVpҠԋ<CE,;űL;\7Fv֒iVl"q !|Qa.,ȃ3+viH: MWWːV7jE}_JXû|(q5u#!vWIDzKLAOnD- DK"&΃ӱ[ KDȏZ&w;}Z8nn&'WU. =it.$`RUAMQJsNZU@ J \SR=! Lh90I9k5-ʮE),~ uN^a/y8(?*[&Kzc}"7v=c^,CF@˖眰Pa ieo4ۧ^l}Q?=BуL Z8_='8ǯDapm.;Ye\³T/TQ -geŭnǺ(u%G E aUɄLY$Zʞyq޺4Li5iեN\H.Ʋyܔ1K NWfml'UI*_DzIiX09*E+ttV)lzjQ=9((ppP]V!RI)wx_+찭mY"ͽ8s8 1-\(۰SeTB@ @9jNӆ۞' =Z*~3y'[[ =f R8y-g*p'=3&G Έ]Qz{~!uc{.n330teGVXp?|a=+v?W|<5oޜ0*aoWoJNXn7[̈́g$B7ϑHǧl,sFP:)Jk,;m`LaٵTï!1tfMH(z* 1[#Sujr-7BwWeQ!Y&uԲJ22Νp_Un&f77fXAӪK׉}u *C,{Q;,ϚpEl)bƒNC@9 8œ*}ދM\aoCG==+ _I5:T'EmFWr%"ǻ# HVл~vrIUBJU6E.|nWU{0&;uN7aj9 N`9N6U:]Ǵ{EpnIz'iUݓheݵ@wp~BX B>U\/euB# ks U]!j`UDfMqCaEe˨9pδ@1 7#jK(ǒ:Vf]3-"HMu | R78]`,  gZZcQ)P |ӓ>S:q@5aQEb~ ~X9I5SPDz@&}T=M+@ӏu-_xިDx\xh{rBɎ۞KO\ADT8K;D3MCU4K(Q?]DnbYW5# )? @Yң\bnʀL@,MKlGkKB5k.@BJ:ܾ֘P᪲:(-|oVwP*U$|mxLi+ʬtԣ!G-dR kN\eePe3)QzcOPMn;bٗ"gr1zsL!SggX.K.Q#M'-;rTGp"*q[*쵀S^>Y m Y2sGYi5- )j\n:3;փfUP~!JߝfX>:Qߍ]*jTXyT:_s5cXۄ&xyquqټz y-WA.DCr=);Xv6VcgղKEU+{ DDpL6栟.U0]6y@Sp :"_B@:+EXv uwvz%z+,^pxZ`4Y^GtZqRBՒ $W׵Kb)ԋyLOkq9# MSЇA6jC*²7j B 6bWoHs !co2s=SѬ,GN\U8췴qI@7TfTn7O~ Å UaٟkWQJu}!8Wd'vO_Oᬘcn]UizdU٤U*N.(9`)J :(lG}􀅜$Hz)W#)|dV9R?F=Zi)ݯN5x#(KYv"ˮ6шZPipr̺f98,C,MJ0tiACK(Lov`4ӒeD(P  Uai]ۖ3S Ebgzn@sj 铛^N*TJ/Dz{g`꿹 A:y Yi-E1 ܯ.IJv5FIT"ueX6n b7jÛ[FRuXvv2CBp;G*ݦ) P#Q;#CZsph󣀳bBba'g.o $_8*06'?M9H4-k4YoڈH_ h$ *Ob=څrs.OuĪեa]T*"`ڗ*D-f3D  b.vMhXdx^p SgNrYTV ڰ8E$L5 p BpRQ#J'ȡޚu` T ^N|W4JCvR鞬7 #.# Ym1TBqAR5z#) AJZOTd ݄e I@ J}c3N[BoPzi' G*h4Co8ZpދeƉ$DނqUy&썺8oDv}s7H%oѵWRр>8 ɛPAXvvID%NLlcB09rJA0ays IJAev%lp8qMB(A_ʭ{nm?08#[[<#? ]( U ǨouɬO6,[v1E}(#MO"5fS$zdebFPpiܕzlYɵxBrFFPW> .}R>PiXń NBN~!Uf#<"ZM%8m8 4@;g*_} dh8ȷ*22LG"&O T&6[`g,Ά0nƆ[bb(L.8@P?KP:PR"ێe{|nJoWf8S#l?6ZqUF5X_O*<Su<,#V79Tg{vԏ@%G 쇌`6Gu;[^<V>ej?\L\F1j0o}ˎkDR Bh91v+yhIV=+Y qA!ӛm-K8;3%8`k*,2v3 fWXJYAE5,ƙ0π͎E[򄭊J>@ ^Fv {{ӄ|µS~ / QhMǐT~l07qaZAFD.꿾  -d* 98]&8]!VIe ~ zA]>>c([t0SF -majzpnen\@LCSp)Uw+̮v z]CDBF%_W j%\s-WQTCd*{" %-g yo@U 78!c4X|_C;j_M;fpvm'z*5O'T)e4/pJӶ-%!˽~_H^AT\/@ba.Lefy>9Ҏev ~ @c(ak/aSBzIJGۺh?j]ǚg.U;~Ak Њp)'OPV*@`qbW22ЍcK qD0{%m'ZO2:X\FY%݁8=7$B-l hz^;Db1N$YIx7 # w[ %Gvo(->y?b􄤣L'7Jkg8uˬ-#xmKao1*^E҈@w4._9,.ʞcXv 3 p@Q:I =kz$TI!$H tۿ`Є vTϽv x˻`k(Ŝ~0&8? nXMr0Fi/_Hnj_۹%UJ:T)M8ǰ:[v܈)P|pV41Б)o:%[A/-#\Vg." f?\KjWKwŒ*2.I眅ܒ,a(;ҷ0ȗ "Ȩsch!4ETnތeKWIϱSNZF,XroFrK!ɳ ]/zwc- #b;&aA: C(դMZɖ:J=~✅oJma|DvV4%ZmW33@Uqbi  <[>%L[kF{^/-Ofr|o,{s`!_r$ncHK9&5t/?e [RV[~GƹNɍBpR.LsZ)lLrsLɧWg4;md]s=T2=Kxż4B~2E я|C\x[#B>)1?+[ eo @UfG<8f݅eWjnR_ԃa;Wl:"ǡwo& Q|SWekaG'aA¬ąpΡz8rcb3?NY]?଒ӶfrEfZDsMb9mfgle dA~iØjҤxxgW wpvʺTU"y S mX| Besu dOq#Xvΐh nkC:liq-/j.+vwN3_!: =B+ldIkXX9lfA+rQEU D.p',yO&$CC,`"g701Ϣ%׭DA! &.l^ғ9[bB c' "kf-+gFO!+Js/6& `^Y%sB?;0"LC~p$T;{@8{0^ 4aJ]Bk)iS^MҼ_Q/bٯ$k t8_œJ@.Le0ɢvuԲ#ΑU d.|`DrpA5UNꛞQEQ"0 * }רAeޝv7+XpY@Wzw0ui0ԴlvCaՉ t؁vu]}RS%BC"͝{%W]fR"V֔5y+ws'@^͛}*5!Q2[ nA@@D!T!IvG R|`i"*0}yul&w~}FkKE\\h }w_?(yap+x+йقOj4766Z{my%jml\llĝK.}eQnFo\t.t/t]uxax++;7#^#ݛ{;K~Hn7B.CquDh"1 %7%z#xWB=F/0 !cI J--E HCqܸ'zI#eb!-HOq$[!8XIzc)Nt )K3wIuߔWZ_pLOcMK`4< bbULuh4&kw=3U|1σ#w #v˼./v6v_ݹl⨻;&h|t⍍Nҍ TA P|1BANX 1vjڃc@C^@B*9ơy▪xa@ynP>L%kT pZ@yiN*.[>4B<b_T @q6PF91"sdcBBn,pb 8!.BNNh6*\$[df#)*oy"Wz;dmdE N<1ԆrŸ́e \w.h_I<i~͈p>쫚|YhlZp7v4U?9uȓd m?^2DMJ]h1Lz!U $UD|2 "iJ!4ܠk.C~c$@6 ':9PfJd 7Nt`앭F&`d)0Qxn`n7\Kx%6f#_T)p`($`,z> ZC9S X8 u8Sڒ-W͉n$k  0*Q3P}IՏ!>Yb/ԯQ#y\}ۍQ%nwsr!r*U5]T_T2{Y{e+n k#J~vW& @gI.LrwT qJ~iMaGu1dK|ȹ[* RifM{q91F}9'ڃ=٨==D>lV Y;VJ &gsILbODea!2;s;$lCT"*һQ.N=[5F==~ud{3N_ZJ%8ypd8h\pTUKقf'ɴQ =:pO b| "HbFV4m(QaWu@  $0g *E`_hi'q$*#w%Ux"~qyUAz* sOX 0ZT) CAk RuoF`+5D 1vd.;&UI Ti%rcJYB}#"taTMقCDڡ"˥sYvƍ!ZkfkvE] %>o3GE Bmu6ŮvHo7\.IMÇƳNxV-JO yqz\tsISYVv%? +'B3Uv3j E= z~@`q<&ʎ^hFNqKBY1~γU3+DL?Fb'88@i_ac!J>}Qy3b"7@%mV2i;ǔ4di[YNvd3K~gL<$~C*k:l_ hڸrL6A Yk}QR::Mb= kQ] $D3D\MlhWK0uarP6l)LՓ^E^S6uj&!۴V3~dYۮ:yRVQkm]TWY\5Bp患6|~#u'|Ί P/"+>E־RU hyJM仚jЦA}ܯ foX[avZvAWLMȤaS 0K-JKwHwF]i^e??qe"Rxdtc-YTD)Yin"͢@RԟÚFJ}:L'-N Nn1 |2{8BzT3 0@jg(,K1SS8g=~rgZr->WR(5F|+FW&)/n'9$ #$vD+I0JEKUv:b? ղ@ 0Q3%PA@6/V^=l_w ax h0/Kkʊ瓵z$#SpY ao^E :Q}U Z&Df$-[8ʜ)Y p<]/4`Zq⵼F(%ɶ-HV]f'Ź8l@ТtfG@]{hۃb@j]O5Q36,CĜN3NnPύQHy'e&L(iB=19pmx\pԩ9N.ʣ(*F^!vkۂa{} B`Rqĩ_UHp>Ab<8#+/8XUxbG?B[[w ăԙU~0!?0-[ 09: %-\ZIp~HϓMpxHӶe i&exяMTy챋YH=̿]V. ~?}tH{MǢH8N&ϵ?y# ѷ TA7GR9\Ju|QMwdL^YJMkVtkKC}hY$Ekܪ߉t>d2KG*!e2Pg@1ӡ/eEKYr~Ŷk 7'Iu6Md)u_-􀑅\.1g-OR, pN" w?=(toAa%I!bKˣ]y 3F2饓cN#8xfr(t3OΏz䘦2j#ǃb#meJ{mﮬa(X IV2(ɓqQsKJ$kTf5<,X\nw/A `TsІ˹&30yM*!Q-]HRo>p*=BW]hIj]7Q+Cp ז\#ȏB5iq$y$_$lٟ6s2԰Yfl)–iS(Wi1.unIZhyX/~EA,q\r_7\! vVۭX+ӶzXbb^;PI]'?y]XL 9sYq#d'"gl Z6ґbcKkTcR#!ĹQ2JPOUkG@>;Y418Ǯ+9]&9l"I;[SMad#2Tl0 J^ vr݀`pgrڔm8yIhgƶA8J'J|*R}Ʉ(KlPiM/9Єbk:`;G 擃ZX< d&GѪXO"]60&@9 YHf3}dmXW  P$.!z%@rӣHY "?ư:dMoH`jq~ A]F C#]Pϔר7%8bzglZI;}TUW~ǕMLù,8"k,@e !KUQ.`or[:/eCٕ</$7^\a}cɳ'gzfa'$B(s{};%B r=#*2"rH A6+mQʱf7,'ьU8{$H$wo.&hF9]vB[^M-OࡒyhZAj? Y2Qꓕ<Ӊ3;(ƿh⼎"]-$,: > [E޷C{x^᳣A[Ѯړ\b ޵kFhJNKh Zu}8 A:/;yt!T} כR㎝ ^;}[}{'p>+U #Es6b8悓oOI8wy0V;? R!n Wt^w¨@QʹY36W4<ܢ'Yȋ\x$"?CAxBIJrHI+x쳍5AQB 1`uLMSSPR~GgRTR[=V:o.ImX]&1@;I<(\h:|dD#}BpZvpHn/W-.FtkH}tDgqhiWyf{@.PD~P}Bb; i^R2n2NM*iq&P[=,ҢRɊD'Th#sHt G#wGh5tt'BdͩMy{?yk5^D@e0&nXY#t%tD/%kWUSP]@˖adxȹ\6+Ԧlɀ|cpQ;lĆh 9@S_Q/H{+%ܮXҫAd'I K͠/ vҐ[V]VE%WH0ҧhz #Tp!Tʥ:=F'x a/9~w>i@N;1+qQ*n¦&huv`i'π~@!ӅM26xZqᔦYHH}Qai@8VPPr-.#,$\P :w\jLי1S97V͓{& +'&\x&'Bd͔qak%gtwpb6p&(ژE|}4Edʝ4r|CY? SH⅛[.܈_XhԧIPBQxї^mV J&i^An⼎z5Y2/˦T˓-z@lH M&>OD`\6Q_j"tY㨵dS|e y-4KT6,J@7Mc&ȿ5+ ]v\'|>#:p`axHEE[DR@aB?F Q+DN;yc(+/H9I앥tҔ 휁L;͉'[ޙAb_ԷƤjDVTG˧5}tA{#v\c-$W~\I LFsF(ʐ~ҨH8C sA?|ZSK 7A^aҷ7DRd) qPiBC"͝{eWYq_ pcFo^k'vgz0tp!* rG@TJV@ц;w3vZ{suNhқvM2|Z߷yPu/h[j=3oNgo:rCAa S! OS?j=`YZ.7׷qwgnl\ml$ޑ9rwmO6{zG6zý^?_49pɁK\;Z䶗O hV #1Cr)!!4ZҩiOA@-t  '%ࢱΑ#-$8a#ԯP >?uNa h eLJTJ^|pq፫]#\}K66zk66$)!/+Uh4>LMq0/p_,LX=]]_j]t۽N{nFTnx/+IH5BK2hAwa b:P.ٙT:ɚڹY"!QN9z8w630Q(N@y=>YzLn,#VG CyO>Keר9q 3[ͨ9\%{ (lᬥ8vq%$(5޷ϙ)A`2tu0ӊU&z&UgC&䉾;%jb)D)=RAVkjB:"$U\"׍=Y 7o:tmÍ<_0 -0\??oW#z& .(/Xmb E(!ybN Hc.쎺η祟W!l#sm D̝pS~zHab>۪# j1531^a>۩y@b8!ۆMKȹfDgK'UnЊ"׋%AuN Nj@bN%cN+3sOõ?8pԭAZ#FZOmEt,E0Uѻ]װkK$0Ąd՞>2ZoJ4{|3@p|ąbz   ȁV)h31YFVńjg`!)MPm%Px>D$9 V7j !8ɽu;H#ԙeBbSz%?R{KozcqlDޝ8얺) Lwhfx 0xvLNgR*T~BԎ/Vz=cEM Dgh;tJHkub74eC&DlAݪu8ϾX8W6[^&`ϯowMR1E4T2)g5qŞQ5.S!$i)2%>g4,8^8鰌ۜ&D` R;fA$Xn?,*S9ZhF&4HLہIg6H6tudU<dXg^ǜ|baEz/.UfX W?uڭ[qH*Is@rI ztYI xyՈ=T0 Rg5Nmd}8k:Ʃ251;@|Oز Jv귈og|.GDoPeg=&oGGVZACeG!S4Ӷ@-x->zBNFy>/D",S9&gY)6Bhy}6MxH$ƹpFU5 8pfQ*9@ʁsZrwig  DE Q4aЏEu'} 3+ I}Q [9%P-H8*9ӘM|W -[BAXy/aMBQh-.Vƹ8+e{Bt{ni0=AG2>ź JA=s t4=l?qҕ}DuyBW) h:"Zdb=%{:|kuRq([4>R^?{]hQ-=T(ImKnp^^Q͐d<6 ۔dϞ&rx >{um?lZ9׉KR#n4.D>7gW;5 io5IQ bl!}  !>{{]W8R%BmXV_Nn#qTf"Α/k}X0܃>eZsk,ӻJzLj>W(T- Qz#qrrrF- /X<ܟP<rY6ka_Ү"B:>Tu:kHiǦ#!'FR F8x$pbMth^guݬnlՅB"af!_Yuzṣْ3ZY&.mm@fΒ$-P:#ZRjy?eQ@l- =cMJAI|q T(G 5t;f gh\h!*ƮN# }80#N\<(:Dy(6!)Ҟxx4,\jD+eϭQ4(pNZoyF 5QqHq3م43!MG-g/5'ܠ.Fau9/3q Ί5/{J^` g+Ϫ :='} /(3!1c$ "m:pU<GКD lmw 8ӚDMCڴgP/l  |aǨl7GpB_TL[Vn)L FRѲ{Q{:fO?^pɽbb']8q%u:YbOOTPn8ѬZFֻT Ni”7up!0Uy[Hn4]ΰ1M{#>{C aYw>08ݶ%JD Z." +G:ww+)5{́"Ft'>@eOQV{>Hp=!Q 6{ q᳿s8b4x-01 ЍNZ'Fe$~q2rQ?6!O <5dL#@s&b>ygCh!4H'^4 8]8:MyψX8ީ8xJ=BŖt ͊ϰFyBfD|VLf'$_E|-e!9xՍ:ׯ`EvgJj۪A!{x$P|<KH{ʗA }}WDH\2 K _4Us(8Q'h8juRn yK 8ݦ8|>lE e8w㳻j9cYbMi`BU} :*yQ#؋` cE`'@|/Ԟ"??v}hoo(/en JN~ }63P6/0Zdy8&HHc[P.||*FȤ^$u}V(G緕" Կ݌n9WbCB6$w9]xuK|xC++-7B d Ԛ1uv]'4#ɫO O#SEoyTQ>F"TZᴑ rI03PL&q"@'Qź̳cqKmN{ s.3I]<,0a"}6REzUe ^<@Wԕ͠]R5tz8ҧvL]<-VS,}"Ѕ @a ?ok-!j5kvǖtujNH_g݈)lWI'tWI|BZ3H |hꜯp!5EF1E#^V̭LqQ1Hj Q;7-6s-(}( p*:L8D0l#BXyA [[TmYӸngu*U).XYܡ%IǪuD6jD*U̔hݶUv]{UJ0>{6Q(,uh-riiL$QyIV1ޞ͇&^_דB.Cyx4JI[]!ӰeeI7 nRK<ȁBN ^I<1mtH!:(p Fа*>G'u`ŁbK0@ɨzm೛hf|@#Z^$u~%bǢڅcgs׳z?RACr 6ktinREHV`IqT*nc" Rv-Ieޡ7wucu]I2|?ɉ|D67 YBYnW&&H{4-ӵeG)z=$g!%XD 8^a V5v:@}C?pH pҧFvQ\ZsWboLq˚=44ghdO-%\0%cq:4${}Ft%Bti^gݔ(ۏT߭'k'e _%ª" ߗRjYiR&0 ɂ&U>47 ux5yĒmzuٞlC0y5\qx(BTNmԩY&.Fѯ7 qmE}_M^I^}*0(u`5p^cwȯDUF ;*Y@¶.yLZ05vG;@%"X6䶛Pwp;B_Z72v|Y۩M~b'A90i:WMrx>f3q;}_y(*O`?ùR`<Eo8^ s*vhѐHaNCgcO*Lk i׈H$ "Ti|P8 %TsDŽR$oB̝)%##O \fVy7j_9O:擬$k?u<>`fEĶ.:(5Q~\>huZ,'Wyy'ɐ= (#j6YA7HDgUP;fxw4ϒI-3g%Iwي\rAM$kFM Wgkw0x)}h!wiT/O֋Ih4Ӻ;y0wڙQ\$ORyĉO ӠմT.ritJCOh''T䈛OVٲUu*ߣ'4~hp0iq:Vp"#z@#_j@;A(lݿTv2B!~N2HL8-E|M}6b#OX!m61*7e)l (kaQ頾#(lυEԥUB-eϿHcL$?f-ƾ!ԼXDtivvwӂH'g[,Q8f9ЁㅈH\Cp&"R$!!OԵӎǴ):I}Ą*>hXPk{ul(#NcV"J&y/9d29:Љryi/@E M\DnDOFѱ 6CՌ3?dt.TF}"& Y߽^Lr!|ک ez!Ffoixc&7Ɨ)yGc0Ezd Uw s<ϓ/&Z)feٸLAQ#ه' lcTwn?-H)fQ_ s@jT؅z &dDÐmk"hLvrY]Ϣ[P.CTE4З5NB8B Vy?t!ӄki[j.\k٨v˖3(ϓW6>{UY ʻMINvNkw٫k!E@D)Y|>7jт- i @*d|;I󋴔_Q阈ϾZ{j@0VcJG^"Jۭy"y1ikx=):[M\eC}h|,$vmT܃l暮aJmđR26s(PsrXT3gEBdHKZuP:$QΠۏCR^J(d&gIUpo2&T忓cM-l,.QL)bw`w$%R21e7Oj|R=.-'A!8>I⚅Y`8>W^dǵ^, 2FA1bځ"2da!1d|+Si`}({02X<%E YGjyL\|>9piuybJq2\Awr,4Q Ks! i>O6!dkjS~51Mn0RN$%+L,…n`vDIJTHxhD%>t{+r-Ƃ>B9&9'i$H{2!-\?qmL0t9`AF( Ѿ)PLϮ5H iV,a J7}ʆ7 i6kp6J!nr#D/9~ \ĝxZGA՟@9k%H  i䭝lWL2_jsp$=!PCN~ "!AՖod]A wR:/Fb0Nj 큈*RTdn<ԢFh(G aRVk<nv{˷R֛Ұ=tI3r8&E_4vzOGI~}(%yD9f^8>9C&{mC.FOȇ|Ñ%']NBS|3|}6hp`pVld ` EGr)jQkl pO BC""͝{$Gyv&Q",HlVUOzgγ(_c}gy@yHbBx;bPL 1ۻ㑗/3$J"E"z^۵]3ӵ%k߽j|v𷻞|뇣7`d?\znoApGBGYG'AT{|\W7Kask8/..5N;v:N{@vssiw.\|nۗ]ڷ־/k.k_X`ȕkk^ j' pȷSeq; Hڣg">c;MNNMȷ ذ|!x"VD Q0[&@;EQLBLiVDsȍ95&0A~F!9ɦ ``cV7bcZ//W0KV}K\?l_AZ:Ek0Ek~q  P@٣t ~ 7';L ȷ ˄Sj}prP S0T.i0x{ K&bQG./!z̉Ў́J]-{_~ٲaQWvKfW&e#d ѲBHof;ls3HgKt`P5Z KgPcT G4ut/QJ4TD6뫀tI&ς6 }fl&Vxv'fey6Û dD|FKC[&P%@x39tQipÙ\'Y*@pnᏜgA29qn8#1ezfU)RB}"FeD/8WRP z :,d5J ? 7o//B B$ZDXNh]FvRm)5ZӀݛWf(:+FX'vfe2o.BO wˉ@q;IHU6ܧo^Wȋ`S]T/V/!:woo, W)TJ]vxnc$:֊kLF g" u[1]eQΌ*WMil^y#ג#\;iCߐyvݙp)ъ;vq b'jm=WZ '|rqT /"`0RH[F6 wDۭe /pSR:vg@Ñ3c=e ՝='uKCifª,P^ !E6}ZBu^X5*(j/8aЗ˵Wj#Z9uà\kj[>; ц"DuhC^ m(vҗt r(=Ӥt N@8 '4pLP0 LpfS8lU-l x*L66OƜë"mS:@ 39p%Nu~P 8 Q$g_U_2-" -J!qVS( /zU Guh|ȝ6{J%|\ '{U\'4 +9h0mHL ݥA,mk(?Ytމycp8'`ܯ'" q=*1Od47\&-NlmI>YN$""Cmq2RX{\Vh ..͢Z@±ƯLss 1D/: Д l:ڼzEwUaZXoG A504\W"5qA-ekA̵0#RiнtAdŴ 1d֢S y@+C\DP Ӑz㞕 I9މRgT("JK5@T(0SuULĤg 8qM".ݦgNa6;T f>Ns7&|LaGQv~]\>:cytlݼt ;,]K86"0qV9, Һ?.q>ŝF[ a"ͱ B|2~b#UJM3\UAx\]p22 y (` 5 fķ1sG839"ϝK7@( hyz36ʓtF(S&J<;)ą]+CBޤLlq}ݘW(. e5ZZZ2P(B>wcǵ6]GN2/ږh2)݆E@V*L&tVzΓN 24ӑyv}2{/s@8JAwű-FFT^&8rHUu xSЪw<<4&U Iă^ yq󩵐4 \f&^yg Mb; #U?:4S`}74Ɓ^!S2u2]0  {}GiBP༄[Y$чx!,qƦ#iV+nO3)eN=$^=G jsDPoKBʈD_"g 5Q=grR@_ZHI@n:pJnyxvU6w1QI- o[a_֍i(Q7<[ ߾Qɳ OT_ie#D A 'a&Jgn1w-Tw=h4C 4XhbG:"ӑ3φ4-T!Dr(n ~Lt`e=&sSGnh2g\9^DoUy9ؿ"=*I,0q4B?L|S~-&O7XQg:$~X@]1/0!]ALlHIYGiG}|Սlh_`@FkA/i`9,+vE,yT"HMEVYY-zpOC)]Yhj8R2/j%`]z-Dɶ# Y3dLwo.m& Rh&W]HQU'Nτě.檰jD[`(MmG#Z 17 QPZB쑜̀t9m91.7C&8qb&z;3[VxC9Hn 'LM%rZd#&`y|=tVJx%tLʷ?S(%>K$O%'Ry\(p 8=0RJa(Ӂ-ѵfKiqZTd-hqy^JHd4g4pt!KY3{mHl&[ 霡? (vdl{~4+Z@-W@!Sq|2o, PW,#% p>t*+tÇ+Bc>V\ g. ݎt2fcÔ64"!ΣnQ}oo+ % ۼ^X1z)j"Q5|^',%ǮgA% 1ZU8eG~N[y41R11꠾J7|diIB^1VL0;^'gBu ŕ5NqqeKYwmi)$n $UD{ mq8uM#OC|tR,8NÏfiR+$ci^_:%\ q\]p~S MK$FN[<=j),68Fj`13Ӧh&HVoCE-WoNθ"N\`w:'YigoʽA."' GfB[/6bK!{ b.yPl'+u\gQ}m8.E˽ Nq,y:Y^IT'ĿCg "Н SXi勜]ui8+Ori=0P!S #2Pd a i!S"+~W*mA:{0dCuXAYݩKd;9D&JppnсHiVI՝*P՘7%/]_gEn.X-v|~Gh=*=ӍPy>D^% 1^%*uzڏTsT;Q .-"aе dWҽ2}":O&-~o%t(YR<&a14oQgDF@*.CЂBc\(|6o Y`\KZ-t~>˰^]^c>R20$Jrr/3Ƴ L~tm'0`Xu DHHZ*/џoaҐzt:{](jK ګ}LՒa=a_^wAn0fcAct|:hkU7eq<Z,U .lKTy/@jLf #>:#iNȓjdY0ڗTCuN' u;PH~P0(Hm>F]ZrGx ]%E&ZMb9#,=/u113o[$0iFr| {B+jL7C yDƳg%LJRrbol-ΊAd U *S@-8tA` =w8"qEwIߴo<])Xyz+i;ijj!;sArƑhJ15 Xu6mZ>"z紴7\ʡk^ؕy%T7"-1JwNa0dAg&B|?tnQDsmuг|a[Ua&vd:Z:K,* v3zr /pMO UNst:[Lu8~Ժ t@s k^ޯC(S()cz\vdU2Bkڠc_%Y'+b|)dx"vrV2yiY{\mvX7.D+%Z@%)>9zNA? QPWHT%G+$Rdw[p0!#AT<꜄go[ȕ|u2d _+~^ő˟#{5L6 S]F3DA+qUG.ߩ5rLJ P iEuCKnk tCcg.閝'r.HAtvudS{qՙ9v+նycCyQRytT\eb.[8tS.\mZ>U~hZx~w T]Py{NKHZ~/M\X@)a\~]Z2ZPCGր|t,Ɔ!9a!ϞhAk2Vg_ҍi[ FC;ʽOMro0nn['V\" a7^!S1)xIz;VJGfHgof`}Q;O(!Rjbv!Ljω]6ua&I2N)$G;Spއ4#4'&_!m ěT)4T W=g*!STp4OJptu0yWdX'iNt#9'WvX͖]{bڎE֬A>X<{2Ц)LE"#opmH^VFɎ0uqc; K}1 /tGҼhz2|2 : | Ai!? fD[O60zxHFy[+Sq;mTNpВLa,+iIzk$-#EDb?/Kutk iUja?ӓB.) V[ r[.1@oeф4OTeLMsK'BCz"͝y%GyzQ"!x! Qf2BWU~H6}ڳpC؞\ZZ'.Z-\7d~ Åj}ev{en] uڝ֮NxN}~{Jt\ǝKW[V/nmֶK{mݭ+_` %蝚@v` ,79Њs0uC؂ 0zIuu^5E^1کDN ,%VN;58fosB ҥG`fZנnوa"C܈验d3}Q X:Tfnv..tL:Q]OPyvA/HCt;iήΕήƻE.`WZYi/\Yu(&WB;#9 ml"BN5݄^JzQ")8h5(M~btZU$ߧkB2TxQگ)|6Q-+Ʊ(hy:g_pޡo;Ԟq)6 |es yN8p'>{2Ĕ\ Sм"$o|}Mȱ {*ޒqtZQ2 >2Qd&$?{=/aF}|S1U$/N6mHa%Sš#ۍ@ωqr_fިR +Q3j];L#D\@Wd8{v/xDH iC MPbu:V\Cy/B?f q}/[FeA/O|M" Hj3ԂQ0h!ڇ4xH΢n`|!d(X0  Ù.k[ǶO'6];ή cPV\ 8!8(4P ~\b#u*0&Z0ADPhɠP{=gVR5،-zuR awhrBIB,6HnmB8 XUTC|BU ~oONIh5!=D ϽC,݌^ %Pg:}.vaa ! <$mH% 6LBTaFB!q|v 7 B u41uM Zn R2;0HP= <&mIےz3Y){ʁ!4 gq 1%gS}Y4`D؅dD񙮭T^hFY-iujŗz)!-"՘o:2 D$)(6siI~%)fWV])$|hq(CR%B#D6( (UOY P˝Tn7?/8 2$ cDI.r i;Lt51*T3͕Em4+̕{/^6x=w Dg˜Dex&z ɃӐو2<V#9"zX )/][~0x0le˴r1[` I*Flu&=CZ@!kDDwTuoƹ]Xި,wzڀ&)!ݡGZ3zwf%TƓ+ܫ0kfS|ۯ@ zդ#iѸj)bD5hֳI/{ؤdk+׵2[t`<^Fd_#؅u3%*_uJŠDrr[v aC%ZɆHi]͒'lnz w7k<,qW(@/`V)|u t|)=<-(iְGmjlh@J a 1"k{-Vtlh┏`SHwKo;NOӲ966ˤhE4YN &eBmr$үkCy[+))H)kC#oZyL,yX`"!bA4ި(,SP! (g%| -(~PeĒP`餗BEo߮1Aߚ^&Zebzn!FQ-S %ZHCd)֤ci@eSCH3'>O%Dg/g ZH҈eNLʙQS69:T + i3tF? 3\~ k=CsZŸa7=ٞT hbiCL{%03էֳ|N^8FOalƗ,ctǗ)OK'ٹ:<˯1SdXR?-<کEuph0I5B.#™zLIݱxTFnh Cyxߥ7plk#ru(Cn%@1])Nc 6|p2L毓Aۿ%[\{:IqҪkF8lav\T݁We'w`oH@m1u 0zJ HMgM7({Ze`ɮ[bu3q$@goPswxqoz l]g Np" ]LP;&Ӝh >Aƍ 1qGCu{6'5g^7ohnfmv&Fu !^(zpro3fo\x0m3'FAvݤuz2? 8$\!1z8P\AEY'g8r=&6BLBL-8pО5I3>{2"T27}*ivh`OQ͡a2/O+GXO%|kJxb"Rfqe S4IItKYj@%b3]>yDJTq9E ,/0'&$yBb(ZC_9l'ƦM'hZO#>L㸌9C&>k$q,QjMC!ڻDL+t ` ]I[ Q)wip Slɴ%[Z\H_Cr$nuH -*%q cLfl"D44sנE9b بUL3e.:&Re^@aR63C2^DÉQ_(Q6>T/q{SbmRh?uf$ýAzU8c x@xC9<2 }'{C:+Vvz w(q"N 5Z nY].n꾒n-O/,8`lRduޣՕ~p"{bԣ-j"MQYFɰX8Os%d6qmGoٖP ϾE>Z.g\>v>Y9'!>n-mh1vm4hDP +MaO3F LwMԨ=:N|aE2hL:D6-P9L"2 2D\Y:*( *׌b2Ǯ]qy}Ķ$t%x¦m|E5/˔q$ܔpQ8|}5Z >2'q3) '&9M/G|2 É(pWdzf}uDS~rL,ln`ըLn[^ADF.S*"r^2ǵ^y%SJ y\f$RX Ä \;p\J5RuSw$wF'=G&v蘌Z'u3`QǕwΜQnjp1FS Y(tK3(9R?#Neѡ3;[c%Z| 1%Bj|v2]0p$|"b7*1A0Q8q M3 bAIb4no8#iD{+&v!XDZf"))'mHW$LFlUY,r6EYoJhNN/j@&>uLW2_x#Xn!{5'ʚ|X+kl'Gi*8>r WG8 Lmu/|vq X7x3)]S^0  }{F_SqXL\9 h3i21rۓKduVRѻBjSݡAljF'=?FeyBq_Xdӧ@j }b#f.zעى褠qZ<(u;7}g1{k0B>&PwSO(G;ѯ݃hia%Fwɯ$Fsݤ$Ʊv``2=jֲ9&zfuĉ82I}^ & yޤ~@_%\Qt\T*\iX1rMpA.uRt. õLeQ&q8FYFt&:ANlfu0Ī8vȟS=)@ٜP!Q݌1Z#tH;Y I| Uȇ6GĦ \$B! )GzΛɶ1izkGJރi9l{*D^U%%xxv=-c^%"2- sgR g{2^F+>:_π^uw-@ldI%i@HKD~'/J1WHd.AcӪb`C}^y'BGi®*<B+ #r١?4:UVdQ=lAU:Ͼ܉_U)d:@^hCy\Tv )ꄍu(-VĹ܇9$>6e#yl=lmVY}0u֑S͆qx!XGOI( 8.r+hR(6tA'W?.Pd*գ,7֭Sֺ%V(dH:kc$+,#K@E32p9焀ngk/r`O#7h tSaC1rMULDђ,yE6dGSgb'C{ˈ#c`oi([rM Qr۔lAFв º)hh#U}'t}]hӤE 8a`#;">n31 by%r!>r'^#R:4ME5E紂WNoB$5mו< 3yǾR!ge"S)\ At{CVB 5##CO>V֫X\.3 u>*rwjqLT6#ԯ"8LwWlf[2pSR;?cײ??V]ry3[jq ~k{voj^M' g@Aஆ mEVȋP3La.N"]Ga@g]!l(yMP&NΖD@2yU"8ӹNˉѴe%*F^ uZBj!2$ '%!c NAH/!DwruQEI PsЀBN,3#W]BK ?|2=7YTa/AaKL:4T&jrN/P6 XuN+8~}{@o5Ѱ12^I 4N/Z X2+J3kM5,x  i+_mj#&u!*3MI#zD&vE=58d~'41 NҥΠ4Atd(߷F_iw "z'&8a۝3. l&x +:d%mQJ! F`r*$QBEÚRgu(K&^5#(f%5=W&XA]/gEˈƱm'x?E6@sN|QFwo% D5a'ѳo_$ީd˹ӰJsjRNțr!jH[S6巐256~j6Hi8S찏jGڮtnZ1IztnO5 pǒ•=U`Ovik]k5 ^~Ft_pQ?osNLg2 EhW)=D$ˌ!0 c&'%D4NZu%a,$o&gWP蘏'y|M9]NbЪ˚n1C5VN jHRFc#/kYx,Q#/FbL6]]Vičl/xS Ի - ^WC-yf>DxV%wUœL3is[!O,PBVX]O6"|oD0%! (un&H!|:DUӈ#ۍک*CuQS9#,t 9&}ΰqҺՌAQ[_;Ab_k"s΃Fy:W:FIͬe2Fdw3κN&N'c@~:|NkHK)B79`M|6WrqEN7I왡m|rO WnilR6OHr(R[IkHDBXv,*E, !#Ukˉ@>G @GbՠFe2Hb4{QLH޳qi6QsT/yvgF8w9lx 5oBk* bgq"F3HbX~;A0B0-VB|WSd6),Վ{ ~؆DNnl2%BwLS,r0*DZvB!Bz9,9*>|m5P.58CF;ރR@'JX3 nA*ݽFQʉS.e OJֈT%G%QM$< xz2D N2T1#,.pfs5[,rNX(QF &b$RLGeT mQ#(## =cV1UJf@ykue ^ j8N<#D rw-YxA/.8yvX'7zM%~Tݨ}y6dGŨ[Ҭ힕i+Q8@"KBT'ToҮ!h>ۼf հ2MΖ KX ϯ%]E%Bm@".QJ5"Pܯݛ%G\nC>-@S.CI>sv T(oh zI1 2"PnW# ho+u4[c8ER-L97T] +F,wE`*fJKipL^I-(3a݈5AqFT:ڀˈ'- % ]$a6tN(oo/4Ap,; f+dx GNhLdqqXmDU Rښ%5JSлƙ /*#HޙF.S$0<\Bhog@,&,njXTʵQKv~/2iYhTپw]l(xv8(88i8\OQƍ#wɨu.m_A.\RIF遄|䤳Q}@;;;ܳ|M)8({Q}6'D6ĽvP*M\*N#+r҅2+sk$>-UX[LQܨhEP$r-:O#@MC$nv']Lg[/* LVUURrf Ɋy1`Ȕ} lqQY퐶CG\=,YP \O]Ea.LF 2Sl}L5"q%l &Yjs:3 <>{ ]dm"FMa+ T*6y f!7"tj3T; L>d@Ž?1<,y*L.܈ K FP;TW%JWFߓٯEu++{]T"[s%bIay焜.sGq_5`2xOK"nkSeJ%D{~D\FR*& gΏ2T ]h| gILJ[Mv6},{! {TsLmpr p`08{ #Q9'Av2rv ƢzتoNMגt=:JEsR>ƚ oD{-Ri7w$,&X7 jHrXlޠ:VZ 9&UC芛 [F^s9hu"hUĀQƷU`%ayM\i5dT_%`dg`E[Ann-N;{13:;ޭȞ.b,d ou>,T[dK VUjђ -l~)OKcF rۛ>Qf#D0b`ҏ iz0ܚώ/]&PE$i3W"K¦(9#\vVPZb?) ~"|K:g-#FnT S$Yx4Rd)[˨'ToԞ cUi#L4|ʗ"S%T)M!QOWiM[UtcT+=U5z.U^7}֭ ΣG*Y W{d+й0~eg 1bXC*` i®䬒8=:Wm@'' eɊjT%ɊjZmqܦl6B9ytWPjO:m|bs0V  2WaAZ`Vb id"]qk zKŷ .;: ? 6Ep.$s!ȥ놼/XTil_#en)+ɭuɪNAt(us^ۯIuK,ʣF@B+FXƐ X]|@M2Pd0W+3e>n* )&-bOSqi 'h"aTEC&[P,Ԉ!oH#HӮ; R&R2md)iMG)<\=tMĂͤ!Twڪlk`q oWTybHK&wLA۩'DMFLbF3]brrݦgTK8 d|D2[=ʣOHXT^4Z2FhY[C= d DjuUdӖUWIpMg@6糦MI j)߮̊=nVaCH賆cM},`EXxC%Q˷=fT6D5t,nG"ٓʻtթz;`4Vc+{#WU˄FTP[$V=yJkLRQwڃ ӂ1-Tov=R|uT WFLEwfTzC8%6=|;~-7,PN´^0- I[|V8F@\)]*,ʧNP+E ,E| CE5xY"ymO``f+";k`fdʟʻRi E&O^|sd{ v#ZOQ =AWe M 7d:,t3yWAvd;&Ѣa|N1~&|?$)? 촂Ld#KvhQ"ċ~O&l]S WdE$]e&@ϵY> ɵ Sjq:F7"~ya81Փ(Îz,? 9/%AǤԄ F@?{5=4R ?'\TwP=`DzkhbK(o!y|{l9PӒ~uU#-''Hջ`bߦ~46:=EUIG*Q=Dޫ%$%R:a-Pdx*RI$LJ" ZSiS6i% * ,^ÅyT}ے^ah~,Z59}fr%cA܆wPvn6Z:dVɚw)9Y9aˈ @?vE&q"nzZH*+3+i93rg)i{Ӱ%aSLa^[rCuz؈%js 2(A0BE)L␫Rս0DC[9,>^`5a2f䪃o4k &kU o FK_FB9Yv%tGpnS ] gI>Jw(jOI>kMX>$*e2~Zk%9l\Qa[{Vm$$%[`!g3Bp%@(1X]!q<gNsr*ܿ{[ N(E2y;kOZF|M>ŴXi|tPINv*TR0UN讛QB i#v*R9A X iR.{KĹۿ*#iJz%Da"T& `덖)}JCDmߑ#HKf,9#`Gh \OO6P,a42(W0۵k [EqVgћm4*Wh"dΔO ѧ(Y,/rG$uM{,dD,D%=sv"MH/"SbH Z8lVтmS)J5c0n)1^ tP@( =h=>sK\<^ `4Q}W8s:yws {ބanւqYRU㫑o4h ui-bumxUܪǃX© i- V q*lr)3ש-XTDwi0eIߓXkgT<+Bkľ}[]ɲvq*PJ @I%շ$p˫aUr^ XjK:/^6XG'hՈ„wMH)j-wގ\pA1(䕒1KU#BŒjd:0T 5tq vrۉGv%`@#c'.*SPJY(L-+ʲs`59Y"94P\`NhBNn?Ɛͥ35򉈟r@;U&m'V1!pk$̑HoǕNëM#MQH CHĥM} \G+q#DDT&E5D3#Gӭ)푇O=iFVbzgZ{F(lۍq<[Ta*ig1u#Cʐ2P";ƐV lLf=>] wU1/dI~J3D,/QQ@WٓNdN N39qgvpE+&uw0Ϊ=\gR_, Y!9EA.qmJo kh"h1aYw~zºƭO;(Lrreiv9+JIʋ=MM /V=-k9&1̃ }WjU$g zR\05l{ghrX+{:[$X(- md7`h:cIcAKAIrtFroi4A[T_^;m7K"-Nd࿧5RvCPNzj,s`שB"riݵ?2)1%aw\ -,Y+6qvxYr鍅#)*<[AS-"AHyNW%,J RֆCK!.}UzlpQ}\[*|D$I Ec*%H~ibV]QCǶ0<_~nӲQK]&^ՊH+s-I-fH|BJ^{(2d"eĚ>15ƠG@![:etQ$)M ZI3W=7YoD>^~ e=Xnrוi ̟eh1IhS+dޟ^! dR*&iBg _)f5+b&\qaʧjT`] 'Gw"RƢr.W aԫɋ%Y6U0kVeQTmm3lsH E) 1}1(.걘3& 9]Jߣ5Jӑc7j=|_q I^tKzJhn z>RzPZo \US_] ǑC3)dYH[ۄ Scζ0DTxgm2b]Y5dOJշ`nFjo*rnxZ M]:}KlC? e&pv꺝?գwt t־#H5Tu"p{FDA.|2'-4<@fdyGYɍl.{1)CJꙇIr0 2}j!#G3h40샘-ʜ ƶ5WrkΥ)ʌvd-@۹+Vr}ʁ,W} S`.*hnېT [%^28we}9,߂-I`@y!/a[ Y̒M|0 ZuZ@p"h|*kG@R~L`skդ ˩Rߩ)#PaAV_G5 u_.l8&rVk!8.p)q€X {&~G}쭒`SZڐg1yd96yn"Or.=Q?uUŋQu,ЃubBwFbr/-Jl}JwP߶- snڡj֐ݦs#ȭԓՈ6{R#Y[؊dbW8qn#Îܼ:X`ØO옒pr"ld!3$S272x澐[$ІY7Q܍<.pK^Ri+srf*朥wڈaM$z'1;YJ}S^6k6F|GOk).mlт ~s0^˞PC.UaXzBˢ0G9A0R˜PCя$%ڒ{dӺG&n %٪R&ֹD泫=o5Atr e2GvJP]ұk] p[AO_Xƭ\wGh%hG[ w ju{m)d(db#L:)p$Ao Yiz Sni74 %7PX]R|þ :m8Z3&t^ْvDGf r"s.7ESKpp ]S&M*{ (a̔Z @th:;n.IW񕙈JL=3hQ:x}y@ի4DzfUhW.]Zln|h컞pVL-7it13 f-sD><GBIԷxIt-۴‘R)9rsfdQɄ2ܪ #-8=KwUZĝ]GN0dMn-4{#}])gm[֙0ž>aȐWwpI ^\ゔO(ɀIWr*n{\ K(: G)pd K|%;8޸ %(E yd&8+)u@pe0Dԛ8YavQxv  CMMv_t{9& i))4ڶ-{ ?˔/Kɳ3`\-N sƠ< lUTH`P$)h/-)7V0I_f-L/Ɯ2l"kʼnxu'ju|**@ 4[l!9ΰœ]̐Y^/,'yt0#-SO9 poޘB[y$S\|2iyy}-m6k$J2t(> aBz!V]5fLlPC^WVؖ3f9S'By˹k5!M@>V"<`"] w1ߩV0kzgtg@yRv< tlf)=%hnY>C*'eL # C\aK s#} cS1E1fr>'Q' +ڜGu"҅j)hے,:I0ʋ`KkoB})UʐH\*`Q (a}T`c}CA/Tk-So5)/|s\T^sCNl뼖l!2S:u/ 8OP/VqP2 ׌Q>/dUA{l uBC"͝yeU} 3Z&UNy=O|U)=2oreL[DA;4  q)")FEA 1 U$ 3ÀF IhBιw{_Gwqs~緞30yVv8r8kmc/KE~,xmm.OƔa|--1_],ϴkL\/+V};7jk5mv7έiεwiFu~ekޜ6̦YGQ?мތW$y.fCn#> XŐρ3JHK|y^Z.UKjmPR^̑ϐs;v2fEȹuP酱[~4P ]V^Ƴ["NNr8j4֞߳ww5mn!mivs.sn"f@))S%Z/IQ69'h3ou(bt! I""Pw}B9] e1Ͷ#p^q"bw1׶\ {hZ&omjKw Q]!y0.Q$+v:~x_TV:m\0C%PPԎ=G:([+D ٝsxCdn!RwYx5lw5 -Sxd_F0AeN8EZ9Z a\7+|*Nk"i>>Rn -kJ4#3)wS+k:QTn:FIfRν}QJqbKBqs\8[kd-ٔLm53A !FDߜ]IeE򒆖's8gK8ߡLR8syr-1z7(1o+`,v}{>3 V1-LWEM)ds%ô8gluZ=Ο矮d{"*+.+W9?oSě}&\ۼ.,hs\h V9WABU%\4ަB**7;()Q'C֋([M%JѺYs; VW^(kb/ÏO Mʜ^ȉYNou۾ʻsam;mg8(N|3\ yްk<S^DglYNBϥ\6JMD8b:drHrFӎJJei`")|BCBUJד-Xe;OIaE/X˴#Uኵr?zT4:UQ{Zt kGlS:0-ֵ0Tr}b,jAYWNO >z&|vI V,B>pzLƔs|>>QΫt8۠SxA#ȋA+tzJL݅hwZ*+`swib\FnС7H-Jm (| hj.-Hx8yu@H z.alImWLļ`~J MWšƨ&L6av11!-ƘD$LA˅ʢ ϯ]oo{RLD`>XZjZ/[KHwﶤ3q>M.Jm,'qz2#]njnud? C'3XIXoSvYO 8NʝCA;pY++֚l,.V4-b(ڈyN82wxdg%xo',qc-xP2ľq9hG +bR*Kl-ԯ!U,d86ۥx2"Gdf#*΁晹 l`8|ϖHF0P&YL9WtlFL JkPܲŖf+?vYMdi%Dϫ ϕBY˶LH tOjս&Y$_B<?eZS Ei.T~>薄XU3H~[uvR5O#n- ,zE_ZpSye^Xx~.EGzr#rXJ&8'`uJ:5wHkjNĎAS<%\ Q>L(;ʔqgú~IZ/T LMH<u/ϝz֊ NT.΁: ?!ʱ(bv'\(P.)SbYPڝ+SS܈+e~m{o+vIM$ʍS9oʜg9s'i.(eY!rS)GQLⱛx7kєgw;ʈZ,ϗdbA%Jö}O076vQT:ƨÅ/\:UTnmQ/Mǣ;f<1Bsr-mp2?t}1P>S#! rN/i6cĂ>}(2̀LӉ@Ƭ.Q~3^͓>b?Y]5((hJjBx6¡e`vB;l ('qAX0,4LK/5CiwY SGABM: zrQ6cW4` 9Q02DCOQj@McZ$ JvEf8'!#S@jL0{3XPRΕ3)`ʄPg$NS{8c۳Urrn^}Xec&' ۔Kƞ9T3icz';)]ytA)|&VLZ=;.֙u闃 Yu&.oqn)L I[\uqm-^=ฤx|7IQ|\֠D&q Ìn`Òk!9h!Z|7%9ŊƋH0́yhLvZ&r%zѽ"'/T"pF?^L1DuzR4A )-V⽳L5 }+{T_Lou,b5y] ɩ5~/(*XLSH06l[ t6f6fC ROOQ"eJ7TYljm)Uޜ Ыǐ,4ޡxkyYwz)}isbɆ-RTAwfIi򄼻5P4ū 'H Jn/ R(Ţ(9-pVy,$h:`71?"u͂r Nf,tA5g `.%WC]$PV dF?p#į޸+NiCغuAiY @{.z:p;֭qs:D_L&|S*wrAW3g+ %Td 'n e\]WsR`)5vxDK5cvL2LJO]5:Nw?-O>"J݅x:ΐ_XZn c1ig ݡ];4Vh?ǵZ` r71h{<[2!=MaЁP鵣.S}ohGGY&p-Q!n8E1fx=ӆϲDN-R䏖lA1by1{b:]v'E D̻ZBJawDsame-i'(]>iu͡ }_yۘ>xT+7~1v04к^hfo՞ g%PPZEՍS1HYY)Sʵ=,:MvێX*:F B#E ZC|oEgb|'F OUAbǵ(]{V0)L8`&3zuf-ɲM'~>$8|v2AgFz9P+.2e뗌_sߍZP}ipu[$gz=$+4OIC36Yim}ȑc<bJ~m>%AKR1c3|P}.z3?vr\%&sͽsCHnv'EyO< Ȼr6Ǧ<)Hz?o~algGO)BI| 9 ovDx8]Cf f H-ʾ}JF\aĠ; hZ<]i2eՀdnQ I|$˴=rqFR>L,sR~`SX T-QR@@W`A Kzb>Az>]xc>uks{ѝA[/2ϬTjKLZ])-g+3e9U& _pې1|!3[ HiimK(q-}DZ+KFR[Z*+Rm:goKdE ZM~ lYCfKrmiV,Kb^K a{!e߉9n lg|#Pe{YpѨm<;V'ʍrev8;].ͮLj9Wi6jk-*n{P54rGLZ4[.DUv; &^L#d!DS7Ra84Y>A]ʍQmKb-$YϐocgYZŲL'w qϒoqo2,ߑoUf!0_<.u/4 hیjՉxPIȷ?Wq15T ౝJk9S8c 6BgYa|E#Ye0ֱSR$9V ӎ؍bihl6[-ʕzw+L"No -:6Xo0J,2x7p}<${IVgq:wa"XB44I&¹|k+x0©qf* PЌ^R Ce =5o"}J>fRmA(K$"%jyf Q Ne"İ%ɷ:\n` Zqa7-9ʁy|{2 B|snm{a}ȷ%uK taBmF?q{Db1u十۳ ckT*l3"ˁ[pnIIԢ\\:j.NA,8r#ݨY  Ѵ yґEFRl(:m$V0,`Y2/LNa k2ZboHJSgnBJ!i|ۧo88}L5kx5h1Øfr_hN.|$<:{|{2 v7dV2Ώo`_M AfȒ nQGKz`3X|:˸vUl$.Y"oy͙=:N_moc̹2 a1l7ш~~sVQr:dl4gqp;)q.RT¯4[V&Vts=\(bZ[㚙a78"ϖ4 <=H Fy!jkfaٌz=Mtpon&lu!;2o@9[ ԑ"߂{nȷ׫!IBee F!X?0oe9,$2pțv.z % p 9jbyʷQ)p) 粶F]Lh<@jH Pwa$1MiK""g8Qz.uO2LKf\ B#]5m G}e0OZbYue51z1a&Ğ9|A#kܜrEKʾ-,("f0Z""-(8!8愡cN\AШT!ެN~-ѡ >e>uu^o`^BC!͝{eWYܒ[C+F圜"cBg}gPshK_穈h{DmaAPO+- A0 Ĩ OZqzݵ^@In"$J_\ <wt}W;a;v?.8 PZy++[Vcl\nm7Z7IsY\Q^Eut{{^#s/\x%k]g%:_eկ+'$v Ig.f49 ̡9̛'|R \ ;*Xu^⽽ng޾޾0]N]}ntu: 91cJtÜ2'*tAMVsތrbI89ig}F sH͑&qc?~Pk<|y@Ɠ8l.V. Ql(Q/kp\b*d1rv>˩tgål nQGP88SL@0raV Mt)ϵsS u<0be;{Ka*mxd"ǝ*ؼRl2NS4lЯa׼\2*qMYs<ᾚB<p Rf dŷf}$ć?Ή8~!T|=0 sk`4)v}A KE]#*7rvЀ i6ጤn~DΎx|nY6\ {:'2ҹDhƊ$v. !X#ۓa%Ny(jIm >6r/m(P$q)b~9;X{7 B?($0 D(,N}t.$Q~eVvGA:q\-S*7 .lVEӶ ?Ÿ/ vpFSa~p}Ҁ+=EݲuD.v}V:|z4,\W'H1(rmO0Ϻǂ?#]!_C"ۍdy9{>L 4KR`Fv 9'$ȁK r;4O)?q^F&}0-F T6ʄ&<7/1bav$87Bet3B!8ZΗ3n*'ٽ4>wyDc S=9NxGg2%-%qE4][Dp cV!<::6Qry'9LHHO 'p"ɣ6(Rr'9s X$tKayYѷJ.p,.X6E@'+V]eKz,2hpe@.I$M@h-9 hq|T#n-PU>XSoD:p\*q43$ߪ&7J[S L~K0%g#0%Jlj~KTY#c,t0G†:+p6[5O?x)-(DL5-A7a,t |*D(~Jѐ̂xQRmĚh (4K3+PǙ.׃q]dSV4VKׄI{sRpf}OsJ)~ AmI6TF y LW!ezt8W~}FDItMY R1Db )}"(L|$H6A~js UYvg`\G0V#}6t!op75j}QFm<5qJ;Q_<̦=EC@x{t{I,u];zZ~ݪku' r鶭BR$r ^ EImfv{%aq^y ^OCnm)[:oKsAl+$D.#S&~fR7dR&Gήg3Kۺ B2 Sw)4iɆqIdM;ШfC܀f>EtB:$谞?R F(iۧaaqazA7݅eSZhW FRn*u '^!@#m-1!`TI87.?Ks@>̭Ee# ON+x.W*2ǖ#+=&&BQ{'KGUIe00Ij7QطO(}8]tW_#Ʌ.EYq ohmy! w5?Sţ=3 B3s!J k@Ixb%WK&] Gs70rBc9eBBti-Ll^ h>TdZFӲcy-XV3h8]Jw YЏa y|Ns> Θs8י B} 0{A<I3R[B%݂߿? qR'gφKLRHm$Gf2,D^"yI>"l/#D&?GHk@2}qy29Ő @5`Vus4u*;LlTT&7>-`͍VC|w*ҁɒ߂Yo A0XV/GJa'6Hm Q/ɥB cӧ1C "QnvC/5#j\d>IGHG|xR>!9q皜So6>aqko֠Fy9u'K\T 0Âmƅ>a}3d=fM Ԭ^r⮹Oep0'v#d|nmQmq s#&*47N-Ǡ/;ُFy1<\F'])Eai4n|O$ #ْ-ɒ̍ӡqXd?#I.Z>k'|̹ݥ>2:NIfkY,`|6iM;ܳO8U8Eɇ'(ah=rJ2TwWL`%0a%#ԐL&X7\zZ@Wi֚5@} eR ̬%#nGIGwɮPϙq$m]$&D0{AuU|;0L'ϾāA ǡ>n7> ѳD:fYk$?j!}3y@3FC&UyVSGyT5ql2XdS%ݲ] 0\qqo~!̽‰u:_m! x׳eǓN|k瞒Rwi tqIYlX;'Ȉu>mf[݅'|$ghѬf}YzQ!}$׆(W/&+tRpl&ٸ+u)DԱr%L;zLZ_dP  x am[3pnk'&8~Q0&|(PӦ|i#II>EJMa\z@^G[t$ k[& h@%\8pNV5׫I Մ,-B˴1*1'[υ EݫP5Gϯsf~Kbm ]{^}/dab.Npt WUDgMD$LڬKT5|ߡ `'Bv׭}n^ 3'+xŀ4XtFR2^E&-p٠24Ia3iק ~&㯪0q8m+M\Q'׹dSXlZDWJ@ܣ3oeIs9}poX[F1 SFZp1IRK"y_} {@Wl)4)m}(y%w6lݔ/>p'˧ ҚcJ&%k[էC_g@# |:>hm)N`\1Co4.DC]p!UY`2lt.!i}teZc߯t;uQS'&=h+u+5 ˦} &z%{Tiâwʨ{gM(_IJHVpE_ѷ0ox4M[4rdu}o$>`(v8˕&&.3*zjt/9сI.g<8S@tYm(Lʂ"7e\ef!i"$O?} w Njp6n]in0f?+#PbP(&p >k GV {n &_!>O&s#>8_4m- 'J  <^ݼ![s$#d{5[6-U7NʚOʌ<}eG`ߍӍK&[EBng^O4˚g EԶGの9= %}B%}1A7U ͦ!- RbP(8ՠR孼\D)OQ;5HVX Kd#wSOwP;Uش!@0VV|?6P*N:SvNI,,܊MyiWļ|OWm6\sb.?]νɦQ'iG|G уkO :iΛ KQZT)9 kܬIҶpnyT%YW&4dͶh 9Gtw>g܋VaicLuyҕ41@b?JVWyM߲U}3<_#g2A}:E޲LZ@'D~[cTbx75ŚkyJݾgPC i:VՍUTfP @>//Y:ϛG5}k$:o8{hiKٟԟuvc$)9L>ۨϫ բTQޒb S%jN7ٰh0CGAQ=n78}ḳfNSf2NGH1]6A(1tN$c"֮l}AM/󾪚 %ٱ>[!3k('i#$Tr.N:AUQ:';z<7dC@FP9fy "oL~B:%OEV$J40Nʲmϲ8?fkߪwPRTxUzw\V:D{޳&=L3kVAolU;ҝ{7 zde&aS4u7\b'Fdh ~ 2HoZIHzQ k`2dPs0.ra1ty6W5"L棴jݭ& tS84niXA~>A>C~R>"yLYSJ{Wp[~lsbvKk^ab (H0R9EYؿDcEf AAvޡu޲Kb]zn/Q ,)Fp戽F;RjoVkxZ_q0}G0r(em²鎅?AN>Kmϟ P1ORAE7wwɷ;-iO.7j"HtZ1QAҫj[E@?(沃T%wF/||{Tt 8RrPXkۂ70>}.WäYi(ȊܖLb@bT@tP̆@@h6,@p49|2ހ,.IҊALk4oJG\tUQK =9ocAHD0,qPܳ#G$*ހ#YQ UqqM[YDb F?G˜Hkwo~qL.Ysq~z(,-8X5wo qcPhht)y>;Xh匬5!߾dc]8XO`+@B e[[AYihV΢VN6PZ9wpք՟#zgR{wA/ "$^BDP M"4dE0bǧ|;dZ@MNP =uLU굳JCᇮʚ LbQwX!ï5ٱ;B1(*e٤,|4GlD8 {S,'2GG~ S,`8h:^$Hj9I'>grR`wy eTNs"gɷgMyB%6\g%đ~"n=@]09Q2[ gZMRs'a]4Ʊ,#gx!CheJ ."jU<{Ef"h#R,W19P> ;H> 0iz Xh"Z Xth|Ak97KM19;ŖeO3k)$7$>.toWwmHbad>^)VO,X*FAU֫à(Z^yf1g@J><ǽr#ɷrY9"!YP٩J099_vb!uWeY̺ i*%  WduVgYD,DS5'Jf㼠^cͩ- dH20ic|PSN$^,|zVRތLkAPj2iB40=beWj9/ȷ $K7k564t4}!g4D@,Es)"Hc`߾c!=)M ^닥4v,)YCm8$?DXO&GQISG6UE+)v'HiӶj;"@e¢t44@O|'_X}Vul6A4`Z b*:Ϟ3!@O 9DWOٓ MDCOܔO.Ţ+ܳ[ӆHXJ0OtPc nS;Ke(/I{ Ҥ i )nP7Q_,!Hc4MУ4.أ]xAeC~vt=@bJP99f[}Ǵ=2L `01qb^GͻwӔ!o9 gE};ogVe&:q :#sI,͖ڨk]v hѿ_2,6#0Y,r0"E*~_LjiN&)ODo"1zCd `/oP2:"Z9XlxXX1!ZqHD1!׌ q VKv G^IqPϙO=0Il,WUtLLgLZO >/o؜Π]y-"aow(yG5]KV%">mqeqIG_zɣAZӲ)BRG,t qn ۍMh*N&N4p ˫/1!N [btIҭ"@܎X,q8o3m~o'slO$*S]tFT#H#Ȭmli4 # NWq8 -G>F3z%uҏmn rzCFl,Ԁ/;C&9oۜ ׹q }3;K'c]=س f: 7O; e3YtYu,Q:7AK NRJ% F]gCKfw̬C>2LiQK{=ouCc>Jy|e<+vbtLsmoRj@Ilѭ9u%+-K2[ .|0`ÕmPnGB~I qw07>`˃zNlq[v:by^ʔ?J B@ J(H`t9'kG!=揺כ!g6ӾQZ&e{gpw:l9{m|MkXLSaLlX0Nf>}khh=Fƒepp#6qOKNA5+27#>[L:AX1̺P8P&U7a[Sd1(xφ#Uƪ֭#j<$~o.M&Gm>$D!oJzzzuHq@n  /p.=Յ-86ct^zfb=`и'lH~Slv zfԗ ؄+R}hgJ>Л}zJ MΚi?q2ssz 5mEݻbvz sU,iX3̦c]윂Ӧ5Sr ю ݶ\Q`+L:̮ `kI~F`GKE,Y0k> Kۯmu\<&(ϣaGnIM$ ߰9p ^hMTQ`i侾d10O pvdme+S`S6a/VUӬ["Vڄ0DHG9VuL&̸{\lڐ9, ]fSu[Јn_ &M0P=Q?zUv9!G46U 5 Mt[y  PG~CgFҖ[y)($1D (@w JET 9"cwy#U$;Aud ٳ-9|Yٳ[ n! fMV,Sm{C> -GM*`#NCYٛ;Jt\SŻ_l!Ca@3fFE0+@N}6dJ8Э/.BL'{sj<,&*V}uDH8Ь-&d5/oߵ( @8eVoj VJE)xȲ'TYE *yՎiv48|":$-rY. ',]iΓ秘#æ'OGl:b[SgO*vc<*θR5>cu\i-~ճg=0thL^6$T\43|"AHFZQc7 Wh#w HǁtS좗\UL!K(aQwdݜu(')P$mr4\,8aU rr4RuAO Uu@A"M@g4`;hUXonxӆ 1WRa$qi”MQ5ӪʦnN٭FiKTVܑ|}RĜNErY ` upI͢TxuΜE[\VV {!=0q i~,/uz)p܁ٝXy*g,issf.kT_P8'lboȕMbͲ#yrdUcW&Yz5;rBsG$EcOU.r^=%"_|AǪޚ<š*RkLPYNY+k,x#_c 7HٽQ=%k۶ I% uzAcu?ݪqy){HMkH=>&KP -9 _hl:u4?A3}C@_:2 {y6˻uNIx %@b`tI=L=w/s8r]!Nx0̥B# {L*hJq RT\@|ikMz  {C`>`'p'x.0z7'kɷMCÉϮkNL,n!-JEg͋22*U-HT@r33#*WaMB1ܮ?|fIҘ(rLcyNKDr`|Y^Vr34jʰ|o4rlC1M) B8-qdJPO|F#HcsH13u3SOMD`?kX;XYmNy N g->)&"Dz ̧NRoWJEFIQar3K&Vz:*6.0q{zCl֫=N;%52$] 6-X {lj7U0lW{d*} &߬(ԧ$7M7>iFx% r$nVX_4=`kȦFTYHGIc"4#Ϣ8!K'DꌳfπpCߟJSMStJ'ͧS'hm]43)h>LoJ4:\`ԁ:0袩HLC?iB2t7#fmz0R0Б*0>`4y=UikNv vZ#Q^7E*(rZ4PKMa3΋6&nAHFѤ q'hU->}hHx Oٚ.Cɚjd&~mg̙ FH]t𷺙,}F5 PrY0Ʃ[Y0-mۇLzOw 3S::k#Ƴe09ʊBC9!ŝymGYA@QF 53L8}{_&hޅ]K])%Xl!d}e.Z*}JM*'Kͯ .-,\S]oo}ᇟ3[<#GOq޵q/ hᚃ ͵fccenvjt;attG:7OGN&o:r#NtZll<} 7whٷv荟?(O Q.ToWL-Aɇ$Nicfq)G7ՈKC JD:JcysX9h꬯Z;VnL;7anz}z}HӽvC@=s uG+VS8@B?i5dJ-EQZ s)oYsް ZkGIOQ  @_ߎ9 5 1혒ʑB6]+X&HewND #r4y͂\|` ʈNljeqƭ  $v}U}鑃=& &,&Ьק.Ф rs }=%DXZZq(,0:`- 8o%sѷAMqxi~݆&$ LiX;)\OU1̋,`$0svzuJd4z4g4aWSiIR9~"y M~R &a LӑqCYSO z`˱]9Z)|ۢH]7!+<(x[ަ$s~(Ӹ;:4Klނir<=Luy)M̩˿CF΀&Nzİ8z'Ұ(X6Q (*H];\;8Z +-QUw]]esW'?ir7*#9vNhOUTNL[h.o'm85,ևYy7ԃ>[CTC4fz9a' ti͙Lr&y BB!LF7M Qgti~f9i99zfg/IN(O澙!)JpyB"9̫Q 墂\o><_ N(2\gCwBA%ss?f`P+4|-RF,d?B0.0agT4K,k752iԖI$=[((Źf t㟵T<׻*Ma>ig.sA&gNq<; M5} 5(dY]l7gHOv/p0rMDAt,AI 0u=X(4O% o@t\o!EZ b Q8S_M i B6ZRi 0MW0,S Plto MxQ:CY89Yպ0p:M5MR$ )|-\(m؊-?V.%x9zS@jxԶl& .Gd)wnҦ[&zMWqݨQ 1HbZ+Ev )SgnU37;^q\c_t?szWYhLߺ9xHs }Ƣw5&Q@+B D](| vĂIC0Q q9]@{i\o] (Cȑt .r4)L-^gH?_Amdd-p|D߯q(cU'/oϰ;QrS8B?$rh <1kaY^2E(DpP]yS o6Q*A[4:tQIԭSo?bMˉ>-tNhb|89!Giҥ/atHmbA TR''d'k")|ԯҸ[5INDDYcCY ~?ܺȳFD^4yIZ^g`>6AT  _lɇ KrG ~53}A2Eyckf5-ﴢk}ۛm͉*QtJ.d܃6$$I$,pCBX|Q.W481b &a id*#zpZ5Y@d,lRǢ^@;UM{`>a>I|M6eF i`gY}Q֧a'dgMNr$Oϋ3,*eY2F4qJ;@-R_3o ėq9?j]'o4iC NA3uZ%1{xHA߫v0)*Wc!x:19$yE; Ump!fiJ P!H.cFzvڦ`?AVڹ>Meгሆ>IqO-P񤎀PԦe+59tr>BY~$j:5\W8$yD6H ؃U'z;qT}RFIeYލYpޕ$)ֶA@Z,:̀Vem !n :Vy701]|H=N>g({ʨ]SDFS/A5t"Js:X'G`/,h"qkZsp s @ڬUG0 ,xOs>;!(<2&^1!҄S'0)`ẇFuu4$=N l:Z.3o2'*А=H\8s)"v΢-L3xVuxo}&V(IΚf4n5LtI0GdugVKcuU3[7T$$ N?k9sѦLB.qa%\xOs0 4~9M$6BY4%4MtA%Z~B>#*yFyi~΂&[^0ZJb8rCn$Ma v_9f$04 JC^v\,i4aHnW*HPSh2: {RnLr "d<V\R\r^V SwgmvAI}^s8t %0͙=T8IԥIN#+[Ma aRM|Ml[/IQIÎN447 -_@sFVGCFpy 48qYQ.6R<$kI"㎲$"/?gTy?k#!;Htm0pAYqGC+`djOM_ (KZ:#öo| LBS62Uj;O2!t@hkXq V63D3: = eޔQ q~ЙMI.͞NsNע)qBg S(g/~A&` ~ p5iLڑ9AĦ705NY\zA]}HQ,A̚u|x`4BoK/n4d!^ϗ)]~{9UEZςY@4ϖ2/LK(2~BDQ(Li`V{hK_OtRS٨-SQ=XP˅67gqxO]D ,!ϫ]xp)A"&"3K״I$q\, YHHl>Ck@_/t ;nCSft 840d-W +F.]z"H26%3 VUuJ.XA/ cXhOX 6[q-vן2NREtQsȦ_lƎVpDH#:@go%yj4,B݊r-bw0ƥ#/ AL$7S9SN)݅]XIV!x@UeG%ף+Nk<{'Q| m;T:Hf: t9RaK :]0K`,BR=,ǓGSloN16x8&S0Tق(,&8€gh3frL\ܓo4I8a UmڅD̿X11IV1pѤԊ;(0 U5("Vx֊愇΂BRLƝUgED %sI@X=,%vi*tV H̰> > :S[$ف`̠D nC,Hډ珆sLQLN%GM"qTdgF̦[aiԗ vӓ;9YپbJxBO m8R%H\3OnAnQ/ O IB^(NCk؛V*< <$iT) .֕}BDj'FUY7N:uRmC\ Lj *RXA:U_貍(npL]+::(_"{`.4ꆥ˚#DZiH2o8Y Cg}}@smt2MWM+wYl[``~ПcڲA=YAW1Zj!S#u= bUsЇjpZ88gMCs"mu Aso}2 flV z0jKK%A?Bwx>zV@1.2K1G3͉nhZ<A*edRB4У޾qW4nЧjY137 Kz4jM/ˌI25kӴ'X#4T)YvGePJ`9 96)8wGi"aSsd/UYҖ68͡]:0͇-h `_Mӽt@"^U܂i [Ư~#F6PgMkq<I D6[Tж͂gOY))\pA䕦@aSXtvGU 46:&\.큑ļ{ie]QWܛu<]Y>}tJ]$;hK0lODA< 5(S3eN૭U=2Ts{9*t"m,4`b4̭doyee:3:99xn.٤=-7,6hAVVY?eԃAfk:6D}fR>mc 7 c8ٱlzp>. zUljB]O"4*`4aqrM]Rpn]{qYuSIl /h8 z4LhM yR9aN=>s *''P <ӭDy%+N><&1br~9AaV:7C2 .#wS"ёp<,@N-sV2zY^yVWP܄XV嚭Ra2Wb58DasȯpQv@AK[/ SwN QPv:NmM fao3:XU_9RFrî M p/l*'Q0aò{"?mkL9>0?*|ƹI݂hF8ޯhC?߂&Qq sbtyyid 8U4[ a*|&6TX}E:TT"aQnI M Rr[JokWlvS_xSZ' #QE?bzmЛ%ȉ<:F[H =+aLҨKr~&nS'a|L`bƎ7ÓCI !I ${dY(~sH(#EYb'1Em fe<ŕzհ/_M3&mC8=2WwV3E,3lhYP `r<(0ުd`8cU\:>\ƶTYBySUi|U4 H݀h ,Ί G>m;;,j>dvr|5Мz=[l3| 7 b]ff{Ex* tce6'(&YKbuMIBS!$zNsiA[&ßM,D@PɸxQ~w2. \e HA ! `cPcVvH:RG uڍF} zmd2<-]]I$Pc15eM%GHG1p$aŸ[}'c4M``&H G2%Pd։vƝ|B7hҟ^4l=d+-]罐![qP&sj:)FUhb/o&V:Ƅx$vXɅ3UylN39Bj;B[ˀnA `o BQeK Ш͂:c͂;Ѳ ͙7b!ɼt$/=WuyXHVh̺NkOCfvz0jjgfxϧ5}[t@| HLe$z@ISC;|Fߞq%`z&t"\~{6&r&'ݙ:ѰI<)tx3Q8u44/Bv)lmC}jEဒc4rg!_bu_c%Riڷ2O&Nܷ 9 X7-ÒpI#-uN:!u3,--oȚb$zwR2-u^j\qōcy>VF}V%ëk^5t?vaU&JA.[ 1I]Q) =9#H7$r)y31"[xPĒg(\,zb=VB(Hih C[*47<:}_#ca8$rmD%]Wح;o^Zw9!H8"?CdDIQ(WgQ@&I+gKxɚ]ݹW"OխqG4rIqv{5!U &[{Dk;x،DN@>T5\2%ͧ1*ːXዐ  SeAFdd}13ufARoMliٱ(-oeWZ6"NS-Ftq霁44p&0jGMԽC=L5&MS=%;q{@J&i~s>QthXDV;a&BPy7Rt˗1J u$wxA)aUGKh=er_M6M4i~r0'󴓳vΤLvVg48`gHNcȃS{2e{nMI{a ߧ±!QP%0)8) L ^iɦ^4nJcsK |1#g)18Fc W)YH bU 7F,HZJ;u$_0CxR<&m =fxPʮCI0.dGv$uW Fa=Dr0ˤQ<913P==DԜP\X,y5|Znֶ_]C$t{ot~Dq c/ Y4f x&QwiF'؛!c}?8\,KFp3jczᝊIH"IiQ \ ĖV;"uOTոHimWչ)#@$PA~Ste!P*'/][ZNq {j곀& k&4ZiX &#[; YHЍx ~b,m)(yROsӭGC4$dt׼bqKKY7#p[9) r߬ eJXq٭x[XD\":9a7oWXR%#)DFO-~p(AdN  WXRFNOȃ4+INR87BDNĔ9 54hds;^~< ZC^'ucDh<R4,qߥ==d&h$uDD/,MQ}!`ObEu$lhݱ:wd)5kà?u7ά=|@㈫#G1wԖ8U}s[l9( Fh\xϼF5blװ.4~}lh55,8* 4W]y+3nFFIY fOryYH ̀xშxh]/.B6+xוGяnյ6>GV!t\>dYjͧ&-Lkqy,q |]%,Ih8rӋ xrB]R+a 8i$wWXg6vN[%LSQ] `S:?fT6Ӻt~^ Lt[F8ϫ:t'73cCϤp⧞8nZ岸w5\IxK@ *J;j#V{p'> 7sS{JL'6uԑkh $;E;jo1 &hռ"ѪZO{͌tҽ9-lU~B,P[v dsA͎Ii0OC@DtƼqO.oofUDɐ:M k'gW26 VyhugeqQxevChX#NI6R$iOP8n<ՠekǦ[I;IfP+"Yj!DYU9MԳWL@5V秎q@Jc!;"̇m$+Ъ :h ] m(I^=.1˅8b%pw&4=%`ˏOmlX՝1-h$Az*7y۱Lr$jK`q[RQo68:yJxg@i>[oSELhރs +ޤ]!=P跍[V,Cm(ҩd w&/\yMΎ!TW;/D:6L_`Ɗ(Q9&oMS!v(?VfDBJf"KWo ґE0|rD"<;툟h^ y`a) h0,mE2c%<+O <^nLXɓ´Mt7["D<##mK%">:@E?4MrU# |(i)vSlC;=GX7-d@D$K9+(Н@Z`-{ƦNm6}yͦx DwgR?B[(y=gU:%\@=oT/  WKգ~{mՌ"T>t.k[,VJ{p&SɵT@7.mg nOlMΈ7MnVxS:%Ja; 7M"4aq Q߈7Hy6N}'uU'%Kn~ Qu/{[^mHMaIVpeXXf"#j? |L .BarlW8aɺUc0V ima[`?q{Cgѷ^%GxQuqkK7q~$8-|v㊭$Pdij=ąLhD^aKhBA$-6JDB!u| ZuXj'uUx1t4M)ԑxYϧ#M6@K 2O./'X9ϱc12cHJSR6ѰaפW=MƬBC!ŝy%WYL½>X}R,ݧ{ wr'H2W$ܕE,b>E$$l@F TT$RPcB\xNg~}ϽL^*;sv%oVV͝+\ۿo=@cPH&,7#>0:x{<Jc/ZYY[nV[F;kGlظt.l{n_^ݷv{wv쿢Wvv\=VkO~E`jžP>G' B2\y:јųjڊVc =F3Z, J\;9%OOLaZݦLH dDGD|F@sQ˧ PGNhO,(cΏq5.1]7:]thu d"B\D~ui@6v͑JG8O1qn7_|o޾ލK޾E]vn^a4 9̝%07o@*BVmoĉ]?9[- J<[x.<ĸP5C~{uU(k\%k~ 4\yR0! &\s Aӣ۸OwT%J!$`̑6%!$fztFA) }~"5!Qז"^1]a5k(W5;$'*2pnEpN GTCTDHnr/o Q CF0#'}7N}* hU*G4̸a"o_.ѱ;?J&$Mu` dk_V!Dib- 1oPB4D}"MjlD'tPPtњ;۩^(44۝#6+Ix]sU"oo R<Ѭ3-'4ICnܞUbro7U1"K>BgJh>O}*M (\fݠ෵պ#Gm 9Y%햪u uYB.%ĜkBҭB-֭6%,YhιƝ(9A}j 09lv%{77!M(D (^;A~ )iB#A£p.- dŸOa.Ӫp! SؼbkoFZa?8#N.J ""'} &O|$O/VPgbbA-"&%aU,ceҹ4# H6s0`fn`3봔=gbgGy-C5w"BryKCAv"YΤcdLZAdq!=hN¼&` d45\4=Jv  4&F4l:1PS%Oad$0 9Rp/ ;"]H3NUkZ,"3*&D9Gfug΄Zbh+LSEab1,MtG`lcC;VFUД]Ǥ8c6q*QZ"ّ{ Wlo_3F@["P!uv@nM%t${`Q7-ICODiqLzgG"$L.+%qjc:F?MySz@ҹKV9&YSivuFa zPIީ'׷_H/A} %pow|I<2H2 xkSͶ+@:{iIK ?]Ԉg LJ]HiЭ\N6#H) 2k˵ y]~^Fy`AIHb @>"uDRnB<"A-Hi#p8Tr>6Ͳ8qD{7ha1MؾfV.D -۪ [[MYg{vtI[tԃs~MB!U4w#Rg0I.3U A t\:_IBфДǤ_$Fd8M.* 4 Lв5M@s ժSHj,G%~1)SyϷ<6,3%"Ҽֆ)|YngC~,ab0ayXDk.R>->ϻmab=#p֛K:XvN)Hⶤ?e#j@y|n#njΪ! 1(ֹFC@ֹk:uVYgI5b<[g38j.gkILm3p!ULH@|ިm7lH@@t 0AnX9MN7s/U%kronJ%ƤF}>+ Փl Evh>}4F`)8zT G~g>Ntܠkʆ(W043%F7O3x I(s0 @Vu2J=`@i$K6=e:<0'-`'/`l.gG2Y~|ϫ,2>J@.O[o_ԁ-"ЁI(ߣMzӌ&߾P5 qԐ4Y(qJ :Nfmr #짩QDj2yXj+]8?o)sK!UW#S6W㈋Kw[X@-2ۛ+.`M'zlH77[WoCU'Hi94Io˫yXD0ihO: 0'y(#A?kȩ!"j8@J<vkmVC6@|"o#G_+9BOJ(@ʭp62VMțNJD\eC^m [닐RX%,:l `)ZwQT36QbX^(ҤՔ6)M=]CרZ?o XܱU*c׏􉚫@Wj4$%Zw&q7'Mzw֦pt"[ ϔа]y_FzTvnlhmۺoo_4 @f$$~B\ ˽J߇\wD08 X2)4MWH7QA 9QO4ִp>1Rˆӎe$%5jO2ĥrZI3RI`G~rY mn$GwhU۬O)je׻QeǏnHyLPI˝189R7s@d̚Jמml՗/F2- T89*>QWLqoYoxp>x ?GUk`ԤƏKjxАj`kW&^@ŀ[:ѦR DAͩ)hwO[|;qp4ۿ(% Ga'"|z'F?j5CB_~I 'lqzX{B%ڇTm"e ~'! a?MQ'4߷&Q=Ϊ Cyit{_l -*$@jW\.hR)A`"r$#S"EUyL&8D~n p=e΋)lpBy(zc>Zt 8jPz9U=;nzҏB:|lK$4m i>lq47=@yhUZlcvgM4߲h<]<8X(QX|DP63SF eè3gJxX9OB:|}4ge )X[BĚY(梆pCJ%{b0?yPZ->Ls,.zX;H~Qz>Oy@jSZcP&δ{+[eNj2Kɯ!RJ )gqØvt}H]maO$m%-N: NCVDPj$"1 fyXjXn. ϰ*B գrw'Mž6<*fDP|~@Bo(!{gF"4`0iy2 E,WC'+FD~%Ivn%TۭfƳG]E:ǪO B_E0$U< Ûȍ՚<;ʃ~Gf _P8(3[%L8,SucQVi:ַl^4)ܷmYpP3vd2pv3 7\%G9g.O8#g8F9U[/^@oB pd~l,#<_0e;[k68E"-'?Iq\}@|EӢq VDA@B*p8͓+/RX-G8ՎNh\fB>@CdS}RuV@ޘg{fjM R*W"wxRpv*Q *9RSBr0xӟ[5P"A5c-PH8G0C‘sɵIpk9&en.FO#3D9_| .hJӓrcΈ8N{=Ff:=od}TRmp!SLup; 7(_e&s ^@0 d"z L! ָ`rM5خO"țjWmu&e# |}QJ@8j)?͓HDNZ]&lp C =ONn>LqAH S[4^:opn~5$<fJS?ytAS~{aU pF2L7:Xƚ 2oq=op~{IfOX|P_!TcT0n҇,͑ 3yxn߶A岸ncsA Q`SЀg5V0̃&|nWIE4q-Dtaw l3fE[r eߤ5Mجt3WB/2[xjQy-8.!=:&wm»\H3(Vy4A~0\m Tdӿn'Q=R Xbŕa"ܠZXXv!zW 1VeȐr.jjM()׽wm؂=s!ƭ8u+1FuԆ 4aMÁx0"ϕ6\Ν(m۪҈Y'"B<{G*g-*E>x`i̜-סYZDҶL#2NnӪ`i8 lK(h"8_ peÉf` 3u5  T;~JdVb+$tBke)yA {h QNx A(CEVPA0]QW@Kq6mpP6o&"(8 ;| uz V ^$76 L9>~B5)6s6 ٓ ![5$AԏKML#t 'ؕ!QJ DjE&Qap(a;"&94$!=m2)xFp Gz` OoNT5º|ƪA׀: 8U>߶h2KudjzlvyZ䓼/G=ogHnw宬nB{YW9E:jT`zyY+$0LVV9f)͂[a+1TooQ <9JxGIQ3¯Ot N*Ò@_X&1뱒 탪yu"Y6^*y)`> ufMm.I /  ;*C'΋  5`+1nrP@% -6BpDuONϊ&4}  Dx)j\h'"m&I'@sDth;vr#N *S?"R@ Zai%x6')z~p4ѸYj-Ν(>r.I ؾTpa ѳiJ-lӼ@,Bz< !]̔BC)!͝yG}W+Y'o٪TBޖ?c.CIO 6>$ӉW, 0pR2NLsCdA%rħPgz5;&JrJO}Ʌ^XeK;-@v7Y{oO^C=BT:~¯\X\Z4FcXi5ZۉynY߹[8ow;N{mӹtm/k\ . Ck{uo| 1gr4O2 YNb3S<_ kb$?}Ǒ)O2"EJt褲2d%|͖s]GjA"7BX$kZ(1$?3YZ @Ci$|},0yi6mȃQQf<9% GN(QD$D⓾mAzE"!uR)cM0=^{*!LC?ѕ&Da(؇: KNa-yڀ:PL ZhJD۞Bh&4 U/⬥8pFqB=W}t9FP| $jbwT35h8pR5[j䵝C8G$haDE(7ฮ-8^q,*Ddw9n$P4"pg4a-9{sFaUgӰ]Ű'eT+ )# Wy֭+kj94lx i|݄DCf0 ;!B E{pL!"בeC"%xM c)f-:BIϐʦ رԢ`6!WLLW.Xʭ쨵$Wdힲ$H9; Ȇ:Td=Y$Oq Pd?ϔIA%h^zbbQb18B|dNq8jBP% g.{ÚFIRzu1!Wge3 idUi\Y^^e|X^CB AO |kQHt kCZhy= b75dd%eO4}dcdeoØiϊ{DŽfMlЍ˒i)K^_ub[?mV&k*ԸTѲ[n;[TD9Xx~H־QP:2U͘`e*G# 9zن`>i&Ei6l:0ySrhA<(Hc}v|c/Ut{Is͑,趉!`a" a'Ѐ[.R4Dv DtU$Wt&@XC#DaK"ܙѻL|D\v]7\D>bMw]e"g[ rhjQk0|ΘD R4<g.Rk09sߐ?+Osbq,y i  m&bO"M#%=E WPQPYz?Y{OY?@|zY4/:qKyJu.RDp0nsJ"w蔛M܈؃)T"K9z{IaVHgg„9ԡ(4|lTU(nr9څ|d|h kBV(r@=;.PYׅ+UC<%< [5*:Qs_X?4cFQMxg'yԒ7,J$*`ԂSN;,W7[ւsD>'q`LS$nfD#U.`\ ZY"8ᄒ8u2M]Zpѹ  ;=ԳԊ&3-&4Ht'[6E[fBa@:_8LujG#&IgIYC0B~2No D&Yl"!v "}S @4or8J zO.Vӊ4G˺>Ms9+vl$#h4'4=&Z>i—;?@- =4:I5'v 8RGe|AP:cpY{S9_ҹukϗѲ0׆ٴ_~}y(P@ ͒:Y-;܃:.)XLqn((d eC$xNXL81VI1M g%E춈<L4WO͍Nuk†ǍUډ7#ԏMe2岟tg h -$wp 4Zj8¶4Ex L70Ai?ƵHFv:Dp~G$uмqYy.y 닁4&Cd{iO+eUBq8f s"E|N)HL'H3Aq'Nw]lQy^B>jBH50É+]YQm;:oP!\!;G+˶܇؄+*!QεF5XEujٰaP:ym0b̟G.$Y,ˣqN+l_1YHM8:iwƤAf4mR,ہtXk4Khs"v}@G | hnSiB:H?  z,7N_pʿ~[#(86p.H<{Tt G\S,&p8HjwL` z>FK 6y BFH_!n m;MU{ig!>&Zùly%qԪcF4{ki} @yi&{վ(Qa4=bhe]&Hx PmF2)yjj%Dm3|׫4;资>-`ah"/eeH$HgLXp4ekH^׈7#>iYD֮+)^*\qj\Nl!ꝟtp P;sAX~Xo' x2y[ H~@NF=5#t,Rqy[B5q ^&N VN`\98ƧD|/W ~ֆ^za!vU WJC]_ӗHm3ʞn'h=}&lVsáE!r縱4X)=D?фC?1I C*x螼Oqx9d DoZ!5f!#u#vaYӨ[(qΓ p48`BL(TAׂ:r:KMI^gX G|Ku'(W 8q %1$O^j„tp)qL&*8sѠϢpT떅~i!lA3עu4..9ܷI=8"m2k&yҐW3y`,Ӣ^OivŵAD>+Ftp;R15uNJbu%O,YI.l&$*bP*Ueں"{@a֞K.I$׸=-Mb $/cpT\PXZbuf GѮdg bN-&9 3&hǦBul l=_|Xx5ܳ ЭF@RPT/bFEREIt#1ԍƣZNBr:BxÁEi6hvRDakxb[X_0{D$AYOFbqA;b/Ʋjwܺ X>&k/,;us%?cT|8u7w9qҠZhԻHߒBԳFsi8]y񐭏:Od'GKqx&3)N(o`fiR54RcBdRcU>aXBTL#r}BkgIYR_oq+ p<ΐ=]MqĄ"Il&3biZpԺ[8pm[=츳 PݞI^a9gw46,stH_U9*#*1}v%>BZw]4 REUd&HaƥwBKF{'cI|zd<ƣ!`..,ܻdHbW+af3CSoR}A՛ 0sbdb569C4Ph62plpHri!udTi*(Ԫb~7_CИVp &(~^fqV2'"1؋Lf?!h.t@ \ozu( e >)DkmHC_Yi56^.[b^2zI.ԝ&K}2l8vI[xDGh^_6K` n|U'uO' =(B 7r[P*~>QQT,]L;P߽V}R#bV3!pVlO{8s>,<;9X\xJhZ*N;l"dzx1T4aEujdQ?6(WM7z On3FdZƒ^U!Y;jB5+ LEԬJ[LhB2c3ۧCBt$ @:?B'[kKk-b[m,Cb0Uh[xMja[A#U˞u@!@/^pb Y&K˳#OJ w НevRK>j. d @vut DY3p kjQۓx,WklnLNۨ`R@fHՏ۶O*ш ֕uk@v^&H |h(TұS hyċ9uKC[X_l3kaePiX=?AwvtYFn|M,ug&PzmIt(ũ NXR㖫Ѭ8{u2љ_Wj` d:v6Dm(MN-dOLB$A:'jy,g]()Fyb$`@+{y[wil_i%*@iB }jc1xsAW#uD$*mKɼl4+Advil,#|㦊> fn;^$u"]N^nCFDPfʮ,yїARt갞C^iJ]擤Zg 4f!R8RP=vNkoc0A҇u.r&YsyMN@i(O)8 1kPºc°lVH!rt4'4/(;Ëi?ΥiV`Uxևe_qUu\jQG}c液F"5a6a!h#zX9f$ϩ agf  L&CE05WZd,0xbfXӹuP٫Dx>dh.J3lTr'0W'G&Ԭ>A,?=t(M͂ؽI1/k:K/x<ۡ{34l$s{P*;ګ]Kקe=dBJ@'Xi\N .Beh(G4j k9Aŝ&8P.feqNǞ>dH_>{s%"!ݰ8!h}Tg{ ^ħCj$U37fb\n/*m>D7q]8s"i; ()$G>m@D# ;%^f =0xeaJ{ >⧮#8u%g*d!hiI'˄ eyB'm ]H nsٽ54yx1\ԴbDgЮ.[xӋ΃⥱e]Qt.\`xIm^1=һo^U38jT|࢘NWt6#S=Cwkx1P9XD -eiB eR8 riZVE"nBC!͝yeWY_wC: $^:ֳJ,^TnI&ۯ'oyYd2Bb "ChkEB0@  $,If2Z@j`sz{]2Iuen_}}[N6?,7?BDohOz2[\Kٿc:GX'@^GFplfά>Y ֛c^oss_osc}{nowfW]syƵ ]57/5_ܻ?5q"'4)K7B4luV(Jx3[߹KL7L'%)wG2!i"9?fZ ӊa-Js4y@B? 4.I{߁CiBmJtSJt?C7OrW!^@!xU8CT88T[J,oE'5|]qjLn$N9Z$lZ 9˩Rw9jμ#`vsnf֬nol\Ul^M({ލ} }SRݕp"?}dVYnPS|0@h|(Ng€ #$Q Ջ)#Y^nV;Fr; P)A]D}g5<DhlLaA$`pI);PMMGPyukwEG)9CQ@0wpxaI4y$ߞ-Ğ)bQDs"jaݝso#" 2DHN2\OtlsCP)4%߶uh|346L.6R4O4=@o@n(%o't\;Ÿ#Td ITE6:4>&Ь4:]Ewoi!y۩* eB\Nw__6 K=0i8 oykY gĥު ɁJpyvSǧY& ɷi1NޚRrDc9|E00 !;H{]2&|o8 Cn6(/)pG $19r@*a8ɷP%<pp+g1Pᲀ]eKY:A˽i܆ k!҉!X/F)e1"ЙCтC+ṷ,yػ.Z1taXB._so/r.S[Rj6 y:`lwiJx*{ (@+1ZD1)׼ KVvUC) p{0t+UA\ "u zZ6q20]@Dȷ0C)wdHs s@'>A,ץ{6A2!쮕#r}|?eqZfqBߎX~t⚽\K/* )=3y*J"!axDɀ5I ȏA5C$Sxu$#0nn2:,*/-sN>@ggL^YGH|Q~м$k1AI2َ`M,E73yրs$hPqNPp9on9m3"m= ](?\St<+|x:fo @"sn ިɃQM0 $f挥Z59}$ånqe d;_솆K84g:w7K g!-"7P'*E@$_[%N3 ]{\Ɲp2-{QZ5,F*$DA?DhUHučr19D|!pPv0hF  R|:X$(YZuPuuq{P]2o`1?,iwچppzPBz%>,qŞ#usBL{~|- }ř8J;`nӕb?I}Cȧ`k>HI!ɷϖG|&1%.U&|'ɔ |*VH{\U:vLN/7$$,\#ɷj@{4h6фfB.˸@qBF (@ZL3u -SZg)D}:D}d̸vjQm@$֓%Ekm1NRGcw^AQ8"߶t>'QѳQ)zDՍӂH#$ <uQuxZQ @6vM CO65FLؼFȍko'W,L,ҶVyra?nCϺi@F s֜Muk[[8ZB v8kƴ-'S,^}lKa ڮ>!u nƓu5m:6/ Tߌgz#Ghzn`˜;bn.;>h%GpVB+\[:Îa[$߾ZzqT=_ҴCd`_9($2 ͹h`\B5s -@E42=QN.a;PP(^ ~pWcO'4ȉn^< U<$zK.+ʵpN\4M,D m$h#Os~Jx5sJW%U# UU^Et"t|st|>{v-:qD0mθFFlΰȁE۵Z0;@C Q)lqxcf<" R2c4-v" ͔}~]z/cjhB &p pR-zt [ĭEXiK ފ8f.!nXBJ|!1n-"~qR4nU1]@=7ȍ HHhvô':OO4{&]Ń/z4E 4FtүHv"SF1+I"I(a@Ưq|12FV&)fzvj # ^4 )',aYBrkY vrxd#V=]4Y<7yWAYn?ʥH4v˚v"TWXY;½1'Jys\-5ٸRܦB@`D} Yfh1;tyya/:zE?IK!jM~oŊtuP `0E2UM"K4<@8g5ϟ$)JS43xĉ̪hNXDz򿴊B=LSU^1%x2`_SXrVh0ٛ ˣEؾġ1J*,z"oW֯pk%];vX? +  V>hNDQZE!P%lP~66`R['QjYf`\gbDBtxه^e=,_#SE@nM9eˢuPFEcTۻthfNWa8r :#Hf?v@-8]'!Vv-_islɏj­]CYm%!LpQIuŇ{8kp<.@wtUՕq";p{V'3,en-;͕-yLgIc$~Y5ѹo*|^K:%BK\"$9nD0{|$lLՍz= R-IVҵQ <xR e= jF2$Lp "&vU1Ҳ]|䲛vĜNh3H͠~ {s 8&hܸwBuk*r3`~ SQTA5:40I M9ss7I[P~ -EBsZe~m ִm+nə\ 79I8}D|oƵGT8>"5˨^D.;2esG$*po?qa8Qw""3 PE8 FK;J-mȔ̘:I\dg;sgiXb>~4ep-+3Ǭ2PMP>@o_d$2tk1` ޹ Z4B_{y%՗OVO")eSC"fɌx`\>L:yEYe<בoؘlBhNym#.Z2ŻQ'b9MKdG hulxko4 \N;}79u|;EſON"!j?Q!SKtuE2lËpp|1v8EW}G'{V<* W:9UEV^-"i h#21!]Dff!K6|Feeslx$wrg"e~\FO ̡ϛftjLtBB mE73ͥɜ آ}ST9y4Ŷ](Uq@d;Ƿ/CrgJ똓Rz1*)PEIMd)ӻ0`X:It!؃rKzmLFvl2|\b]e 7 N dۈF9 64.HuY@'*f! $o&0qR$wJNǔs;Sb}Ϋlk~V0:BZTO+]hDs0%մPj %wQcS9 s~Z5$+UH kuplu2ENTz19@}Xؤ֏^E"z aZdwo-thNP{OF%m(.KP PwTyB=ED' @9q"ND{/:Dp;Q]!P  3r2bsחu"oeo +diͬlj˒Ck (ˡ10/+徏H e9\ip F3 Uw-N@+C\8ogN9* i~`&`[ +ӄ/nO_%kL-!Y;pOޭ3 Wኆ9=qWYG:6c C#fOh>\ƕhƣq0ȈufD:6E4h3/tedY1.pH uƗ) Q'ϒ Zdy)ЂIԩ|bEN\q9: R`EY|3:x6!N Pl7 y_N3F)iFhR} NJ@=^@⍝gOjWJp,)w꫄o:km^{=NBqV3wdD+a.$DIv($$$NHHq_=U4+3?}_}]}?]\Xx#,[dgl#yBß{h p my`p𲅅Jk{{Y^ZXY9lnln;#7|s鶏tC;GΡΑNp䟻k;vK{mOo{zIozvDo8Cϳًmx|HLJVk- ߣ8yE<Kٛmp"ēD/Ь:A{tBA>k a\жO64 C ,O (ޟ*ϐ VD#Ea, h1mZfDg8SgDl!|{sxP=&`G?=rMG:fs. ^^CW`@46L"3  iBi\D2j(xw.V'NvusΪ+6?$%Hj r"c8Pe2~@o@_T gRJ[DtnjR=`JD,6%-6`ߠmED;n&(0T 3g+D!SeBlֶצtkM+Jw棺ePd%w8ҡ B@ɂzHt|<_К[ l.%gGl+2j;QnPH'#gG=\"5r\9DN &T II+@~09E8'`4)i9<"Q٪1r6Q%so|JtBt w 9[aABr[u"""*ꓳ B#gym׾D8D[F-cDH26gW;9{>s,}P>nCЛl9p CG.)at:iH|Gն]癦qCLB06G*" 0T80< qvu |мʐS$FhlIh~4/Hvud)^R| ҷt?'ǐ/^s !^X DoϱX$~~T~!J5O$݉K9E=ĘNx{!%^YYuyQ" ІXs+fW%gq|@ũCd~)bB^a#w `O2} DbjC{#C<.:I]P ^XHr$=(%)@4NQmAR9rr}_Zuu\/KUhlAPl&LYb84s Nr V0 U0Cb<Ӫmf`ӛ˕6SjPW$tӪXm7hnCS8>$0#Cq_TŞO08%8/0U`؈pN[lW]>>Λ4Uﭸ7Dh>`IphF8#||8҉[=Wfеr8*Fa7fL>,x۟ V7U>N˪6-/T>'zh*B 撩{HԂzH;Wx-pn:'FsWj+"TZC,b(%*Y--R-Fp6iIL4\!DO h͡|^NDOJ`xW5臍hlU'{ Gl PD= >Ne lhb댳#d\!%gnhkl17'Y;洕LuJW[)A=`)=~ ך2)O1m:aڟ?OFD9Azi6LJCH*ovE%l&C "g/SPHg⡨ U &Ӹ1b8o+4WZHvK(lwvV3 D6Bׂ2+8QURNYRaF ,*C8r= j")e1Df,6xm$%NW]Mΰ!#Ff&"(}*\1k2+z[t&RZci@\pT"gOҠ$jѼ3hBU0q:g/TGA':~bCcA>c 3ol) B!v Mv*գި^6pH7JHzm!OG=6"" 49{ Ffyc?>o gl"Mzu ki_lЛ@u-@Tsu A:e:}-Jxe"ɧG 5O.EV8g?HB:tKlpiJ/oډ-a[pQߠ}xƔ@D֪(~*_"gߴA b!?U-Pɪ yMJD8L {OɁ7"t!Wu {@Ewpsգ__0O#N>,F4֧ Kz-u}q 7c'!@i3"D3cQƩt}Bh@2d%FBJÎ0nȁXyL4p޸ j3MH}ִ^T 9U?U*l4TYZl:vj/iץHR,YXv60W}֩U0 hC+@'NM\+l}傀]|9r뀞h*4..]64X gUѷ 8<'L!goaťNE"Zuqؠ3 t V@Ҥ1@B3’!$WOTO~ /1]d-q-r翬zmvX[)i4nhظ&_P \B 37͊N"9Xqm15ΈxKF4+$Mw:eċ I(h֦kICcl7ER؅A>#- 0 $,mo"^Ya !7aq\4@Zt])b* }q\#wsV}oĜeh4b!&8,BsV!xIyYW|:BM᎞L]x!{? ,V]iKi3{OfgMe "/_^גG=)kzQ =Ŧ"CQ]*\j6~EA*CAs'2g&bnNjA,O_ؽHYe0-fL# fN)dCK/ D{1F l0~7y>9OmPt8*5pLiۗ M\2Cw\(k%zCRSx6hsoC/k~H[nq|V}]cΥ8tez@Uϛxn?L>o<.Ш:wA r}erEc_*DamA`IZFxZ.3PL CCx~ƴ<}h!Kg褺Pnp|C԰:/Ȉ}ԸHucS)9;wy G#'~_2@JiW90[¾0K`>n\S  @88J 0ǍM;)4*nQq4˥ָtzكh倦@'P4m8eYrd6 @#Ձ`7A^"ÁE\׏f\0 Rԃ) w*/mA;|uKyGԻ6Ź"Ŭ(2`zd7i-9`K;nq: }ǦkyUWI&.SiĆ8Uq pìXaE݆_YL]XGLn+莴OY-\_@ i1ŠG: ׶ )f W%Z.F&8ݺħ 1L0*ڮ TUpz+DA88yQvE/>Aaۙ9(.c z H= ^x,b-WFmNxϡ /"'~ L9(ٛmb_ urґ-6 i~ em]؅T=H~KòQ36N S e+iQa .-OaAꬢogl ,#El?Ht;U}fDHO,;[ C I]'~dsu:%)Kk=gS+u:ل!'!? b%&u!e=>wo6ذx<ʄTa]*=Br*o΍f̜ڋR!8ހByndT%\D?dM@Qs JD8F[g,}vVn0u(:օe@=ͦONtbZ#gKĪepJU^J)E#ʷ!^ÚfU ÚV[+i\>q7I.H♞Hq& v0Wugț/U@n!sHd٫4ao]l7Q⯮i=b GwcPM!}Yq6Ŗӳ|Fa>)NBtI+q:8 {*uu/mfzwdt*E|R@d89-5 mx"i<ăƁR ѧo%rcEj^r %"!਽$kևH@,ӕ 8`j{uQ}FX;6p~lkMF|&T` `]KMZ0%O&BYB + a4L[07"!ۚa%PlA*q؃6q[g38^R:]Gܜ[ٜ58_Afr^*C]}x`d;mN\gySkH.V..3.9 F84`q P#8Wá|M)dCV+\?7NM谞R-F:l8uUVOH%wѸ-\_1p"iy@xc;^d?e㊊}6F?v ]!~l0ţi"=k lҌO'AmPj9Wr ӫM}kNjJ!e{mmgѩ;*.#=p%lWgު+xc3g9AUӂ!ͪ ՠ'q$QaC>gL+`،&Nơ5UiMUq6>1]gY .ߐF vi.)Q7PUs*ҶfɎc 0>[ոuM)3x Q)*]Y%PiqЫَXvN-#v4KNYҁ7YREפI&c.=&AE g) sp%YW`B̕^HLTnEG^'o L T!":6{Kԏiۉ+#+ҿP 9ra:y'JqxOYQ[u4߷3r|W&&/$fVAk|+9v;\K(5^Ż9UV/<#NHk<ѹKݿ$vv*xϸ~- ܖ_5n6vb3dlt괶p_1nk||u]xw=(zM nh3!Yxꕽǿ^emv7@ܮ1 FS|B>/\r@h(:XvHRMG>!!yYX}Ƀ4BCL"͝{dWYggc8JUJw=6;ݻ=Al A1@0DP * a.!hi)JYs=y޳tnmOڪ|w;'_?/_ݳtdkdM-퇯8/ſc;8"?A d {jfnl֓fR\Y_Y_ow:/CIHm&uw;N ?whٸgٹ۽7e`~B.v eLU8{z0D͈NiD{ǬF1)Qͽ(QHiMAh)ϖg D (fHhݧ 1^&p*<59:G.-{`|z$!t;ɡKng0ΡIpP!|eteF.q%0/ p!4lN%ie}b`NJT/8}p#H*4u8!ҷŁD[ 3e4XL8cOr syd!?%N4"* wDhM8ڟ%‘@qz}uqU A$ YDWZf2x>򳑳OVRN' a qeg.')ZҪknn6wZvmZkOQ/nPֻ*"\u{x6JO $ad60/I@p3I2 4(1õ$d60Z̃O-גA B2) #hjt(5o)LCSVu{MU-2@O4KA $pq4<3Ed<;Uy Q(p' DmB>6DĬZT}NCh^!EMhpj$Eqs>:raJ#Z fLIIj6KQʃ$@.kyzFZZeOuc Ҙj[qn uA u|f}@,@&,%1շ[bƴ.b Aдis_U`기.)h&06ԝhnN<}t^.x MK[x&)+WN7v0`vNͭq C/w!*ǓeXBԟ5-/{K=SzѪſcx(${H@c#4ij-.7/>5{>l5Vs{Y[oLgI65Gƃ=KlH&D# zت'Pce}@@zt;YUؗ\p9<ҭƁ|BR$d-)镤z#]9rOdS1婐@  xK?ƹH~s * +h(fo!v\N ! _.έV{ŗj4ښ+4= ԃ|Қ~udH _|ƍ;m` ÅP$Y}>d~w1vẨtuS3b8ϙ[Ӝ"4!wNSu[m aV2x߱J m>K8pҭ3Z&=*D]a(>1@"k.TD$}iξE,fkbJ"wY#{so鎥,^WiPܩ4Vlwf%;W(nKO |'wUA TGZ7vz-Z˝xaП4[5t³.r&0d Rˆ3Qz[<*F-P&ru&#qZP 68 8}!'-G4ipB%`Mvdz$zf@8%.Umdmˆ('= cdQ@J(`.zfŴ@ĂrH4@:A =&|O,B7Igku˙E J{~d"kߴA!+,ɘq6uWn| Yy I'Y=O>+_;JEe7,]h_Pv\Ym$NݕF1a߿XEP9^]l*ocN?8wH:QTlaķe8/ƂBn)N$g4(4-F&MVoB@%.U,`pw%Tj(5@"8O/\: )5ZGV2NȚG]Ȫ8CBpju:; B5<t\ W/68[e}RU tlLe^b󝤉Jv̆ȟaҨZ*QBD 5ڹjBm,ICWR${YUz0JW8H5=]]CJω &ٴI"`wyyj@.~6W9EcAhh/F-8&kAMZ s =`Vd?J~ J#<2h3ۍm.1iڧ<& :9${荞 $lJ `(솄YݧS!=hݕIaxڬ[w„e=R4pW*@oT+LpvmIֳ<ɚ]vJ.1xp9њN4q\ & ,"A5Tdj_I8Tw2o@*@btGNۇh Uc26U*=CtɊʪBɩj3OlEB<+9jGjUưeGd뭈0 6 g5\$0# gmZg0WA/NBf*zY{ I /[os'kJrިq.wK X /Lsgn(ke+~FCo"Ҭ+i3 &e!t[Y8e$kMXH4.W6ZUaSj**mGm&*h7 4ӍIJ2MM-aN"˄O632I { ޕi֯7Y~s>M o/èc]xAJhz3V9eE`JTgryCNʟ/ZU`+!mhQVqfVP:'𜹟])S>AgrHiQwDR6kUw|E=DOys%pbz2yHiL ׺y5'!yFe52hr倰V>aG!yTK]&2D[+0b" jΊ͋ 1͍Hfл}W-WC)d6,XizǓ0{ f^i1%s4w*՘&4ki0kefH&60'mP>vc_U@sm4 %8&o.K`P㎅Me˕]{\0_`aU6 d(ݔKuGNY e0+ }ržq)¨žHbʦ`zK7 )CpU0A`^^Kax\󦹺$4.Ki-N6g5潥SnT`Y8k(;pUQ"?PŌ""."N}u EDC6(Ύ3lEx/U;5ݣ҈|Bd=LFq+S`_ <츣IwL@8HzZ<8-.huqޔz M L6&DYi45Pm& I"&r }ի_舑 q  0Vn! jǁA֮¡d G!BA;K%s!#**^j΢DYcB,PRzÊEͣx&%đoen+ޔCtΦXк{ Pƾ'C\y>Nb˶Ĭ7"(@ `O_[pq ziY y'`\otJ#y!H ^gS@Kqҩ ;s?=VӹJL4Ҽ[}4?B~tD쑊ȧD%k,MDړWB$VZXÞP,hAm;{rڕ"2ympJ$0ca4RB&%L`pMU'#whGyh2P6θ `Gt)q4 ʄg~'l4Rkӱώ5o̼.6vh2\F|9Ƴ&Сq$D_x  Ecu 5.0LBs 0ЂV@FwR h β((. RN:pufE=U8S4H!`ʦ%=. ty6|hŢ2%h.ZWd_b Ii"%8hQvH>wKٹW>'c蝪&gJ'jjcpG6$1Me$2k31$4/+[9l+iTj19x ,r,D:NVM/#QӪLs"6Y3}cj8 ^`f^zMׁQ_>;8Sw'-0AON@&QFn&Aˣ U d6&o: VBճ:`Ӹ"ש7Kʘ)/?VG*:G)^͙Kc|:=$S ڐ!vMGϰgg m`t"YȽ`eVөsA%Sc cUi~3.h\@V_kdʧ$MAq&]b1N“BvAC N`='bh7QR_I4тS{GJ Ʀ D/Mv Yņ(RfGC>9\ۇKjHѰ}3M464L3{{4܅{@QV,&y4Gӳ2&5᰷!Q)@\6i%Ȅ#eI"0=Y̆y]$"k+]g~`B]MfmLVJ]|UG7,{vGknp$GAOYTt`]O[N _]=G<(̥W&k2M<Ć bVWoe{'3EBʪwa8SU*'N&ӯ;*Fi:ͺSBI厓Y &zI^Hn )!̫Ml%H{(2 ZE(xX$DDtp? ߧea JnQ0~SQVLwz'Y۱@B^zE GY G#uG\iI6Hbxx69]qBsn2v#k﵁rg.bISg͙jEڷ-O0/fy <~K_ TY>3Gѐ<ȢWmF3aD5Qf9&Q^ 6lѰ (.s}мl+b;>4ەimgQh?ͲX߁0hˁ.PJLL*`}ȉZU.dc!Nĵ6%Y4AǚDT=}4Q&#)8C" A[I7+ҏN7G@]HtY8!kU'tn4b-h6QJ3=}th~ I~}(Hs B􍮶2UgڕRs2z=F=;Z)'}jb`l0qMF>`t0NI71ZY4S 1ֱa@T$q&IEKkB JGy* cd"jMs&bmb0e&nBDb_u`#&%"}(:VJAH<*(I}6VZ2tayx>`z*FOE<ԫ5;|`OLDcUڼ諄cVѷc"$W8(dDM*-q~ @(Eco<}(ʄ}ɯ:WssEO'P|z %{:e1HBC!͝{eGYΆ EeA Vfu2r<ǹn&HB݄}~a4TABIf`J_Hi>9۽ʤқJͯ볍`Ѹ.5m@zv>G=_(]y; v`++/&n\6tuLWNik}:ZNG>vv`Hh99tt:n{v{sݸs܏uƷpD1Ѿưz6gmBf,9 %ܒCY(wQBp^Ź*ùwR|6! I?ɅjN7Ҁ Sg8Ppމ~D5- yJ'ST0E{?>{JL!7+6(0( .'i!GHPD Sퟱ|}Њ%dY[oַ$>6s_Ѹ'0CI]vZGiLGۘjW=|hn:íA=(=3`DAyCIҸ|?OӬԢ|4hi {H1D4HL@뵑2GfJD 6d @Htm72 nm+'WVV+[{F=L2 L>nbHQњbCEPe:@Ӧ@)st>O;1r)M9? AmkmHJ~0 YlDv֒ aBu+4a9/l}a!w!&D9 CzCم\W!)9t{8Y~ g+$t]iྱ"WHD`ԃPꪈώ@a"mRFSv7U ̻gCc!(Ί!MdDRՑ )QG6Cu3 56H1^!4-Uyns>{.gU$yc,hŹ#@XTw†ⳇmH^'áFBj}& JVIJf(D/1Jsޢz&~asf{4هKߡ*BP0bP@!+ĀٟjCp ɧyPH.27g/2@9/V2zp YyYbpG8C#\ > 3ΎYn0.Aa$&J疰5~(/!Nq84%q1NDA(MY#ˆXĢsCd!8(uH݄Ϯ P؆ug8Y@0{jng'"!,F4g/< oy-8Ճ"I@9$7;l( ƥC¶ygoI`\x/t>߂P4 yI͊!\D-hH:+YN3:ZwE?JG8(Yނ`%URu.n  =@ج%a&Nvs@b׈DY0R ןDe"ڪ//xB&qkM?G)Tt.9q^bFb0"QY/E;}2c6^2MG@J)aQtoJyh+ƀvo>m52G(]6+Q@R 7`B%Wh&8s˅ *i)V`<>N,[$ |<4] R_ȆOG" QPBDĆ0g GHЦq'edItZ1֟Yհ$!Ń"RؘeB%: 쯌=@ 0Gn*_I58Mq}QG7;{Ph}-e66]"S[u+.Y8> s@Je3۔,iS砐$݅9%ԕlݡDL#].֯8)EIVa"%G)XuhCV2My! u΂^l0%B{ U6St:w+>{ M,-R' vg0_#8<ÃZtՁ ӒOnwZ]A`DJ<8EGH,:Zs DmX2mSYU1/Ʀ.΄Uh©q)C4RmNh[}]P@|kX{*S`4.6WEPXѕ/+ؾTb/[iy>R _\M6!p-9H&z ݭ*C*!$$pVd^Po٧,/nOY>[u("b&|i -D>]zĖzC::7=$x}q@&^t̤`ü&P`@tlqc<(80тqNs8rug}3]&70kmqii@Bģf l,Qy4Z|FAݬRQXw3{;i d smll d]eSw4r6Ex,o0XDך\Il^VreK*ˋ=~ܠ)C2M nMKHriMAX)bajVWKOf|v8BN h^oA*٪Mwʥ%r:G1ue\.|6 P`4o&$n3>fؼk[WYveXн gB*9"Wh0Y r@rKP|-^$) <IHSHqj&~[~FC5 s)LPaXjIbQIHfY"(X '3bטVk|E`ܟ)Q=d+NnZ]iRM',Ywu ZY?Qa2}hڍղ*\ 05r7vdQވ>X%bwDYOo5C9_C1s^&JĢѵ?@Sn>aӒAj$~^k*Mꨔq6qm>]cĕh7hȆ;{s*i^ `[K6c&}AqmUuQkh᳏/3-DԮP]l@-0^9=ehVk{mrOݕ^2n}P=Z{b׆lgW< 9I4)j}=۟9p?@lQG|6U*:-oE93.)A/F i"sqI&QG)H hX.U @sSv|_i7?Fh,`6Ai"g]+xM*l'6WYjGFH{ch%]vhO!YfT\鴬bьJ}-Åoc^ꎊ*ÅxƣSY׆&qCu?eV~ @cR?R|;7Eѩ:&n8c.#$yGDl3k5k rQɘ/6靭y"PHEH2Zq׃=#rox;-\S4Rϓ1` ҇5`7ym i ~$IaZ–Ry5C6fHmm s3*+2dtJ(5}ܚƉ=m@hÄl*>Bnto}F$A2[wOu}i/e_ υ3g>u=VmS͞@iM&7ӽn )4!X8_)ee ph¯,[hB`ԭ:g}iTw}Hz_qfL|0\ qu7Wx9Ft|cވr9 fՙW3Wm6|z*'@UuΆO@P>o#a'M LsI'q__!fQ*žNSi^$@=&%cxcFv<ؖx n8^Qܑ'lDcK%^ɇ)UR!I/-{*|tSB}aM{تՌ\/}k~:W8B~G YsEࠍbn(>m|O>z hdנZ#2~( +15(J*9 j|6@ C7hxV[AZiXH7p4ZK mpBit.ZO`E"Wl˃PL -:nE#x4WAA[N&Tc45XIk-e: mb$ÙV[PVFԄSSx۲ͺ`yNa<^ Nٛpׁ)Nk8t}GҸ%N>dˮ  `vʇr{9jvZ7k<5>l:A!4<3Mޥ}$>k;HЗt}(Jʔ;; (  Q9RO'3A+P &C]ts0’ØJ.m4zP⋫}co& (S8y鶘P-*1M0W)  g!N>Б #`@>CZqd@#%yQm҉)VzUNN"n |q;#i/:RVFuӕF T=UeTz:G~\sò( ,^?Q@EdLvQzR0ݬiqNG4*7 Pi6͊ C<*MqDhuP!Sp+H![A;U%*ڠh]sMOn=܂ hz&yC҄# ѽ Sq>ef[  &%I6P,G3|ji^"JBYx Rӽ,p|O= =pZ&vI818\Xk~xs0o$i+mpMf#kZ@6KL430lbkr϶Tm#M@UHf/XmhA$YIl@E g)d0Wh#VI]2TDU Lb l[w2C"iڔڬ ?K$X?(jB*;"~%ü7r*aKٍ68aH_7@R᫗mFx#nT}zK9oCk.ۼibU8k.q6*)e Q(fz/Y's@Н568I$p`mSm.|vذ݅y*M#DfACމh1@m <)d@RkZ*~dl4Hä4ތq46獣nb᳏C .87#δk5*-Lgȵ0o;_ADUlU |hPpТޫh_i|iVkQB8̊nRAr>a!9VϾj<\ ێm{BROu5 nnMK8]"ki¹U 4,&86NqU!B}s{VwUK\ueueﵒcפGv&;sKMf0@Å49'<[>r5a \@adYg4f4Ky)"0C:!!9{W]$$j[L@' 'Qr@ 2R " wl@g{ 96Os`A`cBcx-rp] `Po8h?ɄrresuemmJouu}eusXFc3A23ͤtzEŠ?@LJ iEBXXںzϹdwt⭃m{qo{$i@~;Uu 4t%6@XQ17j73 gW*í gG@<pr8 PחcL]bq wt+{A~ed(ѨmB6 :Úddw[ဢ<"g0%.z# fA]SA4"ŒN` ]ˈ(}n#zmCcɭx|:T1G5|Vƚ9@ea'Ԥ囵$g[5)N$k479ԟcub!v gR)LՄtX*TZJ0;m;f<lJw  q༱vÕ'XQq'<t%0|cr OrAI@'fw=$|ӸTZCVp&x8i.*9Glݏ[t#لP8*-B՟[V.^N>Q)zYdlR)ɃZuП!gS,!*57tQ{gjvj%ڽo`1d8yLHPRub򶭪"t3Z],M2tVCz7/G8{CNvn$ +jߣC!B>u _qDLaݼ _q!5Cq| ל@^^r-ll+Ppn87%=6@!P*~Ȁ[@}YBg*N[!/cpK UwvVʣ`kV>|ځ{ (Dp e2Zo,< v@bAdg͙qsJYEF'VD|Dž:КS+nNV-d0@мvPdNaB"@wCZ0z hIh!PfElnFra V- { iCM/V>^Uzā/!G;VU _Qs0'j[WUųaU((E+7D(bv=wkłc)@'⵽)#j#mOn˱|4(ZuQꄚ."nD}v1 kJ7BZ3/;mMLDfSxֈ^3,mDB LPکU~dϝPq+^U19܈br½$0g_SŸAگb2sJZh 'VBkɬ,{E׹:&Dtm͚%i ToH. =ڣPR{ w7 &7Y@!/QVn^_P U%g#فLJp6[q7*C$׻ (i]( JGkOGqSlGR,٩Ӥ1.i;a#Bz`iݞ\<ESY<κm[7iަLDV_b1:C*ܱڎ-T}oYg"Z3j\c&d=^l8g* hc<&o3zi>{Oq1'̭oh)gzi%Q/P~l89F>;Z$% }6@gRbX-l ܼ|9B*ݗIXO#gWbfMJš^"=¹}=h)q7/:$2:AAm{ /5󰁎_9vyp6v͎!kDI|^XX2s[$VLby8wPIz!\]bE$wa iQ3]*&*\%4X:>o`F+PCӬ6|(g)y9HJ'yd>>dw\|Nq6 |O E'[҆X5byK #qhBKVK@}-<B.XiE!kj'ΦKPw LPQ֚p ZCl-2תȠ$0,;ā?ٙ9S=fIdKڭ${k_|%yl_xT>ṑ"iLH!yQ*eS(ߔC<_l"Q_ftaRy,!;h2 SJ{&=贴*"e "i"$Q:P#*V #;x,\^C,y&빅=fՐ984d6ѐTDsVF4hG3͔Wui@M%cV@ jӜhõx5& n_<Ͷ_ك?)pJ@~r_d>l3KIDQ0w=*(PZy zdI'7WV*& {{lsq"š_[`ylY=B2Cv8v 870e9;Q;ņBbP FH&B_NUٯnNs|5ìRK"ߜb裞yS:EkõNjؗ(,G6-l¦' ౽bMrga g IՄ=)WH4QJ8j=wEZ]"|]ZDDRRR94[L^2U|.mw*^*. ފ묊nƗ?q:MqXJӀm6U(n!h([(뉪4+$b4.D$ -2\L8Ӹ"etK-Lȓ|f]q;LLͻҽp>JCn$lbt1 })I!UeF?! 妸W\>q>O6M#qzBW-Pwt)hlzT8Nop<7*:_ &U7%~libU9\Mҩ~[/h㚄f4rCfm+ X[0qbm^Up8YNi@o1=j~#w R5 I>'N>}UXgIZԮ]\Ρ`ӻMir4H)<k4?2g{2Q@%d6$4]HRC_^fSLiդ!(׺5b(ϊx#oy𥂓8n٢`SД'{D@m7DV}]n5eY)sq5h^录ֲH `8Z:L|GsWvWF;ޣl#q-F0$8F# sC݀^:eX P( \RWՂ#WMnxDe? N o *`O+9?69 N<tf+pOj HSCs5Q> YOxZGv2ѾP,`C'fK eԸ UHߴxu6MfeKZ#+ו^oķl I155JmnJt4>o L?0n^w0Y켛MdW-2sJ)FYwnlӤD蕵AF$5fANAs{ $'_]W&%8N[>,|^$ᾍdzKX@~b9wpɽIB9tV3 $wj60E%/υ(QD2êDOjs-媑O'4$BWZ5dѫpSB/OI:딤yI.QS>WUi™a?++ u:v PI1鄽 en1kʓdy Ήh&d+b%iV-QS3)8be|p;[3X,{Tv tU@VߓV1Ӎ0׸'BЍSc0E ՝hX?CrEI4d© l^nЛً,IF ̙.r+64HBʸx7[Yw 8E8QT>X} q Uǡ`|SWOwШ`#⨽SN(ك~P.Vzgmp|[i!So ހR0C &9/-{^v}qHfiřrXa_k^gfxp?o-ٯ g@,z+Z,6-bp`jb|M"0KbsŔˇ=yfB$d Orf@YJQ>>x1R߰MgCrՑ?K`Hq+^Ϥ$[ȮW;N.˿IT5RպW)R9y\C\ 9ƿG&45EP;Zf@Kn@YxqαDg7ȴ&?킉^.DnA[܌ɴJ[Q+'u] _Q;a1݄ TɈ^>r`!2C[R`LA֏#3Φ ,{ò\2eR4">}9yo4̎:n(tڞMX}vX, Fj^NI_*iypgJ L1#y& Rufq)I.7-wAdL v'$b8վϛ}i崼3x5 K-mP2-;X e  UslGmhb`fPҊ$5ˬC: JfVY A1t{6(ȍh-D_&-}1Ǒa88eIHn4.hcT| y P۵) c4f!ڪy gfU𼠄d!IИ(ѳB誥Ū%u9Y:ѸHrSy*ʥ#շ0ՓwT__l6: i^˦&|^{,Oqislh6wa?!zUm@`X2UNi58-d8kxMA+ hSЗcy9֗CjZ *ʪ0m^0o]w6##XERsa3/̚ye9aZ,`&42ƖR5uRxP&jĒ]=9. L4/$g}41:ކ#|| #k#oEMoņHY @)њԪntU( dIuV7;ޭ;ԁ|YQޅdz9Y`!O-B&́_'V8 9[!V0# ٣+yd-]5RR b|bpV8ʢ4ZqW35_BC!͝keWU4ӗ.tsZُ"9ޙydf$ CH (` e(Idod ,(`s).m4#T؆~ g4n/_z_O~now_ꤷC5N^niN(<2 Nid\pr/QΏ΋Q9( i6jеAQKs DvGU!zΕX*qUFg!NۼR'z2ieX 9KW쮪8ppqZΎ D %:z:SJΠ<0u\:Z'P+.P~t H\+&@d9 bV]M (Nj"LUD/FMDDEBD\G"|eX'Ѽ<މU$8Fi ݑ2k]]NR{g,-7ΚشFPOdlhHM3([<1 3 'fjkfrnqB\6r";d{As6%8%pBYG(NBpV,d;PԃXVQ`B'3cVrd{ H T\+h L}eZZi%ڛAWP'1"{ où8gK7m+@&95=.#%ˈCdoPZF de}=|iqb0Ei#h\sjh ڌx}sKjxrI/!ٸj֥DSFZp&E4%n8mG$y8D9(ѬYfG+>v·fPr\Id\F) 787ݥxꠃV1]Gd_  9^/lfw Dv_eX bh BjXj{쥥ӛ*@VŞ呓N } AܖU:9_~9ժTZ `dl҆SD6 B^(}Q=o? \༅Ȟo[@ g,´̺4@$'vg |3D^hVК+C\R; I"IDNKAU3p6P(w#jj ~}k!;Bdw)pގl~Gd-h'G {8+.QOIVdIV ;Q%i5 Rf~hJm~ .Qk_V$(G"ihusaBK>ws&YE[]ܗn׹D\KtV:L|}$":iQXID)ŨՃJ1K%bAW؆$*;nl5^m (M~h,d%G-LOaP*NܕX(7|DQa&WBD8ͅfH 4La0i4{d)L@^aS/֮MUxSD6$J,0SxJva*ŭ+v'DuaOֱO4N-]חRRrB4t8e} Sh:Qyũ8hOuu簱F4U -b~^vzD߇ wx(0#'YZ.9xەpn! N!#o8B8ϻ$hǟ{!'jD͚X@ΖhEDv V! 3Rz4`%+3WA}g+ QmDv '3Y0WTr8lhA@Nb8qkPQ*[ɽ%[ePECǵȴ|GdAJ"I\d[y{\n24{|NS'g4+e*WQb)O(ǟ-QF Lw؆ޤ^@<6KT.ea<^zfoAHO֟XKEB{s޾kˈd猣 rGd*zq8L̊t!G ohh9kHQK&}uJ&E,קɎ:Y1-gBV׽2&5i QKRq#R8Uܽ0%v˅h+z}TO^'4W\X=5|+:l[Hk$$WH k_ P{I;zXh:Dv PH~.;M&"[ %f͑zP*D\iCS9:P+Yj;Q5; 4ׯL:ê)NoQG>D%TN @SxUC )<4Y];'Zr8bwJta dw#&mna!#`(kI߈xp$y+!<7qÆ28 60TQ GZBcV5d5_9ccs@&=:F RUDo@!c'sZaV,YXbg#m/'_4tx J _ ws6$փ?N+? Y`':qs|E$0'gT16._jT+5y|NQa#6AGYKF'!. N)ju+o0#j̀(dLz#_;'77@ZyNB@*D0/jڜ^ſ*|^9agwJbG z MEs>R4kΠ?(wnt3CI!Kpqfҡgq[spOofd֥ղ;'xg7X!i2Zڹ$t`. 6/)p-D3桅geT'JpSSy1Gd! "oZ璩N0f%|fiw;" U$p86ގ;5PEсx^QhQAJ vS/蛀E~iw2! J@s#y!Qnv5dIhÊQ8S?fO*߿$QRlB6&aWH w}./Z0 $H#Z^j.9Tl;ҫߦet u6m :cS=eTfsOOeb9ΊSeD}TϦV?终bW/u^ņ+fٍc0-<< x)RjýQ& :6@H=aqeP>:00gy ^mŤiA(iI=SvWLZ "{ K# H-x2]=_[h#!*@✇F{m)a =2b[sQ>p' a/ǡK(`e@C;jm"$s^BeDE dc6'qc#͕i1!0"0Rs`/FZJ oV&ꆠϨ6(Uh+Rk+F@)|i1 iFTfu9ͮ~vl!ڦǭ;Wk ùHo\8nT_h1AXVΜvQjnq {\-N1sڡ!gC~6Nv)CE+/鈎'q.+ͥEzYbg%=B?LHOB)oټn@CϹzKg5_; HOsROT :P9̿_`R{- LX`a4fHEE;u+z "=+y☝9=:ˆ&PPƣ's~kb4G|j8V]Zaw`<˧Er(͙xƭuWЃS{" QIkhºfmte4cǔcbgG3!De܍"X't1zc+gBBXճgimmU{04:lUM/ [wdsS( {D%RmI$$o>7pEaJGM5q[/?^L&NΪ5$^$60 KBMbQ0)UAUs;>@dAE̅ٵݫgZ?+?&+~a8@s9 Z8`5 8Q[^KB9@YG/כ-"{ M>bqJn2DoLbCU/dFI蜒<^<eS;KqNĹnX>FүW!Ndp\!t%%XK{mũaI-Y^?;)*ʍvfvmp'U#BmzUB(O3}82[4'WYѨm1co.8!$Wx!09‘IAZO\ZH&jTP6 ZL /E>CO]@m@$075 <{Zzq0`%TσľϪ4?@hPV8Q?՝0#:W"aT6&s+ ðanBH d4AO}?J~wDv (>|>Jd;6@Xv a@.0;Rw" 8ފG9R鳧.h x^JeC6zMz<-³*'K⭐R>? s*_h$L'u'8/ݵRM(Clm'mm/*oN7gWQQEI1D7a*KǼ;23%QzYrͻ/ʲģ=g unkܫщ& rxx h?gE CjОI{A/` +C-)[G h~`͖$'0=.vfNCDNĽ3-D76^ϲKVC][U>w++"\]I8G2+%AJ +]A2 x(ŏ7S9n =:3O>iS5i|\Vo_8d#6+T3ZZO1 h&¡J[Dv Oɦx>75[TMivhεV4p , v6 pt91iDߊG@`H#yU IJd5i0)c*_,IKXhƔFI>fU'\9p&|~稗V$x߱hɎ ]Q?qcIΏ.m4VoD!dύUzb$8 Dʥ(,Ǝ9͚{ﺇ GWW.H3=50<^]'Hq`2dUQ)ܧ'ZZ- DGfZ>?Ct*פ`n16Eui^d3lz9;v-g7v =yftQXntbXFwբ؀MނsZB+O&kG+D P0t-sŞ{svpeڹI;qkl*vx(n?](և.vaR f Z^ZwB!(/: ~4AV$^֔+!`ɵ 5̅2"8T} e؉Y_+Sx"s!{u8A Sflb?c/YzJZ6(r`_04KZ-(=VE!& {[J-xS(EvH M>NZD߾8P?}g \q_ro*ȳ 1;Jf 6vugڠU|_-J\jdbs-QƞP12!3)݉q37z$DdD> ˜X=#StrNQkNC@&o!dVé7XHpA*30G[(b,~NC_qI7vHT"R|UK| }鬹YZ 7khq8 Cǀ!A.UM1'XBA1?gqS$L16$(KP9%YqlXH]>D]f 62Sf[]fi?iu [Ol|?`M\,OfuvFr&US4A-Hg+=e\ji+ h3few%\4ɟ]Nd i!{f֫Py@o{Xdg3_/pHn| U {'W6@'"d7lp086IzdZptYD׵\: kD3Úi%՟h4wЌ&"F:1Ӳs66^Jzq`J@9i6[kN|:8R-r&nǒr{ }9@x_mAV|S%)9es Av))2iP'er+}DGMƵhT;8/"ko7šaBߘk29GB @xIϔ) 9&9zkՙCqU%ʥ 'XKvt)`m{ǬKFypy';lv96!g>`sJ8n.xhA6@P3oLFY۱E #,"mX"d]6a4DPEwNtoId6ӿ3xꏽQPo gt$/ݘ2Q n]*9PrTML/"w6 ):G.q\ &8$;c/!A6סc:C"+&)9EDc#Db^Ӛi.(ɓgڕV4H /+\u8^Ģ=''eAfЌ-@ېA(PݗJ k/ $ΐx n&v1EO2$6Lޗ,V; {EWEPVPppr-yYy:fe8kT-#\kz3Mvmh|Nj9[Ļl&Y N 8xVphK>aA=(8aԬjzKcCȥ8ɎX%?(Blv Skڝ`}Kr≞C^aJBqh]e rXԉCD0 !^= Sj^B͜)Q(/9QKk*Vxˁ&k2 <_d {xZY(B-;(eǵ,U}I+i[ҐHTP jTI*CF_f~ƈrY?'k6 qM,h}9b[3P̗>ƑN*E $q^&!.-G2@.P\t\!NPJ4T|9Ws$a0:ISX \

^uG>mX u4Բ=, O|FgX@TcMU/[Ȥ"qm "OaRSLH#`ΥA>j5t8J7Ii%k7Q{pr}%8"?5\*/"%cH>Dl/pVEvPV;R1"=bMsK#I"j;Q#|pd^D;)扮Ix?m:.LY+Ȫ+4݃9"yY "Bj̲;iսƥ=,U:Kds6<@9̊ bj[J$uU&HFwhVt&?V2l⊭[|EP#36Sqia7ru/9U Pk-X%\gشĐǍR߭Qtzm42DP/H[y f /͋hC$ڟ+\2NڢHTt"u;c# r'Ϲ}g#ֈhAuNC-aieT!f#L%1Y{19@&#j%*J#dHh.vgյRW)D/!k4NNb;x/-9+]sY[Ü2Zhԋnpn$k1T37S ΚC3#ϕbKyoBGHOrZ>Yق)m } YӖyDٵӅi;?3 (7 miMb+6G r> M8 iC"Z:>0N`pռ[IMoQIuK:D?+s"#;00NkỸi kc]4>h˃V/E@SGCƿjh| gQ6Iڄ<1RQtdŦCqLLD8 kIAghCV/s)G:PVD@e2:&ށd4TpԸ=t@(+XiP,:NC_j2Yj[G(St](m *|&!`z!IKI^v?ia=JE:/7,ܜ<|w "{08&IZh Ik͕&a6Vhi4 `t{fƠ"Ht0z~ 1k.qt FhGq q@6 9Qj8eIAc*Qͯ@ !e$K*1Kgq#N<]{ L-XСzFd1RvZv)NizVwqJ&V:f5}.%\rUyF$`ܨI+5C3xfui]C=cu,j- :K !\d/Y/ڈe"s OdtDw탈7 0ırQq 4U+o,'^0*GkNĄA)>zF>duGD2& .t )(;<Ph>n1xZSt4_HiDKY[YO'A^A|K4G6r?Yt6Q.W;I$kTUh. >i埘=6%0!0@La($`R-yWmyjEaZmよƭ~[ @#\s,~nk}!0o6wvP I.`6@J5+?8epʢcptу#6tWh!`'IDC )(i'NEtZSޥq|ƣ(Uݢ8r:}YNJ& -@0dZ#Y;gCoف!վljuYr6ܶY<)\KC d@lifƋG.)Og)Ҋ& `T<ϧX a̅ L<1k-Ҧ瘐r4e|Xv'ńF5g6eE>g?8#a4}nF?rn:1cX QQip,,}8x{D?KĖr8,g͕IPKʹ ReD)oE)<դ= $Y1R(⍋Z MdA `" gfB]9w~ /T抨*OGtU\aʞ>> )U[zJӬHæx =^3CƧ,F_ffaǺpd6%3(x[a Zv&ՍBpNelj5˥c؊œK !Xv9uRn im@858镸Afՙ%:ϮX< E,2Dmpa+ë)NE=ZpΠoы#+HT$Y:KϴN'iPl'zRz3@t{P/ mk7Z )S:X!3NF*w MO QGos6gUL"D(͜[?}f"\ԛ'mX<H n.^Lz 9L\H䑯h޽\̅H|r~\ :/>YFbWPu1~]s$*ŵGpZ\+&eaDtD%k8zhVU8՜V8&Ѹ:QB&;uKxhv̳Ukjn:/֬o$f3d7mpX8#.1\@T!,1[3Oİhↁ lS94l=Ywl|2e=/ɁOҔ&RrVxVY{) F bC4-G4‘Zfr<^_Sz):"qg3Ɖ[6%et*_DJ/{맡o?W"Ҏ+C83tfd @dRک]8:wٴK:DVf;k.@TTurG{L2rHoh% h1ȑPĴV*H09,Děr,y}iHDwBF+wؕn1*,+ٍ 4}V2`2sCW@( *}g{?8&_@R c ~4tbqEjXF Չv!?cFh2u-[\Hy6v†b1G^-8 JP=r (eH޿bOMqgG_ a9_^$)ۺKԏ{HZ& 6DI`^o4pt{6*zLܡS7Pm>OEQqnsNgim"鉋)t-$'y?ڟZa GHwj9'xNdQ>Y QXm3&7CPi Vl#hCN`.caԍӴڽyOf%9zH=.B 0Tc@trY q:],p.C{I1:%lT:^CH*^V,rT>8^ ;Fl7vl;;gnC77ޡAt{ #z 9@=QX% m0DP7[V1Ot@Bz&H!J/Fj1HVB"[ ].pB`%7pRnS&Z!=BJtW)M<_ :7% "$=vڻM|?eI8ˌԶ /WlĈE>bBD6M'Ml>Hw/h.*449q3rpHV6*p<pGA8kqp>Bp|}nz_8? kH"ACI߭0YQ}}tf"FߤY&@nw$(-q {d8x c#b‹ozx2/6nt8T9U#4 4z88q|sc$Q}cߠR5+ku+_Y$އczҤ2Mx6YIV}tI_ c\Han,{|O{XLA1u}ᒂ'8MA#Dɼ(WhVĉOm>גAOϥ%2*P݂}4+ qD| 4m&:[h- 0r?DU8Md"2n} o f&k+MqǽO,FFC9])Vp7k0inXI8Bh,Kx@bBGth|V|VGJ@x@%F]qvK) zhDw ltaFIwJ zu #64[0Tҹi(27_8CӬQ6)Sz8A(NP3ӇЄ b!M9XY$jMLC*Y{ G>?_hD;͘Le`C6%źЫd0L{ۍ$mv:[,μ|bõWk&KfB!o ݵ\;]1/XNw Y;RjRpR-<[ڴt;TDyٮd׳Im2X7qF6qf.dJ_97S+Y^rrP/T3+]'$Mܠws8=ER F]O?Aoxv 1;nrPp%am\*Q!KFBFEXk۵ : }rD/ X[d#`8:"yܽ"E /R9jrFӴYЏJk{*Rx65@"'Om[:©͌fbf:h.F58yTtϡ{z鬎vmY6OR9*3j&06o- ^%b*B-+ )RZG'FYC;#'!koLrȖCCo\-@:I#$_Dr9d߫bYG!N mAׁ>.f=L)$G;A'B `< qZkKTB\UO  I'niSD*xݽ\ӵzq_Lh,h܄#!g+ɆHuB#34) 6rM$G u>#ko2!rE$+zKJa\( >$@,fv$a(yΣU;S~]\LnBFÎ/*)8.fj6Mseic^6f"G3q^(F5 ӵ yJ_4h49jkj7Gf(?^2Lt%20 :aӰO G{ ڃFUxZx$-UEbOS[W IKJ>};N!px gme'jʑ}d>Z &T3Q#gXFHٷ!~EN ?$_b&4܃8 HLkR#W񅄉5rḦ́ $?H#XYv})fki@^v%d 'fCNe+EVG|OcxI1#&DxN a+:g/]PL<aG w`2-!ީP:7ͽMp yũ;;VPRxh`KJ~c鸥EObE٘z<'Փ@GC@bwL0&^ٞ644FX_ҍ_/ȊD, }KVB(>뭄F}!McFbf0!:U㨉Kک8Iϑz#{*͵II}Hnc9dK ZVLfUJ."?q&gzݥFݩ @.*a@ɜI_ٱuk K#wKm&5li簠 +4 q@Ea!A1+ sc҃^.>]*s dCUT:W|m]<]Hgd IU^WV/\$ 't\cDDϭt8.gz;ņ0nDn2G`"wlnXFIVDb8_ kh㊯`m$'}[fl`H0Ls6 ʝS4)LhiC(VO\qga' 2.ܽM&oo;+BjWO<,Ecoş"9M,=:>7F^ZQ|+ $+S:Pa郚tY?޷U+{s!IMwxRy1%;gg(uҏ,S$Nb9OZ`_b&@J+y3K= fxaL7 b`XIB}Ȉofㅇ1d*;Ca&Y;g(j FcM8YUm6 D܋S~ȈE`{/{~;ѱ& fcęIg_.yQ }&JaM#VS!1+ KTMt^* 8q IFz Yji$\`jEy'`3e>6dAab5s'+hP/+odji&>e"i+ֲMt7"2+MҖ༣tR[D9K״%GN %z `_W$H7#n5Oq@MtQ1S&?0?E|:7[D᪏a:I~ĨS+9s,at1=]DG3 p%4c\a$ S{ĎuDE GJ5Kez|f8҄q- #,T<JE ͷ>,1#e?f$c>rr}Tk~\ϐ-@zzЁT|b&ZyA+0Έ\â {%4YFc0N`xUJŐ yNf]NGESF֮ P9k)U:W *WJj y J~ǘhGALw`6]6R4׀=j&u%N}-ݶPa$eW O Cq>l(?g還fٍP,<3JG5P죑m'>$eo^2i _7La~^sF0Y 8Dju>[f W8UwJ?)FqBiM&۩: &%tgVLCrOlPs6q^/+PI=e# _'EbBC&"ŝydY{gn4B b9^rد= Y3$c{|LqPr=q(H !D S^~uU;Z,Y:uѸ56 mk|Lo:rѾG(D8|&N?: $»Av3im7I^Yh5A^붏tv{G״JzG:nZ=rstv۽ݾashyC7\9t}8 Ή'5xLl&Y"{)PPpKQ`7`Wrhg]~ppID=*Dv1Nq_bnjB+PqjtjRȩ?}3j""(JU8Ռ'WMPMBdDCc_T' =J30gH Y_;(5S*I=7Lྜ̥h2bD[ͤZ?ԯ}"Ki@d7Fx)wR{ ȾbJbNArpsG"x37rh,ܳ>ɌQ|SCOg@i6]i0 ;aQJРpP0??c@+-DY"(1hl6gkh\[ڝ͈f;nv<#^t%,#5#vw ?$/z05uF;xʠ)N"0TʴAn-38Q-Hrq^Ģ坫 l*AD[D#1J mDv -.&!2 noQ";nCs3B= pԁe7Ω0I+*r+t"%puge6P~(`ɖ@d t]W.Lc+E"{Y2.o̾Z˹J\O'"޻Pҟپ R$EȏJrD3SF_i+8gèTڪs9ͺvj"{7B 0{ j8JNU8sEGV"ڶ$OU8mUɊ8w{ćsUjtc\S >T8Xŝ| *"qqǢhZ NRsQ%}|zIY}oXL6ڭ4%oիP(|,jyG\ϼpՑ卌tq6ef]w'մWhh"+P ᲆh(͌` %Nt('z}G-/Jp[!D+=cGgQeL)i5h) t|68~`zUe +nD@ν41Mhh8ȝlN+ (kQ&"q.CZ#(uJA1ϫr V%-Rɮ["(%U::Qi~EfnŒ4mVA!L&)PuEԤ~*t`ɀmTDv p8U-W@6 M[M-ڥgkhxI=éIYǔ[" T *u+B W DR@Ң:9GdooiOy gcꈛ~zTӹ *:q 4H Q|KΕ Ϊ@P.%?,'4zQ HJ%:G}"{ (]4(üۘn7z2"S P"u{%EBW$8\E; P?BVt %Z 5(fGQ!D0H9Ce.'8bԝoω>dQ:suRI g|@w߷kۭS)a*[mbyaeBz7ҋp/-ҽH n?_jC3LMdR)-y}$:>(I$2KβPke񏎆vnwX#B!t4`)"4Q(fӹ * ]Ǫpr0SS*p^98!VI)NR'm|yX_ 5TOz7U!fԱZWD-o9W|Ñۭ„#u=QMg4j&8 gc5o1HseHC{EM$[wS {٭c"x'l7  (F͹%%u=x%@MxtEZ{Xq+'.DȂG% 5GAb=&kArH3饀_^ky:;(R&BeCiDYɶTCE:FS+igdl34ؤfM/Z6 $4tEf, Mx l|ʕb. F8# 'QGDm'y2 @'˅(j(`$(ҧ whN Q8 eG %O]lS8-X 3Cuj%3V#D7<;%:  &$[qxcc-]?S347fTB/T`qS}*-J8HPk~2*@`s-f3cio5=GVr_Q1V:2"#!1 Z_Pt8p֪P2a[tN N((qܝ\,Nfl_Q }Ez;mgrYޓ.= y)B / OZvpX!BVpنZvK608ϛ9AU;;A%MPUs ?ٰDx fA;5 ܓ$߹4JK%([lj87:;(H:m"{ LxnEuF!U]-T\w qjkn1@SдҔϠlTB@6.ZEUNުbq1E0Ktַ@;@F[Afz1 8#em\-\3R=r^aZIلK0UЄ>b!sM uyݪ  80g%]~+H]t\o Z|l|4NV}IBZfw]'HkblڕYr+':'h6ƾY쯪|V(ͱO^)+;|rFv:mh4lvy%@χlpdosh׭~=leqeB9'f+"1H ]ӽDvأ^ɀNQjA#CYb锒>$:ryNNnꀭP.k\Ф([`*,$FP s)kh ߁~/=^Xau He+9E[&DKg P!@K~Hf E?5~9&^Q!JȠqlԵDvq ȠID~ENߵjI+C\+Z؊}Mݷ;jLÒhg3ϭ2:A潋 @ KHT/ڬ=|*V풺WD5 Tv2U~4iZǢ@)"~2h8۷+e]DlgJ/_B<4R__k _~qeס.kACl:HT?RE8Wdaf],KH"h&#z?=I[ E B!_yytYJ!~`:tQX E(]?/u.F# 6sAuqeg,(0")]XR5?F 5edőG .#덇=,g52{ Q}.Mn3C" ({C~SǷ%,F?0 &|x\9j$¨Oe$:B2Ro#m.?~Ǹ80J,&@8l QJ^u{ԪP|+dCBo^Јx.Gù*,IpN>! zR> @r^ }k]p%;[znMQ?@|*>YSV9Ÿh^DZHہDr#?'oϻV_DPXj;:HچvNQQ8U yBc "?ȉZ-PA_M#-cPStѱl1h6P*qnsVj%gL)[DݷA* bWW8 8? X`P8p8YkCY7tUN)4Wp)A]{}&/iK{h4UFoloAd-6O O Auf9OLDzbSRQn_jQNJ%) z*Pَ1Pcu]szէn1 Shb9Qt=hye`é|$҅ m4Pأ.Y=X۫j H!uKES7ٗ:}([yMd#$:z }*栘_ P;:0HG*Nm+:u]t?{ZםFtRqY4e՟=4+M+j{Ys hgE/%SWݡB;~F(Hilos8Aǧk+TEA/VTDJnT!k"-"B4lQcv{nP&Dv vCI t8t\aI[!p8[.pmz%ߣ-|X6Y PXp"hgAJU]} .^l 4mh8-q[^w6J(݉m"{ T$P7>TTSRT.`8-6G"ڎ} dE 0h)NDV+{ X! tU *w6 c%m нa]<7*SDSǸ'PS"lН*i9ΩߏnmmH988祬*sWG<6t'M`ռp$yD5z4IpnQj mq<Ƽ0o<'V}P9hMJ*򶟝eU9W/֎"y$㡄t#)PӚDb" `0!qAf ! (*{HմwKRTu79kfX>ke-ӚD {A$](*GP{y^oEXa%s 뎀Xa8J/NNۼ$MؗK5vN\"ġjuHtiu0AG$7Zlo;/E?E}h=sscϻ*% j=&-~(XKw HQگq@?7edf㼯aHB=)P 顠%yY߇l)? m} K#4^uRZ!AQ7d&hkpamaC}D>f '/B9My5}Ҙ+ BPOJ;fZ4tP[ˋ pN[J[s&_Ϫ@M!x̷u~bpRӪU ܯ\!⛑!F́6'Kdu%O 3(Xѩ+tFy";eE7dK4/OlIoatiC_m"@RZj)UӺBOE߬nX(R8=RBI?uYY",^7+>]DOpəO\珣SbOxv_ 7N\H:qlVA(IcnA[jP=^iLq,㚲 { !Pas>j\ȋTyB;m"5~y"RC 0=g8vK2J$[/yH^='a$V{r8rG#)H8A<0} )qsb꼙Gx.X 38(=US5[M}Bё>)R,nёgy7+qhq Gb u %k'Lo.@ fyaႤ4B*gw!NIٿY[uLU6L0+s~?f+7KdtP'PX mmdC~ԓC߬`Ԫ[)4<3mml*0v A!$V-ރTd'}+uI^M9Hvy%[D8;|\ڮ$GH }ycd}xPF4sE$Yutƹ+eDp[ū{.  QT0a"{qBtvack+ ,TÐM_8p]%U~ AcsDx(%YQdU!,./ӡXۯ $=!~:|ͪyX]I$Nv ljs2xqשֻuDƥP\Īپ(dҖ["K+X>qf8IG1DLK9nWW-D| ˢ:<[$dYsTHb&HɝMEJ>f NVB%S4 Zv~V64 1~ꩋ#XUS'8b6{Kw2 WA*B@$^ Ü:Y(]JuL[] Uz-9azDDַD*NGӨ:YiD8^# D..J ɼdBlj-O?]dBC"͝ieGuH(rwD-pk^^+ dzăm4٩S@Jߎ߰ #&\H>-nv.2?. UIbh <ƴbS&zKQ (ԫX@a8Zs06hfCO麣 D:P"!vp.\'T=`Cp/gPsV8 qgCA@8ǡu0zqKמ}Y3 b$Lqk$;MHi7wߛvA7>?Iu݅eN^n^\mM5{ZK$5F8ťcMc)NP?neV}Xh'F$.Ŵ9뎝m@IkT^H*w!)iiwZI4A=X3,a!k/ ѠхB `S5rk裁"U'(Y0PԳ: YȆ{‘ !?DqvJ n8ʺ-$uqɪ4"keCEžzRGB3!E?3'R\Jêdmbx|gF,X|iS:I]kK֞0 wʰPG`XӺ̀hS$ۮ-N0Ú5!ܶ%DZOHuTp1UL(np3Qi )-ܓ Q0:6=55[6DxKAE@[nُXD߂@8~p/3#o(5'O#Ԕ(ȇ]=r;tk^>}]iCK 4܃8RD3 Bt-'LݨT6u pQ U 4 v[58ŖJqB1J#:% 'l(N4\l" P-|Y{Xlqjdm64 Ä (A@~뀾Gi I`9$ڛMq"5~~UnFܜ&+[$ise "h!s,XhU٢^s`X.#kgnˡt-1&3"sIjY 8; g J$iڈRJL 2BFE"f}ޔ88uVncwnq?w&uUJ!1}VX]T2?tgsMxG׼S*'#’c"^O+DF"6D͍ )9?(U=zM}i ۨϢVqeK up :{2 h"ݚ'H "1`~*@F"D%ѡfDY(@"}VI{fs)R( ƅmX>;XQ;Q3[ZaQcyhwؑ5u:Wһ'l@b$[IvR4(@q֩1kqJPxC=]l 2 \gndjSϣυFodKڻS BF*MץH7t Avqr!ēɠOns jiԫ;4шg !`oUUgbB0RГ Q%w?J0Fط~!0]Ot͑|H@O 8oeܜ*;<Í4-ޣ@㐹 8X) ,;5%&V͑!z!4.i,/7ExNM$Aw\b.x0,Ps :H="Rav3 [j~ (}Y" v)Qq &Eg(B\tKv1.,+/qwDctky1^jf}ы;/'k0pe,jå^'kS^)*zmWTMTt*=c9x4]t@HgJyE*R++RlG,0AX=.lp@ }ҀÁn!>.ණ[y/hH )SZ B!-1u7D[syMVUi<w(.Y{ܸVOt w-(Ejg+JG5@ܽӨ?/pT7:Z,9MDߥ8 8Z%78CHⳑWiש!j~'٫[ \0oZƜ2]jd[٫!%NJՓ3Sa W 뺴^Un1%ޡ*̣/߲3U9BT/$iy.R^W=c*º˪m#}Z k4: $)#P^/i~%HkOXWzZIzMlB+A4Jiʼn Ue:cH3>Ew-%km}B_ڻ,h'=6:m78ylbږS3δxr!@$ZЛܖ[˄/m$[@s%WF阮 Rjīz_"k c@/&KKKj;i_< /Yܷ`1,Q+Otb/Jvh=ɎM= g,@Kg9Ov΢l7WL@o GzwhәʃVd=@!u`Jv!$T7QJFo]?s ӳ]rPOv/xҩx3=7t0wUP[fO VG\NFC檪8pN[}I(h hP5>*c4Y؆ɗ(P}_WmpBjTΘF}"nMx7d 64HqH#LSuj"uic.Qq>Y] U9k۱/-);,i]Y7:x= <$zw ANv*/03ZjO?Zl..,Ef6nƗT:94PS|:{ZW[[l>&8˯ 86@'vUn/558^ChofC%=<",n.&85D4qmADQ?Vd[nF'/A(FVo(uGLJ?+(C u= glp|_$MgLsPk䓕ڦ_OXeK9M.|~/`dƉm/OBrr d^\H3u~=65(4?T¡_Tq Y{W\pj< V%'zAq5 ,s*Oi=҂ݠģ hWZubaOH"'^)jމn!,^CL-_FDg[u=Z;'ڦ@݆#% lDw _̳cF vdYvjؽ\-/ "odm*:RR 6OxY VN{4aҴ,$ߓXن%FB4 N~8yeE3JN7, :<^#ZT 4u*U$3lD@ߗPv ӼB;J4|a\>lC.28>9L |نFzאϪc&'V5f L(M #0}sDKtf(ŦxgJ]1܉._5R3j Ms H#ZSR֙R#5/}3/)Q]NN?CYӨEM wp'[ ͦSmE_o4*L"-&ˇ b/ 뜆'a]=kQOE:jJJlvתVB񜍁/:}xj7ĵ~:0'v-)J"@?_tYq%BqmmNHpxuY% h0ݣRݧMϪXB7V[`9=HhȬ8ʓl bVwuL]%LH|`ܠdZw-$侲tDWb9/@,>Vdv :G568`gӕ}^Q8}ubl@k2PyԼ^'KqS>Tu+ęb"SSUy2W7 %3ݦBo9#q c,/WrAfn&kayfb'TXJ۵:)gUm^qV؆0B%uodϖޯY﷊fc3+vQF#t9-V{”΁}HxEd1Kl;DAV/yh0!(0Br>/,7/ Y8:; rN$HQ'wG$ALhIL>@0kחɻfPY'/>Y1R?I hIP]7N>eUg5|N:FMW©L]\h\,*$.l]i>O}OgY^H|8t\MTY=Kn0(Tv{ ݲBfLq{J%!Y`ҋlecBqG ϣnL!O#S]#kC s<>"PݝZ㻤%AifQIXu IsG+QDuY_\'d ƅ rzġ ҦDY9}P-oBzQ*7\[o\Nh^%'|<_ k*DrFD_$'P]dW͈Ӽ3:]&r#$6~6|B#)Jor~H+h sm a9_r}v7(KPЁ*Ap>td-\hUGC˯ B/?rT:z9MvÉ\"x#:WriЯE0b8(l "ڦP j':9݂TjJA֩N\ ^ \>Č]?u8;np2X7a|*":."DǮ+g-5y>  mFv k4huPluylOibS~LVv  ۧwiCuDXDB4 N#8x\"hG<ͮ{-_?F1$,Yru i^^Q괎R?x.hZӺ;,&(POb?kS?%NnZV3(ki|bO_jo*y:LAO_ۇ4nχm.\i6QeZRe8>yGvׅ68'lEYdŘ݅T|K6 g)̉h6Dr- $wAT&TGGo {Ґ%zm:_לH~IGLlđx`G:fmpܸs)jVgSsD xc<ϳ,(%܃V*q8Q驀V'A3gU/[G6>Kc21Ս~Ph~H̯G)SGՃoksz$mL%37\p԰N':u7pb'9Qh*`?B?"+D͕~GDQirLƅ08;~38o}8T:.6"ÔNpA'&oJ0q^Ia2$TFBfv3#"NBLF'9yfġ7jc<ϘN_B@h^uA7):mɪ'XڋU% H+ur&JgPQ:0Mu}8ڔ,dpC.N*ۆHf6j~y۰}‰'R7jҍ_0HPY]*$ɛ  zszVNӧ.czNefܚڄJ@b*N%S8h4g/<BC!͝ieGuߴ mH$VGjEQDZhZc<G6x^=y+6cӝE8!*’؞Ɛ(ID@"T[.̜9uSN=ʿnYl~EZZ^Ed7>oO9xޡGP">;#GG"'AYgZ[;[KK[N]YLַ֖Nr HN@<9Ivli'=|܃`t<}Q{y/i^9{P{pAz7*: ùaj"cc09H fA" #~ 7MzI¹n1Ɖ2(Q#8vNV[6SqɡF/hD4 x ۱!1F 9|G3q DDd1gr9P qp|QEVFкmFC~7"Fĸ&xZ!3 Ւ~!monln;/<ι}0M<9HpnoH.U<í35 gPYP@vuvW֖VWv:KVg+l,/-_ިTx BG&68'qZML?~ Dֵ4PLV 8L ::( B u %:\ =Dd@(ld ܭPq" '4A}@" B?P<6>qp@T=h&q H@dW őq(z: RD^/"{S Ql ; Q^kA3"{  FBsgZ7`$s@p"$F"L+v+Pd@ފ*Zq $E=@j=ɞKd 'F $я8ՙmgLDI_2yyt;22! yuT!7]@"뛢Ca.d,=E<YDSpv`$T!*+*-Zѐ !1o\kg(kG-Mb (%Ϻ#"BG/,p^"GFTTB .JQJBvyDv) [C~,B"62*>y:]C{9EKݦDqD$ @SخB0JdU'&7&Wgr,,zmqnKj'"I$s/ٲWx-}Ը)P6o l#*C8#jˢˁ"aW7ZêL!FTk 5[9hQ4L9O^ZARġ$yH98̝D_?$ϛ4zlX$>q.CD9c NmWS5;MߊegDv”HmDsnӔ> oc83ku?wܘ/}<}vspI";`D\ q(# Gtg܏ThԆ&Fp.2R7IN(c?nX9'4%V4`?(Yjq" Us+Gd!F6pOdWXbI#8~BYp~DdY`;Z-bH"2AڪEv'obu 'c"{x0(ҲeA5r?(hiWAcmo5ԠyڙևmpP =@ Ys=)w"D""ʸ(rKT;VCIa.PݶiVe^,:?܉j"-V9+\t>ո. 2 ~/Bjωh ]괍yrü"oT JQ} /MU P<V{9GͱzUK֘378m$]8gds$6mH%X[NJgtINLIy/ pņT-~ت؋paX K3T_WBn1M#Qy;xԙ*0WMs` əTRIiS-V,* 1иngNѮtYEYs`wa[:|k=~e>;"pT5jQ.L`s\r%v#|!<+k[qS vMw47sDI'nפHwo#6r." b1F(hF:{" ě\#v.BY=NYUSA[X߈.36?H#m"Z*YqPw 5^kADx ZsAQ/-Ve@)"S%Gy$mm+_ O#U?;N7 H,SSI,~  .!F<¥)B qK6bBRЕh(IyMd3 9 Cu@]7@Ӷy7֘H%7QaįpT])אnB>xCWKiֵLMj[gz5ƵG?Դ*{k)L ]Ld`\~46]0%WuD V]y}JA$R}1U OwܬM[ oj|hg&@ *{_Id7#*#>B8&!)S#BGW٭=PYDox .,I=O&3{sOz 3 ԭǾ\ª@>]a*+:X[SmtMdsLM@eHKK맇d~= )P? uB鑄{%cؖI^t(y@#D5@ "o#7r'OZ8bEYrm?UbV',4  qOߟtLJ4[4 |M 1m 5A#RFHq}:V'0ґFT4Pvz/~~*+5b@T?i PXF0 ^FU8t-68X> v~ #>c׌&ɼ´sxy6/d =@Ҥ|{P)z*?ӲoLO!5sn/OܔD|LJUM4CҲVeoqih:hr* h3" f!Ъ օm쵿&wت PcsHVV} Rg3hWX"A-<**@dj̄4x&npGd1nE[#\ %0wXeͭ:͛%>6$qXn:9(+юDwՓ;OPYA4y1L}=dPvp:Vq <,\M9\qvslḓW]#zosN  >i`saðg݁a?-`3cVi9^GGb{%)@i4sQD&qp4}:ФHPC* s_WV/ߥ~js&Ni0NQ7ֻ4+M^jI#8S 2V/I UW5q/(+U*z+#KH؅^AqrmO]G}3]g:#?G}T鈾TvKeXRFtTnp35[Ѳixug"lG$$>GgbPM2xIYukjIB7sB;ϴy3`A/tL\?jЭ_%D"! я:PGk /TOԆ@ts'+hv6@A($!2;ճ(`B/8[CC@=$F8ވgB49a"dz{M +4n%;{DVXY]s^ZRLuDM6D>ʈfD1 WJYjç̊ Qe@Y"Q3㊆ M %[]W(HڜAhڱ f[DѠTCyц]+, FmR?0lC'/"ƈs{q QI^<VtFw.bҨhk >6 8yNQ_"~Avoќvpƫ_ N hlPNQ[ͮAXK8E%9/]whcc۳K_qP 'wڍSPѸ}&$.k|_:RR8|<_ Xs)A:\IENgs7t'D06SȾn9YsG3Au N#C J\MoUNSt*תEaܻX܊'ԃuӈܧ@MҬP2ij$t)Im垡U=* GHtd!b hHdDcxe]% :` $Zhnk_:"( okQ`8nqjpWV]>8+~Ң ";lC]a?.t ׯԞYϷ0ls>v6ݚDܜ.诉2+ A{2D-[@ AXs hP8%=q7Hj}obRk#=={ހ~v&+,7up, @-{Ȯ#f}c6L֓$8~Ȯ}Y݌߭:_EI4"v26L:RZ#)+@ IԿ{7'Dvx^+P<6^I"ǝ0:UE>bSơh BTvmfHYh[p~R L ]h3Fu h8.YsarjGk7\kcWC:c{ˢ[)t"z7 (AY=U}"$}XDcoNX{Pt rǃdUiCs-lZTjt ."%Pv;4Y;P8߬8hXBX+aUtىf3Uls_UU[}V Sƞ}UW8el8}%$ ?a o'Lzb4;1Y z V痋Wj\$LX+*4@/T$(?Kq%4ƍШ;N9nUG` !`hq]G5LǭNT [( A$đ{j}AT/j}ІHY1a6֮t8g/D!DQO'׮`úƙ[pfGe" Ȑr !hG=<&η=$Q NgǩW߉{ͶH뮧 7mƑܵN;(;avnv6w^K%8A Ni4@*3Ixkof0545 C25IЖ0  Zq ,s>Na;zTs0۪"Ch3sʩil[򦗋p +H |\&dYioT=0H}Ɖjf1u:;L]}6pa0=_$&HПbŸX,^-8rj̓Sn4|40}Z,q9P?Tl15Ar@,9a!Y5:#"{R͇L9X3kUt\[cV[Xe^Ev=}֘#RV 8҃7/'ACDysca'arˍcm }nSS;R'hƗfAī}~hbkpr u)D$E{ݍP} +~qs TeĭA'{uvh"'Zv")>Yato'g?69SѺ;?,Q C}Tgv[!ț69Jԩ:S'߼c67 mH90n\A nY>TGAD=NBC1!͝{dWYg7 +u!/%{{s;H@v' /1~8(` WTX@ Z]MD%1&evf*4p bn ңpzcOYܐ~`5dًݡ35ǎ/31sd&Xy&&'CﲭDF,舮hZZ4xl+}(Cl+e"ӭ=MDt+!#,钭C$ }! Ҧ%a'rVU+gm%ܟ'aDܟ@t_{Fjm,9F˭^KdorSك^ELE]:7DeuDUQXnY-hUiT? Sm}rCqm$PHٽU YިmZVPB#iӳe* Dxul(Q@*Y2X BEdՅfE)d=Ef>@jy@`BD5! {\@eq'DvȈ&2%?X#5 "gƺy?Ȁ-d}w9(ЪWU1E>4)MMz-തhLC5$4XhH >?B wPJ3^pec1Kty8a;w-&@#P=xՔ/"jaݙ[5d&RO$u$V% x.VEhy\(1r~ Ǿ g*#]~.?(""MxLYqCd4Cv4 YCӦo.9x=*h7GufM+'GHh'+|4d3#98>\/LT;saX/]xjQn@dT܄F;ӎP] }Ꙋ@桪EĤ>Ad1rhCSp(f|!eCdo2A(IcQOOĊ-8Ѝ`tT Mw(G֐+E,W_gl[rR{]8wBï;B8IāT0'~"oųpPcS=jHtBC|Ȯ1 7BOD h{YBa& p0U[mtF2"8Y ܂!'HMMo6X!ɢSr:"aۍpvgB^$BeB<{(_x(Nc]\5d~!n 1FvJGX>8w7zL='<ԃ` |1T"oum܂N=>>BQLJe$yqSJvl{1B+k5J0qDJ#FDR%*kѭ8 G=/mZhn-اIf2"FDbLn܎ U{8(&`q L=z y}(7KiԳe1(IiG/{ ]hPHR A'#޶Ѭϟ0X2YO46QŸ "ʁvs…DY1婹td bH'WΓ`$ݦCM- g8^#7T.m$V/IHN)-Fy QП>"DVŰMTV g5VSA";Q9luMzY2[2ao86Yswpp&£AkNEb/ aGxB =!>mFtAa4&*ٲ^F ;4y+398[8B5 N`,6M (=DŽ(pLك!MhB)8&4ֵHKuv1:Pj4(ө$[a6MD60 ŽEuNŦ::7!D@-F^>ZB(>:KGG) F ftAN??lTCq.c8Pclc]C[sۺ#H5Az1WzӜY~XY~ RR>" e?$*>xɠ9?Ba̼XIw~nˍ?*d^oa=n(/P x;dFĢrY fk qTNs8%k [ty澔f~L6ԩcDv2Vh: h‚nWR [QnA=£DXre<]"[>|Ok0ó]ດA^7]txjPEڰ% E~Hө|ZkJaz Qs@zQ:q+:jwL' Lp1pN2P6ޮI$2lD GG-6|~Ʉ&gzYmjK";`D㉶f*g` gZ9)`4_7Di!Vpv!t׍R8i+0@t&(8G`{ɥմ]V5 [FS@S: .0)b+=Z5jI~J03=#OM I}wwQ>C$&d#}P96Ṉd㊯CNx%Q'mJ YtAa4j#0hM(H#p)$l$$ H\ɸQ^ ⠛\vC^*O/&[S2kӁ!hdp4GH %^bԂ&T90 %$̶1+x\VU)Az%*=z&g2a&R,T'm]5=O heɥ=7-PŪ#zQ~9afj3!OV.gTs<ްt,m?$?|*+:ްX? "Z[:ۍR;I*ZZpJ9Nbۂ~Q-*I+NsY;4y/PasJO\p̑+J0Wzd hM0ܡd&砲wtK=&8YnM}#X)F=Hy ֪~4 *$NׄIꃂn܆=-!'mwhB<.M-DSsиpŕ'Ђ?P0YI>,@L=k*gЦe>>yc0 Zw5$ADo@EC?bknJ`b,>1 >^9 Jˆ^,ZT-9?^ҁl,֗%*W9y7&Q>&EmQ]5m1Q]qlr߱eu!y݆c2WP!*8ږM M;5^Ij OMlGESg G|Xp8L8;;5NDW5)c(íP =D0yR Z_PFSatךrީHd2b;%  \jE5 aE[iU6Gt^ogmP}܈J^I$ەN wi22{K~ uQQgjՌwi]m3yD;e'H,ٕ~I#Os@rڹF@nĉ u̝Ux /-g#TCD2BSYb4ҫiڠIR#PTQ`D%QުCNW.h:SH~wy}[5ǁ?:B (%E!>Ruf COln'NY<r";PM#!xW l,(0ꀚD@隫X\X ;=]*xG`ԕz)+ Id28ˈ7ҙFjv'&U7dAEu?K1'gy+jÍ[-6K@C=bT# -, DJ蠒:r׌FBRd@Giȋ!覷'+5:uFˆѠp5k+YTErtk|ܿS7gt$V.5,Z8y:B͛` T^oQ 4SΫ7*Zf@iF|ⷌvmC5_p0o0 #'Dk}С.D=rK~Zzm8&Z ڽXY4F]49w?a7%2b}Dt r-K<0FoI>atK"_hA~,PfՇy?PK->W\SS3>^kGx(.%kuLtRlpdr`A[sV,lzvV otU  "le4z`ڦpIBikL3܊a#!@ 9]cRtia.εڝF_fRUE",ۋq kNh/b"k4~6P%|҈fi瞢SS&7׀kl fQaAcj3*Niniw>_ GAmCcL ?\Y Hy#~l!:`H.#.M⃠?+"acDl }^nD$0R/xu8S$J*N^Kn9WB Ѥ9)N96}iVJgoD $DgNy; g>$"D0+#4M!,L+{8wz ɫ$P@sVPB|a-B٪:rK8p_]~5D &8ȍ9Mg=sU$BeaΊUEebhz ӛ9Xg[(y3@@iI/0dNQJhf l6M qKF~\&@xHi8+0K68}P 8&|F2^Oh6 F>G$U.L,ƥ~ZYrkVU~VMȷE8jdz#ʸz`& R_t84~I9E-8ۼt&ҡQvuh--9@:F "˗<Hd0p5 i'aAJn"OU.@;.1#R@Xs?WTtt陌>sѳ:G8s~ŵ]1#Wgd >#w6g!%ݦ[fI5Yh[Vp4Na䮾=iH3%q 8Io}0"]@-$%Y0 1~/`#nL&R:Al[qD~R y$:}c&F: N%EdWen; '$*=tīZsQ9 6juOPV-t=:GXBr`DJ2iwI2}(!_P, x@Aea7O"/+g7Wap8D CB0Q D$NHo%8:&PI-f_6^UA͍z TTBsTzͲE. ;KX>mHَNytf^F@>g" 7ýҰyW r4Ӿ; sz7|`ы ON]Heil=Vjš7e\*OILttHՄ4F)5-"K%s]7l㤥E836gJ9o?HyQ4l )}08gM> BC"͝yeWY_z-*DY&L2ߛǒ G2y+ !4)hIA@-@B&,=KKʽ4s;=IIn_|ϩVKֳv=-}{/^u_(;v#GG8?K~a)ZV]o/7k;hksw^wn7>=?vn|Wngs۽|s^޳;]ueue봢CWYfBs uiB$?!XYsNƂh/ D:DP%#B`W6եhs-˻N{^q ^A@:hA{p Gs,1FT-NR%4s b ̀5@0\ ts_.Nk&@!tɀzU<  % :1&vQ(4u*$Tt6 v v#(=; qӥ8Kκ}}FTT+|ň*-8\tK-$^jB ǟ1G*o/3p4 ZӳCW z W@cT&;W"\֭yHt g"ZApv4A 28MpN-O}튚 Am5T 4,p@/#^WEEiZjns('DaErkC rP#/`BxֳsԈ'3wAjZuh^]^VXF |Pi@.%g\2maˁd |{Wm 56֭[tz2ɷ`Jmx }|9QfTu q 'ܢ52Χȷ/ FHi 8V6f[=C 5Γ0>(}/>U:$!S;W[ݧ #|`P&d 8kVqyB{H''^lD䋁 [Pb#!o/1 A~u""_Ո(F.9B- } R  dx0"qk1M5 3aI癒,9u Tn`Z cəcnW%)vG]gn|SkzKBڈvsb!DfB|ۭ\ VJvn$YrSf@#ߎPWѺiњڍ*L!;o_wj'w} gs{_(OBI=Hj8pDq3({Z--ͥ,2Db_S@!zM7v#bWdqGC..#)Ij=JC#",j. zC1$"LF @نqTkV9͍M FP %<$Y#<4H Bs8 ^,9 ɧ1'<+Um'@8}yDݬ~x6 %z7 Tn-*sn`qG&J6|p~|{u~F9[s)[>EU8ia$s5Nd&9Q1xѵF0ESLjIx m!ty[DpڙҭcŁ͓A=#ByiׇjIs4S;}ݬLM}6LhcBdA@7ɷO% kYC!Gw'۲gnR4MQ "\vq'dy$">M 3[b(hsuK!7)K^i1"2 !29iR@Α:S(|&\pn-XMШx@@lʄӶd7Wn]bOaG@j0 aS,|ϟG\t==rwPvlTqwWw`D=3 SMV AaWI*st ߶kǓ!-ue3+,7ҫR\S`8o[4Sx CAHUqȷ׮k!ahyvw[~fCo׎Ճ;PvԵw>&w >S)TΝDUB ;]j- . sT0ЖN:7oMMԟ5 3njsA'̩?5pǪ3FR4,iRH#e&D#*3 e8vEa==>aS+D&6%lJDw`°wPj/uG#Fn22cڶ})DtBLMflB8#l!%K7&F8 IgY@1$ 1 A0]0VZ?N:t0x*[j~@qt%vM|V^Ǎ̳.꜅q\uQk\>vS];qQEZUMԂ'=\U!pOϛPqv959^LvS8Cق9יE!>7#kdYv /%Ky#fct9"%N5~VtK.?O(fеWPȭ?~U*ڊ]KI}Q5ȳ¡{UlW(4Ά|nVInPTB0s:-qT3ɬ홚AFr &UbmM$Py=P e"Qx٬ZAnqHUM&Ko]e8](G$SPFbY6`ZLvmZhTsfE_YUNg\W0+ItPzx,yXKEV@}`oh"{IiID;I= 9ˊM5K+i֣%w1j&MO wM!HΌ/*ʡ~vUQ֍@4frD"1)XQܑeKs/ZȷOFʕ  ,k6Ͻk5y|6 -{(IJIY֛KYp@c*jn{M ). z /c>T4R-_s1Nn!g'4iz|ŨWAP][VBEUمȋg]S!C8M Ȏ%隫k9,yP]F),p6 n5.-r5 ҂I>GG~;/^_<)k lWJAMA^HPfAZ/,˵k/9AM54 䋞0.xv< ԏsNIsD$Ih2v׾Z, R(R:TFs1 #/E='wp ZݵL/~JUᘈ|{S h0ԉz;jn9㜭M8H ;.YcQP.DPbOZzAӫ t6}Iz Zt+ܒP bF[&P`f| =|„&( D۴zBׁ0;H7+*A@3rxٴNDVvzIT  ӑxG6\"#'0V~{2ԺR8"TFyv~2b4o0!Kp6m$H:"Zۨ(ނ;v"a-uڨ9sR AB0 48ۖpW!j:_#>T~ՄBKlNԳ{G}6QZAцnin[d}z sbjX}h/3 R7^?`Xis5KP>n,^%@!Oh\&|G*{\je2&җJ&k]qs:p7䢶m$}섬"hCyW\:{p8ۚoׁPZݍJRˤLA7ж^Bw"EdQNFo\4jD $-}`C ˇo3,Pַ䪧6v6DJx}4Znwt&K |XWu2":HSE2.07||\/Tq =di[-˞C'}5q-z!͙%QbjV{o9DnB2kڅ2Nɒ-F4Ҝ炣8m@m۱7}R> qOo3ANOMp\=An8;. N eƃώjؘ6ƏA0| FvЄc xކMsCkoFSjKΎ8;/%~v_vE:?'혍J"!Dؕ6ڴ*0%?hNVQ+ C; qPi7ZNo8ӴE# ֶ.g8b]ȁ qnEO^1'.#x 'Hg7!I)UX/oQ'! D+lSki4N$Պ˕3ff})C ?왰M>R,[s3 yi}' z60;_4oo3  n)Rs11n1 ^`# .fa8}fznamܲ΋Y It4#" 8ZU+4Iz<_\W%1rU   ;VGtBn)!ٶ-t@ A$bvA6s0ψ7r"ZelـJ$$m1UOz&Xa(w.[T4S#lڗ{uy7$;A|37TbIc`P e?{)W%~(unZx0_ i ~%=&Hy Y9ej׼b;J2PwͮJH?<6hgMܤ5wrd~ͅ*ou"%:]8:XgAQ5%4H#3A} (uE׶Bi[}P'>hH@VWYߺQш&Ѭ6IXV_:\8P5DmK4}N'/,;%D *݆ 9> YUL$ߞc .A9]iD ?Fbcw^4xyZϴ/2ӝ'9#*iͻ3Aswvq|%]ӱS[IxB݅a _g}9,ز=4iO%mOJtB%~TѹȪc6m8ȩ3`B1NU;Gp9" u>R! !o#T̯[qA?K޾՝ˌ(ڀ3|&O!U]EY O]{˻KnxrR]!v9Kץ$\i$Pkt\rR1J~n&"__; *! 4ҊfJ`#VzU+L3y)g8wosP+$lYI wԭ 3A_}K>O?`Zlu@t$Ew na_r@sGQ][B8W<\ADvj8kj%*Dɶ&R*CBi%{2bb24/,l`en\Ӽv[jU^:AjoO}רeOzk(\h÷ 5J"[(PݫQ s! ̦׶6uEqGz(m8kJKm{@E޷{'і +Yq%]"^ ފ눞jNv=&XϜ@ꗈ .v=Wqo޺+šI^ctHt]F}. M%+hI$߇a 1C,;MzQ uIzLK]JaOhQu~;T0?`dΈIYJ.s]L\{R{6G*{P~*8c'ݵNޮ~z>{sQ$vgsmҒ 4(44<HHb;CC>JUKht9랝{[K{-7k9>W91?7Ͽ|qܧ [v}`xdem o`lss v<*#BmaK|qGG|vڎd5#kmJCN֊YMYvcP@TD_ k7&"4КC&0NԈnC |h3(tF{!Ivc"~#EIt֝ Q~Wgr]VUV{dDLa##w/Y1N:sx&4#@2 wɳ? EPIMp9@/Ҟ: F룭奅v(/lQކ=E)mK(Bh^]n D]e$ )!#1=KYA!<^JHL^bѥ;"jAP8@.7wF~(/Vō (la( N^Jxm# 2JoA,n5D! ¢l!Z^ӌ?f(E } )\`&5Q]P~ B@Q45}Rvڵƙ8e8 3qggêY?$kיB!A1XQ[Qs(ʐbn"ko0NeUL7rm7DEQ"zA}}*9opﶴ2^Ȑ/Z;YR9$kwC&fst6baXpRjtR }}8P|wyL]%[dT7SLr$!7TsQg522z̒ QҀe!-:3z ۟s5`|%8I|ıg[2LtJZl )c ¬ AyCba(ZT4E2  pÉiCm5$?!kWېG PA)$y>TInPB}`w30{m(XzTEqn!܅ Ă#]EB{㐃Uc-`qygRX<yLph3p&4=1gFvb s&t@_7U菴yyV6EM͚uWA8+2I #V9 1,tH@gpFHj[J {)swa +7@U9PQDG9 9oUX+]9"5 ֌HY{b tYV|8jyˁ&+..hiVBYPyoTV?[C Eh Q޷@(F9'jDlTc:2Ҋ;'f!(!)^0XFN)?O>d$$ fbԓU'W;-p|OVۺP0ElNVZxC<tG>holhT JpDm}QOYcQжv,^?^>#|fف!Vq]t\BmV'"Q iQSc! as:b{CL4N>d8!XjiW 7U+d 筺i0' uaZsbD Sukdm"5FisڪLwŨ詙Lp5DmA9y۪l`(;ŝO햦~ |`&*G'|GN%L´i64rhRWeW4`VBo>qJ/Z UmeN';{I,!?YY]@q aerġQ! ZPh}z5d퐱gJ6ݞN oMCyY{qz8,9A)dED͔|-V#N0Nr)kA&0yD}fUlu{]AFt4߂ քT}dLQ9!D{Z{p9BkLnaWc ]mb$c>kӷrvu@A'ħ ȁ};Sܩ ?an ~Թn9o1N%oXwPy!\0ԲE Y3tսsdƥn^Fr7١aJ{jSm0SeS%Sڄm&(]ZަE)ʸ95*ΊGz1KN-Ɩ@rlgSCT?'bNк3"33;HO[uIMr c|痬 -p@~ߝ{_Hm׹%G{/&Qtm3̨8fC147G%{k(hSV ='R9(j^Rc˗z7q@t+PE4!)coG֮4$%IyikQN#>!;jp_'uDd폌,#$10m94ڛq fCyH1GAyI R@r0g&<"~BmT \fNXw/ʳ4tpFtN>dA8iYgܫӪSO@sL'!5cEQ=ܰi@o,&J(EIP+KV;_뼅8͘dphV9NQ ӷ%'P^`8ufp!:3zѣY,M4K tT (5m[}Eܛ.z uUH>KqBԛ{)[յ(A|;}i7Oĥn"GUb@b uTtYfRO';VCJbC{Hz-:3LD[Rt\X,<[ms(@_X_[SIyT^z iKH}\owtmZEՌpRk/G%lX# }ݪ]?qE@Ba]_iYEB}/b)E\Д[=5 D֫uPI[=Iym2Ft8[wmgYň !I Fixb|V? ]x- iG=<_MUMWW)z&'v<= sοu V`NGláIB*nfAGv \8:MhncHWҵEg)Nq'0F4<0Uzaz S(^~ȵŢTJJ*\D^OҚ{U SȺ"y}eG2;'8_;0U%dmiXwAbi$e Sse d]T'4մVldu"RO7)_v%%@1CWghUqgB_,LaE8OڔW@Rjni>ϣ=R*?Ă =HvC)2HGk#R':AsͨnӝmpuSYrLW"Z8CR-Dm^{%䳫VBpUdچrrr = R4O~Ɗ(#L ޛG70-'{bZΛ⠎6b 1eLDN6P wu5%6cT -%tO:@<}3] tNH8Mmp !BFs&D5@WxR%d7~8ST%^@Γ>$4ZG*No9]X^NDt%Y8w (V&;XXt)|Xh%/n%k7ZMDWYtrխVb1=NgWlÝNJ>MU|/GxSOWn:KR$"gnji"1sW47Fh2e~NH% ӧb!x]O[ðm\Γ$+}Ǫ"Go/ gB9뱗@+- ~*ǘx+XKrFRvg %ضǴ@Rţq8x Kb< )sI*"(_̣= `w? + Kr̀,C}g|﫼P]ZXtrd/|CǤ&&)4̩HTT.:{US C8frE5lweQZϣNqOȪán:6ndAGuָt 6Nc}xX6ӊ8#G8y>8Jg*lLDAOA2p<]s4_ uFVaqN:O[EVpNgSc4+zc 3TQ3V8yīqGLJ5OcGAtιDXbMRXtpU4Ǩig4QÿX]Dd)9R@C"(9"9wNBāC.nPi*[ QІ/؟ lѭƏzh&8juU'z68Ҝ(u4kZҰ5mxB_rx!ZxrA^V@$Ī́Im3L¡DŃI@@kh'4gwHn ]n@f䏻X+S9X#){p>>Q ܶ@Lkz!Jr $*͝íc(Vgiٖ4Z *<㞵J](LaQ Qܢ+oبcuD[%Dbj&T=6aA{rBNx'ǩt8 pu3Wy g(:Zϸ'TʒMYs lIᮐn&k|2>;z^g`#|;u;^g)NڣoWr ":?Qdƹ,y3S p,H>i'c!:YGygiFnw&4͔0h=Xe=qF.pNƻ@{|% nlBĬkij-iIhOLۆH9{m /BC#͝{eUy/:{^oڛZ^Ffss903')V-VWQ#JQ[ ΃QWIӤmZqsYk'd.&!o\v<{n㔹Ϟwnϫ:wǣP"oy`@gxgx' O[XY\_͕|ssuzjkmmudZXݹcmZ{Z?n:e):Qx-%[3 `u?S'ydP Z$P5($Q SScrEn% 1Ȑ% 9Q$B|ʴ_+RS&L^Ϛ0\@sLkΠM;kkmꎤE!|ή_kmv*t EskArv! zA$mj K`L."(ur4GT<4G;9{)MN<sϧ8sHH8HH4E})*WZwrĢM8Tt+9W4FCo&*׫@ K81p6p}Ҙ&o4ӹ8q6ͤ.uP=F"} ߒ Ь $g6XnTS[DA@x.3e b!Ty֜~S ǀ@Xp`3Q~@!b6a9PPSϽ4?{svp 5vܿn[ܘ,.4 -lmw` 1 :]cx*kĴHLYj4>ӻٻsoXѻT7Xe$ QΆ$aWR;b?#ð_+ |bs94k M. [>1S!{*T@U o gg8<ΊkzHP$ xN>cLU=%lȈRuJԗtf09q:1B&(CcRFܗysY?UV'VQ_lӾ6!sD5^O2uG* 1BwD٘~Hӆ@进P7AJuM.;_+7: &nѭS"gZa A+ |hUI_'"6Ic2ziss3'\DD2"qw> kÄ`bEUtb$Mq8Tb($KwMHTriDή3p^B+v1!bwXŰ:½*ou>H=Ic@5':~5j8Q:r jpOg>e3y pD>Kn2;2>N{-+y|-9qF`/((ϼq?c[c :13U-Ej4~꯬r6}g,gR2YrdW0qrX`O7 jDENlh@ ^/oj56< B 4 '4i:)ݝ?&@o X`H銇H필o,x|/>@N~};<:b -L*JB-X7un@'m+$8̄ Ƽѿ gw{w;lLi7<5"i<:jty`4-jw'oן &.hy T+6鄈xr+HumD<ϐBXQa/Ҧ3ÉF5tLBnq}Y]1ZWjᢋШY:K0F+ܒ'-jU*PM-\R+RrԪ9TngH6v 1y}1&º=qNi?I=8ȢyhD[ꤳHp^ox·'[#?#Do! E}hvL4E}qdm'it:0]op'*= ]7A1o{PCͅf@FI;4; @p}̂˧SlWam I N͚jAؒ*wU#e?Qe0#v,[M<=D `HYA3GƜӷqwB@f"5i۬-Gsƪ/7V<{ QI>|p-9{1P*0Nd`hdn#gW'|2 3Ѹ*&wZu M?͘44wU2.ܹ.rŅ6>9YZ\K\iv@eN5sL>n=r\y +fcUx v8^A35_%}4B#o+C|j kPAkG'F]%a5D)SoVgoRpmH@pNqIB.r%!TO7_;9Zl& :uobjP-4[lBm$ gơCY3IXϗ^I4s}JAx?'gW .lź#ţP䳚ԁ@?3wt؏/ LoS6eC$5*,?TA}¦:>H F^wAUjS%B^o\!{;oλprDNpWr܏Md}2$|rn-jc1FYS#PBe|pe_ 4Un2M=,D)8~FC_4OH\]|N v L =-ײTbE.a:8PR'(#i}KЁ1p͛:)F,S5VFsPwPƐi.`3nFm`h,lt#f7.-J6 @:m{Az)0B"5k۶ 6 )@,j|qקevYa(S4;l>{򺪲]`Nk;!u&#u<jb T:5݈(IK+nMZbc" gU֛><8@oQZ'N::ݸbtC1 1@31 =%͍|*7}f}}h NFa[/:s":b"_x(S͌lA`&!@5x( 5MWnsgJw2@R=[t@為?(]2\or;'5f!sy&b0s˓UZ<0N2}Jq/-xhl ֌N6'7R,[@u@dorv a\Ʊ\#]F{+ri6/Ez~Pl46*,(HcxPztl:US&,{lX'OȒ5Խ*&eňLt)1kmrm&$U6\nCK6ln c+.O@h[UO>`qL>yZt7dCCgNa+H`u"%âZlڧ#u$7'^XpLkOհ#)߯+8-8O5N}1{*UnL9 -2w|]a;s/6E'ä9fq)]NیXgŷlu. Oh:if 2 kԏEAtT&]ě{ ~ĉ'-&n`D.R5rb '/"4HT5x?}B{E8 ,.HlmiK^mY6 j/g#uBk`-Yu" i0tt> H|j`ɡtѿ,Y^ fn)&^feHxqE4 ƍ,a n.l,6֝ѤStpJד+ʀ"!0 g,2 9q(>~q}=^ELg5r1 UOZ:U4G̤۬ϔ`&4{UqutgDɄEѼ_T,sH@OX!飹٪[b/gyR:SbgݢJg H}9CB>Qn(X>6t@tIWB^`c&n =Q$Ĉgds3&%|B}PKrH(_E$c ]uG(xp+&\}0,3CDx;Z\t* CK]tD; {lb}7ʷٕ,qq=-DUX'D7XveLD/@i 7;-|#t]4Tu.ksi/_W-5%*P,]h3%j] LJKqBJ<\js A7W^1501-_쐂ĤWB8 "yBB7_GzjE8O_k4*7Z$KB-nb5`L_"g72!yBN9BHźLf~*}Sw yu/ GBـm1PIs}p 5th=X\W1 !DiҢ7XgH-zr*)֌8xbN67d3[eph>rc@yA Kv r_VH?pgItE6X|^NA| Fl+wcl{*H/BWGROA\|I ~< < I(]eeGWumO8B:坤Άc[ibG]EdIyU)7D3V)g0m\q`g+rM-'yN$I'ojͧM 䣳KOh&8]sbPC3vDi0t #+ gV>ΈlixZ Q,&78$E^3;o Pt)Ln&qWmh >g=߀p#|j#쐳ԃ7Կ\(+ėnyW+#iV/,O6(>%*/1 5s+{HX.=oa T a\صmDAEzH' ѷ-|, ]PWZp#8w4$ 3vhRt (k)k2F}7J/T#]N59!돦Xt:T+dn*ˀS".i `F2诒g8y7i#Zw$#rhOd혔hOgCp+܆Pv3}a&S4c:W8AN<Z~K^]+& ˽:Y@?jaS t7+uO2|IM|*l+e*x|Fw&M%L 1#Vm pv4vq'PVHq dV8Yɥ;Xwnko-R+:oi FٟĭC1Sܯ=X9 [Z4M'P|-D0&&&La c(prW1DBsD'gG^Fc5Ji\ !T-qp IkWȇ}H ua9[y!5Sd@]:9;Ǹ ԋ.Ъ4HzdrFqMNfnϰEq+ j5׵Ug4Qgł|.V\oWD4|!}v1An4{P&e@kCiM 6d +O;:*7LP9LG1vZA ژH4pĸW^"zh\_Zғ_aABC2"͝ $WygHCЭM"QDOFD\^c^4!$0Ð `!I`H8! mk6@ ʥHW]USz`y+Y][Y9}+GW wv?|dgw_(8GNxy2L~NؓVVZۻw͝Ycwgݎ۳l׍Nzn^s{J;=sJ;3qSvq霵:3wէwa1\Ύ؋N=H0Ot{̞Gisyr9;GtMh`T |7ٲx1F\Q%zNrk+c  9-KΟThUہRMyP;(ٻSl/ڱxȤ޷E>S J@/o-GJ*mr٪8(Λ%ԲO(xl!ޫ%-7)*| N+ ]4?hXC1krC: AO!H hh2Moע¦%w|%:<м sd=W@}({JLJ{Kl Wt,O Q}H|:^u  X6ĄaLV\ ϑ&(wȉA(n_LΞQՙCGETh_7(8GW^EUqh;:Ex{6k<;4nUlV&He#8ڃᘗMîl%kh˴}l2 I PBnqH*`Ӥ86q΅0BޏC}2t.mQ@jР>GY9r}n0\T"/9hTf>v8}rL_> b>MT()toLxwlZ뢢n}-Nm[st t3q#o½]R̼?}yXgmŕNqWunVPщ]V9Y 9"S JZDw8\lӔF)mZSi zOA.uJd/F- OдgVhF>1O w*SGHh*wQEYJn4e -$Zo!O(@?dLR&n)ĂxGM$ߝ~(J@PqyYCgZMON}!HJ [&4 vHlFN.5YD1z@B$ht<ыhc{ִuȍ4Yb w+Cx9Z7T|M{LpY!b+Ә5Zqg0%!OΨA#AH_.#;#Z\7ŬHӻpeluk@4 ֭JуYC [i ))4T2j@ 3vjZs_Q;!͖L>j̪ 7WH ۺU(Ӷ*x`\.Jn#& q6m$!P }Tu˿#g_~(dߥq.2<񼓾"m[8zݥOdHB/",\Dh*]QeəS' #…p)4K*!b=`Bҷ휦e&^}Qr?q#T Bf(mN8HjNp[bd} PFt*!̄(^~BJc:p (7?ۄ[MP:g+ h\'uK %݄fK`hlp."85bj l8/%86RdlǻAFox5Ayj8B0F yHmy˓Aju!/ ฾x mܨ},7 ȃ| Oh $aԽHq|6$lq6pV \5v*d4'KQkLhB*B`Hv*\v$;-{~vP_xIcl2HgS۰&)G(@m2Px* uՋ<&Z ?K tQ;4 Qi,$^0s76r#!`ncmdơHJ֛6W5 -й-G@zzB!:[^wmW^v,j: 3[_a=\IY:;VO/\n{8 E>G-ūCXl!VV37y F8As'!OZ(D` dM:tԕgH:B`IJw i|VD԰,"x?U| i9{ٹ&g_ M+lEai\ܱcSOB#:4vm$ 0JZY#MrWvz#4Gi(;ղTy(yXp?׍ۅl5qд$7K)7ݧ[Fa dji(IqVzT>hL|iL I)d_tBt |g[Bhf#fY^D85Ņa$qY4dV+ݡP(pO3Prt_} W5]'B!׉~NoWjC0Wз}(@SA;\'FNztL:{ƺE' O1Ao{v]3 P09:y|(4 EHjҀJu =2 -̉yx<.ډA݅1Z⹌SyωayÉFlGN#y9{A>$EzN:n*1<#QIt }MÓػK+Y kͲy%Wh.w?lc'ェZ;^r@8 ?n0J/C廒(?J!:*׵mس&){F2TBK{:w`QUxlhd6Ψ D% G@.Qf*5=X`0Z9vU ,n/g;$= ی*$=s4IV8U@">\NGLw2Ap>޷.AO`0ţg;g>W /@\RnׯllU3ԭΏn~ FSwd2*9{oQɈ}BM۬լ#<#V0 +qIu[˞6߾wOnڎwFҬ$fiYMK&?Z69d}/.V,1k<@ \a^Y9pe)qy25{WbPƛ%9|^T^).ٸyMߧC$Sշ+Hgih gvkWA}w7劙8 Ѕb$qvᤳ5"(V&VpBėXG,E>j4}F^@բÙY5jҐ_貄(3j„jb55G<Dž?M.QlI;bb t;0_<^NOh&4x8]6 Up`2pZqQ .[77")9"(+[p0P5n&c(%oHxt)yJ5b0 hlb 'JCrɀǝOfT3g5 CDg'T.wM?1a?wvFA-l&iQp7 ~A917M'8BR&N/5a7rǓ'dN˓|kd8|~;<%([s'9r)Jp6[iuJ:ߟk\ju.NݪإDPUoSUVC-n[I0U%oy?xTzsGBBr(y"k_4YtF#1'Uu,eMӺQЊn2!Ţďmtjádit9N:N2t#RTr@\b2EBQ>J36޲Hee?f0<Me˰"QI8 GK? ilg̖4]4IsJ,BQ>.,S0u;kc1TmZvzKIrgMB1Mi8m/U,L]y%=Pkd:mn4#ȝw* Z"Ldi}jm%4kF/0Ćeٶ9 {`\o[Iܸxp}3nntY lؘ(F¦6Vڒ'Hv"闌 & .K-ARL%EdbhL%P~ D7aS=t~8n@|4n)F{BHo1\P+y:! 8ہF#)4Ѫ MM.v[y3$͊=A,ALfa'PP+B#I#zLIÏ^(!@n) F(Z)y4z8!MLBy<{ٚ5ݸ_Pz@^NΞU,`@q8^Q!P^'N˿%t8%gWਯ3U#l2d[&dX֠m!CY 5n'֪O]EP~*d{Gd3rL' 5 |ލpbzW&\L=S8M)e1R&D9:NRF2Ng#*{4B4z &v}ШE-e !$^YcvGVr*u?N@!qy*ժKCi\2jppYLr%Dh2,e0JQ:4#^ %dAfڢ61 1R<1_RM%B&9ԶoVTu@O!@2Ģ[hSߐp`,j#WLG i"9$m[Y8qOkGR<µkW+ӱ)^H2E&4P\8:ͺ}#r" k{! C8i. 'D>Jo@91*ױGc M!:*dY5&wSbrɫk6焨Cpc%X5&D&<\T: I\";P|H&>!&U!q }]Z98lpݭK0y&g@A$- <_]֩:N,*@4Ǒ xB]kn7 S}:Z6x(1 W @~2#(R#q;Mvp@q7c3ߘֲFGg5(g \Lk*yXΕr5V"`a4ph#JmEgLC<̲ lDZG!=hޣbjx3]gRE·_!MLV ݪ,-z#΄3h-Gj!M$~Q1L\:aKff~^((H?1 UBCJ#͝ eWY{zLg5hJۮ-AYdw5hbyɄ!AŰtWK:R(DI BY2J,E--**xν羳;$Tn&\5vȷ~x/{aa/مh;;۫++Icuksqku}|ll[ɾn[V{k_soޟ[Kd/jfuqyFkE.M.m@zÕC^ N*4WɷwU83Ž fZD2]5f:I1ɷ2a H?9&e4/`~D=^&D2}CO08 p(4N!<Z.dzf\A0ZTvLP=PulLH+1N6Lȓ@0p!5 ӒݪDD]WIȷKl3(NVLyD<  ɷmXR7 Th˕ey0P)R|۲PJ/0Bj8R<xܷIP.qY%&.)8{_"N姰!}םdPOue.+NHpkdfC3"L/-!'Q{I@"Z688P3I]MV87ugBӫdBQެ Z$ȷWZ. "в$F]R0LS%'M)a 0BZgL+uvgo u~$ 5X>Pc]4Tx68Ia?24 )P#ꡆrht*Y!Ri|+.H`9-Tf_O} G!< 2wo_ X^\o*HpD!߾mAxr9?3ϵZixV$|xKdΩHUm[^_!4댦vR z)1?DDrLtULI>C"r!NUy`$,T'rN& 9}"_&e#@kseԖt)ccP b\HMYzZv΄ s9""V`ktr&JV* 8k  s|TPp (_\Y INn-*QTs_/*a} h\ _oeր??`U,[{Vy >W1zF/5Vyҁcei;ӌ;. d~f 6˥s6oD2B dWd3k:j74*De*E+V\ȪI^iSI`&4zAi`93|~ֶ6n-S?AuFi ɇ=4D]Irp@ѨgRMv/qqvrocl@<q`՜m!'Anj3Ɓgt@tBFBԮN ߇%JNaIt=˫xDdMw4&raq BC$[ -wLA qD}W9ݍSOR2Cu0nr胄eU+LQ4_&4U5hgsL΁_dߎWNoz~drԪ"N zu%ee) \<~#%M&+WaA 9oy nJW*nK{-D,6 0LLt@Ly ,ʆc' uq2i:Po9R &${p?nzˀSq1KX}P澲A-b[tX-:I"Χlx0(f@dN} Ui c$(AK@MD YDG5"9x Q~DTȔ+yj+u`d 6'3Hgm܋\'Y=!0_!n`=9ӃiU)J@ 5 &$V$ ތN7r\'fC6j!K#ۊ(ЏYt4na{U*P çqzzI}Ue`=" B\3(܄6sXQOpNgssOIpk^)]*q6޼8Y0p.J-.%`P94+]鯁~ eYye>JoًLltb q"xe0J}3q^ĞN S& ?E+\#sQo8"Lt0/xǹx+<=w| M\+QGk`h5av H |'M򡋦n‰5H>(Lc"3_nC)7 2mҸqGko =RzPs xMz.Uzg*44yu P5ιo&^ꭕ d,EW'I׃*G Eo**`LM;K5B 6ZXr`,Lj;rן@A gqiuP`|-)Jv6\/~GGx@3c_ΔlӔ NzDjԖsqWXqj klȃ%*5gzNڔ2b40hC9eC[s4I#T}5Oe+!J2džO,y*}5cp #9ƑVvRO@b? O.5{ ['MbzU9 x࡞Y6]i\]{ EV-~6^p4c/&|ņ&iߏgC0 s CV'o_m8\3?@_DtU5 a0 f#k,Cy^K!45v*n8>ϺŇьģ͙h>B=iCˋq4zo0?>헉3ZeAl jqLo&"s+!+/1OE&\֝aH^b|cŕl4{G %`F# FmW6>AzäoߩĤω|jx(ȇY! 8hf'8yj$bJ6&+S\A6𱄘\[rMf_j2@ 5FJÅ+C,o~1x?`[IUPbW̍1& $|q)ILkTLplDQhiPB{Y!ڧ ,eHl"W0cQ*k >ll5FYQ\2/AW mݱ zxfhCQ5:þӸ'{nۦn\:QCEwSʳ|XxI~[^%vMg3 lpPʺㅹM,4jm%X8 k/oJuK8ȝ.H 6tvu!B%P΁ F ldsBu UQ}kx{`&6AORl6{ G2~q-MI8J}]I^NˆG鏇@ij-2F4M0K)9E\N_&߾c;>d͕"VV|<*]>;6C|qD.ʘꌳMA˹gzh V%|]yQ<{,1KFfeiKjWu4$D\?m gYe>'$ 'F}PQt9{l@wD0 !Ms2nb* 1HML-BAeX"Ĝ)y(R*XRXκ`3C(Qa2 hwSL8ISѴnӆʗY؅J%t$&ڇp P(IEqNr^oL7X[rPiDdTl^M]HyW 8+Tw@rW@\~6&P˧]u@l%)rׁ%yXΝ꘏ueGhہ :M@L>QƂyE/ Ss6-yXi8ǁ0|:_*׉ٻB>SiuA`~ª\oFmN?'مzԼYW{p,oUZ Fhwm:9:<sMDL.q=l(!o}4!s N _H^o82%G٦ܛ-p| h&4zDc(숙 Wr'( *=Lh ?áSVk.qn0".M6M<I/x3XkJQ_<@[So%yIp ~O8NU%3b,mn%cā>@݅p1C_pS}9?+ "'/ONϬs>C^]9^4>aѦl_y57to`(u.™e¡>k5=L찆KoJDÎ 1fEJA ncGJ%:w{ʩ"(q&'!Aְ5DI}&Ԇ)FIa4hgHK+pBwp5v,@gjގ;>6 YsDžY!&S8;Kңxf%M7`s77m:QqnNt}j1 XBK>ZٱC,f0 "FĵG6;œH0k䞔wU) 1iܹV^)em E)`˩y+<+^Xp4L~jUaKhBER9~<%@tJlNg^i#ʥ6Dʲz}HlڊpB P$OwxTTSD&Pq8Dm7LHj >iE,P g"2}8.Xl%8'(U2MݩVlO T8 M8)BsgHEƱHf8[Brn&}00ew K)_XyZ7y$Qm:*)DBC!ŝ $Gy lJ<5ZAWU?Clo{4I@<j5@@x( !>l,AR""R(S]=]ڮie鴟GD-k˞v2>{詧zdzǡk wgMps$?a8֞VkōV}wݪz{n`>Խl_uzޕ?_yuv۽ݾfoξkԮ9pz7'}ppc8TLG f8ߡ/_}W5ޗŵڳP "Am> w1>vRR_]nkm[͕Vcݾm;˯8t{%ŗva˺AaajBQ$``RYf"gd UฉzQo76V++qcOTF3,Re D}$QVˇE}W)e Or<0|Qv Ö(lhBg)% :~ `@1oQ%Pip@r!} 1)qZ#("DGgD a|5#",כ ^@6n P˙)R9|D3rI ) BԠ:HLHR0~?A'XRuc]7 éEEcg) :s S'cF g8%.]7LUΐP8?,T_XFGd3F.;HPîgv;9 3`Oi1@4c @.#Y]aL(剐iQ@0N/.P2JPk|`` \>?>{@;+WF@Miǖ&>|jxf&jMwA- Xۏz GǹIްhw{)a1 gdž-y}A*re,P׊NL J]-Κ!j/dsp &HTRCkg $`80T.NzճYRFL!FvajI󢠖2G(}QD]M(QҹR]ݨ:a> i\:"a\FTCՑ͛h傾  ]# RHhÒj؁ ЍZ*G=yWʱKq>ք&`h)Ήsq֬uo<&?7K`Ne-$ P;:MFDWձ;ɵ j9w8A)H)SxCfنuEUU6#@(OP%^A.|܋ p<$ynZϬ`*B8Jl[ric(S?'*҈3@Ѯu { R΄8 aUN&-6| "wT iW$:e0WH)G}^ Iꋘꕺ0Ts{㐧 B*gܷJ9^nG|G 0J!&w~y /!9s<Ю )æUlE SkX!9Y*UK8q>]r%p,8TD`vhR_=X)I`T6 hs% >g\^hĂOFe0=OC5 X~<.;䈺jtLi(RП0@+lt"tM)VIyJ"9Ў]:ݓ": JWԽMf:-l92$!9Pzk>{ W,\ bW?Rj|vQ<>E:|'&4BnNwg&HgS#n|y@W ;(M!=8i];*@6T~"+9A r; bD*q%i4 q mqDqy91 y+:@Pλ&PhfEar2ZJR yA=Q]>m&V\Rk{kK1UTP%dL[?)2M"@DFN!v$ 2zstQND > Teo;pH9r/뿀ΞqVJ$9q * iEr 9N|ߏ1@@WM XqZ9N%5009*}T&t>݄dDٕOȚКԺ:~[ ل w8 *+z=>S7]`ҮNu\X|vٟ\Y>-@d,g9Q'<7in!bn0j. pHRRe9i^>M'Dܽ7*<s"Q &8-/*з EV{`;q -GDod=mE\aAD4T@gevӪlxaۯ02gQ:{ r]NZ$:Ʌ?s+G< 9jպ /NU2kn<`FY#Z Y]&ϒ,Nk1ZMP ZVݧK||v Qg ЛVJB" dɅC/1BAsQvJ|]\j(mKTٵ!4K/7hYNsɲn0B0TeJR2s>6 !9-e1X6nzS7\ޙH3K NG6!h'&V:f˘ mijZRNjگ^;iT/ ٺ1Pۊ\٧PU"\*g' P|/ ͻPҵ"t_JI#޽ٶGC4 NJ4F[ }۱ѳ]>^q}mj <0@lX8nN顔AfD[HIP}רh v&n6%~HZyJ`b~>]gS< ٢JAAl#=F6Q(ɞީ#]HM k8tZ <.3#Ɔ֡[ Pɳ(گDP50^%8]qV*za4M흆)*OI*u;S4b{D!e{ٶ$P8S:p\@9t$] |֚ɰ]qA 3ZB' 0TYrLK>D!YQ_N_=|βf/ \Nf+., JѴK&Nfyp ug,ٯsႵ %"#&+}4e@@Q~:=uC,xC0ZP|y.& 0;FjCY] gD>(L96$f$ 7g9-8>N5m3?)mg?ϼuqČTUv;cAD>`b,Y+{Ia)}f=ᕷG61f{OW")yEyy. eȩFil?+totc']QV,PM"(/@;2Pq@ I@x5K(ŭ7v͑Fcط k*_X6YJI;;\ZI٪k^pĭ kK8RVNg`FB4{jNZFF&lŸ:i*^7:Cq@b bo0YSu ~:pd,2V4$I/r)I86pYfY`>I*!=K;#sL%$K ini619 ğ;ďM;kٹݝz~DܢDO|'H>w:4M[_„^݃JJb#$~tQ!jXRԇؐ BZ6nzM~A-O|7EP?aǢfHeH* YCm4#ZvXRak=D\-M_Y+H$N^h;Fq8N0m?@ zg # KEݾn'ܓ#.\Jņ:N˪=C+oLa}2G1ѾkwA{ " )n9\ZE8I'EF2Y7VjZo4{ʲ-qVGGNh‡,A'u;~T BWGK x8f -89OaOMz<\;C Uц7X]ubRೞ UopI9yA!H6{ PNA/t*R%׺eMY)k:*n˚u9)pδc RFd2=&Mf#aC}$8" xW,vӈЭD@* )N]QP!iG yb߃24Ug2B&y`trOhdSAUnVHy> q ClwO= Lat5|I5g`Qۢa uO RbWN^]:a)d,,P/АuA̜?'R<G,b<&] 78;p.TI(Yx3{̹Wȁe43Bgpr1ᐷi򖒈S 50;,q96<–%}#{ke1j '}UR \H~ r&"Ύ=t5}U޺O}`'j1DOzgtF Z֞3JdaЖҍd|Sb7 g4G~LިwʯI3XRTڰ#b䟩pBlې"3UhNUE]öE䩋dNKCy F\>ţ)ѼpR=j$*2 qB\IL^D ;4@l/PH>0 |ΐ'VAEQ"D\ؔOhѩn0&TB39ݥhh-mQ?}{Lxf!lę+ +@--F@BM79P'6uB!]ϯp ʉޅ>aB-/.*\5XS&1WRq-안 au$ bʹ̠fW1ڋF!KH F*V@ɶ ALzģt}}Z zPN rQu1l's܋ֵH'!H/ь}<;Ш#dC*p.q=PꟚ< {23maKBID6U0SipxgaFUU7ODG[.g᳿Ӯ8mK{y\EDʳo& ѵ<=KJ뼚JV#ٗN@ 'j_!s6L4D>"J FT\{ lb9OcfR Ey}kp^vMp\>A+lXBt!RR˄o#5m h>3]WC#WUE|x|ۡ5Evs|58mRY?/wӍj2akbynL֦Hc`;4L>i4dj|8bE[Iݸ4^˥ ne#mJi\$9b9hI/WY.mFw<:h$%BܵaZ2[e%|.@rX${hBd +6lkMʺT8B 7 B\2?0y;JA$m`&J&ѵ %lNamH> #9=,29' Da % =г}Lmb#|27D12UW/#ev$c`L 2z~gH/w>MH(&/|ݵe(ӂj,/)Z9S>ՈXA[O ! :{ڳIy<3GXMnLqQS n}N{J1&th2cFa ;{[7H\Bo<0kIgkY/{a<#.3#/(A f-F?]_gDwF e_[tR<[VP}qN. Aʄ^6y~2~ ]L\"7 $ @."3MFt5a*{Qt[I5RqW'C}X't@#4N}* R>pGLNr}3])N-J(Tii^ݬN%W <ݥyA$ခwPtw8)BCB"͝ eGY'`VHMdLn8}$K{7w$ {Mvly+OaIy((0$d Ҳ K(휛[g[k[kknlt龰iuvg{_so;W?jOnvfڵ9kWι9״A\zus:=$Q3wtBx|eSϨG1;'O-c5JԨEy]S'P8+2(&*rv"NT$)u4 *h֢3MhW(\]`8'zПI<,pqE>$@G'Nm0"g̀0Qm[\Zoln-l,ͧfck3]Zm6lViWj_ھ cwҽ}to{هA;!ă.zcj/ڨ?9\.4DGG̢`vbua Z7 )i56LMBz\(iUU^!c*%+D6 9\L7h- |aʮGp*,݃=C&3u]ep%Ո% ö́ ec/bd4`PT'S6)ۍӊx S lj0ijFx6gGn&Q] t1RȨ^Dn5) !b@?@7 x߇EeD(E=,A0GLP:AeT_ ~c;KK7gbnZYΆFY卭 ; oU8Q!E|5c$XO h\T Q Wx&H͜YY}Q)d!k'ϏZacz6(D$x f'}x~+@yP mjT?]c~跌$H¡bDkS!(OxYIs= fY&A؍j}ĂQQ{ME &8w(OVy|'! :Yk76+$_n"}Dg>oJ^AXFT|\ͯ೯) gTg}DQ+#*hhaAM&Iᰓ:Ŝ5^ $c"l͉]yBW ;9aH踞z\'`\ yx>Qmha"?.%R{եyqgcizAp& ]iA1PLtkxS[\%fs΍y68;?Jf|Nr8rv _Q2hia|l(fR=4mηv|Q9ތ b5fR D '!#㳟Iܼ8{iR fOj(OTz)P2 pOZkח늾1c}# l9@Y  mCe%}c8pXT@?Xʮf< C6F=S$rH,/ztz;ht c(DDQώ9e> bc82a<;VhG6Vk+:wV9 {ҭBT>0'nc9JEpxtE I$'4pk"|X$F}~4ڪ93+U8dVfA'BPOaivRE[43EU#xf9=,ehBu癄y*g4}P'y!Dy M^o4V{0.yq.P &<FYY Hl*Г ziYϜNHO4҈x*"gDƩ : lp p82Y$1c#yx h_{y;tҪ'ʠ~,]$v;n!i# IL<Y?hPcJ} ?HB$}.\}ȩuhá`sUvA\6qB5;vajsy:O;B'LpnQ;c٧qb0,pi%8;ݚt?W8O)ܙy~xHCcЛᎹawHDzDr1> Hq!%([5Q.HW9%XyҔS:y:DV R{7(M7(E =݆&/ -5iC@ {&c4u 8+w|Fl"1e^KM%"ת )D0"8hR fDHD|d&zq 8" ) i@hj k4ev[$wk83.Y ekW+)|];&oaM s>cd ;p~ {}>Dt!udJ'sGwڀH: IۅL`BI0zXB+9wn.5~r1ӮDl4dlH!J($:hxheIrĠ&|Әc8 k.V5;:IZR}hҥƤMէ #0 h={q!uZq+""] e r"$i'DmM]_zk8#~bU~J8Q=bj1E<5]PaτFќϾj<ߞ9J3R`ʻ#iEV,r7_Ŝ;3OCE\M 9(w4  I:s>tAAڡjCu@0 Œ ̃S(9q WH $a$Iz4V\q4p9_Kitj(Q?MYz`;bW: A( eѕPl=.SB[1?a$g"Avlf(hl8RvsGfL;ǍDžb}blEH@:Yv^ov.OZБΛ'.<,(%4@P1P܀R&ucD:[54kFga4p8LF&_A%:e,ģ5tv4\Ñ"OBRr5nnyt+As:&sl$/LBFtzoE#V ]Ig^n GsB8dV8↵QT4ۃ@V|.PbuD>,Asm8*xajK=| BDK?G0 GkpDΐpT(jEi,Xj8 .q'(Ruׇ w{%tH[%;prs [qc%b Jn -kLe|Y\H} PU#%/Z$ 4>Y"'3}|*k%Vp몀@-my]|ñJKhc't㎗Mb]|[Ñ&B/[˧~Aԧ%ՙZ y Ʃ+fz<+zL:g$#Bo#6+fM~Xyy(, FsP]l N@+jF[ud+hZ +ǗѰ90 HtQ!lr (#V%,D%_.ݨZ~ X">r <yZ~ɾL >8?tÑhJi_F]ƪ'jR%H[MVmAm,ԞUsp46[}?K2-ᐖ;Z%Q2cVpX Aj2,p6;N\Cټ2M$H|iBA@KGD @+j(K5_ edE}Z7TC8rwg{tIXe1ID79"5cRHpe8/>d75f MֲԂq'_ܤ: ۔RPx= [ihQ{}dC688ތ`nZF^n"^*:0=Ǹێ{}?pV-g~I4#T,׼ǪvGГs/%b9ԗFO*$Lrqv*GDcG~*F ѐ,9H ^(˦k&[TØ<:RoQs侱dhk؊k ˮKG-4:3-'bl"٨4c,KtJsmNwٟW_,.IJ.W?ʛT=cW|٪MG3ٷRjbA07sB%Á(/~a 𣼡向I^gnjӶa Fi+MrAqUKZ_R=Fs CҼsl`g(α - E~N i-AYo Lp1_n,Es3u"qg >E`1MlJ|j.͘6d<9l\2፷}8VN ecDb)Rm8=壶3ecW1m5;tҙ Su-i[X1>&zqf=T8g"F秘Extz͇ʫ=j m)Z++ 8q|AXԹ0@lRڙ{h 2*vͨlEh۹69{4.qL+ ɆACz),ݣq꾉^md@S{faj-:U(h8[](i%.-/k\Tkeuʇ*BUam?b4$[ۼ%ʅ^Ȉt$=nj C`1en7)JنÊrA"%sU v^Mҩu:f ]84kMÅΑ-i{K]g!E@CUZs`®V qy}Xp5A'SK##FȣKR4qeV1tH"'yb,cRO~㤂3#6G884i=yq P"fP),:O%iV}nʑދ#HrE_ FmBC"ŝyeUy'ewuU^*Mb{PAd 0 o%eiTpIB^FQA ZeL TMPtf4kRȢ$ 9.=}{NQWwL#srqV4 ɝ9s/; y'ee t׸xo=]jDvڷ۞nn^ln;C/ЕΕq'n;N@f'>ıG:ӽ皫{E=5훯w4K@wax%()v2ڜ%<`HΨ+bzxF.rv (3 +ӔinR3%L&g0(L;;6U1Rt} Qp'}]j ס4|Rf4@?<}$g`MlMNtЋ/}0l"z'>9y  ֕䯯gܗ+ vqZO,qҹ}* t}X#fw]_Y# ktVWn}$$G`Bz19{2sa]3JTJC<r= 9l88 "'n-:Sbv%:4gXsU;7Xt~K3[⢢Fuԃne'?`v$ڋ@$>1t&ԣg2K3TTrӰ핕1 kc"c7 E1RX3τ(Tzz#3%9H&4Mpu4"K5ɒ @.pn[QPғ/y%=3 \Rs!rb%I.gF$XY^(4sZ(IU@vEUSy369;db!`l٬+p.K)4%g0 MLX4yB Ӵ[ :rs%vIG4DsGaS%r  AhI6j$Q, .oOCf099>x;U|4 EȒoַu8~-q]C#_ٓ~l Y|Ͽ#DwVBxt]J'8 ٜNs϶9PV?]7Xx궣'4Ms4(nf 88{x2of%z9TUrTC$RlզJk  "%ivUe ].ଭ"7L[Vӎ⽀286Hn,LX_όE$ 'Q ځ>r!a5W<)܎SٛdH4$"l_DT<ƷZc"sy&9dX08BxMĴ''"v <|IHkh-e^9¬cr:KΙP!$@ܗ9S;rʚx@@q%U3?n|^>I^24}J7)ژ:9ZI0'H_`Ԍ1#`EϠ7nzsRU$^dB&lg8[ppɷH4pϕ@'Pܕ$Pw 2ڦP+ +P{.Rq.7 X 1oZ5/IuS%@ERH!,*у8a-OpQ`cAM`0@d:te&Lb61N7UЎ .֔}pcT)(R 2ym@i5#4xm;˂ٱH4ueO&a(4צV` @H{XHp0V03*'<'1^*}jKξkB+ϑs2g%~ ʣ'Ҫ,=o8 ZmAa]QU4lpo F!XAV*%kL.O.vCn@>kD9#=Ԗ8R"Z $H:6R0vJGyvg:^^%'#4 u/ k+-+ Aq '0v;Gy lDBBzoe <0B2Zߨ#LEWᬒWY_pf[¡W(A %61G+3icGU[wBkDd;hỽo>cn ` 1(hT&{p5eU wn.D\i!!\k ARJ :cAH\"s43 0@lz 0lS+m@yAH&gTlOUxIKۘ7RIE^вZc3a"0w9!e}kքlCg⽉ք a)ō*ӺM̓^槮@YZ0xBu(xqi&ΔH.IbUB3 DG7 !o/P"PkitW)_7V8eǁ$ՙ XrFM r3f+{aiL.w]MÈk#(uR Cap5GYπXjoRpZ8ل7gJ$t90!GuA!5-K(dO+Bb@o g3$^ݪdLs%Nv×PAi0ς u7.r*WL ];#^]x!cL&g&LG.NTp>hҤDq| 9[":߈Fch`*xDz_&ёʃP zL SgP)uQ&m8i?+LxyVCqQIP'Dx]DxTExyӔ%=x&m=3!,Y\>ֲC߮„$q% 9zR#ޕ7^z`!4]If`,FM𗆟 qU/FnR:fzƬE &@Z%hlYdmmy D-AlGB ʂݞ3|{F0‘754hEX]5slj$5]M&.|>Qf |C f@S?3ri:1zS i0[N> jiCJ% _5zlTZF$=JӤt|V% ec"Y8.pwV6,(]= 8_vcm֙Tk>(?n 5LfwS>yTRjf;|{MZ.BA׿{p~bJLPhvGyX}M'LVqFpyEFIu뽁l $-8ˍ R1Hu?mR-BD꘭v{FI}Z$)h2De]@C !- Y g5L[JG[q1zF_Vq(y@@YiM|R{mY'rC5<+D:f=dAk` b(-MF-1(d Օn#e| р5!+(Cnh)٨K_q6?S4^6ۓ0!#}2ݦhmY~bQ#L1zb<ڶzAAW‰F,Ibd:Rx%ϪCTԇbV,h_ztOqcr EaŖ|mmÂ%vtD:)<3W3:e<5NWd-E"g7z=P$[,ѠS˽u81trZ/ *q9 n <1zOKr="3v_=@ӎ"zNW;' Ht#U8FF3?aM0)؆ی\! x!R_M 4_Y6xh`q7^ NrVWzYA\YC8i_&ode>`l w9se[>;ĩz~{JB5RZ'ZHvY-A'8-d<{z  W=Mbکx؍UdW~r> KV7ᙲᢖ=6̞caI 2h2a(pѝu,ZD`GBӬ%?0dHOHH4A ѝssα&18;q]WЗ"os'98VyxY*KV.t5&3oOfqߜKvV) p^®Q>hiGe˒r!cͺ,(<<+) .g8bת<~5j$CԄ*EkM%E^h1ʹyRcsnZ\(@b;@HsuTI޻lBxbE9˄]9˳Of~r.#q+h0*#{L0|,3?<0y|ڨRE@B( !0ǡ?mvryKDme 'VQ4@1{6DFAEH*rN8/ΪirLIgeHM_U8nb qHsr`X [Pԑ?0T4צCB=P˿AIb\ιy+]:ɷ_H% mp(岷 fMb p!4jdBWYBӯLpr6p 9ͪJfoדho O#Om1%FF(ō>^( ,.GI{M~z#Ѵ$4K]k+lu# ʧ#9ڬ#cjVBǻϪxRGù~ʙC梿4;!gwPxb[:IJ aLWfiTbƊW!HׅHF$i{ؿeJ 9EՌS'y0(s1RՕ",2Q,HF/WH6|A yCJ9o~|\E5AsUWr(ƣ&@d qZg,bEJ8,bwiJEC%AmRք-8 }ZN`!%fDv8v]༽ X 5Q3&%4wUIBh9t٪JN6 f8ʵqrXzt||O_yps [=6ʇ8Ͼ@'z~,`+RbL{M޹ @ZPv4qDNt}F{W}@''KHc v.2v|dfnM"2VBʗgF<6x"sW/ʳ*)8ƨ,hyR:uS&uE+Wgjw0k|䨺VvK-]WI|M޻S@2lټKAewgreםv(_캺نtJ~_ARwɭpvNtQ;txuAJ;ivf)u:{z%LגCFL TǤsU}ldv[f,{Fِ+ÅШ=az LR|m a]UFBCj"͝yeWYL(g[v(VYIfn׹=I%JedfV) !xM4 0"*`Y E2d$*BRqxν羳;=P'UI[<\DzH{_k؂e$k6=?'}Nz%c?AZOJ+viwyy 3]^^8nlt+m^y8^vf\qvw77n7Mk:t]{MuMﵒ[K/pE^n8 pf8g+pvkmp@358NЉ2}6@Q ɧJ>E>dAxX2`!8]ϑXᄒ'f$Δ (M3j9z;;uq'x 8e(j}o|.9>v76ɯM77.Orngc= ! hYS% ⧽x:_rI#rq3p:Iq6GH8"J-,%")w_W Dgѭ5ĄEk%j}ymc{w'Y;LwIlT%Pӗ lvvP kSE 3*&-<[*7f 953oA@d8(3Q !?54|P9z&;6yUm 3&qR4 ?/g*Tu!B,d5\2Up`,';jӄ?D5U_8/HQPN%rmEP``` eBQ&HezܼW@.8rf<6{589{omHi±7YwN#&iO r<1a u'̱ʼnMeri@p07VDF9>dŁO&o|#cYY!Ur ؃@8X ه&L@(33)9hm$X>b@43R$/"DA Jc":{ 9Tm,Eg"#gt=h]}=i P͊"/ՅAV \iZȲMLKEq4J`P1(GK@3\4v?j"a "}!g lE1+Š|Yьf:Pnxb"q型[Ka6" `0h:P&5Vf#V5yC md|byq$DoK "ȉkL/I nC`%EF۬k@Q[;UBjj#EB{? dq.(AB7LYM+AT){U-?Dْpq2#)x؋»u=$4}\Iyd;ˋ< J?/%gúBvW"c4nd-^ZwUV>(Yr 8cOnԺn:K=k9s/|" YA b4YM~ƊS "b =1ʖFgL_Th PG4k \}68h\H3)q1|~ު2E|9 6ۅQWÔap1Q32W{:ђ+BE"l6&'A}9ժLCBOobH}.@/-g0(~ >Sڄ25i$gላB:*`Zc) f,׾w6h1,/oy}+nAxJ$ ~E Qmv8">ܚhs^|9匇 1j*8hg9#lT^bOҰ(hvd9}n /ˇjͨv<+0761g4hq>IMFDǃ?l5,8us"@N8H9?d QF$z9B6P{: :|]f++B~ y.#gO9$CVul~83 ]Mr֎ 't] r2W`{YN$D=͚Ιn%gZ`@.!XR[ixW640hp_>` x 0=N}lۆ&RT: Q9ZSc _;^p\28r7V稔❵J^"3Ab:VgCΧ 8j.GE1hVd& @Hζ,| [mhO6@XV!˽oͽn)}B3'q(g:p".:^{eFa0"*uz9{ NIG 9QKB#oDp0A@br[6Di^ hǹ|(PmH^~\8 u}΂'EOx@**:Rm7`wpM&89 [^м9h^vê2+&krv B#Ӈu_"hVjo X+u.*̭%8]Hy%vA#u7o֞ V2Uv.b=j75͑rw,Ǜ(E?"`YU*wQ# YopvdfL`!t\+\O/lɋV[rؽ!1v{ L` wjOP=1B$G2ߝR f M~-xqaC[,^C^\ K;Eu zzeq#+4rV=QLYO7؀I?wU/.UdMHX+y$LA-O x%OL29{܆ȗwAĮ-D[dxN[a;a5+3(QPѸ߹`2Wv]몬 5.p~vl(?Ѱf!M6J&$gt2D hc\"I@O"ǚа8u+h:7=j;m@˲5Gu-u~su7]R/^`[ w8 C9)4>Ѭ013e/Iep J ,AxR07X 3KHfm2nh!6;1$\BV &@jJ]c!K5ea }η7 ߡQ8Z {MljQh-FF|"˷r=m{Pn; ,/y1B2+ftY5X{5c}?Q ѡD0#A$ aYQp4?~8]#vXk*WAttUy nj2wБӆ<]Aw MsɒSW1'D9W85$ݧ5殱" ų\h]q" ELBjӭ # ]cV\F==]o1(CcO**kCʬhʿaEb׬* t~ݵ8{w}֩7HTg(Pq1n^:*1SUı{&3 PY%K[7(^Zp ]C=E/[ReEf.S嬆ײ\#Gи g!N1=_,! ߋ.i7OoQ& Zڴ`\F'IjJbn m" DH.*@Ǟi.׹JsOawVo |A k+b(f0x9{QmZ/䓏 |psyI8`Ko|ݦ6B0^f4/lY׼=Eba8*pY?! 5HqeK<Hu %Tޢ"}p};9;fC䋺!P{s_cC'-S.~V+{7*}ڑ`;JӼ0 dLx ꖷB ϚNK%|Qwo>mѪ|8,Ù6b8}9<9D.{ l#RNC7|js[G 3L< >#VMd4=yt}Rl,sM3u0ٌR}+LL1מ& *U.9N<ɐM>k5!tCjT= >1%'c9Tx.9]]HBڪēKO `8s[GCy7t}"Gj?L7MuFS#̯-yr15ʋeTW9pt؆Ȼ!KL[(w(!1f) ~CK{ wZd0h;4Nhq "lByfG@5[4Azfj9pxdj Hz "#* S]po<gv`4kh'ȓ Z H,0,/@hͅx2=r27طMfP˪έz͡&g#g 6~S_(N,1[H9o=HKĆ 6^048IC=Dy+/u&0\ Q-`CdW4盄گ߈S܅:Ov ",Ԧ %9nE"gI4UɟL)@=8&:a4 (WLgP7pm[Xb?2-6W67'6(^aB"@/  q61N6&J8Dp=uE?[#/4 ( u@e9п?dag\**6zX2U(pZ/ AEs^Ñw2nGP?plti> ж T,5f!.#k;`A++r+'go=HԮJC'e0 Rt$JHȂ+ N]T~=G&TŭkQh<'w!}> y {QJ}w ү.5H%w^w{͑ zp5qzKf4Rv!"?+Pv$Д. DkmP:MZg~תd"b((Nsm~+GpqNwEU+Bo)j#.jiIL&3V+%22IK`t{T/Wd"l%:D !ӑD}]%^cWDpMO=/Dl[ pc@a)zwNMW=CH"Rgn\mMDڏQ"(_$ʨ*=b,nGQ$H7Ieћ,ֵQ@᡿`8\Do@8 å%GNـqG_>X0Wu3V/(YPjWΪ%4N~n\_?kAՂqT'T|Iyڵ$5ոĩM]o[^zmпX fZMo9"XKj * ѯמBH*[DV~`=J<}d! {86O0S\LZ bcL\,W(YAh᢫LSg  'l OgQTt FoH"s"}I@:_ٝ5tO@I`fJXqNV8\HOb=_(t(֗,X9ج gKlz8ʴ#jGYZn{{&4| kVe9hב J$;38p!D6#}DžHɅʢz"{yQˢt-L4f`SU<ܱd*Ba U _wGNmI!g߶ ByM#H %gW-;V*XH^! sP6ʹ2eW-LSZ@v\8F‘*VD9f_>|yyM>ʹM*Mm;$Jfdkbkm`,3 g9Ȋ&ϧo|6HHz1#}QpbqSN*D Ha8I^AΎ agVe'JߎU K;c(/qPrw?"J~rk݆Q/Yq" Q^k9{|+ %P0bo[lxb$eh23u6toj6t鏵Z? =sZ3u*SuyfD,Xx hkku<eL9"Ftn<|BI q*d=tgo $*v!rC'_VyOIkZCkI qux\hע-*8~⚮8 3 *p9T#un4Ztu8Նv8%[y}\ j#$jH$ga9sY6"&=i${s}`ڤsE'}^tn׭iqn<)!B~ )滄gJqJ4h/?9(#8/3';4 ƃ44Wbs <4  saJ@sG-,q4Mh2 `Y( kz6Aj6/'zcILط\ ~L! )׉)cxݦ\R~z28j"XkVrUU>G$ ?B8Jt"{12R5јHAOwNd1%}0 8nnh_W6z i0De48#z~`ԅ@ϥ@";cO3D| uzJL ?+B")B8710-j[_!<9ʊ~ :D)Ӄp0/,2=wD)ŒK)ptY^Mվ?X rH!a@4Ã0YH<QSJ"q&?Dd&R@͢8JZ h ~39cwtT;asLt0.9r ~HPjugLKBU&AoȸE++ "ՅMm`($>Ikh3=% q" Rn3Rk $w޻NE%||b {.0?`rm7i'6M#%OdZ ӌ}bp(iͩA?X戮>J'1c %/Gh0x,,;,G"Bi" (}Bd{C79=Dd!X G%hF`q<}oplWj7}ŐˊA$Gz!$0)1*WBDUtAhv*Kk4(&+/W%0ACZ&S Dꨚz&>aZ晞g$Rke UZ]z%8j Q]\5VDm.'N x5(e}(C  hӇ.겾gTq)S>KqBk#-gS髉k ~n$crϣ%y'nyxJԜ,]^~DFaXc.NdlCyxdzi.ԃQwh}<s>?,9HO2" R(\/lpꇨ(*<~eajIO?-NBw F;F1bqz8;h[Vm!_cfk?%0o4 3c7lW5&P_Sq»6*HgӸD)#E"{qs)*8#mB┈+ۅ?>U]"=hv,2.niԻ{HpB3JvdG1W4fG>l\`~Pły8 ,QBV{*Kq'M o{}UxG A2(Zl'f x5N*8QSK &c':I J jqa{,2+-a 7]Rq9v{ON뫜PLG4I]5! ސm;=&Sw)LVO7hK}!pG,>jUP7j+{9ĉ4qCoT~~m#K06|׻QJ*sY 8ެ{eEMd]2wLx4}ݤ&@zX⓼V%o겥 /Տ|#ou64@|~(^Φ5kpB},L\Ҥ-{7ϫ +Y,X~ԡ)_Y 8l1@Aw}Z]7w"{( = tV'%(JBQ͇;6_aoLE-nnQM=b'MSq4!Yz&!cXLѤu+Z1Ϙդ?y+#U"~Wu"vh碢jD&B\e?pIy[V^I՞ gٶUJZV,5WL(nЩHه=y*Y"RxLђd\gH{]Y))LZ"qDw~C :~*k-Ot#gyIҡirV{᜾[i">ô7ibcV+H[E xWy]NҦ& X7S lNEt ^/\:S۱'e4OGJ"{ oegъKetK%Dt+"1qx8D0-7^uaHwsL)na7nlD+؅׍k . fV¼Z;.Ӹf!!뱩yI gI=En7N|(;HNOgS(h;US>R`aIbj*Z~QtUS2ഔ7S+Md_1^ራ w{;Y;sQ{x5 @;9k,F i>!D tͭJ4} $(QDos<'av=45ju%op-6hfNE4 Z@zQ;-kÅT6t\L7!e8+ky\t;3'0WNqMPGtՓػ!$RGpc;q mLӣ+qz*ߛRgR=ңtD7Zw xCa_'f4U tRb ALP( 0ˏճpBTT5=iN)1Y6P8Pj$8\ttJO CZ>Rbv%Ҙ d☌lhO;68XBh:з%6iD66^S(5H^u`ؒA_g].}r$brj?^zCoT1 ڇ9f쯈]aK3B ܌hB+4 lpn\pjiqw%D#"ΆbaߟbB{E/AAXD^(7*M4R@px l (KYy"t@ta+ UC't:P$XEK;bC=;jJ"vA/sG,A(vJvSGq@Pr-&٦ \JRZkzy`1(ęZ44PʌSV4c;Ec^! X/ъӾBt f;™/m `)CdAX<~9ܝ}ܙ5o8=Y ȱ#b+ or(J(' [+!CNv7k)y,O)5Zv'eǣБ7Y- P *Q .mp4ѼKW{\t I J_oэ sSl픑{3loP%7"| w1C?ŠPqI'|n"{ K6$9~٨>$e)3BE`g? 9z]gj''Ryr+ 'A}9夒h'wXE^wU˳+݈%1]%ԙ^iM6Cy%rQF-x>hE  ǬQ,jiT us-Byd3wYAlֽ@ġ\#h6Z4^t]_ѹ/N7o]K=~RRυm(8ء鱝USKl4>/Q"$tM@ .+@\Ln@hM衝 &oϻ条 U !:P.otۥ@> ~aBʌ Th{-@R{Pñ٫mB-GsI%"q ټ 1dO(ະ9ؒ0>6(1Epuq|pJك6P~, C/)]I 3HډMF0 x,C  j#VݪxĶ4 OKEh5MM"[θV)Z[%$(@l(È-MuGPԅ]0㝴-ej%h<,96<5 64X=G+pV]Ic/FŠHlϏzq j>iCjv#q. fLJw[w/>a~|z' L7c:-MӁz0Npe?mxp$D |8RVﵲHB:*_rns>7[aՈuk2HA+`rb(VH BƼS-e-|>"iGz e*6ଈ{nFF@ɉ  QpY8p)q(ߑA/!F"j$'^5}c9> }0eŦOd2A Դ}m"BjB Q@d6&܂6ΏQԡ%PiMh`|)nw{25"1 VhgNS8}јl-o8vmsxS_ K>ʿ8xQ1B968!,bڡӨp}6B$̧w4 Q  :3b퓚 "}cS͍ݶB~٪\VTR'56zoc zk8aY+oj&>Fr8*_n; JNkeNѬh< ե#;Ye ` ;W:I6w.OQn(s^r( B ka%r9˪$1Kp)J&ٝQx*"ٲ j&'rtrD*=rvGe0 P@<HeT( cuA 4.1(\QI cX C$J^#X"gTf8jc l@I%ǧid](/&gg*sɅyx(F1 HҍbQt @&gU  D+K@BgyJc=Vƃ8^߯P- u;zn;P5Z#IJrkV@a1R]p=`.8xH[6c^4x"@G4BYu˺XR٤Kv%d~ gwc8rN=1f.YVZZڈFZ.o,..v:K/;p{9aEw}k~Bȿ&[ ҭSGKć.IEinzra⤏ie^F`e0b,3%7RR"f"1 1IV8 2P`j*WiWZAA=\Br'x;Qcrl}'LRăf#YBӃĔ˙>Of9ba \Ѧ-CnTˉ}ńͮX0ҝ"g6 D:дx7B)Dy47V fv83ΘSvWZb->B/G8*߄U|'N)T[u(G9K!W  ҘQlHQ-$ MS 01_[i~Qx;jqMT&ٟTnļ`2>;3[* ^>ql g_\fO<5ZS*YH zQAgЌ 8B")RM!шhFQQ%^.-=hTŞ(TmV%9D/W&1筳 +a)O"g~jx "JyP[(--׏N!}BtT>PKM#z ѴbVrBή3!r]a'"'jAή78s*ײH`JRldD܂¸D>0M#u&@(!0F% ׶!! #:ml( `;CԚQ {ه <N0ZRV~~.vuH&FyD%oIvSBIAVCg4**\/Np(VQɒ.WK+ <EJײcF(< I א*s蔾۟PtshfDBjn["poS70TBT5 d|Pr͕ܖpz8 O$ӧx5BLʞp" я]Zn֯ F@b8.m)k} r=ë~"1BUBQԬD=L^v:cIQZ[lG2+# 1c i>O'ա܎J 싓;De?:7BN OS6VmN^ P<1&ar*@LBkn"DF GkxFyԡܶ'"ԃ^s 9W{ <Őh&g``炣:+9yo8g846e^?hYzF=AʽivWvhv4='fwACsUS_%g>q& κR,=1U2 9qq y:DmH֒Č<2Q1ppEE[C+(\f3쉊=ITz^lzr$,! hӎ`31_8^G^`*ùܠD G)2i *Eʝ&gL|,Hh' Vq܈F FH\GU߫9Zy R nC nj<&(f#, ~Y'<HB)ƃ-r^ L"g3XڋվW'4W.h4.:I#=6i%8GMAGSZ͙$LWWežw r!q\WMSAL_3 f{"SPy,&Mf1dIjz\LYkT̓h0oet.[NïqgP:NK+ϒߩ;.|Բ,ĔPsꍔ;+a·Z繑V(swQ9㪍LJ8öɮ<`ufQ JZ_/oQ.S}2('ute d1A0)#-Gi+UFT !57.{t0I`k 2.6?V&/USFUT։\!`UvBca|os ѰĝD&'պD{XFN/M86dH✪91`ؠꓬ"*9D N ‹PRv յD v҇lp@7\AV8"rM{TND?"hBܽ„* aX:-}{u_"go7 O(LXw:@-Gy\roϚaô"Ѵyn "n'(;;47b' D"w|?;M<,EElMSQaU:qR#?t!Wmj6.ө '5j W"t'D'݊o ȥPC}F$g}# ik[ '5bE>ӊ JM@dM#!Lʹʵ]1=-pߏ~zQ:O V( s68;遑?tT[8Tw8ErV"RuM2eJl퓨AjaL0I`(ofdWsLN|Eζ+׌!Wddh8kڶT ᥜ"FRc\%ղHfnՏWQ\VNU<խ}[=|p/WepC kdIZ?(rziJ}̄*B?dyBz*a5fp"5PgVpuYxܺ"0{jhOGNOV4.7QI`0ԴvWX}n:G/[ 9.-z ɪG"+Fu$EE Ș6dl=$:!6='sqvjo)t]wYw~֋GY7,v3W|Q(oyyqKt'dK!MeTI7҈]^ǃ /ٻ hGXDIϚ4DW?][N4nFVF) \~c0rW?ey(~ 4؜zł^ [U&6bqe"wk7DArr}A1O|wCui}ӱY7InXW\L/0{k }%ձ;FDRPqN4A4v!mU&.uf!d82^G_YfFkw$!c]:3т0vqm(]u1P4RiQ<>bWro'gך yt=*W>H~.Nk~ G$X0YK|1q 2gT=(~vsֶ2p}ĄIkd4Y; %WR:szFP %9Вtc] ӡozTRo cRT!iQvg[M槟_F 8NR[ idi4X+mK싻MGCF4bu1f%tCO|)Cs On6/7<|o'tӕ+x/k%+s7[#*(ֹXF;n.Ƅ Š 2jZP: =:񼋜1|T:xg:|}܀C҆`0O[YlgH|`A 6YCnl`fi\*yg5zz}W+UJr#qkJnobᨒ5llBKn0 ioeӛ: 7 pvDMDxR/ %/u)!wf֦TF @¹ 5WӍ米xA(2sP0%<(i8-SUe:4bX9Ͽl\Ώsxj C8L*߬ ;9TVI0ߖ DXNUfI#ԃ,3˩ 1ߦN, }>,|K˜7S黽t9wpO e&i$S:rﳏVHm-/FJaD.<:=u&wxJ:Ngw@{閚t^EHcx&94X{ijm?ʻ6͝/ʣۮgY6tvBÛ%2Ll7wNcsM;*cy\Exv$_#g+/NAl2̙.,N3nIR.}njx$2t,Wf)fܬóXJ:u/ꦒٲbټ^GKu7`_˫%cgqzƫF<5mXp#iDf8 m;XNkoM]'Y$ xNJکpWYr|= ߝ4Xqjij1%p Axө HPP"g0"KlQuU C K0M4Q5I,e LZܚMJ#Eh2j ⷗8H+E>%=5ApWny { \p1wupB'Tō$Ⴇd:I E>Sf=0< g.8jP',|V>YH/ |pre;W"*FrCzHƉ(['a&e:ơjB#'1)͔Ѹ.m"i+xȾGZMۚh[W<u &!co3{qx Ҍxos5ŽP&:pyhM![ޔhVl$d#ZǕ$o%p)R?HmQ`uB(%WIk9kj?9 kWy] 13M49{qT KriO"%;ӳ%DwA$ Mhe٪5}t Sezd _u!$Ѽ`NHC>m'J1]! ˪.;⪉*T17Q7 /X{ABaz'U`%$&ieQD:ؼl!&4&nRΠ,?IMh.Ls3wx.bgDpn8rQ̋Wsyd`x$IUT i׀=5,s,HsgQ:- ܣW"'8'*ʺ00V4k5EZW# wOw̘C-]LlKĦ%8tFqv_:6W 8'eTy8ubB Ƴְ܃]r\`4& _fJ+@j|L-b=˄"t7sZ/Y:%y r/\'- ߝODy 9{Ce>:>CZz};41JOv?;//1C_3Scz[0k: ͛*Z%]%Q.~2C t˝!µ"AIm"_*l#T6#'Tڵ ݯ&_@LSՕ؍5ڨ_88(*Cdת{ؼTKk.S2<,+Äb0Jb;}JsL!՗Tgq/-{ xw ݱ;QY%g<866?l&H] e,gʥO\˭_~ɠی& !O-_A?}_*QFO{M~k41vr==gZg`tU 9j8A+IVC&%EKsKTl}\Q>wPH$@ [IrO"⋠;4Pr=Bd}Ly O5h<լ 8TIE!?E\ޕAAek$K|蕦 ,ygd2z|a"ٷ'J^.7YϺ]mvNTb20/6#TdЗ&-o\vh.|FHt+ -e/1GNb@7.䣖ڽh&_ h^ Tj7r3{Q? *1nN(;F(+dK\,5pЉ*ňL~4] QI(uq}=ϵgc#@]fWz0wC6.1\=2[``vApNZ=Vrрtۀ(Hx>nA}]>(=>㴭^BABQ#F?XH0ڞVU:@h~҈Gڋд*!?Jk; ѓ3&D.oVbBjڠ.98a]|g׫BC!͝{Wy ojۺ<993C0u@|؉}_ )%,(%JS} 'ZRRR*ATHϙ9sfvιWM%";|Ff=_9q.*ch_s?P Lgyq^N<0QҝRsa649ϭmWVZW`_>iwZ;}v{O{Jtםkv㚫[7^#>:v])x1N BA ΆCz1DJPQKD JπN @HcP1+ ?SNǫS1Kԓ1aCeAzwapDJ>CewYI=OC,mp🣞/8ar}eAD 0tTt]hqfLt *DDZ p5R5EDQ V#WSvg{ʞE}`Wo[++ޕjQ1-u`r7TN*{ueU}(9/잛[YXZZl--,RAT Tֵ U$Լ (X *[ PBGXٝΤm츆V Q fAo #~.#OBD%-}~xDnuPvJ%*{=I& _iҟߟ MqycCj3:qYDSafs8Iʼn~ t=n) X=з2.P:а̵T=z Fciv@Hp-`mZQ}I9D ϟSDED <>QV}*i=]Eh $B89lT[PT_Cþ'7T`(fSx\;V8rIVqzC${2{$Ά( Z0(QAyi*{ N4(H1z]xE9-@r bRAy8X,mz3^ZyÉ%1lu*{ wd3%8?/@9pbG8Y[3FۀJT=*TTG}xEZh[]V%ioL\*j|Hs9FٙVb[Vo( 9嬰P ũ#񉾡R+SsT٪8nw )a%N ;;ȹs84&z=Tk B-WG9Q 웕$aBW hWQ[KHʕŒM&Q Btq[DB{)UN:EṖmC)6q'I&H mqbPz(efmVU L/ j(Y?+4Tɨ"leh keD=[m",ؠ#WDEgFkC442VHt&(5 &55Dv;a]W`GS1#Zdru:` ' Thr>eC{WޔB! rz:κK I'-u(Ѹjdp(:MF&)vC"z&kK<{*`$&GPR҆jss##EI+%;*W @ájtM<[/fH%mk 8ၒWL++- z^Le_i0* })]e ̪ZuRl&T=DbsL_*=?g#ϢgQG3iX:Z iwT_E~1#)]Ee\BHrrA\KeY@q((6㴠z!*\[U*ҒC6+@ }QٓA@0=$cm%ڙQc|6]ɚcӃ1VWfN2?~aTQ5 $>LgJ[GNhi4}o:8zgvC6*xb"㬸IC 6)裳6(vL7@ц2V(9hx,tDs&(6Gs T$J-|Jñ%CEHu f <ʿ"~!lSRIGK\)#} GlOO1 >Sr!4=6/=bEJQ4rKK] HLc: -ʜR&P#5lK0"u)Q8Sㆬ4wLWoE$񸇔)Jge8wR‰R1&u&, SћG&\8' A1Nq)N>|%-:i*W"MX, +do2k#8A"ڮL3x4m[(g'*{ЊIus?需Ce_ `*4Cr%O-h\#4e NTڑ ^鑺`䶫uN }LKLy5VPCA?C١:7'-בs#\g08oJ4@e]&&fx;pD2}2MЈE`ϒC(JKշSAAŻy $,"9;_?lPv A!8-4ޖ>>QYmϣTn#{LFG5)kTaCCEVFZ 29g6Dʽ?S@]A îF#:T% B9Γ;q~BqC@ 8+nq lNWMD?DU&"BsWsQ;Pىʃܞ S1[?а˸l'2 AQ|~z}#ҾZđ@"i++7MFʾʾ#>WӦ]T!G2xtGYy!QYymTpHz@jyt9PLeRՀ b"걱|5|}Ad 3ow֨lņ.FNG?^AyB pi|?DϘb*ڑ 12|M&j+  fsŃp7]ʯFLzz6@#wD Cz Tn "N)@NBTZnd4D2c&}1aũS!s(g+KY0J$ICNL.Cx4.粿hUk=xʔ5~Z[lkhJ^˅ZbJ cY1CF?ziBo)$A6!;f=i+<\bR1Oe+"Zca鱹<9=`Y`W(&+TE /|/ EuECMb'bf{dC@iŢpsrp+$+})[=@IɳuҐ(suln@V(Wb"fԤ}ؤZMh#W+8MK:9\xeoKVFT/ؾo/>g"Vvke'j]-itpMyQL\Uk;W-NyQ{APU=vjڱSK4;i*# $aυn珎=ᜭ#}?,K[s/tE9 "1zк6nPh&J`+2OhZ6Dlq Ӑ_J*{ M:/H5douqzihrvʮ T(4)Ͳ FWd &bސ^r/2IIV@pu4e+;Q?Kep*8zDŽЬͫ(8[Ed5骓cef-^2g@bhJ@zʤ!6@Dy(2zS1%!\bfC[Ʉ_xp68^P+SPNYZä\AΛA^Beo\BD` 4$!6 I= t2N"T,9AT"l@ .yi4S+}>]/?^q2쯽A]ֶ2{;1kkY7 ۹u 06*q/n6᜴*YmYYZvTR晜Ov씐].Ȫx#/ `r2~3 ˏ'zB>*ֆ$P|uV'س%(Jp'*PKJ Y1CJhC]th NlXw gf%[Vϡ_bwk[k+kQ }^9[F!kvpDMfGv@'m'U02gS5cSV@ |0ES18ޣ 媿chhYs rj":L)%oh" gzL8MQN{u9N~<՗ d3|M0KvO'p1.؞dOe㌰ԳLE^u#&lH$ I /n:Rd@D-M/xW5r<]F\y8Obi#2D9igylgs'aA'8ireAtm>(ES h8+;G*DI#Emw#M-qtgzk$T`\';,'l"sfr]OAn8Rfg H욷ngPQ~;igIX^4ɜCMӆU$=I{SAg~b!mЈ)^F9͢kV М6Ĩ(;%"+,Z-N/6DߥZeY`*8'JA~ WяڼN? -8/?ЮYxŇ)O\Z0`.k46=`1Y+aOyjxm$Ѩg>Nrvg ---`:mԋ.utun/.9;|qǍwzN#:_}ihrkAQ9gF8H@`3>>9# ѩ9o4.~ꩧ!myr8r2VAnto`9D~ޡQPL."|ѡ ۍ;nNG"{ntq)tYU OCW4 BA/ EtL"LrLaX]גVwb[ݯMUW{Ns4ϓh"ê4UhafNEK| Uy<@N; tD%+cUqC<蝁s`JpfbW4{-"de ',YvTcaD0x60:K9RGἎRG5y!ju4V{}\ۼځv9Q ?@7b 2M,a;Je*ěBRnPfףip-0t2\?O8PjD4 :)jYJ ^FF,@q g6=B0;ԟ\Cy&"0aWLR4trtz]iB~g.ξ$ !OzD~# Q(}X1ZaQGID+R1UD8RJ!lFmsUJ3k SSJb?!ϻ&h4Ifw)9Cgh O &vЅni( }`PO/@>@4K6k^u9}Cݩ$oLg]:;PG?Zi8nܵBFdQW\s0#yIp[>\`WWjA0(s'J_jT c_^X:WIFDDpDrzZF{5Gk1Ucz@&4MDU <C]'Dha4\ H17hYτwN3T>:;#\@8piN."{调kUWCw؜竊sV%8I^|t"`H #PnmDO E!ȶLBW X٤dn6S5m]RD*jp{A߉&v9.h7Q  9Pם"bH4ZBr!( Tf' E8v\;K p#3DKӵv|I}N?&@@ l }Ո?E݋2wn5A@H"iMnӞF}r[L\ x[7lMd6Dvٺh;Աt!GLpH>n9[,Ѭh|&(9lW[lR'AxfAGW4yPbkǤTϖ"۩Jp umfCAu9o*ӎc^)rI74#UdN3C-\ sJHMvTJM G;.n:Ld/ɥ>`Z Uܨ Dq8-8T?a:zSM}.V@tx"-G=Wi#|辎`6u]fݮv C_ z5v&V. ۝íhٔȣIpR*)I/p#Ñbv-֝S[QIA=W*YꍚV[`)0#YiD6g @yTЯ oQBa "g=qP1M6Fx@av'ȥ8Fu+~_5YA#)Qot۫0q9C.rtsѵ JZ /H:*i/S>D772S_ͩH$>L, } b?+>"LdMi:j%pfLp|$~WKQ/u8o'p<7t8];8i1;ټc8_@ ߙ9*@5:Z Ĩ.3a |K]btUtjA' % 48pU=XI?7TE[ؑbX5ZWPqr?1Ľp9`Q]84D{FceuJ}&<>xؐ^=kmY{Y m|kDQFaֆsS?"{*ʪ ;κBT?(M.Wf9tgsAe-X)Ԙ5äLDI$vRIqz) B]a84侪RPwĶmUtţf{7TfyIf$FE͝Zw')^5X@)9AHޡ~$ЮAP,ڹTO-ӳ^*y62d} nDk8#Bxy4r+G#ŬPq! Tۥ`dߡ ^C/!*dXSYG Llђ((իj}uf '~iu.tUFtaW/YDɴ,i*[%SBmYEu#jə# Ӯ8= t&٨>* # d[*1fMܽwlVuڡ 0b_^?\ Y٥&8'րQ 7q^fTCM.;@&gfKewQZխIցF:Pu-n}IFt8PZvR44J%O,N 7kN&QDD~Â.E<^N8 g:=WԄI PnƢ-}Iʇ SzoeF#'IMMW j٘%֐ fq\8gJph#P08 㤻#YIN5ՙDcNBҭVgyNQ_7j\I5׍ {g";eB4M ΀{J{ w)3<HKqj.Zk7 gQPHa\Y_)8]xũn!Gz0 SŷTnnqְ/;'ШR8<ќ耲.J2{ c>WK"?rLY;Nf=%馒ti_*yN%UŠD4nwye#Bn:P&ٞPV֩J"PeTE|ekcS}Y݉Ô##{+#CϑD":QҁLgEal몿sX.T!M"n_Id_\ "`kms^I2WЎY@fW)eYjuXQE/ZV!gu/4B Gif+:Lf([v> k eCEEFY܂'fo/HBaF[ Qz_!yVt0ay}dv9pAd#wuT_fC> h88#O d0hBfS[O@NC? `_!6mZA?m`(VR>lTIW b|}aXdm2:5U}oo. VM< 4D_7#5ۜ׃xp3*U8Qy~ x%Yt (r"1נfaf<],Eju+TAU m،loPeTTjY|U)&S\ڴ>Cj-)塌h#ڱd9D noZp.Qc2/r"d-x ZSSSBjW=.ITA8(SկI<|3Srl68S@Jns隣Bx.@ZtIJ7m_tNAq";b[y]`QM2ǀ59PC|F@ZvH]a!6,%a7@ȠjvU_DMPowV՝":Ji7,D%z(c,FM"ta/4|Y;{h I& "^W:yn2!Bf-6 #Aڗz _P =̻OQe.Vɪ:*B䋵؂UA9}^#O;Ӵ OUy- ߂Gn 7%o΅ "i8w[^L<6N*N(m,#go7,0>|",:B~~"&\饱u3wY(pn;WQse (@aAqGz؈IqLG%!̺ADS<-ϩF:"݄ƕ ؕq:gg:tLS"IMi|W_7 Đ >So#o~U|gwdu' ynl`ƹ:4BG02Mz:4% Od_#yge9|8n|ˊf4 Ĭ!*-ljM`|G㚦e<&F3)";h#`:,dgẖ_gc;L1 _KYq@zr%j/2 \w:Z^-: P Ce۲gt\ ANCҀ(1>^>gҨHh07CM3Sgb&(Hj)%yq'ȏa7qa WL!-LG ֹ#;M`pfQkԏfk@lRM&4[,E|3¢`xZ"enAC6a,(8G$o%UB v: $Хiȕv+^:үuGDK'M{Z+y|aBS6HZO"^eY:u{eyI?D/X5#AԞ$bGƳqVRూ{+ݽ2 Dw7Jea/Tr 1cFH X35ݮi}ݨ&Jc wC]zbžIzdZF./rYrUztLJAR2&>5@1V bNTVg]#~Y+i& 'yhhj%R ";aiљvmt}\/]3ϯkMX8䍦]6E} m aJ#H$&PHjm!XRXr-"{ 4$,ڀȂ(ϓhOk,ޏ R}xqZC851ǫ$)J d@Rb~1'ܮ?xNU,0``E]cJY;Sy9Hpl{GzFSo"7vp횐{1!ǕaKQZYݳO$.bae<NB->)Dvme")([G(ԴA](Gw[8Ia`$].!5լđp4.s~$M?VsQ)d}6Iٴ!{0K=U~o҆-DTŃTITgRvR;qY m]^b~K%q F(v c#>ClXqPR W5ng%g$WFy97\q6MM8з7T*1C~s Tu{-ܤ(BC-"ŝidGu{ ~In^By ^vLp,͌g{  1Mxqx3` a H 0E Y̟싔8UZuջGsFzOԩsN:u-yjv᳗6ƵHn]vp7 ]/<8>p7tG$3+Zgh5k;Vnl\u:^oŗۿ7}޾~wQo_9piwe^;`ȫk j01A[L0|  ±ncnII#)n7"7!CGcF!uҪ @`R\1yRP DHv L L;nvV^S&ڪߢ\ zNdlT?Vxgul oltV{YEf^A}^gEI_G%NwI#8q,科l L'?F\9/'G&٧; k?/ݣ`Sn⺼_WH:mDIBUI-^#[AF#uAǀdCj__)p)KR,Whjb/EkYXi38Y(ߔYː:]% 4 {LnGuA̍ ҏmc>񮬌b$Qsǜ!J,{=YHhyprHv6IT0 'atSid_;)psNNvc;YY;X5”9˃( gyWMY3 mV4 }P%΀p22 9iz94'VRDhR,Xo>Zh|>Ȟ̟E1fݒoT1@H ]2K5d4SA3i&M<>M{PRu$6L$-l+HIIOuQb/:Y۱Vծԓz@ٮڭƆkT{Q屍K43-n٩Ht6 q̎GKnդ&ƞH- )}zCty#Q2ڮQL9! ɝN0F݆r`(4oI AnCr< Rarf BA!w#Yτ#'NF}29/kYt0q_yF1Y)h]3FJ;S/9%Y9V Us$Ybb {7B1<= "ML>2Y /Dh1Rb02tH6C3I S1jK֖ U `>vQfexL"A${6R$# gmMFKљ=="ٶf$?v|hHvD?3m!e8[F}ro=$Y\]CĽ9nJ\nt /Y=W եZyP|&xəxJpm87%7t"Y<$ hnY]?iI @@ yp-}Uƕ{⥄z+hǨ\P]22r3^A4EJKML.܎d M ju8F,lJNHg'fvFo~zMtuL"pS_]- (}~#Dd4)M .H.pyU(GFT1Ɠh):i-?6*CƳe-!R+c# Y@j@i`؍KM۔;H&"(NfeHNU;s W((Q\v2& YD=:)a-v&D( q`!ُW*3mDwg2Q[ܝD9\n)Q }&Ha7-xN8wlyo8w&8څЬ[OC>>#釦w?<H8i>LCos]j߬ ì"WҢ2,!Gess-U8v*AG(ZaNT:-a-H d@ \ܡI8'qc^6-5COR&K6'Y͉Nh)r59 @W<)$eK!`Ha q:jBJ{Ã.4t}$U!@4a? ˋ(wr\w aȲN/tP6l]L%eA7_׾1x^^`ؖ= %nU)H9m$_ZGBz!gZGmFFby?I%-;w#oQE;&]cnHv (JiiVM|M2֖1yCؚi$nğHq|n6JTMR-"(d)bSֈ]Ǧ`0ej5  RdžidwsɯnQD=(%YaleQoqnV/="߷( | `ƔIy:tU'=4}t0= II 7^jń48Ñ+i Ŧ?z@Oe*YZYbnw0 ft'…h/@ewm29dי;#0\2c% |jBnGinmx`VMcP(`md'&DҼgnQD§&< W6vV@Rj_6  $YOF(ܳg(LK|@8]ܼb T"AC oD&3\F%\*Su[HvQSLY*žyprWk-FCyns!R(w[F/p({ZNzb~W=6 dѪ Qpe5Vgm7!Dq qPVbU~3܋dIO4b}$̄(k%`B] O"F8HHiXIC:@5QȢT/UYn6^Ҽ +Ywr ]h۲` Yk0J0! ݠ`mi(Hv8$n|wL|F`DQwoJ(?%Fi>"~*eEF[a0X 'qU[n_P*S&XQ]>nk6t ^7՗UF0Eay+&=+ABwl8-!7Z?*uQ@_ Dm(\9"Ɏj3Oo<.ݽQiz7P(vԱnss/fA_ZE (mY!$V`TJePE ¥X\IV yѤ ^hڲt#'_g]IAhd4&7yDoaa| dnO]:瑄<`K}^Z3ɾ:(L"V݀d_~Df=Yٓedk#AoZmXkjTH-+:.F.867gh]|wB7˥9toq!+v}"'ͨ0NpT0+ω@mTmd !JN @5* L!ER#WB?v~$h>,u)EFՈ.GQЕt0~wzKϿT/L#  I,Y=H@̏92uĩz=diBᴕ˳%Pӫ&+\!ÂY-' Hf#$aTE"SˮONE]oBnZbJY r.(R"̎ˆ9Tlqip&'l, BCsvR1Lal0RBjjp4g cqwn@\lNTd@H6.1~HӲ,qDEawk"QU(݇乧WkiUQ>1jtC6eD̯GaYpjo጑uPɲqi1igvզm{A$H:n<&qU$Ӎΐ܌ZM>]smh2.\?;|\JSj\kJ ~T"5y I:`NE> T2pzdꙧ }E@ՁҚ)4K&x\5xf3EU"Z}52}\Ip RhQ_*˄FphpU|&4!<"uG#;ʼ;s 0'},؈~6JnAJۍtYL q~z.]=H9KY4G҃z^|t8iwʕ-H%ۗ6!HU]'J Ec 5DX_E8;):mXj7K^y$F8lۤFU]p Їk-.h (Gl M,X[Ho,GmZ<_G~slIߍѩ<EC$I|r4 r}$BoQ.c4\&W_pNXxx%;vş;tЙ&h,uvTWh5DÞ]=E;TyV:UL.Cb4lh6[V_ @\y8"UGuD";k?P8tyY]Ei5To4yx]XC`K^C54CӾ_/‡E] .'_((T Fvn(+;Zu .,h?H^5xR5%u4!Eō8LcB p=- OkْiʔSCqMh"g.tr^`2ļ/ci&¾ ڨs{!FR#=~kGR n%q,ょF}ȓ,M)ROE0'ꂮ;7ܡ،0:Dr9yNnˮ>20_^~v!)TIQda)bP)n$ $|< TJT61IOrW`CK|=Oy^cdz0OGI`v Y^Zw*?ACPyg>2"V}UG*W ޸@.?ozc15@ZD#}2]G 3:*6C独BCszu/@ CDrC<!$-= `r- Ҋ嚃?Upi-HKuT1]]IR=yKj l6Qm<# #.FjN 5Fanẕ_ @46\-(ʐf9fev݉)HvBؓbRy+w$1|E"Orx7_HEP=K7~=ab(Lj5m @tJg*)9qyޘ(UW+U{>}'NW"nMb:|u6s> hTYڍ*Qִ*! 2xr4MldD T< x֔w)Nig8jE/[KCQq%;rW|eiRPoD,Qˮ`.Ec'oB_ /n(uBg )pf׶0n[R%?vqBCK"͝y\GyG+BUTL6MVқYy 6 Hvm`9vA XX>$pW )BCU *~ve˟T>ybqӗ4 He_Dz-QHALq6t_6;}}c. e/dzY_ӑO]L SG*445\iFQ S(ʀr#Pmqx *)XvҔ&M ~9Ζ4"@@g+6,)Ps@Q@.CPϜT"-,{А("h;G])@"ot˾hJ/n0R۰@!MT!Q HT嶉)WE=k.Bf*9 !XZs"*bS. }PqX1?utVBcaY HAfgsnWkVl-/7kd tCb \NG CUsB/G9, IL PFZ"QU:,;hC= o.4Ns4J4[U{M$89R6se D\n,P$Ţ_ȝFA+DAQpEa X!]HΝpcX G4M4y%W)N? +D IKv!cD">eiAzHpdŭ%jX }0A$hiDSV!$ѷU6<>ڡA7\p^c#Ʀ \p$OaU,2N!ZNYNA<8iC'Wyx]E>,6>m AiӞYx*wR))hI˧N{LVsi ]?E tMǦbg3[^D}\)W=2wAڀ!-t#4c6a*"Dh}ߚtX9O4o74| Boi%1;e Q 1 ZO)QPA,GԍT،jo=G'UɄkTjS-ݵ>"5x$hHe_'+쎌:dCFq8 g 㴜=Q BrNbZ:e7[a!þ^KzX ) R\wlF Qpk CdA^’VNIeH#@\>Jj;Je ď`t\}n>F 1p,tʆ(ɑmOL&](!VX$aĸr A,%&VH솩g̸ 87D#W5Le8 'Pp`>4+B64~蕳n9Y@ *&b:y,[7  bOhu($T"]ilRˮ6PɅ)RA%Gג,v.gIRM8#s"Uu 4pxMEÀ."# ƥw?UФwGhV -G4!y$d~"5ke*b>J,{q$N$';> N2²r' I\p>E\~&1̒V~`aT|__ )w>Hq0D\lN辪$7@m_դz }ظ9 ݲ:_$T0hiQ~+}ޘH=CAsxVmC6=$#t9OlDpf>XvaQ /fsgEYneY.s T(0‰k苷1۴]ꪞUt!5ɫD|]?0Or-kZ_M(ElDcYdETlaɉhzYm7D$R|:zv^T',tcڤ,q׃bou:a 4!'V],FG=1vwƪ}̧ĬU`*bI,{N,|05}cUEX#@Z/#ruOOMtGhF Q,vVb@i0L吮o?f;Avwl푌hŝeõ F5:5>kAqu's>Fѱ9oWP,Z~43QB_UO_@eŖ).z9`G %kD*́)Me/3{EM~Z.hHUZ>qj\7(36>AЫ>:3[M 3(h͖#K1v .Gh^nCS ꦣRjaWPtTceBExvdo<0}ހmMS6iṎg"& |vx\E&56 M F; qx&vX>c޵S-Iv!Tzv(HR[헊m2aAAV±1cٟ HKT*T}GICV _]mFbEQY_RƼ7hf::#Cp tUFހl13ݍo1?qrgᇯ`To<]3Wf!IR[`kJ\ J):c{=bll*Yvf IY΅RT}~T駧 ,$xnT};[ҞuI`< eNIkXPvC??c2-j:Zq\3||4rwʺV9}B (JspXoLE XvP#0;ģ MFdpDFIRQDiKXvt΋R 5؜K9 yEmW]%\!+z OYu xn9*Ee&C wEb}CHu#e0Q h"j0яl"1IVY!x\=n4֐G B !r4M~Tڬ?/- Q~ *VM}S.Ų[ @L'lG%_~SRς4k\~Jti7k-.׿NY~w²YI9nCq:$CkiwmX2}'E{/o=qjI;QqW(@!I7 wW_~s{#Čv^n5VVj-˷5-Ȃ8R9O"v_ja( +}0^Fz+5?cR5-k(Dsryf\m7bh "a$DYծZuMqu()oj=횧+4DaJ.̗NCHӌ=)=cً,xBP2Ц;\ÌW+,Ց@*x ;Dm'*ߨ=F E/9wϓi"d%3 Sy-lXs1 j6UEWY <hũ/@p@JVEWc2 魼\Dz>_M60TCPq|ZҹE'1a В#{CmZpM5? P,w`R J]Rh TloOZJK+Ը\eo4^A(4^jg  1%BV*lYToLFi1Eʠ:ڒHi!B+SR1gyRm[ȽSb;6wCX&Zh#dS!? Lgnd4H 黌SN2}4Ғp@< fsVuHyʤ(,ͬ_~PoN=VD8ϰ"GYʪZWekU!1/<+6W[״ˌ*`Dl,ʐr&&A,^6i-h{yӽ{^7_Pވ!=hsK?=B @2S{4amp|z5U3,&S迪:eS^0o,{ N(gaemw8P C})AGD) Q,랄CZP jbYE'x9?GR<{IW~qIWɥ.#awִ HŇ@FJ#4 xg5%{5ݕV%)^'βn :ERwH=I,m湄>ʯ͐\!E=~aS,F^xX =˾h([~BNTic#zFŒ6$Hl%/y6IAp r2]G=dnbr_,7҂lfݲ! }1C W6V7T,{xa9AXG6,x1w^V\XQrj/z9Ñ3yR]>O 8vpZͦKp~%AD_)ꦉ]-K苷P5ܘ<[P|J@sH-:"Oɱ4D^|ޫc2 q/ h^10E]IKg+, Xƭm<:z%GjBQ@}[AG8"9tUQB>YwvC#Qv׌oU(]DhoY gwLsݿ6wC#L^c=Mꂦd[㎁8cZNl~/Ab'<XXA 8}ު=q{45L{J 64m'4T.>%gA:x β+~F] mNG8Ei%[p \N8{'BKҁtk;J"ge7O S"'31$ԤDstCo%Q)D!$2hBSQh|g6(?0 "oDQK!k_h>QtG H]̼7%;|O`4݇Uǖ=͌R3%JcC=hu!?C>Qe*Rߗ}Tېa6Q0K=.\Qe>m TOvB{4Y^ȑ!wGOG F\ӜE@@f߾YAD/zFr[nCg䑜u~hKQ"V2*i9u١5Oh* ))+C< JVRg`l ^f.ⷕtBS:aUz.tbQ-seena }ŋXT 8 d½ % "I8id#"CW{bnUpQӢE#*b" :*J.TT4'ղ#S+w?eC+Pjm0e/WwvPgs("ql{"թ.Ԥ//)+)*4/)$=y<[5:FSR2!kaP2ѝOAﱢ.{}3fuq+i 陑ZLw0%dR 'XDv#LƱ fm¹QҕQ9LuŠJQA8b"uхvRK_ƪi%G橲iXܚ>牁jOh]9Dz+wzJ*aIZif$76㻐PwӨNyNq8KiVkK?ʹC*iT) !~FE#>QC%^7+rY}b)̻>n܎@*Kh*bܓd5Nr*KÓiBԑ-ק!a.4g VxZ'jgJ9VuT[u䴎¸X%xN" >4r0T*e=$A9yt^wAg_Zh4?#*HPR;,(ȝ[QTJ[ dgH 5󍿉RCc2Xb+`FZ`D^PJ"ΨVIuiP;*8/Y?Н6[/#h&pp-lٛn"?-Y;EdT؊[ҳ֑^)M9WH{)* {A7}J q@gs"+rNHAܧ4)ױj+ :$[~*%_FyfT i]%s9[m,WyA/8nq'~R!5~Mi@TPfo ڛD#}Xj+,q?)RVs|Ư9> gi8,ķ+j{WtTy/$vC-Y R"n*ӬFEa*?|F յ0I wBM]]E@'PFbWebUI8y 2,aUZre鶿SL[^hϦz?'˂nP_Fe[]Y5Q˜џ9R: 2n\WQ}jlp#s}ʦUdB?,g_6}:BC1"͝ydGy{gAHDwh DJwVa@:e{g m>699zX# &\^kA q]MH,( I %N{~[WIJvY^OWzQF'o-5>߀;׍'7^@@Ip|q180:3838?GIX!w7ڭN5LNٞN[G:[s66׻_x6sccs7667#7/PA@@4Ci|en!g 2BƁAD*cr1OIZk 2+e.D0P<2 (DW͈ֈQ8E)S9#%\ `Atq"g׺0]#f~k4R瑯WpbJfXiysD> xF3O`A$HC97b TߡZDjY$3Cw1v kXS80Jt .IJƝL$~ H^AD_Q*l,r6B"T!&PUR*MF"9앶@@̀t7;Ejz"MpER]dRŔQ 桠AL{ LPBU>JSd$PmPp4 cW0v*DkV[E40\WX]w- Ռ9&Qr~m9#٘W}l?Dξj `̙IB>+|5N0\u)++Á~}Hw_|xM>7Iy8։\ƐaRni!!,&d;bֱ^w3p qx8 8j {.8ĺ(DӮMC-.uQY@+>S䳺E>KOrs q2tɾh -,.d*7U.@rtQ>*?;$9Gqֽ\!XԊ>?&19{ PK9 ϕZ:$#.41\7#VRHNkt79щ)kx!"ҽk7=vEuaͿ@-O&;e9Kg@'+nЯ?p!H4lAL s*3:酼S1Bu&A-?w>He%9)nR# hzA]f *rQ[$q*;tԚ98QBYPSǙ^C>fTJu$@{W2I7I >%U,Ėf~3ZwGIw8WS @@bQx~$QmcN1ݜ)r0w/nq+.v=ףQ&DHҹ$* SZvsQ't;9 xh9"%~@Ѕ I,@${D-S'DެG5tk]BA02j:שDHfs"֏ .PJGbX4&՗W =Nζ]pi1 A/57E"@1D !|^ [.88h0XrlrIljfZ"Xk<n\HrI7Krr65&)(FSDM~S{/ c i4\8 gN)fiNher%(a| ]tGnPH@3:k#Oo->X)G\vq̸~9{uu0L*OVD+e[ ޅ qy$=VVJA NA=qhж"͐>Dr;N]"</D@IŹ5ԍ4mVom8[pv.H7A)j!ݵX3δoE"8Z_JrQI|ԫGbMx[:zM>khS?-F?4 ryk(\ |dfMu&N";4kr P*7=Tt#9;f4! &\L eT@W(BsrE`T3sCgF:%l(;`m(N %r]<@{xN5D69{NCIR-FOpkxpeUAyɢ#LeO$A2+)%1k ];$0ɛvGýA|V]9 wXUPX=<4m4RDOC׹ZQ-H>]{KÑBy]p=T1(YbP72GI&}{i,@Y8XUO: 7}Ooi/6޷aAwTt$!5'o7u?-k<@؅"II= eg3mT *o㞧w7׈Ӽ̩c!цsnq J1f- :Nkk.N#G#LHowMbM&еK({u~BIn1FH] 0/arer>Kon8mZЩi<4lKw2sh{ű<:C)|̢l^ʻ3t9%8<a!8+*NVg)_h`75 w/9 Pt!ҿBw5Nsȏ_*ApF8Gn2B}Z<ޭ#xk}=9-MrA ɓt0ge{\6MTm ΕϡKĥfr)kDD`˛ Sz 9(.ov0 Nc1N]'h(x6x2Uf1aGqNU{T6`P iKR5 FCQnTl߉<|ӆqpx;`ʐRFֿDrלz5eˍ⽟+x>\!4ez # ERVUZR^Z b1%}!4 9;ǁ*@V1!PW{\9E e5f_88bXLJwre:r0OϿD\JFBp—I:O GX[N>7Qg}fO-K9Olj:U@OV:Kv<#9HhHKd IcT?T.FQ!6¥46p^!%&Lta>@z-O!'>hM cqN#Y Y3g!w|.XEp,ǧ؛K\>"~qPTks9{5NH g;U4çG]z/ĺx,D>C&s@e<,c"Oa"ݞ =tJX-dt Qm9u\$:M8\sMN(#=WjySZ;( 4Oޙ3'RNE 5,uF78ņ+lmN0rOwAv&@O/{qcN[)P^ЅYhRː%/H~EӺTD "!S3Ԏ_„K$iGD9Sh(Bzla+A{dwmzW4GXDlB370fm@ =o]C^tRVBLj4ᬹ ͝*j8o=chM:v]LI<0WD[ȍ^ۿP{+i t{.H͵|,5ut{H$T2ăJV<E=dvRME18_6a@-@lb3''(8h DlC܅ڛP- T"Tv*_@ JO6pY1\Vd0!zڶʿI`L~  Ye_8nS\B%xt`ܝWB2C)G]"yg-^M13_MšbD#-bjq,!0e'\2'%WN``AB |gM8tu`t`<.X:58:t,X8i^NdM aO?۞l޾6ҡecQ s i]@b=UtX7!4pkx1J_ /NcmHA8tiLӝ6&)fѪfʰzײTj@0'!A 7LMPRpx>T^auteԊb|64:TKe<Ӓg([( t18凩i7l`^I{ ѩi$&^'Man1/~Tj"`!JK(/. 0Z;i\_B~ i:>i;$UZ~kK09*%G;qѦ2rN]B&Ul4Y{u/@!C̙t4s\7K㚔@SߖKij B+4wqw%Z9)_uI7#&$aM%-_Ae[Q3+˧4wO~.qջ) N '&W̓awI49빂HFdV!be~[P9m2ߥ1uKLj8qS8az=[MOH{ᄒ=9iM=<kpY첹q ƀA!*8K|JRCo.@P6cNtDITUC'4(yðS Jb(ɓb"9Bݽᅵ3Q,N F}M} Rz}{;b/ ' UUZL4/ 4:ȣ{d`>Gg4Ou#BJ$;Z!3޼!Zo)Y^i+az"s,~ن:xV|a;-@|)-7>bO70Z^ÌMɺ|ʱ9n848M0lB#<U[8'5m8tI$D~l{aNOYK}/|o8冉AecA^b״_ :ːt"#SZbEN0#Nv*'Å}s_4o? g\pp$I'f /N8+.{(RgG :QmG\29xn"*pagrj)lQԭ/NGY7ȷG-|W7:_uNDܥcxΤoFpL0p`M9Rg)/pS)=T;\S3eӓq {8 @뺅jdxVF;qg@{q] _ 6ECç\fe+|"rslsO`V0B:^uYPq_#P_p}@-zG.m>, "Q$.V-ƛ6z &ÀhRǛ30'=… A4="g!юXqx򊾸6W(0D@#2xKSѕw:<‰IM2:jrtR-kT`bJ;tvwzx q1Dv*Cq>uh8MN.sϬ~2f+oVmִ~6S>kކ^e(ɠ$gpY`E[}B)-1+D7wՖq; 1ϖh#$\֗g|J>{ɧXх2 @G<)޴KBW5Dh&z@,tE$b4^vy5 DlBH|.Dʫ8(RKD`d1 n2:˜evr%̓.4HY1_$=처ɋ k*hos"WJE5I׺Dʓs,G_c7 2om}L7'- 3[.DJUrʹ{I- DQ*}KIL ZRS6tGy)B 0 M*ЭYrQ+ vG|UZvو ]l\6LaOG]cީ޸E$?8<ę"E-MD8Crda3BPļӱam@ţ_!3vBh Q`мG!"͝i$Gu[3جPCx@Oʣ.I+f+d`[F}eP ,v2܁n! @J+ pW|A8Bάʫj+VmnDz/_5__hSGY'flw9>asv^o5vZoDftnnܿ=y^g=w7瓿>܌;s;Ƨ > ƅN#:_ܽ7kA1 gák'O  A~X{M4t ABjk p$#!dh1.?9^N~Bͺ8T0U6ȉ'x ON\hR~ Mˆtpץai:fA M Lrd̊)vB]`+8KUZ g*ȅxB)iڦgѣ Q.1Y2Qy) Ǚ|vgYIE d:we R.WWE \뻹ʵ)Ҷe! E'JudhU0 &X`>*pbC#%w.wOT\R$+ڻkjQT~sT/-1y9QPlC`!&L:$|ճ ',$^OgC]"9 y=Nt|&{1wٷe%kʎC7NOXF4/5fxC>H{r6ݢ2JPC tP7[4WdkCI2b%E%G"$ Ʃ}eWk%G hpx`CHԆ델 "&$& B^RTn#]jB=!]}PVdN(I0̛+ay)@UGeBcWx61"Pƿu4ܣ妁R Fc&mI.Sϭ}'#w/Goj%R /e!pVm⤩9SH' {teR)Yֈ K~ Jױ%%cR:F,& o(wR]$)hj$p8sv-Qs{ [!L3` F bRB[gQs>IIbgF1R؈"P `3 ݦ1 FgGe;?SKR6mu<#\Uq"K8i]Y-'k&(G 0pN6ѻLpBq<["JR&БJJn0 $DN,D@Jz @Ҏo;pEV!'z.! ,X٦+ hÊUq](-#*2).vMZ/a&WG&4 )b.MZKI8y}]h 5Ъ%񤉹XYʡL0n BtNh%kh#\pFӲNCu.0Љ^o c&8^(C#V+۴cPP $ 3r srjb.P~#N;0 bq3hWok6ʚ0\wh;<9Hh=^.Bl"Ӄѿ =ɼӂף%4C^cBCu2;)M* !(U@]8$yJB(r!" {10I6XGDS$5 S$,:H@fR-piQzr&ȩ"D7A  oZ$_! ym h%SM'0}YFSAfJ(@p1Y{EU %@|bn]mTL%D1"_ U!kT.v"l[Kj8 9Kڛ*W?N>˜ +UsOMز⺃ШYmp6)M`s0eZTx#hײ|NIr+ udݕ<E,\]:R+W&mpP*IU˺T2 $k7*6n0,=x=9͍d4獀oe%ePN1vKe*S:r{ᾉV&PzBq,ϒ{+O  BԲa;4CM> *%}ZmSH$b tw^@0P{\}8H 5+sا!іxwSssW7H5O/*q*$UG=IB%9*ъ-"݁T7dF8b fQ#"Q3I:p9^C6z0D~!Nde`'Гd:g+D aO>BP:"h|M4D`QNmS_#D7"beQ PrC|t&H a$CakZG~S%wjF9C!5n[N3zqxe?!4̏N8N>[+G~:G#ϢgLh?4@ )"g`pm ,|Eڅ1aF-q#;ZJ4+qOE%Z* R-v.3 ͗hh잃3 a 蹢bߎ6`kkdͩ<*]pRj(=T6~=U9]̲q`@° g:ռBQns ./IIhy-#kR瓒W$4,T0 8&5*֕tԴ_=p@)AQ?9`_%}r Z'NO&>s4[IeXwQfM|rc8Wx&{@83#j ı+nKGFjb4zs^o͕N{4ךguKCZOp|rMA: J,9ݘm̯ XjMdtQ^M賌pABxco_}R&k FԒsfηm&>QCG.@{ܪ&@1?pLgI z />xH-g> ?by 0˔(B3# YBɶ`p,G9Sיbd#ۊt70Վ(o0B^CG~ZQ?սu.z#(t(xZx6m‘OrdA>lq~#@>\+;Vcs +v@̊iw~OO\`+m(!P-ԏ`8"9BzYr.%B'}Lk͚@~ ǐCtQWߞj½F"%2n? Y #NM`aI{gJ?H+H@DKW5^6acJL6TV9ӺEAJP ]-N N: uKQ<|p"WvP[9KȣaF )FjD\q ijOH+?B Mn4 ! 6Yw ,gbzιf#O*F 9XiN1!Pjf]hd]1Yx g[áΏP&OT:8<+P"q*g-P2Xߺ˪W*?D\l4\kG { ?5TX4`j1IG5 =iڈH*AQZV{e4^_kBЁÂdl^H~0YUZ;'8#m:iVmFdU<|܄B Bģ>3pgt~Q)ÍШ †;Tg6,Vq 0B-'f+!X ,%O[M+pLl802S\Kֶ+`Ň`18WTyQg$u霘 N5IUӶ{P95j4oT/DD]JnrDP7В'$GsОHno- dc*!?68MD6 %x!8j͜Tq ñ(Nm$YFlVNn2o Tg8ET/FqEL9'ŽB4۴urGŴ2ݭm !k|]8$A3)4b5y IHq LA kWGS8IEmDQ ~be2Z53 &Ś('ֳ9NP;6jh4~|{5Y;ӈ(UsOkv=QIó|oLG|Q,)`i* s*¡5—AfSκh٨PN4>u qv &UGDKn0"&Ԃѐ'H}50P',aOWM6 }%/,?'C)ͫڛ*W3h S ϵ' dP/vxt=Ƥ>+|vZ{0Wds׷\:#koqQ8Ml[Ia崹:BC*"ŝydG}g! ";Q@xu c_{-lͺ̍cL+NXA9qN=fw A័DJD9ɩzG۪ycV[+~ޯ~ҥ]\^:w{챛Ǔ7HߡP#?3vc.y <<#J/ZZjQsk^kt6AvCKޡΥQP.'}˞sۍ;nNW2^{Kё {G߾,2H&H;u`p̃1Aүtjlm5knh6Zhssdd훺<.& L~b.x9ٞ<ϲLX0(ε3sű|}]M,nglS}lJ #3D|8rvl!B*r:Y;M$&[;{%(kd $uIS]>Hl %]{3ʌ6˵J]D7-]|vdzXqM@ff48OZZ8]9#uղcӹtns.;t{9K;Cn Ay{@N3D@ k6$@Abk MмՐFh4g*hC`{4MSf nQ*p|=p(Nek}|8Kpf6NG1q83X"&8i@rkkӭ'H؉RZ  pX 78F 3fmмτ#p0*301z..!˄y.WD9fu9/͟q'p$ ikw'KW)taz}`8mۆBȍM&k}Ͱ  rOф̵j:~C>?`K8Jv68;5q^ u kX->%*"k=M8I {@;Yxn6~<T"FzVR@? $?¹MftmFG}I:Sm'V҇0X&V7% m~мɈ㴁,NΓ Ύ<㰇|'hӫٰ 0\wyudm] ;b.ldz# LCj hr"V i=CCCHDF^m0.h͎ɡ !t!Яg' ~ER:8~q\['UQ80KӰK|W [0 4,A'DLDW(mCv, Qܽ&Lx:5Y`So.0NřJ쫢;5PX󤸾b4GB 㿓@w0OCl:)\T@t@Wbb%ZVu'$[\hdUEPTcU "ۍ(.vu٬׺g~$= ql4(DYUI>yR3eiYhDv"Glq UBtw7!pbqz85: O #לTzIB -M8h8abzҍE4I4euh y@ЋDT\m4'ڱ'QrQLJn3agO\A;iF|¸?#TP$#(+ϙpav7|H4?.pT4Vdyt=]78Xy R}Lj3ɚKSӍaM{S&i*.Ҩ2dgpP] 9M֎k`AW8S AAilKz?v.lQFWG=-H͇'abiVn܈ 5#yvz%G2DK;w`0‰_8Ӻ} IFDRiOOfU)PY_wi1i=.##*aU(Ѻ|9j֮1 @H]&d-2a| F;>a宄Tzkt( fH+55._sC*#&mZCsQz9ŸOAy%mByܙrry%"XN!)vxm">iLNiP9QJReJQGO0Qm7;IaNk&H _jYSTܴR? .`*%y K":Whv qDJr^{h5jZ::K:?DY9;7X']~b28ȇRN?T*yĄGa6jC0QTD2 {b֧[h@02R2Nګo?;Ljfv|!CG$ WܸwB3 LM~;qd==&}厄A虩GuaC*wj! hRc(ovSTFM@!cwQdӿ +㿓3_v6e. _w<"V yhQH>7\=ZI,PM󮳺8? ^DU~ F%(x9."+}d++úuc-u*ã'W]Qa!1Y*Pɧy;c[@'jtڵHsQֳwip~;8Ŵc9KfM Rn#_;jnXIHBǸ'4wZ)]TS _Y-Fs8( a&Uq?}l䇼p!ȟT! 9'OɄf6/cBg͞{QanfW)c#Lv/>DBuBZIͅ؜|KC;F8Bd#瀓?1@l4i۰8 "kkw1x#&'+ߟ T$6iPˮR#vn1^c&WhK  _&/lt;6TaQ>=_1D(E62TO £Eۑ QvTy~x7 BfvgҪ/G7WkګH B]Q T9p(z'Y킷+mN3uK|c^?brUu/גTk|i\ e{x8|Bî>WENhW93Z+9_+oZMtʨ@%O= |6n7XiE}ڤ!Azm+Iӊn?8\I 7bXIn~>h#k gyـyK$SI]`O)d8uq>a9QmtQ ɦ[ ԩ[\B%𷌀YSÁڲdp1ϰIH}{E&D_(\TYc&8PeeMv:}o iȓ K{j38>I^c?{{TR :-gmN#"auEAe{t`0AI<ٴl(>#=0Bg#I":މT4x0.%cˇ+C;y cR)fSi|&Gm#vC}Zݓ}Qm>> FֈpګӍz1@"/ "{(}ʐHn&kjL^m9򆺭 e7^V$EmdJ&@7Z*}CM\@{4Q}GrmRMiXkڳ6Q,ƐC6~D~0!@cIc"]C2|[cdNm&aʺԑXk)7*JJ@6Jbo$q6@fX|CoJJϙBr 739iDB B!qd]RWzX.!k{8\yke0đuh?]JZ%ʟAr g%KfUbI#.N*W䍅1û 1*|cr8a~XS|e1L(*S{@ŕ*~OB2~n]_h9*7!W5SiQiJ+98W2Tbd^B00 ?SU ?RH/%k7i=hnU42Ro{晽85jեI\(ֳ̮[Hެ],a5ʚ}ˉVg"EHS Xn} 8HLwڻoa+pkZ4q84sMDŽ}dL2,d3 Q8F S.ɞC z6t~G2j@mᬅLzGT0ohJKD.^$?$4udD<8CDpH.J'ZKJ [bz˩U-9i&n<խfe#=ng0^q,t%Lz׺f@Lu/瞝UHgԅCE0mO-(qz7i.HKLpeM#GTfD#J[q؆:d {4-DyvN!OQ.=v N{(++)ר1g=g!ȟTۇqń&Chv^q87.z nN+̧ _p5  | FwPHO1y /9x[E*A$LMVu? *&jɷ T! D1!?V^g9X{U}wxW7.Ʌdudf+m@ JaV+^Vo%kM14xBB Za9"5 olhL $1xǐt3Nٟ|_BG+B;Q( p8hr&UY&5airȂH  gWLB % @ڱkuFWOUDw/jlb(swCVJԪO8!_kS9F|_k]ùt[;gT¢!0znOwծ"@}ddeyaf-U9x>Q?*׃)"YsД{U.O⾽`Q{`xh1-@V4z⛨+D6Y M0E@JlT5pЇvЈx>,p"i sbrFè@y| ݬ ըa1@Ua]]™MoQcdmdBA;cy =I>`Tp@IK} Y#\U̙%b~*LpWJަVʣC6vv Hi8Qۺ@qsmqzQ "):W,GG-b`ƳnfH/R+67zH~ewNU_$F'8 !khlFSYgb|ȇQ0NVId$*_(9gT VO9muf)=r g{hնǓv1E/Pm>ؓhm6Bk +n6Q^@[6(W`4G%^3$\$q뢜)"*V~8$[ޚ63' $<ﱕ yLr[J ڴ?7d0EZ$T$P6]ϋ]E=e2Y&DJK"ހ1b:U'۰dQs1y(Kb:c=:{7n. LsNZ4ŎiZ>ʳTD3I%/9Qy $Ww5<79P Sw:MBC!͝ydGyggI4NHDON$f4Bī]1M;`{wq\ 3`D!&J wƆ$JP$")"%S^~u}ՏѫVW}u|.qzanW-AdFG7pף?P">;M? 60~܄'{ͭ-/,7wVXk._nCϹЕvuX?>i;N' ܹfo־kn]>{sMvtGy-;^Ӽln82@Ղsds? γ3x  '=h:`!_`~|vPsE$|+snWkiS%43 Ôr֋zHUfD-'z@A:U5D ;4QJ8 D<t#Ѽx.vGڇLyx4y Q8m 3@DHuHhB 6KNBDt1Pl q-;h`tUa4pWpFւSsf"ۡkۡ:7 Sŕn{q\^Yk.5ŭֆ#ggS1hxDHO&58(ܗKEX"Xs'j MtE6LJ*7jֹsc0>sfA\ Pr6<1T/'i5ܪZANL!Q#-!*~-8GT+v`<g EL@׆AуCq\F8 3!>;"5lQ5) V&J"TCֲ`,>XjD-:߰ %NMtt}x P kw9{6Ln0t8 !{(Ζ؅N+"B TS ؉1X:PgSړ X .j?ιzÑ]ԫUW߾᰻N]&[E)ӳVW;Cvd#츐N꤂IMUz#ԭeckQ琌vq(*q/(Ytsas.Y{S02)Etĸ9bꐘҺ_aCpC 7ձʩD3E]Nr-i-ӜH1qNr[z\׬E#\"O RxVx ɣV0$a8IS0ɲ7+;&xi̍l"7|]$9>KD a-q| U{V8|:*sZOoW`1  h>S L]k׎\GE(_@>4MW4  N]*O- TojG1g@R%Sj2sOd^S){ѨMTsgb'Zpz%P5>c")4ꆉ<zŦm fAqQR'aCA ]Ը>?&kPbXZ\!gQBp4Hv["_I4?YPE@QƮ=ݸדFE:N)$`W^o -d 7)8q8G udVBM0ĹӘ>Roٵ**WQhv.iJ}d]T0PńPuĤ} 9U\fP hבޱV8ZR1Ac&UJc6BA5 MWB Z@ TP]65pB3'kۍu>YUųZoG3'K?io7QtbbUf[dOӍHB`dK&p Nɟ4*|(;0,X'<'/{s ^ZPK ky9-'UR`oy]52:I k6_zɧFgZZJޜ˦kQe8,F}9y|JWrjUK^8bnxId'0s>Ć$:u*ˤ lS,?@U# LߩNID^`16 8RԏsnNhYlhŶ(kQ ?IV9;BbZΉ\ tiDXOmCR mxb$|"G lTGsڌ9" `!JU uєLk;deƝT>n0Khft8;dQzf9(7 gZhnԞKy7Y͸p4qc<̮3},l"zsL2}_oV!S}}8.8~P{d8f0o*,ki90AzC(…oZ.HxXzFGԈY._S]B蕸s6nΡDOQ`(3ӒWgh,/@f Lv.Rz]ĨL֞co{SfJ'_ں P }u+ie6c M$y4HXI Ӭnݾpip\%eD!z ¢:[ws͎٘JZ *ԮE>lCŴ"0e jwQ8um5wuQ\B`Kb(:9:CGtU "F#Ro eA]&IFa$h-DIѹƓ*r,@ֵaD%Չ]@ܕ_KÒg0\rM}:Gb9yA$xϮPw՝yIѥ$m8AmJY/[뺕O6쵅$ܗ|]gKQo5U+Ӊ JH |)!M&|Oj5E[trJO?Yl"MҲLmi킴fV. _]\Pm!,fÒU8ɮ;[ݹP5y&ک(.Dj-S;{;'UZTB#D^&~D>Uix?< Ur8kuUnq~BDx՜@_ꍣZh[om;EcX(G8j N .!bp> "ÕhG [8 [ț~ۧ*3H/r$lsG')8wY]q8sm`~nnuqV=QXʎȎNһ@/D8,J -x ѫg[szx:O*OP =`E {('4 4T:qO :mYk J.Qg#({Q(A؄mbi=!!5܉y]yz,lH}Mp[O.#Z 97D^fzb= FZKš"%RJ5F0qfjYm5Ђm(dfMSDA|x-M @?1 IG5)m֪6_puvUj<^`37/JlH/6[.0LbTUcj鿅PAPj^2rڮ1I^0mW.è~xlhЭݍ@awݟ}RrFrjn%mctk[!X`Ŵ $ܲE-r k2BcYAɊԮ ^r{gxSͰ *w Fpd◌55(&w?ͬE=P䬺^ے21}&I6@Ťp'k_7.Ri@.PhGqkS:""0qF$ D@M'>-7/"Rx Ո"4IiƣZp[n#LpL]7_1GY:gX="N|^\ z> Ta5= iVdc[hJeU+>pɸi"u0UK-t":@cE$*\ʧD-@|({ tڑBn"@cGhAA'j8:aYGH|J-'2\DzHT1L'K6 <(a.zLIYݸ DB(>r I(>.c \ }ZZ^YvѶ}UCat)~i^~ -  '%flzWiMԮ{~XZ,jfh`nѡy (MyDLl&\K+D-|ȲO_kf:"q,l'dٟiɟy{,iBir@lhP y4<<J\}uNd+t/G V (<6`*6}76L'&Q/*ѹ%B[R(^hӍ6@1" xo>ط 8bNL+t6eC%=6`2R["ug}68ųuٮJ=Uځ0i|A z5Li)83wdfM#cAQ_+KM}SzJ$iR [ʆRow{b2=^l6HxQ%{{t4op-p>hE<. ƸfV 8}fMբ}}No|!^_tQwJh_梢) lVDzo֧se;qnK O%͞s a4{04\؃dfI $RBj@$Dv܊F {0f=Lh^kCO5'I6PW.,9^D !˯a-"R˃]@@ ”F&Do!BA)O@r8Cw=xŠI`9tܽ%4-BSh)*qvl0 KT /'knj”Ko" 6Sͣ' ZhԘHtp6 MMڸB6^KHZ)8 g8ٓ-͉>K>`I;r`DA7+Wh=V R"4p:ݦJhdYG 6TA;t!|BU./Ka'z]JBCE"͝ GyWO~3jxXknO[ki\oL+V{=ngO7:mci{6677]Y{;;u/V,P45OG]vcUȹi49fjFzT )p׍.ń|#NA`:Hjw/YGPp!0ܣ1JPCl')ʻjgamupz“hnD a!=@z[w2K'd`Țk " ϛ01=D֞oBg՟DLPYFnm#&%(? xG O 8=#,V|yme$t 9`$"Yx̂N}}rdb*>g?#]̊@9ַޣ 1 NE {Iv+4LK.pzwVV7  F\hV#Qs tC#(إ`6Wk׼rBDWo?ADeH(YsuYy~]{5nzu-RuNݚyfHT]Pqul#ߎ0A,V\tɒzHe{5 &4ئ]iJ#W,DIfgG|=Ѕ*nT @1Y`$GUEĈ^@̄ȓB# ZK>a1B(Ἒ|'{/;83qQw9 N&qSAn Tpظ'`GleFTp֎6ʡԒý_i&9|)͕Er_ A^`m&UsA?cFoK F|&alQ Ѷ~ª8lC=Hְ :`!8j^Xd-2͝3ZoY4VNj@t8?5j:M_fJgNR/w QR,#=P8(iڶ䃼.pŸ"fL цuP͹=>~x܏p%8C9/4U )F*q! ..dwHFDxcߘz~zԨӓ\! <ŹzoMidԪ+t [Hj~>*w[JMs,.¼Y}imeKWhWDY15D-]鵉,/#{Y:9 ]34(']o-ePBBhNrj4oa * *<*|qMpT'h!8j}uQswVI9%l/J^[0VbvBnWV7>S Ex0.7TjדT14>f8S 8Ky 6M}rǹ= Zv}"0}]Ws"J>CهͰ \M \Ri 'vI~́zsdiHPA\{B~$J#[J~~!tDPSp~|gקIHDB"HEpac"!V\VEtBi : -^BO:Ja`0E\ ۗtF5"աߗMf3*,n@N+;S _FJ䉃8'j֌d,qR{29 U @S۪]Tf/1" ?h4mxӢ ŭ*hp4esF4mhX5@nO-ieD8Bq Y)/;؅^$qߪ)ޯ3 `ͻ@E^7Zꀎ+'U$zF䉽?`䥾]k]C84NJ/#H_0A Ĥ tat1ݶ-`ǍP BrF"P3 S0nc(M/%T:c?O~f BlwH3' *v86G*N+Ǚm[$+ab?"k<]&yF|K]$zvLN!ko<q/d pXv͚Lq0uz2d@'(RYQ~ͬ:\Q#`JN#&ڧ*'U2,!ӈ}CGR۽ќ%^nٺ;ڗ+#R5nATay#9]{! yVe]G L'$G-N|˨8!j?L3NB-kJG':w!)7MAּ X+;\7*' +d;q Mub;@3;ٙo"8˯Ee\¸L^9S) :$[5S7?f_6ؚ t厧4/{+x HBsa@cDs Y{we iwޢnL4B(ehZ֝7&y-$7dO+ %\4$嚒.|)QϓTFLٚTXd_ *ĜhdLY'oOV.i^dj0 uRs>6hRª3SV*zk2Md Y%+8:Aβ_Hz(J%' n2Lyk .κ-ד (UUM%/g]8/:E6L"k_+ZLz'9z"}gdجå72?Dsʡ ^oTa7lR(ne,tmFeͺP,|hTD,5@4(b)kI>䐌8WIɴcFCKi; 'C3{+=[\N歠s!:WWpy<>~+zA4E$z$d4fV+,eҴ!lԪwC`赟&0zچSh Hp>'2ģ0#جA[N:J;N 8([ uwLZQ͌C\l ty{QwSE'cD1M? m#lQ91bJg}ypұ0gۨpw^cۇ\MY9}$JLU"ogR ayJm6@ڕחMβ_ʩMhiFg-g4B8Hld~tYLƒ"_zEZ8?5Ct_4@Ed0Ig5K=kꬍ5^?1 @tAyK#vW7!7IM~@8{ohN2yV'Bhie;~*Lfq88OH&]$EVZWLH. k2ەK5ctnɅ@'OS,Hމb}e{7LP(CLs"sɜoJX`ݎq"Vz! Ke*Ǩ:&/ Q*OR9,%8/$83‘fet_RU@uDgShNGF^Y W0KGNS^#bg+YՂF=/N5û=I^[&ޟI.q'|TЮm|`fqr@65qvI3&u-\fA#]ꌚLJK\yd#ġKQ8NiAvZ{jZY8}G(VFLRk#NR iWtzJ{_%kWU&80Cj ôul@kLR";`a}ۂқ $7BXJafɆ{o& ~ME^Dq)J>%ۆD˖jUEjrh0~H?dԖ $i_EuWV&T7 7L,稂Ä+F  g N:"D2!-D>yJ#ߜM) 3N"LrEC}B}S3Wkpy(wO&8x1'͐A'@"+~Bu O*_XȦ-!LBIwUY1dĪqKh Ў,}#Fu1Y{IUǧ, 5ڠrWdU_3p wY\e@o]6*@KG~/H;xAYB} V-(\&@7yc`D[h0<`}YB4Pn T7I Zl"7ή&Mf:u4!Mnb*wS5(%#WFmn}(rQQh:uN5L{(Ӹ?hfVi9镺%Hzqֶ]#;Ҕo_a.6z6V=G5BQ.5_:| t \or_8lA@UzK8Wek2oY)dDijq0qD1"1 Њ aikU\R",v!{)}v PN?&ems`.XsY{kH+pmI>ą{8R"-QxD+|&S'":&ceYQ-e>lBcaf;]WK`6J3cj[2 YZbYh8} @"$e7Ԏ"93&&/%&ԁJl]=(%&k̮s)Ȍ6˚'2u[Lr,!% S{@%SYfd>0GIY M#KAꐌ­ܫQӍOV RwfPQ6[8B1t}i Gx"Nhۖ>{=K2L<#&_EJfGJ(H!FtW cdm QKu&Dkv̫W j/ew U(G޸PNV ȲJU pظj\usA/з0&KLx`((8O{:Z-\]7r;@z6&PHwEMۑ܅I+ K>lBJbXڬN<HOw{qIOHv4\qnpdp NJlvq4l Nݎ)C `u IF{& p(iWh"!kPs)\FRTF*vVjɜ9$lYIzz(*3|#|yT29hmZaڕ<)R ~QJ/'oGڙچxPB8K d{GѾI 5DE4D|xaQ‚8Y)`'iCmϑ&sKO!tmH&ۗMX^0\XBCI!͝{]Gyky[U5+ОNbn7}6 P e ,hQRsO7XwѾKyžAroKi۝Igiw.C|ڥOYk[W?+ZsW\ru՝#ы^ 掕|}U&p`J`B)] ́Д?i)Ѐ?gG¡!:;@C@+Yx^@P |vBȗtzZCq!!g~CSCr6vsd,"dqL KVK.;/C Nr``{ h;j'@apZۂڝ`2) XE&XI ~fRAVVbjaʈ%&D e'jrRAb뤛"zԣ֍B4 @E"ghDYA83 ( sL!A@aED>jO_m 4{MhBH =%qa;.P7ftvDׅHO@~,6U MKsdsJ2U:m/a]GԴ@eף?eJ>fLCiaʴmGL ,03J6:{.T ?pÝ ł;ú8aدFmDٜDgԅ|I6`eSv>E[*j8i/%_T =HՕ8ZstJs y}S&B4 !-qLvTA&٧ZDJ{GWpANFП[$X YZ L֮3DݘX9\!W@.(A}Eq%Jno.F ҰRB^4q!I?K^/D*q-B^ ZUBZ@8-8B5΂  AJ@ADGɸSnp&8 ϝ,P:|& Mhɚڹ0uMn@@7 C\CחҎ?Kht6Nif^TQH GJCc7i O&,ay:Q&˘AأɊ^IV*6t|m 1Z>}|Ą{uq\O= @!Nӊ<. D!t  Q!в ЍvI)Чm@/+\8 KopDgnGA( q&V-B@7qr D. u%r;I5Y낖`-m6Ni3s8وs)wJX{3wtrteF29Fi6as1icvpi4&E~Ӓ7'2p@g Nq,臃Zp6ZsJ]ퟡ&8($b#O+⻽(nX3 `$4nj4Y= Px'ďKLT@G ~?gZ/!lăH?ԾMنvB*g=|8Us;:<ƺs \N^[% З{┉KFy`zxv#.ܟXufR& ^z- $NO8:(TA-ڶ "sNHWIB kѹ#%f^tii9; W('@(|`!k,㚍Bg?׵qbk亰O H_([8e4s6yCj":hbx!w_ ?\ 7qIc u(謿0t5pngJ|L%3sk%h|(ǶN>&QDDE'[#-6Vg@'LJ$h37T(Є KqO|m_]^U~D40"xP -rׅ,#P_ s*&8g*p-u%9GEFDyRd#XIӷ-&8>A kַ% s NpN*n~L3@f|$ț2 =!fyP_$t-y NwhFCXdOI"L/FLw018+/.p"Z#l~ )  :udGf(Y4pzN.$f,p@G!JMȁr̬D%+uq Bþ'ҬأZ}:0Tg(2 /BgWi|bמBز>=l4q6thZ_l,)./x< z st}[$(XgnKPInbg>S4x2܊Ξ3Hɓ,wӢ{Dˍ{n5M‰МΥߢ s*4:{6PH^0Enٚ!(?c9J$.#dbQF_Eg.*܅~l8Nr.j\އնG5.H@]XQٹh#Y =?.a2}EOYy1c%$'Z/6E:6>DAOr\@p%cgB}j IY/Nk8RƣnBI9W*WQmdG6|gA'Bz'sbxxk`S]07qkhP F8|è9N Ѓ2f3s}-_ҧ'/9xdJQP퐪}f ր Ʉ@L6T>Ggx)EdAqGuûfb;yQ']<μ]?4 e1}zN lHB:pΚc_!oQ-Zǜ NN{ pO|΂tHņ;h`" {ވ Հp.xMV;,9s*(qi&P1? !vòe3uCBn2@jA݌K LɀplJ"zB BgVB%j+]}5?&TӎS"-+&"8*Ezg6:h=ɄÀ(7LGz'l˟$vtvv36q{6JC PRa QDnS 3 Bw0 f%}C*S?5t~P"5[\[Y#:)/#rb/0!ZuZ& |i am`@X8drr\uE.IL4.zmMĮJ,UZ >~o\3ΎeN"'(Yo^Y Й0Vc@ͳ` .4(?L>S ˖D/2#MV78'Y2i C^T"9Sݢ1 N$[eW(W݀VuQL&fn)ejO,j'A|q=TbrtvviX #]˩Lr^%@o6RqeIUw]oyIu$}0lەG1}ѻٟhelC4Mr[* t NgqfqSSwTP mQ9F|Bee h˦f:@{6iATtb Z.:Aoî4.jvaݦ-0+T o+-m=m(7l8ľi_>V~d.xXxgkՁs(M?~(׽f3vqHxN-8` _Dy%K8 o/f.(̍X2sIېTDdFSnh!x?B4O f_V%e&LgAT-R^.PH{cҹ9 4Yc*P5 +q g*;`/&+Q丼ZL@TnA84Hq ($>_=C;#m)Qe4_ *Oݯqڏ%?_o3ۉk0.o0s\aW:K@f4ID*U"[Vn1ٲ"xr@ID38yF%ϡ7k'¯YӔ}~([in` hf*p߅>= gbV q]uJm73@;f"ldI"~tr,?KEW?/-p s#L9'v6pʓ +gNyYev"(Q$L'p4VL]>H-ۗ?)GY:t"O5iqnkGbsF9<r:/M.P{պ% ߝ7@yE% -n/nNUz>H("j݃t Uxܓ4T $lTDZ&DfDj";R)msND=!atgŮ]'<-G*, CAJ6Sn"~qH""ȎBLՁ'A<4w!,Yd N6 "_L4va٬S սzɲT}w*-yJEt_cHxdr,ʈi OJ,=&!ѐ~dG?s4J@g888. 39!аH|O޾B7(fV"w'C$AgΚF! 3* ׷~d}lqMơچ&h46)TXljJo d逾[ NON3*h3ɽ[h~,<&jٲl>g㎚sbME :Q$ 'k4> ITK R&h1vİM 2S9 #RREzQ80\ki>ȫWoDJ]g4+=,M?He_XJaБD{ EJDt }P;H "8~W|}N;Ϯ qV9Yt}C;  mBunP",ؔU9NHUY\Or&i$phpinٯhM PAEtQu~|~xgdkDĆDnZhZ4d|ȀY`sDx5c: V,b v {P׌& N<\t6jSohS'MDisr-{$o^)eD  zAUsۂ:V]Fg2rDְ6X*ѼU]y FNp稕?K2!2{TD { rUB>Wbs.>er(AKȃ;,'J[ַC\ߧ`zWCfq*\ԟ5#!WDfegyrY<] 5iυ$K_T[*#K0q-4r,cr# |f4-g;؀֫[pOBL#&ȿg!'2)?4S$}XU S$3q%C(jrEd;m ='KpJF#(>=s(ҊhQD ]\DƋM<~!s"޸U]U% NB}p1ńIqꑐ Ѽׄ&> 5 e#D8~8;/Gg~H>@Wp{n'[bd Y :|E+@-rk|nFgWi?Y,ӲjSN3 '7NTHlw ҊU/ǝ(>%.ӝ@]3i̬ jw@bӐG"ڋ fKȣspuJk^to|ՖM~߂Q1N%?v۳Ha dh{b_!b4˃#SM3_M/\/D(fە} 0"d[rJ5݅ /`?-g<UoN7ƭ!1QQB s> &g-&VizpY)R î ;)nF FvJ<Br}!ܣɲeقꐟe8Iu;v įyJa=pvfV:tvT;K8w=u^^f4_ucJq>f4O(7,hOʏ~JEu\ R9jw գor^h.#YoUM$9foO7`|ɨ#V Xж'[7,2SQB{ |&v K\C\L?xcU5 Yr!+5㒗Rm-VaIN|yt eLm#P4!j \<Ӆ+ǚg @ЫE>+ BCF"͝{eGYgg7NwD89}gݽ 7!ϝ'(Dqᥐh@"D4DHB#lv7 JT/,MiwZ;E;E΁v\ڳqik嗵.k_9s֑t^z0w(9: LLh0O88g<a1@)&P>qҟaі PC%JLtQK*,9Ж}#@AB^B;0]&<.QFxZnэS8{/];wN|8}ZM? } V1V;?i ;\|nۗcy ksuڞ[hۧ+J|z.U@~q/"IzCptxJt>E(pe%0嗩28AAopV$]*' 6m"QN=*AT@k75"g** U%|&6`Ђ/PS.PHwh{ \ߠG'y"ā (432q$D!շ W=LiNf<㜆ؙeg.@usK &ZŸKnPp7HzBp36,BEFh4wpڜ,ln-YO{S uĄ&B(*uBZy0lEӳ)Y' -w0{Z$$SU8C{&8! <΢MŨ{B%܌^k_A-%.Sz>0Uk)sZ;STHuՊg2$D^fʬ7սz>Wm["ʳ$G>Emz}^&D IDsbp5%>E|v6b)_0ɵ[8z1koQRp:.ҵZn]()ũ& 0t!s OڡѺ= tAGGeS@c'b=b&bQ4tKO -Mu0NբEbfg?c&\k! ~83I3 DKSO2x4rJ|:"&YN0ZWnVreB#`0{vfeĔS iP[JeU- D<=c%wQ4`BW*o݊TD&ڽWmbݜB/1۔_hwBI6*kl(ο/h'vF8Yψ'g& WAi.=@!\7aVGC^gTLХE{iݡ'ro:pHi&L?F {N)_>  ?}$c~ߝrX f 저/ߐD2<BM D\c}dШPh^FY6[?eB7VDJa5hQu|gH:*Z#g|gy6H6K.s1H?MI :i M=)AխrbO|r~[LX%PQ Wc& 'h'F/c%2|%?yd* 5{=pŮgMuapc aB3j?FHdMh;F`>Ch3njD $G ;pԂ#wpv#A89N2NZ킠a|~Wf"%)J;>b/EKӊ0oڽ`- {5ߡI0Nsӏ@i0tS*J e]ɍTW3p$ؖ&jeQ* vC6k3@["rC&~NGb]#'5fy|~x3gy mO?QkSrD*gp@q\cG:Ch(d0EY1pS3lE"WT" /p<˄p&[ 錠I+@Bv E|Js ))6l P ⠋.1 }nz85[giڻI\/^ Vs>Lߐ;;b&$ՀJ0x?^njG7əES@aI|BG{+q(JOhEhs{ikՉ`ISQĦB$] ]uߪJ>ެ] R)"U8pD@_8Ӟx-[ۢYXC삋?>P%H+.gqҩB:VT/|Bi5bU1gj Y:&-4wXrTFL?-xP#Sg!{3B !ѦMxR:hQ|T)zY qc /7v6)Ѣ"S(݂(ŋU^JH%4i_<ᳫMSp0vY3 b8*&DӲuse҇Vl+Lh\s(Ӭڵqy蠧p_1x@϶U|)R%ϐޠؾ%K,˓qٯx(N%.P{{i$jL8uLД=׭*}>NwPͺ%C~+ ʬ >_N+7M9>G4c/r{׌p!ʸ|_aQ\Qc[q| 'PY=*Ѻ9r~jQ "a]'K|uDž]azTֶ[N?֊f,\y8OH"dBQa3lƒ  ! [q[ ($"q)h ʈ3׈`%ڰ*#趠Ǐ]gd[x\"y|~!@g`-{YRl&0?3F}ٻWtd[Mp|<}־K? #H- uކk.NfU |bsQҋat(6Fz.R2t)t#/*[* `6,@o)zu ) I$vއ0˵TO hZWV6mcڱP_P7;oӭk4VtA)]'r{L^njNr:8.C:3oᔤu1Οh]F:aN4[)2Qh(bMg}} Nq7C}Dى]0^ 1Ej6XFU|oR (zf{L3`p_( MBd˰\zH&ߐy&b e \8{_70lre]$[hb/Mp^&iH 隽\&dɵ%T b/z2as3 L@ǵŹ#+LbC}䎐7pxd.呬olUWy[NqQCy UWFZI!Ԣƕlph8K{E(h S= i%m͹ZU8,^XO>\7b/,8%QI߸ Oa 2Fh EjDIuLLJ!^Ey uvu)zY^j`՜$Dj!aqKLW+[.#Q*>J@uC;fSvHOT6 bmra,4ɇe%:@"Hu~h428|#7آh}0׵Ko)U4iIg5աY Gcd>|shIEoKbjcp?2Q ;Rdi)@ޮ@7-Fڽh,s7K_((SLݳr+V$͘"|YB f0+eJtmä͓4,G tʕ%dMF*sVW.? i@ D} &oQ'raV(wIjEq>qsղ FAާ~?i^]~CUI;g'KHFd%'!Q<dfK<%:%̴C!й.fq]bT`6QԣjGIK}[]T(tG2@(U/N&M]@6"!7 Q;\'*"y킵<, `'[;7,ō]dB=a(eVH""CFE梞ۥɖUGt>FA_-R_E 4m ;zC>])q"$8y6|HdYEjV $+@ ȋoY59 {S=+-Z8!EHinVP;Uqǩc4"7Pq~ " #g ? ثJ1Qφq+%m@!!E=ڶ'7fnG{;Fi(iFaMCmΚiK^\NêyQVgEEм@?GP ߩsA=[ > u8~6\@gSȃu3 P0p8UqMi=m> 8+0N|2JH&@|բorJ< pXhAI'=>P{6/*6TzWH޷+>`E$@o(Ze@iXʈE}e"7x>XZ−l쨌D12$5zJᄀ7bD\ 4+BZEEA!tcX"sXx$N ,fbB? KK8^( )ӣLwYf{ jEen*5sdd(ềneQ8Q|268L>$ Y40m T~,[ٯ~opAf#{KYkj;b'K3VK^ -rTI oTe`Nةp!R=z \hb H-<$ЈdB=PBhA< CKx7ʖ`T,Q7?9[0x!~ QӶ GKL! `6(ju$eZ e7i_TwUlKt9>Ʉ|p*&Y@y,~D T]/?5eԮݜZfּT h`1*A ]. 4{ mXv&aGN%*MP?P6|kieيn!n2$E*AP &4J*Sh6-%2$$Q|G^Z/ᵍږ|P,"t`.}~eՃ כuIAϓy3bi5R9hU>Y?1Ұ'BfM:-{ "FHƃLlSQev݋v >I4~4&^&sq(L^N uƚ &/~ c}Haʬi k^]8Bi*V=눭J@']]0x5vHCTfO9܏~dr?>3_@Q}#T8  ~E t>{ ˿ dԼT@$Z ѰSf.5`!57"), B/OP^7WĪ6;M;bPےG~(ǡWپQ`Wo^\KsYʞ,&4+龘ft]Rbӂl3w;kw vrc7$nh*D4b?KqW VY3#7eFZ" HT7(Te g!ٰ#b%!*b"#[TAGToGyApgzzBa1\+(5;m.gaD&pf3;"*mD;_w]}rqAG,H0ud~Li!?_R jYLCfpXCFւ#9CcŃࠀ2Ѩ9ŨyT5  kա8/2(,VIB< }NIv >۔FnoOݴ*t]}B(nEO5 G hBwj?z7٧M`wA\ 8"j koGrնz)5VM..(biGu0^|V\UK} &a#aiVs0{{?r~aV TjwhB%`Qܡ~-8s3*]sQp"ϧuu/c3:=0V!{4"@(GςQ]q\s.ϹF7K@Oխ(3[0.n`:hE=tC='^\cHl""2eZM#jEY JӏLќ f*8b(֊7 )}C!ZH=Ngc*_&Tu[=UIi?! -Z Ն?&Ep.Zl>g#TH\J2PLGoЫm&D!GaU>s-$t)[51 2o'q#IFMk6!LqcfAvղ '6%[%%Šu^[zPa̵y ޶ba^WһDԛ1T[ʗ<`P5RYz"8yʑn;3g#U$QD`éaH+* <۴wz¹(I8wF5ߞ2[pH ~O 40ZI :g=}%N)c&#Lw88L bqF& }׺ |130n8CtdDV|dŊ"s _npiGSY%>v18j6 e shDY:r~0Oo.Ӵ)8c?')RKɧ_ 䋉Dvz?'?s" bKYFXD7a$A%&fs~UbMUdT'}:)]=2ubBtołG6HdFBCa!͝ $Wy{g!l7m܎"lI$B.vmouĶILx@FD©"pͮ!D E"Dr)87`-gi5_m~nѸ4 M߷Mgw">olY7\mX&l'Lfg,7־vgjm7+zn7]~š++~x\=;.{~!p{:l\;j[Hx GW 4-k' خgT g$9Zpn㜖pqnR=epoo8>N,V95v>{Cwv/ Bu%WC^zWt plJRD DGJFD hAF'}s{ Ѡ4sfcX*4[ei|/A=pFdvNɴ q,h[֜f}N#4;h 5oP D}'eFAuN6Հ0sбBG L\Oqd2ΪIA7pNt@_fL\s4rȇۼsZ=;]<<˳Yg)AvSNDL3;!DD5`#pconXg{ќI~$"Zb\fkɷD!M Zw[r=bO<x㋔G2ms%a/t-_%8AUzUpB =.)]5 ! gQBJkHn\ 9{ mzVUR w@PlQ"<.RyCYz%:H6dHb2f"70ټ!g!rNHGԥRZ5E}d|g @قӫj Z !Cٻu4t܉6mw|&M"1 (~l^u/-KOUvWaheH%HK|K(MUx䤤r}L0pXN*4OCU yFx>Fx^Zg\4(JBVH2 }Q%D| ( KĈ+h4iM ~wQ.!|*wqզaiL+@,'o!IrxA"Nò)S`A;|"ϔ%J-p<;#k!IϐYbslS<N!C׺")Z)dP y Yl% NNe3ÉS çP +TD'qoBEBuAkZ]7;+åO$m8DH\4LD1^nFL-"b$Ȫ.%gk0l{R ^P^:DpqlT@@'**t|?OJLt`=[r"=OU+*h]~Ф38&Ctއ%#}AWo`>'۸ GsS 3f!h[J<k҇8cgymYzXe:0ƬiMeՈ/Plt+xi*(]2 _) hpxaQ8-Z4R}]<thzvG<D3w(w\0 r|U N0]=Nl&# mhpɓ݈f[Ea9LQW`.eW#W5TtArbB-*Gcf-i4I<j˘O.G)-'p-\%J[0hV$S1:YTDHժC& w>BbS :I0kd5.tӪR"I-J'Ϩm Ƿ$a4p2?Z0\)҃uHx\4l;ҕrcHS=y@jR$ΠYry ZD$7өϓ#q z>AWYjNNS+ďrtg'?Ӟ6AIhC,WGMHiI4d<%,7?Oa5}qy:ϐ?´xԢaY[ZY-s=) vHK>!$L%*|h)+'1!gwY6[;2uV:"Erv'b'ChFbg @ --SSԩ]=3 B#OP ٫thE8ZhxKgm ` lu~LЙMLUEDP O2Hݢ՗A|(ݪq p =^Bަ;砕}EE8y5Ep<  cFL^-tOҫc+*C>C|g1ߟ"S@+CgQ7u;HiT g&sZOF_6OL;xZ =YlGoh́D#d/ θ4-A(@Hτ QA%-g3{ OqI[UhR?}c T֧ +bپt:nO`p>4zm. |j:y9Y'6"Lo-ݻ p*OX)Sd "՞x lYဖykid|XnåPɀY&r*B?ɡjzV]J3^,1޹u7а#b`\?{CA>Prp%g@^$ƑG=Acwm!uQꆎ+ Q-.P{\ҵ ^eq`ꚋ9M*L8h-R(`RU{y~iWrL'c[ִV;Ӵ%n `NžUJ`ďpQYXfs\༼4#eC C _O>Chn/b&<hbT{2)%ŒY5Z2XNg4XHh^WfĒ>(5bXP_|r\bdHcWM!i`Rcv\ ƏW c֘Em;@¾dFo*: 4^[*= wkӳ3q"W y[i;R5\)MB71YFuto)J~|*`n=bwX; ({^0{XU[{\^85+kƯ [D'kOk^ uod7:T.M4L47iv*衴7D"9#H d9\ }E.οO~!d1ߝF#՝Y7I1fן M-*9)Ȟ"Vmрd7TĹk&rG"KvʓR.4 x(@0D]"*z7H% k\ٛ: BjJmqcDkUD-DQ{Tbm"}Po 9; V tp0qf,{@8GV4R3pz8Kp1r *Q24I)CmSg?A$NԯEQk#rDKNpc4q4mU:7H\EmɅ"]_ՐPCnodMledھ>tE5id& W-W%$+H|\Hy6!urQ%K˷–?9s[icYsGlV/4]TI땥P%]6䣛4ʝ;*Y4T3]ze .e@4.T\ugjKr"g &AJ8K DFE)֊dw"-lg bV0M#yqsg Uĉ'¤ soUOT;q.3X|C ]PRٜݢN+ t99s{TWٕ:4+v-8o@:8tt -OQשsHk؃uʼtTUUMَ6puD ((}\6*lƎϋ'UoODN|Vw"LmYET|Q~3DJ&8%ڔDKUd;bE>_rL5R[3B*jVI/ KPrL&yuJ:'nK'N'5KG2hEܬtq,٩nH_;-<%18IGql{WDŽ賥1qhe@RM܈-9&Vl1"J,QmmJ&l6NWRZɑdjHM0SKKX"?.ީKHtýNzCU= )/gj`ϋ$tED:8pqbC7 LdKΎh ִȎJߙͯneGE㮦ޤymJh˴h~WxWenH^.GN]pn_Ylx~a97M}:8pad4[iI}*\d6xS\J<$ LTa&]пK*n495xQq:]n 2 r_|+YO{ 0[D,rvΰ# |iU'6K#w-vK SRMt'/Xm|QᡣM:8Xx%C:9 pNnZSӴDq|Eg{$U-LEs9)Ͷ1t<0$] NLNDBJut'De~mi -7+n5`W(^b7;\ڪ?|H4miūqr'mY4+:zJ>JA?tH$fA@OHξCH&3~cp9 Nz9>rSF|)њD^:꺲*ݽ*5ѶJFC/=(fHza3Hh,jD/1f3(_3 :^Y`(n:ˆAfw0S  pw)sY|UE:WC_|JU 5@)4d2 .V;>@MZD!Y:W`0nI곺jΩ_p]Qoƥ<:/T84uai8npO+@E6C:f}0y_IJlUN$/;] r .OP³z_l'+4#gwy-BHQkZ컴?h!U߿}uEEu"gAc L$_ؼ\,MDIhv^K *CBg[Kw|۳%j>⠇%l ]Z|I2(G tw: I @T>ߘkXu6!hY52njEBxz\JsZG,N -(-:gyPgֈˇuA!JFZewTF!Mb-K5k*fum#V2[pRgj[q<жfkS$s .Pݞs筥y\f] OQ*!i%xIx~VٷsAǀFN_nuH JlZkmnW;? M[NJ=/im˖z7i-5j) JBcߓ. X45dM#85CBC"͝ eWY{zVW>$yNXRs0doMԤ &eVdv$lFeQ԰)$3L@JJJqJEx]Ys⤪S9/w-eK{/B~ó~e.;w7 \|u{΁nw/HznxM:nNCɞC${.4sipr彣nKwI0k & &%0& P+f010Oa`~.b0[:o/,Ϙg$C!ݣP,|v.)R&\(0mdZL^s}O/h23))5?Nxc hW\:̽oȜdy`g#vrv`2XZ'ZltF7Fӹtn/>pp=Ax_gF=cԞwO$ u3 |4]"D'ĝZ4q#󫳼4<jIcեRvϩ nBdg8rBФ:ǫݽX :i9=\[UNKB?L1$ A?8k"Ζ cpcg3bz@q[ ^áRΎpL gϔ:A?bm$lq8  {[j;u H2Q\ٕ&@TgzUC`Y8[]Ϟg!P0|*o|2{< SpngDgḄiVk,٫8HOT%; Bue]0 Z&S&8qAYWn=;-I:s~[1ͯ?P*I֗u/ Ͷv|L40@tv/q3fӴ,gUr#uTt¡ѷ FP&|GH  g"rvP #^dt&HΘsQC*?~dISB==z¡[g"}Tj ǫ" t?:&@PPR@*WT|&8CeUzài28;8˩n B]x",#FLKcSB{w17'Q!%* wO'( Bun2S 't`5& > &4qѴhS9phd5nx;2 zVq "y"AUI&|v yQlA'Rr(DED;Η@ȦaPr2a.zv(}RdPMcI(]%O\QJþC0TYmm%ƹY0B%5x Dy>0Э@H!D )g}U;4 U.ж"bOU(KуJD=]*ў.crIM5p}s  63@ pp|1ڹ=)IQx=F>pErAE@Zn C%jήVg '׎H߶ S$BoFƽȨ  {?[WWJgÅ 7U!5jEKiVS(\L,@K=C -3U ]fզTPGǏ_&Ò7ȖUdr,27EHh,F9{V`tZl٧!~CBMNb{:yA0KtV4r^wA >L.+#0*3Er$P뫠^);pR}2ջoB_0ν8?2z, NHWX'|'oFўDy嶛ivvAG1tr&9@q.:tC6TtP$\\p䈻EAeEJ83rU B| Ah!R3m0B(.di:5iWd\;8|v \Fyϼ#9.Йv{:hV9 )UQ&F\NXr$4* ]&8>L4kq} !U *g2! \>(@BZ&3VٙSMًMB5 i>*WC@1 M.GNtL6+Gؽcq%#>nw~ ugLM"J+e`S(!lou%zJ>Ȉ߆(/ @EڠBߎsY4ADzV=}QE-y2o6 +$w|}ۛI b !"W圈'-~?+]!U`"r*7e5R&.ȲsOQ%QHϮ5B t}. i3ejR{MG*"vjܓ5O=l׆!'Ե*! ٍ&go2 g͎zsxhӨ, Ltu^n'S5GP48 @aW$u@f Ple (&DD>Y!dRb))xx)W5Y@6Yֽ~\a"RTNE U^^LU{k"DJ?aQY#Rȯ6sAM!mk7!{.z94{ǵiF8E{W=4X"z\Kvn.`(i־GdT( mTE|NP&l\ܪSL<ψ)T.kҍGR:A%!R3%reC<4N'xH6yA$|yEIنK$&H~]mBDeH[DYVE&D OvB3rQFQxpa$aR%oDhDqfc go'z|Zр6aW8Ff}[)Un?y:XOۊ 'xpm**0 ,z(LU`.W=b޿qvq\K]},/`N'UWaYu(QH`2ZXW{dBndk &{~藕#"(Yxz"&j=sRumoWX3H?:pe/.:>gEA)[IgMT{ _&A4R:7A%x*Faڤ 5 vqWRLܲY< wV)u+k O; $D1N>֬ jۿES։Lx>ynn xT?;s@o,/EchX.X$D^$i"۹tдhU%4 =)i #(;F] Dwyϼqrgt`@b$0Hq۶l8ҍaw3PbNbB4k)?r}[B@R2]DFͽh6j>,ոQO,ݾ!Rhߞ2kiFk'׹/ܜmٝFݹ|:p!8 7,7ڰ$ p-f a\ݝpo4*`P.p<^n(X%Fř(qY7T4͆-GgKGU'٧X!MgߠUiQ"?bWXUu7t<9ܭtkt8hOfYh*v ɺ"}> L Dv<`mfDW4ێĴƄ6>K*Hu&D}X|TڶC|2R{s j|4@<RjZR7ѱIs)Mg!8(@t9&8!+ q:pfIQeHsq4XUٸ"茔8-{"nheI^m@D$[8t MqH+Mpf{$H0LqNJdrUphwq9DDd!qϽeԥK%YB,ŦTH4=U=@]ݲI^!TIz;S>4QB#+1@}a9古Xbw~R)E4E>GӁ22#l(?b_N@!wlX7 r ҋw^V.iY|Rw/v GY+++Y.xoan*DND k~.acmNA=_U Gʶ1-MZ1jPw[FN)T)XJMr9׍\0+kW vyEOUrd\YC([''Ҽ@QLk#2>n|W _,x'xBnU8z8v>T*g&5Dgͪx8MV!!#y v=1 ,Q{ߨ)f# ʊ4Jl{m^_l /g7o3]mh`ך~?tldT/ _Uy>{ kbh i.*i , ,]pL?aTlhWn'D#Utm0k|PJą ~0oh4[Oľ,hnUvɨ2(eHlpz#gFT&5H]?X9K., lx@`'}giY' =kb_#8a@2D}/CV}do0Qa'Kgs(ܷo5ezTO2N0/GXBds餎^SY1'DAB#GsQdDHM`x Jh:V.MZ'~ß"nc${K[^ZKK/xJV U#[zpSri LhV-0*<25~ͦ}cBrܘ Qb 2Euy7vKi`AOMy9ųe'w!:Raԩ~h&!$Vܦe&ƨ*;&.bny 2YW!uE)xVnRa**Y129; Ⱦ%g횭i\N0[ۯ(GFNw YOD:Qz>BC[ S .#;BT䇹d~ʙ"wɩpvIE*;AW,#U#y 0>RDWI2hȄ߯mG=: j jXA .G_!W5cYUD7 .(ЋٖY9/ Zg]z6#)yn wQ>dƁ g2)N<C(m>UP\8ԬȨ6Ta͗ hHDC`vpDTtoR~ATKM)~QMj܆r2=U<*1 FH9xqX?4CjGJȂ>aD鯺O^DFŪ|OLcHؑ>8U1 ڌ[ꔿTBb4 gxx=l̃FݫW3*Os?rrY[&;Du-aI$<ޯ J#IS'Dd'Mڋ mZ5r6Ң*g*\;ofQL{$G^>6JQ_y[t 3Џ&+%Q]{i}$g@ h>HJLh?{j/67ե>ށ4 gl&]߆;R1iuދփիQjXOLװu%ףyzB1^vp ]p>~Y;{'&x Y, &mbBCO"͝ eWYMh>ʍj,ۄdY&ۯ'Ò`e& ;mщȮX((Pdғײ\r+,pK+s>y/$2ZO/j?eC;k}ZGyek_~?P"^3MǛ!ěޓɟE'Վl4[Fc[v\mԷɱ]_?]_;~zNw{)ח띵K.ڸsgtjXjɉ_jp4I4GhN^JSr:p+&8Q' )ԵSӊNL>Ie E}<ߔ& Rр(\γs/y)N p8`147ݟM4!G"pV,'"z͆PTsҟBB2$Rf@<ēޢŏǓBߺ +M ,K*\fn,B&E6HQ~. < 'b8,&BpToNwG^f a09Mc>(a|Λzz!9{ O 5=EuDg<`)ъk `L6"z19{db-#d&[E C_k!0\g6D 6{0|rF+_4x`}F)LG\&u~EʧVw.I0Rfd\.e}SB%8CcYӉ ͌fw{* MB?(AI fM&AdE<#ΠR曮AxM:ExJwv8Gm xXѵFkfS( }nA gKs1NK!ѪT.$r$F"Ֆ%oG@Qө#5:4ㅜiZWUqF}kK|s)Btr+7dawsًmPvx(cw =@cLTAXO'QΆƇBQ<CҬPU7 lj.ç}8!\F##a(|3V-Z^J@pNq;& *Q!?%D|X?%j9&^7YBFA^gL*p~X %4`Z']k9 O` ~Xn7r!}EwnLAD8pf8Apiij]ܟ2!g2Εxt t$L>j3pήrLNyNa|kq<`RtT!K_OdQSJoB8Ր%n֫w3E8A=]x O?,J#p"'#7+p^?# gWbdV\54:Gl 5 P%SH>K=*W0]Knb—bUN ts/61 aIᤁCԁ3D:lbUBV ½N([<oe8/'g7[ሽ- c7}s#7BQ༎XĂ8kj$Yv\} g ЦV@CeCCA@QhVs,VkRjH8:t#pX&zz5;Æ|a< ScG,A> s:Ad8?J`/DYZDx:T_x7Ͷ[[:V龳D>oBAv%rv)$R/C %KF)ij'ȃ{ PR|O3R7=]NJDĪpBc<3rHy;2ơ9cW)Wp"XE摘j 'BAO$]I4= Z4V,ey0:Z@Q9y 89ת*yonŕ}I=T^1"cpַw[V~?6SiX+Rώxu:؉zG&XV}p79;MafKNC2"9>z9Y@rT׉h-9%u@On g6Da9aQW;"ȶ]ؼ 5Đ=ۆ(A8$1v?U*._ 3q?q8馦)SÝ%7Ԗ~r]wʈm3ՄAR>NҭT44cӘ;s Qbm:aSJXiZt7XdE#o}8Fmpp,0@4oMKsump|(Uؠ^I]IGAxж"O6KHiPIϖKCY&E{ђm<:=.Nw4-oc$CLr[ͮe!'oЊIf_+I9Oa Zߩ;FYCEf^nh!AmљJ4FE$tnUs?L>afuhc <Мr)FÄ\BhR$g_a_9,W/K_?~_׬8ݟo)Jx4,x:o)|BUDjF%*!b|U;ɮwDbc"ZbbphEc'[2&:ٓm>d :6AХVa#qIhc DB@L`ڂK26PEꢔj)U"̳[(}/BpֻDeu8/]xd/P£CG<&8ʈ#O]7] ͇MNӭP+!aCMEtu(F#U$$(cUHйHߏ8҆>ˢΛF]󡣡k>`C@vJ#tWVPt@xK[מH.ؓ =AYZUZʍ^IOjxv!;A価xxPV3ACY* _%4ccP|pKUCFyڈ2|4-`TGu "gc RB=N4*w⎔/Gt!g_4I!x覦UaQ^|D>ti&UNav)L Թ<0$+ܭV }M`]蜴LwpDTv~Æ 喁}pevv$,,H]6D  {M|.ҽ%yU҈!/.jyBLkMVVY Bz nh*eds  S2\+˯ 1sH$W+C+X̐T5^eWB}6Ӷ iMAjVOD"MKNE}]bE%=43+2Zs&4;ק~Uena5U'U'W[u>q||>X-RK{:2˻mhmf2 6 yHw\ h2gJ4hۘ4U]Dq[HY#g4~)W:;TfJ|8\ ?gsҰϴ~&Oٟ JM$':Cj5 qz 6y4WF〥>&!Kݟ@rtr A\^3 $X7az2uێRu kB68N7b{獣kUqb6t6[LM,>q^~P+>( x)p۩z ?gӈnR&uf2,F-n}xQ-}=Ht3< Xr#Gx:"ޞq_D>eeEf(I̺g8 4NӭJ(Fz:طt N `8uփwG\=&NV\ӤAR@<9(=J#!QuvdAC;Gy>1{eDo\&DDHwv%z#5M6+",4!g㮃u^.-$y'o iܬ`=v+1'b㊝ǕٔvTچ) $zp9ʧC8E,HTkx9G90T Q5d79V W͝*P#|v<_,- 8o yx:u:gƕ%[x"}mu :}h{X % ϖq 8T>&Aq6! @V@^$^/+ץPoۍiBNXId-Y%Koro;sa~F1eHiwBq&-O<J1eZ`=`suɕ)D_V0S2vqhI?&[o[LПwxgNB0߱n?b4Nbyy 9{qGݗ\(hΟu?3]7lNdYylQ_!ꡨ'VD\zKt}8d48UoAҳjSmwhqe}*xaeK1G.7&g1R+dbȟ$g3^ߕzrYU Oξ`̒r Q1\'_ڊ=ay |1d5cpy 5۱i2Vu- E!tﴻ zH"S!YD^MysR::3 5uU`7 BNꤼ9du'us]y^l7ތ<7-9#*][ OG*sBpԪ[6m0 BpԼfq{ĵ>{дӤAO~xgƊG/٘OH@˕ h^δmh:~_kNp2c j jO7- 47x  jZǂ% glU9'k~zv>j| `5.yD)<:kVSɾB-rAd5<8.wg qokݤ:iMWItz zXjį(1z؏Yw`R*sw~*&mDh8YGH~8p9+Mɴ>0\n#""ׇY:L"=șq{s{W6@Ey=etkXK*5]4}L'B3sMfL#Εi68ҔeEB4Ur#ÁJ&M8cN> @r(}hۙ|g3 P__mC$?6duwp .VHKhNs@}}xqT|\*)<_'oLSyߓ B$N`A'z.Lt0 [wl aWT#W?g?>m+#1rł4l?QSfvme)*1 .6p{_1<( 'kgkFguGDXU` &W6Fy>}gVAպX!g c]7Ϳ V GϪ* MM&&)YE>s 9o*Q+NEK@ؑ6툱b_Ω;,u868!*Eߞ7aw8kppwwpkt/ "aW$Ccn7$_"rZ H+ub<\Ùej\BC!͝yeW]DV|FrLiU,wl}y䭀,MC# b4L"bUX"dքPn(R.%RVs=ݳ;=+9?w~\#.7GqOh4=7'ۺDϡP#?o8\O9\N9 o4v՝Z{uu՜6ךNmxnlnut:ݭ摨w;:vtӉ77;cWm]uete:?BAщsƷ rH_Zjؗ!} =*#y!:HB]ZbTA^By J˄֪TaPP9VHjr{RfL8*2ygJfΧ| PKpNpAp!x O3᜵Z]xK0a=LݡbTd 1b)y\g!k_7` I݊<,XU[Z />$BM2MLXʀ<Ϻa :Bݐr۫?I`y^?Zb*XY p2a8;z]u^ /`PU*k`0OhLh}È*MTCSZ*Mn}d7 W GӜSf}fpQqL)N.ݔ.U=VL\54 > ENJ,>%gTS~GÂaGX g5SQJ~J ާ99F^b89˸sI",k>gw`$BސG>ANK<-IԨY&P]d.;j~; .Y9_b X^B###$തfz8(ȉЦZ(gQW փ,B7jRBKhTe>y]cg)=ا\ 7EZd6k $Y qӂfj05RdX!k,`%2 \pdP=BZbzEy\GF Y\?3#dH H5a#M:~g$+եg. EOrF+ AT?̀f@k6Do?~ DfT;$C0sjBF _vBhԓm$k6XH<.椲 >w{Lh~g!^08}1 MM!{':9MLfyS2>"V>PlSPg>8@A^X -u<|n}T?/`_Q^B<@UGܮʰ"I.AdQU Pp?|RXgȼqTaQlEpPCìBp2HFbBt NY;ۓ;`Oɂiʌd]iHgсb޵yepRdWz>= 7l0QTСpήu6 { O=Bg{.@Asd&,%/[&A(Թ M ׃iJVp4b?՝V}z˓DC_iRv}zPs\x_ D\ol%R6蹑|?aHCA+=iDj;;cH,C^i@(qA D&3`!a)[]&L0󟲸`DLHAbΞD~ǐUVLn Q7,}dwL\ 9lhÒ$$[yI~yeQOCG)} ,G.멿ҧ ҳ+r43kڱJ<@0l$N]Rσaq/yq8G,!*{% 8:F~P&aٔh5#jZ}]#kӋҫxXj ' zwDSHFJBhTQG [V9ʲ#TX$b*:xp)<KcSJpT6ƆDjzcpuHB2RA8t 켁R 9PpE:zep/1Phh-5P=m!4R( " -қy&X|Xme+يbs*#-̕"D|( d(4BK[cv.XGIaD\էG5k Ǖ)qȎPRUE^Gn2A?q>,t"#äZludF\L%4jό.K`B)~FVqGKp2!/ɄR 2k5aGd^*9,T1Kot Ap\. ʲi Muqgr88ٔOlAcVMU^c_n{zFT2yyf 9?Vf8&v#ҦhzӃh$YL"Wp,2z|_FhU;Zu J:Cg$* z#PHJW{wD;8O">vE҅<"ӖM~ `'-:C&R-=0g8p1l&k#H8zQ&HD~LT^7Cv> tMgE"?R]lGTԋ Zst\Տi$_%k;&tY pؙI+ݞH+4:?B]J;IQ)[Sl*ժztᵊ62]b8ʀ°BÉɚgJZh%8tDz/8}wu]df@ b2@Sv|)/TCe߁q&J:W-]C&qU =BW/эtY"6$@81dӵQPU/_ zCP -cY~ @%!U_RzqM@.Qթ"1hR:I/#ZdB䉇lXM=R>k&48L'q龡.#DaF!J Դ@q7G% -F  -,gVf^׮B6=K3F?efwћ&8PHO QEC:( i˰ȋ^XVa䋯{ RiGބΐO03Ok><~ fqgH.2MBEllu\]"Z&/j(sfhmjN6 JTšBvvZU^'W=waGx.Lqd&8l_f&uWph1Ђ̣FevB^3ÙZIb ! $@@ |^| 'as#c~v4ʭKlV+6 Dw/4Q+U]~Y5""h6*fQMjZ7KE3UOzqCθINn܄qAv˗Gh3Ox`(ﵫ[PF}a_}oVir= "8mZOPq {!Y%TÎ(-cB҈9"YSI՗"Y dGUHt4o$k1zj?N]TuG1!e̖ t cxt#^tP"k4qAPhPPP`v΀)t|I =nϧ4ە[hf`\!qQu 83 \dh6o}uyEYG9?guIeY ;$ qU|&ꂄ3F΂iK4g^6yOJ">ph6qGW(09J,3dcP䲑7vfj״PZG)}C&P (U,xGar.yˋźVkS& ׍\u>6#Ŗ̅WNA%[R=Ė&[}r{(p8p_ΛP2OPMHq,Pcަ2rn&$({;wq&*r$W?p!8ljOps)8P?F2RfL2)Eír bdWP4z@Ssh ,{$J~EItж;БwZ|(;.d8 1k'P;g|*8$o@ڛl+4!nGbr9,{ jG8)cojhVhZ,tQCXLB+ Hv HZI%:_s=03P6^|OM}#@ٯS./C'/ ĹՕ@ ֚Sc}h[͇jD n!YFYFTfF+=3r0R95v58}UR_`vnZp9 v5^ר" 2aƳ+ j#ՋG$3@WȓZ k*LnV쓗cl@O?,Y` Nz_ml(JYcfJ|*kf09ԏE/ Bz;MV֦+ªI|yW$ԟ(P\KוqqLFp3i^kpN 9DDU 1GĂyI͓Gqb|?a|8bʬ!wz%ln2S \ܳ.?">MBC ՝{eGYB\pJN:Iglf^7aOK$3dBD yDQ" CDf'@Q*C*XVs~3{5L%VWw^^ksӹk:;ʞe~'L=rGBq2};(O{$wu.VVֺKKKݭvwg{s#=nnnlX?q摍WG͍ͫ_}76Z_hv5فoܰq Dx7O'|<]) }(94DPc5DƲO(4@Z'DLx"f8agq@m)"ejJ#D1H(Q8TQPƄv(ƲMO FG`"s{=bLv ` /\& "/PnSOm7fS;fHgt ȿ!%q[_]Zoho}lc :rtjLL\?q^qd}c0f oj]ݠf46mhijF> _ MP"N'w qdeDL?wc-6D' C4?w`,pb A,9)|vgDz["Q4 vD@s{bC,܁br/22}G*  t: OC#DrXtgi|0^ )P,L"JM@9S!jեP#aVCX9+P4 py56<ٌ(U ,{1TTqW(0cJx~ xyW˾d3Mǹ凪Gb ~90'q59. Y~)S#5 1QQN穫\8A }@rA!zPȃ" iSqIANVZnC(KR7}gPrrZ,* SZZ"ZڡLND~B>E)T1M=`pc(m'V}";mDa,۱!B_SN}#fx@ã#ZV*st2TQFs"%Po3PBc0$r b88wF y].x(}D+.qrao*:K"n K"mIQݑĈe0&9^82Cj߫Q>u *G U!}8T5%`3ʵR/ j|V`zG_ä$ծh8l[9]3resܯ.sçEeVTЬew4 Ed041,mB$Z~*b]Xv'bfM^NJR Sx^e Zm)Xv [8VP G,{XȂA@}B~"TJs: ݇ehE !N[qjQG, M$MA8ik<ʾӆ; !< A; (piNV]Fyi .4M#R3ºMD ;C૗ 5fk󅠏#bD j A9U!GZJ !0bٯZ;GuAz=`_QήT<X;ƍP`V3ߘ8}'Q>MJ/2 :죦@aqr|;~ Ҹ꣈|D sg#EIIw:Pqu DzOŊ[(Iݒc^+ȷ  >e c5 g &7mgUBaļz1U8G898U%iA$f1m6rM*Jqetq')7I1Uguju:MzUu @C;2ڸfE 崒]4F7]1I9?tzjdCEp`4cEkTJ,;eC* g8ǩ/^v W!y@ҁbD!})Uߎe|&mNGHnE[̛fh2{64Ҁ3hڲr>=,{'bʊ|F;Utm esS?q,|WԐ4:BKm X 4{g8ܹN9+d'p MY_jLCSa&TC8gaك37 <)ztԉB2ֹӤ+d\Յka.AW==-8DGq@ A:7wUng CCji!sH"#B_4T$ޮT't&} `pc8iF^G_e$x8lG u,'^Ҟvl헱V8U2nL9Mi`0V8CmxsRQq-,{88AgAan=^tG2}.B }X+T՚s{;mٽg 8Nq**oߪqe"M2@\? hS}z}mB5[k,ExIsIU0&7+LO,O+W!C$#=MMqvˆN?E+?.DNAcT::<b8ӽ#z5yT0#~qAu6D'0πĝ]@ya;>@b䬂ĔY!o\|B~*MUyB$!-Wq[<98<,{1T],eL;n\M>;eՖ;v}SЂ4Q.pZ ^gYg,5/./JTA}T ,]A,Y|M&tʲ󶛫l dNb،.Ig-Z5Te8Ų?6z:8>J ƻMvkE?u:uu8sz&Ѫ2 14ѫUuftWp^<P+49+lЕᜓp ~~ F?' MXfvR'uT`q6Ƌt լBCm^NIZXЊqb_2~+8j=K㾺hDpF@CSeV:N{D/bC5Q}'}9> ڙ-hH'DQE^< ͚AF7UHr] p\9OTq5D 抣8SXA;B3 !i(_uᬩk8$q >}??gUJ`;PPњ{%(yk6ɹ/}pV#h|_L?dp8TuiKU/[=hB]݌HIX۰85qIdݟz2{#U0+NnN1ݗDn985[QЋn[VAPYi};SSNh- ibW|1NfC [sMFrYY9k$TT檾׊ũۺ#2,#cjj`͗XsLꋏrHKH`b)p)`Њ~9,yY Z@%DHhЬ4.C$"0&CƓrNiF@R=Ի:o;B* Fzt(1M1U1SoaQ8~z.r)=6o,@E0LCg{ D)UܫӾ9B)f:),,ΊSuߒl1Ps[c ӋQ5Ī hހehjtyT,ˆD›q9P e Х<ϬxEZgX!SمvaX/G_S{BmZ}؊';w0D Em' Ƒv.Oy4E)Gz=&:]JrhQtէmp&y:(~`Peukd~o4҇:{o'!{M+'$ϲPDsBgB'$#ٷPsSggMɮHU* *3L$]nwM$Mc:)݊3"iMuDA<(R?#5\S*b%4D?8w@bUMYRV$2e]r{/@?[OQoׁ;P}ox'Oabqo/`; h ^k؇HL[pL$ulz >X5 UJUhE%BtxLbp(ޔ1]Uxt?0EYA>T"Z0jG /cH/Sla Gj{՟}R5!&@0JMf@;¢@yg%>pk SXvƕ$lxZ酚09t SC$z,I*&>eoaƐz DOQJ!9hXpTnٝ|̊7N*f}"ն V:~f"Š+mC#g%^8g0/amprpwAI#Ͳ6ʤ:PKn~ԊG @ OwW]FA 7u௰s6LbqPw`SޢtF7CwX`۞U\4X@|fRHQ̷_8Vtt4/òmh'}ȸ:' ,;f$=XA+Q+7kTWqV)WPò3U J707k5@ .ey[z.XZ `<.gp E>eoFJs#[G׬pb8m;s? xԯ|h-φw"9GCj)ۑXlE(WE,s 5.COE1c(JJ{| cHj>hU PXAPP*WȂt ~M(6X[~t@²wXIOEE>z|",GN"ik!LH~7#P(NmitCyuSC#F&- @w3<; ,PFVh54L9j 4KiFCS^g9΁j_1د(Ǚ: {ӽRֆ&(+hVN z{.sy~9b%w9X1 K}MC^ Jm}4@zn@1}E15ùqއr`gn)sX.tmhZ@AK^|{a, P$f:ccgп_^^2eq~pea@:[[jHS#[h8iWЫ㨍Sޙ_i?NOqH4+ ?<}ŲPh\3KG<7ծyG|)C~}IB嫙92׫\:jVmު#mg51~%/ ӭ;͔/(dk">c)bb֛G8,J$)Y2,E3 D˲ݐeByXq}4@Giԣ~o33rC|MJ ͒H,΍:3uDO3V k6}+f+̖@</00R|]y|Ie MD5Nwl>֧yyZ] 0t_ߑrSgkcґS+['WX$ X6#Ռ0.'WT7}T<ʊXYD=OCPG'Xٓ* ^h>bg²oc6 '[@@(p!P~/UKRWH$P ⮒zĢژz5'n(]&Mmn׭-6o"irVD_4j}0ǒ)Efn`Pl89t) ^.Żr6DA$h~L9j> )[DSĂ/\<ϴŅ qs>6LT9].Ƹs 3T;4,ݝ M$y1DBC.tPVX &-͚3 Y~c[ 8nE?/y}̸> 8> 3b,+'?'luy៭Ӈs.c9sR3Bd Ca# ^WIMp*(pDw8+ q炐)eE_?%?~FC s ѻ9^hp9G*\DT֯kTbXY>7-Z@1n(NW;\EA ͪ:/!-W-_ ?M./PC&re ɠWWiNjc6T^=UBQE2t@{XqX>&CZub-}("ВX{t>Tᝃ)==lvސcZu}7iA g% hgEi+Y0 hX48SF]Ls4l}OV >gV;X"Ϙid<+q]8(hQG-ZEGq_qm192$LqOWBC!͝{egU a.*9LUs_>s 洝̝D@B[R{ЋAMo:v znvo݈l-S>nDL4.P=^[  LxR6L"T;)T B:l 9׫⸾ѣiD`U__23%c.VAqNLiv,N 9eIG+] R4"TGzڭ' +=d$K1Mg<ǡ2pH38YkڭF{wm^h]voݸ;vÍn:n"~t}hἾw%}v_3.yNz K93 W""PЎ;.fxsoh%Mนl Cܸn#F¡ Tz" Ar\xs{MhIE>(i;uqV "ygًMl mX1|{e&DX49w,Õ}Gd2 /=,)wq&Mp\/;AOHBt!? ԩ9ԥ35bH:CY@"::ĦZRX M^5up(pF0g@zQ a.q [\U !vsc.uAE(IO8:<^Qr:s2p~Q9[ ӨaNdLB[ ΨD9b)F9 KyHY7$¦’4VK=:_pˆh?I%$j?g8-Z#0HoIMvi"{Iy QMs[_X4ڝ~dw' (JL0bh\5B3TbD<slӱCc0Ž>;^IdJԳcp0"*OdL@ &A&ױ#EFл&D8?C8\!R3;] Nhvp'"}ZAk*~Z]pUj'vGէ'5yUԯ x  %kȏ5m4bEC0l!]'qeTEhy-; nrnS ЋA_Qpesz 2jOAޭO W% ^uVM+w&$ˌ`GX{W{X鶸bT#AʜZڱnw($z.}*P+ QYDq3uJOhßDɪ4am0y^]w 0r>Q*T?jUf!O ͝굒}+?e?^)xӖz 1 ϣSD q |:09?5W XA%bwKf\w2U26Ј>!`~HEtJNiWDpDž}dNӔZHkJ?aUEICdw `SRi Biz>CdM`")OIx#?kV(ı5]drC0LpcYIs:"7ԶEH.$=AUOVOi⻧ٻ*g)]݁NWDPh0\2ͥD4jInZ8IǮ1Dʹ^>_ [OZu2ϫGdC)d?:;m4'gi}1bo'%:xs`sSơC:ax-kMLsfa@t[k4vv^gud_ ![ɚcb詗y@)]:GdnjJhЛCV;W_|Dv R 5I|} SKC"X2[×KsQ#42QN˂rJ \e _Kd&0 oH4]K81Dkb \n#oiÅ;+F(PGl$ZINd/1!A02u}dIP64Lhp9;6cgϻ~C?Faޡ͔YIQbl85ڮ DqASh>G"57T ؽ\ kg8ⳌKQ4οbR(G0Ie0OԣI2S7=M>SO>x7aD-Igt@?j!*"<@ ٮbs!ɴJD, rW:!U:сY6iSԞP_GD@ycD%wO \uӞA_j. 7`ҟ(YmAEI (RPӚ9C*\ަYU|~AGqo%Dqr*?%$k/&6wzU(6Q=P!iPǔ!(w^;\ ~Rn"{ QJoDn,8q*p(yѰ @ޣǬ{vBdP~ -G |t8t)+pnTpvڶB9UA̿}^kBk.mV7q"5>F0;tC"N<@G,G?Uv 0˔Ӥ4*M.0"D+/@\x7+z1Ao,1Tp򦞩\I pV)0cDO"7Vne KO7(2jwš_tJŝ6"*eb1[fhw=FQjwx-EVoDrF|(AgwQV'c" L( YJpOsN=01˛uFDش3[HYdBJV)#6MYU^Fd1 (&0 i4-4IQ./bgE~Ȏ!EkHipT'#pvIQ6H4<0ye8.{LI# 1BIvĺY\] lB8r<\٫Mp\,tDӵ 'E##|6p9"t]&DAe>Ie;urKd_0 hr4a!߸OqT d`(Yarȍ|}tmW !%iYo!Q-UQ@M1uOMI ('(R(t#iw$JSb(-Qcr=j`$C4\͍*`'O9Asp֏E1>P'P JG4=Uzr_vD)ȑҶu;@i!?5t)H}h7猺al_HT-Ѩ0:k;cTWu4k?0v 1,Մg A2GQ$LZA\Lw0Ȇԗ9<4}Z&{>2 D.ƍ=[v$ ŀ.*>$ϊF7ٜaP= %>;ҒIoabqvInq:z=75n/Q+0?ǟ@g#t -&Tnu8LQ~}d٢ytٛ+_0Ҵ4@"yƟ3J];+L:\kKrt+FKE;Nps/Q$E Յ 5HܪnI7&_Xz¦k3ìbTL75+30mA CӦ "X;^Nd6 40,12pU};L.Re2m8Ir"$mt/SЎѵ%FR>𰩉L_cLq`;@iXf26[}9}  4$Vv3_͔A_S:l@1V< y/-&D*\0~~ Aս tFӝAf'Rxlj҅CDuymGh8WViv(T'{x/ ;iohr S[+'9uM3ԧI1A ~Z>sM?UqA)`2FQ)|N3),"jtp8Hi2M<ӁM% :Gi'fV(wwAk5#~f="Z^tt@zw%i3o%%Ę"[Z':t&@ҶPdtUq `7sXv`#u[vʇUvL BC%hr@qQttT MhЇΜf:McnC {tIq}! C_NdS'a'seaV 6S&]$ (@ofհG~aEgs؊P9Bt-"3vq6,`"WuJ]4ABbsfKqtLA,˕uPT Ǎw4OxJaXͭ=i"<3,ڇ%N:Q0Fd`$p**38 wsK.'.18}&4LE.x#;Vq?71l4ǫ(Bj8Z|om~mCD{#tI/e%:*G(0DžлzW57j%@=Ԫt0EJTt/3@ |Suf|n0'"*R^-Xp=u` Q[5؁gO$uAqKLkBwP0hƈ@̈&lVk_jB=&MEh%4(r,M tC+)+6a!DK>8#epíxju|^gNOfk$ԇO##}؀*t\!{N.[gut&8?cxt)4j+}ʈF79Pi=CFP*_7B~A0^V0cLJC/hoi@4Yu.p}Wa6'[Ր/Y\*!y~!89Ѯ}gGýEk B|_2Y^_q7u8ta6GG06J2_Jӵ pRh !/_N L:Rʍ}vE vOdիXd)ѢmeuPI\kt:YÕsWհfbeěf:85xӴ%Jj"Մm pp[;S Dv ^EhD/? +>S \̄V$I'Oa ߔ8gfyr/=NPÁ= Ƅ˓#gp+)io.F2BvYL'jtyUM<"O;g"Cp3 VhpwWQPѮ0p AZMh$(k ezA[8t׶Zbqy|5F^ & !^KKa_iL! )vS珔qJV%QzFN#DvOڨYYL&3ZΨZGy.唔{_nTEja0'Z7԰P}QWANa"wP|ڪb@#8]/RbpO!*x!u@%.~H}NDq+=i@im^);D7]C{ BPB$N~hbU {\Dvm=a#0:N![W ޑ|/̛~&RKd *_$0 aiڱ`|Gݺ41queШޗQUMF Ey[[1i4g/\ :iK9w(̚/եIOQ ˖70Z@VՓ!!wIWK^B)tQ֝J-Cm ;b {J}Tw賄1bc[|6LHZ]^jb)=hϠy G|?'S7tF}.oFdRBs~DŽ&7LǜuͶ5G*|ۨM A(T}t;4|W=e4r+88OZ in3ִ#9Q8H(gG rwR~u;t%QScW ^JU5ˊCxyW\tOؗ}#zQ%U|q^+`Tb/gNbHu LA}"X\(@m6qLwAQgsg+~B%Zl.ވt hC25CGLc~٨SLIWY09 uHSrIRR>3 uɀH[jm[5l_R G!hCIaҩ3Ŷ A u &o*s V\ l񅾬;Oش$ZwNƇ`fJRM45Q ˟.tZGїF&8K#d6BC!͝ieGumE$Mk nUطc[6b4!a aKb㱍=`p?  HIqjwm[ꑏQ:=ԩsN4&ƅ{1l@*s,{=}/s?( 87B/pO^ܽFkgisyZXnZjks1nv.Ng.wqn׍/\\ٷ^t>֟ڍ:=o_ƛ@!g;q3'lLqwGzTM6iOTOqe[V8šP}ׂ3|@;'68ځpp[qq9 vCHzj?Ï> Fz(U|Tn'_ngmtu.^0kcKdE:vS α)ΓlNj8*q5mv;GLAOŲ3%gQ.gX9:Y² 0É! {.2ocW  gkU8L?/h-ͭH;Dv  ~-8C%y9ř>Ų_!o#avnҟr+oHK; [ [;4KXP4S]XN$xa=DRBObQPG?j,)vVyC\v! \܊eC!_NhpXv rϐWΑ\ p563tsqV8s(d~>ob$/SDđ=1} n]R0pkJ>TmFĿ?-**K@m0zٔrϰ\tpתiumY^MIRL2 #8kA'~|01TQ 륂 ׅ=&L)S3? M#T:=7:\f9aƒxsUsE8?eיN#f~T NQp ehLpYvN8X!Sǡn!8qUyss/IJ/D!@JANrjYAS 8%\P?o}Ɵp#tDiY./ ߩ<{8а =XvІ'sh h>p@r1,Hn #WwZX~huuCB䳺_9F:۰0Jߡ~POϪNvH΍ ZJ ;Fòߵn&E4发w3Z]ya?RV0hJ|pZ!" d*TT_ %Vj%:-˾dH`eZZYm*>DsIi!_,ǂp'C$4$0OM% # &:` !v@:Ei_F(;_V~.tvsuAS"AD͊!Z- /uxX]ete5g 88èZ_UŠ8w@. /kJQN{ !:_2cDR\v?Y\='Cj9Ngn/;LU'T򻕙D=W:>5@Xv8HpM|o{|ht#] >eK]|Ni ?PbYť/Ψ&@=A58@X5  {onyKpZyr}Z1E6 K=6ȪjTz˝eo5(>*L@!Y+a*zq{=\`sVex)T?ˋ%_6P:Ϫc.Ԕ'A-F/#tU&4ZpnNV΅Xv1\͔Ӥ4f:΋D j5nsh;K3HWC$: yW \l4~T9AEyg4?qIc͑խRsiissuUQw@x (yDM9F;ӥoYbyTƲІ'Z7Γ?$@JmC6G i"-TC 4ĐH!$+Fj9PYȭ椢v|Ȋ&TT~fzD +gG܎ea٩[.T!m[EB7kQNs49eo [/zaq*Inz0Js-"WnvQZb8,5ZX5EǙD3"X$roLU?kUve]:`َq.·TQ[\**ӉS0 'aKSΕJUXgnVxg ssQ[۳=9;,G$>^$& Ul6v,h XE(jX/7,K+ 5w'|pVI>8mPÙzXsּ0 k~A=)Q'vq@hXvqD{]ԳyFV7^B$T aCTtu,{+*Dqe+PvÀ~êOZԙ(fH)Q-þ÷mƙKq3.!U(7kUZ!\A|)W|)@II +4L?=,1MѤ)\f!Ylٛ&r aI"Dy`'5;"#X7%Ā+P?Q-8.͑d߰yH&ЯfhXvܘΡ SͪӁUEz\Ԣ Z"oNPYR?0fIUͫco& ӄmxN!f^~|WzZz\"oKɄAgI(0ȷqrYҴJO'rsGej @5sV-k*Z|{Ip,ņla<ƲX*^BFRm!q? uz.ɲ:$H.HH_}6$R_\Z H }ui7̐3H @:yUrF+gï5W@xJq͆"f;`fu6N`ٻm8Bz|U8 a#p&r5ڀ.7Rǹ8HHKR `و-OFƳ 9h!pn:3=߃CŸe0^'Dt_ZP?ٹ:T4ǩh˶TACƠ<+? SnvV1xQyрĎk9DeX9{Xj #_Up7 fs[&du(pCJ5U󇬪G:T8(wi;eW M;[mla!GaYB\1LbOqp̼XAW88n0LHJ+Eõ0?.͂͌5XY0K⇵@眇x-{3~^6OYߑX|RrF!)ϊT]mΧ[W'sfe{Ip/(L K)[=8nIK5Ɇ&{.@c] Ea܉eo'SN36RW0#&F#t | _whYXq kp\K?z6%3 h~ޡ [eJ1AxBNJ0|;jUr yn.+Z F0*9Rpvm!by`8rKiQKyj:wX0''P((i-<{5[-;C nqG#DYmP$h3TC IΑ݌IO:j zm(=QĈe7bBi3Rvd1SbGYm Nx iSjԪ B WypNPz8A2SZQ/IVkB:wke)7v!"CIE3q& \Cą Wa&US+;5`yH]:p< :HzTVsiUDnf2 1#36抂1!6ϐLpRqui93* =#'fi.y~w]-ﺡ7Hco!:jUL%AQOR;%*KJeB| EH80sF]+)tzҬ%/Yڇe6 H04m^N1:vZogY݈dBjg el#@y4UJ ?a#2}DO`F@ikVk5֨uL{9&X:8!ku%.XuևWRCTvx IphvP!]VDb7<(ySPG](xVyQ $60u|XGq:,O,W, R ;K;38%7.]WJNp<4`K۹ZTV<'RjTٍ3D".: GbD۷Ј9qyDqwjʈ~(ڠ,ӫE?sc45cǪ5C&c#60}ȝԂ i",cc@qvq3[&ĎNebqڡJ^$\Iv2:4o3zʓL*VϞ4C9:; 1[yR cB ˼XT[~`T-j4t&<܌ N=?7jJÅR0:Iv^QeiWS3:@ҬWC3n7Pn"M(آd0.φl*"x%W]'La/H*d5}t yNQߕ; A+MyXJ+$ե)9$Rؕxd¼T^qB%6`ڛ\zս60U(IwuI|j9p;T߀QAHiRc)f$&xC?ECcė~ebpwiĴVUk ["KV_kd5]̲5Iѹ6W|.BiUPz:j\#PjtzU찛nO(r-b` ݻZ51,!j ( z9dCsR4QӰ5H 9-6*"J+dR/DjV5 q fr#nNNM]xXk#Q0'rXuΜ6ž!Fj2HsCSlX3dQf-yXe 2RGiVKWROt_y%̡5ЦYGmI9;w;"0}ݸ85}Xo)"?+Xof|ٜ̼d8Y{B ^+#,)˶UY'!eQ)_^>eڰxqazY("r fDB c S}Mš`6C>,?opHpG` jPwRoYYHsmAVJO~z^ϏAR)!͚ Yb>#O<R'$]}yRJwM&˯>ٜNbkҵC89٩;5aNC϶NCt'#ZZڬJCIXttU/Rn2(Ҍ΋IW7\`U,p=B$kdV]{QN̮җYEAC>o9Jgף 6U5e~=8Ea8aٽƷHIr\:ӣ*pgm|8{2BC!͝{\GyvT۫vZȺh3 ]go <\!xo.`Ghx4< AD-PJ$c' "?TEΜǞysg=?ndoh#fq[{GY;SOa:;~#Bl. Φd8_j׷+ՍJ^P~wZ?wE/:|Kz^6{6.nծӈt}eoGO]Á )gڿ::hwЬWV/׻^xCQ"B=܏&{{C?+qKƁO0 Glj἗z)N@8ׂ3\|y |]nMxYmD+vLiW"G``Ғ'ڵ&`sL98 rbqH^kنq!j۠ChK[="@_&k3 'B5TxGgBO͚}*!=)\:?$k7 D降Dtb- @NqbkJł$kCMKÈS4)sJvwD8-]Y!d! Ƌҵ$kkM? K'{ qQ ;Y w/$!k7x$?\9SsqXge2^." L{wh3dnF&µV$bN Gz!Y{.Rà]WY{6q_\:GuTG8['.'uq#ݥЛr]zGu:.ve^PƎnp8٥ND@&dЍK(C6&̇bߛ' ᐏ(<* ЍFpmWYb>]v:hoj "ΔxJwxV5چ)T22!)&7ճi<@hBCfNkyL57&4~I C%Md 4:#ko3 \άպ>@?N\F1v((rb,Y{ Ry$w֤IO~rwFЎ&@JMdO7y*Y>4vA {'kwi{w!*^w¹_'25fBN>:ٓh9Bqpb3FGBWct1 jk31bߺUِrRwDҵd~] AFHD[-[.E<tɾ3斄D\<;FT@d@skB@"3Ua#`y(tZ[Do5@nE;-%"{N[+kVOnאcDYnӁt&"RjO%#pĄ>^Hx*Mh0⬅0M#''h>E֮3S$$4h"4{ 䑳 }3 Lgh?8 㦏Wko(N¢~'h4I7^-43p#k6ȯY8e H0 (.ԹU!җOڗ B?v+2ꐏh9 v8:IN߇|6sm4.!-86(sT|' ]GP=˴<*{㬇N)pgX8Nf56 n9$mS!'M ASy6Y{6ˈ'=JOl-C<+(qZ w,m7=WF =)UqK8:(:D&Yv(.. 0x\>sKQ4t_@bc4~zr4n v`+M]@H8…}#se͒#uekmpnR4F򪆮J1$HRaL$ybVUF1ޤ!vϓ> mMEu2ŏUZFY2?PA]'T'dV#3pЈ)fVv#U hqdf)OmTW ȏ$brK/LB3XeՄ*G\e*<Y FWwЁނh˺Ρii# RBԢd[uX:D3cEֶ xCI?fE'цIzUs$XZNRdVZvRdˆxI5ޕsv0.Bq\^gKG 6nnʱp&YP P2Qa!}t8YF@> Kٸɝ8r.bA\"97+mf a깡Tg%)4wux/hl+$ZS.TPK=ɞj=)?iv ;4+ @\?rJH_$&T>ozֆu.2}ΔQk^>}n-j"p kx|dqh0j̈́/(toNh0nɸ=Ή(ON^u?F֮0dEGMkܡCuiĄy,x;d.qi k6NI4y<6/ԍd:rӴ M%燄7e$ȴZ:y",d釲<-Pe vߔ^;,nJ㠉S3iI89o,!+qvk1c(K8jBJ4J/~ N ێM|IӤtHi/-Llk (6R*y/bvX Yik[~ w Y6'1\x[QrC#v lC}N25d#sfU82N삥1X}"*cE~c[Pv0  -z0"fizA0Ghqۛg: T02"?CBrbZd룅^BC+:#2AB!K\{( {rȑI*M/ɖ.96hF8| З܎`}GqגW > !p96xiA4כe0!Zgux( 950"N}j:an[l ZE$*ZHRDǛ&7PnUB8JS=#8!^sCӱ _ek54qFhҪҒ4~ZI'90no9y$JfgJW4a0@H/V$(O_tA$fέA7lIE!Ednm0&➽WBbjH;n]Yvn"i4eȩ9N.#dSm|Ig2G{-Πiҥ0` QꊶU40H}T 6!r]+ErC49ju븋-ucn_e-?C4!VdU`JDTuץ@Xԣ:E36+k,g㪵J< }];& @<3qEִ"VkYge^wõ9t4]QHY $ˇ2D];M#^w/^Ik\qpoAH1Ӗ붪߱qBcfުH(LJMԀe]5K"r_[Yشj=4| ttYE͹袂TۍRa!3cªm)W`'Mw{_xB6;ڞKUmO~,'8LsV{^i.".TےW /ZK">ip1y?-Di ŏt]:S(u4FwBZ&vu}Vg2.ű1#U:Ncq֕]!!L; Y)ԣ*["o&Q^H^ !t6Js.lhک'q^ꌱVϞ#))ۚra#"^C/ay )R!v i= B, IU}VP ѐж} wl?cBp)"4[QF ŏYl19n$m@@iZP8I)ТF: dUMnZl`<r٣ Z-YN rCbdmdDﹴNPi[q]=JMMx< |-?k6*՞DqB>aTD6*oJ#3#90 ӶƒA oh\yVSP8N6$(R%$w.T8B̚;pOS!`SgWkoqGI mOTRr9Ѹ?Ѫة2Q[D'0k70>jsmL[HeGi|7ײ1SM>s'|!o#frp?j+hV܋r2ܘZl$ܮж,ʼn?--6x{ABQm[^ h_b!' /7 Q2'`.J:t~'i0 =c HPeDK&U" $iRGK[ro%kjd*)Nےhl}pQ(֎qިL P]!XvCUY.Q4WCs`"@|uh=|Nk\æ;&@z@ba/>-ŮlŝN'B.0 5^bD$47 ]4_Jo3 63qM85M0"XyEۭPـy7.-S&{4r/ ^#~誟=FFS}ЄFJZߚ ~p1ӺsF#Wc䟊8c~Iq<ۉ IK=,mh3q݉_."4YeoVExCuNhכt8.խB#@n '5G"WBx8yp:~,?>OJA.#Amd* (>q=T;KqYek1wKpڶOQhSv[ '0ѾXa\wj/"$E' ^r\;<`eo/bo&s bX !vnP䅘#[#IHHN8%T ?ܱ t`d*Lb NH)gA`?q 0Y!BI޽£/=z?" (?=_m*B?BU||rmm4J[ Oփ vv-&<_O}gGRl@OJdT' {߈'%iIB!3U(q~ d.7X0^p]p/GJHrS iY Si?ğ[SE`yߙ`m+=;{ң?|ňQpkR:KVqPU,~vnqc OrKZŚT_]1+;\i.7s#|5Y[%8Mi^h8ɻɑ4#1^g;e/C@qA{{ rZ/.za!ଖ'8|~/y`:+<@tXH91l7ieUMKVɯgK$e^+0S綐)-vAE(1S%1#l mHP<.a1j,]WTIr_;Ow6 F(R cxVguU|iRqFhܐO:[iY)hx%3@BC͝ eWYL,7V)Z-n }Mn%Ӂ$L  A5IH K)QMKE,2[6@Bܰ* -xνsn[$ 'UV[ۭ֕O<@ -7'o:c E!{ީ0OE8]N>~VPw_:1]ZZX"\_.u~^uGi?M+GG~n?=i@q޾=^ k%zMOl_zкXIr2+0xt#8O .-}چ( d?#jq '0"z( %#8*mHYh?!~@E*{m[1aQ )8@ $C gD_!go" ~I#f9E>k Â>j]Gr68 F3p7۲} 6!bCMFt|FtV6D8-nI$pB&z1Equ[ΐ'x)<з,C_$ELܙdCM%RO)QOtLң=x5W=|~]:B )թ ZQaB%84,D3 *αΏ)8-#gLqBxe0)$go6ʼnree/ysqNT9.g[Mqb\NnJ44Ab`VD*rv1R LV ")H 8sjHzQ"?XRFZl Tה&g6bQ9=cXp5l0p g7@|?)Yv@("PL>a /&CYF;dT8=hX"B"z 9Sc@&[R}=9).x4¡gMqh-LV\#Ī lA!<$` C KauH(E bPFSr{GD(6!:$I@z9{ =:$GBJp4 glhp$F ?hgdL]:`3-tW8gyT5:%g/aTwLtIV V8`/,4$PP.II+H0 cIƺ%A:Z:mщsM UFn<6l.*Er&(t Ng֪=_p1 6p54_'gwZR`R͌7mp'^?7%gp@S>6SZo%tt$glA C^OtZYȭ&uw9 O,v&eFD[vIPR:-噫hiqA{JаLd̈O$ؔse/Auz'Ĕjt>OgiSij ?C^o\@ J@B1n{q˲nK HkX1mO0NӃ K]I`~s=9zҧ4B3-h֜|I8apUBbVeQBЏwK0<ϪpC GNi0Ap$g2; H Zq+" *~JʃV(AhGѸ'-HFM,iJY!%A0FCb ż04N+V%~0 Ow׻%*L&R)!ôφ)(hD>mG_-hb(>FWq:. NuZbC#55"*+ZO3yET q5NmQ-G)t\ܫQh-ilbJͬY$5d6z#Z'g5N. HJC،|p&g;IPx7Tۘq/̞v1CP8{j RtU԰]|Ԙ2=k4 i(fx(BGWPg5ۢ8ckQAE 粬m S ũT2mP!OLb8AH+ZeKuNEWF:_@Rѳ6bV8RП4ݨ g5ٰ‰0uUfcaZ ,1>O_! XPeGz(+ߋ4sC#%"S,Cz-i%C:*juPo}E"3n\N ^8_ )$ R UXU5W.K% Dz&|x;p][qr64VA EamX^'q4d@uP{l~K* VOU2pRpN^iJ(ks3D *0MfiOs  毣C '4$Y q1qӦf6A m fq|% % ٻL.ylNG&l82^{__qrU'PA$_SDC~Uj?jUwDŽyk/IG8UI{qNZ8>-dj\[rX&. }KN׶.~u9rǁf_Dv@`O@MX*W@&~+YaCoMS$BLۋSy>#z fd}FeaًpbAX¬8≒i>6cZlGƿ!2 @ah[)lڗw6DHl T磺维oފFˎC-F wZGMcT5bd=d,#}VM L,y= ,f\ Ֆ8v=XIм go0J~KG)dFZBYbK4U:~6z^I똘ю{Z1in师zm8@ *m<8܄.eFqFAuoz\']4L i_{X0yp* d"^(I:yi>boӄ tBb 5rrxU:hB4LS/!&,Z?C!~63ɧL72 t6D#BlRI@+n DKb7,!!#kXUȧMԏ`EFpΗ4)}e? [ՂSB0fIOHS&N1SmT#x nJSA 2(FQ֏ϑ[y DQ8J8'hVPѷ1ĽhΛ:qr[ƹlpK#C %P^RNL7%bbȆu.o)ZU2 ?f0QRkeԩơT $r[M@Q c&>-3ψaxwA‡LP/5%g_0nA%AAý@0y=ix1m3Iq}6.Ґ5$^JK͓Vځ<̣ mMnX"JD6tnz6HH,.S=dtBHJ})$YbCT8,oSbM˗I+/NN(RŎˀ>`E4\<8,'gl\[uA (X+.x,,I('74ж^"]GƉHL#\n?RԄC%RL*hv\HG^go)MlN<8Y=TG *p{MKc_"k¦ |M!TqF;xlBލ!W-r~#PTeߴ_bV.7mcGYU8'j>FUxnzbR7ݡ JaQ'[ØHd\sΤp.NΓ-pf< tLS)?du^er}M2ɏsO(M&害ҽf> $ɑs64f @~#4Ln8ͣ 641k(@ q>.:}m3"EԈN*ށN@ӶہOŞܐ38zBxҾ1/p tm Jzs@ZaÎEl[$ $up8gn9%qz+":̸|xm&kGu1Ld@c&'GS.arf 8tU"a/wm=m՝yZ,TG-G[#vg_,r^NHN#$'tx1Dm}A 3ۗ|@\`u_f6m(uT.2G؋6@A("8Zοw@SPUP:գ-1fbH4¡6gLkJIujLRFi /{Uȉ3 86kĆxtyXgFhYf>zA.9t,5sŞH*#.I8 %{!J[̆jNkȇj4Bur9P ‰aDm0FŠQ HPX,} IrPGp ^V;LÝVi3A {.p椁n?XL]3A6Fajm".Vh5HfzvP-pS($MdNN+LF>#3zwf8&`Z4i$4${$Y7ZڃmG d1'd딚>eUP40`KPdjC}jD|ժc.v] ad:HUZ50M*; Z_)CEE8H4,*X"PguΤNH56.rBsmŠ=0YIw_%܏KzWN/rvq\>AES^0*5:AaN}UgSg~G߸lxd#sW8{) ,ٳ^[ۜx ˉGn7&z7\ [4Uݰ8\C..Vuđw[P34fyMe( JU81~y\4U9j9iruӨoqu4wYU9Ͳ#OОzC텩2}ƹ.^5Ȼ5Ʉt h FVWZw% FlR,R=\Bxp\ϊ{Y6l߭ImaMJh o`H eV@XO:NHOS S'QS"Ru"9;fT4kcU -J|7‹+,7m~{~؈V3:ϒ NXܬ,㳇f:Pw:CG'CʆH Sn_'g4'9 [lk8jQ `hJL'oN`oʐjV6P4V*Ý>j=4wE%glX4I(+?")Ϳ`S3_m553ţ#Vڟ U6٭I$ՊWCh |4tɢؓJƲʕJ>n,x224=OFHOoBB dui\ނB[qL]S ;YUAtBDsq}9Łh;.=B:D4/?wygo.GE{ZC GXf.rv 7/̩gY/9 ^C@W?K%rv T,~F`*!R {p w twϑW)gϸ$ŋꬢ{4w A15m`\g ˬ$U:.NQ?"~=0U[^:0,~K98}BC!͝ydGy{wMq$" 3E#EW],kuͮ9azX m|g셵2GPPQDȩz^۪y <}:WKeV{W7N ]eyoo{CrEsG`y>{&?=gG37θ^/o6Wwitͽvgo{Osw;W?jWm[f}eyZkխm^~M b'Q-:z}`wׁڷi{m:,UKR7sQVj פXcڕ1봤ݣ=FUOyUMUUHCh֧4OZb oeץq%j~(@syD9/òi H@ҟ`TB\fA^̓X5]?x<e/1A~aYfp. }n4"\5h.i*cX66 3O@ }a8;HtiPVzQGePEq~NaA|P~Z&@?[s2yJRO~}˚&$]yN g-MW!z ~P:XO0 Uˈ*B7Jm(( Kc`_29Ui,ք. 3sOo|:LP|"0$e9)Q˗K6y,Q%fF"~@gKeLuq٢ QZ,҄(^9Tr9e2AHbț H"rE0-+I6Vj@ByD7?IJ "&tlG7yI[D#-F8wk7djk_ۨ#kCk>.v~B.UM˕`/sT+)oB?8'YW! )t4M fcHݒ}Kdv N 9ikEMhYw , p|^C 8M8\պTq |$=rD/ӄ~NaȄsf hD7%\P`2DzusZ9HmER;*TQUsI!7eBO$rV7mIC`F@.:0tXvg@q`:RyiI$+9Rs{%h㷱lH1 ԹONGztI y{!*5Iξᐂ4~!,6qv ەp;m8v~4Ts)vzXv xYe:'T2D`. *ˀr]0JEcoY E/UXm"Q8(5]Y(mh1}TKӛDu]ɏ߂>_SibJ獆QÆer'ɿw-C@;E<ER3)׾/rVµDM/ @E}61rgUyc8yACBWҡͥ$.!FzWend^#vۧ@ T(&<1PJfn1|v2&!]TVw %VKrtx)MFM;݂9_@7_Xƣ|u)OJb}IGn,F%˞H!7&HD) %+^}s4?de+)ڛ% eVL)wV Z,I+bmh%ӯjVqJIǎHeNLa7ihӰQ&zX9&A&+u]VCv0Zo,ɕCo $KS*p[GJ.PӈCZ(BSJreW'°a$Pq..@PIաʖߥ(mhdB;^<G[8Mp u4Kͤ" H]V)LOHyW-p [+U˗j2p8@9eF8}@-U &{igm4llOs8X1^BJbq"gJC Gg'@t_brm@M zޠ Hen{U= ]/pd?/ ͚w)]ڭrqի5){uÂɳ'rk!.tSݎPV?u? zlZT]MH>#51Oȗ?j3uC}We0{J[ra7}ꀖ͑RǍJ\<8K*g,6Q E#._ѹ8XXqt ha:!Jg?fT4 9ĺBY3ޭ"6h$D|=7ݳPTǪ$WРg`*xp.8rUnE-p>{hi&_3x>eWlgDavx$MxfΠ:aG+=ݬnfKaL?A i_Ay968+A9i :}4GӖ5Fce M- <*f/i|w6&KBaZ %3B#6W=bš{gT0$C8jp4H InacF$(rfN_i`mB iP-XX0Wk!O+0$tؿ` `"` Ao6&l_z(7؟'{OЈnXY2:wD+#H(pxE,|r @ ПSCyF Jxw4OJ 5uYftVO`[d*!Z"(hqsyQR[0V_ dD6hØJw7z]W_`F_9eg<"[#7\A/Dzۋ"YA$qᤓ1D݄e/ %">s/' E'Mj2 qdI¡OhIC!Rswk߁e_Ѯ% ^.;ё&#ҾT\@+b G^qVl~FQ M`OHDgtQ9-z*UI?kjڑjɝ~/Sy=lT%*e= $X&Fo>c noq?!%M@|ᒚEh )F[ Y)p6-Fv z7˄c"ƶd*H]Hp8eK(f:w}CɿQ0YU `^ {za V9K3aA[~.>gaOpZd ެ}!)%S}%A`8\ ž,b [%w86ՕR{n,{v9KaN@4s庅rZ .ݐ^.0T^gdc6h:6lf# OgyfOfqR{ cs,X&EOTΧS2i^,y7{~lb>*M39ȇ="2">==ڋ0{]v 4Z>e{h7QuDQ(iV΋qrqa]"A=GjT;-N(/m p4D,U!I^n7Jfu(y+'x^%%J~lԯ%Gߗ*A)TaMQCW06Iu>i&%Ƀv"=-WeԭĖ.y?ǙpFlO"79)iQ45ak)$'sSo$vf_*"-><,rWQ tbAT\8"1QOWI {{K@J@ܫ Y䁖*%k09fk„ɧOװnXS%臔C}Ѥw@ G\>$yi/5F?opD9[0bp&3p ϷJ^k@9~ B=ҴAAwA; f%Vj^`% O+5EgR#uc?$0t3Sm-/~e`yQxA)xP BHвIA:a}iWCw#fa4rGh/&4,+XN(<"mgDz #N5JUg4T(`]FȆƗq F7K%! J@'4c5,^@H6`ΦS6wϰMTྜi+`'8Uq.1h9+=<Yn:S˦4i*TYOlqTvTyL{Kyl 8,VI %;.lOtkxݥ ʕ$tIJۙүt#Mb^.i,?zd8!u* =jib(vQ /u+Z0K| /Ŧܶ6iMq8u 8L^Nԓ k`@PFUw;0lͶڗX49ʨ~^Oh6p{J$q ID~~=bB6hG]/.(=O/Dz#$\Pnr%kNI6- ja&qrAspK6ۻȭQVx~δeɉz?$Xjrè) ׬N~l-ɭZ,Y%h8q`{rB~{b'} .۹[d |ۛ ]{ln!7)A9$FIF tt/z 2ʉ) y3F{E.Ϋ>&'eVGK!UhXf|tK!99pE54Q$yʢ(< P^0K>} k=Y+ NgÊ)/R?%Tfm uz<)*v›J"[Kz{xA+Mp<(󣑕Ӝ²&4p0t7A*[#/iY#8Q6ekg2NGA(~ T?N ^]n`lBC"͝ eUy1Ks:mnkron+0cp.0fgXsonu|ap>[ (IۤiihHkҵ:{ֺ{.'׿Zǽڥ]V`&7"$ptkt |?cYCw-ޚbLQvZm^oWRsepc^_h4ZfjWZW[xw;j]lwZGuxkkWN-r]{gxA1o[75(Lq3\<#^bRc % בEϩ~1QZn5w߾ռ4j h/lw7&1(c(P.d?%(ҟ.XBܡ][Ɔ}J6&dl{j;3Yb](dړQΫR4 6L4rx5rB#9ɯ$C9KC>FWC#(xJ1O^Hd<0yϢ!G6+1edcS0&] 8rj_mie%!6j@In|K 2مDvP I~րzG~Ӣ(/z@F-׍1/ &q`4 2:S,Y ͂3!*&}DdCmaf4= gyľ.!Wr8/bbrVYݾO(@v9ZėRJro*PEd;09g[AOq>(U(04Q\IdiS!Q@?M%Q]ن.p+ɩd?@[XNLElR',݈sG rckn!'H!?F H "qx=C$T7 ~"{.R0fګAxU ̪F^i$ 'D؇Т -DWM l囥^͍iͨ(F6)+x_Ndwksu/ăQ}xmWG$ {tI4NmJ$5IY|e)JdWoX*}@+lF3%ּsyb $u"uI0/Ăy DvT%c,:~=Q'iUo!q|MTӟzxU鱒[mD6J B@\}]`E;v"]=SEvS3bA[alV rRU{^;з,y6#}$]N^xV|DIpEaǃlZ"F.@>L"`b(^X(Ib#<9˭CD9m"(] yZoR\ /UGu"6 bX~cy[u)48?kK"$/jxR~4  ڨr̥wB^$ܢºNd0,g}w4j@ _6AU+k@(˒wٗIB]? F3l?PJnZ"1L5NYֺ@Rp`,e>>"6ܱNGn*R/t)SJ~"Ǵq0#aa ϒ19ˇQmڴGBOlwDb}pciyiRXXbSn"{B(HNzV9A+K6,z`3'M0` N ;H>j i{s%ZV,(E)%=DvƐRaJ./6)ijx#X4ė6|f\F1# Pvc06 @Ёd=hb),h6m ДMI `{Nc/J! ףnʖk.V}z1=O_+k>ZLO~'05].L.+?d_=rDdmm"o-N" B+K(= mo nт5/B|uGZ# t^TՋXxDEcBIDz=""/v"uUl8Ad71A z39nQH;g`0Yq$#90)~Dd7` a/Ua^;*u}kDA]A?*%w!p&NԛDۙUrkاEYsqzQH*֟ݗ#.}rnVh@hj5XGH)ơ##-NRD(s5%蘕/Tadk3Q^E}LZMF0H2e%ͮ$v1Ou T3MfG߲4ًMh\>`CS7Z>c*p(V}U1E5;F=FYXbQ7*g z1=t"5`r(zRE=v8  ~Hd5 åotOYcpIXCqެkb$W" c>t'] ];(slNn7A <8v±Z#8f9ׁ^mQfUlO19U?. a~]R޳F+)t"&*]F@|&U Ox|Qg*}p`>}ڏ$uQ rdŚx泃[/<9=$8QuR70BA7dqE&9в}$|grMLn_@0hCACKz[09a{g6ڵfinQ{ֈ6P(ܠU{<_., F񝰘eC-W_VA#~d 07'z>WBPhqLf5Qyߋ!=vU;%@Pz272gɶC 0H;/`ˠ[u濡T(z>eUEOi/7K>Bp. Wqʪz^Q+r" ҢML2UD7/>'k&wN̏F܌oN8U§ ں g!<() v4Je (zQ"X6ar&y TH~Jf#OS7DrA܅/Dx8gNbq i+N? n5ae\Y 5,k( (B}iIIP\H[5QI䔵B? ,4tDC@>d<ߝ=! ͗MhƣYR@h^ CtK Dq>{Ia )|J&b B6W=*p~CK N2WTEOQ |v34yC8u0: OOc .v!@Te6G;hosh6'_=o*E!X|H=\WF]-a-p$mhņQ" ,K&iFC Zʈm}5dDIu att{ uުM :i#_P&0.֊I]GÛV*4O涂F^[٨t rϓEXQ0yܞ P"fjy2PKX)KDdG\fr9kAyrU:I';Q,4 n*cVzMnq~F!s,>dz?6Y/~Qlsn ȉ@!?*k2yљg(NJ p>sC.bq #>D[Շr tʢljqiqxx5{~. ^ٴϑܤψdB)+2 rھRV OY]+$DQeA٦9T"*H> cPiF5M`\-W$JIV\oi5 Ls@6r䑞9rZ#.u% zIVFsQē( rh*GuuMuK֖A*K{ ўCLfzW19w5&U#&[~zqn@ZWF( "D'ݸ#wLTP U(8P"{PpmzР"Qqa YTSYhPhDMR7M5j n9+Ido5 ?Y?fɋ&鿉 [@g UU+LBOG- 'I{M+P`ڰFÈy -K4"Qa˞d5yxw!]a #l"x˄n#3rOӲnpaaSP>b$ m?Y=Z^[T$;ZÓef)^+"Ȥq8 [yNo&4惊r:jݸe <NYOB{28bu9C(C2Yjb>Jiv8n'7#Ճg9}-=+ Hrin*w}TV%M6 n[ggurSat1.;I'PNW:@ gWv\1"UxBP%Ң(ݬ:h˜DD!zܸ "E@S_f77CƑ39v~jT$tQי |ͯ}QiTNq8+oWDr-ER }HoJi ԏT@_ _tGⷼYDvv-DV=<<ʀj^g8A*]d*r\Ck"Bb/Rrƅ63`M%Q;9B:Q9sT4ZrQwShjx*{ɾPAWԭ;[?ݤ?=JXʫ9QPC5 v-XG{C9+$i3.\>$&G71}dXEy&'Ir58̶&HXÒAz/^qE&w& Vv:$ _ ;/h>vX3a0M0iOJ+*;qE@q#I=;A7XTDBd3 ™|Ez'p݃~$f;x@zS` gmiߢ8Lp~9Ԟ?W$p >1 aBMffz>Mni-/mW 4@JlxyiI[;z\^Yj)iG o^튎 iGmڠIp:E>M_yoʋWR?Cr"/k>mw'i."ի9WFwUtw],gsjN{ԕ]>I夺;֪+zԛ|Rٵa6Wx+퇍 "zŠ N(%Vp@ٰG7G#@C.BC!ŝ $Gu{wƦc{L{0Tf։,iW=ZIK 0@8 ձ".I{Jp@_ϰ6șUYgTne r#꽗/_>HB\qsҵ;ZP 7x"]p# Γ ' nq{JZkl4WZ[mn۝nwy`oܽus{z}noo{O[ZiO6K;؟\28avsXkc  ?6km/Vfs1ckWbk`67Al1!#^{ p7PB8ϤJpRJkT{0}cejz/JspFsgn4nBjw)M94hvat$@ì0M&@~&Oju!ENcO&ñ}utΈNsDID` D7p6Ve- ԁԱ0w/8º5J7SJ } $xok)~Hnaݶ>jxZt-ѕH7 /xsȝԹ"t#^;\.8猜Z>Etz9']`FEOA'Z --beŽbCFyjt|C >$m4ϨO++NrPr?db ǣ<Sm-p#uJB "}ă( F[DBTd]$8&?IDb՘te9;x2ȁZh77 ?spp4IYb&jBb(T"Z 0EB)q'3ztWIi#ԲY%T|>j%DUϑLr5xAF52D\X99xQZ9 %m4R \e`Z>f}tN8cYy|SgJ|(Ȣ7+.&8pJ@8gk#'K1WJ%#ŁfBmޤ!(׽u0^;U6`y׭qMrjiZm0 9Co4K$-v 5㜲#ef+ʼnTT cc~I &.W|4y_EEY=eE RGqN3 A(=1Уn4l㊉8$iQ8E1ζإ>pZhl hp n8_Sa[`S*Vs( oJ?鍶As^e! HF~Xs6t45nWk&uGVN -cm:1"J0kdHzÑÞ@@ %UJhfOwp`*VךP!O hZF1E@ -Wa;LQPtܑ(4+V]t"\brORhyqUD6&r.akL&V"G7˞B$gSXot+KC ;"s!^>}\]4R)xyO's8 rq+$8qS#^2'r .Oپ]׮/KF m9RN8g&Ú,e&P NhqC`u&xa$ѢE҆N^ÙmdҶ)p4D`t뻮XNL?a~{4!OАn[Mͤ/&RWٝl"i[o7:C;Ўy 4z9y6:23I Ay4mFuB0Ӽܲ8G GlS:=BX' }:^g;A=Wodd|8l|VЫ ͖mu'_ݿ_gMLxUw2Eȣvp묍Lh\)Py$1O'-n_V T qo<Є߹XoM(!s;4JǼi6FL4Ɍ jQg1e8{2W(Ik<0r϶Cz ^{[,5=7DΨ|538xI dpCnoEۇ6ʹ0`LN-88OC edq-V/IVIn>ʹ=0o ޅ>_:C@~4VpS5; A/(KxX'(:ovfu+,[xb tU?Fn6j3㞬,pkt 0~_mfuK!r\)'ZF@RBΥ]$\ B$BZF2"D(kai(Kɫm[.u2 i1-$p!CX^kZ$Ro_P>_0Jp#X绵а8GsT7YB% f &F|t_x&^{]7/U]ĎV =uIPgoC"8n\puN*C߳PY!x4;%8|pHhjkvVtӎɄ!W_lr}fc#sS]i*蒜uaڍp,LC@FZaq}<Lh[iX5djb'KhAgv`tۚCNjY$ւXB#>7`[6Baߍ}'fsLk34yBkևe)8L&LpPDaք4ÉS'+9ȓRjQiC)$^qo-\&x͏QC?C>=l}:itN0A5ZޡI|8a FS!ˌ*c%44iQ_~A>^{a./}<451eA3;וS8Թyԥ37[v&]FLٴE'to.,)J/k/^نӈn(GJZ;C=V쏟Aţ}A h{N. rwV=D3T=:[䉡L@hA><^1k6fσIA&zlI`_!"W~Q|`Dە,c^ &ψ3UD #kCpdCxH27Tp>m/kX }>AڗK#6G'N)| {voUF:+GA?ttJT(Nƽר~ B>%(RviD}у358I.\dwjrsV!gqwGT>,fx2r0Jۗ~6{V+3N4NYN(z8kՄ+:1jl=VQ4e_0,aB#K&1W;B:lM}Pgw E'f>}\n[ܲƄ>6:_gLoc&HL#gd@ʵXު>FUݙЈh~[ G?X9$ S%h y 4 PV2cc[qFg&rW8QFqZMk80>tE}RbPbU[iՆv;(Mt<~tHUrG$_"Lt Q$N>9z]/x+3\^TzbP&P#1;5z!G7y>^{c#AIpi ')8}uһv2nw [KC!&yH1KY'(}Zy|VՉ?,>oSt.oswUIOoљI}NhlaR`P?7 u;MY6-D1+: ԗ\ |\MT0F幅u)K$ĭkpI>icn8IA B(`wv4f^A)B| _~NYTHM* W?Nܟb42qPb&Nr!G@_)z&i] B˶J꣨m 1Pr"Sz/]8{` Ig }t;r̘lxhYuHyF|d7vps{"V'љb[~H~E$>kז.( ho-̟Gmc~@R/ލvdܦuzS}@ufFPQeSؗ]5"`)?F"dR;-_uӂ̿@F="-DX}j)Q)8R8)9dT́>R5a4U|N*MMM:PrF l܈>YzPS!},aWc1w.[BTMuQӟ @DG? sQqĬf\dW٩ж'O`_ښ;G5iCQ2mIR:˹ږ[w\5!|̐Ǚ E40fyeɝcwG5/aL| \N,/V%CrdDL_5tXыi>(e)f2mTM% TcpbND85&?qNJ kyXN /v4z3-ܽ8 f1TH|^P|_e̡1y!SEnn]>G5{gJx ߜ@iF8S/wsdg&E`DY ~Z.gp[0x/y)!BTQMq6 HٶlqH#"{}t*A׭#]pMjaBYw2 ]wC>X%r$Szh&d.Y =zEKW h ^ MŜ58%' v D(qzFPӸN+s(w7N=F@M` ݒ] :TuH;8t v}bu(IE$`0&Ab O iuڭvg{_kowڝ__Kqn_j]Z{v+CSG_9zP;',p4/$k4>p9xZ$hmT"Z DЏ4W-dXHR ~̑fTMJ ySHK#!E9sV8@\W SpYs3(k;h.8GoLqSF_nm5".-GfuYjK/}9w}so{G8;y|Nj `pfvE)6Y(֫Qk .D:@ YoN5dLמHkzRYpr][JL@ 4tLLMg%b @4*SG1/KX0F]QZp &>ݐo"&܉]j7SK}|-r@hn2ʹ)SN4t Н2*Ӧ tSřHa%JxkyD#6 @0ƾ@LvQ٨wA~(+dݣ{B1 BqqWe.wLֺe;pbMԲCDۅYCRʘեqs@ ҪTJ)u}}tQqYFE8_!k>w1 \pDn}(TDVT jO *|Ț_+#A0aqYjOT%3f3G D9SC^h@:Xah#K5V^"qќ! ZVrՁTM9B!IqȈխQߔ8x -OګLb F^&FCb5iABKPz< [l:bhzzP-vcu@O%@`y0l%:>יo}(' [I.(6#@EFBi6*]G4';C)"P@`.2+;(1yD݁ 4Hغ@tNpHrdh騕` ,ZVb>s?˶OMW'Wfu8_#k Qe1/2Mۻ4I r<ƽԚ_xC=Ryc=K&4T9'49ʪc(L (YBӰij@ h[dyH"B4iOFȉcVͪޥ(M֮0"{eF['h#7sY@ 9y8-) YybWS2D+t~τ7nӒ'wyb `o!;Vdٹw!M N4h͊]7jlA>bBbҁڳh"VuS EYS&@SonZ~ |R8ԥҙ a(=W &]teiZ`|=혱@""9(s`,- W=4 Y`Qt@dcI%vn4y0om"p]Az@BNRIFYO+Lh֜6<.~`9 5 y9[ j}n'hK!P$qrJ @5@0q)H6l% ݈ ?$kC#&W$*^F&k7nB7/BOՅ;@؅4;Œ.@^:C PDDVedKg\OǺ4V̚ E[ʹ!Q= VZ*{kI v|8u-(`ceį79 &$:tGUD@rvX=23Ao~|+p8EZnw%s3}&KM;>İ&``` ܪuk,}ݤ' v' Y' ]GbkJP ?X$Qs(ÔxB(1IL/aݹ(^_qt4?2JI啯=a5Ҥw :~Hs=יxz9&4hƒA<u\V'u6.$47O!0gz$8J=|̙"L^Ixkă)Or8StCBC:yrakR(7xUG+˺Ip( γf6&^8}?lT y)Y4Ɇk?YN?RF54j}ˀD*M'u&K7N8e0][@R[u]El Ycg&N_]3 l">kV1 ?͘gYJ͘#>T3q0dR@(cvKd$qǚ=ZVmX9DG~pӵ1L=QKT&ӍF֮L]#o\ nM+'/5w;fJ1~4|KoZ {5Nh^jeq8{5m&o`|6aG&7Y{ 5W-Zb%~5eHj=eyQO4Rbg.8R捎|،ƹl+4p&4=~Ȯ4- 1̉tu(Cgl˜xVQ'hgcoռWn!k(=k!!nFSw{U؉h9*-&b 3_n9$'W}zz asriܣFt)vX?`~tVy`r0xK9 2D4"0m!1&=F4#cȵȎC,=ֶfy@}X`0trZ$>HH轵I?/OFFhb@08SnӮEpYiQBtڈIbv)j:Z`᲌kڍӦ| 'egIGSG#,ުe~dOK@Kc';@҃zg-#$yDXQ@eMDjϟNF_"kw2jdrF phQ1k8G~^7Y3 Wqܯq7%Uщ=iH06ukxYs7^>(4e xxujDKn*e'~@֮3HLbY_ٿWL*|'rr>1>? p<2N>ndH菉Ze_Ӷt7  ż6줕YH(ADsƝ"]ոkNVhaG[E]8gsi }m,:bsNsuRo5 *tYvHR14$o"z %PH*캤ijnVY`cQY .f;49*|ִfi۶UΣq i8͚UaLD_,?c0gR3"D=j<2IaP =0g];CGC0t炣h[MpYLF\1@~s0E8/@}}(M2lbL7uQ^>FB; E+6'9Dhz0 U&|rڢzIXK48(Y]n<;\@:jWqndf2MEE*&s(<mܤK?"[M<$XB<S-evЯLJpYxN9 Ts F4r4I4 k-AFs쳨~?ds뭮2d:s?oT>B]xUp&@}"fT{ùHȥ3UH*Ȓ.tBAqVcX'"x֖3=k4(j|m8+ 1iT70Fqk/ځIUgC4i'aCt*pѱ> * nGBNT$Jj]A,g,Ż* 1S*?|Zm.͚Fut{IzW̼7pp2]3Gn1{UlڅF#T(pp4 ͠  ci JǶG ?l$>Q(@Y{:Q:5ǜ#:@IBj!ҙ4F`Cgk-!CDh&Bkm{HcTLB1a8|ExHci@cCs׼NOlg4}4*Mvg]؅@gdD?JQ):,h(|JSFDX=`BĆ`+] KyX±֣l/Y{ Eug9S_kšy HM%Bt +F`z9*j-[tTb ,M(o+w,oS:\ &@.8 CFpmNI렞Ak% Pg6w+PaƲӭj^ qg9W}E$υXssANz2̯˂%>o%ԁ9g (wW&¢ƱNhLY^мp`XTUDEp^d㋩g0u'd oDA'P6P wNLxeDWa> It"$`Oi8(?}<S:'S)WmS-přIU09}J:M^Q8J88xxQx3"&T16r{{;I;7~D$RcO9ങIzBcsh( 7@A%!ٟ%ߚVo\z]D> D"!d~;)^Aέ$%mF(OjaZ!"BP鈾mԌ  x<>quMp8~SfMzߺ_{ 6Oh׻QU!`&8wrʼn +Ѓw,Q ~sUɄ0._dBI6UnWZ'G9yf2)1+[ !5Mm Gq܄U ;=H^Uѷ>7yS2sp|Ⱥ+{ ^SrEB]HYH񃺉2 ݰ`T `":]Czo6*ꉏ7(ilZ1\1Pd(䷙B6%e[vH~l\z֮jy/L_Whp4g"OVW%yslr,[X6(xu;{9,φ}5Շ4]D<~t9it(cڴeܼ^-:OwB4 p S .O]uA:=;@вkfeq^H8@̬ },tJ:eڦ~ؼ 1ɣ5q-!5`xpetN:+s|qr,YLB _)ۀ$BS-RfU%WWbZY'29 Ing%s`a,ZQ/\U}Oi/ZrJ=_,IzSrH)ŗcQj؛2L)5 XzC^ + F ga4_j8m^N? oc>Ͼ 2?aя0|,'M.ָTN+Yp F8> 5%]>=mPf`K?Ɏ $7#/3hO Qds \^ZZk0پ ԍ9X)>g12!3ײk+9ٗQP2(3GB+NGW6ϐִ䖕G1>S&!˘(/#l#YaݭK3׌KF?[_헉.18-ǵJL@eL2W!H~gidMÀԷ>qoLWPCD' Cg^*&/68F_NH\xJ7..F>SLbw>H>S g]4cUQ$g' 9?%~Z` .ËFv$XH4!ZyÔ>ѸaRy!~aF6h".Z]QK,>ۯ9aVUē\D1 _ⳋx!ZQ-[OW>FyN)s=NB+)ЄJKab?{H*>]o\hb 7 A51э&D~QPuj Gs1'Lp4MWpٖv|Z8jզ8gѮ6'!l/r8uqr#NJLp֮ dL\\%ӒQ&b| A}Ѡ.9,TMEB!//kӸ) M뇽*z4d!l+>B j8,p&F Ek$p\ (Y'8-8Sԟۘ2r"Eb̴j[aJ :$ߦRٹFTFm+^8 89_`=( Rj,sHuѿ೮ O,a my~ rD8KVp`7sB< FolSМihB?7x'ݪ>Ed&@qZV荡B>ڧvP/L6a t?KUnŎsb%BFyg9|FkxOZ)OˮΥ"UGB%"n7AB'" pD>d|ptiy6հAp pę%^*@CDy՝cK }cpuWО.zYTY,ubpI|l ٌP{gLBAX"ѤU DSW[ ZlY믪>E^&#][>8 þiڡٕ]"lRs@x6_2>v 1FoQMJvT?B m|-FHB92R{ 2IMᨱBGhGZS@5ʑrYP;H7.7 ^@>lR%d>;5ݶj@]~8NeO!&5 =[R}ز%ِ"pxF4?Ds>p$02(hVѤa=15ڍ sLS "PVV.@UtP5yx>wHMU$e#$߇k&3qɥp|:l4)R jҐ5K G쐸dlS {" f `NU1i,3\pR` PENg:NڻgKJNO.yQΗ<0٤e-,f/AH_0d/!%6dsa>-OK_zLWu@ EW)Ӿ}T;s1ҐA4D@~7PRYq=1?m56Vq/|>Br˅ K k^QQ:]9h(pP*>Bt0l#Qtw!ّm)/J,ZD<&>KǗ${cg۲A #`nĶ(gG=Q&xLE$x 6# .gٝS>nj#%EVMl( 9*QK3C5-}Zf(sh!9 ʻcZXLbFQ&taaVh5{ey}ԫA/uaeN)2?LYY\H!_!tLj B4!r`8"1.G ^Wg ᰀ@ӖqZ5qq7fZIl_Hw gt4'EJt]ً%)&7bL&%td ?+M N`'@~kK^^]R.2a][eh>xÉl {>.g$.q?[#f-CZ">k /[PU? |U*BI>U ';@d%ۏLV B4 4lf+醒`uN -}(Rg,?wf||K}|keOc: ʵŲ\N3\NBj@!xAf kv͍5Rn!a㻟>o`'o%DMA8K8lݬF$ c\Hg阻˄Cx2Z%=R/W;p*Y &_T ԲuЏ!PO fbfbD/ɂXxIָ}m#Pmuk#j 1{LH"]G Zj j/ LgԳ/(u:S6! ?C4m]LC\RIg?p9`^ɛ'@Ļ?_|!WP#뢈n5[V"x1RRUx@"mh9.:Nf\VI{r[ϣ%Q~1Q޴!&ZAT5b|ÅۏD%{8\aHNHw Q:t27%Gxx|F&NF]caU̴e?FQFLߎiÀ80p΅G^HYg}P(]2FoPc}gSx `37tS~! ҙY ]8~o*p&uqԏC_B>>K)HnH=B^D3D*6\r:u7=SI I--dS(|{Xk-`#M~ $eJF|:*dL2h[cR 9[LVg6JAY  \z0#`Fzq\g<:h?Ew8v"D6_!/]uTeX.ָѯ+$m#w{vp4īOaȮ.g<.QEּGK*)-g>mt+709ڷ*e=ōsDr>kߛGG~|Ke?`:1˧iPGhXos(%%cĐqq|dCqT*ѺlW6y=cd=FHr,\Ot\t_d>`O`ڱȧi&Pz¸6z|1`m۲ 9իrgӆ7*8-hYUhU{&H"Z{-"U!iADVkxZiVmySPuvR3ah[@iAU[iیx&pp.O~W$7Ov=?E]?9҇{ZD`[' GW('a'-/ou`'!|P5"USd nv`P>V!"Ry S ,^6m(]>ås5fY\Ns389\pdGbmBs8+m\+2Db>L1";hk[_ <4vG^+= k 3">C; ^8kOBWHv3 2 Y^"<-'M. gIHęeB^Dv\OأP-!n& W:]^$ %/4GWo2UAJ8qҒ=˒*Żݨ]4 Q2E@Uj!ɂc-w~Podqmy:WުD~Vs C{dq$m Dt  ;n ^sąaa ~49լ8MI` *`PP(Bb D+񻺛IΑ53JeؚMEEY 4xcD$Yݞ=H-Wԍ,@^ +AB9CydB(oSU P330Eq?Ap\ʯs 8!ya9뫰ƭ[{崲6Yknlml[;X۾#1/gل&o|!Jr,V['Orլh+2ۉ]zbAwNC>w0 5mK8#,*:k/^]'PV#.2a†V>0?pX2r `nT ~vݰXY(F5 -EH _8%p 3Cp8t0/>IK88iNjAIQ0g=|S$h⍊IڀQ第uk\ٛ#Tq0lfy+XfBGUQn9O D{M&j~_lQSON]:TwPE\\4"THql6ٍ8źц6,%7ao*^^ $BPي&LJb"8eڴΔ~r"IEUU&D>ǯD67'~!'eiށTJ td"൬'08kޤ]iq%33Mp>n4dx.8)mB[+0aW qzb!,'Z5?F7/"j7;;.Ź(|[YOY^^_BFab+eMꡄ\/D͂iKB3q Y:y '}o!4osYXt) {s[U8cK8" gN J6mVˍ 4rs윪CϾ҄M /M_ܗ(ù *]3njc/T[GF͖řX&3Q}܀8؍ʯ>S|@ĥIIkg낱?$ L|~EX_7w*ET 4J )р Yc8⒮+?zҲBCT!͝{eGY'j9X(U2ÀSy6s! {~ާ"h p  Fã$E)!!MBI>ƭ쭤wkuN,俾'^|O\9_s]BQp3cێ`{p<{ Oaawy[խFkNN}njh;[ΡCCguN[vVܭgtߋv1\Hsqwt`8Gt@")B\ B} 'S#S;NπPc`t}IuC@P9HP;D.dtٔ̈nt@'L׶\ (%S;k$tYV<0@ "*PO+K8J^dcCq4qNCw'>'8:9U/ /q6vK:^#kB!Vg !:(;AkEtXo؞@Zr(RHtu:B;XP Co>:Gp 0 NsW~!8gD G~ɳ1Ţ'k9ތ ]G4~[&@~LNuD7r7%N@XgB*劝u)v) sJp}ٔGUJݰٓpv]7z@"]uL_-DѦ3ta\tNIr6!ZsgݰbQ1;74w70bx uem4R )=+tg/qɔlLnȴ??a:\'!k/B`6cfX:A)4b7lp|1st /XB }p&K"t#OoQ=#T!~ ݌v8H޴өE^TɳBa:Hjh}Ђx !bi#GZqDIċIv*^JnōTεC9IWdC"SS$}!5y05LtDo!kW9AO9KN N/zQ*%k3&cqф4%ڟIfZ.Jב7BPS/f'p|}D'wwzyH)ANcm:hìq.7n'k4ι p fץR;PR 3aC"D.\M)L]d$ӡvf*&;"qd\⨈B|Uڎ܉m%֠.Yk@Ѩ8)NN R(cj>Y;dńƽ: 5D|0Qai,#uhC U~&\v@Fz#>M6tx(<qH({GujLBt Q AЇs4Sp#!sN$sA/ ͑%wc#QɅACs.qcxE}syLQwЀ6J|)N7V﹖ rPK T=GBaHUV(M7W!'NyR>;d^8RhBPk&̀xl$r|bVLm8>Pdm@xzz܋>Yvq.9 "o.MǝϑO߀KR2 a6"D3KXN@C־dϵOJ!85W?fH(rg XL~Q6&X8K.5La'LV1nHUQ- ͠ nJ&;CA7L^f$Zl ~Пx.S2W_jCL6tS$pB1AtU臉{w QނV\diphdC~ 5t 8K9N!N^p #L/a 0c+EvA6P~ ]a goΝGc6UGha`,T, '$㌅]vG52JU%$WDj̧r"sskG庤n}PLNtZrZAs!ZfD+O4ֻ:ڛ=z^ v%%wGJrY1= Xu .̕:J֮5كC Å69'1KzB8u~+N,$JNGe@.2ŀR”ޱbŐZҬx֌& w/ tĜx*'.JgskwLk]=/ Fj S.\ IAqQɘ"L=]m`WeGD( t[nފHz%P2-Tn*&Ȫ1pG&:N@j`u|%Y΁䑟jbF-։Z} :EyPp|@c}<Ž>[n&k0#Ĥi lkuEZrQ*P] u YqRBHBZ-X;E.ZtEP9E@Pݜ6! 2N 9cS̟иX"̌g!N Lu 6b2]WhjmX|xZrAF⮮7.@܁RDG zĆJz\ג )aWU#5BjOLR0k% q7gBav*%RElE/ $bK$D'JCrR™ɮVБȺaGPH~V@WNܜ iBΒf *!5(R}@Pw|}AMv+`40թuuq/qt5«ڥ8A[tht'7d5MUt%ˍ_QQj!N10#rTe`,Utzojl"k/06vXi+*_+Uҍ!bvm/^>s]U?oQFH'#E|+"1X/'23q]i{_ qx4YhwɺG踾 H -@!ȧo"u?eSI"i: `Tn%ͨ ׯR gf?:Xy9 Tkq^JFDZ'E>䘊\^EDuQNk|(\ʚƇ|x.R/Ї<@ 9Ο7 jp&:A>mS 8]LzH}=1怊'lHx͕6idnn3a@AXK൷V֛?<^S^)u'<$8 gC8 ${4 jyKFB66"%!?5+.(>VJBj0Pzƽ=( J ܾuM#4Q]qIO sm0}A>)պA.{!!zAܠ7[n9RA}O Kl&qH y#Ҫ\wͫ&MY*oWqȔ8o:Dl6rƴ9K4jܴWXܭ> (R$I$,K!Lא{eL]uȑ62!ryfHL. .b.4 `67irKI)$U1To ]XQʠ#ʗ +FQ08~a]d8f= uHKTD7}ِr,\tT= 'zhwټ=v\Ҩ}t44Ki܈sQhn)Co\%k Gziا暃^ԑ.J|**aPa< E]m}g~z  hy7;8E%N!ʅuZZjC1L鬁 Ϫf-bph6E68X5e8hweW Bt /?ӧ)zШynQL&Cy=Q8rAа>#EhEKvC4@?M^gC+0)8 MySuJS!9V3`MBQ˭ zXۥBs{Mmӌ 1*ۚde,`;Fb&{2Sqmy.sQ1(N_ty9E=:"@zV;hSG֟oV SߊIb"'{9}@68sLBmV6)R 0LAKl;IzlSVLW~[s$DY+IꟇF=i}H~*LD ލsg(N Qy>= B/zk2ZKm)ђV)rk7u^Vc1:xUTzB%@C.%*:2AT ,W\NNDS}bnp8f.qvgN @}kz*_ k1~*Bc2r_#k_0naH(-\p֏jg=SbU .fߞNo+ G+Șn91s+h˦X EQ)̳aSLq%3iΓw1dG5F[)<8 I/YXm h.4jb+%'>3H) YmԲn+&GSǬEpX!d;+{/]õNȢG,$O@[{SRD4C~̸JjnNGhDE,5]XqO-L_A-w@ә^jMV4 /,bUmFTWY!8ZH<8be68A^ǧ"MZ(ERN$($|DKa`눠UOPBIDsqSV1Hy>G -W:wu@}ODc< 7#i #8e49͒H؀ RRkhyek4BzG ' (YnHl&R"1wlx $Q/j׊\XcJNf$/rF " JZNHpƑJ4)"Wqy VЬoBDf'G ~Ѹ9 Ы3ud:.Ÿ1p6.E ŏ!f Mv4oEWla61_I,v|z_(BGM@:(%9*RCDaoĸ?G|YCR䣋6UDT@,#kî"e?旦SwoFC\Ϻ&[ Fw7l2O iUysx  Vͺ?Wry)8$ODngPΜ F[/*3~#jē~ikNϔ,'k7̈́*JDM7SՎCk'o&Ǫ&802MFxO XԠ Jsv P^gdaq  Ù봺G)r4T'<ߤht݅CӡXC8 /N $ڠ>1.]zv58wNۙ KPMݵs?Y'pX#PnжkN:frOr涑yЬO8`S8h~$jdhIqc7.]1r)ua`\4{k3!!QE DF{ig{nܴƂ9 *Z :ȪXLzDrVU*qV ֪"Yi؁o_T NH>y(DmnՑ:)}=e%AJRkRa7D*t;GtDDj|ZZC}y9 ?[)D- c*Z;9δ4WZyP^s^xW@aHolH,gl8a.-H1t<^P, Bɇx.RW$V889c0W|U:Պ'Ĵ{ӎ9ӆ´ kDYxV ^媔6s)5y EUUmר\Dˍ":,UChu5V H/S հ8Z,H4F!=:({z:}8hݒ"K njs̫;x9t-j#U_JǍ7քQJtΙ} a<b*ĨR&.FI :uqG>q@)jrfם#W%J@jwХ4b 6(lQ9-v1 Ia0a`j_c@KBTqw/Fq^aO(!f@a@Bc)r}!.%t x:BC!"͝{dWY'`Q8CUL;=JInߞHxlf Ta`ơAA"% (`H@@6CeZ lv{{^={Ow?*5}̤Ι]\2w3 g\P#쿐q/>psI~fcffnٌVͭv^o.7VvՊ .\}q݉W:ѮENjw.j;eg\vi|ƥ=Q8{F0sX!N3"0"|sqD^# o 0t倞"g}8AoΜEpPlKRccr]1A™331kj%TuT(r v@^Bn6p)k9u!dCyy\Nx>b36/tg'8V"fFfzpP,9+D(DBLaoY ׂhEZ9QlB:N :]7c ځ1ڹyFzHB吆E|&H`>gNy1׎c1b]Ԯkŕ v*}ÉFMw*R$!'ۉUעvB|{Pet 9@$X>8,jGT4_$gHR!.e4 "풀&g ' F~|߅U[}QsP*7D947vBOhJㅊAgFH"JDc ɺ^ME@=m$!㤿/`A>Ǯ(ݱ/%^-3Tp$2 7DKl-Kss [\s}niB!BɕgLu@zˈʕRHX'xL>#:O(Yk AoT3_'bOJ@|RGνKy;0]"5뫜;!/h ]ewhq}4?Mh6 w hh!/HLPr+$@w?G (uBϖe$fu'vW^Bz)AfR`*:O{|Js! 䍂tDF 8ivSZ[W0{m*;_kFHy,WjMݲ=$: "8ak*g~xw!5'x MUZ&T(]Z CFH 5&$gê8D(oBNںfry,'A7:XYX,P[0aJt?]rkB.2y}'_86qTcHsϐU aiajǀ\zQt9`#Vz7Ϩ_(O>] B?L4<Ӧ%#9* :0̭oI^ @")[r:Oѷٽ(k Ӫ]s0.荶CLO[٪͓x>vAbhz>tId,}H%m gς]s#yi"Ӏ\A@$(J _Eid'C"kLp<, h 8 8I@Շ[$D}#" )jϹ. Қ չ$c$}E.!z Qů"^BDpi yAγe'-tfνC һ̐)S7q&v,X]$ {ٲѾBNZ>EݎkJǍj9@b Y( 2o}>h28 TpgP G~|XӲS穎\iBYx9PKV]Y6t *:!iW gOv`*:p^@p^k 1*gђ+UghWHΈ*?Nscאs+'$s?^mQ8]'M'#g˕R"!dW. CrVn 9QPB\&<|rēygöt}v&fO׍Xroc,U%P.O?|64^ WM@n]_RU#7t}:^9 U m᎖NJ(WP19f>MrZ[uVj/2,8r!kDEB0&TnV'|hㄔra<ۯt_wf0'vjԴ3b &tzԨpYm,x8Qծp"7ha+v--7havt 8baj<,LYT{?ns+QrzbXcp~];:uU=5UYkb8I=h%5eWȒZ\k3{B.v` nN/&qR{~޼PTF&]'mqF:ž/I't{y pCMG ^OhttCF8Pj +\Kx>făP~8 ^ҩMgC~PbiiP{`y_f: `Iz7poHW70nmC$&a6^y嬋nnViGڋ Hjɻ@2ÜˤJQ]9񏌨C8'4A]}7;=ޕ-kl$W+#}2QTE$O%ѽFmPyh~OlMg>o#)zz8=-K_X+keP)N˦&e*w(.&4njszzPq?N3̉i^ QE{y"M,$d!zQ Xv-R%UǴhOVp; LrˆWP K [LBiY NJʖpf(/Y.ke/S4E+hӀ84pT$i=Oή\J-,8[9{[«#, -8I?BD0o*i޲ҩît9M" WiU sATVnR$#]$/[8  &FS#vI8s+V!Tx5z5HE:T:!9F M u:>xMiUX;Vg.%P1/MEFZˍZ)[˓ʻH:t9e{v71dht@iE.bUG$D?4#ܛ%u X}1& zA9y;GO1w9̲m\"mr<8ᣇ i;Wm|_ٛ*xgkyڌ&r8 :{qBUBCؼEvTāh.~n ([=^́RK]. q`$=$_Om-C۲JQqU09deTĆ7/I)7wtf :g7jr2\H}Ɔab [Ǎ2?>OhB'r?ץAe= $g <àK5Rs:gȌpb X3ɤqaRgѯWm0O9R"BQY7Ӳ8\qs u&DV\_зFۦfYz$zA 8H[s0vBP$CnևBaiA&v'm,Vw&(`ʶih9MEL(S`5}SnOMQ>vu`XnP"Az/Ҹ"teD;*BT} APDGL!$D~l*&"#q.39Vm_2*{!' -D*ez4;wի5W _ǔXh'w@i5H>@6NZyIƹ/4IvSQԍn\9n\ "GmKݼn;UI"!C&t8eAgQb-Y/3yLJRf/ᙯS9 MjR_z N2N$.P)Kh`B8B64i5I8A#g_3=AGZzZ&"` #q)H~= ]@""@ B&9DhM&Ρa۴@qn'@i PU 21ТdO1*4> h*F O|%4d5X@A=HܛJ ᔥSfS9{ݞdg6Ԃb2 RKI',&J}(JElrrG|ݨ j^Dgxdt'qI[&4XxlnR_>~K9JFq7Y|В-tOlJP?gTPSrȗ"=PxP 5g@ڗ! F^׍Jp6 =¹Gy NgԅMIvHT$"!8d{~_8@8,,ENx>Cv,y5q)= em<myPmL4`/'lqBmytߍY-M$18[gkys1>EYYz.s͡}*} P3Q];mCo\p{}C@?Pd()ŵͥbgqceq{'LtV#6"R0*X-D[͉hz nÄ22=$|=$^\HLx$hʨʉ]@qq7Ɉ2LrXOqJL$J<亂4OpB3qI4> `c` JtE<Ǵ )q`ukyPA$Kҽ 億S)P$Z$ҁK=skaSHFt4g"o#kO`FR8afp k#8q4 +YG0 EN09ASdm:X r$~'LZ8tQ5[l ԍ%,c{r 5Y:^  &s6 qC>e#ڥ*l5ɋ M:´W`Wg*""TxxZʹZ\LLLBX{J}yսV:s7/WPK7]4Z_T fQ;f 4~+|4| ē4кa,qig'&JR0RZjv8wҳ`;t4Yқݐb)UH,C gӻq)g$i:!ax GgUyL5-NY9C:S߁` tReG/ }d=mgl`w2 vѽߩNƁ! #C)8g\1ԡcd#gK"0Y%kr'̅暚L/89&񌓻bg0j+Ѹ81[8DRcͬkƄsmHIbv7'SAʊ0 yIg45y5MY7` {N4e#.C;<~61]TtۧN9>ijA.t>(OJR̦-n~:)wN ZapyАHi&3OǗPJr< uhg&uABrpBR:zw:u;8LUz)H m_@s$(=%MH-5n 0s!,Ux]{+8z9AuVn&SS$:׼})(h^Yҁe$D/!C}hح"< [lmUT\P}֚*m^4 Tr4͝Uy_vG`ڵ r UڻK;j<U;a5S"ҿ !7u.tAc1ê/Ps.0ڷ#gQȆ!dSBycClat\A&"9)woR׉drC"B#z% )pj!LqS߮*)%wd]`L֎)M?^*fR2SDY{<,>:'Mя~ɥ\ģs&0yKÉBY< ]o9$P'D>V3 o"k_p‰ch'iϢ'^l]D繌'A9ԋȓ`]'r)Ep.8'(<=GD59r-5qXĜo8Si8vbJ0JƲ*la 7 ?{a0ʼn>AKXXqFôgigi)ξ|Lڰ6wTs_q:X T"17GD` MJ0G*xUKpΣk$~C-"(m0T>sh f=H˕#]kq0[M.(XQ`=O5)+ǜ"vUI>&gzRc p4 [ݵ}WViJ ge1m{g2\I9Q%[бX) $T bPr [:=B5X h|5cȄrFZ$pV:n…gNDrv4|[|z Yޅ&QzadɊ-f]7jIBOqS&$ژM V$OX9垚n8PLֆ.@:> z5> ]̩=SRMhFz|.HcAs,C:J a('Nhۯᆰ Lhm'"%Tђ_0dN'Py*l]ICG[,&aNq"U#5S.<mC5ϙ~K%z\ȁ7T"jއ^Hdq}%ш "j$+d-ۺj40ģ &8j4Ɠp[]+s$ {4 2!Ū$ֱ'H. aթ'&$b٠ -1W K +j*>b%.c&k)Uqt+Rs&)@rC8OO$8s$5x+ a[ DjQʺՂ: TN#yX۹X6H3e8ӻqgp$rZWmG.X`yL=Lf-M(Ģ'KgZlqGbeJ}f "\4NaҸ߱ƁI5$h}*]OD)0nL!ElENU/ڳIg`|!ģijY.{ڸ b 3)ߋNXXrkޤFY1+0Y{ LUYaԉbWԅ\2@o'@[Ol:ehUUC/a< ˈDOn+dPQPм^W(B@2pZS8y.rMby -yOႷU8 2lvgyPa7,fnG{cHU44efwaQCX.X~F4O"kmH"&?4 l' $bc߅$[RX fP1SVP  'f _p($p3Nb!PmmfzmT}V;e~ʭ{9c;gӓ%_騖=`sdj3X`zmJSMujҸ8JsQS &rAgQD0ic3ter/?o^N;zJ m6va$U=p1CsbV1zvA$r٧硯B0`=T%}ݔ<%m'KpNT\*\28NF@%ks7 gN\"}oYSX:9IyոYp k"ѻM[|0t !*H2~r˛P|jLǑ&ٶ 5+MhJC0RDY; t Ysyf/hz7 ѮuYh6Ѽ}efs뷙P?dλmռ(=3\qM SWq6ƒI/AL%DZw|J)neK N8$LJ#֛UWX~a~᫫Ua"\hNhI8diN4r#TG|ޙ(Ro}go1 +Ǎ2Rv RKd8D E-fgѥ,Wl_%%鬪ԼyXc{D&SN!sVK=zWvr@u{ɇ3eI d]NDSNabF򼔬ǍG~l7 0GF&$ZC7$e8,g s*F9s"ҏ((!m=vO,?NLŨ뭼;ڽ.D@"./ =}HCb['K}#l3м:I(L\p.Td~8184C<< \m8.P.QO|@ x *:sxOю x+Rn%9gFAA<$+~D|ΟHM*tl5>JPsQGnBC!͝kdGugwFn "3H/ct؀ImXz'!6/Ha y@pAD q5@$$QT[woͭnaYcֲssu7~~qaǯ^/@<*;7`ǣ(D8|8%:H$!D`m8w1(\z)wei|_"873o"G>\)6yd5J\ 枛q# !DAFadC%P[<-y|,O4 E07ymq)JiPb{i.vNΓ>)9]jg霣P uGK6qhH>~~E#O#7୍:vQ,XGX XY}ӺY{UZ|T\76kj\ vNjMuFت)" [㕵zmiciyX^^ٮ5g4$`#}lAiTơQ{Y s0-VC ;^ ;6P';]08^K)^қHJq'PagNpҽt;5A( X۾`(B:mB[j#Ee*^@r:.P'+V$7eruuPp=?? ws _ '9ƹ`q|༷b;Su(oUWR4/Su%}+.7vj0)A,bmMUҜ&KFY{,R qp296ڰ RCV"^d˹E ŬK"MAn;r)OCi>YC5q$D$4IE K8q&d_ =d L/bD_L$v %26<1xSwd@(Ë ݏeSΒ LtTMe%/v~/Hw@L`97ӭd7r(GՙxMӾ/*vDv8\G *)ϖ#0s ߽} *RPsh,@IzlE{$lJ-U@#s}}BtkYD9 nLnu;Rˉ7 >DFl"FH: 4p)(抅dh0տl:f ABtW" zy~qwv5ex_$8o,44Y-^J步 (3}8#]@Rj `Nq$H(!zwiP39B#?"4V&􅨝Y)"DD5+f$]41E=d2O8Tsu4A$]b0h6oѸ*jI(t0ҪS#8r]}򄓺 hM(J#?4ۮih絑zԀxZ(<[ՁpFѥv6!/b5[6T" ܈Վ(#:fjeĥ|G8YWP"Uٓ!q';UE8wO* N=K&LY ~ icF&ɷ):!y+޶bʇx4 䶄HA> {57hYRiA}p0zBT 0g{fuqOjd8.pRy66@,p끡nV-B(˶ܚcаaͅV YNhį@8}&*STSH w2"\qh9pɴ'}k,g(5?MZ xܕo$KZ* & uCڶjHCȄYov-qn&kJ?I<^Zf<mInfmI+(P.fş#K#VJ2+5uS]EmҮ3-TwՕP >Lajrׁxz]ZG4 ch Z1j= H 6{ %IpjܰjNQ5[t;VJ2Hãw JBnp+f[W^pShͪ˸ s4Tv$YC0g GKKZVAAvH h@ ~j`( c8Pza͸:MvBd'DTPJ-ف0ni4n;nHOqxt["kg- |> wb RpZNq[|AɺJSD &uݸj5I;r03TjiWkm=TRyS&ơ%00mAvTFDNtA*2ыڝv@d8RM$KVB zeY{%5"))r#d׬x8.,4U8j@27YVC9`صF*umَJȟ^02٪FЖ\ _e[8HUdۜe7=#8֛mX~i.1㤚y槹rm]F͉֛kMDtKD8}T;fiHAzYi,ϓ0\.)W+"ew¶Nǭ.Du;s4oFN& J848uɝ܌B y]@$( D>]3_ꚉ.ا(4/}bIJd8`%ցUewoO:9MvP\|iqr ^n1J>fh<̎q$KA'"@F80/Ͼ|+l,3,Gnd%eW8i@;yxW˶uedzHy7m:X&fMus%Cw/!yἜ m:sY{sџ1|z8``y8i|KpN3 MS@q-8Xv\RZmYtǃbs~ҪOy>τ#V/Jʆ杴Vs'yT6ӬC e?G ķ@KWKP}ش$1)1- اVO }`J3 hK65<~:Yk@ȫ誽]tr>0Uz0S q6\.FAmIIͱEʘ"Egsgm#xý̊ҴC,C/~2T'C>C N7dtCqW؁) ( l|:z+q+ ؽiS]Z)f~Apb! ڑSrCBM%K?REO~HPwlyM9Plm8iI'+&Do(M鯠v)ƭ92PLDe"@_8u!U6Ub @Iǐr@5I5'BsU .U_>y nP.\+@+ڹdfDC)sq+\nEe.紏[7WλH8lyjIcf X'Bs0;Njbg%Nn1?5}J Py{[Yұ(,ޜ6spglp"yOZ-t#oC!{V?J1ysڋmbYF1~`!{f4E4] B-w{6l3;N<š3\\ ;MX>႘DǤoZqa ]}N>G4CqגwY)ۃ*%eDc'ړ%;0OYaE9O,i#/~x7*i) aqٕ}8} װ P 4ɴ4ٌfִFn!^ }ut dv0t(mÙ dgG9PCVZ!u83'EYTEp":)Ij|C te41~Tow&S",Y>&v.&1^QP SќCr ᄡ?[n)=Ƀ6(4iNQi,;c/Aij.FM%9'[? 'JdYoP p'( 3r.`FJܭWL +t'$zIt5-7i] T*?gWi&P]i%?a[fOs$S$#]m.Ĵ$hBe97,K&' ݌tJn1z 4* $CgZ9,v_d89( #}w:TѭpIҷ@#D Y8=5Oz4jg5YsQ*14qxTNO8Cm+GNt/ [?}m+^0tp+tGxJpN#v /Hx.46d)8"Ξ{?*I#)?.r ^/ti ) ;jSPZSzqΡ~j6[$,L.άyDH*yZЋF6m̛8ܓ UpBaF8zwVm\ jjP% )ӆFV}JV+3ѣ< LuZ3B+*\0;VYZ~] Rb|X>f^u7g$Xq)@b'Ox(~ƓG>2x u9/2ߦw>Wʨo3eU[>48ޥ!߳NN^,pV'Ho(Ȫ}DkX{N&]AY>dETB ĕA&VR㊕2iA"4W-ÛblgEp5r湛ahTbqVֶiRu'im;q(FUj;ЗwDCFFG86Tz-oM\4@J\u )!SiEfh(DR>4-nS"A߉[Hy(\.q!+P"BWz;YxtIYVb4!bU|p甥I'4 sN{ N+*" ieZyFY2]@iQKm"6Њ+ ^;X^eH?Jn)ZRG"Ɣ>KqG Ԥ$k)&Ž/w'ZRi_-V' Q8mƠo:OR[ tBR'[4@r~lK -or#]Rzg"Nڼ'` ќBC!ŝ dGy{w!)G2!<1+:s_w{lwLCs0 s9(s[B"ޓ$QB J"HI"wtMվ+\:zRqO_6 F=ɽn:_( =c1Ax \]B h4Z͕nsuvZk;vsk]w0\tۇխCNΡV{v7mm]wӍ}7vn{7~@ r@9"D hJ wAt bΐ66HxzHSF¸S $t,ַ9KN4*n!=3k=w7Y{΁gtVB!=@־`GQhFvj 3m&LfpL@HϐN+ -O? Ry<<ъ!u;K~nuNP`{MЮ#C^siZεJ7yČ~Bt)Q eDa0)6 -S (肰 {:2zD9fSqXAXjQ1w\%C!~iUU'=e @ߖsH{MOa߁(+_DYkvʴ9$;ӝNm,跽L;f\Vz1W̙}^P,gh%]r 6KC1=WN8$u;@ێP$R=Jny"Ush澙dk aP@`ƩxBE]PtbK(j q;SWTfVbPY4U~R+fKS'aiשCP01dgIw=ܘǎK=/ pT M]aؕJD}Yˊ )F3ѻ3QI Tۊ b,UPy5V8vj:WY@q㬻w OsD"ko#Dxn*@ꁸ 1;@1:vB<jUwi>T؅0>]d"_p -1p<+$k۸*r'VDB4!/yS4;#<үska* '?Aܨ$;hi$$Ge0((NP[}ƹ:4ތfЬ:3 %^/P F~P$jjZ:z9ݦ됵QIMui0Sg`o|S2s+Y{qF޼1?Y^hQHJdRʲ[!`]UtcE#B`"$VQmxj#tO>o D[.g(qH^09_$kf\D\sQ!-$u p!4CE*hfJAE3TC:R )AU/wX(qCh {v= EAYm'\""gK4".<7eG^ȉ;0 QAm PC6Xoxay(QIϰEpsV+eQT{szoyܬ d/ZA$&aK~BS)c.h ~COʼnP%BbnvF"[1bՆ^<k),h|{E! % ڨt yH|Y xC%˹ڦ"TaҵTTD?`mhA]},_lYIE+ɮ #p/D-"\+cm= EZm٭y:V!]TbJ:\4+qu4fEf۲R|t`|Q+/l5+6gW?4Y5d9LԺ6ڮ ſǠVg~َHt`1N}mۗ,78PJdQ0<,ޖ;9%M)H16JTiD#e౰F*.t*+$,xXЋp"d(0ozm#H 8·y:.6?Xo)DkN?!('軥ͪ74ZQ`:Kj&R9 AxLkf"Lt8`=k ꘱ӫւ^Wt>uz0ǁkO亘;͐j'_9Op^o,#09bվOPn_ 1Mm\'0+ȬNä \6=,Nӫ:D}E.U N%87ƁK]W'OwE}KO@#086ՎaHÒOIPy[aj&2bt'Z]PE|}v3j BӣН &FG_0.? U*FbfPN+M8G_.KpЊFgn 0W 7Bh\4AYǦpU&P'9"Yiff%[f0ÅXH-3>oZ@C?rXL S$k/"Bb0\E8$QW~V G$D ɞfϭ4 i`U CDoue$0 bHcVHX8, RK B1tbN ϖcv3LLF;$q88ȁUm8]I`TO#F tL[EnZuS`f!T( M=XU0"iGjr;.kYY3X#p@?"@~`*eBQ$2qjZI% e`N[K~b%!ZцNxU VmWW:9<;USp"yTgݪT#%J.YR/NgيNpDtt4s?CUj hU4P.d ]zMf6M>5iVocŜuۺ reAS%~Hc$e;kR ѷZ5Rv~F~bչ`0GOr`#.k2`E)p[.7]Ta˶!J06] $Un`Wz5ےx{f"h#;.5ew{*3 ͷrՇoh d +?fwY]"/{<[B$V PE1K%ۨIޥn-]k*yd3 y^\k#JDTؕG+1+ږR(&ԔF [q An gCD là|}`d$4h˅k#VbP?'G1^]\T ,RWj`ϊ`amwXI;@& RX6?[y\2IUFn#%y1O>b C : ߅% Hv]6b+58Y='_.8tn}&rW* Lm\,9C\Ö.mH|@6]gTE kl{ܾ+3hgJM4U_}k6X"a "DchY K-HYXWLgY"s'l |v62p LD=K5w ٜlz^ge˒YU\2RM}@w A!ʢUI[ΥqHZãLWZ%a:IY}frP=&ݫU84)ZHI?\>l:`=p`s=ÉijhL4<U#_8WTYj#:%|B(yAFZqa_R;uP") q_o)';/+R76'VHq,m8}Lny,)5RЈ3< 4=(=vұ}{q9o|IBkmxb)ξ7XȆj#F-v<_ Q\d7<ۖGxfy6"bw^B˰53OhYaF) ]`IWS,ŲVؽֶuյT&3(yB{VPXTb&p7XM' \Bw }}҆2^gنcQ=${MjP.y\%vĭ 濠+% S P"IԏO{8,?\Z~@a~jm"lɾ'@zX Aո9C8mU6ʞrP嶙&H/1EBnG\9[aΫoG=(jBQ<`&zl.L~.эPٙ5g`z|^܍&j Ybkg>oWŔ72U+{#ޠdNa-^ g%^&[_fo}j ^[^3Zp[NiҐ6D]齽*wX#+j~q!oP GӜRh bgo-;P{I\ :"U LPGռ럶t:z{HiˬT8#D~1ߛXqD] g+~6D8iV2ہI*+zc҉]7Z0dT8Hg<&A9ϺmQRr=]l'Jw$;Va'YB ;b6z.YÎH|Uh zdv{Uq6FPH3dmbŃ< ™֕i4N]me" ).iB?y( NlA\3h:J=' Qgt8Jpiq)f4a3aK0~K0F>-'@˾M]%t 仍7u=g-/m3䷒>4LG烣8lG|T\00sKd+}@@sTm5:,aa%G}AC/O701ou˹JM;qR9B\O0n!(;lg(r[ԝThXmu(-O#ץٗV"0҇כ >}wщ zuS#k/A$4?F*ΖK"iʈǫ#GeyuR ΄ `8gni/@q>}\wzW ^J1CbE]yGvq/#kŧCl$E ud`A#PBpԘ%!k <+xVw0Jy'[{%F$ldԁe#;cAB,tx#wYDbye4ϪeHSGM޳d1*C*RD(IJvh}tt'l G8@IOY@)|$˼ik}ɞF~^7 l$a&Gۥr.ihdk҈W}>8#='I^d  aº ǭMBC!͝yeWY_fJK?V&ܳmIr{ !23LfJ"BL0n#( P6-@0$Ä**K-Pʅ*4s>gyR̙I~o?_ϟk4^u 5N4 ;;FgyuxѿP"=X8'ho,lm&dfscyei'N}Mlw!vGӛUpp' 2jp   s٤?co!bJtOlE\<(89$'mp +G3yф$BK<C糠Lh(4S] xn 4M-kMo-:8*(<7Њ6PP#@=Hx5>B8oon@ 6pL.J2oӃL>J}{㰱HuM`nBCͶIEu]XXa/ђ{#Ŀw3y45 -fTTuA#^a /Bnc̊#1>4"g5t>(Yrt(he9^\T^tx`܅ӭ:t'jmtOCz=Ѹ"mCP =-GDGj ^8Q_"4[͍]ih^|\ÎbwO>aqY a-0[wF7T/844/u-,JNs@rht9Y|!grFW[`OtAo -ߢz9{R-Dt6Rٯ[1b<!3QF< g|!Ά$_wZĢALv" LB]>M>a'-˂IJ$[nƳ %Z]:P j՛Z,[K|\oKx A<%4|Rg@H~( I0!g=Q tD߳ ^#O% Yl22#>!zؘ(;"Ba H2RQaٟ{Sy)(U]IS sfaPR(w@D /H+V)O[U)s"+V&Dv2[ M~2ҼV|ͱ H`]`-i|_΄rrzU:?b V +j-: 7r TU'm q>EG+5LFA@IfLqr"gY@ y5/.Ġ ZrvR,fN` j~ H~W.V ;l՘A hPSjaY'"ZLu0O֍fs%^e#%Kq֝h:%29 ȇBzD"К+w뮐]j -x&*WkGIf_үPOF,2ɥdS놭 .re-48ߖݖ jkT* AsnŅҘS}=FNH=$<+ +=n] ;MҺ2 `i* mDcӾ.y'Iw cW$7 CH_ ڂ;8Kpa;9$;%5Sw& w8bp 4ru q#uwY%FsB>k9d{imѬףɚ$-H&g3 #)'vz uSN\}hfahr׬x;2"ydϑ/˄JS(29{ܘ}F.r5K{OS JR- |6A/Q-5SV5${{Ʃ`:˭}Y,xG!l.<׽ h6Q-eG= f-w|wsj NYrAQh{j4$brӸn > G"COI.JHb}e)؆)G$z"mͻD ;lhEHJD̴N+PG8" q9ZH4x0f._RFtdb"g±#-TNA#.U >+"?uHn:׍:ـ!2Q@O@ B/T|b!0dsp>Fq_j~x[4fI ,_&4}h}j3XJ ГƩ{@J@k5^q' xxU:V*Nq.Sh~pv Nmp;AQtMx+AId+L ꥓O #xpJvx:=Vq(J ЏA%E~BG`mGp&*Vqr qv2Z':6fI BBBrXI-t~?c}ÑY 9;`Cbp,fMn̴lCYt=9 AImެyh/J≎cVD;`8AZ_PjD-3q$w o `bXBAPr`=LP$}lV9nU0#dpN߷‰Җa'ԻP:5`S>KmzfиKpd80X/4duU+mh r]aԕl Usn@p&~[OGGOuQ2&u:p* nHˮ @+kU㮠su=%x$+b 0m-3"hp\,RZRK%܇4eaE'ziYaX+rYKT#X!]9DJk:)m֯䤞DZ/'g"b;HR#N;WHoEb0"RSF=Z0H{OW@:hADN.*MSG٣6<& ~Cg n FwXPQ bF3ň| /;`>İ`usםo+8}/1*rX |[!g#;Bͯo.jFFY&P`QIt}q : I)\agNN`6DAIrI02&x=4㖯Ozrv4)S!ͭfgNWewfABo^LÒQ̰^=,sݞVnʃR8,ujJ'!:r+dH.$B vHPr~XEyJן63y*uv$Ǔ'dg#gw[8|\x)<ϒF**Gґ7\&9{Mp;rl>[<#$30/тsm ITO|jEuB1c +)RCЇ1KN)PVQ %T'Я Σ*O?2`Yǃϐc*Gy9^F#4/DP;ɖԶ{@ӏqLD- +{,|wϻMB FS0Ɗ=!,H/S$=ч90,'wX:m3u{59{ϏSۃl݊'?D@|gI!"z9۲B a҆C ^iͶ,#gBjvHPZ>GT{{biQ+ KR,#VD H+,Æ";h랖B^1zY:z ^ڬ_ I(L>Z 9$P/jŕIxQ&&/^7Q4 4yBUg0Bp<#?xۇ؄1bOnDT7Tz)4+TdvnTn*E1"ep_Amw U$-%MZOStP[ĭܧH.6)R6 #ݢo1ܠ'#@fRJdZpw k ,197îYѲ$^z,p I]Mή'Ge8T⒧uHw;0o Ҳ#^-'EƏT!OӴVɑC!;0PH<+nxoiy^`!gP֭5ϡ;M7JwWMiӨuq>JhƽP V~@rPΈrp.()hNq+f` I+{'Yy;V/E oW&;LUVh+m8e?1`hɩ}Ь§>sǍ+6Ǘ({$p^o蘑StUڝ . { tLft4r*%lIO!B}%wfcq쉗)4<ॷwZSoUHڬ Rpm4q5 YˎF,ԓO IE06]) P,GJ&w'Z IАGYq=B@̩ ԧ =O̖[Vot,L(z茆kCPV48b)$s/9NJŏQ8}sV9*9{K72<6n{'}79s}=pR7zV$60A g(*^r+Xl0P-Wԯi PszD tar>;,4&M򘫦<:/4>reA*>) _j\zr]6j&ߊi6lLqk*+ڹک:ږpȦ-Amל{7'2e9eq\FY&CmtlvNliuPlnc6cq2X:~wWq"\LpJ>Tr% ^'i8{"V%;H <{GhH-,$jJlWz茂">ri(yj7AIAY-$?sh@|1Oe=) #Yh!kriH%*"Eu*'g{-P9u{OiۑO_PG]i` % X@q) 2Jj(<W`|9' fɭ05UY,MY1W8˾-.a͇c$i QtU_U-,ꇲ~\g8|HߵqR <'|Z! FPϖk%Y9G th5+ ΕYvH3:o[:TAK"Y3ss8ڂKgkU[=,:o>ag7Y5\JNϨ8O7ED HÙOq %f+(>' XSF3/k,E @}.%üfb]q #ĜLd=tK> OO$رTTW(t:Y,(G!?7e6 B(_+'gX{[Lg&yf"B{DXyDW`?73W2Lz=,-%<`̃9} FLFwHi6#!LiMs?Za„9A'(Uۧ}*NR9CIgh[[@J~-uG{Tp=}8hEl+ߴ|sַzˁkϙFiHeUտQ﫚`TBs wf^[1wȥ˓gJ xU 3Q[M\ nؕRT@z;(qA#ətbU2:HnEWyڮxR-O\9@_j25wIwqq UsS$WXO[<f~Gkn6R7ZzF . iԭV ˾ߡ:ٌS>3 's_F%bċR/ ^I"hCV R"G<4с%SQ`5$s6(Z@ElÉ<3ɼz[uyyb:@;@ @^oT@:]A1'H]+j>t ”N ,*Gԃj,여x|_,q<FЁ^%_L5zaTݹZxXѹUq;qxy4/4n6]YqtX2)",?wH^kC|?#SB@  6Ob O<#0C?sL7ՖXZت%ڕz.TPN€ϴn}SqLw=Q}yOM\ BŜǰ)s$ՎOW؎HL@8 HPIW=~O<y`8cSl*<=?D398tpx{cQQP6LuLY͟Q@E8 'v8@LgadDg1g^jJ@(^wHMT/6DF 43Q\cSĭtVa@ơr-`"%LNrHrvAg!-mPACsۯmBxCi'QZMtg*nb}B_E0g,3 N! 8[%`MӊF8@|69 Cybw`М b0i(SzOPӂY[OYok*&1 A~íU$lLV>/{3[G8[Y&}RF(SЗ"v!Y!U_O#-{\6& :XZ*Z!{]V44dA0uESU:}URm[Qġ-uV|[)x6R'でfݙM :PW/NjY"e+ U{qp78j#$>X2}"+m >ܫqH)3Q_ k9ajaC 83 ~8Ӽ đ9S!KQi3'],Ԓ 7qt5oWߑ( en5 "{9 $_{8EU~ ͱE]yԯ+@n쳣@T !hS$zˊ$[8kKk۪kW'u0nKyݽ0Jqp0 P +DSܚO[_7 ̻SluYTܘ0P ލII?>3Y⡽]ktNW ȃ5RvNcg(Bc-jm$P$.YBCx!͝y%G}ǟw!dGQM&D:w;}^߉C@p0 8)aBbr*A`k\?@Hu]۵][yk%k>׿߯~:t:Ǟ8zUγ?t~'xtڝN<Bgƞw.8y& wu:dsw~wockw;X}É zY;e;cIfd/9qr5;^zǻUSU]va'9{Avf0.y?]MQ@GAD9 P~ %* 0ސ$Ps h}L'ac F%:O7 }t.gd4cJv%8H "xX7aiԞF)'@>hfcܦ2Y\c1)~ؓ~my1 |4QMCԯ48ګB Y@<'XɅ}Tz;PGKG𼝬ъrdy8ϦcS'0EzLbFHkT+X!?DrrC%9ךe=y wdVPI>Dr&Ԭ$ fH'AP iSTG۟S (5Z2)2w~2c !gQlȂ0lE66{S+I0)TVyDr $*aQ"G!VOZhH1E:pnxb Qmzj,dbu{.(cU?\Rt;1YJ>(ROT$m}ukMwZi'ik2y&_~nqL'O(`ǷlPv\#(CJ#vznv@v +W#-ig\p#*<u.IMlI [cMB-h(`>T\{Nblt 8jtUu@>YNAhlI|\*w9v ۞W<Z>vPO" p3?eM5OЊr0Ζb|e b +ڋxB1/P)02LLgT4op6,4J3q:#H^iE*A?|DD#R:}iFzeAfFvp"Y ~L@L,|GH0CĢ,nx d՜ TץR7< jwP|p=iH(и[ }q;Mxb?8[[NqvH-5ohтp{R4]M!6azUS `LbE(:WHl8FFKబ/eY-8nH+MjLM lCh7?uUW 2Haӊr37*N>#?Zo@XnRuxyHywXECW/TS#k7жxBY o$- nx$^5YY!JySL?86~' Ыs&9K~TD{Y{Q)>HGiJ;C3 jLw!򙽹q"y3A*E}.эG/q TN4u5k|1(bȏ^VEs>QΠMZzQc,,jUޑ;/Lꎼy]'w4<{.yrU Fl%&:?a*w|$$n?Lvδ3m;8K`\c~%OXA8b͵V߀]̏5TK6:5'K0#~mդmmEueN@K琂`"PD> 0(), RDg";.%# r;i;R oߟP4k3 1#hӵt͎) Sv+)<A s$dVDЗ:TFm۫OBWd]kńLRI@%&HG0%kAM(qO#=N;"yKUQGOғpb>zϰ-G #@;#wYA \#Ҫ~wXءLwMQ8c{l  z!њ# 2iW;52Aǎt:<(R0,ej߻eP9RL Rӌ эk#E] R|bLsIU&E^dT FGUB"B!Gv@cVo}A8/jqk%<ӒG: {|6JאQU6B:TrL7J6Gyy+6OTP@n![b,.tmRk(reu4 ]!:$|g %LA;zQ?ESGij<[~kDG7(o8^cOϒ?l8K$Ƽw)%G"Ipl+V oTOy~yKR~9@,0|]o \abjzT(޶ҵ;1eHinbw|wD 7)$hoL'0 ˣw͇n`Q%~B]&7Z ƀ+RrU׮T_D+d"@<>] 20`C1`LZQZM^0Q_RX#կlLM])B N/}j$}đOnYmc=D<ؓeW5㺰5`QZwE0y$ZɅ- ːrg&RKZ!Z_2"ebE!S:YS~cf,eBL|KՕ Z6>M!MJo" ğQQ[_WRXNoELtOZQ@!j*lAP7#RF!J/ E"s`rCz% ȏ7C4Ej /JKJwY()U䃀ij:'[wb}ƧzXQs[:Ǯ(%2d*>E/d@ ^:lGe<#ι .kW^˫x6CQ^m׍Adʺ$EV. DjCV.Md妀v@%MCU./Wq| vϪҐ?AgI洒g'B`< Ȋ(rkU< V8:]j:$Z-i>*b)T(pާ: HF7{K1:;B #14] |!Ejhϣ Ƴt4AeG:iIVH hXR 75."~Ǣqq4gKHF$wUIGp􂰉VI۸J­Η4(snɓ)zv`s5s=äP{TBXO^.!d, 57j.(LbtcT=F<-q%;o+hJ{!I)HBi5RcG>암kB8+*Į}1I ^UWmŝ2-doŃr,M8̔k9B9σ]sQ<ѓx QM;XJ!Då~sUjw"kC;_}iZT Uf;B2/P7 O>o7ݓ]e.[w:ј4;iB߫0}US fTFmq@k+G^۸.U*>Z6)߷y%<F% V;1; %#BטШ.ZuAgL^l~U6Љ35Cu9s%DD+!Q\"ә0y~ڍ OF\E܃g8079^bhvBWSWZx|E}n1"UUz1`ՔD_I!xָmiJZa/o^Q?aU{. ,fcp2yYP(P;JYI<-F+z.\j0דĊuOrJ[m9:܏({N (fjS`i'e@x,hgm ]7kbjK#{i!vPv4GJZ ]{azH%z YJw#o&Z\ױF>&ũny/  /J7[h/m|݆|sh~RF&Yvx:y y 0m~yL>J'b=Lo<<5Ǫ}X !s*Ӟ 6sYO,WDWhUL+j"~@_"ؽDKۄU]AKz&kuo54$w'wSڽveXEwkv&UMo۽+8lhv$H=62|mm!,|h<0=:A1(d;A~$hdm'mUŝsF[aU+bp1 @KumHQis!k3+c$8T4얏>EbIۡ&#k/Rb8R֝ XHLrP:]Ȩ6*+H~ۭhi4VV$R*޻DMfCR^F~s&<}x3J5C3]7e>X<0C@`Yy݁(Ej#Jm2,|1vwfsg:'gF![^]25ZYi~5<1Je?}/G 2#J]󛡑ĨqP)hY}cWȪYg5.G>nrrr9N|?wC}Қjd96O0q{D`:F<myByGW(r:[rsmyKy\Q/dT Q1}Iq7wζ*:}5O `ʤ1uS$\^quZq^Sgܸug<2L 5|D"Nq0<oA ޺=l""8Gڐ4~`n.S`uM2]H(Qqi)k7HMdNb#f)gU XY|VӪ*z_A/12Dy x.G3tU[NR :vqH%b(!=BO%}hkouWwé92tBC*!ŝkeG]ovQ̔Z0|Ԡpr[ HFS*[p?[%j#C[b>(g_ ;T6$$T%gO u p!FaTaVusOA+Q|vٔ\IȽg9΁, ]+֙2'bDj.M.qf\U(+X, *x;#JjM>B%gig ӗə)~6,k)iBiD=S4qtZ:ϺF<$GW Kplrc<^NyT2rG а~;>㲚yUmƽ˨lsA+ 0>9#~ChgQ@A9sBJ5eP]k4ҩ/g3N(f}<<}u~EbwUP1QQ趞V[!P@ݩ.^7Zϯu4 JU])FALkTL# *5JՂ) un(*'ne[cBQ̥;jĄ֢)#V(+O4j)F7hQsE1W ނ1yqrZԢ2ICF<#xÈڦ!E U@f@Thݲ|K&jKzkⰋ>u33fv%*2T_ Zr #lӅ-q_8@q@޲>Vyb[p i}ʻM:js6A9))'f΃'Lf6XA#N7.h:4ﵥ|i%S⳷y_ u[ǁRh[mC!Lo=]!$NeFbJr4*&vaka :7p(/(mZs%nkO]" T T;b~PԄ- 5n~㳏֦RySn)m[DA 1H%gߚ͌B( gw\:;m4oqRBWjFbKYR} pJOߞCkPk|Fl]  \۵8k8k 64oS{'LPj]9x@$GG/Ȅ+3bJ Em!{̐,tQPnl)s;8nF%nyeWU7S(hnw:q Sxv ѰJjn:gR JR/)U3̭ƫ[_2Y"ȈH`ƳֱΓe%it2 Hu`Ȣy>%; $||FxB)ĜOb Yn$8#Kho!Q4F f՞S}GI]K  hKzEEcE !0E'5lB\!cWJPUFmKL~ bP]'(RVYY)0`PsP썍-|&XzQ@7 Gxy֯ -gSҺ_Y vvj ^vwRAI_mb*ꆩցjĹK&/} Uzc`?'fuF^> N9CnϤ8w[&2:I!]YDk|$"ψ ?8{6p莮6E #OhUҽR3@L{|tL7DʾAw=}2SR@E؆25!fW߽J%z BI:/xkc`2e,TR!⳩RFUYEAQWĝЄ~HںL CA)QDn@Wpg@4(؆ J=PFlCm">kRL#rPnGǬ([cq}p?g,.b 1z'+,wQݐEb{7IaE)DS0[y~~8aE!Ze-Y#j5]dz~T㗉8ٌxtqW7{VqOzHn{(1;@p!2RwiBt%𲌃Ozch3,)GIP³f6^*}ZЁH 4A"62hKs:#|3.qSňuB͘vmj}쮋MPq-FDH| tc Cw"gNoXSĐ_su\d F\=ם,拫Q" kA=; rgnr;bCjc^&JDMYP#"' G|F|pv@gڄg9K7Dis:(nxQA|.NHUJlQxmW:q~#J*@ٵœU2zS-!V~}ѹl_dzotnJ g|7kQs8^T>?CBpAzQjxVн{`G〗"TaoDWtMF,[ wCZ?Ԏ\]+4dKKzuO5 ٯv=:lxTpg]ZSF7׶%x(<<1:l3T\H`dt*p/*%sQ9H˘mH ǬIҝ4 !߶} ̡bMwQekLTrYAO2: ~yO쮯ZSKႛ P :p 8 [O~sq?լhUX LzXs~[lbӈ˓n"'Ģ!kkHkaL*`nC[R$yC$~~) b}eSS:!}ь(n2t r]háv8>L\>dv;ay ]GqYߡp[&{iWh9Ϻ[w$}>{vU/HBnooS'Dt4EЎԩ!l):JSq~r`œ6dHoJu ZIIߺc-D.Eo:Qyn7 ]cϧz*P hl mVv3(FL%Ѡ""@onC7õrA +߽|1qEG ޝT㖾o`DC; t |kplXOlAJ:+ոڏ3"B&i͆=y7ҋ]8)tGG$+КDk#؅FH^(},/\&[uB{zJcv}FL~n=y:f!ߛAxieъ5fPuHd+̐BsOsM8 j?A&yk)1{g͞8G+$cj0|]P-!K V{k}BSO/"Ƴٌ }*9ND%_?TBȚLN@LԩYiC3Y0 q"gUv$s(cR~p2S3 M4{뭳'1thhtJ t2"Oe]ۚWf2ڳ!#4,4R$E+%tOi Q>"^ xv}sCA6q]-"}KL= ":MH/39o]2'8# :$yf;EK{WL NkFy֛*)N]-7V.Y'%9m( RdLʈ6-^?H$s}T^ֆ` O'#:댐B񵪀mM"-BSDuQ$6y=͑-]5d$~h$g:b-7cP UH_3yр<:xlݭ^$Ӏ{}G6ʒ/)Gهkς0! +>MUi7NFu~lTF"Fl wS:d젧U=!S:[ٟAu{xCOUݣ; =UD`¶[D#%gW/~h9#gc6  nv[^: mu_>;vb1m1.[FahU[0mfp_LmPMf"Z`|ݚu!ahqhќP0S;_NزD^3ϒN4 ^AlX㡯4t4,"!ugg|Yh{9W9c0f~3z z ;n| ^&0\NLzpÌ$g+>*@Ő(]JW2\!I@3IuPA>5j(cؒu4|ܬ& QUa넘O]9Q~XԹg5q7 ½E3ydkupWTf8d؞Z\6/)|ڌE]! J['WXjr>\|SdW"kX0Ft FnfJTCVhl0]iCҠe6Shx($閭h]eU1uut ԰ˉxm@u "on4^ B~nx\m'W̫[͠JrKL~cRh>hZjf0%- $S.zgNrLf3Vzf3V 6$(?c|2#($F!JDCpb,,]%Z8,;3NSZ+ )c "M_i'*ޔ51Qַڍ?r}{dD!s Ab;dS]>{O(5D@;.P殂z~B;F/@s:ѐ'e),m|a>Q=n4󼙇QicA{vQ:7Z=YSK,ПHr ma7[LK%K]+ 2Q%"/eˀ ]ĺhȠVTl%K:Ik76#W3j#TCWNl_ 7*}N(D8Ua [[]/9gjWW7VWVduݾm;wl>tOݴ&Ounvv4 ;׹wg{{x}!j%;gҳɃ h1&(ϠWsWP7eP~ҌGtDIk"Q"s<P3ka5E)o%H-{ϿlO= O_߃tT_Tmo_nwOoK;M;nv;v{GTȌ燄<_FBx.xAe(O\ͳKd{?}5a12>G@ub,, U$M H\svyeHϑdCHq$DhHwRDtZ@>cJsC(<6tDo}u^4Qj>Hd-4 EYGe*D$W{[[{[{+d08Vu'a(S?X֢X܎v:C־m B5C0-d;s*6[ȪXOUnR$!49 8y [bD/  -oCʓ0k5fd%P5^tQ%tEAb;d^+@7c6  c 34.sU*nyb{UHְS՘ KֺV4X:;"_9$<{La@:iVY;c QqiݕJқ)b vj^Pt 'D:^s &,0wQӽp!Q%:]0Y{Њ&ijM={_uq.9ǵ6/['Dj`:8 4SqXDB dѻD^F T0o3svjиy8]Acy.*\湍ԛ;5YݘEPcAћr%Own6JTG$ػ ;7 "₫NSu8!kn 2s#LTk׋d.;"I]([Qm!Sбx8}(]U,$q ]՛@/|ո#ڷļ^R 9|5oU,}2u2.>h!8B{le88T$Q\p_"koC I k,olb0"ܲzKG5Q6#gBtƔ8G:Cځ[uF"R  A,d{Ʒ81R,CHu z:MF#)m98A|CwOtݢBNYjQ.> 7Ա;rC9 6/k@B|Dm\ӺQÓ3U#< Ϻ# Q @ 1CdQcq&:kzջh>7k Edo5hx b?ݪzܮ_K{taWHI,^1B(^,HWCw_DW|VmM~1_HA]_̛Gwg=fd331}DcgOܔMH]M)3 Bs,IJ_2Łi8}_ϋUA];Ƴ^U:e7a_gwV Nۈ״ԣY{iK s-F,,NʸiDXL:E8MUJ.'4pfX ŰOF3D~`N:qpV'qTra'f>jWBvmounw6(&dUSRVUeAsN.ic@ϲcbL~?wΐf TҒ4@Bsww%U<}V}AQ,M'i>:m!S~*{Rb=g2;*( CEvcCSNz H"z +0Mizjw)ZbbY%c8,_&)ρߤATk9LM>t jgqPxof%'O" Zߚrdi (ܖh i5}N.E$Q0 λ3ܛ@aK4ԙȮ?::.BTHT20"Q~Q,=zu]a W@tD!k!'%`1aA}@Uqx*8N &b zdJϧ>T(vnX{ţ>JOT>8*|ڣZU8^~w9r l4)D'P_5{J֐P$կh݁'VHx6*9;BbO >#Tl0Q96>-Uk"(f?!ZLоKZ $>Hk2*OO 1YyD.\' ko6>Ixh #v\1Pg}yO(Gl~/Vesţ@q uP_!@?1.+>z]Kڗ_F3ўhn 7f`:GwɎ*ͧfT]𬗍M:O^J C#4MF>FrcƱjUÞ3E}$>UeUHabĉ(BN7_SxX=u8'Da H9t#5%YrG,42S[nD~K^yc!|&T{̀t*#CKS3r@:3ixz. erC!½VD!E.j3tjGCFHcdAwuyF W@$@O1& ؁@/8L@!<>ka#1:Bpz58, ǓVTDEzWUoc?mc]!,Gm[yR_P=N Afa-zkGVAa!t)Y(lqF^oB.ʵ۱[RPv2n'4p\ 5cu%TmCj#>@sSXfMynoa11+m.Ҹ jgkMSZ yFeS7 ~ ijZ,SghPvL!BFcWb[z(̣uvsv7b)%Eok5mjxXV ?qNwQ=t^ɵ'(3'C:@Ѥ>E3Ofm"R?D }w <ۓM=ͽݪoNJiItvUlc zt }Zg@|Am%w[D{dѽ!: 'Gsԅ'R];琟@XwucDcFhe+,&RJG 4Uԫ ;Uom6iwxW\G ֙XHB & 1:Q5ڵk^3qz6BI1dWQQ֮y٪]BJ|>bٝWaQuXuQNPw p4 P̂NiFt6(ҪK?m1QM;">]L5J^c@pT0w]8eWj!@xwLVZQAv c=QۅRy,$7؟#PWcUH}%^u"%H0@uu>m+Xl #z'bOyxD"E>iY(; 3!eGaBd1ک;{sGc~| MQx7J71߻95V*?xtNj9oxx=X'vc[ #0Hw8xI Y:F]'HLpX'p>8T^*H֕0`J6WTu!|U&B=SM-qZKQ(ϪE ;@3-=~ʮQOsA5Vf k_0ֵ@T aHZ= ?E w@M־l &4 z?@|Qa9$p^H־nܺ#.N6KlX R u_L}bwY\3ao1A@@S+Ehdn U~@I\^˲KK)SDj@]%6:4^s# yV#r\?d100GLB]D~j~H[D3utIf!nk#N>Gx?Tw,$Nu|(._O!EZ-V5I:;eӔxGo]66D$ J@㺽%ixM.({xz#NW4YgOZkZ\v-Z ]2B@c纒<}\yB 7J*mYF[M'E,J C:C}ߊ*潯DrPK`Fm]cqHi|}|ze/4);Rm^gYGꆂ0zm7vBq *.M0;1I)+iݩ( _ZfM^b!рXiryB#k5ֈC風纉 aБ&(kT}]\˂#rTU򛏅Ds9D>`u Bz3-GʢwHR>N[ת;",0"]BC!͝keG]NrG>d.S:X8E %}1s=H"ٽIv'd&78Z +(")1X)@,P|LU-Xt{ut{aS5VWO5ȟ77^yq1t^x7:oq6nǃ5s |U]XYYXiV6V,/HΑZtΑ֡$]o(뇯[tڭVsպi}`nl7n;x,;:?h\颳X }g.1ѝ*zۺDQ( h3`4s.ĮBo0cKypxV,iHƽiqMw=IFVsy#YMVvVVwjgy\lw:VY#I(iɡ֑:B=You#5 _{HYWN9<3Pв3x` 0+`6tnMAP@%jRR*l@7H!htv )@e@dY7qF| m@m#ڈ՝UkHm =2r*Cgg͠O Ƣ, :mه;T3a۴f@)餖{)M^S5  0D'D/EgDNL6Pk[8y?~CGR#>]eZ]o)LX+BP.簂"pcOi&;-*)Ag~+t=שŲO!utimp;}d <"y]s1D):{\(,:@@ V2]RlB*9UbZºEdKǍ\4P(c.m<"t Ol ٗB@cw|(8z&%7o\]}?:;a8)bvUZm*C!? oPWw@go5O/G}ZXY堶kCew 0H3O[UHathsacE?qmp HpJvf)YaCg6HF8nܡ y۔P*(V*t5 BP[UtXޅΎ1G%T?9-x tvO< vyU-:+"UȪ,upa b3rZ zvx[nynߢ8CT8gsĖ/eڷA-H`͜['\O2\ De@ 5zjgW]bhT) <؇ eK \k߆$'ə KCw:Gv~rs#-JM#.{EMLeT€#'ž/X(ѤP(^*,&b>>EZU~#mQH2*>nKX\=A.) *] 诌.T${rZbi ѧ̑b> |!\O/Ưk&X!vgpyZ}j'\? g+*DLi3E a͘:'`` AּGjS W *z ּ kW1.O_^H˶p/)*d":{HFpq  ]'8lh3?t~ m@?C*L猖x^ީg#~f+Lޫ$@gS3{gwI UpxB+v>]~Xi@[;,Pi-kROJ/FDAuv*|u3uNJu(wo8AXUFtYmP [oUiT}HaD2ĉ8 #w&8߭7q\~ Lp+,\Ihb{=b/rPCǠ '>4/zŶ:@D:6mt}P,[(JP{DqQVeo)eQ3 l0ZdUНRTe͐D do;; $[uLiĤl4hYCV&rDN/yAl!Gm٫1żT_m,w&E%e.Sf(RNDcFm!uͨ[|M+F {dY/(%j'jNg^NϟFg_̒O8Ag_qdzkj,1rii:y:#g+Pڢ< 5yX}ބ>Q]2ϕRǂȲ⮸ؾԮδfCﰜ.l/oU4mkpy!vjoHQ! Vq  ztdl@Z6e*=v3Hp쳢x=,Uer?iapze@-K<1nb#n S&Sww&{n\X| m 5?]^S ~#QK8ȣOҚ$$xaQO/O 4:;ls{4pI[z.^ă FWA prȂxɾ]>I^~궟zDY?^JZA= ~>{]zV*!ڃ!u" tJV 7R1FuNkCŲk!-[nB(7S'ϙx=:R&'ܞĥZdVk͑GObuxN]<"C*sGRZ %ᵉwF6SQϡP$ᐾWw+Ӓ {Y-GteWINS'sR]WнzZG%g( ,U9F3̹ $] $9x4raA;?ɥ!-5<ԚqjI. kp/~ W47Ƴk¥ĒRDNIAysH\&/#sUx+ iGd'iܥ{V- Q,NTld vV³mlt:-}:7]/ENnyxY˃ǛxHҭ}ǚ)\UiBO&AIh:RG­ٻ\H#+ݪMI^i10_%Hj#e#]]Wx)J@0E>6ST ySB3{8+‹u"V Fß iF|~gS:v"yWn+vB}R .V:59ɞL9Ol ccAh\LdD SSe-BZ*$Y'$]5B׍y7^ }ÆFc϶M)ȮHs qBas]Wd/+.@]Ϡr$4j&]dTI8?rk"aB'Rx ?cͰDA%(ꯁhqZTTKڡRQa=lV=S_6o2V<SEgGQ'Y5F ?a1)Jn (nUu/SqWBm1e;BR*_"ʷ7å`^OD 5Y'!mA1`nAgJo<)~x$Ą'W'݆%1 xߥ*DgF@Ra>gԌAah䱞 :؅ y 1T_ۛe3[}]/jeݶ9)ÃQj>kFv^/1JB9=nYz#7JD2O{3$i@ώzPXsu<>YjV½`B4-du'`(hrE{-:muik+|]-O]j- $.+ oB\Bs @6#EyGn-o$PaeT"h&M..~xߛG#w#r= gն'˕4nT}M19ިb~18}c MP4uOt5A^VV6(RӊƁ0>} VR vY *pS {ڰN=:5{TeeZYO年OO"1-[Zt]+zT$7RW# T T"f$:k_"D5-W QdO1@h%cz%Z]O隡ƅG&֛!|SF'ֻLLyTdO?:o2ț1gt ĎhmmQY " [o a. !zg*uOLF#Mg>NqVxNs5YV[7۠ c{^n~e 1*-r=,U?i4:CDh#ڨ)9bP$ddQ0]FL dP3'*(}֨+:p 1DTo}FzT\Wi'#,^)B]d w[GtlSӮ;@6:S{d{`( Nv7WWn^m1]'r)^OG~Trh/SwΛ,T؇˴cE<'R!"< "'j Z1xY+L$FxG^$:{\+) G6ܖ=n7a8O//U(kB $gsdfkdY0&;-Km0NWzYG̒կ..SEо3%]KF7yė; ?v' 5'2IqT,1|Yo ^yt^~=/n2 r e W= xA8EEB9IDuJE-!ɆB%Ù(@r W6 =w93,P$EftRiDSnk$nx=-p7(v Z!ohBQLԷ Qiws]f{i,y>nѪׅ&QA E6t^.`|f_D.x#7*j1T[|~!QLx oFRP9t;bV2U@W) ph.ç>v3Ԇ@ݧvuX5p?U^߷BC"͝{]GyolZ)ۇKDˮVrffJ@LČQžVݚbmHRR  ҽ=inI zHQ E<[c>Y:}e -qkăF;K{`gsі# қ%g2B($#}L޷nj77oANJkb= a9rNh;5xq yQ8.pV48puQE"_gNB$DnU~MLᵿ4%"!RsK$qty%O4qwH )hm(7v4[T2ko aec Kns<2 Nނє*)-8 CfZwJԼwO|5pz.^;ۏn,M%{;|9Kە"2ۉىkܼ#Bhe~yۯ-5= h*S$ĥ N ՞NڥRr'Fш*1(b+IM!VE܏Q]Sԅyrޞd[k=;HϠ(Hmg2z'Iw$5tRDbFv;0 4jfV햒@$x }ԙPyVMJ_'#A1 #NDhQkU0>EoOUJwZ#kMo)?FO>U27zdKE`i+O;$X!F)Ǜ)|]oGGh C ͠mFJqJs:}N0 ^(n&iYr3P_ڡc.^;fcAL0 XG2HHk[H-+6ƄW2f2vً< x9&W^lץ*)ٴ'(JG%ծF*%SuDj㵱Q$މ@X6zSr(I7Ի:1wv"i*!r{͠*\Oi<㵇+\#AXXHXJ6ykڇ+\=~#O*\JTKI?7fBc=0R,cPGvv"GCڝLQ$"}{~#IG-KB 6o(}8KjnD$)W^ΜT`Eн*nJe"J `$PѬ z6u}Ԯ'=0Nu2U Q{* ^eQ%gt&xl8`&`(Pڟ_><Ă=0*I-7| v W¾ʅͽ@DCXꞻҩZ!GjLQًtjZqNFD؎*P,iQx5PNyHȤڽ}Etm'VViGqpzvjDXj `'tf<(uFs %Wt&[M*a߆L<\kkVmME]6}SJkSP(vJrPKDH͡HGW=Arv8PT*RW'{Bb5}g!On@ c}n/u2+*!QO)'oo}#80 SJMyug44?{uɂRMBg,ce<R g3~ØpIPX!De@H{h|YvĊx1}^2t<$T.˻ l%.bB t>dH+xo bleMC8&W+;ڊUPѺuG :֘,Q5P+El]R!ʋ]xKƑ,RE} uhQ"+T(u*rarGv"(RXiG<Ѣ:!OIe'l:!G+;WEG E]9I XNJ?j b2 Pok1y XkP*8ȼޘ6 Nh2ͅgXџyn.:s Z2RBp7Wqk:"O–?ZꄘI  _)HHz_ #=Ms5 3xe"SR[ˆCYV]!ZpkpbO8YÂfͱdr'&Don݄Y+CLZ͙<1]4v ?JV4v%Q8mA!wuHl: %*Ѧ VDt&zCFBzUw* o&ΨߟE("c6qF幈P`ʉղ&"% Ư-c[{uZZnAu IU /Z%~dC"iýUR/eJXޱ CZuh I\LAMD7gKwFފ׾eYySϚ\)u"MDQY@K2ލ׾ĝ8a"8 g|6Gx S)"v#)|PպmLOiT1m#ɄyzE޵K2 4Jl;ǘ3xcv->k cWS7 a@ Ϛ3aSHl ¦ݕ2ʋS?ɒ;Pʩ:"KP&ƞ7*['$eL,yVk[,mT8TKk71%bڷZFꝗNHˣV<%()QODhK/^J/ľ6 XU zI^l>?ɧ'ڙ]MtU1x8 /af|kW k4nXП<.yhi~;RRRܑ`vvi@Yݲ`1ǙH_R;9gނg4<( a9S UҤ ⫷xA:P+MI8}ZoA3Du#Ed`UB:@5S]CY Inmi7lFu@P'A&>PR7rBAnAWeQ47@cn=O>ԓS=.NR|DboSx;D:%I>HR$W^Td5̇HboHՒ;Ha(5c D(aR/$t9pA.؀giXdy?E gJBQW\r]r*k@@䳹]Q튓ѷگT;ȨzGWW{r[x8A 5͆ wΗkʨ;=ywS K4o L4qZ[^цA-?GP-D$xB|چUHI@VMXeգ#9v% 3`2̆4ݍ% DE(߭vPPX8 i= u^Yںr!t;x,m.YInx i2 D~Jy醑YÁ!CAXDH&ot^7[!:^Ywww;{B '}c&$oNb/h3ς]J9+%2żyrV!fJQπe*5bU I݁BBH=0`](x YUwA8`%$B*DBZtl ʎ gu\ NL;61I +TkuG:[k5S~VPr \@Ij?&"eTL_n&*nCv^W wK8'&gDU/]vP!M6Wŭ؇4슽8O,5b"tPu循9&9]Z> GԤ 'H0Ҡ8"%[ui<?i=O$ZoȤ?`aul7ڛa|Z"/a l^U(2TѳR(h`w}$uj&)ǴR)Tbz^$P蘌&-K|T"#S1oc!!pIeQү=K6[ײU2 \&X"rn=[J0Cv 7vr,K Y%bA/ ~c i` mGFLt^,,7㵏$js툅t<ѲF, ьOM%zBQ;b:U^?,MѦGd'=Sb/@n37fj3 ^8'쮈A(ֺkt lYwJ;@~jJj$'ax$?hZk5&/{Q*|}kdNx3zp4 e݉>gW d JSLmcz;V-kkvT sfYn"T`q%) 1DQraT:0Acq1'^jXs?I ?֘Ⴃo^Uض` whsKJbzHqtg2pqFz]=#?k3(ѲhɭXQ+v"}Ÿ08^ӹْGkB* TsxT6ň_$dG%daLEG~Nui]ER򝩿jיZj8vZ.:TGfvzl >4dvJ)-;:y`]>j΃yςU:T9`8KY&?(YgҔMtH+cG3dcz<7|Yhce'1e,ƔnYsȄMJ8 s s F]Pvcoj4`Huk^S[SP9.NC|1ňZ7)Y⒵^ޢ -XtNR,c#Ե0^ Rd7>5T ijͨ85RXZo7qgXYG,exEOrd*N Tӝn)B@cUjڡT|*TM}ZHMe~|KA;.LgACd#sQCsN`\8T4;RAЅaMAV5(wQ`Ț"3KM^r7T~4E6zZs Pj !=UʣXVQ\EU#5<~`σBp.f9ݔ6N{DUB%=v1䑘#"!uNޏ׾kTNl(DBh3^da‰r(ң&QIKxp!}wVsВiw>X4:ZV-q.-hSg+Y`TDaSmHINFHpPFF(a JttvAߗZ雹X Nد&8q@#\pvg5gEcJ 6|q~5Ok z?/=b\hmƱO.'\iXklW% 㾻_=>(1}LP F]_buթhP=25%i> JЛ[Rnhb2+$#ƑV7)Mn5vb806J8=]g9©{-[x}-*4oJ@FV+ǖ k(^H{z"zDZ))v Zq{[S 7#G-$>!h>2|x+WBC ͝i$GugW|00=1Y`UyZVwz$,a Z>Aؘa}Ю 8%iw%a> gUfur*AЦ"{^|yq奥_v%,>~/o2/oL=e?"t {'~W,-uwWVVWWduh{7immѠvcnXhp;u{װ}ͱ#Wv;v{ݾas`΁{LoO\[HؓtH+ΐ<EHsfir욣I9Kv1cn(_4]z#J P)PP!$eutAbҷqvoMϋCa#9cϋJm"5j (]Ka븑D7ڿz2O p\ o_ѧvd}a4}.eZhPth;vEx`)b(8ʤ_KUQzɎ*"x:!wfd8Npʡ |Vyfs$$D 'ZNJybЛD]gF"3me"CK& g֮B(Pq@m;R(㠡*-SD)vj$QheI[j{(2+sCMJPQBP1R{ld]%;|%BЁjD4HkײAmP@HtBBhJ7PAt[{خK948Y V/Q ĩ0cr0lKHj%<$#jwWHekP?W'aDͶpbk߯I"o/[s Yc@ h9>bV=;(a}~|eRF ZϧԞQge)ϒyTVqB:DKj>Lҋ*P~F,DYJ4 Kspi+ѫ-Sr,3Ѕ }!Je nk/iΓ!IO Pύoakg. !s*0OKx Ho&[Z!bpUl6gJ7ꡀR-ZavBn^X3Dw '8ByA;egR6ȇ~kjʵE4 !Vj~lu#)ǼAupp.^4p ]Ɵ2-qv +xl@}OF*־P;F-HБyTI7H{Ϟ > A^JRtHi]*|@đ2w/ڗkE&Eueǖ&"NZqLsv.Y MJ"#n'-Y7k3ΘHtBL?XA xϑ´͙fݫ1~CL;Q]L 'XJ4ƴh;lmnl|8_Ŝ3iv5vc1*㈟zʘ6t k 30DwE#`w? [{Wmt;4avKWB m8Iܘ=^[4xHr<.;Wsp?x҂»*}̖4(l4O(\ba{ac 눆qNy1]+U I`k߫7 5#.zX4߱7e"3$`r_BT8!!O cjl)Dj I.g/э2Ӻ<ܥjtE6ʪ~j=RZ7nc!.=ErWy4Ef!YdXldUIZr e*+xDf~'vCրN½6,I!F[RØ}#nŝw0hVթ|hdۚtIԄ' 2'@M orCMfID9j i۴JCu#H=eu by1)Zߍ m(hԞmJ&(D̒$%vT(ola+ը@[iөS~,j"DE,\N/D=D;$D=U(l탵@ Ds/SU!VeȾ2 Y{x$[ c^)@+ ZC #j'ʮhď{Q {.Hy^_TX  WɫôK;4j]g"?fNMd\)CvyFzO3F$G%͟>jS̟> | iIF2) B}îGt?ЀV7sC B x6#? ߷OS#:M_YzVB;f|2$00[@RamdC6JQOwʞ1u?h5aR1moÅ;WpW Knn@d鸢,rD>҂x!4#v/s>c1thnU,  qig(욷}R/Bp)<>0ŏߣGG Q ?cX*W 7V[u k2w”O3$ 9` P*Kv76{*?1"4gZcLkݵMwLi%}_h֛*}xR?I(m+RsSUz G iR&p!j .[HS'])Us9H Ez^$Ji`#JdDΈfxfcb A"76 "}Z pONzy1)f|(>`wu_'ס{Pϳ!{k NH'I G=>Ydf*qc@i9/D+<_} X (&@X$VǏ)ج>Ch)I2 ]~w]GyNi3c\v޴d\ wF\y]ƔսHIōڲzJQnF=ts`$77L<&7 D [{oDʋr {U~ˑ[ts[=5Q' t_AVyg>M7/PL謝pv'rys1xC7ev%H9Ecnk/qe+x;Sq1D-߻a.*RJr{t4{ΰS!^8QXv]eIl;:H_q ߵ-I:ӓvҊS$Lmp)˜JǸQ_& &@=u=+W;?Tͺ[På2xAvk)OС9?2[ ,qR|)v(7WYR'锲H${,(4/ ؚ_5E\UQ83ijQ+ztZcu1NoCvv /5TR^jiG:`k=#JA>rc!O!n x(\^PxWBQd`D]Od'M1D÷~ڮE92"Zyfby^:iZ=s_< Di9:C߼MdNy(UTm@k.mgUFjdElv]Bu+<[<(D/5Ԑ.IR޳ܲf.}"8a"sv)Rޒ Iz4aPkռM>,CJq˔*jG/q5B<::U%:'=ũEIKTdgŸNkBu' %tksmMqጦ?kjz2t'DU5!4NG))uDx^eٞJy 19_y'[(*H6ѪS#l!_^:;-"}J),9;]TS8a/{$Q,QɇrGC ͏̪7꼍_k8Aq B:[{K7dI&EZ,|'|oKr<n2y k߅ATtfj88WN M qdCVWby%HhU0Te8JŃs4FY`ABN&~hZ\m6چj! I_͋rE 'Rl46ܾe^[rG90zƞ/h8<<갌kk\:HPq]g@9(VtZC: X-XaiGsGTY,U{/H0P+Y놐4Db Ĥ$u!0|Q?ҝT/fiV~^ >־Tn+B-ӸNu!e5}$D7B?Sj0Af\,Yt#JI,<țA;-7=Ua{Ϯwm qHd5/3'*'Z5ԹPK'a0q́ҋFT؞%vMBo*Ϝ[ȸG0o}kEV柷̛ysd#A(!az}ӧ%]+vԎ0]De+nw`cEۻmYG=EˬˬV}.U-Õ\}n V\׼lk]Me'/"hf;lViEr;`:9,3TvJIGY*sg%LE*{B k FyUYK :kb{nxQdb lN U*6h42r&S.5P.CJp/> *;C^O=Lpԥt/վn׎H#$Ewm'ޒq,$GDGDȐDGYoPُ]8hg+JZ33QRbGLeӍxu粎#IhWb>WEG"?t_ &W4;idz[ f:Lq  钃ݙ~_Be}P">>(< H#dq&$1#+V%ә 0br.Cj9Z4`\GFIE2u=AQq4\r5W,-jT,Oi&Jv(MqA*vn" DRUT771J %ǃQ;1Rp|oh=5/Tv6Wb8 mjl+*na[9[rv@?wx8fą|hPi:/p}JC O^e1ۿ*sN>N$}(@Cup\a7(:?,EdO=;kW@E][M/f[xmT=1R,v'h ZLoh39Bݵf.-APgZޱхmDd 'HsUӆU;ým0>u$nPwQ?ꗙ,jf~'/U8Fڲ=*z"kHU@t&ilznu(/ڃ̠ӋT ,śtuLI"KI+OȪZNfT,h)Ddq2 Vط̌ph($ܤzԢ!+VjG$6(j{v<Ԗn ]&߅|!-B=ՐuepR#J .E@l^Lp٥s,lSa;GSQ_A[D, #%@:er~]ɱRqU7,dzST56ȅ}^3+]WT<N9jJZb܊:߱:Dj@xL2~V>5n#'9IP7DaIyq92PװPv\h%sxox0]Zӎd h&sCJWhJ\B*%ĨHB%td0&g !&J mk_TrZʺځ.N5IoUg qid'T7qV=Ff ۬]_M!u}~~+q/cꦰجn[YdxA17u+ WFZ)*ӃdcSL{>+Piqz)#*+3!n*R7>8ɺ,  TռQ*찵u-H%OKy dhƠVvKLWU4]fJT#kAMM-`KPB.k9DV>e>\`h #vmXQ׵,\)\#Ũ[yaԸ6=_(}S㏋ٶ zavhϪW?KMR ykDj'?Ƹ Bl-\ 9Sp\̉2u*{@s1YyUa.񜢬7vʌ/i͢¶1& }wI GAm_ld3~eOI&! ryt5gXq8g:&S3,VPțTAMQ˱M C~c6@J]C@2TOţ. j')k4ь $v#,Z8>T9Ttm%SݓXYűxkz k} l0)aC@Lؠk7gx@U=̐**SouJ0  1v.2V}4ۚa%n0hhu!iS|J 6 W-gt$0[11VckV:0u(j"TNtPZ:[l=K[4-ؐ6ptF,F]1*{~lywX0V]lL%\Y[3Wj}[rZ(.70G7E7-TӐ? jS;L3E# je}= D堄lʴfZ)\Ix8Ldwp] 1 {'ShSڧ{r 01/΅NESXĖFB.DcsyO&5/I Z l䂢lۺ> Yjɻ?Q.z#˴u=ݦ '`Al ׫:,kDZ[ǖ73r>Fe?yî33(ޮ[$Էxpeb\(1Y2@{TLWߦ? >I"4 !xRW${Y?<Z7ʵ3 { !/=Vhtk eE[U6Jy."k: MT=$#Olv%'rpm@]|19b y"Ӽi&63G*q;u9u#\ī*m;pHUc#X1^Me- rC۞4HSC*vs{3cRCBz*5IP>[Sɩ6%U$0tVLj~ (.V٤ٳ)i-"ʒ:RYSq];@izfaOw)K.Yn~SzE>ON황"" aBSYhU!P5É&Oa99:rxM:ȍhZzYZL]*v}S&NAZ03~UT"[^NRg~Sw%dԴR%E|k0}]'. z%'jM!E*{T?wB؅%<$ߗq}&wy@Ig'r\z3HQi>2JSQk頟j7Qoouמmʢ H3a{ 3pLϰ;($DzPW${b.N+,p1!.B,dZJֆ,"{3l*%敕NX-kA=Ǯer+هb PO^>#( n^ZqEػ{pQb*9&LUU1Ϗe.;K=3(/.t#4ņ,=T}},J~]XbeC U&dx.2m"@DlVŪ ~Ab ֕:F`1#SNp.w8v^[IիONFߴ~zz Llv̠9klT0 h7gn|Qz&Å0%zzi#F "EyU@| GWUʣ\ 䜕RrNqz`lOO7?)3bc3CRceHg.!}"2n *N~,جq$,9j k Gvn҉h Z-ܰVGJF_ /Uj]"kk@?/]Q%i6פL !VV=96WɐQ xd"ţQfQ_3-]<9p(VboyiWa1Fv:%xҿ1f%JgjSWttU 9LHS&'Y$s,߂Q6w;aUP3e 7ܡ0djX(鎨KLih ) QS{^7AtL#F=t'`v܈:Z4,UQ|"vҴtR S[`zԈK>_]bJ-uVQ1TBwgm*P2x룙ev\ݍ~ܧJIw| {#!%*{L0 A7Ά*#yESZ*=f[޲hy`so:!¨כ檯&6<S(s1 er@b~4g<:os|B{,w٨{&9,8]P{ Pl:CHTq2 ȑcIJ8̲T=}7J܁ PsrE}jXvs$C!UBz]T5](+SS)IM]5!Ʌϴ<)= ӂ̴\]QрZKKn*vV=qbVeހ^<1r>zr0ed H:3ZPQ`*Ѩ 9˻4>|`H ނaNBsVXh^MY5سm=`#]31+Jl. ugxb a]1|U9k J ֕BIjFW y<ר3vjQ)Y-b{OLowh'MQhX;Gy:Q/JsjDd1Jj]Fe= +Q YC i"` ۦ \QKb>#jb= JڠX[dWu%`-VU-5 :JaT2&͓*'R^ D%U{(~OVߓ*Q;gP[KIBJI ({[\ -dZؕJD q^g\+_+T>T@a@9x~-`eټNu+i 7tD'*XE.P0EYmj)qST[9v(#v݂WhI_MBQS~UMS'Cq@M)`]ڛp@ g%,ӺσG@LHe_ބ&ufƔlI}|wە3yLs['~AխTv~TLsN j٬] *;_$B@H$s@!-2UT[8X.d+qKȊٰ?ufS\b:Qԗ&WV[[|^ ث` ӺqV ?Rߢ2K*/AP+jeŠZIG`WH~ʈvКDĸ^sũBә IM ˻>j/4|y>5R';/3>U fTʅ#CTsލS!=85i1O !eGytvCVvUzSl?ǺL{g-@wY64:y-Zn/oR c\SDdNc4PϦ$juDv8RjcO-(aٙA3 Q'bE ^Heվ\ xeY|5,;TxHUşcs|#2;&5H KP٪cDW)<$3cR3f)< jQ{iI|ޒw3l)BC%՝ ,WU_P 3ev{oY_l@&%b53aT@X\!¢F 1 EE Vs{t ANȟ{ι{!)IO^J'%N|ɗOg=qɾN M _>pMwA|~>@=nۑWGVsmȊ;+y_SW|z{ΉEމEމ^oRۗ^.t_ݹtElHnO_q 0ݹfds^&;dғLc2I^ML;DҖUYSeo5o,rݨn {_UN51eO;`z)B0ۑZ ڇ*ĆCSu$q~dwVRUV G2Gy&S*YI#Nֹ@^Kfavh/,d lL]"gڕ^>9W:*p)FOt.:nwKN\z] <{E@|QDw,{ `!aM 5u'󾐅[wllH |ܲ.9B]1| YutaH{!mr ~@ Ӑs'v;oxj.bP5yQ 6O^̐]H4w4^\Izy|CQ0d@:U4V[[4%P6,JgyG5l^:hHҷ=5F ֠Ħ8Ob9͔t(R^i,+MjgKSIIP>6=1ȁ AjD#K踬: 1 Fc& #Ulz:WUE=SڕcKe}Ln؁>;BIrgk\KEQ;aWд(Bn(m/XXuZ{Xckײ}Scء@A\uj2nnh͞vjz|ˀABڅ;1*5X_XC_a{?lXVFdGjCKJ$B%Oo&!Ӊ0 34tz;98ϾbfCm!BdmJp5W7"e.]eNZ|-I.>-Dd jyKBi꼩=iEm6E[TvH;\;}ӳ٫y >f?g:82n7yyjʛ/_lY Rg pB:4{(uG5Zؐ&X:VsGV$f]_ە k9yS9p r#VahikY'X'Dvs8.R}4JVbx̅stl>#Y'Ch)BQU{W*h{Z첟g_ Q^~4JcrОR &̅X*N>#FsN€+H\~@x]}n3:{wq? f_kcEg7כ݈Gt7g(UOmp5̢X۩NxAQ:/65O7qz5ÜDkdI7ѓ8W0ڷѾItiл,`lOt|d@PI39oJ+y!x[iM%zu>%`tOX!|./eg蚥fiqbZZ1x!^>gj#o%gFzUv2!hcq@?7:pkF2*pftJPE[+k [tU#Fqv˱lE%rt90o۲A%pUPi[ R3>7I$ݹyEggs\+|t {Է7$izڲXUuȲ2zlX ֝a>KK™.d$b}s۠$M]5ey[BVUZfp!K]>DZ%$AkNryWY֞q=" љQ6mes }$QM8w`@Z_ G嚲PTEE,)٪Q홞9H{/$q4x ^(%ϖE H4; .r^c!ϛ@䋖HuC3 I^oI:غODͫӅt;:H^Mҗw'$DG,gH gDbE2262@yVW?PM"@& *7ZI$Ȳ&)-hR:~d+$eO N&G6ٝLهs93}D"Ė .|, Y~"뫎G.X5H˖aR0Np!}d?- Sj-eC^ 2fF҃@s{Y$\Aݺb7&l1V*Aj,ҟ -Av\U LZHM @9MLZ~"^ܛ?"LDg%$&yX8\+Cwbmn88qb?eTNlv3uZ^ !O~ d'B~&G5Es9eBH M9<#D0~RY]MR!n$d¿m@CRťjϪ}"m͔~d9a}k@{\*8^'n2."*{&//.%R:Ld!"cbFj8_ Y{Sם e.߿[DlVK6Opמ+iUOGpcKO"TxSP[VSL Bz[\Jz\n$-=L.4TC.dD٫E|"D&fk^]@k! Fiq7ݑ)zȆ"T\zꡲvX>WP L9Xww9M"H.ۅFډ /[g;Gí!e7FHG6ҹ6n!#Rԓ3Wg^C9/4 ,skBE_Eڸ^<2HyzȮA2u680 ޲"ґ%B`S¡ʪJ9UY߆/JZeY_Yaeӻ3d7wxD|yb9,sXfh`l Rޭ~^Hd`:Rpjԁ(v "&\L*7ztY"7d"{׍~d-eYDvB2ʒcVq}"erJe ^jڪ*ldYM>^#DS$ rʪ]{R@$GwRmiwD&R %g<ҕ׀F2wTin_8jo"=]:JiNe"L80MTa(QtVMنR`g&n(7 ,?,+FʙJ.S  ݝS?#iNndZh4%[Cʾn?Arؙ>뤙@QGu$c'x\g}Є(Eni6Eքc$4S٬mMQϯ.șׇxkHW$1ҝ {d|6Ba&ӏMp;+r DrKRٸ3-QT.'g/~ d Q}OlNP*"C9 P&4bDw#2tCj78.QWi BOCNd !Dd$H4DR{S?.!}Z~zѲjυ#V+ZQ2bw: NYSpzv#.RռOxg%dW;Qz `ph}H{Pn[|*'>SEAAUQ@>x xM#V351]0VX3uӛ:BكB]73#>X(.Ud/.>RS NɌr'vVsMHLu ]`Ylaj#}Jd$J&a72-r%0X*.$1nA23oTPoD^o$QT卑ǸS#xŧiJ_-*`'VsuacXi ta3\:C.9ͮ5Aş~:2vBYJ!ւqآ~9I_ub٥"H Sx4qc\HB{|$6P*8գ-ُ P9^ETjFF [\>\v鎱.\UE,IHK]<3%*L6±~fye!X b] Aghk*~zooINH8ae{ 7cQ$:>PEt},ýebaר`qP:T4`6֚,TMḈ QjAё5'犺B]vJIY?U[ Ӄ{ap=UO^Z5^m0La̋auI. {zGlノS٫s:-Ztpxo_Oe1KB&dkGA;0]Ĝ'L?O35u||ÿ!G@034.e}C Jd %Yg5 ӈ,|Y%iع oMSp\=&lCY)Vyr >M_هDHk8,Fii̞2ow.\iV5h'3g+.O#-l'Y86\RKg` 4߸D:]ا²~otJl`aYTT OA؍ 5/`@vՃ^\YN\=U9kUM: 39lbDjfM/|rŞ5F;[ԋbolS)U%^ AOM)ꇮ}dK$7yZìhԅtד9o?;胱ãBfg^㑅HJ]Hru2H>+dlؖ*'& O >_W,s7IfG)M7=Wz2t97]!pDyA]#\&P$}ڀ5b$׍Y- J*5n4Ӈ׮ `-~ش$M%CEpoEhٖ,bs$C@UB1LL%R' }"h<)'eʫ*|X_0*16U_5Sb%qq T".G!yYW1H^]Ha;-ޢ|dw P90dCyuB]bnPXP0 ~ ~(EjT7>5 3E[oMֈ^¥$!wNpzޞ%6(: "}Nҟ>I5dQaeiдOŶq"v=Tr$ud'HrMH` À+MZY`%WDc6ΡjըxH {ZlfE\I;W->R?IRl}J} {%N6װX(5s*Vn0~NO)GlR{vlq}s`yF=1D-l48[Gm4!7DܟA[C!3 jnC5EJIO mD4mI(jMhF\W:R2{W@D2!Ȅ,bعL[HϨ'˅pR_VpnҎІRv9>#V3XJ;k'ơ2]'?wjm'M-#1~}VӦ0{g7Dy]0u'|`Q)lvw 6z@^/̵:6"-?Ei"*n"du4# ZAd=UQ@%:qGPZM*s*zF 6tlD5DqI`x4Y stzҩſ ..I%?!]v ?̖Maȯ6h[>.YFC}'(TS4t%m'qA,ѥ'89. ʋs)@v3?ʺnV&,۵3Dzw=oQZ3qY_z@#mBC ͝[dGy{w-%d%5I:SUx1f}a{gmv $lPK!@C0 \%^^{18(W)"r#Wo8xoA=B-Ņw9/##7]ѮsӸXnVgcչmz^08[Ov;m8ON N['{`8޹?s{ȝS3O^7<3AԸʱ\$aqP o!|sfsD6/oCB o6E6%,%跏~a r0OE򧋀\05C^ Jh~h>N &37iA4 1͹%͵0 ZgIYlW9Fi.HW╎`](>Ha7'M0Ni+6șgIJs1m1m *"Q>m]l;vkߣTR][J7ayԄ/AuX>}mI‹t@tL q]"1ƱC34EVm2{~B Q99 ƓQMFU T!zMcTc؉|h:QĈ"b:D fk|c@*y,Ī ה$j%DDG0V1bR$;&{B$v!x;NϿRBx[S%=&w3%׭&vẫ 2AXMv9g~ Xz;`]ΔWҨ6#Oc(=Vե /+ Wr~Jȥ" r ,ߍ@6o~F_xĐG;|7iѰqLO.j=<*ՇbA㟡0{Jb5;_þ*̼oOv 3-m6mՙX!\<gXRݐ4f̮"tMU:Jlo14X2mՊL-BU]":@JQǢX^/}%Ih$Uv+oџ2?Cnݧ}*ha2%9R-v&v|6/gYc@YڡmVofS)3E!Q QZ@tX"2xc&]mGODRU3@ Y} u7!(6=Q0,^5XHz ."N75ZW(w(UBBˈ/[z~վ̀}LCFH^C`އjbcîɯՖkb|ªۓoH<=0;Oic3 RӹdSu1!&]DH/6w45DL=9yYvFɕ{U/jC)޲Nۈؕ[YXn7&Wim{H#g‘hZt$R}VB;HDTPcC UК|'p$Bg\ޤl>TIm$Kk\yC6+oTB:OmiH{qvqX(l^Ǭc~8B\a:xMeḓM8̟e!~:Gz sޕS2=-lQ*z6)D2lR @A6M(Pd޳'5hӒ`&cIetEx }B`Tl*gc޶m#y'# e#+1n,ZRiooDV&#}[_"FnW'3r[4Ng=9ФrMFnWY*ѻVyے~ KM.4#, ^ki˫g.ڽ2Y=X*~`ڮ` |MCY}[x8݄*+Ph\թ[Uw)Qԭ[(G &U ٲeɠ-[s<}XQ8|t蛿ZU]XTp׆>*8T qaOFx*]33.xUeʲ:1OD* ڴEԳŔM BA̮;SBx2laWpWJD:։V'S-Dy"4/ PoWn}6g';Gl0.=d pu}}Sy#,_ }l>a(gsfB;{? &"5H~hٰN~!ϰ*;Hl[v%cM{hisw"nQ;6B7m2Ol%,,Qb*&]YvSYk@+aj|ZSD zqb [7zY&ϣ[hB,ҤLiڢII,/ߥNܰx"Q۞|b"BWOΈ^$u-*gJD&@ ,:|~pFϖ,iz6i$sRN2O PW-Չb5g5jWG`72 ݺuEoni:3IV1R5Ox]w^Wy[;(c"j8H.Ɔ{ԹH8G7_euB%̎u&jGp׌>M6r?DNj.V>?>#<V8vY 8c o*aruS-0"7ppfuM\q'*G$8EA\C/9r]@$~/%%A*h(rt8m3LUs%40HWXJ.$t8׏i]g!T9tHVo+qLiq-"[)"Fn9KѴAQ噫_+bXϸ$%ZLՔi-$ώxcLkC/p-B&^滅pix:of5WImm5{Ъ#k%PNB\ąp/knn.7·w59RmШ6 LN  h ].$+)HOiQ vPx.{- Êg_FC{aS"4Eŭr݄ՂΛЄp&v"ٶh\H76 8ycQMn2j윪[_ŇnO09ކ]d]w)qC0W0#ed 0=-7r6Tgآz 7d޼DJsY ʽR'S5SiKQja[CT,OԵ \A"=;zY9te1e,li';A~~SOpW?8+mؑOMˮ[㍒L,}#9ꄁJ>_** 1(oI|vQB2z^ +y=tTs~3`8gNk]֝Q z`\BQp^Fz οe){$i86p!꒖3R".rTN ɃiTZ(,F$ kQ#FCF%R:i2-Ӓdrߣ /כJmE]!.t3ҼκүO̓ۯh 7ͱfZôI}_ouеvlNKc#+kKxVg'B(jf9a^ϝxs᝹qcE +%AIs´(pP2?8_dYS A 0u5WKj!N,fBc)tNg~7J+xfX!} ).?3*g&_~VK#,5jԱ.ѱ5[kQǏ o5%xpG9+F 2{^9L~Q'/{{?KOb 3DUMߒR oG `-pB /1j'GU伢$ˏN(-w |/zQVxxzM @.u7w;" p9_th\!LVC;Ed uu!^} ts~_;jlYtydNW s?N|760!]%j-8I~#mD397!NP7 $569T)CN5)Y-b4QyƁtm~'z6ޢZO{'jm_l!K۞d&SM}X9p7G4rmu &Шmx}qo/$8qYdږ-{DMn>hAϥ:R&4Ԭie;~MfHrrFyۈ̥ꜲrIƲ3 S`$W9"6Ss QlXpAe?nU]fpCBK}kZPE'cM><z lğ妲F#FnN\h)փIG1NN:O_mlrvUNP]P$@>PQHB0G"І='ONGY@tq ĥ`#g˖)m/M;ڮNE+"TP_+]B-ǩ­E&ZFP x03fJkFN1|#ܵ+(tP>V\gk>*c;Ib8( v\]\ن8 `Вˀ_,}]0| fӆp>B!#2n+>-$.iٳnd:*NӣAlXmg .KQ>ɚt P$7AA-,rE)`A'>'L.cE5Vy#pdFulSaX#M$<["3Rf l:BطtuaHw#W:)PC7FًF\uTK&FB ;J"K bHc:N%/7o]uBgHL=lx+|!faI>rkav xl-n%砧 wwIF:UPt@Ѧ<,]WXu:>]oj7bV=+3"aRPSM%s" e{wиp GiQJN#;i'֑.m>G_Ĥ' u |g>vy\S)qw%k^./4ՃcP h^gR-%/ Zw B0IUe8jK~JAEhҦ5 %7ax1Mi^E;/%a_,!۽Ym+tXS4b MSٽ>e,܁ZU;rpOɿŴn04Ա{ڄ&{GNӲ〝qD[c9Ue|G)Z[_@}3$^H{} *pWxְfKIG+hWDpQ>W|ޡU Z#gUd((ݫYcc7 9a-0eO 41+$4fC?f9dENK(gJX ,l;XPk?dr &c4vKݵR8,UJ{H3q S1m^TKŁψ8iM854BC ͝idU{z,TPH%ʻۼΫW!L%3 Kزm=xBIPe<'# zn=ydw$k~:wsכ;++=ܵc+5'>5t/!gdxcwnvnv>qVu|e{v[k{ݍ틽fwG8y牨?Oz''mD?xwv]3 G?383Uhz薄[&Dph<Ƴy2NtvAd>3!IX'!$HsFmt3 Q#oz늄Ulmbf@燚na0,887*p f.}0XlB+Y;/q,+1*?ck/7b& -x#lWMh <On5X0v`x^B $H qG u&̭a岄0@&('x8(G}3Vd?\2L. b~SVlKlmP9c 6߶j~liDkUlLm0?6ϐmvMN([;W94z.eNs#LA 659V8cgk88O-r8 nX[Yy6 F:b{|CB*m {h3f-G=/-X^־O׊\eV o'IWNOn'cu';Oq~?;z=%͋kѼ]K )ۆ"]mfZ]M\vlS4o`kW4SAt Y(Pp(( WU:Q&?xWnlBG klfwZUZ"-[Œk^ h3c=rn07GLKfomw/nﱨmsfss{sԍIăLo3#F:(H~ws#AYNkἝa 8s27mWD9ak7HHbmD$žW_|R }HePlq+&*|1MVtDqԙ@י8K{2f@SMȍHE][`@8|]-Su 07^e@4!0^@J8GGv*L s&@N kFxVJR+T]Ԡ  CoY؊)!mWt-re&iRG;1O_@cB58lͯAit1Od:qXؼ>MȀ`:kؼTo~W,a(캥a[%a4*o/ju@,*'Y;,Z0Cc-LCLw)_ FU&[3!gL[00Y3igUYfzh853}Zy=08"i &  "*ܜ`._őBy _X0r6ɪs82NsnyW\:&D@Nx2Qnm+DEI=LtRA&LDzQXx[zM&:یf w$XW(︛CИ;3LRwml% ˊ_*ћW? N;W4*/W<5ŇH{LlcZ6MviINHOH?b"a}/֎*#ZPa{NEϾ.ST3 u"rGV֢DtxJFA]gT8`k=# ^Vqv,$QPcuk%"lN" K@۶퓈Vh@&s?dk/6b>|8Ahrcu%qxj3ue%yj[̮NQ(hwl@Px=0:&"6yvI+,S?h꒲jEM_cTى +Pަ)Eni??떎N#FkPž>NCJ lmXefDD֭8PwǨhekOagM5a2z}t?@T8 ?AD¡C0?Bt\%ʏ([hD}4T$&b,K$"L\D5&B$D Bz#[{zHDě FV"T8ByXj`.6,]"HﳵM\R8Glv֚WR4D3twJNAPCUzFIޠ)>E&8)' K80Ěi*}̨>M*JA=zїm"Qa/k F8\eep!2;l&&61Ht `a!g@BuP}ԄzBd{ϝb=ELg'to:7]*L` \> sK;a8~9st0 dž! E oDiVŭXGU,/hXBfR3áHga VmG) I66 @@0#.v[I):>Dj:\4[h( rj9[")my0y~ ՗a۱M^;00c(ډI:M.TﲵwAO=k)(I;0EVp#~Bo`[̄$gǾcBd#ATw66=<\"C($cj\p;^Z.u[JUn"<XC8d5CC ȟn芝whPn@R˴ X )u c^xY:"$H H޲"Is:GV$4yK ѮA~pu 0I =0ɥ]׏[U I &H-+ؚC>*EOYOxn\^ɷ^`BRpK,UmX)Mʭa [6Utd2!  [e ivz&VpxI ڸCQ&,p"خd`0D8Բz_7)O䓅` L6m(et8N `e0W{ { Bs5)7d:^-r !ڷ]SauYhu?/l,QcHhK-H̼?y ciFn<Q x(h2>k6?6Uou &Wp.Aҝ<f BU)0OaԳn?Fc#ʺ9̳o/8Vu~r0 j^k+I IM>h;2\\6(O7 $,bbAGHcxF7~Me^ct0Tw9]Gݨ+2&f*a˖ \PhW4|jX7Jn6 _sQ{Ry*UDC]0YPWt f8I+`gG^ڣu.(bk`1Pha$;7ҁ#%!^9xMi#(8Wk[O~DeOh-ۀ>jd/WЄaP6Κe$C" V1"`\qDa )vJ?[8Sa[Sob`m7U!(u$U)t买cI6$!rԙ9ٗ'B LRɎO#x*;_2u3 @Fjo^e_B(hctVJT'h!Be8l[tW>d:ЩٱtvtV+xcRL9NC̴@V#klw h<񭠅y֗@s,yURFR춂? x|8,u~ 婽*m Ug'e [Bt?!O麠>΀>m"p2%NIkK#KDٿ+/FfghhO>C'FaKWGDn^>GH91Jr+ϑd]QJz6( /?@ܢ8Gj`xi%*4iP8m~gFx;g C=g _.|mPK73VcUcG  Ƒ  rE~mVъPd0NN_x QTJEOV.!*+}|QЙiSLO+MBy-ѲQp.n7k_5%ۧ`8#d>r ǹp>,ff`a^ Yդ|wfz ΀f6,{Mj6>&8T,ҖNu,]6#(*屣Q?_Zy 읆=[g'sn8HfRU,|\,ڦ3eTPh ͏isIp-!nǭɳEsSg%iB)N" Iv('NG\lQۍs<@G!,,&I<{K)WzKm Sao#ן7)70%},,.YUJʋ0jbb.I^&[{4ШEqd"ų6mGs"-HEne#)^w4j^[B=*iG[Bd(^-y8rHbji6 $Fw\_Ta^ya W5ypVp>/xO8`9Xt( 4 xŚYQ_z|P<<ƈ(|;yM@U >GEl@ӵfB"UQa MV(N´W|uc,ͼoB~{D#zMFs݄&@!8+Y4;vpلc9S*,̰c:d%+Y](=U"ugD_WirVN.K_{ hcoaqM)}Z~of~Qr=4K_$DuW~n)p#/nuyC,Tb^GBGu%(pj:5YH;9- zTt`>3UyTSˣA؍EqѪ}Aڪ* *]틎8>a8kcU }|DD0D8:jP;!:xYk IJR4u1BsO>#qkN< uKEZ@VFbdk0tS!-RdQ'֌z"#> 7_&ڷC\Էhn!JgW5SDZfQ)%i N胠g>$Mq!1ohKWWm54\*߀S "5^g 'LBYQLV4SmKQ nW*ltdL7H.b* M) Y_fk6!B3iuax_]ć·4˿!Ac!]t'͉܄ޮ7PQn+a58*ujwywU'Re=K;n1.u֠P|3C 5@Q3\/P"UEV\xC*w[uOrN?Cn(ymcږ>]2)C헞2X+J6[%]{:f\AM`qɉ8XcQ־RbM4 YEN[,-+pvpWjqYs8k.LKoIT_]߬&WByVl$u*_y|Q;'H~uΙYuiA#ڲPDȇ7*,ğ~ R t:N3$brؖ p aqf-wV&B 8,0{;0Ǔa0'W칿_D2!"vI;&R{qWKZWKY0˟+aywVi!Q~DF+℃pC۾w0H'9=q:$|Q IAY0VOO:DrH1S\[YOŞ Sg|> vdBϙ #{j!ׯEݰ[?@G G %;!m@~Bu~Քv x'sE\Q/7^)7$ {6 0̿OAs!a4oQ YhVK͋(LLʴ*0#U1wEv!+w\גO#Qɾ\}.y6TPBKU(Ǒy5%9𔀳P rud?QG:i,$Uމ[.zeD ᓦi[J7>p UHM]:l -,~Ep: Z&5gQ@LF[$ FˋZ"tD!}٣4Ѿ*%%nPX22Wv˪Z|#VGɲY}[yݒqFRRW4ky, RMnF2Jw3vҌg89XɻSGR])ua4|Il<-&{u%i(e o ("!z.]l!vnOs,-uwNz+^ogeu`7o7oApCPlnln޶ܰnMo߅1r#O^*tA:*А?znjByĹϷ #?CotD%$ϱy{+(mS(NFh^(h1 r\Y:) K FttAD|^KϾXeDwyQ/PY6Qpr-ˤ Cy:2P&FHHg%}ăxcFʻs% `:>>Is\"zGn,C?kj<:7;kݵ͕I:|04ɡA|!{sfp|AFψ^ z#ʾ;õ\!gTJ9F'Y-`V{pd Jp.T`=L\x>8t%ʨ!I=' |2osjEz*z 3j'qH=S(\xpS`h)R*uqQ0tQ}{4={T~f󺱤W.&}ل9&!'|_ӳ`h4݂f H4 $o;H$%֜ !q2Uiѳw1vcBfhݸ\psO#fܠиYv!(v$]YZz̄)@$b Hi`'-M5Ue09Xa 5 ȋ1^ $WA .^"+Q[otnaYnOĩzJN#m ޠs<٫MxB MG-GD2LkAgD O?@L}n؍ W5J^@є=9Ӎ&CP7!BqmV2QA'#g߅#k.M@/f8UkYIp01>k%L9L8(aW%A6-5&yz6ρPS0=vw'ը3 Y״gP]4eE:WdcOzKӃğ4m͂ Re$[CQBXts4r{N R^g,-}$)N29i $/4%ExnI49(1Ub<yx5h4r\m6~0uԁ D]ۤl@))R`8ـpj%XRe=P^&qNI$bW(^z'=bE*1@y[һN{}&lDesފAPi#m\ilqA"piI{06xbB  T;m.uD EH\jsہ k0S;] F<'DݙΎzv _d0@,!xyga"GzvQ}!.*5$0*qJW/P+8j7= +H'3u}~FA7Yds 8patLT G.Ex#VgoN~KAT}dwi|~ؤI,ۉV?AQ{Y\P7^<'aDÊUwANB9xvlۃD>[!Gٶ `?NԊyB6y{JSұ9&иmٗ/ExX"/4#NϞi17Z|=h!9Dv[ע0UCL^bå xFbbZi VXW%U{гPMsX׷|UEӳ3`?v'*w2)HUG X7Au h˦q vߧ侣 RDVNRGii~ YH t#ǚp!iE8wH Y&xn |5$FNBͶ -… (>T($PTaRGbaE{Lr<O;Zu+EP]CU]ߣg/  &^+GQ*ESZѳa}];#w& ,;UEz61YtfPQ,+ZwD)z&Vv?tfkTר :&+\Ԃ [+ZpxG)pvI_%"sx{, KT'^񃹈cW>] j"QEds>; |̀$8 )Gہ͑P8^"$EHR*ш &z̕nv:tM(q`?Ӥמy t L cB'C >|/t&| lnWɉ>h$ԕu/[2ylm0d]t}mV尻o-W^ V@ 5 r"^G Z@NXRGy7Y}nxC<=v!bò hZz4@ȁ1$jťw>FKܷ(G7Iu gU.ߜKH.b M`S6BRbkD\8,UT6("}AI w!=Odm0lAba #:K¹\öp̈́1 Je[a hiHPۿӳwp  I)4*ѳ4dZmp\!VP#-2c dG]OQGM~eߺ|mtf8qk/K@vM\ige yntSK BT̛--ږ]ߥgi`d,^jcQ64ܷ|U43'YφlI T'&LlSBQ෢s +Eɋf ':N$bGi%bC3Ёe<w:U]o%#C(o+7î2$K֊(05>Ѹa#!@<"0IEv@"mĞm]s$3px{9-_۵~VcWإtEkKk' 1`keIF?v!y.Lg(*a[F( Rx*Moȇ)WKԷDW-Ԏ=s Y\s#^ 59QGn, Y6tr[-T 8bJF9kq"sB:4't`?0 쨺-ߟ F$^B)oгי0!5n'PyGp%7F4 ڹ? %М0 A Kyjlm4$nS/YU_&-+iמ@P=wg-i a"O|&J"܎Dv{nBX?'Fvm96#?}LJ>g[K_ivȞp .Z:׼Q&[ jk c\ԅ 3&`;o&".PT58ͩ;4U0õ0en<(`z6bOo%_Q(jm1(7| DԷnP NUJǢ1!!+VnP]}n0(K.sM<+U7Cda-V-ށQh#ކGGy4KFpHqV Skx =[u"8DkpÂYIyGk(#a !) ÊUW#|=8ge흢9kSgi9aʩV/=R{=_(I8+q2甄۝bK\U$\W(R\ u n. ӻ4H<3.Wr͛{,iޑ pE\9/D]YI}:[c9s\Nެ1cɺqWƱ0z:4{T\/S@A^{Wr:jczB鮇I]E.:cGD2&?%,G ɖ=Vw- }MfNZ'JJ{+=j])^nwN%O)E[3^"əFzo~fnLcG_L )Ezʨ q |񹮓iR ~\RS2[ Q{[JCJ =-qjGa>`8Zv^D̊gyheUш:V/ ̧g6N,d= )?|L7!"ptͦ\pIqdcup ~H1nC x[ii\?& 7 ǜ6lIގ%-6+t»#[Ըϙ%CnGQ'q;V4uBP+wBI+ߢ;kѰ%+5YnF 1 ]Ecq[o /FyZPy{~~G4REܰl~}/{Lgp~*E9Aיv(/z-ݓ/pSK_g5ArЕ|YV )q6mdìP~1{;e!).GZHS&ؒoWlpv 81 S؀D[[@ť>|=3rMې@6;91ZziSPٴ 8P:+C,0sߊpJfmH00i[̐ᕞ ďZs~}&Y,:?Aܣ 0{NX L{ 'PQ<͙=*ׅJ"oD$r|C5#zAEiMG'S^H+}eSCG=ޮ RhVp2 8CLvr)bpSD@u_,KR<2 #LQk<`ﵠJ%AӊMSѮ=d #ã7o691IXC5PmjG >q5 M0LyxCv^y_>VLy{{ǂ{7ֹ_@b\m anȯr9}cK;D. po{~Z"6U DhhD'9$1uaQZ1 rLa'~9J.}itRiP;1g~SygHaWfᢐR;ae\0 g9"٫5 {qxK\Ή6$5}Ʋ`SYzRd#g?'#gZm{NBZ><_Q/&Y|Ro٪̹N*H7Mq20]g]?ƍk hT^c'Ai֊u Sр2:.N~R|i w8bJ)KAYss/{a6p޹lJe:;R7HżabJG lPA< ߠ|z]hP)4?W@pmLj5P͓D{yINټ?nzωox>aHzf]WAijҵb!3xSaM_;DE4h[^Bnlm0vfJ=3KrdG=dJߝ)X:XbFsK4YwAkÞ`H5U&Hжw\7'/T|àPL~n8LpU$"yc XJ0QhAY4 {ֲ䴡Fg4A ' wTyn&frI;[y7R$ (߀)V$E﷮J@.y> ..Bkz4\ő_c1q<;>d)˭o0{H $2@Ǥ\껜rˀtg߁̀r [($vx{H>cT "R]ŌdsQEIC :mՄߕR6҉S=ogLD,^ࣹ(\ ge9uy/j\xy]MJ:>i'͊= }›rxZ*I5'+/EQ(gRڏ׷{BXMַ:JvuKF-G.?ڷؿl\o߳-gMDC&l:kK닋++[Kk+kzyG.9v/u{ё^x^{Qzw\{oD6.\~Yt1kG_;֟گ)  '8c,,mAu3'ؙ3OZ-H˵ZɎy6gs@@tgӳm`tlZhWwwV+T8ۋKkŝh*xczJ@Y׿ !o[H75n]✖$q,M`qɄ+$L5r#azev'=;Pl˛1#ʅh>GϮAPz$+ 1$wq(O( /puPă= pMneَH6]:wʋг˪6xY>C;Y2 @4L! ls3!mxLH~FPH:>tPPU,Qs+MZ"SI%M졪(K vf,;sQ -D y'={*K&}'Ǚvl*y h ]^,Ev-P>*;^]s]sƓAp"vBe{ D5~նzr!IP\](p-[fckNr.zar] ;LZ#* U@>OώxB yPaH3̙X%ӳ_-Y)#d7kt8 9$ }G$lJI-zZ-^x<,9cM^vF B"b*VҡBVƮH_f-Rѭ-7BI`53=Ձ!J Tݤ[?n QB{u@fIQpWG!Ĺr=wׇ(ϙ%2q "X(hdϙbS4K׫ڨW6RB% 8wqu->K1Ƕgŋ2lMz)Oq}: ϲtٳ>kT1lF쁺>#Φ=R~f, g夆:aVzڬD鳈(.X͈Dv}#7BwBMju`Si m%QX:񦊇c՝.L#լ6V. 8`M0@|Z[\aaYJ'\x$&Y3hYv~<[_J0w``&3vqKeIeL zAFJ)j-EiYbx,V01Io\'}~2[9xC bOQfQֿh:;/3Q- c2 H3V|+x)WVJ[85WW2lWuhlX^ &V&0KU-V0p^ ?:0.яm"û;>;9T,;ʗ*KMBFǤԞG9I!Jě^% H!;A YXpEDc{H u~i`u ) F}kzH.Z3 S_$O w8zvfs: 9ZV9mzk|WDdAFuekFP+kIb=IaBK5]ʈ_zvw's\cix=taJ{%|X$ hSNMJfWFl~HݢUOf<0grs"+;ӥ#er'>! iHU(8j GR qZiS2_W(`@`k FMu"v@={IuN+TRK8X*!nQD}l ck5A ]\b fg7T@ q":4[qPZVKӥ9ƃFUE~Cړ:b(K /#% V1):2%^gRבf"j}: ` !LdqԵTI]+S*݌jp^ZHhd\e*?U40)z}Hz.˒n$ei5C\H>W@y&̪IYIF9̨>p2J&m Q_t= ;͵3-B:|UzLiE,6Q5AT*.Xcd(=xE0Π$Sz›9[8Cs"*itz q+z%Ν.7 -o]9YzmgrB_U+;₹)B K)kaIPG..=]4b`OuQKh`9"3#*g@:8زaS*;Qo# (r}:-lЁcKEE񫎙+AbB %&.b3 @{Vx8i&ȏު4 Jt՜Ͳ =w!H0Ny y%\B_$B[׮WZk)m,qv?ТT߼izxroӳk0ߙŇ2[:0pXa: Q_0?L}W\dc>*#5 mNvW*{ Ch@ CTt^=9̋(̣03[Cu׬7DK8]Ayn&XJuvѦI&H9;]GBӢLc7Q7wy 1YZQ@NgdtwAX!{z|  zp| :Gуo{뉃s_@s'\9^Pt 絤G;6t3GXR(0C&N~<3Տà4yIN9؋)y Y ^N&?Dgrّ͎>LkiP |Gt )R&WU8wѳqȝ NK0c/Te;A'̢I] B\3νgtxF-0`i6g0pEM]9\gWBvL4Vi9 k5Q@MiZ`#\cha;A&^'+ puWÖSHX)ivGek{36 F~^Ʉp<3[Ϧ8-+tbg) )bHРwgLys-ր^HElwjtMJ8o&՚!doSg?8rG45i⯩ rJē|-*+ƓF#Up-6!>m`?Նl#ˮDʃeJ7p+60Mp4>(XFpdNeXGZ80X@$p: )}U2?2pCI=rJBJޢDl !#u +\c`ٹ 1?N"Wx+T^i#Π Ojη1a7$cr56EjQ:l\4R (4rueЁDb$2vp[F$dw!EDDYM&vXpz <|?BH(NҺN´R_P=@Dߥg;Lz+ܼ%t^qOkm i0 UoyFv 1M wdu*ly< fT]hTqB!bk}aP(5p2Jks1dl>I׫*ٻRoj09ErrUz aOTO8)桓n՞Ę}( ʱl8}б34B/SKI,4t 8U+x&mF^ԑ g?g|g0$ۄ61՟HŴ"7!Kh?`eg?83hJgN|=5Of9'a zFQvcv=g&9E: ϔPD@Ű@\Kй5dF&3v~dWj!gbo=֝SE]X5y(TD"LI;UUCJr?n c(kz{;3Nnjda,Xls†`may]<~xEU֝5ܮܮ5=mC\ǕFN{.2z͒YrHazV;xBu3c(iެlgQu܉y(<;Uq'0HoOF;o HFF:k*}AcJ &rЙ yOf"ֽ Y 5F.7q01v} ƅ9'hf,jd\Msv0a8 F?F>[ #P"S]yL 4b#/N@q (Nj$OߡmG4Mr+rq5\-Eu#vPl!"Ң+"ڭOTTsVk.6 qWW\!Νg $߂#7I[B̍ Z?8o4Splҫuppe5p2pKqⷬ"_[(#!<4r,USHIgV+t#{~>C ;V#*';rwU1vmȉLnyorݡgxm۳Iǧ`Ht#[5iGhD:sc HlwJInw[жpw9}Ѥ3&D& %0j86;9̒;Y}}rG9E0M8"-Z(y~8IoXf$u}Av $S5-:'ćز8UkC@I=늒@!ktֳ 05nʽy.ָ1Y8kk<Ri}똣I Y=aD 2 {|Po=YlY7W;sdygA#.N0U zqUhjz. <[RO^$u?sbȺEف CI2_uogV&L"[Xm@ٰxRP|@K`/h:<˅Bp[~4q;KXI6Tѫ0u[fEŒ헹g_Wi 2 y9r??TBCp!͝ydGy{g ѣ4AIM"WU^_{9tt'$! G \i 0QĆC\z&qD@B"!䐜u޼WZ۲kUR+v=vkkz^2M|za:Dy*gOoݺpY,/V:ݍxoooy3u~u;ǺGޱΑw,u{7?O;&N{}sVrhMH=ӊ';џe`*3OЬl@1pbЇ^9LN^*e֏!aLHWA(|EB9>GkJ9e6J p0}"D8Fp&{XkokWrxsVqgw;?}w?p ?`䴾9*vPN^< E'?xMKH !y%G}& !; g4-)#^W * A$VN5AnBZU=&(eb {05n s b}/Q *&z fm{F"́/;GRP <B2uװLf+ά\v:I{ihܽ$z1 {{Ű=qOTj0A/ QD!2.2lbpjP& rN̡.JbbPk/6-ILeML,aMp Ia#897KpQ&tCe88WKwM}=GFd./aشOڮ c7Jyru r؄kd>\{)/W8zFXv zeD>:XVW-A =Hc'+,^ ൗx>wv|0?k;0AAR4.vgL>WJƚH)w&i(=$xAh@t &BmNIh%ݹV럢(Zd:"83v»Sݧ~P RNN4[}ouT]D„@miޫjLoׄpLgN+eLڜbkٖ;?q(x3U#[lsYb(1tφNpQ20"$w(;5z5g'c!,U b3Ώ 65 >B'.8c=2Njr'4hV5F8'I#8ϗ,;1Fy 43g*ҬZ:@w;(k;Lo4Aq|vJ3t=6qU8[f1yr/~ :>)O@\'%U%kI* w8ֈ. ^)F,B tZg$˕Çpn(W=Yp^A&rҙtNvֲ"`QpZ *XR0L@ӳ+t-bWj٩Ԣ g> $:7hHAHʕݞui@zZ-UuB͛`z`Ws{*<}wڢY_E Bz;Mlx^< ]`2%3%lԤ骘d\|rN4\jA8+ vcS'+9(=OJ-kojU Qc(4KD6Lsv2+8p*X\hS$VIRqv8J&?Ӗ"gq( Ӥ`O쭺(1 }=(@ U|[S% y<Лz^ҵ6%: t17"ZW#v o+4oZ *x@h.PtA)W!}ϨB>(^ӆ1a}d3nF*4h9 _F\kRhݟ" p<ćBafRN0~S -WH{P 9wIm|ъ |ԥvhW =^#4+7I7"^{vu=h;́ @+VC> zI@luH4֘q`>H_f88QR u{A#_yXFy 'kk[0?JnVJrrg+`玲?#)[ZT!<]P$!'END 03KlH42Wsqߐ: q ӆqdg8gT2 SSѼyo<;eF5T,ZTؑ ]M.s) tv-H'eԂ|1DZW ;LHch/`=+!$ IԽ>=rSE L}4ayrܹBMG y[߸|uмZ>Z um؈t&NI2 2˦U>M'ba8&kq 񠑂'͎сvj<9(/J`ذ'!߲sycXJFYE6QB@}!a"??5uwm4tBsVM&L>z9Җ\jOPs*#^(3h.%U_=$ʾ\"MpBa0TlZ:b |Mt@8@#4ua#8JQMDbzPc@6K+`$^l$q#;lUmYH3$()TIG댈jЏ\hs˦ =v!UFs+hF6 5MZ )'`Y1)%1@VL4M} xO6zW;g)HFĿĠ*;nkw]NJnp$Uåjw]Yy~}$Ԃ' TTNd\Ki ӵ)$Px|Ja0y/+4bx䬪ge1hF UL.h74ygԏ\7J 2i`)0 υZ*M DIIXJ<_ )ZmCQux "m!Vy-tY.a4ܟSin%v[}FNhdž\ ԅ1 miJ}48t2Ѵ h< Os/^'׀s;vp0I/,'Ϫ>׎ CJhâj^SݮkO7 94軈U_Wu>:O%,mc ,3O#FA LJGS6<tg/IH|; -F|!^cXYeL2ƄMeǧ!^Af=O)Q=㼿:#q }k ue:AuȜurYl0tuXu7eѰS&4q6|c}>zG4$rP6W8H6ǩPSr+iJh$ɓUaBmHgD)H%U+Bkn) 0WMƴ)Pqj љMك|jGx5^;_(6]Jܲsd~/(ԝionv 2i&E%DsKqLPokLF(W;6^=ݦ8pHbNׂ^NJ5+zLJk\|1¥­4O2k"/UH0x-J)7&+%0O*a#tCԬۄɪJc5#cG <FZmntre6k|(ʭvK'*xLBLgr(yn Td{X Zb`M£#рFp<\JFqnqnnQ5;bqpSe($zwXX-6'a Ebv4;DR*> OۏZ0\i%M z㉗ӴٲB }[*|^x~lL(U\B͂זk( Wv$,n7 n'PEL<2!7ph`P6Yd&fUrgp:'HV)Ӭ>r!9R1}Ԅ /W1YSS!|b/XҎ;qf-knyj+=<(S0gLmw#>2mMG[ h"J|]_ELs뺺@ 7 [Pq낄inu 8\Dۍl7Io0Q=ѫv/^bA1N9^(T T{s?u> 0-m& =B 5 [G+oŽVhdf] vj#j\ma(Mˆ6s}[Fࣉ\_ȔbPB#R>SAp|PN"Ζl>$- r"bJ!mtVm[jF^!"{W*rr)r4^Xh}}2+m<0M'ͪsM"uj.F(5%Ҟkb_P]G!q Wt6, ?k*¤vmZ[.`VCy ^dՈX2c/gٳϒ'ƺD^mТ.kYJUpښhV܋c Lb.M Ä́|KoXWlp%6ٰP% TaI !,Y1D0pO6Kg0%HH-I; "4?L\QkO"Ja>B`b'($~АR@.E@AwYo|6x̮-8ƲZгG Mj͵ݓ,D<~&Ћƙ˅/H MՑH )?#Cua1&+@oULlQ%2_Q52R".^:~#0@)=np6vǂRq .R4"I3j^{L\]fNlM@҆+70ƁK' IUA06ayE%"8ӔvnJ $vwnƘH3F;Ϝ={hi4O|g_j6W?}ƨًZiߘL߸uӉ"3cDځǼc~BDi4Z{kͣAk3^movvݺڭ'z^g\>uWwn n\}}犛n=`ɉ7N'xzA ࠢ{v7!{)Ҧ3+R$?A8ٙ\Tx>^'1ϳz@ q@xJ@6Zu!#z ; sB 9X0?dRuaf89tAb/(R29;eEm0N̞kLx=/]!eK|Ę.P-l P3Rt&9{ ķ4G#_g/Z g25jđ۴zZ{r6I'+kkyp؃>7ٯ[Hax㬹kyo//ZQ ="go }RE6vlB"W{o|xP5[8jQw<̆U#Gh*ì`PIO*0U-a"g;нY}na@~ Q[R!{'Q k& %8/̐B(*~DK $*l-ւ3,05F<á.;Mm{ ;ĺRbV8 ggJ3AE+i$)E}McƑr6Ir%jIǹOH8^))]s abˍ"ϐ6c8#pHʹ{ JK.Ԇ$"}2q풳?.+&4&ġ/Ų d8 ߢHտq//Qـ@BrO ݼ0ϔQՓ:Mp*i`(DgP`8sZ)Rȱ:hn׺rpq9!Mԁlǘ>| m=U(خs$5^,*Pvrv$3OF(>4P[偂r@"g_, ybmx0 2 ji=rH}=^O$$̦Nk֋0HCT¾K@<t|@9hw  B3~UF$"Z;eN2#S.qy6}W)N$|GݼεN;I2.)L,% +$37e;e7JYDr?WXCA<uwW޹TH1Q ]ݽK^mC4jB%A-h}Fn5_Xᐣ9r$ &i 酄&S'N'sSaiuɹ1!;⡴EzDrBR];HNzHήAL#?"z!/jYsM` (LoƒVH@WfS:^$7d11X`a H11mCa+. ">C8՜ܐo1Hu*?< R 8 y%,7Q-)oͦ%4$ UϚMOa:QC̆=(4]!Fa1#WhAd8 ~|*8l4ŌIPOLЁ=]jD&H%xp 'sBQA:-$G@$s Iu$~dPȽ\Nx\}S tU2֓lUt]u 3E#X4` {-<œӞQ'2rEђDqF$46CF{@g \cR~}le@¾Bq0=&U4"B~8+S„i"=Ц2r/fJEa4:WZyb}uKpj||Ke:~'πT^cI1mtw޿J.%9Zo0{(Kv>gAm{1U떩PJY]ɯH\ P(ܻ}.1>RO"x0ԢՖm|.-h"i邿p-x@$rݘ#D=g4l1?܉:~ lUӉujP!F`њ3M`#XJ4DML'8z!HMǟ#ԇPZHoi:ǮS~ij !ne.n%d)M/X ŞGhTZ F pI~UclP :?廓J|:C*czkR[J9pl)@Ѓ"!g,x4cl6SonxPD~WȂW/Y-M>j9Nɥ<Qc5>0j|4۞m}MM &:VzEaB4ГfNZ[7vi./ep)N4Aɯ+нAWHJpDDx^ߴ\PVy\>d$Cj@Dlӥ̭ubFXg8>1uO4N@餧͂#pDPmQwꤓ7|lҋ)RpU:4U\YOq֝|}=d%^$\Bjd!tI|c)G HqiPc.- gHq/]O咦=T9fA xt4|5Ӟ:4Uޘ spSZ8dͭON; 61w%|\5aO1_HX(r1Hr3<G Uy5A&6 Ċ?8~LvV1$+ȼ#tnQbfYՔ#;J L&/@,!-3iJ{@St|L+ p Eu0jQ7cZ.0E9W93-T#͇|ť:t_rx_5Dy1b_ ZC[i̾#٥;i2 ФhOAILS4X)l yUc#hiwO9lCnC/CfU (@1⼅ٜJ'J]IU?]69"ہ`fof1ϗ {74;m٥C Γa RaaW,"\^y2P7rSgt=T?Jpl !>=s ָNյ~'C14tj$a C_uTail M@{'t~h|&R"4FT)ZC1rdH+&_%o}B\! ys #GܡUڦGl\ii$4~n {~XR y-;)MzɭPip*lcX%=yW) )h7 M eD1Oݸ<7s,?i% Pc ȟ[bF.#6s6n&lp8 N~#*AT!?á vVlWɲ6 @Dr&! " pX M չ~\9;Qg0I筆$l T3 A-4ƙE 7MF#qm4h6Td*"o| E*:{9p ԕt@DRBG‘CiuGxyBV`JGMjNNQYM,sMѨ)MsÁ'/T);C7KMC7)& Ѯ3e15A~ق(Wb*W˕Sg&<_i QzV+94RL?Dw0X ^*>ӮZq{ZӮv?M>er 5QTg ! U(R#N61#,Жi=JaG1y[걪V찓Aẛ6_<mQ7KfҋbY" ˺K}hߒ8X WlJOOr Z`ԍ>:|&M7Z-Ο|m# @\ M<'/ݵUb<E6s!D-r'Z #O"x1y"*d3#0R 7 M .&ӹZSGb0Y[qwqւ묛5&әN*] ܵH9 Q]_|ҁ!.FpNDtɥ ([7;(ԪݷR=<T]|Lz_i4;B MVϖ ݆hwrٰć9ju#06A~-Q/Ϭ#~, V8ʛ%x}FsUůO;Yn+%cePF-*MnЀfljEUW}좄l\P5-#=p wh҆!.0缟z LDS,X 3P̂G5.ܣ>}P07LIu!Ћ4iַ|+ʲuHudo)ŦM+'덢X+=g@%r)HNW=G@ VM'>`R 튲 /~ېJItX<܄hW.S֗1$| }CO@@+jPGt滷0I[baٗNE/0L03bm QELi,*m]V1Z;uA4E:ˡ@RA2<<s~㲲WZүVV(YXZ2VQ:tcD`]^uE^)dIyUd(0- Bkl%h9uR68XjANXV62gL#1\5b=0/QCTx\bL)HgK1aU.zG5 0-@0lRkViΔBCR!ŝ eWY_f" ]EU*vYrru\>,vW# (0-{EdIf&(E* KK{޻?= p*_ӭO[=zY֭-,ξήe|t#uSq{qG9֓Z+N_ߎn~G~K/ޑAtQAQH? <ǃ˷zm];g=5bԊ~x/B xAMv<" '9 9QmB1q8ѱѩ}G KL)jSP'H]5 jC@ O}=X('QgTjdZJ4te|ҟ5B3.1ܲvvF-sB eO] \5Kޟ e* N!B ,&n\ T&&}}ftβv;;)KcoyDBE *ۆSٵ(R)y;`H!Ǵ̂?C} >[&T`O,KE+zwёFv?cWc߾3WRIu+k^g-ZnW۝A3JT _+ 4wHJ4a@iHg|]e:ݖή6™7nif. n gK%&@ϖ" z!#܈zN#wX;VƮz:mCDL!7W&0Z a@ŠϐYErQ#4JJ4('4֕\( jtvM@:34mX:e0κ00ݦFt0eg=o~@0kKxNݘP#9ΞmC[%ZN<&<мl=b r? x| mmγgG }2Gt$bg/2!4,L:eVk XB _nT : vNgGt> tŎΏ1 p`m*`Q"-g870x7W֬hhcn$F"쀌4hU2|8ЃC^:MWY&ܶ )w.<֪E$q7P0Ez4\Z#9 q,,q%PP2uyFqg6ǃWѼ~R'?>x죫- x2RI DI-7Y>eg\: Xnj$mq"LJR2SzA "NnJoFt ;Te"rPr<ʋʺ{wQ˾e;~Igr=UG 0m T rװ[Csk9!gܰFt2|:BkI+Bt3elOtf\XHvY 8B>*@GI62ZRȍ#R)<YU5/bFPrK+,;CPBz=)R5/3:2QB/F( ;jR^K"ZùyF8U ~!N6NO@tN229Ihݲ|R;JnՍ} M0!y,D2NsM`6(Dce ZkZA$eTL#;!CD$0XEi*]mv|$$NjXSTCa.B{N%-v+FLݓ? 8,"#"\8mP#)R&;@D DetBiލmC@Je:*~`m+ɄĂj!IBFhܪQD1 Ψ36EOlRe\dQdmk]=!=aS-'#"K`@S;n$wFB@%C";uO{Zgub[6\eg ۾630L%\_s_NpHȅ2* g&D^O }E~s8̩ag/0 sφ0m+Kٻ-Qޞ2x¾jl0a=2@%z {aP! .˨k!\}Aj^ O` ݠa aT(o쮮ZQV4S +J4E#|wr@;Zm4AGJd ϰQCY% ]6K`:6`a\_]"XxwU@O0ܱ.9Ԩ}cv 4 @.W\Nքy 5<0,d5g,J@J@y=Z nI0cͅ˗[x~>݅;Wճm1 2oTD$qD|_ZC? }QR@6JS//O-2 `߉"R"E>R$a[7Hr!9{֢UcpJq\ J_YEP>apah>͝P^;i9yf+Qɥ۴a'% nb'5OtCi&;ڭ#0N>Ev!u `K %KۉQF8]Ծ{;pGd/$-p6,Ab2̕02 au b0Fu>H<`l8VABpZ)!Vߏ"UKUc nx bЖ7mĺWHl3mZ񔔱T#ecbF\Nwҋ07NajztoI|0q<2q8BȄ3zf3'O#o Io/!zGϞ] 8Oo耾ή2 ÀEx6-oK@7J_ϧLHEDK۱N%0q'^-F䒘oh`9nN5iR,Q"}P <>j^5ɤs `|ARb=/3cWB6/ѿȦ85#i1v5#"pV~۔O>puK0; â<ZݨsXA*˜e=ȜX9S"șf+ƂףR"J'|ZG߲4RͬeRzIAQv@.u%Xs7Oz᫣?_uH ְBmݷ׍{RwLW $H+;<_\Ѽ2pC9[s1 aPBIHq,,u!8B$R8M)p` BDe5EUQ)޹ 1 L$Uf]͂C1\t\1u8x+Lp\XBѿ^u#X颺j<ШۊTHL%5{A1 ߸'3Q0 DLm7Q:pI&@yj9u _ۙ$0j["\6:O\Ph=]^um,SoʺV*7E+ #NYfX/9㊡JϨ(%*@Q?_V]Әn=4S~}w,6@ 096QS2kL0lĘNe"2u{~h!lDXaAwW>f/&1&J9.`A^!'椤dh^gD#uE`4 Ss]Fi^8y'ϟ;vvj8N<`r&? EQql .M-a ̖`i0iǙ^,5;B8W\LB|nQ붔6۪m`0rh~Z6ݵs&0p7nj#{o4KSOx!|B<.KyuFNb X<*P:؇IvP='R*s}%潢bs㙑cJ5aV[CAs*x*@uL`&,Wsݐ="mXBC ͝{ew]68 Wc3ɠ㼺];=`tFH<ϝq.?u5 VEΝѻLr($(DTntvntϼncAz cM{n6N& J,#Z  w qCm#$P->d`tvc:H!s dnu"T;ڪ9 5< r!YxLYbp%g7hӘ,whFw Ҍ HJH#NRl[ `!0-i3T "9WjR=9&R eLjɤ`+8Jx@oh~L-i"UW9B.0PGJ^IJ(zk۾BB&?!-G9z=U V!g @c3(BCR8ҺiPB8>|Þ/y2 /ӀNƃ~ s{8zJ'p y1ڬ%UC.*p 'w7Gģc%4`u/FBv(y߃M VIiQ1X3Đ39$j Bi󔮏qoj #17hǁ8άV݋ C!O/Q_w>#Dx];ުx%-{f&mZK.ދ8Æwple8S#8T@Ar DAM4/32-39#} TxNyKgms^&RyHP 8q* ?I.q B$]$*y"g-OF3؃j2%g.E%8jzqK ;G(e<$oMOF @{d/.z79XN(%Xкis^s'x Oqnn0۴H6yŦqSߥI.sV~GA,5ƋՕkF b ywu~rX06./ũEu'IU5l35IGκ8wÑ=ɓ1leU۴ &ӳst`|PC`VWD 8?p`W_+rv*vFN%H\ Cr:(q#ȵegyf%MCݞY 9=-D5Xdn)P?Das"7F(%: "\N7u.2kj {oP(2lGhe$JJ 'KeY")% s?S =% ۢ0;FlIxh2 pNVJqDG1('}0 c9O:,vr&`(+TCv4*W  5h,1hJYIQJۜQsd$S7:%W= \:?#!&Z7{Hb &oHpK01D[L |ɺ6`^Qp$@Gq9L@nScԖpfy [meѸWjd 3::n[)d)ef3+e!Q>e*_"{@Jy[#νZ[&x0|`͊G[9X<+]H݋ǥ`L.Wڇ?b,甊>̂`[`2 $Q6$X:fQas{d$ m'U/]/bvYV(S*8sR@"g7jyYB*9I},h=w8 mVԶxȋ ͵ M 9Ì`svJilPX* A?cPZP\dXO&ey2 tX\ecOʺh δ[M0[5I:IY <了l #:((NZEόWfvҚGi,9*LؿCu'NU08GZ9ٷK?p" ڗ, h_4ɷi]ͯ`|=Kۜ Lj`L~vt2c,'gAbq&njMPc{P]̈2sFg_AC;bK[^V$"-~&u8tC$>Uɡa$58L&]cH8:[HJ! y'Y&^eH6u#: t,M}+gfH=l&Nzٝey|'Zm̪,]ْ,ؕX5j\i#gma5-Ҿfwt $m0pzPhX "g_+1.J`B~trޯM L%M`&l%iV/LtʳCG8bOQwN? e +erŊ> V*)|\ "%2op{sY>t2 g(_+> p,p1ב?)I,uG9%Z6+Υk%*{Gޒ|Ɏ9~Mϙd?}tAk V+~J=W 'TRhcm.&-_*Nf}@(@ o?y&[YaY8 +dJ6q[ s8޽duӷ"E8-F@mCkjRիtIb.*:P71 )Kzh/@*aț0(𒺣AEC<~wl^GBg;v(9( tG~C M'8.GQ 9\'}ccD [b4rlR֡|n-8[CqcK#NTʼn} V(/?!HS?&"J?eD]BY "_XMcOTD0:èҺguGz>"ܐw*D=kfЯ.h FT2F`Gi0)'Ӷu-v\op 0:싆kAk0Ʌmiaes{t較K|*<Ú 0?I`^r r`& A:ɆhA'# aMg:׵h9HMZf0}@{s|6L[:4#7UQi /Q=L)mӵ_Ҁq& aZmC8{_- w4۪gnuDrc,QV?{jaƂIpos-Ԕ>B*L䠈n'b|êk]V :&CyH+tNCUI.}Wi$/Bz_\W,FBh L,=- Kl牟n`g)ItP26/v umHBԵXveybry.v=3b0A*ޡC2IXVO%TC?30̧GG0U`b}X LQ2WĵȲF{:y'K[MI&MpKL>W~{-4Bn;)0Y)^Z߉yPQyP>"% ښAՃ.ֶt&V0?_ސ_@@1 i_7sՙNj;O\+Կ3:T3wџ<@M:Tj *'8.Y&ˬ#ꫲO&8רC#A)TNQ+ˡsU%pFpnxK`ݖݕh0}fwÁӊ4WE^\装N/2U^BG_ًX[z?( O Mqҫ~r.A[PR\27"!7'*lg8I@HϷu_-Ѱf;Wrv <%hy̏rH`\4QV  ~=wT&"x]* @`\HwYlէs Ṭ.g5Oݜ '{*bKFH;W0N3U ! A6eAVAvORQCY0@Os2Mf٧T`o 궜"zǤ}A9nƥ* P 9TٚŦۇ͛r@U~yOϗ[\V'Ks33B_4븁jҧf/_)3y~D_iL( Ͳq0_!;E>zAp` ~8p3!ELײK ۚ-lɈ9WJGAc2X7,ra.@VKƗ6oPJT~vp|AX/ʩR&QKbvr1kq Z#0SrN:s>h\-0Vm `j:-yWwqv1>w /-@w'dGeC,Э?@K"qbcݜ|3cʠک XT+Χ{5dy;(P?qP=S'R{ GeC_h15hǐCNqM)ђX9]ȅ(*"K(ru(LIrʨꌡTXF=ՇUk1ѽ)),3J)RMI^L/OxnHun kdۡ+ӋL8]g\9{]>ykd;_׋upl~]yJehO4(vZp%*9#,EHЂ݅"_!8h?i.14G{Üܺ%G&V!NZ+vOʄDJ$apH kΩmVMq! t@@șĿ>FZfcp;eW #s!Vk<:FSƜs,Xs=GrӠWl35+4-Ԁ=FzB[OF}r6 rysݷ1a*]%QB~OYaZ&ab"xئc3<6?KZNm\9m"@j9;~ ^&hn,+ʕޛ2#lvwXB깾 XP. %Fa^/?&, ]J/ݥF81FHA4BXQNgZ $R-rv4m(wfgm@B%eu+YbPrtSg/Quijo)k@.L᮲p|l3 4C/+02k2! |7QAý:o:xf/ж<+ZK[/NFեtl„#'NH~AOg=!qǏ^j|Y_=f<2LWn+D8B~@D_'g] &ݤ^-fETB[Ԝ x LjsQ4$= 9:V] y @ͳbB\/N;@UOr6B|NVH@zKVzA3 +3ˌ.ߢZBB|ns=* e'HoBrL4G*I['߯Pe +/Eܯ)5¡O>,[0 [&qrW"8S9dGWbtU:a7~3%X'IP˴n=%Z7dh2(X+9fL| 9R64hQFgK?E!-4Eζt`<10gZ vPx!ȯ{<0ɶ8?q?G@aа  Qw7c 9'd!_?!a+UWVo< 䴏Jf(Wz9zX.u88,ޟ~dqC,3Jֺr^Twut,yuJK]riuL!pwhjqKZ('5å˙;GK$""ngި!U]ci #JB[ \S_0ӯpZIyk!q?`%+ qOAR%f!@P Yʫ-B(4IL-jHU"AAmQKΜ=<{fSkZ;+Y\XJZZzcW-_k{xrӑcc~!`]V|q--O,=el6=2Fil:;FWz^{eq{^q8G\#ngc۽bcfgU}Ǯ컺{zDK /음ǿ +@? ؃2O+,`\ {G+T>)H*q^6UfD"Ss,/>vGE]K?GD8O$8+KJPPDF͙~8aΙo/-]$L( [> B QBSSAmnl\nlt#Ͼ+Q9ҋo\=Bpwlt{WܞG~c)audr}Ks5X ;[~fD D"|hsec}jnL7f4lA4n%9΃q8K7MqKbD p&D9 qFԯs2ykM[|5 7xXf+]8  O.>Y2B8׶dBHm(`BtY^#jw#61 "i8;p?u \d.DD^jĄ9Ӎ ZsF@pRˎeн밻(ܩJ[hLp|p8F 8IVHWέ&8Wǹq3f6 A%tp( P)T\FpoC<e"#f| ' B'f\S%PARB / 駏|gI&6D%Մ;&L>#)nN+.O (TbA鏖Dw.0D@OW# xn"w#]J/x~5%llpƓA"*!he}EZQ-Q :N N+N"kW bZa0}>PuTPAo7YowT߆w+1YMs /Jnu: tCz7yJlVO'@3BS5mfy!5jh `e\0h[3Qnݫڎ"˥rF=r`6{EEp(Jxi\>j\sIwԖҪu+pvmUq6d8xSm=I|D8%kwWa Ѷ9رC͏13w+ӳ/!L&F,ݵO $zMɞ9]*S)jIpvϟZyh!8+z84;PICY[=} ;uI\֪C4eɅVb x*"ք{@p/ ([s+Y{oU`'d^#@rׇPT (6?= a16t-ЧڗV*I>m.!! ` ϝdUydsg6rQ)\(w~[<usc%/(r $-?t8}&[WJbꒀ&.Rn8Ui~ Ʈ@%Gچ<0d4)}ձ3Y{ ́24chӪ%!N]cDni8J"j[%n)-J BF6.mvsa#nPSh~xL>p| F8ND#'nIL5Z)w"˄&L>HHݣ-<Cl¥b =i0pyzɑ+p sp^qpgjTn Q<:Gǃ/˞<um#(SOkWIZ&+OT|0\ng$\jYU9/NwNUo%kי|KLBs hSSu† eQoFnQI*&q0;/ ^!uG'MxxW9+M< ;wЏZBWW'* )Z w2SBpn63RW ̻ ``E{'=CWچ~S = 7~UE(M铦3.'sJp&8\Q&-Y1_\ ]ڟ<7atBi$N5`Sr[a䫧ީp4煘Yhu۽b%KLC;!ŁUjdo;+?-)Q:.PԽ:t0?|2x[NeQzǓڄ _rmlF[a!(̑6yaVtK\ ܃ӈTmʘmA~~*`Z i(K+#h@xGCYOJi: m}#n@kA;F.E%D1 r.0VaݦU(]nQD/!@_7 aȥfͭT٦#, n'ZDHxAIѪ7'KyOa~m2O[3C.tw 6ٓ!r`D Q- 3/ KD2~"T]Dp05ԒO6Bu$oRY8Sиk-.\U~#8rVReh9&8AѬMh2?KqSH? A̧/}{Y+!3"qxՍۿL8 πCɽT-1nY5{o q]~le<2Y*/et~!]C}|Qs$¼=(BB.l(M{!6Fכ@y s^j'Z'SP Z+唱JB%@7 0o-SDt^kSR \krlSs<isȂpaZ9-RdP.?ouPV'ʮU9}0i˖A!uB4 4nаq+Sgd03Z{jGǩFu!<|XaҤ$ \tq1@]>r;0Q1~9xRLC̞n Kq!gPZa,yq9G/L4n4 +# {ҩ7^ΊEc&$bҒ(Q~VSڬdqM+ ? _̳꒫F!wqkG ԈlT:pU$0B2My:o]AdC@T< Zv,yIt }akjj*ϻ/0Hgb؃JQ"P6OU:~8Wl&HXFwg c|蜎U}Π##-ܙͶVaTb)&ɉ9۴̍(}tUXU{s`ti Q(pl͢q䚑gͻ g4 E^Up hæKFHӢfK|o *w`zrU"TO "Lks[D ӺR^%5*'0 k8dM Ct CUKN&  %:JقP?Ҵ@Hi*#5 ZqCG>kf#m>[7Me|9T=[wcaa+vEÆ}Fx3?K=m)0]3։tvćXTTo ߙJU9NAO[xIBſa\@Z݃2J ؋%?Tu:0ɺA36ASAo'7CMpe/Ŀ ?p :4yjM[A} Ret :1 t} qU~Vu `Z˪ޟAN hG(6,VΪ H˹>C›Ӻ!ټw<~|s(g5F\1s _ p)Auys=$a =3'u9uiGl[Hc%&пzNbE@U,_+Eh9}@qգUU0 pFhJ Qs=Lێvϡ\S|~[#=ⴽ>/qwAOl'k|'8M9qrKn QSG;SZgu0aDVeCgAhqxz5RVct$`횢uÂD(nt0RI}9ݶitCS 7< 2rfX%#0~'B2m Xu$]̢!fCCMꫦjk@U$@`U-O4jeF2`̅#pĭL2])NJ<rO ]>/~kT@4@\3E>Sd|n$HM3 G 15;ugfZ5;gR>h]ڰscC ޕǍ:6w-jm]dB>A&8.%Y*t4m4ܣr5vTVv{) 7(8}H]+6-e1tbvY?2x\-jܠ$zX/ZO[03xo: >k#&&H4uۖm7PT<_ y =T;0ݬ*Df3AY Y߃)`~t@LALp 4*e//$nN' ۂB.oW`Ṫ168#5HϯG x&NV2֌'אn\O:Hwo丮gԎ& ?JHDb&=\HM3eL=r177WCBqTvUݴ "%UپzY{_ՁWX \v6NľyY@UOAC־C|kc x}*Od<6DS6/[CS5}&0l܎==CNrГ}?͛4TϾ׳35Qao9?w ɚ6B-:z,o@m԰11s>^LX𠄳Qj)N>\_q%NkXUI'0<P ~˨0D:U+DYxeD{ae=q#iT;Z{8z[l9eBNi_H˓bE<Mu`ԈAE5=z]iA+:A ЛL&ܫu^2G0o!ff ,ηD]M1qN>O*k?4f|2xͅdoܑXQz&sWx|&ruCm>SIվ'oř)Sв3kS&9CR.G2IOZwUѓAp7!8 1rQn!0w! ՕY6:s0_=̊[{BC 0AowȀtҩ=YHH*fτLI^x4f!s$|p|o0 |{ UYL#yIk7T&JumXޫyzF{n6A.Cd| t YsR2rg(YUeMmv0wUjvYz6g`$7,͊%%Q(egPؾQ_eˢb@mTen&ko3[~gm)z=?u8Lƥfg;d@Yv a虔}^d e/yjYⶨ6+]Sb S,ϠxbI+ bLVB0*!g R%,gd9`Yrx{ݕy{/v#~$Dhs>UrDu/kžm-u۲$t i[_{merXcO"WWe >\t^[rV2F |L{j=ܞMv=]PJ?p ;5j].8#w^|wqޘdJ$XH?a t6sqewBC!͝{eGYPa, Ǩ$>݄{7w$fwaCrpK 0AB6nW(hIiYUHQeYZsOΙ{^٤&旯{_.k랺iiOdZz`!Pa1? :O־P-m[khs<^^[fsyy}:ܿy}:h5[767fy[=[75ƞ6Z|qKZۃ9]P@^#B@. kY(h㩁js YzA0>I8  r8@\'~+b'2B*}j$Q^+hF((qDaS8aὕq}F%p] eoAGZȪ%D %Ĥ,i􈘫H,|9cs,!StzP _T:꺅(R_ȇL 2GzL>%|@חYb[6b [ۣ,Qb$W{2q[ߘ49Gr^eK ؓ%ؗ'ey֗WxmV'6bӔءXSr IgM-ŕB ,z A9sIV㰁'ʒEKRH ҂U۬@a[H”\`כmz/8+QN9 xe)QLSV(X@v)AwGǕݲ :ZM%|\+NX68Ye1IV؆ضV,3VTSxRf [d:%0W4a}o0YĤzjC9z%Jңr4aDDî-Yb$8pʉ^>gBuZj | 'lr׌JBEUő{v p.,ǔFuAOAE~0/vLTUW+k1HI;tV8 P'IU9G<G]Y6TFߋ_SD.㖦48(m8|W҄[8iKST@(+8(x;nQ.isJ7lwx XcpX ۗ"ID~(ܖ5Vba$v\"3D%+%R.JBʙHCyjK^h-&uՈvI'D;SJwHŋ ֫ uonB'%`=-st^kl{`W6Ƕ`Xz8t^Aw`!JFf:zU i6)>pMro=r,5E,(v(:vޫ[rsן4q2+k#Nd*O)M}cѼ%Ó)%^*%T8kR8av JfsP |^~znˊf@]R$ƹG8֎B1bq;gO$:L7nMt0ЉCZLvhmn JSXʬA EM:a%ZE 8 |UѱqGN֙]!A Tsrj48"畫Kax< ig6@n:`޳:VSWX['"c( C~bU %k$J &K|A;(NV*%`cL^((7okL\t%Bv&m0!WrY]$P]qmCDެݲHD8 "0jQR9 H{8D {l} K w0#R2#=4^o=>+ Lf?A}a~&&k+Zk1T[#[sa3o]$엷[2zY9r6Nȉ6u1nBbCg!nU\/nE+30U^6uX%R"$I=c6ܮ% &D^B8dA |kŁ i]"9E7du&(˵<ՍP"g\IܰTEҦ44DOh iS$rU"F׷jg?& Vv䃕s:D$KTsӜ7\rGdtjSѼ םB#i^'TßqVp$9)ִpDKH+H&,ƃ]gZ1A4I~z?@T5%,_"I4ޟ9Zor^?>y d*RlT"J\G0@!/kY:HCc3/ˏb5ahz▞,D40+2k.+ +CVWߡ Xÿ,و#v2SN f$Y+2Ό9B+gq| 8ym {4[&?gz `2 LP|:>'JEmSYRo2!捙T)w}eèVm!5-/T&V`k` Iecy0땄㵐`ZΕȆl ǿߘZ7懗PH -jR+Y% ~ۈyQX#˯f# o!lAXuO` @"0,j˥SKɾW<$" ' O ־җ1уDأ 0CqD<ٸ%mpc|1LEP/ulgDd~kMAMž3iq&S"8a؆”eAncK-!vGJTpЛPf:^-sݶ H$ $'Y)_@8pֹ*ML\%xAV`^/Xu|Wy+(r)z%qT% Eʯc0_x/ZOoӞr7eey=%{etv\ȷFB iUʴH 7$v V5=r͞}Y-0h%) |7v@H؎`:9.-+g[zXy!S; = B0+ҦOyVȑ>d2jX=AhzJ!Q5@e8 6"(4P!#5t#<td5>cKJ828ʗ|,h\]`D+KoU!]"4y!f˒MLwmiNp $!pe>߀4#oƺ[]Z4vwso`kĤTzc=< ~@B/aA6:?]]Gt:`8oS?}Tii¹Д3E>D='Es`JU9e0ɆT#VɓYQ2yd Rx^Y[I,eϰ[[`Pәݙc3)ׂZXϙ0UEo Zk+Q:;MQvU "R*S9~{R&<^ip(uqA,$ߞaض- ~c%nAOs!G6EW.ἤ@H ~ȣ!fmkK}.zHZk üX[m\ R枃A @Å$pOrlñUgLI]yhaЛ]Ƀ+ < ]ĿVcH,$躜Hܙwow3LaU8rBOp42k|].am DNWٚ<>74;mMRXkSnoc\{jmcy%(WGON5<>.$ + 0#,y٣"2]*Qa%n-@vm>`kf5hZ8ǴS|Xպ#yUZ? X欸Yш "p :߯9Y8`FYo-GA˦;96LI.IŜnutD8y%'Wk_߾BP'D-NkΖVhG.h?SVf}dYoBnisWh.񷳺B)/8t *]5)e?mj<\iMNU'MB01kwv`dgۓL-y7(ģ_Di'+PxQJ95Gm dFC,H}H@r TB^un@~:ρ4Vݬ{XJ@,AS IR"ΎP!_,HE1,*xB*<:4Cq髜⇌` _HnCCu̇KoR9ĹAO "!{=bYs0%}bڣf2:WG il}\ٔG2##wMB%) 86TY=!dG|řa1awbuQV56l=#]EL7p)[SnkZ&- 8xe&<-隷z Z0 L\ loqlg3xkn CD_v0 X|x8Y,bI̺;FOP 闑$E7,kb.݇(3("-LY,aĸ dhlI>4ojVB"F N.茟)p)4wܼVZ>G(SFRi0kMd' ҂V&C^4B)2fdp9ѣoW+W1_97so-&ZT [w98D*>!y'ssp>ᜑJ.ƢJy'$AhleuxT.b!s&Tp0T14d:A[g,gyKAu%+N8бd_oo%"Ɏ=P?ݟOBCj"͝wdGyG{r(=S=٭s*;{3sN'M,LI&F>%( D`H()I leS(*/vzo<*u믿R׈=l4>}nƁ$k7ᵛ~WNgW?" lٖ c%hhјVas\9ޚo.o5W{}^g^sf}?^t_~nr^ 6/L_j8!mdsx3,AB_Xڄe ,fy0pBuKeHPHg$Hx׾"XTϚ40 %㵯$_8C%[x$>%:Cj#n# Y!}0]=\onkT`o,j߸#7d.7 @ʌn Q*]D^$"Rlp]8D4v L4 DT q,3œmÊ0~@mā#KӘXa.FTJ0=|w*<@T 16ϤEr8'9,a8'w35gwz4]@V@Ѻ6Z\ߌĿ0Eᠾ.T6Ў[l.`J>Bϧ|p:9h%lՖ;kv;[[͕s;{N? {`~xfg_o?f<8V.(K}Oڋu(ls UZ>K>NKc$k^xG`9\c4 PV5P۳|GɱL&!f pY𦔫VL;pY;J6ȹF y͚W֬GrVӓk% RJob#4@b!`{9=^ۧ /NEߩ&hWGt _${Ox 2cL$zVb!q{4~.ҠlbcGoq#wOM!]໌8 $(BJm !L\*B=#F!`$_ >Ce6FxL0r6+JSʺx:*  6O)0ƛ50˨Ui.VFF!`,!+14'ZuО 0u f1Wwee^ocwp Rlӌ(HB> CmVRj(C0 $/$_ q=fw/D7LD' ;u<abqF[ITPT7iQś L]D'SN #& {6gx8>e3 (4ܪ3y\:m8dͩ;xʹ{ gk!@Nhrxr yYK-ARWX,VIJʁ@ma)1.Eh]ɜmbO39w-#D~@7%ȀnkQ-K"  3@+v\ܷLFkW bQH s֛a@dvnxG=]@AD q=FIINMbMu>L\lhnjdIi , A ̵IfӼ#Ry)_'HK1>p恠 }6Y/>xrylgZ]y:[BȼիeT[l'%O:'sS˕|~t B0e.Bc?Ev&ٵs< B8愝%*6wE5_ DvZVL;[qs '6K~?]#`Vfg g6fU=7zM 8dnp##w)|}?Pr%6+ׯS;Dm-Kl\5d<%EA0,SQq~DC~Wjw+91:AV'NV3lFQusӂr)e8JgTDb$85 xU4\Ь/9\&\YJFMg<tq+y$ܶ,ABslµM! A"'KdtwSёr !zk-2>_[wO4O;\,-ž9&zgR K+*&{v'?ZxXBgpIGn#ٖ&`MY}GعkxKˉkoQ%D pQt 2xMihe0$ê:Eafz85E 3G#* xS8.% 37t!tC]FԶ֦i6ZM\R2sY]q?a iڋP7Bؼtsj<&4M.=.v@30So%kQEr+ I jyi!bx3.GtF,!IG[n9/!rو@2{bgQ5 >EX2"5--B?g2`?@`~\@6e`Q?G^>@y>?r)2!!Az b<tD{RDZWTiHx'TKQ6؎GiJPG((F+}c9NC(Q;IyByl7v 7v٤~+;9f/l\N]2Bp1[B:JӭlLpj[9fr`Aw^d1}9ɀs06B4;iRM ~ YTT*hɀ8s/DyЃހO 8hg"pNA*ʐgb ZϠ7eo|> g'eƦܩZ,hʇwK3.嗧B\dQ0(x0'ʕ6.n?E<265 #&0-FLt)If0Y6jkGA0+L0i.{cNOP!J$,gUT@$,DW-DIl:;Ia`ZQu}qp}-A2@(YNM^n> ͆0;i #?GUcMSrfsKqfp J SFxCDT>GCSB boNR0ܯW,JFR&Dd"/AIzRt ؼJuYrܮuT,d1LlgJ*Ӷ+B͞n2ύԇK2kߣmkkqX+Ӵ7by,2Fz.ף}jFT-b;Sx3\kOTDr"2V6pj-Ode"ŧ@~ČOhY+h) S;W=1щ<@H _Vj3<{E=NA7h@y%]ochajv|E֦. ;y4"E6uZa* Ym<S2^`!%t$ 81 o%w Y)?ď!+m$~ m'7h8T<1iCՍ'\^xT{AC3$hՎc $?]R"&ѷѰGts/OZqƀ=0_mGK&#^9!d-:O{Xipg£}VgK2`ݘ|74FㅰEf=\p"1$Xdflw`-02k0{Au)a/275FtXn;pVmĸ]Zny=N-zqDٶ2Kl :0\)?ֳy(Q\4xQ2 /_14< Q ғULj" NVGhގmQRXQfޞS0ڣ`loA zOAKj,gs56&N}l%PfH7PcA𔙹N"fKu1#h6DS Z3`\s$69aN;E0-XpXj +VD:ƒ"pZ}_gڋQw_$utA(5<ohڍ@ɰ#J_m F*]+x&e*%fo&Eoӌu͈6JE`j)Q퓂Ti&%T%j0њ)_&JJ}& VHK]%A.tBNTGMVMFswӤm#2^RU2k9ظݢE`1t>ޭ:kPt^jm]lˈ(?IU? 3՜(Qqy>`䴍 H dʯJK <ͅsz戀F xZ ypvS,G8D@0 O5SZp  Xb>Kt / NvJbf)~u!G:!0Uyb%ԞouI(~Wqt LukD &$aj6dJzĔ1a yOUɍ %H?l,DBlНbf\ئ;qgg)Jpچp?@d]jED> )vP<8G ̈́,&b׽)K4gۡ "t W[f]A̠qfWq.jVE(vh_n'\]|XD0Yr*ɟ7 (D- jFxx.2wgBA< tC3r-ӝ-HF$L')=Rza!ݏ},->i$č(S==P6.IV@NVX0,-+@>NRlwb&q}Fv0!r&&^;ٱ/UkS$0(1{ΒBM znP/pf-=91,%D놞p1lrcc 9,u'YKSMHT+9) w4Yef'֣q/cx~p[ Fbf?I?(Y1nN*2nԸB:6؋otSINWHtsxYJ+R),_T (yбG\\LB;IW܏kM9(e"׫.XsBC/Gt*1p%]M:>b&qOljxw02v]V7UOp=t^a:nw]oq։vnͷ{yn~|l/l]oM?O;'[[[[$v.N]zIҺ܍ZgmLZ:MPCS oE"wwCv&Lǭ'bօV}څG/:/#ѭ?h<\@*h\N@(N{ A&%tw oL\ʆ*6,{1VjEYq6Zz6+HgJ$cy&H&:a.u:qE蹕&(TFT #?F gb$c "x20Н(oăb>'$8|Jtlk(HD#})e@4)Rϊ\'G߶@*8`Ah(!AH.1b 8!M}v˸`bx<gp6|seF0f HxU<&<)pfQm *{U@NFG2Npر L?NB{c/|p?LL}5f Sv##*[s9uۜsw龃"| |zip![Lv|}m0 AB4.eZkp::N=b 0-˅A3kQ.mw]yQ4hjA97h?ڵ&4 ҏ̮rYaHI&$".tZP-tΑ&.JaTN.[OQg:,@@4zmm*a 84L(Ύy^gă8hS^M DЧ++&8cg6@\~M!1LhP't30n伨 S&(MJ7EY@.'TvP+ wKEӮi$}V#6vĄ+<HItWq9nB#gɿKJa<:|*E&$=;9q@S.0e,?Ьf|Lz#R,K:+$`[LH|>/(-Ff w.Ban3 3uBMW,` 0 n2LE3kk;Ph&}x |*SV>4]3UR2lD>;J>>\DžR|2RhFYUi<(}æԭt+!"vgerClګI``y'YJLuLU꼅XtPBADLyj( 8CgnK@ȍWjHzjB@e8$H5c[ߤ')5ܖ1@r{ = bjyt=$WGoɊ@.3v ]ۛx) gی+54jP4.s+DCDBTvhD4ԏ[Iލ*P(w}+`"0ѷM7R}++V$ \I>>V5͆:V+ FAiC B<# Suց%rAks Mh8jD㆕з7#1lgT F]} y`87s#c 8z:s4{V́\~qgf#-üPXҷ@E3 +۷(A /$fLOL/6a \eZg,l7bC{ /5im+{cdCHUQ*'0xf,&8o\&" fsQ)(| P3ۑT84!Z$F|ͨ4Bʼngni5Ҡtej,z2;,cRIB:6@5rRfp-Ju֐kuyxkk!+LÞ=G@'WVM_JY˲߀]_zx#f-]j0()H9{Ӿ {]E(I\t!Ryղx^ՠ-ɟ:t%fVBH:BgA.dVvY<I {>ev{բBFp6cuWb{vo2fcwSF@`Z̓3)IY?uicYʬ>Jd;:35iP gcW#!+SC=L7`dp횹4W0ps#_(ex^3"c:R 1z*a|d|~x:7Ⱥt:Z q5wh A$ V1tnjH|4.*E#'Mh<~ & k:&J0Mȏeg4jڸc2.ԇ14Mϊ+>9&ƯPT7,0_#wr2ߨ\KOC^6ZqA yN ̱@f+<ԄqlW+@yaPbS!pF ]r Tj;@2oLJޤZm +JRgy;Kr3u2eq+K"KOFh*CDLt,*]606ۭU8*&4-1 u{D@%,X2j%40* %ΒoF0em$(5J$|ڵuhG#߫CF~h$n. g[Ģ*pE?1YXyNI{>ue$= yQ'S^M*C?nhޝm.5fb]>BF&(A:( o<ItˠDU~Q0r˰j[/κ˲ mEqwh}T}MٳI.=Zy؂hTca~uej5Lavl[R:;#p[UyH⎕& ^5rd㾯Pcs#_Iiظgf&'N6MgK`ދ\KaX0+@> 2 TǠhzBƽQ,e:q,Fp4VN{فfR*z:iNRԖE~;%ɜmB2]K,0W(.cUź=@o4F7eLhoLFH ;ϼ{Vhg@4.6tڄAfY%JOaO"ٱf .;׫n4D*TR rz8cQWTLHby~|CQMWV:_Sǻo*olXHYkXC)a"2ar#>]8NKDT)C*9 +D'`:'s '1KLp=a08{qRWyֆJ@?^nB>P0:։rbʹ'QH|Rc77ѲUNގEX!ߞїF3'#`~}2Q! 2fb-3ѡ j"oe!QD"eF@0%Ճ_0l\2Q豘hׄ(P(PԳD0/KۛUHd /n؈D@vjWV@PѬ4[6撀gz2Dt tw +R|1cbh0AEj#_(diƇ&Έ>C] 8l0gki\ȨL4/Fh]MӼ̈́Qwڌl%opN2Jzj40ƉG\SV\G{FxRekD%!P}wТ߰3t6_m:>QCch/YXIo1A%{Te@Df$OU)wmoWCUX{\2I.+\eAen{璑="՛ʎ]AH{!*yVٷ%KM$: ':Jh劼8gdwQ`܅``丨0vo/Aڸ]-eÆ2^n7aL󸨏iNClܮ 0 Tq.6)`YH[PPUiV]!e?gt}Ӳ5B{UVh .%JՂ͎bqfY߀Rm1T ;( jJ$Tw$!8T> MC&@|ID&\N̊h(RV'#\3`vv}ea[a%0,#j<?tTթk%ۅoz Q>]%(uj#BtwQ!'c1!zt*vFԵt\(uz (B C^F։ ){ (lui{WxAhj*u2=K(VW> Ȉ"h" "l1 eEiѣ'p'fUﰠzOdg1]^]_oy|m-|D_czin˻%0@zZ*k @Pk-Ty ,dL#hzij"x.@}R?lDy{C l 2 t@nĻtݚ*mQY܅C_b*@gk㽌dE^X;ED6$uh2)M;@,ϑNr:޳uǕVͣr°cfkaE:?en^_5 %"80ۮ&oo:U0H}77q٫k"z;#oZG pQ#K2O$'&@d[̽me$L-7pT(;JF_]@ Fָ?Ąh24N7I#<1h4lg$ųlc0γpx_zȋT!-|.?%- pzp9:=Oth"; "G 8VC0|pE^$gg59ĮvTv&LR* 7NzKѺhjJOTz Vo bD&d$"o3!Zl'c7#(jUΛSL&p܈iWҹgNǞ-1 f|~)6ye(e }[mka: s ese} ?vKj`Ǝ O'.{]b$Ҕ @2ga߆n eq/5 =!E'/]V+D B$gtWmFnt,ݩdC_xю] =TfșlG68H@˕x !Yj8 8QmYRO bib#&~l,h8 2߾XaBO{f>q:q:Zħt\/j*_7 BgOMi^kD#t~}%ҔeȌStFU@nc%ۣ_T29g]  nex{A7d8+Ӻy޵ $T"oNt/ʆ/yTR*I ̏#aH@ٱf{ZYahn^P+VC>FaRΑ.&d_VbC6qeyh1'.,csP &.[]xz?ΪTa$EQ4[+[A62 `9`v,eNXX}L$h6mP:r]HKmüSEsPX+BC!͝ydGy{gC 93HD=H]6kuQ0m;'" `2GgBC@@X A0^D%D$HN;^WͫG޲dOW_}A8ԥCӍzWO?zٱC!hm~+Fgocucgmul6{^{qy{^y${%K^tn7v/ܼl+>ui|Ň=Ft,>yyxr5Ds3mlh`J3L>4 M;D+8=2mϘX LLB5@}_\NCDADǎ 6pyRF)Ov✚K>BLtq_ҟȫ.u?U1ס,˽2Ϛ)/# Ќi-3XpX?یf4gNHN 3NBovvwZB\X_kmn^nn /:zQEG6/%GG7 f#7 KLhl0s]cz6^@]; Q ]jĿ0SsJ<>vyO!AF+;f@j4(zAAxufLk`ydTR@n" rNV(]!Ϛ^.TRht19s@jMra4g}cm00}W_DBDtt@]i\ǎ]_!@כ!szrdNE ͮML`4fi."4o3q6bm8sFԴj^ hHcb`' ՖJ1V!rm$*@ǯxX-j]T+9v1Jq Ͷ9GFq">Ag74;/:VNż~! |Aݮ#gc6"Nh|`<=s jp@ݤT&Dq,]Jm "g5a\'amwk[@G#9Sw%,u*^8l<=UٸB:$g_Ҥ U4^yv&K$QEzGkCq85ne5q*ٿj44t\͆9MYC㨩v$c}$", 5јQӶPBLu6KQRNh4Kh^cB".\psN2 "G=oP j?PPEcѹ`]Cb *td4;v/yg& hI2 r%/ " #9DHUQuDnǎ,["ɯSI T\)֎l"^iߕ Җ՛u ":`&YVNٿL~_xLQz!}ϓmPUQurDZ)Kߨ0!~ P%N´c!>C$SݣN&vts y=υ,O$ζ֗1}+s2OLoUPQ&8{I2W1}*sG}!DLhU4MΎs4Ȧĕd3rEd`B@[4uxXv֬h%Ɔ3!]Df0fr&_RCkt(7:'~}BZӁh\ %}*"la3ھ"Sjq}&4B=A 1(H׮2NvV&O;znwQscjd]t ?E,)*; /mӸcg5~ P IM 'VFn6ڝ3;zb3' ߺpJɥW8؞JԟnmWV٫{Ϭ @(G}kH >ChCk\%da<OHJ 1D8shU؊Q(cTLt fR["%Ă-]Ir H nB ϐ۵I )픨cA2dr gtB WD٨uz] DUg$ fϠs/VS4_<1QNf Ew8+V;pFۤf8 BэF$H ,LLF$|>Oe l3 ?vnfhFkwa9O=|h5LJDmԚL2t,kZd+X9;ޜYeMs-e0_s[B*_cH7sըpQIR&(`cQà53 Lhc(_4ՁIv!BhEoc|/SwGFn) H Fi>R S<ȝ0*{(ࠬ$;p1]]u|h|z-K{9YMRա4~C!*,Fh0[< b렰IvD }}H;JYQ#$UnWo~43H2~iܨ-$A/T;U!}ԱϨ]veo4yH{UYORv} ,'7fag 6 mGU  :m׸, B|x AXU\Di4@Y@$sN* ]zRS}VyKҠ,5zAXbӻ"YۮFj,V~3CÓl0/E:e J瑦zɊgT-=?<0{KqO|s֨ҨW~Պͺ =(xLJ#2ر"7={[O(oo5mLׄ(}BR>Pg}X<3G>&C\K@|*dQcݴh;k%##f{dӴ<!aUB#|wQNӶOúrX)Zr6‘J:xff?.CO4$@ 7OulїW=Mo4)D$OiwЫMa@-zkM1!#jY7 ]"#4 1m#/:{ȝGT 9ly֍ch0O}ġUmt8M _&S ~B!TY΂pjl^ׅ:c*wl˄hV5ܟ`C- Ypz(H&KTWoƓ蜼scPF/!7Χ4Ҙ ѯGKB &P_37h)"DS^RDg<7gcfe$%~P]wx{-Ӄ\Kn)I*!sA UB̶C@>sr1Xd1Xa03%# v%!^,H$ M ZuL&A#QJ1G 뵑T])($Vb+Tv AhS΋C"j^E |ȠϨ^ X:sQk2og sƩ YaA/O'Â.cйYM*+>_2&B!)H8 v `Af<5gWap?p;9]hZ>@mJYB^,2&|^dH]}vpeZ؁3<0HyX;=BE*:n. G` Oahs6*2_>}r8JŮB@]9a6lm{oc\T&ݱi* ?,IRp6i+d Ue8q^'UDO2rjuҭ}EeT ~ҚlVkJ\#}KnW/9;YKjYZI?[2"ץFH|vNw)AnVId|&cL\!"tBsʄ3`T 'p0J<0^ eGq%Fv h'3 =U.&; ""9LU)M&8!˱U4w{Ԏ)7WLD3Ғi`)4)Jxp$  ]\8U66?!g ǖT 6Lpa8?C6-t96M^hͯ4A|KBfe5\zĮ>]g4۞pxp%mShmފ 勌1Dy CIh˪J*{]f#O88w &2)s`.15eOzf]Ǫ%ϗ>QPY''M?`-l۹Nt$e@x \#& * &4!ĶeߺyN Qe*e!w0yJ2YGޟQP pr[Ӡj}y8M !%1!B_@p9QܹApx"ٲes-VR]!@^għfk)(ø*"í}R7f˗ZTjwB)P |A \+=JePve0}ـ 9?),'-l=nBpF [hF*z]|^TJe{Cξɏ;*ː,|D6]}ϨambȜp ]s s|UZ2zݫZSE8` z6nڳ!sFR)A4Z"Kf˗TjQE/ f I0c.slmI'LBpA_ 1dNg} w4 M>>iۂ)IxIÿqY\qpvW]S #(ٝL9+M˳-;~m*or s Y&Be ̈́f"J1#ʋ;ƿ %Y~A* mQ7=Țm K8 [\Q Ӳ@ A'*)H K܅ϳˌhOÁʧm'crUE!DhDĻu(e.B N^aDGlBfv=$~dJFԛJ€O_MOrHVe ѮQ(loьh="*hDr}しE;Sp Њ3=,Iл [}sLۥFI_Rʠa=YIRՏYR@VSéchZL~? O$.-:jAx)o))P$Q2=8~NӶ Q=I?ܙBC!͝y$WyǻVDH"$1;x^[]qَ J8ebcf`9srA]/D 9"%!ĀM@PWWjm.vڟ}w[KK=tq̾=bLg7|ꡁB.:cۀo8]zޥ};;;ZVk^Zt}^z/EE^?:zv{^?u=:k謧^-];:Kh/K'Jh yMx_i[9?D0@7zcxV!'Dg!@0 LBзh:q)ύ&<dmC l԰pT(F4@MӨv9͵чzHA8G He3ͦL>K_?;=?(E/:x{.v sa@oU"8JŃR!*]Z߬OyF^Q-z/TqT?k]-jۡ9ΟoTNuww-$ZU> @.PL gnߡˬBzӥOH};;:ZH{b`ccWrkEptRjv׷ZVlQi_9:Uzg{/pMۉkBrB00"Εu60X?;`hŮu(^/&q Tx<7ӺE>:2ǹD:߶*$lt0wo/ JT>@fJIٷ7Wq)ESz O*v~{[E**M{m# _>\2eq&Ni6ė pB@ͳ+ HU1߾\ 8R4Ι: $Žx{<'cy͙N3ͺG'OɯפC~@] QD԰luַ6 Zݷ^nu-ܪspprL9`& Ft~L&8 .(J]`/p=u 8C5"sÑoLq\R)LϝMm&u ;H)c( ֭E:$lfBXG %fRlWrQpMgQR52 1Åm' 0QJy >;F7` /w2MVRImٿaQA]~M0dkrL0FY0T{eꔂs3 8;1JM$cϠ7d$6"Sۦ#!JQh=JH$r#YJDiseDmJt؄#"޵!8IZ"Yn0P>xFD kpbU;"$ ViSkLO\ޱ.3 XN(٭: 8m 8Z MӓN'j[! "-+J) &`T^T쪭u}~{CU$ȟ,s\$lCRWF{a70xnwUd\t욆Q%ooW.s!ÙNwM-lTߢ* a;ALYyNhQC20<.$ШC:xnN"C}hM[4Bڌ3q‰@?+D {kY{%FrmZuh⸬p{x B%!ST. !چI*vN$ƪ{T)˄ӳl@aTÔ ;n4Sb,;<¼,̓꩎LȭOv~tE(`*Iggi+NrM1w6׀~HR]J]2;s-Cx\1>~Dyw5ƗO6@(`Yc_fYin(^E9.Ӗ*@J7,Jt Gl.1qm#ШMom^çH끡h쳼i'_t.թۯV |l UuX#J\սW}!P ~QTnrtLM]Ʀ# J\""ICj؏*1HӱJ#<:ۺ#)u@W O5m{ńf^nΏ75|(R@,5g݂a]:mO-i=9T7gQQ[eiNU* ֱ=u/3Id+Û)3Fu Ef5 ̴]-r0@nӖZFNDqvpi8-t:o~lٸ="C@!`׿~Xe(N$_|śBZL~H1/Etk%EDRvRDĴ%zPO\Y>,[ZpH܄)e S f"o:{#-qq{9E-^"{[H7!@^B_Ki["JG*d 岒 )\|Q"c8Ew.i+GH(vݲ*0O`]blmE܈$i A]W?Pl #q?5~U Oa . 9#UQ\2-`9ʎRd<0{݈%R.L`s0s-jѲL40]_Vbىy7U`9̦#F9H/߶+xyTˎ-yc'_mcΒ v'͞*' /BLnnk,whYcF z-IJ99{fI|#9V޽bѨkvecRrl^G@بjJ5+5Kʹ,.h|SeN|N "!SݮNVtD0uh҈)nr}`VC5N޲,< (̵xh#1\玝<Ѵ5$PV/=OtFHzX}oBp`>ȔMԤލ/nrZ?Y%c5ۨJ $&\(Z5~X?Zɜ Հ3\9;Zzs~TN_ٻ9.+#κA Lv*QsL.nTA0NrŲ7Io:4}viW+RO?}7J$nK& H|73B6f.iur̂QdVj%1d9jG XΜ%>, =) 9=]` 8\> l p`3e>oSxܶ 4hwPFy;}^kQ T8Vk2ؗޭp9測:ԿAAC%pK+%b~ꢰD,|A,;s"?'/߮ڔO)|A\RxHVgAG%s 횪q$IXwK.CZ&?+ߞSuT ^,Z8,I}Z/ft+k"PlTQ5K%$ e߽eeEZ~*I(Bsӓ1bwo7T@D9(mF>^VNI=-b,ANn'.^(Z鋙eh'W\d0L>Ԫu8UK}/{~IÆuaA"Yge?pL@Gɕ+.\ hYrɌFS%äZy*gaaX{W\*{kUqf\&ioR'-kƜ aHX-Đl'MXIY3J e3 4ԗdPTB &k " A}q{{{ tCg; /7TɂY~`[ 8I\aiŗ1 < ߬?];5ynWVj?0Ae4Md@} OnnDD0 fM6)@ y)]˓;~$NMr6"" (i6B@ s"%fOcSSYT+Hg-Oc,)w}`pI,lE)lY{fU];]^Ryr@]<: tO)8tWw*IF!%dwV'7R}dR;JL@Jk"t?=  D'SKgkBx&F{mZx7DntC/q%?g8Y28ōpƱ 㺪K}rHǠFFT2eD7ǘ}x$ezIAq#HiSG^`4 r13GJN7՘v,~}R~Bczez {UϞupu3PB),@OԻML5ij;KjS{wLnz6<*˲,TseklTwΩF;Fǯjkۀto5M~x9/g.+t-ps够qj\iV7Qnnl\llĝ˯8x偨seӍv6tv;:7:N^ۼ*w5k:Gۈŷ\=UqJ"Έ.&D5" 9"AAm'F!O  DS"R*!rg0yTQnx M@/*[{|R<5 c+ M\/G$(\s"|#{gSg`' Ւ'  pn OLL"$t 猰CN NcnAPi5֒D RKT{ x+B0C.DB {-d{J܄Y-mY4ó9iVk'4^ rE8QKD?AL³MSp,DD( h<׀:?o4ámRjϟA'+ ܓSψ)w{p\.ڧjb1*]ɄOr0-HrJW͍&4rAᢜқ^f# p[h=Dv{X{ A2B z7r(TҸFdp=`V0z*a0AcP+aZ۶y7 cfQ-ӰJFP;CQg Br`1/ o`@m>fN#ld>Beɫ4#MMah&PNj8`2stjv = ; [R쬓x8Hq{s`㲨{0&4WvWN\!Af6fU`L# '`a,/F#u*ܜ3պX" 9^XBz 8KTev̀#kwk(i-"Y#g &k!D1(5-;Ba8|`*SDlH'[S9Z?Xbv@A429O$Pi+HjkҮFPlp wWkB%2<io-e(1…$gҵ5ȱQ 42 5Ń o`tYy&9=!8@5dmWͲnl< =|Kv&#n!kwixA #ܙLZWY;k@ȤD)/ g6`GryX&XҶaEp3< kQ7ayOI=ai=l Bp۫SHB`Rm{|9 ݢ) x9{XmYq::홣Lf~eAO {9$C PAQJcҙhS?ZRRSD^>g&'˙OlLe. am'zhJ@bOTZN69h21IIHP' .Q6jZB^0;T!}a#Tt=5Zbl (I6 =+M\(d!a T5 8XXUi 'P7i!舔'Q5&LB 0Ƽֵ;Gu*}Ȅw QS];E ]JUWӯ0zjw HGp#8o3 !8EG+Cj'mAbrq*J,9n5wKkC Gpߴ {^K#g JH/ p9O@*DbVB Y!J($a7)Gh^eB܂(hl8wnLTȇ'zߚ/[Uvи|^O8m?D"FZ% ЛL<^<p~jYolۑ M̜DeC)Ϸ+Dֺ % HAtЯ$9$Po@ R Ci*hY<[y8s cW俓t.NrVN(İF"TOޣ[Dƈԉpv㰹 79] 0: eihƑpPsy 2)Ԫ+%(cI= \7QB)? 8+;= %A>g =T)PnJ @,>Y-$%u$+ tVׅRtgl0]fVV \j Y{nC2{tREvN"@S[t[#'AԶ{¼vDϒwj,OR>O9`PJHDȕ4D+v%i W"k D{3F;ȪU0gJ:6U0!``27=KE G$PkIa]($IfyK覊C&Yk]P>‰ۦ0kA TϣeW!$7'YvÖ˸ * sdW$[pAv kmZJ i6&88034-4x$"ZrM(p&,v;5]zЋ 7+nݨG8ֵ[kj)pܘN/$v a]o5 jG=n Ѐu%4; T׉X˛ӓ!+2qڞE3'HUGj#|܈FH-x<+[uR[}иb+iR'U#BPD:WҧUE/hD +5ɍХ%.(FEC&TʶLhgDpUh(,[1 =x~` "x,(4B36qc FnUյAR߳S+*W'b 8 CԞ #T2+F%_39p(~ToB\vBT P!yy_V5/練X4~ Y{f=%鰟z(?v*tcysw8Y{8'abgʎ\JA2?,]X[u;/t/Q^[10B* O^ -ӱs`>E֎?_!k\LupbS\OUӲVd|BkB>MIΜ @=bRdTk7y\IʉuhX\II$o2͉vNA^ًӃB[Low-0(~|Z!5ˉ9y)|j >HՅ֥3OwmQ!F#2!r)@"[}6a' *]TrP td1t-%Kg*D WB/%UJVh)S:) " BN\i>JmUL0bBLmi'ʞs&*!DЛOʝXI(=zJT~e򖅿T+TR|[& |%Vϊb2UBĿ{#yа=Ks9y p ?gJW-[B!/7 ciBِyl6W\!ڟi#E^FS֝$kր#9|pΔ*T`ylc!8r%">)۔5MkSV'e{ 0>oΣFUr⒦ړ!t)2'*I1f4\S&0o%k/҅ Rnp` 6-;h谁WZ uFnQ%Y]-㠱*&8S[8{UY3deoGV6/YUs@JÎ vNFcᚃl֊C^]$ C A7]|*a|&φMz=g:Pj% 98)*ZQI6{%ge,t?8xA\i6X\" @ z{D=*P6KtI*f8)Uc7TG*NEF)xFJF£6o$Q ? .11<յ`AxCHD|H|e(aZsO9*-TvxrsݒӲy$;LF1Wі稨s7'PvS򗾟{yRRyNqNV@d;!^*/{׷r8uU>JvurhW)X?Lם6sl}n1Y8ϧ7CI8"[HY|}Twp&xTRPt_a[ǵ(Þ[HAq^ CK٣V&D+ O,fLE-oθxDlFh}c.PY b_y9# @J.x0 &?ZU(^-W&OPQ芊ױ'6U[))k?j Sb,Cs'3 ^BKqZcV.yJI2PbZgK/DDr \e.3*k7Sg&k ޣJђ ˳ X[pTY$h' -uf ob)T 4%0!.XnR ɭ&$'â:$χ+9Nm(iQ :#OUG>[ܡoL[>P O RgxUt&+K2WI]$ߑd4M z}[nbYh_'4aZ }áUF}%Up8LL$B",GYuT`Ӵ1nΓ(yh\ b =Ąt]jEdMؔ>/dF:5bҞ4+%]e]/yMd;\ ˨w'=zNr ڵ6 @ %#PU@Tqi>8A)/c&4q4,dMZNÇPnvPx.QG)3} Ƽ= v^nҮ?a~oRTrɅ\+SZk-!A7eYF ?Dc/hUI޽ӄ VǞցĠdJ^Dgc6MP-j]2e#jw(*2ZGvIyx\}m i٬74XA_#;Y;082Cu>+B(S1}YaJ~fj[ JC6-TRG~.T( yt~tmz½oT!)aj3ڭ/{8bDYul!qOuKji9/+ -T*yڃQ#(jv,IK,4TP6W!S+n 1@}HO^ϔfM_>_h|(_ޛSC"з1dž!c7q0vr@KY؍H'._SXhxȫފm!͚J'vnҴ)m<Ћp!к; uCxRew'NT1Y{.Pex0mK w궟!If<`RmKҧ*dEv.Nq4%=T<{c?<5>'Y*kߠ?pB3EL#.RڪVZ֠K(c>ʶѸ,ݛ*'kօ C{KU>Id`0my 3BC ͝y%WYL*o;OY5b!}^d}'w $䒙Iyw@xc)YD@.J5J2,VYJYvy}nK3̯|σt;.?9Ӂ鷿>uJt//u 4YoE ' q6}S$@0'Sut Gvk~? \s(Hxd\?<8BQ)Х=T'ZB!- ȉgj[υ xMB#mҸ6Z$2t#xKٿ {63 k5`sB﷝-)I-8o JhSޏĻ?UΥ@!ZG跧mrYW)(~`"6;E*<(`6\:PBT7H1 :e]Iq6͑~۩+fz Vj1 >ݵ"` spVQZ͛Miv¬Ce·0в1(F~{~M0{tU0k`⠎< B3>)ζlzAm⠂4S8K7!R# JB^W/h\z|@;wj=oD-|~{cMI!ywEfyo L"y|q'ZH^F^I ȑFUsL/NΔcN֒zHr Kf%\2tJ@R3`Ow|jUeL5tD™L+ϕ*)EP4N}4V;USh,s4IT.*H5ٿjȓT-$u6xS7G6!AIQI I]ztJ(%Ox6oܹX(Y~IvITM<2 חIcIv۾֚?@Ϡ@7πxk^v=PToN$[Yk'*T-aGڅj')ޣt,42L<Ç @baw~;V/f`L֚'H<$AY7ou|UǠwpXZ  s\:*p+J*/gIE8Y4ǹ"#  Sq-_R-D AnW1}~X]&DRYs*rsX`D5Epj0^D^a>fPϔ5]gMl4K 8ӅfrM!fscX7}xŋ&Ӗ ޅ!T5,ewN0#<<bBX\|wWqNL 9jE>k0d܎*T՝) n;WEú6:)l:`.anfۼ^MGc:=T@v; ' `ݮ߶yK~:Ha޶ 7U|t.^t>#@2U}Vh=53=6Lq@k|Tn )d1+*lWMI6t= VP4F}_PTC}4I0DF. yH{]y*-S*w|n%rf~bCU6 N_2*No6,3XI|Y_՚38!;V)rI#n.{(ıL$}{9,VT=Qs"pr1Rpl-!Ʌs@x’jw[*M&5PΫ{uy<1R_ق_mz#5$zlrdZJi-22D/#0`puYTdޫ-Bl\R&[V,tHh`OSI8Tx#gGEk׸sɺcSwyـ'DnкXRJYq,4ɜ- wc'`wKv2BrYvS{䱗T슖f@ >ظB*seL7#7"BjTeo*Kq\aklÖq,'^Ϥ&~4S1cώZ rQfK=mPaJvSЉZjWfdW;gA)[. rXo"s@S?7r^!xx)дDڍ`\a+uxesD[&/V<(l7L`l}^aˋEp(0%&#T 5P o(e}@s@sx| 0Г9I>Q8FިEgk+c3rp$w%tLDBjoBDZʊym1 ƒ 8b:9rP|H<>G,++i#ZDF,] V[K2y^x*OrEO"iNf+EA$QPX$\NoWRCלHU:BʐP㏐ `JzUGh~:`2 l~ !ygxRQijbw45ZarZa+ۀ7@6 }&;*P+@MZ"/ CnPɨKHPr!TYZ7 ՝@I"Ww[rJXe~U4@x(qd 1ȿ&e'hU4U+K+S!Nd'^EPrXux}% $;ufiH}bia82 +NPY[M_p Ys)ӤV(JpLsʛT&|ע>7l3Np9h~~;l_7͚T \0ԝ HK'۷ 3PbIw"g3\*ՀɊlIkY&Ϗo4]Ƭ#w?؝BC!͝ydGydzH1Ӛ xUx߼^cslZ;'W`03 0cb"s+`0&6`^ \QA PDDNj_u;k[+obsaGx ɡs:,y"Y;lCMsY,;Y$4OA! a|42dmlC*s]I4 &kϷ 8 e]g[. :u瓵BDTZ.vD)I#`d ZQ`c]h4\md&ko!y!@#-G!K #d+&Hi(x4T>Yъ&p{!ID3H8#v8Ŷ|N*W md #N}@d] my"]XXXGE$' aoQ괓a|AlX?/L /8xz}RBV|'5`L{:WΧ+Mq@@zVMl(|]YAT VBt)F mOFp/O!#$:>MDp #&S c$L(D2J@.UFz)U%}2lNq8$$8"֖ !$LH#zw)$P3 sOkd%wA!DCBIc"x-pMMרopx=eT!)Q,yðXr{HNVaLH2"4*Z-x0p3k0d=_|`>8Q{ q ;&z U 1kB1fi8t>Np^f28*dO^wp|'$$deqpa1gF,l76w[Fc>Nv(Fp89ZnNC@_ENyH@̧En ۦBD}☳!V?@-dTżoZ鬵.Mbl85u!xɀzRk"eovd_`TYuGY$fP0hd WKϟ}SYd|0r $"M)V<]jA]AI.H[੨|67r!\l;&:SdV@PvםVYQ#kfC g`ys#S(qJ;w@SN;h|J6Y{3x0g<,,2m"`{=Bj2<|Ux Y T{ZH*K%M³LD繄.!JPᰑV2pϛ˞zWД$v 1slB֮9;]puwh13璵|D@XڹɈp uv!Y{ Pȗ[-Ί&䏡xUK dG ;`i4'odٮ#kAS c)Rpk LT]dn rQWӇK`Hb$82U]UFBE|g%NQO@$zlnJ>`V4Aj yyוP?%P6X1MvmJ/Үm:tt`nS;1Pl:M&Ϫ; .TU[w.S$n94Fbxg*-'LK*W)C\ؼjnw> Q{Jc'SRx%lL r1Rzyr8S7u;tT\l\at@so3W MH`p@(8$?I^n (E"ϲHvxnCFy&9uŃDKV6³e0)>@N&\ADa# 'D1n| :r;]rbuo'k|!fwBg}\}dR7Tj֑QSy *J(39&47)ĺyLv~Yw#!q 0jsqDuH/5j,^ˑ\!]X*W 0:ҡf=Oە\ i{%JVܥ2W)4ȻR[OW#IˑycO"st#$kGMgu̬ХyU@>CYQG(tzY{ Po9i !-O֝ޔܧkz1^vAe$ bozff_ 9a٣S1 Ŷ B$C Sn>O&O |w(4-i# *ē0qL@/"keÃ.,STX!kBnsCg٩Qb.tQSFE94\e K pHy@w)s^ __My}okN-UtM;x L5GIA8ͩpήWK0T|¸y(|d e>?w.-8Ǧ$%$Ba5&CI&@r}nqޯSZV.yd)v/Fű+Y/C>̩_"44lq͌}G]XAw'HrԔ :bMuO`$0o3nbaO(n>բ X \ePn2Q󿮹XƉ%s#sR꙰eKocƍbPЏ)j*O-^Ք&Tzm+4 Eo-5VJET{X|"[ rmύXҨr#$4& rgnr3o,NA";rG>b<'f6̹>7Mo%~ro,2DvYq-(@''_PN3F.x4ؓۓIu ' D)Tggü:0dB0^8TSG1(Y&1!sS} <> &ˏ0+LR{ab 8 G-vUF68,2yP2NЮʂ̱nRJ%庑%S\Qu@aO^;HFa]QY )F>nQTzoC)$H\冝 WG Q. s$OEA('Od:<8&Rg.'V~ G3L ᐼhqaПW [ @ iܻSl{9-,휃;G aL⍡wA޾rFUqZM72% =:{zM 'kc]+< &MîbZu@XDy_M"f,=%Ţ'%ˌhIh6MipN&FᐡY /5iJ.ܼemل9j:chݴQkBMV#UUՀT(N؛k-5mAHjdWk t0J0c2sǔ(rOi'F>an? ;8 8B)G ϟDO0sg-Ϥ2$A7ʛs6瓹,Tgd׼_eq[p5sr5\9T'&5s jQ+Y@6E]D6cscr\ ˮ q( hBI´*!yi8ϙcp>/d2^z) `9W^T4{)i4Ć2 [ )LDFBe"+/hLDyILGD~.qk:KbfMʐ?eIn4e x֬\ҼeOp 5> +RqS\dNpfB!S <^b%k p{X.8IБGb.S0up̜ť~) z4>2K؏5-:0 VU Nρ9/95_f5&OػOMK3E#;0YOD+'nؿjFJ(a+n KvD[~fEh--20Ez$|?ˊf-W SաY~ɘ2~>nNePt\Z(#sa`1?=C=|SvQ5I B+M":dd/1J,5Z(q"^竮RRv6PXlH(X)֒3Y#kA?d..pz<"|ոa^(Vr:Gj(e_Əb%ިbҗÔQ,ꍮVM31XfGR,\p`^zu91lxN c\i8V㚯P01lɚyWV0FQaKLkHUհs{<&֧eow[EC K\=$^?t+)k.s[fPLRqO]?$k,FFOb7I[yR#^P4ɹMm\9|MOznlEggN*Ddmh= #N_\,M-M! ڰNh뭀&iB0NQфJt~}P$vc i}[6{RF%k7$~44ϛmpbu.S ל|®x:Y!l:V@DhUrMbi+$Te&k)ޏ !?# DFb(J}H֒۾iÃB ̓*Pc$q׏ziЋI^ah\Ӆզ7k G dklxBajXj;J'$Ŀj+"m܊-W9tŮ%r&koA^02Jvӵj#+r A9,^T? *}͂!x@:TҼeEs9iY:p2A:OH@t& :0Ç,o +\<)g/f3Oy2I4(?(-Z&umD6^qk-)M5 O>KZsZR@ hzu"n}"YTG4 F| iXrc.3rdtU'R#]&^D[4X/kF("jV|%Ѯ"Uz?#Z?"k| GsߚW '{9V4|g pWIdrpw84m'C֠4q]m=>Gpѝgր8ܾ:pYYc0T:=3lX8-G-軎ئP!Z/:оb@gOV`e+m EAa-P%P]XQdM6L')¹%>}ZN>4 Gh^K>zp{? mS]m8Aդ? kؘ*\C HZv.c"2Yp/9uYԞv۱za=.@k:4Q`K'0㠥G蓞Y\J8<5Eq=^e5j98TxYKs؊IxCiمt|u:7Usyaλ#z*HiiB!f/b? 6lpbĩP:XYYu>(N1-fYDO$TaTG#g>u.7Y VPՎ&e~9:YG{Y(\G>m/*{: $> 4E/o1-]v3jѡUE' {<7kc9:̤Zec>h\}r+|IQT 47@E*_NZ vW2bf=Nf>HJg0Ab>?l/T!piG-ar Vz?XmE&>/!WWi'KA/ȓ.p 6 uUGB+Tj109k= y35 "Wu0ݢ)CL šFՀz=tAkޚU" #&A"=b)7ɜ,gOxga1 iX_́*N)l кJ8i>ƒ_d2?tӍurԡ!n $8i4\D~I]>c(bmwq:Im bqJ 蔬*A5N$ =R8.q~bu]F4= ǚ3u ڪGHqDxBJ'Lw_s&(Mu0-RjՔRVuo1.eoSUhBػU5z@Dr3KO>ˋk +zP9e Xa>20#ex6v6+2|ҋm98Hj>Wզ1,y)p70>ճQ/כd=r gd.캚8J@wX,E$h\u䫑'%R{y.dxt$gf7 ;QWi䋄*',^>l7#5S{-zً.yEU1Nok%(ЀpLy"h5d {E kZY ܦN wA8VY0A긻*J^jy>ps‘cnmp€Q8&Hvo^ܘGgյ?So4ԒBO>M:~#)q V ('g>#ڄ/ U?3q6# p.MuwoҜ*ݜz-a6##w[s=Y͂A>w?Pλڝ64G¹nm̂M$sl t:,<˴,}^٧ %qΛ׿c94NΤG|N{Hs{YS72!-n_5k]t_((OaV[lpxJ8n6;;nPnw{A缴w(u{v .@%'bx?b8l\!gg40?+}Ưѵ[_kXA}>@4']zA#5G*r. :cA)i:zVV>!r>D-Ȱ$`dٮ-‚Pr*S|ü"I000m*F`x|M!] E% @8vJ#8CE&cXA.q@ҖAh-w2$f>P_`>\Axa h!+͓(~az0}_Or9LpǞ'Wbe ~>A|5tsOlds h*w(<>vIay9wZ!Ȭ9)M%ER{@t]X00Dq{rap0Ǻol qC.1@۬mVr7`L.QqzMc 9L#7௿CN3p4֮>O,q=fy*|kpHqn2)bCZ0Z.+WQ 9  ǗلGY|h1K# z2UQ2711ͦjL@,#bB6{7iB>̘ݣe=s M۫yDMKp:Yt(3aO>Rwd4\0J+1Mi'GdGjCL5c_ jUDP O5A(9d_e 닟Xk=‘\!F5-?b:CةD|<ۨQ p1k 5LPv;hjC}dե(Gb:#˒xpjY2g8kxywV v T<;wNkufv:Y{{!:ta:ݓL@)[1N1__H9ZhEsDpḿv\U"x V\vfDEy gW!L\DmhrI LUBʊ pzBZw $O>r?tlj+ `8QI*Jޏ PCnTx>mi #ʔ2Z+Z5F>OGּj~φ*44ωPWmb;0QV K;p1c@1܌:aڭ6D hUEȧF=:rG|t94#*pA~\$) ZF8f*,61 ]H8ap\JRrZ׮i8KѼΉ41^X|:XmHh$"6(Ά(s9ȧ ko+A B­wgYpd/ay KK8G=:/A|) o3o~w㪬۵x=D{F{Z͍Filƌ,mbCZɭw|pԻso hET{7z\ጨԵDaGq{PZaˏqNm7zjmno9OҴpH6Ci U$^s?4CCu.A\q׽򀣒fʳI;@iE~[ȃ8Hk$fNvp0+pJYF 'cZ0 F=tܡ mr a\> %];ks}倝(ȥ}g41MFBǙxZt"iR J@jd>WL>LΘGye i@a_CMJI(~'J> MaRq8";[$=TDOkGl_h *t}P¹b6Ld5&85q{I3ZA̙V(*#šc<>E-Ed[s൑ )t]0c*k/"J8Ӊh-FmzBR&ȷ`0L"赋mTVf0bM7Jd]e]8p9V gd ~7mY}=+mp:$PӤu, W <$`$HDe$qHNN}>^{BN&n*~wz5* D^ˌALK]Sn͈O @ַAB ѲM"ihbhhR!盞!KW(QvBz!4@z5^{ڤ/穢)Z!_HBAaѸ´$>l "u++Sޫ}kNDOZL+%]*` S] s^.7K'>fJ sJRjďe[=I"T5%!wPf}GPuNS1(iɂMRs6Etsě\UvUyڹ}̧U23jI7{KS敦0a$8ڬ 'tXc '#~bd_[>uw|B{5O)Xrs;,qky.W\>*#s7F᡾ZsP>,-lDe{rET4@m﮻)z~@nO[uDv`܇@<^~Uuo|PkYsʥg8ȏ?A8kx|t8*pB"0J<J:8TLc=g-+w&h)13jW'KS=]kqdw{" L2+>&[Փ EЪZy'zN- 2SlH@萠/0U2 /W,] | ̊d4 O׸=z0_$ O2@p p55Oss| U!Mo `)ґ[uT4[xwhgzW}F#̉s` RͨTďDpۧJ^fC#St+<(?i#BRrq-߃"CEerqt1_JߢʈBMoՎ|uJkۉt"R\4ڢ%&5x2XBw"ŋy39)"# |ظ݇m+ǧliin/!06C7*oV-?t%#MI[(BX H+쫰@|vjTf8mW {M-#QeUoy*(IpF,S@"E=T 3CY'XFY4N 5w%U$̦7Zd#64gGĩ9I >Lxé M7Äa\pҹҵڅ681'tB !k6T -d %My^Z̢/ k9M6M@o)(Y@%k !a@.9BAxK _ͣ$z? r˵VtҖt2ƒWE'*,ȤZ0YNGc!W`2/R?.c@^}%dUI1⵷$7RIo?̐y^ӂ|UQGLMF*QQlZ@s\63c !DA+^Bw*i(!Hmۚ΀ɑs{}>y1I r Ĉh@t@tW^iYŻ]38F= 0;9>ZTB:e0[un>;Wn߷Ʒ'ch#Me(50Mm!S_GnE4{ W&Qo`!{tλI b[[cI< i8MU%cmGDyRBݘNm,̸5I^2BٙKz ~T$E[0Ĵ19tȽMgUv 4:W/ER G>{afaݭ%jH( ):#QĖ h]9{skwAÚQ(mwn5OAO t+4=S#)ZZJg}1 i[(:2zV R-@#VykT\ЈuJtHC@UuzH{U! 扊5:G#>g&tmDsK-zO:f6|x[6m(ۚh DS#b;ƒDJwQ2?}fE:U!n}BFJO~ݸ8[)Rah&GAaFȸ82*9fmիZ,?hҼ;9!urDБg?DK]v+9[ * 곀NS'YBc>3OܢgFitb3h/}+HolބlɎi{́qodUoI$Jଗ8= 6ȃHJ2wU#8` BK^(z0*Rf-r~!%vA 9O1kCN!Dzv]P5TzWPl NAu'+_tTD<4.(QlÌ(u@$ԔMCw>nUv͸0H@[]VH%N8mGjOTt~i4A!nFZQ&)L0,J!"^{zROYK y3*?V@|υ?܆#ͪ&'C2 dm;٥DTn^`: jZ1Evf?wTrT\pn/U(fZqls npiЏSIa=b!JHr(\UQ hC=h,ɵ $W TDk7Y w \F¹ 0%">̢q!KGHt^">Zm! OrG $mXL|<ԺRJV'*oI\EB>YIߝv~u g:DPP5@T[m^;l(K6tUl4( CH;xuIP U, 仝!}Yi麎"X eԸ_oټÈ MDjRPe-Iy~ZO RPvy1/~hh}DV;٫[:$47@_} o,%Ajw ^{6S yA5I rv@-@]m=uxu' oznkwݱ]HmǒBg 뭊?mSx"UDޤc"6K6QTq>};ǒž0&BC͝ydWY{fK7/)VITYd}{҃&LH{L (B@êlBAd L*R Ke)-[{>},zo??i>dPkVU=gߴ3t?P~CvCu&s[O8j:ޙfgcvgq:A?>AwǓAp7~z7HxrrC7OA<^+Ixpv @b ?a?TBFtCL/>_ t.S+LO=,HS05 8s !M)@.p>Wկ"0Ktaqy亰zSƇ JUk&5^qϣkኲ}ܥC- ~N'Ak+!H\B}ΙVpAB`}`D+(]s չ:Xw^jYsV'DOKhxG 9Mbyጁ_ {"y.N$e`}[vM gF{`y%S%@Ş9d\3_Gq)okb);x܂e,g=g'}Qn;xco${no]zIp,@0hX8=?ЁO`wph5,hwIoiM%H=JHBDDxrv  nFD4Y<ĉPEDr7 1An28UC(Jt "2Aj6#1@v#9{ 4 ٶ8Atn0a90r}6"u(eRz9e"36k NrFgTo㜵l;{. 9{ Q5TDS 茕knⳡjeurQ5tMU/1ֶas^ !vy#h$2SGSFSŗhߞ@u+Yd\; i#٭Ar@ a4V8`gJ\rc|D=jhE&4Aɕ-W~X{]s;9{ Onٷn i7 ҇'tMrڳi˼ҝߠUcn*7?I9rPڞ0*Hh1zfmv8d/@,5p̝ak鬺rr~nm:WgB'bf-IpԈ|Sa!Tmh<उkLp i'M*qګoM@0̼[ Vt;5"%15'y9p*:38+K)+\>wȇf#WE.`F5@s jK$=r613JלpWhvZ LO&3SPFk:p5R(0\ qrXld$xxZNG2N*8oe_ѽ[H|sw:vP` pZ*r\iqe2 @4]R:[ y8Nr_H6;#;=̫ X Cm@2wjxAcvh~`DZo4sz-{qi駈 "gC1U"Ph[XK@B6z0]Ig0aS7* l<4nb,|٭F4\SgbXy9{ 2| =^>[v. \T%mMv 5*mKu֪{p5vLB+8HzZwfZ\"gf@ńWn} "geB>X&r[.]eO]Kxƥ:=^JRܸ؇u&U?$T/ԥB@HqOU+n_*o(,RK\^&@Y(|؎2=D^ KRKbsrPIp,] Txu9vU;Vs"lDDfSYoa-YQg#mdv."nNF> W4-C;ֈRb-uI]vܣ5susLJNz>Nt~|X.ВzkqXй cA,Prvu{Yڴj™ʉ^*&v $sՔ]P nE}n?F2j0CIشϕ#P\Yd_YT[~$ɓy*ph,C#Ok bvZD.v$ǤMԊ'󣢱g!o?'E-,gd:JNE Pb7he2J0FD8hr"n}IWI1!FІdx:x8xjGwq „cFF͒ݡ_"g2 f$7:c*shQבPEGZHglX_^[IXPbmR";)uFa0|^Ol車{[ M9hx1 b]xR=5a9 (VXbXD+y 99[3*[:b^NF\rNg>طتtJÓE#`nnغx8/EԽǐ+wWº#gg}P0SͮNޡwi3(|ƚb`AmU>_BE ݭ51Mt\+8#feKB]DB%_"uJ8XP4tl0=%ziB>{oF@m['oeYmZ}ķ#iN/wp%1W4v#nᗉ益iyAҫ!Mnl|R@/W( maF\cmݶ!| ͉dLTF[iK3 =?uD;L]4Hp!!NZ$z%LuK*aR.RY F1jJ&4}ZH , ,:I? yU)/luf FDݧ(q6V>7hؕ S{&`ܰ@ LPkLJಋ̇۰I>y%H^UNm멣Q9WBg2VNdcL @U*2ͤ&-X%1e!f*\.I^'I .{}- 咒95jvOlchL@*"e7z88~Ecwګ!Q=:HqVG@R UGV9k1Wľ)_ٛ` J.Q拺ðxFl11x9e \.@-**qħ.mNx QȕݹWu[ea,-D ه%@q(n?5E\wm^~[]nTO9:@:OG%|v&Z۪4"BWxg sUu1㞄(bWmy}!P}sEK'WIs8NIު}jLj<: NJ*@GIm&R@@mi֮jnVOiY(?Y(d=u%nIsjTsW(@Јkb( շ2" ]fUy6M(@8\rj0 Ģy?'9N $;b:'+@IG(η?7Y~ErVp|M"<^~wFf#thQlXb01? y|MVw9pZ#OӵJ 8n E+tQ)QG|cyH21A8_l$)L"[up6Ȱ`˩ qr0,ڒT k[ L7$鷃UwYTeWI^;F넴Ez&L!]F{_aaAHn D;m*[BwԺՁd8#_4a{Fl 8(p?Af&@Q؈|N "Mx#~Tp-\#4 N&4]ny pJ"N]B% =FLe3v>lDD4B NZ{  }+p~Y۲a$d\;µW^= wSXq' UʷzSg&g!m(*Z+8Bhe ^4Ůy#AlKSĮ3mf$dL:g:i5hdqrS&<{ʥӵƃcrMF@`|$XN?-@?AEG gO1Bb=/ j ޥ1KOB9 [kEeWsŦ9@eFl^N4d@pQw}J>a7ĵ_X.ֺ|hmv(* 0Jw&m 8 ,wֶ#Anɢ0*y/P^P \QHN2 p֋CbBaq'k'[Spw٩;< ,^]톤>qnHfW7y3Nlҡ6sJw6`y5Mi M{U#8ȓboLB"P?#BSp)6ߝaET`ʝ u[ҞM\GcM<=_qg?%ru&K' !j0j&KSh 1 ܨHFX~NCBBCݸKF3@S$ӖlAt73~Te<pT< /./N w9!vp%aw׮p =h:Ge:'%f(@Zt.L0w{J~ք{f7 }pJb~-b)_vv)Dl=aϴNi3&8xCwt" n{K.J5(D A澕h桘񒼩.IJųGb0SvbMN-~ Jи.)Lֵ^xFژCq&`V8NOk/tͰgNv]V3 Jl$>%5 m8A ^&k*)}栂,m@h*_IB?7bh|ήJt$~x1+luj^XM!wuۉۛ]KJP=8TgIGѫu␐&XOYX| ϣ&㰐K<9uKaʧH`^ lfOgSHWXf vl&1 ;Llg:oOYժK xz4˒k냓9<IoZP6ޑ=84ٳ` DtȗRTJ{m(\}19;2( \sMb^ p!b݄ W5p$JW#FR0(J;^a W)}LAoލ ,yRTnÕt d$eF\h|-4w\7,:MjGP(yc $'TնdE/҉W{M".@6np8*uS'ӜoPz.;tO%R}T`p%+d 8Ӱn*ŗae<'gG x#cMz\I落~lA l%[qIBC ͝{eGYo6^GȦQ!>ϐǞ{N1{1d}/^ '2X( ^ H(eIb,JR|Lܾlmښ~_s[O\Ӻq_#xW'_wP==|/!؄a /.'a f{guyeikw{eJvn_Y~UWN;Ww;l^>Yv:Wt۝N mdl\]pݑM@%hvݛz[_ 3LL-x6L1&z ienF %34kﴠA %p*h4mJ tAztw p0HʕYu" 0)r GyǂTSȽQG$prFs[Ѹ'iP +mGH"P.w;uw+z߾z+;tj809- "UC+1d&6STh[tB>S X2@0km ωnѻuDom)>!xVזVHa'6jG~tĐ 0BpD\oB@ Mb@PtnC*nC$)x]4#g˹| v,vo0 y AjZ@)8y *%&ǘ(fDTrj?9TECbϚ ȧjhW<}ɔ&`iJ UҬhVuJ&A$ڔix+T7Net4~fptOoA ͐}5ryJx$ؓ()ЊEy Mg$D|-? ^ZZkl77wW[f^^v> %m_%kޯ[^)wkGP 9-@Q պk(H8$ZB\" 1mൡ SqLƜ@ ]˩J^~ъwk1rD%Mq4n(P_kw$!g4kni (,WƵg`d? `&H@=;2I'?aMqCq|i) ɓrٸSėR#T(iJzj@qnTD~E1C.BI_L-,zUgXu짺gX͇SY]i2YRx%b듉?b9s稣psEJw40,PEdρa=zG4a$I8P:T8w:=#P*JH;5pyC379hǡ_ N^{ \:uO:g*pk7X$O!8p8-8:k:^۴!B9rIC)hCSh!>19Uܪ#iPS[VTVtVNmuz¦.|!peXNf>*~ *w`N*8l\)USP{UR:B+*! )M2(>цNn3`] DI.sS˄b'[)u)8`/CGtUK  y5Fh<$m!Jk/ @j&ZjpܯY4Uq ΘmGFnBX9WA ^K E|܄UmNiaQ KMp^ "<`2UhHb u.ߓ"o8$Zs^7M K]+q!&Tv48!vNuH]W VՈ@Dߢ 絡*^l$ezP8P۶; dI. 2'\,?]X:6$1HYW6VsT< yP@{ڮ-5msܔ'ɤns}6u@ RV0=wAWC>^aZN$O ~ 2a^m+g4vk0eZSP fT/a7°DAӱlfF*yiMDf&o sVGSg z]'zMkWZ촏z^R"Ҧr/:mrDr)1ϊ %7в"(eڧH *&@k5TKvs;Fi˲q1cK̖#Xy!C:]3f̏.Kz= G#NЩ\ȇˈx~4%RN"()* ͇v\o¡?Y t>ܽHUu-6@ .atuf'^DH0$)Qkt}YŴ1nPFֶtAU P"+'SHTwReBVҨ0ukn4UT%r 2KcwL몌'H8N^Ymr꒜V[mfnb^圞rD%|0=68Qf PwO$$1lT7v!RT)+"CYJxs8t!D4 uHL"0ivrCCuf~VfiX^;ne!Ԭtb7/ 9qV u(8"R y "$ a_A *k4 #4T/k[64 Dj_Nz ^B)?Qb+ݍ~i&WNIMrl4M[+V-B`q T[SW%LX+8"dL42DTF0H%cMX=I2ވXU&G9(?Fu[Z?&#֡T֪"#e[^;LhL~xNL(1!Dy”R9-TE;#b<@j?wxC5ήKg"zOXu!f Ѻ}@nk4Q/䍃lHյb]Օ!ѕxtpأBQ|ظ(^ rgD9xe@x\Ċ裘Ŧ2 tt\ @zH?"Q+u+Qck!YuB>`;LqmG-9!¬*-Toc{M *|m:l2Q9$ aVq$Ŀb1 m@e:F8QG-AI:vEl~zeҹ[fu2'>6ҳԟjox3]X#e kj: sY$^DSn~̺vVc%|7!=RBJ45ko VZ$(UJxm 'nP3iGLܪqB>,XA䈦H$@kV@a4k|6,F0kֶ`p,LŹ=`<S0`ԭQൎL}bͨ/NkY![)! oFwJن&Qݪw1/-&0Ӵ]:f:y:K@-Oq{0-1ȡx*[  Ct7`.<:nko`7z2|7CwYh2QYU.BRv~({mxfO<(dY7ܟdyCEX|VV+hx>Me1SFuy8i{| da2#rkĺ1u<+hD*F@;7NxcY<4_>~q?aJq=|x5~&fXh4R4]p ;32WrO>*'m Úw7-|ЪiAN+, z0-E.iL&Ϗԓՙ g2JjO_*Lqnaf8Oo Z^AH1Hb-}X6 k"= C1±_O?޹L 31J]5 IQh1Ζi8p1+LlYe808 Ѥڮx9:Q.R.Vn_dn7ʓ?1w"gMCW4ĩKߥm8:rGJ~ }$m$R*ے;!+^P*;k\WZ"AuYӠ0_/u!+2=Zg3'b1fh9=?PŊ4%xͷP ~eR$! 3(xt)s %aydgZj#<q_p8-Kd#2#1 DB0j̩p/$tHqwJU-Dr.T@B*73ㆦF=d@ldt@*L8@%~_]hP|^OnB?|rozRo!KmhfVd ý=%Y7Z |)BvE|rAm _lPvB+^;  q=d+U5p=ʹ:V?bkqWz"pVƹ`W?h?88jn5׆ԷAù="9[BuJP|m\$ P_P:Uy*^SW+|F:d$wkdPe{&èƉ$QŊ¹تXc;9q`5B 8)81b~ o 8E Y11o0TDyT$,`?#XsyiUa7_q/qs*7f>i+ৠ pT#ʐN|h>?Mcj <:XM7Q lhi>aleIExAS!&<=d\}NPP# #垆}NTQ75l@ ~4KǕ-X]:ؒSpmj(>HRQא mep(\KZn?ؒSHMBqpK]^?jM0 Ga?E>U)l*&^1N9؁ F>1mR &tUئ[n%a [CoZsGR5\!{^t(b3YYum@EBcʦ2,IyAX~TR8*0 a"dJ!앮Zs WDZoP[MǛ3ZIO| GjmiRng1'봚|D0Mq|f[[9 r7˟pd_dHZN){ %)ȼߛ#6X!#%26k5@}^ y NnQEE1ԎibdEKFc+cNS_ 񤮃Unҡ<<'ۭbdD{dֿ[L~qS{dK{ VEjZBo_e k5\J{{48׵ ]ԲHGlبSb;'?^H2Tx[=!"~E>{8u_nBtLo*Nj9B8߲;|_-Tabe}C/=8:\:ƨDt NzS]"* *]rFB:^c3|$f-OI2u^"/?޶%JvF@@Nn۸@z$., J:y|1[]HfL>TY[ V@+NzB[)75KM_ I?Q= rUy\3B=J J:#T4y@MH4G<,P]7vƇAEJe'vbIˆ,°ͮ VuT>S643E8B({&rAy[~jYp|M5ª0!M*>KBŇ)Np'2r(lghpj:](g5=^AnصXS=}K;|j03Nr'70x@q[Zc|Mەj3q+ 1O{4dԼu\ѠO[=?0:|{ם!/-ّolģ;x8n7v=wYjNjBC!ŝy$Wyc[)DQ[S=1&xk{l q{2I̙ @b $cDD]; D!!(QIDDΫΪ7g[|- Z^Ѹv3>-[W:K?>v;;sAϱ7]taڭo7f}mhw7v'N;:u:N{s}lm:[qݹ˷.tݎ7767ڎ/ؾ"+ l0#bע;'[jOPyC*7؆ǨU=ZBuABtQ];:CQ`t#9{3 p bLQ?VB@mn^non֥m]~,j_NXNttX{mom;m#ANz3osDGS1 &;A( UFkjv[F}YuD$8q.iN 4wvp 0]WJD/!gS Bg":|b㑳Wq!.f' npBtzFt^"ZBrv1u!Zͨ"j:Jn(vGUFT!P:RԮ_ÄMn0H}qt^M&8 .sm0FKΓ| MLp#("#v#(<ޒ"{9ÈO (N,Na&H&#&vZMꖾ!"izSAtǤt+9{rxOXsغUF2"E"gCg] D :?;fG2,]1RuIďBw'KA} B E ΀s[q؍ bw@7B )7`~dw;Ѽ.T؅qC?rԉC " 4CǛqa?٬NƑaIHAR 9T*!͍l!g.!M;/:Q=E,Kjz9 mT턻iM%uMǘ!L{  UFJ=< ۶HFKxWy2!/ݶ :Ea:0wka:(# ,6cBc"VȢ(ʘ0}4S1VOړSlS%8+ q]'1&8. sRKӵr@IpSѳs^y>9{,T5ÁJݘ4[Ui؋cE~' $r/ʩW)nRrAAO,=#iE":kH$W^xRB&ZcPQ#_(pDҿ;qxi@+B\nІ/PԺK`7=:b3frH>ec] <UwVWt %${VRZAAAbՆadF廬2:KY(Hx@G!ZͻWemC5IZ1Ew~YPAx0h=`3'ྞ瀄ˠkrwBsoY9鏐rD.W]ߙj mQՋn1-L~D+ Oǭ{ j\Y)zҩi.HsX*K3+ey\x 实Ɔ]Z!]gjŚSM5^T(|ApiYy6UoFM->ܠX)xEi*uȣ51k7*A@zU&^In4!z,*FB^(ͣz0BBbHuk$$yr YRv}?&;MP,8#j2۴vE> afr[&T\˩W]D8"bl.Xiv-mc"FPv Sw3" vNsHT#*jdZ7Rz~˂dRs(qi\ұBbzߋڜO]kBzB]{VăANҪ~ʄsp)xC; 4-- C'}}Ppݱ/ hJ*aC /:t='Ȩmc$s/u$Fy=QUeKJpTMtf_YN!Rt杞^j"Bݠ5=l3!}Ө DЇ[ʝ.[ͣmi<(]:hY2ЊTPyGiLH1=͗R5+'(c:U;01=MvKw4LTXӢu-;bJ}SWF%bRnNBFqW Gk/9S_J@z96-Yl 8:|ʨmF DyiIyv6'pq^k "EH>QoLGRTo\L(Kw92d)J79i&¦() bM5D^_⒌* 91:uIsI8 X.J,Z۞PDhw-Bza}{53EjKx>[X@4$ր\ڦ.҄YҧI `d <(a4J4)HnFHk}Ѭj: x4 $dT(uw dTMS޲dtJI]Pk*H<# _0rQ_nߐ:Al't0#DM8vuLIUFLbO$0M0!')9b)r_IvLXA)Z.IM/4' =5˭m=&8x@o- ՍpL> hBLG,:-Y|}']Pq׽֮O B" 9'gP (l7 Te#8t΢5Oѕupi%)uaB'AĖ'KJ#n)%2; ˹ԀUGzr#)"{y4MKq{< l#g!$;S]LJ7@Lp(d}'_Z60ɍJk"TV;Q6 N(@Ҝ*PH*7p d=t&87M:\ʇֈpE^oI ΏZ#I'K2]:GZnOfsE8Iҩ4XԻ"Uʃ ~q+?W}̩%AA%hԑ/K8{I Eee+L#lqu Qƀz YKM23P {PjV? FN.xK*˄.8p?r9v>V:]4blWJ* RhԪN4Ҭ;ʖV<vVaahR)=Cr4}1s &܈=4CvKyɜ=&s&zET$K.}C 9y%&"g_(K3$[P䋊-JqM }:%gVzr3P'ZD+8| 0H(Ԟ^WKoXuyI ώ4]#IG‘AGB(5ԏ>{<S YRc!"gWb89.- /:yq# ,f"}IdO5f5j`S I`.U;־u<&̧_B@KӰWVH|@>f= 8\{ȮGOhɟlhr: /(tR>)[b۾P0D⌁ eN$ޝODŽpn8ڼ4DŽ LdvVm5vm%ڮ&صtUdari*,P4~I6LCP]x=m3ͮ %)5,@A鑹Ir7&@@[,$g?1@ӻm;|ѼsuF,{Sx~W&^T@ՇnSA}BAK/[ R(>p%OM1ZqiT9,RLTuGdEF8BnWȦJHl+#+TGsr k_O$?S'n0 8 K8]yT!o9 Տh͚<%KG)T[V:zL|s0L6$0) 㫩F%x.aiv,!&i2 Q]RfmpGC5Uffu֢ @0Γs"5L\.8q I#{ G_EK#<&9fY(X lBn^ yq](ƫj84 VRް(@ST$Tc)ȋeӯ5+$\AV<^VN%]3 B$o yz*P6WHz!BAH#ۑJzOs1(9Mn6"0#j}m 6rӜ0mQddl% ;RYY `((^IDb6 q6B.Rub9{ akoГĴjiTῧWHtпՑ{1#4kivjz Yz%יIwFC=TZC WiTgT:&triV>iUsIMpx !(|K2ztatM7 ~nwM9S̼1$E]gB≫c0[.'ܠG-tV~6X P=ZF-\DŒr FrFك4}lpN,b\A,4Qx]ER9Oo! h)אz9s _ПC{qw]F]~}1,ǰuK1͙*i\ҁq vҗ ԰h.9 Lh\Cm9zP0y@J R+Xur^a\^a_pp,(A T 5)o1GT ><}B/pO,C?9){3l +%wӏsµLA2 ]?8]"6FN=;6>5"ծrMtX կOaXU+0鲕t?Q=O;39{ٴPH. Y$Դ]#Lԃ&Ix(8(Ƨ"Dc=~@?]RS">|Hs[,B%莖Oe W29)Y]#=l~'%Ρ s^z˂Qt`d43"xпޜOf..j^OS5-t8=^ ?mZtq t8]_ wƽ}>UYG|@/d#KO;tQA{+0$.5Abk@-Rz\חZDNh6,/'TT'o0ATp4H)M~r_gqτS4(#@ޥ"pgd  =*\ @t ~)sQ@_Ȍ$iOP?$g5X' h>O2k8tm:"P9;k8BqV-m4n8իtvr${\-VK&KVPjJ'Fz],IY˿ <๲`IG}l~H4 +ߪh yaMf RB vMM$/0ڌ*YZH||M$Բ AbXByBT~lWQ"&l#2Y*J(Qzp Bnz${?i^zum ͹ ٟpF,19ӜءIOwI#Rf/0iEӎxpw< _-ȯ@N?TVu$ų@W=Wq!Xe(or"uMZd='4J?ƅ6,l׍g^C$#'3?;Bi֢4+ 䈸~.ݤ$v@Պ5G{̏gn2IQC}=ۥpVAj+#bzR A(p-\!cי4z9HK((#؅.lV C@QٜtQʀOt)EպAf{R۶fϑ1i%\2|^;0xިE6F1]{Z#8 Rp*BTBὃ$Hlj"٭,+K\EQ+[>iI+dgt}ɅN~waheA.;z} =1E{9;0{aOˎxPHۚφ'Y !#Pwafo驤LN\E$73ru I>0FB/ rшIP[f|S#_g!9{?`\Z. !-ٸxtILs #5mPNvSJ$HN'{,R6,)߹e^.!-Q,EvQA'!(KXPw92AXTX7455`{&(PFnڀemRY_ %'3X>?L߱MrUPg79 ?,S6 N(HƋ4`Oq$r//~K3 i2d2픬>؍jm0&!g@_Q)_Q^ "5g@#)wFZ@+P?\өha%73/~Ԏ}GֺU" /"sF5B(O|UY"B2=R "8 >" :+gc"zQYM<EKu!Zwx$.K2qfw tMM TyWUsoFnr#xo,r >_p)0,N4_)aIaĆO: }B.tU{߳-g ` Bgz6#T{j]5:N}\ogvs\!vnpP@;_wڃݨvtn8;r}Eu9V-܌7'jg hV'PVds=s:>|Yeh@FE4j40F/!gx2@iX:T)u Ȩt.ENigi=gLA>JmkNipⳗkh<nάdP`*o7萸6" 6 @r;>S = / lDފޫ=fh d%~/{Vf͟gA,w>i2lji*XB/wJ|+^ 1TmkVˮL޻asV s8Z䆱DNb]E{2žbErr >C$p8L r=$<,g Hރ AMݱ8̃r$V̊^t_V٧t`dSBv* 3rsVa`80Z(mqԆxcd#(,9TqFXqGYCsԫs$X@|DݒI-'f$Xr,uog-O[0Č~eWk"Xq\JP |b- Ŀ 13Az:^՟2`'"y(X^nAqx pŢẗ%IEQbPċR|v <"($ lJ|:q i.7>Or!/ I^Ħ>PuQ&.=(NAJ:(~  h)Sr>-p Li&ˣ&0/,P D[ԃu 0 B5%cuoAq,#w,㶩7cX0G/9$Sމŵ1eE:(P|ۯVk\4 ׬K',rbD<ݬP_W9ryW_6 gtP<>s2NM)U%vD,6k ˀwxy`]ۮ\"7\9Tf.<ܧy->@V@'֔ΎI= xĒ*^=G٣9Rp8J*:{v+*mJhW1+JyQM'fU(Ѡ>H);z@wtoY$gb欽S G]#Wq&?.D%vft/NVDI9 .0" e` ߧ˩߶RH5@3szfPURprq0%g}!ـJ;{76v~VSyRsT)44K`1rq 3#0 0IPDvFʮϧ0M%J~k)RJGԵ0wmk P04 ;nb0ЛJ!F<x =i;U1ЛK1? G܆"})RgK:81[q0(!O"_r!Dӱ7=:Y%]^3@YZ"HiU$dάZB Ni87.NNI %o4|TB¾@ IȐtHo]~$$#X>׏H89| ,v*ح&8{-|1(by95\M H[S|#!ēi鎸Uq86v/V̆D@hJ}!|CYdض%2' yktF&f)y|>WcIth|Snҡf0sqn|ҁQ\N$ ۋCy%KQțJ$5VHgei. K-V.*ZԀ%/?Nn׃.D~Q'5\dT#9ǝ1!|^T74p2x/ ϭݷTݕ7QCr2gd3p+_*^C|8Q "̃@(\E@ Oǔ[wPkDyTTd HF}Hٜ;E"{e Ą([8b_pd rpݮ x #e_/@zwNJ\]MD}=Q:AHd"jPQgX >~lYE#vF\邘1K|*K,Fh>yl@ki_@nd ~9;|3'?qm&B{^A\:zlv›pL`-8F{Kɖ=.08bJfNR/mMe,R i_R[>[M,qվ k[>1Qe$YsJG7 ,X,9Yur&c{ ƙ3Opa[JVG1qC %aI Da`sY (η1Nz#+*/B\X$ q"mv݄1u +p p?=4d)֫vUk EI2KZұ<Wz*W zcলv"[AfF"@Hv|{ͮ~44d`:fdmu~P=󡜧㳳eaT;D~^}mʜRFТWgp a\K[3qgRO G7eZ nꏩ)4mېHH$m*紶(lFגy/ڋE[JF|>?C%?O6DD:ϸU77m3|\_v3'Fo)6,pk2#I0#Z)ף2can 7@0|QeA yIIx8OdsvQYa`a[˶zLl.YI 7t[Y@3.E@bLx\]I93ٔ%}YkޣeV%maf^7A}[k|Ru!v³k. 8^$$DR(֞~.kfCrz$|KřJyM^l$_Ls_i$Y7hcҸ횦@Og/ d/-NDL$M`iYU*4oTg=Ѣr@߳g:X#!5>P4B#]KhhWE}hI)uR(sa9{h#!9ńݶ;KMu1"_ސ'E~Vu ,g }pDꕛL.0@d: ׅ[ jϪ7rBA%~o:|ve)X*iP[wrV {O!>IZNxJjW^T#:4Y8q)NNB}a˅݆kHL~:H`*3uLFNC J/oX3AdގEU,y~F́i $g_LOZh"~DQhh|+17\y+'2\~x6o@AmRYsy4Igs|$jKU*C*o:HoruSBB6SݡEg;$PU 4h08,N92k$9qdj2;m0vLz1Q%3*;ٮ3XdjWd\Oe(Ϟ4;,Cd 254mIl5҂!y`fIHl9rKfOQCug o9Hl2KW @dV3}޿`B1׫Mx]}q]VJּD̋A%UՋV},[JgI6UZ.T8Ke.{wW7~RQ$#WLtw9DJl33ۻ& 0V;N֪ZyC3vN؎s͇JhyTb>ZzȒN|p+ypO" 8|'#\'y& # _}>ǖ$>o5T84b懰u˶k'ݴyCTR"fH՟];>I}ZM\\Qg%xK^rboҗ0Ӥl0%?ǪvJ7,[_, ^y`[JМe]CSU;Q W"(ӵuC.r{@p$҅v.ԹQ of% nSRn.pw7>WMx34/n1 ]*mpN@,^@,~)|m qzCbiݪ-)dfMÑ*w*( Y| ̷RTN|:|-xW@4riVi:<YA+*|=Cx\,>Ӎ4c A$4?k'>!oU`t1gӔɱd*Gvƴ-[0d᠈B+TP?>].-f% &gTw9R'l!N MIUW~W0b4/{tU%_"1Kv ;Lf"Wi,aƃ{U[z^ å)0Z e&yC^& $GnMNHϩ _DLX3(T V*f㶗v"-u*)i(Ҹ<,̒4Ο*oaH@|r 5m,K6450j*E R#rɶz`5v9O-Bp6+j|K q8hobL3Z- %Is=>{Imc\jrdihZ-eʨ(]V *zqQs~7{[rfAZVY(Q!HY8e^"c1 tB%"տ}nac@?o3I6អLr7ULnEޞ\EvǗ)| 8!2+*꼩|ި |#}ˇujޤ 9u~lVR@SaP ^ /A?'jp3GtL%Ӝ)5ҕpNWO3>,M?|$s 9E ZD gӴ?GmMD7 tlYA0X Y s|1 U9FsƑ;T79\7uw:F& ‰=RCB_ 5rkCg!ruDhsDZu$2QRGU6|-.QWNw;Fe('rP]ikΪ2Z-P(>iyoM+iR[bkQQ #JP\թdǻXnOY% rBCi ͝ dWY{D)-\YvY~Wj{7yV2 LtFYB@A_"Kb%@d Q ; -03L!EYbK"nϹt߳>g%ʙEFG:5 ;{9}Ε;;k~B5WWo Fv7|α9K0 8a0 'ӜQh6 s?hi^hv@$)^D^ 6H@u*[Is+9(ši\Arrv҉&dP6IFh@G}#0GtrF$ 0<ٛ\p$9dEs9 M"ҀsPU[kiѸGiP.NHR,ҠɤIOijbήvo~vwm_ٽ,9#lWuWtS"} l%i`j -Xߎq@AQ4+hмƖ&A qI3NC]$@ POͶs J.bp\ O@U`pQ';FJBss%LspxÝfXQUٔ8_ 8ϰ!"(E6C+ ̋-a#Dao eҭk K@0}AEjUðо-x X˳ ?(vkH5lCߪ,A)"4IS,Hyg%ܿS0s0ðtG D˹s ໄDY={F2NgyO!@&ǘ3“ZtWo~1A.yMςѻoqBf03n[k40fgu;km,)ͱ&aql耕wv穑R u ^,{Hg_7'G6Ka]rh Wj<6CdSBG&YFP.>đqN"Z: 18.n)`H"4 yN"&qT{iCz *!r( 8F@.rP:\γs]pDpTa0x5i(m ]",&OD(1].Af|bҝQO*F~UG)l^2u6D9[^i 䩪ؖBUI:ȩ8P94R\}fP$؇ <ޥ] 2.EbJJH =saXpB6pdK#76o\Y~lۖVA5\ ̃^8`&t( a(@G"pSfTˉM rjb!䓧M4x`otS#CFfZ$K =&ІpVQ` iKݾ+ 8aK==>o.N 9`k"jUZ.RzQJ`ջ 4+E+[(Z'X\ z0C$ڈt8Zހu;K g]H`7}Ž[P+d;BΞ+ EQRty:9{ N*> ֯iCΞD#:A@啦! 2,sNHXLI&+s@G܁,30ME̩`T z>{]q/9(MDiJ:!rQX윛" hAn ,b[r-( B,n>efd,-&p;T泾mP\06Hg NM_ 4|)re Kz3t?Xx3|e^z9Ey yw: 37^b~1?(J>@7i!z'%!Al{66V,5m&h5-j>:ZEow^o/FŖeJ Yxu@܇҇*x =ݠ s X J'|MHٖ2;  on kTK(е/rk l|"hK/dZ 0##(V- ,ȐH6 Mns!t8xS>fgAVב׻I_MFឩY0aqzbuN>o%gow UR06O{VW3JW.@\վ}S+֑y;Ms.<) ;Pnhp0{VY3֥njN<_'g$~m%xTVN7ImQMq?A(V?D^`M*D(dz oY&jn$7eSF{ PjfZ"s3m*]Bj;}\-/B{ͦX-7i_2N!-:ȧ$:@n8" Ԕz"{QLjt~@Rs?Aoz`%)ulo!bxUTAkPsd>$[[rgHVoF]'zrtүm_M0*9SqrYIz1m,γtxZ0rGn_|a\]p:xg[}jc2ǴH&!vi+T VU6@u#^ݰE_#LܬQ)KLK`QZASX_H=rÜgm$ĒaQlphߛiFiTGb@Xehf{5UMKizs >dP TES#ͳli^4?C>nM*ƃ-ԾrZjߟiބ5>~7'xyQ.eb1|?ʒ/qDr0DDR{ ajo{M8i<ga0:a#ENGtu˥7Ax'#}DGD.DXj0ZTNsá MeF )hZgN^܏8+\8d* +n鷕eI#d( *'CC7$x=ٔy2/:IY*L;1! T4 -( J-%Uw9"x y;4 %uŰ,k4t9]شH~~g+nM#na0 Rԓ} y>]̘xW.S\uQDSeM&u ?dɢdO~{Ȭ4\BypѢ(GmT im8t>Ep[\w 8!8%0LC5sZ,wLa= E^l9̙P'b"ꎂ1ؑ2Z䀐JR:;N r רkHF U'pB!'+t?ү_w&ᆵCUw_|sH<H;D;gu;M%LQ=wHFqL ҪʪG Cxӟ++3w>DU}y8C}{DJ9L2fiH=PR:ENPI] L@5t'$bNTtAP?۳삙u&QGw\aq!/(M-)9'fãrITÖI@RP#gs0 ^/@O\|;M=q h;TBh |URcDmĉiGi6qL idw Jg7H{Ȑ w Hn뉆f0:O$b.aq"h&%4C*ҲYW6ez>S.jyt{68aeiO^Y%'Z ƳtO/kBS^$WHLD=7(%{Z47=kad)Xm4EH?dͯpwJkI X2r] b@rQf}9{ucPL JW|"Tj7[zTQvjrsxARoxJYM6$a7ӕa7'imQ5M!ɇ}(*(leN~zU1V. JhK ]BIl'{> -}'~FO4jN7!B6Ϭ<]ggeA+~oYEu 3ۨdzKo\j$).REznZ2-Cl#90dLOlY8B*+M8AejiR6D]BE u<!"ݘs ;kZsY*7&d+8/l~_A@IA !]{&>zrEվBr1k(Yf75XKW/ltbBN 3SDk` 6]"+ȳ-h,KyǨ F^ԇafG.}iDj*y$7W٥a Jt߃ .KoyqxΓ>aZ Esҗo=S/8Fs+aJҮ4 ASTGtLBn9xW"HIo4rD-5(Su?]گ_;a;C>[/Q>`Eգ/8i]N$1@^_xY7=5dţ XEKIJ sN"MɖhKK| uMKw781P\^LP1@ay~9uSbf hϒE~d$@E3>r4% ] &৲BCr ͝ymGY.Ž:j2XKtY{ Q%2+d!U ((1.hQJ [R)QQJKK$v^t{$5U餒vL+uZK~bH=÷O/=qU}|zu]9E]mxmc=ߚV6l݋۽^DX}w{,>l_vK^nʝ#W>%9 qa+*lR+LP0pr@l><҄&!h0 f p Z4g{F4^`Ofݢl C\ugF4S _`.Pމng$&cH&죐}45g>4g)K+z/?؅n!h $ 1nߍAsT.Dg]/~3rކ]715s&4 Yጼi)ck>Qs >{ O{N̓ qW)s H0n3ZmlIa:1{!{us;>ѼhܠM¦vj"Gf;V|7Pt0w V|Q0v}:E%+i^n7qY 0%J*|63!dé۬U\M% &~ۖA/77 6Fj0Hx2`ކb:dB0[vf{5'7L`w<1T+gaM(#^o6AAfcO ʘp ZelZ$) ?D]I μV>x= fJ~{. Z}^ ]VD+}@ȧD'ڧ޴qߋ>qx.'ոX{ٟ`8J=,nDWGKo!g Jo7- BVJUUܛEtͷDE-C%fˈ-QdY^2lպM'! ^V 2cWH%@eol|*= KQE2̘ 8璖#0dwE)Zjz3nKe# $'L4% BQ#a}RܥAG^Jog V7_uN%#"UhET&W0hD@zr)>NH_S>KȓMw R &ssx*!KlPGܧ`g,km}QZ+Iu&ߡR4?E{f g%CȾ +mH1X 6V0]@qa0*`T+mS*ٷ}ߏb|X+-o(yy-O3.D.g ^B'?ih vM(@3mƲUa*=# 5ePEAO㳏k@&qBG6`ڤGַi^⺬&=xHYN׺O]b_'yF$֥fC N;~VI O*P6j΀C}&by0#dwʁD?="AQV ^I t2~{B):Jٕ(Mro!Γ޳@ra.4ٳsL]&7$LIڄdIH؆9gǥcg1pNp:][Hvչ_ *7"b UmC@s9VzGw7ahI:-鐶_0b:ɈaƎL`B U۳`B3&b=XQ4?ۈpiv?\:8eUfI5 ܖlEh. I:n$Y8[,|5rJ5a<6ckPoj 2vupP3ΪOjz)2 pVQ ) 3,Ǒeo R"x?WWšēۂ!}yZDW|ĊDq3KDȏ7^@v>VwxňL!9-LL0!(yBJF6g DMGP:8ξkD|i_mJA MR/-Ϫ,A/|m"WQ4*׵%#gK~ 2u˺Dq8+)+D5bđ2 }ReVhϿ¼9J~}D{PT="vGk d Eت|#NFR#'  ~Xo^t(ccx֬=CX<^}4i-yI?U~4-:ZM0UOT ~XMnZLbZd֢'B:]hQs $QTHmm ӼDUʡnO,!\u<'Lzf)9k-tl-mʬO=YaX;XxMYqԍ0ϛg^A*LPP k<+E;M(#FrS$|ղuҼo6/V#1\^M?YUy! ؗgy^mh2<'ND-yr6@yNQ*z2$jI 9U|vv" G"ň#6t gdDF.je|u} v,!@ Ղ]Đ:$}Y*q!R+ lRMџxT*Ar8AAi6Ab~F $;4At:$zHoMEr"^o|F ,*N} GкZFШگ#Oإo#{XyP$>C,Y->ש5-.Za1k[hmSk9 Z٥ac@۶-o`ٰt) NL8WuLZc1NA8κɖu]nN*3<]Fk%O ķA8#օd!K{gDÎ)jVpB"ʸ؄c5Q3B~{ tA4]@xA6nbYĄ)b^Xl كwиܰQ3ؘYҔ VYڍ>i(w v R1)d2D,Tĝf|p}EѠ"Y 9m_U>i#"ܖɊдз_%$HE h>T}+ٺ u $LA>?Q(0j9( 'hDtZung9SLVqs5H=zJ6xB#+EjY5sH%C/! IDZٻ^3QDiJ;ݞ?lĆcKRDbt<9T/%~Y&k-AƢxJ"2jK Svd]qI&5Z=Q8Z}\}%JbWibES?yvq 1m6l >zJsh̕ p'ԁB#+`G KƩFdUN|rG@3OVIa8}_SQ#"?#O?u[ Y^]PŦoz\zngךp`Ј}2F]~83v$ m&8~ĤI.pލniuvI,?ALTܓ󨦄|FO3A6- (ub)M-|dԵ&(`S*eϮ3"bjBn N)EΉ $"ٸD 1e/?PMX1u]b:h`\L1Hnݵv&N f*^pTPaƮߌ $d4w=Ȗfmq@靖v,8ӟ *afnhߡ~8Z4veb6 O G+ed}y}&m?a\Ac \NG ӈa|vܣYQxa#8UީZ8l5,3-s5}'qʶfĚ;&T\!q - )TgMR:o8r_~!b;ݢ:&QHΨҾ[D.ZwY뗩uWnEߖr;:-7#Jyn=>7\ҧ)1.YQ>q}fE>ij%Q[dDDyQ8^ֶ+ }GF["*_!4r⺒oO^x8>HU/Ls6M$\Nӯz-%Qw6R`N-mfb:=7Ԓ5ʧ[I`|oA IWUK)ɖ"ݸ` Pn~6"椖IxlGW]":TT|7>{HϸfV_U,?Mg:nm)NOiV#+ mnœ+Tnߒ=AneXA a>i4q3'n3 218eG|78F-)+Bɟ]%;ȄcvfBb:qѫa >{#,JI Iŗwyp3TUV{&&4^ĦaY6:8=#_ZU,gsOe~t5o2kLp"+B_jrn=|yMW)ǀ 80bny"SצA_ E8Mn}¬NJ:vu.}Z Nͫ0!^.eiQF+R*_ 1gxQFeC"2yuo^}sOh? ngKr:cInʣq'D= X?[ACWa$x@An->Ȫ\ xHzA[8}ʷVP8v P@i AIВn-*iފ65 ڶif"+ĉDžզߢwS&Hcld/њ(M+R@2 X5oB{cƭv,i78kvg" es਽Ѷn>gC}n ?kD3LUYv4ЕK6B1_52Ͼh6:M'D/9~2/a::^f ssvkCdvGOs3Ѥ3.bg!iN}asRz|XԺ|юOv,z*oۮ="TjW0˵'cENEqfNNYnk+(%Lx,W`~觓pl | #8 #ިRb?1R:fxrnT 8 U7jA9o*GR?V>*)\=6KXA[JMDÈ_PWyR)TY!\RH PTiCGEեHXD%RdTY\*V<_/F<&Ec}4٢HP_(0Fz6R(48jqS|ح{"A@"S\ZQuKHG]PLA$(6 <ʀcHV %#YݥpG9Ч\ udڳ͑ex߾'RW(q=RƳOզ#\%OYp"YGd8#\)vFY-ru7XbOnS0laވ^+s(ziQp(iln}BVTCsdL_glCôY|&K YVdGѴi~dp!(?ikN# @m0z@ nGBď | >ˀ8`UUTSJ胊 5dUxDCfg4#b 0,n)f[\G }}(S`삂;kQ; O\-H2gO` l9:ޑq狱Hq-vGAæ ڑyAgᔢYZF Pd2c `Q3[O^ۑfh~1P4ٷX߲9b^XRw0[-|ۊvNV$ChаƉ*ϟ{LhN@<[ (!xՖ)t_6k A8 %PTA6mG{Q;~Y5LBC ͝yW]i԰DżhP$A~gml7`(`oiwťB"x)e_((KTHD`t:D"JFm{s8m^3d>~#Vh]݂ٿ[W?/L>q}/"Lvߍx׻S^8hVksosqv{֝mo776:{{[N/9zwz#ΉdD۹'=nw۽dzW=7m=wZvN'w Z9K?8i6\ 40H!ʀn="ɇ}(́# @# }81p LyFݾGp^gsq#4T. YchL0blA'"8[i{%(Πn6Ҹ"g7BPaFHmD{=jx*QTWπv,@ÁB<[N-v؇91hs EtA*1bz E!]|NqP] .r`($H "#A&Fl@!4qcc4evRa6RAs!HTJ^b3W+\$"1@WZMt)JStu =<#g`_Gk&43SIhܔoW/tDda#Wl?De }xC uRh8(]CQ;ԉ' gH@)19;oLH7EFhv%vܲ4Yf) }w gF{o{oqhfgs6>tzn7N=vIJBItN#q¹ '@!:F+"\AD{]e5 2ktv|rcÄšRb*rW"wuJw"J'g?oE6Gj#@'a/F[u#rvʆ B-vN +ًmBkùmf@%к ]E I 9][c(+,A 9uf$|_Û}6Lq(|_},ILuRpH ^B8P/ |QU $D.b.RGyR!K. BJjR/{t+ B.p Q#7Lmh|>[U "o48{0P6v 9Ά(œ= оc(n ёJn'gSWHFRHfA7%ήm{595qE<hb=4Uh- raVgF^oS6XVC /1<л3b!gа9[.ų8W'<'3`d#Ƙkޠ? g x<4唪$I9{DBlnnoڳS5_ m|w9.ϱ]$0\RFHd!87XN7 %nq](9<+LH q.kD>5i9J@x(,Mǁx,᣺>Jx5%@|ڈxQ*&8o0) 8񂴈#5wJ9{i;$"qs¹X#'AF8eML84B#T4/$g7Ā+ƪ{[y19{ (@I^M,Hר1x9Պ'0INZF yC0hL6mh a3y\ٞMBgoaG4rlG64>?獩$XpTW #ԟ] STQB%glCz3Dx2[%>a[$#j۾NξlAe&\/zIlM~Mƭx7|j/V6CLC3"4w"x9 [IEOU8np;l7mD5 ¨ȈI*\+#pV!"OE#,'2h4wDa1c&uPI$w$|\iw!s,BX9\F8 ̮)LðWC9L$M>i1zKlNe T~jJTǁfgP37Pyظ2A/8Q$sYߞ$)h Q:VҠ"z Sըpx Hs'hZ'—-L[5#,]&\͏4^n: q~g/i?]y|!A1(¡#"-- ]E{eG:rz8eFl]5@VY[R83ktH˧|p#F5VH1Wb҈y4=U5|\J(sM8w(k. 棉׈x&E~Ն&ļuaY8Tmp"YC#6V>9{ `m"99Xv#\Ti]6/A;0>/is!O01=2UArVL>"? AnV3ODX\ItP$ #"%Z=}_&g ӯK?̷W ,$ D&~# &EP{<S>]9a#+"+R {T7oykeLy;Yp[29;lCKbjz ̉ Pi6ݩLe]:PZGajxt.ϣTƜg݁5eHҾEoLe 9|)G%l7NVǖ-PVݸ &>JA.w̛~ &&V:BHVgTUBzG|M$P)V^y?9{ EFuĸ }^݅S&)v]O@2>_wԑxV^([j>1ohʉBďKT6uȂlq"n\}ŠRP_Wo ٧mx"IRch^6ˀ(Oy3L:.gqącDa'P)RU!\'rT΅f#ߎzE(bйy}=ݮ &K V ~7Si̖aST^Ųr3İ|FwhXNNrjbn|{HDV7_KÐR۱#! co7&J_oKhr" >hPH4:; O0r\g35f|+N}8S@?+Ԅ|(΃_rA>"nekz M[l<إb6H-I1+St] ,hЪ[IF4m9@$rujDց@-u8AД<ҼloPFF%bEpfGSyVytW%lv 4_RckT<;4Whq`GhvLf&d=P׺ʇΥ- ]u@YoI$r/HV(8{,#(V|k}f@uqH%36P5mgO;n{>ڑ/ {Z!9 rBDwT#.lګpN^>:SDeTa α֭S$$zBTOÏ};A+CJCYngE# O6 xr+{\cKi"Q 1GBs1M/㚖F|p%Ŕ^ _\4`$%5[NBy4r'}DZVM$H:.Ce ricBF<MF*[H@].@]{yѰQ!E\E26es--Fv_!0C9 ÅSPR-y1 f2q)l6\]V(빸æblegՉg{y &p{M[VZvS#4 !nլM&"Mہs@䨎[;T ȫLº(#Xn.?FG_~~6QL^Ӳ)s|k:͟KVOJ>ܱgLP"uMΝp.×W$N m;b8qzigɃ_(wJ%0vb| F&M J1/K hTbz2 <P#HN_z IjpN:)W)6_[,Ϫ9BBıНtŷUW!.9{ӈعS%P{Z߷Okà 5q:PAv 9aA\fnJBn-DaYW1]VP|# eZ8́^dե@b  "OMXLH,aթtzx^fSWȳ7s&b}uSJk'Zج!HEqrkŜqV'Tb}dLBW{$UH<~i "rכA#8΋D8Ip5 9ҧ H.;@1 KJc<Ά+~rt$f0P!=4U%oseb%OEʞ xxP0רR#ڮitcM|t?.ʚ(F K$H^u."qحG6Y1msq#8r7ʼ=}' $ mqU9_jHG^14e>ŔFˁoPmڕlqE6n3kW3ˇgצ\JolHkCxk Q"E o9:S 687˪)(v -R Ј]cϖQQtI@5@iVp&<ȀU9ggo;u`56=L Bu)R ){uv,>eJ'bi AiS+r:KN`e~6_N h=P AVT&Eɕj ۮTO<4z`_|?#`D,sXIE^*dY(p9{ Tѱ<)ɪӼ T$ X9<쥱+dӹZĄxvvCZd &[Swt)n!f:598?w79͂ [A^$t,5XVirJ T"OBΌZDsM;HHW~`WHBJK2Jvrv j)Yu`$'T4#|K$Ɇ*Y*> hX6"9 8B7$ -.MGڭVl<"2yR>hY٦mg5k48(fpgmZtK#<^(fy-贑f"Jݢ)pA8jus+4N&z lY^H'hQ } c6p8jFBuT*(Z~K8a:kpPSҿ!\hШ//l\Nf.qN>!O|QxL vR_7eBٖyeV[nOPݣVT DxT]UWCSt8GޔIC2͂͘GdstZt_J^mpU:,\Kes7d.(k"qw,OgEW rRs_$9C 5xGZ!s ISQ綶gN?HQ:#  댑B|rVko;4u0.g=2Tz)/ ]ȯ:WcTDYGL('.v *,^R]#R˒2 [&YѸ3 S0r7I&IZ&)QX]pNlp0W4#e¹b(p:p4aH̜M"NB4n%Ь/Є8TZNӫēmx Pr鸙#/I]>oX .8\.mmCkNJ'Q`T=³DeC_οkeusyK;ԟSQ>I>hTm@/Vk]jO٦TW4.2B " ~39~&p}Ze'?BC"͝ $WY'wR5-ѹU@>~ &Jc;O H%<^@Z /A4X( $$ !ReZeisvL RܯiNN84ni@Fvc=vxN. {z{{C{D#Fs{nmtu^7݋{NX^9v^w;]&N{Qsnr.MvOyn#> /J/{9h#ќF`4y2ᜆ\" 3"쁌#p2vsڙoo7-B4nbӹtnw‹v_wd\!Ǻ;nb?18cP9Y9UDcB=P"j"u& DCt2&Lɤ}iaYE96VTb@3=(eFL',Զۀ0yX9" 9E>d'j|% Եsc}E&P?OJa)satjtoFd59 !"J~p"·H>ܱCa w DCd4 .8gqqp-<)L-\`<0aN;$Z M_t"9 ><"O$%&@|7V[V]vCXD+gqBWioGY$V$w]j.`YH΋!H#9YI%; PdLU8\'yG6ϋ[BlɋPԋQ"݈7@*Yw}#r䈻}h(j@`! @jyttRE  NF!,QLAY*k W ͚8 rC~,{=@π0{!y8jS?Y(SU5PI$kEF@̆pl!AW*ATDaW Bd5ǃ*0o*z@ `TDegu BtT0dTK{:G6{Gi#(K}'F%?_D=#&zC%4֥ %~E!8du,bAAOVH^?I15SRg*i y}UE jA+t6^P3^'ui0fNRQY-45 FiiD[<~$y3^Ddj!C7U`z?s! 7*낺Qs\ر:}IM"h6-|Y1N=u-_uOdo5P!wp 겪JA# [V%M8sxՙѦ`a ݈TǵGu,Yw<䛯[L Wx TVAd"qܗ3WN?K2NȾ2]YQgAvQ.8Z΂J5*s& &Ѹ)n[@ʊ$YnwRhR2<_,aA]zBQwY=a:pliKP g=rrID.]*/W),HV6 :I?Ddwjw0j'c&UL! CeY?LPnYϫ.QŝN]Unwro$'i||=nV}{EZ}E)`U4PS(oKF Ss*J]ve@g<HumVkFm%!%2߄"ԈHMoHU9=+ᔆG/F8<*x,NVcS}5Lkʄ|*T]}[I{ဟY&%Pdž`L--r_m|cɱ|Q~^jBBlM rM^o)ބY! b,ڲ< mB|r9Xy :ky[XT4ߠSQx=&7KV>l4BK0.rBXo =,7پ@p.Ѿ3Ap^̘bis+YRfrA=_ GL9x5z]RO + KtO z\˞qq55'Oph k9I$5-8OAyKD6ۇ%' K J#D6m.qx?QcL0TGDvօ\S\sқeCˆ (G5G.h(>JS-g{ٝ~a5F 2$M:%SFk$M;J^Ѥ:D'AM1t+7-g 8j7|yU Jz]0ݠ;ĔxA^d=[>n2xi`&4oku-r"NzD P1&<@ꡁҒ终6Mܬ?-ktHHvp>DS{6*ZG 40}6Q .恚V̎I>K ՕVʇiok@iu}X(bL LOA[D m$$)yr~ S*HۘȾK,ZetQLů k(s+{3; 88Ӷtq @ O#Ec2{ "r%/WMqpyp³]\a+),vaDi=#,ccWIy2c=-ydy|2J8ٽb'Ĝneg#_ |3k|{3D&4'f󀤜ůUô` Z&FqupޮvLvP$~dT[wD7A.уњ)؄f>=g %M+߉Cib;44z-<)ԭ:$W`A~k]快8H*Qy8&1 U՜m%Nn-r~5CVv^P 8;Ms̪Xl:ZN<^o ̋_ s4E+ F5"oh2xW!]|CRѷ;&[E`M:|c2)"02UDe%&zW}BREOvfcp3U8;TwBSf\(w=|FV}QϯRȣfO(#s@G(VRvwT:3^tV+UBh_Z#o;hvѭ$Ё@%`4 @ͥџdwBsT^T#y\_\G{(hyaFij˓j}.+"fSn~ī}x?(x^ͪy"΃7i6NIq zoD{HbԪ=uChB#l/fFchDd/34GţDU~?=6^zMF@Z#_RmlBxU,oo7P #XΛ]PUS R^1̸>ƪGL:&/@qB35=aPYU \!B~ڕt+Qd''yee7%}Pa <ɓK9*0N)^$ Z)s ~ a-l[z`fA~p{oشtDŽ l=n1,yY(l ͈:/Ps(jbNs9RDn uu͗z:}J9)i[Χʕ鵯YZY;ITq#r*iԴi^*e_!^4kr]?Pߛ;S.XG iM(gbUU#y޾WQ-y"Sڋ]3U\o MoqR724b;}D&Վ8Z3 XBk";c3ި؎.ɓL"JA? 2CCxU~^euYO \8ݥ*.S,?#h:Md5EN PZQ99lCws >a)j[)9+&*;3~yvKw^N^V[;z(J6)}a{+P1`6mP]R+&=zJs lDwYzre{9Q"utˀ}}b3#Z>J!JOgB]E@eP&u(mpV)hWʁ{{ Tޭ"c"<0M!C$gucpDGd'p%.A8Ľ n!ƛ1G&Pk&\t#]k OOZlNvDv+iE³QHw^hBD>7Ulx97E:8Uyفp]Yz\lCfF okޤѤ1"7VХ{Whi˪6 3Ϗ'ݒ=Eq"XE|ٶ 4OBd4 8amيEN_`]<+r0 aMԵL*o6y[ w<;y)T\PwmJ0VS/mS1dd L-̍0ZlG{eo]p8.wpFdwjW^f1_"%9N1jm}klk|^1Tەֽ-\b?mF/b$db8;1^Q^(A0Ox\;3>Z|EEu|*0yZE Ny%*B8c j +h0)2-kB= "{ ʕvd5Yӎ=φS襠ٴyxEuvlSTGAASw|TB ,X~Ƃ)t+No6 (iVj.|i訊|N.Ī(b#@-E1xKxEk_+Jʜ҇(?Naߊ+F׋_5#'#LyF-~=&: M[Sguo;[v}ivNJsTU'g>QUaTf퇣q~Q8]}2G8UuW2_)J Ep M&:*z3dG{(/ yaX~*#N cxW Q]G"FZpݐsa?kE83 7gfY8qѬ g"* a8,&h"#+SKr~ŰbُV 4oF#\%?jH9N`aYzX**;4e-I>zVc Y+{?S'ڃtXCqρRT* ~D*4D8㮫f;gCT~M)PlOEKa*8[cvOHH51,rSZS5S 9u`ulMԏhjA'>fӖC/JD-:G8AKu޻㨟Ҭ^t*@6-+8Ybni&~W-6\.Gz|<h{K;7mU;¦sVْf|FX2$rm |vE@cЀlIMG<Eﱏ0(>=?n<`lאָ4͕Z^IZVӹlcI76\zّ'w7nrsxHwcƑFF?Ll^8v4]:q % `HN{*fxHc My+LpB6$P+(SR3Zߗ ) oA`1"r DP) SHB:M6l 45ϵP t>EF^V@1C)>a5Ok#<#qOӚ-tAѷـK]g M]^AFPo(DεK)H16Q.Y{ (qfp Bi^O^d VaOUxYي&3"LTߠB,`}Y{ yXUF!L` &iܷڗ,&B44PﱵO43qBbE7ǍG*qt8o|9BFΡ{$%Lo$/?r٥G66NgcNGB|]L3E 2 $F(?&$2%yhAvۀ8-4ۧ +iB3s8US.&Fw! T >2EHPPmwʖ{~$4?KbJ  ٚ[u{LQFRq4EvB_'k0A^sx zgL;G<7qjb8=:Ϫ8g0Aa7jRBE0FB*|^Bt&"sNը])&xL`) BN.L{~G簡x l varx)RS8_SpJc}'y!8fx^N}CAxpgN LAT0-P$u? IyPO@ >pP>y)Kc!4u,) =gѵfMݔz)Rm ϖѩ($ܽ8kki٨/y1Y5vxHgԖшᚬi k +C`&kwpY{))`lUHgg=t|Q8u[qzxqqLoCmc_8+gMqI8KY[%k6 p uj, ,կ5@>gJPojJPؐHM/ IFif_4.LԨZi/!k_1E#% C4wU+@ѵs${wHH$M'uaJIJUqA^ްib8 $BՖVݕCKpWj>hdc[1 ijt4.*++;gD6nsutT(g0S)gRA '}~xYCVLP?B$:hCB!F@3"=;%@ ˹ZnT H[Ruj7&[cPѹMB8ySM?I=DkN0H%GᛎhJݜN.*\ L1vn:Iw WU 1vӵ铵+lh@4 -Gz) GT{ް5;,]b꜄IUdml/vN4 :rq^RItYc"(~)yx@\3Z}xo$k7Y1b +vѪsR' *7# @#ҌB<qѲ葴;jͬxfaDN$~3Y{ "]Yn&8R5Y{ 9DV6P7Ίe7_q-U됺{d4aBscTn6i? U;9%NY~4H G{L㜫73q|GQ⬹c0PԷGjt!Ҙ7ͱnXDL@khevyep7bѩԯUԉqş0R8QtG̛ wpBu owTG8#+LG-\] T`@uܹ;d³Lch(TR jЊ ]:вh 9SAv1 htAC W'e}{"Y369#F>mp/kRyP u+!h"TسTY籁zFMUI;S]Lii&宫49Ū> %Qq>Mn_8D*gZ!/HX ؋7R*ʫV4z+qV.$Aeܠb\{B {B8PQJ).eTjsq+@SdԚ-E8^*wX@ m1=1|p\rhSЙ6<'h1>C3wX~+d64x U'F"=2YrUE]`2 [O<5Ɖ9J&@}*C]/1 ^1Z<HR8Տ+.Hod xpUvf$i!b2$zO!NXV8&._1 ` t}H$So6Š_ǵ] ^4O%kw7[7N;I@O#k7ahE2;-Iѫp&-j_1-R-b]bzPw"]eտdw)ɨv*jW}HаB'DXcvc{Hk{sbC ax&&N7g]ؕ.9c܍=B͍Y"47`u='Ũ-@r@An6qVGnA6g;9n>+$҉ ,1Xʧ'3&4K-\= P.HdOk.-a^RD?E^g 9;T#y+?M+4>p\eC2 WP#&kw+8!.dt09Hܟxс,FP 'hILyy7 r̥="*:Ip.H g.ÚyӨL%MnZlCk@O삦:{%S`i"  ݡ~>|+HH}O Zvf$:X~FKyb$QgԆ*  GU;,pKk&i.KMRBą }謰"'RPi2vSizHi*X "}ЈhNDq3IE/[)voIcq?agFzw.pCB8 GhFnAp<ϼ:Z ʹZ1\0C54&kﲡ ė,MiZ+2?jלߦ;>n#vqHt G*?f"o鞼8bDvD ȼxj6'M+ (M¶NFqʬq|?́QQ? m7@'^P@\DAY7Ya][ߵs"as5D09J"ڴ&~\ttGхŖ~8@_㔶6Vf)ؓ=zNՈzJ1dF"Rn"oW"5 r !  HN%k5&U39e'F,\u G;J>fQ":t̅8YffA8p +%OѪy7~·)qJֻBf]]*?qT hHl'1U q4Y8ݙDCjn Y{ 7 `rՈ %\#*Y{1VRCTQ PptDpț@s g;Ue?^]kYbka/N6{=ΒORu縠QutxnSbcj1-};y8 f68wtHDLDµȀݺ.=n3+CIT) ӴbDAJMYiv)0Cp/R^Mֆ6Db#_9 BP%PCgH>TmZ-r$)Hpvم䧲s ٽ H@BZkn/ڭ8N| &o8jȭ0Wk:CtjLTzY{ :CV+(H+9Sڇx0GOC'h-TmOz4; s=G&b˭ .q>j - (|nlGUE]Xp=  j%Rvt&QXrޢ* p A_8WXpY8A-+. Ə)$wW`(< _Y{ -ȗijTz Q,:K+uDeGM %O(wX[T':PG؁(']9$dI;3N!7 'LOϪN)L[-%.($u̦jut{fIg©J9jC̾Q jt=/Ih<Q~3eS׉Ż0s]Dz o:6xCI;D $c8Y;YyFg^?N2wZP΅~Ҋ s.Ĕ?PA-^[ߕۉ`>*qKhX_oL>y|єVN Ѩ :ٴ[LmBׄ!q]{݅7TNk"j;B|%c-&R/h{֫&B:C6([ ~x+AD(xZnk-ɿNϓ A[PqwӼ8`4͚nr)2Lu{DL䉍g$5AAOyOUK :pyWP$BnE8"0ycH@?G!i#b xw\ H8>97c܁&uWZq)Y)PmKdBcvyrA܁C4X2~m׎q}6KgO)C?g8஀,9n8ڔ5o/ukjUfӰ)k O6EKnJ%0NTr^zv8!{ghg){K9͋[sfb{\}ռc;dHL|>s1g&A\8EqqMRm~щ66`@AIfWs՚<Up!47*N8o&k/%G3gRHuLJ%+.tTqٰmcc oЯ:x'0M;r+*,<ԛ)Sc6tJ{VLklؗ$K D V< B8*< UEwCLIdyMxWGF=[=+ Na XNǁPdw YCV@/8D-f޺U<:ҏg [uj LdVے8aPL7Wi@֎`EУY¾ꊀ~Zx6]hG P 7 h׭K*>i3 /#k,'>~?4't-ϱ -ĿNI~j,ޒYu#/n}w7bN 8Xx )Nȼ{{B_0Fă: G"Ei9-hGp>=B6cg{%O>F*9,y#}e3G0S>>ZJ*wR+% {BC !͝{%WY'52XZA/Bws'`nN3$3d U1X b< Q $!@)P RZVӷϫ{Ι{n1IVmWwzj{e ]>2^89G9>/ǖ!ao{h<^Y9AݽNknk[;^zG/Gޕ^?=O.zv{#^_^uUz5W+WJr<>ֿ~0}-`n'HUݣXsjLz!EvF1c' 2}Y[&DE<%đYOfSa6CȋUF +-*oU4;%yF>ʿE' hL>pR>)נ2Z%go408A#vvTP~xu쳦SmG' i@! Fԧ4 }R:  >jH r9L9$(Q#T\"9Pۣ- p:hl@QzLm|9{ PVDZy?@XRЩ (,62PeO&A5:F689Ļq4nf[t4&gO s nO측9q*ӸגgXA2\yKEB x*Ni4Y("nBF|vP`a<Wɩ(ZZ/ Ra*Dy0l~ @{ z*pyQTy'$쥱t&:rZLLgU9'dwT@/ g-'~@0mܝ%͋I+P w@/AbgA‘/!N8wߴ`q<Xm."gZEBM pd(s༈~r 1NC( GٛmB <н P)Ol"OE# lB'5d>F6<'Ll8iKq@INKt$ه, |'uW!r+"$z N8VkJ26.}m BYzC5BZ8|"奯h#}K&)qgD13g!Y[NvR.VKq[tȜi.!g38mc­8{I NLT2**cbf$n.MgV%ª](hLWz͘=P)+ۅ=usqf} {|O9&}X1d7iź[9͖;OHE%8c%pֈF5RBybL+F_q} ͫ*A s 12'[ܟ߭JMqi[. s$&ygM̊o?gUr iK֝n0u@z!72 V$(:X\XSWs?1 VpZ8->VTi+L"ődv\!!IB ٟPѷ1nQK9( R,v^Ws{$:k.nN|1yW&XդwI _ 4y:kI.H4|6f i,I*"-Rr>r)nzZH= $v#I>8=:ۭ |l8FNukC4X+_:Nqv]HSMviJ kF~I jN<4}‚L"Qp^Ig3=W Jζh1 p38jW'nی 80p,_J$nh4Ӭ 4450HP"2=:z$ m8Q:!5Pr@,@[.݃1y'LOlby8AfgC,S,`e[Sd[rQ+_rFZoTrv I^j^Mf8'Je+_h)H /un188 &!1NZEAK_"O ZĴx$;d# 6L !"%K 0gZ #ʵY_d]p'Uv)&4Pj}J-J8?J^e8oPPȇ[qrZc ^>(W2DQk/ U(ZV%1gE6j]FgOtG-~ǪB l*ܭ cgO9 .!|jq.Y lq+oǙ!J{o}at>TBpy~oo9+J@@_TݗZ*C|!`w"4 4iŒF(-?_GoY lI~g4ӴgJٴnBM'8UŦPϠVzXdX[?L?P.r|CǑ&Rhڴ|6;whU f$(2zh㻌"*ð6oUݖ4 eW[!Z.2?|~ժh)8r^c3pPkjB% g3Ɖ895qb4EH;d]jZ`fCVS57smDOeԙ6yfnuiaQhR`6qUW-GqzubfS&QFΎb<@YwVohR{lfCI@Jl:^?m#D!SEΚvքxwmb,"m./QEu}\}&rv<лuW)`֛F^bRGZwk8p|s)U)T#A_LK16[ &(T{~@5cN6] ͥ~;B5R(NwG\z9NT]%=űWPU7hQi 7ָBuP'7 }^\FoF",iSh(漆GrA0mS9_GƵti`@0nV@X,[ΩEt= G*aBOu 4enFBȆ{pC$/b /F hCPl (ߍUn? 0l,^?S@ 80!~)yb1‡K^GY`Il$+ޖ[IQRGI%ϥ/Ly^v&-mYISޤ6yb&1T q 4/Utr9220;<;΁[J w}mrPq.p {6iupVՉ+=iR`<lj[Rl$0O6ʪ؞!& 8<0qJ!zq h&"o8ZUf^h!ӝZN훟(~uBFɶ$!ַ QLV]"ѱ^p y| U<́}܄;έ;4[;72|r~QwY[]& _Av:>`5CD -v]]h0/P}tCLbu%(]}xTnx)4U^ؼsG/n)Ax*Kv)q"g7ẊDㆢ8l,5/QNUOH!yb@nfU9^KB#boh64W=a_ b&\Q!F +&qøk~Tu8i۔bH\ b\cV^G΢NΞnKS@¹Bj~Mx9u+ $-@/u GԂ(>_iQ+)\D˯^kŮUHCj/R""?g` jD@RH}} (v-QA;9Qgq!v8e_vGwUA ƯplUfg<#l}hKt?ߛֶ8+ IH] T,G:ð'pZ&D^r0in&gO" '8soLrkV4p6Beiׁ|ɡ Siuꠖ7j &gQLK{lfN+Y˜ y: 0LC]= P/o۔6( R VVVD wim3 "0vxUc'64 U[waχkc?gmq3nN+߭4n@;!rF+Hfn+TKUL(,pKuG8y ZW&xU;!o7Y=\&$uH/F~bn\zΑ"iRDŽ>жY6B` |PfMOR=Hi+'[ <zNg9 ')JU ~Lz5|(CQ6PDnh[)g"cSL>'"t8P:$yrXtk"M@=hՕ^: ]O+ 1?ѷ*4Hv,h/npS~d\i@UJ{g*B}0ѺseC7t{ [H؆)*SQЌvGWKٟZᄂYO1#08Wfpԕ*:#NpG2`kO!T7!VqX VNxSuUm+~ɴs 68z,m+}1(_mk  !,iu;@(C5"5Vޟ;q"0R;NXѬvu@'i}JrG=q{IL}4,CԵ:|웍GޱW(}1LP,/F^iJN!qr@hr=V `\dpr G(|Q /-ƽG@!ᐧ.<΅{Rۦ+'}x]bخ:eNw}<=Pa>>*/nL4_uR9{Yr|CN/yUg 8I|q_V5s\\[ Ϛ;YK3Uܷ{fi]%9PjwW-0Y#jIM|vL7Yǔ` &Du%:k( 3lt\T{#BgifbŨ@jŨŐ.U&R]:0:X,yC 5z_xyȿO^ᩌbit ̿[OҢe3Y*{g#_dLByzǽ) l9j챼C囏FV/9Mc: ijRǒ{V꼾4 <'Z eb"%Cʐ  ES/Pu^[P {Pr{ lvTT:;.:P:)B{O S}8oqZWO&v; 1VwxpMGS9)AY6lZY niv EK]l$.N^0/Q05|TR*g4|FhҒ/!B"'`k4]n{xkQ3_>(֩٭HQ9kFHj*YgZVWss=Pof[_ cN8l^:-][ps&0ņ6*.0_p"b e֓ǚD;s ..A 7M]##ˏm`4n. r.giI7lT9J>aLqVhR#kB՛btr9ˤCMZgp]~s}õQ_n/sJ\W8)+/4&}/{Hn(t#TjKR> Q$&!L*P[) WY68X< &q(yiܻ-tLDOgH1ojO.S{ژE8"3-qxJa^i[KWu<_k IAQ^A[98vʣLT,{>FD.i=̘IN2 cj_@0tM[&a1M:>ILkE<$;/z@e ݜzS8c.l$kh9թzݞ~q_$njlK<, 2:9{qeh9yץɦ4o xϩlD- exXVu< ͦc[MzTַهM]V4!omh_L.MA7[H9I{R Vͽ9(?qF۬0]6ޱre}°!&+pK3y:5CP$L!*j`cdsABSjbC /I64Q@auz!Yf_WɆ8Yٛ8t<.ݲ=&Vif8Pg7"ESErBC ͝{eWYOgIg(fW_L;s{ol"P@3n}D)-+0 ZigΔGh !D5h]k}^ZٵIoۯmrﵾp'V9MUv:;O>]6^pb?]s`omkk`ΡNg[]uĽ:Ug׽縿97͍xs#l8߸qA7/Jں)Oz$F 'S/<95r$a[) L)gT5APy\PʡΉeWپ.?GȔ2 ps9ҩ$r3hg#DeTO鼜f6E u $()̙+ 1"& t}βc\v&0lh R AE*ZPm紩”u`:8\}rORͥץ18D3twvQ8~cHnU*  w;`!B~ \fo+h&Q{v/8rsa/]__8sݵZwwh0`q 77dc3>?> q)0$0hNC0VUK@(bt@Xw&Hǹmfsl1NNp>Znhy <ÐFP@C #sRiq< v[9IgkxJ{5ߛtpƭȩwbm"G}ۘFiMvH~Up.g*`_?VhfseGѰ>nTnšhb7(mZϜn0a\.}Td/5Ե :#R!IdFHB=!-?h~&4\x ̖pPv/HU O_j WK46s0>O t~Id 4c] Q*QFjo^]HO#7j"n"!s4Zh1J`dz&}PY8D.VKUʰD;8QQ5K'[P8ĀK9Elz6bԓFw IXމv%@YA.s(#ǜJ;^C~R= vwt [G|.Էnv D?G]T#O9GdՒW4_CEd_Х 0CH`R4z.H7a@Ly.PPiĹNpvGB\dE4RݮJχ rpZ@7a"uGl;y6L ߑѬ[Rlk'.=2 { }Q`a5Xo 4%A P~U"f!!(M.Ck BMh+F/n4krzə]Yb%0jmhἎ^h0m7;#8ko(F%-J$01ˀHnBe }E!"{#.9H!MTK8AO.0T FM+3i+: %[ BM :*<a !0 QGdlD *uT5 -T&v: 7 ' ^[.Nqs% 1/!Z-k ?@domWUȫ(QDu >Vdqz8G8(Lq.Ĩ:gotF>MHar-5WjIsDv6/2=K@a:Jw>={8@p܊]} DimO.Ce \S0 D65* PsK\qU}ب4iiDVua1Jd獀5_h>=G>R"u-TRCpj?GuY%I/R+ MfW ;ۅpTewG}_ͽ]a.v,ʁZ@}l^^* 7#{etIIsn~:Exˋ{h6kZ hY;u0ہgTvGE&\gFMR5%k4 իk};Xs&B(yHd/280@5X!ZjcinyQqA3WcsSprȈ&ຒUY(7Ü* (†2./agU*dGvv1Xx|J7mGPٝF@!G aop$WaձFs{ﻌh0 9۳T|U~1٨egꖶFeq?DdhA Wm(Hns~緍>mLG5aEȟ+/&Gi9P|z՛\KO>H'hs\AǨ7?@OW{2U_zJ/;9ȸDfY3:o%*$iODLs+ZY!q6YJa"]](qY웛̠\/}r@kp,jXJ|Q/fWuh챜by0b<>O%uF vZc u6e*X S!b^maa1_2@GC2 I$b9 -\H&H߇c)H~H"|ِιMPSn5WLރalC+Ca=wUC*ͼhDn#i(!qZq-bm×@T*fj~Ē~S T38̧%+t88$Ե&8wF+S#G&n+vaV睢GN%MQ\5Dmˉ-d8AF-F>}8ehY37ŏ|n`^6fiFi`e[$*"q<ɵA/8(7Xu֧U >o'`O^"PM5WsD{!}Q{|(y&棯^rU =tӵP@DEY0li0n~ r#>DvX(pn10V`b0*sT`*Dc2,'rcéhԣMĬx[ؒ %M0nHҳ*Df/e_ R5 9L%Lq(Ku4VM*D  c.-u[HE/Dy Ȼۖ hbgON(pa謤U5nD#ỔrpP} u\OM-"e[m/*ϊ.?"]e:-V[,9^&*MniAT(e"Q[񊞪(nr/ @AUV^Ѵ)Z:EQ}yE\.5T"چԟ % uPlhq*{^ Bm0]LdiώveW΂[q#>[ѵ3p-YA:=۷0ÊDTk_l'r ad 248hƱBfcF~!ǥ[d߀߮(Fwck=HPj9˞ ^muȾ }-6g+5}f3t3y?0< (Y!R~i0TG*Xhepzvж]RG?4<ϳ4Unz2# & `{DN}f'¡NK Lw;LU2|?uehwob?,T:zT5O T|QG19L:@Wz1Vt-H]VюIo yBeGR*oש>1UIvpZn7{~8_epV.AR$BӑW E,VKR]ny.wΊU5e$.uf[He|'wa]TQ},ܮaXؒ "f$Ok %8? ScK㒖3u/F cH.g5`8_e!ϐ"5&D8!$<.C!od[уCJT4$9PЪR钫7 yW}/5Cam|]gD^Pns)ʴiy0wkCqIߤ=?pYU\C7k7}I;p:> #4uї|rNΞU 'h-s L4ry{'G .&/B$qq=^7Z0ʞڥ.UE7|h%LvtV5U?Ԝ9$FH=8EpľsH?85a}F/.P};YDs5Dp?߀Dt56gaX+ỹFc26Gn1׫]E/++ct~_(4;n=`j@ @:Av$ǽhE m*gQ1jާo#)QvJh}!5G׼'$RI+b[_`(@tP6J[zYZttvE;Z(gr4{6A5Q=Dbo{ȟ-}z# *s pn6DžQx <&(P7TF%42U~Z7I7:[ǐ-kgđ,U}i{ A??TBC ͝{eWỲF1ī//`g(9m>g=kYg6s~ݭV^jقDv#Mǯ89?((Lg3cɿg@NGZmoI;۩:^hvޥ~/ee ;>HX?W<;tœ̮֓pAngy%OШ|~KdZ@Pj`2^xyp%HC"73F<$=;-+Qъ'hK!rC}5'5D>ŔDؔPM- (X,$K 9VPĪS ckΦM)zm@w4Nb"{1QKZ-BZR*_So}*T, PCu>nJ?]!H|JQQc1ӫsy_#(PqpsȾd@ՃagTsR*?7&DL;#"`#!,'}?OSN;0%Po@xX$Cu!i] ]Ad28W0%:㞫4LX)DicX!}B" >Tv)PEOܛu%-B@˼iKhGù]si%vET2h XTΊ# }}nw "\펣DFd-f%L%eOrD#Omw=ֆ'%ЉE;u/(i#I19uXA2";e\mCȦ68I,$(*kX($DһDTHMh(b>zI$̽n#JľP < $X?Ĥ<,hȇTt<Cd)xv]) USM"{U(vq#Z|J9}Ԋ'-6xγ%x<}Ϡ Xv\K@"}x|wbTT[;t C"qG&ϗSH,$uXSON{+TEg_lĂMv>Oa["Xtq3:? >hA/Rws'ܹ $MIj< W\vv; r#E,4Qy*hƓ@b>\~?Qpa`a(1I"{)JAT.S#qX(p80&l)Je|~ų@oWNEǑ)9S4bq\'DN)-VW@MUvOCB ˈMPusr NJa\3:*3#cջ_]`ԉ&ݱ-0G .:e![I@| I wYESI뚯ko( T >!:t P cWds ǁ,'f8MqzbnRg0S Yi亷FuGeDֹxr*˞";D`RNKUQ qH 5J.-% 'bJJMRD1TTp44Cdo2 T=S|݆]#WTVz6-,z!īJj{cڊ1:ԪآERN"mr1wza]%Gz N( 4Uh h?X+4Ft^QG"kllqfu3p ֒gH} 3j3<sHVln$ack=Î;$P?ݤuwMVHn4ԳUѾGЕ[K6MSgoߵdoXiݐ$PmcDv M(N>\T "{O(F5<[.UdPA){d^q0?MVQwt)Mg}#yەD IZ cEGU%{Pb/9??#ߴi&Fu*ͫ O!)FT Pf:qnj5Ln,\8о$r6Tt\ģx!2&۬%9{c)Cy"{ MѬg\2$/X`qiS-̊M "yVkf:Oy7H~Jig_ZHᨆo'[VZB AZ;Lt[rv:/Y>env1 =ij;EVEԡBiL~A5;8TEg\K^AE;%( ࠐ)WӚ>.B9c:-ƣqN#f Ĥp`y^>lxW.tjomlD.=٬hEy^J")NU耰G:[:=,w`XdE c /4zu1JRBAy|mpT6`y^kUzs6W.m 7QNgBMѰbwNMt&9P<`fXM\?:iD6A]4xs|VRv 8+~bVBPv m$TX`H@k%Hj+drHd/7)LN`ۛp$(.UQ@dn rD~&~~ɵ~א0A:'6ǭs3{c, |\x̍^ c4pkFiB_éXj[_8\C==tR= LmgPA/՝AU郳Q Y xN+zՓ(f;t)pΧDHoHL""0ݯ01-3ߠUNjbtZ3/O'OS4,:gE(Qw`y_o|2}DKƥw/tQQ1Q&mO2>c"{ӲRxZBPob QEF϶xF*wƧ>~Ua6Z2MdrV"udmh/L`z}f5"{.zUmlݳGxNQtoZې+ϕ)mΖ xVXfX6cSH Qw`< 5lw O~ы)kUtDH1TN/'8><^ou/l!'U+W)>!\Pf M*~iOnmGbsEI`>R{P#o1:`J;)2cժZ̕Hɪ o;SS8A$?C4^Vqec\sO/}KtmVf`w"mQ\( 2VԈ1PV{E2:_'O%jt [GSյO4iԇmN5ڛ9T <Ś$Pœ6땮7vzٕ6DҌ=$lQQTӈ|3h|D:9TNV 0LyQ:xyPLnT&x?!/ea8(vO U<;9TMojE&JeZu]|C|;_u nk;sae/JƥDֳB~=WH'a|aD0٭AkXhv:\ 4]4BnjL?t|  eUBBb7՞gH B`+P\Ʃss$wnɸa 5gsCr\˫>!5U1$!R,7idU:>}ފ'j=Ln}rTNE4 W2;ǿ#P*#Hv-'ř~;y6T@2UG9a׿(>_b${Z,L7$\cC9X_Au) -n^]-W4«/>߰ <PꤔhY9nG54;90A]O c%R{5SQus,8ƹæM`} {s~@%Q K(,sPiŮ٪}Lj~aֿYHFZ~VX='?'Ѵat o&..|M 7&|+xݥLA?Cd/4VfѦSgmO @ 8j*ѝy*>o I#rLNnV)$L]`C:BpH%ՇﮁzU5=cjh9fxP:CeבkFӳJqXsD>5£&X)oB؏<ݒ1D)>u!hv+zқu.ttU4du <J;qr,PlE E\xbcT,E<\[V'H Ϋ$r!rEbpwc qn*o:s ȀT%1 X|4-xXS逞C?-+ )Š?712[Cgm- ȇ棹§+Rj qGRV֜K~^iCB:kDȹѡX`_|z6A;.m-)[A.]JMWOE$qճ~ 5 Y*>LGq$\-7i=z$IxiؤO!grbpzZ@W7v]sPLI⋦GZTW? ߅]|F8Xzf (@hGoup(zW$`2+8W8V꺲<㹆>gU)ݭhG]#Tf>d|tM^SsESylvnHV4/OtUFo W\"פ#?ER䋚1k4B=5ٽEr ϲ4:K?=݊fp3+q>מL"S{yJ@\xΛ:V,B9K7YH f^72 y M(f Q_N<B>uF'mXJbA+-4âND Čg +anz+ Mcl䨻BCr!͝{eWYL(!"5 :ʍcZξNk( (((@DQjB>R!&@$ 11k={]C[[{tU}I2Dv/__~CA>(Ğ1mKK-/yt:j^%A6n_nlWJ6Lo&8qCͫ\gnQ @wl^bйO@,CzNY?"pV-$ AA cS͍PI67/K6JWS0ŹisF.9j  8%>9茆jI8XFWS sl دhhgGO\LA4_6(1Ւ& S5R T""{5Ixål-PN@h"u[0e{%d ( p"Xn@,-]7>h?MdafM:f,j@L$hY-V ;mq!ƙ34-0A"{5 Zqτ̻Y_f]6q tD~[ 騭8Cɗ v}–(#rN[ ZeنD[(Mm D<%q,9 ! O%2Ef 7H>qBB\# ʸ!"{-Pi?Y~ j ͸M_v] e{*TٟXj/U"[ȧ¼ N^Smg0=ɜ P@< `jM]'@m*44}%[in4wܲ0^Vr/gBdqB*¡Oyv{Q9*ʹ$f5D.uv 賬NUKA3,h|cwV5fviGDή4ބ@疂kTQf m?` R ԙP9yXґnc |4Ŏ]mKv3M]H/ u0J.ϔiL[$ B χl]rH :7t I\'aEfG)Yal'LMk©;RJivU^Gz<rtx N!{ZoU&Ժddh(!|>+N:2c} uDvM ,j[M@o"!O:z4J́Z8H!PJtD^R)]*:0ʄ@ߢ@Ґ8yZ4 "HLkк脫T}bQ*t4rۚo&5n>'i*DBq;"N @(-PCȫ6hC!c6" Jw\PvG?sM}0=Ú)<1LL4er(8\o\a-neH+Wia4A 4 `Y%kHi9ad8(F;Ӑ]HOhg/e$Yg:27Z?\!M׭~4O@XquL`ӁB(s h$X-Mw|1ߴ@56q0X6`g T-V}̚(L3xj߰'\WA.})Ħyh:}֍zub M%M R m%ŖM,Q;vh6pӧs821,qup؊l9v=ԥ*{Y*B7ƦkECkNIdtW[ihhg :#cȕZ&mľ P"CA#.1Oؼzш?@l9с^՘%BT^|-:)![7Jb7ZOJJZX6̈́Zg&GqGG4an:8\t>"{]?ӏ)x,?nz W|w@$3p(E=6P3cɏ]oVk>$-ۃ*Ѿ a [J/ 7vm4G\M w}ұ9vPy 7PqT~σqD,tE2p"z Jz9Am|O2X]PTR38KPPiǘ-ѣTfTY W~ȎA=&cQǔsWIGo$kk ׊yE(:"yxpswuOk,ލcg"꠿Rtdpį{KzWg# Kcuz¹j)Fl~{{P>R^#AVܪ(HNQ6Oݫzu64Q 9 rVve]v(}V赽:9[ ў٭M#?\8V}?o a-ȳ+(C]: 83tzdʜr ʍ`F-ېsy+*`)ՁBTpjN.Ԕ}1 hOXPqi gJ.Hģ %DΩ$Rj`ȗYm7׆՗uXJxga+N~oRWuhH|{e`K@ag$zO (?+ Ӆtg@q-}>Y~w@vPkфRO,MjaC%ݜcIn'tY*ߑpN w/pvqtVioKM@^ZIӼ*8vg5"ǿn& ߌ(_u Su~f5-GƯMd%f+gb&9 v Tm¡͵wjU 3$R Eh]RR|5pmGh3lه{PGk̲?]&3 ))P\᾽נu| HuR:WDޚ(LPd5%╰ H:ꍵ{seU9Ee=΍vYm7ZVa)0z7?jƺi3=pKU.rfwMt[ GS+4hcF{6b"{u"r:5 tUy9Ntך(GPn~0'/LH}jۗѳVhDMHn"DG \u?NbFlnl zII:$[:gxxlg٧߫4b~liPa<)z"{vFLKAbs iT_FP^ly@6i4DDr:D< pAdYU?wd>Bd/A<( '_9>D9ioBBrXP%ԧה?"T棵"e&FCp ]t5JqZ; 3D6OigVK= S8&d4ph*O)P⡣2h E=y}  ۅų>z[ 6([VY-gȮ!<@Q&Xm Qά ̒ 392鮂DDd[uJψv`(`;lT H~lJ* 4hRݎR7 B$MQܲDORv֡ {种o\u;D)@IȻI?_$!h'->F-sv]]Ƀ̪qŦ#0a#*og"y=zpX.BGA"3X0dq8nEAfGU]F`گ`n@N1*0a2p2;u{q4 .ZqD׍ R@J壓z {~`H4tS{g/$xHk+ف!;u"{ucheqy)hϬc<<ڲU9Nt>k j7GFt"coNa`!R bȻaĒ%J:Cm}mGWMI% ma|KH Е 6mR4DCr-y,Amuek$VߴFI< P:P~Dq DhH]7u,%xzgg{67`F#սw(M4HXLffTgPW=LPW5_NZɴI;)}hg oUM}#v2wޟ !UU1m L,9Fr˦L/4)-ȍ kD2Ͷ `('ܞzu%%cǣ"caVՖ0z/FoWxDvG= vxV<.)@LsZ4QR'T fR{엚>T(5dzG A94** =ȶk(Ch[ѐ>e~@ϼ$<?bų" C57TD7Ӛ)G'DŽsVAh8O_AyMP~8-7 m7&!N'@E+V>t+*^?]ێ ScZ OfH0򙻿BCe^e8bQ]LIEz7ϫ=2 /5;#[4gk)OhhU5NxtI:jIJJ;ؾ -\ h^o]50XsG=vtk QYM6&`l:n?܎Vc*՘v|A;U4"ν+xvn$XMG·SLW C!4kC&秛#KKv3sQ |&\L8?sv%Mj }p.J9UwԠ##SC aAZ} GnfRAZQZQˇMt~HdCd'!R'x@ϏkL'Y-xN:{xa t$tt:wס"Ia{p)%;9diqA Ʌx s)ߣϲr"OB4&u7Nԕu^?( w\]7S:VauȯZn,mC]QRW1τB&FuGu[o?#M*pgrpFKӎ9)d|Y3:4΋f4YjŠrҐGfHLfn!ӲRu!si?t=MN\S_NbaN7Sym}H/Ǎ۱܅;'\4\QO E$EJ_02LܵDiZ8?iEs5Mfܦ)M'Cq-+{p>@%)Zm`^YX]\^hL:x=%@`f􇢸:PE8adu Ϝ?ڏBC ͝yeWY*@y7]Dy޳-!~= GLVlekl@Be "(QL6BR*˲?,D+sywNI*=ɗJj~};v@+㗼VǯmA& C~}2}ʼnkN} M~?OV'3flיu{[[_q;;;e[ǷOlo_}bk{NH5'{GN^;rսgꝻvLryz1"M;H@a e?$$9 g㈞MZы hGGv!wa g?'ѸN~{hN2¶gtV j@X-Q E } hrрXa3n=LW~jw% +*P Upr8 +h^BdX ?>%B=́Idl0HV1ɀ@ƢoP~~x=`4|U}="_ |=Itr4Ed@x0C's#qRh4!NCt(VۭyГ#`Pם?@?DVW-诈'0'N!:JRTM( z*NdPԓ/bF~D!+Pi~AE?w/hnN?&1wIə!Nl>u޷wNlߺ,9#\W}+.?޾bkKOCQ=+@@O!P p$ڔf52gRzKMZLǡ9Qarg+\BAd"{1MnrB q㬻79^.6T"{)8"(iDAÊPӉ.S9@2N{198%AC,*%RJKb:GJ8٧Lq8 5jp΁`) }#=$ϙ2%A z̙Y+qTN e L%{;0Rf:vqJ4X28P-F)pjd& 44`?+d XՄta#s觉M@q&Wh8.-ɫ)P2  2*A^Cy}F8X7WcoQU> XuDI |/!4%"$QcS -7UT^_Z^ &Tna<1"eH 6?|}6Jʵ~bK\?[_%WKbh38*pxlhDL"1Rp6_R Krׂ=׆(t5MDv NuFhRN9o#hDsC 8mPf%V{9DvڂX+Ap7VS8kxp84!JlGIAgxj^ubD J+]b"Ǹ;gdvŭWlx $<ۜ󴝘)m*h&"-S"H‡Q3i#WZ`hftcEۥ4gqúQP`VF-@`aGY#,0G'(i<UzcY~NslAs2?ARg "_7e‘B8QT*_=!}HL11ۃ|\Ahya"se`1^dM>.뾣[zƇk;ROUZ%q*70gPAAd3SrPd^1M~E)`5.>'nܰ|a duG@UK_&YXwʣֵPmcGPnxPRΦ ldAi>|BMUBd0R-tܨiʃ i +~n0ZRsGs%}д 'Jk O*}Ćc6w5}xsPx\|IhɗtQza {3^Hd0łX) "! wo:JXId/BbjKzv~َG@(z*)=$}HU0}oT"?`+KT9p*m RVO%,0,{n8ꎜ[50*"}w#.Hh䀆Y Fp 9#leqTyaR a,g>NЯ +Dp낆Rw^`{WRYZ}2)3Y[)[ZSSigI{gj*cfM *MV4Pfh*ljC@a0 4nhUY+*$%FhusjvȊ&R逇pNA9bljN0 nX6tFX QrCAt4Kh7GifƑ@EGqtC#["{ M磲thU8UgC͐#ILŸ*VGD  }Ía9~ǫ0f;:VD/._Jp.;Snl:q6s>?:[ꡧ 2jUn%4g*!qeVCѐ{KdwY!aq`6F4ni6u__Bz.;LC'unp83k[FC.B@vq.Go%SV8X#̟>SlJ ICP~ϳR"PZ5[)Q~UQG6+k9!NAŶ?s4leP9vՃI?_ gcxWMMM :co5cŞcr~a4 M@s!?oNG(ȀQSN[]%DgBNEy**:P@ْ}?;)S(BMG4.i344y|NEla4|V<~˘&Qh0yL1Ƌ=|F$}{‚c;K/B=D̮P7vJs*ֽG47EVj a$aLƻM)9"U_#֘=}PvhwI{Ckl}$=7`>s7Ju?)RnMɧ$^C4_sWT2`Rdt3ëIs4_4̣3J96P| j:Rk{{8fM(GS<΄r nGaA=,v# }"+ X/p̉=g zRKA (!2_EaFwApc5"N%Ng:K:DDx1*о$ z#kUNJHz f]/r< V4eB=ΐA1l.v ;A >qa 0[;[/Dv _"gӵ7 &@%y,X(%‰pAnk'O㞟ηիWuG0II^>L.Qi]n3ҨR@wFj:}س^P /nýݒ).yfM ";o o\0Wwg64|Gtn=Y8i G7e$iYEXc8~[< ?d!DK +[8g#psGsz4sS_%{}r oNB\E5,MϪWԼ/錇ʼn-lp $D2=M%?*WhDm~#^{uJݪ-n^rɃ9,SzBh-/ (N 5n&'\"94ԪBACżjQ rL5W,#>Ό}1L2s;pt#p$2U) [bEIA"}xJ] $&#O91jRgtlI(_rtҴ^EIT:l~pdkdOYSPqTOY]Szk\M>0jbI<*M$%e$Ӳwhwd-"?7W?g=c6;҃WPYjC s*nn3lףʎDO8 E/`S, C85L`:˔%]J0dU-;j]nn[yQ ݔ=gÈ$͎>Ƒ殏ۉo|_l ToR:vx"NV-In8Fcϟy6YO, Fξ!rlzC }Wŗ>A<}CmQBXɈrq~ȲJzHvq5$z?Gae2?|b/~)%H#6H4i䓯)aN|yԪ.hA|72 688m'G6w9C׏|/]!(ŁO#iéW5iU,P-BShS\/'C ]wW.>Fd-̽ 2@_ҩ髞2*+_C[-hFdﲢ(^@Zv-`VN7(?ӿ>n oukCUyϲ {KZz%Ǎਣ3NQVo3~ g8|$[S7:xgNW!OU8[p Plv y?@).|8 x`5 (~BQP^w\VŻo4DɁu8y3/7ݒ~'K5Yq,=R;JGJp4XJvBA-e| A%a]wkuaX^'@8Rp++d>w/=YZ~#DTܮ{NcS2cI=mL= }NIDW*R>htSeq? &K xt|:0Tkr7NdlijL }?;R}'DWDX|L Jb\'-"(>ZLd;d=u=4H 9UTS|?W Ga򫓃gp}ŧS$Aܦ2';"=^Tci*q?i7 Ə$*QVzտX;ѩv@I IPM8&-SuJGމ(RqpwTt=^^۱ܐ]-u |"Gj.~ fρ`G HU<,d{#g[z%H*Jɸ+&~Y6GfɂhSQ6vB_yO͂ fIؔ>S %;Ҵ.WeŞ d Lc<"<;Ex;VAm )@}i_â=f3sX>jJ첍ه덁"DC"}D&;xy*Tz(^V+ˆX-s;^|]XapYȽp@^ "o(* B(>(KkY}ֺ{]&mM/Z^ꔿ^tSz:d_2?qé~@];q0E`7(~PyNg?ֻG{:k{uV}kO\w<۾ng{'?:}bg{;;N旝|J~ 燮> Qd d39ݟesuY D``pXdyaGK!]FpO)C5jz/qi* )cL~e(X7/Wİ>HdCB+6x5e fj*N^tK+HH{z{$2 b GyNHISD@A旉1 D.@Q9PDG7{݊h)YE}r^p}FQMd.\IX?^sEuVXDtNS$[9[c؋=" l4uId0Xv޶@ʈ]?pDn%qqTxCwN?Ή[Dz9au'v}֒vĞZМ$ĘDƃa ?"D&D81?E "gmJ .<9tMohwmw׻#~` r3%!"r@-9(0!%NB82͞?(,a$: Q}H 吪7' ]:N3Z̓USPudSI?  ޡt;S" *bX(Zzی槨mKB."nO3 U@9 Ed/"0eDDa*#Pے+JHO ߴJ@(a`*+k }(n1G, H8 v3Fߣg@ݣ AI"@Ւ~n!)\ ~;sa$-zFMg P5N9BMݹf~@Y,4Z֥U'i(J=$n0=[5ٟ[ )oӝ aH2"=Oo-ͦ7 yC%4e@zz}I> J SѾ' 0JMŸ )1DR["DB#HD%Hss?.e:zcMrpIIA7[qeTJZ?oh眡u:fY.cT̤^EfX?NdgwG@PҬUIy Ð~~ͺ'ʟcl^y3pG:5բj /ꮏf`uͩnp0Լ?kN.&Jaac 8-BzyBq!;G +}%2,7h\}Yg9$e>`=>Q/D+QOݫovnO?T_9Ms&3/cDeD4VcW;7O1-N?!| QAPr&B7K`^ p1},3wܖ_5~95Z<^Mѥe5? LSf>ya<2%]-zzQ۴Qb f,ʣeAީFD|Za4]Iy}Ⱥ&I"$ ;m`m3p* - }ѩ4$.IjJ~> 5صd sњ#I)*] <]ݩdGTc*zoxJ$'vM 8= Od0C/)4W-EdgRR{3ǐ^Cd׺ -V~N:h̩Eؙc8o?4⤩p^5I]SO`n!ϓ幬#B_CSTqgUq=~2,Ox"m(P,()9̭{<#["{Q$} iE: 3yϽlLOO(bTU<8ʤdG.T?HI"; Vף|AdpAzF5`Gj䏛l\S.< 6@Z˩t~ֲJ4m ߡlxA):FDGOD }%7GBbfokZMV.Fu{Z릑z3A7d~so92oJVe2CG?~g҉k)L&0bE";+%q F=!wTpćy3fCD4e17ZNc`(@Wͪ{Sֽ=C+k ѩz"{5U)mKPZ"uRhcWɒ=$[\IixBz_E͚ar Nw=}( 0>Xv`ԁ%҃~`Ry뫠)2s=S2?<ݦjkb{iCV!:8M:sԖmǖ-u&7NN\Mqw@.'V.^DB-L*yjT'w'D,HgKG~IG<|Gޕ%r("<KKu=Dv 4 H>tDVUq)`z%5'*'-e혆Tv1Ňx!O"C'1SԖS[uBIa+a=م'o%0~w){cN12)xqAF+F8%N jQ?ދ]p4r-zH*!0?al=0_w$!NP11MzQ77B m -VZŮ0GTi)+?a;t/™GDB0OJ !ɏin]4n3i 5#mPc1(@d^‘pjQy0 8̰iMcĹ 9ֲD]q!-:ް_;OكKKY6O?'zR%CڡuV\m' tHAgNX#EK\_Bl 2|d%2}zS )8\(isG{,qP9D1k3U)uEUI&άsoĊ`lN/G/qnA{L>.35nTyrDr{ E<M!ʗw7G}lq#z?v#bF8 JATW\":)ɸhs X@Fg踯9E⎑ ZQ5 bFi GZ W0˃p_y'"ie6B 鍜1lĩ*kVV28?z"H\9 9hM¦? H??l$^ƝEt\*&u S;vDdvaH*R:N[:>RSTo2L H$|bt95Sg.4Z(P}ٞV"p B'8ieHֲW8DF4U==:+ө眡j#)0xգ.c9%ĨMe6k}AmFSԊsf ɑIlnˢm! 2ǻyS/Z7|;4.P,UQ"=S.l X@A.|(P,Ȉ?uY(ݡnQ]]l`1T3@| -M.wOVEuY^6c"I?Eds7cUN=8HlXM_n`ޠ_b)TuT$.m $8TT(<&P 30%;qdQ׈f^tLE}Pmg`LٳjH>/.| &HeN̐I"@Mx,V9EGsNKiU$Q+4>y±B3h]]'ٞ5M\ad ̑C?r="2BC!͝{dWY{7>J3R-(3 q_I6;ݛ &ˤ g$$dPvA@={ I܁;A8i=Vhۻn=vwڻhonɶۗإ{[[[[W:~yЕWZWOA+;{Uۧӛ^Z 88w.p;,q`rP?ge<a<`Ea0 j"-Ă@mק  t5@#"-+4FΏz-M4{p$lz4C9J=$Fih4'<gh21&_0f%: zBt5^}^AJd71'R؈ȍ'e"{ ƒC%@<{NsJHq32l+"{ MHƐyPɈst/( Bq[> M%Tk":(ဃr^Ļ4ލe ]^VXM43eXN|ܷN,~C=M boH|j=А0Eq*w lvB--u:q ]l[ Σ8$u`|@V9d#!(-~NGU<ь΅H~[JKX!H=jٞ-ThP#F c"fQ]x"{d @~]Sl"{hhy슍9GunR}4cT׾oWdCr%iiOXI1TPY׾D)Ȟ@ʂ,_UY_4L*L4+A"ډI,POLJ~rggՄ4nmTTq G0JVnnը^N,!Y}EvF5jpY5i5jT[uaI ٩io;^Y 5bK'mux&Zhhf 2kxKds-:[듟*'7$X9ʎB=_7M+fwvB"8$W꥽4 Y>Dd׹ddΊI #nN]H"$MOLR%e_KN{Xq_₳(3& =%3HuG3o5<+6eݯQ(Álfu,ٯ$r fE0a%(EYrjIdovHx8CiuVy,]̗M8vnjX#sHgl%Lc>2D@LVpCp(2^<^E!5IVQ)}6㣋ڥD;DQK$q*D]Duy\ Gu4]aԞu<${ml$gVyLf"Pׯzr-PDaEZE>Tu"{uc FNЎS贇5NHM5#M6,v4];fEź@uQ܈za]>wVӒf? vWh΋[rq`qV}Wmi@sm$jǥ-l}4 ][療̾4a}QڼAe3-V @|nZ8%χz@1%Кq=zśkԇ|ƩYOĊ^{{I@x|h&',gYL*6eDjX.F +&r&?v"Ilo͗:- 'M<+/JJd[I} ]7xXp0ϑ+ EI_TDsrf(OR Cbcㅂp̉,t lpďqfxYC{k'\`p"Y'%rkppԏMӱZ-Q ?,]PDqǓ䤖8Odw;p`({047'wLoSV4?{~PrD 츗SmؘŨ%_"ʳ2>.Ukr8Ӊu88qĊFhnQy& `38FsQN]K* hfZN/2c "}3m!aT~)*5q;>p7q4`Ք"HކYg0ӟSnǂبtzWW#ԯX3QT4_oAM@"n<|wqX]Y4jk<[xByZ!(d~-Ȉz 7"{U=c]Ks/Tm-#0ޒY08 hyz`P+kb*iRyG[8ܓ8+M@tg (3FsJ=: 3 \8s*[NYju,W=i(@EaΔ>B~ 0$t"~~VzFt^{REΌh8(Jp88Wlq%Eo#lrpp*>Uϭߝ';DSp@|2 >spr@(k>kT/4>eTv \n 5|twk7kϗBPD׾x%r0/[5Cӗ'FLƒQM-uzyR?\]O Ӷ}IIoǛ+ijD"XAIMT1q)W/ٍ0#<ze[m;.(&fd䵸X`O1Fda=˅ӳOEܺ/p@C$bvWą 8[>ś: 0')a.d]~5^E/R9;iHqCbm\:^@jyd$pVHC$m<|x:(weMŬ¨->\\)OLh|M:Q! ;]N Q/7P~Hؿ\OQ@siK tKM0l3Pdvt]T2U# T}.4Piu.N[Yw|„:ȯ'Cj菹L4w\hRf6L?C9z}x&q+¬KX{|O~yh?nwC9e a/-UCc[n^sCn^ ĆŬTo5^&։'iPt(zF`<8J%4Dk|U~*,-MZbj^}}[)K-O !s647T髼ťVvP|r u "D 'GDW 3ͽȶ]2 @X?EmD@-nDMda*ut4Di+fLMFGCHރ5Vdtz}1 $0FT*A%D=0y:- ̄3~e ܯQ[;^ģ|!6"C~э Ho@j{RD_gZVpʷӱu T{&po2mN7G4HCF ;jm~X8-;:Yњ| PyٿeϾB05+h i%.|9 ̉6"ij_q/ͯ9T{.HnMc=gx&_AQM;g#RV`crst_郢懸fl RUZqk{=oa?jr^7ȯnz mx)c$*H[Nrq,z䉵 1}PQ?8E( a \unDJ뗞a$u7y9zZ  Y[8[CSu r0-@<hvzva9 KThhW4Wn pGUXUG[Fk2zE=B"[*z0S uWҌ>fh~&UV*/WUE?3CQmEP~PٽD`nW8*Vw r. :m@׿r4dG\ErsomBgE=2=%?8A!({,T|u<@\*ecv*(xAUGŤVtjV T:Q+nj٫m OĕD. %~HSyf'P0mFileH&IO QQ@$/_ ^C ?n`2Aq7EMgG!E'ήpl_ Oz zDv…):5F"{ M % !$=N ;ets* | R"/My|0'&oٛxpJՒqLoHťOiM&MI}Vs(!5z9] DEwRJE8PmG)`%`}ɄJR"QMr3{)OKfgf:LU an!$ GD: ?L KqQ5BL4ts2 J=e0 );C댍rM Z=#c`ڃ6؀ZЌ@Ux`EW"ӉG8K*׶UmCS3g(#r+#M=_*z0aZ#FsaJ9:$uVugtaJͤ`=v4#Bݤr;{Q/RPIϐ9TeFOR|=W$B[T.YZI81P\Ed﷞>Kij$ZFSCٝJ=iϩPҖo8H2&6]uop[que^}`J༽o)CTˇG,f 5nnOuG}rJ -4,X޿J\PF7$!-ӑ=Esr$$h8۴/-xCI?F1|هrS^1?3BC ŝydWY;o*;OB|à@nI&_zB̰MW6¢^d@BEb$(eYThEϹv>2|~}vsj4.y XȺDG}'N ?G!;z;"CFs{dcn[[fk&ǂ^=nmwvIo.'.v;[[e[['w.8~EWu.{*NHNvn|NT:~MD6S8/ q4t <~FsӜ gMip@N;4mځa!~tV")g@bՓd@) \dqȾl(75[܃o~͏f49'FwENM3q^{cK~lv7fss=ںtۗ^}{9l[Ǻۄhw{;F8{=ICO@$ uy"XA1US`s{<٫xca-87Y=g+o]h|džͻh8m8m#0%Aq}38*" !q@ApT~n%~B<0,p i]Dv ӣ0|R&4 }LQ"Ɗ&"~4 S~!>Nd *~ ^ '"2RmB,<ø@:3.`J[m0kQIM8PkBD:X @5nC.8nZ;?NdﲡX&v3dij$ Uߠ' P xÚS屟Jhl4n<6c3="C\}h?5օءwA1߭5ej'o]{2y=섦C0CB#.joQ&,ȔDsH49ґ>9*lTL4!h9oK5$H"1RPbӔ|ձF=~Li"7@$Ym:?؇=m 0kyXY㬍Q$`<ču/zAͫBմl4&I`~LIBNzNQ~ȞeJ 4T$7 # ]WakL;'F N@꠩*1m)DSX>:.q I_D^k<9"L(Yh-'~BFGIc5J1>ݱ *>c:ujpC>? "Uf"175;s ;?@d_1uPg['*(S%vv\"(}["Z3hYuh֭ѥ$j/P A  hm:PYP1\_$wFaw 4xNtNsA@f%یo{\]Tu@K8 BzE*+ҳ^P"0Om54Pri PByiԔ+ⲘRKVX\.LiJ<'/y'|p8<tϵ&{X^n4"TW“x,~8RKvuP}Od0 pN87%"&  n 68?m5c՟lc,*.R!{Mi3bN{ MVOJ 1}̴AA+:}%iH* 㖗?'W NJk҈n$FG|tD"wF ceipID64 9̆J3ÃHoGd2B9=z&'l78ᇀ1(78yP<3RwUNQEG=i\Xzq.{3eWDt,ay2~dtW{)FWV| (}TtU3p*yKh"t#}Ha*eW3c&q oTJ"P=?\n"^'iK@ef)MSCFoY ?k'Yj *8\, MgD#f$2߆(!@[NtIFޝ)?oPs$0foDdwX񄳍rE/t /N4~ua$ !wlPVV(fe|=Zg/j[ Z(I<_c./xMUX@by@ޝYST/ U 9WSRڲن(GYr@9Ɗ~nN_Y7M}_I{|t`OT^߹_6Fa8Vc=J{/ N 9\*czfA uvpy`/*~߅N@ Օ=ʡeV}#(iXSwǧb1n8FPQG}/N 6wDQj nz-qǧ=W)Ƌt%E (3_XjiVDgr1 \>;ulR0Ae#L!xE@|X#.>E]L)l^9@Tg>=&p%|d0eD )VTDv=cfTL*~;ѲvPU ;}:'9@N/ ,'DDO{. jW(z/x.;HkpqU1|e=ggwVOdS+PdpBKQb=}Q 5t#0|u*z⅍WmBBN"mYG$җ|u爮qߊ CsFufu% DV Qi$x9O% )lo z(ZM7fUQ*ԃݦ0\Mj&w jkC2͟ٳlh|qj]:@x;,ɈNFi[BUb $n|V>T/pĄhRTFX))Ϫz?ZG"{ U$>/2{5rU,*g,N}TJs |,0uF4c q-8ꠈiL >#jVZݤI8Xaf1~Y(%pAxAFCid<חׯEwzq)Uj xǵ(ULSCnUL8dh'9N3YDEPKcu|X+ɠZ:ExX#.LÞ`|0sW?wąrB؁A E#)E&TVTG'␂j8Ǎq"9ځcuɱ" \i/>YvuDo*iG:oV) 8UHeE!ng hH&+^umgIߓLK_uNKlb< p=Ѯ;"[y"9oýx j9We,i6[80NdɅя~dD6OwCE'UcO֢xflU U5.GzB尲q2-7yT[Em}mV{FWy= =U]j)sgflwjwtnxs~Mzx"i3 Р-@m@Q*39G= )|]5Bb,^_G__m@ʶ|4Gյfw?d ׯUÝ-M]+4,. P sk~U?lƖ(N( hqNJbln":mE$e׬sU=*Xx(.ঠ挪`J0k-bG<ІS5A?҇VUsut'QhC8&Pg%y=̆R61ס2\eL+l|O> LQͦtK*P.B`Mq]G1_Mqb wJ'I"q-0j^1 GE]NUM/^j#- {TF9:SC'_c=qpjӫ'_:)93^K?\_$^o'gpU ?m64⟡en vUE@P\8S <̣!gYI)Q%xn=Jdab0Ġωd'ox\fVjj#KfC*>xAh꼭rB=7٧0|N=iWӶk`JG|~G_J^^~ԫ):i_X_MH7zhs&:8 Wg8 Lh\d϶º15454uD>0Rֈl۔ M$C*Яٍo@\P$C[s.4D!'j})-a! ?=PV4m5xVGтjA1+ƣ X4tTJQ%:S;?7G`<.uNAti` _=jU4{iŒEḞxG_Qi"uh)_OV6#P [m '%0zGTȴ$ {h|]8tq42~L'@K4*vH8}u/pdPKӤ{sKFbTZ'`,)4c#!x8q~= QIMu $]kś>zE.zRNG_%X1aq(PŽ\K29"{coXnu{˫ PInb Ar.Xۊ'Eި9Qz1va#1gf.z|y4?{=sϹQzuѸ'4mRm"{)9ً]b_(8DO8w`?+b_hlowͽvLgwmv{ΡNht{cGwmgWwzWuzkz~?"?_{۸w* ى7O }h\09:;0(B4{s+l 'yi@. ;QAО' LIJtJIAdou!BS0 @tmʕIR^IqAA,U:ݞ4FW]cϹEq T~`m{ DB3?u!JqފxTh.hh<iP(qI⩙ˮK_u]ӹ:kɏ=vȱ^zG;%49y=˒&(j "{ۭV깂^l 9`/;U=vM#Dv5 Kvd*<^cKSn k̀S)?IbiPyּ0!YKѲZਟ sCem0d6O4&z] ,fZ"- sJNc e7j>c D<6qHa2@"{ R}H@@~[S]ǤW9kXJXs{@ARhy uu.o%oj;u$쵷v۽Vڛ.J! H5'64VsD|np1G9DsҍC8 k]DN(մ4r,϶7j ho _ NHi1Tj Dz#š{Ab\@pE 3՞kQEDePA<*ܝa2ײMr7 &GSLv 6LjF(4Z$GU&"Å&@j9a`|a]$Qsm+)ݮU0N"5wȿaVۦ"o"{ oxL峵$j{:> YAr}؅(9G#K).dlmd' i&HuB2uLyyU7c62i( !p.pVx dUDGAaNE$6+{낄SE:`0 *[&y?C X* L-h^C>FAdJeh&"8#&":}mB(Hf1V.@֠dB$/Z삜˨ۓYر¹!F$8ȁQ/ NLtUm(Ю#bt6p#RZPJVL˭R)8y79nC:WNOÿN|VSr3)Dv N?z W}^RΧV'>w悦鍆pXg$_EJLTm )V}i=ZN+pb!2Mks9_.8qn6@Hul,7dE[A9%:I :n:=3IO1Tϡ*!U4IdovA{K< &AjFft^Nn_qA4T^֨ Uqrqɖy=+-d'I'u0B:ۄ0**i m4'*{0\r+AzUe1[5I k FuuD}@d чzTugB( @s0,f˓bA8^dL>U=wqoU8wiŗ\rK: AiT'۶D11[\0p:oh(E,)cT`?S[.GBiqDVђ'9?Жa. vYg*iW #"( yb&t:Z7{ Idg]);T9Þt4ϝSĢC+KRYBs{vw\IyR@z}ܺ4*?Lo;g NzHUZ7oZE[= 'i=ڳX,1ww+d˰J-B*7=^WO.>jT?AsNHqNTIy*!v˖PjglǍGx/4ÓZxϗlC?Xa' ]/P'(M5t?#&$^s׶Ak(z|ZT$ h+𡎦I*)pX󾖺oKL8g]\L/8hEk86-7vc悓GtRr3 _qI5׵o|y}2Ȕ͏YK!r0 8 P,5/h< @&+%qJBUDIrAw!DqA koiZ{`n֖Dh"72>QP5Op2vj$qLɤ5#wՎl`d[])痉C514Eap4 ][<$,96\"}k@e4Ek}AQ̭*zFM:>aKy}KOU8"tʞ#SFB_aEJ ` DЌ1ZJID|6uh]SX_XH[m#U ˮߘȞk=0Әx7Qѫci ("[! (B+"2r!\Z~K `訲/}%!&vg[Xl$X 2A˥G^soij&6KK*0.Vn3=U$9̖ bɮOEl"u l(wO0$kt}N,goR9۰5LMݪyup N1)EDic9cFApPK~RK@X:~q=ZӇ[OKS5`AQ}9C2V(f̋j] eB*v>c̦v|.Қ{"Mea[eip`2*Y4B-9vz;VR M= }[4D^)|oŹzʰ*?#; ,ռ`p -(=?3Dy P\Kb]8`K$JGߥyW$a0fЕ >d~\9G_~5B$M.Lsn Х]yr} PȷFs˽Iaaz)X뉙9>䗜hchgo!*PeZZD4뮓(u3fuTXY&rPxN1!7K*wȺM#pz[ۘ9[lv3ٺ8\LgR5+5w[˥a$!!QC~ל%NK=SM3DKe͙,v;Z?t&Kk{ߡR5M()N'Q1@G|ljp p^Bd~4nrs9*NiUiʒH$jDU2Aڻ-Liv5]T]nuX^m~uCZ,E l NCZΓBk6b;Kh|bD\^@FKt$ıZ?AKEYBO@9+{*:œǶnGyPX)E$҆ :LܹRY*gHRRJ%mJ3Bi卉k.>d__1.9MKVu>fL_i+>[j:j_Ad_.f Vd8E#*"5Qaǡ(ZF d9{q|K,h󎸏ڌYFz=9F*,Qv5bhpa{Q)sc8UQ-l?b<Խ:M}0eO{e Bs>"hwZY:/-)X&G ~Vڧ+Q'gEXPϴs 4Bq- =ŋq RվhFSqWi7W W +탍'\hU/Ę9w};1VhƬi0 ɽS-oNYlt YkB W+-OOG@P> &f5<|Ws\@0?Bj [j} Ђ#NDBL:tqǸMy"w;@(-(ur Yur~݀CϚ N·b׮[ k- kl:dNJQN$|xV#EDKC18`5rYl^V>44ChVUfL\&R@8́vD'd"{uϿHϼ__~ O!eJ?'[./$I?m .e ox뒊*S i0e?ݶƀ5e"2Nn}!Nͮ91d,"{5S*9* !1Ӛ{SJXZc͙sN[ch687Qyj=Ȟi=7`>e}^=^2vjE8Nq*WA܅dG%-naN nV˃0]il׺1^q:wQGpU,wC4.*([f6Ѭ05h1gD8M$Biͥ1.󜳿fpݎca:ּ6z'oj.(άcb":5T\ !d;C8 2h4\ݦ0dh(e/@T 3?)ysUoiR?ZWS%4ŸxX|NA*=Oin\IC{놃kk A-<-RODN<_9?-t>oDv0 ˒u+H~C|wK~YwS|dihZs~OKq ޕ[C4[)rS5ri7> UL%.L! [JZt@pVǜA(ڷt>cxPY( 7NH|I"-:sC RwCN@O:q7V"TH4o7vAJ؂d}q} BY.@0hg9ޕhB01Ѵ= skB ;F3k@rhwa;?p8yp*S[)[9 KOd*"ں[.D)s6u&ڦ@sZ7Z2JAU z!~O_|?Xr{PA+4 Z !G.!SБ/ns6#aX c8RK✈ '&sts Qy .puB -鬞cޮ#WXӤv}q2-"MՅjDdo.R4B?`AM^4jөS.$@-4#]jRdtʼht'}ֺ(Ɖ$$."0c H$TYO!:92s7S[:R/46M,9WC{Z*aǁ|ZDvu-ID (Bk>ZM4t"uB*ӄhcOjK+iOI̧iN]:89#7 QGOJ O,U$xLjs"HG}i T;7t6^f1~1jD #PgYD3 Q-4Cr,N$L.Ky[nQɊFL¥ r2 |CWmU!#S%Wվ)&\x;]$n/./̝i-8 LJnCkfI8瘯.VE@!#_T<+@ak#?#<˶o!"{D|_4<6ÓWd8UOsJE+[ -=8wu2Gld˥(3\> ښ_gh`b&tAG0՞Օ;>ih"*o3B"s b&#×w\BaT,٭{POE"։F<3 x"9ijsfBC' ͝{eWYLkgύE;ظZI_93fNu(J /F-jEP(bh;NH$ĐHDcĤgg٥Mnso}H'^ӹv }nk-'Rss0 Ρs_=+:vos7+]Cipc,m]Xv (2Ϟm '$FX&S8HIk̓7 ,RODvIɋc)Vt s+? Ub:W8Vp[klhFA(EvD*>!;Ge_=a (X:]e@\ZavF :Jy@EџUf{;\IboAVEED D>%Xv6M(paCشAKz @t:cauȋNc]"|]6Z$)4'@yhVF99\z"CdZO"옷 9l;n{:v_v_/`qwBvwwx@EiT" X+u: Pe/3 8(wu.rG#U4bϙĀrV>y*'$P~@UF@*ƧmD=Ƕ~JQު;\qVCUm7=));lNW|H%?` <مInoa;MhGUT! 4;o.>pq !tu/83 }#`K07 p|{iL#ڲ/5/<ˎk-um[?X/)P7t=%A) R _Uc.Xp\BQ-ZJC(J@ֹA6dr8E/}Q4\6:՟ԣ~FS},G)㐸;l7T \vw|Ϩsz^ŕk{RK_x6N [cK"՘~DgkJIJhER Tl(˙1RG}ڭdr+u,y,{6N$y98Cb'|H]1Rbk_ :lAm9XD0D4j0.&ڳ5x&J`G\i?#pTg&,3]$0HXw uy }JƗv|\rm?u0{4 D#*z3kj`@ ]tkޡ<n_v:=ݮIoI,f$Y[ς "S&3". %bY_&?_dz5XW}aMMijx;6(*$ Qs6w[wQ>z"h/ J[@覈c]e1Nּ^w=Q0:X 7yXPMmF.v#hÐb<1h1])),ީz] @IChֶNWixӸD&@gFM$-"Rp^+sUg崙dvVEiz %0P߃S²;K_Sǹ H|yy&J"$b3Ⓥ ivfDuS*Tyt̓y8) c>;’lZ So*-+Ì UKu-(J=:C$]/oB\q:m+zJOiu#qS^ȝ#f/,\]R0GyBds(c} +*);G0ϧxp9 úkN{" u@n!Hsq]":ޘ(Dx4ZNPPwsHתw^Љ;A 5¦1y[()Kot% d><%|RۉX,hX0&EA ;bHA76݃!o P7h .;cF<{U]fhĮFBsސ&~hą6P`wV'dTt[vd>hGCu1ػ_`4F>fMәtuyztM@Wt~Lu |Xos?gkxcW'F9w<1isM>)-{` H_Sw!*s}Tc)y"8YuM>eP͎I˒'m y ѿ`wH W譡 *UDҝu1ڴLkDaFAg7G.z4TI h5lXӐo=h)T "e=F!c~h{ D)*V2{:1QT͑KzJM3G.I.Bw4ꠐ4ԅ N.OjwR VPau ͩ~Ff;Y;yr[U AXNYktAQ9`\6 ^{"u֎ҤS&?e_|]C,\k wA[3[ycX62|U8[qrԏFD>?gźkPyE^r i_0 kLmrr$ϫx .4 Ӆu^Td `ҵHer?t=&<–E`^S[]ʫ|Gwʟ- 4zK,[W;qަ]wZmo]A(;LY?>Cʜfo#CY[]Hzr,^l#HU0A~LEDSʪi{v)z+j'żI[1iݡZ*i> KnEƴ5?Wxj`!PY(5o*)E^My X(J(mNxyck[FZ;-%;5@c/uO1\^D[M v}a:s]wIT(ɶA3,! CQ PTG,{ZrVܶ~pO){ ] H|"C$:Ʋ|C# n,c<@x"^C.6cuK1y:#kI#y+:͙@6P=SQ3'Z ZP M+%d[K!C{O/5(%/('!u-]VKHa\@& fIԵteֿ)zO(ݝh|f T6fK,Ţ6 _S<{`'vd􀗂bdPiؼ*}mЮkR0 w3!Q-OPTw9,͈( id5h:Ti+ib(|ET%FWV" * ӀJ"Ǟ!#HMe*.[t^@T AFL|i8a5n)(<] HVIܶcKNZPPQ_@d8MboAB[; ",;6ELs A8un/YlwVOٺ2(ۙmN3Jʳ7SHU_ͶBhسD/~.9_W{}+(ԯp iՖZ[Z8*pkE\HâhZdmg*|W󨾣x"u^e^Ȣ,#vg-OpiUf}T+4b]= @c/h_Dkf#Uj<(IJvzHL: X ZK]&$zu~E3 ~6U^~仵4Vcs Xr]glB8'lsΡ0<*ML2WTƲ;icpţʊ@k+s)`$d@,|EQUMUڣ@2(X:Gt]F;Eim+TGxT̓彁غ ħwt1yu2b|6[DbD!o5:fѢj'z¿=H 6da=z"4FAC4+[@|r ϝɣ&lq/ZMa@^Յ!]&C8xmyXuUG8X=i іyqL"kVT:A>GŖq ^$PxJTm"a){6Yrȟr>Y3S:D KmR{q8'i[1J %ʈzhm6$2p+%U\e7q!az"YUTU~r|~噢ekpep֟p-N j'[eq_IJfHŴVq :٨ Or*f#(Pw 6> *)R7{PYE#ϷF<?`tD{<+y^x @fHqGN˽ϑVuC2|C#L"]\o6aGszY,ieNų/j6?Pa@őᎾ /hC޴ewD '&8ANJM;*T<2G]* &SYgTl[U>1O5OeIд4<%#S99 p=1BIuG *GE&3$.ƪ@j8R]!eޫvnrK娧+q[7N/RK1A[e_##LIFzBpD޺S5L`_Tc?߃>d}Ӟc#^ 4š#supGd,џ5K^u-Xʞz)`Q}AՔ,,+5PINgK{17ۢV[9Ptץ!hzhld^S6ysO!\Aي^VTR*_T'L잲C ;^?mU08c>{8iWgr%۱/uz{+k6y}VJ4(mz}QVh46i8E°ד5:RUZg/5^-ٖ)4-ct}V6VO &GϢn?-R61ZKW?W98b%x#aYhKg` p"o̩vUSA_hXTr;j3/xH5F{k^gCIk2߷δixZ 9qɑGA@x:vb?^xy1h=Hmvw{vgw=z9Jz+^?WOW arw|pb8 0 zxvg/~)k%'>gxj4@!g6Ί'BQEpR["ƒU'ъ(v G3F! eetCdoc‚`4ZtauTKIM+?D;PP5P֓z ==V^( .qiZw'%aIt?GtDDePCD8(Ğc0]8v%̓ic%>E д3@m斞hqfq7Y0dxH?IyrYZ}9Q5 `HLJ 0K'*:q'~7\qXo,>Ŕze\'\?FdWr0?Kp:Kt%5R-sD61';Gnm4Rrpq"{)QD}j\pz4C B$m"{)Uyئs᭯ҐuWuMdo0 FMWgNd3=$Cu!OAOK߰8W=IǞ]RT0>d0||7AB}G2+죦HW!mWEB# &")UEEu|, *x#HRy'Z>KU}%'?(wa1Z #񩩇͍".ٕl8īD0`RyV@ I41&c(v#ˈ1SG DGpF"%{d?H^r"{1zи$isG 9*Php4Y90ahx#Д(.kl*L.319'wٔ*LHΊ~g }.+^Rhvdw;4ߓ4( zUeUC:4S|&PU"'Ppi\B"1M|b&YA /z)*J")Pੁ62j@:lo!Lbsm/FK=Py+=dLTU'(M'*p!SDgw\Xٲ'"gCR&: 4+DCeZ hI_l8xAaVM庘UͥGl'mICM'/$Isl wڂDv)O(!KͶ)4|f2'K"aI{hOOO+s] K;6,Fpy`H+793TƳ@ID ;WPnof[3$WHah]{ 떲j*r{́Fd7׊҈?l;Z" 76 {CfNϭFߟwJFx J?3;r||4)i;|顛R@llm}ơD 㴽:3$w(JPIH)P+ X4T}L P)rr Ѩ@L?h>t (ԯmyYy}2I;BOF}(LRY˴@A$ VUѩF=ۊIA8ꈙrB '^#8Ea iѿvl 8Q 4)v7pWy [YAd=$9E?7P,^ 򗿊X{ۡ~XQHϪiAU ͢C.y'GLIuKri4j->Rdf4|b>Qᄧ]6 P`@cote:񹖺c0}"Uˤbxt|Ty w"@W}>`LbUKi;[%WZs@r9Ez6܄GҨ})'ܩI9–a/S4YdCܳEO)<{+IPV }caq$ Y_P{5DHڟї;H$VHn}"HcP ^qJA:mJ`^/RWz%YaN0FtEC M)O؂&ϒoCPiJt?#jY?1Za#0YdC#]AG1";nCH6Yāf; ۷>KdWH(h=g.' uDgiȆ(E6Z{9P; {_nHMyMѭ|{.yq\_ nj:#JǾUA†Sa=i6%-'3;=Qsst}6(vlVB EGQ4:&YEU0w[- ! < f4ϢqoBDf|\MalP3sh}:xd cnOr-$QBѹ*|T,o/uڭ?@}ѽxمi]Y#M~1qƒu@t[-ݖ^ C_8G)~y]g-  p*R6=Fݣ` /wz.μN>PAG߶YjEz.:'X{;@bh9MIo Z^MuId_6 az/swYe7 Y8S#i*"?kixH"ueWt442e}L|S ե^K~yA/է8ͤN9=4Sn&MLԫ֒:zf]@yccQ|Ȯiٴ) z82u+˧ʙ8&9=|WIe_D3u@mYIE| "0O!OtKBC? B>F fIC^Gfͣ[]D}<udۣSVX1eM,3Ocˆ oz{4yb.3ݬlA#!F9˥/cV t"_[Rm8^L>Iz(zK@yV>u\Lka"ިbras%1Qnz: ѭϴa ,(9GH?h3Mc:NM.{=ARLldՕ{hAOSؗ^O2|Ȯ_j0kBh1"!I(NGE8o1T%[z.㺨 %3 w8_4.T}…RfW%'.a47VsE^Dc/F&HYX^Sd"zxy"NXꕅ+C+{p}yP.DJ?z'TCQ )}KIROم|3ە4U/͝wjZ ӝ%& ATb{[[{{u]$aB[t8pėr'S[ XHJo=*anh~GīeG%tzA iWgÍi­m J9ϬWs9vdӾ sW>&Xw]J88O#<:@Tk i(E#. ](H#U&Id'\k"k:,NWH}Q[1n@CypJ X m"{1xMG3ۢNB3}bdo@'yPN0{`m:i{jC%m"yWG[h #VgMv-Z# ~ǽ5DQc(%X'1*w,Kq]N_OSY`S]S :%]!YՕxBNk"l ˡX4~guee9s\V>mU*4a)O98Q?' F v3tZS?c2a(%x(PAVwBGWj0kp63^]TGqDb#혠T XZDG̷:;ItEVDSW} Z=]p#$SPcEŧBA{1Ǫ34V@X.1}#9))"T{`O =-Qo;jIC%ɴ3tZ_4=4j0&aɍ>znV&6@#`1s A0^9D:$-CD`9R$|&X4靷ny 6VvFj VT.UŬhA]I36_|]Ff 4{i'P~ףfDWfPPi jh qHS6CD*maň _ׯ𡼗S} '٥DDySB^C9SaytUǬV5@.M r/vRu m"1Ou_J_Az"SE7~e+"utٱFyyV3W"u`GGS+\Prq9 )|`Cg (LnM>L~[-{ P-~ MO>pGH}UJA68A7? Ҵx`Ŋ6 zHkY}icЙ =\9g?tHO;<MV<>Lٌ`CY^BKֱyRb'^]\׉׬xBib:s lx` w [+vE+?IǤ޴KZ1.2Z]:.7 M=dw9BC._e52V{?)B8u2BC ՝{eGYnS(R2㔎)Nw'a{w"]L3 O10ØLxBkCj@T@%y#!A*˲2UJKE ѥ8m(y,?z%Vwceyueiic9X^[_][m/Ǻvn^~l{u6{f=lw{ǻ^/wVs:sf 'NvN];ݟ@|ԽXv nHZYϡ6Z=C*`H́e'R(L P : X+@π34v w{0%@΁.p@G%k,{ D(Ѩ(@ ڜJTOX6D0l@GhϑѥFwn" S4*@+k&* {ץU ;bURG)(NsG+x~eYD3=*YseAK`]iijB#?JNRZ =e p#vî,yn4 3;Bt#zVmb$Z?[ZSԢja o<9X'xB&B T"N"} A` ǃI#8C#8)Tc9ZvXv)XUk}f,1Oa#+ p2dO͒#Sp),KP/\(CN3R⾿"m[ᄉptP2E WuZ˟cٍV,Q$zpzA^'Gm0`Kpb1o14P)V /ۆ`h CP_bz1MKpVJ}@qr`QiFrG- uxo "J-g, N W˵$L-&I*Dh |簬mC/B0dm- `/ȠzPC4͗lbCoelx҇IvSЌY =~;oYj(ъhb3u/5( bV0MQ*H)Slrˮ歪2c+m<(')#WXz+J=iM6$e``TSE8͊$g}*ИNu+݆L)#VG$+iHϴ]9#giߚ)v]gz)zYÈ-JS5@&4rh)nɰG&V=f5EAʔÂi_9<+ڬτ2Rb8}BQWcٮHKCQ6;uC,{i >gkkm0 #<h:3PQ0k(1;e"%8i_@j;:& BVCeMRDOq'ڌ]j:b\Y>3b<+@PZuyA@Nd'H! 0wo;yRMBHoò/) ^X4INÿAplAhЇ1 G1:?ﵚI^€ \xJ},QP̻rT?i>BFAʐܠ\C:=)$jq0SʪkU f(%5hHuS 6OaPyV< ԗyx'\ёZ^vFg䑊/aspač! 7ok}3@?s6>eWVP F7TYv02i\E,! Q58D`$$vgI>@AZ?gZG$Ї=R;m*Ry)WBq eU>3( U!IJ^!*3Z D.X~.0OÉqcZz9}}" 咋Zҙy~ u 'yB}˾bKTRωГ"pe}9was@;hq]*C:| 0J 颫EܨG,kOѻ8]:@8@Q:Qh<7kЁRgJ??e/0nI9}TF Uq8ã/4Xjc$GUgsᭃNXȧ,{񶀘E/?vz#~pH{[^N(9.ɪq "RpNړ+l8@gpɼRZ=y,sWWTQ_5@0?(zkD1}aXߴBWc%[]upځ͐Yԓo "jJ- ͕ubBx[9JwjQY@JDWP!@g7%1"YJh4ri@ Q>ʞSH*Ϡczj)BUV@a,0 85ɵ{DuAI6]%o4@O߲Fr= 5 '#>e ~<3&y:܇eW1]ހ]$y'-7[|-F)Dhi+b8$܎b,pfsz~L8T=˦ckZ/a’.F؛5]vƍT@yVw*DQDG'Ff:o!<U(JxViDH_WqDz}c$!`IQT,qo(}LEϐPG~O?odrsϊ} ^*DdoWj ;W\%0!cm8sI"M)²L"M1X62Ɖ8Zwߤ;oQxzbٍu{?Aͅ#v]ڗ',5+ @gd{dDe6MzŠ +pFtØ((= X؃/OdDK@fI^C1eIWcه'V I!ѼɳxL @C%bx:#>k򕳃|Q};;Zu @ :P]>}ΘHma3E1釼2p4 4B=_َ4O)J_pU>d~Wl^%IN;AӇڅ=WbS6 >Je7lzD a8_^A+O3&|zUs2O\#AKblhayA}i#b;|tb;Hο]Vv)%Yy"FͤeH)!{~j $OL z1]T}TSZW_#Ü 0 sA&ɼ+-l!FLCde1$s(ߟb`Xvx=<TQcea# 'n鮰Eotyg^-;wIVD*yj0M(,l\PgmOU,qtk~-u+핞~5(hqώP0mCͩu&G&TjBUtp6h(ei^٬8W\ ~<}<yވe[M# 筇eav1 ժݚ "#mUXz<{WY;*ovUA7\!8p=PT#N+8QQ ulAݞ:XֵB#Dov[.uXJM_'ɃQ 8 Xv&^٧uPe/n+LAڈ{PE=yǎOOirTlF}\h1@*UVs2.sDmG.`SO`XAI !_i uTBT% y PDG `EG8Rk%3CdҒaɅ8!7C]5sNQ1POrfQ,gێ+@@z&?hDBZ[P*ni:Zvd0^ltVHbkΎs⨓,N kvmuz;]V}/gЧSd a/cى yF8_ A8._b@2(0_ò+j 'fwT+Wj+$a0PK x6O$c'AJ]@Nv鱚1DzkⅴEB[gre1C98|ՠVr: m$.Hvr\YqLSL0&=qD"-*s#?ZHa3wZ"0MGfpԗ:吗BV8V5ܩaU{7EwO!:Q;o5y린V[$ty1aUSX6]rzf_Dh| 4U-ߜɩzR/xN()4]W BAݥ>e_7^@U#Q{(: bsOsGd6xsOӈ{YZ ɩ_&tyN;3Aϴ>Or&|Wr껒~а)"CSaVX?޲CE#1%Uս]/G }a,ioigW.P_Sb:SXv\˪j=SUK,X!žp#fiYؐFU)t~߬PBMsD4A|[ڞm9B(.S6 I D BU.uZI]>>]@HfPhIXI8R܇O-G} D|\}$ CR%(pB狗eȊ&ho|nʂRD\h2G!(u߶N=E6@ 4j4K;_~c@%HVYTx{)~2UVh+C"_4_)UE?{>3h)BCh!՝y%GyQbzWD 3?VI]G_ko~7l9ìpc@9fÐ@0,#l 0 2r@DBQB"%ĩ{(>򷖵?}_}wE'Ns3y:57cmEmD[e-&nR:йvoy{=o]ߋ~w{ǺG_E~W^qK^ndiɁkN:WNzn'LL_*9y@gD{E - {}BTB]dx,:SN"{@2Ch'URJ H$}E)`%͋:w*TvA'pe U* ^Hg,"R [Hȋ摚NݾS|̓rPMpɳ8yO7Q u} u\8w (@v-[ 'vYu3XEb|"u"7ç4^1RK @Nj ^PR 09UmODd[8>i+faT\` Kd/ФoQ9a.]zQȻ M ɹQ;MJkpT0ljE4d |z!Oc[sz*@cLv&lσJyn^BdgyBcnMA _D.mH"¾~Pr"{.#c͆`^AdцyZnM5D]J Ψq^M8#}<{mw۶Bbz+}V) 0P{:B`BHv*wtBOIB*EyθD|Ob\0꬧+zprxm;O>^uIw+_u,]ExhX8!>;O~/|E>bO^GKTu4 ]ΉyDxUfD#^EḭF)U= =haxD#"ȱt!:uQiR.n<3'ݪ/"0<5q4)͊5fI-?Dc_0vL)3w%_7 h6ƬlrУEHrUVᲚ"$YtU8 9?M*vJO.RHlcmH+ܙP-?פ1V]'6z8b(>$ ~^;Uzz=}L F,9Nwu N]EDM&&~P@>Y/C&w귓`X%w$JI"{6LqdeoԲ/&whw O -XՎ\WY$ig|"Z} }@(.Up;_ޭz+}PǕ3準66}>9&]Lm:[M]1zDvvdϚ1@pu MDv6|<, >lr顢ȾK0:#]N&{ϴ3c]b[^q!u.Xd-Q[ۑ{)wsW0]>e Aֿ11flYw"EInvVUn5"&L3usD#.[Q|*SOSfM7 ĸT)+D7 "E`TZJOˇȽd |F7I"o?6 C: Iivk4TQit%ݭhYK&TI;JBIK NDpj㹀OXu!ڻR";@d"u,oD>j=Sd_BܠJaj hT{6 aP |=p$3haёJ?/ j##o'WAyѭ5,uq':1Dpi+MheH?ֆCGFa iޱ<ꎽԀtQy.(v"S |8Ȟ]4KK TQK-F\gZr&} ^hPMƒ>V9 ji ^=N%fz1 x""]2ۼF7x%2d63IKCaNIyTttM"3 2_Ѳ&$"lld]a:t[jeOu^eB=>Vh`O't4[fe!F;㚭L\t _խ^?uR O9hbV?+v~~D!y~Ru|eH_4Q{_Ph@~ƝݲJ GvQupn CEBL(s"6mc5S B: !UP/8*mjh(BYVS)"R|6a1O*h:;X܀Oq9!sP#!byw}6(B܉WO]d<[ tdDyvN,CO%( *s= ĖNg}K7tĠGKWCDkk,fR};.(b1Y5IB7յx?Uʞ?*w^[V$Mm;yu2k G!UGABHM Ǻ vLЇ(Úou%lD&DKЅxha3 Me6g\i=ӅSѤ6j("W ٰyB 9Awf/3 Z8sN68N:6eN[~Ӭڼ2%%NU>a(盠l >Kw/pɿ[ICShֹ=usGG+-;*3BA{@i·LwFʧf k.5ɸM2+\-wz7᎝!;i 6P }Ⱦ] Q uzv>ak($kkh ߲- 2]eK{#M9;`0lw9":bKEAoҩTT46})f|݉CtL*`M&7kkJۛ+wR,56XlGep8muGU=&mCd/Lݠh%8h=hxA hAbky+h1Qڹy|J9@nwzH}tmjOOP}>a ST}t횼G0T®1>*j݆gɟuGYw!vꙶy(UPlˀ']|zP@]K; Q ?7T*;" Ĺuan fF8PF5T0Eoܾa9&R"~p2Cun%voj}'NsQ8@3{؃%D0 /-2'v f(l NԬޫ|ժ }^sGlz/݅a|7gg Yw7¨PUmphϟdyʂhCkhy']y #̧t摟WQ~IWp.jTwY L BwMkܠ.>VyU* ˇM@"lrS>;p^Gڞ~V7ʉ-I-jh>Z2ܣcn:syh:Q"?|l%댈"{b' N h,¨xVG45M3۵DGe<ЈOwh^ D뾾AEա1 lYEM4iD #ʢ9H7sF..b%_.x}%&K&TeLoYGrQEG9kqp3gixJ.BxD6 sy0%g8AdjrT9_ ˳ zg.}fow[QemQgaöՒt%5yD|wA|O95 w|) qmr}$v@OkWREkD՝Е(jsR ";=&[ME}: <1ϵ9Brl`^IH۳S'Ugn7 )(Ȑ?uz}ɓ?-=Fw7<,)2ާ6Gd7d-ԯKJJ668 V!)*[lw<2[s e-Im=fK,&kc\oDۉc$ CLvVrǒ0$"*[Ľ-܉YpZyJIi9YBc )_aْu:T0?&B<7mU@aK,|gTb׀6uzMz5m"Gl-?@B,]ܱDT)Myk_W(/6!D2")iCv&BRn3mEZ-Y5֖xBNE <a/"EB^#"$.@ "0>'q]$HŷV/T<7RVf -4? {G$g#ؕLQA"4}Ko'OiCyr DHo^פ~EW|Kx@TYu/t,L#|3_#i+?>Q։/w=9rw:wCqҲ9`y%_7,ey;d:W]WL3".[&+'FC9:qZqnOu`]t]r^gtKEWNjr9Ȩlvm}AVa%_!?Ơ\WuٕN`o"Ƒz Dm qĊ׋6z[ Q^Ҍ%DnUP.z?P"_t`t)9woD~V/%8H35:|a;n@!jV S-s嚖&nsO^zg93SXj꽈}힞QgO3߻Xjx{#YA0fM * c(>%B44jhBq⒤#~FD/8 yG|@Kyʪ~AK FLNȑ\K1>&F&/mzHX? Gy ~S [xx{ME8~ |GlٱyQQFDǕ]<}eNj%K;,DT?qdZq6h)RAu󏱌 -#Mu$&4!PMbg`܁;( _zr'6㧞D$ZJ4}>LP8-A%~MhU TC!,i u;$w wIA=~z-x4hC*mwyߎT.JMc=M"GR*G h~s ^tX@Bc5Uϊȳf!}uҧtFeKD:|>{ ϖ#.؜9,nx| 8|tq<&I(B ib@~*ˈڛ%\6OBgDGaMpa7UqPꏐ[9œ̬DK?ixH:yߢҫU}p%/ovvI*=yUS}2 j=pԏBC!͝y\GyG>oU6$V_-7oY6Ɨ$0G¹B@ s8@>ˇlI )RI?I#y}7z=cےJ?}_W}j=+eWًxWL?tK <=б0܋c `jo6߶mlloonml:n|݃nP@;=9%nr]Cntu:Wm'H]ueҺ{=[O^y h=$0#Le%uB@10ŭ(xR&GH0`N)`.e}"EƧ0^}nsCqG.ŹasR91Djm LAUAuL7*)3$bn"7Da%^1ǭ)&e (1E6$]MuEPɲge!+n=PMa^Ddo3ՀhںpAs4 ZDn]3nx)Jd_|͖Ni D[MΞv"; Gbtqr>J]#5[4m#Y"ִA#a[cn= s]Y* DvZ&u0a i۾$"1%I:6"c 9jT34}i={EUgJgi7bI홛 71hE_lPLŶ* iCHP1%#-E1kiHu7;GS( @>cD༠q~udrlm)J e\iw=WE 0.  0`Mæ=Ӑ?>nХBvn) f9 BDbMH~oi6MiǎoAپKr96K{Gkƒ2{TCYxp~F5@'%Ŕ۟&sG0b&`pH ɉF$lPzOޠ$'@7%A13Ho"Y20)յK+Rj}vL<;i泇!>PLiv$8lX17۳H3Hʡi]$2l 4;- SȾI\$ F '9ii~m,6C͟&I<&甑`.}<= PCNث8K:T tN+V^92 aGy^3 m("J$B QJ]t{-j$䠮h 6Ug5/f#$%♍$cYShFCeky#5ENlluo{Xnlt:uNze.?w/'ɡ^|s{t{ h' f7[ aδZ0 n9D;Kj6LmYOn܌z8FAoLOd/1 ,5)W_CMh/r^fq𦞈E ‚") RG6Eac?hCs( eF%=HH͐ Z DQ(&{HaăB`Ƴ[MyVu@؇BM;2>xBP/A]{8~ u1#w׍x%q\:Wcz3o]sPw%Dg|H<ϗT ;Fy_@J@+ &@Kc[Oٟ5W+GQ&" dlX?ًLh RlAqb{nìtr~^mB;\{F??M;Lh<,M0Wn]˺(*K @5 y ζϪ}ݭ},tRjy=X7|%hc¢24#_Ν 4H=*Eiv^TUyTG.ˎȮe Y >٭rYiW>}{c2!`Փ+ɟ.gչr<վe{=A >@|絉T'XMkWt@8uL)mu">L#%-?};N${,m#u-/WΧ ٴ0y|2ΑkNږ5/ 9k.lX_slh.d:n}=2ɫ/Fެ4Ym7y}#9MDCSYAS@I ZX*(Ua:*U9@j$"GMe Uk~yĬ $["IȜO,T-N6\1i!D_tUnE9 ԉ@Oio!7  ubåX9W0T ~t*hlY㦚C ?sA6 pepy)ۄ݄nm½tU,2HYo:߻RIڻ DG /]a\@!tNFֹx"T#f{ԕӻިGrt[XCs8&,N.Pה' =3u TsDr71,ZAjUlxc -lI'Q,SDJ#HK/Y}4?_R?<(!PsNhi } YTGi3Vb,ɛT/fh)ibDx\$dRzǧOjfX$ TuGgv={ 7F#UH%W5 [;LWwNe2x^]!儐7>Z,eIĻ,fبزB(v9H\x}9-[=\˕|QɳA{*˃S <$z_nGM8`&)M3u;ިS;)pįw#PY"veybS18s.˶euAyTu%WҖ*o|Dh2Xꝴm: 3š$گ{Rj 7ugVit NqE;vi*q_`N HiKQ|\:]bhz@q?´0Y=%+]3H=S8' PUy _&dh` 4[6!'N*g 9Y &uuDMQP񲴷,&O.S%Л@΂WFau`TBj-1"G':YE:5ߏUT%zpvpφvF,8¡tn BE&(Q[K!n&+bXeHPWR&u W9dEqHy$PE㟠V>6Q9V?blE'2NǦzfA-W\Yk"{\VK1-?B"[טC[/9:R7DN΢U$_&POnA9 #x~Fz7;Y̟\u^Eh4?cUrn)k"nj:AMx>Bސ^ݮfHl qFN*i9բRSexYq#׫uPgP7m[cM:N3vS+ GG8"R#VGch<0'̚k=yPv, F=qY{~C)6S0:V}ZY>/ 2$MxOLj]QRxSV]8sxk+\ŴnWXmt1eb '".+r$:@+a2.ߢp:'5l_FJfq0iiD#nv,5Jv0+m:OYt$!#>H}JVlH#<(르ht&4O{ 5ۥ$6=π *LBng@i85QY3g0\ýjф rͿLp-B5휚4M0ܥqt16 Սj و/dt@\%MH|)F1vC,Uœ`XwmC`K"wݽH>,H+ D;8R-ݡM+ xU[U6`dE^cLi\S!Emnt#<}8YÓgI/U|v826 j,ݩXkSrOI2֞ >aL"[3N~oB2Z K#pS54NEBS8eh)q;4Y]S!,:Ԋtb5qЅjNy7? K-s aLje6*O&N̎JڽLGu"XΉBr]y ,HC߈ϘrZ%wDB8 Vӌ&+ #%+h4K&oR'HM@㑿SxLRHipIH3a |%}L~y'K,o3PbgWt=*܌I5{'nL'>$TQ)k"]# FIYl}/I@ %.ѰF~-FY],Ϻ]nzW9zc.T =I7,,yzQF7bC܂d)NSGݾ~Eaa <응]6}bRI%ԽFЪZI6}YQ.;Ҭ!Iiۗ?XMb$gvZ@l|M9_KI5ӻepP%Զ&vr(j/p H#\xyKYX(݄yT":e?hrQxo+o^n +T"UZ *OE fê鳃<H!۵/3f - ik U{n8eAUlHA 7_ML.`c4w}Db:0pggOU(^WU~u,ֽa " tN*|+F6| @{'GdcdD!' tZ"=Mu?cNXP`Bps?+qUDY/Uiu&6oBC ͝y%Gygg 0E(iue|~(LQ$ns3` (qLGp"!w@(T~]ڬֽreOW_}W}ZϝK96YW?_9U ] ߱{BBμڳݣh'vz#tޥ~'.Arb_ܻb_?.ɱL]? µ_089* 篭 {(ɾctlHit !CD^zú8źctuD{.'hUAŶF<ܴ9S!gwD{WlĄ\Ѿ *LudU$!v=Fa/Mjg9nt77͞46W$,~35X {i<F I#^|azi Nnosvt\C^&8ӉO)Oj!@T ~j0LB,ԏZVӨMƑpAP (Ѝ{?aP\Htm3<~.ܤ=dwԄoiamxE,FDk'k/6ABGڙuFˉ(>ۈGB~Qrtx~H^g‚ܱ/FSer@o+uOVh|BhLh+欚r$VSvtwv>a]4P˙lUR%N1`3Y8KHF D4(ݍw߭ FK ֏ 54Ⱥ#.=ɻK EBJm hf@)@LD+L"qy~[yT4T |d.q[5. W_o b`+&A6m`ሙW ڣ90'Y{ ウ#tӤCH#L0"\V@+򹮖u}7фBauZn~u";Mx|~p;`Oknm@-B´a/^%Yxvg2dW붒d;_ V'5taD3 H,@+][t] `W}YHͳ>IE}5gR$5k&,;d5q#z+Y`]"eD0j`r !kw4ڰfO2˨_!2M-h=-@YA.$kW7(H!~'yZt%N)LJaݪ*@wEl/u,%Pn&"~Di&eˠ*yQhhsh6lQLB:6 MxB?sn ޴%>wŐ9CvM"9wLW #5ӣ?av^jdҸoF4XH%G=h-hp}CzqBn0B tqwگ@D` Ζul ~ $U {MEa5˕:$g~h6O`ZU4?Oh7+nNpS-JBF4ҕ!c9ŭn7b~gWi+ sr%ʿsqNՉrLLtLCbLhI`\ Of{ޒMdxht^M^'p wLg+f8=\81Pl:[!חTH5 |,P!ص 1\*{G[HS*7 HbgPmXI_NqPkw]cO8 Ĕ]dHot}K7`AGڟ4F/q* 5ɕn:{ZT$=^ 0t#Ôn9Rjp `'t6)Qϊ Y~U23p!qfWNtYFLb]|]~%ѫ~?̟٥8=8l\DywR @I Q+2R:ZHp0-g_ K @4.1S&L8@tK-bڗHA# i@ U?c΂Χcݤԇ" Y{Mi "{JEl@7GOVv,v:&CJ Ed_7Aj^D&t1m 2$a"7YػC5F*=3f&R`hIu+|j:`J'&:D7bR8a `$*>U !kݻyeձu^vks1+'k_Ҥ i0^= QЋ3r"a証۱vBT{5{MJ|Q|Gb#Ф9axIn5 yCF-oy#CRr{͡׻~GIzLe }8T|xP#8˧?#>?g]W:uaEL65h1S}]iĄ"Qbgӂځ`H4O 䐯o(EF6 YBᘼCp4A޴.%zx؄aA|< *džQP+C_J$,N VN3۴ m.6T"@:@ H0ZO+cOv UƄ¥4Xcd$쒄ЇLBq'۷qK%Dbxg}WAAIVg1G٣TH>]^)^XٶQף}?"qMW)%Q{=ĭM&h Ɋ ЩfPOjE_,XNV:/Eӌӳ%$D$4<3rQ d=h8tp~vҡMMC(8]fM_XU%Rn)ic?eT0O>  Tp9] oO"x*9wG❮ЧڗjE#¢t"_=ZeG%Ws:T= ǫܓFP{K:Ρ8.iTvWo4ђ89aK'7<*3skORs:ٷvTJIڵ9;AJlֻ^зpF 4mӼ՞ДDѓ)4~DT0D7sWt33Le yL5(dgV#&޺+]x[Ns!eקc!C!~~gģwRUG/|6N|f;xۮ&^>H J}TϒJNSs4ξ@ű0t9j-΢B^9tӅ{f tin4 ZF,x!Ti1Uq UmyR\D.yt/H=QMwU97xO4U[,7R7|$&_YN&dVz }~#y+-U}L'4;MM  4(ДTR:: Nq$KbZm'.Ljkm$5O+jD*Gk?Fa:L.lh㧌z'Gc$xltLrtpٹUH@XrM'kGEIfUsD2#ZPΊi&ƍjþM>0 79jJCΠ1׷j"mәXO< Äh_8u-RO (@ww\<ԩfS4ϝϖQ_}1i LIDŤs~TtA<`>mg:Њ؈'/W#xCٵ“Z4Ҍ*e׹RAr h2Ba x䞅-r fă6%pUY"3yZ! 'xS"\F69Z3Ce#HlFnԲU]y#u^] ZY"ͧTƳ$JhT:G_T(C8m2mRC# 3ɇbٷL >e/#" eV:sWUh+zpܶ}SiF34t(wH=96%(@`z:ׇ&L񃡨o۱m{U&@*sMˑBcsvztq؊1.E 夎A@X0YNOs/xP5CX봧8 dڭ4Z]< i4#cDXcJC-J%Rj\!R>t ^ESznO^xN;j7FhN_1:#"!gPp Kxf[YdyuZPhW$|6lBrdmvOlw]F4I_1#~r ⌢qbۍ:W bٶ= God1W7zQ|`|6 ;!x&W?ENIY[*[yMAdyXO̡++n[re88xz ±j)E!L ;2@ B@(M66/QZ- UZZWZ17iȞš0Ul ЇmP PV PׅPEiXv2Q}т(AIT\'Z+DD܀_U*]`z19;O8qLnCAL0ָt;^z4h=Fzc#iXF.%}K.>enwI+R\2@?On6Jr JƠh}Gm:rK@fCWqj靠%LeJDGTƮȨ1.P%xI>`ʃ5 :Gqpӹ2%>O0秂heNoo3꬧zu"[wvTPB댝;;uepQ58Q;( I/8a_?Uxx>L>mB^<: <[f[F(vd;M0ɓ' sv6rQc3tWVJ[mlp\koG 0s 7TBahԬ*ӸO/$ƕ5KP)ZkݢV([֔(M NZ9amUީ>$ё>A~6[ LvB3?#gϷ>,AhJ[lhǞ&'Pt²[=5y4Q(I;F2=7lrtgPM :NbJ gK:8'FB1|`%NY}hTh3r:`%P|`6UT%=Tĩ@qKyq_jNI.+*uI zQ(: |qԁ ̗\ 4Z4poخds7w(11z2&z{k['A)3ݳP?vDsj2%bɌIji6'bAItEL.ܠ_f*Z\JD$osaԉ ύv<AJx?4sBSfΐ֙*7(QQuytQT g4żRN`y&94M-~np(JA2#V)b.|`T"g4żS 9xXaNL1*yƪi$3y1b"ꐳf gZ& H5d^0qN')S7:uD_ @B=!]DKHI#WO Hmf"Fr62MC̅urD f}<"fDSR<ĵcFFeThFptVgٛiUd*xε-}c;qmϸUkw$n2}6Q|Ò2hi&/zPUrAXN[֙xZ)-5Le4"gcLË F~[ߝFٽD@lZYkXa4_&g_3QŃ.?ު'􍞙OB@(Ze8HbAqY"+ {j`1eI5"E{(-Py]I W=Z#$ZkHqKR*5#/S>r=4R opPa"}Tg³PAyXg{>im3)"i[0>DRb0(m H a;~ xd#ӺjHTZ-Φ sI@ J (־Hbwd`8.tټ@/`B.l9RЇг :@Lmx@ʊwR"4dA$z/t2m2 u4GZU3h64@\uဒP",*%[mK@t~F!]q14(^S`fq :A^a 5OfWzSl*bkrt r~AV.7U@&mTrFD;}0& 4YaכG8rϦ'*x8T 7`.@\| :(Ic~2RwJ1Vb=҄Dq(ʧ-*\['gA.P>@Ux.h$>Ėߢ:'Qe47YTHT_yGֱ;Brv) 8 & 4!g?g^(@p\\8 8 K82Wd\±u!C]ɔ&tFu~TgezU]2'29&NqB}yG{cYH#M"ǡՎ|8&D5vc4׺2ORgwΩ&T=ӽaU-k&eGzT!p0HJtq!hm:EE-zENΐ-0I!FqSl}BqZ̷o88q&oƩ>::JX{R9>)J$Dʷp>aH]vx *^?F +3>ν{DaB#v8Xf)'9.?<,JZzb:DB\2yn &] S),L993.8}o 4ǕH^M~rXAW),G=}Ɗhe:=I|Bg{C;3,/Mksr(I+Csh#ËmkO[p4J J#J0Ubm/Mc Iٶxb!0%H;9;iE#nm~2jl܆łW: *esʍ9/ ,>)C=PA9P GNʕ`lۚs};Pđ ? hE#0KFkd$2U칤CU}WBVH N-puРbfM1C(]ʝU5Dz9{isՄp8ųV5.bu5 arLCH+lP4!LkT%gw*DD9)"v")jC *Pϧ2 1`sȘ<~vSZ{^yv͛H}p;+EtჺҾ: ==Kߡy:!RmݝU8s Ѵ= M+Jq[k׏׽#ֽnݴh8W@2ůZRaV̀ʖnJivNBFVz%`OcK=RZ΅Xh S桲%唋 1ߨѸ=sZ p.܅Pm8G)&g89)W7inXsR&<`>J'͝s!sl/)^)0WSw=R~hEq\J8K+6Y+l_Elwp1PYcD߀fW4WxB]{Pmb;vܙ@zM='-epiB8(N]{sr WYjqvE,҆z2]!60Τ5gf,5fINX :ΆD %ad$+hxup,oGLPd,-@N ;i|Dq!(V,\S0ί&go17/M#.hL>.Wou] Hfl׸)اkLfrvc@3]Fy{׌Ws...њ6ʨu@[ 0 9c]>a< g-:jv]PIHM`[C'(hoH\4NW,4oiph3It3m"қ\6oPDGD_iŠ(JZ*5#Ym `m峫Q'tuϻxK,:@g?dEz8=viՑM8 ;b);5 E&%s1!Qr(RboF7A #KT=xrJ*ՈW$ 8t ߡgȅx{ jt]aUtÜ$bd5<M}[G󴊷hp nz>0tل64?n} λp"1q um68 KjF3J2TKa49Qj"1jF̉ӭsonے?iLj%<f^jRbYH R; JHrP.DDEn׌L.QfNnbՆXq,P c}pdvFJ@Ė1 Tbi>>LcR9c [GÖlCy'gHѼI(7SWCmFX$c ;5M}NHY2{nr&ܻOuqyDc3'='QM2&l}7YAjsgw.Rw&4ƩSFfZ,єVdOk"ghNS/$b ѥX1~%9SŊeŻ~fb69{R,х *VWw:k渏B}6Uw1 *K*"bZ4e%(%^ݦ" `Ewƛ4 u/W&Tj 񹨫J]֪ܛ'!q7X*nEhE4kp0mF]yS7KVYJ$sFDr`m[:clxZɃuN8w;TicmJڦժBB 49MJVwubqvauETC|nē}y47Ǎ>S:i\9o .䓳xZ=ʣahzq@4@PfF8YL' KCxޟ]@kj&#R"}%Cbpʵ~1;XUeMV͢j:NC.݄|R:ֳ**'iԩxr[7?q闬 8lGe;X|>b֘-VX\ %OUFz5%VVܥ8~Mmq IEɬm%il4= ߣkbq'"i^ ,01"jvNVDĈ]fE$~;m8ddXw)} +4)N}\''<}SY% j@04kcn 8]⩘ӷgEژX.AߘvRߥBC!͝y$Wy{g@(LB0c\zzmeuሉᲘap$anpG@0B`{w06F")罪W]漢z[۱V]j}h\gm=ϛL_vc}<x߱΄π`4hGl﮵Zj^u^u;Gޑw$u{G=r#nt:6}O]wmIoD_;ٟv\A@Rwm_B~%y`;I r  (y)9{ee; IX /Zs%WN~C~8-J6PwPtgw3'aq(xT[QI/$FյtuNБQE;GNw<=t\5F3 VuNTWZ++Nm;띝HօTrv،Ì dLӺ=&?ƉtJr\AΞlKLub35GΞjћTĈ%. 9U.9{!xE@MKv! %Qי1a pLSf~ܧ3N>W5A h2tc]RպtߣIӻv@r`n*8-ۍS4%ϸx,;Lf, $߽U)+M).9 \87,`ZHj _D# @;V!((Kb5cx ԶxHή3cC1?xjMΛFGO1 h)=͌'C.h\KbDSyN}xGuly`<}Ղ\QPX+Զ%}i Su' mfL02Wx+n$ %%A6͐#;b>&aH;ZfW, T(A 3$`W]f@؝;igK7`}NwFCfH4r'R: ~_#g pЄbמGD]/O<?a"mQR Z E](WPßF۾ @Q%<@pUZo0׭Z;FpOkG*px10;̃>/|} z38@pӞfAԥy4XP e.&O'?\L]] ɰ"3 4,ʹn>2uz kr8ŒIUϰlx'Ɇo ͆׷ AOW3ENaˇ}reg[`7A"^Zhv.["p'/g*OY=Psx=A2yFn*)m;K&|9M1df\)͘xfrΪLDVucKRT?V"Lo#g塚W'L猕E{iq%B1D{sOOWr}vz@wXYrŪ@0TlhGm!j%؞ސymVKZ_<؋Eɚtmu OhT?tOFi1knpz[5sc N#~yYd%áɄaikc#1f+AE#fH4AC iuR:R{ 8PXtQ4TJ~}>H,É')Z< bIRU,#fH@L2і=Y˙29Yg%-ьjպQ9=,ݴKA^hBg<*Ru;H()Z”OW1!$ZeS{fț'r;+ 4ˁ[z5`ZGӝp-;FI[NZ< Z߰E։\@[Aq%*^d/$/չXhjtx!WYhbb>h@:b4eMܫ f;WT,O,9a_?]q+gHpW=gg)S9O]GΎU ^@YZhh$x<ˉ 8BUBG;j.mˊŎ5l9C5+5g"3NFHꭑMի_S45c頋Bj,9{KU3Mh%wW~W?#ޜvcyNƽ ' 4#(P}A҃wSAP] ZNCCD. F`MM}ڼ\:DYn)p C}X};'A7Mp X:BDDh(EhOٻQ\t4ԿSH {5${bmq>5s(W@ B,P/:-qbyHkg @r1g\8p4p4]tsidvgSb,Ji 5$kHk.эZO溝*R.qU*3(8+3^ˊy#Qڜ3PrT/(Gz?9Pe+u5[>?F&}NP,$""j ~IE9rs.8E*|h%tHi|o-N#1]"i+irvS嵃蘘85]HwdEJ y~I"aI.myKKWQ<*d5U|H^w !IFJd[l嵃Hh\tD7P\'w?jn@TXbZZU+w o\Gr5.PBQWTm=~>ӷiia>.6rm귘k#=$<0{Nohn2ˉK>PHc'㺵ohVcuPQ8K/U}J@q'r0o,#Tgb1n-_& hKxG0M u_YDƞh4crRSsDdG`$3@P2%#H2 |aGr5JjA꫒xuP}Lj "qOӶ\k>ٽվTvh몣!{-g5c顐sEz"2v>\Vh,hd8䣊=i8JϪ*!j&H_) ܯ5q4@#wnഭᤏڱj;#m{;jD$tFlHH֍*GŪϾdXL0s4¦}-\"ѦΛMxGIAOBtB'uKI/2_wЄxIX:+bU#P?) ; \GqujHGs .9˄n`m`wŮ1V"ziO޴Lޮ=b#T+y9{QՖ &Ϧȳ]/}Α;/(NA_Q'(3`\ !Uy9ɋH_۩_I ִ>v d : %A}}2T( FQ>&ۣ}U cv ._I+־(Da_>䓩E2j˒KհJEM YvʍAqN:4:sҫ!.Z̏j,#g7Tmՠ'$[vulAHΎW&r9"ƅbέXpi<rl.uB CGD ד$D o)8#4 rגWn%b$Gdn͉2}rlgi6m$1<[frUnGJF@|l.ȓ}/7a\&c5_[;W2 y+o.y.E?ەy~MgKL-%֛?<2] Rq}B5V M= #& M_ŝHP~F҉hRQn CF}FW,@0e!PrFXFBtD:8"ȏӗ\2uՖ'!cbnK/ˆ00;-`T$áh^ͪ!GɅC_ѐG|shgJel e͐3CÇ諑e0feۊ!ֲ$G-ӧy.P6A4 V$B%f)}RAkH1ۥL$hpX(5 ;`/I%DxFl["\0@ QdQ[t)#Wj Z&g (]@s͖ҽd FjŹe֙%|؀%)'pesnjr5>q(?xzy8vNήڐr#n|g,KM~ _xƂ"KH,u@KiP;kQk3}mJmLuLh꩕wWke\|^&r˕^^4,gZ~1uX,XBA|B l2? Ŷ=4?j}3z^SȮkSu d=5 1EV(]5ڕ/'gUŀBB38]?T#oAd+f.*'o}/IX4Ź[Jr]  ,"/W5MVǹˠ1_S dٻ6%|(f<$ݐt8ݚ!g];a Gh1vMs-{=9{Ce j? UiQ+E< ](쳨[˛[X/iX6,xF 2/mpPk(#!կc}vX2fe;ٻ*/tCSW5f6OgLeHw6Mzj3rZ}V>}Lf]~0װ&{@}i>œ{j)'M1ZIJXJOV Ջg7ؽxʾOrBGc :ϒ?jj67n~ýfmaȔM{Tmm(Imd.h*(Ԯ p8OAu p!Ujd I;g&GgPpS!7ƲS~[)AXjFHP4PQ_o^Gc*1-IL˗;EYǵ'-SmI*Mv_](=lIsnUJU-Q)y.VDn: ~Yۮxjs,Dz!S UZ l8B\_UHL7B6Fqr= pד+V2t ެ-Ev:qXna0'V"΃-U!O׏%xN5MVBqaFJ륫N|+M3+Ϻ9 s|Tʼ {19{IUIl?E屧S_`Ͳ K}&Y)^'{ƝˬrNo/9me&9{Ue 5>}XvYk5*"uu}}$u!u}@OF yd_ȣwy#(L.(`|C ~Xq@uP& //yzP@7ڟ&A@Vh(' 4A+ Aò/ /^sabrH}}4$}h#挒aZVO>D>[-/˦R6lGvJȡ}}4VЊhB־ZajsTU4Q54RdtiHKhM@#Byo1w\_ D}n) rT #ϛ{Rsd̞Ho84f vK|s{J*FW-rɜ~ʶw(?7: ~9ß&?)Ї@MU K y eQoKjckh7׷[+V+i]~š+6WPyu}hj; k' Q Q^ĩSĒ OTƔjmf*S8v@LO֮YS#4thB ;"9+Ye;,% @q0DNRr., $'0"9ɉPә9=`m[brZf9mJO|٤N L+LW1#"V"lġhCy4rXT|^dk Lsb9Bh2F-5f6 2E\,n0cG ]o#_/چ1f)Mz, ;(=_gs*6@xi8Ӻ~<Zq.4 Ҡps@ ~݆LJFJI oBO#4o cӘb$#DEP"c e:N'BOi"@!@o%G8!Zwq(`h:лlș\@պ[Vs'J矋T$HBc V8F [Q@$5(A@"Z/'k/7$Lv h-]qq;^'i4`h0UsI[Dޑe t F; AXCe"DIxsAS9'tc Uo6<)mD^ )}-h3.9:xלg:, t \᲍`M J՝vrD}/K2"+|rU3 k4@3Mi>5> .X#iC5:o)JD؃ӜєVvkY 4,pz[Mq\ШV#XLw SrbאܼR& 1+ )ۊ=y{l|J%nQZJ5ٌfdQ3N*޿@6~ԪWvvÞ!r)+v ̏\7M'ʇZpvrX7Ӷ7QUG)"Yb>};WqMT:̈~%4Zh)UPñmPD FczA3Ac]$k~y,zr̈3Dw"(17"Q`oM"R͆DB؅X*;ֲRMTsf2%3Y(G qhʼnBݜD>L$dEr FHI51I)2Q's)Q)Ж+c b֗qD v o XT1 &a0LeC~Z9]Wx*,EOxbKp/*yY,Np&w'M$=pSA~Kd{0 H'g9(=+4զDoʩ`$:MH5GDP׼-Y AݐsCҵTn,a8FdDF8Kk TLtJ>c$s}ȷVexaW#Hjob~9u&*i.&[,A,̜Ձ@(b4/9#B=BJg;YzOsy&%k7X1OfNS AoO d}%/ XI0aD΄/VY =(N @jUPy;.g7 y$` \S +Qn ߄\>q xI'H&eLTc5̤X|@S˱61N-}!9%yb {l sF rB;mC }1w;$PO{ 4 ʾ=`rK.U.o=j d ֥@N7Cm5tQg 4=vH>ye~HyQH~"snőP:ѥԳY zЈ݊w11V-]M֮.ݥe:ڞnV? Y[K) Fy\BzUx[hbK}9o#S'y-O?׈D}]OF5b>즌%zE^i 2k `K~%KUe#LNQ Ht,S\`qzW)Ȟ )ygJϜ\Nl֢ DTBᄔg{3S냇{E5(SzkVJv<ëJ.[h9&^%M|-y+Y{Ka#nU jeh34HCK>{`Megw|'kՈwR)pա~d Y{z'(׃o:٘g,SdY`A~587E c6$3oShލV&M >_f|9_1 n6UdJYg84-ܙi &m]%*(GhBQQ%}vII hD;A=Cz[yEpv+;WLoʇ io1b'PufPzC9CpG; ay(MzQl;o?>Wtf--1 @*Pc6 ;79TRlI*,2o1v5B9:@JxϤvC֮#鐄W," z# +v  57 17|Yy$LBs$}D@~3 oBZw#:YuL\Jk9 @&KL~-$Ks&0Wa '%lAeW]4Ƽ.YB"Q@X[Nf7 + z2P˹Me)oB֞o| ryf2Zrzd=yj. "@- H}au'NuH>o5x~iDk*٭P"PZA5!6\YV bcqj)=ksxN{@2!yna{Ӊ!8]BBG6DdfMP8?'+Ѳ =)o/ z~\7Xswl004" uÚ57@(˚W3/t- s ?a;X>"P-о wǙVL@%1% i˙{co׳$Җ lP7d#/0&δHzL=,}ckɓ mF<MxZiJ uĉw.@ݬRvmP)X(@<6z ;P{V`R +UvLP.&ӡe5TSNP4$BJIm;T@h`M[ӎI}>289 (h/;0d9Q!MjީƔsOӗͩm+nrq76gS׼XȔ>_Kٻx+Q:+N%Dj[g*ѫ&YҊ&Rx$д4u9MB;J@%۬{)O+6TȓL dZd )bBcnA¾\UcD٦(jD INkg14j&!w[0J^C0K`+¸C<4/"k}O^Х(-D@;D/#k/.N s,dœQ f3s vpO|p0ڏ7ZReyv@zOf{phL 82Q~{4wnUx^W49 )³}l#zK~l/!DB2i 'kK5GX .&c8D<ܑCQ/9/c?F ׵O]˾.gr(/<,7'4F=吸7GWJ_kxĨnUk\]Gǣ֌4 Yzr v$,2!w^sap\ OOy.rtJo#g3g@ A#@YRQa|砘VWۍ(~rum]d;T-B\<:H.t0%Q7(0,O!'YQ$GsB 9 Rcq 7ShRKj6Ɉ^ԊJF_+?U oQyLSsIuzv3U6@I@؟nL-Ud$zPy"mOehCi fL/hh*}f_NI><~g`.M݉a!C_ycЯkԠ$_"E_Rx\UK6θWMQJ6OҐ(#L\e3s:LriB?Ѭ1oSzm",9qr^Hy|vZ('Ͻ< bn9h^+ e/U9"Ɓ~ 4I1FЈ/ q &93*8g>ι6A qmfpPm3֩9+7\Je_ UcedȰ'jk 3 X6~>g* J w X =Z&A"vgn[``gEϽ6;jP{@Oqmo0* .ѩ2nN\n#kۥy9@߶) N=%rR 2 DHk]uL>n{eO/nϱcn/6zF=Ĥ.liۑb6(WBm[쥨缣xJ\h2 W}s!k*YK!֪x^|x7KOš4sOVKw#?~0וF]5eJKӄ)4 ZfՈGt;|d7쉈Igkj؄!V iR)n(q RC Hzݧ!p[K?~ÀqM7>P3?gn4!1Є.Ѭ2Ivϑ~}lc5A2s[})dCiv}& Y4Q汥`t1h2Z>lRڧJ?b0Дvp7 }4 Rw>9L 9PiPG{skv?8T퀋5pTSUY." , }( y(/} G5f(k2}RFX:bM_uMW "(}|Վ *P;n2z  ~ (AQe{=qyh|ϫK.buM<b7aN +Tz:oԣeA%~xj45.<-A?MuAwV4rÏUnl_\IiE׼id7 :Ɨjr4O˙aKN XB:"tBZ+Zsfۍ[w5lYHyl*^8ri" rm:hrYHm%6+YMg. {IFĺXӧ<a+/ vpLp‘BvI^#I褕wYJw| T@!8(p7;gM"8.dyiV}jk֪zGFPI׿xE^zM$K.n~,ǒ W_Q =;}˾6a [Y&HHS]tȞ1 8 s$so`ty"'q2gy&Ț>,K41 @f6s6qf>68wU ]ek#)fU4astiҸ,M EPsk.Dzc4^5gJYJOg$Pk. ) r(JLPZ i$Q SyR- &\3+eeh̗&3LCleCmqL;DYIiv  8e +=,Ҹq7alj1 JaVG )˰l 2<9NЈ*ph^1)™W>Ί%nsUeZS\eaz#(vbn̈́*y A\O^Ii !_O baYìK95Յrn²u"(xQZF,I=d?a`GKMЪMaهi QOUeFfcٺݤ'Q['?MJZ5@w֑?5HnP4جC??=$-3@`@.v:\9 ʦΩZ KQOcm@STzÂP}6K]i vV'NMc6QfS(B@>!BbUQ".`ޥkv|ҥNbuFWý^z޸Hܻ$PHomt{#kv0-@C9f@Rӵē(uD%}jOXa L;t~Ohݿ^!Sgs6bw'+*?23 pv0c'ՑÈGzBG} ^ S);Li& P}Va=cK0) 6*_@1B Mޓ1y| B:e(D}(S3Ɍu%EByt =1ж!Dž!B쎭ha\>Ua a3>K`fUwMRI錤&L.a3wRix\y>Q(<荘l͆%B#uEMP=W*=P: 59CX1E*Cs1!FHY KDe\V?k|ipΏ}W*O"y8,4arIX@k))/1 1My+2q#y [E&4]ASkzHJf# \l*&2 { kWqgyNBi>A$|V ©eySO}„@iy-DɟTl`xPqPCCފr֖Ð?OPW ݕTw'# [λaRD+I^r# ,N6*t2 VKSM "9jb;upƓqcZTnqN,.d8dSZ.䢾+_`7; Ynx[ɒ+`Rq7"  3pVjwkzJg2*tC =S Dm0/'.Unsbه5 ) {f 56Glףٟ# uP{%}H3]op$-N({\ȿH,p,pp d+fUH(qʌ\QASQf\L6GŬóxI|0eJFPjxe5baf ]w`"?f&?!ɮYƧ_< G@mӭF@e6O)gۖzȼ6N a1C ݅RG:e#PNEׁ G'.-0BڪHm9JSy<@a/'W1+ aY%03A 䏆?W 0`5ljE_# @ ӱ#Q\hш f >nqTg{h]lM I3秄ф&TiYpTٿ`&0oghfFm AlĦ?lVHjE_<ʧ 'aH"~vՙ#5q+Uauv"q= +gDF<}fnd՝+Mk5- ݂*UA]EкPRhT3e'b~3(ebUu1q7g$mTUxQ{GUE^e/f\E{p>0[n7TRۣzzuKFzɢ| qo^e˻/7;Z}He@IMq!oL} zkVuz8̄ b}ާ-,O׿.:+\;+XA=ue_mmF(T:"UH o"Xt(d(ѧ[j" rIZT-;H(v ` E-k.;; }K\Mv"`ЃcʵNض@B.Bzq^FNsr\0*螲a. ]l⥬X Ŋ=s(;}(jn5*F:+IX,1.^ 7{AzMlsGi? ƥ6te[YK0ͪ6|[\?5#(A}G#6}e+'*fT!? ÈSLusӫ?ne_$w@#u t8t85XUSzv buu}w8^ѭe\3rAC|>?]q&1]|aE3 hcJ[P\~\vHJ :rTaf_"^C!Ҩzbe=a6ŵP6P(_5C} g,ʅٍ:Y#5~d9Z\@}埱gy lL%wUp;)q3暴 sEE/g$+?kwa^R3fwM=1rG-ءoI2 66OW-}1@Ѝ1 h y] !Nȸrp;e;@\ΔBpP)+ nsrP@)xN}d&9IǢky`feASd>Jܛ!Vee+[@yq]m[@~ICTi XJ$Oq8TCIJjo qdwqYWTc G~KC?;%Rh&{U!swl70q8%HetUVE3Xm ~M4HY=ڒ"Pf$vke8_Am%nxzXv|Dž7kh/~FkoG MnqΔi0ζMD$A$&bH{D8_.wfʈ9,CF,ttXpSYfT{U3Dj_a+]_TߗzѾ-)@o !GH".Q b#UJ0-5@sS#:% apBdMH\~-JRϴ\0`@ L6lAxK}*g`P|9AK"a2NKS.-,xZvzjuk;^1e\L :I]棎sD2e-v"7;֖3k<~7p&(َkaޖcfl) KM'? y>eM r:Buٴe L&}M))Ѻ=c$"~O] TڇNNb6 A¸|?QEn"}Y)qU:+s5uثH6.(B~F1 M!,ںzp(XuFܩHKAuzJJlMz43~D.5 fhjzK9 M1@޲P7F*zQS$L飼\D`smuiqmgqVmc$gW*D IEVJ< /vH ~^*Wz;^)Ps]%cHjP/P{7miDRsxD0Nvc=/&P>dTqaF@g%&n²j3A)0u;4,܎Ejw_Y`uBQS4QO";V=)[`xUJrU_RRHX +v| e*"}>2ݹ )=Dl[w-4|eԏ{2u.2Y;A$}+}Me .[4M#/S)gfS9g˥p%cl yv:#yiK)M"=91@ܢxZV\<'#"bt:| ʅy^k7f~3u,|4!6S T X4ty @EuPɻ | G OPpP0bhc Bkv$9}) i*v~~> Pdo8N+XK Cp<,Vs5N/WUioe/~11br0rZJES,J{yQ[lA@XUA6c?OzVÖyވe^@-c- DE#E]\UDv=O(?Cb}((Xs%4» ;)1(&%ڥp.ò tGPYar¤d!.M~/6yn]4g?Crh;e%pKa:@s#S&ha0rO1~hJNc4?U[wnjLs2(4S&hA`흆OӴ%U BaJAe T~D1aFXO2+3]TKQ $2C0pLs h&Pz5$\1u*=#0AZ-^MTN} 2ϐ+Y#'gԝvw8f'oEO):Dt XejK?*Tvt &3(WX_f-+<a VC[d]ZnIビwPbzzz_Sh\y۲ UwP0o s簩bCX+y>*YŇi7<XxnH FDkFNMwJq\ѽq½gx-?=D|O4ҫՎ&Aк%0%@,1%wUʁ-H~Fb ?C Wk'%?O*/b@QO>FG?z~>DB Q}Re<(#`d~[N#r wm Qoԓgcty>>>U4oZECusnh5CCţ(BC:!͝{dWY{f?әBIC9"yW6۷'= ymfXy32NJBI "%AAAAP }e Uee}tsk*۪~󝳵kÏ_W_\ "{h+7:/+>v--[**gg,jV5vZjX^^ﴣ^n[vg}u8lĝvZnfݎ[vHufy]poa:X-ѫooBXJSjL-\)nJi'Qm-rl쮬6Mhԗ֑vՊkl\{4j_KpNtuA7ZQowEn6%;ǐ]j0%KdP >AK =0ZH&L&/AAKi}aj,̣?axkMan:]Ο~-94˒AXC].ń~nܗݐu!HSGh:HdQTTPY" $iPԴF^z-S[Ly;mkbͰ/ Cf-o&$է1Pwٮ6Ǫ) xE=pjx'Dٻtj];i)qcy= }N nbzyYm}ˬ;휧e4%j .ΏԭJo~j"ip\?jiyƑ [LDkDD Qa"/1"3%DE_\%QD\;fp~/BƜ.:Id @iKm@F~q'|>/#AThT,Y. *!>Odh@/Dj(QguPe?;8ccfM 77סݣKlO)߉9 PfrÑW ϖs(hQ1W` IEP8T!ϕTo6rRӮO!\(N^b*ny]iRJDڲӔ^nC*9Me?]&'On#H4@rǝ#4Ĭkhu Kkp#sp}I@ B]"nezr0'RRIboDd76^<努"e8Mk84蒀JI';tϖrN%JRgI <3M:s .*wճA $i}H5$փX{; 7_ٳ ]q2H.S{D/98T6g1ihH2<é5PɄПM\X~YVx y%J$g7Us"O-bANTּd۱1@+GjYu(!2JFbIIfoo+.0x8I߽*дI+[[C¤%$3lTCe z|V((XSUQY *]p!TQ17D,B̀B !1ڳ -w@` W2"|JB*?@aJ?HO.XPАHu z]qiItᗛM&LA JG2Lx0Q%@9J"̀cA5NS@1 RˁDĻ.PJ0 sP\a';P%>%6TaNV͖>vd׸P-KBA7!R ΧIER@ϧBQf)x Iin{fuF|FW1p%4]J6muw7i*mRb/L|x8qQe (egK \~x+9Ktg=SutdBz~nă9N5) v ڹg@NW=%LӚr[*z,jhgu2uBm/1o6kg?U B/p@(Cj#r~PAAOVbƶM[m6Wۛ{kP9˗Zq&,k絇#aVx2鉚2@d$Z-h8+dJGCfGi.CZz^{Rhi++-Y{5Gj t6mr1%z2vٞ`#Ǹz V_ZuWlnvyXK$ӝ @ wq.HDvP2n͊UkJ7 u.[s=jXIʔDL!4ǨeUI1uI'zٞ `NR=U`1ȋ]TI.ܭ%!ا$d悤~\Hp\hjmy s[[ њ n.5h U#OWvnT4ʾ?՞%²'AIBH֕$WNrVyw> 6!ߛu)tqH,'tq*Ɋ@ ޷?LZ{j'j[s>ʖ|7ϋoOL5XLf_](C9QfLq3][Hؖ$RhCdўBRi})s[ 2M&ӼoZ58Vs~}^ZbPfw59vH':*KDGHHBr]"mϬl&`JKSڻ\;eE[H\T] QR7l4Uʺaz{ii{{bR 4yb( H jץ"t\דoRÛ y08=I?J^jB/9+F0!ށX(SQ mS?ex O0wR̤loT;мɄfF(h t!zXʈE۶=xbW1a`܊"jt]s  Ms5nGEn,K^tss![G H\GΕ^pay&р {ytF/o%i#A`|[>9,ﭫ߸R?/ 2vy)RG}^J|u@Rʅ*' 0P#N?eJ$ă~%@E%]*h#-[DO-jv'>Ox6E,ėˎVP⟫ʃcu0} =VrPYm>{n!@%K U\Adi (%+)P򣜓t| 2kZ*:/LXv,&E@2@;Y7yc' R)zo]=[ݓ=EB[M.xN1g4Ohg7y@.Մre= >OdӦ s&ƅ 8 ي$T@N zb bk+ 5Z) __ۖ](LTCFcR;ʴ~O;;(poPpH瘿8gw0 Dm{<\UOGQ7 !7DG߻#bb2K 7 Hɳn蒇}}=`QR UzHLNQxoOx궀F@~W#}jdHOg _T"kz1.x&C$5vB ~TMJ$@Efc GDda{"!!/c1~AQjMˋο8ֆӟ5ڴF$K[;SU&LI>[%vޭLA&@ Xip,<-&{ۏfV?lYS(&<_1An'~ ʹax c%NU_xKA70WDuJ$P=s^BB'06r`,Ց Zfy#9p(Bq[,9]XЋP!n8{mo4usk)Ҫ`t3N.pbC XJӟF,TBE=QGdoӞrdwl:lqT9ɪ-kMFMVkۢ%X|pUOJ8gȞa.J*1P٧7^Yxj#Y">P oAdeOh}. <G ۶=cq-"+}$E|z}dče%<^ҝC8yLDf0u΄.gKt0}:Sm+6Hz# gtgP0}T`UϩE$~oPdx Ӆ'ˊ.9,(T꺄z\a,nN9Hr~C{dƕl8A5a#@%̤i+<+?jIHd+r|9s E9o51 % DA#D^ki!<= )W%<Ւ2oa5Ҋ5Eq2&Q˼OMc)POx?Z7 Np2y/DSQD ؕhjȒ3r' C&w4JAU~PO.fPf{ajY>N٭X/1L cQfxTIfZ"W5m0Oe& LOE,0. S?HRjMrKL@ll) 4T^Oxo nzR(Na h13:7T?QFonCrT)Hr*ʘYmR|!Ts Δ$C؈s4-W/FBt PrV 0Λ{8j+`U3]f6KO`rTVDvP+wX2ix %J="{P&u^qnA @LC#}Q7,͍0U=$ݫ= d}_W-y:G'"RHHьJW%BCd!ŝyeWY{zbRE?RM[ՅDYF2w y$2`ل *ݴԈ@H@TMd IfI0p)Ѳ*K{;}On9w]~gi'9tdg!gOr:ȕE"񿱏N: 0<={俣0Xngm}jk}}nl{{#C^HpP?{_~Kzi]^y4=py+H\;Q X'W,@9H]H &*Ҏ;%{g49-RxL6xo 9 ~r8 *qжCQe~@wk3hX0p-GBZ&LafnNu_=6/ bΗ4=XeKggr7KO!TLHNԡD6597R bV/G +}!\ٰ(3au'$ 422m;R nX f9%ΘpC7LH{:1u3D$Ѐ'sո9;lEk)Fr#BVs ճtd&D=f/p)Q vHH~([uW3PzFn42Z; 9l}@u Ж+)\K؜TKEƾ*λ6t_ PEZePfȧeH5d2gV6!@NES1$V6u]_?@AdVL(Sf U*D4;aR !gOYQ/Ǧv!ЋjCش?aA|ӊŊ|Աh =!'3̊3SW$'w*[D@7]ho׵Ho`624&rBqA,;CR|\H*Rs!eSکaJLĹ,ݦߡ'q- eHӡC9@!G@iռK*;ɉS  .l}$e]&Q>2RipLaѳJ,Jq"Y&evAœwX^)9֮*ēw gD[tn| b4 ]E{OLVw\ވt)g +\U|)9n`.IX 憵" iY#nf._Db|zZuyBDc&IiBtXn(UW}c7/r"y 6Dt Ϛ \0 Y? PbϠ} eo5@ F{ƀ+G^]5t/q+^Yo׎J hv9Ö@P^&ٜ U]hɣ(ɫczoS_YdH ,5w4@Re{r4u2͛kI+h_Wϒ)带i ;:%;ʑqEqTo}Ht) r(c}Љtb;yk ~%X@cHAfK/bnwQ)mܨx)Ȕ[]kజi_t19eS!8UN'4OC5%2yt-"p|WDqy /Vk !}JzƗ'Q}iI^z˻[qoBu+p j9~<\FIU'd2'2ƭ\_=y|1c {ra 3&8yPQGU[Ǔ hPf@)͞`@)5 .*^BCyr>F~ᷬp%=J#4>TVu[^Qj A;6AoW6:5ZPdkCN0APZ4TNgV\ (sBLIF_-( To[R9+߄CWV՞b@#g)N yE4l@#Bl,ہ,jz=رx4O q7_s'+{ ՅzԐK])E@Wy0Xuf.͜`YKΎZ1ߢ6bc^uy׌x~WAGE(JPU f@ x<2|7׼8ʴNOfHJ cr/[n\kewJM,GkS+SjF<6Ex!GT%O,U{UtVz@Wi93 a @VD?oi@\.%@o FRbn)R{Umpӎ+TXM'Q˂.'@` D4p8hɄkvHwX qÕK Y B !;X1wѸI3 V@xVCѠ,hG, -˗0Gl=_Hh`_4s0~d#pCB‰b=y/rv ?*^e˵Y\AnT2&S@yWŪ$53 eCԎ{?.MB^oz p$D%PoY-=op 4r^aڹ}ʒ5N4J $٬7$Gʻg5 "ΛإzCOP6 G\e KJ~n 'OuQ>7S[<#5*G\N^?H1G , ()7 0o3ZnM/=&$ Ѯ:;țc6b9P˷1}[ϲYlTEG')t77fy彉 h,7vR4I‚YeV<2ʵ)r=:qܨԱy#qeV}'z -/ZG[UDˤ(ؒ\\>crޔ͝H8k]ȯ7Kv#O$ϱx$+p%M{`jTeNذ(8Rͦ.2aD|/+7`|/|HMF`|{**ֳY[KT 75| kC9 gsؤ3$iY0ZW2)TSo&gWPxFH,Nz}*)ӚqroI4k1 dԐT(9I?1?vhʲ҈'Vx=, ⹫c~d''NJ X Ɗ3ئ"}8}BKBؗNTdPy~WUgRLkH0waO` Gw:K"auhU{c_TUuW9cÚ+oe1;]V{n&N~sXn,׈YψDBKwمuy@Hp-\tFƲ:!|r-wXNZ-HVdʅ*rSXH[SmiDQ{uE2i}}Ec_6)_R;@%}z@fcH_ a)s+w=A<9h؎ask䟐(^Ud˅l;6 #M׈׎xF׵n IÕnWMltlv( 1 +N4qV*4ʶ\f)Vs u'BZ42֥4Eߎ>}qVCeNB-=b4#j W'| k(Z8gjSAjZ;.SčC1 $WK g>+Ճ8Y\ߐZ!"7?&n7ӻcTm-qS|SL]IQ#}'&;"IVov4RCIsw_hns%²";"3$ HjjA;]! ֝0e_׬9 M7O[aACcVh%%ںl4K疉&'H͇gBJjye0bi!|@Q'V(o2]3*ZH#tտJ^ Ѱ^jHe,Z,ljrBDQ$G Lj>cz콜Il\޳0U7N]k)ILl–&UV`Vw6u(א>y59nu")@12iiC 1UH FXzT@( *: vseV@٥:54O(@p3]֎V#9h7AqР+1+OV-žlG'0mw!ʟ8Q~=?#fniU2-92Q-5U?/wmÑ0eGx;?QД(R &:Lq$:avsot, vݱZË́E稳4dMz3.nOw{%8A6AAѠc!_ru 16r*+s I@2C0NrHCXq##Wz[neXAvvPR T,_r¶#P%ϚrV bbQLw} E F\ SurN0mcH6͍V4Q?g#Q6- &0 P){#Q< .l$ + ZP _h6\y5h%g=c&(q{ɑO~#^({#+є ]EUG|^/v{+]yWxNyn#g1i}0)FB"&3<>ʣhzF#!}fBPR7 :#!%9Cc@>Cmc5W2Q5eqI(1?@ƚd?+H{$!A\PN{͙ 3Z.g) Ť黺FLz6!gWktU "!zq0||[xc{{Ig}}fg%m ҵH~6E2PxtC7voáABIhVM%g"!8$]GX:|j8iiM0PRsbH F>IQ#<1rvcn*5v9{) .. f5L`#\$g19ֺb˅p kWLy|W(܆c?{}ҘWdC)("$eK49_y'&(*ˆK8y K[s+y1vTGFx#s>F7Ӧ<'qœ%~iB$悿\wYYbNz2\O$纾>1q=q1U?TrōߩJAqzʡVkh\yZ- Pө+-K?p̎BaVN'rʽUD. ׽mvHQ, !4+R\U^Δb ^rI6*jɋ'yD´d]=e>8*i0o~3fTxΎ[$W.-)4ΌX*@T;hϒ**|nFmϒs\g !?7m["L*,4/$XDH,CPÄ6p'Iߢ'LT+"<ϫД'Hu:*G>^aSYvĘ(R4jbm!mW&uD.rzRi,}Uew6EJ-m}3A \ncUǒ|FXYwlv$:ݪx rq$V Ԉxv"o;Li ֋pb/aKmi苺,Ђv_ sLڗݒxq$ZTjX(Xh4*iJu{XS{خoVz Y: ~@A}I$RΑسn賁GEW8X8TmXy}XS:pպʊ` |2ET%R~8(Fԇ:ъk5@H 5IJu4x` PۥxqvLAɴ^H|bA}eCIbK$_liы iݙ @o}6eT/5VVrFF]O 8W<ҺȈ1{ Lq(y}(,´R|g喒lPO[BqOt4<ּfu@O @A \pԈ'qq*` (3/ļdۦ[\u@+TP,$FC>u{/ŢZ3'ȴ6"@r'dV2 !mLKN` o |JWnᥡR~X27"0HwiPLDWϫDB ƥRj'!?WQcJnP`v_$g1{TÞ;!/ rsPMh 8w(v-AQ]zĒ@\=A|-xGL^yDm6a@LB7-"w[П6=P#=o#Xm DISx MBUh\">=PyMmƥSt4E^jJ$SW| Lw+9 cˤp>ʨת$_x٪/Iy[[DBKCN>M:,ki ^Hef*fo\oբmfL,x4u@k0^uu#b{Zfx;[P1 8u"yFgͶM*)q)wݥ"ZB:SS`H#݌G㪥h;rVQFEu6'{DS\X\f'0 c^ ~@BģNzΒ@E2@4{kUj$sH@F UtǡSwf5PnS:&;b (q:ʀ|OH!Gmʛ9a@<ݩOl6/ !m9`ި:k mvH(dYqwzNXgz:=V<Ћ NY *AyFkt SQMrl}x A`4Ygjk/>p N*.#m?e(`$"UR|:#g ?Hɦ{'(;9$yLgl|1E3uu9{&7E\ju#4Vy@4ax:oB^~l`/N01m ҫ-|OE~-!4OG$t lh'sr w4*nFzV4@*љR?o g?gܜjr%in/ g3Y<@@)4U7qeCzޘ+⹨=|}WI*HN1 bQٔ:vT}-})Q+S3!( 5XZHtd%ĩSWL>An3J|cr49{^ λ2B2S7ڂ@5in4 ٧ֱ):ΘELbžn 5aԄχ3@ SvfmҘ`-NG߆:.ތf^N,3}jܒ\fZusыuź4fyPr/>~IHͺ:ljP49P\>0 ثG&J{Lg^N&.1.dW]-V :8'A),dMG1ʁOn@jDC9`s-З^_Q?'g猁"?]>s͗nTWJfTj۴}GJr2suiZ5_l#χW+,<_cYFOWY~zF6⩁k)uyu2Ĕ,dIa$zsMwrþ D 5T?b3:W*RR{`vK_n%8|r۔>cVDbH@ 3YL)㦅.'@ VaPu#|R2gcžU±׈XuA(sr׳SY.~.T7s9;ϸz)4FL%Z/Al$bFb|ՒR{3ۼ)%=OȲÀt}7_[|UI(osEд'J̃}@s7tf ]lXUpX~~-R=qX]8xɜiyH9{  ' ·O9xo\7Q3C:VaVS3هKHZ!ZY1w5gk H{<bh.5Sv q2Rc$&:2 0hw2S:oϛdl4"$uNcW5KuH:7@5y.~ZwRn&`LX Fi7"!i^Ҷ٠4*]Gi뀲Ϸ8(..A| ͯkiTug)C*]fY\qpA09o mxa3Niشj^Qp0Mi{m3vN{hʽSZmK$g" a-:@zv$5'X70f)T$tSLdQM>r8U IGâOW=h5b'{i+xUdA&i_і3y+:!L^lE)TuUqDEbI Q pJ#iEVo:mسc -XF:^\V;H\ GQкtp5K&/0%/HZt 39Si|ڒ}UNZ0-Oj|n"Lbɒ!2LG\az9ACSwh%#!3'!T9_dD>Gm`p( VUvNăA"ͨ\nݰpAnqghr4^VYޚ1]g$.ތ  N5BFiHZA1C{.LWGK<⽮U?7q6 io.KIzcr]=P}m(dPW|]u y%Pض؊GZ[nU/ ­WX-܊Cg[~|",>8 y<uH']RM⢄'>Ln5FB| \2DIIJT=O,IѪ,?%ҧJgFEFhl8@Q*R}~huvO5 BO8x(R(Tyn@ҥC_H/חC"r=jvI)do=DžELPv< bIC]8yiWVoǬ䮆'g*\m&_ܪjHklaBrvl%`K (qT J S7Qb: E[w* u:S$Rm R݅1z!.ьB[};tݨ)AcK$|3QNu/#~3;Bes6oQPN93[BC!͝y%WYS}UX,eҷߛ7 d H]FxJX$,vYJY !$$,R.X٠J6N*/3US;_:ůu:>ޡ;u$?پB>z(ĞEYYsM;O: 6{Eo=wkŢX_ Ƕtkkc/Il;EKw.l\޹DzijC>7"l'6m.6z^ow_/v9IlHl|!;lyXc<2Xs~XsKDoBzT 1andno m,1QB>X@4Ċi㣉6n[ F`m:@IᡫNKmIl!JX.^M7b u@?M!_f(Uh.'Qu{?G&vPX=89 AJNh XԽ:PҎ* ē,~F5pga%S ի-!; uRJϮO(^8*.$zwXmPAT?[B:ҡ<ž җ \ث{nNMDs :q+@/PPt)|g3(++X+xrbD,FpYBP,fܦ1=mOstw4uBsM$8G''"Y@Nz^XQw|Az2@Eb2q5fR¨9#=؊GM .Nr/[ZA6 !az  kyGu ҺR@0L}p_ vQǵBЯvH(_eSzEWq֘-D~Znϻ(0H+rȧ~`q$t{+ޫа+\BfL8 T.s%M t.oS(gKX| [, z)< Sxu]atT($W"+`pa.7KWZ#rNքvr+8*BOyVGy'9֔LJ(vxԾ5ٻLybxhܹ|ɪ5 yP CE@V}aHw佅@8,e*A5.va x?kE&K$!<wˌ9(KKM7@(NTS &ϒ6>@>YFkPPmF#xӪBQGa?tUeΛrc !>=ZYFSZZxzxQ  R^EN, Ò,84@br\=r:L 8,pBֵvX~$!#u~3gѕ + 0W}Xv"IHڵ:@4s"g$l*I OI1k է n4?Һ/Syrk3GN`Ql)r Ic)UW@%&h7q~"P H#gR((>E#f@SdsB"$DH.j [dr^/.b9g3KGEx$ԏbhWP64%G,=mS(=5 ܄#$H1$&wW`^FE39։=XsYw$2Mwʐ-kX6 FA+2Ru29P*]% & vf^F%.SB[+<\1]:_FV>3> 3L:M7H( LiNѤ\:8LRӌ7o3ԎRelȸď8~i׉ϓ)^ϙ$v}n;S()gXs+ ÂC$Y{jrZ;D̹;[Hi:RCRqN"g3GEu{I׹phD}ƾE7q=xn)SF.SҌ&=2s:]:n"+z!J/]xteE#Kf}]bɬW>9T:%xR@*V:+!iMJqiJy< |&=u6G"Dk߯H WCOtW[2鴯S]4x~Ўg9 i6#iSЋp,|)Xok tb߹s)9IB;vDRH> -\τߊzn y5*í I\Zmoe{x36l! sH'g2ZՁ>MC:b5e P0 Q&!NaEbXs?Bl|`4 P׭Cꀞh5bZx4>Bk6C$=>}Y ylU[,\^#'Rv6Lw҄Pi;]3 >azS(SǨ]`5&c\A8G(H: d@aF< @5eK5dCW>s rčYRRizXCuK"pS?,$b8wO1mZ5'@h!ozL~OcP]UT ЍjQ/[J }DNwg1<=Ba4 ׉gρʕvJm:K09޸(<|Q"ygSB9RBvDj Zs+օ cr[n&go5~qkA6cnUHQqI"sikavOٍ< i\[N]*`mI(LuL5_TxMY&b;&%׮+UY`PEw):jRh9ШP.[ox4Ln g3ձVhl榞~~r:dCL+tƂce+=QuSW%?+7f1u{9W7pɇ>mwKCӀ<٫<ju QaB!?GE`.q2ͣF&uZ#`>0 ͭߑbs1hxzCb}-'$jhM]`i MeL>)Rt$9]߮s?>[:Vu(މ#<&!-25"i/{y$>TQ__sRJc&<哢r$ƊFj\@ž=֬ `Z9.kCm8@+&5uT>Elބhs:PIDp\Hi)F|NYd}2`w( ']c晴Vo3&CdP#sM3lyhiMeQɠǘ֚הpuX<{U o%U,)[/)T hYn7BhG2(U aU nϝ!/?9Hje2%jc;S,&`H:[L(ϡ^dWJƊǼ*S9/BC˞oY`F^dL`k7jYw<.@YHV:yy_ P번'HːXhe۴Ι%W!ncPgT췌iB}6ʓv{P'HÛjjWBhiPH'*>eْ|X;vBquaS0=-`q+0W;"g1 :?/alIQg}θQ*wOp|átwxtBݤ@l<L"R98!M!pI6iKXLa Ê0h NblWOy@HD},R%/ VmԷ|Y_ 5^s ]nE@,)rg#<iHߛp::5!%9ɸ$P/*b%)JpŃ 1{G1 D0's^][b!. 2=no x ʫdreI)%cORKPG/JDJS7oNԏQ;WJ]zȮ(c,M r`}[rف4%ih uę%fjF/\]A6X=$0wHLHٌ=s$ޒc_cz. 9yND )V[t1HcJOߝ/G- 6;t+9{1O 7csxˆ.HViD}ΝA W+猉V= >gJ/|.M:-ƆP1 ,+#ge<_q:G';eܡDk y# 3DT4*'aM)1Vlc7xć>jiW<_2; $.-*Y6/^V~Lb~0FȈمjdtz䊵587@kf3`Wb7pnlO*=#*@0aNh._NT2k\UDTKGΙKQt[-ۯw M.)xdm5OP"~o5V#IXJ;jr}@ti'E g@DӹgT䉁h*Ve$[lKhaqqC ٺ)۳% _AG ] H=ݪ1YT'Df4YmhhlA g}KaN0lHQ],:B1;* /V.jXy?aK =V´E]ѻ?Y3X@c\k $gQI$8(_԰<},t(S:#uιvn< p҇)Q 59Wf)d8^Lq BC ͝y]WyӅ2jGm2SW!(,wKq@~q^(35tZl[t%gB[?Dd9wygw=+)ǒ5?}3{e:$w\](v:۽d]_^[[nVۛ`sscFCC/?tCiq߿pc=W^vظ:ɑ'n^=^9\󼙜=Ô9ONShPc$%N>"g/2 4<`:BS-~cHddqrJS0ș`Fs(9>av\2L0 0#{61#g;dri!0 nӲCdIrc$#`H i͕Z"HdrzuFrfSkn7Vo݅0JNHDg{ Lra+|Jt}xϭ@4pIwȁue±rpN&#-r74~ND brA1E'$6pn%)d^1#}rv1T`ҎK:44b!L,ȅ3BjGgM?Y %ۮuW{[ՕխJ`cO76]v Ezh3?qp8`4q4hi2&Lix|l;@+bK⡺v؍xzG'Ku4pqPj,<zwۃ- ,8~\AHNِ@|PE!6:k EBGٵli<(Lw^?}]r ;@1c%tˤZcA1] J@,c-ӊ{9GZ!@p£6T9:%/+xd<we5!-k] и!0*9RnT^TgANZRTڹH A4; _4 -_$1 mڅu(kS0m늀πʎ' bySd@]aT)C=JA\oyBTVd !JfJ YkH** Nb,mC~mo;*s eWoͳIe`Zxr`ns_($xH/~ ٯ*HLxifK0ly*U`!F|X؝lDhƇ@%BBR eA1=bv%A]rց֞͊"@;2O֗0AP)H3= FR>*oU+6GiSDtBCh7! ^mзQ8}_'[a ıȾ>e>y \(,Dj<%ҞƳ4Eӹqk%j,mM,zB*ǽ]c.μU)ysٙb1FW &g/^%oTf2`i8K$I}ت8$ۉm+w c0 xA+4`[_pqEaۙ쏌{CE<3oֲx|gq(Q%Ms ^" Ss۸,Ah~9p|xtKez|h]TnmM}qi]bqT:C@#WY8whKWh nro7 oc8 )d$g5 s. nk^wy~1rc@Q<v>M:>겯7O*ḯ~wra<*9P.Di>;T; S6ˋQVԪNJU " .$X|hS W*byyZ,]4=I`&< : hon6J{J*5\~ I;WgU:@^`J^y<̯zh -yxx}zPB$KWHhvdd7zL7X0e ] ЭV@bu9gGdk <ߧ)4\Zqyp)EKɌcضSiqg"MOZ9[#K ,h|Q OOQQwxs%z Q=U4AOIH㙺 `*sIR_'n>|C1mz_m]a@LL_Yr, -?U$+FBxts ѥ%츲ss?Jt9R I2 NDT< YDWҰH80_l䑆P9cI}ם {(HP[:=@[# &|RX[}iꗯ!gnj;!i+8ua,DO֌:ݒ dAe]<"$0Al|RAlAn0n])*Zf\0Jܯ/Rļ~@0^H$3oޙ,Wí3ql'%RUW捫6Ik#9D*NdhQFKmX_S\E 0nߴ _v1=[uL:EE(ШT< mlmߊ[*@0j 4m)վT(HAI]zOȮ=R@&rU`32F]Kxdbóa+@jO'g?Ҡog!uu A ݥY;(ĜydNBH:7|q03UVky0]a_ut @P}SX> /Nhw5gN(+CbBZ"X!&|\h77V <~~FA;, VA"4iWtS\QHs O$鎽vjrXGUO/(-#  =Ϊe赚b@ОF@NnO9&tF}.+"oOb* iI4|-{V4Rzal7&uߞÄVD@4ۣ{M$>[3ZjKx/33mZA NYdqv19{a)< ye`A44bq#9%P7~rm+ŲClp}vnZ S"ñJ?aXZVd/!g7e fԗ-R"t""gS #BD}g)Er63eoR%H+F")4E04\A~xX6C8T.{4b.r|sA#FV`,dC_|1M!2hWo2#goʞ42XI3Oj},o"go650nxH76yG6f]׆N8g;a\: M_YSicE,҆3VAaFWԘ״ٿ6*'żI,_Xęd?N\{cn@`tUVfPHVԮX9!~g32b. \kP/K+vlH/i1 ҸxxtJ}9cc&y9S!۲߄vptS{l65ϗhv!GqlJ}x pNaJ費/ОCȧi@' +=P|RL$ /=s"9A[ nH.B|1̌_M oh̀vD_AE]7'T2*uN g -YO}rOϲ޽EnmGZR(yRN$9|wϠ]D!ܹ͞sGeJ@zMʖr!)6v]9o#9^67ɟK+8$y+qr/ >>*FoLDX|3Rב {$qyu#Hܣ ly _J.S ?MR0 u)9BXDkϫ Ysn( )q3kaK"/<SMOʻQ/YEB z-lp$%_"$WؐHwT6kQN_%(OBIPV Hœ]A?ņ$&:{,'H1=.sF̿-XR@_< #>aΆx\&cаM\ыc9l5[I\.>FK,~Q[mX'hybeߜ׌eọ{Yg@WXB}{h #/Fh\( Ug3H.39 跭8s.#cF&5I!&r={e҆?%gO7}H| X[z;MPlSWx|-6>x[1D+oT-f&|Rb.Bਛu3qn|?88u< Y7 7ߒvNnVS&G.uYҜ I GGI*H]u{+]e>P^סf(EMQ] ė?n֍|ob pX791 `]i"q,?q%?/9)(0Ҋhlj'3"]5Z}r%sBw&+%R]vw”tzWJavղ+\Fi_ZF\E;G*[H[d7eJwG}ELTO%g Y V|ֲLJ#gMi|@$;"Z<v^Kή6~(sQvN٪ʩ$I&qvG xBYm,-g+qSd[L =B- j֭jv+x9@Q"BRg.H.]yta*)&@yL\TzׅYte@BX?.V®:Zk8To \EkVÖ@}@{?cb2%1!QFP+Bb;khrv@'f$*K*nQBTN&%g73ÄTSq>=͊ OxEH=QTXYOa8RiTV%i\@,%O1]qLS5TSICJ<V>9lqf'?/4nBB=G*7O6ލ9 =Daunae枲d=Hsyc=Yؗ=2G#]BC!ŝ{eWY==gn $'*cN}913y"҂Rp/W25 DA@ Qt:DDB!`u8k:9i$M.758ހ٧FO?+;>p_(h8߁7878;(uQ9FwjwN]tz^wk3ܼukd֑[#QGr͸ܼ?l#^cc"7s`qúE&Xe,XN_}G[Zz 8.eotD]*Cj5$"QaDfĴ3g( z7jqw v0c_!%r#)9M !:[!/!R0Ԫnךڹ1I*z*V|ZoD@Ru $dEu+MwZixQ 2z*pj!Q w B3 &Ky ҄.l(7aM{4@ЧP'^m6s(s{5j !Äkg:Q꭭wZ{N[[o#7rQيo8A :j^褾B'$nӮӤ<1@pQ '#ߎAVQ%RڐT*1wn$|ɷfLtx$E! 6+f<~((Dsu* @З94aa;U5>'q8ݥ=N7IoyAf!RASN*-AQ r~|{ /.0Ѹ̄&!ݥЌW0Sw;Z:aM=m0@lhK%*Fa8'(K 1Kj9D"'9ex!PV2(;ak:֝arA ;^3 $X^8yL{ZV|PN+). 1ѻ+șJxc>`(D{:xuW87,d$.0], /J^:LL{V/}L|`}zQӲkCsƹhrH&Hi2>0 l0pXF匋beKIFtj8;D'Qц2͇ U3*>KۋIn'sG9%\ST m霬$z|rt-+W%YrjxGxr;T-Ȓc,5bܷ> @sbP}Wߑ #7IC`Ay(%~#f,1DܐNtI13y9$HqGA&)ñWx5t|{!'4IS@jB8BqڨqBÀ|7 .EL#Ik}ɷ7Aajm A'>cш|{!膃ɄӼE1=UjfLQVVNM#y:LMM5'jc^ yr47J41 Dۀ%[hiT#0J#0h]Cmnpw%u˔ 9B`]Xa_Bwn#+fR@&H掝gH,A:Z$q0 4"jD^CVd_jVfScYH R]|!39@j+DQT|J{ʥ+59LQKյI``)ee o!+JQ](A AH1|N8W֐F#,O}zVfڗų{6,e 6:NG*aDĀv[I6uidfh7;[>ې d*J<[UII%H&Ho\(6$:WEDJ6ळQDŕTỳ{`"sAebf}yHUߺyE?^5.td0VW&yKq-)Q+F&Ci@0_"UFב'泱EDWTvx*6ήD?Y`BlCWjW<9KI_$K벘Fc7qS]X3uU:@>r.OӚ~$@sQ3gd*فɎUdePxWsys J )!@^o 'k8oFJր_umuk Ӯσ E XG`ڸL$$`B g ωJVtX0jdZ ٮ9 K H\ !LGE8uPE"芞MHm4\dJFv+W"C5,(wO>x6zJU`ZEPZj?QOQLJ݃v5Lˎh.INjէS EjD$ U,dObS'OWgA JYŢړoWy<RxԞtYl(۶ uqKv/}=UAnGwm"%=$;jOҕQ)7R>` %qO -f -8\h; }in4]>ۚڰB%bTBQ m % euCW}2R ᣢcVشo;B)d:Qh25AwgeHDž"/puz, !uF} b\o9^zN@([ .,&4-J ¢;_DsGaȎQ{!NP%x O`gDԷ3_vNЕe+3JjNC i/Aұ;=ACy4+ts ">{\{E<([q:gR[/*CxD Bd H:j`2&Rȷm[:DWiL~|یu$-GAɷ@X̚ʎQdCHR9+%HGɷW!ybwp2>EHzHW%e0 F҇:3NKKqZOUTˮǃn Թ'ȷ7!)N3q7N$73^xCA?gĥ mYu-*gWUxg$-:2 Ux(.g舮Le#2%TeVHfnp"ٿrJE@WFK'J}.+GȷK|Lk[lB4|eA9Dl*u޼+i;1{b>˞%@{] \ +\PKW:Ҹ5|$g˫L46N)J<]ep^Ц@|DNTв s >{"1 lZqEC__携)a>'Uy;Q.ZuOTdJі.݂2 q`=g<2+jQ+v&#h*P7du?&}]FLKMw">hE!Agj]ˮepu-vLHϙ6 2yFFi>:7 L^t}u+&(œ7%>M x @QQTxd/,%<+\Hue5'韯, W Fl)4VAnh1ps'O'@jl F"zմ,?`a=BڰzIç> {&x!C&O| sEhjOgۛ4\cY/s@r|{!P &RYtyqz3i30P"ZI@PZGwY?I3U߻-cr-?""BnZz&OQXϑH߿WitzQb@ҊX08MPUkuN(۶ *US1 (B8;/0.9g5!CdP|@z Ư\JיoOeFE"W+}{dqHWdޡh|>q ec7yKF0 #x(ͺ`'q]'^`9,+{ԲbjS*"uۨ:+d Bq0lݷc`e ب;4@b!o$#:w)@UF`BjLzZ.uۋAxSmM8k:[Q3uLJ'JX^m$ hd}QiJipݜY1 4YR۳y=iz94'&U޴$HbywѮ]48 /= e=UW]1"A/Õr5D!/3:/ ^ q$Hkq'AQgvP8rg}[JI+T2(ٯ7)nBtOT@יK a$'Sv oч٥=j,˨n#YUw䄦>h}SVz2w,dC}S ɀr$Uì9Bra_޵&yR,*g@OwTw<IXF*3"YHW|xpn5$$O[J[G^y7߭_H(å hT?bSص_i ;>ƅE͠_]oV]qŒR0^K,ExIEFk{tϙ1aP>Ζ+Ɉ$3T-ڿ׎Bf  le+t@Hk.Hjl-bOe;fiL=S pnI=%f= p{Yމ*іHQA/H#TĊ̸Z~0pB3VUF3E#5U}WM3]DYKABC \@vH#gү-F 4̞Y))N1W V~"~Q]%_Z>P*o|Va >CV0.S|#q *Uu"G#q)LLߎo0aVigUhF8x;uG YBGۍoW/eF*7x6-<<A~ ^V'`/S8W "p1њ޻ kz62wD3oVT6 bڰ $͐ewS%G_K~a LFԱzrb 1tBC"ŝ %Gyg D=HLI"CWU~=Y+k﮽apDMV B8H=|@$p%ʝAuuOvO-`?Z{sAk o?ZOlw!(VmZH^ 9zZCᘓR{i8Zuď@)a\{V+0mt=ʊ/ekgLo=.D :ř[[Y bz\-U\ 0EJeCR^f:2:Y!/aBDm4xiԥFFhV_c@ 4x<]&_0П4tl lKV->]c`QeD x "lɪ :S7j@`=5 eg.-J Pg.P9G?3EOrZ'̐WV:δ:]vw+x*L݈ww\ߋYwo\Y7|7$o41,׌ "<`Y8[o71y΄a♖m00X1]! EQ3$W&oL;uRG|~BLoo5bdar1>z*$>oYyƳ: ݀'5-ڂ^ hȧn=3 >Zn 7 <KLȅD=on7T9ۆY`$ڪoC?ҡ_߮3A }.: ]YTJioHؕOCӶp=h.zF)tǬ' gU &L1C!dԵ_i2 ,%SIѲݗo}"ቂ1lv9#&^FqV[|,B?z@vڃMrz" h"ABWj!9 tZ"**M3uuW2d7Ң+)<+h*\:4aqLЏs eZ:I:73rg H g 1Ȳ.HрtdAYv-Gy.6(9q~ߪdV6d'7yPqžG bkDY!rk+c+0ǭC؜1P=RD}jm +XMm#dDl'1o還 ]AE3b۵YBI6ǹ@w>CF6#\\11]#/,(ӺVF*A@onreZ30sVJ_lKQ~WE*YaVI(r(a%nE+F0f CDu1R{Z& &BJV`#ѡ;Qu]KR"M /Vp65t`XaO-:$aj!糆8XcgBj {IЬP~T$aXst%kafp _0Wy<9C .y\F[0Juؘ&D¡9fn1 ɐ{ ;S<yKZ=.\|/\͢ls*f ^#og]KujC>QzVGEܹ_Ka ER@. 6_U죘ڣڀ9`[DIZ2gI8u,Xj˜9|TVt}üF4aTvl7E |A{rea3;n,3-k|q_Ǎ8 '270Y"@I]TMBTX ac vDrusUe-K9wuᒒ1+MJz!P'`ws\ˁbۂኒZ`lIP Kފ{ؑQ0Ru?YP{Q jV z9?\ h9 E,@_79cd$6U( n  ܥMJѪ&wײQ _awkD\L_Zm 轤ukqxoFiyW3ԇQha@eu A?I{"I3wh[ NI놚t%یYob]qK74d %m [&b.Q1;жkC1}أ5|d/h… \IUPTTEGڮ })v bUOJ|k@'[.'0״9tIFO#z$t H-4z*amrI;^&uHTҥjsE`<( ĵ x=65LH)=ro9>yjJ`1Vm@C+j"|x?:2 5/+յ##+Ϡcqj)JldQKW,-r ՋQr(v3JmD MLpO7]ʺQ $oH\wr9\ȩ^۷S9zJ <7j%7Jz" $%2^}h/oטf5* f@mj(|\EM3HHwftT &5@٦5&Tߦ@7(*j["Oo3 LH%}vסϊ`*$u'e3&_K;y-"QLJ;EpDʇzL F% E߅\X5BdgaOi%ąWK1 6]or/1#Sq PVY*pv'&/ٷҁMBm=x7o/5 o_iVl &/\/M@]odR ~l#"@yD0%|՝yl{r2REG(L'(Bo~m!C[6omαk 0ZXABi|l +;VD$`D0=Fa $D{kOew<\2_X$Cх2OT}lS/:8Fۖ{]bL,iC*wd!_f%$ ODR drh:Ъ &Y]qo4T.p ijA7?Rn}CmB ],[8~=#FUӒ;eW 7F>R =2%;g ^J+=#Of:^1iJ1ĝMrf,ϨVHjr{>֍_k2ymɦ# )[uF/M|nϡ'L331)X "*NdhP93*;Fʂ5HHEtImŨo0{x8r:yjnZN'9l/(myߨ2C>rˀ^ZNT^8+{ۋZFirG\e[L+y=_g,6ctY0$VҘb-UW"o|AS9QoOnwx)乼 weTV\6@kօ%RbJE_ؔz* (!$¾'U߂C8Jjdv*7& LLs׶.^9 ЮFhLB!n2ՠ>eEK{VO1@bCS )#+ycB>q'fù}Kv0OuZD|\= V%V?AxRߴ?exZM"ţs${e7gNPj["l U}1%L+#4,+SݢtHΫ_bwYpenuk=q C 9}* 4pj($V[2_Qc7;@Y9A}M}Wz(+J 2TfarHdJl|NUhf~!˗<runє1-]BHEb*k|dL($oo6GF@pZeA"Pt;~3&$bB>pc^NE22}@v*`Ji`(ܳQ.YZiɼ$/*$~"N^Uϝ T:&xq.xws' 1}m'>sQh"{=N@h(xeS|ܪpt$4Ls[6J"6kQ4p |҅SJmBqFhZ/KFb5'IíTtv"˓ʹ3n}+ zQ^N' j/-0`Xoj]e=%7bܐ[J %H"Ó/Ҡ%yc`*em {d<(j+%/3UH$DXB:7roE:t'Ns\ctgaHRʵf쑮M6UP1݆ی !MS<<^Tؼ!rr6FL\Hj$2[ء1 4Ϻ``J)hYQ,=Y"^H=֡2_6WEy h<)Œ|z⋚;6ݨ"z#oT˘vmyZYvBԃ%9iR)}+.%>B\Jn̶Q{ ]Mײ  OΒ2:a:SlOF-uN[@E|p$uظ(bHңHK,\ ȝ-2Av|;1R'ST'1{`MLaS&9LmˋŚe[7{N<}Z^#7N13Y_(>E2nnRchDQ3BUQ2..Ka~ZdO]gn$=)z goQK;a&ÅcקZ=(x>cm(qӊQ^ݶKQK7a /\[bybm$"o̘|(D E;H(J@S+͐fo"8*c @ܤ%WowAs2g汃A]uH x\(1rKUkAs=BND˷ף! b d d.$>%vSIkX>+RғQϢ6eE׻0`i' 1E e UD<[:t7kZD`2n>hLo>#ЈQP88&j$~$ʭ¢v\WRE@.E5Uʧm 8 .;~%L=q1#UvCeĬ\H^R(R]) %aGyΫ?hHVuyx[IMY5bm'0K"BExCdY<ȉ)Py`Dє#X 9i]A@rYO%{K]r!(~ؔQ@a }d.OƌȈ"PuVSL>tQJR*~Q?ΥRr -+u1ПkCm% v>|y65M}B>Lɕr x[+˖;{ʥ%{[K6OtWM ./<y*cvʸ<:eOHBڲ䂸DڊGX8ML9vv!*9M,wF|;{ҥuml+s)uHiʹCH̐aq3NފzvζbF=r@+z}qYb.4{{pR6|'A>{ ü+5Ldw& /T!gq T7ԍɣ*9u&4ߴ=Y3N~# +x2c (hyR ~^-l7*_F9*#i9 $O<>c"#Ջ" k} *,S XKׂIdaþB7G@أ!{0_SDZh Kh0,*/̯DhQ7jg] ܊;hH^!JWiڌ3 {f@dLB-E οH r(YG8# DRÌ| Tw9m*5uժ)#NLG^Sya衘 WRl:8USp$?I]kWPk*XWRV/`,݊2".<2n-ZV䅱KwAR57̒  Q^$Y=v^蝘]dDA#&*"/p>q^[KamLBqͺHpWđBC%"ݝY\Wy{FIURwkm0 ,w%Ko#mj˒%3%3 \@%B0{Xol EBx 8ܥstO)e_9H4w6?|Ykqkf>j4_?rߕz<]tawg{`\\lw6.h,om5N[ͭfrbm׻ݽξnw}_wogw/^_J\ۍ;nwOsxae•W;^ `YN#:_{o{] ԋu `ŀjTMhҜdhv'44'4ԥACh0Z¹ `.4 B8whӄ [Asy. v٤L4YI@hc>gѵ ϟ﨏?Yl4pTBWkKhBB$ 2 m@ߨ0oܪ'9Ӓ4'4M^< a\BT Q !ADTkC! AAV3BLPaD)ә A0}Z)iқ!QaVk͕f{lovֶj1-&HkݭhcDT=M|N-YmW[Zwooi`i!g$G2wQm}-sC>Dk+kvQBf~b6jAԅkJiEEaP 0)̅f0.M3K`B]Y>lyyU`C=@4.Fq#&wCxQ@^BK*+ȷ@K$@H<9RT_B8DNb.n!gys0VNe $ؕ쯩kǐOX\k3 Y0hlnveuŻD8F"U&XfflG,BAR|ƈ$l5%meɂ&͉@dd.%&<.L2B2:QRRe$υ}-h):MP_JA+*LqVkлA^")MBvm*0 PSA^ pJb*$鯴P^zixBH} $t (Զ|]^Tק\y N6m*q`Lm XrY qJqYy1s79!"t$c!8Pg(څk'JR ^}Vv :|^>Lk8IĄl*9 ol{a[~-1 ~ȵגܖUp)&\]Jn8KnbAJoи$ϛĞ!1t N8wp++^oXF^tLS εn'=؃>U%E Eb!̈J&{  %JЕxmAu MDc$жX!ąT[eUធϒV(8sgz/y>'̵̽EҎ̝Zbw F6yuw2GJ?Kx\.6u G{|UO5+lV-2^ Y8C6b:wnr'rG[ {9q{0@z?G.lZ~H,\9+s3 \(O U4n%NAGT2_[݃әIu*=H:<2Vz`{im@Pn0*z $YQ8oM{ -$$kx&U3mԸ3Swx,Mv2zŖX^L{~h3@i!%Ѵ*Ť,ybdIQz0{ʳic#ʩZk[[kB6^I,bfHn}TJԩMT (Oq8ERClMpBYnYw"mPqP>"=OlQ;@▹ b1{(,G$ #GLw1eJ7[چ5a1 h%,#n2s>|eɤm,V?k(_zbB}Kȡ}PgLāz4ט} ǓVԭZ8f}B*r1eD pL29N -!ZF;kd]o6$ Y!b1j>k,f^Ǽt mƃY"xgHg3aq6c.B 8u /0(3oV\N Ag)CS/.++xw-tvYx1N2D7dkD$b%ޚ.r-SMpB~-0'w/@^3'x,=9,.sOsvb\ܬa~D4]G>t&L*H}>ƨ(#eOr sHs m6,ttNǠz"HoG| 8*dULՋHOdxV>sLT}[ߐ7LƲ"[b&M w7V0(#yQ%|!z-hق=ӲT|)oRURzNoS{ЃX$ CJnit?)ə6,uזpNyۊ#?6zǝmrM-}i\J{d5yɝ9 UM @H<"|@EW"AM: 4g:YG{N׭V#Wt҇ҳtwE( DԬBN\qvEj8bݞR_n!TɈ.ђ~ĻV6K=?MfpETBS h#mZ?IaJ1q4D6m2A?Bpռ<jrJ$ SsHyYzKag^3w3Ɉuļx 'Jg֮f>1c(̔ye', &ՔLf p;oY{Y˚p 8J6[cS󓢨~NIy,x0@JZskJPowj3XvǸ=l!M3z'<:`;gڴ(H"'cy(_ݹ26@0E6-_U6è %DfNUY@^\Np;#pۄ3k-s`ېC%Z%Cߴ' '\k!; OJ(&*Լ'7N {%yv#s>?rޫP < g4)[kGomrʸJ8ymĜw"YOoo_ԦaU ΁tr3Xʬ}ggw~hʼRkeKK4CI;{ȷ '!3i7{kft;چߵwu%PI/U0ԨdŇ RVt ]H1|'-V/[@nOHғȷDCMp+JY.ǿ3? {0]B2 sfiIB=U^IlMCMFH=G.7>cO[Qȷ)xԷQC&b<yMD1qaԛl ]u$n0Z ]Y;m7>[جǑ1GVUcw|@UtPgevnxEE6&}ܬ1  Y8A} $R/oцy#f!U&E⩢7JM3]Wi]ñSԬpv F̸_]L\*U$uc&[홅Sz s]~*L륹CDjf>Mq{+^JK U*;SBGyӡ#<>>Y5w(]ZM04<,'lo)]\hF{|}g4* iJXxB,0}=y9ڲk#yA3.*GlSY/=nfiO뵷 mT=N)HKIRͺ!W77р? PA^('LJjA0?S ?2g'k仳iU0nyxK z,l BVЪ[##iK5{Ql+_jț8(k/^+i S@?G$ o 'o dG}rQX,l{C/l /Tuv.'sQyh;QSo2=J'v7 r[Kq[UI2AKaIfTIye4m; duD'7}V@ing2PtˋЋ ){|.<U=5ff0ޕZO,xz$۫f F3%M9^\Liw^ 3g8)h㰱B>j&E?㞒FU-Lj9:`+m ֶQc=mzul&7N_!(9 ZD> 'Y47 c=icm.2` jDrgO(h׾:QOP69V(h>solmK5l\‡u#Ȅ4[m5B췌|QHɜ7,3k/ކ;ɀ) W[A> ۚF~P ۆ?Ӹ5乮H,,~gaZ۽,>l F/O_bgߖsXK&KFӗ.sd )Ul̅#t_ <`cL׃3823y6kǏGqxR7E5;5?B!nb|qr;$jalkтY\>o!@qyĹar.4{FVɆ&0x =[ʒ=Ch%ѸS@rm9=4fFHҵ¶6k>.3Uzِ`ʳb]߂(@<<="c7d6d6 kh [xm Mq̭O=݄dZ[0hOI$U$ï$} hqvꐤ==DA,Gf [ϻ'lZO-F ȈUivlT|@K4IA?8+E2BC!ŝieU}|7݀nCW rr7qCT м5%[4&nhkъ5FD@@@LR&R)r]YswMqN):>~y@gԹ8M__9U'}t(Ğ# =O<w~,n/-uWv[˫[WvV]Ǐ^zceH#{76cWH<=pՕ•!JqNr2ɫ^ :g9K3[;8~y?.\$m@Qu.<(mwW 6o~lcw׏$SvǗ[_* L7ΘRNΘ~A>ckӮ 'A꒳ G2'b uQ2:*ѳ" -"a=O 07q @89@ 6|2Bʀre+ nVCy)G>GƦHsHFAD+dFn͔襦@j| ВCq3p ~)@(Rnיm;Hٜ<(,p:KxbʃCXΓ Njlq,[## ;!:9&w`0rd^u9u 3skL(E̡{m#@4Rum^ c?@! Yr@Qn, t_-GaDv5Fߢ*'*֓n0,<,]&w,l:ݘ:HP;0I=[^[^Prr "ʪӎS(GBIFΎWtr9]b#g'H|_T?35Ba*A6PHܒƗh" )D{ir*KHav啕/rZ+a)v+HHdL-YBqTaƶXC=7>:brf;\NQFB6ָ0'iivSKX(˻Yx-C0m e$0jYrvO?Dh RyJ?%gg4(zle8]e'YߐS s:9ފ,\$`/DL4& BShlyfu'MVD8ḊMl8 hPXv 23PP.Xy'_`Hb O0`X캸AOk. ùG_0X^`qʚ ~Z۷wY6^~?'(/$!Y[sTQyOx.7&3j;,>c6A Pҡf[DISP#T{Hbɐ?!TכR *TU3"Dp YGk>Cn2F""m5)Fv RO5C:/ ԑK=c7Ij?D z^V+.d?*)W4pb j3vW=1s*b*Tq09ARG:!L4/N9FpSy)EfW&ʑTLy|I@/a$!燗Q؊P0f#"43.>\3GHuz@,<}oE[>U0 x>zMQ:{H?(TCC[fL4ZV[=0hKVsH co؊xd&= VaK#k_s@-:S6[B @?󡹱&p,@K_)A0La}R4T''MuSݜɰ[sUUx: /`t".݋\`18وGN rꦃk/$gAǸ8By|V`ոšȳBniEŊDuLva ˩`-zC|Q*ĝhf4{sv!wo254 n+ٮQl%WmrA;$셭]:ڑ` 9MH:p 9% !QN808ǝ"O>ݪJ5qEj