From e95fe63c3cc176521624100ea6739f599083bde7 Mon Sep 17 00:00:00 2001 From: "Josh L. Espinoza" Date: Tue, 19 Dec 2023 14:49:16 -0800 Subject: [PATCH] v1.4.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Release v1.4.0 Highlights:** * **`VEBA` Modules:** * Added `profile-taxonomic.py` module which uses `sylph` to build a sketch database for genomes and queries the genome database for taxonomic abundance. * Added long read support for `fastq_preprocessor`, `preprocess.py`, `assembly-long.py`, `coverage-long`, and all binning modules. * Redesign `binning-eukaryotic` module to handle custom `MetaEuk` databases * Added new usage syntax `veba --module preprocess --params “${PARAMS}”` where the Conda environment is abstracted and determined automatically in the backend. Changed all the walkthroughs to reflect this change. * Added `skani` which is the new default for genome-level clustering based on ANI. * Added `Diamond DeepClust` as an alternative to `MMSEQS2` for protein clustering. * **`VEBA` Database (`VDB_v6`)**: * Completely rebuilt `VEBA's Microeukaryotic Protein Database` to produce a clustered database `MicroEuk100/90/50` similar to `UniRef100/90/50`. Available on [doi:10.5281/zenodo.10139450](https://zenodo.org/records/10139451). * **Number of sequences:** * MicroEuk100 = 79,920,431 (19 GB) * MicroEuk90 = 51,767,730 (13 GB) * MicroEuk50 = 29,898,853 (6.5 GB) * **Number of source organisms per dataset:** * MycoCosm = 2503 * PhycoCosm = 174 * EnsemblProtists = 233 * MMETSP = 759 * TARA_SAGv1 = 8 * EukProt = 366 * EukZoo = 27 * TARA_SMAGv1 = 389 * NR_Protists-Fungi = 48217
**Release v1.4.0 Details** * [2023.12.15] - Added `profile-taxonomic.py` module which uses `sylph` to build a sketch database for genomes and queries the genome database similar to `Kraken` for taxonomic abundance. * [2023.12.14] - Removed requirement to have `--estimated_assembly_size` for Flye per [Flye Issue #652](https://github.com/fenderglass/Flye/issues/652). * [2023.12.14] - Added `sylph` to `VEBA-profile_env` for abundance profiling of genomes. * [2023.12.13] - Dereplicate duplicate contigs in `concatenate_fasta.py`. * [2023.12.12] - Added `--reference_gzipped` to `index.py` and `mapping.py` with new default being that the reference fasta is not gzipped. * [2023.12.11] - Added `skani` as new default for genome clustering in `cluster.py`, `global_clustering.py`, and `local_clustering.py`. * [2023.12.11] - Added support for long reads in `fastq_preprocessor`, `preprocess.py`, `assembly-long.py`, `coverage-long`, and all binning modules. * [2023.11.28] - Fixed `annotations.protein_clusters.tsv.gz` from `merge_annotations.py` added in patch update of `v1.3.1`. * [2023.11.14] - Added support for missing values in `compile_eukaryotic_classifications.py`. * [2023.11.13] - Added `--metaeuk_split_memory_limit` argument with (experimental) default set to `36G` in `binning-eukaryotic.py` and `eukaryotic_gene_modeling.py`. * [2023.11.10] - Added `--compressed 1` to `mmseqs createdb` in `download_databases.sh` installation script. * [2023.11.10] - Added a check to `check_fasta_duplicates.py` and `clean_fasta.py` to make sure there are no `>` characters in fasta sequence caused from concatenating fasta files that are missing linebreaks. * [2023.11.10] - Added `Diamond DeepClust` to `clustering_wrapper.py`, `global/local_clustering.py`, and `cluster.py`. Changed `mmseqs2_wrapper.py` to `clustering_wrapper.py`. Changed `easy-cluster` and `easy-linclust` to `mmseqs-cluster` and `mmseqs-linclust`. * [2023.11.9] - Fixed viral quality in `merge_genome_quality_assessments.py` * [2023.11.3] - Changed `consensus_genome_classification.py` to `consensus_genome_classification_ranked.py`. Also, default behavior to allow for missing taxonomic levels. * [2023.11.2] - Fixed the `merge_annotations.py` resulting in a memory leak when creating the `annotations.protein_clusters.tsv.gz` output table. However, still need to correct the formatting for empty sets and string lists.
--- .DS_Store | Bin 14340 -> 0 bytes CHANGELOG.md | 107 +- MODULE_RESOURCES.xlsx | Bin 0 -> 10700 bytes README.md | 51 +- SOURCES.xlsx | Bin 45015 -> 46926 bytes VERSION | 4 +- .../01.KEGG_DB/00.KEGG_Data_Scrapper.py | 165 + .../01.KEGG_DB/00.Module_Names.txt | 394 ++ .../01.KEGG_DB/01.Bifurcating_List.txt | 23 + .../01.KEGG_DB/02.Structural_List.txt | 10 + .../01.KEGG_DB/03.Bifurcating_Modules.dict | 1 + .../01.KEGG_DB/04.Structural_Modules.dict | 1 + .../01.KEGG_DB/05.Modules_Parsed.txt | 3343 +++++++++++++++++ .../01.KEGG_DB/06.Module_Groups.txt | 394 ++ .../KEGG_Bifurcating_Module_Information.pkl | Bin 0 -> 5883 bytes .../MicrobeAnnotator_KEGG/KEGG_Module-KOs.pkl | Bin 0 -> 4977803 bytes .../KEGG_Module_Information.txt | 394 ++ .../KEGG_Regular_Module_Information.pkl | Bin 0 -> 59874 bytes .../KEGG_Structural_Module_Information.pkl | Bin 0 -> 1161 bytes .../MicrobeAnnotator-KEGG.tar.gz | Bin 0 -> 132054 bytes .../MicrobeAnnotator-KEGG.tar.gz.md5 | 1 + data/MicrobeAnnotator_KEGG/README.md | 69 + data/README.md | 11 +- install/README.md | 27 +- install/{ => deprecated}/PATCHES.md | 0 install/download_databases.sh | 77 +- install/environments/VEBA-assembly_env.yml | 37 +- install/environments/VEBA-cluster_env.yml | 45 +- install/environments/VEBA-database_env.yml | 10 +- install/environments/VEBA-mapping_env.yml | 146 +- install/environments/VEBA-preprocess_env.yml | 124 +- install/environments/VEBA-profile_env.yml | 9 +- install/{install_veba.sh => install.sh} | 33 +- install/{uninstall_veba.sh => uninstall.sh} | 0 install/update_environment_scripts.sh | 12 +- src/MODULE_RESOURCES | 18 - src/README.md | 42 +- src/amplicon.py | 3 +- src/annotate.py | 3 +- src/assembly-long.py | 627 ++++ src/assembly.py | 7 +- src/binning-eukaryotic.py | 9 +- src/binning-prokaryotic.py | 3 +- src/binning-viral.py | 3 +- src/biosynthetic.py | 13 +- src/classify-eukaryotic.py | 15 +- src/classify-prokaryotic.py | 7 +- src/classify-viral.py | 3 +- src/cluster.py | 132 +- src/coverage-long.py | 587 +++ src/coverage.py | 5 +- src/deprecated/preprocess.py | 151 + src/index.py | 69 +- src/mapping.py | 13 +- src/phylogeny.py | 3 +- src/preprocess-long.py | 21 + src/preprocess.py | 155 +- src/profile-pathway.py | 3 +- src/profile-taxonomy.py | 357 ++ src/scripts/binning_wrapper.py | 11 +- .../build_source_to_lineage_dictionary.py | 69 + .../build_target_to_source_dictionary.py | 77 + src/scripts/check_fasta_duplicates.py | 11 +- src/scripts/clean_fasta.py | 124 + src/scripts/clustering_wrapper.py | 439 +++ ...custom_humann_database_from_annotations.py | 4 +- ...stom_sylph_sketch_database_from_genomes.py | 239 ++ .../compile_eukaryotic_classifications.py | 114 +- ...ome_cluster_classification_scores_table.py | 1 - src/scripts/compile_reads_table.py | 62 +- src/scripts/concatenate_assembly.py | 99 + src/scripts/concatenate_fasta.py | 115 +- .../consensus_genome_classification_ranked.py | 222 ++ .../consensus_genome_classification.py | 0 .../{ => deprecated}/mmseqs2_wrapper.py | 0 ...pile_phylogenomic_functional_categories.py | 147 + ...presentative_genome_from_networkx_graph.py | 52 + src/scripts/edgelist_to_clusters.py | 22 +- .../eukaryotic_gene_modeling_wrapper.py | 4 +- src/scripts/filter_spades_assembly.py | 100 + src/scripts/global_clustering.py | 263 +- src/scripts/local_clustering.py | 261 +- src/scripts/merge_annotations.py | 263 +- .../merge_genome_quality_assessments.py | 4 +- src/scripts/merge_taxonomy_classifications.py | 4 +- src/scripts/module_completion_ratios.py | 7 +- src/scripts/partition_unbinned.py | 4 +- ...rmat_sylph_profile_single_sample_output.py | 68 + src/veba | 194 + ...et_script_versions.sh => veba_versions.sh} | 0 walkthroughs/README.md | 32 +- walkthroughs/adapting_commands_for_aws.md | 2 +- walkthroughs/adapting_commands_for_docker.md | 6 +- ...specting_for_biosynthetic_gene_clusters.md | 6 +- walkthroughs/converting_counts_tables.md | 4 +- walkthroughs/download_and_preprocess_reads.md | 26 +- walkthroughs/end-to-end_metagenomics.md | 80 +- ...d => pathway_profiling_de-novo_genomes.md} | 10 +- walkthroughs/phylogenetic_inference.md | 6 +- .../read_mapping_and_counts_tables.md | 28 +- ...vering_viruses_from_metatranscriptomics.md | 21 +- walkthroughs/setting_up_coassemblies.md | 17 +- .../taxonomic_profiling_de-novo_genomes.md | 90 + 103 files changed, 10029 insertions(+), 1016 deletions(-) delete mode 100644 .DS_Store create mode 100644 MODULE_RESOURCES.xlsx create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.KEGG_Data_Scrapper.py create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.Module_Names.txt create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/01.Bifurcating_List.txt create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/02.Structural_List.txt create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/03.Bifurcating_Modules.dict create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/04.Structural_Modules.dict create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/05.Modules_Parsed.txt create mode 100644 data/MicrobeAnnotator_KEGG/01.KEGG_DB/06.Module_Groups.txt create mode 100644 data/MicrobeAnnotator_KEGG/KEGG_Bifurcating_Module_Information.pkl create mode 100644 data/MicrobeAnnotator_KEGG/KEGG_Module-KOs.pkl create mode 100644 data/MicrobeAnnotator_KEGG/KEGG_Module_Information.txt create mode 100644 data/MicrobeAnnotator_KEGG/KEGG_Regular_Module_Information.pkl create mode 100644 data/MicrobeAnnotator_KEGG/KEGG_Structural_Module_Information.pkl create mode 100644 data/MicrobeAnnotator_KEGG/MicrobeAnnotator-KEGG.tar.gz create mode 100644 data/MicrobeAnnotator_KEGG/MicrobeAnnotator-KEGG.tar.gz.md5 create mode 100644 data/MicrobeAnnotator_KEGG/README.md rename install/{ => deprecated}/PATCHES.md (100%) rename install/{install_veba.sh => install.sh} (57%) rename install/{uninstall_veba.sh => uninstall.sh} (100%) delete mode 100644 src/MODULE_RESOURCES create mode 100755 src/assembly-long.py create mode 100755 src/coverage-long.py create mode 100755 src/deprecated/preprocess.py create mode 100755 src/preprocess-long.py create mode 100755 src/profile-taxonomy.py create mode 100755 src/scripts/build_source_to_lineage_dictionary.py create mode 100755 src/scripts/build_target_to_source_dictionary.py create mode 100755 src/scripts/clean_fasta.py create mode 100755 src/scripts/clustering_wrapper.py create mode 100755 src/scripts/compile_custom_sylph_sketch_database_from_genomes.py create mode 100755 src/scripts/concatenate_assembly.py create mode 100755 src/scripts/consensus_genome_classification_ranked.py rename src/scripts/{ => deprecated}/consensus_genome_classification.py (100%) rename src/scripts/{ => deprecated}/mmseqs2_wrapper.py (100%) create mode 100755 src/scripts/devel/compile_phylogenomic_functional_categories.py create mode 100755 src/scripts/devel/representative_genome_from_networkx_graph.py create mode 100755 src/scripts/filter_spades_assembly.py create mode 100755 src/scripts/reformat_sylph_profile_single_sample_output.py create mode 100755 src/veba rename src/{get_script_versions.sh => veba_versions.sh} (100%) rename walkthroughs/{metabolic_profiling_de-novo_genomes.md => pathway_profiling_de-novo_genomes.md} (91%) create mode 100644 walkthroughs/taxonomic_profiling_de-novo_genomes.md diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 2acc3c3d9016a743084c15eeef0ac3f152049a42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14340 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 + **Release v1.4.0 Details** +* [2023.12.15] - Added `profile-taxonomic.py` module which uses `sylph` to build a sketch database for genomes and queries the genome database similar to `Kraken` for taxonomic abundance. +* [2023.12.14] - Removed requirement to have `--estimated_assembly_size` for Flye per [Flye Issue #652](https://github.com/fenderglass/Flye/issues/652). +* [2023.12.14] - Added `sylph` to `VEBA-profile_env` for abundance profiling of genomes. +* [2023.12.13] - Dereplicate duplicate contigs in `concatenate_fasta.py`. +* [2023.12.12] - Added `--reference_gzipped` to `index.py` and `mapping.py` with new default being that the reference fasta is not gzipped. +* [2023.12.11] - Added `skani` as new default for genome clustering in `cluster.py`, `global_clustering.py`, and `local_clustering.py`. +* [2023.12.11] - Added support for long reads in `fastq_preprocessor`, `preprocess.py`, `assembly-long.py`, `coverage-long`, and all binning modules. +* [2023.11.28] - Fixed `annotations.protein_clusters.tsv.gz` from `merge_annotations.py` added in patch update of `v1.3.1`. +* [2023.11.14] - Added support for missing values in `compile_eukaryotic_classifications.py`. +* [2023.11.13] - Added `--metaeuk_split_memory_limit` argument with (experimental) default set to `36G` in `binning-eukaryotic.py` and `eukaryotic_gene_modeling.py`. +* [2023.11.10] - Added `--compressed 1` to `mmseqs createdb` in `download_databases.sh` installation script. +* [2023.11.10] - Added a check to `check_fasta_duplicates.py` and `clean_fasta.py` to make sure there are no `>` characters in fasta sequence caused from concatenating fasta files that are missing linebreaks. +* [2023.11.10] - Added `Diamond DeepClust` to `clustering_wrapper.py`, `global/local_clustering.py`, and `cluster.py`. Changed `mmseqs2_wrapper.py` to `clustering_wrapper.py`. Changed `easy-cluster` and `easy-linclust` to `mmseqs-cluster` and `mmseqs-linclust`. +* [2023.11.9] - Fixed viral quality in `merge_genome_quality_assessments.py` +* [2023.11.3] - Changed `consensus_genome_classification.py` to `consensus_genome_classification_ranked.py`. Also, default behavior to allow for missing taxonomic levels. +* [2023.11.2] - Fixed the `merge_annotations.py` resulting in a memory leak when creating the `annotations.protein_clusters.tsv.gz` output table. However, still need to correct the formatting for empty sets and string lists. + + + +**Release v1.3.0 Highlights:** * **`VEBA` Modules:** * Added `profile-pathway.py` module and associated scripts for building `HUMAnN` databases from *de novo* genomes and annotations. Essentially, a reads-based functional profiling method via `HUMAnN` using binned genomes as the database. @@ -139,6 +205,7 @@ ________________________________________________________________ **Release v1.1.0 Details** * **Modules**: + * `annotate.py` * Added `NCBIfam-AMRFinder` AMR domain annotations * Added `AntiFam` contimination annotations @@ -238,6 +305,7 @@ ________________________________________________________________ * `build_taxa_sqlite.py` * **Miscellaneous**: + * Updated environments and now add versions to environments. * Added `mamba` to installation to speed up. * Added `transdecoder_wrapper.py` which is a wrapper around `TransDecoder` with direct support for `Diamond` and `HMMSearch` homology searches. Also includes `append_geneid_to_transdecoder_gff.py` which is run in the backend to clean up the GFF file and make them compatible with what is output by `Prodigal` and `MetaEuk` runs of `VEBA`. @@ -317,6 +385,8 @@ ________________________________________________________________ **Critical:** +* `binning-prokaryotic.py` doesn't produce an `unbinned.fasta` file for long reads if there aren't any genomes. It also creates a symlink called `genomes` in the working directory. +* Add a way to show all versions * Genome checkpoints in `tRNAscan-SE` aren't working properly. * Dereplcate CDS sequences in GFF from `MetaEuk` for `antiSMASH` to work for eukaryotic genomes * Error with `amplicon.py` that works when run manually... @@ -329,39 +399,58 @@ There was a problem importing veba_output/misc/reads_table.tsv: **Definitely:** +* Use `pigz` instead of `gzip` +* Create a taxdump for `MicroEuk` +* Reimplement `compile_eukaryotic_classifications.py` * Add representative to `identifier_mapping.proteins.tsv.gz` -* Add coding density to GFF files * Split `download_databases.sh` into `download_databases.sh` (low memory, high threads) and `configure_databases.sh` (high memory, low-to-mid threads). Use `aria2` in parallel instead of `wget`. * `NextFlow` support -* Consistent usage of the following terms: 1) dataframe vs. table; 2) protein-cluster vs. orthogroup. -* Add support for `FAMSA` in `phylogeny.py` -* Create a `assembly-longreads.py` module that uses `MetaFlye` -* Expand Microeukaryotic Protein Database to include more microeukaryotes (`Mycocosm` and `PhycoCosm` from `JGI`) * Install each module via `bioconda` * Add support for `Salmon` in `mapping.py` and `index.py`. This can be used instead of `STAR` which will require adding the `exon` field to `Prodigal` GFF file (`MetaEuk` modified GFF files already have exon ids). -**Probably (Yes)?:** +**Eventually (Yes)?:** +* Don't load all genomes, proteins, and cds into memory for clustering. +* Add support for `FAMSA` in `phylogeny.py` +* Consistent usage of the following terms: 1) dataframe vs. table; 2) protein-cluster vs. orthogroup. +* Add coding density to GFF files +* Add `vRhyme` to `binning_wrapper.py` and support `vRhyme` in `binning-viral.py`. +* Phylogenetic tree of `MicroEuk100` * Convert HMMs to `MMSEQS2` (https://github.com/soedinglab/MMseqs2/wiki#how-to-create-a-target-profile-database-from-pfam)? * Run `cmsearch` before `tRNAscan-SE` * DN/DS from pangeome analysis * Add [iPHoP](https://bitbucket.org/srouxjgi/iphop/src/main/) to `binning-viral.py`. * Add a `metabolic.py` module * Swap [`TransDecoder`](https://github.com/TransDecoder/TransDecoder) for [`TransSuite`](https://github.com/anonconda/TranSuite) -* Build a clustered version of the Microeukaryotic Protein Database that is more efficient to run. Similar to UniRef100, UniRef90, UniRef50. +* For viral binning, contigs that are not identified as viral via `geNomad -> CheckV` use with `vRhyme`. **...Maybe (Not)?** * Modify behavior of `annotate.py` to allow for skipping Pfam and/or KOFAM since they take a long time. - ________________________________________________________________
**Daily Change Log:** +* [2023.12.15] - Added `profile-taxonomic.py` module which uses `sylph` to build a sketch database for genomes and queries the genome database similar to `Kraken` for taxonomic abundance. +* [2023.12.14] - Removed requirement to have `--estimated_assembly_size` for Flye per [Flye Issue #652](https://github.com/fenderglass/Flye/issues/652). +* [2023.12.14] - Added `sylph` to `VEBA-profile_env` for abundance profiling of genomes. +* [2023.12.13] - Dereplicate duplicate contigs in `concatenate_fasta.py`. +* [2023.12.12] - Added `--reference_gzipped` to `index.py` and `mapping.py` with new default being that the reference fasta is not gzipped. +* [2023.12.11] - Added `skani` as new default for genome clustering in `cluster.py`, `global_clustering.py`, and `local_clustering.py`. +* [2023.12.11] - Added support for long reads in `fastq_preprocessor`, `preprocess.py`, `assembly-long.py`, and all binning modules. +* [2023.11.28] - Fixed `annotations.protein_clusters.tsv.gz` from `merge_annotations.py` added in patch update of `v1.3.1`. +* [2023.11.14] - Added support for missing values in `compile_eukaryotic_classifications.py`. +* [2023.11.13] - Added `--metaeuk_split_memory_limit` argument with (experimental) default set to `36G` in `binning-eukaryotic.py` and `eukaryotic_gene_modeling.py`. +* [2023.11.10] - Added `--compressed 1` to `mmseqs createdb` in `download_databases.sh` installation script. +* [2023.11.10] - Added a check to `check_fasta_duplicates.py` and `clean_fasta.py` to make sure there are no `>` characters in fasta sequence caused from concatenating fasta files that are missing linebreaks. +* [2023.11.10] - Added `Diamond DeepClust` to `clustering_wrapper.py`, `global/local_clustering.py`, and `cluster.py`. Changed `mmseqs2_wrapper.py` to `clustering_wrapper.py`. Changed `easy-cluster` and `easy-linclust` to `mmseqs-cluster` and `mmseqs-linclust`. +* [2023.11.9] - Fixed viral quality in `merge_genome_quality_assessments.py` +* [2023.11.3] - Changed `consensus_genome_classification.py` to `consensus_genome_classification_ranked.py`. Also, default behavior to allow for missing taxonomic levels. +* [2023.11.2] - Fixed the `merge_annotations.py` resulting in a memory leak when creating the `annotations.protein_clusters.tsv.gz` output table. However, still need to correct the formatting for empty sets and string lists. * [2023.10.27] - Update `annotate.py` and `merge_annotations.py` to handle `CAZy`. They also properly address clustered protein annotations now. * [2023.10.18] - Added `module_completion_ratio.py` script which is a fork of `MicrobeAnnotator` [`ko_mapper.py`](https://github.com/cruizperez/MicrobeAnnotator/blob/master/microbeannotator/pipeline/ko_mapper.py). Also included a database [Zenodo: 10020074](https://zenodo.org/records/10020074) which will be included in `VDB_v5.2` * [2023.10.16] - Added a checkpoint for `tRNAscan-SE` in `binning-prokaryotic.py` and `eukaryotic_gene_modeling_wrapper.py`. diff --git a/MODULE_RESOURCES.xlsx b/MODULE_RESOURCES.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..bf99e33880301c230f8d33c8592a52f5bf875904 GIT binary patch literal 10700 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 T=>h=ouOF{h*Ue7(+pqrzT2LA8 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index b1161ef..9e6a39a 100644 --- a/README.md +++ b/README.md @@ -45,19 +45,18 @@ ___________________________________________________________________ * **What's new in `VEBA v1.3.0`?** * **`VEBA` Modules:** - * Added `profile-pathway.py` module and associated scripts for building `HUMAnN` databases from *de novo* genomes and annotations. Essentially, a reads-based functional profiling method via `HUMAnN` using binned genomes as the database. - * Added `marker_gene_clustering.py` script which identifies core marker proteins that are present in all genomes within a genome cluster (i.e., pangenome) and unique to only that genome cluster. Clusters in either protein or nucleotide space. - * Added `module_completion_ratios.py` script which calculates KEGG module completion ratios for genomes and pangenomes. Automatically run in backend of `annotate.py`. - * Updated `annotate.py` and `merge_annotations.py` to provide better annotations for clustered proteins. - * Added `merge_genome_quality.py` and `merge_taxonomy_classifications.py` which compiles genome quality and taxonomy, respectively, for all organisms. - * Added BGC clustering in protein and nucleotide space to `biosynthetic.py`. Also, produces prevalence tables that can be used for further clustering of BGCs. - * Added `pangenome_core_sequences` in `cluster.py` writes both protein and CDS sequences for each genome cluster. - * Added PDF visualization of newick trees in `phylogeny.py`. - - -* **`VEBA` Database (`VDB_v5.2`)**: - * Added `CAZy` - * Added `MicrobeAnnotator-KEGG` + + * Added `profile-taxonomic.py` module which uses `sylph` to build a sketch database for genomes and queries the genome database for taxonomic abundance. + * Added long read support for `fastq_preprocessor`, `preprocess.py`, `assembly-long.py`, `coverage-long`, and all binning modules. + * Redesign `binning-eukaryotic` module to handle custom `MetaEuk` databases + * Added new usage syntax `veba --module preprocess --params “${PARAMS}”` where the Conda environment is abstracted and determined automatically in the backend. Changed all the walkthroughs to reflect this change. + * Added `skani` which is the new default for genome-level clustering based on ANI. + * Added `Diamond DeepClust` as an alternative to `MMSEQS2` for protein clustering. + +* **`VEBA` Database (`VDB_v6`)**: + + * Completely rebuilt `VEBA's Microeukaryotic Protein Database` to produce a clustered database `MicroEuk100/90/50` similar to `UniRef100/90/50`. Available on [doi:10.5281/zenodo.10139450](https://zenodo.org/records/10139451). + Check out the [*VEBA* Change Log](CHANGELOG.md) for insight into what is being implemented in the upcoming version. @@ -68,9 +67,9 @@ ___________________________________________________________________ ### Installation and databases -**Current Stable Version:** [`v1.3.0`](https://github.com/jolespin/veba/releases/tag/v1.3.0) +**Current Stable Version:** [`v1.4.0`](https://github.com/jolespin/veba/releases/tag/v1.4.0) -**Current Database Version:** `VDB_v5.2` +**Current Database Version:** `VDB_v6` Please refer to the [*Installation and Database Configuration Guide*](install/README.md) for software installation and database configuration. @@ -85,7 +84,25 @@ ___________________________________________________________________ [*Usage and Resource Requirements Guide*](src/README.md) for parameters and module descriptions [*Walkthrough Guides*](walkthroughs/README.md) for tutorials and workflows on how to get started - + +**Usage Example:** + +Running `preprocess` module. + +1) Available with `v1.4.0+`: + +``` +source activate VEBA +veba --module preprocess --params "{PARAMS}" +``` + +2) Available with `v1.0.0 - v1.4.0+`: + +``` +source activate VEBA-preprocess_env +preprocess.py "{PARAMS}" +``` +

^__^

___________________________________________________________________ @@ -100,8 +117,10 @@ If you wish *VEBA* did something that isn't implemented, please submit a [`[Feat

^__^

+ ___________________________________________________________________ + ### Output structure *VEBA*'s is built on the [*GenoPype*](https://github.com/jolespin/genopype) archituecture which creates a reproducible and easy-to-navigate directory structure. *GenoPype*'s philosophy is to use the same names for all files but to have sample names as subdirectories. This makes it easier to glob files for grepping, concatenating, etc. *NextFlow* support is in the works... diff --git a/SOURCES.xlsx b/SOURCES.xlsx index 33478b55c69b9a6360a93ad3009b00742129bfc2..b0f60d3598d7d5ee2e823d371466cebe5c6642f7 100644 GIT binary patch delta 35189 zcmV(zK<2;K-vZ9=02J2^fD}PvbZgeP3z+LzMU6I8D+tqRi&2 zyGSrX(1F<}0R|d5HA|)15FweD zv?hP@gtxSTl_eK7Q7{xMBwImAAxlbCT_MM|eN+?Hm|F{>IK~EFE?G`fo_95E)Ygcg z6;VK6maLV7wK_k>TusD7*IGHRTQIR;6;n^WQPZgN@O;&9K^7Iby}_Qb5%BZjAKTD4 z!%498?x>pOf=j+sCtwa`L=@IGkG+jDcwv(qK3=7o>;NxxwwLpjFbcXPU8UwA5XIzN**f<&)6^P*knBV5+Pox?(M@SVJXR(*?P2cSCfb zdh$NS{)6sGu7imnnp=;z-)|!ej*EYA(Ds!Q27I5V7jVBfWDU0snksh1;9Otl=)TEC zi0_}HaTdq1H?cC`cB~|JT`Nw4k(H!4@cei(9^vFWI3xTp=cH5RPDtAH)O0~L@0Kpf zW>~>?*sjQhjq!kW%NpY6Zn%J?Xe2#=j}Cv}Zm*@mgPc@3O!i%hZJHEDeT(O z*q*qSosB%p4JM8ixFZmZn>v{{&eAOQv`q9H7yciWzR%=vcsw=Bk_a^yB!7S>_nIza zhzba~cL?|%l8wC}wnsqGo#C0~!mV3z?7Nni&PLuCr%C3`UdU?qmmgfLvjOUNQ=&Sk zLAw0(<50J=-RypHxt-Wa=2Zy@uT$;FZuh?dZ@~MC9tob^9tli7U(PR n0c`@7k( z;OH_=qvP?>^>y^;Jo`EvfqocJ)L*!6dzqp^CTIVXp92*H40{eElRFJFe{9F`922Lc zP0I>njInmtihLZ4=);qgFUJ1+jvbN~auW&`*2mHFo+G`Q-5sxeIn)%KFuZK-qu{4fzf2O%K^h7A#EezW|w{Kq=9pd|n&t_)1~jha}^I92|Zrw((hJn7>leQaI~v6Glj8r<||L zpRy_A;zGKv|0Yb5F$X)@U*H=m{a8xL~`4V_ng|kNNn1S$r8s z$zm~yrpqjeipNPFO^Ym!)B9wR6~#X~pVbm?xUY&hXezo$%0-?hl+9;@gI*=<{kuL1 zw)+N6cmSpP=xjns@6naDn?Cj#wPVD3P#}7@5RShcoZ`PHlg|znDdHX;tokkM(Bc!q z7gR&Tw<`R!`>!C^ZNS+aPoTF@Ss$0+1$r0L8Ktug4{aL?fW{F9O#}b{*AA0G4H=W2 zDhGdGZ<{a_#os6GJ6L`v20}Z1S>XXw)0QZzWXj@Nh{?gssz~B z;&;!%=guCFT9G|iCrw+>XcSTctuU2rHwFFma}_*L;yiCFu1pIBJ%OW-^RHiK2V=Lc z0q_I~tt)8beU~%lL<5?;k?Ekto!VH z0-lW6X=wc!VnK0_`duSCccE!<4^DHt-F1O5x#q%OtP2x%R@R!bKmBbV7 zT@ed)K^IZJjAP2?vmrpQ5)SUeob-8I8?)^iJEwr);|CM0RR60 z00960l$Kj=gD?<9w}Mze!A^p4M35R~BZwmPE3E=b+ue62M9hO&V*aAc)f|7%!xuN> z=P*o{ZtB|R_Vtt9PPxmo@w>Z@@ayRF?APtP{`m2C8ODCNPN%$l^Lg9!D1ArmDfd;L zL12Wx?`>84rnt9F(LY7!7b21rKwZ#)+l&S+F{4vV8BO4J1{`W1y;-2aMFpKTdv>tk z%S9t91<~e8c|vzkOiTn5sCj=kNF$gB0~587Ht@7zuh>tKV21=8R%CO*e4V`BCQP(C z+3P05={GZZrCv7~6R9SL#7;poHZw)z;!br}MydB=rqO@{?XtYSQZ!7Y+8XFYg6T?& zLx7lF8I679Qmw61T$3|_n0eBQE5qUS0y&Ezp_mc1ImmEK_=2-|5{iF`Sk>BhWta{m zr)jYw$GxbE)V9ax;H<)QAW5_skpnT+7*<3XrZG#R#eJOkn#I)|X9E&0U#6yMaUdtm zHfj&TFx*f%fK>DWP8TU0BA>83K1lB)um1v*paT>N zNFBBH(_#Ps*AJ71F6w{71D?B>CciD>6aSZPv$6BjpR?qrKhJ+UjTv#sw4VOFKmX~^ z`}(VYo(IU;F9f zJc%n~j3$$KR(|g=i6-fESpM@}dJ|2uK~$ObB)*MC)oI_v(R_a~i%o)+`DD>#o~Gl< z-{(m*iz<^}WP`M_{ODUhnQoLyKblwmK1flbNqLY#iY^T*62G6JV7Jk@{Pz2&XI?F@h&zY8gCpW&7P+7QM~yfgK?B) z$<0&k_n&eyiMAK=CBZ)V?lx6XxKi>4I^Jss1JHgwz<6U7CnueRn_qW7nNWqj}=a`2kCsx=*}zB-6<>*3ldL$aE09lRbCrmBcaW$Sf}z z5C|}-+syT!_z_pa3y!G6FO&N;OXSU~a%sCy>BE2PM&m`J@$yxp(Qel|8wJxsNPF(= ze$kgS+wLm9ca8Q^R0qvQuhFYl1sza#}>*oYw1mGoZQ3?&pwXbBEve|>HDLL&!0{!3u-pp(f#aoqi6fv>C{@C zUTJ?pS-Wv?*sRr?jat3Ys5ffgmJ9QrcHMkktriNO5E2y7ov?bwa+cmC?AW`D z3pP5M5rUZ5<#~GLPSDB4T$3J~c{beV!TfdiMWg=mRotkvH-`s>skXX}{a@1sW`%zn z8}t)QHoPUDsSSW?u8g~>o1%H%&!hph7W6w}4gnCZRSb(f=LOc1z# zaz__??)?Ibz(vt};`kJNuS>@<44c4<-dcD=eIAMv5?lr^0v4%hK9na%Mc zXS?otgm=l@(XKnYMHj!w$vD>gRUi1rp1fvse01%armE2}y0=A#u!McyrZar4*U?$p zCytq$SySqCB4x!RW%JnrsqyHWSvpzyD_oQJ|B2~D9M3+OA{@F8i?M5VUUz?A#og9H z!Ap0$jqd(EZ~S%7zu;xkYT%{Y-8GqXI-TZ0rz#Uf!9w5R6tn0KSAmcGtM71(L!2zGEFT_i0zbLq?6P`tcyjl1x9JE@nu@eR)j~sn^|G*<>uO|1}=W z-DxzB^osz1jQDENzn!Iv`#pblAZGi6Ngw4AZ2uyR3m?X8EjO~!rSIv_L#lVOYxi>bpqdO>1w^@GFqny+hin=LG@Vlh{v zcF2~Vai?SvCJf6=YK`4KB4det~nV)-e zbaj2S|5x`$zTyHrcfa667Ol)ze4fUp8XfrvcVNLvZld164|iD5GLEmg339Eys_9kH282VN2835a8y zoME?ql;QsZeo6-3Ib?rNAU9C`_S{FMVjn*rogck&AJ5*tb)PYy6r6t;!kS?=FD85g!G9Sk z1X-3|hpcKAyZLAqXMB3N$rhURJj`_z=9|1RGrmI}lFK>q`w(` zDabHO#|!TqiT8iwXjVXM+<-GPPzUUm;jbWmfCH@RNzS4L z%)@dToo)%{ZIaJJy;VSb2d0RH_Bd^tk2ynZ?RHR;FW z3{^d1$jhf}q*0E3VIvZ7Wd6%9PtgbrhX1~fGf;^+@Ns;X#ZU2ryI=yB@xylzn7hQ1 zuP%?ECD<-EjUPS2T1Kg-Lfn&rCUZ9A{vHouww(!+g^dOOjB~4ItM}Z83ffUJ^7OiK z_~PK@tM-4vK@C7vP}bhz{$SGIQ_`|0n6rXoO|R(yv^+yOsCNzy57#r4HWpBYrvfe6 zM&d=u%ElM+-MawMA>mZp_c0~p$4^tgSL*`QBi4l|Rty2**Nd1bXtLl@h?!pm0$6a@ z1k>zFFgWE}545(D3|M{tcD9EDKg4t!jRH{B2Z4XO0I49EUh}Zm2459&w}W=0(cOSu zj~Cep(3d_$f=2~aJ&*2_;liNOn#S!pM7CNeCdh|Va+PSB4Q9#xTrgm{NQ-#1dV^1JIs$?d2{m`fM8BPB-43*9gw{2`7fzskU+7?#e%Ma_Tb z#05N2Ff@rG8DOso3Mu;vp|XWmk?psOiLug-tPNi3kr>x&^?I+~Q(_!6s@ZHGv<}zI zsoNkAMuJr;gvfO=x*MktIB0x4(CGmX11PwRW_OvgEWq_1`jHNq-OZe!pyd)WuR-He z$9%thOCB^~JYW|~-)kQpHU&*Bq>Fzn&tS{>#i(&nIPwjZ_m`)3m58JvZWEJm2;fT zVs%82h6>DM1)F($JA;t6z%M%x$gwmZ4>FH$p8}~7w$3NWJ>^BOTS7R!R;Pc4Z`;6X zblNZ)Y#?y2RtOtCi~ksZ?i>$$_3mM>S9Fe@Zm)CLtrA;b7w+!>{c9zMe+T{*q=9RI zgwNbDa=Vg@Fj&E!=o{>mPaYSzLZbrm>`^3JI+XiUc8K^$nTN>(ZWaT6R*IhT5pnYE zp47@DSDQrNl1ZL;FSF9J%0quuS*G;5`KnoDwxsXPdi$`}B%`i1`DevtHCmnadLGnn zG|7yry8iAdnv?16qVMSRTchqs4+lx=E=juKF^BF#f5jmvlYE0H-$e_U0e6lCpo2!@ zzY+k>d0cP%5)b6hQb#Pf__PR-@%NBZB=guM6n5qblv2o=p5Ywo79)RqDA*}4lIT^7lplGHQs4JsLkWSXu6Dh0-7xYng=ih2Wx*+lW1>|p}lVK`Cak? zplBcnh!&^uzzKkcD9~!P4?F8{vj+@o)~mW;DYMKVMi9BA3{Ic`5(#_@yBNBf& z;)Q_H+JncgAMAe}v>MGi)czj@l=b(Ql|c#JZ~wk3^rV$C*I9O-Ow;d?`+yrbUEIUb zyAvuIznmSD8AooC4q-cHRE&qUd0OKiayuEdl$~W~32|fTEkOdIaD@Hjs300YiI74| z3SMN_K@ZQ;6)^DcUQ?M$xO$GRgoY6H(rCVJwhTE`+(&=bXp&B&M)2zG!)~j#3^uKf zutWQx7;Fv?4%)p|HAgWoiedd@loED=SLNTg3*iN;y_K`+XgsbZ(;8$C81?G!4Gn&f6J7(&twh#`GD-}PS zC(cKo-mk6mu>P?Ou1SV7(vOEY!i#^$=TX?70V-70PZ)GQ`(f_38q2^f@sEk}K~ z0Ovu0&%Zm+rX|wul$84I_33f#`p!Mz949eO_KBztjWopYOZ5liU!(^fF}iXfD7*BCD{Dcd3(|(CFDu0{^pSXU z((*?G&f}DJ0a~L#gGVR_BASiU``Tst2)*cNoDjY6HU16<^%mh=04pbOE~;r-zJI-k zO3ah1i=(S|uCrHv<&p^w@*$Jgdz?Q5%8)D^chjb{6|cTvBkS8|td*zHk>S!*w7b~e^# zzKAqI@ke9G1JJHQBp?ZN^ky+K*?dqQzL=^C2O;*xx~`1PHg@i=rUZY~S6ozA^Z?Um zj!%+=hlaWP2wcW0*(egYp0Zr$mhcs-+;)f*h@ex>FLQ3GA&k*$)e1~)r>8E9HKz7} zpxUd}7KT(=DjjUmMAQnsE!8Hg-x9L!$_GxsjL`^{IYyorgNp?m9c5d7`9cc@#RwIC zrE4VXAJWm(x^Ju)JeGgwxFXn|9-SUxaE9Y3P32V_S_Tz^mO;b=?DymGg7_1;e5Qf& zEw?CjjN$>Ifl3d0jaqASBMv;x%F}i{wZmKU3TLy?uD82IX|@mPVA;fbr{gD5qbNhJD`h+CPh%V+&iZIvdkg+hztw+Ry+EaklojQ|;Eu)< zcP2HREhdXwsx_*fW>csM$PW={iE#ZfRm16b_kl+rCv*I|0v#5AJd1yw!ifm~9bRNozbKK>1qn zn{@HpB4K!*{x)K~1eg6mCDNqd7hQJcf7TGEK%KYg^gC@$%v(QO%~_&&OI=Yq$8O;F z&{Z`fc>S}Vn6&jWEas2|BY8s2?j661!`Hr0I3{U;0nvYtvkAEeB{@d^kci9U$seP5 zB(SZ<7wZ=J$U{EHF`ZT?Nadu{x0CHd9mE$5ezDWi{1} zKazfBnz?%Tm^^^>E$=x8nCg!V#L(vno(m**4j}V{Dw=Sfephji&~ql1 z%UMj!HqP&IwjgCg`>?MlL;l)~bM?W2yNFvn=nH?PG!1ug<(gA~uKAz2VSCkJtdIPH5q=A2iqP2FwM!m-Sn2M=KQpnmzp*jnSM;{Uh`o>Alu^WUpY37Uq25{>YwvRTmaX zqAc#6l1BZG^!V{_3-^zIz!p$}7M;u5}q&@+}@N{)TyFdY6CaQ>>H{K(nvbg?_}pzJGr~hPn|&TeFT5 zN|L|cL9^C7DCP}C7Oo)*rG6;rSj;FDDN4xP>Vq1S@?fKWxJoD+Ey(J1ZlC@SdR(g6 z`m(?GcUz5@?|QC_IBz!H5P*e2zHRvXgbY=+@oLBxFQyECfo+w6;s5;~|GoUDoWOs* zB^oXId*HVH$44^UeXAp0Joom@SYa&WHr^ww?V}9p*~<3&eWtcwY4C>Fo<^0v@2eP` zIfa4*VD|l6Tz&7*y>hf-Btth#`e{Z1WUN}Rh^atY?=5-f!nEg^A8kL3RGtH*U6{i{M|J***QMG`&t35%h zs-97K`{`$^9Et_MT=an|2**ydxCeOKvIH;QU+1rvUxJE`kFQQ0Lu@(>qX&P{lcKVX zDwSJ4@93U7LA;z2TT*`P^9#Ud`U6F-0$=}N)h?ZmE2j;#wr39dU~80)P!itrYLj9P zCU@EX>Cx4{t7mV&KTi7`JW}l657OG3f2$l%**t1LnfDiiyLfJ8TS~FkaWIbh`*u3z zVLzJ<^1;vFpPYTVI@>h(dGvqi8NFrC0uItE^m){$AjxVUNZ&~M@*Ul{GF&R`V5)Ux z`^U%hUv9g+|Ew8A_XA%;+P9oM8s-y7ru#tv6)paw{ZcD75F^Tv#lD@MT3gjK!~ULD zZO~kaxK+b_P|K|3?^ma_R_(-ItDPTzI$sI@c?D2<$)Tt<4FCX*H|>AFf4G0Zb84*~ zTMT~x>>JSLxi@LiN5WI-Gj?5G8eK27FX!%oLw==~bdc{AZBzpe_~Ges6%X;wPj18i z?4fVooPGK1-kyCr`*L*dE`L5|TioWY*?wdm_Dk>@tzFkRw7#5)IvzMK*xhczBur0G zaih6=aq`kWr#juLfa-t9Z=lFzZk$}14))x?jpwh!@x`0$#w`2aZs)JJd)%2iClo7s z+~11*pck1pO;dWW$tNG42jCl`oR&Dl~@q_KafkeYvF1g#K*S|y@!3>FW5 zSd30tVY8g_7MLZiK^JI_gt|g3kMw6{;9YT_Y91Iv8B(9780EKsNJy_{dBj0VN=>mt zZAeQ-5!^+oNyY0>WT6Qn)-wQCdJGIR_5jZsrn9YZC6ll^U#^(w;LwIe-P_p=*5Fs= zDD^MbQeFYtMY4Ym9sWq6=LsZe@*HwHK~0>Hi{aRmR71VTu^)5KxnrHInkv_u@0Lf^ zIGe!%JI0X8F+jtn+_wve3x1EwkFRWBc{ZXX0y3~Yj6`nh#88duF_j*crA?DMQ)Yu* z7mrsx^SG3toik!g^(U$=CEIpqzN+L7@I-sSq3pCCv)q4~UA?4L&tMZ~*4)JO^cKXt zD>Eyv^j^g+MEv;=#8_0&)pE(1=aOZ4)KNrAoN{Z(_$|H72R|mb=aLLvrGs9IcBNLuSdzwqcuZ;5% z2m@^^OF_G25g^YE9!KIdZ`q~HBrq1v@X?2Iiw1x9;fJ%E%h*#M6j|=G5p-{GK6Y(3 z+Y0XppNKP|+Vtf5Bo#MoBbzzIV5~bzambtGpO)H-^OvB@lkwGz*mnnT23yXCj|0)C zRDjp~h2$1A0@_2NF|H&Fxe7n3Tgh%6&^(Bj%vX)g4^aYShY^wU@G)gr(1gk{c+M%L zoNj+qZzBdy!?D85Qgh0#!`#LQB1_FroCK+!^4H}Gkh8bE%28LX2)w2GugW>A=)|+$ z5ycF)4qK&K`z1D>D+Iuhk9*9ru=p_@oXL0y|wq z3@jfm9R7GjW8DNdMnh>z8-U3e@0x#9?1ScQW88IEdpS?=3!=|AHf(sFNM2G9P-+o= zA4Qchy+O*k*-4{k$8kPV<*tH{89gO`K@L`pbj3X9N6Z%=KS&h)Nx*zxl>(FX9(&ZS z&}$8c%YdjbxxqnsZ4BofZ&GDa|56@xefEXg$kC@$cfw)+_t)<~f4VBE;&Xp_8NGU^ z1XbTcy)~rSxmK{akS|turdI0k2_t_2qTvvKtT@c1cff8tylW?XfQyqhX`R#;IIP}C1?Rr- zPkyKXgp5O11uz^H*m~L5soU}Rj)z(b7!E(+R4xD?wG4CzH58*yJKY|=AglMf@ouKi>+9#uglQJ zsQ|kaV>JVtKzX(yEeP-4+5xi7g!21{YHM8GX;LHf-0~t%cYw5HhQt<+vC6Y3?%!j& zpe$)=sC< z&tYgWERZbcn0J{-Yz9Lfhx+VJo$yLN?5ZyH=LOra8#$~uOa6c2kyeEt*>@b`L;O_Q zbh$NgWTBycDFbu9zArmGy|VS#zNVHlF-RcKr99K1^he-tS#Qocw8%0&6wCS;tN2Z* z#kMSDCSLpCQC9Uj1FhN~K(i+@{pwU^-7;hzX``2wa6cvcgB{Odi|@zL6JGg9?Zs$| zl;zx#=TEw(3h#eho_WBKRz>%AUc2iw+>E-9tiuyrc?wo)h1z zVEg{2vUH-OV@>_p$Ue$*-@?Lm+I4XRF5jVOL^0r7V zNsJZ;rF!s_`G`NHG*|xCmh+^~5n*iDuoANKVRi+3Lx^0Wg@E3w78k&rnKLm9OhsEa ztF$S;h+fKlhrzgK!duN$*8*9~t~8_?cLsNnRk7%Lj($Zmb-fl+%d1>Ij|^d9g-~@x zp5A|69*n>KDnnVB6?0@5h|96ZHgsoJl-Nwv zPrZtFmmdumZxyJYz^&v|i9v@IJtM=$JdetYu1wKHFAqh<2X_u^vAhh*#YC(mg{E>f z(d5D|5BY+NrMOW_!J5l+9-Y4c$UAKEymWsm#@h2op$6wdZ4Ev4Z>|gpXNwo%gH&IP z$CmKRx(L;Thc>vZ$#MUN)eKa7s_2fj!L7<%{$sd?mG|;4gy0~|XqLv-@d*6-4_VTQ zwH~6Eb`OGg;%j~wi5DMhE;tB%T)CjMOuJ2~Ersfuwdl;PuMbBxW&=!(t=3gE+)aNG z_NA>%gBPb_r4usq72PlM6+I~=BOl{0{*e1Gk7^Y|`t4z4F_#r!UE`;@$R`CKfK+nZ zH@(nP{#4OR?s- z(qj%B%d>^|z)Dw2%sJ#D8nbvi-sf9U1FIc)H>R8GoUUJi51Bu5w$ATYd7^*C8LoN+ zv{6=D%w7AB82YANgy=*ZMfF~0)p_Y~R?%~nCb=jhn6r!gZ4#kV!Lu($7p%>8?dj#! zdZ+U*FUCAc*heL%>(NC4d=p&ZbcpAKwtYU`#K#nF2K1L>amER4&0ZZ*J@h432X{gQ zEAny6oaW8hm2q8-PTV;|0MMi~8ckP%a<<*%D zYzZV;psBR8Ic;U7#}!xXp^>ksQUuq)zOZwuUdj#+Vobzk+g*~hW4>ltx%XDG-?%W%6GdM^5j7pp*&SB#n*F6Jb+S)B{O8KwT_8H z=J*qV9#s0xDvv4moky0XJ1{-fENQ@Bmb1ltt;(J2>QEjvh>3qA+)xhCt?YSGiU3{P z`o7M*-|U8}g8j+!sT;nez}k1zsFi~KL;d1NPT0gykd;p|U=Lj2;7mc7xA=nlTxiLDuS(B?tM^|lZBr1qVH(+0Z{ z45JX~G+l!7mI~Hm5MwQ5HH1h24>-)>k#@YGCTV0{2Yk-F7y}~y7>u(?6Y7i1I?xo}6 zq79v%p`LAp!d%O3Lefh0(6Uf<$gGJK=O9%1%z}Tc8&FOoIN9}3w(C3PBK5^dr$fV) z9aLBgg;W}8O3i&CIrwb z#p(@NnTfjBsu`Z1U(`4ciG0O}Z=&F&p)K1wKuwuhv>}*0-Diud8@g6YFEEiRbU;EF z8Nr`pUHZ;lu(}TDRt=x#+AL;NGe_$$vF)(x4-9`SB%kqbF^1^(C5U0UF%^xegc^V0 zlsBE_#%yb?T%)k^d%xrz-qgf(-oEsx=W6|>5RdH_`^0lI3xM@cWL^ct?x96_O?ll$ z9hqvTLu+vz$%5w9O<{P-El-0*y2u1os~u~FvIK7kohmZySmkeH>;Is5QEsRI=}z}e zqfvjV`pUf#n^l1kGaFjO^z8|SW(LbxSw}UfPir}DRYmsmK z)t*~dvPcvvZT@GWmDR2pq*(dAO2#fAqL+V#m904y2X#*?B()W)qj_Bkjmj^d@R{XJ zymeuNdlXjYvpjVbDkPYb8e0FOb`;9}%Uik&GBr@E-^<01@}{vidQPk%-N4q`7=hh3 zqEC^iV3xTTu9U%+pf*P+?M)^b8foabmT`Ek1Ea3M(5o$7i*qpY*P)riV^r=kpl5%V zg@y9gM$@xh51oozKT6(4DuV_1lDs;_ICl*$R`cxE<3QN|2c~RCV77k7vWaa&ywnI3sL~c$gJ6la~n>e?VYb=JTI_#yWrdRNQ~x zf#qR@CuBH!&JhX#Fm`55k*Eg7{9T7Y2R1xe2Fs{b0M+yZB{Z*Jf7cc z3m>|5!GGOjwI1WULPJ$Glx6%W3fK#di|FuJxb#Ao)dak@mfe&?yuAJTfJ~b!T=VJ+ zDxOy^d{RL=5c1(KquS&}>4Ik4${Sw{1!zSfM_);fRAa%^7ca-3GC z8E)MMi+EKk3Ri2;8Mxv}lAIR})vNM&c_q|ma&q(GEC!QX%cPbvR3+B-k`%-;vGS07 zu>x!j!Zhq&Y-0__8a?fUr{d(Tc*d2FU#UfTP)lEycaFn?CRLYH78*PCwzXY+wj_ilvtCzRcLe|UrhT@@> zz^Rt*S=-i#DFLQw*zF}+6JpjCMXUj~Dxn|;4{>_h3ThZB{%KRZX{{Q_JlB6YZe0z)!j>%S@^8mMstM0}KmwpFDNO@vyJHG);}$HcGKC zq}0BEiR=7P%_V=8P?rwQ&r=U8SRJr*en70y6B9bs?R@I?y0z@fxYEZTM7Di3YJzFshZ2ykMU*|c3}&1*$o|+o<{irSk0ZL*8UgjK#=1ZcNh8o zci*I%o4UBQVtY#EG}rS=y{d>Uc?ffkI#nFPI_hCe-M@eCtW@IA(XX`whUhIM6Rt&f zQf;qMFGDm1nlHac!#A7f*sbXD4KWtUvu!V@aBj`)Wh;3}Q#fIhGXH4KnIBjd`=|C) ze+`GPtEU5f>7uTz@&v28Xw~#0?p}X0+GJ~?Sr=o-l$M#1!JUGEd&<+AoR_|CNr-Nr z2Uz>j0=j?Gm(x1^AIiU;2^#=*V-t-e@&|y8T+=tr=>Cok?H0e2wvP4X8!u=B;S0Hi ztUU+mHBqtJjzZkvXjfeX1)KPn%^{G0zB>kWH2c_E?l%j*ZjdPl zdveChEc3BI7pbE;XO#cbth+#tlvGNv-De(tMU{U-((kz^8v4r`DkCX*5r0B@i#EFF z9~Dl}S?aYq`WnuazwrI39<_<$v>ww{8R_Ze);r`+IQ!5|Np9JoVop|yy=sXlAaPHo ztL~AM6TIJ%p55`i>=vNSk_i4rdb@>U zdnXq!16WzT{g*!J3xD;+DEikQb_$(vE2Y?aNm3sF9oeC+LW6RKz;E}4mfzp&C464p zLPEP%vIWBQxzb->WrrvAd!q%1=G?qj{l|ZtoOf=a%Ya7CWsuqW@+w_IBI3vrCdyKQ zP$+E$ty$K)T&&OFe5^|cR==DDFY7!TA+FKiYaPr)@1M`J29iq z6Z^6$jzjMVZ4}|W<7g^ZU+KE^fTedN0bLpsy3wmuR628R?N$ZdhGSQ2ibsrR^l^U_ z4qxaHM=`C;-wZaUkr)_Lp(SPzpk$%??%TX6&3E=2FwGC9F0VLHr?TFv5Wc#0WkZLQ zRSJL$Ix(pef?|~HnozZNOHVNh3!rw6OQ**D&0}TBRAxL(7yUWyF#g64^-cTU8@na_ z!55Wpq6d+CH@;~CJ}>lv7mos!C6Rw;HA}o^N0JIhheW9Dx*dN~CJ1@$w0e2O`4csJ zcn)iq);HPZmugsKvYSyg$M9gf9M_z<6i~JHMWweh*nMegMrQ^#9gqX)SsmXfy|p}1 zO8k5?m|v3LeE&6g2G-0D)tBOZ3R3VGAWT~)U7pE@e=__~-q6xAb2ZR%^DTc6^)7E? zU&&EzmRjL*wNCK;sk9z>G3)5t@_EdZ#n8&DnvC(o`U{T_rw}XKCI77BM*_HZUmayp zW$xM}5t+H%t>Cp=Ad>{v{GGNtG$R`#!UWxmKTtLQ&M8pLo= zS{x1QBfi=3yC3^5e)7BLD?oof5c!t^9<_+A4xSCo4?^Mom{0X;nQ#+anFBRFUYou= zb49x<_qRxr;=-Rz>g*d1ayeN|ygX>O(8)r(<)(;0q(vwI4Jr%NHNS`0hed<8%On3D zm6eCJTW3&PtVg-B?ifT{)FLSMPcBcz9pA3)&wW^LB$oqix~Ful!AgHh-Pb7z-Ji8B zd;!iEo8H!sFO|>h=FwT-S*Pv~Cb+SWuXr7!{J3;mpNXtrGLKrTqbddJLSJd5(=Qe0 z87`%WJc800BsVNinGj%~%R~<$R?^E{L>#Vk;8v@v}he5?w zEi3FfQ%&izzxpiqi<1szHGjsIWSwVe#gt=?l;w>V6L_(cr{YRTbiHL*9^KM4nBc)7xVyVM z!8N!O+}&LocbDMq?(Xgo+#$HT`|zCe&dhh-IrDG#b@i^hx@zs!eebTWC20OuduUjR zLoN0iH(|;Of&@!&uXu>j3j@Id`XUh{_FHN~GH%q;#i(2Mm}Hc9IXu7K-q#Ol{SnZ} zz@uVqp-^U<^6P{UmS(5kt{Df`jnwBEVqmlo;MvW~CC0RQe_8z?qvv_9G*SQC)(`wl$sf*Wr%5c%Lflm08-1Gx&3`k-rVEpjbTP@W zRDmNWBttZ&rkhfBGxDlf?n^TA+1V0CUi%|QgC5UjnIal`$605~yP~cgk{XN1&icnE7u#!3dk}c;DN{$S*&!18}3&6&@r|$?q~BI@IF3jB$W) zp^5?hOFM=2`T*rSr<(G8ua*Jht5y`bCRi*Lj|QK9DARgG+=)vI`xeuxN2~z4h&TZ`xXV8kSdLUB758Il&Vw1I%RjRvSl+dTxl zlq*vR?FBLtZpY!V!Az!Q96m~{ex!CyP(^jze9>?JgQ--A<%P+P-P&^p~7lF1@wjj zCA!c{Q=rTw$28mWD&Snb^Le}&PZBKw4!UQoT#IY$TFl_12{(v}yHU=!AuW(2gKwrs zqdFL;OX7Taq0?=G3*Ub5(o)N&)1dEHK|L4j;=B~8_sv44_U|_|8YST1Yq{TFmi!62 z>8_tHI!xBvJ4$9}ydz6)eq;AD#-v|r3mqMJoVd-0iua#${e8hkAY334u6-Z+)zm}BB{ICQ z=JZyC5SCcYE*g!Cftwe=O^b2P*|SSPiBSO=zgp#aVj4=wFgyQ-XRo41ccfb^?F~*; zRQCI4Y-x{^-GG9bXy?mtc~8NBaLE+~IhAg^`WE3I4WZwSs!`3J1M35#q7!=J9yYlS zs2C#~EaiTN!yrfncp7$Sb)=V24umqNNW?lJC8y63F)AIn9E)gvmbJu z*xl%(G|4-smXlKGMC&WOJLV4M0EK>@*Gq%hsn}wcxlKLhUL?jA{&iQ3#!_-!Q}hcA z3&&*rNT%|dscSt%Glp}3BQ>eC%Gmyq8-jj#0){;VSH=whRsJRa^_mw9g6G*iQdFx2 zR%f{$yao<`kMbcBXz2MjpWU}}W%KA*CPrij#02ag2;ifVB$NG+pBNzA=TJjnZ&)OpS} z-IA#9lk+1|$vPaxh2iF+fMM5m}ZoOmVOG?ix42K+tMtKJul7SG&9 z`xx4Qvp&=$G(@<0MKi%^j+u`~DslUf|D3ghp`o*Z0swYNb~8M&~Fq?Saa7xPYhqdvR1py2Em18 zpH{9Y)c)iCB8YD)m7*A6R#up9L20*A@yk}Yz%Wjko^^$AwVCDY(SSy^!SXWcl?`d` zG7OfW|5x0-pezkON)uVo0nz2B_?J#nTOnI{KTnxg5w$xqEs$=_as*llRQ3=eC_2a; zxw^Ury%fg!vQ=EE0-Dw36ws2yGrCB8-y>m>flFUDcI;%tSln64I;1ceZZE^6@Is#e z;0-L@NRZy%aikXfNAGqiGw!O2YhLJi_PqLO&?=vChjLCy5-f&GY z;{-Q+S6Ybz=-Lek>@Q)xb4JmAm_M-y<`FRjDT?t-5UmR&A(QEJ;8I_W=25sq+tmG?u_1<3|8X>d7fA->8k!ifnS1HXS6t8bZQE?nZ_MeB-o5s60K>FYhJbZYaw zV+`mm{jxS0M@@tn#o9%dFLQ)S<{_AcOfBcbAxxXQMcky!fNA8BfDSjBMLLgc4rLT7 z-i~ETd1}t*^e)cr%j*KMo0l7wb4c-sN@Ws^7t|?`G%b;$Zk($^OHzuCZri((0&+wL zOdMk=BOtPPM_;{jp>>amb#`>0w{yW^O&RSd7$l$4lAvg;S?3)>eo=8LvhZ+-*%gN< zPW2TzuvsQ@)cy^}rop(CmznhconFUmGe%LFBKtFy*+592W>V@ygn_9U)y^>4C^Ofb ziBnT!S{-bRdOn-XF8zIbmT@Np47fPjgQ_#izmdYtv{p*#NG%ea?2v;umXpv6-D=+| z1`4*AOQfsD)9Ub=c|`4)Sou7((ALnFt3@<8w;LPWLaO}MSZwAC^25b1RswH{#YVI@ z5S?2H+%R6g?AwXzX@(2pv7oAB43qh`E}^jqo3|B9_+5E;zxztk$;BQ70FbBxbP7ID zrM8}15Z@79cBk*E5}{B{K^TFj#~_Vpd=V5(oAw_xoC5iwkPsHDv!D3X`tu~x^mQ$} z!1D&|+kQORDV-~6dygMXGQm)E!w?T6TtoNJcWYjgXmkOh5e2t}UpyYi4mr#N+|lvy zc6b1t&(EaB>Mc))V)QUC2TclH?(X8u*v2r87DbgoD>#4WxPqpG30l*OkocDKeyEjt zABJ|qQp;b+*pyD=5w-gQ%H5y^1-4&#RV5{;MopZydQgWW3$k{EQ4G_zjSAuI-M}7- zpL%ZK#zleboul5SnTng+dE#7eG9P2@&Uv6iBkSI8ETc^(LN5#{vivEl?D5nfR$>Q= zb$RY)dm(3^2zOL>ba_lU0|nXPiAFx;@P+gnndQ@)!=-g0sMp^D4_HR9vt)31BD9}_ zo;Rv?^UHy2-r{|lPopNcn3cDx_+rOxO~z$zLEcNrt0b}FYqmLcp9Q2T7h5En{rx~` zR1!K_sy!c;EUBvcu$R#=#7evJDH!7SCj_c$l~wseQ>rvC-=kjwYOk9N_h)E^Tll9O z?*hUs0TRU=)gcoxZlKWt`>>Vsqd5v4F$V0+#C=xKTTk0tu1bWhEX=%~(_T=YZ`kdN zy=hK7A0CY(tWnXOW>XgB;`k=f#tH#Jw5`#fE8p%b@J#SE?;Pu9Yp|tOEKG^_Nnd|v{jV$U#=eeMII@m9z6~@qD!PuA588s{i)imUS_hpJp+ zl5w7&G zZ_U12sJhn4ZC}5)80L{2cBoh|&bGapBw^|!OYLj@;hc`HG81QpGk%ZO&J@uLS?)!T z%z)FA|5~l7VL4a;TiE8N#Yn3}k}OuD=spP5X9I=tCx4BY{-hEL!iG5BNLv#}#_28R z-5}z*R+9>ae&SiJHVarCR1~*^ksJIq#pBvyc?s)PX2_5BP*NY>X;{z51-?snayTWh zlIBrX5--sitLt065r(mQbLG$^n6hCL1c;!rph=S4-;D zjhOpu0^UK^z9LrPu4levwL@oa6f#xY>mJwQl>u3TjP{&7?oI_t{#IY?q;~k~jCn%@ z<8Q7(6KH}_Y~Yba2Cz%l<7Z*~Wpj!jdAto6=EeD&Kn{kJlMf={iWrGv*tB0R`rz$) z5G^S21tjJti-EV@6sC#P@gl!bmX{N}AD2|()%o(BoE~>k&NT*Pm;-PN@p|`0ld$kt zma7#62$8Tx1UZ7RX*^I>N)aeRKXe=>ar$D1XinC?>h<6k&lYtSO!! zrTdvhG`|9$=pm@` z?}EJ?t>{CqqW+ke8YWt;m|sbRNmOSzbk;P%jxl9EsO9S3zH2noew$-f6m*zeBfKFu zf9G{`>NkOQHu^Lvsi{ap+WK;&biq}+p;nXKo*DPB6i1{lUmy;CXF)>w6g13w=go_! zp6x!8a8@;FH0;#TkDNO*8J_u#LjN}JdXw5#qu*Z zd6ACBM8{j*cIgXw@SSK`#$411{c>7GeENch$%Lq8+v{36`!%;r=KMRZ(%>oF{5wf={*Bm=^rgbb^|+ZKBQ~)6}u*$>YqEtGq$7 zbXW1@Hh(>4eefAaB)-mqbrt`+HhcOsKi~X}6DLK~b+L2%?4LXbF^ylC5Qrsl^yFEF zgg@$pHmD8065A7(usdUOn@mhaqI$&_HSz4~rbuf*7`0`JgPwSd(RvR8+?>%bL&0=~^nM>~al-dtPkd) zKXoWwh3ix)14Ma<+tyDs^vD1zFuiG1UYh)P@Vf4d}VH;%iJ#Ut}pefOkZu;=nfAF zGrjkbBl>{!*KvIW5{tv}poLKb@hh_Y-MR+m-SHOEP<1OW7RhB; zNPb+n-qTR>@h&3;xhvookAX5QNW7kS=MLBN>uxheAKH#wKdaf#IN;kcd;&S00EV)a zCz|(1ZdA7c&h{nN*d!ZtagA#7$J-WfWzd@TWWw6_oq~akT4JF1wFl_Xe5B=Y79Mpv zEr=+ldap*2ldw3nHr3Hd8K(3(IN$i#}|k zCyt9L0PCS(&Cy6ak4U}XSl~|eSs(2bwKAdD{V^$cfozz}u%bceto&z$WBw;57*yV4 zkPLH+16m%YOXp-xq&C2*HEvE(PvISOEj%u}XkgzBA&OAQ6hL{kmSYdo#!1=OB!_$q zV&NRoKuco_YTby%-A=9;f{YcXY_GKReV{If^Z~PJq}OE^vc#eZqmJ!&B-IyvUidea zo<3C(o8PF>64y=dyB+Y;nZ2$19T>A55+$_AP|*j0apCe+Qg1-Nauc!N@?)5sbj@?q zi3C!U?o~lIY=$ixGun73co29fU z5lVs%o@S9_(84{n;TXst2Pfo-ed}v^Jba$42;#<8@g)d^^W5VmQaf^?v=^yWCdvB4;^^}(Ec^Iu(Na*)&}l4M?Mo?| zVm}S8GFX&mx*CjAwREuzx_cDp`^5@7_Wqk+_85Y_C4S3fYM0bltEJa+F3 z9xpq{q1D4+_XoS>1oW%Px5eqc5=j5~D$+{@t;Z9TN>v+FKMr@Dg2u^f<4UO%9sBY{ zFx#!T+eil zRYfykYO(U7&RKwbdLUU_r=hvm)%TUck6OYa@yq-sm&?ONd^A-@Z!^RM;%GSuzUq`p zJh4s-nyNSCH>Zxn<0JVl5<^Vo(#Y1iy=Y}>{9sim=P5u!`^4)av(^Nb8q}?UmGvcn zQdWonPBs24FT=1cn3p`CVr^>7uC}u?PN@tSxw&g_^6^2QHjKb%$GVpWo5|3ruZ~ZQs8U{F+vwCNvqaPB6rF}wFC0T@bMkVkc+4n+30QEyn)L!(&Z=DtEzwZt zt2k#*z{Gcs_bRP^YKF6&{yBs3#f3Yw82zSx^~G&gYO;v>)i_D;)a-ho(`{v*^ko?M z5^zO(#i4!%T#|Z=3u=65OH|T1n-87jG6*SwC9=k4nY(!f6LvGTo<`6Gu_LIa>gd#f z$PoVc$j4z3J5Stobzi=?9%W@hH;BtKI31B1H21tu*{ah1&enJ5UUfcR+FJ*s599&wv$Mf50h8P7=ld;Xr!sMNSMFts?@zTibtq{z zx2y)7CDDa%lVQ-%9_yny7)H^5ns=={p5qmZ5vsUfcbF5QB#rQx#5$P$yqY8guagYB zxH0aU%RXC?;EBkEK&{Cm7Sw~CA6*=Z+BfAfExS-&U~zRl`v)FISGpx+rda^7nNCpm zWSobvg?@OxE?fHKW?nZxQB$vn(uPb|T8b+>sIKg8uu5*+SeJ?YzmA$ea5p9Sj)QJI zs>GCR587x6AMh!)AKUs{czHkDam}F*7?HC-PQNBHv6;ie;gP<%zywE({pwRS%SJm?aUj_?M|1A3#ctYjbb1*LwFn{D2S`fs^R{)yWDjWsllim)BU z0{Pm`*U=3bbaO_#!YYPTr=&BN(S5Rc4F9X3}Zf@N>jk#s?_C-|<;2Xq)QV zH0jF=wW!=nvV3%V6~;MkWxw4Qyi0sewjRNn;<+0xeF$Z!7c-Yk#@p<-vl^2U7yIn! zIqTKjFq>%+LQvLOh>l_)z@J2&t$(Wp2Nj%HxixTQx={D+>+40z{ zCa>j{v`?B6OB%*KwrNJou)*D(o;t!kvpF1_+}$T!)?poaH~VAZ)YVCC%4g>0)Q9{k zKLDj4c7X(d(bJQ;SQrt_`~RW7q6d8l%fgkL0i{Km_G6eVV4t`s zXnHwOv8N=4 zctKD%-`d@mu=74UWZH`92(drTOcX!-nSMGP2>~8k_f$jS%ak%>i%#GkO)56usFy`G z?MVrUs~#p%K<;H!3!%~l(3#OBHZnodcz)g|OXlem_UH}C+)ccxP25+r*6BmQg>LslXa68T@OS!6s+;O(0fnz%(h0k$>6>X`Pvj4_AO22 zk{+D5sWByNHquGm{x0%vQyjKw*WJQ`RNZ~C?JyCjHbyE?)A=Q^toF8b3%T~^sK>(n z2z2}V?O(DX7FpdM<*350_Y1_PzVTW*_BPSkyz`P&u{d6&XKv1@Z!4hQ{y~uz%j9v) z{uZ9CUl-W;%ltW95^K_mw#=WY}-f!5I`U-i!;pR9yBD%xPpMfsFr4tFnZ8_LodLL@%Na<6r z?>%uV;4)xx`mBP-8S(}5FLXO+F}WOX_bxraywY)Bo6bkRoD5$2X|zeP90cO=Udi@0Hg>8i0%8*?mxg){z7#SDCxm@(i zdrYcq=0{?259MHJRD+!e&uy63y^R>4rQ8=DZ)3+0WZ?CvD|UC~o2SbtT=W!xbvnXd z_?<(aloP-7;GOGfsV}ByQuv zjZ%?f9J3F-ns?OZxeo&?cu2|YRkzB*K7My+-w@4jW2B> z@hg2o5zm&rJx5MyiWkS8&~2E!;1WVjs)1VjTPjm^8t+_NI~&alK_M=jjoYf#TwT5W z1AU#C2ynwGP3k}#Ok>NtD~lp$l-3<)Rp<-BvD4Q@7ZgPJmpu(;lqWj>r?^SK@v-Gv z`QkmPHf-(Rodh)Qb7qL)0XR_r)V@~+oZfJFIvM?1tjfPNZgnzr&NnYuo&ShtZ|4iJ z=v!B1*3rI2JbW&lr?sOm*l>S|7fDI?x0r91+NY$?$j1W}zXzUtgN4;?F$f|7J%4aY z;Gp({;qT}7r8LQ-XkJ74II;fT^iM+c3h0`yu3rM}-ttzNQ61*ebUogIZ#z0c6d>>z zI(rOy_c|Z=I)IoLpPa9VhL9SL0CZpVU_Xww%P6(%MN9!FJYvSfcSQjw7~ z>ksWvK`Y2h!*efLH7D{4tv;lXK~prw*&rU8*cJ#2mi)+Pr${ibVy{_qZ}GZ|GqaS0a2bD&7st!%$`wc0HdY>W z{+E~Z_!qy=_X1v^d8Z$MNZ-6wfnVUx7ctjBVt=UCHkk$>maA+a+&}hf@SA zl*a{4?T{Sxa1ZzCrY9hBTiH`NgS|L!H#qw81a<1{jDeQ?3-GmoRYbJxyVLyHnugMb zlq0=C+E2cyQ_-OgxB*WSfJ?)(F>$!TMxD3&-8Or|>NnsdQfE?U%joJ4L=w9GmE=Js z%KiG;eO0BNjag`(GRfO8Qa%68L&w%%^4%wOvk+;DZ^9Jx+1|psve6o@vWNYOLUQ$J zd`gbTgQXIa3Gt_I^@|erf~7{r-LV z!KLp!F!a9%D-;f zpi4}CQ<>s2?D(z$e z^W)I1)_CXVosr>&M?#PJ<2?^q23%CaAzZtD25p3of^a>eDvQ5Af04oLA(SR2YCZ|q zqSq<#{n5#!EyZB;N1ydIj_4k~CEi(3Y<3$zcCtiI`j`Uflm0NJGYcM6l>JWEH1+DQ z8@0=w>7k7kcS>ZQ&Vg)73X$&vpshy`ex0Ufuyw{i)heX!E*2$tf>ibfCTXPM8YW&84)A@GLHS2tZ zB;|&kzZp9Qip~U1W+f-jxhS8#})FAV*{WR9W>F ztT6hpQw^|_6c{`qwsq$~SoIXiZh@k*`pz_iC zE5kePW^vu;DY1Mj;@Gp;HZ%lK#NDJLlTMb>MT_}5v~U}M14i_{0M3h@2?LK26LaY7 z%NDPhu-TyQ%U02SkveM~j+H#6eIx}bTs6nB_}qe9uum%F4r+E+vSTHicTxsL;NP>C zg76=|T`;|u&b2m(GIsOJQ!y7iFkNE!Rw)fAblPD|I*2pFh%28)xA_4;{p}B}z7Q3< z3*CMk#Y$PVc!T+dY9jy7#&TNX6^Xv84ll)uS7p!D6A8`)UiB;`>0MP%f6|QolnR5> zDpyDqnl$Q5SLEZPyT!;ul18QKcU4AIRE2fd8~45WveEq@*nvCrvb*?w?lN4pBIoX| z+Le~a`{%QTv>7eDm`I>_DSMnLL{R8hY+VITpKPS+qfTherS#UZcN2=p5w&2My+o!P zVz0HUsM;^c3s3$@{=)u10x2Uy*Xky{3!z4(Shl4%s~zPTZg3sc*^a^ItJlecHy1gx zzhy4dx3TDVt={!`^z%BLa>-gNGIAwXtBy_A#R_XB#tmD^adHN?o5JV)0?%lhvUmU4 zJmWX5+NeYARSh8WyNj^U2>097vD4i=TK?$pwLMR!=Og_;$~w?weE64KpUN%hSn-*W z*nm#S2jR5`89Fj_h#YO7ux3exN~(HE6`37ISyUvBP+#TqrbjwVfS`uBkV|Q7P=8I= z&C{BvJ=5n7{P+@bihK{~?%MJ&0S_|cUfGwo8IF8{?|?WMlK8 z;T>ke(JxS$;D_oZcm1`shbj3SZQm_=w*Uzu!!Xpf(Zs|G(jL1)^n!7FD-Y9xWP2qd z>6t_17?d&Dv)O!g)eTEs~WG5WW{GLpoU zOtHn>-3`KVe?rn{a5W8J#2`t2oCobb{yxJy<4wYi<&lb`o!=L#Gb3sqjS#nNh6WJT zDwj@ozoTcl732E`mZ{g7-B;BNz>5AdoG6Ud6~uy;hD>$1g&LxyG+8qcO^Q420V_&4 z8{N{^(mONPmK1n!|6SmgU}-!{3j0c>ey}?{&-6p@kn6c>DpHH`l)kr7cp3^De>f;z zc|Y>j8EiG0(i>`7{v>IeE9djyW0JIHT`#RS)1~z25}(X3Tx14@G(kam;cGc>gR=7D)khx$F3?h9SQ!aub)})LhoSEe^+b_*kgJ{cXtk+?4!#mwL7@GOf^o`YU|jNzg&S?SKX1f@(8n zwu&`X13^i)hknJ4TJ_S$K*aek^k8!aQ8$}O&x@QrcH^eM!b-KygAd&6@_HR~1hHDpu(J_b4<@nRtJmZTDfkr~L5$P!N7Xc4LKDuj(815Op{pY$ z{Me;=&+s7*ZQnXgxqGzB)PdOwKn`5k2Y&Iw(Pj+O9Fs)#g2_~*r>Z8F<;Mr_xK1=W zLXJh$>C^BnL_hn`yQkjs#+zpi)KH_vCSc}x1>^?ncslw>U%19c2o&k4q*V;_;|+q$ zHB%m;d$DA%@A5eZ-)D6iq-}LOOWTBq?VEC3PW*9M8~BsP|CqD+_uS=_4?Sa9^2w%6}_3 z8IaT&OfK$i)_DvL1UhPc{7kkTr8zYOe5#5My(j~(0#SjEUb2gT3A$?UHp|vTWzmoQ zS!Mes4beOTdVR~nD+-BR{d%f6f~jx@=%gMPt#Rs5@-`^_bn|v%h5t zunjSq*M@3RCdv7_sl*CIB4n%%X7 zk^dP?9_KhV3XmV}|82UgBj!lR5Bv5W(4LnMb^x;+Pl2R)5XpCvfjFeg(@lu+qG*dU zv}1@29?uZ=5v(Uf^>2Zvf2lm>r<_=?GQa|&I;5ANGz$YsC=x!XUaVK?kvt*IRi`Cb4b!yW!CC#2Wt^w^IE1o!9i&mBVvNnsiv+);fRZX{j zb5_<>n^XLmn>RM=`%U3RH?vLr^hqaA*T3HvfGZ)FwX7RR&xtJCLr?J!$HU5_sVrc~ zyX%eTyy+l}N0o#vq>Fgfk@R6qBI%Fzq{cNbN1dbB!!LdzTY(j+v>kU_eLVO{8U$xv zx)uhj+LLv6$Ccl~dCX&ZeP9-J;%$p<>+YAjP@iWEt_jvtM~$87vb(YD8l&C2`+%e8 z!{MO^fEV?8yB0CS%s0%@D8D-htN^>IgaN5F@BRjciLC6=i%L*@okO{tC@< z;N7u(2Vt5nh2<|NBQMWuRQ<-8cE>~*iHEo6_R_kcdoRmymbMosqz14#Y3s&+e@pRZl0~4&kuVc%()N%Cy zQHD(?dCM77f0aYDf<1p+S%jMN-fA+%wQU*|VhpTbpD)oC(Sq2UMJ%lcEXOe9E*`>` z6BPS3`$ZYbv0*xx#!DsR-NKikAX>8jP|q48jHYk@>`O_XEYyxLvFA&3x7tH%*fT>x zkS}i>t=Gs%$Q#$36J=Nf?9$<>`&y;P8jEQo_nNJ14iqf?*&;OC_xJMI?s8`emJ790 zhC4*8!1@Xe!c~JBQtUHb!&jh!*uJy>Dz*AkOKX0kV1*YQKU$5Z8b+)3X|o(Vt(@r; zRuzlqpCiK^c@@k?YueS^MuPeMOTA(y8cmPu`Vd<2nyuttNI>J>C?yt+HZevPLiG?; z|L0fy2d34@k-C|DVc4Bab!LIq@|tRjX-oI44Q4N&;~2$Nj@)_bew$X6Q?wTFCl0Ff z7RS}{2*jRkHou-Dj!vbZ`Lt_TJX&kwWD^fZcO$h%rb4msRj44#wVP2Mrgq_fjV1|fOEuNl0sj5hg3iWohz43ivU~Fhw z;A%zp3af{sOuxqH@V#~DZqym!<757-m+*7CQ<9BBcD|ze?9)i*8ElAKz_oe%?bnJ(5K`cQ2i={%uVu&Sg&C=eb1)6TFQ$x z#BvOaf0;df`zx`Irv2L0gLM9CcGQw~;&qjkHd#Yk4%|TYZ>IkFqrX zg$rn9DK3FZZNmM$5M$}%?O35oYK0`nLo6(&m>3*B^d?LG)zqe8Daqn!aYLjJPL{d1 z$EyTSD5j0L&D7>Mp`aQxfPMz9T4ee}l1RNTmzJgj`8PYmA|3Dgn0^#MFNTm8Aw5j+ z6K&atE;zhL>p2GgdSHE*F6YQq938lvD34*#bD_!~aF61TJ(`^wir9WM-Y2~k3iEHd zj8)u~EHQc5hB1`uKp~Lf06-%V(*$KpdEODos`KbMf7aE61IjW}Y7!z9L`;?PwLfzrY49LKk3$4O3S z#~M5>DJXL%RUu75oyeGM)r0zz8SL+1Qgr>I^o}1J8Q;M~0eUcJ5iwJ_WQWwKm{ zG^uK3jEUMw;;^^CSM>i!K`?!N*?MOf)n`l9?D6YNF3H$^cAM|;+QYm69d-r;85F~J zX#}#7Rk8dswXvz(;g*!WKF)$bv4L$piTB%`gNsezq3iwqZmek2`)w+ClaJpO0pI)e z<%AyKxBj@By?VUd>e_fZY07%P;{SMww%G)p-fsG~=!b&ovpOSd09=25ejZ-W=BMbi z_p80jqaA!5KCe$bgvtw~A%C=MdqxB8gXCzUv0$(mL}USdaS#bYOp;)f7-R(jb8%2J zLfrgd*o*7(j)}}Cx~>kfc2lGw&h4GEzf%CJE%%`)_^T&(^M-2#@P5z)XaTq%HZ3%G z2dx;v&4IXhyGR|-EpHZdi3j9m@M!vzDix1Xj0+q+g5$G2(9lT`wPEZUVKo~Iu9Tu3 zHM2t`>S3HI^n6+&ZZ&w+npg*xQStPV2E1ANg!{MpQHpe*;{$WbL3h48h4H*6Ky6~? zq*i~W;NaCVYL*t)b;|ww%K*X2FaptV8qDL*VKbDS9s3n#y{Min{HW;XqCf7aiw_tV zcHXC|Aqd|H2ub|H=8C_Ee=T}d0fz$XRs2QrS+d?4XP@x2jB)<7EuyI1r;@?ULSo3}B zW8i0mf?PN^Wb|)JhPl;d7t+LMquX5M6hrO)+GOpYL3+bB!oQ9@duoY9IIj`%k@y7E zHS>>62PI<=lgFUM3D}E&r6fen4`PXN?mIbV>%Ya;hd^>D!&H{f)RHGU1ahka<|P&> ziZ#dY{jmHi{Ay1m0!;6~u1xF}C4I{OBboMnWyNg$bJ+S=Jnn6TWkMYYOu%t7$ zn8)S6kwtme^&1ywF)XuE$_JK|`%S^YuL!@Aq#GIe397(K5Kxl%@5X>A2vUi|nGw+D z``^Y0gfId%IOYCVWPa8ksU}(BVT{mQ&R)$Oh=aOih^KqgpGE?|{9`0QxUN}>SXAY| z;>zAc6w$0HQ~=eF3l$^K)&kU$K7etF4$MOokx_&2ho|_LZ-huBnFCr_-)a@aAw~$n z^8=J(ux5T}h(iKLg#L&QC3;#(U7-YCqOSHV9@e~{J*qnySF|l%7g%SVux`)_P(eq? z!SiEKV)YdSB_%K^$x-v;lw!>lgv=!}h+HBc#<58%vKS2$^uY9kUv#K23Ycy35aCpBc_UdP~wObq$R~EDT(*;{gi+>DutisC@lzHW9?CM@el$F zDgD|C!@?auGL>C=%cE zv1m42g0+_Qq>7qv&7G@`!9ewomH%plpp36PXf92fWs<&fS>H0L=t$oWs9NN5QpN;1;?goIdo1pz7v)Dkk*{NHo2?lS}u^f6=cUV+qk5g>NjJ5ji` zXQ)KaW`n;`Jyc;d0H>-Q_|U7FN4Ds3biVsYMIG=F2buq|rkN=;+8&V*53L|kD$ZI$ z*pMGJXX6&?57pWvu5Oyn*GgwUxUq7NjGV!-LxkY~+v-_`_u0elKY$XpmgN)Y_J6oD zT#9g#y8V+3D;z}?+X}F3`6n*f%*UYNYAhexyfL!S;)Ik$1Nr|eu~ha+Iz#Q5EKseB zBI6Xxr(oudR+NK)4l|IX_F&W8x~UC-xSaVE5yB`%V@2)eSJ z!8JAW)q`k&a%DqUUuSoipo4G8&`9aO#W74JwS4?UoYySI(0QwZ?jS9K>A24hiRZk3 zLmpr1r^*Z61WW!h6Y*2nnvGI5Da9u)t-ggdfsuOB{twEn-QZDgj%nTCZvKrgk{iF( z6|+aOyjwuS)6vp}``mm}X8NAC&wsruQU2L*;GH%PMCAM#HU<5^EIHf~a=5q!8_ZD( zgIca;<1#JU^<}2h*w`qZn<1!-eOFe}^zkr4f^Xp42GcbLdUQ~&1@i-bu} zq+MW|Ztirp6y!KJzm}QiIMDSSC##a4b0+-cIq@)YMoPkh{Qrd?YWu}&0>5&Q9NG_5uO zaGg`*ximNynR@1owOWz*-;$23&1kh)^|${oruvr=aoQ5%yL^E^9n6!T5ucXFFZvAr zKM=CI_VmO<@uLX!i%Rl;XM;MvQ_UbI$*Sn^JPG@i`G00VSKCmIeZsfdMn$Be-jP%3 z|0nXFUTE+Tyswfv4@9BZv_hA`eLM$Qq1EU%!i}?pATd8o zDIQBf>iBc7JjCus*p8KvwCjul#2%lr%6u1SK9>L2^|5e>onLk3PINvcX4?Yi%KM zH{o#LG*#JoVwQ99Z1@4zt1Nm%j(c8Uq?B!XmhYcK1dsavHPYD5&U*tPae@skoS@Al z3%ST;q)L5XU)}b9O>A|&NZz`snZG~Oe;1uN2<;kfD%pkVjO1J36!k2J96>Hrr5W8fcMP0-u{{xF9u4h zH)ey2+KG$mxBg`2pHZ*^OTG0XuC~Mc_zM2(zmmh%zwOz;`0eICwrP&p;(OL>W&HDH zhUK&+SoEIUvB2`y^#ev;_WSqjIH$i`YW?%px9h~$`2U>EX5=4VeA%iHP5B<`Wf?oX=Saod$wolGERAYq{`~) zwD1VS_4g)SH(0M)8r}A4I}5MTi8(Xh#A+Lz+R^?Zx)|QmqWAb zfA4(9^eOaSlxCiU<{hJ;Evg##grvP+FpZ|(m4hHnDTCBGJMVszF1F0+m0sEiF}4FJl_X;L#Y=5)!}KCO4( zynN5{DzQ4_>()2o!)G7ce|1Kj-JL(6f>0|;dw%7YsnZ0p7f2W8PMhd+CED%Y!CgiF zZ{L4<+2V1&x9zOjjLpmb9l4)6``GTQ7v8d1-Ctq20&WhTlNfy3QGS-7xVYt`Pr;#g zYr|JMuC70_Al&%i;R_iM+)@KCRTT?l{aEHzgelqSRe0w*g)jyeb)WXCpX8=D&x`3W&d}x z*+S$^Kn?fFw_-VyC%A0?`O^3H+A@tFGv*Z6TRxwZvoHJA1K}P~uV)=TN+Jy@UEDj* zU0fB@GF@XspO;^@s-k=KhK#s5^HY76`$$$8c{LX@;*#YWtV&_2DcZUe^|;Z=LX}JC5c1 zsXU`Uw;#@bA@%h=1Aoo2E%_xOag%1>E^6$u=$dRWtM$pMp2a0qGbcS+%UfV{Kkc3V zEa#s89V&b$xAb^QRlb-}!6Fj-?s9!l4fEv8H8(g98p+k(V`gAjKG|!ni40FQpK_ll z1H-rN3=9&$v2g@Yg>~A}i0kYb z8AK4~09nr`r>#?$K}^IlFaWPyK>}|kPF}fAUIsBigKk0KG_YHKt`n6(j0>VGDxL#Y qWWQdYsc7Bgg7r!=;1tEkz)-@(zyKUdL;^t@C$C$t%=Ta?m-}T zmD*L+X4}1|$^j>M3z)M_nqIa4{l+9DX}db*x>uz(w#T368-FuC`?RhrV?~8zycwJL z#5N7uHODU&YrkiihEnuy1)wQ^p!05NA3Q_nr9Y1Daiv23^?^9pFMv1hCW{CxPwHZ;y~ z5-hzts%E+1k}uQ=K%-T>#I1b50g07gp!<|>c|Dad?4$I$zVf&}i zFi5M{N(90CAey)H%`wl<7ObLo8|fOPZ9kJ*-&AE96_F|{n4-nlJcS{DqOT@I*CrjS zU=?HA4oq~ulk>GO3c4U&rDh=H0Uiu}KXg283BrggMMXmto$yA14!691R&zb}q~w2~ zaN~yl)iFUKu|QwI6lxg`OK);c1vzE{uaD3?{LYeFrkak8(~rRc?i(p~t2Rs(H6`Mb^U# zwxf;}dpBO}?VqLlH_fp2T@%(N^N!IcxtE+C8tZ%36#S`Y^gMifHt>7u7w&&qp~|s2 z3f%qNACxUi@Yc~PHVu+1xaAp{!;E&{(LRpNmt-<^Q|wHv*mYCO4c*v^6DP4kCk*`9 z4w5*AQ0U7zaIP=Y;AGz$O`lqcU~~b`fv(^>+Hi`9^bz8sz#8Dtc-mEvi91_-VC%fK zO^G6NBH?M-Z*UJbjNWdzgcN^iBt0-69hkd4nSnu0svNRfcfCXcY&)U0plfw0Ro_EG zF^Cj)?fBFVUCYi!p5+FiV+HQWu_kWnWZr3(W{IaoqhGw}|ET+YUPr@Is=X|UP%}aD zM|gm5=puorfUJ8$;P0Wci5DdH2wZfhcxt&gw5=rZUCT?SBkvTalgwqC?w!^27ay#; z0qS>CqB^KZx)}B2NVn7N>~3FH402lz15w#kVR}Bw;EIaWW6Q`t2%L-$Rv3A#rd>o5NmM1A+jQ#f=J0vaSCKN2J zkE7>3M|w58I~YxN;JmVJN%<(I1X^h;)vinW^6M$eDe*zHmC&|@k{-d+yZPr&v%Pg2 z-v9)Hgw~g|385<(^RfXW{K$6D;!16u5dnv8&3xxTRKq5tSrW&888bq)^h7A!Eeu=N zO2X30t${Y2AP%$$n7?mS=g%}FZ^0SiHrp&wZ zO~Ba@?n)YuB1)j+x)$B0q(8o|g9l2iV_nUp?x3V6u=H{M`P1y6&DOR6jv%44 zC2gJSi!ijj1;y-0_t1agmqr`K9KM=OXnO;!9u_GXCQ+1yiiwV%35B_bp_@iyg{JsDIK|9%*9Tmy9ubw0!kq>vC5jg>n@$^6N$mR=r;L-M!7IUg ze32Q(Z_=bNPJ}a%ae&P!bMToS+1dn9gi9M`9%96g0 zQ_T49LB-c75ng{a-q#ns^^obWhE&YLO3PoOb}fqH*{PvnJLz8a;R}dO>u@x~-hFtA z`t$^rV`|aNDDg5}OJw4cDB({ZhK?Q2?*AjFqc}^WESXSJfpu%)iIni2by{6?2gd{J z9{>OV|Nj600RR7#mD>t}KoEvsMfL&GHS-XwQ1l{VLRWtktysN%vn9w2ix6?$NC_))+WtO z1c8U2$0jdR7mtmLy9wIQK#0U({i;Ftw;EVM2Bk$Nq#p)83A6b! ztkO)O29|$Rx)xHN;wv%TMxg_i3^Nxxo)+`f!9M&wN4`6i(6O{i=5>Wa2P|nOzW;ll z_dG4jd` z)>EE_@GKH990#kpXaY=Th)Xfm$Ybm|8=}?RH35GnMc|+&BaiXw<3`ODW7#cI{>+ib z@?6CDC-MRS0RR6000960JdQyQf-n$8uhR4Y6i{Q*013Kw31;>sAK$t0eY-#bjA zNje>t|9qF;M3Za~Rc1YjZ=+Fl+Bb1De_zaElVD{&Su~la>A3Ruc@oW{%H$W>AgwGv z`qodT8>P~Z=9Rw>Qj};?9%PWBOM{BU?`J63Z8R>w{r>5h7tpN1-K6r+VU+#5mRT7m z3{$&(sLV(sRsMP#Pt!?M*^-B3c9Woal`V{>^CUypN0m*SrPGRhZ|B4QyrM`qf067e zsmPtp7*{k}Z=TQM%HNaUHvM%lPVP4-x(2zgY<_>EqF}J>(jd;Vz59yU4aSRX9?v$s zg33&B9W@LmnmwiSWbiw0;sIN{i%p2e8%IgAr|EnYZ+^&N9A#N@^Hlr&r`(U8#wpwX zwBZTSbeiHw;!Q7QSv={FH+||nf12J-@OJKa*Ih;9@BMgo>#olC+#AI2ZlnAAcvzD= zbkR7uolfHE+&w1qkvldY;+lKzQ#5xM@qCmHvpv_WH=6Dunz{Dt!x!zBuUZG)+TorX zrpYVUsP8rEt=>MP%tw2T!)9yGU0%FDedU_XR?53`WTef95WB-Cq~U;Lh>>_rFHp-OvBn zb?4D&p15;=o!6R#b~bTW-~^u|6i9mMWr&mDUuaZEZg%S#3X0!->QbNwfN#Fg-Z zBkJ(W zL9@|o^y(G494`hV?Eg+X`6XVU@$TcUJDsKM6!u+RQH(yt)g#t9Yt)dF_>dj8;@UXJf^CU{$-`V5I6PoyzWnPUE_jS*O zC}UAMd&QQx_~s@VB+^>;j*S|-`^AhsGAZ27qKPB&I~m`tT!ACFE{NT+GYH`3sXmuZ z*z+(pI)0p_$#_Lx7Mfc?^G`rTS7iDqS+V8J@YQI09cMed1e4ks= z4%b+jM7!DScDmil;?IV|CwKK_&m9d0@t7sejgDr7ASQNso?f{V zbaFA*q{n8S4flC4f8Bl2sK0y_H|p%o;Xz@lt!`ug*K~ndf8oXk{REQ@Z^>tB1E88K z-omRUt`OniKt2{o%ba6Chdhd4K}V97~;-PgG9`m^*g!@axXi<3=T(=Y>S)n7N7uUft0QX9R_exu!O)S8X@ zL9NlO*~`Hre>Dy}jb5)^T2#GVukOf4e5gBRP3MWjb$m=_bG*peuDc%LT{3sH>&|Y` z#V>L)j`e=k2mY}quNfU5UAv~KYBY@QZP6htVV}3@3}5SYbe8ssW9DYolscVAS@B5O ze6~PpJo;vqPFDU3*W~?wVmcAWvk#^Shwj5-?3$g|f8AGcw{=kP(%o*OyMNCcf8Fyh zc$u^scb@x^_8B6PbjR$jg8qFj9A^;#GzFPEe zXX)a8e~%rA+5TYCM|lL>zliQ-_aJ_g=he}L!HP|$T|ab3i(A(?c-=gB(dfK<)vR}W z>mhBEao@KN2#vvH7~{iY>hO+UkXT&(;IO^s>zdtW3rnk5%+)BKy07RK3o#AD@4Z{N zH*)B|eN5)B+>txM$!E38aWvPWY)LvgO5q6uyxJhu-1(1%C;P8YER`)D7K2zJ*TVXuoD zKRBqO7(!3PlCgl}aWoy&E~5D;i5GGbXE;e&&*#zIqMs^?<6+`al0}lx+mxV$Y(C#g z>)-9Uk4nWpem*)sdgVTzy?yIGV?Zf5e=&qL!)#tm_y&UiGExY#EWHj{)hu@N(JapR z^l+0cH0ybo>nO}Mn+N#LrWAdJ?=~63_ny2_kasT4%?a{mU*XBkS()^mKzMR20u1!;rVU~^;-Z>KQf5*|R zfY`?Iw<5X&4F$aH9+Jpqi@_k7Vh$^K32wL_ZNvcwSk;r9MGKgREZ7QwwG;r1`{`sqVDyTgSd z$d8M0a>rYamR9>Q!p6DA8A3;r4BR?SxLxepbzqh#dib>r~G!OK_ee}jV>fU2OZ zy~F*%q`#-6Wlu0?1;?6R(*bCChH_Bv92_35XDDqfpbAd~TC$DAi;|U%FXX#-0ir{~ zskZN9O306&rhc#11*k`?3sI~X0>ZBsF;mcF!J`l}zX$}d;I0X#*_B{$%C#P7Z6z77 z`u^=~4+nmT={6b#psEi7e{}&;K{CDOVXqCoD&%el?M9=!0lOYAvJs#!eTW2)3aWY@ z-6z9^L8Uc~+jEF)wNOlu52xfR(KH*(lKZ(}z;clm`AYgCb@}q?s7ADOLp&yefXvC1 z6AXN?JM)wmQm#=PL7^Zy|>dt_}$3I`4e0D$IGx_+Hl7x8dK?@06 zG#MvT!rxbH`({j_#CB2ukk8O(DdZo?4MucI%#`f~{y;1QrV=t&Wk6SWe?h18#+@zM z5Sjmy^w_n5ei6SBe{=~&x=6>CS-7(YpI(sGDPL`N6-VU(+nsi|*6th>wX2R3oTTG^ z{IEaCqJD!EZy7>c=;k^R0Oag6I-P137(YA-A>fWsri)}Ygh(|({`3Ec5q7{_A#B!D z%kt!R*Nu|fQH?N{E^bFkjFcC;VM6#r98Z3gflDzgorjB>f6s{vc%oov5=An=UK12j z_7y^93#}sCZx<6|r5#xtywoExuGi}IUcINpIA~O}**<6;u9;J}K^}|*t5gV)>tu8{ zP9Jd4_;{ex10V)aa2d_+GG$qS>pk=%9WuL{IYB|oC1hTM#;1Xu^2FE|$L6 zK0Is+np#K~e_5Wvmh+2I^Y(TI zA#H(Qb|8>rX+9og9^XC%QX_1gPmp`ci(a>caC)sye+}QZfz{}=VKmr4;9ji|HhLES zG5*{+9`@?p!(OlG96Q}!=dfEPw!SXh-vRp9N)G=H{3}QU*8mBhxntyZB^hC`f<4hU z*eRbpE^viL1?1VINVaq+_owU-@sTnQlLy=^2K=lPJ>?_f#; zrDc_ef2y)f>2>o}v&d{o-<$RJVXa9p5sNHCi8C7-t-BUCt)7wSg z(doBF-H{#+lGI(2bi-o~-G%;&Lr^C922s9?7BB@u}diI%o8Z3kTpHSIn*sifA+|qAo_~*XNht^cl2@yqyUgcy}6zh z_S(G;-lJ?@tP(#wjPZMWyY7X|@g?Kr6$uDbm@%_&_IwIcX-G=M%1s2hg;L}Kk;5yn zWI<~b63j8etPc~?uy?T`wBPn7|obk_eHn)a@Vz+haKE* zf7O#{xd)I*{bC>iSPy)J68KF-(j252INNbN$1UQ7Sj*C@$F&?-3~??B zd%c3B&~b#fu+Z^$ zwBT-S3 znsuoCKME-8?=LHZ61w01eO2g5D`l>;>^_;M-y`<{H*mVRhog5VR5E@!J0>%Z+$0^s zcFd?44{P(Z#y{kCGHNM1%gz$w#?o7Y1VZ5m`^iy3G=35xg_ab&$gYDPo~0{b;NQKb zGL>-k99;NR&5z;$jMzi$`93s!q8XVcMmTuY`k$R052)%9PIL0)xBMZZ>A@m@gIt@eus z(KLZQtR=m}KV(&&$at5QfNN;g*AZcd7}4BN8af-^vcF%@#|x`V9=vkze}wj;!C(QS ztjsd6VW|*LNeq7wPb2=Np5IT5N|MoMnMf1c=w(3wE?1$!{p%cVDvGo_@&gdg?M|y+dt9!y)9N0wV{04OAwssR<(`XVN)hg_<_;&xkQxuz zfL)!zjH1tDqX%X2%L9JlT@+`k9tepMJ1K4;IJoz})~>&tor#hD zL}q>gb29e9<7`<-3AH{mo3(`EJ;Thbc!D*_&05Myrg1hS?W(2s}Mze^d#tm-s#iQrL{s zSbp+S#EQ`;N0+`ddQG*=HET7PiCGFd0(y;~oB^f9gc=$NUNS=HR#pS8u1Kd`1&N?* zoU6wSjr!|@7cD5)!}gk;RQc9=-M?iC9-8f589Y#ZZBUcVt4{?MSf1yzXCzFv@P>6DUI;VzUbs-ZbWr0zYi$CX_~U3$tU^$B=@D1ff=Cyn4NqTIieu;_@#v)Gj|QB_DeVHZMu7&8 zP!2>i8>jcR%k&X?(a|^|df{vQ9S-U(!npuePT*Wr)3kj5dJmPDCs!9oSMOYBul~v< z6CC7&e{3VbDN=NB^D^5~%LHm5GGY+jgGT}8UMUtR48h}QkPI^@0Q7|L+VDlo*X_d> zUr~;)&BNN)R-Yic_mr*&)Lty` zae7BlhFn+5cGRE7I7FQF(YW>&{GooUf46#pN);(9%7wuljVJC*YC2m?7PnMuR6Wh6 zP!o_JBG3}y`eUkw)9>yBk3LT3_;m$3EdF>F|2l;e5&k>I{KnBE;Xy4`v{UdCj(=_Q zPAI+h+0C@30P@fOtq7942%2g5;0c|y?o2I55ggSRirMs6fBm|+ zrRUAPW!4n;8QGoMj}QE))sx*1p%I2si4*1eGa{4Lct(Kowct$HX zAqhtEgqqzueietWeW7qn(f|XZe;;QPat}&!jQk-Hm&cPoM)62sTa7Q)E%K3ve2il{ ztxk~A$2gfN)_kO%#gJDB|KpTsO9oue{Iyo{meOe~kPn3!#x-{ovU%7*q~ zUr~nqwHfE?g9CRFw|LMOe@bZ@?&8WdrvP2^KXb$Os=-(-9k@>*yaARP6dWb?qo-U) zrp{L?u3U-7z898}5nny>iFAe`AtG_w_j=4ZuUwnPo3|5{JJJsG!@UaqMu5{~)kkf4 zff0Wm*WN|gs+34U)~q~b*W8B>y!;FF7wbk$zx?xmey5@3d+j)ie<3@t@n6#0xoIxz zx7?0aDgrcn`ZXG(Ihp!L=sD7Rt@X%W!5l5j`M~{=J^QLIERsZ7+&d+W`W@-<Dg(p+`#=7B`A<24e|t+bTJ-n8ZTpXpWVriQ zN4$9M?U}K{SjcU>M_AiO8Pv0t?f3gkZNJjs4Y56qDt+HqF*tJy1qs0H`?t9I-l2Qt zXvIi|ZkF`Zi~`75wO$cZfwbOR^3H{6&oe*Tei*4d2Tq5P1 zK|8E>>8h?DmJ@><_jZ&a2He|jH@cnrTF)M>He}RQ%r{qif>u>Mqw@CC&sI4U3x2ui z162@?on~^0Byyw*>#T-oTvi;MetAAI|-hO|a z_BnW@*uNj7wKxA(Ii9k4)P6GWF9vt<+{(6;Vy)v~9QF6@bjrhiHXG!FpT9pj`*d}- zY4G#tf6+5~%bo=sq*v(ks82zX)jp8Ek@V#|x^ZQ=RM^2(>&o_zkLkbMc6t9`kKmK&S68`fFp!AYMQEM6i02*)Fe}DgQ|A6PzT0OQH{QlWDpv`k{(xQ)q zr_yKay1X>HUTR;?-2;dGN-yak-z(av1|0Ci)8i^0;+>z|hX2_^-@G~d^4YyT`*il@ z=-gfYe9X4E&0Dkm$UN+q;5Ayiu5oC6ITLj}a9psv-GoV)o}l7JbNAxprF~9yx>W(y zf05rnk;&XRxiTH>xqlnaUx(w1H`$F@_P^cEUvKxgGj&i1^aJVW1)7iz;)3r8QrW3fo75hOiGH;ru^j?!s zKE}f`E%ig&VB1bE5UHB8rKU(@|4<<{f5`}1AqKTdMB^AN9{jKvowCAaIpr-dOIm|2 z&>RVMg;*Zx&&t5N;y%?pForUuK20&oZvl~zUd{4|gOrq-Vu#w0mW(2}i&B${*P+Nl z6GW_M0Iu{H7-sANo;6HoTj5G3VRgP-G10-H4U4+Bvl*vBdXHm2=ALuMI$1SUt~cK;kE(Gtg9CPqA(dl*hE2I| z7Z4Zx9+w|q*}n2@L`ei>V0##e+}4Sq8r5SeJuFL`CUvIF2D>gEuX^TjDM34D#F*+& zR9i~6?aq8v$sOQ{_JBj#X+37Se>1y!Nvod0Cd{n4iRtMrhATSbF@bDEJ4rqP zwKc`6tN089b)h?y@(TbKG>wnp|MtQ1OdkbS61>uKBz?r(lV8Dd%NUKFe{y(0PL^oy z8gr_ib>tx0Bvt6oMXJdgG?mxx~(=OYjX+E$i=cF7_@o*O)l z#A)8LOPNVvES%w^59JmOf9}H%XE&Fzr#vXK+-D=`-r#)f+HAHJ-Vr_#XF|2<$@NJp zZrDaPbBMuMca-9gH_1OOwHN0vL6;}vs~NHH4&V&7oDClbqED#+ulWnfEocO^heBgq zNfvSyepI)T-8!Io5HFdp8k--Y1jr5}BIn^_%CMjbm1FRnQ%E`8f2iI@44j5zg_))1 zlwF6pjS)nanx8lcQa$Cb%M~DJZ+VrYu38azOZ8usb5_xbXT2kk<1Iz-*!x0MdNxS1 zOroT0sTj2|9n&BG6r3z2HbmgnL;|5|IImQ(@^Jo4!sx+HCYP;wTO*Lq!}7#$!^+{H zZI!l*KH;T{L@i=ce;%DZ3~^RwBtl=SM>^Cv?FbrPzPfhnk261|z$pE&k$)saZv|VH zo_h^&%q!~RVTUQYZ5&5kM)*(qU$hVKaCrh$bg^DHiL|+LZVLK*cnMU{j`xa@aP{n~ z4eW7^bo$25fUF^x>O8H2h^={7w34C$&cZbF{hTfAT)*D0e+&ou1nc?cPyJ>x zQ*?>SBDRAAL7C!m3IIZSYbq59#BY`H#vJ zw)TKi$B`}+G$1?>t;#G4Qt|JnWt+T$X)V{Im{agc9Vi5Lx`-H9K3q8b@rcH{32uyr z(v&s;lQG^kf2r69&D+Mf>#+86p5PZmpKol~@H~;cq#&TwBK$szDr0(slykF_M$eAp ze5A@<1s^kdO8$ZztQzTxdCrfRFFt;dDEgCt`MxRzChI-+s9T}e8V;8MQDJg}gYw!K z&O6?u%B23KJnH)F3$>A>Pp9sL!~XBD-+%seRZ_+0fATVV^-c+@zJ+>gNV9XTTrnVp z9S>jaa96%bEpMG$q-xtPd}o<*?+~=9PjK@Euzd-4tZ$3Mft;f;ub^XRguS$s&Q$u+kRV1h6F&A!$vb!IViJfXzno$&q0{L>51_&(G3sy4pI%=V_JhvcUtnN&$ z)Zr6Ge*#3qA^uo#m`U$|-FA4_PWS*9CvDO?sV{I?y^#veec_+{Pyq-Thpq}>I4ZF9 zvaeIO6Lt0_v;$vTn+`S9a$OHR9( zwHpq_l`B?g*FAg*SV7^b;^V2ogRHe3K3)_sf06A9S{=M=6qY5@TpWEFrS6zJ9_UL!V%0|pVgYN{<#^4rPv07i3p^Z}kb}7bc1~!56Y(rWQ z-o3R0WSa@)_Yu|BxVqD%M(DZaMV{^eX~_(UEgoZ)XHne0$8m zZy@Gn0^<=VDfol(g`h;p(S#yJ1;URPI=hfZg7TPaf#HQ^ag3hB&|+91S#==JEoWkoK%Pr^ra|eCz~8dooO5WAWqK%<^)XiQn^22wS;$Ph_Q9j9>U9QM zwLO4lPh|Slsm!`%$UM?UFDv1GO7;gkp2HU3kE18N@{!t$(H1Goxh2n^bWIiBf4MyK zfFZ4l?(N326+xRK(PrPAv}^ZoKiaQ1rlZUU*4sd=4{P zS;y37x1R}z)%&XR!aH^p)3e?stMMekKKJb!7-dR%c#~_Hrj)X+{h*@Rx+cZUSP%SxNP1WVzQf4w|j;nQ-;FZwS% zuY?1jw?KX-Kc3`^JUQ0Q>p@k9vN9{?$S@F>V~=g<&a5c0nW&$774I%T8ZO={P(OiN z$*B^94l8;_hK+e1l^0!^qKRG}ii!{J9N1!c8I+5OSV;;^e*utp*yMTXe^iXM=Z``S&V||OHHt7y2JeDu(pi!^mPTE5N$OPjit^3O)d-&2gp295|L|3-5uIu9TQ_ z$VD_}@pin=x1t7CJMeByH`h5`zXBgJf8=bP->>pSe~U9*^$2LAthSiD_8&3yO}hxu zi8zYtz09if(&4P4=PFHdQARLl7x~*HLZ^afUyLqTo9)`u%d7QH=U-lod6KY?N=(p+IIA%?Q2C$rk&kMEO_Ca!#C>f-k zor`m=UP}y`jv?$m}>!OS;TeGoz zf1Sf)3YfJJM9ZThTRKX7>?5T$VsAbBgB0LmZ(0k`Ss4_ww&J3ug@N zW2;)BFhgk6D%h0ob}{71gET^Us#=P#=ahH=r4&nM$XII~6Nk+4CjvdF^qW;4Q|>#D zEK7G_da7B{fWItfi}_lWJJ;2rJZcaVe@D2X9H3j-^P&_1y0-Owoq5064OIpEljl=6 zd`W?|@2F8L1^bB>w!)SL8iY7XXhW4};4V(PlQxv#eL2Ip#Y&20&s(k;cd!&1ww{rM zYCNot8lAroaFpD8?7=6uwW<@NBbVhp0sUaVgJee6qOxxF{NQy~y^B^eS4}%9(mUFt0c2!Ue$zf=Id@X+3TKpQ7rgdq(H5{ ze^$fUp8|#W#UCwuqaD#5e6Gwh(vgO2NMAM#1u{#t>8sjMM*-et1d9`e{4&*`%x@BZqwZ?#(+yeA9vLuRDZV@9d&jr(&&vU zk=bbE+27aqm!FNZ^NqKdQKETx=Bw*Z2$Hhe(Iz2-@+X{ubmfM7+ zmFl5oq3V!X6D!U^sPdTw|5!JmoJMf6>!EDdcgjWTi<3@=hATU?NGgc~f9NMwcu=0_ z+72lh*Or(E_bIRfs%ItFmRN}lT&`lfj%W#gq|P&n-;zuSpjC?18?rJJb+1)3JUzdt zaUK%+iVxpJ!AV0~wsnA-GP7tyFnPMq7FRcPt(IP3B30;sgfKFKKgYWCox5Ol9nh^B zKFzgR%&2CL)?Z@VVbvcPe^^L9^qnVdeLJ z$veEMiR-+5=~2(s`b!}m+b{Ns=VlfF>z~NH3W(i9i}ITCx{W$A)l7%h;yRKA&8wTj z@RVDg28(o&3942*)(T|_-Vi!fWZ1FF-^SMeLGhy8PXE)L?wdxVe^m9Adm}ch0wZQN zw20~36AH}?ma(#qYEYlna@?$DS>FRP6qllf(=daI_$)evgsyo%;{moX|D^y4Gx)K_dUq0b8%bR%X!Up#!tjuS5>MB%7 zFef#%{zvU7l>3*rbQff5pjN+^iy!4pV{P=DSVOvjt+g=%yKO|DB2mFCb1z&egDpXA zj!@d0Ofodm&~Yu}@LC5(U4fxjTe=qKVC1huGl$2h++{$|e=Z9P<*kjTXS*Ic6}Ntr zyp2=_3-Bd*b&7HB8eFXA*{#Qcu>TKC*^a<${fuQ3+lF|lHTdqJCHADRXGuYXo!k0R zoR(%iAk;vNSvN%J4)KNC;tS&YgQsd&gZ1;rcy^v~sXN=teelv*C{iYqr>X`{z_3sp zo-;1id{(mCe_9whIYN9!#43$ZKT;+rP|o)hIKD?lcg3k~W7!iB1o*=bc?8rdv+>=h z-tVKLtLvP#%LOc)3x3PPW*n13FRam!^wTVxI+*W5wyIbjx`X7TR^hOUaeifg`~2qW zzTMdnZrE5&tCrLG?(6X|D{3Y$6E6OMz_iTgKmUw%fA*=k|Gopu!w65vaP-J`iDGm) z^S`~Dn8M|7K^pBBMhO=l98RU!xtA{r1{CeCgi%@|4Y=M%LeH524;< zVbN#tzEx!F1wGqP^4jTY6W_w`rxId1Jj~i`en57pnM&k=mV$7=f9Fjk+^>&c-_+XT zLG#v+e=&(IId3D1jBqf1WBby+uip6*XE5eMV(Z(iWS)3Dztt;n2JdBC-DOMaL6*64)m ze<4Kfs*sgAtFlRnIp*Ch1mK||)+W<&?i!pgvLAfNIm6Vf^K z-oBd9${-s{VWp{*8?`pt0%3j$Vu>Bu55ZS2Z>xo@m-P+BLo0z(E#0%Wtr1s5>L9I0 z?qv`1eE55@Du&b3laI2&Olf@c=P>BWfA%CyRg}*^W}`@Nl5d_V_W4+I&8%YoUN5zMBrv z3o9quL1%%VbXS&{QsFII9@+;O7V18E>Wt%IUwvts8n&rJ@&<4U6atm2|4$^C)VznKGxWUn` zx(Et3@h_W0AOU@M3_NK#1mQbJ)H1`V114zpv9;W97JS_xQx5jzjF(yFV}UMGM{~|7 z|EF1ZfgCBRlwiBhJp76(e}$yqb5At%mo-#IQt~4Hg!C3|bk9F3oS?JRYjyNBoGX9f z`%^t?6UAvgrmHg2)61=Q$e(cbp_`K2vO&e1tQ33I5>Y_no=jKWBPl0%zau@n<9pdH zK$|5QZq73m-D4KnO~{Y=32l9Iy~MutqMq@CU)IY3ebN{H z>WfkIuRrV*I^kAIvGtOqJpMbfLtBLgCnyt;*icCBO!gz0mozrM;2 zPwMwZ3l7b>d9V79e>pkt+(MTDjhxFMv-Rawx`af;ktIx&r2?T)+6r2;tarIspTYT9 zmkz9cISXFac{V~^qrcZWn2Fv?&)l!%)WxF^E0k7=)<1S)Mx7`2Wm6o7-Vxd;!g@auTA9BYY)m6D zFs4FF%pgF?LiOFZc~hG2>^ESVA52|daiC6Ry;UK6b?wTA4k@b?02g#(QYQq(DA_fk zYVDSuViXoY?Hrd*jr*I&%95$fc$hBwbJ}72jUDQn_PsZDOZtN^D&Is8BKK~5(*%58 z=mRev1u9D-f6r=`c+HL^6^;&xP}_Ao{-jJ0^4e+j@`&>%YWDCP)-J7Yvdb^ku*hUL zqiT-f!E`yUIdLhVYVC_kZ)dRk($tL33~V|e2hg)RzEOH>d7_l~`DQS`B)|FoYw!%L znH{Px#rqVb;4wg$wobY{lMnx7_@TU^rDf)7pylRUe<12z-p0O?quMOB!sTk6;QLc) zJ@R7K(YNLEm??{)l~*+xI>MhnEYf)(N(PMU+v0#kzrQRe}puM;h?lQ8rDaAv*UL^_Feqs zch6UVe|#YFF9kem5nCNR8=4=4!u>Iy>eVvgCb%*OYI?jjeR<}Jc2(|gktD^1KbzFq zHyq@0vYL2#&}^ZTg?7tL5rIgHPyiZK7N~1}53vu625*-~{yi!y4{Nv1pte|#a%J5y zh_9#%-S-)f+wN^(}3e<(Z(nzOYD$X-pN)dSkr87u&sK4NY zeCwh7-Ku;nom*K}dC)b@(vb&!{V~EXpqpiWr5z*K-N$pj+s^Jkuq3mB9E`@b0|@_* zf3~w(YGYgS{i{@XaN3UG8-F{(5dsMi2EmcQY@f*u0WxSKBw9lD#-o0Reu^ISpyS>_ z4|?V|=_k3rf96_MrK%E$i0*SD_TC7wYE`aW`JMlKS(&k&-9N?ngiClE%9rU%wT9}F z{ZMIyIL*?61gn#Z=VKX6szq}#>f$~Ff9%*i(Sgw2qOTx;hNV_-)I+!j}A&?u}J^V_Q>7sx7BKL=ri)A%` zS8vfXE(RaW*6=OlRfhvq7X$l`)hp%}m4&P3GFsOv#)tqMZL}T7#B?9o0EU_pFafg8 zv$SH$F-OYs#)}EO*vV6IB_tuWepz%fSB{knt}Z$$Ro?8 zW+h2ww!1XoCv_6#p6o?ZTDd^Mh;Dp;rA`l(nw*y^n`c2^10trI74cZAUw3tV19W9e zw{9ot*d5z;$L^TjvE8w4tk|~GvDL9{+qSKaUe3Aq-Ty!TeQ%Gk$JlF^=B)bWthK6E z%}-956>e8>!4Irb@s2+jVZ9;X!km&?1pD$wYlP|RaRg^&GhimpA3CqWCQ&zRwVN;s zQ>WCP-c!A0@zV;@C_)e{RspGZwtVv#40<1I6=udaJj&b%X_ z8)R0%FsaD-u3@q8tN&yDwcL3nKH(YrijAD6d^7inL5&#)G?NdbhOKMGFwKei7=Ak? zSgq(o>}Fu#&!*&By%844vWb*{ld1LTb0+OVUtBcn6IY8=>;PpO+H9-}=8OpICp4O4cwP z+s#70ceCYW)p98~Y5%v}fJ2i&owyMZ_r3*22fg^&;}@}~kJnW_hJA`jr9y~kev=EO zfzvaoQp;*4D>Ifl27hj)J-{=kW6eqrD@!`t;182ksAW(55R}}nNd|UuE8?H-{06}qfGShp8S{CKayDE7M!$csl-nXLhqY5q zoU!G*`x{#+$NfB5@RgvkLtQ^ON`;Ru8D;Lkm%{7_^_U|M!*)i9wR{PzoBX9zy-WE> z0Hb~M^;u;-p3GT=2#L5CbU16Bi!ZH4ie8j(DJD?A4BdFkSZ&0Jx{@S3#Cb-MkGro4 z=q-=oRT0ed68@!;Q+)jmU1?ab{Sv8kd#q``{%5I=D{83NOndpSxiDE4*?Jej2U;CZ zJw-$^*kOo(O~ZNm48y0~>UWc%?BPf{Mcp$aq927(4pr!*0DdPm)DNNM(=V?p4i98I6f;+7Za5pAm)JOuenTgi&ZvC_->7a>kfMNMp_h&y*@x&e@tKju zpixfS-Heo6#WA22oJ!lvTt?Tx*h@eP8D7&Macb3Bget;UhSDTTGGDKW8Nt)j zl1oO2ams=0jKLuK%wzwqZL{m$qdBK%`)Y2D13t$4QZ8@CSY6Q6lB3<=B1cP)Fizqi$9zfcZkVeOggh?K)<;?BpEd~uz4i);tRqyT!iI2hANDjjGGSaHL>?0%RrmU44wQevHX zp=6;(8v-<=q05Zn?>DGAYV+K@zt!Lf`G4vu9It-`RsGdvTk!q9Y+JM^m$kF6iX=~i zO7FKio6Lkel15%{H1p(9x)`7fPPmtJLBhB>)nLwYJZ$)JdWbIA@{w|)$vV8~oGK6P z8+N9nXrJd^B&}F(*(((r2Y4zb)n_0MIk$0prWU%!E*>%d=V{a&VrP-1hN4gMHMym3 zqE8Q%;po_4=1(&+{r%prO26ZG8`_7v_4-7@;7&(>W^=JNnwl>O6^R26J1e6EI<^vP zgldy*?WA!vp_CB)id&^OWh?2obD-_Na@Ti-^-y6=)0D}7568qz6n~cAXX}hAC0G>H zHZ7N?g*pI#adp}giF~pb_LbX1*Y>KcugxEx$yiDz7jqds-}bO_5Q}P1WMmq)!LBV^^aFm40-jBe!qHFdA!M)p3I{8-OD+G@>Cz_>P$eA zgm@=CbtBXvcXBbCi4et9gSXc-Fccd2*KsM-W)W+M>wx0+u)CQaVz-4G9b}se$ z4T`s@q<&0=a}in~LB~N0=PWkVtFn=@|Lpr0Vbs@rWnVJzxM?mOB z8c$b+&`~wu%v`cPFnt6|n{6}e1m~B&WYv<3L7HU~dk2%njafRQO8JfYi6FfySBPSM zwzR}@4NQZRj8nD31H=R7WYuVpEwEP{+^Y9aRh^t9UNk~X?tKF%b-#%3sSTIr)d8VmQ8ueT@$^@)A?VSDfs_+8GKbPHPzPML?!gjr^8aEQwa*6De&4 z*UU%w7xvUc1oe!*wF2sb+pO|lkxpO5iz&pRXug&KCBgyxewGW47s~=kc$*1WMjPaS zrU6W3hHqkgMNERec{${Upbq5{NEw`3Fo~eUB~%V3cEdFgfqi;E=2Ix_;8HN%f7|R1 zVt?k*V#kIo)&T5M3pwu8IV<1%}Qv3HL1B2Sa>+ZY>R>wCVC3daOx#-)h_$s(c%73 zQk4E8qjB1|#OheYwWHqUN7i6$(Sx>E11!tUt?j!@AurL$ur(zAMyCmf9^+0TO|4N(3l z=r^t$NnatxsTZdaTdik9yi$rz+b?g9cR)VUYKitbrCbWb>88gZMbszwhGvXf&&seX zpb!(_WAUXZ%u+xouRbi56tm;tfS_m>6wURAi!6Y=OAH?T3uXYriV?(C3SWz#PNax( zIXTdGUx6qiBK3h!d^WT>*l&}nxZ5E;0m6UL9u}qRBHmERo0@(rs_^MslMNQ>UQepD zr?`_#7o}e9n#z~uaC{bWcjQm8If~&g@=E(BY~}1ZSMGj^*JCK8MdaTXwJs%H{5UZf zqX_WLqg;)!%_5^HR^7(&8GMCf^RLUAT<&LSvYGq1W#Xc2@quxl?@9GlTOMe$uzl@K zbf{H$x{4Fx8Y1PZR5UyFfdbq^(P%KU<~>VXh-7u~CIY#B&*ms@?pe z-t?K4Z}iTj$tOkIt7*R6gxT$%R^dPfUn+1(DfZLE@8UJ{y0Sy5nIbrJX}&CXFi&WA z6P%s+JUKej&3C3mHO0*)Piv;O!ZV|v&W0;UZ_}KU zAYw|I_!1D@t`n=B1oVrfmN^bpP3 zk^~-X^V;3b>r1}g_VllkhX`*6!e)p_gAaQUP%IIXD+7+Ljf_+AH&+JKO~ZocG(v2X z`{h3=ypsn3S)aP)NI@}$rBhhx1DNjZ_rPlF213|(-GM7G7I`<31nmC#t#rSC`mSxt}{Tp8P9U*HH*f%odf$cXV2(huOa}>cu zYRzb0TC;=UxB+`S03ksB!0sOG-V6dN2!kKG(ag3?Ou5F=X-w-u0I^JVCrAG6i5YWF z@6qfdB0-Ef8!~G`yOQzwF*P&9Z-ld#+*LZpvD_jd$B(B{i~~@1@`lx$@sOwFusAB7 zk$U^lT1p)YP8Jq@82po9xat>A_y9 z&!?LAKNqO2t5OFy3JaoEz1`tL6*7ASNa%it5NXaAfmm+h@>c3Lu7c&Aq!(1&VN_ zcEi%pD~rDa(%(H}z~o!LV5IYzX9dPQeAVP80g)sX*AjAU-iNd;RNL|}REn<(L)23< zcER#fX9Ev#x62FqYWx%OMdZdY z(yxrbzkKIeaE3!h)62h>3pVzX=x7Vs z5!O5J7oc;5n{NZbmT8tpJ7HO&*C7e+KUt!0qN*AJ({jm9YAhd{wKLI0QC}r9%9vO5 zg!&`bDIEuEtNKqtYd+n5+b9RbM21%NxIsSKnSSrH28haJpg@b>i^L>|+NDKw5q^o7NXn~vp2)JSfe9CaS=_{aV((`UD$C<12{%(a*w!4DzWU)h`N_pV|RwNXGm z8?b@%(F!=HE8$uz7iwV1#25O#3W>nFQjq(PGo?$ z_`{N;ez?m7{A;7n7MiYAatjDblR*vXVVkl!-%QJkaT3ZPbYPwKNA1}w|) zA0SO5Tz~AN@Aucujtye1Ns~!v*|Nwtx&yevht1+%vpO?$dJM9D-c5AZ1-BNBR^_3@ zlsk*2w>+Gx6;|AK3**7OeT%e2i}^L(`t&N9CBlCt@qK7@3YQFpmIN)J8>$3A+8*UL z3mUA{=E3JS?_=vp=N_Dxq^l~jM6TqW6uxidMeI9LYIT>vAIiT}pcJJK5@TRUFsp(m zv@%^ao-c!xGqKb5@Q&S!-X0UkDRL32bGLKTyQD%z%NnqTE5trJP}U6y4{=>zw816; zHQlLu=RHNjfU8ctMvhlJ3tt9gv?*uGhCHZ?q-#3PK|WXdewM=CD_tygt_{Ou9-_3W z%7m+7us5;^HeRs;cQrAf1cNTHHq^Dvf9(@6Q?qjk%nhqdXL6CeM2#XUmvNA%v0!r- zwO@UqaOFLbXl}$`dT}noO;U!JyZ=Jwx;t&VPUji;kY}GfB31RQgE$Xh%b3POq%_Yy z^UYC4Z)e)6Y#8j#IBV7Muc~MB3(G?BR`H}VeoG&%MIBS-G%}8@G@6)G?aWeY_eELf zc@uxa%tlmHi%*1f;>~%;_#!0OKV0h|V5b$RSyF4?*jSA_El>ffTxIkGZdW4=>&4KJ z-Dq$~`an4Dr{Whd?R5hzw_4EC@v;ZjPW~3Pfw64CJ;{uLggv1$nilzpMV7ANg--Yh zeg21ggcFIWQ|!E)ow9j@d3l`m(6}5o=aM<;z*+8^)0qtwC+F`h93Y)Vonpu~*K?7F z({whj+*)LKHZlq^b)~M{Pt;D9+iyLBzaD3RVrWS_HvzZWxs^Vqeb4n=h&S&8|VgSy3mG8WHLARHtUW>zv+N&dbuZ>hDXqVlYy|ZBR3|rUf9KuR(|F;!^N#7 zS+82<=n#v`LIeiraC1_Vp^3Cz7G5naQ%7-I)HXc)va>98o%Ek?mH$1%V|pc=>pr$& z{(Spup1wGC=Ke~qkfZI0uC%# zai}3zK@Dp1)cavrwKI5C{5T?`|6bz8Twh{iw>V=)h~fpfmpkw`j$ho`Bs68McWqLC z)|fV}?O3c~{-%;&M?oeW?5U;86CBoU&H$MBd$ zbx+T7=NEwfh99=}I!L@^q*xy#PjxH!k>)|$?LK1E5htwO(gP1v*J~rdjM_b_Ci#_>MOPp21?3oB8 zBpqdxG|CTkAqUCt7rC9~6(pQ(XuzN4teFtuNv8v|^$jvB!RVesu-}%)sk#f6uKmz# zr5jmS?xxRRu7wLTPG?gg3s)wuT$)tM3&58c4T9+QZ9S|1Ne-kNp)8^s&)T(k9w!TbTzfu?F}VZ~&#h?L8Y(UOq-!uHz$p&pEOw0ool>{hu6xj_i z3B$K>xW;zJ)xwRYU$q5r+U%N>=VVO)xfi&-kmRh2fn9I-aC~V)D244Np*?gbdwC1% zY|>fq`BO}D4b@GERSQ-p7nuSiG8WR(-J&XrP-7vfb6BgmfQvyy`2{N`BTHHwrBA(X zxPQuhgDyhXX{qt!cCG!MWw?ahVNOyXeoF6<=GTi8@?>I2jt{)z-=QS6RX`a5J2Zk! zeZw0S=V6WDHwV84ZTZH7fXD4nvoDgE}!F}@r6 z!cXEw6K~T}%@mZG3YKq`_5`Wp5I5;_)0(%-;TXm>Y{dsQYvuEa8j-C?9?^t;wP~9- z+|@R|K6v6DgTE;tpvlw-SKdjC_j3@B3Z(3WLD${u>)OEFToyl2p$T7zM8g7I(eLD~ zG~`RX;8_75A7=w#0h3Z+Pj!+NTTZ_CWW&_)y9COarZg!MNrLsCW>H|$!9S@+R#V;y z4Nv9zZ)tiscs_{sWWbkxi|&SKzXn4tyKO;jB36BCv}1V=t$v`^urF86aFh|d_@fz> z)pnzLL3EQwy!ISxdvy3Gwa+jj^k~$8`jOYwRQ;r%fm!nWD(5B zwCE}IdO05IC`TwAD`SGq_3h)_n#XJ1s(dPr4l~JOCu*)V=LHDO&dk_Xo{nE%JL6Dr z3O<3RiEhC7ag^%~3tiI=3t)y%p;rmbb7D#PI5A`LRy9St-Q&iCpLIiA>1k6DG0DwV zkYe(~qBw}hQ~{xam{HjUp=CsL_I@4(B0nZ@v|;A-clo@LDAyQSxl_}rRvA+wf4ti) zteVGwV-knB1wzNH>9;zYXzY5Z5l*yUHF!3oP6%iT**KVL(9kbu-UD<53eflFR7={$ z<(CsvNT^-;d2NE;$JT2rEiywG3EFy^enwD+iLnec6adXocBN(*4dCzJtnF}jTdect zcR2N2KkxB1MM*+b56$P61Aw&ht^yESVh&93XM2-%m8Jgd6`aL(0i6W1B ze$Yp{w5TdMzYv#%V~+C)ge+(1Gm{JFaT-(}H{kjDx-vKPr~jFqAaQ|h{^QHvs;%Lr z;PHeFh;SRE(956BM-9I94GhR1jJ;o+b_`_YM}5Br zXch)FrNtwER8cTsmR`*n2X=T#?Ltx1C8d`$kl_ryp)y$MTfXu#eB- zxSXWaW+tB~du)qV!jPA=>%!#I909E`;4l_<>rsP#q!y%m5&L>>Lw$(sf~4*(f9yMSy+@);Fce-w=_-tOmj4<6?&a#`Ag zSb%uBA92WI2px&6xXOK!8D1>nWO0eVJzzt?N@@zM9OUw&4_=Y7DY80Cpa%&%l^qBC zk}=<>p#rkv(%R4acu3enz$c>#dRM9SzDRMb#yc|W|}k&r?*Yd1NX<*xFYUWP0Kod$n2a2 zA#z1Hn|s`H1Z|KQOZG80oId+{VyI=sw9Iu}&ZKejKoo{JpWrU~*=UhT$DW;ks!Z-# zC8pqW6K~(NnjTY)8xm_D^pE_84g^X>m`?XdakPV_P+=9zP%N|s;c%a+)i++O67Rmv0ww-}5ciMs_RJ zX1mhy>tH5DfK0>l+s8VG>`zf5y(`^%-BJnP-$K7`H+$NqE{`#O^Gez!O#nd{gLuc* zjp%FqErYo_GaAbqlSymOCqV|*eWcGvRU7A?@2Zm?)7Qs=WRJO_$i1i=B%cemxk~up zc!DLsSxzH4Pt`1wB=;l6#B&@ChKV4`hf7IpCmnGn0|BDq1KYEwaC|M^jt(svlwy2; z?GON~QRT%VD;D1*I~d*H7NBp-)Mk?L;%M56^Fx-69KyQJ+i2UHLuh&Mn>yrqYANv4 zA|Z8hH5FY!E=n?ZnhVH`uze@z+O%AI?NnxP)0rCqtZ(Ee6L#G#tAouq{2%*`Q*Vo^Ph^KiMyl3!W z^3vl(FLs~o5dBKJ0yUa%K;WID+i~W{dOudy{Fe1r%v4Ai4iKVl^u_wI->Co>H$lIZ zosKnr@Bco@x=s#nwkMbj`1w3F@WS-;ZH;oD+xZY0%!(Neg{^$^9rbo~IZZL$%4#sS z)Y^)Nm}xckq_RB0;K=g5Ri`^uB>tzTEx4gRyy#4pjZgz(_QI z`rBI+vQy96E<>-*vKlE=6u7l11v3?fRp_eg;#P@re7_6`BM zpIK?~{>HA^mnTYxQ)KUk<%2PI``-2SXC;F`un<#x$ES)#w6E3gg;0sJ@!UrLeX zFCvpxUJ1UgBT$CU=)5Coj@fxSJU?$x#m7NXaG(03u0u5iMyzVBzrF(2cd#Z=>$bTr zHk|4eTEOcY!!SH^OH<%-jEHf;3IZExGdv}iCv}l*O+v(%=b`yvNw3#@%-HW%_Nmvq z_5I>@#bTS65FVjiIN^y;@l7`t-|snw8929fP16o|Be5R*qzPmIfpaErR*(J*(M6hV zoIYd2i#U=@1l#V$HPD6=!A*i4zFbDk^pc&9K45LPCa8MpRmXtzI^)Rm{h?#($jx`&@1Q|e(4BzFk|A})9s5!V>Stgeh#@_G-l)Xg%UN|K62FAg;8{OivQ>1R}5N_!x$-s~ht*pgWz(17s!l zrGP&o+tx)op&!x7-3b!0O7Pb66M?}2Zt1)@KFUPC0wHJnIbvsRVsGCP&pt>)t~rdz z-KrllMr=?zbpU&>dWqJxy!+MB3eQQ)id}x<|_N z&jHW=Pn;e7Cf|N67HHz8yNtso1S>#&Fr(GM*HV%kv>zI%{z}ht7|f^8vo6 z<1EXp^yG>s;pdad+n|xhG;N^CT$&J#Dp$y-HrwA7;+*kJzPSpRy_`BTKp+ae9glYV z7F$d?OAjM+V&2B_-x51k2LwUNVyf`Fdnzymy}DaW0G*E*M4{eb{VJT&$*&LZJqsJk zS%`|dG51jDV$t1eO|DKaweXK)^&DnMofv*OG zLX7pj7yRdGrN>u8VgTwD0su5UB)LApesZBiYkPn0kiG9QfXum?+d+P~Tyc29Xive11+wPT?wtz*J;)oEoMq~|jfq0-pT2;Rk}*^!X<5crdwIDTlr|8ckf zq|O|BMH+PJt92UgZ%7GEa;A}0Ww~?{Fc@1-) zn8=|iFdc;_@J#dG#tmS<`SNrm;t-=qf+7#Y77-vX&h)UYqi|gi@~D4xkbEhAXSI4F4D;EBy5B zhoc$(POHxCQa_%L9w;}?#i4)~EnjQ>lb7SQ+v`}+LvPSR5{Hx@kWCu15`5gAkP{(>k2ub8ALCq;Rgg4%dWKprj;UYq^sWxogtj@|6 zjWJvW2<-dVBt~lfD%V;ZQQz}73te(>dwMDO-7uoU#VI@&LXP2xcY(^&vD5+ItVq85 z1va~w&AFl7j{ujDe-T~)(>|5{2Y}Wau9NXe|kr8~5|s7>fe8 zXr?xl9K^Rv+HVY!vC=C~ z#fm0*=c#%vmyL<%nU@{Lel2kVNB=r)a_!X@&?^O@Xg|;s6T>ZZgxypYfSOBTCyy-= z6C%6@Qb88$FS;8KoG)T)aBvZV*s+riG*~>CTr`~q@2bUG6tfYeen;t2G7|pTqvYLb z*JnhL)%X|`^ao9~F_ksVC@X@_h;f_PoGs!r%CxL5*JOIG7{?C@&K(fu=6FR!a*lip z6$FeE7;}{yd6?#f8rrd31Lib(y-njGE()=VL=YIEg(<)jusW60yMS8xB0^%}L5gFi zoWef6f^5NG@JMeUR<09z;(y+Wr)4z;)6i(JnG#>^ncm1ns;kQu;GYw`OT>dY_j+Rm z57I^SkPxXg`aFJ`(91n=hXY$CNZ9Ke&9uABC5VS8oTOhvMH1pG8{=@7Qz==t^)62d z4sFU7L8T2HcOSV#}tnWKv%n=@V`+<-JQbIEnSPsSJZcz!}^-r370RQ zr?nG%dqu<*aXDqX1w-k}{AqmU=EU8z+1(H6VmD1Ld9c~+4vMevJ<%w_DOtImr6;&G zT^FXQ#;H2@q|hXhxd*K2vgLCi&9Ki%(%6a*T4Gfsm=J7zZ8c19VB#Md!+WVna3N@)LO&$D z4blRO?Ry$s4%(>mc|bnuyx_S4@Z+aLJx6XA#9nHV-<5x1Bw);{NBEu>rLSNZ1zH6_ z9Oj-I)C49b;S8gG1mxuG48IYwHTejSJFRt;W3eg);>09z8CZPqI`Rqc{GBqD^H-MH ze3k=^A_(%Yo)2mvCc8j&h@rV4IBXspR<>A(!;zgAuT~d0Eqj9ru>y8Npq=yn0Cwg9 ze?Lrwqh9NIYeUrf1(It=gofa{aOeA1h*x_x%X;E>2TWMmo$NdvheB_sxaUQ@<&Nh_ z%RsOdrZyt{l-#XOcA*Vh3?b{c!yqremW^sZD~(8n`)yWNAjd=!bFZ%443<@_OZ@UN z;=5`cSy|5oY0ZDJXvFQ&BO!=(x%kC^fBIzj5!~l*5*)NRn|g2{J#Hm(nGq@Qg60m7 zc0&jOX;9Q(NiDcpo}r|qP-90rH~_D(p0jw_`GNz)iHtr}S@P#V%F|oQWanQQQo{MwozPh+`R5$}Ifu2lofxIKNjiUhUE{b|*3^3tM5Gy(RkR z#D!nUc*p42FY=~9ZgP)G4YY;1_s4nZSOMI?xNl5TlbO*e?wHLbpM&!Exxph&h#*Mq zRXfT>%o$kvF1o0U>RX&T>&%d=(d8QzAoGQSF9op3FzEdJ|lJsbv`CIth{R_o8V$D!glyn7Cm|bWFkWeXdT_67yjQX7~fl@ z>ro7UywmrWIy9^I``O5mK4Mb%u|$M*m5BHB{y6#9R}D1Ri`SSKT=W4MU2ho^RxdGw?W=rC~7*uY@gZZ#p&SO0vJnhm+dmK=M zaw&hj1wl8Hyx2 zQ$^`_VQ9B4jg_4PwF|3-k-ay!<}8Gks0W?WD9?lDxwC_#GjzcHYVFu9szZA1*z48n z&DKK(a4g-h;>gfxe|2qJ9Zza_RD18UZtgixZ{IZk6X{qBOB-8UFDq?mJ@MQ%W7bzBiCn{ZPg&R ztVc^Tmf4jr@hk=C-Q~~Lffc{b5Pue8Gs|PNkfEwOqlF+zHl849X6B|ve-g5Jm5 zc6#n0&riqVs|SSr9Ff#FDu&zGL@(r|sw>9tHEhEuD{xs=s}*Go*FbGXUCFcfYK@H3 zMTo&80y8uIBzlC}Dq``uN5J<)D_Pk>Ap>VUB}JWiDGmHI`bE&bz)+(%kxPzaKv;va zt$qqyK5XGd&^^#l8?(L-KrQSiUzvm-K^P06(wR(6w46#!Qokvh?XLQ|khqe=%7DX4 zF|283`LPovVywf4$!K@LhqY({ir59y;c4Zt6PoT z#pBjX^^vG7NvB#S%4op;D$Cao(+gQa>r&+sp_>_LMJ1lbOCttI{B_A8c!fy=cawU} zhDxhVf*Hwl^_#AZjp|JOuf#!g`^>e6QDp4Dl75S1kFZY`L>LV?|CQ##(8XNKc;-H& zoMs=k;Cs7FY4*L|Ja@aUYn#X=?q}0V#F<;Z6mF-|Yj!<0kQc9E{XtDNut9Ogt?GrS zOSqepHz$cxZaq`GQmUWcOT9Vjl&Uz>{v7#TI+|E1TEgERl&i!3Ij!%tn0ksvMSajM zL;^{#*PI+y&N}Jwxna&EG={B~-h|4$z1LcE=eZ?{09~wD`!>?v&s+9{Y#pm6D=6ED zTU!oqkhgLR7!xfC#eOWU&t9kb0gIuSpoc4>rYa}56UeCIiD_4Z9L_K4RODib9lTA( zD%-Ih(so}Pde^0-*oJ#gLSD*CIG=;MKPJFbviRbvAtkavcI!z@Wq6pk8M>A9$a4Oq zR3OPnR=1k`X;4q$#__qv23>wWw&M9BfXKAyv9t;nX#KUlB1ycHh^C`E6j4nicDX zo&DkK1BRiW!UWArTxb6tgo4 z>rInseW0Bcq1|`CncnW6UWKRY*6uHt`IG7OA}kLMA8?bT>Z-=VLY(-;c^jC<_wB4B zsYd#F-$hdqQ6MfT zbs2VW)nQCV1Uj_|{iISdsC2EfLeY##=xyHg>GRO2I2vREU7FMn!hPP{=!0A`)Qx}1 zhNzS{j#tM;_CF_X)=6^xjDQH6^TJE5bJ&#()Nj?45UaEmySqr&+*UHna7t#M-E@?s z2LvMqcGh#@*A_1SjZ795^a>MKC8F-Jq;BWVQKbx39i~^SUJ)UkYOI}YDU!J!1wt5cvMPDD1 z24o1{U-xDPtP8epwX1h)SJ5fT&#p|^5PIfMBsV;l;YsUMA*~c)Wso>hOiPrj=8m<2F&b#p74Jq}5Oq z7Slu8b?@GIpvr;<0A7pyPb~p1XEW|&=SP2*jm1GFh_Fb5P*rT7htd|?rNZT-VdRBa z@_cHe5vGM8NW|W4YBAD|`%s?_d{i1j!0GTPLiyXI`);}hJpEh5TmzXzv}K5(NdpX` zapk{B2Ky>TW9JaT=LI-K<9}@(@#2}*iCSn8v;EYVtmg#@I7giiqSxB2_H1i#poO91 z_iEdGWz~lKsGx25&s&1X>~3LR%?LGLjD%5F)4Hb+lM2cvuNI+AO8Rn%cMoY#LE9Ir; zNx&DAIY!PmbZ72B2>l#L82HIOX?;`LQVV^*x`z7L3mDs7Tut7BT5VDI`pxjR0J=>zJ;q>J0eJM7M^fCR*suQ&$!VWF zy}V**EH%(>T^-AL!HKUT*sdgOHWb#eMcnMyMS9soXnsRp$H&Lm$s^zRk_}MFiwRhfI zn=pzr(C3c@VUv&s&AJWksU1$gbK3`qKb3ghiR81QwNZt*y2H&R-yBs#(A-{2S(Z znJlU>I1D6?8hb%D>#RDD2D@5Bt6oI@+=BfP@I8ao7vnfWO`U2bFLkxg0;{rI1(E(=I|c?_rTwwb$S4MZD6m zx~i%FmXkw$!(1{_Aum)hj-~j&;Uu*spy8$TF+h-Kb#ZrE0P;r%`L5_OjYEw`-oz^Z zZ9}U}JB_}Iv8ctwbEMzR#OaDj?((|i7mZSCm#II@#vJ3!S;Xc!0LqF2%u!?aVoZGR zi%Om2RHQAI@xH|ga;_wtLTg`tM z91eFY9wzRBid8x8`SA3<+0=uvtL9$=k&@q360zeZE!V#=^0%bGKSa$xLtR$}kI+$T z!0Vp6eAbbB;>yNIZanjqN|y$oltBo^Ub@!1jCXQhhOsgTy3y5ofYzkvE@O_#Qq zSm|jcS2Io0cg0e?4)(@qe5p z*Jj!TIh2ZuRVHqC^jW5*E|pE3^Y;ExpJ-=igc21M$zI++#>l=FxzTo2_fUD{!{|R- z(QFWL`TMN!(&@MmS}|B>kIsZ8?hrNkf0VSZwQU-={mTaAMSy?!DLNgf4Q=I2fZKoT zuaYp^Hbr8`PMJDP9_W$rAFlD-#FK`SqvCIA|J}dQv1i$jj!g++_O8ub2gq7QDe($5 zJ)wz=$R+%ywy&*A(l7B<_z$Pd=uo-`s{mZT9O}R3 zAX-bE;+2w3NzbzZ=Wdhp%tU~Jmz#nhhKE>!JMN2^2Hk)nR^fm7hrfoCYk!O#ccDN0 zgrkB2KCzp`r}fIH)VJ4Z&vZ#Yd3CKujn-oiRRjD>%gu`~dwXSaFKRxM$OoM96%-qZ zaj5=V8Xg82d5I<6ZN5hD1JOdV4P&nRg|Yv&-`TuF00vINn-#v ze1yaO|DpC8#~AHP|H{qs@OEKO*Nz|uB~Wv05cZNtGA*T=z_lz6sUK?hL;D{y|A$M& zY_3~j$n%q-k(;_Ioau5U&7A2r4bX|L18WoG76*!R%gYJ3pX)g(82!Smg)vU*Xi;ad4!{Ka655Xyog=r>lWWGEdi6YGkg!ji;5E1M+Q4&h-u zxHS}t`Zyd!z`Pq6b@^vENd)hnoZ;3YG}j&SvF3PBcN5X@IOC|RLh4jKc9r6GrT5@= ztvfix?=?{pw7N}kuF6sZUQP=}niCK7eXuD^n!ER)zx=G^RfXF(Z9JmajkVvw|JuB$ z@vhhe1&=ZNDXCLqSWONBXi4=jVg_7*zY7i3Y5gIxht-1gIu*o)aiUxg*gZqHh>I3( zc{=&tQtm|Ql9GPI$9X`uKfg9)K|O%rFx;sI+c48ULv$WJ zwxoT!ra|MTKf{tse)jY6g~>~ckH=X_h-gKN>6>dmmL5cr0=W*1QM^(MDoU4SjRT%hi z9Hm5$32y%kame7FfA5h7&Za^8SZhZSBGVg5zg)5=+EsiWvP2xn71UtMYT-NSJ4D=O z%_4M5QELAF2f21#Tvsg%&Oe#bKX#7(=R*~TR3`#@MjQu1f)-~{hlKl2R__1F_wmDm z`h#K}Ev~!{4d-8kz964a|2@wqtGKl~3f%wPsQOoyz=$})dIH>ku3G;q`O~Mhn7>=G zsYk>8=K{>XXUa>8%dQs&eJY4Ms3*q#8&n^wpbj4#$;khn?bA|m99aVigmu|p|Nb97 CSNlc) diff --git a/VERSION b/VERSION index 0a7e926..a0fef3f 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -1.3.0 -VDB_v5.2 +1.4.0b +VDB_v6 diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.KEGG_Data_Scrapper.py b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.KEGG_Data_Scrapper.py new file mode 100644 index 0000000..e1f5f8f --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.KEGG_Data_Scrapper.py @@ -0,0 +1,165 @@ +from bs4 import BeautifulSoup +import pandas as pd +import re +import pickle +import ast +import requests + + +""" Script to download and parse KEGG information and store it in data """ + +def download_kegg_modules(module_name_file, chrome_driver): + module_ids =[] + module_names = {} + module_components_raw = {} + # Parse module names + with open(module_name_file) as module_input: + for line in module_input: + line = line.strip().split("\t") + module_ids.append(line[0]) + module_names[line[0]] = line[1] + # Access KEGG and download module information + for identifier in module_ids: + url = "https://www.kegg.jp/kegg-bin/show_module?" + identifier + site_request = requests.get(url) + soup = BeautifulSoup(site_request.text, "html.parser") + module_definition = "" + module_definition_bool = False + definition = soup.find(class_ = 'definition') + for line in (definition.text).splitlines(): + if line.strip() == "": + continue + elif module_definition_bool == True: + module_definition = line.strip() + module_definition_bool = False + elif line.strip() == 'Definition': + module_definition_bool = True + print(module_definition) + module_components_raw[identifier] = module_definition + return module_components_raw + + +def parse_regular_module_dictionary(bifurcating_list_file, structural_list_file, module_components_raw): + bifurcating_list = [] + structural_list = [] + # Populate bifurcating and structural lists + with open(bifurcating_list_file, 'r') as bif_list: + for line in bif_list: + bifurcating_list.append(line.strip()) + with open(structural_list_file, 'r') as bif_list: + for line in bif_list: + structural_list.append(line.strip()) + # Parse raw module information + module_steps_parsed = {} + for key, values in module_components_raw.items(): + values = values.replace(" --", "") + values = values.replace("-- ", "") + if key in bifurcating_list or key in structural_list: + continue + else: + module = [] + parenthesis_count = 0 + for character in values: + if character == "(": + parenthesis_count += 1 + module.append(character) + elif character == " ": + if parenthesis_count == 0: + module.append(character) + else: + module.append("_") + elif character == ")": + parenthesis_count -= 1 + module.append(character) + else: + module.append(character) + steps = ''.join(module).split() + module_steps_parsed[key] = steps + # Remove modules depending on other modules + temporal_dictionary = module_steps_parsed.copy() + for key, values in temporal_dictionary.items(): + for value in values: + if re.search(r'M[0-9]{5}', value) is not None: + del module_steps_parsed[key] + break + return module_steps_parsed + + +def create_final_regular_dictionary(module_steps_parsed, module_components_raw, outfile): + final_regular_dict = {} + # Parse module steps and export them into a text file + with open(outfile, 'w') as output: + for key, value in module_steps_parsed.items(): + output.write("{}\n".format(key)) + output.write("{}\n".format(module_components_raw[key])) + output.write("{}\n".format(value)) + output.write("{}\n".format("==")) + final_regular_dict[key] = {} + step_number = 0 + for step in value: + step_number += 1 + count = 0 + options = 0 + temp_string = "" + for char in step: + if char == "(": + count += 1 + options += 1 + if len(temp_string) > 1 and temp_string[-1] == "-": + temp_string += "%" + elif char == ")": + count -= 1 + if count >= 1: + temp_string += char + else: + continue + elif char == ",": + if count >= 2: + temp_string += char + print(step) + else: + temp_string += " " + else: + temp_string += char + if options >= 2: + temp_string = temp_string.replace(")_", "_") + if re.search('%.*\)', temp_string) is None: + temp_string = temp_string.replace(")", "") + temp_string = "".join(temp_string.rsplit("__", 1)) + temp_string = temp_string.split() + if isinstance(temp_string, str): + temp_string = temp_string.split() + temp_string = sorted(temp_string, key=len) + final_regular_dict[key][step_number] = temp_string + output.write("{}\n".format(temp_string)) + output.write("{}\n".format("++++++++++++++++++")) + return final_regular_dict + + +def export_module_dictionary(dictionary, location): + pickle_out = open(location,"wb") + pickle.dump(dictionary, pickle_out) + pickle_out.close() + + + +def transform_module_dictionaries(bifurcating_data, structural_data, output_bifur, output_struct): + bifurcating_dictionary = ast.literal_eval(open(bifurcating_data).read()) + export_module_dictionary(bifurcating_dictionary, output_bifur) + structural_dictionary = ast.literal_eval(open(structural_data).read()) + export_module_dictionary(structural_dictionary, output_struct) + + +# Execute parsing functions + +module_components_raw = download_kegg_modules("00.Module_Names.txt", 'chromedriver') +module_steps_parsed = parse_regular_module_dictionary("01.Bifurcating_List.txt", + "02.Structural_List.txt", module_components_raw) +final_regular_dict = create_final_regular_dictionary(module_steps_parsed, module_components_raw, "05.Modules_Parsed.txt") + + +export_module_dictionary(final_regular_dict, "../01.KEGG_Regular_Module_Information.pickle") +transform_module_dictionaries("03.Bifurcating_Modules.dict", + "04.Structural_Modules.dict", + "../02.KEGG_Bifurcating_Module_Information.pickle", + "../03.KEGG_Structural_Module_Information.pickle") \ No newline at end of file diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.Module_Names.txt b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.Module_Names.txt new file mode 100644 index 0000000..db9ec87 --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/00.Module_Names.txt @@ -0,0 +1,394 @@ +M00015 Proline biosynthesis, glutamate => proline Arginine and proline metabolism #8a3222 +M00028 Ornithine biosynthesis, glutamate => ornithine Arginine and proline metabolism #8a3222 +M00029 Urea cycle Arginine and proline metabolism #8a3222 +M00047 Creatine pathway Arginine and proline metabolism #8a3222 +M00763 Ornithine biosynthesis, mediated by LysW, glutamate => ornithine Arginine and proline metabolism #8a3222 +M00844 Arginine biosynthesis, ornithine => arginine Arginine and proline metabolism #8a3222 +M00845 Arginine biosynthesis, glutamate => acetylcitrulline => arginine Arginine and proline metabolism #8a3222 +M00879 Arginine succinyltransferase pathway, arginine => glutamate Arginine and proline metabolism #8a3222 +M00022 Shikimate pathway, phosphoenolpyruvate + erythrose-4P => chorismate Aromatic amino acid metabolism #8641b6 +M00023 Tryptophan biosynthesis, chorismate => tryptophan Aromatic amino acid metabolism #8641b6 +M00024 Phenylalanine biosynthesis, chorismate => phenylalanine Aromatic amino acid metabolism #8641b6 +M00025 Tyrosine biosynthesis, chorismate => tyrosine Aromatic amino acid metabolism #8641b6 +M00037 Melatonin biosynthesis, tryptophan => serotonin => melatonin Aromatic amino acid metabolism #8641b6 +M00038 Tryptophan metabolism, tryptophan => kynurenine => 2-aminomuconate Aromatic amino acid metabolism #8641b6 +M00040 Tyrosine biosynthesis, prephanate => pretyrosine => tyrosine Aromatic amino acid metabolism #8641b6 +M00042 Catecholamine biosynthesis, tyrosine => dopamine => noradrenaline => adrenaline Aromatic amino acid metabolism #8641b6 +M00043 Thyroid hormone biosynthesis, tyrosine => triiodothyronine--thyroxine Aromatic amino acid metabolism #8641b6 +M00044 Tyrosine degradation, tyrosine => homogentisate Aromatic amino acid metabolism #8641b6 +M00533 Homoprotocatechuate degradation, homoprotocatechuate => 2-oxohept-3-enedioate Aromatic amino acid metabolism #8641b6 +M00545 Trans-cinnamate degradation, trans-cinnamate => acetyl-CoA Aromatic amino acid metabolism #8641b6 +M00418 Toluene degradation, anaerobic, toluene => benzoyl-CoA Aromatics degradation #76d25b +M00419 Cymene degradation, p-cymene => p-cumate Aromatics degradation #76d25b +M00534 Naphthalene degradation, naphthalene => salicylate Aromatics degradation #76d25b +M00537 Xylene degradation, xylene => methylbenzoate Aromatics degradation #76d25b +M00538 Toluene degradation, toluene => benzoate Aromatics degradation #76d25b +M00539 Cumate degradation, p-cumate => 2-oxopent-4-enoate + 2-methylpropanoate Aromatics degradation #76d25b +M00540 Benzoate degradation, cyclohexanecarboxylic acid =>pimeloyl-CoA Aromatics degradation #76d25b +M00541 Benzoyl-CoA degradation, benzoyl-CoA => 3-hydroxypimeloyl-CoA Aromatics degradation #76d25b +M00543 Biphenyl degradation, biphenyl => 2-oxopent-4-enoate + benzoate Aromatics degradation #76d25b +M00544 Carbazole degradation, carbazole => 2-oxopent-4-enoate + anthranilate Aromatics degradation #76d25b +M00547 Benzene--toluene degradation, benzene => catechol -- toluene => 3-methylcatechol Aromatics degradation #76d25b +M00548 Benzene degradation, benzene => catechol Aromatics degradation #76d25b +M00551 Benzoate degradation, benzoate => catechol -- methylbenzoate => methylcatechol Aromatics degradation #76d25b +M00568 Catechol ortho-cleavage, catechol => 3-oxoadipate Aromatics degradation #76d25b +M00569 Catechol meta-cleavage, catechol => acetyl-CoA -- 4-methylcatechol => propanoyl-CoA Aromatics degradation #76d25b +M00623 Phthalate degradation 1, phthalate => protocatechuate Aromatics degradation #76d25b +M00624 Terephthalate degradation, terephthalate => 3,4-dihydroxybenzoate Aromatics degradation #76d25b +M00636 Phthalate degradation 2, phthalate => protocatechuate Aromatics degradation #76d25b +M00637 Anthranilate degradation, anthranilate => catechol Aromatics degradation #76d25b +M00638 Salicylate degradation, salicylate => gentisate Aromatics degradation #76d25b +M00878 Phenylacetate degradation, phenylaxetate => acetyl-CoA--succinyl-CoA Aromatics degradation #76d25b +M00142 NADH:ubiquinone oxidoreductase, mitochondria ATP synthesis #cdd346 +M00143 NADH dehydrogenase (ubiquinone) Fe-S protein--flavoprotein complex, mitochondria ATP synthesis #cdd346 +M00144 NADH:quinone oxidoreductase, prokaryotes ATP synthesis #cdd346 +M00145 NAD(P)H:quinone oxidoreductase, chloroplasts and cyanobacteria ATP synthesis #cdd346 +M00146 NADH dehydrogenase (ubiquinone) 1 alpha subcomplex ATP synthesis #cdd346 +M00147 NADH dehydrogenase (ubiquinone) 1 beta subcomplex ATP synthesis #cdd346 +M00148 Succinate dehydrogenase (ubiquinone) ATP synthesis #cdd346 +M00149 Succinate dehydrogenase, prokaryotes ATP synthesis #cdd346 +M00150 Fumarate reductase, prokaryotes ATP synthesis #cdd346 +M00151 Cytochrome bc1 complex respiratory unit ATP synthesis #cdd346 +M00152 Cytochrome bc1 complex ATP synthesis #cdd346 +M00153 Cytochrome bd ubiquinol oxidase ATP synthesis #cdd346 +M00154 Cytochrome c oxidase ATP synthesis #cdd346 +M00155 Cytochrome c oxidase, prokaryotes ATP synthesis #cdd346 +M00156 Cytochrome c oxidase, cbb3-type ATP synthesis #cdd346 +M00157 F-type ATPase, prokaryotes and chloroplasts ATP synthesis #cdd346 +M00158 F-type ATPase, eukaryotes ATP synthesis #cdd346 +M00159 V-type ATPase, prokaryotes ATP synthesis #cdd346 +M00160 V-type ATPase, eukaryotes ATP synthesis #cdd346 +M00162 Cytochrome b6f complex ATP synthesis #cdd346 +M00416 Cytochrome aa3-600 menaquinol oxidase ATP synthesis #cdd346 +M00417 Cytochrome o ubiquinol oxidase ATP synthesis #cdd346 +M00672 Penicillin biosynthesis, aminoadipate + cycteine + valine => penicillin Beta-Lactam biosynthesis #3b2882 +M00673 Cephamycin C biosynthesis, aminoadipate + cycteine + valine => cephamycin C Beta-Lactam biosynthesis #3b2882 +M00674 Clavaminate biosynthesis, arginine + glyceraldehyde-3P => clavaminate Beta-Lactam biosynthesis #3b2882 +M00675 Carbapenem-3-carboxylate biosynthesis, pyrroline-5-carboxylate + malonyl-CoA => carbapenem-3-carboxylate Beta-Lactam biosynthesis #3b2882 +M00736 Nocardicin A biosynthesis, L-pHPG + arginine + serine => nocardicin A Beta-Lactam biosynthesis #3b2882 +M00039 Monolignol biosynthesis, phenylalanine--tyrosine => monolignol Biosynthesis of other secondary metabolites #cbde82 +M00137 Flavanone biosynthesis, phenylalanine => naringenin Biosynthesis of other secondary metabolites #cbde82 +M00138 Flavonoid biosynthesis, naringenin => pelargonidin Biosynthesis of other secondary metabolites #cbde82 +M00370 Glucosinolate biosynthesis, tryptophan => glucobrassicin Biosynthesis of other secondary metabolites #cbde82 +M00661 Paspaline biosynthesis, geranylgeranyl-PP + indoleglycerol phosphate => paspaline Biosynthesis of other secondary metabolites #cbde82 +M00785 Cycloserine biosynthesis, arginine--serine => cycloserine Biosynthesis of other secondary metabolites #cbde82 +M00786 Fumitremorgin alkaloid biosynthesis, tryptophan + proline => fumitremorgin C--A Biosynthesis of other secondary metabolites #cbde82 +M00787 Bacilysin biosynthesis, prephenate => bacilysin Biosynthesis of other secondary metabolites #cbde82 +M00788 Terpentecin biosynthesis, GGAP => terpentecin Biosynthesis of other secondary metabolites #cbde82 +M00789 Rebeccamycin biosynthesis, tryptophan => rebeccamycin Biosynthesis of other secondary metabolites #cbde82 +M00790 Pyrrolnitrin biosynthesis, tryptophan => pyrrolnitrin Biosynthesis of other secondary metabolites #cbde82 +M00805 Staurosporine biosynthesis, tryptophan => staurosporine Biosynthesis of other secondary metabolites #cbde82 +M00808 Violacein biosynthesis, tryptophan => violacein Biosynthesis of other secondary metabolites #cbde82 +M00814 Acarbose biosynthesis, sedoheptulopyranose-7P => acarbose Biosynthesis of other secondary metabolites #cbde82 +M00815 Validamycin A biosynthesis, sedoheptulopyranose-7P => validamycin A Biosynthesis of other secondary metabolites #cbde82 +M00819 Pentalenolactone biosynthesis, farnesyl-PP => pentalenolactone Biosynthesis of other secondary metabolites #cbde82 +M00835 Pyocyanine biosynthesis, chorismate => pyocyanine Biosynthesis of other secondary metabolites #cbde82 +M00837 Prodigiosin biosynthesis, L-proline => prodigiosin Biosynthesis of other secondary metabolites #cbde82 +M00838 Undecylprodigiosin biosynthesis, L-proline => undecylprodigiosin Biosynthesis of other secondary metabolites #cbde82 +M00848 Aurachin biosynthesis, anthranilate => aurachin A Biosynthesis of other secondary metabolites #cbde82 +M00875 Staphyloferrin B biosynthesis, L-serine => staphyloferrin B Biosynthesis of other secondary metabolites #cbde82 +M00876 Staphyloferrin A biosynthesis, L-ornithine => staphyloferrin A Biosynthesis of other secondary metabolites #cbde82 +M00877 Kanosamine biosynthesis glucose 6-phosphate => kanosamine Biosynthesis of other secondary metabolites #cbde82 +M00019 Valine--isoleucine biosynthesis, pyruvate => valine -- 2-oxobutanoate => isoleucine Branched-chain amino acid metabolism #656cdb +M00036 Leucine degradation, leucine => acetoacetate + acetyl-CoA Branched-chain amino acid metabolism #656cdb +M00432 Leucine biosynthesis, 2-oxoisovalerate => 2-oxoisocaproate Branched-chain amino acid metabolism #656cdb +M00535 Isoleucine biosynthesis, pyruvate => 2-oxobutanoate Branched-chain amino acid metabolism #656cdb +M00570 Isoleucine biosynthesis, threonine => 2-oxobutanoate => isoleucine Branched-chain amino acid metabolism #656cdb +M00165 Reductive pentose phosphate cycle (Calvin cycle) Carbon fixation #408937 +M00166 Reductive pentose phosphate cycle, ribulose-5P => glyceraldehyde-3P Carbon fixation #408937 +M00167 Reductive pentose phosphate cycle, glyceraldehyde-3P => ribulose-5P Carbon fixation #408937 +M00168 CAM (Crassulacean acid metabolism), dark Carbon fixation #408937 +M00169 CAM (Crassulacean acid metabolism), light Carbon fixation #408937 +M00170 C4-dicarboxylic acid cycle, phosphoenolpyruvate carboxykinase type Carbon fixation #408937 +M00171 C4-dicarboxylic acid cycle, NAD - malic enzyme type Carbon fixation #408937 +M00172 C4-dicarboxylic acid cycle, NADP - malic enzyme type Carbon fixation #408937 +M00173 Reductive citrate cycle (Arnon-Buchanan cycle) Carbon fixation #408937 +M00374 Dicarboxylate-hydroxybutyrate cycle Carbon fixation #408937 +M00375 Hydroxypropionate-hydroxybutylate cycle Carbon fixation #408937 +M00376 3-Hydroxypropionate bi-cycle Carbon fixation #408937 +M00377 Reductive acetyl-CoA pathway (Wood-Ljungdahl pathway) Carbon fixation #408937 +M00579 Phosphate acetyltransferase-acetate kinase pathway, acetyl-CoA => acetate Carbon fixation #408937 +M00620 Incomplete reductive citrate cycle, acetyl-CoA => oxoglutarate Carbon fixation #408937 +M00001 Glycolysis (Embden-Meyerhof pathway), glucose => pyruvate Central carbohydrate metabolism #c644a5 +M00002 Glycolysis, core module involving three-carbon compounds Central carbohydrate metabolism #c644a5 +M00003 Gluconeogenesis, oxaloacetate => fructose-6P Central carbohydrate metabolism #c644a5 +M00004 Pentose phosphate pathway (Pentose phosphate cycle) Central carbohydrate metabolism #c644a5 +M00005 PRPP biosynthesis, ribose 5P => PRPP Central carbohydrate metabolism #c644a5 +M00006 Pentose phosphate pathway, oxidative phase, glucose 6P => ribulose 5P Central carbohydrate metabolism #c644a5 +M00007 Pentose phosphate pathway, non-oxidative phase, fructose 6P => ribose 5P Central carbohydrate metabolism #c644a5 +M00008 Entner-Doudoroff pathway, glucose-6P => glyceraldehyde-3P + pyruvate Central carbohydrate metabolism #c644a5 +M00009 Citrate cycle (TCA cycle, Krebs cycle) Central carbohydrate metabolism #c644a5 +M00010 Citrate cycle, first carbon oxidation, oxaloacetate => 2-oxoglutarate Central carbohydrate metabolism #c644a5 +M00011 Citrate cycle, second carbon oxidation, 2-oxoglutarate => oxaloacetate Central carbohydrate metabolism #c644a5 +M00307 Pyruvate oxidation, pyruvate => acetyl-CoA Central carbohydrate metabolism #c644a5 +M00308 Semi-phosphorylative Entner-Doudoroff pathway, gluconate => glycerate-3P Central carbohydrate metabolism #c644a5 +M00309 Non-phosphorylative Entner-Doudoroff pathway, gluconate--galactonate => glycerate Central carbohydrate metabolism #c644a5 +M00580 Pentose phosphate pathway, archaea, fructose 6P => ribose 5P Central carbohydrate metabolism #c644a5 +M00633 Semi-phosphorylative Entner-Doudoroff pathway, gluconate--galactonate => glycerate-3P Central carbohydrate metabolism #c644a5 +M00112 Tocopherol--tocotorienol biosynthesis Cofactor and vitamin metabolism #5fda98 +M00115 NAD biosynthesis, aspartate => NAD Cofactor and vitamin metabolism #5fda98 +M00116 Menaquinone biosynthesis, chorismate => menaquinol Cofactor and vitamin metabolism #5fda98 +M00117 Ubiquinone biosynthesis, prokaryotes, chorismate => ubiquinone Cofactor and vitamin metabolism #5fda98 +M00119 Pantothenate biosynthesis, valine--L-aspartate => pantothenate Cofactor and vitamin metabolism #5fda98 +M00120 Coenzyme A biosynthesis, pantothenate => CoA Cofactor and vitamin metabolism #5fda98 +M00121 Heme biosynthesis, plants and bacteria, glutamate => heme Cofactor and vitamin metabolism #5fda98 +M00122 Cobalamin biosynthesis, cobinamide => cobalamin Cofactor and vitamin metabolism #5fda98 +M00123 Biotin biosynthesis, pimeloyl-ACP--CoA => biotin Cofactor and vitamin metabolism #5fda98 +M00124 Pyridoxal biosynthesis, erythrose-4P => pyridoxal-5P Cofactor and vitamin metabolism #5fda98 +M00125 Riboflavin biosynthesis, GTP => riboflavin--FMN--FAD Cofactor and vitamin metabolism #5fda98 +M00126 Tetrahydrofolate biosynthesis, GTP => THF Cofactor and vitamin metabolism #5fda98 +M00127 Thiamine biosynthesis, AIR => thiamine-P--thiamine-2P Cofactor and vitamin metabolism #5fda98 +M00128 Ubiquinone biosynthesis, eukaryotes, 4-hydroxybenzoate => ubiquinone Cofactor and vitamin metabolism #5fda98 +M00140 C1-unit interconversion, prokaryotes Cofactor and vitamin metabolism #5fda98 +M00141 C1-unit interconversion, eukaryotes Cofactor and vitamin metabolism #5fda98 +M00572 Pimeloyl-ACP biosynthesis, BioC-BioH pathway, malonyl-ACP => pimeloyl-ACP Cofactor and vitamin metabolism #5fda98 +M00573 Biotin biosynthesis, BioI pathway, long-chain-acyl-ACP => pimeloyl-ACP => biotin Cofactor and vitamin metabolism #5fda98 +M00577 Biotin biosynthesis, BioW pathway, pimelate => pimeloyl-CoA => biotin Cofactor and vitamin metabolism #5fda98 +M00622 Nicotinate degradation, nicotinate => fumarate Cofactor and vitamin metabolism #5fda98 +M00810 Nicotine degradation, pyridine pathway, nicotine => 2,6-dihydroxypyridine--succinate semialdehyde Cofactor and vitamin metabolism #5fda98 +M00811 Nicotine degradation, pyrrolidine pathway, nicotine => succinate semialdehyde Cofactor and vitamin metabolism #5fda98 +M00836 Coenzyme F430 biosynthesis, sirohydrochlorin => coenzyme F430 Cofactor and vitamin metabolism #5fda98 +M00840 Tetrahydrofolate biosynthesis, mediated by ribA and trpF, GTP => THF Cofactor and vitamin metabolism #5fda98 +M00841 Tetrahydrofolate biosynthesis, mediated by PTPS, GTP => THF Cofactor and vitamin metabolism #5fda98 +M00842 Tetrahydrobiopterin biosynthesis, GTP => BH4 Cofactor and vitamin metabolism #5fda98 +M00843 L-threo-Tetrahydrobiopterin biosynthesis, GTP => L-threo-BH4 Cofactor and vitamin metabolism #5fda98 +M00846 Siroheme biosynthesis, glutamate => siroheme Cofactor and vitamin metabolism #5fda98 +M00847 Heme biosynthesis, archaea, siroheme => heme Cofactor and vitamin metabolism #5fda98 +M00868 Heme biosynthesis, animals and fungi, glycine => heme Cofactor and vitamin metabolism #5fda98 +M00880 Molybdenum cofactor biosynthesis, GTP => molybdenum cofactor Cofactor and vitamin metabolism #5fda98 +M00017 Methionine biosynthesis, apartate => homoserine => methionine Cysteine and methionine metabolism #782975 +M00021 Cysteine biosynthesis, serine => cysteine Cysteine and methionine metabolism #782975 +M00034 Methionine salvage pathway Cysteine and methionine metabolism #782975 +M00035 Methionine degradation Cysteine and methionine metabolism #782975 +M00338 Cysteine biosynthesis, homocysteine + serine => cysteine Cysteine and methionine metabolism #782975 +M00368 Ethylene biosynthesis, methionine => ethylene Cysteine and methionine metabolism #782975 +M00609 Cysteine biosynthesis, methionine => cysteine Cysteine and methionine metabolism #782975 +M00625 Methicillin resistance Drug resistance #869534 +M00627 beta-Lactam resistance, Bla system Drug resistance #869534 +M00639 Multidrug resistance, efflux pump MexCD-OprJ Drug resistance #869534 +M00641 Multidrug resistance, efflux pump MexEF-OprN Drug resistance #869534 +M00642 Multidrug resistance, efflux pump MexJK-OprM Drug resistance #869534 +M00643 Multidrug resistance, efflux pump MexXY-OprM Drug resistance #869534 +M00649 Multidrug resistance, efflux pump AdeABC Drug resistance #869534 +M00651 Vancomycin resistance, D-Ala-D-Lac type Drug resistance #869534 +M00652 Vancomycin resistance, D-Ala-D-Ser type Drug resistance #869534 +M00696 Multidrug resistance, efflux pump AcrEF-TolC Drug resistance #869534 +M00697 Multidrug resistance, efflux pump MdtEF-TolC Drug resistance #869534 +M00698 Multidrug resistance, efflux pump BpeEF-OprC Drug resistance #869534 +M00700 Multidrug resistance, efflux pump AbcA Drug resistance #869534 +M00702 Multidrug resistance, efflux pump NorB Drug resistance #869534 +M00704 Tetracycline resistance, efflux pump Tet38 Drug resistance #869534 +M00705 Multidrug resistance, efflux pump MepA Drug resistance #869534 +M00714 Multidrug resistance, efflux pump QacA Drug resistance #869534 +M00718 Multidrug resistance, efflux pump MexAB-OprM Drug resistance #869534 +M00725 Cationic antimicrobial peptide (CAMP) resistance, dltABCD operon Drug resistance #869534 +M00726 Cationic antimicrobial peptide (CAMP) resistance, lysyl-phosphatidylglycerol (L-PG) synthase MprF Drug resistance #869534 +M00730 Cationic antimicrobial peptide (CAMP) resistance, VraFG transporter Drug resistance #869534 +M00744 Cationic antimicrobial peptide (CAMP) resistance, protease PgtE Drug resistance #869534 +M00745 Imipenem resistance, repression of porin OprD Drug resistance #869534 +M00746 Multidrug resistance, repression of porin OmpF Drug resistance #869534 +M00769 Multidrug resistance, efflux pump MexPQ-OpmE Drug resistance #869534 +M00851 Carbapenem resistance Drug resistance #869534 +M00824 9-membered enediyne core biosynthesis, malonyl-CoA => 3-hydroxyhexadeca-4,6,8,10,12,14-hexaenoyl-ACP => 9-membered enediyne core Enediyne biosynthesis #d27bde +M00825 10-membered enediyne core biosynthesis, malonyl-CoA => 3-hydroxyhexadeca-4,6,8,10,12,14-hexaenoyl-ACP => 10-membered enediyne core Enediyne biosynthesis #d27bde +M00826 C-1027 benzoxazolinate moiety biosynthesis, chorismate => benzoxazolinyl-CoA Enediyne biosynthesis #d27bde +M00827 C-1027 beta-amino acid moiety biosynthesis, tyrosine => 3-chloro-4,5-dihydroxy-beta-phenylalanyl-PCP Enediyne biosynthesis #d27bde +M00828 Maduropeptin beta-hydroxy acid moiety biosynthesis, tyrosine => 3-(4-hydroxyphenyl)-3-oxopropanoyl-PCP Enediyne biosynthesis #d27bde +M00829 3,6-Dimethylsalicylyl-CoA biosynthesis, malonyl-CoA => 6-methylsalicylate => 3,6-dimethylsalicylyl-CoA Enediyne biosynthesis #d27bde +M00830 Neocarzinostatin naphthoate moiety biosynthesis, malonyl-CoA => 2-hydroxy-5-methyl-1-naphthoate => 2-hydroxy-7-methoxy-5-methyl-1-naphthoyl-CoA Enediyne biosynthesis #d27bde +M00831 Kedarcidin 2-hydroxynaphthoate moiety biosynthesis, malonyl-CoA => 3,6,8-trihydroxy-2-naphthoate => 3-hydroxy-7,8-dimethoxy-6-isopropoxy-2-naphthoyl-CoA Enediyne biosynthesis #d27bde +M00832 Kedarcidin 2-aza-3-chloro-beta-tyrosine moiety biosynthesis, azatyrosine => 2-aza-3-chloro-beta-tyrosyl-PCP Enediyne biosynthesis #d27bde +M00833 Calicheamicin biosynthesis, calicheamicinone => calicheamicin Enediyne biosynthesis #d27bde +M00834 Calicheamicin orsellinate moiety biosynthesis, malonyl-CoA => orsellinate-ACP => 5-iodo-2,3-dimethoxyorsellinate-ACP Enediyne biosynthesis #d27bde +M00082 Fatty acid biosynthesis, initiation Fatty acid metabolism #d9a344 +M00083 Fatty acid biosynthesis, elongation Fatty acid metabolism #d9a344 +M00085 Fatty acid elongation in mitochondria Fatty acid metabolism #d9a344 +M00086 beta-Oxidation, acyl-CoA synthesis Fatty acid metabolism #d9a344 +M00087 beta-Oxidation Fatty acid metabolism #d9a344 +M00415 Fatty acid elongation in endoplasmic reticulum Fatty acid metabolism #d9a344 +M00861 beta-Oxidation, peroxisome, VLCFA Fatty acid metabolism #d9a344 +M00873 Fatty acid biosynthesis in mitochondria, animals Fatty acid metabolism #d9a344 +M00874 Fatty acid biosynthesis in mitochondria, fungi Fatty acid metabolism #d9a344 +M00055 N-glycan precursor biosynthesis Glycan biosynthesis #588cd6 +M00056 O-glycan biosynthesis, mucin type core Glycan biosynthesis #588cd6 +M00065 GPI-anchor biosynthesis, core oligosaccharide Glycan biosynthesis #588cd6 +M00068 Glycosphingolipid biosynthesis, globo-series, LacCer => Gb4Cer Glycan biosynthesis #588cd6 +M00069 Glycosphingolipid biosynthesis, ganglio series, LacCer => GT3 Glycan biosynthesis #588cd6 +M00070 Glycosphingolipid biosynthesis, lacto-series, LacCer => Lc4Cer Glycan biosynthesis #588cd6 +M00071 Glycosphingolipid biosynthesis, neolacto-series, LacCer => nLc4Cer Glycan biosynthesis #588cd6 +M00072 N-glycosylation by oligosaccharyltransferase Glycan biosynthesis #588cd6 +M00073 N-glycan precursor trimming Glycan biosynthesis #588cd6 +M00074 N-glycan biosynthesis, high-mannose type Glycan biosynthesis #588cd6 +M00075 N-glycan biosynthesis, complex type Glycan biosynthesis #588cd6 +M00872 O-glycan biosynthesis, mannose type (core M3) Glycan biosynthesis #588cd6 +M00057 Glycosaminoglycan biosynthesis, linkage tetrasaccharide Glycosaminoglycan metabolism #d66432 +M00058 Glycosaminoglycan biosynthesis, chondroitin sulfate backbone Glycosaminoglycan metabolism #d66432 +M00059 Glycosaminoglycan biosynthesis, heparan sulfate backbone Glycosaminoglycan metabolism #d66432 +M00076 Dermatan sulfate degradation Glycosaminoglycan metabolism #d66432 +M00077 Chondroitin sulfate degradation Glycosaminoglycan metabolism #d66432 +M00078 Heparan sulfate degradation Glycosaminoglycan metabolism #d66432 +M00079 Keratan sulfate degradation Glycosaminoglycan metabolism #d66432 +M00026 Histidine biosynthesis, PRPP => histidine Histidine metabolism #66d7bf +M00045 Histidine degradation, histidine => N-formiminoglutamate => glutamate Histidine metabolism #66d7bf +M00066 Lactosylceramide biosynthesis Lipid metabolism #d53e55 +M00067 Sulfoglycolipids biosynthesis, ceramide--1-alkyl-2-acylglycerol => sulfatide--seminolipid Lipid metabolism #d53e55 +M00088 Ketone body biosynthesis, acetyl-CoA => acetoacetate--3-hydroxybutyrate--acetone Lipid metabolism #d53e55 +M00089 Triacylglycerol biosynthesis Lipid metabolism #d53e55 +M00090 Phosphatidylcholine (PC) biosynthesis, choline => PC Lipid metabolism #d53e55 +M00091 Phosphatidylcholine (PC) biosynthesis, PE => PC Lipid metabolism #d53e55 +M00092 Phosphatidylethanolamine (PE) biosynthesis, ethanolamine => PE Lipid metabolism #d53e55 +M00093 Phosphatidylethanolamine (PE) biosynthesis, PA => PS => PE Lipid metabolism #d53e55 +M00094 Ceramide biosynthesis Lipid metabolism #d53e55 +M00098 Acylglycerol degradation Lipid metabolism #d53e55 +M00099 Sphingosine biosynthesis Lipid metabolism #d53e55 +M00100 Sphingosine degradation Lipid metabolism #d53e55 +M00113 Jasmonic acid biosynthesis Lipid metabolism #d53e55 +M00060 KDO2-lipid A biosynthesis, Raetz pathway, LpxL-LpxM type Lipopolysaccharide metabolism #83d2de +M00063 CMP-KDO biosynthesis Lipopolysaccharide metabolism #83d2de +M00064 ADP-L-glycero-D-manno-heptose biosynthesis Lipopolysaccharide metabolism #83d2de +M00866 KDO2-lipid A biosynthesis, Raetz pathway, non-LpxL-LpxM type Lipopolysaccharide metabolism #83d2de +M00867 KDO2-lipid A modification pathway Lipopolysaccharide metabolism #83d2de +M00016 Lysine biosynthesis, succinyl-DAP pathway, aspartate => lysine Lysine metabolism #d84e8b +M00030 Lysine biosynthesis, AAA pathway, 2-oxoglutarate => 2-aminoadipate => lysine Lysine metabolism #d84e8b +M00031 Lysine biosynthesis, mediated by LysW, 2-aminoadipate => lysine Lysine metabolism #d84e8b +M00032 Lysine degradation, lysine => saccharopine => acetoacetyl-CoA Lysine metabolism #d84e8b +M00433 Lysine biosynthesis, 2-oxoglutarate => 2-oxoadipate Lysine metabolism #d84e8b +M00525 Lysine biosynthesis, acetyl-DAP pathway, aspartate => lysine Lysine metabolism #d84e8b +M00526 Lysine biosynthesis, DAP dehydrogenase pathway, aspartate => lysine Lysine metabolism #d84e8b +M00527 Lysine biosynthesis, DAP aminotransferase pathway, aspartate => lysine Lysine metabolism #d84e8b +M00773 Tylosin biosynthesis, methylmalonyl-CoA + malonyl-CoA => tylactone => tylosin Macrolide biosynthesis #2e4b26 +M00774 Erythromycin biosynthesis, propanoyl-CoA + methylmalonyl-CoA => deoxyerythronolide B => erythromycin A--B Macrolide biosynthesis #2e4b26 +M00775 Oleandomycin biosynthesis, malonyl-CoA + methylmalonyl-CoA => 8,8a-deoxyoleandolide => oleandomycin Macrolide biosynthesis #2e4b26 +M00776 Pikromycin--methymycin biosynthesis, methylmalonyl-CoA + malonyl-CoA => narbonolide--10-deoxymethynolide => pikromycin--methymycin Macrolide biosynthesis #2e4b26 +M00777 Avermectin biosynthesis, 2-methylbutanoyl-CoA--isobutyryl-CoA => 6,8a-Seco-6,8a-deoxy-5-oxoavermectin 1a--1b aglycone => avermectin A1a--B1a--A1b--B1b Macrolide biosynthesis #2e4b26 +M00611 Oxygenic photosynthesis in plants and cyanobacteria Metabolic capacity #9378c3 +M00612 Anoxygenic photosynthesis in purple bacteria Metabolic capacity #9378c3 +M00613 Anoxygenic photosynthesis in green nonsulfur bacteria Metabolic capacity #9378c3 +M00614 Anoxygenic photosynthesis in green sulfur bacteria Metabolic capacity #9378c3 +M00615 Nitrate assimilation Metabolic capacity #9378c3 +M00616 Sulfate-sulfur assimilation Metabolic capacity #9378c3 +M00617 Methanogen Metabolic capacity #9378c3 +M00618 Acetogen Metabolic capacity #9378c3 +M00174 Methane oxidation, methanotroph, methane => formaldehyde Methane metabolism #9e7336 +M00344 Formaldehyde assimilation, xylulose monophosphate pathway Methane metabolism #9e7336 +M00345 Formaldehyde assimilation, ribulose monophosphate pathway Methane metabolism #9e7336 +M00346 Formaldehyde assimilation, serine pathway Methane metabolism #9e7336 +M00356 Methanogenesis, methanol => methane Methane metabolism #9e7336 +M00357 Methanogenesis, acetate => methane Methane metabolism #9e7336 +M00358 Coenzyme M biosynthesis Methane metabolism #9e7336 +M00378 F420 biosynthesis Methane metabolism #9e7336 +M00422 Acetyl-CoA pathway, CO2 => acetyl-CoA Methane metabolism #9e7336 +M00563 Methanogenesis, methylamine--dimethylamine--trimethylamine => methane Methane metabolism #9e7336 +M00567 Methanogenesis, CO2 => methane Methane metabolism #9e7336 +M00608 2-Oxocarboxylic acid chain extension, 2-oxoglutarate => 2-oxoadipate => 2-oxopimelate => 2-oxosuberate Methane metabolism #9e7336 +M00175 Nitrogen fixation, nitrogen => ammonia Nitrogen metabolism #2c2351 +M00528 Nitrification, ammonia => nitrite Nitrogen metabolism #2c2351 +M00529 Denitrification, nitrate => nitrogen Nitrogen metabolism #2c2351 +M00530 Dissimilatory nitrate reduction, nitrate => ammonia Nitrogen metabolism #2c2351 +M00531 Assimilatory nitrate reduction, nitrate => ammonia Nitrogen metabolism #2c2351 +M00804 Complete nitrification, comammox, ammonia => nitrite => nitrate Nitrogen metabolism #2c2351 +M00027 GABA (gamma-Aminobutyrate) shunt Other amino acid metabolism #c5d7a9 +M00118 Glutathione biosynthesis, glutamate => glutathione Other amino acid metabolism #c5d7a9 +M00369 Cyanogenic glycoside biosynthesis, tyrosine => dhurrin Other amino acid metabolism #c5d7a9 +M00012 Glyoxylate cycle Other carbohydrate metabolism #872b4e +M00013 Malonate semialdehyde pathway, propanoyl-CoA => acetyl-CoA Other carbohydrate metabolism #872b4e +M00014 Glucuronate pathway (uronate pathway) Other carbohydrate metabolism #872b4e +M00061 D-Glucuronate degradation, D-glucuronate => pyruvate + D-glyceraldehyde 3P Other carbohydrate metabolism #872b4e +M00081 Pectin degradation Other carbohydrate metabolism #872b4e +M00114 Ascorbate biosynthesis, plants, glucose-6P => ascorbate Other carbohydrate metabolism #872b4e +M00129 Ascorbate biosynthesis, animals, glucose-1P => ascorbate Other carbohydrate metabolism #872b4e +M00130 Inositol phosphate metabolism, PI=> PIP2 => Ins(1,4,5)P3 => Ins(1,3,4,5)P4 Other carbohydrate metabolism #872b4e +M00131 Inositol phosphate metabolism, Ins(1,3,4,5)P4 => Ins(1,3,4)P3 => myo-inositol Other carbohydrate metabolism #872b4e +M00132 Inositol phosphate metabolism, Ins(1,3,4)P3 => phytate Other carbohydrate metabolism #872b4e +M00373 Ethylmalonyl pathway Other carbohydrate metabolism #872b4e +M00532 Photorespiration Other carbohydrate metabolism #872b4e +M00549 Nucleotide sugar biosynthesis, glucose => UDP-glucose Other carbohydrate metabolism #872b4e +M00550 Ascorbate degradation, ascorbate => D-xylulose-5P Other carbohydrate metabolism #872b4e +M00552 D-galactonate degradation, De Ley-Doudoroff pathway, D-galactonate => glycerate-3P Other carbohydrate metabolism #872b4e +M00554 Nucleotide sugar biosynthesis, galactose => UDP-galactose Other carbohydrate metabolism #872b4e +M00565 Trehalose biosynthesis, D-glucose 1P => trehalose Other carbohydrate metabolism #872b4e +M00630 D-Galacturonate degradation (fungi), D-galacturonate => glycerol Other carbohydrate metabolism #872b4e +M00631 D-Galacturonate degradation (bacteria), D-galacturonate => pyruvate + D-glyceraldehyde 3P Other carbohydrate metabolism #872b4e +M00632 Galactose degradation, Leloir pathway, galactose => alpha-D-glucose-1P Other carbohydrate metabolism #872b4e +M00740 Methylaspartate cycle Other carbohydrate metabolism #872b4e +M00741 Propanoyl-CoA metabolism, propanoyl-CoA => succinyl-CoA Other carbohydrate metabolism #872b4e +M00761 Undecaprenylphosphate alpha-L-Ara4N biosynthesis, UDP-GlcA => undecaprenyl phosphate alpha-L-Ara4N Other carbohydrate metabolism #872b4e +M00854 Glycogen biosynthesis, glucose-1P => glycogen--starch Other carbohydrate metabolism #872b4e +M00855 Glycogen degradation, glycogen => glucose-6P Other carbohydrate metabolism #872b4e +M00097 beta-Carotene biosynthesis, GGAP => beta-carotene Other terpenoid biosynthesis #6e9368 +M00371 Castasterone biosynthesis, campesterol => castasterone Other terpenoid biosynthesis #6e9368 +M00372 Abscisic acid biosynthesis, beta-carotene => abscisic acid Other terpenoid biosynthesis #6e9368 +M00363 EHEC pathogenicity signature, Shiga toxin Pathogenicity #66406d +M00542 EHEC--EPEC pathogenicity signature, T3SS and effectors Pathogenicity #66406d +M00564 Helicobacter pylori pathogenicity signature, cagA pathogenicity island Pathogenicity #66406d +M00574 Pertussis pathogenicity signature, pertussis toxin Pathogenicity #66406d +M00575 Pertussis pathogenicity signature, T1SS Pathogenicity #66406d +M00576 ETEC pathogenicity signature, heat-labile and heat-stable enterotoxins Pathogenicity #66406d +M00850 Vibrio cholerae pathogenicity signature, cholera toxins Pathogenicity #66406d +M00852 Vibrio cholerae pathogenicity signature, toxin coregulated pilus Pathogenicity #66406d +M00853 ETEC pathogenicity signature, colonization factors Pathogenicity #66406d +M00856 Salmonella enterica pathogenicity signature, typhoid toxin Pathogenicity #66406d +M00857 Salmonella enterica pathogenicity signature, Vi antigen Pathogenicity #66406d +M00859 Bacillus anthracis pathogenicity signature, anthrax toxin Pathogenicity #66406d +M00860 Bacillus anthracis pathogenicity signature, polyglutamic acid capsule biosynthesis Pathogenicity #66406d +M00161 Photosystem II Photosynthesis #cfa68a +M00163 Photosystem I Photosynthesis #cfa68a +M00597 Anoxygenic photosystem II [BR:ko00194] Photosynthesis #cfa68a +M00598 Anoxygenic photosystem I [BR:ko00194] Photosynthesis #cfa68a +M00660 Xanthomonas spp. pathogenicity signature, T3SS and effectors Plant pathogenicity #461d27 +M00133 Polyamine biosynthesis, arginine => agmatine => putrescine => spermidine Polyamine biosynthesis #a5b3da +M00134 Polyamine biosynthesis, arginine => ornithine => putrescine Polyamine biosynthesis #a5b3da +M00135 GABA biosynthesis, eukaryotes, putrescine => GABA Polyamine biosynthesis #a5b3da +M00136 GABA biosynthesis, prokaryotes, putrescine => GABA Polyamine biosynthesis #a5b3da +M00793 dTDP-L-rhamnose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00794 dTDP-6-deoxy-D-allose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00795 dTDP-beta-L-noviose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00796 dTDP-D-mycaminose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00797 dTDP-D-desosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00798 dTDP-L-mycarose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00799 dTDP-L-oleandrose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00800 dTDP-L-megosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00801 dTDP-L-olivose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00802 dTDP-D-forosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00803 dTDP-D-angolosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00048 Inosine monophosphate biosynthesis, PRPP + glutamine => IMP Purine metabolism #e0a7d2 +M00049 Adenine ribonucleotide biosynthesis, IMP => ADP,ATP Purine metabolism #e0a7d2 +M00050 Guanine ribonucleotide biosynthesis IMP => GDP,GTP Purine metabolism #e0a7d2 +M00546 Purine degradation, xanthine => urea Purine metabolism #e0a7d2 +M00046 Pyrimidine degradation, uracil => beta-alanine, thymine => 3-aminoisobutanoate Pyrimidine metabolism #25585e +M00051 Uridine monophosphate biosynthesis, glutamine (+ PRPP) => UMP Pyrimidine metabolism #25585e +M00052 Pyrimidine ribonucleotide biosynthesis, UMP => UDP--UTP,CDP--CTP Pyrimidine metabolism #25585e +M00053 Pyrimidine deoxyribonuleotide biosynthesis, CDP--CTP => dCDP--dCTP,dTDP--dTTP Pyrimidine metabolism #25585e +M00018 Threonine biosynthesis, aspartate => homoserine => threonine Serine and threonine metabolism #de7d78 +M00020 Serine biosynthesis, glycerate-3P => serine Serine and threonine metabolism #de7d78 +M00033 Ectoine biosynthesis, aspartate => ectoine Serine and threonine metabolism #de7d78 +M00555 Betaine biosynthesis, choline => betaine Serine and threonine metabolism #de7d78 +M00101 Cholesterol biosynthesis, squalene 2,3-epoxide => cholesterol Sterol biosynthesis #4e96a2 +M00102 Ergocalciferol biosynthesis Sterol biosynthesis #4e96a2 +M00103 Cholecalciferol biosynthesis Sterol biosynthesis #4e96a2 +M00104 Bile acid biosynthesis, cholesterol => cholate--chenodeoxycholate Sterol biosynthesis #4e96a2 +M00106 Conjugated bile acid biosynthesis, cholate => taurocholate--glycocholate Sterol biosynthesis #4e96a2 +M00107 Steroid hormone biosynthesis, cholesterol => prognenolone => progesterone Sterol biosynthesis #4e96a2 +M00108 C21-Steroid hormone biosynthesis, progesterone => corticosterone--aldosterone Sterol biosynthesis #4e96a2 +M00109 C21-Steroid hormone biosynthesis, progesterone => cortisol--cortisone Sterol biosynthesis #4e96a2 +M00110 C19--C18-Steroid hormone biosynthesis, pregnenolone => androstenedione => estrone Sterol biosynthesis #4e96a2 +M00862 beta-Oxidation, peroxisome, tri--dihydroxycholestanoyl-CoA => choloyl--chenodeoxycholoyl-CoA Sterol biosynthesis #4e96a2 +M00176 Assimilatory sulfate reduction, sulfate => H2S Sulfur metabolism #4e96a2 +M00595 Thiosulfate oxidation by SOX complex, thiosulfate => sulfate Sulfur metabolism #4e96a2 +M00596 Dissimilatory sulfate reduction, sulfate => H2S Sulfur metabolism #4e96a2 +M00664 Nodulation Symbiosis #88574e +M00095 C5 isoprenoid biosynthesis, mevalonate pathway Terpenoid backbone biosynthesis #4e6089 +M00096 C5 isoprenoid biosynthesis, non-mevalonate pathway Terpenoid backbone biosynthesis #4e6089 +M00364 C10-C20 isoprenoid biosynthesis, bacteria Terpenoid backbone biosynthesis #4e6089 +M00365 C10-C20 isoprenoid biosynthesis, archaea Terpenoid backbone biosynthesis #4e6089 +M00366 C10-C20 isoprenoid biosynthesis, plants Terpenoid backbone biosynthesis #4e6089 +M00367 C10-C20 isoprenoid biosynthesis, non-plant eukaryotes Terpenoid backbone biosynthesis #4e6089 +M00849 C5 isoprenoid biosynthesis, mevalonate pathway, archaea Terpenoid backbone biosynthesis #4e6089 +M00778 Type II polyketide backbone biosynthesis, acyl-CoA + malonyl-CoA => polyketide Type II polyketide biosynthesis #af7194 +M00779 Dihydrokalafungin biosynthesis, octaketide => dihydrokalafungin Type II polyketide biosynthesis #af7194 +M00780 Tetracycline--oxytetracycline biosynthesis, pretetramide => tetracycline--oxytetracycline Type II polyketide biosynthesis #af7194 +M00781 Nogalavinone--aklavinone biosynthesis, deoxynogalonate--deoxyaklanonate => nogalavinone--aklavinone Type II polyketide biosynthesis #af7194 +M00782 Mithramycin biosynthesis, 4-demethylpremithramycinone => mithramycin Type II polyketide biosynthesis #af7194 +M00783 Tetracenomycin C--8-demethyltetracenomycin C biosynthesis, tetracenomycin F2 => tetracenomycin C--8-demethyltetracenomycin C Type II polyketide biosynthesis #af7194 +M00784 Elloramycin biosynthesis, 8-demethyltetracenomycin C => elloramycin A Type II polyketide biosynthesis #af7194 +M00823 Chlortetracycline biosynthesis, pretetramide => chlortetracycline Type II polyketide biosynthesis #af7194 \ No newline at end of file diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/01.Bifurcating_List.txt b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/01.Bifurcating_List.txt new file mode 100644 index 0000000..8d909f9 --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/01.Bifurcating_List.txt @@ -0,0 +1,23 @@ +M00373 +M00532 +M00376 +M00378 +M00088 +M00031 +M00763 +M00133 +M00075 +M00872 +M00125 +M00119 +M00122 +M00827 +M00828 +M00832 +M00833 +M00837 +M00838 +M00785 +M00307 +M00048 +M00127 \ No newline at end of file diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/02.Structural_List.txt b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/02.Structural_List.txt new file mode 100644 index 0000000..7fbba00 --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/02.Structural_List.txt @@ -0,0 +1,10 @@ +M00144 +M00149 +M00151 +M00152 +M00154 +M00155 +M00153 +M00156 +M00158 +M00160 \ No newline at end of file diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/03.Bifurcating_Modules.dict b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/03.Bifurcating_Modules.dict new file mode 100644 index 0000000..a09f7b4 --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/03.Bifurcating_Modules.dict @@ -0,0 +1 @@ +{'M00373':{'M00373_1':{1:'K00626',2:'K00023',3:'K17865',4:'K14446',5:'K14447',6:'K14448',7:'K14449',8:'K08691',9:'K14451'},'M00373_2':{1:'K00626',2:'K00023',3:'K17865',4:'K14446',5:'K14447',6:'K14448',7:'K14449',8:'K01965+K01966',9:'K05606',10:'K01847'}},'M00532':{'M00532_1':{1:'K01601-K01602',2:'K19269',3:'K11517',4:'K03781',5:'K14272',6:'K00600',7:'K00830',8:'K15893,K15919',9:'K15918'},'M00532_2':{1:'K01601-K01602',2:'K19269',3:'K11517',4:'K03781',5:'K14272',6:'K00600',7:'K00830',8:'K00281+K00605+K00382+K02437'}},'M00376':{'M00376_1':{1:'K02160+K01961+K01962+K01963',2:'K14468',3:'K14469',4:'K15052',5:'K05606',6:['K01847','K01848+K01849'],7:'K14471+K14472',8:'K00239+K00240+K00241',9:'K01679'},'M00376_2':{1:'K02160+K01961+K01962+K01963',2:'K14468',3:'K14469',4:'K08691',5:'K14449',6:'K14470',7:'K09709'}},'M00378':{'M00378_1':{1:['K11779','K11780+K11781'],2:'K11212',3:'K12234'},'M00378_2':{1:'K14941',2:'K11212',3:'K12234'}},'M00088':{'M00088_1':{1:'K00626',2:'K01641',3:'K01640',4:'K00019'},'M00088_2':{1:'K00626',2:'K01641',3:'K01640',4:'K01574'}},'M00031':{'M00031_1':{1:'K05826',2:'K05827',3:'K05828',4:'K05829',5:'K05830',6:'K05831'}},'M00763':{'M00763_1':{1:'K05826',2:'K19412',3:'K05828',4:'K05829',5:'K05830',6:'K05831'}},'M00133':{'M00133_1':{1:'K01583,K01584,K01585,K02626',2:'K01480',3:'K01611'},'M00133_2':{1:'K00797',2:'K01611'}},'M00075':{'M00075_1':{1:'K01231',2:'K00736',3:'K00737'},'M00075_2':{1:'K01231',2:'K00736',3:'K00738',4:'K00744,K09661',5:'K13748'},'M00075_3':{1:'K01231',2:'K00736',3:'K00717',4:'K07966,K07967,K07968',5:'K00778,K00779'}},'M00872':{'M00872_1':{1:'K00728',2:'K18207',3:'K09654',4:'K17547',5:'K19872',6:'K19873',7:'K21052',8:'K21032',9:'K09668'},'M00872_2':{1:'K21031',2:'K19872',3:'K19873',4:'K21052',5:'K21032',6:'K09668'}},'M00125':{'M00125_1':{1:'K01497,K14652',2:['K01498_K00082','K11752'],3:'K22912,K20860,K20861,K20862,K21063,K21064',4:'K00794',5:'K00793',6:['K00861,K20884_K00953,K22949','K11753']},'M00125_2':{1:'K02858,K14652',2:'K00794',3:'K00793',4:['K00861,K20884_K00953,K22949','K11753']}},'M00119':{'M00119_1':{1:'K00826',2:'K00606',3:'K00077',4:'K01918,K13799'},'M00119_2':{1:'K01579',2:'K01918,K13799'}},'M00122':{'M00122_1':{1:'K00798,K19221',2:'K02232',3:'K02225,K02227',4:'K02231',5:'K02233'},'M00122_2':{1:'K00768',2:'K02226,K22316',3:'K02233'}},'M00827':{'M00827_1':{1:'K21183',2:'K21181',3:'K21182',4:'K16431',5:'K21184',6:'K21185'}},'M00828':{'M00828_1':{1:'K21183',2:'K21181',3:'K21182',4:'K21188'}},'M00832':{'M00832_1':{1:'K21183',2:'K21227',3:'K21228',4:'K16431',5:'K21185'}},'M00833':{'M00833_1':{1:'K21254',2:'K21255',3:'K21256',4:'K21257',5:'K21258',6:'K21261',7:'K21262',8:'K21263'},'M00833_2':{1:'K21259',2:'K21260',3:'K21261',4:'K21262',5:'K21263'}},'M00837':{'M00837_1':{1:'K21780+K21781',2:'K21782',3:'K21783',4:'K21784',5:'K21785',6:'K21786',7:'K21787'},'M00837_2':{1:'K21428',2:'K21778',3:'K21779',4:'K21787'}},'M00838':{'M00838_1':{1:'K21780+K21781',2:'K21782',3:'K21783',4:'K21784',5:'K21785',6:'K21786',7:'K21787'},'M00837_2':{1:'K21791',2:'K21792',3:'K21793',4:'K21787'}},'M00785':{'M00785_1':{1:'K19741',2:'K19723',3:'K19725',4:'K19724',5:'K19727'},'M00785_2':{1:'K19726',2:'K19725',3:'K19724',4:'K19727'}},'M00307':{'M00307_1':{1:'K03737'},'M00307_2':{1:'K00169+K00170+K00171+K00172'},'M00307_3':{1:'K00161+K00162+K00627+K00382-K13997'},'M00307_4':{1:'K00163+K00627+K00382-K13997'}},'M00048':{'M00048_1':{1:'K00764',2:'K01945,K11787,K11788,K13713',3:'K00601,K11175,K08289,K11787,K01492',4:['K01952','K23269+K23264+K23265','K23270+K23265'], 5:'K01933,K11787',6:'K01923,K01587,K13713',7:'K01756',8:['K00602','K01492','K06863_K11176']}, 'M00048_2':{1:'K00764',2:'K01945,K11787,K11788,K13713',3:'K00601,K11175,K08289,K11787,K01492',4:['K01952','K23269+K23264+K23265','K23270+K23265'],5:'K11788',6:['K01587','K11808','K01589_K01588'],7:'K01923,K01587,K13713',8:'K01756',9:['K00602','K01492','K06863_K11176']}},'M00127':{'M00127_1':{1:'K03147',2:'K00877,K00941,K14153',3:'K00788,K14153,K14154',4:'K00946'},'M00127_2':{1:'K00878,K14154',2:'K00788,K14153,K14154',3:'K00946'}}} \ No newline at end of file diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/04.Structural_Modules.dict b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/04.Structural_Modules.dict new file mode 100644 index 0000000..b9aa2e8 --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/04.Structural_Modules.dict @@ -0,0 +1 @@ +{'M00144':['K00330', 'K00331+K00332+K00333,K00331+K13378,K13380','K00334+K00335+K00336+K00337+K00338+K00339+K00340','K00341+K00342,K15863','K00343'],'M00149':['K00241','K00242,K18859,K18860','K00239+K00240'],'M00151':[['K03890+K03891+K03889','K03886+K03887+K03888','K00412+K00413,K00410_K00411']],'M00152':['K00412+K00413,K00410','K00411+K00414+K00415+K00416+K00417+K00418+K00419+K00420'],'M00154':['K02257+K02262+K02256+K02261+K02263+K02264+K02265+K02266+K02267+K02268','K02269,K02270-K02271','K02272-K02273+K02258+K02259+K02260'],'M00155':['K02275','K02274+K02276,K15408','K02277'],'M00153':['K00425+K00426','K00424,K22501'],'M00156':['K00404+K00405,K15862','K00407+K00406'],'M00158':['K02132+K02133+K02136+K02134+K02135+K02137+K02126+K02127+K02128+K02138','K02129,K01549','K02130,K02139','K02140','K02141,K02131','K02142-K02143+K02125'],'M00160':['K02145+K02147+K02148+K02149+K02150+K02151+K02152+K02144+K02154','K03661,K02155','K02146+K02153+K03662']} \ No newline at end of file diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/05.Modules_Parsed.txt b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/05.Modules_Parsed.txt new file mode 100644 index 0000000..c8229a5 --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/05.Modules_Parsed.txt @@ -0,0 +1,3343 @@ +M00001 +(K00844,K12407,K00845,K00886,K08074,K00918) (K01810,K06859,K13810,K15916) (K00850,K16370,K00918) (K01623,K01624,K11645,K16305,K16306) K01803 ((K00134,K00150) K00927,K11389) (K01834,K15633,K15634,K15635) K01689 (K00873,K12406) +['(K00844,K12407,K00845,K00886,K08074,K00918)', '(K01810,K06859,K13810,K15916)', '(K00850,K16370,K00918)', '(K01623,K01624,K11645,K16305,K16306)', 'K01803', '((K00134,K00150)_K00927,K11389)', '(K01834,K15633,K15634,K15635)', 'K01689', '(K00873,K12406)'] +== +['K00844', 'K12407', 'K00845', 'K00886', 'K08074', 'K00918'] +['K01810', 'K06859', 'K13810', 'K15916'] +['K00850', 'K16370', 'K00918'] +['K01623', 'K01624', 'K11645', 'K16305', 'K16306'] +['K01803'] +['K11389', 'K00134,K00150_K00927'] +['K01834', 'K15633', 'K15634', 'K15635'] +['K01689'] +['K00873', 'K12406'] +++++++++++++++++++ +M00002 +K01803 ((K00134,K00150) K00927,K11389) (K01834,K15633,K15634,K15635) K01689 (K00873,K12406) +['K01803', '((K00134,K00150)_K00927,K11389)', '(K01834,K15633,K15634,K15635)', 'K01689', '(K00873,K12406)'] +== +['K01803'] +['K11389', 'K00134,K00150_K00927'] +['K01834', 'K15633', 'K15634', 'K15635'] +['K01689'] +['K00873', 'K12406'] +++++++++++++++++++ +M00003 +(K01596,K01610) K01689 (K01834,K15633,K15634,K15635) K00927 (K00134,K00150) K01803 ((K01623,K01624,K11645) (K03841,K02446,K11532,K01086,K04041),K01622) +['(K01596,K01610)', 'K01689', '(K01834,K15633,K15634,K15635)', 'K00927', '(K00134,K00150)', 'K01803', '((K01623,K01624,K11645)_(K03841,K02446,K11532,K01086,K04041),K01622)'] +== +['K01596', 'K01610'] +['K01689'] +['K01834', 'K15633', 'K15634', 'K15635'] +['K00927'] +['K00134', 'K00150'] +['K01803'] +['K01622', 'K01623,K01624,K11645_K03841,K02446,K11532,K01086,K04041'] +++++++++++++++++++ +M00009 +(K01647,K05942) (K01681,K01682) (K00031,K00030) (K00164+K00658+K00382,K00174+K00175-K00177-K00176) (K01902+K01903,K01899+K01900,K18118) (K00234+K00235+K00236+K00237,K00239+K00240+K00241-(K00242,K18859,K18860),K00244+K00245+K00246-K00247) (K01676,K01679,K01677+K01678) (K00026,K00025,K00024,K00116) +['(K01647,K05942)', '(K01681,K01682)', '(K00031,K00030)', '(K00164+K00658+K00382,K00174+K00175-K00177-K00176)', '(K01902+K01903,K01899+K01900,K18118)', '(K00234+K00235+K00236+K00237,K00239+K00240+K00241-(K00242,K18859,K18860),K00244+K00245+K00246-K00247)', '(K01676,K01679,K01677+K01678)', '(K00026,K00025,K00024,K00116)'] +== +['K01647', 'K05942'] +['K01681', 'K01682'] +['K00031', 'K00030'] +['K00164+K00658+K00382', 'K00174+K00175-K00177-K00176'] +['K18118', 'K01902+K01903', 'K01899+K01900'] +['K00234+K00235+K00236+K00237', 'K00244+K00245+K00246-K00247', 'K00239+K00240+K00241-%K00242,K18859,K18860)'] +['K01676', 'K01679', 'K01677+K01678'] +['K00026', 'K00025', 'K00024', 'K00116'] +++++++++++++++++++ +M00010 +(K01647,K05942) (K01681,K01682) (K00031,K00030) +['(K01647,K05942)', '(K01681,K01682)', '(K00031,K00030)'] +== +['K01647', 'K05942'] +['K01681', 'K01682'] +['K00031', 'K00030'] +++++++++++++++++++ +M00011 +(K00164+K00658+K00382,K00174+K00175-K00177-K00176) (K01902+K01903,K01899+K01900,K18118) (K00234+K00235+K00236+K00237,K00239+K00240+K00241-(K00242,K18859,K18860),K00244+K00245+K00246-K00247) (K01676,K01679,K01677+K01678) (K00026,K00025,K00024,K00116) +['(K00164+K00658+K00382,K00174+K00175-K00177-K00176)', '(K01902+K01903,K01899+K01900,K18118)', '(K00234+K00235+K00236+K00237,K00239+K00240+K00241-(K00242,K18859,K18860),K00244+K00245+K00246-K00247)', '(K01676,K01679,K01677+K01678)', '(K00026,K00025,K00024,K00116)'] +== +['K00164+K00658+K00382', 'K00174+K00175-K00177-K00176'] +['K18118', 'K01902+K01903', 'K01899+K01900'] +['K00234+K00235+K00236+K00237', 'K00244+K00245+K00246-K00247', 'K00239+K00240+K00241-%K00242,K18859,K18860)'] +['K01676', 'K01679', 'K01677+K01678'] +['K00026', 'K00025', 'K00024', 'K00116'] +++++++++++++++++++ +M00004 +(K13937,((K00036,K19243) (K01057,K07404))) K00033 K01783 (K01807,K01808) K00615 K00616 (K01810,K06859,K13810,K15916) +['(K13937,((K00036,K19243)_(K01057,K07404)))', 'K00033', 'K01783', '(K01807,K01808)', 'K00615', 'K00616', '(K01810,K06859,K13810,K15916)'] +== +['K13937', 'K00036,K19243_K01057,K07404'] +['K00033'] +['K01783'] +['K01807', 'K01808'] +['K00615'] +['K00616'] +['K01810', 'K06859', 'K13810', 'K15916'] +++++++++++++++++++ +M00006 +(K13937,((K00036,K19243) (K01057,K07404))) K00033 +['(K13937,((K00036,K19243)_(K01057,K07404)))', 'K00033'] +== +['K13937', 'K00036,K19243_K01057,K07404'] +['K00033'] +++++++++++++++++++ +M00007 +K00615 (K00616,K13810) K01783 (K01807,K01808) +['K00615', '(K00616,K13810)', 'K01783', '(K01807,K01808)'] +== +['K00615'] +['K00616', 'K13810'] +['K01783'] +['K01807', 'K01808'] +++++++++++++++++++ +M00580 +(K08094 (K08093,K13812),K13831) K01807 +['(K08094_(K08093,K13812),K13831)', 'K01807'] +== +['K13831', 'K08094_K08093,K13812'] +['K01807'] +++++++++++++++++++ +M00005 +K00948 +['K00948'] +== +['K00948'] +++++++++++++++++++ +M00008 +K00036 (K01057,K07404) K01690 K01625 +['K00036', '(K01057,K07404)', 'K01690', 'K01625'] +== +['K00036'] +['K01057', 'K07404'] +['K01690'] +['K01625'] +++++++++++++++++++ +M00308 +K05308 K00874 K01625 (K00134 K00927,K00131,K18978) +['K05308', 'K00874', 'K01625', '(K00134_K00927,K00131,K18978)'] +== +['K05308'] +['K00874'] +['K01625'] +['K00131', 'K18978', 'K00134_K00927'] +++++++++++++++++++ +M00633 +K05308 K18126 K11395 (K00131,K18978) +['K05308', 'K18126', 'K11395', '(K00131,K18978)'] +== +['K05308'] +['K18126'] +['K11395'] +['K00131', 'K18978'] +++++++++++++++++++ +M00309 +K05308 (K11395,K18127) (K18020+K18021+K18022,K18128,K03738) +['K05308', '(K11395,K18127)', '(K18020+K18021+K18022,K18128,K03738)'] +== +['K05308'] +['K11395', 'K18127'] +['K18128', 'K03738', 'K18020+K18021+K18022'] +++++++++++++++++++ +M00014 +K00012 ((K12447 K16190),(K00699 (K01195,K14756))) K00002 K13247 -- K03331 (K05351,K00008) K00854 +['K00012', '((K12447_K16190),(K00699_(K01195,K14756)))', 'K00002', 'K13247', 'K03331', '(K05351,K00008)', 'K00854'] +== +['K00012'] +['K12447_K16190', 'K00699_K01195,K14756'] +['K00002'] +['K13247'] +['K03331'] +['K05351', 'K00008'] +['K00854'] +++++++++++++++++++ +M00630 +(K18106,K19634) K18102 K18103 K18107 +['(K18106,K19634)', 'K18102', 'K18103', 'K18107'] +== +['K18106', 'K19634'] +['K18102'] +['K18103'] +['K18107'] +++++++++++++++++++ +M00631 +K01812 K00041 (K01685,K16849+K16850) K00874 (K01625,K17463) +['K01812', 'K00041', '(K01685,K16849+K16850)', 'K00874', '(K01625,K17463)'] +== +['K01812'] +['K00041'] +['K01685', 'K16849+K16850'] +['K00874'] +['K01625', 'K17463'] +++++++++++++++++++ +M00061 +K01812 K00040 (K01686,K08323) K00874 (K01625,K17463) +['K01812', 'K00040', '(K01686,K08323)', 'K00874', '(K01625,K17463)'] +== +['K01812'] +['K00040'] +['K01686', 'K08323'] +['K00874'] +['K01625', 'K17463'] +++++++++++++++++++ +M00081 +K01051 K01184 K01213 +['K01051', 'K01184', 'K01213'] +== +['K01051'] +['K01184'] +['K01213'] +++++++++++++++++++ +M00632 +K01785 K00849 K00965 K01784 +['K01785', 'K00849', 'K00965', 'K01784'] +== +['K01785'] +['K00849'] +['K00965'] +['K01784'] +++++++++++++++++++ +M00552 +K01684 K00883 K01631 K00134 K00927 +['K01684', 'K00883', 'K01631', 'K00134', 'K00927'] +== +['K01684'] +['K00883'] +['K01631'] +['K00134'] +['K00927'] +++++++++++++++++++ +M00129 +K00963 K00012 K00699 (K01195,K14756) K00002 K01053 K00103 +['K00963', 'K00012', 'K00699', '(K01195,K14756)', 'K00002', 'K01053', 'K00103'] +== +['K00963'] +['K00012'] +['K00699'] +['K01195', 'K14756'] +['K00002'] +['K01053'] +['K00103'] +++++++++++++++++++ +M00114 +((K01810,K06859,K13810) (K01809,K16011),K15916) (K16881,(K17497,K01840,K15778) (K00966,K00971,K16011)) K10046 K14190 (K10047,K18649) (K00064,K17744) K00225 +['((K01810,K06859,K13810)_(K01809,K16011),K15916)', '(K16881,(K17497,K01840,K15778)_(K00966,K00971,K16011))', 'K10046', 'K14190', '(K10047,K18649)', '(K00064,K17744)', 'K00225'] +== +['K15916', 'K01810,K06859,K13810_K01809,K16011'] +['K16881', 'K17497,K01840,K15778_K00966,K00971,K16011'] +['K10046'] +['K14190'] +['K10047', 'K18649'] +['K00064', 'K17744'] +['K00225'] +++++++++++++++++++ +M00550 +K02821+K02822+K03475 K03476 K03078 K03079 K03077 +['K02821+K02822+K03475', 'K03476', 'K03078', 'K03079', 'K03077'] +== +['K02821+K02822+K03475'] +['K03476'] +['K03078'] +['K03079'] +['K03077'] +++++++++++++++++++ +M00854 +(K00963 (K00693+K00750,K16150,K16153,K13679,K20812)),(K00975 (K00703,K13679,K20812)) (K00700,K16149) +['(K00963_(K00693+K00750,K16150,K16153,K13679,K20812)),(K00975_(K00703,K13679,K20812))', '(K00700,K16149)'] +== +['K00975_K00703,K13679,K20812', 'K00963_K00693+K00750,K16150,K16153,K13679,K20812'] +['K00700', 'K16149'] +++++++++++++++++++ +M00855 +(K00688,K16153) (K01196,((K00705,K22451) (K02438,K01200))) (K15779,K01835,K15778) +['(K00688,K16153)', '(K01196,((K00705,K22451)_(K02438,K01200)))', '(K15779,K01835,K15778)'] +== +['K00688', 'K16153'] +['K01196', 'K00705,K22451_K02438,K01200'] +['K15779', 'K01835', 'K15778'] +++++++++++++++++++ +M00565 +K00975 K00703 (K00700,K16149) K01214 K06044 K01236 +['K00975', 'K00703', '(K00700,K16149)', 'K01214', 'K06044', 'K01236'] +== +['K00975'] +['K00703'] +['K00700', 'K16149'] +['K01214'] +['K06044'] +['K01236'] +++++++++++++++++++ +M00549 +(K00844,K00845,K12407,K00886) K01835 K00963 +['(K00844,K00845,K12407,K00886)', 'K01835', 'K00963'] +== +['K00844', 'K00845', 'K12407', 'K00886'] +['K01835'] +['K00963'] +++++++++++++++++++ +M00554 +K00849 K00965 +['K00849', 'K00965'] +== +['K00849'] +['K00965'] +++++++++++++++++++ +M00761 +K10011 K07806 K10012 K13014 +['K10011', 'K07806', 'K10012', 'K13014'] +== +['K10011'] +['K07806'] +['K10012'] +['K13014'] +++++++++++++++++++ +M00012 +K01647 (K01681,K01682) K01637 (K01638,K19282) (K00026,K00025,K00024) +['K01647', '(K01681,K01682)', 'K01637', '(K01638,K19282)', '(K00026,K00025,K00024)'] +== +['K01647'] +['K01681', 'K01682'] +['K01637'] +['K01638', 'K19282'] +['K00026', 'K00025', 'K00024'] +++++++++++++++++++ +M00740 +K01647 K01681 K00031 K00261 K19268+K01846 K04835 K19280 K14449 K19281 K19282 K00024 +['K01647', 'K01681', 'K00031', 'K00261', 'K19268+K01846', 'K04835', 'K19280', 'K14449', 'K19281', 'K19282', 'K00024'] +== +['K01647'] +['K01681'] +['K00031'] +['K00261'] +['K19268+K01846'] +['K04835'] +['K19280'] +['K14449'] +['K19281'] +['K19282'] +['K00024'] +++++++++++++++++++ +M00013 +(K00248,K00232) (K07511,K07514,K07515,K14729) K05605 K23146 K00140 +['(K00248,K00232)', '(K07511,K07514,K07515,K14729)', 'K05605', 'K23146', 'K00140'] +== +['K00248', 'K00232'] +['K07511', 'K07514', 'K07515', 'K14729'] +['K05605'] +['K23146'] +['K00140'] +++++++++++++++++++ +M00741 +(K01965+K01966,K11263+(K18472,K19312+K22568),K01964+K15036+K15037) K05606 (K01847,K01848+K01849) +['(K01965+K01966,K11263+(K18472,K19312+K22568),K01964+K15036+K15037)', 'K05606', '(K01847,K01848+K01849)'] +== +['K01965+K01966', 'K01964+K15036+K15037', 'K11263+K18472,K19312+K22568'] +['K05606'] +['K01847', 'K01848+K01849'] +++++++++++++++++++ +M00130 +(K00888,K19801,K13711) (K00889,K13712) (K01116,K05857,K05858,K05859,K05860,K05861) K00911 +['(K00888,K19801,K13711)', '(K00889,K13712)', '(K01116,K05857,K05858,K05859,K05860,K05861)', 'K00911'] +== +['K00888', 'K19801', 'K13711'] +['K00889', 'K13712'] +['K01116', 'K05857', 'K05858', 'K05859', 'K05860', 'K05861'] +['K00911'] +++++++++++++++++++ +M00131 +K01106 (K01107,K15422) K01109 (K01092,K15759,K10047,K18649) +['K01106', '(K01107,K15422)', 'K01109', '(K01092,K15759,K10047,K18649)'] +== +['K01106'] +['K01107', 'K15422'] +['K01109'] +['K01092', 'K15759', 'K10047', 'K18649'] +++++++++++++++++++ +M00132 +(K00913,K01765) K00915 K10572 +['(K00913,K01765)', 'K00915', 'K10572'] +== +['K00913', 'K01765'] +['K00915'] +['K10572'] +++++++++++++++++++ +M00165 +K00855 (K01601-K01602) K00927 (K05298,K00150,K00134) (K01623,K01624) (K03841,K02446,K11532,K01086) K00615 (K01623,K01624) (K01100,K11532,K01086) K00615 (K01807,K01808) +['K00855', '(K01601-K01602)', 'K00927', '(K05298,K00150,K00134)', '(K01623,K01624)', '(K03841,K02446,K11532,K01086)', 'K00615', '(K01623,K01624)', '(K01100,K11532,K01086)', 'K00615', '(K01807,K01808)'] +== +['K00855'] +['K01601-K01602'] +['K00927'] +['K05298', 'K00150', 'K00134'] +['K01623', 'K01624'] +['K03841', 'K02446', 'K11532', 'K01086'] +['K00615'] +['K01623', 'K01624'] +['K01100', 'K11532', 'K01086'] +['K00615'] +['K01807', 'K01808'] +++++++++++++++++++ +M00166 +K00855 (K01601-K01602) K00927 (K05298,K00150,K00134) +['K00855', '(K01601-K01602)', 'K00927', '(K05298,K00150,K00134)'] +== +['K00855'] +['K01601-K01602'] +['K00927'] +['K05298', 'K00150', 'K00134'] +++++++++++++++++++ +M00167 +(K01623,K01624) (K03841,K02446,K11532,K01086) K00615 (K01623,K01624) (K01100,K11532,K01086) K00615 (K01807,K01808) +['(K01623,K01624)', '(K03841,K02446,K11532,K01086)', 'K00615', '(K01623,K01624)', '(K01100,K11532,K01086)', 'K00615', '(K01807,K01808)'] +== +['K01623', 'K01624'] +['K03841', 'K02446', 'K11532', 'K01086'] +['K00615'] +['K01623', 'K01624'] +['K01100', 'K11532', 'K01086'] +['K00615'] +['K01807', 'K01808'] +++++++++++++++++++ +M00168 +K01595 (K00025,K00026,K00024) +['K01595', '(K00025,K00026,K00024)'] +== +['K01595'] +['K00025', 'K00026', 'K00024'] +++++++++++++++++++ +M00169 +K00029 K01006 +['K00029', 'K01006'] +== +['K00029'] +['K01006'] +++++++++++++++++++ +M00172 +K01595 K00051 K00029 K01006 +['K01595', 'K00051', 'K00029', 'K01006'] +== +['K01595'] +['K00051'] +['K00029'] +['K01006'] +++++++++++++++++++ +M00171 +K01595 K14454 K14455 (K00025,K00026) K00028 (K00814,K14272) K01006 +['K01595', 'K14454', 'K14455', '(K00025,K00026)', 'K00028', '(K00814,K14272)', 'K01006'] +== +['K01595'] +['K14454'] +['K14455'] +['K00025', 'K00026'] +['K00028'] +['K00814', 'K14272'] +['K01006'] +++++++++++++++++++ +M00170 +K01595 K14454 K14455 K01610 +['K01595', 'K14454', 'K14455', 'K01610'] +== +['K01595'] +['K14454'] +['K14455'] +['K01610'] +++++++++++++++++++ +M00173 +(K00169+K00170+K00171+K00172,K03737) ((K01007,K01006) K01595,K01959+K01960,K01958) K00024 (K01676,K01679,K01677+K01678) (K00239+K00240-K00241-K00242,K00244+K00245-K00246-K00247,K18556+K18557+K18558+K18559+K18560) (K01902+K01903) (K00174+K00175-K00177-K00176) K00031 (K01681,K01682) (K15230+K15231,K15232+K15233 K15234) +['(K00169+K00170+K00171+K00172,K03737)', '((K01007,K01006)_K01595,K01959+K01960,K01958)', 'K00024', '(K01676,K01679,K01677+K01678)', '(K00239+K00240-K00241-K00242,K00244+K00245-K00246-K00247,K18556+K18557+K18558+K18559+K18560)', '(K01902+K01903)', '(K00174+K00175-K00177-K00176)', 'K00031', '(K01681,K01682)', '(K15230+K15231,K15232+K15233_K15234)'] +== +['K03737', 'K00169+K00170+K00171+K00172'] +['K01958', 'K01959+K01960', 'K01007,K01006_K01595'] +['K00024'] +['K01676', 'K01679', 'K01677+K01678'] +['K00239+K00240-K00241-K00242', 'K00244+K00245-K00246-K00247', 'K18556+K18557+K18558+K18559+K18560'] +['K01902+K01903'] +['K00174+K00175-K00177-K00176'] +['K00031'] +['K01681', 'K01682'] +['K15230+K15231', 'K15232+K15233_K15234'] +++++++++++++++++++ +M00375 +K01964+K15037+K15036 K15017 K15039 K15018 K15019 K15020 K05606 K01848+K01849 (K15038,K15017) K14465 (K14466,K18861) K14534 K15016 K00626 +['K01964+K15037+K15036', 'K15017', 'K15039', 'K15018', 'K15019', 'K15020', 'K05606', 'K01848+K01849', '(K15038,K15017)', 'K14465', '(K14466,K18861)', 'K14534', 'K15016', 'K00626'] +== +['K01964+K15037+K15036'] +['K15017'] +['K15039'] +['K15018'] +['K15019'] +['K15020'] +['K05606'] +['K01848+K01849'] +['K15038', 'K15017'] +['K14465'] +['K14466', 'K18861'] +['K14534'] +['K15016'] +['K00626'] +++++++++++++++++++ +M00374 +K00169+K00170+K00171+K00172 K01007 K01595 K00024 (K01676,K01677+K01678) (K00239+K00240-K00241-K18860) K01902+K01903 (K15038,K15017) K14465 (K14467,K18861) K14534 K15016 K00626 +['K00169+K00170+K00171+K00172', 'K01007', 'K01595', 'K00024', '(K01676,K01677+K01678)', '(K00239+K00240-K00241-K18860)', 'K01902+K01903', '(K15038,K15017)', 'K14465', '(K14467,K18861)', 'K14534', 'K15016', 'K00626'] +== +['K00169+K00170+K00171+K00172'] +['K01007'] +['K01595'] +['K00024'] +['K01676', 'K01677+K01678'] +['K00239+K00240-K00241-K18860'] +['K01902+K01903'] +['K15038', 'K15017'] +['K14465'] +['K14467', 'K18861'] +['K14534'] +['K15016'] +['K00626'] +++++++++++++++++++ +M00377 +K00198 K05299-K15022 K01938 K01491 K00297 K15023 K14138+K00197+K00194 +['K00198', 'K05299-K15022', 'K01938', 'K01491', 'K00297', 'K15023', 'K14138+K00197+K00194'] +== +['K00198'] +['K05299-K15022'] +['K01938'] +['K01491'] +['K00297'] +['K15023'] +['K14138+K00197+K00194'] +++++++++++++++++++ +M00579 +(K00625,K13788,K15024) K00925 +['(K00625,K13788,K15024)', 'K00925'] +== +['K00625', 'K13788', 'K15024'] +['K00925'] +++++++++++++++++++ +M00620 +K00169+K00170+K00171+K00172 K01959+K01960 K00024 K01677+K01678 K18209+K18210 K01902+K01903 K00174+K00175+K00176+K00177 +['K00169+K00170+K00171+K00172', 'K01959+K01960', 'K00024', 'K01677+K01678', 'K18209+K18210', 'K01902+K01903', 'K00174+K00175+K00176+K00177'] +== +['K00169+K00170+K00171+K00172'] +['K01959+K01960'] +['K00024'] +['K01677+K01678'] +['K18209+K18210'] +['K01902+K01903'] +['K00174+K00175+K00176+K00177'] +++++++++++++++++++ +M00567 +(K00200+K00201+K00202+K00203-K11261+(K00205,K11260,K00204)) K00672 K01499 (K00319,K13942) K00320 (K00577+K00578+K00579+K00580+K00581-K00582-K00583+K00584) (K00399+K00401+K00402) (K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125)) +['(K00200+K00201+K00202+K00203-K11261+(K00205,K11260,K00204))', 'K00672', 'K01499', '(K00319,K13942)', 'K00320', '(K00577+K00578+K00579+K00580+K00581-K00582-K00583+K00584)', '(K00399+K00401+K00402)', '(K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125))'] +== +['K00200+K00201+K00202+K00203-K11261+K00205,K11260,K00204'] +['K00672'] +['K01499'] +['K00319', 'K13942'] +['K00320'] +['K00577+K00578+K00579+K00580+K00581-K00582-K00583+K00584'] +['K00399+K00401+K00402'] +['K08264+K08265', 'K22480+K22481+K22482', 'K03388+K03389+K03390', 'K03388+K03389+K03390+K14127+K14126+K14128,K22516+K00125'] +++++++++++++++++++ +M00357 +(K00925 (K00625,K13788),K01895) (K00193+K00197+K00194) (K00577+K00578+K00579+K00580+K00581-K00582-K00583+K00584) (K00399+K00401+K00402) (K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125)) +['(K00925_(K00625,K13788),K01895)', '(K00193+K00197+K00194)', '(K00577+K00578+K00579+K00580+K00581-K00582-K00583+K00584)', '(K00399+K00401+K00402)', '(K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125))'] +== +['K01895', 'K00925_K00625,K13788'] +['K00193+K00197+K00194'] +['K00577+K00578+K00579+K00580+K00581-K00582-K00583+K00584'] +['K00399+K00401+K00402'] +['K08264+K08265', 'K22480+K22481+K22482', 'K03388+K03389+K03390', 'K03388+K03389+K03390+K14127+K14126+K14128,K22516+K00125'] +++++++++++++++++++ +M00356 +K14080+K04480+K14081 K00399+K00401+K00402 (K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125)) +['K14080+K04480+K14081', 'K00399+K00401+K00402', '(K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125))'] +== +['K14080+K04480+K14081'] +['K00399+K00401+K00402'] +['K08264+K08265', 'K22480+K22481+K22482', 'K03388+K03389+K03390', 'K03388+K03389+K03390+K14127+K14126+K14128,K22516+K00125'] +++++++++++++++++++ +M00563 +K14082 ((K16177-K16176),(K16179-K16178),(K14084-K14083)) K00399+K00401+K00402 (K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125)) +['K14082', '((K16177-K16176),(K16179-K16178),(K14084-K14083))', 'K00399+K00401+K00402', '(K22480+K22481+K22482,K03388+K03389+K03390,K08264+K08265,K03388+K03389+K03390+K14127+(K14126+K14128,K22516+K00125))'] +== +['K14082'] +['K16177-K16176', 'K16179-K16178', 'K14084-K14083'] +['K00399+K00401+K00402'] +['K08264+K08265', 'K22480+K22481+K22482', 'K03388+K03389+K03390', 'K03388+K03389+K03390+K14127+K14126+K14128,K22516+K00125'] +++++++++++++++++++ +M00358 +K08097 K05979 K05884 K13039+K06034 +['K08097', 'K05979', 'K05884', 'K13039+K06034'] +== +['K08097'] +['K05979'] +['K05884'] +['K13039+K06034'] +++++++++++++++++++ +M00608 +K10977 K16792+K16793 K10978 +['K10977', 'K16792+K16793', 'K10978'] +== +['K10977'] +['K16792+K16793'] +['K10978'] +++++++++++++++++++ +M00174 +((K10944+K10945+K10946),(K16157+K16158+K16159+K16160+K16161+K16162)) ((K14028-K14029),K23995) +['((K10944+K10945+K10946),(K16157+K16158+K16159+K16160+K16161+K16162))', '((K14028-K14029),K23995)'] +== +['K10944+K10945+K10946', 'K16157+K16158+K16159+K16160+K16161+K16162'] +['K23995', 'K14028-K14029'] +++++++++++++++++++ +M00346 +K00600 K00830 K00018 K11529 K01689 K01595 K00024 K08692+K14067 K08691 +['K00600', 'K00830', 'K00018', 'K11529', 'K01689', 'K01595', 'K00024', 'K08692+K14067', 'K08691'] +== +['K00600'] +['K00830'] +['K00018'] +['K11529'] +['K01689'] +['K01595'] +['K00024'] +['K08692+K14067'] +['K08691'] +++++++++++++++++++ +M00345 +(((K08093,K13812) K08094),K13831) (K00850,K16370) K01624 +['(((K08093,K13812)_K08094),K13831)', '(K00850,K16370)', 'K01624'] +== +['K13831', 'K08093,K13812_K08094'] +['K00850', 'K16370'] +['K01624'] +++++++++++++++++++ +M00344 +K17100 K00863 K01624 K03841 +['K17100', 'K00863', 'K01624', 'K03841'] +== +['K17100'] +['K00863'] +['K01624'] +['K03841'] +++++++++++++++++++ +M00422 +K00192+K00195 K00193+K00197+K00194 +['K00192+K00195', 'K00193+K00197+K00194'] +== +['K00192+K00195'] +['K00193+K00197+K00194'] +++++++++++++++++++ +M00175 +K02588+K02586+K02591-K00531,K22896+K22897+K22898+K22899 +['K02588+K02586+K02591-K00531,K22896+K22897+K22898+K22899'] +== +['K02588+K02586+K02591-K00531', 'K22896+K22897+K22898+K22899'] +++++++++++++++++++ +M00531 +(K00367,K10534,K00372-K00360) (K00366,K17877) +['(K00367,K10534,K00372-K00360)', '(K00366,K17877)'] +== +['K00367', 'K10534', 'K00372-K00360'] +['K00366', 'K17877'] +++++++++++++++++++ +M00530 +(K00370+K00371+K00374,K02567+K02568) (K00362+K00363,K03385+K15876) +['(K00370+K00371+K00374,K02567+K02568)', '(K00362+K00363,K03385+K15876)'] +== +['K02567+K02568', 'K00370+K00371+K00374'] +['K00362+K00363', 'K03385+K15876'] +++++++++++++++++++ +M00529 +(K00370+K00371+K00374,K02567+K02568) (K00368,K15864) (K04561+K02305) K00376 +['(K00370+K00371+K00374,K02567+K02568)', '(K00368,K15864)', '(K04561+K02305)', 'K00376'] +== +['K02567+K02568', 'K00370+K00371+K00374'] +['K00368', 'K15864'] +['K04561+K02305'] +['K00376'] +++++++++++++++++++ +M00528 +K10944+K10945+K10946 K10535 +['K10944+K10945+K10946', 'K10535'] +== +['K10944+K10945+K10946'] +['K10535'] +++++++++++++++++++ +M00804 +K10944+K10945+K10946 K10535 K00370+K00371 +['K10944+K10945+K10946', 'K10535', 'K00370+K00371'] +== +['K10944+K10945+K10946'] +['K10535'] +['K00370+K00371'] +++++++++++++++++++ +M00176 +(K13811,K00958+K00860,K00955+K00957,K00956+K00957+K00860) K00390 (K00380+K00381,K00392) +['(K13811,K00958+K00860,K00955+K00957,K00956+K00957+K00860)', 'K00390', '(K00380+K00381,K00392)'] +== +['K13811', 'K00958+K00860', 'K00955+K00957', 'K00956+K00957+K00860'] +['K00390'] +['K00392', 'K00380+K00381'] +++++++++++++++++++ +M00596 +K00958 (K00394+K00395) (K11180+K11181) +['K00958', '(K00394+K00395)', '(K11180+K11181)'] +== +['K00958'] +['K00394+K00395'] +['K11180+K11181'] +++++++++++++++++++ +M00595 +K17222+K17223+K17224-K17225-K22622+K17226+K17227 +['K17222+K17223+K17224-K17225-K22622+K17226+K17227'] +== +['K17222+K17223+K17224-K17225-K22622+K17226+K17227'] +++++++++++++++++++ +M00161 +K02703+K02706+K02705+K02704+K02707+K02708 +['K02703+K02706+K02705+K02704+K02707+K02708'] +== +['K02703+K02706+K02705+K02704+K02707+K02708'] +++++++++++++++++++ +M00163 +K02689+K02690+K02691+K02692+K02693+K02694 +['K02689+K02690+K02691+K02692+K02693+K02694'] +== +['K02689+K02690+K02691+K02692+K02693+K02694'] +++++++++++++++++++ +M00597 +K08928+K08929 +['K08928+K08929'] +== +['K08928+K08929'] +++++++++++++++++++ +M00598 +K08940+K08941+K08942+K08943 +['K08940+K08941+K08942+K08943'] +== +['K08940+K08941+K08942+K08943'] +++++++++++++++++++ +M00145 +K05574+K05582+K05581+K05579+K05572+K05580+K05578+K05576+K05577+K05575+K05573-K05583-K05584-K05585 +['K05574+K05582+K05581+K05579+K05572+K05580+K05578+K05576+K05577+K05575+K05573-K05583-K05584-K05585'] +== +['K05574+K05582+K05581+K05579+K05572+K05580+K05578+K05576+K05577+K05575+K05573-K05583-K05584-K05585'] +++++++++++++++++++ +M00142 +K03878+K03879+K03880+K03881+K03882+K03883+K03884 +['K03878+K03879+K03880+K03881+K03882+K03883+K03884'] +== +['K03878+K03879+K03880+K03881+K03882+K03883+K03884'] +++++++++++++++++++ +M00143 +K03934+K03935+K03936+K03937+K03938+K03939+K03940+K03941+K03942+K03943-K03944 +['K03934+K03935+K03936+K03937+K03938+K03939+K03940+K03941+K03942+K03943-K03944'] +== +['K03934+K03935+K03936+K03937+K03938+K03939+K03940+K03941+K03942+K03943-K03944'] +++++++++++++++++++ +M00146 +K03945+K03946+K03947+K03948+K03949+K03950+K03951+K03952+K03953+K03954+K03955+K03956+K11352+K11353 +['K03945+K03946+K03947+K03948+K03949+K03950+K03951+K03952+K03953+K03954+K03955+K03956+K11352+K11353'] +== +['K03945+K03946+K03947+K03948+K03949+K03950+K03951+K03952+K03953+K03954+K03955+K03956+K11352+K11353'] +++++++++++++++++++ +M00147 +K03957+K03958+K03959+K03960+K03961+K03962+K03963+K03964+K03965+K03966+K11351+K03967+K03968 +['K03957+K03958+K03959+K03960+K03961+K03962+K03963+K03964+K03965+K03966+K11351+K03967+K03968'] +== +['K03957+K03958+K03959+K03960+K03961+K03962+K03963+K03964+K03965+K03966+K11351+K03967+K03968'] +++++++++++++++++++ +M00150 +K00244+K00245+K00246+K00247 +['K00244+K00245+K00246+K00247'] +== +['K00244+K00245+K00246+K00247'] +++++++++++++++++++ +M00148 +K00236+K00237+K00234+K00235 +['K00236+K00237+K00234+K00235'] +== +['K00236+K00237+K00234+K00235'] +++++++++++++++++++ +M00162 +K02635+K02637+K02634+K02636+K02642+K02643+K03689+K02640 +['K02635+K02637+K02634+K02636+K02642+K02643+K03689+K02640'] +== +['K02635+K02637+K02634+K02636+K02642+K02643+K03689+K02640'] +++++++++++++++++++ +M00154 +(K02257+K02262+K02256+K02261+K02263+K02264+K02265+K02266+K02267+K02268+(K02269,K02270-K02271)+K02272-K02273+K02258+K02259+K02260) +['(K02257+K02262+K02256+K02261+K02263+K02264+K02265+K02266+K02267+K02268+(K02269,K02270-K02271)+K02272-K02273+K02258+K02259+K02260)'] +== +['K02257+K02262+K02256+K02261+K02263+K02264+K02265+K02266+K02267+K02268+K02269,K02270-K02271+K02272-K02273+K02258+K02259+K02260'] +++++++++++++++++++ +M00155 +K02275+(K02274+K02276,K15408)-K02277 +['K02275+(K02274+K02276,K15408)-K02277'] +== +['K15408-K02277', 'K02275+K02274+K02276'] +++++++++++++++++++ +M00153 +K00425+K00426+(K00424,K22501) +['K00425+K00426+(K00424,K22501)'] +== +['K22501', 'K00425+K00426+K00424'] +++++++++++++++++++ +M00417 +K02297+K02298+K02299+K02300 +['K02297+K02298+K02299+K02300'] +== +['K02297+K02298+K02299+K02300'] +++++++++++++++++++ +M00416 +K02827+K02826+K02828+K02829 +['K02827+K02826+K02828+K02829'] +== +['K02827+K02826+K02828+K02829'] +++++++++++++++++++ +M00156 +((K00404+K00405,K15862)+K00407+K00406) +['((K00404+K00405,K15862)+K00407+K00406)'] +== +['K00404+K00405,K15862+K00407+K00406'] +++++++++++++++++++ +M00157 +K02111+K02112+K02113+K02114+K02115+K02108+K02109+K02110 +['K02111+K02112+K02113+K02114+K02115+K02108+K02109+K02110'] +== +['K02111+K02112+K02113+K02114+K02115+K02108+K02109+K02110'] +++++++++++++++++++ +M00158 +K02132+K02133+K02136+K02134+K02135+K02137+K02126+K02127+K02128+K02138+(K02129,K01549)+(K02130,K02139)+K02140+(K02141,K02131)-K02142-K02143+K02125 +['K02132+K02133+K02136+K02134+K02135+K02137+K02126+K02127+K02128+K02138+(K02129,K01549)+(K02130,K02139)+K02140+(K02141,K02131)-K02142-K02143+K02125'] +== +['K01549+K02130', 'K02139+K02140+K02141', 'K02131-K02142-K02143+K02125', 'K02132+K02133+K02136+K02134+K02135+K02137+K02126+K02127+K02128+K02138+K02129'] +++++++++++++++++++ +M00159 +K02117+K02118+K02119+K02120+K02121+K02122+K02107+K02123+K02124 +['K02117+K02118+K02119+K02120+K02121+K02122+K02107+K02123+K02124'] +== +['K02117+K02118+K02119+K02120+K02121+K02122+K02107+K02123+K02124'] +++++++++++++++++++ +M00160 +K02145+K02147+K02148+K02149+K02150+K02151+K02152+K02144+K02154+(K03661,K02155)+K02146+K02153+K03662 +['K02145+K02147+K02148+K02149+K02150+K02151+K02152+K02144+K02154+(K03661,K02155)+K02146+K02153+K03662'] +== +['K02155+K02146+K02153+K03662', 'K02145+K02147+K02148+K02149+K02150+K02151+K02152+K02144+K02154+K03661'] +++++++++++++++++++ +M00082 +(K11262,(K02160+K01961,K11263)+(K01962+K01963,K18472)) (K00665,K00667+K00668,K11533,(K00645 (K00648,K18473))) +['(K11262,(K02160+K01961,K11263)+(K01962+K01963,K18472))', '(K00665,K00667+K00668,K11533,(K00645_(K00648,K18473)))'] +== +['K11262', 'K02160+K01961,K11263+K01962+K01963,K18472'] +['K00665', 'K11533', 'K00667+K00668', 'K00645_K00648,K18473'] +++++++++++++++++++ +M00083 +K00665,(K00667 K00668),K11533,((K00647,K09458) K00059 (K02372,K01716,K16363) (K00208,K02371,K10780,K00209)) +['K00665,(K00667_K00668),K11533,((K00647,K09458)_K00059_(K02372,K01716,K16363)_(K00208,K02371,K10780,K00209))'] +== +['K00665', 'K11533', 'K00667_K00668', 'K00647,K09458_K00059_K02372,K01716,K16363_K00208,K02371,K10780,K00209'] +++++++++++++++++++ +M00873 +K18660 K03955+K00645 K09458 K11539+K13370 K22540 K07512 +['K18660', 'K03955+K00645', 'K09458', 'K11539+K13370', 'K22540', 'K07512'] +== +['K18660'] +['K03955+K00645'] +['K09458'] +['K11539+K13370'] +['K22540'] +['K07512'] +++++++++++++++++++ +M00874 +K11262 K03955+K00645 K09458 K00059 K22541 K07512 +['K11262', 'K03955+K00645', 'K09458', 'K00059', 'K22541', 'K07512'] +== +['K11262'] +['K03955+K00645'] +['K09458'] +['K00059'] +['K22541'] +['K07512'] +++++++++++++++++++ +M00085 +(K07508,K07509) (K00022 K07511,K07515) K07512 +['(K07508,K07509)', '(K00022_K07511,K07515)', 'K07512'] +== +['K07508', 'K07509'] +['K07515', 'K00022_K07511'] +['K07512'] +++++++++++++++++++ +M00415 +(K10247,K10205,K10248,K10249,K10244,K10203,K10250,K15397,K10245,K10246) K10251 K10703 K10258 +['(K10247,K10205,K10248,K10249,K10244,K10203,K10250,K15397,K10245,K10246)', 'K10251', 'K10703', 'K10258'] +== +['K10247', 'K10205', 'K10248', 'K10249', 'K10244', 'K10203', 'K10250', 'K15397', 'K10245', 'K10246'] +['K10251'] +['K10703'] +['K10258'] +++++++++++++++++++ +M00086 +K01897,K15013 +['K01897,K15013'] +== +['K01897', 'K15013'] +++++++++++++++++++ +M00087 +(K00232,K00249,K00255,K06445,K09479) (((K01692,K07511,K13767) (K00022,K07516)),K01825,K01782,K07514,K07515,K10527) (K00632,K07508,K07509,K07513) +['(K00232,K00249,K00255,K06445,K09479)', '(((K01692,K07511,K13767)_(K00022,K07516)),K01825,K01782,K07514,K07515,K10527)', '(K00632,K07508,K07509,K07513)'] +== +['K00232', 'K00249', 'K00255', 'K06445', 'K09479'] +['K01825', 'K01782', 'K07514', 'K07515', 'K10527', 'K01692,K07511,K13767_K00022,K07516'] +['K00632', 'K07508', 'K07509', 'K07513'] +++++++++++++++++++ +M00861 +K00232 K12405 (K07513,K08764) +['K00232', 'K12405', '(K07513,K08764)'] +== +['K00232'] +['K12405'] +['K07513', 'K08764'] +++++++++++++++++++ +M00101 +K01852 K05917 K00222 K07750 K07748 (K09827,K13373) K09828 K01824 K00227 K00213 +['K01852', 'K05917', 'K00222', 'K07750', 'K07748', '(K09827,K13373)', 'K09828', 'K01824', 'K00227', 'K00213'] +== +['K01852'] +['K05917'] +['K00222'] +['K07750'] +['K07748'] +['K09827', 'K13373'] +['K09828'] +['K01824'] +['K00227'] +['K00213'] +++++++++++++++++++ +M00102 +K00559 K09829 K00227 K09831 K00223 +['K00559', 'K09829', 'K00227', 'K09831', 'K00223'] +== +['K00559'] +['K09829'] +['K00227'] +['K09831'] +['K00223'] +++++++++++++++++++ +M00103 +K07419 K07438 +['K07419', 'K07438'] +== +['K07419'] +['K07438'] +++++++++++++++++++ +M00104 +K00489 K12408 K07431 K00251 K00037 K00488 K08748 K01796 K10214 K12405 K08764 K11992 +['K00489', 'K12408', 'K07431', 'K00251', 'K00037', 'K00488', 'K08748', 'K01796', 'K10214', 'K12405', 'K08764', 'K11992'] +== +['K00489'] +['K12408'] +['K07431'] +['K00251'] +['K00037'] +['K00488'] +['K08748'] +['K01796'] +['K10214'] +['K12405'] +['K08764'] +['K11992'] +++++++++++++++++++ +M00106 +K08748 K00659 +['K08748', 'K00659'] +== +['K08748'] +['K00659'] +++++++++++++++++++ +M00862 +K10214 K12405 K08764 +['K10214', 'K12405', 'K08764'] +== +['K10214'] +['K12405'] +['K08764'] +++++++++++++++++++ +M00107 +K00498 K00070 +['K00498', 'K00070'] +== +['K00498'] +['K00070'] +++++++++++++++++++ +M00108 +K00513 (K00497,K07433) K07433 +['K00513', '(K00497,K07433)', 'K07433'] +== +['K00513'] +['K00497', 'K07433'] +['K07433'] +++++++++++++++++++ +M00109 +K00512 K00513 K00497 (K15680,K00071) +['K00512', 'K00513', 'K00497', '(K15680,K00071)'] +== +['K00512'] +['K00513'] +['K00497'] +['K15680', 'K00071'] +++++++++++++++++++ +M00110 +K00512 K00070 K07434 +['K00512', 'K00070', 'K07434'] +== +['K00512'] +['K00070'] +['K07434'] +++++++++++++++++++ +M00089 +(K00629,K13506,K13507,K00630,K13508) (K00655,K13509,K13523,K19007,K13513,K13517,K13519,K14674,K22831) (K01080,K15728,K18693) (K11155,K11160,K14456,K22848,K22849) +['(K00629,K13506,K13507,K00630,K13508)', '(K00655,K13509,K13523,K19007,K13513,K13517,K13519,K14674,K22831)', '(K01080,K15728,K18693)', '(K11155,K11160,K14456,K22848,K22849)'] +== +['K00629', 'K13506', 'K13507', 'K00630', 'K13508'] +['K00655', 'K13509', 'K13523', 'K19007', 'K13513', 'K13517', 'K13519', 'K14674', 'K22831'] +['K01080', 'K15728', 'K18693'] +['K11155', 'K11160', 'K14456', 'K22848', 'K22849'] +++++++++++++++++++ +M00098 +(K01046,K12298,K16816,K13534,K14073,K14074,K14075,K14076,K22283,K14452,K22284,K14674,K14675,K17900) K01054 +['(K01046,K12298,K16816,K13534,K14073,K14074,K14075,K14076,K22283,K14452,K22284,K14674,K14675,K17900)', 'K01054'] +== +['K01046', 'K12298', 'K16816', 'K13534', 'K14073', 'K14074', 'K14075', 'K14076', 'K22283', 'K14452', 'K22284', 'K14674', 'K14675', 'K17900'] +['K01054'] +++++++++++++++++++ +M00090 +(K00866,K14156) K00968 (K00994,K13644) +['(K00866,K14156)', 'K00968', '(K00994,K13644)'] +== +['K00866', 'K14156'] +['K00968'] +['K00994', 'K13644'] +++++++++++++++++++ +M00091 +K00551,(K16369 K00550),K00570 +['K00551,(K16369_K00550),K00570'] +== +['K00551', 'K00570', 'K16369_K00550'] +++++++++++++++++++ +M00092 +(K00894,K14156) K00967 (K00993,K13644) +['(K00894,K14156)', 'K00967', '(K00993,K13644)'] +== +['K00894', 'K14156'] +['K00967'] +['K00993', 'K13644'] +++++++++++++++++++ +M00093 +K00981 (K00998,K17103) K01613 +['K00981', '(K00998,K17103)', 'K01613'] +== +['K00981'] +['K00998', 'K17103'] +['K01613'] +++++++++++++++++++ +M00094 +K00654 K04708 (K04709,K04710,K23727) K04712 +['K00654', 'K04708', '(K04709,K04710,K23727)', 'K04712'] +== +['K00654'] +['K04708'] +['K04709', 'K04710', 'K23727'] +['K04712'] +++++++++++++++++++ +M00066 +K00720 K07553 +['K00720', 'K07553'] +== +['K00720'] +['K07553'] +++++++++++++++++++ +M00067 +K04628 K01019 +['K04628', 'K01019'] +== +['K04628'] +['K01019'] +++++++++++++++++++ +M00099 +K00654 K04708 (K04709,K04710,K23727) K04712 (K01441,K12348,K12349) +['K00654', 'K04708', '(K04709,K04710,K23727)', 'K04712', '(K01441,K12348,K12349)'] +== +['K00654'] +['K04708'] +['K04709', 'K04710', 'K23727'] +['K04712'] +['K01441', 'K12348', 'K12349'] +++++++++++++++++++ +M00100 +K04718 K01634 +['K04718', 'K01634'] +== +['K04718'] +['K01634'] +++++++++++++++++++ +M00113 +K00454 K01723 K10525 K05894 K10526 K00232 K10527 K07513 -- +['K00454', 'K01723', 'K10525', 'K05894', 'K10526', 'K00232', 'K10527', 'K07513'] +== +['K00454'] +['K01723'] +['K10525'] +['K05894'] +['K10526'] +['K00232'] +['K10527'] +['K07513'] +++++++++++++++++++ +M00049 +K01939 K01756 (K00939,K18532,K18533,K00944) (K00940,K00873,K12406) +['K01939', 'K01756', '(K00939,K18532,K18533,K00944)', '(K00940,K00873,K12406)'] +== +['K01939'] +['K01756'] +['K00939', 'K18532', 'K18533', 'K00944'] +['K00940', 'K00873', 'K12406'] +++++++++++++++++++ +M00050 +K00088 K01951 K00942 (K00940,K18533,K00873,K12406) +['K00088', 'K01951', 'K00942', '(K00940,K18533,K00873,K12406)'] +== +['K00088'] +['K01951'] +['K00942'] +['K00940', 'K18533', 'K00873', 'K12406'] +++++++++++++++++++ +M00546 +(K00106,K00087+K13479+K13480,K13481+K13482,K11177+K11178+K13483) (K00365,K16838,K16839,K22879) (K13484,K07127 (K13485,K16838,K16840)) (K01466,K16842) K01477 +['(K00106,K00087+K13479+K13480,K13481+K13482,K11177+K11178+K13483)', '(K00365,K16838,K16839,K22879)', '(K13484,K07127_(K13485,K16838,K16840))', '(K01466,K16842)', 'K01477'] +== +['K00106', 'K13481+K13482', 'K00087+K13479+K13480', 'K11177+K11178+K13483'] +['K00365', 'K16838', 'K16839', 'K22879'] +['K13484', 'K07127_K13485,K16838,K16840'] +['K01466', 'K16842'] +['K01477'] +++++++++++++++++++ +M00051 +(K11540,(K11541 K01465),((K01954,K01955+K01956) (K00609+K00610,K00608) K01465)) (K00226,K00254,K17828) (K13421,K00762 K01591) +['(K11540,(K11541_K01465),((K01954,K01955+K01956)_(K00609+K00610,K00608)_K01465))', '(K00226,K00254,K17828)', '(K13421,K00762_K01591)'] +== +['K11540', 'K11541_K01465', 'K01954,K01955+K01956_K00609+K00610,K00608_K01465'] +['K00226', 'K00254', 'K17828'] +['K13421', 'K00762_K01591'] +++++++++++++++++++ +M00052 +(K13800,K13809,K09903) (K00940,K18533) K01937 +['(K13800,K13809,K09903)', '(K00940,K18533)', 'K01937'] +== +['K13800', 'K13809', 'K09903'] +['K00940', 'K18533'] +['K01937'] +++++++++++++++++++ +M00053 +(K00524,K00525+K00526,K10807+K10808) (K00940,K18533) (K00527,K21636) K01494 K01520 (K00560,K13998) K00943 K00940 +['(K00524,K00525+K00526,K10807+K10808)', '(K00940,K18533)', '(K00527,K21636)', 'K01494', 'K01520', '(K00560,K13998)', 'K00943', 'K00940'] +== +['K00524', 'K00525+K00526', 'K10807+K10808'] +['K00940', 'K18533'] +['K00527', 'K21636'] +['K01494'] +['K01520'] +['K00560', 'K13998'] +['K00943'] +['K00940'] +++++++++++++++++++ +M00046 +(K00207,K17722+K17723) K01464 (K01431,K06016) +['(K00207,K17722+K17723)', 'K01464', '(K01431,K06016)'] +== +['K00207', 'K17722+K17723'] +['K01464'] +['K01431', 'K06016'] +++++++++++++++++++ +M00020 +K00058 K00831 (K01079,K02203,K22305) +['K00058', 'K00831', '(K01079,K02203,K22305)'] +== +['K00058'] +['K00831'] +['K01079', 'K02203', 'K22305'] +++++++++++++++++++ +M00018 +(K00928,K12524,K12525,K12526) K00133 (K00003,K12524,K12525) (K00872,K02204,K02203) K01733 +['(K00928,K12524,K12525,K12526)', 'K00133', '(K00003,K12524,K12525)', '(K00872,K02204,K02203)', 'K01733'] +== +['K00928', 'K12524', 'K12525', 'K12526'] +['K00133'] +['K00003', 'K12524', 'K12525'] +['K00872', 'K02204', 'K02203'] +['K01733'] +++++++++++++++++++ +M00555 +(K17755,((K00108,K11440,K00499) (K00130,K14085))) +['(K17755,((K00108,K11440,K00499)_(K00130,K14085)))'] +== +['K17755', 'K00108,K11440,K00499_K00130,K14085'] +++++++++++++++++++ +M00033 +K00928 K00133 K00836 K06718 K06720 +['K00928', 'K00133', 'K00836', 'K06718', 'K06720'] +== +['K00928'] +['K00133'] +['K00836'] +['K06718'] +['K06720'] +++++++++++++++++++ +M00021 +(K00640,K23304) (K01738,K13034,K17069) +['(K00640,K23304)', '(K01738,K13034,K17069)'] +== +['K00640', 'K23304'] +['K01738', 'K13034', 'K17069'] +++++++++++++++++++ +M00338 +(K01697,K10150) K01758 +['(K01697,K10150)', 'K01758'] +== +['K01697', 'K10150'] +['K01758'] +++++++++++++++++++ +M00609 +K00789 K17462 K01243 K07173 K17216 K17217 +['K00789', 'K17462', 'K01243', 'K07173', 'K17216', 'K17217'] +== +['K00789'] +['K17462'] +['K01243'] +['K07173'] +['K17216'] +['K17217'] +++++++++++++++++++ +M00017 +(K00928,K12524,K12525) K00133 (K00003,K12524,K12525) (K00651,K00641) K01739 (K01760,K14155) (K00548,K24042,K00549) +['(K00928,K12524,K12525)', 'K00133', '(K00003,K12524,K12525)', '(K00651,K00641)', 'K01739', '(K01760,K14155)', '(K00548,K24042,K00549)'] +== +['K00928', 'K12524', 'K12525'] +['K00133'] +['K00003', 'K12524', 'K12525'] +['K00651', 'K00641'] +['K01739'] +['K01760', 'K14155'] +['K00548', 'K24042', 'K00549'] +++++++++++++++++++ +M00034 +K00789 K01611 K00797 ((K01243,K01244) K00899,K00772) K08963 (K16054,K08964 (K09880,K08965 K08966)) K08967 (K00815,K08969,K23977,K00832,K00838) +['K00789', 'K01611', 'K00797', '((K01243,K01244)_K00899,K00772)', 'K08963', '(K16054,K08964_(K09880,K08965_K08966))', 'K08967', '(K00815,K08969,K23977,K00832,K00838)'] +== +['K00789'] +['K01611'] +['K00797'] +['K00772', 'K01243,K01244_K00899'] +['K08963'] +['K16054', 'K08964_K09880,K08965_K08966'] +['K08967'] +['K00815', 'K08969', 'K23977', 'K00832', 'K00838'] +++++++++++++++++++ +M00035 +K00789 (K00558,K17398,K17399) K01251 (K01697,K10150) +['K00789', '(K00558,K17398,K17399)', 'K01251', '(K01697,K10150)'] +== +['K00789'] +['K00558', 'K17398', 'K17399'] +['K01251'] +['K01697', 'K10150'] +++++++++++++++++++ +M00368 +K00789 (K01762,K20772) K05933 +['K00789', '(K01762,K20772)', 'K05933'] +== +['K00789'] +['K01762', 'K20772'] +['K05933'] +++++++++++++++++++ +M00019 +K01652+(K01653,K11258) K00053 K01687 K00826 +['K01652+(K01653,K11258)', 'K00053', 'K01687', 'K00826'] +== +['K11258', 'K01652+K01653'] +['K00053'] +['K01687'] +['K00826'] +++++++++++++++++++ +M00535 +K09011 K01703+K01704 K00052 +['K09011', 'K01703+K01704', 'K00052'] +== +['K09011'] +['K01703+K01704'] +['K00052'] +++++++++++++++++++ +M00570 +(K17989,K01754) K01652+(K01653,K11258) K00053 K01687 K00826 +['(K17989,K01754)', 'K01652+(K01653,K11258)', 'K00053', 'K01687', 'K00826'] +== +['K17989', 'K01754'] +['K11258', 'K01652+K01653'] +['K00053'] +['K01687'] +['K00826'] +++++++++++++++++++ +M00432 +K01649 (K01702,K01703+K01704) K00052 +['K01649', '(K01702,K01703+K01704)', 'K00052'] +== +['K01649'] +['K01702', 'K01703+K01704'] +['K00052'] +++++++++++++++++++ +M00036 +K00826 ((K00166+K00167,K11381)+K09699+K00382) (K00253,K00249) (K01968+K01969) (K05607,K13766) K01640 +['K00826', '((K00166+K00167,K11381)+K09699+K00382)', '(K00253,K00249)', '(K01968+K01969)', '(K05607,K13766)', 'K01640'] +== +['K00826'] +['K00166+K00167,K11381+K09699+K00382'] +['K00253', 'K00249'] +['K01968+K01969'] +['K05607', 'K13766'] +['K01640'] +++++++++++++++++++ +M00016 +(K00928,K12524,K12525,K12526) K00133 K01714 K00215 K00674 (K00821,K14267) K01439 K01778 (K01586,K12526) +['(K00928,K12524,K12525,K12526)', 'K00133', 'K01714', 'K00215', 'K00674', '(K00821,K14267)', 'K01439', 'K01778', '(K01586,K12526)'] +== +['K00928', 'K12524', 'K12525', 'K12526'] +['K00133'] +['K01714'] +['K00215'] +['K00674'] +['K00821', 'K14267'] +['K01439'] +['K01778'] +['K01586', 'K12526'] +++++++++++++++++++ +M00525 +K00928 K00133 K01714 K00215 K05822 K00841 K05823 K01778 K01586 +['K00928', 'K00133', 'K01714', 'K00215', 'K05822', 'K00841', 'K05823', 'K01778', 'K01586'] +== +['K00928'] +['K00133'] +['K01714'] +['K00215'] +['K05822'] +['K00841'] +['K05823'] +['K01778'] +['K01586'] +++++++++++++++++++ +M00526 +(K00928,K12524,K12525,K12526) K00133 K01714 K00215 K03340 (K01586,K12526) +['(K00928,K12524,K12525,K12526)', 'K00133', 'K01714', 'K00215', 'K03340', '(K01586,K12526)'] +== +['K00928', 'K12524', 'K12525', 'K12526'] +['K00133'] +['K01714'] +['K00215'] +['K03340'] +['K01586', 'K12526'] +++++++++++++++++++ +M00527 +(K00928,K12524,K12525,K12526) K00133 K01714 K00215 K10206 K01778 (K01586,K12526) +['(K00928,K12524,K12525,K12526)', 'K00133', 'K01714', 'K00215', 'K10206', 'K01778', '(K01586,K12526)'] +== +['K00928', 'K12524', 'K12525', 'K12526'] +['K00133'] +['K01714'] +['K00215'] +['K10206'] +['K01778'] +['K01586', 'K12526'] +++++++++++++++++++ +M00030 +K01655 K17450 K01705 K05824 K00838 K00143 (K00293,K24034) K00290 +['K01655', 'K17450', 'K01705', 'K05824', 'K00838', 'K00143', '(K00293,K24034)', 'K00290'] +== +['K01655'] +['K17450'] +['K01705'] +['K05824'] +['K00838'] +['K00143'] +['K00293', 'K24034'] +['K00290'] +++++++++++++++++++ +M00433 +K01655 (K17450 K01705,K16792+K16793) K05824 +['K01655', '(K17450_K01705,K16792+K16793)', 'K05824'] +== +['K01655'] +['K17450_K01705', 'K16792+K16793'] +['K05824'] +++++++++++++++++++ +M00032 +K14157 K14085 K00825 (K15791+K00658+K00382) K00252 (K07514,(K07515,K07511) K00022) +['K14157', 'K14085', 'K00825', '(K15791+K00658+K00382)', 'K00252', '(K07514,(K07515,K07511)_K00022)'] +== +['K14157'] +['K14085'] +['K00825'] +['K15791+K00658+K00382'] +['K00252'] +['K07514', 'K07515,K07511_K00022'] +++++++++++++++++++ +M00028 +(K00618,K00619,K14681,K14682,K00620,K22477,K22478) ((K00930,K22478) K00145,K12659) (K00818,K00821) (K01438,K14677,K00620) +['(K00618,K00619,K14681,K14682,K00620,K22477,K22478)', '((K00930,K22478)_K00145,K12659)', '(K00818,K00821)', '(K01438,K14677,K00620)'] +== +['K00618', 'K00619', 'K14681', 'K14682', 'K00620', 'K22477', 'K22478'] +['K12659', 'K00930,K22478_K00145'] +['K00818', 'K00821'] +['K01438', 'K14677', 'K00620'] +++++++++++++++++++ +M00844 +K00611 K01940 (K01755,K14681) +['K00611', 'K01940', '(K01755,K14681)'] +== +['K00611'] +['K01940'] +['K01755', 'K14681'] +++++++++++++++++++ +M00845 +K22478 K00145 K00821 K09065 K01438 K01940 K01755 +['K22478', 'K00145', 'K00821', 'K09065', 'K01438', 'K01940', 'K01755'] +== +['K22478'] +['K00145'] +['K00821'] +['K09065'] +['K01438'] +['K01940'] +['K01755'] +++++++++++++++++++ +M00029 +K01948 K00611 K01940 (K01755,K14681) K01476 +['K01948', 'K00611', 'K01940', '(K01755,K14681)', 'K01476'] +== +['K01948'] +['K00611'] +['K01940'] +['K01755', 'K14681'] +['K01476'] +++++++++++++++++++ +M00015 +((K00931 K00147),K12657) K00286 +['((K00931_K00147),K12657)', 'K00286'] +== +['K12657', 'K00931_K00147'] +['K00286'] +++++++++++++++++++ +M00047 +K00613 K00542 K00933 +['K00613', 'K00542', 'K00933'] +== +['K00613'] +['K00542'] +['K00933'] +++++++++++++++++++ +M00879 +K00673 K01484 K00840 K06447 K05526 +['K00673', 'K01484', 'K00840', 'K06447', 'K05526'] +== +['K00673'] +['K01484'] +['K00840'] +['K06447'] +['K05526'] +++++++++++++++++++ +M00134 +K01476 K01581 +['K01476', 'K01581'] +== +['K01476'] +['K01581'] +++++++++++++++++++ +M00135 +K00657 K00274 (K00128,K14085,K00149) -- +['K00657', 'K00274', '(K00128,K14085,K00149)'] +== +['K00657'] +['K00274'] +['K00128', 'K14085', 'K00149'] +++++++++++++++++++ +M00136 +K09470 K09471 K09472 K09473 +['K09470', 'K09471', 'K09472', 'K09473'] +== +['K09470'] +['K09471'] +['K09472'] +['K09473'] +++++++++++++++++++ +M00026 +(K00765-K02502) (K01523 K01496,K11755,K14152) (K01814,K24017) (K02501+K02500,K01663) ((K01693 K00817 (K04486,K05602,K18649)),(K01089 K00817)) (K00013,K14152) +['(K00765-K02502)', '(K01523_K01496,K11755,K14152)', '(K01814,K24017)', '(K02501+K02500,K01663)', '((K01693_K00817_(K04486,K05602,K18649)),(K01089_K00817))', '(K00013,K14152)'] +== +['K00765-K02502'] +['K11755', 'K14152', 'K01523_K01496'] +['K01814', 'K24017'] +['K01663', 'K02501+K02500'] +['K01089_K00817', 'K01693_K00817_K04486,K05602,K18649'] +['K00013', 'K14152'] +++++++++++++++++++ +M00045 +K01745 K01712 K01468 (K01479,K00603,K13990,(K05603 K01458)) +['K01745', 'K01712', 'K01468', '(K01479,K00603,K13990,(K05603_K01458))'] +== +['K01745'] +['K01712'] +['K01468'] +['K01479', 'K00603', 'K13990', 'K05603_K01458'] +++++++++++++++++++ +M00022 +(K01626,K03856,K13853) (((K01735,K13829) ((K03785,K03786) K00014,K13832)),K13830) ((K00891,K13829) (K00800,K24018),K13830) K01736 +['(K01626,K03856,K13853)', '(((K01735,K13829)_((K03785,K03786)_K00014,K13832)),K13830)', '((K00891,K13829)_(K00800,K24018),K13830)', 'K01736'] +== +['K01626', 'K03856', 'K13853'] +['K13830', 'K01735,K13829_K03785,K03786_K00014,K13832'] +['K13830', 'K00891,K13829_K00800,K24018'] +['K01736'] +++++++++++++++++++ +M00023 +(((K01657+K01658,K13503,K13501,K01656) K00766),K13497) (((K01817,K24017) (K01656,K01609)),K13498,K13501) (K01695+(K01696,K06001),K01694) +['(((K01657+K01658,K13503,K13501,K01656)_K00766),K13497)', '(((K01817,K24017)_(K01656,K01609)),K13498,K13501)', '(K01695+(K01696,K06001),K01694)'] +== +['K13497', 'K01657+K01658,K13503,K13501,K01656_K00766'] +['K13498', 'K13501', 'K01817,K24017_K01656,K01609'] +['K01694', 'K01695+K01696,K06001'] +++++++++++++++++++ +M00024 +((K01850,K04092,K14187,K04093,K04516,K06208,K06209,K13853) (K01713,K04518,K05359),K14170) (K00832,K00838) +['((K01850,K04092,K14187,K04093,K04516,K06208,K06209,K13853)_(K01713,K04518,K05359),K14170)', '(K00832,K00838)'] +== +['K14170', 'K01850,K04092,K14187,K04093,K04516,K06208,K06209,K13853_K01713,K04518,K05359'] +['K00832', 'K00838'] +++++++++++++++++++ +M00025 +(((K01850,K04092,K14170,K04093,K04516,K06208,K06209,K13853) K04517),K14187) (K00815,K00832,K00838) +['(((K01850,K04092,K14170,K04093,K04516,K06208,K06209,K13853)_K04517),K14187)', '(K00815,K00832,K00838)'] +== +['K14187', 'K01850,K04092,K14170,K04093,K04516,K06208,K06209,K13853_K04517'] +['K00815', 'K00832', 'K00838'] +++++++++++++++++++ +M00040 +(K00832,K15849) (K00220,K24018,K15226,K15227) +['(K00832,K15849)', '(K00220,K24018,K15226,K15227)'] +== +['K00832', 'K15849'] +['K00220', 'K24018', 'K15226', 'K15227'] +++++++++++++++++++ +M00042 +(K00505,K00501) (K01592,K01593) K00503 K00553 +['(K00505,K00501)', '(K01592,K01593)', 'K00503', 'K00553'] +== +['K00505', 'K00501'] +['K01592', 'K01593'] +['K00503'] +['K00553'] +++++++++++++++++++ +M00043 +K00431 +['K00431'] +== +['K00431'] +++++++++++++++++++ +M00044 +(K00815,K00838,K03334) K00457 K00451 K01800 (K01555,K16171) +['(K00815,K00838,K03334)', 'K00457', 'K00451', 'K01800', '(K01555,K16171)'] +== +['K00815', 'K00838', 'K03334'] +['K00457'] +['K00451'] +['K01800'] +['K01555', 'K16171'] +++++++++++++++++++ +M00533 +K00455 K00151 K01826 K05921 +['K00455', 'K00151', 'K01826', 'K05921'] +== +['K00455'] +['K00151'] +['K01826'] +['K05921'] +++++++++++++++++++ +M00545 +(((K05708+K05709+K05710+K00529) K05711),K05712) K05713 K05714 K02554 K01666 K04073 +['(((K05708+K05709+K05710+K00529)_K05711),K05712)', 'K05713', 'K05714', 'K02554', 'K01666', 'K04073'] +== +['K05712', 'K05708+K05709+K05710+K00529_K05711'] +['K05713'] +['K05714'] +['K02554'] +['K01666'] +['K04073'] +++++++++++++++++++ +M00037 +K00502 K01593 K00669 K00543 +['K00502', 'K01593', 'K00669', 'K00543'] +== +['K00502'] +['K01593'] +['K00669'] +['K00543'] +++++++++++++++++++ +M00038 +(K00453,K00463) (K01432,K14263,K07130) K00486 K01556 K00452 K03392 (K10217,K23234) +['(K00453,K00463)', '(K01432,K14263,K07130)', 'K00486', 'K01556', 'K00452', 'K03392', '(K10217,K23234)'] +== +['K00453', 'K00463'] +['K01432', 'K14263', 'K07130'] +['K00486'] +['K01556'] +['K00452'] +['K03392'] +['K10217', 'K23234'] +++++++++++++++++++ +M00027 +K01580 (K13524,K07250,K00823,K16871) (K00135,K00139,K17761) +['K01580', '(K13524,K07250,K00823,K16871)', '(K00135,K00139,K17761)'] +== +['K01580'] +['K13524', 'K07250', 'K00823', 'K16871'] +['K00135', 'K00139', 'K17761'] +++++++++++++++++++ +M00369 +K13027 K13029 K13030 +['K13027', 'K13029', 'K13030'] +== +['K13027'] +['K13029'] +['K13030'] +++++++++++++++++++ +M00118 +(K11204+K11205,K01919) (K21456,K01920) +['(K11204+K11205,K01919)', '(K21456,K01920)'] +== +['K01919', 'K11204+K11205'] +['K21456', 'K01920'] +++++++++++++++++++ +M00055 +K01001 (K07432+K07441) K03842 K03843 K03844 K03845 K03846 K03847 K03846 K00729 K03848 K03849 K03850 +['K01001', '(K07432+K07441)', 'K03842', 'K03843', 'K03844', 'K03845', 'K03846', 'K03847', 'K03846', 'K00729', 'K03848', 'K03849', 'K03850'] +== +['K01001'] +['K07432+K07441'] +['K03842'] +['K03843'] +['K03844'] +['K03845'] +['K03846'] +['K03847'] +['K03846'] +['K00729'] +['K03848'] +['K03849'] +['K03850'] +++++++++++++++++++ +M00072 +K07151+K12666+K12667+K12668+K12669+K12670-K00730-K12691 +['K07151+K12666+K12667+K12668+K12669+K12670-K00730-K12691'] +== +['K07151+K12666+K12667+K12668+K12669+K12670-K00730-K12691'] +++++++++++++++++++ +M00073 +K01228 K05546 K23741 K01230 +['K01228', 'K05546', 'K23741', 'K01230'] +== +['K01228'] +['K05546'] +['K23741'] +['K01230'] +++++++++++++++++++ +M00074 +K05546 K23741 K01230 K05528 K05529+K05530 K05529+K05531+K05532+K05533+K05534 K05535 +['K05546', 'K23741', 'K01230', 'K05528', 'K05529+K05530', 'K05529+K05531+K05532+K05533+K05534', 'K05535'] +== +['K05546'] +['K23741'] +['K01230'] +['K05528'] +['K05529+K05530'] +['K05529+K05531+K05532+K05533+K05534'] +['K05535'] +++++++++++++++++++ +M00056 +K00710 (K00731,K09653) (K00727,K09662,K09663) K00739 +['K00710', '(K00731,K09653)', '(K00727,K09662,K09663)', 'K00739'] +== +['K00710'] +['K00731', 'K09653'] +['K00727', 'K09662', 'K09663'] +['K00739'] +++++++++++++++++++ +M00065 +(K03857+K03859+K03858+K03861+K03860+(K11001,K11002)-K09658) K03434 K05283 (K05284+K07541) K07542 K05285 K05286 (K05288+K05287) +['(K03857+K03859+K03858+K03861+K03860+(K11001,K11002)-K09658)', 'K03434', 'K05283', '(K05284+K07541)', 'K07542', 'K05285', 'K05286', '(K05288+K05287)'] +== +['K03857+K03859+K03858+K03861+K03860+K11001,K11002-K09658'] +['K03434'] +['K05283'] +['K05284+K07541'] +['K07542'] +['K05285'] +['K05286'] +['K05288+K05287'] +++++++++++++++++++ +M00070 +K03766 (K07819,K07820,K03877) +['K03766', '(K07819,K07820,K03877)'] +== +['K03766'] +['K07819', 'K07820', 'K03877'] +++++++++++++++++++ +M00071 +K03766 (K07966,K07967,K07968,K07969) +['K03766', '(K07966,K07967,K07968,K07969)'] +== +['K03766'] +['K07966', 'K07967', 'K07968', 'K07969'] +++++++++++++++++++ +M00068 +K01988 K00719 +['K01988', 'K00719'] +== +['K01988'] +['K00719'] +++++++++++++++++++ +M00069 +K03370 (K03371,K03369) +['K03370', '(K03371,K03369)'] +== +['K03370'] +['K03371', 'K03369'] +++++++++++++++++++ +M00057 +K00771 K00733 K00734 K10158 +['K00771', 'K00733', 'K00734', 'K10158'] +== +['K00771'] +['K00733'] +['K00734'] +['K10158'] +++++++++++++++++++ +M00058 +K00746 (K13499,K00747,K03419) +['K00746', '(K13499,K00747,K03419)'] +== +['K00746'] +['K13499', 'K00747', 'K03419'] +++++++++++++++++++ +M00059 +(K02369,K02370) (K02366,K02367) (K02368,K02370) (K02576,K02577,K02578,K02579) K01793 +['(K02369,K02370)', '(K02366,K02367)', '(K02368,K02370)', '(K02576,K02577,K02578,K02579)', 'K01793'] +== +['K02369', 'K02370'] +['K02366', 'K02367'] +['K02368', 'K02370'] +['K02576', 'K02577', 'K02578', 'K02579'] +['K01793'] +++++++++++++++++++ +M00076 +-- K01136 K01217 K01135 K01197 K01195 +['K01136', 'K01217', 'K01135', 'K01197', 'K01195'] +== +['K01136'] +['K01217'] +['K01135'] +['K01197'] +['K01195'] +++++++++++++++++++ +M00077 +K01135 K01197 K01195 K01132 +['K01135', 'K01197', 'K01195', 'K01132'] +== +['K01135'] +['K01197'] +['K01195'] +['K01132'] +++++++++++++++++++ +M00078 +(K07964,K07965) K01136 K01217 K01565 K10532 K01205 -- K01195 K01137 +['(K07964,K07965)', 'K01136', 'K01217', 'K01565', 'K10532', 'K01205', 'K01195', 'K01137'] +== +['K07964', 'K07965'] +['K01136'] +['K01217'] +['K01565'] +['K10532'] +['K01205'] +['K01195'] +['K01137'] +++++++++++++++++++ +M00079 +-- K01132 K12309 K01137 K12373 +['K01132', 'K12309', 'K01137', 'K12373'] +== +['K01132'] +['K12309'] +['K01137'] +['K12373'] +++++++++++++++++++ +M00060 +K00677 K02535 K02536 K03269 K00748 K00912 K02527 K02517 K02560 +['K00677', 'K02535', 'K02536', 'K03269', 'K00748', 'K00912', 'K02527', 'K02517', 'K02560'] +== +['K00677'] +['K02535'] +['K02536'] +['K03269'] +['K00748'] +['K00912'] +['K02527'] +['K02517'] +['K02560'] +++++++++++++++++++ +M00866 +K00677 (K02535,K16363) K02536 K03269 K00748 K00912 K02527 K02517 K09778 +['K00677', '(K02535,K16363)', 'K02536', 'K03269', 'K00748', 'K00912', 'K02527', 'K02517', 'K09778'] +== +['K00677'] +['K02535', 'K16363'] +['K02536'] +['K03269'] +['K00748'] +['K00912'] +['K02527'] +['K02517'] +['K09778'] +++++++++++++++++++ +M00867 +K12977 K03760 K23082+K23083 K23159 K09953 +['K12977', 'K03760', 'K23082+K23083', 'K23159', 'K09953'] +== +['K12977'] +['K03760'] +['K23082+K23083'] +['K23159'] +['K09953'] +++++++++++++++++++ +M00063 +K06041 K01627 K03270 K00979 +['K06041', 'K01627', 'K03270', 'K00979'] +== +['K06041'] +['K01627'] +['K03270'] +['K00979'] +++++++++++++++++++ +M00064 +K03271 (K03272,K21344) K03273 (K03272,K21345) K03274 +['K03271', '(K03272,K21344)', 'K03273', '(K03272,K21345)', 'K03274'] +== +['K03271'] +['K03272', 'K21344'] +['K03273'] +['K03272', 'K21345'] +['K03274'] +++++++++++++++++++ +M00127 +K03147 (K00877,K00941,K14153)(K00878,K14154)(K00788,K14153,K14154) K00946 +['K03147', '(K00877,K00941,K14153)(K00878,K14154)(K00788,K14153,K14154)', 'K00946'] +== +['K03147'] +['K00877', 'K00941', 'K14153', 'K14154', 'K14153K00878', 'K14154K00788'] +['K00946'] +++++++++++++++++++ +M00124 +K03472 K03473 K00831 K00097 K03474 (K00275,K23998) +['K03472', 'K03473', 'K00831', 'K00097', 'K03474', '(K00275,K23998)'] +== +['K03472'] +['K03473'] +['K00831'] +['K00097'] +['K03474'] +['K00275', 'K23998'] +++++++++++++++++++ +M00115 +K00278 K03517 K00767 (K00969,K06210) (K01916,K01950) +['K00278', 'K03517', 'K00767', '(K00969,K06210)', '(K01916,K01950)'] +== +['K00278'] +['K03517'] +['K00767'] +['K00969', 'K06210'] +['K01916', 'K01950'] +++++++++++++++++++ +M00810 +K19818+K19819+K19820 (K19826,K19890) K19185+K19186+K19187 K19188 -K20155 +['K19818+K19819+K19820', '(K19826,K19890)', 'K19185+K19186+K19187', 'K19188', '-K20155'] +== +['K19818+K19819+K19820'] +['K19826', 'K19890'] +['K19185+K19186+K19187'] +['K19188'] +['-K20155'] +++++++++++++++++++ +M00811 +K20170,K20169 (K20170,(K20158 K19700)) K20171-K20172 K15359,K18276 +['K20170,K20169', '(K20170,(K20158_K19700))', 'K20171-K20172', 'K15359,K18276'] +== +['K20170', 'K20169'] +['K20170', 'K20158_K19700'] +['K20171-K20172'] +['K15359', 'K18276'] +++++++++++++++++++ +M00622 +K18029+K18030 K14974 K18028 K15357 K13995 K01799 +['K18029+K18030', 'K14974', 'K18028', 'K15357', 'K13995', 'K01799'] +== +['K18029+K18030'] +['K14974'] +['K18028'] +['K15357'] +['K13995'] +['K01799'] +++++++++++++++++++ +M00120 +(K00867,K03525,K09680,K01947) ((K01922,K21977) K01598,K13038) (K02318,(K00954,K02201) K00859) +['(K00867,K03525,K09680,K01947)', '((K01922,K21977)_K01598,K13038)', '(K02318,(K00954,K02201)_K00859)'] +== +['K00867', 'K03525', 'K09680', 'K01947'] +['K13038', 'K01922,K21977_K01598'] +['K02318', 'K00954,K02201_K00859'] +++++++++++++++++++ +M00572 +K02169 (K00647,K09458) K00059 K02372 K00208 (K02170,K09789,K19560,K19561) +['K02169', '(K00647,K09458)', 'K00059', 'K02372', 'K00208', '(K02170,K09789,K19560,K19561)'] +== +['K02169'] +['K00647', 'K09458'] +['K00059'] +['K02372'] +['K00208'] +['K02170', 'K09789', 'K19560', 'K19561'] +++++++++++++++++++ +M00123 +K00652 ((K00833,K19563) K01935,K19562) K01012 +['K00652', '((K00833,K19563)_K01935,K19562)', 'K01012'] +== +['K00652'] +['K19562', 'K00833,K19563_K01935'] +['K01012'] +++++++++++++++++++ +M00573 +K16593 K00652 K19563 K01935 K01012 +['K16593', 'K00652', 'K19563', 'K01935', 'K01012'] +== +['K16593'] +['K00652'] +['K19563'] +['K01935'] +['K01012'] +++++++++++++++++++ +M00577 +K01906 K00652 (K00833,K19563) K01935 K01012 +['K01906', 'K00652', '(K00833,K19563)', 'K01935', 'K01012'] +== +['K01906'] +['K00652'] +['K00833', 'K19563'] +['K01935'] +['K01012'] +++++++++++++++++++ +M00126 +(K01495,K09007,K22391) (K01077,K01113,(K08310,K19965)) ((K13939,(K13940,K01633 K00950) K00796),(K01633 K13941)) (K11754,K20457) (K00287,K13998) +['(K01495,K09007,K22391)', '(K01077,K01113,(K08310,K19965))', '((K13939,(K13940,K01633_K00950)_K00796),(K01633_K13941))', '(K11754,K20457)', '(K00287,K13998)'] +== +['K01495', 'K09007', 'K22391'] +['K01077', 'K01113', 'K08310,K19965'] +['K01633_K13941', 'K13939,K13940,K01633_K00950_K00796'] +['K11754', 'K20457'] +['K00287', 'K13998'] +++++++++++++++++++ +M00840 +K14652 K22100 -- K01633 K13941 K22099 K00287 +['K14652', 'K22100', 'K01633', 'K13941', 'K22099', 'K00287'] +== +['K14652'] +['K22100'] +['K01633'] +['K13941'] +['K22099'] +['K00287'] +++++++++++++++++++ +M00841 +K01495 K22101 K00950 K00796 K11754 K13998 +['K01495', 'K22101', 'K00950', 'K00796', 'K11754', 'K13998'] +== +['K01495'] +['K22101'] +['K00950'] +['K00796'] +['K11754'] +['K13998'] +++++++++++++++++++ +M00842 +K01495 K01737 K00072 +['K01495', 'K01737', 'K00072'] +== +['K01495'] +['K01737'] +['K00072'] +++++++++++++++++++ +M00843 +K01495 K01737 K17745 +['K01495', 'K01737', 'K17745'] +== +['K01495'] +['K01737'] +['K17745'] +++++++++++++++++++ +M00880 +((K03639 K03637),K20967) (K03635,K21142) (((K03831,K03638) K03750),K15376) +['((K03639_K03637),K20967)', '(K03635,K21142)', '(((K03831,K03638)_K03750),K15376)'] +== +['K20967', 'K03639_K03637'] +['K03635', 'K21142'] +['K15376', 'K03831,K03638_K03750'] +++++++++++++++++++ +M00140 +K00600 (K01491,(K00300 K01500)) K01938 +['K00600', '(K01491,(K00300_K01500))', 'K01938'] +== +['K00600'] +['K01491', 'K00300_K01500'] +['K01938'] +++++++++++++++++++ +M00141 +K00600 (K00288,(K13403 K13402)) +['K00600', '(K00288,(K13403_K13402))'] +== +['K00600'] +['K00288', 'K13403_K13402'] +++++++++++++++++++ +M00868 +K00643 K01698 K01749 K01719 K01599 K00228 K00231 K01772 +['K00643', 'K01698', 'K01749', 'K01719', 'K01599', 'K00228', 'K00231', 'K01772'] +== +['K00643'] +['K01698'] +['K01749'] +['K01719'] +['K01599'] +['K00228'] +['K00231'] +['K01772'] +++++++++++++++++++ +M00121 +(K01885,K14163) K02492 K01845 K01698 K01749 (K01719,K13542,K13543) K01599 (K00228,K02495) (K00230,K00231) K01772 +['(K01885,K14163)', 'K02492', 'K01845', 'K01698', 'K01749', '(K01719,K13542,K13543)', 'K01599', '(K00228,K02495)', '(K00230,K00231)', 'K01772'] +== +['K01885', 'K14163'] +['K02492'] +['K01845'] +['K01698'] +['K01749'] +['K01719', 'K13542', 'K13543'] +['K01599'] +['K00228', 'K02495'] +['K00230', 'K00231'] +['K01772'] +++++++++++++++++++ +M00846 +(K01885,K14163) K02492 K01845 K01698 K01749 (K01719,K13542,K13543) (K02302,(K00589,K02303,K02496,K13542,K13543)+K02304-K03794) +['(K01885,K14163)', 'K02492', 'K01845', 'K01698', 'K01749', '(K01719,K13542,K13543)', '(K02302,(K00589,K02303,K02496,K13542,K13543)+K02304-K03794)'] +== +['K01885', 'K14163'] +['K02492'] +['K01845'] +['K01698'] +['K01749'] +['K01719', 'K13542', 'K13543'] +['K02302', 'K00589,K02303,K02496,K13542,K13543+K02304-K03794'] +++++++++++++++++++ +M00847 +K22225 K22226 K22227 +['K22225', 'K22226', 'K22227'] +== +['K22225'] +['K22226'] +['K22227'] +++++++++++++++++++ +M00836 +K22011 K22012 (K21610+K21611) K21612 +['K22011', 'K22012', '(K21610+K21611)', 'K21612'] +== +['K22011'] +['K22012'] +['K21610+K21611'] +['K21612'] +++++++++++++++++++ +M00117 +(K03181,K18240) K03179 (K03182+K03186) K18800 K00568 K03185 K03183 K03184 K00568 +['(K03181,K18240)', 'K03179', '(K03182+K03186)', 'K18800', 'K00568', 'K03185', 'K03183', 'K03184', 'K00568'] +== +['K03181', 'K18240'] +['K03179'] +['K03182+K03186'] +['K18800'] +['K00568'] +['K03185'] +['K03183'] +['K03184'] +['K00568'] +++++++++++++++++++ +M00128 +K06125 K00591 K06126 K06127 K06134 K00591 +['K06125', 'K00591', 'K06126', 'K06127', 'K06134', 'K00591'] +== +['K06125'] +['K00591'] +['K06126'] +['K06127'] +['K06134'] +['K00591'] +++++++++++++++++++ +M00116 +K02552 K02551 K08680 K02549 K01911 K01661 K19222 K02548 K03183 +['K02552', 'K02551', 'K08680', 'K02549', 'K01911', 'K01661', 'K19222', 'K02548', 'K03183'] +== +['K02552'] +['K02551'] +['K08680'] +['K02549'] +['K01911'] +['K01661'] +['K19222'] +['K02548'] +['K03183'] +++++++++++++++++++ +M00112 +K09833 (K12502,K18534) K09834 K05928 +['K09833', '(K12502,K18534)', 'K09834', 'K05928'] +== +['K09833'] +['K12502', 'K18534'] +['K09834'] +['K05928'] +++++++++++++++++++ +M00095 +K00626 K01641 K00021 K00869 (K00938,K13273) K01597 K01823 +['K00626', 'K01641', 'K00021', 'K00869', '(K00938,K13273)', 'K01597', 'K01823'] +== +['K00626'] +['K01641'] +['K00021'] +['K00869'] +['K00938', 'K13273'] +['K01597'] +['K01823'] +++++++++++++++++++ +M00849 +K00626 K01641 (K00021,K00054) ((K00869 K17942),(K18689 K18690 K22813)) K06981 K01823 +['K00626', 'K01641', '(K00021,K00054)', '((K00869_K17942),(K18689_K18690_K22813))', 'K06981', 'K01823'] +== +['K00626'] +['K01641'] +['K00021', 'K00054'] +['K00869_K17942', 'K18689_K18690_K22813'] +['K06981'] +['K01823'] +++++++++++++++++++ +M00096 +K01662 K00099 (K00991,K12506) K00919 (K01770,K12506) K03526 K03527 K01823 +['K01662', 'K00099', '(K00991,K12506)', 'K00919', '(K01770,K12506)', 'K03526', 'K03527', 'K01823'] +== +['K01662'] +['K00099'] +['K00991', 'K12506'] +['K00919'] +['K01770', 'K12506'] +['K03526'] +['K03527'] +['K01823'] +++++++++++++++++++ +M00364 +K01823 (K00795,K13789,K13787) +['K01823', '(K00795,K13789,K13787)'] +== +['K01823'] +['K00795', 'K13789', 'K13787'] +++++++++++++++++++ +M00365 +K01823 K13787 +['K01823', 'K13787'] +== +['K01823'] +['K13787'] +++++++++++++++++++ +M00366 +K01823 K14066 K00787 K13789 +['K01823', 'K14066', 'K00787', 'K13789'] +== +['K01823'] +['K14066'] +['K00787'] +['K13789'] +++++++++++++++++++ +M00367 +K01823 K00787 K00804 +['K01823', 'K00787', 'K00804'] +== +['K01823'] +['K00787'] +['K00804'] +++++++++++++++++++ +M00097 +K02291 K02293 K15744 K00514 K09835 K06443 +['K02291', 'K02293', 'K15744', 'K00514', 'K09835', 'K06443'] +== +['K02291'] +['K02293'] +['K15744'] +['K00514'] +['K09835'] +['K06443'] +++++++++++++++++++ +M00372 +(K15746,K15747) K09838 -K14594 K09840 K09841 K09842 +['(K15746,K15747)', 'K09838', '-K14594', 'K09840', 'K09841', 'K09842'] +== +['K15746', 'K15747'] +['K09838'] +['-K14594'] +['K09840'] +['K09841'] +['K09842'] +++++++++++++++++++ +M00371 +(K09587,K12639) K09588 K09591 (K12637,K12638) K20623 (K09590,K12640) +['(K09587,K12639)', 'K09588', 'K09591', '(K12637,K12638)', 'K20623', '(K09590,K12640)'] +== +['K09587', 'K12639'] +['K09588'] +['K09591'] +['K12637', 'K12638'] +['K20623'] +['K09590', 'K12640'] +++++++++++++++++++ +M00773 +K15988 K15989+K15990 K15992 K15991 K15993 K15994 K15995 K15996 +['K15988', 'K15989+K15990', 'K15992', 'K15991', 'K15993', 'K15994', 'K15995', 'K15996'] +== +['K15988'] +['K15989+K15990'] +['K15992'] +['K15991'] +['K15993'] +['K15994'] +['K15995'] +['K15996'] +++++++++++++++++++ +M00774 +K10817 K14366 K14367 K14368+K15997 K14370 K14369 +['K10817', 'K14366', 'K14367', 'K14368+K15997', 'K14370', 'K14369'] +== +['K10817'] +['K14366'] +['K14367'] +['K14368+K15997'] +['K14370'] +['K14369'] +++++++++++++++++++ +M00775 +K16007 K16008 K16009 K13320 K16010 +['K16007', 'K16008', 'K16009', 'K13320', 'K16010'] +== +['K16007'] +['K16008'] +['K16009'] +['K13320'] +['K16010'] +++++++++++++++++++ +M00776 +K16000+K16001+K16002-K16003 K16004 K16005 K16006 +['K16000+K16001+K16002-K16003', 'K16004', 'K16005', 'K16006'] +== +['K16000+K16001+K16002-K16003'] +['K16004'] +['K16005'] +['K16006'] +++++++++++++++++++ +M00777 +K14371 K14372 K14373 K14374 K14375 +['K14371', 'K14372', 'K14373', 'K14374', 'K14375'] +== +['K14371'] +['K14372'] +['K14373'] +['K14374'] +['K14375'] +++++++++++++++++++ +M00824 +K15314 K21160+K21161+K21162+K21163+K21164+K21165+K21166+K21167 +['K15314', 'K21160+K21161+K21162+K21163+K21164+K21165+K21166+K21167'] +== +['K15314'] +['K21160+K21161+K21162+K21163+K21164+K21165+K21166+K21167'] +++++++++++++++++++ +M00825 +K15314 K21168+K21169+K21170+K21171+K21172+K21173+K21174 +['K15314', 'K21168+K21169+K21170+K21171+K21172+K21173+K21174'] +== +['K15314'] +['K21168+K21169+K21170+K21171+K21172+K21173+K21174'] +++++++++++++++++++ +M00826 +K20159+K21175 K20156 K21176 K21177 K21178 K21179 +['K20159+K21175', 'K20156', 'K21176', 'K21177', 'K21178', 'K21179'] +== +['K20159+K21175'] +['K20156'] +['K21176'] +['K21177'] +['K21178'] +['K21179'] +++++++++++++++++++ +M00829 +K15320 K21191 K21192 +['K15320', 'K21191', 'K21192'] +== +['K15320'] +['K21191'] +['K21192'] +++++++++++++++++++ +M00830 +K20422 K20420 K20421 K20423 +['K20422', 'K20420', 'K20421', 'K20423'] +== +['K20422'] +['K20420'] +['K20421'] +['K20423'] +++++++++++++++++++ +M00831 +K21221 K21222 K21223 K21224 K21225 +['K21221', 'K21222', 'K21223', 'K21224', 'K21225'] +== +['K21221'] +['K21222'] +['K21223'] +['K21224'] +['K21225'] +++++++++++++++++++ +M00834 +K21254 K21255 K21256 K21257 K21258 +['K21254', 'K21255', 'K21256', 'K21257', 'K21258'] +== +['K21254'] +['K21255'] +['K21256'] +['K21257'] +['K21258'] +++++++++++++++++++ +M00778 +K05551+K05552+K05553 -K12420 ((K05554,K14249,K15884,K15885) (K05555,K14250),K15886) +['K05551+K05552+K05553', '-K12420', '((K05554,K14249,K15884,K15885)_(K05555,K14250),K15886)'] +== +['K05551+K05552+K05553'] +['-K12420'] +['K15886', 'K05554,K14249,K15884,K15885_K05555,K14250'] +++++++++++++++++++ +M00779 +K05556 (K14626,K14627) (K14628,K14629) (K14630+K14631,K14632) +['K05556', '(K14626,K14627)', '(K14628,K14629)', '(K14630+K14631,K14632)'] +== +['K05556'] +['K14626', 'K14627'] +['K14628', 'K14629'] +['K14632', 'K14630+K14631'] +++++++++++++++++++ +M00780 +K14251 K14252 K14253 K14254 K14255 K14256 K21301 +['K14251', 'K14252', 'K14253', 'K14254', 'K14255', 'K14256', 'K21301'] +== +['K14251'] +['K14252'] +['K14253'] +['K14254'] +['K14255'] +['K14256'] +['K21301'] +++++++++++++++++++ +M00823 +K14251 K14252 K14253 K14254 K14255 K14256 K21301 K14257+K21297 +['K14251', 'K14252', 'K14253', 'K14254', 'K14255', 'K14256', 'K21301', 'K14257+K21297'] +== +['K14251'] +['K14252'] +['K14253'] +['K14254'] +['K14255'] +['K14256'] +['K21301'] +['K14257+K21297'] +++++++++++++++++++ +M00781 +K15941 K15942 K15943 K15944 +['K15941', 'K15942', 'K15943', 'K15944'] +== +['K15941'] +['K15942'] +['K15943'] +['K15944'] +++++++++++++++++++ +M00782 +K15959 K15960 K15961 K15963 K15964 K15965 K15966 K15967 +['K15959', 'K15960', 'K15961', 'K15963', 'K15964', 'K15965', 'K15966', 'K15967'] +== +['K15959'] +['K15960'] +['K15961'] +['K15963'] +['K15964'] +['K15965'] +['K15966'] +['K15967'] +++++++++++++++++++ +M00783 +K15968 K15969 K15886 -K15970 K15971 K15972 +['K15968', 'K15969', 'K15886', '-K15970', 'K15971', 'K15972'] +== +['K15968'] +['K15969'] +['K15886'] +['-K15970'] +['K15971'] +['K15972'] +++++++++++++++++++ +M00784 +K19566 K19567 K19568 K19569 K19570 +['K19566', 'K19567', 'K19568', 'K19569', 'K19570'] +== +['K19566'] +['K19567'] +['K19568'] +['K19569'] +['K19570'] +++++++++++++++++++ +M00793 +K00973 K01710 (K01790 K00067,K23987) +['K00973', 'K01710', '(K01790_K00067,K23987)'] +== +['K00973'] +['K01710'] +['K23987', 'K01790_K00067'] +++++++++++++++++++ +M00794 +K13312 K13313 +['K13312', 'K13313'] +== +['K13312'] +['K13313'] +++++++++++++++++++ +M00795 +K19855 K12710 K17625 +['K19855', 'K12710', 'K17625'] +== +['K19855'] +['K12710'] +['K17625'] +++++++++++++++++++ +M00796 +K19853 K19854 K13307 +['K19853', 'K19854', 'K13307'] +== +['K19853'] +['K19854'] +['K13307'] +++++++++++++++++++ +M00797 +K13308 K13309 (K13310,K16436) (K13311,K13326) +['K13308', 'K13309', '(K13310,K16436)', '(K13311,K13326)'] +== +['K13308'] +['K13309'] +['K13310', 'K16436'] +['K13311', 'K13326'] +++++++++++++++++++ +M00798 +K16435 K13315 K13317 (K13316,K16438) K13318 +['K16435', 'K13315', 'K13317', '(K13316,K16438)', 'K13318'] +== +['K16435'] +['K13315'] +['K13317'] +['K13316', 'K16438'] +['K13318'] +++++++++++++++++++ +M00799 +K16435 K13315 K16438 K19856 K19857 +['K16435', 'K13315', 'K16438', 'K19856', 'K19857'] +== +['K16435'] +['K13315'] +['K16438'] +['K19856'] +['K19857'] +++++++++++++++++++ +M00800 +K16435 K16436 K13326 K16438 K13322 +['K16435', 'K16436', 'K13326', 'K16438', 'K13322'] +== +['K16435'] +['K16436'] +['K13326'] +['K16438'] +['K13322'] +++++++++++++++++++ +M00801 +K16435 K13327 K19858 K13319 +['K16435', 'K13327', 'K19858', 'K13319'] +== +['K16435'] +['K13327'] +['K19858'] +['K13319'] +++++++++++++++++++ +M00802 +K16435 K13327 K13328 K13329 K13330 +['K16435', 'K13327', 'K13328', 'K13329', 'K13330'] +== +['K16435'] +['K13327'] +['K13328'] +['K13329'] +['K13330'] +++++++++++++++++++ +M00803 +K16435 K19859 K16436 K13332 +['K16435', 'K19859', 'K16436', 'K13332'] +== +['K16435'] +['K19859'] +['K16436'] +['K13332'] +++++++++++++++++++ +M00672 +K12743 K04126 K10852 +['K12743', 'K04126', 'K10852'] +== +['K12743'] +['K04126'] +['K10852'] +++++++++++++++++++ +M00673 +K12743 K04126 K04127 K12744 K12745 K04128 K18062 K18063 +['K12743', 'K04126', 'K04127', 'K12744', 'K12745', 'K04128', 'K18062', 'K18063'] +== +['K12743'] +['K04126'] +['K04127'] +['K12744'] +['K12745'] +['K04128'] +['K18062'] +['K18063'] +++++++++++++++++++ +M00675 +K18317 K18316 K18315 +['K18317', 'K18316', 'K18315'] +== +['K18317'] +['K18316'] +['K18315'] +++++++++++++++++++ +M00736 +K19102+K19103+K05375 K19104 K19105 K19106 +['K19102+K19103+K05375', 'K19104', 'K19105', 'K19106'] +== +['K19102+K19103+K05375'] +['K19104'] +['K19105'] +['K19106'] +++++++++++++++++++ +M00674 +K12673 K12674 K12675 K12676 +['K12673', 'K12674', 'K12675', 'K12676'] +== +['K12673'] +['K12674'] +['K12675'] +['K12676'] +++++++++++++++++++ +M00039 +(K10775,K13064) K00487 K01904 K13065 K09754 K00588 K09753 K09755 K13066 (K00083,K22395) +['(K10775,K13064)', 'K00487', 'K01904', 'K13065', 'K09754', 'K00588', 'K09753', 'K09755', 'K13066', '(K00083,K22395)'] +== +['K10775', 'K13064'] +['K00487'] +['K01904'] +['K13065'] +['K09754'] +['K00588'] +['K09753'] +['K09755'] +['K13066'] +['K00083', 'K22395'] +++++++++++++++++++ +M00137 +K10775 K00487 K01904 K00660 K01859 +['K10775', 'K00487', 'K01904', 'K00660', 'K01859'] +== +['K10775'] +['K00487'] +['K01904'] +['K00660'] +['K01859'] +++++++++++++++++++ +M00138 +K00475 K13082 K05277 +['K00475', 'K13082', 'K05277'] +== +['K00475'] +['K13082'] +['K05277'] +++++++++++++++++++ +M00661 +K18385 K18386 K18387 +['K18385', 'K18386', 'K18387'] +== +['K18385'] +['K18386'] +['K18387'] +++++++++++++++++++ +M00370 +(K11812,K11813) K11818 K11819 K11820 K11821 +['(K11812,K11813)', 'K11818', 'K11819', 'K11820', 'K11821'] +== +['K11812', 'K11813'] +['K11818'] +['K11819'] +['K11820'] +['K11821'] +++++++++++++++++++ +M00814 +K19969 K19979 K19974 K20424 K20425 K20426 K20427 K20430 -- -- +['K19969', 'K19979', 'K19974', 'K20424', 'K20425', 'K20426', 'K20427', 'K20430'] +== +['K19969'] +['K19979'] +['K19974'] +['K20424'] +['K20425'] +['K20426'] +['K20427'] +['K20430'] +++++++++++++++++++ +M00815 +K19969 K20431 K20432 K20433 K20434 K20435 K20436 K20437 K20438 +['K19969', 'K20431', 'K20432', 'K20433', 'K20434', 'K20435', 'K20436', 'K20437', 'K20438'] +== +['K19969'] +['K20431'] +['K20432'] +['K20433'] +['K20434'] +['K20435'] +['K20436'] +['K20437'] +['K20438'] +++++++++++++++++++ +M00786 +K18281 K14132 K17475 K18280 K17827 K17826 K14134 K17825 K18279 +['K18281', 'K14132', 'K17475', 'K18280', 'K17827', 'K17826', 'K14134', 'K17825', 'K18279'] +== +['K18281'] +['K14132'] +['K17475'] +['K18280'] +['K17827'] +['K17826'] +['K14134'] +['K17825'] +['K18279'] +++++++++++++++++++ +M00789 +K14266 K19884 K19885 K19886+K19887 K19888 K19889 +['K14266', 'K19884', 'K19885', 'K19886+K19887', 'K19888', 'K19889'] +== +['K14266'] +['K19884'] +['K19885'] +['K19886+K19887'] +['K19888'] +['K19889'] +++++++++++++++++++ +M00790 +K14266 K19981 K14257 K19982 +['K14266', 'K19981', 'K14257', 'K19982'] +== +['K14266'] +['K19981'] +['K14257'] +['K19982'] +++++++++++++++++++ +M00805 +K20075 K20076 K20077+K20078 K20079 K20080 K20081 K20082 +['K20075', 'K20076', 'K20077+K20078', 'K20079', 'K20080', 'K20081', 'K20082'] +== +['K20075'] +['K20076'] +['K20077+K20078'] +['K20079'] +['K20080'] +['K20081'] +['K20082'] +++++++++++++++++++ +M00808 +K20086 K20087+K20088 K20089 K20090 +['K20086', 'K20087+K20088', 'K20089', 'K20090'] +== +['K20086'] +['K20087+K20088'] +['K20089'] +['K20090'] +++++++++++++++++++ +M00835 +K13063 K20261 K06998 K20260 K20262 K21103 K20940 +['K13063', 'K20261', 'K06998', 'K20260', 'K20262', 'K21103', 'K20940'] +== +['K13063'] +['K20261'] +['K06998'] +['K20260'] +['K20262'] +['K21103'] +['K20940'] +++++++++++++++++++ +M00877 +K18652 K18653 K18654 +['K18652', 'K18653', 'K18654'] +== +['K18652'] +['K18653'] +['K18654'] +++++++++++++++++++ +M00787 +K19546 K19547 K19550 K19549 K19548 K13037 +['K19546', 'K19547', 'K19550', 'K19549', 'K19548', 'K13037'] +== +['K19546'] +['K19547'] +['K19550'] +['K19549'] +['K19548'] +['K13037'] +++++++++++++++++++ +M00848 +K09460 K02078+K14245+K14246+K22798 K22799 K22800 K21272 K21271 K22801 K22802 +['K09460', 'K02078+K14245+K14246+K22798', 'K22799', 'K22800', 'K21272', 'K21271', 'K22801', 'K22802'] +== +['K09460'] +['K02078+K14245+K14246+K22798'] +['K22799'] +['K22800'] +['K21272'] +['K21271'] +['K22801'] +['K22802'] +++++++++++++++++++ +M00788 +K19835 K19834 +['K19835', 'K19834'] +== +['K19835'] +['K19834'] +++++++++++++++++++ +M00819 +K12250 K15907 -- K18056 K17747 K18091 K18057 K17476 +['K12250', 'K15907', 'K18056', 'K17747', 'K18091', 'K18057', 'K17476'] +== +['K12250'] +['K15907'] +['K18056'] +['K17747'] +['K18091'] +['K18057'] +['K17476'] +++++++++++++++++++ +M00876 +K21898 K23446 K23447 +['K21898', 'K23446', 'K23447'] +== +['K21898'] +['K23446'] +['K23447'] +++++++++++++++++++ +M00875 +K23371 K21949 K21721 K23372 K23373 K23374 K23375 +['K23371', 'K21949', 'K21721', 'K23372', 'K23373', 'K23374', 'K23375'] +== +['K23371'] +['K21949'] +['K21721'] +['K23372'] +['K23373'] +['K23374'] +['K23375'] +++++++++++++++++++ +M00538 +K15760+K15761-K15762+K15763+K15764-K15765 K00055 K00141 +['K15760+K15761-K15762+K15763+K15764-K15765', 'K00055', 'K00141'] +== +['K15760+K15761-K15762+K15763+K15764-K15765'] +['K00055'] +['K00141'] +++++++++++++++++++ +M00537 +K15757+K15758 K00055 K00141 +['K15757+K15758', 'K00055', 'K00141'] +== +['K15757+K15758'] +['K00055'] +['K00141'] +++++++++++++++++++ +M00419 +K10616+K18293 K10617 K10618 +['K10616+K18293', 'K10617', 'K10618'] +== +['K10616+K18293'] +['K10617'] +['K10618'] +++++++++++++++++++ +M00547 +K03268+K16268+K18089+K18090 K16269 +['K03268+K16268+K18089+K18090', 'K16269'] +== +['K03268+K16268+K18089+K18090'] +['K16269'] +++++++++++++++++++ +M00548 +K16249+K16243+K16244+K16242+K16245+K16246 +['K16249+K16243+K16244+K16242+K16245+K16246'] +== +['K16249+K16243+K16244+K16242+K16245+K16246'] +++++++++++++++++++ +M00551 +K05549+K05550+K05784 K05783 +['K05549+K05550+K05784', 'K05783'] +== +['K05549+K05550+K05784'] +['K05783'] +++++++++++++++++++ +M00637 +(K05599+K05600+K11311,K16319+K16320+K18248+K18249) +['(K05599+K05600+K11311,K16319+K16320+K18248+K18249)'] +== +['K05599+K05600+K11311', 'K16319+K16320+K18248+K18249'] +++++++++++++++++++ +M00568 +K03381 K01856 K03464 (K01055,K14727) +['K03381', 'K01856', 'K03464', '(K01055,K14727)'] +== +['K03381'] +['K01856'] +['K03464'] +['K01055', 'K14727'] +++++++++++++++++++ +M00569 +(K00446,K07104) ((K10217 K01821 K01617),K10216) (K18364,K02554) (K18365,K01666) (K18366,K04073) +['(K00446,K07104)', '((K10217_K01821_K01617),K10216)', '(K18364,K02554)', '(K18365,K01666)', '(K18366,K04073)'] +== +['K00446', 'K07104'] +['K10216', 'K10217_K01821_K01617'] +['K18364', 'K02554'] +['K18365', 'K01666'] +['K18366', 'K04073'] +++++++++++++++++++ +M00539 +K10619+K16303+K16304+K18227 K10620 K10621 K10622 K10623 +['K10619+K16303+K16304+K18227', 'K10620', 'K10621', 'K10622', 'K10623'] +== +['K10619+K16303+K16304+K18227'] +['K10620'] +['K10621'] +['K10622'] +['K10623'] +++++++++++++++++++ +M00543 +K08689+K15750+K18087+K18088 K08690 K00462 K10222 +['K08689+K15750+K18087+K18088', 'K08690', 'K00462', 'K10222'] +== +['K08689+K15750+K18087+K18088'] +['K08690'] +['K00462'] +['K10222'] +++++++++++++++++++ +M00544 +K15751-K15752-K15753 K15754+K15755 K15756 +['K15751-K15752-K15753', 'K15754+K15755', 'K15756'] +== +['K15751-K15752-K15753'] +['K15754+K15755'] +['K15756'] +++++++++++++++++++ +M00418 +K07540 K07543+K07544 K07545 K07546 K07547+K07548 K07549+K07550 +['K07540', 'K07543+K07544', 'K07545', 'K07546', 'K07547+K07548', 'K07549+K07550'] +== +['K07540'] +['K07543+K07544'] +['K07545'] +['K07546'] +['K07547+K07548'] +['K07549+K07550'] +++++++++++++++++++ +M00541 +(K04112+K04113+K04114+K04115,K19515+K19516) K07537 K07538 K07539 +['(K04112+K04113+K04114+K04115,K19515+K19516)', 'K07537', 'K07538', 'K07539'] +== +['K19515+K19516', 'K04112+K04113+K04114+K04115'] +['K07537'] +['K07538'] +['K07539'] +++++++++++++++++++ +M00540 +K04116 K04117 K07534 K07535 K07536 +['K04116', 'K04117', 'K07534', 'K07535', 'K07536'] +== +['K04116'] +['K04117'] +['K07534'] +['K07535'] +['K07536'] +++++++++++++++++++ +M00534 +K14579+K14580+K14578+K14581 K14582 K14583 K14584 K14585 K00152 +['K14579+K14580+K14578+K14581', 'K14582', 'K14583', 'K14584', 'K14585', 'K00152'] +== +['K14579+K14580+K14578+K14581'] +['K14582'] +['K14583'] +['K14584'] +['K14585'] +['K00152'] +++++++++++++++++++ +M00638 +K18242+K18243+K14578+K14581 +['K18242+K18243+K14578+K14581'] +== +['K18242+K18243+K14578+K14581'] +++++++++++++++++++ +M00624 +K18074+K18075+K18077 K18076 +['K18074+K18075+K18077', 'K18076'] +== +['K18074+K18075+K18077'] +['K18076'] +++++++++++++++++++ +M00623 +K18068+K18069 K18067 K04102 +['K18068+K18069', 'K18067', 'K04102'] +== +['K18068+K18069'] +['K18067'] +['K04102'] +++++++++++++++++++ +M00636 +K18251+K18252-K18253-K18254 K18255 K18256 +['K18251+K18252-K18253-K18254', 'K18255', 'K18256'] +== +['K18251+K18252-K18253-K18254'] +['K18255'] +['K18256'] +++++++++++++++++++ +M00878 +K01912 K02609+K02610+K02611+K02612+K02613 K15866 K02618 K02615 K01692 K00074 +['K01912', 'K02609+K02610+K02611+K02612+K02613', 'K15866', 'K02618', 'K02615', 'K01692', 'K00074'] +== +['K01912'] +['K02609+K02610+K02611+K02612+K02613'] +['K15866'] +['K02618'] +['K02615'] +['K01692'] +['K00074'] +++++++++++++++++++ +M00852 +K10961 K10920 K10919 K10930 K10931 K10962 K10932 K10963 K10933 K10964 K10965 K10934 K10935 K10966 +['K10961', 'K10920', 'K10919', 'K10930', 'K10931', 'K10962', 'K10932', 'K10963', 'K10933', 'K10964', 'K10965', 'K10934', 'K10935', 'K10966'] +== +['K10961'] +['K10920'] +['K10919'] +['K10930'] +['K10931'] +['K10962'] +['K10932'] +['K10963'] +['K10933'] +['K10964'] +['K10965'] +['K10934'] +['K10935'] +['K10966'] +++++++++++++++++++ +M00850 +(K10928+K10929) K10954 K10952 K10953 K10948 K11018 +['(K10928+K10929)', 'K10954', 'K10952', 'K10953', 'K10948', 'K11018'] +== +['K10928+K10929'] +['K10954'] +['K10952'] +['K10953'] +['K10948'] +['K11018'] +++++++++++++++++++ +M00542 +K03221+K03219+K03222+K03226+K03227+K03228+K03229+K03230+K03224+K03225 K12784 K12787 K12785 K12786 K12788 K16041 K16042 +['K03221+K03219+K03222+K03226+K03227+K03228+K03229+K03230+K03224+K03225', 'K12784', 'K12787', 'K12785', 'K12786', 'K12788', 'K16041', 'K16042'] +== +['K03221+K03219+K03222+K03226+K03227+K03228+K03229+K03230+K03224+K03225'] +['K12784'] +['K12787'] +['K12785'] +['K12786'] +['K12788'] +['K16041'] +['K16042'] +++++++++++++++++++ +M00363 +K11006 K11007 +['K11006', 'K11007'] +== +['K11006'] +['K11007'] +++++++++++++++++++ +M00853 +K22850 -K22851 K22852 K22853 K22854 +['K22850', '-K22851', 'K22852', 'K22853', 'K22854'] +== +['K22850'] +['-K22851'] +['K22852'] +['K22853'] +['K22854'] +++++++++++++++++++ +M00576 +(K10928+K10929) (K16883,K16884) +['(K10928+K10929)', '(K16883,K16884)'] +== +['K10928+K10929'] +['K16883', 'K16884'] +++++++++++++++++++ +M00856 +K11014 K11023 K19298 K22918 +['K11014', 'K11023', 'K19298', 'K22918'] +== +['K11014'] +['K11023'] +['K19298'] +['K22918'] +++++++++++++++++++ +M00857 +K22914 K22926 K22925 K22915 K22916 K22917 (K22924+K22921+K22923+K22922) +['K22914', 'K22926', 'K22925', 'K22915', 'K22916', 'K22917', '(K22924+K22921+K22923+K22922)'] +== +['K22914'] +['K22926'] +['K22925'] +['K22915'] +['K22916'] +['K22917'] +['K22924+K22921+K22923+K22922'] +++++++++++++++++++ +M00575 +K22944 K11004 K07389 K11003 K12340 +['K22944', 'K11004', 'K07389', 'K11003', 'K12340'] +== +['K22944'] +['K11004'] +['K07389'] +['K11003'] +['K12340'] +++++++++++++++++++ +M00574 +K11023 -K11024 K11025 K11026 K11027 +['K11023', '-K11024', 'K11025', 'K11026', 'K11027'] +== +['K11023'] +['-K11024'] +['K11025'] +['K11026'] +['K11027'] +++++++++++++++++++ +M00564 +K15842 K12086 -K12087 K12088 K12089 K12090 K03196 K12091 -K12092 K12093 K12094 K12095 K12096 K12097 K12098 -K12099 -K12100 K12101 K12102 K12103 K12104 K12105 K12106 K12107 K12108 K12109 K12110 +['K15842', 'K12086', '-K12087', 'K12088', 'K12089', 'K12090', 'K03196', 'K12091', '-K12092', 'K12093', 'K12094', 'K12095', 'K12096', 'K12097', 'K12098', '-K12099', '-K12100', 'K12101', 'K12102', 'K12103', 'K12104', 'K12105', 'K12106', 'K12107', 'K12108', 'K12109', 'K12110'] +== +['K15842'] +['K12086'] +['-K12087'] +['K12088'] +['K12089'] +['K12090'] +['K03196'] +['K12091'] +['-K12092'] +['K12093'] +['K12094'] +['K12095'] +['K12096'] +['K12097'] +['K12098'] +['-K12099'] +['-K12100'] +['K12101'] +['K12102'] +['K12103'] +['K12104'] +['K12105'] +['K12106'] +['K12107'] +['K12108'] +['K12109'] +['K12110'] +++++++++++++++++++ +M00859 +K11030 K08645 K11029 +['K11030', 'K08645', 'K11029'] +== +['K11030'] +['K08645'] +['K11029'] +++++++++++++++++++ +M00860 +K22976 K22977 K22980 K07282 K22116 K01932 K22981 +['K22976', 'K22977', 'K22980', 'K07282', 'K22116', 'K01932', 'K22981'] +== +['K22976'] +['K22977'] +['K22980'] +['K07282'] +['K22116'] +['K01932'] +['K22981'] +++++++++++++++++++ +M00851 +(K18768,K18970,K19316,K22346,K18794,K19318,K18971,K18793,K19319,K19320,K19321,K19322,K18972,K19211,K18976,K21277,K18782,K18781,K18780,K19099,K19216) +['(K18768,K18970,K19316,K22346,K18794,K19318,K18971,K18793,K19319,K19320,K19321,K19322,K18972,K19211,K18976,K21277,K18782,K18781,K18780,K19099,K19216)'] +== +['K18768', 'K18970', 'K19316', 'K22346', 'K18794', 'K19318', 'K18971', 'K18793', 'K19319', 'K19320', 'K19321', 'K19322', 'K18972', 'K19211', 'K18976', 'K21277', 'K18782', 'K18781', 'K18780', 'K19099', 'K19216'] +++++++++++++++++++ +M00625 +K02547 K02546 K02545 +['K02547', 'K02546', 'K02545'] +== +['K02547'] +['K02546'] +['K02545'] +++++++++++++++++++ +M00627 +K02172 K02171 (K18766,K17836) +['K02172', 'K02171', '(K18766,K17836)'] +== +['K02172'] +['K02171'] +['K18766', 'K17836'] +++++++++++++++++++ +M00745 +(K18072 K18073),(K07644 K07665),K18297 K18093 +['(K18072_K18073),(K07644_K07665),K18297', 'K18093'] +== +['K18297', 'K18072_K18073', 'K07644_K07665'] +['K18093'] +++++++++++++++++++ +M00651 +(K18345 K18344 K07260 K18346),(K18351 K18352 K18354 K18353) (K18347 K15739 K08641) +['(K18345_K18344_K07260_K18346),(K18351_K18352_K18354_K18353)', '(K18347_K15739_K08641)'] +== +['K18345_K18344_K07260_K18346', 'K18351_K18352_K18354_K18353'] +['K18347_K15739_K08641'] +++++++++++++++++++ +M00652 +K18350 K18349 K18348 K18856 K18866 +['K18350', 'K18349', 'K18348', 'K18856', 'K18866'] +== +['K18350'] +['K18349'] +['K18348'] +['K18856'] +['K18866'] +++++++++++++++++++ +M00704 +K18906 K08168 +['K18906', 'K08168'] +== +['K18906'] +['K08168'] +++++++++++++++++++ +M00725 +K19077 K19078 K03367+K03739+K14188+K03740 +['K19077', 'K19078', 'K03367+K03739+K14188+K03740'] +== +['K19077'] +['K19078'] +['K03367+K03739+K14188+K03740'] +++++++++++++++++++ +M00726 +K19077 K19078 K14205 +['K19077', 'K19078', 'K14205'] +== +['K19077'] +['K19078'] +['K14205'] +++++++++++++++++++ +M00730 +K19077 K19078 K19079+K19080 +['K19077', 'K19078', 'K19079+K19080'] +== +['K19077'] +['K19078'] +['K19079+K19080'] +++++++++++++++++++ +M00744 +K07637 K07660 K08477 +['K07637', 'K07660', 'K08477'] +== +['K07637'] +['K07660'] +['K08477'] +++++++++++++++++++ +M00718 +K18131 K03585+K18138+K18139 +['K18131', 'K03585+K18138+K18139'] +== +['K18131'] +['K03585+K18138+K18139'] +++++++++++++++++++ +M00639 +K18294 K18295+K18296-K08721 +['K18294', 'K18295+K18296-K08721'] +== +['K18294'] +['K18295+K18296-K08721'] +++++++++++++++++++ +M00641 +K18297 K18298+K18299-K18300 +['K18297', 'K18298+K18299-K18300'] +== +['K18297'] +['K18298+K18299-K18300'] +++++++++++++++++++ +M00642 +K18301 K18302+K18303-K18139 +['K18301', 'K18302+K18303-K18139'] +== +['K18301'] +['K18302+K18303-K18139'] +++++++++++++++++++ +M00643 +K18129 K18094+K18095+K18139 +['K18129', 'K18094+K18095+K18139'] +== +['K18129'] +['K18094+K18095+K18139'] +++++++++++++++++++ +M00769 +K18304 K19591 K19595+K19594+K19593 +['K18304', 'K19591', 'K19595+K19594+K19593'] +== +['K18304'] +['K19591'] +['K19595+K19594+K19593'] +++++++++++++++++++ +M00649 +K18143 K18144 K18145+K18146-K18147 +['K18143', 'K18144', 'K18145+K18146-K18147'] +== +['K18143'] +['K18144'] +['K18145+K18146-K18147'] +++++++++++++++++++ +M00696 +K18140 K18141+K18142+K12340 +['K18140', 'K18141+K18142+K12340'] +== +['K18140'] +['K18141+K18142+K12340'] +++++++++++++++++++ +M00697 +K07690 K18898+K18899+K12340 +['K07690', 'K18898+K18899+K12340'] +== +['K07690'] +['K18898+K18899+K12340'] +++++++++++++++++++ +M00698 +K18900 K18901+K18902+K18903 +['K18900', 'K18901+K18902+K18903'] +== +['K18900'] +['K18901+K18902+K18903'] +++++++++++++++++++ +M00700 +(K18906,K18907) K18104 +['(K18906,K18907)', 'K18104'] +== +['K18906', 'K18907'] +['K18104'] +++++++++++++++++++ +M00702 +(K18906,K18907) K08170 +['(K18906,K18907)', 'K08170'] +== +['K18906', 'K18907'] +['K08170'] +++++++++++++++++++ +M00714 +K18938 K08167 +['K18938', 'K08167'] +== +['K18938'] +['K08167'] +++++++++++++++++++ +M00705 +K18909 K18908 +['K18909', 'K18908'] +== +['K18909'] +['K18908'] +++++++++++++++++++ +M00746 +K13632 K18513 K09476 +['K13632', 'K18513', 'K09476'] +== +['K13632'] +['K18513'] +['K09476'] +++++++++++++++++++ +M00660 +K03222+K03226+K03227+K03228+K03229+K03230+K03224+K03225+K03223+K18374+K18376 K18373 K18375 K18377 K18378 K18379 K18380 K18381 +['K03222+K03226+K03227+K03228+K03229+K03230+K03224+K03225+K03223+K18374+K18376', 'K18373', 'K18375', 'K18377', 'K18378', 'K18379', 'K18380', 'K18381'] +== +['K03222+K03226+K03227+K03228+K03229+K03230+K03224+K03225+K03223+K18374+K18376'] +['K18373'] +['K18375'] +['K18377'] +['K18378'] +['K18379'] +['K18380'] +['K18381'] +++++++++++++++++++ +M00664 +K14658 K14659 K14666 K14657 +['K14658', 'K14659', 'K14666', 'K14657'] +== +['K14658'] +['K14659'] +['K14666'] +['K14657'] +++++++++++++++++++ diff --git a/data/MicrobeAnnotator_KEGG/01.KEGG_DB/06.Module_Groups.txt b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/06.Module_Groups.txt new file mode 100644 index 0000000..9c7c0c4 --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/01.KEGG_DB/06.Module_Groups.txt @@ -0,0 +1,394 @@ +M00015 Arginine and proline metabolism #8a3222 +M00028 Arginine and proline metabolism #8a3222 +M00029 Arginine and proline metabolism #8a3222 +M00047 Arginine and proline metabolism #8a3222 +M00763 Arginine and proline metabolism #8a3222 +M00844 Arginine and proline metabolism #8a3222 +M00845 Arginine and proline metabolism #8a3222 +M00879 Arginine and proline metabolism #8a3222 +M00022 Aromatic amino acid metabolism #8641b6 +M00023 Aromatic amino acid metabolism #8641b6 +M00024 Aromatic amino acid metabolism #8641b6 +M00025 Aromatic amino acid metabolism #8641b6 +M00037 Aromatic amino acid metabolism #8641b6 +M00038 Aromatic amino acid metabolism #8641b6 +M00040 Aromatic amino acid metabolism #8641b6 +M00042 Aromatic amino acid metabolism #8641b6 +M00043 Aromatic amino acid metabolism #8641b6 +M00044 Aromatic amino acid metabolism #8641b6 +M00533 Aromatic amino acid metabolism #8641b6 +M00545 Aromatic amino acid metabolism #8641b6 +M00418 Aromatics degradation #76d25b +M00419 Aromatics degradation #76d25b +M00534 Aromatics degradation #76d25b +M00537 Aromatics degradation #76d25b +M00538 Aromatics degradation #76d25b +M00539 Aromatics degradation #76d25b +M00540 Aromatics degradation #76d25b +M00541 Aromatics degradation #76d25b +M00543 Aromatics degradation #76d25b +M00544 Aromatics degradation #76d25b +M00547 Aromatics degradation #76d25b +M00548 Aromatics degradation #76d25b +M00551 Aromatics degradation #76d25b +M00568 Aromatics degradation #76d25b +M00569 Aromatics degradation #76d25b +M00623 Aromatics degradation #76d25b +M00624 Aromatics degradation #76d25b +M00636 Aromatics degradation #76d25b +M00637 Aromatics degradation #76d25b +M00638 Aromatics degradation #76d25b +M00878 Aromatics degradation #76d25b +M00142 ATP synthesis #cdd346 +M00143 ATP synthesis #cdd346 +M00144 ATP synthesis #cdd346 +M00145 ATP synthesis #cdd346 +M00146 ATP synthesis #cdd346 +M00147 ATP synthesis #cdd346 +M00148 ATP synthesis #cdd346 +M00149 ATP synthesis #cdd346 +M00150 ATP synthesis #cdd346 +M00151 ATP synthesis #cdd346 +M00152 ATP synthesis #cdd346 +M00153 ATP synthesis #cdd346 +M00154 ATP synthesis #cdd346 +M00155 ATP synthesis #cdd346 +M00156 ATP synthesis #cdd346 +M00157 ATP synthesis #cdd346 +M00158 ATP synthesis #cdd346 +M00159 ATP synthesis #cdd346 +M00160 ATP synthesis #cdd346 +M00162 ATP synthesis #cdd346 +M00416 ATP synthesis #cdd346 +M00417 ATP synthesis #cdd346 +M00672 Beta-Lactam biosynthesis #3b2882 +M00673 Beta-Lactam biosynthesis #3b2882 +M00674 Beta-Lactam biosynthesis #3b2882 +M00675 Beta-Lactam biosynthesis #3b2882 +M00736 Beta-Lactam biosynthesis #3b2882 +M00039 Biosynthesis of other secondary metabolites #cbde82 +M00137 Biosynthesis of other secondary metabolites #cbde82 +M00138 Biosynthesis of other secondary metabolites #cbde82 +M00370 Biosynthesis of other secondary metabolites #cbde82 +M00661 Biosynthesis of other secondary metabolites #cbde82 +M00785 Biosynthesis of other secondary metabolites #cbde82 +M00786 Biosynthesis of other secondary metabolites #cbde82 +M00787 Biosynthesis of other secondary metabolites #cbde82 +M00788 Biosynthesis of other secondary metabolites #cbde82 +M00789 Biosynthesis of other secondary metabolites #cbde82 +M00790 Biosynthesis of other secondary metabolites #cbde82 +M00805 Biosynthesis of other secondary metabolites #cbde82 +M00808 Biosynthesis of other secondary metabolites #cbde82 +M00814 Biosynthesis of other secondary metabolites #cbde82 +M00815 Biosynthesis of other secondary metabolites #cbde82 +M00819 Biosynthesis of other secondary metabolites #cbde82 +M00835 Biosynthesis of other secondary metabolites #cbde82 +M00837 Biosynthesis of other secondary metabolites #cbde82 +M00838 Biosynthesis of other secondary metabolites #cbde82 +M00848 Biosynthesis of other secondary metabolites #cbde82 +M00875 Biosynthesis of other secondary metabolites #cbde82 +M00876 Biosynthesis of other secondary metabolites #cbde82 +M00877 Biosynthesis of other secondary metabolites #cbde82 +M00019 Branched-chain amino acid metabolism #656cdb +M00036 Branched-chain amino acid metabolism #656cdb +M00432 Branched-chain amino acid metabolism #656cdb +M00535 Branched-chain amino acid metabolism #656cdb +M00570 Branched-chain amino acid metabolism #656cdb +M00165 Carbon fixation #408937 +M00166 Carbon fixation #408937 +M00167 Carbon fixation #408937 +M00168 Carbon fixation #408937 +M00169 Carbon fixation #408937 +M00170 Carbon fixation #408937 +M00171 Carbon fixation #408937 +M00172 Carbon fixation #408937 +M00173 Carbon fixation #408937 +M00374 Carbon fixation #408937 +M00375 Carbon fixation #408937 +M00376 Carbon fixation #408937 +M00377 Carbon fixation #408937 +M00579 Carbon fixation #408937 +M00620 Carbon fixation #408937 +M00001 Central carbohydrate metabolism #c644a5 +M00002 Central carbohydrate metabolism #c644a5 +M00003 Central carbohydrate metabolism #c644a5 +M00004 Central carbohydrate metabolism #c644a5 +M00005 Central carbohydrate metabolism #c644a5 +M00006 Central carbohydrate metabolism #c644a5 +M00007 Central carbohydrate metabolism #c644a5 +M00008 Central carbohydrate metabolism #c644a5 +M00009 Central carbohydrate metabolism #c644a5 +M00010 Central carbohydrate metabolism #c644a5 +M00011 Central carbohydrate metabolism #c644a5 +M00307 Central carbohydrate metabolism #c644a5 +M00308 Central carbohydrate metabolism #c644a5 +M00309 Central carbohydrate metabolism #c644a5 +M00580 Central carbohydrate metabolism #c644a5 +M00633 Central carbohydrate metabolism #c644a5 +M00112 Cofactor and vitamin metabolism #5fda98 +M00115 Cofactor and vitamin metabolism #5fda98 +M00116 Cofactor and vitamin metabolism #5fda98 +M00117 Cofactor and vitamin metabolism #5fda98 +M00119 Cofactor and vitamin metabolism #5fda98 +M00120 Cofactor and vitamin metabolism #5fda98 +M00121 Cofactor and vitamin metabolism #5fda98 +M00122 Cofactor and vitamin metabolism #5fda98 +M00123 Cofactor and vitamin metabolism #5fda98 +M00124 Cofactor and vitamin metabolism #5fda98 +M00125 Cofactor and vitamin metabolism #5fda98 +M00126 Cofactor and vitamin metabolism #5fda98 +M00127 Cofactor and vitamin metabolism #5fda98 +M00128 Cofactor and vitamin metabolism #5fda98 +M00140 Cofactor and vitamin metabolism #5fda98 +M00141 Cofactor and vitamin metabolism #5fda98 +M00572 Cofactor and vitamin metabolism #5fda98 +M00573 Cofactor and vitamin metabolism #5fda98 +M00577 Cofactor and vitamin metabolism #5fda98 +M00622 Cofactor and vitamin metabolism #5fda98 +M00810 Cofactor and vitamin metabolism #5fda98 +M00811 Cofactor and vitamin metabolism #5fda98 +M00836 Cofactor and vitamin metabolism #5fda98 +M00840 Cofactor and vitamin metabolism #5fda98 +M00841 Cofactor and vitamin metabolism #5fda98 +M00842 Cofactor and vitamin metabolism #5fda98 +M00843 Cofactor and vitamin metabolism #5fda98 +M00846 Cofactor and vitamin metabolism #5fda98 +M00847 Cofactor and vitamin metabolism #5fda98 +M00868 Cofactor and vitamin metabolism #5fda98 +M00880 Cofactor and vitamin metabolism #5fda98 +M00017 Cysteine and methionine metabolism #782975 +M00021 Cysteine and methionine metabolism #782975 +M00034 Cysteine and methionine metabolism #782975 +M00035 Cysteine and methionine metabolism #782975 +M00338 Cysteine and methionine metabolism #782975 +M00368 Cysteine and methionine metabolism #782975 +M00609 Cysteine and methionine metabolism #782975 +M00625 Drug resistance #869534 +M00627 Drug resistance #869534 +M00639 Drug resistance #869534 +M00641 Drug resistance #869534 +M00642 Drug resistance #869534 +M00643 Drug resistance #869534 +M00649 Drug resistance #869534 +M00651 Drug resistance #869534 +M00652 Drug resistance #869534 +M00696 Drug resistance #869534 +M00697 Drug resistance #869534 +M00698 Drug resistance #869534 +M00700 Drug resistance #869534 +M00702 Drug resistance #869534 +M00704 Drug resistance #869534 +M00705 Drug resistance #869534 +M00714 Drug resistance #869534 +M00718 Drug resistance #869534 +M00725 Drug resistance #869534 +M00726 Drug resistance #869534 +M00730 Drug resistance #869534 +M00744 Drug resistance #869534 +M00745 Drug resistance #869534 +M00746 Drug resistance #869534 +M00769 Drug resistance #869534 +M00851 Drug resistance #869534 +M00824 Enediyne biosynthesis #d27bde +M00825 Enediyne biosynthesis #d27bde +M00826 Enediyne biosynthesis #d27bde +M00827 Enediyne biosynthesis #d27bde +M00828 Enediyne biosynthesis #d27bde +M00829 Enediyne biosynthesis #d27bde +M00830 Enediyne biosynthesis #d27bde +M00831 Enediyne biosynthesis #d27bde +M00832 Enediyne biosynthesis #d27bde +M00833 Enediyne biosynthesis #d27bde +M00834 Enediyne biosynthesis #d27bde +M00082 Fatty acid metabolism #d9a344 +M00083 Fatty acid metabolism #d9a344 +M00085 Fatty acid metabolism #d9a344 +M00086 Fatty acid metabolism #d9a344 +M00087 Fatty acid metabolism #d9a344 +M00415 Fatty acid metabolism #d9a344 +M00861 Fatty acid metabolism #d9a344 +M00873 Fatty acid metabolism #d9a344 +M00874 Fatty acid metabolism #d9a344 +M00055 Glycan biosynthesis #588cd6 +M00056 Glycan biosynthesis #588cd6 +M00065 Glycan biosynthesis #588cd6 +M00068 Glycan biosynthesis #588cd6 +M00069 Glycan biosynthesis #588cd6 +M00070 Glycan biosynthesis #588cd6 +M00071 Glycan biosynthesis #588cd6 +M00072 Glycan biosynthesis #588cd6 +M00073 Glycan biosynthesis #588cd6 +M00074 Glycan biosynthesis #588cd6 +M00075 Glycan biosynthesis #588cd6 +M00872 Glycan biosynthesis #588cd6 +M00057 Glycosaminoglycan metabolism #d66432 +M00058 Glycosaminoglycan metabolism #d66432 +M00059 Glycosaminoglycan metabolism #d66432 +M00076 Glycosaminoglycan metabolism #d66432 +M00077 Glycosaminoglycan metabolism #d66432 +M00078 Glycosaminoglycan metabolism #d66432 +M00079 Glycosaminoglycan metabolism #d66432 +M00026 Histidine metabolism #66d7bf +M00045 Histidine metabolism #66d7bf +M00066 Lipid metabolism #d53e55 +M00067 Lipid metabolism #d53e55 +M00088 Lipid metabolism #d53e55 +M00089 Lipid metabolism #d53e55 +M00090 Lipid metabolism #d53e55 +M00091 Lipid metabolism #d53e55 +M00092 Lipid metabolism #d53e55 +M00093 Lipid metabolism #d53e55 +M00094 Lipid metabolism #d53e55 +M00098 Lipid metabolism #d53e55 +M00099 Lipid metabolism #d53e55 +M00100 Lipid metabolism #d53e55 +M00113 Lipid metabolism #d53e55 +M00060 Lipopolysaccharide metabolism #83d2de +M00063 Lipopolysaccharide metabolism #83d2de +M00064 Lipopolysaccharide metabolism #83d2de +M00866 Lipopolysaccharide metabolism #83d2de +M00867 Lipopolysaccharide metabolism #83d2de +M00016 Lysine metabolism #d84e8b +M00030 Lysine metabolism #d84e8b +M00031 Lysine metabolism #d84e8b +M00032 Lysine metabolism #d84e8b +M00433 Lysine metabolism #d84e8b +M00525 Lysine metabolism #d84e8b +M00526 Lysine metabolism #d84e8b +M00527 Lysine metabolism #d84e8b +M00773 Macrolide biosynthesis #2e4b26 +M00774 Macrolide biosynthesis #2e4b26 +M00775 Macrolide biosynthesis #2e4b26 +M00776 Macrolide biosynthesis #2e4b26 +M00777 Macrolide biosynthesis #2e4b26 +M00611 Metabolic capacity #9378c3 +M00612 Metabolic capacity #9378c3 +M00613 Metabolic capacity #9378c3 +M00614 Metabolic capacity #9378c3 +M00615 Metabolic capacity #9378c3 +M00616 Metabolic capacity #9378c3 +M00617 Metabolic capacity #9378c3 +M00618 Metabolic capacity #9378c3 +M00174 Methane metabolism #9e7336 +M00344 Methane metabolism #9e7336 +M00345 Methane metabolism #9e7336 +M00346 Methane metabolism #9e7336 +M00356 Methane metabolism #9e7336 +M00357 Methane metabolism #9e7336 +M00358 Methane metabolism #9e7336 +M00378 Methane metabolism #9e7336 +M00422 Methane metabolism #9e7336 +M00563 Methane metabolism #9e7336 +M00567 Methane metabolism #9e7336 +M00608 Methane metabolism #9e7336 +M00175 Nitrogen metabolism #2c2351 +M00528 Nitrogen metabolism #2c2351 +M00529 Nitrogen metabolism #2c2351 +M00530 Nitrogen metabolism #2c2351 +M00531 Nitrogen metabolism #2c2351 +M00804 Nitrogen metabolism #2c2351 +M00027 Other amino acid metabolism #c5d7a9 +M00118 Other amino acid metabolism #c5d7a9 +M00369 Other amino acid metabolism #c5d7a9 +M00012 Other carbohydrate metabolism #872b4e +M00013 Other carbohydrate metabolism #872b4e +M00014 Other carbohydrate metabolism #872b4e +M00061 Other carbohydrate metabolism #872b4e +M00081 Other carbohydrate metabolism #872b4e +M00114 Other carbohydrate metabolism #872b4e +M00129 Other carbohydrate metabolism #872b4e +M00130 Other carbohydrate metabolism #872b4e +M00131 Other carbohydrate metabolism #872b4e +M00132 Other carbohydrate metabolism #872b4e +M00373 Other carbohydrate metabolism #872b4e +M00532 Other carbohydrate metabolism #872b4e +M00549 Other carbohydrate metabolism #872b4e +M00550 Other carbohydrate metabolism #872b4e +M00552 Other carbohydrate metabolism #872b4e +M00554 Other carbohydrate metabolism #872b4e +M00565 Other carbohydrate metabolism #872b4e +M00630 Other carbohydrate metabolism #872b4e +M00631 Other carbohydrate metabolism #872b4e +M00632 Other carbohydrate metabolism #872b4e +M00740 Other carbohydrate metabolism #872b4e +M00741 Other carbohydrate metabolism #872b4e +M00761 Other carbohydrate metabolism #872b4e +M00854 Other carbohydrate metabolism #872b4e +M00855 Other carbohydrate metabolism #872b4e +M00097 Other terpenoid biosynthesis #6e9368 +M00371 Other terpenoid biosynthesis #6e9368 +M00372 Other terpenoid biosynthesis #6e9368 +M00363 Pathogenicity #66406d +M00542 Pathogenicity #66406d +M00564 Pathogenicity #66406d +M00574 Pathogenicity #66406d +M00575 Pathogenicity #66406d +M00576 Pathogenicity #66406d +M00850 Pathogenicity #66406d +M00852 Pathogenicity #66406d +M00853 Pathogenicity #66406d +M00856 Pathogenicity #66406d +M00857 Pathogenicity #66406d +M00859 Pathogenicity #66406d +M00860 Pathogenicity #66406d +M00161 Photosynthesis #cfa68a +M00163 Photosynthesis #cfa68a +M00597 Photosynthesis #cfa68a +M00598 Photosynthesis #cfa68a +M00660 Plant pathogenicity #461d27 +M00133 Polyamine biosynthesis #a5b3da +M00134 Polyamine biosynthesis #a5b3da +M00135 Polyamine biosynthesis #a5b3da +M00136 Polyamine biosynthesis #a5b3da +M00793 Polyketide sugar unit biosynthesis #5c4f24 +M00794 Polyketide sugar unit biosynthesis #5c4f24 +M00795 Polyketide sugar unit biosynthesis #5c4f24 +M00796 Polyketide sugar unit biosynthesis #5c4f24 +M00797 Polyketide sugar unit biosynthesis #5c4f24 +M00798 Polyketide sugar unit biosynthesis #5c4f24 +M00799 Polyketide sugar unit biosynthesis #5c4f24 +M00800 Polyketide sugar unit biosynthesis #5c4f24 +M00801 Polyketide sugar unit biosynthesis #5c4f24 +M00802 Polyketide sugar unit biosynthesis #5c4f24 +M00803 Polyketide sugar unit biosynthesis #5c4f24 +M00048 Purine metabolism #e0a7d2 +M00049 Purine metabolism #e0a7d2 +M00050 Purine metabolism #e0a7d2 +M00546 Purine metabolism #e0a7d2 +M00046 Pyrimidine metabolism #25585e +M00051 Pyrimidine metabolism #25585e +M00052 Pyrimidine metabolism #25585e +M00053 Pyrimidine metabolism #25585e +M00018 Serine and threonine metabolism #de7d78 +M00020 Serine and threonine metabolism #de7d78 +M00033 Serine and threonine metabolism #de7d78 +M00555 Serine and threonine metabolism #de7d78 +M00101 Sterol biosynthesis #4e96a2 +M00102 Sterol biosynthesis #4e96a2 +M00103 Sterol biosynthesis #4e96a2 +M00104 Sterol biosynthesis #4e96a2 +M00106 Sterol biosynthesis #4e96a2 +M00107 Sterol biosynthesis #4e96a2 +M00108 Sterol biosynthesis #4e96a2 +M00109 Sterol biosynthesis #4e96a2 +M00110 Sterol biosynthesis #4e96a2 +M00862 Sterol biosynthesis #4e96a2 +M00176 Sulfur metabolism #4e96a2 +M00595 Sulfur metabolism #4e96a2 +M00596 Sulfur metabolism #4e96a2 +M00664 Symbiosis #88574e +M00095 Terpenoid backbone biosynthesis #4e6089 +M00096 Terpenoid backbone biosynthesis #4e6089 +M00364 Terpenoid backbone biosynthesis #4e6089 +M00365 Terpenoid backbone biosynthesis #4e6089 +M00366 Terpenoid backbone biosynthesis #4e6089 +M00367 Terpenoid backbone biosynthesis #4e6089 +M00849 Terpenoid backbone biosynthesis #4e6089 +M00778 Type II polyketide biosynthesis #af7194 +M00779 Type II polyketide biosynthesis #af7194 +M00780 Type II polyketide biosynthesis #af7194 +M00781 Type II polyketide biosynthesis #af7194 +M00782 Type II polyketide biosynthesis #af7194 +M00783 Type II polyketide biosynthesis #af7194 +M00784 Type II polyketide biosynthesis #af7194 +M00823 Type II polyketide biosynthesis #af7194 diff --git a/data/MicrobeAnnotator_KEGG/KEGG_Bifurcating_Module_Information.pkl b/data/MicrobeAnnotator_KEGG/KEGG_Bifurcating_Module_Information.pkl new file mode 100644 index 0000000000000000000000000000000000000000..7535b8621c6f91a5e9616a6454ca3485f5d6d8e0 GIT binary patch literal 5883 zcma)Ab-W(661{bSqD6}qyQM;sl_a>^M{y}~DRyz2DHqRsJcH-%?(XjH?(XjH%9+h3 zyZaS>um5a*IoX|a=FDzn@0t^6VshR5iHV7|N)@)CS%GFxu3MOa^_p|Xm;uXY)fFum&2777S=O|0G_UJgS~Qy9bsa4pE$F(QHXALBUFB-8 zY4g#dJX&d5GSio4Xp2Bwj!D~UC~fPZv~7mcwjD}aI+V8EP}=s8wgkqEl=gMCvT17C zAt_W|YYDYTJmrB@?ztqkp!GSS}D zo_5cf=t^7KBV~fJIZbLso8JHW3Cjn7PiG-%0D(8XM)={1FK-ZH^dFV=2hFr=c*4>Zh zPtk$#Q$jeY{Xwawu5?1-N>2w*Bf+NBx-2aONMq;_-K&=H%G-I2rWjv8inbjmJ%cgLjcpbxT-O;r-PijK=w@>Y2|zFz@HCj>gN zR{@6#i~^kmjZ?I?bx3QAR8DTKz_fvEf#F3yWjgEBMjJXc>ole)>9k(<4%wd`=nTnT zrZAZ4;n$hN0A~#YoZX34&e1u6)@88(Aokoq=jD)bzB@mKL3g%^n~ z%n~J@q4j|-8jE-FFy1A@c$emQy0Rr*)>B+)nhtb%ngvy%A^3_wS9S!I!vuX*CP3HH z)tLZYN7rNmbUj_0imfV{9j;5omaeAjXEvlM%;F=tA<&J99(~YLAReRNkmxlEV(6wJ z{mhX5<{|wpL;71gdR-KBTcF!>y#Rp!jzD(`fBd{LrC~->Xv)}BXpAgcA&FADbc!C3 zMd?~=dSI@aL^X6*pa*qXDeEmgxCZzC|imFzOFSrJ~^xlTRM8efTf@( z271yM%aeyJPwBB>?RhF#;&f#ZA1r8WY#coeWJ!W`K$U#zPw&ifnDCwv=$Y9p05I!W zfu7x|P!{j$bCL?}jI#9HtODzANzY5Kk+v14+vn#by)e8Wy+#_{f?k-WETd)iei0_z zX39Vp>+*~96pMTuy(AkX(hR*c(95zkc|z06v$Tfo6-ioTdu5Uq*_*&r7_OY5H@8zF%rW$q zY3N%aQ=~Con^hx&X{Jx=uIcQnQWn6{VCFb?sWN&1DU$Qr{zkf7$iazlF*+1B4 z|Il>LXH3%{4)l@EXYJwhM+1E<*I8Vw>EoRc+1`Dk6N1;8J_(cBqF~De@rCuCKGmg( zu!cSz=rdhd%;}y!i?AC%__>}!W9ajNzR)Q&@{xQo(3d*LPzoXS#%TI-7K(M!&{rTd z5*TBeDbQdY_-ZaHZqoF%TvT)m`g*4uWQM*G=$oBxW$~_lE9*vBeEAZlrf+9gnmFI- z(vZdHyMex!Rt)r!#rFgKAO|*DyMlh0kd9q4}<=vQO(zaG;6W=Q|rL@xx6e%B*_)xQt)hfL7y>Hiq$Ph$js z?g*q1f9VJeH2yUa#Qgr&&#$7t_xTF?N1%V^*TOYR;J*U>yGLj+JN~CfSXK1j9${6} z{}Lg#Se508S(qByQ<@--X9?0C)PU5QXA9Dv)dVp-N02;^n!4b*K=Ml@(hSc76nH+a z1A(3w$kXjHQsOCIC`fyfjGT)EX%CZ;bFmnv{% zq-T|dRXYF*yd$nXt4iZ|CwV$sWv%0#1?hBI&&veq>9V{FkiIdFcLfr7H(Yzh;EUkh zn}I!K;69Dn6C*tVFlMCGRcBz?gjm85py#AOmCe12SgJB%r`6aP1jm zz2^Pp>CPB$c%>knE?@8}L3+9@uLjZ?BL!OnB=7;aW@7-u7}X4D8GteIkl}5q*#Jt+ z+FMg_AxO(CNX4ZfEwdmcSAw*T2x7SglCu>~!xm6rhijkH)a>QyHrvQ>pddZYk`EH3 z$7%UsAYHbFvU~`Tz=z_RvjvQ74{HVv$2BD@|AZ_b0c1m(;^bDtM>e+}6>n{i=(=u> zuG%(7S1rd|9EhypqsN~w_?YJTW8?G7yB+hdr%Vbg@x*K zWW4Ka4c-nt@#4L-L6l(H9Q3@@P)XJ zdAlCaCU|?1+_uTyUMzRR+e?HmDHd-p1#th~UM8a(dpiwSyp1z~RGcpdgxxS-fi@FV znBlLK5bcdlIlfBzZBg*w4LfBVQXO9nSpEv#Z&j|r4QZK;Rk>D>MN@no+Cj50a%TEIsgCw literal 0 HcmV?d00001 diff --git a/data/MicrobeAnnotator_KEGG/KEGG_Module-KOs.pkl b/data/MicrobeAnnotator_KEGG/KEGG_Module-KOs.pkl new file mode 100644 index 0000000000000000000000000000000000000000..cba82d55a434321fe1799278460e124ab722ee7c GIT binary patch literal 4977803 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%0A=(l|}hCgK=OShq@>ra9^LX*2O~ z<#e3$Ghy{2ZJFcg(&Mys+9qwQM|KJF*6sC^>$JVI87KT!c-* zAIeW%+v|(xIBnQBJ#rna&&{Jq%Q-K6Tg+U1NW3HUiVo#Dm8$zyb-$|aS8_I4RZ!ip zs{0jUP~ESp`<2Ga>V9>v1mQkF+C#nlibANjU+KDCu1VZf-Uf37uLsmxxUZW{M4S7G z>on0v+b!d%H_DPk_d5sU zpsQQqcZnyCq{*r;3i8W$ep@~6OuC!}I#(arO|W}J;TmUe4&-8K-n)mw_KYxY`p%K1 zH|OM3_p9TgXsY{_dc^8}<&mM@enqeGqPmX1NBigwJFITcw;-hX1q%R3jBG3PoeTM? z8FaWqPlCjpoi1=jA&*DwG+IpY78fibnCU>>J5Rs*3O_Yt-9oQ7bcPc=#g`K2tisvR zT~y16w5(t`!SW7lIzt;znqGfIN>^0aN`lvz0dtNnvR@_G=?Ohg9Cs#kxT}jiW9@7r zAwO$Iod2J=UvV%2DiMF}c9HS!Sfk4hJheLtb~3&CVO2k@>W4+oR{gN5A6E6ls(x72 z4@-+?p|SO<9~PQt^~0)uSkElvc_iEam|Q%^Q~SK&g`oF(<7|Ja*I-3CjaaN_*2mhh z4PFgv<9T&k$FJJpHEgh1wd>=pk*9}p3Hw!6n|5}9KWRL4p}|dOIXz=8JjC? z3&ECxt<1#|e2*#aHX?0n5|`NQxhSXV!+>W4KMV6#o(j#mA!+EeAJSpBf7A6E6ls(x77Pteh=Urm$+ z2VyXh>WS1B3S+>2sRPCPOzz94xs7IxXUhsb~BMSH;G9ObJ}*xcp42F zraW7VVH?4=g6#y`3w99fDA-Bx20$~g!AP-o7U@lbU4q^WC$=%MYl2M;Z&lc?g1Lg- zf{S|~^NwNi*U8I}Ob+8_$lj1$$<+@lS6xpt)lWp34MviW6a7@L!J4YqVAX4|>NQxp z1#BHa{YAY7ivjUXDv@1WBA6kt>T0;s=1E4QAorVwF=nnfcN6R$bexKyzgofo$QVHq<;3s;Rx7i`bf!B>FM-LdNw_mo=-2N7t`Ol21d9un5X=-T3Fw=H0haWfj=n2c6!(tw z<)f)~mbjM=?rwvvwOzJ6jXGZIVH+am_!Y$YYQc(vmCV&`hFWe~S)^42)eno7z^JyB z%SYwyM#CO-O9-27sl@G6SlbJB5bS7nO*9#P-yqT(P3quG8Z|c2By<;ry*a{gp>+f9 zjdU8*t_qtQVWS}~xb5yDy)8)WcSfZ45NS`rI|O@0V0Xaev3+MeF}Z|wUq9i+uTSqM z_WcD12;LomgZ%B}Cpq2n*;WkI4@;#`ufeK*Sk(_pvj^1vdJR^+21^GZ)N8Pcf+pSS zczd02-UOq#)V1zVZRG@cq?{=Dq~IjM$%0dWtWtJy0%<=b(y2jWa}PS)r$zdVNu1Hq z*gV|JOX#0d*yn>C1%g5Uiz0nV@MXd2g0Be95PVf|Ccr0~$wXSkS@AR&%Oda%F`O+p zNAS%EL~9`MJU_|Til_6%a6yndW77NR6i_i0-E}*Z6_qOrw*pDb^SzR z#xqTgUxqF=2+Cb)1Hp#Dz`~RlkMK&PscvjCMz;~{jX1l4Ua)s`;!ZmdX($*4od~f8 zHI}>ZCJK9ybIDW@vzh_hqT9_CwuQqwY)&K>Tg6i^`=f0WPdHrB?^O4z_FxwX z=O>LRkbmK+JydX5(EFSVrI_ zjIYes5g!e~RO_+gJT5pn!pN05=#BCZoo>WOKOv?Q1SbkUDL6@RGN3_$D+lrvm896Z zp#7l?V5f@dv|!={rLa=v#njI#Y|3FWf+3ur4^I0ielf!8HCWaCYQE}zRo$JM9CHARw}$%%F|!JojM4OmgpE~FzdBr>j?5^gBXaKK3Tsd(x$_wh(L#9%A# z(E!7I`NUV>eLA zz9!OHg0Gvd(-TSO*&>}|62~dBs@9$>(s@C`v`YHVFHe1KU8?R^)%~ivUr7m_jJq_L z)xw9QUV|lHtLlE0d-!?{mYn^(>84(THE0-vuT=A>*I?Cau6hsShj$78b-Gax ztX0M~o*}EHqHrK4!8fN{a&Vuc3)1h?AJVPnmdo00>GpI-x>E%FO1!Gd>Z{$0*h9(( z?};}N`Ole88;JCS+vdE#Y0^tey9X!_P!PL*o+H<`0K zHczd+qnBXK;p+)N69`%KTk^GnHHCU>L z>VAc+B8s;ZxoU8GXn*e~&d&(Hdpu#-X!%FU)op^?1$PMU6x=2Fli+T_JwP6G6-(l- zL%#D59QhIAd&P90ndB22t%hco=x&Dc`M74{D4v(Y#J+GI%AgJzF)&0tzH}&?bdi#}ZMn3h2 zBYt#P<>|;q`xU_%mJ)8e*RJ|A{iMUa=uXaxCtMKiL`Z)_A9}Xpog?_B;9S9Zfci@g z;$-{o`668)_?GE(au}c5Z^sjx^6B!vTf)Y2I{d!ae-NYw-^r==LXj>K{77)I;KzbX z1eXeaBDhR&x!?-Hm4MQMqjYTVNAak)Ur{Qj&DMa^$=4h{q@sFQ@QC11!DE0pI1b3; zSToQyhfgZ(Z-W0c0|#X3l$obRdPeZ9;5i54fDtyqriZNQeO;`B`3GlTQSmQ{dp`L@ z%r97=xIzr1$}c3+!h%IimyOUi#(Z>DyO_cjcNmJM?$?+ZPuL~%xX1}e`IHKAzDlr^ zV3uHM!7_l-g%Q+dOyo9FN>Vu`DZ-I=REZT8WuxhDw}=ZQYaM z*Kt}DuUk`0YYEm4PRhaNQ0%n4WwyfB6Ra=TK(HY|8oL~lXC<9WMVvVfAwvV{IGkH? zbxlWCQF?{M$+I{Em!~lvFzrYTW5J}*M?O`mq0qdk7-fT6ofF}towsbJD4PqmDDkAO zw_Ay{wO|{;wu0>h+XJLqDmppaQKX%MG%N>|^~SpGa%Y9Tse}>1vci?cQ|((6_Ey2J zg1N!P{DqdhdpuG5*2z%7keoflxu?T8u?w4dyH{|cC;5b>PB+xS>VBmLP~ESp`xQQG zYOkE)=_bNZO^0%`8q+P&d?o`g_h@2bCp+dNjM=w}>5suQ$S0=VF47$)VIz?7;VzN> zB)D5}PYL8!kg4|1<*8TB`y6WMzfYWh5!`PEj`ie(#r6R|VQ%nrOgHGp&@z^3;}J!9 z)J!NHn({p^(i4Iw1%DI#r{F0-ji8xGJ*e(il7i}fWzRDd=6d^8?iaYhEL%WiYhXY> zBs}wYqM05l|C__2$m;D^6h^)MN+NM>hy->i3r}|>`|x!pb9$|mv+KqAOTi6-UpWw+ zM5gB({iM6Sclp@&#XjwG`LOAD3} zEGt+J$i-D}zpCz6)%~ivU#V00k>Fy%j|J8Js=8lQ_p5sQRo1HN?N@QbRdv6r?pM|Q zs=8lQ_p9oD^*`Z$HLUJez3P5d-LIZ`J*(x?gF( zRNhw@+wi%3(ar%}e84*6EN#4B+F`5`Y6tDIA}uFaUa*4T)q)iTD+yjBSQ*gL7>n%m zyQ_+{nqYOo8iF+eZP36Cfh~z^$J03P(OXvxvjyt~eK68B6B~%MpBiL8)F2R0) zzRMLEb|n~%;?j)HSnd8j5zh5eJiRxbP)fW-m`kcc-14hAN<&7y{i@!6Ro$ERI;f2w!i%vK2+1!7^n|R4REY&d;g#!RS;ma^x|V;|;XB z@<@@Uk(`qsnxNU*SA5y1?>qJqT)iv!Bcc&IZtX8K7dbNJ*47J_Vy z;hcr)enolJ+ppSvB{%O9>=(k*<;XwFaKn*e?Yo1_`6IN1^fD7m0IlL3C^$&)z6j*9 zTTFb1#8VH?``p&J(cbHUI8O4a_bbW=1RoR}E;s^^0CSIy&u`&Kki3%6YKE_jfyx`-e!-btyjSu(HSg9PccG-S1 z;*I(oFwmZ?D5nUj`;|(ex?f2=!@S;8_k53vmyAN$Y^ z9faiZt(o+A@ADDAKOh6`i#)Y|7rZ2x57&`)e!&9aPlaVN)+Kv79%x~OEh3m~ zQngsH*W0h^?N{~oEB6Au0Yl&?qG2%bp$(oGjfOFeu#O1bo2=N){(WF0@sXTBuPFAGi&`Y>+*Izyzd3eFUKEdu-b zn1!#4^bNt;f^!7l6r3wK4^UUtr@!IgK9MdEd`s}}f^Q4HBls==uWo-RdbZB^`hmiJ zD7a8?QE;)6iSB!GJh9{$J!x;`A39LPs>x7l`DKcGx!?-Hm4d4TR|8I=jtRU*q-zB~ z6Z~9o9gsO#Da~)Br=&;xrO7%5h^+leoWB;_DEN)ww}P91(`L6f>-Q~!-vP=dH)42T z;J`H!c&ozxSi(j+Z}oORH7tBnnRkleu3+f(smJzik?si+*RuM!ir%Dbs>&Nf?iJI0 z!8GJ-jH&j1k^X8D$F6XyZ2O={4+$PNooeurXGJLJz*x1c;DY5%BYE* zCgW0tI;)Puj}+xu!E=J=1upZfiGS`1?$@!EJ|!wm~~Klc;MQ#!`r7d*As z3w~L+Sh->WO{8B7ZWR1R@LR!6fEJ2a)WcI@o;r9l2b-$u;>g`voc-Gsm>g`wU zadE>BXP3}39q%Xh9{LKm>VDO!w_nxUuj=hrZFRqzuia7(3|rZOq27KquI^WOm9(Fg zP*nG;(kiO^RlWVHx?g#-ZG*?nR6CZh!9-Bqud4f%j1SfQ%6E!uS2lKt@2PEkU+@FL z4+R$rE)rDttLlDL-LKSb^tnV+mR;_luD4&wm_DqxU)cerskdKM_p9oDRo$RH&bb`w0K$~%}h(CSEN^_SEZ%Wth97m zCM}zmOUtJfq_nW4G@42)rj>YLPa22XrIphvY1On^T0O0i)=X=qwbMFj-84I`m)1`k zqz%(XVjXg!K-PLDjhtUPde^wa;TWl#dZ{lKP6;1OrC}PSahjw}#4(t#j-ED6bJFY6 zX5#7en|vyVe2hu(mN}kI-AG%fZPK=S#6^_1Zm*wQzn<65bxck1$*s3vRrjmvewDYD z;6zUAdNe(j9?xxSthVu_ezJ;ek9Bs<(A=L&Pp4i~p304=Z0Vp9X znzNN>EkAJpiG23gi7>VvvRE)X!q8L*Tfc-2J+bRF>K1b`4p@!nhtBINmy6IjwVjC1 zYQ6XNu%U;fOQ!uclU z45IQQ`o#`gDM?Oszxw}*`_<UTm zcOo7q$H@R0PxKbFnjeVahk^?Q7nMMoB4>5@Np}O0?MuXPsYy+LSpBf7AJ)+4jMQte z@^D!Fu;>A+A6E6lLOZN}Sk(`!`eB_?{jj=Y`EgV~toC2z#d4_Nuy9V{$Xri=o1rGK zA5_@kf+K=~`?b6V%0*wO;~!GkhXqFk12X{>^JDzPgqn$a48iFB$BOf~;OzB1$Lzj<=b3H<)S6a)LfsbV@Um?mS}8^h=DvkIGX zSiJ^|0}NFjS4LUkQ)O$$fa8s;9~PxjufeLNQx^ z53BlNF$vM;N1wdS@#bZ#0-LEd*I`Qrt1E}tBZuYG5i5j;%1i06aMI}xCyp}c_E;_X zU~sa2;mKELI3&uEit?`!g-b}RqO%#oZ^YE zHqnfTm?tRg#0VRVIMQ2lt5IJwsgo6Uio>{2Ij&S547kpxJyl_+2|jHGHfvNrEQ;eN zDwE5iOt=EZ^;NII(n5r92dB~0Yp~Q5yF>O=wM)spVwPZO!7_qn1^&|f%0GNv(Harn>#1K^OHtM~N%ys2a#>fT*@E>1 z>kBpja*x3B$yB?MNUs%aEa(UtL08ZN#LL^fY|Ty#Qa%iF^}}-gbn-TqeN=a8v!TJla=3tmCU67D`3E z2CH6!m1pt2f%a;?6t`n_Mm**DL0_9D7g!WgSx~T$U|}E!4z&0>Bc2-VFmD$tPwdm2 zYL^iEOu>?ZS41E;r4slmKk0(hFjVN4Fuj=jSj(<(+-5}?PvVBwaVKtzgvV|ky)iek z!P8(GF*8?)#TCbmH&=}6}GX%*mf&hNF!2L&=d3p1HlkbE^uEV=Gad< z*piakB%Zjh(>51UOE%^NnZltSHjAghAU4l3*72q-OWcum{ci0iF2>{bSrsgI)k5A5 za$Ehd{`>u~*f>!AutLk{|A8U4>Gb1tNxD>Y`f}WoE=!lE zE7Fzes&sYwsmS!&_#R%He#V2&Y9h*Y=@;qx^viUE!|4~(uhWfspzkd9%xxx+C2w0^SkReiU)R_ZU~2bWgmA$bZg!+CZcqxI21( z)1;$R{w3X?{t8`|Egm0C5AmRVN*>Xw9~L7`^~0)uSct)a^2Iqw@IE`_pa{y`d`P(G zaCJ8t)1hKGOz{4~HSD`Fjq`27hb!y|!I8m$3WQbYLn3`xaFpO^!7+l50J-IMS*B`_ z^%Dnjum&gccp|5xY*K4i2eVR2m%IJy@W$v$ypQiOZdWyMmLE z3-$VLk?sl7sL!3z?VsbRx?ffIE9PLHjG?Gh_baJO-98TG>Wf+SWI)(w0ou>LfWn#y zyCZT~(;;kslN_xq{oOqh_v#0=lJbJ=7Vr}>TvkZB-=n=kq$>qi39c6WRB(;pTEWi*KNnmFNJdyZ zN5Qz>PaRUimu?WluYzIR3)2@9AF}Zqh5c4=lNqY}Rdv6r?pK}aeuYs3D|dCj%H1jk z9y-e}hHF-DJjs2&RB$wa)8(f06~P&1(2=$1;AaLqhg&e5pA}DZuw`UnCuMuK;+-S- zrr=z`d4M|e!G!&k?fD{IAo!N)y5otM-;O8Fu_0~WEn$p9Q|4xtN?XlUmbEA zs&togF4`3$9Mu#xb45j2X_{m$3vWs7-&;jtt40_qu@$fWAT%tFjpB7{ifJvu+QG@< zo6VuvX?e?Rg{>!8U$B8-Lx420rx=AuiDes)=hH04qNH^k-XRM#=&qvl3aQcQFZCL% zdJR^+221P2=c;j>R~koGi^b=cr+N)my#}jZgH^A=qKBy0U{&`k#GtxgQ3#jF>FQEJ zb-(H`X~xujuU*izwW7=ws{55DCZi#KiuzIAukx&tE3>`w&bhs)nselr^m@T&g3Se6 z04g!|(UfHxAGxE&5H!|p#I$W;>dJj%dy#f9Nyl_D!`mqsF#LOg6_-*^D~H*2^i7Jg zOJU+{-l_I2<*6%k&#q#aE7+~jN3rLK(}S2+zFlE^2=+7sCN_4IwtI=Rw@GYA&?&;z z{i+k!*i`qc>V8$-ujXTyd^^8jf!Ht4Hjh}B?8!d0u)-D*)N8O93+gpk-UPsy=^?RR zgVk2|D|HXm{i?cOX?{_!!K&_8)&1&!!u@Jo-LIV74+oO=6JGvpSnsrGV}#uau;VkJli3|v*7db&vKr((E9aIN5H4rB>w0PA%k{US(g zag2>!{c^nA#J;$?%MV8$-ud4f1b-$|aR~+V2-LKluG?EOycyZFp#lJ)*i`&UYV8;bT-6A zg|QMMIrn-?)<9mSF9_}4F4OJuclpme1dOvziKCPN7^LZk*fO@g|S~0MwcW1 z@`S6~3{X4Y9c0cQ!KEy{%!E4I^3)zEI7slm2pkNgJRcHI95Uy_^|{eL%OQHLoFm__ zC?61fP;j{52mo~&4lC;or}kw9n|lU)j-L+J=gUW#k#?^0L63=O+_e_xopd;czdbg{ zsN;C9eT=8}c)`a_$KY1ouX0WI<4_wN=|tgvPlfb-!4CvK6kI5{Nbn=U#eyFTE)iS` zM7_C+xy6zSxLjdZ2(A=dCAb>MGp2#g4ZKFAYfZu#R0jnAT%_xQ3(r}&t{3T-f*XR) zbc!ndwVx0dBvmhM1`>|nit{FiY0Z^+-7O;hF4$RqV&eA)k!}qVEBK_h-hNfxuiACP z_lzS(nbNN(carr58wfTOYy?Q!`dp%!#jf6dmAjGZepTJC{#^~Ex?ffItK2cx+pkbG z>g`wU4!$0%%ibr()SYxI)*A$GG`;B#<=*`!k#;eO+akg`&Q;Z@fNu>lQ#EwNx#HYS zuzS!s?;rZx^)!Q}bnNo$|F}mPq4q> z0CRDCx#k-05h)4YD`*|4OVZ*yI%+ZN!ULUeez2Gh38vmi(~?6)I?SX_uhD&OABZRB zJ&w%UfK$|Iq(~pBDE|tacFH1eWC{fB)T!BN!L(3Xm~U~dTf_Z1GxU??fo3W#mKIM- zq?u{S^osP#^s2N}nw6GL%cNz~a%uUrg0zS>L% zW?Cz)oz_X~rrBw|w0_zkZJ0I^>#*bbp)P6Q{+^EBHSSQ#shfJKFBVQ`9ZaQR8l`cX zq)o&zm~h&6+BD5cuTPtahm$Y!v`{;jN${3Ao~C_i>$FYUR*%dhdF%H2$#vSUJ+5){ zQ96hPFMNXn`+dqV?W~_YEy$!@^piz&-ussPbBK1Ie`paX%}u+d-P7CB+eP9|lm1lN zQ$M+sj>vnZz4gE}n1_ARzC1LOaWkGu`=$NU0gmGh!8&@yr^~ZmL{i@?-tj<5I4~Wg z2Uc{vV;ct<7!HA^lUOMDL-isiE}k26uzj2m)U)`gNFye9c02JC-j$BjD>{_tRI2V* z)%~ivU&(`ERY7&Xs_s{aL3O`UW2o*|)&1&T3BrAVRE_Z{?)63C$*L6BH=^??2>ZA# z{vGK&?L&(8u;3BFqk_i-j|-jv6bYvm6xYAS6KXk%^HXAYx-fKg=J>NBJtufx@Pgn) zfLG|w9~Ky15~;dhjaVFMH;@b2hJuX*uN7@Xc>9Jp6Z_n8R;M!7SNOXtMR1Y3ro2gLNC z;32`of=2|83LXRWW@g=tHBX52q)D1)dm_Yz^m($(MUvV=|8$8m^hFr5j(DYzJKX6_ zpVv!X5WFb(`!qXO9k=u8dYJhI3)n+Lu_?EO{G^^XX6U+YtesKFV_i+TnBpxiSVAz< zfuvoRRKCJb%~-e4D@&bxiP}=)oK-kG8W5HdX<5N?g5@39aDJ-o2JCJnr7J3ICBbXV zpu1Kn^i_f#D}#&2E+(ssJY(%_A|XF(MjTwi`Qq9UXQ;LGcHIc;GFZD>F?3C}>qBlg z5NsF>T(lNh>FUtfjZMbr#%9&F5ocG>3-*pIJ?%iGpstw=YCZ4$O3ZdBU<{+1aB!-9v%=mI>~tuw?<&&VV8__w4ZRpPk&L&Q+^}d((d;44Jq7O&>?PP+ z@J_)#f_(+=66^;^KvQsIbEYM+5^eb~_`72=s>(_F=(M!9atiW{&X_ zcZYM>0H4=tJk@%vIFAcXOlL0JLC24 z0gC%nF`X7nSni?(y4qauS%pnGtkcQ+RI2;cl~GpJ{mPB4x?k1XuiBAZHO7KT@y8fN zAIhNO&J<;X?sHCrb8{DC@n(v$xnPSDPnXrUTZy!_U>m`(W{XNA3~gb^Wk?TlB1y+vVf73?aQ8(eg*^oYC16BF*3==ana?jg=S9o88S zCy@3EPBfiZbm)dU$Ph^QzQIj`-2bz=)B`q48FcsuM0`f67^a#oV_quJ7yxpj2eLi1 z2L_qdE=uTqJhcZ44k_&1L73S)ecqz+gC#hIhWCr<17>0XVr5AM$Y91hk5Jf=@d6fc zoJx3|Wtu#b?&JNWwX)D|s{2)Szp`${GP0Wp7gZu# zH%oeM33;I{mG{+hG4Loys%QPwKax6T|a@7lKX;a@%8ZJ+$@S2+sLpk3PL9Eo=c@7_;E?JtNJ-q0%2Lp_j}QEEx>U1Nqb|MS7KBDZwnk(t>3K%L2Kn z>jv|7d68BK5{ul?@yMFiuB5QnIE*8_G&x))o+dm_wX4Mw(vvZ>o8hZ)$l!c8Fghg>Cj@9PwQQ^6d+M4L05aDsP0!3LUq5&1Il=)0j0WMG1_GN*U(NDc)4pbGM3*(b-${&Usd-jFG`@K`JjjD zepTidni$;?u32mpEn2W038gNFc|D(>dyhJl|A;<@C6(A8I*{SvUWMH!_>16v!CwUr z2p$wXBzPD=Jx2Z3wEt0&9uqunIu=0;3GI{dgfi_}$*9qS!c!(=YbXgEde+BWAr@XZ z%7gblAMyJGO$=V-sr|d)B|*LYY90BGRQD@(i6bj-RblKZm@C)~@MJY)p9M@Woz~m0 zMyz(VA5$sS+pkm#)%~ivUuBDUb-%(0SlzFx`<0cu|1S5dVXs%+ud4f1b-$|aSFwaL zU?C?xnjTA!OGjrdoyRA$x;~Co`cA`s#Pn2pIz5w~P0yw0(+lav^!M~qJD>Ky&+jeq zERSoy)q)}|WRk3AOcoarX@+1?!D52N1xpBK3YG-)&B4I?6ttS?^g;0|B(Ai~S7(WP z>ELGd676}}@-*W9d0x`6`w&~*3gUdVU`4@7=IXLeMc~RJtsgxI0y!-cRiN3l0#x zI|2v!+sRMlUTe9n7^?e~N};-6Rrjmve#KD8P7d~A#J+llpV(G0(3mz$d+wKZm^wlF zo@GT^PO!XS1;MKYD+*Q;yhgAxps|j^XP&@&EtOW4!k0RUdw%)?9P%bM87T&NY8? z7W$RGowQG(U)7uA>=*1y!V!%fXgDC@{nYqFnYR3r>`C}h#cqnQBK5TkyJYev*2BN% z%}ll5T_IeVkMK&iHCHz;sA&P$s&HK+(jTh2LD7xEO~TE>EyAtBG~qVkcHs`d38f2# zf{=t!l5WB$-L1kOQUL~4{24gF@n_s;-TlG?p-{44mF!oAepRwx)gJ3i9)*78v|6%X z75Y`|=`kiSDxQawR{o?;Rqu2Q{mT7*$$m9b=vP6WDfFvYEpdkAkXh(g?jZ~P zN?O*s$=e#~d4;#Wq76cX!4B62CsG2BG*^Rix;9p6lT_*sq%Uly=qtikLvDy$-nV&b zk$M9&$d)Q>C461@hOjljXP_->ZQCdj@WYvFdlhyNb`*AsN_=)TFz%vgS7A3{cVQ2} zpB8#@7*$%esj&(%?7Vb`><_|rB!#ZFI~uHofw50MPl-+CzP@t5e72LX^bg~U?w^|d zZWA%0@7>rzKJwjsgxn+fE!wc9ZAfCz(kO?hbg1wH;fKOu!r{V?gd+eS;EpX{0hxKc zI?}qMvW~17!2=u}F_6VE)*Tyl1oBARd9UYf;c?bY5eof^Mkw?v8lljy>Je7xSDoOK z6#A8BCCT~QNwC-+a0Z3}&*ZwJqMd}Dg_8Y>%hbMP_n&4njgH_nR2^gE94q{L$hmMe z9{+KQrlg1)5mb*?bb>H0oG6?GxO~HlPmh>^4Ed9-J4HBEI88WRI72v7I7>KNI7j%U zaISD3;Lk|lDSp`t6kV7iqISggrZd{a59nsFdip^ut+3fMEJ3f(ud>~UF2?q&WWOre zuL}JN6H}pI$s#%=8D~rmVR0d!Nlc-=F`{->hh;sUjjRWSer21L>{lL&+yArZS0~P< z3pW3%*Zd7%kA7_wO3vADW-lLYr^^X>iNbQy#=b%nBp-QKcu#m=_yDMPC>@-BZI8mk z!V*(>ScQibhk^et9#$7?SxJK>*QBJu(iIqP%kYrlp-#QM4#DS!KO7!rfhdx+(U0mW z8TY;M;g5$u86Iho2*Bjg`swiK;W5KwhyRYq*wQ?CT&+wri1FdihR0jLpOu%44^OOX zTn&al_rGn;vHpjTLE)6)sT7E%Mg)lA>BBQ>6}=RdlEsX?XlD=4u`t#I_ry>h{*PmD z`p1Xo4=)&An2(`-(ePpm7^~Cek#%Q$`0L?shQA$NGW?xyA_+DhcG>Xq;Z#*eM>0AE z&mg~Qc=hla<+vmA`s;?*4{sRWIJ{|i^Y9kMWXPiprVVfNRpeXdkvoRJAKp2b?jC>Oh|E1Q`W7Gc-h%Zj-V=cesv%}|xe?@L!4T>)eU!>ql9ZNECxB0xn z!@>_<63XI$jmS@gd1lEd5s5^X`7dN0&Ni&g%VZrp73!92>e5uguTE?Grfx4nITGwO zem{FXPqgxRVm`+2#%%>hgl>v4zSOrRB=OVDzTb%D#8rdl)4E;|txTy}r4iYatI1iS z^F-7Yt~}%Nh3lXEPo@WK6&_aMVG-rsPBbnQ9#-LD6&{wGlfuI?DQ&fKaxlod%eu9y zw2aBZmqM=Tf?I{vQ;X2*l-A4=iyF((+N!V9sCS!)>Sk4|*0*khRPSdl8u=cvcjMp_ zyBY#Mx!;r z56aKNxAot8vv&CHmNr2DZM?`HXq&1A?C70ufAK=oR*p+b)>P|72T0qTn>a)o$nUj z3Z(hrxx2HTXzO`pYCkib>&NxgBR({*ip8BZME%Y?&k^b-5m_O*Dmv z#o4I3#76p^aH(*aaJev5xI(y6xJtNMxCU@NVk;gE37?vi%=OmYAlxY2B-{+t3v!Rs zO?9iHX(7VX&b9J(MR%kYUU6vMspu}@?v!(!;wQZ)N_=c&RBe-DmG6JQnh!)B5eu=p zRnrwclWI2(%40PNc~RkT@%TCn}1-ElRi zale*gu65ZXZlUIu!d5BobZ|7QzF}!%*yWe4cl7);@nf~Ul=Vl!9}~^(eRzj>7$Qk< z9b{zigY9hHF2b(DZlTp8sS7rsJroUvZwggZ+D-Cv#?q)mG$f|Sy;a&LmHxZvSKfdZ z`cf=9BOaf}QDO1$^S%~C!Vh}6ztNI=< zyeWvOMVno3E8WmEob6fN)RgKZ_P3~Tt1wNtEh<|uTT#73(eG0P{~?&St&vW6@?lvH z?~=}#x%}=?`(EKb;eO!(;Xz@#@DN~k=#3f*?O{caqzHGyx~p(k*=!;E?l>P;=?US< z)MT5=kNuRQ87UeaF?8r(vczr}g+jk7^eeg=enwmp7y6Y~0dZdEnui5pM;S{y1u3V~ z9?P*!BxCA!4KasB@BMdglsbf8a`bkZ|3Gw#S4uS-ulDqn-xBr`_7?U5e1<8U(sO5D`2hj!hHw%@u8t>Kw;o3rfURc6nb9F`i&@kGEEH8(~{vJ7Ifa2VqBHCt+t{ z7r@1X`{~#lj*dn^4?flOcY9<#erA-unI*b;IHZwJGK0p9;oRl|L%>)j#Jxii-w^Gw zB@LD>Q_^4+`c>}KN*b(rBr41+%qM(0xCbnnNlD;xBe&8WDGLi^JrfTz+=4!`&`ePz z8zm4m$J=TV>lV#Aw#2a-6VNeU*B$t}B~)5cSSmHSe5)Oc43ouMma%SGVL4%WVFiG3 zOl}9JLg!4}f@01jvIKKpE9zVP32f;*KGJPOb->A9QyQ3*VpN5JFxJRNa}MRyACoCz zCYU}aXFcB?!_R6yvbwNF^PJHVsNkGD-GP}; zH?eNhrj7^lEaJz0)w-_*QyBZ+U9n(ULp zk*mes670zBwoPLZ}3t6|Y@Ht_T z(Bg`sF%sfoJzgzl-QvO$jY600hJPuBK)!mRU)7CK=vRe)MVJW(N}*rfV>8?<+$Y>G zJOE5trh3r-PZu5noJO$H#=YzRtTb4KepTpKtfi2}xObWyTp`v@gG;WKC47&gXTwxt zrCc+`_$A=yxpvZvM%WOa}L_Gn#X4 z2ByIm#pu!N$=Fz5*g)7Y)bVK{kzMs=MH`360N6n%#(2hyH?!_5S;t{H7N_p0Ory=M z+al}O4{*(}m7=ew2p4FUu&otsBWx>dmzDTBa<<?wRpDD*2^;pc#xkHLrp^^+By5+dUUViq|q6}aRH=N!^0(pSz@ z^DNR)E#rkWO>{o?;6@8)5uMW@A(K8W5bwrdH^Xa2c_&dZ$I*yJKekvR-93vbHIHbC8 z)t~|^Ixa=zs9>!BOwsWn!r3;wV9k%gx^tp+C#5x$k8k$a1{T*6zpp7-12 zw&jIyH;?qg6Prg1{i<3_^3B9TzZ!ThDfFvCzp7`hLcc2Xt5{$#Cb$?eOHNtF1*heD zTD?fQdP#U$ctv;>P{T7yeeT82fYa$4*1akGEflc)Yvy=c(L2Js!h2E4`6V){Lz;{{ zEZFn774XH-j#%qHQhS1AnOTHc)A5~rUM%CYEBcr)N60bfa469ARuU&*@zIC&dAO#_?*oe1d~{tj_pcaD-kl#hm!D zyskv4YNd$GQ+#emQCApAIT2&)TO7jrjHc0-3nN4p z7Tyuw72Xrx7d{X^1pFd>%$4zE+q2(<@RR3y(aXkJ^^TuSm|ggoFo!Tv__#2qFc-kf zxXknrI4MdV4Z|eKydS1f;w*$|lrV67&3SxwUSU4r)5841X8_+v1W#u71+s*vJl}9Z z6&4Z}7Ct8|0;o?M$F%?AUSI!JWV7ZQEuQr_=kbOmePpQ+d1PeaSz6ID!m`40!t#JE z#1@$Ex}u^l3M&aMp)GWTE}$-No9V{JH}9vo4F_es8mKuYtQ>M~1Daki(qaXgY~7cH z)r8fBHGsM)#`x;-H%7Q~@3494Ix4N(D0K)?RIRUQgAjR7j4^woRNzJ|zF&8Yn`XZ; zzYTxgrarP+qlEtfVJ(^xjtaOssIY~wWg{QWOY>IGOY?77x3y5RUlsZlV-ea*?BNRi zs?e_r{i@Kf47|)jv5B;iO@+;pJ34@T})UI!E z-m!7s72Xrx7d`;$y>SO$Uw5_Lo~{=krMRV&PF+8u)8wpjN@f#g7d{5mm38pZiCH3i z3cKq$n-WJG9PLz}Bz!{nWL9FWqViKwVpE>BEiMq^)Poyv`~i3$#qkG*Q5*xgdX1`* z{i@Kf{`s?C>0n&wSA~96=vRe)6$@&iUlsZlCdWd*D)g&rTt3T*!bw7*UzO}v-U$`@ z6&G3kCL4s|)~k7S;h!&E_~D>(12w;*&j_Ct77+ebSWs9_?k-oGF%LvP+oWyE;`tpia5LOhvD69nV9&eD)Xe;UnU13D% z34Oqi+vFNq<= z6qx#7OLdBG^}t*%w!x<;fwRCR-*8-<&M zn}u71TZKZuq7e%Hs+wQ#`_BlU4Tt@9i{Qg{M6&Zq#aqz2g@lDe0b{L^lom;K{8Pfb z85EO3zlx>1(637NtMTfj93+K)Rp?i-r!VxYLcc26uj24n=vQvD3jM0kuY!MO0EgO% zp$)So?JI2p8&wa=TAdzB93R8K*SHYr);%J(DjG?j)Ss{YcHy5WBe^;dW7XViRFcrFwO>uL6r=c7cZrHF>%(ILIO2AaTL_K{aY z3BPS4ZoH=Gb>R)+P2q3CTYv{=5}$B(E!nS}84CR>2n>aORp?hWg`v=|r1f0ajEX|P zf{fD`OFNliqtLGk{fa?S=vUQFGPQOVb^+X65&JYdM;m^0wR?(*!@_29_zxvEYL(CJ zDSS)VD=Tqt#rC^Tmbm2zQ}IYI6B@I9<5l1Gk?#om3kL`X0uG9Ev*GvWGl0AA{^ye|1=PhM6z)t7xyLP4ahu%^sA$kz|ds=?}Id>4r>XeThHC z?}ST*%Y@5?slpY)mBLlR)xtGE{%&z3>5Uq+|9b0g5N;H15^e@i<%HtJ)vb!Ag{Z~l z7X9LOMR%kYQ#V?7D!NO!JLMxCPc!#KiSs}(`C(DoIqp~Ufv7X&C1-`{iVFRz(60*p zs?e|Ymnw3AaG-FI@Ll11!uN%Pg+l;mHKHqr#icivto_~?Q9G-{vYxmmOj1Ackt0Gx zBoXJWpQHi{AGi5OWgV^%)E%w*F~YHpmM%el9xG-|@z!R-gg7OigFnkmcD#?AAdJtH zM?_ENPYo_V4>4vLLI_kRt9goWYRdby1JLP;&JfNN&dN$w0zUB^MJ4-HpIhw7MCb{9z}*%$SDqY1Ni!?ErgC3eZ_A%ivS00N%k3iUD(u#@(}-t{JroUvZwggZnzlPS1&5p97`9n0#;d(m+9#F% zyRu(lLND~IZlPZl`c zwPmHyuSmDcLb0m!j>*E8qG{UX>*jQ`dNx$2XWaZXvqX?U&arE&zD}dwZ8D~rOs!hq zx(!mjpDAd}vXd6A(TL`6gkA2GHc7=^N4wZ&St4UieR6_mhCQwRxyFJmN1ikjm2BaM zY$zEZL*FFtDxBsTBW{}@G2m_4#5vG-|eXOPN7Xgr%18J*;o&# zT|>-Om_ACoH%gsI*27Ug{{zh-Ug_UDUhU~Cza{J?>@DmA_{R|Bk%r$lOT2-<=-W{; z4_s|qAWE^codZ(L?G^{}gPIrgFdOhD13pHsh0!`Q<-ycfhX{wJCf_QeUN*O8xPcY= zRnv@xepRwxkyG3Y%J&^L9|#``f6p$`=@YT3njoKP7Gc(4Xy|&$5S~5x8W3GG5^J3u zWnv>9xc1KJb8`uE3zMQ!%Nz5_C!^FJXosukhML7UkDBu~nl1UbpH@`pSHxqtAtp!L zV0LYio%LW)R;ydLM%0-Nj&@rsOPEKQLD$JrXW;C*-akrcmh4w0`&DfsFZ8QIzsj9j z$$nL`UzO}vu`}sJ{*+d0l>7kIPRYRN4w{hu#=LY3Bjseg+AZqkE9D)jp$)2G^B8Ba zTAM3Jc369+m^cWm%X?9(_7?VO)Vtwt!PzMSBy_lfW6l1yO5X`3lC$KsDmyyfd7yO% z2IhY5!R{yD@h;d>tur9!`|3jHd&LZM$3`jv;n zlKrY=zpB@XJ_`%~A?A z!ICag(qM6@D?F^~EIY&5!a2e(g>!}T0QUf$zWHn}P;_C6I6uY}CO*IMA0&l`Rd`tK zF>~q_9#-LD6&_aMVU1UXhgDy`Vc!jp6;2DRrFSJAjq7sEy@iLxCZq7MGAsdpU4@6W z5z)WowXYe>B5!B7eOWtsMk8&)AGkAR(}{RJIY{dZ8-zlK7}Q+2Y^3PR!p0#t(LJ`! zO%-hxBD1c=m5s6M$E&ZUn2g07@wZTOOJS>&<9Ukw8hQIC`ephX zAHLy#xlRse!B%@@bbR>M@a^F{!*_@84c{MrF#K@%_u)sC#E*hb!GuI|5aE}SSYkQ@QSJYoT5d9MTO4`iwTPZek}Lc)smn+;T>9fK;G4QVuI2q&W4(+bNz3v?E1&1uKK^7}*7*awDJFD6 z{dcqQ*{uCW>~B#GnosNMldv+SYL!MbLO`Kva+bQyQixeBy&JmCe|U5K1zUbn;bGB+ zd)koS6836Zv!$EIK2c(CU~})Q!hXWH8?8PR0e|a=A9{dw2MPzJLa%2Z`JSTh3kM5_ z2!{$k0DK&eeBOUplpr3A#x@4uc%D8&%^wRt5snm&0(j6)%{V(+(J>)v6T396cq4}T z_>UA1TD-KHqUO&+1Rvjx*a?bC8mzn-tv8O>+axzcD{;uvE%&CT)Fs43b&CqO3e$w! zqSENHsNSLI_bI}1l5^<@5mEfDar3PuModBb9<}ck?i2189uOWBrV9@NK1nWeX0V49 zJ(40O!m!kiwHqpbUvA9fDm@`QnVQ6X;KzPS(To(0j_Bb1mn;V(JS;CxT%-#RtDcJ5U8b>mHX{xmW93L0DMtxE6^<5;5sn4wNe|K*YmuVkQbbNC zroW#lIzB{gC@1yQh$p1mt`n_0Db=B*(f+?sbh2=YaH?>caJq1Ya3;V(yP6s|1F_8`ixk{4EsP-BC>tZ!3C7cvpBYDv9$M zHYG+a769MZVT)7$hf60;`X8x1L7K=c!mL3Fu>aDfXIJzwVUCb<${hXgu=rrJgm9{mNZx{H6;yJ;bFy;S$J55hgEo3)f$pb z))dwXwna&URd`q>4VD9<@US=zaWXGFth9)>|EKV<3jIndO`%^E`j!2l(68{LEordA zz=z)mX0tbvWyf`A+-;54VKd(fF(&ayXrb>&Sf&w#ZM)E~#;e85?z6bCMA9s96VH3V z5xrr)VBOML$4vzm(`6McCoC_lAgl;zlo=tLW^KI0dmAHZ%er>d8BLYntE*^4=n4I- zB-tD{n*&8-!pg!b!m7e#!1v=U#4ctvMXQI1Lyr0V*31%iTgrQ}~v! zm#{bBhZEv3Jtg%~toF5TzpUf)(~E74xV%-NUlsaQ^bDdX7y1<=;x$Lh>(M6Oelk0~ znPaEWuL}LjMWYwl&)9;<+H=*hJQt_YX!v@hA&cZrH<2Gp~kAU6cma@>V4ApN-^xKU!u=aYsBpL`?boQG81T_`uNwJneE{d+;77_aV( zl4*bVq`Ou4Ln^?aibDjq1+4G)S$DtiKqwUY7113^8Z09PxD#6WL&$O?!joka76Uy{ZG9_FnVe|~PJk$i%>_=4kQ!4f9h-r^0 zdOSp=d&8%ydQ#D!g{OoWO=Vk$w7)c^Zg9@^^+WuOn$HT)g+e=`h&>-A<3q({*y?Be zICkuO?U#Mzl~6KCFDJ{_6umCIA-pO4O?V67FK1qrj{MHdl1AkBRCr(bAmx~!W_riP zEfqdpXijMOIxvC9t660%%oZXpw}Pc_h}7n~EQ5Fuc@FK5=d+x{qaG>i#oWGRlJJRC zVA|rN{zcKJgn5K{h53X}3-bg1IZ%*kh|eloAVu81eim~)HC&6vKvGNX^m#(AIx{Z=Kc&qgl zZ4e^wiP_m~lnQ*U_H z7Yz)yw6`m9RDm*W|AiOBN1o(&b22x*M zQS_?tTF5b775Wv;u|U!$IM&8*LVNLBE+lBOf^;M8ps^2J25! zfqPB5-%(jd=xXYYR{a>^*hXun4I1w$KSrAg^U#!hj!^o{WXJo+3BveHc|;9lH^z+RM|tmY}gsVV22h}P+f&JfNN&dSP>7LLo+If{NMoGY9soG)A;TnN|*1Y~E< zyhzc-!mot?6n-uIM))mY6XJfHCYaje?^5e76D}8~rdA}!xiU*Md(Na?NOQhL+gJRj zZ$#beeD-?b2H{5GCgElvzM=P2w7vQ+3-9u65Qd(a^NujyB&;VAU0Lcc2Xt3tnu{ZPq% zRp?jjh}TMv3i-!!>ztMm%&!KXSWlkH`oadnhM|tR)J?>f6>S`%7C8%Ilfwps7jI_W zSF#R!XV%>Zrv7HM>b6C7h5U%dWzUnv60wX(Kf=i!gg8N>1hhyAxj(+P~9m? z7+3u0T~yyy*iG0yE7@}K*~2L5F~!GLDir#atx)J!I1qczF4?c*1U?welMOrhxSYYf z5avvVcpPzBP%#MeZvS~ncv*NwcvW~!cpdO8-tst9y_qF$P&nzlrNY~dLPw{!cNM)S zyf1tpdM z{LF@Q_9#KsBZr<73{DOVr-_YtU~0-aeQqvcZedbXYI$QD{>dnLSD2ion#DJdn)5cA zb-vtBE1F;UjPTj0Y~w?jCc6<$i3?h{kg#wlaPg%nZ;@0V>!o=U_j&KZ6i-~L(62m~ zY+$o(C~Oq1g?o#Kkc|~>5+ZUJ=k-N*)CT;Dbze<&E-g^sT+tS(&ZR=V(6q@7MbG$p zh`qFCzq7TP+X&kV+X>qXI|w@pI|(}ry8w1Ewm5O$S?E`VepTpK^_XDUX5c;HFnLn= zbBq-eFf!<7)N@4nWn@sXgHGX1vg^O7^R&(67d;?SebeW~UP-zCyp! z1X1W$g?<$yqtLGk{i@Kf3jM0kucR7H5q_3Tv_ikSrqHkIlUd1rg^{n&uMEzi{j1Qg zs_o=*Y@b{Xthcnvj*4~?b{2NYN_b^)8QWWlG2W+`o`?TX!t7i5+@8X>guSw| zS0{DfCrfx=gsGT}_Hm?xJk@frK877UjFf~n!!mPNin(6KApRpt)e*vvLyk9VX0Pdz?=; z%L52`Ny#zPO*OBKt@*;|UJfdE2JBVcuO-(dUK5 zgvEs=0FT-PJ>(i?sVos)i|dP}Raiz?Hs!rht{|%A6|EqwD11>^3E({j@I#}ms3UZR z5uqpa0Y45>K)Upo>{o?;mA7W39+VY*c=QqSz8aFQ(60*p$|;PiRrmw+XD(#!l&D zq|L-&`MgRm2rmjR2`>w;2(JRZnJE_|&FhNZ2$7jJGrCtNlLixsnHRp@JkpOu7&=cz zpvIE@s?e_ng?`1haJ>3A$t(K``z0p@SB+*AyDiz@x&wp*Q(<7}JqIqn5NxErXWjRO zgHwS4jVHySQ6hJEq&1KM&35T9H4jhC?g#-#9oM~Xj7U@KfPv;TWL) zXo7Ck-=RCm@MKH_tZT=qG$obB20>KJOm8PxHy(AZR_&*9QfdY@@fTUw&B&d2n6&u= zPxZOegwq@Kp5X`1Om!wpzVg{wf{@unYU9(ZbA9eS;e6o&;X=SaqBl0iSH4Km#lo*b zE+v>Jf1M@5sW9dJwy7)Guk0^{e${g@&2Gw(j|p=mcZT5O;XOrePWtYg*3A`lM!cY- zPRf$e`|2S?j6u5Lzo_{sVIHAmzZ%#KV}SjwHA-+2$1IH&|6#Mi^f@`}$=t<|UCl>U z7uIN=Ya3x`Ek$b!>j>)#>j~=v^-Mre{PAi-MH{84Pe9drYU~bVS#M(9rcE82p1KaY zFm+$G?rXy4!WOB;7#!EKrl+j2#=D|36(AX&2t}HZR zz1=qbHmmb;`2+{^Se-{&1CG!urkH%!>^xVZRJBqx=<3kjQPdSiQclF!*dmXZY}=2* zsXG#X5QQtY-8eJHk$BM6O?nldUsaeKFJXs2(;3^C;;UP?hOnlvR%nqS+@zB0C|Wl} zZMGVGtMwIakXksG$Hx)w_s zY$beM_=d1Gz~73t&9-fn$hU0puI*LWLD*5)DJlty;#qJPMY{^S3A+n>0RFVBkI{my z(H1L1pd>xXPBeS}63ZToR1kSv}p1oDMlk>ba*0SKc*GfP-qR*W^9ozc?)B z6U3OQX9@P#-mbhH;uhh{*+{=?OTQ+(p6Wywig|L-CGt^xl73uosr0t+j_|JVp76f# zf$$;V7a=@(SUri4#Ai%^e}R}g7t^cEDjQ=qVRqqT!W_ax;p4)b!d!r#KIl7t75Wvc zO`%_rG=t7i=vRe)l{7fEQ(-zC$!UvCS|p3pE1NCKCC(+k6D}1l6D}8~3RehM3RekN z3)cWnJnSRGUeFum8l<}3x*LQWg`0$%0Vh1>O!h{%Dw-A|vbSgyxLwg5sYR}Fv`Y4? zlKraCuN+_`Wno;cnQV&Do>v2FOR!i+SXWq2SYOyc*ihI=_%h%-O7<&Tqh!A-*{{r^ zn4!S&zG5idl|zJ0IK%7@_LF;rdxiUi`-KO9Da%w3`v2*|Lx4kz?Pi3%9MlZ+N38o( zQ&%sEk41?{A*M2WLWL(&p*x}*#8Zl9q==y6VXYubYC2VonNaCzm7YnZLcfZ}$6AH? z=u<(Kk(i(664`0>+{r~n{U5xK;ueAgPjL+7>NToL_N$Wp>VE+J3jd=*zbf>rLchYy zH@s|k`EaTeJUQB9UdQbK`BlTKhu72-|A1?N;dR67hc^sw9Nsj%d3cLr!rqRJ52p=p zqrmb{beZ8D!`~0@9Nsm&JL*{-hW8BbwLq+vSVdZW>~l(3>#2TlIK8eO!Q)~0$Kk`n zM?#xz#qiPLW5dUXPbeU*Pb}nQ4hq+Z-T;H&a7Mm~hyPOR=|JRvTK)7R9BcV4pB+9o z{3~+4CzlAr7ltoV&`&9rEp{<{-Ydgbhp*KS4;&kB_+M_3Sz;DVjY*L_*b7eGWwvg^vq!3Udi_3zLLT0DdMH zD)~o@a8r?zux{f2j&*ZhwdYH1yl6P$&)<|r$v@8{ZGykEL0Uk~e-#!K77DEn=29v@ zr)UvjQQ`B#V#4BpAIndKL1D=#wa2>Ja=(yuoT%AIEt7RnkEvU(sY?q9zj~7(rWZb9 z8jN!z*46i=mCtiqAAd3%HU7YEim|=bf431tXx4rsu5G-7=F_^~3$0A4TBQ-$ldH*D zqVq(*#=H{Eh>Lyxhc`!m@skSuiZ(3Suk1;MepTpKg??qUw%V^S-S7+js?}u+Fw6^N&H0s^PldsMtu)cL0q&fzPxCQ7mY0C+3 z7ppoh9@scGNyT2rtniy<37be zh_OpNLvuf2=vmgPo@ic6^9z(cV-MTfR&hfxfu~wGwl;`u; z$r71x7%S`jql9M3epTpK^|V^(S1fa}Zorsjak`}$CvC^jv@F5aWnQ>FN?cEA8~Qz^ z>Q3RVMvI#(F3=R+Bit+8C)_VQ0MtwHn3KhHMGu8YqBsNp;V9|sUVkOSFZ04j)qE`K z3jGTDAWc>1SJm=RBdQgWA3>13#^Tv{WsXSzZ$&+6oAnd#_(-=AwK3(E>{oQAe+v55 ziL+{w=3li>{y>;l^DM`Oz59?3zcP#WxBV5r6H3qoVy?hck9KvSbqD1OaQhFRH>MYU z{qI|MuyBZQsPF^fhr(gP;Xpk_6&_Z$1Qv5PTZM-e%~5z*x_i1$cqjWu;bDzepHFxG z!o!l>P$M{1_^Au1gz{6P4jaF}qo@FU>}AU5BT+Qi5d4C5oMJ1Xn&-ww;`=m;jU z>KN;ejXK!p8N;mCGeFOA))gKW=a|C7q9^>9-Qh3MRfxePbhgEo3PKt$xRd`s1 zhZT2Vn3Pve) z1l2QEMB!m|dS+qTSjxvHN%?3web#dZQ|@^673;nlbp*mNG~(upwn%l3;}MPx-*C*X zUk@>yVM)katGSJ^t+1W2y|9C@qp*{(v#<-`=W;(CchE$L&IlX>`ImcSJ=e~ZzL_Of zh?>ZZv`PCpmML7|aI&QA9g2Fa^H@oP6w`rz<)`I8!*QsU#oL zcy*4VUkc|6=S8LF&^YaqUycvC(7OKVb)Br!geI%Lw4P_e9XEzgo&Zh9t^xho-@^n zgTZ7ww+fSlPY9pP%2t;hO>J6)>_1-36Jj&P*4GK7D2XczuC_DHGh4O@c|#0wY?q() zZ41O>1j`~$rMouhYV2_rvTkAFbHXB_#l;B0T=O&0TFkn|g(Vt=E+LUr;BK6+{srrn z&N}Y6`P5|d;o)u`xUQlRp(pgSl4Nr<=Rnbz zu(Gg8X|Qmwvpov^s?e_r{VEQDg?<(7P|{#AF&6sOu@hN2 z$pf=&y|A-|33mko?A9)6c+?r1WqZkKJ0v-+#{%AHvylJO)2{|>ehU4n(60*ps?e|M zd8^Q`n9U3Qs?e|K28DiA=vTE>rcctN@#=b8;|3rtDu`}sN_Ft0TU5AJm?qp7m3Y+k zP`yLZ?^A?-at7Eohp}cOvMkgR$P{LWxJT`Kh5Lm2g$INOh3UdWfKQT(9D~!tiXKT3 zsZ+wHHP+61L1HFgrh8naCxj)vC2VLY6#A8}lO+vS2jB5R zzuJi8MVZd1(63A}dPMM%+IS%ZABiMSh>w)Wb(HW^;b`F);aH%a^x&$ESO1~txD=7B zg6Z#PijEIa8w+@NB;(Z0d7IGo6RML^9cw$L^^p69C1EY=Pb;Z>u1T*%X-?Q%f!ojI9W?HoB&?u3zBoZvS z1hW_%rsm_!%3-G=vRe)6&oA~2W(FY{c2uW81o6APAUdtB>d`d zF;344m||qB&w7R~`?LjpWTBa&NH)rF<#<~yV%?%y$38Gt#>y}VyNnxqf zB&Ti6H-nA|N|&*2S)tIcSg+WQf7QnLny|UB1>hXX!jS z*BbOmr}58`2CHPh!azjIPLECgL?`7>#OMmM6X~OwpiWM4Yotl%+t;R4=vP?fm_%;1 z>83>+$$V#!+^*=3Y&KkjV=&OH^<1V?8PDCF_2id{xvo{{SJmHaxwo=qO7^QlzmjsX zrm$8+MH!e~aven_`<2HMrjIV{C&$1w%|h*EWg@Z*rvGD)9c{tEX??&Z+@X+AePf?2OR#z&47 z{ym>#isSD)PSKPU5mXA*;}xACj0-0UCjtHp7z>l>F))_S$=01BoGP3qoGzRpoGF|o zoGqLq{8BhqI1jLuuzd2zU!ds16wx}#JM=ghIb!jjikZcm-Eor08PdSHgb^zZQNY{1!l$9+2T9`C6FIFSYJ6;c{VWYQdM}AaP}uU|8nh z?2g8NJki#R8Y>@P^E#isUbsQHQMgIC8HjI)VY0ea(KO*U;dbE;pw_@~xqc&DN7mB2 zLTq{<{_faG!9$@BlDnnd(9RKV5hT@Xy4gSAWy?px)v6uh2^s8w6LcgL@6#CWw3i?&A z(673MepTpKg?<(Lp&mAc;VZ*ehp*L}1lXtJ!#Dgd{tU5YYPInx8NM}qd-%@q-Qjz~ z_lF-0KOFvj_)#@MH~v||ai8O|{#LUonmt5ZP8xb_4n-4%j|+1Oa|v?`lY~zIerB&1 zp|%NXLEOlcg!KkS1UtNW)t)c4VI8nfoxdrKw!-q$8ui@1fSUg*EGR4#S{*{nQTaJV ziwKJfg??4&S9F6yzj82~D4Znx9AFGWKlem^vZ7N$#Bs{Q*lDT2B~N4c^%CYxHO~^x z7S2g6f)p}b&sB7uaK3OsRJL%stdCO|YaP@VS$A>N>D&-!BZ3t2MSgAFZ}K^vf3Q1d ziAjPv=u#Cf6D}8~HkD&0oWC+koz4K8MRm0b*M!J0iupN(enqo9lkGMb<$xP=aUOZG z%LnZO`*{5DEvOiTdABuR5?&Tw5ndHu6J7^=4F^$L{>?0LP^BlmrNY~dLdTBsuA=vZ z_k|CH4*`25-e4SfKTw%Eoj9Wza14Xmwfmo$?Je(CjOGT?^F z|Im|SE#u0{Tdb*0Jy!@<<|Axs+2>x}yr8B9T&u!$jR?ltcy)uK8-<&Mn}u71TZL)D zZNlxs9f04m%Vi^XVo_@GP57j{Rro_H49wQy43fzCW6_}nS>}Jdl ze~eO_hhwYGhJlaylg~XWJSIFYJRv+O{8@NPm;uyH=u>_+=I2;cdVSY{r&W3;l=S|M z2Ib~1rgk}(zZ?$PH)&+J@>z7 z=GbAfWbB-sB_`Ootzo`l4n5cB&J)fTE)XsRoG%H)$vSY6qKk!Jg`7zaZ;k5LS;C^i zl=s`Fj&+FG?5bayqBijy#;eN}O%<*Xt`x2kt`@Elt`)8mt`}|)ZUp=;g?<$aOrc*@ z^XP70=vM=qVJuk(C=Y zfu4`)!uU}2ajcE+Z+dwRyw-WyIpvj5((Q$5<~2pH3vUQ-3Wa`EEu6#y(p}L=CHqyO zUopyB-F|v};Z_&RP|1FUYhsKQCX{THLcc2XE4(9<0zuk}poDOjmv%c`_{Xaka*8Fz zcTHYkf32VA%S~?@#pAeol~VPZ@Or94C5W|cK$79y6U%&jOQpAkcZ7F^_k{O_4}=c^ z7fTk!uzIot@);8v^1#5$##to~%qGk(d`y@_m?(T)m{XVwa84NX4TU%0E9FCHb+IyMFxFH@FM^9!lj9`S^=jG|?Q<%H#%%3enI9JF+g z{GxR$MIF36Ev9Wn9ih;#{uj`%diYb8>{o?;Rp?iReii1%Lcc2XD~<|l1+hT_T>7_W zU>Y|^ocPz1>af1Bfv{nyn`W6!#FrIq9HJIZvq_j6lPt5DbzjLkf))q2p*w1{o6W7; zBI`!``ucCB=<6wBPlaiBYem}#+X~xdCBBZFq;|*>Q5sO)DN5wA@S}H8eOF;OVfU=; z)t^0#l8&T&Y^6e>U)c(Uenq&xlKraCuL}LD(654u$Ngc_XiE00LchXuhJg{g=R&_K z^efq1f1k5h5=7k94CPk$V zj%>p}86^YIMGtJ%EWUZvoVU>={=|6oX+`r3pAkMAmHJSI{|X_y_@)b5w~(-KC=f%L zD~oE8RL4Ih%$t$nXEDVS3;k-~xnu*IZ9`$BXf3S79zr%&v`L6st`L#1{J1wCEb#sz`plJv)k&t?}yj_MJP0yBaOxF%Z8{(LKVw!hOR1!UKTa zny7+|i0O(R3XuVqnPVT0k~41IZw?b$8rb=J(s+*?<}<}rOZ)$SSkrP?#aY{VIZdr_+P7WQe>nT2EQj>Oe%XM{wG zL~d8X`Wk1($=pYUm6exRPq#ypdKR?z|} zYW34+gh(OGY71Fc=vM?e;q0)wjj@JMvR@VY72V)xIcNwe&dJ~edq$yOWt%iieSAnu z_Nzj_irs9XUsYqWwN`G}2=itL z^+tVa6GfW}g?>dN6#7-&H%j)ax*517XPA}jSIicp?F{rwocY)!6C0DpdB>^aUEw|9 zec=PZ83v+JTt9blQ6Ro~id#)aPP~2D%g!oYXf|PX;bTDkaDDqdF-wF`VPc-MDG^zM zIOnQQ5(@pQ(6458IgVW4u%Aq1|4;gtW$R-am#c9PM10b4K)@dp&F$?zJE+b=-eUo8 zv{}e^wr&?;S7Eo%@^Hwyxrd^m@J*qLO4D}d=Zw+i?Z=XJadc2=pHw2rE~0%E?H8g} z7c=>I^_?uW$MRgr0WrRj>Bz^cgM8$>z?5U>*tpd)+JB*675Y`7UlsaQJ=fsxRkB}| z>{o?;#WGpwSA~A%q*&-zPumen_AAbh|B`<75c1NW%TPDfy!zbF7j<$_*=f(O=rh7+ zg$0Cv6&4g05*8Ld2h^ukT&%~dMHPKsSWH-4SOTcKVeNFiRF(#Hi1ejZSVmYj<-Jk8 z?Uz@yg0Q0SMPVg?_jrSZMq5!w=n5l3Pv`@F94GE{>F>tXk}0{lM=IH`3jL~Nzv5ip zas)bb|G(&0C(dDBSpHQd4OU5mRd`sr-lb!r7O(MYIcW>a3o9gdfg7q^e>%D^tQ2B% zucF>ovmub*l)g3X?+%Qbv>YtY<=?)va42>P!pA zdbw7Xu#@un>tv}jAi!O<-akrc79LjNVbwdR;3)p0={SXlbxSi&xbYsZ3J;6ss9q9Y z7G4ov1>92@>%2aEa;Lxn;|=TH6#ft^SrI-9pPQ!y{Objv!3)|PjW@?`#Qax zO$q+T&BRA)Pmp{vi!f_2P`D6qj+|Z5$AmdTZWQu(A4xj-Hgj4xSJat#m`QI^mJH)p ze{X^fdR|iVQ$k6DRd`r+Pb@qvPuI}Oa(B~(^i>_{5IHKwP`j&0r9pi)8g2{lOnC0@tT%LdGX&Vt-Wy_> z!L_)}eRAB@!UtxSeb9GL4<$K?p~NfWei)7dz2Fg*{*+2ROf=)wV~QRRk$27fuum%b zv+$HKqp36qQA%%y<+%%GWb{rJpQn|(G@vr_5 zKI!#;h#hVhUBxzARhS%H5{Ryx)tul856gzbor&q7ipD8vunG_BDhJEe!ZpIR!gYY1 zg{7zo{!n;Wg@;vmSopt7V=6qXYDe2)Ct+t{7r+?yEnDnc6<~tL-s8A;0Y--x2l~4iF9m{0{gdHY+~fc1R3^ z6Z=@G6MXW)p$G*|-^fGrF_Nx@HKFjZNV$-Qhr+|+z+8A(g@;vmSTVU49+sSu1B3&G zgM`Avsu$kE!^%BS;bAc<+=>+*R!M_JH^5jIHfktK?5EaD;t=s+G1;vhC5(LVjO;XQ z(h;vGduV-OgHY(;1cj-1BSl{pHV(NKJ~s86D%vbW1oBPmI2JBW6JJX);WarsY@z0s z!d5Bg>I3=z79JLNvW16LcvyvpRd`r&g;ID}B@GtqUrB>icv#hV;bGOc#U%|^;bCzS zsr?Frq~uYe@UZmRTvh7UWZ_H6-x`d0ld^g?RHvuo=9*a|S|CoKYpcFaquwRvX?@h| znN(nX>o!RBeka3Pbh;6bg?usLPO6IscS@V2B5q{7ce5-JMzy}OfN>UCJj{|1S4XWe zGahW=hioZqm5&fFC%v0$pNOrk+a~L{u*%Ik-|~JPlcm}V*sa`Hp!3c z@6a8DC$iH3dy(T*nvzOmgGd->qGUe#1nb75PWlQn(@CjW=vSn)O80);YR0QVznU;* znR<&`r#XDlu2bk&;Z;PCxmdwT8pv2(AUOdHUACDE$^uwurYOiE3|BS;)gsm{nsrc7 zVl{>n7O(3LeBBZ%Eh#LOnr!A{z8Q4nqb+0Ivchu0^1=!Lzm}PjB2qe=i}VIFG+xz; z`W6`hnXx)P(rrX-ub+BNX#fMJq`}IYypjfsrKZrYE@}qHh#{nZl_k#KjK*KjESZtu zx0I?&LgabB9*nN(L1623n`3#;!~fJqu{FlCS7wPl0YmU=-*k;|t#F-iy>J8I4#04m z^$uXH?eXE}5bN{KBvR;C}f!J-ig{fb8T zONG0E1UE(Rai(xql5Gn8DpuB#2J6l25ruwL=vVAD3;pV!C=J#qE)Ru%Rp?iRepTpK z^_4(LgT)@Uq`@lmE4o2RgH`BP^_6p>UlsaQpu>bR-s?%K2zvd&?335 zoSxhy+?DZc`(u=Fm<*4t7Kw=PvMKZ{wv@95LqqZw?KXSzHApxZe%?g=X_M4J{cuQDVgi3)hE(^HIJI}HkvK-B7R!Y{K991&qk#_l(i=Z zeu|^~NDErGkg#wl5WL8YHH)M=MAUGA42sEOiYG3`P^c*>OXM>x!=o1Z6@&uWKO563 z)h12T$X@lzy*r9afAtmXz8ZCgltO)TMO&mg$MO2EUrzyg#@9n^3I+z+)@p7eY%6Rh zY%lB}>?rIc>@4g8__?IW2r9uSp5WmHIDlnP?UD6#B}(7S5*@Yn0+1yY9zSpn!ciGV z1vfORY|( zBISo*c%Ey^ohO_xTp(Ns=oZo&)9w5sMHdUd3ON%6L5r(jXNjCBbi3a+bpseJ)$dfl zG(~L&?|5~&qN&0a!j-~R!qvhx!nMM6!u7%p!i|96rO>ZpurV#tn9tKHg??4dr%U~( z)1{vEqtLIIQzNB88?HAUWpcwes52a|W_ztJtdVlOQPEmU(b~c~!n(qG!umix6X2CO zUTvsoqZIW!;h@&)4qWCpv2N3*4zg+3ehHN^UVYWNuL+wATcj2|7N(c2vPAB)jG57u zi@LR%+eBS!(AR@)yVPW-Q|MRY)e+eog??4&SJ4$b1H|5{WWS2l5@HndR-s=xheID@ zx?Mb32;G6936^X)38TS#GcHN=ps`W3dCY7Rah&V7Ws@zJPjE1gO+N%SHtj2>nEbwM z|5l<@wNfp1(! z>#e&%xKX%CxEXM#%9Q|H%3Bpp3lVfOjRLnTx+Ap+c7xWPitZBbPC1rrwxIV!iS26y zza#bzTZHOh5mpr@1HOMy-;S-OX!Q_bhx4vy%`A=f!aBmb!g|8` z!Un>I!bZZE0sq!Qzp^z7{i@Kf7{W|D^#ow#o$>0f93tG3GtB;AKetXYDZIJfXsqslZh_Q}k1cW~7K* zKlNN_9O#Hy)EaXpds?MuQi)*G%qGt%`fG?dJrh;7dO^{P!b>6NHDR-7W{qfaSQA|d zUQ_AyP*TME3jM0S-C(gQ^eY#QlKl!>CPQTpb8ZcVZwggp-?E#8TLhuOV#so{&K$D0 zO8cY|Q63QOt7yLvwYqJi#C|7B?4aUdCX&4Vs`n8G`N(&HDaX#Saf?6>okG9r7W!48 zUlsaQy?ZJ2E9S>Szbf=AxJpZ(xAfq9*$VG#Ne`M-=p@u!hOR1!UMvC!gS#wz$Y=naQ=H( z(IY9s<1%boW9?=O*>}hJxJpk5Po^ezIW~!O zKiPCe{)aCe*FpRh>6O*SNw<2@$6gX%7G4ov6pm{b84CI) zBcEH*q!hJ`id%oplKraCuhP~*B(@j=gwMk~vZEblr|2*p((uIC#&ApBt|5lrV2J45 z8>LPp>v8CWHZ+GcAVX;xulDqn-xBr`_7?U5>Yhl1T@HU);td=Hza1qfD6DY52n64L^w1x`BpK+ao`E}o09#iy0~e^Lcc2XE37Id z`&FS|F$HfR0cAsBqhO&F`W4qAg?^P+#{}~Bj`dVK$Z5jq(M!BRVgFm`SMHB~Z^PUv z+!d|keLC_#D7r_uSGZ5OUw8m;PsFtrCxGdS9tsgR`+fE_4@XI7_j)JOVJE{2A64_Q zsFR___ki5nbebfM z%qmPD-?#2y;Sk|a;RnJGg~Noy0Y8!4J$&y%zp6R<{IG?76&=GBDcsWv{VGOEppJah}g4bdI$oKggYpXCD^z&R%w$|>JGGJZ>H!g!dFAC zj|K1BJhj-FGu>~g!dAl9g>ML311=W$mh$Rtqg1kAWjhr5RWyWwhSIsNakk+o5Vr=* z@vQ#8L$SJ4xJpJa zh&r8t=Z%e0fv=S#e=L)@LyhD9a#J7KtWjz^2Yj_D5tNCwM};kfEgShLX*T_4t)5Ah zzhT|h!ZxA6pR8l?c8azSQH$VNeB~V#?Ii3h?2?uIVevwE5`6ydDaLb`ziIdnCH|bs z=k^r7CG3@zxc0K_?UN;rTtV%|rk9gj?VJ2uOyok`czf;l&a zUoFXJs(F@hws1~r^}V#J&Q)}taK3OsRJO(j;o_$I4O$mjcX8AiF(-^>n7a8Qzqal- z`JAzr3Hy{KXj9m_E>+<&;c{VWQ#q!|?aC-=R>!n^wF=jShi>r`(Ff6I32j!H0jThTkhyTW@>2_G!; zVzj%E*7P0e^a#r4fAG4ZwLemOg6xo4gjtg!(&`bqwwhhh$AmdTuG2?&Pj&iq;%ZLo z=88HaUNGrR%98Oz>hDdAK|I3#Ma@qMg?=?^GYo`6zp^K`YFgw@G)Ubq3;pV-XbSiQ z4gHItH!*tq1Wm1u&88xb4<@Sr$kGVjWGZnePl6h*XG{&pXFX(u48Sy_xr)vUQERmJ zm%TvIg(<@IjPGCQSJ51Wex-M=IiB9h{!!>xg?{Bug$!J{!Ar#`^s9P?hp5TkZJ(g( zz&$XU|Gu`*ejy^=1etGH3*?nC5$~Ux++QT=xbLR%ARqZ|K7#XmECCF{@P{9%^IIOG z(xJi+gdYlr35N?m5{>}srMqOm$_ueVzoJ__Y~Oe!`i32mLHwwq$5PZ9OZrB?Yryy? zQ%w4GN>8a-=vPDn)K|aIuabwr0W>$Ug??4&SA~A%8c#n68eFH}B<<;i@deUh$$nMn zS0(#Z$$nLvk4Vyix#nwrQ}~v!m#{bB_u?`w4lP7? z;K_Zh+b`?*{MZh(#*Cr1zjcLvRp?iRepTpK^~5wFmU~Qng?=?TGcgUu^iEhUOND;* zPei|JalKRMSA~96=vV(s=vODsIstM4|Ax;FpBw(QKF%9Iboj#XMGCIsv3?aE7F+wm z!zw&1xon@!CUsh!RA7DUHb`~ya!0^D_#WX`ifJ)CLkC@rf19Kt{$#v& zvn-JXt~S>}uKY*x@3_0*GMGc@7JkTB_?!p)=azy<1ziP1a%kOLvB`!ow;& ztir=8JSa*Cs_H_(pg7*_n1s|)fumrlNhkP zutF*jwNQOtXo!CPFP-80njK)rljyo zz*RX&W*lu;1X@u~{$_nmJ3i8FL~X;s^qSH@ujs_J57Z;!PlrrjK3$)!vpx2icUHAgyTO21vv9jS#`qzO9}>{la2 z@!Z{6&-9VrLmh1k_lCIeunG^$^h=8*A7N}DJE5e(Dm<(K$yJ?{`t6wDoGF;#3J=Rh zVS?tM{&Q(NzYtCqP7zK8)F6Bw1L<@{X9#BsXEl{A!#$j%=$FE|!g*2YEqFaqw+Zma zhg@jg|A{)CO)(=}+>~1G^Zv6b{a^OpJpRt<>idr*L?qNK6=Eh4>Re|&A*dRXno^Y* zVotDKhCHE$Dtc?R6nCW@TJt>IbT-sbLl8|-YEDg+dYR{;rclr4z1O<<^Y_>D+;@M^ z${(NC*=w(Tos<3D*B;hhpS6OArJf2Nmc6v{9@YnTG}=iFFhY@TA_)385R%m(U@)*S zum~^&SQH2z7QN6A(3`=-iZob}2Fs4k4a;g4Jgo9Dn;mrPz-{sqOc?WA6lt&&X9;@B zLcl=huP7_0naA1<_ALujw+JxA6pC)QrvvLyS64s`?VyICFdSGMSi&on*W0d4lwD6d zqNPksrr5mhiJ_zG|GWU!JntG_W$lpI>q@UCc1wK@`!OSHRd%5~iDpMrj+rA7gSom?LD zD}{e6f9ZoJ=vUceyRI$JBfLzH`s>qcIU_)RYIZGLZ$b^2htl6%sU^!yzkCYO(2T$5&a!_4wzq6=0rNrSEWXE;oR0lP`-%fOTf#fpnK)6{!*`6N#+KTUzuiVZOgeR zz6_>~H)-;gDdBsrChs767kCeNANVKmfq?Ze(qIMs3XaQWz&DJ{67;K}Uull(muE02 z`aUS+>ua2}pkK8JOmGLCGaI-QxC^)&m?Owjt6Y|urj=0>`|w;77j?xS>zDVUc^_~; z@E5C;jTqDOgI3acyvm9o=j?v@Fq)6Jrlx$~zPH)6KTciHuUHkeDEc}b^ecD~V}Nym zvBr>K3#_+$eMDaaHUMfs0n~w@U+qFS>IR;0o5agb+rCTKIAHX{vI(69c* zT=6*&^s7jNl?{542CF;z?K9w2;e`dOA(c0Qz6Z?b=FN zjoEPj+{7~a5~uQPG|vIfb$Ppsx%PZS7XTLm7kQ-;BI+A2L3Al_8E`pp1#l&Bm4F4M z$rW6AHKJ>PUjn}ZehvHv_^m*?3P|L68uYW&71vUC9dJExgKLQ|scyZ|OX_wr@hjw1 z#iI1UX1ep!&%Bkkw*j{UcL1}2I|cR&366O;qB+1lz@LD*f~+CdXCCun?8_K+pNX+U z>A&_DG#>yS1pW#<1UxL5HM)F+&yNC+3HWcyN}GQvv843_=TY~!s;&c(;wdXB(ldX| zXHa<76%;5+C$#4f&393=_%aT(+kblyNnb$eMORX=Y5hT8M)Zn_6n2I2`5L0vfj3M} zK00&U>9#DIT+pwwO)}D8@iGMcN_=y@UH{|hSA_xv1^p`MS3$oD`c>Y&MD{Cfa)N#p z^eYX6pkD?3DsSo)Ge`&E+vttk1?+IUB-kluSEUBA?e0S1ZeR{@k5%fN$_aihqCdMx z=^@PHsm9@r^PVirS;9$O+7F=pAn;ed))5#UkaF##Z4#heWTa z82oJr|4*az4DhULYMZKa?Q@9cyQtIDVYz(XOEMrxA?Q~@zcQnQ>buLExYZvt-tZwq*`Y?k`tyo=~P6A_KiC>%18+uf#If%L!+ zt0rwrgrTNpD_2k(tg#Dt$fv+(z`wpw$D%p_s>VXVKx1goTKzWIN*XJ2d&xg2yXOz7 z#9h|jp|o2J7zPZtN({?drkAi1v6t|@jA9b>D;q~$QYuFFtDs-ynJeg5LBFyEMroQ@j5K)$ z{i<9B$NOd7@jmERY*uvYH>YB4HZ)Mid*?Lr#d^@M=ps35nmcQay>*$YF2aYCEmNxw zi|0TW>)KrXc(6+4A;64EyW%@91&#y05BvvkJn#bnKd_;{rjAHf3i?%fwf9S{8T2c225Q!{ePpQU ztf#RR^s52o0^XoczkGw-%~U7u+)+9&>EJe?;sW$Yggy`oz#tRhgJZ99qv;kGL`woo0ZRkR0Luc)3G%B>2%T~TL?c{O zYkRU^9aVLh8%fPtCpaF~qf_|lKo$|$$JE%8oM76XL z*pa@O3{0uy9c?sFsI^F{9P}&RCY{7InvVA_3i_4xN!{kWpkGDys}|OX&zMJoew8QB zCf+b>LseMEsS1i&q{V&=qIH3>zmwh>IdMY9IIrbb<1b(*}n-fJLg0xh8J zl`YYC`eheU4;Tk*2y6t57vwiK2W;B}(WWLMWQiWTnU}Pu)1Ps36t)1i1hxVu026_4 z0$T&y2>8E7_A7cLvR?)LDzaY%{VGr3LBC?X3HsH)4gD&zU&-)U>!)ql&@`Khw41i$ zW21|75+8MmUi8xr`D0sb+WettOLKCXl6Fcvr(F=WTJp3@Q~9W9@@l+$+Jk~l-zw~t z_EtgOVY>B8)6(>`ueC8hY-Uf3yQ?UZ^?o`4-LCx2`su)Q5C!>#xr>%!-SyK9$&}Gt zK4)nr50cTz&SZ)nQ%Zcn)k^L&@SK2hmlS6(O?pH5DUfyq!_&}DkrSZ96#_FKv$+Wf{qUC`V zfDyn~ffa#~z)HZ%0ybsZ0_uWr6-287s{yM6YY3zP4MEp9Yk8@gee~8rVKgwt-FEHg&CfOZ(AsGcPrI4cRw0M}3P*y-@{HZ$T}YK;1-FS3DTov5MwlyIKWw z%0EgMq;$r1uGp$$H=X1qu@CLiwXWP6d0V6Jwe7Kj0_p!gnJ<|F?Bq?vX7HeuotmDz zD|J)7PN8P}Z{71yGm-tuyC&#Yyt<-h`DK03uY!KX)DiS6EmTg~YBz9TT*v8Ly3Vr6 zlr-=Ca$SkbvA}w+po=MAcItR7Y+zzh_&QQA(5wRuSFiPCh$&l$+CazUYG9Ai^R!Hj zqi#cBBVfE~Vg7Khofh%cHl^XI z1^p`MSGK1Q`c=6Uj`T|dLBHxbpP<&!jQ~fi%BNOI34(rAxW}umGPD%$Ykd{;tA2T^ z4;#htQOEq$OHGBIU=Zo-;RH2BnboG`bgyr<8g};8UPT+AGbJw1@;ccX@&FWhjd6Fj zi$ziKb4(j2rt@fWK5&66=(wjX*+qyh1}-tVyd>G2U54m#6V*C(U0#(}BD%^&nho{) zgMMY*p}&DTjaeY*SGHP;7^Q>4Ck&aOUnwJNzg*pX`nimj5p7K`DM)vIO)&`C2|CPm=t#1zx6p;O(F){Ws26p87wd$h7jgrY%9@M14c`1Zq6W}(xw5I*{j}oU z*wmqXL^i+Z-rLSlN(G-kV4Kr(H>CYWz<7HI=^E^Z>oQwEV^ivaer25#^s52o&%7&S zztuz#*{^s%f_|llOExZa-%!P>3i?&P*66hT?nG0s-k7Cu!(SR$23QtY4p?504b>g) zuts>PUMJh-iYSZ(RsvQAMhVatAKWJUM%_*3`Jk^V+Ozv`FU z(9IT!D0Lu z_ykx0d@9KM|GK$diO@sj+s|EGtM(-IW>1Emfs3liAYd@Cupl>XiPTyS@sixhG%*jY zN;O^bm%~sW4lE8V;g#AVs&Yvy71|lv8AO4Q%yU5QHfC^=Iocu?bbG!f3i=hh=Ad8w z+t9D-k^L&@S3$oL$F85QOV_6xSUF^+vUy!G=_S7@-JEVgE>|uQ;%-g1rQ6dTX?D6Z z-Gx{$yEtrf(ml+5vJtAu-1O&kZ@MqtZ}nOo(gW#13Nk6UGjChBrATyvs_IA5qq&+D zEj^x|Nb^ivKFR6H^i+B}J%d2mKm9n~^h+3p@Yfg4_a~|G^I4BL`FxPY%tAZ#YW&KV z(#z=;$+45E_*!~h1=xRng~BSC-b!z$cXH!QLVS;p3gT%$w^rzPrw`JH>7(><`Xnt# zpQg{!ztZRB0O%SES>6;yC&dkX5Td~*Dhfqu@0W`p8Uic|3?ztS)W`V}uj(654i74)m1UuiiG`c=@cbdM$vyvTmV&N{MRMfR)6el=t*y$U(L z-x^LwQd~YA{epf~&j#pi)hp$8Ro5_m=HqlnftJf}QMZHD)it50+jc}W+0_*dCHq*5 znvFN}&L$RB81C_|Xif!o19k`Y0QLm-0`>;>0j3G~UioO-ExrOnyB|cCtatl+y^iQA z9pEJy2F$@zJZ86A^qe}N%y~L(A7YC5NvPTXQmLE?9P08WrV+kZF(~z)JDj>BfFoT& z4>t3J{)aLS98KN#fMZ-i>Fi{TKh8?Bp6I-;=gGVPtL}I-f8d&mT;xWAhGnM1tf4Rc zF-j)_CjmbJP6kd9=vnebci+-Rw_#4E@()#apN7&bS5n|4?}0ql&!Dbvb#U<27iYO< z(654iWiMOMuY!J6cHk3qfuLWp64W}fSC@Mm2}NdQtqV-T?Vw*Zs_a|JxsVr4Es0uJ zf_}wyh0?R;gyLBHykt2)y_Q7Y6kLBF!sQ+`6~jS0|ECRzs()YM)o<$bQM z2H|vVi_&(k)aa6qY!aex0XvwS$RB#%j;4O$Rri0SNLB9(6)lCeOn}J(^ zKLSC&3i?$=Q7NjeGJ6nakf2|cJ;)d1oVL>}svKxdIe(PnsoNOX1lSb#x`3{eAC2#^ z3$yuPEYhN|1xj01N~GQ`Cm@<=B4QV6^55DOwDq%9Nb&vr7?Y`^LBFzI)|Rd!TnGJ1 z;VKwOmjagomsg{xP4b&75nbgXk*#cC1^vo;1cR?$&qwK`$Er?>>{pTfD$nM6T`W9n z(66{^kqc>F<2ppk`8I@#9f8Tf6v3H8aMjd5UkS}>QBxG1Y`)OqX=|f0@@oB?O0(U7 z-32t!>Y2}61V_?0>}6uz&2TNX51P|}>A=2LsW#%>mir@0zyUxB90(i)91I*H;7b%X z$aXnes?~BPb%%PLzTZtMJrP98!>NljSdj)R(qOTT)f@2+Z^XOywjk1;^?iSLf`?^1 zb|x{KC*?TqSK(Dy4|(*<;4=zR*ebxP&IRj=*(9@^l}L?jR%6{=sDsx+b8Xiwnnb!7 zjc5$8E-<#LZ23KNw}v6=Yt(IEb=aKstO8LTXaG&11+)d49m%q+mR&2!8b-jQab8kX zwLEhM4-0CB{$TsibJKw7z`j*KHHjs%KcWO20F+jVjnD>#jMQ#vY!O-H5R_)Pk_gTc z%|vvliHJ(CKgD;vqyv!eLS}pCL88y{n2Sq8k`o^pI6JO z*d1vI9~Gue*`J1{#nP}eJT0DTaS}rZ0R!Acl5?YK!%vdpvR6)KZ z&^uO6qtYsA)wEh#J*|<}OlzgJ(>iH%8k5#dW7B$ReN@}ZERfgzUI7cH#ZES!rEzGq6!WW}HcI2u#%U9DwDroPu3qoe^@BId?KuCX&C?cXON!!4 z>Zud>sK74OyQBFkw+|jx@UVi1WtSO|221l}@UVi1rC|^}tl(kg{YhJ-&whCuy>Yuh zn+CC1$%-($Dm4^hqPz=*yMZ~tJyyvcOR94b{nf`{chH3cK; zm#?Z2NI z#41Iy^w>;A!x#azx}r4YjixT0^oRc(?E&(8FBbv^x(B>?gxdZMMzk=nh{=i7lv|4< zNiy4^)GcOp8sl&chI@(Yqx`$&8l(T>SI}G%h%{Ki!^#6tQ7rwkGk91W9w1$nC-RD% zWbcrO1;N9zSy188)H%PUbAIQY6Fe-1_hW^SpRd;JdGyWSyl+}EBlOFs5It=oU5a9S zcoxy$f#-nvRb?R)MfrSHYE&1_ZI=EQ(R>Mb*%WlI+|>@^RV!hjw3)spR{&dDx|lZJ zq{&;RgkOM~yo2an;631d;Ge(;g1p)V533v{wuSnl=yhcZ4jvW(ALUb7ZUG5pOYfWD zVQKF+!#hKM8G21;(m#iqsHW|iIW@?6M0UQzU9;V&LPxaOG#*8h?|Ks@A*n2T3N^~h z*vyX3$D(u`@O|Jvfa8H506zpy5YRyWk^YD}d%hE?JIU)>9g8-q{A)zCIEA`Xtxgd= zJf=sh#Vm0eb+dp-gQZRg9+o=cc^fJ^4r$XEX|QaC(9!S zz&^k<0n@XX%6X%v56V+n?&o3|0`y9yFO@U}m$W+&I0!h{E9Ew))nta3lzqUwI~7|g zk3(qmdemVw`3`V6a0GCqfZq^2EOo|3^vK0P@UYYg_t6vg+W;Y=m`*bfSV_ahGOCJB zNshFK(0thHf`?@edWz|xmwADASTlH7d7cR#mfn;}PPF*{=3)8nJ?K}uG||E6_^RVN zggyG9O63VAQurU7w|?vjTKIGjJIU+h3Zc4_Q9lJZwbE+2cZgQZY|O`IqJ?snx9iFj zs&w@I?iEm`MHU;2gW1pY&6dS&UJYk_k;3$L>B-T0vCB@v!+vBc?qIR zfy;o)fh&M3fvW@>333$?hrGNR(KWy?fnNc?27UwlR^X$?<{|wob;Y&RT?bqb+~8Vr zjZnAV=%o%<88nv7)7@rthBaeW8&{TFX?q)RJ8%au8@N+ozmR*XyAjO+?g9P;%oSt} zIWFfX>dr#egZoU39ZLVTzo7X5@F4J4;342)!K~5cBYb`ocuc@A6~EqIj&9!K%%kpa zRb2-n#Zy+2ryYOHXHa<76%;W_Q}lC)=DSD%0?ZLlXJ0d#)$)DJ3n;zlN^SByl`kWD z#Y8$iGd^EK^g8f{$)OP0HBnc4H2&W~zoHii!ezr#ubvGxrB1P)l4-=Y!$H5wUDXur zwqI`Md?AJO&>Ob7l{6!WUc`H#byec6APr3bCYk~vV>K?fMzjsEt;tDruOYlWqDdwa zAIPJWDbkSUv2VLrZ-n0b$!Jaic5=CY7WMPB)xB_Mq{e z)>wC@mUHIchkn%#`c=@cf_@eBtDs*&LWne2dK0v&eZ%P&a@X>$vs*?)*(LDAR&>?` zU?T8MQ-_tJ<#!uI+nT7>!h+6HE(aYwcoKEr@;WhRZJBR$Ft_YT-DI!Ren6Ypoe=Hp zBJHWP@!b{CRA4t?cdt~;dF=@H^pdWIq`J42po8nHr=dO_*caH(E5&%%cPA_9e@`fn z5`~~&(F>6VE7D*E{fd)F_A7K=ijER?118T!O@~XvSy{&Fm;^QVEQe@$UdAfwIZsBclJH!LrQa!GJeKY_Z5t}cUwtq-Dk_-VRh?xcjp)^FL) z6ngbrKI;6nv__&qyhWf@&i~?=2{w8txB=8jQH1G`YEbw>WIbgmZ z&vvxZ2h7iAH`7j1_L~<_deM}alzn?D)+5^TV#6@>DoU>buLExYZvt-tZwq*`rd-V$ z?;?87L}C}(1)%nUHuY#O!G-?As!7}2%+=Iv5pkLW3NRe9eJjubt4HQAY!jDIzWq|wW>taD`#XtxggG{8!-Lj=}M{nzl z0$tfDQXaw5UewzvgPGM!s`X+R4;cnL<_q>fmrJIe28)sYhhy&e7jt6EC$|$`pW7(62P){@b%(b%K5s^sAs>X>#wU>(ce=vReY$Nl^q*{@`R2>R946*sYo z4JPPUT!ia>921igRm$7?5$4WEt(O!IKIm79{$n>-@))pNs-Rz)UE0G8DfEcDsEAu; zer2NW$me2RXLrb<#rVVOL2XpmcX5+sndJuX9cnI8<|!F&>xdda)8)#hW`3Yed5rpC zl|wC~R%T$oJ8X+;f}K^Nk@VaRX}=LL-X211Tq976OQ@f*DRo~5f_|lo-L?nZR#fxc z!$H5&$mrY9(bVXj67;JUfeG&5wV4gv3ETzT4a^bnR?04wX99W95o~R)i3{C)=yvyB zH17lM2mWG}#JX0rhzG62+iLy^ntruXKaA!ht|^hd{PG*n(;uhq31FTn6pA&jrR+&W zPq|3n>~m9tfbq||xUC#IiWQIMd?4so$}sHS`9Z&`dz21cJ!zD*ot{w0-W1udbOX_5 zwGR4KO^&{7Jc52@uS=n%7@D$wr`M(YJ#Z~>9dJEx1MmmnM&KskX5bbm|$I%<0$=vV55pkL()JhETqZctPw z&9;&KN-KG%Fy0O6h|FF?th#>r5mU#!Uy1>|~vZXKp?3ubX+#|n6-3C@i=q5d@KvV}BKoe*I zZ2>LYqNC~LVIVHP z=vP6%3i_2_p+HhjZ>6`>JDk2nQdaRjJ~q0R?^3~EL>o&Vqz}_a>ErZCT97_XpQV4L z&&vV$zb|Ai@p4hty?Z$b(O?tlDxT0|iy#^TED8(-76XO>!-2&Ge5Z0R**T?5M+%edD3QjNl(x|>o6-p zM6_Lxbo7`bT&xf>+8P~IJ%DfldJ?RA<0E!*X3Aq!Umgn_=bHLez5$ctV744Y_N&N# zHK2Uh$4Ahwf_@eBtDs*6{YuMg(654i74)m1UzL&ls$cHz{E?tv$#C8;Pw?&t`c=@c zY$%Y^CcCf){mME-IR@LhGyg=TaslwE%Y%N^=!%+Cu4#k?aj87;qOzda2nzaDzAS{( zwJj8m?YyTNU9!haLi8F@lt1&XAmezy zJcCXP`c*YNDobo9=vT6udj^_D+tV2I=#~6Zi4V{(U$b6QxIMW9@CGaCnQZ27dS}Xi zPR8-K8DQ@K@4C9E1m+ChZ72XckCUsNhT;b(eF%I6d<=X7EC48r`jusYkkh?w2!npb^q~_4p`@R#-j=2!yE3aNlt8}!2wg9#SwgM&q6M=66TLaq&7~Mg?qBo8Jjs%VZf_|09M$oTvHw68v zd|z(`vqjLa8n#Jl5bm8Gk-xYd)s$DuminMy*{a+uEZ`LZS;X(!3Z~KoV4^XY>LLc{ zaJx04ZGde}PRJIS#@U*ZOta5IR)6s8tjrX+1;$~Z_84}|Bd(f|XLB9(6RnV`3eiihqpkJ{m z3HlXxVvL0YfrEg91=crmS1)H+NqYmX;bx+6C~#P%)mAPZ)Vo{`lt)l^Byf}~C|smA z4o4&U9&ikBEN~p~eL?=VdPB{Rw~`q67Qs^c8Da~afaZ^Y9|I=>CkfOLPN7coCnGw= zM6yHKO>M2FRKxx9r!MZ+*rv=v^JgX^y`FYlXCMmtl^N%Pe#K}A`c=@c6gQTO+{ z+DW-#S+EuMSXrwz#}Q#yzhygDY}JXKHOWi5zPC%)dRLPjQ>nh!B5x`Lr@SL3^CeS& zoxF+cG=6KEeIjrY}!)*;3_g>(67WR(?R5LA4Kg&;f6~R8I?!Tf8X`~ zYcwhnnC^yhM>d;;sXP{?$s*26Y2Tkm1c_MWud7ZLmn8CHv z#HxD=b*EZgQ5j?9B%_GWXAUB2r~Z|vp)?B!9+o=cW_scl;E%wq0_$~;h!s36*ipg5 zVo-G2eu<)ZaJmRt3Wxutfn|VYf#rbZ1$hv4cw$yhNP)^+np?Hp^}f)pnw?(ck*4uAlhJah*U2Tr zPJgwY97D>(sS6&~fbs%5;zHme@2TKn`35%9VEKp$9#-(Mbbyl+vU#_PvZO_RGp9f4 zD5#32NsC4TxvZi+Gq;Be^acHy@^Q)gWO5@YU zX%lqhS)SKx#e-LzkhEEDhckKFJZ+J-q}Xa{ZYiJhLQD99g6}<)&-nG3>w-7QXj`lhQR8if!RbAU>UwNndp`vAH zQAO*rV1}X^Ikc8yj_WNtgUYKZ4HP)<5Vg)tVGS4 ze%yF3=|p3cWGxSN`66zzfAD!Rcv$%N2M>!u6g;fpVbv86uzZ2h5Iig$S0W8o@UV1B zBBxc}7epE?y%Z-HVXbJ0@8;c-9Wx-aodo;@I2kwvI8{LJHIy?oDW<8Tqw|27Cln1mlu1f)g>~^ zr6^nmTn=2}mDV)zt?}^}H)yaGFpmj&^u!4t0`lV6EuPAz5xw;1rOID$7L#}mO zz&+X0`=;5#RU~*=*@Pv(4B5P9(m#h<|J3T9S&RH$I*9yR@vwq^g(bAt(#miXf775} zsS}>}fvpU6+DpD*C6RH=bu8#t;xA%A5BgQvgNHND=@yEuZf-2KW=+?YL>T12zOU0>%q?Y`0G2>`f4DY9bwSf__DR90VK; z1pP|B@9u<~+&{XV9WCn1^uci)@R;5>1EUI=|1nHNP`t= zu#~WgNm!92JG&YvTEv9YELhT zXeQOYtt9g&Up)==>A=3geqPzi-<_;PNI!jT(68vBpkD?3D(F|1`baEUC?!F^3i?&h zugXY+#g-`2UVP*%fCM>sbEIcClG>pkDl*CtV9%2V4)_0Q^BHx7dcowf zpNqxx)I^rPRMJFN((XXuAmCuHRMc{rwPtup-WPe)70oXuw;trk!)Wpy;Bepw;79?# zL1BK|%#1~=V<{7rwodWYsZtglee*GyE+X-m?2>3B@B5;yG8g=c&wG}@Z(J3Y>diAEe05l7kRDbGX zo%m$HnuX@iOr#?=X-LmN6!fd0Uj_Xt=vT_fm}efv`jee)T$K+)FgbQBRPPX>dROYE zdYz1pcH1cma{f7y{VM2J8dO2QitJZg2mLDOS3$oD`c=@cv||eTRnV`3eiig9oeP70 z74)m1Uzr^@=vVJSx_Tc7`c=7-aV}&&i|kkB*I`=({Yoavw!1?rs(B9N9rP=WjJ~}q z;u3hL^a>e(gMM`fugz@WPT(%!ZeWf8i?{4j*=Sv_cY3mT&oyzODMy>Ld(pfPxF7h7 zRlLNlZc*jk-ph% z@a+b9{+@MlTO8be`5c--zZy^ug-o!RlL>-;Rd?pPuAVeX+SV^cA$wEMuXF>^F4PY} zzp8om8qHsRU)XMFmH0`;$!RLVS$PU?)~UdMR>O$gW#wszX1S={VSYRv(HTG=I1@Na zpoz68Ac`@=ingH6KbyL9fOCQKfb)S1fD3_(fQx}kfJ=ePfXf9ush<5cu0(W|i!>G6 z1grZ0`>=+7(66lDf_~L(;dK8QBj;bh=RnY}f_`OQ51p=j8NLlAV@Dw9SLOt# zuokvC)`y;UyvI93MSAKpx@$@FV^MmfuY!IR^sAs> z!8i%}RnV_=WR2`sLBAr5V&1|lCL-tT+vt+p1)PhN=1rp6RjJX^+2<}4?gr)n_gH03 zH&jxci|EfTsI=9ufRjV!@wiJqrhVVTDCfv;GaM= z&qa0dPk3t4E2;#lZ74BMqx1~$tZOPtqs-LLA)4=^PLqgx&wEJ*1S!0L!iz5IcKl=` z7NPxknHP+oqW^_cX$m4xzD~0@fH#4+fVY8nfOiGC4|*+q#rs}r7KJPvAE5AIrBK)Z zqWl=qC%^*WQ{XcJ|Ib z^1fk+hP$Z7{bK%^k^L&@S3$qhgrQe0=vPeMk^L&NUj_Xt=vP6%3i_3HsAmnbZDv>7 z(SG?0E7clZ@z3+_vqn&ib0sd%1J1A1TkL-?boHX!l(GC`FUi3mv(4pxSZHT@8SO3y zt^lqCt`hKg-6U$ueKn$MfM1$iE#<9I{@P2*X06}$+p4ZhRKee)eyxiN9Vq(c^@wf& z{s7zv+yvYV+yeX&xD~h!xE%=kRnV`3eiig9`5FZMD(F{1zcK??(654iC2oVZS|ec@ z1pTVj!6d#Zoe}gaqoD--N)Z6PD|CIKL&_NpkDy;w!=u-<%a%^7kO4O6S9WbifJ;ul zJ$fZy)99ld7OmHG-&4=z1%+`dv?+blJ5!tn9dh4hfV~5}>*|WLW*29Qb?N8sI`Jt# zKk=dS>8t7?Z6$tY~W4-uc+os?d9%9G{;1ulaVR% zPl)EaR=3WM?_Nar0r$JSne$9OU?qL6^0e{LqDAE4htPc3>Iiu$`{tvF9&`1eUj_Zj z#;e$h=51eV;tdn@t2`ZujHAT5Gu2(TzH z6j%%x1`G!l7ufnLFaG>Hn#xJx60>fK5uqL4(r7Q^+Hy3~5r4U=)TvpXj9Q0t`v^3@ z3aki>G%XSZsd8mRqky1a1^r4#)}UYUGDP;PpkD?3D(F{{{mRb$k^M?u-a)^*rebCW z{VM2JLB9(6RnV`3ekIF8(69cT=~rhCz&U> z&z2_&;V|B#?tS2&rclU1P>=i&(MQ0?z$aFzA5@s}t7wSx$MfnfOB+kzMBSTyj`jf3 zkt_rZbgoFPMMm4fh!zGGF*$B<_PlzVWVS=8Tg>VReIY~Na4!)^B>(Pu@UVi1rNI_{cYUsnJxvj`C)n zbPMoD;8x%^;C6u?T6DSa;DfTPs6*~FF_W6+xVzDuy?<`vY`(vtsxy2;Qi`v}i|)Rg3ys1Q*6Fg?=!yPNdl zJe2i_X9qQ3*r0rRU$;t`e4SEYuM1n4UW7$xzGXubrzYzoRd zLmHG1oJgneh-2|cMX5bd!kHD=0CTA^0)uAJJSoON6qG<#V%XSWJ!mBI=NnvSV8DLpp zIbeA~9z-1uv?IJEcSf!EE21zGSP57e7$rbo8xk9Ijkw+7>1Uqyk`Byva?ydyZgxdCvjba^1L@9ZQ2nDC zRN^P(POY`%_FcX}-HX6Wz{|iZz^lM(!0W&p0%o~Zm!tAqh~5U?F}cpbkRIOiQqif| z(XmtL$X|Y7V(}uXAK122AJeLN!s#rj=PvN}!NandA$V9CVw0TrQnbx#D-%=ju%P$^ z539V4ez+XC0tg<~Lv+K#f?1=>NBI0G@R%TPd}RS;@-Mo*noMi+sQX)0m#N85SxF&7 z$Z7Tr3eUQNER~v~pF=d?MT#zNCcs9|11rj@NW0({Pv09D;gN@fghkr>LUi_ejWGv-+B1PRkXsPLoC@lIuf1 z=vP6%8c_bgheXh?f_@eBD<;YJfqw!Y_`6Z`pd)|uMTyADpP;Y+_|)ZkgEBp>Xe#lv zO~?(BlMMKhnIMz>K*$P%OeAkb;};ep13UFiyt&*~E|=0?)Z2VJNo4gRjE!8g&k3t3{0uy6%(V@;#e86I0y*QwER9m#VeAx(0N zdaXv-j}>^@2x~?l1{>9)tLdCIlDd_Em4Q*FrEu_y{=}?ZS5&Hgxf*q=18YMmfugV7)2@e8)1%iI1d>WX%KB6~120j560G|r-bX)Hj3$4-O z;^T7{*E()gQz$C!We37-83YUl78c~jEp1QAAzms-@KFw}N=opd6$bU;z~aCXUKwey z)EPm)I(3MJMH`b>er;hqNEk6OHNG(IYX7kZBWF(=Iocd3X)9w-+S(`l8_=&hLB9(6 zRnV`3e&uJXNP{(?TovxgYQX9O+lRC@)vswK1t1}J>e^nXfF_#iM|+)2ZK_+hs&flT zO*DG5m^KI?%IeYcNX4?N5PG=g?RD4a0jGN8`D(aWHWxeH>Ikb%O}i44lC11j-`2o1 zI8LQL>QK?E3>U6pe1q`OeK8<+#!W0eGzmFiqXe|Ax=B|8-JisB7dZ@UNgRd88pKY;dw zz+ZuffQNxcfJcGH1bL^~AyV-Zh~~LSLF>$>)hqm*q?-kq^q)rQ8Q@vh)HYSepyv?H zcTuN_55ejCQn zUjsG}=sDaVNuxki2O2;VXaQ{jU#AndMK_kg)w)2JP5J@jtiIOJf3#n2M3eEr#@mhK-2BbFq~I@Fjy6Yqi%PxWSBN?@X&_IaZlbFz9*lo;mA_m8oh*Q^qG9W| zZ0CxK;;rXS@{)#sHvH;;`eo3W{O2laIVJOCzGMoplQ&Tu5nBiA*(YLG>ZW>~5(oI- zx@TiS;T!cw&wsR>jB_uv_crZ%(erm(9za@~r<+)ZMaIc~l~TRumw(lVF0MN~vL;GP zzdVpf9t0c=90JS`WQ`^xWu})Dj#_`s!>pwLpW>nL*OQJObA*c(v{JLmQPl%lo%|o- z#xehlqSMoVzdT0u<*~qVuBl(;yMmx!F)v?D=LG#K=vTz9w|#s~SHucO$iVm%_zd`$ zz~%>e-<1Q%IkFHi(9)F9TJPInD>2jhY>=~~45`Fj7U!X~TMQTm47W-GA89^W!b(an zY_EN-*471VxfGg9SDN|6uq>kGfaQS|tg=uDdz%;)vP-{oMe0TZE17~WzS!uDa&^sw zc24YSqR~AV;-Fsz{VM2JdP#zQ74)mfeihlTf_|mFO=Q3Nl02e=YGl9SWJ|2h$bMx5 zgEN4+r$zQFJ1oiTPiKmtUtzwH@kqw7)t!aV=qeaUfq!xJ)p zxy*JgzdLN3VSa(&dDyR3MQBRT&$@^ z$FuaMlBVENrSd@FAmCuHRI*#`7G`*-Hxrq|_A5cZ(tV_Dvx0sl$EfmAM%QCLOmtPM z1H%)D=D8@cUn#pi9`r%KTF1!(y5rVO_!v56U0^J*96D>a>(LyWAXw zEr2b7t$+!@MBtmi*1$FbCf8PnR@))k9*FE$>V%+Q<*^|mu7=zt42w&F$bJ>{E00~# zCH_#}oCW>r3*Tq+y^=d5&JHkoRsmLZT2EK`q-2e=5+UicQxpd>P5*15xwdN-P4Wwm zMl=Rk7Z_Vrwk*yJ)@(%`hPUP*D+ zWsyxo_^9iFqMwGQ#nP}eJT0DTaS}rZ0R!AeHsPmLO{nCnQB=5BR zb$b1@avGIZNvo#S(&}lAv}Rf>t)13MqtlqQZW^1`OY5WBu6aBMc?sA1sm8OqHJ#2< zJvCAjl`amSshv8hn|f&+8m*oNf7&RGPaCIA&{52jd@R)Iu&y7xS#HO%FKwQ-NLy0W zIZ{uZz(=LiuHGHXFGyH2J#ZT;n@u@)rtSDBi?^hc_^4|mJ$Hxvu`SQq{Gs3rCZ{QB zr?hk01(B@K&3>B7N4=J6ynEV%LcP$tmi9_}t5Ed1MYo@(rRiy3Yh%8e>TIJy=*Y}Z zJpkQqi=S{{I*5Y81h|Vo4k_p$$8?(WTz9(08M(#D{8k z6pyH>Kl>@@SNbFO({<_kbORlv9PMtoXloafZb~<&TaathtiQ;u>9%xxx+Bd_cc!}# zYt~jL&Pn&EpuM)t8)b~W5n!0U9YILy0?MU5Zuj{n&_1_86&MuMxP-oU% z5lsbl19taH1(nh%drvRvHIeGxRuUzSubzhbbYNd#Kd;o5OW&QW#AL6pjqF$SP|&aP z*e7O?cI838GOJIwqiq&5fi^t0#AxSbOPXGBTQ_U$dCJ!rL~j6Z0&f9t1MdLu3VdeK zW&QhJ(hZ7EIv=3$VWm)qJMuB2Pk;r$r@&_dJp$5+UfRzQ4Z!<-Az&ad2pB9tO~)l; zo78KV&4y67C@|C%YBJtRJ`B-t7uAA(74)m1UsbneI)|_<|G?i49jx@8pI{}u^X^xn zn9>rT$a{1W@Dt!<;1u9g0dIaoT(y4rQ$(k^NX|Wa*MElSbQ9@pXh{f)Mi<)Inbe)- z>e@hP(f{mg*(lQ0w)1K0Zs-^5wIx8)zy4U8(p`L%i5*|>@<{Sxsoh*Znw#osb^5vx4K#_`>6!| zD(F{1zY6+Q(62Nz2mLDOSN-xzbwU~0uPi3Lb{V9*c`)c#k^PEoXIExOIeR!asi$JU zT(x2<1^r4h$Cln3@)J_uOn{g%(L~&;+dZfPkNB>?g}r85l(uuFMi=_RBt+i=b}+fZ z_G6yj(Y56Jt-r$*6m|l326h2<6>!*4Xn#F=H!Iadag+WYDC`OB1?+8=ggw%cV;Z9A zz`nqK!2W{#XOHYxZYFF6{mRBf(66534Ve!F{Yuf6oJl!0(gg zQ`?j)5nbgX-MQNKCg@kzBN%+u-9f+VkxFlY50hpKqxolyoPPnI13|x98^%e{uN13R zW98d)#*V;bV2XfAM;>zK-K6-D<`tuik>)7eXcKIHD%!gNyL%J1sa(F`@vR5%WnyAK zs{kjeAM~rBUj_XN2b`c^$r2FstDs+L{R{e)&WF%B4gwA~ znnz7sM(sLgSc#0?+H1^2;ZWePN~^8oDEqr^yDNnws5=rk$`!<0Q5PSL=zG91z_Gw_ z!1o0-S8yLSKi*0TDQOWb$w#2pC!qNw;K#s;z)1o&N8*|2aC$PLQ%qF!JWwWNWo?3f z>SCR|?AVI&vcoo^NBKuXo=Fx%>*{|}t z6Z9*k9W?v2f=?SWRber-!2ZrTT#Dadb{>Tl$vjnED!EZiAsDnS-vGDi55SGyM32-6 zySaKmrUm>Fg84a!pYk3nvR?)L%GozTzY6-5ChwqM1^p`MS3$oD`jzZc zLB9(6RnV`@j#~u%3L4(~z(0YYUvc~n`jv*l*P&c&27E(cwg#Eq%PkNE{i?Dx$oewF z`bXRYqWRCHe-8C7lT{+yY2cOVAab~C>i(jN^vS)|Q8f9kH&N~pGwmpHtA$5Y>{%I- zjz#G>;QPRT0LKGA0DcIZAjp5Ho+uG~P{=~HJdwJSysp);AfrmVMj(q*s5{l_ibiC= zQg7Tqm;AxIE3#kF8$rKPBtRVKgMOu6uq86+S5vFL5an3sD#phiCXzb>xhjKxRrBmM z4G|9ViWKxKMT{(e$5{D2a4m2ha6NDX@CV>V;3nW^;1&TZy0Vs8M`|6H|N3pz-45IV z%m(fh@QNz#yS5y6Bbs9(U6SCT@+U-dT}wg9rFAc&`+)mh-pm=1AFvWZn3Y6_oZ-2eFg9PLXI;cQWdy0H;=3Ex+Yg z$kxnfBQc03#97|1E4qg$zBD-l=zk%%sDYY4@f-ZPi50kzz^`Ycc@A){%iCS%`1286 z09*(J{i@3@=|1nHdeE=l_pay^LBFzDu^03!O?^$#Zk2!0Sx+@(yHNf`D+T>3Z-Fg+ z5ebU41wKSwQ_k@I(ZVXxOhkv8s3vbnb>Mfrr2Vr;PtaVRM_nyv(L9PK-xbU{b&+iq zwN+-h$bLnVsmOjMXVRjftXRjU<2Zq}>KbC{Khp6O8eP(P{g97RQii1;r5~pgDJt-< zk|_Noot#cdr>6guh>Tild0JL(@sOXT(<#WtsE72^nYo75ApM+=1wpX*ps$g_Iq6&# z*!YMMb$+@atKgi7RLRSf4(;M}358xYwiTYtj%_{WlypV9GF|1(qV518WHKZY5{vTgyw`Y=&6}h0(wmm$y3Pn;45|Jz#y{ zYrqBqJ%{Y6(kKwsfdWwOO8d=rK3Diw=b%lxWdzFU59w1M@F zYEL`d+=ETGwCTP_cD&$W*@%fWSi!^Umyg?Pqm!HtSG;^hm*j$fGhY=1tPB5gf3H_iLzNEjlHL$A zz-S?@)<8v&&+li4`}adkF?d+&i{N1e4=Z?B!NUq3md=I2!wMc&@UZfhOYVhcg@`m* z!Nby4d?n|j1P@D{5j?DliqrP6^zyIs6P7$cIBMw-Mzp-(VR7v2Wq+5SL)-ZUa5iub zaIOFih0oJb`Fund02cxmRh2baZp%v$T?$+VTyB+QO}5jnEKa)qxQe>}vN~e@Ygcnk zRjLv0`Bzm*hRlg?5>aGK>2X1gJ%aU`WmvrUmGil|;!-+P}tx5o?Q`N1s zy$!e>xC59C+$peMSl7aTH=;SfJ;0xUxq_^rn^HS)1rO_8>l2Q%I-~{<%N#=#qQ;h5 zxpPGttl(ko4<#xA2LPpjiA2N1y_S0a=XqF-R`9UoWh(AY@USw)DtK6IGCEB^6^Xkg ze%4Lt=5z~kMT6H+xi#IEZclfl+3C)77h)M(#YLNw?&1Aazz;QsZcTSI|C(=CAhP(D;dMZ7goRrO=Z)#w%6%It&QktuPdMrmg`n^ZD+w2q)f_xmzIv@^nb5qe?QoV zYEkp{4Y-I|v4>}O!^N__omr5;2m?@m|v4u`P(~ z4z|c>^79XRvW*wMDR@}w!$^b0ND?(#qL(dEDuz?D{6lNWU!jwHO6*45NqV|BPlo6$_SWcne$ zrtUZ1PN~QA3jEGXV$0}dxfX@%fa`%9s!F|q{qjaD!Aa2x?`9NkF;S$!%4<{bufz;Ujrl#9MA&_tY{tJqJvR``L}w_2K}%M+{= zX|N&ERzex+W>_kBUX`k8kHA#eKS84QoUi{y7} z_d!9wY85iF-9hKf2JQsz0`3Op2pCR^x@Yf1RnF3x+GEY5;=qVTJo6XeJZjc7x zSr^Ly74)kic<2ZHie9J#LBHCCZrBxwG+4*08}bs#0lN(vbxPaQS1$x_#O~xu!4S7{)Lh70PrC2SKuMw zVZp4?b1_sbX-#tTsQX)0moq~?WhEU|Im|qR!n3ZRt8|^vo zMNJQ5DfjIvrge{*>;;rwbR`9w*5v#$qE}3$uq&i#dkxX+z#AqfrHMK2bmf6lx$@}1 z^$towzml7LU9k%Co{@08`oM|QHc3Ih%KZ^(u=J|@x6`lMkp?U1S4XGspea;y0+riYEXXC2kFD~QTjN2k`|;-(`V^l>GP5l9_2z6pP>m) zXb_^o&Sxm(CfF|*K{Nzd6c`FD1`Gp+1B(mz&Q{ApZOh|WIVoIXbRjV-v@uy4?PXkB z&ab-ES*|K|YUYS6??Y{nMxgmsU`1f0Y1NCI$9-i)qkvU_pkD?3O2Z)NSG){Czfw#@ z(oNq+Z`>}>JS6feUdgkoQVyPU7YcU+bAWrSQdy+AYo3ef&n~JdMNyv4Y8>A3?AkLf zE(xop{Q%kz0)GV_0v-k)0UiY&6XY4OL*Df#5Y2OuCPK4m^@@tY-zFo`(NN4|e%?!w28;Ve`Z?%V7$sy^i0oJOdSt(X_2wp&Xo#rsmE+e-Pf(I)@&8}Uwp$$ zjZ8z^!b>7t>GT=&tH^$p_u$F}ufZAgtDs*6{VM2JLBG<18}zH7Uj_Zjb_YSf3i_4o zhdN*c{fe_6PM6v*2mMNynq_G;6b+Bae&t;e^s8Ic6XhR)TdUzw1;SG7L5-TAU)i-; z+el^vGj&6bKFVRydW{s{*#%sw>o#;R#;uR; zzhu1n0HqIskARPXPk;r$r@&_drnYwB@k|vTN#8NRhyaT2NUX^76&}^)6U-X(1kBe#zZy^uzz2UJ zV4!>J2mPuXLw~Fbj0M&M))z3#G#eFh&DA5ly*IKGcRdRrzwAP6t)1i1hxVu026_40$T$?zpB-G z9d+2@^hVIHl;xL>xDdEVz&t1-uJ*f^Ad2i)LBC>UEG%ffsH~o9qi7O3<0Hn%$G|7R z0^m~tqe!P8W1%$^A+}$B?&4a<-3sgE3MmJYJ!lXx7+Bcy2-WH>&8p=PFDZPA+!Tja zB{`Oh;EVcjU~ymxudEd~B`#^DLXo3A0yOM2ewCKy$YHt|xc<+%%jex)Jz-%P)1$*=gd{^&F)4NePdAZuVNCrcW_M@48Z`e|rdEDcM; z)8c7~^p&(^S}HA_mPyN|<fdRil` znbt~cr*+ckG$yT^#-{bs`lz<$(aPJSgz}=8rWzl+HHC#v_0&jBRJu5PrgrM2ZtA6R zXta7AF+w&<(cc>ztZcG-bz8gS`AJ@WWT}|m}l8u<*3NAP;N!NqN4cy0?{-k&LgNhWd11UtmA4Y~}AxR?eC%(I0u;q=SbY4!&2Ch!*UHt-JcuE1v&ownZh zlH!DL--W`5l|r4f-^YkP0TuwC0-p((c9io+FYV`u2H^d^5HJuJ1Pm6S*4A|#KaUuY znr?1^p`MS2DH*{VM2JLBBEsSJ1D5 zeiig9nO)numDeF6=vQ`>>ID5t=JwNIugn4>`;|K3W_lv%S7xn{^PTpRFF3WSEAOQI z=F}B8Cx4LNbT&%_{R$$&QV&3J8B(|Zt9yN;!JYe>G+E0;@&F)@$~uTf17m=7fw2N6f7zY%Th~YQ zHDCjv1_b?zPOk<1N~6t;ltI4|Q`GVd>K3-@lb~PO^i&J_RZC8+#%l#20-~gZm4g?MY4h9YpKOuuT#pD^fGWcb;JrN7w}DKl-y$41Wk zGl`G#$QP|^hy1av={$cZ;CD?bN4Oz0%$) z6uqtp2WeWGp7ymi<`6757YmxBK?PIn0Cc-zF7(rZ=^zRU7-k7Gw9ZIjhGZfmC^cc4 z$%ABnGCNeOQ{`!G*trcxo3~WwHkyZc_?Vk#IO#(fyS3Mt3F+fd;IK-o{lD3J&*&?wtKAzb7EG+s*lWZV zcP}cjE7)Vi-s{S3d(^1JLV^-SArW<>v7n-$9L-~_s93O}SW(1i#6}#J*jsF9e6Qb{ z^Cln8`EWkGXFSOmlMmO}Yp!|Ud$azl&NZ(&bsVMfI$RDECsB7YFvJzKQfT9F3Zhei z(}2@~p}=nhJTB{!9v^0P7FZ7WF|a(a0ml7NA!EubcaRS>NTtOl$OtRawwc8Hj{*78y( zTVK{jp+B&W%avG7-@YEA^??n5p8^{Sm>#rkltvX%4X6VRpb4}De4PTG7^x)aSGKp7 z>v_ll<73U+mz(fkoAwmEhvYsQDj-l=%R~LU<3-TWkT>@MRTn1bYj0LU$t`zW&E}?&l zab9Y6un1g(!gyc;aIII0w5`gCR)S)s()B3Z;Gzm6(EcAmzoH$2ex=?K*{|e45cDgJ z2i;K-10v{G%niB(Ra=}WwpMWxaB|7p(zKpucbRUrkvfICQ-RZ5p-VQjVyKlWy6elv zR}xTayEF{VGh9=qGdp)R>!N}32ar`wUwRfwX9FXEbAWS!kpihzt5|>dQ18_3gRE^@ zz|KQyv@6MS=R3X}%ko0%dRC_nAK9;HkDy-#{VM2JLBG<>9Q3Q8Uj_XtA9Hm%=eE}x ze2eMUF|;{RK38@fx<<@Y5BU93moj69HAo>&t`c=@cf_`PEjZRC>0gM|3k=Aq&*{_0rg z!dAJ7E+_Un=3S*IMK3k)-O{r94V>J-bAQN$Urk&09uAsPUwzaEw z-HfHbjc(L;=8;`WCEXd^ z@SMqzdESRi(61Unzp^8Cy>wG+=zgFG`js8b+qw`begQ#eHz4R&<^(67XJ_pzdznlg z!l_YpY5v`wd=fV(o$PJh%kSOM%N=9`q|U#x!dT1*8o6m5gwo z&_O=6Heo}nt?K9AU4njP^mWeKbAu(DNmb*~2CO(f8fq&;%vl9k)d)Mx0vh+LTZx=t zMgY=*Obxsinm=*PY6H)w{)pBA)&I7xv&2STsx+OKuV1VGMr6PGx2IpV#1{MC=~rXs>m$c&{fjhM!Nby^ z78Nr6HVw-=iVnoGGx;dHg&1hROJ}9CDar*!M6PqvxoKn?m3}V~+%7$NURG}MlJnCA z6f^!_73O_xc^+$X--*mOl!Y1vhle3fOpPUF(msC2bq z$r~P>+q3|AA*NPUkDx+t#Gk`$+FXcseTEfOHIUcv$S9NJ?95R5DXU zIO`Rgz)Tqc{LJK4Z51`HHgm07Q@gHW3oq%qO7p~4sBc}W*UQvtWK}B$Qa8xeTQv`B zQL9@zYz0-4S9YF+>X6cQaz$-c_1;~)RCUs+2DN4J(ALu!LQ0rMCdI*g$?m`&{)kSr z?&g%8Blf0lAFtEC)%T~t!_wp%JS^`Q!Nbx;7+ZmvWrIW-tl(j3od_OQ-Y5qTOFqVm z3zSVX!NY1*h>md?e5K2Qu}0!jxFsBOuC$VfW{~*Dc}Wv&d1nA+c|6Ze0ImhD111XC z5a~)$+o$Uh-2nW_xe*H+=BY8E~;wq_KMpPO#m;k``fNxlBfPGT zD4%WJe?wOmIEIY!H;E^s+4>J&YRKypZN1R*St`S&rtS;8UNgOW@^x?m86$CVk=Myy zXH)>4oAt;gF0M4ncoHqVnJ(v%vA`9sps*YIzg&fA9B{SC3H665577h@RoXdk=XHoC zx=8U1_4}_cOAQ=a|Kuf|zqKyiIJd-Y^GzxhH=9V;LHf_}-<7G+TCiC!kL67c|C36^ z3hUsVUJ^H3zicvZx*NC$xEHt&m?Fq6PSiy{bgMMTgC^#3T#NC;XijxaWgykheiYF( z*V130GbWPqK6qHc!%_%00?Muc(_%#<8OVHAQCC{oOI;Ov#j0MaDK>yS zKdeMhP;DL8^pf1g%mya=w~_R^ZE36Hsi(>OO%H5w2V1P`Pbff&apx2!R>NTf7dM)E zQL&*)Ma4y(IwQY^s17t-F30w4AFC?xjeS+E>LJM$RnDB><&$o=uo|m+@5Vg82{6E3 z5^1n(t_dENhihtb@gHfhG;V{3#XK<^_!|&BET#%wW@?XD^fTIl=JeoU*>+6J6ed@r}9kUS4}v8Eaw2hzWkGzAwb6-NR`0Y`hKw)@&G9P1@T zqO-k)Ym>I5G76>uVO5^%D>_anAd(X~G6`g9?=cJpMd`cZUp`e+$3N@SCn>}heQvP(d}01ZUb%y zCb^bn$+^=@vP=5lEWLPS#Pif3ErL(q%d__ZQ-J${2Y?3!{Jk179mo!cXe#gs@F);G zEDsGWv#2&u!NamdeS}T6KBpj27R9+)3m%pRu#9zPqn0U9D`lj?Qf5YoZiN%w)J@D0 zP=_1afwNlliepeZ)|IrdN^~5e<4shlD_mKx_?4GrhxP4yNl~dN-DIyA!Xv*Hj2^Y% zj>N5Q{2zE&LB9(6RnV{4ZHTfZTGm}@a=JTjJ|G38d((YsO1eKikRD7AAr^a96tt=7 z5w;4Q8nm%#>9O>9dLlh(^)g(fr_*!_vK+ZHZ_6$e@oHA}b7^L-Ziohu{*qouFPb)# zwU^SY^m2Lyf%ZQ(uyxRI%SJ~T)Y5D!^(H<1M%E*cGao8&E%iau3BU5~^iKLaMJ0Px z@xAoE3fyV>6-v;rf_|kP@s`d}3HlX;oSqdgsX26z^j0XzrH1fCZ#zcD(F|X zy^uLC=vQ0?*x_CtC-T-h5VF=m#z9eLr@2{Yi9~& z&}~$rwDgK2dF4^S(ZDglu>zja&QB}!abD6JbgnzWN}`v^^F>Nntn`|bT&&wI%_>96 z7r0M6+rIqm3g-fm^)%HNrvpP>Q@_f0k$!6y^s7jNrT#I)`$y2PWL3egGKW#~Ef8t2 zf_^0`iss;;Uj_XNL!w3fk%vjpuQ)VKwb3Dm^g6LJ? zHIplc8Zqr=ms%aa(NV-H+Z45Pz<@VhTQoZDxZdUk@AxAk97y!8N~8Pdom(BJ>i1Fk z0QeC22>4il20nIq|5oMBviOX;&w+oKLbcx3maX^_(O1CNz&BP|QCt$+{VD8;Z%~!# zGjBBIb*0w+9_>DG2j&6hEeQfmA}P#|XaQhBlVc;a_vO%4#lqArVs+YR;^5uSOZo%Y zkyDpk`Y-+v&BcKwfF*&YfTaceKV<}+d%5Aiw8s0E^LqWg^!HqzM^>0CGIEHhBRbv| zD^s_M*J(>^p5OXW_BxSX^tv@rS`%2yHPsGg4wao&Z|P6nI>5TXdcgVu{l;2D*CV;@ zh4rp6=nQj{Z4Hp@~+K2${;g$~dyYdCFP~$(UTleID`0D28(>>tpn$ikK!6C?nK?r zWt|?#|4pq|s@s*iUjVxSgI!DK7yVuL@RI)e=Gv#^(CRsRqq&dO5dcS`pkH}&1pO-L zSCIyb3F33$AHWwrHgqSYN#(1#CFZSfP?!UJ>vD}Co3iCG;J!a~-CGxZjMc-^qqSmQ z-1g@)krpl)Me_{Xa0{p`tu|xnW?b3}`Lklq**YYt){8}XNk3pQS5Sytebo;UEe+^tXgL?@_RVkmf_@eBtGql%8Z3{6rF-+BUzIaQq`?aM6>Nir zfkoWAKIm69-#W>&MLUI-wM#YVS2k@Z6RBF|K)TF9z`;P!ukhP~?0$}QmrA=Km&#%! zjWY`Py~!2Jn>;4xAsX$XR-41?1&A&LdcYXqA^|%}@#6iWuEXZ_66!7mE(0zH#sXIW zR{~c7^ynIeLICEpQ?dLT=j9esj+)hkwmc(FRL zhJXD$Sbmz z6%;5+7N*w`&32J4vCPb*dny~7m3$xb zCQ5I)l7dZZ(R&Bc-%TWX25H*fL-aoIfyrfQGMhcI8?$W;S03#lf_@eBD_tu^8muM; z;(z-zScIwi-_u|P{R*!Mo%ho&d2d&fRXy#RKeiMOFMl8gUmBctPkW?2(_VuY)FJ86beKJ3zM9OQw$Iizr^qzFM7PuACmflM zqM(3!eo5NYf{>1tjEo)aUOJ8!RXsw#^vWDhBp1oAsm%2U)pw(;sb9|x;T1|fB@)gl z=~U$UrIMeXhEj;^SF}jbuha!Uqd&+epmau%Pf7YBeVM*WU#D-mGi?zTMAR2p2v`_c1XvX42P`JYeXwbM3i3F%^ky1lPEJ)~ z8*NOMM0+XMmKTkzDa(|lwi40nCDlqB$ARV0{4uaRu!3pTv}sZ0N{ChlRskaWRnV{0 z4UVKQ90dgZidG2vRnV`r5Omt^hNumXxgm-HVm=1)KX9)s_B_S=^qLQV4}p(>kAY8s zPX$c!+KtFm{<)WQP}Roy3lzRA6>2!WeU0cFU=Hvt@SPw}@!0|6dqjP3fu9GM7nl#2 zUx1oi8}kyT>}*6{?n~W5z`~{=_eJi57e&<1MHSpK^3OECLKkcKakmQm{fZ@dWGSnY z?*}oHmqGL+U|C=};K#u7zzV>Mz)Aw%uPvYs`l}#X6<7^e9auwD$*sv_7x_@Kazzf!@QmQ5sc5HJ}bOfF{rq@O4cbM)+m2ZCVrP4op8F z=vP6%I>Y*iwqxwAhI^0EiNgkkoSGy)o8B}6I0rZv7zvCL(6Q>`swtd1qVrrNCuxoK z^ATNOB01Z-N3tBWHA2Qvcaf{h?N+byxEvS@Tmf7upi_6V^VK*n$v0Ww zb`1*SfeFC1UMVYvDkoZra5^eokHQTuitJaB{YuA+pkHZ;$azTDa27yhzw(8)sqEav zj!+(UDw~GnfqCu|7OjT=I^HNF4&>1XiH?chwN4i)iR4qeCt5h5V99ybu7PjT9 zp||K;;MQreJprX(nUa=RV`#FN>76H2H^g6{tC4&LhTEp|{;AZR2AmEI1%3nk78nMc zA;=4TWWVy3&?ZrT*vNim&7rN8QiiFARFzoB?JHGT){5uoJu^*-v0zHN|FdyWYtV`> zqV!i+(v6@F#$8zpmG7?&Sh1t@vp?jKk4%Y`UXOf&=u_Y`Am~?-{mQQ7)R}d5*bJW9=D-%f zmd;qKD+5=r*c#C`CQ=Sv%uE9j4RS3_$i9JS_=!s9XuWhtly-8ZdIvt-E{J{(>}v9= zLfqKc1)+cbM)8^(bM3aHLfqQ^^1$i4$2EtN^1*zUo-2=db zz(c^pz*GVHvP~mJR*9is3&3~=IUZ`;^)RBTCX&}2F_%FTBYFaO(&e&b>ooJUl{ot6)45{rkQy!MS3$qZ-BEiPHxeo;RnV`TgQ397S`c=E zma#Js^eZ*OuW5->fK!2>UlrHT4neU5EFj30`S!c7m*h^SW8T7LNkQ7=Xoq?~U@_na zUMc#7Di^mBc~Q;FP=S!lhA&qfyF-`vkzE3G%A=*C`uX*GWWO5V&8f!G7H(57MfNLf z<61Y5P=gc+_@B#uRhJt_(63-Q?ZAxDXlPbQJMl5-S2Z~UrQfDu)*A51&djrFRbIL2 zcj>HjHbsSk6@TlTbZ#1%My20N1f@$)o|l!IyyX0J0R`C@^^#s1lWVF<7?LjLqqfw3 zH(HmKJzbhEleF5YlSOK5x+1Hz%nTzpB=K<4xO6ot-7==9?BjN9>yl9~U7M~;6a6u1 zU!QKEkR!O}4>ITX(v9iQ>85mZx`j7sj@OsnmTpgz&}cUl^3I=;JhET$*9-d9n(pnd zsJAjN{KQJQ9_mQg-|OVGtGac|x|W+Us-2Rd(6k7SvNZVZrCL@`RQ!3ly4!9;JbBr| z>n@hZ>w`Jw2?~1#-)g!TnzA%Qm0wJRtQLUYN(eV^yb{< z_5ab&iR@QFzbbn4q%punK+vy(ex-#V=vSTIo35Y~~yl zMO0U53omI=({i*G>RXrU^^&rea|sNjZjh@h9*ke7lxfR#zhWL79gZ%=POhj}0ebH) zUaFFsPTMyT&Hfd1#;$&K2dw3DFkiAeu!lb)e`mQ1UZ;Jl?@v8)e$cOi zex*4e=vP6%3i{QkzH0^jibZ7*tcvY`?Tu~{*{>q|6?PN5I*#mDLBFa*_AB?#kL*{N zog@2|rbqLbBQ{FVud)eN=jxh=+H2|jT8#2BBVR0COaH-3GVJE7aXF?sK~2nR8G|qI zdXW+Qj$E%()C!4ctjISRB30v_;rXP`<43;%Yi`6H{Dt&=vOc;@yUqnSF8oy4y1%tos^*L zT`H|^B~6lWKG*b8we2}BTW;r4!gasA(Y=n@xmw)87VG*Ga%jo-K4SWbHc@Qg;s#ex z#fB;s6&H#6r0=aEssjy|%ViMmfuVe%^dun9A3i_4yeL=q}`a(%q2#D-gv_jCY_M#c~2KEuKK?wSlj?3Ct zoJpe$2YxrVWrBW{w_**?DNa(1pkHym;OP6Zb(4w?%;hfFh`_4%Bq#FP(gu4ro$7C8 zr_xr}9HN@UeR-3*w}7{ScYwbG?*i`u?*ktQ7_D-A)KecJ`WX1c2M9GBuVFKIJv z4q5H0j{LHpqcM# zS|sRKPtgoPztR%NWZEGDF&~I(6Z9*V7f}{+i!__qu~&wZvkI`PfW=%~1i6>3ZY4-* zW~bMcg?3qMq4^WntTqTd-5=39z`DSCWu@m1(N>=DKR=~zL#q=xf`C<3L^YreG=L`1 z67WkD@=8y3ti*+?HpClwNf~p@_@`g1|3=WS{sXdKHG+Os5BgPPzY6+QUVs#CTl}?; z(#Po&R%nrwRgCOc+;Qvv%UDdx{~Yuy_&5WBLBMw2GD`fSO~ej}b~I5%Dg4Z_T^kIw z;V#tu-0NfzG57jw;_5t<<_VdbGlfbtJcu7Pv zsUBn{vT^FG4?+D<;4t8Duhf=H-<_-knND9@pb*)wXoa9(DO?{(QtqQQrdT&2!;wS} zl%;IFdkBSxfvLbFR#}nPj8vx~ddx)%D&?63NnOlDtHF^a1ecZe(`Zizo&lZ(W&qCt zGlAy?JSiiLHsmiLdeKEn188=}Zq>t7;QJ{%BucLUuezqr8`{6Wj%c=v+6^LxzTqVu zHKgz+3U9e6=vVx`f_@eBD=7VNqz{Cwb&!#@l+bBzvRML9A8O*Nvf64`9bPKcl(&}A ztMP6hI^ELRU*nZW^2(!tqk&_9V+DCrrU<*e;y5qq4O;0=uu`?c4V9FL!mHPuDCC$ZTdtrYaDUSz-O(`R)5ymJfsm9sN~e#ItTr+&N0i|kiH zzanJe#@^UZ<=X<_gqqDCTN0lDbh=r(I9buOj)w%`Q)D%0?6X%(B@l72OsGC0ye z|Nqjj#w^rFSN{6Pt0N7TBFzU6OB3`DL}s8zC|9P3T~MyeUa^FU$rPLSlL|iPPVMp` z$>(1V*ZB!zh-*K(EUbv->@kka=CdN+nl`&DP`4tm60ovq1rJMY5j-r89v=In(p7$* z;zasL@URpoiH5imxXMRN@UZe^C8CNp62ZgLyxk`82@`nmuoTXWhLFFcnLvVvrIlIc z^w7ZcIlY?q4jWUu&z ziyKO*qk!mW?hfqXa_t%<--}XTGtjS-|5$QawLez1C_c z6aV%+tcE&Zq`?XvR`9Tbhh(f`_H_o_6Y%N48Er+tND0!_r>k zI9lR(-~{h1m6oVnd86A>iooI|>P`lRxPszFYU6MUqEms>fYX7Yz;6WE&{2aRHq1(L zM6ghn+RxxKKOD{90cQbc10w`_uqK}t{fW*+G}1)6YqQKS!~)VL=npPd{90{OMx%MY ziMU~#rs;1y@oY==ucaf`WHIo_O zkBBY-E(ItyhY@t;&g3(r<+ydp!y_ zxF~p7!NUq3R`9TbhlO(h_SpX-3D|MK@y5Hz-g|~m5+3<7;2?TwWFv5oN;Oml5h?~^9&i7rYjS;9=eGZKajk zJTw)AMeX>IHI)J#*$MpGQVUh$|u!s^~D9#g4!9C)JClAT@`Xo#K$rUTCa&jK?9 zc`MPCQ$R5j(eozK%|5YnUa%5LN37$R{o*AwXIUNhFzP0+AbJ&e&E)DlY-47ZTAiBR zU+J%H|GRch-1??#EA+62z}vjw9e+d)suI1cQt+^frSQOC+CA`thsDGbJgi8ArB%ts zMDVbR8+~?=1yd7m@UV1VZR&)|RG}S-T|d_vIHSJEWcpX{I8B9f=@qjOz3eS0mrSiZ zuOfO4cpaEsR%Ry08)d0(n;rs2>6y3Cd>eSj6qL6IGxobyB2bh$%vBVUHJ|qD9hUA7 zdE_HgB0j4g`2^9Yz-PecK=81N6`hZwyjNPCwt%Lyr8P_NusS+>Fyw=Wr4yES z3ME~$Mv*VCroW5nFnesh@<@XfJgiFau*!@$mEd8C%wc;>nH6Q32_BX%%j5}Lwuxsu_Z!3 zuOM~={i;DTG=Y|rT$F51+rSQ@F0c`>F|Y|RK){YvL7TOA+!WDfCek5?iERrnwVN2Z zw?biSU>jgtU?4CE2>MmfuP&t{Tqa;@Zgog?I2KXRuNq=~<|CK}n}*U8-bO*cDn9q7 z2>O-npWtu?{Yqw%3a(pQIO{3sS0#h1R$9ZmZq!jUBrVm)K=V4*mFjI)@8b|1Zz8-Q zWitAemy}=CEJ7j_(VM}93BJ!-)n6#_|q3PHaL`c=@cf_{~EFOddI^JCDj ziY=Xt)5I3YWm5_I?0>%MX zyOwUrD|+wV)a~PSI)*{<~ke827IL>jE1UqK_Q%{Ay`zkfVu+#1*=fBDVclVo+b ze$(;D>FP-ylSq+_wHi*M-`xS+>5s@YTw9LG4D6;VZ8-?%4OpbXs&~v$SzBf$+@^J) zob-yrtgV!Nw+vBPB?xu$Ce)VOPL0hPMz|wgtc|$#ut%#@90MF%s@KIJ$xW|&dOj#| zM^y*G6HxkG~je#DDWHLx4h9s6JEB&%)v*=Pp+ib$lg0tEdE*OBMw6EnTP1pO+HARBw~7%+al29J76 z9}yVx20(RU*0}>$D?S{ zcn?i8v2Ny+^sIOs%_o2-fv2nz4}a~Rrdx?f);a7IuEN?5%|P=x*ObVnO;L9B_P!*;eHUxrxRSWu6G1T*21^r4>u}!e* z7WN_NS6nsDWU_ePyNRx!v`=^e(Tgr>H%WK$l9v>9SgYO3rFuj0p4ee2ZGu??FyM+3(Q*tpg@J~$NzTu&ZH-SJ)**{{?XLBA>>Gok-0981yUO1O@%7NYJ5v2^0eMhUzBf2&kwqZsPcV zN58_kKIm6LzY6+Q(65-3D?z`~R2=lHpkJvQ90?caDBx%#uc0TWzS+E1fB9e4(K z7MKA%2h0SX7cgTt+wwFhUO@Dsi{!FzcE)bC+(NdX#Jr5sE5NI+sVI$d3V0pSY!|f~ zGCLM;cuBW+Qg{=E$bO}Ej_g-KzsjjM%rqbLtDs*6{c5I@v2rw*;xASbLDF){$j_Bf z=zoQ_^%5`(co}#FcoldJcpaE6zz(9+BYsDwSj72kqEsqc8s9|eEmM+lzq})>cFoEr z-nLvw-bLv>;C{Q9W@+qRvOa!&tJ^Y;csil+*CSR71w7U7nkWIy| zA{0bO7k+bi$+y6Fz(41z6X3iL)P#9}c?GQUdRkkk`K=_Xp4?vY4}$Ji^ex35*4~AA zZV_Nnpr2LZuc~GG2Ug++#Jzemi*E@umn=0a4QMEEuQ8SP2*jcfTcqS;GzZLgDGr2koE z=;{^gN?fc5tnUi)?D79fjlj_xnpl0PE%hpzHK6Y5m7J`#iKqp%U9Jc0HF}?#dL!yK z1~vf(m{zS)E&tq2xkVS7QMb9(K}Xd8VoNV6QHj2PYcJ`JNS$Kaf0d*;NTp&sV0)A6 zj*8?WK|2 zU8fF+x~T>^#uOv_mD(b*Uj_Xt=vP6%Dw@Wf(0nc*s-g{@q5}l|iWNvppcdqVyp4i> z74$203TGIohiqICGohkua{cslaE80T`W80l~+a4xG{-k!C zQ~VblJ=Qhm17TKe)2|lPinM`?b;8l1XG1s=6&H2tSd(jr>OjNg%BGf23p#ZgM^z(M zW^Ly4rvBv*GKS?3ghtYPH|F_GfC2Ur2p#!M#wlArBj{H|dMdnygML+OSQ&*RH%jU^W-D3gh{!3l)3zWVDz5>1mz5(U{-vZwW@|>($*=EBkcEdjA z%&$Oj`1j9?fB$^I{J;Xhf0s6W~^y^6xV)Fk=*{t=8 zR`>e40(kX`HF;z$6N&f?+iz_|{eg9Wb%FH+w2)+PTQHc z>UiWYK;42sUsE8Gv}WyvU0tULEfb5P&<_auRh?!C`c=@ci1ItahKWwGN^w%0OV=0) zj54`Kn+I7{jHtOzUD|z)_UAeZ>C!7M;E@Y~-dwqjQtjr5cW|+ZgS>g z;T`kOjO{na`*x^3tS3$oD`c=@cf_|msfkn`-f_~MfI8KbL;&`WJHJW1e zv3;txpyZuM-ATa7t{`5Q`4q`HQ}+j_PJU<7aua4s-Xz`n35`d~KE*E<&a3ja{;U(Z8nv@3NxMpSgF z;f2)otgcdNM)oV(Bj{H_zY6+Q(62Nz?`PbJs)*)(ey%wiKj>FxP7sYDvS0nlDK1J|GnY$Q+zsp#_1NqCKlj79^f`x&q)uoH7W04kxtx?*hR3i0mF%Z!p6NyL1 z4HvtR*Ak#f{3q0{?RC0&5Jz|&MC$_U0qX-B2$*~tVsYmKm0Z#_c~_{bTAh{$qALdd z%33+HUj_ZD40Axh^;;P#w*j{UlYG!9@R)|&onDexl@HE(+udel70$PUy7SWp>t3F{ z510bn4?F-oD98g;mxI0HVMIZ{VkC+OX`XCBzoI!hWnyJTg|+S}=A(5rg>JHz3i?%E zDT97hQ79={1&<)-)&Dg8N{JpL`&H1df_@eBE87n>b?uWrN*||B@`k&^*!V23_#IpE zPU(yEW%??8oxVwP(zofm^w0Et(FgzcdCVnV{!#c_&4*}y6X_~mUdzRTi24Ex z0Sg0*0E+_sfW-uSr!G|drlO&n3YS=Lsd`HhKO+A?R0C#SGHKav!ZRMZlyI^s5~9 z)MjU;?6T`1rHIJU1A~60bqEsIkAP)?<$xap%L6L_D*`JCSlM*_BTK|8h*kww16Bvt z5YXpzv!iRAwY=2nG-aV)8-@PBIxbgYHLbhrAzB~U0Qf1ep+N8921y!KL^YreG=L`1 z67Y4($zu6KWZN_kx}aZqsF|Q&Ssx+LleSO8y~osL7ILc^Q8v$}H;n+!0nPSS>W`c=@cf_@d*uZsVIgA??toEh$qPR*)!x_Qo*he=h|kIQJH z%Ym_`Kma@4EnVsA%G##Q**Gt0f-P4Tmdf!wHvza7xDJ>oU@~uZ<<(hSkLU*APbSyu zDI0HbqnBh+(L{bzS*LZVSKNa7tuCr6bzQHx9nmD<4&YAUE?_cnH*gPdFK{0)1qk|8 z(654i74$3Z34?z1uiQO4aSV4hnnM4Vhw7kTX~$gy7R{iXR>8y4pizp++#12dQrvW-c0n+cx#~pct+eW8=!lj`2gMM`J-@a( z8Fx!IShZ_ctBssz;&haT0>1%%3k(C!0L}!43ut*!8T^{ImhFDjjqti=+p=9N{~8f3 zMp8G*>XcB~?S;)8_AGc<*{@E!g}Z2_;9;o|-tcY|JS^=DA`O=INI4CB%UCLSlxR{3 z9#$p0u^b4U>mcA@;1FvhR!F;*Rl-V5E{D5VF1$LYrGF`DJ6`bIk-$;F(O#)*9<3(F zdP!Fy`QD?d*h;o>t#)Bap1>o&0!{=@0!|j>#ko5-@ujU5%3r6e1FBeodc|p`7(A?A zaUBg8JS;kg=#+Gh;9&(1D^DYGv@Z!9+^Yr;E4NCs&CSA2uv2yhb}`n9$m?A*Hr3k- zOjrDZy4`@m!0xW4-Md{-R65ED%AgZ>Ie(A?2#M|dKYs-JN7j@%OD{gq#PaUM zLFHgH4*?DZ4zo&4^IR1lfhYmL1Pb6t;3(i|;1~hxLQRyzyg=v&>dE7%JKpQ`{dVZ9 zbj9c?PNeQ6;ACJ3@N3`{;8fr=;B*1679l7 zXS@NVA<1i{-l-JS+xHtwBz+SLidZdM~Lr6b7<*9nowTDL}wnzP=lRvxmr= zD81!MErkc~74IPWyNPsqrhmSN=zZV=lLrqg&k)+5+735(SWIt~rf<;e%yY#65seV5 zadfr3sh5I>^>4+)>I4rf(qNquJgnehK8< zK~sbik1(N~eDJW80YQeKB_Ss)W#j}ndOGg}56i4+O<7KhEu6QZn|Il-wxYGRE?cW! za`)&?#X#x?xw;Gz?x9o$(2+$kn=fP+!{)b>D>iG`#dh(MY$Dm%A;#IitR8lCRLN)2 z!FRn&V_j+4hfcSQ6(nv;uQ-xd9t9i?90MFH$j5Aj+Lc|>OL~KP z+X+@8A)K|3bo82&T&yUAI*<=3U*Ne(i2P`l*LD{k#c8T9P6vj%rhb)sSop1(5`;ix zI>YOOhs7U67n5dFlOtX5u>N9wLnBmYDw;>s0+|*6O22vum<7BHyaK!myav1u%ogY= zC9u&``El`2^M_`OPW&cHZ<&&MbvbG@>`i?QG zK1KAIiO7Fr0Us(p^=K|p*oorH@{v~82y_bMWq)ejUTFNy;U(V!-vR%etBysr4;+Pg zfO!S_W_>Z267yRL#;eZ;@ZO5PrMS};OJZT3TLf4X=x3Gs?L_$gft9!cajR~o^DTkq zlBK2sQS^$X5iJA!2w2uCtGd9qiBUFV{nF*BTLD+e$&+7^*cVJ}%Rfu0Cl@9#N zBfMT+Nu^(UNgdTLthA7pYoLWj(aODuDcX$ZW{3*PZZG%ZT>u1cf(=b@J8_xDlx0QeC22>4il2B~`UI#wliWbqkwp9B9e zg=)QxC+(Mrz5>1mzOhOTZgQ%y9@bahBdT3IdcIMqm;-$4a*d#Db_x2G?-7E2#o0aRSHAB3i=hpL&h6&e23B`=}wQs6S+a$qcQ z1#l&B6)+CC8n^}+4@?kbBTWk%SJ1DBT4Fu_LBGQ7qu8iyx1e7sK$rK7woJ(f)2j{v4h0S?+v(pX z4OXYp2>MmfuY!Ih2eMweE#00bF|W598W((!U0d?I(&Th^p7=X*yh!(^`_hzje|jK2 zm>#laK(1?PYI;Nkxh&|!l%}P}(&Oog^rY2`mYSYU(<$Jcliyuw$u|RuOiQYMF3rr< z4S77IzoZw^i>56PkMvTSm0nJ-AkhBDOufngV2-wOu+SII_BZL_H?kf9^Z8I|*_5PE zHT=rA(>v+!lH*#T;(O_R6)-&8iWc-M&C@}@3i_40LC~*)e#I0TX|Uc5`W2r3IzRr< z{pyt%%~$cDU-c;lKsorCHBGhCCCTq*B>^GmSJ}oD^s7jNr8&fDdyxh!=vP6%(%tvE z@B!8X)^`eld@Y?xR>N~?LlcX_*Oqz}%^Fa5^$PJ-izcEL&~~{VaNa=&YQaX-Z47Jz z3@|NmF-o>wlY~H0VD(F|5QkTS=ekovScd6GHF*BwjkvdUKOfhAv_j*|*HTf^kBP+}m8OdD^P~u}3 zD^s_M*U1=aemmlX+3Q4l(d*VgX-!})*AxxSeEDUk)m!>gw+^r_upY3!0HdgGY0N+? zw;1d-xpknnE{TFo5sqsj?6e;qoR->}iAs0m(g$~dy z=>fMx^R>HD_X}V*V6bcH{G#LU9$pgp&J5%_6>D|f8_j*JP8X}({0IHYn`>>m0m}4 zHW2hHg}88DM$oTneoPGdmHdWCk{a}@Ghr?b2YzS6B{mMH zI1{Rst;Ay?M+N<=A;;x>Sdm||c1cfo8!1SsmanI1qo;xCz%#(Jzzo6Y{>5{Ao(ViJ zprdKKnXeIWX3|pjB6WW)>++H~%SzRtUj_Y2o#Q7)?NK~myafBh_E`s57g(>XY$^-@ zd!|l>2r)mUZbPdhe4%!1RYWzQ4m5x!&=T-uOLR2l{k4(~1VO)|bq?^>Y5s@NuizP; z*Xy6=OY^4%^yd|?P^6C3myfz0sP@vrX_2&O>X#NvKS)1Ji>D>hl4+^5bXq3;C@q_o zqf01^Zo8M3Pb;VZQC+N#mD0*-m9%PFEv=r`NNc9G(ofRbsef80t((?M>!%G+RWNJ2 z)$Hm*wU;WqONlV`v6kwofr{MJn!VIY?bJ!#v=JK3uELn6P11n$v$QEXx_Wg(Q&%%@ z+9E%PQ%>3{ZJoBED4L|+I*^YtK-rC_IMmfuY!IR^eZ?9s{ld23i_40LC~*) zewBC2k^L&@S3$qZMhW>uZd5YRWa;P?o4~vZ`c-7V($P#oV2zWg`xhAr&ZcXO0L}q| zeiihq$bOZrXxLUXcSiQBpkHZXjO)^(N>%aoMzlM(%I>PeyB6u6oovS z??^zY5i|_VGh9;)0gsASx6E`JW~3iG3#GGx5x_aXxxh$4{%Wj0e5iNaKCUEqTENaj zX|yYKJ7#9|Om7!b*R#5cvIohz;3C%y`c=@c>=rMwUlmJ;Y!LLTpkHa)v`Ll(keay< zD%nXL3s_FtH{(mop-U6~VOG!Ok|${-vuu&d$Fu-2WmgpOQP-A7x>(odav(lhrQ#Ui z*iyZ2&d9nfvdEcm>$EhSfYPr_NehrA$kQbh{>CR$H^g5cZ+~O$iQA@S>Qw4Z15O8q z0>1%%3k(C!5by(oeiig9_aW90P#2zV9V6&hczHrHitJbHJ-Z!92|>RS+XLpt)=)9F zaf*gW)oPo8hz6M`=vOpG(65S1XopLIpkL7nLBCRd_ToJ?1(T{$d}ls_!W&ez>HN^d zm0G)^ZQ{qY*C)WIt}ZHp$5~L4;k><+Ym-75e1X!Jz*oT6z&F4g;9KB30pBRMBHORZ zHBR5r#~kWwwN6u$+Po?i^8xb%3jhlOeSw95g@K@7sTF8V(GZO07xXKgN`iicw`tI? zoW?4Cter_4LBD#@CJg0&$KU=XFIBrT9uzNoNsgj6yDQ#>-BXHXW?uHyI@9xPDHeY- zZPH!3e`piK!<*E-1-uQs1N6W^!g)29|ND5Toyr6&3xviYTM(y zx2wc+`@+PsHIzTF71^(3Lkap-(62P8_-o=%+ zXM3)ZD66M&MC6d};2_!~d!DtEPre(62-&Ogr$WZ8YTSk#^!^ zU4Qsq+J%qWGKMV#@{n3J09Xex=Szj>z;; z`Z#@(drBS!pYc&4S*;sYuq&o7(wFJ0^mY0s%}L*;@6tch_eCGP^yd-KvuX|9s~7Vj zn%_iK^*?P97DUt+SO{1cSOi!U=m#t&;5(a53lpnbb6s4z#Aad5KvkP@U_c|FwY(}cL<+xq!M%`eqYq!L_ zE%rdPr;F;E@f2zo(LTVwzOScr4yMidrw&T*$r@nF}npXkifU8}r z#R64~M>GMr7P!tTD{{KDO_tnmq;)-YH&`7@p&bfZ3O&&)Zlvzd{v5HF752$Xnk3W< zZbjiX;C5hAS=q(pcBhqCOLdZ%jKbX}Qe*+^`;q-BvR`S_6xpwI2d23(=vVlD+p1X0 zyO0B67ab&E-&5_*-EMQod#H)4k^L&@S3$oD`jt--LBAqEa%8`P#1r%@P8C7F$|et; zu5@G>SMs`Qb$0`+iu_fKr@Kr5t_7|GCJJc3W|t`9*CV;+He$-Wdaif=Xp4UO` zrm{}qt$M{RsNd?MYDH$A;&w!nfIEOYfxCdoz}>(-z`ekIz!czq0ly{aSGgT9Ca5vr zRjZ8duXfS;kGuK%G}Q;dhrma`#{x89p=7IVwJD=>@fmfW1OG6Es{8`=$}bUp1$+&B zW0i6~QSdbW06KU32DRzA1a)(*Km7M-_kkTU4=}G&L_{CdL3(~f3jhn69Pc-KpVBMn z*DOrkB37sTM_k_Z^Agef@;BG)n1tryK+vxu`&G8w2K|bGDRY)h=#{#-Ud7oAkr6hA zl+LB3e-Y1+*+7hB?U6=Vz2*jZX@BriL&j5-^g<`7$@NTA!v$Winch8DI~a7wNL*ax zb+XrG>zc@GWL>+&#p0&LxdDMC&zo#AxaMUs)NwzFy}rx+agTWg?D@Iu@>ts6Vg{ur9EkKrdwrtl4Y> zL_Y;K1S&ukr~!2Wx~w;<5h6y)a2ti7BR)U61t1gvaY zLBCR4Y)6A^5A5Kr(rnAfTkM2rXJ8kXi*;dUoO&B`%`d3i4HyjU?ppGY%YUb8Mb?|# zIT{tM=KSUAEdnI%gZ93_e*Osbr>v>e)2Q@&iJ)}p z$@8+ZcGbOfe!75y<~_Znm&W88$hhfZKFZU;f>FrwE`>|eWs)-Gi4iq6U6EBbZxpWP4vg4eSNxtLUtj@AJ{IY8`GcDP3h)z3vZHD zDd<Pa4xNT(B7ekMt=xC6M;ACdRGt}G^( zFUVP0?m^++QltoaycUBfz7;Gy$g`U7pK)^thEO`X&0NCsBCH z6*{6j!~exfI>0&aUW@{L&0l#g=vTSraj4QJ zJF;K>hh@JSvj7oB^sm_32@kan!*knzm1JWZ1jk`JV0)A6vWj33J0jZ2MC1UmTg-Y} z#D(JL)CCWVSt)o}`5H2KSjFQEiYLkeqj+h(;weN=1Ji+LfMdkAK%#_5Dc?r!~RtHs02v8-Z?mx2KmeW4h-9V~)I_cbh)ns-y3rK4i_)``O2rC%vbBm zOW8<+6+A5Un-#^E$epfM(Fh10R-a-E7$jR-vjh(-cvv+SgA3^tJ?|8?s*}?+L5qxh zF?D|gA`KR;5In4A)$A&mULy@w@URqww-^8`;b*|6z-GYa0(Ot`@;0Y)#R@e7fi{-f zIBt#7Hl-3dc#DCE2APO>om#ZFcLi4@ zg~7n?rM%3Dqm8W$6njy(HxN9mVctaAj;rY+4OXPVvN5cCDD4x1hxHxPMDVbf))kya zllV^{@2u^7m1+z2*E)#S1=a)B2R0CJ5Np&+LSqF>LWR1j)yX!D|8yNu184#*uWTy# zS+D3I>H-@98v~mF0|a)^BVP2Th&D43H>-N>7G6^PEKT`ap|CZu4X`aR5Eujm4=cM8 zyCo&kU{!*LrBM+)ELj>g$6yxK6cRkF;9<$Zr`eFvdw|o%I$drzH}#UT1(}Vy0cWDv z!o~7S(AIh@D=7h}R;Rq2D$<7h93(CV0)tGUCT6tO)a?=N0PJXTLIY?)j5JvPmpm-S zZ1Avxhm}rcu*nh;JS-YQ(SrO!t<@Dj>#j68-HlwEX3@OvP4}fK>HhRUdN4hNSbi7c zqD@VYsG!I_@W-a5$I|2JiS(q^>%g3zPSYtUjES?(T6Up`d$X#aOEYsdi5=5l(hKQD z(}uhDQks=sPOl)4*~oXG4G(#%K)3qB*;MLHdiag3hsP!#DlMHK^g$s9`IT>{chcV} zD%yaG@1^%uVDUEVWu(ERtKmxt)$yjGARDU>*QmjGh2VJ)7q!H zb;~-BRHMJTTAMf3i6lz%Ge+3>cN4tBM)VgGc zcpB~Lz%#(JzzpCyU?%XqfO$f}aI}qn0nv*tk~?7@=5i+Sbiuk=(BbT5lwJW|bxo~Y z+FrkoXts;m4dSoA;U$H9kV5dVf`?_RpytL%gB3ii;9+SvR66eer%$eu}uS4>IUL~F||lfz+F4`0a*lvP6Srt&eJ!Sdgxi5a^%(#6_{ z%N}~PO2sk2v88%l(c-X{$l#K9==^cjKTbgDSEi)y<>4(m6=@eIQ#Zt4psNx4nKGE@ zkA5n3rvaw}LxJA_zXgT?X9)O48Fcl#hg&J=S4GgTtSfK^$TvCFMn(7IbQRg{)VH3a z_ssPEqOo8~VszO!&~1Z;$BQWa)s>oD4ivKxy=)@&bH%nUUPbg8@H#NNtjvjY-Y83T z^FPK=sb}6o^KIZAQxM;Q;qb1NYBEroak0|!3k=1Th)BOjTP{wEyyK0)*;@EH(k zu!PQWZ5P`zp~yH^s7b_YedkmG&u6+Ip|kRx{(G8 zzS^n4X~5|M+d9i>i``E%+TW`m}NP`vhtKwjoVTS;R0*4t#4BNOiO-CR~z%PNq zDwW!^w1#unm(MU-EqcW`rc$}cI=afpsLQKg>40{zNM|JU@ZdeE=xLB9(6l?(~# zwsd=%l=o>tze=Cb5EY_ArqB4OTjbIiK}>=4Mfx&*mA+2jq&ex^^j-RA`o17WcrlMT z?(2FSp3r=V<~NaILvl~IAfmp&LcqenBEX_RKVUHd-`Q-|&E~8b)0S09%z7h6gf`Ag zqP>)B>-JLn)Md(2TNXIIq$<9WcDu`=`D0*tUDFJBDa9;8!ioSlnkq=}R<&`zG%Cp1X@ z;9@19)_HO?n&+Dcey6VYFGLjdtDs*6{mRa_GJg{a|A(IOMaz%-b75;KmL$i^Qf2;^ z8ZncXLG&YFSztNf$H4Ny3c!lMN&-f^+;KFlS3$HYuo|#Bu!cYyGQ((IDc15*2l7X; zHVXZLbzClHpT2!PMC$_^06zsb6fiv~fS)v~h-yF`XaG&1CE)9t@(9S&7#?K#gPhy+ z1A=}P^sAs>X~YKoD$-!-c%dueUNMK6^IPCM;GZ^!%8*Wg^FA=If_~-8oJSwQ(4{yP zG|hUz`o>Hn#ECCEHG;-&XkxKaXkM&OttsE2boQ`;M{ZQA`=aVf`2F zcN}oM%jK$J`y}bBHBY4OB;aIM2>O+>CaLRPY3%`5RqZs+OPXM<7i)K@iDW!2Hvza7 zxDJ>o$lJ9pSwF5vbOZ1wljGB^CvWtU>?b<#-Bi{o9b>P!1@&89R8>5OUU563Nx&Vz zoxokdWZ-V#9^hW!K41!PzkuJOY>#HQY09mpS3G25oU+wrrg}*ZH~J}$`XfBkD;`rR z=vOph(62Q4FOS!L(62UEGpJ8!z+isbl1AAI*c#Xd*cKQl$TLA(L6(Z`5N+?GmTvU( z5l(C;%?3MBw{uyiJaK-!<3zbDb-w_10|vX6(guKVYcq`FJ^+)ih1E8%x5A+$FdEGJdphoUA#-1vGgs{UdW%VwcIW)srFrq@{)eQ zVy>WROJDUvM2iDU080W(0ZRkR2$&3YM$jH+SwzdZNWl-?PKY%v=vR3+s|6?MS6a^7 zy3{O+vhxJ}>U?hsMUT^%3;GokNzktp{m=RZk!{V%x+cSoZD(;*WnUHaD~*^XV7@E~ z1pO-LS3$oz$Jt!%hMb0qkqnGc!0%123s?N-&qFlYMY3v2^#Vi}0zF_1aFKwSrV3Gv z-JT5p+Pq#u-KD@~z~#VL;0oYM;3{Aoa5ZoZFdmp7;7zscuW=osi7wKet2uwx+T{i| z=vQj)nKaV#Wh2!h`&H1d@>mS|m9j00k3wSv{pu8$IYGZFuBIKX0mcIpfNO#4fQbV2 z7v;KcniNkHF{cc5RGRx#GxO5JV1?Z710(%L9P^_^a76G_fS zY1{YjvI=L3Rz5Aa_www0z!czq-~r%4f&D`6sUAi&6$tuO*KGDxT^?rJn5>Dc1d;tJ z=vR^bDksFz?DTI>ziNv78`-adeiihqpkLX3s41I5`Y3%I^eYG`k^QP!h85|Sj*5yA zp?s9I&Ol%gu$_Q?vXTPHgJTCoJDR8>4=g9lW!lg#)cxG+#07G%kTy)C-KZPvb;^dR z%c(sO?dc*>+I3FY8__<%zQBH7S!?2(a)6g~Opxk9Rw5gxcKL^(ekgDlaJW}C^LHmJ zDfbr~hsb_K3kCfupBAf;{fgf3mXDB5TQPb$O^ZcnPL_)9Vm=1)KX9+Cs+@F-_j&9C z;6vae;A7wu;8Q_9l;>#IpL?lM#VPX(6uvAKYQ!A>8qqhv9N=5vI|0*{n`mpkHZk9`vicx8sb$#xUqt#P|>T)n@Pzf_}wrJF;K3;OYLs zNhu8(PnjunDEItevR>%OcY)W7XzLDq9YXJpp(9=7bvpPtJ+_9Q#3e2kMa9X!IVjoX zJTexz!WDGauTgmwqH)00CKve{Zv1#e6HHWTEAl|ExDL@o7ip8I-yifVYmT5_1^tTH z94kAwpxYrP_NrdeF-fJ>t)!3?_|~lHC0)RnjYsjAESh(>Ep1Fg;+7d5LFu=31Y6gi zP|AsHmxaKlfx3Z<6<|UGazmAhii?QJco|_9J=vP|Nf_{a${XDwJXdviUYJ|zO#NEI>K+vy( zer0R}j)q1<*1T^vG{sr4`!-FzvatpIO2_8BCTY3S3N!$&#?OFFfz5!;1*}?f5bztA zss;4rGDJ(?)+lXLDv^4(7>H<)iHKdOIcs}Y(B|6~!Ft!TXp^mb*J3|J`HMI2bs@ zD}#O&^ec6TTj&$F0=EIT1CxL|fIES^fXTq!0^dj4t#`9caJl=an*!VqJODf>kgABU zgyDJ^(Nq(OPR4D(qll)tmYB2BdK}Rcz>_XlPy~&Jr>&&zt8FDUjPVD07R?z}N61U{ z^`KvMnM~$*gGKf$zY-7nRnV`7z|8qI5cI1?1sZYCuc`zye2PBtG%y`_26z^jAsF4i zc#h9Af#(IRf7;h&<7%~&6MVi%-CxVPyd=)Dk|Kp*ws{4GS6!jrP!_Y|bwsmWB(Ju) z`$RLbDovC2iEpCxmMgX7mewoYLG*VM$!sI{pyEA5?*kv0T)WqxUtxJtGCKZTk^PER zs5CtXnB1MU*&5)PnAA8L1DkqD#yacSG6kyRZsFpJ+^u`XR#uXc&jMbNa#iAOB`yX6 zgG`}j{L1YS?Evg(ax8r6!aF0{#YFnsh^Lupc zrM|iwSNfNA+{)-#a}}R7+d7G?CC&YL_yBvj+SGrl)Yji+D{5qr5;-0UT7__Xu96@}Y?+kr`Cr6T4jM2D3yt81e<8HKw|RBg1Z?+5+rO`0X> zS30gl_N&N#C6BkDUzwRo1`rL3;YQXH<HbCHvmtVg0L}r<1x5m+1RTig;;PA? z5Yc%ql5>xy`|}Z9V4|vS9nB+I`7t!zkD=}&SCnUWZV)!9_v83i?&huY!J6sdX@L4kB~U zcEI*VHLJCE?PMak+-^zYPb`0wQ7b*St#|~lU^^c zLi4>)CM8X3(@m`Zh&XF}xvr7z(pZTqWs!W2ch58>`6HTtFGf!r2XgO~q4GtP{_09i zxr_9QS%_XXQAPg8`hUEN=r!PVV0Kwa7^32hvQ#(!V@1s-@#R}+z74!%3e^rNMv8Z> zq-ZaeMye{`U;9HSIhB6)hdlC;DUs(=k9>mYQ{Xe;bKoDq7Xtork^L&@S8zNJq8{qMrl1nw-ST znj>~|ExFyRv+j<<9>AW!UclZ0{Um8Ki|lJ9{of>2>MmaSO?l> zaqZB7ozVq0D%l7@zY6*ldkC@Ov`G&7mBvQUuU_`qL6?R3oW_C6L%?<2%U*YV+9=Lu zF8P~jS3BCu`SG%*wfRlz-U8kR-U0p&ybHVsybpXJV3*hI5UJ!NL>~j6m|P)9a7p>h zOSzThSL$`ChmW%287g~P`9?% zDa5Fbwd){S7g!HiAJ{;^->Ol!-0(!FkR_o)UDfJzl7)X*N7MkCK+7weO-=$GL|tGb zU}IntV1OX+__LqVrieB(kq$X>a4)v-k{p`U{kB43YhW8-TVNnC2-ptT9@s&^B-d>7 z)J}+Y1|s{F8X@Rcxo-shDmR1dP#R`IztU{cuA0{*d>AvBU{+D?d8Ur9fp360z_$Ws z7;$0DpjmI?mh-)fWw+JZg=9UoRa>q&rNt-cS8Az^%61F-)qfcMN+U4nS3$oD`jz5$ z_tI_Y_B4rQr>)SE`RG+^iA0|6N|V#w$hB!!Zm4_HeQ8R%KRu8hOb_LKFxdps)bxl7 zIwk2X^_{ApOEYsdD_Z(XdLg}N+R8AJ zUP`ml%jp#airV9Mc@2+&Cm&LM;cS1C9)2V1wLLXSrDcpzU3Kv*-%jtOze|Awor>?J z_f_Cd(^j;gUuhq(Dr|$*fXIFo^ec6Pqm7XBZ$!Tu)2EMqll~RM>8HN~&H~N`MhNn- z&ROlxMKsbxRb8IXojZy?nFDb$?`oaPFO$e{DcP%FudqI*`(IHE$!Lu(kCXSk+(uH8OgR~$N& zWZ%%2o`urczzEtmM1^b9%Xsc`U~H)#X|VY7i)Gy_9;0C%2cEFjkwZDH_7tM0 zf$6|Az_Y*%0e=*Qp_Y5XOhnI{h=iT$Aum`7uXpP>y5-ReUqW-1)#@RkBushh=Me@UVi1r5#ouch(nMPHV-ykQnAO zk#4zcn@FtG((Y~aF)~F-dm(>T6gsPyRC|C$c}YKDF;|fHhra5Eh!zKy0G0%n0+t4r z5wLjchiGfDETZLHq-!|eHCFHpUV*w5txi7@{!gUA3LaMOJT3PLZguPmS6e|NnzDCQ zA3WB(jY`^79!F0)-b8XcH)h+Qhrn{lMn{DJg z6Q`pz6!;DBTVNP)25=@YT=4&~_nu*QRn^*m2qgpp(m?_N0)Z5ey>{P$NRdE7jYvW- zA(Y9YcIb$27LvLn*6_IT<}@H(Z>$X~4|XN`O^b*ETep|!d_Rx5Z| z-dw@MqJzu^{tN^UE5BjgHWSJa_s$OM^(P&trxZq)l zA);`!G*a-ef`=u`WHyKsQCR(Aethj000x<7z2cDcwEG$Ce)ifTY0b7U3PXTJfJMDh zlqdHY)M`_y7fnp4g1n5Bk9^I{q;lfVTdP8`P0SpxD0EteF3a7Pv&#rCV%#|K*0jbQ zO5F;;ioh__(n+h?&}FG5dCV%*1rIBDSoDKKfy02qf#6}~m1FR*ax(-EtNgp(3U=$k z!&0VTGg~MREgy93XO<7y_-xA3JSp?ZFi2r50V_KftgFOQN=om1Crxbm{ExFb&88#J zT-`N`CZ>>)h(-aUfiYEO%a514HR1q$hq|?`4%?ybRUoPZ4WJ3MfVM!-tgmEh?pjIz z0WrCPhxPB82CGmWiBtO{)4XZEG{1gcEuO^gNQ3w&Ghfk9gVRE3;WQ*Ik`_(hN{gk% z(-LXPv{YI;Et8f_%h4s2siMAeW5qNqt&~*V< z8lA?ZHPc$Cwrlo6Xnh6?rpCSG53Y~()JRQKx^>ygQ#*B1H}%q3G+I4%{e)w^TnPGwqCk4~FYDGQ`7+meqB z0^_Age3W%j_uV>wY>QT#KM;&BO-@tNwrRVxJtBqSYWCBPeAH{Hi+4`DP*A`w6?RKg zRVd`d(e0;cX^*t0U84o5KB%$fD}aK0Nc5=t@Uh$C5%x{{QP4WoSvv}P*H6>ANU1y2 z@CWK6`FqXWDR&oN{gP!Q--bmmI{FfScybt~!?{Hb6K@J077jSU!%`oKG+4pI(yltv zU=1kug>o4zQpiQZfdSXh~JffnsL$9V;%SAo}D zQ~M3A-(N>G+eMuwM?Qb?l9qN-h%{JQ1*XB;Ip5(!a zMm=8yuqV8$n8B+-QRnV`3eiihqpkD?33KG#h zMk0brW%GtCn3|mKcW#juS(@W!d8t-YRNC?(za;2adFvMRt7;1y^eYm^1pO-LS3$qx zFsxxw>o_S3`c=@cv~&pimD{-r9f?=w2Dw+VwHI|qcCOLR?$Cj>IXNm!tX5!axmY`X z8F$x)?@)7*Qc!8ZR!7tTnl4vbH9MbH-f{aXc|w|PS?AvFkJ&cIOx{)9cO9-@7Z_(Z zQGf+|bvew|W2{fz20*02k`XEBSHHA=A|DNzgv-#mz=gm?Rb`DR50@bNHE=0#nN>2in9GC?mh>f8Qup6hM^+43yRWWF zHQbngTb10^LWV%&0mzi?JOHISlsWl&?sNliBXAQi6S!HB?Q4++ORW*~s{!R;C=&}A zuSBupgMMX`j4bSWse^tM^sAs>c@igr&S%j|^Ht0K!Ab(AAPspn+9q(>j%e=$?Ch6_BVfnd^7z)O zb~h8VG*)SMG^YW30DD@c+-Bs^UG9x20s8* zS8{>R@o&GOSq8ukmW5pN|oJVj>*FY$K$INOralY{1o8WY6c+gO<)H@_(opf^sq#REfJ#p9gc@Lcqen5UV8c zkq#ghwGt;FW>S<}klJW*G?%C}YvdhT3enQQGQhG{S=8DVyGF(=sCdg$HxyXG6l6VP zp)<_YMMSmcu?#<}ARaU#N2t;Nv#MXCHHp4)gkK|XD7Eq$UZ=41{O%ykD$uM04Og$_WUVbkZJ^_FU0}D-{q$&KsapqF7Z_(+M4$1W zyCnu?xjuCpSRHgk{TJW!k``$C{_$SY8Id~0CjTr+bD~P+rod(<*BKSbm$pE(rHK^( z(eq6=I;2SYK6P8Wx&{=fZ-Z#Et5=~U$ql8Rv7L$K3C4lf4ruNO>;&u#>;mix>;_B) zb_b>j=<{0Qf3#VogFP*2Wn`TgwB(+)7j$bO}^ zi0oHEzl!Wv7Nr8}&|<*iz!Jccz)}K+Ao9kPt*yxWT=Ib_u{+TvA0he}_yqVn z@ISz(0{)kx$A0JYxg{OcmtUeV2l&e64K3mGl2ha%U#&Mt2Nd+HpkJvEHGM}V7MK>{ zTfl1BvSPJ#*(6Uw^nGA!lanM${caoAQfxAH)+s1#3v35$59}aNKP9xkZoQM0wBy8j zybB7u0=ofItx~&k;yX=4vnV9o$ea+cuo&%iga%D-D*7=Bne$~`TX*Q2($*5J*quxfcLuopA zoHlv_coKLDcp7*{Fk@u-ET5kPo)@rt(sI+diHaqyU+zWf{#ey@IPibjN{ST1kNGMJ zuepMb(zQc-9nowTiELu~CB>ii)9oCW_YIWZbR`9w)(`p?qQ99)QFG{@?;v^?c+ceU zAkE!DJnL*5(|L)WxcmsEk4*`Y?ichcYpI}L<(@4one}WLQ`K=dbk|iUhUuk??89)A2fZ@(@&?u@^*lJcPdJUMnt9zZ2<7rJk((8%_ zDVaxCbsnHbE~q-PVPV&3*%6}BBKYa0QX=SznqRN8#)^=EExh4kE!p#|Al@;qjqOTY z;2YYlzOBKz&{&nqbt+L4-^X!YQa}mwWYzRwlZ;M%{DWr&tm#eA;{^RG=vP6%3i?%K zzY6-5PGxNip;=INg`i&r{VM2JTFM3eDzaZi_N$;@MfNNC6y|VP{~~J;duGtDf_@eBtDs+%E$0o$XG3 z^ZG_USYMAzf_@eBtDs*&T8QjdW~kR`L(s2+e#LTCaY@XbEV5t8924{_`4!e#aU4=H zTN>4t1tv{-I24y3S)FXU6$wl}%6W&@Y~qh|6iP<}KLLIU90ME+{0ulwkdHEZ3JJmo z?TB>c@zkB*b*+v?S&;)7JE@bYJH_f0$iqWmK)1pP{l5cDfG!e6Yb$n_NO z$2Yv=bnE6irW5L##cXKcsLD{N({yL%>Z2SM{R+jH$s?rJ*Bsfu@3*aYASZvQQuz_^ zv8yY(kWq`f4MjepYwP?==jWfI^cnCu@CEQCFbDVw_*%e&h?DH|bUvCNU_^j=y{ktr z2f`GX7nl#2A6Nhw1S|+d_A6Q;=vUj*3_Acj3g}ruztVPDOW&W-D8~UmpW8B?21@i% zKdDs2)P8xQ)z>;rnf1z(x#Se!Km9tH95q{>ifD$5+8yYrry)8W=mTc}XA1ZkWGu9? zNA9bd+0Lf!9N=8wJm7rb0^ma6BH&`+65!XsrNCu^Jjk>Q4Gvczy3$3OpWT16<6fYW z_}CQmtE!QLe$~Qg{xv=4AHX-j0DSQ00S1~QKFK)q>_{MCd5FzV-2%WMQ&5%(T#N_1 zy1c{Gvlm8T2(SpSs8^~Vx~rg8n~L;jVj>jec~3Ft{Qc0>>ARD{?DF`oY1&z>2^y)6z+66{D$;dbtX9!+}*Rg@(E6)M`z#_pVOe8eUhl`PNa0 zMgwDjHG#DRywXiABl0RjF6p{`jk?0>M0v$+x`C((w1Bo(D#x6fvx}$)j0M&K)&<51 z^2nV}4Aw)mzKP`XhXeP9UJ|8VKjTIyj0ZLbHUTC86M;>E&4A4X3>yl(tgE&}v=uPP z{nu=MD{Dq7m@u+C!0aP z@}pyUl5tvkF0`%lfb)&JrL*al&Xz88CYQ3d$=G|bm&9*%H?TsUl;x#dcNuUwa0PIs zAlr?5L=nFV(bd3jOs=CY1syN1@sctG=+x}ms;?zY6+Q(66*6+}WsPg$~+n^Qe%ocCMvBi>jYGmuhD9q^7o^ zPX4nRl=k%Nm7~!wE9&wkN!4ZAgXNR_RvizReO;^oAsW5*SE)Pzm|m$j%uQEEZ@LR} zvyR|2&K``?4^2tVcpW3diA$_|9!A~aeuH|&5?07tjp9d8cO-BWa5V4};HSVbz_9{0 zjoLixxsS7wlAdbBMXZFU8m^B=^8~Mx^PqpftS(te-U;##4Ehz$r$N86_aNw3`Q_0n zW`KFT%O!|humf>|pVyt>6$05_CCx^5h^`mk1`PQYN_#=Sw%#_6ETuFe`QpOdWC*Z` zD`?o#SA7f7V!-0S62OwcQoz!J{HpgzwzMpwNF73faxh19KJb&AtWwBuo3 z>Z#Z-SN4*gU!~zzlCvIz&T3v#knTK&1pSJJjqF!)XY+(wLBGP8R_V4C6<#k(c>!=C zaFM+`g&b`4CS8K)*TAK~WmZYF4s#e5uTd}SmDK&W)sbIZtCp*)lCq5V%imU|h7U50 zD%P?5oo&@qbV%WSJ$JeRxDmJsmjWwtjJ(@0S3U1eOAp29^=zZq|V(xty0|pVDG^c@%~MD*!73!vyHd zc3=d{2I&Hkv>~6A!@a)IV7a{-my9qG`KmOJu7PMIFbWtAj1lM-EP?f`Ya#j$ur^Qw z3LvsywMZNn^eg&`c4F#H$EaV>`GS6BZQ@x3m7dVXgQl}a3ZM> z;6~skU?y-ga0_rNa2s&DfR@%G+2$|NsPzNfMcv)NJ;1%deF7dwlvV9fA3!wAL>i5l zD<4Aiuxp7qE3HQmJqkSLa;?fW(>`G(eXXWJZd$a&&@P`w^BJq-%vEF8bBLaI^~iqJ z4Ej~>ud=c@!z1Wd;;aY#N~6RP&~uIijxvsp62}JpD(F}L&t$(kW8eU#RnT8v6+{{= zty{WPhUMU4(J2}Xc;z@_7ST9b%dO|7;9>nM@vs!5=+yqmG;f+O&97fhTXWfX(;zpNsFd$rNz?XX^FICS}HA_mPyN|<@mL=vF`NK@@c3FFxGqhv|<{T zR!S?URnqXZYFaIgNUNtc(#SL_jZS0InrSUm+cgjD&?|IAmulRrTa#l~s;5S3q9Q+m zRzI~%$S2}+l3$w!&KC7r}aMS0SFx6U8i@{-6O3cg@+nv%9n+okOh zsbe?$X-7U59r;A0ozpH9bcCnEZfU9tg@WmJ`)OL*BkgI|h@!6#m;m!JOQBf4denW; z?Y4M?ebasv6feNf=2|q?bS|oQm7_2nsE_PmEFO^jUYu&|#zC6YuPpT4D9fKz*B#C+ zYHH7Z3LaMQu!4t0`lywFNP`tTEOmo@=?nV-`wQ~GS;Ou;-Acrck+JAN6b=FouC&@Z z7e>9Cvk4zc-C@AtuArGhcB&sEIs!NnI0`r#_=zBYTODK6F;#Oh8)Orof#xqwM4$^<#!g4n2hIS_ z1kMuZ_VN_O`TA@`=a`7;OZPd?6*R}%qiX8YgItK_MZm?tC9b98GCj$qh%N&z2d=Qn znu6ckG_A#jw63D=YO7-^%u^ia5qgkosQaB?r#8m`>7_=S03SD?a3gRNFte&u=sd;h zuo82r{_WdPxZOk?==t~PJ~Bp9cemGdY0vWBs?^|C_oMItFbjClDrFYI1o<$c-@8b@ zjy5IBJHQV*ddg?VZ>L3!w4XrxN#H5qY2X>)S>QR~c>&!)!Ej`sd;!smF4FNyZvR3H zE2r|y3AA6ng3_zNYp$vDLjBjTBbx1^PLs2rzj!HlSi!>z9+s`GgNK#(A-FLG4~uP7 z@UVi1r6_rvRL&600MH(zMvD$*4_E+A7 zVgUFqB6wH|INC2~dBez~OU?9Zz3k(No&cT%o&uf*o)OTk z6;Er z?l$vj%QKaCT7>w2!?or6qF3Or+~6(0M3!TT-d1VGNS?CRz`OcgRNe#L2R;Bk6rh2# z9bY0(6t-cXQ1^G>e@vlJe0JUPGen;QUjScPrCx6L(AK`&p0(bRMcW#P0J7hpJpl5@ zJitI>fRM&bO*J2)`GEyYj#Hg^e9O^SPcxXhg{)3}9LMz`UcyHzKer+i>tFm9nu`I8 z14{r)0!s;a9K9pHGi_D&YCWoa1ifCrmwwOXxn$^Ekx^I_h#E(}VbrbUb+T%h1CJic z{&BHibh}kiS`8TCnhlSop#O~q8A;tJU^FlWSW}>9gsS7a^rDK6PiVZdX7$<*VBM&5 zNuv_U2cjQ5EOn;fVR@Gb9@drB%aMKVuBu8+tf#;6QoYc!q`YQsiPg@vDwWrnD0o;M z*^C)EgNMaDirG4NSdj)xE2gIJsC25L$$1O7EL&FemM)8^Nr=7=Y;AJrN*Z6baV8ZDfbD@D1gr!U<6pPl$x5Q^F>>vK!mhw>z*MU&nt3fb4bdLJp1@wf-U8jM z&);Oh!Mbk5X1g$!?szkBP**ssbwX3@ObiZCDtpE??mIwK@!NXExoa^lq zJS_E@n(R{U71Mzj^RPFLsGnM#JwoSs6nG4H+$uG!Hq^78w2~|i+G%hrrEE}te+JEG zT~ng!V2Ne+AE}#>6^_(rQLvW`kIT|iZ`tzC^TmSe+GhwWxJ%{ zVfi*u;S1DD+D5=oa0fUUT{sy%V5}1}WGk?fcQI0Qt~rjn?*i)q>jN7Ia;NTj@75W0 zURY_A~f$OTcW##d2z%@q_eO6$GX5zTgy7N&F8i5`cm$MM4(D81=Q?HrfqEku7a zk@o%a@Gsv%^e*t8$#vRdYyb$?dELqCRU594Q2N-E5NWCUcfX`lnAfECg>EoWkWB5} zKIf7zfG>eLz*hom2FqKf1uO?2-?&(Y3;S;r4?=6%fus?d7nl#2--$k2=j!%@yi}0j zqa0k7*z}ubKwz0qki#>R*X|B{oseue9wB`W2Io4)^=%sB|<#Z>uh6p!Cyp3hvY)>+|tj}FVgW8b#gEM)`{t)baFZ+{ij4wx^(5KSy{x4N*!6? zbd#di!B)2%n%@SN2Zov!OchnGh-erP^eepyT5v`hte{^7{VM2JLB9(6RnV`3ekGGg zUU%WtEZb7hukzy9`-SX5W>eD&)b=6roUw(g!eYn{a9x!r3LkS8whAkfHyBzayHQMg z04-i;Lg2X>xWzBgEw#?Qt-1lL`tlAG?yN-km6vxTx(B!yxDU7=cmS9MJP14lJS<>k ztRSYc&pl$Lnw~`8^cV_{yFwRtah_KjAN?CoQTH_Pj49~+E7D*E{Yv}9OoU(6Spbm+ zE5Bcn1}oBFF?0s~%Etxy*lUgp`V}0gpkJ98Q!d6%6bt&*IA@=TI;M5mdazH{2R3lI z$az|!eGkz_z<6L|U=v`1fMuPQ=vu68ifA(zwJS?`qsx+SOX{|&>U2R~{<#7r)B20UK07v4CIQSCu`vjXzplr1i+Cf=vUqxLB9(6mHQCOfk1obC#_@X z%%ziuK&568`__ItB9ZP#!G~{>xLTn*sdN6ci#C z3d8A$`Yx)wK}`|maNIhJx?cfj1LpuizoHdp3G!gyHaRhj^Rkv$mu}Imt+7839yMjEVo(64s1&LF=bR);&&KX&o{QOn*d zyCIqi><&!xN_lg+6H`Hsy}ev4FD$(Y>7Pm(f=jO37uXNj-z(+bs@Y_^mvqWuL%LGi z+j>>RN!{vTF8LvF2yiHHm>`cr#B$}e(4I8U6-2+W>4q7oUmj_SIAH0YJK8S``juM8 z>?1+HvOb}cGL|Qi1}n#zn&U4@(64Nq(d%MXM8#oJFIgQ9!5U5$kkL#N@hC*2fib|E zz*+(Zr)HzdCs*T`vqoKEbsBStuGm1-1X@7bE0t_cV^|ka4;Txq1FQ>-6L5dUYSuWp z9-{S4#DS`AyP=m9HcO-5MktI2HU>5UCIAzGO@YmT%>@ju3cReVwnVfQFv;bS1}o@S zN{FZ~7xb$_1c&l*-i{}LCxM_}nH4SQS5*K~txB^kM2`Gg@D78kvl6hf5q97rXkHlZ z^d0#`nzcot5;gpfKy!81R1`7IKO+&10!9O4s!DfW*HWJFKi{ElZL5oVsQ8sLWuBX+%5!tW)_32l#6$JeXib-U@;`k@%S3$oD z`c-7V3i_3nJdynhLSkgUD%z3#N*&=%W2`F8fsO&P`G?@|e2`t<7{%H{xK|b#Kg)ON zKkotW10Mh%0v`b%3%FXjIJJlPyO$Ivg!3*GKC2Y!gx>f9(U-s+;49#30h(?jA%g+H$P7 zOhabHez`70$nVCY`4bIW&$6W}Dpr8*JIPBrzPCfyx{`L}9$KCFtEZ6YU@~7a1=!Xv(MHz2 zn{r6n9jM#U>vUjc-CI31KMqF$?lYQ6;Jcwc)wJtH&okS}a4WO#9wsKMt=eI)N~x}> zHva0^hi*@Sdh_cbN=v`oms{=!><=6OOc!JgMc7sNTQBM5(|>fZm3R~Eyh}Q|&7m&V z>6Tuh!>bz*ER7 zRnV`PR3^fz*c8~z=q5qG3i?&hue1-i-`)pK3p9rY{faRn=vTHf5BilB;tDE8^1z^9 zvAuzE(l7UP{)uuly1O2s4a#KVntTDx(x4+pZQ1vAvEm@89rstMJOG$psfz?_yQ`)J zNFcQt+a{ELXi7@=;K!<3(dnLtQFplCKu05a>xUnq_Hjp0cO-BWa5V4};HSVbz_9}U zouFR@{VM2Jyb*r~{s;Kf-wpZiYI*Sa+!D0WFHx8SeC2YzLH6!7gMO6<$c_hIY)AI1 zpkL7=6uZY9f`WdfEoYmvhx6gYTmW1MT;%K+4I!GoFG2Kc;8Nf+tHd0d7p3qTwFJ46 zy8pI11rEhRdUaK*5m@}URjJ|8z#A3IU4C3CJ|x_g29fct?5fS_OX)I9H~Db#8~zbcoOqkg%Jd+RG{ zq+X5Xyd?XS7R$?{Fceq;SP>W|$m5DOCVAQ15FsXiFq+J8uWu-TSHE11OGcQ8sJ>cP zuYqVJFbWtAj1lDDgr$4A7NYL}YXdc)0O~+PfUfRl+e9tw_2iNLD(F|`&*&h>0Y9&L zNzLgK%HC(gu9A{z06)>{6-`?)o6D2AnKh_xsj8+nuS?h$%ifRCK8tufQhD1*Wy!AN3bKEKrM}E8DLppIpEvC z^1x7F1z<&iExy=~tb}M~U=?6Eu&O{B9181XafFw;IYjyzD2xO~xxCdO>*N?jYXWNl z-vQPZ=st?X$O&12s17uMCeQ-f0=`c9rfr)V^sAs>RY41JKU60?*7}H&k#Z(-oc9=c zA=pcy+)ff7Pj5N_I1xArI2kxaK$mZbtJW|73(=`AQYt5%i2V}LX(lSxEA(W7Ra{&v$!A{CE%PF#3HkdNG>>&nF`O-|TdQI3 zCjNB#(qEu-Ja7VVB5)FLvVciJ9u?WNt4Fci+M4Bv*?uZYGhC_HtwPD?SeB<#*S9)S zz-w|i(>0aeT(;j|d0k|`3i{Q60W(Ij;8D;!b*p#jIzhh*`jzrP_)${OuZWFe+s&X~ zb#(@r&m1)+YF;^|qNlXsrTv$en%eu=OxSjUnu5n@Gjy8Qw^~*FblpzdCW*^4y-pLO zdDALvi7q+Y#kFRY#WzRQKaWe!2QF|0ZTGZ$x(Lz5z$GSEG*6<2UW({46V*D|U-k+_ zLB9(675yOSSLIL`5-T`2psOfQinZ&do{If)WiKgqk4nR>q*&>!jaTzh5%jAZD%2Mc zO<8nUT(vaf^~){PNadDu+f8F+ISJACfvrtm$Q4JeyNzopps;?2DJX0UYzJ%)>>yyX z(WtS$-^og~UK_^mE-35@>;_D=%0gj}wB?wFXb)gdU@u^A0lN)lhqS@BmLoltCYG^P zzcKagu0=J|jA(X8Yz^8_O!w-$N4f>TDBeGx7C4znx^eY`jL0ni02>KPR zupY2Juz`TtLaFYh4CnDTqzOzp`3tdqKP;>)8N0ED~J_lvykHZnHfum zbQ-I-;*v>~l1>toRk$kES;cRI!en4dCGXVSO|hj+F6H*r?Epmft7E*0v|U!y1^vpC z9LU$z`drhK_SNKcpSxqxRbHNcc^%#7df*1&M&Kr3CU7%w3verN8*saTx1;FUt(9Si z9t9qAc{3B8pRf{< zSL{%wXptH%=vPJCavsA&wN-8r^sAs>*-IMPuVCOE3LFLm{VM2JIv^xR=%da;Q@}q> zUy=PvQ+lUR{$1vF@nL)_X)2m@`8lu77r>Xm9N;Sfsa90> zT96Hd0W&W!A27dhVQO0E>h^=YBzH2ct_N2oCH7UEbJT|bivWvyrF@N4xtNv6i|XbQ z%w;^4TyZLkkAiO7zvN3I9lctWbnL%X=%%1w>33Mq8&_5``$@%A(hss>)#gFJvgNEy zgHH46c_)_@PVIMq8mgS`eNs^#Bsvh$LEeB0Mz2o$LoaFl>~BaFkf)ZjXdccbKN8G1 zWq~bfI>BiN{i+f4tDs-W0VmyB}@HeU-jW|484I1Mt$HM<6vtE5YAtUPSYms3_z-)h`!7GzeG_7z``~EDQ_* z77_4OI#BVcw^^%ZTpu0f|E@!bCD2~dwd(~QvP)N`PR;T_)H=*F%c1#gV0mDuY1MVc zp~@8z4FgsJf_@eBD|LgQU-2>o{VM2JLBGOv5=u$XuOj;uYa1u*ExqvepJ?Px;mjkQ9a3xV)CHT;&mqcubY8e{1Po{)x&P9 zZjfmKcc5@*B@$z;U*3)A9^hW!KHz@f0bmyJAn*|Iuz;sj>{1{n`) zpkI|s;)1`Fvomx~X6F-;{fd=X(654iRVa3Q9yR4bpfx|s?x0_l*V%wUw(Hy`c*z<~ zuhpocqO{nY%&Zh^VmFkxcuACOZL4lmsk|My1Gp2o3%Far`$v?`ym9Ll@X_uwv3zv# z-gp4bS*|I6LG76yLiDg}$p_cG0Q78jv@Q0wu6xYuWIxxGc z%mj|VRHa6B;M^t~#+zvV6?n@ObgoP?xVNpOWZRZ^uBf#w2@{(`J@)%t@_{Ll=Tet^ zgy>`76CmhULBFyiIdx{emFq(n*#OuO_@2OQ4Y;3=N3^kt6vTleya|XVx|Y%r`T`>8 zSDGgx`&H1dBKwt=Ot|nz_N)I*`qdfp;`gDyNP~r?Ja||G%0pn-910vZmsn$~cEb1N zm9`QNcsP4Schp+(NK?eyR&vq4~r45VQC!HCc(q9C8N%vv;%yB z4)>z>9K|A0hk40MMUNfQD_)Y@tMw}Fyv(Cp?y|OX6H`*%Z#H-OvuTs}(hluvE%I-_ zLEW3cUxBxPzX5Lp?*Q)t?+MsiwiG9|Uw(k-L*OHm*Oa+d5BQ0fbcknr$WA`*`_#mW z2Ua~`@UYk$h&y1vMZMr$HPT?^9aHeI;EV(hOL3BDhzo&8gB3iikBu&c$y6(>NP`tT zEUh?#hgI(BBql>&0ZOYRMAQEs4@=vk;9&(1>&L;v3Lci7{K8fa9+t-A zRUn}Z7qI`+QLFaxt653Ms^nu>-RrcY)|POj*J&fKy3tjgN2(D!U(u8DDHD-I*`N1X zevGMeOkGj)>l+OnIc3EjF5V3n%jS}21?7K)-qxuiMT&EH#T57)> z=Ox8{vfaMy4mQas`ksH#o%8o9B)A^udwzwOaBhU~2sJX3i5g#S!k0_{CIXw9IvHT} z1e+t;!bCN>V%az7P+K>iMBVqjP6iP>fo^oL#ce~~WUmu1TlR}>5pCxpaohF3?|^7W zU?*T_uN3QEO|h$&^q)#~s+IJc@YT~$-viha*vl(h`MZ;q^xublS}#sS|oxn??cH|x7ry(PJ3ew zOn72l<7`3QL|1RiKQY(U8y1hHrT`S?$|1ijJaI7%Ta4f`=7pu=1gR_Y18{%r#J? zso-J#!Co7APWr-6dBe51`y;Q^OTf#(E5NJ3Yrvm?*MZpry|Ri1t*dxV68>M%EcY*hS_kj<94+Y#=21<<@A0zt2MC8A*fDiJS z%h z4<1%e&A_@tNrQ~_5oxew{FFVDQ8UtD1rO^Qe?b%;O{Rcr88w236+A2vz48#D$gRFP zYmgUcfKzfbipmr;5SGroCL$KHkFZS-W~vl#bB{ixyX`87?xs9OCEzC`Z0E@VS z_JR7UZy{O?SR7aaSQ1zYSX#iit_P8=Ygt6gxu`~pr99@7R6clE!NZC)STX|JJJD)k z7&?{rWd`s|e`&C}^vlx`^<5;tTYI5Jl+}B57InV@&IZl_A`KR;5NWW2hZSkCOA3Dv_v0d_#=*${|OWJ5(U_W4guT<7s8QiCPNv9ln*e11oUXO|L zC<}jiFqixg2>Mld9_?^GZ~<^3a1n4Za0&2h;8Nf+0c%5r+t9l43Pe}BNMtKJxzu^2 zeF*v$T>R%~r01(f3i?%x{J3A!DE|Py0S3UsmYcU#Ub~6@V3iVWt)IE49U@G{|Pa=H4nnzoIpQeiihq&E&mP z1-=dXRnV_;sw|s@A`MnIySxSc>R*z6)eHJn(654iCE7)#!NL*{^s7jNrCoKGO1T~uqy4wVn( zn{^{S>g3*{{3^<)S>QR~c>%YO5k|JM7ZAPZBC!C>rqwH|OsZ`t zF|VNXD)5?X$}Xp4iq{d%c2TE^55Zr&q=3v)2>MmfuUH(^VZ;XgD(F{1ztZaXV9<8 z#o2mqAXYWewIxSb9HlQ+V^EfU2+3vM%j+vya(|y_L8Qq`^{S1pSIG5%jB| zUj_Xt=vOi(7nUxGnOgHq(66AToC5r(Kr5F*3lgn{PDM1sMeR;co72+}oeuPYGk`M% z`6BXkvF=gaH7%9SrtTczTp;LI9AmVJcKi_S@vwka>(*KEJ%Z>_;4zmgD1w%XPgsc* zhIuJjXl<#}h^Ntf#_Bk8RdWaZs;5PEIma8U8T6~XB@!phU&A`tW|;+y!Mv(_U9{2{bU(654i z74$3F2rv04>Bw0K$~Et!@|OQ&VhvS~S17ajTN_S5ods0t9(d;PRx z8kSZ{E2mY`@U&`LEsaR4r!~^ZG%AfwW73*wEmRfEdajqS$S*bS)vd`dDb-UWHBsr} z@R{1Fle(#w#-h=Zt+}7pP26Do<;}T(4kj7@ zHB7uI=vP6%@*|X>Uj_Y2d&Qt%1^p`MS7y_R>{mg*(kigglwt2%?pH5DUS4l0XH!?( z-X$b1m$W*ldD`zRjc6HQSztNf+raX`P+$dMMFA@~Ede#|u7qf1U=?6Eu&O{BWPy?8 zb%d9?kUz>bP#6h}a=Dm&`t~u1)&$l9z5}c+V9lpxqcjRcb)W$>ffmpf@O2^uxJ$n> zGUi2Z(61uiN~2bOpSrDGT?2~Lw?Q=7)vHjFcnWCsv7Lz( z>y4Gb4ruNO>;&u#>;mix>;_B)b_b>j_+CYuG^1NbW;-)wbqoD3dwac@d@AkZB`r$K z!Bc4@eZAB3%q?vyIh3IPFHzwD*QbCK$YrLdv z)_S&Ut2)_N`{nhh-{7J`@f`Z)O^9X!Hv_i-w*t2Tw*z+ocLH|-cLVnbc$Ub1WiMOM zuY!J6cAye;fuLV818EA>gdFrM9b=Wp(=CF2h4q7kCqci`3L)rMLBA@rP15i%-03ws zj8?}8`jrODi525WY}LGdQQ#5VQR)0$8Q?0v=YiVV! z74j4mwgt8Wwg+|)Xv!kAziz#gm9*o;>2enob_I3=rdp-wX*jz~L$n95C$JZ=w}8cQ zx2=V`O@u+eQbR`etL#^*4gIZjliPsXfjfXZ1#}kKAFS8NRadI_PCAJ8lx0v}av)6`*l`H7bl%fQ~zPQih~ zrzV#D)Dq1Ry4T!7C9qX)5%jBa6-WldfmH>0DIN5y0p%objH2E1qpuEq@CP*1Ho#*Yi-U-;*FM6Z=u6-O-!|>;dd) zm2#Wmgm`a63D^fHfqjAffc=331pJgbTC^Aa_Sa zqt{wyn0QO&O2Ep-U{X9GQ9H`v&Sw(c#WHcX#q*G#1DdP5rp(x~ER94o3K$KHsVZ9y zpUrF7pT0xg+E&N@UiT^x)qw`k1X@5_KtC62MOSvMgw8{l1;HhySqJvCSYvio# zKlGB;&vvm~CM&`a3+cnT0kdda-RtCIqq%vc*JW?W1o2E0vXJqh*Iw<~d>q&a1``nCq=LSt1b*QrEJd>_YoNsDJ&f@pfM zNk%UA{=sRfniKR*LBCQP?n^`N2kc+9CL7dpx|PV-t>!)ug@b^DE3LM+qx{z0c2^3A zQg;||xGU(OP)+<}L`MKe0!INy13wXPxqR<*`7u_~63`-8l8-=FABX18fnNZ}11AXR zBU+?seQ^?^lTB3gJWwWNWi8GA%f;Gxt9#5q^Oq)KgQX?i>4+lxRbG_`{VM2JLBG;~ z6!fd0Uj_ZDyt-l=MfR(pUnw{qc9l60SHA+j1|s`a(65MP6!a^F1Il|L#h}z{atI`y zLxIDbsUu!jwogJZ)28Le)ExmF=?XpQc;(Sns_CpRZ;uIvs$I}AXddgDid@dWn_xYP+s75`NLKDsQJUdO3Y=vBiT3;Y=F_R` zTOAyHZK{HP74)mfeq~WApp`5JME0woU*!p)R<}Vm=vUSpji6u2y7?Q85!gC|ew7xtH^%UFVCVY{0cZ5I0uOASF}RVuY!IR z^sAs>1^udDp6Dc(PE%&RpkLjn<|uChf_~*j>576PuPyDoX45u*woU`7#C)>l)hu?& z8`QlC{1tc$_#5yx@DA`U@ScDrYtXOcrEa0ydP*da&G9n*$bD*AXcNmhZ9<0j?2$%$ z$rEWPbt?cX0>ey8Zpu|ofdW7HpkHO1NvngK*OoNYRzT3N)CfPKC4LMX0UQY&CBVp} zzGgjA4)u8eQ0@sOuqco5dgU9@G0xApWh8U&U|mEE9|8M4ZaA(L4tT`c=@c zL?JR#QCFE|^4J>Lub6d%enl$;{YpGK4b=bg^sBB`NRj=DBvX<7DsR}873-*UG;4=e zT@1hU({xN;NOVc(^)o&ynV0f@{XG359Zyl7CrY1nVmc|EoK8vqDG?#1b>*p9S*z-P z`eizeg60g}q@T{nHH9`j=`22KN$rj;P*2i1>0C)!_$bTQ`RRhJ(pHEKq)J|1qn~_S`kR=n?6f^t*Izx-MPMo!UXaGS8); zUul6G^sAs>sT&0S3J%s8z?r~V0tQPZBG6{?Y((dnh~$l0?wsce8l;Wor@2A~f(y~S z2)G!y#I=+aLEFkp5nTpc4qRcCH91{cgaHLwk=9kzU2SzFf^=F`c7(i!y5ISAqP%J6 zdYzY)qe$+TH=uAMa1$`IsuTfIAv&x?N+5Z8-iE^MCQ@X9$bKaQf|@1hS3$pG1w}5} za;&pY6z@U9z`C#v#sS|oxroLDmssDm>MgCh$_>5L=#hM3Bh<%N>J3ZBp_L>q&l9Md z=<4mds114TR>jRx+=(2zM9V`$E^X}g!D?=^dyf&yton9P?< z0k-u^J%{Ld6KR`B$eb6fq#de-tdn(8AsEY-(0tkIWYT0&_$s2;fIpdB z+&x0s&91b%9#BsvPm7S#$t%`3Tw5n$I?DYkH+ai0(Xc4d+bYc%$x|xmoo@IpD(?aB z10Mh%3eZsG6gyXwQB;rl33Y!5{>K!GMu!M6pCS4j_yYLSDs{eWA$`=EYBlaxZ+R|3 zEn?N$-=IAJTGTwiKqo)wKT=c8hiHCa0h4QiZ*f#bjbs%+n7W0muGW)JbiW+pC8GCb z1Fd2V>RZ|F`K^XUsc5h8z9meqZM`*`IEB05IMAsiIr?Ual#p zDrwdg3Q_&|V3dAnO6u)4R*=(C)}+IzJKS#|la|qiHN5DRID)z(fun$f8Z2+6;9)UpEBjIKuy}cbhZQ_5b%Wqx<+)0WSS{kF zi)Nzu(} z>NpTj{ds};fcb$1fI+~5z+hk@0c*!@o890LE3rqkHE6r;o->`cAEMOT9I!0TwMzg? z0!sl)1Iq}wpF(+R(Yc(LWT;XrERVuaUdB=@oQ~tp?%+^iEqqK3QRL6gM z0-}i~;=ovYgUwt)k2UwCY3^^M|86TTnN%ssF|uE7U6mA_Nhugnm<&v*3 z?Wx-V*wGa9FS9z_8PP5#s@2+xN>uKKXezKfFwHCVk5$LxDV2Rtv})zZ4od=2H*q*wPv>i$^O z<;;*TTS-1gkm_DV;WbxiG{vVYUq>|CMOv87T_?KzHy_Nrfzq3KXqgJgjE$up$jsq`?XvR`9Uk zV5|fL4=Z?B>IT8X;$;XPR;0lS9#-(M%qStdLh!K2!Qm$6Hn}QygS9o)s44ZLr&wRv zgi~4_p9TD9~3Hy&jK$v6tke ztZ(}@3YP+x0hfEFtQe}i(n^H1Qt2ubA`MpXu<+~8JElm3H7IykU3eT5;W%sxY-Y5G z;9&(1OOu?3@RV~8XRPPaLCyotw_c(cq4?umXeE&XI54`{OIi%L8(6_qc`4Uj23!tY z0bD6yW>Z8*&AC@0x*GV6$#J35mDhNw)xuBf+N!QAGC+Af>NmKk(5Y^}ya~}v;AY?! z;8x%^;CA2+;7;H!;BFw&U zKBQ;BYB_T**-37jw3p(SsJ+gv`fJm!3fk^z_jD1Wi-Ai_F3(WK zb1W}KbeV~2o$N1r1)?imBvz_so2#l)6F=5SgO$Aj?G*|7mDVO-(q)2v74$20gP>nA zN@Hu#ixKoIwmHhFph+asU_tr07q}0&A9w(WG+05u3i?%~!Gb#%^ea1OiZoa^z`Tky zSPJ~a8Y1Xd>J1Cv&OgZ9`HODQudHJb&b3C%6i#%g>wvFcHV`#|7SQ&}mW=MA0VC=G zV}W&mb%AjLZX5Kgy=jgF>;sg*zQBIK{=fkOHCC-I%5}C)i6D)e19b;^omeMk)2j6d zrgjK*LBEoHj)u4pxX4>7=vUU6f`0XP?-3mmpYVby;Jo>IlU=-DeonXf0{9Y`1AHaO z?_yoA86#Mugdevp@n79j`+S0zQ35WyGq zA;2QQqFyOqBULVDB~qlg3li)!ZY)dfLD+p4;<6(DHqqR>9%xx9{5SllI~1*rMuHT>E3i-x*xG#cBKNF zl^#?{P>W}@PUuiiQ^sAs>F@y&FD(F{1zp{l&(63l71^voNNkPA2 z$s~JF8`d8__+$y}*6I{lEjjEZ{-lA>d&F^O|Cp>h$0dE7kNQ`liQF zc-$4br0vN6VV84>r>J`xh%{J1zfy--MVyOMf_|kFBN>{5epUVl9GnAzgXkF=Vj>Mz z(67q-tux3WDAHhQu8uTVIs>eESaZ<^ZAqjvH4UQ6IXOcXNo_Tj#}$9*T#>D^3K8-( z_Y9+MC9e|=-^kE9QMB7B=a6o|{M7CLMkcvR_q0ucpq(eihlTBKs8!CM`v@0y)w1fCc?3=vV3# zG7?p*U}tz}xoqy`@-Nq#b2cQkKU=3Mx2K`EnFvFUJG?v<9 zpGGU44)o{B?Jd>prJSziSthP2ovJp=XQO!zaIVYS-Ilb@M-=p{rjqXEm9R!ijfjtW z8%6f3GU!(pyt!5PXapL>=6dVo$yKRWJYl2eNxf>r;DW6Ltn3u9t_V%C#yQQYuH?yi zx==b|y@4apT-`N`CV{6%A{qsZ2F6sCElaek5kSd=%kNOPw$*89RYv2oKvV}BKoe*I zZ2>csk}K=Vu9Y}Y4f>T@XIF2XmL~8#3jCYUuQ;^~`c=@cf_|mbg>+-ODb3U%7xb(2 zVfu)M5J_3=uTS_We}>8#LA0^-Y5FXEp1w$5ra9@W^mY12`lcKJU1J`B^yOHpu&3p` zh~_hqj^fDxu>hh$z=FVFU?E^(UFL&I`tej8XG7;0K|&1b4y5z#OpvR`R267;K*z7X^)S|PGu1^p`M zS3$qhbS##M>}-+!D(F{{{VFexW&g}e5s@2B%`3;obG$k4Lt1~jWpykzmuS-1tw^4cr zco%pNcpvxx_)x%|8|459Df0jWjflY2T4c{>C3zMp>`8tg=x*hpO57z1)L^b#2v`^x zVwG6lw3k}cN}Ls%NwJn$e2b&GM5U<>P`_LX(bB*&z_M0Z)Y{6bLvuHpm=c$#ZYZ#V zDJWJJl!;-k-fQ_Opxo!xbV0weeiZa8y##tof_}xTWbekW`~?d7RnV^n445&J@m;4b z8sCF{74$1RztfqUeb8bb9!tbb+lt>U{0i)cpY12AJ$x%HFH4yRDZr``emK z3otEYc0hAStCPuCA(654i74$0xh`$5>1AOZ5M$uzF{CsXH=vONn2dN19 zRnV_Qq04)7tOc6TBl{JLo5+3@^eY`ixW8P`uWT7Ex`{@JpkD?3D(F`jT7rJXR{lE3 zIM)L~zry+!^sAs>$r&EP%9=pXuUJv*0Mm|6n>Cpi89jr3RUT*jokGM59e@79**vWd z^t=Pd=Gt!^Mi2 zkY^uFd^l6KD{+BuXt(;d2Dy;Os#LC1iOAztj`NaIr`c4furD^5X{+TQbZ2`UzA3U_ zsSSgEMNbO)RnV`3eiig9n+1b@r71h;S3$pG;f9xNUeg8rDzB1*ex>zN(64GW9aAVO zlvB3a4YnX_I2%QNh4#`EvWIG;Byl+gSko06GP&7Cq)wd2wM{GvAAzX~H0waa)oVTM zhAl*GpyP5~V7Jlzw4WJE-8#U!z&O*A7f;2uYhmDDpSlgKj%;xHFTUp`dCKei$9qZn zuC(vkP$GODR~PwOZI+I0hELB!qU{YMFB&63%wWAohC#af7KUfy4&@&I6Zr7jYz zEh-cyl@Fvg)0}-UNxY+;31%ifTPHThFfa8~?3Y2mitJZiPxKV@D@BI4 zw?htlk^RcHRFVCPT$C0Dl%oViX$Qev^JKrC)vp2|ATr#Or zl23@jT2!Sv+na4rm<&v*!x@*awe_U4=^_PlO& zFqixgI0QHpI7~n*%g-cl>IeyvhcCUj?nWukPJQ!{rl_XZ8(kjlm(?*D>w5jq@&hf8 zaj~|`YPz4PR2~QX+~m^o>@|&sKUvVPf_{~|AMfug-hG08g(r(%y2ySN^eZMn^TQAN z)iK6b(bQCEzWW&zmY`qJ3fBO?1FjYLvdLFi1+j8&pzcQCCSay(89U<^FLhc~jMSiC zX`Se&+dUF0y+NzJ>Fw0c_Mo>A{mn!QyP~MFQ5cUS12CR&=#S%l2%oUbTP< z`jv-=)nYY|Zn7qcD8y1S=vVm#4*Hd7`0O?IhPRb~eSlKn-NeqDw7IdZoq`}~4{`uX z(_Km142cdzbdZT^jY4iK$sGIC{qGQWwxGkdXT%Po{?o$D#8RJn(VbreSC&%G+8x+UvTllli` znemCX4()nhZn+<@KX3prUBH)W*3@ivpqF$9&2$G_N!$iw9S|@`w>i|sI^B|C@$l*f zErr0>oj7qc+e9bN%}1)fJPJ74HT6_Z%Jx$;&e1eK2K|cP;s2k0b;bf@fz=-iBDv65 z1InpX=C}M4LZ7Sc?Sx2 zR-!`QqvhR*?g8!v?gQ=z9sp(m4+0MX4-0t8Mw^@nk5~!biN5JE6drelE@?aHd$MNf z-*}3;r-5fop{7o&KKY!Nf`_H12_9DPu#BHo*WN^9^cE_WTRLS+t}}Ly(a_l2FTYRS z)~>FRMe5rin(XS@m*)XPF{5x2+0Mj8Gw)V*Kyyc6Ctzn_7hqRlH()BTJ1|Yao2)|- zb8+a%!#%&-wJz`d-d?YaYAWsHB~2CCo+znyOI%;;S!QZYAq-dtm?91nx-8OQF{}m; zD|lGGWK%A9|I14Xu$7kv+MWAEuBlz4&1qgQ6RsZx>URC|42jD#y-w4*t?OHLrtPy` zTx*Jq?%%7`#(7+FK5&66=+Ixgz>5%F3|wMz&3KUHFGX~jiE5p^U7K zVCyZ~9O|*(=aLUhi6p(cj_kpcVj!%y6w~cGb30$3Z z3JTi-+X34HI|%fKN*jmtovftDAGqT0g2JxAZopKl!~myF+%!ac0DA&^0ecI0-IXTN z2H#qT;h;1zvFB~8*A5<*#<+fYI*k@Qtg3rdCfVR&1rLkkcGhXZ!zz0aa)O5yJS?Wx z;9=QL1NUq#Q6ddiPCpYoEai~MYvkZzX|jkkSlI{}JSeI1vsMHTE4QIY zDKcU%3@c>_un4fIfCiQui7FSf5)6Gemq1gaUjD$9#YbK#NV+`_5ul@2KVAENOL+QMKP$8qqSqvcPh{w}It>p}-2jiUPKf za>tRE)Jlj}237%v1FH&hH_T4gBfQjw1yZho!bo70%Ud0Ckc>gJCa@Op9bj#N?n5L$ zX%vX+Km%w3Eubyn>ss;%$ZG-xtaJCE;9&(1D|lE}+Y9o4;$h`iHRxA`xLY1jri(A$ z9~oO-0$v7Q0bT`O1O5cO4$KzhCgdu8kXK-p@t_Tv@C}sSG$jUQ?zcNlz(68iL?37=<#Vkt>QOlHv0*6@}!Rxa3OawD6q<&1@5x|kI zpch)k_@k|)+$H8XF5W8H&5l9ySl1NQ+0F6|dpGrx!hib(O2-2y04D+`0VfN1#S2B> z$nUy5Kkb8t0WJ1UMQMgB^}2-<&~)M==RoTER;Lb+d*+$08T6~5U)cnspe{^C>K8%3 z3i?&hukw0MPNNz>r#ew1(qIMsDlf(HxWC3bMLlOExE9XNbtckoLPM!7ye+c6vITe+ zV$Hs~c4nnm6T6|j#Y7xQ1)w#CG2eOx+lTv1tZ1`Xavnf) zmTNY1q_Kw(J?vT{z?m0-)*Hs4(DFgoJ?8a6zY6-5d`M(X3;I>iuY!Ih7c|>RwOSa4 zPK9PQ1Nfy=jj*`{{i?i!Ho4Q=q+;qTeu`54l=o0~FK{1lKkxuBOQ0EzsLQ#L#pK4? z|FDS*xv**R^$41e0*?WYTcw65LV!JKCGE#8NEfk}^fNt!=CiITk&_?W%yfUC?gijQ zQ-I*8-TX_4UUrebIX{t()9_e)&BblSo0hX8nzMmF1AnnfSq-!^FW<0|4pypIRgnfO zFQtQi74)k}gB5A8T6QQQztW&zv15D56JHfUzsie&pkI}vU_*=sf_|0zM9{DBaS8gB z&geLT3;Gpf!}Cs;l1a}jc|pIjgHbty^~-O(brd(oc7L*k%BVF^%${;yU_M}eC;C|M z(Lr94LyWe0gR4@|ulnV8XsxxqMYO-yCc8jX2O2;VXaQ{jhH8bpQZsg~M3gJF|5z{8 zTE4+n+6nzyLBHCamYW9b0qj||)4vS;st^w>=vP6%3i?&hud+ce=vNx2gMJnCD|LgQ zUj_XtZ$6Z}UCY_KXpOrC*8KM6bqJPkYpJPSMrJTKs!t<{l3YWV`97hR+%x)z|eSNJ|j zi*`NWD=57Ryylv+%W3`oI-=Pw>NJTM`WG+h^iB#vzY6*lK2kxy3i?&huY!IR*{_0r zMe?RqAe;;up~*2*QdXVIMuBQG!r3V8Mop?~cwJqY`ts5T51oEFTHv&UJ# z^@jY6);4j`ZIWQ2K(h`sTwSrqwLobhY6BgY>jJxt?k5kPvDB>ttP6}YEqU=&Y`c~c zKa}fJw}I7>4Nm{X_q?P9n!bO$m+D<|(rxn3k~Al(RBj4vX7Zq41^tS|fjy6EUz2lo zc`hB~Jm7rmB}A%K*SpY4;+Nq+aIu$^UeJ26#v57ZFXg(+fXjg^fGY*;NOY2@eZW&GXeMwoa0_rNa2s$ta0hTF za2IelaF2jz3Hp`o&4PYaE)G#)31CTJDW@ceqUipcEqgt*xxkTgIj>iL*WkZAmkgaN zvfMmkOKN*t4x?@*uTv%0e3xFBdsCsqSWN;ot0xhlUg$cPG%8Wi*2~taN?m2>C_5;0fyjQPW~~MNDz^fu zuFB)-7LommNC-i{Vyf1F64|c?lyi75z7p`NDEf~L*-a&$HnVA?qp^E{`{-+FuDN0$ zZu|4jb<{VOzOs+I1yq(+1^tQd(nLaVa`$W*M?9fD~9g+P?V`gN((#sL_t2vAjU-=jz?>{@cYy|zPUk-Qr zj#|ZHb!kJU)1DDfdseqP#q%Xd`$$BifYHF1sz=a_ons<7ODOI`HkLP_a3gRNFte)c!I`?nN~8pmC*o}=+-@R87SPk@@VJ>HQxi?2R;Bk1U>>j7G%eS9`2`q_ma{yt0#Sm z!e^C2osRMaqA!6tz*oT60)C)ccEI=s(Eu`#%mWMr<^|>xn+WA8n~?y9Qw?+{7|2?(J|AT)u{WUt+K zAQF&3LXAjhp(KPdS+qYWhzclz(xS8tO7D;ZHl#{#fk-EyAWd?-K%_S*Nr3nM%`sN^ z`v360$8*j*o)7o6=a^%yy`H(}nq|y!k5L{29P65TDtpD{iCX0a!F%Z^Uf*hIm@ZGS zlHPd_Yb&QFiBIHCCjln|rvRq{(**n@4K-H3`~{-ZTvQNPr#u7EnI@96t$D%X)UAg+ zo4RvcU2eDfFMoyTT;M$5eBc7$Lf|6cVu8N0=w;`tOTESq~8Y}$=y`wO@_sc)2R6YbeTxn@T&@UfF^ce6s@C5KAFiVh^5T17ZJS#{LSP_oyIa|cBR$zeUGxO*rG_85>@|- zYl}vwwa7oX!E1g=(654i74$3LKi6eq&)b*Cegz3F=vUZae(e;SpkJv^1pP`2f;lj+ zf_|lptaA9M*cn|i!+y<6TELi%M{f9;J0_Epv>98)Ez6czx$46vTi379n#baC$vr_U zunkimZJ$7JoQ7voTGMU}M9JdB1t z+^?e5s_V3fC)Yz5BGZq_sdji&A!z$U;LU{iq) zUez&;`9yLUqMMFIX^Tp!UY7}B9HQ|i;+$B^)~#JZk7duNF>O9IPGj}85rv7sPL;glhvrJ_s>yy=>UIMrnS%ah$oYF9+S5d}TASH=GNLKK-oR9^ ztn17v5A2$$_5J&~SWHj-Pw7h~{W~Ss9S9r*9PE`k-O+4vsF!pCVrvW8^lVF~ymh+O zcev!cz!AWa!1n~c9;pb|HdkPN@ok`HARRfGqMDxgpvU@U^@g>D{%0}o%i~q@c(=IRU_zELBIMz(654iWu_W(M5cGryXn0= zWOijWNgwc0;bf~=uu9aDK1v^_PtvDpPMVwMrO(pm>5Fmz{_hKzOT1i^34y*KqJ>O^ z)l4>)MGy@F76k?aivdG`p}^t-zEiQ9{iLF)lM0uZ^+sd4CV*jRFYVeoz0~-=Y*p&W z0;fyl1dXk31vI}3tOyJ@t-8)QRJk&u5x^=y(654irEU=PD_(}6Ulo!4ijENUE6o&N zsn{58XPU?tQ*+udXcTteX8-udhXbYN-U8kR-T~ef@GEG@)qnLqq7O_2wc8Ky z>lR3-s5iCUDL<|*X{mg*!cRhPNzktt zx$NEemA^nizY6-*fB~nEWWrIK3y)B3@`(8R{hw@AD)r6CAF%UqN$8AhKUY_N&|hl}5(> z?t*@mhXR)Ek^RcYkDy=W{Rj@Wk^L&@S4xA%N+IZ1W(&|#L#;6m*2;L}@M!-lqETKk zH5Ctt4`P97r@Adl+qqJs%OYw5qHh5^m>iap?zf|B$@g1Z-1^tQ@nBsA2@wXOKilARLI?5JZew)VF5s2(pLBA@mq9MkXF*UJj#5{}^Io#=Fjck|tu9p-B%Pd0L zw|Yw!xCtG_CEpjEK5db06>&mQCQj>*Obe!k(!y%*dYuE@G>DIK5i0s=a9S)4Nkh}( zX^Hfev}9T;4NFU>Wzw=~xwL#*f#F*TD#XWFF%8c@7|}t}%4tMeC9RrPORJ|f($~_O zX|1$&8kyEf>!$V6`e_4Hel3!l| zy5$~ePYN;=t1vlDQK9H{i*7$nP5Y#M?HUV}kL52PPAXyvk9q*Q-4+jaU^<9`{KDKt zt3_iSDj9yXYWTyrQ6a}D9!z>VC`Tfju~EI%q<*F7FZS>~-76i%EowyAN0I5E$3yx{dL}(<+A=$*=hE}( zh4dl<<&3o#TixDVBjjMAFP!an(#3zzdN^vHJpe|O{*dT>%Rj$j*6_IhNUx=TN{)|( zif^PhRiGc*VMe6E(m)wJtl(j(8w3w4cvy_o!NYnbcv!gn%fc5tta6ld47Bsm$@Iq1 z4n_mtFnQ7K5z%gpYt>tLaBk)$MGMpk`{t;Rt<)P;>a?6xU>tShUA^sO2>2ehywwiK zmOtGFq_pi^u~mmBGQmqa$Ipu;t&|H}HC2&Ul_m-|iHUs4PQcE7iTuFKOHdi6b>H2n zo8)zJVfCe3@UTcOq4o(L7Ax!EVFeFM=9S=KVJp#Gu!hqCYIq@)Yg$RGC+(`swY^Rb zhBlbu45vWt5Chf&)^`PMwv9QUL0==yh9)NWs?-ZK>p;WRfj~nzxbw?#52(MkM)w6S7JkK`DIC(kp?Sx zSmr#GIf}u<(iACErWVbS1}k`23R3|sYZ>QV$Qo)Za~Y!Da9xMjwZeQ}h60+GD{{&3 z`66Sx7dkf3gffD@Q|FRKB`WaGZB?Z%NhyMdWsMj-ESZvYXy&V% zNP`8NA<|%pI8c*KLIaMD41?qntQITdyLmnC z0qzCv1MUZA2$)M`m&$e)Iq48}ZKjFk1|!dg@*y-I1|9((wMrdv5Zm-|E0MI$mcO!~ zXr`Wp=2NaIkuTrdEVKVY-7~tnbXXpqXR`9S`_5=@0OTV^7&r)>9 z;9NP{K%1bsmyKFcT|ny$yBZB!qe zpIXzKAOrn3{R)K^Gn-9#@8u=^r&66_ zrJ~W|tEZyA53nz=pI2(hrSDEw!jV*8TcQy3D_SAaU9^ z?&Mj|$v7uN)|z5ut-A8@RACQlnvnJ}G4T~NZSGeo)h%m}=34)tbTdBDiqg_A59F2y z0S5zz0EY_P#H`uuFfZv2n(4k{C2<>!bwD^?-R4La%L`g|g`=t)5H~<~f_0ytRdFMj zAdgmkc?@u@YwD>y4=H(jbV<;!29(!U%^38npkD?3D$-y@8Y~5ui8NT}7#oj3JMsz$ z`jre0LBG->>~-~vNP`vhtFl+ovO0>)#$s9~G5eq}6Y40Vy}pq%9B-mhIR@CYx{l>~ z`AtNd17m?LfGvS>0$-wQ{Mic8)-GyS(fAr&vR!UR-S$d;HV(U?Imzm3O7kJn9<;uctjM=6Fp5&2Aj%CsuU=I9bV3b*EAg=xkx=(*s^d%c% zo0a!!Q=DDBfjU;lh_$F+t8~=n-72ZfC_}i(P+)Oa(6FVi`U;{Yfu(?9z|z1nz_J2v ztp|~fXL&>`xJbbdE!u<(FpBRmoVt~)PKPC=UmD@1o{If)RWAkoik1rc6;vujbx@U#1?-+p{13my?n!m(N0G(et3nH{Y;C}w@q9Vr$Gzp zcNt>d1KxLa#aVNTgR%|hFA#f8uii%}eGGg8dOg?IKiZiT|^mII6_ zpo8m{riOtq1r`Jr0u}}q0fK%-D?}PB`g9GKi*i>QWH(@vfSwg;u(ZC?8tQl&%=hCsn}_VPIpne!{+r&L}vkg;B4R= z0Y8KCllnnjm(W7zQgncRDR3EZIdBDVrGQ_&-d57`@@hmuzhc-e ziWWXOPtqc@tdTf#RdYX$DCk#ntx*&rPRRty&uEmOU-2ph{VM2J1Ii!3Cix+7G!XQw z@(SAFN+8l;1^vpbXhgN?m!Hrnf_{~EdqKalHEz(a{%h!0WYCE;Sdj)R{V;C>MeFOQ zW74q{lu$qkyMCOGqtH;?&we`Im6U4fr|D+5{^0chn z;wERLGbt$WsBY3vXXlzi_NeqrJ{B!;Hu#{gk-~ZDd=-jrgLG0Cri-#l+k&MQ3g4u> zXqTqTQ0Y~N%1ZfV!B2aNMcz+WrK{6)zf9WKq-!ZC*_7>@mFYmz-=^QC->2)+AGnj; zQ}t#4>(XHHZ%6j44*T{MpptwQSP>X5Q0vrXE>-2qh(-Xb0FnJF=vV3nLBHZ<2>Mmf zuY!KX;v}+P1^p_Y?gafRvR|>X4*FHluY!IR^sAs>1^r5X96`Uj+X-lmu6aKP{R$Vn zpkEEcn?AB%1^p@;q&qrvDyLN3imrLg$q?%vukxRj>)gIp4`0axMHO}V)u!q)?ZNEC zv<{2sKo=`Oh+epZRVohw4z1L6fMG`rP2B~y-$mst1w9(70g z4eCY1C?LxID~G2aQg<|P3~(&)BjCrtallUm{JSEL=($g@QqZr;pkG;6fK(CmD?C^~ z@i!&tS3$pG!0h6FJ{C?x(691b74$1529)oBrqiHbb%K5s^ecCm>9joxf_Nlii7ka2 z{xD!^U>RUpU^zivi*`7}TER>8y5cUBE21zQSP57e7$HDk={WOSS8K?_Ca<66D5Jr7 zb+2zUSZ;rfOV%`zIK@PRTN}|xU>#sxU_AkEuvYYX)(sGS9oP`40YSf_(Sv?fQ*Uz` zWQ{QM$EkDV?i=(gy+4utD(F{1zbaRUHn4^ukC}}sN_Z20zO|@Z+v^mwNR!k$h}H$x z1J(yN5HKS(8&2O;d=E`cHR=kh(-c_K2-HB-1X@7bD_bp$PhCVkU=*+surV-N!2K1J zTo$iQ5REaBHaQGzn|VoVI?bw^qc9fO0@xB52aE@{0=5RW5%5p9I$X6KqV0hRE|2V2 zLBDF|EVq}@EiMOwe)Sm5@Hi0ktDs*oerk8)M+;RnkDy=qgji^HqKR~Rp|hAR$^0}9 z7;ovHl&XVpfm>$Ir`;9GCZq`7Hc`Ye5(z9ku;Ku}nE#rSgm~`-oOtXCdkXLB9(6RnV`3e#L$@=vP6%>JU6S z=vUY#f_@eBtDs*6{VM2JLB9(6mG+83zbgMB23q-=(a=bxEhAOXuY!Kn6~!R3U)hmf z(692rrnp|^iFAvTjDAumcDvKRbOxE5N@3A8uS~1xDQ$RZzwlC1fu2#)rrb}FJ1s_= zGreAxa?9(Z)rpQN&z876$LmD>F>hMM*wZEFy13S?d(MX(l6J3w>8T7Ir8ZnWZuC4nL%S|U zT)91$OsJHKhE~lxRHZtr_#IK02<%kJJ4QJQ`jy`ApkFnr-CL(h-`Wtvl7(W>uY!IR z^sAs>1^wy>$TUX+-vf>Uz7GWbD(F{vm8VP_azcKTJ`waQGQ?i{4Ze)V6I{R(P#WWS2+SCRcHvR~!7Ip|kfsYUjy$bO}65ZSMSew7WL z?abT1lh(LPkZqv#rW{W0sY(rPZOZ#lxF47SJYbczqTQ0}OhkWjkt`=pWo=gB<$7|R z(T(f%9vsrg(0&|v0(cUb1v~{j4g6WaCPFcAbZYPnqGw&CeT7+SdxhI>b+Vubd;z5w zftOrUF$J{hei_kh7j>F)>nZ>4B{>2~A?Q~@zhb`{^sAs>1^w#Ufj066{YvMg#Hx9^ zYLKF%bLPKTN$HEVr(%Xuyc(TY|5f7hIpBHV1>i;CCE#zs%fM^_Gi;ly^5r_w&L3KB z&1U5*D7|V*q$D((Vy)=q`BPqOIF!DQ(i^~=z+1rEz&pUZ0`9C6cO8|#kLUvv6|GLo z5Af?2NJmpCPOTqTm$ZBNVQ`7cib1~$`c=@cf_|luDY9P${VM2JmLwS3#gf2MK+vy( zepRdca!@CIS~EuWtDs+LSMY1&B55g(*XnQQm+*xBJwwNJCem)g4P^3?HI7)TVeAC? zs}i&Nrb@Ba)3vvFsnP6eX1-3Hta+yUGP+$CVML6lAQ7$jHGYX4pn%SRXQjr-A@ z;hN1lo0$g@&2%l9MQnqjO+ns`u#3=jk9fWICg!87S3vut$4$%*BC=ma_Nx)bItu#L zH-mnahoE-QuQG+2F##e1^udDPKL!b1=t&yTJgCG zZNJi&N?OjATz4RF5OAJuvqI_ZRyJI zaLIRpBY-1;?+NIjN@!{^kafjC}gB3ii;9+4I3m#VRu!4sbJgjn7MN0}EmQF9^b2%3>*F4}e;Pa||+BF?E4D7akAe@TjusZOQqj^GMYas;{8?v>gDPa&y&_u1MW*U?o#f&@2e&BV4`LvI7|X z)8eC*t04{^R`9TbhozS!cv!*13LaMQu*z0N!05`Es_dv#1`jKESUUUFvd=S3Y00Oh zUZlbDS0#8@*jI|W*7Q#?UOa8>Qpi=n$XcRySyT&g6tpXN7Nx(sQcISZe)&A27fe)B z9tiQtUPAOY;ALQTRaqzuRQdO+)UZ4d1dNjSRW$zryk-hTx82p&;B_kzD9VC7Y3pEn zjz+hu$9|hj-Z3S1C%WW4MDGJ103QPX0zMMp2_Z*by#$}kFNx1q&Ou==Fwf-;eS!Oj zDGM9d>E)5;fQq=&!~JU@w2cK#RCMc>=S{B2RTcpe=<>C44VLzz6~Cjc?G3k-RJ)`h z++--QxGQMb(pP;2(UQPYz%XEGU>RUp0rwDXPYtm=q7__JV*{8Uxz^CnHk`VZtWFQf z<}i3z1Io>4mf&HTJ7n;%h<(#9gNMaiafb~Sj4hVAGSXmi5D`2qCY9h}1rIBDSTa7g zZGosn!udl@*~zrpI@xJmou*c}<*873rU5@Uc~OwWtUL|T=`Lz_dQv?T(OEzrI2$-e zpm$CQgnjIh4P1-YbE!KII3KtGxDdDqxEQzuxD>byxE#0wxKhAttZc_xH(rfsx{HE` zrKRzcw8$)Lk>Fw3)<-ctw0#L4R`9U?FL_u&zbcQZ7$_~<>?^&nEE){vt)9YnmdAO0 z(IM;n@hX)km`LG&2%`NnR}cYN8Q z9z#tWXL89|K!3j6LVIdHz~J&r6U!_^WbSj(JP$bE<=Q7oE9h5wR&L61Ik!2cpMLqU zw~_2nvg$+{EcOaPzcK@0(692)*VOto(qJj?*T0i~B`bBL!HP6kkp?T$VCB_I(62Ne z2mLDOSLy~qzY6+QUa3YJEIPug0*ngXjyAY_XtjLHE0>HaV2#dAsj3wXt?l3BvbTV@ zfp>s+f%ky-1zDG96y=9rYUb1=AEEGZrBEmR$)||s0CRzPz-I#8qL44RY?5Cf8i4ov z0>D6EL0};PYHi$3_#nRrSuO@qw$qGQ*7WV`AzB~U0Qfqvp+NVk*SkGw6o~3T184#*pe^9*L<(@1e)+%T zCJ6eK^#zUs>=n@Yjm&qGX|^fWY<1=1aV|xH2h={^nu^D*ezISsRJW`>I!N{pqB+B}0P_NKY)eTyr zTF?^|QrupMPOqt39x%< zj!_#La{J}CsN2ESYc;uz=UD+y0gb4;n7EKDshVatG$#SO1A72_0($|I zfhoY=z*GTau9i6FJ=>8dxGikDjG_B`y_kF|9pEL+5a#{cEvofSPb)h{QaLK9K@Ks+ zpkJvif_@eBtDs*6{VM2JnsE0p?t~Hpxkp^kub4H1esztLYHCevFp&mp>!PWM&t_i< z`c=@c%ubPQgRI=uE`ASp&Q%U zurbIfWu5N35!Y`FjJBI-4>Lb022O2bsM{0>`jw1fZI4DD^s6H1SG*Os13|x1=6f|n z9#`rfz&+?!WiL6yrHB}|>{d#kpkL)phfYmagN3p>u!hqt#8&jv z^CtV3wWwR$>vU3~6ODBctqZINtPgA;pbIw}PT$n_NVl(1S6H34IlKT3L`|Rtw7pVq znYw8gQ4bgeYy@l!j23WzIfUqa*aXoS6V-IerQ2@iB~j|NzuO#zvA`Cun_NpLnR?}J@sf@l{pD;ZXBl@P{HT3s z6nX1KcaHC**YYenc~X2Y?5GnS!hl^eaq6@6jgjTbtnBqtPj{Uzzui z+zo7z6!fcXqzn3$UX}FkrC%wyanP?K`&DGWitJZ@gwoPMPI@Q3o8DucRO>=b{D6;* zu3{r*S<&qD(?{v!^hx?O%}I09y!2W6Jbh7;?zUXOT;k=Tj1S&|h!!%Dj^c4aUIft~ zU{PQ&uoy4|7z!*d;Hz3K^YtQ_qdlJ_<}@b%cdhV-p}n+gD|n=~_{&zMPR$Of6#QK~ zvK7$$DzG9j+_dUCr&8t0h(-Xb071VB`jxst(64wIBKuWjzl!WvnhJw{74)m1Uj_Xt z=vN9!=nOPb1!X>cy5gf13g1=!#Y%F*GLNmAm@qN}{#D}gIpBHV1>i;CCE#zs%fM`b z*8WACtJnl6`j^?wT5YI#ub}j*DKRL!Wml}nY*p%YvHZS{(i^~=z+1rEz&pUZ0`4pW zrA)~0Bl^HZVi#6?oVt!(cn-M&>4qOym$dDq69aPIkp%rJvR_5^tDs+LWD5FK(654i z74)m1UujJk^s6s(_h?akg0sk8~3%vUn#SGFCK&!@Iyk^L&~I)i?tUHKNy zyJ+SpKjWaIj5m???#e8g%>zw$2onoTi|}nx+Rl|4UDAk`> zRPThs&cH6fuE1^reTTGRt?h0l1^mG2a!(ZY0wx1ftdg)tI`*83Xdhr-U_W4g0Y7cG z-Sdz}9UW?xrHO-nHK07hnvVlX<1I;8UgJ{sNb?PN0*nDR6)l_)Q3=Xj zsoM>hWC}8|DePsr2ckVqR8s;{J@RBkQ-HmJsa~lW(rzfCw7!2o7t8xp|5N%>N&imC zbq4|m0S9}fg6nD8JJd@GKxfqMCegKcQYA0dt-ix0-vy2Ujs(6ZFpc?yYc;MU3V5Xx zgZytcVAvdOifVernJSO<%QWHUN5`zF+4MLUD+HFB?s%2T6M&zZJm^5DVG0f+HzH^j+R<=y*{r{_bTuY;5Fc% z!0W&pz?;BZ0(EaiKY;r34x)E~_e`!hb#NU%@RDK~*gM+E(K0_WvFH%h0|xynj}_fs z#oK6UbPf7d9$bTd1=-|C;CsMP!1sY406zqd1|s`a(67qJ=n0PlPXJE>vjnG)ET7`@ z)4-nv3^-cX_dIb#=Ht4RU_rlfma-PB zHe-nA8uTlzI5rW{h@LGgnf2_TU+I1Nchj#FIX$vpK{45ezS(Rl@^adakBv+`nZQRa znTvkfA%ARZb)P>J+E=EDX{WSv+9mCZNFBS`Pm}mqbYx*od!#)nXdA4;!+Y!1^p`MS3$qZgM-$d3i__bprj)$ zTgGV2aLcBGFDmdmjWrG!4{T-X#QBg-Z5u?}ny98h%n5Tj!^Q;azU6f?h}ekK=wOT6 zk-CXq*J+bxV`oIWxJYX%EhKhBGzr)p*uyJj)znILFE7cuD%B}gl5vIbBU4e|2iOh^sAs>1^tSZY@H!_lrs?;8twb##*i0A1K%(?77I-f zV_d7=(t5Pq%u70@lF?yv)W=rpjVfar$<)em)Qxv_86<3e5Y5AP(;dr=LWEsC%XY5V zsuQ+qf|q0y$xB~N7hhUEYX%om5z6V_5;CpIdot)(LBIOQdxZRVwRinwektfzt2##~vR^?! z3Hntw63Nz}&Gw<*HB^$F<}ljla1$xrgfY6{m1!e#glo1N$}W$As@CRg>?khzzF#8e zcPD|#M>#9W`9Uw^F(@4i{0R6la2)Ux;CSE!K{k8!%%z?)GhKNibtie9vSygUwbR66 zbt-k!tWJ59J(F^)#cAPb)SV6l{Ys5+D=iW9E9+uGztZ8!POoLUDXGs095g z=vVn1qg(UrHI0T7!^DcyR^wzRxpbOh*p;WMR89kaUUehLbLDA>PIr+`M5KBqqO*WL za5iv`fI}1U;@u;r%i{H1>dphs2QC0E1TF$D1}*_E1ug?F2d)6F6flv>*ITdo)rh9M zNa=jcUt8yq_Cb=0lIAoxB@@lZkwr7;S3$q}obK}lFaSsW1%QF>t>2ROC~G`CS+wF> zn7T!PL8ef2yK)3B2fMoBV5nygL18GcIIx6Qsvo+mpjMmxaw!uNp&&0K>q(!#GX^lIax|M*Hff1&qlh(?qwct24=vR5z2>KO$ zB>`k&A}J_Y6gbAfq+yfCSo z+m#$>iG2Hoi)+=IMBctyW(_2T(1O51z`{=SkwdO-KgdgRh|!!fxGE{Hhh`YmhXRWO zOL(Q|6RKR&N)YqiPysuQr;@vk%|N1_8F{(e^CeMNE?Sk2JB$VWD!aS|{i@uz>R(M9 z6!)jg{oCnRwV+=`_N$;@1^vqRRFVBEvR`T89`viAUzPo!UsXmcZ9eX#HSQ8%#}dy_ zqI;@R4xV%$3iksufCsEn5&VeCITO*JT%^3=#-*+iJ0ou?ddjh(4~j5G3cttDejIoL zcoLWeJOw-r{8_-2GQwzI^9-VAT_l%%vuX7Tx7}(JqZQ{1D7^^0I7ccQ46?CWWA11^tR+f}mdo{i*{6FX&f#9fE#Ui|kjC{VM2JLB9(6l@{$mzY6+Q z(654i74$0^5QBc@q>@I1FxZj(O8cdtUy<(S@t|J?{mN{}@+T=rI4PyqC5&>=uN0z& z>>p!cp#=RZp9%c$pkJLmXn+nC^cOrVwZRSa?;C-efSUz&4n(G!KOzbqmKx#j-Y&tz z(wG=Ltb7KgX)<_Nkp?T$V0jX!B6wJJqIy09_b7N+!NX!9rO4izC)R>Yu(q=XiZ<-8 zbr7u!tOu+QY#?Aq)@)RS#u{X>8g+%$DT{(a!Ilj~O`rv|y|UFJCt?>-4;Te(1Z)h9 z7TAuDFyNaY8e<~ucF6CynU^{(h?twBFc#PX*b*2Aj0d&?wg$El@V^ERi`EDpR`9U& z3XA@kJ?iA5r&sA=e?=5tS+Cin^poIW1rN)8E|rIt@l*bi7J;UwbTnBazepYEj)0-F z3b3j%cNFv+`tRyil0TdxA2Y5iFouTzHPKwlHH#)8X+|Pi2Ur(auc~ZW#$6qolZO54 z)NN>WN^C|e!WV2CTsvX)Vxp}15i7~Fa zb*nm$R8v!O5a)2WEGCHZ))k(QR5_=$=kx1zY+o@m8rn5BT&xuI7G*@CL^PSUD{&$E zM%k^tt-)?^luG4Bm8hvS*X3w0DLIt!#uezqS00V(L%m{~^G(6SQX57ZEP7I;!HP6k z!NUq37W>uUVFeE>cv#n3lBnQeX+&srv{-z)YLG(F_R7ClNj59be_C|0Ed7=ASVc~xH&S{%QR=mQfGmd`dqGRawtNv-a6!;h;=+P(ZR%3JM`1#4Z- zXXbK~dBA7D=kwKZwHu&pQRM=_K=MY3ZLO=-ZVOpS5u&uz&ksb}v2su)?!ti{%yo+a zLx7=HiRDdZ<|V9Dbg{$bcF5V(mO^t_rI~jO%OF}7SPod;DhmZtwQ$vqCZ@y{sT&Tg zWC{vEh$(M`t1BU(HIL#=sp%pOmi4192F~#`+g8BV)>?|zMIf+k5p8E8?cPLV<%eo? zXuxk#w}Y!|K#}^6h$gyv6;ra%S-X11E+*Dt134gfLvs?aJFo|^C$JYV8JGg>4NMjA zy$U;N9Q{tGGCp@nf49Hat1GE=fS1%!J(s$Imsto zHrZ34aZ2e8Asb9aGzHijnCg}F!ty5RGPs@lxwz58K_z{uq=BsDx&wiOfP=kKX$EB0 zI@C+bK47Ne=KR5}Ckuc19WMDUa0GB9@I3(!C_j^ImzG`KQYOmLRhIAk>`KJgFON1w zk{#%uJJv5#QXMl=%C;_(=y5KVi>k){<5en80Dfw6wT#mzA`O=9G?aHpONa708tD(f z^}r3ljlfO7&A=_dAAwte+XVi*+5Dw+mihtir0y=@Zr~o^UV&8Q$AlgDenc}&q_kel zl@B7C=~~@7!Dt^s^f2&<%Vo*dPx_dZ)LrcKr6^i-jwjKaWp(v>&eHibqCdO3j-RwH z3i{P&G)mB~@~9H@D;=0BISq}Wq<|XuzYY0hM_?kblOR|2+WF{|K$3QJ+N>#AZmw$M z?KlbT-GM#)5^)6b;gyDPC88-Oo0z4sN_(R@71#&Z*D7^F%Sq?{h!SuBPyz=62LT5I zhY0v`1vRvjCOIqW%EPET-0SrHZb|7WKTmlCbwR%h`c=@c*t_bDc#k*YeS2FFX%hX= z-9h2C`l2MvS-F5w zeY9PMC$u16SP>X*T6Ha2RJk&u5kSzd^d@Lli!@k4zlt@LA zkuKKhmX=0GRX1pfYN0z}pfSsTg@sxKVx*NC$xEHt&xF47SJODfh%oH%MHAJD%nV6ModJ=upBPcxT z3Sv;%zoB4l`Zu1S?nz*lDFpp$>qvtYX|N&J`6kpJZhCVTgd|W zxRr3Fa&O$OZdJ}g^C{PqJ<$AMi*`$Q{|j}`0MD92(W;Zn?m0xyyGY+`^o^ij$t41h z`GtW+fI+~bz+hl80Y75Uuj^sAs>MfNKn9)o_>Y~get^ee4g{PaBN zS3$oje*g>RhrrRmF%<)atS}sWw|cfX)(5#?l*f5}(NVC$@^~&e!9?V}k?3cxAl|W# z!B6r!xk9M!6x2@zrd3)kKjoKSKwd%1MFXG8)BQT}sI`_klS|G5`t#)$(NpwQ7Tmuy zG2ut`HRqyv9&o9kB*HZ7NyPb=^+;zEm$v0@sof(Bk?U`Z>d5owjQ zYFaI=p4LcTOKYaJ(%NZcS|_cW)=TTB4Nz4uYm0HwE5u_1}9-@t5Z~4GF~r>XgOecU2_dU?pH>0pqUL+pHDGmM4S_Vs z0;7Z1HNDi$)|a(W7zwQ7@>U1h^LmKZ2Q~n{4s0mUed_ft`-uWk9cTbeparxAe4TQ# z*fv$RP1`~Q{Yq!exdnrMWt~_Zms(v6sF$N~1#l&Bl~*c{sVb*i35u0U*Pw8%i-LX?^sAs>O$+)}(654i zrO6@aS3$oD`c=@cf_|lCdeEd5S7p$zWIvRD!*KWrLBCRtX|0#X&=^6# zGImPPuLhK7cvBS0INmSMqI(4Ws_Gt9AgoT%uXIAKTshf-jH7C{>(VMn$e_|M->_CI zl;S(PK`E6zw&ST*KJ=dGlzDqOl3QFzG}8cosY%9jz%c9C-Z*gCe+tDLHGT;5kudexQMIUD+Gi2iA! zqSJ&P_y(dkfwxQ!g~&)nN^@y0Ns;|3Pm@8v(%Pc|&9oftRG@CJu6JM)FSS}0?>Vwx z!Gub{0YGW(^IuKBY6kr(=vP6%3i?&huY!KX$}_TGY3&^JD_(|v(66%XtDV!P-briR zB`|XsE8KgkQnudRhr<294B!E)lr@C2=9!58S-_R84*C0@LG-MPlrd#KuibWiMO)`pz5ltNEr=$!{mi57V1D_T&v#dskE7w zWPQ+S=H{r6t<)PjYo{YCNP;@@IO@i`x(pId{Ho&SDDFf)7gbmyxMX06xWKIm7G{VM2J zk^PF`G1^p`MS3$oD`qhB)Cqcgo`c<~j1^p`MS2|V+ z`jz~J&3G5|t8DPhrpD5E8$rJc`qdxd@!SgB2HXzZA)vG9fXGgYf_{Z}WYDkZ6rHx8 zoz&Z$t1Km_{BjtuG_VY?EU=s)ccKnq(N^%1Vr|Q}b43(}11kY510w|J>mbpOC+iLS z&=$X~U#{-;jfN7Wm0#nMHBAIzN(U@!BN_>;1FQ?IC(uoa)~#pV08!AdbPQ$9QWGVx zItL?h+^)3GZoni{fOaGK9*FidQLWbI>~}JvDZt*qRIjWT9`0Y619haepNn;xrR`bz zQb`f;O0GK)I0!h{E9KfNv(}+rQUE$TLu)DtNItPEvTyQtxa7OQ5x|ka_XKnx@ms1H zU)jqf(Tl72>Qsp_p>ICg6m>pLzdF`0Q*W~a>~4)P^T)YZW1tSBk5{QY0r;uO)iTaQ zQuaPSFVvBJzdYHm>ogV7zC4vnrU5_q>y+S6|KDkdPIpnegWLLI}%E>i0_?~r(e z-dsz7It9tDs-m%o_Bo51p~qDU5fc{5YP#Otft+ zu0G*~`4pG~%mwBN^1`HU>B>atAu940F0NH;l6teJW!6CGD+>Y(0SgxKj*pEl z(g}Q2!~$j2+97{zi%pw96l%FNG3}IgPP?RC5s6pW?59b5EIK`1yhqxTg0{gbOioi& zD0q*nk-IArZDI4iO`B8q_12g8!^53TM{$dqvWfLm(654i74$1e2&(|A0;>V5 z3-ZfU*Xvn+%}NSDLMW}ZyiUV|hWe3Sr@2pc>sEChpr$6LbYDBP6ct6c)C;RTgWOv~ zjjpKq^~yBj7SCQorp<f0Lnl5&(vg5Di!#q405~P-pM=DWW;RTwosXnSimh z*5jr90?`17GYbF%fdzqu1gNzY4Ka_s+Q@0397Nrsz+h9TDNVNILl6yhQLSy18x7MO zU46yHk^PEvyPCIxex>s-I?NR78A|9hf4NPF&3#PFx?X#}{VJupR_=6uy*l=x+pB`D z)tUDX6R(f#SNtHd2ia0i$JMsDYs=b{e_t*0 zG@M=M&84ND4V}vBoEKs`iFTt{y{*87L9z=Oa{fu6h2;kkyphpbf7ljxfsLE%wX=r-K+r4;V^H=dyG zNnn;KME0x5eihlTYC*pW`jrOnpkMuup1DbdI|WO z$%}TEwg2o&tLqyeWxlmpzLO&dyyDu5NT`YQAKc(IzeF}7iC$Of^pSi~jfu5<6P34s zw}E$ncLiv$S;>2qqD45252*VP_?IaZiqEcFevIf7;8S3ZRca$+#w7(^lxI)=*Ociq ze~|l?rt&Y)9w3HDxd1TGxgz?Hv<_Sd(ZawYCdaAHmX%tj=xGL1x0uzj_fn$`^%8!f z`MK-C!wMdjI#Z;<@;5`4UG1Dsuo6zF_CD4ctlv+RxID@0GiEv<;kbpDSNQQIy6SzyDhAz4s`|+Vy&>;7km_bcr-2G_IaLuNC5BlYUh-SK$egQMD>)G;8 z!l|9Ed&KL5hZQ`m;9=?I3LaJ-YuXy17~SR0q|r2ZSkR452O$U&oGxbt08+iev)6OZbPfX)U10Ii0VKCXaX&uEy(NSyh-U=Ne7o$)JJ)# z)^awQo>u=xq`~?hz{BbU4=d7O1rIBDSiYx%t(@LT@22-O+H2pVjad4Ck2*y*dsPkY zPx>f*oIXjPra5VDnwLIHpQkTMd|S!|%r{=!We7tHB3j5qI-JB8c@ac|fJK49z+%7< zU?{M-fbY~1vY%8mbyDFHn=<7HudUoLw3l{mO{bc5maR%1S>SX@A>xwex)sp;DzG9j z+_dU)cTwfah(-Xx!_u3eUG+DuefR}zpg+GZ+V?O2#gup=wNQyk-CXq*JZ@{+8pQk`NYc;Wh=rlP(NurIKmS8BRF09*)M1Y9g& zG1wypP)t(654iRp&@;Bs_|BfOUcOfb|7hE7lb)ud;YLw@ev+^`6(PzE)E_ zrhZxHl13#eaBpc}4 zfgOQ~t|cCemh?M&N#r|YoG3bp*5tdPImzl|GA5FE(678Xf_@eBD}~r#zpFs5+I&84 z9fKW&xu-Qn@0ES_S(N_jN{Y;=H|}{vFPMl> zpBgG&Li9J_WngwyNj#$R?^UT`P649+!XJJW&3^!|nL^QRcQr1&ZY70%Q5Fk^8RcLw zHwFdi&||;NCGVILegV4VJw)#V9{?W${{lV|&>+gAph4x6`6b4!IVj8p=DA#NkhwND zYv#u%8Z%K&2e^;EMo~5EKnNTQ&Ue%|exbtOXvEHKFWy}KAm2i1FY4FIQepLy>cC(K zHyH{n?h5+N^i^L$v?Q<;Fbr54SO!>Dz<20D)DX)fTERuNw#V+(GwWv?PTfjYr^6D} zl_R{=Q?XyJ>ZQ7}Ey&@+N*cA>y7AY%qyrc`*^;Zb^`Kry+SZ_&fAm4eTKqff`W2eU z>^D;jYDU_?#frS5XWCGuvgV?0gY&RDq6W}(x%yM?euWG!_Eqw}w3bsiE6nX1KcZMrKte$T2kJRXoiV&DvD9yK}0iMOUzkmJ%s3C z;1QQ=RjwcEF)I;GJ})K3q73>~{vF!3>(gGLXNznF0oO`lt~Xeu!Lt4;PMEu?HQB$c z1vP7J=N-ssrfuyyh}H$x1J(yN5YUC24Ns$|?U6QnHR=kh(@vHbpn<3fw1Bo(wpws; zyNG(gC}1OCV_>v^`^zg%@53gD#+XPuI`aE%<|T#A(mcO83S)sSfGvS>z<6LQU~6C- z0iC1O;i~NrZ4XRvxonWWG4Bv9=iAin2uuWaaxHntnRio7!E^GSQIusf1UA}4ou7pE z?!X>?i8i?QdMb#JZamqV(fy_t&Z}Pl?Z4snDyf0p~>&UUCHmiqiY= zGNRco(!$g_u4wx9ZpxolL(MBFz3NKsY!7-3(LYTjvyH+umv10?6L`zyyomPBD&}9F zs0kjR|NA|Z-Zv#g8l55ymbFw1t~S4I(64;7=Rjw(in=9tYt2AT@{(J&E&nvHO1!1S zE}V%>G>v6H~t%Tw!O3Q~xg9XJT(qIt< zR?ej9m~C`kW{ahka zYw60uE~C(^4wV&q!PbR6ttI>Es&sXl?w3jXnshCN9KkhzV7Zunn|_ympRP-P z;7$s@qA$B4-I#7dL&@4JvzCsM(;w5V={DqAH0$F#t-x;Nd2SVM!_U`Bd? zTWO=IOJ=4&rH9hP=@F~fiZVTx9;YBrCI4^RqA?*+2pv^Fm7dPkBz8=HNzbHbO`A4* zEj=Fftf27yaKP6{Fr{Wvw zO%<4_ZFi^G75cuQUqu=$-{J-RO4Iwn6*r3wYI&%Y2pOZb#$ixX4hOzdX|*-J@aoyQ z^^w$l4>-ydbY7{2!w(Ss5I7n*1~?Y@ks!ahb!jG=B>G3^)-u zNs!;>oYnpmM5mfaL!}=x%VAxMpkKIHJ8vyhPDk?$6EVPO#TE1`S!LR0(}MF$D` zm9{HEzY6+Q(61s5R-T{nlI26B!SV$Ql%(=6PG3_Ft@#EMtz-TQbL~0cdEf=$Mc^gi zZ@|mIY=Ih;)Falq1QgB9EF!;_F0Y{Uswv61Zz%w3I=M3|Td#{@=yjCd0Nw=N0^SDR z0p1nxyJ_2_)zABgJ}?npj<$A_+nsHj|Q@fvWh{l_UV`w`Em6_gl>^fD^B79qv zwsWOM7y7~kMBf5-FuB6^YZFuM=vq4cm3?9-6m|x70d@s;6R?p}Xn);$cPrI;ZO(o6 zL}4#rGBCv|MNeZdI2F-8z`nqK!2SY$+Mr+cd@tGJ;6LbBSP=0$5Be3aNzktpjn=*E zgML*vzaM;LG-9`%w4pe@Ds@$g>{oJwryZsMdjmng!q*G8(V$K#Py0`Hkzdtjx>D?jj(Vj0-kR;N(H>+&NLE6`;1fI+{?zg%R$3i_2Tlim3>=vTFN z4$^fYgqw?ii-E{~74)m1UuBmZo4w_-AM`7&I5u&5ldNP$EEH2od#Ipai4hEgtE?DY z^(q({p%z(u6fH7?9)i-LuGHw@sc{&h!%b9c$gbBfzw0HLvh8B+Tb;<3Y1~I~$@c}P zPg`VLIW3875%jB|U!@Dd!|?gVli5os*(bR4xTyvyuXkz}#KS>$IcR zso_Yk(?(u(>sEDbAAJj`I=o|zmPK$>pckXh$%RyDo6DMCuTYOhn-fo78}f#Wy9Bt@ z^(1iC$ltESWFjlO)weY`7aFBfxltv8NLY^clBhMd+t>79uCbyd`v=|G{OfWk&B%VG z@EkPcK|s*2XoX)|FB1J6g8I3L&NGo*2{<{wz!k)iwQi;fMOLkg(Yyq>6u8W_+Dewv zFRws!C2$pRwN=*SMQt2+If+W^8tSgKI$We}1u4I5J;-mV`<-7$?B#xWotMP7*UNG} z3O4{Z0ykBadIS6AEml%qHPK$nTT!^pL_xn|Nl@>oSze)8f_|m#O3<%@eiihqpkJ|+ zQ!H*@(`k8_*G|g6nq7eiK5eThE%P)nUgzW;E%nSO)K!4Myqpt{!Xyg8pn2{ls6aOZ zw^V$ed@gfqbpwJbl((aBMgUyODM3-<(dPXe<{p;pha&7Ss>f^6%^Dd<-N%FnCz$(~&U#8D|1 z00tUc1=mZhTo!WfN=qT)tpCv7<)BL3W$qo!b&CN*fT32Yy*i#{OIV4sLJz8yyU|i; z4y!ctj$s)@%L2;*%UdNO>~kMhEFt>Biqs7URx$<1{_2+_TwS3qJ+grEU-W~1W#_t) z{VM2JdP#zQ74)m1Uj_Xt=vP|X1pO-LSN-y8H9{HLuiS??vR_5^E4Ee@4=1u;DYGM# zi_L&PT!lA)fL_xpGMj}}YwAnt?+NV%ScACRzpToV$WIVFd67kBk5jny&6+X@k zRJAr?1CQd8@B1Z^w`EmtpjJhU!*wK& z-9@i3mp6RZv{pTfDzaY%{VK9wMfR&~o2V-ZTK*99s~!P?f__!*>)fbXvnB)M{xG2u@NcAFDY$LW zuY!IR^sC5zm1nESex>m^=vQUXuY!J6_F>(e4V(i6{c1pYml`75tH>r+-cyxw@TB`_ zr2ByxzynrUQ({4>&P4Pl7b$PJ`CHdWU7U9bJxhgHulJyvJ%;w^TVFhYxUpjihRuC7?*TEVmswSkVyb%EVR z_tPoiDC#x>HU>tU7Kys;EK$k6b(=BNZEAJU5%t4<(@Tv^LmTTQ5w3KQxaF56X-4*| z^8cto%EN%et!b2JT&z9@%c4!#kRzx&68N4gD6N*cPAI>Z)}23~?uWq9uAo2+`elx_ zl1^8&+SUE)^(H^-acKU;H5*Mk=B>3FcG^r-2z}|#P&yGf2{;)z1vpipdld>om5+|~ zC>HvPQ(-OkPDAN*SL$^uU&b8t;VkOphE3Tiu zWIA>KVRZz!(W>U!s#L>``8QRGK!W<}TBC|}taB9$daMkGGGhFJJ6#Xl0Ne-!{mOnW z#sAUI^)gKo^s52oU?>xj{mS@7MbNL5-@a-Kh1^nD3;IXUuTG#DemcKpf_|0fpJvT= z8sfVI{R*RVPeH58pkD?3s$2)Q*1EuY!1}-jg1lmE`1qlWAX;eGs4J{aV=l*g4Ma_# z1+=|VZ<&^XT|_-#6tEGnF)&)d{k!?ZU=u`ROr#hSg5ONuA0p?z}{#sXUaTLR;N z@xWHV*1$FbR-5wt(N)_a+8&tT@}jLs(s?=BAp_gDsoN2l2<+rq3dL^w4IN-wewb!W zK^pRPZGz2DLVI^$55I&YttcpVBnjaro0z4sN_(R@71#&Z*DB>UL!in15hdUNpac#C z4gwAa4iWI>I$E<6BR!z5JdC=-y-wfnmXyeT71^)o88fYCXme)!!=PUU{VES(LBAU9 zY@=?_ugZO(S^f8;U)7ZTJ?K|KzY6+Q(692!JLp#$r-ObK^ec6P$bJPaC+Jr?l+&?X zc_*zA^s8F8(xiQgXbvzJm9aqMdCvS2i}-VMg!mQ>$*KSe`8#$-ckgsax*U}0;+!I%~2m) zsW+<5L%%A=Q8(Vz+jSX1^(^o`JgP~@y!4B1gT~m-6JtAmCu&5a3V&|4gk(PdUs> zx`Y0s?^uafBL8Sgk^@uVNEf$d4^IUu{kK=*88J!+p21l#DJO(({HT6{Xt}DZl zxvGn}srLDa*SA`vvOd8|dig!Rt&%)Rd?I%`2{;)z1vnL$Cdj{v8mnLa0?}zMQcfp5 z=oyI4G*KZ_xILtDNa-Q<`iK|o>S_x8m%l=EE^r=jK5zkWA#f3Ju|Qv0^m;u0rCw@v z8R0KS;R@hN;3}_FLQ_>vw~|~epp9IE!nH069#-(Mf`>J2(3%>O@=4Pg^JyteLBYeS zx1a%S3u9-ys%aQL^Vp{$w_kpXx*e=eQ6f2;+Y!-3SFd79YHdJd%3VyXxr)heH#8>! zy90Xwdjfj_lYuF~-oR7=->bEbar8SnOv_Iq&oqsp`+L1k)l@pbOPV3_1S+Wy?K8m!=91rN*i>%qhNfOKdd0{;R&@^?cn z_*&I|GQXtU(B&Ky<^uCvF7uO7_2nk#Q4<;vQwGR)KQE=T8E_z;{0o{$mMNp_%k1J5 z2}Qgz8>M2rYwf(KUn@(6S%@Un;(G`;844`!3gXV`tG0e%wm3 zI8<)AN|MnpXQBC&YidNcVN*c{b@#te_YCl?DG+2wL*a9Xo_CSHIX{uk)f9ZNe96VZ z!%`a!f>yF95IiheA<|&&N;B*R1P|*tHG{9Ow1zsKMhPC4j3&^THidq9CYPKA^ykYhe4vsz zvf%!ui50;R&x3Q(JP$bE<%-uKtqT!d1Y8VU;+2{S^o^Gxx*WIyxDvPuxEh!)(5xX> z5&8F&*C4tU_%-kw;J3ikrk2ZNc9CKxx(O<^M#9RIO*j2rWl{) zKu9hN0t*2P3vy*X{T}2c?cdeu2Un#U(Nu<@J``9SSi&piYoy90tyIW$$z71h8qbaO zTG>A!?;~6Hh-ze8%dT9sDjoZ8wNo|kA?-*_S?*ls*QRjwegdv|tobUffmpf=zrIbj2}SPO7e^%Ud$*jDVD6Yf}U3YM)0uqrsbvr|6O@lGHL}6 zD|lGJ!wMdjO{mP0>7Dd$dXJe-v!se2^ls-! z7bR}xx=hl*6E9EN!$5q8@4HTNcrB!1BNfz*m74 zf#E>Vue6~QkIJ^in(Z|e2mLDOS3$oTP~M^eg3(rsTCH<$^^({VdPi<&@VKKAiLur% z??QApa1U@Va363#Favl1co3K=(7lUB8}rdaRwC_>zUdJZ9(9Fo!%bf@V#)sW1a(gW zvrHlAS3$oD`W2D;G~q`YtVn~EhgF>cXt4a1GuRqk@y{7;m5Ej>#q%XDF90sAm}@QK z5M1o)O5diwbg7p#z*a{EFqN<1x+{UJfUAM&0&cI9M9l-&Ai5U#waJ-4bmecoB#Vlk z?e|q(mt(CzpnkoJ3PsoKmp3B13Ah=!1^6RyD{vcdJ8%bZCvX=K^sAs>1^p`MS2|J; z`qh`@5xGmBU?lO;u_V3+LBf(m}H3rQgmk zamf68mCEZ(gqgrxS>#k;57}x|QBgRBFK?<8Ys`bUcu7%D^klbkr`v$rfjfXZfx84u zo=UZ8O)u|$HORdt=1g3Z@%?Dda80pz^wX0@qa^b%e7h}TCNtTO0V zLBGoW!ui!D%dFnYF_1GN4VKYRWKoVZSl$#tzq*ZA<96VVs(Vy{u#_?(=vS4$obp$g z$61e7(M+xgfO5bq->_Cw+&#Gjut-vj87+d|_QsU|oM!oVY2WvN_g!6a*78iQ)rLF( zxt&>3dXC(#OCjz^A|*U@kBZ_)Ne`LjG~)pr93vzGHw90Tc*M&X46lm?H}U3jqrQ zivU5tq7@3D4g~!w=vTZ=-5ilB=vNGE4Raq>o4A*4(68{QE}vn*cvir8tv#@IUO~Sq z7r>2vp!>@Q{VM2J>JCA_3i?&hugWJF8lMDa3H~4U-u!>h>DvE~2oa(ss8ooVnChN~ zkQzf`3>8#N5yRy&olrwfZBSEkj+7fUPYF4wQWAuW5{a3JQgiBIs41qJ5`16Jz1Eff z1)uM6&SSlQcs=gD_PVb7dhdH*dsutD)*9O{f1c0tffod}?Dx&MVo7V?@Dg=@FY1~k z#(Tv|+N#2(dkuxxT|t&gZ9(2dw7^A*E^fwH#euesg?K`myWU3W9amDYX_*$^L-bD* zm76u_fgd3H5ctUCGEAB?Hu)}7Xd<{)+F%6zD(F}8>k0Z*oo)M%o_I=n&tC;aV;h_H8lZ^PM4N3<3rNyO=u61Fax;L$tezO7(_b zEta%8%hrvDP`8)Y$%DYMn^c=(GvxbFH`MEz4Wd-;hiHEniT19A?*WL00S5vHd8I7|sdPHA60`b++;EE z9q|1Ubu6k~pe8H@bQS2ExmpX-ZdM}CphdQ*KzGZ#7vdICpn7oK^1uo}Ppc&Gk(S{< zv68}CSkk*vDRrZj(d<=dD*i+#Ulq}6z|Vlyt+HHF@Zr>MvKi}1*PyNsu%;;}hBA?q z`ntOOQ>=N6VzMsc$bJ>{tH^$(mn5=Z1^p`MS3$oD`jyr;LBDeHjdJ(MpcwQkSx|z0 zMP}`1tYfeTNG=)Wn)v%^rz57c*7VP-KA&$&+CD16GW!~BOx&%z28rz@l>Y8Yb$N-) zAq3H@CL&&)b}g?XdINY9SWr}w4nBXYC{-;ct2SCNuiruQUEn=aD7R8D=J%~cBxiF` z*Ve&2NfetykNq*1EHou{C)!PXis&;S=vP6%3i?&r`|EWQKNRzWf=F}JWW0@_Uvd`F;%)`T%PJYXN-)=xae@LseCl$@GniMX$MjJ+H4SfLABqfJ-(s zkvsrMwze^%e!wQcrod(bRx*k}pl96z(Jz24ff5k(t28a(a*+r9ioO!`D=|gQaXaW& zMA4qlIProYy(vMzs^fJ39gXrm@B`2VNBy8*ZR}Kqa)aIOCN#>Xz-GYaz!m~VnVMMK zX_Kw=%9@%=)RnDHQy|BCRYWzQ4m7;7u9#=aMS`de^ar*Awgv_W(kLd5Mkn6}(Y7Yi zL9jA9=i7TplzRP)JEAZU*a_Gf7z7Lkb^&$;b`#M3>rJlO1JRzq5SJ_Ijc?4Gn4W$` z-9A9juY!IR^sAs>MfR(-m(lLVOsdL8XKp!>{mLgq#Uo2iq(!HU%{!AoY7j73psA-~ z>Fst!v>ULy$w|nn32{$ELrf$G5)V#B$a>92E*2qCbK+1m_XYNIx#FEj{%cCzEiBq5 z=}Gj{*pH?7q!uYn2aVD^n2Qgwi_3LQ;Dxp(@*h3@sw8_x(654i74)m1U)hut^sAs> zX;usRRnV{UPSCFy6oY;h^sAs>aT-^F5!>IX1yvojb@HuY8w>z`Y4WlH#>gtTt!q{4 zO8$^yd|T?avpTZD>4aCnNi(uvMfNK@ZH??#ts=XM+_gISBgK27gYHf~+e>of(pqqi zl@uKiAMVFg${z=wD70j!@8nM*dK!2JcoujLm?vQQq=luHrt=ZKU?MrJD-L=7qLpxV zPgZ-q@`R6h8O>L$4lgskzpo*B9eBg!OhJ131%*~i&hdO#sV+wlK8UKT`nO$Mfe1Aw zyvq&V^GifHkm!At#`a5BCVK6MsC)!`3@ijb5uhRBw$X@nl%U7_oVqW7f0;sAVcB)d zuMm9=d;@%Im3koah*xV`9+pz2-tu8E@xXsTy9*BSO95R4{vWBSx*=KySk~nD(xt0) ztime32X)I^o%%Q#UV3_o;5uoqERPtq$xqQ-30N8E1*`(BD&QMM-!-oyWo@%ol{293 z*W2s$d+GOFgG>4>5gEx{nS1cx>r36*UZ*%di56VeL)q;_deQCHM`;6KL)TQ?NOQH2 zFQ@L(kGf5OO@YmT%>{bKN=;qGe(-V;6u%7tykzy7dhnC0a7ncg$@M|AQBi6s0a4yW zp#`)HdDEO3%W5<`N)p#wzv=+5*R$&`+i=OYz;?xT@+8rWglI=#Ag~j#GcZV?=ceQ9 zKidV-t}bd+%)vx%AF!9#L+yJotJ^iE-;&6cz!CU9LB1 ziFcgG#*iPmqFNNh6-`CTECOv|=_QW(wg4$>HgfM(r7cUNT)B-AYdODGVNk4IQq31D zaFd?Eimo8n41Lv45v>HQ4D<>$R8?6`i>LBG;)RZfP^MLuZMf_{}obGeDTZMLS3U%nA!qo7|^gMM`;J>e_?GpkbL zrP*3GXHS|c`kXAPqr6@x1G3ki%O&TTNNG^X(|o=w)SJ-rF7!ItSygv2>Z5@%h1L=q zv}ds=WR2DlWBod%FH|4BluIrHI!ojh(NjTv^?3P}CMNu-zUC@4uLiDhc_UeguS0Y_ za076oSJp}xVQ)rs3os5C58Mje222pBSro@pYnS|XM0Wsp0)GbX0{#NrEuaY%*4|Ap zWsEiVQg1@?rT&dx$K z8+a6$1I!g9jY<*kmQ$Mi2@~s!NQU?nnok4I0M7!E{YuAgn7qEGHNFA91r`B|1?hLH z*bk-!EC(MyxL9#xY}KoMh<=x@FkqGjx&g}=7e+@Lkr|(gebV?v=8|poQ z6@j04rH)-xxssK%DA$ENjNTgC^(YI2^+9F+vL$n??Fm73tYlTvDb9g(vO*83>trh3 zM<+mbBo_25Ip!5@u51@_%=0!^R*bZpA?2#XLBHzc$E#`b6TE#iv8rp2M0BEw2u81# z`i+-lWcD|tICv{18uw{j@>{{!G0X0*j;)YtLB9(6RnV`3er4;SpkD?3N-N@^Uj_Xt z=vQXb3HnvguY!Js)g(FsVKzh^(?h?7Lp(3^-83s($QYhIf)%uwL}## z?Y2_~8covm9dC+}{Yq^S*{>q|RnV`3eiig984!bh^>6Zs=IY3P#rZjTn{M}ZDb?^} zz0*tblaM#ZT}w)=cJ5XwzsE${O^C^=1q@!Yc6wf~iY>^JMs!$RJE>4CDY;DkfS1G? z)XY4YJ3RzE3`_y00@DO+Hd-xxAs^ahc#tzq44+2Fth3OZ?V4J8>9OY^n(JCJi`c=w zo-LULNL8ilp7eTL=IlX(ew7FPDqqvM1tK?-8o95R+A4PPb-bjY>ng41EQD%{Aom-1 zNnT<`ik2I`tQ~62#TNaF4y)H;3l}TEgkH!kRmw{)YE^Mx ztRSiaHJ2-!TG}nhSIcPZvUSKYjn}WPzw|+_=w|)UyQ=$c#r0bQ1MDWm#xnbWFq{8^i+co4R$Sg&D+;2@3Vcq9z!?X9i=^7soH`MHw4jM zz}_au6-W2m$F=0)qu*g)6!ru52YwA4Ake=kZJO;sD=FXyBiF$w90D8)47WB974)lg^rR8H zVXOl!vzQNBDh2(jlOIYu31X?8LBEpUt1WMWer0_k=vTJN4f<6lUl)qNdcgVxAt2~ik^Sm4dc<#m(}6R9 zpkD?3D(F`%#hPVL9jtUjK9vOh%9o;%{i+o7E3?kYG-#bdn;SPUimdzpjDA(^T;8>d zvRvpdcv#vZX1g&~)oS9hWqa^Zrf*4y@KNVSgv zx~)2oa7=bA1(~j$Ib4S_bOIMCBulfCjnqeNc&CDJ_ ztoXNT#M#-SD(G}Yc8+Xr_E`3K_C)ri)ysmBJ)J#6LBEF|A2#e{5%*?QKcCG{)i8^* zzhy6GFPXOJ-Pz08E7_~rYY4+GBC z+iX#`IQuU9KKmhOK*^U9a7#r1*6_77qHZR_d?sVdvWU6^%K<%r<$)D|p1_I%zEdYF zPJyl|fTT-om{dwb9hmk)dllD~7p%-is}-fDA|dILa;b^Yt~Z)L2i5@km{vsxR;pYJ zQD0zfU>#sxU_Aj}tA>@uX#*>1D-3ymBd^o&pkv^EUMI%5>NYLv8XkUD$wBN_uhx|r zn8#{+$YN2ANhebB>lO3S{$&ML(mz;ru|g-L|6BPVY1T#|=C{aO#kW;CAnLDDzEvTj zC+7paq|RggTJ|w(Mx}=I54v+|VGVbBoZw*v4=Z?B!NXD@7agew4@*;_IT#vCfQ-66 zixcxE?*)Tk6=x8%MAOkcgy?6$>OgPc=fE03A7D*jEkT-MQd-`%5v>EP3#}MZwt^g?_*$F0VJ4AT~p^Ij{xr3t&ru?!&TC8f8QkpbFH0I?xdCb&7nF zCQxEw*t$`(pdKL7U1( z)o3f)Z;@-go0C{H()!*$rAg^th=Yd}Jgneh$wyiq8um`edSdwvn1b~NjgmM&$KMy3 z&fG{)wRnPAEgU`3xSJ(i-FMsRyy)|O`Bka12iKn);7&+m!LG(m1Mc|6<>wS zFPBl*u{u1#WqAl5R`9TbhZQ`m;9+Te3?7!Va3T#>q`?Xv7QD4DfZ$;T4~yls*2}@e zA}d~AP;naK+OZo^cyr@~ic6Pv99RoJ(My`T0mVJ16?JIzYBdPp$&V&CRc;Ba2+?Hb zu>W6pSc+E_^eZSPLBG;Auq-#Q?5ynUw79D%(^~fXY*bpvwcwMT%SS1R;`4{>{OkgX z@;niX=c4T5Y;-mz`%j6Wbm_`Vl5(A!{4u+ff&#GUCY|i^R0AtFyONLPx+hf^5k(4D zXV*wd{!g)ruFI}ZDh)HkXvZv*b#_yBGb-&O#hb#WIH!d%CA&4dEt}w%N&EKf4hphS zd+q{-RqJGTWq--;&hE+n%AFL2MPC;5E2WMM`c=@cf_?>s?HJ%#;5etRl}a3AonR%! zPKE6@5``0ilM1bd#urAMR>~%P3U#Lfr@4ZbK(g_jj_3^FOyDfwY~XhSE-zIG6gA39 z8V@a$WvSK1{qH<9{{Wm1TmW1s(1macwJ*OI(P$HCsI-WgC9yVTa{MnBi<+y0y|HNi z(L@}o$#Quaq7HC5a0PIsfWfj=!*}>9L|2;#KS$l?T365@T?F7FqU8-}-U!?T-0WHn z_`&%&MB{;5f!nOI)Q0HFmnm4kv~H*F4y)tv)(WCUZ)8)Fr&!AfHbox`b6|glhz_c(`*iv2j;B}jA zsoT!#N(vIM#p4cMQbq)Q|3EKQS`}>scK&xsnuAr!cL8=ad8JZ^{j)owJxrwF86M}P z+H9*;_M&cYSJ!|d^?eWxb#-mWZK)e+uxw8h^s9V49pqNvHeiBv6}f8S#&$cRJAgY) zE_TJ-wAqJFQ7$~x8U1^tR(MtL8&1(60T=vT?2+zk4awkDVGPK*Wq zD4=1=DWK(Lh&nD((lt8|Ql3J+M^{q!C*UgJYTz1yuIAWA8=>nET@Ty<+*nj9>2oK) z8PP4kIAFY0a*CBgn-b_uUowHZ|F$~qJ2`c`qbQX)X8Lnc@<_Kb1bVbh1!T2TgK`ri z#$UP9y}*6IL?F^&+0Pa9D|LqM5Dk_CdH~BCN=Xr@1c?Y3fv3a2TTMe0rvwB01pC_frkWX25uJw9dqRzL~~tBLCK}{IHD(jCta?r!kTHHwh}?) z&5uthR`vWrzfx3m3k;@U>2^>N^sAs>1^uejZfY((8PeG)z^Oo_!O}j*`-Wx$4Z%0l zEVlsTfbqbsz-_<;LE11W?4VAL5ZwXX3H%wj3-}9gw}6R3-hqB#nmqpQrS3jpA~4Cd zbdsqKRX%SSuzXVLyfD)4(&pv%qt}Ji*w0`SX0954<4YN#)RC=dSX5*8{#p z-QSD4G$p=bC2dv7Uj7;iue(CEMikmN5iM|0tt_ugZmiHFe!AUOvX=a9l-_ZrMoNqR z9-@DmNWn{#U?u+m(TBiCCdZXNHK0qBVmqrz^b5Zv=vP6%QU?tB zm0Y0ZRFNMA=_&*M2kBQDJA!@{^sC5z74)mLJP7)g#^cC-71^)U4T63J87b&jI+PK+!np3ls;YgwxMX3st>k$-Y0keTet+FH&npEc^ddx*~akTAciOrjB%PbXQrP9VL z`DwJD0iFe(1LgtG1M`6w1YD^YINJZci0CC3$>TE7-^%TBkx8||it|;JUISitO&t?z zU;8Ga1ukmVIP!VROF_R1`c-7Va+-~@#->B{pkD?3N+WO3uS5`si9O%RMv?tW^Jvho z6q1Dmj2nuOp#@6NuOOxb{i;EqIGMIM1vu4vM~kx`x`_y8T6dmK-5J1{uAo2+TB1hw zD+RL8$I&oBzsjGb9i9W`Suf#OOGjSw5xrm{Md=`8`HNN}gFxD8iE+uv?aOGsVs$Xo z)Hh#4^g8f{$(4tIsQwEIEe`hBaVg@IZQ7c3BKyDX+Byl-QQ5oP;61-YiP0r`U!}4A z(v>N@;fJVv1bhrE1U?a#ZlF}snAt<59*e; zx>CEQ#c-4!MR$xTjG9O3t3E)ZKDXWxwq{8p!&sa%oe(f~US1ZnBC!dGr^RB5FIp$8N!!6zY zZ`8dAykrW*)?t^0=oJ^~o6{4?AcV(aWWUOnfrzjy5cDfrp$t@jsz6ina*) zRU58O(64+P)c|d#(^}n(FY+r5`W626FWW04I#)%r-K$)k@Zas&_B@a&q8U zAjSM2#p_lsNCWkXCfv8Fdk1(Icn|m|@ILSX@FDP#fRRga=XKRWM4teknp_q^xDKCt zNk&NvRNO2R&+SVS%OqYrV9>8vfoLsL@HVhwt_#UvJz#z37HH+-w%HoqFdI>~vDcLw zWQ*Md(Wby=z~;af0)DGnwRn+AE#1CEUD@h1=E6U$BB}v(py8DwIcjCpLevKO16u)G z0|Nv$i$O=+2GO=AQlbGu?QQQR*=@C2+7X3;z)rx70+JTyOq&C%RuWbxC9s60Lqmm8<(@s|>cyhk%3nyo7 zU>!jkz^hC<>sd+MJUdF{tWLxKhG=f&n&lcthW!w20&EIwR#et4vy$Qk5FzFl)NN^X z?C*82GNKAl1!_PYXb5TUbr84`A54r3k;A3DR@CooK@RL6t(8CnuzQ`VE1w=hv zR0{f4(654iC8uQz!zQO@y=p|Up-B$Jp%;&idG2v zRlat?{;J6*l`Wn)VRn*MZQ&QXK5qXT02{id4&TgYN%5Gq(dDJ0VnH4sa2JF6NMJgF62$^j(OU`r&b$M!i5g- zdOf?gq1$lDw!n79bs9uvnnScBFc8=Y*clik;I3Mt>p$BC(XK9P6loc%Elv#gpl;8i zP8XQ%x5C%%P2I16eSo2^RjrA0nD6H$ZMc1-U&XWJ05peL9r?#43i_2dN6@c=eiig9 z28f_v1^p`MSIXX`G_{(il?gerUunS+*{_0rmA?s5YXR^N;4PzU$!b9G`M0ekGLE7g z^5#?ue>wS0o5xwZZX19S8B`Q6-mhpj70ggqXnjqX{g3^&@}JW}`V*D%Pl3-|U71|c zvbNk(lnei+CdW}IeFc0Cd;@$7ECLn--w9ZJ%RkP1`s5m?@91I<^_5DC0F7N$%9jSZ z0YSf_6}ALQK+vz!v`}YT`D+^F0AQGao)y`zv|SGR75%`*yr5s=X2>d@0BnT?Gs&aw|9Um;woF#kCA|%L3g^p)7*6nyrVci3blNUAAyWfNDbrB<5vbm-x}?DA4ibFYE`i;1SksA$EjDRFh~*4r+V=}A^NMmN#b z^jr3!ZcShp{N?`c=@cU~&ZgidG2vRnV`3 zex<{53+wKzEagKpw_=6D*I`L79Pd}LI-L??0$vT#&w$l|-oVd+HGn?An!s8DOr(m> zFKg!7h}Hqt1=a)B7hs`mR3Mpc=p{whlJ#X{6#4<1xLk?V^zEA=+8o#d_yw?~04r!E z*;>npDnJ#e0d=4uNCweTktbUoWPTP2^`^hom#X?lJNedJG649cUnd_$waB)vC6_*x zw)c{f6v)WBBkBVS^=jeCmvRXVqHeIOD;>9gbCI^Z+O%l?Iv}Mn_He~|1>@}yFDdz( z9lBPOTO&QWzSoW{6oON&Gn6mc7ue4)(P62dnkJu!1E?G3b@JHs-#W5i;oGTp5Be4E zGrWPky0Y~YPVx$rmtNJfGgIXZppJQu_ap^9Gyj2BMIN&0U91%z1r7P=<&)@l_X7|3 zB?{4_Ba6w!4VvWJco>B#g^08s`7}h+ff>L|;1OUJFdKLjm;=le@RZdCzPOKDsiY^- zH$92MQ?Ae=TSxj2)8WXo)IA5xGlj^0CF*a`ukZ-wc#B)7x%niNeq%~X_n?(D>te0w zbk9?%JI!xUDUvj5|D*Bf4C>AV&H~N`eh2&>7zLaoNK0pt={os&R#FfP-zt=+5xK|9F5( zixA+KOPpWfb+R?sx?cNcU2>I+m5bf?F%4o!U&|%e0oS`iz0Ut~Bchvtn@z3;BWmb4 zMB`0VYF2RJx(!j#uY!I>KM49&(654i74)mZ7%Q*f$bRLEgvfrS2_ooMiUbImV0kAK zv>K#9?r9~0ty|;>9R%5GR&f?A3PPp9xys61+Y49)SQS_e_?aNBMVrKC@9iad%4_kr z1`2(EHG#E&zJj!LR9uL(hOElHK7DA2-=;Y5USE|3xsz|eB^#QEd{tUkZ;YrPunDj! zu$e$NWeKcj-2%}sfS_MlTNjCNNR8j^n$DF97;n<@UXt4QN9O$0J=cU z2p(3X!IIa6>^8rmJM04t1@;xBMM04QPA8d`D5h4@w4SOO;*#gX&^{12$S)yVD+j3Kl>j`)e zot|qeuz{7z3V*B8MqVec5E%jbd7biEt8UYx&J%^}(7(tO!%?dcwze@R5g-FNsnu)zsZJYZq>9?&J zBd8-+so_ZN?=x=Y7=wIKGY5Mx@H51@BI+%?;`m->wiB0(Jg^JRWCSg&YbsWw=pOD&@B2S`)EOX3hL?6PFc6Ueo50g;J$mgr4^gt+u(d!7K_WI9-7GX`yQcgF)!*hIn(JCR9B^-Fop7YPD7d$-d(!J=ZFi@k z3VCmyF|jt^9wxjdm!s5|b%3EU|9S2`-;{Jp&`8%3FWk)NI&F}{;!7y~-IeOeWd91H zS4|`v0mg^d5xoJt2`nfo%Y-9;t0-0dNJTt9iQhr&TxxwDNa!DCK z(qmU!m^MDT4ew{1k`?!`? z=IX5bqOc#ZKk#ed0D*2zjDOwwKr5Bn4W^ufQ8)xR6c}!mW!c^I>W@HlIB*1TByf}< zjWv-5%YtGB4=cal`UHNhni(FXn@k2C0v-mY2s&oVocA^SV^?>!W&mfGCKJ@G@o}(4f+1| zHJIuCM%|0ROQygZrZ?|pM6b9=-<+OE$7y2s{Y|ceks=wIT*>A3K;18aZGdfo?F9BddGFRlk``7RhUlgP zQQE0cs^AMT2+?2@5yVh0!>+EN$Flc8+|nf+IXPVH$t6PyCHWsHy>L;Iqk`rh6ovx( z7V_X>*UL+K6)vaTn2QO$Sql&=&LNauQaia1n@k# z3eBs5pkL*W(hhTgpkHbKrM|}MRWre-v`Nsff_|kDBj{H@e)^T{{g-t5WlLw>vSoOS zmFK(B$-3JMEkFCLN49*nLe?`|G5bmO(`=<|<*Zk>O15gYTK2PS^{lrP;X;d#u}0QM z1rmm~JK0)U-)!w{oowA~y=?t#gKWcWqio}>U$#lMX|`FmdA0?r4P_Q!=+K!5@tDs-W>$Q{Jmrcwj(Mc37$Pd&SvQ}mfW|Omr zkjv_*zBeVCnoY~5XEU;y*(27y6iz;yojt087$`a?%jRZ}Wshf1WKUYXHq6=6*)tS4 zA54q0QbRN*B(mYC`uS{rs;;%wbN`mTn7w4$Vs&RPXRlzup$i>OShn3>7_W&UW#&6t5aLiHh5PqfU9&Na1n4Z zFd7&mU};(vS50x<5nbXU<#dwe;E#wdHIep)?vboS88TvCPTdu*uDzekr+-3p6>v3h z4R9@R9dJExgMgvD-Gn^*&;P(`sxsgupuW?cM5Q-D=1N=nJ47#rSpT+sXGHW z(-qn+CBDqhwvwzTI$p(MAqKQ2gHdRn?Y+c*A1Bi_@Y?UQL}W>Nf_|k&3HnvguPk1N zP7f?HSJ1E0WFGV@tz?3JWy?g-?+Wi#@#d0kLXqb*vn*%M{{-r{<1|S%{j30ApeL}R zE67z!i@Bd7S_xPg=mo3-tO~3qpwUH<&=PiaM7>?4(>FiuBdL7QuY!IRX|N&<79+$Y zAm~@}!U_6S-W?)N(64BP3J~RbQ^LZP5aTveiihq{1zxV1@?q8{pYg~%?5&g)wWz1<(AfHv?NEJT0jN; z%JTE!u47$IF8dbGPys<~IjjY+4UdX;g{ND-}a0@4KA3*xJB40{WjwnCk57 zSxNr-VxS;as6;JcH$-zI*DTlYeCmg26JS$dv!c>-hiEBJ_@7@;x24r#JJh|(h$=u8 zr~!4LA+WC`Mnua>M7h#?(cepiqD#-Er`5j^^s65|{Ytr3f_@eBtDs*6{VM2JkWC`{ zmEHuch$H(|(691N(64NnEwW7~pGs>?6Ql)sg%$3MqExMG@AC)>vw+#aqgJVXDsKF9 z5k2OjQr$D;lxhluqWiJ>PP+sGrAYf}w4VW<1)c-u0nY>Tffoc^S#M&3e-Y73F4Ddt z?KI%En-Q1L`K} zZbu6Gl?I=nUzuaD%pn!ywC zw^B(@qHlTq|Rb;|+XCCU z91g2YbBKa|74)m1Upcd-&gNv2y(C1p(-<4suOj{5C{Eze+!()|Rq>JV%SnvqlQ~l`XQBNjd0O zP%zd5))(*w1^r5m5%eoH!f)vorvqmILB9(6RsIw`;c4I*;91}~V4h%Xzx;VV&j(%* zq#2o5kj(b2#4vw}y1y57P35!5U$K%r?MP+z8VawwLbayokNKO37Pv@hSMfNLM5wqPGb!CB6_MkoZSZyI4!bgR>RaULN)5k{5_IEl7mFCcF-)z5Z z|LoV)$qHTTWW)FR+ZRZ4Hc=X{h;fOWu9SxkZK%j~P{>+GBC z+iX#`IQuU9KKmi>f*b!*=D4rzGU2Y5M%2wjW%WOq8J0!V9as+N0W1%!0Q3Y_6!4w( zx?Y|195tO(xWo<%#E8(sq!-$&xVAi1WldSFC^eOTUYC?hO~R)1M)T*u8bBY@s_2YE zm1`mD3k3Zt=vSPH(HA276|HbNa0PIsfETJ&Qvj>{DnwVCi0MlQgx9))yoqdCtf@~g z{0(T{2;2nR>{<;bsC*ov@xZOXZB|)Q%zHafRBBCW-A>&dR>xFmd!t5*Lw^@_fAQ-y zU}+0;kC!w^Xbid+h5LYsz@(zG4QJ{BD>0YKU^^LwhfJi%0+!J{vR?)L3JYIkzY6+Q zT0nCY;EU{_UupRi^sAs>rByl^q4K}|o4aL8buAb)C;uJV*2};vz^lM(!0W&pz?;AV z0jrD#S8-SEjBPcc?XZ>tZ=>{%DKRM9i>M8-1v%2fLHmODQThP*5cmlA7+45=BH+$i zwrJJz8KTck#M;6(8j5wzhU6!q z^cz!>GoDAa)MTc6o=V+megj#uY&ocSHL@C=LEV|aS-{!A?||O}qkwY+EHV}0P|tmy zl@$8jw+f{yQ4=me^Fpta^Pt(hS_*oTo>oo(TJetYJ1LHj8s@*eR8!{Pv=WW%S3$ob zV%jV8rB}Uoh%TcS;dMlB0B-^dipoUbc&jK?E#)V1qIAtWXub=)X9`N!!|U+Am52|O z-n_C>FW3vK*c^H#KIW2zrbJj)UGgcS&w$T?FMxjmUkZ3Pls-W(!PiSl7?Hn4VG*#{ z<$8nc-4l7pH)mD&C|#WDp;1(CSXUSxOFP4(RWbf|WWP%79Q3PvFS^Ix-aW)pQoq~B zO6vExJ?)Fae!%{~uYm&uZ1$^(wRWJDO6>+y&cP@g0vrkqw@QT)CltpBM27=M07n8x z37GVCLg9y+&7fbYAupkE#sYt|7Sc>#)9Za1qK=D1_OrRMt@i8WS5o&U;40v1;2Ht# zt79AexYr@N9=HLxv8XIDR^5!~7GNAO-YPl8GM5Qiob)9VsQYiL)5$eCkMAf-C61Z? zT$J3^LNT|E2cU!NB0)?OZ|T2sr+b0>fQdk4zp|ezvR|n)1pNx8MbNKU6qSO0r3u&8 znA(YHHVyg}-J)vQ8_0rYu6|;(`?|PphZ0)!TTmO4VrYK4hnMQFz`ekIz(imYa6j+> z@E|Z5ct}7WRMxU|YXx`3*L*5<(}3x~3}B{!=~j-1+M~`wG}}a^l+|202hm*DYE>ZI zKaS`L;7OO)(oFlbmGELr3;c4>uZpuTrK+QqTNU>!5BgOnUl%4q(61DDS!>xnXpB99 zpkJvGf_{|-aLoi7f^ViR`?sP_a` z1b*U`vR0{bB`c8^)y*Za(|9V`{_P)7<}W)02>KQ664|fnvJj^(BKwOhNI!b|m3n&6 zuOjxuTs8MA<`+m!s>cS@#<{7BJ+wnHB^fax^sHKpkL{{B7r7@vO5R;irsi*zoL5w{puWlJ7fUSdmi+wpkJktJm^=N zlbAie_xGccJiEH!lD`zt)%@}yZ)wfn%}TONYN<~H>eyMYQ};sL!VKAi>y`&r0D4*_ z4vso|`H7Wq4)UN{DT&(3X!a^J(~e6NRuLP_N^a6r@)mAg4byCx! zN(KFjs9r(8vTi}__GC|yuT{{mv<|+TQR5zO9A(r=Yh--nZK+$YTEsyeJ4f~_?I!+j z(61EjOJ+R%1rICPEX5E!rABPC`1n?yAR546wDbmTGu@Xt^%seF;tZYQ{(0txC zC9<&Y;_hmk`5SdF0xy|DSxiT@^UH`{agjVjeQc@{IX=>0MH;MMK*`t=C;`F4O54QX zVFeFMtScK}D}~Q<@US>@oXVrzV%z7@>hb_mXnTn&(8bti6B!rHK{urFg(b@UZYOZxzV}%F1;RJS^+}!NY|RL1`kVPXz;L%$4&|{vm`5ThkHXS9Zhn?5Pb))2S{OS z1M4^!tW{;&S9K$87F8%04;B$XZMTvt*8us>wyXBSY^A(--LU6fs%jn2ko|0xlvwRGhr zNm;v)PWH#_QVJUPbdyeYd8&bxn_bCAEve0oTVErEtFvn)Eo;bAy07c9>yrxZWk{7_ zrQXSI%5J96E}~9pyPn*`6jqNr+?w5%P4LU4eS3BXg-T<|8eU=Zvb(asWOrxxWPjyO z;@axV?#m`-lTdBKUh!)re=wVzJw#DfN8Nr(HZ_};P0wazGqXn!Yt&X7%+4NFL5HY3 z_uTBU?D6c0>`ANFZYp~^dxnC>UjJ_!cCv_jv#OuZ=BH|y#o6Do7qgd4n>KqndnJ1{ zdkul8G`25S6wEY>sIf(*$rezlJL%%Ll3vrD^lx?C67ZFE0%(f-tJ z1#ArrFfB|Kw(pg>L$}$My6vov_d)-~4qlRZRNp_)OO+Op-et~MdE?M2<*uC4(^>iZxX>go!M;^)I+^mX$6O{|FA1pYq&&0)ZS zz(K&lz#+h)z;NI&V1$4-S?AMs2HjLfj`VKJAx;0wQC_cOXO)ijk_-c8cWH?;VA^fx z5NPaBgB)*)GHQ^0?mtw@M*=6hyoPCn?=3gz6DL!53UI0`=*AYyRqkFo0Y9C(Gk`N) zL3!=;%baZ`Sx+p#0aLJk)=_AlPMm-sy z^1HmG#Nz69cNcYEw^8ls^tUQD`YJgAULTJqbG}q56IK7VYb*4yTJBwL5NWWWPy`RFB_FE1Nn5ml;9>FBXbRMOIo$X)T3H4U z%bFs1SovMvDJtoZIe1tEnfJ^rT9MdtO;O)8XTQXF@^|kzbshZtU*TZ|{VJ`Xf_?>a zV<%^BC|c&`|c9OoAtf#PNkp_$Hi|i2jgS66Q;342)V2Z#RTW!pTX1y%c>D0{tW&)1@vw+zG z)XJpt)Cc*BwY9mKYht-i5FS71S0su2g!cLr_{>{JVTQ~&(yDq+RyChCsb8Y>74S9i z4e%|n2v`h!Cs1?aALsLQ3X$5y9O^5T7XJNRRmztJx&g}o%L0)Gi&hBw6>n~&!6F`+ zzlV_qE9h5gV8!68g+$P=lA&{vhD*kZS{o+CJ2+39JS5HLajusV#P)L3Rap^HvG^ z6|E8UE2aCTA#MO}^u7`Ft2FQh{VM;$dqmK$f_{~j0_Jc;AR0~b+ZWWWCTr0_8Z0fP zf_@eBtDs*6{VI)ekp@end8EP0cM$!?HtvdI#)pz82$$0o?n^sE&lv;^26i!Zar)qJ z?}li16P4tFW%H&S7&ToEp>8j)6NS*G`D#-qGWkB#4fQ&$2XxG^AENzTBsXUn2@XIs z3^))t$SdXRs1?B>UJ^@Ds>7|M*fxCi2-FV;jsTAIN-^H`-IU=Y;Uvl^nG0jmSOfu93w0DXWpfwcq- zuyPR97_~N{b%1q&^?>ySSSS_jRzuTZ#nrg1kMc zSHK_0gMP*D5cI2{U&+lyCZBu}Z_Q#L(qPGfAm~?Vq7C|0(654i74)kvUB>oHE4P&9 z@Ix3{9|0c&3xQ7rXppKmt+RBLp!MSC)O`W`%M=tK3p2-8h`t8C0lu|LTr+L;SFVb* z#{DV^&XhjL!Bg%HKcL+O*Zrk{uI9fFeNfB4ZitovmNhvcn(TflbXDGiy5+5o%)^@Z zdU{C?q~=DUfW$i0`6-$~zY6+QS+qw#$*Z^>Fz8n{6c9Dx0^XAg?HvmGRnV_Q@Xep6 zPt5l|5%eqB+7v+{&51f(H_tz%4c27V#XR1bdSsI5iWB_O?gTHU^pZ3BB3fZ3O;AL< zm-cdgt-_#Ky`-AXR^TQ*ffZe$R3Ui8PZ6yItPJ!5RsmK8Ruk|}>p}GUt&XU-ixm9O z?Sxp<@;=n9X?2=iRhRemQd`ANzK)lIenm?K{fd51=m7P>6TEAvq!r*u+UG{EA5J!LBAqcFY!Xwz+=A;uqLn;&{vRlkD}|@ z?osab>4OduG{vpw^>WVB9X8;S4Nb(BQS<1=i24DW0Gk4v33O8(Bxokiw?GuxujG7a z%|f5F1xnDbf_|mry2yT&KgSp`&)$!qU)k2D9Q3Qmer2Xia?j2LfxsrX|7PO6F25`L}vhJ0%rkd1HTh+xvY@7e3X@x4Nzxr>8{CD{ya4Q z0Gtn809+`LhGNGOG5lggqfMj;hknc~-+dj>{g;bdB@Xt+qWMP?=?objd}P1UmQKf) zw0OA@^ec6cpkLuv=)9DmU$NoPD7H0}g8{%Vt!c_il&aBZTW_dJUCAHv?Y*SHry6f| zM15ePUbS=_@&P4I>LBU{yLzMI(JVysFn3aIe9R%VRmJCK4_8#GR^4}qm&!iaiD+iY zJ2a>nTTb*O7`#LIl6`^w{1Vw|j3lg6Fx~e6>V|op_UrCK)0T@418mT*ylLtwEb)0( zDp%FcX^N6l6TXEs;)TFPz{S95V2ps7tSYXW<|0IwxJWrFG(G(h(WNFTi^paL6y?WI zhr67*D_mW(nI_~vA-W2<8n_0y7Pt<$9=JikP~J|?S2uY{zRCKwTTmDWj0bM@N|Clz zIl)SLR+9DHj=~)-3i_2+D3Sdt=vORNp>MA5EP$Y2**ZM3UzLM?74)m1Uj_Y2%cfPJ z6|8Es0&$j=JC8M>4mX@ACZ<>?@9p(+Io2|K4KC@kM5I)0tl_jG)MCFcb!&T_)`7|7 zqVdK9BUD@5Zhe$C05)_@E#}Razg2;c){nYPfK7qTfXxN^9;I}!g{M3Yi=g-%$>b%g zS41M&2l5J+R0~m==zsO16!fd0Ux_@To_wBl34BkD4k-o+TO>M9(60zSBP&4AuY!IR z*{_nFBIsApi-LZY%#A_6()?iVb!DYe(DBrj^o~CPR{>W8*9cf1>exmz>vf2(2W|jv zEGm`jxs%_F=oVlcFy1POMwJ$&1Ul1~OrY++txj2&v2ff`luE4g{#=w~_)Lr0YT<07 zSk2~jQ*M%#_pjXPUf@1pA}|TKU%)C@t5T^&_A52XKWLY?yj_$9Q?35Cm2}=2K|ao7xb&t3T5-Ry}g$dHcPA09Z?tv>;&u#3<3rNk^L$ylWn>! zwTS_LGVK!dtDs*6{fgDA-iS|mBR&&o*g>SxDY9P${Yq2KHckwZ@3A?x2K`E}%KtF^ zO2&$yUsZ#C74)m1UnK)_(62No2mLDOSLy~qzk-%^IdBDVr4h80{S%+-s}NmnB3Amc zTU_f3ikW6iv5KN_ck&z1yb-twxY@OIN+w^XafrqPw*t3WWvSg#YE(=Y@>jv_ow_@$ zj)dj5f|RLS4{{fEfAQ-?dDE8T9xsU`qm}2qDBK531SS=gI{s$Fv>p-kt4g_IUce3a7Qq=n6XQJv zVM`3Mw9IaapvDIg`3jGMhWwH9Nm9)32OjWCbW0r`OfGKFgrfK`3R4P^7;Bw;8lvgI z3}7bk2rvtn4Ll0W0p<#rTNS%hljY-9D(Ok|O;4imlqs23>YEcO>WkW?W_>$axFn3 z&m_I~M|r*c%v3tsOIp~c^Daq?Y@cn5gRDbM2CU;vu`CXvF8dFa@{z!aE)V)u(654i z74$0&2|>SV7qqOVkD*GJVpa~hhidp7;PoQxXkE4q)SPXB?TYJ2R-5mDXh&cmuoJK| zFi60%uHM8LvkRhKUDPQ2f~zf-e0xy0XHlmM(nO&7N_Bfv_bXr@V5n;;d#@&-{k){y zXJ+9kRWZRFfaWl(!vZ7GL9Q9uuY!K%9Yd^1*^+KAN;O=U?(|a7uQ0ZigMJnCt2BlO z{Yp%UpkF0!i8f)8{VM2Jwp1j;t@i%Yc|B$TGl55dS-@-oyL#EBtn*Zw1aF>eVx7!I z_A5=ak^PG0Mr6NAi>{zw>&e7-f|tZaGpeI(dd@9vLykO&OMU~K z44eX-DoCRcv0Qymns&P4P0D$IDlsOs{y)NRc*8~ZD|L>@eiihqG>m91 zW9OzpztR}7o6##2N!^KFr|%E?)ivH2jbtUhj`q18xB0+6 zfN{Wh;8x%^V1j_TSpnI#L%1E$9l)KypMkr8zW{d&Qr94SEg!@Tm67>g>h1$30+U=z zXNodZKj0-DIojK+zEHfz9@wnXAS%KXuAK@@1EvErfSCe&LIthLXCaymJPOPK<_eNV zWWNgfm58n-XDMs3YF$m9D?z`~>mBr~{0L{Dl@wP|Qxb`&{)g#Tb;ad~>{mg*3i?&h zuhOb2=vNw)gMJnCD|LgQU%|Qw`c-7V3i=ht1!VLI`c=@cBKuW-j?-@<`&F_@79s6} zekD8n->h#aU8nX`G>`b&I!pUIw5^wcSAbW6*MQf7H-I;R1p*AJ4X#R;i)EcY)En@% z-$v;jQ({nd%Wk=CRyOgrW%+#{r4N7)fscTXfrY>)0`4roCYg{wL-e_cpmw`?*%R-T z70pyP{HnO5VTmwsiL#>zonFYgwTPQ62EGHnU!q>pzupBx%2GgAW2JDl%+B4Mqf(b$ z+IC;i-SX~*xCQmO2iGkRtN`@1Nz#Y6no~qCV8kCN(dgAc7-ySgz@~pT_5e#gEsX*sB#>HBZ>+LvB zrTlo{ghE|x*rZ;nS)>GVoT>Ysgwk(JNmOSWA|Ms(o~KfGn%_VXh3qjks_0EPgSs<; zvw*XK-vPe|Mgivt(mxnHEN_Y6VO2=6{fspSGm>%KYw|rxoilh?nxektjaQzGo;{946BG0!eZ zH6EHQ4DzBw2-WIV66=V}^EitXnLg{Sacfjv~QNTICxxje>>+bTP zNPSzgsZu&pccItSo7V63NHN}I|8?!P@j$Xhjz^cG%z|REfjcxLx_V!ZnuxJyl?9=$C zQI=3gkp?SxSox*AG?xJ#;Bw#!f%=P*aC-_qodBr6Tt(g0z%{_Nz;(d&zzx8Sz)ir- zz%9TyV7wr8!3H+2;9(K9&`wv%bx3-_!wMc&dO?DR6=|^2`XzW+nrDo9R0Auuyo)QJgneh1rIBDSjmzeJS?s0 zf`=76EOmq6VFeE>9cng|POFnor8TArFv7MftZ-)(r79V<9zkIiFdKN(D#;`-)wzfs zbCFye&GA}J0d|5Z7lI^Fs4>!hJ&pD=z_Y+}z&zl2U_S7I0F#7*;m8X7BBGaEBsUK8 zg=?4H`2gR~PW~!NuK};SraT7a6!0dZ1ukmV@F951OO;Bb!7|^N;9=?1Q!#LYhZQ`m z;9)WH${EZ~!4-4IJV!O~+VN4O!O|2NJS_P|1rJNkZS7j0|QJ; zL0JphT^%CIw$yEBbwR&MzA2Fg%eq6k-70(;Q}W%*=qerWDk9{lb6(+^LBA4}%CbA_k{SGic$DBs64 zuqj>3CD#GhyMn@QXi0V>qMLx5O)kC~i?eZv#+#_rOnEzRLo~rfLB9(6RsJt}#FyS9 z%56MYzg|)zvU1R`7y^QR1^FiES80R~`jto$VsY_ew97INP(vl0J9xn-Sdtj0477B`$16h*jhteaQss{@dz^bfa1Hj-pg*$UXee zMXBn?EY%|0sLoaF)Ibzl&6t1XPWJ-$0TY2q!2JR}Gx-Ii_8_9kz(c^pz!ZULh&jWD zNP`vhtBQxH3i?&vhR4$1c`ORm;{0r-^pFE0b-x6*0k#FU6WIGCMk*hIe$~k%4c1ue z7RobCn!uo6wHr2niAF8o-Ko4e(}3x~3}B`}?~fQ$ZSDPLA)0L>ZCjZu=OCKvTCECB z5RW5z0(jEp3W}f?^=T^w{mNUVTBHIB`c)dNgMJnCE1R?<4OY;vA`KS%#k6`Qc4N@5 zG(C8R)<}cJk}T*~vcJfbd>EOoMgWHcKfW|rHAVgi`c=@cf_@eBD>Fvbbs&~4%s$CJ zWxZQ!@os#cmcA{U@d;Yo>||eNUu9os-(=rri?YSpciH#Z4>_U3^QFvjU(rd4zP>b~ zZYC<1WyJ2}%OdIyEC=)emIqbA`Mog z!NOmP$bpdtE9h52zY6-5EsleJRVAI%d{6pRA~jT`!P25B(qMJ+4V{e=^ec6UJqn^u zQw-*`ooWYSve5}h#&7sxD{w9_u81eoOKyw&yAaD?H zFmMQPC@>s23>YEcd*!2T)cmIMilirzLz;HdM|r)r=qerUC3&QoLt0BQ%T2p&TXGx~ zwA()36iFDO%l<>9d?aw9%WHLISL1u7uYc}j>P`Vpbp_oxogeTY$~bU3b!Px)x`OiB z>45%hD=B4(IgZP`0IO~kn&-G?wdTnY>Qzfohd-UZ^n8>q04@YB0xkwd3-oLRv`tN+ zM=|RH+3?idm!LG(m4bdnYfJ_n0wVjB-X(fTWWT~t7}>8Ft)1+;97>{mg*vQ8J-ujCF7$7Fk8hk|I* zs%j%J5K+*te8`LJS3$oD`jve6J*ThY<|L~^wP9IJMFJ>@H~QGgKd`YxdE(>}z^Xw; z4w(x+_93RyENPbigdyfr;4@bjmB5T6EhQOFU!d@VT3dXH(pSLOz&F6Rz#?EV@ST9E zzfo4sWqlB>M+=s`i#gO+DlGyuc2y}~8t4Wr11t-42bKeR0Lu%wN2@_7#GY0nF|wIT z#11s0O3<%@e$~kjrOONl4g*G5cY#+{EKA{b9_eCv?&?j*{;j0tY|yWQel?lC^N@E7 zrHBpsm4!DcmFlG3ew*fb2Y45F5BMkWKJWqXA@Grad7$1RQprL@p8%hlTp>tg@6JE> zQn{(nbd2=PvLdeJUz%8UXmckgbgx;aC9rb??Im^JMSgv)j?w%(mGbX_AAl}OkCQJ2 zboE3z@}Kz(L;D)wx@5yNsQ(&A4hWO|*TeTN79d=xbU!7-{>& zUzU2lE_Lex>lX@D?HPC|#iY@rZ$#b3UZ;}>ed{KOHU%~VHV3v4=%R8>%LuM6E4{LA zU!tyTbs9zCA6607fI86d%6gsD>n%iWpg*t`ur)A1z-<+)SuM2h&}3h{8Z%Ctzn_5HJ|n1=tnXO~C)Ez{|R74@7$cLtHK!q%B^mP5R)ksM`k^3he7z z)wa40Pp2$?M&%G?*%-;yhSo6oFtiT@4)RN2eWXitbfg;}YGNW2sB{>bBY?w!Bdn4z zL%P>dh%(@4AP0^Cjs=bbju-G>DO!*%ZuEelC_L zbr+*P8W>Y()#c{O_bDu^*{l>(TmQ;fzpf=akSM-fav9KBBDc3x^i@4xex->u2H@6u z6`EHA*SI{gU#T%7`&H1dv`-59m4+KFRMN;9^eYhu{#VeiO4UZtuc}&XX1g(8)@pL~ z$o5E6XCj^q;iHz!Jk^^i=2CiE*sf3b&$JDZ)xEfoH_-N{Z5`c=@cQrC#= zS6b5r{VM2J>IOl-3i?%=QzQEo9pN1TON~~uVk-;i1wIpSzfzl^&R=**0qkVq_!5P$3WbV-OXlAo`W9FOEC#+4=oU(-fdS|T zL|sG$$d>}T0!stk1gPo!Dy@Xd@_UedqdRrW0X<9s`;6o(AnNI&Qp5JQLBG;UHnLx( z1vI|jzQ|4_@I&b^!>z+q%Izh~ZO(WPH?fYwpq?LDC{?s_r}OL8u@9|wVePNLD?f%? z9t#`?91olzNH0u{qvVlZ(j8>TJ;_SE2}U}Xj&5^`iyP{`o&2=o2JREjuESmkaRGG8 zGgY6T1)S}gdMf9?mt{re9g@vaui80Yuh=_!&(E`x-g)=Ymp_`s7jUNwfs25PfziMi z0slxaK8gS=;qr{t3}lz}3Jtz_q}2 z!1cfl0v^BJ=J9XxQoV%%^%fMy0po#Ny;4>TRZg%Hrc{+~N8t_^MfNKtC<^+Om?t_9 zqhl-vz5{}O74$1kB4PjR4p}AWS3$ojaawu}z2REmIssFX0@!K&dxMq4FT>;eCNF7# zbvLjwQ{_0W8xPzH+y+b#q=~tW+xhK??f~vIxn@rp<@39|r0_LbUf*5RwaEGQSJdxy zQCX+DoqQsqNx=QU1Hgko(62b=(4vR+OVF?Ko(07q=vVZJpkLuLN&xYLtYe6f;&~u~ ze#Iy)#}ymUBl}ei8%)rzaQdp)xtykItq`8qo0HG?*GIN7_ZVuLBc2W;i5LG8N`H4H zoe1iUdj-*}CXyQ(#)sDty#c%lEGR0mgXM1(rK(4?ldqq|@1XfE@SZ6s-3;D9?^{Xc zhKf1NmE>ujra`%q>9IfNl7*(EMF)noPZ50vd=7j8ME0wEP50Dq1^p`MS9xx|L7o`y z4k@=fqk<}hdNQlaOc(U4pkD?3D(F{fogi1CpkK+>(SmCb*{_0r)haoCLivMzC9Na- zPJWR(NV3xqWj-HGcNqixr^$)M#fx4D4d+#QD&%>u!j4H&IC( z(&V^JC{f*b2z7gToxG=Qx~w+kxSj7q-B7P>)OW^!?Zl$GUS6s8m+G1fZyG(^*Z8Nf{75nvWD8+a6$1I!ih zlvQQ0>Ew@FsiY^-H$92MQ?AgeDi?104^wQqXQ_J*m}d$>ze>U5w9*Xvl@{3Ri=aVo z5racb64|eUex8c|@$FENl31KL*9?ao~wUOYs;w z`BR9V2A%<)1)c-u3DN|Wg2K*6^n!^Xifc@I(MlZnrKwB-r?6kVjOHs=2SZKc)oX}e z2i`EbQm4TpUr=bZJnTf!uV`^ayilVB{i*_~pejf+Uu3@u`c*!PE^&@`iE5P)#OGNl z=vVpe#j6tZD~}Ey^eY=Y6?9z-f^T_w76FUBr|1nbw{sn?`x!(PK1!E@xRQb|byX=} zdI_`1lB6o?jl#L4ky&ZW(g%Hu-pA$qTJ6KFUQ$hGD{zyZz>2OQ)~LSfr-)VpRt9{pTfDzabkDn$0H0p*{eIbG{RgZwHhH_)J8 z(Lt2hPD`*?Xrt*>8#R^1tb7&G3>WDT%gjtg&*Ld7=(zT{ucP#aE46btp0^PF!$bTp&juP?ad zOW-TuYv3CJ6M?d~Wq%bp&=M8-I~Ui8k(}$B%ClDvoI{t)3Jd~f6XePqd~~pvw0~DS z4XH{xC6KiZ^`XGrz&u{56FOD?z)CtcbsrR2;ylPZx%c=6{qMH!iR@Q2N6@eS-RM{3 zRSo)8(654i74$2cP=kII^ecHS1^w!O2>t5JK?6jB(qDOu5yZ43)Y&u3Eu|*WFLfLo zsow&>1C9qy5J;n;CArq*Cm}l7M0Le3tXfUnFhvIqW^SL#LJCE#V?6<|8>H{exZhCq#q6TH23M13{0TN`8G z>nOcpN|0kcOn|b_p`<+1MBsWGrFVdLf%ky-fe(NW1^jNZRBF`t7||ytBHOgvnSJQN zCrCH^yt<^_%MXKJe^#v5A`O-%N13C8hoye>V|W}J8FM4jU@3rI@UXhU!>X7}!NcM( z>RrZ&_kj0-4}cE^Oi85b>5D*pcNY)O`y4(-i7Ohj25WBl-gP68Oq0m6yvhljzh> z7Jxj(Dbr{Ephc|ay6?~)fRpG0kfN23w)ikF{?J(tm21IH>cGF z4@>!*6{DyO9+tLCbd2r1V?-LP;9)66U_-}i{E4^cAktoYz@UW~o*g<3~MWn&< z{t-N^ez~OaPLvOgmBP}_LMgg9*(~cN5y@><*2dU+P_N^@Dr!Qrb14vv>|A5~3T@2u zu2o&Ft1a}3E>`3fy^t%bRMuS7E%5AaAS!^S%avBm(x5BvxP@jBGsaF7TKcoKM!T>r zv21g?@2XtC8ZgdoqE&>B7FbRM4~w;#+?ix9i8NSrkqJQXu+#{*(h|1;w*z+w=q!q2 zY44rZ`06!xQ+E$=FK{1lKQKjrzU)$YB#h8}`_dM`|Db!mH*2XU)ddWrlW*?ghTosi1_N^dLx4F2{4?D)o4}z~Vrv*YtlY@; z;9=$d5j?Ei9U={u4O?2I1rMvK`RGL-KjrqKQU7HxDe7~z3bvUD!cm?_WG`cQjx<=l zcIdHpp9_!tp+Ka;iZobxZ53&-A`MpXusU)|Dqk{AQt+^XhXsdhIcJU4n}lv0g=jP| z1{hmawv>*QO=7oJNNXkPR<=6!_u6FF5jB7UXaX&uE#OLRFLh!+WvzGyaeSe-WEqb%N%ZpKF)8`b-1^Zc=`)qVa@mnAuEnYKz>r=O>7 z5XlPN?5FMcSntTBly*ovQfSomuBDyRE-J`7Oo?C8ZfW-HUZoB6{- zqD_Z!i&|aRrNe`VMWf!3ZcLMD%}!IX@Ax3M1Icemx2D@D%Ic_JgUdO!tigt}yEdMG`d9!ZZ{y|#Pl@$>`*{T}(3QVbi}=a49fzN()|({eS; z;`Cg4KD}Vt@<~oFrkB#o=@kTGN0{MLn@K;*=&I|a8Ga{S{94u{U_Kudh|i36y&6yX zW_m0ALvmazRD37Bs{-B6k5Gb#6+A4NEP{viKZJ)B^eY{plvhCnyV?k1Ooe7N)A6&q z>NV8;+3J-3n9vW`d8ud@+9_R+!VSQUz~rh@M>a~8Y$fJWtz>US;WiU#X=^Fqf_@eB zE6t;k1}oBF1^r6NC3L)ftg}&qewEkSkp|07gM)r0KMdGh|C-6x(q^w5fYbXdz(Dhp z$MsSxmqAuigebYa(2*LX9V-V{;x6H!hH%}Sz+AvktHkoA)yq6qs&}!&afe#YrZyj% z!z#@hNvRe>n$u&`Cub%1YngQ7`Fv_+{K4lHI0ko~p(8sX})GT1&*n^?J}EQNUR z$ZR6f{}XAjf_^oi98dQ-&^t`fuZo~w-DjPFF-v1fq`~3^3Hp`$ZxWs%&wULXITvwP ze9e$rW-h8yIeezbl8x5uGRSL6qHYPVlQGmhzZKchZl~l!y4^A;EenivO?eQQIaGF9 z-DMPYqk%ENSYQQ#o~Y539p5I^dgYbbg8*K$`k-I2-Y77^1pP|g=2!HcUjsqE3i_1> zpGT{4qHa!+I!J_X@q~%l1LPqv=vUrOLB9(6m8O(J6tI4|E}Vw-oYSCLUHjq<5N&88 zPSt$@(e$HBoxf{x-Wa7#T&d`?N!|?6Pl3%%4mm{k+rqWv(W0&IRw!%@{2bT@*jB(w zpvbJX?X6T3#ZCGTYDjQUTe%0`$lPv5SvD;2W3;I=_N+J!G&!~|G%iPt1e${CO{b~S| zsab%5#u30l(adA*0{58NsGA)aYzlP|thH(#;_BLnX|N6YRW?hC$KEf4ennfz`P8~m zheR~x&Q<48kiCAnEB$FVV0T~-tJF1|bnb;H0eb@_un({=uph9$AUC)iQ?u1op02ub zJaq?poxb0lUwaD2TOLf^A;6))VZbke!+|4!BY~p?+**T!SzKB@XYIFoq!~KK>lN2T zJILQ~$#Eu%G+2=aOP%lqy2M|-mne3FMuebW>4j=U8mxXf5_(k7ud;1RAzQS**pwF8 z%t>MLtF^_ccs3ecf97H(hSQ6+C7N3STf1EGP9)!k(qP%j#KIY!X9F!^EUbxwIcM`( zUH+KT+>wiSvWpe6(zp&Rcyze8D|Nd8y90ZeR!va~GJ& zLB9(6m5#=Oe#L|u^sAs>X;usRRnV^@`&H1dv>Mi`GU!*?(M&eUdEKvGTL~vof}s}r#q6YzqF76KLq76E<;ED8(<76TR+WV2J=k1T;`Nnj~pXCt3K;G3RtInUv4~axRs>c8RueFQZPLF2!<}jXNQU~7FfX*)YW|2X(*U_ zxw466bd$4cSx2)06s|63I4w|Gh}uBM<+{Lbqx-3gu0q|az-qua(<1te(aB^9({0wE zZcVG>eb9fgwwDy0O5eY(ml|E(%Jsi5NpnM$f_@eBE8^>@!=GJsoSKO?-KPhB(h&c_N%gRo|Rm& zXS%Uz7zz4Sxr17!+_B2%(HH`y%@l3=4Ib$bJ>{t8#g#OUP)Z#qVes6k~v~zzV>M0$%B6QN2htjyY@8 z)vZoPxUDm~19~QSsc?uRUy@ z)HL&Hy1j#I?*#4w?gs7w?iJ)0R5NwIydTjN-~r%4V5%T%$ZtDs-O zDB9R)M`X;_qCV(X{}1U`Btbj1KPt_d2Bq0F?ugZ_oH}VRA2mcO>C=!jXPPSwO>?Jt z(!A*hX}&Zp&7T%X3#NtA!f6qPK5?OyOli?HoPkT>l9g0v@iZbWk(NwLrKQs{Y1uR~ zEti&0qtfU!CXG!iq!m$ZD|8}5X1ymDyMC(iQK_2rv5|_@L`80Dt$u2!PU@y!S_O?( zPwr-EwKOjMD6Ni;T=2|F+30EHO>5=raLP&Rq;=DJ6t$1kT{qyPPCCs}sWfiYq@bN) zWWQ3|Xv3}_@~CulZnK7VzUkNL7zzsEt2X)#AEl(G{cZYPI-X*!B_eq`F`bl7PN$^* zln9?DU3qF&ZgG>-(&-em@z+iI>C9YHm)~Lf10O|NbSrTo18_PwohK>0bNyx)qzkhO z&WT9%^Ql8zk}jpts}7a5T{l{OPkZ8ix;$NxuJp^KeO0=ef^5{)dIvqY}Av((I(~XxR~>{BkXOnS65a53Kq1I%~9bqz);xYb;zWn@c_<(ddP1W4jX9l|ilS zR^L_-mTwi6%2g{-lhea-UQ$4bnP-r8=AuJE|KQ_dO>cr8C+Jr}zY6+Q(654igMmfuZ(#kW15cj%8j9AZQ^8{8p9`pc%dP;U;dQ3&0SpsiqyA2w56--P{ED? zWZ2YM|IbZamn*3T;cd~}4%i;p0oW1P3D_Cf1=tnXO~Ci+EX0g%9hvR&lhnGyjBOK2zc3|Du{v4eXVGM)dmc*NVSWRh zdYG%5_CMOk9YNiZz)?WZui(Z{q$z@ar4FQE9f_{Z_M&*o6WScc$ zTdWDJ1*|P#{15t-d6E&sr!vz8{mSDR$ybCZ!+)T|oDG}XrFOgh@=`>X0TY2qR*5;(cDwBce*RZd_g_{=esNhyudYhUGTtx$RFxEWD!=4K z<&dE0%g#{f5JToK-06DY2H-|uGH{b1_xWDXuLhJeXp*2`1^p`MSLHU4akd4vGe!=y z8x37SzY6+Q(64OPRP;aD(4XfedBI+ipkJviBKy^HP$`0bB{HfOpFg89wg9#Swi4Kq z(-|f@z%(a-X3e|-v{S{~aXYlP2ZDa(ZKhSd2AmVDge!!0u_w_&Cj+NcT0~^dO^jo_ zKFCD_pUMe-ohEW^P)_HPGl2d~x#g&nr!w}(KbTlNC*o9|gXX!wc`k3~AYB(Ax)8Vs zxY#R|2T|X6DWc1OiNGY_a^MQ!N`anE37cixEU!XzHSkB^Prx<6pMh%y-fKJpPSCG% z<29Q6n6J=A)2lXW>US((MKr@j%Jt(r#Gbt8X~XVr~9^-DT9-1E&!M`S;tc=Y<+zu=ND zfvKEyJ%ih?#JJ)nZv*U-kM zriaqQ>5=rP)oa6?9#2nDkQv2Kg4?3bAkmqzs-H>Iay5kF^jvyAy@p7PD~R{DqJdQNzf@1%ECV5YVy zIkI1A^%3-|pkJvQ>;sQ&UtqtA%*F<_Jitn1?AGdQJPHQ_2US{aIY;v9b@Mjr5b6#E z4s(T83yR+1h>ie`1dalZ27V>TZ*GJ5P{&wFbX1+e<-2BA`Qy<1E$}0Z#+Z0MmeH1$2j2hX`oTBYMF_%9xVdA6~mn7UCD{0bfSx6=1q+ zYUa{^{VJjvF6uN1;rg1Ff_@eBD@9_nv*e&(xveAUS5D80>{krIiVJBrwa9)YyW?}# zH?&|;NDG=r3kJ=}e}$X$BJdLMGVls89rzpYDlkL9#NXzse7UCi{6W6_ni^k6=?znY z6Kgg_IqjM~QVRzy(cVVs9pGKyJ>Y%d1K>jech<5+tCo)uePSZk7H(daM|56*D7b=d z_<40nTdWyft4qyR9`vihBeluQE3svqv=iB{a{mhYm5z3t=}Y1kEyWLppLGausPz@O zwYguroHMoVJe;~CfFoT&FSM4ZM_Wl_i4l8XKx^%P44TKfrWnrl?zRehH`$ixOMi#b z@xTediNHy~$pVHN1+>j0l^#W5a*=2l(4zWOlqR@RuUmzZ&wc$2>iSkk3?hw8XSrt3 zuY!JM6O4vMCL{HW$bJ>{tFk9L0_%=i$0@8qzml`PIVuPJirDRD^Xj_W24T@PubkrD zMusHKgunNajwtfdS9=d9sEJvv(dKloZ?&rU>AGFNJX7NGEU(kVXlAEYgVpjmE|xXQ z_c1xD{`p*T0dS!!XuGEc{>6wc0WLMUjx>UPW%~&;7zX{S&XzB-Uvc{8r+q=c3i?&v zZRmu;244k{)@WK*44k&RL&~krrh%YeX@}*lqYN(AC_%q!)zxe6hN*N9a4&Ela6d3b zz#3C_DdX-nI)vw%YGR$t;gFa6LIOI4j*!*Xi+D-)DgE4wqA(m- z3|Jf(AwXaDY#XWy1vt(&Sj$qhwAUAfx=6V!my9$KZYAmv%Oe^Ej0VO4V+Fb?C%Ssp z6%nljtPIqEI?w{Em>a`yMvuFumNn>6y9BA(nJgjmZc0_}LIe;O+oWNYb zP+)EW->I`?Gyf^Sb~WRgr<6{$uo(|Sdw$oJ)lie?f>o(gGoG6AMqzwJ^M}Bqz;M%Q z$hfJ>#Sx7FmH?InmI5LTR?E03(DthZxTx{v`n1jlz=pt&1^U5ch2{M9Cx|vSQBB^n zw#bpwiH-m^qwc3(CszXV@Gm-0j<%p~ORwv+wc;AVnsU?@bJ6Q>jQVz#Z2p$%#a3&ButbQ3hEE|-& z9pBlAPH3aE!o2v#sORTGwYmoG@?E;ld%*j^2f&BGN5IE|Jjdj)*PnVx0YkLY`3!~6 zD}@IB_g^CV3iulM2KZLMu%qNZdTGByGyt#qS%87StiT`vYC6cWt(Z1)dgTXGHwQ4p z6bPav`CN#Gx~LXBtl(i;I9lewJYC@gZu|8}gT>nFID1$0&U>zuMw|2A<9Uxx08Ru> z0!{`_5%A_0${8ldLPV#!sLrudc^abAO{5gbma<-6@}&Pdle)89T?+_J`e!3L2RIiv z4>%vV0JspiNWc)#!;V;9;-yxXKvtKbFcFvpT<(=xHK_7RE5Wr==_(Yic2T6k(m@!M z>}gelz)cDsmb%ElyhW6}NIiT2oQ+w4fkxGU#ie!|WF@&6X)nVIA#Vr0H-js27n1Z4 zuA38>3m9sZdMR+xn8!*4X*QFh!ZWLz&WGl(N;4#O7z(T;nR#~sf4Ti5)nm$50 zElS;RU@=pWWfQ{r2v_g5+`MUAlcf*`53A8-U$P<1_G4fpYpvj61rH0miDh3W6oTH^ z^XMSw0~c5?sVkD5Uh|8r1Zh=$=@Kt#M5vAmm?|f7-6Y_0;0oYM0WYwQ6g75Sh3IPF zk0!^LN>^UvC0SIoyuP-o>&o%I{0r*WyQnS_Wxu=;(PZEz;AY?!;8x%^;CA2+;7;H! z;BG-4Od<_dUf=`|tDFzM#xNk#Ud|+)UWY=Jr$RA`^hqte?~rMot6z8Hj?1uzZ_URBmcb{P}{1m6ssF!wMc& zq`~T!kHM^a9C!kF5_k%DS}$7c>&Us_iFh9b$_kuI*QO*zGNkB zRU-`+1e{rcLBMQ++=eY&a0h!yP7WHFhg2oS%a@}a>O+CKfqA^LR>$w*2Ue0LSQm1? zpkLYcQq9=)meL+mEwxJ3ZY>XVB6nvQy~nv&+%)|Tt9waKo7S_NN`Kfd*Q&0SyLG=@ z$4YW7>6%}*T>m6qU*d8DAm~?lldp+YO*)6eK#SV6xE`c=@c%xD<& ztDs+L!MU~(8z8`$qj}J;SOG>FENr5Y1`D2{R=D>#{YTLebhvUK^q)wBmA6VkzgiHc z#zMftz#_m8fklDgz+%ASg1lR;b3nKRq9uW)fTe+D1k%vC9wf7oUh3u~9cOUGIt z(efbZSJ23+@bPtv%cDbhXQs+8K*#sjd2`9x)K*h+d(Y?mI#e=ih$7y@o0-fDcoT55 zUn1{$o#NkG-5{rDxgCW&Dv=m#{qinEcLVnT_X76;_XAUa2Y?5GsRG_`1u>Op{=-(% zQ4UnLM^Sjp6_m-!Okav2q<`Z{>Yf6gHie*HiTbM}Vx5Q4D&GL#0ztphMCDuzr8`yM zS>8(WO7R$0L`v?LV_=g018*H<*cnOL~Wqsa$R7z z(fu^9u0q|az-qua(~=iY6;z@H5oHbP*0eg_2mP>Xdr9t3`u=sjB*K;6mG!?bNi*nI z<$tI_%JIN~)-;g@E9h6+7*+2{op)%8mx$xjFCX-d0=c?hKBQ9lFz`sFrFaZFKtuF6 z@C5KA@D%X0KvS6<R_np{e1<|bl`6$ zCljNl))|#n*TYUI>6y)nN|~to*IipQI*kc$a)Y=0lAvD&{i^Ih)#w62zv5L5`c-ZP za$c3k(=CF2m7SF}83g@GQ`0l_iD?41XbMf_k()a$ck6C)kZ+#z7S5cDg8dsfEMpkHNgjYxx4_F!wRQn3;06$!7Y*t_L8>V5>Q4y*yJDX{lR z(OUV?sN3=fUcXl4>!P$?rPN?ywE?0HO~m1uRyG^Cf(-wbq)7IMnJLP&klmC^Hmj5r z$gN*)UX>IlR*_~=*b>;Pl6Pb#<$-FrT$Dk-Qd)uU<{h$@|BQy(0@xDR%9~69%FPd72bdO=SaYULiA5XB`F3b; z5A5KVuuRQce`T`NjdwONu^(0170um%-GM!My> zWHc}a7%SjKtG8^cp=B-6=~tp|WvgRIRYh3O-R}zpA&DYA>>1z2S_^ z$bN+xqU}e>^2O9zei%OY^9$G_iJGVNdeEuTtb-N|;Gkd0(L(L8F@%gws-}UxY7?0PEtfx~ZgZ<^)M~_3+5*v*uCDF4 zosrd*N3CD}+{BuznEbXyb30&rU9IlU^fBZs|26sJ*&XbHsdKUw7hQj z@_HSnskFD3)Xnn*DrvRe>B(|TzZZ2=i{kxF5kCoC7W6Ax#xld5?M)cjuY!I>j745P zox12PepfxCd=GdZ_yG7&fCd?Q^XpY_k=^hU>OKYjX$p0PW!H=LIifFsFM+SDlF0bB zI<6O%hegY8C$nl1tMTSLvz2&uu(eOP8(QLr%Cf82J4)Qhnu!-){6WOowP!RMhoj3o{#}DnlH9Q6V zN~3Jhuas4UspA{(8;bs8uFX1Jx5cx}KN)@Q9Dc3Bpjf@6n$G6pCPRU_T|vW^zG_}XKLF+fh5_>f3jhlWn7lOy>i1h1 z(IPIYk^VSO{RA^Ahf}wh)#)KgjXc6jJr(=ql3vpDtF*M0MB$gKT)C{5#2>d=Uh$Z0 zb>8cEm=yhU`Rj=PqJL+MUm?o5&CY5;E!tOfu>wr!nO0V*thuOL5Iw$ur~sNSm&=0L zf0SKpdZp6$N?L=IT(=LfFR-6iD!86j3kP^fLFR02(ZsyVnnrJ~Zgmis`~o-_ zI0QIUU>cUHmSdy5Y#{oLZvzX>0_BmWNR9)oaE|uN8ii5Of_@eBtEa6`1pUeu*+IYR z2mQ(h*H(wfWShW_*%a8!DKbI73i?%3jxPQ3Qo2RZuOj=E7HgflZ=Sjs!1CfOpWu8! zANdma3iulMMu0}6VQyE7A0RVY`JIbv9XF~4{Yp#Nkq~p1b7D@=uhb%&(juE#i`3NJ zY#V~lq{zT7R#Z(5P+Ow86|l9-)#W7LhSFdirFYx4(Qak*eS_la&NS^x^WU6))e8Dm z5%jB|U&)Y=Zb&z#$xJ()rbnWY+kxb_q+8Q%$aM}>>!&-?o$0Q0ce*Fto9;s_u4S*E zrlbc{z(%M`rlyC|!|9RqsMX7GkseP^P{2DU4=A;^veP3`2pv^Flcwcr2*v5S^n7~3 zv=v}Cy_jA~FQ-=!h<;w3C;1_a94z#OGyG1v__eG@oP0j$0LTundNrQ%&Gc6Khva%r zh4D%6q<2*y@{b>(ME0woUujm0>{mg*D*HjdVh9cT)$4SGpkL{jaNdfN6Z9*k+toy| z8bqaWz>lnH>fIhEDQkE`1^p^pGISIMO>a+Y6{TC~Rck;0(8YBpuh$xd{A>52MfU~v z1NH|F5M+%eJJ<1E(xI3fZ4R=M=w+7lMInvI&vJ;1b-Jak?_t#qSg-oB&zyZbJ?Ilh zs=ho5INCM!RKAJ~`W4A~uA*_S_QsJjn62a^`;~W0C`sjW);uCeYEMOfmBB zF9I(CF9WXt(}BMMuL3g!x{A~z*1C8bl zUh}J#5{q)l@R=gZF?^l*>Xz`jTGPUwD-Nrc+05-lm)k9a(z3uv*Od2}nL}l# z)m=tWHyRiNj0IK@=oSqH$+Jbe{LIXIU0WNiKx$TB)4!l4eS=GiN+j2Ze%Y!@-9qX? zzsf&I(63n4it}udiNzq%$QaqL{8b71Ro;&%zhcm@G@b_iD(F}02J1QRLbJLC%MBoA zZ0N)cIhXqaqUlGMVu5M4-58}!T&d{7huaL%Pl3%%PKaCGZwuFw@3$uHtx(t+_&Kl* zu&scVK#^H%+gnNbmPvrJBMLhKI|I8|C3ZKhJ9a~~JFo|^ClK^2wE}Zs(68tYk^Rbg zL(s3(83v1EP|g7i0p>KyL9N?n{2FQ{B6HZ*CFoajqEQTZnkuqi1^ud9Q<$qfvnV=a z-fW5qE&}+8{u*_fifCV+Om{g2_)n9|0ThSOQxQ#Yk%CG|^>jpM0Da(0;4A^(p@o?r z)OE3KokQKZzRN|4fw0Hh6>3_(G^8c=TR4b^CK{uT5q zg~9UWd&9OS+BA?e?=X7RF9j1$nSJA$q89gpeiihq!-IYm^eeMl1pO-LS292a{VM2J zLBFz$=0U#-`W2Dub69tG!;kD&wV+>dZ~|9qX9yg-SkGvP2ja}CdQEk^n>grK;C z$-pVrCbdG1)h~aK=u{Uewz3Q$ry)AsL~^$Egb;G-*2?5e>dta?x!tOb&qj0(a4v8j za6WJWa3OG!fWxz1j(vTJmlU}`-*y=a6M;#<FmuLA)67;K}UzuNxctTp9ysdr_ z*{_0rRrV@cR>w04DqV^lbxJuX(;T98fOUcOfc1e5 z1gvotXIOl-VqzxLizf5~oV}!yRsrLo@Em9&nIV-yC{O(j2;T?0X1lP>y{rN( z91i1>U-~7=Jz^0O#4R@`q-LJsk3#8a;8(z}fn$JUf!_ef3G`(|0`*&nsV*upbtiaT zt7Ab%_2dczTAobZDOMNss~c&JpkLW)HRxCB4F6vAt21XEpm>b>E0=b*NKr7rEDM2T zq=^XcE3@PBh(-aUfib{Xfv<%%tgVP>C17Qs2GoHDPzcb~-Ddi;X*_AWxE?&LJQT}} zt5%6LSi!@xZMnSf^XpRYw%F5O$E)-g;CkQ&;6`9Fa1(Gda0_rNaGQWRUVfyuH_?Qy z*ZEHB?gH)x?g8!<@QUheKx>ct5lu0X)+Ja69z-oN} zueB(63c^E(G1P?2CSTd$HJne**j5;8H#9t8| zmuvb89#-(Mh`nQrq~Kv?n^CjI$vi>Bc!=yxHz&f;lA zS|Tl(mP$*fWzw=~WLhpQpGKw8X-pcMR!A$Ns;Jf$U9u-%yMC&1uWn5aN~w{G)I_D* zP>ie8PMy?Ey|fA%t)57TX|*&i{V1)Dj(qVfsC%QQkvFZCuj{EdrFGJ}X+4Tcr>whf zz{k3}PVRnfg_ZFx7HP18hZQ`m{4!`2qqpmW^kMoazgx-z*iWDEQO*HXP*^#aq|egl z>5KGb`YL^$zDeJvf2HqAtaIfo0_iJk3GRQhA{u0(x~yhe8qJPqFfa!&1eg<;3m6K_ zE#Ny9*v>8e&6@2#C9zWjIl{~GHw^9hU0bwfZSfbZN}XC}JIfoId1etbe+VoJ3^%QY z1_4zrj%Wn11h6Eq6tJ{_2T|}+85EYak`h7V5WJk%$=OEc#8F-+?_Jf6sp{Hp#!zw) zPnpo_=Kn;N21{cm2Y=Fu)cpFQ(9`Dj?(q*6F7E0P5Nq_JS=*Jkj-yYv`nH0j?NwAN zSFJ=ObSuYsNhc?^1kv>14Dh1*;Nv3PTs=_qhh?*%cowTT z#~^rE!NbzVO3SC?tVh%fxn|fZvYj0>V5FP?oCpLDi>03JIkm6N3o)&dJvY2uX|#Bq zOherS+$_i|&z#QeRxi~^Zd=}t!X1@J)U|$j7oxj?dw_d^`+)m_DZm53gTPdQ?p@d6 zxz>vhTdAfe(OU9R6drR0WwP?cXt%3nWbm-?c(NZ())8CB%ZjB1`PVetH$d>PYPA-7 zl#xzLX%}okmba4lW1a;Xd#E-_5|?9v6IzD( z1xgE18|b)P7uaodKka8$p>9=RHDH`+Dg0HH^{l1z6y+M!t!Z_<5Be|G_L5xY_5JI5 zsnM0mt6cy4k~AX?R;0no!)oxbf`?_3ckr;v`EaWr21FXH;9;?%)k&WwN#9;OJ%*G9m!4;)ab7hT(# z)O1dt?WoFeraAi{lzw4K3X1OGEw!T4JrAYsFu#GauGnLW`l?3gfm{Ab+sRhDp*;!OIuf^ix|%SLa~e&_0y)O7P=J&?T8i@5)h=d57i)*3k#=R3%9@M1 z1?OQ6LMb)mjM%jNmi*5*_>ubysi#>C3XL0bws++s^#jcqdf)~icv$*@rhDTB4@*7b-;0M8^s9}WFQWa1zxh4i zA86>%SiLF4kG`^`-iqLJiJcb8^D{uTfjenw}E$ncY*f=`~s~m+x`y_eF%JHa#;j5P?Vo| zNsDQF={xzD?=ut2)=)iQTi#^(2W@x&JUO4~zF+(G%@!MjZ&fP)1$+k#fR!=}Fwj{D zO7CGSb7hCqx@9)%W(NkFg1oIE%?@#O?IJWm&xOKJU~XU@uarTEe0$Oj4&;nitV?EG+1ht zpkLK$J^7}W2h&G_eiihqpkJ|f)f@21^p^-NP~W*AvNe%LBCQr*asflzQBGJnXQI*#{pKtW})TncoYr<4yv@;O*2q* z+qiKYLfxUjVXmMhkPH`xBRT>&5;zJt8u*m}<4~FYk{yMidrW>k{XiXP-5G%p4&0WNhdos#KECL)>yTn=1em9<{i zScv$mNb4%j=WEuuonRM^nqB>ruD?xDl9KRf+)FFK@O| zqtWf@-@X-v+f2kco_~+-qYzNk-Q{&%+Oxc;DrM{4eJI=yOaUIS%38h6S@Tpx54lMG z$xdZ$HY&2ER$}~i;*d-GakQTRo&=r(o(7%)rUB0i=p~AQqh<8-h+c4!c&KL660hA( z2kLFv#LAaZdIgy7nzGC3zkU_b3>S5p?p^b+tg@Cq;;_#5ylFhiiWthc*O zKO@sLpWCvfcr7{yL+K4uVo86P$O4YJLHznmm~_2cPcs3RGscA5q0MQ=Tbt zd6w5{Vzli^tHHE=j*G=j^LpY)JE&wic1x4GC0pMapmjIWVoS=z%&WVU7nMhF- zapAfG(UmUJXsG88`js_@euJQ2^&lC2;r%1%SN(EHCnW^^3Z6>Pukv0e=vT6=nL({C zUtUcjLBHblxCgiwxDU7=m?B{5pkT{+3b|C0iv_fRR$~%LgUy00N2iP(zYIr$Dor9K92rP~LzoDxf2mIFLLBDDR{mQ$D z_Q2{eFM28HSN7rr{i+-dF<}fa7FYpTQJ`_9-YkqYk4w4^1Z&jQt&VVk>QDuuCeQ-f zUa1^&S{Zc_^?+4?Re{xjaRTlyXCW=RR!6jki4$)QQBrFBqP7g!HiAJ_oc z5cn|=*{^Kb8T2bP zDnwTUe+2#nTm$?WxK_Y@G6_ zddxex_DGX^0C*6XD##j<{VM2J5b>R*ESDVXY8q(GF(k5I zI8FnwoQwjM0kABsab41Xuf_@eBtDs-mdML7A1^r4Z;>dm#^sAs>1^p`M zS3$obfVV9Uf_{}7BIsAgIvXXjUuBzQ(66#-N3nk8o%x(InUp%qLvW=C4D{&WY^bnQGIf1!=p;jpiHZ19RtVF0rbDULFW;w#n zhvu+KGv~`)0MUZLLcqdSSy%j2^NA^%WI|h%y5YcLrU2PrHyq*Wy_TCdgMKAPrJ!F0 z{mKTupkLj^pb_+|@=e;|Egw9CeiihqpkI0Tl7=q_gMP(QPfI>6^@4uo)Eg~l<@j{X z%o5zKYgH<*Gm)ZCd3+*Ks%@#;D&&5Wo3e$|)Z|LB*3-2&dr6dREnjctPPYNK19t#- z0(S{?3q{h>7xF>g{aV=FYhwI8<(P6mnp0e}*Q^V4K-@oA3b5>pkIk25cI2ZgtHTRT}TN*zl!WvU1u68gPAdCf_@eBD@{eln3k)q zCXu@#HU<4ke$!^YQYgjBEmRh&@*N*kI~@fx)QqfHN_83B-Zycr(Wz;c|ByEP2>965 zW!`eyN8zbhb^fKb#b+pe4txQ8348^74SWN9D`4txD|K34m1sqy?-*c207Z8s*5g2x z%2|OyK+vyfg_VIC5cDhcpvZnD_w1lw6;<$zjz>_{DQrbaa~iAou@)h&8T6|cG=A{% z1pO+qU-ir7U}h|D%nSm*X(A5#m9j0;EL(ZAh)83`3S~htf79CvH#GqdV{mM4OMGK#eah{i{+iS=ey}Flz ze)T_yepT0!KIm6LzY6+Q(67vB81$>4UuoA9^sAs>1^p`MS3$oD`c=@cDnGBD+d3lq zRnV_=PD=QxY_1OaRkoZ5{YnPmZ=sp}%ij;B0Fblh09^8C0S201e$cPvdZ}ejTnTC-J`*>Y_!$^A*+zpj^bMx-OXpkD?3$_BomUj_ZDs~EHW zpkEbo6D{Y3p6~-;K42IyKd^v+C6nm8c91R?V~>d0fU>ZN*K3B<;J+xB44)~o+&s$M zqjZ?%2b%ks#pHY*P)4ad*TJ1be!sv3h?j|V!UO?%uuGCUq@_zXeqL)p?5wj+v z>4^RYyb8>yD(g6;y;hY9OZiE5HHqIq^G)C_Q&74YvY)(drADKt(O1JGksD^Nu=UvQ zbIAv$L~saQ@)4qsflq)>fqw#@377?fex-TL{q}=?WepMZtDs*g<9NS316E7lJ4Ix_ z3i_3@NQlG4ywQ;1#w@Qvzp@5t%aN;`4-V5XV18f$U_oFZ0qs_F*qklmCHYWmzF!oD z;lN_R;=l+&Zf9jnvvw9CCVyzxh#bDO*B6Bxw##L?WTc7o8K&5J|Asf`I1?%A zj|gAo@2dBxL!h4%ysp)eZKga4^^<{9Dy^9|Xn9ZZeb`K7pqb#;b!!A#Ih{++0QxiK zie8$RUD@FB2NTOI!$IjeXr2oM{VK9w=@i2#lR9+D=JlXohz$tF@3cH4RCT%IlF?_I3GCt9XV zK=U*ckzQEG`)45P17`wf0e=wa_ISeT0nR~mu8COu>pthZf{ga|sEs-fN*AGdF>ncR zscW?he3>R9ngm=9Tw#^9URTC8zD&k?XyUt5R zo3zT;qi_RoBQUwDRKz@m$+eQg)AjUk--^O*CQ?F)pkD?3D(F{1zY6-5JW;dvmj+*D zpD!c(6{~@uUo~=UvuRE?3i_2+4?(|@13^d2u8~Gns%xF6wc+v=aj7ms8q3(AU#V4o zs#YmCx29=mKvA=8foRLBwOZz9RIiK3*Drr=;<{2WXb|2O&Fz5gfgOMyft`Szfn9)I zf!zc&yTXH-_pAa#n?J7tLu*sBm)9$np-OvuNeg>Bu0!|j_*~I6t#4LIg^F(Hg zq2@jnr3tRo>sp>T>9YSigSx)esl$_F<1E*-%y4IWUC}juNxfZTS9TuPoex}4skd7C z2QPAU?XL95mv~7I2Ik_de?|M6iCi}cxE#0wxKhABp_4>C@>Phg2L5Pre7bezHC}49 z@L0IEs_Q~J{0r*WyQr?0w_o0fXfkjUa5HcVa4T>da651Za3>J-tDs-e4doG|ZW#0{ z#=Kh4uj|LFpU0XC;H&E( z*=fK%2&G?`l4c@hrlK=zR?|HXrS34lflOL9Uuh$x;rs~djs%VZjs|`O{2Dk0I99*| z>Z>(r2M9H&x2yJ6l6UiIg){BZWT4fQ?;yGVi?_tT9qvCh8-9Rp>#)G-I$xvW!SCG$? zzG_}XKLF+fh5_>f3jhlW@~hq>HSxlT7I9IHKpfP`vsRsdICYCzogR`P9l^sIP_9L@ ztnE#v)wo)5T}117ONm{r)x`#gHgqiw$ocK5$zJcve=TzR<;Ey&;z~uAA7nE`KLs{7 zIeSpuZwuGb5?#N;Rw!%@{2bT@*jAt)PueW>x3`iae=u_Gh{8_5&cH5KspQlI9o`Mm z?!X?vp1@uL-AuGbt=Myy=#Uk!G%>N~{dgmISi!@h!`u$sQFV{tVFeG%*3@#$70a0s zq|-L5POT9tu74eUN!ps*#dRV5D| zR(W*Q7TAvUE3p&PYSvMWiGE$Dsh_w!nM+Oq z{?o71j!)D2sfZ@HNajtco{s1Ypbwl0oF(9qWHmGnsA9>eznnwexxjhA`M?Fhg}_C? z#lR)NrNCvtL|~GDz9ty3$3#!_r$8JS>IAu=7{ZTWw@hN@WcuUwb!cwy;Kg zOV0@&7O#?~0KJrv1}o2k8V%J~eg=7G3m|w{!NV#qrzcziTq$5ilWU+R*{cv;4g3-K z6L1aiXW&`^@0XTMzQW3`f7erY18^fS*|lT>ml^hEFX`;jXUw8wAGFr;#aEl`w0Cgr zoxokd-M~G-y#jke4y^7+GzEA7co2v*Si!@R$8FCug9Zcv!*13LaMQu!4tWd|+}MU0uX(lpdK`EHcoKLDcv@h`f_NoNL-eePV2sO<@w}Bd@G}CRRx-Nb zi)g-Nbx_sxp1y);I`B7>i^K<~Xhx+apKkN*!Woz^?X+O)z3$qCcvz7J3lFv( zj63nam50SU81$<~+X>ZjbCA=+=}uY^8Nob5m9kU6$C(gX&hk2qhBkt=8u&?^`~fwvozEo~02jJ~VyXW{=fv5nQE?4MS^8;=AI!cQs zv7Pb=tgv!EYG@6{!*>hZq*vwo)qrt!6L~u;#2X3@=vP6%GI!j%R-FB^3+tc0rmy<^GYrEHBBGjr9#;}^6ahHN)|3aSxj}SgSg}uz`?*F zz@Y+Pk5n_hxNVXsf1L&NBhiz-`AAdLdro?_pkD?3Dt9rhErWi=dOqk^3?uTduXr2e zu3rk`#nQksf~-)Ot4`3ba;H&9X<8-dSLKoPlB2wr$UtWMX*I)yQROqV z#x&qr0dJ0I^?AUlck>eG1?v7<)pa=Vf5}SPs*=;}6%?ksLeW$h$nsT0GhC!YEHjpf zrf=_Nt;b0AI!bT2Qagv^c?;1$OeC`nY1-aF^e*t8$;E<;G+46zx0IERpDXBBc@orF zNM1b!{p#O@ex-w!pkD?3D(F`PLQXfN8`ES4G9_zw%SBs9$?2AKYq|}2L2{OKN4hiJ zmF`aWqMn_dV+#1M;5xM*4Ak$63z9h zekM)J)lIFP({t(h^nz*2!y~>gR}hGPZWFoUJh)|}D>sug!|$YvU(0#~a^{2L z?^*1?UX7=GGrg7mA-SGYVSLg%>0K3c6zE=ILBG->XGxObECnoW8FBcDWN2E}N(w*% zXMZ`b)2Xr+Qlq?1)MM3+sp{Gmmq)+4T08$PoM6-bO2Xp{v4Vi!HNRfLQtfxsLQN~L z!o|v5YcZPSz^BDuyAszqaqm{&RuGwK6_v_WD-k`p9Oor<9_!aSrpvb@CZm5)6n5(` zd{fY`)P|7;i=Gr|u$0JwC|P&X8h6>7q|sA5`SPBsRFF~YJ{0Z;rT`CEB_=efPDS*P zixg_!hJHD`RByXY1|+PO_Ty+j0Xzvj1w0Kr155*+6)>Q*IvkikkLU##$(=C2=Jj6P zW53G0tp|J=rB{IIuBn+z2j#CKn&F~OlZc_Oc`4{uLB9(6RnV`hQ?p2e74$1j7Ee0^ zE$CN4zZyJJo6MXVXc;FeL>jETGz0;R z%wMT(aUtbL#y0E|wNCjd@K0~2qNAwY<>!dL0KNpivP$v6+$N~>)9$a(QWCjrcgn|o z-=RGKPQ)z0KzDps8aLT|1|gaanBC;q2+hVQ3#FcB2z7H>T}>%RWQZE-CD|oy%Ng{m zpkD?3O7BTzzmi!h=vSP;=)k~C>p{ON|H&Nkna>*X-&H3G`c*y;QZlT5xui1?xI7EoJd3Po-`G5cDfG!mYH#Z9vekf_}v&aA-wQ@r<&O{VM2JHUigj zn1r1nJnaJP3IzR%_z{u)s$X75clZl%J#YhXBQP1b3Ah=!1-KQsO~BMH{~%-7X&#rA z=T7SG0`3Ox0qzyB9O<>RyD9HSG{r<}{ie)G4x;v5Wl{%Ccu38GDb&0Jn@2mMOTaRhA=^sDkR z+F>Fv35e`hPtpue0YSf#^^J!368H-E8u&)QxGV2JW1$r-ITDuNxwzJGw?bv%mHXhp zIdsXaz#w2YLB2Q#A06zaI(a?HAyuiSW2tg3)Q19d1M_&Le2rB311mwycS8m2G;XXo z02c2j=vPYpE{E@`-GY9l@KU*p{JYSvnysK;1^p`MS3$q>2zHVED(F{1zbYZ51pSIu z2>MmfuU@Akyy1+jZpWj*E9$9jjKmr9jZsfb)NC)S7usyS%VqBY?*ktI9|9i%9}BW> zkLdrOdP#9Y`1pP`*P!>iZ zvR?)Ls!R5q4WTyt7}&_z5JA5R`V}F2EOI9i5Oi949v$R--~#IXt_uNWJ#U+!UumgwfHy|aulnU5=pAPR=K$vd=LvYNnr+S= zE1118Ktdbz479C${<+LxllDhx0I%R3brTpruRAZg@r>a!A zJ6h4Gyw+zXi0P1(_b=S(df*1&Mqn~O`PdjhxwEetIbQ6sb^FeGF2FwpE04xYBB*@)NafSQkB3_bxN?ZL!Q5X&^1}qMY z5TLIum+j+=hTbV8mZfNEuP+K{oy&5`ND~pUL;J4f5sd;y17m=(0^LH{kJ!Ggh-f8X zWuOMsfd)_r(AC|Hxvu!Pdh)i5gMMYdPtdQdm(*<7tryDolDlcpuXJP?^eZvTHGRBn zqXwCg%#5Q3Yx8D!3>6;zgI&~UDQ{GJSEuH-26IqZvbxsZvp=R-Ui+Q z-UZ$hFmkoJB#Qn3(TBiCCYR}|(D?X?my}A@940#ThDOrQOf36p^?*UY%0EG5zY6-5 zEt5TvO;5a#@?fYUhX98HhXKC?4hMpMRbEOv1pVqUn&ENa2_WcK=Ic#Vo1kAY!z(9i zp6bQg(fQ5@xL`{FOF9Ltt9()lhU7FSk<#*Jh_gDavPPo0oNLyb?65{58V!sA##WWB zB1gJW1{O>dD^a(y)e*i>_o^dm00qzlT0mRCvZAdWvGQ$Li33&HDT02rlebRm-;I8y z<>{&YQEApRD9xsyS37dW&rE~)C^KKZpN6D4(_Cq2nmf&t=1o6H^QB>F{rv#Bz4yf_$Y%y_3qfxn*=br;ZLYk04QCy2_K6t(#`m&CA03k zdH&dzb4317=L@z>Tcxej&(k)DTe%B@itMECnnLEF)lPr&BjsbVqtg=3VXAmPcU}Fxurxtfp@ti)aO4MPMahWdUnG zEgPj#N7Micpb4~qwt%lwz>_LHqb$bx5m}9wt5|)l&_CKQSL2d#z>oYo`6#MI)^M#x zi@5n~c}am!wU1o~^>r)tqN41<<|{X#ZbMgBI&S~w!oslBbiQIfnB9WL*u)iE4W*$j zH}jH`zhx_({?qSse%tc6*27bNOTJ_)U~9ib8(E71tF5)}yDfFwd7aM2{kL}4O`RXQ zlc$b(WHsLz?OjZ}QSZ%MZr4<|yNT;s*Q*`&tdtsBxm%O^hi<=6u;2Lds)bQiIq-~G>ql2sj5z*R5I=amvF4n23>^h8(*y-V1aHQ(X zqkyAbQ%_~bu0g*F`c=@cG)lM46C3MD(65$)G!WUZ8bQD6*1DQ*{sSh-c;G;zlSKBb zpkD?3O7FsiQF-N7z(x!Dl??mhF69NV?9X=erK1O}V;6BAljc_~!-Iac29$+0y-`HY z(;&MxqIH0Ef%Sm(fei%eWhAK8X6VO=HgZwB@(V7yoEUCG-KJHYF7UkwJIc+e`x&qW zu%&Bh|DvwDwU@Nb@Hi_48;5Pt+|KG0*D~l=YL1{^slNpMiv4v48eR!&g2|TCu+QVo*0z3*lW|bPEFg-tEB?UV$k7g9WUrG{b8eA7Ul#SMl+l3x%P;+`v3usYQaj3Tl!U<=4cb=gJ#Ew~`sp zec840$YVE4wtR&=Z*??YF3jB)vCD94HA#N`IShNhsIoa6qD5d8$$*yPv@G$w6|XfqSh-KwJ^ z1-B`G=3<4}*8sI8np*)|yIiXV$+w|2m~~0JHab6vmN52XDL$zYc;t^M%^kV;- z1pO-LS3$oD`jzjgBKuX)uQaQzE#?hNG)2qy7%-j}T!+a7o>(7d&IZ7Sz>iHG=7FZ) zpCH=UL^W|pZQc~WTQ}Z}x}SQT9La5(FFGU}--5a=y-w=^IpA!K=;tm{)=@2{w?(ua zusyJYS2kMsrtIXUg6!$#E>==(8@_rs)OQE=0QU4sG2Zpv$x3i-^|g`xiWcevLB9(6 zRnV`3ex=DkXJ8r|gMJnCt7Dy>rMMO{)E{Rhg_&?pVxtXJ@py<_Cjch`Cjln|rwCYF z6ymD&%ikk9)kO*ir#<>;AdnzySQmcza;4%~@0+WEty;7?NRbFW&GM=k+6$)3osD}O1{txA4ICIbd zO_%yZqOhTPJ&g;E@z)d|L&po(RhR02$(Jg=NH$KWOSyGS1Rs6TWWMMo;AX!>x75FS zYjuMTT*cc_xT6xO?fT_ii0%gN0qzCv1MUZ=01p5U0#gOFih`Kxhj`dZH9d*G=}{CO zbA>K`jV#r1(=69kb5lWTI0NNl)_8vvejv?;9)fsDv%|pBIs!epQ?@)(^U15G|I#2d!Gj%*| zpP~0mGbL>wJu{0O*6clKGzoqB0!n{%B}Hb`4*4ZSFPliQS_lF&9ns%_SAiK-CF$VH z*Q!!s!CA%fBrV1pXub)&WeOrb@H)J0C8AxL=bW5?El!V|^7Yv7bIAv$q>V5K0v{pz z7ziF#@US+*OT&T$1rICFXgTClX?zsX^gJbl{OiooBzRali}KcKxIry=Se+IT3hsuj z6g;egsY&mW=1I$g3+Y+S^Nw{J&2uu}GTAEonWo71tKQUMcKnbw{0R8i)fI5f=C*Fp zvAIodVX||5hSKN27r>XmSHRc6H^8?79z>I(&(rm$zGHwfW^{s0o|S=+Xl4Zl0kZ+K z1A~D%fFZz~0!E17VMQ9Oay#n`!NVd|fR?_$;SD(s`0dP=i8NSwcN;t`(R#G4f6+RI z<^ncGkp?SxSmkI~Dr11LzzV>M0_N$L`|Rtw7pVn zM{RSvh9sfcg_p!+w~KWkWww0+ z<0uk3m;6#N;gs1ouHkhaJgneh1rIBDSi!@BbrNZ?^d@Mp7(A>qce2nN56A_lrHbQchv?Ce0JL-m?SC>Q@to&O9{Ysr;eP`H28Z7yS@Y+Qh zEJm)NUx{UGv|SC^a>Bo_dQWuF-7lwjNuF{VeIK+^UGxSWn?0mb`7rQErKNajIzU78 zIPe7UB=8jQw1A;p`BgRbOhfdni6BbIkny~gaCXm+q>~on$h?T=OIF9UEz|fbh^7O7 zGdWX`o_v`6V*1OZ2u%kp?U1S7p!13AIjP z4%R`xk{^n)HZy9r>+bOi<)mNkVQp3K1pVq1?>3^xs9}EZrKVy~&~Vz6`zf+q&otVc z?)8eGI=LXaEIWDd>6;FZ@uF+O~c|Mn109@z_3cI0E_F_br z0GFCvGoF}4IEe668$rJ^(`chD-@Lq6{4I*Ya9}ZDabScXuLBhqA}B-wJu4~09w|6vqz$zx! zint=-HEUWbkE8BK!0Nynz?y>G6g@q<{g38vr!_Gv)^$-@uTo<3QEq@}LlcQdhsXU! zuAs%YJ)i6kzKzLa*QQ*uS*4_iZb~m)l@u^mA!kw864@)fF{ra z+5*0=rGTu~Neeq#3i?$q=vNvr)Cq%r#Y*XaNrPqYaAdy<`jy7ef7uu+Kh~NopaXEp zp9L6be)$^fIg}V=B}Q6X4#>$tbIjmM+-2?^!gX^3a{)uGQq#r%#ol}W-&Ga+|DlEw z5JHte=n$HmefFt=NDU;^hy;+(LS1ay1r<<=qDWT)96)+YfD4Ku5PBzo^eRXbE)R;* z!AnOzujiWC@gMj;?$!I9_YbefS+i#EectP=y~?b4%`i>RZzWDZe5}q%)D}c@c&*uB zLRc8lBEX`+VpdrwguR6iE?Z=n*JP<5&M!LGf1KU0^=vVSP3HnvFzjutF zUq$vSrC;>k5cDfs(+B;kS`bdga9|-IvR|=q4Ej|y*=agKzp9S2rYOp?&b}q9OWt{l z2BpPU(64aB)dDpe$mCRDOWk(qS%^i4l|S!vZ$+(4wT8Z-ZqrszEqIek)y=>yz^%Y- z!0iHT9lf4hZ~4$K;G^ATV#4if>3k2GGhDOPgfeg+qWfJ-KDh1#U5F~2O($I$3aW>^ zKIm7G{Yu9wvZhrdpp-0Wj0*XdvpF2;rM`-TY8fvn=(Z)z$lsQQ~a8r46XN!pWh-&kj3sGtX~RNtTMWxPEP5jNK%%U)fj_^eeZWx7$I#vW53nz=pI0i{f>sL$c&XIcbe`T@ZHt(pb*&Z!)%UsN z2fz=3gMmW?^h>QrY^kDSqda^O{l9_)#0Wn<{JmpNBU*5gWGyVW<@Pyf_|l@ zRD0EJ67(zUU5zHB(`V>#&w9^M2oiOe$bMDLf+PN{?s^~etDs-0I|Tj8_shy>VpEy2 zm&x37l)on0SZlufId9I`oTj=HP(Kkksn)_JD6iSwj)zm1 zCdw&(T~DDs6()&GP6Gxr<=uKCO}gKOhB=oc-27gYHY6**{^IBAM`6Rg2_g;H&Fer(640EIe9QD&6Z|QbMO{7 zvB;*O_ChO6Xqr3Cljcps(tK(D^o_JYS}+Yy3#EnAB5BdISX!KpEiQC-kd{azRFF@a zqJyNR(#W)QS|%-s(RJUg^2d%=_xS^dKxtyy zCT*LxOW#8zD|Bm+Ch@W8>If+9n0BJjEEG8=?UE*|Q1p96Z;*CNyQe+u8uP-9+QrT5bZbgM>w3qImw+4BylpvCGvAE!^!r|Glw zdHN!KnZ8Q@NMBb&aO0oF9QPIC2(Q1{5Y28P9Zuq^J}07~z+AxGz&yabz%XDw0nbzf zPqR7e^vAxRBxb#l|GO5>!_i*IwZ%HnI(3n{)Kvf^-K3EBp;o(#qxnr>31Eb2H8lvR zaw$Y3fyjOp^efpagMP)!5cI1&l}7ffpkHY!4Ej}MzY6+Q(66d1om&(1E1iEqBYLWC zkV5w3pkHa_6!a_cgq@4g;Vivc*-Em8$mfu~9rjQ;2ufV72CVK1rCednO3@@}?3yMn zdMy$x6lgYq($yPSda5>}4$yVEF0k9^e(Iv5sap$J8yI6+m_KY^*=Q^AL$xk->sehx z&WYNx@} z(l&qgw$X{8-l*phyuA0KylDzW zuY)(x->k$btDV{^a>L9OwvKh)<&yVIiJw!Ke1PafAhKTt{VK9w|bQ&-KP6y5q;7%l7y!#FI zV91|E-Pyo7z`4MA!1=%hz=gm?z{S8Nz*JzGATQ}VWO%;}(d8}@*~;>~G`k)_HRxBk zaXm#NJzY0a(68D!-G4=+`~&zJ7y>yV=vOPN8F;&j4!hk|Xp~if)qvH3H3YoUEhW*+ zu7ZkAAuB|Ky29!>uhJ<{iKqp%fsR+UMc>gpgs2aU2G#=B2F3`uzvA&~P+14jx+ao0 zCA`x0y(CJ#e#Q+^7z=C!Yz&M8#sixGn*y5&_{S7@Syyd=XiH#%%a!!TH|AZEm4BDI zt%0Cl1^ueJl%8-IaJe9Nf1TG1sw)s(3H%25EpQd^JK*;M`kYdd`GIMnm_yYy)Ljc) z2TXS@`3>upyTMDM#MYknVia%}!jIaA4l$>1<=WeT+krcPJAu0d_6<3my$4ayuk2?q zXY8O~>rD^kn^{fbT$^sAs>MfNMB+ywnfRuh6D zRHL12QOc}1sMc1g8UuXW6RbL$e9O;_+R?dI-poIzp z5!tWmW{m7tLBG=J4Cgan@YZ|@d<6vkD(F|lGSabLwYgY1)fUd%lJB|Ohc)C5s_#&@ zmDOnj#*y6Ch$gzaw&S)0m8XCv$L&n4xr)hedo(8jI{-TZI{`Zby8x4cU4h*MOddK5 zG4I)~q9)}jsL|6|NVS*OD?*A&dwWSUgvanH>TI8Vi-@9`Bj{HHZ>FGMRky1tBKy^# zdV_X&v+fs)K@{|>$bL1X3i_2ozWRI<^s8+34f>Ug)xY^CUq{QKpkK*G@FaYtr>tFc zN+1tWt=kB{=mv_QU&)xEY);h>_t95m1g(Z=#chAKnU4C#|CZUM_FmPRIWKp0^darJ z{8}Y0GYgTVT71vTO@;yUxq^l*J?a~X7629mh64)$3j>P?SX=9h==WO;(c&&rj8V58 zMfR)6enl?{`jw2p_D%%-D(F{=e@eE>ml-sJex+!%IMB}{U_$A2m{5jUNiAhrhsb(p zFHmH^s`|9oXm78`ex=3;`c=@cloUgotE+i8{s3G9Tnk(WOb4z9ZUAlsZUSx=Fz{%R zYzMFHE~gu}QFl9V2XH5Fmw@Gr4o7vgcn_i(CQ>dwP807#biZqfIV-IP5IqPySZ?8>V-k2)RmWtO>9-nZ$E^k(|2g4j60DAE7D*^8Z50Tf`=76tl(iq8Y~@-ITbB< zSi!>@x}qk>9O!TPntsqGRz#%13LaL`a>_5kDAgx^2utN);1KI8qJ1d_ANB}&Y0Bs5 z$J8AL9PSEz(xO#IT1oLt%)yppc^!}(h33y(Q&eX&Vzg!a;GUQ@^w48aIuZjgZGjg&tlV+rk8gfu{jM@H&{XoDHCK#I0j+G+nhhq09`9=8YhA;|O7yFx^_oy1 z8ZPRU_%SvSl|ako3LR@pAV@i!wMc2WP_o=TtM)!XoXUcXOgB!9(lIOafmuDE|h9K(qPH#8fma{ zFKKuhn^MdJ>nPR*%!5L#x<3dv1T2u1g9rp{Pfw4+G`{=J(1*(N*OFR#GBlw{7VF!46=R;>za2 zc3aW6`JTbUq7{ON)s}@gcL*KDiskrkz{6?<4=Z?B!NdAL#KQ{ul`S2*jeO8uC~uS| z{>9;wd=pp#7$MM<)s*#Dl}jNS2?YHr=vP6%8dRt8GDI3IGtSADtIfx4G|BA(jTTZlfYBJ(*mwkE^>`v&mel%MRMaXJ7d4_Ah6oR$h`OhN-qL0xu%w>+UdNE=oJ@r zTZGnlo6 zpVm{PK*oKs2z2hlFy8DCO>jCnl&%ME@Jn<{Id$Ju-yqWhZb9MJT7*ATbvvRvfIES^ zfV+WvfEmEOzYVQ5eM| z=vP6%YWB#jI35>yqwAB(^3+r>}Am;+-SuZI>+tC{Q0xOAM z)>2=($V-i;N6izHOhffluA2s23S0(UF5vdMTIsLgX%g&(}C-O8-N>un}C~vTYy`EpkL)5Am~?g!=@6C1pUgk=8ayd zHC-1fLC~*)e#Pq%^s6hJRMTiF{9B~KQlAL=l?|72hSb_5=vR3fE$~)Z&Uj0WvPWow z6}(h*#hOAX=vOkFC`wxGjDwwhb671~%xpJo*%J_b2iVHwMZ2k7zSY*QrIooxqHR#v z7T6B>99JrRg!*Q>-XId?GEe#>U6XaYgM`X0@&Jupd-=M9;12Gx#;b}~`Wuj-Zw`c*zeYBh|l zh)q#Tlt_csZz@Jt(68j?;pdX2!ZTEJ;9@@~Fw`9Ci(ap!mI7g$s6!fcqH~Lju=YuB?My1)(>}d{GNKFD_rJ;P3gHbU^bEkRIylGgP zFU_C6krqe`rr~L!v~XG^Et(cfi_;}^q|_axCDI5LSScx~&QfV)S~@M0mQBm0<uY4x-Qs-1>h0l0y@gqwrZ;A5}R)yHNkQwtTj2eb#Nle(#w`e`&8 zZH4+8q_xwS^zF0`Itpr#z2NX%))!tsU)S&G-`FsXO&d`ZO;UFq$Hzj8!2D2kWLwfT zf_@eBtDs-`o(ht3dM~}7KFIG@PosVMh>vB@5??lS;Gx(3FbL0Th%P)xG%?2!d=gXXm%473Rj$0>gm$1oqx)n#$j!)v)g; z_o2MY(@R@wD>oeNg%7dfAt5jpWO-c?pX-{pitr^vh{=vsZam_JV zY~WX@y?vDQ1mXJmH7!&dtG*fsj0ZL`byz7{L~Mp=a}zb%9gCaD0z)^RK;3t|PD8h` zmCG(!$G4_#qStjh_<3)OXge2)_O33qJ)%j#4#19HDYCsf#LiyQe=60i7U^D1N) z7%7vDveGR2POWT;_&un0H*ulV9GW)wtd*L|F3v=(O^bc#_3L13$|y9b_TiTM0{a2` z0|y9fF;r+aJJ3tIgJ!z#Td8RDwIR=gSElV8>|%wG(bDM9`UakogzO;s=`tfQK_0I9 z>ImRS*VMQ21(bM2sC@xllFYEZRnhDp$`Wb^fa zSn7`Rx^~w>RV(cpYvdEDJIU$_t<^1TQM=7);mOoZ0ZuUm`DnDXGdK;=z(w-)wg0d$ z`r4p6le%96X8~se=Lnc$TOE9x&O>xQZ~<^(UD;rpaWSGxfT_SVtHc~?BeHmnddTI} z{ioIG(ZDZEF0G(n<+(iQS7P(1!#w95 zMoSw_+Cjex`c<_G#EVsd)qvH3H3WIZSo-*(3>*R+3IzQs_l=-m!3@<6}6zQ?Nx`ju7(45UH75;0nY znQB8PdC4u?JpRPBmUv@{t8u`1Q;@GX$Nifk+6>s-{o61ng{&~ipgfYhq6G5wY3Ew6>v<_3HEl%Gcs+JKXx>n=MM$^u8C=zv~AiheGgGv z*2F=Y#7DU^>f#;KP84J)R$-SkS%sqC6X783mUd5j*fr*>iRI7S8|9`crr6%-_QYHm zqI$Btjc0P!?1 zeVv=K9BHuTsorKpeFu0Kcn^3V_yG7&kahb+|Npy}v@Dke>|+!@sTG=VM?ORJIq(JW zCGeGiUrMACy|iB=8UlM{7GPFjHehxEYKm52Y!jt1)-GWvb#no8n}Yl)IS-x}(J&V^ zf_|kvSkSM$r{;zT`qj_;?ND3`z2`?;N$>@cy>s>zu(Wxd1Dp$-2b>RF zAmAQ-Y){oiUTXIk*e^k0DliSW)GI~WR^{bZ(sza1e+3Fxx+t<=DLD(qlBenhAtO}v zCo2_7oi)>7qM!NCG~IK+^S}$hi@;03Ux1f^R|Nc0@_n~Sg&^N~Qqgu;Kf!A#y>3dR zBy^W}u^w|L>Gv=U{SBqJfVY8nfOmoSfcFLTKkd3T*L;ZRBNMUBwvCWXa`|1y6-YPy zq`sun&tC@T$)H~?3-ci8S3$oD`jtkeGin}=mZO@KoV63#ud1M54Vf~E2}eQi*cPd0 zRPO-q0`CFu3(#PXlIJlUCFn%{BkKMR{I@9-WfxD{PY`_yd6m5#X03TbgeR+JM>Gd8r^yvfr*C9_<>u74nVY(Ktd1?0PBw>m ziQqcFb4bvyf_{ZnsE7Oc zSSTtR3ABpAPe}bF=vTQhG;U}Gcp&X_khKq~)6FF%=vP6%@{NT2o>-8}or&;V_xqcq zlMgM<9-#9)2s{KlY?a!c5c%s-E8$9&w<5R-%YOF+noqi>L{5I>c%=FhbO*WE!aq_!MSb| zA4fGn+Yv>pZN`^I(654iCHo$1gIR!C1q>-czY6-5y2C{J#5Ue16gH8m0ifw2O>JiM2#|s z1^R)PWXiUQN)hYLce0Ub+=p_>j|5XrnsakyI+494=vP6%N{8i@j}G?->4Ua~jU z#nMmHQ557uA|}|+T}i~VU!-Hwu@oC^+2+#m>4bD*Iw}29A}C$D^5m?noU(&-N;;K- z7Eij#Af29Tm<`gIe3YkwEx7a;DV&|okyPG$%59s@OXp{mj%QU?@-n4EyC_|ZO26*g z+OFHWu&=e`AYGa+OPBj)(!L^HNg=xsG$dC^at*w>;QV$wduMv9gS|w zw*Oos`HktObTe{U9d-L#({1VYbVs@~-IeY}tlf>;U`D!^TlJcJ@B7mq(*x%Q?yGH09geuHoMMtU>-RSLLPsQ6ZTTLsvE=5?sl!Fpa~zZz04 zi!=Xn=HJgxq^-aT?(N?%@dIAT>y$4^jxD3SPENb3TeYrp3yFU9nxW9POw8g-+V7_^ z7~hwMUoTg8<1{EnoNVExi+lPCbQTggYvk|LVlt6cz4~b-tb)-hRcqBEdU9mHitJZS z1s-Qyki)t>1%Fld9}RVbY6?B(6z?$_V8n(w4bcEN9XJCxQ;M4Qsfat#XC0@nf4>q@{dn<(g4d2Z^e zSze=Af_|k#!*947zIv9=;%&ld4#$OmA$Q?d3PAO`MG!3tECwtNd=pp#7y&E^EG6K@ z)H|fNYH38v0Luc)0m}<`??gk8nQKKa^?D-CS1Y413RuPE?Jg6$4D)yH-w zRv>Ox0^6fG3D^PH5!eaX8Q2Aw4D1T*CSaMN^JzQ9?`maj(|ZpJ>t0^3!!(ul_L3GQ zdD|dqz251ISf5uTU72L6{Y^3GS89u(U)|xoK}2aYVu&%TZX5KgpkHZwBrp4FVRyBc z5!CDvI^1xgSQAIi#l2nwk4Cs9xMajkQPa3!BIIl697)~MUMH)D8Gz-eZMPHYMYmfX zr4@h`T~kJAGl$AftGkS%ZWUlvU^QTM0sEwu!l>B@Sva>$R&c%N4XbbHU(nXC$t7hi zDlk7p_N$;@RX_7Cq0O^;a?r12ddxXRf_`NkLnBq79tucv{X63J4(>6BKuW!hdM)bCvX>VH*gOyL%=>?-agiOf_}v-q@-s$U3u3V zN1O&3Io_weJ^(&6IWdf#;-DxOdFe0qnqIw+QThb<6!;AI9QXqG68K7>2Pu4pJO%gx z6nJ0H7-D%?bmqcgsi<^bjdf__CS1pSJR6Z9)Zbqo5HC-)5cl|}|ea2={^ zef$*T#M36yhEj~Q>KR1Ox+v&ZLBEn~9!!*#op(@l2v_j`x9nG^&ox9&JNjcvk-NBT zP~W9hwg!TSW!`Xj*5_5SJ}7)=byVGDx;V-GoTfV3M7SeMbc`z~xvfT?|jQ6X-ld!NY3l$TY9N<>0Ip_k-R>kp`;@9+t686&b|5Q*{&+JS>H)fiqF9@5G_t zVOc{EK*l!m|1&(SUhuHW;9&(1D|lFDJq#X}{NSM-1P_ZHT$`9o**e&-^8*w_pxBru z8V8IAHW5fmYhUunY=&ra6E)0I00D!NbznINEqx1b)ycwl>tQ zF~GN-za?iyb)a=!tBIdwwZ4}`E|&djL)6FC>SdiejjU?bIO@i`ddG9okZ#A_E4vof zU&A5e^cJqzZekak;HAO`J53knMlSZcxsfYj8dJzb9ZBAi6?z3ktW^B4rL6RJS9#1Gp2o3%DD&2bcle z3)~0XFVMq_vZKfh)dN;)=$q(C525g|D=3qd{Tm8Ep?~8s>K+H4Foj5ir4)<`)j6oX zpjEyEz5@PHw@*hwH>x3`CseZlvl>wW&nk_bvpa1;j8~7yk<+9Mt;Id&-nqGM9$;Qz zm{sEDp>cJ7D-ns#dSD}WqXp3%UTfya4GSY$1XvVU%qok9q7c&&i?T&uSc19{z>=mQ zZyqfitC6m*kuP78B`k}+7K8EYy@l!j1w@GYl*JK z+9rrLby25|SXTC!=C`13%eqb%Zegy6*y80~1}V%x+NIdP%dt8KabkR12By z(VS#;M8c6M(qMUW1P|+SZ;9Yx5k#ef;9B%kbI?S(uvw*XKa|A4ZS_<$tsLn%lK5zkWVO=Rg&Y-#&(IvoC zV478GM79{GL_Cw_<#Ou&)9SFWXjOA%U6P$;Q2n+p5m8W&mLbrC9_w7i4mQQL)sX)O z?sN@sEpQz$9k^bQFXVK!x)IS$z|Fudz^ww)u%#lYZlxMLENgI1SozTvQ_&1lnp4y~ zZ&|A;VVqo7RUbSo>qH7LtXLP$ST|3yc?10DyS0GW5$ ziMO{|e-O>VZB(L~4XS;(<-Wjv!2ZAi01jc~l8v%%#-LxRud3fX zRX0eX@LkoPtR#Y@^X`itqw1d}uAT#)2VMYP1YQFE0=x{oB2eEfI$T9}#~CJn5RqS< z_%)PXHzfvTe{1yGp;Rb;ruzNgP^{>tgUTC9iZ!SU0}D-{nSNAQ@0kdHZaDt z$k^?t32hAg>r%I#)j>zpf3bm=KsA83i?&huWXwn zib1siuplrTh%{J1zhc#;K#Q7?C#y?P5+BUcl64BtJRtvBO~rdyJJA5v0FDHH0{j#>3WzjVGD}@XO9cJOQ~oLHvAS^3ud0vL zEqM8Zex=A3&J>6=ST)fk(qP#%6!a@ahWAbp^sCwu8}uuz=9V42Q3m}guYz?BAsgF* zINuKk76KLq76BF&8o6--&6L zc9b`fY_Mv&pVMkb1HUl2_G`v^ElLp%>i0pK$NP2NmVV;uL@qfA_@!T`9iPm0CnK8T zA_b(A>ZyoM0|vn9z!?I*QUL*xmq~_y^_R1#I~zC$I2Sk%I3KtGxDdDqxEQzum3bzPTu ztIu0W?g6ASdl7|~TtSgcwcdLf(JL-$75|I_?Wfy0F7In7z3xg1HmynTO+~MMSmmCk^0hTZF5 zfPPhq9~tzkpkD?3D(F{cw+Q-G(66-M4Ej}Mzp4h%bxsG)0L~O(fRrb!ddOLb&NdN? ze;J+6bp_E|%r{1+Z7p;zK=VT2BH&`zl3T8fpHmS{11<$Fv&x3NsO=0=?l;o9g1RfM z4i{2;+d<|#ynl`yNzV0#k^H=Bqs zivAqkC+JtNd%N|zzO&Iv-nbcJfS60Q?Bn*sHwq$9zD;Ys1H22o2fPn_0DLIOX6)>4 z^>;66qpF_tF$$m53Qao7XNW!rz5u=iz7o(QMLN-j_iIE$aHgLHm=%}}m|cLHJiKfx z7W6B5vePn6pafb#8|VmVE#+i!OMwD-+u|VTSGgfL3b4(6(62ZXIof-S26P(-njNT$ z$I_dQ1C9qy08Ru>67c4i;;Id*Um-f#MM~wQcl{JZr<$nH0ja&UN*$%){&ecjaCI@! zWS;spqO*XrfpdU!f%Aa#feQq5>ORq%s*AkT?lG`mg2Gf_8gQvs>d;h`ms^PpS1MhB zLeQ@w`&H1dL_@2Vg^e^c=vO^bDvnoURGR>s8c9phg-OA?Iif90gzvfWy-G1&2i13| z+sf5-pfB~U5lwV;#dNbJs5}KUqHbqm1>$DCvpt%VfE|Dxft`Szfn9*fz^=e<0>)f1 z%+0ewfuY^6y~h~3m)9%Iw@Q0^N!{Gy1uBiC4egD-XKsO);`xsV#zj74)m1 zUj_ZDYCF52(NhTPstX0B2L%0!87SyixfM!ry{cpB7ROn4!FkZ>U&=Xd8}5##-|8f* zCytLyRKN04OM4%by8T%T?AZga?Sp5_2fj4go)&dpHL z8#Chs{VM2JLBASQ5A$|B0z3*l1_b@8p@p2zn?I#BJ_9}nz5u=y+SgV+@GEA1b@QL`~RwL5Z~ ztVYA3Wh`WMWJc3|XAwk;0*e8Q1K$Le07d{y0!s<hAzB?+1NauOraLVtc$Wo^pcNum73vbfrtOR@fqw$~Fu zjd~IJYL9{rY=-IdyX%1){1Rm{l!N3=^$ohZZ*>a_x7H#t)&|w>i0%OH1nvUv2JQi7 z0QUm-0rv~|mZc~ZgX#e*k?luMdI*JwT|o(~?B7rfA^jVVQTI6TgefRYWn{lnu7pAL z1+DTW@D=cnx_vr$*bNa!rJ4np)z~VKw=~$#?%WmGHr?Hp_O6E3;vRGF+*~&gFfTC7 zDjBde@62x{ab`T%QzLhy1<@Q{Yc`k=7DluPuqd#YRThno7?8OywCD>KI9XdUA zx^HB^l4GKld|K)S{mR)|TFz=cdDYAkWb@y{)VbRGQBN^t^NvZ8p3J$ZUDn%jPT{NR zwPK^MYj5z9l1^*+dJ}iL8Mp&SVn={i<3IlFj2Zk0yO#XM%>_t1-`W|6a5im6UIp1SmV9ursg=Fxe`}I58@$XYOG8g^s6D&Dc%%C(68t)w*W!E3i?$|QSqfT2SIiq5%jC7ug0lH zJ8dWES89yiY7SGOjA+a=${eV9W=|LEG)vpFpkHa39@(#|8+d(g1a1Ou_D&+&obB4% zIn~E))ZGr;0o)1PC15$DBLS_A?m;xeM9StxSls&%-S1jr&PwY6L=OTFxm?>RopC&3 zC2f?{Q@Lr;hMO1ktDs-e#}t>YZ|9~O$~bm{A`tYepkL7s4h9YZ4h4P${1`Y4I2<@a zKsQo+A`2$i?kl}L<4n6xcA=xZzUUI|=;vH=w26vdj=_42D~NZj?suHmiBc@}6Hq@9 zIH}gcC5Y#VuxvJ~W}gU1Q~bJ~OrZ*s#3iQzgPC$=P2##HIbEwWO{}O(1b#gW&9i}X zT&^%3(mD^(`M?FhgnX&b5k3zHxuqv=xUD>uoy9!r^{pnlO zt!Z_bnsu)NQ4=VE7SIMd0tT#3PSM-55>6mmJ&pEKqwOTLpkL{S)DN~REw>x6JMgbZ zziMc?8}zH7Uj_Xt=vTJ#3;I>iue5Lv`c=@cf_@eBtDs+XjB+D?DK=I?zp6$%wV)Kw zY*4KY+h7dvZIc(hK7s7kb**MwmeXo|FO_{A2~``SKDJgb>x^k6Q>(^NH{R8ij@$EY zl@^9YPHPIA!ah{)SUOYM!W9+8TlbydB^}>qGno7JKhv+C1D*$70A2)M0{#NL47?)9h9<6}b@4XHAKD#4FujJ->!!q@Y?f}F++|C5 zp|qJYsQ(S6w}7{ScYt?+_ki~W+*vFrjT#>!`p85$PMU2}Ch|P=;0mN0eo|l35$#CV zLZGsrx)Jm%osZ=_q{};Ht3i0wYDK4PDa)x^d1bF_Y6!NURX%WoYE@Vps{yOKf|!2x zGKt%#k!DR3lX6w+1)5Eubagqy$pYC%)B(CK*9CSP-A_Z?XzJDi)&|Cymdvj8&)wE5 zT&+vpdR7M=QUApTUXpoK&mZfhW)D(i(654il?RfbUsXZB>dEFm2>MmfuY!K12{-6h zPQFp?;b;4i-WF}Hb?Hy zqV#81YAYScpn4wB3npqbS`AG`FCqF1@G|g9T}c-B>eaebno|JT)g*o$%{PEIO`+&z zZ=k(UrO zzfvn;jQGEt{p$4DhA4oW{;CuC%}=s_S&3IXhFQDKaB(tqQ-I)MsS$3XC2j_Sho!km z#>7a2<)+c#VL5w4;lp)i)Pv9wJgjOL+F>%VD-b*^JlR=x9k1qKj_tOz)U8gWaZUn$ zY4YGJS>}P6^LM_+m1(u3m#UZ zi$BGN#^}<@r{}@*O4iXE!(ti-j5md*W@OonH$}7=u(`<<*q|ee&X$NKm`GE%M=6u3 zOV+>dx>zAIv?ia3<~G2#E|=%2p=q)-%i+3FTY^P9jD zzzEZ7idU@4r4Wq-mIjsqmIam*@K`mhhWZt(q(sn69V>YqC!=CMd!07&s#~?L>v%XB zd8ga2UbeL@=WF%bevGM>)fElDUdQ(KFYAy(|6u82g-*!-wPQt+_UhWpTv`vUvbt=Z_Pxeu_CmMAp$ zfhZgVe81M}h$29*u>H=9lZwxQ<|!s(fYFNU zG(-d7bl?o&Oo48XORT>BS%}Uy5#xvMbFM2C&3gDOh-i5Mnim2W0T;WL{B!k9rXrdK zTnb!fl?}O5=kAE(inOkv?n{dn@AxBf`=76tl(iaG$-YeN3)6k|o!Y(j5 zCL2?uDME;?lf*bs-R@5CP&{spHhb1eO{0xyuJsRMJh`=Bsf7mBKHPF&U_W4g-~d6M z7Zhq&^NyEv2aR#xw~|N>Mn51NuWoa&i#mt_+*nr*3Cr9X3Eh-X6_Kzz)EUz)rx$*{{%6D^G)pz;7S4#ZYsf zjM5ZW>h~;RoO2FOqi$ezjo@Jg532|s7VlCscv!*1(#RYYlV4Gn zf`_HZ0t}ftMt1v35j?Ewb9h@{0AG4f(Hmq-L>;c%0#77HEuM#nqoDR9f~;1t- z76KLq77_Rt(GqqsM2ovfr*FP)4jvZH8FnNWJgnR$BMny2uj-LQ@nEVO899P}rABzw zhtHs2X+jz1PWg(uZu6kdJ#A8nG+05u((#k}N6@b{qbf6|y&*xrYLg=6YC6UrfNOwj zf$MbEs9O?P3K(fxLBCR41pSJgzK-Pc z)~T=(jwsRK86PU%Co`-{VFecWK7j0zrM4c zf__yqxSHkypuo;H8X`3O@frt(=QA1Jbb-3{ZFKGp36O~*h&9>ht zM8l{K<&qx>rkphA<_)cf%AjABLB9(6RnV{Ux;E%n8Xtpx74$20gP>nQMhf~>p-@`# zG`)@1xZSB)J?L!JopmV(Pr4h0dw?0hy;ezdS*hNS=#MT^o(QM1wv>?CPwumXD6`Uj z1nozG$AHIyCx9n`r+}vgT&Wm1T1G#E=vfzuhiW#heo-$WJESIh0i_p#mt0fCVJ#Y8 zM)Zn{x-IcQs#m=f^sAs>1^votHjTceL<{;=q`|_YE9h6E3hD^vshW=#^s6D&S1|Pc z;VlyMt4+0f!htc;VCB_X(654iHKaNh?$&wE>k@58Yw!!4$)(^HGSgmE^SYXfKE^6v zXDK>LnaXw3fJ=ePfXfBakde5reZUont^|H#a$Tv|Kh;%UQa~HMjK8nzdL)1Q1M1hf zsL+ODP+f;;I&eL318^g76L2$d3verN8xU!*f__Ce4EmLlGS&=}Ua7r&7b-yy=-2YD zQ&>eDupl$axv95qjMppDm0sC(xMW>mz4|($B~%+A+7K8EYy@l!j1%OMKwg=HY7<18 zx~Nm10+l^QUZ}R9Zp*q(J}@@MC}r`W+KRgG0$T$UT}#|n4KLezNl_k*%%D7^S^#d3 z<|L~l08Y@aL<;ui2>MmfuS8U55*L+6PWF#l$Iy)K?rA~4GE1h;tTk>0{VGqR3JEZ% zmU9+D*~7PHg_@Jl^}vgA!_OT{5q~^(o|-T_=F1lcHrc9vMWe9LZDRWMG$XCyVkP?3 z@^4L*s)mbtCD!C7q7rDiTxr!TFhNTJ`+Y^~u5bz_=l+--bIc?~z3#gf*RKtXv6}?_ zDo@XvAFTx&LB9(6l?{Dz2@CpF^$LTnwL6aj4(S!_A47U zl!;WW67;Kv`8Wpss$n|~LIG(jAM~p}p`>51QGMhf2)MgwaBYXf5hOjmLiQa4-&(Yhv5$aNgJ z*Y}d*No$_p5QVY8M!?3vIAA;w^sAs>olQqLM}Re{ldZ((Avzzp0JzXATMdk`7bCg^ zm1%%3tR>K4*0!*hblO`N5IJe*RP@OTHrchx@%c- zoEy9(hNVXqE=8K-F4(^8Lx)Jhw{q=m!0o^tz@5Nd0{e!XQ{97T25>KMA8@}QYshgq z-;u~Wk^PD`3HlXXO#^N2YT^n9{Yvd2W1TH|f_|mpBSDAS8>j>fBWfO1DlvS8%^y;H$$|! zi5l&W9o!M5Qa7GJ-FLiB1`*>1mt7J)ZB5-ouTwTmok(npXge1v%Y^m`+asC;>;UZO zmCZK3DLZ>f+XSgjwvuAo@aWx8-yPTk*wZW9`Ps=z#5UJsD-?o$MJojTD(F|Q(Ggzv zH>B6q2A7?UR`PxlPa?&<*O}>+Rmj1tdYjAM0p11P1KtNd06r9OkwzBnt^e*NC8d=G z>|+!@sTG=}?)ePS=fD@hm%vv7*39w-(@Xm`q9J&{&jQQ}%m&OZKuzHTZ7bGnU^W{{ z-CV%jra)>4$>&8h%tei$Uj_Xt=vQ*!sq=y`EeHLIfh*`&LBG=J4CganFlT%T1pP|M zfXH;TqF5Pu)(!gAkZKES48=S0RFT`uE-Tz{*l5It=okxIx|{*0A4@XMQ(rdBe#;d5v{Z*?%#G+w=k z=q2DUCRge-v16)NYAp`-c$RXV*}kXC2B>sq8^tn1JXzz*Z*5$3pkp+O?EoM^@i$P}mmO4)`9hy+F?(w7+h> zgOwVhxJiE}6m|x70VZ1|S?9Hu+zrw0z#hP!z+M7YNI}2qdnV;}Hn*Ql<4gfgu@-75 zdYsMxPD3HFu#@3OX$~le%96X8~se=Ll%umg2n(s`C(?4_p9TSXVaKW?YQu z5@0GY%_{L%GdiPqje5xC)cvQ`DeE#vh*#F727$$YTbD|Ya#z+YcZIdHgH2IvwJ-St zce)0+7Pt!l9*Rkb7iW2c%>67;J) zqXzxTf}zOi-X^f1U*&1F2>MlS2Q5dk^A?^gTDQyrabZqisIwP(y~uvW(lO{)c{SR> zaz2R;vIDTA^^yk5RQ6o*1!!tjyGz}93cPQ2MRPY`cVG{z)HMX?+zU|x_690oA7Ec# zKVW|W4{!FI8z~n)U3nmN2YH>IZ=1eGWWNgf6+I*9R~`{MvR~Os&_<|+T!rnhF6dXi zJ{GBUj9wJ9kB*HZ7Ny zPb;Jq(@JUOG%Br&*nW-&_v$q?Tc>6!QwtSEXKfEsCv{UV z_0woH+6whGNNcAt>Dy@?bmYUIoqtIjp)b6CzOLWVzp-H&n>M1@ZYwit8pp>%DNyr6 zJ7nw2*9ZM7=vSg$4AQmfx-^|G(QPSUHy@fr@=Q0To6^k`HI}RI-I{Jox2HSOo$0Q0 zH)8E>)aPfUdsPqvMLBuX{ppYCf%IT{$m+GCOpl~TDX5E^uX>}?s-uo-Pn4caPvz=X zUp@Cv>6!GbY0K=Ko=eZC7t)Iev?%ozXv<^ZwR>8ordOzxkxCc8n)SM7uWslyvy}Dy z2H*0H^k(|26!blLQQt~$tAOFz$TgAuN`rD_zY6-5xz)XTwdRz_hIu!_r-SWQn~4bker8o;-JH3dxe&1`Ee5H*1kXaQ}Y zBj9oEhG$*~`c=@cf_~K`E8!KqAXnN867(x=I3oL1(63h18ypkMh!+a?CY z=4zFoUny~m+Tw?_#lgTK)>q`#rqFvVHxwIR3#lJdcNlQEEA)H#+Z|~oSx*%2H!osZ zGU-)Eq4_h{RDu>WVzf&;ZN{vjhaQ8{vA}V_@xTediGuuStUr7xdlvdi)E!w*s*_Qg z;!6FVnHjyWpGMul>LBE3ayY{^W#Ezb;IF-|?DeyqQBIx^iO%7=$bKbbRiix3Y`D(qJ>crLD)XigcM7+?uHOx!0OPVb| z=vP6%3i_4alb~N|1`YZZ6I~JXD`t+MUsWSu87yg>3(c<3enxt!ui~Hz`jrk@74fec zOG^d)D(`jViJ`UI0p3wm(hBfE+UFn>aZGJa4dRt)Bl1Jn?3DGErNg4}P%inAUs9HJ z4lem9=M`cr=eIlpr6Yl#06zte0)7Vk95`CQ+EPc+`Kj!P)OC-g?l`Y&ckPs0-<+M) ziPW8Bb%jDDnC-kB^eb0f)){p(+cex)}t=vT5Lrpnk7~Ih>vB@JD|K~)O$WopQKOIXX*3wMfx&*mHv^wu7*I@n8h-ZG@C8_t!6_s zyNSpduO-5qh=u}l0doWM0P_OFfcXSGQ}OKFz~5@rGp^?bl>fU<6o#X{kZUW5vDOHS z)TM62Tt^yRLgy`x<~M;QfDxwE)S^X|OCcHwEDZ$xD(F}020_2#WeECJ(654irKvFJ zS2_a||7*0fPf8t*4XU*vq>KT+ZStbmC%DAAuGMVgxVgTUbn-6y)rP2#t<_6~I?Zd1 zoJ(LFb>m&V(=_ThG!M6Eb^nJEufeRTwIq-*M1`2sAmUj_Z@F}lX% zz!Tm-f_@d*uZ9Nws>h@<9%{oTz^2BAkd-*-S3cF~5Gm+aLBGh#$$ zQR$DxPo%*L9+vunb}WR6;Jl^4uo`p#8u;fkQjS^|F+J!9DckssC3ETzT4cr6F5bzes zKxLh$*~L(NzlpWbWO4QYnhydG0S{ZHjK$cXAGMNVFPN2BFC=cEPoVjvYf5AmcExYi z-Ty@0Gr+T^K%zOVjh{pGyo>bY{Ec+3h9BxnF77B7;-GpN&ER1L4=Z?BjW(~&_aGW= z4@{cLHVPgV*$IP(<>ROZXbWN0YMXsR@%WHxr0y3tz3H>a651Za3^q=fSs_sS~T(BgJ=eDFK{0aX|RHa z6+A54@;BPPFf7{~xCRevSJ+p(0spEzETxnR9#-(M(qWkF#26F9=7@A81-Z70G4|7R z6a~fd6(8s4t|SK9FVZpTSc;0EDk9hM>4bD*Iw}29BDh_;^5m@C<|e14Qz^)wRW})= z({l~1+;k=%74bFOXlkG zsPb|vk=9(LNP`tTtn7D;OO$OnBMnyYu!4ux%Lgw10SoOw;2Q zAv;08YKq)lodzRk;H?w%t2!cWs{%5 zDLeIwvtUsWnjPZXEy%UQfrWsDfkl8t1?ZPu?DC6yNpXVo4VOS+1h6Eq6fjbNz9QRN z7`9R#Hu;Hil+ia@&g;vPGxrs^WJME^xJn1_DwcXfO+sMbLAEnrQc z0Te)_!3z47dYiw84f&5%N2y=r?n{utpkFnDer5eZ;W;&uJj1B*tap(}gQYb0@DhT4 zwX&LlQA06{G)YAote{_MaLB7cg|+ZyW4o_-xYbd0Pw6UbZ}oFtpP*mS3PHb;-@En= z&(auw_Fke$&03Q@Z>6HyB9_F9D7@qfWlOFB)ys%paZ#)IXFzD%SSVkU=C0RJdfk;2 zby{ZUHxd2SL`Ann|9lJ4+rT>}$CchFlaU6CAwJSz(F#GoYAcUr-lmFguD9#ofPPg3 z{i+Q5RnV`3ewD|qNQ0$CPNcyK`jxst(654i#h@7UtDs*6{fg7LpkD?3stbSVXHH5| z4)ma3LCx~R`oi*~6S&xptK|$JJHXZ6T#7GYWcHp2YD_IUiT2#^3JxLD?{q0v*8?~B zB{~6@0q&;y23_5^x&?(>YmpdhgX(rfcK~++cL8?;_W(11dx86a`vuHvIy{%X?*S_{ z^iA}nhfsLf6?&y-fLF9z{Tq=6ix?jE!v+0H9b#EXHjxIa8T6~5Uk$1=oO0GvZWwWb ztwiLaJmv@eD(F`Y=F{qJ^^EEr;9cN7;C%r{DEQdrJ*Q$)$i!P=w<#z<79MY( zAo>*e4EWqC8*lxy6tDTaCepaVN~%CFIm>{l#)f_^2E5DgLZD{qLPU$yFe zOsCK|buKKj^MLcMg%pgdr_JAmh%N#yHo5p}U2R^bBARBRMz^U`wa9+O7#!KJs-Ry5 z{R)0-$Cf8Szslo6(60#AcrxsjDZnX4VQI*xO>5PlU(qJFdYjaVQd#3`4i5U2?P`L4 zW!t=LoeEXmvezT~cI;K{YSx!+`mK`Mt7HDE39Q zfR)IMVy-j|*lFBY?l!i{mpM8wiGqG*KTBl4`gfyW=?#hOS3$oD`c=@cY_}iTuY!Ih zlVfDR3i?$w2>Mmtd~`~Zq})bp+%8~0qBL(3-C37PV%yz~!acwY;9jegM;%#I?nm@T z7d6@n$dflR#LmcDioRmy=|i*GC(FtsXg>-(20RWt0Xzvj1w1X_%61o5nP(6^>ms@A zo29m2_&y2W&q4J9N-qL0xu&87Xs7csqE}qhZQ=L#s+Sb~PYOZ53i=gC0YSeC`c=@c zu5`Xqqt~8k4+{DfW;rrKRe$;?cgxbA7CpRd{tU0{IpBHV1>i;CCEzc>%fKrF&1*%6 ztC-*vPS%WU%A=~O@imlQHzoPBX|h5|E{^85-tYC~p8hwK-U8kR-T~eP-UHqjaFI^j z<>vDtqK{0ZL=bh7R|U-F&bR{M?_OUL^sC(7MllKcmGz^bUj_Xt=vU(Z8VyLtdD@dO z!fMFY=HzZ?2Pq)92JjhP(wME$_ddUbYX;RHRjM8U9;~(GQZ=X^M)U~qDDW8YIPipk z2g&_OQ_oX~o;Hz&@{SA{&sd3Uh50K*_N$;@<#|2mSI(UY`jt0C(654i)i2mS+~piH z`Mk@6;2xE#8Qw`+WS*$*Lv+7u$t+?U6iqV5wAL;{*FEI*LB9(6m3&Ad`&H1dFevmo zefK8{`c=@c>g|inPSuU@t!@Ht25td@ekGHi8X~_r%{o?optX$!Kpe z=8K#f;`?0k1K@|i!N4H`evqO+lW;93J4rCV*r|Z%M0)b!rihcR%sfZ>Ws&_#trPUC z$LUH>Sf5a!LLxmrh3IMTCPBXn`jw3{dR_b+u!T2F(64ND6!fdZVG$kSw2{burN#*Q z)noLD$AKpVQ$|%!^7$#?X#wjNne@z(7xb%qSQ7Lr9aS#p^f38E=Cv%L619X~5$f1V zP8KU#i8u9BMALvvfy=D2 zAunoM;&z+Rk*=WbN~^;~+V)2B%hngUin`zVb&9H>RqWMX5^YLu5Z9n^EpQz$y{_!T znYzJBL^ab&_9hf=Hj$RLX48r6S3$oD`jr_abdEFHnFysgh=Xcv$O~hDZ=1Z3#X|4Z zx~|o1EBQmUzL(@Bt8rpO)W_E9r9z!z@=$DT?JUPpH{R8ij@u4;nq}9|Te}v`zvz`M zeU~jh|d>ikwJdf4IeAexh?Er{muTC<_k@@ip3 zivWuPi&}SPII-NLSZLXo07KekCv6jlGQ``;`pJxGnz& zJ?B8+An!18)v&p<=+Fy)NZrA}A+Deq+Gvi7jjs;=Tz11A6{3ZzyP4OxHqQ1;wDt}TYv zA}6CX#g+O!dsC##uH!W723Dt~3w|n*{VM2J)f@DSH|u`Ugu44Tm8OiMV@CF?g`JY1 z`NQ0c3ib!IjY1mgU0uAUG!VzUT0*62#7vRp=F#ig)M9@mbxV7l9PjcQFV`^7FIx7v z-SQ}{0IcYmTFl#c6Z9)F-646eHE&tVDdMY_DPK z;E5G`FsI+;lJ`uB-H9&w0MUm)WWNgfRb;=i-A2%_`f|Ky$=7ZN{mR_^v?|qdH|STI zD*g-7*{eplQs^b^%!7VayWSb?g?Lo<0(ConcA_Lq+7c}YH(@xi5U?u~wd3MK_9i(YqS*&Vn>^@O zG)B;`WK2-R)IoK;cZ+UIX1(e}8s{Y7mnJV{a+KNbWJFV3)amx6dMcvRfB|qiaE5>` zDPy4-EE+vR3!O#X*}yr#xxjhA`M?Fhg}_C?#lR)NRA8DQzh)gm3|)rkau)^tO8bYP zUnz92S*A4*nr*wtai+fTZW8n>dxL_0rLkjzb4QAfT$vbGBKuVp^sDL;ctulzX+Y4g zf_~*wi4IE!)u(id&w$T?FMuxvd12Btx2wp0)z+3J=vUQvV|q0k`M7^mm8#8v%}q{z zd#&5HL^Q!fav<^GWQsqf)%JH?tVkJJXir3Q8(>?Pi`ypo_b3h3{;$_*tm3vJ58EL3 zWAh9yTi6D6;^Lj{;^N{c5NGwUPrq~JjGXzwv1*4p{7;(|+jEWPPC;CSE!;6&gg0cM`EDcAPuSBOq_k&;zt zvwjMqQ%xkV+rly&DN%+t-ltP{hO6u3RR_VpMsyZ%HgFDbE^r=jK5&76PTlYG^)K>L zyN7Au5)`Ha(|}98QpP7$UT!5)pR05Q3c5JftM7fO3xqb zB{8ow?gS63+TR)^cv$Kj!NUq3R`9TNJTj=hf%E+Wz=FVVU?CuQSj=o)^J*+Kso0s4 z;!S8i8KV};>*Bn%TZi^q7g*2ba!Zxg28cEU#sV7w8w2A6tZ}tO*Mz$XqD@`YX^N0) zw}x)L1$A52b-KWez>1kMsJ5c+yTI1KMAs6@Rln=DUTXB~;29;P)a}unWOYQsk!VNP z)H=zY+-MrvRsTKd=_b2&*{hvP3$f1mibcPzsdx{+US69XHoa(SIgskhaOOn2-R$d2 z@8e>HFI5Zer&6^)a6qkIib{fdqoup(L$f7H@1XiVO2NbOR#M~GPasOPe(ZB;ob!P5 zT|wJD{RS5zx(K+~@1`}XDX98&0Qs?>xq6L5jf#JYHz{0>H0tOci=kljr4AJ5)Y7mHn zy5M0256j1zNP`tTEQJGPn7DrC$PqlOA=N81N${`~cFEoBdmSc}VOApQx`mL?L6A)< z!NUq3)}Y!&{iB);>+qu+T=(J9#-(Ma(9$7w+CyItM#B-7Ouc@!17KQ2p*OiBY0S9gdfo@eheH2 z1P?2CSk=Syghzl!f#6{U4~s=kv#5_2>a5D`Hg@chPf``Sd3;$$UU^zjashhYAtY9TYBEb)MC9l(|vbKbyyiQKLs#~?L>$n+1$wACw zT5^JIW($uZ*(eF<-SF$>>h6)J`ihNTl`ihd_npf`K*qJPQ;Q4YEcfcCm7HjgR;gO6 z7PUA%9OI?3rX*{6aHoc{{-8ViIia2uJS??g@UZ?Ld*>N_M{%TmAp}B5fDu^&k&Q@Z z=FW|POa_SzMu5qg@sJj5f-zu&SrgY_xL}iWSgDBQo+@Ti@UVi16+A4(Pgq=G&Bkc^5wa|3osbPD z@O}a7Q|`W|mgt2LEetFIED9_Ji~xdu6=kr@u;^Lrqsq;Ac0HB+QamA(WPjiQ;6UIY z0oRCgq&M`z-cnv_&96&=0MPheV{XwxDu z5b1Ry2ZHu)yjMhn(gZryr;TE&<$(L@T+bL^> z#MRl}r`Nh|>r_5kmz?9`pkD?3stWp5(61WsAPS)A{E&>Cv#d?ZcVkOOLm{$heQD{R zuU5*Jk=Cz*nA$bCeobJE-Gn5$i8(30FTuEL)3*+=F0h_y={T&AM|A^48=8pXmRc;w zA{ysf4K0`HTU7wszFt2=H{A@S&0VSJLSNVt(N@6LCMWZU?zfF=sn(8;&9+5hJ79a@ z$G{E({fDFtiE}4wDd7jlY`dVaE3g}|yLIAs(dT}+gz5~-e@pkHMcWy222 zf*qp_R?x4sf6jYseP5`bmS%1Rd}Yg8FqXog+`V43^lZ)K+4`Gl%i~=i$hOG)@)~`w z18)Ft0)GeI0^SDR0p1m0<+YR^wO_rD=mX$Glk1>FxlF5%y(MGXvdDDOaqXuj&J_{n zKQPK*X)xtT3;NZ@Fh@24HWe@`tq#@mHb=At5cDezLeQ_$+-PRxz`B%a5oNG~ex=o- zlj{}7vZ1;}<}ksn5@oP>y#)PAIq~GOTi@72vV0VYkY2nhbgVS9kcNVOr3gG9pZ_}g zRWImQMbNK;eiihqwB82&N^hE=Uj_Y2(;(A4Ej~jue3)C`jsNR))uyw`&KQy_B#tIp))^;srR99B+zs3VOa-O^_X76;(*?ZO3Q;JO zlF(XI`_VT&gu=tF&@G&kuaZQ1ZXcuXao`D4P=O+9hR^U;Mn$OVX=^E8y_Y*sAtHUv zU%Bo%;CbK$;6>mi;AP+yV5T6wbh(O0gsOk(L#qvk@HLcPHzgKj^C{}2&4`4(E&-)) zq4YNJ4)8AU9`HW!fgnA6xz6LNj}U!qA_BwAHz}7~@<8QEuAm!!R$tN*i2mLDOS3$oD`c?Hy7%{&Bjs=bbehnNiz$ftDDZ zFv%;PT(v3vP}{}1>a8m4ESf!Fb(1S0LGIq$W+o$P41GTY)&kZB))DyPn@~WzE-BMB} zQGZbw4{Te@YbHk4f`0sC`gQ<M_jA*x@c zhdk(4w%DnvM_Lz&WYOw12ds=afx&{b&UVS+ImBAjKGRA#6op~HJixr(sX|k>#w!1U z7RUKbOooEAi&V}z%NVCUsY;1(b5)d1SCBef8_Y$x+oEV#nbrKeAp&@5n=$BZmQp14jTsze+1#(67=kG;%Uw2mMOB^`KuV^vo=O z8Q^?~>Q@TPGeVKx%t60OmXI)#KP^8iKQF&1zbwBhzb?Nizb(J320+)C z%_=Q58coVH&5mf0iE??(WHir-XfQArFa($z7zzvn<`M8!%4g>e{$^%-K1pnKEZP)_ z7>@P=uC3Rpf}j?vTOE1ebdy}=qO_S@6wSqe5x_{(YUC+@&=QD70ZRfwzY6-5ra{oJ zco?GkRnV`3eiig9_Nzg^N@r}cZDhz`py>2XR>*D;ICeLJMngQ1`dp6)sJ)!mQE*AM zPpwq5u7ZA5{g%-S`c=@cf_|k#ENxW=Tj?PsP?UG38bVo_xq+d;Fzb}>ki_2eT8mVT z=2FbkG@2jH;k9O}m%AXMg@A>DMXWPd{!|N-Dw z>#EFNRKM~uYIMnXK8|7A7}&(*QTN7;21784N zTBpd_R#9Cw>y#KZ8K^BiJ$%r~wHEB}&>lc2{%pX&Is(7N!!!ud9Kf6=C;H8NXpJ^W z6o$|@xAkfLCwJm7Z|VLPM$riRRnV_AnSy@hPe#zMuCCXJ2GNt()U76Qtbg>D%vmi@ z*Uf4X|8>1u)eR<6G6yZCTF7{(+ltmIl;NGFO>bXaJE2z0sHSnNw`3E@e4WUhZU^oF zCINQ>lLfkkl6~q6`JhlSEw6W*m_hpJ z&|gWzIuM4(?9TA$Hq1=S^)~Xc*B>s;7R44ydoI6Le>&@zRDZIe+$88%LB9(6RnV`l zW-<8BdPPym>3(%>-IAZBU;U|W6~4$64dVgm;M&WuXpPru^B3-PBXARNGcWISBrpw8-1s0HU#fS}HwCyGxCfXDOcS7%%X5Rif}n{Wnr`B}k+R}H zfaZh1L%_q_@FdtvYjLYx&iG_6anfbWMpoHYqKePt*4d@T@6NUrrl_=MX*b zB7L*Dn%YG}Z|I<31^wy=kZ4u|G9U*UK+vy(ex=1r#44G7RnV{4IW&qlaSGuTc7si zO2b$ch?+nPXnSX?g%6{Ps0XYLtO2YEj1i<&tby&g7NWIHq!Pa@Z0mYUHl3`c^-O8f_@eBt8Mmfue55Y zM!fl`;ESpZ#YXU3mK=Rwl ziRJCcWi*S8G^xC^oLt^jPATs$??J5HO|M^0EALf9Aqz?hQBE)KFCQo$EFZFdZJ5hP z%13Ev`|PKNZ97mTs#)DnmNQa!QxOm4)8#Yev!<;$pz^u$`SOMGMFdJYR-Y$%sD%P7 z^o29&)SYzkt4WUlB0gkoPvhRp_?2&zZmp{fZ?t=vP6%!u?H(&-si$lZpL1EA~g8v*A!k7O+0OS#bd`glJ)45nxeZF<=BR z5?CBqLcn`k?_l}pmPE7^ur#m?u&f|W!vXyU($!5UnxWh!GvtO<-Ut%gz?*}gYxsVYUaHht?@ zAJyRWnq1FYit*Im3bii(BxF~<8*C>%^j^z8N1{&5Bk+{J{&>63i?&huUH^H0saAe>d!{rBi+R3 zvsyvFTFSW!iu%*YEMqO%kfbJ9&RcoMPySSCBb@~*Lx07i)(j^KUh^s?0^*LcFyq=vP6%3i?&huY!Ih_L^+zPgx>A13m}70KNpi z0=@>m5nz0`b46pY6f5#m#`*vw0_e;|QE$~is712_gMg@h#V7>*DjkM2qWV>JjOIgn zb_$EX3i?&1Y2oo+LBEn^I)fGCDW4|tj%sm!2GO%FQZXgjy+OaKW`m3|&_nNoeiig9 zO^5N!iEVvOD3H|7B@~9A?7UnRBi-O@%Z90TM0+P-XTO9j0qH11HQaSHx0{K{{ixO+ zXzmH@1?+8|3Y+QZUi%^{fu8^suph8LZ~$$ za*vIIjr1-T2Cu@+?=EmxOPCF;Orc{IQ8n#v+3D`hmI6@it2mFrHg9U`+< z2SC*i=v&SDw6v1eD@W7-3ZMzJfVP1Dg|?TvvTH5&m~!B)?k&YInDbA+R{xDLF7Eb7 z4!f4Of_{}LOM#Y%eKjCe3H*1`ue$xS22!;~|4!?VE@v+Xm2>FttoN&2v*lnuDotD7 zFNc(KmqW{8n>-4cLGe3PG8DBZR+_v1V z+`jxVBF*q-zub|JdOmgW&gCvN8o3_2a<_7KHF71>?e@z(%e~6I?HbFO4-v*Q@si%R z{0X|<7C&LXa(^1itY=1&UN}-XNHPLyHSh;>qg)B9(^!fUWNV6Iy39$hA@wU&hRA+= zPxmU1;1<+a>zBd93LaMQuwb1;87w^s+WxGk!C+lc+?FjT8Hw7EXmQh9Y$FD1EHDn( z*wmpQ$eP#`(Pk#fw1}CtBTGX!-jcqpyiZHFtw=>j5!}@_^o{pEmBrNVZaYNVyQt8L zr=Sl+I|4faJ9}rNMUcv_-qI#cs=He&mtmr>-V^n`fW3izyi>N9zPq#*i@m_QTa=M0WvG zfV+WvfT_SV;9lT9V7frRJ1^S!ksh!Xyc2!XLnu7#3SG)}r2k=;{BV!a_c-u`Dd->! zFZ&E{$u!j5c-mS@TC03z{|iZz)S%@uFX|^w|2(nK$9h@ zA$kp^*G-8<+09eMqM@w~HWAHlq4YNJ4)8AU9`HW!fq*+}*RB86M~FT)5!-Axa}^q$ zZrErNPw`oON!v0`;vKO+wT>}lX@12`z6QPlzMZA6q#M-$hzhd-0|okKuGY8>vKEY2 z-=RktEIlG#xJ8povnhC3X%;FewVv|reZnZEzlLT9X4HAUg z=DZH7&FR*W+b%s{S(oR2U+>qcnp!{cmL{q@k;EA=?Vh|@JZM@w^fVr5iUdsPvfyDc zGFBq)4?cv!!>aC?HJdmenC2~c614i>=MzZP(BxLQU#;o^;K5p}3485fM2`TE0*?WY z15XH;)VM6(gNMcB4<1(Vu!4uBMI?AwS{tu|brU?S;9)Tjf`?U&BxHYa z583akCXJ##ywy{)Uj+|K8$c@PY`{ou=wqXbn;M(3h{lvA)c zHg~0>OD)kY5p4x*ZE|9AbiZv}OQ9|LJ8X->cEI+)kAWQoGHRp^eQhUeDf0)(?{`6A zS70|_ck5JfYHZ0p5$y%+4eSH#E5Je$Pua}JtV312%EXF7@VH2&H}@SDXY+i$Y*$&z z2l@4CX{&WGw>-qJmGj6h(SJ-o^ibDq7j@-cDjHQsaLLd8lA@@8MXuMizJ=fi4a(6d z9RvIl_!V$0a2)V!;CKNS=#0((BaM`HiM|uPuhp?^qx$98$fwYEs`Y6n>3hjm3&+rD z^qmg;&J+}*K~2On5%pcvaEBUo3Ke?vd;0zWoCBN-oF`y>n{EEM7a+P2xCpqo?$mC# zUtNmmGT?IH3hUH3TaHsaPWqDIVVPG-9vS_aq6`*OC3slGur1@Phe94?@q-~kEN>#x z`)d7L0nun+MPMahWdYBp{7!nhS49+MuoM?>!vf*P+}s%<7gdzOVy;9Ptl(kU^Pxop z^CWm!$Fmo+vsyi?5vvWB zj*Y8h>zUHgX;<}Y9-re)q(f{rmA`QX6}Oe?a-#R?fI)pHqkal-YOU4sQ+~w-Bnz6z zbR9*U?$@b~p;odpxa3TrKTB>$%8CWR;QqadIsewzoP%bR!K$V)4#C4BfS4LVf~NdVfCU6R?x44eiig9JHv=FSh8QD3|7#u zG!24&74)mL$7!qRQNOyA(U>eq+a5BIR#WO$L6WZJ*h}Pe*jWiNGjBe$`uYAV?wTS3$qhR15l5(654iRbA`cnv7}% zY4HyFReBW#{YvlApkIlfKqbcIYZ3!FO{*1Z5<_lrS<3suslrMUS1SXnxI)mcG#KOS z(Q3(V!`=+~m07!Dhb4oV(|Da|9m~u)&IT)2r4|pwEbJVM0|-sT-=K5?a3XLLa58X; zAPp|wA3iAZ(>{oWDWm!{lumagB~EezT7z63XVTZVJ_tFQ%V)c0(62s zUkx~YG=_q*-)T7BVd}gKya&7wd>}wWdG74AC~vV1`Z7Dy z)e!pTwmua?qR_@LZ?S<*k5JIBf_@eBD?KMcztU0{^ea~VJm^=vIf8x_^eZzbWM0c& zUK>8cI>5TXdIF4*pkD?3D(F{wAnxF)m{dO%UNIFLU!=Xe=$iuE4cr4v1*QqoMnZXz zG01g*10QC(iIsd97Wxj3gCAF9Y{i<39ropntG{AE4)L2cTVZKja(65S)4n(RSF&Ntb zQ3fmMSJjowgsXt71-yHkI``^V*C4tU_#^Nq;5y*X!1aQ(7wCDi6P;AZ&bg7kn}C~v z39h9gEZRui>MgO}{NXH=`Hs7gP{cm8b8SZ^aqXSJWZ*7f3UIf;exdT)R#OoL{mT9f zLBC2>bu43nDm|smE}1XwH7Vw!O*MrR*nwKmuhIh?^sE0#^eg2rit1MsnTqOHycOks zD~~RZVTErsx~kLltMb^i+;^2LtNb+|rKGxF|6cy4Jb|VnPgFkZr1IqQl=9T_KO~}} zmaaT4DYv-E@5(c1C;~t?>6d4vo?H>@a>XKjnPC#qT9PnI)McT*7$<>c)S|6cxBjfqf3#n%$t7ceANqAN6*VGjyH=w`;O4sC(kYdkHtVClL9Jd`ISyHp zvRJCI^o?`%wwIux%8u`*I~GnV^N_*V+!bZ4>b_fgOYFmBBk6x?#XDp**`G_X|0Jg! z&zEcqZ0DD#p0nkE)p3XJy90eYdY|l8|6BKheiihqpkGDxtCW%2wwzJ@YI(gJ6D4I? zX8{EL%3riC*gu;=dDy%j8j1(fQM zEK17(%e$tGd2@%#Ppi9(rf)@HC17P>6@k7-B^~^bSo{g&mT7CFu<^|LGyNB|wP|ok zQHxT-$yVL!Qj4O4LKo=O@{U&!6lX0tY30@Cyn2lH7inv^7MH9ItW#g7M7}Cak7#{h z17Jg7BVeq6@sWwH|JlZfHgQqA_LLW03Z8CG-xhVBE=aGWhW2U-6Qu7)z&5~m*All? z%gc7&68X*!KD8^>CU6HdceK7t)jcHI*)?_0ZktD?e6<}`ma5Y2?%Mi6_V*C)(6*Z@ z7^_8TZ@*r-^8K>Bp&3!um+1wNesl{rcD0|2}P6l^+*2&eMbRD1IGZr1bzh^3k3a2^Cjq4 zoWKPA>SLaWpkD?3%8x9Ae#N>F)vu!Zm2DJcmCCre4KCC~;C3MBSBmkJ(OA9agfN-x z^^j+uwgKQ}tC4)$uTY6^I|)$HGu`Mt6H{qOX5t47@`u1jt}aKv8~Vy} z;Wjaa=RQR#=vP{^f_~Lyzp;t4WP*OBJrpFep8L^nT`jz%d3|!E!(sapNOpeDHktb}11pUg+4T65vua<^~5%eo1UY09ra|UAz zU`s(-bla9ROJ__$zhYpH_JN7&R~n3a0cpP{_aQf)#Nj}d2o)Yi~$*xN~ja(jo z?Hit@@2_=VM*-E<^VU+R5v9ytMByb@D4NRtSiOR1ri+^SKLe3$VxKmFFz9brh zCFQ5(XXWSR7v-1bSLN5`H|4kGchvys8nap56m6FY1D_qyAQR=ef~We`oQMVka{)tu zxq+d;Fkl`5->G0B=a4mxUx&oJH;R9kVKN-;1zcN!MtbWkRJS^rd494Efdh-8xfn14 z7-?D!WgAxK5{O0tO9DZ^3i_3%LC~*w7=nHk^sAs>X>$|wD>)_PR|xtQM*)5goUD-D zAZzVzWUWTt^U8LOoHO3NOiXDG**^Q!N)5SHlF40v==SOqL86)|o{(Ga4;%m-2pl9x zMp=`iS*8? z*VM0a1I$m&i0#xIIL`a!{E_)|ytVQ|ZXx?$wV^7Wz@1J6P6AE_P6198@E<8OSpDj^ zh)#1+-r!4lN1A9)siXS=$>ZuP(X1EO<)bAj`K^MMP13xSIS`pUdV z_NM9*Z>cndzU?v;E(fjvuJlfMG1Pgrwe(vtF0Vl$s$W%4_^4>E>Q6GmTT%T=v*R14 z$hYZ?Jjjxx9wcd0x%gzM%8h62N^Qx65zQRcOl z_Eq-SE7^v^+N=4|9A0Z`1Jth;M6?jFFtCVq=2_cn`e=P3E_(!hBZ0+DL7q)qd81ri z@hNr+Xcc~zMm#v^S6v*O;~2J$flX|*6wV&>D}U7}kcwG&D8q9YaJY?;X0FGzEBaj% z`bheI0R;UDk9xx?@LDnScwWxHTmf7O1pTUdLgSE3iIfy}2BY$niLg|(#y(>$R@_^xlrZ2m*VajxY>_v(!JB?b z(66fb3A`T;EC2-kil;j0S5?rjv>sI_@JyU2U~i(@6KP#hS`+QvSk?4Ol<{?{_3IT1 zFYUM9Qiiy+2i2zB32KTi(E@aa_sdgm1jmMMr)`tO)!E*s)zDTjr7h7V=eSthG>Z+; z_v*);&m|WC7rKJBd)hr+jOY^JQj?3X*3s|09MKgf$~q0590dJ}zhcm@s-R!V0i%a^ zBys$Ud$4~uh1-m(L;uz6S4(+I&Lg#!v6jx>u#K1VR^IW%i^|889&x#xq|H=QxU)rI zv`K+kt>jl|V{Wv9W=5ITRbAYqSZ1}FT26Wc-al zVI;6PummtlfW9`y_FgF(9*7b2tDs*sTb40H)&{Z3LBFcb<)JwbI3KtGxDdDqxEQzu zxD>byxE#1bkRG!(Jc^)SX+oJPsoXn3zhY)+%b&vCNR}S-D_%&D7J`12mW`la!ALm_ zI2K+vy(e&w$c<*MsfpED`G0KNpi0=^a`!=zzZuN4YI zSk8AYR^AwQEmJF`8YpH@H9If}n8S%acKSWoTMBZ})?-NBQj)fQH5Bz>z&yab-YIXD zI=^Qvi21e$QT{gD^(Yj_{sVGH+x92uSNyete$|qH(|wX;P1%E4wI{F_u(!>q|55a- zPSCH4pkD?3N{)o6ex>~lZ^@uvX|Y}!?#VI&vqK2wSA=cl}6m-*&__QaB)|Jd@fUpbi&x$wHPW~ z)vdp+AT!hIYE^60BI>wRW4xu(X=bnJn6A!2RDaN&)0;~nU-~)g`4u|Ew?K2T_08sy zaU@^SMtsRwU>vZqsZ;nxzhF~Do0%wUk-&^GRH|RycuV@W@;*fn*z2^gRv) z{Yv5d_NR{OS3$oD`jrZXXz} zxX4>(EJ_{^sA_Tm1bg8zvA&wF|XR|i`gFZD_=j9O+d@jb+cM%)9t_=z$D;KV6uQeiz;lUjZWUnv19Hw zF^ihkxT$DPbIoS*aNmb$x@+lAYF>5ywzTSs`ODh)koO1uD(F{=Aqo0b(67>3)7Ao| z4^jQ9)e8ER8SYX23er{3uau1zUdG(c%jmX)e&vCliOt`(aUqYdY`iW*)dN=d@sh8= zgA|&|y<3f;?}xxzz}mn%0v2Bd2zZKv+!Fd?Sn8%5ptNDFMCsjXETVBHQUpR&zY6+Q zdVP0wI8vR%9+p|lI;EAnGI&@D z{`IQL%A_bOWfY{HC4r@kxg#$$r)bMKk4IV3%xm1v38Yyb&F{OW{MoV&M-g7%}pW5DCU6Tp+e4B#mN z?qE4#WXeB-=vfzu4q!oXz1;Iv5CqzhZQ_5;%I`06=ksU;9&(1D|lGJ!|GRO8yiN>b#YRvKR7q0@T244 zVR2fZz0EWq7?lUnFx}^aMv=>Yb-!BG1Hgl|R`9SsVLbj}G!E@z9&!k1VMSl&qyig-;nyms&$sg0&@MPMahWndM7cGiuiQVvPoGYI_-HxFPMl_pL$Kagy?19 z6<}uFnallHy;`>l3q;0IDe>!Qz5%>x3VFBP)nDo@YpLqCI~P?!*D1bTUfu6;$@`|n zn_icEi0C6A%3uW#OC0SegT>K7@UWD0F&$k556jCv1rIBDSk+wc5`u@tC=|{^5Dg)C zSoK)Qs_IueGd#PPD3b}Mv)|ni?GEe#?CG72T&2-iW>q^zsb%+Zv6dPIW|#j|lA%^{ z-G0FSzyaQ=G6UMb9^@@$!A;9Hxs{BY6J@ae_wcZSex-u{ z(4b#Ilo%yo1q=F>Qk^p(n*c$-lIxXZ@P{%QLB9(6)h2mU1tijHEx*2I#)H0a$PcB} z_F?8p(62n>Z?~rc2dt_=zp~mELBAp=kg}Uq>pRIyIy!P08J6m*0r zgN2C}Ww4kF2RIo;{!UpP2U$xd3K_8uM&S_Pr?pmFm9!W1h7WMC1pP#dRj4pkG;5+n`@D8(#Mb((P!2%S6;Pwk@yx z@?H<7r)0)y>gJ?(c!$g01>OVR2R;Bk1U?cZU4@wRt53Wovs^RsQxra{6&eJ+eSzpp z;49#3;2VK%k&}~MIo=Tspi0YZz(8PjV2}VcWvfW>bh+vo>&Y5S-(0{DQ&1XtqDF=y z8s?&`ZQ*)R1}o@SDg_zzs}9vEgMOv;FX&gQ(t@*OM!i;28mfBQS~6HX-c}A1t*U=z zRecV49(VzG5qJrB8F&SlDM*VoSMh$x+ZOLfK~=p6UPI}1Q({r}GqSvAOM9=2W9TiE z-Ui+Q-UZ$R-UmJqaA##c)w|{+L?4@oC`V7E+AvR!n9L$ZSD)3Fv@H@_mqr<^YH2tD zgM)q*^sAs>1^r67aaj*!Xp2f^I|D7*+6UZYVuG@@fCv2w#?-sOd%*j^2LgN98RbX$ zyvc&`F?~V5^0&2B5Xy7Kuqa0%Vf{;bxWBv_>9rm7D?NQmsiN`OnDN=f#z!WUXR|K4 zBy8NAzAfrLU62f|MniRls;%k!5wHy~-nCRuNKf*1-qMEKH~IyMu6IClN9&WYcp^qD5VlwKLnr2K_4NS7sas{i+xAs{z#nmWf+t ztsF2UZbLK?xE;6ym?ZGE#kN!`bt~1o=$iuE4cr4v1*QqoMnZ8SrrbFN@aGTmS4T8pFs0T*ObVXO;L7r_owN526)yK@>YY? z1kWLQ-bMQ6^o#O#p`3%&OD=AU#Gwp;Xhs>VpkGxD$O=Kf`Z2?>1F)lWGP*&(>XCWi z*9^+>z`xHL8Qb0FTEEHYXHKP0aNPrtgsTjJZx z=D87tn}C~v33X?Wl2x}_tI-fkzh6y6;dT?Lu&aJO9@n5>F)Ts9l239z55w2Y@~{fh ztyjYd;a|W*_*EHAvu+_o3j>P)ivo)QBY=^>;=mFDtb9E~n#@ZgS_)ViSO!>DkfvdS zFq7rIrR-Xo=_{Zx8d%ZgDy*h&Um4LVz^cFxfYk)L4^v$lIidzo08O9;v;}-!OX(_- zO(2J>A8JJPt27W%{VM2J_<*DORnV`Z`c=@c8bQAb`c=@cf_|mof;S*cz3F5s@q{FL zORdvKW8-H95j*do67;KChZ{zqR@{bmC5w8>&|>x>`@f8;Dt(67k;vmS%8KCl6> zA+QlJR**JsLBG;y9LSIyWJAIZ*0<|Ar)N`3X){f?pQ7|LAGbzZ1*sT7z09<=KAgTI z{08!5rL7;_HtqL+LEllp(ZDglFM(eH#{$O*c;@xhn#spoE9h5M(64MNXod6ew4h(v zlcF==1T(o0mSN2JYSqak#PgW?(c)k=Pa z$~an(qX=yBrmyPaW=l7!R#U6WT+}VZTdNv~3ZUt7RZ~l$Dk=$Ji=_OO9tx){Tpo|v zw!lm!ULj0+4X$4k7-Khy>R0LY9Q3Q8U+JL;`juI$LBG;u7!1K9s$Ve*LBDEoXdd({ z--*eLIo6m@(A#BK1pUfstm4Pop0wGroNzMItXQ1*E*uWu!1MGM;6~sk;AUU~a0_rN za2qfYxLx3Oq#gOTIz)}$N#A7PE?^39w}3xUuchy-rXreVqD(mrbd-G`qUo-sTI14s z0MUcMLoRPN_>(?jEt#)oO3L{|=HbWDe8T!TbCqQ}1JP5iuIzu>Fg%0kSr>`Tqu=|S zx0H2QKjej4y{T+_{AAg(<_(a!Y!M!LK`cmAznb;e*H8!jiYGxEF-@ofT0;|P0d1!= z=qb}Q?IP*{s{?BQYXV~g%r^yuXd14CXl)Z|M@Inny53SilcwMLC~N?12y6rd{fbdI zM8F>-=vNwy^L#LZex<>fZi5lkuM~l)B_!xqJ@ZAWRI42;X`!{eyh;dSL8(E%aw7

^__^

diff --git a/src/amplicon.py b/src/amplicon.py index c673ee7..f66abf9 100755 --- a/src/amplicon.py +++ b/src/amplicon.py @@ -14,7 +14,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" # Reads archive def get_reads_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -626,6 +626,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/annotate.py b/src/annotate.py index c050e86..eda3cf5 100755 --- a/src/annotate.py +++ b/src/annotate.py @@ -15,7 +15,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.25" +__version__ = "2023.11.30" def get_preprocess_cmd( input_filepaths, output_filepaths, output_directory, directories, opts, program): cmd = [ @@ -880,6 +880,7 @@ def main(args=None): print("VEBA Database:", opts.veba_database, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) diff --git a/src/assembly-long.py b/src/assembly-long.py new file mode 100755 index 0000000..0c35cc2 --- /dev/null +++ b/src/assembly-long.py @@ -0,0 +1,627 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, glob +from collections import OrderedDict, defaultdict + +import pandas as pd + +# Soothsayer Ecosystem +from genopype import * +from genopype import __version__ as genopype_version +from soothsayer_utils import * + +pd.options.display.max_colwidth = 100 +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.12.14" + +# Assembly +def get_assembly_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): + # Command + cmd = [ + os.environ["flye"], + "--{} {}".format(opts.reads_type, input_filepaths[0]), + "-g {}".format(opts.estimated_assembly_size) if opts.estimated_assembly_size else "", + "-o {}".format(output_directory), + "-t {}".format(opts.n_jobs), + "--deterministic" if not opts.no_deterministic else "", + "--meta" if opts.program == "metaflye" else "", + opts.assembler_options, + + # Get failed length cutoff fasta + "&&", + + "mv", + os.path.join(output_directory, "assembly.fasta"), + os.path.join(output_directory, "assembly_original.fasta"), + + "&&", + + "cat", + os.path.join(output_directory, "assembly_original.fasta"), + "|", + os.environ["seqkit"], + "seq", + "-M {}".format(max(opts.minimum_contig_length - 1, 1)), + "|", + "gzip", + ">", + os.path.join(output_directory, "assembly_failed_length_cutoff.fasta.gz"), + + # Filter out small scaffolds and add prefix if applicable + "&&", + + "cat", + os.path.join(output_directory, "assembly_original.fasta"), + "|", + os.environ["seqkit"], + "seq", + "-m {}".format(opts.minimum_contig_length), + "|", + os.environ["seqkit"], + "replace", + "-r {}".format(opts.scaffold_prefix), + "-p '^'", + ">", + os.path.join(output_directory, "assembly.fasta"), + + "&&", + + "rm -rf", + os.path.join(output_directory, "assembly_original.fasta"), + + "&&", + + os.environ["fasta_to_saf.py"], + "-i", + os.path.join(output_directory, "assembly.fasta"), + ">", + os.path.join(output_directory, "assembly.fasta.saf"), + ] + + + + # files_to_remove = [ + # ] + + # for fn in files_to_remove: + # cmd += [ + # "&&", + # "rm -rf {}".format(os.path.join(output_directory, fn)), + # ] + return cmd + +# Bowtie2 +def get_alignment_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + cmd = [ + # Clear temporary directory just in case + "rm -rf {}".format(os.path.join(directories["tmp"], "*")), + "&&", + + # MiniMap2 Index + "(", + os.environ["minimap2"], + "-t {}".format(opts.n_jobs), + "-d {}".format(output_filepaths[0]), # Index + opts.minimap2_index_options, + input_filepaths[1], # Reference + ")", + + "&&", + + # MiniMap2 + "(", + os.environ["minimap2"], + "-a", + "-t {}".format(opts.n_jobs), + "-x {}".format(opts.minimap2_preset), + opts.minimap2_options, + output_filepaths[0], + input_filepaths[0], + + + + # Convert to sorted BAM + "|", + + os.environ["samtools"], + "view", + "-b", + "-h", + "-F 4", + + "|", + + os.environ["samtools"], + "sort", + "--threads {}".format(opts.n_jobs), + "--reference {}".format(input_filepaths[1]), + "-T {}".format(os.path.join(directories["tmp"], "samtools_sort")), + ">", + output_filepaths[1], + ")", + + "&&", + + "(", + os.environ["samtools"], + "index", + "-@ {}".format(opts.n_jobs), + output_filepaths[1], + ")", + ] + + return cmd + + +# featureCounts +def get_featurecounts_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + + # ORF-Level Counts + cmd = [ + "mkdir -p {}".format(os.path.join(directories["tmp"], "featurecounts")), + "&&", + "(", + os.environ["featureCounts"], + # "-G {}".format(input_filepaths[0]), + "-a {}".format(input_filepaths[1]), + "-o {}".format(os.path.join(output_directory, "featurecounts.tsv")), + "-F SAF", + "-L", + "--tmpDir {}".format(os.path.join(directories["tmp"], "featurecounts")), + "-T {}".format(opts.n_jobs), + opts.featurecounts_options, + input_filepaths[2], + ")", + "&&", + "gzip -f {}".format(os.path.join(output_directory, "featurecounts.tsv")), + ] + return cmd + +# seqkit +def get_seqkit_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + + # ORF-Level Counts + cmd = [ + + os.environ["seqkit"], + "stats", + "-a", + "-j {}".format(opts.n_jobs), + "-T", + "-b", + os.path.join(directories[("intermediate","1__assembly")], "*.fasta"), + "|", + "gzip", + ">", + output_filepaths[0], + ] + return cmd + +# Symlink +def get_symlink_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + # Command + cmd = [ + "DST={}; (for SRC in {}; do SRC=$(realpath --relative-to $DST $SRC); ln -sf $SRC $DST; done)".format( + output_directory, + " ".join(input_filepaths), + ) + ] + return cmd + +# ============ +# Run Pipeline +# ============ +# Set environment variables +def add_executables_to_environment(opts): + """ + Adapted from Soothsayer: https://github.com/jolespin/soothsayer + """ + accessory_scripts = { + "fasta_to_saf.py", + } + + required_executables={ + "flye", + "minimap2", + "samtools", + "featureCounts", + "seqkit", + } | accessory_scripts + + if opts.path_config == "CONDA_PREFIX": + executables = dict() + for name in required_executables: + executables[name] = os.path.join(os.environ["CONDA_PREFIX"], "bin", name) + else: + if opts.path_config is None: + opts.path_config = os.path.join(opts.script_directory, "veba_config.tsv") + opts.path_config = format_path(opts.path_config) + assert os.path.exists(opts.path_config), "config file does not exist. Have you created one in the following directory?\n{}\nIf not, either create one, check this filepath:{}, or give the path to a proper config file using --path_config".format(opts.script_directory, opts.path_config) + assert os.stat(opts.path_config).st_size > 1, "config file seems to be empty. Please add 'name' and 'executable' columns for the following program names: {}".format(required_executables) + df_config = pd.read_csv(opts.path_config, sep="\t") + assert {"name", "executable"} <= set(df_config.columns), "config must have `name` and `executable` columns. Please adjust file: {}".format(opts.path_config) + df_config = df_config.loc[:,["name", "executable"]].dropna(how="any", axis=0).applymap(str) + # Get executable paths + executables = OrderedDict(zip(df_config["name"], df_config["executable"])) + assert required_executables <= set(list(executables.keys())), "config must have the required executables for this run. Please adjust file: {}\nIn particular, add info for the following: {}".format(opts.path_config, required_executables - set(list(executables.keys()))) + + # Display + for name in sorted(accessory_scripts): + executables[name] = "'{}'".format(os.path.join(opts.script_directory, "scripts", name)) # Can handle spaces in path + + print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) + for name, executable in executables.items(): + if name in required_executables: + print(name, executable, sep = " --> ", file=sys.stdout) + os.environ[name] = executable.strip() + print("", file=sys.stdout) + + +# Pipeline +def create_pipeline(opts, directories, f_cmds): + + # ................................................................. + # Primordial + # ................................................................. + # Commands file + pipeline = ExecutablePipeline(name=__program__, description=opts.name, f_cmds=f_cmds, checkpoint_directory=directories["checkpoints"], log_directory=directories["log"]) + + # ========== + # Assembly + # ========== + + step = 1 + + # Info + program = "assembly" + program_label = "{}__{}".format(step, program) + description = "Assembling long reads via {}".format(opts.program.capitalize()) + + # Add to directories + output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) + + + # i/o + input_filepaths = [opts.reads] + output_filenames = ["assembly.fasta", "assembly.fasta.saf"] + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_assembly_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + # ========== + # Alignment + # ========== + + step = 2 + + # Info + program = "alignment" + program_label = "{}__{}".format(step, program) + description = "Aligning reads to assembly" + + # Add to directories + output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) + + + # i/o + input_filepaths = [ + opts.reads, + os.path.join(directories[("intermediate", "1__assembly")], "assembly.fasta"), + ] + + output_filepaths = [ + os.path.join(directories[("intermediate", "1__assembly")], "assembly.fasta.mmi"), + os.path.join(output_directory, "mapped.sorted.bam"), + ] + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_alignment_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + + + # ========== + # featureCounts + # ========== + step = 3 + + # Info + program = "featurecounts" + program_label = "{}__{}".format(step, program) + description = "Counting reads" + + # Add to directories + output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) + + # i/o + + input_filepaths = [ + os.path.join(directories[("intermediate", "1__assembly")], "assembly.fasta"), + os.path.join(directories[("intermediate", "1__assembly")], "assembly.fasta.saf"), + os.path.join(directories[("intermediate", "2__alignment")], "mapped.sorted.bam"), + ] + + output_filenames = ["featurecounts.tsv.gz"] + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_featurecounts_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + # ========== + # stats + # ========== + + step = 4 + + # Info + program = "seqkit" + program_label = "{}__{}".format(step, program) + description = "Assembly statistics" + + # Add to directories + output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) + + + # i/o + input_filepaths = [ + os.path.join(directories[("intermediate", "1__assembly")], "*.fasta"), + + ] + + output_filenames = ["seqkit_stats.tsv.gz"] + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_seqkit_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + + # ============= + # Symlink + # ============= + step = 5 + + # Info + program = "symlink" + program_label = "{}__{}".format(step, program) + description = "Symlinking relevant output files" + + # Add to directories + output_directory = directories["output"] + + # i/o + + input_filepaths = [ + os.path.join(directories[("intermediate", "1__assembly")], "assembly.fasta"), + os.path.join(directories[("intermediate", "1__assembly")], "assembly.fasta.mmi"), + os.path.join(directories[("intermediate", "2__alignment")], "mapped.sorted.bam"), + os.path.join(directories[("intermediate", "2__alignment")], "mapped.sorted.bam.bai"), + os.path.join(directories[("intermediate", "3__featurecounts")], "featurecounts.tsv.gz"), + os.path.join(directories[("intermediate", "4__seqkit")], "seqkit_stats.tsv.gz"), + ] + + output_filenames = map(lambda fp: fp.split("/")[-1], input_filepaths) + output_filepaths = list(map(lambda fn:os.path.join(directories["output"], fn), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_symlink_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + return pipeline + +# Configure parameters +def configure_parameters(opts, directories): + # os.environ[] + + # Scaffold prefix + if opts.scaffold_prefix == "NONE": + opts.scaffold_prefix = "" + else: + if "NAME" in opts.scaffold_prefix: + opts.scaffold_prefix = opts.scaffold_prefix.replace("NAME", opts.name) + print("Using the following prefix for all {} scaffolds: {}".format(opts.program, opts.scaffold_prefix), file=sys.stdout) + + # Set environment variables + add_executables_to_environment(opts=opts) + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -n -g -o ".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser_io = parser.add_argument_group('Required I/O arguments') + parser_io.add_argument("-i","--reads", type=str, required=True, help = "path/to/reads.fq[.gz]") + parser_io.add_argument("-n", "--name", type=str, required=True, help="Name of sample") + parser_io.add_argument("-o","--project_directory", type=str, default="veba_output/assembly", help = "path/to/project_directory [Default: veba_output/assembly]") + + # Utility + parser_utility = parser.add_argument_group('Utility arguments') + parser_utility.add_argument("--path_config", type=str, default="CONDA_PREFIX", help="path/to/config.tsv [Default: CONDA_PREFIX]") #site-packges in future + parser_utility.add_argument("-p", "--n_jobs", type=int, default=1, help = "Number of threads [Default: 1]") + parser_utility.add_argument("--random_state", type=int, default=0, help = "Random state [Default: 0]") + parser_utility.add_argument("--restart_from_checkpoint", type=str, default=None, help = "Restart from a particular checkpoint [Default: None]") + parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) + parser_utility.add_argument("--tmpdir", type=str, help="Set temporary directory") #site-packges in future + + # Assembler + parser_assembler = parser.add_argument_group('Assembler arguments') + parser_assembler.add_argument("-P", "--program", type=str, default="flye", choices={"flye", "metaflye"}, help="Assembler | {flye, metaflye}} [Default: 'flye']") + parser_assembler.add_argument("-s", "--scaffold_prefix", type=str, default="NAME__", help="Assembler | Special options: Use NAME to use --name. Use NONE to not include a prefix. [Default: 'NAME__']") + parser_assembler.add_argument("-m", "--minimum_contig_length", type=int, default=1, help="Minimum contig length. Should be lenient here because longer thresholds can be used for binning downstream. Recommended for metagenomes to use 1000 here. [Default: 1] ") + parser_assembler.add_argument("-t", "--reads_type", type=str, default="nano-hq", choices={"nano-hq", "nano-corr", "nano-raw", "pacbio-hifi", "pacbio-corr", "pacbio-raw"}, help="Reads type for (meta)flye. {nano-hq, nano-corr, nano-raw, pacbio-hifi, pacbio-corr, pacbio-raw} [Default: nano-hq] ") + parser_assembler.add_argument("-g", "--estimated_assembly_size", type=str, help="Estimated assembly size (e.g., 5m, 2.6g)") + parser_assembler.add_argument("--no_deterministic", action="store_true", help="Do not use deterministic mode. This will result in a faster assembly since it will be threaded but can get different assemblies upon rerunning") + parser_assembler.add_argument("--assembler_options", type=str, default="", help="Assembler options for Flye-based programs (e.g. --arg 1 ) [Default: '']") + + # Aligner + parser_aligner = parser.add_argument_group('MiniMap2 arguments') + parser_aligner.add_argument("--minimap2_preset", type=str, default="map-ont", help="MiniMap2 | MiniMap2 preset {map-pb, map-ont, map-hifi} [Default: map-ont]") + # parser_aligner.add_argument("--no_create_index", action="store_true", help="Do not create a MiniMap2 index") + parser_aligner.add_argument("--minimap2_index_options", type=str, default="", help="MiniMap2 | More options (e.g. --arg 1 ) [Default: '']\nhttps://github.com/lh3/minimap2") + parser_aligner.add_argument("--minimap2_options", type=str, default="", help="MiniMap2 | More options (e.g. --arg 1 ) [Default: '']\nhttps://github.com/lh3/minimap2") + + # featureCounts + parser_featurecounts = parser.add_argument_group('featureCounts arguments') + parser_featurecounts.add_argument("--featurecounts_options", type=str, default="", help="featureCounts | More options (e.g. --arg 1 ) [Default: ''] | http://bioinf.wehi.edu.au/featureCounts/") + + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Threads + if opts.n_jobs == -1: + from multiprocessing import cpu_count + opts.n_jobs = cpu_count() + assert opts.n_jobs >= 1, "--n_jobs must be ≥ 1. To select all available threads, use -1." + + + # Directories + directories = dict() + directories["project"] = create_directory(opts.project_directory) + directories["sample"] = create_directory(os.path.join(directories["project"], opts.name)) + directories["output"] = create_directory(os.path.join(directories["sample"], "output")) + directories["log"] = create_directory(os.path.join(directories["sample"], "log")) + if not opts.tmpdir: + opts.tmpdir = os.path.join(directories["sample"], "tmp") + directories["tmp"] = create_directory(opts.tmpdir) + directories["checkpoints"] = create_directory(os.path.join(directories["sample"], "checkpoints")) + directories["intermediate"] = create_directory(os.path.join(directories["sample"], "intermediate")) + # os.environ["TMPDIR"] = directories["tmp"] + + # Info + print(format_header(__program__, "="), file=sys.stdout) + print(format_header("Configuration:", "-"), file=sys.stdout) + print(format_header("Name: {}".format(opts.name), "."), file=sys.stdout) + print("Python version:", sys.version.replace("\n"," "), file=sys.stdout) + print("Python path:", sys.executable, file=sys.stdout) #sys.path[2] + print("GenoPype version:", genopype_version, file=sys.stdout) #sys.path[2] + print("Script version:", __version__, file=sys.stdout) + print("Moment:", get_timestamp(), file=sys.stdout) + print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) + print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) + configure_parameters(opts, directories) + sys.stdout.flush() + + # Run pipeline + with open(os.path.join(directories["sample"], "commands.sh"), "w") as f_cmds: + pipeline = create_pipeline( + opts=opts, + directories=directories, + f_cmds=f_cmds, + ) + pipeline.compile() + pipeline.execute(restart_from_checkpoint=opts.restart_from_checkpoint) + +if __name__ == "__main__": + main() diff --git a/src/assembly.py b/src/assembly.py index 5156eff..32fc4fd 100755 --- a/src/assembly.py +++ b/src/assembly.py @@ -13,7 +13,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" # Assembly def get_assembly_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -683,8 +683,8 @@ def main(args=None): parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) # Pipeline parser_io = parser.add_argument_group('Required I/O arguments') - parser_io.add_argument("-1","--forward_reads", type=str, help = "path/to/forward_reads.fq") - parser_io.add_argument("-2","--reverse_reads", type=str, help = "path/to/reverse_reads.fq") + parser_io.add_argument("-1","--forward_reads", type=str, help = "path/to/forward_reads.fq[.gz]") + parser_io.add_argument("-2","--reverse_reads", type=str, help = "path/to/reverse_reads.fq[.gz]") parser_io.add_argument("-n", "--name", type=str, help="Name of sample", required=True) parser_io.add_argument("-o","--project_directory", type=str, default="veba_output/assembly", help = "path/to/project_directory [Default: veba_output/assembly]") @@ -758,6 +758,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/binning-eukaryotic.py b/src/binning-eukaryotic.py index f8cfaf2..9fdc054 100755 --- a/src/binning-eukaryotic.py +++ b/src/binning-eukaryotic.py @@ -14,7 +14,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.12.2" # DATABASE_METAEUK="/usr/local/scratch/CORE/jespinoz/db/veba/v1.0/Classify/Eukaryotic/eukaryotic" @@ -310,11 +310,13 @@ def get_eukaryotic_gene_modeling_cmd(input_filepaths, output_filepaths, output_d # Run Eukaryotic Gene Modeling "&&", + os.environ["eukaryotic_gene_modeling_wrapper.py"], "--fasta {}".format(os.path.join(directories["tmp"], "scaffolds.binned.eukaryotic.fasta")), "--scaffolds_to_bins {}".format(input_filepaths[1]), "--tiara_results {}".format(input_filepaths[2]), "--metaeuk_database {}".format(opts.metaeuk_database), + "--metaeuk_split_memory_limit {}".format(opts.metaeuk_split_memory_limit), "-o {}".format(output_directory), "-p {}".format(opts.n_jobs), @@ -1016,8 +1018,10 @@ def main(args=None): # MetaEuk parser_metaeuk = parser.add_argument_group('MetaEuk arguments') + parser_metaeuk.add_argument("-M", "--microeuk_database", type=str, choices={"MicroEuk100", "MicroEuk90", "MicroEuk50"}, default="MicroEuk50", help="MicroEuk database {MicroEuk100, MicroEuk90, MicroEuk50} [Default: MicroEuk50]") parser_metaeuk.add_argument("--metaeuk_sensitivity", type=float, default=4.0, help="MetaEuk | Sensitivity: 1.0 faster; 4.0 fast; 7.5 sensitive [Default: 4.0]") parser_metaeuk.add_argument("--metaeuk_evalue", type=float, default=0.01, help="MetaEuk | List matches below this E-value (range 0.0-inf) [Default: 0.01]") + parser_metaeuk.add_argument("--metaeuk_split_memory_limit", type=str, default="36G", help="MetaEuk | Set max memory per split. E.g. 800B, 5K, 10M, 1G. Use 0 to use all available system memory. (Default value is experimental) [Default: 36G]") parser_metaeuk.add_argument("--metaeuk_options", type=str, default="", help="MetaEuk | More options (e.g. --arg 1 ) [Default: ''] https://github.com/soedinglab/metaeuk") # --split-memory-limit 70G: https://github.com/soedinglab/metaeuk/issues/59 @@ -1071,7 +1075,7 @@ def main(args=None): if opts.veba_database is None: assert "VEBA_DATABASE" in os.environ, "Please set the following environment variable 'export VEBA_DATABASE=/path/to/veba_database' or provide path to --veba_database" opts.veba_database = os.environ["VEBA_DATABASE"] - opts.metaeuk_database = os.path.join(opts.veba_database, "Classify", "Microeukaryotic", "microeukaryotic") + opts.metaeuk_database = os.path.join(opts.veba_database, "Classify", "MicroEuk", opts.microeuk_database) # Directories @@ -1097,6 +1101,7 @@ def main(args=None): print("VEBA Database:", opts.veba_database, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/binning-prokaryotic.py b/src/binning-prokaryotic.py index 29f80c9..a52eb54 100755 --- a/src/binning-prokaryotic.py +++ b/src/binning-prokaryotic.py @@ -13,7 +13,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" # Assembly def get_coverage_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -1683,6 +1683,7 @@ def main(args=None): print("VEBA Database:", opts.veba_database, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/binning-viral.py b/src/binning-viral.py index f109b01..55f299e 100755 --- a/src/binning-viral.py +++ b/src/binning-viral.py @@ -14,7 +14,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" # geNomad def get_genomad_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): @@ -953,6 +953,7 @@ def main(args=None): print("VEBA Database:", opts.veba_database, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/biosynthetic.py b/src/biosynthetic.py index 5c1cb77..9996c68 100755 --- a/src/biosynthetic.py +++ b/src/biosynthetic.py @@ -13,7 +13,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.12.18" # antiSMASH def get_antismash_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -336,7 +336,7 @@ def get_mmseqs2_protein_cmd(input_filepaths, output_filepaths, output_directory, "&&", - os.environ["mmseqs2_wrapper.py"], + os.environ["clustering_wrapper.py"], "--fasta {}".format(os.path.join(directories["tmp"], "components.concatenated.faa")), "--output_directory {}".format(output_directory), "--no_singletons" if bool(opts.no_singletons) else "", @@ -415,7 +415,7 @@ def get_mmseqs2_nucleotide_cmd(input_filepaths, output_filepaths, output_directo "&&", - os.environ["mmseqs2_wrapper.py"], + os.environ["clustering_wrapper.py"], "--fasta {}".format(os.path.join(directories["tmp"], "bgcs.concatenated.fasta")), "--output_directory {}".format(output_directory), "--no_singletons" if bool(opts.no_singletons) else "", @@ -483,7 +483,7 @@ def add_executables_to_environment(opts): "concatenate_dataframes.py", "bgc_novelty_scorer.py", "compile_krona.py", - "mmseqs2_wrapper.py", + "clustering_wrapper.py", "compile_protein_cluster_prevalence_table.py", } @@ -860,7 +860,7 @@ def main(args=None): # antiSMASH parser_antismash = parser.add_argument_group('antiSMASH arguments') parser_antismash.add_argument("-t", "--taxon", type=str, default="bacteria", help="Taxonomic classification of input sequence {bacteria,fungi} [Default: bacteria]") - parser_antismash.add_argument("--minimum_contig_length", type=int, default=1500, help="Minimum contig length. [Default: 1500] ") + parser_antismash.add_argument("--minimum_contig_length", type=int, default=1, help="Minimum contig length. [Default: 1] ") parser_antismash.add_argument("-d", "--antismash_database", type=str, default=os.path.join(site.getsitepackages()[0], "antismash", "databases"), help="antiSMASH | Database directory path [Default: {}]".format(os.path.join(site.getsitepackages()[0], "antismash", "databases"))) parser_antismash.add_argument("-s", "--hmmdetection_strictness", type=str, default="relaxed", help="antiSMASH | Defines which level of strictness to use for HMM-based cluster detection {strict,relaxed,loose} [Default: relaxed] ") parser_antismash.add_argument("--tta_threshold", type=float, default=0.65, help="antiSMASH | Lowest GC content to annotate TTA codons at [Default: 0.65]") @@ -881,7 +881,7 @@ def main(args=None): # MMSEQS2 parser_mmseqs2 = parser.add_argument_group('MMSEQS2 arguments') - parser_mmseqs2.add_argument("-a", "--algorithm", type=str, default="easy-cluster", help="MMSEQS2 | {easy-cluster, easy-linclust} [Default: easy-cluster]") + parser_mmseqs2.add_argument("-a", "--algorithm", type=str, default="mmseqs-cluster", choices={"mmseqs-cluster", "mmseqs-linclust"}, help="MMSEQS2 | {mmseqs-cluster, mmseqs-linclust} [Default: mmseqs-cluster]") parser_mmseqs2.add_argument("-f","--representative_output_format", type=str, default="fasta", help = "Format of output for representative sequences: {table, fasta} [Default: fasta]") # Should fasta be the new default? @@ -943,6 +943,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/classify-eukaryotic.py b/src/classify-eukaryotic.py index 216c26c..a9bb93d 100755 --- a/src/classify-eukaryotic.py +++ b/src/classify-eukaryotic.py @@ -14,7 +14,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" # Assembly def get_concatenate_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -160,7 +160,7 @@ def get_compile_cmd( input_filepaths, output_filepaths, output_directory, direct return cmd -def get_consensus_genome_classification_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): +def get_consensus_genome_classification_ranked_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): # Command cmd = [ @@ -172,7 +172,7 @@ def get_consensus_genome_classification_cmd( input_filepaths, output_filepaths, "|", "tail -n +2", "|", - os.environ["consensus_genome_classification.py"], + os.environ["consensus_genome_classification_ranked.py"], "--leniency {}".format(opts.leniency), "-o {}".format(output_filepaths[0]), "-r c__,o__,f__,g__,s__", @@ -224,7 +224,7 @@ def get_consensus_cluster_classification_cmd( input_filepaths, output_filepaths, "-n id_genome_cluster", "-i 0", "|", - os.environ["consensus_genome_classification.py"], + os.environ["consensus_genome_classification_ranked.py"], "--leniency {}".format(opts.leniency), "-o {}".format(output_filepaths[0]), "-r c__,o__,f__,g__,s__", @@ -252,7 +252,7 @@ def add_executables_to_environment(opts): "filter_hmmsearch_results.py", "subset_table.py", "compile_eukaryotic_classifications.py", - "consensus_genome_classification.py", + "consensus_genome_classification_ranked.py", "insert_column_to_table.py", "metaeuk_wrapper.py", "scaffolds_to_bins.py", @@ -481,7 +481,7 @@ def create_pipeline(opts, directories, f_cmds): # ========== step += 1 - program = "consensus_genome_classification" + program = "consensus_genome_classification_ranked" program_label = "{}__{}".format(step, program) # Add to directories output_directory = directories["output"]# = create_directory(os.path.join(directories["intermediate"], program_label)) @@ -504,7 +504,7 @@ def create_pipeline(opts, directories, f_cmds): "directories":directories, } - cmd = get_consensus_genome_classification_cmd(**params) + cmd = get_consensus_genome_classification_ranked_cmd(**params) pipeline.add_step( id=program, @@ -698,6 +698,7 @@ def main(args=None): print("VEBA Database:", opts.veba_database, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/classify-prokaryotic.py b/src/classify-prokaryotic.py index b5abb15..e6f1d47 100755 --- a/src/classify-prokaryotic.py +++ b/src/classify-prokaryotic.py @@ -15,7 +15,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" # GTDB-Tk def get_gtdbtk_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -138,7 +138,7 @@ def get_consensus_cluster_classification_cmd( input_filepaths, output_filepaths, "-i {}".format(input_filepaths[0]), "-c {}".format(input_filepaths[1]), "|", - os.environ["consensus_genome_classification.py"], + os.environ["consensus_genome_classification_ranked.py"], "--leniency {}".format(opts.leniency), "-o {}".format(output_filepaths[0]), "-u 'Unclassified prokaryote'", @@ -158,7 +158,7 @@ def add_executables_to_environment(opts): "compile_prokaryotic_genome_cluster_classification_scores_table.py", # "cut_table_by_column_labels.py", "concatenate_dataframes.py", - "consensus_genome_classification.py", + "consensus_genome_classification_ranked.py", # "insert_column_to_table.py", "compile_krona.py", @@ -443,6 +443,7 @@ def main(args=None): print("VEBA Database:", opts.veba_database, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/classify-viral.py b/src/classify-viral.py index ed0da0f..50cca6b 100755 --- a/src/classify-viral.py +++ b/src/classify-viral.py @@ -14,7 +14,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" def get_concatenate_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -359,6 +359,7 @@ def main(args=None): print("VEBA Database:", opts.veba_database, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/cluster.py b/src/cluster.py index 320ef00..e13263f 100755 --- a/src/cluster.py +++ b/src/cluster.py @@ -1,6 +1,6 @@ #!/usr/bin/env python from __future__ import print_function, division -import sys, os, argparse, glob +import sys, os, argparse, glob, warnings from collections import OrderedDict, defaultdict import pandas as pd @@ -13,7 +13,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.24" +__version__ = "2023.12.11" # Global clustering def get_global_clustering_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -26,18 +26,35 @@ def get_global_clustering_cmd( input_filepaths, output_filepaths, output_directo # "--no_singletons" if bool(opts.no_singletons) else "", "-p {}".format(opts.n_jobs), + "--genome_clustering_algorithm {}".format(opts.genome_clustering_algorithm), "--ani_threshold {}".format(opts.ani_threshold), "--genome_cluster_prefix {}".format(opts.genome_cluster_prefix) if bool(opts.genome_cluster_prefix) else "", "--genome_cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", "--genome_cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill) if bool(opts.genome_cluster_prefix_zfill) else "", + "--skani_target_ani {}".format(opts.skani_target_ani), + "--skani_minimum_af {}".format(opts.skani_minimum_af), + "--skani_no_confidence_interval" if opts.skani_no_confidence_interval else "", + + "--skani_nonviral_preset {}".format(opts.skani_nonviral_preset), + "--skani_nonviral_compression_factor {}".format(opts.skani_nonviral_compression_factor), + "--skani_nonviral_marker_kmer_compression_factor {}".format(opts.skani_nonviral_marker_kmer_compression_factor), + "--skani_nonviral_options {}".format(opts.skani_nonviral_options) if bool(opts.skani_nonviral_options) else "", + + "--skani_viral_preset {}".format(opts.skani_viral_preset), + "--skani_viral_compression_factor {}".format(opts.skani_viral_compression_factor), + "--skani_viral_marker_kmer_compression_factor {}".format(opts.skani_viral_marker_kmer_compression_factor), + "--skani_viral_options {}".format(opts.skani_viral_options) if bool(opts.skani_viral_options) else "", + "--fastani_options {}".format(opts.fastani_options) if bool(opts.fastani_options) else "", - "--algorithm {}".format(opts.algorithm), + + "--protein_clustering_algorithm {}".format(opts.protein_clustering_algorithm), "--minimum_identity_threshold {}".format(opts.minimum_identity_threshold), "--minimum_coverage_threshold {}".format(opts.minimum_coverage_threshold), "--protein_cluster_prefix {}".format(opts.protein_cluster_prefix) if bool(opts.protein_cluster_prefix) else "", "--protein_cluster_suffix {}".format(opts.protein_cluster_suffix) if bool(opts.protein_cluster_suffix) else "", "--protein_cluster_prefix_zfill {}".format(opts.protein_cluster_prefix_zfill) if bool(opts.protein_cluster_prefix_zfill) else "", "--mmseqs2_options {}".format(opts.mmseqs2_options) if bool(opts.mmseqs2_options) else "", + "--diamond_options {}".format(opts.diamond_options) if bool(opts.diamond_options) else "", "--minimum_core_prevalence {}".format(opts.minimum_core_prevalence), "&&", @@ -60,18 +77,36 @@ def get_local_clustering_cmd( input_filepaths, output_filepaths, output_director "-o {}".format(output_directory), # "--no_singletons" if bool(opts.no_singletons) else "", "-p {}".format(opts.n_jobs), + + "--genome_clustering_algorithm {}".format(opts.genome_clustering_algorithm), "--ani_threshold {}".format(opts.ani_threshold), "--genome_cluster_prefix {}".format(opts.genome_cluster_prefix) if bool(opts.genome_cluster_prefix) else "", "--genome_cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", "--genome_cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill) if bool(opts.genome_cluster_prefix_zfill) else "", + "--skani_target_ani {}".format(opts.skani_target_ani), + "--skani_minimum_af {}".format(opts.skani_minimum_af), + "--skani_no_confidence_interval" if opts.skani_no_confidence_interval else "", + + "--skani_nonviral_preset {}".format(opts.skani_nonviral_preset), + "--skani_nonviral_compression_factor {}".format(opts.skani_nonviral_compression_factor), + "--skani_nonviral_marker_kmer_compression_factor {}".format(opts.skani_nonviral_marker_kmer_compression_factor), + "--skani_nonviral_options {}".format(opts.skani_nonviral_options) if bool(opts.skani_nonviral_options) else "", + + "--skani_viral_preset {}".format(opts.skani_viral_preset), + "--skani_viral_compression_factor {}".format(opts.skani_viral_compression_factor), + "--skani_viral_marker_kmer_compression_factor {}".format(opts.skani_viral_marker_kmer_compression_factor), + "--skani_viral_options {}".format(opts.skani_viral_options) if bool(opts.skani_viral_options) else "", + "--fastani_options {}".format(opts.fastani_options) if bool(opts.fastani_options) else "", - "--algorithm {}".format(opts.algorithm), + + "--protein_clustering_algorithm {}".format(opts.protein_clustering_algorithm), "--minimum_identity_threshold {}".format(opts.minimum_identity_threshold), "--minimum_coverage_threshold {}".format(opts.minimum_coverage_threshold), "--protein_cluster_prefix {}".format(opts.protein_cluster_prefix) if bool(opts.protein_cluster_prefix) else "", "--protein_cluster_suffix {}".format(opts.protein_cluster_suffix) if bool(opts.protein_cluster_suffix) else "", "--protein_cluster_prefix_zfill {}".format(opts.protein_cluster_prefix_zfill) if bool(opts.protein_cluster_prefix_zfill) else "", "--mmseqs2_options {}".format(opts.mmseqs2_options) if bool(opts.mmseqs2_options) else "", + "--diamond_options {}".format(opts.diamond_options) if bool(opts.diamond_options) else "", "--minimum_core_prevalence {}".format(opts.minimum_core_prevalence), "&&", @@ -107,8 +142,10 @@ def add_executables_to_environment(opts): required_executables={ # 1 + "skani", "fastANI", "mmseqs", + "diamond", } | accessory_scripts if opts.path_config == "CONDA_PREFIX": @@ -142,6 +179,21 @@ def add_executables_to_environment(opts): # Pipeline def create_pipeline(opts, directories, f_cmds): + + # Genome clustering algorithm + GENOME_CLUSTERING_ALGORITHM = opts.genome_clustering_algorithm.lower() + if GENOME_CLUSTERING_ALGORITHM == "fastani": + GENOME_CLUSTERING_ALGORITHM = "FastANI" + if GENOME_CLUSTERING_ALGORITHM == "skani": + GENOME_CLUSTERING_ALGORITHM = "skani" + + # Protein clustering algorithm + PROTEIN_CLUSTERING_ALGORITHM = opts.protein_clustering_algorithm.split("-")[0].lower() + if PROTEIN_CLUSTERING_ALGORITHM == "mmseqs": + PROTEIN_CLUSTERING_ALGORITHM = PROTEIN_CLUSTERING_ALGORITHM.upper() + if PROTEIN_CLUSTERING_ALGORITHM == "diamond": + PROTEIN_CLUSTERING_ALGORITHM = PROTEIN_CLUSTERING_ALGORITHM.capitalize() + # ................................................................. # Primordial # ................................................................. @@ -159,7 +211,7 @@ def create_pipeline(opts, directories, f_cmds): output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) # Info - description = "Global clustering of genomes (FastANI) and proteins (MMSEQS2)" + description = "Global clustering of genomes ({}) and proteins ({})".format(GENOME_CLUSTERING_ALGORITHM, PROTEIN_CLUSTERING_ALGORITHM) # i/o input_filepaths = [opts.genomes_table] @@ -206,7 +258,7 @@ def create_pipeline(opts, directories, f_cmds): output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) # Info - description = "Local clustering of genomes (FastANI) and proteins (MMSEQS2)" + description = "Local clustering of genomes ({}) and proteins ({})".format(GENOME_CLUSTERING_ALGORITHM, PROTEIN_CLUSTERING_ALGORITHM) # i/o input_filepaths = [opts.genomes_table] @@ -245,8 +297,20 @@ def create_pipeline(opts, directories, f_cmds): # Configure parameters def configure_parameters(opts, directories): - assert_acceptable_arguments(opts.algorithm, {"easy-cluster", "easy-linclust"}) + + assert_acceptable_arguments(opts.protein_clustering_algorithm, {"easy-cluster", "easy-linclust", "mmseqs-cluster", "mmseqs-linclust", "diamond-cluster", "diamond-linclust"}) + if opts.protein_clustering_algorithm in {"easy-cluster", "easy-linclust"}: + d = {"easy-cluster":"mmseqs-cluster", "easy-linclust":"mmseqs-linclust"} + warnings.warn("\n\nPlease use `{}` instead of `{}` for MMSEQS2 clustering.".format(d[opts.protein_clustering_algorithm], opts.protein_clustering_algorithm)) + opts.protein_clustering_algorithm = d[opts.protein_clustering_algorithm] + if opts.skani_nonviral_preset.lower() == "none": + opts.skani_nonviral_preset = None + + if opts.skani_viral_preset.lower() == "none": + opts.skani_viral_preset = None + + assert 0 < opts.minimum_core_prevalence <= 1.0, "--minimum_core_prevalence must be a float between (0.0,1.0])" # Set environment variables add_executables_to_environment(opts=opts) @@ -257,7 +321,7 @@ def main(args=None): # Path info description = """ Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) - usage = "{} -i -o -A 95 -a easy-cluster".format(__program__) + usage = "{} -i -o -A 95 -a mmseqs-cluster".format(__program__) epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" # Parser @@ -276,24 +340,45 @@ def main(args=None): parser_utility.add_argument("--restart_from_checkpoint", type=str, default=None, help = "Restart from a particular checkpoint [Default: None]") parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) - # FastANI + # ANI + parser_genome_clustering = parser.add_argument_group('Genome clustering arguments') + parser_genome_clustering.add_argument("-G", "--genome_clustering_algorithm", type=str, choices={"fastani", "skani"}, default="skani", help="Program to use for ANI calculations. `skani` is faster and more memory efficient. For v1.0.0 - v1.3.x behavior, use `fastani`. [Default: skani]") + parser_genome_clustering.add_argument("-A", "--ani_threshold", type=float, default=95.0, help="Species-level cluster (SLC) ANI threshold (Range (0.0, 100.0]) [Default: 95.0]") + parser_genome_clustering.add_argument("--genome_cluster_prefix", type=str, default="SLC-", help="Cluster prefix [Default: 'SLC-") + parser_genome_clustering.add_argument("--genome_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") + parser_genome_clustering.add_argument("--genome_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 + + parser_skani = parser.add_argument_group('Skani triangle arguments') + parser_skani.add_argument("--skani_target_ani", type=float, default=80, help="skani | If you set --skani_target_ani to --ani_threshold, you may screen out genomes ANI ≥ --ani_threshold [Default: 80]") + parser_skani.add_argument("--skani_minimum_af", type=float, default=15, help="skani | Minimum aligned fraction greater than this value [Default: 15]") + parser_skani.add_argument("--skani_no_confidence_interval", action="store_true", help="skani | Output [5,95] ANI confidence intervals using percentile bootstrap on the putative ANI distribution") + # parser_skani.add_argument("--skani_low_memory", action="store_true", help="Skani | More options (e.g. --arg 1 ) https://github.com/bluenote-1577/skani [Default: '']") + + parser_skani = parser.add_argument_group('[Prokaryotic & Eukaryotic] Skani triangle arguments') + parser_skani.add_argument("--skani_nonviral_preset", type=str, default="medium", choices={"fast", "medium", "slow", "none"}, help="skani [Prokaryotic & Eukaryotic]| Use `none` if you are setting skani -c (compression factor) {fast, medium, slow, none} [Default: medium]") + parser_skani.add_argument("--skani_nonviral_compression_factor", type=int, default=125, help="skani [Prokaryotic & Eukaryotic]| Compression factor (k-mer subsampling rate). [Default: 125]") + parser_skani.add_argument("--skani_nonviral_marker_kmer_compression_factor", type=int, default=1000, help="skani [Prokaryotic & Eukaryotic] | Marker k-mer compression factor. Markers are used for filtering. [Default: 1000]") + parser_skani.add_argument("--skani_nonviral_options", type=str, default="", help="skani [Prokaryotic & Eukaryotic] | More options for `skani triangle` (e.g. --arg 1 ) [Default: '']") + + parser_skani = parser.add_argument_group('[Viral] Skani triangle arguments') + parser_skani.add_argument("--skani_viral_preset", type=str, default="slow", choices={"fast", "medium", "slow", "none"}, help="skani | Use `none` if you are setting skani -c (compression factor) {fast, medium, slow, none} [Default: slow]") + parser_skani.add_argument("--skani_viral_compression_factor", type=int, default=30, help="skani [Viral] | Compression factor (k-mer subsampling rate). [Default: 30]") + parser_skani.add_argument("--skani_viral_marker_kmer_compression_factor", type=int, default=200, help="skani [Viral] | Marker k-mer compression factor. Markers are used for filtering. Consider decreasing to ~200-300 if working with small genomes (e.g. plasmids or viruses). [Default: 200]") + parser_skani.add_argument("--skani_viral_options", type=str, default="", help="skani [Viral] | More options for `skani triangle` (e.g. --arg 1 ) [Default: '']") + parser_fastani = parser.add_argument_group('FastANI arguments') - parser_fastani.add_argument("-A", "--ani_threshold", type=float, default=95.0, help="FastANI | Species-level cluster (SLC) ANI threshold (Range (0.0, 100.0]) [Default: 95.0]") - parser_fastani.add_argument("--genome_cluster_prefix", type=str, default="SLC-", help="Cluster prefix [Default: 'SLC-") - parser_fastani.add_argument("--genome_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") - parser_fastani.add_argument("--genome_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 parser_fastani.add_argument("--fastani_options", type=str, default="", help="FastANI | More options (e.g. --arg 1 ) [Default: '']") - - # MMSEQS2 - parser_mmseqs2 = parser.add_argument_group('MMSEQS2 arguments') - parser_mmseqs2.add_argument("-a", "--algorithm", type=str, default="easy-cluster", help="MMSEQS2 | {easy-cluster, easy-linclust} [Default: easy-cluster]") - parser_mmseqs2.add_argument("-t", "--minimum_identity_threshold", type=float, default=50.0, help="MMSEQS2 | SLC-Specific Protein Cluster (SSPC, previously referred to as SSO) percent identity threshold (Range (0.0, 100.0]) [Default: 50.0]") - parser_mmseqs2.add_argument("-c", "--minimum_coverage_threshold", type=float, default=0.8, help="MMSEQS2 | SSPC coverage threshold (Range (0.0, 1.0]) [Default: 0.8]") - parser_mmseqs2.add_argument("--protein_cluster_prefix", type=str, default="SSPC-", help="Cluster prefix [Default: 'SSPC-") - parser_mmseqs2.add_argument("--protein_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") - parser_mmseqs2.add_argument("--protein_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 - parser_mmseqs2.add_argument("--mmseqs2_options", type=str, default="", help="MMSEQS2 | More options (e.g. --arg 1 ) [Default: '']") + # Clustering + parser_protein_clustering = parser.add_argument_group('Protein clustering arguments') + parser_protein_clustering.add_argument("-P", "--protein_clustering_algorithm", type=str, choices={"mmseqs-cluster", "mmseqs-linclust", "diamond-cluster", "diamond-linclust"}, default="mmseqs-cluster", help="Clustering algorithm | Diamond can only be used for clustering proteins {mmseqs-cluster, mmseqs-linclust, diamond-cluster, mmseqs-linclust} [Default: mmseqs-cluster]") + parser_protein_clustering.add_argument("-t", "--minimum_identity_threshold", type=float, default=50.0, help="Clustering | Percent identity threshold (Range (0.0, 100.0]) [Default: 50.0]") + parser_protein_clustering.add_argument("-c", "--minimum_coverage_threshold", type=float, default=0.8, help="Clustering | Coverage threshold (Range (0.0, 1.0]) [Default: 0.8]") + parser_protein_clustering.add_argument("--protein_cluster_prefix", type=str, default="SSPC-", help="Cluster prefix [Default: 'SSPC-") + parser_protein_clustering.add_argument("--protein_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") + parser_protein_clustering.add_argument("--protein_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 + parser_protein_clustering.add_argument("--mmseqs2_options", type=str, default="", help="MMSEQS2 | More options (e.g. --arg 1 ) [Default: '']") + parser_protein_clustering.add_argument("--diamond_options", type=str, default="", help="Diamond | More options (e.g. --arg 1 ) [Default: '']") # Pangenome parser_pangenome = parser.add_argument_group('Pangenome arguments') @@ -329,6 +414,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/coverage-long.py b/src/coverage-long.py new file mode 100755 index 0000000..d282754 --- /dev/null +++ b/src/coverage-long.py @@ -0,0 +1,587 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, glob +from collections import OrderedDict, defaultdict + +import pandas as pd + +# Soothsayer Ecosystem +from genopype import * +from genopype import __version__ as genopype_version +from soothsayer_utils import * + +pd.options.display.max_colwidth = 100 +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.12.18" + +# Assembly +def get_index_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + cmd = [ + # Filtering out small contigs + "cat", + opts.fasta, + "|", + os.environ["seqkit"], + "seq", + "-m {}".format(opts.minimum_contig_length), + "-j {}".format(opts.n_jobs), + opts.seqkit_seq_options, + ">", + output_filepaths[0], + + # Create SAF file + "&&", + os.environ["fasta_to_saf.py"], + "-i {}".format(output_filepaths[0]), + ">", + output_filepaths[1], + + "&&", + + # Minimap2 Index + os.environ["minimap2"], + "-t {}".format(opts.n_jobs), + # "--seed {}".format(opts.random_state), + opts.minimap2_index_options, + "-d {}".format(output_filepaths[3]), # Index + output_filepaths[0], # Reference + + # Get stats for reference + "&&", + os.environ["seqkit"], + "stats", + "-a", + "-j {}".format(opts.n_jobs), + "-T", + "-b", + output_filepaths[0], + ">", + output_filepaths[2], + ] + + return cmd + + +# # Bowtie2 +# def get_alignment_gnuparallel_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + +# # Command +# cmd = [ + +# # MAKE THIS A FOR LOOP WITH MAX THREADS FOR EACH ONE. THE REASON FOR THIS IS THAT IF THERE IS A SMALL SAMPLE IT WILL BE DONE QUICK BUT THE LARGER SAMPLES ARE GOING TO BE STUCK WITH ONE THREAD STILL +# """ +# # Clear temporary directory just in case + +# rm -rf %s + +# # Minimap2 +# %s --jobs %d -a %s -C "\t" "mkdir -p %s && %s -x %s -1 {2} -2 {3} --threads 1 --seed %d --no-unal %s | %s sort --threads 1 --reference %s -T %s > %s && %s index -@ 1 %s" + +# """%( +# os.path.join(directories["tmp"], "*"), + +# # Parallel +# os.environ["parallel"], +# opts.n_jobs, +# input_filepaths[0], + +# # Make directory +# os.path.join(output_directory, "{1}"), + +# # Bowtie2 +# os.environ["minimap2"], +# input_filepaths[1], +# opts.random_state, +# opts.bowtie2_options, + +# # Samtools sort +# os.environ["samtools"], +# input_filepaths[0], +# os.path.join(directories["tmp"], "samtools_sort_{1}"), +# os.path.join(output_directory, "{1}", "mapped.sorted.bam"), + +# # Samtools index +# os.environ["samtools"], +# os.path.join(output_directory, "{1}", "mapped.sorted.bam"), + +# ), + + +# ] + +# return cmd + +def get_alignment_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + cmd = [ + +""" + # Clear temporary directory just in case +rm -rf %s + +# Read lines +READ_TABLE=%s + +while IFS= read -r LINE +do echo $LINE + # Split fields + ID_SAMPLE=$(echo $LINE | cut -f1 -d " ") + READS=$(echo $LINE | cut -f2 -d " ") + + # Create subdirectory + mkdir -p %s + + OUTPUT_BAM="%s" + + # Minimap2 + if [[ -e "$OUTPUT_BAM" && -s "$OUTPUT_BAM" ]]; then + echo "[Skipping (Exists)] [Minimap2] [$ID_SAMPLE]" + else + echo "[Running] [Minimap2] [$ID_SAMPLE]" + %s -a -x %s -t %d %s %s $READS | %s view -h -b -F 4 | %s sort -@ %d --reference %s -T %s > $OUTPUT_BAM && %s index -@ %d $OUTPUT_BAM + fi +done < $READ_TABLE + +"""%( + # Clear temporary directory just in case + os.path.join(directories["tmp"], "*"), + + # Read lines + input_filepaths[0], + + # Make directory + os.path.join(output_directory, "${ID_SAMPLE}"), + + # Output BAM + os.path.join(output_directory, "${ID_SAMPLE}", "mapped.sorted.bam"), + + + # Bowtie2 + os.environ["minimap2"], + opts.minimap2_preset, + opts.n_jobs, + opts.minimap2_options, + input_filepaths[2], + + + # Samtools view + os.environ["samtools"], + + + # Samtools sort + os.environ["samtools"], + opts.n_jobs, + input_filepaths[1], + os.path.join(directories["tmp"], "samtools_sort_${ID_SAMPLE}"), + # os.path.join(output_directory, "${ID_SAMPLE}", "mapped.sorted.bam"), + + # Samtools index + os.environ["samtools"], + opts.n_jobs, + # os.path.join(output_directory, "${ID_SAMPLE}", "mapped.sorted.bam"), + ), + + ] + + return cmd + + +# featureCounts +def get_featurecounts_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + + # ORF-Level Counts + cmd = [ + "mkdir -p {}".format(os.path.join(directories["tmp"], "featurecounts")), + "&&", + "(", + os.environ["featureCounts"], + # "-G {}".format(input_filepaths[0]), + "-a {}".format(input_filepaths[0]), + "-o {}".format(os.path.join(output_directory, "featurecounts.tsv")), + "-F SAF", + "--tmpDir {}".format(os.path.join(directories["tmp"], "featurecounts")), + "-T {}".format(opts.n_jobs), + "-L", + opts.featurecounts_options, + *input_filepaths[1:], + ")", + "&&", + "gzip -f {}".format(os.path.join(output_directory, "featurecounts.tsv")), + ] + return cmd + + + +# Symlink +def get_symlink_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + # Command + cmd = [ + "DST={}; (for SRC in {}; do SRC=$(realpath --relative-to $DST $SRC); ln -sf $SRC $DST; done)".format( + output_directory, + " ".join(input_filepaths), + ) + ] + return cmd + +# ============ +# Run Pipeline +# ============ +# Set environment variables +def add_executables_to_environment(opts): + """ + Adapted from Soothsayer: https://github.com/jolespin/soothsayer + """ + accessory_scripts = { + "fasta_to_saf.py" + } + + required_executables={ + "minimap2", + "samtools", + "featureCounts", + "seqkit", + # "parallel", + } | accessory_scripts + + if opts.path_config == "CONDA_PREFIX": + executables = dict() + for name in required_executables: + executables[name] = os.path.join(os.environ["CONDA_PREFIX"], "bin", name) + else: + if opts.path_config is None: + opts.path_config = os.path.join(opts.script_directory, "veba_config.tsv") + opts.path_config = format_path(opts.path_config) + assert os.path.exists(opts.path_config), "config file does not exist. Have you created one in the following directory?\n{}\nIf not, either create one, check this filepath:{}, or give the path to a proper config file using --path_config".format(opts.script_directory, opts.path_config) + assert os.stat(opts.path_config).st_size > 1, "config file seems to be empty. Please add 'name' and 'executable' columns for the following program names: {}".format(required_executables) + df_config = pd.read_csv(opts.path_config, sep="\t") + assert {"name", "executable"} <= set(df_config.columns), "config must have `name` and `executable` columns. Please adjust file: {}".format(opts.path_config) + df_config = df_config.loc[:,["name", "executable"]].dropna(how="any", axis=0).applymap(str) + # Get executable paths + executables = OrderedDict(zip(df_config["name"], df_config["executable"])) + assert required_executables <= set(list(executables.keys())), "config must have the required executables for this run. Please adjust file: {}\nIn particular, add info for the following: {}".format(opts.path_config, required_executables - set(list(executables.keys()))) + + # Display + for name in sorted(accessory_scripts): + executables[name] = "'{}'".format(os.path.join(opts.script_directory, "scripts", name)) # Can handle spaces in path + print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) + for name, executable in executables.items(): + if name in required_executables: + print(name, executable, sep = " --> ", file=sys.stdout) + os.environ[name] = executable.strip() + print("", file=sys.stdout) + +# Pipeline +def create_pipeline(opts, directories, f_cmds): + + # ................................................................. + # Primordial + # ................................................................. + # Commands file + pipeline = ExecutablePipeline(name=__program__, description="Coverage", f_cmds=f_cmds, checkpoint_directory=directories["checkpoints"], log_directory=directories["log"]) + + # ========== + # Assembly + # ========== + + step = 1 + + # Info + program = "index" + program_label = "{}__{}".format(step, program) + description = "Preprocess fasta file and build Bowtie2 index" + + # Add to directories + output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) + + + # i/o + input_filepaths = [opts.fasta] + output_filenames = ["reference.fasta", "reference.fasta.saf", "seqkit_stats.tsv", "reference.mmi"] + + + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_index_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + # ========== + # Alignment + # ========== + + step = 2 + + # Info + program = "alignment" + program_label = "{}__{}".format(step, program) + description = "Aligning reads to reference" + + # Add to directories + output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) + + + # i/o + input_filepaths = [ + opts.reads, + os.path.join(directories[("intermediate", "1__index")], "reference.fasta"), + os.path.join(directories[("intermediate", "1__index")], "reference.mmi"), + ] + + + + output_filenames = ["*/mapped.sorted.bam"] + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + # if not opts.one_task_per_cpu: + cmd = get_alignment_cmd(**params) + # else: + # cmd = get_alignment_gnuparallel_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + # ========== + # featureCounts + # ========== + step = 3 + + # Info + program = "featurecounts" + program_label = "{}__{}".format(step, program) + description = "Counting reads" + + # Add to directories + output_directory = directories[("intermediate", program_label)] = create_directory(os.path.join(directories["intermediate"], program_label)) + + # i/o + + input_filepaths = [ + os.path.join(directories[("intermediate", "1__index")], "reference.fasta.saf"), + os.path.join(directories[("intermediate", "2__alignment")], "*", "mapped.sorted.bam"), + ] + + output_filenames = ["featurecounts.tsv.gz"] + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_featurecounts_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + + + + # ============= + # Symlink + # ============= + step = 4 + + # Info + program = "symlink" + program_label = "{}__{}".format(step, program) + description = "Symlinking relevant output files" + + # Add to directories + output_directory = directories["output"] + + # i/o + + input_filepaths = [ + os.path.join(directories[("intermediate", "1__index")], "reference.fasta"), + os.path.join(directories[("intermediate", "1__index")], "reference.fasta.saf"), + os.path.join(directories[("intermediate", "1__index")], "seqkit_stats.tsv"), + os.path.join(directories[("intermediate", "2__alignment")], "*"), + os.path.join(directories[("intermediate", "3__featurecounts")], "featurecounts.tsv.gz"), + ] + + output_filenames = map(lambda fp: fp.split("/")[-1], input_filepaths) + output_filepaths = list(map(lambda fn:os.path.join(directories["output"], fn), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_symlink_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + return pipeline + +# Configure parameters +def configure_parameters(opts, directories): + # os.environ[] + + # assert not bool(opts.unpaired_reads), "Cannot have --unpaired_reads if --forward_reads. Note, this behavior may be changed in the future but it's an adaptation of interleaved reads." + df = pd.read_csv(opts.reads, sep="\t", header=None) + n, m = df.shape + assert m == 2, "--reads must be a 2 column table seperated by tabs and no header. Currently there are {} columns".format(m) + # Set environment variables + add_executables_to_environment(opts=opts) + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -f -r -o ".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser_io = parser.add_argument_group('Required I/O arguments') + parser_io.add_argument("-f","--fasta", type=str, required=True, help = "path/to/reference.fasta. Recommended usage is for merging unbinned contigs. [Required]") + parser_io.add_argument("-r","--reads", type=str, required = True, help = "path/to/reads_table.tsv with the following format: [id_sample][path/to/reads.fastq.gz], No header") + parser_io.add_argument("-o","--output_directory", type=str, default="veba_output/assembly/multisample", help = "path/to/project_directory [Default: veba_output/assembly/multisample]") + + # Utility + parser_utility = parser.add_argument_group('Utility arguments') + parser_utility.add_argument("--path_config", type=str, default="CONDA_PREFIX", help="path/to/config.tsv [Default: CONDA_PREFIX]") #site-packges in future + parser_utility.add_argument("-p", "--n_jobs", type=int, default=1, help = "Number of threads [Default: 1]") + parser_utility.add_argument("--random_state", type=int, default=0, help = "Random state [Default: 0]") + parser_utility.add_argument("--restart_from_checkpoint", type=str, default=None, help = "Restart from a particular checkpoint [Default: None]") + parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) + parser_utility.add_argument("--tmpdir", type=str, help="Set temporary directory") #site-packges in future + + # Aligner + parser_seqkit = parser.add_argument_group('SeqKit seq arguments') + parser_seqkit.add_argument("-m", "--minimum_contig_length", type=int, default=1, help="seqkit seq | Minimum contig length [Default: 1]") + parser_seqkit.add_argument("--seqkit_seq_options", type=str, default="", help="seqkit seq | More options (e.g. --arg 1 ) [Default: '']") + + + # Aligner + parser_aligner = parser.add_argument_group('Minmap2 arguments') + parser_aligner.add_argument("--minimap2_preset", type=str, default="map-ont", help="MiniMap2 | MiniMap2 preset {map-pb, map-ont, map-hifi} [Default: map-ont]") + parser_aligner.add_argument("--minimap2_index_options", type=str, default="", help="Minimap2 | More options (e.g. --arg 1 ) [Default: '']") + # parser_aligner.add_argument("--one_task_per_cpu", action="store_true", help="Use GNU parallel to run GNU parallel with 1 task per CPU. Useful if all samples are roughly the same size but inefficient if depth varies.") + parser_aligner.add_argument("--minimap2_options", type=str, default="", help="Minimap2 | More options (e.g. --arg 1 ) [Default: '']") + + # featureCounts + parser_featurecounts = parser.add_argument_group('featureCounts arguments') + parser_featurecounts.add_argument("--featurecounts_options", type=str, default="", help="featureCounts | More options (e.g. --arg 1 ) [Default: ''] | http://bioinf.wehi.edu.au/featureCounts/") + + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Threads + if opts.n_jobs == -1: + from multiprocessing import cpu_count + opts.n_jobs = cpu_count() + assert opts.n_jobs >= 1, "--n_jobs must be ≥ 1. To select all available threads, use -1." + + # Directories + directories = dict() + directories["project"] = create_directory(opts.output_directory) + directories["output"] = create_directory(os.path.join(directories["project"], "output")) + directories["log"] = create_directory(os.path.join(directories["project"], "log")) + if not opts.tmpdir: + opts.tmpdir = os.path.join(directories["project"], "tmp") + directories["tmp"] = create_directory(opts.tmpdir) + directories["checkpoints"] = create_directory(os.path.join(directories["project"], "checkpoints")) + directories["intermediate"] = create_directory(os.path.join(directories["project"], "intermediate")) + os.environ["TMPDIR"] = directories["tmp"] + + # Info + print(format_header(__program__, "="), file=sys.stdout) + print(format_header("Configuration:", "-"), file=sys.stdout) + print("Python version:", sys.version.replace("\n"," "), file=sys.stdout) + print("Python path:", sys.executable, file=sys.stdout) #sys.path[2] + print("GenoPype version:", genopype_version, file=sys.stdout) #sys.path[2] + print("Script version:", __version__, file=sys.stdout) + print("Moment:", get_timestamp(), file=sys.stdout) + print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) + print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) + configure_parameters(opts, directories) + sys.stdout.flush() + + # Run pipeline + with open(os.path.join(directories["project"], "commands.sh"), "w") as f_cmds: + pipeline = create_pipeline( + opts=opts, + directories=directories, + f_cmds=f_cmds, + ) + pipeline.compile() + pipeline.execute(restart_from_checkpoint=opts.restart_from_checkpoint) + +if __name__ == "__main__": + main() diff --git a/src/coverage.py b/src/coverage.py index 77c0131..b7b331f 100755 --- a/src/coverage.py +++ b/src/coverage.py @@ -13,7 +13,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" # ............................................................................. # Notes @@ -525,7 +525,7 @@ def main(args=None): # Aligner parser_seqkit = parser.add_argument_group('SeqKit seq arguments') - parser_seqkit.add_argument("-m", "--minimum_contig_length", type=int, default=1500, help="seqkit seq | Minimum contig length [Default: 1500]") + parser_seqkit.add_argument("-m", "--minimum_contig_length", type=int, default=1, help="seqkit seq | Minimum contig length [Default: 1]") parser_seqkit.add_argument("--seqkit_seq_options", type=str, default="", help="seqkit seq | More options (e.g. --arg 1 ) [Default: '']") @@ -572,6 +572,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/deprecated/preprocess.py b/src/deprecated/preprocess.py new file mode 100755 index 0000000..73adac7 --- /dev/null +++ b/src/deprecated/preprocess.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, glob +from collections import OrderedDict + +import pandas as pd + +# Soothsayer Ecosystem +from genopype import * +from genopype import __version__ as genopype_version + +from soothsayer_utils import * +import fastq_preprocessor + + +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.28" + +# ============ +# Run Pipeline +# ============ +# Set environment variables +def add_executables_to_environment(opts): + """ + Adapted from Soothsayer: https://github.com/jolespin/soothsayer + """ + accessory_scripts = set([]) + + required_executables={ + "repair.sh", + "bbduk.sh", + "bowtie2", + "fastp", + "seqkit", + "fastq_preprocessor", + "minimap2", + "pigz", + "chopper", + } | accessory_scripts + + if opts.path_config == "CONDA_PREFIX": + executables = dict() + for name in required_executables: + executables[name] = os.path.join(os.environ["CONDA_PREFIX"], "bin", name) + else: + opts.path_config = format_path(opts.path_config) + assert os.path.exists(opts.path_config), "config file does not exist. Have you created one in the following directory?\n{}\nIf not, either create one, check this filepath:{}, or give the path to a proper config file using --path_config".format(opts.script_directory, opts.path_config) + assert os.stat(opts.path_config).st_size > 1, "config file seems to be empty. Please add 'name' and 'executable' columns for the following program names: {}".format(required_executables) + df_config = pd.read_csv(opts.path_config, sep="\t") + assert {"name", "executable"} <= set(df_config.columns), "config must have `name` and `executable` columns. Please adjust file: {}".format(opts.path_config) + df_config = df_config.loc[:,["name", "executable"]].dropna(how="any", axis=0).applymap(str) + # Get executable paths + executables = OrderedDict(zip(df_config["name"], df_config["executable"])) + assert required_executables <= set(list(executables.keys())), "config must have the required executables for this run. Please adjust file: {}\nIn particular, add info for the following: {}".format(opts.path_config, required_executables - set(list(executables.keys()))) + + # Display + for name in sorted(accessory_scripts): + executables[name] = "'{}'".format(os.path.join(opts.script_directory, "scripts", name)) # Can handle spaces in path + print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) + for name, executable in executables.items(): + if name in required_executables: + print(name, executable, sep = " --> ", file=sys.stdout) + os.environ[name] = executable.strip() + print("", file=sys.stdout) + + +# Configure parameters +def configure_parameters(opts, directories): + + assert opts.forward_reads != opts.reverse_reads, "You probably mislabeled the input files because `r1` should not be the same as `r2`: {}".format(opts.forward_reads) + assert_acceptable_arguments(opts.retain_trimmed_reads, {0,1}) + assert_acceptable_arguments(opts.retain_decontaminated_reads, {0,1}) + + # Set environment variables + add_executables_to_environment(opts=opts) + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Wrapper around github.com/jolespin/fastq_preprocessor + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -1 -2 -n -o |Optional| -x -k ".format(__program__) + epilog = "Copyright 2022 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser_io = parser.add_argument_group('Required I/O arguments') + parser_io.add_argument("-1","--forward_reads", type=str, help = "path/to/reads_1.fastq") + parser_io.add_argument("-2","--reverse_reads", type=str, help = "path/to/reads_2.fastq") + parser_io.add_argument("-n", "--name", type=str, help="Name of sample", required=True) + parser_io.add_argument("-o","--project_directory", type=str, default="veba_output/preprocess", help = "path/to/project_directory [Default: veba_output/preprocess]") + + # Utility + parser_utility = parser.add_argument_group('Utility arguments') + parser_utility.add_argument("--path_config", type=str, default="CONDA_PREFIX", help="path/to/config.tsv. Must have at least 2 columns [name, executable] [Default: CONDA_PREFIX]") #site-packges in future + parser_utility.add_argument("-p", "--n_jobs", type=int, default=1, help = "Number of threads [Default: 1]") + parser_utility.add_argument("--random_state", type=int, default=0, help = "Random state [Default: 0]") + parser_utility.add_argument("--restart_from_checkpoint", type=int, help = "Restart from a particular checkpoint") + parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) + + # Fastp + parser_fastp = parser.add_argument_group('Fastp arguments') + parser_fastp.add_argument("-m", "--minimum_read_length", type=int, default=75, help="Fastp | Minimum read length [Default: 75]") + parser_fastp.add_argument("-a", "--adapters", type=str, default="detect", help="Fastp | path/to/adapters.fasta [Default: detect]") + parser_fastp.add_argument("--fastp_options", type=str, default="", help="Fastp | More options (e.g. --arg 1 ) [Default: '']") + + # Bowtie + parser_bowtie2 = parser.add_argument_group('Bowtie2 arguments') + parser_bowtie2.add_argument("-x", "--contamination_index", type=str, help="Bowtie2 | path/to/contamination_index\n(e.g., Human T2T CHM13 v2 in $VEBA_DATABASE/Contamination/chm13v2.0/chm13v2.0)") + parser_bowtie2.add_argument("--retain_trimmed_reads", default=0, type=int, help = "Retain fastp trimmed fastq after decontamination. 0=No, 1=yes [Default: 0]") + parser_bowtie2.add_argument("--retain_contaminated_reads", default=0, type=int, help = "Retain contaminated fastq after decontamination. 0=No, 1=yes [Default: 0]") + parser_bowtie2.add_argument("--bowtie2_options", type=str, default="", help="Bowtie2 | More options (e.g. --arg 1 ) [Default: '']\nhttp://bowtie-bio.sourceforge.net/bowtie2/manual.shtml") + + # BBDuk + parser_bbduk = parser.add_argument_group('BBDuk arguments') + parser_bbduk.add_argument("-k","--kmer_database", type=str, help="BBDuk | path/to/kmer_database\n(e.g., Ribokmers in $VEBA_DATABASE/Contamination/kmers/ribokmers.fa.gz)") + parser_bbduk.add_argument("--kmer_size", type=int, default=31, help="BBDuk | k-mer size [Default: 31]") + parser_bbduk.add_argument("--retain_kmer_hits", default=0, type=int, help = "Retain reads that map to k-mer database. 0=No, 1=yes [Default: 0]") + parser_bbduk.add_argument("--retain_non_kmer_hits", default=0, type=int, help = "Retain reads that do not map to k-mer database. 0=No, 1=yes [Default: 0]") + parser_bbduk.add_argument("--bbduk_options", type=str, default="", help="BBDuk | More options (e.g., --arg 1) [Default: '']") + + # Options + opts = parser.parse_args() + # opts.script_directory = script_directory + # opts.script_filename = script_filename + + # Threads + if opts.n_jobs == -1: + from multiprocessing import cpu_count + opts.n_jobs = cpu_count() + assert opts.n_jobs >= 1, "--n_jobs must be ≥ 1. To select all available threads, use -1." + + #Get arguments + args = list() + for k,v in opts.__dict__.items(): + if v is not None: + args += ["--{}".format(k), str(v)] + # args = flatten(map(lambda item: ("--{}".format(item[0]), item[1]), opts.__dict__.items())) + sys.argv = [sys.argv[0]] + args + + # Wrapper + fastq_preprocessor.main(args) + + + +if __name__ == "__main__": + main() diff --git a/src/index.py b/src/index.py index 8f532d4..5c10154 100755 --- a/src/index.py +++ b/src/index.py @@ -7,7 +7,7 @@ from soothsayer_utils import * __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.12.12" # ============== # Agostic commands @@ -22,11 +22,22 @@ def get_concatenate_fasta_cmd( input_filepaths, output_filepaths, output_directo "-i {}".format(input_filepaths[0]), "-o {}".format(output_directory), "-m {}".format(opts.minimum_contig_length), - "-x {}".format("fa.gz"), + "-x {}".format("fa.gz" if opts.reference_gzipped else "fa"), "-b reference", "-M {}".format(opts.mode), - + "&&", + + "cat", + os.path.join(output_directory, "reference.fa.gz" if opts.reference_gzipped else "reference.fa"), + "|", + os.environ["seqkit"], + "fx2tab", + "-i", + "-s", + "-n", + ">", + os.path.join(output_directory, "reference.id_to_hash.tsv"), ] return cmd @@ -51,22 +62,25 @@ def get_concatenate_gff_cmd( input_filepaths, output_filepaths, output_directory def get_bowtie2_local_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): os.environ["TMPDIR"] = directories["tmp"] # Command + cmd = [ """ - +OUTPUT_DIRECTORY=%s +FASTA_FILENAME=%s for ID_SAMPLE in $(cut -f1 %s); - do %s --threads %d --seed %d %s/${ID_SAMPLE}/reference.fa.gz %s/${ID_SAMPLE}/reference.fa.gz + do %s --threads %d --seed %d ${OUTPUT_DIRECTORY}/${ID_SAMPLE}/${FASTA_FILENAME} ${OUTPUT_DIRECTORY}/${ID_SAMPLE}/${FASTA_FILENAME} done """%( + output_directory, + "reference.fa.gz" if opts.reference_gzipped else "reference.fa", opts.references, os.environ["bowtie2-build"], opts.n_jobs, opts.random_state, - output_directory, - output_directory, ), ] + return cmd # ============== @@ -115,10 +129,10 @@ def create_local_pipeline(opts, directories, f_cmds): ] output_filenames = [ - "*/reference.fa.gz", + "*/reference.fa.gz" if opts.reference_gzipped else "*/reference.fa", "*/reference.saf", - - ] + "*/reference.id_to_hash.tsv", + ] output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) params = { @@ -207,8 +221,9 @@ def create_local_pipeline(opts, directories, f_cmds): # Info description = "Build mapping index" # i/o + input_filepaths = list( - map(lambda id_sample: os.path.join(directories["output"], id_sample, "reference.fa.gz"), + map(lambda id_sample: os.path.join(directories["output"], id_sample, "reference.fa.gz" if opts.reference_gzipped else "reference.fa"), opts.samples, ), ) @@ -273,8 +288,10 @@ def create_global_pipeline(opts, directories, f_cmds): ] output_filenames = [ - "reference.fa.gz", + "reference.fa.gz" if opts.reference_gzipped else "reference.fa", "reference.saf", + "reference.id_to_hash.tsv", + ] output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) @@ -365,13 +382,22 @@ def create_global_pipeline(opts, directories, f_cmds): # Info description = "Build mapping index" # i/o - input_filepaths = [ - os.path.join(directories["output"], "reference.fa.gz"), - ] + if opts.reference_gzipped: + input_filepaths = [ + os.path.join(directories["output"], "reference.fa.gz"), + ] + + output_filenames = [ + "reference.fa.gz.*.bt2", + ] + else: + input_filepaths = [ + os.path.join(directories["output"], "reference.fa"), + ] - output_filenames = [ - "reference.fa.gz.*.bt2", - ] + output_filenames = [ + "reference.fa.*.bt2", + ] output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) params = { @@ -417,7 +443,8 @@ def add_executables_to_environment(opts): required_executables = set([ - "bowtie2-build", + "seqkit", + "bowtie2-build", ])| accessory_scripts if opts.path_config == "CONDA_PREFIX": @@ -509,8 +536,9 @@ def main(args=None): parser_io.add_argument("-r","--references", type=str, required=True, help = "local mode: [id_sample][path/to/reference.fa] and global mode: [path/to/reference.fa]") parser_io.add_argument("-g","--gene_models", type=str, required=True, help = "local mode: [id_sample][path/to/reference.gff] and global mode: [path/to/reference.gff]") parser_io.add_argument("-o","--output_directory", type=str, default="veba_output/index", help = "path/to/project_directory [Default: veba_output/index]") - parser_io.add_argument("-m", "--minimum_contig_length", type=int, default=1500, help="Minimum contig length [Default: 1500]") + parser_io.add_argument("-m", "--minimum_contig_length", type=int, default=1, help="Minimum contig length [Default: 1]") parser_io.add_argument("-M", "--mode", type=str, default="infer", help="Concatenate all references with global and build index or build index for each reference {global, local, infer}") + parser_io.add_argument("-z", "--reference_gzipped",action="store_true", help="Gzip the reference to generate `reference.fa.gz` instead of `reference.fa`") # parser_io.add_argument("-c", "--copy_files", action="store_true", help="Copy files instead of symlinking. Only applies to global.") # Utility @@ -559,6 +587,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/mapping.py b/src/mapping.py index 8db61cc..b06175c 100755 --- a/src/mapping.py +++ b/src/mapping.py @@ -13,7 +13,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.12.12" # Bowtie2 @@ -451,9 +451,12 @@ def configure_parameters(opts, directories): assert os.path.isdir(opts.reference_index), "If --reference_saf is not provided, then --reference_index must be provided as a directory containing a file 'reference.saf'" opts.reference_saf = os.path.join(opts.reference_index, "reference.saf") - # Check if --reference_index is a directory, if it is then set reference.fa.gz as the directory + # Check if --reference_index is a directory, if it is then set reference.fa as the directory if os.path.isdir(opts.reference_index): - opts.reference_index = os.path.join(opts.reference_index, "reference.fa.gz") + if opts.reference_gzipped: + opts.reference_index = os.path.join(opts.reference_index, "reference.fa.gz") + else: + opts.reference_index = os.path.join(opts.reference_index, "reference.fa") # If --reference_fasta isn't provided then set it to the --reference_index if opts.reference_fasta is None: @@ -491,10 +494,11 @@ def main(args=None): parser_io.add_argument("-o","--project_directory", type=str, default="veba_output/mapping", help = "path/to/project_directory [Default: veba_output/mapping]") parser_reference = parser.add_argument_group('Reference arguments') - parser_reference.add_argument("-x", "--reference_index",type=str, required=True, help="path/to/bowtie2_index. Either a file or directory. If directory, then it assumes the index is named `reference.fa.gz`") + parser_reference.add_argument("-x", "--reference_index",type=str, required=True, help="path/to/bowtie2_index. Either a file or directory. If directory, then it assumes the index is named `reference.fa`") parser_reference.add_argument("-r", "--reference_fasta", type=str, required=False, help = "path/to/reference.fasta. If not provided then it is set to the --reference_index" ) # ; or (2) a directory of fasta files [Must all have the same extension. Use `query_ext` argument] parser_reference.add_argument("-a", "--reference_gff",type=str, required=False, help="path/to/reference.gff. If not provided then --reference_index must be a directory that contains the file: 'reference.gff'") parser_reference.add_argument("-s", "--reference_saf",type=str, required=False, help="path/to/reference.saf. If not provided then --reference_index must be a directory that contains the file: 'reference.saf'") + parser_reference.add_argument("-z", "--reference_gzipped",action="store_true", help="If --reference_index directory, then it assumes the index is named `reference.fa.gz` instead of `reference.fa`") # parser_io.add_argument("-S","--scaffold_identifier_mapping", type=str, required=False, help = "path/to/scaffold_identifiers.tsv, Format: [id_scaffold][id_mag][id_cluster], No header") # parser_io.add_argument("-O","--orf_identifier_mapping", type=str, required=False, help = "path/to/scaffold_identifiers.tsv, Format: [id_scaffold][id_mag][id_cluster], No header") @@ -558,6 +562,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/phylogeny.py b/src/phylogeny.py index 002cce6..0730b4e 100755 --- a/src/phylogeny.py +++ b/src/phylogeny.py @@ -14,7 +14,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.27" +__version__ = "2023.11.30" # Assembly def preprocess( input_filepaths, output_filepaths, output_directory, directories, opts): @@ -650,6 +650,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/preprocess-long.py b/src/preprocess-long.py new file mode 100755 index 0000000..fe1e58a --- /dev/null +++ b/src/preprocess-long.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse +from soothsayer_utils import format_header, read_script_as_module + +script_directory = os.path.dirname(os.path.abspath( __file__ )) + +try: + from fastq_preprocessor import fastq_preprocessor_long +except ImportError: + fastq_preprocessor_long = read_script_as_module("fastq_preprocessor_long", os.path.join(script_directory, "fastq_preprocessor_long.py")) + +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.29" + +if __name__ == "__main__": + print(format_header("VEBA Preprocessing Wrapper (fastq_preprocessor v{})".format(fastq_preprocessor_long.__version__)), file=sys.stderr) + label = "Mode: Long Nanopore and PacBio reads" + print(label, file=sys.stderr) + print(len(label)*"-", file=sys.stderr) + fastq_preprocessor_long.main(sys.argv[1:]) diff --git a/src/preprocess.py b/src/preprocess.py index d28ccc2..146b03c 100755 --- a/src/preprocess.py +++ b/src/preprocess.py @@ -1,148 +1,21 @@ #!/usr/bin/env python from __future__ import print_function, division -import sys, os, argparse, glob -from collections import OrderedDict - -import pandas as pd - -# Soothsayer Ecosystem -from genopype import * -from genopype import __version__ as genopype_version - -from soothsayer_utils import * -import fastq_preprocessor +import sys, os, argparse +from soothsayer_utils import format_header, read_script_as_module +script_directory = os.path.dirname(os.path.abspath( __file__ )) +try: + from fastq_preprocessor import fastq_preprocessor_short +except ImportError: + fastq_preprocessor_short = read_script_as_module("fastq_preprocessor_short", os.path.join(script_directory, "fastq_preprocessor_short.py")) + __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" - -# ============ -# Run Pipeline -# ============ -# Set environment variables -def add_executables_to_environment(opts): - """ - Adapted from Soothsayer: https://github.com/jolespin/soothsayer - """ - accessory_scripts = set([]) - - required_executables={ - "repair.sh", - "bbduk.sh", - "bowtie2", - "fastp", - "seqkit", - "fastq_preprocessor", - } | accessory_scripts - - if opts.path_config == "CONDA_PREFIX": - executables = dict() - for name in required_executables: - executables[name] = os.path.join(os.environ["CONDA_PREFIX"], "bin", name) - else: - opts.path_config = format_path(opts.path_config) - assert os.path.exists(opts.path_config), "config file does not exist. Have you created one in the following directory?\n{}\nIf not, either create one, check this filepath:{}, or give the path to a proper config file using --path_config".format(opts.script_directory, opts.path_config) - assert os.stat(opts.path_config).st_size > 1, "config file seems to be empty. Please add 'name' and 'executable' columns for the following program names: {}".format(required_executables) - df_config = pd.read_csv(opts.path_config, sep="\t") - assert {"name", "executable"} <= set(df_config.columns), "config must have `name` and `executable` columns. Please adjust file: {}".format(opts.path_config) - df_config = df_config.loc[:,["name", "executable"]].dropna(how="any", axis=0).applymap(str) - # Get executable paths - executables = OrderedDict(zip(df_config["name"], df_config["executable"])) - assert required_executables <= set(list(executables.keys())), "config must have the required executables for this run. Please adjust file: {}\nIn particular, add info for the following: {}".format(opts.path_config, required_executables - set(list(executables.keys()))) - - # Display - for name in sorted(accessory_scripts): - executables[name] = "'{}'".format(os.path.join(opts.script_directory, "scripts", name)) # Can handle spaces in path - print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) - for name, executable in executables.items(): - if name in required_executables: - print(name, executable, sep = " --> ", file=sys.stdout) - os.environ[name] = executable.strip() - print("", file=sys.stdout) - - -# Configure parameters -def configure_parameters(opts, directories): - - assert opts.forward_reads != opts.reverse_reads, "You probably mislabeled the input files because `r1` should not be the same as `r2`: {}".format(opts.forward_reads) - assert_acceptable_arguments(opts.retain_trimmed_reads, {0,1}) - assert_acceptable_arguments(opts.retain_decontaminated_reads, {0,1}) - - # Set environment variables - add_executables_to_environment(opts=opts) - -def main(args=None): - # Path info - script_directory = os.path.dirname(os.path.abspath( __file__ )) - script_filename = __program__ - # Path info - description = """ - Wrapper around github.com/jolespin/fastq_preprocessor - Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) - usage = "{} -1 -2 -n -o |Optional| -x -k ".format(__program__) - epilog = "Copyright 2022 Josh L. Espinoza (jespinoz@jcvi.org)" - - # Parser - parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) - # Pipeline - parser_io = parser.add_argument_group('Required I/O arguments') - parser_io.add_argument("-1","--forward_reads", type=str, help = "path/to/reads_1.fastq") - parser_io.add_argument("-2","--reverse_reads", type=str, help = "path/to/reads_2.fastq") - parser_io.add_argument("-n", "--name", type=str, help="Name of sample", required=True) - parser_io.add_argument("-o","--project_directory", type=str, default="veba_output/preprocess", help = "path/to/project_directory [Default: veba_output/preprocess]") - - # Utility - parser_utility = parser.add_argument_group('Utility arguments') - parser_utility.add_argument("--path_config", type=str, default="CONDA_PREFIX", help="path/to/config.tsv. Must have at least 2 columns [name, executable] [Default: CONDA_PREFIX]") #site-packges in future - parser_utility.add_argument("-p", "--n_jobs", type=int, default=1, help = "Number of threads [Default: 1]") - parser_utility.add_argument("--random_state", type=int, default=0, help = "Random state [Default: 0]") - parser_utility.add_argument("--restart_from_checkpoint", type=int, help = "Restart from a particular checkpoint") - parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) - - # Fastp - parser_fastp = parser.add_argument_group('Fastp arguments') - parser_fastp.add_argument("-m", "--minimum_read_length", type=int, default=75, help="Fastp | Minimum read length [Default: 75]") - parser_fastp.add_argument("-a", "--adapters", type=str, default="detect", help="Fastp | path/to/adapters.fasta [Default: detect]") - parser_fastp.add_argument("--fastp_options", type=str, default="", help="Fastp | More options (e.g. --arg 1 ) [Default: '']") - - # Bowtie - parser_bowtie2 = parser.add_argument_group('Bowtie2 arguments') - parser_bowtie2.add_argument("-x", "--contamination_index", type=str, help="Bowtie2 | path/to/contamination_index\n(e.g., Human T2T CHM13 v2 in $VEBA_DATABASE/Contamination/chm13v2.0/chm13v2.0)") - parser_bowtie2.add_argument("--retain_trimmed_reads", default=0, type=int, help = "Retain fastp trimmed fastq after decontamination. 0=No, 1=yes [Default: 0]") - parser_bowtie2.add_argument("--retain_contaminated_reads", default=0, type=int, help = "Retain contaminated fastq after decontamination. 0=No, 1=yes [Default: 0]") - parser_bowtie2.add_argument("--bowtie2_options", type=str, default="", help="Bowtie2 | More options (e.g. --arg 1 ) [Default: '']\nhttp://bowtie-bio.sourceforge.net/bowtie2/manual.shtml") - - # BBDuk - parser_bbduk = parser.add_argument_group('BBDuk arguments') - parser_bbduk.add_argument("-k","--kmer_database", type=str, help="BBDuk | path/to/kmer_database\n(e.g., Ribokmers in $VEBA_DATABASE/Contamination/kmers/ribokmers.fa.gz)") - parser_bbduk.add_argument("--kmer_size", type=int, default=31, help="BBDuk | k-mer size [Default: 31]") - parser_bbduk.add_argument("--retain_kmer_hits", default=0, type=int, help = "Retain reads that map to k-mer database. 0=No, 1=yes [Default: 0]") - parser_bbduk.add_argument("--retain_non_kmer_hits", default=0, type=int, help = "Retain reads that do not map to k-mer database. 0=No, 1=yes [Default: 0]") - parser_bbduk.add_argument("--bbduk_options", type=str, default="", help="BBDuk | More options (e.g., --arg 1) [Default: '']") - - # Options - opts = parser.parse_args() - # opts.script_directory = script_directory - # opts.script_filename = script_filename - - # Threads - if opts.n_jobs == -1: - from multiprocessing import cpu_count - opts.n_jobs = cpu_count() - assert opts.n_jobs >= 1, "--n_jobs must be ≥ 1. To select all available threads, use -1." - - #Get arguments - args = list() - for k,v in opts.__dict__.items(): - if v is not None: - args += ["--{}".format(k), str(v)] - # args = flatten(map(lambda item: ("--{}".format(item[0]), item[1]), opts.__dict__.items())) - sys.argv = [sys.argv[0]] + args - - # Wrapper - fastq_preprocessor.main(args) - - +__version__ = "2023.11.29" if __name__ == "__main__": - main() + print(format_header("VEBA Preprocessing Wrapper (fastq_preprocessor v{})".format(fastq_preprocessor_short.__version__)), file=sys.stderr) + label = "Mode: Paired Illumina Reads" + print(label, file=sys.stderr) + print(len(label)*"-", file=sys.stderr) + fastq_preprocessor_short.main(sys.argv[1:]) \ No newline at end of file diff --git a/src/profile-pathway.py b/src/profile-pathway.py index 3f674f4..d84738a 100755 --- a/src/profile-pathway.py +++ b/src/profile-pathway.py @@ -13,7 +13,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.30" DIAMOND_DATABASE_SUFFIX = "_v201901b.dmnd" @@ -625,6 +625,7 @@ def main(args=None): print("Script version:", __version__, file=sys.stdout) print("Moment:", get_timestamp(), file=sys.stdout) print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) configure_parameters(opts, directories) sys.stdout.flush() diff --git a/src/profile-taxonomy.py b/src/profile-taxonomy.py new file mode 100755 index 0000000..2aa4db0 --- /dev/null +++ b/src/profile-taxonomy.py @@ -0,0 +1,357 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, glob, gzip +from collections import OrderedDict, defaultdict + +import pandas as pd + +# Soothsayer Ecosystem +from genopype import * +from genopype import __version__ as genopype_version +from soothsayer_utils import * + +pd.options.display.max_colwidth = 100 +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.12.19" + +# Preprocess reads +def get_sylph_sketch_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): + cmd = [ + os.environ["sylph"], + "sketch", + "-t {}".format(opts.n_jobs), + "-c {}".format(opts.sylph_sketch_subsampling_rate), + "-k {}".format(opts.sylph_sketch_k), + "--min-spacing {}".format(opts.sylph_sketch_minimum_spacing), + "-1 {}".format(opts.forward_reads), + "-2 {}".format(opts.reverse_reads), + "-d {}".format(output_directory), + + "&&", + + "mv", + "-v", + os.path.join(output_directory, "{}.paired.sylsp".format(os.path.split(opts.forward_reads)[1])), + os.path.join(output_directory, "reads.sylsp"), + ] + + return cmd + +def get_sylph_profile_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): + # Command + cmd = [ + os.environ["sylph"], + "profile", + "-t {}".format(opts.n_jobs), + "--minimum-ani {}".format(opts.sylph_profile_minimum_ani), + "--min-number-kmers {}".format(opts.sylph_profile_minimum_number_kmers), + "--min-count-correct {}".format(opts.sylph_profile_minimum_count_correct), + opts.sylph_profile_options, + " ".join(input_filepaths), + "|", + "gzip", + ">", + os.path.join(output_directory, "sylph_profile.tsv.gz"), + + "&&", + + os.environ["reformat_sylph_profile_single_sample_output.py"], + "-i {}".format(os.path.join(output_directory, "sylph_profile.tsv.gz")), + "-o {}".format(output_directory), + "-c {}".format(opts.genome_clusters) if opts.genome_clusters else "", + "-f Taxonomic_abundance", + "-x {}".format(opts.extension), + "--header" if opts.header else "", + ] + + return cmd + + + +# ============ +# Run Pipeline +# ============ +# Set environment variables +def add_executables_to_environment(opts): + """ + Adapted from Soothsayer: https://github.com/jolespin/soothsayer + """ + accessory_scripts = set([ + "reformat_sylph_profile_single_sample_output.py", + ] + ) + + required_executables={ + "sylph", + # "seqkit", + + } | accessory_scripts + + if opts.path_config == "CONDA_PREFIX": + executables = dict() + for name in required_executables: + executables[name] = os.path.join(os.environ["CONDA_PREFIX"], "bin", name) + else: + if opts.path_config is None: + opts.path_config = os.path.join(opts.script_directory, "veba_config.tsv") + opts.path_config = format_path(opts.path_config) + assert os.path.exists(opts.path_config), "config file does not exist. Have you created one in the following directory?\n{}\nIf not, either create one, check this filepath:{}, or give the path to a proper config file using --path_config".format(opts.script_directory, opts.path_config) + assert os.stat(opts.path_config).st_size > 1, "config file seems to be empty. Please add 'name' and 'executable' columns for the following program names: {}".format(required_executables) + df_config = pd.read_csv(opts.path_config, sep="\t") + assert {"name", "executable"} <= set(df_config.columns), "config must have `name` and `executable` columns. Please adjust file: {}".format(opts.path_config) + df_config = df_config.loc[:,["name", "executable"]].dropna(how="any", axis=0).applymap(str) + # Get executable paths + executables = OrderedDict(zip(df_config["name"], df_config["executable"])) + assert required_executables <= set(list(executables.keys())), "config must have the required executables for this run. Please adjust file: {}\nIn particular, add info for the following: {}".format(opts.path_config, required_executables - set(list(executables.keys()))) + + # Display + for name in sorted(accessory_scripts): + executables[name] = "'{}'".format(os.path.join(opts.script_directory, "scripts", name)) # Can handle spaces in path + + print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) + for name, executable in executables.items(): + if name in required_executables: + print(name, executable, sep = " --> ", file=sys.stdout) + os.environ[name] = executable.strip() + print("", file=sys.stdout) + + +# Pipeline +def create_pipeline(opts, directories, f_cmds): + + # ................................................................. + # Primordial + # ................................................................. + # Commands file + pipeline = ExecutablePipeline(name=__program__, description=opts.name, f_cmds=f_cmds, checkpoint_directory=directories["checkpoints"], log_directory=directories["log"]) + + # ========== + # Preprocess reads + # ========== + + if opts.input_reads_format == "paired": + + step = 0 + + # Info + program = "sylph_sketch" + program_label = "{}__{}".format(step, program) + description = "Sketch input reads" + + # Add to directories + output_directory = directories["output"] + # i/o + input_filepaths = [opts.forward_reads, opts.reverse_reads] + output_filepaths = [ + os.path.join(output_directory, "reads.sylsp"), + ] + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_sylph_sketch_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + ) + else: + output_filepaths = [opts.reads_sketch] + + + # ========== + # Profile + # ========== + + step = 1 + + # Info + program = "sylph_profile" + program_label = "{}__{}".format(step, program) + description = "Profile genome databases" + + # Add to directories + output_directory = directories["output"] + + # i/o + input_filepaths = output_filepaths + opts.sylph_databases + + + output_filepaths = [ + os.path.join(output_directory, "sylph_profile.tsv.gz"), + os.path.join(output_directory, "taxonomic_abundance.tsv.gz"), + ] + if opts.genome_clusters: + input_filepaths += [ + opts.genome_clusters, + ] + output_filepaths += [ + os.path.join(output_directory, "taxonomic_abundance.clusters.tsv.gz"), + ] + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_sylph_profile_cmd(**params) + pipeline.add_step( + id=program_label, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + log_prefix=program_label, + + ) + + + + return pipeline + +# Configure parameters +def configure_parameters(opts, directories): + + for db in opts.sylph_databases: + assert db.endswith(".syldb"), "{} must have .syldb file extension".format(db) + + # --input_reads_format + assert_acceptable_arguments(opts.input_reads_format, {"paired", "sketch", "auto"}) + if opts.input_reads_format == "auto": + if any([opts.forward_reads, opts.reverse_reads]): + assert opts.forward_reads != opts.reverse_reads, "You probably mislabeled the input files because `forward_reads` should not be the same as `reverse_reads`: {}".format(opts.forward_reads) + assert opts.forward_reads is not None, "If running in --input_reads_format paired mode, --forward_reads and --reverse_reads are needed." + assert opts.reverse_reads is not None, "If running in --input_reads_format paired mode, --forward_reads and --reverse_reads are needed." + opts.input_reads_format = "paired" + if opts.reads_sketch is not None: + assert opts.forward_reads is None, "If running in --input_reads_format sketch mode, you cannot provide --forward_reads, --reverse_reads" + assert opts.reverse_reads is None, "If running in --input_reads_format sketch mode, you cannot provide --forward_reads, --reverse_reads" + opts.input_reads_format = "sketch" + + print("Auto detecting reads format: {}".format(opts.input_reads_format), file=sys.stdout) + assert_acceptable_arguments(opts.input_reads_format, {"paired", "sketch"}) + + # Set environment variables + add_executables_to_environment(opts=opts) + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -1 -2 |-s -n -o -d ".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + + # Pipeline + parser_io = parser.add_argument_group('Required I/O arguments') + parser_io.add_argument("-1","--forward_reads", type=str, help = "path/to/forward_reads.fq[.gz]") + parser_io.add_argument("-2","--reverse_reads", type=str, help = "path/to/reverse_reads.fq[.gz]]") + parser_io.add_argument("-s","--reads_sketch", type=str, help = "path/to/reads_sketch.sylsp (e.g., sylph sketch output) (Cannot be used with --forward_reads and --reverse_reads)") + parser_io.add_argument("-n", "--name", type=str, required=True, help="Name of sample") + parser_io.add_argument("-d","--sylph_databases", type=str, nargs="+", required=True, help = "Sylph database(s) with all genomes. Can be multiple databases delimited by spaces. Use compile_custom_sylph_sketch_database_from_genomes.py to build database.") + parser_io.add_argument("-o","--project_directory", type=str, default="veba_output/profiling/taxonomy", help = "path/to/project_directory [Default: veba_output/profiling/taxonomy]") + parser_io.add_argument("-c","--genome_clusters", type=str, help = "path/to/mags_to_slcs.tsv. [id_genome][id_genome-cluster], No header. Aggregates counts for genome clusters.") + parser_io.add_argument("-F", "--input_reads_format", choices={"paired", "sketch"}, type=str, default="auto", help = "Input reads format {paired, sketch} [Default: auto]") + parser_io.add_argument("-x","--extension", type=str, default="fa", help = "Fasta file extension for bins. Assumes all genomes have the same file extension. [Default: fa]") + + + # Utility + parser_utility = parser.add_argument_group('Utility arguments') + parser_utility.add_argument("--path_config", type=str, default="CONDA_PREFIX", help="path/to/config.tsv [Default: CONDA_PREFIX]") #site-packges in future + parser_utility.add_argument("-p", "--n_jobs", type=int, default=1, help = "Number of threads [Default: 1]") + parser_utility.add_argument("--random_state", type=int, default=0, help = "Random state [Default: 0]") + parser_utility.add_argument("--restart_from_checkpoint", type=str, default=None, help = "Restart from a particular checkpoint [Default: None]") + parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) + parser_utility.add_argument("--tmpdir", type=str, help="Set temporary directory") #site-packges in future + + # Sylph + parser_sylph_sketch = parser.add_argument_group('Sylph sketch arguments (Fastq)') + parser_sylph_sketch.add_argument("--sylph_sketch_k", type=int, choices={21,31}, default=31, help="Sylph sketch [Fastq] | Value of k. Only k = 21, 31 are currently supported. [Default: 31]") + parser_sylph_sketch.add_argument("--sylph_sketch_minimum_spacing", type=int, default=30, help="Sylph sketch [Fastq] | Minimum spacing between selected k-mers on the genomes [Default: 30]") + parser_sylph_sketch.add_argument("--sylph_sketch_subsampling_rate", type=int, default=100, help="Sylph sketch [Fastq] | Subsampling rate. sylph runs without issues if the -c for all genomes is ≥ the -c for reads. [Default: 100]") + parser_sylph_sketch.add_argument("--sylph_sketch_options", type=str, default="", help="Sylph sketch [Fastq] | More options for `sylph sketch` (e.g. --arg 1 ) [Default: '']") + + parser_sylph_profile = parser.add_argument_group('Sylph profile arguments') + parser_sylph_profile.add_argument("--sylph_profile_minimum_ani", type=float, default=95, help="Sylph profile | Minimum adjusted ANI to consider (0-100). [Default: 95]") + parser_sylph_profile.add_argument("--sylph_profile_minimum_number_kmers", type=int, default=20, help="Sylph profile | Exclude genomes with less than this number of sampled k-mers. Default is 50 in Sylph but lowering to 20 accounts for viruses and small CPR genomes. [Default: 20]") + parser_sylph_profile.add_argument("--sylph_profile_minimum_count_correct", type=int, default=3, help="Sylph profile | Minimum k-mer multiplicity needed for coverage correction. Higher values gives more precision but lower sensitivity [Default: 3]") + parser_sylph_profile.add_argument("--sylph_profile_options", type=str, default="", help="Sylph profile | More options for `sylph profile` (e.g. --arg 1 ) [Default: '']") + parser_sylph_profile.add_argument("--header", action="store_true", help = "Include header in taxonomic abundance tables") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Threads + if opts.n_jobs == -1: + from multiprocessing import cpu_count + opts.n_jobs = cpu_count() + assert opts.n_jobs >= 1, "--n_jobs must be ≥ 1. To select all available threads, use -1." + + + # Directories + directories = dict() + directories["project"] = create_directory(opts.project_directory) + directories["sample"] = create_directory(os.path.join(directories["project"], opts.name)) + directories["output"] = create_directory(os.path.join(directories["sample"], "output")) + + directories["log"] = create_directory(os.path.join(directories["sample"], "log")) + if not opts.tmpdir: + opts.tmpdir = os.path.join(directories["sample"], "tmp") + directories["tmp"] = create_directory(opts.tmpdir) + directories["checkpoints"] = create_directory(os.path.join(directories["sample"], "checkpoints")) + directories["intermediate"] = create_directory(os.path.join(directories["sample"], "intermediate")) + os.environ["TMPDIR"] = directories["tmp"] + + # Info + print(format_header(__program__, "="), file=sys.stdout) + print(format_header("Configuration:", "-"), file=sys.stdout) + print(format_header("Name: {}".format(opts.name), "."), file=sys.stdout) + print("Python version:", sys.version.replace("\n"," "), file=sys.stdout) + print("Python path:", sys.executable, file=sys.stdout) #sys.path[2] + print("GenoPype version:", genopype_version, file=sys.stdout) #sys.path[2] + print("Script version:", __version__, file=sys.stdout) + print("Moment:", get_timestamp(), file=sys.stdout) + print("Directory:", os.getcwd(), file=sys.stdout) + if "TMPDIR" in os.environ: print(os.environ["TMPDIR"], file=sys.stdout) + print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) + configure_parameters(opts, directories) + sys.stdout.flush() + + # Run pipeline + with open(os.path.join(directories["sample"], "commands.sh"), "w") as f_cmds: + pipeline = create_pipeline( + opts=opts, + directories=directories, + f_cmds=f_cmds, + ) + pipeline.compile() + pipeline.execute(restart_from_checkpoint=opts.restart_from_checkpoint) + +if __name__ == "__main__": + main() diff --git a/src/scripts/binning_wrapper.py b/src/scripts/binning_wrapper.py index cfd1c0e..a9904e6 100755 --- a/src/scripts/binning_wrapper.py +++ b/src/scripts/binning_wrapper.py @@ -12,7 +12,7 @@ # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.5.8" +__version__ = "2023.12.4" def get_maxbin2_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): # Create dummy scaffolds_to_bins.tsv to overwrite later. This makes DAS_Tool easier to run @@ -740,6 +740,9 @@ def add_executables_to_environment(opts): "merge_cutup_clustering.py", "extract_fasta_bins.py", } + # if opts.algorithm == "vrhyme": + # required_executables |= {"vRhyme"} + # if opts.algorithm == "metacoag": # required_executables |= {"MetaCoAG"} @@ -845,7 +848,7 @@ def main(argv=None): # Binning parser_binning = parser.add_argument_group('Binning arguments') - parser_binning.add_argument("-a", "--algorithm", type=str, default="metabat2", help="Binning algorithm: {concoct, metabat2, maxbin2} Future: {metacoag, vamb} [Default: metabat2] ") + parser_binning.add_argument("-a", "--algorithm", type=str, default="metabat2", help="Binning algorithm: {concoct, metabat2, maxbin2} Future: {vrhyme} [Default: metabat2] ") parser_binning.add_argument("-m", "--minimum_contig_length", type=int, default=1500, help="Minimum contig length. [Default: 1500] ") parser_binning.add_argument("-s", "--minimum_genome_length", type=int, default=150000, help="Minimum genome length. [Default: 150000] ") parser_binning.add_argument("-P","--bin_prefix", type=str, default="DEFAULT", help = "Prefix for bin names. Special strings include: 1) --bin_prefix NONE which does not include a bin prefix; and 2) --bin_prefix DEFAULT then prefix is [ALGORITHM_UPPERCASE]__") @@ -870,8 +873,8 @@ def main(argv=None): # parser_metacoag = parser.add_argument_group('MetaCoAG arguments') # parser_metacoag.add_argument("--metacoag_options", type=str, default="", help="MetaCoAG | More options (e.g. --arg 1 ) [Default: '']") - # parser_vamb = parser.add_argument_group('VAMB arguments') - # parser_vamb.add_argument("--vamb_options", type=str, default="", help="VAMB | More options (e.g. --arg 1 ) [Default: '']") + # parser_vrhyme = parser.add_argument_group('vRhyme arguments') + # parser_vrhyme.add_argument("--vrhyme_options", type=str, default="", help="vRhyme | More options (e.g. --arg 1 ) [Default: '']") # Options opts = parser.parse_args(argv) diff --git a/src/scripts/build_source_to_lineage_dictionary.py b/src/scripts/build_source_to_lineage_dictionary.py new file mode 100755 index 0000000..e593068 --- /dev/null +++ b/src/scripts/build_source_to_lineage_dictionary.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, gzip, pickle +from tqdm import tqdm +import pandas as pd + +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.13" + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o ".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser.add_argument("-i","--input", default="stdin", type=str, help = "Path to table [id_source][class][order][family][genus][species], with header. Can include more columns but the first column must be `id_source`. [Default: stdin]") + parser.add_argument("-o","--output", required=True, type=str, help = "Path to dictionary pickle object. Can be gzipped. (Recommended name: source_to_lineage.dict.pkl.gz)") + parser.add_argument("--separator", default=";", type=str, help = "Separator field for taxonomy [Default: ; ]") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Input + if opts.input == "stdin": + opts.input = sys.stdin + + + print(" * Reading identifier mappings from the following file: {}".format(opts.input), file=sys.stderr) + source_to_lineage = dict() + df_input = pd.read_csv(opts.input, sep="\t", index_col=0) + for id_source, row in tqdm(df_input.loc[:,["class", "order", "family", "genus", "species"]].iterrows(), total=df_input.shape[0]): + lineage = list() + for level, taxon in row.items(): + v = level[0] + "__" + if pd.notnull(taxon): + v += taxon + lineage.append(v) + source_to_lineage[id_source] = opts.separator.join(lineage) + + + + print(" * Writing Python dictionary: {}".format(opts.output), file=sys.stderr) + f_out = None + if opts.output.endswith((".gz", ".pgz")): + f_out = gzip.open(opts.output, "wb") + else: + f_out = open(opts.output, "wb") + assert f_out is not None, "Unrecognized file format: {}".format(opts.output) + pickle.dump(source_to_lineage, f_out) + + + + + + + +if __name__ == "__main__": + main() diff --git a/src/scripts/build_target_to_source_dictionary.py b/src/scripts/build_target_to_source_dictionary.py new file mode 100755 index 0000000..367bc94 --- /dev/null +++ b/src/scripts/build_target_to_source_dictionary.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, gzip, pickle + +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.15" + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o ".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser.add_argument("-i","--input", default="stdin", type=str, help = "Path to identifier mapping table [id_database][id_source][id_protein][id_hash], No header. [Default: stdin]") + parser.add_argument("-o","--output", required=True, type=str, help = "Path to dictionary pickle object. Can be gzipped. (Recommended name: target_to_source.dict.pkl.gz)") + parser.add_argument("-n","--number_of_sequences", type=int, help = "Number of sequences. If used, the tqdm is required.") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Input + f_in = None + if opts.input == "stdin": + f_in = sys.stdin + else: + if opts.input.endswith(".gz"): + f_in = gzip.open(opts.input, "rt") + else: + f_in = open(opts.input, "r") + assert f_in is not None, "Unrecognized file format: {}".format(opts.input) + + if opts.number_of_sequences is not None: + from tqdm import tqdm + input_iterable = tqdm(f_in, total=opts.number_of_sequences, unit=" sequences") + else: + input_iterable = f_in + + print(" * Reading identifier mappings from the following file: {}".format(f_in), file=sys.stderr) + target_to_source = dict() + for line in input_iterable: + line = line.strip() + if line: + fields = line.split("\t") + id_hash = fields[3] + id_source = fields[1] + target_to_source[id_hash] = id_source + if f_in != sys.stdin: + f_in.close() + + print(" * Writing Python dictionary: {}".format(opts.output), file=sys.stderr) + f_out = None + if opts.output.endswith((".gz", ".pgz")): + f_out = gzip.open(opts.output, "wb") + else: + f_out = open(opts.output, "wb") + assert f_out is not None, "Unrecognized file format: {}".format(opts.output) + pickle.dump(target_to_source, f_out) + + + + + + + +if __name__ == "__main__": + main() diff --git a/src/scripts/check_fasta_duplicates.py b/src/scripts/check_fasta_duplicates.py index b4ca8dd..527b508 100755 --- a/src/scripts/check_fasta_duplicates.py +++ b/src/scripts/check_fasta_duplicates.py @@ -3,7 +3,7 @@ from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.4.17" +__version__ = "2023.11.10" def main(args=None): # Path info @@ -30,13 +30,15 @@ def main(args=None): if not opts.input: identifiers = set() duplicates = set() - for line in tqdm(sys.stdin, "stdin"): + for i, line in tqdm(enumerate(sys.stdin), "stdin"): if line.startswith(">"): id = line[1:].split(" ")[0].strip() if id not in identifiers: identifiers.add(id) else: duplicates.add(id) + else: + assert ">" not in line, "Line={} has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(i+1) if duplicates: print("# Duplicates:", *sorted(duplicates), file=sys.stdout, sep="\n", end=None) sys.exit(1) @@ -48,13 +50,16 @@ def main(args=None): identifiers = set() duplicates = set() f = {True:gzip.open(fp, "rt"), False:open(fp, "r")}[fp.endswith(".gz")] - for line in tqdm(f, fp): + for i,line in tqdm(enumerate(f), fp): if line.startswith(">"): id = line[1:].split(" ")[0] if id not in identifiers: identifiers.add(id) else: duplicates.add(id) + else: + assert ">" not in line, "Line={} has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(i+1) + if duplicates: files_with_duplicates.add(fp) print(f"[Fail] {fp}", file=sys.stdout) diff --git a/src/scripts/clean_fasta.py b/src/scripts/clean_fasta.py new file mode 100755 index 0000000..92192c6 --- /dev/null +++ b/src/scripts/clean_fasta.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +import sys, os, argparse, gzip +from Bio.SeqIO.FastaIO import SimpleFastaParser +from tqdm import tqdm + +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.10" + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o )".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + + # Pipeline + parser.add_argument("-i","--input", default="stdin", type=str, help = "Input fasta file") + parser.add_argument("-o","--output", default="stdout", type=str, help = "Output fasta file") + parser.add_argument("-r","--retain_description", action="store_true", help = "Retain description") + parser.add_argument("-s","--retain_stop_codon", action="store_true", help = "Retain stop codon character (if one exists)") + parser.add_argument("-m","--minimum_sequence_length", default=1, type=int, help = "Minimum sequence length accepted [Default: 1]") + parser.add_argument("--stop_codon_character", default="*", type=str, help = "Stop codon character [Default: *] ") + # parser.add_argument("-t","--molecule_type", help = "Comma-separated list of names for the --scaffolds_to_bins") + + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + assert opts.minimum_sequence_length > 0 + + # Input + f_in = None + if opts.input == "stdin": + f_in = sys.stdin + else: + if opts.input.endswith(".gz"): + f_in = gzip.open(opts.input, "rt") + else: + f_in = open(opts.input, "r") + assert f_in is not None + + # Output + f_out = None + if opts.output == "stdout": + f_out = sys.stdout + else: + if opts.output.endswith(".gz"): + f_out = gzip.open(opts.output, "wt") + else: + f_out = open(opts.output, "w") + assert f_out is not None + + # retain_description=True + # retain_stop_codon=True + if all([ + opts.retain_description, + opts.retain_stop_codon, + ]): + for header, seq in tqdm(SimpleFastaParser(f_in), "Reading fasta input"): + header = header.strip() + if len(seq) >= opts.minimum_sequence_length: + assert ">" not in seq, "`{}` has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(header) + print(">{}\n{}".format(header,seq), file=f_out) + + # retain_description=False + # retain_stop_codon=True + if all([ + not opts.retain_description, + opts.retain_stop_codon, + ]): + for header, seq in tqdm(SimpleFastaParser(f_in), "Reading fasta input"): + id = header.split(" ")[0].strip() + if len(seq) >= opts.minimum_sequence_length: + assert ">" not in seq, "`{}` has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(header) + print(">{}\n{}".format(id,seq), file=f_out) + + # retain_description=True + # retain_stop_codon=False + if all([ + opts.retain_description, + not opts.retain_stop_codon, + ]): + for header, seq in tqdm(SimpleFastaParser(f_in), "Reading fasta input"): + header = header.strip() + if seq.endswith(opts.stop_codon_character): + seq = seq[:-1] + if len(seq) >= opts.minimum_sequence_length: + assert ">" not in seq, "`{}` has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(header) + print(">{}\n{}".format(header,seq), file=f_out) + + # retain_description=False + # retain_stop_codon=False + if all([ + not opts.retain_description, + not opts.retain_stop_codon, + ]): + for header, seq in tqdm(SimpleFastaParser(f_in), "Reading fasta input"): + id = header.split(" ")[0].strip() + if seq.endswith(opts.stop_codon_character): + seq = seq[:-1] + if len(seq) >= opts.minimum_sequence_length: + assert ">" not in seq, "`{}` has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(header) + print(">{}\n{}".format(id,seq), file=f_out) + + # Close + if f_in != sys.stdin: + f_in.close() + if f_out != sys.stdout: + f_out.close() + +if __name__ == "__main__": + main() + + + diff --git a/src/scripts/clustering_wrapper.py b/src/scripts/clustering_wrapper.py new file mode 100755 index 0000000..b8eddbb --- /dev/null +++ b/src/scripts/clustering_wrapper.py @@ -0,0 +1,439 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, glob, shutil, time, warnings +from multiprocessing import cpu_count +from collections import OrderedDict, defaultdict + +import pandas as pd + +# Soothsayer Ecosystem +from genopype import * +from soothsayer_utils import * + +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.10" + +# Check +def get_check_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + # Command + + # Command + cmd = [ + os.environ["check_fasta_duplicates.py"], + opts.fasta, + ] + + return cmd + +def get_mmseqs2_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + cmd = [ + os.environ["mmseqs"], + "easy-{}".format(opts.algorithm.split("-")[1]), + opts.fasta, + os.path.join(output_directory, "mmseqs2"), + directories["tmp"], + "--threads {}".format(opts.n_jobs), + "--min-seq-id {}".format(opts.minimum_identity_threshold/100), + "-c {}".format(opts.minimum_coverage_threshold), + "--cov-mode 1", + opts.mmseqs2_options, + + "&&", + + "mv", + os.path.join(output_directory, "mmseqs2_cluster.tsv"), + os.path.join(output_directory, "clusters.tsv"), + + "&&", + + "mv", + os.path.join(output_directory, "mmseqs2_rep_seq.fasta"), + os.path.join(output_directory, "representatives.fasta"), + + "&&", + + "gzip", + os.path.join(output_directory, "representatives.fasta"), + + "&&", + + "rm -rf", + os.path.join(output_directory, "mmseqs2_all_seqs.fasta"), + os.path.join(directories["tmp"], "*"), + ] + + return cmd + +def get_diamond_cmd( input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + cmd = [ + os.environ["diamond"], + {"diamond-cluster":"cluster", "diamond-linclust":"linclust"}[opts.algorithm], + "--db", + opts.fasta, + "--out", + os.path.join(output_directory, "clusters.tsv"), + "--tmpdir", + directories["tmp"], + "--threads {}".format(opts.n_jobs), + "--approx-id {}".format(opts.minimum_identity_threshold), + "--member-cover {}".format(opts.minimum_coverage_threshold*100), + opts.diamond_options, + + "&&", + + "cut -f1", + os.path.join(output_directory, "clusters.tsv"), + "|", + "sort -u", + ">", + os.path.join(output_directory, "representatives.list"), + + "&&", + + os.environ["seqkit"], + "grep", + "-w 0", + "-f", + os.path.join(output_directory, "representatives.list"), + opts.fasta, + "|", + "gzip", + ">", + os.path.join(output_directory, "representatives.fasta.gz"), + + "&&", + + "rm -rf", + os.path.join(directories["tmp"], "*"), + ] + + return cmd + +# Compile +def get_compile_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): + + # Command + cmd = [ + + os.environ["edgelist_to_clusters.py"], + "-i {}".format(input_filepaths[0]), + "--no_singletons" if bool(opts.no_singletons) else "", + "--cluster_prefix {}".format(opts.cluster_prefix) if bool(opts.cluster_prefix) else "", + "--cluster_suffix {}".format(opts.cluster_suffix) if bool(opts.cluster_suffix) else "", + "--cluster_prefix_zfill {}".format(opts.cluster_prefix_zfill), + "-o {}".format(os.path.join(output_directory, "{}.tsv".format(opts.basename))), + # "-g {}".format(os.path.join(output_directory, "{}.networkx_graph.pkl".format(opts.basename))), + # "-d {}".format(os.path.join(output_directory, "{}.dict.pkl".format(opts.basename))), + "--identifiers {}".format(opts.identifiers) if bool(opts.identifiers) else "", + + "&&", + + os.environ["reformat_representative_sequences.py"], + "-c {}".format(os.path.join(output_directory, "{}.tsv".format(opts.basename))), + "-i {}".format(input_filepaths[1]), + "-f {}".format(opts.representative_output_format), + "-o {}".format(output_filepaths[1]), + ] + + if opts.no_sequences_and_header: + cmd += [ + "--no_sequences", + "--no_header", + ] + + return cmd + +# ============ +# Run Pipeline +# ============ +# Set environment variables +def add_executables_to_environment(opts): + """ + Adapted from Soothsayer: https://github.com/jolespin/soothsayer + """ + accessory_scripts = set([ + "check_fasta_duplicates.py", + "edgelist_to_clusters.py", + "reformat_representative_sequences.py", + ]) + + required_executables={ + "mmseqs", + "diamond", + "seqkit", + + } | accessory_scripts + + if opts.path_config == "CONDA_PREFIX": + executables = dict() + for name in required_executables: + executables[name] = os.path.join(os.environ["CONDA_PREFIX"], "bin", name) + else: + if opts.path_config is None: + opts.path_config = os.path.join(opts.script_directory, "veba_config.tsv") + opts.path_config = format_path(opts.path_config) + assert os.path.exists(opts.path_config), "config file does not exist. Have you created one in the following directory?\n{}\nIf not, either create one, check this filepath:{}, or give the path to a proper config file using --path_config".format(opts.script_directory, opts.path_config) + assert os.stat(opts.path_config).st_size > 1, "config file seems to be empty. Please add 'name' and 'executable' columns for the following program names: {}".format(required_executables) + df_config = pd.read_csv(opts.path_config, sep="\t") + assert {"name", "executable"} <= set(df_config.columns), "config must have `name` and `executable` columns. Please adjust file: {}".format(opts.path_config) + df_config = df_config.loc[:,["name", "executable"]].dropna(how="any", axis=0).applymap(str) + # Get executable paths + executables = OrderedDict(zip(df_config["name"], df_config["executable"])) + assert required_executables <= set(list(executables.keys())), "config must have the required executables for this run. Please adjust file: {}\nIn particular, add info for the following: {}".format(opts.path_config, required_executables - set(list(executables.keys()))) + + # Display + for name in sorted(accessory_scripts): + executables[name] = "'{}'".format(os.path.join(opts.script_directory, name)) # Can handle spaces in path + + print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) + for name, executable in executables.items(): + if name in required_executables: + print(name, executable, sep = " --> ", file=sys.stdout) + os.environ[name] = executable.strip() + print("", file=sys.stdout) + +# Pipeline +def create_pipeline(opts, directories, f_cmds): + + # ................................................................. + # Primordial + # ................................................................. + # Commands file + pipeline = ExecutablePipeline(name=__program__, f_cmds=f_cmds, checkpoint_directory=directories["checkpoints"], log_directory=directories["log"]) + + + # ========== + # Preprocessing + # ========== + + program = "check" + # Add to directories + output_directory = directories["tmp"] + + # Info + step = 0 + description = "Check sequences for duplicates" + + # i/o + input_filepaths = [opts.fasta] + output_filepaths = [ + ] + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_check_cmd(**params) + + pipeline.add_step( + id=program, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=False, + ) + + # ========== + # Clustering + # ========== + step = 1 + + # i/o + output_directory = directories["intermediate"] + + input_filepaths = [opts.fasta] + output_filenames = [ + "clusters.tsv", + "representatives.fasta.gz", + ] + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + if opts.algorithm.split("-")[0] == "mmseqs": + program = "mmseqs2" + # Info + description = "Cluster sequences via MMSEQS2" + cmd = get_mmseqs2_cmd(**params) + + if opts.algorithm.split("-")[0] == "diamond": + program = "diamond" + description = "Cluster sequences via Diamond" + cmd = get_diamond_cmd(**params) + + pipeline.add_step( + id=program, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + ) + + # ========== + # Compile + # ========== + + program = "compile" + # Add to directories + output_directory = directories["output"] + + # Info + step = 2 + description = "Compile clustering results" + + # i/o + input_filepaths = output_filepaths + output_filenames = [ + "{}.tsv".format(opts.basename), + ] + if opts.representative_output_format == "table": + output_filenames += ["representative_sequences.tsv.gz"] + if opts.representative_output_format == "fasta": + output_filenames += ["representative_sequences.fasta.gz"] + output_filepaths = list(map(lambda filename: os.path.join(output_directory, filename), output_filenames)) + + params = { + "input_filepaths":input_filepaths, + "output_filepaths":output_filepaths, + "output_directory":output_directory, + "opts":opts, + "directories":directories, + } + + cmd = get_compile_cmd(**params) + + pipeline.add_step( + id=program, + description = description, + step=step, + cmd=cmd, + input_filepaths = input_filepaths, + output_filepaths = output_filepaths, + validate_inputs=True, + validate_outputs=True, + ) + + return pipeline + +# Configure parameters +def configure_parameters(opts, directories): + + assert_acceptable_arguments(opts.algorithm, {"easy-cluster", "easy-linclust", "mmseqs-cluster", "mmseqs-linclust", "diamond-cluster", "diamond-linclust"}) + if opts.algorithm in {"easy-cluster", "easy-linclust"}: + d = {"easy-cluster":"mmseqs-cluster", "easy-linclust":"mmseqs-linclust"} + warnings.warn("\n\nPlease use `{}` instead of `{}` for MMSEQS2 clustering.".format(d[opts.algorithm], opts.algorithm)) + opts.algorithm = d[opts.algorithm] + assert_acceptable_arguments(opts.representative_output_format, {"table", "fasta"}) + # Set environment variables + add_executables_to_environment(opts=opts) + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o ".format(__program__) + + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser_io = parser.add_argument_group('Required I/O arguments') + parser_io.add_argument("-i","--fasta", type=str, help = "Fasta file") + parser_io.add_argument("-o","--output_directory", type=str, default="clustering_output", help = "path/to/project_directory [Default: clustering_output]") + parser_io.add_argument("-e", "--no_singletons", action="store_true", help="Exclude singletons") + parser_io.add_argument("-b", "--basename", type=str, default="clusters", help="Basename for clustering files [Default: clusters]") + + # Utility + parser_utility = parser.add_argument_group('Utility arguments') + parser_utility.add_argument("--path_config", type=str, default="CONDA_PREFIX", help="path/to/config.tsv [Default: CONDA_PREFIX]") #site-packges in future + parser_utility.add_argument("-p", "--n_jobs", type=int, default=1, help = "Number of threads [Default: 1]") + parser_utility.add_argument("--restart_from_checkpoint", type=str, default=None, help = "Restart from a particular checkpoint [Default: None]") + parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) + # parser_utility.add_argument("--verbose", action='store_true') + + # Clustering + parser_clustering = parser.add_argument_group('Clustering arguments') + parser_clustering.add_argument("-a", "--algorithm", type=str, default="mmseqs-cluster", help="Clustering algorithm | Diamond can only be used for clustering proteins {mmseqs-cluster, mmseqs-linclust, diamond-cluster, mmseqs-linclust} [Default: mmseqs-cluster]") + parser_clustering.add_argument("-t", "--minimum_identity_threshold", type=float, default=50.0, help="Clustering | Percent identity threshold (Range (0.0, 100.0]) [Default: 50.0]") + parser_clustering.add_argument("-c", "--minimum_coverage_threshold", type=float, default=0.8, help="Clustering | Coverage threshold (Range (0.0, 1.0]) [Default: 0.8]") + parser_clustering.add_argument("--cluster_prefix", type=str, default="SC-", help="Sequence cluster prefix [Default: 'SC-]") + parser_clustering.add_argument("--cluster_suffix", type=str, default="", help="Sequence cluster suffix [Default: '']") + parser_clustering.add_argument("--cluster_prefix_zfill", type=int, default=0, help="Sequence cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 + parser_clustering.add_argument("--mmseqs2_options", type=str, default="", help="MMSEQS2 | More options (e.g. --arg 1 ) [Default: '']") + parser_clustering.add_argument("--diamond_options", type=str, default="", help="Diamond | More options (e.g. --arg 1 ) [Default: '']") + parser_clustering.add_argument("--identifiers", type=str, help = "Identifiers to include for `edgelist_to_clusters.py`. If missing identifiers and singletons are allowed, then they will be included as singleton clusters with weight of np.inf") + parser_clustering.add_argument("--no_sequences_and_header", action="store_true", help = "Don't include sequences or header in table. Useful for concatenation and reduced redundancy of sequences") + parser_clustering.add_argument("-f","--representative_output_format", type=str, default="fasta", help = "Format of output for representative sequences: {table, fasta} [Default: fasta]") # Should fasta be the new default? + + # Options + opts = parser.parse_args() + + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Threads + if opts.n_jobs == -1: + opts.n_jobs = cpu_count() + assert opts.n_jobs >= 1, "--n_jobs must be ≥ 1 (or -1 to use all available threads)" + + # Directories + directories = dict() + directories["project"] = create_directory(opts.output_directory) + directories["output"] = create_directory(os.path.join(directories["project"], "output")) + directories["log"] = create_directory(os.path.join(directories["project"], "log")) + directories["tmp"] = create_directory(os.path.join(directories["project"], "tmp")) + directories["checkpoints"] = create_directory(os.path.join(directories["project"], "checkpoints")) + directories["intermediate"] = create_directory(os.path.join(directories["project"], "intermediate")) + os.environ["TMPDIR"] = directories["tmp"] + + # Info + print(format_header(__program__, "="), file=sys.stdout) + print(format_header("Configuration:", "-"), file=sys.stdout) + print("Python version:", sys.version.replace("\n"," "), file=sys.stdout) + print("Python path:", sys.executable, file=sys.stdout) #sys.path[2] + print("Script version:", __version__, file=sys.stdout) + print("Moment:", get_timestamp(), file=sys.stdout) + print("Directory:", os.getcwd(), file=sys.stdout) + print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) + configure_parameters(opts, directories) + sys.stdout.flush() + + # Run pipeline + with open(os.path.join(directories["project"], "commands.sh"), "w") as f_cmds: + pipeline = create_pipeline( + opts=opts, + directories=directories, + f_cmds=f_cmds, + ) + pipeline.compile() + pipeline.execute(restart_from_checkpoint=opts.restart_from_checkpoint) + +if __name__ == "__main__": + main(sys.argv[1:]) + + diff --git a/src/scripts/compile_custom_humann_database_from_annotations.py b/src/scripts/compile_custom_humann_database_from_annotations.py index a644bb5..6604413 100755 --- a/src/scripts/compile_custom_humann_database_from_annotations.py +++ b/src/scripts/compile_custom_humann_database_from_annotations.py @@ -11,7 +11,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.11" +__version__ = "2023.12.15" def main(args=None): @@ -31,7 +31,7 @@ def main(args=None): parser.add_argument("-a","--annotations", type=str, required=True, help = "path/to/annotations.tsv[.gz] Output from annotations.py. Multi-level header that contains (UniRef, sseqid)") parser.add_argument("-t","--taxonomy", type=str, required=True, help = "path/to/taxonomy.tsv[.gz] [id_genome][classification] (No header). Use output from `merge_taxonomy_classifications.py` with --no_header and --no_domain") parser.add_argument("-s","--sequences", type=str, required=True, help = "path/to/proteins.fasta[.gz]") - parser.add_argument("-o","--output", type=str, default="stdout", help = "path/to/humann_uniref_annotations.tsv[.gz] [Default: stdout]") + parser.add_argument("-o","--output", type=str, default="stdout", help = "path/to/humann_uniref_annotations.tsv[.gz] (veba_output/profiling/databases/) is recommended [Default: stdout]") parser.add_argument("--sep", default=";", help = "Separator for taxonomic levels [Default: ;]") # parser.add_argument("--mandatory_taxonomy_prefixes", help = "Comma-separated values for mandatory prefix levels. (e.g., 'c__,f__,g__,s__')") # parser.add_argument("--discarded_file", help = "Proteins that have been discarded due to incomplete lineage") diff --git a/src/scripts/compile_custom_sylph_sketch_database_from_genomes.py b/src/scripts/compile_custom_sylph_sketch_database_from_genomes.py new file mode 100755 index 0000000..9c25424 --- /dev/null +++ b/src/scripts/compile_custom_sylph_sketch_database_from_genomes.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, glob, shutil, time, warnings +from multiprocessing import cpu_count +from collections import OrderedDict, defaultdict + +import pandas as pd + +# Soothsayer Ecosystem +from genopype import * +from genopype import __version__ as genopype_version +from soothsayer_utils import * + +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.12.15" + +# ============ +# Run Pipeline +# ============ +# Set environment variables +def add_executables_to_environment(opts): + """ + Adapted from Soothsayer: https://github.com/jolespin/soothsayer + """ + accessory_scripts = set([ + + ]) + + required_executables={ + "sylph", + + } | accessory_scripts + + if opts.path_config == "CONDA_PREFIX": + executables = dict() + for name in required_executables: + executables[name] = os.path.join(os.environ["CONDA_PREFIX"], "bin", name) + else: + if opts.path_config is None: + opts.path_config = os.path.join(opts.script_directory, "veba_config.tsv") + opts.path_config = format_path(opts.path_config) + assert os.path.exists(opts.path_config), "config file does not exist. Have you created one in the following directory?\n{}\nIf not, either create one, check this filepath:{}, or give the path to a proper config file using --path_config".format(opts.script_directory, opts.path_config) + assert os.stat(opts.path_config).st_size > 1, "config file seems to be empty. Please add 'name' and 'executable' columns for the following program names: {}".format(required_executables) + df_config = pd.read_csv(opts.path_config, sep="\t") + assert {"name", "executable"} <= set(df_config.columns), "config must have `name` and `executable` columns. Please adjust file: {}".format(opts.path_config) + df_config = df_config.loc[:,["name", "executable"]].dropna(how="any", axis=0).applymap(str) + # Get executable paths + executables = OrderedDict(zip(df_config["name"], df_config["executable"])) + assert required_executables <= set(list(executables.keys())), "config must have the required executables for this run. Please adjust file: {}\nIn particular, add info for the following: {}".format(opts.path_config, required_executables - set(list(executables.keys()))) + + # Display + for name in sorted(accessory_scripts): + executables[name] = "'{}'".format(os.path.join(opts.script_directory, name)) # Can handle spaces in path + + print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) + for name, executable in executables.items(): + if name in required_executables: + print(name, executable, sep = " --> ", file=sys.stdout) + os.environ[name] = executable.strip() + print("", file=sys.stdout) + + +# Configure parameters +def configure_parameters(opts, directories): + + + # Set environment variables + add_executables_to_environment(opts=opts) + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o ".format(__program__) + + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser_io = parser.add_argument_group('Required I/O arguments') + parser_io.add_argument("-i","--input", type=str, default="stdin", help = "path/to/input.tsv. Format: Must include the following columns (No header)[organism_type][path/to/genome.fa]. You can get this from `cut -f1,4 veba_output/misc/genomes_table.tsv` [Default: stdin]") + parser_io.add_argument("-o","--output_directory", type=str, default="veba_output/profiling/databases", help = "path/to/output_directory for databases [Default: veba_output/profiling/databases]") + parser_io.add_argument("--viral_tag", type=str, default="viral", help = "[Not case sensitive] Tag/Label of viral organisms in first column of --input (e.g., viral, virus, viron) [Default: viral]") + + + # Utility + parser_utility = parser.add_argument_group('Utility arguments') + parser_utility.add_argument("--path_config", type=str, default="CONDA_PREFIX", help="path/to/config.tsv [Default: CONDA_PREFIX]") #site-packges in future + parser_utility.add_argument("-p", "--n_jobs", type=int, default=1, help = "Number of threads [Default: 1]") + parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) + # parser_utility.add_argument("--verbose", action='store_true') + + # Sylph + parser_sylph = parser.add_argument_group('Sylph sketch arguments') + parser_sylph.add_argument("-k", "--sylph_k", type=int, choices={21,31}, default=31, help="Sylph | Value of k. Only k = 21, 31 are currently supported. [Default: 31]") + parser_sylph.add_argument("-s", "--sylph_minimum_spacing", type=int, default=30, help="Sylph | Minimum spacing between selected k-mers on the genomes [Default: 30]") + + parser_sylph_nonviral = parser.add_argument_group('[Prokaryotic & Eukaryotic] Sylph sketch arguments') + parser_sylph_nonviral.add_argument("--sylph_nonviral_subsampling_rate", type=int, default=200, help="Sylph [Prokaryotic & Eukaryotic]| Subsampling rate. [Default: 200]") + parser_sylph_nonviral.add_argument("--sylph_nonviral_options", type=str, default="", help="Sylph [Prokaryotic & Eukaryotic] | More options for `sylph sketch` (e.g. --arg 1 ) [Default: '']") + + parser_sylph_viral = parser.add_argument_group('[Viral] Sylph sketch arguments') + parser_sylph_viral.add_argument("--sylph_viral_subsampling_rate", type=int, default=100, help="Sylph [Viral]| Subsampling rate. [Default: 100]") + parser_sylph_viral.add_argument("--sylph_viral_options", type=str, default="", help="Sylph [Viral] | More options for `sylph sketch` (e.g. --arg 1 ) [Default: '']") + + # Options + opts = parser.parse_args() + + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Threads + if opts.n_jobs == -1: + opts.n_jobs = cpu_count() + assert opts.n_jobs >= 1, "--n_jobs must be ≥ 1 (or -1 to use all available threads)" + + # Directories + directories = dict() + directories["output"] = create_directory(opts.output_directory) + directories["intermediate"] = create_directory(os.path.join(directories["output"], "intermediate")) + directories["log"] = create_directory(os.path.join(directories["intermediate"], "log")) + directories["checkpoints"] = create_directory(os.path.join(directories["intermediate"], "checkpoints")) + + # Info + print(format_header(__program__, "="), file=sys.stdout) + print(format_header("Configuration:", "-"), file=sys.stdout) + print("Python version:", sys.version.replace("\n"," "), file=sys.stdout) + print("Python path:", sys.executable, file=sys.stdout) #sys.path[2] + print("Script version:", __version__, file=sys.stdout) + print("GenoPype version:", genopype_version, file=sys.stdout) #sys.path[2] + print("Moment:", get_timestamp(), file=sys.stdout) + print("Directory:", os.getcwd(), file=sys.stdout) + print("Commands:", list(filter(bool,sys.argv)), sep="\n", file=sys.stdout) + configure_parameters(opts, directories) + sys.stdout.flush() + + # Make directories + t0 = time.time() + # print(format_header("* ({}) Creating directories:".format(format_duration(t0)), opts.output_directory), file=sys.stdout) + # os.makedirs(opts.output_directory, exist_ok=True) + + # Load input + if opts.input == "stdin": + opts.input = sys.stdin + df_genomes = pd.read_csv(opts.input, sep="\t", header=None) + assert df_genomes.shape[1] == 2, "Must include the follow columns (No header) [organism_type][genome]). Suggested input is from `compile_genomes_table.py` script using `cut -f1,4` to get the necessary columns." + df_genomes.columns = ["organism_type", "genome"] + + opts.viral_tag = opts.viral_tag.lower() + + print(format_header("* ({}) Organizing genomes by organism_type".format(format_duration(t0))), file=sys.stdout) + organism_to_genomes = defaultdict(set) + for i, (organism_type, genome_filepath) in pv(df_genomes.iterrows(), unit="genomes ", total=df_genomes.shape[0]): + organism_type = organism_type.lower() + if organism_type == opts.viral_tag: + organism_to_genomes["viral"].add(genome_filepath) + else: + organism_to_genomes["nonviral"].add(genome_filepath) + # del df_genomes + + # Commands + f_cmds = open(os.path.join(directories["intermediate"], "commands.sh"), "w") + + for organism_type, filepaths in organism_to_genomes.items(): + # Write genomes to file + print(format_header("* ({}) Creating genome database: (N={}) for organism_type='{}'".format(format_duration(t0),len(filepaths), organism_type)), file=sys.stdout) + + genome_filepaths_list = os.path.join(directories["intermediate"], "{}_genomes.list".format(organism_type)) + with open(genome_filepaths_list, "w") as f: + for fp in sorted(filepaths): + print(fp, file=f) + + name = "sylph__{}".format(organism_type) + description = "[Program = sylph sketch] [Organism_Type = {}]".format(organism_type) + + arguments = [ + os.environ["sylph"], + "sketch", + "-t {}".format(opts.n_jobs), + "--gl {}".format(genome_filepaths_list), + "-o {}".format(os.path.join(opts.output_directory, "genome_database-{}".format(organism_type))), + "-k {}".format(opts.sylph_k), + "--min-spacing {}".format(opts.sylph_minimum_spacing), + ] + + if organism_type == "nonviral": + arguments += [ + "-c {}".format(opts.sylph_nonviral_subsampling_rate), + opts.sylph_nonviral_options, + ] + + else: + arguments += [ + "-c {}".format(opts.sylph_viral_subsampling_rate), + opts.sylph_viral_options, + ] + print(arguments, file=sys.stdout) + cmd = Command( + arguments, + name=name, + f_cmds=f_cmds, + ) + + + # Run command + cmd.run( + checkpoint_message_notexists="[Running ({})] | {}".format(format_duration(t0), description), + checkpoint_message_exists="[Loading Checkpoint ({})] | {}".format(format_duration(t0), description), + write_stdout=os.path.join(directories["log"], "{}.o".format(name)), + write_stderr=os.path.join(directories["log"], "{}.e".format(name)), + write_returncode=os.path.join(directories["log"], "{}.returncode".format(name)), + checkpoint=os.path.join(directories["checkpoints"], name), + ) + + if hasattr(cmd, "returncode_"): + if cmd.returncode_ != 0: + print("[Error] | {}".format(description), file=sys.stdout) + print("Check the following files:\ncat {}".format(os.path.join(directories["log"], "{}.*".format(name))), file=sys.stdout) + sys.exit(cmd.returncode_) + else: + output_filepath = os.path.join(opts.output_directory, "genome_database-{}.syldb".format(organism_type)) + size_bytes = os.path.getsize(output_filepath) + size_mb = size_bytes >> 20 + if size_mb < 1: + print("Output Database:", output_filepath, "({} bytes)".format(size_bytes), file=sys.stdout) + else: + print("Output Database:", output_filepath, "({} MB)".format(size_mb), file=sys.stdout) + + f_cmds.close() + +if __name__ == "__main__": + main(sys.argv[1:]) + + diff --git a/src/scripts/compile_eukaryotic_classifications.py b/src/scripts/compile_eukaryotic_classifications.py index 609526e..4841d85 100755 --- a/src/scripts/compile_eukaryotic_classifications.py +++ b/src/scripts/compile_eukaryotic_classifications.py @@ -6,7 +6,7 @@ from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.3.20" +__version__ = "2023.12.14" def main(args=None): @@ -16,20 +16,23 @@ def main(args=None): # Path info description = """ Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) - usage = "{} -i -s -c -o ".format(__program__) + usage = "{} -i -s -c -o ".format(__program__) epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" # Parser parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) # Pipeline parser.add_argument("-i","--metaeuk_identifier_mapping", type=str, required=True, help = "path/to/identifier_mapping.metaeuk.tsv") - parser.add_argument("-s","--scaffolds_to_bins", type=str, required=True, help = "path/to/scaffolds_to_bins.tsv") - parser.add_argument("-c","--clusters", type=str, help = "path/to/clusters.tsv, Format: [id_mag][id_cluster], No header [Optional]") - parser.add_argument("-o","--output", type=str, default="stdout", help = "path/to/output.tsv [Default: stdout]") - parser.add_argument("--eukaryotic_database", type=str, default=None, required=True, help="path/to/eukaryotic_database (e.g. --arg 1 )") + parser.add_argument("-s","--scaffolds_to_bins", type=str, required=False, help = "path/to/scaffolds_to_bins.tsv") + # parser.add_argument("-g","--genes_to_contigs", type=str, required=False, help = "path/to/genes_to_contigs.tsv cannot be used with --scaffolds_to_bins") + parser.add_argument("-c","--clusters", type=str, help = "path/to/clusters.tsv, Format: [id_genome][id_cluster], No header [Optional]") + parser.add_argument("-o","--output", type=str, default="stdout", help = "path/to/gene-source_lineage.tsv [Default: stdout]") + parser.add_argument("-d", "--eukaryotic_database", type=str, default=None, required=True, help="path/to/eukaryotic_database directory (e.g. --arg 1 )") # parser.add_argument("--veba_database", type=str, default=None, help=f"VEBA database location. [Default: $VEBA_DATABASE environment variable]") parser.add_argument("--header", type=int, default=1, help="Include header in output {0=No, 1=Yes) [Default: 1]") parser.add_argument("--debug", action="store_true") + parser.add_argument("--remove_genes_with_missing_values", action="store_true") + parser.add_argument("--use_original_metaeuk_gene_identifiers", action="store_true") # Options opts = parser.parse_args() @@ -44,20 +47,15 @@ def main(args=None): # opts.eukaryotic_database = os.path.join(opts.veba_database, "Classify", "Microeukaryotic") # I/O - # Scaffolds -> Bins - fp = opts.scaffolds_to_bins - print("* Reading scaffolds to bins table {}".format(fp), file=sys.stderr) - scaffold_to_bin = pd.read_csv(fp, sep="\t", index_col=0, header=None).iloc[:,0] - if opts.debug: - print(fp, file=sys.stderr) - scaffold_to_bin.head().to_csv(sys.stderr, sep="\t", header=None) - print("\n", file=sys.stderr) + # SourceID -> Taxonomy fp = os.path.join(opts.eukaryotic_database,"source_taxonomy.tsv.gz") print("* Reading source taxonomy table {}".format(fp), file=sys.stderr) df_source_taxonomy = pd.read_csv(fp, sep="\t", index_col=0) df_source_taxonomy.index = df_source_taxonomy.index.map(str) + df_source_taxonomy = pd.DataFrame(df_source_taxonomy.to_dict()) # Hack for duplicate entries that will be resolved in MicroEuk_v3.1 + if opts.debug: print(fp, file=sys.stderr) df_source_taxonomy.head().to_csv(sys.stderr, sep="\t") @@ -65,7 +63,7 @@ def main(args=None): # VEBA -> SourceID fp = os.path.join(opts.eukaryotic_database,"target_to_source.dict.pkl.gz") - print("* Reading target to source mapping {}".format(fp), file=sys.stderr) + print("* Reading target to source mapping {} (Note: This one takes a little longer to load...)".format(fp), file=sys.stderr) with gzip.open(fp, "rb") as f: target_to_source = pickle.load(f) #target_to_source = pd.read_csv(fp, sep="\t", index_col=0, dtype=str, usecols=["id_veba", "id_source"], squeeze=True)#.iloc[:,0] @@ -83,32 +81,44 @@ def main(args=None): df_metaeuk.head().to_csv(sys.stderr, sep="\t") print("\n", file=sys.stderr) - orf_to_bitscore = df_metaeuk["bitscore"].map(float) - orf_to_scaffold = df_metaeuk["C_acc"].map(str) - orf_to_mag = orf_to_scaffold.map(lambda id_scaffold: scaffold_to_bin[id_scaffold]) - - orf_to_target = df_metaeuk["T_acc"] - orf_to_source = orf_to_target.map(lambda id_target: target_to_source.get(id_target,np.nan)) - if np.any(pd.isnull(orf_to_source)): + gene_to_bitscore = df_metaeuk["bitscore"].map(float) + gene_to_scaffold = df_metaeuk["C_acc"].map(str) + gene_to_genome = pd.Series([np.nan]*df_metaeuk.shape[0], index=df_metaeuk.index) + gene_to_target = df_metaeuk["T_acc"] + gene_to_source = gene_to_target.map(lambda id_target: target_to_source.get(id_target,np.nan)) + + if opts.scaffolds_to_bins: + # Scaffolds -> Bins + fp = opts.scaffolds_to_bins + print("* Reading scaffolds to bins table {}".format(fp), file=sys.stderr) + scaffold_to_bin = pd.read_csv(fp, sep="\t", index_col=0, header=None).iloc[:,0] + if opts.debug: + print(fp, file=sys.stderr) + scaffold_to_bin.head().to_csv(sys.stderr, sep="\t", header=None) + print("\n", file=sys.stderr) + gene_to_genome = gene_to_scaffold.map(lambda id_scaffold: scaffold_to_bin[id_scaffold]) + + if np.any(pd.isnull(gene_to_source)): warnings.warn("The following gene - target identifiers are not in the database file: {}".format( os.path.join(opts.eukaryotic_database,"target_to_source.dict.pkl.gz"), ), ) - orf_to_target[orf_to_source[orf_to_source.isnull()].index].to_frame().to_csv(sys.stderr, sep="\t", header=None) - orf_to_source = orf_to_source.dropna() + gene_to_target[gene_to_source[gene_to_source.isnull()].index].to_frame().to_csv(sys.stderr, sep="\t", header=None) + gene_to_source = gene_to_source.dropna() # Lineage - orf_to_lineage = OrderedDict() + gene_to_lineage = OrderedDict() missing_lineage = list() - for id_orf, id_source in tqdm(orf_to_source.items(), desc="Retrieving lineage", unit = " ORFs"): + for id_gene, id_source in tqdm(gene_to_source.items(), desc="Retrieving lineage", unit = " genes"): if id_source in df_source_taxonomy.index: lineage = df_source_taxonomy.loc[id_source, ["class", "order", "family", "genus", "species"]] # class order family genus species + lineage = lineage.fillna("") lineage = ";".join(map(lambda items: "".join(items), zip(["c__", "o__", "f__", "g__", "s__"], lineage))) - orf_to_lineage[id_orf] = lineage + gene_to_lineage[id_gene] = lineage else: missing_lineage.append(id_source) - orf_to_lineage = pd.Series(orf_to_lineage) + gene_to_lineage = pd.Series(gene_to_lineage) if len(missing_lineage): warnings.warn("The following source identifiers are not in the database file: {}\n{}`".format( @@ -118,31 +128,47 @@ def main(args=None): ) # Output - # ["id_orf", "id_mag", "bitscore", "lineage"] - df_orf_classifications = pd.concat([ - orf_to_scaffold.to_frame("id_scaffold"), - orf_to_mag.to_frame("id_mag"), - orf_to_target.to_frame("id_target"), - orf_to_source.to_frame("id_source"), - orf_to_lineage.to_frame("lineage"), - orf_to_bitscore.to_frame("bitscore"), - ], - axis=1) - df_orf_classifications.index.name = "id_gene" + df_gene_classifications = pd.DataFrame({ + "id_scaffold":gene_to_scaffold, + "id_genome":gene_to_genome, + "id_target":gene_to_target, + "id_source":gene_to_source, + "lineage":gene_to_lineage, + "bitscore":gene_to_bitscore, + }) + df_gene_classifications.index.name = "id_gene" + + + # df_gene_classifications = pd.concat([ + # gene_to_scaffold.to_frame("id_scaffold"), + # gene_to_genome.to_frame("id_genome"), + # gene_to_target.to_frame("id_target"), + # gene_to_source.to_frame("id_source"), + # gene_to_lineage.to_frame("lineage"), + # gene_to_bitscore.to_frame("bitscore"), + # ], + # axis=1) + # df_gene_classifications.index.name = "id_gene" # Add clusters if provided if opts.clusters: if opts.clusters != "None": # Hack for when called internally - mag_to_cluster = pd.read_csv(opts.clusters, sep="\t", index_col=0, header=None).iloc[:,0] - orf_to_cluster = orf_to_mag.map(lambda id_orf: mag_to_cluster[id_orf]) - df_orf_classifications.insert(loc=2, column="id_cluster", value=orf_to_cluster) + genome_to_cluster = pd.read_csv(opts.clusters, sep="\t", index_col=0, header=None).iloc[:,0] + gene_to_cluster = gene_to_genome.map(lambda id_gene: genome_to_cluster[id_gene]) + df_gene_classifications.insert(loc=2, column="id_cluster", value=gene_to_cluster) # Output if opts.output == "stdout": opts.output = sys.stdout - df_orf_classifications = df_orf_classifications.dropna(how="any", axis=0) - df_orf_classifications.to_csv(opts.output, sep="\t", header=bool(opts.header)) + if opts.remove_genes_with_missing_values: + df_gene_classifications = df_gene_classifications.dropna(how="any", axis=0) + + if not opts.use_original_metaeuk_gene_identifiers: + metaeuk_to_gene = df_metaeuk["gene_id"].to_dict() + df_gene_classifications.index = df_gene_classifications.index.map(lambda x: metaeuk_to_gene[x]) + + df_gene_classifications.to_csv(opts.output, sep="\t", header=bool(opts.header)) diff --git a/src/scripts/compile_prokaryotic_genome_cluster_classification_scores_table.py b/src/scripts/compile_prokaryotic_genome_cluster_classification_scores_table.py index 1e4a031..3ee1147 100755 --- a/src/scripts/compile_prokaryotic_genome_cluster_classification_scores_table.py +++ b/src/scripts/compile_prokaryotic_genome_cluster_classification_scores_table.py @@ -30,7 +30,6 @@ def main(argv=None): parser_io.add_argument("--fill_missing_weight", type=float, help = "Fill missing weight between [0, 100.0]. [Default is to throw error if value is missing]") parser_io.add_argument("--header", action="store_true", help = "Include header") - # Options opts = parser.parse_args() opts.script_directory = script_directory diff --git a/src/scripts/compile_reads_table.py b/src/scripts/compile_reads_table.py index 3b3edd8..8075113 100755 --- a/src/scripts/compile_reads_table.py +++ b/src/scripts/compile_reads_table.py @@ -7,7 +7,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.8.28" +__version__ = "2023.12.18" def parse_basename(query: str, naming_scheme: str): """ @@ -43,6 +43,7 @@ def main(args=None): parser_preprocess_directory = parser.add_argument_group('[Mode 1] Preprocess Directory arguments') parser_preprocess_directory.add_argument("-i","--preprocess_directory", type=str, help = "path/to/preprocess directory (e.g., veba_output/preprocess) [Cannot be used with --fastq_directory]") parser_preprocess_directory.add_argument("-b","--basename", default="cleaned", type=str, help = "File basename to search VEBA preprocess directory [preprocess_directory]/[id_sample]/[output]/[basename]_1/2.fastq.gz [Default: cleaned]") + parser_preprocess_directory.add_argument("-L","--long", action="store_true", help = "Use if reads are ONT or PacBio") parser_fastq_directory = parser.add_argument_group('[Mode 2] Fastq Directory arguments') parser_fastq_directory.add_argument("-f","--fastq_directory", type=str, help = "path/to/fastq_directory [Cannot be used with --preprocess_directory]") @@ -55,6 +56,7 @@ def main(args=None): parser_output.add_argument("-0", "--sample_label", default="sample-id", type=str, help = "Sample ID column label [Reverse: sample-id]") parser_output.add_argument("-1", "--forward_label", default="forward-absolute-filepath", type=str, help = "Forward filepath column label [Default: forward-absolute-filepath]") parser_output.add_argument("-2", "--reverse_label", default="reverse-absolute-filepath", type=str, help = "Reverse filepath column label [Default: reverse-absolute-filepath]") + parser_output.add_argument("-3", "--long_label", default="reads-filepath", type=str, help = "Long reads filepath column label [Default: reads-filepath]") parser_output.add_argument("--header", action="store_true", help = "Write header") parser_output.add_argument("--volume_prefix", type=str, help = "Docker container prefix to volume path") @@ -69,27 +71,41 @@ def main(args=None): output = defaultdict(dict) # Build table from preprocess directory if opts.preprocess_directory: - for fp in glob.glob(os.path.join(opts.preprocess_directory, "*", "output", "{}_1.fastq.gz".format(opts.basename))): - id_sample = fp.split("/")[-3] - output[id_sample][opts.forward_label] = fp - for fp in glob.glob(os.path.join(opts.preprocess_directory, "*", "output", "{}_2.fastq.gz".format(opts.basename))): - id_sample = fp.split("/")[-3] - output[id_sample][opts.reverse_label] = fp - # Build table from fastq directory - if opts.fastq_directory: - for fp in glob.glob(os.path.join(opts.fastq_directory, "*.{}".format(opts.extension))): - basename = fp.split("/")[-1] - id_sample, direction = parse_basename(basename, naming_scheme=opts.naming_scheme) - # id_sample = "_R".join(basename.split("_R")[:-1]) - if direction == "1": + if not opts.long: + for fp in glob.glob(os.path.join(opts.preprocess_directory, "*", "output", "{}_1.fastq.gz".format(opts.basename))): + id_sample = fp.split("/")[-3] output[id_sample][opts.forward_label] = fp - if direction == "2": + for fp in glob.glob(os.path.join(opts.preprocess_directory, "*", "output", "{}_2.fastq.gz".format(opts.basename))): + id_sample = fp.split("/")[-3] output[id_sample][opts.reverse_label] = fp - df_output = pd.DataFrame(output).T.sort_index().loc[:,[opts.forward_label, opts.reverse_label]] + else: + for fp in glob.glob(os.path.join(opts.preprocess_directory, "*", "output", "{}.fastq.gz".format(opts.basename))): + id_sample = fp.split("/")[-3] + output[id_sample][opts.long_label] = fp + + # Build table from fastq directory + if opts.fastq_directory: + if not opts.long: + for fp in glob.glob(os.path.join(opts.fastq_directory, "*.{}".format(opts.extension))): + basename = fp.split("/")[-1] + id_sample, direction = parse_basename(basename, naming_scheme=opts.naming_scheme) + # id_sample = "_R".join(basename.split("_R")[:-1]) + if direction == "1": + output[id_sample][opts.forward_label] = fp + if direction == "2": + output[id_sample][opts.reverse_label] = fp + else: + print("Long reads support with -L is currently only available with --preprocess_directory and not --fastq_directory", file=sys.stderr) + sys.exit(1) + + if not opts.long: + df_output = pd.DataFrame(output).T.sort_index().loc[:,[opts.forward_label, opts.reverse_label]] + else: + df_output = pd.DataFrame(output).T.sort_index().loc[:,[opts.long_label]] df_output.index.name = opts.sample_label # Check missing values - missing_values = df_output.notnull().sum(axis=1)[lambda x: x < 2].index + missing_values = df_output.notnull().sum(axis=1)[lambda x: x < df_output.shape[1]].index assert missing_values.size == 0, "Missing fastq for the following samples: {}".format(missing_values.index) # Absolute paths @@ -97,10 +113,14 @@ def main(args=None): df_output = df_output.applymap(lambda fp: os.path.abspath(fp)) else: if opts.header: - if "absolute" in opts.forward_label.lower(): - print("You've selected --relative and may want to either not use a header or remove 'absolute' from the --forward_label: {}".format(opts.forward_label), file=sys.stderr) - if "absolute" in opts.reverse_label.lower(): - print("You've selected --relative and may want to either not use a header or remove 'absolute' from the --reverse_label: {}".format(opts.reverse_label), file=sys.stderr) + if not opts.long: + if "absolute" in opts.forward_label.lower(): + print("You've selected --relative and may want to either not use a header or remove 'absolute' from the --forward_label: {}".format(opts.forward_label), file=sys.stderr) + if "absolute" in opts.reverse_label.lower(): + print("You've selected --relative and may want to either not use a header or remove 'absolute' from the --reverse_label: {}".format(opts.reverse_label), file=sys.stderr) + else: + if "absolute" in opts.long_label.lower(): + print("You've selected --relative and may want to either not use a header or remove 'absolute' from the --long_label: {}".format(opts.long_label), file=sys.stderr) # Docker volume prefix if opts.volume_prefix: diff --git a/src/scripts/concatenate_assembly.py b/src/scripts/concatenate_assembly.py new file mode 100755 index 0000000..bcec4ff --- /dev/null +++ b/src/scripts/concatenate_assembly.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +import sys, os, argparse, gzip +from Bio.SeqIO.FastaIO import SimpleFastaParser +from tqdm import tqdm + +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.12.18" + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o )".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + + # Pipeline + parser.add_argument("-i","--input", default="stdin", type=str, help = "Input fasta file") + parser.add_argument("-o","--output", default="stdout", type=str, help = "Output fasta file") + parser.add_argument("-n", "--name", type=str, required=True, help = "Name to use for pseudo-scaffold") + parser.add_argument("-N", "--pad", type=int, default=100, help = "Number of N to use for joining contigs") + parser.add_argument("-d", "--description", type=str, help = "Description to use [Default: Input filepath]") + parser.add_argument("-m","--minimum_sequence_length", default=1, type=int, help = "Minimum sequence length accepted [Default: 1]") + parser.add_argument("-w","--wrap", default=1000, type=int, help = "Wrap fasta. Use 0 for no wrapping [Default: 1000]") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + assert opts.minimum_sequence_length > 0 + assert opts.pad >= 0 + + # Input + f_in = None + if opts.input == "stdin": + f_in = sys.stdin + else: + if opts.input.endswith(".gz"): + f_in = gzip.open(opts.input, "rt") + else: + f_in = open(opts.input, "r") + assert f_in is not None + + # Output + f_out = None + if opts.output == "stdout": + f_out = sys.stdout + else: + if opts.output.endswith(".gz"): + f_out = gzip.open(opts.output, "wt") + else: + f_out = open(opts.output, "w") + assert f_out is not None + + # Concatenated assembly + + if not opts.description: + opts.description = "assembly_filepath: {}".format(opts.input) + else: + if opts.description == "NONE": + opts.description = "" + pseudoscaffold_header = "{} {}".format(opts.name, opts.description) + + print(">{}".format(pseudoscaffold_header), file=f_out) + sequences = list() + for header, seq in tqdm(SimpleFastaParser(f_in), "Reading fasta input"): + if len(seq) >= opts.minimum_sequence_length: + sequences.append(seq) + number_of_sequences = len(sequences) + sequences = ("N"*opts.pad).join(sequences) + + # Open output file + if opts.wrap > 0: + for i in range(0, len(sequences), opts.wrap): + wrapped_sequence = sequences[i:i+opts.wrap] + # Write header and wrapped sequence + print(wrapped_sequence, file=f_out) + else: + print(sequences, file=f_out) + + + # Close + if f_in != sys.stdin: + f_in.close() + if f_out != sys.stdout: + f_out.close() + +if __name__ == "__main__": + main() + + + diff --git a/src/scripts/concatenate_fasta.py b/src/scripts/concatenate_fasta.py index 0977942..38d12ae 100755 --- a/src/scripts/concatenate_fasta.py +++ b/src/scripts/concatenate_fasta.py @@ -1,6 +1,6 @@ #!/usr/bin/env python from __future__ import print_function, division -import sys, os, argparse +import sys, os, argparse, hashlib import pandas as pd from Bio.SeqIO.FastaIO import SimpleFastaParser @@ -12,45 +12,7 @@ pd.options.display.max_colwidth = 100 # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2022.02.17" - - - -def fasta_to_saf(path, compression="infer"): - """ - # GeneID Chr Start End Strand - # http://bioinf.wehi.edu.au/featureCounts/ - - # Useful: - import re - record_id = "lcl|NC_018632.1_cds_WP_039228897.1_1 [gene=dnaA] [locus_tag=MASE_RS00005] [protein=chromosomal replication initiator protein DnaA] [protein_id=WP_039228897.1] [location=410..2065] [gbkey=CDS]" - re.search("\[locus_tag=(\w+)\]", record_id).group(1) - # 'MASE_RS00005' - - """ - - - saf_data = list() - - if path == "stdin": - f = sys.stdin - else: - f = get_file_object(path, mode="read", compression=compression, verbose=False) - - for id_record, seq in pv(SimpleFastaParser(f), "Reading sequences [{}]".format(path)): - id_record = id_record.split(" ")[0] - fields = [ - id_record, - id_record, - 1, - len(seq), - "+", - ] - saf_data.append(fields) - if f is not sys.stdin: - f.close() - return pd.DataFrame(saf_data, columns=["GeneID", "Chr", "Start", "End", "Strand"]) - +__version__ = "2023.12.13" def main(args=None): # Path info @@ -120,7 +82,15 @@ def main(args=None): safe_mode=False, verbose=False, ) + saf_filepath = os.path.join(opts.output_directory, "{}.saf".format(id_sample)) + + f_duplicates = get_file_object( + path=os.path.join(opts.output_directory, "{}.duplicates_removed.list".format(id_sample)), + mode="write", + safe_mode=False, + verbose=False, + ) else: os.makedirs(os.path.join(opts.output_directory, id_sample), exist_ok=True) @@ -130,29 +100,43 @@ def main(args=None): safe_mode=False, verbose=False, ) + saf_filepath = os.path.join(opts.output_directory, id_sample, "{}.saf".format(opts.basename)) + f_duplicates = get_file_object( + path=os.path.join(opts.output_directory, id_sample, "{}.duplicates_removed.list".format(opts.basename)), + mode="write", + safe_mode=False, + verbose=False, + ) # Read input fasta, filter out short sequences, and write to concatenated file + sequence_hashes = set() saf_data = list() for fp in pv(filepaths, description=id_sample, unit= " files"): f_query = get_file_object(fp, mode="read", verbose=False) for id, seq in SimpleFastaParser(f_query): if len(seq) >= opts.minimum_contig_length: - print(">{}\n{}".format(id, seq), file=f_out) + id_hash = hashlib.md5(seq.upper().encode()).hexdigest() id_record = id.split(" ")[0] - fields = [ - id_record, - id_record, - 1, - len(seq), - "+", - ] - saf_data.append(fields) + if id_hash not in sequence_hashes: + print(">{}\n{}".format(id, seq), file=f_out) + fields = [ + id_record, + id_record, + 1, + len(seq), + "+", + ] + saf_data.append(fields) + sequence_hashes.add(id_hash) + else: + print(id_record, file=f_duplicates) f_query.close() f_out.close() + f_duplicates.close() df_saf = pd.DataFrame(saf_data, columns=["GeneID", "Chr", "Start", "End", "Strand"]) df_saf.to_csv(saf_filepath, sep="\t", index=None) @@ -173,26 +157,39 @@ def main(args=None): saf_filepath = os.path.join(opts.output_directory, "{}.saf".format(opts.basename)) + f_duplicates = get_file_object( + path=os.path.join(opts.output_directory, "{}.duplicates_removed.list".format(opts.basename)), + mode="write", + safe_mode=False, + verbose=False, + ) + # Read input fasta, filter out short sequences, and write to concatenated file + sequence_hashes = set() saf_data = list() for fp in pv(filepaths, unit= " files"): f_query = get_file_object(fp, mode="read", verbose=False) for id, seq in SimpleFastaParser(f_query): if len(seq) >= opts.minimum_contig_length: - print(">{}\n{}".format(id, seq), file=f_out) + id_hash = hashlib.md5(seq.upper().encode()).hexdigest() id_record = id.split(" ")[0] - fields = [ - id_record, - id_record, - 1, - len(seq), - "+", - ] - saf_data.append(fields) - + if id_hash not in sequence_hashes: + print(">{}\n{}".format(id, seq), file=f_out) + fields = [ + id_record, + id_record, + 1, + len(seq), + "+", + ] + saf_data.append(fields) + else: + print(id_record, file=f_duplicates) f_query.close() f_out.close() + f_duplicates.close() + df_saf = pd.DataFrame(saf_data, columns=["GeneID", "Chr", "Start", "End", "Strand"]) df_saf.to_csv(saf_filepath, sep="\t", index=None) diff --git a/src/scripts/consensus_genome_classification_ranked.py b/src/scripts/consensus_genome_classification_ranked.py new file mode 100755 index 0000000..2c190fa --- /dev/null +++ b/src/scripts/consensus_genome_classification_ranked.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse +from collections import OrderedDict, defaultdict +import pandas as pd +import numpy as np + + +pd.options.display.max_colwidth = 100 +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.3" + +# RANK_TO_PREFIX="superkingdom:d__,phylum:p__,class:c__,order:o__,family:f__,genus:g__,species:s__" + +RANK_PREFIXES="d__,p__,c__,o__,f__,g__,s__" + +# Fill empty taxonomic levels for consensus classification +def fill_lower_taxonomy_levels( + classifications:pd.Series, + rank_prefixes:list, + delimiter:str=";", + ): + + rank_prefixes = list(rank_prefixes) + number_of_taxonomic_levels = len(rank_prefixes) + classifications_ = dict() + for id_genome, classification in pd.Series(classifications).items(): + taxonomy = classification.split(delimiter) + classifications_[id_genome] = delimiter.join(taxonomy + rank_prefixes[len(taxonomy):]) + return pd.Series(classifications_)[classifications.index] + +# Get consensus classification +def get_consensus_classification( + classification:pd.Series, + classification_weights:pd.Series, + genome_to_genomecluster:pd.Series, + rank_prefixes:list, + number_of_taxonomic_levels="infer", + delimiter=";", + leniency:float=1.382, + ): + # Assertions + assert np.all(classification.notnull()) + assert np.all(classification_weights.notnull()) + assert np.all(genome_to_genomecluster.notnull()) + + # Set and index overlap + a = set(classification.index) + b = set(classification_weights.index) + c = set(genome_to_genomecluster.index) + assert a == b, "`classification` and `classification_weights` must have the same keys in the index" + assert a <= c, "`classification` and `classification_weights` must be a subset (or equal) to the keys in `genome_to_genomecluster` index" + index_genomes = pd.Index(sorted(a & b & c )) + classification = classification[index_genomes] + classification_weights = classification_weights[index_genomes] + genome_to_genomecluster = genome_to_genomecluster[index_genomes] + + # Taxonomic levels + taxonomic_levels = classification.map(lambda x: x.count(delimiter)).unique() + if len(taxonomic_levels): + assert len(taxonomic_levels) == 1, "Taxonomic levels in `classification` should all have the same number of delimiters" #! Might need to change this to allow for missing taxonomic levels + else: + number_of_taxonomic_levels = 1 + + if number_of_taxonomic_levels == "infer": + number_of_taxonomic_levels = taxonomic_levels[0] + 1 + + # Scaling factors + scaling_factors = np.arange(1, number_of_taxonomic_levels + 1) # d__Bacteria;p__Actinobacteriota;c__Actinomycetia;o__Actinomycetales;f__Dermabacteraceae;g__Brachybacterium + scaling_factors = np.power(scaling_factors, leniency) + + # Get container for scores [SLC -> Taxonomy -> Score] + # + # For example the following MAG: + # CLASSIFICATION=d__Bacteria;p__Actinobacteriota;c__Actinomycetia;o__Mycobacteriales;f__Mycobacteriaceae;g__Corynebacterium;s__Corynebacterium aurimucosum_E + # MSA_PERCENT=80.0 + # + # Would be stored and appended for it's corresponding SLC: + # d__Bacteria += 80.0 + # d__Bacteria;p__Actinobacteriota += 80.0 + # d__Bacteria;p__Actinobacteriota;c__Actinomycetia += 80.0 + # d__Bacteria;p__Actinobacteriota;c__Actinomycetia;o__Mycobacteriales += 80.0 + # d__Bacteria;p__Actinobacteriota;c__Actinomycetia;o__Mycobacteriales;f__Mycobacteriaceae += 80.0 + # d__Bacteria;p__Actinobacteriota;c__Actinomycetia;o__Mycobacteriales;f__Mycobacteriaceae;g__Corynebacterium += 80.0 + # d__Bacteria;p__Actinobacteriota;c__Actinomycetia;o__Mycobacteriales;f__Mycobacteriaceae;g__Corynebacterium;s__Corynebacterium aurimucosum_E += 80.0 + genomecluster_taxa_scores = defaultdict(lambda: defaultdict(float)) + + # Iterate through MAG, classification, and score + df = pd.concat([genome_to_genomecluster.to_frame("id"), classification.to_frame("classification"), classification_weights.to_frame("weight")], axis=1) + genomecluster_to_genomes = defaultdict(list) + for id_genome, (id_genome_cluster, classification, w) in df.iterrows(): + genomecluster_to_genomes[id_genome_cluster].append(id_genome) + # Split the taxonomy classification by levels + levels = classification.split(delimiter) + # Remove the empty taxonomy levels (e.g., g__Corynebacterium;s__ --> g__Corynebacterium) + # levels = list(filter(lambda x:x not in rank_prefixes, levels)) + number_of_query_levels = len(levels) + # Iterate through each level, scale score by the leniency weights, and add to running sum + for i in range(1, number_of_query_levels + 1): + taxon_at_level = levels[i-1] + taxon_level_is_missing = taxon_at_level in rank_prefixes + if taxon_level_is_missing: + weighted_score = 0.0 + print("`{}` is missing taxonomic level `{}`".format(id_genome, taxon_at_level), file=sys.stderr) + + else: + weighted_score = float(w) * scaling_factors[i-1] + genomecluster_taxa_scores[id_genome_cluster][tuple(levels[:i])] += weighted_score + genomecluster_to_genomes = pd.Series(genomecluster_to_genomes) + + # Build datafarme + genomecluster_taxa_scores = pd.Series(genomecluster_taxa_scores) + df_consensus_classification = pd.DataFrame(genomecluster_taxa_scores.map(lambda taxa_scores: sorted(taxa_scores.items(), key=lambda x:(x[1], len(x[0])), reverse=True)[0]).to_dict(), index=["consensus_classification", "score"]).T + df_consensus_classification["consensus_classification"] = df_consensus_classification["consensus_classification"].map(";".join) + df_consensus_classification["number_of_unique_classifications"] = df["classification"].groupby(genome_to_genomecluster).apply(lambda x: len(set(x))) + df_consensus_classification["number_of_components"] = genomecluster_to_genomes.map(len) #df["classification"].groupby(genome_to_genomecluster).apply(len) + df_consensus_classification["components"] = genomecluster_to_genomes + df_consensus_classification["classifications"] = df["classification"].groupby(genome_to_genomecluster).apply(lambda x: list(x)) + df_consensus_classification["weights"] = df["weight"].groupby(genome_to_genomecluster).apply(lambda x: list(x)) + df_consensus_classification.index.name = "id" + + # Homogeneity + slc_taxa_homogeneity = defaultdict(lambda: defaultdict(float)) + for id_genome_cluster, (classifications, weights) in df_consensus_classification[["classifications", "weights"]].iterrows(): + for (c, w) in zip(classifications, weights): + slc_taxa_homogeneity[id_genome_cluster][c] += w + df_consensus_classification["homogeneity"] = pd.DataFrame(slc_taxa_homogeneity).T.apply(lambda x: np.nanmax(x)/np.nansum(x), axis=1) + + fields = [ + "consensus_classification", + "homogeneity", + "number_of_unique_classifications", + "number_of_components", + "components", + "classifications", + "weights", + "score", + ] + return df_consensus_classification.loc[:,fields] + + + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o ".format(__program__) + epilog = "Copyright 2022 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser.add_argument("-i","--input", default="stdin", type=str, help = "path/to/genome_to_classification.tsv [id_genome][id_genome_cluster][classification][weight]; No header. [Default: stdin]") + parser.add_argument("-o","--output", type=str, default="stdout", help = "Output table with consensus classification [Default: stdout]") + parser.add_argument("-l","--leniency", default=1.382, type=float, help = "Leniency parameter. Lower value means more conservative weighting. A value of 1 indiciates no weight bias. A value greater than 1 puts higher weight on higher level taxonomic assignments. A value less than 1 puts lower weights on higher level taxonomic assignments. [Default: 1.382]") + parser.add_argument("-r", "--rank_prefixes", type=str, default=RANK_PREFIXES, help = "Rank prefixes separated by , delimiter'\n[Default: {}]".format(RANK_PREFIXES)) + parser.add_argument("-d", "--delimiter", type=str, default=";", help = "Taxonomic delimiter [Default: ; ]") + parser.add_argument("-s", "--simple", action="store_true", help = "Simple classification that does not use lineage information from --rank_prefixes") + # parser.add_argument("--assert_resolved_taxonomy", action="store_true", help = "Do not allow missing taxonomic levels. (e.g., d__Eukaryota;p__;c__Pelagophyceae;o__Pelagomonadales;f__;g__Aureococcus;s__Aureococcus anophagefferens is missing phylum)") + parser.add_argument("--remove_missing_classifications", action="store_true", help = "Remove all classifications and weights that are null. For viruses this could cause an error if this isn't selected.") + parser.add_argument("-u", "--unclassified_label", default="Unclassified", type=str, help = "Unclassified label [Default: Unclassified]") + parser.add_argument("-w", "--unclassified_weight", default=100.0,type=float, help = "Unclassified label weight [Default: 100.0]") + + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + # I/O + if opts.input == "stdin": + opts.input = sys.stdin + + if opts.output == "stdout": + opts.output = sys.stdout + + # Leniency + assert opts.leniency > 0, "--leniency must be > 0" + # Format rank to lineage + opts.rank_prefixes = opts.rank_prefixes.strip().split(",") + + # Classifications + df_input = pd.read_csv(opts.input, sep="\t", index_col=0, header=None) + genome_to_genomecluster = df_input.iloc[:,0] + genome_to_classification = df_input.iloc[:,1].reindex(genome_to_genomecluster.index) + genome_to_weights = df_input.iloc[:,2].reindex(genome_to_genomecluster.index) + if opts.remove_missing_classifications: + genome_to_weights = genome_to_weights.dropna() + genome_to_classification = genome_to_classification[genome_to_weights.index] + else: + mask = genome_to_weights.isnull() + genome_to_classification[mask] = ";".join(map(lambda x: f"{x}__{opts.unclassified_label}", opts.rank_prefixes)) + genome_to_weights[mask] = opts.unclassified_weight + + + # Consensus classification + df_consensus_classification = get_consensus_classification( + classification=genome_to_classification, + classification_weights=genome_to_weights, + genome_to_genomecluster=genome_to_genomecluster, + rank_prefixes=opts.rank_prefixes, + number_of_taxonomic_levels="infer", + delimiter=opts.delimiter, + leniency=opts.leniency, + ) + + if not opts.simple: + # Fill empty taxonomy levels + df_consensus_classification["consensus_classification"] = fill_lower_taxonomy_levels( + classifications=df_consensus_classification["consensus_classification"], + rank_prefixes=opts.rank_prefixes, + delimiter=opts.delimiter, + ) + + df_consensus_classification.to_csv(opts.output, sep="\t") + +if __name__ == "__main__": + main() diff --git a/src/scripts/consensus_genome_classification.py b/src/scripts/deprecated/consensus_genome_classification.py similarity index 100% rename from src/scripts/consensus_genome_classification.py rename to src/scripts/deprecated/consensus_genome_classification.py diff --git a/src/scripts/mmseqs2_wrapper.py b/src/scripts/deprecated/mmseqs2_wrapper.py similarity index 100% rename from src/scripts/mmseqs2_wrapper.py rename to src/scripts/deprecated/mmseqs2_wrapper.py diff --git a/src/scripts/devel/compile_phylogenomic_functional_categories.py b/src/scripts/devel/compile_phylogenomic_functional_categories.py new file mode 100755 index 0000000..10f45f8 --- /dev/null +++ b/src/scripts/devel/compile_phylogenomic_functional_categories.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +from __future__ import print_function, division +import sys, os, argparse, glob, pickle +from collections import defaultdict +# import numpy as np +import pandas as pd +from tqdm import tqdm +import ensemble_networkx as enx + +pd.options.display.max_colwidth = 100 +# from tqdm import tqdm +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.10.23" + + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -l genome -o ".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + # Pipeline + parser.add_argument("-i","--annotation_results", type=str, default = "stdin", help = "path/to/annotation.tsv from annotate.py [Default: stdin]") + parser.add_argument("-X","--counts", type=str, required = True, help = "path/to/X_orfs.tsv[.gz] from mapping.py at the ORF/gene/protein level. Rows=Samples, Columns=Genes") + parser.add_argument("-g","--genes", type=str, help = "path/to/genes.ffn[.gz] fasta used for scaling-factors") + parser.add_argument("-o","--output_directory", type=str, default="phylogenomic_functional_categories", help = "path/to/output_directory [Default: phylogenomic_functional_categories]") + parser.add_argument("-l","--level", type=str, default="genome_cluster", help = "level {genome, genome_cluster} [Default: genome_cluster]") + parser.add_argument("--minimum_count", type=float, default=1.0, help = "Minimum count to include gene [Default: 1 ]") + parser.add_argument("--veba_database", type=str, help = "VEBA Database [Default: $VEBA_DATABASE environment variable]") + + # parser.add_argument("-p", "--include_protein_identifiers", action="store_true", help = "Write protein identifiers") + # parser.add_argument("--header", action="store_true", help = "Write header") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + assert opts.level in {"genome", "genome_cluster"}, "--level must be either {genome, genome_cluster}" + + if opts.level == "genome": + level_field = ("Identifiers", "id_genome") + if opts.level == "genome_cluster": + level_field = ("Identifiers", "id_genome_cluster") + + if not opts.veba_database: + opts.veba_database = os.environ["VEBA_DATABASE"] + + os.makedirs(opts.output_directory, exist_ok=True) + # os.makedirs(os.path.join(opts.output_directory, opts.level), exist_ok=True) + + # Read annotations + if opts.annotation_results == "stdin": + opts.annotation_results = sys.stdin + df_annotations = pd.read_csv(opts.annotation_results, sep="\t", index_col=0, header=[0,1]) + protein_to_organism = df_annotations[level_field] + + # KEGG Database + delimiters = [",","_","-","+"] + + # Load MicrobeAnnotator KEGG dictionaries + module_to_kos__unprocessed = defaultdict(set) + for fp in glob.glob(os.path.join(opts.veba_database, , "*.pkl")): + with open(fp, "rb") as f: + d = pickle.load(f) + + for id_module, v1 in d.items(): + if isinstance(v1, list): + try: + module_to_kos__unprocessed[id_module].update(v1) + except TypeError: + for v2 in v1: + module_to_kos__unprocessed[id_module].update(v2) + else: + for k2, v2 in v1.items(): + if isinstance(v2, list): + try: + module_to_kos__unprocessed[id_module].update(v2) + except TypeError: + for v3 in v2: + module_to_kos__unprocessed[id_module].update(v3) + + # Flatten the KEGG orthologs + module_to_kos = dict() + for id_module, kos_unprocessed in module_to_kos__unprocessed.items(): + kos_processed = set() + for id_ko in kos: + composite=False + for sep in delimiters: + if sep in id_ko: + id_ko = id_ko.replace(sep,";") + composite = True + if composite: + kos_composite = set(map(str.strip, filter(bool, id_ko.split(";")))) + kos_processed.update(kos_composite) + else: + kos_processed.add(id_ko) + module_to_kos[id_module] = kos_processed + + # Read counts + X_counts = pd.read_csv(opts.counts, sep="\t", index_col=0) + + # Organisms + organisms = df_annotations[level_field].unique() + + # Organizing KOs + organism_to_kos = defaultdict(set) + protein_to_kos = dict() + kos_global = list() + for id_protein, (id_organism, ko_ids) in tqdm(df_annotations.loc[:,[level_field, ("KOFAM", "ids")]].iterrows(), "Compiling KO identifiers", total=df_annotations.shape[0]): + ko_ids = eval(ko_ids) + if len(ko_ids): + ko_ids = set(ko_ids) + protein_to_kos[id_protein] = ko_ids + organism_to_kos[id_organism].update(ko_ids) + for id_ko in ko_ids: + kos_global.append([id_protein, id_organism, id_ko]) + df_kos_global = pd.DataFrame(kos_global, columns=["id_protein", level_field[1], "id_kegg-ortholog"]) + del kos_global + df_kos_global.to_csv(os.path.join(opts.output_directory, "kos.{}s.tsv".format(opts.level)), sep="\t", index=False) + + # Sample -> Organisms -> KOs + sample_to_organism_to_kos = defaultdict(lambda: defaultdict(set)) + for id_sample, row in X_counts.iterrows(): + for id_protein, count in tqdm(row.items(), total=X_counts.shape[1]): + if id_protein in protein_to_kos: + if count >= opts.minimum_count: + id_organism = protein_to_organism[id_protein] + kos = protein_to_kos[id_protein] + sample_to_organism_to_kos[id_sample][id_organism].update(kos) + + + + + + + + + +if __name__ == "__main__": + main() diff --git a/src/scripts/devel/representative_genome_from_networkx_graph.py b/src/scripts/devel/representative_genome_from_networkx_graph.py new file mode 100755 index 0000000..4a82f64 --- /dev/null +++ b/src/scripts/devel/representative_genome_from_networkx_graph.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +import sys, os, argparse, gzip +from Bio.SeqIO.FastaIO import SimpleFastaParser +from tqdm import tqdm + +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.10" + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o )".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + + # Pipeline + parser.add_argument("-c","--genome_to_cluster", type=str, help = "Input fasta file") + parser.add_argument("-g","--graph", type=str, help = "Input fasta file") + parser.add_argument("-o","--output", default="stdout", type=str, help = "Output fasta file") + parser.add_argument("-m","--maximum_weight", default=100, type=str, help = "Output fasta file") + parser.add_argument("--genome_statistics", type=str, help = "Output fasta file") + parser.add_argument("--sort_by", type=str, help = "Output fasta file") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + + + +G = nx.path_graph(4) # or DiGraph, MultiGraph, MultiDiGraph, etc +H = G.subgraph([0, 1, 2]) +list(H.edges) +[(0, 1), (1, 2)] + + + + + +if __name__ == "__main__": + main() + + + diff --git a/src/scripts/edgelist_to_clusters.py b/src/scripts/edgelist_to_clusters.py index 061b60e..30650b8 100755 --- a/src/scripts/edgelist_to_clusters.py +++ b/src/scripts/edgelist_to_clusters.py @@ -8,7 +8,7 @@ from Bio.SeqIO.FastaIO import SimpleFastaParser __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.4.17" +__version__ = "2023.12.11" def main(args=None): # Path info @@ -26,7 +26,7 @@ def main(args=None): parser.add_argument("-i","--input", type=str, default="stdin", help = "path/to/edgelist.tsv, No header. [id_1][id_2] or [id_1][id_2][weight] [Default: stdin]") # parser.add_argument("-o","--output", type=str, default="stdout", help = "path/to/clusters.tsv [Default: stdout]") - parser.add_argument("-t","--threshold", type=float, default=0.5, help = "Minimum weight threshold. [Default: 0.5]") + parser.add_argument("-t","--threshold", type=float, default=0.0, help = "Minimum weight threshold. [Default: 0.0]") parser.add_argument("-n", "--no_singletons", action="store_true", help = "Don't include self-interactions. Self-interactions will ensure unclustered genomes make it into the output") parser.add_argument("-b", "--basename", action="store_true", help = "Removes filepath prefix and extension. Support for gzipped filepaths.") parser.add_argument("--identifiers", type=str, help = "Identifiers to include. If missing identifiers and singletons are allowed, then they will be included as singleton clusters with weight of np.inf") @@ -53,6 +53,7 @@ def main(args=None): opts.script_directory = script_directory opts.script_filename = script_filename + # Input if opts.input == "stdin": opts.input = sys.stdin @@ -62,7 +63,11 @@ def main(args=None): opts.output = sys.stdout # Edge list - df_edgelist = pd.read_csv(opts.input, sep="\t", header=None) + try: + df_edgelist = pd.read_csv(opts.input, sep="\t", header=None) + except pd.errors.EmptyDataError: + df_edgelist = pd.DataFrame(columns=["query", "reference"]) + assert df_edgelist.shape[1] in {2,3}, "Must have 2 or 3 columns. {} provided.".format(df_edgelist.shape[1]) if opts.basename: def get_basename(x): @@ -72,9 +77,13 @@ def get_basename(x): return ".".join(fn.split(".")[:-1]) df_edgelist.iloc[:,:2] = df_edgelist.iloc[:,:2].applymap(get_basename) - edgelist = df_edgelist.iloc[:,:2].values.tolist() - - identifiers = set.union(*map(set, edgelist)) + # Identifiers from edgelist + if not df_edgelist.empty: + edgelist = df_edgelist.iloc[:,:2].values.tolist() + identifiers = set.union(*map(set, edgelist)) + else: + edgelist = list() + identifiers = set() all_identifiers = identifiers if opts.identifiers: @@ -84,6 +93,7 @@ def get_basename(x): id = line.strip() all_identifiers.add(id) + # Read in fasta if opts.fasta: id_to_sequence = dict() if opts.fasta.endswith(".gz"): diff --git a/src/scripts/eukaryotic_gene_modeling_wrapper.py b/src/scripts/eukaryotic_gene_modeling_wrapper.py index 83591e7..cd15774 100755 --- a/src/scripts/eukaryotic_gene_modeling_wrapper.py +++ b/src/scripts/eukaryotic_gene_modeling_wrapper.py @@ -13,7 +13,7 @@ # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.16" +__version__ = "2023.11.13" # Tiara def get_tiara_cmd(input_filepaths, output_filepaths, output_directory, directories, opts): @@ -131,6 +131,7 @@ def get_metaeuk_cmd(input_filepaths, output_filepaths, output_directory, directo "--threads {}".format(opts.n_jobs), "-s {}".format(opts.metaeuk_sensitivity), "-e {}".format(opts.metaeuk_evalue), + "--split-memory-limit {}".format(opts.metaeuk_split_memory_limit), opts.metaeuk_options, os.path.join(directories["tmp"], "tmp.fasta"), opts.metaeuk_database, # db @@ -1380,6 +1381,7 @@ def main(args=None): parser_metaeuk = parser.add_argument_group('MetaEuk arguments') parser_metaeuk.add_argument("--metaeuk_sensitivity", type=float, default=4.0, help="MetaEuk | Sensitivity: 1.0 faster; 4.0 fast; 7.5 sensitive [Default: 4.0]") parser_metaeuk.add_argument("--metaeuk_evalue", type=float, default=0.01, help="MetaEuk | List matches below this E-value (range 0.0-inf) [Default: 0.01]") + parser_metaeuk.add_argument("--metaeuk_split_memory_limit", type=str, default="36G", help="MetaEuk | Set max memory per split. E.g. 800B, 5K, 10M, 1G. Use 0 to use all available system memory. (Default value is experimental) [Default: 36G]") parser_metaeuk.add_argument("--metaeuk_options", type=str, default="", help="MetaEuk | More options (e.g. --arg 1 ) [Default: ''] https://github.com/soedinglab/metaeuk") # Pyrodigal diff --git a/src/scripts/filter_spades_assembly.py b/src/scripts/filter_spades_assembly.py new file mode 100755 index 0000000..08351a0 --- /dev/null +++ b/src/scripts/filter_spades_assembly.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +import sys, os, argparse, gzip +from Bio.SeqIO.FastaIO import SimpleFastaParser +from tqdm import tqdm + +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.12.5" + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o )".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + + # Pipeline + parser.add_argument("-i","--input", default="stdin", type=str, help = "Input fasta file") + parser.add_argument("-o","--output", default="stdout", type=str, help = "Output fasta file") + parser.add_argument("-r","--retain_description", action="store_true", help = "Retain description") + parser.add_argument("-c","--minimum_coverage", default=0, type=int, help = "Minimum coverage accepted [Default: 0.0]") + parser.add_argument("-m","--minimum_sequence_length", default=1, type=int, help = "Minimum sequence length accepted [Default: 1]") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + assert opts.minimum_sequence_length > 0 + + # Input + f_in = None + if opts.input == "stdin": + f_in = sys.stdin + else: + if opts.input.endswith(".gz"): + f_in = gzip.open(opts.input, "rt") + else: + f_in = open(opts.input, "r") + assert f_in is not None + + # Output + f_out = None + if opts.output == "stdout": + f_out = sys.stdout + else: + if opts.output.endswith(".gz"): + f_out = gzip.open(opts.output, "wt") + else: + f_out = open(opts.output, "w") + assert f_out is not None + + if opts.retain_description: + for header, seq in tqdm(SimpleFastaParser(f_in), "Reading fasta input"): + id = header.split(" ")[0].strip() + fields = id.split("_") + try: + length_index = fields.index("length") + coverage_index = fields.index("cov") + except ValueError: + raise "Your fastq identifiers do not look like they are from SPAdes: {}".format(id) + sys.exit(1) + assert ">" not in seq, "`{}` has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(header) + coverage = float(fields[coverage_index + 1]) + length = int(fields[length_index + 1]) + if all([coverage >= opts.minimum_coverage, length >= opts.minimum_sequence_length]): + print(">{}\n{}".format(header,seq), file=f_out) + else: + for header, seq in tqdm(SimpleFastaParser(f_in), "Reading fasta input"): + id = header.split(" ")[0].strip() + fields = id.split("_") + try: + length_index = fields.index("length") + coverage_index = fields.index("cov") + except ValueError: + raise "Your fastq identifiers do not look like they are from SPAdes: {}".format(id) + sys.exit(1) + assert ">" not in seq, "`{}` has a '>' character in the sequence which will cause an error. This can arise from concatenating fasta files where a record is missing a final linebreak".format(header) + coverage = float(fields[coverage_index + 1]) + length = int(fields[length_index + 1]) + if all([coverage >= opts.minimum_coverage, length >= opts.minimum_sequence_length]): + print(">{}\n{}".format(id,seq), file=f_out) + + # Close + if f_in != sys.stdin: + f_in.close() + if f_out != sys.stdout: + f_out.close() + +if __name__ == "__main__": + main() + + + diff --git a/src/scripts/global_clustering.py b/src/scripts/global_clustering.py index 4783794..8e8b6f3 100755 --- a/src/scripts/global_clustering.py +++ b/src/scripts/global_clustering.py @@ -15,7 +15,7 @@ # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.24" +__version__ = "2023.12.8" def get_basename(x): _, fn = os.path.split(x) @@ -50,13 +50,15 @@ def add_executables_to_environment(opts): """ accessory_scripts = { "edgelist_to_clusters.py", - "mmseqs2_wrapper.py", + "clustering_wrapper.py", # "table_to_fasta.py", } required_executables={ + "skani", "fastANI", "mmseqs", + "diamond", } @@ -97,7 +99,18 @@ def add_executables_to_environment(opts): # Configure parameters def configure_parameters(opts, directories): - assert_acceptable_arguments(opts.algorithm, {"easy-cluster", "easy-linclust"}) + assert_acceptable_arguments(opts.protein_clustering_algorithm, {"easy-cluster", "easy-linclust", "mmseqs-cluster", "mmseqs-linclust", "diamond-cluster", "diamond-linclust"}) + if opts.protein_clustering_algorithm in {"easy-cluster", "easy-linclust"}: + d = {"easy-cluster":"mmseqs-cluster", "easy-linclust":"mmseqs-linclust"} + warnings.warn("\n\nPlease use `{}` instead of `{}` for MMSEQS2 clustering.".format(d[opts.protein_clustering_algorithm], opts.protein_clustering_algorithm)) + opts.protein_clustering_algorithm = d[opts.protein_clustering_algorithm] + + if opts.skani_nonviral_preset.lower() == "none": + opts.skani_nonviral_preset = None + + if opts.skani_viral_preset.lower() == "none": + opts.skani_viral_preset = None + assert 0 < opts.minimum_core_prevalence <= 1.0, "--minimum_core_prevalence must be a float between (0.0,1.0])" # Set environment variables add_executables_to_environment(opts=opts) @@ -119,10 +132,10 @@ def main(args=None): parser_io = parser.add_argument_group('Required I/O arguments') parser_io.add_argument("-i", "--genomes_table", type=str, default="stdin", help = "path/to/genomes_table.tsv, Format: Must include the following columns (No header) [organism_type][id_sample][id_mag][genome][proteins][cds] but can include additional columns to the right (e.g., [gene_models]). Suggested input is from `compile_genomes_table.py` script. [Default: stdin]") parser_io.add_argument("-o","--output_directory", type=str, default="global_clustering_output", help = "path/to/project_directory [Default: global_clustering_output]") - parser_io.add_argument("-e", "--no_singletons", action="store_true", help="Exclude singletons") #isPSLC-1_SSPC-3345__SRR178126 - parser_io.add_argument("-R", "--no_representative_sequences", action="store_true", help="Do not write representative sequences to fasta") #isPSLC-1_SSPC-3345__SRR178126 - parser_io.add_argument("-C", "--no_core_sequences", action="store_true", help="Do not write core pagenome sequences to fasta") #isPSLC-1_SSPC-3345__SRR178126 - # parser_io.add_argument("-M", "--no_marker_sequences", action="store_true", help="Do not write core pagenome sequences to fasta") #isPSLC-1_SSPC-3345__SRR178126 + parser_io.add_argument("-e", "--no_singletons", action="store_true", help="Exclude singletons") + parser_io.add_argument("-R", "--no_representative_sequences", action="store_true", help="Do not write representative sequences to fasta") + parser_io.add_argument("-C", "--no_core_sequences", action="store_true", help="Do not write core pagenome sequences to fasta") + # parser_io.add_argument("-M", "--no_marker_sequences", action="store_true", help="Do not write core pagenome sequences to fasta") # Utility parser_utility = parser.add_argument_group('Utility arguments') @@ -132,29 +145,50 @@ def main(args=None): parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) # parser_utility.add_argument("--verbose", action='store_true') - # FastANI + # ANI + parser_genome_clustering = parser.add_argument_group('Genome clustering arguments') + parser_genome_clustering.add_argument("-G", "--genome_clustering_algorithm", type=str, choices={"fastani", "skani"}, default="skani", help="Program to use for ANI calculations. `skani` is faster and more memory efficient. For v1.0.0 - v1.3.x behavior, use `fastani`. [Default: skani]") + parser_genome_clustering.add_argument("-A", "--ani_threshold", type=float, default=95.0, help="Species-level cluster (SLC) ANI threshold (Range (0.0, 100.0]) [Default: 95.0]") + parser_genome_clustering.add_argument("--genome_cluster_prefix", type=str, default="SLC-", help="Cluster prefix [Default: 'SLC-") + parser_genome_clustering.add_argument("--genome_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") + parser_genome_clustering.add_argument("--genome_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 + + parser_skani = parser.add_argument_group('Skani triangle arguments') + parser_skani.add_argument("--skani_target_ani", type=float, default=80, help="skani | If you set --skani_target_ani to --ani_threshold, you may screen out genomes ANI ≥ --ani_threshold [Default: 80]") + parser_skani.add_argument("--skani_minimum_af", type=float, default=15, help="skani | Minimum aligned fraction greater than this value [Default: 15]") + parser_skani.add_argument("--skani_no_confidence_interval", action="store_true", help="skani | Output [5,95] ANI confidence intervals using percentile bootstrap on the putative ANI distribution") + # parser_skani.add_argument("--skani_low_memory", action="store_true", help="Skani | More options (e.g. --arg 1 ) https://github.com/bluenote-1577/skani [Default: '']") + + parser_skani = parser.add_argument_group('[Prokaryotic & Eukaryotic] Skani triangle arguments') + parser_skani.add_argument("--skani_nonviral_preset", type=str, default="medium", choices={"fast", "medium", "slow", "none"}, help="skani [Prokaryotic & Eukaryotic]| Use `none` if you are setting skani -c (compression factor) {fast, medium, slow, none} [Default: medium]") + parser_skani.add_argument("--skani_nonviral_compression_factor", type=int, default=125, help="skani [Prokaryotic & Eukaryotic]| Compression factor (k-mer subsampling rate). [Default: 125]") + parser_skani.add_argument("--skani_nonviral_marker_kmer_compression_factor", type=int, default=1000, help="skani [Prokaryotic & Eukaryotic] | Marker k-mer compression factor. Markers are used for filtering. [Default: 1000]") + parser_skani.add_argument("--skani_nonviral_options", type=str, default="", help="skani [Prokaryotic & Eukaryotic] | More options for `skani triangle` (e.g. --arg 1 ) [Default: '']") + + parser_skani = parser.add_argument_group('[Viral] Skani triangle arguments') + parser_skani.add_argument("--skani_viral_preset", type=str, default="slow", choices={"fast", "medium", "slow", "none"}, help="skani | Use `none` if you are setting skani -c (compression factor) {fast, medium, slow, none} [Default: slow]") + parser_skani.add_argument("--skani_viral_compression_factor", type=int, default=30, help="skani [Viral] | Compression factor (k-mer subsampling rate). [Default: 30]") + parser_skani.add_argument("--skani_viral_marker_kmer_compression_factor", type=int, default=200, help="skani [Viral] | Marker k-mer compression factor. Markers are used for filtering. Consider decreasing to ~200-300 if working with small genomes (e.g. plasmids or viruses). [Default: 200]") + parser_skani.add_argument("--skani_viral_options", type=str, default="", help="skani [Viral] | More options for `skani triangle` (e.g. --arg 1 ) [Default: '']") + parser_fastani = parser.add_argument_group('FastANI arguments') - parser_fastani.add_argument("-A", "--ani_threshold", type=float, default=95.0, help="FastANI | Species-level cluster (SLC) ANI threshold (Range (0.0, 100.0]) [Default: 95.0]") - parser_fastani.add_argument("--genome_cluster_prefix", type=str, default="SLC-", help="Cluster prefix [Default: 'SLC-") - parser_fastani.add_argument("--genome_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") - parser_fastani.add_argument("--genome_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 parser_fastani.add_argument("--fastani_options", type=str, default="", help="FastANI | More options (e.g. --arg 1 ) [Default: '']") - # MMSEQS2 - parser_mmseqs2 = parser.add_argument_group('MMSEQS2 arguments') - parser_mmseqs2.add_argument("-a", "--algorithm", type=str, default="easy-cluster", help="MMSEQS2 | {easy-cluster, easy-linclust} [Default: easy-cluster]") - parser_mmseqs2.add_argument("-t", "--minimum_identity_threshold", type=float, default=50.0, help="MMSEQS2 | SLC-Specific Protein Cluster (SSPC, previously referred to as SSO) percent identity threshold (Range (0.0, 100.0]) [Default: 50.0]") - parser_mmseqs2.add_argument("-c", "--minimum_coverage_threshold", type=float, default=0.8, help="MMSEQS2 | SSPC coverage threshold (Range (0.0, 1.0]) [Default: 0.8]") - parser_mmseqs2.add_argument("--protein_cluster_prefix", type=str, default="SSPC-", help="Cluster prefix [Default: 'SSPC-") - parser_mmseqs2.add_argument("--protein_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") - parser_mmseqs2.add_argument("--protein_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 - parser_mmseqs2.add_argument("--mmseqs2_options", type=str, default="", help="MMSEQS2 | More options (e.g. --arg 1 ) [Default: '']") + # Clustering + parser_protein_clustering = parser.add_argument_group('Protein clustering arguments') + parser_protein_clustering.add_argument("-P", "--protein_clustering_algorithm", type=str, choices={"mmseqs-cluster", "mmseqs-linclust", "diamond-cluster", "diamond-linclust"}, default="mmseqs-cluster", help="Clustering algorithm | Diamond can only be used for clustering proteins {mmseqs-cluster, mmseqs-linclust, diamond-cluster, mmseqs-linclust} [Default: mmseqs-cluster]") + parser_protein_clustering.add_argument("-t", "--minimum_identity_threshold", type=float, default=50.0, help="Clustering | Percent identity threshold (Range (0.0, 100.0]) [Default: 50.0]") + parser_protein_clustering.add_argument("-c", "--minimum_coverage_threshold", type=float, default=0.8, help="Clustering | Coverage threshold (Range (0.0, 1.0]) [Default: 0.8]") + parser_protein_clustering.add_argument("--protein_cluster_prefix", type=str, default="SSPC-", help="Cluster prefix [Default: 'SSPC-") + parser_protein_clustering.add_argument("--protein_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") + parser_protein_clustering.add_argument("--protein_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 + parser_protein_clustering.add_argument("--mmseqs2_options", type=str, default="", help="MMSEQS2 | More options (e.g. --arg 1 ) [Default: '']") + parser_protein_clustering.add_argument("--diamond_options", type=str, default="", help="Diamond | More options (e.g. --arg 1 ) [Default: '']") # Pangenome parser_pangenome = parser.add_argument_group('Pangenome arguments') parser_pangenome.add_argument("--minimum_core_prevalence", type=float, default=1.0, help="Minimum ratio of genomes detected in a SLC for a SSPC to be considered core (Range (0.0, 1.0]) [Default: 1.0]") - # Options opts = parser.parse_args() @@ -196,6 +230,19 @@ def main(args=None): configure_parameters(opts, directories) sys.stdout.flush() + # Genome clustering algorithm + GENOME_CLUSTERING_ALGORITHM = opts.genome_clustering_algorithm.lower() + if GENOME_CLUSTERING_ALGORITHM == "fastani": + GENOME_CLUSTERING_ALGORITHM = "FastANI" + if GENOME_CLUSTERING_ALGORITHM == "skani": + GENOME_CLUSTERING_ALGORITHM = "skani" + + # Protein clustering algorithm + PROTEIN_CLUSTERING_ALGORITHM = opts.protein_clustering_algorithm.split("-")[0].lower() + if PROTEIN_CLUSTERING_ALGORITHM == "mmseqs": + PROTEIN_CLUSTERING_ALGORITHM = PROTEIN_CLUSTERING_ALGORITHM.upper() + if PROTEIN_CLUSTERING_ALGORITHM == "diamond": + PROTEIN_CLUSTERING_ALGORITHM = PROTEIN_CLUSTERING_ALGORITHM.capitalize() # Make directories t0 = time.time() @@ -279,50 +326,125 @@ def main(args=None): # Commands f_cmds = open(os.path.join(opts.output_directory, "commands.sh"), "w") - # FastANI - print(format_header("* ({}) Running FastANI:".format(format_duration(t0))), file=sys.stdout) - for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "genomes.list")), "Running FastANI"): + # Pairwise ANI + print(format_header("* ({}) Running {}:".format(format_duration(t0), GENOME_CLUSTERING_ALGORITHM)), file=sys.stdout) + for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "genomes.list")), "Running pairwise ANI"): fields = fp.split("/") organism_type = fields[-2] output_directory = os.path.split(fp)[0] + + if opts.genome_clustering_algorithm == "skani": + name = "skani__{}".format(organism_type) + description = "[Program = skani] [Organism_Type = {}]".format(organism_type) + + arguments = list() + + if organism_type.lower() in {"viral", "virus", "virion"}: + arguments += [ + os.environ["skani"], + "triangle", + "--sparse", + "-t {}".format(opts.n_jobs), + "-l {}".format(fp), + "-o {}".format(os.path.join(output_directory, "skani_output.tsv")), + "--ci" if not opts.skani_no_confidence_interval else "", + "--min-af {}".format(opts.skani_minimum_af), + "-s {}".format(opts.skani_target_ani), + "-c {}".format(opts.skani_viral_compression_factor), + "-m {}".format(opts.skani_viral_marker_kmer_compression_factor), + "--{}".format(opts.skani_viral_preset) if opts.skani_viral_preset else "", + opts.skani_viral_options, + ] + + else: + arguments += [ + os.environ["skani"], + "triangle", + "--sparse", + "-t {}".format(opts.n_jobs), + "-l {}".format(fp), + "-o {}".format(os.path.join(output_directory, "skani_output.tsv")), + "--ci" if not opts.skani_no_confidence_interval else "", + "--min-af {}".format(opts.skani_minimum_af), + "-s {}".format(opts.skani_target_ani), + "-c {}".format(opts.skani_nonviral_compression_factor), + "-m {}".format(opts.skani_nonviral_marker_kmer_compression_factor), + "--{}".format(opts.skani_nonviral_preset) if opts.skani_nonviral_preset else "", + opts.skani_nonviral_options, + ] + + arguments += [ + "&&", + + "cat", + os.path.join(output_directory, "skani_output.tsv"), + "|", + "cut -f1-3", + "|", + "tail -n +2", + "|", + os.environ["edgelist_to_clusters.py"], + "--basename", + "-t {}".format(opts.ani_threshold), + "--no_singletons" if bool(opts.no_singletons) else "", + "--cluster_prefix {}{}".format(organism_type[0].upper(), opts.genome_cluster_prefix), + "--cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", + "--cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill), + "-o {}".format(os.path.join(output_directory, "genome_clusters.tsv")), + "--identifiers {}".format(os.path.join(directories["intermediate"], organism_type, "genome_identifiers.list")), + "--export_graph {}".format(os.path.join(directories["serialization"], f"{organism_type}.networkx_graph.pkl")), + "--export_dict {}".format(os.path.join(directories["serialization"], f"{organism_type}.dict.pkl")), + + "&&", + + "rm -rf {}".format(os.path.join(directories["tmp"], "*")), + + ] + + cmd = Command( + arguments, + name=name, + f_cmds=f_cmds, + ) - name = "fastani__{}".format(organism_type) - description = "[Program = FastANI] [Organism_Type = {}]".format(organism_type) - cmd = Command([ - os.environ["fastANI"], - "-t {}".format(opts.n_jobs), - "--rl {}".format(fp), - "--ql {}".format(fp), - "-o {}".format(os.path.join(output_directory, "fastani_output.tsv")), - opts.fastani_options, - - "&&", - - "cat", - os.path.join(output_directory, "fastani_output.tsv"), - "|", - "cut -f1-3", - "|", - os.environ["edgelist_to_clusters.py"], - "--basename", - "-t {}".format(opts.ani_threshold), - "--no_singletons" if bool(opts.no_singletons) else "", - "--cluster_prefix {}{}".format(organism_type[0].upper(), opts.genome_cluster_prefix), - "--cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", - "--cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill), - "-o {}".format(os.path.join(output_directory, "genome_clusters.tsv")), - "--identifiers {}".format(os.path.join(directories["intermediate"], organism_type, "genome_identifiers.list")), - "--export_graph {}".format(os.path.join(directories["serialization"], f"{organism_type}.networkx_graph.pkl")), - "--export_dict {}".format(os.path.join(directories["serialization"], f"{organism_type}.dict.pkl")), - - "&&", - - "rm -rf {}".format(os.path.join(directories["tmp"], "*")), - - ], - name=name, - f_cmds=f_cmds, - ) + if opts.genome_clustering_algorithm == "fastani": + name = "fastani__{}".format(organism_type) + description = "[Program = FastANI] [Organism_Type = {}]".format(organism_type) + cmd = Command([ + os.environ["fastANI"], + "-t {}".format(opts.n_jobs), + "--rl {}".format(fp), + "--ql {}".format(fp), + "-o {}".format(os.path.join(output_directory, "fastani_output.tsv")), + opts.fastani_options, + + "&&", + + "cat", + os.path.join(output_directory, "fastani_output.tsv"), + "|", + "cut -f1-3", + "|", + os.environ["edgelist_to_clusters.py"], + "--basename", + "-t {}".format(opts.ani_threshold), + "--no_singletons" if bool(opts.no_singletons) else "", + "--cluster_prefix {}{}".format(organism_type[0].upper(), opts.genome_cluster_prefix), + "--cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", + "--cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill), + "-o {}".format(os.path.join(output_directory, "genome_clusters.tsv")), + "--identifiers {}".format(os.path.join(directories["intermediate"], organism_type, "genome_identifiers.list")), + "--export_graph {}".format(os.path.join(directories["serialization"], f"{organism_type}.networkx_graph.pkl")), + "--export_dict {}".format(os.path.join(directories["serialization"], f"{organism_type}.dict.pkl")), + + "&&", + + "rm -rf {}".format(os.path.join(directories["tmp"], "*")), + + ], + name=name, + f_cmds=f_cmds, + ) # Run command cmd.run( @@ -339,11 +461,11 @@ def main(args=None): print("Check the following files:\ncat {}".format(os.path.join(directories["log"], "{}.*".format(name))), file=sys.stdout) sys.exit(cmd.returncode_) - # MMSEQS2 - print(format_header(" * ({}) Running MMSEQS2:".format(format_duration(t0))), file=sys.stdout) + # Protein Clustering + print(format_header(" * ({}) Running {}:".format(format_duration(t0), PROTEIN_CLUSTERING_ALGORITHM)), file=sys.stdout) mag_to_genomecluster = dict() protein_to_proteincluster = dict() - for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "genome_clusters.tsv")), "Running MMSEQS2"): + for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "genome_clusters.tsv")), "Running {}".format(PROTEIN_CLUSTERING_ALGORITHM)): fields = fp.split("/") organism_type = fields[-2] @@ -363,20 +485,21 @@ def main(args=None): print(*proteins, sep="\n", file=f) write_fasta(protein_to_sequence[proteins], os.path.join(genomecluster_directory, "proteins.faa" )) - # Run MMSEQS2 - name = "mmseqs2__{}__{}".format(organism_type, id_genomecluster) - description = "[Program = MMSEQS2] [Organism_Type = {}] [Genome_Cluster = {}]".format(organism_type, id_genomecluster) + # Run Clustering + name = "{}__{}__{}".format(PROTEIN_CLUSTERING_ALGORITHM.lower(), organism_type, id_genomecluster) + description = "[Program = {}] [Organism_Type = {}] [Genome_Cluster = {}]".format(PROTEIN_CLUSTERING_ALGORITHM, organism_type, id_genomecluster) cmd = Command([ - os.environ["mmseqs2_wrapper.py"], + os.environ["clustering_wrapper.py"], "--fasta {}".format(os.path.join(genomecluster_directory, "proteins.faa" )), "--output_directory {}".format(genomecluster_directory), "--no_singletons" if bool(opts.no_singletons) else "", - "--algorithm {}".format(opts.algorithm), + "--algorithm {}".format(opts.protein_clustering_algorithm), "--n_jobs {}".format(opts.n_jobs), "--minimum_identity_threshold {}".format(opts.minimum_identity_threshold), "--minimum_coverage_threshold {}".format(opts.minimum_coverage_threshold), "--mmseqs2_options='{}'" if bool(opts.mmseqs2_options) else "", + "--diamond_options='{}'" if bool(opts.diamond_options) else "", "--cluster_prefix {}_{}".format(id_genomecluster, opts.protein_cluster_prefix), "--cluster_suffix {}".format(opts.protein_cluster_suffix) if bool(opts.protein_cluster_suffix) else "", "--cluster_prefix_zfill {}".format(opts.protein_cluster_prefix_zfill), diff --git a/src/scripts/local_clustering.py b/src/scripts/local_clustering.py index 198f8c9..e35c27f 100755 --- a/src/scripts/local_clustering.py +++ b/src/scripts/local_clustering.py @@ -15,7 +15,7 @@ # from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.24" +__version__ = "2023.12.11" def get_basename(x): _, fn = os.path.split(x) @@ -50,12 +50,14 @@ def add_executables_to_environment(opts): """ accessory_scripts = { "edgelist_to_clusters.py", - "mmseqs2_wrapper.py", + "clustering_wrapper.py", } required_executables={ + "skani", "fastANI", "mmseqs", + "diamond", } required_executables |= accessory_scripts @@ -84,7 +86,6 @@ def add_executables_to_environment(opts): executables[name] = "'{}'".format(os.path.join(opts.script_directory, name)) # Can handle spaces in path - print(format_header( "Adding executables to path from the following source: {}".format(opts.path_config), "-"), file=sys.stdout) for name, executable in executables.items(): if name in required_executables: @@ -95,9 +96,20 @@ def add_executables_to_environment(opts): # Configure parameters def configure_parameters(opts, directories): - assert_acceptable_arguments(opts.algorithm, {"easy-cluster", "easy-linclust"}) - assert 0 < opts.minimum_core_prevalence <= 1.0, "--minimum_core_prevalence must be a float between (0.0,1.0])" + + assert_acceptable_arguments(opts.protein_clustering_algorithm, {"easy-cluster", "easy-linclust", "mmseqs-cluster", "mmseqs-linclust", "diamond-cluster", "diamond-linclust"}) + if opts.protein_clustering_algorithm in {"easy-cluster", "easy-linclust"}: + d = {"easy-cluster":"mmseqs-cluster", "easy-linclust":"mmseqs-linclust"} + warnings.warn("\n\nPlease use `{}` instead of `{}` for MMSEQS2 clustering.".format(d[opts.protein_clustering_algorithm], opts.protein_clustering_algorithm)) + opts.protein_clustering_algorithm = d[opts.protein_clustering_algorithm] + + if opts.skani_nonviral_preset.lower() == "none": + opts.skani_nonviral_preset = None + + if opts.skani_viral_preset.lower() == "none": + opts.skani_viral_preset = None + assert 0 < opts.minimum_core_prevalence <= 1.0, "--minimum_core_prevalence must be a float between (0.0,1.0])" # Set environment variables add_executables_to_environment(opts=opts) @@ -130,23 +142,45 @@ def main(args=None): parser_utility.add_argument("-v", "--version", action='version', version="{} v{}".format(__program__, __version__)) # parser_utility.add_argument("--verbose", action='store_true') - # FastANI + # ANI + parser_genome_clustering = parser.add_argument_group('Genome clustering arguments') + parser_genome_clustering.add_argument("-G", "--genome_clustering_algorithm", type=str, choices={"fastani", "skani"}, default="skani", help="Program to use for ANI calculations. `skani` is faster and more memory efficient. For v1.0.0 - v1.3.x behavior, use `fastani`. [Default: skani]") + parser_genome_clustering.add_argument("-A", "--ani_threshold", type=float, default=95.0, help="Species-level cluster (SLC) ANI threshold (Range (0.0, 100.0]) [Default: 95.0]") + parser_genome_clustering.add_argument("--genome_cluster_prefix", type=str, default="SLC-", help="Cluster prefix [Default: 'SLC-") + parser_genome_clustering.add_argument("--genome_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") + parser_genome_clustering.add_argument("--genome_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 + + parser_skani = parser.add_argument_group('Skani triangle arguments') + parser_skani.add_argument("--skani_target_ani", type=float, default=80, help="skani | If you set --skani_target_ani to --ani_threshold, you may screen out genomes ANI ≥ --ani_threshold [Default: 80]") + parser_skani.add_argument("--skani_minimum_af", type=float, default=15, help="skani | Minimum aligned fraction greater than this value [Default: 15]") + parser_skani.add_argument("--skani_no_confidence_interval", action="store_true", help="skani | Output [5,95] ANI confidence intervals using percentile bootstrap on the putative ANI distribution") + # parser_skani.add_argument("--skani_low_memory", action="store_true", help="Skani | More options (e.g. --arg 1 ) https://github.com/bluenote-1577/skani [Default: '']") + + parser_skani = parser.add_argument_group('[Prokaryotic & Eukaryotic] Skani triangle arguments') + parser_skani.add_argument("--skani_nonviral_preset", type=str, default="medium", choices={"fast", "medium", "slow", "none"}, help="skani [Prokaryotic & Eukaryotic]| Use `none` if you are setting skani -c (compression factor) {fast, medium, slow, none} [Default: medium]") + parser_skani.add_argument("--skani_nonviral_compression_factor", type=int, default=125, help="skani [Prokaryotic & Eukaryotic]| Compression factor (k-mer subsampling rate). [Default: 125]") + parser_skani.add_argument("--skani_nonviral_marker_kmer_compression_factor", type=int, default=1000, help="skani [Prokaryotic & Eukaryotic] | Marker k-mer compression factor. Markers are used for filtering. [Default: 1000]") + parser_skani.add_argument("--skani_nonviral_options", type=str, default="", help="skani [Prokaryotic & Eukaryotic] | More options for `skani triangle` (e.g. --arg 1 ) [Default: '']") + + parser_skani = parser.add_argument_group('[Viral] Skani triangle arguments') + parser_skani.add_argument("--skani_viral_preset", type=str, default="slow", choices={"fast", "medium", "slow", "none"}, help="skani | Use `none` if you are setting skani -c (compression factor) {fast, medium, slow, none} [Default: slow]") + parser_skani.add_argument("--skani_viral_compression_factor", type=int, default=30, help="skani [Viral] | Compression factor (k-mer subsampling rate). [Default: 30]") + parser_skani.add_argument("--skani_viral_marker_kmer_compression_factor", type=int, default=200, help="skani [Viral] | Marker k-mer compression factor. Markers are used for filtering. Consider decreasing to ~200-300 if working with small genomes (e.g. plasmids or viruses). [Default: 200]") + parser_skani.add_argument("--skani_viral_options", type=str, default="", help="skani [Viral] | More options for `skani triangle` (e.g. --arg 1 ) [Default: '']") + parser_fastani = parser.add_argument_group('FastANI arguments') - parser_fastani.add_argument("-A", "--ani_threshold", type=float, default=95.0, help="FastANI | Species-level cluster (SLC) ANI threshold (Range (0.0, 100.0]) [Default: 95.0]") - parser_fastani.add_argument("--genome_cluster_prefix", type=str, default="SLC-", help="Cluster prefix [Default: 'SLC-") - parser_fastani.add_argument("--genome_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") - parser_fastani.add_argument("--genome_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 parser_fastani.add_argument("--fastani_options", type=str, default="", help="FastANI | More options (e.g. --arg 1 ) [Default: '']") - # MMSEQS2 - parser_mmseqs2 = parser.add_argument_group('MMSEQS2 arguments') - parser_mmseqs2.add_argument("-a", "--algorithm", type=str, default="easy-cluster", help="MMSEQS2 | {easy-cluster, easy-linclust} [Default: easy-cluster]") - parser_mmseqs2.add_argument("-t", "--minimum_identity_threshold", type=float, default=50.0, help="MMSEQS2 | SLC-Specific Protein Cluster (SSPC, previously referred to as SSO) percent identity threshold (Range (0.0, 100.0]) [Default: 50.0]") - parser_mmseqs2.add_argument("-c", "--minimum_coverage_threshold", type=float, default=0.8, help="MMSEQS2 | SSPC coverage threshold (Range (0.0, 1.0]) [Default: 0.8]") - parser_mmseqs2.add_argument("--protein_cluster_prefix", type=str, default="SSPC-", help="Cluster prefix [Default: 'SSPC-") - parser_mmseqs2.add_argument("--protein_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") - parser_mmseqs2.add_argument("--protein_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 - parser_mmseqs2.add_argument("--mmseqs2_options", type=str, default="", help="MMSEQS2 | More options (e.g. --arg 1 ) [Default: '']") + # Clustering + parser_protein_clustering = parser.add_argument_group('Protein clustering arguments') + parser_protein_clustering.add_argument("-P", "--protein_clustering_algorithm", type=str, choices={"mmseqs-cluster", "mmseqs-linclust", "diamond-cluster", "diamond-linclust"}, default="mmseqs-cluster", help="Clustering algorithm | Diamond can only be used for clustering proteins {mmseqs-cluster, mmseqs-linclust, diamond-cluster, mmseqs-linclust} [Default: mmseqs-cluster]") + parser_protein_clustering.add_argument("-t", "--minimum_identity_threshold", type=float, default=50.0, help="Clustering | Percent identity threshold (Range (0.0, 100.0]) [Default: 50.0]") + parser_protein_clustering.add_argument("-c", "--minimum_coverage_threshold", type=float, default=0.8, help="Clustering | Coverage threshold (Range (0.0, 1.0]) [Default: 0.8]") + parser_protein_clustering.add_argument("--protein_cluster_prefix", type=str, default="SSPC-", help="Cluster prefix [Default: 'SSPC-") + parser_protein_clustering.add_argument("--protein_cluster_suffix", type=str, default="", help="Cluster suffix [Default: '") + parser_protein_clustering.add_argument("--protein_cluster_prefix_zfill", type=int, default=0, help="Cluster prefix zfill. Use 7 to match identifiers from OrthoFinder. Use 0 to add no zfill. [Default: 0]") #7 + parser_protein_clustering.add_argument("--mmseqs2_options", type=str, default="", help="MMSEQS2 | More options (e.g. --arg 1 ) [Default: '']") + parser_protein_clustering.add_argument("--diamond_options", type=str, default="", help="Diamond | More options (e.g. --arg 1 ) [Default: '']") # Pangenome parser_pangenome = parser.add_argument_group('Pangenome arguments') @@ -191,6 +225,20 @@ def main(args=None): configure_parameters(opts, directories) sys.stdout.flush() + # Genome clustering algorithm + GENOME_CLUSTERING_ALGORITHM = opts.genome_clustering_algorithm.lower() + if GENOME_CLUSTERING_ALGORITHM == "fastani": + GENOME_CLUSTERING_ALGORITHM = "FastANI" + if GENOME_CLUSTERING_ALGORITHM == "skani": + GENOME_CLUSTERING_ALGORITHM = "skani" + + # Protein clustering algorithm + PROTEIN_CLUSTERING_ALGORITHM = opts.protein_clustering_algorithm.split("-")[0].lower() + if PROTEIN_CLUSTERING_ALGORITHM == "mmseqs": + PROTEIN_CLUSTERING_ALGORITHM = PROTEIN_CLUSTERING_ALGORITHM.upper() + if PROTEIN_CLUSTERING_ALGORITHM == "diamond": + PROTEIN_CLUSTERING_ALGORITHM = PROTEIN_CLUSTERING_ALGORITHM.capitalize() + # Make directories t0 = time.time() print(format_header(" " .join(["* ({}) Creating directories:".format(format_duration(t0)), directories["intermediate"]])), file=sys.stdout) @@ -278,50 +326,127 @@ def main(args=None): # Commands f_cmds = open(os.path.join(opts.output_directory, "commands.sh"), "w") - # FastANI - print(format_header("* ({}) Running FastANI:".format(format_duration(t0))), file=sys.stdout) - for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "*", "genomes.list")), "Running FastANI"): + # Pairwise ANI + print(format_header("* ({}) Running {}:".format(format_duration(t0), GENOME_CLUSTERING_ALGORITHM)), file=sys.stdout) + for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "*", "genomes.list")), "Running pairwise ANI"): fields = fp.split("/") organism_type = fields[-3] id_sample = fields[-2] + + os.makedirs(os.path.join(directories["serialization"], id_sample), exist_ok=True) + + if opts.genome_clustering_algorithm == "skani": + name = "skani__{}__{}".format(organism_type, id_sample) + description = "[Program = skani] [Organism_Type = {}] [Sample_ID = {}]".format(organism_type, id_sample) + + arguments = list() + + if organism_type.lower() in {"viral", "virus", "virion"}: + arguments += [ + os.environ["skani"], + "triangle", + "--sparse", + "-t {}".format(opts.n_jobs), + "-l {}".format(fp), + "-o {}".format(os.path.join(os.path.split(fp)[0], "skani_output.tsv")), + "--ci" if not opts.skani_no_confidence_interval else "", + "--min-af {}".format(opts.skani_minimum_af), + "-s {}".format(opts.skani_target_ani), + "-c {}".format(opts.skani_viral_compression_factor), + "-m {}".format(opts.skani_viral_marker_kmer_compression_factor), + "--{}".format(opts.skani_viral_preset) if opts.skani_viral_preset else "", + opts.skani_viral_options, + ] + + else: + arguments += [ + os.environ["skani"], + "triangle", + "--sparse", + "-t {}".format(opts.n_jobs), + "-l {}".format(fp), + "-o {}".format(os.path.join(os.path.split(fp)[0], "skani_output.tsv")), + "--ci" if not opts.skani_no_confidence_interval else "", + "--min-af {}".format(opts.skani_minimum_af), + "-s {}".format(opts.skani_target_ani), + "-c {}".format(opts.skani_nonviral_compression_factor), + "-m {}".format(opts.skani_nonviral_marker_kmer_compression_factor), + "--{}".format(opts.skani_nonviral_preset) if opts.skani_nonviral_preset else "", + opts.skani_nonviral_options, + ] + + arguments += [ + "&&", + + "cat", + os.path.join(os.path.split(fp)[0], "skani_output.tsv"), + "|", + "cut -f1-3", + "|", + "tail -n +2", + "|", + os.environ["edgelist_to_clusters.py"], + "--basename", + "-t {}".format(opts.ani_threshold), + "--no_singletons" if bool(opts.no_singletons) else "", + "--cluster_prefix {}__{}{}".format(id_sample, organism_type[0].upper(), opts.genome_cluster_prefix), + "--cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", + "--cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill), + "-o {}".format(os.path.join(os.path.split(fp)[0], "genome_clusters.tsv")), + "--identifiers {}".format(os.path.join(directories["intermediate"], organism_type, id_sample, "genome_identifiers.list")), + "--export_graph {}".format(os.path.join(directories["serialization"], id_sample, f"{organism_type}.networkx_graph.pkl")), + "--export_dict {}".format(os.path.join(directories["serialization"], id_sample, f"{organism_type}.dict.pkl")), + + "&&", + + "rm -rf {}".format(os.path.join(directories["tmp"], "*")), + + ] + + cmd = Command( + arguments, + name=name, + f_cmds=f_cmds, + ) - name = "fastani__{}__{}".format(organism_type, id_sample) - description = "[Program = FastANI] [Organism_Type = {}] [Sample_ID = {}]".format(organism_type, id_sample) - cmd = Command([ - os.environ["fastANI"], - "-t {}".format(opts.n_jobs), - "--rl {}".format(fp), - "--ql {}".format(fp), - "-o {}".format(os.path.join(os.path.split(fp)[0], "fastani_output.tsv")), - opts.fastani_options, - - "&&", - - "cat", - os.path.join(os.path.split(fp)[0], "fastani_output.tsv"), - "|", - "cut -f1-3", - "|", - os.environ["edgelist_to_clusters.py"], - "--basename", - "-t {}".format(opts.ani_threshold), - "--no_singletons" if bool(opts.no_singletons) else "", - "--cluster_prefix {}__{}{}".format(id_sample, organism_type[0].upper(), opts.genome_cluster_prefix), - "--cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", - "--cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill), - "-o {}".format(os.path.join(os.path.split(fp)[0], "genome_clusters.tsv")), - "--identifiers {}".format(os.path.join(directories["intermediate"], organism_type, id_sample, "genome_identifiers.list")), - "--export_graph {}".format(os.path.join(directories["serialization"], f"{organism_type}.networkx_graph.pkl")), - "--export_dict {}".format(os.path.join(directories["serialization"], f"{organism_type}.dict.pkl")), - - "&&", - - "rm -rf {}".format(os.path.join(directories["tmp"], "*")), - - ], - name=name, - f_cmds=f_cmds, - ) + if opts.genome_clustering_algorithm == "fastani": + name = "fastani__{}__{}".format(organism_type, id_sample) + description = "[Program = FastANI] [Organism_Type = {}] [Sample_ID = {}]".format(organism_type, id_sample) + cmd = Command([ + os.environ["fastANI"], + "-t {}".format(opts.n_jobs), + "--rl {}".format(fp), + "--ql {}".format(fp), + "-o {}".format(os.path.join(os.path.split(fp)[0], "fastani_output.tsv")), + opts.fastani_options, + + "&&", + + "cat", + os.path.join(os.path.split(fp)[0], "fastani_output.tsv"), + "|", + "cut -f1-3", + "|", + os.environ["edgelist_to_clusters.py"], + "--basename", + "-t {}".format(opts.ani_threshold), + "--no_singletons" if bool(opts.no_singletons) else "", + "--cluster_prefix {}__{}{}".format(id_sample, organism_type[0].upper(), opts.genome_cluster_prefix), + "--cluster_suffix {}".format(opts.genome_cluster_suffix) if bool(opts.genome_cluster_suffix) else "", + "--cluster_prefix_zfill {}".format(opts.genome_cluster_prefix_zfill), + "-o {}".format(os.path.join(os.path.split(fp)[0], "genome_clusters.tsv")), + "--identifiers {}".format(os.path.join(directories["intermediate"], organism_type, id_sample, "genome_identifiers.list")), + "--export_graph {}".format(os.path.join(directories["serialization"], id_sample, f"{organism_type}.networkx_graph.pkl")), + "--export_dict {}".format(os.path.join(directories["serialization"], id_sample, f"{organism_type}.dict.pkl")), + + "&&", + + "rm -rf {}".format(os.path.join(directories["tmp"], "*")), + + ], + name=name, + f_cmds=f_cmds, + ) # Run command cmd.run( @@ -338,11 +463,11 @@ def main(args=None): print("Check the following files:\ncat {}".format(os.path.join(directories["log"], "{}.*".format(name))), file=sys.stdout) sys.exit(cmd.returncode_) - # MMSEQS2 - print(format_header(" * ({}) Running MMSEQS2:".format(format_duration(t0))), file=sys.stdout) + # Clustering + print(format_header(" * ({}) Running {}:".format(format_duration(t0), PROTEIN_CLUSTERING_ALGORITHM)), file=sys.stdout) mag_to_genomecluster = dict() protein_to_proteincluster = dict() - for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "*", "genome_clusters.tsv")), "Running MMSEQS2"): + for fp in pv(glob.glob(os.path.join(directories["intermediate"], "*", "*", "genome_clusters.tsv")), "Running {}".format(PROTEIN_CLUSTERING_ALGORITHM)): fields = fp.split("/") organism_type = fields[-3] id_sample = fields[-2] @@ -364,20 +489,21 @@ def main(args=None): print(*proteins, sep="\n", file=f) write_fasta(protein_to_sequence[proteins], os.path.join(genomecluster_directory, "proteins.faa" )) - # Run MMSEQS2 - name = "mmseqs2__{}__{}".format(organism_type, id_genomecluster) - description = "[Program = MMSEQS2] [Organism_Type = {}] [Sample_ID = {}] [Genome_Cluster = {}]".format(organism_type, id_sample, id_genomecluster) + # Run Clustering + name = "{}__{}__{}".format(PROTEIN_CLUSTERING_ALGORITHM.lower(), organism_type, id_genomecluster) + description = "[Program = {}] [Organism_Type = {}] [Sample_ID = {}] [Genome_Cluster = {}]".format(PROTEIN_CLUSTERING_ALGORITHM, organism_type, id_sample, id_genomecluster) cmd = Command([ - os.environ["mmseqs2_wrapper.py"], + os.environ["clustering_wrapper.py"], "--fasta {}".format(os.path.join(genomecluster_directory, "proteins.faa" )), "--output_directory {}".format(genomecluster_directory), "--no_singletons" if bool(opts.no_singletons) else "", - "--algorithm {}".format(opts.algorithm), + "--algorithm {}".format(opts.protein_clustering_algorithm), "--n_jobs {}".format(opts.n_jobs), "--minimum_identity_threshold {}".format(opts.minimum_identity_threshold), "--minimum_coverage_threshold {}".format(opts.minimum_coverage_threshold), "--mmseqs2_options='{}'" if bool(opts.mmseqs2_options) else "", + "--diamond_options='{}'" if bool(opts.diamond_options) else "", "--cluster_prefix {}_{}".format(id_genomecluster, opts.protein_cluster_prefix), "--cluster_suffix {}".format(opts.protein_cluster_suffix) if bool(opts.protein_cluster_suffix) else "", "--cluster_prefix_zfill {}".format(opts.protein_cluster_prefix_zfill), @@ -599,6 +725,5 @@ def main(args=None): df_proteins["id_protein_cluster"].to_frame().dropna(how="any", axis=0).to_csv(os.path.join(directories["output"], "proteins_to_orthogroups.tsv"), sep="\t", header=None) # Change labels? print(*map(lambda fp: " * {}".format(fp), glob.glob(os.path.join(directories["output"],"*.tsv")) + glob.glob(os.path.join(directories["output"],"*.faa"))), sep="\n", file=sys.stdout ) - if __name__ == "__main__": main(sys.argv[1:]) diff --git a/src/scripts/merge_annotations.py b/src/scripts/merge_annotations.py index 50515fd..821c534 100755 --- a/src/scripts/merge_annotations.py +++ b/src/scripts/merge_annotations.py @@ -1,12 +1,12 @@ #!/usr/bin/env python -import sys, os, argparse, re +import sys, os, argparse, re, gzip from collections import defaultdict, OrderedDict import pandas as pd import numpy as np from soothsayer_utils import read_hmmer, pv, get_file_object, assert_acceptable_arguments, format_header, flatten __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2023.10.26" +__version__ = "2023.11.24" # disclaimer = format_header("DISCLAIMER: Lineage predictions are NOT robust and DO NOT USE CORE MARKERS. Please only use for exploratory suggestions.") @@ -72,72 +72,78 @@ def compile_identifiers(df, id_protein_cluster): if len(organism_types) == 1: organism_types = list(organism_types)[0] - # Genomes - genomes = set(df["id_genome"]) + # # Genomes + # genomes = set(df["id_genome"]) - # Samples - samples = set(df["sample_of_origin"]) + # # Samples + # samples = set(df["sample_of_origin"]) # Genome clusters genome_clusters = set(df["id_genome_cluster"]) if len(genome_clusters) == 1: genome_clusters = list(genome_clusters)[0] - data = OrderedDict([ - ("id_genome_cluster", genome_clusters), - ("organism_type", organism_types), - ("genomes", genomes), - ("samples_of_origin", samples), - ], - ) - data = pd.Series(data, name=id_protein_cluster) - data.index = data.index.map(lambda x: ("Identifiers", x)) + # data = OrderedDict([ + # ("id_genome_cluster", genome_clusters), + # ("organism_type", organism_types), + # ("genomes", genomes), + # ("samples_of_origin", samples), + # ], + # ) + # data = pd.Series(data, name=id_protein_cluster) + # data.index = data.index.map(lambda x: ("Identifiers", x)) + data = [genome_clusters, organism_types]#, genomes, samples] return data def compile_uniref(df, id_protein_cluster): df = df.dropna(how="all", axis=0) - unique_identifiers = set(df["sseqid"].unique()) - data = OrderedDict([ - ("number_of_proteins", df.shape[0]), - ("number_of_unique_hits", len(unique_identifiers)), - ("ids", unique_identifiers), - ("names", set(df["product"].unique())), - ], - ) - data = pd.Series(data, name=id_protein_cluster) - data.index = data.index.map(lambda x: ("UniRef", x)) + unique_identifiers = list(df["sseqid"].unique()) + # data = OrderedDict([ + # ("number_of_proteins", df.shape[0]), + # ("number_of_unique_hits", len(unique_identifiers)), + # ("ids", unique_identifiers), + # ("names", set(df["product"].unique())), + # ], + # ) + # data = pd.Series(data, name=id_protein_cluster) + # data.index = data.index.map(lambda x: ("UniRef", x)) + + data = [df.shape[0], len(unique_identifiers), unique_identifiers, list(df["product"].unique())] return data def compile_nonuniref_diamond(df, id_protein_cluster, label): df = df.dropna(how="all", axis=0) unique_identifiers = set(df["sseqid"].unique()) - data = OrderedDict( - [ - ("number_of_proteins", df.shape[0]), - ("number_of_unique_hits", len(unique_identifiers)), - ("ids", unique_identifiers), - ("names", np.nan), - ], - ) - data = pd.Series(data, name=id_protein_cluster) - data.index = data.index.map(lambda x: (label, x)) + # data = OrderedDict( + # [ + # ("number_of_proteins", df.shape[0]), + # ("number_of_unique_hits", len(unique_identifiers)), + # ("ids", unique_identifiers), + # ("names", np.nan), + # ], + # ) + # data = pd.Series(data, name=id_protein_cluster) + # data.index = data.index.map(lambda x: (label, x)) + data = [df.shape[0], len(unique_identifiers), list(unique_identifiers)] + return data def compile_hmmsearch(df, id_protein_cluster, label): df = df.dropna(how="all", axis=0).query("number_of_hits > 0") - unique_identifiers = flatten(df["ids"], into=set) - unique_names = flatten(df["names"], into=set) + unique_identifiers = flatten(df["ids"], into=list, unique=True) + unique_names = flatten(df["names"], unique=True) - data = OrderedDict( - [ - ("number_of_proteins", df.shape[0]), - ("number_of_unique_hits", len(unique_identifiers)), - ("ids", unique_identifiers), - ("names", unique_names), - ], - ) - data = pd.Series(data, name=id_protein_cluster) - data.index = data.index.map(lambda x: (label, x)) + # data = OrderedDict( + # [ + # ("number_of_proteins", df.shape[0]), + # ("number_of_unique_hits", len(unique_identifiers)), + # ("ids", unique_identifiers), + # ("names", unique_names), + # ], + # ) + # data = pd.Series(data, name=id_protein_cluster) + # data.index = data.index.map(lambda x: (label, x)) + data = [df.shape[0], len(unique_identifiers), unique_identifiers, unique_names] return data @@ -487,63 +493,112 @@ def main(args=None): df_annotations.to_csv(os.path.join(opts.output_directory, "annotations.proteins.tsv.gz"), sep="\t") if opts.identifier_mapping: - # Protein clusters - protein_to_proteincluster = df_annotations[("Identifiers", "id_protein_cluster")] - protein_cluster_annotations = list() - for id_protein_cluster, df in pv(df_annotations.groupby(protein_to_proteincluster), description="Compiling consensus annotations for protein clusters", total=protein_to_proteincluster.nunique(), unit=" Protein Clusters"): - # Identifiers - data_identifiers = compile_identifiers(df["Identifiers"], id_protein_cluster) - - # UniRef - data_uniref = compile_uniref(df["UniRef"], id_protein_cluster) - - # MIBiG - data_mibig = compile_nonuniref_diamond(df["MIBiG"], id_protein_cluster, "MIBiG") - - # VFDB - data_vfdb = compile_nonuniref_diamond(df["VFDB"], id_protein_cluster, "VFDB") - - # CAZy - data_cazy = compile_nonuniref_diamond(df["CAZy"], id_protein_cluster, "CAZy") - - # Pfam - data_pfam = compile_hmmsearch(df["Pfam"], id_protein_cluster, "Pfam") - - # NCBIfam-AMR - data_amr = compile_hmmsearch(df["NCBIfam-AMR"], id_protein_cluster, "NCBIfam-AMR") - - # KOFAM - data_kofam = compile_hmmsearch(df["KOFAM"], id_protein_cluster, "KOFAM") - - # AntiFam - data_antifam = compile_hmmsearch(df["AntiFam"], id_protein_cluster, "AntiFam") - - # Composite name - composite_name = list() - composite_name += list(data_uniref[("UniRef","names")]) - composite_name += list(data_kofam[("KOFAM", "names")]) - composite_name += list(data_pfam[("Pfam","names")]) - composite_name = opts.composite_name_joiner.join(composite_name) - data_consensus = pd.Series(composite_name, index=[("Consensus", "composite_name")]) - - # Concatenate - data_concatenated = pd.concat([ - data_identifiers, - data_consensus, - data_uniref, - data_mibig, - data_vfdb, - data_cazy, - data_pfam, - data_amr, - data_kofam, - data_antifam, - ]) - data_concatenated.name = id_protein_cluster - protein_cluster_annotations.append(data_concatenated) - - df_annotations_proteinclusters = pd.DataFrame(protein_cluster_annotations) - df_annotations_proteinclusters.to_csv(os.path.join(opts.output_directory, "annotations.protein_clusters.tsv.gz"), sep="\t") + with gzip.open(os.path.join(opts.output_directory, "annotations.protein_clusters.tsv.gz"), "wt") as f: + print("\t", + *["Identifiers"]*2, + *["Consensus"]*1, + + *["UniRef"]*4, + *["MIBiG"]*3, + *["VFDB"]*3, + *["CAZy"]*3, + *["Pfam"]*4, + *["NCBIfam-AMR"]*4, + *["KOFAM"]*4, + *["AntiFam"]*4, + sep="\t", file=f) + + print( + "id_protein_cluster", + *["id_genome_cluster", "organsim_type"], #, "genomes", "samples_of_origin"], # Identifiers + *["composite_name"], # Consensus + *["number_of_proteins", "number_of_unique_hits", "ids","names"], # UniRef + *["number_of_proteins", "number_of_unique_hits", "ids"], # MIBiG + *["number_of_proteins", "number_of_unique_hits", "ids"], # VFDB + *["number_of_proteins", "number_of_unique_hits", "ids"], # CAZy + *["number_of_proteins", "number_of_unique_hits", "ids","names"], # Pfam + *["number_of_proteins", "number_of_unique_hits", "ids","names"], # NCBIfam-AMR + *["number_of_proteins", "number_of_unique_hits", "ids","names"], # KOFAM + *["number_of_proteins", "number_of_unique_hits", "ids","names"], # AntiFam + sep="\t", + file=f, + ) + # Protein clusters + protein_to_proteincluster = df_annotations[("Identifiers", "id_protein_cluster")] + protein_cluster_annotations = list() + for id_protein_cluster, df in pv(df_annotations.groupby(protein_to_proteincluster), description="Compiling consensus annotations for protein clusters", total=protein_to_proteincluster.nunique(), unit=" Protein Clusters"): + # Identifiers + data_identifiers = compile_identifiers(df["Identifiers"], id_protein_cluster) + + # UniRef + data_uniref = compile_uniref(df["UniRef"], id_protein_cluster) + + # MIBiG + data_mibig = compile_nonuniref_diamond(df["MIBiG"], id_protein_cluster, "MIBiG") + + # VFDB + data_vfdb = compile_nonuniref_diamond(df["VFDB"], id_protein_cluster, "VFDB") + + # CAZy + data_cazy = compile_nonuniref_diamond(df["CAZy"], id_protein_cluster, "CAZy") + + # Pfam + data_pfam = compile_hmmsearch(df["Pfam"], id_protein_cluster, "Pfam") + + # NCBIfam-AMR + data_amr = compile_hmmsearch(df["NCBIfam-AMR"], id_protein_cluster, "NCBIfam-AMR") + + # KOFAM + data_kofam = compile_hmmsearch(df["KOFAM"], id_protein_cluster, "KOFAM") + + # AntiFam + data_antifam = compile_hmmsearch(df["AntiFam"], id_protein_cluster, "AntiFam") + + # Composite name + composite_name = list() + composite_name += list(data_uniref[-1]) + composite_name += list(data_kofam[-1]) + composite_name += list(data_pfam[-1]) + composite_name = list(filter(lambda x: isinstance(x, str), composite_name)) + if len(composite_name) > 0: + composite_name = opts.composite_name_joiner.join(composite_name) + else: + composite_name = np.nan + + print( + id_protein_cluster, + *data_identifiers, + composite_name, + *data_uniref, + *data_mibig, + *data_vfdb, + *data_cazy, + *data_pfam, + *data_amr, + *data_kofam, + *data_antifam, + sep="\t", + file=f, + ) + + # data_consensus = pd.Series(composite_name, index=[("Consensus", "composite_name")]) + # # Concatenate + # data_concatenated = pd.concat([ + # data_identifiers, + # data_consensus, + # data_uniref, + # data_mibig, + # data_vfdb, + # data_cazy, + # data_pfam, + # data_amr, + # data_kofam, + # data_antifam, + # ]) + # data_concatenated.name = id_protein_cluster + # protein_cluster_annotations.append(data_concatenated) + # df_annotations_proteinclusters = pd.DataFrame(protein_cluster_annotations) + # df_annotations_proteinclusters.to_csv(os.path.join(opts.output_directory, "annotations.protein_clusters.tsv.gz"), sep="\t") diff --git a/src/scripts/merge_genome_quality_assessments.py b/src/scripts/merge_genome_quality_assessments.py index a9a8be7..e20a4dd 100755 --- a/src/scripts/merge_genome_quality_assessments.py +++ b/src/scripts/merge_genome_quality_assessments.py @@ -4,7 +4,7 @@ import pandas as pd __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2021.10.16" +__version__ = "2021.11.9" def get_prokaryotic_description(x, fields=["Completeness_Model_Used", "Additional_Notes"]): output = list() @@ -93,7 +93,7 @@ def main(args=None): print("Could not find any prokaryotic genome assessment tables from CheckM2 in the following directory: {}".format(opts.binning_directory), file=sys.stdout) # Viral - viral_genome_quality_files = glob.glob(os.path.join(opts.binning_directory, opts.viral_subdirectory_name, "*", "output", "checkmv_results.filtered.tsv")) + viral_genome_quality_files = glob.glob(os.path.join(opts.binning_directory, opts.viral_subdirectory_name, "*", "output", "checkv_results.filtered.tsv")) if viral_genome_quality_files: print("* Compiling viral genome quality from following files:", *viral_genome_quality_files, sep="\n ", file=sys.stdout) diff --git a/src/scripts/merge_taxonomy_classifications.py b/src/scripts/merge_taxonomy_classifications.py index 46a2c9d..cb0f784 100755 --- a/src/scripts/merge_taxonomy_classifications.py +++ b/src/scripts/merge_taxonomy_classifications.py @@ -5,7 +5,7 @@ from tqdm import tqdm __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2021.10.11" +__version__ = "2021.12.11" def main(args=None): # Path info @@ -62,7 +62,7 @@ def main(args=None): for fp in genome_taxonomy: id_domain = fp.split("/")[-3] df = pd.read_csv(fp, sep="\t", index_col=0) - if id_domain.lower() in {"viral", "virus"}: + if id_domain.lower() in {"viral", "virus", "virion"}: for id_genome, taxonomy in df["lineage"].items(): genome_to_data[id_genome] = {"domain":id_domain, "taxonomy_classification":taxonomy} if id_domain.lower() in {"prokaryotic", "prokaryotes", "prokarya", "bacteria", "archaea", "bacterial","archael", "prok", "proks"}: diff --git a/src/scripts/module_completion_ratios.py b/src/scripts/module_completion_ratios.py index a209a57..7ba04d3 100755 --- a/src/scripts/module_completion_ratios.py +++ b/src/scripts/module_completion_ratios.py @@ -29,7 +29,7 @@ from collections import OrderedDict, defaultdict import pandas as pd -__version__ = "2023.10.23" +__version__ = "2023.12.1" __program__ = os.path.split(sys.argv[0])[-1] ################################################################################ @@ -469,7 +469,7 @@ def main(): parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('-i', '--ko_table', help='path/to/ko_table.tsv following [id_genome][id_ko], No header. Cannot be used with --ko_lists') + parser.add_argument('-i', '--ko_table', default="stdin", help='path/to/ko_table.tsv following [id_genome][id_ko], No header. Cannot be used with --ko_lists [Default: stdin]') parser.add_argument('-k', '--ko_lists', nargs='+', help='Space-delimited list of filepaths where each file represents a genome and each line in the file is a KO id. Cannot be used with --ko_table') parser.add_argument('-o', '--output', default="stdout", help='Output file for module completion ratios [Default: stdout]') parser.add_argument("-d", '--database_directory', required=True, help='path/to/database_directory with pickle files') @@ -482,6 +482,9 @@ def main(): opts = parser.parse_args() + if opts.ko_lists is not None: + if opts.ko_table == "stdin": + opts.ko_table = None assert bool(opts.ko_table) != bool(opts.ko_lists), "Must provide KOs as either a tsv table (--ko_table) or a list of KO ids in different files (--ko_lists)" if opts.ko_table == "stdin": opts.ko_table = sys.stdin diff --git a/src/scripts/partition_unbinned.py b/src/scripts/partition_unbinned.py index d938507..bf4a2eb 100755 --- a/src/scripts/partition_unbinned.py +++ b/src/scripts/partition_unbinned.py @@ -4,7 +4,7 @@ from Bio.SeqIO.FastaIO import SimpleFastaParser __program__ = os.path.split(sys.argv[0])[-1] -__version__ = "2021.08.05" +__version__ = "2023.12.18" def main(args=None): # Path info @@ -24,7 +24,7 @@ def main(args=None): parser.add_argument("-b","--bins", type=str, required=True, help = "path/to/bins.list, No header") parser.add_argument("-f","--fasta", type=str, required=True, help = "path/to/fasta") parser.add_argument("-o","--output", type=str, default="stdout", help = "Output fasta file [Default: stdout]") - parser.add_argument("-m", "--minimum_contig_length", type=int, default=1000, help="Minimum contig length. [Default: 1000] ") + parser.add_argument("-m", "--minimum_contig_length", type=int, default=1, help="Minimum contig length. [Default: 1] ") parser.add_argument("--mode", type=str, default="unbinned", help="Get 'unbinned' or 'binned' contigs [Default: 'unbinned'] ") diff --git a/src/scripts/reformat_sylph_profile_single_sample_output.py b/src/scripts/reformat_sylph_profile_single_sample_output.py new file mode 100755 index 0000000..be7a531 --- /dev/null +++ b/src/scripts/reformat_sylph_profile_single_sample_output.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +import sys, os, argparse, gzip +import pandas as pd +from tqdm import tqdm + +__program__ = os.path.split(sys.argv[0])[-1] +__version__ = "2023.11.10" + +def filepath_to_genome(fp, extension): + assert fp.endswith(extension) + fn = os.path.split(fp)[1] + return fn[:-(len(extension) + 1)] + +def main(args=None): + # Path info + script_directory = os.path.dirname(os.path.abspath( __file__ )) + script_filename = __program__ + + # Path info + description = """ + Running: {} v{} via Python v{} | {}""".format(__program__, __version__, sys.version.split(" ")[0], sys.executable) + usage = "{} -i -o )".format(__program__) + epilog = "Copyright 2021 Josh L. Espinoza (jespinoz@jcvi.org)" + + # Parser + parser = argparse.ArgumentParser(description=description, usage=usage, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter) + + # Pipeline + parser.add_argument("-i","--input", default="stdin", type=str, help = "Input fasta file") + parser.add_argument("-o","--output_directory", required=True, type=str, help = "Output directory to write output files") + # parser.add_argument("-n", "--name", type=str, required=False, help="Name of sample") + parser.add_argument("-c","--genome_clusters", type=str, help = "path/to/mags_to_slcs.tsv. [id_genome][id_genome-cluster], No header.") + parser.add_argument("-f","--field", type=str, default="Taxonomic_abundance", help = "Field to use for reformating [Default: Taxonomic_abundance]") + parser.add_argument("-x","--extension", type=str, default="fa", help = "Fasta file extension for bins [Default: fa]") + parser.add_argument("--header", action="store_true", help = "Do not include header. Doesn't apply to unstacked dataframe.") + + # Options + opts = parser.parse_args() + opts.script_directory = script_directory + opts.script_filename = script_filename + + # Input + if opts.input == "stdin": + opts.input = sys.stdin + + # Output + os.makedirs(opts.output_directory, exist_ok=True) + + # Process + df_sylph = pd.read_csv(opts.input, sep="\t") + assert opts.field in df_sylph.columns, "--field {} not in --input columns: {}".format(opts.field, ", ".join(df_sylph.columns)) + + genome_to_value = df_sylph.set_index("Genome_file")[opts.field] + genome_to_value.index = genome_to_value.index.map(lambda fp: filepath_to_genome(fp, opts.extension)) + + # Output genome values + genome_to_value.to_frame(opts.field.lower()).to_csv(os.path.join(opts.output_directory, "{}.tsv.gz".format(opts.field.lower())), sep="\t", header=bool(opts.header)) + + if opts.genome_clusters: + genome_to_slc = pd.read_csv(opts.genome_clusters, sep="\t", index_col=0).iloc[:,0] + slc_to_value = genome_to_value.groupby(genome_to_slc).sum() + slc_to_value.to_frame(opts.field.lower()).to_csv(os.path.join(opts.output_directory, "{}.clusters.tsv.gz".format(opts.field.lower())), sep="\t", header=bool(opts.header)) + +if __name__ == "__main__": + main() + + + diff --git a/src/veba b/src/veba new file mode 100755 index 0000000..132127a --- /dev/null +++ b/src/veba @@ -0,0 +1,194 @@ +#!/bin/bash +# v2023.12.18 + +# Define available modules +AVAILABLE_MODULES=( +"annotate" +"assembly-long" +"assembly" +"binning-eukaryotic" +"binning-prokaryotic" +"binning-viral" +"biosynthetic" +"classify-eukaryotic" +"classify-prokaryotic" +"classify-viral" +"cluster" +"coverage-long" +"coverage" +"index" +"mapping" +"phylogeny" +"preprocess-long" +"preprocess" +"profile-pathway" +"profile-taxonomy" +) + +# Conda base +CONDA_BASE=$(conda info --base) + +# Script directory +SCRIPT_DIRECTORY=$(dirname $0) + +# Function to display script usage +show_help() { + echo -e "-------------------------------" + echo " " + echo -e " _ _ _______ ______ _______\n \ / |______ |_____] |_____|\n \/ |______ |_____] | |" + echo " " + echo -e "-------------------------------" + + echo "Usage: $0 [-m ] [-o ] [-v|--version] [-h|--help]" + echo -e "Example: veba --module preprocess --params \"-1 S1_1.fq.gz -2 S1_2.fq.gz -n S1 -o veba_output/preprocess\"" + echo -e "GitHub: https://github.com/jolespin" + echo -e "Developer: Josh L. Espinoza, PhD (ORCiD: 0000-0003-3447-3845)" + echo " " + echo "Options:" + echo " -m, --module Specify the module. Available modules: ${AVAILABLE_MODULES[*]}" + echo " -p, --params Specify parameters to give to each module" + echo " -v, --version Display the version information" + echo " -h, --help Display this help message" + exit 0 +} + +# Parse command-line arguments +ARGS=$(getopt -o m:p:vh --long module:,params:,version,help -n "$0" -- "$@") + +# Exit if getopt encounters an error +if [ $? -ne 0 ]; then + exit 1 +fi + +eval set -- "$ARGS" + +# Default values +MODULE="" +PARAMS="-h" + +# Process command-line options +while true; do + case "$1" in + -m|--module) + MODULE="$2" + shift 2 + ;; + -p|--params) + PARAMS="$2" + shift 2 + ;; + -v|--version) + echo "VEBA Version:" + cat "${SCRIPT_DIRECTORY}/VEBA_VERSION" + exit 0 + ;; + -h|--help) + show_help + ;; + --) + shift + break + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +# Validate required arguments +if [ -z "$MODULE" ]; then + echo "Module is required. Use --module." + exit 1 +fi + + +# Check if the specified module is valid +if [[ ! " ${AVAILABLE_MODULES[@]} " =~ " $MODULE " ]]; then + echo "Invalid module. Must be one of: ${AVAILABLE_MODULES[*]}" + exit 1 +fi + +# Perform tasks based on the specified module +case $MODULE in + "annotate") + source "${CONDA_BASE}/bin/activate" VEBA-annotate_env + annotate.py $PARAMS + ;; + "assembly-long") + source "${CONDA_BASE}/bin/activate" VEBA-assembly_env + assembly-long.py $PARAMS + ;; + "assembly") + source "${CONDA_BASE}/bin/activate" VEBA-assembly_env + assembly.py $PARAMS + ;; + "binning-eukaryotic") + source "${CONDA_BASE}/bin/activate" VEBA-binning-eukaryotic_env + binning-eukaryotic.py $PARAMS + ;; + "binning-prokaryotic") + source "${CONDA_BASE}/bin/activate" VEBA-binning-prokaryotic_env + binning-prokaryotic.py $PARAMS + ;; + "binning-viral") + source "${CONDA_BASE}/bin/activate" VEBA-binning-viral_env + binning-viral.py $PARAMS + ;; + "biosynthetic") + source "${CONDA_BASE}/bin/activate" VEBA-biosynthetic_env + biosynthetic.py $PARAMS + ;; + "classify-eukaryotic") + source "${CONDA_BASE}/bin/activate" VEBA-classify_env + classify-eukaryotic.py $PARAMS + ;; + "classify-prokaryotic") + source "${CONDA_BASE}/bin/activate" VEBA-classify_env + classify-prokaryotic.py $PARAMS + ;; + "classify-viral") + source "${CONDA_BASE}/bin/activate" VEBA-classify_env + classify-viral.py $PARAMS + ;; + "cluster") + source "${CONDA_BASE}/bin/activate" VEBA-cluster_env + cluster.py $PARAMS + ;; + "coverage-long") + source "${CONDA_BASE}/bin/activate" VEBA-assembly_env + coverage-long.py $PARAMS + ;; + "coverage") + source "${CONDA_BASE}/bin/activate" VEBA-assembly_env + coverage.py $PARAMS + ;; + "index") + source "${CONDA_BASE}/bin/activate" VEBA-mapping_env + index.py $PARAMS + ;; + "mapping") + source "${CONDA_BASE}/bin/activate" VEBA-mapping_env + mapping.py $PARAMS + ;; + "phylogeny") + source "${CONDA_BASE}/bin/activate" VEBA-phylogeny_env + phylogeny.py $PARAMS + ;; + "preprocess-long") + source "${CONDA_BASE}/bin/activate" VEBA-preprocess_env + preprocess-long.py $PARAMS + ;; + "preprocess") + source "${CONDA_BASE}/bin/activate" VEBA-preprocess_env + preprocess.py $PARAMS + ;; + "profile-pathway") + source "${CONDA_BASE}/bin/activate" VEBA-profile_env + profile-pathway.py $PARAMS + ;; + "profile-taxonomy") + source "${CONDA_BASE}/bin/activate" VEBA-profile_env + profile-taxonomy.py $PARAMS + ;; +esac \ No newline at end of file diff --git a/src/get_script_versions.sh b/src/veba_versions.sh similarity index 100% rename from src/get_script_versions.sh rename to src/veba_versions.sh diff --git a/walkthroughs/README.md b/walkthroughs/README.md index 3586d83..2aecec6 100644 --- a/walkthroughs/README.md +++ b/walkthroughs/README.md @@ -31,29 +31,43 @@ sbatch -J ${N} -N 1 -c ${N_JOBS} --ntasks-per-node=1 -o logs/${N}.o -e logs/${N} #### Available walkthroughs: +##### Accessing SRA: + * **[Downloading and preprocessing fastq files](download_and_preprocess_reads.md)** - Explains how to download reads from NCBI and run *VEBA's* `preprocess.py` module to decontaminate either metagenomic and/or metatranscriptomic reads. + +##### End-to-end workflows: + * **[Complete end-to-end metagenomics analysis](end-to-end_metagenomics.md)** - Goes through assembling metagenomic reads, binning, clustering, classification, and annotation. We also show how to use the unbinned contigs in a pseudo-coassembly with guidelines on when it's a good idea to go this route. * **[Recovering viruses from metatranscriptomics](recovering_viruses_from_metatranscriptomics.md)** - Goes through assembling metatranscriptomic reads, viral binning, clustering, and classification. -* **[Read mapping and counts tables](read_mapping_and_counts_tables.md)** - Read mapping and generating counts tables at the contig, MAG, SLC, ORF, and SSO levels. -* **[Phylogenetic inference](phylogenetic_inference.md)** - Phylogenetic inference of eukaryotic diatoms. * **[Setting up *bona fide* coassemblies for metagenomics or metatranscriptomics](setting_up_coassemblies.md)** - In the case where all samples are of low depth, it may be useful to use coassembly instead of sample-specific approaches. This walkthrough goes through concatenating reads, creating a reads table, coassembly of concatenated reads, aligning sample-specific reads to the coassembly for multiple sorted BAM files, and mapping reads for scaffold/transcript-level counts. Please note that a coassembly differs from the pseudo-coassembly concept introduced in the VEBA publication. For more information regarding the differences between *bona fide* coassembly and pseud-coassembly, please refer to [*23. What's the difference between a coassembly and a pseudo-coassembly?*](https://github.com/jolespin/veba/blob/main/FAQ.md#23-whats-the-difference-between-a-coassembly-and-a-pseudo-coassembly). + +##### Phylogenetics: + +* **[Phylogenetic inference](phylogenetic_inference.md)** - Phylogenetic inference of eukaryotic diatoms. + +##### Bioprospecting: + * **[Bioprospecting for biosynthetic gene clusters](bioprospecting_for_biosynthetic_gene_clusters.md)** - Detecting biosynthetic gene clusters (BGC) with and scoring novelty of BGCs. + +##### Mapping reads and rapid profiling: + +* **[Read mapping and counts tables](read_mapping_and_counts_tables.md)** - Read mapping and generating counts tables at the contig, MAG, SLC, ORF, and SSO levels. +* **[Taxonomic profiling *de novo* genomes](taxonomic_profiling_de-novo_genomes.md)** - Explains how to build and profile reads to custom `Sylph` databases from *de novo* genomes. +* **[Pathway profiling *de novo* genomes](pathway_profiling_de-novo_genomes.md)** - Explains how to build and align reads to custom `HUMAnN` databases from *de novo* genomes and annotations. * **[Converting counts tables](converting_counts_tables.md)** - Convert your counts table (with or without metadata) to [anndata](https://anndata.readthedocs.io/en/latest/index.html) or [biom](https://biom-format.org/) format. Also supports [Pandas pickle](https://pandas.pydata.org/docs/reference/api/pandas.read_pickle.html) format. + +##### Containerization and AWS: + * **[Adapting commands for Docker](adapting_commands_for_docker.md)** - Explains how to download and use Docker for running VEBA. * **[Adapting commands for AWS](adapting_commands_for_aws.md)** - Explains how to download and use Docker for running VEBA specifically on AWS. -* **[Metabolic Profiling *de novo* genomes](metabolic_profiling_de-novo_genomes.md)** - Explains how to build and align reads to custom `HUMAnN` databases from *de novo* genomes and annotations. - ___________________________________________ **Coming Soon:** * Workflow for low-depth samples with no bins -* Workflow for ASV detection from short-read amplicons -* Workflows for integrating 3rd party software with *VEBA*: - * Using [EukHeist](https://github.com/AlexanderLabWHOI/EukHeist) for eukaryotic binning followed by *VEBA* for mapping and annotation. - * Using [EukMetaSanity](https://github.com/cjneely10/EukMetaSanity) for modeling genes for eukaryotic genomes recovered with *VEBA*. - +* Assigning eukaryotic taxonomy to unbinned contigs +* Bioprospecting using [`PlasticDB` database](https://plasticdb.org/) ___________________________________________ ##### Notes: diff --git a/walkthroughs/adapting_commands_for_aws.md b/walkthroughs/adapting_commands_for_aws.md index bc6acb8..091fe36 100644 --- a/walkthroughs/adapting_commands_for_aws.md +++ b/walkthroughs/adapting_commands_for_aws.md @@ -38,7 +38,7 @@ This job definition pulls the [jolespin/veba_preprocess](https://hub.docker.com/ "jobDefinitionName": "preprocess__S1", "type": "container", "containerProperties": { - "image": "jolespin/veba_preprocess:1.3.0", + "image": "jolespin/veba_preprocess:1.4.0", "command": [ "preprocess.py", "-1", diff --git a/walkthroughs/adapting_commands_for_docker.md b/walkthroughs/adapting_commands_for_docker.md index 939780a..b6d4899 100644 --- a/walkthroughs/adapting_commands_for_docker.md +++ b/walkthroughs/adapting_commands_for_docker.md @@ -24,7 +24,7 @@ Refer to the [Docker documentation](https://docs.docker.com/engine/install/). Let's say you wanted to use the `preprocess` module. Download the Docker image as so: ``` -VERSION=1.3.0 +VERSION=1.4.0 docker image pull jolespin/veba_preprocess:${VERSION} ``` @@ -36,7 +36,7 @@ For example, here's how we would run the `preprocess.py` module. First let's ju ```bash # Version -VERSION=1.2.0 +VERSION=1.4.0 # Image DOCKER_IMAGE="jolespin/veba_preprocess:${VERSION}" @@ -90,7 +90,7 @@ CMD="preprocess.py -1 ${CONTAINER_INPUT_DIRECTORY}/${R1} -2 ${CONTAINER_INPUT_DI # Docker # Version -VERSION=1.2.0 +VERSION=1.4.0 # Image DOCKER_IMAGE="jolespin/veba_preprocess:${VERSION}" diff --git a/walkthroughs/bioprospecting_for_biosynthetic_gene_clusters.md b/walkthroughs/bioprospecting_for_biosynthetic_gene_clusters.md index 23be35e..54f6187 100644 --- a/walkthroughs/bioprospecting_for_biosynthetic_gene_clusters.md +++ b/walkthroughs/bioprospecting_for_biosynthetic_gene_clusters.md @@ -12,6 +12,8 @@ _____________________________________________________ 1. Compile table of genomes and gene models 2. Identify biosynthetic gene clusters and score novelty +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. + _____________________________________________________ @@ -37,8 +39,6 @@ We only need the `[id_genome] [path/to/genome.fasta] [path/to/gene_models.gff]` Now that we have our genome table formatted so it is `[id_genome] [path/to/genome.fasta] [path/to/gene_models.gff]` without headers, we can run the `biosynthetic.py` module to identify biosynthetic gene clusters via `antiSMASH` and detect homology of components to the `MIBiG` database. -**Conda Environment:** `conda activate VEBA-biosynthetic_env` - ``` # Set the number of threads @@ -55,7 +55,7 @@ GENOMES=veba_output/misc/genomes_gene-models.tsv OUT_DIR=veba_output/biosynthetic/prokaryotic # Directory -CMD="source activate VEBA-biosynthetic_env && biosynthetic.py -i ${GENOMES} -o ${OUT_DIR} -p ${N_JOBS} -t bacteria" +CMD="source activate VEBA && veba --module biosynthetic --params \"-i ${GENOMES} -o ${OUT_DIR} -p ${N_JOBS} -t bacteria\"" # Either run this command or use SunGridEnginge/SLURM ``` diff --git a/walkthroughs/converting_counts_tables.md b/walkthroughs/converting_counts_tables.md index 13c2721..1e8a7b6 100644 --- a/walkthroughs/converting_counts_tables.md +++ b/walkthroughs/converting_counts_tables.md @@ -15,9 +15,9 @@ _____________________________________________________ 2. Provide a counts table and sample metadata 3. Provide a counts table, sample metadata, and -_____________________________________________________ +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. -**Conda Environment:** `conda activate VEBA-mapping_env` +_____________________________________________________ #### 1. Let's convert to a Python pickle object without any metadata diff --git a/walkthroughs/download_and_preprocess_reads.md b/walkthroughs/download_and_preprocess_reads.md index 2da95a5..6219160 100644 --- a/walkthroughs/download_and_preprocess_reads.md +++ b/walkthroughs/download_and_preprocess_reads.md @@ -11,7 +11,7 @@ If you want to either remove human contamination or count ribosomal reads then m ``` echo $VEBA_DATABASE -/expanse/projects/jcl110/db/veba/VDB_v4 +/expanse/projects/jcl110/db/veba/VDB_v6 # ^_^ Yours will be different obviously # ``` @@ -111,28 +111,12 @@ Here we are going to count the reads for the human contamination and ribosomal r * ⚠️ If your host is not human then you will need to use a different contamination reference. See item #22 in the [FAQ](https://github.com/jolespin/veba/blob/main/FAQ.md). -* ⚠️ As of 2022.10.18 *VEBA* has switched from using the "GRCh38 no alt analysis set" to the "CHM13v2.0 telomore-to-telomere" build for human. If you've installed *VEBA* before this date or are using `v1.0.0` release from [Espinoza et al. 2022](https://bmcbioinformatics.biomedcentral.com/articles/10.1186/s12859-022-04973-8) then you can update with the following code: - -``` -conda activate VEBA-database_env -wget -v -P ${VEBA_DATABASE} https://genome-idx.s3.amazonaws.com/bt/chm13v2.0.zip -unzip -d ${VEBA_DATABASE}/Contamination/ ${VEBA_DATABASE}/chm13v2.0.zip -rm -rf ${VEBA_DATABASE}/chm13v2.0.zip - -# Use this if you want to remove the previous GRCh38 index -rm -rf ${VEBA_DATABASE}/Contamination/grch38/ -``` - -Continuing with the tutorial...just make note of the human index here and swap out GRCh38 for CHM13v2.0 if you decided to update: ``` N_JOBS=4 -# Human Bowtie2 index -HUMAN_INDEX=${VEBA_DATABASE}/Contamination/grch38/GCA_000001405.15_GRCh38_no_alt_analysis_set.fna.bowtie_index - -# or use this if you have updated from GRCh38 to CHM13v2.0 -# HUMAN_INDEX=${VEBA_DATABASE}/Contamination/chm13v2.0/chm13v2.0 +# CHM13v2.0 +HUMAN_INDEX=${VEBA_DATABASE}/Contamination/chm13v2.0/chm13v2.0 # Ribosomal k-mer fasta RIBOSOMAL_KMERS=${VEBA_DATABASE}/Contamination/kmers/ribokmers.fa.gz @@ -151,7 +135,7 @@ for ID in $(cat identifiers.list); do rm -f logs/${N}.* # Set up the command (use source from base environment instead of conda because of the `init` issues) - CMD="source activate VEBA-preprocess_env && preprocess.py -n ${ID} -1 ${R1} -2 ${R2} -p ${N_JOBS} -x ${HUMAN_INDEX} -k ${RIBOSOMAL_KMERS} --retain_contaminated_reads 0 --retain_kmer_hits 0 --retain_non_kmer_hits 0 -o veba_output/preprocess" + CMD="source activate VEBA && veba --module preprocess --params \"-n ${ID} -1 ${R1} -2 ${R2} -p ${N_JOBS} -x ${HUMAN_INDEX} -k ${RIBOSOMAL_KMERS} --retain_contaminated_reads 0 --retain_kmer_hits 0 --retain_non_kmer_hits 0 -o veba_output/preprocess\"" # If you have SunGrid engine, do something like this: # qsub -o logs/${N}.o -e logs/${N}.e -cwd -N ${N} -j y -pe threaded ${N_JOBS} "${CMD}" @@ -161,7 +145,7 @@ for ID in $(cat identifiers.list); do done ``` -Note: `preprocess.py` is a wrapper around `fastq_preprocessor` which takes in 0 and 1 as False and True, respectively. The reasoning for this is that I was able to keep the prefix `retain` while setting defaults easier. +Note: `preprocess` is a wrapper around `fastq_preprocessor`. It creates the following directory structure where each sample is it's own subdirectory. Makes globbing much easier: diff --git a/walkthroughs/end-to-end_metagenomics.md b/walkthroughs/end-to-end_metagenomics.md index baa22b8..c2592c8 100644 --- a/walkthroughs/end-to-end_metagenomics.md +++ b/walkthroughs/end-to-end_metagenomics.md @@ -23,12 +23,12 @@ _____________________________________________________ 12. Classify eukaryotic genomes 13. Annotate proteins +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. + _____________________________________________________ #### 1. Preprocess reads and get directory set up -**Conda Environment:** `conda activate VEBA-preprocess_env` - Refer to the [downloading and preprocessing reads walkthrough](download_and_preprocess_reads.md). At this point, it's assumed you have the following: * A file with all of your identifiers on a separate line (e.g., `identifiers.list` but you can call it whatever you want) @@ -41,8 +41,6 @@ Here we are going to assemble all of the reads using `metaSPAdes`. If you have **Recommended memory request:** For this *Plastisphere* dataset, I requested `64GB` of memory from my HPC. Though, this will change depending on how deep your samples are sequenced. -**Conda Environment:** `conda activate VEBA-assembly_env` - ``` # Set the number of threads to use for each sample. Let's use 4 N_JOBS=4 @@ -65,7 +63,7 @@ for ID in $(cat identifiers.list); do R2=veba_output/preprocess/${ID}/output/cleaned_2.fastq.gz # Set up command - CMD="source activate VEBA-assembly_env && assembly.py -1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -P metaspades.py" + CMD="source activate VEBA && veba --module assembly --params \"-1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -P metaspades.py\"" # Either run this command or use SunGridEnginge/SLURM @@ -98,7 +96,6 @@ Let's start the binning with viruses since this is performed on a per-contig bas **Recommended memory request:** `16 GB` -**Conda Environment:** `conda activate VEBA-binning-viral_env` ``` N_JOBS=4 @@ -108,7 +105,7 @@ for ID in $(cat identifiers.list); rm -f logs/${N}.* FASTA=veba_output/assembly/${ID}/output/scaffolds.fasta BAM=veba_output/assembly/${ID}/output/mapped.sorted.bam - CMD="source activate VEBA-binning-viral_env && binning-viral.py -f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -m 1500 -o veba_output/binning/viral" + CMD="source activate VEBA && veba --module binning-viral --params \"-f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -m 1500 -o veba_output/binning/viral\"" # Either run this command or use SunGridEnginge/SLURM done @@ -140,11 +137,8 @@ Here we are going to perform iterative prokaryotic binning. It's difficult to s If you have a lot of samples and a lot of contigs then use the `--skip_maxbin2` flag because it takes MUCH longer to run. For the *Plastisphere* it was going to take 40 hours per `MaxBin2` run (there are 2 `MaxBin2` runs) per iteration. `Metabat2` and `CONCOCT` can do the heavy lifting much faster and often with better results so it's recommended to skip `MaxBin2` for larger datasets. -**Recommended memory request:** `10GB` - -*Versions prior to `v1.1.0` were reliant on `GTDB-Tk` which needed at least `60GB`. `GTDB-Tk` is no longer required with the update of `CheckM` to `CheckM2`.* +**Recommended memory request:** `16GB` -**Conda Environment:** `conda activate VEBA-binning-prokaryotic_env` ``` N_JOBS=4 @@ -161,7 +155,7 @@ for ID in $(cat identifiers.list); do FASTA=veba_output/binning/viral/${ID}/output/unbinned.fasta BAM=veba_output/assembly/${ID}/output/mapped.sorted.bam - CMD="source activate VEBA-binning-prokaryotic_env && binning-prokaryotic.py -f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -o ${OUT_DIR} -m 1500 -I ${N_ITER}" + CMD="source activate VEBA && veba --module binning-prokaryotic --params \"-f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -o ${OUT_DIR} -m 1500 -I ${N_ITER}\"" # Either run this command or use SunGridEnginge/SLURM @@ -194,9 +188,7 @@ for ID in $(cat identifiers.list); do #### 5. Recover eukaryotes from metagenomic assemblies Let's take the unbinned contigs from the prokaryotic binning and recover eukayoritc genomes. Unfortunately, we aren't going to do iterative binning here because there aren't any tools that can handle consensus genome binning as there is with prokaryotes (e.g., *DAS Tool*). We have the option to use either *Metabat2* or *CONCOCT*. In our experience, *Metabat2* works better for recovering eukaryotic genomes from metagenomes and it's also faster as well. -**Recommended memory request:** `128GB` - -**Conda Environment:** `conda activate VEBA-binning-eukaryotic_env` +**Recommended memory request:** `48GB` ``` N_JOBS=4 @@ -209,7 +201,7 @@ for ID in $(cat identifiers.list); do rm -f logs/${N}.* FASTA=veba_output/binning/prokaryotic/${ID}/output/unbinned.fasta BAM=veba_output/assembly/${ID}/output/mapped.sorted.bam - CMD="source activate VEBA-binning-eukaryotic_env && binning-eukaryotic.py -f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -m 1500 -a metabat2 -o ${OUT_DIR}" + CMD="source activate VEBA && veba --module binning-eukaryotic --params \"-f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -m 1500 -a metabat2 -o ${OUT_DIR}\"" # Either run this command or use SunGridEnginge/SLURM @@ -257,8 +249,6 @@ That said, if you decide to move forward with the multi-sample approach then the **Recommended memory request:** `24 GB` -**Conda Environment:** `conda activate VEBA-assembly_env` - ``` @@ -270,8 +260,6 @@ mkdir -p veba_output/misc # I recommend having this light-weight program in base environment # if you do a lot of fasta manipulation. -conda activate VEBA-preprocess_env - # -------------------------------------------------------------------- # Method 1) Shortcut @@ -302,11 +290,11 @@ compile_reads_table.py -i veba_output/preprocess/ -r > veba_output/misc/reads_ta # Now let's map all the reads to the pseudo-coassembly (i.e., all_sample_specific_mags.unbinned_contigs.gt1500.fasta) -N=pseudo-coassembly +N=Multisample N_JOBS=16 # Let's use more threads here because we are going to be handling multiple samples at once -CMD="source activate VEBA-assembly_env && coverage.py -f veba_output/misc/all_sample_specific_mags.unbinned_contigs.gt1500.fasta -r veba_output/misc/reads_table.tsv -p ${N_JOBS} -o veba_output/assembly/pseudo-coassembly -m 1500" +CMD="source activate VEBA && veba --module coverage --params \"-f veba_output/misc/all_sample_specific_mags.unbinned_contigs.gt1500.fasta -r veba_output/misc/reads_table.tsv -p ${N_JOBS} -o veba_output/assembly/Multisample -m 1500\"" # Either run this command or use SunGridEnginge/SLURM ``` @@ -327,8 +315,6 @@ Let's try to recover some prokaryotes using the concatenated unbinned contigs. **Recommended memory request:** `10 - 24GB` -**Conda Environment:** `conda activate VEBA-binning-prokaryotic_env` - ``` # Setting more threads since we are only running this once N_JOBS=32 @@ -337,14 +323,14 @@ N_JOBS=32 N_ITER=5 # Set up filepaths and names -NAME="pseudo-coassembly" +NAME="Multisample" N="binning-prokaryotic__${NAME}" rm -f logs/${N}.* -FASTA=veba_output/assembly/pseudo-coassembly/output/reference.fasta -BAMS=veba_output/assembly/pseudo-coassembly/output/*/mapped.sorted.bam +FASTA=veba_output/assembly/${NAME}/output/reference.fasta +BAMS=veba_output/assembly/${NAME}/output/*/mapped.sorted.bam # Set up command -CMD="source activate VEBA-binning-prokaryotic_env && binning-prokaryotic.py -f ${FASTA} -b ${BAMS} -n ${NAME} -p ${N_JOBS} -m 1500 -I ${N_ITER} --skip_maxbin2" +CMD="source activate VEBA && veba --module binning-prokaryotic --params \"-f ${FASTA} -b ${BAMS} -n ${NAME} -p ${N_JOBS} -m 1500 -I ${N_ITER} --skip_maxbin2\"" # Either run this command or use SunGridEnginge/SLURM @@ -356,9 +342,8 @@ Check Step 4 for the output file descriptions. #### ⚠️ 8. Recover eukaryotes from pseudo-coassembly [Optional] Let's try to recover some eukaryotes using the updated concatenated unbinned contigs. -**Recommended memory request:** `128GB` +**Recommended memory request:** `48 GB` -**Conda Environment:** `conda activate VEBA-binning-eukaryotic_env` ``` @@ -366,14 +351,14 @@ Let's try to recover some eukaryotes using the updated concatenated unbinned con N_JOBS=32 # Set up filepaths and names -NAME="pseudo-coassembly" +NAME="Multisample" N="binning-eukaryotic__${NAME}" rm -f logs/${N}.* FASTA=veba_output/binning/prokaryotic/${NAME}/output/unbinned.fasta BAMS=veba_output/assembly/${NAME}/output/*/mapped.sorted.bam # Set up command -CMD="source activate VEBA-binning-eukaryotic_env && binning-eukaryotic.py -f ${FASTA} -b ${BAMS} -n ${NAME} -p ${N_JOBS} -m 1500 -a metabat2 -o veba_output/binning/eukaryotic" +CMD="source activate VEBA && veba --module binning-eukaryotic --params \"-f ${FASTA} -b ${BAMS} -n ${NAME} -p ${N_JOBS} -m 1500 -a metabat2 -o veba_output/binning/eukaryotic\"" # Either run this command or use SunGridEnginge/SLURM @@ -389,8 +374,6 @@ To analyze these data, we are going to generate some counts tables and we want a **Recommended memory request:** `24 GB` should work for most datasets but you may need to increase for much larger datasets. -**Conda Environment:** `conda activate VEBA-cluster_env` - ``` # We need to generate a table with the following fields: @@ -403,7 +386,7 @@ compile_genomes_table.py -i veba_output/binning/ > veba_output/misc/genomes_tabl N_JOBS=12 # Set up command -CMD="source activate VEBA-cluster_env && cluster.py -i veba_output/misc/genomes_table.tsv -o veba_output/cluster -p ${N_JOBS}" +CMD="source activate VEBA && veba --module cluster --params \"-i veba_output/misc/genomes_table.tsv -o veba_output/cluster -p ${N_JOBS}\"" # Either run this command or use SunGridEnginge/SLURM @@ -433,15 +416,13 @@ CMD="source activate VEBA-cluster_env && cluster.py -i veba_output/misc/genomes_ * global/pangenome_tables/*.tsv.gz - Pangenome tables for each SLC with prevalence values * global/serialization/*.dict.pkl - Python dictionaries for clusters * global/serialization/*.networkx_graph.pkl - NetworkX graphs for clusters -* local/* - If `--no_local_clustering` is not selected then all of the files are generated for local clustering +* local/* - If `--local_clustering` is selected then all of the files are generated for local clustering #### 10. Classify viral genomes Viral classification is performed using `geNomad`. Classification can be performed using the intermediate binning results which is much quicker. Alternatively, if you have viruses identified elsewhere you can still classify using the `--genomes` argument instead. -**Recommended memory request:** `1 GB` will work if you've performed viral binning via *VEBA*. If not, these use `16 GB` for external genomes. - -**Conda Environment:** `conda activate VEBA-classify_env` +**Recommended memory request:** `1 GB` should work if you've performed viral binning via *VEBA*. If not, these use `16 GB` for external genomes. ``` N=classify-viral @@ -458,7 +439,7 @@ CLUSTERS=veba_output/cluster/output/global/mags_to_slcs.tsv rm -rf logs/${N}.* # Set up the command -CMD="source activate VEBA-classify_env && classify-viral.py -i ${BINNING_DIRECTORY} -c ${CLUSTERS} -o veba_output/classify/viral -p ${N_JOBS}" +CMD="source activate VEBA && veba --module classify-viral --params \"-i ${BINNING_DIRECTORY} -c ${CLUSTERS} -o veba_output/classify/viral -p ${N_JOBS}\"" # Either run this command or use SunGridEnginge/SLURM @@ -474,7 +455,6 @@ Prokaryotic classification is performed using `GTDB-Tk`. Classification can be **Recommended memory request:** `72 GB` -**Conda Environment:** `conda activate VEBA-classify_env` ``` N_JOBS=16 @@ -490,7 +470,7 @@ BINNING_DIRECTORY=veba_output/binning/prokaryotic CLUSTERS=veba_output/cluster/output/global/mags_to_slcs.tsv # Set up the command -CMD="source activate VEBA-classify_env && classify-prokaryotic.py -i ${BINNING_DIRECTORY} -c ${CLUSTERS} -p ${N_JOBS} -o veba_output/classify/prokaryotic" +CMD="source activate VEBA && veba --module classify-prokaryotic --params \"-i ${BINNING_DIRECTORY} -c ${CLUSTERS} -p ${N_JOBS} -o veba_output/classify/prokaryotic\"" # Either run this command or use SunGridEnginge/SLURM @@ -502,11 +482,10 @@ The following output files will produced: * taxonomy.clusters.tsv - Prokaryotic cluster classification (If --clusters are provided) #### 12. Classify eukaryotic genomes -*VEBA* is going to use the *MetaEuk/MMSEQS2* protein alignments based on [*VEBA's* microeukaryotic protein database](https://doi.org/10.6084/m9.figshare.19668855.v1). The default is to use [BUSCO's eukaryota_odb10](https://busco-data.ezlab.org/v5/data/lineages/eukaryota_odb10.2020-09-10.tar.gz) marker set but you can use the annotations from all proteins if you want by providing the `--include_all_genes` flag. The former will take a little bit longer since it needs to run *hmmsearch* but it's more robust and doesn't take that much longer. +*VEBA* is going to use the *MetaEuk/MMSEQS2* protein alignments based on [*VEBA's* MicroEuk100](https://zenodo.org/records/10139451). The default is to use [BUSCO's eukaryota_odb10](https://busco-data.ezlab.org/v5/data/lineages/eukaryota_odb10.2020-09-10.tar.gz) marker set but you can use the annotations from all proteins if you want by providing the `--include_all_genes` flag but that's not recommended for classification. **Recommended memory request:** `12 GB` -**Conda Environment:** `conda activate VEBA-classify_env` ``` # This is threaded if you use the default (i.e., core marker detection) @@ -522,7 +501,7 @@ BINNING_DIRECTORY=veba_output/binning/eukaryotic CLUSTERS=veba_output/cluster/output/global/mags_to_slcs.tsv # Set up the command -CMD="source activate VEBA-classify_env && classify-eukaryotic.py -i ${BINNING_DIRECTORY} -c ${CLUSTERS} -o veba_output/classify/eukaryotic -p ${N_JOBS}" +CMD="source activate VEBA && veba --module classify-eukaryotic --params \"-i ${BINNING_DIRECTORY} -c ${CLUSTERS} -o veba_output/classify/eukaryotic -p ${N_JOBS}\"" # Either run this command or use SunGridEnginge/SLURM @@ -539,9 +518,6 @@ Instead of having 3 separate classification tables, it would be much more useful **Recommended memory request:** `1 GB` - -**Conda Environment:** `conda activate VEBA-classify_env` - ``` merge_taxonomy_classifications.py -i veba_output/classify -o veba_output/classify ``` @@ -554,8 +530,6 @@ The following output files will produced: #### 14. Annotate proteins Now that all of the MAGs are recovered and classified, let's annotate the proteins using best-hit against UniRef,MiBIG,VFDB,CAZy Pfam, AntiFam, AMRFinder, and KOFAM. HMMSearch will fail with sequences ≥ 100k so we need to remove any that are that long (there probably aren't but just to be safe). -**Conda Environment:** `conda activate VEBA-annotate_env` - ``` # Let's merge all of the proteins. @@ -582,7 +556,7 @@ PROTEINS=veba_output/misc/all_genomes.all_proteins.lt100k.faa IDENTIFIER_MAPPING=veba_output/cluster/output/global/identifier_mapping.proteins.tsv.gz # Command -CMD="source activate VEBA-annotate_env && annotate.py -a ${PROTEINS} -i ${IDENTIFIER_MAPPING} -o veba_output/annotation -p ${N_JOBS} -u uniref50" +CMD="source activate VEBA && veba --module annotate --params \"-a ${PROTEINS} -i ${IDENTIFIER_MAPPING} -o veba_output/annotation -p ${N_JOBS} -u uniref50\"" # Either run this command or use SunGridEnginge/SLURM @@ -607,7 +581,7 @@ If you are restricted by resources or time you may want to do just annotate the PROTEINS=veba_output/cluster/output/global/representative_sequences.faa # Command -CMD="source activate VEBA-annotate_env && annotate.py -a ${PROTEINS} -o veba_output/annotation -p ${N_JOBS} -u uniref50" +CMD="source activate VEBA && veba --module annotate --params \"-a ${PROTEINS} -o veba_output/annotation -p ${N_JOBS} -u uniref50\"" ``` @@ -641,7 +615,7 @@ for i in $(seq -f "%03g" 1 ${N_PARTITIONS}); do N="annotate-${i}" rm -f logs/${N}.* FAA=${PARTITION_DIRECTORY}/stdin.part_${i}.fasta - CMD="source activate VEBA-annotate_env && annotate.py -a ${FAA} -o ${OUT_DIR}/${i} -p ${N_JOBS} -u uniref50" + CMD="source activate VEBA && veba --module annotate --params \"-a ${FAA} -o ${OUT_DIR}/${i} -p ${N_JOBS} -u uniref50\"" # Either run this command or use SunGridEnginge/SLURM diff --git a/walkthroughs/metabolic_profiling_de-novo_genomes.md b/walkthroughs/pathway_profiling_de-novo_genomes.md similarity index 91% rename from walkthroughs/metabolic_profiling_de-novo_genomes.md rename to walkthroughs/pathway_profiling_de-novo_genomes.md index fc10d50..52ce9c0 100644 --- a/walkthroughs/metabolic_profiling_de-novo_genomes.md +++ b/walkthroughs/pathway_profiling_de-novo_genomes.md @@ -1,4 +1,4 @@ -### Metabolic profiling of *de novo* genomes +### Pathway profiling of *de novo* genomes If you build a comprehensive database, you may want to use a read-based approach to functionally profile a large set of samples. This tutorial will show you how to build a custom HUMAnN database from your annotations and how to profile your samples where there is full accounting of reads and your genomes. What you'll end up with at the end of this is a merged taxonomy table, a custom HUMAnN annotation table, and HUMAnN profiles. @@ -14,8 +14,8 @@ _____________________________________________________ 3. Functional profiling using `HUMAnN` of custom database 4. Merge the tables -**Conda Environment:** `conda activate VEBA-profile_env` - +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. +_______________________________________________________ #### 1. Merge taxonomy from all domains @@ -64,7 +64,7 @@ do rm -f logs/${N}.* R1=veba_output/preprocess/${ID}/output/cleaned_1.fastq.gz R2=veba_output/preprocess/${ID}/output/cleaned_2.fastq.gz - CMD="source activate VEBA-profile_env && profile-pathway.py -1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -i ${UNIREF_ANNOTATIONS} -f ${FASTA}" + CMD="source activate VEBA && veba --module profile-pathway --params \"-1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -i ${UNIREF_ANNOTATIONS} -f ${FASTA}\"" # Either run this command or use SunGridEnginge/SLURM @@ -86,7 +86,7 @@ The following output files will produced for each sample: #### 4. Merge the tables ``` -merge_generalized_mapping.py -o veba_output/profiling/pathways/merged. humann_pathcoverage.tsv veba_output/profiling/pathways/*/output/humann_pathcoverage.tsv +merge_generalized_mapping.py -o veba_output/profiling/pathways/merged.humann_pathcoverage.tsv veba_output/profiling/pathways/*/output/humann_pathcoverage.tsv merge_generalized_mapping.py -o veba_output/profiling/pathways/merged.humann_pathabundance.tsv veba_output/profiling/pathways/*/output/humann_pathabundance.tsv diff --git a/walkthroughs/phylogenetic_inference.md b/walkthroughs/phylogenetic_inference.md index 6e7f4d7..7fbbe5b 100644 --- a/walkthroughs/phylogenetic_inference.md +++ b/walkthroughs/phylogenetic_inference.md @@ -12,6 +12,8 @@ _____________________________________________________ 1. Download the proteomes of similar organisms 2. Perform phylogenetic inference on proteomes +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. + _____________________________________________________ @@ -235,8 +237,6 @@ diatoms/SRR17458638__METABAT2__E.1__bin.3.faa Now that we have all of the files we need, we can perform phylogenetic inference using BUSCO's eukaryota_odb10 markers and score cutoffs. For eukaryotes, it's advised that you use the eukaryota_odb10 marker set because this is the core marker set used for classification. This isn't the case for prokaryotes and viruses. If you don't have enough resources to run maximum likelihood trees via *IQTREE2* then use `--no_iqtree`. -**Conda Environment:** `conda activate VEBA-phylogeny_env` - ``` # Set the number of threads @@ -260,7 +260,7 @@ MINIMUM_GENOMES_ALIGNED_RATIO=0.95 OUT_DIR=veba_output/phylogeny/diatoms # Directory -CMD="source activate VEBA-phylogeny_env && phylogeny.py -a ${PROTEINS} -o ${OUT_DIR} -p ${N_JOBS} -f name --no_iqtree -d ${HMM} -s ${SCORES} --minimum_genomes_aligned_ratio ${MINIMUM_GENOMES_ALIGNED_RATIO} +CMD="source activate VEBA && veba --module phylogeny --params \"-a ${PROTEINS} -o ${OUT_DIR} -p ${N_JOBS} -f name --no_iqtree -d ${HMM} -s ${SCORES} --minimum_genomes_aligned_ratio ${MINIMUM_GENOMES_ALIGNED_RATIO}\"" # Either run this command or use SunGridEnginge/SLURM ``` diff --git a/walkthroughs/read_mapping_and_counts_tables.md b/walkthroughs/read_mapping_and_counts_tables.md index 29ab766..a17f404 100644 --- a/walkthroughs/read_mapping_and_counts_tables.md +++ b/walkthroughs/read_mapping_and_counts_tables.md @@ -15,6 +15,8 @@ _____________________________________________________ 2. Map reads to global reference and create base counts tables 3. Merge the counts tables for all the samples +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. + _____________________________________________________ @@ -22,7 +24,6 @@ _____________________________________________________ Here we are going to concatenate all of the binned contigs (i.e., MAGs) and their respective gene models (i.e., GFF files) then index using `Bowtie2`. -**Conda Environment:** `conda activate VEBA-mapping_env` ``` @@ -44,7 +45,7 @@ ls veba_output/binning/*/*/output/genomes/*.gff > veba_output/misc/gene_models.l GENE_MODELS=veba_output/misc/gene_models.list # Set up command -CMD="source activate VEBA-mapping_env && index.py -r ${GENOMES} -g ${GENE_MODELS} -o veba_output/index/global/ -p ${N_JOBS}" +CMD="source activate VEBA && veba --module index --params \"-r ${GENOMES} -g ${GENE_MODELS} -o veba_output/index/global/ -p ${N_JOBS}\"" # Either run this command or use SunGridEnginge/SLURM ``` @@ -63,9 +64,18 @@ Here we are map all of the reads to the global reference and create base counts **Note:** Versions prior to v1.1.2 require the output directory to include the sample name. (e.g., `-o veba_output/mapping/global/${ID}` where `-n` is not used. In v1.1.2+, the output directory is automatic (e.g., `veba_output/mapping/global/` and `-n ${ID}` are used) -**Conda Environment:** `conda activate VEBA-mapping_env` ``` +# If you have run the cluster.py module you can use this: +SCAFFOLDS_TO_MAGS=veba_output/cluster/output/global/scaffolds_to_mags.tsv +SCAFFOLDS_TO_SLCS=veba_output/cluster/output/global/scaffolds_to_slcs.tsv +PROTEINS_TO_ORTHOGROUPS=veba_output/cluster/output/global/proteins_to_orthogroups.tsv +MAGS_TO_SLCS=veba_output/cluster/output/global/mags_to_slcs.tsv + +# If you skipped the clustering, you can oncatenate all of the scaffolds to bins from all of the domains +cat veba_output/binning/*/*/output/scaffolds_to_bins.tsv > veba_output/misc/all_genomes.scaffolds_to_mags.tsv +SCAFFOLDS_TO_MAGS=veba_output/misc/all_genomes.scaffolds_to_mags.tsv + # Set a lower number of threads since we are running for each sample N_JOBS=2 @@ -84,7 +94,7 @@ for ID in $(cat identifiers.list); do OUT_DIR=veba_output/mapping/global # Set up command - CMD="source activate VEBA-mapping_env && mapping.py -1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -x ${INDEX_DIRECTORY}" + CMD="source activate VEBA && veba --module mapping --params \"-1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -x ${INDEX_DIRECTORY} --scaffolds_to_bins ${SCAFFOLDS_TO_MAGS}\"" #--scaffolds_to_clusters ${SCAFFOLDS_TO_SLCS} --proteins_to_orthogroups ${PROTEINS_TO_ORTHOGROUPS} # Either run this command or use SunGridEnginge/SLURM @@ -111,16 +121,6 @@ MAPPING_DIRECTORY=veba_output/mapping/global # Set output directory (this is default) OUT_DIR=veba_output/counts -# If you have run the cluster.py module you can use this: -SCAFFOLDS_TO_MAGS=veba_output/cluster/output/global/scaffolds_to_mags.tsv -SCAFFOLDS_TO_SLCS=veba_output/cluster/output/global/scaffolds_to_slcs.tsv -#MAGS_TO_SLCS=veba_output/cluster/output/global/mags_to_slcs.tsv -PROTEINS_TO_ORTHOGROUPS=veba_output/cluster/output/global/proteins_to_orthogroups.tsv - -# If you skipped the clustering, you can oncatenate all of the scaffolds to bins from all of the domains -cat veba_output/binning/*/*/output/scaffolds_to_bins.tsv > veba_output/misc/all_genomes.scaffolds_to_mags.tsv -SCAFFOLDS_TO_MAGS=veba_output/misc/all_genomes.scaffolds_to_mags.tsv - # Merge contig-level counts (excu merge_contig_mapping.py -m ${MAPPING_DIRECTORY} -c ${MAGS_TO_SLCS} -i ${SCAFFOLDS_TO_MAGS} -o ${OUT_DIR} diff --git a/walkthroughs/recovering_viruses_from_metatranscriptomics.md b/walkthroughs/recovering_viruses_from_metatranscriptomics.md index 9890813..81a2035 100644 --- a/walkthroughs/recovering_viruses_from_metatranscriptomics.md +++ b/walkthroughs/recovering_viruses_from_metatranscriptomics.md @@ -15,9 +15,9 @@ _____________________________________________________ 4. Cluster genomes and proteins 5. Classify viral genomes -#### 1. Preprocess reads and get directory set up +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. -**Conda Environment:** `conda activate VEBA-preprocess_env` +#### 1. Preprocess reads and get directory set up Refer to the [downloading and preprocessing reads workflow](download_and_preprocess_reads.md). At this point, it's assumed you have the following: @@ -29,8 +29,6 @@ Refer to the [downloading and preprocessing reads workflow](download_and_preproc Here we are going to assemble all of the reads using `rnaSPAdes`. -**Conda Environment:** `conda activate VEBA-assembly_env` - ``` # Set the number of threads to use for each sample. Let's use 4 N_JOBS=4 @@ -53,7 +51,7 @@ for ID in $(cat identifiers.list); do R2=veba_output/preprocess/${ID}/output/cleaned_2.fastq.gz # Set up command - CMD="source activate VEBA-assembly_env && assembly.py -1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -P rnaspades.py" + CMD="source activate VEBA && veba --module assembly --params \"-1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -P rnaspades.py\"" # Either run this command or use SunGridEnginge/SLURM @@ -83,8 +81,6 @@ Where `g0` refers to the predicted gene and `i0` refers to the isoform transcrip #### 3. Recover viruses from metatranscriptomic assemblies We use a similar approach to the metagenomics with *geNomad* and *CheckV* but using the assembled transcripts instead. Again, the criteria for high-quality viral genomes are described by the [*CheckV* author](https://scholar.google.com/citations?user=gmKnjNQAAAAJ&hl=en) [here in this Bitbucket Issue (#38)](https://bitbucket.org/berkeleylab/checkv/issues/38/recommended-cutoffs-for-analyzing-checkv). -**Conda Environment:** `conda activate VEBA-binning-viral_env` - ``` N_JOBS=4 @@ -93,7 +89,7 @@ for ID in $(cat identifiers.list); rm -f logs/${N}.* FASTA=veba_output/transcript_assembly/${ID}/output/transcripts.fasta BAM=veba_output/transcript_assembly/${ID}/output/mapped.sorted.bam - CMD="source activate VEBA-binning-viral_env && binning-viral.py -f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -m 1500 -o veba_output/binning/viral -a genomad" + CMD="source activate VEBA && veba --module binning-viral --params \"-f ${FASTA} -b ${BAM} -n ${ID} -p ${N_JOBS} -m 1500 -o veba_output/binning/viral -a genomad\"" # Either run this command or use SunGridEnginge/SLURM @@ -123,8 +119,6 @@ for ID in $(cat identifiers.list); #### 4. Cluster genomes and proteins To analyze these data, we are going to generate some counts tables and we want a single set of features to compare across all samples. To achieve this, we are going to cluster the genomes into species-level clusters (SLC) and the proteins into SLC-specific protein clusters (SSPC). Further, this clustering is dual purpose as it alleviates some of the bias from [the curse(s) of dimensionality](https://www.nature.com/articles/s41592-018-0019-x) with dimensionality reduction via feature compression - [a type of feature engineering](https://towardsdatascience.com/what-is-feature-engineering-importance-tools-and-techniques-for-machine-learning-2080b0269f10). -**Conda Environment:** `conda activate VEBA-cluster_env` - ``` # We need to generate a table with the following fields: @@ -137,7 +131,7 @@ compile_genomes_table.py -i veba_output/binning/ > veba_output/misc/genomes_tabl N_JOBS=12 # Set up command -CMD="source activate VEBA-cluster_env && cluster.py -i veba_output/misc/genomes_table.tsv -o veba_output/cluster -p ${N_JOBS}" +CMD="source activate VEBA && veba --module cluster --params \"-i veba_output/misc/genomes_table.tsv -o veba_output/cluster -p ${N_JOBS}\"" # Either run this command or use SunGridEnginge/SLURM ``` @@ -173,9 +167,6 @@ CMD="source activate VEBA-cluster_env && cluster.py -i veba_output/misc/genomes_ #### 5. Classify viral genomes Viral classification is performed using `geNomad`. Classification can be performed using the intermediate binning results which is much quicker. Alternatively, if you have viruses identified elsewhere you can still classify using the `--genomes` argument instead. -**Conda Environment:** `conda activate VEBA-classify_env` - - ``` N=classify-viral @@ -188,7 +179,7 @@ CLUSTERS=veba_output/cluster/viral/output/clusters.tsv rm -rf logs/${N}.* # Set up the command -CMD="source activate VEBA-classify_env && classify-viral.py -i ${BINNING_DIRECTORY} -c ${CLUSTERS} -o veba_output/classify/viral" +CMD="source activate VEBA && veba --module classify-viral --params \"-i ${BINNING_DIRECTORY} -c ${CLUSTERS} -o veba_output/classify/viral\"" # Either run this command or use SunGridEnginge/SLURM diff --git a/walkthroughs/setting_up_coassemblies.md b/walkthroughs/setting_up_coassemblies.md index ebf7a8b..b922e9c 100644 --- a/walkthroughs/setting_up_coassemblies.md +++ b/walkthroughs/setting_up_coassemblies.md @@ -14,6 +14,9 @@ _____________________________________________________ 3. Coassembly using assembly.py 4. Align reads from each sample to the coassembly to create sorted BAM files that will be used for binning and counts tables. +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. +______________________________________________________ + #### 1. Concatenate forward and reverse reads separately Refer to the [downloading and preprocessing reads workflow](download_and_preprocess_reads.md). At this point, it's assumed you have the following: @@ -43,8 +46,6 @@ cat veba_output/preprocess/*/output/cleaned_2.fastq.gz > veba_output/misc/concat Here we are going to coassemble all of the reads using `metaSPAdes` which is default but if you are using metatranscriptomics then use `-P rnaSPAdes.py`. -**Conda Environment:** `conda activate VEBA-assembly_env` - ``` # Set the number of threads to use for each sample. Let's use 4 N_JOBS=4 @@ -67,10 +68,10 @@ R1=veba_output/misc/concatenated_1.fastq.gz R2=veba_output/misc/concatenated_2.fastq.gz # Set up command -CMD="source activate VEBA-assembly_env && assembly.py -1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS}" +CMD="source activate VEBA && veba --module assembly --params \"-1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS}\"" # Use this for metatranscriptomics -# CMD="source activate VEBA-assembly_env && assembly.py -1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -P rnaspades.py" +# CMD="source activate VEBA && veba --module assembly --params \"-1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -P rnaspades.py\"" # Either run this command or use SunGridEnginge/SLURM @@ -91,10 +92,6 @@ The main one we need is `scaffolds.fasta` which we will use for binning. Note #### 3. Align sample-specific reads to the coassembly - - -**Conda Environment:** `conda activate VEBA-assembly_env` - ``` N_JOBS=4 @@ -103,7 +100,7 @@ N="coverage__${ID}"; rm -f logs/${N}.* FASTA=veba_output/assembly/${ID}/output/scaffolds.fasta READS=veba_output/misc/reads_table.tsv -CMD="source activate VEBA-assembly_env && coverage.py -f ${FASTA} -r ${READS} -p ${N_JOBS} -m 1500 -o veba_output/coverage/${ID}" +CMD="source activate VEBA && veba --module coverage --params \"-f ${FASTA} -r ${READS} -p ${N_JOBS} -m 1500 -o veba_output/coverage/${ID}\"" # Either run this command or use SunGridEnginge/SLURM @@ -125,7 +122,7 @@ _____________________________________________________ Now that you have a coassembly and multiple sorted BAM files, it's time for binning. Start at step 3 of the [end-to-end metagenomics](end-to-end_metagenomics.md) or [recovering viruses from metatranscriptomics](recovering_viruses_from_metatranscriptomics.md) workflows depending on whether or not you have metagenomics or metatranscriptomics, respectively. -**Please do not forget to adapt the BAM argument in the `binning-prokaryotic.py` command to include all the sample-specific sorted BAM files and not the concatenated sorted BAM.** +**Please do not forget to adapt the BAM argument in the `binning-prokaryotic` command to include all the sample-specific sorted BAM files and not the concatenated sorted BAM.** More specifically, use `BAM="veba_output/coverage/coassembly/output/*/mapped.sorted.bam"` and not `BAM="veba_output/assembly/coassembly/output/mapped.sorted.bam"`. diff --git a/walkthroughs/taxonomic_profiling_de-novo_genomes.md b/walkthroughs/taxonomic_profiling_de-novo_genomes.md new file mode 100644 index 0000000..a2ae3d3 --- /dev/null +++ b/walkthroughs/taxonomic_profiling_de-novo_genomes.md @@ -0,0 +1,90 @@ +### Taxonomic profiling of *de novo* genomes +If you build a comprehensive database, you may want to use a read-based approach to taxonomicly profile a large set of samples. This tutorial will show you how to build a custom `Sylph` database from your genomes and how to profile your samples for taxonomic abundance. + +What you'll end up with at the end of this is a `Sylph` database and taxonomic abundance profiles. + +Please refer to the [end-to-end metagenomics](end-to-end_metagenomics.md) or [recovering viruses from metatranscriptomics](recovering_viruses_from_metatranscriptomics.md) workflows for details on binning, clustering, and annotation. + +_____________________________________________________ + +#### Steps: +1. Compile custom `Sylph` database from *de novo* genomes +2. Taxonomic profiling using `Sylph ` of custom database +3. Merge the tables + +**Conda Environment:** `conda activate VEBA`. Use this for intermediate scripts. +_______________________________________________________ + +#### 1. Compile custom `Sylph` database from *de novo* genomes + +At this point, it's assumed you have the following: + +* Clustering results from the `cluster.py` module +* A directory of preprocessed reads: `veba_output/preprocess/${ID}/output/cleaned_1.fastq.gz` and `veba_output/preprocess/${ID}/output/cleaned_2.fastq.gz` where `${ID}` represents the identifiers in `identifiers.list`. +* Genome assemblies. These can either be MAGs binned with VEBA, binned elsewhere, or even reference genomes you downloaded. + + +Here we are going to build 2 databases, one for viral genomes and one for non-viral genomes (i.e., prokaryotes and eukaryotes). The reason for 2 separate databases is because there are presets used for small genomes that are different than medium to large genomes. We need a table that has `[organism_type][path/to/genome.fa]` with no headers. We already have some version of this with the `veba_output/misc/genomes_table.tsv` we made for clustering. We can pipe this into stdin for the database build script: + + +``` +cat veba_output/misc/genomes_table.tsv | cut -f1,4 | compile_custom_sylph_sketch_database_from_genomes.py -o veba_output/profiling/databases +``` + +This generates 2 `Sylph` databases (assuming you have viruses and non-viruses): + +* `veba_output/profiling/databases/genome_database-nonviral.syldb` +* `veba_output/profiling/databases/genome_database-viral.syldb` + + +#### 2. Taxonomic profiling using `Sylph` of custom database + +Now it's time to profile the reads against the `Sylph` databases. Since `Sylph` takes in a sketch of reads, we can either use a precompute reads sketch with `-s` or with paired-end reads (`-1` and `-2`) to compute the sketch in the backend. + +``` +N_JOBS=4 +OUT_DIR=veba_output/profiling/taxonomy +DATABASES=veba_output/profiling/databases/*.syldb +MAGS_TO_SLCS=veba_output/cluster/output/global/mags_to_slcs.tsv # Assuming you have clustering results + +mkdir -p logs + +for ID in $(cat identifiers.list); +do + N="profile-taxonomy__${ID}"; + rm -f logs/${N}.* + R1=veba_output/preprocess/${ID}/output/cleaned_1.fastq.gz + R2=veba_output/preprocess/${ID}/output/cleaned_2.fastq.gz + CMD="source activate VEBA && veba --module profile-taxonomy --params \"-1 ${R1} -2 ${R2} -n ${ID} -o ${OUT_DIR} -p ${N_JOBS} -d ${DATABASES} -c ${MAGS_TO_SLCS}\"" + + # Either run this command or use SunGridEnginge/SLURM + +done + +``` + +The following output files will produced for each sample: + +* reads.sylsp - Reads sketch if paired-end reads were provided +* sylph\_profile.tsv.gz - Output of `sylph profile` +* taxonomic_abundance.tsv.gz - Genome-level taxonomic abundance (No header) +* taxonomic_abundance.clusters.tsv.gz - SLC-level taxonomic abundance (No header) + +#### 3. Merge the tables + +``` +merge_generalized_mapping.py -o veba_output/profiling/taxonomy/merged.taxonomic_abundance.tsv.gz veba_output/profiling/taxonomy/*/output/taxonomic_abundance.tsv.gz + +merge_generalized_mapping.py -o veba_output/profiling/taxonomy/merged.taxonomic_abundance.clusters.tsv.gz veba_output/profiling/taxonomy/*/output/taxonomic_abundance.clusters.tsv.gz +``` + +The following output files will produced for each sample: + +* merged.taxonomic\_abundance.tsv.gz - Merged genome-level taxonomic abundance matrix +* merged.taxonomic\_abundance.clusters.tsv.gz - Merged SLC-level taxonomic abundance matrix + +_____________________________________________________ + +#### Next steps: + +Subset stratified tables by their respective levels.

Wz+-sex-hthsl!+sgmfNhUM1ba4P@tYZ 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%0D+kW}tvE>N$y2C1)$3XvxsvgVI!&y) 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 proline Arginine and proline metabolism #8a3222 +M00028 Ornithine biosynthesis, glutamate => ornithine Arginine and proline metabolism #8a3222 +M00029 Urea cycle Arginine and proline metabolism #8a3222 +M00047 Creatine pathway Arginine and proline metabolism #8a3222 +M00763 Ornithine biosynthesis, mediated by LysW, glutamate => ornithine Arginine and proline metabolism #8a3222 +M00844 Arginine biosynthesis, ornithine => arginine Arginine and proline metabolism #8a3222 +M00845 Arginine biosynthesis, glutamate => acetylcitrulline => arginine Arginine and proline metabolism #8a3222 +M00879 Arginine succinyltransferase pathway, arginine => glutamate Arginine and proline metabolism #8a3222 +M00022 Shikimate pathway, phosphoenolpyruvate + erythrose-4P => chorismate Aromatic amino acid metabolism #8641b6 +M00023 Tryptophan biosynthesis, chorismate => tryptophan Aromatic amino acid metabolism #8641b6 +M00024 Phenylalanine biosynthesis, chorismate => phenylalanine Aromatic amino acid metabolism #8641b6 +M00025 Tyrosine biosynthesis, chorismate => tyrosine Aromatic amino acid metabolism #8641b6 +M00037 Melatonin biosynthesis, tryptophan => serotonin => melatonin Aromatic amino acid metabolism #8641b6 +M00038 Tryptophan metabolism, tryptophan => kynurenine => 2-aminomuconate Aromatic amino acid metabolism #8641b6 +M00040 Tyrosine biosynthesis, prephanate => pretyrosine => tyrosine Aromatic amino acid metabolism #8641b6 +M00042 Catecholamine biosynthesis, tyrosine => dopamine => noradrenaline => adrenaline Aromatic amino acid metabolism #8641b6 +M00043 Thyroid hormone biosynthesis, tyrosine => triiodothyronine--thyroxine Aromatic amino acid metabolism #8641b6 +M00044 Tyrosine degradation, tyrosine => homogentisate Aromatic amino acid metabolism #8641b6 +M00533 Homoprotocatechuate degradation, homoprotocatechuate => 2-oxohept-3-enedioate Aromatic amino acid metabolism #8641b6 +M00545 Trans-cinnamate degradation, trans-cinnamate => acetyl-CoA Aromatic amino acid metabolism #8641b6 +M00418 Toluene degradation, anaerobic, toluene => benzoyl-CoA Aromatics degradation #76d25b +M00419 Cymene degradation, p-cymene => p-cumate Aromatics degradation #76d25b +M00534 Naphthalene degradation, naphthalene => salicylate Aromatics degradation #76d25b +M00537 Xylene degradation, xylene => methylbenzoate Aromatics degradation #76d25b +M00538 Toluene degradation, toluene => benzoate Aromatics degradation #76d25b +M00539 Cumate degradation, p-cumate => 2-oxopent-4-enoate + 2-methylpropanoate Aromatics degradation #76d25b +M00540 Benzoate degradation, cyclohexanecarboxylic acid =>pimeloyl-CoA Aromatics degradation #76d25b +M00541 Benzoyl-CoA degradation, benzoyl-CoA => 3-hydroxypimeloyl-CoA Aromatics degradation #76d25b +M00543 Biphenyl degradation, biphenyl => 2-oxopent-4-enoate + benzoate Aromatics degradation #76d25b +M00544 Carbazole degradation, carbazole => 2-oxopent-4-enoate + anthranilate Aromatics degradation #76d25b +M00547 Benzene--toluene degradation, benzene => catechol -- toluene => 3-methylcatechol Aromatics degradation #76d25b +M00548 Benzene degradation, benzene => catechol Aromatics degradation #76d25b +M00551 Benzoate degradation, benzoate => catechol -- methylbenzoate => methylcatechol Aromatics degradation #76d25b +M00568 Catechol ortho-cleavage, catechol => 3-oxoadipate Aromatics degradation #76d25b +M00569 Catechol meta-cleavage, catechol => acetyl-CoA -- 4-methylcatechol => propanoyl-CoA Aromatics degradation #76d25b +M00623 Phthalate degradation 1, phthalate => protocatechuate Aromatics degradation #76d25b +M00624 Terephthalate degradation, terephthalate => 3,4-dihydroxybenzoate Aromatics degradation #76d25b +M00636 Phthalate degradation 2, phthalate => protocatechuate Aromatics degradation #76d25b +M00637 Anthranilate degradation, anthranilate => catechol Aromatics degradation #76d25b +M00638 Salicylate degradation, salicylate => gentisate Aromatics degradation #76d25b +M00878 Phenylacetate degradation, phenylaxetate => acetyl-CoA--succinyl-CoA Aromatics degradation #76d25b +M00142 NADH:ubiquinone oxidoreductase, mitochondria ATP synthesis #cdd346 +M00143 NADH dehydrogenase (ubiquinone) Fe-S protein--flavoprotein complex, mitochondria ATP synthesis #cdd346 +M00144 NADH:quinone oxidoreductase, prokaryotes ATP synthesis #cdd346 +M00145 NAD(P)H:quinone oxidoreductase, chloroplasts and cyanobacteria ATP synthesis #cdd346 +M00146 NADH dehydrogenase (ubiquinone) 1 alpha subcomplex ATP synthesis #cdd346 +M00147 NADH dehydrogenase (ubiquinone) 1 beta subcomplex ATP synthesis #cdd346 +M00148 Succinate dehydrogenase (ubiquinone) ATP synthesis #cdd346 +M00149 Succinate dehydrogenase, prokaryotes ATP synthesis #cdd346 +M00150 Fumarate reductase, prokaryotes ATP synthesis #cdd346 +M00151 Cytochrome bc1 complex respiratory unit ATP synthesis #cdd346 +M00152 Cytochrome bc1 complex ATP synthesis #cdd346 +M00153 Cytochrome bd ubiquinol oxidase ATP synthesis #cdd346 +M00154 Cytochrome c oxidase ATP synthesis #cdd346 +M00155 Cytochrome c oxidase, prokaryotes ATP synthesis #cdd346 +M00156 Cytochrome c oxidase, cbb3-type ATP synthesis #cdd346 +M00157 F-type ATPase, prokaryotes and chloroplasts ATP synthesis #cdd346 +M00158 F-type ATPase, eukaryotes ATP synthesis #cdd346 +M00159 V-type ATPase, prokaryotes ATP synthesis #cdd346 +M00160 V-type ATPase, eukaryotes ATP synthesis #cdd346 +M00162 Cytochrome b6f complex ATP synthesis #cdd346 +M00416 Cytochrome aa3-600 menaquinol oxidase ATP synthesis #cdd346 +M00417 Cytochrome o ubiquinol oxidase ATP synthesis #cdd346 +M00672 Penicillin biosynthesis, aminoadipate + cycteine + valine => penicillin Beta-Lactam biosynthesis #3b2882 +M00673 Cephamycin C biosynthesis, aminoadipate + cycteine + valine => cephamycin C Beta-Lactam biosynthesis #3b2882 +M00674 Clavaminate biosynthesis, arginine + glyceraldehyde-3P => clavaminate Beta-Lactam biosynthesis #3b2882 +M00675 Carbapenem-3-carboxylate biosynthesis, pyrroline-5-carboxylate + malonyl-CoA => carbapenem-3-carboxylate Beta-Lactam biosynthesis #3b2882 +M00736 Nocardicin A biosynthesis, L-pHPG + arginine + serine => nocardicin A Beta-Lactam biosynthesis #3b2882 +M00039 Monolignol biosynthesis, phenylalanine--tyrosine => monolignol Biosynthesis of other secondary metabolites #cbde82 +M00137 Flavanone biosynthesis, phenylalanine => naringenin Biosynthesis of other secondary metabolites #cbde82 +M00138 Flavonoid biosynthesis, naringenin => pelargonidin Biosynthesis of other secondary metabolites #cbde82 +M00370 Glucosinolate biosynthesis, tryptophan => glucobrassicin Biosynthesis of other secondary metabolites #cbde82 +M00661 Paspaline biosynthesis, geranylgeranyl-PP + indoleglycerol phosphate => paspaline Biosynthesis of other secondary metabolites #cbde82 +M00785 Cycloserine biosynthesis, arginine--serine => cycloserine Biosynthesis of other secondary metabolites #cbde82 +M00786 Fumitremorgin alkaloid biosynthesis, tryptophan + proline => fumitremorgin C--A Biosynthesis of other secondary metabolites #cbde82 +M00787 Bacilysin biosynthesis, prephenate => bacilysin Biosynthesis of other secondary metabolites #cbde82 +M00788 Terpentecin biosynthesis, GGAP => terpentecin Biosynthesis of other secondary metabolites #cbde82 +M00789 Rebeccamycin biosynthesis, tryptophan => rebeccamycin Biosynthesis of other secondary metabolites #cbde82 +M00790 Pyrrolnitrin biosynthesis, tryptophan => pyrrolnitrin Biosynthesis of other secondary metabolites #cbde82 +M00805 Staurosporine biosynthesis, tryptophan => staurosporine Biosynthesis of other secondary metabolites #cbde82 +M00808 Violacein biosynthesis, tryptophan => violacein Biosynthesis of other secondary metabolites #cbde82 +M00814 Acarbose biosynthesis, sedoheptulopyranose-7P => acarbose Biosynthesis of other secondary metabolites #cbde82 +M00815 Validamycin A biosynthesis, sedoheptulopyranose-7P => validamycin A Biosynthesis of other secondary metabolites #cbde82 +M00819 Pentalenolactone biosynthesis, farnesyl-PP => pentalenolactone Biosynthesis of other secondary metabolites #cbde82 +M00835 Pyocyanine biosynthesis, chorismate => pyocyanine Biosynthesis of other secondary metabolites #cbde82 +M00837 Prodigiosin biosynthesis, L-proline => prodigiosin Biosynthesis of other secondary metabolites #cbde82 +M00838 Undecylprodigiosin biosynthesis, L-proline => undecylprodigiosin Biosynthesis of other secondary metabolites #cbde82 +M00848 Aurachin biosynthesis, anthranilate => aurachin A Biosynthesis of other secondary metabolites #cbde82 +M00875 Staphyloferrin B biosynthesis, L-serine => staphyloferrin B Biosynthesis of other secondary metabolites #cbde82 +M00876 Staphyloferrin A biosynthesis, L-ornithine => staphyloferrin A Biosynthesis of other secondary metabolites #cbde82 +M00877 Kanosamine biosynthesis glucose 6-phosphate => kanosamine Biosynthesis of other secondary metabolites #cbde82 +M00019 Valine--isoleucine biosynthesis, pyruvate => valine -- 2-oxobutanoate => isoleucine Branched-chain amino acid metabolism #656cdb +M00036 Leucine degradation, leucine => acetoacetate + acetyl-CoA Branched-chain amino acid metabolism #656cdb +M00432 Leucine biosynthesis, 2-oxoisovalerate => 2-oxoisocaproate Branched-chain amino acid metabolism #656cdb +M00535 Isoleucine biosynthesis, pyruvate => 2-oxobutanoate Branched-chain amino acid metabolism #656cdb +M00570 Isoleucine biosynthesis, threonine => 2-oxobutanoate => isoleucine Branched-chain amino acid metabolism #656cdb +M00165 Reductive pentose phosphate cycle (Calvin cycle) Carbon fixation #408937 +M00166 Reductive pentose phosphate cycle, ribulose-5P => glyceraldehyde-3P Carbon fixation #408937 +M00167 Reductive pentose phosphate cycle, glyceraldehyde-3P => ribulose-5P Carbon fixation #408937 +M00168 CAM (Crassulacean acid metabolism), dark Carbon fixation #408937 +M00169 CAM (Crassulacean acid metabolism), light Carbon fixation #408937 +M00170 C4-dicarboxylic acid cycle, phosphoenolpyruvate carboxykinase type Carbon fixation #408937 +M00171 C4-dicarboxylic acid cycle, NAD - malic enzyme type Carbon fixation #408937 +M00172 C4-dicarboxylic acid cycle, NADP - malic enzyme type Carbon fixation #408937 +M00173 Reductive citrate cycle (Arnon-Buchanan cycle) Carbon fixation #408937 +M00374 Dicarboxylate-hydroxybutyrate cycle Carbon fixation #408937 +M00375 Hydroxypropionate-hydroxybutylate cycle Carbon fixation #408937 +M00376 3-Hydroxypropionate bi-cycle Carbon fixation #408937 +M00377 Reductive acetyl-CoA pathway (Wood-Ljungdahl pathway) Carbon fixation #408937 +M00579 Phosphate acetyltransferase-acetate kinase pathway, acetyl-CoA => acetate Carbon fixation #408937 +M00620 Incomplete reductive citrate cycle, acetyl-CoA => oxoglutarate Carbon fixation #408937 +M00001 Glycolysis (Embden-Meyerhof pathway), glucose => pyruvate Central carbohydrate metabolism #c644a5 +M00002 Glycolysis, core module involving three-carbon compounds Central carbohydrate metabolism #c644a5 +M00003 Gluconeogenesis, oxaloacetate => fructose-6P Central carbohydrate metabolism #c644a5 +M00004 Pentose phosphate pathway (Pentose phosphate cycle) Central carbohydrate metabolism #c644a5 +M00005 PRPP biosynthesis, ribose 5P => PRPP Central carbohydrate metabolism #c644a5 +M00006 Pentose phosphate pathway, oxidative phase, glucose 6P => ribulose 5P Central carbohydrate metabolism #c644a5 +M00007 Pentose phosphate pathway, non-oxidative phase, fructose 6P => ribose 5P Central carbohydrate metabolism #c644a5 +M00008 Entner-Doudoroff pathway, glucose-6P => glyceraldehyde-3P + pyruvate Central carbohydrate metabolism #c644a5 +M00009 Citrate cycle (TCA cycle, Krebs cycle) Central carbohydrate metabolism #c644a5 +M00010 Citrate cycle, first carbon oxidation, oxaloacetate => 2-oxoglutarate Central carbohydrate metabolism #c644a5 +M00011 Citrate cycle, second carbon oxidation, 2-oxoglutarate => oxaloacetate Central carbohydrate metabolism #c644a5 +M00307 Pyruvate oxidation, pyruvate => acetyl-CoA Central carbohydrate metabolism #c644a5 +M00308 Semi-phosphorylative Entner-Doudoroff pathway, gluconate => glycerate-3P Central carbohydrate metabolism #c644a5 +M00309 Non-phosphorylative Entner-Doudoroff pathway, gluconate--galactonate => glycerate Central carbohydrate metabolism #c644a5 +M00580 Pentose phosphate pathway, archaea, fructose 6P => ribose 5P Central carbohydrate metabolism #c644a5 +M00633 Semi-phosphorylative Entner-Doudoroff pathway, gluconate--galactonate => glycerate-3P Central carbohydrate metabolism #c644a5 +M00112 Tocopherol--tocotorienol biosynthesis Cofactor and vitamin metabolism #5fda98 +M00115 NAD biosynthesis, aspartate => NAD Cofactor and vitamin metabolism #5fda98 +M00116 Menaquinone biosynthesis, chorismate => menaquinol Cofactor and vitamin metabolism #5fda98 +M00117 Ubiquinone biosynthesis, prokaryotes, chorismate => ubiquinone Cofactor and vitamin metabolism #5fda98 +M00119 Pantothenate biosynthesis, valine--L-aspartate => pantothenate Cofactor and vitamin metabolism #5fda98 +M00120 Coenzyme A biosynthesis, pantothenate => CoA Cofactor and vitamin metabolism #5fda98 +M00121 Heme biosynthesis, plants and bacteria, glutamate => heme Cofactor and vitamin metabolism #5fda98 +M00122 Cobalamin biosynthesis, cobinamide => cobalamin Cofactor and vitamin metabolism #5fda98 +M00123 Biotin biosynthesis, pimeloyl-ACP--CoA => biotin Cofactor and vitamin metabolism #5fda98 +M00124 Pyridoxal biosynthesis, erythrose-4P => pyridoxal-5P Cofactor and vitamin metabolism #5fda98 +M00125 Riboflavin biosynthesis, GTP => riboflavin--FMN--FAD Cofactor and vitamin metabolism #5fda98 +M00126 Tetrahydrofolate biosynthesis, GTP => THF Cofactor and vitamin metabolism #5fda98 +M00127 Thiamine biosynthesis, AIR => thiamine-P--thiamine-2P Cofactor and vitamin metabolism #5fda98 +M00128 Ubiquinone biosynthesis, eukaryotes, 4-hydroxybenzoate => ubiquinone Cofactor and vitamin metabolism #5fda98 +M00140 C1-unit interconversion, prokaryotes Cofactor and vitamin metabolism #5fda98 +M00141 C1-unit interconversion, eukaryotes Cofactor and vitamin metabolism #5fda98 +M00572 Pimeloyl-ACP biosynthesis, BioC-BioH pathway, malonyl-ACP => pimeloyl-ACP Cofactor and vitamin metabolism #5fda98 +M00573 Biotin biosynthesis, BioI pathway, long-chain-acyl-ACP => pimeloyl-ACP => biotin Cofactor and vitamin metabolism #5fda98 +M00577 Biotin biosynthesis, BioW pathway, pimelate => pimeloyl-CoA => biotin Cofactor and vitamin metabolism #5fda98 +M00622 Nicotinate degradation, nicotinate => fumarate Cofactor and vitamin metabolism #5fda98 +M00810 Nicotine degradation, pyridine pathway, nicotine => 2,6-dihydroxypyridine--succinate semialdehyde Cofactor and vitamin metabolism #5fda98 +M00811 Nicotine degradation, pyrrolidine pathway, nicotine => succinate semialdehyde Cofactor and vitamin metabolism #5fda98 +M00836 Coenzyme F430 biosynthesis, sirohydrochlorin => coenzyme F430 Cofactor and vitamin metabolism #5fda98 +M00840 Tetrahydrofolate biosynthesis, mediated by ribA and trpF, GTP => THF Cofactor and vitamin metabolism #5fda98 +M00841 Tetrahydrofolate biosynthesis, mediated by PTPS, GTP => THF Cofactor and vitamin metabolism #5fda98 +M00842 Tetrahydrobiopterin biosynthesis, GTP => BH4 Cofactor and vitamin metabolism #5fda98 +M00843 L-threo-Tetrahydrobiopterin biosynthesis, GTP => L-threo-BH4 Cofactor and vitamin metabolism #5fda98 +M00846 Siroheme biosynthesis, glutamate => siroheme Cofactor and vitamin metabolism #5fda98 +M00847 Heme biosynthesis, archaea, siroheme => heme Cofactor and vitamin metabolism #5fda98 +M00868 Heme biosynthesis, animals and fungi, glycine => heme Cofactor and vitamin metabolism #5fda98 +M00880 Molybdenum cofactor biosynthesis, GTP => molybdenum cofactor Cofactor and vitamin metabolism #5fda98 +M00017 Methionine biosynthesis, apartate => homoserine => methionine Cysteine and methionine metabolism #782975 +M00021 Cysteine biosynthesis, serine => cysteine Cysteine and methionine metabolism #782975 +M00034 Methionine salvage pathway Cysteine and methionine metabolism #782975 +M00035 Methionine degradation Cysteine and methionine metabolism #782975 +M00338 Cysteine biosynthesis, homocysteine + serine => cysteine Cysteine and methionine metabolism #782975 +M00368 Ethylene biosynthesis, methionine => ethylene Cysteine and methionine metabolism #782975 +M00609 Cysteine biosynthesis, methionine => cysteine Cysteine and methionine metabolism #782975 +M00625 Methicillin resistance Drug resistance #869534 +M00627 beta-Lactam resistance, Bla system Drug resistance #869534 +M00639 Multidrug resistance, efflux pump MexCD-OprJ Drug resistance #869534 +M00641 Multidrug resistance, efflux pump MexEF-OprN Drug resistance #869534 +M00642 Multidrug resistance, efflux pump MexJK-OprM Drug resistance #869534 +M00643 Multidrug resistance, efflux pump MexXY-OprM Drug resistance #869534 +M00649 Multidrug resistance, efflux pump AdeABC Drug resistance #869534 +M00651 Vancomycin resistance, D-Ala-D-Lac type Drug resistance #869534 +M00652 Vancomycin resistance, D-Ala-D-Ser type Drug resistance #869534 +M00696 Multidrug resistance, efflux pump AcrEF-TolC Drug resistance #869534 +M00697 Multidrug resistance, efflux pump MdtEF-TolC Drug resistance #869534 +M00698 Multidrug resistance, efflux pump BpeEF-OprC Drug resistance #869534 +M00700 Multidrug resistance, efflux pump AbcA Drug resistance #869534 +M00702 Multidrug resistance, efflux pump NorB Drug resistance #869534 +M00704 Tetracycline resistance, efflux pump Tet38 Drug resistance #869534 +M00705 Multidrug resistance, efflux pump MepA Drug resistance #869534 +M00714 Multidrug resistance, efflux pump QacA Drug resistance #869534 +M00718 Multidrug resistance, efflux pump MexAB-OprM Drug resistance #869534 +M00725 Cationic antimicrobial peptide (CAMP) resistance, dltABCD operon Drug resistance #869534 +M00726 Cationic antimicrobial peptide (CAMP) resistance, lysyl-phosphatidylglycerol (L-PG) synthase MprF Drug resistance #869534 +M00730 Cationic antimicrobial peptide (CAMP) resistance, VraFG transporter Drug resistance #869534 +M00744 Cationic antimicrobial peptide (CAMP) resistance, protease PgtE Drug resistance #869534 +M00745 Imipenem resistance, repression of porin OprD Drug resistance #869534 +M00746 Multidrug resistance, repression of porin OmpF Drug resistance #869534 +M00769 Multidrug resistance, efflux pump MexPQ-OpmE Drug resistance #869534 +M00851 Carbapenem resistance Drug resistance #869534 +M00824 9-membered enediyne core biosynthesis, malonyl-CoA => 3-hydroxyhexadeca-4,6,8,10,12,14-hexaenoyl-ACP => 9-membered enediyne core Enediyne biosynthesis #d27bde +M00825 10-membered enediyne core biosynthesis, malonyl-CoA => 3-hydroxyhexadeca-4,6,8,10,12,14-hexaenoyl-ACP => 10-membered enediyne core Enediyne biosynthesis #d27bde +M00826 C-1027 benzoxazolinate moiety biosynthesis, chorismate => benzoxazolinyl-CoA Enediyne biosynthesis #d27bde +M00827 C-1027 beta-amino acid moiety biosynthesis, tyrosine => 3-chloro-4,5-dihydroxy-beta-phenylalanyl-PCP Enediyne biosynthesis #d27bde +M00828 Maduropeptin beta-hydroxy acid moiety biosynthesis, tyrosine => 3-(4-hydroxyphenyl)-3-oxopropanoyl-PCP Enediyne biosynthesis #d27bde +M00829 3,6-Dimethylsalicylyl-CoA biosynthesis, malonyl-CoA => 6-methylsalicylate => 3,6-dimethylsalicylyl-CoA Enediyne biosynthesis #d27bde +M00830 Neocarzinostatin naphthoate moiety biosynthesis, malonyl-CoA => 2-hydroxy-5-methyl-1-naphthoate => 2-hydroxy-7-methoxy-5-methyl-1-naphthoyl-CoA Enediyne biosynthesis #d27bde +M00831 Kedarcidin 2-hydroxynaphthoate moiety biosynthesis, malonyl-CoA => 3,6,8-trihydroxy-2-naphthoate => 3-hydroxy-7,8-dimethoxy-6-isopropoxy-2-naphthoyl-CoA Enediyne biosynthesis #d27bde +M00832 Kedarcidin 2-aza-3-chloro-beta-tyrosine moiety biosynthesis, azatyrosine => 2-aza-3-chloro-beta-tyrosyl-PCP Enediyne biosynthesis #d27bde +M00833 Calicheamicin biosynthesis, calicheamicinone => calicheamicin Enediyne biosynthesis #d27bde +M00834 Calicheamicin orsellinate moiety biosynthesis, malonyl-CoA => orsellinate-ACP => 5-iodo-2,3-dimethoxyorsellinate-ACP Enediyne biosynthesis #d27bde +M00082 Fatty acid biosynthesis, initiation Fatty acid metabolism #d9a344 +M00083 Fatty acid biosynthesis, elongation Fatty acid metabolism #d9a344 +M00085 Fatty acid elongation in mitochondria Fatty acid metabolism #d9a344 +M00086 beta-Oxidation, acyl-CoA synthesis Fatty acid metabolism #d9a344 +M00087 beta-Oxidation Fatty acid metabolism #d9a344 +M00415 Fatty acid elongation in endoplasmic reticulum Fatty acid metabolism #d9a344 +M00861 beta-Oxidation, peroxisome, VLCFA Fatty acid metabolism #d9a344 +M00873 Fatty acid biosynthesis in mitochondria, animals Fatty acid metabolism #d9a344 +M00874 Fatty acid biosynthesis in mitochondria, fungi Fatty acid metabolism #d9a344 +M00055 N-glycan precursor biosynthesis Glycan biosynthesis #588cd6 +M00056 O-glycan biosynthesis, mucin type core Glycan biosynthesis #588cd6 +M00065 GPI-anchor biosynthesis, core oligosaccharide Glycan biosynthesis #588cd6 +M00068 Glycosphingolipid biosynthesis, globo-series, LacCer => Gb4Cer Glycan biosynthesis #588cd6 +M00069 Glycosphingolipid biosynthesis, ganglio series, LacCer => GT3 Glycan biosynthesis #588cd6 +M00070 Glycosphingolipid biosynthesis, lacto-series, LacCer => Lc4Cer Glycan biosynthesis #588cd6 +M00071 Glycosphingolipid biosynthesis, neolacto-series, LacCer => nLc4Cer Glycan biosynthesis #588cd6 +M00072 N-glycosylation by oligosaccharyltransferase Glycan biosynthesis #588cd6 +M00073 N-glycan precursor trimming Glycan biosynthesis #588cd6 +M00074 N-glycan biosynthesis, high-mannose type Glycan biosynthesis #588cd6 +M00075 N-glycan biosynthesis, complex type Glycan biosynthesis #588cd6 +M00872 O-glycan biosynthesis, mannose type (core M3) Glycan biosynthesis #588cd6 +M00057 Glycosaminoglycan biosynthesis, linkage tetrasaccharide Glycosaminoglycan metabolism #d66432 +M00058 Glycosaminoglycan biosynthesis, chondroitin sulfate backbone Glycosaminoglycan metabolism #d66432 +M00059 Glycosaminoglycan biosynthesis, heparan sulfate backbone Glycosaminoglycan metabolism #d66432 +M00076 Dermatan sulfate degradation Glycosaminoglycan metabolism #d66432 +M00077 Chondroitin sulfate degradation Glycosaminoglycan metabolism #d66432 +M00078 Heparan sulfate degradation Glycosaminoglycan metabolism #d66432 +M00079 Keratan sulfate degradation Glycosaminoglycan metabolism #d66432 +M00026 Histidine biosynthesis, PRPP => histidine Histidine metabolism #66d7bf +M00045 Histidine degradation, histidine => N-formiminoglutamate => glutamate Histidine metabolism #66d7bf +M00066 Lactosylceramide biosynthesis Lipid metabolism #d53e55 +M00067 Sulfoglycolipids biosynthesis, ceramide--1-alkyl-2-acylglycerol => sulfatide--seminolipid Lipid metabolism #d53e55 +M00088 Ketone body biosynthesis, acetyl-CoA => acetoacetate--3-hydroxybutyrate--acetone Lipid metabolism #d53e55 +M00089 Triacylglycerol biosynthesis Lipid metabolism #d53e55 +M00090 Phosphatidylcholine (PC) biosynthesis, choline => PC Lipid metabolism #d53e55 +M00091 Phosphatidylcholine (PC) biosynthesis, PE => PC Lipid metabolism #d53e55 +M00092 Phosphatidylethanolamine (PE) biosynthesis, ethanolamine => PE Lipid metabolism #d53e55 +M00093 Phosphatidylethanolamine (PE) biosynthesis, PA => PS => PE Lipid metabolism #d53e55 +M00094 Ceramide biosynthesis Lipid metabolism #d53e55 +M00098 Acylglycerol degradation Lipid metabolism #d53e55 +M00099 Sphingosine biosynthesis Lipid metabolism #d53e55 +M00100 Sphingosine degradation Lipid metabolism #d53e55 +M00113 Jasmonic acid biosynthesis Lipid metabolism #d53e55 +M00060 KDO2-lipid A biosynthesis, Raetz pathway, LpxL-LpxM type Lipopolysaccharide metabolism #83d2de +M00063 CMP-KDO biosynthesis Lipopolysaccharide metabolism #83d2de +M00064 ADP-L-glycero-D-manno-heptose biosynthesis Lipopolysaccharide metabolism #83d2de +M00866 KDO2-lipid A biosynthesis, Raetz pathway, non-LpxL-LpxM type Lipopolysaccharide metabolism #83d2de +M00867 KDO2-lipid A modification pathway Lipopolysaccharide metabolism #83d2de +M00016 Lysine biosynthesis, succinyl-DAP pathway, aspartate => lysine Lysine metabolism #d84e8b +M00030 Lysine biosynthesis, AAA pathway, 2-oxoglutarate => 2-aminoadipate => lysine Lysine metabolism #d84e8b +M00031 Lysine biosynthesis, mediated by LysW, 2-aminoadipate => lysine Lysine metabolism #d84e8b +M00032 Lysine degradation, lysine => saccharopine => acetoacetyl-CoA Lysine metabolism #d84e8b +M00433 Lysine biosynthesis, 2-oxoglutarate => 2-oxoadipate Lysine metabolism #d84e8b +M00525 Lysine biosynthesis, acetyl-DAP pathway, aspartate => lysine Lysine metabolism #d84e8b +M00526 Lysine biosynthesis, DAP dehydrogenase pathway, aspartate => lysine Lysine metabolism #d84e8b +M00527 Lysine biosynthesis, DAP aminotransferase pathway, aspartate => lysine Lysine metabolism #d84e8b +M00773 Tylosin biosynthesis, methylmalonyl-CoA + malonyl-CoA => tylactone => tylosin Macrolide biosynthesis #2e4b26 +M00774 Erythromycin biosynthesis, propanoyl-CoA + methylmalonyl-CoA => deoxyerythronolide B => erythromycin A--B Macrolide biosynthesis #2e4b26 +M00775 Oleandomycin biosynthesis, malonyl-CoA + methylmalonyl-CoA => 8,8a-deoxyoleandolide => oleandomycin Macrolide biosynthesis #2e4b26 +M00776 Pikromycin--methymycin biosynthesis, methylmalonyl-CoA + malonyl-CoA => narbonolide--10-deoxymethynolide => pikromycin--methymycin Macrolide biosynthesis #2e4b26 +M00777 Avermectin biosynthesis, 2-methylbutanoyl-CoA--isobutyryl-CoA => 6,8a-Seco-6,8a-deoxy-5-oxoavermectin 1a--1b aglycone => avermectin A1a--B1a--A1b--B1b Macrolide biosynthesis #2e4b26 +M00611 Oxygenic photosynthesis in plants and cyanobacteria Metabolic capacity #9378c3 +M00612 Anoxygenic photosynthesis in purple bacteria Metabolic capacity #9378c3 +M00613 Anoxygenic photosynthesis in green nonsulfur bacteria Metabolic capacity #9378c3 +M00614 Anoxygenic photosynthesis in green sulfur bacteria Metabolic capacity #9378c3 +M00615 Nitrate assimilation Metabolic capacity #9378c3 +M00616 Sulfate-sulfur assimilation Metabolic capacity #9378c3 +M00617 Methanogen Metabolic capacity #9378c3 +M00618 Acetogen Metabolic capacity #9378c3 +M00174 Methane oxidation, methanotroph, methane => formaldehyde Methane metabolism #9e7336 +M00344 Formaldehyde assimilation, xylulose monophosphate pathway Methane metabolism #9e7336 +M00345 Formaldehyde assimilation, ribulose monophosphate pathway Methane metabolism #9e7336 +M00346 Formaldehyde assimilation, serine pathway Methane metabolism #9e7336 +M00356 Methanogenesis, methanol => methane Methane metabolism #9e7336 +M00357 Methanogenesis, acetate => methane Methane metabolism #9e7336 +M00358 Coenzyme M biosynthesis Methane metabolism #9e7336 +M00378 F420 biosynthesis Methane metabolism #9e7336 +M00422 Acetyl-CoA pathway, CO2 => acetyl-CoA Methane metabolism #9e7336 +M00563 Methanogenesis, methylamine--dimethylamine--trimethylamine => methane Methane metabolism #9e7336 +M00567 Methanogenesis, CO2 => methane Methane metabolism #9e7336 +M00608 2-Oxocarboxylic acid chain extension, 2-oxoglutarate => 2-oxoadipate => 2-oxopimelate => 2-oxosuberate Methane metabolism #9e7336 +M00175 Nitrogen fixation, nitrogen => ammonia Nitrogen metabolism #2c2351 +M00528 Nitrification, ammonia => nitrite Nitrogen metabolism #2c2351 +M00529 Denitrification, nitrate => nitrogen Nitrogen metabolism #2c2351 +M00530 Dissimilatory nitrate reduction, nitrate => ammonia Nitrogen metabolism #2c2351 +M00531 Assimilatory nitrate reduction, nitrate => ammonia Nitrogen metabolism #2c2351 +M00804 Complete nitrification, comammox, ammonia => nitrite => nitrate Nitrogen metabolism #2c2351 +M00027 GABA (gamma-Aminobutyrate) shunt Other amino acid metabolism #c5d7a9 +M00118 Glutathione biosynthesis, glutamate => glutathione Other amino acid metabolism #c5d7a9 +M00369 Cyanogenic glycoside biosynthesis, tyrosine => dhurrin Other amino acid metabolism #c5d7a9 +M00012 Glyoxylate cycle Other carbohydrate metabolism #872b4e +M00013 Malonate semialdehyde pathway, propanoyl-CoA => acetyl-CoA Other carbohydrate metabolism #872b4e +M00014 Glucuronate pathway (uronate pathway) Other carbohydrate metabolism #872b4e +M00061 D-Glucuronate degradation, D-glucuronate => pyruvate + D-glyceraldehyde 3P Other carbohydrate metabolism #872b4e +M00081 Pectin degradation Other carbohydrate metabolism #872b4e +M00114 Ascorbate biosynthesis, plants, glucose-6P => ascorbate Other carbohydrate metabolism #872b4e +M00129 Ascorbate biosynthesis, animals, glucose-1P => ascorbate Other carbohydrate metabolism #872b4e +M00130 Inositol phosphate metabolism, PI=> PIP2 => Ins(1,4,5)P3 => Ins(1,3,4,5)P4 Other carbohydrate metabolism #872b4e +M00131 Inositol phosphate metabolism, Ins(1,3,4,5)P4 => Ins(1,3,4)P3 => myo-inositol Other carbohydrate metabolism #872b4e +M00132 Inositol phosphate metabolism, Ins(1,3,4)P3 => phytate Other carbohydrate metabolism #872b4e +M00373 Ethylmalonyl pathway Other carbohydrate metabolism #872b4e +M00532 Photorespiration Other carbohydrate metabolism #872b4e +M00549 Nucleotide sugar biosynthesis, glucose => UDP-glucose Other carbohydrate metabolism #872b4e +M00550 Ascorbate degradation, ascorbate => D-xylulose-5P Other carbohydrate metabolism #872b4e +M00552 D-galactonate degradation, De Ley-Doudoroff pathway, D-galactonate => glycerate-3P Other carbohydrate metabolism #872b4e +M00554 Nucleotide sugar biosynthesis, galactose => UDP-galactose Other carbohydrate metabolism #872b4e +M00565 Trehalose biosynthesis, D-glucose 1P => trehalose Other carbohydrate metabolism #872b4e +M00630 D-Galacturonate degradation (fungi), D-galacturonate => glycerol Other carbohydrate metabolism #872b4e +M00631 D-Galacturonate degradation (bacteria), D-galacturonate => pyruvate + D-glyceraldehyde 3P Other carbohydrate metabolism #872b4e +M00632 Galactose degradation, Leloir pathway, galactose => alpha-D-glucose-1P Other carbohydrate metabolism #872b4e +M00740 Methylaspartate cycle Other carbohydrate metabolism #872b4e +M00741 Propanoyl-CoA metabolism, propanoyl-CoA => succinyl-CoA Other carbohydrate metabolism #872b4e +M00761 Undecaprenylphosphate alpha-L-Ara4N biosynthesis, UDP-GlcA => undecaprenyl phosphate alpha-L-Ara4N Other carbohydrate metabolism #872b4e +M00854 Glycogen biosynthesis, glucose-1P => glycogen--starch Other carbohydrate metabolism #872b4e +M00855 Glycogen degradation, glycogen => glucose-6P Other carbohydrate metabolism #872b4e +M00097 beta-Carotene biosynthesis, GGAP => beta-carotene Other terpenoid biosynthesis #6e9368 +M00371 Castasterone biosynthesis, campesterol => castasterone Other terpenoid biosynthesis #6e9368 +M00372 Abscisic acid biosynthesis, beta-carotene => abscisic acid Other terpenoid biosynthesis #6e9368 +M00363 EHEC pathogenicity signature, Shiga toxin Pathogenicity #66406d +M00542 EHEC--EPEC pathogenicity signature, T3SS and effectors Pathogenicity #66406d +M00564 Helicobacter pylori pathogenicity signature, cagA pathogenicity island Pathogenicity #66406d +M00574 Pertussis pathogenicity signature, pertussis toxin Pathogenicity #66406d +M00575 Pertussis pathogenicity signature, T1SS Pathogenicity #66406d +M00576 ETEC pathogenicity signature, heat-labile and heat-stable enterotoxins Pathogenicity #66406d +M00850 Vibrio cholerae pathogenicity signature, cholera toxins Pathogenicity #66406d +M00852 Vibrio cholerae pathogenicity signature, toxin coregulated pilus Pathogenicity #66406d +M00853 ETEC pathogenicity signature, colonization factors Pathogenicity #66406d +M00856 Salmonella enterica pathogenicity signature, typhoid toxin Pathogenicity #66406d +M00857 Salmonella enterica pathogenicity signature, Vi antigen Pathogenicity #66406d +M00859 Bacillus anthracis pathogenicity signature, anthrax toxin Pathogenicity #66406d +M00860 Bacillus anthracis pathogenicity signature, polyglutamic acid capsule biosynthesis Pathogenicity #66406d +M00161 Photosystem II Photosynthesis #cfa68a +M00163 Photosystem I Photosynthesis #cfa68a +M00597 Anoxygenic photosystem II [BR:ko00194] Photosynthesis #cfa68a +M00598 Anoxygenic photosystem I [BR:ko00194] Photosynthesis #cfa68a +M00660 Xanthomonas spp. pathogenicity signature, T3SS and effectors Plant pathogenicity #461d27 +M00133 Polyamine biosynthesis, arginine => agmatine => putrescine => spermidine Polyamine biosynthesis #a5b3da +M00134 Polyamine biosynthesis, arginine => ornithine => putrescine Polyamine biosynthesis #a5b3da +M00135 GABA biosynthesis, eukaryotes, putrescine => GABA Polyamine biosynthesis #a5b3da +M00136 GABA biosynthesis, prokaryotes, putrescine => GABA Polyamine biosynthesis #a5b3da +M00793 dTDP-L-rhamnose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00794 dTDP-6-deoxy-D-allose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00795 dTDP-beta-L-noviose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00796 dTDP-D-mycaminose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00797 dTDP-D-desosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00798 dTDP-L-mycarose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00799 dTDP-L-oleandrose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00800 dTDP-L-megosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00801 dTDP-L-olivose biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00802 dTDP-D-forosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00803 dTDP-D-angolosamine biosynthesis Polyketide sugar unit biosynthesis #5c4f24 +M00048 Inosine monophosphate biosynthesis, PRPP + glutamine => IMP Purine metabolism #e0a7d2 +M00049 Adenine ribonucleotide biosynthesis, IMP => ADP,ATP Purine metabolism #e0a7d2 +M00050 Guanine ribonucleotide biosynthesis IMP => GDP,GTP Purine metabolism #e0a7d2 +M00546 Purine degradation, xanthine => urea Purine metabolism #e0a7d2 +M00046 Pyrimidine degradation, uracil => beta-alanine, thymine => 3-aminoisobutanoate Pyrimidine metabolism #25585e +M00051 Uridine monophosphate biosynthesis, glutamine (+ PRPP) => UMP Pyrimidine metabolism #25585e +M00052 Pyrimidine ribonucleotide biosynthesis, UMP => UDP--UTP,CDP--CTP Pyrimidine metabolism #25585e +M00053 Pyrimidine deoxyribonuleotide biosynthesis, CDP--CTP => dCDP--dCTP,dTDP--dTTP Pyrimidine metabolism #25585e +M00018 Threonine biosynthesis, aspartate => homoserine => threonine Serine and threonine metabolism #de7d78 +M00020 Serine biosynthesis, glycerate-3P => serine Serine and threonine metabolism #de7d78 +M00033 Ectoine biosynthesis, aspartate => ectoine Serine and threonine metabolism #de7d78 +M00555 Betaine biosynthesis, choline => betaine Serine and threonine metabolism #de7d78 +M00101 Cholesterol biosynthesis, squalene 2,3-epoxide => cholesterol Sterol biosynthesis #4e96a2 +M00102 Ergocalciferol biosynthesis Sterol biosynthesis #4e96a2 +M00103 Cholecalciferol biosynthesis Sterol biosynthesis #4e96a2 +M00104 Bile acid biosynthesis, cholesterol => cholate--chenodeoxycholate Sterol biosynthesis #4e96a2 +M00106 Conjugated bile acid biosynthesis, cholate => taurocholate--glycocholate Sterol biosynthesis #4e96a2 +M00107 Steroid hormone biosynthesis, cholesterol => prognenolone => progesterone Sterol biosynthesis #4e96a2 +M00108 C21-Steroid hormone biosynthesis, progesterone => corticosterone--aldosterone Sterol biosynthesis #4e96a2 +M00109 C21-Steroid hormone biosynthesis, progesterone => cortisol--cortisone Sterol biosynthesis #4e96a2 +M00110 C19--C18-Steroid hormone biosynthesis, pregnenolone => androstenedione => estrone Sterol biosynthesis #4e96a2 +M00862 beta-Oxidation, peroxisome, tri--dihydroxycholestanoyl-CoA => choloyl--chenodeoxycholoyl-CoA Sterol biosynthesis #4e96a2 +M00176 Assimilatory sulfate reduction, sulfate => H2S Sulfur metabolism #4e96a2 +M00595 Thiosulfate oxidation by SOX complex, thiosulfate => sulfate Sulfur metabolism #4e96a2 +M00596 Dissimilatory sulfate reduction, sulfate => H2S Sulfur metabolism #4e96a2 +M00664 Nodulation Symbiosis #88574e +M00095 C5 isoprenoid biosynthesis, mevalonate pathway Terpenoid backbone biosynthesis #4e6089 +M00096 C5 isoprenoid biosynthesis, non-mevalonate pathway Terpenoid backbone biosynthesis #4e6089 +M00364 C10-C20 isoprenoid biosynthesis, bacteria Terpenoid backbone biosynthesis #4e6089 +M00365 C10-C20 isoprenoid biosynthesis, archaea Terpenoid backbone biosynthesis #4e6089 +M00366 C10-C20 isoprenoid biosynthesis, plants Terpenoid backbone biosynthesis #4e6089 +M00367 C10-C20 isoprenoid biosynthesis, non-plant eukaryotes Terpenoid backbone biosynthesis #4e6089 +M00849 C5 isoprenoid biosynthesis, mevalonate pathway, archaea Terpenoid backbone biosynthesis #4e6089 +M00778 Type II polyketide backbone biosynthesis, acyl-CoA + malonyl-CoA => polyketide Type II polyketide biosynthesis #af7194 +M00779 Dihydrokalafungin biosynthesis, octaketide => dihydrokalafungin Type II polyketide biosynthesis #af7194 +M00780 Tetracycline--oxytetracycline biosynthesis, pretetramide => tetracycline--oxytetracycline Type II polyketide biosynthesis #af7194 +M00781 Nogalavinone--aklavinone biosynthesis, deoxynogalonate--deoxyaklanonate => nogalavinone--aklavinone Type II polyketide biosynthesis #af7194 +M00782 Mithramycin biosynthesis, 4-demethylpremithramycinone => mithramycin Type II polyketide biosynthesis #af7194 +M00783 Tetracenomycin C--8-demethyltetracenomycin C biosynthesis, tetracenomycin F2 => tetracenomycin C--8-demethyltetracenomycin C Type II polyketide biosynthesis #af7194 +M00784 Elloramycin biosynthesis, 8-demethyltetracenomycin C => elloramycin A Type II polyketide biosynthesis #af7194 +M00823 Chlortetracycline biosynthesis, pretetramide => chlortetracycline Type II polyketide biosynthesis #af7194 \ No newline at end of file diff --git a/data/MicrobeAnnotator_KEGG/KEGG_Regular_Module_Information.pkl b/data/MicrobeAnnotator_KEGG/KEGG_Regular_Module_Information.pkl new file mode 100644 index 0000000000000000000000000000000000000000..c2ff119458617fc2f233808a9688ce2e15594fcb GIT binary patch literal 59874 zcmbrn1+?rovbG&&W@g4FySu|oC(Lw`oFpeqU14yTnVFfHnVFfHVJ4Gg!tgzB*_Q0g z-2bkB-M!Y9UG=J@Qb`s|z5mGBV1zl=9c_dWMp&uAUvn^GHW+D+AtMeQjGVKFG#b55 zXE2KU8PaTZ8r{LDIUyt&j24JqIvBkmdW~*pFh+^=o4vu9!-tGCbTC#KXtURB48|@z zq`jm+7$+y1Z6V_pMAC1jgYkwB8F}bn{8F^hOB#a-3J+d?WIrDU(s9!xcC$Y?_cQx`!u zQMEsqX5C3J9#(3$JM-v~G&bhZZ*>RL4j(f5(7|*;lU}$V586*A;XI+%U7T=PE-{ z66PMJY?!B(gn9qxB+TcgpTCT>sU$RtNIeP7NOT6RNF;-{=R>EATuDfV$)sr+nkS)K z$aoTZ)g-hB{cNy+Ct<--q?z>7!9pQSO3K1st`-R_qFHp9%FALwMoKSUMB_>?5sA)V z$w(xFrCjNyi_kn5mvN<+Ekjd250)!EklTahhpSYqP_UY^@{nQ5`4vkUid}24(z;zQ zC@PQ?6cxpJhBQ?ODKG6_rwOyw>7-&N?UuYWdQgo{qthI$T(wMpuu3*q)h)AHjHA;X ztX?RQ^gFG=8g7|2qlaE|uvV#M+G`Eg_RL+U^w4Oun}c=Blr`Fo!Fq0u_2&rXBkjyh z*-n$59&LiyVBM*U(%*Hc*-hrvN6_u&k94r1e?~)#NcimeL^oP@+}srXMvIV|eN47- z$?Ns|Ij=F;#4S5)jxv%~+aqbU6UEon7DI@ltZuiGDNS!$eiyM%>@-e4>LZnrLl zh$kIv6HMAl2HQrWGuW;qC+QL-XR<8=sCPo85l*SI~Wuqp2OxjymRzG4)0QU zXex(y^&H-<^x!$Xdl{*6c#mqN&B318U@wn!@BfcH-={Qo^MA_o%=Oy0h&Ipj{Yq<9 z@_hf2SIP4OT;&7*_dGwSRD+Ku&&t2&`N99c^ZXDm@Q0T6@;pB*7?eCeywtdo=SO%6 zKe80^JU=QJnLIx_5}m;@C80b&wqpK9XK-9LINr^FLTS2ozug_2Sf;emR_)Mlb=p)J z%|_CtcIZ+)3{G-`pIiprplvzDE5TC>R$$>HBJT4Z*9!%U*1a=$(M#b= z)u3MX&|fJvqCIU6Ud=r;dwuHA*NSgUEp6GAdOg}$9j7<4!J8icTh;jA_W0i^!)j9Z zzU%S7SFoDxelmF9yLc81U4Zg_>1m&qkQ=~^Tf3ybwh#EASoxwk|!MCo#zY2L8*w)}X z*Wmj(a%<5s?{qgF(oAVg2S1bzcG~Z&rfBvP%37zJq=SFET0e$>8m+-kZjhe~<=bj4 zfAK!gucf+evgkLj2!1ckmb8=R;ExzgZ}6wLmw%P4Ued7#)%xfX9}N4z0YkF={~D#&lqmp*B_x=-SuG%d%*MraWyT8v4VtW$jV}SkJwXH-^u=sK2Z(zjUP^<|-X=D&e0tvovO`Bh+=fj8 zTP=%CDqMptx*U8SHW{=`ZIkm7Luw^9Mes>0o3?FA=t`+bn>H1k%%+y0OgT*u$hDsq z+O?l90%+f`=^a4(8F-0t_EMWM`s}q^ZJP<&)t)&5uJ$a@uJ)|F#2`?6w%{{Ydv@rG z+P$XD0VlILB`CG$3Ib}-nl?AIt36KzX!bfbuLGz(Uj=A2+cv*|O1`$N0VlI2u1C?T z2z1G$wgi-~od__J?OWmiQKS{1pC;CIfc)!4fVQDyeE}ivBx%_Ka57sE*W+HOB0!0- zg(aZ47l}Zl*K6CN4iNWZ5ooHAF75zvFA)LNjJBi$l%1t20K-mOT0l^$+3MRea57sK z*OgkXDnQvGh4R3aws+trh^y zGqh}VXjLh;Mg%AUZClfU(TCbv5uj|eZEXQDUCoZI11Ga}aXnq@>7}SW)ZMW4VXQk- zKGdMrptq#{N#5*gluo59Dy4?B4e;wV&4!gw(jFyts6v@jp-`s#>T^*Z39OlPyFG89 zQVr7@{VqeeJg|*CFbub`Wc`D0^6{m%3ACzP8y0~MRkm&F0Cw7pmogEEbZztKvzJmz zheK;zWLrd^STya}meFUo+v(U=?h{LH9RMuPSGo;!v}8gJwJn^?w!?KxZZCm+UZd4h zyVT&Jp<0_p#CDLl%FB-OmRDy0sqN$d$sSaIMz?3?0Lk9D2J~$g2T1m=HK1#|2?&|3 z#$?0KF7;q6GHrKo}te ziu^&)9@oJYpS0Sk9U`B_5WCx;6>qgVNt0wS2I#3IwovF$7su>}MR66*z8x;{Ty>^y z5<4Q$UU=mSZL4s<0=4Vx8of^hZA@SiIurd3_h_o z<~j-5Ta}XoKr;B6Pl5JU<~!5$VLv4Ybc}+IfMdfu>13AKG)~f(W=JFNF5~$3+onP{QnD0Z}Ik?j>+CyA;=T zx~w9gR_AgF=xe&70;tuwQa}i)OOt;UoXoDq^^mR!0#q(kVb@APAzc>$K0bO?*E>Mw z+zb+;_-FS>{rz&pWF= zdo8;QTAfh4y9%_sb`P}IjrZ~rgJ}2czTlI=FG1W7?TyL<6`xdXsXZ8cs*y?Tp&H$> zhb0-(#Q?}2fs@&zxSp=ZqJXFCacEE16IFm@J?Q|+cq#&#U$Lhhz^2bsfEKy;tOL|_ z&k4wTiTzfpxilJ-)Sh>oV*WxD?C7g~(E;l5mjWO=H0)&u#u#d^M4;25Oug#Bm_zNg z2q4k4*BuyZsJ&4GTK1*`V-K~r0w4=^>}>(TV)Q)h9XOf2i|ZD9PcP*+)#~)@eHejm zx9kIG|As!S`0OSW*pH%5=#G6{qZ9ii&~zr~$9xLyMdz~sG?KKD*yqq*biN2ctKGz= zUpj!zzX|{apKSkHKuA`XUi~+4GW!RvC+nYjDMq5y#F|^;k=nQLi>48pnI~EhO+@O^ zwSNiq`nt*RlZJ+z?P_YV-)_==()gx5`wmZTkniO?ubxRpYCk}GrSflHN}DPK`%ylN zNz-1ZC^CKf33e>bO$Jy$!^!Ly$*bx4RWD^`^k{m1gOStCey`EA-y_}bk|lpYyKaBh zCHwYQ&1cI-7^%pN5qT-&Xfms1Bf%(>)l0fIa*giUC^fooqgLs(VWZXPri~8mEyfrT zV5z5RV?xJFWFo=Ff|J?UxSsrRqCiu_%W);3T53G`D0Bqr+W5g|GwHNiHUYF3wFv`2 z72D|BM9^N;Cgvps!AgNm5`5CQCViVU(%zAqEYjYQn;g2Dc`cg)PG(c$y7p7)rOdoO zU*6O(N~OEB5Ys?=W=$Ib43pS&&|Z+H4}hi%TQ-A$Q0$w8F(aJJX2SJ2XAS~1fJtJr zNI({wRX|Y!=`b^|PFJ^OvpG&RID179cW)=u@1E6FD!`wvxAAH z(8E}Zvo0@XGF+Kn^y$jkwW_ojhMxtoT&Eu2iMT*Oj5GI(BUpIGL@A>pHHcm$G~-zgLG5>5i=d?d5&V zicin)wW3eY@3jM+n|z%>=O$kl+CT60BH$)pAKE|f4S1<3vtjh<`8^cci|IyHpUUrz zgU>wjO#+=qKFlR4wwp%4Bi{^Klk2uQFClW}_weY`^Lq>Esx5oAC7jH*lA!W?>xw|a zxO^LE&+l#JqpVcaMcOX<^e)u)HM(OvKv$#c+m3KD+X>gB8q@^(X3!qh&Jn;YsqG>l zRz6fmyTZwAH(U>C_lkg&-a`VaeD;h$L$gGCIY8;$y9&@l*vA1%XBGjEdtU*SxSO^g z90qB)9`^wi0mXfw1Qho{0cdtQbmtFtfVdB-0f`;z0C6A2OU=ZG2cPOwrFI0g7o8(( zK+leX_DPYWc?m)EnjJeP_-uAsSngP8udt2_0EG)99}itkXv0o`li7*5p3svj0!rw~ z5>P@<2|%9EQyn0or`3SOPIrKWo)G{VgJ#3d6i_j8+s=ZM+1a=r_c?kg3Llf;T{{;> zIlg7>K?Cz<*H>nnT}?Ycwd_1R`DcHAMV!f|o?RgEqVnn|`MNP3hzrHer!TOH&)8rZ zM$K#=NbDjHj&xltZ^gh~UENEd{oB8kmr_lw0orBJCp2R=(PgC>R)6gZ*q*OfdH}_^ zJ+3(Ci_vO3iLPZ=DU{MvSj5cHa^c#pmZzC~_KEgb9ZeprH|s$^P!G*B_vk>{HTdKovfQ2pryN+muM%37q>*8T7R}% zp@$ElWxLINx<<{U)z*RskEY!&0naJX^pN#nnnsU~-68Q%p4!Ym+zBVMyA+ygxx0h7 zI_E`aT*gtK-0lJOl6|kdc>(~MUAxZ#O2GY9pxw6z9H3-BSOuCrd&mLC5f9gZzCGdq zb@`)Jpw+O)9H1_LJOCQ2r1pdZnDt2kMJ84H^iMgCb)V*?u&&b6vu7kwNyf9#Zr$f1 zKxZeh=b^pd@B%Mo5Fn|&7=1Fm(X^MKhYuNNsJ$G4PJ-!QfgUzw+@bbr1h8FduQ@Q@ zP$6ili6Fio>^~8pe%I%)3^SPLQ!q>u6*Z(PT#P-=Ky*3eg)9y z{DA}H*@qF(_hlbBK%RZfODv{*&Y#HVe}2B7!uHSSGvVcj8TN~Wua|uyd~BcN$v>tq zDxt;A4fdtu>VUy$R`Sdkz&u$HtJikhX-Hd`vi*jfLxJ8(S}hDwOKP#(`1f zRlCdhdE7`7amU7k_O@yK0BG}HViQ2es8VW#3E^Zm5w1ryu>}6N&tVdUBHKj%_Cwo_{W0_@{6H+fG>#jGI<$D#tPL)B$hyS`BYXS~TU;IF6;K4Y>AcmD{y! zI>#~i^uo(zgbhJ?)9w4S*b8Pe$al0m1$ag{3_Ee%7&9xBe19Cv;rZ6AhIas39w*E; z<%v0!f~f^2p0}HQn=ANa zS)X=#ZfI}T=LrBaedOr8(B55}Pe7qQ6YolW()Gee8FQ-VX-azD_$R%VDwCw=D-j9n zg7bSwn6sgf@~%sx?K|OEv-LE08ZB$OH|mrYFXil1ujSkFc(Aq^#91g%oO&RxN6R_^ zWyefU`tgu{?KVqLiO@U||B2G3cG%XCKhz6>VgZ5)t!AFf6#0|@D$O-BKV3MP^>96x z`+6xdhrJ$&EdZlTEgy|9&$N`a{;e$t>fhEv6>roWGH5e?)C+_9WXB@%_J7HRMLi^n z#A1~Q|1%dBcW-<4azzuo%Z$=y%#Q&QSHwx%~GvdZV|1U<|gaD!u z+YGmc!O3h>TsPuoiXpFRSx9H48rqFGJOW9dMs^DaC@fo6fF9M}Ru1sNZ7m=-Z=2Fa znM_%0wrzxmb|Yn?Yg;%hRO7k|+eOc#4iZo^u%mz?zq)-5EEu=7Z70XkWKa`i zg<3#}i7}Dw3@5W)a6P77^-_E`Y`@c3g9pn3dZe}+aIr~%X+zbMJTyMzp+=RRhJ0yy zP#f#fvfUB!>TM4X+Ec+;k!o>I1(qvMt>5!f#pK3b5(qlBiFI!{ne8Ka4Tmzx`4$z1lCBT!(Mt9F6jxluYXvY}<9TNq?n|7>#O8OH!4o+sr<9hl} z&`VJq+HAVC6JZpeUuDB3%?wn>P6G7|I62B`*1KV+NG>l{I$&a_x=-wNS^!8r-M`bJ zt15Nu3^gDnlf@fpDT>&SvD{)oWuHsp4 zz-T4jo8Y0&K#R>c-oGISuEtm1J#4jleNa94JoMo6(4%kH;Awc+%$gu}Eu74*QxuBp zdcBk-yG>29VjiQUBw!7ZDYBNT=3AX3(&Gi6MyCnwD?NM>uDxV>>Y-hFG z;AD2Y1f{|qdMTn{6;FLUU(CA`erZICij2%cTK?$RU7)VO-4$`>COk9RWcxi5&lRWB zrRpT<(cIiCxu^~w;C*m1yI;Xbod@*tU(|UJ{{O7bL!hqC!!BM_6>ZieACX*M;>pC0 zJ?cIwj*kh*73?J5`)2wkvBzP1)Ad9URKinxQb0xXo;?L8v!`)g^JgTGcR&71J^HM~ zRXCrMw_G7|m^lprA>1Ba{ukh6_9Cu_`;r9y$8cYkxWau!-YVg~>HrCSO+Y9@Wk%ZT z!b8033cLX)vo~=)-naBpgvfU8ro9cL42Vfe6$Q-~yi;TQS%p4bb8?H2n&Kp9})&swmL+P-ug!+jNSR(}jNcrct=gm2)m!j7x>{wXov zn#CNiHkaw46>}cyNb%q-QLB}f7`73!Yu_s5P+icN+P^&H?~0JWSIE9$uhC*}61L>w z6%$*ia!RRy>0fb|Zp9CO3$kth_8@;Og8ZoxB(0vL*(skt^sz(fljh;krL-^Xh{x`9n{o!JN7Gi%%EFW+8`hJLshg9Gp6?n95gi&f1 z>LfNI95!C#%Jw7kTz8mni(@ib#$Ym8(mWIvOr?=W!BkSAq$Lm8l83CvLnh_H_?$b2zC*9w^9Xn-at5f1m4`IqAys(Dz&x1D`CG{B{q~T@ zDncGxA+P9(yIqf0!I{lpX5PjaP`JQSb&Z?@%yqo-^eoZxS& zbZtUcWuiiriKWW=g#o-y;k(V#>T4zKzWSsj%d2%BdF0x*B4!@B?|gwG35qpW)0;n- zJ)5Mi1AV7SU5CjE9VV9!n%}{>qY#ExN7D0z~gc&`8 znTiNzRs?xcTTE6e5Vkwy59KxOX2WLrTOg^;>VeEw1TuRike=pSwDZ>W>UkXj#ne?T z5QZBzrw1}u5y;#Mq(~~2u>xVTEPp6fP@ZDC_D(fiO9nDI*06d07D3BEGI@QynpQ|0f-KGu&rgSDH$+l;hV6usJf94aUeOsL1Vjr8s z%MvrP&sJX z8WK=%Z%qOJsry=vqx;%HFxPz@2he@p2ryCGxAh!A>GcC3r8zg?07`EdfL!UJ0)o;E zD{Uh%)qFM++gv`2B10`h#`}KC;VwY3wh*58 z<=lWHy%(ljLUAECnk^5dHZwn*P^!K-`(p1pf*XX|OP@_AxW0huq_)b-t zR$>roibmHg(!`(G&NZ67BhYS(U8?|FL3V@oj_~dkKs(a+aDc4bvjQ+ewY>yXGKOgs zI83A9>VwUAmieL+iMB6{!WJx@wQWD>_$hHB%Jzqo*#Qz%2nXt=us`2o%MOAOX!hqG zT&3A%cSxjDHksI=k?wbxKsyZDQ-3%wWyq}8u%kcvWInQGM@HJW)E-r%6FWN4YzU+; zeT?Xtyq01Ag(?)4Bva-1jBewBim+OhccS4cb5G(*vLl`-z?507d>xUP_%v0$WdlPjZM6?b*;V z&L(?b&w-QKxe`>aofiezPSLXSp*_wEBEZZ>*DiE`I4_C-W@_2R4p8JSi9nZ6+b(s0 z+T*e+z-M&11JoW@@KUPZr{T9NgHP3(ZMzEEH~d^3fCe6Wb`7-eP`ow*6pfBu=K%9) z*GB*~nLKfTW#t>I04BRhK=?A6jh5XEC$n2{-9)!m1lV_Cw@E0xBUfV*n?!f8%;cKUM@(`}`yUh4iz0 zlyyJH2kn>WlOof$U!lEL{q1kS@6gpa`}PN%%>KmnIRAH$@{-{NqBl1#4DP=}- z00WI&0i??)4p3Z2<)zTF$q@zi;8%P$y6nM+uGF6F5EuhaW@AcFwdYtB0Vy*!v>RZY z3LsOC>j27(7Xb{>vGD~28#9q%6Tr!ALR^nxBE6L9N~vWghLO{ZOxapBNsaE>q=BZ( z%9QS8ftLTCO%CnN>J+@hkZF*otoiKQR8^WvY3fM#wL58=NHa!m+q5;hYtz-}zD*x# zw)1pshCnkTPCYUsv=@q*cqujGKA?up9DFkFqxzpE(kzm+ZB~~gOJ|Fci~&j0?9nHu zG#WNXr0H{{HfNyGfiHKi8r`?Kp<@xC@v(W}WHv9Z=g)k4De|YO)2{QwDDp=`VQWO1 zlVPbfBh7q9$6Ar*nz6REYjnptH9E1RMyHkrn%0=`Pu93qgB%SvUY}x@AxBBG8qh%lz!3a57sA*G;pyUdp1&@XD5eQJ9AAINSB1 zJ?NzZz(g>^z@?$Rf4dAXA&5Q`jLQa}%{IM8TMoLKKTTU6PG&3M>I)shGX#*(Canmg z)G6W1TuHQ#Dm0wb7?UZyhOG>{(%q#ISOpII_HjLNtLdc-i1|lb9Y!^AYe0MA)(n6W z*R{2vJ#lOE5`yScjMoW1^Te$ST}>Qo>~Jz$UxG^A20?(JnSS07+UuX8@=LqZ5u=Tx3)AvkLAcn-s-d=Dr+Z)$I z+9wLQ!7>Rbq^c^@+g_40LX=gP`4D2L~WG*dfq;N$8V^nvJ1N1=84M09 zAu-={ZN;Z1#I6gpdiflimSju~RpAYAGP@DiQ*%=gV4O^s{bp!S%`FjN#l2~_IzVb} zivY^C>~;sptvh(BDR*b^sbse8u0RtN%HAF5T-ke|qp}ID@4av`yARiuyhe5rfe}tD1S({1E zMeQE;jhv2iNUX%UXeNys%3;@M|`u8VjZ-0KS00|BAFAh-u{>n>C4L$VV zf=@Og({uS9+UJ1&2!Jfwwm+eL4(P8M(6A9mL&bvB3M0Z{AsE*!II>8+(S-BQ6;_n)j*ZT{cj3n1r3|U5xsWlVPYw*HHWqZHh>`NK;bbHc?oegs5T~wK3i-Vw}}JIR1(vLlR#H=psk)1 zPG*zgx(<`;rL+gj@-_vGoNl&M!ltaziA`0bQ=1yv4K+;w*mgw)J}tBxYC2v*6l|KY z>4VQaiWzD&N3@~61)HfV*<)#I=HQcBLA&5gRw;GBLNIcgBWW0SVQA0UMJhhAX3rK4KCuGbyu~8T#uL`wBpKpnpO-BG zhqX6ck9#S-6mc^R&mCSca+;1c9gk(8J?>=#z{(%r$a2szS+pd!JRAmnxE}P7D8O=H z-&T}>dR!|7Kv%W3Y-I|*m{is&^P5vU(*3%id(FI?AlJ-rl$@S?FkjKUE9`E5|66Wb8l4Kp+V`RBF~w0~|J^Adv8 z=e9}knSXA>YII_oLi^{oSyeKn1F(7UsU^^+4R@ayV2cP~n7(ZZ?FU1);-!q7y<-jA zI{4%S1>e;+&|al)Tk*-1LeI7fKIx3oQQ1DwRF3qlcaUVXCB<$>IGoGIbz2T90?K)V z_MG220*rH;wu=Mg{H_t8GUXC32gv!|c`1|8pjogzl!?}Ca1KQ8IC#WBo z*-PH|=R;@nXWRDX-R-guFGYY%MbUxDwb}JtxABB?I3S~zJpDH7a5^Hqdj)nFv?{NXZsua89p?$CA3A~g+dNpxk@R?T= zCqYMTwXgGJIIOElP&MzVL4a9Hv^@>lwLM)v3T-KuR_j=XrX`gKm# zFOC4c{jOc&0Oj-22(XES(W8LyZD{-G%FovD0lXfG)QS=fAYm9lU!vxibQ8r@I`Wp1L~%Zl`+$1noPN|9jyuXvB5x?~ejp zhs6PD3CK64VCKnb3eU3?Lye<8D2_#88Nl(S%t#C^l6c@ z=Xm#8|9JsLLYRP62_Qs!0k(JFU*x3>i38nTdr1QPb3Y`D=Bd5RyB{NdB>?D2hvHS} zN|JS$8ct@f<9d?c&`YV5I!158D1!FZ@2wi0*xNNawRfPsEWI0myfu6e+CQQ9Bf#uu z$3Ad?Pw2x4ux6OpM-EVCKCS?oB>%(#8uw3m3EFZ?qiUZSFlL~6 z{1V!$>#r&RmucG94zPmx4KHQb?1*Os7ksMGPVJx2v8L0+*SByo`JG z&|Z9gr~v9?{@VeH$d3_l)BNNBrujJnZkk^lz%;)`fbFv_`^^DN^Lqq16~?Vv4ltAU zX9SRF+g}balQzQWWlmG!V2Kf-^@ATaQU#D9Mivl0S(#!KIGK%#>j@uCFV#XcI*e)| z8ly%hHfD`xoCfWMXzT#wg=idTFGS-;z%4bN16XSO2)LytZ~#k97=d=1Phlblu++r7 zl-hbmPZE6Q89garYd^7Kvz z?dhF90-oL(93Z_jM!?fMlLMr8<^ZsE&0O0o4v^ki1CZzQYz|N|X6L0$h8tpz;4?SG zoY2t_{CI=S1t+t)B`8D869lMk=vvMT?InJ`0MOHCFfqRal=wyf)XF8+bbxfVB0w?i zSla>8)rkPzrJf}Ykgl`>@Qqv70n*jurA!xR_}kVGKIzxeYh3_ZznWnS27nrwCA5X0 zV@cOi`ND8ATLjk=yl52g1TQ85wGfNTM_z|}is?Uk`j(J@SM53tNXH{T6u2a8Z=;qH z&KF6W;K^PZI%>d?Z(9ZqH!0(~2FnEj_2#>_yac4d3Kc*@;vo)T@)ZL>f0J5kB?mD1 z$^yJcO+bCMW2}&<_3?IW757F4tXh$$BDB>UAOlwCrL?o}{8~dk^Da6x6QsVgOI>v4 z3T#c#N@=34Sqn~PYbzL)rgijEepV?X>vds7njMjWW*&$IxAkju%Qgr!DPaJR6+CRgMc`0IMGbcMmHj&R_M!K(Q1_j_dVVmrg8|HGDcGD<_ZP9o$$>rIJ ztr@<#Pi#HB;*-MKvn_&8(t>VV20GV$D@le*R~N}{4JWg0aNSzlRt4x!ZU^lJVfzSh z0Y$@hZ~$$0AbUE1LH3G3pJHcwJ3w*UCjxG$%mIqqz7;^}+Rp*L_x&q?l68Q9U^+f*I}lE0 z2jO}$4z39Bvle!U1oRCZ8Ug0US*CMs=x9JfMkc=aFsoC_X;4`=B(a=6HJthEH zh%;TsLRYk;|8pE1j+WxOmM7>XFH908v~V0Xi}byTk!ZeQ5;Pd(gGZ9H7Kp9)U!?lPd%SrC5Wo zE8%2z6|O6FbrkTdxJCj}>e>pxu_U`rKqaKau7|@=3)e%sF$z$KyLOWV6w=KVphXw< z76(Y)t-O>4hOu_fZVNv1sm$90t?XrABXs;I*_vQ?!r?|LT-V|5D8SC$hTQ}0I^0_W zns%Q9=x~1xXxRe}VB!aBK-(S?5Yo>H6?+&?W{=={+>c5iAGtKR9+VSHt%Q-;W0I2@ z9+$_W411OHgao{ds`+Z!lQ95D|B;~%`wE|e?d{{!F#ryWGkSO?1VCHPY~Hi(6WyPy z`b?Smd0swq-B8Mpq$DgNz2E{An-^W67`(S14zNMFvqHD-GXm4~ zx_+VR%N`h&(<>fW@$qTL_Nxk|lF--WGn$e*@^v_wy&*x>t#1Yak_G%0wA=9QD!?|3 zcN`!a->m?&hxVQWnBsk2$}&a)@7o8_r*1j04+E`Lo`!uSI=2L=%X5KQlaFCnbfyje z1P%u{ab4%n^iotgoE%T>a~K89(c;v;2s9&QhQMD!dtLQalmww?`L%rJCn%Y#@(Wqm z)r-}+mqk4Z9=>wPH-YgHY1ua(7>4-A-vj%n0xOPy_4>ZIJP(XDI5p;!oSuE_;+X4S z@||ZLQK$ADbhXsC?Rz+x{ebJq{(<*5cVfTt%VJ-K}=f1rezo(2us ze?r79@pC<}p8cZ0@{)si(|#45Cx$P8SqCrpSVqBls7%5C=D}f$-(zriU=i>Si5K&x zY2O!t)4t@muAymvN-h>lI^KW5$!vr%inNZXmqHy5pfzkH7{wV!)>1WJ+F{z9M0T1z z9T|esE3f8-5opTOe35Q5QDE~!d+Hhypfq=_3GHL^Rt;!c+W{()P6RlW-mt_0nwpfC zQVEt|I0hJevK+!*=N@#-6m7og!(pjVf=c&-L4b?B31A^;Zygq{08M7@7jXcSFB$>P zW~8>518BK;1jw_dEg>M7JfZ1X5)KzR<9ggn>!mPR!Uh;y21e0BvWZh8Mjn~~1=S%; zW~o(kLp5z#{JJ@plTiMR0Pqt)&~DBZYCy+^IDn!nMxd22ZM~8Mm~-U_FdLiNDh|*J zuNnd0&AXa_kTjirSRD?RGU0mC){Fv_OD<)SfI2Q~N5D(+Iu2mgbtAw@O~#}SpzZn< zAYnRU0|Aw|d$u8*%!cB6+#BhoEQ#ElXdA-_G#!{tpxt!CDn1z#wQSSiQ`4Sp+bqy* zoTo9}+$GU=cmz0JlG+x~{@raE0SaVlTRDJjw~hb>t!3LdfNi&p0C%^wY&!=Ser?Z7 zkq%~_s3&&_K3n{z7mI|@v2b$e1qC_~=jI zM&3_jS*yW;YCSlS2iptEkx_s{IArTl639O~uH$Lg(efFhWR1{{fs@&>5>!?kR}oPE z;CN_H)d>RfE+R)Kw1UR(JvHq_$4T5tQIM;GT6VGnd>5zGfVQ3L0443T8oR3|tQwHo*$yy|cTNr9j%Np$%090K@Z&lTa4hM92sHFN9~U~nv80P4KstJM zu>%}Sx}*m5?NSH0&GfP=K$*N;K(sLnnODH!79(7l_$v9&kIHwcvB|_1m014JJ~1fm zZsegYkgRGn7*=sMfd>>D=dM-+vCU&teT_$OEv{$cb&8?Lb@n#e^%796c0&ZHP*c0n z0dnuA0I;Q*Y`xh5a_^P^Fj%F`-YTGyxQ^Whhf9laJ?=ZAfJbqs1QhpO0m!4c+X3Rf zCjfaA_c}n__eFqleb4T9fRgiofMU2pQ=^7Q*C##bI0fh-;rR#-!2;I+5N|5EJhaTp zgP-SdAqv+c5-Qp!E#E#WAf}X$=`lF07UFtJpNIm~x($0$0!ryq@=*juzVZ7!(I;CA z+V%{z*GkXUd{T)#SM|w~`13WoZ7;Yaws|oEMA5gGpex!kq4qMI%wEBDZC{l@aW@~o zkV5hqkjXSW)PlD;5}QA0!TH&dhDJ?1bg>mm_v|&rpya)-ka9z{b%^Q>2gt}bBS3bw z?JWmT_H6-0esKtfXu3Mb{*L41=eto5fPJ72kdg04fDpNO*#R=^!y1sb zzJab(u{1*efWrwuT#xG8ih!c}7qmz9oqUv0Y4geV(IzdK5UUCQ4BC<7iQUZ6KTjgmxvzr~-76$8>;#H&zYk*w_wG z@Wu&%Hmh)zvVfQ@IOD;|Y9&pp zPYPX4X5S`*!y+QCM>U0B3d8Wra($Z;MxZI7Q$c&HK6TwE%ZF8;l#6NICx)1=?z3mp zSA7!Z4DJ)l%vklw^-4BV#V7YH*~~SXLw_~8Z?i)Cy!LDn;7Bn0JfSN#Cg?ffu+J0M z6Fyf(K+~CXOF%ZBrvj)SIj;jGYrYDgzT5l`kcvhXU>>IF05wXh25?ESfSB>5uLCEu z1lN^Hs{%yPm4KA$RRN;tJAhIP)BsNIIe=0NRRKEd3k#^k-LpmDWVR@-$GwIWOqFC1f(zjj!kf0~DzJM4v+aEW8li7y29{127z&ab{U?T}A?u{eB zW}U<~ae%mo)qvDCb%3}xi$I%>nQiU>wjCY;Y7y4@9Kg0)R)9VO>8%{Vwp&MlCDyKO z;{dkZwhEB3+c`kbcKa$oGItOV60Y-}JHlaaCax!Z5CuHpCIKaUXZa{A9;JMj;8Vv7 z+O{jScUN``fc7(`wmY~1X16X3;2)HHoa{x>1 zUj?wl0S;h^10%rp%AOr0pkfJjT*Arh5L~y!p+SIODy9e=CIMOE@BlDXfK88ZfFf|D z0Pj^$EOjfK9&J0yaZ19`L6Bb3xZpXvnG#;+&c48FZ zhe(@tk_4pN$q`_ty=$j9fNrNopw0b)cA5hyb$SH2sJL%u2&lx}u`}WD)1|l`_t{Z^ zkhrWw0*d=w`6x;V2tSV#eDZVH%(>SE=d-3lH10i24r+u$%@lAyXfcLV`C z+Z5kBpfaLq7TvmbuLG!mA1^@}?I65A`b_l`3lBiMksqx1WM(0? zhoVpF_J%zypP{huOV;)X9DcP_f>Qf23FMncIQy&tD-R7=xs0V@kAr$5o{;~%=m=p? zrR2P$4b9TiQ_x;?o)%C9$TYn|VvQ|-bnO{XFG$Z;Jhu?4k zvgpk!-sNgyMbNUhV0$Xw=A|@?uYbHFf!r)y#gp2*(9!-WOKDy5GVmXy*44`&Xpd2-~plBF(;wu6+;f zIr0N9r2#nr!&pc@i)F69E|6-GC0ezmKJM9%E=THrigFw{X3Fj7D90_hIx5Mcitnvp zcx=B&E~F?S3x9=^*>4I)+3>r>^Km1`P#7jbyZ!%^k20zHx#GW~Pu;3#BaEe_pwfuE zlpb~O+epw}NJfr;4w~C24v-F8EBmZZP-{f zx@luW$Mn*rvT@*KHZHEGcf25=&0;MZAKKG9fqdl2P|z)#P(Jevp_0`qC~RN-<4RPU z2-H(QvApF5WQ@j7nnK4i#2v3TDIAW=;kpKs2LaYU8E;G>0af=?1|U~$DhDv|)B$i6 zY#IkB@zVxChd=oZQwK2c^c6r#%^;vs47i6A4nHP?>q^aB5nwx$%_0FQHERUiUb8uX zQnT|?W|iz?a|EBcmUBY;?(n$+kZU4l!-+V_`BWWr+t-NM+r?LydtxJX(%>WJY*1RQ-+l97uXt19?K!)2 z09rJyoR@Qeq%Io(PlPS!0BSEEfIRIhIDnQz0zlnEJ-VU;e9tQdAlH6n0TpeVwhA2X zMZtA#SBnDd9ZGC<38);d5ddl1v^5<-+qDAVwzjn$K-+aHfULi+18BQm062$_@z-|% zZ8wO3+jc_%6>VEK6i#Lv;kvdP2LbJLV#p-{X*;X}=r%uuHVzQQwgF%vh>q!Y0%8<2O54N9YzJJAVn@A{rBBmz zJHaTv1%^+)hlOi@Z2;RpCW`_bLZRN-Sps?S<&0~~c5$ERvTO9ob*6L+c9YM%Qq`|b z@SPBV_NDSmg$>(XazRzLli40{GTT$Zs4(v(@w~G2U+dT#+O4sVd=vI9D!^pk2@X*9Ppkk5U+PH?Q1(xb03C>)o#FuF*;A_kV~x`sU_5(z1Sn{n zeiINgkA?X&;V?YI_4J*sm(u1vX2Z{ck<-|lq2#&HUck-^fX*3ltt7Nh6I~DiZW2!H zLI+6jMHN6My4V2{d`Sh6i7s`31YgEW&_+|nmj|Cr(NT!6sL^e^655aETonNI&H8pV zv>(m6hLGs|beX3h$H@Z*O`EH7UTlr?_XyqPLytlx~ z>{eX2@@;ylTKRSuRV&{C?N+`s0J)X#f_5w49RauUJq}>ydn zR(_C|ppC5jQ1F>s`QaMfwnw1d%8yngnXO%oRg+G}N6{_wl9 zIexDD=ez76dt70LlF1F!_5_^Fo>Ub2@}5%AdHvPmieh^j+P}PKY5+H(IKY?pTn*^j z^8#WN%q_hDho9QO^(bDd2GGCmZL z*Q$h|rAQvEUOA3V9|u8(wp6#DI6wjUGyrU_q3Zk00Sd_H5g@3M6eWy31+=&JQwD%D@&Hpo`w(^N2(Xu|XVVA>%FubYY2jox9j+@g zeH7q`PHHnqK+4P*0Zy(qZ6*iEg_$EjC%9>|I6yAUS^>C+(q?mjT$r7g@$^DS zSU}$Lei4mM(-wsG8xaX$|Pwr-8?+IrBjQPq8A>%+-x16+@4!yv$Bb#iAYv`4j302Ff9HWpA(I<-yU zWHt=fL)tV5hy!kL%hVsF$MBCGyk`f)QyJtDwCXaYz7E=`t>Y_Flwc0`i$|Hu=#(JKPcUKcXr^ zkK{-P(Eq3!(6pl+K>uTEK+BF5P|?3>$HC!L8m{Yqf?kS(&QJSv?L-)b{%l2MNCfTr zpBw<%0mgNwK)e2@Rsk~XGzU=sbY4o^=$CTrjNp^r0wy>U+Sf163IIo)`8dvo_B!nx zUZQ%eFPs~E5(FkW4?2E#UFH|hhm+X_5>#jQ!YIJZanCM-_TqH0fP7pEpc!{YFPu+v zoKkgZRgh8FWe$+6%WFW>u5f@{xv~aukE8?S%GEW1yFeVEyKrp{U_|5qHQDtwAhjC= zgnVQo!)}C=*-f~f%$uWtpL)7Q0{UuhjXcP^W9$ouPAyuMI>~lDo zeSzyyf2kO9lY7)(NkCD5Ex?Dw3WaI#IbId`#ach)SH?76OM& zez+dzw+h<72`xqzVY0p@IYs@Q@O;P&&Q?DM$ci5#K!jZG=m1&qV-4uqPY#e3Ki2@x zk2%2S^=l2_jF^Cm(rojCli44*uJoTlfZ0aAiN7QuZATaY43fL{N!5|C2U)qupNcL1ekr~#?X=m1L1R0G(;=KxC0QUiK6tAL=C_RP!% zheKAluGAb7$fub(t)zXyJTzUwqiu6aTq@2bZ$(F>)uF)5?Fc%~!%Nwc)Apw}ue{Eg z-*dsfa3-2M%scS_6~#k$t`WYDes*-WV?IQxEp^}Khm%=DVXLKXD$IOfgIH=UXxFPP zAH^5n(I~SMd~ztC%`*wK4{X!A&z^N_KKs^lpBT4a^T~#}1?016_4uU+>ibU0%;SO* zh_+?gU?Dh}Ei8Fyy@=%U+K6N}ZBb~~da)Y7=*j_%xkL?U+ma5T(^55{V@o?ghA&eC z_~A4Ms1lZ|0jVwT03C}J0>E}0)`x}&2+7d+V?{Wbt%U2zSUCtNw^)dhfC|N`HGu0v z93UC1*MPRI;Q+~4vj%i*EeA-(+BJYNl>;PW-5QYEdJd3`^#hP6V*>~1A8jb0$gP&P zzqhpa%Z3UM$z*@GZ3Ks3OvCkLZX&s&?a+GVFbOD`o7RAqZRP;U+`I;`Amsqb+@c0_ zY)b)^xY-T}hhIp;^|-gG3a~L?TL~!c?WzE)_}e=`+&k2OrtRneaqmLFA1oq%diR#>r1$< z?vYV|oeZ3`Fz( zF!LNZT(T&6Rb=N$F8?&zZ6?sqhxVv1r~zyO6i`V-Vi&>TSL1O#q)VbezsJt4OC_L0 zTowT~ByzOM0TOXV1iC3x&sPelM3LH6a5B3Z*Q2;53J^uxu9bkIxUL3t?0N@?;)V!t z7jM^Y6i|tR%Rb;_b~CO=aZ62roqrNg6t~rYzTNHsQQW~x*-l}?hTR!`@?)^6-39Hl zV|Ukm^4n$6C&L$R-j~mcb}TNz;n&+GsN8xW3J`Q+4???k4@CeS5_{MIw0oombnQ_G zD7}yIQc*j#$D>ce?%5O2K1_cy0))+vm_b)<*te(QFqXn~EuW17uH|zQkPV-YfNS}J z18DhT1U&AS96-yLBS4NbY;u5a?A033wbuj$(`nh|bvWG2f$K`W83kOawx1?I#B?$j?=Pal|hIDoXJyW^mYvhwDoH9tB*fKO`Wf{)_1ozZK`>MuB5#UMyMl}LL+^M$W!C_Q`>v4}31=zCOw$UY^xW@o^vzNO5}Q>(h(Z^+%m#;14X#HqhXnHVl76$n zaE76*-?z)wn#AUmxFVcO-tu-0ykm1aK!o$u0B(|S0E5m~1Nad#0YMYpVA_C_SrgYa zX+;6f_qMGq0ma>^0Ub*mAnvpVu(8eo;_lUe)cOKK-2AAzEdVF81#vy@h4fOSkDYvp zEexY<$GKzN7J>E&+(iSxL=_!{#h`uEzjy?ieJr$u11Pg(02oBDq_LC(l&qx#Kre++ z?lKNgvX+eiyArru-T_M1@)1CyZ7VoH$r@4vIG^MI3!^IqK#`}mvIFb^S%sG(#rn}4 zu9pu!waqcH)u3bJsq;mv!(rJ+f@(b13p6gl){g*6ay-caOtfJHSbgo=Pyrz$x$($0g2T`R*Ol5N3h*0H+)5|`6{1Z8fFZb% zcryo3YV!baLkF8UhYJW%XkB^>IGJsU>rreK1XyWicfr;YP!!wLfYi2ifGD=B0bSc( zK!`%W#k~U@elrZ$qu5C=Me$=(Mau>-BHcEF_Tsp64d~e}&|VyOtpR=8%>it^dlg`M zVh;zf^`14LX?qC>TI!myz2Wft%($*)76sVX+P8frAVcg|1=#AbzXKTJfEv)T106uA zg95-_Rpv<#b^xUgsR8^Vvjco1ht+`84tIcW2`GIh1ORQ@O*_#6(sxn~;Jyb3NZ%{16v_+=63>a)At0TO;i1PH2OS2{q#uZjRC#=Ca410?*K8j#wx4v_Hc zB0%H}N*o~JH$;G-61&j>5`I$zh@x*d3#cT#Z@0i) z)v-GrAmMk_fW+>0fP~*8fPZcyN5YTn^k^>bb)59yC%kA-d(`pwJ3#s$r~!R@P(W0g z#kGgvWcDzwEB#0maHSuWfRuhL0_^H;+T#wO^b-+anyPD0I)KtoMF0t|Z5I&Y?s4$- z8913ei|cVe7X(@?Jtg+M1QhoRH6XPY9U$(P1n@rsr+;WRm~+x2(J%*c&yVX>U3}fqAP2wCrsGmDKd?9XOf2i|eU*uO`4xDoa4A`9J{w zuC#uO4c*AI4;?2_9|}GXRok*tZT~$$!;=mVM^{mi#^f+;Y*j9~{7v z|BitFa@daoVlrqoe}coE3b>w(UxEPJZ|KSYDgh&>qFeHGrEG93YBOs{nK9qd9=3My~>FV;aK&EH!2g=-F5f zV5zYqz<$xLjUymvt1EKGg_GHMxNeZ~g8&93GbWIL3^JjB{31hs;6v-gw0}D2$3v@m z)LT89$bFN9i9;{~xB<@rk}zon&}e-!2S~!?5ny1`vMC%O2~*a9rcLDlnLTv`sIi+i zjRVxP)7F5NO(!5Ey2}SKJ)F#D!1YAW7zC&TDeE&yK#88Y2Jm}X0zyc-P-Ip(nazgl zAjsTaIaKoJg zSZdiC(6;3qz*5WCfR3%;0G1k30~ntO2+2t3$FBq@vz2i@8LLRZm&VwQqy=z2I5Mh- z2B|z)ch-X)*?J_ls=`!CSCg#Q#`@hF&ign(O4q0WI*qZWfQlCU5HcJtU&nPV){y|! z4vl!y)dGngT){3m#k8LAN=)lJKujA{0L8SSfDn_eLKzB&Q$M&K)5a3WW8#u+br-ms zmD}zlr(oSuqP!#Xh@}0+vx4vy7pb~t~wuO_~cDNc8ZZH3NzNM^XdgvYH6qK%J;!o^p z6Z&3oSk6({iew*!k}JjU&2fYX+O^#`0*q`^+s^?qbpHsn^}~(_IKbz4ATQ;Jo$E;w zJ1F?%K4ZGj2SdjZdqQp<0*9;fBq(JL(@UWZw}LWgf>F?{By{WuXdhM{8GSM-)MQ;p zKJ#fJU1zAHPuyIuhf3qoE{F2RROI-5z>Xa&xjg-TUFC7^lhhnv_nFuU(Wl>Ed7}HI zwmGTpGqsbWPruOe6!{DpoiMv|DjcqKm!Q&px&-pgNPIkbR%(um9QFGGdo-qY2A(`; z&Xn)G$T#$Z31>M#;?AxCTm|6(X*stBa1(?BsD6G8;G%Z{QBx*GFNDMIGUK|Y7fT@j zIJJ8j6{&E%(B(e?%s1MzOB9Mq{H5}p8&{j0?J@_@^zsNaSlhQN96-}613!F7eMl|Y{FXp&dJi8gRS@k`ATmnPTCTc{}Yp@S!OgX1W4qww6O0IA(1 zAjHch$#yfG%x=N;cyA2?x)!Zrw@E-T-7dgm5;Q4UQUmzSWd|_wYc(LX*9AnS z2;&VnnZ1eYO1&k4{F~+Qvc3fF2hf)Q<-KJ66v5jHMVh`N-+B4MTg%>c08QVk0d0HV z0W|%f2Cy^F0W|%n1|;^e1C)bL0>Dm2#x$P_2uaXR+|S@Jmcv!8^M(B9DWJ(vtH(pN zPBjHzDv;3l(H`1Y9>~|YZijCaO8x=zi^=-3c&IG#=-NLdE(82i-f{x~r1q_Vs2p2W z{skwq?{Gcb?t=s{q~5DI6dfQ&s_HN2hXtWK3NH7!Eo>GN!Ep zG&0jUKr*JU0?ZQ5-~a>28LI%38#6h;MBU6)fYVsBIKV2!tW|*S#B2_5Bkk-pfS*lv zfE#J&tO8Ukb2-3`v~$-0ejV9?@fZ+R0djUe0TrwBLtSv#Vu$NiZ%QElboAS}e2YB# z){>lz-xi)1Vcni$9S1OeQUh9+I)L%JHK1)h2QYrW3eYGm-~h&7Faq3M(6faE1f>%W zLM;r3aUrfNy{H71)=;LwQo4$Ho6BJQpQC%2`KJj0^ygs9Klo@)I?ggp#zv|XbouFMh;-AjcY*1HW3iCVmNHW z;AFNbu4}cK1pc$kZZ0_~H(VZzd`x?cp0im9g2To<397lwxa_id#3>C>{8DL0z&GzsMib*r=4&;?pow^k~@u@*UDf=hzN}!|!t8dfEhv1G2u(oLiss-sp;11^9iCmYpL3 zX?1P{xEd<8^Bh2_^97WfwHadB1&*NAg*6dQJUM_?7uSHkUE%=c;L<9f(U=32gUbWJ z$#xEqUf}?>)Rh6?S}Es>fUe!4YCzBKa9{!kT>_%MeY?w%2^n=&5#0!Mk0TQ? z>=IHm9J+kxJ_jadyj27EAub0d;ogTDzz=abFewL}YCy*xabPkII@N&09&=!F4m#C< z)Shr)3JyBefUZ5|z?4Jn=^D_pXB?Pns6AT)_yJ=Fre=3u6<{CZ3j#v%)oz9t;c)dH zt{2~zqX4Tf+`K0N72j6_K;h+vlGhxd_`V(hK4`iiZwQD{u+H!%oXpD$BOo?|N9DI@TKkSt zkDBlKJAPQz6+yQjQ1pGN)!%>|c_tR|{v2iM*Y-=4;Tzbm ziL7+azeSn)js2d=47dNt`~C?s$IrR{ zH6oyRt#$9)}s+&Pjb{x+DfQB zNVBr=?q0^LqoJ*WoHUjWyegX3R-<&stLw*jQcR{-IpW2Sh?$ahQfX^YD^!{!+DfHK zKPd9jbkfk)q>>-RTB_Yg3dqL_PNG01+Txxuu(d(cLn>??G_9>m>4&tQ%=dE9Zovr{Xu{q0v03Vx+XCYA1e6+X@Xkn<(Ay)?(>StNYzX2J*XY2Gq8l1NhxO0&E}S z!&3sH3myzRplNMKN_VkSG;kL?%RnxsWk7Ay9l*sd0=n4%7HU(&M*wYC;n5R=%^7Ie z-$d!2c9Weqh6{jTAc6vyyw;4v*TnS-s1&~FLPh83!%r+bRJGnwS;$QC!%TXBueK!S>`=2 zyS?lb8Ho2(0X;8k6m%YlUg(c_PgAwPTM;QVG)%!Lo%eK^hvQ`mCIj)F5rIZ|kIr;} zu5p%t&LKb-9(TV;Lpxj5g2R&g&N*m!vqtF-&z1SOA-qXxWgv&=Wx&YJcL0YM22_ z%h9lfiqd(nkh$}6Q8910QU>C^N4r(+^{N(lmB9H1H0-XTbl%ze5s8_wp@?#2bCCUsG&ceC zdT}0dO3gQv(X@6WrBmOeACaoGn^8o$vRjay`qls_QNx7YhMZ6nf4ChDZ`LTC`i@}0 z$_rxkcgjF#v-D;(AfGK;vSgt4 hy_Ertz3l+)dnW}L$-L_T?Rzf;h*Z5VVCKxJ{{i8mMbrQQ literal 0 HcmV?d00001 diff --git a/data/MicrobeAnnotator_KEGG/KEGG_Structural_Module_Information.pkl b/data/MicrobeAnnotator_KEGG/KEGG_Structural_Module_Information.pkl new file mode 100644 index 0000000000000000000000000000000000000000..ba8537763248ce220ebb84f0f1e6752f234d5ced GIT binary patch literal 1161 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 literal 0 HcmV?d00001 diff --git a/data/MicrobeAnnotator_KEGG/MicrobeAnnotator-KEGG.tar.gz.md5 b/data/MicrobeAnnotator_KEGG/MicrobeAnnotator-KEGG.tar.gz.md5 new file mode 100644 index 0000000..12fdf2c --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/MicrobeAnnotator-KEGG.tar.gz.md5 @@ -0,0 +1 @@ +7207b9efe0124c6e9781cf4cf4fa24de MicrobeAnnotator-KEGG.tar.gz diff --git a/data/MicrobeAnnotator_KEGG/README.md b/data/MicrobeAnnotator_KEGG/README.md new file mode 100644 index 0000000..3c1a62d --- /dev/null +++ b/data/MicrobeAnnotator_KEGG/README.md @@ -0,0 +1,69 @@ +# MicrobeAnnotator-KEGG + +**If this is used in any way, please cite the source publication:** + +Ruiz-Perez, C.A., Conrad, R.E. & Konstantinidis, K.T. MicrobeAnnotator: a user-friendly, comprehensive functional annotation pipeline for microbial genomes. BMC Bioinformatics 22, 11 (2021). https://doi.org/10.1186/s12859-020-03940-5 + +**This data has been incorporated from the following source:** + +https://github.com/cruizperez/MicrobeAnnotator/tree/master/microbeannotator/data + +**File Descriptions:** + +* `KEGG_Regular_Module_Information.pkl` - Python dictionary of regular modules from `MicrobeAnnotator` of `{id_module:structured_kegg_orthologs}` +* `KEGG_Bifurcating_Module_Information.pkl` - Python dictionary of bifurcating modules from `MicrobeAnnotator` of `{id_module:structured_kegg_orthologs}` +* `KEGG_Structural_Module_Information.pkl` - Python dictionary of structural modules from `MicrobeAnnotator` of `{id_module:structured_kegg_orthologs}` +* `KEGG_Module_Information.txt` - - Table containing KEGG ortholog, higher level categories, and module color +* `KEGG_Module-KOs.pkl` - Flattened dictionary which includes `{id_module:{KO_1, KO_2, ..., KO_M}`. Note: This is not structured and should be used cautiously as KEGG modules and completion calculations are complex. Generated with the Python code below: + +```python +import pickle, glob, os + +kegg_directory = "{}/MicrobeAnnotator_KEGG/".format(os.environ["VEBA_DATABASE"] + +delimiters = [",","_","-","+"] + +# Load MicrobeAnnotator KEGG dictionaries +module_to_kos__unprocessed = defaultdict(set) +for fp in glob.glob(os.path.join(kegg_directory, "*.pkl")): + with open(fp, "rb") as f: + d = pickle.load(f) + + for id_module, v1 in d.items(): + if isinstance(v1, list): + try: + module_to_kos__unprocessed[id_module].update(v1) + except TypeError: + for v2 in v1: + module_to_kos__unprocessed[id_module].update(v2) + else: + for k2, v2 in v1.items(): + if isinstance(v2, list): + try: + module_to_kos__unprocessed[id_module].update(v2) + except TypeError: + for v3 in v2: + module_to_kos__unprocessed[id_module].update(v3) + +# Flatten the KEGG orthologs +module_to_kos__processed = dict() +for id_module, kos_unprocessed in module_to_kos__unprocessed.items(): + kos_processed = set() + for id_ko in kos: + composite=False + for sep in delimiters: + if sep in id_ko: + id_ko = id_ko.replace(sep,";") + composite = True + if composite: + kos_composite = set(map(str.strip, filter(bool, id_ko.split(";")))) + kos_processed.update(kos_composite) + else: + kos_processed.add(id_ko) + module_to_kos__processed[id_module] = kos_processed + + +# Write +with open(os.path.join(kegg_directory, "KEGG_Module-KOs.pkl"), "wb") as f: + pickle.dump(module_to_kos__processed, f) +``` \ No newline at end of file diff --git a/data/README.md b/data/README.md index 10b3b4b..6525e90 100644 --- a/data/README.md +++ b/data/README.md @@ -9,4 +9,13 @@ The following fastq files are subsets of the original SRA sequences designed for | S3 | SRR17458630 | FASTQ | DNA | 2389989 | 75 | 150.4 | 151 | 56.38 | | S4 | SRR17458638 | FASTQ | DNA | 3142566 | 75 | 150.5 | 151 | 46.34 | -[**Download**](https://zenodo.org/record/7946802#.ZGVSpuzMKDU) \ No newline at end of file +Also includes the following: + +* Metagenomic assemblies using metaSPAdes with sorted BAM files from Bowtie2 +* Genomes, gene models, etc. +* Taxonomy classifications at the genome and genome cluster level +* Annotations for genes and protein clusters +* Biosynthetic gene clusters +* Clusters for genomes and proteins + +[**Download**](https://zenodo.org/records/10094990) \ No newline at end of file diff --git a/install/README.md b/install/README.md index d7d56b0..f92e986 100644 --- a/install/README.md +++ b/install/README.md @@ -3,16 +3,18 @@ ____________________________________________________________ #### Software installation One issue with having large-scale pipeline suites with open-source software is the issue of dependencies. One solution for this is to have a modular software structure where each module has its own `conda` environment. This allows for minimizing dependency constraints as this software suite uses an array of diverse packages from different developers. -The basis for these environments is creating a separate environment for each module with the `VEBA-` prefix and `_env` as the suffix. For example `VEBA-assembly_env` or `VEBA-binning-prokaryotic_env`. Because of this, `VEBA` is currently not available as a `conda` package but each module will be in the near future. In the meantime, please use the `veba/install/install_veba.sh` script which installs each environment from the yaml files in `veba/install/environments/`. After installing the environments, use the `veba/install/download_databases.sh` script to download and configure the databases while also adding the environment variables to the activate/deactivate scripts in each environment. To install anything manually, just read the scripts as they are well documented and refer to different URL and paths for specific installation options. +The basis for these environments is creating a separate environment for each module with the `VEBA-` prefix and `_env` as the suffix. For example `VEBA-assembly_env` or `VEBA-binning-prokaryotic_env`. Because of this, `VEBA` is currently not available as a `conda` package but each module will be in the near future. In the meantime, please use the `veba/install/install.sh` script which installs each environment from the yaml files in `veba/install/environments/`. After installing the environments, use the `veba/install/download_databases.sh` script to download and configure the databases while also adding the environment variables to the activate/deactivate scripts in each environment. To install anything manually, just read the scripts as they are well documented and refer to different URL and paths for specific installation options. -The majority of the time taken to build database is downloading/decompressing large archives, `Diamond` database creation of `UniRef`, and `MMSEQS2` database creation of microeukaryotic protein database. +The majority of the time taken to build database is downloading/decompressing large archives (e.g., `UniRef` & `GTDB`), `Diamond` database creation of `UniRef`, and `MMSEQS2` database creation of `MicroEuk` database. Total size is `243 GB` but if you have certain databases installed already then you can just symlink them so the `VEBA_DATABASE` path has the correct structure. Note, the exact size may vary as Pfam and UniRef are updated regularly. Each major version will be packaged as a [release](https://github.com/jolespin/veba/releases) which will include a log of module and script versions. -**Download Anaconda:** -[https://www.anaconda.com/products/distribution](https://www.anaconda.com/products/distribution) +**Download Miniconda (or Anaconda):** + +* [https://docs.conda.io/projects/miniconda/en/latest/](https://docs.conda.io/projects/miniconda/en/latest/) (Recommended) +* [https://www.anaconda.com/products/distribution](https://www.anaconda.com/products/distribution) ____________________________________________________________ @@ -33,7 +35,7 @@ Currently, **Conda environments for VEBA are ONLY configured for Linux** and, du * Download/configure databases -**0. Clean up your conda installation [Optional, but recommended]** +**0. Clean up your conda installation [Optional, but highly recommended]** The `VEBA` installation is going to configure some `conda` environments for you and some of them have quite a bit of packages. To minimize the likelihood of [weird errors](https://forum.qiime2.org/t/valueerror-unsupported-format-character-t-0x54-at-index-3312-when-creating-environment-from-environment-file/25237), it's recommended to do the following: @@ -83,7 +85,7 @@ The `VEBA` installation is going to configure some `conda` environments for you ``` # For stable version, download and decompress the tarball: -VERSION="1.3.0" +VERSION="1.4.0" wget https://github.com/jolespin/veba/archive/refs/tags/v${VERSION}.tar.gz tar -xvf v${VERSION}.tar.gz && mv veba-${VERSION} veba @@ -106,14 +108,16 @@ cd veba/install The update from `CheckM1` -> `CheckM2` and installation of `antiSMASH` require more memory and may require grid access if head node is limited. ``` -bash install_veba.sh +bash install.sh ``` **3. Activate the database conda environment, download, and configure databases** **Recommended resource allocatation:** 48 GB memory (time is dependent on I/O of database repositories) -⚠️ **This step should use ~48 GB memory** and should be run using a compute grid via SLURM or SunGridEngine. If this command is run on the head node it will likely fail or timeout if a connection is interrupted. The most computationally intensive steps are creating a `Diamond` database of `UniRef` and a `MMSEQS2` database of the microeukaryotic protein database. Note the duration will depend on several factors including your internet connection speed and the I/O of public repositories. +⚠️ **This step should use ~48 GB memory** and should be run using a compute grid via `SLURM` or `SunGridEngine`. **If this command is run on the head node it will likely fail or timeout if a connection is interrupted.** The most computationally intensive steps are creating a `Diamond` database of `UniRef` and a `MMSEQS2` database of the `MicroEuk100/90/50`. + +Note the duration will depend on several factors including your internet connection speed and the I/O of public repositories. **Future releases will split the downloading and configuration to better make use of resources.** @@ -163,7 +167,7 @@ qsub -o logs/${N}.o -e logs/${N}.e -cwd -N ${N} -j y -pe threaded ${N_JOBS} "${C PARTITION=[partition name] ACCOUNT=[account name] -sbatch -A ${ACCOUNT} -p ${PARTITION} -J ${N} -N 1 -c ${N_JOBS} --ntasks-per-node=1 -o logs/${N}.o -e logs/${N}.e --export=ALL -t 12:00:00 --mem=64G --wrap="${CMD}" +sbatch -A ${ACCOUNT} -p ${PARTITION} -J ${N} -N 1 -c ${N_JOBS} --ntasks-per-node=1 -o logs/${N}.o -e logs/${N}.e --export=ALL -t 16:00:00 --mem=24G --wrap="${CMD}" ``` Now, you should have the following environments: @@ -183,6 +187,7 @@ VEBA-phylogeny_env VEBA-preprocess_env VEBA-profile_env ``` + All the environments should have the `VEBA_DATABASE` environment variable set. If not, then add it manually to ~/.bash_profile: `export VEBA_DATABASE=/path/to/veba_database`. You can check to make sure the `conda` environments were created and all of the environment variables were created using the following command: @@ -218,7 +223,7 @@ ____________________________________________________________ ``` # Remove conda enivronments -bash uninstall_veba.sh +bash uninstall.sh # Remove VEBA database rm -rfv /path/to/veba_database @@ -230,6 +235,6 @@ ____________________________________________________________ There are currently 2 ways to update veba: 1. Basic uninstall reinstall - You can uninstall and reinstall using the scripts in `veba/install/` directory. It's recomended to do a fresh reinstall when updating from `v1.0.x` → `v1.2.x`. -2. Patching existing installation - Complete reinstalls of *VEBA* environments and databases is time consuming so [we've detailed how to do specific patches **for advanced users**](PATCHES.md). If you don't feel comfortable running these commands, then just do a fresh install if you would like to update. +2. Patching existing installation - TBD Guide for updating specific modules in an installation. diff --git a/install/PATCHES.md b/install/deprecated/PATCHES.md similarity index 100% rename from install/PATCHES.md rename to install/deprecated/PATCHES.md diff --git a/install/download_databases.sh b/install/download_databases.sh index 12833fd..06c4d48 100644 --- a/install/download_databases.sh +++ b/install/download_databases.sh @@ -1,11 +1,12 @@ #!/bin/bash -# __version__ = "2023.10.23" -# VEBA_DATABASE_VERSION = "VDB_v5.2" -# MICROEUKAYROTIC_DATABASE_VERSION = "VDB-Microeukaryotic_v2.1" +# __version__ = "2023.12.11" +# VEBA_DATABASE_VERSION = "VDB_v6" +# MICROEUKAYROTIC_DATABASE_VERSION = "MicroEuk_v3" # Create database DATABASE_DIRECTORY=${1:-"."} REALPATH_DATABASE_DIRECTORY=$(realpath $DATABASE_DIRECTORY) +SCRIPT_DIRECTORY=$(dirname "$0") # N_JOBS=$(2:-"1") @@ -28,7 +29,7 @@ echo ". .. ... ..... ........ ............." echo "i * Processing NCBITaxonomy" echo ". .. ... ..... ........ ............." mkdir -v -p ${DATABASE_DIRECTORY}/Classify/NCBITaxonomy -wget -v -P ${DATABASE_DIRECTORY}/Classify/NCBITaxonomy https://ftp.ncbi.nlm.nih.gov/pub/taxonomy/accession2taxid/prot.accession2taxid.FULL.gz +# wget -v -P ${DATABASE_DIRECTORY}/Classify/NCBITaxonomy https://ftp.ncbi.nlm.nih.gov/pub/taxonomy/accession2taxid/prot.accession2taxid.FULL.gz wget -v -P ${DATABASE_DIRECTORY} https://ftp.ncbi.nlm.nih.gov/pub/taxonomy/taxdump.tar.gz # python -c 'import sys; from ete3 import NCBITaxa; NCBITaxa(taxdump_file="%s/taxdump.tar.gz"%(sys.argv[1]), dbfile="%s/Classify/NCBITaxonomy/taxa.sqlite"%(sys.argv[1]))' $DATABASE_DIRECTORY tar xzfv ${DATABASE_DIRECTORY}/taxdump.tar.gz -C ${DATABASE_DIRECTORY}/Classify/NCBITaxonomy/ @@ -86,18 +87,56 @@ echo ". .. ... ..... ........ ............." echo "v * Processing Microeukaryotic MMSEQS2 database" echo ". .. ... ..... ........ ............." -# Download v2.1 from Zenodo -wget -v -O ${DATABASE_DIRECTORY}/Microeukaryotic.tar.gz https://zenodo.org/record/7485114/files/VDB-Microeukaryotic_v2.tar.gz?download=1 -mkdir -p ${DATABASE_DIRECTORY}/Classify/Microeukaryotic && tar -xvzf ${DATABASE_DIRECTORY}/Microeukaryotic.tar.gz -C ${DATABASE_DIRECTORY}/Classify/Microeukaryotic --strip-components=1 -mmseqs createdb ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.faa.gz ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/microeukaryotic -rm -rf ${DATABASE_DIRECTORY}/Microeukaryotic.tar.gz +## Download v2.1 from Zenodo +# wget -v -O ${DATABASE_DIRECTORY}/Microeukaryotic.tar.gz https://zenodo.org/record/7485114/files/VDB-Microeukaryotic_v2.tar.gz?download=1 +# mkdir -p ${DATABASE_DIRECTORY}/Classify/Microeukaryotic && tar -xvzf ${DATABASE_DIRECTORY}/Microeukaryotic.tar.gz -C ${DATABASE_DIRECTORY}/Classify/Microeukaryotic --strip-components=1 +# mmseqs createdb --compressed 1 ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.faa.gz ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/microeukaryotic +# rm -rf ${DATABASE_DIRECTORY}/Microeukaryotic.tar.gz -# eukaryota_odb10 subset of Microeukaryotic Protein Database -wget -v -O ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.list https://zenodo.org/record/7485114/files/reference.eukaryota_odb10.list?download=1 -seqkit grep -f ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.list ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.faa.gz > ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.faa -mmseqs createdb ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.faa ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/microeukaryotic.eukaryota_odb10 -rm -rf ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.faa -rm -rf ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.faa.gz # Comment this out if you want to keep the actual protein sequences +# # eukaryota_odb10 subset of Microeukaryotic Protein Database +# wget -v -O ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.list https://zenodo.org/record/7485114/files/reference.eukaryota_odb10.list?download=1 +# seqkit grep -f ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.list ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.faa.gz > ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.faa +# mmseqs createdb --compressed 1 ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.faa ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/microeukaryotic.eukaryota_odb10 +# rm -rf ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.eukaryota_odb10.faa +# rm -rf ${DATABASE_DIRECTORY}/Classify/Microeukaryotic/reference.faa.gz # Comment this out if you want to keep the actual protein sequences + +# Download MicroEuk_v3 from Zenodo +wget -v -O ${DATABASE_DIRECTORY}/MicroEuk_v3.tar.gz https://zenodo.org/records/10139451/files/MicroEuk_v3.tar.gz?download=1 +tar xvzf ${DATABASE_DIRECTORY}/MicroEuk_v3.tar.gz -C ${DATABASE_DIRECTORY} +mkdir -p ${DATABASE_DIRECTORY}/Classify/MicroEuk + +# Source Taxonomy +cp -rf ${DATABASE_DIRECTORY}/MicroEuk_v3/source_taxonomy.tsv.gz ${DATABASE_DIRECTORY}/Classify/MicroEuk + +# MicroEuk100 +gzip -d ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.faa.gz +mmseqs createdb --compressed 1 ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.faa ${DATABASE_DIRECTORY}/Classify/MicroEuk/MicroEuk100 + +# MicroEuk100.eukaryota_odb10 +gzip -d ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.eukaryota_odb10.list.gz +seqkit grep -f ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.eukaryota_odb10.list ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.faa | mmseqs createdb --compressed 1 stdin ${DATABASE_DIRECTORY}/Classify/MicroEuk/MicroEuk100 + +# MicroEuk90 +gzip -d -c ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk90_clusters.tsv.gz | cut -f1 | sort -u > ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk90.list +seqkit grep -f ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk90.list ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.faa | mmseqs createdb --compressed 1 stdin ${DATABASE_DIRECTORY}/Classify/MicroEuk/MicroEuk90 + +# MicroEuk90 +gzip -d -c ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk90_clusters.tsv.gz | cut -f1 | sort -u > ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk90.list +seqkit grep -f ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk90.list ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.faa | mmseqs createdb --compressed 1 stdin ${DATABASE_DIRECTORY}/Classify/MicroEuk/MicroEuk90 + +# MicroEuk50 +gzip -d -c ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk50_clusters.tsv.gz | cut -f1 | sort -u > ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk50.list +seqkit grep -f ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk50.list ${DATABASE_DIRECTORY}/MicroEuk_v3/MicroEuk100.faa | mmseqs createdb --compressed 1 stdin ${DATABASE_DIRECTORY}/Classify/MicroEuk/MicroEuk50 + +# source_to_lineage.dict.pkl.gz +build_source_to_lineage_dictionary.py -i ${DATABASE_DIRECTORY}/MicroEuk_v3/source_taxonomy.tsv.gz -o ${DATABASE_DIRECTORY}/Classify/MicroEuk/source_to_lineage.dict.pkl.gz + +# target_to_source.dict.pkl.gz +build_target_to_source_dictionary.py -i ${DATABASE_DIRECTORY}/MicroEuk_v3/identifier_mapping.proteins.tsv.gz -o ${DATABASE_DIRECTORY}/Classify/MicroEuk/target_to_source.dict.pkl.gz + +# Remove intermediate files +rm -rf ${DATABASE_DIRECTORY}/MicroEuk_v3/ +rm -rf ${DATABASE_DIRECTORY}/MicroEuk_v3.tar.gz # MarkerSets echo ". .. ... ..... ........ ............." @@ -213,11 +252,17 @@ rm -rf ${DATABASE_DIRECTORY}/Contamination/AntiFam/*.seed mkdir -v -p ${DATABASE_DIRECTORY}/Contamination/kmers wget -v -O ${DATABASE_DIRECTORY}/Contamination/kmers/ribokmers.fa.gz https://figshare.com/ndownloader/files/36220587 -# Replacing GRCh38 with CHM13v2.0 in v2022.10.18 +# T2T-CHM13v2.0 +# Bowtie2 Index wget -v -P ${DATABASE_DIRECTORY} https://genome-idx.s3.amazonaws.com/bt/chm13v2.0.zip unzip -d ${DATABASE_DIRECTORY}/Contamination/ ${DATABASE_DIRECTORY}/chm13v2.0.zip rm -rf ${DATABASE_DIRECTORY}/chm13v2.0.zip +# # MiniMap2 Index (Uncomment if you plan on using long reads (7.1 GB)) +# wget -v -P ${DATABASE_DIRECTORY} https://ftp.ncbi.nlm.nih.gov/genomes/refseq/vertebrate_mammalian/Homo_sapiens/latest_assembly_versions/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.fna.gz +# minimap2 -d ${DATABASE_DIRECTORY}/Contamination/chm13v2.0/chm13v2.0.mmi ${DATABASE_DIRECTORY}/GCF_009914755.1_T2T-CHM13v2.0_genomic.fna.gz +# rm -rf ${DATABASE_DIRECTORY}/GCF_009914755.1_T2T-CHM13v2.0_genomic.fna.gz + echo ". .. ... ..... ........ ............." echo "xii * Adding the following environment variable to VEBA environments: export VEBA_DATABASE=${REALPATH_DATABASE_DIRECTORY}" # CONDA_BASE=$(which conda | python -c "import sys; print('/'.join(sys.stdin.read().split('/')[:-2]))") diff --git a/install/environments/VEBA-assembly_env.yml b/install/environments/VEBA-assembly_env.yml index 692c79e..6d5a013 100644 --- a/install/environments/VEBA-assembly_env.yml +++ b/install/environments/VEBA-assembly_env.yml @@ -1,4 +1,4 @@ -name: VEBA-assembly_env__2023.5.15 +name: VEBA-assembly_env__2023.11.30 channels: - conda-forge - bioconda @@ -16,15 +16,16 @@ dependencies: - bz2file=0.98=py_0 - bzip2=1.0.8=h7f98852_4 - c-ares=1.18.1=h7f98852_0 - - ca-certificates=2022.12.7=ha878542_0 + - ca-certificates=2023.11.17=hbcca054_0 - cairo=1.16.0=ha61ee94_1014 - - certifi=2022.12.7=pyhd8ed1ab_0 + - certifi=2023.11.17=pyhd8ed1ab_0 - cffi=1.15.1=py39he91dace_2 - charset-normalizer=2.1.1=pyhd8ed1ab_0 - colorama=0.4.6=pyhd8ed1ab_0 - coreutils=9.3=h0b41bf4_0 - - cryptography=38.0.4=py39hd97740a_0 + - cryptography=41.0.7=py39hd4f0224_0 - expat=2.5.0=h27087fc_0 + - flye=2.9.3=py39hd65a603_0 - font-ttf-dejavu-sans-mono=2.37=hab24e00_0 - font-ttf-inconsolata=3.000=h77eed37_0 - font-ttf-source-code-pro=2.038=h77eed37_0 @@ -38,21 +39,22 @@ dependencies: - giflib=5.2.1=h36c2ea0_2 - graphite2=1.3.13=h58526e2_1001 - harfbuzz=5.3.0=h418a68e_0 - - htslib=1.16=h6bc39ce_0 + - htslib=1.18=h81da01d_0 - icu=70.1=h27087fc_0 - idna=3.4=pyhd8ed1ab_0 - jpeg=9e=h166bdaf_2 + - k8=0.2.5=hdcf5f25_4 - kernel-headers_linux-64=3.10.0=h4a8ded7_13 - keyutils=1.6.1=h166bdaf_0 - - krb5=1.19.3=h3790be6_0 - - lcms2=2.14=h6ed2654_0 + - krb5=1.21.2=h659d440_0 + - lcms2=2.12=hddcbb42_0 - ld_impl_linux-64=2.39=hcc3a1bd_1 - lerc=4.0.0=h27087fc_0 - libblas=3.9.0=16_linux64_openblas - libcblas=3.9.0=16_linux64_openblas - - libcups=2.3.3=h3e49a29_2 - - libcurl=7.86.0=h7bff187_1 - - libdeflate=1.13=h166bdaf_0 + - libcups=2.3.3=h4637d8d_4 + - libcurl=8.2.1=hca28451_0 + - libdeflate=1.19=hd590300_0 - libedit=3.1.20191231=he28a2e2_2 - libev=4.33=h516909a_1 - libffi=3.4.2=h7f98852_5 @@ -64,14 +66,14 @@ dependencies: - libhwloc=2.8.0=h32351e8_1 - libiconv=1.17=h166bdaf_0 - liblapack=3.9.0=16_linux64_openblas - - libnghttp2=1.47.0=hdcd2b5c_1 + - libnghttp2=1.52.0=h61bc06f_0 - libnsl=2.0.0=h7f98852_0 - libopenblas=0.3.21=pthreads_h78a6416_3 - libpng=1.6.39=h753d276_0 - libsqlite=3.40.0=h753d276_0 - - libssh2=1.10.0=haa6b8db_3 + - libssh2=1.11.0=h0841786_0 - libstdcxx-ng=12.2.0=h46fd767_19 - - libtiff=4.4.0=h0e0dad5_3 + - libtiff=4.2.0=hf544144_3 - libuuid=2.32.1=h7f98852_1000 - libwebp-base=1.2.4=h166bdaf_0 - libxcb=1.13=h7f98852_1004 @@ -79,11 +81,12 @@ dependencies: - libzlib=1.2.13=h166bdaf_4 - llvm-openmp=8.0.1=hc9558a2_0 - megahit=1.2.9=h2e03b76_1 + - minimap2=2.26=he4a0461_2 - ncurses=6.3=h27087fc_1 - numpy=1.23.5=py39h3d75532_0 - - openjdk=17.0.3=hafdced1_4 + - openjdk=11.0.1=h516909a_1016 - openmp=8.0.1=0 - - openssl=1.1.1t=h0b41bf4_0 + - openssl=3.2.0=hd590300_1 - pandas=1.5.2=py39h4661b88_0 - pathlib2=2.3.7.post1=py39hf3d152e_2 - pbzip2=1.1.13=0 @@ -93,9 +96,9 @@ dependencies: - pixman=0.40.0=h36c2ea0_0 - pthread-stubs=0.4=h36c2ea0_1001 - pycparser=2.21=pyhd8ed1ab_0 - - pyopenssl=22.1.0=pyhd8ed1ab_0 + - pyopenssl=23.3.0=pyhd8ed1ab_0 - pysocks=1.7.1=pyha2e5f31_6 - - python=3.9.15=h47a2c10_0_cpython + - python=3.9.16=h2782a2a_0_cpython - python-dateutil=2.8.2=pyhd8ed1ab_0 - python-tzdata=2022.7=pyhd8ed1ab_0 - python_abi=3.9=3_cp39 diff --git a/install/environments/VEBA-cluster_env.yml b/install/environments/VEBA-cluster_env.yml index 2f2d189..b9ff294 100644 --- a/install/environments/VEBA-cluster_env.yml +++ b/install/environments/VEBA-cluster_env.yml @@ -1,4 +1,4 @@ -name: VEBA-cluster_env__v2023.5.15 +name: VEBA-cluster_env__v2023.12.8 channels: - conda-forge - bioconda @@ -9,27 +9,36 @@ dependencies: - _openmp_mutex=4.5=2_gnu - aria2=1.36.0=h1e4e653_3 - biopython=1.80=py311hd4cff14_0 + - blast=2.14.1=pl5321h6f7f691_0 - brotlipy=0.7.0=py311hd4cff14_1005 - bz2file=0.98=py_0 - bzip2=1.0.8=h7f98852_4 - c-ares=1.18.1=h7f98852_0 - - ca-certificates=2022.12.7=ha878542_0 - - certifi=2022.12.7=pyhd8ed1ab_0 + - ca-certificates=2023.11.17=hbcca054_0 + - certifi=2023.11.17=pyhd8ed1ab_0 - cffi=1.15.1=py311h409f033_3 - charset-normalizer=2.1.1=pyhd8ed1ab_0 - colorama=0.4.6=pyhd8ed1ab_0 - coreutils=9.3=h0b41bf4_0 - cryptography=39.0.0=py311h9b4c7bb_0 - - fastani=1.33=h0fdf51a_1 + - curl=8.1.2=h409715c_0 + - diamond=2.1.8=h43eeafb_0 + - entrez-direct=16.2=he881be0_1 + - fastani=1.34=h4dfc31f_1 - gawk=5.1.0=h7f98852_0 - genopype=2023.5.15=py_0 - gettext=0.21.1=h27087fc_0 - gsl=2.7=he838d99_0 - icu=70.1=h27087fc_0 - idna=3.4=pyhd8ed1ab_0 + - keyutils=1.6.1=h166bdaf_0 + - krb5=1.20.1=h81ceb04_0 - ld_impl_linux-64=2.40=h41732ed_0 - libblas=3.9.0=16_linux64_openblas - libcblas=3.9.0=16_linux64_openblas + - libcurl=8.1.2=h409715c_0 + - libedit=3.1.20191231=he28a2e2_2 + - libev=4.33=h516909a_1 - libffi=3.4.2=h7f98852_5 - libgcc-ng=12.2.0=h65d4601_19 - libgfortran-ng=12.2.0=h69a702a_19 @@ -38,6 +47,7 @@ dependencies: - libiconv=1.17=h166bdaf_0 - libidn2=2.3.4=h166bdaf_0 - liblapack=3.9.0=16_linux64_openblas + - libnghttp2=1.52.0=h61bc06f_0 - libnsl=2.0.0=h7f98852_0 - libopenblas=0.3.21=pthreads_h78a6416_3 - libsqlite=3.40.0=h753d276_0 @@ -48,13 +58,34 @@ dependencies: - libxml2=2.10.3=h7463322_0 - libzlib=1.2.13=h166bdaf_4 - mmseqs2=14.7e284=pl5321hf1761c0_0 + - ncbi-vdb=3.0.0=pl5321h87f3376_0 - ncurses=6.3=h27087fc_1 - networkx=3.0=pyhd8ed1ab_0 - numpy=1.24.1=py311h8e6699e_0 - - openssl=3.0.8=h0b41bf4_0 + - openssl=3.2.0=hd590300_1 - pandas=1.5.3=py311h2872171_0 - pathlib2=2.3.7.post1=py311h38be061_2 + - pcre=8.45=h9c3ff4c_0 - perl=5.32.1=2_h7f98852_perl5 + - perl-archive-tar=2.40=pl5321hdfd78af_0 + - perl-carp=1.38=pl5321hdfd78af_4 + - perl-common-sense=3.75=pl5321hdfd78af_0 + - perl-compress-raw-bzip2=2.201=pl5321h87f3376_1 + - perl-compress-raw-zlib=2.105=pl5321h87f3376_0 + - perl-encode=3.19=pl5321hec16e2b_1 + - perl-exporter=5.72=pl5321hdfd78af_2 + - perl-exporter-tiny=1.002002=pl5321hdfd78af_0 + - perl-extutils-makemaker=7.70=pl5321hd8ed1ab_0 + - perl-io-compress=2.201=pl5321hdbdd923_2 + - perl-io-zlib=1.14=pl5321hdfd78af_0 + - perl-json=4.10=pl5321hdfd78af_0 + - perl-json-xs=2.34=pl5321h4ac6f70_6 + - perl-list-moreutils=0.430=pl5321hdfd78af_0 + - perl-list-moreutils-xs=0.430=pl5321h031d066_2 + - perl-parent=0.236=pl5321hdfd78af_2 + - perl-pathtools=3.75=pl5321hec16e2b_3 + - perl-scalar-list-utils=1.62=pl5321hec16e2b_1 + - perl-types-serialiser=1.01=pl5321hdfd78af_0 - pip=23.0=pyhd8ed1ab_0 - pycparser=2.21=pyhd8ed1ab_0 - pyopenssl=23.0.0=pyhd8ed1ab_0 @@ -71,6 +102,7 @@ dependencies: - seqkit=2.3.1=h9ee0642_0 - setuptools=66.1.1=pyhd8ed1ab_0 - six=1.16.0=pyh6c4a22f_0 + - skani=0.2.1=h4ac6f70_0 - soothsayer_utils=2022.6.24=py_0 - tk=8.6.12=h27826a3_0 - tqdm=4.64.1=pyhd8ed1ab_0 @@ -80,4 +112,5 @@ dependencies: - wget=1.20.3=ha35d2d1_1 - wheel=0.38.4=pyhd8ed1ab_0 - xz=5.2.6=h166bdaf_0 - - zlib=1.2.13=h166bdaf_4 \ No newline at end of file + - zlib=1.2.13=h166bdaf_4 + - zstd=1.5.5=hfc55251_0 \ No newline at end of file diff --git a/install/environments/VEBA-database_env.yml b/install/environments/VEBA-database_env.yml index 8e56e1c..f78e9c4 100644 --- a/install/environments/VEBA-database_env.yml +++ b/install/environments/VEBA-database_env.yml @@ -1,4 +1,4 @@ -name: VEBA-database_env__v2023.6.20 +name: VEBA-database_env__v2023.11.30 channels: - conda-forge - bioconda @@ -14,8 +14,8 @@ dependencies: - bz2file=0.98=py_0 - bzip2=1.0.8=h7f98852_4 - c-ares=1.19.1=hd590300_0 - - ca-certificates=2023.5.7=hbcca054_0 - - certifi=2023.5.7=pyhd8ed1ab_0 + - ca-certificates=2023.11.17=hbcca054_0 + - certifi=2023.11.17=pyhd8ed1ab_0 - charset-normalizer=3.1.0=pyhd8ed1ab_0 - colorama=0.4.6=pyhd8ed1ab_0 - coreutils=9.3=h0b41bf4_0 @@ -27,6 +27,7 @@ dependencies: - gettext=0.21.1=h27087fc_0 - icu=72.1=hcb278e6_0 - idna=3.4=pyhd8ed1ab_0 + - k8=0.2.5=hdcf5f25_4 - keyutils=1.6.1=h166bdaf_0 - krb5=1.20.1=h81ceb04_0 - ld_impl_linux-64=2.40=h41732ed_0 @@ -57,10 +58,11 @@ dependencies: - libuuid=2.38.1=h0b41bf4_0 - libxml2=2.11.4=h0d562d8_0 - libzlib=1.2.13=hd590300_5 + - minimap2=2.26=he4a0461_2 - mmseqs2=14.7e284=pl5321h6a68c12_2 - ncurses=6.4=hcb278e6_0 - numpy=1.25.0=py311h64a7726_0 - - openssl=3.1.1=hd590300_1 + - openssl=3.2.0=hd590300_1 - pandas=2.0.2=py311h320fe9a_0 - pathlib2=2.3.7.post1=py311h38be061_2 - pcre=8.45=h9c3ff4c_0 diff --git a/install/environments/VEBA-mapping_env.yml b/install/environments/VEBA-mapping_env.yml index 5af32f1..feb6918 100644 --- a/install/environments/VEBA-mapping_env.yml +++ b/install/environments/VEBA-mapping_env.yml @@ -1,106 +1,84 @@ -name: VEBA-mapping_env__v2023.7.25 +name: VEBA-mapping_env__v2023.11.17 channels: - conda-forge - bioconda - jolespin - defaults + - qiime2 dependencies: - _libgcc_mutex=0.1=conda_forge - - _openmp_mutex=4.5=1_gnu - - anndata=0.9.0=pyhd8ed1ab_0 - - bbmap=38.95=h5c4e2a8_1 - - biom-format=2.1.14=py39h72bdee0_2 - - biopython=1.79=py39h3811e60_1 - - bowtie2=2.5.1=py39h6fed5c7_2 - - brotlipy=0.7.0=py39h3811e60_1003 + - _openmp_mutex=4.5=2_gnu + - biopython=1.81=py310h2372a71_1 + - bowtie2=2.5.2=py310ha0a81b8_0 + - brotli-python=1.1.0=py310hc6cd4ac_1 - bz2file=0.98=py_0 - - bzip2=1.0.8=h7f98852_4 - - c-ares=1.18.1=h7f98852_0 + - bzip2=1.0.8=hd590300_5 + - c-ares=1.21.0=hd590300_0 - ca-certificates=2023.7.22=hbcca054_0 - - cached-property=1.5.2=hd8ed1ab_1 - - cached_property=1.5.2=pyha770c72_1 - certifi=2023.7.22=pyhd8ed1ab_0 - - cffi=1.15.0=py39h4bc2ebd_0 - - charset-normalizer=2.0.12=pyhd8ed1ab_0 - - click=8.1.3=unix_pyhd8ed1ab_2 - - colorama=0.4.4=pyh9f0ad1d_0 - - coreutils=9.3=h0b41bf4_0 - - cryptography=41.0.2=py39hd4f0224_0 + - charset-normalizer=3.3.2=pyhd8ed1ab_0 + - colorama=0.4.6=pyhd8ed1ab_0 + - coreutils=9.4=hd590300_0 - genopype=2023.5.15=py_0 - - h5py=3.7.0=nompi_py39h63b1161_100 - - hdf5=1.12.1=nompi_h4df4325_104 - - htslib=1.17=h81da01d_2 - - icu=72.1=hcb278e6_0 - - idna=3.3=pyhd8ed1ab_0 - - importlib-metadata=6.3.0=pyha770c72_0 - - importlib_metadata=6.3.0=hd8ed1ab_0 + - htslib=1.18=h81da01d_0 + - icu=73.2=h59595ed_0 + - idna=3.4=pyhd8ed1ab_0 - keyutils=1.6.1=h166bdaf_0 - - krb5=1.21.1=h659d440_0 - - ld_impl_linux-64=2.36.1=hea4e1c9_2 - - libblas=3.9.0=13_linux64_openblas - - libcblas=3.9.0=13_linux64_openblas - - libcurl=8.2.0=hca28451_0 - - libdeflate=1.18=h0b41bf4_0 + - krb5=1.21.2=h659d440_0 + - ld_impl_linux-64=2.40=h41732ed_0 + - libblas=3.9.0=19_linux64_openblas + - libcblas=3.9.0=19_linux64_openblas + - libcurl=8.4.0=hca28451_0 + - libdeflate=1.19=hd590300_0 - libedit=3.1.20191231=he28a2e2_2 - libev=4.33=h516909a_1 - libffi=3.4.2=h7f98852_5 - - libgcc-ng=12.2.0=h65d4601_19 - - libgfortran-ng=11.2.0=h69a702a_12 - - libgfortran5=11.2.0=h5c6108e_12 - - libgomp=12.2.0=h65d4601_19 - - libhwloc=2.9.1=nocuda_h7313eea_6 + - libgcc-ng=13.2.0=h807b86a_3 + - libgfortran-ng=13.2.0=h69a702a_3 + - libgfortran5=13.2.0=ha4646dd_3 + - libgomp=13.2.0=h807b86a_3 + - libhwloc=2.9.3=default_h554bfaf_1009 - libiconv=1.17=h166bdaf_0 - - liblapack=3.9.0=13_linux64_openblas - - libnghttp2=1.52.0=h61bc06f_0 - - libnsl=2.0.0=h7f98852_0 - - libopenblas=0.3.18=pthreads_h8fe5266_0 - - libsqlite=3.42.0=h2797004_0 + - liblapack=3.9.0=19_linux64_openblas + - libnghttp2=1.58.0=h47da74e_0 + - libnsl=2.0.1=hd590300_0 + - libopenblas=0.3.24=pthreads_h413a1c8_0 + - libsqlite=3.44.0=h2797004_0 - libssh2=1.11.0=h0841786_0 - - libstdcxx-ng=12.2.0=h46fd767_19 - - libuuid=2.32.1=h7f98852_1000 - - libxml2=2.11.4=h0d562d8_0 - - libzlib=1.2.13=h166bdaf_4 - - lz4-c=1.9.3=h9c3ff4c_1 - - natsort=8.3.1=pyhd8ed1ab_0 - - ncurses=6.3=h9c3ff4c_0 - - numpy=1.24.2=py39h7360e5f_0 - - openjdk=8.0.312=h7f98852_0 - - openssl=3.1.1=hd590300_1 - - packaging=23.0=pyhd8ed1ab_0 - - pandas=1.4.1=py39hde0f152_0 - - pathlib2=2.3.7.post1=py39hf3d152e_0 - - pbzip2=1.1.13=0 - - perl=5.32.1=2_h7f98852_perl5 - - pip=22.0.3=pyhd8ed1ab_0 - - pycparser=2.21=pyhd8ed1ab_0 - - pyopenssl=23.2.0=pyhd8ed1ab_1 - - pysocks=1.7.1=py39hf3d152e_4 - - python=3.9.16=h2782a2a_0_cpython + - libstdcxx-ng=13.2.0=h7e041cc_3 + - libuuid=2.38.1=h0b41bf4_0 + - libxml2=2.11.5=h232c23b_1 + - libzlib=1.2.13=hd590300_5 + - ncurses=6.4=h59595ed_2 + - numpy=1.26.0=py310hb13e2d6_0 + - openssl=3.1.4=hd590300_0 + - pandas=2.1.3=py310hcc13569_0 + - pathlib2=2.3.7.post1=py310hff52083_3 + - perl=5.32.1=4_hd590300_perl5 + - pip=23.3.1=pyhd8ed1ab_0 + - pysocks=1.7.1=pyha2e5f31_6 + - python=3.10.13=hd12c33a_0_cpython - python-dateutil=2.8.2=pyhd8ed1ab_0 - - python-tzdata=2021.5=pyhd8ed1ab_0 - - python_abi=3.9=2_cp39 - - pytz=2021.3=pyhd8ed1ab_0 - - pytz-deprecation-shim=0.1.0.post0=py39hf3d152e_1 + - python-tzdata=2023.3=pyhd8ed1ab_0 + - python_abi=3.10=4_cp310 + - pytz=2023.3.post1=pyhd8ed1ab_0 - readline=8.2=h8228510_1 - - requests=2.27.1=pyhd8ed1ab_0 - - samtools=1.17=hd87286a_1 - - scandir=1.10.0=py39h3811e60_4 - - scipy=1.9.3=py39hddc5342_2 - - setuptools=60.9.3=py39hf3d152e_0 + - requests=2.31.0=pyhd8ed1ab_0 + - salmon=0.8.1=0 + - samtools=1.18=h50ea8bc_1 + - scandir=1.10.0=py310h2372a71_7 + - seqkit=2.6.0=h9ee0642_0 + - setuptools=68.2.2=pyhd8ed1ab_0 - six=1.16.0=pyh6c4a22f_0 - soothsayer_utils=2022.6.24=py_0 - - sqlite=3.37.0=h9cd32fc_0 - - star=2.7.10a=h9ee0642_0 - - subread=2.0.3=h7132678_1 - - tbb=2021.9.0=hf52228f_0 - - tk=8.6.12=h27826a3_0 - - tqdm=4.62.3=pyhd8ed1ab_0 - - typing_extensions=4.5.0=pyha770c72_0 - - tzdata=2021e=he74cb21_0 - - tzlocal=4.1=py39hf3d152e_1 - - urllib3=1.26.8=pyhd8ed1ab_1 - - wheel=0.37.1=pyhd8ed1ab_0 + - subread=2.0.6=he4a0461_0 + - tbb=2021.10.0=h00ab1b0_2 + - tk=8.6.13=noxft_h4845f30_101 + - tqdm=4.66.1=pyhd8ed1ab_0 + - tzdata=2023c=h71feb2d_0 + - tzlocal=5.2=py310hff52083_0 + - urllib3=2.1.0=pyhd8ed1ab_0 + - wheel=0.41.3=pyhd8ed1ab_0 - xz=5.2.6=h166bdaf_0 - - zipp=3.15.0=pyhd8ed1ab_0 - - zlib=1.2.13=h166bdaf_4 - - zstd=1.5.2=ha95c52a_0 + - zlib=1.2.13=hd590300_5 + - zstd=1.5.5=hfc55251_0 \ No newline at end of file diff --git a/install/environments/VEBA-preprocess_env.yml b/install/environments/VEBA-preprocess_env.yml index d2f59b2..a7f174b 100644 --- a/install/environments/VEBA-preprocess_env.yml +++ b/install/environments/VEBA-preprocess_env.yml @@ -1,4 +1,4 @@ -name: VEBA-preprocess_env__v2023.8.21 +name: VEBA-preprocess_env__v2023.12.12 channels: - conda-forge - bioconda @@ -7,46 +7,50 @@ channels: dependencies: - _libgcc_mutex=0.1=conda_forge - _openmp_mutex=4.5=2_gnu - - alsa-lib=1.2.8=h166bdaf_0 + - alsa-lib=1.2.7.2=h166bdaf_0 - argparse-manpage-birdtools=1.7.0=pyhd8ed1ab_0 - - aria2=1.36.0=h8b6cd97_3 - - arrow-cpp=10.0.1=h3e2b116_1_cpu - - aws-c-auth=0.6.21=h3cb7b9d_0 - - aws-c-cal=0.5.20=hd3b2fe5_3 - - aws-c-common=0.8.5=h166bdaf_0 - - aws-c-compression=0.2.16=hf5f93bc_0 - - aws-c-event-stream=0.2.15=h2c1f3d0_11 - - aws-c-http=0.6.27=hb11a807_3 - - aws-c-io=0.13.11=hf1b0a34_1 - - aws-c-mqtt=0.7.13=h93e60df_9 - - aws-c-s3=0.1.51=h1222a00_14 - - aws-c-sdkutils=0.1.7=hf5f93bc_0 - - aws-checksums=0.1.13=hf5f93bc_5 - - aws-crt-cpp=0.18.16=hb1454fd_1 - - aws-sdk-cpp=1.9.379=hdc6349a_5 + - aria2=1.36.0=h1e4e653_3 + - arrow-cpp=12.0.0=ha770c72_1_cpu + - aws-c-auth=0.6.26=h2c7c9e7_6 + - aws-c-cal=0.5.26=h71eb795_0 + - aws-c-common=0.8.17=hd590300_0 + - aws-c-compression=0.2.16=h4f47f36_6 + - aws-c-event-stream=0.2.20=h69ce273_6 + - aws-c-http=0.7.7=h7b8353a_3 + - aws-c-io=0.13.21=h2c99d58_4 + - aws-c-mqtt=0.8.6=h3a1964a_15 + - aws-c-s3=0.2.8=h0933b68_4 + - aws-c-sdkutils=0.1.9=h4f47f36_1 + - aws-checksums=0.1.14=h4f47f36_6 + - aws-crt-cpp=0.19.9=h85076f6_5 + - aws-sdk-cpp=1.10.57=hf40e4db_10 - awscli=1.27.23=py39hf3d152e_0 - bbmap=39.01=h5c4e2a8_0 + - binutils_impl_linux-64=2.39=he00db2b_1 - bird_tool_utils_python=0.4.1=pyhdfd78af_0 - botocore=1.29.23=pyhd8ed1ab_0 - bowtie2=2.5.1=py39h3321a2d_0 - brotlipy=0.7.0=py39hb9d737c_1005 - bz2file=0.98=py_0 - bzip2=1.0.8=h7f98852_4 - - c-ares=1.18.1=h7f98852_0 - - ca-certificates=2023.7.22=hbcca054_0 + - c-ares=1.22.1=hd590300_0 + - ca-certificates=2023.11.17=hbcca054_0 - cairo=1.16.0=ha61ee94_1014 - - certifi=2023.7.22=pyhd8ed1ab_0 + - certifi=2023.11.17=pyhd8ed1ab_0 - cffi=1.15.1=py39he91dace_2 - charset-normalizer=2.1.1=pyhd8ed1ab_0 + - chopper=0.7.0=hdcf5f25_0 + - clang=15.0.3=ha770c72_0 + - clang-15=15.0.3=default_h2e3cab8_0 - colorama=0.4.4=pyh9f0ad1d_0 - coreutils=9.3=h0b41bf4_0 - - cryptography=38.0.4=py39hd97740a_0 - - curl=7.86.0=h7bff187_1 + - cryptography=41.0.7=py39hd4f0224_0 + - curl=8.4.0=hca28451_0 - docutils=0.16=py39hf3d152e_3 - expat=2.5.0=h27087fc_0 - extern=0.4.1=py_0 - fastp=0.23.4=h5f740d0_0 - - fastq_preprocessor=2023.7.24=py_0 + - fastq_preprocessor=2023.12.12=py_0 - font-ttf-dejavu-sans-mono=2.37=hab24e00_0 - font-ttf-inconsolata=3.000=h77eed37_0 - font-ttf-source-code-pro=2.038=h77eed37_0 @@ -55,6 +59,7 @@ dependencies: - fonts-conda-ecosystem=1=0 - fonts-conda-forge=1=0 - freetype=2.12.1=hca18f0e_1 + - gcc_impl_linux-64=12.2.0=hcc96c02_19 - genopype=2023.5.15=py_0 - gettext=0.21.1=h27087fc_0 - gflags=2.2.2=he1b5a44_1004 @@ -62,54 +67,62 @@ dependencies: - glog=0.6.0=h6f12383_0 - graphite2=1.3.13=h58526e2_1001 - harfbuzz=5.3.0=h418a68e_0 - - hdf5=1.12.1=nompi_h2386368_104 - - htslib=1.16=h6bc39ce_0 + - hdf5=1.14.2=nompi_h4f84152_100 + - htslib=1.18=h81da01d_0 - icu=70.1=h27087fc_0 - idna=3.4=pyhd8ed1ab_0 - isa-l=2.30.0=ha770c72_4 - jmespath=1.0.1=pyhd8ed1ab_0 - jpeg=9e=h166bdaf_2 + - k8=0.2.5=hdcf5f25_4 + - kernel-headers_linux-64=2.6.32=he073ed8_16 - keyutils=1.6.1=h166bdaf_0 - kingfisher=0.1.0=pyh7cba7a3_1 - - krb5=1.19.3=h3790be6_0 - - lcms2=2.14=h6ed2654_0 + - krb5=1.21.2=h659d440_0 + - lcms2=2.12=hddcbb42_0 - ld_impl_linux-64=2.39=hcc3a1bd_1 - lerc=4.0.0=h27087fc_0 - - libabseil=20220623.0=cxx17_h48a1fff_5 - - libarrow=10.0.1=hcf5dfb8_1_cpu + - libabseil=20230125.0=cxx17_hcb278e6_1 + - libaec=1.1.2=h59595ed_1 + - libarrow=12.0.0=h1cdf7b0_1_cpu - libblas=3.9.0=16_linux64_openblas - libbrotlicommon=1.0.9=h166bdaf_8 - libbrotlidec=1.0.9=h166bdaf_8 - libbrotlienc=1.0.9=h166bdaf_8 - libcblas=3.9.0=16_linux64_openblas + - libclang-cpp15=15.0.3=default_h2e3cab8_0 - libcrc32c=1.1.2=h9c3ff4c_0 - - libcups=2.3.3=h3e49a29_2 - - libcurl=7.86.0=h7bff187_1 - - libdeflate=1.13=h166bdaf_0 + - libcups=2.3.3=h4637d8d_4 + - libcurl=8.4.0=hca28451_0 + - libdeflate=1.19=hd590300_0 - libedit=3.1.20191231=he28a2e2_2 - libev=4.33=h516909a_1 - - libevent=2.1.10=h9b69904_4 + - libevent=2.1.12=hf998b51_1 - libffi=3.4.2=h7f98852_5 + - libgcc-devel_linux-64=12.2.0=h3b97bd3_19 - libgcc-ng=12.2.0=h65d4601_19 - - libgfortran-ng=12.2.0=h69a702a_19 - - libgfortran5=12.2.0=h337968e_19 + - libgfortran-ng=13.2.0=h69a702a_0 + - libgfortran5=13.2.0=ha4646dd_0 - libglib=2.74.1=h606061b_1 - libgomp=12.2.0=h65d4601_19 - - libgoogle-cloud=2.5.0=hcb5eced_0 - - libgrpc=1.49.1=h05bd8bd_1 + - libgoogle-cloud=2.10.0=hac9eb74_0 + - libgrpc=1.54.2=hcf146ea_0 - libhwloc=2.8.0=h32351e8_1 - libiconv=1.17=h166bdaf_0 - liblapack=3.9.0=16_linux64_openblas - - libnghttp2=1.47.0=hdcd2b5c_1 + - libllvm15=15.0.3=h503ea73_0 + - libnghttp2=1.58.0=h47da74e_0 - libnsl=2.0.0=h7f98852_0 + - libnuma=2.0.16=h0b41bf4_1 - libopenblas=0.3.21=pthreads_h78a6416_3 - libpng=1.6.39=h753d276_0 - - libprotobuf=3.21.10=h6239696_0 + - libprotobuf=3.21.12=hfc55251_2 + - libsanitizer=12.2.0=h46fd767_19 - libsqlite=3.40.0=h753d276_0 - - libssh2=1.10.0=haa6b8db_3 + - libssh2=1.11.0=h0841786_0 - libstdcxx-ng=12.2.0=h46fd767_19 - - libthrift=0.16.0=h491838f_2 - - libtiff=4.4.0=h0e0dad5_3 + - libthrift=0.18.1=h8fd135c_2 + - libtiff=4.2.0=hf544144_3 - libutf8proc=2.8.0=h166bdaf_0 - libuuid=2.32.1=h7f98852_1000 - libwebp-base=1.2.4=h166bdaf_0 @@ -117,12 +130,14 @@ dependencies: - libxml2=2.9.14=h22db469_4 - libzlib=1.2.13=h166bdaf_4 - lz4-c=1.9.3=h9c3ff4c_1 + - minimap2=2.26=he4a0461_2 - ncbi-ngs-sdk=2.9.0=0 + - ncbi-vdb=3.0.9=hdbdd923_0 - ncurses=6.3=h27087fc_1 - numpy=1.23.5=py39h3d75532_0 - - openjdk=17.0.3=hafdced1_4 - - openssl=1.1.1u=hd590300_0 - - orc=1.8.0=h09e0d61_0 + - openjdk=17.0.3=hea3dc9f_3 + - openssl=3.2.0=hd590300_1 + - orc=1.8.3=h2f23424_1 - ossuuid=1.6.2=hf484d3e_1000 - pandas=1.5.2=py39h4661b88_0 - parquet-cpp=1.5.1=2 @@ -164,38 +179,41 @@ dependencies: - pip=22.3.1=pyhd8ed1ab_0 - pixman=0.40.0=h36c2ea0_0 - pthread-stubs=0.4=h36c2ea0_1001 - - pyarrow=10.0.1=py39h33d4778_1_cpu + - pyarrow=12.0.0=py39he4327e9_1_cpu - pyasn1=0.4.8=py_0 - pycparser=2.21=pyhd8ed1ab_0 - - pyopenssl=22.1.0=pyhd8ed1ab_0 + - pyopenssl=23.3.0=pyhd8ed1ab_0 - pysocks=1.7.1=pyha2e5f31_6 - - python=3.9.15=h47a2c10_0_cpython + - python=3.9.16=h2782a2a_0_cpython - python-dateutil=2.8.2=pyhd8ed1ab_0 - python-tzdata=2022.7=pyhd8ed1ab_0 - python_abi=3.9=3_cp39 - pytz=2022.6=pyhd8ed1ab_0 - pytz-deprecation-shim=0.1.0.post0=py39hf3d152e_3 - pyyaml=5.4.1=py39hb9d737c_4 - - re2=2022.06.01=h27087fc_1 + - rdma-core=28.9=h59595ed_1 + - re2=2023.02.02=hcb278e6_0 - readline=8.1.2=h0f457ee_0 - requests=2.28.1=pyhd8ed1ab_1 - rsa=4.7.2=pyh44b312d_0 - - s2n=1.3.28=h8d01263_0 + - s2n=1.3.44=h06160fa_0 - s3transfer=0.6.0=pyhd8ed1ab_0 - samtools=1.16.1=h6899075_1 - scandir=1.10.0=py39hb9d737c_6 - seqkit=2.3.1=h9ee0642_0 - setuptools=65.5.1=pyhd8ed1ab_0 - six=1.16.0=pyh6c4a22f_0 - - snappy=1.1.9=hbd366e4_2 + - snappy=1.1.10=h9fff704_0 - soothsayer_utils=2022.6.24=py_0 - - sra-tools=3.0.0=pl5321hd0d85c6_1 + - sra-tools=3.0.9=h9f5acd7_0 - sracat=0.2=h9f5acd7_1 + - sysroot_linux-64=2.12=he073ed8_16 - tbb=2021.7.0=h924138e_1 - tk=8.6.12=h27826a3_0 - tqdm=4.64.1=pyhd8ed1ab_0 - tzdata=2022g=h191b570_0 - tzlocal=4.2=py39hf3d152e_2 + - ucx=1.14.1=h64cca9d_5 - urllib3=1.26.13=pyhd8ed1ab_0 - wheel=0.38.4=pyhd8ed1ab_0 - xorg-fixesproto=5.0=h7f98852_1002 @@ -218,4 +236,4 @@ dependencies: - xz=5.2.6=h166bdaf_0 - yaml=0.2.5=h7f98852_2 - zlib=1.2.13=h166bdaf_4 - - zstd=1.5.2=h6239696_4 \ No newline at end of file + - zstd=1.5.5=hfc55251_0 \ No newline at end of file diff --git a/install/environments/VEBA-profile_env.yml b/install/environments/VEBA-profile_env.yml index bccbda2..f6f3fab 100644 --- a/install/environments/VEBA-profile_env.yml +++ b/install/environments/VEBA-profile_env.yml @@ -1,4 +1,4 @@ -name: VEBA-profile_env__v2023.10.16 +name: VEBA-profile_env__v2023.12.14 channels: - conda-forge - bioconda @@ -21,12 +21,12 @@ dependencies: - bz2file=0.98=py_0 - bzip2=1.0.8=h7f98852_4 - c-ares=1.20.1=hd590300_0 - - ca-certificates=2023.7.22=hbcca054_0 + - ca-certificates=2023.11.17=hbcca054_0 - cached-property=1.5.2=hd8ed1ab_1 - cached_property=1.5.2=pyha770c72_1 - cairo=1.16.0=hb05425b_5 - capnproto=0.9.1=ha19adfc_4 - - certifi=2023.7.22=pyhd8ed1ab_0 + - certifi=2023.11.17=pyhd8ed1ab_0 - charset-normalizer=3.3.0=pyhd8ed1ab_0 - click=8.1.7=unix_pyh707e725_0 - cmseq=1.0.4=pyhb7b1952_0 @@ -119,7 +119,7 @@ dependencies: - numpy=1.26.0=py310hb13e2d6_0 - openjdk=17.0.3=h4335b31_6 - openjpeg=2.5.0=h488ebb8_3 - - openssl=3.1.3=hd590300_0 + - openssl=3.2.0=hd590300_1 - ossuuid=1.6.2=hf484d3e_1000 - packaging=23.2=pyhd8ed1ab_0 - pandas=2.1.1=py310hcc13569_1 @@ -198,6 +198,7 @@ dependencies: - six=1.16.0=pyh6c4a22f_0 - soothsayer_utils=2022.6.24=py_0 - statsmodels=0.14.0=py310h1f7b6fc_2 + - sylph=0.4.1=h4ac6f70_0 - tbb=2021.7.0=h924138e_1 - tk=8.6.13=h2797004_0 - tqdm=4.66.1=pyhd8ed1ab_0 diff --git a/install/install_veba.sh b/install/install.sh similarity index 57% rename from install/install_veba.sh rename to install/install.sh index 8c8fa6d..ac81638 100644 --- a/install/install_veba.sh +++ b/install/install.sh @@ -1,12 +1,14 @@ #!/bin/bash -# __version__ = "2023.3.27" +# __version__ = "2023.12.19" SCRIPT_PATH=$(realpath $0) PREFIX=$(echo $SCRIPT_PATH | python -c "import sys; print('/'.join(sys.stdin.read().split('/')[:-1]))") -CONDA_BASE=$(conda run -n base bash -c "echo \${CONDA_PREFIX}") +# CONDA_BASE=$(conda run -n base bash -c "echo \${CONDA_PREFIX}") +CONDA_BASE=$(conda info --base) # Update permissions echo "Updating permissions for scripts in ${PREFIX}/../src" +chmod 755 ${PREFIX}/../src/veba chmod 755 ${PREFIX}/../src/*.py chmod 755 ${PREFIX}/../src/scripts/* @@ -15,12 +17,34 @@ conda install -c conda-forge mamba -y # conda update mamba -y # Recommended # Environemnts +# Main environment +echo "Creating ${VEBA} main environment" + +ENV_NAME="VEBA" +mamba create -y -n $ENV_NAME -c conda-forge -c bioconda -c jolespin seqkit genopype networkx biopython biom-format anndata || (echo "Error when creating main VEBA environment" ; exit 1) &> ${PREFIX}/environments/VEBA.log + +# Copy main executable +echo -e "\t*Copying main VEBA executable into ${ENV_NAME} environment path" +cp -r ${PREFIX}/../src/veba ${CONDA_BASE}/envs/${ENV_NAME}/bin/ +# Copy over files to environment bin/ +echo -e "\t*Copying VEBA modules into ${ENV_NAME} environment path" +cp -r ${PREFIX}/../src/*.py ${CONDA_BASE}/envs/${ENV_NAME}/bin/ +echo -e "\t*Copying VEBA utility scripts into ${ENV_NAME} environment path" +cp -r ${PREFIX}/../src/scripts/ ${CONDA_BASE}/envs/${ENV_NAME}/bin/ +# Symlink the utility scripts to bin/ +echo -e "\t*Symlinking VEBA utility scripts into ${ENV_NAME} environment path" +ln -sf ${CONDA_BASE}/envs/${ENV_NAME}/bin/scripts/* ${CONDA_BASE}/envs/${ENV_NAME}/bin/ + +# Version +cp -rf ${PREFIX}/../VERSION ${CONDA_BASE}/envs/${ENV_NAME}/bin/VEBA_VERSION + +# Module environments for ENV_YAML in ${PREFIX}/environments/VEBA*.yml; do # Get environment name ENV_NAME=$(basename $ENV_YAML .yml) # Create conda environment - echo "Creating ${ENV_NAME} environment" + echo "Creating ${ENV_NAME} module environment" mamba env create -n $ENV_NAME -f $ENV_YAML || (echo "Error when creating VEBA environment: ${ENV_YAML}" ; exit 1) &> ${ENV_YAML}.log # Copy over files to environment bin/ @@ -32,6 +56,9 @@ for ENV_YAML in ${PREFIX}/environments/VEBA*.yml; do echo -e "\t*Symlinking VEBA utility scripts into ${ENV_NAME} environment path" ln -sf ${CONDA_BASE}/envs/${ENV_NAME}/bin/scripts/* ${CONDA_BASE}/envs/${ENV_NAME}/bin/ + # Version + cp -rf ${PREFIX}/../VERSION ${CONDA_BASE}/envs/${ENV_NAME}/bin/VEBA_VERSION + done echo -e " _ _ _______ ______ _______\n \ / |______ |_____] |_____|\n \/ |______ |_____] | |" diff --git a/install/uninstall_veba.sh b/install/uninstall.sh similarity index 100% rename from install/uninstall_veba.sh rename to install/uninstall.sh diff --git a/install/update_environment_scripts.sh b/install/update_environment_scripts.sh index 2c98bc7..59a98b0 100644 --- a/install/update_environment_scripts.sh +++ b/install/update_environment_scripts.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# __version__ = "2023.01.05" +# __version__ = "2023.12.18" # Usage: git clone https://github.com/jolespin/veba && update_environment_scripts.sh /path/to/veba_repository echo "-----------------------------------------------------------------------------------------------------" @@ -17,13 +17,14 @@ if [ $# -eq 0 ]; then chmod 775 ${VEBA_REPOSITORY_DIRECTORY}/src/* chmod 775 ${VEBA_REPOSITORY_DIRECTORY}/src/scripts/* - else + else VEBA_REPOSITORY_DIRECTORY=$1 fi -CONDA_BASE=$(conda run -n base bash -c "echo \${CONDA_PREFIX}") +# CONDA_BASE=$(conda run -n base bash -c "echo \${CONDA_PREFIX}") +CONDA_BASE=$(conda info --base) echo "-----------------------------------------------------------------------------------------------------" echo " * Source VEBA: ${VEBA_REPOSITORY_DIRECTORY}" @@ -31,9 +32,10 @@ echo " * Destination VEBA environments CONDA_BASE: ${CONDA_BASE}" echo "-----------------------------------------------------------------------------------------------------" # Environemnts -for ENV_PREFIX in ${CONDA_BASE}/envs/VEBA-*; do +for ENV_PREFIX in ${CONDA_BASE}/envs/VEBA ${CONDA_BASE}/envs/VEBA-*; +do echo $ENV_PREFIX cp ${VEBA_REPOSITORY_DIRECTORY}/src/*.py ${ENV_PREFIX}/bin/ cp -r ${VEBA_REPOSITORY_DIRECTORY}/src/scripts/ ${ENV_PREFIX}/bin/ ln -sf ${ENV_PREFIX}/bin/scripts/* ${ENV_PREFIX}/bin/ - done +done diff --git a/src/MODULE_RESOURCES b/src/MODULE_RESOURCES deleted file mode 100644 index a30553e..0000000 --- a/src/MODULE_RESOURCES +++ /dev/null @@ -1,18 +0,0 @@ -Status Environment Module Resources Recommended Threads Description -Stable VEBA-preprocess_env preprocess.py 4GB-16GB 4 Fastq quality trimming, adapter removal, decontamination, and read statistics calculations -Stable VEBA-assembly_env assembly.py 32GB-128GB+ 16 Assemble reads, align reads to assembly, and count mapped reads -Stable VEBA-assembly_env coverage.py 24GB 16 Align reads to (concatenated) reference and counts mapped reads -Stable VEBA-binning-prokaryotic_env binning-prokaryotic.py 16GB 4 Iterative consensus binning for recovering prokaryotic genomes with lineage-specific quality assessment -Stable VEBA-binning-eukaryotic_env binning-eukaryotic.py 128GB 4 Binning for recovering eukaryotic genomes with exon-aware gene modeling and lineage-specific quality assessment -Stable VEBA-binning-viral_env binning-viral.py 16GB 4 Detection of viral genomes and quality assessment -Stable VEBA-classify_env classify-prokaryotic.py 64GB 32 Taxonomic classification of prokaryotic genomes  -Stable VEBA-classify_env classify-eukaryotic.py 32GB 1 Taxonomic classification of eukaryotic genomes -Stable VEBA-classify_env classify-viral.py 16GB 4 Taxonomic classification of viral genomes -Stable VEBA-cluster_env cluster.py 32GB+ 32 Species-level clustering of genomes and lineage-specific orthogroup detection -Stable VEBA-annotate_env annotate.py 64GB 32 Annotates translated gene calls against NR, Pfam, and KOFAM -Stable VEBA-phylogeny_env phylogeny.py 16GB+ 32 Constructs phylogenetic trees given a marker set -Stable VEBA-mapping_env index.py 16GB 4 Builds local or global index for alignment to genomes -Stable VEBA-mapping_env mapping.py 16GB 4 Aligns reads to local or global index of genomes -Stable VEBA-biosynthetic_env biosynthetic.py 16GB 16 Identify biosynthetic gene clusters in prokaryotes and fungi -Developmental VEBA-assembly_env assembly-sequential.py 32GB-128GB+ 16 Assemble metagenomes sequentially -Developmental VEBA-amplicon_env amplicon.py 96GB 16 Automated read trim position detection, DADA2 ASV detection, taxonomic classification, and file conversion \ No newline at end of file diff --git a/src/README.md b/src/README.md index 574149f..790091e 100755 --- a/src/README.md +++ b/src/README.md @@ -3,25 +3,29 @@ # Modules [![Schematic](../images/Schematic.png)](../images/Schematic.pdf) -| Status | Environment | Module | Resources | Recommended Threads | Description | -|---------------|------------------------------|-------------------------|-------------|---------------------|-----------------------------------------------------------------------------------------------------------------| -| Stable | [VEBA-preprocess_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-preprocess_env.yml) | [preprocess.py](https://github.com/jolespin/veba/tree/main/src#preprocesspy) | 4GB-16GB | 4 | Fastq quality trimming, adapter removal, decontamination, and read statistics calculations | -| Stable | [VEBA-assembly_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-assembly_env.yml) | [assembly.py](https://github.com/jolespin/veba/tree/main/src#assemblypy) | 32GB-128GB+ | 4-16 | Assemble reads, align reads to assembly, and count mapped reads | -| Stable | [VEBA-assembly_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-assembly_env.yml) | [coverage.py](https://github.com/jolespin/veba/tree/main/src#coveragepy) | 24GB | 16 | Align reads to (concatenated) reference and counts mapped reads | -| Stable | [VEBA-binning-prokaryotic_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-binning-prokaryotic_env.yml) | [binning-prokaryotic.py](https://github.com/jolespin/veba/tree/main/src#binning-prokaryoticpy) | 16GB | 4 | Iterative consensus binning for recovering prokaryotic genomes with lineage-specific quality assessment | -| Stable | [VEBA-binning-eukaryotic_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-binning-eukaryotic_env.yml) | [binning-eukaryotic.py](https://github.com/jolespin/veba/tree/main/src#binning-eukaryoticpy) | 128GB | 4 | Binning for recovering eukaryotic genomes with exon-aware gene modeling and lineage-specific quality assessment | -| Stable | [VEBA-binning-viral_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-binning-viral_env.yml) | [binning-viral.py](https://github.com/jolespin/veba/tree/main/src#binning-viralpy) | 16GB | 4 | Detection of viral genomes and quality assessment | -| Stable | [VEBA-classify_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-classify_env.yml) | [classify-prokaryotic.py](https://github.com/jolespin/veba/tree/main/src#classify-prokaryoticpy) | 72GB | 32 | Taxonomic classification of prokaryotic genomes | -| Stable | [VEBA-classify_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-classify_env.yml) | [classify-eukaryotic.py](https://github.com/jolespin/veba/tree/main/src#classify-eukaryoticpy) | 32GB | 1 | Taxonomic classification of eukaryotic genomes | -| Stable | [VEBA-classify_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-classify_env.yml) | [classify-viral.py](https://github.com/jolespin/veba/tree/main/src#classify-viralpy) | 16GB | 4 | Taxonomic classification of viral genomes | -| Stable | [VEBA-cluster_env](https://github.com/jolespin/veba/blob/main/install/environments/[VEBA-cluster_env.yml) | [cluster.py](https://github.com/jolespin/veba/tree/main/src#clusterpy) | 32GB+ | 32 | Species-level clustering of genomes and lineage-specific orthogroup detection | -| Stable | [VEBA-annotate_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-annotate_env.yml) | [annotate.py](https://github.com/jolespin/veba/tree/main/src#annotatepy) | 64GB | 32 | Annotates translated gene calls against UniRef, MiBIG, VFDB, Pfam, AntiFam, and KOFAM | -| Stable | [VEBA-phylogeny_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-phylogeny_env.yml) | [phylogeny.py](https://github.com/jolespin/veba/tree/main/src#phylogenypy) | 16GB+ | 32 | Constructs phylogenetic trees given a marker set | -| Stable | [VEBA-mapping_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-mapping_env.yml) | [index.py](https://github.com/jolespin/veba/tree/main/src#indexpy) | 16GB | 4 | Builds local or global index for alignment to genomes | -| Stable | [VEBA-mapping_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-mapping_env.yml) | [mapping.py](https://github.com/jolespin/veba/tree/main/src#mappingpy) | 16GB | 4 | Aligns reads to local or global index of genomes | -| Stable | [VEBA-biosynthetic_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-biosynthetic_env.yml) | [biosynthetic.py](https://github.com/jolespin/veba/tree/main/src#biosyntheticpy) | 16GB | 16 | Identify biosynthetic gene clusters in prokaryotes and fungi | -| Developmental | [VEBA-assembly_env](https://github.com/jolespin/veba/blob/main/install/environments/VEBA-assembly_env.yml) | [assembly-sequential.py](https://github.com/jolespin/veba/tree/main/src#assembly-sequentialpy) | 32GB-128GB+ | 16 | Assemble metagenomes sequentially | -| Developmental | [VEBA-amplicon_env](https://github.com/jolespin/veba/blob/main/install/environments/devel/VEBA-amplicon_env.yml) | [amplicon.py](https://github.com/jolespin/veba/tree/main/src#ampliconpy) | 96GB | 16 | Automated read trim position detection, DADA2 ASV detection, taxonomic classification, and file conversion | +| Status | Module | Environment | Executable | Resources | Recommended Threads | Description | +|---------------|----------------------|------------------------------|-------------------------|-------------|---------------------|-------------------------------------------------------------------------------------------------------------------| +| Stable | preprocess | VEBA-preprocess_env | preprocess.py | 4GB-16GB | 4 | Fastq quality trimming, adapter removal, decontamination, and read statistics calculations (Short Reads) | +| Stable | preproces-long | VEBA-preprocess_env | preproces-long.py | 4GB-16GB | 4 | Fastq quality trimming, adapter removal, decontamination, and read statistics calculations (Long Reads) | +| Stable | assembly | VEBA-assembly_env | assembly.py | 32GB-128GB+ | 16 | Assemble short reads, align reads to assembly, and count mapped reads | +| Stable | assembly-long | VEBA-assembly_env | assembly-long.py | 32GB-128GB+ | 16 | Assemble long reads, align reads to assembly, and count mapped reads | +| Stable | coverage | VEBA-assembly_env | coverage.py | 24GB | 16 | Align short reads to (concatenated) reference and counts mapped reads | +| Stable | coverage-long | VEBA-assembly_env | coverage-long.py | 24GB | 16 | Align long reads to (concatenated) reference and counts mapped reads | +| Stable | binning-prokaryotic | VEBA-binning-prokaryotic_env | binning-prokaryotic.py | 16GB | 4 | Iterative consensus binning for recovering prokaryotic genomes with lineage-specific quality assessment | +| Stable | binning-eukaryotic | VEBA-binning-eukaryotic_env | binning-eukaryotic.py | 128GB | 4 | Binning for recovering eukaryotic genomes with exon-aware gene modeling and lineage-specific quality assessment | +| Stable | binning-viral | VEBA-binning-viral_env | binning-viral.py | 16GB | 4 | Detection of viral genomes and quality assessment | +| Stable | classify-prokaryotic | VEBA-classify_env | classify-prokaryotic.py | 64GB | 32 | Taxonomic classification of prokaryotic genomes | +| Stable | classify-eukaryotic | VEBA-classify_env | classify-eukaryotic.py | 32GB | 1 | Taxonomic classification of eukaryotic genomes | +| Stable | classify-viral | VEBA-classify_env | classify-viral.py | 16GB | 4 | Taxonomic classification of viral genomes | +| Stable | cluster | VEBA-cluster_env | cluster.py | 32GB+ | 32 | Species-level clustering of genomes and lineage-specific orthogroup detection | +| Stable | annotate | VEBA-annotate_env | annotate.py | 64GB | 32 | Annotates translated gene calls against NR, Pfam, and KOFAM | +| Stable | phylogeny | VEBA-phylogeny_env | phylogeny.py | 16GB+ | 32 | Constructs phylogenetic trees given a marker set | +| Stable | index | VEBA-mapping_env | index.py | 16GB | 4 | Builds local or global index for alignment to genomes | +| Stable | mapping | VEBA-mapping_env | mapping.py | 16GB | 4 | Aligns reads to local or global index of genomes | +| Stable | biosynthetic | VEBA-biosynthetic_env | biosynthetic.py | 16GB | 16 | Identify biosynthetic gene clusters in prokaryotes and fungi | +| Stable | profile-pathway | VEBA-profile_env | profile-pathway.py | 16GB | 4 | Pathway profiling of de novo genomes | +| Deprecated | assembly-sequential | VEBA-assembly_env | assembly-sequential.py | 32GB-128GB+ | 16 | Assemble metagenomes sequentially | +| Developmental | amplicon | VEBA-amplicon_env | amplicon.py | 96GB | 16 | Automated read trim position detection, DADA2 ASV detection, taxonomic classification, and file conversion |