genomicepidemiology-kma-091b8ffe66ac/0000755000175000017500000000000014157033525017111 5ustar nileshnileshgenomicepidemiology-kma-091b8ffe66ac/hashtable.h0000644000175000017500000000316314157033525021220 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "hashmapkma.h" #include "hashmapkmers.h" #ifndef HASHTABLE typedef struct hashTable HashTable; typedef struct hit Hit; struct hashTable { long unsigned key; unsigned *value; struct hashTable *next; }; struct hit { long unsigned n; long unsigned tot; }; #define HASHTABLE 1 #endif int intpos_bin(const unsigned *str1, const int str2); HashTable * collect_Kmers(const HashMapKMA *templates, unsigned *Scores, long unsigned *Scores_tot, HashMap_kmers *foundKmers, Hit *hits); HashTable ** collect_Kmers_deCon(const HashMapKMA *templates, unsigned *Scores, long unsigned *Scores_tot, HashMap_kmers *foundKmers, Hit *hits, int contamination); HashTable * withDraw_Kmers(unsigned *Scores, long unsigned *Scores_tot, HashTable *kmerList, int template, Hit *hits); Hit withDraw_Contamination(unsigned *Scores, long unsigned *Scores_tot, HashTable *kmerList, HashTable *deConTable, int template, Hit hits); genomicepidemiology-kma-091b8ffe66ac/qualcheck.c0000644000175000017500000002254014157033525021220 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "compdna.h" #include "hashmap.h" #include "pherror.h" #include "qualcheck.h" #include "stdnuc.h" #include "stdstat.h" int (*QualCheck)(HashMap *templates, CompDNA *, int, double, double, unsigned *, Qseqs *) = &lengthCheck; int lengthCheck(HashMap *templates, CompDNA *qseq, int MinKlen, double homQ, double homT, unsigned *template_ulengths, Qseqs *header) { int i, j, end, rc, thisKlen, prefix_len, prefix_shifter; long unsigned prefix; thisKlen = MinKlen; prefix = templates->prefix; prefix_len = templates->prefix_len; prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (prefix_len << 1); if(qseq->seqlen < templates->kmersize) { return 0; } else if(prefix_len == 0) { if((qseq->seqlen - templates->kmersize + 1) * 2 < MinKlen) { return 0; } else { comp_rc(qseq); return 1; } } for(rc = 0; rc < 2; ++rc) { /* revers complement */ if(rc) { comp_rc(qseq); } /* iterate seq */ qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1, j = 0; i <= qseq->N[0] && thisKlen != 0; ++i) { end = qseq->N[i] - prefix_len - templates->kmersize + 1; for(;j < end && thisKlen != 0; ++j) { if(getKmer(qseq->seq, j, prefix_shifter) == prefix) { --thisKlen; } } j = qseq->N[i] + 1; } qseq->N[0]--; } if(thisKlen) { return 0; } else { return 1; } } int queryCheck(HashMap *templates, CompDNA *qseq, int MinKlen, double homQ, double homT, unsigned *template_ulengths, Qseqs *header) { static unsigned *Scores_tot = 0, *bestTemplates = 0; int i, j, end, rc, template; unsigned thisKlen, prefix_len, prefix_shifter, shifter, DB_size, *values; double bestQ, thisQ; long unsigned prefix; void (*updateScoreAndTemplate_ptr)(unsigned *, unsigned *, unsigned *); thisKlen = 0; prefix_len = templates->prefix_len; if(qseq->seqlen < templates->kmersize + prefix_len) { return 0; } else if(prefix_len == 0 && templates->prefix != 0) { prefix = 0; } else { prefix = templates->prefix; } prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (prefix_len << 1); shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); DB_size = templates->DB_size; /* realloc */ if(!bestTemplates) { bestTemplates = smalloc(1024 * sizeof(unsigned)); Scores_tot = calloc(1024, sizeof(unsigned)); if(!Scores_tot) { ERROR(); } *Scores_tot = 1024; } else if(DB_size >= *Scores_tot) { free(Scores_tot); Scores_tot = calloc(2 * DB_size, sizeof(unsigned)); free(bestTemplates); bestTemplates = malloc(2 * DB_size * sizeof(unsigned)); if(!Scores_tot || !bestTemplates) { ERROR(); } *Scores_tot = 2 * DB_size; } if(DB_size < USHRT_MAX) { updateScoreAndTemplate_ptr = &updateScoreAndTemplateHU; } else { updateScoreAndTemplate_ptr = &updateScoreAndTemplate; } /* get scores */ bestTemplates[0] = 0; for(rc = 0; rc < 2; ++rc) { /* revers complement */ if(rc) { comp_rc(qseq); } /* iterate seq */ qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1, j = 0; i <= qseq->N[0]; ++i) { end = qseq->N[i] - prefix_len - templates->kmersize + 1; for(;j < end; ++j) { if(prefix_len == 0 || getKmer(qseq->seq, j, prefix_shifter) == prefix) { ++thisKlen; if((values = hashMapGet(templates, getKmer(qseq->seq, j + prefix_len, shifter)))) { updateScoreAndTemplate_ptr(Scores_tot, bestTemplates, values); } } } j = qseq->N[i] + 1; } qseq->N[0]--; } if(thisKlen < MinKlen) { for(i = 1; i <= *bestTemplates; ++i) { Scores_tot[bestTemplates[i]] = 0; } return 0; } /* get query cov */ bestQ = 0; template = 0; for(i = 1; i <= *bestTemplates; ++i) { thisQ = 1.0 * Scores_tot[bestTemplates[i]] / thisKlen; if(bestQ < thisQ) { bestQ = thisQ; template = bestTemplates[i]; } Scores_tot[bestTemplates[i]] = 0; } if(bestQ < homQ) { fprintf(stdout, "%s\t%d\t%f\t%d\n", header->seq + 1, DB_size, bestQ, template); return 1; } else { fprintf(stdout, "%s\t%d\t%f\t%d\n", header->seq + 1, template, bestQ, template); return 0; } } int templateCheck(HashMap *templates, CompDNA *qseq, int MinKlen, double homQ, double homT, unsigned *template_ulengths, Qseqs *header) { static unsigned *Scores = 0, *Scores_tot = 0, *bestTemplates = 0; static HashMap_kmers *foundKmers = 0; int i, j, end, rc, templateQ, templateT; unsigned thisKlen, prefix_len, prefix_shifter, shifter, DB_size, *values; double bestQ, thisQ, bestT, thisT; long unsigned key, prefix; void (*updateScoreAndTemplate_ptr)(unsigned *, unsigned *, unsigned *); void (*addUscore_ptr)(unsigned *, unsigned *); thisKlen = 0; prefix_len = templates->prefix_len; if(qseq->seqlen < templates->kmersize + prefix_len) { return 0; } else if(prefix_len == 0 && templates->prefix != 0) { prefix = 0; } else { prefix = templates->prefix; } prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (prefix_len << 1); shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); DB_size = templates->DB_size; if(DB_size < USHRT_MAX) { updateScoreAndTemplate_ptr = &updateScoreAndTemplateHU; addUscore_ptr = &addUscoreHU; } else { updateScoreAndTemplate_ptr = &updateScoreAndTemplate; addUscore_ptr = &addUscore; } if(foundKmers == 0) { foundKmers = smalloc(sizeof(HashMap_kmers)); foundKmers->n = 0; foundKmers->size = templates->size; foundKmers->table = calloc(foundKmers->size + 1, sizeof(HashTable_kmers *)); Scores = calloc(1024, sizeof(unsigned)); Scores_tot = calloc(1024, sizeof(unsigned)); bestTemplates = smalloc(1024 * sizeof(unsigned)); if(!Scores || !Scores_tot || !foundKmers->table) { ERROR(); } *Scores_tot = 1024; } /* realloc */ if(DB_size >= *Scores_tot) { free(Scores); Scores = calloc(2 * DB_size, sizeof(unsigned)); free(Scores_tot); Scores_tot = calloc(2 * DB_size, sizeof(unsigned)); free(bestTemplates); bestTemplates = malloc(2 * DB_size * sizeof(unsigned)); if(!Scores || !Scores_tot || !bestTemplates) { ERROR(); } Scores_tot[0] = 2 * DB_size; } /* get scores */ bestTemplates[0] = 0; for(rc = 0; rc < 2; ++rc) { /* revers complement */ if(rc) { comp_rc(qseq); } /* iterate seq */ qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1, j = 0; i <= qseq->N[0]; ++i) { end = qseq->N[i] - prefix_len - templates->kmersize + 1; for(;j < end; ++j) { if(prefix_len == 0 || getKmer(qseq->seq, j, prefix_shifter) == prefix) { ++thisKlen; key = getKmer(qseq->seq, j + prefix_len, shifter); if((values = hashMapGet(templates, key))) { updateScoreAndTemplate_ptr(Scores_tot, bestTemplates, values); if(hashMap_CountKmer(foundKmers, key)) { addUscore_ptr(Scores, values); } } } } j = qseq->N[i] + 1; } qseq->N[0]--; } if(thisKlen < MinKlen) { return 0; } /* get query cov */ bestQ = 0; templateQ = 0; bestT = 0; templateT = 0; for(i = 1; i <= *bestTemplates; ++i) { thisQ = 1.0 * Scores_tot[bestTemplates[i]] / thisKlen; if(thisQ > bestQ) { bestQ = thisQ; templateQ = bestTemplates[i]; } thisT = 1.0 * Scores[bestTemplates[i]] / template_ulengths[bestTemplates[i]]; if(thisT > bestT) { bestT = thisT; templateT = bestTemplates[i]; } Scores_tot[bestTemplates[i]] = 0; Scores[bestTemplates[i]] = 0; } emptyHash(foundKmers); if(thisKlen >= MinKlen) { if(cmp(bestT < homT, bestQ < homQ)) { fprintf(stdout, "%s\t%d\t%f\t%d\t%f\t%d\n", header->seq + 1, DB_size, bestQ, templateQ, bestT, templateT); return 1; } else { fprintf(stdout, "%s\t%d\t%f\t%d\t%f\t%d\n", header->seq + 1, (bestT < homT) ? templateQ : templateT, bestQ, templateQ, bestT, templateT); return 0; } } else { return 0; } } void updateScoreAndTemplate(unsigned *Scores_tot, unsigned *bestTemplates, unsigned *values) { unsigned i; i = *values + 1; while(--i) { if(Scores_tot[*++values] == 0) { bestTemplates[0]++; bestTemplates[*bestTemplates] = *values; } Scores_tot[*values]++; } } void updateScoreAndTemplateHU(unsigned *Scores_tot, unsigned *bestTemplates, unsigned *values_org) { unsigned i; short unsigned *values; values = (short unsigned *)(values_org); i = *values + 1; while(--i) { if(Scores_tot[*++values] == 0) { bestTemplates[0]++; bestTemplates[*bestTemplates] = *values; } Scores_tot[*values]++; } } void addUscore(unsigned *Scores, unsigned *values) { unsigned i; i = *values + 1; while(--i) { Scores[*++values]++; } } void addUscoreHU(unsigned *Scores, unsigned *values_org) { unsigned i; short unsigned *values; values = (short unsigned *)(values_org); i = *values + 1; while(--i) { Scores[*++values]++; } } genomicepidemiology-kma-091b8ffe66ac/hashtable.c0000644000175000017500000001635114157033525021216 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "hashmapkma.h" #include "hashmapkmers.h" #include "hashtable.h" #include "pherror.h" int intpos_bin(const unsigned *str1, const int str2) { int pos, upLim, downLim; upLim = *str1; if(upLim == 0) { return -1; } downLim = 1; pos = (upLim + downLim) >> 1; while(0 < (upLim - downLim)) { if(str1[pos] == str2) { return pos; } else if(str1[pos] < str2) { downLim = pos + 1; } else { upLim = pos - 1; } pos = (upLim + downLim) >> 1; } if(str1[pos] == str2) { return pos; } return -1; } HashTable * collect_Kmers(const HashMapKMA *templates, unsigned *Scores, long unsigned *Scores_tot, HashMap_kmers *foundKmers, Hit *hits) { int template, SU; unsigned i, j, *value; short unsigned *values_s; HashTable_kmers *node, *node_next; HashTable *kmerNode, *kmerList; if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } hits->n = 0; hits->tot = 0; kmerList = 0; kmerNode = 0; for(i = 0; i < foundKmers->size; ++i) { for(node = foundKmers->table[i]; node != 0; node = node_next) { node_next = node->next; value = hashMap_get(templates, node->key); if(value) { ++hits->n; hits->tot += node->value; kmerNode = malloc(sizeof(HashTable)); if(!kmerNode) { ERROR(); } if(SU) { values_s = (short unsigned *) value; kmerNode->value = smalloc(((*values_s) + 1) * sizeof(unsigned)); *(kmerNode->value) = *values_s; j = *values_s + 1; while(--j) { template = values_s[j]; kmerNode->value[j] = template; Scores[template]++; Scores_tot[template] += node->value; } } else { kmerNode->value = smalloc(((*value) + 1) * sizeof(unsigned)); *(kmerNode->value) = *value; j = *value + 1; while(--j) { template = value[j]; kmerNode->value[j] = template; Scores[template]++; Scores_tot[template] += node->value; } } kmerNode->key = node->value; kmerNode->next = kmerList; kmerList = kmerNode; } free(node); } } free(foundKmers->table); return kmerList; } HashTable ** collect_Kmers_deCon(const HashMapKMA *templates, unsigned *Scores, long unsigned *Scores_tot, HashMap_kmers *foundKmers, Hit *hits, int contamination) { int template, SU; unsigned i, j, n, *value; short unsigned *value_s; HashTable_kmers *node, *node_next; HashTable *kmerNode, *kmerList; HashTable *decon_node, *deconList; HashTable **Returner; if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } value_s = 0; hits->n = 0; hits->tot = 0; kmerList = 0; kmerNode = 0; deconList = 0; decon_node = 0; Returner = smalloc(sizeof(HashTable *) << 1); for(i = 0; i < foundKmers->size; ++i) { for(node = foundKmers->table[i]; node != 0; node = node_next) { node_next = node->next; if((value = hashMap_get(templates, node->key))) { /* check for contamination */ ++hits->n; hits->tot += node->value; if(SU) { value_s = (short unsigned *) value; n = *value_s; j = value_s[*value_s]; } else { n = *value; j = value[*value]; } if(j == contamination) { decon_node = smalloc(sizeof(HashTable)); decon_node->value = smalloc((n + 1) * sizeof(unsigned)); decon_node->value[0] = n; j = n + 1; if(SU) { while(--j) { decon_node->value[j] = value_s[j]; } } else { while(--j) { decon_node->value[j] = value[j]; } } decon_node->key = node->value; decon_node->next = deconList; deconList = decon_node; } else { kmerNode = smalloc(sizeof(HashTable)); kmerNode->value = smalloc((n + 1) * sizeof(unsigned)); kmerNode->value[0] = n; j = n + 1; if(SU) { while(--j) { template = value_s[j]; kmerNode->value[j] = template; Scores[template]++; Scores_tot[template] += node->value; } } else { while(--j) { template = value[j]; kmerNode->value[j] = template; Scores[template]++; Scores_tot[template] += node->value; } } kmerNode->key = node->value; kmerNode->next = kmerList; kmerList = kmerNode; } } free(node); } } free(foundKmers->table); Returner[0] = kmerList; Returner[1] = deconList; return Returner; } HashTable * withDraw_Kmers(unsigned *Scores, long unsigned *Scores_tot, HashTable *kmerList, int template, Hit *hits) { unsigned i; HashTable *node, *prev; prev = 0; if(kmerList == 0) { return 0; } node = kmerList; while(node != 0) { if(intpos_bin(node->value, template) != -1) { --hits->n; hits->tot -= node->key; for(i = 1; i <= node->value[0]; ++i) { Scores[node->value[i]]--; Scores_tot[node->value[i]] -= node->key; } if(prev == 0) { kmerList = node->next; free(node->value); free(node); node = kmerList; } else { prev->next = node->next; free(node->value); free(node); node = prev->next; } /* early stopping */ if(Scores[template] == 0 && Scores_tot[template] == 0) { return kmerList; } } else { prev = node; node = node->next; } } if(prev != 0) { prev->next = 0; } return kmerList; } Hit withDraw_Contamination(unsigned *Scores, long unsigned *Scores_tot, HashTable *kmerList, HashTable *deConTable, int template, Hit hits) { unsigned i, belong; HashTable *node, *prev; HashTable *cont_node, *cont_prev; if(kmerList != 0) { prev = 0; node = kmerList; cont_prev = 0; cont_node = deConTable; while(node != 0) { /* check if k-mer belongs to template */ belong = 0; for(i = node->value[0]; i != 0 && !belong; --i) { if(node->value[i] == template) { belong = 1; } } if(belong) { //withdraw score --hits.n; hits.tot -= node->key; for(i = node->value[0]; i != 0; --i) { Scores[node->value[i]]--; Scores_tot[node->value[i]] -= node->key; } cont_node->value = node->value; cont_node->key = node->key; cont_node->next = smalloc(sizeof(HashTable)); cont_prev = cont_node; cont_node = cont_node->next; /* delete node */ if(prev == 0) { kmerList = node->next; free(node); node = kmerList; } else { prev->next = node->next; free(node); node = prev->next; } } else { prev = node; node = node->next; } } if(cont_prev != 0) { free(cont_prev->next); cont_prev->next = 0; } else { free(deConTable); deConTable = 0; } } else { free(deConTable); deConTable = 0; } return hits; } genomicepidemiology-kma-091b8ffe66ac/qseqs.h0000644000175000017500000000176314157033525020425 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef QSEQS typedef struct qseqs Qseqs; struct qseqs { unsigned size; unsigned len; unsigned char *seq; }; #define QSEQS 1 #endif /* initialize Qseqs */ Qseqs * setQseqs(unsigned size); /* destroy Qseqs */ void destroyQseqs(Qseqs *dest); void insertKmerBound(Qseqs *header, int start, int end); genomicepidemiology-kma-091b8ffe66ac/pherror.h0000644000175000017500000000320314157033525020741 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include /* errno error message */ #define ERROR() fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); exit(errno); /* succes or exit */ #define sfwrite(ptr, size, nmemb, stream) if(fwrite(ptr, size, nmemb, stream) != nmemb) {if(errno) {ERROR();} else {fprintf(stderr, "Writing error.\n"); exit(1);}} #define sfread(ptr, size, nmemb, stream) if(fread(ptr, size, nmemb, stream) != nmemb) {if(errno) {ERROR();} else {fprintf(stderr, "Reading error.\n"); exit(1);}} #define sfseek(stream, offset, whence) if(fseek(stream, offset, whence)) {if(errno) {ERROR();} else {fprintf(stderr, "fseek error.\n"); exit(1);}} void * smalloc(const size_t size); FILE * sfopen(const char *filename, const char *mode); /* cyclic */ void cfread(void *src, size_t size, size_t nmemb, FILE *stream); void cfwrite(const void *src, size_t size, size_t nmemb, FILE *stream); genomicepidemiology-kma-091b8ffe66ac/loadupdate.c0000644000175000017500000001255414157033525021406 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "loadupdate.h" #include "pherror.h" #include "hashmap.h" #include "hashmapkma.h" #include "updateindex.h" void * memdup(const void * src, size_t size) { void *dest; dest = smalloc(size); memcpy(dest, src, size); return dest; } int CP(char *templatefilename, char *outputfilename) { int bytes, buffSize; char *buffer; FILE *file_in, *file_out; if(strcmp(templatefilename, outputfilename) == 0) { return 1; } file_in = sfopen(templatefilename, "rb"); file_out = sfopen(outputfilename, "wb"); buffer = smalloc((buffSize = 1048576)); while((bytes = fread(buffer, 1, buffSize, file_in))) { cfwrite(buffer, 1, bytes, file_out); } fclose(file_in); fclose(file_out); free(buffer); return 0; } HashMap * hashMapKMA_openChains(HashMapKMA *src) { long unsigned i, key; unsigned *values; HashMap *dest; if(src->mask != src->size) { free(src->exist); } dest = hashMap_initialize(src->size + 1, src->kmersize); dest->prefix = src->prefix; dest->prefix_len = src->prefix_len; dest->DB_size = src->DB_size; if(dest->size == dest->mask) { addUniqueValues = &megaMap_addUniqueValues; } else { addUniqueValues = &hashMap_addUniqueValues; } if(src->mask != src->size) { /* norm */ i = src->n; while(i--) { key = getKeyPtr(src->key_index, i); values = getValuePtr(src, getValueIndexPtr(src->value_index, i)); values = memdup(values, getSizePtr(values)); addUniqueValues(dest, key, values); } free(src->key_index); free(src->value_index); } else { /* mega */ i = src->size + 1; while(i--) { if(getExistPtr(src->exist, i) != 1) { values = getValuePtr(src, i); values = memdup(values, getSizePtr(values)); addUniqueValues(dest, i, values); } } free(src->exist); } free(src->values); free(src); return dest; } unsigned ** hashMapKMA_openValues(HashMapKMA *src) { long unsigned i, index, pos; unsigned *values, **Values; Values = smalloc(src->n * sizeof(unsigned *)); index = src->n; if(src->mask != (src->size - 1)) { /* norm */ i = src->n; while(i--) { /* get key and values */ values = getValuePtr(src, getValueIndexPtr(src->value_index, i)); Values[i] = memdup(values, getSizePtr(values)); hashMapKMA_addValue_ptr(src, i, i); } } else { /* mega */ i = src->size; getSizePtr = &getSizeS; while(i--) { if((pos = getExistPtr(src->exist, i)) != 1) { /* get key and values */ values = getValuePtr(src, pos); Values[--index] = memdup(values, getSizePtr(values)); hashMapKMA_addExist_ptr(src, i, index); } else { hashMapKMA_addExist_ptr(src, i, src->n); } } } free(src->values); src->values = 0; return Values; } unsigned load_DBs(char *templatefilename, char *outputfilename, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths, HashMapKMA *finalDB) { int file_len, out_len, DB_size, kmerindex; FILE *infile; file_len = strlen(templatefilename); out_len = strlen(outputfilename); /* load hash */ strcat(templatefilename, ".comp.b"); infile = sfopen(templatefilename, "rb"); if(hashMapKMAload(finalDB, infile)) { fprintf(stderr, "Wrong format of DB\n"); exit(1); } else { finalDB->size--; } templatefilename[file_len] = 0; fclose(infile); /* load lengths */ strcat(templatefilename, ".length.b"); infile = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; sfread(&DB_size, sizeof(unsigned), 1, infile); if(finalDB->prefix) { *template_lengths = smalloc((DB_size << 1) * sizeof(unsigned)); *template_slengths = smalloc((DB_size << 1) * sizeof(unsigned)); *template_ulengths = smalloc((DB_size << 1) * sizeof(unsigned)); sfread(*template_lengths, sizeof(unsigned), DB_size, infile); sfread(*template_slengths, sizeof(unsigned), DB_size, infile); sfread(*template_ulengths, sizeof(unsigned), DB_size, infile); kmerindex = **template_slengths; **template_ulengths = DB_size << 1; **template_slengths = DB_size << 1; } else { *template_lengths = smalloc((DB_size << 1) * sizeof(unsigned)); *template_slengths = 0; *template_ulengths = 0; sfread(*template_lengths, sizeof(unsigned), DB_size, infile); kmerindex = **template_lengths; **template_lengths = DB_size << 1; } fclose(infile); /* cp name, seq and index */ strcat(templatefilename, ".name"); strcat(outputfilename, ".name"); CP(templatefilename, outputfilename); templatefilename[file_len] = 0; outputfilename[out_len] = 0; strcat(templatefilename, ".seq.b"); strcat(outputfilename, ".seq.b"); CP(templatefilename, outputfilename); templatefilename[file_len] = 0; outputfilename[out_len] = 0; return kmerindex; } genomicepidemiology-kma-091b8ffe66ac/seq2fasta.c0000644000175000017500000001447314157033525021157 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "penalties.h" #include "pherror.h" #include "qseqs.h" #include "runkma.h" #include "seq2fasta.h" #include "stdnuc.h" int * getLengths(char *filename) { int file_len, DB_size, *template_lengths; FILE *infile; file_len = strlen(filename); strcat(filename, ".length.b"); infile = sfopen(filename, "rb"); filename[file_len] = 0; sfread(&DB_size, sizeof(int), 1, infile); template_lengths = calloc(DB_size, sizeof(int)); if(!template_lengths) { ERROR(); } sfread(template_lengths, sizeof(int), DB_size, infile); *template_lengths = DB_size; fclose(infile); return template_lengths; } void printFastas(char *filename, int *template_lengths) { const char bases[6] = "ACGTN-"; int i, j, max, DB_size, file_len; long unsigned *compseq; char *seq; FILE *seqfile, *namefile; Qseqs *template_name; template_name = setQseqs(256); DB_size = *template_lengths; max = template_lengths[1]; for(i = 2; i < DB_size; i++) { if(max < template_lengths[i]) { max = template_lengths[i]; } } file_len = strlen(filename); strcat(filename, ".seq.b"); seqfile = sfopen(filename, "rb"); filename[file_len] = 0; strcat(filename, ".name"); namefile = sfopen(filename, "rb"); filename[file_len] = 0; /* Allocate stuff */ seq = malloc(max+2); compseq = calloc((max >> 5) + 1, sizeof(long unsigned)); if(!seq || !compseq) { ERROR(); } for(i = 1; i < DB_size; ++i) { sfread(compseq, sizeof(long unsigned), (template_lengths[i] >> 5) + 1, seqfile); j = template_lengths[i]; *(seq += j) = '\n'; while(j--) { *--seq = bases[getNuc(compseq, j)]; } fprintf(stdout, ">%s\n", nameLoad(template_name, namefile)); cfwrite(seq, 1, template_lengths[i] + 1, stdout); } } int intCmpAscend(const void * a, const void * b) { return *((int*) a) - *((int*) b); } void printFastaList(char *filename, int *template_lengths, int *seqlist) { const char bases[6] = "ACGTN-"; int i, j, n, max, DB_size, file_len; long unsigned skip, *compseq; char *seq; FILE *seqfile, *namefile; Qseqs *template_name; /* sort sequence list */ qsort(seqlist + 1, (n = *seqlist), sizeof(int), intCmpAscend); /* skip invalid templates */ while(n && *++seqlist <= 0) { --n; } /* open index */ template_name = setQseqs(256); DB_size = *template_lengths; max = template_lengths[1]; for(i = 2; i < DB_size; i++) { if(max < template_lengths[i]) { max = template_lengths[i]; } } file_len = strlen(filename); strcat(filename, ".seq.b"); seqfile = sfopen(filename, "rb"); filename[file_len] = 0; strcat(filename, ".name"); namefile = sfopen(filename, "rb"); filename[file_len] = 0; /* Allocate stuff */ seq = malloc(max+2); compseq = calloc((max >> 5) + 1, sizeof(long unsigned)); if(!seq || !compseq) { ERROR(); } skip = 0; for(i = 1; n && i < DB_size; ++i) { if(i == *seqlist) { /* get seq */ fseek(seqfile, skip, SEEK_CUR); sfread(compseq, sizeof(long unsigned), (template_lengths[i] >> 5) + 1, seqfile); j = template_lengths[i]; *(seq += j) = '\n'; while(j--) { *--seq = bases[getNuc(compseq, j)]; } /* print seq */ fprintf(stdout, ">%s\n", nameLoad(template_name, namefile)); fwrite(seq, 1, template_lengths[i] + 1, stdout); /* get next target */ while(--n && i == *++seqlist); skip = 0; } else { nameSkip(namefile, max); skip += (((template_lengths[i] >> 5) + 1) * sizeof(long unsigned)); } } } int * intSplit(char sep, const char *src) { int n, *seqlist; char *stringPtr, *intStr, *errStr; /* get number of elements */ n = 2; stringPtr = (char *) src; while(*stringPtr) { if(*stringPtr++ == sep) { ++n; } } seqlist = smalloc(n * sizeof(int)); /* get elements */ n = 0; stringPtr = (char *) src; intStr = stringPtr; while(*stringPtr) { if(*++stringPtr == sep) { *stringPtr = 0; ++n; seqlist[n] = strtol(intStr, &errStr, 10); if(*errStr != 0 || *(intStr = ++stringPtr) == 0) { fprintf(stderr, "Invalid list parsed.\n"); exit(1); } } else if(*stringPtr == 0) { ++n; seqlist[n] = strtol(intStr, &errStr, 10); if(*errStr != 0) { fprintf(stderr, "Invalid list parsed.\n"); exit(1); } } } *seqlist = n; return seqlist; } static void helpMessage(int status) { FILE *out; if(status) { out = stderr; } else { out = stdout; } fprintf(out, "kma seq2fasta prints the fasta sequence of a given kma index to stdout.\n"); fprintf(out, "# Options are:\tDesc:\t\t\t\t\tDefault:\tRequirements:\n"); fprintf(out, "#\t-t_db\tTemplate DB\t\t\t\tNone\t\tREQUIRED\n"); fprintf(out, "#\t-seqs\tComma separated list of templates\tPrint entire index.\n"); fprintf(out, "#\t-h\tShows this help message\n"); exit(status); } int seq2fasta_main(int argc, char *argv[]) { int args, file_len, *template_lengths, *seqlist; char *filename; seqlist = 0; file_len = 0; filename = 0; args = 0; while(++args < argc) { if(strcmp(argv[args], "-t_db") == 0) { if(++args < argc) { file_len = strlen(argv[args]); filename = smalloc(file_len + 64); strcpy(filename, argv[args]); } } else if(strcmp(argv[args], "-seqs") == 0) { if(++args < argc) { seqlist = intSplit(',', argv[args]); } } else if(strcmp(argv[args], "-h") == 0) { helpMessage(0); } else { helpMessage(1); } } if(!filename) { fprintf(stderr, "Need a db\n"); helpMessage(1); } /* get lengths */ template_lengths = getLengths(filename); if(seqlist) { /* get sequences from list */ printFastaList(filename, template_lengths, seqlist); } else { /* get all sequences */ printFastas(filename, template_lengths); } return 0; } genomicepidemiology-kma-091b8ffe66ac/main.h0000644000175000017500000000135014157033525020205 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ int main(int argc, char *argv[]); genomicepidemiology-kma-091b8ffe66ac/align.h0000644000175000017500000000517014157033525020357 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "chain.h" #include "compdna.h" #include "hashmapcci.h" #include "nw.h" extern AlnScore (*leadTailAlnPtr)(Aln *, Aln *, const long unsigned*, const unsigned char*, int, int, int, const int, NWmat *); extern void (*trailTailAlnPtr)(Aln *, Aln *, AlnScore *, const long unsigned *, const unsigned char *, int, int, int, int, const int, NWmat *); AlnScore skipLeadAln(Aln *aligned, Aln *Frag_align, const long unsigned *tseq, const unsigned char *qseq, int t_e, int t_len, int q_e, const int bandwidth, NWmat *matrices); AlnScore leadTailAln(Aln *aligned, Aln *Frag_align, const long unsigned *tseq, const unsigned char *qseq, int t_e, int t_len, int q_e, const int bandwidth, NWmat *matrices); void skipTrailAln(Aln *aligned, Aln *Frag_align, AlnScore *Stat, const long unsigned *tseq, const unsigned char *qseq, int t_s, int t_len, int q_s, int q_len, const int bandwidth, NWmat *matrices); void trailTailAln(Aln *aligned, Aln *Frag_align, AlnScore *Stat, const long unsigned *tseq, const unsigned char *qseq, int t_s, int t_len, int q_s, int q_len, const int bandwidth, NWmat *matrices); AlnScore KMA(const HashMapCCI *template_index, const unsigned char *qseq, int q_len, int q_start, int q_end, Aln *aligned, Aln *Frag_align, int min, int max, int mq, double scoreT, AlnPoints *points, NWmat *matrices); AlnScore KMA_score(const HashMapCCI *template_index, const unsigned char *qseq, int q_len, int q_start, int q_end, const CompDNA *qseq_comp, int mq, double scoreT, AlnPoints *points, NWmat *matrices); int preseed(const HashMapCCI *template_index, unsigned char *qseq, int q_len); void intcpy(int *dest, int *src, int size); int anker_rc(const HashMapCCI *template_index, unsigned char *qseq, int q_len, int q_start, int q_end, AlnPoints *points); int anker_rc_comp(const HashMapCCI *template_index, unsigned char *qseq, unsigned char *qseq_r, CompDNA *qseq_comp, CompDNA *qseq_r_comp, int q_start, int q_end, AlnPoints *points); genomicepidemiology-kma-091b8ffe66ac/chain.c0000644000175000017500000003247114157033525020346 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "chain.h" #include "penalties.h" #include "pherror.h" #include "stdstat.h" int (*chainSeedsPtr)(AlnPoints *, int, int, int, unsigned *) = &chainSeeds; void (*trimSeedsPtr)(AlnPoints *points, int start) = &trimSeeds; AlnPoints * seedPoint_init(int size, Penalties *rewards) { AlnPoints *dest; dest = smalloc(sizeof(AlnPoints)); dest->len = 0; dest->size = size; size *= sizeof(int); dest->tStart = smalloc(size); dest->tEnd = smalloc(size); dest->qStart = smalloc(size); dest->qEnd = smalloc(size); dest->weight = smalloc(size); dest->score = smalloc(size); dest->next = smalloc(size); dest->rewards = rewards; return dest; } void seedPoint_realloc(AlnPoints *dest, int size) { dest->size = size; size *= sizeof(int); dest->tStart = realloc(dest->tStart, size); dest->tEnd = realloc(dest->tEnd, size); dest->qStart = realloc(dest->qStart, size); dest->qEnd = realloc(dest->qEnd, size); dest->weight = realloc(dest->weight, size); dest->score = realloc(dest->score, size); dest->next = realloc(dest->next, size); if(!dest->tStart || !dest->tEnd || !dest->qStart || !dest->qEnd || !dest->weight || !dest->score || !dest->next) { ERROR(); } } void seedPoint_free(AlnPoints *src) { free(src->tStart); free(src->tEnd); free(src->qStart); free(src->qEnd); free(src->weight); free(src->score); free(src->next); src->rewards = 0; free(src); } int chainSeeds(AlnPoints *points, int q_len, int t_len, int kmersize, unsigned *mapQ) { int i, j, nMems, weight, gap, score, bestScore, secondScore, bestPos; int tStart, tEnd, qStart, qEnd, tGap, qGap, nMin, W1, U, M, MM, Ms, MMs; Penalties *rewards; rewards = points->rewards; W1 = rewards->W1; U = rewards->U; M = rewards->M; MM = rewards->MM; nMems = points->len; i = nMems; bestPos = i - 1; bestScore = 0; secondScore = 0; points->score[i] = 0; points->next[i] = 0; while(i--) { weight = points->weight[i] * M; points->next[i] = 0; tEnd = points->tEnd[i]; qEnd = points->qEnd[i]; /* get stop score */ gap = MIN(t_len - tEnd, q_len - qEnd); Ms = gap; /* gap */ if(--gap) { gap *= U; gap += W1; } else if(gap == 0) { gap = W1; } else { gap = 0; } /* match */ if(Ms == 2) { MMs = 2; Ms = 0; } else { MMs = Ms / kmersize + (Ms % kmersize ? 1 : 0); MMs = MAX(2, MMs); Ms = MIN(Ms - MMs, kmersize); Ms = MIN(Ms, MMs); } Ms = Ms * M + MMs * MM; score = weight + (Ms < gap ? gap : Ms); /* 128 is the bandwidth */ nMin = MIN(nMems, i + 128); /* find best link */ for(j = i + 1; j < nMin; ++j) { /* check compability */ if(qEnd < points->qStart[j]) { if(tEnd < points->tStart[j]) { /* full compatability */ tGap = points->tStart[j] - tEnd; qGap = points->qStart[j] - qEnd; /* calculate score for this chaining */ if((gap = abs(tGap - qGap))) { --gap; gap *= U; gap += W1; } //gap += ((MIN(tGap, qGap)) * pM + weight + points->score[j]); Ms = MIN(tGap, qGap); if(Ms == 2) { MMs = 2; Ms = 0; } else { MMs = Ms / kmersize + (Ms % kmersize ? 1 : 0); MMs = MAX(2, MMs); Ms = MIN(Ms - MMs, kmersize); Ms = MIN(Ms, MMs); } gap += weight + points->score[j] + Ms * M + MMs * MM; /* check if score is max */ if(score <= gap) { score = gap; points->next[i] = j; } } else if(kmersize <= points->tEnd[j] - tEnd) { /* semi compatability */ /* calculate score for this chaining */ if((gap = (points->qStart[j] - qEnd))) { --gap; gap *= U; gap += W1; } /* cut mem score */ gap += (weight + points->score[j] - (points->tStart[j] - tEnd) * M); /* check if score is max */ if(score < gap) { score = gap; points->next[i] = j; } } } else if(kmersize <= points->qEnd[j] - qEnd) { /* cut in query is reflected in template */ tStart = points->tStart[j] + qEnd - points->qStart[j]; if(tEnd < tStart) { /* full compatability */ tGap = tStart - tEnd; /* calculate score for this chaining */ if((gap = tGap)) { --gap; gap *= U; gap += W1; } /* cut mem score */ gap += (weight + points->score[j] - (tStart - tEnd) * M); /* check if score is max */ if(score < gap) { score = gap; points->next[i] = j; } } /* if the modified tStart was invalid, then the entire mem is lost. */ } } /* update seed */ if(points->next[i]) { points->weight[i] += (points->weight[points->next[i]] - kmersize + 1); } else { points->weight[i] -= (kmersize - 1); } points->score[i] = score; /* penalize start */ tStart = points->tStart[i]; qStart = points->qStart[i]; gap = MIN(tStart, qStart); Ms = gap; /* gap */ if(0 < --gap) { gap *= U; gap += W1; } else if(gap == 0) { gap = W1; } else { gap = 0; } /* match */ if(Ms == 2) { MMs = 2; Ms = 0; } else { MMs = Ms / kmersize + (Ms % kmersize ? 1 : 0); MMs = MAX(2, MMs); Ms = MIN(Ms - MMs, kmersize); Ms = MIN(Ms, MMs); } Ms = Ms * M + MMs * MM; score += Ms < gap ? gap : Ms; /* update bestScore */ if(bestScore <= score) { if(points->next[i] != bestPos) { secondScore = bestScore; } bestScore = score; bestPos = i; } else if(secondScore <= score && points->next[i] != bestPos) { secondScore = bestScore; } } /* calculate mapping quality */ *mapQ = 0 < bestScore ? (ceil(40 * (1 - 1.0 * secondScore / bestScore) * MIN(1, points->weight[bestPos] / 10.0) * log(bestScore))) : 0; points->score[bestPos] = bestScore; return bestPos; } int chainSeeds_circular(AlnPoints *points, int q_len, int t_len, int kmersize, unsigned *mapQ) { int i, j, nMems, weight, gap, score, bestScore, secondScore, bestPos; int tStart, tEnd, qStart, qEnd, tGap, qGap, nMin, W1, U, M, MM, Ms, MMs; Penalties *rewards; rewards = points->rewards; W1 = rewards->W1; U = rewards->U; M = rewards->M; MM = rewards->MM; nMems = points->len; i = nMems; bestPos = i - 1; bestScore = 0; secondScore = 0; points->score[i] = 0; points->next[i] = 0; while(i--) { weight = points->weight[i] * M; points->next[i] = 0; tEnd = points->tEnd[i]; qEnd = points->qEnd[i]; /* get stop score */ gap = MIN(t_len - tEnd, q_len - qEnd); Ms = gap; /* gap */ if(--gap) { gap *= U; gap += W1; } else if(gap == 0) { gap = W1; } else { gap = 0; } /* match */ if(Ms == 2) { MMs = 2; Ms = 0; } else { MMs = Ms / kmersize + (Ms % kmersize ? 1 : 0); MMs = MAX(2, MMs); Ms = MIN(Ms - MMs, kmersize); Ms = MIN(Ms, MMs); } Ms = Ms * M + MMs * MM; score = weight + (Ms < gap ? gap : Ms); /* 128 is the bandwidth */ nMin = MIN(nMems, i + 128); /* find best link */ for(j = i + 1; j < nMin; ++j) { /* check compability */ if(qEnd < points->qStart[j]) { tStart = points->tStart[j]; if(tEnd < tStart) { /* full compatability */ tGap = tStart - tEnd; qGap = points->qStart[j] - qEnd; /* calculate score for this chaining */ if((gap = abs(tGap - qGap))) { --gap; gap *= U; gap += W1; } //gap += ((MIN(tGap, qGap)) * pM + weight + points->score[j]); Ms = MIN(tGap, qGap); if(Ms == 2) { MMs = 2; Ms = 0; } else { MMs = Ms / kmersize + (Ms % kmersize ? 1 : 0); MMs = MAX(2, MMs); Ms = MIN(Ms - MMs, kmersize); Ms = MIN(Ms, MMs); } gap += weight + points->score[j] + Ms * M + MMs * MM; /* check if score is max */ if(score <= gap) { score = gap; points->next[i] = j; } } else if(kmersize <= points->tEnd[j] - tEnd) { /* semi compatability */ /* calculate score for this chaining */ if((gap = (points->qStart[j] - qEnd))) { --gap; gap *= U; gap += W1; } /* cut mem score*/ gap += (weight + points->score[j] - (tStart - tEnd) * M); /* check if score is max */ if(score < gap) { score = gap; points->next[i] = j; } } else if(points->tEnd[j] < points->tStart[i]) { /* circular joinning, full compability */ tGap = t_len - tEnd + tStart; qGap = points->qStart[j] - qEnd; /* calculate score for this chaining */ if((gap = abs(tGap - qGap))) { --gap; gap *= U; gap += W1; } //gap += ((MIN(tGap, qGap)) * pM + weight + points->score[j]); Ms = MIN(tGap, qGap); if(Ms == 2) { MMs = 2; Ms = 0; } else { MMs = Ms / kmersize + (Ms % kmersize ? 1 : 0); MMs = MAX(2, MMs); Ms = MIN(Ms - MMs, kmersize); Ms = MIN(Ms, MMs); } gap += weight + points->score[j] + Ms * M + MMs * MM; /* check if score is max */ if(score < gap) { score = gap; points->next[i] = j; } } } else if(kmersize <= points->qEnd[j] - qEnd) { /* cut in query is reflected in template */ tStart = points->tStart[j] + qEnd - points->qStart[j]; if(tEnd < tStart) { /* full compatability */ tGap = tStart - tEnd; /* calculate score for this chaining */ if((gap = tGap)) { --gap; gap *= U; gap += W1; } /* cut mem score */ gap += (weight + points->score[j] - (tStart - tEnd) * M); /* check if score is max */ if(score <= gap) { score = gap; points->next[i] = j; } } else { if(t_len < tStart) { tStart -= t_len; } if(tStart != tEnd && points->tEnd[j] < tStart) { tGap = t_len - tEnd + tStart; /* calculate score for this chaining */ if((gap = tGap)) { --gap; gap *= U; gap += W1; } gap += (weight + points->score[j] - (tEnd - tStart) * M); /* check if score is max */ if(score < gap) { score = gap; points->next[i] = j; } } }/* if the modified tStart was invalid, then the entire mem is lost. */ } } /* update seed */ if(points->next[i]) { points->weight[i] += (points->weight[points->next[i]] - kmersize + 1); } else { points->weight[i] -= (kmersize - 1); } points->score[i] = score; /* penalize start */ tStart = points->tStart[i]; qStart = points->qStart[i]; gap = MIN(tStart, qStart); Ms = gap; /* gap */ if(0 < --gap) { gap *= U; gap += W1; } else if(gap == 0) { gap = W1; } else { gap = 0; } /* match */ if(Ms == 2) { MMs = 2; Ms = 0; } else { MMs = Ms / kmersize + (Ms % kmersize ? 1 : 0); MMs = MAX(2, MMs); Ms = MIN(Ms - MMs, kmersize); Ms = MIN(Ms, MMs); } Ms = Ms * M + MMs * MM; score += Ms < gap ? gap : Ms; /* update bestScore */ if(bestScore <= score) { if(points->next[i] != bestPos) { secondScore = bestScore; } bestScore = score; bestPos = i; } else if(secondScore <= score && points->next[i] != bestPos) { secondScore = bestScore; } } /* calculate mapping quality */ *mapQ = 0 < bestScore ? ceil(40 * (1 - 1.0 * secondScore / bestScore) * MIN(1, points->weight[bestPos] / 10.0) * log(bestScore)) : 0; points->score[bestPos] = bestScore; return bestPos; } void trimSeeds(AlnPoints *points, int start) { /* trim the start of each seed */ static int ts = 0; int len; if(!points) { ts = start; return; } else if(!ts) { return; } if(points->qStart[start]) { /* iterate seeds on best chain */ do { /* trim seed */ len = points->qEnd[start] - points->qStart[start]; if(len < ts) { /* ensure at least one nucleotide remains in seed */ points->tStart[start] += --len; points->qStart[start] += len; } else { points->tStart[start] += ts; points->qStart[start] += ts; } } while((start = points->next[start])); } else { /* iterate seeds on best chain */ while((start = points->next[start])) { /* trim seed */ len = points->qEnd[start] - points->qStart[start]; if(len < ts) { /* ensure at least one nucleotide remains in seed */ points->tStart[start] += --len; points->qStart[start] += len; } else { points->tStart[start] += ts; points->qStart[start] += ts; } } } } void trimSeedsNoLead(AlnPoints *points, int start) { /* trim the start of each seed */ static int ts = 0; int len; if(!points) { ts = start; return; } else if(!ts) { return; } /* iterate seeds on best chain */ while((start = points->next[start])) { /* trim seed */ len = points->qEnd[start] - points->qStart[start]; if(len < ts) { /* ensure at least one nucleotide remains in seed */ points->tStart[start] += --len; points->qStart[start] += len; } else { points->tStart[start] += ts; points->qStart[start] += ts; } } } genomicepidemiology-kma-091b8ffe66ac/hashmapkmers.c0000644000175000017500000000560114157033525021742 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "hashmapkmers.h" #include "pherror.h" void hashMap_kmers_initialize(HashMap_kmers *dest, unsigned newSize) { /* set hashMap */ dest->size = newSize; dest->n = 0; /* set hashTable */ dest->table = calloc(newSize, sizeof(HashTable_kmers*)); if(!dest->table) { ERROR(); } } void reallocHashMap_kmers(HashMap_kmers *dest) { long unsigned index; HashTable_kmers *table, *node, *node_next; /* save buckets */ table = 0; index = dest->size; while(index--) { for(node = dest->table[index]; node; node = node_next) { node_next = node->next; node->next = table; table = node; } } /* reallocate table */ free(dest->table); dest->table = calloc(dest->size <<= 1, sizeof(HashTable_kmers *)); if(!dest->table) { ERROR(); } /* refill table */ for(node = table; node; node = node_next) { node_next = node->next; index = node->key % dest->size; node->next = dest->table[index]; dest->table[index] = node; } } void hashMap_kmers_CountIndex(HashMap_kmers *dest, long unsigned key) { unsigned index; HashTable_kmers *node; /* get index */ index = key % dest->size; for(node = dest->table[index]; node != 0; node = node->next) { if(key == node->key) { // Keys match change value ++node->value; return; } } if(dest->n == dest->size) { reallocHashMap_kmers(dest); } ++dest->n; node = smalloc(sizeof(HashTable_kmers)); node->value = 1; node->key = key; node->next = dest->table[index]; dest->table[index] = node; } int hashMap_CountKmer(HashMap_kmers *dest, long unsigned key) { long unsigned index; HashTable_kmers *node; index = key % dest->size; for(node = dest->table[index]; node != 0; node = node->next) { if(node->key == key) { return 0; } } if(dest->n == dest->size) { reallocHashMap_kmers(dest); } ++dest->n; node = smalloc(sizeof(HashTable_kmers)); node->key = key; node->next = dest->table[index]; dest->table[index] = node; return 1; } void emptyHash(HashMap_kmers *dest) { unsigned i; HashTable_kmers *node, *next; for(i = 0; i < dest->size; ++i) { for(node = dest->table[i]; node != 0; node = next) { next = node->next; free(node); } dest->table[i] = 0; } dest->n = 0; } genomicepidemiology-kma-091b8ffe66ac/kma.h0000644000175000017500000000142514157033525020034 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ char * strjoin(char **strings, int len); int kma_main(int argc, char *argv[]); genomicepidemiology-kma-091b8ffe66ac/seq2fasta.h0000644000175000017500000000176514157033525021164 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ int * getLengths(char *filename); void printFastas(char *filename, int *template_lengths); int intCmpAscend(const void * a, const void * b); void printFastaList(char *filename, int *template_lengths, int *seqlist); int * intSplit(char sep, const char *src); int seq2fasta_main(int argc, char *argv[]) ; genomicepidemiology-kma-091b8ffe66ac/hashmapkma.c0000644000175000017500000004666014157033525021403 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "hashmapkma.h" #include "pherror.h" #ifdef _WIN32 typedef int key_t; #define ftok(charPtr, integer) (0) #define shmget(key, size, permission) ((size != 0) ? (-1) : (-key)) #define shmat(shmid, NULL_Ptr, integer) (NULL) #else #include #include #include #endif void (*hashMapKMA_destroy)(HashMapKMA *) = &hashMapKMA_free; long unsigned (*getExistPtr)(const unsigned *, const long unsigned); long unsigned (*getKeyPtr)(const unsigned *, const long unsigned); long unsigned (*getValueIndexPtr)(const unsigned *, const long unsigned); unsigned * (*getValuePtr)(const HashMapKMA *, const long unsigned); unsigned * (*hashMap_get)(const HashMapKMA *, const long unsigned); int (*intpos_bin_contaminationPtr)(const unsigned *, const int); int (*getSizePtr)(const unsigned *); void (*hashMapKMA_addKey_ptr)(HashMapKMA *, long unsigned, long unsigned); void (*hashMapKMA_addValue_ptr)(HashMapKMA *, long unsigned, long unsigned); void (*hashMapKMA_addExist_ptr)(HashMapKMA *, long unsigned, long unsigned); long unsigned getExist(const unsigned *exist, const long unsigned pos) { return exist[pos]; } long unsigned getExistL(const unsigned *exist, const long unsigned pos) { return ((long unsigned *) exist)[pos]; } long unsigned getKey(const unsigned *key_index, const long unsigned pos) { return key_index[pos]; } long unsigned getKeyL(const unsigned *key_index, const long unsigned pos) { return ((long unsigned *) key_index)[pos]; } long unsigned getValueIndex(const unsigned *value_index, const long unsigned pos) { return value_index[pos]; } long unsigned getValueIndexL(const unsigned *value_index, const long unsigned pos) { return ((long unsigned *) value_index)[pos]; } unsigned * getValue(const HashMapKMA *dest, const long unsigned pos) { return (dest->values + pos); } unsigned * getValueS(const HashMapKMA *dest, const long unsigned pos) { return (unsigned *)(dest->values_s + pos); } int getSize(const unsigned *values) { return *values * sizeof(unsigned) + sizeof(unsigned); } int getSizeS(const unsigned *values) { return *((short unsigned *)(values)) * sizeof(short unsigned) + sizeof(short unsigned); } int intpos_bin_contamination(const unsigned *str1, const int str2) { int pos, upLim, downLim, template; upLim = *str1; if(upLim == 0) { return -1; } downLim = 1; pos = (upLim + downLim) >> 1; while(0 < (upLim - downLim)) { template = str1[pos]; if(template == str2) { return pos; } else if(template < str2) { downLim = pos + 1; } else { upLim = pos - 1; } pos = (upLim + downLim) >> 1; } if(str1[pos] == str2) { return pos; } return -1; } int intpos_bin_contamination_s(const unsigned *Str1, const int str2) { int pos, upLim, downLim, template; short unsigned *str1 = (short unsigned *) Str1; upLim = *str1; if(upLim == 0) { return -1; } downLim = 1; pos = (upLim + downLim) >> 1; while(0 < (upLim - downLim)) { template = str1[pos]; if(template == str2) { return pos; } else if(template < str2) { downLim = pos + 1; } else { upLim = pos - 1; } pos = (upLim + downLim) >> 1; } if(str1[pos] == str2) { return pos; } return -1; } unsigned * hashMap_getGlobal(const HashMapKMA *templates, const long unsigned key) { long unsigned pos, kpos, kmer; kpos = key & templates->size; pos = getExistPtr(templates->exist, kpos); if(pos != templates->null_index) { kmer = getKeyPtr(templates->key_index, pos); while(key != kmer) { if(kpos != (kmer & templates->size)) { return 0; } kmer = getKeyPtr(templates->key_index, ++pos); } return getValuePtr(templates, getValueIndexPtr(templates->value_index, pos)); } return 0; } void loadPrefix(HashMapKMA *dest, FILE *file) { /* load sizes */ sfread(&dest->DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); sfread(&dest->n, sizeof(long unsigned), 1, file); sfread(&dest->v_index, sizeof(long unsigned), 1, file); sfread(&dest->null_index, sizeof(long unsigned), 1, file); dest->mask = 0; dest->mask = (~dest->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (dest->kmersize << 1)); dest->shmFlag = 0; dest->exist = 0; dest->exist_l = 0; dest->values = 0; dest->values_s = 0; dest->key_index = 0; dest->key_index_l = 0; dest->value_index = 0; dest->value_index_l = 0; } unsigned * megaMap_getGlobal(const HashMapKMA *templates, const long unsigned key) { long unsigned pos; if((pos = getExistPtr(templates->exist, key)) != 1) { return getValuePtr(templates, pos); } return 0; } int hashMapKMA_load(HashMapKMA *dest, FILE *file, const char *filename) { key_t key; int shmid; long unsigned check, size, seekSize; /* load sizes */ sfread(&dest->DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); sfread(&dest->n, sizeof(long unsigned), 1, file); sfread(&dest->v_index, sizeof(long unsigned), 1, file); sfread(&dest->null_index, sizeof(long unsigned), 1, file); dest->mask = 0; dest->mask = (~dest->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (dest->kmersize << 1)); dest->shmFlag = 0; /* simple check for old indexing */ if(dest->size < dest->n) { return 1; } /* check shared memory, else load */ size = dest->size; if((dest->size - 1) == dest->mask) { if(dest->v_index <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; } } else { if(dest->n <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; } } key = ftok(filename, 'e'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared, load */ errno = 0; dest->exist = smalloc(size); check = fread(dest->exist, 1, size, file); if(check != size) { return 1; } seekSize = 0; dest->shmFlag |= 1; } else { /* found */ dest->exist = shmat(shmid, NULL, 0); seekSize = size; } dest->exist_l = (long unsigned *)(dest->exist); /* values */ size = dest->v_index; if(dest->DB_size < USHRT_MAX) { size *= sizeof(short unsigned); getValuePtr =&getValueS; intpos_bin_contaminationPtr = &intpos_bin_contamination_s; } else { size *= sizeof(unsigned); getValuePtr =&getValue; intpos_bin_contaminationPtr = &intpos_bin_contamination; } key = ftok(filename, 'v'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared, load */ errno = 0; dest->values = smalloc(size); if(seekSize) { fseek(file, seekSize, SEEK_CUR); } seekSize = 0; check = fread(dest->values, 1, size, file); if(check != size) { return 1; } dest->shmFlag |= 2; } else { /* found */ dest->values = shmat(shmid, NULL, 0); seekSize += size; } dest->values_s = (short unsigned *)(dest->values); /* check for megaMap */ if((dest->size - 1) == dest->mask) { hashMap_get = &megaMap_getGlobal; return 0; } else { hashMap_get = &hashMap_getGlobal; } /* kmers */ size = dest->n + 1; if(dest->kmersize <= 16) { size *= sizeof(unsigned); getKeyPtr = &getKey; } else { size *= sizeof(long unsigned); getKeyPtr = &getKeyL; } key = ftok(filename, 'k'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared, load */ errno = 0; dest->key_index = smalloc(size); if(seekSize) { fseek(file, seekSize, SEEK_CUR); } seekSize = 0; check = fread(dest->key_index, 1, size, file); if(check != size) { return 1; } dest->shmFlag |= 4; } else { /* found */ dest->key_index = shmat(shmid, NULL, 0); seekSize += size; } dest->key_index_l = (long unsigned *)(dest->key_index); /* value indexes */ size = dest->n; if(dest->v_index < UINT_MAX) { size *= sizeof(unsigned); getValueIndexPtr = &getValueIndex; } else { size *= sizeof(long unsigned); getValueIndexPtr = &getValueIndexL; } key = ftok(filename, 'i'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared, load */ errno = 0; dest->value_index = smalloc(size); if(seekSize) { fseek(file, seekSize, SEEK_CUR); } seekSize = 0; check = fread(dest->value_index, 1, size, file); if(check != size) { return 1; } dest->shmFlag |= 8; } else { /* found */ dest->value_index = shmat(shmid, NULL, 0); seekSize += size; } dest->value_index_l = (long unsigned *)(dest->value_index); /* make indexing a masking problem */ --dest->size; return 0; } void hashMapKMA_load_shm(HashMapKMA *dest, FILE *file, const char *filename) { key_t key; int shmid; long unsigned size; /* load sizes */ sfread(&dest->DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); sfread(&dest->n, sizeof(long unsigned), 1, file); sfread(&dest->v_index, sizeof(long unsigned), 1, file); sfread(&dest->null_index, sizeof(long unsigned), 1, file); dest->mask = 0; dest->mask = (~dest->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (dest->kmersize << 1)); dest->shmFlag = 0; /* check shared memory */ size = dest->size; if((dest->size - 1) == dest->mask) { if(dest->v_index <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; } } else { if(dest->n <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; } } key = ftok(filename, 'e'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared */ fprintf(stderr, "DB e not shared, see kma_shm\n"); exit(1); } else { /* found */ dest->exist = shmat(shmid, NULL, 0); } dest->exist_l = (long unsigned *)(dest->exist); /* values */ size = dest->v_index; if(dest->DB_size < USHRT_MAX) { size *= sizeof(short unsigned); getValuePtr =&getValueS; intpos_bin_contaminationPtr = &intpos_bin_contamination_s; } else { size *= sizeof(unsigned); getValuePtr =&getValue; intpos_bin_contaminationPtr = &intpos_bin_contamination; } key = ftok(filename, 'v'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared */ fprintf(stderr, "DB v not shared, see kma_shm\n"); exit(1); } else { /* found */ dest->values = shmat(shmid, NULL, 0); } dest->values_s = (short unsigned *)(dest->values); /* check for megaMap */ if((dest->size - 1) == dest->mask) { hashMap_get = &megaMap_getGlobal; return; } else { hashMap_get = &hashMap_getGlobal; } /* kmers */ size = dest->n + 1; if(dest->kmersize <= 16) { size *= sizeof(unsigned); getKeyPtr = &getKey; } else { size *= sizeof(long unsigned); getKeyPtr = &getKeyL; } key = ftok(filename, 'k'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared */ fprintf(stderr, "DB k not shared, see kma_shm\n"); exit(1); } else { /* found */ dest->key_index = shmat(shmid, NULL, 0); } dest->key_index_l = (long unsigned *)(dest->key_index); /* value indexes */ size = dest->n; if(dest->v_index < UINT_MAX) { size *= sizeof(unsigned); getValueIndexPtr = &getValueIndex; } else { size *= sizeof(long unsigned); getValueIndexPtr = &getValueIndexL; } key = ftok(filename, 'i'); shmid = shmget(key, size, 0666); if(shmid < 0) { /* not shared */ fprintf(stderr, "DB i not shared, see kma_shm\n"); exit(1); } else { /* found */ dest->value_index = shmat(shmid, NULL, 0); } dest->value_index_l = (long unsigned *)(dest->value_index); /* make indexing a masking problem */ --dest->size; } int hashMapKMAload(HashMapKMA *dest, FILE *file) { long unsigned check, size; /* load sizes */ sfread(&dest->DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); sfread(&dest->n, sizeof(long unsigned), 1, file); sfread(&dest->v_index, sizeof(long unsigned), 1, file); sfread(&dest->null_index, sizeof(long unsigned), 1, file); dest->mask = 0; dest->mask = (~dest->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (dest->kmersize << 1)); dest->shmFlag = 0; /* exist */ size = dest->size; if((dest->size - 1) == dest->mask) { if(dest->v_index <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; hashMapKMA_addExist_ptr = &hashMapKMA_addExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; } } else { if(dest->n <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; hashMapKMA_addExist_ptr = &hashMapKMA_addExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; } } dest->exist = smalloc(size); check = fread(dest->exist, 1, size, file); if(check != size) { return 1; } dest->exist_l = (long unsigned *)(dest->exist); dest->shmFlag |= 1; /* values */ size = dest->v_index; if(dest->DB_size < USHRT_MAX) { size *= sizeof(short unsigned); getValuePtr = &getValueS; getSizePtr = &getSizeS; } else { size *= sizeof(unsigned); getValuePtr = &getValue; getSizePtr = &getSize; } dest->values = smalloc(size); check = fread(dest->values, 1, size, file); if(check != size) { return 1; } dest->values_s = (short unsigned *)(dest->values); dest->shmFlag |= 2; /* check for megaMap */ if((dest->size - 1) == dest->mask) { dest->key_index = 0; dest->key_index_l = 0; dest->value_index = 0; dest->value_index_l = 0; return 0; } /* kmers */ size = dest->n + 1; if(dest->kmersize <= 16) { size *= sizeof(unsigned); getKeyPtr = &getKey; } else { size *= sizeof(long unsigned); getKeyPtr = &getKeyL; } dest->key_index = smalloc(size); check = fread(dest->key_index, 1, size, file); if(check != size) { return 1; } dest->key_index_l = (long unsigned *)(dest->key_index); dest->shmFlag |= 4; /* value indexes */ size = dest->n; if(dest->v_index < UINT_MAX) { size *= sizeof(unsigned); hashMapKMA_addValue_ptr = &hashMapKMA_addValue; getValueIndexPtr = &getValueIndex; } else { size *= sizeof(long unsigned); hashMapKMA_addValue_ptr = &hashMapKMA_addValueL; getValueIndexPtr = &getValueIndexL; } dest->value_index = smalloc(size); check = fread(dest->value_index, 1, size, file); if(check != size) { return 1; } dest->value_index_l = (long unsigned *)(dest->value_index); dest->shmFlag |= 8; return 0; } void hashMapKMA_dump(HashMapKMA *dest, FILE *out) { /* dump sizes */ cfwrite(&dest->DB_size, sizeof(unsigned), 1, out); cfwrite(&dest->kmersize, sizeof(unsigned), 1, out); cfwrite(&dest->prefix_len, sizeof(unsigned), 1, out); cfwrite(&dest->prefix, sizeof(long unsigned), 1, out); cfwrite(&dest->size, sizeof(long unsigned), 1, out); cfwrite(&dest->n, sizeof(long unsigned), 1, out); cfwrite(&dest->v_index, sizeof(long unsigned), 1, out); cfwrite(&dest->null_index, sizeof(long unsigned), 1, out); /* dump arrays */ if(dest->n <= UINT_MAX) { cfwrite(dest->exist, sizeof(unsigned), dest->size, out); getExistPtr = &getExist; hashMapKMA_addExist_ptr = &hashMapKMA_addExist; } else { cfwrite(dest->exist_l, sizeof(long unsigned), dest->size, out); getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; } if(dest->DB_size < USHRT_MAX) { cfwrite(dest->values_s, sizeof(short unsigned), dest->v_index, out); getValuePtr = &getValueS; getSizePtr = &getSizeS; } else { cfwrite(dest->values, sizeof(unsigned), dest->v_index, out); getValuePtr = &getValue; getSizePtr = &getSize; } if(dest->kmersize <= 16) { cfwrite(dest->key_index, sizeof(unsigned), dest->n + 1, out); getKeyPtr = &getKey; } else { cfwrite(dest->key_index_l, sizeof(long unsigned), dest->n + 1, out); getKeyPtr = &getKeyL; } if(dest->v_index < UINT_MAX) { cfwrite(dest->value_index, sizeof(unsigned), dest->n, out); hashMapKMA_addValue_ptr = &hashMapKMA_addValue; getValueIndexPtr = &getValueIndex; } else { cfwrite(dest->value_index_l, sizeof(long unsigned), dest->n, out); hashMapKMA_addValue_ptr = &hashMapKMA_addValueL; getValueIndexPtr = &getValueIndexL; } } void megaMapKMA_dump(HashMapKMA *dest, FILE *out) { /* dump sizes */ cfwrite(&dest->DB_size, sizeof(unsigned), 1, out); cfwrite(&dest->kmersize, sizeof(unsigned), 1, out); cfwrite(&dest->prefix_len, sizeof(unsigned), 1, out); cfwrite(&dest->prefix, sizeof(long unsigned), 1, out); cfwrite(&dest->size, sizeof(long unsigned), 1, out); cfwrite(&dest->n, sizeof(long unsigned), 1, out); cfwrite(&dest->v_index, sizeof(long unsigned), 1, out); cfwrite(&dest->null_index, sizeof(long unsigned), 1, out); /* dump arrays */ if(dest->v_index <= UINT_MAX) { cfwrite(dest->exist, sizeof(unsigned), dest->size, out); getExistPtr = &getExist; hashMapKMA_addExist_ptr = &hashMapKMA_addExist; } else { cfwrite(dest->exist_l, sizeof(long unsigned), dest->size, out); getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; } if(dest->DB_size < USHRT_MAX) { cfwrite(dest->values_s, sizeof(short unsigned), dest->v_index, out); getValuePtr = &getValueS; getSizePtr = &getSizeS; } else { cfwrite(dest->values, sizeof(unsigned), dest->v_index, out); getValuePtr = &getValue; getSizePtr = &getSize; } } void hashMapKMA_addKey(HashMapKMA *dest, long unsigned index, long unsigned key) { dest->key_index[index] = key; } void hashMapKMA_addKeyL(HashMapKMA *dest, long unsigned index, long unsigned key) { dest->key_index_l[index] = key; } void hashMapKMA_addValue(HashMapKMA *dest, long unsigned index, long unsigned v_index) { dest->value_index[index] = v_index; } void hashMapKMA_addValueL(HashMapKMA *dest, long unsigned index, long unsigned v_index) { dest->value_index_l[index] = v_index; } void hashMapKMA_addExist(HashMapKMA *dest, long unsigned index, long unsigned relative) { dest->exist[index] = relative; } void hashMapKMA_addExistL(HashMapKMA *dest, long unsigned index, long unsigned relative) { dest->exist_l[index] = relative; } void hashMapKMA_free(HashMapKMA *dest) { if(dest) { if(dest->exist && dest->shmFlag & 1) { free(dest->exist); } if(dest->values && dest->shmFlag & 2) { free(dest->values); } if(dest->key_index && dest->shmFlag & 4) { free(dest->key_index); } if(dest->value_index && dest->shmFlag & 8) { free(dest->value_index); } free(dest); } } genomicepidemiology-kma-091b8ffe66ac/qualcheck.h0000644000175000017500000000306214157033525021223 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "compdna.h" #include "hashmap.h" extern int (*QualCheck)(HashMap *templates, CompDNA *, int, double, double, unsigned *, Qseqs *); int lengthCheck(HashMap *templates, CompDNA *qseq, int MinKlen, double homQ, double homT, unsigned *template_ulengths, Qseqs *header); int queryCheck(HashMap *templates, CompDNA *qseq, int MinKlen, double homQ, double homT, unsigned *template_ulengths, Qseqs *header); int templateCheck(HashMap *templates, CompDNA *qseq, int MinKlen, double homQ, double homT, unsigned *template_ulengths, Qseqs *header); void updateScoreAndTemplate(unsigned *Scores_tot, unsigned *bestTemplates, unsigned *values); void updateScoreAndTemplateHU(unsigned *Scores_tot, unsigned *bestTemplates, unsigned *values_org); void addUscore(unsigned *Scores, unsigned *values); void addUscoreHU(unsigned *Scores, unsigned *values_org); genomicepidemiology-kma-091b8ffe66ac/runkma.h0000644000175000017500000000352714157033525020566 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "penalties.h" #include "qseqs.h" #define nameSkip(infile, c) while((c = fgetc(infile)) != '\n' && c != EOF) unsigned char * ustrdup(unsigned char *src, size_t n); int load_DBs_KMA(char *templatefilename, long unsigned **alignment_scores, long unsigned **uniq_alignment_scores, int **template_lengths, unsigned shm); char * nameLoad(Qseqs *name, FILE *infile); int runKMA(char *templatefilename, char *outputfilename, char *exePrev, int ConClave, int kmersize, int minlen, Penalties *rewards, int extendedFeatures, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int ref_fsa, int print_matrix, int print_all, int vcf, int xml, int sam, int nc, int nf, unsigned shm, int thread_num, int verbose); int runKMA_MEM(char *templatefilename, char *outputfilename, char *exePrev, int ConClave, int kmersize, int minlen, Penalties *rewards, int extendedFeatures, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int ref_fsa, int print_matrix, int print_all, int vcf, int xml, int sam, int nc, int nf, unsigned shm, int thread_num, int verbose); genomicepidemiology-kma-091b8ffe66ac/kmerlink.c0000644000175000017500000000311414157033525021070 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "kmerlink.h" #include "pherror.h" KmerLink * initKmerLink(unsigned size) { KmerLink *dest; dest = smalloc(sizeof(KmerLink)); dest->size = size; dest->n = 0; dest->list = smalloc(size * sizeof(KmerAnker)); return dest; } void reallocKmerLink(KmerLink *src, unsigned newSize) { src->size = newSize; src->list = realloc(src->list, newSize * sizeof(KmerAnker)); if(!src->list) { ERROR(); } } KmerAnker * pushKmerLink(KmerLink *src, KmerAnker *node) { KmerAnker *dest; if(src->size == ++src->n) { reallocKmerLink(src, src->size << 1); } dest = src->list + (src->n - 1); *dest = *node; return dest; } KmerAnker * popKmerLink(KmerLink *src, int n) { if(n < src->n) { src->n -= n; } else { src->n = 0; } return src->list + src->n; } void destroyKmerLink(KmerLink *src) { free(src->list); free(src); } genomicepidemiology-kma-091b8ffe66ac/compkmers.c0000644000175000017500000000262414157033525021261 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "compkmers.h" #include "pherror.h" void allocCompKmers(CompKmers *compressor, int size) { compressor->n = 0; compressor->size = size; compressor->kmers = smalloc(size * sizeof(long unsigned)); } void reallocCompKmers(CompKmers *compressor, int size) { compressor->kmers = realloc(compressor->kmers, size * sizeof(long unsigned)); if(!compressor->kmers) { ERROR(); } compressor->size = size; } int pushCompKmers(CompKmers *compressor, char *qseq, int kmersize) { int i; long unsigned key = 0; for(i = 0; i < kmersize; ++i) { if(qseq[i] == 4) { return 0; } else { key = (key << 2) | qseq[i]; } } compressor->kmers[compressor->n] = key; return 1; } genomicepidemiology-kma-091b8ffe66ac/seqmenttree.c0000644000175000017500000001136114157033525021613 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "pherror.h" #include "seqmenttree.h" SeqmentTree * initializeSeqmentTree(const long unsigned size) { SeqmentTree *dest; dest = smalloc(sizeof(SeqmentTree)); dest->n = 0; dest->root = smalloc((dest->size = size) * sizeof(SeqmentTrees)); return dest; } SeqmentTree * initSeqmentTree(SeqmentTree *src, const unsigned start, const unsigned end) { SeqmentTrees *node; if(!src) { src = initializeSeqmentTree(64); } src->n = 1; node = src->root; node->start = start; node->end = end; node->covered = end - start; node->branch[0] = 0; node->branch[1] = 0; return src; } void reallocSeqmentTree(SeqmentTree *src) { src->root = realloc(src->root, (src->size <<= 1) * sizeof(SeqmentTrees)); if(!src->root) { ERROR(); } } unsigned addSeqmentTrees(SeqmentTrees *root, SeqmentTrees *node) { unsigned pos, covered; SeqmentTrees *bud; if(*(root->branch)) { /* search */ /* adjust limits of root */ if(node->start < root->start && root->end < node->end) { root->start = node->start; root->end = node->end; root->covered = node->covered; node->covered = 0; *(root->branch) = 0; return root->covered; } else if(root->end < node->end) { root->end = node->end; } else if(node->start < root->start) { root->start = node->start; } /* search tree */ pos = root->branch[1]->start; if(node->end < pos) { /* left */ root->covered = root->branch[1]->covered + addSeqmentTrees(root->branch[0], node); } else if(pos <= node->start) { /* right */ root->covered = root->branch[0]->covered + addSeqmentTrees(root->branch[1], node); } else { /* split */ /* calculate right side */ pos = node->start; node->start = root->branch[0]->end + 1; node->covered = node->end - node->start; covered = addSeqmentTrees(root->branch[1], node); /* calculate left side */ node->start = pos; node->end = root->branch[0]->end; node->covered = node->end - node->start; root->covered = covered + addSeqmentTrees(root->branch[0], node); } } else if(node->end < root->start || root->end < node->start) { /* new leaf */ /* create and grow bud */ bud = node + 1; bud->start = root->start; bud->end = root->end; bud->covered = root->covered; *(bud->branch) = 0; if(node->end < root->start) { /* right bud */ root->start = node->start; root->branch[0] = node; root->branch[1] = bud; } else { /* left bud */ root->end = node->end; root->branch[0] = bud; root->branch[1] = node; } root->covered += node->covered; } else { /* extend leaf */ if(node->start < root->start) { /* extend left */ root->start = node->start; } if(root->end < node->end) { /* extend right */ root->end = node->end; } node->covered = 0; root->covered = root->end - root->start; } return root->covered; } int growSeqmentTree(SeqmentTree *src, const unsigned start, const unsigned end) { SeqmentTrees *node; /* make room for new anker */ if(src->size <= src->n + 2) { reallocSeqmentTree(src); } else if(src->n == 0) { initSeqmentTree(src, start, end); return end - start; } /* make new leaf */ node = src->root + src->n; node->start = start; node->end = end; node->covered = end - start; *(node->branch) = 0; src->root->covered = addSeqmentTrees(src->root, node); if(node->covered) { src->n += 2; } return src->root->covered; } unsigned queSeqmentTree(SeqmentTrees *src, const unsigned start, const unsigned end) { if(end < src->start || src->end < start) { /* miss */ return 0; } else if(start <= src->start && src->end <= end) { /* leaf covered by query */ return src->covered; } else if(*(src->branch)) { /* check next */ return queSeqmentTree(src->branch[0], start, end) + queSeqmentTree(src->branch[1], start, end); } else if(src->start <= start && end <= src->end) { return end - start; } else if(src->start <= start && start < src->end) { /* left side */ return src->end - start; } else if(src->start < end && end <= src->end) { /* right side */ return end - src->start; } return 0; } genomicepidemiology-kma-091b8ffe66ac/spltdb.c0000644000175000017500000014742214157033525020557 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include #include "align.h" #include "alnfrags.h" #include "assembly.h" #include "chain.h" #include "compdna.h" #include "ef.h" #include "filebuff.h" #include "frags.h" #include "hashmapcci.h" #include "kmapipe.h" #include "nw.h" #include "pherror.h" #include "printconsensus.h" #include "qseqs.h" #include "runkma.h" #include "sam.h" #include "spltdb.h" #include "stdnuc.h" #include "stdstat.h" #include "tmp.h" #include "updatescores.h" #include "version.h" #include "vcf.h" #include "xml.h" int print_ankers_spltDB(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out) { static unsigned target = 1, allIn = 0, thread_num = 1; static SpltDBbuff **buffers = 0; int num, size, tNum, infoSize[8]; unsigned char *buff; SpltDBbuff *node, *nodeN, *node0; if(buffers == 0) { thread_num = rc_flag; buffers = calloc(thread_num, sizeof(SpltDBbuff *)); if(!buffers) { ERROR(); } return 0; } if(qseq == 0) { /* catch remains after last call */ while(allIn) { /* find and write next target */ node = *buffers; num = thread_num; tNum = 0; while(node == 0 && --num) { node = buffers[(tNum = num)]; } node = node->next; target = node->num; while(--num) { if(buffers[num] && buffers[num]->next->num < target) { tNum = num; node = buffers[num]->next; target = node->num; } } sfwrite(node->buff, 1, node->size, out); /* update cylinder */ nodeN = node->prev; node0 = node->next; if(nodeN == node) { --allIn; nodeN = 0; } else { nodeN->next = node0; node0->prev = nodeN; } free(node->buff); free(node); buffers[tNum] = nodeN; } sfwrite(&(unsigned){UINT_MAX}, sizeof(unsigned), 1, out); sfwrite(&(int){out_Tem[2] - 1}, sizeof(int), 1, out); return 0; } num = out_Tem[-1]; infoSize[0] = num; infoSize[1] = qseq->seqlen; infoSize[2] = qseq->complen; infoSize[3] = qseq->N[0]; infoSize[4] = rc_flag; infoSize[5] = *out_Tem; infoSize[6] = header->len; infoSize[7] = flag; if(num == target || thread_num == 1) { sfwrite(infoSize, sizeof(int), 8, out); sfwrite(qseq->seq, sizeof(long unsigned), qseq->complen, out); if(qseq->N[0]) { sfwrite(qseq->N + 1, sizeof(int), qseq->N[0], out); } sfwrite(out_Tem + 1, sizeof(int), *out_Tem, out); sfwrite(header->seq, 1, header->len, out); } else { node = smalloc(sizeof(SpltDBbuff)); size = header->len + sizeof(int) * (8 + qseq->N[0] + out_Tem[0]) + sizeof(long unsigned) * qseq->complen; buff = smalloc(size); node->num = num; node->size = size; node->buff = buff; memcpy(buff, infoSize, (size = sizeof(int) * 8)); buff += size; memcpy(buff, qseq->seq, (size = sizeof(long unsigned) * qseq->complen)); buff += size; memcpy(buff, qseq->N + 1, (size = sizeof(int) * qseq->N[0])); buff += size; memcpy(buff, out_Tem + 1, (size = sizeof(int) * (*out_Tem))); buff += size; memcpy(buff, header->seq, header->len); /* find cylinder piece */ tNum = out_Tem[-2]; /* extend cylinder piece */ if((nodeN = buffers[tNum])) { node0 = nodeN->next; node->prev = nodeN; nodeN->next = node; node->next = node0; node0->prev = node; } else { node->next = node; node->prev = node; ++allIn; } buffers[tNum] = node; } /* collect remains */ while(allIn == thread_num) { /* find and write next target */ node = (*buffers)->next; target = node->num; num = allIn; tNum = 0; while(--num) { if(buffers[num]->next->num < target) { tNum = num; node = buffers[num]->next; target = node->num; } } sfwrite(node->buff, 1, node->size, out); /* update cylinder */ nodeN = node->prev; node0 = node->next; if(nodeN == node) { --allIn; nodeN = 0; } else { nodeN->next = node0; node0->prev = nodeN; } free(node->buff); free(node); buffers[tNum] = nodeN; } return 0; } int print_ankers_Sparse_spltDB(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out) { static unsigned target = 1, allIn = 0, thread_num = 1;; static SpltDBbuff **buffers = 0; int num, size, tNum, infoSize[8]; unsigned char *buff; SpltDBbuff *node, *nodeN, *node0; if(buffers == 0) { thread_num = rc_flag; buffers = calloc(thread_num, sizeof(SpltDBbuff *)); if(!buffers) { ERROR(); } return 0; } if(qseq == 0) { /* catch remains after last call */ while(allIn) { /* find and write next target */ node = *buffers; num = thread_num; tNum = 0; while(node == 0 && --num) { node = buffers[(tNum = num)]; } node = node->next; target = node->num; while(--num) { if(buffers[num] && buffers[num]->next->num < target) { tNum = num; node = buffers[num]->next; target = node->num; } } sfwrite(node->buff, 1, node->size, out); /* update cylinder */ nodeN = node->prev; node0 = node->next; if(nodeN == node) { --allIn; nodeN = 0; } else { nodeN->next = node0; node0->prev = nodeN; } free(node->buff); free(node); buffers[tNum] = nodeN; } sfwrite(&(unsigned){UINT_MAX}, sizeof(unsigned), 1, out); sfwrite(&(int){out_Tem[2] - 1}, sizeof(int), 1, out); return 0; } num = out_Tem[-1]; infoSize[0] = num; infoSize[1] = qseq->seqlen; infoSize[2] = qseq->complen; infoSize[3] = qseq->N[0]; infoSize[4] = -(abs(rc_flag)); infoSize[5] = *out_Tem; infoSize[6] = header->len; infoSize[7] = flag; if(num == target || thread_num == 1) { sfwrite(infoSize, sizeof(int), 8, out); sfwrite(qseq->seq, sizeof(long unsigned), qseq->complen, out); if(qseq->N[0]) { sfwrite(qseq->N + 1, sizeof(int), qseq->N[0], out); } sfwrite(out_Tem + 1, sizeof(int), *out_Tem, out); sfwrite(header->seq, 1, header->len, out); } else { node = smalloc(sizeof(SpltDBbuff)); size = header->len + sizeof(int) * (8 + qseq->N[0] + out_Tem[0]) + sizeof(long unsigned) * qseq->complen; buff = smalloc(size); node->num = num; node->size = size; node->buff = buff; memcpy(buff, infoSize, (size = sizeof(int) * 8)); buff += size; memcpy(buff, qseq->seq, (size = sizeof(long unsigned) * qseq->complen)); buff += size; memcpy(buff, qseq->N + 1, (size = sizeof(int) * qseq->N[0])); buff += size; memcpy(buff, out_Tem + 1, (size = sizeof(int) * (*out_Tem))); buff += size; memcpy(buff, header->seq, header->len); /* find cylinder piece */ tNum = out_Tem[-2]; /* extend cylinder piece */ if((nodeN = buffers[tNum])) { node0 = nodeN->next; node->prev = nodeN; nodeN->next = node; node->next = node0; node0->prev = node; } else { node->next = node; node->prev = node; ++allIn; } buffers[tNum] = node; } /* collect remains */ while(allIn == thread_num) { /* find and write next target */ node = (*buffers)->next; target = node->num; num = allIn; tNum = 0; while(--num) { if(buffers[num]->next->num < target) { tNum = num; node = buffers[num]->next; target = node->num; } } sfwrite(node->buff, 1, node->size, out); /* update cylinder */ nodeN = node->prev; node0 = node->next; if(nodeN == node) { --allIn; nodeN = 0; } else { nodeN->next = node0; node0->prev = nodeN; } free(node->buff); free(node); buffers[tNum] = nodeN; } return 0; } unsigned get_ankers_spltDB(int *infoSize, int *out_Tem, CompDNA *qseq, Qseqs *header, int *flag, FILE *inputfile) { unsigned num; if(qseq) { qseq->seqlen = infoSize[0]; qseq->complen = infoSize[1]; *(qseq->N) = infoSize[2]; *out_Tem = infoSize[4]; header->len = infoSize[5]; *flag = infoSize[6]; /* reallocate */ if(qseq->size <= qseq->seqlen) { free(qseq->N); free(qseq->seq); if(qseq->seqlen & 31) { qseq->size = (qseq->seqlen >> 5) + 1; qseq->size <<= 6; } else { qseq->size = qseq->seqlen << 1; } qseq->seq = calloc(qseq->size >> 5, sizeof(long unsigned)); qseq->N = malloc((qseq->size + 1) * sizeof(int)); if(!qseq->seq || !qseq->N) { ERROR(); } *(qseq->N) = infoSize[2]; } if(header->size < header->len) { free(header->seq); header->size = header->len; header->seq = malloc(header->size); if(!header->seq) { ERROR(); } } cfread(qseq->seq, sizeof(long unsigned), qseq->complen, inputfile); cfread(qseq->N + 1, sizeof(int), qseq->N[0], inputfile); cfread(out_Tem + 1, sizeof(int), *out_Tem, inputfile); cfread(header->seq, 1, header->len, inputfile); } else { /* in the case of equally well scoring DBs */ sfseek(inputfile, infoSize[1] * sizeof(long unsigned) + infoSize[2] * sizeof(int), SEEK_CUR); *out_Tem = infoSize[4]; cfread(out_Tem + 1, sizeof(int), *out_Tem, inputfile); sfseek(inputfile, infoSize[5], SEEK_CUR); } /* get info for next read */ cfread(&num, sizeof(int), 1, inputfile); if(num != UINT_MAX) { cfread(infoSize, sizeof(int), 7, inputfile); } else { cfread(infoSize, sizeof(int), 1, inputfile); } return num; } int runKMA_spltDB(char **templatefilenames, int targetNum, char *outputfilename, int argc, char **argv, int ConClave, int kmersize, int minlen, Penalties *rewards, int extendedFeatures, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int ref_fsa, int print_matrix, int print_all, int vcf, int xml, int sam, int nc, int nf, unsigned shm, int thread_num, int verbose) { /* https://www.youtube.com/watch?v=LtXEMwSG5-8 */ int i, j, k, tmp_template, tmp_tmp_template, t_len, file_len, score, tot; int template, bestHits, start, end, aln_len, fragCount, maxFrag, DB_size; int rc_flag, coverScore, tmp_start, tmp_end, bestTemplate, status, delta; int seq_in_no, progress, sparse, fileCount, rand, stats[5]; int flag, flag_r; int *template_lengths, *bestTargets, *matched_templates, *bestTemplates; int *best_start_pos, *best_end_pos, (*targetInfo)[7], (*ptrInfo)[7]; unsigned randScore, num, target, targetScore, bias; unsigned *fragmentCounts, *readCounts, *nums, *uPtr, *dbBiases; long best_read_score, read_score, seq_seeker; long unsigned Nhits, template_tot_ulen, bestNum, counter, seqin_size; long unsigned *w_scores, *uniq_alignment_scores, *alignment_scores; double tmp_score, bestScore, id, cover, q_id, q_cover, p_value; long double depth, q_value, expected; char *templatefilename, Date[11]; FILE **inputfiles, *inputfile, *frag_in_raw; FILE *res_out, *alignment_out, *consensus_out, *frag_out_raw, *xml_out; FILE *extendedFeatures_out, *name_file, **template_fragments; time_t t0, t1; struct tm *tm; FileBuff *frag_out, *frag_out_all, *matrix_out, *vcf_out; Aln *aligned, *gap_align; Assem *aligned_assem; Frag **alignFrags, *alignFrag; CompDNA *qseq_comp, *qseq_r_comp; Qseqs *qseq, *qseq_r, *header, *header_r, *template_name; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; Assemble_thread *threads, *thread; HashMapCCI *template_index; if(!outputfilename) { fprintf(stderr, " No output file specified!\n"); exit(1); } /* load databases */ status = 0; inputfiles = smalloc(targetNum * sizeof(FILE *)); nums = smalloc(targetNum * sizeof(unsigned)); dbBiases = smalloc((targetNum + 1) * sizeof(unsigned)); /* set these */ bestTargets = smalloc((targetNum + 1) * sizeof(int)); targetInfo = smalloc(targetNum * 6 * sizeof(int)); template_name = setQseqs(256); DB_size = 0; template_lengths = NULL; for(i = 0; i < targetNum; ++i) { /* get length, size and bias */ templatefilename = templatefilenames[i]; file_len = strlen(templatefilename); strcat(templatefilename, ".length.b"); inputfile = sfopen(templatefilename, "rb"); sfread(&bias, sizeof(int), 1, inputfile); dbBiases[i] = DB_size; DB_size += bias; template_lengths = realloc(template_lengths, DB_size * sizeof(int)); if(!template_lengths) { ERROR(); } sfread(template_lengths + dbBiases[i], sizeof(int), bias, inputfile); templatefilename[file_len] = 0; fclose(inputfile); if(sam) { strcat(templatefilename, ".name"); name_file = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; saminit(template_name, name_file, template_lengths + dbBiases[i], bias); fclose(name_file); } } dbBiases[i] = DB_size; if(!kmersize) { kmersize = *template_lengths; } if(kmersize < 4 || 32 < kmersize) { kmersize = 16; } /* get scoring arrays */ matched_templates = smalloc(((DB_size + 1) << 1) * sizeof(int)); bestTemplates = (matched_templates + 1); best_start_pos = calloc((DB_size << 1), sizeof(int)); best_end_pos = smalloc((DB_size << 1) * sizeof(int)); alignment_scores = calloc(DB_size, sizeof(long unsigned)); uniq_alignment_scores = calloc(DB_size, sizeof(long unsigned)); if(!best_start_pos || !alignment_scores || !uniq_alignment_scores) { ERROR(); } /* allocate stuff */ qseq_comp = malloc(sizeof(CompDNA)); qseq_r_comp = malloc(sizeof(CompDNA)); if(!qseq_comp || !qseq_r_comp) { ERROR(); } delta = 1024; allocComp(qseq_comp, delta); allocComp(qseq_r_comp, delta); qseq = setQseqs(delta); qseq_r = setQseqs(delta); header = setQseqs(256); header_r = setQseqs(256); points = seedPoint_init(delta, rewards); /* open outputfiles */ file_len = strlen(outputfilename); strcat(outputfilename, ".res"); res_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; if(nf == 0) { strcat(outputfilename, ".frag.gz"); frag_out = gzInitFileBuff(CHUNK); openFileBuff(frag_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { frag_out = 0; } if(nc == 0) { strcat(outputfilename, ".aln"); alignment_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else if(nc == 2) { alignment_out = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else { alignment_out = 0; consensus_out = 0; } frag_out_raw = tmpF(0); if(!frag_out_raw) { ERROR(); } if(print_matrix) { matrix_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".mat.gz"); openFileBuff(matrix_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { matrix_out = 0; } if(print_all) { strcat(outputfilename, ".frag_raw.gz"); frag_out_all = gzInitFileBuff(CHUNK); openFileBuff(frag_out_all, outputfilename, "wb"); outputfilename[file_len] = 0; } else { frag_out_all = 0; } if(vcf) { vcf_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".vcf.gz"); openFileBuff(vcf_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { vcf_out = 0; } if(extendedFeatures) { strcat(outputfilename, ".mapstat"); extendedFeatures_out = sfopen(outputfilename, "wb"); outputfilename[file_len] = 0; fprintf(extendedFeatures_out, "## method\tKMA\n"); fprintf(extendedFeatures_out, "## version\t%s\n", KMA_VERSION); fprintf(extendedFeatures_out, "## databases\t%s", noFolder(*templatefilenames)); for(i = 1; i < targetNum; ++i) { fprintf(extendedFeatures_out, ", %s", noFolder(templatefilenames[i])); } fprintf(extendedFeatures_out, "\n"); time(&t1); tm = localtime(&t1); strftime(Date, sizeof(Date), "%Y-%m-%d", tm); fprintf(extendedFeatures_out, "## date\t%s\n", Date); fprintf(extendedFeatures_out, "## command\t%s", *argv); for(i = 1; i < argc; ++i) { fprintf(extendedFeatures_out, " %s", argv[i]); } fprintf(extendedFeatures_out, "\n"); } else { extendedFeatures_out = 0; } if(xml) { if(xml == 2) { xml_out = openInitXML("--", noFolder(*templatefilenames), **targetInfo, argc, argv); } else { strcat(outputfilename, ".xml"); xml_out = openInitXML(outputfilename, noFolder(*templatefilenames), **targetInfo, argc, argv); outputfilename[file_len] = 0; } } else { xml_out = 0; } /* open input streams */ file_len = strlen(outputfilename); for(i = 0; i < targetNum; ++i) { j = sprintf(outputfilename + file_len, ".%d", i); while(!(inputfile = fopen(outputfilename, "rb"))) { usleep(100); } setvbuf(inputfile, NULL, _IOFBF, CHUNK); inputfiles[i] = inputfile; outputfilename[file_len] = 0; } fprintf(stderr, "# Collecting k-mer scores.\n"); t0 = clock(); /* collect from DB mappings */ uPtr = nums + (i = targetNum); ptrInfo = targetInfo + i; while(i--) { cfread(--uPtr, sizeof(unsigned), 1, inputfiles[i]); if(*uPtr != UINT_MAX) { cfread(--ptrInfo, sizeof(int), 7, inputfiles[i]); } else { cfread(--ptrInfo, sizeof(int), 1, inputfiles[i]); (*--ptrInfo)[3] = INT_MAX; } } Nhits = 0; target = 0; targetScore = 0; rc_flag = 0; qseq->len = 0; qseq_comp->seqlen = 0; *bestTargets = 0; while(target != UINT_MAX) { /* join best templates */ read_score = 0; *matched_templates = 0; qseq->len = 0; qseq_r->len = 0; for(i = 1; i <= *bestTargets; ++i) { num = bestTargets[i]; nums[num] = get_ankers_spltDB(targetInfo[num], matched_templates + (*matched_templates + 1), qseq_comp, header, &flag, inputfiles[num]); qseq->len = qseq_comp->seqlen; if(matched_templates[*matched_templates + 1]) { read_score = 0; } else { // PE //target = nums[num]; nums[num] = get_ankers_spltDB(targetInfo[num], matched_templates + (*matched_templates + 1), qseq_r_comp, header_r, &flag_r, inputfiles[num]); qseq_r->len = qseq_r_comp->seqlen; read_score = 1; } /* bias the templates */ bias = dbBiases[num]; j = *matched_templates + 1; *matched_templates += matched_templates[*matched_templates + 1]; while((k = j++) <= *matched_templates) { matched_templates[k] = matched_templates[j] + bias; } } if(kmersize <= qseq->len) { if(delta <= MAX(qseq->len, qseq_r->len)) { delta = MAX(qseq->len, qseq_r->len); delta <<= 1; qseq->size = delta; qseq_r->size = delta; free(qseq->seq); free(qseq_r->seq); qseq->seq = smalloc(delta); qseq_r->seq = smalloc(delta); } unCompDNA(qseq_comp, qseq->seq); best_read_score = targetScore; for(i = 1, bestHits = 0; i <= *matched_templates; ++i, ++bestHits) { best_end_pos[bestHits] = template_lengths[abs(matched_templates[i])]; } if(rc_flag < 0 && 0 < matched_templates[*matched_templates]) { bestHits = -bestHits; } if(read_score && kmersize <= qseq_r->len) { unCompDNA(qseq_r_comp, qseq_r->seq); update_Scores_pe(qseq->seq, qseq->len, qseq_r->seq, qseq_r->len, bestHits, best_read_score + read_score, best_start_pos, best_end_pos, bestTemplates, header, header_r, flag, flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); } else { update_Scores(qseq->seq, qseq->len, bestHits, best_read_score, best_start_pos, best_end_pos, bestTemplates, header, flag, alignment_scores, uniq_alignment_scores, frag_out_raw); } /* dump seq to all */ if(frag_out_all) { updateAllFrag(qseq->seq, qseq->len, abs(bestHits), best_read_score, best_start_pos, best_end_pos, bestTemplates, header, frag_out_all); if(read_score) { updateAllFrag(qseq_r->seq, qseq_r->len, abs(bestHits), read_score, best_start_pos, best_end_pos, bestTemplates, header_r, frag_out_all); } } /* verbose */ if(verbose && verbose++ == 1024) { Nhits += verbose - 1; fprintf(stderr, "# Scored %ld query sequences.\n", Nhits); verbose = 1; } } /* remove inferior read matches */ if(*matched_templates != 0) { if(read_score || (flag & 1) == 0 || (flag & 128)) { /* PE or SE or last in pair */ /* wipe all from same fragment */ i = targetNum - 1; uPtr = nums + i; while(i) { if(*uPtr == target) { *uPtr = get_ankers_spltDB(targetInfo[i], matched_templates, qseq_comp, header, &flag, inputfiles[i]); } else { --uPtr; --i; } } } else if(flag & 64) { /* first in pair */ /* conserve second non-paired */ i = targetNum - 1; uPtr = nums + i; while(i) { if(*uPtr == target) { if((targetInfo[i][6] & 128) && targetInfo[i][4] == 0) { --uPtr; --i; } else { if(targetInfo[i] == 0) { *uPtr = get_ankers_spltDB(targetInfo[i], matched_templates, qseq_comp, header, &flag, inputfiles[i]); } *uPtr = get_ankers_spltDB(targetInfo[i], matched_templates, qseq_comp, header, &flag, inputfiles[i]); --uPtr; --i; } } else { --uPtr; --i; } } } } /* get best templates for next read */ uPtr = nums; target = UINT_MAX; targetScore = UINT_MAX; rc_flag = 0; *bestTargets = 0; for(i = 0; i < targetNum; ++i) { if(*uPtr < target) { target = *uPtr; rc_flag = targetInfo[i][3]; targetScore = abs(rc_flag); *bestTargets = 1; bestTargets[1] = i; } else if(*uPtr == target) { if(targetScore < abs(targetInfo[i][3])) { rc_flag = targetInfo[i][3]; targetScore = abs(rc_flag); /* clear inferior matches */ /* j = *bestTargets + 1; while(--j) { if(targetInfo[j][4] == 0) { uPtr[j] = get_ankers_spltDB(targetInfo[j], matched_templates, qseq_comp, header, &flag, inputfiles[j]); } uPtr[j] = get_ankers_spltDB(targetInfo[j], matched_templates, qseq_comp, header, &flag, inputfiles[j]); } */ *bestTargets = 1; bestTargets[1] = i; } else if(targetScore == abs(targetInfo[i][3])) { bestTargets[++*bestTargets] = i; rc_flag = rc_flag < 0 ? rc_flag : targetInfo[i][3]; } else if(*uPtr == UINT_MAX) { targetInfo[i][3] = INT_MAX; } else { if(targetInfo[i][4] == 0) { /* PE */ *uPtr = get_ankers_spltDB(targetInfo[i], matched_templates, qseq_comp, header, &flag, inputfiles[i]); } *uPtr = get_ankers_spltDB(targetInfo[i], matched_templates, qseq_comp, header, &flag, inputfiles[i]); } } ++uPtr; } } /* verbose */ if(verbose) { Nhits += verbose - 1; fprintf(stderr, "# Scored %ld query sequences.\n", Nhits); verbose = 1; } /* get fragmentCount */ if(extendedFeatures) { fprintf(extendedFeatures_out, "## fragmentCount\t%u\n", **targetInfo); fprintf(extendedFeatures_out, "# refSequence\treadCount\tfragmentCount\tmapScoreSum\trefCoveredPositions\trefConsensusSum\tbpTotal\tdepthVariance\tnucHighDepthVariance\tdepthMax\tsnpSum\tinsertSum\tdeletionSum\n"); } /* close files */ i = targetNum; while(i--) { fclose(inputfiles[i]); } i = 0; sfwrite(&i, sizeof(int), 1, frag_out_raw); fflush(frag_out_raw); freeComp(qseq_comp); free(qseq_comp); freeComp(qseq_r_comp); free(qseq_r_comp); if(header->size < header_r->size) { destroyQseqs(header); header = header_r; } else { destroyQseqs(header_r); } header_r = 0; if(qseq->size < qseq_r->size) { destroyQseqs(qseq); qseq = qseq_r; } else { destroyQseqs(qseq_r); } qseq_r = 0; if(frag_out_all) { destroyGzFileBuff(frag_out_all); } t1 = clock(); fprintf(stderr, "#\n# Time for score collecting:\t%.2f s.\n", difftime(t1, t0) / 1000000); fprintf(stderr, "#\n# Sort, output and select k-mer alignments.\n"); t0 = clock(); /* Get best template for each mapped deltamer/read */ /* Best hit chosen as: highest mapping score then higest # unique maps */ alignFrags = calloc(DB_size, sizeof(Frag*)); w_scores = calloc(DB_size, sizeof(long unsigned)); template_fragments = calloc(DB_size, sizeof(FILE*)); if(!alignFrags || !w_scores || !template_fragments) { ERROR(); } frag_in_raw = frag_out_raw; rewind(frag_in_raw); fragCount = 0; fileCount = 0; maxFrag = 1000000; /* Patricks features */ if(extendedFeatures || xml) { fragmentCounts = calloc(DB_size, sizeof(unsigned)); readCounts = calloc(DB_size, sizeof(unsigned)); if(!fragmentCounts || !readCounts) { ERROR(); } } else { fragmentCounts = 0; readCounts = 0; } /* Get expected values */ sparse = 0; template_tot_ulen = 0; i = DB_size; while(--i) { template_tot_ulen += template_lengths[i]; } /* ConClave */ if(ConClave == 1) { while(fread(stats, sizeof(int), 5, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; flag = stats[4]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); sfread(best_start_pos, sizeof(int), bestHits, frag_in_raw); sfread(best_end_pos, sizeof(int), bestHits, frag_in_raw); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best */ if(bestHits > 1) { bestTemplate = -1; bestScore = 0; best_read_score = 0; bestNum = 0; start = 0; end = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; tmp_start = best_start_pos[i]; tmp_end = best_end_pos[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(alignment_scores[tmp_template] == best_read_score) { } else if(tmp_score == bestScore) { //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { } else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } } } } } else { bestTemplate = *bestTemplates; start = *best_start_pos; end = *best_end_pos; } /* reverse complement seq */ if(bestTemplate < 0) { bestTemplate = -bestTemplate; strrc(qseq->seq, qseq->len); } w_scores[bestTemplate] += read_score; if(fragmentCounts) { fragmentCounts[bestTemplate]++; readCounts[bestTemplate]++; } /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; if(stats[2] < 0) { if(extendedFeatures) { readCounts[bestTemplate]++; } sfread(stats, sizeof(int), 3, frag_in_raw); qseq->len = stats[0]; header->len = stats[1]; flag = stats[2]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; } if(fragCount >= maxFrag) { template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; fragCount = 0; /* control fileamount */ if(fileCount >= DB_size) { template_fragments = realloc(template_fragments, (fileCount + 1) * sizeof(FILE*)); if(!template_fragments) { ERROR(); } } } } template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; } else if(ConClave == 2) { /* find potential template candidates */ while(fread(stats, sizeof(int), 4, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; /* best templates, skip rest */ fseek(frag_in_raw, qseq->len + header->len + (2 * bestHits + 1) * sizeof(int), SEEK_CUR); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best */ if(bestHits > 1) { bestTemplate = -1; bestScore = 0; best_read_score = 0; bestNum = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; //} else if(alignment_scores[tmp_template] == best_read_score) { } else if(tmp_score == bestScore) { //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; //} else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { } else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } } } } } else { bestTemplate = *bestTemplates; } w_scores[abs(bestTemplate)] += read_score; if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); fseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } } rewind(frag_in_raw); /* discard insignifiacant templates */ Nhits = 0; template = DB_size; while(--template) { Nhits += w_scores[template]; } template = DB_size; while(--template) { if((read_score = w_scores[template])) { t_len = template_lengths[template]; //expected = (Nhits - read_score) * (t_len / (template_tot_ulen - t_len + etta)); expected = t_len; expected /= (template_tot_ulen - t_len); expected *= (Nhits - read_score); //q_value = pow(read_score - expected, 2) / (expected + read_score + etta); q_value = read_score - expected; q_value /= (expected + read_score); q_value *= read_score - expected; p_value = p_chisqr(q_value); if(cmp((p_value <= evalue && read_score > expected), (read_score >= scoreT * t_len)) == 0) { w_scores[template] = 0; } } } /* identify sorting keys */ while(fread(stats, sizeof(int), 4, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; if(bestHits != 1) { /* best templates, skip rest */ fseek(frag_in_raw, qseq->len + header->len + (2 * bestHits + 1) * sizeof(int), SEEK_CUR); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); bestTemplate = 0; i = bestHits; while(i--) { template = abs(bestTemplates[i]); if(w_scores[template]) { if(bestTemplate) { bestTemplate = 0; break; } else { bestTemplate = template; } } } if(bestTemplate) { uniq_alignment_scores[bestTemplate] += read_score; } } else { /* skip rest */ fseek(frag_in_raw, qseq->len + header->len + 4 * sizeof(int), SEEK_CUR); } if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); fseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } } rewind(frag_in_raw); /* choose the templates */ memset(w_scores, 0, DB_size * sizeof(long unsigned)); while(fread(stats, sizeof(int), 5, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; flag = stats[4]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); sfread(best_start_pos, sizeof(int), bestHits, frag_in_raw); sfread(best_end_pos, sizeof(int), bestHits, frag_in_raw); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best according to sorting keys */ if(bestHits != 1) { bestTemplate = 0; bestScore = 0; start = 0; end = 0; tot = 0; i = bestHits; while(i--) { tot += uniq_alignment_scores[abs(bestTemplates[i])]; } if(tot && 16 <= qseq->len) { /* get seed */ rand = qseq->seq[0]; i = -1; j = qseq->len; while(++i < 7) { rand = (((rand << 2) | qseq->seq[i]) << 2) | qseq->seq[--j]; } /* minimal standard */ rand = 16807 * (rand % 127773) - 2836 * (rand / 127773); if (rand <= 0) { rand += 0x7fffffff; } tmp_score = rand; tmp_score /= INT_MAX; randScore = tmp_score * tot; score = 0; i = 0; while(i != bestHits) { score += uniq_alignment_scores[abs(bestTemplates[i])]; if(randScore < score) { bestTemplate = bestTemplates[i]; start = best_start_pos[i]; end = best_end_pos[i]; i = bestHits; } else { ++i; } } if(bestTemplate == 0) { tot = 0; } } else { tot = 0; } if(tot == 0) { bestTemplate = 0; best_read_score = 0; bestNum = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; tmp_start = best_start_pos[i]; tmp_end = best_end_pos[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(alignment_scores[tmp_template] == best_read_score) { } else if(tmp_score == bestScore) { //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { } else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } } } } } } else { bestTemplate = *bestTemplates; start = *best_start_pos; end = *best_end_pos; } /* reverse complement seq */ if(bestTemplate < 0) { bestTemplate = -bestTemplate; strrc(qseq->seq, qseq->len); } if(bestTemplate) { w_scores[bestTemplate] += read_score; if(fragmentCounts) { fragmentCounts[bestTemplate]++; readCounts[bestTemplate]++; } /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; if(stats[2] < 0) { if(extendedFeatures) { readCounts[bestTemplate]++; } sfread(stats, sizeof(int), 3, frag_in_raw); qseq->len = stats[0]; header->len = stats[1]; flag = stats[2]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; } } else if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); sfseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } if(fragCount >= maxFrag) { template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; fragCount = 0; /* control fileamount */ if(fileCount >= DB_size) { template_fragments = realloc(template_fragments, (fileCount + 1) * sizeof(FILE*)); if(!template_fragments) { ERROR(); } } } } template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; } fragCount = 0; free(alignFrags); free(best_start_pos); free(best_end_pos); free(matched_templates); fclose(frag_out_raw); /* Get expected values */ Nhits = 0; i = DB_size; while(--i) { Nhits += w_scores[i]; } Nhits = Nhits ? Nhits : 1; t1 = clock(); fprintf(stderr, "# Total time for sorting and outputting KMA alignment\t%.2f s.\n", difftime(t1, t0) / 1000000); fprintf(stderr, "#\n# Doing local assemblies of found templates, and output results\n"); t0 = clock(); /* print heading of resistance file: */ fprintf(res_out, "#Template\tScore\tExpected\tTemplate_length\tTemplate_Identity\tTemplate_Coverage\tQuery_Identity\tQuery_Coverage\tDepth\tq_value\tp_value\n"); if(vcf) { templatefilename = 0; initialiseVcf(vcf_out, templatefilename); } seq_in_no = 0; /* preallocate assembly matrices */ matrix = smalloc(sizeof(AssemInfo)); aligned_assem = smalloc(sizeof(Assem)); matrix->size = delta; for(i = 0; i < DB_size; ++i) { if(matrix->size < template_lengths[i]) { matrix->size = template_lengths[i]; } } if(alnToMatPtr == &alnToMat) { matrix->size <<= 1; } else { matrix->size++; } matrix->assmb = smalloc(matrix->size * sizeof(Assembly)); aligned_assem->size = matrix->size; aligned_assem->t = smalloc(aligned_assem->size); aligned_assem->s = smalloc(aligned_assem->size); aligned_assem->q = smalloc(aligned_assem->size); seq_in_no = 0; template_index = smalloc(sizeof(HashMapCCI)); template_index->size = 0; hashMapCCI_initialize(template_index, matrix->size, kmersize); /* allocate matrcies for NW */ i = 1; threads = 0; while(i < thread_num) { /* allocate matrices */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); /* move it to the thread */ thread = smalloc(sizeof(Assemble_thread)); thread->num = i; thread->thread_num = thread_num; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = extendedFeatures; thread->seq_in = seq_in_no; thread->kmersize = kmersize; thread->template = -2; thread->file_count = fileCount; thread->files = template_fragments; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->aligned_assem = aligned_assem; thread->aligned = aligned; thread->gap_align = gap_align; thread->NWmatrices = NWmatrices; thread->matrix = matrix; thread->qseq = setQseqs(qseq->size); thread->header = setQseqs(header->size); thread->points = seedPoint_init(delta, rewards); thread->points->len = 0; thread->spin = (sparse < 0) ? 10 : 100; thread->template_index = template_index; thread->next = threads; threads = thread; /* start thread */ if((errno = pthread_create(&thread->id, NULL, assembly_KMA_Ptr, thread))) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); fprintf(stderr, "Will continue with %d threads.\n", i); threads = thread->next; free(thread); i = thread_num; } else { ++i; } } /* start main thread */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); /* move it to the thread */ thread = smalloc(sizeof(Assemble_thread)); thread->num = 0; thread->thread_num = thread_num; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = extendedFeatures; thread->seq_in = seq_in_no; thread->kmersize = kmersize; thread->template = 0; thread->file_count = fileCount; thread->files = template_fragments; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->aligned_assem = aligned_assem; thread->aligned = aligned; thread->gap_align = gap_align; thread->NWmatrices = NWmatrices; thread->matrix = matrix; thread->qseq = qseq; thread->header = header; thread->points = points; thread->points->len = 0; thread->next = 0; thread->spin = (sparse < 0) ? 10 : 100; thread->template_index = template_index; /* Do local assemblies of fragments mapping to the same template */ depth = 0; q_id = 0; cover = 0; q_cover = 0; seq_seeker = 0; progress = 0; counter = 0; if(progress) { fprintf(stderr, "# Progress:\t%3d%%\r", 0); fflush(stderr); } else if(verbose) { fprintf(stderr, "# Template\tScore\tProgress\n"); } /* get index, seq and names on the fly */ bias = *dbBiases++; templatefilename = *templatefilenames++; file_len = strlen(templatefilename); strcat(templatefilename, ".seq.b"); seq_in_no = open(templatefilename, O_RDONLY); if(seq_in_no == -1) { ERROR(); } seqin_size = 4 * lseek(seq_in_no, 0, SEEK_END); if(lseek(seq_in_no, 0, SEEK_SET) != 0) { ERROR(); } thread->seq_in = seq_in_no; templatefilename[file_len] = 0; strcat(templatefilename, ".name"); name_file = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; alignLoadPtr = &alignLoad_fly_mem; if(kmersize < 4 || 32 < kmersize) { kmersize = 16; } if(extendedFeatures == 2) { printExtendedFeatures(templatefilename, 0, 0, 0, extendedFeatures_out); } if(assembly_KMA_Ptr == &skip_assemble_KMA) { alignLoadPtr = &alignLoad_skip; } for(template = 1; template < DB_size; ++template) { if(template == *dbBiases) { /* swap indexes */ templatefilename = *templatefilenames++; bias = *dbBiases++; file_len = strlen(templatefilename); strcat(templatefilename, ".name"); fclose(name_file); name_file = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; strcat(templatefilename, ".seq.b"); close(seq_in_no); seq_in_no = open(templatefilename, O_RDONLY); if(seq_in_no == -1) { ERROR(); } seqin_size = 4 * lseek(seq_in_no, 0, SEEK_END); if(lseek(seq_in_no, 0, SEEK_SET) != 0) { ERROR(); } thread->seq_in = seq_in_no; templatefilename[file_len] = 0; seq_seeker = 0; if(extendedFeatures == 2) { printExtendedFeatures(templatefilename, 0, 0, 0, extendedFeatures_out); } } else if(w_scores[template] > 0) { if(progress) { counter += w_scores[template]; fprintf(stderr, "# Progress:\t%3lu%%\r", 100 * counter / Nhits); fflush(stderr); } else if(verbose) { counter += w_scores[template]; fprintf(stderr, "# %d / %d\t%lu\t%3lu%%\n", template, DB_size, w_scores[template], 100 * counter / Nhits); } /* make p_value to see whether assembly is feasable */ read_score = w_scores[template]; t_len = template_lengths[template]; expected = t_len; expected /= (template_tot_ulen - t_len); expected *= (Nhits - read_score); if(0 < expected) { q_value = read_score - expected; q_value /= (expected + read_score); q_value *= (read_score - expected); } else { q_value = read_score; } p_value = p_chisqr(q_value); if(cmp((p_value <= evalue && read_score > expected), (read_score >= scoreT * t_len))) { /* load DB */ thread->template_name = nameLoad(template_name, name_file); seq_seeker *= sizeof(long unsigned); lseek(seq_in_no, seq_seeker, SEEK_CUR); seq_seeker = 0; thread->template_index->len = 0; if(xml) { newIterXML(xml_out, template, t_len, thread->template_name); } /* Do assembly */ //status |= assemblyPtr(aligned_assem, template, template_fragments, fileCount, frag_out, aligned, gap_align, qseq, header, matrix, points, NWmatrices); thread->template = template; thread->t_len = t_len; assembly_KMA_Ptr(thread); /* Depth, ID and coverage */ if(aligned_assem->cover > 0) { coverScore = aligned_assem->cover; depth = aligned_assem->depth; depth /= t_len; id = 100.0 * coverScore / t_len; aln_len = aligned_assem->aln_len; q_id = 100.0 * coverScore / aln_len; cover = 100.0 * aln_len / t_len; q_cover = 100.0 * t_len / aln_len; } else { id = 0; q_id = 0; depth = aligned_assem->depth; depth /= t_len; aln_len = aligned_assem->aln_len; cover = 100.0 * aln_len / t_len; q_cover = 0; } if(xml) { capIterXML(xml_out, DB_size, seqin_size, t_len, readCounts[template], p_value, read_score, aligned_assem->q, aln_len); } if(ID_t <= id) { /* Output result */ fprintf(res_out, "%-12s\t%8ld\t%8u\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, (unsigned) expected, t_len, id, cover, q_id, q_cover, (double) depth, (double) q_value, p_value); if(nc != 1) { printConsensus(aligned_assem, thread->template_name, alignment_out, consensus_out, ref_fsa); } /* print matrix */ if(matrix_out) { updateMatrix(matrix_out, thread->template_name, thread->template_index->seq, matrix, t_len); } if(extendedFeatures) { printExtendedFeatures(thread->template_name, aligned_assem, fragmentCounts[template], readCounts[template], extendedFeatures_out); } if(vcf) { updateVcf(thread->template_name, aligned_assem->t, evalue, support, bcd, t_len, matrix, vcf, vcf_out); } } } else { if(sam || ID_t == 0.0) { seq_seeker *= sizeof(long unsigned); lseek(seq_in_no, seq_seeker, SEEK_CUR); seq_seeker = 0; thread->template_index = alignLoadPtr(thread->template_index, seq_in_no, template_lengths[template], kmersize, 0); thread->template_name = nameLoad(template_name, name_file); skip_assemble_KMA(thread); if(ID_t == 0.0) { depth = aligned_assem->depth; depth /= t_len; fprintf(res_out, "%-12s\t%8ld\t%8u\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, (unsigned) expected, t_len, 0.0, 0.0, 0.0, 0.0, (double) depth, (double) q_value, p_value); if(extendedFeatures) { printExtendedFeatures(thread->template_name, aligned_assem, fragmentCounts[template], readCounts[template], extendedFeatures_out); } } } else { nameSkip(name_file, end); } seq_seeker += ((template_lengths[template] >> 5) + 1); } } else { nameSkip(name_file, end); seq_seeker += ((template_lengths[template] >> 5) + 1); } } if(progress) { fprintf(stderr, "\n"); } /* join threads */ thread->template = -1; assembly_KMA_Ptr(thread); for(thread = threads; thread != 0; thread = thread->next) { /* join thread */ if((errno = pthread_join(thread->id, NULL))) { ERROR(); } } /* Close files */ close(seq_in_no); fclose(res_out); if(alignment_out) { fclose(alignment_out); fclose(consensus_out); } fclose(name_file); if(frag_out) { destroyGzFileBuff(frag_out); } if(matrix_out) { destroyGzFileBuff(matrix_out); } if(extendedFeatures) { fclose(extendedFeatures_out); } if(vcf) { destroyGzFileBuff(vcf_out); } if(xml) { closeCapXML(xml_out); } t1 = clock(); fprintf(stderr, "# Total time used for local assembly: %.2f s.\n#\n", difftime(t1, t0) / 1000000); return status; } genomicepidemiology-kma-091b8ffe66ac/seqparse.c0000644000175000017500000002427414157033525021111 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "filebuff.h" #include "pherror.h" #include "qseqs.h" #include "seqparse.h" int openAndDetermine(FileBuff *inputfile, char *filename) { unsigned FASTQ; short unsigned *check; /* determine filetype and open it */ FASTQ = 0; if(*filename == '-' && strcmp(filename + 1, "-") == 0) { inputfile->file = stdin; } else { openFileBuff(inputfile, filename, "rb"); } if(buff_FileBuff(inputfile)) { check = (short unsigned *) inputfile->buffer; if(*check == 35615) { FASTQ = 4; init_gzFile(inputfile); buffFileBuff = &BuffgzFileBuff; } else { buffFileBuff = &buff_FileBuff; } } else { inputfile->buffer[0] = 0; } if(inputfile->buffer[0] == '@') { //FASTQ FASTQ |= 1; } else if(inputfile->buffer[0] == '>') { //FASTA FASTQ |= 2; } else { fprintf(stderr, "Cannot determine format of file:\t%s\n", filename); errno |= 1; } return FASTQ; } int FileBuffgetFsa(FileBuff *src, Qseqs *header, Qseqs *qseq, char *trans) { unsigned char *buff, *seq; unsigned size, avail; /* init */ avail = src->bytes; buff = src->next; qseq->len = 0; if(avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* get header */ seq = header->seq; size = header->size; while((*seq++ = *buff++) != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } if(--size == 0) { size = header->size; header->size <<= 1; header->seq = realloc(header->seq, header->size); if(!header->seq) { ERROR(); } seq = header->seq + size; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* chomp header */ while(isspace(*--seq)) { ++size; } *++seq = 0; header->len = header->size - size + 1; /* get qseq */ seq = qseq->seq; size = qseq->size; while(*buff != '>') { *seq = trans[*buff++]; if(((*seq) >> 3) == 0) { if(--size == 0) { size = qseq->size; qseq->size <<= 1; qseq->seq = realloc(qseq->seq, qseq->size); if(!qseq->seq) { ERROR(); } seq = qseq->seq + size; } else { ++seq; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { /* chomp header */ while(*--seq == 8) { ++size; } *++seq = 0; qseq->len = qseq->size - size; src->bytes = 0; src->next = buff; return 1; } buff = src->buffer; } } /* chomp header */ while(*--seq == 8) { ++size; } *++seq = 0; qseq->len = qseq->size - size; src->bytes = avail; src->next = buff; return 1; } int FileBuffgetFsaSeq(FileBuff *src, Qseqs *qseq, char *trans) { unsigned char *buff, *seq; unsigned size, avail; /* init */ avail = src->bytes; buff = src->next; qseq->len = 0; if(avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* skip header */ while(*buff++ != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* get qseq */ seq = qseq->seq; size = qseq->size; while(*buff != '>') { *seq = trans[*buff++]; if(((*seq) >> 3) == 0) { if(--size == 0) { size = qseq->size; qseq->size <<= 1; qseq->seq = realloc(qseq->seq, qseq->size); if(!qseq->seq) { ERROR(); } seq = qseq->seq + size; } else { ++seq; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { /* chomp header */ while(*--seq == 8) { ++size; } *++seq = 0; qseq->len = qseq->size - size; src->bytes = 0; src->next = buff; return 1; } buff = src->buffer; } } /* chomp qseq */ while(*--seq == 8) { ++size; } *++seq = 0; qseq->len = qseq->size - size; src->bytes = avail; src->next = buff; return 1; } int FileBuffgetFq(FileBuff *src, Qseqs *header, Qseqs *qseq, Qseqs *qual, char *trans) { unsigned char *buff, *seq; unsigned size, avail; /* init */ avail = src->bytes; buff = src->next; qseq->len = 0; if(avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } if(*buff != '@') { fprintf(stderr, "Malformed input.\n"); errno |= 1; return 0; } /* get header */ seq = header->seq; size = header->size; while((*seq++ = *buff++) != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } if(--size == 0) { size = header->size; header->size <<= 1; header->seq = realloc(header->seq, header->size); if(!header->seq) { ERROR(); } seq = header->seq + size; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* chomp header */ while(isspace(*--seq)) { ++size; } *++seq = 0; header->len = header->size - size + 1; /* get qseq */ seq = qseq->seq; size = qseq->size; while((*seq++ = trans[*buff++]) != 16) { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } if(--size == 0) { size = qseq->size; qseq->size <<= 1; qseq->seq = realloc(qseq->seq, qseq->size); if(!qseq->seq) { ERROR(); } seq = qseq->seq + size; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* chomp header */ while(*--seq == 8) { ++size; } *++seq = 0; qseq->len = qseq->size - size; /* skip info */ while(*buff++ != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* get quality */ if(qual->size != qseq->size) { qual->size = qseq->size; free(qual->seq); qual->seq = malloc(qual->size); if(!qual->seq) { ERROR(); } } qual->len = qseq->len; if(qual->len < avail) { memcpy(qual->seq, buff, qual->len); avail -= qual->len; buff += qual->len; } else { seq = qual->seq; memcpy(seq, buff, avail); seq += avail; size = qual->len - avail; if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; memcpy(seq, buff, size); } qual->seq[qual->len] = 0; /* skip newline */ while(*buff++ != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { /* warning */ fprintf(stderr, "Truncated file.\n"); return 0; } buff = src->buffer; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 1; } src->bytes = avail; buff = src->buffer; } src->bytes = avail; src->next = buff; return 1; } int FileBuffgetFqSeq(FileBuff *src, Qseqs *qseq, Qseqs *qual, char *trans) { unsigned char *buff, *seq; unsigned size, avail; /* init */ avail = src->bytes; buff = src->next; qseq->len = 0; if(avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } if(*buff != '@') { fprintf(stderr, "Malformed input.\n"); errno |= 1; return 0; } /* skip header */ while(*buff++ != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* get qseq */ seq = qseq->seq; size = qseq->size; while((*seq++ = trans[*buff++]) != 16) { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } if(--size == 0) { size = qseq->size; qseq->size <<= 1; qseq->seq = realloc(qseq->seq, qseq->size); if(!qseq->seq) { ERROR(); } seq = qseq->seq + size; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* chomp header */ while(*--seq == 8) { ++size; } *++seq = 0; qseq->len = qseq->size - size; /* skip info */ while(*buff++ != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } /* get quality */ if(qual->size != qseq->size) { qual->size = qseq->size; free(qual->seq); qual->seq = malloc(qual->size); if(!qual->seq) { ERROR(); } } qual->len = qseq->len; if(qual->len < avail) { memcpy(qual->seq, buff, qual->len); avail -= qual->len; buff += qual->len; } else { seq = qual->seq; memcpy(seq, buff, avail); seq += avail; size = qual->len - avail; if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; memcpy(seq, buff, size); } qual->seq[qual->len] = 0; /* skip newline */ while(*buff++ != '\n') { if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 0; } buff = src->buffer; } } if(--avail == 0) { if((avail = buffFileBuff(src)) == 0) { return 1; } src->bytes = avail; buff = src->buffer; } src->bytes = avail; src->next = buff; return 1; } int getPhredFileBuff(FileBuff *dest) { int seek, avail, scale; unsigned char *buff; avail = dest->bytes; scale = 33; buff = dest->next; while(avail) { seek = 3; while(seek && --avail) { if(*++buff == '\n') { --seek; } } seek = avail ? 1 : 0; while(seek && --avail) { if(*++buff == '\n') { seek = 0; } else if(*buff < 33) { return 0; } else if(53 < *buff && *buff < 59) { return 33; } else if(94 < *buff) { scale = 64; } } } return scale; } genomicepidemiology-kma-091b8ffe66ac/compress.c0000644000175000017500000007744514157033525021131 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "compress.h" #include "hashmap.h" #include "hashmapkma.h" #include "pherror.h" #include "valueshash.h" #ifdef _WIN32 #define mmap(addr, len, prot, flags, fd, offset) (0; fprintf(stderr, "mmap not available on windows.\n"); exit(1);); #define munmap(addr, len) (-1); #else #include #endif unsigned (*valuesSize)(unsigned *); static void mmapinit(HashMapKMA *finalDB, long unsigned size, FILE *out) { /* allocate file */ fseek(out, size - 1, SEEK_SET); putc(0, out); rewind(out); /* map file */ finalDB->exist = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(out), 0); if(finalDB->exist == MAP_FAILED) { ERROR(); } posix_madvise(finalDB->exist, size, POSIX_MADV_SEQUENTIAL); *finalDB->exist++ = finalDB->DB_size; *finalDB->exist++ = finalDB->kmersize; *finalDB->exist++ = finalDB->prefix_len; finalDB->exist_l = (long unsigned *) finalDB->exist; *finalDB->exist_l++ = finalDB->prefix; *finalDB->exist_l++ = finalDB->size; *finalDB->exist_l++ = finalDB->n; *finalDB->exist_l++ = finalDB->v_index; *finalDB->exist_l++ = finalDB->null_index; finalDB->exist = (unsigned *) finalDB->exist_l; } static void rmemcpy(unsigned char *dst, unsigned char *src, size_t n) { dst += n; src += n; ++n; while(--n) { *--dst = *--src; } } HashMapKMA * compressKMA_DB(HashMap *templates, FILE *out) { unsigned char *data; long unsigned i, j, check, size, v_size; long unsigned index, t_index, v_index, new_index, null_index; unsigned swap, *values, *finalV; short unsigned *values_s, *finalV_s; HashMapKMA *finalDB; ValuesHash *shmValues; ValuesTable *node, *next, *table; HashTable *node_t, *next_t, *table_t; /* convert templates to linked list */ table_t = 0; i = templates->size + 1; while(i--) { for(node_t = templates->table[i]; node_t != 0; node_t = next_t) { next_t = node_t->next; node_t->next = table_t; table_t = node_t; } } free(templates->table); templates->table = 0; /* prepare final DB */ swap = 0; v_size = 0; size = 3 * sizeof(unsigned) + 5 * sizeof(long unsigned); check = 0; check = ~check; check >>= 32; fprintf(stderr, "# Preparing compressed DB.\n"); finalDB = smalloc(sizeof(HashMapKMA)); /* Fill in known values */ finalDB->size = templates->size + 1; finalDB->n = templates->n; finalDB->mask = templates->mask; finalDB->prefix_len = templates->prefix_len; finalDB->prefix = templates->prefix; finalDB->kmersize = templates->kmersize; finalDB->DB_size = templates->DB_size; /* allocate existence */ if(finalDB->n <= check) { finalDB->exist = malloc(finalDB->size * sizeof(unsigned)); finalDB->exist_l = 0; size += finalDB->size * sizeof(unsigned); hashMapKMA_addExist_ptr = &hashMapKMA_addExist; } else { finalDB->exist = 0; finalDB->exist_l = malloc(finalDB->size * sizeof(long unsigned)); size += finalDB->size * sizeof(long unsigned); hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; } if(finalDB->kmersize <= 16) { finalDB->key_index = malloc((finalDB->n + 1) * sizeof(unsigned)); finalDB->key_index_l = 0; size += (finalDB->n + 1) * sizeof(unsigned); hashMapKMA_addKey_ptr = &hashMapKMA_addKey; } else { finalDB->key_index = 0; finalDB->key_index_l = malloc((finalDB->n + 1) * sizeof(long unsigned)); size += (finalDB->n + 1) * sizeof(long unsigned); hashMapKMA_addKey_ptr = &hashMapKMA_addKeyL; } finalDB->value_index = malloc(finalDB->n * sizeof(unsigned)); size += finalDB->n * sizeof(unsigned); if((!finalDB->exist && !finalDB->exist_l) || (!finalDB->key_index && !finalDB->key_index_l) || !finalDB->value_index) { free(finalDB->exist); free(finalDB->exist_l); free(finalDB->key_index); free(finalDB->key_index_l); free(finalDB->value_index); /* fail over to swap */ fprintf(stderr, "# Fail over to swap.\n"); swap = 1; /* map file */ mmapinit(finalDB, size, out); if(finalDB->n <= UINT_MAX) { finalDB->exist_l = 0; finalDB->key_index = (finalDB->exist + finalDB->size); } else { finalDB->exist = 0; finalDB->key_index = (unsigned *) (finalDB->exist_l + finalDB->size); } if(16 < finalDB->kmersize) { finalDB->key_index_l = (long unsigned *) finalDB->key_index; finalDB->key_index = 0; finalDB->value_index = (unsigned *) (finalDB->key_index_l + (finalDB->n + 1)); } else { finalDB->value_index = finalDB->key_index + (finalDB->n + 1); } } null_index = finalDB->n; finalDB->null_index = null_index; /* fill with null_indexes */ i = finalDB->size; while(i--) { hashMapKMA_addExist_ptr(finalDB, i, null_index); } /* get relative indexes */ fprintf(stderr, "# Calculating relative indexes.\n"); hashMapKMA_addValue_ptr = &hashMapKMA_addValue; node_t = table_t; --finalDB->size; shmValues = initialize_hashValues(null_index, finalDB->DB_size); t_index = 0; v_index = 0; while(node_t != 0) { /* get index */ index = (node_t->key & finalDB->size); hashMapKMA_addExist_ptr(finalDB, index, t_index); /* mv chain */ while(node_t != 0 && (node_t->key & finalDB->size) == index) { next_t = node_t->next; /* add kmer */ hashMapKMA_addKey_ptr(finalDB, t_index, node_t->key); /* the actual value index */ new_index = valuesHash_add(shmValues, node_t->value, v_index); if(new_index == v_index) { v_index += valuesSize(node_t->value); if(check <= v_index) { fprintf(stderr, "# Compression overflow.\n"); check = 0; check = ~check; hashMapKMA_addValue_ptr = &hashMapKMA_addValueL; getValueIndexPtr = &getValueIndexL; ++finalDB->size; if(swap) { /* sync and unmap */ if(finalDB->exist) { finalDB->exist_l = (long unsigned *) finalDB->exist; } finalDB->exist_l -= 5; finalDB->exist = (unsigned *) finalDB->exist_l; finalDB->exist -= 3; msync(finalDB->exist, size, MS_ASYNC); munmap(finalDB->exist, size); /* prep new size */ size += finalDB->n * (sizeof(long unsigned) - sizeof(unsigned)); fseek(out, size, SEEK_SET); fputc(0, out); rewind(out); /* map file */ finalDB->exist = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(out), 0); if(finalDB->exist == MAP_FAILED) { ERROR(); } posix_madvise(finalDB->exist, size, POSIX_MADV_SEQUENTIAL); finalDB->exist_l = (long unsigned *) (finalDB->exist + 3); finalDB->exist_l += 5; /* set pointers */ if(finalDB->n <= check) { finalDB->exist_l = 0; finalDB->key_index = (finalDB->exist + finalDB->size); } else { finalDB->exist = 0; finalDB->key_index = (unsigned *) (finalDB->exist_l + finalDB->size); } finalDB->value_index = finalDB->key_index + (finalDB->n + 1); finalDB->value_index_l = (long unsigned *) finalDB->value_index; if(16 < finalDB->kmersize) { finalDB->key_index_l = (long unsigned *) finalDB->key_index; finalDB->key_index = 0; } } else { finalDB->value_index_l = realloc(finalDB->value_index, finalDB->n * sizeof(long unsigned)); if(!finalDB->value_index_l) { fprintf(stderr, "# Fail over to swap.\n"); /* map file */ size += finalDB->n * (sizeof(long unsigned) - sizeof(unsigned)); values = finalDB->exist ? finalDB->exist : (unsigned *) finalDB->exist_l; mmapinit(finalDB, size, out); if(finalDB->n <= check) { memcpy(finalDB->exist, values, finalDB->size * sizeof(unsigned)); free(values); values = finalDB->key_index; finalDB->exist_l = 0; finalDB->key_index = (finalDB->exist + finalDB->size); } else { memcpy(finalDB->exist_l, values, finalDB->size * sizeof(long unsigned)); free(values); values = finalDB->key_index; finalDB->exist = 0; finalDB->key_index = (unsigned *) (finalDB->exist_l + finalDB->size); } if(16 < finalDB->kmersize) { finalDB->key_index_l = (long unsigned *) finalDB->key_index; finalDB->key_index = 0; memcpy(finalDB->key_index_l, values, (finalDB->n + 1) * sizeof(long unsigned)); finalDB->value_index_l = finalDB->key_index_l + (finalDB->n + 1); } else { memcpy(finalDB->key_index, values, (finalDB->n + 1) * sizeof(unsigned)); finalDB->value_index_l = (long unsigned *) (finalDB->key_index + (finalDB->n + 1)); } free(values); swap = 2; } } --finalDB->size; finalDB->value_index = (unsigned *)(finalDB->value_index_l); j = finalDB->n; while(j--) { finalDB->value_index_l[j] = finalDB->value_index[j]; } if(swap == 2) { free(finalDB->value_index); swap = 1; } finalDB->value_index = 0; } } else { /* values were duplicated, clean up */ free(node_t->value); } hashMapKMA_addValue_ptr(finalDB, t_index, new_index); ++t_index; /* clean */ free(node_t); node_t = next_t; } } /* convert valuesHash to a linked list */ table = 0; i = shmValues->size; while(i--) { for(node = shmValues->table[i]; node != 0; node = next) { next = node->next; node->next = table; table = node; } } free(shmValues->table); /* make compressed values */ fprintf(stderr, "# Finalizing indexes.\n"); finalDB->v_index = v_index; if(!swap) { if(finalDB->DB_size < USHRT_MAX) { finalDB->values = 0; finalDB->values_s = calloc(v_index, sizeof(short unsigned)); size += v_index * sizeof(short unsigned); if(!finalDB->values_s) { swap = 1; } } else { finalDB->values = calloc(v_index, sizeof(unsigned)); finalDB->values_s = 0; size += v_index * sizeof(unsigned); if(!finalDB->values) { swap = 1; } } /* dump part of DB */ if(swap) { ++finalDB->size; fprintf(stderr, "# Fail over to swap.\n"); if(finalDB->exist) { values = finalDB->exist; } else { values = (unsigned *) finalDB->exist_l; } /* map file */ mmapinit(finalDB, size, out); /* dump arrays */ if(finalDB->n <= UINT_MAX) { memcpy(finalDB->exist, values, finalDB->size * sizeof(unsigned)); data = (unsigned char *)(finalDB->exist + finalDB->size); getExistPtr = &getExist; hashMapKMA_addExist_ptr = &hashMapKMA_addExist; } else { memcpy(finalDB->exist_l, values, finalDB->size * sizeof(long unsigned)); data = (unsigned char *)(finalDB->exist_l + finalDB->size); getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; } free(values); /* skip values */ if(finalDB->DB_size < USHRT_MAX) { data += finalDB->v_index * sizeof(short unsigned); getValuePtr = &getValueS; getSizePtr = &getSizeS; } else { data += finalDB->v_index * sizeof(unsigned); getValuePtr = &getValue; getSizePtr = &getSize; } if(finalDB->kmersize <= 16) { memcpy(data, finalDB->key_index, (finalDB->n + 1) * sizeof(unsigned)); data += (finalDB->n + 1) * sizeof(unsigned); free(finalDB->key_index); getKeyPtr = &getKey; } else { memcpy(data, finalDB->key_index_l, (finalDB->n + 1) * sizeof(long unsigned)); data += (finalDB->n + 1) * sizeof(long unsigned); free(finalDB->key_index_l); getKeyPtr = &getKeyL; } if(finalDB->v_index < UINT_MAX) { memcpy(data, finalDB->value_index, finalDB->n * sizeof(unsigned)); free(finalDB->value_index); hashMapKMA_addValue_ptr = &hashMapKMA_addValue; getValueIndexPtr = &getValueIndex; } else { memcpy(data, finalDB->value_index_l, finalDB->n * sizeof(long unsigned)); free(finalDB->value_index_l); hashMapKMA_addValue_ptr = &hashMapKMA_addValueL; getValueIndexPtr = &getValueIndexL; } --finalDB->size; } } else { /* sync and unmap */ if(finalDB->exist) { finalDB->exist_l = (long unsigned *) finalDB->exist; } finalDB->exist_l -= 5; finalDB->exist = (unsigned *) finalDB->exist_l; finalDB->exist -= 3; msync(finalDB->exist, size, MS_ASYNC); munmap(finalDB->exist, size); /* make new mapping */ if(finalDB->DB_size < USHRT_MAX) { size += v_index * sizeof(short unsigned); } else { size += v_index * sizeof(unsigned); } ++finalDB->size; mmapinit(finalDB, size, out); --finalDB->size; swap = 2; } /* set pointers */ if(swap) { ++finalDB->size; if(finalDB->n <= UINT_MAX) { finalDB->values = finalDB->exist + finalDB->size; } else { finalDB->values = (unsigned *) (finalDB->exist_l + finalDB->size); } if(finalDB->DB_size < USHRT_MAX) { finalDB->values_s = (short unsigned *) finalDB->values; finalDB->key_index = (unsigned *) (finalDB->values_s + finalDB->v_index); } else { finalDB->key_index = finalDB->values + finalDB->v_index; } if(finalDB->kmersize <= 16) { finalDB->value_index = finalDB->key_index + (finalDB->n + 1); } else { finalDB->key_index_l = (long unsigned *) finalDB->key_index; finalDB->value_index = (unsigned *) (finalDB->key_index_l + (finalDB->n + 1)); } if(UINT_MAX <= finalDB->v_index) { finalDB->value_index_l = (long unsigned *) finalDB->value_index; } --finalDB->size; } /* move pieces to correct location, rmemcpy */ if(swap == 2) { /* value_index */ if(finalDB->kmersize <= 16) { values = finalDB->values + (finalDB->n + 1); } else { values = (unsigned *) (((long unsigned *) finalDB->values) + (finalDB->n + 1)); } v_size = finalDB->n * (UINT_MAX <= finalDB->v_index ? sizeof(long unsigned) : sizeof(unsigned)); rmemcpy((unsigned char *) finalDB->value_index, (unsigned char *) values, v_size); /* key_index */ v_size = (finalDB->n + 1) * (finalDB->kmersize <= 16 ? sizeof(unsigned) : sizeof(long unsigned)); rmemcpy((unsigned char *) finalDB->key_index, (unsigned char *) finalDB->values, v_size); swap = 1; } /* move values */ if(finalDB->DB_size < USHRT_MAX) { for(node = table; node != 0; node = next) { next = node->next; values_s = (short unsigned *)(node->values); finalV_s = finalDB->values_s + node->v_index - 1; i = 2 + *values_s--; while(--i) { *++finalV_s = *++values_s; } free(node->values); free(node); /* next = node->next; values_s = (short unsigned *)(node->values); for(i = node->v_index, j = 0; j <= *values_s; ++i, ++j) { finalDB->values_s[i] = values_s[j]; } free(values_s); free(node); */ } } else { for(node = table; node != 0; node = next) { next = node->next; values = node->values; finalV = finalDB->values + node->v_index - 1; i = 2 + *values--; while(--i) { *++finalV = *++values; } free(node->values); free(node); /* next = node->next; values = node->values; for(i = node->v_index, j = 0; j <= *values; ++i, ++j) { finalDB->values[i] = values[j]; } free(values); free(node); */ } } /* add terminating key */ i = 0; if(finalDB->kmersize <= 16) { j = finalDB->key_index[finalDB->n - 1] & finalDB->size; while(j == (finalDB->key_index[i] & finalDB->size)) { ++i; } finalDB->key_index[finalDB->n] = finalDB->key_index[i]; } else { j = finalDB->key_index_l[finalDB->n - 1] & finalDB->size; while(j == (finalDB->key_index_l[i] & finalDB->size)) { ++i; } finalDB->key_index_l[finalDB->n] = finalDB->key_index_l[i]; } /* dump final DB */ fprintf(stderr, "# Dumping compressed DB\n"); ++finalDB->size; if(swap) { /* save prev mapping */ if(finalDB->exist) { finalDB->exist_l = (long unsigned *) finalDB->exist; } *--finalDB->exist_l = finalDB->null_index; *--finalDB->exist_l = finalDB->v_index; *--finalDB->exist_l = finalDB->n; *--finalDB->exist_l = finalDB->size; *--finalDB->exist_l = finalDB->prefix; finalDB->exist = (unsigned *) finalDB->exist_l; *--finalDB->exist = finalDB->prefix_len; *--finalDB->exist = finalDB->kmersize; *--finalDB->exist = finalDB->DB_size; msync(finalDB->exist, size, MS_ASYNC); munmap(finalDB->exist, size); free(finalDB); finalDB = 0; } else { hashMapKMA_dump(finalDB, out); } return finalDB; } HashMapKMA * compressKMA_megaDB(HashMap *templates, FILE *out) { long unsigned i, j, v_index, new_index, null_index, size, v_size; unsigned check, swap, *values, *finalV; short unsigned *values_s, *finalV_s; HashMapKMA *finalDB; ValuesHash *shmValues; ValuesTable *node, *next, *table; /* Fill in known values */ hashMapKMA_addExist_ptr = &hashMapKMA_addExist; swap = 0; size = 0; v_size = 0; check = 0; check = ~check; finalDB = smalloc(sizeof(HashMapKMA)); finalDB->size = templates->size + 1; finalDB->n = templates->n; finalDB->mask = templates->mask; finalDB->prefix_len = templates->prefix_len; finalDB->prefix = templates->prefix; finalDB->kmersize = templates->kmersize; finalDB->DB_size = templates->DB_size; /* allocate existence */ finalDB->exist = malloc(finalDB->size * sizeof(unsigned)); if(!finalDB->exist) { /* fail over to swap */ fprintf(stderr, "# Fail over to swap.\n"); swap = 1; /* map file */ size = 3 * sizeof(unsigned) + 5 * sizeof(long unsigned) + finalDB->size * sizeof(unsigned); mmapinit(finalDB, size, out); } finalDB->exist_l = 0; finalDB->key_index = 0; finalDB->value_index = 0; /* get relative indexes */ fprintf(stderr, "# Calculating relative indexes.\n"); null_index = finalDB->n; v_index = 0; while(templates->values[v_index] != 0) { finalDB->exist[v_index] = v_index; ++v_index; } for(i = v_index; i != finalDB->size; ++i) { if(templates->values[i]) { finalDB->exist[i] = v_index; templates->values[v_index] = templates->values[i]; templates->values[i] = 0; ++v_index; } else { finalDB->exist[i] = null_index; } } /* decrease size of values to what is actually used */ templates->values = realloc(templates->values, templates->n * sizeof(unsigned *)); if(!templates->values) { ERROR(); } /* get compressed indexes */ fprintf(stderr, "# Compressing indexes.\n"); v_index = 0; shmValues = initialize_hashValues(null_index, finalDB->DB_size); i = finalDB->size; j = 0; while(i--) { if(finalDB->exist[i] != null_index) { values = templates->values[finalDB->exist[i]]; /* the actual index */ new_index = valuesHash_add(shmValues, values, v_index); if(new_index == v_index) { v_index += valuesSize(values); if(check < v_index) { fprintf(stderr, "# Compression overflow.\n"); j = 1; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; break; } } else { /* values were duplicated, clean up */ free(values); templates->values[finalDB->exist[i]] = 0; } /* update to new index */ finalDB->exist[i] = new_index; } else { finalDB->exist[i] = 1; } } if(j) { fprintf(stderr, "# Bypassing overflow.\n"); if(swap & 1) { /* save prev mapping */ finalDB->exist_l = (long unsigned *) finalDB->exist; finalDB->exist_l -= 5; finalDB->exist = (unsigned *) finalDB->exist_l; finalDB->exist -= 3; msync(finalDB->exist, size, MS_ASYNC); munmap(finalDB->exist, size); /* allocate file */ size = 3 * sizeof(unsigned) + 5 * sizeof(long unsigned) + finalDB->size * sizeof(long unsigned); fseek(out, size, SEEK_SET); fputc(0, out); rewind(out); /* map file */ finalDB->exist = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(out), 0); if(finalDB->exist == MAP_FAILED) { ERROR(); } posix_madvise(finalDB->exist, size, POSIX_MADV_SEQUENTIAL); finalDB->exist_l = (long unsigned *) (finalDB->exist + 3); finalDB->exist_l += 5; } else { finalDB->exist_l = realloc(finalDB->exist, finalDB->size * sizeof(long unsigned)); if(!finalDB->exist_l) { /* swap */ fprintf(stderr, "Fail over to swap.\n"); swap |= 1; /* map file */ size = 3 * sizeof(unsigned) + 5 * sizeof(long unsigned) + finalDB->size * sizeof(long unsigned); values = finalDB->exist; mmapinit(finalDB, size, out); memcpy(finalDB->exist_l, values, finalDB->size * sizeof(unsigned)); free(finalDB->exist); } } finalDB->exist = (unsigned *)(finalDB->exist_l); j = finalDB->size; while(j--) { finalDB->exist_l[j] = finalDB->exist[j]; } finalDB->exist = 0; finalDB->exist_l[i] = new_index; while(i--) { if(finalDB->exist_l[i] != null_index) { values = templates->values[finalDB->exist_l[i]]; /* the actual index */ new_index = valuesHash_add(shmValues, values, v_index); if(new_index == v_index) { v_index += valuesSize(values); } else { /* values were duplicated, clean up */ free(values); templates->values[finalDB->exist_l[i]] = 0; } /* update to new index */ finalDB->exist_l[i] = new_index; } else { finalDB->exist_l[i] = 1; } } fprintf(stderr, "# Overflow bypassed.\n"); } free(templates->values); /* convert valuesHash to a linked list */ table = 0; i = shmValues->size; while(i--) { for(node = shmValues->table[i]; node != 0; node = next) { next = node->next; node->next = table; table = node; } } free(shmValues->table); /* make compressed values */ fprintf(stderr, "# Finalizing indexes.\n"); finalDB->v_index = v_index; finalDB->null_index = 1; /* try to allocate first, else gradually fail over over to swap */ finalDB->values = 0; finalDB->values_s = 0; while(finalDB->values == 0 && finalDB->values_s == 0 && (swap & 4) == 0) { if(finalDB->DB_size < USHRT_MAX) { finalDB->values = 0; finalDB->values_s = calloc(v_index, sizeof(short unsigned)); if(!finalDB->values_s) { swap += 2; } } else { finalDB->values = calloc(v_index, sizeof(unsigned)); finalDB->values_s = 0; if(!finalDB->values) { swap += 2; } } if(swap & 2) { /* free exist */ size = 3 * sizeof(unsigned) + 5 * sizeof(long unsigned); if(swap & 1) { /* save prev mapping */ finalDB->exist_l = (long unsigned *) finalDB->exist; *--finalDB->exist_l = finalDB->null_index; *--finalDB->exist_l = finalDB->v_index; *--finalDB->exist_l = finalDB->n; *--finalDB->exist_l = finalDB->size; *--finalDB->exist_l = finalDB->prefix; finalDB->exist = (unsigned *) finalDB->exist_l; *--finalDB->exist = finalDB->prefix_len; *--finalDB->exist = finalDB->kmersize; *--finalDB->exist = finalDB->DB_size; msync(finalDB->exist, size, MS_ASYNC); munmap(finalDB->exist, size); if(finalDB->v_index <= UINT_MAX) { munmap(finalDB->exist, finalDB->size * sizeof(unsigned)); } else { munmap(finalDB->exist_l, finalDB->size * sizeof(long unsigned)); } } else { /* dump piece of DB */ cfwrite(&finalDB->DB_size, sizeof(unsigned), 1, out); cfwrite(&finalDB->kmersize, sizeof(unsigned), 1, out); cfwrite(&finalDB->prefix_len, sizeof(unsigned), 1, out); cfwrite(&finalDB->prefix, sizeof(long unsigned), 1, out); cfwrite(&finalDB->size, sizeof(long unsigned), 1, out); cfwrite(&finalDB->n, sizeof(long unsigned), 1, out); cfwrite(&finalDB->v_index, sizeof(long unsigned), 1, out); cfwrite(&finalDB->null_index, sizeof(long unsigned), 1, out); if(finalDB->v_index <= UINT_MAX) { cfwrite(finalDB->exist, sizeof(unsigned), finalDB->size, out); size += finalDB->size * sizeof(unsigned); } else { cfwrite(finalDB->exist_l, sizeof(long unsigned), finalDB->size, out); size += finalDB->size * sizeof(long unsigned); } free(finalDB->exist); } finalDB->exist = 0; /* set poiters */ if(finalDB->v_index <= UINT_MAX) { getExistPtr = &getExist; hashMapKMA_addExist_ptr = &hashMapKMA_addExist; size += finalDB->size * sizeof(unsigned); } else { getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; size += finalDB->size * sizeof(long unsigned); } } } /* both allocations failed */ if(swap & 4) { fprintf(stderr, "Fail over to swap.\n"); v_size = size; if(finalDB->DB_size < USHRT_MAX) { size += v_index * sizeof(short unsigned); } else { size += v_index * sizeof(unsigned); } fseek(out, size, SEEK_SET); fputc(0, out); rewind(out); finalDB->values = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(out), 0); if(finalDB->values == MAP_FAILED) { ERROR(); } posix_madvise(finalDB->values, size, POSIX_MADV_SEQUENTIAL); finalDB->values = (unsigned *)(((unsigned char *) finalDB->values) + v_size); if(finalDB->DB_size < USHRT_MAX) { finalDB->values_s = (short unsigned *) finalDB->values; } } /* move values */ if(finalDB->DB_size < USHRT_MAX) { for(node = table; node != 0; node = next) { next = node->next; values_s = (short unsigned *)(node->values); finalV_s = finalDB->values_s + node->v_index - 1; i = 2 + *values_s--; while(--i) { *++finalV_s = *++values_s; } free(node->values); free(node); /* next = node->next; values_s = (short unsigned *)(node->values); for(i = node->v_index, j = 0; j <= *values_s; ++i, ++j) { finalDB->values_s[i] = values_s[j]; } free(values_s); free(node); */ } } else { for(node = table; node != 0; node = next) { next = node->next; values = node->values; finalV = finalDB->values + node->v_index - 1; i = 2 + *values--; while(--i) { *++finalV = *++values; } free(node->values); free(node); /* next = node->next; values = node->values; for(i = node->v_index, j = 0; j <= *values; ++i, ++j) { finalDB->values[i] = values[j]; } free(values); free(node); */ } } /* dump final DB */ fprintf(stderr, "# Dumping compressed DB\n"); if(swap < 2) { megaMapKMA_dump(finalDB, out); } else { /* dump values */ if(swap & 4) { finalDB->values = (unsigned *)(((unsigned char *) finalDB->values) - v_size); finalDB->exist_l = (long unsigned *)(finalDB->values + 3); finalDB->exist_l[3] = finalDB->v_index; msync(finalDB->values, size, MS_ASYNC); munmap(finalDB->values, size); } /* set pointers */ if(finalDB->DB_size < USHRT_MAX) { getValuePtr = &getValueS; getSizePtr = &getSizeS; } else { getValuePtr = &getValue; getSizePtr = &getSize; } if(swap & 2) { free(finalDB->values); } free(finalDB); finalDB = 0; } return finalDB; } void compressKMA_deconDB(HashMapKMA *finalDB, unsigned **Values) { long unsigned i, j, v_index, new_index, check; unsigned *values; short unsigned *values_s; ValuesHash *shmValues; ValuesTable *node, *next, *table; /* prepare final DB */ check = 0; check = ~check; if(finalDB->v_index < UINT_MAX) { check >>= 32; hashMapKMA_addValue_ptr = &hashMapKMA_addValue; getValueIndexPtr = &getValueIndex; } else { hashMapKMA_addValue_ptr = &hashMapKMA_addValueL; getValueIndexPtr = &getValueIndexL; } i = finalDB->n; shmValues = initialize_hashValues(finalDB->n, finalDB->DB_size); v_index = 0; while(i--) { /* the actual value index */ values = Values[i]; new_index = valuesHash_add(shmValues, values, v_index); if(new_index == v_index) { v_index += valuesSize(values); if(check <= v_index) { fprintf(stderr, "# Compression overflow.\n"); check = 0; check = ~check; hashMapKMA_addValue_ptr = &hashMapKMA_addValueL; getValueIndexPtr = &getValueIndexL; finalDB->value_index_l = realloc(finalDB->value_index, finalDB->n * sizeof(long unsigned)); if(!finalDB->value_index_l) { ERROR(); } finalDB->value_index = (unsigned *)(finalDB->value_index_l); j = finalDB->n; while(j--) { finalDB->value_index_l[j] = finalDB->value_index[j]; } finalDB->value_index = 0; } } else { free(values); } hashMapKMA_addValue_ptr(finalDB, i, new_index); } free(Values); /* convert valuesHash to a linked list */ table = 0; i = shmValues->size; while(i--) { for(node = shmValues->table[i]; node != 0; node = next) { next = node->next; node->next = table; table = node; } } free(shmValues->table); /* make compressed values */ fprintf(stderr, "# Finalizing indexes.\n"); finalDB->v_index = v_index; if(finalDB->DB_size < USHRT_MAX) { finalDB->values = 0; finalDB->values_s = calloc(v_index, sizeof(short unsigned)); if(!finalDB->values_s) { ERROR(); } /* move values */ for(node = table; node != 0; node = next) { next = node->next; values_s = (short unsigned *)(node->values); for(i = node->v_index, j = 0; j <= *values_s; ++i, ++j) { finalDB->values_s[i] = values_s[j]; } free(values_s); free(node); } } else { finalDB->values = calloc(v_index, sizeof(unsigned)); finalDB->values_s = 0; if(!finalDB->values) { ERROR(); } /* move values */ for(node = table; node != 0; node = next) { next = node->next; values = node->values; for(i = node->v_index, j = 0; j <= *values; ++i, ++j) { finalDB->values[i] = values[j]; } free(values); free(node); } } } void compressKMA_deconMegaDB(HashMapKMA *finalDB, unsigned **Values) { long unsigned i, j, v_index, new_index, pos, check; unsigned *values; short unsigned *values_s; ValuesHash *shmValues; ValuesTable *node, *next, *table; fprintf(stderr, "# Compressing indexes.\n"); check = 0; check = ~check; if(finalDB->v_index < UINT_MAX) { check >>= 32; getExistPtr = &getExist; hashMapKMA_addExist_ptr = &hashMapKMA_addExist; } else { getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; } i = finalDB->size; shmValues = initialize_hashValues(finalDB->n, finalDB->DB_size); v_index = 0; while(i--) { if((pos = getExistPtr(finalDB->exist, i)) != finalDB->n) { values = Values[pos]; new_index = valuesHash_add(shmValues, values, v_index); if(new_index == v_index) { v_index += valuesSize(values); if(check <= v_index) { fprintf(stderr, "# Compression overflow.\n"); check = 0; check = ~check; getExistPtr = &getExistL; hashMapKMA_addExist_ptr = &hashMapKMA_addExistL; finalDB->exist_l = realloc(finalDB->exist, finalDB->size * sizeof(long unsigned)); if(!finalDB->value_index_l) { ERROR(); } finalDB->exist = (unsigned *)(finalDB->exist_l); j = finalDB->size; while(j--) { finalDB->exist_l[j] = finalDB->exist[j]; } finalDB->exist = 0; } } else { free(values); } hashMapKMA_addExist_ptr(finalDB, i, new_index); } else { hashMapKMA_addExist_ptr(finalDB, i, 1); } } free(Values); /* convert valuesHash to a linked list */ table = 0; i = shmValues->size; while(i--) { for(node = shmValues->table[i]; node != 0; node = next) { next = node->next; node->next = table; table = node; } } free(shmValues->table); /* make compressed values */ fprintf(stderr, "# Finalizing indexes.\n"); finalDB->v_index = v_index; finalDB->null_index = 1; if(finalDB->DB_size < USHRT_MAX) { finalDB->values = 0; finalDB->values_s = calloc(v_index, sizeof(short unsigned)); if(!finalDB->values_s) { ERROR(); } /* move values */ for(node = table; node != 0; node = next) { next = node->next; values_s = (short unsigned *)(node->values); for(i = node->v_index, j = 0; j <= *values_s; ++i, ++j) { finalDB->values_s[i] = values_s[j]; } free(values_s); free(node); } } else { finalDB->values = calloc(v_index, sizeof(unsigned)); finalDB->values_s = 0; if(!finalDB->values) { ERROR(); } /* move values */ for(node = table; node != 0; node = next) { next = node->next; values = node->values; for(i = node->v_index, j = 0; j <= *values; ++i, ++j) { finalDB->values[i] = values[j]; } free(values); free(node); } } } genomicepidemiology-kma-091b8ffe66ac/tmp.c0000644000175000017500000000446614157033525020067 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "pherror.h" #include "threader.h" #include "tmp.h" FILE * tmpF(const char *location) { static int tmpNum = 0; static char *tmpname = 0, *dirname = 0, *filename = 0; static volatile int Lock = 0; volatile int *lock = &Lock; int fd; FILE *file; lock(lock); if(location) { /* set location for tmpfiles */ if(filename) { free(filename); filename = 0; } else if(dirname) { free(dirname); dirname = 0; } if(*location) { if(location[strlen(location) - 1] != '/') { filename = smalloc(strlen(location) + 15); tmpname = filename + sprintf(filename, "%s.tmp", location); dirname = 0; } else { dirname = smalloc(strlen(location) + 12); tmpname = dirname + sprintf(dirname, "%s.kma-", location); strcpy(tmpname, "XXXXXX"); filename = 0; } } file = 0; } else if(dirname) { if((fd = mkstemp(dirname)) == -1) { ERROR(); } if((file = fdopen(fd, "wb+"))) { unlink(dirname); } strcpy(tmpname, "XXXXXX"); } else if(filename) { /* open tmpfile on previous location */ fd = sprintf(tmpname, "%d", tmpNum++); if((file = fopen(filename, "wb+"))) { unlink(filename); } *tmpname = 0; } else if(!tmpNum) { /* set default according to TMPDIR */ if((tmpname = getenv("TMPDIR"))) { dirname = smalloc(strlen(tmpname) + 13); tmpname = dirname + sprintf(dirname, "%s/.kma-", tmpname); strcpy(tmpname, "XXXXXX"); } tmpNum = 1; unlock(lock); return tmpF(0); } else { /* open a "normal" tmp file */ file = tmpfile(); } unlock(lock); return file; } genomicepidemiology-kma-091b8ffe66ac/kmmap.c0000644000175000017500000001122114157033525020357 0ustar nileshnilesh/* Philip T.L.C. Clausen May 2019 plan@dtu.dk */ /* * Copyright (c) 2019, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "hashmapkma.h" #include "pherror.h" #ifdef _WIN32 #define mmap(addr, len, prot, flags, fd, offset) (0; fprintf(stderr, "mmap not available on windows.\n"); exit(1);); #define munmap(addr, len) (-1); #else #include #endif int hashMapKMAmmap(HashMapKMA *dest, FILE *file) { int fd; unsigned *uptr; long unsigned size, *luptr; unsigned char *data; /* mmap data */ fd = fileno(file); fseek(file, 0, SEEK_END); size = ftell(file); data = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); if(data == MAP_FAILED) { ERROR(); } /* get data */ uptr = (unsigned *) data; dest->DB_size = *uptr++; dest->kmersize = *uptr++; dest->prefix_len = *uptr++; luptr = (long unsigned *) uptr; dest->prefix = *luptr++; dest->size = *luptr++; dest->n = *luptr++; dest->v_index = *luptr++; dest->null_index = *luptr++; data = (unsigned char *) luptr; dest->mask = 0; dest->mask = (~dest->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (dest->kmersize << 1)); dest->shmFlag = 16; /* exist */ size = dest->size; if((dest->size - 1) == dest->mask) { if(dest->v_index <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; } } else { if(dest->n <= UINT_MAX) { size *= sizeof(unsigned); getExistPtr = &getExist; } else { size *= sizeof(long unsigned); getExistPtr = &getExistL; } } dest->exist = (unsigned *) data; dest->exist_l = (long unsigned *) data; data += size; /* values */ size = dest->v_index; if(dest->DB_size < USHRT_MAX) { size *= sizeof(short unsigned); getValuePtr = &getValueS; intpos_bin_contaminationPtr = &intpos_bin_contamination_s; } else { size *= sizeof(unsigned); getValuePtr = &getValue; intpos_bin_contaminationPtr = &intpos_bin_contamination; } dest->values = (unsigned *) data; dest->values_s = (short unsigned *) data; dest->shmFlag |= 2; data += size; /* check for megaMap */ if((dest->size - 1) == dest->mask) { dest->key_index = 0; dest->key_index_l = 0; dest->value_index = 0; dest->value_index_l = 0; hashMap_get = &megaMap_getGlobal; return 0; } else { hashMap_get = &hashMap_getGlobal; } /* kmers */ size = dest->n + 1; if(dest->kmersize <= 16) { size *= sizeof(unsigned); getKeyPtr = &getKey; } else { size *= sizeof(long unsigned); getKeyPtr = &getKeyL; } dest->key_index = (unsigned *) data; dest->key_index_l = (long unsigned *) data; dest->shmFlag |= 4; data += size; /* value indexes */ size = dest->n; if(dest->v_index < UINT_MAX) { size *= sizeof(unsigned); getValueIndexPtr = &getValueIndex; } else { size *= sizeof(long unsigned); getValueIndexPtr = &getValueIndexL; } dest->value_index = (unsigned *) data; dest->value_index_l = (long unsigned *) data; dest->shmFlag |= 8; /* make indexing a masking problem */ --dest->size; return 0; } void hashMapKMA_munmap(HashMapKMA *dest) { int unit; long unsigned size; unsigned char *data; if(dest && dest->shmFlag & 16) { data = (unsigned char *) dest->exist; size = 3 * sizeof(unsigned) + 5 * sizeof(long unsigned); data -= size; if((dest->size - 1) == dest->mask) { if(dest->v_index <= UINT_MAX) { unit = sizeof(unsigned); } else { unit = sizeof(long unsigned); } } else { if(dest->n <= UINT_MAX) { unit = sizeof(unsigned); } else { unit = sizeof(long unsigned); } } size += dest->size * unit; unit = (dest->DB_size < USHRT_MAX) ? sizeof(short unsigned) : sizeof(unsigned); size += dest->v_index * unit; if((dest->size - 1) != dest->mask) { unit = (dest->kmersize <= 16) ? sizeof(unsigned) : sizeof(long unsigned); size += (dest->n + 1) * unit; unit = (dest->v_index < UINT_MAX) ? sizeof(unsigned) : sizeof(long unsigned); size += dest->n * unit; } if(data && dest->shmFlag & 1 && munmap(data, size) < 0) { ERROR(); } free(dest); } } genomicepidemiology-kma-091b8ffe66ac/ankers.h0000644000175000017500000000370714157033525020554 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "compdna.h" #include "qseqs.h" extern int (*printPtr)(int*, CompDNA*, int, const Qseqs*, const int, FILE *out); extern int (*printPairPtr)(int*, CompDNA*, int, const Qseqs*, CompDNA*, int, const Qseqs*, const int flag, const int flag_r, FILE *out); extern int (*deConPrintPtr)(int*, CompDNA*, int, const Qseqs*, const int flag, FILE *out); int print_ankers(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out); int print_ankers_Sparse(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out); int find_contamination(int *out_Tem, const int contamination); int find_contamination2(int *out_Tem, const int contamination); int deConPrint(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out); int deConPrintPair(int *out_Tem, CompDNA *qseq, int bestScore, const Qseqs *header, CompDNA *qseq_r, int bestScore_r, const Qseqs *header_r, const int flag, const int flag_r, FILE *out); int printPair(int *out_Tem, CompDNA *qseq, int bestScore, const Qseqs *header, CompDNA *qseq_r, int bestScore_r, const Qseqs *header_r, const int flag, const int flag_r, FILE *out); int get_ankers(int *out_Tem, CompDNA *qseq, Qseqs *header, int *flag, FILE *inputfile); genomicepidemiology-kma-091b8ffe66ac/ankers.c0000644000175000017500000001303414157033525020541 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "ankers.h" #include "compdna.h" #include "pherror.h" #include "qseqs.h" int (*printPtr)(int*, CompDNA*, int, const Qseqs*, const int, FILE *out) = &print_ankers; int (*printPairPtr)(int*, CompDNA*, int, const Qseqs*, CompDNA*, int, const Qseqs*, const int flag, const int flag_r, FILE *out) = &printPair; int (*deConPrintPtr)(int*, CompDNA*, int, const Qseqs*, const int flag, FILE *out) = &print_ankers; int print_ankers(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out) { int infoSize[7]; infoSize[0] = qseq->seqlen; infoSize[1] = qseq->complen; infoSize[2] = *(qseq->N); infoSize[3] = rc_flag; infoSize[4] = *out_Tem; infoSize[5] = header->len; infoSize[6] = flag; sfwrite(infoSize, sizeof(int), 7, out); sfwrite(qseq->seq, sizeof(long unsigned), qseq->complen, out); if(*(qseq->N)) { sfwrite(qseq->N + 1, sizeof(int), *(qseq->N), out); } sfwrite(out_Tem + 1, sizeof(int), *out_Tem, out); sfwrite(header->seq, 1, header->len, out); return 0; } int print_ankers_Sparse(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out) { int infoSize[7]; infoSize[0] = qseq->seqlen; infoSize[1] = qseq->complen; infoSize[2] = *(qseq->N); infoSize[3] = rc_flag < 0 ? rc_flag : -rc_flag; infoSize[4] = *out_Tem; infoSize[5] = header->len; infoSize[6] = flag; sfwrite(infoSize, sizeof(int), 7, out); sfwrite(qseq->seq, sizeof(long unsigned), qseq->complen, out); if(*(qseq->N)) { sfwrite(qseq->N + 1, sizeof(int), *(qseq->N), out); } sfwrite(out_Tem + 1, sizeof(int), *out_Tem, out); sfwrite(header->seq, 1, header->len, out); return 0; } int find_contamination(int *out_Tem, const int contamination) { int i; i = *out_Tem + 1; out_Tem += i; while(--i) { if(*--out_Tem == contamination) { return i; } } return 0; } int find_contamination2(int *out_Tem, const int contamination) { int i; i = *out_Tem + 1; out_Tem += i; while(--i) { if(*--out_Tem == contamination) { return i; } else if(0 < *out_Tem) { return 0; } } return 0; } int deConPrint(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out) { int contPos; if((contPos = find_contamination(out_Tem, out_Tem[-3])) != 0) { out_Tem[contPos] = out_Tem[*out_Tem]; --*out_Tem; } if((contPos = find_contamination2(out_Tem, -out_Tem[-3])) != 0) { out_Tem[contPos] = out_Tem[*out_Tem]; --*out_Tem; } if(0 < *out_Tem) { return printPtr(out_Tem, qseq, rc_flag, header, flag, out); } return 1; } int deConPrintPair(int *out_Tem, CompDNA *qseq, int bestScore, const Qseqs *header, CompDNA *qseq_r, int bestScore_r, const Qseqs *header_r, const int flag, const int flag_r, FILE *out) { int contPos; if((contPos = find_contamination(out_Tem, out_Tem[-3])) != 0) { out_Tem[contPos] = out_Tem[*out_Tem]; --*out_Tem; } if((contPos = find_contamination2(out_Tem, -out_Tem[-3])) != 0) { out_Tem[contPos] = out_Tem[*out_Tem]; --*out_Tem; } if(0 < *out_Tem) { contPos = *out_Tem; *out_Tem = 0; printPtr(out_Tem, qseq, bestScore, header, flag, out); *out_Tem = contPos; return printPtr(out_Tem, qseq_r, bestScore_r, header_r, flag_r, out); } return 1; } int printPair(int *out_Tem, CompDNA *qseq, int bestScore, const Qseqs *header, CompDNA *qseq_r, int bestScore_r, const Qseqs *header_r, const int flag, const int flag_r, FILE *out) { int contPos; contPos = *out_Tem; *out_Tem = 0; printPtr(out_Tem, qseq, bestScore, header, flag, out); *out_Tem = contPos; printPtr(out_Tem, qseq_r, bestScore_r, header_r, flag_r, out); return 0; } int get_ankers(int *out_Tem, CompDNA *qseq, Qseqs *header, int *flag, FILE *inputfile) { static int infoSize[7]; if(fread(infoSize, sizeof(int), 7, inputfile) == 7) { qseq->seqlen = infoSize[0]; qseq->complen = infoSize[1]; *out_Tem = infoSize[4]; header->len = infoSize[5]; *flag = infoSize[6]; /* reallocate */ if(qseq->size <= qseq->seqlen) { free(qseq->N); free(qseq->seq); if(qseq->seqlen & 31) { qseq->size = (qseq->seqlen >> 5) + 1; qseq->size <<= 6; } else { qseq->size = qseq->seqlen << 1; } qseq->seq = calloc(qseq->size >> 5, sizeof(long unsigned)); qseq->N = malloc((qseq->size + 1) * sizeof(int)); if(!qseq->seq || !qseq->N) { ERROR(); } } qseq->N[0] = infoSize[2]; if(header->size <= header->len) { free(header->seq); header->size = header->len << 1; header->seq = malloc(header->size); if(!header->seq) { ERROR(); } } sfread(qseq->seq, sizeof(long unsigned), qseq->complen, inputfile); sfread(qseq->N + 1, sizeof(int), qseq->N[0], inputfile); sfread(out_Tem + 1, sizeof(int), *out_Tem, inputfile); sfread(header->seq, 1, header->len, inputfile); } else { *out_Tem = infoSize[0]; return 0; } /* return score */ return infoSize[3]; } genomicepidemiology-kma-091b8ffe66ac/nw.c0000644000175000017500000006202114157033525017702 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "nw.h" #include "penalties.h" #include "pherror.h" #include "stdnuc.h" AlnScore NW(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, Aln *aligned, NWmat *matrices, int template_length) { int m, n, t_len, q_len, thisScore, nuc_pos, W1, U, MM; int pos[2], *D_ptr, *D_prev, Q, Q_prev, *P_ptr, *P_prev, *tmp, **d; unsigned char *query, t_nuc, *E, *E_ptr, e; AlnScore Stat; Penalties *rewards; rewards = matrices->rewards; W1 = rewards->W1; U = rewards->U; MM = rewards->MM; d = rewards->d; q_len = q_e - q_s; t_len = t_e - t_s; aligned->start = 0; aligned->end = 0; if(t_len < 0) { t_len += template_length; } query = (unsigned char*)(queryOrg + q_s); Stat.pos = 0; if(t_len == 0 || q_len == 0) { if(t_len == q_len) { Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.score = 0; aligned->s[0] = 0; } else if(t_len == 0) { Stat.len = q_len; Stat.match = 0; Stat.tGaps = q_len; Stat.qGaps = 0; Stat.score = W1 + (q_len - 1) * U; memset(aligned->s, '_', q_len); aligned->s[q_len] = 0; memset(aligned->t, 5, q_len); memcpy(aligned->q, query, q_len); } else { Stat.len = t_len; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = t_len; Stat.score = W1 + (t_len - 1) * U; memset(aligned->s, '_', t_len); aligned->s[t_len] = 0; memset(aligned->q, 5, t_len); m = t_len; nuc_pos = (t_e ? t_e : aligned->pos) - 1; while(m--) { aligned->t[m] = getNuc(template, nuc_pos); if(--nuc_pos < 0) { nuc_pos = aligned->pos - 1; } } } return Stat; } /* check matrix size */ if(matrices->NW_q <= q_len) { matrices->NW_q = q_len << 1; free(matrices->D[0]); free(matrices->P[0]); matrices->D[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->P[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->D[1] = matrices->D[0] + matrices->NW_q; matrices->P[1] = matrices->P[0] + matrices->NW_q; } if(matrices->NW_s <= ((q_len + 1) * (t_len + 1))) { matrices->NW_s = ((q_len + 2) * (t_len + 2)); free(matrices->E); matrices->E = smalloc(matrices->NW_s); } /* fill in start penalties */ D_ptr = matrices->D[0]; D_prev = matrices->D[1]; P_ptr = matrices->P[0]; P_prev = matrices->P[1]; E = matrices->E; thisScore = (t_len + q_len) * (MM + U + W1); Stat.score = thisScore; if(0 < k) { E_ptr = E; for(m = 0; m < t_len; ++m) { E_ptr[q_len] = 0; E_ptr += (q_len + 1); } if(k == 1) { for(n = q_len - 1; n >= 0; --n) { D_prev[n] = W1 + (q_len - 1 - n) * U; P_prev[n] = thisScore; E_ptr[n] = 3; } E_ptr[q_len - 1] = 18; E_ptr[q_len] = 0; D_prev[q_len] = 0; P_prev[q_len] = 0; } else { for(n = q_len; n >= 0; --n) { D_prev[n] = 0; P_prev[n] = thisScore; E_ptr[n] = 0; } } } else { E_ptr = E; for(m = 0; m < t_len; ++m) { E_ptr[q_len] = 5; E_ptr += (q_len + 1); } E_ptr[-1] = 36; for(n = q_len - 1; n >= 0; --n) { D_prev[n] = W1 + (q_len - 1 - n) * U; P_prev[n] = thisScore; E_ptr[n] = 3; } E_ptr[q_len - 1] = 18; E_ptr[q_len] = 0; D_prev[q_len] = 0; P_prev[q_len] = 0; } E_ptr -= (q_len + 1); /* Perform NW */ pos[0] = 0; for(m = t_len - 1, nuc_pos = t_e - 1; m >= 0; --m, --nuc_pos) { if(nuc_pos < 0) { nuc_pos = template_length - 1; } D_ptr[q_len] = (0 < k) ? 0 : (W1 + (t_len - 1 - m) * U); Q_prev = (t_len + q_len) * (MM + U + W1); t_nuc = getNuc(template, nuc_pos); for(n = q_len - 1; n >= 0; --n) { E_ptr[n] = 0; /* update Q and P, gap openings */ Q = D_ptr[n + 1] + W1; P_ptr[n] = D_prev[n] + W1; if(Q < P_ptr[n]) { D_ptr[n] = P_ptr[n]; e = 4; } else { D_ptr[n] = Q; e = 2; } /* update Q and P, gap extensions */ /* mark bit 4 and 5 as possible gap-opennings, if necesarry */ thisScore = Q_prev + U; if(Q < thisScore) { Q = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 3; } } else { E_ptr[n] |= 16; } thisScore = P_prev[n] + U; if(P_ptr[n] < thisScore) { P_ptr[n] = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 5; } } else { E_ptr[n] |= 32; } /* Update D, match */ thisScore = D_prev[n + 1] + d[t_nuc][query[n]]; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; E_ptr[n] |= 1; } else { E_ptr[n] |= e; } Q_prev = Q; } E_ptr -= (q_len + 1); if(k < 0 && Stat.score < *D_ptr) { Stat.score = *D_ptr; pos[0] = m; } tmp = D_ptr; D_ptr = D_prev; D_prev = tmp; tmp = P_ptr; P_ptr = P_prev; P_prev = tmp; } E_ptr = E; /* get start position of alignment */ if(k < 0) { pos[1] = 0; if(k == -2) { for(n = 0; n < q_len; ++n) { if(Stat.score <= D_prev[n]) { Stat.score = D_prev[n]; pos[0] = 0; pos[1] = (aligned->start = n); } } } } else { Stat.score = *D_prev; pos[0] = 0; pos[1] = 0; } /* make back tracking */ m = pos[0]; n = pos[1]; E_ptr = E + (m * (q_len + 1)); nuc_pos = m + t_s; Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; while(E_ptr[n] != 0) { if(nuc_pos == template_length) { nuc_pos = 0; } if((E_ptr[n] & 7) == 1) { aligned->t[Stat.len] = getNuc(template, nuc_pos); aligned->q[Stat.len] = query[n]; aligned->s[Stat.len] = (aligned->t[Stat.len] == aligned->q[Stat.len]) ? '|' : '_'; ++Stat.match; ++nuc_pos; E_ptr += (q_len + 1); ++n; } else if((E_ptr[n] & 7) >= 4) { while(!(E_ptr[n] >> 4)) { aligned->t[Stat.len] = getNuc(template, nuc_pos); aligned->q[Stat.len] = 5; aligned->s[Stat.len] = '_'; ++nuc_pos; E_ptr += (q_len + 1); ++Stat.len; ++Stat.qGaps; } aligned->t[Stat.len] = getNuc(template, nuc_pos); aligned->q[Stat.len] = 5; aligned->s[Stat.len] = '_'; ++nuc_pos; E_ptr += (q_len + 1); ++Stat.qGaps; } else { while(!(E_ptr[n] >> 3)) { aligned->t[Stat.len] = 5; aligned->q[Stat.len] = query[n]; aligned->s[Stat.len] = '_'; ++n; ++Stat.len; ++Stat.tGaps; } aligned->t[Stat.len] = 5; aligned->q[Stat.len] = query[n]; aligned->s[Stat.len] = '_'; ++n; ++Stat.tGaps; } ++Stat.len; } aligned->s[Stat.len] = 0; aligned->end = q_len - n; return Stat; } AlnScore NW_band(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, Aln *aligned, int band, NWmat *matrices, int template_length) { int m, n, t_len, q_len, thisScore, nuc_pos, pos[2]; int bq_len, halfBand, sn, en, sq, eq, q_pos, c_pos, W1, U, MM; int *D_ptr, *D_prev, Q, Q_prev, *P_ptr, *P_prev, *tmp, **d; unsigned char *query, t_nuc, *E, *E_ptr, e; AlnScore Stat; Penalties *rewards; rewards = matrices->rewards; W1 = rewards->W1; U = rewards->U; MM = rewards->MM; d = rewards->d; q_len = q_e - q_s; t_len = t_e - t_s; aligned->start = 0; aligned->end = 0; if(t_len < 0) { t_len += template_length; } query = (unsigned char*)(queryOrg + q_s); Stat.pos = 0; if(t_len == 0 || q_len == 0) { if(t_len == q_len) { Stat.score = 0; Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; aligned->s[0] = 0; } else if(t_len == 0) { Stat.len = q_len; Stat.match = 0; Stat.tGaps = q_len; Stat.qGaps = 0; Stat.score = W1 + (q_len - 1) * U; memset(aligned->s, '_', q_len); aligned->s[q_len] = 0; memset(aligned->t, 5, q_len); memcpy(aligned->q, query, q_len); } else { Stat.len = t_len; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = t_len; Stat.score = W1 + (t_len - 1) * U; memset(aligned->s, '_', t_len); aligned->s[t_len] = 0; memset(aligned->q, 5, t_len); m = t_len; nuc_pos = (t_e ? t_e : aligned->pos) - 1; while(m--) { aligned->t[m] = getNuc(template, nuc_pos); if(--nuc_pos < 0) { nuc_pos = aligned->pos - 1; } } } return Stat; } /* ensure that band is equal */ if(band & 1) { ++band; } halfBand = band >> 1; /* check matrix size */ if(matrices->NW_q <= band) { matrices->NW_q = band << 1; free(matrices->D[0]); free(matrices->P[0]); matrices->D[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->P[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->D[1] = matrices->D[0] + matrices->NW_q; matrices->P[1] = matrices->P[0] + matrices->NW_q; } if(matrices->NW_s <= ((band + 2) * (t_len + 1))) { matrices->NW_s = ((band + 3) * (t_len + 2)); free(matrices->E); matrices->E = smalloc(matrices->NW_s); } /* fill in start penalties */ bq_len = band + 1; /* (band + 1) ~ q_len */ D_ptr = matrices->D[0]; D_prev = matrices->D[1]; P_ptr = matrices->P[0]; P_prev = matrices->P[1]; E = matrices->E; thisScore = (t_len + q_len) * (MM + U + W1); Stat.score = thisScore; E_ptr = E + (t_len * (bq_len + 1)); c_pos = (t_len + q_len) >> 1; sn = q_len - 1 - (c_pos - halfBand); if(k != 2) { for(n = sn - 1; n >= 0; --n) { D_prev[n] = W1 + (sn - n - 1) * U; P_prev[n] = thisScore; E_ptr[n] = 3; } E_ptr[sn - 1] = 18; E_ptr[sn] = 0; D_prev[sn] = 0; P_prev[sn] = 0; } else { for(n = sn; n >= 0; --n) { D_prev[n] = 0; P_prev[n] = thisScore; E_ptr[n] = 0; } } E_ptr -= (bq_len + 1); /* Perform banded NW */ pos[0] = 0; pos[1] = 0; en = 0; c_pos = (t_len + q_len) >> 1; for(m = t_len - 1, nuc_pos = t_e - 1; m >= 0; --m, --nuc_pos, --c_pos) { if(nuc_pos < 0) { nuc_pos = template_length - 1; } /* get banded boundaries, w.r.t. query */ sq = c_pos + halfBand; eq = c_pos - halfBand; if(eq < 0) { eq = 0; ++en; } else { en = 0; } /* get start penalties */ Q_prev = (t_len + q_len) * (MM + U + W1); /* check boundaries */ if(sq < (q_len - 1)) { sn = bq_len - 1; D_ptr[bq_len] = (t_len + q_len) * (MM + U + W1); E_ptr[bq_len] = 37; } else { sq = q_len - 1; sn = en + (q_len - eq); D_ptr[sn] = (0 < k) ? 0 : (W1 + (t_len - 1 - m) * U); E_ptr[sn] = (0 < k) ? 0 : 37; --sn; } t_nuc = getNuc(template, nuc_pos); for(n = sn, q_pos = sq; n > en; --q_pos, --n) { E_ptr[n] = 0; /* update Q and P, gap openings */ Q = D_ptr[n + 1] + W1; P_ptr[n] = D_prev[n - 1] + W1; if(Q < P_ptr[n]) { D_ptr[n] = P_ptr[n]; e = 4; } else { D_ptr[n] = Q; e = 2; } /* update Q and P, gap extensions */ /* mark bit 4 and 5 as possible gap-opennings, if necesarry */ thisScore = Q_prev + U; if(Q < thisScore) { Q = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 3; } } else { E_ptr[n] |= 16; } thisScore = P_prev[n - 1] + U; if(P_ptr[n] < thisScore) { P_ptr[n] = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 5; } } else { E_ptr[n] |= 32; } /* Update D, match */ thisScore = D_prev[n] + d[t_nuc][query[q_pos]]; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; E_ptr[n] |= 1; } else { E_ptr[n] |= e; } Q_prev = Q; } /* handle banded boundary */ E_ptr[n] = 0; /* update Q gap */ Q = D_ptr[n + 1] + W1; thisScore = Q_prev + U; if(Q < thisScore) { Q = thisScore; e = 3; } else { e = 2; E_ptr[n] |= 16; } /* update unavailable P gap */ P_ptr[n] = (t_len + q_len) * (MM + U + W1); /* Update D */ D_ptr[n] = D_prev[n] + d[t_nuc][query[q_pos]]; /* set D to max, and set E */ if(Q <= D_ptr[n]) { E_ptr[n] |= 1; } else { D_ptr[n] = Q; E_ptr[n] |= e; } /* continue as usual */ E_ptr -= (bq_len + 1); if(eq == 0 && k < 0 && Stat.score < D_ptr[n]) { Stat.score = D_ptr[n]; pos[0] = m; pos[1] = n; } tmp = D_ptr; D_ptr = D_prev; D_prev = tmp; tmp = P_ptr; P_ptr = P_prev; P_prev = tmp; } E_ptr = E; /* get start position of alignment */ q_pos = 0; if(pos[0] == 0) { pos[1] = en; Stat.score = D_prev[en]; } if(k == -2) { for(n = en; n < bq_len; ++n) { if(Stat.score <= D_prev[n]) { Stat.score = D_prev[n]; pos[0] = 0; pos[1] = n; q_pos = n - en; } } } aligned->start = q_pos; /* back tracking */ m = pos[0]; n = pos[1]; E_ptr = E + (m * (bq_len + 1)); nuc_pos = m + t_s; Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; while(E_ptr[n] != 0) { if(nuc_pos == template_length) { nuc_pos = 0; } if((E_ptr[n] & 7) == 1) { aligned->t[Stat.len] = getNuc(template, nuc_pos); aligned->q[Stat.len] = query[q_pos]; aligned->s[Stat.len] = (aligned->t[Stat.len] == aligned->q[Stat.len]) ? '|' : '_'; ++Stat.match; ++nuc_pos; E_ptr += (bq_len + 1); ++q_pos; } else if((E_ptr[n] & 7) >= 4) { while(!(E_ptr[n] >> 4)) { aligned->t[Stat.len] = getNuc(template, nuc_pos); aligned->q[Stat.len] = 5; aligned->s[Stat.len] = '_'; ++nuc_pos; E_ptr += (bq_len + 1); --n; ++Stat.len; ++Stat.qGaps; } aligned->t[Stat.len] = getNuc(template, nuc_pos); aligned->q[Stat.len] = 5; aligned->s[Stat.len] = '_'; ++nuc_pos; E_ptr += (bq_len + 1); --n; ++Stat.qGaps; } else { while(!(E_ptr[n] >> 3)) { aligned->t[Stat.len] = 5; aligned->q[Stat.len] = query[q_pos]; aligned->s[Stat.len] = '_'; ++n; ++q_pos; ++Stat.len; ++Stat.tGaps; } aligned->t[Stat.len] = 5; aligned->q[Stat.len] = query[q_pos]; aligned->s[Stat.len] = '_'; ++n; ++q_pos; ++Stat.tGaps; } ++Stat.len; } aligned->s[Stat.len] = 0; aligned->end = q_len - q_pos; return Stat; } AlnScore NW_score(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, NWmat *matrices, int template_length) { int m, n, t_len, q_len, thisScore, nuc_pos, W1, U, MM, pos[2]; int *D_ptr, *D_prev, Q, Q_prev, *P_ptr, *P_prev, *tmp, **d; unsigned char *query, t_nuc, *E, *E_ptr, e; AlnScore Stat; Penalties *rewards; rewards = matrices->rewards; W1 = rewards->W1; U = rewards->U; MM = rewards->MM; d = rewards->d; t_len = t_e - t_s; q_len = q_e - q_s; if(t_len < 0) { t_len += template_length; } query = (unsigned char*)(queryOrg + q_s); Stat.pos = 0; if(t_len == 0 || q_len == 0) { if(t_len == q_len) { Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.score = 0; } else if(t_len == 0) { Stat.len = q_len; Stat.match = 0; Stat.tGaps = q_len; Stat.qGaps = 0; Stat.score = W1 + (q_len - 1) * U; } else { Stat.len = t_len; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = t_len; Stat.score = W1 + (t_len - 1) * U; } return Stat; } /* check matrix size */ if(matrices->NW_q <= q_len) { matrices->NW_q = q_len << 1; free(matrices->D[0]); free(matrices->P[0]); matrices->D[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->P[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->D[1] = matrices->D[0] + matrices->NW_q; matrices->P[1] = matrices->P[0] + matrices->NW_q; } if(matrices->NW_s <= ((q_len + 1) * (t_len + 1))) { matrices->NW_s = ((q_len + 2) * (t_len + 2)); free(matrices->E); matrices->E = smalloc(matrices->NW_s); } /* fill in start penalties */ D_ptr = matrices->D[0]; D_prev = matrices->D[1]; P_ptr = matrices->P[0]; P_prev = matrices->P[1]; E = matrices->E; thisScore = (t_len + q_len) * (MM + U + W1); Stat.score = thisScore; if(0 < k) { E_ptr = E; for(m = 0; m < t_len; ++m) { E_ptr[q_len] = 0; E_ptr += (q_len + 1); } if(k == 1) { for(n = q_len - 1; n >= 0; --n) { D_prev[n] = W1 + (q_len - 1 - n) * U; P_prev[n] = thisScore; E_ptr[n] = 3; } E_ptr[q_len - 1] = 18; E_ptr[q_len] = 0; D_prev[q_len] = 0; P_prev[q_len] = 0; } else { for(n = q_len; n >= 0; --n) { D_prev[n] = 0; P_prev[n] = thisScore; E_ptr[n] = 0; } } } else { E_ptr = E; for(m = 0; m < t_len; ++m) { E_ptr[q_len] = 5; E_ptr += (q_len + 1); } E_ptr[-1] = 36; for(n = q_len - 1; n >= 0; --n) { D_prev[n] = W1 + (q_len - 1 - n) * U; P_prev[n] = thisScore; E_ptr[n] = 3; } E_ptr[q_len - 1] = 18; E_ptr[q_len] = 0; D_prev[q_len] = 0; P_prev[q_len] = 0; } E_ptr -= (q_len + 1); /* Perform NW */ pos[0] = 0; for(m = t_len - 1, nuc_pos = t_e - 1; m >= 0; --m, --nuc_pos) { if(nuc_pos < 0) { nuc_pos = template_length - 1; } D_ptr[q_len] = (0 < k) ? 0 : (W1 + (t_len - 1 - m) * U); Q_prev = (t_len + q_len) * (MM + U + W1); t_nuc = getNuc(template, nuc_pos); for(n = q_len - 1; n >= 0; --n) { E_ptr[n] = 0; /* update Q and P, gap openings */ Q = D_ptr[n + 1] + W1; P_ptr[n] = D_prev[n] + W1; if(Q < P_ptr[n]) { D_ptr[n] = P_ptr[n]; e = 4; } else { D_ptr[n] = Q; e = 2; } /* update Q and P, gap extensions */ /* mark bit 4 and 5 as possible gap-opennings, if necesarry */ thisScore = Q_prev + U; if(Q < thisScore) { Q = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 3; } } else { E_ptr[n] |= 16; } thisScore = P_prev[n] + U; if(P_ptr[n] < thisScore) { P_ptr[n] = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 5; } } else { E_ptr[n] |= 32; } /* Update D, match */ thisScore = D_prev[n + 1] + d[t_nuc][query[n]]; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; E_ptr[n] |= 1; } else { E_ptr[n] |= e; } Q_prev = Q; } E_ptr -= (q_len + 1); if(k < 0 && Stat.score < *D_ptr) { Stat.score = *D_ptr; pos[0] = m; } tmp = D_ptr; D_ptr = D_prev; D_prev = tmp; tmp = P_ptr; P_ptr = P_prev; P_prev = tmp; } E_ptr = E; /* get start position of alignment */ if(k < 0) { pos[1] = 0; if(k == -2) { for(n = 0; n < q_len; ++n) { if(Stat.score <= D_prev[n]) { Stat.score = D_prev[n]; pos[0] = 0; pos[1] = n; } } } } else { Stat.score = *D_prev; pos[0] = 0; pos[1] = 0; } /* make back tracking */ m = pos[0]; E_ptr = E + (m * (q_len + 1)); n = pos[1]; nuc_pos = m + t_s; Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; while(E_ptr[n] != 0) { if(nuc_pos == template_length) { nuc_pos = 0; } if((E_ptr[n] & 7) == 1) { ++Stat.match; ++nuc_pos; E_ptr += (q_len + 1); ++n; } else if((E_ptr[n] & 7) >= 4) { while(!(E_ptr[n] >> 4)) { ++nuc_pos; E_ptr += (q_len + 1); ++Stat.len; ++Stat.qGaps; } ++Stat.qGaps; ++nuc_pos; E_ptr += (q_len + 1); } else { while(!(E_ptr[n] >> 3)) { ++n; ++Stat.len; ++Stat.tGaps; } ++Stat.tGaps; ++n; } ++Stat.len; } return Stat; } AlnScore NW_band_score(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, int band, NWmat *matrices, int template_length) { int m, n, t_len, q_len, thisScore, nuc_pos, pos[2]; int bq_len, halfBand, sn, en, sq, eq, q_pos, c_pos, W1, U, MM; int *D_ptr, *D_prev, Q, Q_prev, *P_ptr, *P_prev, *tmp, **d; unsigned char *query, t_nuc, *E, *E_ptr, e; AlnScore Stat; Penalties *rewards; rewards = matrices->rewards; W1 = rewards->W1; U = rewards->U; MM = rewards->MM; d = rewards->d; t_len = t_e - t_s; q_len = q_e - q_s; if(t_len < 0) { t_len += template_length; } query = (unsigned char*)(queryOrg + q_s); Stat.pos = 0; if(t_len == 0 || q_len == 0) { if(t_len == q_len) { Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.score = 0; } else if(t_len == 0) { Stat.len = q_len; Stat.match = 0; Stat.tGaps = q_len; Stat.qGaps = 0; Stat.score = W1 + (q_len - 1) * U; } else { Stat.len = t_len; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = t_len; Stat.score = W1 + (t_len - 1) * U; } return Stat; } /* ensure that band is equal */ if(band & 1) { ++band; } halfBand = band >> 1; /* check matrix size */ if(matrices->NW_q <= band) { matrices->NW_q = band << 1; free(matrices->D[0]); free(matrices->P[0]); matrices->D[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->P[0] = smalloc((matrices->NW_q << 1) * sizeof(int)); matrices->D[1] = matrices->D[0] + matrices->NW_q; matrices->P[1] = matrices->P[0] + matrices->NW_q; } if(matrices->NW_s <= ((band + 2) * (t_len + 1))) { matrices->NW_s = ((band + 3) * (t_len + 2)); free(matrices->E); matrices->E = smalloc(matrices->NW_s); } /* fill in start penalties */ bq_len = band + 1; /* (band + 1) ~ q_len */ D_ptr = matrices->D[0]; D_prev = matrices->D[1]; P_ptr = matrices->P[0]; P_prev = matrices->P[1]; E = matrices->E; thisScore = (t_len + q_len) * (MM + U + W1); Stat.score = thisScore; E_ptr = E + (t_len * (bq_len + 1)); c_pos = (t_len + q_len) >> 1; sn = q_len - 1 - (c_pos - halfBand); if(k != 2) { for(n = sn - 1; n >= 0; --n) { D_prev[n] = W1 + (sn - n - 1) * U; P_prev[n] = thisScore; E_ptr[n] = 3; } E_ptr[sn - 1] = 18; E_ptr[sn] = 0; D_prev[sn] = 0; P_prev[sn] = 0; } else { for(n = sn; n >= 0; --n) { D_prev[n] = 0; P_prev[n] = thisScore; E_ptr[n] = 0; } } E_ptr -= (bq_len + 1); /* Perform banded NW */ pos[0] = 0; pos[1] = 0; en = 0; c_pos = (t_len + q_len) >> 1; for(m = t_len - 1, nuc_pos = t_e - 1; m >= 0; --m, --nuc_pos, --c_pos) { if(nuc_pos < 0) { nuc_pos = template_length - 1; } /* get banded boundaries, w.r.t. query */ sq = c_pos + halfBand; eq = c_pos - halfBand; if(eq < 0) { eq = 0; ++en; } else { en = 0; } /* get start penalties */ Q_prev = (t_len + q_len) * (MM + U + W1); /* check boundaries */ if(sq < (q_len - 1)) { sn = bq_len - 1; D_ptr[bq_len] = (t_len + q_len) * (MM + U + W1); E_ptr[bq_len] = 37; } else { sq = q_len - 1; sn = en + (q_len - eq); D_ptr[sn] = (0 < k) ? 0 : (W1 + (t_len - 1 - m) * U); E_ptr[sn] = (0 < k) ? 0 : 37; --sn; } t_nuc = getNuc(template, nuc_pos); for(n = sn, q_pos = sq; n > en; --q_pos, --n) { E_ptr[n] = 0; /* update Q and P, gap openings */ Q = D_ptr[n + 1] + W1; P_ptr[n] = D_prev[n - 1] + W1; if(Q < P_ptr[n]) { D_ptr[n] = P_ptr[n]; e = 4; } else { D_ptr[n] = Q; e = 2; } /* update Q and P, gap extensions */ /* mark bit 4 and 5 as possible gap-opennings, if necesarry */ thisScore = Q_prev + U; if(Q < thisScore) { Q = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 3; } } else { E_ptr[n] |= 16; } thisScore = P_prev[n - 1] + U; if(P_ptr[n] < thisScore) { P_ptr[n] = thisScore; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; e = 5; } } else { E_ptr[n] |= 32; } /* Update D, match */ thisScore = D_prev[n] + d[t_nuc][query[q_pos]]; if(D_ptr[n] <= thisScore) { D_ptr[n] = thisScore; E_ptr[n] |= 1; } else { E_ptr[n] |= e; } Q_prev = Q; } /* handle banded boundary */ E_ptr[n] = 0; /* update Q gap */ Q = D_ptr[n + 1] + W1; thisScore = Q_prev + U; if(Q < thisScore) { Q = thisScore; e = 3; } else { e = 2; E_ptr[n] |= 16; } /* update unavailable P gap */ P_ptr[n] = (t_len + q_len) * (MM + U + W1); /* Update D */ D_ptr[n] = D_prev[n] + d[t_nuc][query[q_pos]]; /* set D to max, and set E */ if(Q <= D_ptr[n]) { E_ptr[n] |= 1; } else { D_ptr[n] = Q; E_ptr[n] |= e; } /* continue as usual */ E_ptr -= (bq_len + 1); if(eq == 0 && k < 0 && Stat.score < D_ptr[n]) { Stat.score = D_ptr[n]; pos[0] = m; pos[1] = n; } tmp = D_ptr; D_ptr = D_prev; D_prev = tmp; tmp = P_ptr; P_ptr = P_prev; P_prev = tmp; } E_ptr = E; /* get start position of alignment */ q_pos = 0; if(pos[0] == 0) { pos[1] = en; Stat.score = D_prev[en]; } if(k == -2) { for(n = en; n < bq_len; ++n) { if(Stat.score <= D_prev[n]) { Stat.score = D_prev[n]; pos[0] = 0; pos[1] = n; q_pos = n; } } } /* back tracking */ m = pos[0]; n = pos[1]; E_ptr = E + (m * (bq_len + 1)); nuc_pos = m + t_s; Stat.len = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; while(E_ptr[n] != 0) { if(nuc_pos == template_length) { nuc_pos = 0; } if((E_ptr[n] & 7) == 1) { ++Stat.match; ++nuc_pos; E_ptr += (bq_len + 1); ++q_pos; } else if((E_ptr[n] & 7) >= 4) { while(!(E_ptr[n] >> 4)) { ++nuc_pos; E_ptr += (bq_len + 1); --n; ++Stat.len; ++Stat.qGaps; } ++Stat.qGaps; ++nuc_pos; E_ptr += (bq_len + 1); --n; } else { while(!(E_ptr[n] >> 3)) { ++n; ++q_pos; ++Stat.len; ++Stat.tGaps; } ++Stat.tGaps; ++n; ++q_pos; } ++Stat.len; } return Stat; } genomicepidemiology-kma-091b8ffe66ac/updatescores.c0000644000175000017500000000606114157033525021761 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "pherror.h" #include "qseqs.h" #include "updatescores.h" void update_Scores(unsigned char *qseq, int q_len, int counter, int score, int *start, int *end, int *template, Qseqs *header, int flag, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, FILE *frag_out_raw) { int i, buffer[5]; /* print frag */ buffer[0] = q_len; buffer[1] = counter; buffer[2] = score; buffer[3] = header->len; buffer[4] = flag; counter = abs(counter); sfwrite(buffer, sizeof(int), 5, frag_out_raw); sfwrite(qseq, 1, q_len, frag_out_raw); sfwrite(header->seq, 1, header->len, frag_out_raw); sfwrite(start, sizeof(int), counter, frag_out_raw); sfwrite(end, sizeof(int), counter, frag_out_raw); sfwrite(template, sizeof(int), counter, frag_out_raw); /* update scores */ if(counter == 1) { //Only one best match if(*template < 0) { template[0] = -template[0]; } alignment_scores[*template] += score; uniq_alignment_scores[*template] += score; } else { i = counter; while(i--) { alignment_scores[abs(template[i])] += score; } } } void update_Scores_pe(unsigned char *qseq, int q_len, unsigned char *qseq_r, int qr_len, int counter, int score, int *start, int *end, int *template, Qseqs *header, Qseqs *header_r, int flag, int flag_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, FILE *frag_out_raw) { int i, buffer[5]; /* print frag */ buffer[0] = q_len; buffer[1] = counter; buffer[2] = -score; buffer[3] = header->len; buffer[4] = flag; counter = abs(counter); sfwrite(buffer, sizeof(int), 5, frag_out_raw); sfwrite(qseq, 1, q_len, frag_out_raw); sfwrite(header->seq, 1, header->len, frag_out_raw); sfwrite(start, sizeof(int), counter, frag_out_raw); sfwrite(end, sizeof(int), counter, frag_out_raw); sfwrite(template, sizeof(int), counter, frag_out_raw); buffer[0] = qr_len; buffer[1] = header_r->len; buffer[2] = flag_r; sfwrite(buffer, sizeof(int), 3, frag_out_raw); sfwrite(qseq_r, 1, qr_len, frag_out_raw); sfwrite(header_r->seq, 1, header_r->len, frag_out_raw); /* update scores */ if(counter == 1) { //Only one best match if(*template < 0) { template[0] = -template[0]; } alignment_scores[*template] += score; uniq_alignment_scores[*template] += score; } else { i = counter; while(i--) { alignment_scores[abs(template[i])] += score; } } } genomicepidemiology-kma-091b8ffe66ac/hashmapcci.h0000644000175000017500000000561314157033525021367 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #define murmur(index, kmer) index = (3323198485ul ^ kmer) * 0x5bd1e995; index ^= index >> 15; #ifndef HASHMAPCCI typedef struct hashMapCCI HashMapCCI; struct hashMapCCI { long unsigned mask; unsigned len; // seqlen long unsigned size; // size of index unsigned kmerindex; int *index; // k-mer posititions in seq / chain int *chain; // k-mer collision positions long unsigned *seq; // 2-bit sequence unsigned cci_size; // size of closed chains unsigned cci_next; // next available chain unsigned cci_avail; // avail chains }; #define HASHMAPCCI 1 #endif /* pointers determining how indexes a stored */ extern HashMapCCI * (*alignLoadPtr)(HashMapCCI *, int, int, int, long unsigned); long unsigned hashMapCCI_initialize(HashMapCCI *dest, int len, int kmerindex); void hashMapCCI_destroy(HashMapCCI *dest); int hashMapCCI_get(const HashMapCCI *dest, long unsigned key, unsigned shifter); int hashMapCCI_get_bound(const HashMapCCI *dest, long unsigned key, int min, int max, unsigned shifter); int * hashMapCCI_getDubPos(const HashMapCCI *dest, long unsigned key, int value, unsigned shifter); int * hashMapCCI_getNextDubPos(const HashMapCCI *dest, int *chain, long unsigned key, int min, int max, unsigned shifter); int defragChain(HashMapCCI *dest, int size, int shifter); int newChain(HashMapCCI *dest, int pos, int newpos, long unsigned kmer, int shifter); int extendChain(HashMapCCI *dest, int chainpos, int newpos, long unsigned kmer, int shifter); void hashMapCCI_add(HashMapCCI *dest, long unsigned key, int newpos, unsigned shifter); void hashMapCCI_add_thread(HashMapCCI *dest, long unsigned key, int newpos, unsigned shifter); HashMapCCI * hashMapCCI_load(HashMapCCI *src, int seq, int len, int kmersize); HashMapCCI * hashMapCCI_load_thread(HashMapCCI *src, int seq, int len, int kmersize, int thread_num); void hashMapCCI_dump(HashMapCCI *src, FILE *seq); HashMapCCI * alignLoad_fly(HashMapCCI *dest, int seq_in, int len, int kmersize, long unsigned seq_index); HashMapCCI * alignLoad_fly_mem(HashMapCCI *dest, int seq_in, int len, int kmersize, long unsigned seq_index); HashMapCCI * alignLoad_skip(HashMapCCI *dest, int seq_in, int len, int kmersize, long unsigned seq_index); genomicepidemiology-kma-091b8ffe66ac/compdna.h0000644000175000017500000000323314157033525020704 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "qseqs.h" #ifndef COMPDNA typedef struct compDNA CompDNA; struct compDNA { unsigned seqlen; unsigned size; unsigned complen; long unsigned *seq; int *N; }; #define COMPDNA 1 #endif void allocComp(CompDNA *compressor, unsigned size); void freeComp(CompDNA *compressor); CompDNA * setComp(unsigned size); void destroyComp(CompDNA *src); void resetComp(CompDNA *compressor); void compDNA(CompDNA *compressor, unsigned char *seq, int seqlen); int compDNAref(CompDNA *compressor, unsigned char *qseq, int seqlen); void unCompDNA(CompDNA *compressor, unsigned char *seq); void qseqCompDNA(CompDNA *compressor, Qseqs *qseq); long unsigned binRev(long unsigned mer); void rc_comp(CompDNA *compressor, CompDNA *compressor_rc); void comp_rc(CompDNA *compressor); void dumpComp(CompDNA *compressor, FILE* file); int loadComp(CompDNA *compressor, FILE* file); int getComp(CompDNA *compressor, FILE* file); void dallocComp(CompDNA *compressor, unsigned size); genomicepidemiology-kma-091b8ffe66ac/runinput.c0000644000175000017500000004010514157033525021141 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "compdna.h" #include "filebuff.h" #include "pherror.h" #include "runinput.h" #include "qseqs.h" #include "seqparse.h" #include "stdstat.h" void (*printFsa_ptr)(Qseqs*, Qseqs*, CompDNA*, FILE*) = &printFsa; void (*printFsa_pair_ptr)(Qseqs*, Qseqs*, Qseqs*, Qseqs*, CompDNA*, FILE*) = &printFsa_pair; long unsigned run_input(char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int minlen, int maxlen, char *trans, const double *prob, FILE *out) { int fileCounter, phredScale, phredCut, start, end; unsigned FASTQ; long unsigned count; char *filename; unsigned char *seq; Qseqs *header, *qseq, *qual; FileBuff *inputfile; CompDNA *compressor; compressor = smalloc(sizeof(CompDNA)); allocComp(compressor, 1024); header = setQseqs(256); qseq = setQseqs(1024); qual = setQseqs(1024); inputfile = setFileBuff(CHUNK); count = 0; for(fileCounter = 0; fileCounter < fileCount; ++fileCounter) { filename = (char*)(inputfiles[fileCounter]); /* determine filetype and open it */ if((FASTQ = openAndDetermine(inputfile, filename)) & 3) { fprintf(stderr, "%s\t%s\n", "# Reading inputfile: ", filename); } /* parse the file */ if(FASTQ & 1) { /* get phred scale */ phredScale = getPhredFileBuff(inputfile); fprintf(stderr, "# Phred scale:\t%d\n", phredScale); phredCut = phredScale + minPhred; /* parse reads */ while(FileBuffgetFq(inputfile, header, qseq, qual, trans)) { if(qseq->len <= maxlen) { /* trim */ seq = qual->seq; start = fiveClip; end = qseq->len - 1 - threeClip; end = end < 0 ? 0 : end; while(end >= 0 && seq[end] < phredCut) { --end; } ++end; while(start < end && seq[start] < phredCut) { ++start; } /* for(i = start; i < end; ++i) { if(seq[i] < phredCut) { seq[i] = 4; } } */ qseq->len = end - start; /* print */ if(qseq->len > minlen && minQ <= eQual(seq + start, qseq->len, minQ, prob - phredScale)) { /* dump seq */ qseq->seq += start; printFsa_ptr(header, qseq, compressor, out); qseq->seq -= start; ++count; } } } } else if(FASTQ & 2) { while(FileBuffgetFsa(inputfile, header, qseq, trans)) { if(qseq->len <= maxlen) { /* remove leading and trailing N's */ start = 0; end = qseq->len - 1; seq = qseq->seq; while(end >= 0 && seq[end] == 4) { --end; } ++end; while(start < end && seq[start] == 4) { ++start; } qseq->len = end - start; if(qseq->len > minlen) { /* dump seq */ qseq->seq += start; printFsa_ptr(header, qseq, compressor, out); qseq->seq -= start; ++count; } } } } if(FASTQ & 4) { gzcloseFileBuff(inputfile); } else { closeFileBuff(inputfile); } } freeComp(compressor); free(compressor); destroyQseqs(header); destroyQseqs(qseq); destroyQseqs(qual); destroyFileBuff(inputfile); return count; } long unsigned run_input_PE(char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int minlen, char *trans, const double *prob, FILE *out) { int fileCounter, phredScale, phredCut, start, start2, end; unsigned FASTQ, FASTQ2; long unsigned count; char *filename; unsigned char *seq; double eq1, eq2; Qseqs *header, *qseq, *qual, *header2, *qseq2, *qual2; FileBuff *inputfile, *inputfile2; CompDNA *compressor; compressor = malloc(sizeof(CompDNA)); if(!compressor) { ERROR(); } allocComp(compressor, 1024); header = setQseqs(256); qseq = setQseqs(1024); qual = setQseqs(1024); header2 = setQseqs(256); qseq2 = setQseqs(1024); qual2 = setQseqs(1024); inputfile = setFileBuff(CHUNK); inputfile2 = setFileBuff(CHUNK); count = 0; for(fileCounter = 0; fileCounter < fileCount; ++fileCounter) { filename = inputfiles[fileCounter]; /* determine filetype and open it */ FASTQ = openAndDetermine(inputfile, filename); ++fileCounter; filename = inputfiles[fileCounter]; FASTQ2 = openAndDetermine(inputfile2, filename); if(FASTQ == FASTQ2) { fprintf(stderr, "# Reading inputfile:\t%s %s\n", inputfiles[fileCounter-1], filename); } else { fprintf(stderr, "Inputfiles:\t%s %s\nAre in different format.\n", inputfiles[fileCounter-1], filename); FASTQ = 0; } /* parse the file */ if(FASTQ & 1) { /* get phred scale */ phredScale = getPhredFileBuff(inputfile); if(phredScale == 0) { phredScale = getPhredFileBuff(inputfile2); } fprintf(stderr, "# Phred scale:\t%d\n", phredScale); phredCut = phredScale + minPhred; /* parse reads */ //while(FileBuffgetFq(inputfile, header, qseq, qual) && FileBuffgetFq(inputfile2, header2, qseq2, qual2)) { /* this ensures reading of truncated files */ while((FileBuffgetFq(inputfile, header, qseq, qual, trans) | FileBuffgetFq(inputfile2, header2, qseq2, qual2, trans))) { /* trim forward */ seq = qual->seq; start = fiveClip; end = qseq->len - 1 - threeClip; end = end < 0 ? 0 : end; while(end >= 0 && seq[end] < phredCut) { --end; } ++end; while(start < end && seq[start] < phredCut) { ++start; } /* for(i = start; i < end; ++i) { if(seq[i] < phredCut) { seq[i] = 4; } } */ qseq->len = end - start; eq1 = eQual(seq + start, qseq->len, minQ, prob - phredScale); /* trim reverse */ seq = qual2->seq; start2 = fiveClip; end = qseq2->len - 1; while(end >= 0 && seq[end] < phredCut) { --end; } ++end; while(start2 < end && seq[start2] < phredCut) { ++start2; } /* for(i = start; i < end; ++i) { if(seq[i] < phredCut) { seq[i] = 4; } } */ qseq2->len = end - start2; eq2 = eQual(seq + start2, qseq2->len, minQ, prob - phredScale); /* print */ if(qseq->len > minlen && qseq2->len > minlen && minQ <= eq1 && minQ <= eq2) { qseq->seq += start; qseq2->seq += start2; printFsa_pair_ptr(header, qseq, header2, qseq2, compressor, out); qseq->seq -= start; qseq2->seq -= start2; ++count; } else if(qseq->len > minlen && minQ <= eq1) { qseq->seq += start; printFsa_ptr(header, qseq, compressor, out); qseq->seq -= start; ++count; } else if(qseq2->len > minlen && minQ <= eq2) { qseq2->seq += start2; printFsa_ptr(header2, qseq2, compressor, out); qseq2->seq -= start2; ++count; } } } else if(FASTQ & 2) { while((FileBuffgetFsa(inputfile, header, qseq, trans) | FileBuffgetFsa(inputfile2, header2, qseq2, trans))) { /* remove leading and trailing N's */ start = 0; end = qseq->len - 1; seq = qseq->seq; while(end >= 0 && seq[end] == 4) { --end; } ++end; while(start < end && seq[start] == 4) { ++start; } qseq->len = end - start; start2 = 0; end = qseq2->len - 1; seq = qseq2->seq; while(end >= 0 && seq[end] == 4) { --end; } ++end; while(start2 < end && seq[start2] == 4) { ++start2; } qseq2->len = end - start2; /* print */ if(qseq->len > minlen && qseq2->len > minlen) { qseq->seq += start; qseq2->seq += start2; printFsa_pair_ptr(header, qseq, header2, qseq2, compressor, out); qseq->seq -= start; qseq2->seq -= start2; ++count; } else if(qseq->len > minlen) { qseq->seq += start; printFsa_ptr(header, qseq, compressor, out); qseq->seq -= start; ++count; } else if(qseq2->len > minlen) { qseq2->seq += start2; printFsa_ptr(header2, qseq2, compressor, out); qseq2->seq -= start2; ++count; } } } --fileCounter; if(FASTQ & 4) { gzcloseFileBuff(inputfile); } else { closeFileBuff(inputfile); } ++fileCounter; if(FASTQ2 & 4) { gzcloseFileBuff(inputfile2); } else { closeFileBuff(inputfile2); } } freeComp(compressor); free(compressor); destroyQseqs(header); destroyQseqs(qseq); destroyQseqs(qual); destroyQseqs(header2); destroyQseqs(qseq2); destroyQseqs(qual2); destroyFileBuff(inputfile); destroyFileBuff(inputfile2); return count; } long unsigned run_input_INT(char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int minlen, char *trans, const double *prob, FILE *out) { int fileCounter, phredScale, phredCut, start, start2, end; unsigned FASTQ; long unsigned count; char *filename; unsigned char *seq; double eq1, eq2; Qseqs *header, *qseq, *qual, *header2, *qseq2, *qual2; FileBuff *inputfile; CompDNA *compressor; compressor = malloc(sizeof(CompDNA)); if(!compressor) { ERROR(); } allocComp(compressor, 1024); header = setQseqs(256); qseq = setQseqs(1024); qual = setQseqs(1024); header2 = setQseqs(256); qseq2 = setQseqs(1024); qual2 = setQseqs(1024); inputfile = setFileBuff(CHUNK); count = 0; for(fileCounter = 0; fileCounter < fileCount; ++fileCounter) { filename = (char*)(inputfiles[fileCounter]); /* determine filetype and open it */ if((FASTQ = openAndDetermine(inputfile, filename)) & 3) { fprintf(stderr, "%s\t%s\n", "# Reading inputfile: ", filename); } /* parse the file */ if(FASTQ & 1) { /* get phred scale */ phredScale = getPhredFileBuff(inputfile); fprintf(stderr, "# Phred scale:\t%d\n", phredScale); phredCut = phredScale + minPhred; /* parse reads */ while((FileBuffgetFq(inputfile, header, qseq, qual, trans) | FileBuffgetFq(inputfile, header2, qseq2, qual2, trans))) { /* trim forward */ seq = qual->seq; start = fiveClip; end = qseq->len - 1 - threeClip; end = end < 0 ? 0 : end; while(end >= 0 && seq[end] < phredCut) { --end; } ++end; while(start < end && seq[start] < phredCut) { ++start; } /* for(i = start; i < end; ++i) { if(seq[i] < phredCut) { seq[i] = 4; } } */ qseq->len = end - start; eq1 = eQual(seq + start, qseq->len, minQ, prob - phredScale); /* trim reverse */ seq = qual2->seq; start2 = fiveClip; end = qseq2->len - 1; while(end >= 0 && seq[end] < phredCut) { --end; } ++end; while(start2 < end && seq[start2] < phredCut) { ++start2; } /* for(i = start; i < end; ++i) { if(seq[i] < phredCut) { seq[i] = 4; } } */ qseq2->len = end - start2; eq2 = eQual(seq + start2, qseq2->len, minQ, prob - phredScale); /* print */ if(qseq->len > minlen && qseq2->len > minlen && minQ <= eq1 && minQ <= eq2) { qseq->seq += start; qseq2->seq += start2; printFsa_pair_ptr(header, qseq, header2, qseq2, compressor, out); qseq->seq -= start; qseq2->seq -= start2; ++count; } else if(qseq->len > minlen && minQ <= eq1) { qseq->seq += start; printFsa_ptr(header, qseq, compressor, out); qseq->seq -= start; ++count; } else if(qseq2->len > minlen && minQ <= eq2) { qseq2->seq += start2; printFsa_ptr(header2, qseq2, compressor, out); qseq2->seq -= start2; ++count; } } } else if(FASTQ & 2) { while((FileBuffgetFsa(inputfile, header, qseq, trans) | FileBuffgetFsa(inputfile, header2, qseq2, trans))) { /* remove leading and trailing N's */ start = 0; end = qseq->len - 1; seq = qseq->seq; while(end >= 0 && seq[end] == 4) { --end; } ++end; while(start < end && seq[start] == 4) { ++start; } qseq->len = end - start; start2 = 0; end = qseq2->len - 1; seq = qseq2->seq; while(end >= 0 && seq[end] == 4) { --end; } ++end; while(start2 < end && seq[start2] == 4) { ++start2; } qseq2->len = end - start2; /* print */ if(qseq->len > minlen && qseq2->len > minlen) { qseq->seq += start; qseq2->seq += start2; printFsa_pair_ptr(header, qseq, header2, qseq2, compressor, out); qseq->seq -= start; qseq2->seq -= start2; ++count; } else if(qseq->len > minlen) { qseq->seq += start; printFsa_ptr(header, qseq, compressor, out); qseq->seq -= start; ++count; } else if(qseq2->len > minlen) { qseq2->seq += start2; printFsa_ptr(header2, qseq2, compressor, out); qseq2->seq -= start2; ++count; } } } if(FASTQ & 4) { gzcloseFileBuff(inputfile); } else { closeFileBuff(inputfile); } } freeComp(compressor); free(compressor); destroyQseqs(header); destroyQseqs(qseq); destroyQseqs(qual); destroyQseqs(header2); destroyQseqs(qseq2); destroyQseqs(qual2); destroyFileBuff(inputfile); return count; } void bootFsa(Qseqs *header, Qseqs *qseq, CompDNA *compressor, FILE *out) { int i, end, buffer[4]; /* bootstrap in pieces of 1024 */ buffer[3] = header->len; end = qseq->len - 1024; for(i = 0; i < end; i += 512) { compDNA(compressor, qseq->seq + i, 1024); /* print */ buffer[0] = compressor->seqlen; buffer[1] = compressor->complen; buffer[2] = compressor->N[0]; sfwrite(buffer, sizeof(int), 4, out); sfwrite(compressor->seq, sizeof(long unsigned), compressor->complen, out); sfwrite(compressor->N + 1, sizeof(int), compressor->N[0], out); sfwrite((header->seq + 1), 1, header->len, out); resetComp(compressor); } compDNA(compressor, qseq->seq + i, qseq->len - i); /* print */ buffer[0] = compressor->seqlen; buffer[1] = compressor->complen; buffer[2] = compressor->N[0]; sfwrite(buffer, sizeof(int), 4, out); sfwrite(compressor->seq, sizeof(long unsigned), compressor->complen, out); sfwrite(compressor->N + 1, sizeof(int), compressor->N[0], out); sfwrite((header->seq + 1), 1, header->len, out); resetComp(compressor); } void printFsa(Qseqs *header, Qseqs *qseq, CompDNA *compressor, FILE *out) { int buffer[4]; /* translate to 2bit */ if(qseq->len >= compressor->size) { freeComp(compressor); allocComp(compressor, qseq->len); } compDNA(compressor, qseq->seq, qseq->len); buffer[0] = compressor->seqlen; buffer[1] = compressor->complen; buffer[2] = compressor->N[0]; buffer[3] = header->len; sfwrite(buffer, sizeof(int), 4, out); sfwrite(compressor->seq, sizeof(long unsigned), compressor->complen, out); sfwrite(compressor->N + 1, sizeof(int), compressor->N[0], out); sfwrite((header->seq + 1), 1, header->len, out); resetComp(compressor); } void printFsa_pair(Qseqs *header, Qseqs *qseq, Qseqs *header_r, Qseqs *qseq_r, CompDNA *compressor, FILE *out) { int buffer[4]; /* translate to 2bit */ if(qseq->len >= compressor->size) { freeComp(compressor); allocComp(compressor, qseq->len); } compDNA(compressor, qseq->seq, qseq->len); buffer[0] = compressor->seqlen; buffer[1] = compressor->complen; buffer[2] = compressor->N[0]; buffer[3] = -header->len; sfwrite(buffer, sizeof(int), 4, out); sfwrite(compressor->seq, sizeof(long unsigned), compressor->complen, out); sfwrite(compressor->N + 1, sizeof(int), compressor->N[0], out); sfwrite((header->seq + 1), 1, header->len, out); resetComp(compressor); /* translate to 2bit */ if(qseq_r->len >= compressor->size) { freeComp(compressor); allocComp(compressor, qseq_r->len); } compDNA(compressor, qseq_r->seq, qseq_r->len); buffer[0] = compressor->seqlen; buffer[1] = compressor->complen; buffer[2] = compressor->N[0]; buffer[3] = header_r->len; sfwrite(buffer, sizeof(int), 4, out); sfwrite(compressor->seq, sizeof(long unsigned), compressor->complen, out); sfwrite(compressor->N + 1, sizeof(int), compressor->N[0], out); sfwrite((header_r->seq + 1), 1, header_r->len, out); resetComp(compressor); } genomicepidemiology-kma-091b8ffe66ac/README.md0000644000175000017500000001550314157033525020374 0ustar nileshnilesh[![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg?style=flat)](http://bioconda.github.io/recipes/kma/README.html) # Getting Started # ``` git clone https://bitbucket.org/genomicepidemiology/kma.git cd kma && make ./kma index -i templates.fsa.gz -o templates ./kma -i reads_se.fq.gz -o output/name -t_db templates ./kma -ipe reads_1.fq.gz reads_2.fq.gz -o output/name -t_db templates ``` # Introduction # KMA is a mapping method designed to map raw reads directly against redundant databases, in an ultra-fast manner using seed and extend. KMA is particulary good at aligning high quality reads against highly redundant databases, where unique matches often does not exist. It works for long low quality reads as well, such as those from Nanopore. Non-unique matches are resolved using the "ConClave" sorting scheme, and a consensus sequence are outputtet in addition to other common attributes, based on our users demands. If you use KMA for your published research, then please cite: Philip T.L.C. Clausen, Frank M. Aarestrup & Ole Lund, "Rapid and precise alignment of raw reads against redundant databases with KMA", BMC Bioinformatics, 2018;19:307. # Usage # A more detailed guide on KMA and its options can be found in the pdf "KMAspecification.pdf". For practical reasons you might want to add kma to your path, this is usually done with: ``` mv kma ~/bin/ ``` ## Indexing ## In order to use KMA for mapping, the databases need to indexed. This is done with kma index, the most important options are described below: ``` -i Input fasta file(s), space separated. By default kma index reads from stdin. -o Output name, the name given to the database. -k kmersize used for indexing the database. -k_t kmersize used to identify template candidates when running KMA. -k_i kmersize used when performing alignments between two sequences. ``` Example of use: ``` kma index -i templates.fsa.gz -o database/name ``` ## Mapping ## The default settings of KMA is set so that it should work on most cases, but it is evident to use the right options for the right problems. Some of the most important options: ``` -i Inputfile(s), default is read from stdin. All input options takes as many files as you wish in fastq or fasta format, space separated. -ipe Inputfile(s), paired end. The file pairs should be placed right after each other. -int Inputfile(s), interleaved. -o Output destination. -t_db Database from indexing. -mem_mode *.index and *.seq are not loaded into memory, which enables one to map against larger databases. Templates are chosen using k-mer counting. -dense Skip insertions when making the consensus sequence. -ref_fsa - will be substituted with n in the consensus sequence. -matrix Gives the counts all all called bases at each position in each mapped template. Columns are: reference base, A count, C count, G count, T count, N count, - count. -mp Minimum phred-score. -Mt1 Match to only one template in the database. -ID Minimum identity to output template match. -apm Paired end method, p: Reward if pairing the reads, u: unite best template matches in each read if possible, f force paired reads to pair. -1t1 One read to one template, no splicing performed. Well suited for short reads and whole genome mapping. -bc90 Basecalls should be significantly overrepresented, and have at least 90% agreement. -bcNano Basecalls optimized for nanopore sequencing. -mrs minimum alignment score normalized to alignment length. ``` Examples of running KMA: Short read mapping, one read maps only to one template: ``` kma -i singleEndReads.fq.gz -ipe pairedEnd_*.fq.gz -o output/name -t_db database/name -1t1 ``` Long read mapping against a database of genes: ``` kma -i someLongReads.fq.gz -o output/name -t_db database/name -bcNano -bc 0.7 ``` Whole genome mapping with nanopore reads: ``` kma -i nanoporeReads.fq.gz -o output/name -t_db database/name -mem_mode -mp 20 -mrs 0.0 -bcNano -bc 0.7 ``` Whole genome mapping against a single genome in the database (still nanopore), specified by template number (here 2). This is the same as the line number of the wanted sequences in the \*.name file from the indexing. ``` kma -i nanoporeReads.fq.gz -o output/name -t_db database/name -mp 20 -bcNano -bc 0.7 -Mt1 2 ``` # Result Explanation # When the mapping is done KMA will produce the following files: 1. \*.res A result overview giving the most common statistics for each mapped template. 2. \*.fsa The consensus sequences drawn from the alignments. 3. \*.aln The consensus alignment of the reads against their template. 4. \*.frag.gz Mapping information on each mapped read, columns are: read, number of equally well mapping templates, mapping score, start position, end position (w.r.t. template), the choosen template. 5. \*.mat.gz Base counts on each position in each template, (only if -matrix is enabled) # Shared memory # The databases of KMA can be put into shared memory, this enables you to align several samples at ones while only having the database loaded in one place. KMA_SHM can be used to put the databases into shared memory, and most importantly take them down afterwards. It is of the highest concern that these shared databases are used correctly, as they will take up a part of memory and they will exist there until they are taken down again, the computer is restarted or computer breaks down. Example of setting up a database in shared memory. ``` kma shm -t_db database/name -shmLvl 1 ``` -shmLvl specifies how much of the database there should be stored in shared memory, use. -shm-h to get an overview of the different levels. Example of taking it down again, always remember to do this then it is no longer needed: ``` kma shm -t_db database/name -shmLvl 1 -destroy ``` # Installation Requirements # In order to install KMA, you need to have a C-compiler and zlib development files installed. Zlib development files can be installed on unix systems with: ``` sudo apt-get install libz-dev ``` # Help # Usage and options are available with the "-h" option on all three programs. If in doubt, please mail any concerns or problems to: *plan@dtu.dk*. # Citation # 1. Philip T.L.C. Clausen, Frank M. Aarestrup & Ole Lund, "Rapid and precise alignment of raw reads against redundant databases with KMA", BMC Bioinformatics, 2018;19:307. # License # Copyright (c) 2017, Philip Clausen, Technical University of Denmark All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. genomicepidemiology-kma-091b8ffe66ac/penalties.h0000644000175000017500000000155114157033525021250 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PINC #define PINC 1 typedef struct penalties Penalties; struct penalties { int **d; int M; int MM; int U; int W1; int Wl; int Mn; int PE; }; #endif genomicepidemiology-kma-091b8ffe66ac/sam.c0000644000175000017500000001121014157033525020030 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "nw.h" #include "pherror.h" #include "qseqs.h" #include "runkma.h" #include "sam.h" #include "threader.h" char * makeCigar(Qseqs *Cigar, const Aln *aligned) { int len, cLen, rep; char op, pop, *s, *cigar; unsigned char *t, *q; if(Cigar->size < (aligned->len << 1)) { Cigar->size = (aligned->len << 1); free(Cigar->seq); Cigar->seq = smalloc(Cigar->size); } else if(aligned->len == 0) { return 0; } len = aligned->len; t = aligned->t; s = aligned->s; q = aligned->q; cigar = (char *) Cigar->seq; if(aligned->start) { cLen = sprintf(cigar, "%dS", aligned->start); } else { cLen = 0; } rep = 1; if(*s == '|') { pop = '='; } else if(*t == '-') { pop = 'I'; } else if(*q == '-') { pop = 'D'; } else { pop = 'X'; } ++t; ++s; ++q; while(--len) { if(*s == '|') { op = '='; } else if(*t == 5) { op = 'I'; } else if(*q == 5) { op = 'D'; } else { op = 'X'; } if(op == pop) { ++rep; } else { cLen += sprintf(cigar + cLen, "%d%c", rep, pop); rep = 1; pop = op; } ++t; ++s; ++q; } cLen += sprintf(cigar + cLen, "%d%c", rep, pop); if(aligned->end) { cLen += sprintf(cigar + cLen, "%dS", aligned->end); } Cigar->len = cLen; return cigar; } void saminit(Qseqs *template_name, FILE *name_file, int *template_lengths, int DB_size) { fprintf(stdout, "@HD\tVN:1.6\tGO:reference\n"); while(--DB_size) { fprintf(stdout, "@SQ\tSN:%s\tLN:%d\n", nameLoad(template_name, name_file), *++template_lengths); } fseek(name_file, 0, SEEK_SET); } int samwrite(const Qseqs *qseq, const Qseqs *header, const Qseqs *Qual, char *rname, const Aln *aligned, const int *stats) { static volatile int Lock = 0; static Qseqs *Cigar = 0; volatile int *lock = &Lock; int flag, pos, mapQ, pnext, tlen, size, et, score, tab; char *qname, *cigar, *rnext, *qual; unsigned char *seq; /* flag */ /* 1 read paired 2 read mapped in proper pair 4 read unmapped 8 mate unmapped 16 read reverse strand 32 mate reverse strand 64 first in pair 128 second in pair 256 not primary alignment 512 read fails platform/vendor quality checks 1024 read is PCR or optical duplicate 2048 supplementary alignment 1 template having multiple segments in sequencing 2 each segment properly aligned according to the aligner 4 segment unmapped 8 next segment in the template unmapped 16 SEQ being reverse complemented 32 SEQ of the next segment in the template being reverse complemented 64 the first segment in the template 128 the last segment in the template 256 secondary alignment 512 not passing filters, such as platform/vendor quality controls 1024 PCR or optical duplicate 2048 supplementary alignment */ qname = (char *) header->seq; seq = qseq->seq; if(Qual) { qual = (char *) Qual->seq; } else { qual = "*"; } if(aligned) { mapQ = 254 < aligned->mapQ ? 254 : aligned->mapQ; et = *stats; score = stats[1]; pos = stats[2] + 1; tlen = stats[3] - pos; flag = stats[4]; } else { mapQ = 0; et = 0; score = 0; pos = 0; tlen = 0; et = *stats; flag = stats[1]; if(rname == 0) { rname = "*"; } cigar = "*"; } rnext = "*"; pnext = 0; tab = 0; if(qname) { while(*qname) { if(*qname == '\t') { tab = -tab; *qname = 0; } else { ++qname; ++tab; } } qname = (char *) header->seq; } lock(lock); if(Cigar == 0) { Cigar = setQseqs(256); } if(aligned) { cigar = makeCigar(Cigar, aligned); if(2 * sizeof(int) + 1 < header->len && header->seq[header->len - 2 * sizeof(int) - 1] == 0) { cigar = (char *) Cigar->seq; sprintf(cigar, "%dS", *((int*) (header->seq + (header->len - 2 * sizeof(int))))); } } size = fprintf(stdout, "%s\t%d\t%s\t%d\t%d\t%s\t%s\t%d\t%d\t%s\t%s\tET:i:%d\tAS:i:%d\n", qname, flag, rname, pos, mapQ, cigar, rnext, pnext, tlen, (char *) seq, qual, et, score); unlock(lock); if(tab < 0) { qname[-tab] = '\t'; } return size; } genomicepidemiology-kma-091b8ffe66ac/matrix.c0000644000175000017500000000775514157033525020577 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include "matrix.h" #include "pherror.h" #include "tmp.h" Matrix * matrix_init(unsigned size) { int i, **ptr, *src; long unsigned Size; Matrix *dest; dest = smalloc(sizeof(Matrix)); dest->n = 0; dest->size = size; dest->mat = smalloc(size * sizeof(int *)); Size = size; Size *= size; Size *= sizeof(int); *(dest->mat) = smalloc(Size); /* set matrix rows */ ptr = dest->mat; src = *ptr; i = size; *ptr = src; while(--i) { src += size; *++ptr = src; } return dest; } Matrix * ltdMatrix_init(unsigned size) { int i, **ptr, *src; long unsigned Size; Matrix *dest; dest = smalloc(sizeof(Matrix)); dest->n = 0; dest->size = size; dest->mat = smalloc(size * sizeof(int *)); Size = size; Size *= (size - 1); Size *= (sizeof(int) / 2); *(dest->mat) = calloc(Size, 1); if(!*(dest->mat)) { ERROR(); } /* set matrix rows */ ptr = dest->mat; src = *ptr; i = 0; *ptr++ = src; while(--size) { *ptr++ = src + i; src += i++; } return dest; } Matrix * ltdMatrix_minit(long unsigned size) { int i, n, **ptr, *src; FILE *tmp; Matrix *dest; dest = smalloc(sizeof(Matrix)); dest->n = 0; dest->size = size; dest->mat = smalloc(size * sizeof(int *)); n = size; size = size * (size - 1) * sizeof(int) / 2; /* get matrix */ tmp = tmpF(0); if(fseek(tmp, size - 1, SEEK_SET) || putc(0, tmp) == EOF) { ERROR(); } fflush(tmp); fseek(tmp, 0, SEEK_SET); *(dest->mat) = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(tmp), 0); if(*(dest->mat) == MAP_FAILED) { ERROR(); } posix_madvise(*(dest->mat), size, POSIX_MADV_SEQUENTIAL); /* set matrix rows */ ptr = dest->mat; src = *ptr; i = 0; *ptr++ = src; while(--n) { *ptr++ = src + i; src += i++; } return dest; } void ltdMatrix_realloc(Matrix *src, unsigned size) { int i, **ptr, *mat; long unsigned Size; Size = size; Size *= (size - 1); Size *= (sizeof(int) / 2); *(src->mat) = realloc(*(src->mat), Size); src->mat = realloc(src->mat, size * sizeof(int *)); if(!src->mat || !*(src->mat)) { ERROR(); } src->size = size; /* set matrix rows */ ptr = src->mat; mat = *ptr; i = 0; *ptr++ = mat; while(--size) { *ptr++ = mat + i; mat += i++; } } void Matrix_destroy(Matrix *src) { free(*(src->mat)); free(src->mat); free(src); } void Matrix_mdestroy(Matrix *src) { long unsigned size; size = src->size; size *= (src->size - 1); size *= sizeof(int) / 2; msync(*(src->mat), size, MS_SYNC); munmap(*(src->mat), size); free(src->mat); free(src); } void ltdMatrix_popArrange(Matrix *mat, unsigned pos) { int i, n, *dest, *src; n = --mat->n; if(pos != n) { /* row to be emptied */ dest = mat->mat[pos]; /* row to be moved up */ src = mat->mat[n]; /* copy last row into "first" row */ i = pos + 1; while(--i) { *dest++ = *src++; } /* tilt remaining part of last row into column "pos" */ i = pos; ++src; while(++i < n) { mat->mat[i][pos] = *src++; } } } int ltdMatrix_add(Matrix *src) { int i, *ptr; /* realloc */ if(++src->n == src->size) { ltdMatrix_realloc(src, src->size << 1); } /* init new row */ i = src->n; ptr = src->mat[i - 1] - 1; while(--i) { *++ptr = 0; } return src->n - 1; } genomicepidemiology-kma-091b8ffe66ac/compdna.c0000644000175000017500000002110514157033525020675 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "compdna.h" #include "pherror.h" #include "qseqs.h" #include "stdnuc.h" void allocComp(CompDNA *compressor, unsigned size) { compressor->seqlen = 0; if(size & 31) { compressor->size = (size >> 5) + 1; compressor->size <<= 5; } else { compressor->size = size; } compressor->seq = calloc(compressor->size >> 5, sizeof(long unsigned)); compressor->N = malloc((compressor->size + 1) * sizeof(int)); if(!compressor->seq || !compressor->N) { ERROR(); } compressor->N[0] = 0; } void freeComp(CompDNA *compressor) { compressor->seqlen = 0; compressor->complen = 0; compressor->size = 0; free(compressor->seq); free(compressor->N); } CompDNA * setComp(unsigned size) { CompDNA *dest; dest = smalloc(sizeof(CompDNA)); dest->seqlen = 0; dest->size = dest->complen = 0; if(size & 31) { dest->size = (size >> 5) + 1; dest->size <<= 5; } else { dest->size = size; } dest->seq = calloc(dest->size >> 5, sizeof(long unsigned)); if(!dest->seq) { ERROR(); } dest->N = smalloc((dest->size + 1) * sizeof(int)); *(dest->N) = 0; return dest; } void destroyComp(CompDNA *src) { free(src->seq); free(src->N); free(src); } void resetComp(CompDNA *compressor) { compressor->N[0] = 0; compressor->seqlen = 0; compressor->complen = 0; } void compDNA(CompDNA *compressor, unsigned char *seq, int seqlen) { int i, j, pos, end; compressor->seqlen = seqlen; if(seqlen & 31) { compressor->complen = (seqlen >> 5) + 1; } else { compressor->complen = seqlen >> 5; } for(i = 0, pos = 0; i < seqlen; i += 32) { end = (i + 32 < seqlen) ? i + 32 : seqlen; pos = i >> 5; for(j = i; j < end; ++j) { if(seq[j] == 4) { compressor->seq[pos] <<= 2; compressor->N[0]++; compressor->N[compressor->N[0]] = j; } else { compressor->seq[pos] = (compressor->seq[pos] << 2) | seq[j]; } } } if(seqlen & 31) { compressor->seq[pos] <<= (64 - ((seqlen & 31) << 1)); } } int compDNAref(CompDNA *compressor, unsigned char *qseq, int seqlen) { int i, j, pos, end, bias; unsigned char *seq; /* trim leadin N's */ seq = qseq; bias = 0; while(*seq == 4) { ++seq; ++bias; } seqlen -= bias; /* trim trailing N's */ if(seqlen) { while(seq[--seqlen] == 4); ++seqlen; } compressor->seqlen = seqlen; if(seqlen & 31) { compressor->complen = (seqlen >> 5) + 1; } else { compressor->complen = seqlen >> 5; } pos = 0; compressor->N[0] = 0; for(i = 0; i < seqlen; i += 32) { end = (i + 32 < seqlen) ? i + 32 : seqlen; pos = i >> 5; for(j = i; j < end; ++j) { if(seq[j] == 4) { compressor->seq[pos] <<= 2; compressor->N[0]++; compressor->N[compressor->N[0]] = j; } else { compressor->seq[pos] = (compressor->seq[pos] << 2) | seq[j]; } } } if(seqlen & 31) { compressor->seq[pos] <<= (64 - ((seqlen & 31) << 1)); } return bias; } void unCompDNA(CompDNA *compressor, unsigned char *seq) { int i; /* get nucs */ i = compressor->seqlen; seq += i; *seq = 0; while(i--) { *--seq = getNuc(compressor->seq, i); } /* for(i = 0; i < compressor->seqlen; ++i) { seq[i] = getNuc(compressor->seq, i); } */ /* get N's */ for(i = 1; i <= compressor->N[0]; ++i) { seq[compressor->N[i]] = 4; } } void qseqCompDNA(CompDNA *compressor, Qseqs *qseq) { qseq->len = compressor->seqlen; if(qseq->size <= qseq->len) { qseq->size = qseq->len << 1; free(qseq->seq); qseq->seq = smalloc(qseq->size); } unCompDNA(compressor, qseq->seq); } long unsigned binRev(long unsigned mer) { /* swap consecutive pairs */ mer = ((mer >> 2) & 0x3333333333333333) | ((mer & 0x3333333333333333) << 2); /* swap nibbles */ mer = ((mer >> 4) & 0x0F0F0F0F0F0F0F0F) | ((mer & 0x0F0F0F0F0F0F0F0F) << 4); /* swap bytes */ mer = ((mer >> 8) & 0x00FF00FF00FF00FF) | ((mer & 0x00FF00FF00FF00FF) << 8); /* swap 2-bytes */ mer = ((mer >> 16) & 0x0000FFFF0000FFFF) | ((mer & 0x0000FFFF0000FFFF) << 16); /* swap 4-bytes */ return ((mer >> 32) | (mer << 32)); } void rc_comp(CompDNA *compressor, CompDNA *compressor_rc) { int i, j, shift, r_shift; compressor_rc->seqlen = compressor->seqlen; compressor_rc->complen = compressor->complen; /* reverse and complement*/ for(i = 0, j = compressor->complen - 1; i < compressor->complen; ++i, --j) { compressor_rc->seq[j] = binRev(~compressor->seq[i]); } /* shift */ if((compressor->seqlen & 31)) { shift = (((compressor->complen << 5) - compressor->seqlen) << 1); r_shift = 64 - shift; for(i = 0, j = 1; j < compressor->complen; i = j++) { compressor_rc->seq[i] = (compressor_rc->seq[i] << shift) | (compressor_rc->seq[j] >> r_shift); } compressor_rc->seq[i] <<= shift; } /* add N's */ shift = compressor->seqlen - 1; compressor_rc->N[0] = compressor->N[0]; for(i = 1, j = compressor->N[0]; j != 0; ++i, --j) { compressor_rc->N[i] = shift - compressor->N[j]; } } void comp_rc(CompDNA *compressor) { int i, j, shift, r_shift; long unsigned carry; /* reverse and complement*/ for(i = 0, j = compressor->complen - 1; i < j; ++i, --j) { carry = binRev(~compressor->seq[i]); compressor->seq[i] = binRev(~compressor->seq[j]); compressor->seq[j] = carry; } if(i == j) { compressor->seq[i] = binRev(~compressor->seq[i]); } /* shift */ if((compressor->seqlen & 31)) { shift = (((compressor->complen << 5) - compressor->seqlen) << 1); r_shift = 64 - shift; for(i = 0, j = 1; j < compressor->complen; i = j++) { compressor->seq[i] = (compressor->seq[i] << shift) | (compressor->seq[j] >> r_shift); } compressor->seq[i] <<= shift; } /* add N's */ i = 1; j = compressor->N[0]; shift = compressor->seqlen - 1; for(i = 1, j = compressor->N[0]; i < j; ++i, --j) { r_shift = shift - compressor->N[i]; compressor->N[i] = shift - compressor->N[j]; compressor->N[j] = r_shift; } if(i == j) { compressor->N[i] = shift - compressor->N[j]; } } void dumpComp(CompDNA *compressor, FILE* file) { sfwrite(&compressor->seqlen, sizeof(int), 1, file); sfwrite(&compressor->complen, sizeof(int), 1, file); sfwrite(compressor->seq, sizeof(long unsigned), compressor->complen, file); sfwrite(compressor->N, sizeof(int), compressor->N[0] + 1, file); } int loadComp(CompDNA *compressor, FILE* file) { if(fread(&compressor->seqlen, sizeof(int), 1, file)) { sfread(&compressor->complen, sizeof(int), 1, file); sfread(compressor->seq, sizeof(long unsigned), compressor->complen, file); sfread(compressor->N, sizeof(int), 1, file); sfread(compressor->N + 1, sizeof(int), compressor->N[0], file); return 1; } return 0; } int getComp(CompDNA *compressor, FILE* file) { compressor->seqlen = 0; if(!fread(&compressor->seqlen, sizeof(int), 1, file)) { return 0; } sfread(&compressor->complen, sizeof(int), 1, file); /* realloc */ if(compressor->seqlen >= compressor->size) { free(compressor->N); free(compressor->seq); if(compressor->seqlen & 31) { compressor->size = (compressor->seqlen >> 5) + 1; compressor->size <<= 6; } else { compressor->size = compressor->seqlen << 1; } compressor->seq = calloc(compressor->size >> 5, sizeof(long unsigned)); compressor->N = malloc((compressor->size + 1) * sizeof(int)); if(!compressor->seq || !compressor->N) { ERROR(); } compressor->N[0] = 0; } sfread(compressor->seq, sizeof(long unsigned), compressor->complen, file); sfread(compressor->N, sizeof(int), 1, file); sfread(compressor->N + 1, sizeof(int), compressor->N[0], file); return 1; } void dallocComp(CompDNA *compressor, unsigned size) { compressor->seqlen = 0; compressor->size = size; compressor->complen = 0; free(compressor->N); free(compressor->seq); if(size & 31) { compressor->size = (size >> 5) + 1; compressor->size <<= 5; } else { compressor->size = size; } compressor->seq = calloc(compressor->size >> 5, sizeof(long unsigned)); if(!compressor->seq) { ERROR(); } compressor->N = smalloc((compressor->size + 1) * sizeof(int)); compressor->N[0] = 0; } genomicepidemiology-kma-091b8ffe66ac/compkmers.h0000644000175000017500000000203614157033525021263 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef COMPKMERS typedef struct compKmers CompKmers; struct compKmers { long unsigned n; long unsigned size; long unsigned *kmers; }; #define COMPKMERS 1 #endif void allocCompKmers(CompKmers *compressor, int size); void reallocCompKmers(CompKmers *compressor, int size); int pushCompKmers(CompKmers *compressor, char *qseq, int kmersize); genomicepidemiology-kma-091b8ffe66ac/dist.h0000644000175000017500000000543514157033525020234 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2020 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include "hashmapkma.h" #include "matrix.h" #include "pherror.h" #include "runkma.h" #ifndef DIST typedef struct distThread DistThread; struct distThread { pthread_t id; int flag; int format; int thread_num; int *N; long unsigned ltdMat; long unsigned covMat; char *outfileM; FILE *name_file; HashMapKMA *DB; Matrix *Dist; Qseqs *template_name; struct distThread *next; }; #define DIST 1 #endif HashMapKMA * loadValues(const char *filename); void destroyValues(HashMapKMA *src); void kmerSimilarity(HashMapKMA *DB, Matrix *Dist, int *N); void kmerSimilarity_thread(HashMapKMA *DB, Matrix *Dist, int *N, int thread_num, volatile int *lock); int kmerDist(int Ni, int Nj, int D); int kmerShared(int Ni, int Nj, int D); int chi2dist(int Ni, int Nj, int D); void printIntLtdPhy(char *outfile, Matrix *Dist, int *N, FILE *name_file, Qseqs *template_name, unsigned format, int thread_num, volatile int *lock, const char *method, int (*distPtr)(int, int, int)); double kmerQuery(int Ni, int Nj, int D); double kmerTemplate(int Ni, int Nj, int D); double kmerAvg(int Ni, int Nj, int D); double kmerInvAvg(int Ni, int Nj, int D); double kmerJaccardDist(int Ni, int Nj, int D); double kmerJaccardSim(int Ni, int Nj, int D); double kmerCosineDist(int Ni, int Nj, int D); double kmerCosineSim(int Ni, int Nj, int D); double kmerOverlapCoef(int Ni, int Nj, int D); double kmerInvOverlapCoef(int Ni, int Nj, int D); void printDoublePhy(char *outfile, Matrix *Dist, int *N, FILE *name_file, Qseqs *template_name, unsigned format, const char *formatString, int ltd, int thread_num, volatile int *lock, const char *method, double (*distPtr)(int, int, int)); long unsigned getPhySize(int flag, int format, long unsigned n, long unsigned *ltdMat, long unsigned *covMat, FILE *name_file); char * mfile(FILE *outfile, long unsigned size); void * threadDist(void *arg); void runDist(char *templatefilename, char *outputfilename, int flag, int format, int disk, int thread_num); int dist_main(int argc, char *argv[]); genomicepidemiology-kma-091b8ffe66ac/decon.c0000644000175000017500000001227414157033525020353 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "compdna.h" #include "decon.h" #include "filebuff.h" #include "hashmapkma.h" #include "pherror.h" #include "seqparse.h" #include "stdnuc.h" #include "qseqs.h" #include "updateindex.h" int (*deConNode_ptr)(CompDNA *, HashMapKMA *, unsigned **); int (*addCont)(HashMapKMA *, long unsigned, int, unsigned **); int hashMap_addCont(HashMapKMA *dest, long unsigned key, int value, unsigned **Values) { unsigned pos, kpos, *values; long unsigned kmer; kpos = key & dest->size; pos = getExistPtr(dest->exist, kpos); if(pos != dest->null_index) { kmer = getKeyPtr(dest->key_index, pos); while(key != kmer) { ++pos; if(kpos != (kmer & dest->size)) { return 0; } kmer = getKeyPtr(dest->key_index, pos); } values = updateValuePtr(Values[getValueIndexPtr(dest->value_index, pos)], value); if(values) { Values[getValueIndexPtr(dest->value_index, pos)] = values; return 1; } } return 0; } int megaMap_addCont(HashMapKMA *dest, long unsigned index, int value, unsigned **Values) { long unsigned pos; unsigned *values; if((pos = getExistPtr(dest->exist, index)) != dest->n) { values = updateValuePtr(Values[pos], value); if(values) { Values[pos] = values; return 1; } } return 0; } int deConNode(CompDNA *qseq, HashMapKMA *finalDB, unsigned **Values) { int i, j, end, mapped_cont, shifter, DB_size; if(qseq->seqlen < finalDB->kmersize) { return 0; } DB_size = finalDB->DB_size; mapped_cont = 0; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (finalDB->kmersize << 1); qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - finalDB->kmersize + 1; for(;j < end; ++j) { mapped_cont += addCont(finalDB, getKmer(qseq->seq, j, shifter), DB_size, Values); } j = qseq->N[i] + 1; } qseq->N[0]--; return mapped_cont; } int deConNode_sparse(CompDNA *qseq, HashMapKMA *finalDB, unsigned **Values) { int i, j, end, mapped_cont, prefix_len, prefix_shifter, shifter, DB_size; long unsigned prefix; if(qseq->seqlen < finalDB->kmersize) { return 0; } DB_size = finalDB->DB_size; prefix = finalDB->prefix; prefix_len = finalDB->prefix_len; prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (prefix_len << 1); shifter = sizeof(long unsigned) * sizeof(long unsigned) - (finalDB->kmersize << 1); mapped_cont = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - prefix_len - finalDB->kmersize + 1; for(;j < end; ++j) { if(prefix_len == 0 || getKmer(qseq->seq, j, prefix_shifter) == prefix) { mapped_cont += addCont(finalDB, getKmer(qseq->seq, j + prefix_len, shifter), DB_size, Values); } } j = qseq->N[i] + 1; } qseq->N[0]--; return mapped_cont; } unsigned deConDB(HashMapKMA *finalDB, char **inputfiles, int fileCount, char *trans, unsigned **Values) { int FASTQ; unsigned fileCounter, mapped_cont; char *filename; Qseqs *header, *qseq; FileBuff *inputfile; CompDNA *compressor; /* allocate */ compressor = smalloc(sizeof(CompDNA)); allocComp(compressor, 1024); header = setQseqs(1024); qseq = setQseqs(1024); inputfile = setFileBuff(1024 * 1024); /* set variables */ mapped_cont = 0; if(--finalDB->size == finalDB->mask) { addCont = &megaMap_addCont; } /* iterate inputfiles */ for(fileCounter = 0; fileCounter < fileCount; ++fileCounter) { /* open file */ filename = inputfiles[fileCounter]; /* determine filetype and open it */ if((FASTQ = openAndDetermine(inputfile, filename)) & 3) { fprintf(stderr, "%s\t%s\n", "# Reading inputfile: ", filename); /* parse the file */ while(FileBuffgetFsa(inputfile, header, qseq, trans)) { fprintf(stderr, "# Decon:\t%s\n", header->seq + 1); if(qseq->len > finalDB->kmersize) { /* compress DNA */ if(qseq->len >= compressor->size) { freeComp(compressor); allocComp(compressor, qseq->len); } compDNAref(compressor, qseq->seq, qseq->len); /* Add contamination */ mapped_cont += deConNode_ptr(compressor, finalDB, Values); /* rc */ comp_rc(compressor); mapped_cont += deConNode_ptr(compressor, finalDB, Values); } } /* close file buffer */ if(FASTQ & 4) { gzcloseFileBuff(inputfile); } else { closeFileBuff(inputfile); } } } ++finalDB->size; /* clean */ freeComp(compressor); free(compressor); destroyQseqs(header); destroyQseqs(qseq); destroyFileBuff(inputfile); return mapped_cont; } genomicepidemiology-kma-091b8ffe66ac/nw.h0000644000175000017500000000373414157033525017715 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "penalties.h" #ifndef NWLOAD typedef struct nWmat NWmat; typedef struct alnScore AlnScore; typedef struct aln Aln; struct nWmat { long NW_s; long NW_q; unsigned char *E; int *D[2]; int *P[2]; Penalties *rewards; }; struct alnScore { int score; int len; int pos; int match; int tGaps; int qGaps; }; struct aln { unsigned char *t; /* template */ char *s; /* score */ unsigned char *q; /* query */ unsigned pos; /* start of aln, relative to template */ int len; unsigned mapQ; /* mapping quality */ int score; /* aln score */ int start; int end; }; #define NWLOAD 1 #endif AlnScore NW(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, Aln *aligned, NWmat *matrices, int template_length); AlnScore NW_band(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, Aln *aligned, int band, NWmat *matrices, int template_length); AlnScore NW_score(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, NWmat *matrices, int template_length); AlnScore NW_band_score(const long unsigned *template, const unsigned char *queryOrg, int k, int t_s, int t_e, int q_s, int q_e, int band, NWmat *matrices, int template_length); genomicepidemiology-kma-091b8ffe66ac/hashmapindex.c0000644000175000017500000002477214157033525021742 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "hashmapindex.h" #include "pherror.h" #include "stdnuc.h" #ifndef _WIN32 #include #include #include #else typedef int key_t; #define ftok(charPtr, integer) (0) #define shmget(key, size, permission) ((size != 0) ? (-1) : (-key)) #define shmat(shmid, NULL_Ptr, integer) (NULL) #endif #define murmur(index, kmer) index = (3323198485ul ^ kmer) * 0x5bd1e995; index ^= index >> 15; void (*destroyPtr)(HashMap_index *) = &alignClean; HashMap_index * (*alignLoadPtr)(HashMap_index *, int, int, int, int, long unsigned, long unsigned) = &alignLoad_fly; int hashMap_index_initialize(HashMap_index *dest, int len, int kmerindex) { long unsigned size; dest->len = len; dest->kmerindex = kmerindex; /* convert to 2 times nearest power of 2 */ size = (len << 1) - 1; size |= size >> 1; size |= size >> 2; size |= size >> 4; size |= size >> 8; size |= size >> 16; size |= size >> 32; if(dest->size < size) { if(dest->size) { free(dest->index); free(dest->seq); } dest->size = size++; dest->index = calloc(size, sizeof(int)); dest->seq = malloc(((len >> 5) + 1) * sizeof(long unsigned)); if(!dest->index || !dest->seq) { ERROR(); } return 0; } return 1; } void hashMap_index_set(HashMap_index *dest) { memset(dest->index, -1, (dest->size + 1) * sizeof(int)); memset(dest->seq, 0, ((dest->len >> 5) + 1) * sizeof(long unsigned)); } void hashMap_index_destroy(HashMap_index *dest) { if(dest->index) { free(dest->index); } if(dest->seq) { free(dest->seq); } } int hashMap_index_get(const HashMap_index *dest, long unsigned key, unsigned shifter) { unsigned index; int pos; murmur(index, key); index &= dest->size; while(index < dest->size && (pos = dest->index[index]) != 0) { if(getKmer(dest->seq, abs(pos) - 1, shifter) == key) { return pos; } ++index; } if(index == dest->size) { for(index = 0; (pos = dest->index[index]) != 0; ++index) { if(getKmer(dest->seq, abs(pos) - 1, shifter) == key) { return pos; } } } return 0; } int hashMap_index_get_bound(const HashMap_index *dest, long unsigned key, int min, int max, unsigned shifter) { unsigned index; int pos; murmur(index, key); index &= dest->size; while(index < dest->size && (pos = dest->index[index]) != 0) { if(min < abs(pos) && abs(pos) < max && getKmer(dest->seq, abs(pos) - 1, shifter) == key) { return pos; } ++index; } if(index == dest->size) { for(index = 0; (pos = dest->index[index]) != 0; ++index) { if(min < abs(pos) && abs(pos) < max && getKmer(dest->seq, abs(pos) - 1, shifter) == key) { return pos; } } } return 0; } int hashMap_index_getDubPos(const HashMap_index *dest, long unsigned key, int value, unsigned shifter) { unsigned index; int pos; murmur(index, key); index &= dest->size; while(index < dest->size && (pos = dest->index[index]) != 0) { if(pos == value) { return index; } ++index; } if(index == dest->size) { for(index = 0; (pos = dest->index[index]) != 0; ++index) { if(pos == value) { return index; } } } return -1; } int hashMap_index_getNextDubPos(const HashMap_index *dest, long unsigned key, int min, int max, unsigned index, unsigned shifter) { int pos; min = -min; max = -max; while(++index < dest->size && (pos = dest->index[index]) != 0) { if(max < pos && pos < min && getKmer(dest->seq, -pos - 1, shifter) == key) { return index; } } if(index == dest->size) { for(index = 0; (pos = dest->index[index]) != 0; ++index) { if(max < pos && pos < min && getKmer(dest->seq, -pos - 1, shifter) == key) { return index; } } } return -1; } void hashMap_index_add(HashMap_index *dest, long unsigned key, int newpos, unsigned shifter) { int pos, neg; unsigned index; if(key == 0) { /* likely undefined region */ return; } neg = 1; ++newpos; murmur(index, key); index &= dest->size; while(index < dest->size && (pos = dest->index[index]) != 0) { if(pos > 0) { if(getKmer(dest->seq, pos - 1, shifter) == key) { dest->index[index] = -pos; neg = -1; } } else { if(getKmer(dest->seq, -pos - 1, shifter) == key) { neg = -1; } } ++index; } if(index == dest->size) { for(index = 0; (pos = dest->index[index]) != 0; ++index) { if(pos > 0) { if(getKmer(dest->seq, pos - 1, shifter) == key) { dest->index[index] = -pos; neg = -1; } } else { if(getKmer(dest->seq, -pos - 1, shifter) == key) { neg = -1; } } } } if(index < dest->size) { dest->index[index] = neg * newpos; } } void hashMapIndex_add(HashMap_index *dest, long unsigned key, int newpos) { int index, pos, neg, shifter; neg = 1; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (dest->kmerindex << 1); ++newpos; murmur(index, key); index &= dest->size; while(index < dest->size && (pos = dest->index[index]) != 0) { if(pos > 0) { if(getKmer(dest->seq, pos - 1, shifter) == key) { dest->index[index] = -pos; neg = -1; } } else { if(getKmer(dest->seq, -pos - 1, shifter) == key) { neg = -1; } } ++index; } if(index == dest->size) { for(index = 0; (pos = dest->index[index]) != 0; ++index) { if(pos > 0) { if(getKmer(dest->seq, pos - 1, shifter) == key) { dest->index[index] = -pos; neg = -1; } } else { if(getKmer(dest->seq, -pos - 1, shifter) == key) { neg = -1; } } } } if(index < dest->size) { dest->index[index] = neg * newpos; } } HashMap_index * hashMap_index_load(HashMap_index *src, int seq, int index, int len, int kmersize) { if(src == 0) { src = smalloc(sizeof(HashMap_index)); src->size = 0; } if(hashMap_index_initialize(src, len, kmersize)) { src->size = len << 1; } read(seq, src->seq, ((src->len >> 5) + 1) * sizeof(long unsigned)); read(index, src->index, src->size * sizeof(int)); return src; } void hashMap_index_dump(HashMap_index *src, FILE *seq, FILE *index) { cfwrite(src->seq, sizeof(long unsigned), (src->len >> 5) + 1, seq); cfwrite(src->index, sizeof(int), src->size, index); } HashMap_index * hashMap_index_build(HashMap_index *src, int seq, int len, int kmersize) { int i, end, shifter; if(src == 0) { src = smalloc(sizeof(HashMap_index)); src->size = 0; } if(hashMap_index_initialize(src, len, kmersize)) { memset(src->index, 0, src->size * sizeof(int)); } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (src->kmerindex << 1); read(seq, src->seq, ((src->len >> 5) + 1) * sizeof(long unsigned)); end = len - kmersize + 1; for(i = 0; i < end; ++i) { hashMap_index_add(src, getKmer(src->seq, i, shifter), i, shifter); } return src; } HashMap_index * alignLoad_fly(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index) { /* move file pointer */ lseek(index_in, index_index, SEEK_SET); lseek(seq_in, seq_index, SEEK_SET); return hashMap_index_load(dest, seq_in, index_in, len, kmersize); } HashMap_index * alignLoad_fly_mem(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index) { return hashMap_index_load(dest, seq_in, index_in, len, kmersize); } HashMap_index * alignLoad_fly_build(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index) { /* move file pointer */ lseek(seq_in, seq_index, SEEK_SET); return hashMap_index_build(dest, seq_in, len, kmersize); } HashMap_index * alignLoad_fly_build_mem(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index) { return hashMap_index_build(dest, seq_in, len, kmersize); } HashMap_index * alignLoad_skip(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index) { dest->len = len; dest->kmerindex = kmersize; return dest; } HashMap_index * alignLoad_fly_shm(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index) { static HashMap_index *src = 0; if(kmersize == 0) { if(src == 0) { src = smalloc(sizeof(HashMap_index)); } src->seq = dest->seq; src->index = dest->index; } else { dest->len = len; dest->size = len << 1; dest->kmerindex = kmersize; dest->seq = src->seq + (seq_index / sizeof(long unsigned)); dest->index = src->index + ((index_index - sizeof(int)) / sizeof(int)); } return dest; } HashMap_index * alignLoad_shm_initial(char *templatefilename, int file_len, int seq_in, int index_in, int kmersize) { key_t key; int shmid; HashMap_index *dest; long unsigned size; dest = smalloc(sizeof(HashMap_index)); dest->len = 0; dest->size = 0; dest->kmerindex = kmersize; templatefilename[file_len] = 0; strcat(templatefilename, ".index.b"); key = ftok(templatefilename, 'i'); read(index_in, &kmersize, sizeof(int)); size = lseek(index_in, 0, SEEK_END) - sizeof(int); shmid = shmget(key, size, 0666); if(shmid < 0) { fprintf(stderr, "SHM error i.\n"); exit(1); } else { dest->index = shmat(shmid, NULL, 0); } templatefilename[file_len] = 0; strcat(templatefilename, ".seq.b"); key = ftok(templatefilename, 's'); size = lseek(seq_in, 0, SEEK_END); shmid = shmget(key, size, 0666); if(shmid < 0) { fprintf(stderr, "SHM error s.\n"); exit(1); } else { dest->seq = shmat(shmid, NULL, 0); } lseek(seq_in, 0, SEEK_SET); templatefilename[file_len] = 0; return alignLoad_fly_shm(dest, 0, 0, 0, 0, 0, 0); } void alignClean(HashMap_index *template_index) { /* Overwrite later */ /* if(template_index) { hashMap_index_destroy(template_index); } */ } void alignClean_shm(HashMap_index *template_index) { if(template_index) { template_index->seq = 0; template_index->index = 0; } } genomicepidemiology-kma-091b8ffe66ac/updateindex.h0000644000175000017500000000346514157033525021604 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "compdna.h" #include "hashmap.h" extern int (*update_DB)(HashMap *, CompDNA *, unsigned, int, double, double, unsigned *, unsigned *, Qseqs *); extern void (*updateAnnotsPtr)(CompDNA *, int, int, FILE *, unsigned **, unsigned **, unsigned **); int updateDBs(HashMap *templates, CompDNA *qseq, unsigned template, int MinKlen, double homQ, double homT, unsigned *template_ulengths, unsigned *template_slengths, Qseqs *header); int updateDBs_sparse(HashMap *templates, CompDNA *qseq, unsigned template, int MinKlen, double homQ, double homT, unsigned *template_ulengths, unsigned *template_slengths, Qseqs *header); void updateAnnots(CompDNA *qseq, int DB_size, int kmerindex, FILE *seq_out, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths); void updateAnnots_sparse(CompDNA *qseq, int DB_size, int kmerindex, FILE *seq_out, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths); void dumpSeq(CompDNA *qseq, int kmerindex, FILE *seq_out); void makeIndexing(CompDNA *compressor, int kmerindex, FILE *seq_out); genomicepidemiology-kma-091b8ffe66ac/alnfrags.c0000644000175000017500000011603614157033525021061 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "align.h" #include "alnfrags.h" #include "ankers.h" #include "chain.h" #include "compdna.h" #include "frags.h" #include "filebuff.h" #include "hashmapcci.h" #include "pherror.h" #include "qseqs.h" #include "sam.h" #include "stdnuc.h" #include "stdstat.h" #include "threader.h" #include "updatescores.h" #define mrcheck(mrc, Stat, q_len, t_len) ((mrc * q_len <= Stat.len - Stat.qGaps) || (mrc * t_len <= Stat.len - Stat.tGaps)) int (*alnFragsPE)(HashMapCCI**, int*, int*, int, double, double, int, CompDNA*, CompDNA*, CompDNA*, CompDNA*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, Qseqs*, Qseqs*, int, int*, int*, long unsigned*, long unsigned*, int*, int*, int*, int*, int*, int*, int, long*, FILE*, AlnPoints*, NWmat*, volatile int*, volatile int*) = alnFragsUnionPE; int alnFragsSE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, int rc_flag, CompDNA *qseq_comp, CompDNA *qseq_r_comp, unsigned char *qseq, unsigned char *qseq_r, int q_len, int kmersize, Qseqs *header, int *bestTemplates, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *best_read_score, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB) { int t_i, template, read_score, bestHits, aln_len, start, end, W1, arc, rc; int q_start, q_end, t_len, *qBoundPtr; double score, bestScore; AlnScore alnStat; /* reverse complement seq */ if(rc_flag < 0) { if(qseq_r_comp->size < qseq_comp->size) { freeComp(qseq_r_comp); allocComp(qseq_r_comp, qseq_comp->size); } rc_comp(qseq_comp, qseq_r_comp); unCompDNA(qseq_r_comp, qseq_r); qseq_r_comp->N[0]++; qseq_r_comp->N[qseq_r_comp->N[0]] = q_len; } unCompDNA(qseq_comp, qseq); qseq_comp->N[0]++; qseq_comp->N[qseq_comp->N[0]] = q_len; bestScore = 0; *best_read_score = 0; bestHits = 0; W1 = NWmatrices->rewards->W1; arc = points->len; points->len = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { template = matched_templates[t_i]; /* check if index DB is loaded */ lock(excludeDB); if(template >= 0 && templates_index[template] == 0) { templates_index[template] = alignLoadPtr(templates_index[template], seq_in, template_lengths[template], kmersize, seq_indexes[template]); } else if(template < 0 && templates_index[-template] == 0) { templates_index[-template] = alignLoadPtr(templates_index[-template], seq_in, template_lengths[-template], kmersize, seq_indexes[-template]); } unlock(excludeDB); /* q-bound */ if(2 * sizeof(int) + 1 < header->len && header->seq[header->len - 2 * sizeof(int) - 1] == 0) { qBoundPtr = (int*) (header->seq + (header->len - 2 * sizeof(int))); q_start = *qBoundPtr; q_end = *++qBoundPtr; } else { q_start = 0; q_end = q_len; } /* check ankers */ if(arc) { rc = anker_rc_comp(templates_index[abs(template)], qseq, qseq_r, qseq_comp, qseq_r_comp, q_start, q_end, points); if(rc < 0) { if(0 < template) { template = -template; } alnStat = KMA_score(templates_index[-template], qseq_r, q_len, q_len - q_end, q_len - q_start, qseq_r_comp, mq, scoreT, points, NWmatrices); } else if(rc) { alnStat = KMA_score(templates_index[abs(template)], qseq, q_len, q_start, q_end, qseq_comp, mq, scoreT, points, NWmatrices); } else { alnStat.score = 0; alnStat.pos = 0; alnStat.len = 0; alnStat.tGaps = 0; alnStat.qGaps = 0; points->len = 0; } } else { if(template < 0) { alnStat = KMA_score(templates_index[-template], qseq_r, q_len, q_len - q_end, q_len - q_start, qseq_r_comp, mq, scoreT, points, NWmatrices); } else { alnStat = KMA_score(templates_index[template], qseq, q_len, q_start, q_end, qseq_comp, mq, scoreT, points, NWmatrices); } } /* get read score */ aln_len = alnStat.len; start = alnStat.pos; end = start + aln_len - alnStat.tGaps; t_len = template_lengths[abs(template)]; if(template_lengths[abs(template)] < end && mrcheck(mrc, alnStat, q_len, t_len)) { end -= template_lengths[abs(template)]; } /* penalty for non complete mapping */ read_score = alnStat.score; /* full gene award */ if((start == 0) && (end == t_len)) { read_score += abs(W1); } //read_score += (((start != 0) + (end != template_lengths[abs(template)])) * W1); /* Get normed score */ if(minlen <= aln_len) { score = 1.0 * read_score / aln_len; } else { read_score = 0; score = 0; } /* save best match(es) */ if(read_score > kmersize && score >= scoreT) { if(score > bestScore) { // save as best match bestScore = score; *best_read_score = read_score; *bestTemplates = template; *best_start_pos = start; *best_end_pos = end; bestHits = 1; } else if(score == bestScore && read_score > *best_read_score) { // save as best match bestScore = score; *best_read_score = read_score; *bestTemplates = template; *best_start_pos = start; *best_end_pos = end; bestHits = 1; } else if(score == bestScore && read_score == *best_read_score) { // update best match bestTemplates[bestHits] = template; best_start_pos[bestHits] = start; best_end_pos[bestHits] = end; ++bestHits; } } } if(*best_read_score > kmersize) { lock(excludeOut); update_Scores(qseq, q_len, bestHits, *best_read_score, best_start_pos, best_end_pos, bestTemplates, header, *flag, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); return 0; } else { *flag |= 4; } return 1; } int alnFragsUnionPE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, CompDNA *qseq_comp, CompDNA *qseq_r_comp, CompDNA *qseq_fr_comp, CompDNA *qseq_rr_comp, unsigned char *qseq, unsigned char *qseq_r, unsigned char *qseq_fr, unsigned char *qseq_rr, Qseqs *header, Qseqs *header_r, int kmersize, int *bestTemplates, int *bestTemplates_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *flag_r, int *best_read_score, int *best_read_score_r, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB) { int t_i, template, read_score, W1; int compScore, bestHits, bestHits_r, aln_len, start, end, t_len, arc, rc; double score; AlnScore alnStat; /* unpack qseqs */ unCompDNA(qseq_comp, qseq); qseq_comp->N[0]++; qseq_comp->N[qseq_comp->N[0]] = qseq_comp->seqlen; unCompDNA(qseq_r_comp, qseq_r); qseq_r_comp->N[0]++; qseq_r_comp->N[qseq_r_comp->N[0]] = qseq_r_comp->seqlen; if((arc = points->len)) { qseq_fr_comp->N[0]++; qseq_fr_comp->N[qseq_fr_comp->N[0]] = qseq_fr_comp->seqlen; qseq_rr_comp->N[0]++; qseq_rr_comp->N[qseq_rr_comp->N[0]] = qseq_rr_comp->seqlen; points->len = 0; } W1 = NWmatrices->rewards->W1; start = 0; end = 0; score = 0; *best_read_score = 0; *best_read_score_r = 0; compScore = 0; bestHits = 0; rc = 1; for(t_i = 1; t_i <= *matched_templates; ++t_i) { template = matched_templates[t_i]; /* check if index DB is loaded, and rc */ if(template < 0) { if(rc) { qseq_comp->N[0]--; comp_rc(qseq_comp); qseq_comp->N[0]++; qseq_r_comp->N[0]--; comp_rc(qseq_r_comp); qseq_r_comp->N[0]++; strrc(qseq, qseq_comp->seqlen); strrc(qseq_r, qseq_r_comp->seqlen); rc = 0; } } lock(excludeDB); if(0 <= template && templates_index[template] == 0) { templates_index[template] = alignLoadPtr(templates_index[template], seq_in, template_lengths[template], kmersize, seq_indexes[template]); } else if(template < 0 && templates_index[-template] == 0) { templates_index[-template] = alignLoadPtr(templates_index[-template], seq_in, template_lengths[-template], kmersize, seq_indexes[-template]); } unlock(excludeDB); /* align qseqs */ template = abs(template); if(arc) { rc = anker_rc_comp(templates_index[template], qseq, qseq_fr, qseq_comp, qseq_fr_comp, 0, qseq_comp->seqlen, points); if(rc < 0) { /* rc */ alnStat = KMA_score(templates_index[template], qseq_fr, qseq_fr_comp->seqlen, 0, qseq_fr_comp->seqlen, qseq_fr_comp, mq, scoreT, points, NWmatrices); } else if(rc) { /* forward */ matched_templates[t_i] = -matched_templates[t_i]; alnStat = KMA_score(templates_index[template], qseq, qseq_comp->seqlen, 0, qseq_comp->seqlen, qseq_comp, mq, scoreT, points, NWmatrices); } else { alnStat.score = 0; alnStat.pos = 0; alnStat.len = 0; alnStat.tGaps = 0; alnStat.qGaps = 0; points->len = 0; } } else { alnStat = KMA_score(templates_index[template], qseq, qseq_comp->seqlen, 0, qseq_comp->seqlen, qseq_comp, mq, scoreT, points, NWmatrices); } /* get read score */ aln_len = alnStat.len; read_score = alnStat.score; t_len = template_lengths[abs(template)]; if(minlen <= aln_len && 0 < read_score && mrcheck(mrc, alnStat, qseq_comp->seqlen, t_len)) { start = alnStat.pos; end = alnStat.pos + alnStat.len - alnStat.tGaps; if(start == 0 && end == t_len) { read_score += abs(W1); } score = 1.0 * read_score / aln_len; } else { read_score = 0; } /* save best match(es) */ if(read_score > kmersize && score >= scoreT && *best_read_score <= read_score) { *best_read_score = read_score; bestTemplates[t_i] = read_score; best_start_pos[t_i] = start; best_end_pos[t_i] = end; } else { bestTemplates[t_i] = 0; best_start_pos[t_i] = -1; best_end_pos[t_i] = -1; } /* align qseqs */ template = abs(template); if(arc) { if(rc < 0) { /* rc */ alnStat = KMA_score(templates_index[template], qseq_rr, qseq_rr_comp->seqlen, 0, qseq_rr_comp->seqlen, qseq_rr_comp, mq, scoreT, points, NWmatrices); } else if(rc) { /* forward */ alnStat = KMA_score(templates_index[template], qseq_r, qseq_r_comp->seqlen, 0, qseq_r_comp->seqlen, qseq_r_comp, mq, scoreT, points, NWmatrices); } else { alnStat.score = 0; alnStat.pos = 0; alnStat.len = 0; alnStat.tGaps = 0; alnStat.qGaps = 0; } rc = 1; } else { alnStat = KMA_score(templates_index[template], qseq_r, qseq_r_comp->seqlen, 0, qseq_r_comp->seqlen, qseq_r_comp, mq, scoreT, points, NWmatrices); } /* get read score */ aln_len = alnStat.len; read_score = alnStat.score; if(minlen <= aln_len && 0 < read_score && mrcheck(mrc, alnStat, qseq_r_comp->seqlen, t_len)) { start = alnStat.pos; end = alnStat.pos + alnStat.len - alnStat.tGaps; if(start == 0 && end == t_len) { read_score += abs(W1); } score = 1.0 * read_score / aln_len; } else { read_score = 0; } /* save best match(es) */ if(read_score > kmersize && score >= scoreT && *best_read_score_r <= read_score) { *best_read_score_r = read_score; bestTemplates_r[t_i] = read_score; if(bestTemplates[t_i]) { /* Handle negative insertsizes caused by trimming, user stupidity or sample error. */ if(start < best_start_pos[t_i]) { best_start_pos[t_i] = start; } else { best_end_pos[t_i] = end; } } else { best_start_pos[t_i] = start; best_end_pos[t_i] = end; } } else { bestTemplates_r[t_i] = 0; if(bestTemplates[t_i] != 0) { best_start_pos[t_i] = -1; best_end_pos[t_i] = -1; } } read_score += bestTemplates[t_i]; if(best_start_pos[t_i] == 0 && best_end_pos[t_i] == t_len) { read_score += abs(W1); } if(compScore < read_score) { compScore = read_score; } } /* get rc flag */ if(arc) { rc = 0; for(t_i = 1; t_i <= *matched_templates && !rc; ++t_i) { rc = matched_templates[t_i] < 0; } } if(*best_read_score && *best_read_score_r) { /* both matched */ if(compScore && compScore == (*best_read_score + *best_read_score_r)) { /* proper pair */ bestHits = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(compScore == (bestTemplates[t_i] + bestTemplates_r[t_i])) { bestTemplates[bestHits] = matched_templates[t_i]; best_start_pos[bestHits] = best_start_pos[t_i]; best_end_pos[bestHits] = best_end_pos[t_i]; ++bestHits; } } /* check direction of qseqs */ if(*bestTemplates < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates[t_i] = -bestTemplates[t_i]; } lock(excludeOut); update_Scores_pe(qseq_r, qseq_r_comp->seqlen, qseq, qseq_comp->seqlen, bestHits, compScore, best_start_pos, best_end_pos, bestTemplates, header_r, header, *flag_r, *flag, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } else { if(!rc) { strrc(qseq, qseq_comp->seqlen); strrc(qseq_r, qseq_r_comp->seqlen); *flag ^= 48; *flag_r ^= 48; } lock(excludeOut); update_Scores_pe(qseq, qseq_comp->seqlen, qseq_r, qseq_r_comp->seqlen, bestHits, compScore, best_start_pos, best_end_pos, bestTemplates, header, header_r, *flag, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } } else { /* unmaided pair */ bestHits = 0; bestHits_r = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(bestTemplates[t_i] == *best_read_score) { bestTemplates[bestHits] = matched_templates[t_i]; best_start_pos[bestHits] = best_start_pos[t_i]; best_end_pos[bestHits] = best_end_pos[t_i]; ++bestHits; } else if(bestTemplates_r[t_i] == *best_read_score_r) { bestTemplates_r[bestHits_r] = matched_templates[t_i]; best_start_pos[bestHits_r] = best_start_pos[t_i]; best_end_pos[bestHits_r] = best_end_pos[t_i]; ++bestHits_r; } } /* check direction of qseqs */ if(*bestTemplates < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates[t_i] = -bestTemplates[t_i]; } } else if(!rc) { strrc(qseq, qseq_comp->seqlen); *flag ^= 16; *flag_r ^= 32; } if(*bestTemplates_r < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates_r[t_i] = -bestTemplates_r[t_i]; } } else if(!rc) { strrc(qseq_r, qseq_r_comp->seqlen); *flag ^= 32; *flag_r ^= 16; } if(*flag & 2) { *flag ^= 2; *flag_r ^= 2; } lock(excludeOut); update_Scores(qseq, qseq_comp->seqlen, bestHits, *best_read_score, best_start_pos, best_end_pos, bestTemplates, header, *flag, alignment_scores, uniq_alignment_scores, frag_out_raw); update_Scores(qseq_r, qseq_r_comp->seqlen, bestHits_r, *best_read_score_r, best_start_pos, best_end_pos, bestTemplates_r, header_r, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } return 0; } else if(*best_read_score) { bestHits = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(bestTemplates[t_i] == *best_read_score) { bestTemplates[bestHits] = matched_templates[t_i]; best_start_pos[bestHits] = best_start_pos[t_i]; best_end_pos[bestHits] = best_end_pos[t_i]; ++bestHits; } } /* check direction of qseqs */ if(*bestTemplates < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates[t_i] = -bestTemplates[t_i]; } } else if(!rc) { strrc(qseq, qseq_comp->seqlen); *flag ^= 16; *flag_r ^= 32; } *flag |= 8; *flag_r ^= 4; if(*flag & 2) { *flag ^= 2; *flag_r ^= 2; } lock(excludeOut); update_Scores(qseq, qseq_comp->seqlen, bestHits, *best_read_score, best_start_pos, best_end_pos, bestTemplates, header, *flag, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); return 2; } else if(*best_read_score_r) { bestHits_r = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(bestTemplates_r[t_i] == *best_read_score_r) { bestTemplates_r[bestHits_r] = matched_templates[t_i]; best_start_pos[bestHits_r] = best_start_pos[t_i]; best_end_pos[bestHits_r] = best_end_pos[t_i]; ++bestHits_r; } } /* check direction of qseqs */ if(*bestTemplates_r < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates_r[t_i] = -bestTemplates_r[t_i]; } } else if(!rc) { strrc(qseq_r, qseq_r_comp->seqlen); *flag ^= 32; *flag_r ^= 16; } *flag_r |= 8; *flag ^= 4; if(*flag_r & 2) { *flag ^= 2; *flag_r ^= 2; } lock(excludeOut); update_Scores(qseq_r, qseq_r_comp->seqlen, bestHits_r, *best_read_score_r, best_start_pos, best_end_pos, bestTemplates_r, header_r, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); return 1; } return 3; } int alnFragsPenaltyPE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, CompDNA *qseq_comp, CompDNA *qseq_r_comp, CompDNA *qseq_fr_comp, CompDNA *qseq_rr_comp, unsigned char *qseq, unsigned char *qseq_r, unsigned char *qseq_fr, unsigned char *qseq_rr, Qseqs *header, Qseqs *header_r, int kmersize, int *bestTemplates, int *bestTemplates_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *flag_r, int *best_read_score, int *best_read_score_r, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB) { int t_i, template, read_score, W1, PE; int compScore, bestHits, bestHits_r, aln_len, start, end, t_len, arc, rc; double score; AlnScore alnStat; /* unpack qseqs */ unCompDNA(qseq_comp, qseq); qseq_comp->N[0]++; qseq_comp->N[qseq_comp->N[0]] = qseq_comp->seqlen; unCompDNA(qseq_r_comp, qseq_r); qseq_r_comp->N[0]++; qseq_r_comp->N[qseq_r_comp->N[0]] = qseq_r_comp->seqlen; if((arc = points->len)) { qseq_fr_comp->N[0]++; qseq_fr_comp->N[qseq_fr_comp->N[0]] = qseq_fr_comp->seqlen; qseq_rr_comp->N[0]++; qseq_rr_comp->N[qseq_rr_comp->N[0]] = qseq_rr_comp->seqlen; points->len = 0; } W1 = NWmatrices->rewards->W1; PE = NWmatrices->rewards->PE; start = 0; end = 0; score = 0; *best_read_score = 0; *best_read_score_r = 0; compScore = 0; bestHits = 0; rc = 1; for(t_i = 1; t_i <= *matched_templates; ++t_i) { template = matched_templates[t_i]; /* check if index DB is loaded, and rc */ if(template < 0) { if(rc) { qseq_comp->N[0]--; comp_rc(qseq_comp); qseq_comp->N[0]++; qseq_r_comp->N[0]--; comp_rc(qseq_r_comp); qseq_r_comp->N[0]++; strrc(qseq, qseq_comp->seqlen); strrc(qseq_r, qseq_r_comp->seqlen); rc = 0; } } lock(excludeDB); if(0 <= template && templates_index[template] == 0) { templates_index[template] = alignLoadPtr(templates_index[template], seq_in, template_lengths[template], kmersize, seq_indexes[template]); } else if(template < 0 && templates_index[-template] == 0) { templates_index[-template] = alignLoadPtr(templates_index[-template], seq_in, template_lengths[-template], kmersize, seq_indexes[-template]); } unlock(excludeDB); /* align qseqs */ template = abs(template); if(arc) { rc = anker_rc_comp(templates_index[template], qseq, qseq_fr, qseq_comp, qseq_fr_comp, 0, qseq_comp->seqlen, points); if(rc < 0) { /* rc */ alnStat = KMA_score(templates_index[template], qseq_fr, qseq_fr_comp->seqlen, 0, qseq_fr_comp->seqlen, qseq_fr_comp, mq, scoreT, points, NWmatrices); } else if(rc) { /* forward */ matched_templates[t_i] = -matched_templates[t_i];; alnStat = KMA_score(templates_index[template], qseq, qseq_comp->seqlen, 0, qseq_comp->seqlen, qseq_comp, mq, scoreT, points, NWmatrices); } else { alnStat.score = 0; alnStat.pos = 0; alnStat.len = 0; alnStat.tGaps = 0; alnStat.qGaps = 0; points->len = 0; } } else { alnStat = KMA_score(templates_index[template], qseq, qseq_comp->seqlen, 0, qseq_comp->seqlen, qseq_comp, mq, scoreT, points, NWmatrices); } /* get read score */ aln_len = alnStat.len; read_score = alnStat.score; t_len = template_lengths[abs(template)]; if(minlen <= aln_len && 0 < read_score && mrcheck(mrc, alnStat, qseq_comp->seqlen, t_len)) { start = alnStat.pos; end = alnStat.pos + alnStat.len - alnStat.tGaps; if(start == 0 && end == t_len) { read_score += abs(W1); } score = 1.0 * read_score / aln_len; } else { read_score = 0; } /* save best match(es) */ if(read_score > kmersize && score >= scoreT && *best_read_score <= read_score) { *best_read_score = read_score; bestTemplates[t_i] = read_score; best_start_pos[t_i] = start; best_end_pos[t_i] = end; } else { bestTemplates[t_i] = 0; best_start_pos[t_i] = -1; best_end_pos[t_i] = -1; } if(arc) { if(rc < 0) { /* rc */ alnStat = KMA_score(templates_index[template], qseq_rr, qseq_rr_comp->seqlen, 0, qseq_rr_comp->seqlen, qseq_rr_comp, mq, scoreT, points, NWmatrices); } else if(rc) { /* forward */ alnStat = KMA_score(templates_index[template], qseq_r, qseq_r_comp->seqlen, 0, qseq_r_comp->seqlen, qseq_r_comp, mq, scoreT, points, NWmatrices); } else { alnStat.score = 0; alnStat.pos = 0; alnStat.len = 0; alnStat.tGaps = 0; alnStat.qGaps = 0; } rc = 1; } else { alnStat = KMA_score(templates_index[template], qseq_r, qseq_r_comp->seqlen, 0, qseq_r_comp->seqlen, qseq_r_comp, mq, scoreT, points, NWmatrices); } /* get read score */ aln_len = alnStat.len; read_score = alnStat.score; if(minlen <= aln_len && 0 < read_score && mrcheck(mrc, alnStat, qseq_r_comp->seqlen, t_len)) { start = alnStat.pos; end = alnStat.pos + alnStat.len - alnStat.tGaps; if(start == 0 && end == t_len) { read_score += abs(W1); } score = 1.0 * read_score / aln_len; } else { read_score = 0; } /* save best match(es) */ if(read_score > kmersize && score >= scoreT && *best_read_score_r <= read_score) { *best_read_score_r = read_score; bestTemplates_r[t_i] = read_score; if(bestTemplates[t_i]) { /* Handle negative insertsizes caused by trimming, user stupidity or sample error. */ if(start < best_start_pos[t_i]) { best_start_pos[t_i] = start; } else { best_end_pos[t_i] = end; } } else { best_start_pos[t_i] = start; best_end_pos[t_i] = end; } } else { bestTemplates_r[t_i] = 0; if(bestTemplates[t_i] != 0) { best_start_pos[t_i] = -1; best_end_pos[t_i] = -1; } } read_score += (bestTemplates[t_i] + PE); if(compScore < read_score) { compScore = read_score; } } /* get rc flag */ if(arc) { rc = 0; for(t_i = 1; t_i <= *matched_templates && !rc; ++t_i) { rc = matched_templates[t_i] < 0; } } if(*best_read_score && *best_read_score_r) { /* both matched */ if(compScore && (*best_read_score + *best_read_score_r) <= compScore) { /* proper pair */ compScore -= PE; bestHits = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(compScore == (bestTemplates[t_i] + bestTemplates_r[t_i])) { bestTemplates[bestHits] = matched_templates[t_i]; best_start_pos[bestHits] = best_start_pos[t_i]; best_end_pos[bestHits] = best_end_pos[t_i]; ++bestHits; } } /* check direction of qseqs */ if(*bestTemplates < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates[t_i] = -bestTemplates[t_i]; } lock(excludeOut); update_Scores_pe(qseq_r, qseq_r_comp->seqlen, qseq, qseq_comp->seqlen, bestHits, compScore, best_start_pos, best_end_pos, bestTemplates, header_r, header, *flag_r, *flag, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } else { if(!rc) { strrc(qseq, qseq_comp->seqlen); strrc(qseq_r, qseq_r_comp->seqlen); *flag ^= 48; *flag_r ^= 48; } lock(excludeOut); update_Scores_pe(qseq, qseq_comp->seqlen, qseq_r, qseq_r_comp->seqlen, bestHits, compScore, best_start_pos, best_end_pos, bestTemplates, header, header_r, *flag, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } } else { /* unmaided pair */ bestHits = 0; bestHits_r = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(bestTemplates[t_i] == *best_read_score) { bestTemplates[bestHits] = matched_templates[t_i]; best_start_pos[bestHits] = best_start_pos[t_i]; best_end_pos[bestHits] = best_end_pos[t_i]; ++bestHits; } else if(bestTemplates_r[t_i] == *best_read_score_r) { bestTemplates_r[bestHits_r] = matched_templates[t_i]; best_start_pos[bestHits_r] = best_start_pos[t_i]; best_end_pos[bestHits_r] = best_end_pos[t_i]; ++bestHits_r; } } /* check direction of qseqs */ if(*bestTemplates < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates[t_i] = -bestTemplates[t_i]; } } else if(!rc) { strrc(qseq, qseq_comp->seqlen); *flag ^= 16; *flag_r ^= 32; } if(*bestTemplates_r < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates_r[t_i] = -bestTemplates_r[t_i]; } } else if(!rc) { strrc(qseq_r, qseq_r_comp->seqlen); *flag ^= 32; *flag_r ^= 16; } if(*flag & 2) { *flag ^= 2; *flag_r ^= 2; } lock(excludeOut); update_Scores(qseq, qseq_comp->seqlen, bestHits, *best_read_score, best_start_pos, best_end_pos, bestTemplates, header, *flag, alignment_scores, uniq_alignment_scores, frag_out_raw); update_Scores(qseq_r, qseq_r_comp->seqlen, bestHits_r, *best_read_score_r, best_start_pos, best_end_pos, bestTemplates_r, header_r, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } return 0; } else if(*best_read_score) { bestHits = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(bestTemplates[t_i] == *best_read_score) { bestTemplates[bestHits] = matched_templates[t_i]; best_start_pos[bestHits] = best_start_pos[t_i]; best_end_pos[bestHits] = best_end_pos[t_i]; ++bestHits; } } /* check direction of qseqs */ if(*bestTemplates < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates[t_i] = -bestTemplates[t_i]; } } else if(!rc) { strrc(qseq, qseq_comp->seqlen); *flag ^= 16; *flag_r ^= 32; } *flag |= 8; *flag_r ^= 4; if(*flag & 2) { *flag ^= 2; *flag_r ^= 2; } lock(excludeOut); update_Scores(qseq, qseq_comp->seqlen, bestHits, *best_read_score, best_start_pos, best_end_pos, bestTemplates, header, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); return 2; } else if(*best_read_score_r) { bestHits_r = 0; for(t_i = 1; t_i <= *matched_templates; ++t_i) { if(bestTemplates_r[t_i] == *best_read_score_r) { bestTemplates_r[bestHits_r] = matched_templates[t_i]; best_start_pos[bestHits_r] = best_start_pos[t_i]; best_end_pos[bestHits_r] = best_end_pos[t_i]; ++bestHits_r; } } /* check direction of qseqs */ if(*bestTemplates_r < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates_r[t_i] = -bestTemplates_r[t_i]; } } else if(!rc) { strrc(qseq_r, qseq_r_comp->seqlen); *flag ^= 32; *flag_r ^= 16; } *flag_r |= 8; *flag ^= 4; if(*flag_r & 2) { *flag ^= 2; *flag_r ^= 2; } lock(excludeOut); update_Scores(qseq_r, qseq_r_comp->seqlen, bestHits_r, *best_read_score_r, best_start_pos, best_end_pos, bestTemplates_r, header_r, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); return 1; } return 3; } int alnFragsForcePE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, CompDNA *qseq_comp, CompDNA *qseq_r_comp, CompDNA *qseq_fr_comp, CompDNA *qseq_rr_comp, unsigned char *qseq, unsigned char *qseq_r, unsigned char *qseq_fr, unsigned char *qseq_rr, Qseqs *header, Qseqs *header_r, int kmersize, int *bestTemplates, int *bestTemplates_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *flag_r, int *best_read_score, int *best_read_score_r, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB) { int t_i, template, read_score, bestHits, aln_len, W1, start, end, arc, rc; int t_len; double score, bestScore; AlnScore alnStat, alnStat_r; /* unpack qseqs */ unCompDNA(qseq_comp, qseq); qseq_comp->N[0]++; qseq_comp->N[qseq_comp->N[0]] = qseq_comp->seqlen; unCompDNA(qseq_r_comp, qseq_r); qseq_r_comp->N[0]++; qseq_r_comp->N[qseq_r_comp->N[0]] = qseq_r_comp->seqlen; if((arc = points->len)) { qseq_fr_comp->N[0]++; qseq_fr_comp->N[qseq_fr_comp->N[0]] = qseq_fr_comp->seqlen; qseq_rr_comp->N[0]++; qseq_rr_comp->N[qseq_rr_comp->N[0]] = qseq_rr_comp->seqlen; points->len = 0; } W1 = NWmatrices->rewards->W1; start = 0; end = 0; score = 0; bestScore = 0; *best_read_score = 0; bestHits = 0; rc = 1; for(t_i = 1; t_i <= *matched_templates; ++t_i) { template = matched_templates[t_i]; /* check if index DB is loaded, and rc */ if(template < 0) { if(rc) { qseq_comp->N[0]--; comp_rc(qseq_comp); qseq_comp->N[0]++; qseq_r_comp->N[0]--; comp_rc(qseq_r_comp); qseq_r_comp->N[0]++; strrc(qseq, qseq_comp->seqlen); strrc(qseq_r, qseq_r_comp->seqlen); rc = 0; } } lock(excludeDB); if(0 <= template && templates_index[template] == 0) { templates_index[template] = alignLoadPtr(templates_index[template], seq_in, template_lengths[template], kmersize, seq_indexes[template]); } else if(template < 0 && templates_index[-template] == 0) { templates_index[-template] = alignLoadPtr(templates_index[-template], seq_in, template_lengths[-template], kmersize, seq_indexes[-template]); } unlock(excludeDB); /* align qseqs */ template = abs(template); if(arc) { rc = anker_rc_comp(templates_index[template], qseq, qseq_fr, qseq_comp, qseq_fr_comp, 0, qseq_comp->seqlen, points); if(rc < 0) { /* rc */ alnStat = KMA_score(templates_index[template], qseq_fr, qseq_fr_comp->seqlen, 0, qseq_fr_comp->seqlen, qseq_fr_comp, mq, scoreT, points, NWmatrices); } else if(rc) { /* forward */ matched_templates[t_i] = -matched_templates[t_i];; alnStat = KMA_score(templates_index[template], qseq, qseq_comp->seqlen, 0, qseq_comp->seqlen, qseq_comp, mq, scoreT, points, NWmatrices); } else { alnStat.score = 0; alnStat.pos = 0; alnStat.len = 0; alnStat.tGaps = 0; alnStat.qGaps = 0; points->len = 0; } } else { alnStat = KMA_score(templates_index[template], qseq, qseq_comp->seqlen, 0, qseq_comp->seqlen, qseq_comp, mq, scoreT, points, NWmatrices); } t_len = template_lengths[abs(template)]; if(0 < alnStat.score && minlen <= alnStat.len && mrcheck(mrc, alnStat, qseq_comp->seqlen, t_len)) { if(arc) { if(rc < 0) { /* rc */ alnStat_r = KMA_score(templates_index[template], qseq_rr, qseq_rr_comp->seqlen, 0, qseq_rr_comp->seqlen, qseq_rr_comp, mq, scoreT, points, NWmatrices); } else if(rc) { /* forward */ alnStat_r = KMA_score(templates_index[template], qseq_r, qseq_r_comp->seqlen, 0, qseq_r_comp->seqlen, qseq_r_comp, mq, scoreT, points, NWmatrices); } else { alnStat_r.score = 0; alnStat_r.pos = 0; alnStat_r.len = 0; alnStat_r.tGaps = 0; alnStat_r.qGaps = 0; } rc = 1; } else { alnStat_r = KMA_score(templates_index[template], qseq_r, qseq_r_comp->seqlen, 0, qseq_r_comp->seqlen, qseq_r_comp, mq, scoreT, points, NWmatrices); } /* get read score */ if(0 < alnStat_r.score && minlen <= alnStat_r.len && mrcheck(mrc, alnStat_r, qseq_r_comp->seqlen, t_len)) { aln_len = alnStat.len + alnStat_r.len; /* Handle negative insertsizes caused by trimming, user stupidity or sample error. */ if(alnStat.pos < alnStat_r.pos) { start = alnStat.pos; end = alnStat_r.pos + alnStat_r.len - alnStat_r.tGaps; } else { start = alnStat_r.pos; end = alnStat.pos + alnStat.len - alnStat.tGaps; } read_score = alnStat.score + alnStat_r.score; if(start == 0 && end == t_len) { read_score += abs(W1); } score = 1.0 * read_score / aln_len; } else { read_score = 0; } } else { read_score = 0; } /* save best match(es) */ if(read_score > kmersize && score >= scoreT) { if(score > bestScore) { // save as best match bestScore = score; *best_read_score = read_score; *bestTemplates = matched_templates[t_i]; *best_start_pos = start; *best_end_pos = end; bestHits = 1; } else if(score == bestScore && read_score > *best_read_score) { // save as best match bestScore = score; *best_read_score = read_score; *bestTemplates = matched_templates[t_i]; *best_start_pos = start; *best_end_pos = end; bestHits = 1; } else if(score == bestScore && read_score == *best_read_score) { // update best match bestTemplates[bestHits] = matched_templates[t_i]; best_start_pos[bestHits] = start; best_end_pos[bestHits] = end; ++bestHits; } } } /* get rc flag */ if(arc) { rc = 0; for(t_i = 1; t_i <= *matched_templates && !rc; ++t_i) { rc = matched_templates[t_i] < 0; } } if((*best_read_score_r = *best_read_score)) { /* check direction of qseqs */ if(*bestTemplates < 0) { for(t_i = 0; t_i < bestHits; ++t_i) { bestTemplates[t_i] = -bestTemplates[t_i]; } lock(excludeOut); update_Scores_pe(qseq_r, qseq_r_comp->seqlen, qseq, qseq_comp->seqlen, bestHits, *best_read_score, best_start_pos, best_end_pos, bestTemplates, header_r, header, *flag_r, *flag, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } else { if(!rc) { strrc(qseq, qseq_comp->seqlen); strrc(qseq_r, qseq_r_comp->seqlen); *flag ^= 48; *flag_r ^= 48; } lock(excludeOut); update_Scores_pe(qseq, qseq_comp->seqlen, qseq_r, qseq_r_comp->seqlen, bestHits, *best_read_score, best_start_pos, best_end_pos, bestTemplates, header, header_r, *flag, *flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); unlock(excludeOut); } } return 3; } void * alnFrags_threaded(void * arg) { static volatile int Lock[3] = {0, 0, 0}; volatile int *excludeIn = &Lock[0], *excludeOut = &Lock[1], *excludeDB = &Lock[2]; Aln_thread *thread = arg; int rc_flag, read_score, delta, seq_in, kmersize, minlen; int flag, flag_r, mq, sam, unmapped, best_read_score, stats[2]; int *matched_templates, *bestTemplates, *bestTemplates_r; int *template_lengths, *best_start_pos, *best_end_pos; long *seq_indexes; long unsigned *alignment_scores, *uniq_alignment_scores; unsigned char *qseq_fr, *qseq_rr; double scoreT, mrc; FILE *inputfile, *frag_out_raw; FileBuff *frag_out_all; CompDNA *qseq_comp, *qseq_r_comp, *qseq_fr_comp, *qseq_rr_comp; Qseqs *qseq, *qseq_r, *header, *header_r; AlnPoints *points; NWmat *NWmatrices; HashMapCCI **templates_index; /* get input */ matched_templates = thread->matched_templates; bestTemplates = thread->bestTemplates; bestTemplates_r = thread->bestTemplates_r; best_start_pos = thread->best_start_pos; best_end_pos = thread->best_end_pos; alignment_scores = thread->alignment_scores; uniq_alignment_scores = thread->uniq_alignment_scores; seq_indexes = thread->seq_indexes; inputfile = thread->inputfile; frag_out_raw = thread->frag_out_raw; frag_out_all = thread->frag_out_all; seq_in = thread->seq_in; qseq_comp = thread->qseq_comp; qseq_r_comp = thread->qseq_r_comp; qseq = thread->qseq; qseq_r = thread->qseq_r; header = thread->header; header_r = thread->header_r; points = thread->points; NWmatrices = thread->NWmatrices; kmersize = thread->kmersize; minlen = thread->minlen; mq = thread->mq; sam = thread->sam; scoreT = thread->scoreT; mrc = thread->mrc; template_lengths = thread->template_lengths; templates_index = thread->templates_index; qseq_fr_comp = setComp(32); qseq_rr_comp = setComp(32); qseq_fr = smalloc(32); qseq_rr = smalloc(32); delta = qseq->size; read_score = 0; stats[0] = 0; //lock(excludeIn); lockTime(excludeIn, 65536); while((rc_flag = get_ankers(matched_templates, qseq_comp, header, &flag, inputfile)) != 0) { points->len = rc_flag < 0; if(*matched_templates) { // SE read_score = 0; } else { // PE read_score = get_ankers(matched_templates, qseq_r_comp, header_r, &flag_r, inputfile); read_score = labs(read_score); qseq_r->len = qseq_r_comp->seqlen; } unlock(excludeIn); qseq->len = qseq_comp->seqlen; if(delta <= MAX(qseq->len, qseq_r->len)) { delta = MAX(qseq->len, qseq_r->len); delta <<= 1; qseq->size = delta; qseq_r->size = delta; free(qseq->seq); free(qseq_r->seq); qseq->seq = smalloc(delta); qseq_r->seq = smalloc(delta); } if(points->len && read_score) { if(qseq_fr_comp->size < delta) { free(qseq_fr); free(qseq_rr); qseq_fr = smalloc(delta); qseq_rr = smalloc(delta); dallocComp(qseq_fr_comp, delta); dallocComp(qseq_rr_comp, delta); } rc_comp(qseq_comp, qseq_fr_comp); rc_comp(qseq_r_comp, qseq_rr_comp); unCompDNA(qseq_fr_comp, qseq_fr); unCompDNA(qseq_rr_comp, qseq_rr); } if(kmersize <= qseq->len) { if(read_score && kmersize <= qseq_r->len) { // PE unmapped = alnFragsPE(templates_index, matched_templates, template_lengths, mq, scoreT, mrc, minlen, qseq_comp, qseq_r_comp, qseq_fr_comp, qseq_rr_comp, qseq->seq, qseq_r->seq, qseq_fr, qseq_rr, header, header_r, kmersize, bestTemplates, bestTemplates_r, alignment_scores, uniq_alignment_scores, best_start_pos, best_end_pos, &flag, &flag_r, &best_read_score, &read_score, seq_in, seq_indexes, frag_out_raw, points, NWmatrices, excludeOut, excludeDB); } else { // SE unmapped = alnFragsSE(templates_index, matched_templates, template_lengths, mq, scoreT, mrc, minlen, rc_flag, qseq_comp, qseq_r_comp, qseq->seq, qseq_r->seq, qseq->len, kmersize, header, bestTemplates, alignment_scores, uniq_alignment_scores, best_start_pos, best_end_pos, &flag, &best_read_score, seq_in, seq_indexes, frag_out_raw, points, NWmatrices, excludeOut, excludeDB); } } else { unmapped = 0; } if(sam && !(sam & 2096) && unmapped) { if(unmapped & 1) { stats[1] = flag; nibble2base(qseq->seq, qseq->len); samwrite(qseq, header, 0, 0, 0, stats); } if(unmapped & 2) { stats[1] = flag_r; nibble2base(qseq_r->seq, qseq_r->len); samwrite(qseq_r, header_r, 0, 0, 0, stats); } } /* dump seq to all */ if(frag_out_all) { if((unmapped & 1) == 0) { updateAllFrag(qseq->seq, qseq->len, *matched_templates, best_read_score, best_start_pos, best_end_pos, bestTemplates, header, frag_out_all); } if((unmapped & 2) == 0) { updateAllFrag(qseq_r->seq, qseq_r->len, *matched_templates, read_score, best_start_pos, best_end_pos, bestTemplates, header_r, frag_out_all); } } lock(excludeIn); } unlock(excludeIn); destroyComp(qseq_fr_comp); destroyComp(qseq_rr_comp); free(qseq_fr); free(qseq_rr); return NULL; } genomicepidemiology-kma-091b8ffe66ac/printconsensus.c0000644000175000017500000000355114157033525022356 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "assembly.h" #include "printconsensus.h" void printConsensus(Assem *aligned_assem, char *header, FILE *alignment_out, FILE *consensus_out, int ref_fsa) { int i, aln_len, bias; /* print alignment */ aln_len = aligned_assem->len; if(alignment_out) { fprintf(alignment_out, "# %s\n", header); for(i = 0; i < aln_len; i += 60) { fprintf(alignment_out, "%-10s\t%.60s\n", "template:", aligned_assem->t + i); fprintf(alignment_out, "%-10s\t%.60s\n", "", aligned_assem->s + i); fprintf(alignment_out, "%-10s\t%.60s\n\n", "query:", aligned_assem->q + i); } } /* Prepare consensus */ if(ref_fsa == 0) { for(i = 0, bias = 0; i < aln_len; ++i, ++bias) { aligned_assem->q[bias] = aligned_assem->q[i]; if(aligned_assem->q[i] == '-') { --bias; } } aln_len = bias; aligned_assem->q[aln_len] = 0; } else if(ref_fsa == 1) { for(i = 0; i < aln_len; ++i) { if(aligned_assem->q[i] == '-') { aligned_assem->q[i] = 'n'; } } } /* Print consensus */ fprintf(consensus_out, ">%s\n", header); for(i = 0; i < aln_len; i += 60) { fprintf(consensus_out, "%.60s\n", aligned_assem->q + i); } } genomicepidemiology-kma-091b8ffe66ac/runkma.c0000644000175000017500000023212014157033525020552 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include #include "align.h" #include "alnfrags.h" #include "ankers.h" #include "assembly.h" #include "chain.h" #include "compdna.h" #include "ef.h" #include "filebuff.h" #include "frags.h" #include "hashmapcci.h" #include "kmapipe.h" #include "nw.h" #include "penalties.h" #include "pherror.h" #include "printconsensus.h" #include "qseqs.h" #include "runkma.h" #include "sam.h" #include "stdnuc.h" #include "stdstat.h" #include "tmp.h" #include "updatescores.h" #include "vcf.h" #include "xml.h" #ifndef _WIN32 #include #include #include #else typedef int key_t; #define ftok(charPtr, integer) (0) #define shmget(key, size, permission) ((size != 0) ? (-1) : (-key)) #define shmat(shmid, NULL_Ptr, integer) (NULL) #define shmdt(dest) fprintf(stderr, "sysV not available on Windows.\n") #define shmctl(shmid, cmd, buf) fprintf(stderr, "sysV not available on Windows.\n") #endif #define nameSkip(infile, c) while((c = fgetc(infile)) != '\n' && c != EOF) unsigned char * ustrdup(unsigned char *src, size_t n) { unsigned char *dest; dest = smalloc(n); memcpy(dest, src, n); return dest; } int load_DBs_KMA(char *templatefilename, long unsigned **alignment_scores, long unsigned **uniq_alignment_scores, int **template_lengths, unsigned shm) { /* load DBs needed for KMA */ int file_len, shmid, DB_size; FILE *DB_file; key_t key; /* allocate DBs */ file_len = strlen(templatefilename); strcat(templatefilename, ".length.b"); DB_file = sfopen(templatefilename, "rb"); sfread(&DB_size, sizeof(int), 1, DB_file); if(shm & 4) { key = ftok(templatefilename, 'l'); shmid = shmget(key, DB_size * sizeof(int), 0666); if(shmid < 0) { fprintf(stderr, "No shared length\n"); exit(1); } else { *template_lengths = shmat(shmid, NULL, 0); } } else { *template_lengths = smalloc(DB_size * sizeof(int)); /* load lengths */ sfread(*template_lengths, sizeof(int), DB_size, DB_file); } templatefilename[file_len] = 0; fclose(DB_file); /* allocate pointers */ *alignment_scores = calloc(DB_size, sizeof(long unsigned)); *uniq_alignment_scores = calloc(DB_size, sizeof(long unsigned)); if(!*alignment_scores || !*uniq_alignment_scores) { ERROR(); } return DB_size; } char * nameLoad(Qseqs *name, FILE *infile) { int c, size; unsigned char *ptr; ptr = name->seq; size = name->size - 1; while((c = fgetc(infile)) != '\n' && c != EOF) { *ptr++ = c; if(--size == 0) { size = name->size - 1; name->seq = realloc(name->seq, (name->size <<= 1)); if(!name->seq) { ERROR(); } ptr = name->seq + size; } } *ptr = 0; return (char *) name->seq; } int runKMA(char *templatefilename, char *outputfilename, char *exePrev, int ConClave, int kmersize, int minlen, Penalties *rewards, int extendedFeatures, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int ref_fsa, int print_matrix, int print_all, int vcf, int xml, int sam, int nc, int nf, unsigned shm, int thread_num, int verbose) { int i, j, tmp_template, tmp_tmp_template, file_len, bestTemplate, tot; int template, bestHits, t_len, start, end, aln_len, status, rand, sparse; int fragCount, fileCount, maxFrag, coverScore, tmp_start, tmp_end, score; int seq_in_no, DB_size, flag, counter, stats[5]; int *bestTemplates, *bestTemplates_r, *best_start_pos, *best_end_pos; int *matched_templates, *template_lengths; unsigned randScore, *fragmentCounts, *readCounts; long read_score, best_read_score, *seq_indexes; long unsigned Nhits, template_tot_ulen, bestNum, seqin_size; long unsigned *w_scores, *uniq_alignment_scores, *alignment_scores; double tmp_score, bestScore, id, q_id, cover, q_cover, p_value; long double depth, expected, q_value; FILE *inputfile, *frag_in_raw, *res_out, *name_file; FILE *alignment_out, *consensus_out, *frag_out_raw, **template_fragments; FILE *extendedFeatures_out, *xml_out; time_t t0, t1; FileBuff *frag_out, *frag_out_all, *matrix_out, *vcf_out; Aln *aligned, *gap_align; Assem *aligned_assem; Frag **alignFrags, *alignFrag; CompDNA *qseq_comp, *qseq_r_comp; Qseqs *qseq, *qseq_r, *header, *header_r, *template_name; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; Assemble_thread *threads, *thread; Aln_thread *alnThreads, *alnThread; HashMapCCI **templates_index; /* get lengths and names */ file_len = strlen(templatefilename); DB_size = load_DBs_KMA(templatefilename, &alignment_scores, &uniq_alignment_scores, &template_lengths, shm); templatefilename[file_len] = 0; template_name = setQseqs(256); strcat(templatefilename, ".name"); name_file = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; /* print sam-header */ if(sam) { saminit(template_name, name_file, template_lengths, DB_size); } /* open pipe */ status = 0; inputfile = kmaPipe("-s2", "rb", 0, 0); if(!inputfile) { ERROR(); } else { setvbuf(inputfile, NULL, _IOFBF, CHUNK); } /* load databases */ strcat(templatefilename, ".seq.b"); seq_in_no = open(templatefilename, O_RDONLY); if(seq_in_no == -1) { ERROR(); } seqin_size = 4 * lseek(seq_in_no, 0, SEEK_END); if(lseek(seq_in_no, 0, SEEK_SET) != 0) { ERROR(); } templatefilename[file_len] = 0; templates_index = calloc(DB_size, sizeof(HashMapCCI*)); if(!templates_index) { ERROR(); } alignLoadPtr = &alignLoad_fly; if(!kmersize) { kmersize = *template_lengths; } if(kmersize < 4 || 32 < kmersize) { kmersize = 16; } /* allocate stuff */ file_len = strlen(outputfilename); seq_indexes = smalloc((DB_size + 1) * sizeof(long)); /* make file indexes of template indexing */ *seq_indexes = 0; seq_indexes[1] = 0; for(i = 2; i < DB_size; ++i) { seq_indexes[i] = seq_indexes[i - 1] + ((template_lengths[i - 1] >> 5) + 1) * sizeof(long unsigned); } /* open outputfiles */ if(outputfilename) { strcat(outputfilename, ".res"); res_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; if(nf == 0) { strcat(outputfilename, ".frag.gz"); frag_out = gzInitFileBuff(CHUNK); openFileBuff(frag_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { frag_out = 0; } if(nc == 0) { strcat(outputfilename, ".aln"); alignment_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else if(nc == 2) { alignment_out = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else { alignment_out = 0; consensus_out = 0; } frag_out_raw = tmpF(0); if(!frag_out_raw) { ERROR(); } if(print_matrix) { matrix_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".mat.gz"); openFileBuff(matrix_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { matrix_out = 0; } if(print_all) { strcat(outputfilename, ".frag_raw.gz"); frag_out_all = gzInitFileBuff(CHUNK); openFileBuff(frag_out_all, outputfilename, "wb"); outputfilename[file_len] = 0; } else { frag_out_all = 0; } if(vcf) { vcf_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".vcf.gz"); openFileBuff(vcf_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { vcf_out = 0; } } else { fprintf(stderr, " No output file specified!\n"); exit(1); } fprintf(stderr, "# Running KMA.\n"); t0 = clock(); /* allocate stuff */ i = 1; alnThreads = 0; while(i < thread_num) { /* allocate stuff */ matched_templates = smalloc(((DB_size + 1) << 1) * sizeof(int)); bestTemplates = smalloc(((DB_size + 1) << 1) * sizeof(int)); bestTemplates_r = smalloc(((DB_size + 1) << 1) * sizeof(int)); best_start_pos = smalloc((DB_size << 1) * sizeof(int)); best_end_pos = smalloc((DB_size << 1) * sizeof(int)); qseq_comp = smalloc(sizeof(CompDNA)); qseq_r_comp = smalloc(sizeof(CompDNA)); allocComp(qseq_comp, 1024); allocComp(qseq_r_comp, 1024); /* allocate matrcies for NW */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; /* move it to the thread */ alnThread = smalloc(sizeof(Aln_thread)); alnThread->matched_templates = matched_templates; alnThread->bestTemplates = bestTemplates; alnThread->bestTemplates_r = bestTemplates_r; alnThread->best_start_pos = best_start_pos; alnThread->best_end_pos = best_end_pos; alnThread->alignment_scores = alignment_scores; alnThread->uniq_alignment_scores = uniq_alignment_scores; alnThread->seq_indexes = seq_indexes; alnThread->inputfile = inputfile; alnThread->frag_out_raw = frag_out_raw; alnThread->frag_out_all = frag_out_all; alnThread->seq_in = seq_in_no; alnThread->qseq_comp = qseq_comp; alnThread->qseq_r_comp = qseq_r_comp; alnThread->qseq = setQseqs(1024); alnThread->qseq_r = setQseqs(1024); alnThread->header = setQseqs(256); alnThread->header_r = setQseqs(256); alnThread->points = seedPoint_init(1024, rewards); alnThread->NWmatrices = NWmatrices; alnThread->kmersize = kmersize; alnThread->minlen = minlen; alnThread->template_lengths = template_lengths; alnThread->templates_index = templates_index; alnThread->mq = mq; alnThread->sam = sam;//(sam == 1) ? 1 : 0; alnThread->scoreT = scoreT; alnThread->next = alnThreads; alnThreads = alnThread; /* start thread */ if((errno = pthread_create(&alnThread->id, NULL, &alnFrags_threaded, alnThread))) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); fprintf(stderr, "Will continue with %d threads.\n", i); alnThreads = alnThread->next; free(alnThread); i = thread_num; } else { ++i; } } /* allocate stuff */ matched_templates = smalloc(((DB_size + 1) << 1) * sizeof(int)); bestTemplates = smalloc(((DB_size + 1) << 1) * sizeof(int)); bestTemplates_r = smalloc(((DB_size + 1) << 1) * sizeof(int)); best_start_pos = smalloc((DB_size << 1) * sizeof(int)); best_end_pos = smalloc((DB_size << 1) * sizeof(int)); qseq = setQseqs(1024); qseq_r = setQseqs(1024); header = setQseqs(256); header_r = setQseqs(256); qseq_comp = smalloc(sizeof(CompDNA)); qseq_r_comp = smalloc(sizeof(CompDNA)); allocComp(qseq_comp, 1024); allocComp(qseq_r_comp, 1024); points = seedPoint_init(1024, rewards); /* allocate matrcies for NW */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; /* strat main thread */ alnThread = smalloc(sizeof(Aln_thread)); alnThread->matched_templates = matched_templates; alnThread->bestTemplates = bestTemplates; alnThread->bestTemplates_r = bestTemplates_r; alnThread->best_start_pos = best_start_pos; alnThread->best_end_pos = best_end_pos; alnThread->alignment_scores = alignment_scores; alnThread->uniq_alignment_scores = uniq_alignment_scores; alnThread->seq_indexes = seq_indexes; alnThread->inputfile = inputfile; alnThread->frag_out_raw = frag_out_raw; alnThread->frag_out_all = frag_out_all; alnThread->seq_in = seq_in_no; alnThread->qseq_comp = qseq_comp; alnThread->qseq_r_comp = qseq_r_comp; alnThread->qseq = qseq; alnThread->qseq_r = qseq_r; alnThread->header = header; alnThread->header_r = header_r; alnThread->points = points; alnThread->NWmatrices = NWmatrices; alnThread->kmersize = kmersize; alnThread->minlen = minlen; alnThread->mq = mq; alnThread->sam = sam;//(sam == 1) ? 1 : 0; alnThread->scoreT = scoreT; alnThread->template_lengths = template_lengths; alnThread->templates_index = templates_index; alnThread->next = 0; /* Get alignments */ alnFrags_threaded(alnThread); free(alnThread); /* join threads */ for(alnThread = alnThreads; alnThread != 0; alnThread = alnThread->next) { /* join thread */ if((errno = pthread_join(alnThread->id, NULL))) { ERROR(); } } kmaPipe(0, 0, inputfile, &i); status |= i; i = 0; sfwrite(&i, sizeof(int), 1, frag_out_raw); fflush(frag_out_raw); freeComp(qseq_comp); free(qseq_comp); freeComp(qseq_r_comp); free(qseq_r_comp); if(header->size < header_r->size) { free(header->seq); header->size = header_r->size; header->seq = smalloc(header->size); } if(qseq->size < qseq_r->size) { free(qseq->seq); qseq->size = qseq_r->size; qseq->seq = smalloc(qseq->size); } /* Patricks features */ if(extendedFeatures) { strcat(outputfilename, ".mapstat"); extendedFeatures_out = sfopen(outputfilename, "wb"); outputfilename[file_len] = 0; initExtendedFeatures(extendedFeatures_out, templatefilename, *matched_templates, exePrev); } else { extendedFeatures_out = 0; } if(extendedFeatures || xml) { fragmentCounts = calloc(DB_size, sizeof(unsigned)); readCounts = calloc(DB_size, sizeof(unsigned)); if(!fragmentCounts || !readCounts) { ERROR(); } } else { fragmentCounts = 0; readCounts = 0; } if(xml) { if(xml == 2) { xml_out = openInitXML("--", templatefilename, *matched_templates, 1, &exePrev); } else { strcat(outputfilename, ".xml"); xml_out = openInitXML(outputfilename, templatefilename, *matched_templates, 1, &exePrev); outputfilename[file_len] = 0; } } else { xml_out = 0; } /* clean threads */ i = 1; threads = 0; for(alnThread = alnThreads; alnThread != 0; alnThread = alnThreads) { alnThreads = alnThread->next; /* reuse what is possible */ thread = smalloc(sizeof(Assemble_thread)); thread->num = i; thread->thread_num = thread_num; thread->template = -2; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = extendedFeatures; thread->seq_in = 0; thread->kmersize = kmersize; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->NWmatrices = alnThread->NWmatrices; thread->qseq = alnThread->qseq; thread->header = alnThread->header; thread->points = alnThread->points; thread->points->len = 0; thread->next = threads; threads = thread; ++i; /* check header and qseq */ if(header->size < thread->header->size) { header->size = thread->header->size; free(header->seq); header->seq = smalloc(header->size); } if(qseq->size < thread->qseq->size) { qseq->size = thread->qseq->size; free(qseq->seq); qseq->seq = smalloc(qseq->size); } /* free the rest */ free(alnThread->matched_templates); free(alnThread->bestTemplates); free(alnThread->bestTemplates_r); free(alnThread->best_start_pos); free(alnThread->best_end_pos); freeComp(alnThread->qseq_comp); free(alnThread->qseq_comp); freeComp(alnThread->qseq_r_comp); free(alnThread->qseq_r_comp); destroyQseqs(alnThread->qseq_r); destroyQseqs(alnThread->header_r); free(alnThread); } if(kmaPipe == &kmaPipeFork) { t1 = clock(); fprintf(stderr, "#\n# KMA mapping time\t%.2f s.\n", difftime(t1, t0) / 1000000); } else { fprintf(stderr, "# KMA mapping done\n"); } fprintf(stderr, "#\n# Sort, output and select KMA alignments.\n"); t0 = clock(); /* Get best template for each mapped read Best hit chosen as: highest mapping score then higest # unique maps */ alignFrags = calloc(DB_size, sizeof(Frag*)); w_scores = calloc(DB_size, sizeof(long unsigned)); if(!alignFrags || !w_scores) { ERROR(); } outputfilename[file_len] = 0; frag_in_raw = frag_out_raw; rewind(frag_in_raw); outputfilename[file_len] = 0; template_fragments = calloc(DB_size, sizeof(FILE*)); if(!template_fragments) { ERROR(); } fragCount = 0; fileCount = 0; maxFrag = 1000000; /* Get expected values */ sparse = 0; template_tot_ulen = 0; i = DB_size; while(--i) { template_tot_ulen += template_lengths[i]; } /* ConClave */ if(ConClave == 1) { while(fread(stats, sizeof(int), 5, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; flag = stats[4]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); sfread(best_start_pos, sizeof(int), bestHits, frag_in_raw); sfread(best_end_pos, sizeof(int), bestHits, frag_in_raw); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best */ if(bestHits > 1) { bestTemplate = -1; bestScore = 0; best_read_score = 0; bestNum = 0; start = 0; end = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; tmp_start = best_start_pos[i]; tmp_end = best_end_pos[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(alignment_scores[tmp_template] == best_read_score) { //} else if(tmp_score == bestScore) { if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { //} else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } } } } } else { bestTemplate = *bestTemplates; start = *best_start_pos; end = *best_end_pos; } /* reverse complement seq */ if(bestTemplate < 0) { bestTemplate = -bestTemplate; strrc(qseq->seq, qseq->len); } w_scores[bestTemplate] += read_score; if(fragmentCounts) { fragmentCounts[bestTemplate]++; readCounts[bestTemplate]++; } /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; if(stats[2] < 0) { if(extendedFeatures) { readCounts[bestTemplate]++; } sfread(stats, sizeof(int), 3, frag_in_raw); qseq->len = stats[0]; header->len = stats[1]; flag = stats[2]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; } if(fragCount >= maxFrag) { template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; fragCount = 0; /* control fileamount */ if(fileCount >= DB_size) { template_fragments = realloc(template_fragments, (fileCount + 1) * sizeof(FILE*)); if(!template_fragments) { ERROR(); } } } } template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; } else if(ConClave == 2) { /* find potential template candidates */ while(fread(stats, sizeof(int), 4, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; /* best templates, skip rest */ fseek(frag_in_raw, qseq->len + header->len + (2 * bestHits + 1) * sizeof(int), SEEK_CUR); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best */ if(bestHits > 1) { bestTemplate = -1; bestScore = 0; best_read_score = 0; bestNum = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } else if(alignment_scores[tmp_template] == best_read_score) { //} else if(tmp_score == bestScore) { if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { //} else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } } } } } else { bestTemplate = *bestTemplates; } w_scores[abs(bestTemplate)] += read_score; if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); fseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } } rewind(frag_in_raw); /* discard insignifiacant templates */ Nhits = 0; template = DB_size; while(--template) { Nhits += w_scores[template]; } template = DB_size; while(--template) { if((read_score = w_scores[template])) { t_len = template_lengths[template]; //expected = (Nhits - read_score) * (1.0 * t_len) / (template_tot_ulen - t_len + etta); expected = t_len; expected /= MAX(1,(template_tot_ulen - t_len)); expected *= (Nhits - read_score); //q_value = pow(read_score - expected, 2) / (expected + read_score + etta); q_value = read_score - expected; q_value /= (expected + read_score); q_value *= read_score - expected; p_value = p_chisqr(q_value); if(cmp((p_value <= evalue && read_score > expected), (read_score >= scoreT * t_len)) == 0) { w_scores[template] = 0; } } } /* identify sorting keys */ while(fread(stats, sizeof(int), 4, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; if(bestHits != 1) { /* best templates, skip rest */ fseek(frag_in_raw, qseq->len + header->len + (2 * bestHits + 1) * sizeof(int), SEEK_CUR); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); bestTemplate = 0; i = bestHits; while(i--) { template = abs(bestTemplates[i]); if(w_scores[template]) { if(bestTemplate) { bestTemplate = 0; break; } else { bestTemplate = template; } } } if(bestTemplate) { uniq_alignment_scores[bestTemplate] += read_score; } } else { /* skip rest */ fseek(frag_in_raw, qseq->len + header->len + 4 * sizeof(int), SEEK_CUR); } if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); fseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } } rewind(frag_in_raw); /* choose the templates */ memset(w_scores, 0, DB_size * sizeof(long unsigned)); while(fread(stats, sizeof(int), 5, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; flag = stats[4]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); sfread(best_start_pos, sizeof(int), bestHits, frag_in_raw); sfread(best_end_pos, sizeof(int), bestHits, frag_in_raw); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best according to sorting keys */ if(bestHits != 1) { bestTemplate = 0; bestScore = 0; start = 0; end = 0; tot = 0; i = bestHits; while(i--) { tot += uniq_alignment_scores[abs(bestTemplates[i])]; } if(tot && 16 <= qseq->len) { /* get seed */ rand = qseq->seq[0]; i = -1; j = qseq->len; while(++i < 7) { rand = (((rand << 2) | qseq->seq[i]) << 2) | qseq->seq[--j]; } /* minimal standard */ rand = 16807 * (rand % 127773) - 2836 * (rand / 127773); if (rand <= 0) { rand += 0x7fffffff; } tmp_score = rand; tmp_score /= INT_MAX; randScore = tmp_score * tot; score = 0; i = 0; while(i != bestHits) { score += uniq_alignment_scores[abs(bestTemplates[i])]; if(randScore < score) { bestTemplate = bestTemplates[i]; start = best_start_pos[i]; end = best_end_pos[i]; i = bestHits; } else { ++i; } } if(bestTemplate == 0) { tot = 0; } } else { tot = 0; } if(tot == 0) { bestTemplate = 0; best_read_score = 0; bestNum = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; tmp_start = best_start_pos[i]; tmp_end = best_end_pos[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(alignment_scores[tmp_template] == best_read_score) { //} else if(tmp_score == bestScore) { if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { //} else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } } } } } } else { bestTemplate = *bestTemplates; start = *best_start_pos; end = *best_end_pos; } /* reverse complement seq */ if(bestTemplate < 0) { bestTemplate = -bestTemplate; strrc(qseq->seq, qseq->len); } if(bestTemplate) { w_scores[bestTemplate] += read_score; if(fragmentCounts) { fragmentCounts[bestTemplate]++; readCounts[bestTemplate]++; } /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; if(stats[2] < 0) { if(extendedFeatures) { readCounts[bestTemplate]++; } sfread(stats, sizeof(int), 3, frag_in_raw); qseq->len = stats[0]; header->len = stats[1]; flag = stats[2]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; } } else if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); sfseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } if(fragCount >= maxFrag) { template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; fragCount = 0; /* control fileamount */ if(fileCount >= DB_size) { template_fragments = realloc(template_fragments, (fileCount + 1) * sizeof(FILE*)); if(!template_fragments) { ERROR(); } } } } template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; } fragCount = 0; free(alignFrags); free(best_start_pos); free(best_end_pos); free(matched_templates); free(bestTemplates); destroyQseqs(qseq_r); fclose(frag_out_raw); if(frag_out_all) { destroyGzFileBuff(frag_out_all); } /* Get expected values */ Nhits = 0; i = DB_size; while(--i) { Nhits += w_scores[i]; } Nhits = Nhits ? Nhits : 1; t1 = clock(); fprintf(stderr, "# Total time for sorting and outputting KMA alignment\t%.2f s.\n", difftime(t1, t0) / 1000000); fprintf(stderr, "#\n# Doing local assemblies of found templates, and output results\n"); t0 = clock(); /* print heading of resistance file: */ fprintf(res_out, "#Template\tScore\tExpected\tTemplate_length\tTemplate_Identity\tTemplate_Coverage\tQuery_Identity\tQuery_Coverage\tDepth\tq_value\tp_value\n"); if(vcf) { initialiseVcf(vcf_out, templatefilename); } /* Get expected values */ points->len = 0; /* preallocate assembly matrices */ aligned_assem = smalloc(sizeof(Assem)); matrix = smalloc(sizeof(AssemInfo)); matrix->size = qseq->size; for(i = 0; i < DB_size; ++i) { if(matrix->size < template_lengths[i]) { matrix->size = template_lengths[i]; } } if(alnToMatPtr == &alnToMat) { matrix->size <<= 1; } else { matrix->size++; } matrix->assmb = smalloc(matrix->size * sizeof(Assembly)); aligned_assem->size = matrix->size; aligned_assem->t = smalloc(aligned_assem->size); aligned_assem->s = smalloc(aligned_assem->size); aligned_assem->q = smalloc(aligned_assem->size); /* allocate matrcies for NW */ for(thread = threads; thread != 0; thread = thread->next) { /* get remaining thread info */ aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((qseq->size + 1) << 1); aligned->s = smalloc((qseq->size + 1) << 1); aligned->q = smalloc((qseq->size + 1) << 1); gap_align->t = smalloc((qseq->size + 1) << 1); gap_align->s = smalloc((qseq->size + 1) << 1); gap_align->q = smalloc((qseq->size + 1) << 1); thread->aligned = aligned; thread->gap_align = gap_align; thread->file_count = fileCount; thread->files = template_fragments; thread->aligned_assem = aligned_assem; thread->matrix = matrix; thread->spin = (sparse < 0) ? 10 : 100; /* start thread */ if((errno = pthread_create(&thread->id, NULL, assembly_KMA_Ptr, thread))) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); fprintf(stderr, "Will continue with %d threads.\n", i); threads = thread->next; free(thread); } } /* start main thread */ aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((qseq->size + 1) << 1); aligned->s = smalloc((qseq->size + 1) << 1); aligned->q = smalloc((qseq->size + 1) << 1); gap_align->t = smalloc((qseq->size + 1) << 1); gap_align->s = smalloc((qseq->size + 1) << 1); gap_align->q = smalloc((qseq->size + 1) << 1); thread = smalloc(sizeof(Assemble_thread)); thread->num = 0; thread->thread_num = thread_num; thread->template = 0; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = extendedFeatures; thread->seq_in = 0; thread->kmersize = kmersize; thread->file_count = fileCount; thread->files = template_fragments; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->aligned_assem = aligned_assem; thread->aligned = aligned; thread->gap_align = gap_align; thread->NWmatrices = NWmatrices; thread->matrix = matrix; thread->qseq = qseq; thread->header = header; thread->points = points; thread->points->len = 0; thread->next = 0; thread->spin = (sparse < 0) ? 10 : 100; if(assembly_KMA_Ptr == &skip_assemble_KMA) { alignLoadPtr = &alignLoad_skip; } if(verbose) { fprintf(stderr, "# Template\tScore\tProgress\n"); } /* Do local assemblies of fragments mapping to the same template */ depth = 0; q_id = 0; cover = 0; q_cover = 0; counter = 0; for(template = 1; template < DB_size; ++template) { if(w_scores[template] > 0) { if(verbose) { counter += w_scores[template]; fprintf(stderr, "# %d / %d\t%lu\t%3lu%%\n", template, DB_size, w_scores[template], 100 * counter / Nhits); } /* make p_value to see whether assembly is feasable */ read_score = w_scores[template]; t_len = template_lengths[template]; expected = t_len; expected /= MAX(1, (template_tot_ulen - t_len)); expected *= (Nhits - read_score); if(0 < expected) { q_value = read_score - expected; q_value /= (expected + read_score); q_value *= (read_score - expected); } else { q_value = read_score; } p_value = p_chisqr(q_value); if(cmp((p_value <= evalue && read_score > expected), (read_score >= scoreT * t_len))) { thread->template_name = nameLoad(template_name, name_file); thread->template_index = templates_index[template]; if(xml) { newIterXML(xml_out, template, t_len, thread->template_name); } /* Do assembly */ //status |= assemblyPtr(aligned_assem, template, template_fragments, fileCount, frag_out, aligned, gap_align, qseq, header, matrix, points, NWmatrices); thread->template = template; thread->t_len = t_len; assembly_KMA_Ptr(thread); /* Depth, ID and coverage */ if(aligned_assem->cover > 0) { coverScore = aligned_assem->cover; depth = aligned_assem->depth; depth /= t_len; id = 100.0 * coverScore / t_len; aln_len = aligned_assem->aln_len; q_id = 100.0 * coverScore / aln_len; cover = 100.0 * aln_len / t_len; q_cover = 100.0 * t_len / aln_len; } else { aln_len = 0; id = 0; } if(xml) { capIterXML(xml_out, DB_size, seqin_size, t_len, readCounts[template], p_value, read_score, aligned_assem->q, aln_len); } if(ID_t <= id && 0 < id) { /* Output result */ fprintf(res_out, "%-12s\t%8ld\t%8u\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, (unsigned) expected, t_len, id, cover, q_id, q_cover, (double) depth, (double) q_value, p_value); if(nc != 1) { printConsensus(aligned_assem, thread->template_name, alignment_out, consensus_out, ref_fsa); } /* print matrix */ if(matrix_out) { updateMatrix(matrix_out, thread->template_name, templates_index[template]->seq, matrix, t_len); } if(extendedFeatures) { printExtendedFeatures(thread->template_name, aligned_assem, fragmentCounts[template], readCounts[template], extendedFeatures_out); } if(vcf) { updateVcf(thread->template_name, aligned_assem->t, evalue, support, bcd, t_len, matrix, vcf, vcf_out); } } } else { if((sam && !(sam & 2096)) || ID_t == 0.0) { thread->template_index = templates_index[template]; thread->template_name = nameLoad(template_name, name_file); thread->template = template; skip_assemble_KMA(thread); //skip_assemble_KMA(template, sam, t_len, thread->template_name, fileCount, template_fragments, aligned_assem, qseq, header); if(ID_t == 0.0) { depth = aligned_assem->depth; depth /= t_len; aln_len = aligned_assem->aln_len; cover = 100.0 * aln_len / t_len; q_cover = 100.0 * t_len / aln_len; fprintf(res_out, "%-12s\t%8ld\t%8u\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, (unsigned) expected, t_len, 0.0, cover, 0.0, q_cover, (double) depth, (double) q_value, p_value); if(extendedFeatures) { printExtendedFeatures(thread->template_name, aligned_assem, fragmentCounts[template], readCounts[template], extendedFeatures_out); } } } else { nameSkip(name_file, end); } } } else { nameSkip(name_file, end); } hashMapCCI_destroy(templates_index[template]); } /* join threads */ thread->template = -1; assembly_KMA_Ptr(thread); for(thread = threads; thread != 0; thread = thread->next) { /* join thread */ if((errno = pthread_join(thread->id, NULL))) { ERROR(); } } /* Close files */ close(seq_in_no); fclose(res_out); if(alignment_out) { fclose(alignment_out); fclose(consensus_out); } fclose(name_file); if(frag_out) { destroyGzFileBuff(frag_out); } if(matrix_out) { destroyGzFileBuff(matrix_out); } if(extendedFeatures) { fclose(extendedFeatures_out); } if(vcf) { destroyGzFileBuff(vcf_out); } if(xml) { closeCapXML(xml_out); } t1 = clock(); fprintf(stderr, "# Total time used for local assembly: %.2f s.\n#\n", difftime(t1, t0) / 1000000); return status; } int runKMA_MEM(char *templatefilename, char *outputfilename, char *exePrev, int ConClave, int kmersize, int minlen, Penalties *rewards, int extendedFeatures, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int ref_fsa, int print_matrix, int print_all, int vcf, int xml, int sam, int nc, int nf, unsigned shm, int thread_num, int verbose) { /* runKMA_MEM is a memory saving version of runKMA, at the cost it chooses best templates based on kmers instead of alignment score. */ int i, j, tmp_template, tmp_tmp_template, file_len, score, rand, rc_flag; int template, bestHits, t_len, start, delta, aln_len, fragCount, maxFrag; int fileCount, coverScore, tmp_start, tmp_end, bestTemplate, status, tot; int sparse, progress, seq_in_no, DB_size, end, flag, flag_r; int *matched_templates, *bestTemplates, *best_start_pos, *best_end_pos; int *template_lengths, stats[5]; unsigned randScore, *fragmentCounts, *readCounts; long best_read_score, read_score, seq_seeker; long unsigned Nhits, template_tot_ulen, bestNum, counter, seqin_size; long unsigned *w_scores, *uniq_alignment_scores, *alignment_scores; double tmp_score, bestScore, id, cover, q_id, q_cover, p_value; long double depth, q_value, expected; FILE *inputfile, *frag_in_raw, *res_out, *name_file; FILE *alignment_out, *consensus_out, *frag_out_raw, **template_fragments; FILE *extendedFeatures_out, *xml_out; time_t t0, t1; FileBuff *frag_out, *frag_out_all, *matrix_out, *vcf_out; Aln *aligned, *gap_align; Assem *aligned_assem; Frag **alignFrags, *alignFrag; CompDNA *qseq_comp, *qseq_r_comp; Qseqs *qseq, *qseq_r, *header, *header_r, *template_name; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; Assemble_thread *threads, *thread; HashMapCCI *template_index; /* get lengths and names */ file_len = strlen(templatefilename); DB_size = load_DBs_KMA(templatefilename, &alignment_scores, &uniq_alignment_scores, &template_lengths, shm); templatefilename[file_len] = 0; template_name = setQseqs(256); strcat(templatefilename, ".name"); name_file = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; if((verbose & 2)) { progress = 1; verbose = 0; } else { progress = 0; } /* print sam-header */ if(sam) { saminit(template_name, name_file, template_lengths, DB_size); } /* open pipe */ status = 0; inputfile = kmaPipe("-s2", "rb", 0, 0); if(!inputfile) { ERROR(); } else { setvbuf(inputfile, NULL, _IOFBF, CHUNK); } /* load databases */ alignLoadPtr = &alignLoad_fly_mem; if(!kmersize) { kmersize = *template_lengths; } if(kmersize < 4 || 32 < kmersize) { kmersize = 16; } strcat(templatefilename, ".seq.b"); seq_in_no = open(templatefilename, O_RDONLY); if(seq_in_no == -1) { ERROR(); } seqin_size = 4 * lseek(seq_in_no, 0, SEEK_END); if(lseek(seq_in_no, 0, SEEK_SET) != 0) { ERROR(); } templatefilename[file_len] = 0; /* allocate stuff */ file_len = strlen(outputfilename); qseq_comp = malloc(sizeof(CompDNA)); qseq_r_comp = malloc(sizeof(CompDNA)); if(!qseq_comp || !qseq_r_comp) { ERROR(); } delta = 1024; allocComp(qseq_comp, delta); allocComp(qseq_r_comp, delta); qseq = setQseqs(delta); qseq_r = setQseqs(delta); header = setQseqs(256); header_r = setQseqs(256); points = seedPoint_init(delta, rewards); /* open outputfiles */ if(outputfilename) { strcat(outputfilename, ".res"); res_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; if(nf == 0) { strcat(outputfilename, ".frag.gz"); frag_out = gzInitFileBuff(CHUNK); openFileBuff(frag_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { frag_out = 0; } if(nc == 0) { strcat(outputfilename, ".aln"); alignment_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else if(nc == 2) { alignment_out = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else { alignment_out = 0; consensus_out = 0; } frag_out_raw = tmpF(0); if(!frag_out_raw) { ERROR(); } if(print_matrix) { matrix_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".mat.gz"); openFileBuff(matrix_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { matrix_out = 0; } if(print_all) { strcat(outputfilename, ".frag_raw.gz"); frag_out_all = gzInitFileBuff(CHUNK); openFileBuff(frag_out_all, outputfilename, "wb"); outputfilename[file_len] = 0; } else { frag_out_all = 0; } if(vcf) { vcf_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".vcf.gz"); openFileBuff(vcf_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { vcf_out = 0; } } else { fprintf(stderr, " No output file specified!\n"); exit(1); } fprintf(stderr, "# Collecting k-mer scores.\n"); t0 = clock(); /* Get alignments */ matched_templates = malloc(((DB_size + 1) << 1) * sizeof(int)); best_start_pos = calloc((DB_size << 1), sizeof(int)); best_end_pos = malloc((DB_size << 1) * sizeof(int)); if(!matched_templates || !best_start_pos || !best_end_pos) { ERROR(); } bestTemplates = (matched_templates + 1); /* consider printPair */ Nhits = 0; t_len = 0; read_score = 0; while((rc_flag = get_ankers(matched_templates, qseq_comp, header, &flag, inputfile)) != 0) { if(*matched_templates) { // SE read_score = 0; qseq_r->len = 0; } else { // PE read_score = get_ankers(matched_templates, qseq_r_comp, header_r, &flag_r, inputfile); read_score = labs(read_score); qseq_r->len = qseq_r_comp->seqlen; } qseq->len = qseq_comp->seqlen; if(kmersize <= qseq->len) { if(delta <= MAX(qseq->len, qseq_r->len)) { delta = MAX(qseq->len, qseq_r->len); delta <<= 1; qseq->size = delta; qseq_r->size = delta; free(qseq->seq); free(qseq_r->seq); qseq->seq = malloc(delta); qseq_r->seq = malloc(delta); if(!qseq->seq || !qseq_r->seq) { ERROR(); } } unCompDNA(qseq_comp, qseq->seq); /* reverse complement seq */ best_read_score = abs(rc_flag); for(i = 1, bestHits = 0; i <= *matched_templates; ++i, ++bestHits) { best_end_pos[bestHits] = template_lengths[abs(matched_templates[i])]; } if(rc_flag < 0 && 0 < matched_templates[*matched_templates]) { bestHits = -bestHits; } if(read_score && kmersize <= qseq_r->len) { unCompDNA(qseq_r_comp, qseq_r->seq); update_Scores_pe(qseq->seq, qseq->len, qseq_r->seq, qseq_r->len, bestHits, best_read_score + read_score, best_start_pos, best_end_pos, bestTemplates, header, header_r, flag, flag_r, alignment_scores, uniq_alignment_scores, frag_out_raw); } else { update_Scores(qseq->seq, qseq->len, bestHits, best_read_score, best_start_pos, best_end_pos, bestTemplates, header, flag, alignment_scores, uniq_alignment_scores, frag_out_raw); } /* dump seq to all */ if(frag_out_all) { updateAllFrag(qseq->seq, qseq->len, abs(bestHits), best_read_score, best_start_pos, best_end_pos, bestTemplates, header, frag_out_all); if(read_score) { updateAllFrag(qseq_r->seq, qseq_r->len, abs(bestHits), read_score, best_start_pos, best_end_pos, bestTemplates, header_r, frag_out_all); } } /* verbose */ if(verbose && verbose++ == 1024) { Nhits += verbose - 1; fprintf(stderr, "# Scored %ld query sequences.\n", Nhits); verbose = 1; } } } /* verbose */ if(verbose) { Nhits += verbose - 1; fprintf(stderr, "# Scored %ld query sequences.\n", Nhits); verbose = 1; } kmaPipe(0, 0, inputfile, &i); status |= i; i = 0; sfwrite(&i, sizeof(int), 1, frag_out_raw); fflush(frag_out_raw); freeComp(qseq_comp); free(qseq_comp); freeComp(qseq_r_comp); free(qseq_r_comp); if(header->size < header_r->size) { destroyQseqs(header); header = header_r; } else { destroyQseqs(header_r); } header_r = 0; if(qseq->size < qseq_r->size) { destroyQseqs(qseq); qseq = qseq_r; } else { destroyQseqs(qseq_r); } qseq_r = 0; if(frag_out_all) { destroyGzFileBuff(frag_out_all); } if(kmaPipe == &kmaPipeFork) { t1 = clock(); fprintf(stderr, "#\n# Time for score collecting:\t%.2f s.\n", difftime(t1, t0) / 1000000); } else { fprintf(stderr, "# Score collection done\n"); } fprintf(stderr, "#\n# Sort, output and select k-mer alignments.\n"); t0 = clock(); /* Get best template for each mapped deltamer/read */ /* Best hit chosen as: highest mapping score then higest # unique maps */ alignFrags = calloc(DB_size, sizeof(Frag*)); w_scores = calloc(DB_size, sizeof(long unsigned)); if(!alignFrags || !w_scores) { ERROR(); } outputfilename[file_len] = 0; frag_in_raw = frag_out_raw; rewind(frag_in_raw); template_fragments = calloc(DB_size, sizeof(FILE*)); if(!template_fragments) { ERROR(); } fragCount = 0; fileCount = 0; maxFrag = 1000000; /* Patricks features */ if(extendedFeatures) { strcat(outputfilename, ".mapstat"); extendedFeatures_out = sfopen(outputfilename, "wb"); outputfilename[file_len] = 0; initExtendedFeatures(extendedFeatures_out, templatefilename, *matched_templates, exePrev); } else { extendedFeatures_out = 0; } if(extendedFeatures || xml) { fragmentCounts = calloc(DB_size, sizeof(unsigned)); readCounts = calloc(DB_size, sizeof(unsigned)); if(!fragmentCounts || !readCounts) { ERROR(); } } else { fragmentCounts = 0; readCounts = 0; } if(xml) { if(xml == 2) { xml_out = openInitXML("--", templatefilename, *matched_templates, 1, &exePrev); } else { strcat(outputfilename, ".xml"); xml_out = openInitXML(outputfilename, templatefilename, *matched_templates, 1, &exePrev); outputfilename[file_len] = 0; } } else { xml_out = 0; } /* Get expected values */ sparse = 0; template_tot_ulen = 0; i = DB_size; while(--i) { template_tot_ulen += template_lengths[i]; } /* ConClave */ if(ConClave == 1) { while(fread(stats, sizeof(int), 5, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; flag = stats[4]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); sfread(best_start_pos, sizeof(int), bestHits, frag_in_raw); sfread(best_end_pos, sizeof(int), bestHits, frag_in_raw); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best */ if(bestHits > 1) { bestTemplate = -1; bestScore = 0; best_read_score = 0; bestNum = 0; start = 0; end = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; tmp_start = best_start_pos[i]; tmp_end = best_end_pos[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(alignment_scores[tmp_template] == best_read_score) { } else if(tmp_score == bestScore) { //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { } else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } } } } } else { bestTemplate = *bestTemplates; start = *best_start_pos; end = *best_end_pos; } /* reverse complement seq */ if(bestTemplate < 0) { bestTemplate = -bestTemplate; strrc(qseq->seq, qseq->len); } w_scores[bestTemplate] += read_score; if(fragmentCounts) { fragmentCounts[bestTemplate]++; readCounts[bestTemplate]++; } /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; if(stats[2] < 0) { if(extendedFeatures) { readCounts[bestTemplate]++; } sfread(stats, sizeof(int), 3, frag_in_raw); qseq->len = stats[0]; header->len = stats[1]; flag = stats[2]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; } if(fragCount >= maxFrag) { template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; fragCount = 0; /* control fileamount */ if(fileCount >= DB_size) { template_fragments = realloc(template_fragments, (fileCount + 1) * sizeof(FILE*)); if(!template_fragments) { ERROR(); } } } } template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; } else if(ConClave == 2) { /* find potential template candidates */ while(fread(stats, sizeof(int), 4, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; /* best templates, skip rest */ fseek(frag_in_raw, qseq->len + header->len + (2 * bestHits + 1) * sizeof(int), SEEK_CUR); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best */ if(bestHits > 1) { bestTemplate = -1; bestScore = 0; best_read_score = 0; bestNum = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; //} else if(alignment_scores[tmp_template] == best_read_score) { } else if(tmp_score == bestScore) { //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; //} else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { } else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; } } } } } else { bestTemplate = *bestTemplates; } w_scores[abs(bestTemplate)] += read_score; if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); fseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } } rewind(frag_in_raw); /* discard insignifiacant templates */ Nhits = 0; template = DB_size; while(--template) { Nhits += w_scores[template]; } template = DB_size; while(--template) { if((read_score = w_scores[template])) { t_len = template_lengths[template]; //expected = (Nhits - read_score) * (t_len / (template_tot_ulen - t_len + etta)); expected = t_len; expected /= MAX(1, (template_tot_ulen - t_len)); expected *= (Nhits - read_score); //q_value = pow(read_score - expected, 2) / (expected + read_score + etta); q_value = read_score - expected; q_value /= (expected + read_score); q_value *= read_score - expected; p_value = p_chisqr(q_value); if(cmp((p_value <= evalue && read_score > expected), (read_score >= scoreT * t_len)) == 0) { w_scores[template] = 0; } } } /* identify sorting keys */ while(fread(stats, sizeof(int), 4, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; if(bestHits != 1) { /* best templates, skip rest */ fseek(frag_in_raw, qseq->len + header->len + (2 * bestHits + 1) * sizeof(int), SEEK_CUR); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); bestTemplate = 0; i = bestHits; while(i--) { template = abs(bestTemplates[i]); if(w_scores[template]) { if(bestTemplate) { bestTemplate = 0; break; } else { bestTemplate = template; } } } if(bestTemplate) { uniq_alignment_scores[bestTemplate] += read_score; } } else { /* skip rest */ fseek(frag_in_raw, qseq->len + header->len + 4 * sizeof(int), SEEK_CUR); } if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); fseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } } rewind(frag_in_raw); /* choose the templates */ memset(w_scores, 0, DB_size * sizeof(long unsigned)); while(fread(stats, sizeof(int), 5, frag_in_raw) && stats[0] != 0) { qseq->len = stats[0]; sparse = stats[1]; bestHits = abs(sparse); read_score = abs(stats[2]); header->len = stats[3]; flag = stats[4]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); sfread(best_start_pos, sizeof(int), bestHits, frag_in_raw); sfread(best_end_pos, sizeof(int), bestHits, frag_in_raw); sfread(bestTemplates, sizeof(int), bestHits, frag_in_raw); /* Several mapped templates, choose best according to sorting keys */ if(bestHits != 1) { bestTemplate = 0; bestScore = 0; start = 0; end = 0; tot = 0; i = bestHits; while(i--) { tot += uniq_alignment_scores[abs(bestTemplates[i])]; } if(tot && 16 <= qseq->len) { /* get seed */ rand = qseq->seq[0]; i = -1; j = qseq->len; while(++i < 7) { rand = (((rand << 2) | qseq->seq[i]) << 2) | qseq->seq[--j]; } /* minimal standard */ rand = 16807 * (rand % 127773) - 2836 * (rand / 127773); if (rand <= 0) { rand += 0x7fffffff; } tmp_score = rand; tmp_score /= INT_MAX; randScore = tmp_score * tot; score = 0; i = 0; while(i != bestHits) { score += uniq_alignment_scores[abs(bestTemplates[i])]; if(randScore < score) { bestTemplate = bestTemplates[i]; start = best_start_pos[i]; end = best_end_pos[i]; i = bestHits; } else { ++i; } } if(bestTemplate == 0) { tot = 0; } } else { tot = 0; } if(tot == 0) { bestTemplate = 0; best_read_score = 0; bestNum = 0; /* iterate hits */ for(i = 0; i != bestHits; ++i) { tmp_tmp_template = bestTemplates[i]; tmp_start = best_start_pos[i]; tmp_end = best_end_pos[i]; if(tmp_tmp_template < 0) { tmp_template = -tmp_tmp_template; } else { tmp_template = tmp_tmp_template; } tmp_score = 1.0 * alignment_scores[tmp_template] / (template_lengths[tmp_template] - kmersize + 1); if(tmp_score > bestScore) { //if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(alignment_scores[tmp_template] == best_read_score) { } else if(tmp_score == bestScore) { //if(tmp_score > bestScore) { if(alignment_scores[tmp_template] > best_read_score) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; //} else if(tmp_score == bestScore && alignment_scores[tmp_template] > bestNum) { } else if(alignment_scores[tmp_template] == best_read_score) { if(uniq_alignment_scores[tmp_template] > bestNum) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } else if(uniq_alignment_scores[tmp_template] == bestNum && tmp_template < abs(bestTemplate)) { bestTemplate = tmp_tmp_template; best_read_score = alignment_scores[tmp_template]; bestScore = tmp_score; bestNum = uniq_alignment_scores[tmp_template]; start = tmp_start; end = tmp_end; } } } } } } else { bestTemplate = *bestTemplates; start = *best_start_pos; end = *best_end_pos; } /* reverse complement seq */ if(bestTemplate < 0) { bestTemplate = -bestTemplate; strrc(qseq->seq, qseq->len); } if(bestTemplate) { w_scores[bestTemplate] += read_score; if(fragmentCounts) { fragmentCounts[bestTemplate]++; readCounts[bestTemplate]++; } /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; if(stats[2] < 0) { if(extendedFeatures) { readCounts[bestTemplate]++; } sfread(stats, sizeof(int), 3, frag_in_raw); qseq->len = stats[0]; header->len = stats[1]; flag = stats[2]; sfread(qseq->seq, 1, qseq->len, frag_in_raw); sfread(header->seq, 1, header->len, frag_in_raw); /* dump frag info */ alignFrag = smalloc(sizeof(Frag)); alignFrag->buffer[0] = qseq->len; alignFrag->buffer[1] = bestHits; alignFrag->buffer[2] = (sparse < 0) ? 0 : read_score; alignFrag->buffer[3] = start; alignFrag->buffer[4] = end; alignFrag->buffer[5] = header->len; alignFrag->buffer[6] = flag; alignFrag->qseq = ustrdup(qseq->seq, qseq->len); alignFrag->header = ustrdup(header->seq, header->len); alignFrag->next = alignFrags[bestTemplate]; alignFrags[bestTemplate] = alignFrag; ++fragCount; } } else if(stats[2] < 0) { sfread(stats, sizeof(int), 2, frag_in_raw); sfseek(frag_in_raw, stats[0] + stats[1] + sizeof(int), SEEK_CUR); } if(fragCount >= maxFrag) { template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; fragCount = 0; /* control fileamount */ if(fileCount >= DB_size) { template_fragments = realloc(template_fragments, (fileCount + 1) * sizeof(FILE*)); if(!template_fragments) { ERROR(); } } } } template_fragments[fileCount] = printFrags(alignFrags, DB_size); ++fileCount; } fragCount = 0; free(alignFrags); free(best_start_pos); free(best_end_pos); free(matched_templates); fclose(frag_out_raw); /* Get expected values */ Nhits = 0; i = DB_size; while(--i) { Nhits += w_scores[i]; } t1 = clock(); fprintf(stderr, "# Total time for sorting and outputting KMA alignment\t%.2f s.\n", difftime(t1, t0) / 1000000); fprintf(stderr, "#\n# Doing local assemblies of found templates, and output results\n"); t0 = clock(); /* print heading of resistance file: */ fprintf(res_out, "#Template\tScore\tExpected\tTemplate_length\tTemplate_Identity\tTemplate_Coverage\tQuery_Identity\tQuery_Coverage\tDepth\tq_value\tp_value\n"); if(vcf) { initialiseVcf(vcf_out, templatefilename); } /* preallocate assembly matrices */ matrix = smalloc(sizeof(AssemInfo)); aligned_assem = smalloc(sizeof(Assem)); matrix->size = delta; for(i = 0; i < DB_size; ++i) { if(matrix->size < template_lengths[i]) { matrix->size = template_lengths[i]; } } template_index = smalloc(sizeof(HashMapCCI)); template_index->size = 0; hashMapCCI_initialize(template_index, matrix->size, kmersize); /* if(alignLoadPtr != alignLoad_fly_shm) { hashMapCCI_initialize(template_index, matrix->size, kmersize); } else { template_index->seq = 0; template_index->index = 0; } */ if(alnToMatPtr == &alnToMat) { matrix->size <<= 1; } else { matrix->size++; } matrix->assmb = smalloc(matrix->size * sizeof(Assembly)); aligned_assem->size = matrix->size; aligned_assem->t = smalloc(aligned_assem->size); aligned_assem->s = smalloc(aligned_assem->size); aligned_assem->q = smalloc(aligned_assem->size); /* allocate matrcies for NW */ i = 1; threads = 0; while(i < thread_num) { /* allocate matrices */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); /* move it to the thread */ thread = smalloc(sizeof(Assemble_thread)); thread->num = i; thread->thread_num = thread_num; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = extendedFeatures; thread->seq_in = seq_in_no; thread->kmersize = kmersize; thread->template = -2; thread->file_count = fileCount; thread->files = template_fragments; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->aligned_assem = aligned_assem; thread->aligned = aligned; thread->gap_align = gap_align; thread->NWmatrices = NWmatrices; thread->matrix = matrix; thread->qseq = setQseqs(qseq->size); thread->header = setQseqs(header->size); thread->points = seedPoint_init(delta, rewards); thread->points->len = 0; thread->spin = (sparse < 0) ? 10 : 100; thread->template_index = template_index; thread->next = threads; threads = thread; /* start thread */ if((errno = pthread_create(&thread->id, NULL, assembly_KMA_Ptr, thread))) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); fprintf(stderr, "Will continue with %d threads.\n", i); threads = thread->next; free(thread); i = thread_num; } else { ++i; } } /* start main thread */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); /* move it to the thread */ thread = smalloc(sizeof(Assemble_thread)); thread->num = 0; thread->thread_num = thread_num; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = extendedFeatures; thread->seq_in = seq_in_no; thread->kmersize = kmersize; thread->template = 0; thread->file_count = fileCount; thread->files = template_fragments; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->aligned_assem = aligned_assem; thread->aligned = aligned; thread->gap_align = gap_align; thread->NWmatrices = NWmatrices; thread->matrix = matrix; thread->qseq = qseq; thread->header = header; thread->points = points; thread->points->len = 0; thread->template_index = template_index; thread->next = 0; thread->spin = (sparse < 0) ? 10 : 100; /* Do local assemblies of fragments mapping to the same template */ depth = 0; q_id = 0; cover = 0; q_cover = 0; seq_seeker = 0; counter = 0; if(progress) { fprintf(stderr, "# Progress:\t%3d%%\r", 0); fflush(stderr); } if(assembly_KMA_Ptr == &skip_assemble_KMA) { alignLoadPtr = &alignLoad_skip; } if(verbose) { fprintf(stderr, "# Template\tScore\tProgress\n"); } for(template = 1; template < DB_size; ++template) { if(w_scores[template] > 0) { if(progress) { counter += w_scores[template]; fprintf(stderr, "# Progress:\t%3lu%%\r", 100 * counter / Nhits); fflush(stderr); } else if(verbose) { counter += w_scores[template]; fprintf(stderr, "# %d / %d\t%lu\t%3lu%%\n", template, DB_size, w_scores[template], 100 * counter / Nhits); } /* make p_value to see whether assembly is feasable */ read_score = w_scores[template]; t_len = template_lengths[template]; expected = t_len; expected /= MAX(1, (template_tot_ulen - t_len)); expected *= (Nhits - read_score); if(0 < expected) { q_value = read_score - expected; q_value /= (expected + read_score); q_value *= (read_score - expected); } else { q_value = read_score; } p_value = p_chisqr(q_value); if(cmp((p_value <= evalue && read_score > expected), (read_score >= scoreT * t_len))) { /* load DB */ seq_seeker *= sizeof(long unsigned); lseek(seq_in_no, seq_seeker, SEEK_CUR); seq_seeker = 0; thread->template_index->len = 0; thread->template_name = nameLoad(template_name, name_file); if(xml) { newIterXML(xml_out, template, t_len, thread->template_name); } /* Do assembly */ //status |= assemblyPtr(aligned_assem, template, template_fragments, fileCount, frag_out, aligned, gap_align, qseq, header, matrix, points, NWmatrices); thread->template = template; thread->t_len = t_len; assembly_KMA_Ptr(thread); /* Depth, ID and coverage */ if(aligned_assem->cover > 0) { coverScore = aligned_assem->cover; depth = aligned_assem->depth; depth /= t_len; id = 100.0 * coverScore / t_len; aln_len = aligned_assem->aln_len; q_id = 100.0 * coverScore / aln_len; cover = 100.0 * aln_len / t_len; q_cover = 100.0 * t_len / aln_len; } else { id = 0; q_id = 0; depth = aligned_assem->depth; depth /= t_len; aln_len = aligned_assem->aln_len; cover = 100.0 * aln_len / t_len; q_cover = 0; } if(xml) { capIterXML(xml_out, DB_size, seqin_size, t_len, readCounts[template], p_value, read_score, aligned_assem->q, aln_len); } if(ID_t <= id) { /* Output result */ fprintf(res_out, "%-12s\t%8ld\t%8u\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, (unsigned) expected, t_len, id, cover, q_id, q_cover, (double) depth, (double) q_value, p_value); if(nc != 1) { printConsensus(aligned_assem, thread->template_name, alignment_out, consensus_out, ref_fsa); } /* print matrix */ if(matrix_out) { updateMatrix(matrix_out, thread->template_name, thread->template_index->seq, matrix, t_len); } if(extendedFeatures) { printExtendedFeatures(thread->template_name, aligned_assem, fragmentCounts[template], readCounts[template], extendedFeatures_out); } if(vcf) { updateVcf(thread->template_name, aligned_assem->t, evalue, support, bcd, t_len, matrix, vcf, vcf_out); } } } else { if((sam && !(sam & 2096)) || ID_t == 0.0) { /* load DB */ seq_seeker *= sizeof(long unsigned); lseek(seq_in_no, seq_seeker, SEEK_CUR); seq_seeker = 0; thread->template_index = alignLoad_skip(thread->template_index, seq_in_no, template_lengths[template], kmersize, 0); thread->template_name = nameLoad(template_name, name_file); thread->template = template; skip_assemble_KMA(thread); //skip_assemble_KMA(template, sam, t_len, thread->template_name, fileCount, template_fragments, aligned_assem, qseq, header); if(ID_t == 0.0) { depth = aligned_assem->depth; depth /= t_len; aln_len = aligned_assem->aln_len; cover = 100.0 * aln_len / t_len; q_cover = 0; fprintf(res_out, "%-12s\t%8ld\t%8u\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, (unsigned) expected, t_len, 0.0, cover, 0.0, q_cover, (double) depth, (double) q_value, p_value); if(extendedFeatures) { printExtendedFeatures(thread->template_name, aligned_assem, fragmentCounts[template], readCounts[template], extendedFeatures_out); } } } else { nameSkip(name_file, end); } seq_seeker += ((template_lengths[template] >> 5) + 1); } } else { nameSkip(name_file, end); seq_seeker += ((template_lengths[template] >> 5) + 1); } } if(progress) { fprintf(stderr, "\n"); } /* clear index */ hashMapCCI_destroy(thread->template_index); /* join threads */ thread->template = -1; assembly_KMA_Ptr(thread); for(thread = threads; thread != 0; thread = thread->next) { /* join thread */ if((errno = pthread_join(thread->id, NULL))) { ERROR(); } } /* Close files */ close(seq_in_no); fclose(res_out); if(alignment_out) { fclose(alignment_out); fclose(consensus_out); } fclose(name_file); if(frag_out) { destroyGzFileBuff(frag_out); } if(matrix_out) { destroyGzFileBuff(matrix_out); } if(extendedFeatures) { fclose(extendedFeatures_out); } if(vcf) { destroyGzFileBuff(vcf_out); } if(xml) { closeCapXML(xml_out); } t1 = clock(); fprintf(stderr, "# Total time used for local assembly: %.2f s.\n#\n", difftime(t1, t0) / 1000000); return status; } genomicepidemiology-kma-091b8ffe66ac/stdstat.c0000644000175000017500000001641414157033525020751 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "stdstat.h" int (*cmp)(int, int) = &cmp_or; int cmp_or(int t, int q) { return (t || q); } int cmp_and(int t, int q) { return (t && q); } int cmp_true(int t, int q) { return 1; } double fastp(long double q) { /* P-value from quantile in a chi-square distribution */ double p = 1.0; if(q > 114.5242) { p = 1e-26; } else if(q > 109.9604) { p = 1e-25; } else if(q > 105.3969) { p = 1e-24; } else if(q > 100.8337) { p = 1e-23; } else if(q > 96.27476) { p = 1e-22; } else if(q > 91.71701) { p = 1e-21; } else if(q > 87.16164) { p = 1e-20; } else if(q > 82.60901) { p = 1e-19; } else if(q > 78.05917) { p = 1e-18; } else if(q > 73.51245) { p = 1e-17; } else if(q > 68.96954) { p = 1e-16; } else if(q > 64.43048) { p = 1e-15; } else if(q > 59.89615) { p = 1e-14; } else if(q > 55.36699) { p = 1e-13; } else if(q > 50.84417) { p = 1e-12; } else if(q > 46.32844) { p = 1e-11; } else if(q > 41.82144) { p = 1e-10; } else if(q > 37.32489) { p = 1e-9; } else if(q > 32.84127) { p = 1e-8; } else if(q > 28.37395) { p = 1e-7; } else if(q > 23.92814) { p = 1e-6; } else if(q > 19.51139) { p = 1e-5; } else if(q > 15.13671) { p = 1e-4; } else if(q > 10.82759) { p = 1e-3; } else if(q > 6.634897) { p = 0.01; } else if(q > 3.841443) { p = 0.05; } else if(q > 2.705532) { p = 0.1; } else if(q > 2.072251) { p = 0.15; } else if(q > 1.642374) { p = 0.2; } else if(q > 1.323304) { p = 0.25; } else if(q > 1.074194) { p = 0.3; } else if(q > 0.8734571) { p = 0.35; } else if(q > 0.7083263) { p = 0.4; } else if(q > 0.5706519) { p = 0.45; } else if(q > 0.4549364) { p = 0.5; } else if(q > 0.3573172) { p = 0.55; } else if(q > 0.2749959) { p = 0.6; } else if(q > 0.2059001) { p = 0.65; } else if(q > 0.1484719) { p = 0.7; } else if(q > 0.1015310) { p = 0.75; } else if(q > 0.06418475) { p = 0.8; } else if(q > 0.03576578) { p = 0.85; } else if(q > 0.01579077) { p = 0.9; } else if(q > 0.00393214) { p = 0.95; } else if(q >= 0.0) { p = 1.0; } else { p = 1.00 - fastp(-1 * q); } return p; } double p_chisqr(long double q) { if(q < 0) { /* Handle negative overflow */ return 1e-26; } else if(q > 49) { /* Get p-val from table, to avoid overflow */ return fastp(q); } /* claculate p-value */ return 1 - 1.772453850 * erf(sqrt(0.5 * q)) / tgamma(0.5); } double power(double x, unsigned n) { double y; if(n) { y = power(x, n >> 1); return (n & 1) ? y * y * x : y * y; } return 1.0; } double binP(int n, int k, double p) { int i, j, nk; double P, q, pq; /* P = n! / (k! (n-k)!) * p^k * q^(n - k) */ q = 1 - p; if(k == 0) { P = power(q, n); return P != 0.0 ? P : 1.0e-308; } else if(n == k) { P = power(p, n); return P != 0.0 ? P : 1.0e-308; } else if(p == 0 || q == 0) { return 0.0; } P = 1.0; nk = n - k; pq = p * q; i = n + 1; if(k < nk) { j = k + 1; } else { j = nk + 1; } while(--j) { P *= (--i * pq / j); } if(nk < k) { P *= power(p, k - nk); } else if(k < nk) { P *= power(q, nk - k); } return P != 0.0 ? P : 1.0e-308; } unsigned minimum(unsigned *src, unsigned n) { unsigned min; min = *src; while(--n) { if(*++src < min) { min = *src; } } return min; } /* double eQual(unsigned char *qual, int len, int phredScale, int minQ) { //E(Q) = -10 * log_10(sum(10^(-Q/10)) / |Q|) unsigned i; double sum; if(!len || !minQ) { return 0; } // sum quality scores i = len; sum = pow(10, (phredScale - *qual) / 10.0); while(--i) { sum += pow(10, (phredScale - *++qual) / 10.0); } // return average return -10 * log10(((double)(sum)) / len); } */ unsigned eQual(unsigned char *qual, const int len, const int minQ, const double *prob) { /* static const double prob[128] = { 1.0000000000000000, 0.7943282347242815, 0.6309573444801932, 0.5011872336272722, 0.3981071705534972, 0.3162277660168379, 0.2511886431509580, 0.1995262314968880, 0.1584893192461113, 0.1258925411794167, 0.1000000000000000, 0.0794328234724281, 0.0630957344480193, 0.0501187233627272, 0.0398107170553497, 0.0316227766016838, 0.0251188643150958, 0.0199526231496888, 0.0158489319246111, 0.0125892541179417, 0.0100000000000000, 0.0079432823472428, 0.0063095734448019, 0.0050118723362727, 0.0039810717055350, 0.0031622776601684, 0.0025118864315096, 0.0019952623149689, 0.0015848931924611, 0.0012589254117942, 0.0010000000000000, 0.0007943282347243, 0.0006309573444802, 0.0005011872336273, 0.0003981071705535, 0.0003162277660168, 0.0002511886431510, 0.0001995262314969, 0.0001584893192461, 0.0001258925411794, 0.0001000000000000, 0.0000794328234724, 0.0000630957344480, 0.0000501187233627, 0.0000398107170553, 0.0000316227766017, 0.0000251188643151, 0.0000199526231497, 0.0000158489319246, 0.0000125892541179, 0.0000100000000000, 0.0000079432823472, 0.0000063095734448, 0.0000050118723363, 0.0000039810717055, 0.0000031622776602, 0.0000025118864315, 0.0000019952623150, 0.0000015848931925, 0.0000012589254118, 0.0000010000000000, 0.0000007943282347, 0.0000006309573445, 0.0000005011872336, 0.0000003981071706, 0.0000003162277660, 0.0000002511886432, 0.0000001995262315, 0.0000001584893192, 0.0000001258925412, 0.0000001000000000, 0.0000000794328235, 0.0000000630957344, 0.0000000501187234, 0.0000000398107171, 0.0000000316227766, 0.0000000251188643, 0.0000000199526231, 0.0000000158489319, 0.0000000125892541, 0.0000000100000000, 0.0000000079432823, 0.0000000063095734, 0.0000000050118723, 0.0000000039810717, 0.0000000031622777, 0.0000000025118864, 0.0000000019952623, 0.0000000015848932, 0.0000000012589254, 0.0000000010000000, 0.0000000007943282, 0.0000000006309573, 0.0000000005011872, 0.0000000003981072, 0.0000000003162278, 0.0000000002511886, 0.0000000001995262, 0.0000000001584893, 0.0000000001258925, 0.0000000001000000, 0.0000000000794328, 0.0000000000630957, 0.0000000000501187, 0.0000000000398107, 0.0000000000316228, 0.0000000000251189, 0.0000000000199526, 0.0000000000158489, 0.0000000000125893, 0.0000000000100000, 0.0000000000079433, 0.0000000000063096, 0.0000000000050119, 0.0000000000039811, 0.0000000000031623, 0.0000000000025119, 0.0000000000019953, 0.0000000000015849, 0.0000000000012589, 0.0000000000010000, 0.0000000000007943, 0.0000000000006310, 0.0000000000005012, 0.0000000000003981, 0.0000000000003162, 0.0000000000002512, 0.0000000000001995}; */ /* E(Q) = -10 * log_10(sum(10^(-Q/10)) / |Q|) */ unsigned i; double sum; if(!len || !minQ) { return 0; } /* sum quality scores */ i = len; sum = prob[*qual]; while(--i) { sum += prob[*++qual]; } /* return average */ return ceil(-10 * log10(sum / len)); } genomicepidemiology-kma-091b8ffe66ac/KMAspecification.pdf0000644000175000017500000075574414157033525023003 0ustar nileshnilesh%PDF-1.7 %µµµµ 1 0 obj <>/Metadata 513 0 R/ViewerPreferences 514 0 R>> endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 4 0 R/Group<>/Tabs/S/StructParents 0>> endobj 4 0 obj <> stream xœµY[Ó8~¯ÔÿàÇd5uc;NœB‚á²,‹¢Ò>™63È´¥Ípù÷{Îq“´“š¡Á‹4!IçæïœcOŸlëò:Ÿ×ìѣ铺ÎçËbÁ>LgëͧéìǦ˜¾ÍoÊU^—ëÕôýÝU¯þ*òE±}ü˜=}vɾŒGðŸ1IÂ"¦3ÍL,Ù¶þýƒ­Æ£§³ñhúB0!Ùìz<0(b‚é„§©fi¦¹„_naÐË÷)»ÙÁŒì†žÌþéåxô!˜…&X†qP°ð›ý==‡yßG¿,¼/Ašr-$ à=Þç0=Eâ‘fâ ¦gÏC˜Û0 Šm8INdWå >¬À ôÓª†;úécNLðúÍ“p¢‚!>°P˜`Nâ`ƒ˜Ã¥¼ÆÏË9|‹Ñf0•'E¤ÖÜ89ßû0Š=sɦŽ`º®ëõ­;Þ_¬×µ¿xW†k?JÁ(­$ Sš%LÄ47ä¡ß]râ7)Ê)û‚Šž Ã Œ¢o‹wÙô-zïÍå«g,:×%Š s$‡ˆc®!ÒTÆÓ~¤Í0à—x)B5ÀE4î¦ WÊ:”uú0Fóȸ`†²Nß„Yĵæ6œh²ÞoðF,^!³”x¹Y…Bt£Vhì‡ %ÁëPHCi(¡ÏwøÕ¦ñÉYHÛ©æ9}L÷ëPDƒù¨§b¬#;£ä^\ô¢Tœ¥½4%ãŒÃòJ…D1îã¿E…—DÆU¹ÁbqÌ–ü0 ¿CqvYåhª;¸ÃK1Ô>=ùT¬yæï!óÈßæU™¤˜.’,:…ÿ.º€û€™àʸ¿¢™r_x*‚|èÄSÞ`„ø Œ?m I¸aúùe(ŒŒ~“ùƒI¹P.˜‡‚_ù**’Ä Á½áÇÉ|í _Æ<>Ÿ›oø‘äIz6~ê _›h¾PAÅ'ñáÿø”›¶Å5ffJ?Ø.Ãóò1¶ˆ"¬ÞØéžy³=ÀY~ß?Q..wím¾jÚ¬Ÿt`ôXc¯»†²gá‹«Df°"<-¯¿ì^1ÊJ%Ð/²¼ªPµo (µ•¤6u”øzÛ¾Z`§¹EëQÓ Â[8Lç‹Ó5pºË¯(ßuÛF“¤9ªÑ=ùbçM–ÒX&²ä`(lÊ”y;[:(Ú¥.·…5£'IšhÑ IÐOy_ 9IRPyAVAó”àù”ŒwG~¬÷;90¥- ôñ¢YÇF¦ Ë[(hË*§`(ë éÄÚ{qÃçð×ìCÄPï‡"xµ “nFû õ:4#'IÀ8§MDúä(&Ôé5Ù õWvMXаö:¤Ž;Ûó4½Ç!Åw|Yoém ûövlÌ U¨œÆ ü£è£@ìœU›FDtþ²µ¹õ8i¼¿-p2]¡=ÖЫtŽ/r\ôËf*B¡6„vÔ5~ 'ÂЛb5ïÛi·eƒ–k£,?z"ÁÑ=m¨ ö ]C¡k£…ÀºÐ½ÄÍ13ÑC•Sý?xÒ鈄8©ÇY¾ÙÊzë³ûQÊ#§v¿goÒ8-]&TÚýMë?¼Qy’f—QVU±Ý¢XØ'%ßB±ç ž-"]öQߥv„Ü=7’tùï8[®¤˜ëÂþº‰9r8-Åz‡¸UºðRòE³ÖÉØËC@[.amÕ&T‡kiÝ4ñ;j¹õ¸¸/ \²"p³T' Ç~ÁLrÈ#ä’¼úѹ_Ê-|2Ëx┢l"æéò=»½a±†Z)pò,Q—V'¶Eæ°i¥‰µmÃöµ7‰Sí¡C1ÅRj¸t¡’íb÷¼0"q @©Ÿv£lÙæ/E@Ôh'ôAÀ6aAå!V)ÒZ¾³[³(ØA¹ÕfõÊV)WMªÏ)HhEØr¥Ûaëʽ> xW¸\µŽØ5Ñ|µ_M%­ÊrP ]IÂz-Òö%µÃ^vQ}%y;ÑŠãŒâÿ4¤?Í´äNÅÈCäAòÀ¦YîähÛËÜ6-ÙŸ¾×†J³Sr…¿WéF$#P@åó…·„#$7.Poº ¡q¹;`Ú‚-êÏ "nÕö¹SBÖ´MŽíroàЄ@"w _tDuõ[\yËÈ*âÉÿîR©ð8`ŽË»}Ûe;ecñá[±‰HîUu•Àå¶Í%ÍöNKù6JæûÚw"„mÔ½qØP¤¿èª~›rö)“åpóè|üß?kð•‚ïí$B 5ßÛIÎEæ|¼EÈ$Ããý³ðv!ãtÞ#¤Ô\ 8(?û4Â)@|z>¾·aÄ|ém«Dèl¾7*‚ï±D’çs€ôF‚™­?E€ÿ9«@_ endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 7 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> endobj 10 0 obj <> endobj 11 0 obj <> endobj 12 0 obj <> endobj 13 0 obj <> endobj 14 0 obj <> endobj 15 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 16 0 R/Group<>/Tabs/S/StructParents 1>> endobj 16 0 obj <> stream xœÍÛnÛ8ö=@þÖ"VÄ›.‹À@â6³ÝE±3h€}hû ÄJ+ÔqÜDÙÎ×/Ï!%Qi'=Ønt¡xîW’ç—OM}_Þ5äââü²iÊ»¯ÕŠ|<¿yÜ~>¿ù¹­Î-¿Ô›²©7ç~Ü6ðèU¹ªž rõfI¾Ÿž$qÿòû‰YE¢ÏäæŸ§'oÕ¼¿ž¼6Æ ËbÉ `ïÛ`&„æOhqÙŽí Á#y‰Ÿw@¹DO9˜YM'«ÅœHHK½4 ’Å\Ì—Ë~RÑOfˆëPH˜&2½^„Ê+Š$N¹[D`/Œ)n(. ©u…Êx .TŒõ l«ÖŸü\k•ckçCÓìý©öÊÂ^`˜8²¨D‘Æ…Ç(>&°7fyL³ @ŒC𫶃·ß!BU›;ÅzP•ÔŠ(xui ¡ÀzÅÒž½)UZµÐ~ñ}0z-ËæŒTˆk5ç zÐq÷ÈR˜§]T¤?ë6ˆV«pJ‘±çáß¾†Ka’Ôúlc™S:2—5We\U—N€øªõ£’fÇV;‹è%^b¢~‹’Á˺ú£Uˆa<ûjÔ£›½n"Ö¦%}ºµ5ÞûðùÁˆâ³æ1ÊÙÏ“˜zÙ‰´*M’*9³uÙTÁT‰KT%7ìp†£ªzÀNö„Ìb/I; ~+¯ ëèd.¼’åØEÌ}`ƒQ§R“8ñR74;ÓF Ö©;€ƒuƒ¥×h°&~}ëŨ–1Éx¨Ä‡Ó8õ!Vöå‡Ñ@_*!p­â£&§·q@üäGû¹,Üð<Óì…ê4 7"T¸‘);¾< ;â†/ÐM´Þèº\WoJœÀÿ¿Þ0q64=ð÷ÑŸ£ŸB"ªm;’&Ø„vC©»ÀüL÷L­á¿*¨š¹„Èÿ·ŸfÏŸ¢Ï¡P£¯ EUñB*ûòJbብ1¾è‹Éë¶$íÊN3*ÓIµª âÌ.ˆÍ0]Eëщ){ûÂ|™á¨ÉWVy/Õ£ìbX¿s3c–"âvœ_-,daP¾Ü Ç\á'©=o²(Ì-ŒÄú_N4žÔjF…©Ë-FV…/Lç@Ó`QÝÍ`$·ží„zÅû†‚aY×L0_X-P‘A&åT¼ƒ ¢ÞB¥¿…W½‘UJÛ¤f‰iÖh]1êš`è•·ÑzÓnÂC÷ÂD&\„cJý€ÂÉ1•èÀ=䨶¯lCÉqÁ÷Dk²`iºUש¾²,®›x` »žöÍ–T7åXg7h’o[cž8ŒÝk:~ýt“AÜBt¸Ü—9Q¸îiÓ… ÓÝÉì(¶ÏENi5c–“›;¥<Á´‡«¢MømÁ´h`¸[0–ëìy=èàvQß2lÈê¶îÐËø&w(FÛNm[Y É É:•Ôòy®C©ˆ™àG¬\°¨2 ’j³ŠìÎÔ8Pž4ä–LTYv†ãú¶]W±Ý™‹®²×d=b]À=õoõÀ-|×u¬†^[Y×]} Ö®à@1w«3Sª‹9k!ÉšÊÆ$p(Q‰êT:îu kÉÁø!ôŸZËÇË.(ôÚt¸¸Ds?kväVìÆŒLÈX,}èdB–ÆœïæÂ$:«øŒÌ"ÛAæ¾*ÕCI~ü"T ÍU-P̾"ÚKfìRTÑ«Êégõ XMK0{Ž{÷¼z·‹w’ iÜÑÏy&@wßL[AÌÊF‹;3ê'3½ØÞ­bFŒÎ\Æ® TÅä]Ášµˆêw@FwøÊ5Ù*$*xÞÅ9+ô\`}Ã^8±"&)\ÛZé- *,ÉYõ3¢F?°q¶?Ú²_0ûo»°Y®B9¿œï€8¬îÛŠ['™öŸn€a,Ú,þÒ•º3Qwߢè³Ò¶ÄðT/ž†Å¨Ä0Èã?”-¸‰·" «¯¶ ™Ù¡ žB_Ó£á õŒW ö›fPW_õ׺ÙÒ¬Zg wLQ†êb[.c”•¸)ÅfT\€MÖ1V9Ш>åÎ}0¶à1ÃYJÏÃ+_êÉU2—:øê+®Òeo: îÅÈfú½3ǵ¿®‡ ]W_v…ø¤áoØVíº ØÎë…ìÒ¿¬î—ÍÑ%Ï€Ö¨Ô¦ð*1Fä–a7?fÎ  ~tšUL³]D54iî!roÚlß-+òCà¿zã­/gª’ÇOÁ=`ênµ°Ñ Íý98$AÇZÒ‰*Š=HîÆ«·ù¢“"–“5Ý ÝÑ-mër·;'1GªÓ•õ$>„C6+(ÈÅÖc„è?íOsÎgµ2¶“îÕNYÆ;U[F³bí«#)“/ ¥¡R.d,üL7ñ:ÿÿŒ×‚ª¼–]1ãqúBÍü+B¶Ha³êÑ©N9¬Mî¢zÔ< °óÔ|¿“¶ñ†qvP”¶ó†ÑÄ…À¿qCi¿áf M’#ì¿)$¸d7{™lû ÍóX†«}y‹Ìc00õ€9´É4SìbÚÅ}½Æ ÃÓ4k,Ãb@¿ŒÐ©Þ¼zÛÏzišºø»‰í¬Ö¡ÑY\¸Û¶dUáRVSoì3¯ºûÈ=§‡œKwƒsl+³BˆíѹU¢èÏHõg‚íiTN•z™sæ8çf-à•}k´Râràèh×ø H°¸Å™u2Ws2k¿qÀó!Üp¼Ý$å°-cØóëÀ×S×kÔÅ]Û«¯ ­Nà4ÁÓ@*ÖqøZ™k`Ý·Úú¾Û¬õ÷§u\ÜL»úQ3FaÒêÑàq†3,ëÆº[÷¡c`ºn¯½¼ÀòTüˆ§”†ýüã±8›Â~9|ÀRö £ÓŠ­ØàT(Ø!°à£Ì €µ9[=Ä#ZOXƒßê-Îø®`žY&ᄲ‡R—ëþ­FÓ endstream endobj 17 0 obj <> endobj 18 0 obj [ 19 0 R] endobj 19 0 obj <> endobj 20 0 obj <> endobj 21 0 obj <> endobj 22 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 23 0 R/Group<>/Tabs/S/StructParents 2>> endobj 23 0 obj <> stream xœÍ\moÛ8þ ÿ_°±"’¢^Š"@^ÚÝÞ¡‡ pt…â(‰qŽ:r»½_3C½Z¤““Űc½Îœyæ™!ÙãÓu5¿)f•xýúø´ªŠÙ]y->_®þ8¾üñP(nçË¢š¯–ÇŸ6Wžú­,®Ëõɉ8»8_¢0ÂY–$"&7"‹•X—‡ÿúE,Î.ŽßJ!•¸¼9úõðàóä2È&wA<)Eð‡¸üûáÁxïÇÃgk ¶5HÓШ$¸–÷Ÿ=ÅŒšé0ò‹™²‰õg_Ì}NÊu0M&"˜ªI±˜ßâÁ:”.-+øE—~ŸÓlò÷§ÁTO~ð@2›<Óxò€0ƒ¯ù >>ŸÁ³hA¯bjˆ2&̼ ùùч»Ä›÷çâØcìg«ªZÝûíýíjUñÙ»ÎBÃÓ(¸ËhÆ™ÐF$BÆôþî–§®ûôÄgRÔSÕ#E÷‘ùEŒûâc7†âøŽÞûów"bƒ Ø :ÛŠœqt¢CåóýŠ<ï ü*Ÿø¹¨öEº‘2ÊÃÈ«A NL XŸ^”­JÅ–Ìí1ú?Z 鋊Îàwy}$ aŸxÄWÕ­€×¦øÚ¼üJöoµ@sd…âµN!º«¸Å—lAU£/àSÚ¾¸÷ ¾‡ž áÛLþ¨h(ˆ¾Q}lb!µ¼\>nñJ-„iâ<Sß$¹ «»v1‰n ]i—ìAÏ‘ô’¬Ç À~¹nº¼`3I™„™O#>×yh¼ ÷Œ<—ì$3ýòMLUh¼=¹#ÐwVÖsËb± Lí$!›Ž*ÍCíÕ±Çì¦5¼âÐŒ0„I%gaⵌù#BõLU\±ÉLã0÷‰d#‚:ÝÕ2 2‹9Ú¼*¯a°·½œ î ƒÓçx^UÌ— Mtj(¬]C<3on`†ÄH†ñ˜„o ‚ëV«²@Þ{×aϱ€FVå=ÜáqQT¥˜/Eu}kMûµ@;25ΗGtþ; Â]~›!4“tKR¿xwGßQZÚI[uؽno•PT=ºóe3Î -ñjÅçðuï&à÷ŽÞ:¼Å¡5´y-o®ö=±ÓžÆ4” E³8Œ2ŸÂG|hQPðÈ¡qÂq©«²»ÖTöÔÂŒS,…)–[‹×‘4§'ñkx¯>™*8ŒTû[›ÓHŸ¥ð÷ì„+8d ƒƒ¿ëëæßÙ~™JÝyaÏ:Z—],V`_ø8Á¸Fǰ{T Uø*↻b±A}l½Œ¼‰g ÌÑ[àµÜ~bRWÛ¯«W [²U À}"·Z6JºäÏ&]Ú×dmÜÐ@Ñ_OîpdøU ŽU„jpáA?ŒBíÓå­Â¥z¶„× bW¢Én:¬îîÂö‘¸.‰ÖPžRóœ¹S½­Mîù†ñà&ºËËâÍn¿¢ü¸Vc£ÊWt²r‰!¼äKh5Ž›[ìQóÐqÉ­ Tñ åƒåù1dØA„ ÖïZ˜ôF~È ¶êb€&3ƒ…É3Äq‹4%=Á–\h,¡ø:€ )t,ýRö5""˜\†É˜*~BÖå+2k¦–åè÷‰ï!Ní=Œ©hæ9€:XßP >IL¨½Mæke’!òˆ!_i¸èq Î㿤}y‚üÍ#ÆfÑäðøÙÔI÷¦†Ý®Š2ÊÊÖdÀ|‰²;rq6oN!ýô¨~´Up’b±6­(®{ÎQTâ;ò!{©-¶í/ª:;ZqúnƒIîjÈ=1çYbtq°ŸH ‚!_Ö#“ˆŒÃ­;^Âp&cÖòâìŸDž-Í*‹"" Œ*/yŠ2Q·[ Š–ü'šI)w`šÌ“™Å7·6ŸØÄävˆÝbf+dë@F|À¦¤Ä\Í#±æ:7½™½…ÀRDý0f=T€@*Ý£4ßÛéÁŽÑ¶DµXühý‡È”­Ì¬Iç‘”oN¦Îˈî“oàƒO_œàÙ4Áú‹4ÑÉ4ÖašKrX¡AÉÙywj“¼µá‰tü²(6XÄGá|Œ…Œ®ñjœÉ= õ] YÖZCã\ýúÁo²†bˆGé±É.ë P´Ä«aF>´[¼XCNW^reŸ˜ŒgÔÖj6Vô |޵ýf©š¸@¶%‘wcÄG:îIWmËÑsŠVs_íŽ)+@jéÓ Ô%Ú&æa4èåÄ'8&ÞºpqräP™[1B•Æârö™q.NC6Ÿy$‚‘/ûÈkû¼³j¤ --¸nLôhÛˆ»Ù ÊÈí¾«@æ0Tn»Ô©«­ûR‘¨Dߨ@—´ï£äÕÕwlE‰ µlS °i¬D·V]àYöI4¥r$žX°˜ÊØT6&Šb÷†ýI©­$ˆ‹¡àì£ôjüTyYq•—ciÜŽýdà9·ªköŠSk>uÛ<Êr…ù„GÝqÈ!×ÂL{ÝD‹§Ük{$§m技ĭº3º½PZ§ÄÍ<š4Á‘MZ®ÃØ;d½2CË{iÐ0ªqÍ´''v¶þinÁ ¸ØE`OϰUªe”„Ú'—{SŒ€wEÁú”¯ª!³0ó5ËÅRΩñ ûv — 4ºÛš²$òP{Ǹ¸ªKÖêÉð$8}TþÖÔ·æºáT pNµ«mdî³Æ!ÖÝ÷ùIMƒQŒ5<òÀf±r¼=•W,9wã)oÜ‹pJ’=Ô‡Ñ! ™ª[î‚„Žs—˜›6†Rõ²ºé8«ƒ 4§b’Íê˜4“Z¡ë¸{Å'%¡nv‹áùó“‰) Ð2}N»ø‡/÷}^žø’ëj•ºÚ½_þþÜÜ·.“égWÉve¡x׎Â_“ì1@d\#అ妞"È•¶µ?•ê¥ÞDoª´kÐi>¯]À:,´û22¿í°E…Xe85åé:2ÉÍ“Qá)[Q×xôb,}SPðˆ9ívIt€†{ÞBëHØp8«ôéÒNõÎv-„sà ÅÕ‘Ä ˜GÁŸã¸|)ô™G'¬ÊEŠ»*Gq˜+Ä—È,b㢞.Zw/¸¨Œ&Ôé™»Ó¸óõCž…^­F¹o@Q‰tIõe/S9\«Ëžºø³„AÖ2•ý ªÃ·*,Óñõ{ ѹKÌE`Åà Î`B‚k¼ ŒI7 ­xiž ‡ØQzY¢¤€£jo ˜y±‚ ·CØ€Dñ• #¬yyd†âQl(»s°q1ôˆÞjëq75à5럺UK¸¨¢óºóQ±”Ø­;Ûn XËP¦>1.“lwMÖSèn³•Š®3#°L½¸<º¡ÝT«¡têXVxÀW;Ñ1y¾[n„“¹ ø Zõ9ñšªØðb`_ƧcÝ4†×»…Œ튖ÜóMì'¸Å­…Mp÷¯&##ãªæ‹€se’R´ãf‡¢Þ‘¼ŸÀd Ç:”ny¸ø#Ù{÷N¶%&A6ðåq³ÔÞ·%Ãh’;dH¾ÿu"%!®ñacäLÚgþUus,áHB¿áv¨rI› ìZÝ©´ûóížý­eN÷¢-ûïfç©SOëêeüüë#M„³_/ `&Raî¸þ6NÞx(SíÇœ€§f‡,ZMlL_f¸Â“uC„[¬5ó¶t¶½s‡¾ßcÞõOÚw[tÛqê ÿýòÍîG#¾!Ó>ß`]7® 8ըŏb+á¦_íÓ„ ôeF aÝR,Á³7ÑnõÛ¹•ïkM†9xŠ£g°çV9iL5 *ÿ,6¬;”tLk§Ý¢·´e~)O-OÒ\ÿåT.Âäÿ?n¥©U endstream endobj 24 0 obj <> endobj 25 0 obj [ 26 0 R] endobj 26 0 obj <> endobj 27 0 obj <> endobj 28 0 obj <> endobj 29 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 30 0 R/Group<>/Tabs/S/StructParents 3>> endobj 30 0 obj <> stream xœ½\[oÛF~7àÿ0b×¢8^ƒ¢@â4íî"A 탛Z¢lbeI‘è$Þ_ßsÎð*ÎX²s”IHqÄs¿|gF¼Þ–Å"›•âçŸ'¯Ë2›Ýåsq=™®7Ÿ&ÓÇM>ù˜Ý«¬,Ö«ÉÕÃM‰ýžgó|ûË/âÍÛKñùüÌs=ü/I¢Hx"LC‘¾Øæçgý$Vçgo¦çg“wRH_LçgyBŠ0rã8qº><¹‡E¿]Åâvo·t—Tw¿Ÿ]¦N2ºs‚Q.œObúŸó³_὜ŸÍ¿ÏA»¡ßã€Wôþ÷B2Aåzv2c62}vÉÜ;ñ(ß:ãh$œ±?Ê–Å-Þ¬@¡ôhUÂ=ú{䌓Ñß¿vÆjô·ƒ7‘Éh猃Ñ 0ƒ¿Š~½˜ÁwÑ;œ^Å$ˆ†nbäùÖ‡Uâ×÷—bbqö7ë²\ßÛýýÝz]òù»JÜG(X*ß ¡B ÐûÛ%‡žÛøÄïÄȧ?d40ú2‰ÄP´6“h½÷—ÿ~+<¶„ÈÎ>#ï¶èñk'¢¡Ø(ïà|NþO+2ˆ¤x?Štx,s® Qì*ecõ¥)qH&†/&62:5üä:¾Èª]ý’W*©+mÜ\¢‹•jfÐRÄÐ}7)UöÈnmËø·9}6ƒû»z…5¿ÑÓÏð~UçÐG\˦ô@BYmK|åŸÐóV3Iûòž5âÝ|Oa´Æ…¯L ‘Žó’þ)ò/hò|îÖœtÊt?JÐižŠºA©ÐJ(X™mc-?=ŒÙÜ*PTaÌò±©Ñ"7²QXb«—ž«,Òx§ˆéìzô/Ÿ`ä[ ^£?Š0úOm¥(q“ÄF¦„ÄÁE( ž ÄÖúIâFÊFfŽ¡¹,01‹2ŸCþìb¾Ä%t:ÁR’™×ÑZì°-¤Ë&ßΛ¼ýT ÂAµÔ9c‡k0‹.Káø^ú.{æò¤ [ Cn*¶(‰[Š–·J‡ÓQG’^feN‚^ìKJ—ÚbtbÃ7\1¦b, Qvu}n"dhö¦cAËm›‡†ˆÓ^@w–èשÌHC¥ÈVóº}Éá2êût/|ÉÜZïŒjª-Æ&5õóãáª5„0:mÖ°>p’ž#‰ÕÚKX·³2e<ú ªõÕ7Á \uÓClÝ­ø¶ŒD5¦0J~Ê.³6† ­>ÛËT.¦ð"WÙèò!/u=«x4ÌhºeÔ?:H‹2Jþ(y1;ÉŽ ®EÊ °'‹©%ËsIŸHMïÄJ†à¡…L?hR&UúRBøÃ4éË„ÈV‘¾ïQ1“¤jÕ('Þ|½ÉÅfKy}çÈ€2cÊOÜàäâ+6µŠ¯Ç _©=½s;¦OeëÀà£ÔFå®*jø‡*©Tº©o£yapP‰éözuík{ØY=4ÙáÝ^­ks’€]†£ßã»l*¦]‚UÒ(¡åÚ–á¦5Ò1§›£¥ ï¶tÆR2VIåCOl¢ïix0 •\³Ð):ˆ¶ôýçÒW6úQj¢ÿÒØ‰<Úó1’cx©Š¨ ä .бçúvÁ)V±6ˆÝh˜þB´Þ‰ ±ÚΕ²Ä2ÛËúj^•û¢,ÕÀWøRÚŒôê¡q/+ÂV²ü\Ö&_½UaÝŽ¤ù7‚T8¶Öè(Ÿ#ãУgeÊt¾@®MýœRƒÆ¶‰Á^z=Mʧ6‰ßÀÌå²FN{잟¿è#ýÙÉüHça2',Žûýu‹oª­Dº~¨íŸÏ/h"¬Þ‡ ÌpÖ‰v×êÙ¶ü葇}—¦ãTՌٞ2Ù£Sdˆì¦¤ž=-óÎä­³Xë¯Õ¸Y‡ßcƒS;ql´: h+„b¡çÅu£ß˨ý~Ç.ÍàÿºÀ¶ÑjžÍºèØR£{é†×@"ƒŽÜ/ê¨î– =)@ØÆ—©Õ+>°Ýn˜Øè*<Á *º4Ú؈”i)åP7W$8\}Æ} ì Z‡ ò®J,e€# C¯Øô.c4³™ ŸuAÚ…ù`Ÿ6õÇc;R÷Iæ>X—%·l}c b£—å˜ÑÁ樊K(bk ì]E0¡f^qV)C7´rôᨺ¥{l¾£ÚÛ›ÌC›Ò©„}sò¡/Ž*‹ ìÆÈ,°ËÊPÊ[JÓUV¨lf·%[ºÆ¹¥…7>oQ4·´9Â[drT—3ð¡µáPË©¼ °Op¤&…(ä‚–*UèÓƒ“q™îèá/ªD³õ6¿ÒÍ':£;I7±1ÁèN& jı¹«‡:hî‡Êܽi£q#°îãìmÑšNÊŒ{¦—ØÔP‰n–™îÚ—ô ±ùc BÄâ̶°ú],qÖk,M §S”¾Ô=¢‚õ‘ôZoQ«QAûz4’Ò@`\%D|È[Ã"P²±ÞÇ‚0Æ9ŠOìúkœª_:kŸé@THw›jB¡qQo`1@‚Oî'~¥G3EÈÚù<@$ Š{ÐO­|®·«óMo¿°Ã5/ðQA:ÔͶ}H~G õ[ü(´Sü®@2" åÇG¨Ä%¢ ã1ÔH+$!}÷Ð\]UK0òwdù>«2Ð4X8å O<Àf£2ut^-³¥X9ê¸A >¬&/íÈ«À³Aº‘Ð'½—Ø6 ¾¶!¦ífeZÓ´šÈÜ4ÝÁTƒ)JÁ²BK¼åͼ9™>ÓvÏXüènPyÐ Z$䶪ŸP!ƒCu€7 n¸Ã«?AÁdØmAZrd¨+ì K2c/ˆ“ oŒ½`„ÐÂBÆ0ÐÕ#î"Ã28ëí†ç–¢Ö)¼?Ê£Â<ŠYVФ‰Ìª ³ßu7 4l%¿zË6°ñ¬LðhY]žÂ£ãO†Xøbü}BŒï·9ЗÚäÆ žÑªÍaÕrîƒ"C°tfÌø–è´ßmwÛçAˆÚ•UjRcµA·rôÄï¨ BàŠÌ¢+”°=®¢Âwœ,¥Ÿ¨Xxgv?§~¼Ïðòã,‡&'–44°éG ¾Q¤ìÓgx õ‘¦˜O„Ù>ú(Õ¥y²þRbÙàU®Í‘dJÅxk„oPÌs§âÄF±kõу,d^Ô¶^}øØ œøö$è0!³6¬&™¢7¶¡yO‰v?…ñ¥ôÐúfFó‡"ë›Éiý¢5=eXèy»7Ëì ý‰Y=Vw}™¦”–Ä Ó„ï ‘·søÚlf¾w*qÅBeÊvèý2Z‚ç`ž•ˆôO¦è£'sĘ~vœ%;$×1©¼—йvh¤—¸ßÿ"ÁvøÏB†pëlQ7!×Õi„ ÍÕ€ b êVuÐÎ[€€ÛmÈOlˆ/ˆÉ±ÍL›lóÌZ¯ñ endstream endobj 31 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 32 0 R/Group<>/Tabs/S/StructParents 4>> endobj 32 0 obj <> stream xœµZ[oã¶~ÿÀGiQË¢(Jȵ—ƒZ4ÀyØ.´Ž6*Û©­´ÛýõgfHÝ,1Ž f,Þf8×CÍ/·uù5_Öìâb~Y×ùò©x`Ÿæ÷›çÏóûŸ‹ù¯ùc¹Îër³žÿþò¥Æ¦ŸŠü¡Ø.ìêæšýu~!þS*IXÈd&™Š#¶-ÎÏþû­ÏÏ®îÏÏæwœñˆÝ=?ã0(dœÉ$HSÉÒLô¬`п§ìq+²GzSæíÇó³OÞ½¯¼'?ö æf÷¿œŸÝº¿Ÿ½™ƒhŸƒ4 d4à€zžHf´Q%‚ÐNfæŒÌHž}2+?õŠ­?K<æÏ"/¯ÊG|Yƒ@©k]Ã/êúÃógÊûÏÇK&¼?||a>WÞΟÅÞ3*` ʯ8½\Â\´?ƒ¥m$’2PÖ¯}Ån?^³¹Åد6u½YÙíýn³©ÝÙ»Pt³)%EÄŠ ÉÆcZ¿r¨ßÆ'ÎI‘Ïh̨1z e'1–ÅoÙüWÔÞÇëŸoXè,ÅÙÙg„€\âo&½¥Ÿx_9køåSc‚‘‰u„›$sòH-f <åMÈ“»óÛEÄ/€XÌ"Óž…‹™èµ¥r‘Â#Œ`øå"¾ÀY¡RˆÍ¬4YHì ¸>®}%u‹žÓ#@Ú#€+CŽºNiŶKeÔœÞЪÈY³Vv‰Ï…èzÍfP»D~³ûæ ûàêºû&¸î¢?†r¤Ãzœh™´£ˆ™Ë…Y§• 6ÓºZ‚f3(ܲéRá xÞ.[Ê Qïnlq˜0Îjl× ‰žM©7B··(!ïhû$•‘” B¡üöUj÷¾qƒ*ÅPË8Ô‘Œ›P‰)¿@Ƥü gêm ˜l±âËèÎu?ÿjòª*×]qxà*îp™¡²±¹zG—;‹¸!⃡D?:–¾°ÐOÒlŠþ©®0"“„w-dv¾ðrL)+öÉŸñÌ”¾Æ?;?l…‰ç±m+`øCk+¥ÏSÝ^#ûìŠe.Z†…åCšÇjf=ÍÈt‚>¸j|¥½ÒHKMhèµ`dˆöRI90Íôò‚ ÂÃ8? -]šê¢É:”¦†q¿‰8&+´I¢Ë˜À$E7dV­Ky@G3³N·A“f]&‡Hñ ¹»;DJBÙÈPìËW®ˆ‰ð5b§žG&+Be'©ì.d4ÐæÑ sf<î¬A‘HahÛÜÚ¢4mº!1DÎP†¤Èñ6¡Hì,´ y }éŒ>ˆ‚Þ=µL‘a°¦LØýò“·^º"˜FT¾°ìë\WAf§ÆåÆŸe„¦(9b9_j¶ô¥XE^#¨’^ý¾Âaë–­w/;\€VÑ¥ª ®¨éC@:NQKÁqýyµ’΀Z¤²@)Û®I=u&õ$;…¾råM2NƒäýÚ$™¾7å½é•}’kæL¯‘œ¢ÿÞôJ©±q4ô1ñ>”¥äCÓ{=xØqV_’¡8‰£[6/Š㽿M’é{ѩ峱…¯íë `>GÚ4‹˜À³72)†ús}êÄ!ßý(º‹; ÁA„mÅxô¡Ï*F‘žÄ€3Ðs9Å€s™&³ÊÛãü¶DEsE7ƒ3½•ìAñ‰­wÀb{}E×H[|/¿µ­å®û‰‰Mõ?|ª¤ýï%xPªÇô| Ý knõ³Ç'ý oª…u½«®&øBWÛ¾ã­W†ÈÝ?ÐG׎tyvòåãøŒË ³If"»â0’Ô]fÝÐDs¥Wäx/÷ä[jŠyÍ gŽ êQŽŽÁ’SŽ×vãºïñEû×Ê/í6Ôuüa}¾WbŸéBýd‘ŽÄÍåF2IÐ~uaŽÕxtnIãy<‰ªåhP‰ïÚ‰X…ʆ„ÌÑþ•#œ½ŠùÛEa¿m° ¢©’¥]6Û¸æ´t«ÊË~5LHÑU Ï«áõPï~‡Yò›hœM›¨Q ÆØg_Æ†å¸æ~ÉRvlŠýuöê‚={ê_;5%›†‰²Lõ*ä 1Õ™r0:°ÅLumÄM”"µA“6ÑAS,ï 5g•EÈzÊ&tw×NQ‰Uµd…îŠ\ O¡l{:˜QUCD”žÄÀÑ…b«C­Ú“…Œ³ãx’‘}7ÅytæÏH Dâû ü¼†d=„=:™¯›4Ÿc#þ/k€Ž¼;‰çž Ïëì2þçó̼#Ô1g€h"¶öPV^U¬&@„[ô†ð¤ú€?ÂÿÞˆ˜ÆiöbGå LÅ<2a“"¶:ÌGû^¿î!'sB{øÁÖk”œð)öFì‰ Oë|ågn(1µIÚ[z®Y¾~hTUÀOŸÍ”Æ–¤§AÉ ¯³ ì\ €untÏt,ÕzÁ åÓ†Z;AHZmÍ·£dд(àúzC” _dSÂoà5î…Œ¶iñŒ2Ð|~«’à·á»oT7­)pÈLKi×Âôž`hÒ„PðÇ‹©–}i ètéëÒ‚9ÕD£­5T%ZGY£‹JC¢¥þlí Z“…{[ç锸{výæ]–´ÅÖ@Z»iX;,‰¸±óµ‰Šß÷(ã‡oà¢tvÔãAƒE$­Úµ ád:Ô@!”Tþ­åÏy9(Ž’€[ù<˜ §y–`Ùâè¯CŽ.ØÚÀ Oã)\ƒ ú4d­=×U½4#˜c!xP°Î¾ûá2šb?í†Ø)ÛØÙ~ÈŸü®¤S=À¸®«»[è‘L…’ê_*±âDú€S»¶ÏÛBnC׵ޥ0Mxm¨ßÔù ˜KËP¨Êï0÷scyè¥Ê5UÖ-³è³^olÜd.Â)ÑO~Õ ù®‡ã(ö@^Qm À$¶k¾ŽÝÛ NW§.ܶwŸ¨p‡ Ü÷¶U¥þ.Þ]!^¨WHôOg÷>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 34 0 R/Group<>/Tabs/S/StructParents 5>> endobj 34 0 obj <> stream xœµZëoÛ6ÿ ÿ?JC%“"©Ç`pœ¤ë†`ºaPb%5æØ^¬¬è¿;’zYb{LÔ’ø¸Ó=wÔdþ\®òû’L§“yYæ÷_Š%ù<¹ÝîþœÜ~Û“Oùãj“—«ífrórW⣟Š|Y<ÏfäârAþ9?£!ÅiÇ„™I’Šˆ<çg¿ÿ@6çg·çg“kFXDnÎÏL¢„‡I"I’É0‚‘'˜ôþ&!{Ø‘<ª»Ôܽ??ûìÝú©÷Å^Aü?ÉíÏçgW°ïoçg¯æ :ä IBu8P„ ½¿O$Ó{Ñ”‡ÔN&pF¦'Ï6™'?ñŠg?ˆ=â‘—¯Wx³ª¡M WjèÏRï—s?àÞ>ÞŸ¥ÞÞ„·CÜë\¾º‡µh~[9z‘HÊ0µ¾ÈñÚ‡Yäêã‚L,Æ~±-Ëí“ÝÞ¯·ÛÒ½ó4”n^ fI…"%\’˜0¡öo¦ŒÛøÄ5 òõ{ŒžF"µ“èËâ·F‡dò µ÷qñá’ÐcUÂm!HHdÇ•göÈÄTÇ™!2ö‚ÜÞö¶¹+‚Iô½÷:pO®ÌYhøýK?ȼ­o"F ¼)I¾ÛA4Yø£†00=cÔÙ» -LÐÛø:5¯ Pˆo}}|YõVêwΈÆQ(SQgY†ÅqÈ­"ü×$ä–_bš´f7Uf¹‡›êÊ&Åfÿ²Ç5\nýT_ᤘTîª |̼\Ï+Ð00­ó²]½!(½Ò6z>9óÊB1{ô¹«X'Ùý¨f‹Žyj–ïǨX¡" ½S=¾G&¥ß{­ÂÇ7R†ƒ¡ýPÓ#Ìh¡ÆBwL™:e2Dßuj³¹C‰Þ“)ÎR‡ƒåÌb=´Æ[ÔÁÌ™Ô#†RfgLêÒ•Ç\Ñ¿)Ê}øË/Ût\7ƒ¯ ʃßC ÔÕ ;óW§’”u.1vâ´; ‹Å¬ª« Äâ:¨ª…KÄðM)Є]ŒÏùzMrÅî”ë0í.Æ PŒMË”_ªß©•_$î¯jì/~—¡5!ö&(·üwßÔý%Q7/­]Ejø¤yì W Çû.¯BѺPaÈ4 !¹­Þ¯ ‚Ó’ý ‘…©…Ÿ)eÉå,†Ÿ4› øÉæ”ÉËYÀ’f(‰qˆR> "¸eT=¥Qo„^«=Ø•~„×RoKõ- 16Ça$3´uÀx‹²œ%;f4Ä_Áê‚™ýp©š?Ç «q.¯f®â<§afSú©q®§JÎîoÕe¥¥!.¯áOv„Í[©¿0ª™WÊSâÖL”ÌNÛªÄ×z¨Z"–€°ãs¨ìÀ˜…1:ósÀPfì$‰ÝhÛ1¿h¸­c¯äu‡‚†ølm¾Õ±GùõÖù9†”u‰}ÄØs†#hžÛØË2™³,Cù)ô™³Æ•H™K³  $–u&š¾è޲)§V>S9SèG󗵨Aõ¼ÄEîð¿Ø±p<ªg­/!€ð!Bž0§!*_=ÌŽ)¼q¸ˆTZVÂDŸ¾là¡ÊM¿X’þ–³!? ‡ÌÓ¸_nÞnô+" qwÞ,¨Yb“Ù¨Òœõ^ONbÀYóE09Ä€s&£ýùÑYƒ'ù±Q¡ÝéÁƒêÀ%ãašöáB'nb“§[Zਠ·ª´$UàÀ@-õ(Jõ#¼†XŸtÐaÇéµÁmsø,àÍÆ¦tPä"é"ŠìDà ÓŠ«·Av‘d!· Õ´Ã3@fU¼Ï!Ž«•RA0”Œq‡ôã æ22n†³’…3µÿ÷¤aLA®¶®¨²´·±Þ y¢Ýᯮ>*\\Ï®ìÙ™Ää÷Ìj~£AÅY‡' Ϩfàè–-Up‘ 1à:UXÈ|ÀüYÁŒéR÷=ÓC¿ÃŽÒ[ôv)ö–,,ŠþèöU÷Q2ÄÀÍû@­o#°í"{Í^Ó¯‚x°z}´EVËBA®UYUWïÞ®vˆäð+Ždÿ®n=…î½7 ñ•ÀP÷¥vxoºÍº+üF‡oðÂÈ&ÙQÕ:ër*Obàè’ÒæÖQ íí …̲*Ôê"®pÖƃw ÙÑÃÕ£ f›~£˜ 1 ¾HÐ}Æ|½F›ÿZù¤r5ÝEUnrЦ>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 36 0 R/Group<>/Tabs/S/StructParents 6>> endobj 36 0 obj <> stream xœ½ZYoÛ8~7àÿÀG±ˆi‘º @Ͻ E²Ø‡4Xȶœ õµ6Ýmÿýr†2%WbUÌæA1-’3œã›ƒž¾ÜËr™Ï%¹¾ž¾”2Ÿ*äaz¿Ý=Nï¿íŠéûü©Üä²Ün¦wÇ™„¯~-òE±¿¹!¯Þ¼&ÿŒG>óá/Mã˜ø$Ê"’†‚ì‹ñè¯d3½º¦ï8á‚Ü/Ç#®&ù„“(fI‘$‹˜PoÖjÒ/w y:¨ÉŽÒjôËxôàÝÓÔûDC¯ ô‘Üÿ>½Uû~~šñ=IÂ"qÆ®è}¾Lë iÀ|;™‰32-y6ɬiâ{:‰=B'ÂËWå 6J øj#Õ'|õÑ£“Ôûãö%ÞG Byêè$ôv €¹z”KX^ÎÕZ°š©­DDK­®}5‹¼½}M¦cµ•r»¶Ûû»íVº³÷ e‘›C©YQ X˜’ "1á!î_Oé{oãÖ$À§h3š´½ŒDj'іŇZ‡dú´wûú·7Ī’ÀAaì¸òÌ™Ø×8ÓMF‚#ý½€çÌE9?8Ø¥Ú&ÿè`×K*„WŒ¬àQÐ@„‘œN"o ÃWœðP0ÿgܲ$î,˜‰ ‹þÝŽFg°Y\e–±ÈJ÷RE·¨p_°ÀFE~¢1De¥Ùr£º€ñÕ„š­z»4£Æd™ïÁ,TRñGâ[XšË|¦vÉ1Þè™ÿª(Sª• nvth²˜qû±H¾ùFÀT‘“£b ¡5øX¿ªTà —`ö¸F‡Z|BÍ!Úê#nU2³‡)ß̼Ê2V0¹:b˜¨ ú“æÑr áÌ-|ÎÂ^¤oÑ\|œd]ô]¼…ÌΨøQ~ –r¤ð^½1Øè y¬¼ÕÂMŸÐCWJ£¤‹þ]!kßh 8ÂG¹V¾q¬òRœµscQÈ‚ÀÆ™³LœG)óS™/)ùê!Aã €¡Øpd­ä“Ë9p¡‹ŸÃ®î$ç0qµ"›£’ VÅVQå²{\å T‚8c™íx}ö9³¯ º„~ì T¸UwõœTºÉ`|B¿!×yE0»Â|Ò–øKmLôÉ:q¥ë(ã,n°w[eÜèsƒ#UáªáÅxàI#¡ÀàO¹v¹:Z±VcܪŽÌ¹$²ê<^_0cY ÓªŠ¹z Zq0£Í®Àž¼¹ª—…áö³Éphx48¸ÔÑ£éöë*'ÚWgsäá'±+Gï;Âô93ëf ¬Ê ¬Ÿ(ËÜN . ‘`9EŸñ¦ÎŒ7LX<¨2W@¥P¤‹¾k ²Y¯sí"ލeP‰XhõÖyƒ[VúA·Xu„ ìh;íyÁæÕŠ5y˜Ãf´Šñ]õ”®V…‘’ŒÀŒíiͦH²‚JúÂÇ=ôŽ’”0£†Flÿµ‘Ï]¶…,6‰õªÌYm¦ü"WA6? #…CÁ³û¡… ¦ë‰6”C½}Jöxž:3"ôeA­ [½â\Zõ$] Øêð˜Ù­ûy<>˜„~oú!ØàÐÛàl;ÚˆxysOžïÆ®ª~‚«x˜ èwXQ÷hÎÏ¿¡B,fN£ßQÎ̧jå4D©›6J.»Ó‡%L„¯W (ƒê{ ìô¨2f¦ò$½¸ÎÜ AÌmŠò¨Koè$óŠ%êx xªB‘rÜPî±0i+¾|ŽîaqÍÂj¯JœÝ? žt1`Ký!°œ. f&(Ù.3Oí€w…u]=3ÃF {E 5x–XNöæáN3Hm'î¹³j‹+>üáà(g¬67äIØÅ€k7´™;#ýˆL¯8ݶðHt1ð{¦Ô•d7x2‡_“•Ð7 àŽb¹jÕ»‹@q ÷nV{eå,æƒó?«íû)óŸÿjÊBæ‹321þpÒB¦KœÿŒ7~r endstream endobj 37 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 38 0 R/Group<>/Tabs/S/StructParents 7>> endobj 38 0 obj <> stream xœ½ZYoã8~ÿÀGkË¢(ê§3{ t€~˜,˜X‰…–팭t’ýõSU¤[b»ãeo€Ø¦Hª.ÖW‡4™m«âAÝWìòr2«*u¿Ìì÷ÉíæéÏÉíÛS>ùU=kU›õäÓó]…—þ‘«E¾NÙÕõœýu~øþ¥i³€ÉL²4 Ù6??ûü[ŸŸ]ÝžŸMn8ã!»}8?ã°(`œÉØOÉ’Lú!̬`Ñ/Ÿö¸ƒ;²G¥fôËùÙï£[/-½h”3ïOvû¯ó³pßßÎϾ›ƒðƒ$ñe¸Ç6ô¾œH¦'h*üÀNfìŒLOŸ]2+/å[o˜7Gª,q°…ÒÔº‚_4õÇȧ£œyc1úÃÃóx:Úyãhô„¸‡â·÷°O‡—Á­ Jé§VAÞo}XÅ>|œ³‰å°_mªj³²Ÿ÷›Í¦rwÞEêK7BÁ*)B?J™,f<¢û·KŽÍÛøÄ= òöM{ŒžF"µ“èëâ·Ö†lò+ZïãüŸ×,pA‘Dvù´ôähãÅ£8ätúÉ?ª%\‚ñWo,WÑ<øAB.E qëCãqÆ¡|W^ÂS@¯ÔÆû{ºãÎtŠSè‡ï¥/lôîGýCt*ªöÈÄŽÃd–ÎÈ|SšcÚ®¬'Ù}‹'(ú¤1f\°ÅAÅ–yù䙃Oáe×øˆ‚¸“ÿÁ»¨²d• ðf£M\"½Ý™ÿ„iä§©Mâcœi\&§Ð—®ü'rˆþ-ê:÷Ähõ„¨Uâ‡B´«Ð8¡m«<.ÁL” ⺵ÇãÑ#vå\ ?6f)+v¦,`ç.…³…ÌàV0èG­Yt$ªÍrIôŒ´vç…Æ6Í5\¼h\¹ðx¢¯“§Î —JŒR‰Ž.qåe2ã~<áŸ×ºé,â”üŸÂüóå×hP*/äæt»jã¥zñ]ƒvÏ5¾å ¿¾ñwÜŠ#Ú~;´î!ã "ëd¿Xƒ¸ª¼`/žFlJß—5=B}ÅÏfcìÍO¨haþâÉòÖ#vг!;U9Œ¥ªòVTÕ²÷dЮẸËü‚™sŸÐ<é€FZYh ŒjŠÄ]xÑp|k·•9ÝðÞ‹›õÖhÙÄ«xŸ¼ôX‡6ìØ/¬íÁ¯æ¤¥ÿ°gŠ–™ü+…P:ªdx~ËM½3/ßôatl™(ñã>ôn5I°Ê‚¡•â+µççôÊtÑyAS/æ$îɲXAð/ª£ØÓžlÕÚùÙ”°É‚&¯¾ä5£ÖëÞšé!/ò0Uu³“Úü;ïlàt´ ©$ œÜ­°"”C†Ø;ÿEUºk)HÓ ôSÇàDßu`!³¢¼ì?«F,Šå®Âu€y-t֔ΠòHB=>ã.À “N¤ëD>ò»RMÑÍW¶!v×xj ¿!mÁ‚Š••©vªZ¤PÎJ(õ…UÊÁNÃwäªl‚œŽù¤¨Uƒ_xôÒc½2_Ô™#îFEUìNí6Ý<§ÁК5·Ø‰dH#(ƒB€Ãÿƒ¾ë¢ñöÀ¼4Vš×¶÷IcÕ©;­­PÛÍ}v[‡«öôQÑžÓï±½F m©½’-V,!|–oCÇ@£ûÛìîÁãâ‡Z„Ë!‹üä×Z©#¯™NJ¡Uç£h%Ê‚^÷ÃbAù“Yð-—sWè©Ïm‚Å4g2‘ ì7¼›g2‘pl«ÿè e!ƒ1ë•b–p³‚b–…ìQõ:k‰(bàS®yÐ_–^§Õåê!Š/lÔO}†Õ§Â9*y˜Š³GXœTZUÙ>ÂjC¤†T¬j@¶*¾Ræ]zaàKb?°êáèasÖ5arÎÚ†"ÿ0&C½Æíæµhº5— Gº;Fm¯;ü ö»v–Ðt˜­£êw#Òfÿ0¥~h¿k›š4EUÆGü öYÉÚÚ3˜é,´ödÆ’üÕUûû}µËvÐÇ1Ç(ó)^4yéLÿ°ŸÞi Ô_£”«bØ›xGÙé2´­:Ø&:Ûò¿žñ¦e?t›„…1Rû”ü¤rm.UL•be_ëßHw‹J§ü%)ó¢‘[Ôm÷v_ÀqU‚Ù¸NúôœnnÛNO›“k–ñ¾¥éí +…†Z½K]‚älc ^)Ð=0»`xïä0­^°,Mixšö¥Mû"Ðþe 䇩#;ƒ}í”NÕž@±$Pµ Ä9Mà‹ ŸDLfõOž\OcœœM#½FÈøOq4/„ ÙÌÃõé˜.]Ãî˜n’ÍÌícZ…Cš½žf—õUÚŠ–d˜NÇq}½Þ5£)ܜӱèL›]ivŒ„m¿ÖB‡ky ÂeûSóù¾¦º— é\ oÁ«“ƒi/·žœ’:²O)šwyTÛåoÇÆ³p{»žÃPR»Ol ¦*…½{Õ)™÷›ÄTϨ9PÝ×/‡µXHˆòX§‡Ëñ¢3„Òˆ/Õ‹—òýöð@4s–?ŠHø™Mô£éƒ³Ça<‹1œ¿›w7pmé#O¢!\§2‹úùg牪#ÂYŘ…ìQõ¾»?m Y\† ÆE„u ,靸ð,ÙGÁ l·˜Ïy0íàXÆa=Âc¶œxU#0 hr¸±!`žv"3Ùl* AD΃­l—×hJóW¿’M0À©z+»%nt!ÚHW³Šß€Ï ÷ACkëA´«®›^Ø3—€¹¨'Z/Xi‰šËf“±Ï‡d‡Ùžç¼ L@@«Zî/–Þa%©ŸXŽž»&JC|ÄvÂ;gŽh"8>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 40 0 R/Group<>/Tabs/S/StructParents 8>> endobj 40 0 obj <> stream xœ­Z[Oã8~Gâ?ø±Y‘4Žã\V¨Ø›f«}˜Ù‡Ð¨ÚNkf4ûë÷œãÜ“i×# ØñwŽ}.Ÿ=½Ø©Õc¶Pìü|z¡T¶xΗìÓô~³ý{zÿ}›O?dO«u¦V›õôîíAá«_ól™ïf3vy5g_NO|ÏÇIEÌg2•, ¶ËOOþú‰­OO.ïOO¦7œñ€Ý?žžpèä3Îdäűdq*½Z^¡Ó/w1{ÚÈ쉞’âé—Ó“O“{'™<;á$gÎßìþ÷Ó“k÷ãéÉKt%ˆcO- ¸ÀûçH˜ž¢‰ð|3Œk ¦7ŸM˜W'žä;Ç&ÌqƒIö²z‡5L(5­üEMŸ'Ž›Lþ¸½p\1ùìàsx2Ù;n8Ùâ,àÇê?_-à[´'…¡,)Hé%FE_}èÅ®oçlj0öËR›W³½ßl6Êž½‹Ä“v”‚^R^˜0!YÄxHã×]ÆÚMrâ71ÊôM{‚‘˜!úsñ±^C6ý€«w;ÿíŠùÖBP(Qœ® o`ædô`%j†Nî¡íþE9¢éO'¢þŠmÑTŽŽ¥VÙ t£ è€è}æ¸àPèw«µ#µ¹œSãu§÷Õ‡™ƒáOä±öcú©V9{ÈÕ7ˆyŽn».¹ û ¢•ˆWMz,ükY>©gh;:Ö§:CS¨™ÊP´†®¥ nhê±Ú£ºõÂd_ñ'ªµÓ+ç‘>¶"HŸ•èÀôì•[³WŸ{á¨ãôðƒCñ…?ŠÓ!üc3Y&ò)/`îWB‚ÕÍð¯ÝS’-èTxÒˆ<6ÁÂÖG2ÔüŸÕ–éÌw2÷Ù€ÓSöò§ê_t9É3ÌÝÏÿÃ'z$*|/2I|,‡@‰Oæ37: 1sx'¯ 9šIl¾˜…e¯Tÿ†–°Ýo ÀCzáóèÆçóX†#Ì9áà˜Ø,/ð±„ò_ÏÄ9µRkØþ¶§G÷`Ží3ÇL}¨¥ôƒç¢ï ýò¦ýNÂw¨P|5‚ {JS(d2³•X8q ƒiŒ¹lhÍe…<_Z‹Ér’½Ý…1&ÃìæìKªs¾xÖÑÙVLŽ<1 Ì\’³ûŧÉnf ŽûF¼ñõŒlÙ“L¹õ9Æ]®°"QÐÜŽeÄt2Ê )iAT²&ú¯}É©§b QëûßѶzÍÞh‘U!G|ªFºÛ"ë¢Ô 3ÿ×_üL‰æ ¼«ÿBf¬É2%£3ýJy‰3 ?£á±] r„B”—LålRö?ä}²*£th ª™$=–•¦-êY5æ[Uä\Ï–|\pÏ7Ê7f£±5 c/:<æ%¶b¤!|Û1Ïs«ÐZy¹/<_¡ ¬ÉÃN,Æ£â‘Aˆ±¹N­­µ/†ð‰’B@’EPлãnÊö:ؼâþµ&êÀ¤òíû;Pè3Ç*T¹Y¥‡—Lû?5Ã6;àzÜÊÿVðyLAjˆWÁ«lsyÔ`Îê½È¿RdªCÉÖѦ¸¥¤GG¤3-V!LøÀ*DŽh¥f¨IJ”iÒ³¢•èÒ»ŠÄ^úüR]Óœ~û³´Ã(¬5HfnÚa»×Ø£ ‚7ÄJçq‹A†aX}!´¬a(k>_kâX°Ä¨OÜRÝm*˜-¨Ö섀ťé|rt´ ç«æùÔ0¿ŸGíáq~¢¢7ÊÍqìBUÑãÆÕg¥½]BG|¢þ…-¥+2^Os‹ã·§Õn– %d!Ñ‹ ?yUÁ8kÎr,)§ÏZ²Æø˜˜¤­ÉX+"†">J€ƒ«B¦lr9$€ílh€¡‚Ì+;'êöLA”ª3öÒ rß?:Í¿ŒõûTxIòCÄ|µ Óš§#Ä,Q¥œòØ#_²|½,KÂúU¶´VÖŒ°¸bPl_ÉÓØ) %uKˆPz©IkAC„ &RLÉÛ{½-øûÈÜ ðz;±­6z½¿U›°4šÚð4zÓÚþ"æX2:;A´‚ ›ÊK»¯ç±,ÚÊÛ£&å–°4ù¯D»ÓœŒ,º+ã<þDãµÄ¥³K[vÃ# ?­­Ñ=Áó'˜qÊT”ðL\†(a§ÊW2MiÜ+z›VĤf!eG!/ë!Þ¯Z^Ï›UyX'FƒbU¯/ôð5MD^× {º"i™Êˆ0ZV4[mNH]ô6`(¶×q£á†tx^ZãØ-Þ‡ž&™Ï–ÄPubQm­Ú#ˆê´Û±J{n½ëb/êyàÆ)Ó*ÝhÖ0Úè3ÅÜáiw•i©ÅÅ”ÎÁmcb)‡Ú[ù¨X`ÒÂZ‘)Œ„e”oY; A|”WöM¼ZørHÛ¼Úƒõ%…öÇmáÅïª5:¯ŸX˜6H€üô™ü Þ´èĨæ±%x–©¤¬‹Ó_Þð»õÂIË[ïù«"~°q÷8·à©©ès¨Zïü›9Cö«´#ÿÇQêå;E ¥/¨ÐÅÚóMdÐÏ0…£khí”"ˆøQ\‚69g Ò!l;§†Î¹^_m%Ñ{`£“zp]ݸª<àϪª[T]É=~½½ídÅnTõµ}K°öÐ6¯¶Åü›¤ª¼wˆîþPÝÇjºø¾"(¸?ÕUß: 7HË@Ô°æ–.4ÍÛèÂY+Òó4ÂÉÁƒ.‚™Ü9逶ÝqFGt¼8öâI?[r/0+6:³Öî|q €ç/ûª\ ½ãmYxÓØMßA7ù'8Uˆœ¬w‹¯[N)s¬®kWúºác•/a›?tŠS†²Ú ¬Ýj’ðÒØ4ëÖ®†Ë ÅË+kWÃKþLçjxI’¬•çéJ»®æÔYØT¶´zd¸[6ˆ1êÇÖÊÇÜO<ÿÇî•ü0üy endstream endobj 41 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 42 0 R/Group<>/Tabs/S/StructParents 9>> endobj 42 0 obj <> stream xœ½[ÛnÛ8}7àࣵ¨e‘EiaHÓ¦{A °m±Pl%Ö—Ô–{ûú!%Û±Ä(V')PWÖÅg8ž93TGgë"¿N§GgE‘No³û8º\Ý}]þ¸ËFïÒ›|™ùj9ú°½*ðÔY:ËÖ“ {ùêœ}é÷?À?qE,`*Q,[gýÞ?¿±e¿÷ò²ß]pÆ»¼î÷8Ü0ÎTäk­˜N”/àÊnzóA³› ü"»1ßâòÛ›~ïãàÒ‹·^8Ș÷™]þÕfß}ßï=ÚqlÖ¾÷,0À%Þaj¥¸a†d05Â,<=ÈÖÞ00o(é<¿Á/Kp¨¹´,àÈ\ú4ð†ñàï·gÞP>yø…y<l¼a8¸Ã ˜ÂG~çSx£ÃKৈ"”òcç@NŸ}¸‹½~{ÎFŽ`¹*ŠÕÂï«UAï2öÍ à.%"_H&€ùc<4ûÛsË^|N ½âØ`6óâ]N?xP³½3"`…º±ÉEï÷SËFïpRßžÿùŠ§Î”t1S¨ÐœcCÎ ÁZH½¡ä¸J–øutƒ¿w\5kx }é2æÈ+5gp2gÙ„ß•½j0Q`¹¸¦+×a 2Ý£éšYê0‰¥üf˜ñÖR/DÉÆ“6pn<^žÊàÔ  —Q |hBU¡À¨z”jQ%È’Àý°¾Ö?dÅfçâÖ‹“~û± —,åó Dï6£e|Ä~àtâQÆ7ÍfO쉭Ú“!™ëÁ ü¼Þ¹½Y!¼è:õ,&>wÙN<ç"Š}³^‡ÑÒž~ÚèVéŒáÃi¯T[þÓý ÇF·ÝŸj|$Ee‡ó¥§0ƒi{í _ñ §#³TT-Ë Ã'æi‘mðš%¬ý!Þ‹HYД´é¤ièé¼ÈÖeD_‹þ¸Ï!Ö2Ÿ½"[a€ëÏaMžN).³yA ‘¬bä 2Í€!›N®&¥ ¦"˜Ä81-Ò+ÍÔrÙb’‹ â‘Ö©B%r¡ÐP¨ u;ãH;ÌJdQž)3PU ¢²MBíÁ!åÓÁ@özlØÔô“¤ÒO‘Ò]ðCªª ’Š2Ò\UÆ(bTÐ&šÆKüºÅpZÐÉä ¹èÀos³"›f2½Þ ÁŽ˜Éwù‹­Lv7ç0ñb.Ø Xóúþ‚´¹œlÑñ0D/5[I'wC›ûša²ï8Ä"Ã1Ï*ikFü )‡d¢«8Ù‚k¦&†”Pá”Ieƒ?A(qãÐpQ³ÁšÄØe”ù²²eÃzo”•äæsêYýfz¡†hšwVaWä™:¼‚ì£À¨ñ Ð?Pñ:J'8c‰¯æ˜ù E^€üí€m £„,ŒÙŸ“5ÂØ?C8`°úýßÅÊî/Ô~qç€muïÉ­u×ü†Ê,¢z45Ù}Zæú²+7'«IqøÒ…NV“rÎÑÉÍ(tÚ+_9]¹¯I÷ŒjY›î:¡Eþ£,›{"°Ý#2.àìÀé‡Ö`#븇 yºprÉê$˜)ÂHp’I3̵érb‰ÈÆ&ßšU…xMW4rÃ+Í´zúäâܹӜH?Ž›6WØ]š¯wŠßìÝT¢ä¶ÒßV ž0§–Ì m„Êþé» ê}€C“Zo~î ±gnHÍú´:hÿÄq£ºÛä¨ZR¸:|3¤z=¡RQäêîõáèQ®ñð8™„ðV£»€¿1Ù4®!¶:Y{DjŽmÏ“ 8¹„sqš “&¨9ͳø²ë!Ôv–¹¶o#<çβ~,]ƶNÊÉu­3*„n2éH–„ƒÔcxÌôжeù…’î‹}ñlø°¸¿Õ´«ÔÆ[leØø®¸Ëf,7m¹ Ü”ÄiÚ‡ÛE,ßó`VЕ4Z Øuø¦urÈJc¨Nœ\T¹–,–”q=;ŸÍsÔû5³ÀEcŽÌ*¡{«ÇÈb‡­ï_•v²aƒÔÌÕcš?<2ÍŸ)]7|kõ,YU'dÒ`Ⱥó9’Ä·ª?ƒŠ+7 <2 ¶½ˆA×Õít˜Ûê/²ÂDpÝɲ„'îæ?õRpÀ,Ö›ªÆϬò…xØÚ ø˜›Â¸ˆ.O |ÊaN«Ûɪ| Á€ÆWÀÌ×å6A:cfG£Ú&9¨;–‡&¹ÏóŸ‹UõÀñ|÷–¹³-kngKOZA`Ì;Nþ³•±oú w˜æ&üGç{ÙWöíòtëT“étT†] Óé\ϲě`L¶ l¶[¬É²]èF„¬J“<CöÚl,LîvÀ</&ˆþ¸±Öƒ•¬~1owÖ·…é4ƒÄf¦ÃŠy¿" Û¶kjx’î¥-Ð ‘ þ¹K*›]"‡5õÿÑ&z†p4É0MÑÿ?Ó7¡‰ endstream endobj 43 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 44 0 R/Group<>/Tabs/S/StructParents 10>> endobj 44 0 obj <> stream xœ½ZYÛ8 ~ÿ G{Ñ8Ö-A€ÌÕ=ТEìCÛ7q§Fsmân;ÿ~I9w¬ñ8«d€ÉÄ–LR$¿O¤<ÝÁ²È¿¦£‚ôzÝAQ¤£oÙ˜|ìç‹ÏÝáÓ"ë¾KóYZäóY÷Ã/Þú=KÇÙ²ß'7w·äŸv+Žbü1F)™Hb#ˬÝúû72k·n†íV÷ÊÈðk»EaRL(‘*ÒZȈÁÈ&½þ Éã $’G{eÖW¯Û­Á04Á·P ?“áŸíÖ=È}ßn½ØvlÖ‘dXÅk}ßÏTs²Pãح¦ãM͉?÷ÕLCd˰£vXNòG¼˜CíЬ€ovèSvLð×›AØáÁ§/HHM° ;"X`Fð‘ÅÇó<‹Ù& ÊÓB˜”‘q.¤yôa¹sKºŽd¿™Å|êÎ÷‡ù¼ð—ïÜDÒÏ¢`–d*bœp Ê"È1*¬ŽÝ´—ÌqÙ‹Ï1´—L:`žd8úPzbûÙA—Е«\ô~ZÒ}‡A}sûlj›FŠ»˜IH4Ç`OÔ¨¸¤Ÿ*5Öñ²žN|iÔQ‹ûýÜÜ•Nªôû†»CÍ2ƒ0ÿÄ IË1î¾6ì—à ‘tTçwá+îJê*ý€±ù…\/ñ#û àIí×ñ¶ ™Ã¼åÎÒb´.-â,|J¤ÙOÄpN²9Ì(ò1âîÙHÏ@r¤8kRv(÷‡=›#å.'ÔAz —çèWÞÀG|üÇNðU«YØœrm8Aü!ÁÓ6.ˆD;—øºh_9 ©škˆ¶˜¥“0³óQ k€f…Ùq…>?Äì+ûì) ½Á/6‘⮥{ëÍ8Â.5ûÅ4óÇ+Œ>³°ºœ2ÞrJ%çèO|ñŠ:R—ßÔj·tbfR}Ä5æ΢Øi]mIܸ“rf“Uì˜ÅSÒC%óŒºs¸ ¯Êɹ ™8) ìuº¸W1¥ð\ı:o\Åtl™£JÍ>WqýÄ×ÂjÓÔ[ë&c~–[ [ C¯ÁV5Gl…õËòQÉVÀNã+P–À&Þaam$7ƒ®T2Ax¯…²_x¯ÈIÆ•= lW¤-q™ŽÕz¤ ðJ5g‰þ(Ål« «Í#oÍ­àú,7vNJ¡Ògh”R­fK$KÒÃâ>Ç[øø>ú“x”á°¢ÖÛÛXé:ÜOxḏ½8–÷1¥ð› à7îwÜ‹y¿Ãzå=9諞boÃ05·å_|ì–ö%|ÙÞíA_3ýJÐwVÐzÖvØ$8Û w;!ø]++[‚Uº|‚š#õøµ–Ç\ÊRªÜ) 8S=€¡ºßá{zo¤Z/Ù A0\êF«õn:—÷}o ªrvúŸÄ™å»â¾ñ»–}m—W.ü&NƒäqõœÛýóÒ«çxjä^ü&'œð°‹?æ…܇Â^ž$ƒCˆ€Ó̾³Á\ÞìÒ’m¡a…  É:ñ×¹ˆiZÊŽùÇæÒør¼P:JœŽ¯%"og9\Sìиñwí;\$UøÞwjÞbu|ªG·§z°õìê…4¹ÜÆÄ”³+k£ÑøÄ™LWðÿÊYO¡RBè2ñÙ#ü·þހŨÜaƒ¿:˜ŠH¹´|õ¥6Ù =í¯â™ÅÕ¾ßóv Äcy–û{'1¬|ùZØ¡ÆË2Å[¢Y…XC»g,Í·,t fÒÀL[kcâí­/S´Ê€fzqw],m͵}:/ðÔçloyCÔ*h¸ÃþZz;©`<9Ë€Æ-®UT_UÕjªPõ/žMÙ®s…{F‰,Ú5NÜe™ÕÆÖÅÛû\š(<ù¿ ¬ÖþrZ–.G¨ÍC}”±X`qàXN­?7öNjq– zʨdUøF™C ¢Êž ã—©/F>·´Zßz{IIy\ –ïù‚`E&ˤΦ¬Ò&OÛÎI7¹[D-Ë7}ÊÞݼð.Ëj¼‹w èLh9X/é*Cq[!›íÊ^¬6ÏMPÄúí8 ÄV×â $ö÷îX°(qy¥6,Þš›(~ÙÿCüÒ†-J endstream endobj 45 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 46 0 R/Group<>/Tabs/S/StructParents 11>> endobj 46 0 obj <> stream xœ½[YoÛÆ~7àÿ0dQQÎÂaapl'ím¤ˆ>¤} %Z&®6Kt›þû{ÎP‹mò˜’î‘Ä©!¿³o3î_.«ò>Vââ¢YUùð¡‰oýÛùâ¯þí¿‹¢ÿ%—³¼*ç³þ×§» oý\ä£b9ˆ×Wâñü,Žbü眵"&3ÂéD,‹ó³?~³ó³·çgýRÈDÜÞŸŸIX )ŒÒÔˆ43QßLaѧ¯©¯àbì¯ÜúêÓùÙ·à6tÁC¨ƒB„‰ÛÿœŸÝÀ{??Û›‚ä5i™äx÷ß#aŒ:Å4L ¦!Ïç0Ó0 Šeس{IOÊ1^Ì@ þ«YŸüWaÏ¿~¾ {*ø3Ä J¬Âž¨€!ü(ïññrÏ¢u„¼Š‰‘ĘȑŒ®}X%n>_‰>aìæU5ŸÒöþq>¯øì]¹Èð0«Lb£D e,“Úcì–í³†¢ŸKÞä5Á¢ä9-n‡ß™4h?°tÚŠØ&¢ßwªý/¨ÔÏW¿\‹øPM)*2iƒä¼&äý`Y¢«L§å,ì¥Áoýt¤ý7àeœFŽB%†÷’ûDµá®06®ƒo;ÌtÑÇÇ£‹§:PˆW¡ ÊP®îopk„üÚŸš…Ò>4`S‰I"§(b»t’°åÊXFºé_¡y• ˆÕ¦–HõZL™½:΃½š œB*}ZG~¿ Ã:æÖ¥éHøç‡aOª`Ï׷ͻͯdd)fï¾ÎS\pZGŠ^µôù°œ€h¼a­E’cjm’âjž2Ô>_޹S*2Š.6ö•Ž#K² å«Ú“¸-x …·âCq‘$ÙŠÄ5Xo`JY£±O*Q®04x…& ìþG\ôhP¦M÷Ôf#D(®aÓì|Í•6¬IÛð¹ÓƒÙàq› ™’Ã-à=3‡Î T¢èíR‹a3 eZ3GQ­¶"Ø/Uä£|êV"÷á²~¤ÎùH<>aO0)+ï¿Û—{˜!ìòI俸F-B™ÕQãª1,cóM¥bˆH„ ºt`Ùt !.v64 ü”Ë5M&1BÚ5 V±Ø¹f‰†÷Cfƒø«(ºDí¸TmlÖ†ÿV¡–ûŸÁ:ûLuÄ$1C¯B'Ä„½iä™ÜCf)Æ(‚è9[«H) æ~;›@Þ1  ,&Ü‘^$U9ÂAÅj»®š‡nýÉ×p>Vùë9ä~ýìy%ªõ訷•ë#~%æ ’ÝÊ"®Ka¹ jŒU‚‹²„’A—}flö©S¬ n.Ùzkm°Ç¢vÅcß‚y¿p׎ߩ΃‡¤=k·Àï¼kÛ÷ lýW]!¡b6âlˆ4…ÃÇM*±í"`^jçôÁTG™Ú“å¦õ³e´“ûðu‘Ïv4¨þoùl,‚QÞ»þ5䊮Ú@zQ'®Ìt‚Ú~÷øÛ*÷ö¼þ¿OZšA›%¦ÙöH2®Ù´AO *xÚ†Ò]_6)f¡ªÇ^¾ÿcsNé²È8ŠÄ}TdNãÒìOгhqpH @wÎÜ9 ˜ïïàœØNt úà~—ÜiƒTåZgÞóïè¯|…Ëø በàq]´¼Ÿ+B7 ®HÓ©¶®+¡c8¸í!]/IÛ`w½v˜;Ôô»Nÿ£âBuÚŸ/ P;7§îéHõƦ€x8ÀWå«]ž/ÂæÔ‘rŒz{âñ Ά𶺲ÿщýÁ«¥øŽ»MC‘OýàI¸ÁcŸmðø:uYëÄîReMϾñ£ÆÊœO§~Øš´Ä)ÜÄ<˜€ƒëdÊý+Ûø‚àeÖSzËût„l{ê™Åz‰  SïÎPY܈€É1ß/êù>WìIÞâëØ|Ú„1oñu1|À"Ƴ·<¶ŠifMé"·'gM“9xCôZ™¶€UÌÛÑ1%4ÛØÕçíxµÓlcïñ­X±27.;¸N"íÚ- ePRRü@·5Ðð+5ƒ¹û*–q·l,ååÀ^à­A/áeÞ8¤çäÌÛ+X’ûÄ z–”Bv ·®ŸK@k B‰=i`¹¹ôO¡°ÜÕ §ñ{;.)aQ¤‰tƶ]` i0>¢aë}eªÛàÎÌpŒu÷±ç\`iê£&Ö)Ôƒû܆Wl„j’ÀØÍÍ:˜û–7µýol=‹ýgeÒú¾a‹xб6¾CÏRJ ¾L=qþjùÜÜç’¬Í>ÄÀøX­‹WÆÌžå“ ˜]·ClÛ¶ò=ØKbM²÷ü¼±âcLªÈžž/ú’Bñݨ­uÈÇ$MEúƒÖR >×›áã ®{ƒLŠ;5W|Çnµ åwóÏe(•à¾Ò©UÊFº[’qGÔàâÉùÒ.ÊÞŒ—»meL)°‹ßàOŒÐ|“üñIÑÙ7ŒÇfËí¡/Jª6 ³ÀpUÿ:ñ‡fh •-´®øËv ŽAá2êQCw`ÉxöN5pÝÿ­Õv3ýa{n{;-Šú +cîßT˜*n#­*ê#Ŷ®*Gxà#Ÿ¤ÄX·Ç=_{W›s¦ùd"~Àõý€vôÒ1ñ2¯ò;¬áê9ðîT‡ínN¬»Ò=¹Â¿^û—7|AÅŸœ"$ÂçuFbLnGÁ¿„œ¯ÎLV(:¾Qµ‹iÜΖ†m§HÆPRïwTöКl© endstream endobj 47 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 48 0 R/Group<>/Tabs/S/StructParents 12>> endobj 48 0 obj <> stream xœÅ[[SãÆ~§Šÿ0V ÍŒ®§(W±Àæ$9¤’ZRça³ PÅØÖfC~ýéîÑÍÒ o³‡*@Öíëéë7=ããÓǪ¼Ío*qrr|ZUùÍ}1¯VëOÇWOëâø—ü®\æU¹Zø|]á©ù¼xœÍÄ»ó3ñçáAàø“¦q,e‘HC%‹Ãƒÿ~'–‡ï®ŽßK!•¸º=¥õ§ï>N®¼trï…“BxŸÄÕ‡ðÞ_v–@ %H?R[p÷Çž0£¦ÚÜ0S6˜‘>û0^2)½i<ÞTMòEy‡– Pº´¬àˆ.ý>ñ¦éä§ËSoª'¿{øAx2l¼i8Y£nàOy‹—7ð,z‡—Á«˜¢¢ÈOy½õá.qqy&ŽÎþnUU«·¿¿_­*>שñ îŠTì+-t`>ø˜ £»m—{\òâs åUCÅÄKCquóq"õHö½+L¬ˆ6ýÚ™Vÿ‚F½<ûá\¯µ”ve¦0Bq¸v&ýØaJ Æ%]…¡¦¸`ÓÌO] %׺ý°Î—­zåñòå˜ÌóéùO[PÚ&χ¢ûFº=niÒ°JÆH^‘;/çlù8ó#çÀö­a#”LùÚ3;¦ý°ËÒuš¿üág.dœùÚ)Öí§¶vt%ˆêIQUåÒ‹¨tÆg+#a@ed'Œ²ˆbË"ôÃÓÙ_sáÇIfÃçÎb˜a‹¯ÉbвXø&Y,Ž›<˜Å¸¼:‰(‹9öU¯#WƱÅw©øÃ;0[>òeËô¹qñ¥ËÝÆòíÒeâ§Ú%Åÿ-]jHâ»ÀRÑÛ„”Žö”'þ*y áÄÛú\£Áw‚ÌÇå¤ÄÉZf¿…§'ïŸè¶qµ„Ùw=$ob—( }ùú²š²áÇʆÿ† Nhs¶„kš<¶Ä”¾r ‚>ׂð·I\©( ’ê@½ÀÏ8×_ WoØ@q üö•¡jì@©î1NfБn‰°ÀÇcš.ÌÅ-&Ü– Mý ¶]˜ÆJ¹CGGMŽí¡‘"ïW:ÆË·­zªüuc &·iBˆ»§|#ΟŸÑp˨ÍŦˆÔß(§{«Í–vf#‹UG‚ k”Þ+°¦ìitÐ3¶LÍPÿ)ss¿1 iKNe<)7øÞNžOQïr±†Ú°i}¨î²¥®¼Ô-¨ÆS*£ÏEŽ·{Bdj}†qè+—¦÷í|ZP2?q¡°5>ÃD#EpÀ Ÿ–)FŸŒ)˜X¦~h/Mˆ‰ž…nÖrË8±2zݤ  pÒ¤öÞA øzä"¯ 6*(µ;FÑùns½dj ¿rQ`²Ñ4æ{*'E݃^ 1(Ò'ý·mfúcŒØ¤N.U±÷¹,Æå¡Zú™ …/€*E´£ôàiæ—ÿ£u1QÎÁFÅFóoa[$ìyQW;'[בc$‡ÐÐuÌ,Çå·$L~"“çlvÉÙüD©Ö.6?‘8×N(ŸØ"½_‰FéÇgó(œóØ%d÷Æ$´ 4«½¢>¯=)1&éßJ¤„I^ä…­K%±ÍmGás/ú©dPŒ4iÅä€X‰9=`f¢ìЫR¸oôÛöýúÿ¹®¦î”Ñ«hLŠ×ÀPbnóŽ£&ɽ±yuªül7ó6E†xú[܆šZv’Q³Of™€ÒÑ›‡mÉÊžb"…½£¡¬üe ø66+xlžV7¡0|½îä9í¡³™i5Ú»×…øDë«íí‹ßЪdZLÚ8žºé…¸ñÓè2½áŸÕ#S~ZyÈm¥îå,Eå)I>gºË-w²m–(«'¸!ÚîÔsÛåxÍ_xµ¹«õ楸k¦²ýÄÅì¦:°)ÚÑ$XätÎ4l,Ô}]4éÞªxü>9.hqLLÆ.7-K¤9aø '„²?;Ì€˜µÝ#b)7õAÛ™êGF¾ Åfk²6ŠIy‹jC^çžÙ™yéB`1Þ©÷åh}ùâÔÈÃìÀAjSFjÞJÔ0 Š%Ô›ßÌ€EN¡ø¼SÓæ _;U+¤uv û꫹›·m»Êöü¡Ë¿4ÿ[,9mß?EÙdXm¼œž±¿šðD†VÙGn€5‚š¹CµnŽD¾aâœîíf±MlpÛjý­|Û3?¶€ÈÐS"1ņ/]kpÊ€ £Cçƒ uêÏ&=fP,= ÙºB‹´«¦È¶Õ·mO÷üʇœÐš¨Û&!ùM{³ÙÝIEºÅٴ懘ãë¬IdéomllàÅN˜fûêv?¿Y¼©nš-Å›-Kµ¬9ãWØ­<¶ËcÅ\ ²¶Ø_D†’ºC0¾€ 3¤ic#¾æ‘ŒR¤Q´—¨3¶}¾¡²á÷v±×!Šiw*%Eü³= þõm…ØÙtˆËh•9´ƶ^ÖŸYt2hý‹oÛ`ŠûÈWï>vú üøõø’kß ÊR >÷¶A nÆ SÚ_Vîëc¼˜öWØGuÂ…’¨gPnq®„>½À?¸IˆöEæHrö¥«#¤„Jè`Æ¢29;ÊG³9MO>±ÁFg‡{1$^½•×’*‰1‡¶w®‘ÍõúdÖ¸V¶ü5hQàèz}òÇ.G•”À@Y+HM míu ¾ _UXßœcaS™’™/](û&Ù1 L’Sç`¶”ñ‹1é3 /–ÓW3ÅéŽ2ØK€‹ââFˆèí¿c…!’k¾A¹â#¹Ùsãâc¹Ñs0ߊæâ€"0ò\Ú—á€yÑS#®PÁ….‹;2Oê#>ØV:¶ï-•žYÒìÚꃉúQ»¶^¬‹&]Õx®ö»¤½@ ðm9’‘kÌÖÌžÆÖm‡Öè—ÖÙúÛRú{¨G+ÎÍ2Ç5¨¹£Æ È¸ë¿ CÛàžÝgÙî£AvEß7R51¸\5½—J”Í2H·Ô›ãæjaÖ±{Ô†´l«êº` ]ÿθëh)m]Gû™K'l^ƒîc§ê‹ñòÏV¼v—M lÓÄ/:J™÷èæà{_¿eÜéD0õOÆU{<•íªÜp|(t^å׸ˆlžãÛÚ(±÷ëñh0±FEö‚²ÕcëÄ­vûÍý&d§RwôrhM^ì²B·G¢¹ÞŸì«D6‚©ÄOœZ´U½ÿjS endstream endobj 49 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 50 0 R/Group<>/Tabs/S/StructParents 13>> endobj 50 0 obj <> stream xœ½\[oÛ¸~ÿ Gû`­ˆ¤(Q€a ÍeϺhö![J¬$F8›(½œ_f†’(K¢¸ãhlKg8CÎ|s±ŽŸÊÅM~]ÓéÑqYæ×wÅ<¸<ºX=~:ºøñX}Èoy¹X=}|¹*ñÒ?‹|^<ÍfÁ»Ó“àïÃ(ŒðŸ1IDÎt`b<‡þ#x8ý~xp9º›ÑÝ8ÁøSpñïÃ3˜÷ÃWs »¤i¨åD¸¢÷eG2½…F~262=y¶ÉÜÓQñ4ž$£`<‘£|¹¸Å PºõPÂ;ºõ×h<1£ÿ¼?OÔè¯1~ÆÂŒžÇ“xôˆ ¸†?‹||q Ïâîg0ÓB¤Ö¡ñ.äíÚ‡QÁÙû“àȳÙß­Êruïßïç«UÉ·ß• 5Ï¢`”–I(U 4 a‰˜h¸a¯ã㟓ȯì2L€=×—#÷xß™"ЊÓAŠC"úé68ú€J}ò¯Ó b³L±FvºŒ4vèOX#8×ãd”?Ô'èêg¬T!Á~x¹AÊÈ Q‡# GyàáL«ƒNéì¿Ààâá«c»óðsc"ðZN¶k%*ŠC¡|+ùÍòK¬ÒÛå ˆ7œuï–wãZú8æ¥2d${gçV0è¦ù´\<àCnÍhšxñŒ6¯|FsgéáÔsÒ+“ ê½JÁ‘>Ò\|ÇwŠocÝç>"µ’ pýVËómç¥2ÔÆÇ+ßOu¨”Ì»°>MJ(@“Ù(Ç¥.Ë6€Þý˜éž×‰“0ñ01„4³I¯út&%¼š“Ù$†×,ª^¦Âû‘H“™Â!Ù ï¼Ó³öœÈLíÀä<âl&Å”Âa‘„·z–Nñ>a§ÇÑH æ¥k²5qÅ â8RZ[Bp[¹y-);Z»§êÉ”>›1©3Y˜IŸ:w…;=}Å0âÛœVÞ*=F‘X¹žã‹ÒçNM•(¶ÊÓ°I&‹ÂØ{ö;;¹ç×›_‹²ñVúò­ô•‡~’fCôwÝ=2ID°ÞCæ dŽ&¥DCz}ÇEÖ°óRÝÕLõ¨d"T>"S6"©ŸÈ z'tNKüSŒÑ_Õ½ß*ô8ñ†uÎø¨¤­^§³ÞP\2ÑiŸ~sJ ±§7\®6IìÑ"x9Z, ~Ð'"Mçb˜ä®ªì“b>¬±Œò( ƒ"A ÉþEhö¿*ož !E/sÀ]ÅXF£ïxèËàÓ°oh†¸q•9 Õtt ¿×w-f¥›xïÌõ¸ŽãûrE!1D!ÞÅò;:Ú@†MuJË0óQù†œ\IŸTHèy¬@ôOM0e Ðîâ« )Py¹«죟4 S§¿¹˜¶É, ¥×Ú=7!V¹›VèÎë©8L½ô¹CÊDéÁeâ!Ó¹|WaÔÂhŽhëßS“&À ãU›opô¾¸XCtî[L+0NOgIgâøˆQP¶mbp&ô1=I¸µdxR»y÷ *¥ÐdË->U* ÜT°¡=†¥Œq¦ŠM¿rcôPm̆j„¹[ó÷=úš+ÌÔ*%| _˜é!3'? ÑÑ ¸–•MëÕÞvz³Xb¸Ô žàa‘./=çOlN¢Ðþzxݦ’„kKè$¢_gÔ[-3⺴d%§È‘Y°’—íLhãÏòy•±]” ` 8ó%ø¼9:™ïÍC¶‚µ,{(ÂJw ètùñRƒó`ŒOle@%Àî(”Çuõ‘ Éò©ãRgª¯*7…WëlõU• ´´{l öÔGÅ•W]…‚°dù ñUQçõ0WqñzŠÐ°'Rïž`S„– ë~ûVDmLbr°¯ÑIyMôŒéããd×tÜ@xù©TVŒ–Š0%æ!Æ—RÉ2{ÈBÔ^Î.›ý²«ËíS4"4ÊG‘ošxÃÂò±£V•âúüOD‚XQÕ®Šþä`ë¡WXv,È?Z_(Ó*»sn™ŽUÓý11^Tn´åËimÓN¼N„pvq°Š¾^Ûd kj#"õ€Ü\à¢mõÈë\ SUé°`WUúª—ªˆAŒ†¸'Ž{ÚÕ=¼Œå¦jÊj$ˆ³×w»õ?GgÛüu ¬š C.‘5E1{ÝU½šÇ:± ëJNº2inÕ‚´%"*ïò×Pí1¡!Ó`!›i¯:ä¢s¸É@w^Ϊ.¿A9‡ÓÆ]çеq`¸›k–*H—56\›áz˱ÎV ™@Ñyô´u³u¢aæÎ¼` ¶V4gC p›32bŸçø÷ªUK¹©ÃŠÓ’ų0ö¶ª­JÉtˆŠæM2t-V8ÂV`z‡ð±”—6YÑʰ¶C ;$ǬFþì²"®·Øb¬ypRþѨ¤.P´;a`½<†(±ÓéB´ 7µbPßEbµÍQâe›~/Ùr]±ŽÂÌ+T¾æ ­ÂÔG…Ò8N‚ëmøV;õ×'x:*Òü´,z/°ÎZæ»¶´©µÈšÝ;*ƒ¼Î1Ú ‡*UÓv„œk”Ù¯X£R¯Z#öcøžÖj›Zö¾ØÄ`€óªÅ6½.?Ĺàl'| „øÚ·`Ê  s›´ÁÝ„Zºh‹==Ê·å×®E(üKGd¬Æ’Ý/¡ˆ³uõ«nþu&Ò‚ž¤qe)ÛtÖ¿œÒ$¦ñöP—Ïð*œúqöO¤¶ ÿ7`{=«Í› ‘Fa…goe¿Dn"³Jöѱí¡Ëݱí!׸ñ2[1.[;”LÄN °õCI• 1ÀëxÈ| ¦ˆ…_l¶š ŒÊF9·c‘ØKÛÌ]ÑÞ&¡á&ÅI¬Aò±¹Ul½PR¤C ||Ĥõ ûÂh[Q Æ „±.ßë EàÊÃ[§&m•— tJñ{ê2Ó5_†(i»›VÑóä¤r­¦¹%q+«4øõÌ7=ªµwíÞ¯R[ÕÔÎ%î¥K¢È½kH© ^ ù.ÞÛÓòúË7é«—o±=ÛwQ£$̼'ÍûÆ}ØCf«µe+¥ŠŒúÞÌÀ› 7>ï+Òxˆnïë!óåsÙd¦¦/ö‡_È˸vµ_î:a‘ÚëÌNXÓO xØÝª–7׳¼ûBË!^ã…¹<®ÄoºzøØÕáPIBã£ÂÖ™‰ÍƒÚ+Ôª3“‹–ŽBxhñõ×i…ÂCÆvÉý¯À®ý&]·ª•«ºø½˜ãv¢ŸX²ûÉeFË¢©‰ÛŽvÅg|ñ÷VŒ—w¶Ì«Š¨&=Lœ³<·ñþ+S'bVWÀú cœ>•aÌ}$úÂI©Þ'œv:–V_-¹ÛŠ×îÌ\²‹Z[ÉžªÑ«™”š¿ÈvJšg3ê¬+õk«Æ™±þ †¿ùº]Ù3ý’íçªNç73ðæê§`¦¾ÿ)vH0LæËç…«9¶!²Nÿ×#Aö|˜Û!­ü"@Ï0 endstream endobj 51 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 52 0 R/Group<>/Tabs/S/StructParents 14>> endobj 52 0 obj <> stream xœÝ[ÝoÛ8ÿAÖaM‹¤HI¸À@’¦»½»»H÷Ðíƒ+‰qŽ&ò^{ýÍú²­‰jï¸W µõùÎ g~3¤'ç/åü>¿+ƒ³³ÉyYæwÅ,ø4¹Y=žÜ|{.&¿æóe^ÎWËÉõú¶ÄS¿ù¬x™Nƒ‹w—Á—Ó“HDø/M­ ¢Àd&Hc¼§'ÿúK°<=¹¸9=™¼—TÁÍý鉄›¢@ÆŠ$1A’¡àÊÜôóu<¼Âƒw”VG?Ÿž|Ý„éè1ŒGE~nþvzrïýíôä»%PÛ$‰0jC\áýû@˜¦ZD4̘ fGŸ]˜§0/áØŽ‚p¬Fùbþ€KP¨»´,á›»ôû(§£¿<Çzô{ˆA(ÓÑk8ŽGÏh€;øo~ÏïàYôŽ0ƒW1 D#Rr û[î ®>^ÂÙ/Ve¹z¢ýýýjUòù»N…áÜe”JÚ˜“±Ãhoûž{(yñ9…òªmƒ1ˆ—ÆÁÍݧ‘4;²ŒXqҋا¢ßZÓ“_Ѩ/?¼ "¶Èg[ëçÐlÌf†ñs§| -c€’J MÉqh|êA±"¥PØÂ“Ô‘0¤R·Â“‹5óÿ¡Ìü‰5¨Û„[®àfwv>CS¸Ðåmñ oÙ°ç´ðïVpþ«{ý$”¼Ä{´;ë.û°8_†•EÿXsxYÒ9WähýÇ:`–J x—¾â$ ¥®Ÿu±+bÒ,sQ6¤L Eñ'Ó"#Çó¡ÉróW4û1&m=”朵;µZi¶ik­'/ý0Ä´uÓ®;eסvTc†ôaˆ…°yœ’™Ð¤ìl.§”’B©YkÇßîÀÝòe툷žÒ‚žð<Þê®^@3.µŠ„N® ï—š‚Aë¯ë8ì©¥Sš¿ Ô[×òÚu†¨k¬ÝaÅaÙü©bDÇV¢Q©ÈH[}¸÷9î00CE«HbØ;‹ä…™Æð‘EÓ1~Ê+ø;ÉK9µpʼƒËçðy>MÎðÊt¬Î"m®¦\ÌXdD‰xp¤ÛÑ„”i¥{Yë½}5äJ)nØøÝ¾d¤ü嬹,SxÚ¶ÚAÝ%•îð Ûy)>m/ñ1÷Ææ|J§ãìÌÚÚ‘·Ð9È–ré\åBg¿Î·¼o‡‚K. n“ì|µ/¾¦ðMÂés;06ræã?jÆy¶öoŒ)UæÖðÈ*àÔ,”URuÝùšrÉ*Ñ%4%ëI4›KhÓ‡]”¯}äÿ©fîŽî¯«œáîZËPû4ãh’³ÏOeá?ó"nÖV> á}øW<—= «§.æ.O­j ŽŒ˜Úò2¿…wäž1ñ‘n¨ºdB)mÈh1›Ñ$ä²Á^ξášÇjËÇ’©yLÀ\‚ç]7=‚¡¹¬Ð!j?«&3ÌmæÉ§Â¤”ÀCv±\~alÖ‡OMf?‘Ë9¨-_ùb±‚cG§ëdÜSˆà”»ojŽÎëÙ~­¿mÒПڛó2€›˜`†t1[>[ïcªµŒGé…­xÔ6…ÂV;j› K¹­ ØBžÎŒÈ…:äÚ ›kÇ ~_ü”-ä)Ó‡Ïòú`x'Þ~æŠ 0ys\CzÍØìé>üb öÉÛ7}pxiêWw ˆ/ŒHM¬ÂÄoŒ¸>¤ 1mëD¶£d$,5 ¶£¤’Ba‹0ØáII›t#LÃŽ1…xÝyÓSØLÞv¡2dzà‹VàV5€Á:‹m­#NåAì]éQá*†¼gõÑÃãØÙ³›·øíå5ôU•'lÏè/œ»G®óô+ӉД\ƒúß»Ò%ÄèȘËm¾ò¦ a\ã’ ×…|¶x$eŠM$†o•KI‘R([Œggaë ÈÍ:s»†œ˜7ʹkn®¾×œ­Õ®ƒÕ©fñ­é?;Þœúfi§nå"°Y„ôëØöԙŊòØöŒ#¨Ÿ÷2h]2ÌÛUáfí±p„ù×Pbo?¸…óíÏtsÉÉ,MŸ¸gŒkOoÀì— ŠÕˆD=4 ï¢$o °åý,Ã8Ñ2õÙši:Ó"M÷`ïÆ•öu"‘À;í0M—Ô'úY(±]rWneÇCä|_¹„Lƒºß»)F?ÎúøeU5I1u,p¯…KmJñs{¶®; ®Þé´U¾+g…c™tê ®Ú&Ép™“_q“Æ8m¾ê&M1<0[ɧ/ù/«†sé{ev'çï0Œv•ºÝîòf§š;ui•ô vke·®Ðêý:›û ¶<ð®*¹ÿÀŒìoËýúº”ßðX—˵Æõ3b4|ލS|?Ã爱–B©üPv[¯¨z·DRàR)GRIgëƒÛ â9*ÿ(ŒH'©ˆ)ÑÙ‘†€@¢ÌªYˆTÿÖOlìŠ`§î´ãÝŸðk–ú« >» !›&Š’‚o) JäŒôõÁ´É¶f¡#s{w–)ΤR mÇo•0Ž3}iR p&§+¬hŽË™ðeB¤AÕïÝT§l¯¬ìàÏQ&®ÖƒQ6BÄãlRUQ&$É·ÁN:¦LÀìlþ!“†›b0Ü“€ùÿ¤˜Jg}ƒÝb~©ö2úS­>pzS\SÚãpM™à$ìŸC*ä€ Ÿ?*‹¼™€én7îþ"©—jÚÍ4­HHÎÇ4mJ£‘iF ÷¸?ŽiÆò 1ø¨f¬E¦)˜AºÁ¶ÖŒ3ûÔÞ˂Ք™Åf豩&ãÖâ–>)pm"Èܯ&ÀAŲml•IÜ'À.å´›ßܹ„Ÿ â)’uº:û•ê§³z ¼Éqyg£Ù‚Ðþ4Á¿¤ùÙS?‹Í‘mþö?vp³^šsÃ[$EpÑ®Rµ!;Çp¶(ƒí¥,^V€Û[{,Rƒîl%ãZˆ ®!°½ÁŸj’tˆø~KLßR‚ζejüá!ì½bBFÄ(߯¸ÉˆØóŒÿYÓ§ÎÿV릿 endstream endobj 53 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 54 0 R/Group<>/Tabs/S/StructParents 15>> endobj 54 0 obj <> stream xœµZ[oã6~ÿÀG«¨d‘%jÈäÒËîm'Ø>L‹B±•X_RG™îì¯ï9‡ºYÇ±Ë 0±DQüÏí;$5½Ü•ÅC6/ÙÅÅô²,³ù2_°Ó»íÓïÓ»/Oùô§ì±Øde±ÝL?¼Ü—Øô}ž-òÝlÆÞ]_±?ÏÏ ÄZÇ1 ™JÓ‘`»üüì×oØæüìÝÝùÙô–3.ØÝÃù‡N!ãLÅA’(–¤*ðd ¾û°Çg‘=Ò®î¾;?û8¹óôdéE“œy¿³»ÏÏn`ÜŸÏÏ^-èK${p…÷éD˜ÁDµ B;Œï f Ï.ÌÚK&ùÎóã ó|1ÉVÅ#Þl@¡ôhSÂ=úmâùzòï÷—ž/'¿yxÃ<®'ÏžMžÐsøS<àëÅÞEïðRÊÑD„R¶NäxëC/vóþŠM-Îþn[–ÛµÝßo·ÛÒ¿K(7“‚^JÄL* ÀÇxDm·×ô±É‹ï ”Wôf>ˆ§#v7ÿ8áñ@ö“+JFÇTôskZ6ý úþê‡k:ËL‘Bqú‚ü’—/žšì00|(.(rÊ¥cz‚ûÏž¯ªx£ç! õ¦Ž[è÷`bÑQÌð8 ´´‰ŒÁì (å´î`"ð0LOmàÎ\@ÈSðűøÒ†ò ÆÂ©œ1€‰CÀã0Kg0_Í!mJWÖŒ“t ÿÃÂCò/ˆÑ6š3úK÷Xv`Šù’-óÕ“W)‘çsç°*48ŒƒãÀ"ù!ÍEÎ4§’Sð•3|©NÁOˆÃx¿‰UC˜¤A|0 œŽ"!0biƒ!ïBjY;ä^9­VWVU: øñøÚ~,Æð?Õq¹Šâj¡aÁsVè0öi5™ §æ®ðe ¬˜+,{²Å^•dòjµ¾ k|ž•Ù=¤áŒú™ªØ@C¹õ´;i…ŒþU}Á?tõ_ªÖ\ÓÆ-“ÁÀ¢d…亢¥]#×·-%mk¢¢3+e‰ü3ÑÕÙÊ´eho\·­§”ykŽ/5õè½WëœÚ²¡ýq5ÿ:â¢0àÃ<âo=SMϛٕR¬ò¦hÆ(\å8¤³Ï´E_!îíWâçj=f¹õ|®Zø†Í@õ¦CñÜ€Ö—Ž4#£s±M3+Bk¬M–Úäíâ»3ãZ<™ì)ÉL’ôÓ<Â,þ[—Ãúm0‹j¿-Z§|©ó˜„¦dÂáÏ4 mPÛ›0èL¬(ÙÂ3Z2µµnªª 6t9É=žVþa²ÊžëïyÁ7ÁG=ó ÷=–uÌt#Å,ñž]©3R:Hmêtf´(æAbibo^]5cí§ *]ûQ”Æ#2QÊ2îÑÚØ–Ç:  ,Ö;Ù /1A&$;M©—<£ÌŸœåþHéŒOÊÙBA(n9TP¥® ª(‰Fà;·u¬¼†ì)áB¼}Ò- :Ù¹"q·$°Lš©ùè>厮1%c$WN£‰1Û5ø&’²IÄ&¹ø=e‡Çfã*b5­ÂƵì./¤PFZ@²Õ 3'E]™/\VHµ )H=š Pq¢îKtK0mCwX-GX-[`z:L‘¦½Z1ã²ÆÍKö²æ²Xy²¡¿Ž{SŠ{n]ýð‹ ¡oY‰{&ш&…û\»c°QnŒaebõO”ZÙ¾¾}3ð®&²R¾q–ã""/¾µ‘"%-(¿bµBÙlÃ2çÎ/Ã1LKÕ«îˆür´XÇQPœìT=G®8ö¬h=f 7xÔÍ“sè+ Še¶ÇúM¥TUJT¾óÐd㺟cU‡úUï;9ªgo:c‰*ÊÚJ¶K¦Ö^’îwd Œ"£¿RY›:hzEj§“ÅrÎV#¸%cÕšhß?ÜÅ6A¬mÀ7üúH °_àÐðàÓç¼w D®»ï1oÀW*‹¸îK%Ò6˜!aU^iöFTbê‡f£ý_îÊßÏŒ_§Ž¡û8;0’qÈã7ª¹³#‰1\ŸY`J´ó ü{ßÿâÁÀ˜øVfŽ…‚ùr·3Wâq+´ŠwÐ ÎŽš¤Àý¾ÁIÓV_Ï'òeA‡ö­­–7þ9ÿì®Þ h‹Á6ýAöKš=§ñš‘voŠ~áŽ.’KÁq54³³s1‘êSð>³E»HbLÏoí˜ë =t·=u±;€ÍJðA}ð§l šUƒû‹0äzæ§!ç7!OÙÃuz ÍW3_Àur=æ«dæGÐ=”¦»¨KzoRstaFÀ_x„?¡0E¿Ä®0¨ªßÄKÕÂÔûp:Œ—Öc]ÓBϸì¼Á[ PVü o©'5…PìÕ(”¨”¢®aü˜Þâ73ž6½sD^©nf® Y©q[}Ü~'ÈÀMh"«—  erÙj•f-Õ-üWÆ ¨*T›î(Ûj3¡Z¯bã_Ô•#áµè½gÔŽM\¿Ö±\é!gë:NŸ«YÐf g‡ÚBŠ“R–³SmÁÓ8zØFJ\kÜäzkR²À -ѳÖÿ£ïðVMIrñb>z¥…4,Ú=(_MÉUQÙ¢ÝæÀ‡ÔNÔæ®DMè :‹ø?-s¶Òåq<&Àµç§<`L͹Hç°¥þ ê¯zµ‡1ýRš6§D§—«íñ­p•½uu™}ÚßñÂÇæÅ-À´bQð‚ð¸ˆ4áX«v÷ËkÔˆ¢ Aè  é9$v¯H(?i8žÏ|Jñ5©¨–P:/V¿Ïñ5õÄ7°{SfÄH5{Ô]wo‘Of‚ãP@3IK7m¹v¸*äp)TËl*êtM­XE»½M¹ hm±ˆ»oôE’à‡^˜ÎvŠ+<¨¢¹Ï]„‡'6í5ÕÖ=TÓ„·Æ#ЃÀ°è8WЩ}V¡ƒÔ6ñƒIÖÙ~"HŽ'cál?ˆ‡á˜ÎÉx¦%cWxš ÏÙ´´¢Oé,0Î>ŒN9º§eÌIþÕÉ¿ï endstream endobj 55 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 56 0 R/Group<>/Tabs/S/StructParents 16>> endobj 56 0 obj <> stream xœÕZYoÛ8~7àÿÀG±ˆiñÒ±(4½ö@5°i±Pl%âØI¬\ÿ~gHI–mqìÃæA‘%Šßp.~3ÒøÝ}Y\fÓ’¼};~W–ÙtžÏÈùx²ºý9ž¼Üæã¯ÙU±ÌÊbµ¸(ñÒïy6ËïOOÉÙ‡÷än8YˆIE$$:Õ$Q‚ÜçÃÁßoÈr88› ãOœpA&—ÇA!áDG,Ž5‰SÍܹAŸ¿Çäj 3’+ó+©~}΃ M‚9UANèO2ùs8øó~^-Ø• Ž™[à ïúH˜½…&’…n˜‘7˜=}¶anhä÷t„ŽD-Š+ü±…š[ËÎÌ­%Á__ÞÑ‘ ~PüA(O‚5©à 0…Cq‰Sx½ƒ¦0•§…­Yâ\ÈáÖ‡Qäã—÷dìpö³UY®nÜþþiµ*ýù»L˜ö³(¥EÄ„$RãÊ`l†½fŒK^|N ¼bW`2ñE&Óó€Ç{²X*îDìRÑ·iÉø+õËû?>Ð[fRÅÙä¥A±ÆèÀhXd/&:lh™ãGˆ ¤BÚË+—Mü™³EvE¹l=:…18C¾Æˆƒ×1Zg|KªˆßØ>V®hRÍa$ÈQ5ÎÀ˜ƒ} s¡p7‡¦$—L&.M¡Ø™YFi”Ñ¡‡³2»€¥eF%ù‰¹^lF¯)‡Ñ¸p»žlAnAZEo4iíãmµGÙµN4Kž# ®rJ±¬“©‘hÞèîÝà‚o`‘¡_©­6ŒÉ­Nª§ìù¬²>L­ä¥Ùï)WógVŒĵÜ­î ÷€!gª7ìá‹Cñ¥?ŠÓ.ücwì=˜(4üÃóè &2üÃÓ§MéËš‘Ž»ðûÒi+C<¢“ÛÀ7÷ Œ‚&ÔZ‰ÅSð(e:q Ž ÉP Ñ ä-¬90ªDº`úAys©Á×ÞÂ6-åˆ;úfî1¬ÿc5}ÚŒ|YS§œEDz¤f{l6Ã’ÌóÅ-­6|Sš¬›€Ï¨àÕ¶ç-(D¨™”®eô©1ö¦FÈ5Gà'ÞðU̢Ã2="(£mý#0œ¥Ê"Ôà‘t X¾Eepn'Àã.‘¯Ñ‘¶wJ¸“ùDZ5¿j¹ûÄÊ[i£Òˆ©Ãñ½1;«üë:ä[É!¿4µûº­ ÊŒL+öŒ[ÿ#ÚÉr‚V‘a'ØÌç/Y(ܨ»Å÷Æ;Dá>Ýbj?S<ã¢OîsßäÖWÔ]EyÒT¦8KÏëfð¦¢ÜÖü%vƒ0£Ú’ÑjžVƒnd3: R7‡¶’¿-k~ó¥0•$,~UöúàrÁéÔZ`1|°3l±Q2ìÀ7±qÀ”è)ÿÌðxÑXúí%àmHxÀ4»´[9Äí þ<õ%W‚…NñzÍàߪ0éT”h‘c,d†ÙœÚ&Eëv›«È|ô^´“ª(åÒÆ$†Îm.?Á F¤iÓÎëBiÜ6 Kó¯¨ú*£·ì^y÷€·—SlDLqÅRéÒ^¯ù.Ü Úè(fÔ®0–‘bò×·0k*+2døzåŸçèxiY_7A}…9s Ÿ™múoxs‰7MZøé-Ƶ’Ü!{¯¼Ñu ¹¦C€ï·›ý!\梶.*óu“ú"“W[ø~¤÷ä‡ÌtN[Ô¨î4㻌ËtTa`™Ïê”Qw³OÈ“·p BÁãPd ª—Ö¥,¿}])B¨AveðÙ_À úŸ{0ïÝFܲ¯Ö‹93ÙîÓoØfÏhÛx„íðçí— °Á0röÒø”ñÊkÀ‹’À亚˾ú+LÝíAÅÆK+ßÄZ|Ë?gÞ¶-É%³ô¹·šX¤É1øÇÔÄÝøq„ÉîWoß*Lo7ß[Ñ+pïøÿwªËèÕ£·â]Hq”!y/³ÛÆÑHÍL}¼‡?SÚQum|ulÂß…ucö®ÙÛÛžp&Ç÷VÔpvàïtlÌnh"©4Mšl…ÇÃÏ©^‘ãë›§íïRJC=ЬÙRíÃUoÃÓw?BqÆ+òÁæÑ â훡CdOÝ(íO~|áŃ¡¯eý Ùδá/¶QdFñÜxƒÊzkÖÉD°Ô!kóÖp‡ëä3rzí*ÈØÂ!ˆ7Ó(ÔÔå ûßV°Ý–_FÍeüZYoª”Ö׆ÛLÞ‘JšÂÄåCÛM;ñz3û¾Õ©_ d­ïJJ¨€d/H¶®^Ôl¾&çÛÖ¼á÷­oììB³È×¥ƒgpÍD×&ÙPýéVsÖˆ•/Ìšò'Ð@Kn/ µ¡€Ùz73o-žT2¿®}ð/ðѨw endstream endobj 57 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 58 0 R/Group<>/Tabs/S/StructParents 17>> endobj 58 0 obj <> stream xœÍZYoÛ8~7àÿÀGiQË")Jè½ ´hûÐ Å’c¡¾ÖVÒæß/gdIŽMFµ;YlË¢õÍÁù8‡ÆÏ7U9Í&»¸?¯ªl2+röi|µZ_ݯ‹ñûì¦\fU¹ZŽ?Þ^WðÕ¯E–›ËKöâÕKöÏp!üiÇ,d*ULG‚mŠáà¯_Ør8xq5ŒßpÆ»šÜ, g*’D±$U0wfÑÛ »Ùš'²¼Ò»«·ÃÁ'ïÊ×Þ̼‚ù_ØÕïÃÁkóÜÃÁK %H’@‰ ðïë™0GŠj„n˜Ì‘=÷a~â{Ì /›—7p±4Å[ËÊ|Â[Ÿ=¤½?Þ=÷GÒûìÃó¹ö¶þ(òÖà€‰ùWNáçåÄüv‡ŸšG)"” ´S‘Ó½oV±×ï^²±c³¿XUÕjáÞïoV«Šn¿K(¥Ì*%â@H&• ÌãbtË~dK^øyÅ¡ÀldÄÓ»š|ò¸>’ýlDƒ%VD›‰>t®eã÷àÔw/{ÅÂS=%]Ì)‡*``â°¦;Lñõwÿ¯!ò06/¦¾^ ‘9‡…/MÜ™»™?RÞ./©Äã‘B§xî8ò';„´áKŒR¯œÀ`RØ%XÍd¥ªb 6ÂûÕÌá1«Ê¥¯¼–~oÉqêsémàîʬƒgã×ßÌ8€ôf ]V+_Ÿ¿.îKtÀ¥Ké‰'3Žç)~¼52Ì3¼¬ )·`‡*[š°ÊèM$œL€;=ÐÁÈG`ú6ž Ûx!¢^:—Tô'© Ÿš~0«6˜.¦å"çI¹F¨@9eé3yDåòX%6üŸãª°à±É#µKÆ]f¼ã,`†jÝ|`yQs‚!»½t-òžµ¤Q Š2J߆;ét¬ró¼öátÑnôáNÓ÷¹^‘¹^ªsðc²hç†íèªg´Ûa¦~›`À’x7àq²ðN“@º û,œPyX¥<ˆ]‰Ä<»µ/1‚ì!훘ض™Ø^ a ¸•I*à]¨u¿„åÓ6ר{üÂø.æ%Ý6¡UÐÐ"Ú¥6óCIå€Éw¤‹Z¢‰K(±ï0ãÝÚhú©9GjLˆòönG²Â[…ò,N.À\¬iþ_°ŽfAcŠfá֦ל'ד.FÊ"òHlóÎçéØ^¨Š38$«6p«üÞ– %˶GBË<…Ö°C•®ê¤ý ød±)L•"ø½¾$+T#™œ%ÀÉå’36¹² @›vì.Ö]‹"÷yT·E7…qý¤úÆÆæþ6EÃ@»Äê5ÿÉÕ¢sˆÊ@ëãTjŸÇâ1Œ. xÌ?0KÀÔឬ×&’9ðK‚ºÆKÓ®­§^ÝÙݱ’Ý/oÛ)nëóºhi À9».vÓµ}>ÍÛN Š<óG¼k¤Ìs'ïuË^]²•³of]iDIèzÌQªƒÄe[²´K…J'+L=?Ò8?Z‘³â80t(Öœd™p8¤NàärÑEÎ2JmP“³¦j“æ‹e]X@Vk8–r€÷ùäšØée‘Øøè¡^Œå‹åín†T³²J]geù–[uUV=ßñR=Ú© –Á÷@YyC[ë¦PÃÑUÅÈ2{äD—í¤ "É¡iï †l+Cu–'—B.„6”òôÙŽfFó¨6½æ$›¬‰˜Ûx…Swß/Û?C£¦# íÖY1o»¥ØÒÀÂ}[«¯ëú‚..Ì~”Ò¥F¯É*:!Ó³8¹ 1;)>è©h`Á£ <ìKâáž <Üóëó÷îCDbÇŠø*“͉¸Ñ\ÁEd©?7Qlàk³÷³¶…~ÝœÇÇÊn´G•­Gq ]‚m÷ߣ¨ÏD,ÃïñUнcVù²i3˜{éÁؤMÝk%tÞ½ÊÙuý2‡IŸsó¼¬Ê®Í¬í_6¬ÖÛ´ý¿llîð X;ìqÙ»‡QœÂíLªT?1…œ …,Õ’R}ÌÁ›‡œ"“¥ü!¤üO­`zQdƒYíÚaÍ+9uv·„í»×AÎ$qõšªÎãŠ;Ü[ÝÚæxûÖDÇA©úpGã×°toûZb®A £r—1z‰¬ÌâÂìíÓë>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595 842] /Contents 60 0 R/Group<>/Tabs/S/StructParents 18>> endobj 60 0 obj <> stream xœµXmOã8þ^©ÿÁ“ÕÅõKü©Š…îÝžvµ•Ä®N¡ Pmi¹¸Û3Nßhb*/ˆÄ/“yÆžyflz'Ëjz[Œ+Òï÷Nªªß—rÝ-¿÷F?ËÞçân:/ªébÞûú|SáÐïe1)—yNNÏäŸn‡Q†?ÖjMQ™"6dYv;} ónçtÔíô†œpAF·Ý!F8Qš£ˆÉ0óB¿r÷ÉëÙUïc·sbÝÇiT’ø;}êvÎAï—nç͈} Œ¡J¼²À¯ð~ ÓX¨•”ùa’`0ýÜ…yˆMT.ãDG$NDȚwؙƺ©y-7õ-Šýyq'2úc‡ÄÜFOq’Fè€1<¦·øùt ßbtĨ ´¡µÞ…¼ßû EÎ/¤ç öÓEU-üñ>\,ªpñ.-UaRJh*$‘ À(ÄOÆVì-2>{ñ;öŠ}ƒIæÙ”ŒÆ×϶X©iElÛ¢/[×’ÞgtêÅà3‚e¦T¡9û†ô!ò³h:+‘;…#OŽTqäi%I £ªž¯îc ¤¦óXEýoCËÛ˜Ëh‰³ CÝnø_h`êst»_µZĶnA¸˜Å Ï\ó$f…ëVåÖ¬ª¨bMŸÐØ Teõ0 Å[iåÞmÛó_Ãm<˜Û„<_¼_®_ç-#©µDg†6áŸÁ/ð7AWa8 /Ê#·¾-§\z ­\†Úym€îï†OƒÁ+Öÿã™T8& 7ŸH¼Â±Ȱt%ùìáX‹tL|Å®5•ÒcæS0Ã!7{PŽ=:µ @¬ûÖRïôÞÆï¦»P)¨ôùJû(VTÅ αuâuîm&ÙÚLŒ 7W¾Ä‰‰àdc\̸ïÄ ²·>J¹A'2o&eOˆPçüíÙË«à·`îY3BXÊ› a]#Ü:ëźãßì禎¡Ýó×CžmcРŠIŠá" γÊú–ìÔÌ3æHÙ“»€Ù,Q­–èJr¥ºY”ëòº_ëŸ!í VŸ¶I[šÁ“4y~*QÁd­Kÿ4™·wöÁo0/¤"É·;‡2» –Ù™>_QÒ[ñ•MCaF3wõÀTèí¿'ø¼Ùd!8… ˆ6Œ•>JÈuóU”©è»y(óx*(óšwÈ &T(-ÚðÙy_´¢¼l‚» d¸„ºuu.@*V>èƒw¼`wó4Ó-ø°` þå°è h•okïñWò6Z†â ÜÚ¬o-Ç^TE#[AúŒ«3ÆÍYn itžö™T @dž‡ix*œáv'»o~Ž1ž¸i=d|`òDö· @µÞ¨n“êœÉó³ÜBsÈÐìákÈÝK Q¶64cy¢v´3ú`L¯Ú(ƒØfÃ\­ ÁN©lêHÄ9M¥Çkìß©I߈ÿ?íïÅ_ endstream endobj 61 0 obj <> endobj 69 0 obj <> stream xœåÛŠ&ב…ï ~‡|ƒÊ8ìƒÛÌ`,„Z0Be©FjÜÝeJ%°ß~bí\?î‹fþ5 vKVîêÎû‹ÃîgÇyŒóhv ;ìôcøa-އŸyŒ<¼µc´#Î~Œ~DÇGžóóÈ¶Ž±J}³Œt?¦Ýò˜~ôÞY†l³ ÕCf«?¯[êÏËîÇòZÎc•¥¹êéqë¬k©Wyc‘uK]K±â0º·ÕµnZý¨¿®ûF]WÝ7ˬûÊN⇳ µke©×‹á嬷Äsõ:V/h£áæ²: ¨?÷”ÝeÎÔbÀΪˆxIëeý¬PX ¼œ©…×bÂÓ ——×f­÷ôãü¶²å·³²“å¹yÙÉrݼì´òÝ*8Þà|=Æ;œ÷28ทÁç+d>á¦ÏZÀùòÀW9e>_µVÛU¾X8ö ¡Š#*ŽˆY-ð:Q[ꎛkS}àæqD8nžµ¨m­À‘eÃò¬EmŸeYnxzhؤ,Ë=ѯ¶#Ëò€óõJ1ì,˳•å,ËëÜ[T ¸Z÷åYѲæµèc×’ÕÛ¦Ê0‘/YQ¨EXNעܮˆ™±·ºÅu+<ë-­“­0³^–{âž²Üù^–Gyg£œ@¦<¨…¼,/Ĺ—åUæµvÖVçv–Ô*WÚŽjeKÛ®V›ûƪ•(V ´¨±ú¡"ô*aŽ!e²Ò Ð;Z«`ƒ¡¶£Z÷µ^¡µJÖ}E¿mW‹ª6€y)Ûl¸ym!ΕDm!ÎÅY?ç²ÕOĹò¨ƒJ«Dêx9«÷ï^èYYï€Ê©¾£Z»Økçj1ò¢,×ózÖ“½bÔáªWZõVV+'*ÕkϽ<轨}”c^iÕgýäÇ>kÓ¼²©¯Iepu$êï•MQ­”ª¢t1T ¿Ê®z½Àp”¦J«ȉºoÄÀÍUPè à•_£ÝPV–—Â}ô"0 D[5êîZ”åYïä•c6äqY^UÜQã T9$}qV)X<äzÅh‚$ÿ„ (v7£ "¡+¿f%Æ26‹cÔƒZL”DzáEgåtùœ¨“ˆsA0;âœ(™ˆsýoÄ9Q=çÂb.Ä9QHçʯu¢P5”T¸Z÷­] îªäTuEªüZ>P{PgQrÊÄŠ›«â&*M½ÿÚ®V~­Vïíµy«ž^x­Ž8×cVGœ+¿Ö@œk;×@œ+¿ÖDœ+Fk!ÎåÁZˆsGå?è]eÏz€ï^d íèDzbÛ«„#´`õÜ£œ›Ôã3ª‘ì¤;Q | ²'\D…8[m€ƒê³²¥V°¼i@Rž¨>wåO”XXÞQF?gƒ–× ,oïÑ·àôá»¶Ÿ0ß½k·‰Ý½PwýË€­£îÞÚ‘ÖU¢U+°j;âèU0ë=ìU«¾¢BUÍ(ïè-¨Ëè•%U†Q Þ›¡H:[ÕŽÝÐ{Ntr<£ö®Vh@:P,*MÑÐv†è({aè¾HŸ@Wqì@ ˜8úEºbh˜Ž, TÅ XÞÞ;,ƒî@Ù)\&ZV;¤ˆ•ázÔÏÚ2܇gL4 ô%GìwªÐ¡}¡Ÿ'¬ YEä®´>hœ t°éR )Фw· TâÝî"öLž˜*ÐðvëÞ/PŸwË‹Ä3ÐóÍd7½@­ŽOÑ ¥$–ÑLÍ=vìsÏ+ tQéH4Äíýîšà>P×ý)ú/ê\ -%²$0$" M9ö`†þš ŒhµBì1ì&–79–QZ}¡ú`=·ï&}µr¬°<ѺûîÜ  ý¹š!½û„Ý÷Ä~ ¦Ø]8ö8‰È߆üäo ±{9þoP ûüm‰ý@þ6Ôš«Ã7ìò·mr&ž±½Gþ¶í=ò·mï‘¿m{ümÛ{äoÛÞïi`{üíÛ{äoÇÜÈߎ‰"¿)¿…-öÜÒùÛñÖü­RRö¿=±ÈßÞ°ÈßÞ&<£×~äžJ{ù‘{,ER"û(û‰üíð>‘¿•˜’ö,‚éY;ÎVöX‚iY;0£&²vìégÏ*袉ü¨Æ‰üð>‘¿»—Èß*×P``ÉžQÛU+<£‚Z£žQÂ{k5÷\†É¦öo_«Š]îùgV$òwÌŠ v¶ ¦=äïDìQåjµ‡:Œ3Û{äïÜ#²v‚œ=€L´DÖNÔ–k~BìY;áG"k+hPÀòö~OU GdmµTŒ‡˜™:öcøØ=k ìòwNìòwNìò·õÈßÚŽ=db…ýÈ=hÕþ$òwíYù»0ÊdÛÓbü]Û{äïB–$òw!b¹ç¶ÄÙ ù[}îã uYAþV—Åà ˽¨Î=×íØ#«Ñž˜o1µ%°¼½Gþ®•PÀòZP`N;±}s؃Ͳ1·œ˜Ñrì û±O„¨úˆp­0 £c› çŽ=†±³fßZá­2Ù\Í¥öqçöíµ?¨Tµª\ÛcÛ9+î»kŸžN<Y»çÏêµõŒ‰osqÃ69èé¶¹_û\î17ÙŽýÂи¹GŸ·¸¦zŒ–ð~Áòæ~Árs(&VØ…g€Œ!•—5çbX‚'{²:18cjB§ÁÛj¾?öˆÕö…*öÊŸí‘j7رÏ|»tb¨B9EàªÆí°`vÂÌé{xÚ3«…ç „ƒ|à:rŸ×°ê»!`Tšh0°TÓŠF œö€4Qv³]IlV•iǯ~õð9Þö<¾xxóðù×ûËÓÛח¿yýÝ»§÷øê8¿>>ÿîÜóë_ÿòÿ ‰Ý/ñû%q¿$ï—´û%ý~ɸ_2ï—,a+•íößL ÀL`ÀL À LàÀ\©.pÀש.wwY»Kã‚&M š&hº ‚f š¥ì©‚B‚)(˜Â‚)0˜Bƒ)8˜Â·©¦ÿ»óõ. š4·÷YÂûÜ£qA‚&M4]Ð Askw&Œ½÷h\Є IAÓM4CÐLA³”=•@PH0SX0Sh0Sx0Sˆp…—jƒBÄÍ;弮ؕ»rdWÎìÊ¡]9µ+ÇvåÜ.Ü¥“»tt—ÎîÒá]:½KÇwéü.ॼt„—ÎðÒ!^:Åß%Rˆp…ˆ[ð„0¸Kã‚&M š&hº ‚f š¥ì©‚B‚)(˜Â‚)0˜Bƒ)8˜Âƒ)@˜B„+D¸T"\!Â"\!Â"\!â¶MC¨à÷h\Є IAÓM4CÐLA³”=•@PH0SX0Sh0Sx0Sˆ¸!ücì]4!hRÐ4AÓÍ4SÐ,eO%LAÁLÁLÁÁLÂ"\!Â¥Ú AïRø-Å]4!hRÐ4AÓÍ4SÐ,eO%LAÁLÁLÁÁLÂ"\!Â¥Ú á ®á ®á ·m~]s—ÆMš4MÐtA3Í4KÙS …SP0…S`0…Sp0…S€0…Wˆp©6(D¸B„+D¸B„+D¸B„+D¸BÄ áWPwi\Є IAÓM4CÐLA³”=•@PH0SX0Sh0Sx0Sˆp…—jƒB„+D¸B„+D¸B„+D¸BÄmo…ß[Ý¥qA‚&M4]Ð A3ÍRöTA!ÁLaÁL¡á<áwóãû§¯ÿe7¥øêɾØuñë×%¯K».ýºP7¯Ë~2>{²/—•yY™—•yY™—•yY™—•yY™—•uYY—•uYY—•uÉ×%_—|]òuÉñ±“ëj¼:¯ÁkòÚxí¼^'¯´g´g´g´g´c´c´c´cÔ;õN½SïôÇiÇiÇiÇé‡ÓNÐNÐNÐNÐNÐNÐNÐNП ½ ½¤½¤½¤½¤½¤½¤½¤½¤½¤½¤½F{ví4Úi´Óh§ÑN£F;v:ýê´×i¯Ó^§½N{DŸs¸®´G¶pé6âmäÛ¸‘p#âF¸tñ6òmÜH¸q#ãFÈ”17rnÝHºuü__WÚ#ôFêØ¹wrïäÞɽ“{'÷NîÜ;ywòîäÝÉ»“wüH_WÚ!÷NîÜãã#וöÈ¿“'ÿNþü;ùwòoŽ\WÚ!ÿNþü;ùwòïäßÉ¿“'ÿNþü;ùwòïäßÉ¿“'ÿNþü;ùwòïöÈ¿“'ÿNþü;ùwòïäßÉ¿“'ÿNþü;ùwòïäßÉ¿“'ÿNþü;ùwòïäßÉ¿³Æ;óÀ™Nþü;ùwòïäßÉ¿“'ÿNþü;ùwòïäßÉ¿“'ÿNþüùòä?Èÿ ÿAþƒu?˜Á<æA0‚üùòä?Èÿ ÿAþƒüùòä?Èÿ ÿÁ>̃`ó ˜Á<æA0‚ỹ`ó ˜Á<òä?Èÿ ÿAþƒüùòìÁ<æA0‚ỹ`ùòä?Èÿ ÿAþƒüG¿Ù¡_ä?Èÿ ÿAþƒüùòä?Èÿ`òä?Èÿ ÿAþƒüùòä?Èÿ ÿAþƒüùòŸä?É’ÿ$ÿIþ“ü'ùOrŸä>É}’ûdýOòŸä?É’ÿ$ÿIþ“ü'ùOòŸä?É’ÿ$ÿIþ“ü'ùOòŸä?É}’û$÷Iî“Ü'¹OrŸä>É}’ûdýOòŸä?É’ÿ$ÿIþ“ü'ùOòŸä?É’ÿ$ÿIþ“ü'ë’ÿ$ÿIþ“ü'ùOòŸä?É’ÿ$ÿIþ“ü'ùOòŸä?É’ÿ$ÿIþ“ü'ùOòŸìÉþå¸BøðùãK‡ð·ÇÌ}ê—™þö³§¿¾þáéo5bÑöïËØ‡ç×§‡ÏðŸß}øöï?|Y÷þéù¯ož¾y}ø×§ÇoŸ^®54·õ¿}x÷öÃÓ›ïá"þà7ÊÂãëÛçüùåõí<ÖbÿôïÏ/þÓóóŸÿ~‚ßüðýÓÓ+¼|}øãã7/Ïýü/ß×?úù·oß=÷Ѽy÷öۧS·}÷òøþá÷o¿ûñå‰ïúÙïøªBr§[?ÞŸîØ•gºcïÁþtVmº«¾?ÝÕØŸîÀjîOw`µö§;¶ás»c/m¼c/}½c/c¾c/s¿c/Ûþ€Ç^öý½û{9÷7<>Fã³Ç÷O?|uýøÉ}¿>àì?Íù÷rç8ßnú?„iäÓ<ÓùŸÖ™˜/õÓ>_/ùO~:¦“Ÿæ™Îÿ´ÏÉ|ÉŸ×aùzéŸÉ‰™/û=6Ó‰OëìL§?íôõŸè)šÎÿ´ŽÒ|©ŸÇyš/ûÿ}¨þå/þrÍO endstream endobj 500 0 obj <> stream xœ}TM›0½ó+|ÜV`0HRB@Ê¡jÚSÕ'‹´äCþ}íyìna%ôì™yoöøùaèÚ‘ù?L_õÈÎm×}ëï¦Öì¤/m牘5m=Nˆþëk5x¾M>>n£¾ºsïm6Ìÿi7o£y°§mÓŸôÏÿnmÚîž~çG‹÷axÕWÝ,ð²Œ5úl }­†oÕU3ŸÒžÝoÇdzÍùˆøõ4„9ÄÔ}£oCUkSuímûdlSÚ'ót×,ö§¬Óù#\Úpû 3öǾE@0äÙ_—þ¾åÕ/•qi\ Nf„ P@ ¨J3¤ ŸuØ\ ‹ðÚg«ôáa%QD¡bbTŠH  4æ«ô< •œ£ýXÌè“=ç[„‚ƒ>Ž xÇ„¢© šò =PJ(Îv@pÍ.®ÊVdW1¢ç®‰¥l5’kOѯ‚O;|[«ù?Bñ‰0§<爆yŒE-•¬7šOb·.WFà3/å’WFT[F n‚„vQØ›à–·Øunwài±Àb‰Å|õÐJ…ŠÙ/N@¥dBP¼C›B®:% jSÈ•å–dŸ,aŸ gšøRS‰ë/Õê!q;Cw;Éø+‹ù”póÆÅ÷aVß±sŒf' 07ºÚN¿×¡\–ûý§… endstream endobj 501 0 obj <> stream xœì||TÅúö;çlzÛ„$„l’ݰll ´@(’% Bh YÜ„–B ÒŒÐ(ˆ½+v¯ n”`E/vÅÞ^½–+ØñzUÈÿ™óîTîï~ßÏïþ¿}“ç<ϼóÎ{æÌ93g’ "3&ª.Ê/¬Ø—^ö i™ÍD) Eùc ÎØºáÒ¬ k?1»ßÕ÷;@$΃£ºv^ÍÂØ ÞDž1DÁɵ˖Úv-|+‡hó¹DA5,œ9罹œN4mQTŸ™g4,ßÜ5šè  GïYõ5uÃïxù"‘oà,8¢îN…r!ÊÝfÍ[ºbýÔyÐâs¢I3ÔÖÌY›R@âÁ…Dý&Í«Y±0Ëœ1õÈO¶yõKkÞ»%e6sÇòoöcÝd:›OÈ·âh{±ÿ÷s¡>ö„¼ÏpmßÉÛ㼟¼Ît5üQ¿;œë Îcj¥ýÀqã0žJNÚ¦’R:œs#ÝxÊç;DéÁÃiÐ þçi ~Ή÷UŸM…ʯӔS=בþ  «õTu²ºTü> ¸±ÕÎ÷ M=•sh‹È| 9B_'‡i+ôµ~=Œ§Ò>xÙ©Åuh†sœx™Ëtà¨/$“úÊ9¾ýñ×ê÷]­´xƒÖýQsõÉüú-òœ4&¸Ž®>ö|'ô%÷ä÷ì7ãý¹äuiÏvÌ«§SÙÉÚÝÓѯÝCér~J馦޾“ž1A(=¤Ï÷Û/cÐÏËþ(N™~=u j;ñêË©‡~#u=Á߃*+—¶ µ¿S£6ÎàQZQ7íJê©}A¢–ß‘(7ŠiÔhš„ØO íÐFüîCùâc²Ë6Ú:²ê_S–¶–2µõdÕQþ©^Û«á¹&±÷ÏîEÀ°€±i׊ð߬«¦Ç–ñ«§Ö ë7zP ¢+ý¾ ¥_1özçNŧÚ½3 íC²žÐ‡%x‡¿Ùî×öuˆŸG뀕ÚRz8²Ð\t.°RM^`æoÅé¿Ò Ø×ºà/ëÿŠ¡Ý$›b)ÕtMמ#»¾Ÿfe&7uÕߤµºrÀµÀ|Ü,f6 ˜ Ôå 06©‹~MÑ—P¥¾2ôYT£ï¤ùz eë÷Q©þ•c1ØÔ3€!ÀL ˜”ɘú—yÊýës²þa_6Jü„=„—Jµ»i„ö.9´ÛñŒ|H“µ‹©ŸöübŸò£û4ñUžÿ¤­v=劃ÔW+§aZ õÂ3¯£MõÑr©«v:rEîSkm/ýOŸìïF¼†?ãà¹(þg¦¨ÿOϰ€ýo1ÓcÿÞ¿}œÌ´ƒ”¢}F›ô`ªÒKi“v'p!Ê…(O¦MâvÚdÄíc6ÍC]ÖÍ&ªÒÞò×]K§kÍTŒµÁ¤ÇCLɦ"¬÷!÷ÿí$` XÀ°€,` XÀö¿×ägLƒ?ãÏ‹ês¦¡ÿàs¦ÓÄÿ¾)?oŸ5ýŸ3ågÌ?ãz°€,` XÀ°€,` XÀF$~ó§Ü°€,` XÀ°€,` XÀ°?Ç´… @d] /õtŽLÆûÑ( ‘€Kê“·n¿ó?9wÀ°€,` XÀ°€ìÿ[ÓýHá¿€«ÙŒ¿mK¦D2i&8&‹‚Œ¿REvrÐ0N%T %M¦©4fÓJÚBwÓvÚ%ú¦f¥öN훚“:(uHê°Ô|[˜ÍlëbKµÚÚVÚZl›Ïÿbj7þÖ-2Ú1G ãX*÷g¬¡¹FFß‘Œ}Rû#ã`dndL²¥—ÚÖØ6"#!£h?ˆ~Ç!øœü­qq½›n‘ª½V{B/Ö‡SΗ:~èþñŒóñõÉÇë?^Oôñºåßiå¿<Æ¢eÀ¹Ôâ³KèæSß«Œã=²3úhýJ}§¾V?Sßd:Mwë‹uÞ¨ï×è_é_ëßèßêßéßë?èõÓõI¦B2Q,ÅQîMu§,ʦB*ÂHNU4êh-¡¥t­šˆf‘,ÒD¦˜ ªÄTÑ(ˆ&±L¬ç‹ Ä…b³¸FÜ'v‹ÇÄ“â)ñ¼I7™Ä>S)Øb 5…™ÂM¦HS”)Ú#œ¢·)rE)‹þÿxüßGFYóÿ5e~߸¥ÿêqwÅS2ñßÎ:q4O#:~TŒ¿kKúYô‰cߌÒ)ßå?ÇôãŠÓôéºü]:¿™2™åÝ<õ¤¢!0ó)0óÉUµ~ÝÒ%‹-\0^ãÜ9³gÍl¨¯›1}ÚÔ)“«*=åeÆ;¦ttɨ‘ÅE…ù#\yÃO6tÈàÜAs²{÷ÊÊÌpt³wµ&ÅÇšc¢"ÂÃBC‚ƒLº&(«È^\mófT{MöQ£zɲ½ŽšcÕ^\Åc¼¶j#ÌÖ1҅Ȇã"]é:)̶a4¬W–­Ènó¾Ph·µ‰ª2ôÆB{¥Í{ÀÐc mÊ0 Q(¤§£…­(iV¡Í+ªmEÞâe³ZŠª ‘¯5"¼À^PÞ+‹ZÃ# # ¼™ö…­"s¸0„–Y4¤U£Ð(yZ¯î(ª©óN(óZÒÓ+ ¹¼ÁÞ#—m¶ì3]`kÍÚÝra›™fT;#ëìu5S<^½Zô¢–– ÞX§·‡½ÐÛcå'I¸äzo–½°Èë´#Yiù‘oÃl·µ$tÞ~`GOßì0$)å%&Ô+MèzˆëKO—}¹ ÍE3Pð6—y¸l£¹²•^­ZÖìV5 nYÓ¬jŽ4¯¶§Ë[UTíÿ^6+ÉÛ<ÃÖ+ £o|;ðz›WϨžQ;KrM}‹½°Ç­ÂãuB¸jü×ZÔÚ'ñ5Õ¸ˆÙrÊ<ÞlûBo¼=Ÿà°É{0{¢Çhâoæ/ðRu­¿•7»¨PöËVÔR]È”¹ìež]Ô¿}_ë›e{@•²ÞÄÜ”Œ¢O]ƒ×Zm©ÃóÙ`óXÒ½®J _¥ÝS_)ï’Ýìí±§K7Îh´Âµ­‚啇8BmÍ¢WÊ»‡­{þ0T˜q»Œ¢¼£ùÃla!†³ø#¤êÝQ0JVé²iÁ(Kze:ÛïtÉâïSÃzL.3GúÄçùÍ®q´ìP[Q}á1ì4ÈßA¶“÷S“cá?1Z„ÊÛ9JUéÌ\ø4¤1\ò.&Ù¼4Áæ±×Û+íx†\<òÚäX÷·t¢½´¬ÊcÜmÿSRÑ¡Äõ¹\òR:ªUA+À3Xì´¨Ûj”Gå#ÅQÇU—¨j»ìWKK]+ÞUòQ¶´ C\Péהּ{g8í鲟½²ZC)2½¢ºsµ˽¸ÆŽWaqKM[{óŒ–V—«eaQõ¬!˜-ö’ºûDÏ0‹ÑùrÏËJyî8*¥ùH¥Q~«]œWÖêçM¬òì Þv^…ǧ ­ :¿²µê<»lx^Mz¥Sl² 3•£jÄ[v¹ˆšZ“á0ʵm‚ _¨ò ªmÓØgæe'raÿXÛfâ—Š6ÁʾfŽÎôG‡¢Æ,k ¼HȨdk%9À®ð W¨+Ì©EiRéòÁóbÃmQÂÒŠœå†»M4·†¹,»ŒLåþÈfDJ_óz.ÃŽI„óñ…»^»Ê³=’ß8""_žÂ¤Yx†ð>)²ÕÉçou嬖êJ¹zP"žU| ¯°'¯fŽGzÃíõùÞ{¾ôçIûƒ¥?O¾H¸ÙrÑm©¶c!ÆŒñEð\ÓeJ[[{{…'ýËÊtÌ¥)@•ÇæÄË-È1q#%ªáém®­‘ý ·G¶ q”ÔVb^ª„)ñ†!C˜?"Š6r¾¡Q-žµ»!áÆÒÑ\é­tÊ“zfWóÕì¥Qö!Þà Δ!O”]Ùgïg,>˜ëᎠ’ÂÐ7šèaEœ¬’)$=¯µ£ª¶ÚÆÏÈDÌe~Y„[ØS5ß”Qo Üâ¯$yYº#"*ÜÖ ñ-uDo¹æ9B*+¹óFiƒ?ç6{#УŒc†ÒߣƒªÙ|o@Weèc2MY•ÛW`é”62… Úå(©ÁÛÛGÀcÏUCå"áϱ‡½!òÊ#1îXÚÚï°Ÿ‘~Œaío?ùü‘e&*U¶ïðNvöÊ =Þe¸[ZB£NÞ€Ç+4êNÍQ+ß `ùÀÏ›­H¾*í£[µqNƒ…Á-£íxƒh lttLŸt[]¥ŒB—'kÙo‰c‚äkÚHÞbªJÂ_â›ÙâÙ±8ëH±X›AGoÞCàRäZ‹geŽÅÛˆ'S…È;‚&fû»<GJTã&™xüñÔÉIÓ\kóÌÀÃŽ„ÅÕ-Å-r‹Z[ã6ÿ™¼óRb^<Š¿K€ @?¢ê€[×€ š‹L‚"Ð^P¼ö8uÀRà2 ± îVddÓÎÝ–$F㦞£ÄÙJœ¥D³g*±V‰5J¬Vb•+•8C‰J,Wb™MJ,Ub‰‹”X¨Ä%æ+1O‰F%æ*1G‰ÙJÌRb¦ JÔ+Q§D­3”¨Q¢Z‰éJLSbªS”˜¬D••Jx”8]‰IJ¸•¨Pb¢åJ”)1A‰ñJŒSb¬c”(Ub´%JŒRb¤ÅJ)Q¨DùJŒPÂ¥DžÕ8M‰aJ Ubˆƒ•ÈUb•ÈQb€ý•è§D_%ú(‘­Do%z)‘¥„S‰žJôP"S‰îJd(áP¢›v%º*‘®„M «iJ¤*‘¢„E‰d%º(‘¤Dg%•HP"^‰NJÄ)«„Y‰%¢•ˆR"R‰%•S"T‰%‚•R¤„®„¦„P‚üB´+qX‰CJüªÄ/Jü¬Ä¿”øI‰*ñ£•øA‰ï•øN‰o•øF‰¯•øJ‰JìWâK%þ¡ÄJ|®ÄgJ|ªÄß•øD‰•ø›)±O‰•ø@‰÷•xO‰w•xG‰·•xK‰7•xC‰×•xM‰W•xE‰—•xI‰•Ø«Ä J<¯ÄsJ<«Ä3J<­ÄSJ<©ÄJìQâ¯J<®ÄcJìVâQ%Qâa%RâA%Pb—mJìTâ~%îSb‡Û•ð)Ѫ„W‰{•¸G‰»•ئÄV%îRâ/JÜ©ÄJÜ®ÄmJܪÄ-JܬÄMJlQâF%nPâz%®SâZ%®Qâj%®RâJ%®Pâr%.SâR%.Qâb%6+q‘›”بąJ\ D‹ç+qž”X¯Ä:%Ô¶G¨mPÛ¡¶=Bm{„ÚöµíjÛ#Ô¶G¨mPÛ¡¶=Bm{„ÚöµíjÛ#Ô¶G¨mX¬„Úÿµÿjÿ#ÔþG¨ýPû¡ö?Bí„Úÿµÿjÿ#ÔþG¨ýPû¡ö?Bí„Úÿµÿjÿ#ÔþG¨ýPû¡ö?Bí„Úÿµÿjÿ#ÔþG¨ýPû¡ö?Bí„ÚöµíjÛ#ÔnG¨ÝŽP»¡v;Bív„ÚíµÛj·#ÔnGl—¢M;×—6ÜŠ=³/-t6—Îò¥ 5séL¦µ¾´HÐ.­fZÅ´’é _êÐ _jh9Ó2¦&®[Ê¥%L‹Ù¹È—šZÈ´€i>‡ÌcjdšëK)ÍašÍ4‹i&Sƒ/¥TÏ¥:¦Z¦L5LÕLÓ™¦q»©\šÂ4™©Š©’ÉÃt:Ó$&7SÓD¦r¦2¦ Lã™Æ1eÃTÊ4Úg)•0òYFƒF2û,¥ "Ÿe ¨©€)ŸëFp;S·ÎtÓ0ŽÊ4„›fÊeÄ4)‡“ `êÏYú1õeêÃɲ™zs»^LYLN¦žL=˜2™ºsê &çìÆdgêʩәlÜÎʔƔʔÂdaJö%uaJò%ufJdgS<;;1Å1År™)†ÑLQL‘\ÁÎÆu¡L!LÁ¾.@A¾.e “ÎNK‚‰ íL‡qˆK¿2ýÂô3×ý‹K?1ý“éG¦ƒ¾¤  ï¹ôÓ·LßpÝ×\úŠéÓ~®û’éìü‚és¦Ï˜>å¿sé.}Ì¥¿1}Ä´ë>dú€ï3½Çô.Ó;ò6—ÞbzÓ×ùtоΓ@¯3½ÆÎW™^az™é%y‘i/;_`zžé9¦g9䦧ÙùÓ“LO0íaú+G>Υǘv3=Êu0=Ì·˜dz€iSGîäÒýL÷1í`ÚîKÌù|‰“A­L^¦{™îaº›iÓV¦»|‰X¯Å_8ËLwpÝíL·1ÝÊt ÓÍL71maº‘“ÝÀY®gºŽë®eº†éj¦«¸Á•\º‚ér¦Ë¸îRÎr ÓÅ\·™é"¦ML™.äÈ ¸ÔÂt>ÓyL˜Öûj@ë| 3@ç2ãKhÍt–/Á jö%`1gú‚Ö2­á櫹Ý*¦•¾„:ÐÜ|Ór¦eLMLK™–pêÅÜ|ÓB_B-h'›Ï‘ó˜™æ2ÍašÍíf1Íäž5póz¦:ެešÁTÃTÍ4i_ôTîÙ¦É|ÑUœº’Oäa:»;‰Oäæ,L™Ê™Ê|ñ.Ð_¼<Ãx_¼|¼ÇùâÏõÅ÷áR¦Ñ¾xì D —F1dg±/~-¨È¿Tè‹?Tà‹oåûâŠA#˜\LyLÃ}qx¿‹Ó¸4Ì[ Ê4Ä+ÁL¹¾Ø‘ A¾Xh /¶ ”Ãu˜úûb³@ý8²¯/V^X_¬œ›ÙL½¹y/>C“““õdêÁÉ2™º3e09|±r”º1Ù9gWΙÎÉlœÅÊ”ÆíR™R˜,LÉL]|æ© $Ÿy¨³Ï<”È”ÀÏÔ‰)ŽÄr3;c˜¢™¢˜"92‚#ÃÙÆÊÂÌ‘Aib§Î¤1 &rµÇ̰JŽ©µŠ©³þ ý ð3ð/ø~‚ïŸÀÀAàø¿¾CÝ·(| |€?ð%êþòÀçÀgÀ§Ñ3­žeýøøð|ûÀï£üø]ààmà­¨¹Ö7£úZß¿Õh}-*Ãú*ð ôËQNëKÀ‹À^Ô¿ßóQó¬ÏA? ý ôÓQs¬OEͶ>5ËúDÔLë´ý+ò=<¸Úwãø(ððpä"ëC‘‹­F.±>¹Ôº hvÂ?pêv n;|> ð÷Fœa½'b¥õîˆÕÖmk¬[#ÖZïþÜ ÜÜÜÑËz+øàf´¹ ¼%b®õFè ¯®ƒ¾¹®A®«‘ë*ø®®....A»‹‘osø8ëEáã­›ÂgZ7†ßf½0üë:Ýa=Wϵž#r­g»›ÝgmmvŸé^ã^»u;bˆXcYSºfÕš­kÞ]㊠_í^é^µu¥û ÷r÷Š­ËÝhë©A[çæ^¶µÉmjŠoZÚ¤ÿÐ$¶6‰Â&ѧIhÔdn²5é‘KÝ‹ÝK¶.vÓâ ‹›{›†zï[¬ÑbÞÖ¾{ûbKZ1صzq”¹x‘{{áÖîù óÜsÐÁÙ¹3ݳ¶Ît7äÖ¹ë·Ö¹ksg¸kr«ÝÓs§º§mêž’[åž¼µÊ]™ëqŸŽøI¹n÷Ö ÷ÄÜ2wùÖ2÷øÜqîqðÍ-uÙZê;Ê]²u”{dn±»O)æ[Šn–—‚žEä÷±¸,û,ßXLdñZv[ô¸˜dk²Ö#¦‹(ßE,èrf—‹ºè1I/&i®¤YÅ1_ìüaç¯;›:¹:÷è]L‰æD[¢ž ¯-qlE±Áy…Ì}sŒkµ&Ú3ŠcDL‚5A+ú:A¬']Ø„ a顈Ù!¬ÅúÃBþÈ` ±™*œ¥m¡T^ê 0Ù+Îó:&Ê£«¬Ê|ž—ÜU“=­Blª4~.Á/°Ä(¯Û¸‘RóK½©=>}Ë–ÔüÊRo³Ô.—¡Û¥&„T:§-iZâô¸N£Ø}±ßÄê š_4k11"&¦=FsÅ ó1ÑÖhMÚ£uWtßAÅ1QÖ(MÚ£ôDW<òúºGN¨(މ°Fhñš+"¯ ØÑ«Oñ ×¹]^'ŸÙ¹tÓ–,uß(UŠ&YtJ¯ü^²eùÕd”Éù»Æa éK`K•séï·úÝÄŸÝÿ~ãŸæÑ®KuÚ9ÀÙÀY@3p&°X¬V+3€Àr`Ð,–‹€…À`>0hæs€ÙÀ,`&ÐÔu@-0¨ªéÀ4`*0˜ T•€8˜¸ `"P”€ñÀ8`,0(F%À(`$P …@Œ\@08  †ƒ\`0Èý~@_  ôzY€è ô2î@àºv +Ø+¤)€HºI@g HâN@ ˜ ˆ" B L#ÚqÔ Q€O¿¿?ÿ~þ ü~¾¾¾¾¾¾û/_ŸŸŸ>>þ|ì>>ÞÞÞÞÞÞÞÞ^^^^^^^ö/ÏÏÏÏOOOO{€¿»GG€‡‡€€]@°¸¸Øl|@+àîîî¶[»€¿ww····77[€€ëë€kk€««€++€ËË€KK€‹ÍÀEÀ&`#p!pМœlÖë¨nD³Àü˜ÿó_`þ Ìù/0ÿæ¿Àü˜ÿó_`þ Ìù/0ÿæ¿Àü˜ÿb1€5@` XÖ5@` XÖ5@` XÖ5@` XÖ5@` XÖ5@` XÖ5@` XÖ5@` XÖù/0ÿæ¿Àܘûs_`î Ì}¹/0÷æ¾Àܘûö:ü_n•vþË–,9fc&-iú4" ¹èð¥~ßeÍ¡%ÔŒ¯õ´‘.¥Gé]šAç@]M[èvú yé1z†Þ<åß 9;|FÐ<ŠÔwR0u"jÿ¹ýÀáÛ¶ èc<—¢ÔÉd;êi7·uœï«Ã—¶›·ÇQ¸Ñ6J{ÞïÅ¡öŸñÊE¹} ,k cŒ߆ÜpøÞÃw7eTE“i M¥jªÁõËßÕ™‘™K4æ¥ù¨›‰cJòwž°¼úhÔZ,¦¥ÔDËðµz‰¿$ëå&ZޝÆïº­¢Õ´Æ\nxV£f¥Q^¬¥3qg΢³ ¥˜=çй´wmGçÿnéü#ª….  qŸ7ÑE¿©7v(mÆ×Åt ž‡Ëèrº‚®Âsq-]wœ÷Jà Ý@7♑u—Ãs£¡díCô$ÝG÷нt¿1–µ55. Æ.ĬƞsLyü–­µ¸vym-þ+]ÿÙÇ´XæGy"9 ß™eÍq#±×Àúèqérãúz•ßóªñ¸î˜‘¹Ö(Iu¼÷·ôt=fàM8ÊQ•êfhV7úXÿ Gb·å[èVº ÷âC)fÏíÐwИÛwÑVÚ†¯£úXÅ|ÝmÜ9/µ’¶ÓÜÉûi'µþß«;™»ßï;âÙEЃxB¡ÝXiÇ—ò< ߣ~ïÃÇåÇé¯(Ë(.=IOa…z–ž£çéEz¥½Æñi”^¢WèUzSDA½L_àxˆ^ ú„¢i>þ?€q¾Ž¦Ñ´ÿ“«Ûñ”L ´¥ý§öåí?飨AT`¹ wi]ˆOìóF +…›þFñ´£ýG} 8óÐ;A³ßÜþ5aÕ\¢¿‚UN§Lci]é]çôW|rÔÎF4ͱïlÌу76ê±y²½+¬1Ï¥…llD’¤”œ[5Ú·§ |`—qŽ‘sËöþ<ÔS!–œ6³|xÏkwÓÙÝ­Y+Çö®™žS>_ÙcrROµèý!žaÖù)ƒÊåïT×´cŠ JÃzc¬5ÛSh¨Ó?ŠNÿ(‚÷ËQ%GÑéEç#Z¬²I"›Ò)Cdù:M4=(zRõ½[Ã&añyí€„Èæá2¿±#ÖšžÔ&²·7¦wÊhY;;MÌ1µ‰žÛsÂúÈÿtjDK ܧ„|\㣃Y9‚ü+‰\câÓ49ZòÑ5EjA¡ñ®é«JÖ>wÑØ‰W¼|fbKhn î7~ÑøIëåÔnž¥dF’ðLG”ä¨J«“ ±Ñ~¨¡Q„4ƒ~ á,B?ï¹(êŠå~Éúk¯yêæl×­ßžl¹­>J)=ˆ _ä샥iÝæ‰ÚGþòµÑñoÏÞßwçd—Ë@­—¼­Ž.¿û™{Ÿ;Øéõâ{B`–<–¼äŠzC2?þÝwzìƒlr…ã®Æ@j%P4Iì h‰©l-æ5xy ^^#!¯‘×àå¡a<Ž-ÇAËqÐr´=c¨ËÙ@àÍIðMñ,¾Çpr |?ïà 8VæÌÏñøË<Î/Ô:`¨ÏfqUOA“h¤žòãî£üz¼‚ñ`Ôó‹4èÙÂHGœ.¥·l`[¡I­d­AÙ°²sGAË )ÎZC²3he‰ADzÐrcnó,Ñ6÷ß mê·…ÖÜ]hkhãkÚ6lDûxÖ±Âñ}‰i€cà˜8¦Ži€cOßo¸øÜq€›AFàPæþQ´ôxAG ]Â×:¢·ÎÒÛŸ¿eÍ+w™Æö£Ñ)ÖÂaX-š„­ A»_ƒv¿í~ Úý´û5@‚ð¶ØpÐ ¸‡…yåš-+`»ª\é>š*ïD4Ã/c,MÚ¬4ƒãv;y–±†ÜáJ;“,¶þ3Zp]®€Ä-ùüßDÆÝ7-ˆOÎí)z¨yËý„Èêy†Ò F—cîâÜc.IņNÝ‚ý;ÂFØØ¶³0ÖÔ8’ICµ,»f>b‡Ðø"µÒ0ÄÉcR®­¦ýåCþÕ…Á‘µížˆÔ'PðB±%fZ“é4Ì ÆA"wÙsÈó'Y@›0…?Hðð‚@€r< ÑGðÓ Öêw:‚KäÓ$góZm>+Gä{p0Jœ2€¼Ò}U &"ëñÝ:üçòGךÝ?Ͼmçb I½’´G‹ÛŸ¬ˆð®r÷…1òI_…“ÓK^›æ³öéD¬{éјÙlÕ`GŸfíÓˆ>ß°[5Ø­vŸ¡º:aOÉføvL ÑÜûHß…¿ÉýTyÈàˆûç~Z·eãxrÅwVÏ€¬ ÈžOË^œ¥Î肘ÔÈ—ÔüË 1²BjZ¡dµBÉj•UÓ9}«ÁöƒÜͧïÓ8ïÓ±O Ç> |ß 0'¾æ‘ð ž8¬](]Ç‹9Óa³Wóˆî ¤ëèBéZR'@ʵDéSgú|í¡ÏýêžÎ¾‡^{è¾SŸéšŽ]ù…;¿°!]ûùëw=¶¾œxäKo{òý'ýàûF¿ñ÷o_÷ã{–¯º÷Ķ럻gpÕ}?B:øÁÁX÷`qì+HŸEh­«´ÖUZÞ´6¼i­«4$‘CôB½@¯Àñ/ÌG½pI9&–AAÓ<èwÔ6Ä—7•b¥Š–†{O+`wÜJA,ÖnáÅ‚*õ䋹Ýÿõ–õRÐ =b… ·U n¿v >Ý<6^ù•/.ßÖ!Üôøu-ùêâ”aÙu{ÆV\]gš;WÞ³EÅ…â. X'öcÄŸP-6² o°¯¨¯°ï-€-Çã0WgEh‰€¢ ¨(jŠpAº§ZBþØÎžË9ZA¿§ƒCÍí!ý“ïKrï ìHu:­€ƒðÈcŠv(–Å|»àìbd5y zv‡Ôòo‡d·ãuÑX4ZÈ8Úñ¹‚VŽÚm«j[Õ|CW1Iµí®þ–ÇÂë2ºªrë&6?×¹Ò™M?ð­Î-~àøX0ì€Ë©­ˆç~SÄ(di\2ºciû¶MVS¢eymþ/y×ÀvCç‚Í+ì¹8Kncu^®V¡Ú/ž™2 ø@»g»s»æÿÚ5XÛgˆÊ\"•“¬ø@*'⃑T$Å»ex¬†· À7pˆšÎý4Q cÐQ7R!ÏujŸVõó˜ :¾úÃ¬Žæ81Ј7æ8áZ%l5Š¢½¦ín]|ƶ6ö¹fE˜¿%ã¬É?¯ð,êóN¡±® UD ¼£ÇtÖ8<íqWO\tàè„vêy§Aœ†Z…¬¦?¤d@“[–îþêxûޱf$9kJ¯ÜÕ·d|i$5¼ýº«†ÓÍÛX•l‘hŠ iŽá’ãM +ë\©‘«¯»z$_såg·¤ì\æ·{-L¨<ìk\™n\Þ\›n[µkÅÐí£Uf§_âDY²x$½'ìõÖt”5,oI¥[GvAµhþç×`œ…Tv\ÎÁ¼H„¸OAuø‘âÅç¦á8£-0Qôjþ&äã»ÞçÂIˆñÚkAÙ¡·àaRó©á¼v.¸_”þe¾Dhi™1yåÅ(#<ÿå"Ë7³¢G’Ôº*èçS òìz3M«ÙàÆ*<½Gz“¤eª¢d$|ò9'–æ€Å˜]ƒÂ®Aa× °kPØ5(ìOTÐ0ó€Ë#szp CtXvÏs%ZDJ$Jäõ4Ü–RæI–-GóÒT‹D%Ñ|O×þ™›®ùÁ¾N5_–ØÊ‘›–õß4”@¨%=þÚÍ?ÜßѶçØn2\@êÂßÖº¢ªrÍc¤£4|@,‚R‹@ç[Á]ð3êÂËxÔˆW:ñJwÎhÎ5 k– [`#g›œ²SŽ–ù‡eEÍ+,™¬hÁÕá{ãããã‰ñ„ûxq7í)’ŠÔ7 %1e·Ó qœ29c^{Py†Ì_Áâ–ò'hÑSø 8¾d+õGŒ$ëƒ5ahnޥޠª1k4œ–ÊÂí°j ûÞ øë ï-ØÝHýE[ðÔÌų¹¥ÐÑ”B³°QžÄË´¥ ɰár6ªjñª¼*‚W…ñÆáŠáp G–&›@³eµÁ?XL×^îœyñ¾7ß(•ÉBk1 1Ñ OÜçOxLTþ]âÒ䊂•3™ŠÆÅhÀ‘㸕Ô[Ë|ž UOâq÷’´öú®‹šD¨ÞDù?/$ mê;ÎÄ?I5qfhX3wþªÙÚ:“Ë0¬žå}”õ/WùOâñj<*ãQ³ãås¢wX,IÚjk À?¯•~]š¯ç p¼8mPE±ÿ8ùG£Î"6ŽÊ¿žUÇÛ"¾`Ô¬3â›òßçøË¨Ý@ãvܪ3H!¯?&R|þmv—YG²œž çæ€r%uf—!²v·™"à‡<øY#ƒø2÷kc¿GS7eo(“~O{¤Iò²“6ä×<é®Õ[Úóÿ݉Xñò ûF+¥HC81˜ ýÕVÕÕòíéL{¹­ÙÝ8ÒùÌkõi/ž®íJ…oüzÐêÜÒëlª2±K×à…›ÊíùgÝU-ùþDGµœÿº=Ñ9íÅwÈT V]Q8"c±¢-gàíç“Þ¬—ð†fp k[‰³ÚšZ¢¶r¯?Ìl‡2ã³è HëSp2æ˜×~^ñŠèƒ"n­%Î*µ ÜÿˆX4³ šùaó0äÖU·l¼Q9r{wÏþ£Jr¬¯Ù¥é?ÃE³ã¹î†*“£»—µŽµ–iVG~Át=Rϧ_ºóŽ_|¶Oð]á Å%²þˆ¯qÛ#ã›™HûÂ>ZôÀ¼ ²à`œiSgÇ%þtµ‹°æôzùœiÂ}N·­zª“ܼI>§˜&tîsŠnÛÂT3|ùYò²»ú™óÈŒâÝ?9ÐùƒòÕŸT¸ë¡+* ÿ½¿8Ô®Z¬ëà³û†ïÝÖtáíÚÉÏCÛÀû3û«ÄÖfIÀYõ) az×?à|ÇYãDì,=ÏK<ùKu–±RŠºþ¡ ‰³Šq‚£.!åǘÏ0Q GϽ û@XŽ΄còñm ggAûQü›@ÝRmFí#¸-§™Íÿ‚\’è˜ü7Á‰zvñâг0¶õL'žY<çÆ³ Ÿ‘ÆÊÍ3Ä’œ¡>üžS^5øXÓV+‡k¶k‚¶QG ðp Ç9Ãï)è€&xĔҴµsD©Ù^°TW6Mž—ذ^D3ª°( -òm£§Ìµ×ŒÞ½©®q˧‡ª7ÅþR°!¾ÁÄàÊU£ñÛ_ºwÙŠû_ºméõ«­ò^É-°Þ2oËÕ_±ù‘mõvîæƒ&e¼þü«—±¸$nàÞn½ýßî_aóû%¿f[ ô£@3¬E¶ óðArG„ƒ?W„9*&#ÐAè/ !¨d–R-|´b’¨~äÒ°ñqªóä¯Y°nÀÊä}¨Ê„µÞ ì XYü÷Œ5€‚©£ˆÆ ù¦B›ü[‘ç[ð/ÚZñ~ÐCÑtè™A˜D}¶…@}h½¿p/zxà^Šw@þV[4üÕs\iî."Š~cœ&¢báÏ€ë/ÁÖ«×§ªªìKÒÏ­ ä+fÇ Ä–œ³—O†8Ñ3)‘Vk“»©ÓI¿Kwº¤ªEÚ?«ªƒ †ã Œ}†•ÂNOÄaÔå÷]‚õÚlÈ®¤I°>ÿM|7ÍҤ̀QHÂiqî¯ì%äëñŸ­$ÜJs&‘Ëß׳&£AóŽÄo 2V§¢ A~1ÆI0xL‡)ä7DÖ0NRpë…RÝê­9¾"kÀ;ñÁœ÷[#ó÷ óЮûä/ ·uáFt«vÐM/¶»͉UÚªbò ~1§“†ªªPþ%b¡ú‰*;Gz£Þ«ÍÅ*qÊ’i…SÓ€ù"ªIåÌ‹w/TÞ×Ý úŸÔÝí6Ý$#΀…!ò÷Pár›Ç¢'óŒ%àtú-LTVü•AYÇ)<Å;ƒqÏVgdž»/äy’ÖÓäÞ Ÿ.n}1€÷¹:â§¾ xù°H36€F~ÐJÀCÕÌà?Tô4Lrè¯Ém¥TÔÆ|Ž+ý~ iZÕš¸U ]Ô[$”«Éyc’ï„\7ø£BþLù b8#zì²öv¯è¶Šl>±$Iàmñ8d¯Hw„þ Áõ?6êëï Í=SÚWÖ, ùÈÐW‡ËW¯-ÇßCu9æØ¶õâÛT'ˆ°Þ ûý,f%šÁpõwXÅ61o ÏàæÃºí ¤*]›§óVXº6QtÛ?z麳ýöÝzëñÛZ:öÿèÖ›¦÷æŽûnY³fO8Ð>o¾;ÿÇË;?ù³Cû~yÿòÎC/Ü·æA¥%·ãÁ¡+¹¶¹cçÃP‹] ì:x¹ª‚éÀ{ˆàæ[€ÉÄØ{:_ö¾m‚¿ª´ì\ˆÃº] #+{_A»ü«B3,•2¥õQòêº-÷M>Tp ±4†;MWæBG;ÚlIûç¾Ü¼¬ÖIüiäÎ+“ùJMB3|zùd_ïfQ§Ë_ëoìWm±ŽzØ¢ Ë`QtÖÄ(üeÌ]P èùÛ¾µ~P<°ÉI52«QY­ Oýì dûVîzTûÊÙ“j@=ÔYµñG—®)R"à#¬/2Ú³´‰÷lYŠï¼õøž¢í,e ¡ú[ÚM¦üÿ.Zqø¼m ´Îæ³U·fÃŽHç§~~hßÏ%?ùâÁ¥·]³6RÝn£Ëˆþ5] ¬ú¹•ë>¯´tì|P³êãÀªi Q&Tßh lSµBB¬ƒ?vmFrËìIˆo47;2ïÃ1§z¥Bns:³›Ì¿£ð`I4‹o(`Ï@æ}EÛ÷òåñØeÊãÅ<Ç )ÉuÈÇY[™Ç´ÈQs¤¦½n[@ˆ¹6Þue·~ Ö]U®00±ÕôçþlÛò”Sb€3"õ&îoIW~E‘?z£ÝÛÚa$pÁš\ùÿu9‰×Â- gþ{Î$ü}òeß&.~ôcU\:Ët´.ZgòÂßöÁLÀUsúLÛ9ïR]b+pßâ±€T#ðëF4€QÚ AkÑHIDgбF%“h;§ Ã%xüQEÒÁƒ Ãû¤Zp>Y2ÊéZk&.4oýìHzÃ@½Àè¨R®ª{SKÕ@£?ѽv|mOEݺ½½ÃKkMè{=£·§c¹J¹²gíúµ=•x¬ïÆ•·Gà›`õZõÞ°×oŽÆ[“eé®Mí¹í}qÁî4s¢,H sry]¶²´7ÑV+Ou®‡~ÞøÕøÀšÏÀ(@§£v3%€{Ô=a¸J+Ÿ|÷yX)¦Üð‹)}3_)¦?¼PÜf6åOë-A§Ëoeó§ IqÚšü]YðÂE«ïcEg¸E†Q×J}éó(ðh95§ ðÆvÂ:mˆN “îyWœ-¸âiø,ØÎ{áZ°%ßn½îË›7<¾£ ÐWv%6ܵ!“Yßd¥€ìõK þØŸß¾$=ùðíÄ΂„˜{|ÓdgäèkˆEÁ‡cA€ì+àÞCX?ÊÆ1 Î_§CŽ€ÁaIFÎÀ9¼“v¦5a] U]Ô’ ª·/~¿¨èz™R#*)]GQ¨Bæ©üiÊ øÃV†ÄSPzkÈë )Ƨ.Ã5ñäóv·-Ó½ðUrÁ¨\q¬ñâ4î½Ûƒj…ú¤ÇZjjøÔ þNÎÐÂ;dcY8̇f{N”ùÆÉŠÉš0,“Χ°JZè‘3 +H² ¶-‹&Žw¹ò*y™òª”–´òªÖ‚½§Þ Œ®r_(!säëä)Š—Ëý„ @ñÜ ø‚Cþñ’µ½ž…!Ïâ Y ¢b"h '>˜ÓñæE.¤¸ p«s7È~ŠŒøïóAA€š•Px‰§IÖÌçƒf2wY@žï÷Ív‡["~„kÆl5ÆÍ6›Sš« Aeµîâ,™%†4Åûh|ÌþŽdÉéu<ÖÁù·:8õV'À9£ºü9‹™1œÇà Ö¤Í27i«nš´zSaž©i†`sVÑñaÈé1›¡¡>Hé€ÌÑ‹ö¹»… hÖ ¢P áÈW=Í#?î>®…æôŠz¨ h=¨[€¶#Sqc¶KC¯ê½ ™#ÚíHFþ*½åþñIJîîkqÛ¬ ò]¼[ØòþÞÞòÍ÷Œ•ÏV7š ´åºb{—¶­itâoÞtâ`·mŠ_Ǫu@V·¤ÔÍý)¾$,,?ðƒ›ºîœhµTt¤òŽŒµl¹ ª‹µãùVýiZå N½®M™‚“B—YÒþöÂ¥ìßR—¸\Θ4á&ç›þœÁØëÌàÄ”ÔGþ¹Îàë½°èNÖBõ™˜EoÅÈ'µ¥?9Þï|SQO Á3W¤¾ZòÏ <É4<‰žåˆ¢Te(ªÅ_þ¡Zô‚R|€Ð1Ζþ5ÉMLÖ·ïzôŠÄPg½¬§ ‹ÑkYÝ´ûö`n¼%3šMðpÞ¢ÑYæµän;zÓ]ÏÞÚ,¸B²I’-1°CİIŒ °c[ åØN;x-7œ †€´¯”ð/Ÿät×,sÍ®ïÉÆWĉšæ\3oŽ77TŸ ŽôGO/t(Í-åAVËýOkχï¦^J(Q†Î¼Þ5«¬ï1Çýqkš/ÐÙGªÏ(àüËàŽ)ÚPr¼Yµfp¹Šêÿ‡é/m¦§kÐíË&:p‘ýCÉyûßtÇǰ?¾š±8C²<“9ÿ4¾ƒ7 …i$cÔãËs`Éêäÿ .¼Šßl0êI’áô¼,äŸÎ—‰6•ºgu;°}ê“”SØîí+HHŒÞÆð¹¥s9.Ýš^^»­ÑµÐ™Úwg‡W 5¹ bxbxbÃØ›}{{7À‘«¿~0-ÏšZ{W¡¦«—βݨ(‘*¥*©<¦…Ó)á…S§…“"âƒË<ì&° aïØ› ¸ÂõèF\£UžUÀUªàe@Ì«d—Î*àR¨¾˜‘ZÈè#ŠfN³)¬¥ØKh@i…_MïµÇGæÑh·V_yçÈÈ'†o@í! o4v;"«ci’1yb)wÏ–œo·ÙBéÌngUG¼¼£Úé«Ñë o,[RtG_yVØä”»3ѱc¸ºzôŽÕëÑ%Eyß® zƒ^g’-¾ÑÈ1eý7lÆ?D$—ÈôµŒ5º=©îŠ%C)“ÅYJ5DXKƒ  ÎjÒ ?®»‹bìGH“ú³Í8çÎ@%š+Á2p•bj˜ ”4B0,©Fꤠ“Z€Njê4©è$”= ™éæ217eª€‚Eî²–:jD~d‰žì¢'êTÕ“3”á‘SŠÜg‚ÇN)è`XA¢gAM¿TY‚‘>_d(údÙFòqFôXá“Ç=^¹åÞ±òÔæ6¬8c¬~¨|ôO.ýDgè {Úƒ­¹î˜³ svŽ8¼ùÆ{º–\aÍ÷\P8›÷æ:gi-@w û(Pü ¬{ ¡[‘lÈ6ìh %¨¥|ìL VÂ5 •]õqZ¤ýÒ87Ý™øz‚€~NC YGi‰Òtú›CŸªø§ ÞÁ`å‹û©û)â9 ™Â)Ê“|%Ú'¿µÑ´ÓD˜ôoyµÜüs}ªÔ|5¡ "ôL-2@ˆª|Q¹#š|èN“ü–‚™a&Mý[ŠGUBè‰xÜxqþøCGø;Ö€lÁÆœsG|Ý;‡rË’<ÃÑ$|WÃè®ÜŽo^ßÔ²ë‰-W?¼±êIrÏîÖum!‚ bÁþ[F«m.crZŒ’™çœ²ÔvëÌ­7þðŽ®Î¾¸Fºó¡êÉF Ë.~@ѰûªÙ(0‘°tk:Þ]ÐïnMà»5âºá_×T”Í\|9gOR•fz\ÑÙšÞÀ€Ð‹` êŸÄÉô»ª†LÃ9±Á0«€=k¢³Š¶/ e©ì%³Ï¥.ª8!5ï—Ô¹gâÜ cóÅÝeuÓK,§×YÌ/Á˜ ÓíjBz{¸÷Ú¾pG̒äÓsz9=Ô´Yõþ\0¤Muãë?97šyÉ ½@Ð M©Iìu]èTE…-’„ª1cX·þ1C6[f+Œ ÖÙ–1ìÚ¹ŽÒ]³릾Ñnßl_OuÓlgoÝ@¤W¸±4©A@r›“i¤Ó§Sêdœ¾?®žm:KçëóÍ*àŒM³J᜺f;Ò–ôÐôÇCÚ¡é€I’è&à `’ÔUÎZ ãJOëÓ5µŽ¶•ÕâÕPðÃņ©;4îZ’Ž;L$Έü.Þ×»,¶ùî±òïÚaRÕÚÞ[º·³mÍ’Ë%UÔó$ Œç¬nüPkn?´:N1 c` ¼á_e`ÈÞìMº=˜{{Ùû¡‡v<í<½wƾ+¶ÀÖiG6ÁAq ï ôí¯½Ø áÉùëíßûDïã³÷vïܲwöPïÍÛ®èíÈr†Uc‚fjÔã5 å™uö "hž^eDJYNkŠ „ zW—¨h ;OôÞûø¬¯thגּøZM&škàårœ/è™UÀ%K´ø Ò%¥ÎZã‹ ‹ °(M¶}lN?”^êEyac~Z0}t)ʧ]ç UÜ€*v…&–SÊS@úFÜëê‰1LÐ÷ €{vÀ=ËÓÀ)P¢ùé÷òÊbFz¯é©ì°€0Y[ ÜÕׂŸZÄ "´iü®Q•GúKx´¹ÈL½ZÂÓS/¨Ì¬jÜr)3/eéjxv³žNG x‡ÚºsLóÓÔs€ÿÉÚ—@¹q– Ö_¥Ò-Ué*Ý÷ݺZ}_n©Ým©ú¶ÛvÜNÜ>;§lwÇÎAl9 Nì„X&»,°ïÁÄ6탆ì[ÃNœL„k’7³ÈÓBfŽ(ûÿUI¥v·ã$cµ[-©ê/Õ÷}ÿw{Ä ëåj5²9†øoÞÈ!ò n‰X#V¢¿3¯­][ÝÌÏÖJ•(W¨õóé)ß”3c‰¤G¾Øy‘T'ŠKtä»V[й¥Ùš€Îî/Ô„Æù®&}”dù%#ê=a9Ü|[õ |~ݳ"«xö¢ëD¾›uèPÂ-òiß5à÷4ß“p VC p€ø,ÆAgg/JùÓòµÀ(bgäzáÓ¹éêè>r­ªËŽ›&vU’µÍÕÞÑÚ4¿n*Ç»%Û°Éó‘Yx©S …"”ˆÞËp‰›ð-²9Yà2Д ¹JJ6ßbû­bý¿kv/9Ôj v ×°ý1RÞ-—¯~rrûÑ©°û ÿ»eí¢3A›¶ ÷ÎIÑë³üÀ7œØ‹¸÷âæÍÃÓÛ¿áä ]˜‹‡o€Å òUúƒwY<ÁªöáÊÞm‹µ;ùýS SÓ¼ÓÓ?Ÿj‡¨9ï™°Tª5ZfÞ( °뾜qNðþTM@‹ß¹XZ—÷ õ!·FW «5npké" ^½’5¿½è?G‡Éú*,¹úɉíÇ&ÃZ«è uåÇÛ‡ŽA‚@e¹X%Èõ¾'¶|BåZ _… òc½î½òc¤ü™:iÊFló3Oo ž&z"ùÀÖM!DMŽžöì&~º6T ek= ÝÃ'¦Üxó?‰­É4òrÇ/^{þåçEp›ø¡éšïÉÖ¦,ŸvùóžKã+²v¨«@\‹¿Õr8©s:.ð'z½3é$9õ X¨¾ŒËƼzµŠ„¨°xâ¾ ¤ÆãV}Ï—@+$|¾¸[§sÇÿR¼ ýAÄjíÈa¹7º®ÿž¡éÑ#µª;øùÚx%ê¯òS2°r2ÖK2Èe/Üsx_Š,·…K•áZ7© hµñùš€Öí¯ [$!<Ñséªqrô¨V‘‰—ãŒ~MçTẩq†wUýæ·ÛCAy ¥ÝXTV JsQˆRšÔ›4Vw»a¢ÔsÕ(]k»˜.¢«`óeúe(O‰uóËcc…aþÀŸˆ-„ƒLj"9sáæ‚æ)œ³àcKô9Wö¹wÎoé«í­ò[j;ù™©a¾mJ3¦ŒãDEŽV7ŒÏÆ,øµŽ—ÏÞ¾š—Ù¹¥&\¾«¹’l™®ÖæÁ±Š«õ]ÈYjBòº"nW„C>ЯƒE£^kÞVF]ÿˆŒVR«1´w·so/m»“’´¥—лýá*¾OݪNÖw.v%Iëƒ{øâE1*ýR8ûÉ]»oBò–Ïd¸8¶˜…Á‡Ÿ†8¾0 ©Ë}€„^Ð'æ¦øû ôÇÆïªk·ToæßW›¯ øÚ¿~ª{*Î[*Tck—J’Õ”¸Õ­2WLBNJK߬ hñù÷Õ´ü_Z. ªV^º‚ký]‹ÓÕ·½B”¯ 6­Ok‹xšä€w>$cA$‡«–§ÁVq*Êðî$ÇP² [;’¢Co6CRýnÕgê ïaçb=ÙýÕa‰Ûþ Ü›·‹½#ÊºÍ›Û Á ÃíìîBaè¶anßՎ鯔‡n€¼±º‹¿®6UiÕ*|Ï”¢ÍÍ׫hÀ@àZ$‰º¥r#0Ze꺚€Ö© ÕÅJ®Ö]öNþî÷ý/òæ¡ÄÍãx›",¥P€Ýÿ‰»c‡ƒhÕüNõì|ëŸå d²÷E£D×¾}ÆÊ|'8-ÇgPpȱkºÌwò\®æ«NÆÇ«qp!b«T¥%ÄãE„F«\uz^À#4VðåjZƒ3Ö¼ŠKB ¸L¦5jÔ(¼2rÞ6ö_æÐ­˜ˆWF E©µ´ÖŽü¿!<¢Ejhxü þ[™_÷ð\ÜçÐÀƒT:6.pÕ½e?•_Ãå+‚_é!~AîKó‚eÒ/ÈQ&„5ëÔñÉÃ3¤YÄŠú×p—}ŠøæOÃÞä'?›Ü±Ã$˜‘6ë™õ|à^´ÅÚLLøH~ˆ(f’àþðáâµ­Õž¯õVîõš“µ"ž²OÝpZ#'Àt4ÕÙ’he*"ˆ—›™1iå­7Ö´v/txõb²&ˆëkÐΚF–LGS½•k‹TïP›] Çï õê_ëØ DVeo9p%íùõ“c¸)[ÂàD¬ŠþQ¢Zc÷ã } ‚,´ŠMÒVöW˜>ì>Ԫ딽ò^[•X¶í\¸[Úl–Þ†'à·oX›†P¥pwýaêAê‰ab†Ø8Ì¡Ö\Å«Z#übm`ªÚYºðÖ(S’¢‰ðù¥s裒fþY61V05ëU1íT§Fƒb_,ŽØDýF@Ë÷­Qè›]÷¢/!•#–Ĥ8ö;$YãN$ÕÐ<âœRWÙöêEñíž^9ÊÍ9¡ÙºD9TüœH&Í”ôŠzÐÆÜõu,|x¦÷¯Õ9Òóêèâ\¾ëæ/.xìú,.†Š…Žx0Öµãî©t5X‹¥^ß·Ð^-8÷]Wä ÎÍ»6ý&”véî»mrß°—: ƶfîØœõsÖ| š'õdxÝöÁáÅ­Åxy{Wx¸¯ÓížÊ®Ûˆ/¬Ÿ¾sKN§ ×_Ûñ¾PßxjûÁ^þÍ%RëÎ¥SŽ‘Qû0ŽACúø,õOÄ:¨ùÜ#uˆ›f3QAMSÊOÌõw o ¨¢#hº_nb>N¹^¥E´‰ÑKg'(¼|óœi`Rœ™C§. ¹‰(:¹¬¢S´ëU–"Æ à M9ÝZVÐÝRJ:[üòØr¯ð„P¼as]K‘*5r ¿¬¼g}(=Q­&åpsºº¡š–£I—œãÛ5X&†µ‘Ïßæ¶yÖí›Ú—î1Ó÷>yýá§î­Zâƒé:1¹_W‡ KîÙ;dM‘,} j•G/b§±åRhk¶6•ÂŸŠž§RT(o±½$n4‰{LâÀ´}¦;KÚ°+ø|n"Vi8á©U¢˜ÄØ/¶tç°ÏW'4•QëÛ¸vW:ÿ¨¿kñ¾e¢M#g-V?5~í•]¯ÊTEÙ›JyëÏ`] D˜ø’Ø52:=¥8)Û¶¥Ç ?¿´¢ŽØûæir‰ðšé,‡ô©C»‚òœ>ˆºj£¢ËnvÃð…ZFŠÉKùb‹a7:è¬ A÷Lûj¥±6¤"NY^ p ƒþ7 Cݧa¡ímé~ø_¤h }CQ¡ ÞXÖK_P®Ð•¾È꺗]ZqEH¬ÉV¦ÐcB»ˆ¯aÙ`,õ€tËV0]¼ðÖ÷1¨ŠRêC¥|ñ3N}(>M&‰a” ºvÿTH´.—#°Eâå":5î«4Lnlf_„äZ`qL¿ã%ö¨ ‹òh—tøUøJm35MÜûVBlÑJ9b:Ê;hZÝ(m’îꆤŒ;Q±©Ñûôî}ºzó™¡Vp\‘qÜìuZywˆn~Wñ[Ñ߇|~#`<{­¨Ã)îËÀýƒ’¸yÐâ¨\ÞƒY챦èÕüÛŸ 8Ô1Ð!öóÄ=qSOÌ®}~#ê\µqøòVØâ²—µÌ~¼& Ôg&'b8#mdb¸’ëÏM¹Ô¢l¨Ø/uŃš©Ô¥q=<×Ñ{z1¾earb¯fZ—“ÉIª\½+\‹7:¤Š ‰àèï‹,Ò¦µgÇòý‡q4 Ù„\v4ߤÁ1Qé.çg5SŸïÛ>ÖÎæ6MVcÛn6yg´ï¼üæ~¾}묧0’*ŽµÙ S’åÄzqc±Ž~I¢h%f×èÂì–•%n‚¬è Þ8/ %,eô¹‰6wl\FÒêRIî÷(aÈ{ZLAqŽè"}[|´‚mÑÔô£Óo#šZ€ ¸I&”3ÿKET!ý,†£¯”)+H[P÷±„$´ ¡m¸qÕ*]B_ZµK(R®=Ð+Ú†ZÛ>EêQWÂó 1½ÑéFÓ”™‰è@J>(^k¡ÑTtAþ'–hƒe™@%Úd#ƒçjJ´©_þê-‡þûÁžþÃ_9 Ÿ{ÿÞ;¼ªRaoiÿ,¿,þÏÁ¯trý]Ë·Àç ø|lüžëû»vÝ3=qÏžþ®÷ è=V?AýBUuœ–«:Â=«ôRù`³©2RƒbA.íÀÝÅÚŽU+:ÆÙÙ5+:®\ÐÏ|»‚ŽUÈn킎‡v¦ÆFÊ1ýÙ^«&=5½)‡rþÞщ :*ɱ;G‡·÷zÀonûƽU6Ò­Ë\[õYµü@ÛpÚ1uß“·n¸{ï ê–õÏlžÚ{ ëï'°þŽ {^äì¼ACmÓŒÞ(Ã`vœAù£mD§HˆŠÉ ¿•&ƒÈCäÉ ú²Þ7¬ËUlÁÇ3чòGÙi¤ø¯ž?*§Êçyò8OÈ3ÁöáôQ|nKúh³Lõêu|ÚéA»¦‘ÎÕqÃñ]©Ê†jšec_M¥¯/Ë—ÒýQFÎ#mÕâÿ]L$ÓsZ<ù%\;&æÈ,vƒ#‘m³¿D¾ŒD× "_«¢u#¢c©:^Öe&Œ#4î˜"$Q†UŸLS_?Áê…æ‘.IJ­Èd\bÂT“_"Õ:­Öé9ÜíÝÑ•Ü0>2Ðï7…c~£ŠÔõ\À¢Óé´öüTï›§.ç‡÷öŒ%J«×ę̈wȦ·jäs&ã€õÆÂdirvòC“ONÒŠæ¬ÿ!5eÅ„6‚Jl+š¶âf­àçå Ø¡÷fEd+5hEé ˆ3zŸÿ›„ë‘ i,¤Vu ¸^Éø¤‘4æÑ«ղѲ۲h¡ÄF¬?CÝR'¸WD†ÐhÁ*5`]@m/ XÚ~9Þ›ÿ…`Ñ¿*Ö²PfJjÂú3Üu‚æ^‘YE£ý*ÊÃ}7XÉç:wÞ3Ó¾mC;§W¡«™Ò5}mcÞdyãÖMådzîè\ŒH;4Ô6õj]¤g¼ÐVN;Rå¹­›ËI`Þ @*qºí± ÍÃj¼!¯5ÚOt¥‚‘Ìð5CÝ{ƳF«ƒ52‹ºXqnÎm÷%»S¡HÛÐBÄ&}€>DÊk·Vúvì¯L¾:·qn÷Ü╟ËÏmë|6±bÛ+•é057ÿ ò5êD©¥,U`‘ç;ûŸ¿h==V1‘ý%jÕ!wåo ÖñBs“3sì\hb_kç³¼ZeÛ+¼ž›© n^÷ ö>ê$™×Z³±ˆ:Ÿ²€lÕÊr%¾Wᢾe ÷#}€TiŒÁöŽ2VÔAöNw~}:5Úî‰úµj|éžP"ùÊ$’Ûxó°;cåœí;îÝ2wlKÛ¯P?ZÙA-9 -œÅ``d¤²r¡XI—'|¡À*Ô1peÚس!¡V»øÄúC›ZÊ%šNHÔàwäÕW‰âAÌ?Ó„%š“xBNâ9‰Wä$!”“øjœ¦\-ÊûM5'_lº¬k—ã씪.]Äe„péšu–¦šàä5E¥ :ãa/•Z:ø]æb^kä-J畽eÿ]"Î>(›\¿F7íÞª3æ³kiÝêîa}G-†‘ê/ôÄ^âÖ‘æFF:öv¢›wÏøDG>Ló3{ù;Õ‰™Ú<ß‹¢'z~:;å㹚º*)=ÈÜë2%ïý%)»íi‰ù™š0Ï‹«˜q5WÔUYBîz´âi­ŽvI¯;»rÉ dj ÊŒ¢¼yfÉ´c/ú³blåŸdqUÏ(Àº6¨óÍ´zì6·ÖHÂWY–5‘„ú—A¬P¿£ d|™  'ÿ \ˆßÿ9¤è1Z|¦0Â"ë=dÄ%Twf„g3µÁnÞŽ¦ø´N,¸¹y(à4!ä&Å1ÁC»35a°ÜÍÇíXIÂÇc% ggáå4…«‡ò—œ\HW/\%$½ž¿>úÎá%QñT?¢ã‹\Ì.g23ó8§Ê´Þ䃢;³…˜áGøÁÁßΓü¼9Sëæ­h£Æ§w(68¢å‹ b8ê" 6êÙ$йÅežåIÅwÏ› !­5;Z¶?"iU̬â.«™Y ¢Íæ|–Õø„êZ‹ ,ê# €“”† ¤V9ø–{ÂUmVó¯{ªÈâuþ0kÖKPW Ãb·˜L¦µÐ€Ü?·þÖêüF³ò›¿%žÃ˜ºþÈ(ÂÔλ“Èù¿þÖõ¬¡,‘¸'±i}w‚ãÝë7ÑÄM;jv«hZãÀqÀ Ó¨²†ÅÈbVM%œ\…:´lømi<"’ñ‘ˆéí+ÖØ´W¹—•ăÙ*;JQ½sÄe‘#Ò¤ÌÕ#pçïýÈg‚ó˜îïØoÞ¿°°ßLygPÈú"òsž‰{7#¹ãÜ;ÍO óE>“ õµ÷‘}³„·çUˆ8$UQb%QÖ#ΉižX¶/šk}ld}ñY"î­ qÞ¡Â\À!k‚MÐÈ*xçØ¿ † ö)Ql ®Áq›(&GýNœA‚:~dÓd*T~,+!qmŽ®L3€x‚örMCÐA%;Œj`Ñ+„¯0Z߈ƞ¥ÆÃϸaªÙù=ƒæì.`ÏbFüÁòEì ¹ïY" X_È/ÔXCìa”ÛMbΚƸ-…§GîÖ ©£€¤Èú%Ü×*r›UõçT4šûäôGm:U]Eý…ÔÛÂ^gÀ¢¡>¯Òéš¿þÔÇJ¥5ë©mF«Ž‚tOÂ_º7=F#ù+Ô›‰Ô^ºßú3}ÄËPñR}ë™ò:„>” ‘î½è9ž‰0H„@"ðƒ¤¤T MA08s`( ØL³R=—õüÙ\e¤·Ñ3n§Ï ·™‘q|{‰e±bUlÙÊñlçx||àSYEŸe‘gƒµqüû²·gÉ ð]çÖ„`¾p±Tºa.b¦9¶B\!þÃ()ûGÆ6È¢K©ŒâuÊøB³€Â±Â‹$²=Y’„¤ª/1ö#TÔŸÙ…®õÏ ¢—NÝ@ÜsKlP¶ Ò÷©èúë”É™ ÛÜFê›$ù$eò¤Á$|UÿämP?õE âù"IþoRg…{.hÕ’?&Á ¤Îö¸üÓ;ÓÄ3ù îÍÃM¬3vΑ®1A¤ëté(9Í·sɯH­R@îÌIHâ "!,¨Zq¶<âiƒyà‚{áêåN‰{qò[С҆bwèœ!ôEAB(<‚ðl0ÛÓãhpĸ¥çŒ3FÐÆ÷š ¨<¼¥Í™Ü¤“ZµÉ™¢ÅÙ¨Ö– ¢ƒê'?VŸ?n:િ®¶dȵëU—¾¯Ò[‚^ÜJêêÊšmFšBýÀöÕG­i£Í ΃/™m&¥Ökê§Á¬Í«3Ø™úNÄ×ê'¨cz1y„B¢ñ$/H{ ‡] aî1“Ið 7Ý€¸ûXÝ 8îÖÛÆõ“ªYbR ã¡ $‘ ¶‚Ú)’‚saJ„D¯ ILt5ZÚ°Û…³kÈÎ;ÔÅOÈBªéXªþ-- "v õ†Ú ùbuý,k¡v3èWYõÔ‡ËLSZÆôfž|Áf ‘LDœb;A?¦Î±ë× Þ)‡&È$ðÔ¯<¦K7¦#uqË@~ÍÍ3I–™l4D[¸´€¦>zÏÄÝè³<†NŠa˜ÉwØ -@’?VkÍÚ7_pxŃOÔ?ÄÚT:“ŽT,F z¯~+ø¢ÚÔÍŽ˜9ÎÍ’ûÃqÔ\Rmæ,!³Ëéaß|DÃz ’#¿M–i/‘#ˆ¿Á:›Æ1p\³L LÏ `{ÙÏÄO†B^ÇñP´çËy2Ÿ×{O¦–zÖ¡Kþ<²Ô‚ûê*Sâ¡øIžœwˆ<›ÿ}ž2Rðü”÷¤ZÒ÷>,à5¤8€Ô©¬Ù?²f—²¦sMÙ¤Œ,{aO|a ;ÙLM £[LÁÎD|(К¬æÁ½ëÆú=K &¬Ùl)Fþ«Ñh0µÇÓ\¶Ô–ßã¢Þ6ŸÉê°D}6{Àåï™.|ØÈ…¸d2–„° ¬>§¶ ¢—Øa¥¶? ¶¡ øXÙBØ‚zsöTdÉ}À|¸ó4}D@õ÷Kí†1PÐQ‘ì)A<Žî<-À#åpSÿŠRú•º‹Hï) êƒMäçP/_G>çòFXÎL«YÝîaéŽíåkû<k vÄâ•BªšŽvYêõÊÒÆŒž‹º†Œ&”EùhÔiþª?›‹6î‹u‡Ò=ßÌç‚]£¨ ¼sí&Ú‰9i¾Fü¼cFïxÔù4³D=–M}VsD9ßÓ(s~Ç£‚Ÿ‰|Z`–²ÔcBV“ú¬ 9Ò2FOi`TáW‹hÅwLºH•&ríàG?–™¼iØžI%œ5…Ø“FŸ*…«S“™‘„A£v—ÉjÒ»Â|böðdLm°Xôf«Ù`·êUaçî=»¯óGuTÆÃ»ºSm|¬[ìsxFçî~ÌCS&,³–à·ŽJâ–:7*h½_ì¸*cÄ¥N Ü’±ãqÁ¨$h)°¥¾ú¶(ˆït‡-£.ìZ]¿'4²«TœKiŒQõ©j*­Kc #Ï“ÿ&bp¤P,̾¨rx6“H€<­UQP&ÒõÍù|¨k4«t‡3Ý([…÷|î÷8‘'ŽáÌî<´Šî_öZ,Þİ­ì$¼¶f³.<„šŽ¸Ò…–t']GäÙKRûlÙw…`4ÛNðUnsðRð¼Pú!!´äÒ\GZæ+'\4:”pŽ"hö'!zlõãÖôúb¢ÔÖëµæH¦Ø:y29qóXB÷«6ŒE»b6RExÜÉumœ1Ú<>·Ù¨£:YYšiKUvöX*“ÎTWñôù]ð”ÚGô×`?´ÕJ˜¹ `¾liKD´´Œ<Ê=ÚvÈwØ|û/jbâúkÅ„g{»ö¡ý`[äQ¡ƒÿÅ#±#BRoøF¹Õê8zš¹Ìà)R¥¦Ô'²ön5šM†ÛÕf¯Ý‘=c€üiÆYœèp:š¤ÿÙlÕ“&£·Íßçòù]õD½ áüO—ßçêéëöhuZ“ ˆ6ð:¹îÙ!bЏNœwý-b#R„ÌA‘¶l>_ÌÀGÜ»îØ|FCL#fæ%¶€kÊ©¸êDÿ¡Ô¦eÇFéà3y ÕB£ªCåã=K¡m`Ûñr„Ps?­ÝF”2 µ%‘F q^{a¡Ö/µ§{þç¨ ™Ø–ìeÜÝ´\ìWà›N„ƒ…—0ùã¾ÊKø*=åãº$©0QŠ ¹°!!u»—ʰßYÈô7ú\9‡·ç²^ø_sy ¯Z-½"÷™t“Vsxøšî`ŸUoJ„ÎOuù¢ã‡&ùGÙ¤/õpîÈð¶N_ÁqÎ`øæ@¯7í5 tù2^S¾»pÔ59–ˆ2ªŸ¹9[Æ•ç;<&£ÞÉZ]¤št$ú"©Ñ.?—è¥F¦‚':èäú3¾Ó«¦]Ÿoïµø“öö.Ö«ïH•7ÉECŒ+„§¸ß%ï‚Iâ˧SV„Aa€äÌ>KÊi>YŠp¦ˉ¡ýÊÖ÷ðˆŒù´Ð8FÎío È#è\)”¼ *v8½}Q>M‹ÒG-K¡üµí›:8òßÔÚÇW ¹úIùµRþ´¥bÛû!§Ú÷)Iÿg‚–EêåÀOáÍðQ!´gÙÍ.âûúesJÐôœÜeü¼Ïsˆ.l—}÷^EŠæ¿ÓŒÇ!c‡‡¡M‘ö|8’o7¿3éRkÕ$ o ÒmÁ€ÿ=þ]Ävô G D|Í._‘#¢à,Ô«ôàš`‚r},2&$Dˆ3LpcåŠìƆ2@­‚€Þfv£ÆÆqäÕÇq>‹ŽþáJ,,«ôVN@Ñ™¿ð]ƒVŽ\ýŸWAEäEµ^M¡;ÖÚ­§ê¯Zñމ?À;Vä¤n[Ö³ð]É9©Ä;XîXù½šß£ym‰¶©ßBIU!bÚî‰Bñt&?dAÚGT ¬²ëͧG–B§û—†zÒ‹éÃNt¥ÌÀÂËýðØ9)}d©?tZh=aEîßè~åkDÁ­‡|"={ ?»8INÝ:3qp<þ &¾.ß¶.eGÏ3[©×GçrÉ©ÕÑC›²éÉã©jwÀ×UͶUºü;Ñ·Àäçà·EvÁõ¢ß»]ÀïÀvp £@ß^ªhï"{kÃ4@™O5¥iÀ‰vAóP¥u€ŽVÞÑÊd´..·J;×y²m)§L€´™c#žÎ=CMë€Ï¥*©X'²ªK³Ío¯¿I£j¨yÔÐö„(*¶foÆÖA¦ë›¹<²  ïÿNéþ±|Æoèõèx l³z“~•9ºØvʵÔõ¸ù}«¨J—pj^C•æäã\m§×’¹ëq+jÓ¥ÖT<¹|sEšçЬT§EF·à|wy{Ÿ'<²{ØËæ}j†³„Ý¢B6 ¥ˆjF¾g …¦¤Sc[IÁWZ5j¼óÀ°]Á_#‚AŠ´Ñ£¿˜\Š0ŽÀ¢ãp3Ã뵋b?VSRQh~~y]âvGJ‚@sˆÖ‡…ú§ä,®¶DÔfs¨¿ÿÐâ2kh5mp¥üõ/·î·j0åÔª´j3ê俞ü6¨Á»(‰ú¾Nôƒ-gCÙPÖè¾¶–ý„±íøKÅßÉbÏCî~:¾¤?þŒåûÒÂ=DQÎYh(RŽÛŽ âÐÅxÏC>×¢?ŽSª ·´ÐÜC…‹- ñX‘…Õ3¨zº»/U-v"„H-VÚÞÌjŠÖ¨ôþTO<7Ü6<^J‡ú7u:“ ?¡Õ\¬ì€ÊúD©º=³>ç20ŒÑé0ÙŒ4ke"I_ØéL•»“CNg4éá'#mbMiO êââxâdÂëIú ¢C´"¾FDƒI„uÖÆ‚‡’º ÚeÓˆ<ê.b¾øÚ·„­bGð-ù¨à¶•m†GÛ!Mæ1É(Æ©)rl­´Zl d£÷À“j=3»·Ì ã´Z²?_>jó$Ô*5MR,ç2hÕª;AÙ ¤µ´J}[ÿ·ØÁ¨ VLÓß&ï¢íÐF'ê¢âvö#ib‰ê¨ô¢s1tªa7š‹Ã-¤Œ¡S s¸¡Î´Zʰ ו!ïrG­Nݾ¯spS‘SC ÓîfÕ½ýa>-‹š†ùÛE˜R‹›W]ÿÇêx!ù5¼§ ù=hÙ‰¤4•Ćªâ˶°6 5‹kËM(6yM‡‰EQDwÁãBvnc*IãsQ@JM; ò%ûÁ¡-ßê'ƒv/£¥TOQz{Äç‹:ôÔÓ4­c}vÎgUS‘Ô¤–õÒv¨gSݬEõÆZƒü?£Å¨…8Cw³ËfOh´j ÞG–üõ¿à}ŒwàÊ’P¸È ö¼™²!l·Úµšuëì%仳hì=‹…uvÊ›Zô–ïLÚÖP‚‡’ÈJäy·ÌÊó”ÓÛVÞtríûWüIÝIRC©¾@ima7ìБ¹ÒÙÑ+»žú¯*JcñØ>‹†üIÞ4¬Ûáp›ÕÔ‡Iò µˆ`20f˜öõÇ›@3³†ÐŒFð„HZu}Á ½B»7µ¥­x"ôaQ»ˆ€eÂEÄ ´Öå]ðA8 Æ ào–9CÁ ¿ÎCk*5¤£Ú¿hi(QŒßVIÃÊŽòx…;p’OJ“‚»zmÉ„6§¤Òk4äF°!+`Ó’w|ÒAÍÞbÕ_ýojÀ„^6ê9ߢCÇ,ên¡n“ÇÖa="—×+Žr5œõÒh¿Þ^ª«PÌc™¡2mN?TÓ?×sÀã‚v‹êùQRmñ»\Ð$c2¨´&ýi’cìF©1ê·’à=ÜRK`ÉõðGÚ ÷õFÉG~r.`‡"r¼X6è–Ç܇˜ègè[  zþ´Œ))›ÃnËc<‚Ž~F€Ç@6ü ü‘%PÃ'o‹6|òP#úǬ÷Ø4õ14õšÚ¿ÌÿŸµ/oâ:÷]ÒŒ¤Y´ÌhßlK–mÉ›¼Û’å ox¶Á `°YÈB @J–6¼¬½é’´II“´¡€ßðr“û{yI›†¼—þBÚÛ_ÒÜÜ,í˽´ÍkSËïœÉ–IÉ»ÿðlçŒÏœóïûËùŽŒp‡9žf?ù\ÞäKÍu*³I¢Y–cЫM®Ñb°“Ó¤Î1$‚Ÿ•×=2ˆ ¤÷ãÜ5Mip˜]ñ7çÕjZƒÇäl‰Ößœ_°‘+Ë Ñžô²Âäqâ|jaò|7áFÛÉËß}£üîMKÞ½é*ïnϯ¬æUVä%O“Ùåy¹åàÝ/#JÏý}‡Ü n.’-Ç,’Ù¶N&Jz&;CfÇäk¨Š¿ûF&€ÃsæWK.†èè @‹5™ì‚ŠGÕ&ŸÝæ3©õKÀåÊ•4)×å X4èõé8~üy­ %)À.ÿVéɳ1Œ-Ïã)°0Œ¥öìŹ‹èqbXna…2ÛÍØ&ʰÊ3 í@@c¹—ÓšÄx3fƒ;hYáýEJxéÕý ÌD³£Pž2dÙm^ƒJ£1g9ì9¢F#æØYf ¹Æqð ›Ór4I2¬ö ·Ã/1Œäw8š¶M“¿Aw#ÿŠØ‡,«ÑŽpoÁU8ÜÚz>å4R¥¶Ê-7Ì7e7Àtü]¤Î`1ð"‡)ËjÉ™û\¥¡Ëpú@·(jØosCMÜ Q|ò=ôëøC@ç +ýt"Ëxë¨Án9M»ò I ŸÍûé¸á¼ X£¶ÂûËh[üò ü:MwŽfÀ G“Ò‰üR'X¹Áµb–E ÆÝî|8¢ùno<ÌvÊŸðºšV2ƒãç?|ù¹K©oð#ÅÊ®nÆì–³´Ógé Y0“ÎGÏËDp˜á½+O'pû*­_4ÆW´{éõ•í x”€$­Z­µŒî# •;Àè2H®ÒFjfî¥3Z´ÌÈ60ïŸáPkbx‡Ü8eÛž…é¸#\W‚ÿ··„CMà?äƒ÷â×£o‘7š±É4C™[À»à{¨˜¹%ýtQ6ƒr…Uh‡Vʲ@QHGk°‚ÈDóí67дx·ÍY IoÈý®RrÄÁ_Üñ1ý‘.üůH£dŽ«$\ ½¡Òʾ{ j¸Ýê(JpÃȳ{ñ_€¯¼€Qø²\ÁõnùzY(à~#’ÛTŽødû>å5ƒv•œ‡c~šòÆà¥-±ž/^¾?€ì½J/aÇÑ'I^3è•û©ôÊ™i”LŠË<0îkÙ—j»ÕYÈö|ºû’¯òRq~#öæ¢o`übÉÂ70þ¼\ø†ù–¡Dº‹Ée;{6ñ¡$ØDü-ú,¢ÏÌ$Íx>ŠŸÀo"ý.ÐFé<ÜÚÔ <™(¬W{Fæþ 82ä‘ÊÃß_¯‡ÁH¡šü-N“ÿø²(ÏŽDäÐtx"ÉAœbªí©%ܪ:£Ãdñ…­'t§ÉâòS«&T:ƒŽºEÇj@'åX\s¥Ø)âÂWxÿK8Þ/¹yGÿà…ü-'ŸÛRPì’7 Ò¾¿ ÆBX-¡²£‡Š¹H òÞõPšÌÅ܃kÞ×¥Ì^Ù‰øäüC¿¯ÖiHôs¿Ó•“ã¤x+è§&¬¼÷<¦Â¯×Qû<ùÌIˆÉ—%,¢¢ÿSn(*Æ 4Gc"NLj.y֥ì2þª™@8þ‹Z^xüp|òmŸÛéóze/ÂáäSèŸÈ{ŸÂ3c&ÀàpÁ.‡9à&s‰ÂÐ]9ÌÈv^KQ9Ò–ÂLFAœßˆ/„ËsFéRôÃë‡ITï°Vƒ/ë­°»*{KP ™E;‡‘c?K®{û—ÉŸky†àžóWïîÚõοüb AQ8EËïfÐÂß‚z¿J”œZ?§aK¸‘ ÐA¬´Òâ¼âT“áT“áÄHÇÑ” ‘Rl}›ô·öŠž2\k° V‡%‡6lØ@`œ]4Ùy5¶åz̲ëÝ_½9Nª)ŒdxíkèS¿|}êgŽ­¥ˆóÉ.ÐÞ“/a6òFÄ¥à­Ó–Ÿ²ÖW!q„/Êh™µü4ÁÖW É ‘´Bì™X–ç¬ÕÏ!Z³À0‚Y‹"£&XýOÀcò z_¨<ðAq"ï¶_®¡XQÞ(ùz&£ÜO-ì«ÔB;,ÜOŠ}5AÍ·r ß|ÌëBô«œfà #ˆÚ9= ·1}â å8§æ²ÑÆ©l^d)òe»›9JÅÛ ° ‡æXôbPW¡âÅáÐÇ ±‚ßõbøI@\ ÿôí÷åzO€ke‚¦i˸,mýsG[G+¡sJ‚ÅÀàùñ³Š1 Bš€VAßx"ùÃã'’Ïþ€æij@«~tüÔÐúéŸ<»ŠüФaF­›Aëž—[W¬P– ½í¤‰EÎa" $¸`­´Ü<Ð8Ni¸!…ÿ!9qôy1?ž1@X:”hk]ÑAà¬CZ° ÆCúþЩã?¤Úø$Úâ8ºö ž&q4÷ÙŸLƒþdÎ~DÒ ¢ì¦Êíõ3jó9Æò‚BS ïÃ͘Ï%ÂòBa‘ÊÆãóیˢ Ò•ýHÏ|hözÍ ÈZ uè£?æ´;ܤÖk£ôfŽõÔß6ÉùÉ·€v<*·£,õ…¾§ ='2ó yYqïÒ¢ö\B$˜åÛÁ/õe }ÔküˆÑ阃á5üúÈè}Âí°;=6âÛ)°œYOÙ¼ž#·ú#ûd¹r3¸þ­|}»|ýâœ̽·Àõ~ùz`Îæ¼> Ëïb߯×GÊ-—¹ÞpùâŠå(šñARDÅ)²ä$?‘õwJEQ~¿Á 1Y¹AEÁ½ÀËËý ÊDÏ(M…——Áý³U*¼Uôz‡ö‚w‡BnÜþ–Ö)ЍþÓOõ¨(:µo¥ï_Ð:DÓŠ?EùüAó­äe–l˜ú–Fø}Ô¶I•Ïï4¢$þ%ÿö(¸ŸãSMBÔp>Ž=J^Ÿ©‰ÙrZ8¢2l8CÚbò5ÔÄæqƒ¢‰¥}#Kî˜MØAÀQAb)‘6zDÉcԠɯ-ºW˜ƒß9¿¤ú¥Ï’E‹ïqlcÖÜeü—¤YFBÙ_×ÑÝÛ_ÛúÞ@„(U ¾ç òÎð“ÕЛµZ\²²À8ÿîbqqꕃN`ÍÖ÷rUçà{‰%u¥ŒÊyr]˜E0ýÝ>\‰:giŒä™?›g{†4ÅÒþ=Oê ªÿf\‚/ÒèT{X¥Ö©Q ˆ Ñ 4Á`ò“ F²vQ‚W¹r ­úÎܽ¬ÁÀÉEU¼S”ì,DÍ~TÍ9%Ñ¡'ÑÀnÖ0{"€š‚ø ¼Äª’ÓN¯||†gÊ¡šý™çøTv8Ý>'ZŸÚÞ•JþSæ¹k$9vÀ1p€1ø3‘ƒt!}È/ᜱöt×1Û úó³Ù9¡p9‘]8ÌÙ˜Ž$:ˆv=¼/Yzûâ„ÔÎcí%Ù1©]£i—bÙ%lÞÜQ^ÿaw˜è‘=ZstÖnðã®ÞìÞjØzµ!¬"µ ¦N+—ü’G¾¸»þÄüfkχ‰%¯þ’¦Ò NÒ¸Ü36?ªé“òRÅu¦ò”§œhªôðþY`ô†#ö° ¥x8´…:“¿WœC¹rÝÉ ûˆ÷nXìQ§' À ¸‹Z˜+,:8µb…ÙG½¨ÕƒýÆkOþÑîñz.§Çðò™Çãµ£|ú‰^O¨hÕ'ŸèXùèNþåÀÏ]$"D‰¬å®Pdªk†ÞQð›F,¨ù$;ä›AÍ'ÈáE.R9ˆy:ÁÁD æ“ ðüZ‘š[Îí»ãì åðx`æ†ò“Y7õuîî duܨ׹§+€¶¿úÍÞ^½>÷¿zûšGvÆj¶Ý¿fÍûÀñè7™»ŒQD ¹•‹Ì f=…ðZfŸ²’ÁÌž‡>$È´Nicvød:!?‚Ž„yÇâ>œX å)ÏNÍPŒ¢MnÑì61—áê(¸½1$´<À .AeÑÈz%Cãëd zà-¼–z#1Úe ¤¸ä.пuÈEÒ™±‰3%ÙੜÁM3nw%˜-•1MoÆ©ÐW9ƒV ÖËA¿0ö‰¯ /²1Nƒ!¹ “Hס`¥“ PK†qL ÚB$pJù_µds^*-ű¥w‘4«™­Ô™õjBÃêPSË@‰A*j/©ÛÔVÈ@Œˆ“j¾zÍuñÕ‡ÃÖÆÝkÿ+R³4¹B° À‚$“ÛbÐ|R3ÒÝäñÇBV·ß 8˜ˆ—å•üSÍ¥c74¿¨Qv*éI&ñ½ û”þ)ÁZcºîÕîx »;ÇõŽlâ,¢7Ôj%ÀK¤ݾ:4çõ’íCÒ j9AŽ*©Â+9%€ì4T–t •rŸ‘k·ËÕu‰ÕÞÐ\B~ ßHw4•w!œ—ʼpµœ°÷2àFêÎrýirâøÞêëž™jÚ½¦B«(ŒÒPLiïTS|c£7¿ooÇÍZVCj–ÙŸhõ[#ݑ걶bà'#Ô¦êÕÛ£G ÜuƒUÑ}á}=÷l­1»\ŒÎä4,,åÉq{ëúKÊÖF½*Îj2X8Ê]W–ÛZæòåúHÎffͼޘíC«®o®è­Ðbdqï0ë½s4Q øv ¥¼ì!7ƒQÓ~‚@ f0ò¬9ó †lþT<Í­§GˆõH*2LȾà¬:«ä`É3‰TQ)•'9• ðÍy#HdžÓÙÔdøèC=D±Ax] —Ky ªÙFÐQ4ü•4z \¾"§þu֜܊% Ð -Þì·áŤZ«zŠH£Ënçðz TªÕ¬æ‹{}xöI%‚On0 …•£¿<(km3XËIDëžA‘SUUdÙ Z}2À¼@T©ðÔ ô‰*Xútχå§ù¤9“ˆÒ1©ÙËçt˜9çS <”*žTð>ÙtÛ·TŽ÷DŒ4 “2dÇ7·E·uxÛoêw…ýY»är`Nž!†dgEÖÔ÷'JNo{bª‚5IF¿‡³pÉ.º'Z£ëëœ8IX³1ÎíV솬@ò!/=%÷¾¹‹ø¯I7RŒ4#[dî™[;ƒ5Nk­VmÉ Ötцæ**È,ð¹' ëâ3¨)-:%³«© †»,#Ó Ã:–_ óaºó]B”,I±«Z’ú(2êבOíê½u}4‡7„»öÛáï¨ój”ÒjèœÊ•%îìÏíñ•k 'ïôÿDªˆgw´D­žØp¬~¤Î‰>¾ú;7µÚw?¹¡ï™ïÞ³¥F£xPÈ9µžÓwîÿáë”ØÊÍ÷ŒÔÇ}:Ñ%ìn² ¨{³²º‹Æ÷Úq!é½ë·ž¢(‘ŸÁÚN!"ÉÏ 5§¬̈œ:È,ïWOZá³é„üPN:½h±š¼êF™ àûpRC%‹(½ä³yr8”B7û†ÕFûƒÞÄPøÛ‚ÃjÕÿí8PÛsSWíx»×ÕÔ=TÖpã@I¸g{]Ùðª._ÛêaltÕèØjCm¥³dÿì÷Bí±:»6Þš?:9 fÀà 3@ò"qd³<EpÀ4µÕ`œñÇ’^¯ª N€|(jL'T™\!µ6E¦o, Š ²@ÿùC*I¦ÕèRú'–²„òÅ ª–D”á3Æ¢¾[žÙ™ÛÝXd  J«Öêú"£÷`ÖúŽþÂíøKÇvï}|,pÜÛ0«ßPc·T Æ;¾Ž¾Þ÷£Ç9ƒÁaƒqƒœkßwlˆu˜uUã÷öôûÆæï°gÿñD¸°ksiõhC¶ìåZ(éÕ¥˜°IÆ„M2&L(.‹ Å4&¿&Ä_-Jüxß§7ånÿñ¾ýOoÎý‰T;ÑÓ¶µÞ!ÕÈG'&$R˜pû+þtßÚG¦¢U“¬MÁŒ}L…Lj\ ×z”›‹Yc,ïäðƒHÁ7˜ f¦1°Þð0Ô~ÂYƒE(XfPYß=¿L•x–‹²… Œ¢uªÙ!•–¡( Pý"ì(H‚ä¨OÔz Ù3àám¬¼ûwDмÄ3ÔKiùÅ­Þ yÑuà˾ F¥J‰ „HrÛ™°ü ‘lï4cS û+O‡¸H†LMé aÉÓ P”Š,‚Ž™;³-Æ90‡X¿MN5Ñ›XN³ZTj(âF7Önl/Ö‘Œ†¤ÍÑÝÑu‡×å[÷ \ÄJêY ££ÝÍYî€GÍÛ V9Ëg ´'âå›'SpE¶´x?胵i´X„µÅt+ûrVÆrV®Ì‰áz Ó'Z¬æ«ys™Œ[ûòçÜn²uÈ|ÍhQ®ÝZ¦ Å>wþ\B~ÁbA5´Xöÿ ï¯Ûó̶ú]k«X5…ëušHßTc|S£7¯ooç- ¿T£×ì’¡biO¤j´£˜–=R¥¯Zµ»aàÈ €ŠÕ S݇ÖÝRnr:Y½Ñaʲ¹r\ÞºÕ%e뀢7¶®Ü¼ÿD¢&±*ÂÁ°<5£¢ƒ-+vö„ü=·ö׮͑Ac-ÔÒŒBÒák-œ:6Uyrë÷¦ª‹¤ÓñV^°ñj‹ÓâŠom«Žº´‹A#‰EFï´° È…f,EV ¯(}Ô6÷RLd±Î‘64ïú(:E¢hiÍŠ¢Ñ¬!fÔÚíÚ›#èdm U4/‚nÕpf'‚ºA§ÃEí¬’ºø,x R¨Eµ3s—c4¸ÐVÍ’9 m¼€æ­+/oýú÷åÕé2•ÏŠáò_ ’ «æ º!' I¯’R×I_wWÏ­CµÙœêºñØŽìŽX¾(m¨ŠÑ09e%pWÜZßÙ_4qt]Îsb¥mM”F7Dcêè«Û»”²£c z–òúŽýO§`é]#UÃñ,K<7QPسtÚF0'Ju,F¥&€J·œBL¤Q©´,*••J_ŠJç‹øq”†HV̲zsxŒB?™}À`ôÿ^’²rd@Š#½€Zž—ñh9Ò‚¦ÖÆ—Á„<ÚQ3w@'[d&u'’¾Sš¾Sš¾#§åÒ‹¶B¿$ºV´0]¦0 $óŽœR¼p _‹1 {r¢‘Ô¹< Ì`RÌ ±1èn˜$þ‚(¹B.S³O˜hg…\1uV¬xk@¹·NA²] ã—NSG.uT2t¿$oT‡ëüiøŽx!xi<ÝèxºÑñT£ãpòð4\íNGjÉÑ›AôTþ’·”„9'å—‘¡Î$/õyð:K 䛾*OH_‰äŸ¯ÙulÛ¦ïî¨ ´ïhªH~£Œäóábâ–©vÿ¯}‘ÄÀò5›AoÓ–Æèp­ëð¡ýÑŽUBÁÞ›:SX¾g¨¬ñƵËlXÕê–±üp°±ÐÑ|M¥«tßì÷CíõµWŒæ·ÞÔ ¸÷1Í7*–¶Åh¾a:²oÀ bš` àU0Òg0ïXywP®¢M¸c€J‹‘}ç^Ü/ZV@\y {ny ûxبøPM£=E£÷¬ÍÇ"Ž$Xç/ž|òºžÛ†b~þ¸7>­ª¶[€Š›ÓÖP‹¾¾êYß#jN`ÛnÿÁ«°z˽½ýߺ¡¨Uw¯àûÂpצҚ±†lÆì„R} ˜›ï,Eøå2Â/—¾þ$; ¼þ9q%Âׄ?¾ðÓ‰kGøïT^÷ÌÔö'‘ªÏì„Çç-cU›¼þ–±jxĤoí¨?ôó{¼q_GìÐëîùÎH jòá!pÌ­ž|¦¬ž»Œ¾CøR5oõ5œòÈVßúSöÍ$t̾ÙÅ“Zhô­ŸNÈO Ï{å*6ßôú7ôÚè–D—Iý!gÒ’8A«?g ¢M\¼JR+¡Dj|äé"/òZâ[*( Ú7pzQŒÔ Siœ>º`ñ½#mñ-=Sb¦BãÐÜ9AmQ̽•W7÷–Æ4 ¥4öFbß’2öV.oì-ÿrc¯4R­SÏÑ›tI º_4®-1Š ¡’UÑ< LÒj¾låh¤ÿ¶Þ\kýžÁ§Ðw¾™·  `F“Ó"êÞlœèðx«ó%›×ªâíF‘×qN‡)¿}Seé¦Ýw­ù¾æ¾ô–-ãöƒiÜ^qnÅÌiàþ9í@Ì=nþ\¡À/Gì1K ²áú2\'ÍŸ§És1VGÿÓX=»*ñèhù†Ö"ˆ}-Ããëk«ÖÕ8ÝÍ×AÅŽ uêD隨׌‡KÖ6À„©°C¹rС+oìÉuF: jFâYhpÅ ½œh…i&n €aÖp<l Y(½Å(Xô¤µ°)×]ž+Y½VRo1°&NÇ:íF_ÃX]ñê†'ƒñu`VçÌ}&²@-LYu =ì :7í'I$<ƒ>cÍ~[á%¢ÀÃq´g3½U^J*!^_Öc@ê…—E¥tYØÓn±/GëNL†ë‡ö;*£Ë ó’%ózHB½½‹2ºòœÞS÷0¨äcXò›è$Zíñ¾Ÿl}Ÿä’`—D=ÖÃèi%ýÎ*΂uÏþ+Äì£sÀ%€„âÊÎÆp¥Ñ±yÌ^¥`öŠ”‹ióë>D‘¿IÊ §«Àu¹—p×}”«Ò":Zà÷Ë õœ+Í»pNò©LTRÓîGû û t!ó Ú_Ù]‰¹î½Óð¹8Ñhµ¢ÿSí­&¹K'ZÂÐÑ´Íá¡0Ãi†·8Q¯âͼ»¢«`d'qÉ…þ£Ý¦– Mò?PEóºvšØ1÷{|+àFÅ@.&;/‡Æ´×3 Ú²C!érŲ.ÆcI±üÔÖˆKL½b¨ìãDª¸!ëRÂ0NÆþ2/Ru®ÙØ›³Xo-ÞxßP뮾*Çç5OÜ7쬯ÊãÔE«iOQ<¸rªÅ‡™ÊÚükoïõ?3ºÅQ[]jr–÷”–®,–ÐU‡†Ë=Ñw¶µ|ãŽ}…*†å,\èCkéªÑ}Z3O‡{÷tmÑðfýÆÃ=^oõJHGá¹Ë¸~1¢®O!êZˆ¨yÀqOI›˜­Ë jø jøp9D]ºQëabÚäõ„Þì³xü<‰þ`öÏ v­á¿ìQûÅ98cð‰œ¬,èËÞv0–`,!¢nG®W,¼…&[x± oÅ9Ì„y3 Y¯(2ï‚e¼åBjpÓ‹%—šyéÒ–¼ Ë8Ùra~l—,™¼º­W‘ø™15¾e[¿96vÿX¡+6\à ¥`èžáCkò¤Ò¾ê˜?ÙTÜV( »ªÇÖ¸-åñøê"ÛúkÖEL(S?ÙÈn© u¯ˆ¹,•±öüŠmyÙñ¡Š¼¶xµÝ^ÓÜ…þ>ÚiÊ.u9‹óó-ƒI.§¢¨Ðê(/-µ»+¢=_Î\Ò z²ôd)Ò¬äÛ=áZ©aá8$ g…k2Y«> Å?ÎÊR…Æ­—TK¹F†ù× Ê†ª>KdÅ?NÈÅUÖK ÕrƒXÊ1›3¢²ñC‡Þß0ñÀ¦àÊ:¿ž¢0BE“šœÊÎÂöímÙ˜¹"Þš½nŸ¿päèHóT_M6ÿ´³²»¸´³Ô2¶ÙY[SŠUF¿vðúµ-Ç14+èLV=¡ãuå#û[t`*„z÷4¯¸c¬ÒU³fב²±¯õú|Õ+óÖÓ¬ôQ7è£.ÐG0¨.½Ö¡ •3Å4ZÛ%~<û¯KàaLËÛ.%øq2û¯Ë CâªÈ°+8ôàdÓŽUµ9|îàƒÛ¶þ·Ü[ËzÊ¢ÝaÁé)ö„xL¸åµ£]@…Þû@ÿ­?;ÚÕvÏkwï~|c¨.ñÐp,¨M<fò×ÁDÉè0„t¥í¿ÂY'Ï#cºoìŒos.ÿY oÁØ€—e¡Ã 1,£  Å6°2Âæ­¿%Wµþ擆š}ždàž ùÞ¼IK@†ªI ß ’S ^T§õ‚…U©X‹ X8ö—;4(ëy3ËOàÓC¨¾Ø „Ýܲ|U) ÿß·6ðTà) Sé¹ ð¯Ä•þ\4m¥{R–ü¡KDÞµIþüyÿ ɯØéö€Æà%—A•Œ2Ì:£¡Ð[)Á™ïò„ú:SrK>…¢AçÍT„‘êM’µKF‡dÖbc ¯ˆÂÙ 7Ö>{AŽü^)ó«Ì–K¡Ì¯Pd~•,óCux½dh“ôÙß“ù¡*Eæ{ë>HÈUHé³k–ùËùte¡Ÿ²ÏTot´f¸9ÈÀ„RúÞšÁúªõñ,g||…«(מ„Á}¿ä}Û’CÖÆÀ†£Ã…èªþÃa½Ñ¨ÑòV#kÖ©Œ@œ•öT„› -›Ýè ûð6A“ü=†åuï„ô0šš»PêËÙÅNä©OCkúHŒE´…BdÎg@✠WH{C¨â# íICÎg²¤ÿxA\ƒýlqù¹^°á¾‘¶½–ó7l=:šÝTž£¥H‡J厴ä¯ÜÑâÆƒwöÞÒá~ÒXÐVÖ´;h+뉔¯,2£«àF@¾èஃ­ w¼nu‰ZË2´Î 5XYŠÑ1•cûWX‚áÕ{ºC­¥v¿eìÎÞ¬ìšN(å7€YR¿Ø›KysëRÞÜÈ)ë²RÞªHyë—Jù on=ø2¹›Ô1ïõsúäì§`d ^=¢ãéyAÿ,£U¥=m° Š¨Ç‘0~`ü|HRŸ–ôAt,0z´]ç² àG]|ÃK®Áð¯.®)³(ÜA¾ÿIŸ.-ú/$Äq<úv_"é©e=õå>ÝÎW^\wïH±«n}]YwÄ–·æÎ¡ý½þÉíu¢®W6¬4…ÚËúûݶŠþêHG‘49µm5}ÄßÔPØÓRk“*ë;ò«7®æ4EúÚkW¢¿‹vvÆœ%á<1g,iòUZÅpqµ·½§;%«êRôÞ¯X™ 'õH-¤v½?þ‘׫ªø8\úX•Iìï¿U™¢toü#Ù…[ñq"\%}œà×î¼%–:oë¸Ü¦mŽå¶VçpŒb`@`{QÏu+|¨±4Ú¾½ÓS°þ£m;W•{õ?´þªXYd2„Û+š§°Êø=wìé/Öè9Åa´°€JtU£û› ˆ ­ÚÝÜz@žS‡Š6É]³2PÐZb÷¥cúH„…H›B;&, ÈÄ……O"´u¥O²}Yàp‚ìOÉï—ßWâ[Xøt:ÁöÁÈúd¸š}ÇteX_tß ·Ýzú†ŠÚ}ÿýöÛÀñd°kOÛÚ›Ú<¹Ý»Û×ÜÔîÁ<ôç ÷?}é{ß¼t|¸ÿ™Kk¾v ºó®v¥Žé¸>RD£ebòMyMèI8ŸVC4?ÈàZ§(Èá|@¿Bá)éh>гuÈ-iÛÎà‚mgÿY†¯¨TÌ;!Ù¼ÓÍ;ÔªLóÎRìY¥4ò„RFž>ÙÈ8™53<Ë9g ×Ô½³é ¾Ëk'Êy;КªFV„iðÍ$Fiøªþu¾¾>dn9´ý<†Ú6ÁnШ8§ÙèEJÝÓX^^g•×ë÷¨y‡I/òz.;˺¹©îÖ£Ïíz[#¤vrÂ÷‚^ÊðÒ–^aíÈðÒ2²—öOÐjÓg—)²¼V/-£xiÿ$›}ú —–™'ÜÿjËÏÞÊ]Ïîªß¹¦’W“¸NÏ”vïhNôíM{i§æúFÛJt)Ë!²fª~ð®…€>t²çî-ÕF§[¯3:Í>›ki<«òÆÖ–Ãx>o®¦áЉ+x²láU{Zj'z*Œ,^¥Äó]&Ò(ã¿ñü§Kã¿¿2ËZÐÑ)\×K¯¾*<¥xi™“È(½ ÌÈVÕ¨>Â(¼¦6ÊÞZõìÇóQ}¯‘FOÈé+ré_3`Tß úz àJ¾å$W{`H´Áe·ñØgjF ìûööl{ŠÊ&I=À7¤m?/ÏãÀâyÛO~Lªûu=ÒbÒº ”ëhü“ { ¯v1=}e4H-X€ä¿èdWX— ®Bÿ?â¾LŽâZ·«{zBwO‡‰=9§ÝI›wµ³Ú]iW”‘@˜‹°A_“œÀ6¶?û^¢A–¬K0³cY6A¶±¯}Á×¾NŸõ \>cc4z§ª{vgWB˜÷ù½·‚éîêê™êSáü§êÔùÓƒ›fŸÅÇO …*öòC÷^|ï¶.Ùíæ»ß!{d³Û¯F/š3ã¼¾8úI‘°ÅFÖlï¦i„Ú.øØ º§mdž¡ôˆåÌ.[ Z¦£ 6Œ‚ÀÊòžÃ/; Â÷á›ÿŸ6ø-àóˆÿ¡ ãm‘xÑb÷Û“I¼„e×}Ú ìß¡(â³õ'f Fì³µLÛqƒ—uÞi®¼u÷¨*ËÓÔÆÚÝF–áß©F+o%¿/ãXVMgªÔÿ‡>ZôKö~í¶-½¼ì´¼NŸl$>Z®‘ýØGëÖÅÄGëÞ__¾û›šVïùƒñI-„Ê"žHÂ3>4Q§Íá°ì ¼^šC Ä ˜e×x9Ó¡â³'é6ð5¬°¾ÜÖÙÃ: w˜ÇqÄN:W±pa¨ Å`ÂÍŠžhår4E$BÜK–HŸ!«úGq¹fŸ†A Ç2'ë—8„¹ü«µÌ®d³ƒÔW)‰)PY†Œb`^hý—oÞpõƒ›³ùê7¯¿Žß}ÙÞùùeõ¹‚›F:—õ¥U ýÉ»þràüå_÷kŸ{—÷žÏ•Ë:<‹n{ªúé£×wÇÏ»ìfªîoX¥ ¤âñ ŠPÜb>÷¢¸áðån”!µcÃÝóXV\!yDaáS£,£‹<£3_dt‘gôñ™1@BbPÅ©<þä}íŽd-ZÑמÒŸÁ_AÈ,ðÄפà©þC±Åy ™êðφè DzãÙ!ÍÎ>¯/ O2¬­O•ô©ÂWñwL"•3M–üÓ]å˜×îâ4W94ƒáI¿»Êéžr¥}ŸÔ‰5ÓŽ²A” `î…ÊXÝe¥‚\¸7¸Èš¾+L"òÓ¹ 8§ÕH×ônŠ×DÈc¦óÿÃ0/ÍëH¯¾O8þi.y_~a—Íß¶¨ÜwþhAÀ3-4kV{V^Ü£¾o;F—ÎúÒQ³-è”\²èŒÇTú®¹sÿeô‘y™Ìg0êC³5½² íÇ‚^… fe;"í–vN…ðpjGó+˜C$ Y’˜°b)šå:_'yÒ‡ŸôéÝ`dî¡LÀD‡ñè"êÍ^Ô{’ˆ«Û•'ö`ªøž µßƒH·Ð»‡æ‘ñÀ(!Z \Ç'|/6ńᶮI¿ H²ñÌG…ª“Ü&ÿ_| i£ÙÞ½l[¥Ñ§]¶òÎÍÎ@H$N…þpÐê²bÇŠJZ]Ù‘Æ»OÒÄ©PóÀ-¥eé:Z5µ-¾y@ ¯jh‘Ý¥•nL’C©fO¡x%ü(éC12|&T”p£¤ %(é@# ‘ÄY7 ¬‘±Ô¦¥9— '.<ĺôf€Aí»ü--òØ©÷+È!ãn÷ÂÂæWÁJPÆa ä'i…JQm$5€ÃÝÞ@ˆXà¶Áo=;ŒÖù8²:ƒd¶¨”Ž‘ãdÏŸö÷ÏÛÌ«Ø5Ò¡Ñžü£ [YI ½ÂÚƒÍÁH!(FqÖþMÛ—F’µ7ë4D GPµã5}Ɔ!±€¸ßÿnŒþÃÉnÍ;òs7 ÆÔûÚ˜šê@©vBSÎ1õQmHíÐÇÍìÑÄC·êxdš†JJCj÷Á´¸°¸­¸»È¸"¸"¤spç†IËe4Osã„ÞÜýN8а;å4`¿VÃ}Y$ÿDïãkkU«\ž™Í¥í~§JE¡Ÿ’o; ðÞÃüîŸÙ.}ÿLôµ­ÿ¾­[ñ¨¢ xm vÐ xÃC[&4'Á¾î  xY÷мü}‚õ7@OÛO°þÛÚ˜¬ÀË)4O‘5Œð{}$pCщ›àøWÒâwb(y¬þ”,kÄDä)YŠÜæ1÷Ô2îžFv*RoÔà÷q„sê¨Ä©SQ9õï„ãGà²ä:Å Ñ` ©Á¬ÎU§‹Òçg?Ô2™dAù ÇF–-škã¤e"YtË$ ¦™Ý¢[&ºw#Hú”¶¢x‚y@·L~Gzˆ=Ó‚šX”!,OMI”äЬÂX$C ­um¸º€º £… L¶€@-‚ÍJ‰b˜Â ød Ó\ ãžÐƒu<Úƒñœ ?~Ejï™Õ³¹‡‰÷ ž1:[[(Qy;6µ¿Ó„"³n鳞ÄiºˆP÷›-6ö è) ¦öx«©‰˜Kæ sé¬S¢gsyk¯{¼eÏhvX°ÇŸî[\ú<ÞæÞF?±tïWoÝÚÃË6[ÈëòЬd“ð~–P¾gómKNówkë¹`(‘Ãu5BÓ?gG› , Ã/AJŒ>Š®`)F=e.ý2½…ä1é)ðÔJ’bÖSôQúû:¤Xô”aȳ”ý9¤pzÊjH¹‡<Åë)Exj=É#LüÖ8ý’Ǫ§ AÊ’"ê)ç0"|ÏlH‘ô”õô´Áx)¤Øô”²†¤Øq ± 3ôÏéyįo"Öõ!ëú Žuýœ´3ö{íi±®Ÿ«J;ÙØsU¸U7¤§RS&{韧_wî²k%ÓçàãÂÔg½­CÍÅá&»/?”-emO­ùÜE]m[îZ·ê®‹ºÛ·ÜµiɶÁ@jdëýÉ‘­$öí©<º‚­ïá~œŠ }‡ÉTï²òŒ½FßíM÷ê{¸í‡«äÖÄnölþ|W˜m>ÂÖt—hãð¤é †ëðX c& xÇb¢w,2ÑÞ0kåØmÈ@#7J8÷T;½dڮͥ?}çH.’‹P¥1zf…³¸_KïÊÏ1WkÛmês»D¶Ö´ûµ*ÜfÊÏU!ƒf!éñK¦zê}àö½EkM^²¢·/Þ_ˆ€‘I3¬ÐÜ3’œ±¶/°`~z¸ìwv®è Šbâ%·Íå·9”ÞŽ@kXÆlD‡`œÙÓÒnwÛÕ€Õfµn‡è/ÏÎŽl”i&P¨@LœÊÓGè¡i+ñè‘úLìx%^myVÇzã®9ÛJ¼*·<[mÈ: þc;f˜}D°^i–I'0Ö¾ã„ѬɈP³q?í®äÅÚoé÷Þw{ý_¬Ç9þ¢ÞOò8zÌh2’ >µt}©Ff>†¡Õ,¥û®©ï—¹¡î{‡^®H”}ïªþiî*õÙÉ&2-¤·½;ú4ÞMkÿi5w«>ÛØ$²ù¶#FYO/Í-¹|Vl -) æ€0y2ý­©Õ‘]J–½6ÉîB—26ˆÖÚØ[ÔY[‡£…ʃ1³¨pÍ ñM’M”¢íép>$šm.4ßí0‹n1>L£PÏ2¬õWƒ îžÓBU´y÷©Ž1ôÍܪr­chÅMqTY.Óo–Qy_S}FÙÙûíi¬Ý>mŽ©¼¯ •è3Ue'ÛûíG}˜0|øŠ;}O|Nudé%Ÿ,/¼t®»µ),˜ñ˜göÄóÎ…%…WõÌZ×ë½S —“¹ùA{¼#‘j‹J-ëf§;6|bQ~ÓùˬY\NÅieÍfSb`yÁˆWVöEÛbvÕ1¼ªÝíJ” e¡¬‡–Ò¸VpÝ·5o:ô 'cû©÷*þšéóË ãµý´JnÍ“NÇpôz†1jo08xŸ?,1¨¥v»U`ŒœýpKD§ÍÆŸü¼Ùb„Aßj¦w„ü0ì›Y«›xÓeè/@Ý…¨fª—Ú­iË$ú%Saô çå^þ™sO¢ B;Њߜ-2TLŽÑoÆPl¯s§Ôê¦Ou£î½ ®ÓµÛñÿ¸‡vÆöV;™î½Uf¢^ë›ßtN¡©‹í.Wãbû”µvú _½cæÅsÓ+W$:’ŽèЖ¡¡ ýÁy£ËÖ><£¿2CŠ;<öT_:Ñ•GçÏEÿ &€š½!£dZ;#ÍsÛ‚ÞÂpSÿùñÌùh°¥9ŸqÅÂA¹³ö-O*µÛÃñ”»\hÅ-}¤µ¤…ñíÆúþ héØc®N*®”T UèSTÙ‡·M?Ó¼Sý¶ijCoð™³G+û´-ÓÏT›wšÔoWM§µsôÉéóð-L#ùÆ!T^´mn°£%ðæ£'Ó™è8§ìeäd®˜u~¯/1z îÞOÑŽD[<Ñ“ÄH9™÷³üæõËâF^ä8Aâ£.^à•s‹ÅjŽ ,/u¬ŸéÜð‰îUWªä”cv7Yƒºœ¾í…6¤E ñÆÐM‹Cð«Žýf|­¥c'•êQb+œ_û«æ ÜR[KÞcÙc¥Éq\#)œŒÑ¯‘4À} D"Á£¼$ò?F"£‚ü©€÷eŽç¹—½oà‡˜Þë‡(ÓúÚ~´þq= Ž‘·‹ÄÈ»ÇÈCr†ø=Tÿød¼ƒ8Aí×¢lc–«zPñ©AòÖ÷t÷v¯:%§d¡cm1Å/GÙêVl¡»ò½oúûN<§@XÃŒ]7Ü44´ç†Ýý4`,°|¡t+ tkHéÊõy»HŒ<èx8FÞõ‡$/§É#õ NÑÊ—˜Œ’WîhÇ@ 1JÞ[¬-ÊX$—èRy¦§««‡¦Õ®¸D#жÅíߺé†]3 d4žò¸úo{n|ïJL_ 0€îß}Ãhç§Þ¢7ÑwO"èŠÍA9Ùƒ<û¥Ý!èõûÙ¡QCG‡ýìñgu½¿*ífcû«póÝCoŠÎºxdtëÌPdèâÑ…W¼·É‘öD¬‘íðéRÈŠfÏßµ²Ø²üºE£×®*·¯¾z´sywÀß¹¤shu›3س$Z8õº‰þ èÎ:‚Þ_á„~ß¿›½a ~®p@¿_%7Îi=ßdV|N£g`ð¤ÁbuÊNÄ*˜„Æ1ÊÿºÀÄX ¤s†K4Œž{aðð‚<Û©¥uô|üQŒžs>*²Ev#÷þônkTä~æz,Û"nc\uÀÑû«‰)ï¯Bž ø(8Úkåj päù›Å µ½%Ú–ò‚…Ç2¬˜jˆd}Jf´c ˆÖ6¿p´]rÚ$ËÕ±rK³'U”í *‡ì° ¾âP&Ò?8?·ˆàè´ÞõêÓu}¨b™鎌ĻÌòãJ˜ÚÚ2rå ePæ¡$9B!vpwÈèÍ‹à¼VùÄvø¯¾N=mÏ |Ë`þáj(óPµþ ¬ã‘zÔ¾`ÚÆbÃYæ’Û§ or&pµœÙ<#Ú_NHF‹ÅìoêmŠB’-5£y¦‰Óˆ`fÏ)wÊ™€Ñà1,oLv.îðÙc¥`º/ãz<7§°ˆŠìñúl’"ÊžˆâŽ{­˜;W²ó†R.Ö*Û%ƒ`yI0svÅêÉö%ÅLÀlð¦‰ç¶ãÔ{t};Á×'ñõÇëøzwÅæJùB-¨åa7ïân˜„ØÛÏèíúpµ!ï?ˆ±í ›Á»OàçêÔu¦Úa'd0ÿĈî˜êOy¸¹œõOô /ŽyýÛ±G&’Øn€ÑIvÙd]d0iTAµn4\{…"8ê-ÚNßBuj>êS´ûH¼9Þ,øÆ e©”€û̃`PÉÐ>öe® ¹ëá‰á kÝíÓÐv°ü`ògZ÷U3×±®‡'Æ«³F-JNÛ®)XÛž™{a¥i Åƒk4ZÜÉî\¨œtŒ¶t¹Éî@Ky« Ôþfo•{×D_./éY¬Vέâ0Ë‚$X}MbÙ,9×®¨€ïV„<ùЬ¼Eç Ga„¦ùé'Jؘâ\.*û‡;Òé4+‡QøA¢;Qç×Ï$ƒ ä‘Î?P…üRøAº¡Ï{‡-Òì ·øEÆæXÆïÙ‘Áƒó6ôªa8Žnìõ}J,‘œ_”CÍXÎ/ÐfÎĘ…38ñ~U£ Xþ:sËH²itsïÌ­#©ôœ­ýíÃiÑÕ<Ø\˜™QÔ–JM®lm̰¥Ò>œ’2à1~Ue…vݪy?lŠÇpP0ÚtkOƒ7Åm8õpU¨@zƒ)©Ñ ¾T\ŠL’£‘°Gœh®™¿ÓPàÌbåŒFÎjF£f%àÀêáÌʳtÅî³™kŸC‰eñJqÕlóÙmgV ‹gVà.ñü¦Ö2Ÿ7$A?E“[ò@#9FØfÃE…%ü.Çuc2…tsµ“Ê&„‚ |'ñïÿ‰ð”#£¸ÆdN^K_o•ÌÌ¿{BVÚˆî`“qÙo³Òè6^m D¼±ö|íû&Þ#ëÕÔy̘!–¹V›_6N”.*ÆÉ’h“L–BXg´·»ÜÔŘÁÈßÿ3/[ `yòôÍ'wC)@ëÉ<ãà¬ô Åçà™ÚLLàöG‹úP›‘wÅÀ*‡‚Ö.gS”Lm¦VVP&J¢ÜPªŽNõS³©…Ôrjµ…ÚF]EíFóˆÍyÉ¢­Õ¥ÕÎ]Û{múÒÍ;Âë7Æ7šGæ ó¨ÊaHΗåêµ;6Î*—‡æmÜqmÕä_±FõϹìÊWμz׬]Å‹.i¿Ä»ê¼ày¶ÅçºÎ¥»ggpM-bË•».9ïÜ--3Î=ï’]Wš’›/ˆ&A0­Ç”ze íXñì?aû(Oàá óÿ¬|•$©«XDR±±h[¹TLéG»~tëÇú}Ó´ëéÇé÷M®©×‰iß_ÿ=æx¾\μ[*” q|Vë(Âß7J…B‰^Œ?Ozq}ÓDÞ“ûòåb1Ž år½€oÖÖàÏwqîÏá3æî"6N ¥ÚOK¥Âëp>'çâo»>Ð·Š­m'Gàì®|¾L‡õL5œü?ö³r¾Ü' 9üô1ú8ûÚh>Daý{ýýUö7p}„ø¬¢Ÿ§eߤJ?H©É1ôÉŠl]XXWx½Àø ¾B&2n£?~(3nÞ¡o‡šZ‹ZO'\v©*|µÀXµÜ¶Èxç?bÎŒWÍ;ê{ÇŸŒ¦Æ¹>ú^›KÕ YÉþX^ÛE? ÆVSÿ¢æׯ.•×Þ¸``G“ly‹—÷.ím]Ô¹tS £5!ÈN /0KÃÁäv+¥Ÿ]wÁ—ª]јu„ƒ²I'F.¾õã«lâ—&‹—é·ˆ,£ê×+Èõ‘Í »ö7”Oç¶d­˜)QpX(;nµ*†quŒ¾ù€B˜-õÅqù$‘‰`eÇ«G5ŒWë¹Ôþ„†¬IzÎFŒà”Ú[§d«U>L%P¢ Ç>½áŠ¢µ×D»]¤Ÿ 9˜³€§ɾ e~B‡cô1RßOÖ¯‘J®ŸÒ¯@±„ë§õë1¯cNó3äúvxþ÷äúYr½Šþãcÿ\?§ç?Jï"2zž\/‡ëäú»Df³ =u³]q‰†•zÑŠ#ñB¼`õŽ¡[*VÊ*•¤’»ë@¯—ÍàFåÖ)Ž5¿Jm/È 3ñˆ–=Óu ª?p„uOk.”›?’dR·© £¯-¦&mÒÐêíL›s2twÓ覞޵~ÑfaܼWàC©| gÄ,ùâ#=ñÄÌUí¾¶–8Ï™]‚›wÌȵ·¹SE|Nw‚9Ôµ²/äÃÁf]Ê b2É×Sö¦‚^AI¶Ím//j÷›%;ǹC"ËÚ’ÞdÈ÷Úç€ì »ÅDv/è²|žÞGêê{D–^¸ÿ=öw Oº5®h‹ZÒA#âÅhTÁ8<>êqÈÝxKƬ˜j VœäU|Þɸƒ6žy×l¢a‡*Y˜ŸcL’×í ð¬‰þ£]ÀËÒô·ªÀ೓‡é¹-FPAÔG ­ìï Ì/’2û¡Ì_„2·R‹ c¡ÈtAÅÝü(ïn”œšàÅt“òã*$ï9C6µMt‚;ˆaêxÒ~¦cè=‚EˆEÜ^Él¸ÿÖ"yœáÇ ¯8zžGæŒ_ù kUg(&X¬G‹ËoˆÝé|µÿ6qF†UZ†F+˘xsíoÈbHn€gjOhïzŒÞïјÔ9Í ùA‹Ù¥?B™ׇTyW€x„6õqxzZuò=ëÂÄ»…&¸Å Ö>J&ïp&>tz¹liÍo0X$ÕŽ fÎ@×~-Y,  ‡œªG°7ÿç—ýÒl5 Ö°IU× T”Jhs ÅÇcA°±Û&XKÁ&×è„øxuZµž#;¥fR‘©¶Ô‹‰)Ñ?dTUÀi†™µßöÒ€LU5Ä#q´Eñ9]A…£—nþ!ýQ¶Ðˆ5ÀÌIŒY±Ò¿4<£ œñžÚ(¦®Ã¨ •¥:5nÛC^*Yz-§x*„þ¬ fPb"Å{“ã/Q±hNŒK¸ä¥qóe“î Ø›¬²B#aó“ãUªˆ\ <"%Æ«ø¡#æè±ËNse RÓùrê‘ÔbN¬Âì“§ôWí±bïìæW$WYÛ½iO¸3­>eõ5Ç–¯ §½Ö[¼=½uW0µ3â3ŠI¯Õ®ÒO«v_in«¿”ñØçu9£ªð[¨©ö-6 ýJ dp­êúŒ²Áˆ1S³þìè“Ð-½hå!‹gÜŠ%à7^¦{Á«c¼lõ€¦ÂïiôŽW—M]áh|?ba> x›·Ê›?»é!Ñço¾s}á_÷Сի–÷ [6qSŠý-ÕÞ¶ñö5FÒ'ÞJ4*ѰT³>âMa*[ÂvÊâ) ö‚Q/gª^NRS¨õ—ªUIB9©$Täž,|j²ðz%ML§mÞwNÒ9ÉŒØ 29{•ïƒnf-,¼ÊÖ~öaÇ…÷P3‹§pyÉ%š´w3InYrI¦ïšU”UÑø[“ì&ˆŠhd@ÿ$"Ï!¿_RÇЪƒTZÂÈJ(³,§ŽG£­ÜxV€ŽñÖë¨6¼°ª¾µI‚ÌQu¼ Ù»¸ñ*~àH«c¼ÚºcrÂÇÖè»Ú8«ÓÑkXQw*ÚšëÄÌ'ýKÌ~nŽv-êè^S‰&V·{½{9ŽŽ‡x£$­ñΞ¾ ŽPÔµåÓ+r g4ÉFv)o n¿»iΖžÁ-#qQ‹F%OâŒÕ^TT›K2w]ø™Õç}áâ^Ùå‰'t,¸ô‚§(&`™¸ãüÐén‚*¬Xbã/ è £ÐZLŠ~ü¤Þ§š ³UˆA+ œiT"ñ«tJƒÕ¥Äõ²!uz‰&Ë1ùÛä÷¶,?OÆ=‰VÂϧ@:Nöa)ɔԭ'È:Éã§çh$¡ÖXóga}¡“ƒ€ß·z½¾¸­ýÕ\’LfÉç€R³ï‡ßíö 3a¦µ_±f€Ïˆ6Ô¾Rïiô»Ò| âÒJekí»µ[$AÃå³R=šÖœ7¢Xž#m)Ö†‡ƒ7ÏÓø,xymè*øø‰¢|B{í¶3åœÂ_>ñƼå1û¤´qÑm'œOéÓ똊ÜîM@d—hA¿@È$«NÌC´Ïr‡=²ñEæU“Íé±Íáì‚…þ5¼"üÁËVN>Å`GrƒÑçÏM¤ÿÄ넯PN¾M[m^ÉÈ ŠÇÃÑÐ:Õ§­¿àKcè܃}iÇ“h¨ÇN¨M©Åŵê™VïÇuœ–gzÍ×Ñc*èY9ý݃Œ»”,O6 ú÷@ÒI›OU¥—å¸á™è?ªh *ŸÓÁÿ›ä÷zPò’×)ã~õ>eRB*úD`¨¹|Nº¶šÅä3K¿¦:¢Ç^{ÙH(W ¡½õ¶:O·O(‰ŠÕuž¬ë¼[™X—|üPh\³1tž“¨ °&Bãukbræ<©¦§E2òåVݲêàƒøsß#w:ò‹zzöüÂÞÞsŠNÆu_¸¨ûØwÖÞ ŸÏ÷nžÛ”›¿©£o >n&ú™ØN”ŸÊèõ7âªPP ¥ÄÇFÖœ V剺Uiyœ0öÕsM±*q}M¯#C£ÞÞ•˜}ÁðR³èuâÍ«<ìËÌnõÜÈæ\ æ%KQ›áäŒ Ã©ÚŸ'šÞk‡ALvÎiK”TSí}g¢ ï¢Û}T;5D}‚è¹–~ªÜ¡Œ¿_ÁZ]õ·ôS ¢Y +o(o*¬¢¸gŒ‡qKsë­‘h÷íˆÁè~ü„ŽÃ-J? îSžµ0ðtxÆxuòyÂC£ öÛ³áËR`ó&lêÍí&+EØ ÔÁÙNƒà²ÉŸÕ8‡sšüxÈw‚„|Ò#ÁŒÔ:RP•DgÌò«ÖYö»Ñ”ôÌ^)„%úu­9ræ'üù˜½öô„àþCµ1ÈmʤúóqÁì‹çƒßpÙ . <ÃW0jCu+°xwã­<¢*FÛx`²!ÁL:yŒðlãÕ@CåÏPózž ›Å˜.õ«àqXa„"@Çèá&}@rK¦“WLûV@6’¢Ê,+«P>Ý*¬=ŒË7ÀQah³YÊŸ<•¤oÆúëOïbýõ.ödýÖÖ7ÑÅÈ ¢ÏýLê½w5 !ûè¦ÛgTç5e¿ÓÊÃíI¦z2nVñÚ~0@ÿgäÒ…©Äœm#èõá Ö[ž_öz‹óŠèʼn!¯«j6*ÕKÍÇoð$Õ% q$ã™i`†ý~RúÈS·FÞT„r˜´Eë4€õ3b–®bx{Àå ÚyúSô4g ¸Ý!¸xÉ€¤ Ç°qs'ma”T%#ýeæn†•‚nÌ/Ëпµp؇³ Z®ŸÓ¯aƒ‰6XL'_ ;q¤Zìòyº×ˆ£ÖšeÌ]:ùGö1nßÊ•yl5ØPŠ^k¸”øD‘ÀôÑCU‰=I¥ªK¿BõVÎuxZž½ýœE— ‡B³¶/^´m8t³y ¹4”\Í3á˜écë¾´­¯³úå ë¿´­·óâ/_¼f÷¢XáÜ+g­Þ½(^8÷*\[¨î4TA}¹[Ý>†× ‚[K¸$tÅ8P>éÐ& ‰¿Ýiåk³8Iä÷=æ’9á¨Ùë‰¸îæ­hƒÇáðxôú­‚#ävšvºæNv;áW¨‹žk¸ ðièÌDíD Q&×øãj7þú—$|]ÇBšK=×*Ö<Š]tÜ×6+£Ì™ë+Ä,N“hIwÏN¬ï9J«fÝŽ®ó¡ªês†‚1ÛýmçÎîñuÍuzœ`A &§SŠvÍ˦¬ºxð_¡”I¡G —Q£TïÁÂÿfïLÀ›ºÎ¼7IW’y_0æÚxÇÈ&ƒmÉ»ÁØŽ7v°,ɶ@–TIÆ6! '5 ¦Cš¦Í÷•¤™o’.ÓB“”fÚÔy’n“<ÓLÓtò5Ó–¦mÚiÓ„&MBæ#æûŸs¯6cÝæ™>£ûbûl÷œ÷ý÷}Ï’a}9U²1??M)ÎÄüeùùûòÝùªü|ÕúDUjp ÿ•’#©vE I¡%U#¦æ¬LÉLé2·t¤dg¦¤¯ÍÏ^™Ÿšž•žœ‘®ÓS†-Å k DNÈ«j"¾šË®äzNP‰)ørv²^"¦küÒt½^“®9Oö©"â>ljø£—ʦ±!OAÜæq=Y]¹K—fÏÏéE-/•­,íÊz…›g.}åÃäc'ç-+Hb_IŠ7$|p™›§ïä•°×"ìÁÓvéÙ <8?÷¸³¢BU¸‚nJ¡*-~…rBG¯Ž ù œ´ÔðçoZVöŽo6¶V-S‹N›cl¨Øë²û ×/K6¤%³·ge͟Ϭ]Úæj+äªê‡š õ ‰‚*3')=1)ñæ]íÚä,¶#5mÕªŸq\þ†m`˜…xïG¼¯ÀScéÙâUTóâbUÒ2ªy’ª&:ò£5—?wú+ûë~2½yËè–^—)+.·ªË½yýV}¼F«W§®)Ø´}]6_0Zß´¯&Ë—TT·¢f÷òtd‹•›J’¹šë–µ#'ûªØ·×%kÄ$ò†¥N¬¼ù@]za¡iûÆÂº²ôÜŒNg}Nnå&²KØ2®Wd2˜´s|*íž;çLUüAvyµ†þUhôÿ‚ÎõjuóÏi¤‚Œl='°móƒ‰q ñì¦$ Ùù©Œ$ÅÑ_ü\Nfæ’Tòï´¦²ùÜnð[”0«™2“6K[\\^Îùñ7sFhç«è'WXÙá‚EE×û xQ1ý˜.ùXÆîŸ>~¯Í¶£?¯a¸¹ipÓÒþC¶{6oíhM*ÚP~wæöm}»·÷r÷Ááá-ûWÛË·¬[¶ô¦æ’†¡2£ÝµzÓÆê̲‚ÓüÙu[K »Önh¨g¨R?(Åë¨Ês™Kj¨#,Y¢*¬0먅܋ŒŠI‰ðùI³&èE‘~|õgL¢?ÁÝŸ{ó¬wUgjrB5«xm‘yWÝn¹½¡u°6+¿Å¹¥ÏeÊ>È&6TMÅI†ÂÆšÜëN÷&"df§èôºÊ.GMj^iûšµÔGîi¨j_™[¹1¯ nE†DìÚÈ|ñ~zžI8Ïc¹—aÌrŘ2òÿ‡jÅKêö5ÔïªÍήÛÓX¿§6{8¹ º°¬zY|rÁÚÂÕËô\|ç±Ý7Uì8ÖÓ9E~Níhß_Ÿ[Òj­mwŸƒäß&džä4¼gÚ’³qç¹;q®½D²ó&œk…r®‘¿„>¥‹ÓÎ~"9^£D‘º4ù°¨¿–”œŠlð~¿>935Y="¢øÁ¹dÌ×¹ ~”12Å%ryÉòªyÜËç´\¹\áVT‘ó­0õ·Œôù ‰ú¤ãå5ù 6æV•,“ÔzM~e]^uך,Ê͵Ù é¿*3dgç$_Ù²~Uzņ¤´¤Ò¤T­:9)nI¥© ÏÔ¶½ÆK5ý—Î`˜ªs¦l¼}î gv¶ª¢¶ì)ªe-ÝÀT؉ªód«VP•#ò:GZõâ'šZ“–žÎ¥6 n̯«ÈÅsr¢&gEmaÇÍÛ-ÚÄx¹y{|N¹´lí tŠ0oyåú<ÛÐÖMÝ{Øqã–ê¥úÄ$¼tÍ(4¤ê«ë̉驆†šô¢CrZrbzrЍNIÒoë¬ßžÀ‰ÛáŸFæqn-o¥gX9ÃHÞøJð{’û7FCöcÓõO±”ÈS¬Š[›Þ›‘½$mþ}‚F¼$JÅ%y½éϱo¼É,:.êtâñÄœ¬ÜöÎ=ŽzØÃóÓôÏd>Ë¥ò»™J¦â¬1›&£QUP*/€.W_ä$»îAvqÝÔÂfë†âº²l•F É,ZWܱ«Ç²¬*31!9‘mHK›¿˜Z™9yˆ=¹¶¯.WÇ«R2¤¸„¸†öMfMb /-{’sÐßVA„ç!ÂK™Æx¶p%Õ»°P•¸4*Ö×DÅúUÇwíc,êãŸyKëvmlÞU–iöï©luQ«JÉ]‘»f³1ƒÍݵ¶¦£2m ®µ¢}irauAáš¼Döc= *û¶˜îm2¨Õ‰Ix‰¥Õ”4îX•¼,·º­jCkvrý޵™™¥«É>´0ç¸eü^&•É<Ç'é¿N5O ¹BôFޝàéµL#Î_Qgç'ˆlÒü#p!öaC¿:='éƒÿ› KJàÖ­HMO"ç– ñUjYLÙo“V›±|yI oR3€Ï•¬¢vÕá>»¢>p}r9ä=ÜÓ{j ö³ææ5™§úzÆ7˜6m\ß6–ÚÖÙjnÙÒÖÌ:vö÷mÜVdvn2fg–Õæš‹úX©|õêòÒ:iõüo+6-_f®¨Z·VÞ÷/„ö½âì’µáë)å¼zY>¯Î9÷×9°"ÿ}îj./«abo™9)A'jÕiyÆeÕí•ÜÒþêõ7¯J[Z·scóîê4kœ´®¼hM^Bí–Ê-\±ùŽÑæxQƒtlÀóJIý¶Ê¤%¹kÚÊ=áãë*ûL…Y%«—`ÿɾ3WÆ…·°#qLÒÙ8oÁŠ8nŽ!GSÚAô£yC¯hÛ€}õñ‡²’²ùDiIÃ^yDu·`P½…Wá gÕzÐ8ëT3ÔXåSÜäc*üpý¿rrTo¥å,ÍXµš¾ü†,¬óZÂÕrß ߩȯ®Áª* ÉO‰¨oº¦ÌE‹fJ\!O,.Úz":^‘wâß/K¿¨‹_’O&¤_%'¯%‰©‰‹We1t."_HÚ’¤òóòFP’?9–”Ú”ÇÃ’šr ¹2Ÿv—,鯹U‘W“ŒšŒ‚’¹7ókAÉ*Qä?¯%ÙŸ_²-,9;–Ús½¹ÞeyŠ\¸Z¤±¼ÑüÇ–,è.<\Txµç^KJ4¥ëJ_’¥ìë+fˆ”?¼ò± ­!yŸHÅѫ䱰Tî¡òHXV}æ¦æ(ùåâRuºêôêæÕ/Ȳæ+a©~M–µ²¬kX×y•¼Ró¥Úçk_^(u_[¿o1Ù°bcyHžÛd ÉÙH1µ˜ž5W˜­/«ÿß ³ ó]ï6Î7ÝÛt¹¹§ùÅ–î–Ç[·¶~­­¨íÎÍ囿°%yËØ¹|fË¿Æ$&¾´çGÉaEžØš¹õÀÖC¾×¡íHêÈ긥ã'¯u¼±˜tævv„äPçmQòeYº„®Ý]gº^%r󪛧nþV·®;¹;»;¿»ŒÊǯ’_ÿyÒóÙžÏöÞÕû}u}ÏõßÑyÛG·go÷ìwÜ»ãí;_Ýõ©Ý†Ýî±ï9¿÷Í}wìûÅÀê§,±üfðk‚ÕbSÛ>a{Û¾×>dwÙ1tp˜î~cdlä%G¾ãñý®ý¿>pøÀôxÕ9<ºbô×—Üßô|ú#Þò{+¼øÔ¾D_¦/ÏWæ«ò­÷5ù:|Û|T>¯ï9Žÿ±G–||\ÿôDÙ„ŸÊ3“)“ÎÉ:´êÐÏoÙqË~ìÖ­·þàÖßúÚ­oÞzé{Dw$åHΑÂ#Æ#î•À‘ÀÑ^ȹ(y/°)&ÿ䨉•Óǘʞʟ*›:<5=ubê4äÈÃSŸŸzlêkgoÛyÛàmûoûÚmÏN×Nß“˜Ä$&1‰ÉÿHywúÝÛ§ /ÞÑyᣛ?:y÷£ïÎÜ2syæòñnÈù;÷Üù…»î:“˜Ä$&1‰ILbò7-ÿ+&1‰ILb“˜Ä$&!ùå é„ïÄÛw×Ü}ï=Ì=kî¹ÿ¤êC¤ó䉓?›í›ýÔì»§ö:uê­í¢rˆÊ}1‰ILb“˜Ä$&1‰ILb“˜ü1B¯d%—Oþ#Rä ´…§ÿ.`­ñôÓL¾¤”y¦@xJ) cTL¦ðªRVG´k˜ƒÂ*e‘)SQÊZFÒL)ew&4^ÏôkRÊqL™æ’RŽOP‹A=gzIðßH`ÅôÓJ™e4(eŽÑd¾®”y&3óm¥,DŒQ1qYz¥¬Žh×0uYJYdÒÒ?¥”µŒ!«[)ëØ®Ðx=³"kP)Ç1iYw+åx ŸõRN`ª¥¿‡&,ù¿*¹d•G)Ëœå²ÌY.Ëœå²1Fæ,—Õí2g¹,s–Ë2g¹,s–Ë2g¹,s–Ëñ ™Ò+JYæü(#171•Ì*¦¥­Œƒ±2^ÆÍøð5ÄøÑÖ€’—ñÐï´8Pr1Fô˜'DbºÑ6ÌŒ ÏGkvü´côA|·ad<ÓŠÒ ZìÌ8Ftb6;æèe&iIbÚ1ó$æ£+:Q¦šHørcÌ$î ®!…t®dªÈïl†jk™rº¾3x0Vº¬Cæ°2”±›QA+éƒ~¾=½hwPœ×Ôgˆr˜zÔÑCZ-”B´òê>ÌjQü•ì˜Gi®2Šyœ”GÑÒ…–Qºª<§’ k@VôP[䨲•uwR¯!ž0¢x.Ñjc-XßOk.º×A¿–™É«ÈûèRìrS¶ƒtdXãH‹µ zŸlõÔ4v#w³˜Î6Jg˜¤Æ”(äô>—âÉÄ~y_¼Ô‚>j§{M<ײFÖqXãCí2»VÈ;t0´Kê#$F£ì f+4±Ðõ­ÊúFš]†é^‘ž«óUíUV÷+žôüj̲ŠYwO÷Ó5mÔÉ*B{ŽÌ«óä°âמÐhâ¹òŽ»0ÞN}ç¿&ßêb÷o&ã¶C+SB£¬Té—˜ênª™âgW@Æ©i–ö£âo(ORÿ¦Döe­$††¨.Äo¢guRˆáÁùóQõsµ]¦¼ìêJ^Î4“”´LÆÚíàè`^°*¹›Dy9e@Æy¯ˆÌÓÊÕ¥äy»R·(9ÙN3ŠƒZ(k7HõîòÂó+wÈþ㽪e(dCù eùT°Q¦~åô‘ãS^·<´ÎB ä,:N9Yi<-Æl\±ÔA#ÍIcJŽü«Ù“{ä“¥ãK£ûéÎY£ÎÉ…„OÅ…zÕEø±D¶E~ZæJoèÉÃFÏ^Í#–kZ*ûž%Ê«ä|àV¾ËVÉå1/r~²ÑsÌ¡äy2ÒI³ÿµ}TÎâ.eg³#ÄñT1BóCáL²z<Í—vņàFr´W—ӱв >_-Ìs #¡dA^°Ó<=NŸ(t÷É®ZÐF Ó|$÷U(sî[;K•è g‹ðÓ@P›?ætºÁÓ@ÊY0G{piiÈ›÷£MÞ§ ×ÈO'Nå {÷õN¸ W^û”#;׊_ijˆ¼ß²Ø•µä¬íRö½œÚìUNŸàs…ü\4¬ìsÐe¿ò(Ï;ò núÜm¡v=Å„Où…ù쯰!Bj;áæPr½M‰U«ò¬í¢ºFž™ú4©èxí½E¹'úœÇn—F0²E¼BˆŒ‡ž ¿ª Ž^<»•/ÈnAö ïvÒWŽvõ ?ƒ…£&|÷°œ ¾:#¯Â‚u{„‡xèë/'õ·‘ˆVÖzêbWNª±Ð^Fæy+”÷Ñ(q†tÆu´/Ý8ÕÈ^¶2ò¤‰öé0‰qÊqôOÜÇài0F_]ÊdìØèw²f˜Ë~Œ°Fœþëäc9óÛ¨Á¯6*‹[0£›fœÅŸº]ôŒž2‘¯Ï‚çÄb9%ú.Íò^ *v/~æZ®±£Þõ>ê¥.:»EW¿òýS= x¾µ2M´·“iFmNËnÚÒ†6 Y´=ý¨5¢µ-ÅÑ£ôÓÚFÏ¡VŒë£gœe§¯æB¨›)¢WOhåkÍLbó/õ*4üú²‚æò7†òß¼éó‡™xTº©rUµ´Õaõº}î!¿ÔàözÜ^‹ßáv%³Ó)u;†Gü>©Ûî³{ÚmÆøVû ×>.uzì®ÞI]j·LºÇü’Ó=ì°JV·gÒKîÈÌ•URù±¶\ê¶8=#R«Åeu[ u³{Ä%µŽÙ|dÞ‡OrFÎ3äöJõŽA§ÃjqJÊŠãÆ¢’Ï=æµÚ%¢î¸Åk—Æ\6»WòØ¥­m½R»Ãjwùìu’Ïn—죃v›Ín“œr«d³û¬^‡‡˜G×°Ùý‡Ógl°8ƒ^YÃ"º1!Ö±¸|˜Åë’†,£ç¤4îðH¾±A¿Ó.yÝX×á†Rê·âN— ¼.»×g”ÚüÒÝâóÚ}’×+~¬aõ•K¾Q ¸Z-”É-£cN¿Ãƒ)]c£v/Fúì~:OòxÝØ ¢-fw:ÝãÒàJŽQÅê—.ÉOXC3Ü]XË=$ :†éÄòB~û„7;Ø’bf±Oµ¸&%ë¶TÖ›às²×[¼!j·ŒJc² fF‹ÏqÃýnt˜d‘°£òZÄy¬#/³{Ýöá1§Åò«ÚàÒµÄÖôÙ‚jãªuQèý^‹Í>jñ vÐ- yæ0ˆ{H³Õ ó]»ÏØ>f-±øJ±‹R‹×íöøýžÚŠŠññqãhð>#†Wø'=îa¯Å32Yaõ¹]~Ÿ2Ô9fµøh^Ì7æñ8pÒg”v¸Ç@lRƒ ù‰³’fŠ­õÛË%›ÃçËêñ:ÐkÅ;~Z°vï¨ÃïÇtƒ“Ôª ;üÆí †È åWÛ?°YýåÄâÞrrOpìÏøˆÃ:¡Ù8u¸¬Î1ø~X{· žRâ(•Ã"b8f¸ž¶rÁ×±ï>¿×a•2¸õÃà\u”@‰« &H*ñ’ȱ¹Ç]N·ÅMÏ"£‚gÁl)Œù=È6;1“Œ±;=ÑD‘—à»òp²!'#ŽA‡Ÿä§ø^¨<ä&ÑBTVP—Kƒtu»B™"¸ %Š/Ø]ÆqLJÇnsXŒnïp©U`ä>%§”b{©[Ð Ó,žK^ßWF´“/Ìûݰ‰ A,9‘Ø(îè4IPF%Êøø.²9><°ì¸ ® 2¶riÈ‹¤GB8 › c°ÂŽâvÉ=ˆdç"P,4QýìÆ­ Y|>·Õa!þas[‘²\~‹œON)!3FY+õ(™úÅRª‘fCyGó,iŽp·rÅ݈öÁn§~*¯MæòÊ'V AD,,'¹Ü1D~Ú)Ï òЀÅÔƒc$x}¤QñXXÃ}v’¢Ý‡œQ¯©ªðXR…4Ub|Ä=zIŒy]PÆN'°¹‘C©.ûíVÐÁÂ~ ç·9hàÕÊ.nt´G¸.·Ÿ„ŒœÌJËž¢tùFÈy0hŠ\K„¡^²¼Ïgr`‹B'Ïõxkm’z:›{·™»›¤¶©«»³¿­±©Q*6÷ ^\.mkëmíìë•0¢ÛÜÑ»Cêl–Ì;¤-måRÓö®î¦ž©³[jÛÚÕÞÖ„¶¶Ž†ö¾Æ¶Ž©÷utâ\oC$bÒÞN‰,¨LÕÖÔC&ÛÚÔÝЊª¹¾­½­wG¹ÔÜÖÛAælƤf©ËÜÝÛÖÐ×nî–ºúº»:{š°|#¦íhëhîÆ*M[›:zqäv MjêGEêi5··Ó¥Ì}о›ê×ÐÙµ£»­¥µWjílolBc}43×·7ÉKÁ¨†vsÛÖr©Ñ¼ÕÜÒDïêÄ,Ýt˜¢Ý¶Ö&Ú„õÌøÓÐÛÖÙAÌhèìèíFµVv÷†nÝÖÖÓT.™»ÛzæîNLOpâŽN: îëh’g!¨¥¨ÁRïëi ëÒØdnÇ\=äæÈÁÆø9BéyYa³Yðäb´ø<±7.bo\ülco\üõÞ¸Ðѯ؛›o^È»{#öFì ŒØ ³yìMŒè71‚tbodÄÞȈ½‘ñßï ]ðw p]Édî`»8å·¶_6úÛ×»¡).ŽÅîÄŽ'ãù‹7:>1‘ŒWõÞèxƒŒWŸ¿ÑñIId¼˜s£ãSR0?ò[/ે~Oèd&›ÉD*ËaV3EØ€blM9³ Gð³É´‘™Â–œDÚzô(³“y‚ÙË<ƒdþFü‰ø7H­ï1“lsˆÍb9¶ˆMdW±v#›Í¶±¹l?[ÂZØ.ÖÅîdoa÷°3¬“½—u³±cìÙƒì“ì­ì7Ùãì ì]ìÙìoØYöö“Ã>Îűs\û4—Ï~‹«b¿ÍmdŸç¶ð›¹~¾³òýÜ~7ÁoçnãwrÇù]Ü)~/w?¿{wrò^î«ü!îüî›üQî|€û9Œ{‹¿‡gùûx=ÿ>…—øßñ+ù7øZþM¾…¿È÷ò¿ç-ü[¼‹›¿…ÿ?ÿÃßË¿Ç?Ä_â?Ç¿Ï?&Ôð_6ðÿ,4ò?šøŸÀ?~͘ýO`|? ÆgÁø)0~Œ_ƈ_‚ñ[`|ŒSÁ8Œ`\Æ-`Ü Æ`|Œ'Áø0> Æ‚ñÁøë`ü0~ŒÆ¿ãKì,ǃq/ã"0^Æõ`¼Œw‚±Œ}`| Ï€ñßñý`ü ? ÆgÁø«`ü]0þ¿Æ¿ãwøc¼ ŒÓÀxƒñj06ƒqïã0ã)0> Æ€ñ£`üÏñ?ƒñÀø?Àø0¾·ÕF3Ö¼Á8Œ Á¸ ŒÍ`Ü Æ{ÀøO‚ñGÁø^0þ<? Æßã‚ñ/Àø-fÓùØÆÏ‚ñz0Þ ÆÛÁØÆ>0> Æ÷€ñ'ÁøQ0>Æßã—Àø`ü6{S³·rÉìq.—½‹[ÉžàÖƒq+÷‚ñ »Àøß Æ÷ƒñ#`ü?ÆÏƒñÀø50þ¿ ÆWø}¼È;ù$ÞË/çñ¥ü¾‚? ޾Œm`<ÆGÁxŒ?ƃñ90žããã߀ñ%þ‚$Sù÷„|þ’Pο/T 5‚IØ ì»Ð$¸Áx2šqœ+‚q—€ñZ0nã>0&/É{ÄS`| ŒÏ€ñWÁø;`ü30¾ÆWØŽ°KÁ¸Œ›Àx/‚ña0žãO€ñÃ`üÏñ `üS0~Œ?`Ý\<;Æ-ãJ0^Æ­`¼ Œ‡ÀØ ÆGÀøŒ㯀ñ3`ü}0þ ¿ÆïñÛà—ÛÁs'Ÿ /Ìã÷òe`\ÆëÁ¸Œ{Áx'ˆŽ‚qŒÿŒÿŸã'Áø»`ü2ÿ Œßå/ *þ÷`ú–°œ[¸ ŒÍ`ÜÆûÀøƒñm`ü?Æñ\4ã$cã%`¼ŒëÀx ïã`|?ÆgÁøi0þwô¾Çlc“™l>³—½ ŒëÁ¸ŒGÁxŒ?ÆOñ¿€ñ+`ü:¿Ïær:¶9µ‹+awrëØ=\ë䶃±ŒñI0~Œ㯂ñwÁø‡`üs0~ Œ¯°Oóqì·ø<öÛ¼‘}žßÈoæ·ð}ün¾Ÿ·ƒ±Œâ #óŸãÏ€ñçÁø`üM0~Œ ÂoóÇ °„¿O(â¿"T况øß ü`ø¦àã£`|Œ? Æ_ão€ñ÷Àø§`ü[0~O¨QñÂU®Ð¨*šTÕ8룧{"/c#oã0žã;ÁøÀøY0~ Œ_cšXžÙÂâAˆÝÆ`|ŒƒñÝ`üY0þ6ÿŒßa9Ä}"'±î&6›3q7€±Œoã{ÁøÀø«`ü¿ ÆÁxž½‹OdOð; –Ÿä׳óí쿌?Æ3`üq0þ2? Æ/‚ñÁø 0¾Ìïx~—Ïï2ø}BïVð^øà!¡…?"tðG+&Àøn0~ŒÿŒÏƒñK`ü¿Ç¿©ù‹ª,þ÷ªjþ-U ÿ¶j;ÿ•ƒGuˆOuIuÿ¾ê3`üE0~ŒÆ¿ãwÉó—¨Áƒ¡¤¤ñðÔ”¨bEÍ…ÙÙ‹333IEí™ àšñˆjV/ÎLãB€ž‹þ¢*:l]c ðÀtã:ZÁ —É]"ËŠB@¹èÔ3³gæÎÌÎΈ"+êžyæïqÝ?½çÙg~øôé'hebš^ôª˜2†Vfgf¨³“d˜UŒ¨¾$ÉWPybéÔTccI‰Á êQ?-MK›M›M7C¤€íqïtkkeekë4hf¦«‹L¤V±jÍEqbf†ê¡¹3duµÀªUb’‡¶‹dÑñž™KÀ„(0¢Piºh"©Õ³³ 3}é;䙣ð!ЙÙ(rj‘Uëžøîq\t ùfe9\D µFVŽbRkdDQͳjá‚< ÔV{s•† Ѳv•t2ú#j£VÉÖ«µŒZ;˜ ôáÄȇÈ}èéšÃÃL&²€ê :3O‚Rë?"îµJÜk•¸×*q¯ý°¸×ãÞPÜ#Þi=øh¦õPäæäº)2öµ¡Ø×.ûðºp죎}ÚŒ}¹¢Ä>*áØG%û$ÎB±OzB±/¯ã õc_Å1:û&Ïè„9Œ¾ ” ¢áoa>ÆœÆsžI ŠÑ¨%šMZ-£ÕŠL*„쪙9JP«fµ"Qíbç’VƒÚúzJ­~=©i/M“¸œBñáK9„k—è,d$¹ïž©)å>rÓ<ùíÒt½i97ÌLku¬6n׃¦M£r¢Y­îé95ÑÜD§å&ƒâÂa„¤^ÍêI"‰ÌN%;Ñ>añô¤'.€ôÊOô!I#€GÊÃÑÓ.LPz«' *˜¡ô,«ØŠ¿RŠ"–MÐSàâ_;EéYNLQtŽÒs”>˜£ô9G‘Âõr”ÈÌ‹WxV‘£Hn¢Má$E:iSD–Bž’›¤ˆëõ"2•œªô4UQßÊÏÏ¿’ßx¥±±‘ú¹ò²œì‡ŠÓ‰R([)½TYÉt9TÀæ(§Xf(aÑêaØѻޤø\ ¥,Sh݉éPïâE ÏÄ ŠxQ‡lEnº,“s꺹KTr—†¼ˆ°2Z&Tõ:F¯‹c’©äAL£èj ˜ôV¯„:Mazõ\‹¼!&K.©ë.Ý!'±©;.ÑX!ILÉbáúe9Z´¬^¿Œ˜øsRž'0XÆÐ®ð^‰ØÎ…1Eµš =cMéãY}â\æ\æ™’3%³­³­ä¬¹]¼]œé¬s3YÈL`29&ë’ÃX£žõF1›>†$u9ãMQ³&¦¡z¥H¶W¯aô9ϰÀ–ðä™ÿ_Ü•BÕõÿ™13ÌÌ5&#¦ì[$tǾYCÑj$K"k“G‰J+êITR©l-Z†©¤I¥"K¥TJ¨Tâwî[½½ïû¼¼¿÷žpÎ÷œ{–ïòùžï™¹7”ÙkÁ?¶"Ên„íHè28`Òói‚¤Ž¬§€fE³¢)2±ÇEæÆF£AÁØcgKþ@ÂXˆ$À.d[X[õSLŒÖâÀeb‡ÔÚ™ŒE¿*‚ZÐ/£IXD”Ad9É¿tÎáÜÐ7!"Bs\P M•#[„‚¡^äòÒ¦$4Xïò§È™2Yƒ"$ZŸ;X?A${,Ü@¼pJÈæÈÊjH°#´WÁ`ш‰ü6œGJA´`#€JÊÔæÀÇ`’ì!‹ƒˆËÃLAKäp†`5,‚Ћ!°á⼄ÆñÇKh/!/©ÂH‡GÌ1À$Œ¦˜BÓjl §€ÒÐÜ8bZ±QZÇOÊÙ! MÅL4¡IЄ„Фˆ…CAS€š¨qD4.% v˳…´ŸäƒG€s² ‡ƃ` $!¡bk›6 Э@'­GÊìœìdŒ€ãÛ ~MÎQ üÀOÑIüÄŠ'ðSGð“BÁP («-ì ÌVb¹d²‚¸‚’Â<îßAPˆ‚(T #&&›Éöån[.d׉`!ò0ŸÏ¯æóx<þ0DyLÛÃ’|E‘±4‚á±kØÜ)W ›ÇÁ 7‚”‡QêÈ$aDн]že%èûÆØí¾Ü(®<­œìstê\T÷'2o¿¡¡¥¯¥¥ÏçAT,Dëéé3kÔlYÓ²æ¦SCCmÖ,ăо;¸}ÜFn H ñAºÎåqk¸ ‰ÊcÖŽqd<ùr×rÁŠüAY#áÏ0†á¡‰Aò‚R ]±‹Ë툗¡‰ ñ"2&¯_V9yù±-1¨¤c# ‘”@fˆô 1,4­†XCä¥dd±X -zÞfñ ˜ ØÁc±Ì 3‹ÇƒÈ£ÉíÇÖÅ I$h"¡Áx2ŸHLáóï®ÁŠ’‘)´vó«»UpÁBçÅ2Cë…ÀeŒÖ›"G`™|>«¿™(¨ª™¯¯ïïØ!õRñ“¹)àŽ”_‡àñDqXQ<—‹ÁL0@T+JB2| Ó¾–†þX›) Â’ÄZ;^ÁüŸzD1ѵàÀ‚…æYfДºîVæÈKËBƒ²–Žñ!#øZD‚PV<²&N®Ìí{lÀä9[ À É$HTðQ»Fpn`®^™Y„bè1*"DBÐïïe€cÐI C  TaX‡¢ü€e!,ŽæÃE‚`È¡ß[A Àe’c1oÿI@Û‹€~ rhCà·ˆ«¡¡ Œa±X [¦ c¨ÂD"¡0¸–\,K öaI˜Ò(›†“€>f½¾¾0JDscRû~Öò>þéêÁˆ’ËF£Ë M" È8‘›Qt3b Ò(Ûý‹*ü˜Çå ‘â[Æ m%$ó€Á‚#' D3" ò“QS¦ËÌŸ…aaì€!²‰$¡­S¡'µFr¨@ø“#Ž‚Þ‰c욘 ØX 4`‰Ìb슩„¨2tÕá©Ä„Wܾñ<à_a!j”Âï30Ñ|‰F¢M£)Ò¬:HHtK|ZÂA4ù4‡–ÐBA`ü{Nêà¸&"x,/³N·Eòó¢ýü5l¢×h*,ˆ ÓDŸ=ÔTpò‹‰øWuhÿXt ð#{ü• '{ æÈ&’4ÒíÓ¿ˆb…qÙÝ€´ì%˜˜D$Ì¡ áf0°‘<‡ô‹cˆÃâ <àE°æŠÌa9¶ Æ M®è·[#Ñï›#߆¶@¬8¥3¼D)öÞe§øAe^j“§§½+¾]ôF‡sð<˜#TR „Ãâpt]0Å3ï,OŸÏ¼¨Õ„Nø ,:1[°_ÁÀqè4…ã‰tÜb&ž†Dèd/¿u!¡Á1‘LLEˆÂta÷ ÀðȈ@¦,ƒPÈôé¿}¼Ÿ©Ë#õBtÆd½ghx–GŒ_x”‚›ÍYnÎ}¾>|ÅT¹$ÞÝOÿ]uíY=Õ­¯Eî‰ñ5[¾Ó_ï|òž9ð-¸+|ÆöÛ®ï[C­v7uii,ÒÚtm‰qÃ¥§û^Jwú7sUu©O=¬Ü±·[ e¥n­Á>š•®è6óÙl–Áƒ†·R•ëîzǼyÞŸcf'SüA'ìèK!À²€¥²T¼$^BÆ(ºiÙ®Kó2.Íû¤è{˜·'ªC²Êx,É–PÖzìnEîµú¾þ{åœ2ž~¥ì‰4Ç;ÃŽ°CÁ‚‚ùé6cÏD¯ùåè°P„:wìq÷us'ĈH"ÐJmÐö&ŠÃ$·Å;Á aûñ2ŒK7û§1¢Eÿ‹žc`:2_U<“Ç»ùÅ …-ÁÌ(_rËóÞR·û2+e&ô¬h6R²Š¾þÖöðÎÒdSLݪŒÜÕ&õ-’òfóÜJóF ËÓîÚì3ݣˋSw4‹I%†íØåým[]ú¥õEŽ;Ÿß,ˆjT~ÜŸ=]Ün²Ô¿Ouø|…æZg…÷Ü=}/ýýÏ6TÜÊ|’×ÓüX\Sô³Åq®ÏìYÙ†7l ê–t<èJ,ÑÛqêQ*‰]«ÓgÖü)eD=×Pî\ò¹õ±ïëGûOY+àÌ=·¸Sg*Á¢0€±#ûI†è¡è%ó+zù °@&íš•±»_3;CRÈ‚9–ú‰HšS ž#°c•I;vŒ dÊ ð‹ R˜“€ lëXÒÑ×…Jé0Ñ¢.Œÿwðùï€æPášòö§ö»4’ôgt^íz^—·HÙíôÝ6†‹ŠØû{Å÷œNÇÀ ÓÞ ?ðÜ;Ýa´õ®3¹+àYO0a¯“®¾ËûBÅçöe4ÈßÖUÙ|°0XFs8éÕÙ7¯\ŽÖ({Ôoû6ÿ/RãªÒÆ2küá¯ÇÖì~¤ÞjçQ–ÞøRÝN[íTºëbwè…æ÷ÕÙÙpÄæ¥ðÁo)s*_+æ¤ 5ÑD.x„»ŸŸ}ȳpkšÚlÖñœ÷‰© M+ž¶@‚Ä9”Ö»8~»_ÖMä ¶ë½ðLÙîr­–ç¡R¹øy̸†í¦›vúáÎÉŠ–9P½«äè9ú•À»®@šÀ‘bX 1<:;Š'ÀBàÏäù-° >BV ú—Óˆ¤1G=‹P0pj®™R³áÔml ê)ޝÕµœ—ªôaN²ÇÞ¥/Žõû¯«'‡–pZ²paAÑi§uÞƒÂtí ØM‰ðx~MÁ¼tË¿‰ÕÈ O,CáÐs ÚÃv°í84úOàY‡ ×¿ …€×´œ­¼B¶m=gOÇ=½›°È[®³vy8D/¹{-iG•v³øá¬pÿ*/Ümº[^[¢U—×åRïý2²ØôS—ãû3ß™bßw]ÛA&ÜÜfßÕç1½Íµd׋WÛV?`×tïé'ÎýC¨g§†ŠRÔ÷ÏÃ/âó´E¿wE]a¸ÜFŽÞ[Uhüg°VÝ"êÿ–’¹™ –]Â3u¾60®gšÏ‰¦Ü|e>ú™Þ~ì·½ïQ•Ô[—ÌuúsV©~{eÅ:©Ù#Zñ=\9>hÅr¬Y‚ÚôD"÷“ÙE–w¥ÖÜW_ÿHoX´äõÁ¨=kN;5N¨>ÉHôŸýáðÙzĸ™þ·ÌåÂå9}”š—ÿ²©|ùõ݆sÏѯr©[«,>k=ÅÌ=kí2;‰+••eÎÁ7Y²ÙùÓaÖkkñU3oæ+)6ÚôÌé¹!pªÖP€OHù¯@²:#êìƒüÒ‚ µ`#ÔøMñ‹aÇNñóÿíãá_ CÎc~±nÔ'lé‚mdÛVœÉ2ýCåÜA«‡WY§–{é?|mŸGs~z6ûÅíõ‹RI}•»?‰¿¸j¯&q2RëQئf~qÂð}Ui»úõ¸-:gÜ<¿ }å`ë2+ ^–H˜B¼ûýì*3Õߊ¾Å[õ´ÞF\Ñ¿vEå+·íUí!%7 ¹†Cgo©c?/?_-¢§W|ÚTé{œÔ4Ç0SÏè¢×~ÖÙ;²ª®È¼:¹OæÐt¦™œ· Éì(É_^—òðGãÞÛ®—žè^Ìþ’U@ídí=ž÷¿gAìƒK9¶ùänÛ­ÿ©õ¯9A‘ïê<’ƒŽÄ*îX¡ui·õ€×‰#Ó ÕU]°] ÆÌŠ©ÍèJ¬õ9ÊéˆÊl¥«9¼ÎnUþÎ]‹:…=P:_]eŽÂ§S°)ü¯RM”sÉæ¸ýñå²ÄbóÂÙRÒ÷2?ŸéÅ^ÒËö°—¼ƒ÷·ûHNy‰ïÔH“Ø}ëHÓë9ÏUw–‰98_<éE}ÿùvê‹®\|h—øèÍû§/ǶÏÿúÑQÿÖƒÔaÛ­D7‘1·R’/ØŸ uãäMCÛÀXú*ŒY\è6G¤°ÍhPÔ£•í¶··õ-=.v„8v;w#]á‘ÓÐ`EÏ;–oÜËý!¥YReês%¨³"DïpûÚ⻡~ÅR­o`˜#œsþãá5[p¸!ô«+HÝò_Z`ë쿳I›ô LJ7 o,$ Ð"FŠÿs¯ÅÁý£?À!þü°¹’¾oÑ4íÓ-'94g½Kýç½YKk„õ,s;YE4š‰w¸´‘ɵ†ñÅ[(}F×óˆe7`%˜Ö÷3D7§ìñUYSšïðgOȪ¦ödM^éãsÎ$’Jí[Zï;“ÐÃZÿZÇ}–øÜW%"nUÚ^XÙR«-[2p;|ÀdE¡ä Ý¥£ÀSúñÇ Ä´î[ízþLXôÁŠ„"‡Ù¯D¯Ðã®í1ÿðýùœe4yç%ꇣ;ÄM.8¬jéíµÙ¹éqRERºôc‹ò¬•¯3\ÓföÎ]ú"ÛT댮wÝ‹û•Bæå¥»ŒRš²5?¹,Ù©¨¯Ê3ŽÜèqéO±Ó3”Ón^Jßöŧ¯Ñ½:kÏæ+\ÅU†úù5u#Õ\ã…%—ï:#£\|‚õÎO~u§ºÃAŸ-]ª+ï+:Z¸×žó²Tê»—¸|îåçQ+ÅÙÅUa:¯œÂq|žr§W^•n^ìøÊ¸P¬GÙá £Ê6yþ‹^tbGô+•öj»¼º×e¼žnÚöÎÙ..ÙÞþnù¡Òá¶2VWMNjRïÃ^ÇW³‹éêÇŠ7³»·úÇûTÌM{äõçŠê8uõ½á<õš;¬ ]k:ÿ°Í¨%9Õ5ÙÌÙû%b(^Á[“¾Òwï~ WÝ´'e[¤žå» î+»bW°&·©ãá–¬‰xªøÃžß„D“ð·ÎhÆÄ 8<$GÆx OñÛ`æýkýC 6ÕÍEk™à˜Ù6%.oŠo0ï)gèÁËn9Qu-p.pLwøÎ€€Ý«Æ:á‰|`]ÔÙ­šâìÜa7Øeг³þ{¡Ï¿è?N=„L^Ÿš§îSwN0I[laËñápXIÝç[#Ö•…†ûE'D­Ó‰ ‡­&:ÀÁzr: ²' òÿî /LðA_˜ xÁF(­{õGÐÄ P´dç}ƒûÓ‹r;<fjßo‰ V:@Ù7­3`Wžõ¾ M PvM¶¦Å/ú^ø¦‘k–¯Éõ¦Õ N}P­¤_”³2(-{C¦ÛâhWrÓLG™3ëL÷ƲaÏ-„µgè6—.j>'·Ç¸«'ð–­y|¢ò}ñì˜MÛoÏÂÙi\ßJ»|ô:Ðò-D{o†¥F˜·C€<)4bYî¾›¹;ìæ<6m¼ªÿ!BõÌËRµÞƶjižzN®3ÕœÒ/’ñPž§Ãèê«Óº»<ÿ¬ƒ1™O¾Î?}æeÅã§Ó·,šïm¤³VmæÆòAµ¡gš& ¡¹K3B""‹/Äð¬ÄcX u Ž%Ý™EáV:êܱQ&rú†ùÅë_Ziá­t÷OçÉ䤷?ê—,ܯÖy§(§ñýÊ€yÏ— ÿ¹Ù‚G¼G,•—¸æçw®¯•/¿Ö>ïUýý³ ¹ïr>®Ø×‚yXhwué@NÉÑž–Ç–oÄÌ®+?Pd9?NNŸßtøð¡ÄD¥oö{åK¾/Pfʪ»à˜Óõ66~æ»7†y Çч•Ê!±Ý¥ß†3ßRØoBMK‡á^¼ÓöööØð€æ÷.qq­f{)ÆOÓQLü0\nùýxÃÑ•5…[x­]âb?Ÿk}ëÀúåd¶}Ø„C5WÃÃWßr_GMt»ÃäàË`þ‹…S÷þ¯×ïCÂÉÏJ RkðSb’šúA ˜Åd‰Â¤ÂSk§ÃÊ“7â™ÚêƒW­øÓPér7ûAÇÉ}Ó+7ùÅÁSn˜K`Ï ¶úoßËæù¯R.œÅVù§–í9ù^¼_|3žƒÅ(e'=Øhä,·p|ÃÞÐg[¦Ýw;ždéìä;ÒyÙ»>änÈ£áA©Ê‹â~!nÉâ½Ð2*þ²«ö·ƒvªš #¯ÆÒ§#ý-ó},ƾkàáâ'…I¦uÄĘ̂.,ªl6al2ó¦.5÷êQ÷^ªq<3ãóe¹Æej?’Ÿ­eåOßÐ{Ð5õ,KAÉîq“ƒzþ»…=PmxÛÓ.úêUñŒK,M*Œ¸saË=–5ïr%Ò8¼Ú¼ vN ÙЫ^™s$Ú–·;c\)%­ô=OàÕ® Ÿ‹Ù©]}Àißöò彯ÕB<,EiAAúÊï‹Nß{°[.âFÿ»Ì£3l+äàÔÁöDeRFD&7¦¡ª¹ýv8ûûÞ¦èäJ˜1U%)“ bÁà5¦ú!™1ò"m]cäS±_5²éÖü|%»è¶Sì“oÂsòÒŽßþå Ñ#BvÇcÒ‘7*ƒ7ÿ¼ýαàðz)Cêó…GµOØl2õŒLö¼õ)iNÍ¿ðˆ6!õ8¾!…pu×µ>Åz#Ê£‡Ÿ¿6sÃf_ 9=G*¥\™Ÿ/Ù¬l.¹!®î‹¤Z¡jYÞðQMœÃ¹°àæ@Õ©= .Í¥\÷tç;Ÿ/Þ–±”×^"G%…H„\¤‡¸Ÿ&¦l¯ê^Rz5úYi‹çð 󵄮5gJ›’¬ÿº¥vˆ'¡û!˜xêµ±‹JÛ_UbËCu…ƒFs?È´ï—‘ P˜‡Ãzú‹ô…“­V‘xXµ9ÖÃè#Iö¥†}È‰Ý ªDÒ²àhK‘}:’¸Ë×îÜÚl_­ÎÆ`þuQî endstream endobj 502 0 obj [ 0[ 507] 3[ 226 579] 17[ 544 533] 24[ 615] 28[ 488] 38[ 459 631] 44[ 623] 47[ 252] 60[ 520] 68[ 855 646] 75[ 662] 87[ 517] 90[ 543] 94[ 459] 100[ 487] 104[ 642] 115[ 567 890] 121[ 519 487] 258[ 479] 271[ 525 423] 282[ 525] 286[ 498] 296[ 305] 336[ 471] 346[ 525] 349[ 230] 364[ 455] 367[ 230] 373[ 799 525] 381[ 527] 393[ 525] 395[ 525 349] 400[ 391] 410[ 335] 437[ 525] 448[ 452 715] 454[ 433 453] 460[ 395] 853[ 250 268 268 252] 858[ 250 250] 862[ 418 418] 876[ 386] 882[ 306] 890[ 498] 894[ 303 303 307 307] 910[ 498] 951[ 498] 1004[ 507 507 507 507 507 507 507 507 507 507] 1081[ 715] 1085[ 498] 1092[ 498 498] ] endobj 503 0 obj [ 226 0 0 0 0 715 0 0 303 303 498 498 250 306 252 386 507 507 507 507 507 507 507 507 507 507 268 268 498 0 498 0 0 579 544 533 615 488 459 631 623 252 0 520 0 855 646 0 517 0 543 459 487 642 567 890 519 487 0 307 0 307 0 498 0 479 525 423 525 498 305 471 525 230 0 455 230 799 525 527 525 525 349 391 335 525 452 715 433 453 395] endobj 504 0 obj [ 226 0 0 0 0 0 0 0 0 0 0 0 0 306 252 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 522 0 488 0 0 0 0 0 0 420 0 0 0 517 664 0 452 487 0 0 0 0 0 0 0 0 0 0 498 0 514 0 416 514 478 0 514 514 230 0 455 230 791 514 513 514 0 343 389 335 514 446 0 433 447] endobj 505 0 obj <> stream xœì} x”ÕÕÿ¹ï;û–Ùg’I23& “ ! ŒÙØ!!M@ ;AÖ»¸ÕWܵØ:Pîµ­RmkÕÚªØöëf£b톒ùŸûž™@Pìc¿öû?9™ûþî=÷œsÏ=w}'D€2hª*¯¬o L€M¿@ëª*_X±ýïyÕÀòQàõ%uyS·œ÷n7Ãzhj]Û¼áÆ¶–“±¾¥uó&Ïþóü2@Ë!¹µcÃêµïM-ΨìÐg­îÚÒŽžXýÀ¦ÔÎöæ¶¿¬{ðc´§C{…ÈÐ?ìôa¹Ë“:×n:·Ûœù,ÿ tZ×úÖæ3”%hïWV_õÚæs7$÷›7`}'Ê{Ö¶ojž|_~°à}X®_×¼¶ý…Ý DϘR¼a}Ϧ¨.ÃþÜÂå7t·o¸äý!ÌÖ>`š<Š\«gÿß«fýUÀéÉ·½Êñ EÄxdÚÑW4VU! ÆD„z v@³ëÈ´#Z¬v+Œ"ý¹\ÆtÜ Fè5—hfb»qev-ÈA%ß)/@“©„âëp™*ä‚ È4‚ìh¢A˜tµ °¨Îãá9ÿ«äƒòN!Ïò:ñi¹‰÷­ŽyÃ^ƒ™d¹Ðs*râ á_oå›#qÅø~(Þ‚¥ßT²4²%¯îÚ¿WÖx~ýîý¦Úÿº$~}â_ÒÛ kÆãËÚaá¹>Xtª6eÁÙ'ð6ÜxžýùX~<ÂzÓ ~þt„Cãû¡P@µl TëÏNhú —Ƕõµ%»šÄßõU,Ù!Æê4Bߘ6/…í§ÜÞÜ8.ÿÕè;âù¸·}ÉR öTÛc¿~ìÇIY ¯ÂBùaª?Þ¾øÓSŸ ÿÍ„ý*?ž'ˆ>=Ž\Y<ÏÞ<–?LF¼J¿JFQe£Û;Á,þªöÇȧDÿÏ ÏŒµ+¦ày7Éï˾O°Û{"o\[’SüâÔä±ïNEŽ“xl—Nôuñ°ªNÂÛð Oƒx^¸ŠñÞ»X Ü#•o†]l%ì’-„]Â/1½‰²oÁf^Ç>Ár>\Ì~ObÝóÂ¥ð}Ig¬.ƒk¾Ž?ÿ—‰ýø?íÁMÐM‘pûN*³~ [ O”߆çÅÞ˜^ôgÀþ·Ÿ4A4A4A4A4A4A4AÿÍôuÞ«Gøø~-áÄ{õMÐMÐMÐMÐMÐMÐMÐMМØÎÿ´4A4A4Aôÿ‰±”LkÎ*±„9±d,Eà81§‡4È… ¨‚EP õ° š¡ÖÀØ [`|—MI™’RœRšô¨=FÏþW£Q© =ÚÈ‘4B ÔIš­°Άn8wD³è8Mý+W޾}+æª îŽ»ÍG[…aú‡éghíoZ>h~6õ¦¡ßœ K¤\Ì‚à—þ‡(Îo»Å(…J8a%´1#Kb©¬†-c+X[ÏzÙf¶}‹í`ײ[Ùcì9P°¿Iú‹µ}Œ±¿÷¯„ÇHŽx0®kÜ«S%3ðÑM¼?œxŸ€÷jÜ6¶¢è'õQê3â¨^céX¿½Ä^>e¯þS$þ;Œ²Ž‰ÕqŠ«‚—]º©§{ã†õëÖv}ÖšÎÕí-«V®8sù²Æ†P}ÝÒÚš%‹-\0ÞÜ9ÕU•å§ËJgÏšYR\4£pz^nNvfº’/Íí´šŒ z­F­R*ä2Q`]å«nò„ӛ²tßܹ9¼ìkFFó(FS؃¬ê±2aO“$æ+DÉŽã$ƒ$‘dFÏ,˜•“í©òyÂ+}žA¶¬¶óWUú=á!)¿HÊËÒ¥‚ ^/jxªœ•ž0kòT…«7wöW5U¢½­¦ÂWÑ®ÉɆ³ZÌ…3}Xf)“2BfUÉ€*=o6,ú«šÛÂ5µ U•.¯·QâA…d+¬¨+%[ž5Üg¸Ò3ý\ÿŽA#´4tm¾¶æ3Âb3*õ‹Uýý—‡Mp–¯2œµõ·Nìr{8ÛWYøÐØ‚¥# °°Üoôyúÿ è¼oèÏc9Í1ŽÂoü+ð,ïâH˜°>žô =Äþy½Ü—+ƒÐ‚…p_m•=ÐâŠ@0/КxÍsñ[ˆ×ôÅkFÔ›|^>TUM±ÏæNg¸¯Å““Ñ—>~ü`½',¦7µ´vrlnï÷UVRÜêÂÁJÌ›c}­ÈÏCùæ&ìĆچpžoCØê+'dxø¬©kTbjakEšZcZἪJî—§ª¿©’ä¶|µ û  zh`šÇµ§Wb#÷#l¯ÀAI¯êohë»›\m8?;< .o8؈ákô5´7òQòÃY‡°9¯Ô¢¤…};N:.Ì{®ô«< ‚Kl䣅 O5>|峰ˆÃ%ùˆ–Ïò40ÄŰ•˜ϱƒÑ_1—W‰\µb®ËÛè%ú—\1Ÿäþ°j”-#2F|¢vNêIs‡²¬RyŽT)Î=®z^¼ÚÇýêïoÑϧ²k€IyÅ•á%F_¸%àór?s²T óÖ7UàZ­ÆíÎWÝìÃ󤺿y0Ú×Ò? öo¨jê,ÁuÑï›×Öï«k˜å’œ_ڰݵ•·m†lA}9š |ÀÇ®¨²+ê–5ì3x®¨oˆL¨h*o˜„u û<¸ÿK\s9“<¼À--Å‚J’wí ôIµ2‰!•[H܈qÅ4€‹ÑZ¹IÏ`4Zßà=èjôâZ:Ó²†°:€‡›Ü?åæðÔ„ì9á¾Öf®Ò?¯µ×eÜ ŠÌ «Ñ‚:f%ª%¾ÞP©çZ³OÊ"·Ž¾Æpc€7Ú°¦QZ¯Æ0Ìõ•„édSžÎÊkì7û¦J›®uÿrjô êˆãÂ"6ÖHARêÐóVVµ6yhŽÔáZ¦ÃBã"N;îù²ôv)i\±JàÝýZ½&¬ÎEƒøáym.ßsä~ec#9/•. `ÛÆ°=JʘF«æq_ðs9ºÊEŸçfja©ï\Ü:¹Ó’%%V‡õþyÍxº‘¾9¾¢¸²Šo‚Ú˜ÄUòžë0î¸% FômñŽ"Ü;øéÇç¸öáB…ÆþãáåœlÕñ\½ÄîïWéÇW x©ô#(1+?ù„“æ›oþ€°8 !“°¾ÏÁÏ^qD\8^O[#—Bgk¤]ì¤Bl”? %ãýÆ™ñ‹•hûëÇ;GŠÕ<á5ПK·ìßeq–œå wᜌ‹ð±ðô{Œ¾HÊsxjÂáY8ñq¾ñåÒ×êihÁiŽ«›ú«ûùå´µ9°XKáu1&qE0œ6hˆw'ÜWãijô4ᥔÕ6x½.\‡ˆž¼¡úšù!PCý©Y&]Ršûùä¼£4ºÂJ<’:šÛ}^<;Â|ï¡èse±®þ~_XZ±Õ(ŒæÓqÁÍ〟 _s;¿\ÅíÈ–b‰ÃM¯…?ZûùÕ|ES#aê7÷{Šûqó]ç†,½õô&<¤øY䑆ºÙ…% Â<^jDC$¨ösAšüÜ›µJÿ1ŽôY a•d=[Ú®‰‹H+‰g6‚£+yçÙÒe ñJäÕó0¼AœU.®í õ ±á‘ôçqUW|ÀH 9Òé[Y~vEÍèSḛ́mÁÒå. ,VÆ¡øñt¦ÄÇE4 …­‘ÔR÷ °…àÜHªá‚͑Ԅ^‚M$ÒI‰ÐI…°‘`ÁúHêl„ukI¡‹àìHÊig¬‰¤”#tFR*Vt´´´’B )44QÝ*‚•‘ä*„g,'XFÐHÐ@pÁé!‚z‚¥µ5KG’+Qi!Á‚ùóæÌ!¨&¨"¨Œ¸æ!TD\óÊ N#F\ ÊJ#®…³ fÌ$(!¨#(&›E3ÈX!Át‚id³€`*éM!È'È#È%È!cÙ¤ ½ÉT—EIA’é~R˜Dà#½4’ôxÜ©)‘¤ÅÉ®HÒ„$‚D'Õ9ìÄ´X ,Tg&0ÓH¥1õ:-†@I¬APEk” 9ŒDD* Œ$`Q‚a‚£’û‚JŸ!ø'Á?þN𷈳ᯟEœõ!ø”à0Á'$ò1ÁGÄ"ø3Á‡"‘?üà÷T÷;‚ÿ!ø-ÁoHä×óÁûï¼qœŽð+‚_Fg ¼Cð b¾Mð1ß$ø9Á?#‘ŸRé'Tzà5bþ˜à Á«¯üˆ$Hðb¾LðÁ‹"vÜ—Ø÷#ö2„žØ—#1çÌ%˜1ã¹ÉªI¤Š˜•Ó„òˆ‰/ÊÓ"¦„`ÄÔˆP1-C(%˜1ñÙ:‹`&A AqÄ@(Š˜²fDLÅ…Ó#&ÞÐ4j¨€`jÄÄ#8… ?bâÌ#È%_r²É¥¹4™ ‹\Ê$È 'Ò ü“|¤F’^rÉCN¸©½T‚’L&p‘zA"“$vrÐF`%?-Ô™ÀDzF‚žDtTÒFŒ+4ãJuĸ AE $PÈIRF’"1FÁ(bå†búÓ瘎 øÌÿÓß0ýÓg -î¿`ú4¡Õ}8¡Íý ¦1}„iùÆô!Öý ËÄôL¿Çô;äÿ¦ßbþ7ˆ¿ÆôÊÂòû˜ÞÃô.¦_aú%¦w «Ý¿0tºßÆô¦71ýyo þ ÓO1ý˯#¾†éǘbzÓ+˜~„釘~ ?Ûý²¾Ëý’~²ûEÄúl÷÷‘÷æŸ×¯u£ÏéÏr?«_ã~Fßé~kžÒOq?‰i?¦}ºîA]·û ]ûqÝ&÷c˜öbÚƒåâÊ„1=Šé{˜¾‹éL»1}ÓÃÚóÝi·ºÔnq?€x¿v›û>ív÷½È¿Óݘvaº Ó˜îÀt;¦Û0ݪÍqïÄt‹æA÷ÍšûÝ7!ÞˆéL×cú¶¦Ó}æ"÷µšÛÜ×hîp_­¹Ë}òw`ºTô»/‹Ü³"÷E¡¾Ð…»ûB„¶‡Îß½=¤ÝδÛ]Ûl?oûîí¿Ü4+4ÛB[CçíÞÚ:'tîîsBû…oA‡pEpVhóîÞ¬×Ú»©Wü¬—íîe•½,¿— ÐkìõôŠºM¡îPÏîît×t÷u‡»e3Ã݇ºèfšÁès{º]©ÕˆÁmÝzcõÆÐúІÝëCë:Ö†ÎB×­uî^ê(j µïn µµ„š‹šB«ŠV„Vî^:³hYhùîe¡Æ¢†Ð(zQ}(´»>TWTZº»6´¤hqh1ò--ܽ 4¿hnhÞ9EÕ¡*ì<$“=É¢‘;°8=+Ïw]‡\Ÿ¸dà »žs‰æ„$w’•È*–$²õ‰$^“(&8_s AgVvu‚ã5ÇûŽ2KБ•[ v£Ýcm¼oöEõÕ–UN™.õÕm÷¥W'ØX‚Ímª>¶±Ë@dÆøïP=LT¡Ì^fsW‹O1þ›790ví@}] °`P]º ¬ªYfW„ýuü¬]V\†Ð²å Œ]Ý(}ë¶ò¯¥ò¥W]5`gåR¾ œR×wíJ)o\îãù`PÊGyP¤¤Â€Ê+{z{ ÁR˜™>1‰¶g¯…„–M‚ ØƒÛ ðGÔ  SfT'èÝz?¢zÑÔ#‡÷8CWS_ uk…P™v‰VjË*ªƒÚœüê±=—Z lZ‰•=›ÒK+Y//8›z6a™ÿôJe|)‘ª¤Mqæ¦/×ú?Kì?íÀ99WÑSy'Àðõc~[]gAôáÏep\ÏÂ/¡.ÆÜNØÀÆçá‡ðÖWþªÿkÐðùZЉO€,Ñ#Ñ¡á0 Ê £8×cÉ"óãDÑŽã}4|}Ô8<¨0ƒFÒÕ ?Eî_ØÑ行—£…¼,\ŽùIã°òÎáG‡ãÎ|Xõ‚Ó¥ßÖ/Řj ÁŠØ¿1hƒvè€ÕÐ k0^gC¬…u˜:`=l€Ð1ܽ°ó›b*Ÿ [`+láy° ó[ð¹UÊ`ä/Á‹Fðçb¸Ó%ø¼ .‡+à[ˆü9–7¶ÔWÂϫᚑü5ãryþZ¸Óuðmõ0 Žý­pÜ.q¯‡›àf©t܃õ7‘åuÇäï€;QjÜ’÷âìyð8Y.y<Oãœz žÁÙö,æ^€}˜Þ‡Cð[ø=üþȬÍOá3x £ßQç1ß =×àsõHÄÏÁØÆ#{>Fll6Çê(žIqŠ×ƒ’—ãh\4J§_§¸-.·5:^¼O¼GÇxÔÃëG8Çú=V‹äFÇllo•8ckìèüÝ'­¹îÇt>ù8_ŠçÂÎÓw`7<‚9z+Çsß…ïÁ£¸ Àx ‡'`p¤¼KÇê#'.3>?<)Í‚gá9iü¿$Þ³˜Û«}6V³_Ê¿/ã.ô ¼ áEœ;/Kéø1ΟÀOq×ú¼›AoJ3ÈÇð:üD–oË L.>/‹á\,¿%ìÄ‘ùoÁ€W îßÁÝC%Ì”vÞð¥†Çrì9vÕ¬Ó4læ’µ¶Tx7i še‚†B¬uéMjYm¥R¨‡²wß{wÅ{ïD<ÈòÞzsÈxôÍ!sqq^Þ¼bâ (DqgY*Ääó§42“×$%«AP* _Z®0cFaaAÁÔRaú´\Á—fÀ”>}Z©0£T,˜š*H¢$)qQ˜sÅw¾X..9ªÎsW­[•>¯u}~ƒ8eÚꥅò[4*A¦P<årøgV{K‚Ũ3È-v³Bi1kÓgÏ?z¥Ê‘äPj4JQ£v:í*µF¡3-Â;^OôÙy*Áí<Úû…íÂùÐàW¹PÞ”0 ¡ÇsdI²$›š¿ºN«³áûìž`æé™ Ý¢¡²!-Ë:PÌüØWËNÉot=.‰Mãr{»¦ÕeJ’](w!P†?’8+…c/³YS>Sí6«A‹ºŒ‡\¶ÅàÐÒƒí ëû××ÏHÎ\¸®zñÆÚB“V#Êä*µ­¢yKeÇ}=e™‹{o{aÓ¼ –eÊúm¥“üÙÙ;vÞ^]³ýôl_Àg4bü’k†/qö9=«~øÌCÌóNÍÀˆ5È 8OsàO'F,hTÛì*»]•™‘¤OÒCöÍ™ŒÌ°í›€Wt›WÅ_µv„=Ao½ŒŽ¹8V­\±1Pl.byxï/M-0n¿üÀŒí>PÿËæxÐl’?ê.´€j®··+Pë•4»PsLôQ5Rü 2ŸWôJ!“ã«Ã‚Þ;U†«[©3i†•KÙN”©´FÍðâ•‚¨Ñ RÍÑokm ùï•ù¡Ý!’ÛœI6ýðYn[¢Ó¢žb4)ìÎD›NirYde¸)Þ"“[!úƉ·Þ™h½ÞiU–¥‰ƒ,kOPUŸmfG1Ë;øRÁT Ý'—á‘ ªcõ*I K56(…Qðë1-|%ƒÈD9_YG¿¯³ò™ÎžætzÍ á}öº^Û#·'%Ù RUê”rV~¾ËÌÿ íÒèÅœK%04Nßʳ½V}n®%46«'G£1z®Éaù9,!‡iÅœœ’<¾òM«ÍÍÑ[@c÷äèlÖìø™rÊ¥À}¹ø± Žhñ@Di[µø_×é¢OŒ³0²<´K‹e•òŸ «7Ñé1Ë…„£KT“3³ÒØ[˜'¶I. ÉÌN—¡ÍH1Êž” å ©þœäî§I.KŒ]¶úó úîž·Œð´¦ZÔú¤Ìä/Å].ƒÚ’bãÿþÇF–‰cã†<ØâèìC™AÇ’©RgàÕ’9ÈÄ'¬‹Z¥2d 2ÙcAG­†¯%ZÕ ¦Jë™9o I‹:óT¥õ«â5]1i‡$Þ%‰Št ¦3²rEW:ÇìŽTQ9-=#=kp+•É2 ë6ï쌬4o¢ÃcQ ©¦z£SM*TØœ.«þó;U´'«d-f£Ò–ä´á©"DŸˆwàÛB¤Ã¥¼oA}8~>]«ñMÒ?)(ÁavÐ Žtÿa­/E§3§´›;åèêy¶Øñƒ›¢¹øÀÑXnC‰yf¾GâÇÌ7Ž 9]ç?ÜõÚøée—&„‘áUòN§§Î`t!p(}Ì+~KÍé^wšQÎ&ûäz§?9Õ§Sê„LEBR¦Û—¨a×òÎYxÇ—É”ZÕЇj<ä†d›ø¢Ö E•A×7¬ác»&ú‰øŒ,ߊvòþïñxÀ2(TÕ¹–ÌéY3?VúYÅã)Jüqêøoa¦w8ù/·²ÖŒêÁȺ‰/š‘ {PÃÍ(g~ܕ áªá†¦sK{»¦wdq[{ºÆ;nÕŒ]4Ç]ÐGï‰2ñQ¦Ðè•:OAÍìòµ§—lžY§În,›œ UÉ5zËôÅMÓ®l™î 6]xo‹¿²´(Í *¬I.›!Ù—\P·~ËÖ²¦ÓÒ\žd½^ãó{-ÉIæ)Í×­Z|ßýkf©±håçÎB¼§[e°ƒVñ¸ñ'‰#%Õ wôª”OMm©ŸªV ΈbéŒ–Îæ ‰KšR>í2µ©R?í#MÀHï½ÇX¼³ð]?v¸Z“f7_õôÕÃG´Vƒ\¾O™™|øâû×áæÞÕ´ãζVåX…{æß~Óeí3†D“xŸ7¥ å곊›«Ó¿ø(wÉšMüOøÿµPìÅeÃvixÔV›ÊfS¥ûuNüêOÒ³üV«Gu8«ÍvØsBÇòF¿U<öVtXÕŸt‘n–êpWV›Çv¸ËsBWOx°Í{°‹½|O4¨‡›JÙj¾Ýj ªáUìA+ÏëUGÿ¤³èå²}ÊŒDÁ¨UËD¥Íi·j‡_MUYv³vø~—‚¿è” N#‡ûvô#Ù|\Ax€÷?’œåd‡ƒêÉ“³”"-ŠÙAÍôä&ç§§ÏÊ/d%{”J¾$”‘Y|Ih#ù',‰<\ |iÑzp?0Iû.=ù£.²¤ä¦ëB[³¸±½]³:ò¹¹=]ù'¬Š¼Ù Œ»( ñÊK_ð()E…B9öÒ ›/Èð0Qê³çtV.¾ ³_bç¯3­3§dH£ShÍZÖâ´+–Ê즄Ö?Ü=3cá†ëÖ†¾½\+>ª°:œf}ª/eòüöM}Áª³æø­væ64“<‰Þäák²Ò—>£ó–¦3¾åÂÓÓ 1®sð옋;lÜ'Í+»O§Oçc’VãÏ¿Æ1¹}’;´kóüiNY hôÙI7JG1^Æ=€¯oàJŠ]vã÷^ î^´§“ :º¾†ÅÀ1/ÞÑï ô6f¡3³Û8ÎTåF¿æÇÎÉ‘×|»R®cjÀc< ý•¨µ¦Úm.³êÿÑö%ðq\ežutUu}TÕ÷}_êSÝj¥ÓRK²$_’-;–ïÄ)Jœ8’8„@œ19IÈ$ä$aab6À,Ddw“„õ†œaȬÈf²Áʼªênu·;‰ l«ËÕェ÷}ÿïþª ?|! ³Å Dá;xÌz•5d×á)à—µî@Âu¥Å¥\‹£º #oq%ŽÞø§;«çÿ‡×M™#® ­È«Ž ™r{!™’ŠQÀû.9ÛÌû ®lBmpʼn ÊI´íq(W¹‚Ù.ÚâÝm¹R±¯‰t$2làa!)c‚»´‰"€ú— -hȧF‰Æ@]ïDMÙnt7wë«“þc1™)WkÔÄX©wrf‡V¼¨s“ÙC>ÄX,&!4­rLê\&Έ×çu;ü˜\? ®÷^øV-}\îpjj*šZ·. ¯Tð§æ€õRd€¯„6‹´ú韛5C~ð›°ò+ú½±ß‡h0²b|.:S_Ö;À×Ï ú½„8î9h°ž5&³b‰†èY1e-n»ãk×ïx`wÖÚŽŽìúä®ÌóÖöÙÞušíòkmí[û&ŽÍvXä›ý=öÀµCÉmwn~úÉûæû3s¿²°µ×ß9÷¡›ŽÆÚf{½íÛo¸ù¨¸;QS>$Ê% co±‡·Õæw~SÉѼmÚ­®ƒ|Mvçå†ìoP†³š¯y[hœ{¹É}Ì_³÷ÎéOŽ 4'%k0äÛxÔýŽ·ÏÑ2Vp|%“Ò·ècí•Ý6ÔŸÛº®Ë¿rÈghD‘Ï8A…»§øÔƒa+ÒcWHüÝ.ñ7 õÉ1äó\³³/îÆ Òû<ä ”ØÖÅìíÏy Zö-ÔåbÄÜö<˜Àˆ3ž˜½P§tÐ0i5‡RŸ8A§¢j+Ô(Ü€x©žÿ–¶-}Ñ‘b@ƒ«XšîÝ4—°´ñýð‰f°ÐÕáasߣÝßI;ÔVôê¹t)«Ò« ä¿fE üÍÍ×ÇÚ¶È@¹¾Œ“‡NÒP7ô¬¤1tE‡³ üDLJŽa0(¬ÌœÈqAXñ§áWX˜HÎf_$îpøÚÞŽïö]ÉÖ+Ì%ÉcÚ[I˜L– íË«>ïÄÅŸ õËÅÛÞš,«,X‰Í‚ãL¦ûjAëæ© Zô!Oߎžx^FJSÐaui 8€›Â]-{¦ÊXÆÝKxÔ#“×OE¿¢ô¤¼uÍÎ.ÚÕ¾oc¯A½cÝ¢ÎF©¢ÿ=:´®LTqø}ÃQÜ8e»u+_ v¯ß>ñîoP-Ààô˜H[1e„.¿Þbí?P-ô»†æ‰I!˜ßõïõ³ûÕp*'2b{¡«_Έ-°ºÆüÏŠ«Ã?ˆ~æwBÿÞ„_²á —¸ÔsBÝZ±é«{¿$‘¢!I¤¨&‰´Ž“4NûókR‰RÎá˯) ¼=óŸšmÝ6’Ñ `"‚‰ôléÊoêpµoܽ©XØû‰ißpOZ¯@ äÌKs6ÎÖÒáñ¦£Áp²smvâÃÛr¬Å¦g5¸Ñl60vÝ•$zr™mƒýGgrŒÁbÐÚÞûy€\¯ ó4¤TH½Ù e…ˆô¤ÚÕ šÀVÅüÐë§E(J"9Dð¤Ð|øäƒÐÏK¹0åÊÏŸC)Ù!Ç‘çV%HšÁ‘·@,ðf¶è™?ÝZµL7³jµÍlT+Å(ð&`‡f€ÅŽ@¤}˜" ø 4åßq')ƒm-vU£ßŒ5ˆ|ŨDä¿¶~f‘ÌvU£ 'ù°+ΉL^ýûÃÆ?=·û¾i›ùFà®»Í1¬¸Ù¹ëhÇ®©¢öf˜ÖûÀ9VÃ7ï½{Okþʇ!WWLì…»ºÃ;´wr¸&Êxx'E)÷µUÜë ÇA&m~Q‚sFç)Ú±‡»8ž÷ Œ®®hIfËþùWµ”£'£^ÎgqN :\c »¼Ž„óZn³ƒÅoEàï`jÎïpú@Pêѽ”°B¿ËÙÔàˆVþéqÝJªSÛ8~÷§}¿—bÌÉ’íCÚ! D#ݼ †üŒY[À) ¦ó’ qð*1êdtNâ¡´¿ŸÉE}ÀŸŠ<3ï7C䡞+’C(\MÝ¡àw^vFW·½ëJCÄkwë•èã+߯U\Àæ‹hI-|ßK ¨û^< 'p`ƒžˆ†Ô"Ž—Ñ¢ÁPB¥„ï_”âî5#ü&¼ fù€ÒS®Ü %ÅÀCmT>¨ò/€*~h‡„e«‚˜fh×f ³Êo²’¸nÞ-Š>§(”åÔå÷^ÈšýfW7¬ED‘´ˆj}ì5ÖE¼Àß&OÃð8¶o÷„Õ`û¬Tå¾™¨n, ¿"ÅY 'úSSï.¡?G¿¡è;rFú8rËjgéP:OÁÿõyà×t(OÁ_|ÒapgéSˆ“7é!²#äâ¨g$zÎZÊ/óêqt¬R«D`Kg¶_±ígK¢ns›’ã} ¥ª¥eu 5zN°–ÔùeA[¹QÑ5[ à*} 2 e-ϙʜ³šÄg+üQƒU –W l»¦còªn“19ºÿ®Í›gôŠ`Ø`Ó*àÿ•<0ŸîO»4´++š+é,¬P–ü{÷mÛz¤«íäýwêî™ÕªQ%Cü¿ÁÁ솫¯9÷ }]½3Cc€Ò›Ð„Z¡¯7¡³Ý±"IáÜÂ. ƨw’%÷;aÈ¢µ j1œçãreXI@Ϫ¹\ÍÛ/wªDa–ûƒ€%©w„dÉâ~G° ç0a•¾e‹ZöPVe\]ò8XÍo"ÔzFíL¶ó»FRNՖͽÛz£Z%© UæÎ‰­é'3fÖ^óÉáRo«ƒ@×ê‚Îáw¶nî îÛ5jÆãsZüýÓOvÝsßǯæUœÇ*ÕâñŸ`7@wÁ$‹FP<‹ß¿«pSÏ`!¾+XïÐ9gDzjÚïÒ9õŽ|œHß¶æÊS0Ë{ÂÚ9÷27Ûw~lljöüñô£ÌcSg ž£J5›_Ê&—$µ$'!µ²§ж”‘9Ѿúröõ×Ïã \@õ‚üŸ$î…ÛÚ…š‹ÏIW÷ s³c}çpé³ç…êÅNŽ¥‚焺ˆe“1ù¤¬¥vAÂz,#›:B¶jF^’VÚŸVÏIÀÃ8Ù¹T4å""—I*R¬°“Å?bjÓöo=ÔÁo)Z åa ˆÜ³“ÅáC˜’±Ç\­çFÙI±Úo¶¸@ûã¦Öê(.WÒjRålYÓ¶ >`)U¤¶s­„‹ô˜ð‰-–„ަØÈÀ¾»®  ‚ ÿÍšoMé|£=Ñ@ï–œÀwá‡À|'„V"qk¯Ù‘òºÜ¿qe¾rZñ#I Ï„¡e€³bÒÓŸã"”)Yfwß{ÇU=¡Oؽ““¥¢SRFÌý3ÀÜqèÿÊ1çaøÞ•i;°©mSÛ®¨Æ©uh 5 9!çq×qW4;"£"ü‚»¢‰EWä8ê?º¦g}ÏúµççÆýc`¤Öáæ±³­ûñ‘nŸÉÈîO¹ ´ ´3 Zd°’%­¤{ä¿Ël,z4±(Ô^lníy¡îrûÎ \ÈÈžS¹R´Š-xYï‘ü+`ê(ü¸Ò`õ‰ÖLÉZVŽÁ*J©4ú¬6R¬üË.%¯”iBþðWƒ⃉ؼÇXM+_^éÐYR¥Ä€ê&áß­¨$‰ο.‚ìtú•Œ !€ 7Íž¼í#ÐG6ÌíX¿c=´ã#‰ö;ØD‚½ýHû¡C3^Bvhî¶Å“\”‹lgÕ½N‹Cãû–ã‹ãCó…Zm½$‘G–$žjÅà@²ÚSQLꤠUŠXµµ9øÜÉÛéR½¶³BÍÅŽí[Žƒë ãC…Ày¡î’rÝI¼$@“tI9¾Q=Fš[FŒ”DèÙr›Åñ&“ÊœÕjMVqCGúº7¶šÍF'TFåH\NZXƒ.Ø5}íÈɇpŒý¥†Dp’ÒoíF‰XÚrIqC(ÝѤ©m]› Q`èÞ£ …1zÕ ÊeK|jxC0Ño$4 t/*þ¬jb¸à¹åFSαS“FŽc©ʘc³I’"iÊå4„šÆÍÙñ<ãp»Õðy•^ps²÷¦(b 8ÔÓÌ{ã)O¢Ç ¾$½JV£7ކ†ÀIR áêÔ9{©½ÑóÙ(ç‡^ÄšZ6f–Kž*yöºáöÔ9Á^R·7uÝÊÓ.òÞª1º©ºÁ÷MŽèÐê­Z qKÞ[ÇtGÀHp©Ñý'fbcÝ9ã^˜2åÒaÈÊëÀ‰kÝ8vkûFj]¸ÏzF{"®ÜàHÉÕ~÷='®îÓ{Z,ð ¡{TÄ…ƒÃéuûç¶ìØ×¹ÿÞiÑgžÜ£Àgn:¡o]Lõ¯E3\‘§5OúXƉ ¾ä)DÅ!þ­B!êdY&óZ´Ä¼Á;ÇkÚeDÁL.‰}R) xËR¯¯¿„YÕÍü[Byh4óš-9™7gƒ¬–§T:ß{KV9·+ 1!å›åï8sÿ~Ûuˆß;š"IR¡T)™® »3›?¶9nÉo:úÈÎ ×z?7YêÝ=^`÷^õ·}È/®zºm»÷ë9½Š¡ì+ɘôLxýz¸÷c{»£}S…lOblO›5Ñ)R¹oå>)2鄦`´ ¶UÙ\gg×Ô¤ÃÞeïZ#[:Ùs]F\S]Y…Ÿ?—*…Éßët¦±eÿ¸éç<6Q¥œØu»+ÃVŒS²É…¥…²ÇÂY99Ê{ÿì%–Dê§§øsX@Gþ^KøÇ–ÿ8fú¹V©ã‘¸T¬"RhƒI:2´j@%Èç/5Ôqh×|pný c­%çæÞüto„b½´vhëÁâè•=vY|. 6õg\§5(ÉNËä a‰ÒkpŽ3ëi£•ãâÉÙ<ÑžPfúè`û=÷8ÐWeÖ ó‡±á¬³K¸Èúî7%ÿOhÚ] ý@äq/ àW¡4àù›PšEľÎ5𫼎lIçÙ¢+]t‘¤«˜V@»OÁxG £¸eûÏ,džEùM?T[,Á±Ó|ißéàD½Q=»$å ŠR©C6…rc­”˜¨$'‚ýøXÔ²ýg‚´ªzÓ5æÇN |)¸ï´¼˜]ÖƤDnϪ\UL^0$JPd&'j¬Nò… üpB°jù<ËU“•ãÐ\0R£eEÌæã,—Øù©Å9KÐJšÃÎWÇ„!!5~ð¾ísßÙ¸ÍP¹2~Voˆôn½~4<쀭”zåM »¥{sÑ® uÅŠ›;œüðÄ[‘¼G½ïºMG†èCŒ×cÒu»{n?<â2:;j“Ž ÔW,½k×®iõ¸ ã-ƒwð†®€9[hw›ú¡™é‰.?©TÿÚœ [Ò£3!G6ÄE‡¶^X.¢J{6à2ŽAàõ¼{ý6õB_k"Ͼ‹°ŸòÑfº7§ÀôçøbÉg¡  îŒ 9Ç0ÙÔHÞªØo+ЬTÐ+' ­—â28¡SÈNž¦\N§ÁQø-šSðš¯a¼ÄR6ígÇ—X‰Ø¯ŸY*™_ø€±r§~y&ŽzA(«!-V&l%g[~L§!ƒ ÿ cíQ§#¨C0\gG=²ò‡U>Kýå"‘?°Me Úí IZLWh…ÞFÈ´"d,£ßXí 1Bb_D)0íH=ä¾cô{iÒò˺;ûBÄ;´¬Þ’&Q”¤•à~ºl<d#×,;ÄGzL¡ 42 ~\¼.æŒêU©ƒS‡Å\ÂⲌ©j .WQ¬r;Z2i™Õ6ãΖ˜Ø|X£|Tj-ï*ÂÍ#ÏÕ{vw%Ø“i„#0½*OÁOH!¢Ù#¦xß?`[‡?ý¨䕹ý[@]#´¿ uµ€÷<QFpv¨¬.$®[˪…¾øK‰:µçßðÅp¨•yËŲ,ß1öð~f¡·šÜqq ‘h)š8¯g­wš·ëQªÍK¯/±ásüH©­XgˆKÐÞÙµEu¶{$;f¯j²*”¿€ Ý~Å6VJ-,€1É Äs¹kIñ‚Y#ásÂûL«¬]ëÛŪQc}F«áT™¨e]kZU¹Ø>¸Š# rÓ]™«çJ¢Â•Njqøe:³û哎|&õƒÑ¦QÀ^ÍàÖÅÎM+jÚ*´õoi3×ibGÎÊu]}ߦ•ƒ«'í–®‘ú“èG$QÑýù/Þ1>ê)N$}c=Ñ`ßLÎ7à‡*p¹úB.ÓV«-¨P£6 uÀxŽÏ—6µÂªI•îØˆ{Œ¬7n¢ÄvÊ].2¹ž%çóÆsB“Ù²¤_:sÐ/)‰yøŠ$°\W£¬£ÿÀó]"Õ‘×jó|®v®kô}‰éŸvo-ˆÐ^t{`n¼˜²bψ‹'!³ÖŒèQ³_ hÆñ{})²È«±U¹t!y…ÔÅ_KdSé¿ô%"²( qÖ%´É ¯Ù‹3GÜ6wçLÔÖ>-mŽ~јžhëÜ9^ è¸ôÚ¶®ârméáOÜ|E¡eæ–©ÒÃ'_QHÎܲ%3YpÆFvº®-3ÙæŒ•v>!ï.¯Ü¾ ö…z 6‹<­yFÕªj5«LfHܾ=fbò­‘:,™Tf·BgÑM—k6,±_ö»Î,%Ë$Ù°Hþ×¥/ ?&¦Î µ3ˆâr#%k}° ECµM5`#*ŽÁq…_•#šD©;ÇmÛÓ,&—ƒ/ RîÀMݿ횎±}¼ý ¾ åϲž¤0Ð:ÝŸöhÛÚï¹ÿ„ЫsǬ+“­ø5kî>ïíæ¦NĆsöNÖ|fh0³aÿ5‡eÙF~x­<±[Ÿ™ ³¬Cg‡vælæµ|¢¤³³aG7yGLU+#Ëtr¡j·¿10\zþ,!¯*4 «·Q= ½Ïï­]9°°o•R©79 Þְ͛õîWYv=¦žÒTˆõ9M8Ž>¢09Ý6AWž\¿rèb‘}:2Vôb‰ã¢6$ß]Bþ Pl¨™ÍûP‚ (‡¨ù×~ Ÿ&ÇÛ_ »±Æc(F½Â—ÜçÂPTE4š<ËÛš×½št˜øÿ’µäxB\|8ºÔ+ LŒºÏ Q[ò¬`kRK[íN©dDÅ€oµ•ª>ʯiPyño8­!Oª¿%>ÐbnÜ6ÑZØwï–äúþ”JI ¸ô¹·°®«0‘³ä&¶N´æ¶t*¸¦3NÓ¨@yÜœÞl°Ä Îpk4Ò±¾gèØtZÍÙ%ˈÍ+:Úæ²Ùžhk,Z\Ï÷ͯoatM•y„½ˆ‚‡Õ’߬=~Ý‘[Ž N­X·îÈÀ-è[€Kq(w*‚À½çD>NœËÔ’î©'~ˆ? òcAbn»Êˉméÿr¯ªÝ}`<Aqà¬oíÆ°hÚrȵ;0(–äÚ6d}¶Ò{ùBÿCVJèI.dö—òREär¹ Õ§lWÞådi ¤éFènù©º¯Ý0, _=|—(Ž[·§S ½q1¹A•Q”®Ù³}¸m¹4ÞL¸–zNWØ*ʈéÄtž¼Ö­ÒbA^mûÆE¡²¿}¸Ô¶,”Æ›Ë\¬ÇzºÂeQìÀª—!y³/QìW()ú: ˆhËÿo ý+ t]zò2ú/F3áÒÄ¿ÿŠ~ê„>ÛÄúyi3”î̤}~‹¢Íþ´Å×™!±Âˆs$¾ÌkDZ՚nùªlfAt¥ä.M—0G6t µñeA{x*{e6VËYùš^¼Zƪž‹Ã”Îa4Ø4âÑn;TØV´Ä!¤šh=ˆã´”oŸÕMÈÏåÉùW†’…ŸóŽòá@ïæVÏ ÉUB’ ?²¶9œi¿¡Kx`>Y9-RõÆwÏ£Oª¦¡£Ír øö¯è¸ð‹ˆ ‚ 7üGžæ¹ÄˆWe)'V¥nßÊ{-¤V߯¯å¼yõlm¸Vöp Dµ 8X ôF 3õ®l›¿}’ÐYÜœ+h$áÐè\V«ø\ž€uìÜ0Bi£Ïjv²úÊHxãgÿ{͈B©¦Ð4K¨Ä^aBE^°2øæg¿²p½”NÅH@‰w_”xP" =Þ,Ró!©gØsQϰZêöñjÞ[€Gtcx%U,Ó'Ù¤_¸Ù`‰Zu_Õ媪­Äe§¼®“¸B¶Õ¾ÚÄŽr!—Ý­ÃÑO®üW™N‡ŸE)øú¯ãˆ>¾´ú¬ÆÎcÒŽªà7W†Õz;‰à]+4®Àþü48¯@qŠXù< >P¥W Wî—0”‚N6éõô‘-À¾ðœÙ,6ˆÄÒ·Œø”LjaT=Ñ@¬±)±ÒVË4'Ó©ö«ft’¡U¥‘¾]Ù2¸8ô)æY{剹• ¸Î°Ø|:„þ„Òæb ø:¤{÷†5.„6úm 'ú4m¢f¿ûã_xå1%Ð`cPÃEôc @ ¦¦.x§Ÿÿú7wˆº’–îï‘ï¢,fƒ¼P«ü4ì ^D´Ú|±Sð¼…Å!"Öê³Ù½$ê:|Ê<Ÿz†9‚^ öôaäÖU3'w'³Õ¾z{ÝDsð)Á<Ϥž'¯6Ëïí¨”Ü™"éñe‚I`ò«dï¬Iÿ€ç?%H 8˜O Žzx‰ÍGbR³¤è?BÞŒm>±­Fº#ý/Á E’‘¶>oçl·›õ&öõµ¯o5ß‘Š:c.²³s]Ú¨¸=²&ç$­ê|ŽVÓjÜh6))ÑÉÊŒeÃ[6Ovû-Ñ¼×æ2GÚ\«W¤Û³ð :@·"ˆ_OÉO›ÛGJí6ûˆ­ØÙúD°ù™p1kƒXþ°³¯ÔžÁ|]O%çÃÔ#,Ë >ã»–{»¾^/j9ZXZȜɰP±xÓíX¹m<Ú°h²ë),ËR`aßà3‚ïZŒ{T¨[¼iËPåqîª"Ÿ–¡VFèÃtrôêAwWÚGà¨RM*Í¡ö¨¯¶bKбâ€73Ó«%Ø-G+œý¬¬åôþ„»¯=N!/eÆ[m£&*Ân30Fe8Bz.ê1¸ò#1Å¢ÚcêÓ¿›æB©|¨WÄ/ =†|ù-®èý¸üf„HÔș¦°ÛQ®:ìöQ‹£;ZŒ}6;ï;`²^‹Õ é·{$‚K9ßlr!“}9SiԗʵKdÙg…÷Z$&/RûˆÙjé«òÒj5¢® y¸_6ƒ^”é^súí|G ‡Ý½ø\Îc°;d°jp ¢TR˜H[¬3¤ÃÈ"Fâ Nbðu@åòù{7ç~L«Ä3¨¢ŒÀA»Ü.Zñq¦PÁmLJoÅ{ù>|û#¤‡BÐUr¦Öà ºÍœâ§Ü»Á|ó¶Ôíól¹×#yæt¥S€,Oû8©£aÎ{õqÔU8þ¦_áÔ …Úè6™]ô) ì¬ƒlþ€t¶ÀØó›N)ÌÆ*2¼`¯P±àJ¡Ä·A<ñ&@F¦ü¶©°Ø#¡@ca½1d4†\ΘΩÇЖÃF§ ¹p•÷€åZUÝKU©žµP~ÑNMŸ„d*/q…²EèkºP´|TEÅAGÞÔè^»_‰:;g´i ôS]`—ƒU…ÁW°°ó Be´‹eƒ)#ûÂÊoÕZLI‰Á IÀ-+¯TˆRÂJðÇ8‰C E+€>ð÷}ôиDVOCMA”žV`êõð–y^Ù5ýžƒjüê®à°xó¶«7ü«øVTüe§h`š0ùŽ;N–ßŧøD¢hò@T²­ÄqÞizbž ?;8Ÿ„(“§-Áyéi¾TTg;g¯µ7È£Lx©ƒ¸x |Î.d2Éò¼`¥Áð³Âå¬%w!”ÜZ+ÚM¤½Ž\“.'ˆwªpy¬ÝÀá‹—-;`sŸqø,Ýí)*^a="ÀŸÇëéxÇ?TðëQu¼}Ðï ² ¬V0µ7àíÞÒöãÕs¬KãñÖC¬@£Òs\ÜoÖ{[l\Âo2‡[]ÆW–ž¼h+¿OÀ(³§fŸMÍ›!ÊÃÑm1o”²‡_D0©Ž+Q~•æ–З43ö*´JTY_4èO™š@b¨Ûëèõgw€rJI'Ó®sM0Ñbqlƒð0림@ïLîŸ*ç›xT¦9\pãÆ²©ta!4+? ÁO@:È ?É«(•0>¡™w!hæ Ç“q¤ÑL¯–±+Å "WkzQ…6P\»—?~,´éöí7ûÛ|o~,ÅåùüXšS”â³ÓãmÞƒ{zïœ>xu¾#7µ#QèhÜ!êýëáe÷…º ‡d¿Å“Í1ª¬*+×úÁ61“ËÆ N´<œ/—Þë®+|¦a[PñwU– ¶€¢f!¢ð™Æ}7­á׈V} ?XWÂÇÔ®p2l©G•†IÖ †J?ˆ¸¼Z#ƒÁzщfúc†“¸£@ƒ±uE\™ ]¯T¬Ì̬çƒ4kV/c¢zEã74#‚@н€’KæüL–÷G¬-Åžî²|\-ùÍRÇïòk46²Ra“uø ¦^ŒÌ³V߆‡ÿÉÞ—€·q\iV5€îÆ}‘8x6ï ÁÃ÷fyf{Û¾îVùœJÔ Z—ÔPÔÒYÞ¾í²òÊþÀβ-ÞRAT“#ê-Ýå-ÛZËËv\½µ ©¶XÔ?ȃ Œ†ºrG±‹°xv·—jMA4 v‹Íì­v–À‘–šÚÁ¶b^gÉSN Ç4ŸFÛÐ1¶WµÙjPW#`,ïâ…N oyMW¬ÓÛÚÈW|F(/hŒ?[°þìŠÜøbw_jjÉùŽÖ7¬ìüÝÅdtó^ˆ˜ãg#ëϱº^ʾÈenº´Ë§YÊ#íÚϿʞOïŽi´fÝ—©4îÒÒ2½bFcÜ^^µµ:_£é¼\ÉáÝn,Z óó\fµûNؼ¥-*°¯ýO“S[Tb¶ŠN‡]c2™ËšËÌUvìÔ›ÅB·ýfبÕðr3ÙÉ}•{Y•§Éƒµh™Ý«Ò»:‘·Ì]îr7ºtHï*oôv–¹ušÖxQ¼ö¯,)ͺ“yù\Š&(°û²½{}O lÖ÷Íìjäu?ûò³²kKŸv(· ÈzdvYa²©ìúÆ­CU ;j삺—+­ÍsÃÕË©‹*Kz·6ÂŒÃ6G™<àh¬r:kÚ¥ü'¾œÍŵg,Ŧ²êêž}m? »8žÆÔ‹Ü+Ü/Á6l5ú2èoZò*OÁ²„P œ»ëòêâ¥zw\Ÿ›TägKX~ü»n¯½—¼wå¹Ìuå¶Ì•¿ôUeî—j®éÎÞœ_l/,³óxŠS› ²›é©ØÚìq`µÈAâ@Ãi¬Ú£k¿O :#O™ÀoŠfžn-³Y«Oá‡é½…ån«Ã¬¢¡!^FÜ„aqJ;m4ãÊ׆-r/Þ#s˜¦bŽœËÀÊU`î×jM~KÏt×§µ uÎH%÷Ïro-ÌÏ'VÙ]±ÅWk……ºÄQY¤Á¼UÛ±ø¾;/ÿœ·Š&íÓ°–™¢ôÂÚu¾àÁp;Y™õ°Aj ÿ«æýpÖ’‡úX4è¸9PZƒÇNšó‚YÌø ù|&ù€€Yó4{"bîÎ9 g¥DyƲÐÖàF­¨®¨°ÒÎi4¶Âº¢¢J·öª¦² Ê¥Ó¹ª ªœz½³ê—d/uêÜï¸ÃškQ>Û%çåëú G­º¡„~À¢ixO<^²Ç2˜}UýoZ]ò™´¼°ævë.!Ÿˆ¬ïÙP tÝèY6ÿ€ÉçÉðòpâÅ}AepU–ÛÕª×x½YoòTTØ΢³Ô—WÚ¼ |ŠQõŒÑ¦×h 6ÃïçM55:³ ²šÙX][¥·èµØàÁsopåê÷R\#?o ?wR§«È?ÅmGzû‘/W#\õxIØ2›ý@“w¾)?܆NÀ“Lå«@åu| ò¥ëºÈií…侟š»ëååv ~J£7jMõ¥nÉ&ð¢I„¢CÊÓáò8I²€6h5A<»S/I¥¢É¤µæ å%PAWŒvŸ{ ףבm—wþ\OYȾ·¤Ä`OŸŒäkPž"™uý×ktf—§¼¨2OÔèÍκêâŠ<áã¦êÚr—A´Z-5ÕeN£Î^@æÿ~œëÓæ£fú»:Hoû™˜|?”<áé Ñö³Hv{承™ç8q]˜õVÝÚ5FGžä­Ç›ô\Ÿçtæl6Ýé²ëmçΡY®ŸÛÇ}Ìž@%èÂç®]û¨êús.ÀÑJ?o8^ÇrÍ@€<)Ú^‹ä؉êz2¾Iwv»QÇÁÖˬS½`4¬ý–·ç;ìz» Þyz;DÜ[ªYÕ„f^¹º*ýÀ[U)g†6e²sæn­¾Fã®ÜeÙ•=~L„éßò½Çú”ÆÝ½ž¥àÇ/­7‡°®ÊýÒ—ËfsÂyÆÖ;˾ õZ-ÖZ  ÑÕ¨º]™Oø[¤d±¬5¯oAÈ‚fÑ•ê«Ô£H@fˆ°RФ uÀ~{CûÐ{ÑACKè}x„fšèø\d*Òyèð¶Ãµñ”'%VÅ¡ÃêîW÷[|°'NGúÛÚúG‚©Ã¡hÿÕ®¢Ý‰ÅÑÅÞo¼¥åºh{´àÊkK®µMìuìå¶ìàwèê½&ïâ-Ñk÷îðzwì½6zË¢P=;S^š¾Ñô «ò1Ê&ò±–‹¿`ÒÃö‡ô I°óÝáë®F®¦‚?" ÊòËÚZ[jäw»üî”ß•ãºúú÷õÇGn½j|e<Õ÷}mm¾{ÈË[­Í­Í•¤´ÖÑ´67·räõÒÀÝ–æ}çQ_[KK%nnkkÆ/“ƒkW“×·÷=¤¤ú¼ø ¶öjkkókPÁ÷Aa/‘v¼àçZš.{gJ÷ú|mœ$3­ Pøï¤ÛÚ|m^(ÀŒë:÷†*©ú;têF‡hΩ®¶µë ÉÏØ£Ö-ä{ìù6±ãy§s»·¢¢äuïîí_5îQ z'­•}Þaü~Ë--òiJÎèìx>Â:yK^xw·5B;ºè½3Ö³Á–þî?¤‹öË:2IŸ|âU¾<¤ü’[òóž’³™î7êŠêŠRlúÔ{vøû*G>ðì ‡MÚé+¶“o  B^UñöŒOÞ0Xbøú‡îýøð@ïM—»¬F‰ã¸+w–m›l¹ú¶©ÚÁÆòÝ[‹+Š+mîªb§Þé®ì¹ª£uËÉØL{ÿ®sç”o,s<žF$Wÿ=÷uÕ•š7MÑ{²½ìi|è)»Xô¨Ñá0>ÍÝñD}}åUIDì´³ÎÉMf¡'EF×SõõªÊ/F€ÏEÌŒ ÊEÙäÔßÁ¶e5Y7jÚ©AÈÙ÷£®hïÀüåµÛ⟙Ý6_aÂÑ®×:tRoÅåñ‘êéé®kj¬N½E%šTú’Ji0º'üì]îbƒ”'•X§½7rç®ðt=쀊e¥nëÂW¸ï¨Í?p¼¸†HýkÜ÷¹¤æçœÅÐú³Ü·ÕŸÖüê<­•û¶ª„Öõˆì¡þžR},Tv ^åzÚqH~­øøÉbÏ#• üÉÎ/Ñ…•.­Wz‰COt~1R@­’þ^5yDf —çTNÿùÌçç}¿æ“6Ï®¶ú‘|ƒNJ`¤mî«-¨þð‡mõ}3·MÝõỬUÛºöv×è äéÜ»³Þ­W¿ê[ÀKN*ѼÈ;ÏØÌºâBû/,V±¸ØQPÆ=\ì"ZÊsvJ4{Z 6¤7Q¥ås•"Ÿ¥£z|™;o{4ÂçbOÃf×þHLÓ3®$à4®}Yg3iTwð=µnõÍÿf5ªªø‚¢|Þè´rO—Ø­ïÜNž:.ÏIT‡naO¾•Ìf§Ã$–•9êÊÄ[Uî‰2Á¬²Úú„*Q{Þ-0=yÀY ù´;[U)òªKêœùD„]ùñ0•\O?S³'' ê<®¤ªÎ¥Š¯J‹¥Bî†8WT]ëR}PSíÚâ(±ëÔñÖ<_MoA‘À½a°æ[¸–wNë ·óhýñ¢b­½È¾ÆsHª*.‡Ü#ç"ðK9{n#9wYê6:ŠÌ¢©ø„ è‹NØ@…/ësà¿ÁÂ~b—ó Bñ‰0ÛŠND6`ÏýˆŠ%Ùê-)®®¹åÚ+a5®¬.V¯.¸gù¦Õ¼òF×øe»ú›\š¢m×x›ÚÖ~o°Ú­ÜS%î×Á™ÂÚ›…¾>ð«<»P•Ÿ Ëó6“`äM8 .]®-ìƒØÙï4=Ù€‹=ëK¹:Hgýð…Ê®ÖÙÌ_{Ÿª¸º¶@}ä›Q£·™8ƒÕ ù¾° ï÷™-yVî&»Y€šþ:ð©ŸðÔùÄþtc†TC—Dÿ¬úgõ“ iÊoø?¢]˜„Ú,ú#Ѻ!=§v¥‡ÖÑ_+¤Ûô± é·ê¿!ÃÎ ÐiÃi㤉“é± ™ódºsCúu†,7Zþq=Y?qa²ugÈ~cÞƒùgòÏ8neälûÓ“«J!wqš~H¨ pÈPá•”Nf¨èsÅ9ôÝ©äB¥2ËPÙ$£ò¼4}ï|ª8Uqªò»çSÕÍQ5—EÕø.@ÏÖ<[»½öÕºd]²¾£þ{ ý@ß÷{~Ökü–7 ô«¦ùê|O5×=ÖÒôg¡…MÚ¤?½•M­ó9ôØ» _µþ¯l‚SéwKŸØ¤Múÿ›.û§ö[(ÝþÓ[@粩Cè0SrvÜÝqw§©Ó±I›´I›´I›´Ifº#‡¾Ó5¦çºžÛbÞ¤MÚ¤MÚ¤MÚ¤MÚ¤MÚ¤MÚ¤MÚ¤MÚ$Fôs4\9¼ªH‘>Š•12ÑšŠ~ºÒ þ¡\V¡õcrYŠÔgä²¹Ô?•Ë<´ÿ›\ТÆ!—ET¯y@.k‘$|J.ë¸ãé±ôh¯ð¼\6 z1O.M¼¸C.›PÄÑéÉeŒçÓr™C¼»P.«Û-Êe52¹írYƒ î2¹ÌC{£\ÐV÷V¹,¢|ÇSrY‹,îE¹¬Ããé±ô¨Á}»\6 |÷—ä²QP¹ÏÈej—¾H°Z àlš»ä2³3+3;³2³3+3;³2³3+3;³2³3+3;³2³3+3;³2³3+3;³²Ñä’ÎÉefçÏ# µ jFíPÚƒÂ(€(†’𥠭J §¯~h C)мp¤E€$4mÑKÒZÞCÀ½¯Aà4¢!(Í@K-ÇH Œ)´LKÉË wŽÒAŠD‚ÿ1àY†¾ÊR³µB©:]ë@:¾$ÄW‚qý0‘@×˼»¡6­äèàK¦õ™‚ö0Õ!rA<³Ôê…ú !­~j…\™œ˜¬©DGY€£ª¯bÝ%è› - À¤V“ }޶íAÀ‰X'LûE©]·Òþ!ÊBó0&±r¾J2"…W¢íIêÓ0`Q¼—уOŠ0ôL‚ú¨6aªI8­‡þÏC†éã§cH²¯Ã ‘Hõ‘µ µ%(¥¨’ ß ”#S‚Ú‚è†×ƒ²¥˜ÔÕ‰¥(Ò(%Iý4L½2 -$¨“TnHöE˜êÄl‘¤Q‘©~9^‰Çâr»2Ê<ȉPûÄe”Qh™§£2™Ij© 2bœêÂæ†b[†=B£†Dœ¹Õ<ðúaü­E©¯•¸f6c£0?Fe½bÔ¶3”3ƒ8[#bµC´Óúz¨{éÜÍöf •6O%,S;,ȳ4ÛÞJôEåH&ú3¿$h4(1¢¾&‘OkÃ0”y’P»Q–ž-˜‡Ó^òÓ!3`>G/%󉟎Ç÷n¡¶œ§'óâÿ½rä(‘ßRšQçº>9}.< ROF)Áv}Ú?™Y{~=(Ç|<ÍM¢šECøC4®þïäbÝf6þ“GIÕÒX'—Ð.1Š,‡9дDÉK3pnäxåxk‚ò2Ÿƒ4‚ˆ_È—áÉüš¥XHÜäJP A†C‘·QŒ&iœÇ©îÌ J?âÕ+¨åYZ¦–f–I¥½­p+9# çu’<Ô„/.GEvS»FåÜÁ¤„äº_Î×!šmÂTC†n†âP¼¼Þc)¹‹ŸÄy-³i<—” ØŠ¤6MÉ+›Ÿl\Ozœõ° »Dí ói#›-Éš†éL‹Ð9Åfþù¶'}تS üu9¼±t†áÝÚ6{~°•_’×îõ\ g ]¯AfÅ\kkV M˜.l'¡äÊDzW¤ër”æÿ5e±çω*–bò+ÓŠ•è|aù)H׸°œ[˜Â¡ÙÿÂ1ʲxTöLFº2CÂY;Ž9šï²IV7Ò|’uPvŠ•s£ÚC=ã§å Rö^ëóÜú™P»./„hž^¢»0õ>ñªÚˆ…Ò|ÄŽ5É2ß».wÖɳ7“-2;Ͳ:]âj ­“1¢ÈŠÓÑ|´1?)QÃv.yÉD÷ÅV8%*/¼ÊϧgN2kŸÂüÍ¢ $ŲvTö»‡êœWe_ÁöLe?+qÌâ*.ï…Ø1º'÷S=•Hñ£Ì*¿>Ÿý |‘¶ŸêNì–s}Pž«y¥X³×Ì0Ý©'ilÊ/ì[(Oæ®óàíº,³Î²çÃ%ËC™3…{ãìæY—ÝÛ¯ï¡g áuz+¸2{°Ì¬É¬DŠ=H9s#ghJ=”!qzn¡ñ6—µÂ2Ô3KH^©Ò¾ÌÎ%̇M²Ç“t–DÒ”yK—nÕìži™½ÒäÆtÆKÔŽóïÒÊj°@Ï<™eBY‚ô•Œ™±ËuÀÈZ;RÉÇ,ó©ÊŠ·%'‹ûAbŒfœwÝQºF(«Lö¹›²Nl”Sr{%i®`¾š‘õÞxÍõ_À£‰´öI¥Q*Í¢óÏŠßm(ëÛ GÇÐ ÔöÁj9A[†¡M‚,:GöB­Zû¡¥8&åã5ÔSûè:4|Ótc2&àuêWÐ7ˆ$Z'µËd‘¾h?c¤MRÎ *{´ŽÀû€ÌGzôAË4ÔIyÍ‚l¼QèÅÎ!†å5‘!‚v)­a.ªa:¢‚lÔ&@þ|´dSy?–GÓ8e¤=ÔFD2‘ÙˆFh´NÃû8ðMÒñ{¨Î í(ÕaŽ3](2²WÖ•ñûì•|#@­z¨ †(šŒýúà}ù»àè]!Æ g?Õt’Zo@¶Ñv„Ö2Z1OõQmˆU‰ ú¡¼þïJÛn‚¾2,YÒrm·Ïp1ýzä×>j¹1ZcÞ裵)ê+rÔ#ûr‚ê±~Ô}4(WÕx2!ƒ4zz%:ÙcYHØxÄ·ÙX”¨–.2G˜åø´ìéóíB¬ÞCmBpM¦G¾d27ÿXg¡™óË&šÈÕDvUÎK÷qtèóR‹¯¹]Ú$bÉØlJê‹%ⱄ?ŽE½RO$"M„Î¥’ÒD(J,†‚^ãPh&Z’Æâ¡èÔr<$ø—c ));HX|9AzHD²¯Uª&oi‰ÏICþh ¸ZwÇæ¢ÒÐB0IÆ™š '¥H¶œÙXBê ÏDÂD’Gž *%c ‰@H"p—ü‰´ †Rj.$íž’FÂP4Ú*%C!)4? CA)ÂZ¥`(H„ãD=:F0”ò‡#IoŸ?žI„É~i>a4 RáYiÖ?Ž,KKáÔœ”\˜IEBR"ㆣ°¦BóÐ3$¢¡DÒ+ §¤Ù?µ%¥D´§`Œ@Ò#%çý`×€?eÒe~!’ ÇAdta>”Îd(E$¥x"Þ hAz$[’æÀ¸Rx>pTJ[2è:Fa¬Ø¬4>H³R¡C)è¾>ä•d5k’Ò¼?º,À¥ 71_Œœðƒ.‰p’X4䟗âdxZ’á=…‰J~ 0ÏÆ"Á˜ó'X(áMÔeLЇè¿ŒCŒßîmî”4²#9.H%üÁм?q=чº6¡ÁòqÒˆ¢áPÒ;²¨õ'ëÀ›Ò®D,–šK¥â[šš–––¼óJ?/°7¥–㱃 |n¹)šESI™5²ð'iáË –\ˆÇ#a rÌ+][Ë-K J)´¤™$.N……ˆ© ×±é‘Å.†–Í&ˆyð2•X`*ÐxTdm¥¨ Ã(07HJIŒ-E#10×z~f*ˆ0PÜG ©8dƒ`ˆ¨IxæB‘x®E!?A 3vâ0/sá™pŠä)ã@ž‘YC ˦öH3þ$`EÓCqB­ ¡¨w)|}8 †ýÞXâ`©5ç{åÜRî¥aAç³q2Ü(‰}Wæ!ß#f¾.:ÓÀœŠ@‚£æÎM—Ä”9 Óh'ÎIÒ©zƒ BÐ B,ôH³ H~dŠÀ„<:ƒ­À£Ð]ŠÍ@Ò‹£øiÂVâìÒµ €üÉd,ö“øÆº¢)?Ë«áX¦–HÌÑVš”3ö÷ê(¢ ÍŠÌòÑ|Kš³ÂÍ#‡A¯Ž„!NÙØDV‚­X0DDCÉéáYò¢‰/€BÉ9:aAôÌ™¼IÒ(G hØŠ'C$UÇâa–Y/•Mx’MÙÒÄÒ\lþ":’i°ˆ˜ŒA.¥X® RJ€eâ‚?¦o qÿLl1”µðFc)2eXRËÓ˜EŠ|(9GÖ…™PÎÌõg)š Ã'SLapQzº˜È|&ǧöõL HÃ“ÒøÄØÞáþ~©¦gê5ißðÔÐØô”=£SWHcƒRÏèÒåãýi`ÿøÄÀä¤46! áѾ‘éþáÑ]R/ôƒõ}f"“È€²¨áI"lÏÀDßT{z‡G†§®ðHƒÃS£Dæ í‘Æ{&¦†û¦Gz&¤ñé‰ñ±É¾ÄŽNÀ({F§`é…6i`/T¤É¡ž‘:TÏ4 Ÿ øúÆÆ¯˜Þ54% ô@cï ëé`CR}#=Ã{›oÞÌȽ™¡Xg󆯿 ÍÿïÝÐÐÉß“8÷[øïB·£þ8ù›×Âû'è7.ögSÝg0`àÁ/]*¿ÑHø¹—Êo6Sþ³—Êo±~Õý—Êoµ~uÛ¥òÛíÀïˆ|ÓBMùÕð¿ Ùൠ½€ƒjÀøÛ `‡ÑµP‚“+Ì¡°Æè¸݃ÇÑCøJô| ú Ž 38†¾‡Ðëxý|3:‹ïÀ¾ çác¸?€ëñ¸ŸÆ=ø Á/ã}ªÝ8¨ÚoP%ð’êF|³ê>|Àÿ`.6|÷»Àv/`;Øl§Û×ÛÛ?¶ßâ›1lzÀæl€Í ض¶AÀöÀv5` ¶%Àv3`» °ÝX>’‹M%ea3¶"ÀVOƒö àka ¢EÀv°lŸl'ÛS€í `û`û`û ^À/‚­nÆ`ó¶­€m`›l~À6Ø–ÛûÛ=€íaÀö×€í1Àö$`û›\lêײ°™[ `klƒ€m°ÅÛûÛ‡Û€ís€íIÀö`û`ûo€íM[-` `«lM€m+`Û Øö¶Àl‡Û*`»°= ØN¶gÛiÀv°}+ÿh¶BÀÖØ¶¶½€m°ÝØ> Øl¶çÛ7Ûl¿lgq[1`ó¶>À6Ø®ló€íFÀöÀö1Àö0`{ °=ؾØ~Ø~Ø~Ø~Ø~Ÿ‹Mü|¶bÀ¶°]ØæÛûÛçÛ‹€íuÀö/€í,.Á…0z¾o#€íZÀlGÛÇÛ_¶'ÛÀö}ÀöS¨ýŸæ>ÙðË\•j7׫ÚÏM©ÜUª9¿ê>òÃH\‚ä3‘Ç"ßÙß½²²²§•ÃÝ݇ ö¶¨Æ¢¦þ ò¦¨Å¢Î¿â_™ºÝ‹î5ÀzX´Åm½½GŽ=z˜y8 b%‹b ßÛ’$i¼ó|çÐê±cqRÔø†VVŽ ,¢˜iç}D*éªp[^§LÝÝ0â±cÇD‹ªnÄð‘#€uhüÀñãò9¯Å¼î*\é_¹ƒ‚¦Â™yœÕU:>m]=ö:ôQc^gÝ5СÔ°¼.¨± î~“4 =‡ˆ¦à;~z…繿Öç_iqhh|\ê^9NT39(ÀÁ~pÖ±c«:Ö©­VV W¬Ìv÷­Ò@£xdQ´LÓ H=-ååLWU³ÿ“Â# ÀhÕX«‘¤7©üT@?óÕ$­‚ &ôVÖZj‡Žêh¹·üÀVB¿he…ØS¯¬`5VkÞÄâ¹5áœZÍéxðÞqŠËîÿQ‹)þ[y[§¡š+Ô±Î$¹|µãµãããÇ†Ž [î´Ü.•h·´WôZ¬Ógœ˜íF@ª 6‰ú‘X„Ó‰i?æ:’y‹æ\½€õàÈOŠiO‚QKÈØ#m QÏ«”q%±…Z’_’ÃT#Ù™zÖ«¥,oê±`¼út@ê"áy´ûÏíMQñæ†î‰;õÔ`y½¶I+¼h%M½°WÓ‹`˜’âÛ³iK0ÍÏêXo&ÎõçŽç‚{Á¹G%ÒU»£¬¬§§÷0QÏ£äø7ÛÃz†2Y©‡9îè!½ÀéÁÅi“ ®ÝA×À»R4%++«AÄ ´K•—˳$ÙëŬ~àhƒÜDäÕ3½½½àÙ•Hq%a ‘ÐÛ¿ÿÀc«G *lHûš®ˆz,¦­¸›âSdÒŠ¼`ƒ&é#/=-/¨<ñ8•% QØÖ .‡ôDæ $¾·Ù8q*¥—ü)Jy°î ½ˆÛ‰ßÁr¢6.¯¬­%)Ø â |oŽç5ày-ñüŠZòÈtØ 3¯¸º}èÐé4ùÁ-`Wƒvç ùþ9x }eLkÈÀƒ¡|>ßúwúôYƒ,%%ÛÚ#Û"äï•È+ówýíý/»^vQº¨y¥y…ìu²06–I Fqš ;Mþ¾ l;Wàøƒ°˜‘‹B餛vN)Up2y´çN¹²ÈG‰,4ºÀ‹/¾x曋tÕ(š¡Ò_:dÔb£¯R¡(ô"¥3è›hfmÑì왳„Ù#ˆ¿ëQ„ÞDÿh2gΜ1ª±Qíó!¤˜ä4áÑžÀläСÈ+¯(<²ÕÖˆµæhÍq˜Óœ>5XÿukkàÀÅÙÙW^YEYçºä\Ÿ F¢å²#ÉÊäé޾åDÄ#íJ„®÷ÐOžx¤*ºq+•‰©\ø_LÎSòØÅŸó)þ ¯­¿}èö·ŒXàŽ)þ(4Ý Ó¢YïÓòš“Š+Ð ŸŸ×5ð0KŽtpX}|Ò÷Ÿ'«¥è3%+E 8¡1zU3Fï3«à;ùʲ„©óô?ØþP¹¥Þ|ïκ÷dñ‘êùW‹[Žq}GÔ/úލNW•8{+@|à/ÜöŸðü€Ï˜F 3ù–(LÕ´š·sÓ“ÍvŸ•TD»nŸ?9ŽLŢ͟‰4 va"œEƒÍ%¾"Ò¢³çoøñÎæ2_)9®²»2ǧÂó¡ÆÉ”>.÷õøJœÆæv_k«¯¹«¥¹¥ëJ¨vøÚÓUß­'ÿ$ÈŒ>=9®·«÷ŒO4×øªXµ$ÚŽ“{õOH“£[z›{;Û;úZš«|L£¢ 5šdšóÁåÙÆ¤:‚ÍÚuÜŒÑç“e‡¹¥öÅŸÛl½ãåNñ/ªª±ž}(/ÿHr&Põ›¹é½ÿOÛ¾ð ieß/>`[0ÿäFá‘ÏnÛõØ«ï?z|ô¾k^»¿öyôžæën8bßuÓï¿~ÓïœÃÃÿ»˜3‡zÿþ¸c0ö]Ù÷}|Æ.Q‘}ɾKŒ5Y’]…!E¢±„™¤Iö-*k(Û-D©cMY"YRýf(¹Ýîòýãþî?3÷çýÙæý>çõ<çó>Ÿ|ÌvÇ0T;Æ™4^%D}ã\üã­;8C’T]1¸ûúÙO|íRwt”+õµƒ×SKÄ…Ålõrìœ ®™ç”íŸMñ;j4.âŒUл¶2öÙNñõP,°{óõ«Áªhó®ðh±Xzíf‰“Ý¥WÛŸîÌl³'iN:ÞÙŸ‚,}ÛÀ’Uu‹«Õ+æ´u@™‚KRJrú®$Ì2Œg†ò|t„sLJð£<ˆ’0"daH¹h!¬fáLèÂå€Å}¸WvÌsÃä0^iÊ-‰¬‘Ìrk/Lµü`s?}ª”(k‘¯¤̉;ð@ }@£ÑŒÕøV[‚ô?ñSm‰Ÿ—'q«ô·2ÇSÒ;ÓHœÅ­I$X%œ° ` ¥ 8&91ôïm»ÿO‹W¶.àêÿg˜ˆ÷+¡`ßOIJñ“C’­$>ŒÊÛÒ8ovšî+{+É ó–¾ ·åãm•f<QŽ&Ë›ð[¥½x^ÖÎóÓ–Å|Ì‘·ºýZ¸(kü‰R…FœDפ•þ3S/{o€¼P`rµjt/̤ça.XÚœIG™ž&}=d"Xì“Îw+.¹‚lÉ=ŸÄPëöÆ}@TåÒž'ÍÞ'1´L¾¢¡:#™kèÎ:(6‰™7¯SôŸ™Ð¬t̬4ÚåšÌÑ+xvþTøû7arÁ—¹ n?ÒŸ:>jÛaËÛ+›5¹:žw7l>0Ý4i _X#^töB”G¯_]¥[¾mõ¥zûºU‹ºuz%'ÈØÂ¶ŒÁœX=ä¶Ô‹ógõrÜ’eŠpü•%IÐVRÂ\ öl¿ÛH¹3U)@bÛø±©¯/A$sç鿉t på=àáëïJT)@d2ò²Q¥d[MY€Øüïäóï„&{¢|ä•NŠøi/øž±züx[†‰€qñãav#Aºù^\¯AqÀËð–|À{éƒ;§äføt×ì´Q¶YÀ¬óâ†æÊž£¥=eêëë7O\q.:¤eVÛ3)ª)Š=baJ=A*ùéxr2às~ÙÈÞ8û ]9Ç>»ÖÇ´LQcæmZ¥™œ«C¢§íÆ "æv =ñ¥w}=Ç ÍL‰Ê™³ùÊä2¦8GBhÍÕ¼кß*ež[ÊrÜ5¢}ë®æ¢)ß\ͪ=æ×7ÿºNÖò€—ê»ÐFÐ ú !H _»”ç—ÂBdB°¿X€Jù Ô, â *}[™¢’¨‹‘Ì´E¨c-EГBL›âc0³4›‰Xä §ÝÒ‘9¯;º rõ§:ÓîÙ>å3‹C?Fˆ}¥m³³4äÀnHç€[°zu0å}& €€Òµ]­‹vLjì«C{”¶˜à²Ûj¨L8û¯H²( ¼í˜<»û]\yÍ<Ý·êÝ ¢L|á ±ØÊ#%&ä¶[ÄNˆŠþÿl¿íNú'»ÿ-?®À_N©¥¿à sq4¼emȬ²³¹Ÿ±o!þžÔ¡|‡aÆœ…B7Q¹3âᆖšÞW<5eI¸SIQ›`L5ñé8%fÈÒú~¤.÷`Cˆd†åðü |XM}Ý–(1_(CU›`ðÞ®_VÙaoÃ}¸¶e©yGIL I9§¾kõ« PÄó¤¦a´Ïã ¶;8ã;ÏFMM!î²¾pPëõ˜oøM§'V²dˆ–¯¹éBË<ǦU"ýÙãÌ>6j˜àzӸưÁ™²+ÅXŽÄþ³7ééÆÚ9]6ÎÃ?µj»±6Å„+”:Þ;wø˜Nj´Œ–㺚Ðw~DF$|;"F¢;jEº“¾P€vñÄÚò$d±þ¾ìJ´G÷t¤ÖªUi?`Bìf€bÉýy®I±IÆ$.‹P“‘SvUBʺÉJÉÈÊ+KÉ)º)H9É:»J) •rŠò¤œ³Âï‚c—Ic²§¨ÛlŠŠüÕÞ·:ÁiÿR¬}ýNmÁ€`-³&5Áž‰æìHü¥¥-8í¢@ÈcwÑ@óo/ðq‰€zÖ`€ä'ïÞbBžÚEƒkؾ$Qåœ`uöÁgõnEvVò/>ÌìkÒÌ 7|U•<ÑdE¹XyÅðà ãD½Žóm_©ç^Ñýq¡›O…8´:ƒÀq2%Ææ¤ë(P[B%’]9Yþ…Y…ºåéRdí~¡7Ç*-îÉë‘I½õqGÖÉ7Ô ®7 O·.ò3“UwçVuˆ‚>ÚÝi¤“ëð f«Ñ÷R1÷ÏŸqòQONJl ­ãœ¾}•3—E±ŸÛÚQrÿ JgYªgŸ{ÒºŽÜ{){7y5C;æ–v+c’ª8p}86åFš’_z’„võ}·ÜfvÚ5//É^êÞõe«‚<¬ˆ¾ImÍáãÀ×á€Öx|X«Å Ô¨_“ˆ>™UÕÏ ÿtK€.·”Uª)*(Á»R¨«F(·Sg†”sAqFªX16ŽÞ„%s {rÉf:¬¿AœµÞÃÎNBÆÄc˜¯täõÍHŒ ].£Ó5¼{ÛŠvþcWÔ>ÒFƒgüÚž”ÉbÙ¼®“³þ^_¾c jÂëÒAšhIÇÙÓ5:·½§ÝnW<ì‚8ê{w¬±vXéÙÊß8mnè-Sp`¦#È>2=‚‰÷¹îKOw“ñQ»ˆ´¦Ïl’…µ*Žu®cr×GNâ{V8áØ†˜gE Èœ¿§´É}[( ýQqÿŠÔÊÀ¶¶Šý“ í„T‚€yåíDBa«‰ˆÍÿœZ(ðy&òLàÁç 7üé9áŃ>·Qô†r÷–îXóåªsˆ{½±5¾] UÚ Ñ½ÑBÍ=¬èõqjQéA´¬]yÄŒPOêrþlê1Á¥9º×ÞxíÉ2«€I¶”¾(( £,}~Õ¦óØ^²7nA32¦ÂŒÒÓ…ÆO*×8 ¶ÂI =–»¼—÷ÙcY?hÝUr)òq‘¹‰AÒI==xemü59Í€}h¾®Ø4M†)¸!UuáÓ¸„-=¡¥èõ0ÿQÆ}5ºGçæ4.G¿¯åx¡Vžè0$fïVÚf"YEªDÖº­Fí‹ÌÓJRÕòŠÒ¥³}Ù‘’+F–—ùä…Z”}\"Ìî]£+Þ#ÓõáiìÅUÇÅÓÆÄÔóuM|BŽì¢wºED•„Ò•õžœ.O)áÀ¸½sâ9>&ª›í‡rxʧ¯fÚZmu@t±7ÌNz@`ÜÏÎD+¸rd¬®Œr|ÕÄRYÏÑo¡?­Œ¥{# [Ç^{ø´æDs‹بÿ´àH£VFÛÂN«WÑßê¸ÂK#ïìrK7‡ËÜðÍè¨ð¹gsúÓºb8&Ñ›¸3î‘SœC+¤cž[]³o }?çÝ"š$™tPñHóعÃñ­”mýùÒi«>k!¼Ö’LÇÒ2ÕŽÈÆ¼,‹c{côájYæDzß賸Ä|jŽÀÃ7¿H‰~ð—0Ú³s3BÍ #1ÛªÞÔ 9ôû\ë‰ÚnÌùKí#’5î2“Íâ!zâåÛmÌŸ¨Ábôcuÿ§g@¿%x-ÁYwHäÈ:ÊÈlÁîè.ؙƀÑ.Ø©ÿ³Ôç/ÎDåož…¢R¨Ë;ƒ'%„‰Àï—ƒXeÿŽ­.¾ÈS„_æéíäŠô;÷ðîœ ÈqËðr‘¸’¸oÊ:nÊnV‡Z§¾•|»î¾Ãy¹~E_÷¥ØüôQóнð§ƒîüYTWÆ)êWÏô…R'7»:Â%ÕÖZü{½£¿4˜uª4jä-{¾B6òËç£\c’Ï$h[ R§œî۫Ϲ¼_=Á´§ì³×¸9\,kJ•#¿¿š+8UÿÆ¥ã°jH˜À2Ó™›ÉÑ?t ƒµÄ\ ¿£€Œ:kÎcÞ†? îe­‹ä¡ôô±M¿:ý¡)iYKâõ¦JO½ü‚PÉd©È\Ïð2mi†(:ÝV•j‰"þO‹ ;~±Mê±]N•®2ì!ìÁÃâ’ÉŠ¯XâL4­•dNŠì(ÿ ²öZr¯gz…M¼‡/®& å ô&H\T u€ÉЪ©Òpe,)‚Ó—åŒ&.hò ¸k^‹ƒ©sl R;òrym‰›)2ö[>ºgÞyhÜŽüÚy5h0´ZÈÃÜàäT½8ôÒ0rè­èükWéwèXû«ƒ$ϰZõ6Ëè|J}úŒHž±¶ò¬üšÁÜòû®_Ï ãßÐIã)ü¤-¹’³ÖèU£Æ¿ ÙûnV1#”]ÿë³JÀ©ÒÍ„·T‘³ž*¥›ÀÄàÒÈH 7ò²jo¶¥Ñ‘ÆH+~lƒ _ØÂ!XùO·ºo84c㲬NZéh6©wdÙÁ"u¼>‡æ6×{{ï0=ÅDfü)P"0D¥ý×àúuJøc­ÕJŸoFLIŠ Þ½C¸‹-*-°»—øq A6¬æˆå©~ÅÜrŸ;Q¶Ù«¹ù”½€Ë®C¨–€9F`B¯q½NÒ7Ö»s‹aU/E~6Ÿf rÌ?›ÜÒœ™"œ×HpBÂ#HóŽ…X¥©3ËÐ0£ÛÙ¼|‡eÙŒb2$ÝÑ'åî)¹Ř5^±$[yd´‡:õó‰y¡}gV—Áš"kJ^ºÚV@ªà¹É8šüÞûÇ;ÛJ¥—Æqêí:*ê˜5ž°2PQ/ïËèÑ¡Âuº:¼––â{èØéÑ[ôI1‰ÒzxÓþ‚´ýl¨R×]¿JO¾Æ!dX8ÚSKÑâ>úµiâ ô‰/"䙹’øÉÔü¶®üòÔMWcOÿîút¤”\*í4ß„Žà×jÎäØU†Ð %ñŠ|Æ!Si'’ÿ¼ìþ endstream endobj 506 0 obj [ 226 0 0 0 0 0 0 0 312 312 0 0 0 306 0 0 0 507 507 507 0 507 0 0 0 0 276 0 498 0 498 0 0 606 0 529 630 488 0 637 631 267 0 547 423 874 659 676 532 686 0 473 495 0 591 0 551 520 0 325 0 325 0 498 0 494 537 418 537 503 316 474 537 246 0 480 246 813 537 538 537 537 355 399 347 537 473 745 459 474] endobj 507 0 obj <> stream xœì @TåúðŸ÷œ3̲ ÃÀÀ0̰ŠšŒ ˆ! ÂØà âB¥A(¹”K‹e¤Yi‹¶h¶gå0ZaZYYÝ«{¯·}±å¶s³Ò æ{ÞóÌ (–uïÿöý¿oxÎï}ŸwÞåœ3N tx‘ ®dTqÍħЫ€Ý jGɨq£ß-œ´Ø³‚š'TÛso>”ŸÀVc©º†ùõÍÁo³®qŠÇ.Xh*zÌõ5ÀrLV®žÓíí†è~í$¥áÊú­òc@õ»Û—‹/Áä~Ó®Å=ÕKÄu}ã§Ñ—K·€ë¤ún9^^Ðýz]˜{Ry•~鿬² Û}¾ÿ4émpþV¿{‹ØEõHïƒS²œà‡&Ýo™ ÁЧÍà²ÓmOʃ² 2N²K`÷ƒú7ûû=Œ9ݶzê.‡åb-”õ—´ Ê‚‚¡LJ阷¼OÙ 8ótÚVƒ^ù4èCB@/½Ò+ÜúÓ)¯|äôòõ)S'üõ'·ÁëRD·M=®}ÉåO«Ï¶Üf?¹¿Õ̳¼?»øFŸzúÍ£¼–÷n菉Tô?g§Ìï«‹Kx³o½bÎÉg4žvá¹¾÷…b¤í¿}¯áyˆ jCMûíü<ösÉoåó‹øD+~óIöÁ$¾Øÿyz*ž„áLŠar¨ð< e¯A¼p Ä Ç`2[J÷Ha/†/€ÉÒ<Ìû3ê(”Ëñ2€ ÃÙQ,‡e„»pÀ$܇z÷»7ÿo\×À>ú³{€$ $ÂÍðé)ÓΆWûµçÖÿ±ØÖÆõTéâ/ÞŸûä_ç¢Ö áVÔ³zìµ0µAXסÎ>U¾Óñ’Ó¿ÿ7DxŸ×¾ƒ â!zþ¿èÿ߉7 ºP¾x]¿õ=ñâ¨WA…\_Ìè/Ÿ¸– V¢Vûâ3ÿ+ýS€QØ #7 ‘ãžþß;üž‡ Ô1ÿ²¡²……ô\%œ9§èßiåûoŠø £Îù³û€üß"ÒSÿþ~Ðç1b4ÔˆçÂbáQX,Ç/§837ŅØ†qi,¯C½œÜÆ)§¯Æw$7$ô®Sx߯€ð· H@€$  H@ÿâì‰ÿŽ÷L9ÿó°/ï=3  H@€$  H@€$ ž°v€$  H@€$  H@“Eh†Tj±/~Òߌø·Û˜µ¨cPÏôÅ«N¯¤÷Þÿt_€$  H@€$ ÿ_ˆèÓxú ¸ìÆ0$~ ;€8@!ÿ×;ZH†tÈ‚<ȇ¡0FÀH(±øæZ“ ¦À4˜gÃØÂØÅrŒ™Æc¾q¨q¸q„Ña 1éL­¦¦KM«LW[^>&yå¿y‹5› kÎéUóhƒïÝÕX³ËWs=œ+×ìñÕœmÌ3îSó2ÓÅXóZ¬°fæ=‚ã˜$–ˆ{ðÇ(KAÞgzÆm„$Ñ"¦ˆò߈ô6ÏŠ¥âÈÿêŠÞ?©Ïüør€WñŸÎðýàš“üXã ¦ö²ÔÀ¬ßðýñ¿54Ï‚x¦x#D ¯ã!2Á.{¢}\g¡§Ã,&°0¦cq,¥±J6™McóXke°eìJv[îa›ØÃl/{Š=Çž—DIbY³±1l+%ûAnï‡ÿÞ1Æß_Gà×…JRo{D\.®ð…Z|ìÿ%~ƒü¶'ÏYR1j‰•Pi´à/œ0bîîèK`)Ö°õbT Ÿì ´ýª7~c\¾ˆ§—ÏæéWÊævòÿƒ;¥3¦O›:er­ËYS=±ªrÂøŠqågŽ-SZR‹Ò¢;<ȇØã&L÷‡û†=Äñ%%ñ¾\Õမq¯¬rQÜ3 pØ3jÝBOÙëO‰rò”•þ”žâuæ$>U%u¾ß cÝ+gš²2Ñûò¯1Ýä­u39ëg·™‹‹Éo5.·£ŽzßXKڳ혿¾q6wC•Ëm77»#Í£(L|ήvÉE|ÅÜ‘£ÝP×à+å¶—ó~™JÚꊩƒ¼.s•käy¶2väÁ ¨åýpGÆI±–´¹fÍq'Öfáúœcr’ÜŽZt_­Ù5»–Ï’YçN?ˆÍ%É-Ê¥pl'äögæ#²›\‚A¬å³…S)^Ì£†c‚§KŽò5ÜäbðgÃV|9x¨O=-£Ëx’È‹Ž.3$Õ&‘üJ— ¾>),îà^uéÐÐÓ'jç”]£Ü¼C馒ÙŽ:اR…¯ƒ¾Úúï§À}ákKóé,ó'‰ܹh°ÙÄg1Öä†J“Ë<Û\kÆ5ä¨tñ±q_Ëó[^m.¯šì’gÛ·JjúÄ(}ÅÜ„Éþˆ0×`i†Á?­r|Œ<ÖŸlj 6—W·ñÊ; Á„;­´Ž­¿jHÄ Üš¥xº™KëÍx‡*m«ïð®œÙÖîp´5—Ô5åu˜ÇÎj3W»†ä¾Nt-3,åME@9+¯••‰gϨv3[]Õî`««'»véL«k\ £ëFÕ¶§`šk— ÏvÙ*p+7òˆ‰GxM1,ç7ìr¬”S%Ù Ç:ȶ`¿AC‡@6ß& M"›C¶qÁIŠmDãq[bšÅ§ç¢ÚƶºZ¾¹ §™›™G€[0hg‚RãV™gr«Í£¸½ˆÛ‹È®äö \,š¡sø™ÔVgÆs ” Œ–¢È«4ux½5®¤ý†ÎÚ$\jSQ'»Ü!xö+,gb¾1\ëÐ<ƽ²¡ž÷œ.^6È2¶¡—­¿BÌ2Ö‚5„øjÀ¥r¾±PÎ N \~%FÜ+kݵ¼Q×ÙµòrÖ¹¡Ì<§êTXyCöÚ¶s®¼7q+¨,Wp„`ß ÚEF±±ZrR{Þ`Ƥ†:z[‚†j\êt–ª d™G¢d-«ÊàK>,Ñ¢ÖªÜ!6¬yXmã[Ra ª­¥Î˱+|°m[=²ör¥¯z“Æò¾àïØUžõ)^MUL4/Æ“…wZ®)“ÝZËØz<ü©¼-æ!þÂÁüŒPûêØGÖ >r ú]´Ôtxï1/Iê%Y™f~sà  »paCmÛ‰÷”Œ¬Ìà­ZÙÜÖ¬í¿ù+XÛC4‚'Düj¤QK~˜8¯W‰Ùp3ª’h‡Y¨ Q Jb–8†@¢˜éc†8Ð3$1åIŒÞ‰ºUôîE£9µt—ˆ7•Žl‡Ãq8Å¡ÈBää`d29™‡4#“‘IH8!Cä[ñ\~Ï 4Œ C[Š˜5¨‚ä‹F• RL…bÔOPEìu*æ!ËBÔËP7 @=ŒŒ]OÆa‹ Ëš0· s›°F–0a (…Ÿ= ÆÄá'OBâGOB&âÂÂaJûžbß¾%"|Cøåì$|MƯ_¾ |NøŒð)ោO< !ˆ)öáC1qÐcÔ#>ðíˆ÷ ïÞ%¼CYÞ¦Ø[„7 o^'üƒp€ðwÂß%¼Fx•ð ub?áeÂK„©Ù(ç_Ïž#a!ë ãë4‡Mˆ „t„0B(AëÁIé`‚š "„‚ A-Ÿj¥c ò_¨¨_£~…ú%ê8 ¾ú껨úNË›¨o >ú8êÔݨ¡ÞŠSq j[Iž^ê çK~ 9g1aáB+a4aùa$ÁA("Œ œACŽ"DpìEQð8ï|BðåN€}¨¢Ô— Õ4ë©gU„JÂÂxBa¡œp&a,¡Œ0†PJ(!’ IÔy!‘@0â BAOˆ¥aÆ¢7#»PA=†zõgœàŸPDýõêaÔïqV¿Cýõ3ÔOQÿ‰ú êǨ¡~ˆ³»õeÔ—P_D}õ/¨Ï£>‡ú,ê>ÔgP;PÅõaÔ¨;Poæ³/t‘—."œí ÇG!ÖH˜Kn™C˜M˜Eh Ì$Ôê3Ó ÓS S“ µá,Â$‚“PC°läê,B&!ƒ0NH#¤¬ ÍM ÁLP$‚HŒv$8¶"½¨Ý¨Ÿ£c_GýêÔ¿£þ õ¯¨¯¡¾Šú :zê*Ñ’x™hK¼”Ù/)[é¼xÛJ犲eÎåÛ–9Õˆ-+_&ª—.Û¶ìeʋʖ:/ܶÔ)-\*¨–”-r.Þ¶È©^Ä4”µ:kZ?i=Ü*F¶Ö´Îj]غ¡õ‚îlÝÙº¯UìðîuD´Vº²õšV!ÓheaܜԪ-]XÖâ\°­Å)µ j†na[˜ÝÂ*[êZ̵£%%­”çÎo‰Ž+Õµd·8ZÄóËšœÍÛšœšššV4mnz²I±¢i]“°C‚£)D[z^Ù|çóì¼ CÝ+x=¢ªi·Ð ¾º^v.:àtÄÙ¶¹ÎÆmssl³œ³·Ír6Øf:ëmuζiÎéÛ¦9§Ú&;§l›ì¬µ¹œgaþI¶§s[³ÚV圸­Ê9Á6Þ9í¶rç¸måÎ3meαÛÊœ•elŒ­ÔY"$âð·9ae¡I]gl6 ÍÆƒÆCF±9þP¼°ÂÀÂâVÄ­‹Ãð"ÐEŸ¨_§ß¬ß®W„ÉQÓ±2Bh_.d‡;Â_ ?.Aø–p!l]Øæ°íaâ„°aß„yäíal{è“¡¯†ŠBg„6…Ša¡<.ê¡¶œÒ0m¢Ö1Æ®‡ÛµEÚ Zq–9´¶ÜR‡6%µ´H3A3C#nÖ0‡Æš^úÊ«*Lø&Ä"xCˆÌÄ0B ƹÙÉ¢KÅÇÿgS0v Ôd”wy'–»ƒ+§¸Ùj·¥š_U“ÝÊÕnpNžâjgìêÚv&Œ®qGòÏÖåøªµkÁ8ªÜm¬vyÄ-[Œ£jËÝ+yØáÃ^ÌR›1}Aë‚ 3dàuú´,lÅ_ ¯ÈÖ…€ƒð®º¯OJs¼yÞóåúsý¾Àœ˜“òQžwåÔÏå`Ùƒð †#L€càÅŸ½äÚ(Ï#Ÿ=>;wÊ~æó±ã|†îé™›ÑÇâ|òoòÍÆC˜·=è÷_ÿ^{Å7;äï=˜‡û‚§ì÷ùâyßLðzžè)û’œæ‘Ë=ÝSëqÒÿÑË;ïöòá?áSÙ3ä=J=î=žãÌýÌëèëÛ°,yŸ—åöÞexÚÛÿO‡¯ÑÓœ_É3ñ|ÖþÌ—Þ ÿ‚oàˆ|=ßâyò=Æøh9„±“­'Z~ÄŸŸàg8Š3ø tõŠuÒÝ8Çø€Á&B÷ñÐq«¬S0%žiÁ,„©˜†iY¨üª RÔ=)á'¥húI ‘-l‹Äó2†Å²8fÀsÓÈX"KbɽÒô=)&L1³fñ¥EË%õ=e1GL¯¼é,›-Â+ÿ>—Ã9lËgƒY!Z²0ž‹ñ¡˜–-sTÂL˜GŸ /cý‘xª´ÿÑS[q?DÁïOÞQÝ[»öˆ°ö2z$¼8Sç1lQL‡sÍÞX²÷[Åï×ÒQï×,Ç{Tâqqp>B÷ñ<±E‚B¨€ñP³´ìV<Ö‡²—vg=QLì%Æé»Õ1@´C‘9_¹F¬ [´F¨¢®÷ß{/û# íû™ý½Î×;u]Ï…Ú;tfç°ð¤pY#C…  ¥ÒœlòS­yy¹#„üAVsr¨ Û !æå&b¤ß2Bàq&¾ó˱¤+EX’4¬:GÁ2,1‰‚ƒÅÄ­%ÏV^a.H‹SHÁJQ”Z0Êì\tfò+ªØÔxcj¬ iŒGv=­=ú"ôØYRñ±=Âç…®)Ê%Zµ  ¾5-!*%'þŒrm˜Vjˆ‰‹ U ,«ïÚg‰Q©b,qñ^—¥kz$Æ{TzF É`…÷ø3²Óµ R¼ŸïT‡±qæïç#Y4Zs¬¢Yh´U­2'«@2³p³Õ‚oއ4,BÔhR)fs‚J æäØ ãħ ±EEE1…CÂóÂѱ3¦OË‹ëÌezûôi±ûsó–]±o‹Ý7}³sð ÚзóÀ¿ÑVvNFF­%:šæ,UL ÍÉVkÁ`Fd“¤v2zHN^a‚F:«;n¢¤5ægØE*5lRg‘7¬45\ù4{”5ÍL¥CtZ&u…PKʘfé¢ð(µ(ª£<×õ6¾žLð~%if\‘W’_=ññ„ð<„B,«‡$°úFhåŸ ¨–:ØäGó³c¹)›°à™„ÉëÊ8ÐYÄ/ —!ºÇ°ç–ÏΩµD†Ò²QP€WFùV(_»Q‘ _ÊÜ!’FTª¢‹¦´¯zý†J×mï­*˜å,6¨”¢¤ ³]Z±Ä™i?ëŠÒ9cíZ•&XÚ§7ë#bR’¢'Þqxë] ša´"â­ñ ã4æ sQëÝ-÷ÌËOJ3Çfðox¯öâ΀Dh"/= „›ñ|ˆ®ƒˆõ1¶ƒÙ!¡Uyxþ©ˆCQÇיQÔ™Áh‡â²9Íè ¾ÍIÉÖüðAyI8fÅ ôƒ9œ»@Ú;í¡Ÿè~))++‰{ðÛ»&uʘqý’UWÎÛÐ#lòtm)OÍ”3S«6yÇÔÛŽüåš!çß‹³Ž#×àˆ2á!O{\j‡p#,d€i€ G«ÅÅ=†OÀ8hY…ÕªÔwøº­—»­­J•»Ê?ïq(w—t­=¢°Ðn×ñ•mxä?P#-¾î—FRø Aœ*,¤ëîáòP•B ¢;—]ÆÃa!ÝKØßxx.Yjr’JŸš€—º{Ÿ:2kŒª{½:6•÷y¬÷KéfE Á[ä¯ñña±üÒ!5l·°ñ)ÝÆ*bqD;´2íÐp²ÔÉÉ…ö»™ï*߀UlŠ#¤°:Rp$ÿ4ÎaŸä0ßü`èÄwy?ubÄ¿pþGZñ¯´>›¬`p8ž?òmAöoxd¨ÔëF!¡KB´!Ú¡u«\Óoš7tØ9×OΜd9ÉÍÖ騢FÖÍ=;ÿæ#÷O®sÿ¼±¦mn±A#•êU)SF.ºgvÓ}-C##YfVA¼5F­ŽNŒìêJÈŠ‹TÕÞ÷ý¦Í]íÓc’¬ñy|Íâ=`Þì°ß°{roX:ˆ)>ª}TùÈH³†"&EÀ:fàÄÙ/)»Y8@ƒ·‘HÓ$j Þ}ŽkùœÎàŽcö¹::°¹!´*ÿ’æ^Å›vOÐw+ŽB›?(­Ð&äZSóŒÚîxMBnª5/A«Mȳ¦æ&hØ'Zc^ª57A›¢Ò©”J¼ê®#þ°ôœ?ÔmaïøÃäSv=ú4 Òý>aÃÕn"õ•Ùãø‰µÃïÓ_ÏØõZsyŽ÷âx˾­åA½ÿÍ6à=B%¬Ç.$ ÏíÈÌŒ é^v„: *ub’Jg˜¨;î¶Bîú8¾ð‰'—wÌ¡î/WO/­ÖTÖS}÷Ó¨HecÑÑÒubAúÈB}P÷’“<{aP¤)75mP¢&Bß}+»4:$U®Vª°Ö9]›Ô:µR‰é5SÝõ–`Õ†«$´ªÂSR»í]¦ÀwæÖàèã`¬ß×QÂ\‡!a£äÅÅ?…?~ì1û~yˆ§Jï{ö,~üÕà§êÚž”冖݈Åy é v7ú'åØ7j}:ÍŒò|¼ ‡7¨oµ6;;ÆnWÙbcã:„Y;Sr4…”‚*½F»›eáB·yíÔ™…q9x9L<£ãW-]cðÔ²)Óª=«Ÿ?øð]ƒO<¹¹´—Âótü^x†=//<ýð´‘>«ÖÌøc>`1s¯¥ÁŸñ ‹åñµ!{Ry¾Ú˜mIÉŽ×ÝWJ‰ÙÉÉÙ‰b÷ ‚:ÁŽv£º ëÛ¨l“†ÅJ,Y›˜>ÄÒnHÕ÷ZüÆcŸàR|Äû¸Ç~q^A˜¹pà/]"84%,Kot("à ØA³ðHj˜ÊÉ¿“`ËEì„„!Ó¹"¬¸ô4[²FÇCµ2¬ƒ-{ïbÉUz§ÿ“‘©È›¢3¼°0ûÂãç—=œœíù÷«ô{˜‹ÛÎu²{$ˆ1yÖ^ËUêÐ,šÍyiúî'â‡Æ’¤6ØR̶8Õà´µÖAé)~‰ÎH³F0QÔÄÛR’mzÕÔÉ%àUúãÏ#SqãU›cééžo<Ť~žäN³@¯û«ÿ5K~ëõ@«ÐWÞöÅÆ?¼¡¹iý‡7VtmªXYWIe’iÜÊzNá†Û»Û§MØztÛ­ÇÜÓÇoýñ‘9÷,9véSιoqQÙEwñ§U\E"îåxH‡å¾§»ån ñ¸yžÞ‘¤Òfù{ÅgLSm‘ËÃ,Ï™Ö7göË…þǯB~üýÅÑ ßðS}ïâþ¥ÏßÏìÄU°>HœtîE¶]Zé_ ×~°qBL¦#}DÝÈÔhUwˉëâÂ”ÌØ ”ÑõEQ‰[=xë±íÓÇßþýgm¼d^zÁxmTžðæì»,[zÇäsïç+ån¾æùùN/ºN¾ˆä·NùÕÐöŸ©õø®’ün¥O9lJ_üÄWG¥¸fÜ%5Œ^à§–ð 4¯²ilö¸üøìŠ™3+²KZ7×Ú¦VŽˆ RbV­Î.:8ÑeŸ0«qÖølvÙœMsE'&Ç娯©“Ò’bްfåddŸá\X5mí4[hlBdhŒ9Θ§‰O2DY3(}z]ã=*~‰û3ª}»”†±áÊ¿"ð¹}§Ãx|Gå2û¾®ýè»ö_ËÔó¾x|Ë%ù—œü\ð¥ü곇?ð‡œî=*z5R‰×ð—!i«1]¯9ÖÙ³Ñhô鯄zµZ?ß¡¢ñl¹ŸaR`¼ïÓÐããAÅνFÓÁgZ}âÄXE„ï1ŸÙôöXù©M÷^p žß<ä{²Äoò+¿ÿNœýˆû踮2Í·ÖòÞ«}ß÷Wû^ªRi--V•JU’,y·ey‘¼&±Ø±c›Ä!±³Ð„Ä4ëf9Ð=Ó ¶d[à– éfB:¦ ¡É9™tã9h«<÷¾W›6Çqè™S稞žKõîý¿ý!® å/ë3(ÄDå>†4t¤#)3M¢í(ÚB0–t4’T ™ä6PBÄ($Ä H~”Zv͈ÿJ¡a8öÎÁæÐÏÕÇø9<2ϧ=âÆFsTDèÁ a`“¯–9ÏÙœ¡s.ísÑ Ë˜bABjˆ&£F=˜7»,Wôòº ’ÓåþζAòàuާ1u•ª6s”ð*i}wk4m“’¿K µe©¬šQ¡éÊkJ‰®+ÍØ%‚_ÿBòÿp¢MK+*¯ít´B,gПTÂŒ\L´Ö‚©ÜA p¿²ýoð>© ¸ç e"2Ñ™RÍè°³ç%Œv_L„–Ê1ž1“@9&¨#5ÎgÁÌ_†³½´è¡26ô°ivZ­.™Ngê“Ä>Îg©6¦ò_T´®+ÉØeÂÇ5~ ¦ò©#eÖT0Û­c”è¿W²5ÕD¿}Ûãó¡•ÒÊw"»ZÓ»"h‡\Ť&à†¬ « "tÕ‡ ]Ðë¼ +™ÃV_Ò±àÍ`?wa=–€w•çİD›Vî!÷ |…KcNsa–Ãé.÷‹7Àó.fèž¡ Ò"m{&Þj¦‰žÊ®N2tá¸JH£Ã…»+éo÷A…ð=죨gÒåÓ¸P&yvN RE•ÿ„\E(!dÌ+%¸Óý øñ[‚E¬HiEÖžc“—±Û±aŸ¹`¤5ôãœ:Dïó¢Þ_þ8þZ;Gãq¡ö©É§’s¨èœp7Ò}µ–O‡®Nd¡OVd¾òá…ÕýbjEhŹåÒ@Ǫjnü·®îuÓwTÎ[ý~+ºzú£Si/뎎¶;+_W²™Ø£OFSNEBìoÿôL´Í¯Eû:¶©›ÅŸ`ÝÖÞ]ïªl€y»×¡',»üšÆ­ì°'ݪÊ[Jgèå¦ëÿŽˆhGZÎózÄ{û  Z´eÖnA-N®cp6‡*/FãÝq,šC÷ŸîEºç_š¸Êý¨²‘žEÌÅJ„"þ!±%YØÜräg åG¾u88žo53¤H"bÜmcY~¾Áé®T¹ÕË)þÌbÖËú~þ¡‡_|lPª³šã «§LvS|Ó½¥MŒ{ ƒHë‡ P$ÚŠGôBñóƒxdÑØyé”iŸ#y”ª)æ ù¿¶ÕgÿùñÊ«m½ðX±òGGáð¶ýû7ÜYf1çÙ°vîþï<2plcb~{hý) W¨Oa0’ÒÉ1÷]ÛUv"6Ρҋrå¸9Tq^2¬CqNPלC``/Ôi½è8Íb:. E8ÿ8P¬ \øQ¹]%’Š B,U.£€[äv“GGñckY³É­£^&£G+®TÄ:ôVg@¥Àè]Hò©˜Ã>sÉLÓ&Äl"*Ì(:bm™±Oé -sl^ª^ÕsÁÂ.LOµ8%WTþíC#I8´gk‚eV Þ¬ãßn‰T(LJZù ԟaÝa8º ×ÿ° nœ±Z!Kxâ<â“=‹= Ô¸U"$âBÅ  1Ä(ØÙÚ¶K=‡vœ‹í­ ¹ž3ÁÔS™¿å¸¹W#´ÃZK äëÚ:;g"Å´@‘¾chèäÆDlݱ¼­×tY¤ ТǭֵfãÖð™>;ºæS?;]ºgSÐûm^TàØ¦S«×}pCH"ù9¥qnØç¨ üõQ¹Á¢”ilZ›OO™&¹-dvƽ_2¿³·xx4 ÕäRÓ`t¨E:£Nnöj1ÖéMä·‰˜€.lº`Glç$3Z!ŸC33¦)Š3Çy3¿&t] ¨‘m ùu̽q‹äºH‘ˆpLÄ€ð÷íÖðµçê(uò.°KÅ žÿ ð\>àƒˆûÄŽ~K‹º@±ÓòiSÃiu/vZxWµž&¯ëë:ú•;oÿû£Œ%áËPÖìH$RΘikŒõG-4úô‘OÝÖ–ÜõÉû±}µh8ÿ¥ñ5“%3<„M×îñò!Ì`|N$~ÑȘuê(f;™£heZKV“WÓ j<µ¥’FõžlÔí?"eήdç+'+ߥIM&K[hâÏØŸ‰% 'T":(WS8Nk”øÇ]~5ìF‘]û .‘«hB¨ñ»Àø‚×ßL‚ñu ërâ(Å ±“˜ÃÆsT£ÓK<.ã°æz&3˜Ž¹h¼9¼>lCÖèz9­Ìrn¬6 Ü…¯4…#ÇI™«+Ù1à‘’_Æ¿HÊݹTKŸGAVþ(Æm©pÒDáßÁþ;Á˜ÁXÆJ?ÀfqÚœ …`ùÀO™1¨±Ûç?¢Ò2 ¦¯]›ÇÞQ¨i‚ Uòy»¦¢ Õ®²a.ÿO ‹$²öÄ}1">(ˆ„!™0‚"…»Óõp%îs99°,žf•mZÕœ#BNjYJª‰xò ÔÞ‡®ÁËàø· ¨¹;oµKs45KJ--îp—Ó¡¢ßqLM4m“¿$¥Ÿ&¥æx(™UÓŠ·¦cn…€+$hÉl®Ì0rŠ(\Aô ú·_ÅP¯X­¨[ªÿ¢ö;+“`æ4˜ùs[…ÜÓç%Œî…wëàÍsbÆ6­(§5=rÄÓ/¸†·åH¦&5­U³¤rE%Qwd"›„ü>þMRbIÓmF‰ž©|¢^0ìÆzÜ>•HÆTL„“j ©’¿þ&~7þ Œ:¨·ÊŠu èlžE¼^¤m[•“+pú{ª›cR赚‚;uÄ F*é Ì¡úœé5'ŠÀùa'–sŽ:·9q™ÓæÄÂé$,s×_ËIZ²èåhÙòv¤Ø »ÛÄà—Î×sL™@ôÑê’Ro#˜˜˜œàÚ8‚Ô9¼Ì®Ð…DkNöÿw0ܪ T8–miiJ"’-ÕÄ¡z‡à¼ž+ZXÜâw«ƒ°_‘ùðºüÑõ±Î{f®Wx{bÝ;KI9·þnØz }ïÙm¡?më\—6ä»[6FlR¹P(—æÛ{=ƒ·†ïr§ÝµÙi–YÍmqYUþµg¶ü\éN:ZséÌ%î½þ&‘Ò‰ºÞWyGèKbÉ´µe{K¼?¬FsôÙ3ÛæßNË(‚ d4éª-¬VTΘM:rfæHvßX\êLû*?íÏ'FwÛ-€œÄ¿Œ´ Ÿª÷zŸÅs=„6ÄVï’tÃ횪"ñu´€Ä*Ò4Zއ¸Ù‡àžÏœ¸\í Ö› ¯$ªÍ„ïë‹tÖ²ŸÌ0€œêÛŠë#»?{[¦ïØvøÊ}-Z1‰«å 6UHìØcL–“©¡VV"f„ÄW.½Lç0Ês˜=|æ¹S]R½U+Ó» mQ výDáŽ¢ÇÆÚ(·~$%$ÈcÈ䮙ݓ«÷A×ˬFÌsØäŒ×;©~›DD ¯;ŒL"AÔ’£äSÿÑÖýûÄTaíe¶™GrÔ¦2bÆ%)\v.ŸÃ‹\‚]ÿüKW»“ð_#ÁT7ñêK\Ÿð”¼sl®û¸ù 7X¶šÜË‹G³@ˆZËVʼnkˆÿÚ{¦¸ùe'cŽ»=q3£d[ÙøötíW±™N F´f%ÀÕ ¹3±*^•e±Å d)"pR¤m\ÇI>·ïÁUr§Ô¤OßuþxfSo@oÈuwìùÐÎù_P|ÙH¡ó=ÅË@ßüWjwˆG0ÔÈÚ"í^™Öej‹mF«ÇJƒ£K'Ó:ôZ§¿q,K’†\¨ç®uq’b” !ÁU€ÐQäƒ3ë†s!B66§=ü,ðÓðÑ"»°‹jÁk˜ºŒ] _;|qxš&÷ç j[ó®ÿðG~ï/ôCÔÚ‘4:pa°¬(‘%¤(uW+®:ë7Ÿx]^l9vç} ´¸ïIp•¶$}¾”C)¨¼¼&Û€iûÞ÷*ªq®éH.­¼FÆJ|÷%èËßb¨9öV ºv ÝÉ(¹¯¢eNUå§•°ÚÂãG¾LBîENÎ"G÷ŽàsØ–ÙBfD ßÉìLŽ€×Q5»i;œ£Ž–þ4¶þ­âÉÂí§)d˜¹³œÕ’mFÚY0à éárßj>'งîäÕD@®Xæ ãZ˜äßþþŠšZ]ì˜FS•9¬=´M0µ2„]o[ôšA—ÚóÉÝSOLF¾åªV=iWÛõJ¡€´ÂÉZKwœS*5ùN•'ëqµz5:·˜ÄÔr¹3Ö_äÏš½_nßi.~ÑÐê94‹nzpÝ0¥óY2ÑÊ¡‰A¡X(Ը͡˜BÊÙ‘c»Ð ьŧ£RáU!­Ö›u»Ü2ô„uhyOèhö™ÚVŒÃC »zž¼aAûd5ŽÐ¦ìe îã‹bwæ(•c€ÎzM„4P‹¢ …̉õÅçúSà·Ùœ´ ŒŒ_çC(_yñ ‘ø¿¢¹ƒ¬9“VÆxÝ49À2øó”Þoµû ôª¿Þ²ëÃ}ÉOLï ¹PlfÞNïLÇóAÒߟ2Æ“i»³vwÇ@¤Ý Ãqg;úëZ žOõâcÓ-­ûÆ2gÆ¥VR»rÒ ’Bñj׋JåÁ³›‚)P¹9ð*„™BÏ0ÿÓIÐ2BÈ ¬4Jl#°§‰¯A˜£s|k1|ÏÙÁg¢¯³Eý©\Š)p©XÏ e±|@ü眹]ƒ/œïj5ý›8´u"xuëdV~QmXΉÿŸ>šK–.ÇŠ&~÷¦9”„øE¿{þW¦ö‰žÞ©Á˜ 86#D’¶M‡{Îkïºûo÷üì®ØðÍ“±|Ô€¡oGBÙ‰§J§*­M+“êuŠŽã_ÿÀÑožè=òôVû¾{ÜãQà… ×߯>¢Hr¨Š‰VŽ˜`<3鼑kl°]ÌÅ ö’¼Àµ À^Á¯$ç¯$¯p}fÔÍýÍâ>îfßÓà=ê‡_)Â>Nˆ(œ:“×È|^̹’Ï3æ„Û·ÐU*Ü:à.]íðÁ:é-‹K%Š„ O{pŒw ó‘šgÇ^äýÀÐæG6G$2‰Á ôÔpýMÁQ ‘iärçl  qG¡8²Ô–ƒà}vµF“Ý5’méïÊR‡n!Èý EžÝ^\7`…+æ#m`Î9q!Urä¥Ã _>Òe˜ú@’¾_å’î+I.óŽ:˱ùM hM9´@ðÞ¤¤«ÏrnÁÑäNs— ýn¦šsŒòøCÚp‡KúïŸÏ2–ø¡úÖŸÞjêj ê¥8*6Äýn‚Ý}« ¾|ŽîïO≌- rôU¡årtâŒ@ âJO‡E(Ê›Ù&„b1#o}ㄞGKô,yQ"O#Ÿ}ê©OC”.œœœ,nÜ ¯¨té9l[N\´€×IP§Ÿ¾ØræÔɧ Ÿ€ÍþÕÀÁ'!bŠ3…»K{K «JÝ4$bRXé´•Iˆo¬è?gÈsH^å0ìæ!Mð‹DÉjzÄÅØ,ß,ÌÕ¸<´‹€@WLóžUÀ±¢6@ú¾)Dk„s µ˜Jíh‰ ÞéôsÈfBz ŠLq_½úÚñ¡õ¾æúÌf­ê ëãtEv–’Ò¤Fù±ZJV¹®<ÍZã) `‹™P©w¨ÛèωF6?ÌÁ.’ÐK`ßYS¤´ 2@‘“Æl»íREZªT½›Þ Ü÷Ïó¾ø%ÐíÈæÙ|Þ9î†G!F-Ì¿¨5N¥S‰d“T‘Mùñ¼èpi£@W.e þ’¹Ä†ðŽð T€$·’U5è†ôßtŽÆmâ—@˜ ƒ]Ó–>Bð…&î² ±å#«ƒy-Äb@(‚Âø- “ƒ|¿Tïãå*ôvdj6™ÌL«¡ßÜdµöÑPÀ·‡3àíb9ß7­2ÈAU8»§89à…žs<ŸéƒvH• ¥pÁP-B>– /$ùõ(c.v{V.oÙsVëOÁ 'Ö˜•Vz`‰˜©I™w˜A݇¹Hõ—s˜½ n9Yv:oPÞª“äkN„—¿èq ×g‘Çg~xçSSÐï*¯‡‘lçÙ)Îv1];Áë`âa;~øàS…Ç¡ŽŸ˜Zâ ;^ØWš(• :c¶äLPyÖXT ä¡$kn²œ+9Á¥.pyAß Ðÿ‹¹>ö–ót= r\€%Æsž,ÛÑRc¡ÐbWheo—¸ S#dËy·›áþnŽ‹‘°Ïþ8¢BÖ"£çV!—±¯#b¶¸vµêF:Z](C ìÈÛCùÙtL†ÊæÐÉt-83|éê„üj c9ƒªò—.mã7ÌJK›‚\bÏøý­‰ÄÑê÷gìÕ bJéðˆ6ì³ÒB£å™Æ¬i‰¡o³,ñCOÒ&‘Ø’wÂ.•Úï¤n$/>èˆ(Zªuc^B@èpó q;‰|pvt4| Êi64º $Ï\¤Bà•åNÐ=¹% ã…¸¯3{¬P•Ú Iö†–´3¿¥°^ „íY6ú ÉRM õ°ɯ‰šXkË?r¶£lÎ o(㈛X&Œ,Å@0$qdþŒC*udüŒ`Pµ‚Êì»èü*¶ªò‡: £ €Hõ6 ²¨Ó1ôÖ{Ó­ ÞRé’¸³ ‚| J€t¹{¶¿?ÚU€|åDƒmCˆxÁèþ¨p»xQ¯5®9ìÒ¬aë†5­Ð ¦ò…5\>¸µ0\ê*J7c-1ƒÈ@m᪓š¼çëæWëžn¹ý{šeh²[ˆQø]0– Üðça<¿ŠÒ mIp,™°Á’á´ˆv‡‚š…‘*±4µïl T#yz¨k¿[†·bh)Èådï=dU£Ô=ÀÆ>†|ækÈiìâ…LN¶ïï€þ¨ j=\ÕÕ~[û“—r"4ŒXÚ{´íàU \9+¤ÉGï…‡¸ZfïÌï/ì†:¢ 3Vè-µ”<E=•¨]ww5h„+߀µRãÚ-ǤåM±é‹èˆ¨?éP *¯ÔŒ JyxDo:$yF$>fyÀ|DE" N°'Q"“AubhDzhßRT’4›myÓ£›#02L-.«m¼–à¿v<ŠôÍÚl® ¦£T“l2:4 ‚ÛwÕ“rC¬y×z¬z©j”ž÷⿽±a-“6 ‹KïÃl ¤ªž ØÎQ䎜x|<µÙh^&ۢюÛa¹{þèd ÞÈuÜÉ ivW~²°^”b®.Ï(¤KMkØF]l|ž „§P¾'Þ² Zë©%¦Ü =)xseûTäeÊV߀º2H“çrE˜0Ó.’šžf6$è×´rfxÍç¨Ér®,´µiÃs¾ˆ0Ñ×%¤Š|w7k$W "ÊZ‡ø ¥ÜÌ®Õäü®$?úwKØ´ÒÝ«½C.©‡ä›@apèàæatŒ¯,LÑwT}!I«œÑ´2úØVàÛøHÞLÏ}Ÿ’Ó$ døý*w?1Øàî•2ZÀŽCÀKXÈýùÐlW—q–¼[¶Hn“Â<Í8b¼ç(wäv‰¼¼÷!ñ ÷žÂm…»îŠï‚’^›.€a¹xÀ$õBŽ2^p”Ô¥‡,ç„U²ŽÛ“]ÍкùÚ¦ieqqSß»qóiÙr½7ä„,”uÆ<d]ùÊÊö9QÁ 9Ñf ò”îc¼^! àÕ;´føc´…ÿ®fx nÁæx37¶šÄš·š&¬óåÍl K¤R½Ïbv©€#È=µ+«‚#¦Ê“øçðŸ ]È02‰"Õýÿ#²˜ou“Å犸­ˆõÕ3(óƒqÔ:ŽêÇÑñß½ AuÑÈ5˜L£ÙÖŠÿ¹£°‡zŸéÅ^´÷…Ö¢l3*Ç7?Ÿ³p] “['º¯NL€Ê–ký"à׉—¹7®ÙÁ”[Ûü`ºˆ¾û³îè}¾#zQÙ¿µ1€ÏŸ¨u[M¨å”¬Wz­Ž«yÕB®î¥3µ5>­$úhŠ­÷¯ÀR¬×+Å«¿áŸÓÊ÷jU©í¬ kU2ò³ÒÑÕÁ¶Ã_9rçßìŽ*1[0šº™ÊÔ¤ÐT¾1:èiõ(Gól«GÕ^èž1ÚT‚é-Ùá˜ß‹è;Ã÷Œ5R‰[kñ`"ÜÓ·µ£÷Ⱥ„;·±ÅÑ‘Ièt#Ñöí^׎ÁákÔ8TùsaÔÌÚúGôÌüºp #U.»UžHéØ(·4áyü¤ä“çÖÑ9lë,"•"pIâ³ c­ƒ‰®Q+áê‡r‡‹Csèªå*QT«Ü*L5wýµKJMA¥ÿ39wa]­1ºŠd²¹7ɳ\¯iË‚,˜®n£K—Özîù‡ÛÚ÷Ž·(ಀ2¡Ât_Ûš´ÉÓÓ³Ê[[móå ~Úà³ÙüzjÉz[ðà§·…h¥Z"×Ù4VV#Tê”ÚÄêì:gÂ&>ýÕíGžy0/w·&kæWyµ?_=•jÝ·:!s¦¹³î¹Ô‹äA$ì¯í¤A6•¨A¾0c äµ5HËåĹpÑ=À‘pÜAÜvy¾ÅpS_x Ëbj§ÞTeðkþKå^ÀÂÔÞ«\Í è³æ> #†!û¯¿~˜F4ˆ髦 Å¾‰˜¹ŠBlè‰ 9ƒ|üËÆ«s–üÓ²'˨`Nm ®v_1þ.>qP€0¶X¸þ&AY,:_æ·—éÈÂóeŒ9±¬X?.ÆÜÔú¹Âù27úƒ›8_† :ŽÏ8úÕíÇ/8öÕ»Z+óšÄxw+šÚøš®ìš´}óÎg.öÞ;w÷ßx¨ØsïÜý½Æ"þ‘yðö€ý²•³æØÜ/ëHSµ~ÙÓ7ê—”¼ß~ÙwùŠæ~Ùeà_©_$ [½=öºüܺ¬whx<Ê­Å¿­ð÷% qØ/»-_Ò W~óLAf‹Ø*[êç½ZSн¾N¿º|æüÑìÞ±¸ ®Êþ¼o0±z—gåò,(ÁZ§“ÂN§’„;Ï Ý´òHmþ®MÉXlåæÞʵ)ÉËäÈÊN·øÍš¤¸ù| º# 7ÚÍ­py¥¦žØæéï ôËn].ýª|«&5ôËŽxcQZ*™íõŒë§Õž§ýcÕž'Îã`—¹>ü;ª‡•Á¥71Ê(¥p NÁž"žˆŽç¨\°ÈÊ4öAM‰?œ‚s“°WéJÕ×PïúñE­5Ë9N»ØeB$¡DjƒU© „‹YäZ\]­­f‰Õ®§IÇÜ#ë7wGhþ¥¥Îå@¢‡•áB1ÅhÜI”obo¹"o4Îì‰ÔÏìéÏ새 ‘×3 So(29èA3ö †s'íÈ:ÐxÖ—‰;mçuxÒNQ+‡[-*'´oÕ, žPÈ·3Ám›œÊáRÕÄ‚£|röÿ܇Ý ?Ø[Ù='6bZ†1b:˜[›v¶xÕžÎòêr§'±õ¡5‘\H%"p\ȈÄlv(æLØål×Èê‘.µ–{e:½&²¸4BƒÕ(5úŒÖ Ýì å6uçö—ŒR#“il:“S-Ôè5R£Km ØÍŽPn#ùiòòò±o"­X™F¶`ýHrë›uûU'Ns,ŠÌ »½gºG%“©z¦‰òýHùüOlÌ9ó‘Ö-û¼oD†Þ‹€×úäëì¾âú·ʧe°óÝPxò)bŽOáÙdcG<ã_ºì9…ÛøîÔW¡w•ó)¯`åæSl±D57D ©Åx2…ü4&ÉœH]å]{•’–‰÷¨¼Y«Í¯5˜Å¸ˆ†0”ša¸1ˆ-ko˨2ƒ¾eï§ví|b[t9:ÅìÔH¤uB¥ÖœÚÖjØ´=ÜjLù—Á¯óÆè÷í-xHBÝÇæî‹4wÄ6( ºë¿Á#Î!mÈGy+½¤PHÚýˆ ®jž×-8EÌ6ã*X$µˆ¯®‡Ç9!oÀ3¿À%ÉùÄ•„¢vlø¾ƒÏ’–vß>ì1ZéªraûùNâ}‹Y,Øv ÅN È㡨j‘ÐoÀ?q²"íä1d Ùza¬§'1•ä¬cØÌ&þ/m_Gu¥[÷VWUWUwuW/ÕÝÕû¾ª7©[»Õ’l-^dY2x•7lc°%Ëf‰!Û„†Å„„ ‰= ÎÂbK¶ic'ðoÞ0žÉ¾d& Lò’b&Ã$Á­woõ¢–,ƒ3¼±>«»JR×½çžóŸåž{‘õ¡/íÚ¡í›6Ñ¡!<±µÍhb§V$–;$œ3A÷WâŠ8²ˆcŠˆRç+ñÄ •Œ!¼w87XQaW³x¢v•\dspÅÍ#¡þ0Î÷Q³4ãJŽˆM[—>¤ì\”öÖèÊÔ$_œÍ™TâzZö –õAÜ!713ƒé«ZL Áx™¡ *'º«ÒˆG»‰®©T·Gxã.W\‡ÓVÈ\¼{@nj՞0!zOW°Jì¼ëÂE\µ³œâ‹‹HâMÙúZWO¼ŸÇ¼µÈê¾:q†À ð}ðÄÂdh0_™ e.S«~‚ x Ídz§âCk1§IÚ­}¹øjbh {`` }­€ç>•0` ®Ø8¾V˜ìBV \ŸÇ{µä…s¢ÕÒeYÈ Ñá#BÑ”š7ú“Ívö/}¦ŽL$Åè}É… >5+¡ÊOý6Â'I“ ©ÐªŽ„¯¤Ó W"âûÕÒ[ï_ñ˜¿BR|q×Ô¶½˜¾›>ÆLÕs°G/cB[BŸ ­êÉ…$)”ëYE»6Ýtè¦C»p:tûóþÏ è Ë›0áw ôc¯]–¡ÿTÇ %˹,áå݃®J,ée%W·yPáÊʃ^˜Q¯š}½—¿U1…£ýx@²—a ’I]áò½u«À ­*g~äš‚1ìÂ:–ü¨\ìzIH5¹JÉ™]ôÙÝ¥2¦ÐßR0ådS¨LSè'‘”ÝH\?å^´RÙ¤»1{£pãØØiÂlÑ“Á{uSAû(Þª¶¯X¾h 3ÐÒ_IØñâTXÜÌë¦,lÊV]9‘GYoe¡SÊ^ÝŸ¾\WWàñzÄ®í]yM`!æ›E³y›våu†¿»ÂÞÛ•©~e¸«ßºC”¿ Ÿž!_&²Ä Ÿˆ—θÑ"èŒ ƒaž² Vª”ã”Ã9§\Ê•bó¨øŽÂUüöB'bæ•4È7Ïžù{ìP{‘¸ôÑ‘w¬ð*dCN‘’¸µ¹z&ÆWSÙõ;aíFIݧ`઺¬4órÍ:Q«G©÷º‹ðs'Í^Úë/±O¼‘A//òËgëQÊÖ×ëëQÎû…ŠÓÁÔ E×¹ÀÕò.HN’R•~G‰áÞ|®7$R¥ßÑ à‘ÊfÕ+4ý·¤Ö‘ S2G¡Q>ø\‰’Ò˜õdØäh¼_N±¢æÒ„Íï׈,¥âth^þ™?P¯¢y-!®Ø§!™HècEØ[àúA¯"ÛÚôE/h ¤¾{°qPŸæumÅ™ïL£×z-øM›ž´-ËÙåÕ¾#ñx¼k¶,g¥PBµjB¹Ê¡½ Ã¹Àw•éC3Õj ÕRøí¬+PG©º·Ô«´ú]JïíÌdùõª‡!¼[¥ ,Êd;ÑÕ/Y ±E0’uðä ¿FjåT0˜´óä Ÿ„Jˆ!eçÈ£¼Ç5KIèbÙKÿw–®N/ÏáŒv“U£ÁdÅDÖq—öð•+«Ã2ãAÜs/¢rЏs¶èÝJ%ÐX-—µðš"ÜZPšÊŸ"ü~\ôTA |t—÷gC‘uÜ…ÉjÕ¿Ž))ô­–¬µ/üwJYÐJàŠ¬Ð³ÙH.P”$ïTG[º¡Ù­S;¦œM±D“°ïÿŒrk&‘s Ô‘/“¹!œÈYÿFb=Šdµè,½ÄiY’$<3Øš¤µ\é{ ¦Ö V°™J»•J¯¥‡È“ˆ6âºJ-rÀ²!Û‹°çd@ædkNtAvÚ8ã ·Lµ’XV vÏ«ùŠá‰kü]4s/YFf#®Øjª«â€=LÉÄÀ?Û­¹Ek¦J´ÖÖT<ë˜ï’/ÒÆDs¼Õ®.·IŒÞ*‚8mÈ&Ь&56Ë¥oÀ­²¨VKA‰<<wP.¢yg‹¦s[W>nóÄ l±&ĉ-ð›P¦DšÈMY‰`œ.œùËÿˆ+€>®› !¤{ï:'"_g(»Îsj*uMk‹Q.¢Ë+¢L Ê$¥ö­m½÷ó Ãã½ÆX8(ñå’Fj­'ãlYÔÑáχ4,«dÎ`y³ã ÷ ß¼"„‘Ž-ÁaÕѲaÅðð2‹WkñàýÑ6´_¤y$C9";ÅÚrx-¢œ,èE÷^KFž’&²Okêx¬.†[9âruçMc}Ñ—²ºMLÃÖŽÅc­²·°¥+¹<ˆ‹g:Cû¿\y·=båYKØaoñß–©ŸoHgVíé@k÷z™)/SZɱ¼ÝÕ³ûâչܤ&H$‰îId¡?iE{¨ž*X» °ª{‡^ ÁPÈ}Ð3Á>j=0[4TœªËX©ÁY;¥)™ç,ÑìMx·Ý^zBço‰F»½¸8{(ß×pôHlxréÒÝ‹=çÈÆ&{D ù¾ÛåL¸t¬†³øN­ÛŽGú·¶ZZ: xÉ¿ ^¦e"O¤N „ Á‰‚ ùÔ_Ißä;&‹ísL ûWãb99ìRöül²x-d -”Ù˜ŸÍA/CŠ¡h¯A´èè ‚NÐŽ±RÐé ZØ]vÛšV5Û²2GCêE“MKqjƒÓ’rÅ¢ÞÒõ £ <õFc®d~´Åɨ9ÑŽ+[ÁoàAJ&:ˆåÄâÖnžXþ’ˆp˜ˆKÀýD†è‡ Ï0L&NW ¥š"ì«1ºy‚ªGZ÷EV=dx@—dÈüqÍ‹¨Ñx ä'ÖöÜ\[1¤è/¾q±µ«R…´ltë•ø¡Rtç#³dò—%É ÿÌåI24]¹‚¾ƒgý…-–˜ æœò]¹•992tphùî%ž†°ÝtÙ\ÁžÍÎFé/¼•ˆ˜]&.6»Mœ;äß&‹MY_LæTçwkìºä@Ö¦V«E^'B Z£h_Îiå¼Á^Y“qø:-¦Îdj°ÉNÓî/ø#Z³SçiÌöÒvI*³Co³p Ö†ëá·áQ„ªi"u"bÀbì xÄ::Â!F,‰ø„o¯e’š,gÈÎâéœr_¡OÓ€G‘¬:ˆC"q9çFÚÊéIÜ,œ¦ÚG%øÓw¤Zò_éëÕëz õù‹®iÅr»q|aÎÑðœCVÌ¿£¡àøsœûßmúqeÈo\VP±6¸æú k.³0‚tôjfµÉîBCª«»avTФæ…ÂpêçsÑHcS4R¥ßˆ~MD;âØ ø®tЍ(~ð<ÒÄø7lbá܇qÇ^±JÉ !_«tû©©&r*6Ïæ@0FI‚°Èáp#§þz>)ï¦x)àtF¬œÆøÉǵluô5°•~¾=ÿA9Ž~Â9—>-å9šS9«Á!§ß«Œ¤$%pÌÇ,ÕfŸU¡–JDXÛGNäýX|“b™éúÀ³'œèžðœhèÈG³ãÑIK½*å1SËÉ Â~ó¯ñ—÷Ç¥j–JdÍ!fÉpÄ–uW—?•³5þô§Ò¾ôÖÜÀµV[&•µu¬Ê˜¯Ì£ó¯¡Y@ÿZÒÉlÌê³ðÎ‘Ö ·AóO '⬴ „C8žX<ãÕ)„ª¤ |Èdg'‡%í®-í•%Í…€ÙQžIÊŸ¾.ß1šµÌ™A3ñ—X+$Z‘^<‡ÆjDšÑwŽ0Óx¯Ù(,g;¢›ðµle]©d)3g“™¦‰Õ· Þ2ˆŽ]yóPøoyGÒïN¹t¼=éoï&ßë›IF–öí_•ˆ,ß·Üßž°Yâ¡P{̲Küzð<‹F„-Àæ)wšÃ4+ ‰0sé”[Ea#Ð>®?XoZ6ç°q†—]›;m±²¸+|¡6º-ij{gaC‹¬ö¼Ï•C”ÆFààäª+Êâ¯ðF N…¿` Ê&Ó©U{ú± è‹>bYhN_¬Ì)7åä›Ë–T LŒF¾9ìT þñØSÖ‰¦§…ÔÁ²1Õ¥L©fLÍ‹UÌÝÓ–ÌÌ|k £±YNñչºÙ׳e‘%‘H;“Ûšò•í)ÏZËö”Xȯ¾ªEÅšýr®<­oε§Êèñ†â…„¦}2¡CR^ÐÈÜÿ Oøtf׸y’¨ˆ3H]:ohμœ³ËíÀâ†ÓŠZ­Uv‰õ2*…ƒ>ƒà41$P½ {Ñ+¥RÜRé›sY»ý«bÔeân ²‹Xr†hŸ?åIx[fã÷ÅŸdʲ|A9ÉqþÒù×ëÜ‹Ü<°ÎL,ûøxY­µúBÆë·­ taèÁˆ:! Ëý²×æ¦()§Ó§ejëu` ðâ!• };€íÃJgSxè°¦z­œ°/Ã{ЈÃDfÊàuÁÔI£WíE:îd±z½Zy\;IŒ—‘ÇêÂtøè_}Ô)ši‚Q4NEÅqñœKKe(Þv¹ÂŽÜ£R]OrR2A†Õ[¥RW¦¤8=^“¬z„@$­aKy<`7«¡I‚/“D£í%®yÎãÍH©”©; ¼×dh7©™ÎNS¶ªEÆ”OušH{dÜ>Y@¹´x­0é1¶ù3 _yruoÉGŠ„>Dòr*NÛ5p5€Ëqñp$eׇg ;Ýa+ Ç Ø YÒÛ~ wA¸ò– $k ÜZmé'³±Xf)¢Ñ”)¢8†T¯ú|þ¹ÒIgôáÿ†#gXóÍFÎÀ['%>ÅsEð6ÒÞ~>:îç)ç¸XÓÞ …¾=»Ìuq2P†…™j4,ªÅR±ö~–†RCÈ·rðš $îWNJ~ô^˜!ÌÊ‘##xáÝÁ¸PŸƒïðÈUÅM¨Ÿ}–fѬÔZàtŒ Ò,óå#4K¡›ÿx?üÞ‹fè%:°÷›iµš³ 8é•XÉTÏ4œä7³ºqv?y3QüªÎH½Jt«¹.œ7[gÜK:|Q RK_åHc<è [5ô¼²RÄ狚 EQ«B ó„§ž†¬A, :)]ÂzŸ _T²±yBC˜pžó 'i–Ä¥4Þ¸P1Iëlypo5yº4©úûJ®téøsT!pˆzbösþIùœíWøœCíÃÃmÃí¥;©†þ–üô¿t}Λ3¿†µ ÷%ÜÈó€EÂC˜á}§y*h_¡Ç‡~_ÿ‡ªYTåûÙÄï¹vø àlq·'f〬qç"¸O¥õæ•SíÊ)÷¼W ž¨f”‘÷hMZšÑµ\mñét¾–h¬Õ¯Óù¯ègÞÿ¬ºIöŠàW”±}å4¯¡ÑÝ@ ¡éÏÏ·ÙÈYœœ7ºoq–¨Ç³°2ëÈÅãNVãj ‡Êg²CáF—ìdµxÛy¯ F44Qø )X>­ 5áWléù-xž|VÉ µŸ LEX|ŽsùmË)ZÉ ]”]°Ë Ɉô¼€‰“÷j4åWaþ5)ÅZ:] %o èõ¶K±V|£5kǯí±ÛÁý°Ž:Bœ"þ ð*W·¯ÔÓö–9AiÙЂe‹M’là¨FÔPàý¶dªµ%‰{4ÌÌíÐ>é"dÈýHO&ÀÌïKªàÌ BKèN ÷žj%ѵÀ'K*h”>Xj1-äiÉXúU6Ëf8nwétP‡ ?á{ÁÐëÁï š ái³›¿“èJ!ê{¿§H!²î ©ZÕ>I*gyÊH-«¯]3BK GÄ®#óÃ9Ùž_™ƒkÔHZIjíK¥­?øa麗õ½+ã]¯~ÿ‡ã?üþk7Pj†d g+ÇK°äLNÌÔY4,áœ6Ë\y@h8JÏ,e—©\…¹©9oÈ5ÁÂIhs+ó¤ÎqD$zt͵×P¤­!èŽÈ<¹k”'~øýWwaÓ@†tùáÀ‘—´’€£¦¾[EãùRéØCÝE¸ ûa¶aâ4g{S'¿‰×¯â%lÂP µ«†€·¶S®Ð¥AÍ+¢Ã¤Ñ˜"Èá†=ñ‘Gðëf#œÉ#ÑY³Ç̲fŸÜþÃýjɇùfMéPRžì8C¸aCÕ³&ý›6Ý›tåÑçqIiŽè­îÖÎm7 JZôÈÒ߉ŠÕª¿ð…ò+È£ÁhK’ÇÄE²²ORSáFÙ‡à1ã'ï1€ß©^A<á}ÐC qƒ -ˆ3H¸{ ñ‘*³Äku,QÑ4s8¼Û»¸¯i‘dÈ‘u°¡;a2Ç»ˆ%"®`ƒU¥z‘÷Ô©Òñ#z i†¥×>s|zãÆéãO¯EÖ*ÉhMx<סñ¼­ŒÇ)!M™uÄY¸›04OédNÐU°„‹o›â= ¤VF#JJtÏâŽ4emºÂV&z~û5zú3k‘S1:Iÿe°êÔ)0ò%„…Š™¼öéãÓhDŸŸ±C£êeÂŽ¹B´¡ï´Zúo{c®˜×Ú 3…¢Pú™;vÃãâQ†f¼žØu†h„¯´Ã×D†{"ÃÑwàxoŠسàV¤»ûÁ-§;èËÚR§–áæÉ¦S>µl£µn>Am-7âH]lÕÏëÅQÎnAÆãÅ+’T:Ô¶«w"“ÙE’-:tö޾É5Í‹}hžáÓËvtçGÛœÁþ]‹wëŒØâµ{ÚÖwx¤xo2·¡?ËÓHÆ…lîÜxëÀ¦ÃÛ²Îö5­]»‡‡W=pS·ÙéôίÍc ‡=»$ïÏÚÕRÈí ˜GvIÌב°y‚Ær[¼’h úm‰Ñ[W´ï\Ù*@:½RÙa^9C‡U!ÄAKÎÍ0p*’(9ì?š"4ž"â ¶6*_·M%Ö#²ÞFˆ„T!R:¹Úd§[.œ¥\ÛŒÅ13• ;yxàsÅ}m7Œ¶ ϑըùP×æÞ–¿ÜyÝ Ùf§Ííƒ#,>S©ß5èºáèîæoíþÚþvÙ*å2ö•³8,rnUKfi£¬¢HG6…ý9înÏ•ÞdfË=h¶ÿÉËqU#òÕÓgˆ(|º ]"¾«Ñàß‹ »*¯#®æ¯Î— — ³¢©Éã4òl.å‘$Óz÷ëïXœ" Õ‚ ¶5쥬êWqbêvG¹y‰Ã‰õÆŽIžc!«)±“hüx×SýÁs¼U9ݺûâú6¢ËùžNùÑ‘û–"ç!Äí.Ân=-¥èØF}®^Äqøç£‡\Qî’iz–ÖÛL¿iŒê– µnèKkÕGkåíŸ(l{`KZî»eìx5ô<ÙN¯ènu¶-qøøðE(&|}Þdw‰gÔ‘ÚÝ{fq¤a°±&ÌölÂÛ†…ÙM›Bn›WÒ‰¡€}V˜¹Üʈ†[f0wÏ“eŒ‰H–…6,Ëû*²Ì7#ˆ´^…,_|>úŠ¢||ðγû;ö\›Y ba梽[zÛ6÷\…ƒm›cŠ(行r“I膯îk;wñý¢Å*l!ÙäÁæ´ÊMÃH˜›ìg6Ί2 3›ïÃ2á@Ø¡JÕ4𗦽ŠþÔ´£ÜHkàׯ¤«UÐ4p·Þ{N’õd´ü:›±iÒªö°Ê‘\Gê·q*c4`óÛDú.'% b’ÌkTD¦¹5«‹$3öV4ð¾Ó܉Õïîr#Ïl¥ÔÇP¿z4n9´×â20´^6¿ØØÒ‰¾œ?³²=Ê«y5ަ˜­Ùݺá®u ¶îɵþÆdÞÃÿŒ9êó¦#ã¹ìÈâ6ùõ¢ÍeCR‹t¯YoôºL±e»:›¶îýÔÈíÍh¦+fÞ&ûÐL×±„»LBÿKèY` Ú ´4âýíGÚa»Ø.b5ôHbßÑ{À>ÀB»S*‚t­n†[ÕÂc ªað±…¶oñmonÛ¶4ƒx“Ô \¸óÚÖTV–[×,Ú©Ë…|÷4 de/J,ÞO€H57î) zmƒœhhߨåÍ«ï f›h#ޏÛ,›Mþ&·70Ò¦€Ëî7Ðæ`Έj´¹¬´Ñç4»$Qïrš|½;gFºS’ŽV#ºnžyÑ5Dôà^b­PªIí× &BXô®ÞsÜÇ=GÑ ‰è†L™ö©Äv„xYE~Ë$¬ÊïØÄUô ]®Œ1ÓUŽe’}}Ÿøê¦ÜÆÁ´À fxZl]™k^Ñd½iŸ½!4È&Ù ]µ.ž·k$‹M7öàÎ9íßµ²¾*3X¨Ï_À…›>L%7ÏQÉŠÓ2—b´,ß½ôœÙŽ$]­å¡69ã®PÂÊ<¡Ö²Ôf{ïªìöÄÁÉë8 %ƒ’GÒÑ÷P¸=b†žæ¤ön†Ñ˜W#i ÉïÌàëQ$Ë•ëRv·Õ¯j;´œŠ5Å”qÇ”U½¨÷÷ÁqßQôB"TnëšÜŽPY£¬ªø§¯êB6–²¬dîëÜÿø®Ž-ýq 2+I†c8Oóh{fyÎaiis¤caƒl¶»`¸Úv­tÀš \sx[X·ú®-Zƒ‘×[›ÏÀˆfƒ1ÜERbR©T6/øZX+^Xÿ „ᡃDÕG¢¬¡‘Çé…Ÿ/°‘×ðÜs¾K±¯.4^ü8’Ÿ×q8WWC¾½;HA»ß¢SŸ$) ÒSVñ¨ Ò‰Ë0>ÿrŸßUðùúÓbKk¢oP zCôºôêzˆÆ/ËIRŒ(oÕIúIÏH\gItEók{4¸‹+d8㢱[–ìxd{ƶìν€ßaCj·3Š )KÂïMýæ_õMnxÛ6WÀÍÛS~Éc ¡ Ü¸áŽ®OÞÿäž/bcJéOøùšõZì%eàÿ¾ «QÆê5 Vo:-VQúš²Y¥R̪Q„Ðמ ®½*/éãÃóc‡Î}rñþk[°M¥Óóé¥;k.ÒZ#)‹šÝ5i}F`xVK‹Æ.Þüàu5 ܼêðÞ.“Ã¥38Þ?r*å4òú²F »A“Úží‹ù)ÝA·ÚrZ½½â!­¾mYûÎá¤ÒÃé-ò0% IÆ»¯PS“äóˆ†‹Š ˆ­*„ÊÛ§’«*oSä·L¶­ª«—^lVU0YñºvdôjšÄfîÙÜý!>’èñxØK³ûkzIÒêl·=dá-v‹Ü4Ò’^¦8Jö0ÌF°uåêÈ—.B@vó½DÕW¢,•§+uE´l° `i¥‹™®(¤ID‹ðóÓ.+/gÞ8…nмï(°þ‘¨NxJ_ñ©ªÊ9ã2Ç/œoÄ-!7ʼn1€ë‘¬Ñˆ¢ÇÔ= ?à*>QvóXùcÆÆÖý÷ºkäÒš»&¨±»¦àÍ_ÅîZÅ[؃ÔV™r‚*TqÀ¶¶ðDºÓˆHDHEøn’žÇ4óvÃ?âŽäc”ªøT>o¯/Å€UÐV«ZŠa](ñ2vÅã5ô§»g Q|Ó&–½`œ384(ùÿñÁxY6U¶îOÎyÞç{G’¢9º(Ö¾aIR‹t…”²­wÛÍ œÖåwï”>8ƒn#峸-¢5è·*Àù‰{¿1ñÅŠŠû¸`Ü]•ê~Àõ~}uÉÖƒLþŸyxú<|‹ yð/¸}в„"$Ùkçl™žù*=ëP· –a׊~.)¤ÅËËk/h+ãGãÖ‘ÿíc™]ëu_T]ì6ßäb+ϦCõ.68´õá9£Ã¥7Ù£NìcÛåTo´a ±Nôǽíq¤<Œ)äB>¶Þ Ø£·-/«un¸ìc¿…PQ@öÄ›¡ò€ÊÍêæ"Òe+þyxqÆ <þI™#Ú**£žèÛ§«Ø"ØöœÑªÚZGjÜ8WQÔ"/^êŠ*©®²1–±fP‰"Áã)s%öÊêꣃ͢úO€Ço86Ñ¡³Xt•(éYsÃHS5É8 0«§ÞQÁ ÒRÈîvÂoƒG¨…Œ ™ÝäCèÎ"ø ¼ƒú9ºÃTî´Àçá„rG]¹Ó‹îì£^Cw¸Ê°>Mß„î*wúÑÛ”;F|­½s& K‘=ëDö,8Sà{öWŽ[©C•xƒbÐRo°RDÉ…¹¹I¤9ö)JcrÛœ~ƒêd5K.jSC­Ëf´!,ÛUÈÁZyÑLÞ‡‰<Ñ|†0ÁŽS Þ/ÑX„ë ÖÿõqǧÐaù—Èmš¦gÉO”]¦ò)Œ ¦©í3~tøO‚whu%Y´ 4£îsþ¤M'ÝMQ7rŒ’1%»‡â‹w,ö ©uË@Lc¸= ô.ÙêuXõŸõ·dâ¦PÒ`6¨M^»Ók²I:wëpÊ¿dtÇâ^\u e&'Ðl†ˆkÏ à×mß` ¯%Ð×h![¶„Ðùµ\ÁdÈ¥Ÿê^ûk—‹ê¾=.JOS·×‡újYnéËÏG¡|?\ƒ #œÈm8Ô—\Öâeä5Œ³¡#ØÕkˆtÆ;y .)ªa }é&ok­Ör¤4‰E«R=Û»=Ë"‹S²³0Öéâõ:VkôØÜA’ RЦ¡E§d–utc2ÓKzWX´ê8Õ¬s6-Môo3@Ò•ê,ÛñA¸v!´=C4ƒ{«±ðËGmÇ#úòL'ðkA4Y°Ø¿Ðp û¬ÑúT•FØ ýì} |Å™ou÷Ü÷}Jš–f4£c4:F·eKc–l¶F£‘4x4#fFâ4„,!GBö±ä K¸‚mL Á »û !/l›@’ß¾@¢_åž)ÐQ·àûÇÔgðýcê~¦à#¨ûTÞ3dçÃú7¯nii Š)½‡Å;w°B§«hª FÖZâ1Šè#©w?ú±w3*˜äáí"݇ÝØÛ{ãõ×…1 [€›Â¿4ñr÷˜zß=¦n9¦u(8vðíã—y`s·±…åß>^ÑUÝ´Òä²°n½¨þD"ƒ»Ä‹C Îèžë½ñСnüƒX©Ue~wÓGßMáݶ´XÌ„®»þFà§òý?Q_¦?‹wàHôdʪ?¤¤ðâú:ñõüâzß9W×Ù`ôe™µÊUV ÁÈ`Q‰(‰RöˆHi`a}i›¤0îâ§Í¨ï¶KEJ§]o3(Å–´X".¢{éÏA,ªÃ±Èû8ŽEu8mè‘Ë­T]§nþƒê¹_È_=€Ô«V­ölxç¤^s-ž|û=e ¾¹X.Iµ5FüÝàeºšÁ¶”D«ð²"}¹Óà0›Õ g•»ÂXêÕ´RƒËê´ëÌF•³q ÆÕ¬îñ=¾oÓƒ ÃtG ßô¨G<ƒžÁAO'£‚TÕÓ„T--Õ¨A×@›îìEÕ”¥ú°K«5!—ÎEwüÆE=â¢\.qïu'Mß3Ѧωo€¸»‡¥ËSû÷‘ÝVû÷áÿdÿÕúJtž‰Rk!@¹iĨÁÀDf zK{•A¦TÈÕ5.¿S­©h«îV¨¥äÕJ}=›jšJ›kËd¬T$ÊšMÛ÷u»ôÁŠšîjÓ3M£-%rÞàq±&µN­2:´†R“B¬±6µ¨Úí¬Ôêµbͨ5kd ³Ae©í©*iª*“‰ì¾ àØ8öÒ7¡vÉ!Ryü¿ Ö ¿ìQ"ÕKÍTóm”Qe$T5âÏ£Õ1Á¼þžêkNZ¾g¡-wðÀ ±jß¿cÑ[«,|¨â6öÖlÏlóo ºT2Z"•Èí¾öšR?«ßªÞä4iMVê#jZ³ú®! ë ÷y^ Nl`eJªÌö&Qi” 3kñUIµfÊo1”ùªØMYÛð¼£’¾žú²Ø³3xÁMPÒ@ßD÷Š]PbáKÜôAz”Xù’F(éƒæDv\¸õ¡æ³¢TŠìG Èvœn|TnÕÚŨþÅ—ñƒ~øüëÝxC.ç¼T+Ùð%¥(˜$V¢6jÏPµH³†ÕRK×3ÏÐ-ø–òÕ5¨w­,tøìZuµÆ×UÝP¢’¬ž^ý“TSÚˆ#í,ÚÎ<.jF.dÿÒÓõ#¥ÕP¢“ðœzMx†’ð.KQ8¶¶Z¬ø5§ãǰ€“ZŒ;§{ÎüWQÁˆÕ& ƒÔZºÛáuh™ÕHi“¯ zW‹) %Á½×þV¯—4#¤>.í")Ò"+pãCõ¨ u£-h íB— 9”DËè:ôÞÄöùød¼ýŠ«»®®ZÌø3ì¥3žÙà°jõô‰út ͦæøÕ™™á¾ææ¾á™ÌÕqiÉî‹m%[SGn¾òÚk›.K´&í/ÛoßiÙIwn’lRÔ4ƒ×&öïÜlÚ¹?qíA©wvºÂ @Ô¿¨çßo¿Îèü _aø W`ˆÝ-ÍÁ&ÿiä?­ü§p^º&¿ösíy©¥0_¹¦}¡?æå†ææ†Ûðá½`c°ÑƒS«mMð÷P°±1Hãã. oÌÖ=ópCsS“‡jlnn¤žÇ'W/ÆÇ÷píÛpй [ýQ0ØøSÈPwBb'ní*8PO7Õ·œ„Ôí Í4ËWZ•BâM|Ù«Í ÍH€ÿØèè¿IKdÇÈ›N&éçèçħQê8V[«†‰ÑÑ-RÕŽVé€lìÉ–ãôûGm'ÅÇéU²m oáüÖ)üî#¿1²ŒûA-/LòvG¶‘­Xfa@ГÁðÍ»·î+Óš”"<¬(Õ._“+¸µÞÞïiö–¨•©Ö Rš´ÚŠºNßEiïý|rc¹^®µ°öæL&ƒºróE-K׫ &™DÆ6ØY«V.7håͳxíqýcÁÏBÉž@ˆËà ç“üý£Ÿ†ü“üùè· .O yªäOdÏÿä¿™m¯äO çE¤ýg„<ã¿ùgùþ¾Å “þžË¶÷0©ÿm„Ÿä¢·0·€*‰&N÷8õØQdk8N=þ¸Î©Pמ4ƒ«8)n9©€*¸Ii¿³µ#¿“D’݇ŒC:ŒsV &jÍËT™[D2¹È´iË¶Š’ÝÁ'¿ÑþÌ%Çž­j2xÝN©J Ãßêïõ5}Á`­A_Ýl¨ÑÓŸ´84bƒ·Ý§Ö<óƒK?w ã™wüÝF­Õ „ –D§¥îhÛÛãñõînì¸8ä®êÃïì;ùzÑæÇkÿ>¨º×`À#̵ƒx$ÓhƒACÐ`mÿêF‡Ø ’µÞ/æÄäo!€ÑÕÖòß‘˜òæ©yË’ìЖÿÛnDX=Z»mn#ÛÝP«urF©’W4:»‡v5ú‡#íήf,E”T#s:+ʼVyãÖ][™'7íÛè’¨t ¹ÎÌ:½%&›©®¼¢¶ÒÛ1ê˜ê(‘i ‰Jo7yËtFÆbWUÔº=­ å2Ðòa¢å牷ñÞ³àö'¬Nµ!'õMêA$Gnêqä„ú«G‘Äð$È-ÁÞFžÂç~V}#Ùy²sÏÛ› ·ð0X©Ã1rS%Û蕈ß)­ÕÞ€C%úXìk©¨²ÊæïiV®–1J“ت>3¦ÒHiZªUÓ¨¬³\¸'o£_¤Ÿõh ïˆxˆìˆ8Ü£Ô»•VÙaQ¨ï(x~@|ÆÜ»üî€âçߊ%«[sžgN­Æg1™Ïâ&qÞo³€)ã¨-±V”:´ÏJdR‰ˆ®ln-¯*Ýo÷8-ê;UzJFQ•-ÍŒš% Q”:•Jf©µ®^¦14ô“.—ÌÄÚVaq9:“AçRRq¬}nFJf¬xÏŽÒ:êg õ³c2ã+\”~E¼^”ÎÎ; _’ 7…?³ÿÄ7àxÉOÿÃ來~¿yü|E¦¿p ãÔ÷.ýüŽoýóòužÐžÖk®ölÞKÆ 2O†õlj8â’>®§Ælô(ÚuB"Q”ÐãQYA<1û¬@ÎQÜæ|s#‡¿§àášWŒ¶ø:Û}žÒãms5­ÝÏ;¼c ±wƒè—ÝóCUoUPzKéÜxøÍë=XÏüÌY{‰Á‹Ó)EªWŒ˜Ç ,bO9ÅëUPf.ÈÒ‡º'°K>n€?ºNgßVç9ó5Òá.O]‹}b’ê¦KD㨠َ¨¬O3›‘9™^Ä0È­‰`Á&3|—ž Ýü¢‹¸]‰B³z¥Z­UÞp“Ñ Pß©¬ðÔ˜SJ5uk·³n-WY½¥¥ŠY™D©8sÐåë¡Bt½h? ×Q5­; ]²Ð¹ÕBŠæ;çö3›øÞÛ¸/j³·Z³¯2¾‰¬w¬n×™uŽ{›[ÚK¼N©\¥Ô)½ÁMžÎ¥úÚá ªM©¥n9jëÚ·G«³¡ÔSR¦–›õʲ–­µÞ-Û/Ùx-ú(7ííA›‘÷Hó8Ó{ÌíWXìfÍð)fZ„1;ÿվ씙ÿrPØõÞ´Žd²m†xê¯môlj`Áßr©³ºÙµexû¾v¥^¯èìiêr}¥2…B®Uy»«çwlÝ¡/ÞĪôF‰ÌVnwi ÚP{g·-µö¶û»ŒŠÊËÊ”r£^¹?¼mÞ$RD±dÛ(])êCÍøûrPø±†q-̳Ž`ç‘Kørï¬ïö*}[ôú:«R™\.—Ù=õ®¡ñ¡Ý¥ 6“ÆGMªuZÍê{ÖzkÛE=tCWd‹W¦T‹Åen«S©VölÙЧ´Ø©±º·»ì1š)íØ \ïA§hA¥ÈqT­²<Ít#R2$bz8s}Qøò:k¯kÍU¥T­þZ¥Q^uÈ£Pݪ(¯¨2-(U¿/5[JJÍÔ“ý¦v›l7x¾üÌ+ŒÕô<íbP²Dè…~ká“&½v“ï>³Fš÷m9)à_¦Â)í²¯FµfíšòZ‡²©ÕYçqHåJ…ÖéoosêªÛT•ýývK¥/`¹Šm©ó¼Z£ÖÆZJ]¹½®»’ÝØ»£y8ÛŠ¦L õ Ú#ÝÇ™À£N§8P}xkÍð©Mn„ÁØ ~X#å¿aáŒÔY»5Úéî¬sId…Lêð6–õ ïiVjµòöÍ[:K±ã)äëÅÃÓñÑ=û©CÁ±§B«KM%¦µVÝVßÔjrÚ •AXÔêJm¹¶|ÇŽî=z‘|Š<µý0mbv öàí3öÉÉE¤úàöéìÓäˆöx[}6©L&—Élu¥#}S΀ՠ©¤úTZµæÏ–:SËÎ,u88ÙU.UÀ„Ó^j²ÊUò¶®¦™ÁB•øì¥¥ö/д½q[ z³Ø«o5Ò<ÖBjƃ°}˜[¸þñâGô'ƒF®ô\Ku}óçfmi¹Ô\ë6#êýûÄŠt’ Ì;eGTøûeî•á‚i™w´:׿ýP«Ói%ÁRo_­ÝQÈßÝQÛÎC¯åˆàéõõˆ¹G ÑVBן‹Ä0æH¢—|+GÒæsÐ#ÒGdCÉEy4}^:•#ŨâøZR–“îRQy4ÀÓ½ëÐïÔ‹Yú.¡?’Fœ¥ ‡s¤õh?G¯­Oº6 ¯ÂÒ£óèWºÖ¥›†,}Úøóµdzá\d^°Ðyôë1Û­¶[íµ<ýþlr\çÜY’)eKVö¦ëú³‰>•+*¾Ï‘ûÏL•ÃÞYú•@¾¡§Ï¢ÿ™£ª¡rT¯>O53ëS­è^¿›§wsT÷{Ž7sTßU?xlH6Î6¦ÖRS}ÓýëQÐüGšw5ŸZŸZ‚-ÛòÇÖKZ¿Õæn{½}Cûµ@ov˜;nïøegsçݤ.ÚðRWu× ]¯nŒmü—M ÿhrÓE*Ò_€¾“OÝÆ<Úû¡èP÷' è~žN÷tö,÷‘}%ut~¡NÒ:RÂ÷LhHŽ!o‘‰~ȧ=§EÈ&úŸCúu>-ôïù´kø´ Õˆói9b¥wði}O¶/%Ú)}œO«PLŧÕ‰¬•OkPÜÒ…wâà?Jf¹OSHj}„OÓHd7òiYíˆO‹Ê®äÓbH[ù´Òn>-Eìõ|Z†Ì–¯ói9ÒÙ/ãÓ j{¶/%ªµ_ɧUÈl¿—O«¥ŒýI>­A­ìÓÀ %’sñGø4‡3—æpæÒÎ\šÃ™Ks8sig.ÍáÌ¥9œ¹4‡3—æpæÒÎ\šÃ™K«56ö·|šÃùkˆEM¨5¢VH Š J¢4üŸE(ë…T -’cJbJ œ ¡8‹Æ¡lÍù4ÉEá3 µÂqjªÑ ¤¦¡$Š–¡Æ´…6&Ñ I±hZ^v—HqHÍNXøŸ„:+p­Ð›å¹ñû!²¹6ä'ý‡¡…E¨ËB¿aè·Aøº[!7¥øìð—ÎÊ3 å1"CüœüÌX´òÓp—† …2rí$yIYÒËœyt—áÚ)Y‚Z35ÊçIÙž0:1r]‚àº\%5¢húÄ(Ï#Ës$ÔeIyšè4¼ÚËÉÏg€‹\™z‰41"I,+Gþ/À‡œ+i™LVÛBm!VDøxŽ=ßO0Àõy«ÈÝ‹×3¸V¢|>ÌÇé(‰21"!ÇÝ4áCÐòZeø+8ûIU2›•ÁA‘€)f¦~Dâü“ëןíg­\d]&8Eˆ?­‡Ù2/iŒxZœøçùgc¯áF›*¨_]`Áë·Îñða±Í÷nÄgù1;C4);×J)×òµ!ϰ$œ,Ü Bˆ•©ìld†ŒÇ GÂç””³½pUqñ É9©¸ôñ.>ͱ-ÆÇ®\3N¢ÿ¹m”‹â ^3¹Ö‰åÍ4æI¼‹ñ8㨮&ñ2ÊË Ì:” ­ÚO4&é$Ì¹ÖÆ¹µžPµ&.DIœ^&³ŒÑ>ÖjÊ0Bs$qçêù6/Y;«yïÍE‹Ü AàæƒŒN8°%kÚÚ`K³Ö|”qz¬†›±ÄùQ$gÝçá«<÷(‡5·=ë9é¼9 §oÎ ¢|_\ÔNðz÷™Süè#Ì+¸¹Ò¯gÁŽ9»ZäçA\I29K £Ü(¿6žýt‘E(LdÇ¸ÅøX?Ãûj„Ÿ'¯ùcfŒÌÐÓÄ6yÏ­[HOŽó íê<ŒfòV ùþpÁí¡ÜJG¨½~tó¯‰nök¯Ž“•BlÜ_¹9XÎkr#‘ C?Vlxe&ä£y²HÖdqboóy#,Çõ4á%ÊTKY]æÇN‡õ¼ÆÓÄKâY¿.´¥ G5„ç¤Ìi m:‡Ä2ÁqáCêQ –ÈŠ“C&šÇÁ 9â>s¸\5"ycGæ<ñ˜‹ü3DaÄë,ˆâah1I"Îú³î#„Q&Í&ŒëŔ«Ò$Vpºšæå^Ì ŸC£©¬ôib¥ Ò:çEg¯†?¬ãÛ ê'gÇÐävÁh9NJ† Œ…(:gvB®Jû Ä5&øó>¢©]d„zSdŒãÚ‡ã(ä÷7€X’ǹmPÚÂ×ö£Ý¤~hm‚Ô'm@é0|öóõð½P2yœÞB¢ ×ß(\Å­!†ø1‘ãtÊÙ¬„…\ ‘ÎF 7íògCÐöióû éÑ,Ÿ<§!‚n·Ù  “.‚ÏíPo‚ô"2sÜŽà<'K?á÷àeåêa|vòg°Ž0Ã@9©BƒAÂM¿^øÜœãö·ÀÙI2BŒÁ•}DÒ ‚^?–v˜ärRqšê%Ò`T1}ÿ[²Ø“#ÇËx^k…Øí"çsµ8ùBü±— 7Frœ6zIn’è Ÿõóº'r¬íu±Ä~R+D$žÈZȱ^Ž{Á:¹>Æò8áúúÍçE°jö<>µ"œŸâ5}6.õÁó5‘íù\-cßüK­BsëËzð·ˆÜ·q2?XDW|mjhleGb‘T2œÍ°½ÉÔb2ÎÄ’‰ŠÇÙñØÜ|&ÍŽGÓÑÔÁèL@=NE—Ù±Åhbre1ʇW’K6žœ‹EØHrq%…¯`qË AÖ‹?Úüìx8¾8φ‘dä”nMÎ'ØÁ¥™4îgr>–fãùíÌ&SìæØt< ÇY¾G¨“„NÙtr)‰²˜Ýåp*Ê.%f¢)63eG†&ÙáX$šHG7°éh”.LGgf¢3lœ+eg¢éH*¶ˆÅ#}ÌD3áX<è ÇcÓ©î#Ì.$¡Aè'œHC+©Ø,;^ˆÅWØåXfžM/MgâQ6•„~c‰9` ªf¢ pebH%¢©t€ʰ³Ñpf)M³©(HË@‘´ŸM/„×HxÒø’…¥x&¶M&–¢)¨™ŽfHiv1•m`n¡õx<¹Ìθlla1ɰ±›ÁXgp Ș€¾’³ìtlŽ4Ìu”‰^‘‹c¢–Ó—f‰6²*åøÆð%äTdIÅÒÑhx]ZÄÝ@‹sP’Ž] Õ3Iè )Ì‚¸¾°ñDæÃ)`,š d ªSè“ÝœŒÏìh0ô­Æv¾¼—ÀŸI…g¢ áÔ, QkÖ:çõE\I‰X4^ŠT…ÓÕ IvK*™ÌÌg2‹õõËËËáºT¯Ï¬,&çRáÅù•úHf6™È¤ùªñ¥H8M p½\gé¥ÅÅx ŒŸ °{’K€Ú »f”Á‹‹1Po&êggbéE0bN©‹©œ@•(|†A•ÑÔB,“æ¦WˆT‚I\`;É”˜Å=øÏ–laf)’ñc“<×úñ5B £åùXd>³eè4–ˆÄ—ÀþsÜ'`-U±jÎ5òªC çã–ó$°wÐ}:“ŠE8£: ¶(´µ Pƒ^À/p8Iaï™I.'âÉðL!za*°.Ô‡K™Eˆ3Q,&®3/" ± ì—«Ž#¾2›ŽepŒRO˳Iì1˜ej?;N¯ÉD6ZJ¨âm!š,ÇÄ£3±p ™š«Ç¹z¨y WªA½Ä,ˆàfÖ„ë°ÿÆ×Æ5~€a¾, 2ahÀŸâÜÜ…¡CY,ÕêíX9iâH 7@…«À´™?;›‚À‡]œqdÆV Q¸œMNCÀK`PÂ$X vváR`†Âét2 cû˜IF l%2a.¦Æâ€Ln±@Zv‚Ö?¨&͈ÈéaÝz$ÖââÞ?1Á޳C#Û‡‡ú¡lh´wxªoht »®ƒ±}<cq‡|SCý¸±‘þñÞAȆ6 Mîñ³C“£¸Íh4ÄnOõN ‡ÆÙíSãÛÇ&ú¡û>hvtht`zéé„awÊØþa'CÃä«Ðp?NøëÛ¾g|hËà$;86Ü×…›û³Ðæá~®+ªw844âgûB#¡-ýäª1heœTã¹Û5ØOŠ ¿üëÅbôŽNŽCÖRŽOf/Ý54ÑïgCãCñ1hà WŒ‘FàºÑ~® 5[ ¨‚óSý9^úúCÃÐÖ¾8¿r@}!C(/ëg¢³a˜½ÂéÅ+Š7/Š7/>¶Å›½› ò¿xã?ç N{śśśśk£yñFFá âÍŒâÍŒâÍŒÿx73ÂÞø{߆>†Öû£ù݈ª‚ÿ*$ì;8ןHÔ¯RQP‡n¾Ðúj5®Ïô\h}­× _h}×ï¾Ðúz=®/™¹ÐúF#Ô‡O„wWˆH}üßHŽüË\ÈJ ”ùP3J†ÞQÔ…ö¢MVû ˜ö£OBȺ”ó0è#h?: üÀ¯B¸ýèJô[Ц¥¥””޲QÊM•Q TµÚN RQSÔ>jšŠS‹T’º†Z¢>I¤n‡Ô=Ô'¨¨OQÇ©›©oS·R/QwQ?¦£Þ ž¡NSÏRg¨ïÐ2êyÚÈl¥Yf]ǤèvæJzs-ÝÇ\GO0‡èiæzúræNúóýqæ×ôíÌÛô—˜wè¯3ïÑ'˜?ÐßaþH¿$ê£ÿEÔOÿwÐû¯ ± Oÿ±°À¢ °ØXl,v³€E°¸°¸°ø"`ñ `ñ`q °ø>”þ°x°ø`ñ>õ,­,œ€…°!Àb°,vó€Å€ÅÇ‹Ï÷OÏ/¯o§‹?ƒMK ±ÿ! +`Q XÉ€ç­Gû‹€Å `q`q7`ñ `ñ$`ñ€Å¿ïï£Ê‚®Ùi]Km,F‹=€Å<`‘,n,_,,Nß,~X¼Xü‘úèþfÚJÝJ»©»èzê1z#õ =XLó€E°¸°8 XÜ X|°¸°x °x°x °ø5`ñókF̼Í™w˜ræ=¦žùÓÁü‘éõ1#¢~f`-ÄB¾/ ;`QX´€Å¹/Ú’nB7Ÿ,î,ž,~Xüí§dh†²¢4å,º‹QÀb`,V‹·_,ŽÏÀÙ—‹ŸoïSiu ]F}‚®,:‹AÀb°¸°HW,>XÜ X< Xœ,^,~X¼X¼ÃbDÌõŒ•¹“©aÞb‚€ÅfÀb`q)`‘,®,n,> XÜXºJ±˜è*ØJA¨T)GPW' ÆÚÕÁ™¨B¥$@mˆvì:ýê€tLNÇpž””JM©«K ꤚ#Õ1HØQE!RXå'sQé•ùå1L ¥ˆW+ç ê¡l•ãP© •8*¡bÅ( ½% ¸„†Éi˜B=Å2ëºV  pJ˜Ïç+[ÀTtu¬‹„Ò1bd°* ¡Â¥€"JH’ TDN•1É3áyÂ^ž<¢*%±)xB1Ü™bWs9œ'êPU8p‹•~(åp8R ´¬§ÈÓÓ“BF˜ÈÄS(Q•LD¸ OÈã%NÇE„[¹¸ÄÄÄw¥SQ:MpjuQ+ÀÛ‰¦D5¼J`·z±8…¨€.2ØïoG5¼ tÐ(õwoGéŒ.oµ·Ã &„·kHþ•·+QVæâ+´XЉ©Q¹þ¯ÞΠ" TX±†»6›)Tà×4X&¥0(ræÂûÃÿ4˜øggP´…Â4J™Ê癕õ](©21båÌ èêÖ‚V¨4…rl6¡·ôWÏ'Ȇ§r}Ø_¬XŒ†ë3Ú.ƒÍ¸'œ„üO`P†*`G zD] ˆ ¢Æ€HBÈÕ (€63›¥F¬²ØluEÀfg ˆ Ø’XÏ$óà` ab€©ª„K~‡a0 A¤s®= ©V 4”AwŸIh8ÓÖ úüÏ ¢ 8# ðJÓ#T$ºQUæAô¬Q… {Á͇cÖˆÅuÒ:±¸†AA*Xˆ:,”¡%é½äï1ÈWx×A&¯jþxçñÕµUDÍ_ߪAW9‚ˆÅ€2„NjªÌ±šŒ B8 E’à B¸§ *8±|¸à0bñÐÐ °0èU|¾;ÇϯR×ÜÓphT„­Ü.…IE™tµ¯wÐ((M3/%"tÄ)4*J£–~aR&E èI£¥Ôðþó˜b& ebj‰ ¢K¬ ¥T•hL”ÆÖÄXDL¬K¥„X1ª½C1.®ÔhMÃPšK"X¦`Â%ÀM„â.ÄxbåiÀ,JÒ¡±ë"Ø¿8ÑlÑBWÈ*Ä@hˆ©Ñ•ƒãp ªãX&„ÒX¸B1Š¥!rZ'ݘÙÀ±)°@$ `“A.d‰$Š^¶0 °ˆ¡(Á…ˈš]¢®/…¿øRŒ…©Æ¢¨F”@”…XÄ„a4HݰªL&Âd²‘> ;€*L™ØMØk÷Ô&XnJugÒQ&SÖY ¼¶SFx‚ Î vH&#¤i¢7ªšÓ<ˆ*ì)—ÿñ(eTÕ^¯ï訿^[¥r"¡Ø(S[’ éa1Ì7ðx ÈLÊd5 ߃üäk ׂ\%$€š…•ÊÜ,LƒK`È Ü;!'°™¿í7Tˆ‚½%$]u¤°³d&aÒårŽ21ó,*ÐHLQ£ b5Ä˪4ðY€&KaÑP.±žP¨’& B·€QAšGÈæ)À ˆ¯£€-tÇVx6˜‘FO…0€û˰@ƒŸ1 ű¢‚ÛjX$”¥±*µ 嚨0”£åB©¦º½³^á4†R_ 9Á/ð¼©F¥TÄÃ¥*©Jå.ÄxÄÈ`‘t„¦²ÐØp“ãyñÀ>›„²5±/¢³Qºv½D.m!V‘ -TcªT"€¥Ô¨€¨«”ë nu Á ¤7pèÂS…Š (.J Ã‹2´ 4!еzÄó¢xÉ\¤¼ ©(–¥Ùp›Db«Ïj*2 t‘µ‹ t0”­Aè@Üu±!…ý¨R©†¡¤ReÞ•¤R@l‚XT‹¡"À„gB PR‚ºžî)™ Άàœ@&×”ð¨¼FÂ+%‚h)®”¹ ÿL lÂfk#Úˆ‘á‰&M”&«ä‰xlÊfPðl«2 Û‘ÍЬééá_%T4Aô6cƒ›¢VT«°"˜ËXH»†ƒÜ• ãiR…ˆÐ ÒQ-r©G:@®¥ëH- +µß*˜Xew—J ¥îR÷º˜ºx¨«ÍªÍªbW±Ù,”­%çU)¯ŽWÏójxµ¼*^¥¤RYPV¯4†**#l:P‚8ÑÔ*D›ýO½…Æ"DŠà„IÜS/ qצfÓ6CƒC8p/XŠÁ ÷B±+pØ ®Zó0ßE$„6DÂ!®+ÐiR!J´è¨Söp¢jé¬'î.)Ï@Û³BNÉ-§¹)n$©-Ur´ [iÒ ð p½t î"|$qGxào.ÀO ¢žî‰¼™¸ÓT)÷PÍ."Ø…àõAN‹„jý´Í"eèüJ058¡šzdµ¢@íTw6¬© }6¨WVHÜ™T4#"Ì(°:$u£Õ‹¸(.iDª•/ü§•6ø})2727<8™”Ããð”÷Ř—p²cÿîµl9 k‘HZ]$ßR°¤! ¥ò 19ÑnØ ""ø‡hÔ`"BN4þDE€‹”øOdDL'Þ9#<‰#èÈUø‘\N4(èòh ©”„DôPRhdò2ÈHˆ6¥‹‘´»IQ†ŒÄ€G_d @D$¢&„ä8Jˆh|Fh~Há1q‘ʲáEy$,K ic2"91ÆÆdTbD´ ñ½}“1¡IqÿJFŒs€££à_=ÅtFûð £]T†u¦Of»J#ågmMkI(Êeá *e€6™Ô›‚à¡Tæ*Š¡ƒH(–„Çm4Z wõXÀ<ŽøfH<ñ]-øM"˜qSÁ0½çm噿Î8zëîÅFã[˦ ±ËÏà„ãXžA>”O&¡$’®P1ï`uúά]‹V çáZjmÁÙÁçj’'`T]Ò„ ®.ÞVèºÌI¡sfEÅE&ÅÇq»áÚ°‘¦K Œ çöÁ a S·çoãšâÆPNÖåtɃ£b#lƒ’BcLF ÃûôÒâ:ã8×Õžkï2TáÎê*ž^ö_ÑL gA9KóȵÄ-Õ>q#¢à#3#ƒ¼L¼‚Ævuñi;™ëeëåìÈåZàfŠþvEAŠð ´¯¦…Q BÎ@uÐÎ$e (²2ûȲëK½ß&}¬s6ÌÏ÷Ï–Šü¡†çf×¼ ƽӊ{OxMé´¼b³Õ0ꇃAú—6Ìþ½¬ìüŒõOÚ§x<ç,ù|©¯éç€òy×fNùZb´uò™{Ú ç£c®£»5Tï±5Y°¥b‰Û÷;Ne-+6U‰®Ý?‹¯÷åWv`=âK/õgßõò1-wÏzx0.ã”AÚ‘öímc§–DñéSÆÏf„Þx÷Äfãç…k<‹£š>'›YßÔïÄÖênñ¼iÏæÒÞ´bŸyîCfžÚµ|Uÿ©f®ã¾øÀ‹KöT¯;ä—–‘>?ï0e°NÎÃ:Kë-mCÏÎ×ú‘oûýqq38$!èî ”,BÁ€I´1}LoÞýg(¥%µ¥¾†™ ˜uëNø‘ÆÁõ…zf޽˜o=¿Ïû^6 ¸Ê©L†Œ1Ü÷Í•ï•9Bùýü°Ä˜_¾ŸŸ[*›3P½p‰M^iºà“©tL …†¢Ø|4ã¤L÷|€˜ "ñ_Œœ„ëB}-06ÎT I¦ÿH2ôýk¼*Ûúܧ8ãíjú¨Ão:¢|‡¼%_²Í)ëd]麨C{¦ ÄëüNþñZîáQô­ª¤Ñ‡û—õ£[Ærë…[$2¼h!õ±ÒúyýWyzl²ÑýÖÚ½–d{Ð.ítÙ'nö­ŠáßôËæÍÚî®s êÀó3Í[¤m÷¿ì¿óªíÇ÷¼‘-%ïs}9¿£`[ÒñáÜYÚ1þaú­k½øâ_ßê.™°ÿr‚ðnšó\ÏÁZ»JÇ%ì6¼Ÿ•ûyÏœèÉ—š çt¿ñÄ¥›åÕ¢:³è¹Ì‘—Ñú§^M‹Y¾(ä†/…TôüáëCyß°÷s–…m®ˆìø5>æAÿñ-V‘Kñ * ÐØ;1Cõg9ìeø+{…´Àd¬ï·bÛpô}2Ø îx¯Ÿê­âÚâ86ïÂq`|< °wQü¨°Ð¤“as“fÅ'F%%C–ÂᎸ×ÞÉw,eÏ%ª8¬þïèóßÍ΂˜’§}Ö[§DÛýÑXÞÔ\7Þ,àÈõÎXs¶[…·ÆIÂMº¿¦Ý ÞÔÓw£ÁðõGs§ãý!Ñ/–¿YAÓiׯr¥+ÄÆWÌ—mÿð)ÒÐF¶°e¹Ñ«–±» *Í‚®¬þæuƒqóÏ¢›Åñ]_÷Ålˆ|`UïTœy󹕷åáÌqÙÏÈ6ßgggãqË>NÁ·K½ŸSöÒ4'µã¶îGúÉ ØÀc^Ù;}Ñ£øÝ-ûó÷ç<»CM½ëë’Âî£ô;—¼ èD·З"Ýpï·'Ÿ˜yŸ½h¼³¨`w¾xëS·Å BIÇ´Jdí[KÑë}ý‚å_)ULX*¢9,Rˆë@à風£àdðóü–X`Œ0ÒÁ0à™x7*C¨{¢°ÁÓsÌ”ž§¯êiÎàyN´Ìyn¡+³ndmšòlOAØžÐÿº{ftK>¢_0:ï‘1s&¢éÚEà JôÅGá^ù#ò‡eýÏ)Q-† C.#è0Xƒ}po|¤ºü_è®c„bÔÿ ­»å¬¬šNéÜÐzìÈüÇדÇû£%vIM‹eëº~~áÚSvw{ìÊŠyjéêXÝ€¼†žM“ÎMÞbØh„f>+ø°êæ7´­éüZ&åÒjŸ&iPφq‡Ö?kY=ûž°òÅÆÔKÉ­ë¬Íû&|ÿ"{&ȳÓj§5%œãŒÝ¾&š™¸éTë¶HÛêñÚ¯fNªŸ»Êdh­·ýW1wô<K¯†È—2uŸ^`†®‘>8ÕëõØUiÕNþÜ]ñúÜ"Öð…wƒMÛð+gÓ§¡½˜zÚ·éå~v?ÍŸ\f;°åëÒLñø‰/·'lŒ9ì:æî—䊃œ3û¿Ûµµ¿#u~ï™—‡ô‰5βjmÎÞQöüë›EÇ›÷ìOr:5¶ú/³ýæ±Ü³þšê=Bï\YY±ä¥ÃåÂdS᎞8ÿåðö¾´£¯éÍ­ZÏ~òÛÜ­³Žégíc2õÕÄwûžäm¿28¾<Ý2‰Ú½mžiÅÖŒJËà%³‡¬(˜z,®@w_ÅÁQÒñ?VÚÇ”v>)Ëì2¿|»Ñ²á¤!¶ESÖžzfúüxñ•°c‚`ÊÝav‡7ï*Ëß<·÷ÃõËtçöh¿Ÿ—?-Ë¢"ÿÝ’+¦÷_÷wyK›¯¤ˆ_ÁZt)êÒ‹¸W…9×¹ýåÚÕÓ¦×ùÔ}¸c¨Ýýè˺»€PÐ „‚mø¨%3ûÃ…ˆ áš^Ã1!õ¿BÉVx?05åá&AQ‘Ä3À”á/Œà['.nïb„£³â`ËUWñôÅÿ?¶ÊîäèþoãÇ»Gu/›‘_‰]|ÿôÜ\މçyMÞƶÏv ÿN5Æ¢z+‹3ŽÏoŠèlç0Wã±þƒ «?:Û¶…Øä¯GJ Ç4]m—›[¤=X+jȉ»^ÚëD­áÈBó+©é/^pOë?œáqkVÛùk>73mŽÖk›VŠVVµl˜¢û¥ÆM˜ÈYôýPî‘?¿©èv_|<wÇÀYr Ð_÷ \z`•¢kíÀuv´àèáæÀw°µwprµuÄw¶ u˜aëææ8ȉæ8Óù§Ã±O\øóÊŒƒ½ ê{–ýìê¼ñé iÙÿOŸ{<+÷±Ô;oû zñÝšÂdÙ ï+óHËí#Í@«W•…qF‡=/éÔscWÝù <ånÑÊ+•N8]ï4šbû:.2ìœÓùsæ_E -ß‘ûèQŽ‹w»l…~™v¢‚îèXxÄ­ï÷ù½NZ/ñ‹v NÜû24nxöÚ¬Šäs†-7îìéÌuï39Ĝᾇ1ÓØuÿÇÍMWÇyäp:»=+_»‘¿iÞWl㨹÷ÎäŒÜÁ|Á§ /œ>×ßX›ÿæcuPJÄk§ÛžÙ0ü㤻»Xú?uräl\žÔ/é⊦'Ñ÷dHVÕëZúQ&[iöM̈ëì<Œn-ò²2`òù0cf³*¨}ÆâÌ!¤-‚#jáØ!ý{9ÜZõåè[ôŒcvþ5l¦÷{fês¬Ñz‰Þ†Ë»o¿Ðl±®XÇ×ÿôÁIÚm_®¦?kÊŪµšzÈ/­ÝÒs&Ûå³ãë{?§Ë÷ÒŸE¯ñÔZÌD.§¦œô9ÛR{ðÒ ‘áù¸A9ŽL,@/hpù¤TŸ‘°émýkÝùs·Äõ@§ sÓtMø>ŠŠ´ß,™–¶Iô£—Í¡Sn!ç"Kg9îzúWáõ¨ÒÐÂ^õz¯p<ƒ¶Ï ÌT]´³o¡€ük(H_þ_¡Z{WpkÿÿäÖ¸à*€“«â"áLT¹8¬þÏ£Véïñ€ã Ä€¹CÒo‰Ý íŽÔÅÌèæïxæÃ‰É¦;‡XG·N 8xŠêÒó=“VÅîÓ0(º¦GKêr!Z|ÉõªÇ~g…Vrø²Ô<󘢾ÛZgýyûéÖ R¦MUÑÃŽ.`=Ø<å ¯7¥•?ï¥}`¿[Ñn”<9£î¢yî¡Y¯Æ~<½@ÿ“÷‰Køá¸p'Á¾ü0Û;ž:šŸÐ´îMOÞëÛ¿Eë|¾îüó‡¼ûÞ<`j7cÿ‰V»$Jz >éûgÝÛ·#Ö-~¸°ta¦ÁC’¬/WŒ[ÒûCÁÀ)ϲÝl:L®>éÑi§Œ<¤¤´h½KêííB›Ïc'®3u²¨r O :³MçÈfK®~:CÎ\Ý"½X‘µqÙ9‘i’EÇê„ØÒÊÅ"×u´ó”’õG Í ðß„Ïn´òݲ¼ÉbÆS?À‹Ç' 5'Ko-˜6ðžYs ñÞóË:Æs‡I!E=ËÊ îNðkq-Ði5ó=Ç952ÅëYeUâIb‹ùÓ ï¼êw '=^¼ú¿/^xhÍÓ7ÓvÉŠùM•9é ßÞë×âÛ¿P×j_á¢Há‹•3!¥—<˜´mzÅ|+«÷oc«¬ÖÚ¬õ4®²qéÈcªïî10iS{\‡Àd²î Þ¦-ã–<*^ÞëÉŽ±Ÿ6ŸóÎɽ-¹¿Uæà;ªãòýóý2}ÿOïÜÔ°ª#QîboO»?5‚] €ÕvÃÿ³«Ï¿? Oß •7ÁÒsðôxú:µ‘ìÈà˜ˆUMGBõþ]l ›Vš˜–0ÇnVR,î©€„;ö±71BÆ H$ñ°añ°¡âáÔdP›£|l6Býð°‰Ñï¢oä‡Ì½¹’àäÞvwê’"ûnemîÞ¶>oøæE·“ÙÙ•!v6U‰·bwžú’yÅ­bÔÝ£‡UôuÚ›3#bIö¢UÞêØëSn÷ö3üè>|UàÍâÑÍ4»þ[_ 1Ø{÷¸Ñü®M­á—G,0û¨»h_vÒâÕŸ®ö#y[_XÙíìžöÖ·³¾Í²Û”o=Ô:z²o˜1#*njîæg‹?‰Ö~ôðDæv³Üé]œÅÑçE–oo6|Ô.ʳÊÉõ×Âú@_q߸ʞÓ$­¶½>mÇ1_Wf óBÍ‘£ÏK>î¹|¼×dû¿,{§•|²ìxb3Ø$*·tÊŠYqñ…'“ª<)Ô}¨µ•GÆP]>KTæÿ¹qmša|ÏE^…óž{ZG쮚83³Ê(Ì9'óé£ô ¶X6^Û›s³mFذæi´mË<¨ó©·¨%sõ·†—Ö×`矫նj{1ðMΗ‚é›ëûÞåS>æìeøùtËßDúW—lÝ;Ôk~§šÛ»ví\° ï7ŸMƇ¾2~ÞÑQ}Ò/§éõ\Aï7¯å%süä÷ËÌfÍ}QôM¶ê5Kø*Ê­H†¿ÅƬyútnlغ!·¶O;®B8©o »½é‚wØ%C¿ïï™QY°|뤿&Žõñ ¿¼uÞ4¦Ð'úGòÎÊòØØÙ—çèj-¸ÆÍÀŠñ ì0 EñôMÿëÀõû+a×g%ùé!ù(˜Aæ²5?ˆZtÕX\m\SÚ7ëz!ÆÔ¶ô)cèµ)ºmßËZ&–s1í2<\ã%lîD<8ßZhõÛßiü÷_EXÐOhþÈîú2¿Äf,E˜}~<3ØjyáJ¹ù» {Ó¾Ýì›i}Â…ÿíþîÖÒÓŸ]Bżñ{©u2}ý©s!Gü}²íÎíß {PWVÀ]¿nÄÓ/§ (ž£#fçW+ËGýÆÞýë%³~9÷ÆýçS‡¿Š”J¦Ø8D¿ê¹ìá6iû°—¹ß})È—ÈùEEëNî·AS*Å&’»SW_·A¼Çñoν—&;ø Âüéò CûF&ÙÞSÖ,*᥎Ýñ!”Ï›µ!lt¸Ö¾'~+›Üß;•[NLh0òI|¸þýÒµ—ý¿¹Wéq{¥_TÙ ÇL4ºµXÿ¬iTpžçÄ{+,’O z}wwAÉ OÌ»öˆÊÍ õMÝ ×\ó?{sö÷¼iøä œ£é’¬®Q0¹ZBáê’¹Â_Déàjï8õoI:ö¢i¾áӰ΃¶Õz3É÷×¼üåm4è+>ìs&hi¨Ýš• Ê{NÌž¼i‹}´ixys¿ŒÕt7-ö»|·¶ÚÝ:篞)[t“³|‘Á—aå-Õú˜‡au {âöÓÓÆ¥ë˜H®Ùô Õ¯YÇÚ;ÄëEÏ‹Ç%‰x9œ¼¯*4÷Þâúa´©§ôØ·wIý”/GíÑmûÆØÔ ô_"&5/MÙg9k<ÃÕiTïf“Ý#'|ä[´î>•иδ—Ueí™k¡Åd>©ŽÍ³Ugš\Ö3Û}‹î§†þ§;o—¢«¢^ŽÏvw™07¬­•F‰FÝÚHñJf†×?Yïó¿ý9øá‹LªðàË!·]§ÍŠ_C1YÒÍdƒåþ œÙÀþÿ¦£ endstream endobj 508 0 obj [ 306 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 480] endobj 509 0 obj <> stream xœìœ \ÛU¶øÏýý²ï IX$!$„K jI)Pº—–(Ô¥P --²ØVíXÇqtÐZ×qÜj]Æ­jS\†ºŒUënÝ÷µ.ãŽÖ}¦KxçþN@èTß›ÿÌûëÌ˽œ|ï=wùÝ{ι7?úi Lø!ƒ¦êʪúÈkû>xd7€p\uåœéº|n?ÀCë±Þ4Q°ð¤ë^Ë`g⨦–Îæ®c–öÙJ¦`ûž–z]ágç7,> @qó²®åW}Ry3@Y€:aùеËR¬ €f€ñžö¶æÖo*¯çÓá|Åí¨0œœÐ‹õ*¬g¶wö®™1QéÆúG“êW¬jiÞåìA€®žšÎæ5]ÎüÄg°½û»:Ûz›'\›¿àñ9X¯_ÙÜÙöúš[q­âüõ]«zz‡Mð[ÜOïßÕÝÖu¶ò‘íÓC‰à¶PäY¿yáãã”o!—‰éîOO~’óÅ€}ïš4ר€j€ŽS@ØNÍæ½kþö$¶»Æ$µŠ÷1_ G€r°,€ ‚€«ÐÛ¥ç2e³…{°U%¿D^„S¦Ågà.T •‚(“iÙnÐ ‡ ó$z.ÀÜE. \&Zƒr“às»·‰;ä¾SœÝñ4&)¢0ñç^ÃJ’E?÷Æ&™rª]Q‹gðã¹îŸ~îÿ…$+…©?÷þ’ø2xÎç Ï‚ïç|þ¿K>ƒ+~´mlø±6¶6þï¬(žâ)žâ)žþ_’p\ö£mpêÿϵr =PŽÒøs¯cl ýÜkˆ§xЧxЧÿÌ$»nù¹×OñOñOñOñOñOñOñôïšâ¿WÇS<ÅS<ÅS<ÅS<ÅS<ÅS<ÅS<ÅS<ýdc’Jÿ ÎÅ–„“A½XOjø?#ÓCäÂ\h…ã nI+u™†‡¥1zp¢… ‹SWw2ÆR„‡>ÝõÞÒØS¬‡XÈ,ñbP°Ï¤Ê—±~?$þ/Îè_« ðÓ‰™ïPîþoÆÿw©êéÌRÆÕVŒ«ýO®äß;ý ñªYrÌÑG¹¸±!\¿haÝ‚ùóæÎ™=kf팚êªé•ÓBS›R^V:¹¤xR0/7Çïófz2œIV³É¨×jÔ*¥B.9Õžš&WÄבù<µµ¹¼îiFEóESÄ…ªšñ}"®&©›k|Ïö\vPÏõ öd&ט’›ãªö¸"»ª<®A¶¸®Ëª<®ÈTž+•e>©¢ÇŠÛ#\ÕIíU®krUGjNhï¯nªÂù¶i5Ó=ÓÛ4¹9°M£Å¢K¿§kóOeRAðW—m@¥çˆÞêæÖÈ‚º†ê*‡ÛÝ(é`º4WD1=¢”æruð5ÃY®m9;úÏ4ÁÒ¦€®ÕÓÚ|TCDlÆAýbuÿs ’í©ŠdŸø~n¹-’㩪Ž<8Ùì…£`¹×äqõ ¸xÏÐgã5Í1Âkúx‘oqÔLØ>R\®÷çvóµœ5‚¥X‰¬¯k º –:  4F„&Þ²c¤Åæ-ëGZF‡7yÜÜUÕM±ŸÚ“"ë—ºrsÐúÒ°Ý}MK[Ú9›Ûú=UUd·ú†H¨ ¡æØ^«·å±sn¢ƒ›¡®!ôtE¬žJê€ ÷AÇ¢iHlXÄ:=M-±Q‘`u_—«º¿©ŠÈçòÔ5l‡¢áÝÛ&º·ÁDhäëˆØ§£S|Õý ­Ë"Î&G+Æç2WƒÃ 5¢ù= mÜKS${7>Î-=Q…{;¨÷Hg¾s¥Wåjb#÷*\5øá©œ‚ &t—Tå­œâj`é†O‰õà¥qó`EôN¯åM":½ÖántSú‰%9bk’{#ª1s™P1º&zÎ.zóe»ªÛªÆ,pܤòØc³z·EìÁ8BÅÝY;Ò$zñä¢NÀi$÷b’+ \ ž6O£c(´ ïÛZòïìEžÙu‹$oÇ¢¤~\Ú'S-nl©Ó1kŽ·JõR}´Z{PóÌ‘fW¿Ê3{Q?ŸÜ›\x‚pÓ ßÌæ³&[&âѬÁÛÍSÓìq™\5ý̓Ãë—öo …ú»ª›ÚËøž™­ýžE SÒZ6¬sœÈeÙlv}enÞ=•Û<ì̺m!væ¢Å ÛM®3ë&LoªlÜ–‰m Û]!I+p-WòŠ‹WøL ±¢’ú;¶‡ÖK­2I!Õ[H:ÕˆŽAË @:ÓˆN@Œt!IÇ:)©MŒ×mµ«•»çäÆöþ¦F~¸ÀŽ®Äaž©VéÙÒˆa;2!v™Qã êØ Ø£FÃõ oÐÒøõX‰¬oŒ4øC:¥p6E ÖS†n§9å>þ `c¿ÅS(M< ïj\,j «ø°F2’R‡+oñ`SK“ ­-ƒ–Eêt—j¤iÃ+Qæk“Dãˆ5ß–èÕê5uNˆ?¼¬ÍãGRîU66Òâ¥Ú±ølSD‹+ò1elZ›fòµàϸTÞõ~>MÝ ,ô¬Á›…/ZšI‰Í½wf3^þ4^‹Ïä‘Á*~Ghcsì$­’ï\‡v½õƒÃ×{ֺǤÜÿrà ŽíØÐذ"rd 7Gu°V/©ûûUúC {©ô£D%lS‹ƒÂ5މÎAá²”IˆsÝÉ%ˆã ]„£’JG<‰åˆ ‚›à"8 é„4B*!™à $ì5ÎAöa7ámÂ[„7 o^'¼Fx•ð áeÂK„ç /^ ¡‰$är ÂB6ÁGð2 ~B B8‡Bø;Â7„¯ _¾$ì!|Aøœ0DøŒð)áÂÇ„> ü…ð-á}Â{„w)>s)êrÂB6ÁOÈ"x BÁMp4Âj‚Š $((„¿¤ˆÜCø‚ð9aˆðáÂÇ„OSD>Eø”ð aáI ÅÇ ¥ë£Ú…b„°•p+áRÂ%„?ž Ü$A”Sðýžpa=áTÂ)„_Ú(o#tÚ)^–Z ÛÕ„ZB%a!D¨ ü†ðkÂÅ„)„©„rB¡”0“0ƒPC˜L(!¨(„•„à ‚œ #ˆ„XÌ3Ba:'Q ¢¤\Nµ„ý„}„½„¿þJø3}#ÜK¸‡p7aÛ€õ,DD‚°Žp²–zÄTéüÞPëüå[ý,ç»(ï ìÖÍs>„²åA”PîGÙrŸöpçŸQnG¹ eeJe+Ê­(· ÜŒ²å&”Qn@¹å:”?¢\‹r ÊUšvçf”+Q6¡\r9Êe(—¢\‚ò”‹Q~r‘zµó<”sQ6¢œƒ²]\$.iwnÀÊÙê6ç4µ¸P\íàëˆìê„BÜôU„Ín‚+ çÎ0‡ ç6Î&œEè'üŽp&á Â<ÂÜ4î ›C˜M˜E˜I¨%Ì Ôª UÆjÄtB%!JpRÉ„¤ôå K$Ø 6‚•@°  §™9tò”¯Q¾BùeÊ(Ÿ£ÇßFy åM”7P^Gy åUôÞ+(÷¢ÜƒrÊv”«ÑK¢#Ù%dì?:È0í„å„e„6B+¡…°”ÐLh"L"L$3 „|BGÈ%ûä”Aα]œ/Î(wN¼OœU(õ(âðTfçÔl— {Í »e ÁŠƒnHp ¶nHð n$Ü@¸ž6~á„k ×.&üžpáBŠÇ ç–Ž¡ýM8Šp$a1¡‘Ð@8‚p8!L¨',",$Ôæ„ dÅl‚ŸEð¼„L‚‡Ap“¡]'AF  tFé0JåÊ~”}({1,ÿ†òW”ÏP>Eùåc”P>DùÃó/(‡ò4ÊS(»PžDyåq”ÇPEyåa”A”?a߉rÊ ÛJ¹•°‰páròÈe„K ¿%œ>`ÎCü†¬wáׄS ë §~EXG8™páDÂZÂÂj „>B/¡‡ÐM8žÐEXEXIè$¬ L#„Èi„©„ÃSå„2B)a2¡„\XL0ŒAOдt#ij‚*D¡G^Fy åE”PžGyåY”gÐKàes¾táGÆ?6´÷qºèuþFÌsžÆòœ¿®]>uËúð)µë¿ڲ.¬]W¾nö:Q»Î8iÝ–u¯¯Sœ\{bø¤-'†e'ZO4kkW‡×lYÖ®fºjûÂõ}ï÷}Ó'ZûêûZûzû.ì{ÊkûnïÛÙ'ïYú&—׬ï;·O°b»}ÌÈÕ®>­¡¦·¶;ܳ¥;,ëÎì®ïK÷t3!ÔÍšº»ºìt[w¦¿†wvtÛSj\Ý¡îÝâñµ«Â][V…WÖv†¿èd¦i1 .”gPD0Šõ°Q¬ °¢k… >wÛ‘·<ܾeyxY^k¸mKk¸%oi¸9¯)¼$ïèð1[Ž•·8|ä–ÅáÆ¼†ðØÿð¼úpxK}xQ^]xá–ºðü¼yáy¨Ÿ›7;¯°&¤Ï̪©ÐÍ×-щWêXHçË®ùB3¬Bl©}¹ø‘訑¹fBˆ*ôÁíÌæ¬ïåÿ*ȱs¡>0{P9¼pvDµàÈ;3â]Ä?Cu‹#Š3#^|dÃ6ÆÎiÜÆ„éõ+ÿcx©~ú† V9;’¶¨a@ܼ9­²qvd=/‡BRy˜—»4Žééë =ž^üì=¦5½}ø#á'²¯—·ôöïxèÄ›i¢@Oß-ézø¼}^ãŸñ O¿´²Ÿ{ÿ§SÒ’c@¹ zÁ˜¿FЧÂå°à~xž‡¯™šàt¸ÞƒOà+؇‡XÉl,•eÿëþ²Dô4y'èÅ €D€á½ÃGoþï ÃÍXK”ù~Ð [†‡ÖE/ˆFŸRhÁ$5 O vÞ+Tðúp1¯ gð²4brStkôÊqËY‚;^ «ÐÇÃRX޵nX'ÂI°~§Àz8 -ò[8~‡ŸgÃ86Âyp>\ÂEð{¸þ—À¥pZó Ø„úßc}“Ô RËf¸®ƒà&¸n[á*¬_×ÂázÔÞˆú-X¿^ê±%Ögj®CݱQ[!ÛbmT€ÛàvôÞÖƒê‚AØwÆxÜ ÷À½ðgôêôó±Oj«ÿñOƒ°‚‡áxÃXyu»à)xúïô‡ÒôýñYžgá9ŒÀàEx ^Wá5xÞ‚·á]ŒÅ÷á3©µ¾obËnÔ¾ 4òåѱÔëmì÷NlŽàCìÿ1 ÁçcÆPÿ7°×Gð|1¯b),X| źžÙ±e/ScÉͲX.ËcA6‘Mbål«d ±–ÇÂqp.ÆÅ…è}ЇK1Vcýu8n6nñ›¤𸹠{ìˆ~lÔ/â,/Œ³æ»ðlávãí¯H-OHV~[²òûØþäÞ‹ìû2ú÷¥ÑvâzßÁ±Ï¡_ž“zq¯½ŠÂû<†½nÆö·bžû>EoqŸ}‚µ±|t3ýWÌ}ù^¬íIlÙƒ÷Õ7èÙ/àK,}ežïGÍW(Ÿ£ö |Â×(¼Ï§¸®=¸¢ÏÐÇ_¡×¿Ç–¿aù;Øù\Ñ^؇%Þò¶|'Õ÷Á0DaoEÆ&¢~XzÍÙ/åwá®&Š=£øBt€‰LÆxª0r4LËt?|¤¤¡Y0ªìÅÛT’FêíoÄ÷*3³°fÅ{ØŽ³PgaI±õH KDaL€¤Kæo¥ãÛ™žÂ›<¾ÃøNÅw± lXúùEæÁÈö³l–ÏŠØ$‘ɼø4éSYó ÆË|, Àýaij)Ø2U±jlf9¬ÏÃTVs¨;_¸O€”ðþ~En`r¼ÿæÁ¬¿Œ1¸@ÇÊ?žÄ×Fˆöˆ»ñVA å†Ãaþ¹ö\»jÊ4P3AÉ" €KP¡·…,2Á[¢ëzsW««R õPñæ[oýÖ›»»XðÍ¡—†L^²”–ƒùÌì6Kb5J¥BáÉÈJJŠ‹‹Š § “&æ ž ŠoÒÄ©BÉT±¨0]ºROI‹¹Vܽ¾Xs S8ÁUÕ^›.æzíN‹’%Ë=)Ú`¥ß¢O z|eÙ) •R¦Ð(UY%•ÕË«2¢OÈTµ!àJõ$(dj£VŸíNÉHPF}rÃÞ¯ä†}GȪöÝ#š‹Ûæ)Ö굂\­ºÞíHÏ/O·zÓÌz£Þ`P¦:S•J‹Qã9¬îÀ&uª+M£7¨M66Í™®1èTFû7†èÄá½J9Ú³ RCÆIu¹Z«hʪs„May*0YK+ò ¼Q²C‚‡ñ}ú²D8¢Bðí&&±XQ©pˆº´BoV~ŠRxN8p‡®ºbZ)ûƒð¼ O+ðùòSTâr›ÓŸxmÎT¿M¶NÎî±ú ¦dß•œi“Ë<“F.ÇYÚ¾÷“͉f™sß»£ºS“ýƒ1³,{T²J½fƒ#+]^„1´£Æ^(ÝŽ¡õjH“˜–nÐ'ôª4þ'}æÖtþç~ªåþ»Ä*±Š¡ î÷R|¸¨ð…!ô¾Õ ó¸¥}¡ݸ9w¹ýóR”ìZ!Z(3b´ºrRôì4ᛲ|yÉJáϪâ¬-þ2Ÿ]¾Ldõ¶ìÂi¹·ú3ÔNܼLÆ7_°ÿIµ^%“©ô*qÒþ§GL!dç2Ê*²K2 9Ùüozc$ˆ_ E `*, YJÓÒ'cÎNTÙu:9øU…ƒÂ÷¡d—ªÕöt¿NéÉÎIKóLÎiõ´›Ç›c—¥4h)E›ì€ bY ‰]E…¦ugìÜ »=1qLpd剞qFô‚ø…§ºµ"Pjö‰2½§,wB¡CÍ\ò„ôoí<Œ"<æ©*a‡¢ ƒ•,>uIqtƒ&··dÙÔù61X~lCe‚±aÁsV‡V¥Wr i?ô•f%DO5ؽ¾ÌÔ)G/·e&¢Ÿ»'Vp»LþXÖ‰¿ä@œw—X+ÎÄ]ò? 7„4îÜŠ lPg” 7†Œ¶œ 1«•jP) ùücSg• ²ú;B†¹â ©¢"…u  ?íC;KƒE…ëÎ0p«8B†l|~A£wä‹A2œ ¯}Sì„1Ÿ¿'d6«Û°Dl“•æÌJR cåâβÒðaþ$MRѼΠY3ÊóÍKƒ³Àë ¦¨„è:OxrvuI¶ÃPXœsÔ‚Ã n›… ltÍ(÷¦Vͩ˚vÑg¶O5§ùíìeI«PhMš J&gM;¢©)0gî¤ÆµÕxÚ¼[ßË»`"œssA”Mé²¹eB‚5³3dI—' R®ÏŸ™nµd;åÉ™5Ésô´鬡°àΊ(4ž™a|%™¤û§ˆ[2ñ0šY?rE±ƒ®(ñ{‡3úÐ.Jïœä÷8ôâóLjFga&ÚJ-0•`pÅìv9›§IÌ,òy SµâÕ¦€;úrtaR¦FgÑÉñ~Ò±—¢~¿EÔø‘9bµý_²6YÃãßO>´˜N|¿MVd±¿ÙœfI…´T£Î© êD½¨dKB¦Pî,KªÙŸ–¥H̘™H[å;M‚%Ç·ÓΑëȱt?=B2 ~eÐk†òà‹[IL´‹:™JgLЪ-ösÆÜšÝ¬âP ‚ÁHwfÙ•BjRÅŒ9^£ÓaS(Ä›•™ùE9ø^ œ>~jt•d ü×iŒjÉ.çj'¥Ëj¹OàÂ=â2ü-Ú%é”Apd•¤‚/µ$8È^9Ì HõÉDw'ªƒJ¹nÂ-IÇnÕõŠ=x+ÍgÓ­4rl¥c7rê̆q@/±C$Ð!²t†„‘3$<,NÈÏsŠzõ„Òߤš€Ùè.šqdiÁ[± Mò¥¦z­Jý$¡À™Q”aNu&MÌó(…w F£a^‚ßcÏwq5… ÂCbªB…Pòó"³ý Ö,«5=Ë™mI·ÈüÙò¼.+šX¦ÏèLîÑÛ±äKé ì ¢ßGOJáÈ÷³B©L<ä×3½8*ÅØ{¥˜j·_¿R%×$g§;}6µ°¢”i“²RÓ2­JáJ–;9-Ó¦dM·+L©YiiY6µì€Þ™xUÔš$—®VüþaÉÑ÷”Z¼uñC4éõ"n;Zü”Z§E¹†ïv£ðp²<r¡8””i4¥€_¾dÏ‹2[z—mÜîøæ†ðµyg°hô}Vr•RyÐN¤xµ'Ú…“E…Z«Wi¶Ä\¿S™Ë´‰YÜa vœ•Ÿ˜nVF“?7?ÑêÆ÷QA–œásZ5®¢iî7G–/à‹œ¨Ð*ç&ÒMJ¥#ô²á/…›äí`ƒ ”‡¬6­Ý£uxì~Y ]kÌ$ ²koOŸkªñgܧ̉¥f)"ƒ´…ƒßýBÿŠ`L 8]Ùv¼lsFq–¿(M%¾«Ò[õ åy™A‡Fa°ìe²‚øyÃÈ#ž üØwŽ%¿  OHÐÚVS°0×`7ë]¸“S‡?—­”v2™¿½Î½M£ñØî^-Ø…½¾•«oOï0-ûà)À§PüwÒA BQH­ÍÂcãàÍ,øÒЛÒoYÏ®<¨*¦ º$OŠÃ gÓCZžkZ®,jt‰™¨´(„é̘–ëªÌ•‹çà˰BÁ߈ïÃÛlÑikp'·OÊ>•¿/(Ô à–‹Õ!€w­Ç¤òx’™øû'2ÌædK’Ê K’GiÎÌHèEê X?`Ó‹w‹áX4@EQQE‘ÕE»ð®yÿrÀ-8,XT4z×&HûÂ_àÄX}ô5˜Jv¥l±˜5y’G숾$7&z’ ³„bvqq†Ø¯Ìs-K÷§eUߤ–žâw(…ÏŒf³QÐøŠß)F£`<𵤹-ãµg&E²[ r=¸Ç~™éÿ-rë¿(ïŸ…Ž ûsgñâ_~–åÿ“ùÎ_^–ŽË7ŽÍ e<ÇóH^1.?óÏf%(Õÿ¢ÜÏñÏÿ@îŒçxŽçxŽçxŽç_t~+žã9žã9žã9žã9žã9žã9žã9žã9ž•¥*“+ð¿M#Jÿ~Æ$iDéo¤/ `—½#ÿóùY$V–Oöp¬,‡$Ùg±²2å²XY 'Èý±² &ÈoŽ•ÕàRŽÌ£6>K ‡+Ÿ‰•u0Aå‹•õ…jA¬l€öÃGþ×r¦²?+3P&>+  MΕEHON‰•eì•å Kž++À’\++¡ÿŸâej\œE¾)V&;S™ìLe²3•ÉÎT&;S™ìLe²3•ÉÎT&;S™ìLe²3•ÉÎTÖ’Ü)±2ÙùFpA!äCci.t@ tÃ*èAY½¨›Ž¥nè’>›QÓ¥•‡-Ó`f,DÝrhǶ©Ö†lÃÞ'àg+öÔC-––¢¦ Vcù8[ÎQk¥’ æàÌkqÞ>é‰+°´\Z‰ …ÿ«Úµ8vä®Ñ5çC–|£µÈ‘žßŒ3ta_>·ŸÃçhãb}ga­µ¼µ××3ºŸzÔwH{Xñ£ëY&ÙÁ•X_Š-\Û,YaüižU±º¤§ôak‹´ßë®Æ±Ý’¦{µJVs¡¾]ÒÍ…™¸&niÜJÉ®åÒø6©Gtâ3¹•[¥OWlE#}]’¾Gòi®eÄ{?샷÷â*:pdZaº´›i'£ûhFéÄ´BÚO³ô WÌ×8#Ÿµûñ¹Öbm5–z%?ôàþ–by…´¦nÉ|¿ø¹=X;16{/î‚ùé\…õÖ˜§F"áðX œbœ¯&4:wtôر?~.z¥¶JqËW{ܨÇ~8Ç«.‚®ÑÞ<Î)>Vbÿÿjï;ÀšJÖ†“,« GQ)†pB»”Qš E,‹!9@š)Rl€.vqmØv@ì«‚¢X×µ‹]°»öîÚ¾™9 ½ÞûüûÝÿ{7B23o¯3™d!P¤ýïTgæúü¦>‡ID”“®úuŒ‚¢B‰$Ó‚‡ d…x¤¡Õ䆑ÃÖÇ›xâ' EôK˜…'A²À¸iHU†d€ÔCè5£ç*¤;iôj<²‰Qדêk IBÊPõÿzŒ’U\¡÷L=uC†Hö ɨÞIõv†UÝÕKB¯ƒa?b°rèf!ÏÑk1Űk\çg‚K£º@ :†öRä}èU!˜ƒJBõˆ\óÐÓLhT;]õÙ[_-ê÷iþîôÝshD#Ì@s¬‹æ0GúÉ5ä^F¦ï"õÑý­gˆÊ¯w9蹨ºÌÑíWH“Q@èy‘U[¡÷; é¬Öwþ‚ÜE%éýlˆc2®Tú=ÉA‰véB¤§!R„”ú.߸žý¾¨³éí&Õ×z±>WEú¹ÉjÜ3¥hï®A±©—ñ뾯 û<ð¶«‘ÄFç ã|ønz”ú3ºéêÆjTÝ ¶oŒ-Cgi#½ rÕïÁ곦¾|È¢ÎrðÌfF¢B§5Š·d£KJˆd!ôJWçKãZBúÐCïq ÊY †¼nKßoUãOjiÜiÆt½%Òåÿ¡ Ý@‡Î¢¤e# Äè7äYo—!2êÚoÔc²ò‹‘†Ž×³AŠJTqšÞu+P0tãÓœ¡O4USbiP­ }•¨×»éž+üŠGÕuÚkP”*u2‹þ~NþO#ÀÐßB)\´I £8Ð-ùh†æ0PEù`%Œ‚Àl˜qýº3òTêC¡.õ8’üŽãxTã‚)ÃÑ@hA\.e0âÁÔ’h‡ƒÙ0ðÌÕÃAŒ@0Æðuª‚$¿€Ež!xúžHJ æ±: JÅC ’…ƒÐÕ¯úÚ¡!Ô£1Û:”HTiX¤ŠPDg¨,L˜¡Ôi1™2I*ÂDJU†b`2î…u…OÝY_(S%c¡B…H)J³”É ,T'Ö@>ÑÉR &3¦#Qª±i¢L*Ê0=G£L1R§7M¨&0BL¨1m2…ó¢±0©ˆPhˆ^˜† 0BžHˆÅ„“‘³˜˜ÐˆÔRTñZ¡T¦a eÒDµòbr% ø@E-•`¡\*ËÀÒ¤ÚdL£KÔÊL­|¥Š$ Õr€©¨„ZÃÆxZLBµ:5¡ÁÔÐBª0²ZtQK5Т„PŽéT  ˜f4ÒL®U…FA•„p€œäƒG”,TÁ5». zxbJ™( ,=àËæøé—Ýá2¹ÚÀZµPLÈ…êT¨òq]¨&¨à´H ì¡v˜Nä"Ô¸·b!j¥R›¬Õªzzx¤¥¥±å<6÷Ðf¨”Ij¡*9ÃC¤•(ZT¦ 5hÂÕ3ÓèT*™D\ccñJ0a¦1¥…Ñ §¡eDÀ×Z‚…‰¥ˆhÒÃ*µ¬Šž…À¯„Z.Õj¹Ä ¤•!>í@ )Õ†ÈõwÝA`ˆu"- Æç(€Ë‚8ÀaiÉRQ²‘di€©T!’é@2ÔK¯T€Ðq‘º’yb(|KZ2­@ðƒ@ÐhÕR¡(0 ´z! ¸H$°¶¨a*‰•i ™R(nh=!i*j@à>øB§U² & š&™©Z*Ì$8tˆ%N²4Qª…Ë:ˆ,QÂô"ëMÍÂ… «RQW: NpÑÇ¡`§IS¥*B,²•ê$8ò ú"ã Ü‹Â%$ÓtUlªšÑC„Aˆ³ÐÌ)J 4 H.¨tÈÜ ë&4eƒÊim£Aéô& m`1 “¨A„)23 è m l< Ð1e"¨~ h!ªÜ†8û~- @BF)’ a|ˆ•"PÃZ!Y`¥2`H±¶˜@_ºÏº"‰Ä¨<’~h^8mn,}¸Aé Ë2)ˆS’7¤¥&[à€’jÈ‚Å]*Ï2ˆJÒ$£„¤u0y5pR%@C ¸†€5[©’’%ö«¢’ X’I£·4"-Y)ÿ†Ž0 tj†@ÄJPT‘,)„Hk°ú8Á/–¢ÄëI†¸0Q9Š0êÀ ¥¦ YÝ¥ú4&#E¿¤I† "‘h¹B#EÕ½F ‚I \T׊¾e˜o¡\LçÏçb<ÅŒåqƒ0g;³°8^thdL4 øþÑñXd0æ äE±0îà(>W À"ù/<*ŒÇs¼ˆÀ°˜ ^Dð""A£çLD£#1ÈPOŠÇ@bá\~`(úðÂxÑñ,,˜i¢þX”??šæÏÇ¢bøQ‘.`ÈFð"‚ù€ 7œ zp˜Ã¸±`€ BýÃÂ+ÿ =ÉÏç…„Fc¡‘aA\0À’ù„qIV@©À0^8 ò÷á"¬H@…ÀôÒÅ…rÑàçþFó"# ‘Ñ|0d-ùÑu¨q<—…ùóyh`~$ Í 0"€Á%©@Sc <@à8FÀ­—%ˆëh ²10Ûú{Z(ê—bB"[¶P£Jÿq“ñã&ã߰훌î&ƒ‰~~Üfüß¼Í ½÷ãFãÇÆ7«ù[†·ëü¸Ùøq³ñãfãÿ¿› &üŽÂ—×à§ %·©¿RB¡é¿q@¡ÂoFx£o.|ë¿ “|++*€¡û^xkk?ë{ámlüÁï…·µEðï¾¾ysOc}/¼€Ïø :‚‡ß(1¡PÛRZRe”NÔé“”ž&jJ€ ë1pâá8Àé pÈ(°>¸N©Nk€Óàø€ c)ð¯y5À¡Úáüp\N€Ã81úh„£3ÂipüàÄœ$©ëipá8œÞ'à 8 iއñenA5gвDY:ð¸B³søgeÕ[v¢º: FŒ%«NªfÐ) ºjÄˆŠŠ sª9}ø¯‚RQÿü½ÂÄ„fnZPP`Τš[ެÐT¨+FU\˺–u <,̨f †žªƒjÁÀqYS*Ã4‘µ S-Y’® •N¿ èZ0] kŠ…µŸŸ_ºì™¼D^¢Ä“ðªG0Í)Ls“¾’ªªWeL3 Ó Çq‰,]U}℃bf*#efÒ)LS°ÉCêt ÝôNcšEE0›Q˜Íüz÷–¥ËªeÕòò‡ñÃxniN±„ }Çeh Ɉ'ª †l baI§XX@4:ÅÔôÙ3:ƒji&“UW[6£ZÚø9øõö“³©+ *ø—&à´>töJÊaÊIÊg°«±2§ZÕñ„LÍTsÀ”TÌŠNµb¸’l©$[šbkeKµjîgægÓ»¬½ÌWæ+‘Hª$U‡§WN¯´²¶ Z33®gmmNµ¶¨c-;QU…|©§˜[Ó©Ö¹wàOÆ»w¦ šµ9ä^M1ÊeXËhb™"Iÿº•†|ݾÌPËXXˆšHe¡·ÕYX˜P«hzÑDð þ8nÏö$ Ç5xŽã †…[nhî[kª­ Çq˜Ê£Q©KÜ‚aÚ­™ ­­)2˜ÝT:5§;J/àƒp–ьÊöY”Þ艶lJtˆ‚[ü¾ðw4"F·ßñäðÊ쟯d©³(ó5Ás‹îÒã rÚˆñz%žc²¡À„F¥Ñì¼€ˆ‹-nu`ÂåóÀ‹pë:iã(xÓ$†Î°£Å8vxs80·cÆ 5ÉRE’V©àØâÍङŸË• 1§=îg˜v-›¼ÄætÄ;Àu»6õëÑR9á.Ð å*,*ÐoßÚšã‹ÃÿswOŽg!`Ø÷­âÙeÿˆdÖ¸%\·´£‡GFñ9ÎxrØ^(UÁ»¬ ã "zpº»ûvvæzrºàN¤FMj$ oñj'c SM)&9T ˜gÒr@Y¬éxŒ²iœKå»Å^Sû™ÏîÒuSóËí[æhE]^< °pmïw±¬¸»“Zèl®gšmZÕ;¤äâ/ "ò‡ßXà²2ˆ“22Ç.dô‡££ß´æñ:Ÿl½=<#db¸(ïÖÖ.V«–°Ýެݮ;ìþ¬Š²nëÌa»3>©ÜÞÍ<Õ±ý„lÂjIÿs7»uu2}À²¡Â°%ÑËJz?œí¬ú9â–sbíMßK^×|ÚýúéǙº¯_©Þ:!úøè ®¹ƒlBöwy¢xþÉacŽ-:4Œ²?/娹ÙEÕÅîk¹xëZǃ©Ç Ö–øŠóÎä°ÞYíb1c3;Ü·˜´ŽqÃá<ÍäÑʪ°ˆ)îLêØŒÞŠnßuãé¯Úg=Í‹® µ|ÍŒ‰yX rt¢·Á[eÙ;y¿»ÄV1÷ÿ0êCY·’JŸ2<t ‡ãq^AH77PÿƹH-kôƹ*U g=ôw¸:7B/"'‚¨d|0Ã$¦©©•JÃࡆ1NËíýÕwæBý ÊZÜÊÛ…n…3 $MÌ%¤ Œ’)™ ûÜÊò'‚16_Ú¬lE‘EWžY(y™r¨LÐaüùì„A/?þÅ^[|zFó—w­TÑlÃK&¾Yæ7gÂõ®ßúÃoKàänÇïÄ ¼ÀO&ǛӞ®4mNyÒ†E¶ØDûu/>>¼¿ ‡¯crýê Î› GwÜ]èÆz-:Hõ¾x§ÀŠwŽyMAµ,õŽ<Ïk^y犵åXÖÜÜð¤ÖÕ.™w žDïé®~¾hÚ¹4¿‚â â%ž?ï‹c/]}wôó™Þi¿¶×†­?<ðÞÕ”šŒ!G‡`§½ßy{kå®Ì'ºü¼ó“k7ìpÛ8nj¶k»Óªu66e’ÕC¶ÍÜ;lÏÛ˜=ïmñ†(cOÉ2ƶJöFÕË¡qõJ@ei1»ë”9/XbêO­L€/8?á­LZÔ¹ŠãŽw#ó¸s}ó•JP$€ï¤©H¨%06Y©–j3`•»ãÞ¸ÇÓÇ ‡UÊ“ƒ†^8þ÷Êç¿*4Ë e¥7®„Îv“Êþ©foí­C 9Em:y­MDg›'§‹N‡mÒâXó?ÍÎGÏkÉ›Û.`öæÃð®—)©÷Gï}4ÅÌæm3ú‚gSNt8îÕyÒÒ¯’XGß›ìøð^ÄÊÂýN‚c3þâþaqêçâS%ôï×Èæ$]t¹,(É=uÇ%˜í¼172†ouÛ„õ!eÖ,\1ée<¾ô¯qòËîwÌ÷îŒÝKó9+wÖòPÊ€IsgWÉÚüÛgÙV¼ŸXÔ<ÄÞ"gùÄÇ1韩‹£Ì¡ØâÁw\w þí {ôòâöéþœ´‹oôš0§PHÛæh]úñíâ-Ô“FyoZy³4š À"E¸ L<°ƒÿB7ÅMÀ“Qåi²°ÀáhC§ƒøËÅmúFÝ’ g(xö²2eϳgdÙ7Û˜3¢¬sþ.vÝj˜‚yñ·WŠV ÿñðÌ±ÍØÔªp@ÁêMašÁ¯ÌìØE–D‚s  üsû}I¬[†Ÿâµ •Ãh£rŠãAFåÐïß)‡P@’êw–B`kÛü©•ÃL‚|¯=غ)íÊÉŒAáÔR¶väP¹•݆“ûFçídŸk±bºÁý–N JmÍ´ovæ²ý‚×½wI—¹{Ü{ÿKî‰A±÷—ªæÊ6ö;÷&£|}›ÌD×§+»z3ÒÚ&íÓ^Þ!ç™åaÖo–Ýyÿhì¶[«Öj}vFéÔ¢ë(ËÞüé#‡Úï)++ O:²<àKVFǬe-qÉý€?·=²¬SÇSº=øíUè Ö¹jϬ°®n¡†<Œ}ºæúÂ¥Çz*÷f;kÍŸŒêX¾8g¿sôöÒ”>S G ·* íÖ”¯yÖBùiª§lË烎Lw:*Ù»ÔqR 1­{q|ÞÎÛïl+9&ÚšmzΟµqnÉêô eóum/Ížd§ëäá¹Ö\Q0tz—ò‚§u¼ðgûÈ£‹žðn¾¥Ê)–cHÜU<,Ê?ÉqýÒìÐÐaÕáí «ÿòXÖÓ*õ¨ÝÊO €v`òÎhG+™87÷ŠÿO~¨'ˆ£Æô„qÿHIvÁ»’‰ÙÁx]L`iú0(Êðc´±õáàž~ž Mxû’ÝϞ𿱱Ճ›|ü_ö9ìËÕwû.¸ÔÎFœ¾vp¸}¯·™?önÎéùtÊîþ«C‡_k±ì鉋÷ù±n1£Ã§¾¨x¾å,¿å´íeæ;§EY^ÿ!Å¢àjýàó{tm°þûÒY c¯=y;Ö7àýøfªýÔ’œmƒ jåÄç·m˜3pyxÏ¢C/}ÝŸ$° fSJÂj¿ýÒ¹Ëø‹y×ò'·´Þ~Ø!¨¨ó±qÙwïrvµº4¼ïéä'û~=•ËÚ|µYÇýS+Ÿ´›o÷¦ªW–ºÍdÁ‡ åxß‚´½üÉå™Õ÷Kæl*l7ýܸ5¶Q¶ûjŽ8ˆÿšÄþp0DÒªbâhßâ„Ý¿Éh6î7Kšµ[Ñ·‹¡ŒMîD»Àh]µ2©;¾…™SúÉàØ‘ôg{óz=!ùĽ¬à·qÅg:áƒàrs:ØK®´±¯À¡Míܼ8¾ÞžÝ¼{~"/‰—»§—Owïî_w¡W"áî+òyw÷ሼ}lŽCâ;Q¦gsÖ·îÞ½Ó6ùÚc:Ú¼¯oŽ›,ÖJ•5- ¬APƒx†áœ¹ãÝÝq?Ô „FÝ çX£nÀý— á,´¸U]³¦á”FÙzÂäZ+q ãµa›§÷ú¥ó¶¥ý/ì•lçséÕýžÜ…¶áW¶Îº}|Ô l‹gesÂ_½nq{o¨³ýz¥ûÅÔ çªŠ2>žíÒ.øØ(ÚdÏÍQÑ™¼Ï¡šV&j3@t§ô³}/«Ê³/²vöîò`Ä–g1»®ú 0uÿS‘$Úã³oOç÷×î|jÒ)ÊÞtÛ‰å[ºPß Ý^nîí]´©W§i­w¸M˜Ú+Z½ú¾P0+ozyƇ{ëç;,oéËéÝ~pBg‹Þ«,;xY^øtjÞñÈÝ—½vÍz;½ YdÞÚ…ïésCtçwç-cÞ•˜Rïú¼¾úG^>¡|ôò` ±R×1o˜ûî9/ãÖ­l^ègö¡-J/udEô)tmíÛîô´7›Sw{Ï„¶úžüœ9î½Æm¢ýœ£+ÏÜïv«Ë¯%6¼ð]ëãš=ys<ûvíú!ëÚ_Žä-j9”þqEè²÷Ïú=Ÿ};ufë LÊÑqcv„®—ß;¼þH÷ qÞn/N–TÕͼðšß+kÁÕuÔ¼ÇWÿ´KÓ-R´ ËZ0޻Ȼ,MòtëæÐñó*>µfmØÙ+aQ³%Ù{Å‘E'¥[„E­¯Ú?Äñ³L<Ç4Ñpß ¯Å³—Cá1zv>ž=ÏþµÎHl°MÄûØÑ¨­¼þUo+E ™T.TgˆTv²VŽ÷¯#@ýÛ{bŽ”0 AIBŸH@Ÿ ?5’FýçYˆºOõ°1ǦºoÒ‹ÜÕ nFg´eŸ­Ö&uZl9¿yhö€ùcÏdXÍÚO$°Y}ßUªOË'|Þ×ï>óX¯òu+_J¯ˆÊ;ù¬ÎNLœ5vZpTLµÕì1gÚtxÙ;`ÿTɧÔ[}ÍØ®‹ïöi·úÜ6Ç´¹=jˆõIÏtzi7vÍ,턯Žw¥»˜jûÛªu¦V‹'ÿ•ÌžWàÖÏ-u0OÔÁBª²`þí ¯*ò^w»þ±×©½>O]6ß)v~|êÚËfÅ ]ò„7ëcùÂ|Ê…•žmjŸr?9tÙV^fó@Õ¦Íw¶\ºÒrò î`?Ï‘ÎmÇ—¾r~wÕ“.Ø?%Y¡,Ú¡­ìoÊXCusé›ÓÏ.\bYQþº&o¼ƒ²åXnѨ;ý݈••Ãù‰¹•Ž"ßüÜ—_¾{Ѫp‘sÍï«óO=.ò¿5Ôlɤ¾Œ4ÆiF©®ƒý>¡pÛ³«Uíèûnønæòä:áñ(ÿMá°ùÕ” …Á{ã_毶j»0«Ã)Šë¡ÒÅ«ûqÓÚûTY±byff§¿BçuØð!Ä)ëõ²wå©;æ×þ©Koûèa÷…m~¹P攬»[ü×ÇiZf=”ö*þˆ?¦‡Í¼qC'ýÚçôÒØˆÈò¬¸N…éÍ=;f>õg–öû°öĪáû '/ŽÊ­8ºxÔPfVhê§Œåû÷Êå)Gù;ę̈ß99ô<‡¾‘F¥âÙóþÛ«é#aý]IAöAX|ôAla±2¾ˆRÔ,9ÍpãÕ–¸S="JÛ¾X~•ýPgÌÂY-— ºÞ5Ïk™Ž‹P¬8±xt[–K“6Žþû »fuþjfGר»Qo¦çP)ÉÍöòŸ8kÙ•Ç?Í—ZŽ_yaí¨M²—ÅÓKŸ'~Xq!òÕÔ¬qï,¹t¹ÅŽˆ©Ó’Gôé»G4&d¬­»Ÿ²ÏÊ™·½¦}ªÌ‰šµÍZ7”&oq>¥¦kQ˺¶ð{ô•âfµÔÄT‡¼aññ¬Uœãk‚Ûòß+Ú}\SµëÝç-5²PqE§QÏ'±â“_î]ÒçnÊýªÉ ¿Ò[ZÛû²gLuæŸé1fåå!®÷$¿Puw–¯«PZÞía«Ïgd‹_·_y1òM°iî©iÅ뮼½›–::¸ø¾&\XÖâÀ‹9‹?uš_kíŸ&-÷m{Ñ;øɵ¬Œ° ùÙòBïš Øžt®÷ƒ“Ck ¦š£Ðœù_{s¶é‹7£˜Ž·1IËú D*`^·bʱA—d=à×E½zxú ù[DÞΖòO|ܶ,Êë–¸|K?lS@ÍûFo£ÁXQ ÛWqJ1éì—û‘e©«+Èæ÷yyo@µ‡søÃ¥oj·Žõí±ãpu§šq]M“íO•«cæO“­–´;ƒ÷j9ïDÖ²ƒ.w_l?»NXó™1÷÷‚YGŽUž¢šÞU;mëWêÿr±mùºÒ]ŸRÞl:½oåõÜÌbò dÛ릺³#vZèãžx¿ö óžxØŠzvnÏuCׯØnþTº¡ÅÌ´GÝkÖàL$õM¿áàlÓnîÓ6Õ#E«Mfõ=Ûü.ë±ãí’¸vö«%ŒÏ[¬Ý>·XQœ’]`µÌ{ò#t›fj۬ɮ±øyLÏãí¾ûØí=çÓWþ*b;Æ~Òsº"Åqðàu?Ípßqº–Bù½#F endstream endobj 510 0 obj <> stream xœ]ÁjÃ0 †ï~ »CqºžB`t rhW–í[É ‹lç·¯ì…&°AþÿOü–>µ¯-ùúÊÁv˜`ðäç°°Eèqô¤8oÓÖ•ÛN&*-p·Î §–† êô‡ˆsâv/.ôø ô;;dO#ì¾NôÝãNH *Õ4àpAg/fBÐÛ·NtŸÖ½0ŽÏ5"<–þðƇs4ÙЈª®¤¨ß¤…äþéÕöÛpv?³»:>÷öž¹ü½{(»0Kž²ƒ$Gð„÷5Å3•Ï Ýo; endstream endobj 511 0 obj <> stream xœÜz XSG×ð̽7 a û¾&,’BØDE\ !(4 j-ÒºáRZ«V»Hµµ.}kpÅZ·Ö.újk«õok[ÛJµ‹¶ÖºÔ*ä?w,Øåíó>ßû}ßÿg¼sÏœ9s¶9çd&ˆ0BÈ:±cË+_þá „p`'¨”úŒªØCÑ_®TÕlb£ÞY€ÓH„xL­¾®aêðoh€“áY_WßZ۾ɣ!·1 Â5jeÍ™­Š%ÀëSx†iáÜEû/w‡jL³‚û©7alFˆŠ¯×©”w¾ýdûš×Þ œ¥§<ùB€Ó€žmT6¨¿—ÌDÈåzÑd E5Å$sózƒZ?aË‹Y‰Î€ÎFÄÙÆá“?¬œî,¿! VðÙ8òµ î}¤ g±ôg / íahOè¹¼…öý™ÐOèßv7^xéÞÌÀg"ÁFiˆ"c ‰QмõVÌIÜ Ò…¼u¼$†Yßtª¥\hSXÀ§x‚û8£ò¢\)®²W ¼eý#p’пÞvo–9‰êð«uLmE½¼]Hy?—ÿ­A ûOðejÐú:Êÿ7×jÿ«õù_ô¡lÑëŽhî…¹üã£ÁÁŽ~ßܘáý}Ò?ÄŽ(2ÿ÷ùýw|ÄU‚‡¨«!W‹®Ö\5X,] XÅÁάm¨Šò¬ÌäÃÓÓRS’“eÒ„ø¸Ø˜è¨Èˆð°PIH0àïçëãíåéáîæê"vvrt°Ù |CSÅæKFT±æð*3.92ŽK”€PBT™Y@Jcf«;”R”µ÷Q*¬”Š{”XÌÊ‘<.–Í—°æ“y¶OWðòÛQ^! 6gùI*•yþÝ´u§‚õ:Û-v±:¶ÛÉÙ88Ô÷æDÈ9¨°ôžg1§‘dD„™U± I…lJã:uêP¥|*1¬2×ÀŽhÍv¹Uâáž[oæ…‰%lÇ  ¹ry(FiÃðÃÄ7rqr/Ö`~6ÇĘ££¹äž‚Ž™dœÛÜCeKôb^à>T¾UVO÷s¼´Gªa`nWa³¨ÚoR$ÄTš©*næðÀŒÇxn¦m`æÞò* Dò.’Êfaø½ÎbO·|Íp3öü‹iµu¾°LR8nR›ßQeómaù‘u>íÞœ 2»åVÐ~” ¢üh2 A9å17¨p03aðO‚º¦G „¨$ÌŽ0‹«FZûJQpðß\Ôc¹Ê­"¯ß–ÙÔ4:Î2¢žC 3áTaù¤ŽÑ9Hðœn ^<®[—MªØ'†ÓØâòЦr«r*»Ca®b ¥“`©{XnÄr#Tˆ!`wPB2å·OP™e‚ŒU=œp‡‘ª‡²âÄŸ8Ô]îšíNE@ §Â‘{ÝtÒ%}鸞JØ‘ÔCÅïèâ^±;¢àª°ÿÒ7Há$àÆ^ŠŒú¨ /¶ú} ϶ˆÄ ÅòÄ GàI€§Æ]ÄÖ¨ ]„®A·P·ˆIEžžI®.BE¾°g¼»»]jg>¤HttîtÖ :k#Ãñ‚ÎAg˜ 3Tà.tŠ…NB¡H(ò…Œ"¡{å E ÷ÝìÎs/>Ãõ Å×s‡Q` )4™ÝèBª°,š«Pa5k¾Y&éÁ"ØYž$›] QayŽ·9-¦°G`)5§Æš%“+º1^Q X3µ<^^у-jWD÷!Œ- –ûÙÞ••ȳ9Ë;Ë5Ó%}DÞtU¶>æ·wÌàOaIëk(7!ô¦‚ •[ØN‚íä°ë`^]XVaÞPiNäK@%Þ™½[1‡«»U’|5TŒ«»£W ·d@Ü>«ϱWs,£9‰Å+þ@â nº˜“¸‚“¸‚“X¬(&óµÜ–Tt QN%$;yï¤ìE°U~Á•9žb}&Ù˜Œ`ïy~¯2oFöPûà{Ôn*.;.››‚€á¦œ¸¯XÛ”÷¼Œ`¿WñfÛ”Ð.’ÓsßÇÈ}w¾6{@“}–ÃTÛנĘÊÄ›Šd¼1(úIä‡åKÛÓÛ_i¹Â›‰$ý3,ŸF8Cˆî²=ÖnÓPìëè*:ˆ£Q :l9…T¨‚jAq€ í…»Öç(îzòÅsky-CáèÔ…Ò_Ën4}#tFž( Ç:ÄGpOzŠF¡Bà‘ Ðd€~àoá4˜Ápö› ÒŸDO£ƒè]tùÇxt ð-Ë~”‹Ê@‡9húœ—Ã[ŠÜÐãè%´A_ãxüþŽþÁ²ÛrÂò=¬ŠB24 MFÕО@ÏÝK蟔„ÞhñµÌ±l¶¼ƒüAûm`õô&Ⱥ‰Y<«¨Mtkÿ¯–FË6ðƒè ÚCËkŠ‘ ½”gÑl­êd¥êw±xq™‚XúG hZŒ–ƒëÐz´}ƒ³°ŸÄ?PŽTuˆW"(ÛêûÐR`¹ 2P0h;ÍD³`åh%Z +ŸYG¡]E}xÎÀ™x.Åá…øEü C£îÐN´3KWÒUô\ú+ú¶×7¶Mÿ)K‰eøÊø3 ¼–‡ÊѤGFÔ‚æ¢6Ðn´NðÞ6hfðç!ho ÏÐhÑ7è2Ü…y`£GC“BËÀ <ÇÓq6â5xîÁñ›ø;|J¦†QéÔXª”ª£ô”‰ê¤ÌT7uˆê¥~-‡Óù´‘~˜ÞF¿N¿C@Q?šQ2Z¦‰y’132W™ëL?ñ$ÐâyJ^W߆þÂþÉ–pK†¥Ú²ÜÒ íðq XŽ"ÀžØUª…ÈÑC{Z+ønX´=¾ã¼·õ × J_‡ý} BŸ€}Ÿ¡¯Ð-tœÃÙçƒq–ÀÐ&Á>5㹸 ¯ÀëÀÏÝx7´ÃøS°²,œ@URÓ¨fj.µœZC=Mí£Sga',4v›.  é‰ôdzm¢WÓOÑkéçèõt}˜~‹¡˜áL c`a:™ Ìvæmæ4ó)OÊËàu@3óvóð.ò]ù~üd~¿GÀ¶ / ûÑNô6êF»ï¿*áÅXŒ»Ñ?ð%š¡Û¨TeOÅíÌ{8v@ŽojD×@Ãü•Š'Ò*< ü׎kñdô,íOo G£¼F\F—àTƬAwyo %¯ƒÚAS¼ºߦ¶! ZAÍìÛb©ÄN¨ ¿@m‚ˆyÉQã‹ÎRéÌ>FEQ‡¯à”)àÓéôp¡3Œ^ /€šeBgüRÒ_Aþ| ¹UJm‚šp* ÚõÑÛæ!”‰_èwA[x•Tö§^Àcúéûˆ~Ú²ûP_!ÔçÒ—MåBÄ·l¥¢ÑšþÛÌè u‡ª¡"™s r¯*Ít—r„|*ƒ:¢‡ÚT×Ê:¸7Ó?Š@¾@·=£¢‘ˆÏSÑ4åk'`Tù£Ò¼cŠÅ×åE}òbñMy‘¸O޲ä}rî‘I“\‚]‚]‚ët—¥ßUðÐÄ2‡¹ÛÑwÞˆÏÎŽW(õw/æ*Ô{äýŘ4”Fd4Lâʼnä¢1¢)¢zÑ\ EX`'â ìxHHÑŒ=\‚™ß]$âcЦD@ŒB;;>&ê¡L» -r8D=§™@µãA/·wÚsŽó_ïõ½rÅ<æ{%K.—§'€Ûx‹âc=ttQ¼7÷®é\ãþ ärø'“¢©x*vKÂœäÆ Æô…-5}4}û5Û¨M}â,ú^þë.Þ˜~£ª/ÐzççŸ ÐÇŠ¸‚„‰ Í gI ]HH$Ð'$$NBI…!±$Ð#DÂJÃC$=–Ç÷z¡Ö;>!¡ë /ow//oOàáå  §'80Á+Á›õŠ£â½0íãíéA%D„ÛÁI/áCTæ%óòòeãã"‚ØΘ☈ÄÎ>RÙ‰àìÝp‚*&¡QÃÅO¾:ï"DÐEÄùB.çz¯tn«]Ò]8'¸¤qÍÀ L&ÅSƒ±‹»—gR’GpJRbê°—äp‰$%ã`Iˆ€ïqß,¦Cû®û…•Hû#¥B=‹'yCýºŒ{q[ÂÄPOÿ°’„¾ÃÒ‰ϾŒñ‚¢ÃÂ’YÝl* »sŽ!ƒ»÷ÐËî,!ÖþôiúE…Cú(T‰f` 9Í£4²&’ñUðœ1¦<<ÜáLíîááéííåããŠ1ŠŒŒŠˆ ¼½}"##¢¢¼"½=0ÃÚEP”ÖÕÇÝÕÕ'ÊËKK`7åáNyyŠP+Ï‹²ó‰ðg}¾uí¡Zb»KÎì%ÿ¡‚(Ä÷òtâ-pvæ‰ „yöv=X °G7ƒòXŸè˜›ÁÑû° ‘(ºÒw½÷Jï”AíÊñq¯øŠ ;èa ¼8×?$>ºÈ |oÄ¡b¡\(·ö‹Ä££NG­#™Ô*oUˆœøÇpóJƉo¿ã3> a á“”8,5‰Ë^.w#Â#hˆj:<\ÂH†¥r©ìåæF·õ/UDgV ÃpQbIZ…¬XÑs;~x´wî¹¥B “++*™ä5ú.ýd_dÿ3Ŧû8><=+cø´Ìë»M]ÃJyùTóD…aZÿ)ü£µ}IÏ€Š…RQ“"pv4ŽŠñ‡/¹hˆdÚÏ1).ÚFO*qîÁÁ GÏD!–&JìÓ!¨ÀŸ{“³7Â}ypQØÇ%„û¤¥ßŽÖØÜzýЏïJo1Ö(«è çX¹ÜÅËêO’Ç`²µbq?± `Á1âåÉᵤ óâs8ðVJ2PàžÈø•Vo<0#Gæéâ3'4AQ9}ÆžK¥¥ýß|ùÛi¯~æÙgjç,Mñ¥§GHœ“RÜ<2.3D*r^èêUÛа¤¹yÙÉþóWÍÚcí|ß7öî=ôκ²'¤¡Ä3Éh3TæHô²"2Pà‘)D~¡“‰öŒS´»Øå¦݉±O$Ó)ÚùDõ`§îP¨!§¯ô‚©D}WÀtb» W°s[±"÷ð0ç°p·ð0‡È0d/’8±a8кûÐ0,†.È5 b%ÇĈå$Ï!l¸˜rõô÷ ÷ óõXÉø{ú¬-1Pp´óS!’¸¸üOµyU@ÜJ»{Ú¼NêÁñ m|Q{û[_5OÖ­ür\Nì0Y{ÙC¯ÌÜ4Ř”Útk"2¯ŽšÿÞ£l˜·~çš·¼]ðä%õ…G·<ü±¦2eõ@‘hkÍèÒ¢á§ÿ~£Œ4ú‹¶òÿÇFö ™j¾÷»ö4ð7Á|·/°Á4dûÌ ¢áÁ9d™ †ïzô” Â}©ËÛÁc§ a±Áö(_·Á(‰ ·ÁŽx UiƒP<}•ûË90æqqcâ Ì'øL ~4…žD`;àÔÃ̰Á9ð’m0…œx&L£R^ˆ fÑð7¯Ý󑘷Î Q8o« ¶C9¼S6XD)ø®6ØÕKm°ªî±ÁŽT¯¿ vBSEƒl´çôw˜B`‡Ax'v¨'°˜Óßa.Ývuè °û zâ+ì9ïCÖ>C`?"ËÊ3`MÐ 8”Ð[í#p é,ÄßaÞÁ¦y«^]«T©Ù-l¹FÍéu&@±¹:ƒ^gPš´ºFV_¯Šgó”&å_e×׳¥Ú:ÉÈ–ªjC³ºf€nxYkCµ®žÞ¬69ZY|ª”,Òª :£®ÖUª®kªW&ئSâ¥Rë’¢ò{²@Q]A©×´F©Ù<ƒ²EÛXÇŽ­­Õ‚²ô´ôrÖÈÖêM¬ :¥¶ÑÈ–kÔF¶XÝ–ê”lA­žÉª”z­IYod•5l½®EmP)êX¶V[×dP[ÑÕJ£VÅê›U¦&«¥&]Ú¤QØ­IÃ*AH}½ZE¦tµlƒæ Óª”õ¬Q[×heS§nT£o—Õl‰–Ui”¥ÊFdzìxÀÕê ¬Qm2qæ aÃ10ª´êF“Œd[t†™§4ñ úz0Ì5éXXʼnï84‘¶‘5š€Zi¨!N1ÆkL&ýð„„–––ø›/ãK‚ÆÔPŸÐ`âþ¨ŸÐ`œneÏaÿæŠu=`ÕdIñØòQ#Fåf—[ÌŽÁŽ•›_\–Ïf”æçå—;ŠE‹¨R×îhe›ÀE¦{[ ¶ëÕ†­É¤†Mj%†ç“M¼È ô]M“ÊÄÙߢѪ4ƒÖÂ[Û¨ªoª¥à³­Q_8—ê Z[Ü€Ca_„ëë[ÙHm«n¨æVýÆ«q€úU"ä5ÜŽB@™ Z'ƒÄÃò{¼2ˆ‘ZbR7p™eЂÔ]Kc½N9X((­´ª aöêH<êšLú&[£næ2h4êzý}ýåNr£„zXÜh´n"*F:d@ p—®‡ûz+ŒªQ+v„ïš0þžßæË Þ¨zª¡×ÑÝôú<ûèWé—Q9¬×ÃÊZ˜WÁ›E[à)G'Ž›ÉFÅ¢\Â[Oz%ൄ‚L=¬(à•ÿ6§làTïRÀÔÁj2’‘Þj m†¾æwü†ƒ¥­`s5à¸Õà Ö ð•v©H P$¬Ö‚¶˜1ÂS \¢ˆ„:Ô«9OM¸ou ¬–B,¥¬û½]VꀗüÚ¡ñŸQ©‰¿8ºÔkX4ô©%ú©‰Öé( ÎZâ‰ZÂËÊ)ÉZ#áªíÔ.†w ñœŽÄgEÈRC›IVsÚiÉúz²Â',Œt°’³Ÿ£á¼Käj‰ 6þÔÕ„†Ó—‹‚&Àª€gÓ=5¨á­!|Yb/7bI¤¨ˆ?ëaN5h·3,Ñݺ®ÁÆSE4f‰Ô:›åÚpR‰ +žh¬';Íù³Öpò4d—•Džu§¹ØeÑx]-‰K–ŒLDªuwþ\› Œ€Ñ-¸ÙZ›gZ¿™ƒè”6½­Ö7 ²îžuw9Ÿ±6Y×ßân šlœ´Ä[Æ¡™>(R8Û4Ä =äE´ÒâãиŒ·é’@è@Vô& Q͸‘M¢Mü=ÚÿZ\ÖÛhÕƒ¤C†”£Qh<¹P-8x,`¹Ìý‚ÏLô\=)€ȇVD°åȉÈSI|hÝÓVx7ÙöÞô¹fÝ-=‰•»&R‡¸øo´OùAc@æo40£'õ¦¤¨G뮵Y*’ $×:Ö’¬ª‡µ56©Öè¨!ózR³ZÅ'K{_•°Æ•5Êï·œ£¨'P$¬‹‚·šì?Ò«ñw¼ÿ¾—~ã^s/³¬uÅD4ÿ­ ü±õZ[U¹_¯ŒA>à,±Úb"ò¾i8þV[kHk$õNù§–Z=­âUk ÓÙúߪçU©9&Â_ ßB•ÜÊGC¢Zÿ/öèßϤ¹RMT„£ñ¾ü8( ÍÀøKršP9]¨‡œH]aSÈ0@ŸÔJ°‘ó§Y6PH]âVÑÖK³%˜û¿§øÁ¤‘;µ_âþïùøÉ¥í~i|»è…#ÞrĪ«Ý/ PaÆ2{©ŸãDS¾<$UòE1|ÌàöT 3]eÒqÒØAÿ mþHNÚX8#)XjâèL®Iƒ1cÜäÄVvö²åóÉm7v<ùÏ]íç¥íôQxâºh S”¸àϪóËKGäÞ:×0ÒQö‚Ôñžª˜JÍ_J”¤Ç3|7jR¶ÌCêÆ „nḩ64²¹J½Zæ.uåÐ7û¼&Cµ²±Y W™3p¬È_®Q¶˜Ô²©‡°ws·"Ø\µ\9ÈÅG$ à¦i7OÛ4¹U™” zî|››- ôr”&É¥ÉRò™äå(ã†I‰I)é)铤eƒ”_&ó’zXå;ÁÍO[w¥XvT£*^#² ˜ ¢Ø²Yep¿„cª‘ÚŽC{óÝŽàET;ÆhËñ/œ8Én=´äåEMWwÿtþˆó¡:å5þŸì¿}pcχS§ûQëM˜øÂ­ë6ù¾C}ùð˜Ò NU—þóö9~žõö®ó‹LŸ=CO¯ï¶¹€}WftœwrVrÒ*×µ®û>×$l½xáõŽeÑo, ^T{à‘Š‰º¦Cò­á‹¦{È×?ú]ùQãÑþ7G¶Oà²&dî¹Ìˆ÷g]^/;öÓÅŸsGwä®óÞØÙ;íÆszh[5~ìF‘ýç§B&l^uò•ÅͯüðªãϽEwÝÑt½âž±sÑ‘ý ¿qþ9éü¤É|!D,'À˜‰”†KCÆR¼ÐÛv5ЩŒúx¸©k¹Ë+w7 ±à†±…Jùð¢0’fs¸ f¸4M:¬+¹+q¡Ô¶\e¨²:Á+ƒC%7;¨H¤„1RÑ€´PêÄ!9YÜË䃆0va 2_ð‘z Ä7íæP^– –'‹KIº/+èùóÑè™·¿«x=Ï_¶¤umÌêCí/ã³þcNš;*Ï £6N{çøJ·KL©ã (ÍÜ{leñº3!Õ·²RƒÇêem?-M[´ó›oÖ þ÷Ư.ý`KDñìWö*³Ž~÷Ò±§}¶?fAæîgwüåDËÁ]oλñžÃsW×ôÇœÎ(õóK‹¸•5rØ"m§.ÙòØñÛ˜«g>ŠZìȳ›¶®yñýyüɌߧ£4mp:Nü›B¤qV¡áÿJ(7§6üË”ÜQ9ò³ÓšÙzçÕ6Mw´g½*Üò@î3s]ÒÄaã7EhûŠ÷±SN‹nwùE_?!XùQà¹Þ×’f¾ýãgSÕ+üV:ì) œ2·6e:¯#¿¿¹ø|YÛ†ù쳯,ž²AxëkéíBRÇäˆÞ=ÿVÐѳ㿟µ»tcìV<ûÚ†­ËSú×_œ:ƒ·þ™­>Ü¢ê¶â’ +ïûùã_Œ¾¶§Cyå±Où] KÖÍ-t”?7óÖ·¯0[kwD~ó˜çËò eºÂÓ)ÏîÖÕì\»ÿK­ß7̾íy1üÛ\[¶W»ª§ukÿ™ÒmQ¦y9—Ó7Ìð¼X¹?TójË/j›iKÉãÒùoÿ›)ép/%)¸*&Y“1V-ì ï ]ògÉh2ãTJ’~ž$ý8‘üÃ+“ïÏ@n—ÍÒR\ŠÙÉ_´k—íÛç³úÀãè'O¾uÝé#Ëí¢ÃIÕR—7o˜üÎ<ñùôgX·î¹ùKN>r©Íë‘—"VÖ¹¸s¼ç©lúÄÓã&ó–>¼Y÷³_‰_hü5íòú[û{®ºâ`:¬iùøûµÕ‹Ž;Ybš-Ù¶ñ©9kºo=õ`Q|“ßÈìO®îvdË϶t­iWiûìÞë¸Ú´ßîéo»Œ_§L<8›2ÏYxpÃKCbg½ŸÒüÚÆ)·÷]ã!’œèýàLrü(…‡Ü¹jvè[/Öþ¸ú=ý÷™—®;Îûôý¹›Ôyfl4%¸{ÃvßjyÌÇ+¶F æ|ä½sÊœ¯ž}Q×/_òi;ã %àWk pFGÐR¹|±Ëû™7U—Ï+{Œ  Èm{·\¾ÕÀý–ÊFª¢XYzz*{ïÇRò£k¼,Pêo%ö:cû9V, ²n“÷oó¥:‰Ín2it­©•+é©R™L*Mµ•‡D©,1Ifþhô/¿Ê©Gô3®ûE®_3kšô» [–‡Mÿ¥Õ˜{ûŸÝÀfηáé U%Î|?§¦õ‡—›•ríûgú?¶þÑÚoΜ]-9 ÿÜ?ñÍ꣇âj×­Ó„¯=5<öÃîŠð##.‰2ÓVÇn‰Lß|yÔ#9uÞ¿®~¼òåö¹ÏWŵŒùví®šŒu%þ2a¨ûú-—ñ¾øÀS*÷ª žz}@jé¢[/ýø$õ–ßéCãów.i;4ürù“ůô½4»ÁT¼ÝûÄj»È`4±³J›º¿ÐU Ÿ`™|ç…Z‘pÓó'LüqOÆ4Ïù-Ì'7¾Ò¶ªß|òá³/ù¦È¿vU¸1Dº“¿àØN¶ÅmÁy[ÝØ,ÿ¢tþ./13tþš6ñäSúµ†ç$ãæ¹ï(Zaùçó†ÿþýkÿ1NªÂªoì/ÿywÊ•úQ‹ËÏSª×?gÿÏLÞã‹;6übðµ«WÆîî*x§úÇ»ÿçDFƤ-Ãʵý¡ YÇNlýœ7÷3ÙòÖ‹õ3ö÷»ŽõÖ¾{*÷‚Ë$vìwÕs¶oõy'&5,î úy׎0gÕÆ[åþ·ƒõø¹ôåÆÜDA_»×/_×Õ;Ž»yà§Ò·\:*½ËÊ쬊ò-ú0€zñ§¶/è]“¯wöÎÄÔ£Þ.-ß³‹Žtµtž½*|l^Ïš7·¥ÆöÎîÝÜr¡¹ š‘uäƒa_d»nN™á7ã\Ê—gü™ÞÍùÌ;“’Ò‹ü«÷Š6,;ýayÖˆ“þã7éϹ_´²iýKtAUxÛmƒökÇFÛ\>9J=_ñêÀ%!àª$H‡Áy!Y–šœ,KæðP⇠”„ù›†ܤ.Öë†h¢Ò¨£€ äˆÉW\6¥êš]cÍ€f¢?ÓìÏÌL¡¿3S" ¶šá;x¦FMÜi¤„\ ØßWG®’I%yã»üµó–Ì’f¿~&4ìfó»Á–“ÑŠ?³·}GJk:ºYø¡êØÞo~{äÈÙîe«7~uÞÓ^ºîûö·ˆßÜ|ø‡™®(óÛ_òk ^rÄóL»)fåÝpM+¾£÷ůìû:µû¼J ÉxP‘\p}æ+#nDCþ™ã8nOéºÓO¹½å“õ ¿áÚªà¼é9W[[ÃöI¾»!ï✠=›>¿þüù§ƒû+dÙãÓæm¯¸Ô{¹²5lÛ­è—¬´Y™9¿¤é¢ñº8ú‰£³òJ žûè’•O®›óÝ…ôC7×>(y©ö©ç㾊¡|“GªoÈ]·ÿ´È? ¼TwbÞØŽ£Áát§ÿß(/®|;ÛÜê EÓˆ!WÔ'Æ“qû%¦pê;†ò|}³+ÚËóΑÛeó¥>÷–¸SŒC •¡&¸®ç¢l©=9ø{Ç©ó½OJÃkP^’2¦ºðÅϼówööÉï·Ë2—Tç(|é¶RýN<ýkÚÈì÷v_‹xäô…7'”mÞíó?uÝž°gä“¡_o útö™›ž³]ÏýÜéwY8uç‚Î}Ë*öûŸXuzÕ“I×ÿܲøéi…£Jþï,Õ¬¤CÌÿÔÆˆN>|G¦ïCbÍSö·iï+ßôŸ ON*á¹ ê~êöûjëþÚvlÑ™cñÝŸOÝ^Ý”Ç~'UrçŠom‡8f|T[“Yµñ öò iòK×·sdOÞ±Ál¦ëba‹ÅÖØíR¼n°ìT’ÌúðÞ§«wÅÙð˜œ|pR‡KkÌñó×VÞ|X;±Bý÷–¼¥ýlÆã´ù šXE™4¤ãJt›w´–!c„b¨ˆ²ÏÒÄØÄ Ô[2¶€\S× „&þ€Ê3ã'Ø$:Û8Íb]Ì¢Oïß»°zjï5›¹ò݇cÛôb?l,úºzMGÖÖ[•ª¹OœXê=1NIøåϯÊs·~É+[÷þÝ›ãGDÆØ¯Þ\l¬¶,©1±raÒ—¼Ž©òîŸiI `Y⮂®Ô…ÓÄ:—Ç6^pI{z;lžÃ©?wÊTô\ ž^«­ž*x5Bvñ î“w] ž™s*ùÔ̬Y“â||_è_ŽŽŽ‹Z\¬»tw‹+o¤hÙiŽ[³–ˆ¾ð}“ù7vSvÿ[Í@s‹îcnž¢Sflø’±äú=ÎÂô’yå=²­ÙÓ_=w=óàY!ïÅd†ÉÕ†3ú¸·ïÝ|áÝÇûŠïV&$¾3w¶= i51N†HFßQ¼»™½²4ø¬ÿ;i?I6¹ÅsVŸŸòGÉ·$ªÌҸРq^ÖRdaÉ’(ÿ0 ÞŽŸ‹“û6mVH¿\˜9àž_Av&HT:-^¬Ê ôLûFà¡?ROÔÙÀÑÀÞej3Fž7Æ47µÓÀl}B‹›ï§ZÌŽ™!’—yŸéÄóÍ¿/ò]«¿º>„÷–ѶYÏx+J•Û-ͨÚ2µ®+æ“ó‘æÙ©µ5M"_›‹¯/ÚsŠ©àœZŽøž ‘¥¶?Yxfaé܉…¶Ò¶þhQ»güûšjUܬ[Ë~ùä(µ&Ôm­Ç‰Âœž?¶Ëïaé‹Je~Éxa!O×̽7®¸À!ªª¸u[x§ÌÅè6Ó¥§þ®j³ÒÜ~»söc…®{êÖ½üºi¡ÇžÔ}Á&7O¾`Kfa«È øï±{ö+ç¨öÛk¹¾FÕyò´>Úë©Qå;¥ÖI<º›¢rˆˆX}éìcýƒgßäÎ7¯4lb9 ,63124n2…#JÆ^ÐøÂ@^¡j0²3³‚‡âAÕ,4ê9™ yGÎNGð¸ ù eE ”Y ùVíž\ðÙ_Œ=šW<ôÍ]’OýßécP„¤…Ç0Å iEƒ–™v7øÜ ŽYö…j *8Óv |Ízk’¥‰‘á”Àç"ñu§ÿTn¹AÉ[{îŒ3³×2~©ÏZÅo¼Uñj–zÿ!{¿éÏÖˆUž5ÙÚË}€ÙòÓT•OÌú‘-‚Ú­òÏXvx—I´mò±ßzÁ6ëü~=`_uúõÁõ‹Îu˜×!d3ºbË…ÙÁo",d§*[ ÿ{ã9—çÊžý/gž’nÞ~®» þSÍ7.îýb9·•R®j›º­yã~g’Å« ÎNœÕ¹]þ’W‡Á©mŸ÷G¿æäJñlfxÇõô°ôÑ^ùw3ìë­µÏiû¾. ½uÎì §¬Â|»O1±Ì’Õ™§mW6Þ‹<°¡KrG–ÿ ‘¿Ý3¦mϽʺDŽea°YÔÄøcl†MŒo€B/@É;&ƒšX†RyØ8 `–2 " $Ó7bj‡˜ôà2¬†ü úXÁÎ 0‰–¿HIOˆEÀo¦Òö­÷´ºd žüü7í–$ìâñà‚žó鿱y¾Wg½u:2Çz{˜Z…OBÊ*oõÖ­¡>WE[æþ*p¬rw?ò¸ûòÑ]ÿߺtü8csÅÆ—·ë3Mv9ê/·«Úb:—uΑ~"æ í/­ûV•¦i •…6ÍÐ?žÌ±iС{û>p-ü{ˆéó•[o±1çÿóž1ïcóú=曜ço{öxÿ‘çæG<ÿÖh~R*¾o0­Öó«m†ÛŽv p¶}•jl•Â`羪Kkf°´ÁÒW)‰ùËB·/ÓVä_ã}ïúÿf¶¥òå |ç|õ•ÚÊ,~ñg¹ø‰ ­öÓÏu.JVþ÷Û2jnlƒÁùÛw¶n¾}gaž`“ endstream endobj 512 0 obj [ 0[ 600] 70[ 549] ] endobj 513 0 obj <> stream Philip Thomas Lanken Conradsen Clausen Microsoft Word2021-06-02T07:50:47+00:002021-06-02T07:50:47+00:00 uuid:1EE84C39-D685-44BD-9B31-1422C384A72Fuuid:1EE84C39-D685-44BD-9B31-1422C384A72F endstream endobj 514 0 obj <> endobj 515 0 obj <<394CE81E85D6BD449B311422C384A72F>] /Filter/FlateDecode/Length 1114>> stream xœ5×w¸ÖcÇñçSV*##«’=J©¬dWVÈÈ&{ ÙÙ#[B É&Ù{–d7dïB*eg“sî×Ïùã¼®û:¿çº¾¿u¿ÏS«ÕýÌŸŸºßKÖjõÜ]HïBƒó >+,zQ¡ñ@ŒÆ´B“k M/+,Ö¥°xÌ,,1£Ð¬i¡Å¨BË5Ñ iÕ¾°rëBëÝ mÇÖÛãïB»î…öí ë÷(tYª°YçB÷a…m_,ôœZØõ‡Â>] û[8Ô‡›ó„N…>û^\8åÁ ; gO,\Ò«0øÌÂÐÉ…ë~/Üvaáö1…1 t,<é’?5¡0¶Eaܦ…×\Ï×-LZwKêîQ·ÜŒ[0·â¦ÂÿGŽªûÜä-ªU-h€†X b!,ŒEЋ¢1š )ÃâXK¢–ÂÒXË¢9–3õmVËc¬ˆ•Ð-Ñ +£5VÁªX «c ¬‰µ°6Ö1ÄíVë¢ Úb=‡ÜaÕí±>: #:alèãwZm„± :cStÁfØ[`Kl…­± º¢ºc[l‡í±vDìdλ¬vÆ.è‰]±vÇè…=±öÆ>Øûa€Ñá`‚CqÇ8Òðw[…£q ŽÅq8' NÄIè‹~è8q NÅi8gàLœ…A8çà\œçTî±:àB\„‹q ãR\†Ëq®ÄU¸×`®ÅP\‡ët¯Õ †1#PíK¶®š­«fëªÙºj£P½ýÕûW½cÕ»R=ŠÕM­.H5Ä}û1ÆœÕßÀƒxã<ŠÇð8žÀ“x Oã<‹çð<^À‹‹qx ãñ2&༊×ðºS©Îï ¼‰·0“0Sð6¦â¼‹÷ð>>À‡øã|ŠÏð9¾À4LÇ—ø _c¾ÁL'VݱY˜o1sñ¾Çø?ágü‚yø¿áwü?ñþÆ?øóÍY¥UL#¦ÓˆiÄ4Õç©ÑÔhj45šM¦FS£©ÑÔhj45šM¦FSã)´FZS¥US£©ÑÔhj45šM¦FS£©ÑÔhj45šM¦FSS5ULãý‹¦FSS5UL#¦ÓˆiÄ4b1MSŠFE£¢QѨhT4*ŠFE£¢QÑØ'"¦ÓˆiÄ4b1˜FL#¦©bª¢QѨhT4*ŠFE£¢QѨhT4*YÄ4b1˜FL#¦ÓˆiÄ4b1˜¦Š©ŠFE£¢QѨhT4*ŠFE£¢QѨhl¿ÓˆiÄ4b1˜FL#¦ÓˆiÄ4b1˜¦Š©ŠFE£¢QѨhT4*ŠFE£¢QѨhT4J1˜FL#¦ÓT1UѨhT4*šuÿÈO÷ýáëæõdfùÊ–Ùã sV)ÌmSOƒ¾C ý¦ÔӰͼBÛ+ ý‡¼Z9ÏFϪÕþ/Uw endstream endobj xref 0 516 0000000062 65535 f 0000000017 00000 n 0000000168 00000 n 0000000351 00000 n 0000000644 00000 n 0000002526 00000 n 0000002695 00000 n 0000002935 00000 n 0000002988 00000 n 0000003041 00000 n 0000003218 00000 n 0000003468 00000 n 0000003644 00000 n 0000003890 00000 n 0000004072 00000 n 0000004326 00000 n 0000004621 00000 n 0000007586 00000 n 0000007719 00000 n 0000007749 00000 n 0000007910 00000 n 0000007984 00000 n 0000008225 00000 n 0000008530 00000 n 0000011716 00000 n 0000011843 00000 n 0000011873 00000 n 0000012028 00000 n 0000012102 00000 n 0000012335 00000 n 0000012620 00000 n 0000015379 00000 n 0000015674 00000 n 0000018073 00000 n 0000018368 00000 n 0000020691 00000 n 0000020976 00000 n 0000022852 00000 n 0000023147 00000 n 0000025574 00000 n 0000025869 00000 n 0000028212 00000 n 0000028507 00000 n 0000030600 00000 n 0000030896 00000 n 0000032678 00000 n 0000032974 00000 n 0000035157 00000 n 0000035453 00000 n 0000038352 00000 n 0000038648 00000 n 0000041862 00000 n 0000042158 00000 n 0000044555 00000 n 0000044851 00000 n 0000047272 00000 n 0000047558 00000 n 0000049437 00000 n 0000049723 00000 n 0000051596 00000 n 0000051892 00000 n 0000053141 00000 n 0000000063 65535 f 0000000064 65535 f 0000000065 65535 f 0000000066 65535 f 0000000067 65535 f 0000000068 65535 f 0000000069 65535 f 0000000070 65535 f 0000000071 65535 f 0000000072 65535 f 0000000073 65535 f 0000000074 65535 f 0000000075 65535 f 0000000076 65535 f 0000000077 65535 f 0000000078 65535 f 0000000079 65535 f 0000000080 65535 f 0000000081 65535 f 0000000082 65535 f 0000000083 65535 f 0000000084 65535 f 0000000085 65535 f 0000000086 65535 f 0000000087 65535 f 0000000088 65535 f 0000000089 65535 f 0000000090 65535 f 0000000091 65535 f 0000000092 65535 f 0000000093 65535 f 0000000094 65535 f 0000000095 65535 f 0000000096 65535 f 0000000097 65535 f 0000000098 65535 f 0000000099 65535 f 0000000100 65535 f 0000000101 65535 f 0000000102 65535 f 0000000103 65535 f 0000000104 65535 f 0000000105 65535 f 0000000106 65535 f 0000000107 65535 f 0000000108 65535 f 0000000109 65535 f 0000000110 65535 f 0000000111 65535 f 0000000112 65535 f 0000000113 65535 f 0000000114 65535 f 0000000115 65535 f 0000000116 65535 f 0000000117 65535 f 0000000118 65535 f 0000000119 65535 f 0000000120 65535 f 0000000121 65535 f 0000000122 65535 f 0000000123 65535 f 0000000124 65535 f 0000000125 65535 f 0000000126 65535 f 0000000127 65535 f 0000000128 65535 f 0000000129 65535 f 0000000130 65535 f 0000000131 65535 f 0000000132 65535 f 0000000133 65535 f 0000000134 65535 f 0000000135 65535 f 0000000136 65535 f 0000000137 65535 f 0000000138 65535 f 0000000139 65535 f 0000000140 65535 f 0000000141 65535 f 0000000142 65535 f 0000000143 65535 f 0000000144 65535 f 0000000145 65535 f 0000000146 65535 f 0000000147 65535 f 0000000148 65535 f 0000000149 65535 f 0000000150 65535 f 0000000151 65535 f 0000000152 65535 f 0000000153 65535 f 0000000154 65535 f 0000000155 65535 f 0000000156 65535 f 0000000157 65535 f 0000000158 65535 f 0000000159 65535 f 0000000160 65535 f 0000000161 65535 f 0000000162 65535 f 0000000163 65535 f 0000000164 65535 f 0000000165 65535 f 0000000166 65535 f 0000000167 65535 f 0000000168 65535 f 0000000169 65535 f 0000000170 65535 f 0000000171 65535 f 0000000172 65535 f 0000000173 65535 f 0000000174 65535 f 0000000175 65535 f 0000000176 65535 f 0000000177 65535 f 0000000178 65535 f 0000000179 65535 f 0000000180 65535 f 0000000181 65535 f 0000000182 65535 f 0000000183 65535 f 0000000184 65535 f 0000000185 65535 f 0000000186 65535 f 0000000187 65535 f 0000000188 65535 f 0000000189 65535 f 0000000190 65535 f 0000000191 65535 f 0000000192 65535 f 0000000193 65535 f 0000000194 65535 f 0000000195 65535 f 0000000196 65535 f 0000000197 65535 f 0000000198 65535 f 0000000199 65535 f 0000000200 65535 f 0000000201 65535 f 0000000202 65535 f 0000000203 65535 f 0000000204 65535 f 0000000205 65535 f 0000000206 65535 f 0000000207 65535 f 0000000208 65535 f 0000000209 65535 f 0000000210 65535 f 0000000211 65535 f 0000000212 65535 f 0000000213 65535 f 0000000214 65535 f 0000000215 65535 f 0000000216 65535 f 0000000217 65535 f 0000000218 65535 f 0000000219 65535 f 0000000220 65535 f 0000000221 65535 f 0000000222 65535 f 0000000223 65535 f 0000000224 65535 f 0000000225 65535 f 0000000226 65535 f 0000000227 65535 f 0000000228 65535 f 0000000229 65535 f 0000000230 65535 f 0000000231 65535 f 0000000232 65535 f 0000000233 65535 f 0000000234 65535 f 0000000235 65535 f 0000000236 65535 f 0000000237 65535 f 0000000238 65535 f 0000000239 65535 f 0000000240 65535 f 0000000241 65535 f 0000000242 65535 f 0000000243 65535 f 0000000244 65535 f 0000000245 65535 f 0000000246 65535 f 0000000247 65535 f 0000000248 65535 f 0000000249 65535 f 0000000250 65535 f 0000000251 65535 f 0000000252 65535 f 0000000253 65535 f 0000000254 65535 f 0000000255 65535 f 0000000256 65535 f 0000000257 65535 f 0000000258 65535 f 0000000259 65535 f 0000000260 65535 f 0000000261 65535 f 0000000262 65535 f 0000000263 65535 f 0000000264 65535 f 0000000265 65535 f 0000000266 65535 f 0000000267 65535 f 0000000268 65535 f 0000000269 65535 f 0000000270 65535 f 0000000271 65535 f 0000000272 65535 f 0000000273 65535 f 0000000274 65535 f 0000000275 65535 f 0000000276 65535 f 0000000277 65535 f 0000000278 65535 f 0000000279 65535 f 0000000280 65535 f 0000000281 65535 f 0000000282 65535 f 0000000283 65535 f 0000000284 65535 f 0000000285 65535 f 0000000286 65535 f 0000000287 65535 f 0000000288 65535 f 0000000289 65535 f 0000000290 65535 f 0000000291 65535 f 0000000292 65535 f 0000000293 65535 f 0000000294 65535 f 0000000295 65535 f 0000000296 65535 f 0000000297 65535 f 0000000298 65535 f 0000000299 65535 f 0000000300 65535 f 0000000301 65535 f 0000000302 65535 f 0000000303 65535 f 0000000304 65535 f 0000000305 65535 f 0000000306 65535 f 0000000307 65535 f 0000000308 65535 f 0000000309 65535 f 0000000310 65535 f 0000000311 65535 f 0000000312 65535 f 0000000313 65535 f 0000000314 65535 f 0000000315 65535 f 0000000316 65535 f 0000000317 65535 f 0000000318 65535 f 0000000319 65535 f 0000000320 65535 f 0000000321 65535 f 0000000322 65535 f 0000000323 65535 f 0000000324 65535 f 0000000325 65535 f 0000000326 65535 f 0000000327 65535 f 0000000328 65535 f 0000000329 65535 f 0000000330 65535 f 0000000331 65535 f 0000000332 65535 f 0000000333 65535 f 0000000334 65535 f 0000000335 65535 f 0000000336 65535 f 0000000337 65535 f 0000000338 65535 f 0000000339 65535 f 0000000340 65535 f 0000000341 65535 f 0000000342 65535 f 0000000343 65535 f 0000000344 65535 f 0000000345 65535 f 0000000346 65535 f 0000000347 65535 f 0000000348 65535 f 0000000349 65535 f 0000000350 65535 f 0000000351 65535 f 0000000352 65535 f 0000000353 65535 f 0000000354 65535 f 0000000355 65535 f 0000000356 65535 f 0000000357 65535 f 0000000358 65535 f 0000000359 65535 f 0000000360 65535 f 0000000361 65535 f 0000000362 65535 f 0000000363 65535 f 0000000364 65535 f 0000000365 65535 f 0000000366 65535 f 0000000367 65535 f 0000000368 65535 f 0000000369 65535 f 0000000370 65535 f 0000000371 65535 f 0000000372 65535 f 0000000373 65535 f 0000000374 65535 f 0000000375 65535 f 0000000376 65535 f 0000000377 65535 f 0000000378 65535 f 0000000379 65535 f 0000000380 65535 f 0000000381 65535 f 0000000382 65535 f 0000000383 65535 f 0000000384 65535 f 0000000385 65535 f 0000000386 65535 f 0000000387 65535 f 0000000388 65535 f 0000000389 65535 f 0000000390 65535 f 0000000391 65535 f 0000000392 65535 f 0000000393 65535 f 0000000394 65535 f 0000000395 65535 f 0000000396 65535 f 0000000397 65535 f 0000000398 65535 f 0000000399 65535 f 0000000400 65535 f 0000000401 65535 f 0000000402 65535 f 0000000403 65535 f 0000000404 65535 f 0000000405 65535 f 0000000406 65535 f 0000000407 65535 f 0000000408 65535 f 0000000409 65535 f 0000000410 65535 f 0000000411 65535 f 0000000412 65535 f 0000000413 65535 f 0000000414 65535 f 0000000415 65535 f 0000000416 65535 f 0000000417 65535 f 0000000418 65535 f 0000000419 65535 f 0000000420 65535 f 0000000421 65535 f 0000000422 65535 f 0000000423 65535 f 0000000424 65535 f 0000000425 65535 f 0000000426 65535 f 0000000427 65535 f 0000000428 65535 f 0000000429 65535 f 0000000430 65535 f 0000000431 65535 f 0000000432 65535 f 0000000433 65535 f 0000000434 65535 f 0000000435 65535 f 0000000436 65535 f 0000000437 65535 f 0000000438 65535 f 0000000439 65535 f 0000000440 65535 f 0000000441 65535 f 0000000442 65535 f 0000000443 65535 f 0000000444 65535 f 0000000445 65535 f 0000000446 65535 f 0000000447 65535 f 0000000448 65535 f 0000000449 65535 f 0000000450 65535 f 0000000451 65535 f 0000000452 65535 f 0000000453 65535 f 0000000454 65535 f 0000000455 65535 f 0000000456 65535 f 0000000457 65535 f 0000000458 65535 f 0000000459 65535 f 0000000460 65535 f 0000000461 65535 f 0000000462 65535 f 0000000463 65535 f 0000000464 65535 f 0000000465 65535 f 0000000466 65535 f 0000000467 65535 f 0000000468 65535 f 0000000469 65535 f 0000000470 65535 f 0000000471 65535 f 0000000472 65535 f 0000000473 65535 f 0000000474 65535 f 0000000475 65535 f 0000000476 65535 f 0000000477 65535 f 0000000478 65535 f 0000000479 65535 f 0000000480 65535 f 0000000481 65535 f 0000000482 65535 f 0000000483 65535 f 0000000484 65535 f 0000000485 65535 f 0000000486 65535 f 0000000487 65535 f 0000000488 65535 f 0000000489 65535 f 0000000490 65535 f 0000000491 65535 f 0000000492 65535 f 0000000493 65535 f 0000000494 65535 f 0000000495 65535 f 0000000496 65535 f 0000000497 65535 f 0000000498 65535 f 0000000499 65535 f 0000000000 65535 f 0000058030 00000 n 0000058647 00000 n 0000124945 00000 n 0000125634 00000 n 0000125986 00000 n 0000126252 00000 n 0000160403 00000 n 0000160721 00000 n 0000208117 00000 n 0000208271 00000 n 0000226459 00000 n 0000226760 00000 n 0000237715 00000 n 0000237758 00000 n 0000240873 00000 n 0000240919 00000 n trailer <<394CE81E85D6BD449B311422C384A72F>] >> startxref 242237 %%EOF xref 0 0 trailer <<394CE81E85D6BD449B311422C384A72F>] /Prev 242237/XRefStm 240919>> startxref 252717 %%EOFgenomicepidemiology-kma-091b8ffe66ac/db.h0000644000175000017500000000141014157033525017643 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ void dbInfo(char *filename); int db_main(int argc, char *argv[]); genomicepidemiology-kma-091b8ffe66ac/valueshash.h0000644000175000017500000000321214157033525021423 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef VALUESHASH typedef struct valuesTable ValuesTable; typedef struct valuesHash ValuesHash; struct valuesTable { long unsigned v_index; unsigned *values; struct valuesTable *next; }; struct valuesHash { long unsigned n; long unsigned size; struct valuesTable **table; int DB_size; }; #define VALUESHASH 1 #endif extern long unsigned (*valuesKeyPtr)(unsigned *, int); extern int (*cmpValuesPtr)(unsigned *, unsigned *, unsigned); ValuesHash * initialize_hashValues(long unsigned size, int DB_size); void valuesHash_destroy(ValuesHash *src); long unsigned valuesKey(unsigned *values, int DB_size); long unsigned huValuesKey(unsigned *valuesOrg, int DB_size); unsigned uSize(unsigned *values); unsigned huSize(unsigned *valuesOrg); int cmpValues(unsigned *s1, unsigned *s2, unsigned len); int cmpHuValues(unsigned *s1_org, unsigned *s2_org, unsigned len_org); long unsigned valuesHash_add(ValuesHash *src, unsigned *newValues, long unsigned v_index); genomicepidemiology-kma-091b8ffe66ac/runinput.h0000644000175000017500000000330414157033525021146 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "compdna.h" #include "qseqs.h" /* pointers determining how to deliver the input */ extern void (*printFsa_ptr)(Qseqs*, Qseqs*, CompDNA*, FILE*); extern void (*printFsa_pair_ptr)(Qseqs*, Qseqs*, Qseqs*, Qseqs*, CompDNA*, FILE*); long unsigned run_input(char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int minlen, int maxlen, char *trans, const double *prob, FILE *out); long unsigned run_input_PE(char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int minlen, char *trans, const double *prob, FILE *out); long unsigned run_input_INT(char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int minlen, char *trans, const double *prob, FILE *out); void bootFsa(Qseqs *header, Qseqs *qseq, CompDNA *compressor, FILE *out); void printFsa(Qseqs *header, Qseqs *qseq, CompDNA *compressor, FILE *out); void printFsa_pair(Qseqs *header, Qseqs *qseq, Qseqs *header_r, Qseqs *qseq_r, CompDNA *compressor, FILE *out); genomicepidemiology-kma-091b8ffe66ac/version.h0000644000175000017500000000134314157033525020750 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define KMA_VERSION "1.3.28" genomicepidemiology-kma-091b8ffe66ac/decon.h0000644000175000017500000000250414157033525020353 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "compdna.h" #include "hashmapkma.h" extern int (*deConNode_ptr)(CompDNA *, HashMapKMA *, unsigned **); extern int (*addCont)(HashMapKMA *, long unsigned, int, unsigned **); int hashMap_addCont(HashMapKMA *dest, long unsigned key, int value, unsigned **Values); int megaMap_addCont(HashMapKMA *dest, long unsigned index, int value, unsigned **Values); int deConNode(CompDNA *qseq, HashMapKMA *finalDB, unsigned **Values); int deConNode_sparse(CompDNA *qseq, HashMapKMA *finalDB, unsigned **Values); unsigned deConDB(HashMapKMA *finalDB, char **inputfiles, int fileCount, char *trans, unsigned **Values); genomicepidemiology-kma-091b8ffe66ac/frags.c0000644000175000017500000001040314157033525020355 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "filebuff.h" #include "frags.h" #include "pherror.h" #include "qseqs.h" #include "threader.h" #include "tmp.h" FILE * printFrags(Frag **alignFrags, int DB_size) { int i; FILE *OUT; Frag *alignFrag, *next; if(!(OUT = tmpF(0))) { fprintf(stderr, "Could not create tmp files.\n"); ERROR(); } for(i = 0; i < DB_size; ++i) { if(alignFrags[i]) { for(alignFrag = alignFrags[i]; alignFrag != 0; alignFrag = next) { next = alignFrag->next; sfwrite(&i, sizeof(int), 1, OUT); sfwrite(alignFrag->buffer, sizeof(int), 7, OUT); sfwrite(alignFrag->qseq, 1, alignFrag->buffer[0], OUT); sfwrite(alignFrag->header, 1, alignFrag->buffer[5], OUT); free(alignFrag->qseq); free(alignFrag->header); free(alignFrag); } alignFrags[i] = 0; } } sfwrite(&(int){-1}, sizeof(int), 1, OUT); fflush(OUT); rewind(OUT); return OUT; } void updateAllFrag(unsigned char *qseq, int q_len, int bestHits, int best_read_score, int *best_start_pos, int *best_end_pos, int *bestTemplates, Qseqs *header, FileBuff *dest) { static volatile int Lock = 0; volatile int *lock = &Lock; int i, check, avail; char *update; const char bases[6] = "ACGTN-"; if(!q_len) { return; } lock(lock); check = q_len; avail = dest->bytes; if(avail < check) { writeGzFileBuff(dest); /* seq is too big, reallocate buffer */ if(dest->bytes < check) { resetGzFileBuff(dest, check << 1); } avail = dest->bytes; } /* copy seq */ update = (char *) dest->next; ++q_len; --qseq; while(--q_len) { *update++ = bases[*++qseq]; } avail -= check; check = 33; if(avail < check) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } check = sprintf(update, "\t%d\t%d\t%d", bestHits, best_read_score, *best_start_pos); avail -= check; update += check; for(i = 1; i < bestHits; ++i) { if(avail < 11) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } check = sprintf(update, ",%d", best_start_pos[i]); avail -= check; update += check; } if(avail < 11) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } check = sprintf(update, "\t%d", *best_end_pos); avail -= check; update += check; for(i = 1; i < bestHits; ++i) { if(avail < 11) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } check = sprintf(update, ",%d", best_end_pos[i]); avail -= check; update += check; } if(avail < 11) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } check = sprintf(update, "\t%d", *bestTemplates); avail -= check; update += check; for(i = 1; i < bestHits; ++i) { if(avail < 12) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } check = sprintf(update, ",%d", bestTemplates[i]); avail -= check; update += check; } /* q-bound */ if(2 * sizeof(int) + 1 < header->len && header->seq[header->len - 2 * sizeof(int) - 1] == 0) { i = header->len - 2 * sizeof(int) - 1; } else { i = header->len; } check = i + 1; if(avail < check) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } *update++ = '\t'; memcpy(update, header->seq, i--); update += i; *update++ = '\n'; dest->bytes = avail - check; dest->next = (unsigned char *) update; unlock(lock); } genomicepidemiology-kma-091b8ffe66ac/mt1.h0000644000175000017500000000245214157033525017766 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "compdna.h" #include "penalties.h" #include "qseqs.h" void printFsaMt1(Qseqs *header, Qseqs *qseq, CompDNA *compressor, FILE *out); void printFsa_pairMt1(Qseqs *header, Qseqs *qseq, Qseqs *header_r, Qseqs *qseq_r, CompDNA *compressor, FILE *out); void runKMA_Mt1(char *templatefilename, char *outputfilename, char *exePrev, int kmersize, int minlen, Penalties *rewards, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int Mt1, int ref_fsa, int print_matrix, int vcf, int xml, int sam, int nc, int nf, int thread_num); genomicepidemiology-kma-091b8ffe66ac/stdnuc.h0000644000175000017500000000307514157033525020567 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define getNuc(Comp,pos) ((Comp[pos >> 5] << ((pos & 31) << 1)) >> 62) #define setEx(src, pos)(src[pos >> 3] |= (1 << (pos & 7))) #define unsetEx(src, pos)(src[pos >> 3] ^= (1 << (pos & 7))) #define getEx(src, pos)((src[pos >> 3] >> (pos & 7)) & 1) #define getKmer_macro(kmer, Comp, pos, cPos, iPos, shifter) \ iPos = (pos & 31) << 1;\ cPos = pos >> 5;\ kmer = (iPos <= shifter) ? ((Comp[cPos] << iPos) >> shifter) : (((Comp[cPos] << iPos) | (Comp[cPos + 1] >> (64-iPos))) >> shifter); long unsigned getKmer(long unsigned *compressor, unsigned cPos, const unsigned shifter); long unsigned makeKmer(const unsigned char *qseq, unsigned pos, unsigned size); int charpos(const unsigned char *src, unsigned char target, int start, int len); void strrc(unsigned char *qseq, int q_len); void strtranslate(unsigned char *strp, char *trans); void nibble2base(unsigned char *seq, int len); genomicepidemiology-kma-091b8ffe66ac/hashmapindex.h0000644000175000017500000000654014157033525021740 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #ifndef HASHMAPINDEX typedef struct hashMap_index HashMap_index; struct hashMap_index { unsigned len; // seqlen unsigned size; // size of index int *index; // k-mer posititions in seq long unsigned *seq; // 2-bit sequence unsigned kmerindex; }; #define HASHMAPINDEX 1 #endif /* pointers determining how indexes a stored */ extern void (*destroyPtr)(HashMap_index *); extern HashMap_index * (*alignLoadPtr)(HashMap_index *, int, int, int, int, long unsigned, long unsigned); int hashMap_index_initialize(HashMap_index *dest, int len, int kmerindex); void hashMap_index_set(HashMap_index *dest); void hashMap_index_destroy(HashMap_index *dest); int hashMap_index_get(const HashMap_index *dest, long unsigned key, unsigned shifter); int hashMap_index_get_bound(const HashMap_index *dest, long unsigned key, int min, int max, unsigned shifter); int hashMap_index_getDubPos(const HashMap_index *dest, long unsigned key, int value, unsigned shifter); int hashMap_index_getNextDubPos(const HashMap_index *dest, long unsigned key, int min, int max, unsigned index, unsigned shifter); void hashMap_index_add(HashMap_index *dest, long unsigned key, int newpos, unsigned shifter); void hashMapIndex_add(HashMap_index *dest, long unsigned key, int newpos); HashMap_index * hashMap_index_load(HashMap_index *src, int seq, int index, int len, int kmersize); void hashMap_index_dump(HashMap_index *src, FILE *seq, FILE *index); HashMap_index * hashMap_index_build(HashMap_index *src, int seq, int len, int kmersize); HashMap_index * alignLoad_fly(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index); HashMap_index * alignLoad_fly_mem(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index); HashMap_index * alignLoad_fly_build(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index); HashMap_index * alignLoad_fly_build_mem(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index); HashMap_index * alignLoad_skip(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index); HashMap_index * alignLoad_fly_shm(HashMap_index *dest, int seq_in, int index_in, int len, int kmersize, long unsigned seq_index, long unsigned index_index); HashMap_index * alignLoad_shm_initial(char *templatefilename, int file_len, int seq_in, int index_in, int kmersize); void alignClean(HashMap_index *template_index); void alignClean_shm(HashMap_index *template_index); genomicepidemiology-kma-091b8ffe66ac/ef.c0000644000175000017500000001073114157033525017651 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "assembly.h" #include "ef.h" #include "stdnuc.h" #include "threader.h" #include "vcf.h" #include "version.h" void initExtendedFeatures(FILE *out, char *templatefilename, unsigned totFrags, char *cmd) { char Date[11]; time_t t1; struct tm *tm; fprintf(out, "## method\tKMA\n"); fprintf(out, "## version\t%s\n", KMA_VERSION); fprintf(out, "## database\t%s\n", noFolder(templatefilename)); fprintf(out, "## fragmentCount\t%u\n", totFrags); time(&t1); tm = localtime(&t1); strftime(Date, sizeof(Date), "%Y-%m-%d", tm); fprintf(out, "## date\t%s\n", Date); fprintf(out, "## command\t%s\n", cmd); fprintf(out, "# refSequence\treadCount\tfragmentCount\tmapScoreSum\trefCoveredPositions\trefConsensusSum\tbpTotal\tdepthVariance\tnucHighDepthVariance\tdepthMax\tsnpSum\tinsertSum\tdeletionSum\treadCountAln\tfragmentCountAln\n"); } void getExtendedFeatures(Assem *aligned_assem, AssemInfo *matrix, long unsigned *seq, int t_len, int thread_num) { static volatile int Lock = 0, next, thread_wait = 0; volatile int *excludeMatrix = &Lock; unsigned pos, end, asm_len, chunk, nucHighVar, maxDepth, depthUpdate; long unsigned snpSum, insertSum, deletionSum; double highVar; Assembly *assembly; /* init */ asm_len = matrix->len; assembly = matrix->assmb; maxDepth = 0; nucHighVar = 0; snpSum = 0; insertSum = 0; deletionSum = 0; highVar = (long double)(aligned_assem->depth) / t_len + 3 * sqrt(aligned_assem->var); chunk = 8112; lock(excludeMatrix); if(!thread_wait) { next = 0; thread_wait = thread_num; aligned_assem->fragmentCountAln = (((aligned_assem->readCountAln >> 1) + (aligned_assem->readCountAln & 1)) <= aligned_assem->fragmentCountAln) ? (aligned_assem->fragmentCountAln) : ((aligned_assem->readCountAln >> 1) + (aligned_assem->readCountAln & 1)); } unlock(excludeMatrix); /* get nucHighVar */ while(chunk) { lock(excludeMatrix); pos = next; if((next += chunk) < 0) { next = asm_len; } unlock(excludeMatrix); /* call chunk */ if(pos < asm_len) { end = pos + chunk; if(asm_len < end) { end = asm_len; chunk = 0; } while(pos < end) { depthUpdate = assembly[pos].counts[0] + assembly[pos].counts[1] + assembly[pos].counts[2] + assembly[pos].counts[3] + assembly[pos].counts[4]; if(pos < t_len) { deletionSum += assembly[pos].counts[5]; snpSum += (depthUpdate - assembly[pos].counts[getNuc(seq, pos)]); } else { insertSum += depthUpdate; } depthUpdate += assembly[pos].counts[5]; if(maxDepth < depthUpdate) { maxDepth = depthUpdate; } if(highVar < depthUpdate) { ++nucHighVar; } ++pos; } } else { chunk = 0; } } lock(excludeMatrix); aligned_assem->nucHighVar += nucHighVar; if(aligned_assem->maxDepth < maxDepth) { aligned_assem->maxDepth = maxDepth; } aligned_assem->snpSum += snpSum; aligned_assem->insertSum += insertSum; aligned_assem->deletionSum += deletionSum; --thread_wait; unlock(excludeMatrix); wait_atomic(thread_wait); } void printExtendedFeatures(char *template_name, Assem *aligned_assem, unsigned fragmentCount, unsigned readCount, FILE *outfile) { if(aligned_assem) { fprintf(outfile, "%s\t%u\t%u\t%lu\t%u\t%u\t%lu\t%f\t%u\t%u\t%lu\t%lu\t%lu\t%u\t%u\n", template_name, readCount, fragmentCount, aligned_assem->score, aligned_assem->aln_len, aligned_assem->cover, aligned_assem->depth, aligned_assem->var, aligned_assem->nucHighVar, aligned_assem->maxDepth, aligned_assem->snpSum, aligned_assem->insertSum, aligned_assem->deletionSum, aligned_assem->readCountAln, aligned_assem->fragmentCountAln); } else { fprintf(outfile, "%s\t%u\t%u\t%u\t%u\t%u\t%u\t%f\t%u\t%u\t%u\t%u\t%u\t%u\t%u\n", template_name, 0, 0, 0, 0, 0, 0, 0.0, 0, 0, 0, 0, 0, 0, 0); } } genomicepidemiology-kma-091b8ffe66ac/kmers.h0000644000175000017500000000166714157033525020415 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "penalties.h" int save_kmers_batch(char *templatefilename, char *exePrev, unsigned shm, int thread_num, const int exhaustive, Penalties *rewards, FILE *out, int sam, int minlen, double mrs, double coverT); genomicepidemiology-kma-091b8ffe66ac/filebuff.c0000644000175000017500000001352214157033525021042 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "filebuff.h" #include "pherror.h" #include "qseqs.h" int (*buffFileBuff)(FileBuff *) = &BuffgzFileBuff; int BuffgzFileBuff(FileBuff *dest) { int status; z_stream *strm; /* check compressed buffer, and load it */ strm = dest->strm; if(strm->avail_in == 0) { strm->avail_in = fread(dest->inBuffer, 1, dest->buffSize, dest->file); strm->next_in = (unsigned char*) dest->inBuffer; if(strm->avail_in == 0) { dest->bytes = 0; dest->next = dest->buffer; return 0; } } /* reset uncompressed buffer */ strm->avail_out = dest->buffSize; strm->next_out = (unsigned char*) dest->buffer; /* uncompress buffer */ status = inflate(strm, Z_NO_FLUSH); dest->z_err = status; /* concatenated file */ if(status == Z_STREAM_END && strm->avail_out == dest->buffSize) { inflateReset(strm); return BuffgzFileBuff(dest); } if(status == Z_OK || status == Z_STREAM_END) { dest->bytes = dest->buffSize - strm->avail_out; dest->next = dest->buffer; if(status == Z_OK && dest->bytes == 0) { return BuffgzFileBuff(dest); } } else { dest->bytes = 0; dest->next = dest->buffer; fprintf(stderr, "Gzip error %d\n", status); errno |= status; } return dest->bytes; } void init_gzFile(FileBuff *inputfile) { int status; unsigned char *tmp; z_stream *strm; /* set inBuffer, for compressed format */ if(inputfile->inBuffer) { tmp = inputfile->buffer; inputfile->buffer = inputfile->inBuffer; inputfile->inBuffer = tmp; } else { inputfile->inBuffer = inputfile->buffer; inputfile->buffer = smalloc(CHUNK); } inputfile->next = inputfile->buffer; /* set the compressed stream */ strm = inputfile->strm; if(!strm && !(strm = malloc(sizeof(z_stream)))) { ERROR(); } strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; status = inflateInit2(strm, 15 | ENABLE_ZLIB_GZIP); if(status < 0) { fprintf(stderr, "Gzip error %d\n", status); exit(status); } strm->next_in = inputfile->inBuffer; strm->avail_in = inputfile->bytes; strm->avail_out = 0; inputfile->strm = strm; inputfile->z_err = Z_OK; inputfile->bytes = BuffgzFileBuff(inputfile); } FileBuff * setFileBuff(int buffSize) { FileBuff *dest; dest = smalloc(sizeof(FileBuff)); dest->file = 0; dest->inBuffer = 0; dest->strm = 0; dest->buffSize = buffSize; dest->buffer = smalloc(buffSize); dest->next = dest->buffer; return dest; } void openFileBuff(FileBuff *dest, char *filename, char *mode) { dest->file = sfopen(filename, mode); } void closeFileBuff(FileBuff *dest) { fclose(dest->file); dest->file = 0; } void gzcloseFileBuff(FileBuff *dest) { int status; if((status = inflateEnd(dest->strm)) != Z_OK) { fprintf(stderr, "Gzip error %d\n", status); errno |= status; } if(dest->z_err != Z_STREAM_END) { fprintf(stderr, "Unexpected end of file\n"); errno |= status; } fclose(dest->file); dest->file = 0; dest->strm->avail_out = 0; } void destroyFileBuff(FileBuff *dest) { free(dest->buffer); free(dest->inBuffer); free(dest->strm); free(dest); } int buff_FileBuff(FileBuff *dest) { dest->bytes = fread(dest->buffer, 1, dest->buffSize, dest->file); dest->next = dest->buffer; return dest->bytes; } z_stream * strm_init() { z_stream *strm; int status; strm = smalloc(sizeof(z_stream)); strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; status = deflateInit2(strm, 1, Z_DEFLATED, 31 | GZIP_ENCODING, 9, Z_FILTERED); if(status < 0) { fprintf(stderr, "Gzip error %d\n", status); exit(status); } return strm; } FileBuff * gzInitFileBuff(int size) { FileBuff *dest; dest = smalloc(sizeof(FileBuff)); dest->file = 0; dest->bytes = size; dest->buffSize = size; dest->strm = strm_init(); dest->buffer = smalloc(size); dest->inBuffer = smalloc(size); dest->next = dest->buffer; return dest; } void resetGzFileBuff(FileBuff *dest, int size) { dest->bytes = size; dest->buffSize = size; free(dest->buffer); free(dest->inBuffer); dest->buffer = smalloc(size); dest->inBuffer = smalloc(size); dest->next = dest->buffer; } void writeGzFileBuff(FileBuff *dest) { int check = Z_OK; z_stream *strm = dest->strm; strm->avail_in = dest->buffSize - dest->bytes; strm->next_in = dest->buffer; strm->avail_out = 0; while(strm->avail_out == 0 && check != Z_STREAM_END) { strm->avail_out = dest->buffSize; strm->next_out = dest->inBuffer; check = deflate(strm, Z_NO_FLUSH); sfwrite(dest->inBuffer, 1, dest->buffSize - strm->avail_out, dest->file); } dest->bytes = dest->buffSize; dest->next = dest->buffer; } void closeGzFileBuff(FileBuff *dest) { int check = Z_OK; z_stream *strm = dest->strm; strm->avail_in = dest->buffSize - dest->bytes; strm->next_in = dest->buffer; strm->avail_out = 0; while(strm->avail_out == 0 && check != Z_STREAM_END) { strm->avail_out = dest->buffSize; strm->next_out = dest->inBuffer; check = deflate(strm, Z_FINISH); sfwrite(dest->inBuffer, 1, dest->buffSize - strm->avail_out, dest->file); } deflateEnd(strm); fclose(dest->file); } void destroyGzFileBuff(FileBuff *dest) { closeGzFileBuff(dest); free(dest->strm); free(dest->buffer); free(dest->inBuffer); free(dest); } genomicepidemiology-kma-091b8ffe66ac/stdstat.h0000644000175000017500000000221014157033525020743 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define MIN(X, Y) ((X < Y) ? X : Y) #define MAX(X, Y) ((X < Y) ? Y : X) extern int (*cmp)(int, int); int cmp_or(int t, int q); int cmp_and(int t, int q); int cmp_true(int t, int q); double fastp(long double q); double p_chisqr(long double q); double power(double x, unsigned n); double binP(int n, int k, double p); unsigned minimum(unsigned *src, unsigned n); unsigned eQual(unsigned char *qual, const int len, const int minQ, const double *prob); genomicepidemiology-kma-091b8ffe66ac/vcf.c0000644000175000017500000002177314157033525020045 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "assembly.h" #include "filebuff.h" #include "stdnuc.h" #include "stdstat.h" #include "version.h" #include "vcf.h" char * noFolder(const char *src) { int pos; pos = strlen(src) - 1; while(pos && src[pos] != '/') { --pos; } if(pos) { ++pos; } return ((char *) src) + pos; } void initialiseVcf(FileBuff *fileP, char *templateFilename) { unsigned check, avail; char *update; update = (char *) fileP->next; avail = fileP->bytes; /* header stuff */ check = sprintf(update, "##fileformat=VCFv4.2\n"); update += check; avail -= check; check = sprintf(update, "##kmaVersion=%s\n", KMA_VERSION); update += check; avail -= check; /* filter stuff */ check = sprintf(update, "##FILTER=\n"); update += check; avail -= check; /* INFO stuff */ check = sprintf(update, "##INFO=\n"); update += check; avail -= check; check = sprintf(update, "##INFO=\n"); update += check; avail -= check; check = sprintf(update, "##INFO=\n"); update += check; avail -= check; check = sprintf(update, "##INFO=\n"); update += check; avail -= check; check = sprintf(update, "##INFO=\n"); update += check; avail -= check; check = sprintf(update, "##INFO=\n"); update += check; avail -= check; /* FORMAT stuff */ check = sprintf(update, "##FORMAT=\n"); update += check; avail -= check; check = sprintf(update, "##FORMAT=\n"); update += check; avail -= check; check = sprintf(update, "##FORMAT=\n"); update += check; avail -= check; if(templateFilename) { check = sprintf(update, "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\t%s\n", noFolder(templateFilename)); } else { check = sprintf(update, "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tspltDB\n"); } update += check; avail -= check; fileP->next = (unsigned char *) update; fileP->bytes = avail; } void updateVcf(char *template_name, unsigned char *template_seq, double evalue, double support, int bcd, int t_len, AssemInfo *matrix, int filter, FileBuff *fileP) { static const char nuc2num[256] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 8, 1, 8, 8, 8, 2, 8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 8, 1, 8, 8, 8, 2, 8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; const char *PASS = "PASS", *FAIL = "FAIL", *LowQual = "LowQual", *UNKNOWN = "."; int i, pos, nextPos, bestScore, depthUpdate, bestBaseScore, nucNum; int template_name_length, check, avail, DP, AD, DEL, QUAL; double AF, RAF, Q, P; const double lnConst = -10 / log(10); char *FILTER, **FILTER_ptr, *update; unsigned char nuc, bestNuc; const char bases[6] = "ACGTN-"; Assembly *assembly; if(filter == 2) { FILTER_ptr = &FILTER; } else { FILTER_ptr = (char **) &UNKNOWN; } template_name_length = strlen(template_name); update = (char *) fileP->next; avail = fileP->bytes; assembly = matrix->assmb; nextPos = 0; do { pos = nextPos; nextPos = assembly[pos].next; /* handle insertions now */ nuc = *template_seq++; if(pos < t_len) { ++i; } else if(nuc != '-') { --template_seq; nuc = '-'; } /* call base */ bestNuc = nuc2num[nuc]; bestScore = assembly[pos].counts[bestNuc]; depthUpdate = 0; for(i = 0; i < 6; ++i) { if(bestScore < assembly[pos].counts[i]) { bestScore = assembly[pos].counts[i]; bestNuc = i; } depthUpdate += assembly[pos].counts[i]; } nucNum = bestNuc; bestNuc = bases[bestNuc]; /* Check for minor base call */ if(!depthUpdate) { nucNum = 5; bestNuc = '-'; } else if((bestScore << 1) < depthUpdate) { if(bestNuc == '-') { bestBaseScore = 0; bestNuc = 4; for(i = 0; i < 5; ++i) { if(bestBaseScore < assembly[pos].counts[i]) { bestBaseScore = assembly[pos].counts[i]; bestNuc = i; } } nucNum = bestNuc; bestNuc = tolower(bases[bestNuc]); } else { bestNuc = tolower(bestNuc); } bestScore = depthUpdate - assembly[pos].counts[5]; } else if(depthUpdate < bcd) { /* too low depth */ bestNuc = tolower(bestNuc); } if(bestScore) { /* determine base at current position */ bestNuc = baseCall(bestNuc, nuc, bestScore, depthUpdate, evalue, &assembly[pos]); nucNum = nuc2num[bestNuc]; /* INFO */ DP = depthUpdate; AD = assembly[pos].counts[nucNum]; AF = (double) AD / DP; RAF = (double) bestScore / DP; DEL = assembly[pos].counts[5]; Q = pow(depthUpdate - (bestScore << 1), 2) / depthUpdate; P = p_chisqr(Q); /* discard unimportant changes */ if(nuc != bestNuc || (t_len <= nextPos && *template_seq == '-') || DP < bcd || evalue < P || AD < support * DP) { /* QUAL */ //QUAL = lnConst * log(P); QUAL = lnConst * log(binP(DP, AD, 0.25)); QUAL = (QUAL < 0 || 3079 < QUAL) ? 3079 : QUAL; /* FILTER */ if(bcd <= DP && P <= evalue && support * DP <= AD) { FILTER = (char *) PASS; } else if(bcd <= DP || P <= evalue || support * DP <= AD) { FILTER = (char *) LowQual; } else { FILTER = (char *) FAIL; } if(avail < template_name_length + 167) { fileP->bytes = avail; writeGzFileBuff(fileP); avail = fileP->bytes; update = (char *) fileP->next; } strcpy(update, template_name); update += template_name_length; avail -= template_name_length; *update++ = '\t'; --avail; if(pos < t_len) { check = sprintf(update, "%d", pos + 1); update += check; avail -= check; } else { *update++ = '0'; --avail; } *update++ = '\t'; *update++ = '.'; *update++ = '\t'; avail -= 3; if(nuc != '-') { *update++ = nuc; --avail; } else { *update++ = '<'; *update++ = nuc; *update++ = '>'; avail -= 3; } *update++ = '\t'; --avail; if(bestNuc == '-') { *update++ = '<'; *update++ = bestNuc; *update++ = '>'; avail -= 3; } else { *update++ = bestNuc; --avail; } check = sprintf(update, "\t%d\t%s\tDP=%d;AD=%d;AF=%.2f;RAF=%.2f;DEL=%d;", QUAL, *FILTER_ptr, DP, AD, AF, RAF, DEL); update += check; avail -= check; check = sprintf(update, "AD6=%d,%d,%d,%d,%d,%d\t", assembly[pos].counts[0], assembly[pos].counts[1], assembly[pos].counts[2], assembly[pos].counts[3], assembly[pos].counts[4], assembly[pos].counts[5]); update += check; avail -= check; check = sprintf(update, "Q:P:FT\t%.2f:%4.1e:%s\n", Q, P, FILTER); update += check; avail -= check; } } else if(pos < t_len) { FILTER = (char *) FAIL; if(avail < template_name_length + 105) { fileP->bytes = avail; writeGzFileBuff(fileP); avail = fileP->bytes; update = (char *) fileP->next; } check = sprintf(update, "%s\t%d\t.\t%c\t%c\t%d\t%s\t", template_name, pos + 1, nuc, '.', 0, *FILTER_ptr); update += check; avail -= check; check = sprintf(update, "DP=%d;AD=%d;AF=%.2f;RAF=%.2f;DEL=%d;AD6=%d,%d,%d,%d,%d,%d\t", 0, 0, 0.0, 0.0, 0, 0, 0, 0, 0, 0, 0); update += check; avail -= check; check = sprintf(update, "Q:P:FT\t%.2f:%4.1e:%s\n", 0.0, 1.0, FILTER); update += check; avail -= check; } } while(nextPos != 0); fileP->next = (unsigned char *) update; fileP->bytes = avail; } genomicepidemiology-kma-091b8ffe66ac/kmapipe.h0000644000175000017500000000241014157033525020705 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #ifdef _WIN32 #include #else #include #endif #ifndef KMAPIPE typedef struct pid Pid; struct pid { pthread_t id; pid_t pid; FILE *fp; FILE *ioStream; char *cmd; struct pid *next; }; #define KMAPIPE 1 #endif /* open or close pipe */ extern FILE * (*kmaPipe)(const char*, const char*, FILE*, int*); void * pipeThreader(void *arg); FILE * kmaPipeThread(const char *cmd, const char *type, FILE *ioStream, int *status); FILE * kmaPipeFork(const char *cmd, const char *type, FILE *ioStream, int *status); genomicepidemiology-kma-091b8ffe66ac/spltdb.h0000644000175000017500000000330314157033525020551 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "compdna.h" #include "qseqs.h" #ifndef SPLTDB typedef struct spltDBbuff SpltDBbuff; struct spltDBbuff { int num; int size; unsigned char *buff; struct spltDBbuff *next; struct spltDBbuff *prev; }; #define SPLTDB 1 #endif int print_ankers_spltDB(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out); int print_ankers_Sparse_spltDB(int *out_Tem, CompDNA *qseq, int rc_flag, const Qseqs *header, const int flag, FILE *out); unsigned get_ankers_spltDB(int *infoSize, int *out_Tem, CompDNA *qseq, Qseqs *header, int *flag, FILE *inputfile); int runKMA_spltDB(char **templatefilenames, int targetNum, char *outputfilename, int argc, char **argv, int ConClave, int kmersize, int minlen, Penalties *rewards, int extendedFeatures, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int ref_fsa, int print_matrix, int print_all, int vcf, int xml, int sam, int nc, int nf, unsigned shm, int thread_num, int verbose); genomicepidemiology-kma-091b8ffe66ac/main.c0000644000175000017500000000502314157033525020201 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "db.h" #include "dist.h" #include "kma.h" #include "index.h" #include "shm.h" #include "seq2fasta.h" #include "update.h" static int helpmessage(FILE *out) { fprintf(out, "# KMA enables alignment towards databases, using two k-mer mapping steps and one alignment step.\n"); fprintf(out, "# %16s\t%-32s\n", "Options are:", "Desc:"); fprintf(out, "# %16s\t%-32s\n", "", "Alignment and mapping"); fprintf(out, "# %16s\t%-32s\n", "index", "Indexing of databases"); fprintf(out, "# %16s\t%-32s\n", "shm", "Shared memory"); fprintf(out, "# %16s\t%-32s\n", "seq2fasta", "Conversion of database to fasta"); fprintf(out, "# %16s\t%-32s\n", "dist", "Calculate distance measures between templates"); fprintf(out, "# %16s\t%-32s\n", "db", "Make statistics on KMA db"); fprintf(out, "# %16s\t%-32s\n", "update", "Update database to current version"); fprintf(out, "# %16s\t%-32s\n", "-c", "Citation"); fprintf(out, "# %16s\t%-32s\n", "-v", "Version"); fprintf(out, "# %16s\t%-32s\n", "-h", "Help on alignment and mapping"); return 1; } int main(int argc, char *argv[]) { int status; if(argc != 1) { if(**++argv == '-') { status = kma_main(argc, --argv); } else if(--argc && strcmp(*argv, "index") == 0) { status = index_main(argc, argv); } else if(strcmp(*argv, "shm") == 0) { status = shm_main(argc, argv); } else if(strcmp(*argv, "seq2fasta") == 0) { status = seq2fasta_main(argc, argv); } else if(strcmp(*argv, "dist") == 0) { status = dist_main(argc, argv); } else if(strcmp(*argv, "update") == 0) { status = update_main(argc, argv); } else if(strcmp(*argv, "db") == 0) { status = db_main(argc, argv); } else { fprintf(stderr, "Invalid option:\t%s\n", *argv); status = helpmessage(stderr); } } else { status = helpmessage(stdout); } return status; } genomicepidemiology-kma-091b8ffe66ac/alnfrags.h0000644000175000017500000001123614157033525021062 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "chain.h" #include "compdna.h" #include "filebuff.h" #include "hashmapcci.h" #include "qseqs.h" #ifndef ALNTHREAD typedef struct aln_thread Aln_thread; struct aln_thread { pthread_t id; int *matched_templates; int *bestTemplates; int *bestTemplates_r; int *best_start_pos; int *best_end_pos; int *template_lengths; long unsigned *alignment_scores; long unsigned *uniq_alignment_scores; long *seq_indexes; FILE *inputfile; FILE *frag_out_raw; FileBuff *frag_out_all; int seq_in; int kmersize; int minlen; int mq; int sam; double scoreT; double mrc; CompDNA *qseq_comp; CompDNA *qseq_r_comp; Qseqs *qseq; Qseqs *qseq_r; Qseqs *header; Qseqs *header_r; AlnPoints *points; NWmat *NWmatrices; HashMapCCI **templates_index; struct aln_thread *next; }; #define ALNTHREAD 1; #endif extern int (*alnFragsPE)(HashMapCCI**, int*, int*, int, double, double, int, CompDNA*, CompDNA*, CompDNA*, CompDNA*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, Qseqs*, Qseqs*, int, int*, int*, long unsigned*, long unsigned*, int*, int*, int*, int*, int*, int*, int, long*, FILE*, AlnPoints*, NWmat*, volatile int*, volatile int*); int alnFragsSE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, int rc_flag, CompDNA *qseq_comp, CompDNA *qseq_r_comp, unsigned char *qseq, unsigned char *qseq_r, int q_len, int kmersize, Qseqs *header, int *bestTemplates, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *best_read_score, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB); int alnFragsUnionPE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, CompDNA *qseq_comp, CompDNA *qseq_r_comp, CompDNA *qseq_fr_comp, CompDNA *qseq_rr_comp, unsigned char *qseq, unsigned char *qseq_r, unsigned char *qseq_fr, unsigned char *qseq_rr, Qseqs *header, Qseqs *header_r, int kmersize, int *bestTemplates, int *bestTemplates_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *flag_r, int *best_read_score, int *best_read_score_r, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB); int alnFragsPenaltyPE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, CompDNA *qseq_comp, CompDNA *qseq_r_comp, CompDNA *qseq_fr_comp, CompDNA *qseq_rr_comp, unsigned char *qseq, unsigned char *qseq_r, unsigned char *qseq_fr, unsigned char *qseq_rr, Qseqs *header, Qseqs *header_r, int kmersize, int *bestTemplates, int *bestTemplates_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *flag_r, int *best_read_score, int *best_read_score_r, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB); int alnFragsForcePE(HashMapCCI **templates_index, int *matched_templates, int *template_lengths, int mq, double scoreT, double mrc, int minlen, CompDNA *qseq_comp, CompDNA *qseq_r_comp, CompDNA *qseq_fr_comp, CompDNA *qseq_rr_comp, unsigned char *qseq, unsigned char *qseq_r, unsigned char *qseq_fr, unsigned char *qseq_rr, Qseqs *header, Qseqs *header_r, int kmersize, int *bestTemplates, int *bestTemplates_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, int *best_start_pos, int *best_end_pos, int *flag, int *flag_r, int *best_read_score, int *best_read_score_r, int seq_in, long *seq_indexes, FILE *frag_out_raw, AlnPoints *points, NWmat *NWmatrices, volatile int *excludeOut, volatile int *excludeDB); void * alnFrags_threaded(void * arg); genomicepidemiology-kma-091b8ffe66ac/kmathread.h0000644000175000017500000000214114157033525021220 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include int usleep(unsigned usec); #define lock(exclude) while(__sync_lock_test_and_set(exclude, 1)) {while(*exclude) {usleep(100);}} #define lockTime(exclude, spin) while(__sync_lock_test_and_set(exclude, 1)) {while(*exclude) {usleep(spin);}} #define unlock(exclude) (__sync_lock_release(exclude)) #define wait_atomic(src) while(src) {usleep(100);} genomicepidemiology-kma-091b8ffe66ac/makeindex.c0000644000175000017500000001213014157033525021217 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include "compdna.h" #include "filebuff.h" #include "hashmap.h" #include "makeindex.h" #include "pherror.h" #include "qseqs.h" #include "seqparse.h" #include "updateindex.h" int (*biasPrintPtr)(FILE*, char*, unsigned char*, int) = &biasPrint; int biasPrint(FILE *name_out, char *format, unsigned char *name, int bias) { return fprintf(name_out, "%s B%d\n", name, bias); } int biasNoPrint(FILE *name_out, char *format, unsigned char *name, int bias) { return fprintf(name_out, "%s\n", name); } void makeDB(HashMap *templates, int kmerindex, char **inputfiles, int fileCount, char *outputfilename, int appender, char *trans, int MinLen, int MinKlen, double homQ, double homT, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths) { int fileCounter, file_len, bias, FASTQ; char *filename; unsigned char *seq; FILE *seq_out, *length_out, *name_out; Qseqs *header, *qseq; FileBuff *inputfile; CompDNA *compressor; /* allocate */ compressor = smalloc(sizeof(CompDNA)); allocComp(compressor, 1024); header = setQseqs(1024); qseq = setQseqs(1024); inputfile = setFileBuff(1024 * 1024); /* open files */ file_len = strlen(outputfilename); strcat(outputfilename, ".length.b"); length_out = sfopen(outputfilename, "wb"); outputfilename[file_len] = 0; if(appender) { strcat(outputfilename, ".name"); name_out = sfopen(outputfilename, "ab"); outputfilename[file_len] = 0; } else { strcat(outputfilename, ".name"); name_out = sfopen(outputfilename, "wb"); outputfilename[file_len] = 0; } if(appender) { strcat(outputfilename, ".seq.b"); seq_out = sfopen(outputfilename, "ab"); outputfilename[file_len] = 0; } else { strcat(outputfilename, ".seq.b"); seq_out = sfopen(outputfilename, "wb"); outputfilename[file_len] = 0; } fprintf(stderr, "# Updating DBs\n"); /* iterate inputfiles */ for(fileCounter = 0; fileCounter < fileCount; ++fileCounter) { /* open file */ filename = inputfiles[fileCounter]; /* determine filetype and open it */ if((FASTQ = openAndDetermine(inputfile, filename)) & 2) { fprintf(stderr, "%s\t%s\n", "# Reading inputfile: ", filename); /* parse the file */ while(FileBuffgetFsa(inputfile, header, qseq, trans)) { if(qseq->len >= compressor->size) { freeComp(compressor); allocComp(compressor, qseq->size); } bias = compDNAref(compressor, qseq->seq, qseq->len); if(compressor->seqlen > MinLen && update_DB(templates, compressor, templates->DB_size, MinKlen, homQ, homT, *template_ulengths, *template_slengths, header)) { /* Update annots */ seq = header->seq + header->len; while(isspace(*--seq)) { *seq = 0; } if(bias > 0) { biasPrintPtr(name_out, "%s B%d\n", header->seq + 1, bias); } else { fprintf(name_out, "%s\n", header->seq + 1); } updateAnnotsPtr(compressor, templates->DB_size, kmerindex, seq_out, template_lengths, template_ulengths, template_slengths); fprintf(stderr, "# Added:\t%s\n", header->seq + 1); if(++(templates->DB_size) == USHRT_MAX) { /* convert values to unsigned */ convertToU(templates); } } else { fprintf(stderr, "# Skipped:\t%s\n", header->seq + 1); } } } else { fprintf(stderr, "Unsupported format for file:\t%s\n", filename); exit(1); } /* close file buffer */ if(FASTQ & 4) { gzcloseFileBuff(inputfile); } else { closeFileBuff(inputfile); } } /* Dump annots */ cfwrite(&templates->DB_size, sizeof(int), 1, length_out); if(*template_ulengths != 0) { **template_ulengths = 0; **template_slengths = 0; cfwrite(*template_lengths, sizeof(unsigned), templates->DB_size, length_out); cfwrite(*template_slengths, sizeof(unsigned), templates->DB_size, length_out); cfwrite(*template_ulengths, sizeof(unsigned), templates->DB_size, length_out); } else { **template_lengths = kmerindex; cfwrite(*template_lengths, sizeof(unsigned), templates->DB_size, length_out); } fclose(seq_out); fclose(length_out); fclose(name_out); if(templates->n) { fprintf(stderr, "# Templates key-value pairs:\t%lu.\n", templates->n);// / 1048576); } else { fprintf(stderr, "DB is empty!!!\n"); exit(1); } /* clean */ freeComp(compressor); free(compressor); destroyQseqs(header); destroyQseqs(qseq); destroyFileBuff(inputfile); } genomicepidemiology-kma-091b8ffe66ac/Makefile0000644000175000017500000001063714157033525020560 0ustar nileshnileshCFLAGS ?= -Wall -O3 CFLAGS += -std=c99 LIBS = align.o alnfrags.o ankers.o assembly.o chain.o compdna.o compkmers.o compress.o db.o decon.o dist.o ef.o filebuff.o frags.o hashmap.o hashmapcci.o hashmapkma.o hashmapkmers.o hashtable.o index.o kma.o kmapipe.o kmeranker.o kmers.o kmmap.o loadupdate.o makeindex.o matrix.o mt1.o nw.o pherror.o printconsensus.o qseqs.o qualcheck.o runinput.o runkma.o sam.o savekmers.o seq2fasta.o seqmenttree.o seqparse.o shm.o sparse.o spltdb.o stdnuc.o stdstat.o tmp.o update.o updateindex.o updatescores.o valueshash.o vcf.o xml.o PROGS = kma kma_index kma_shm kma_update .c .o: $(CC) $(CFLAGS) -c -o $@ $< all: $(PROGS) kma: main.c libkma.a $(CC) $(CFLAGS) -o $@ main.c libkma.a -lm -lpthread -lz $(LDFLAGS) kma_index: kma_index.c libkma.a $(CC) $(CFLAGS) -o $@ kma_index.c libkma.a -lm -lz $(LDFLAGS) kma_shm: kma_shm.c libkma.a $(CC) $(CFLAGS) -o $@ kma_shm.c libkma.a $(LDFLAGS) kma_update: kma_update.c libkma.a $(CC) $(CFLAGS) -o $@ kma_update.c libkma.a $(LDFLAGS) libkma.a: $(LIBS) $(AR) -csr $@ $(LIBS) clean: $(RM) $(LIBS) $(PROGS) libkma.a align.o: align.h chain.h compdna.h hashmapcci.h nw.h stdnuc.h stdstat.h alnfrags.o: alnfrags.h align.h ankers.h compdna.h hashmapcci.h qseqs.h threader.h updatescores.h ankers.o: ankers.h compdna.h pherror.h qseqs.h assembly.o: assembly.h align.h filebuff.h hashmapcci.h kmapipe.h pherror.h stdnuc.h stdstat.h threader.h chain.o: chain.h penalties.h pherror.h stdstat.h compdna.o: compdna.h pherror.h stdnuc.h compkmers.o: compkmers.h pherror.h compress.o: compress.h hashmap.h hashmapkma.h pherror.h valueshash.h db.o: db.h hashmapkma.h pherror.h stdstat.h decon.o: decon.h compdna.h filebuff.h hashmapkma.h seqparse.h stdnuc.h qseqs.h updateindex.h dist.o: dist.h hashmapkma.h matrix.h pherror.h ef.o: ef.h assembly.h stdnuc.h vcf.h version.h filebuff.o: filebuff.h pherror.h qseqs.h frags.o: frags.h filebuff.h pherror.h qseqs.h hashmap.o: hashmap.h hashtable.h pherror.h hashmapcci.o: hashmapcci.h pherror.h stdnuc.h hashmapkma.o: hashmapkma.h pherror.h hashmapkmers.o: hashmapkmers.h pherror.h hashtable.o: hashtable.h hashmapkma.h hashmapkmers.h pherror.h index.o: index.h compress.h decon.h hashmap.h hashmapkma.h loadupdate.h makeindex.h pherror.h stdstat.h version.h kma.o: kma.h ankers.h assembly.h chain.h hashmapkma.h kmers.h mt1.h penalties.h pherror.h qseqs.h runinput.h runkma.h savekmers.h sparse.h spltdb.h tmp.h version.h kmapipe.o: kmapipe.h pherror.h kmeranker.o: kmeranker.h penalties.h kmers.o: kmers.h ankers.h compdna.h hashmapkma.h kmapipe.h pherror.h qseqs.h savekmers.h spltdb.h kmmap.o: kmmap.h hashmapkma.h loadupdate.o: loadupdate.h pherror.h hashmap.h hashmapkma.h updateindex.h makeindex.o: makeindex.h compdna.h filebuff.h hashmap.h pherror.h qseqs.h seqparse.h updateindex.h matrix.o: matrix.h pherror.h mt1.o: mt1.h assembly.h chain.h filebuff.h hashmapcci.h kmapipe.h nw.h penalties.h pherror.h printconsensus.h qseqs.h runkma.h stdstat.h vcf.h nw.o: nw.h pherror.h stdnuc.h penalties.h pherror.o: pherror.h printconsensus.o: printconsensus.h assembly.h qseqs.o: qseqs.h pherror.h qualcheck.o: qualcheck.h compdna.h hashmap.h pherror.h stdnuc.h stdstat.h runinput.o: runinput.h compdna.h filebuff.h pherror.h qseqs.h seqparse.h runkma.o: runkma.h align.h alnfrags.h assembly.h chain.h compdna.h ef.h filebuff.h frags.h hashmapcci.h kmapipe.h nw.h pherror.h printconsensus.h qseqs.h stdnuc.h stdstat.h tmp.h vcf.h sam.o: sam.h nw.h pherror.h qseqs.h runkma.h savekmers.o: savekmers.h ankers.h compdna.h hashmapkma.h kmeranker.h penalties.h pherror.h qseqs.h stdnuc.h stdstat.h threader.h seq2fasta.o: seq2fasta.h pherror.h qseqs.h runkma.h stdnuc.h seqmenttree.o: seqmenttree.h pherror.h seqparse.o: seqparse.h filebuff.h qseqs.h shm.o: shm.h pherror.h hashmapkma.h version.h sparse.o: sparse.h compkmers.h hashtable.h kmapipe.h pherror.h runinput.h savekmers.h stdnuc.h stdstat.h spltdb.o: spltdb.h align.h alnfrags.h assembly.h chain.h compdna.h ef.h filebuff.h frags.h hashmapcci.h kmapipe.h nw.h pherror.h printconsensus.h qseqs.h runkma.h stdnuc.h stdstat.h tmp.h vcf.h stdnuc.o: stdnuc.h stdstat.o: stdstat.h tmp.o: tmp.h pherror.h threader.h update.o: update.h hashmapkma.h pherror.h stdnuc.h updateindex.o: updateindex.h compdna.h hashmap.h hashmapcci.h pherror.h qualcheck.h stdnuc.h pherror.h updatescores.o: updatescores.h qseqs.h valueshash.o: valueshash.h pherror.h vcf.o: vcf.h assembly.h filebuff.h stdnuc.h stdstat.h version.h xml.o: xml.h pherror.h version.h genomicepidemiology-kma-091b8ffe66ac/updatescores.h0000644000175000017500000000237214157033525021767 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "qseqs.h" void update_Scores(unsigned char *qseq, int q_len, int counter, int score, int *start, int *end, int *template, Qseqs *header, int flag, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, FILE *frag_out_raw); void update_Scores_pe(unsigned char *qseq, int q_len, unsigned char *qseq_r, int qr_len, int counter, int score, int *start, int *end, int *template, Qseqs *header, Qseqs *header_r, int flag, int flag_r, long unsigned *alignment_scores, long unsigned *uniq_alignment_scores, FILE *frag_out_raw); genomicepidemiology-kma-091b8ffe66ac/index.h0000644000175000017500000000135614157033525020376 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ int index_main(int argc, char *argv[]); genomicepidemiology-kma-091b8ffe66ac/printconsensus.h0000644000175000017500000000157114157033525022363 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "assembly.h" void printConsensus(Assem *aligned_assem, char *header, FILE *alignment_out, FILE *consensus_out, int ref_fsa); genomicepidemiology-kma-091b8ffe66ac/makeindex.h0000644000175000017500000000230314157033525021225 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hashmap.h" extern int (*biasPrintPtr)(FILE*, char*, unsigned char*, int); int biasPrint(FILE *name_out, char *format, unsigned char *name, int bias); int biasNoPrint(FILE *name_out, char *format, unsigned char *name, int bias); void makeDB(HashMap *templates, int kmerindex, char **inputfiles, int fileCount, char *outputfilename, int appender, char *trans, int MinLen, int MinKlen, double homQ, double homT, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths); genomicepidemiology-kma-091b8ffe66ac/mt1.c0000644000175000017500000003337214157033525017766 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include "assembly.h" #include "chain.h" #include "compdna.h" #include "filebuff.h" #include "hashmapcci.h" #include "kmapipe.h" #include "mt1.h" #include "nw.h" #include "penalties.h" #include "pherror.h" #include "printconsensus.h" #include "qseqs.h" #include "runkma.h" #include "stdnuc.h" #include "stdstat.h" #include "vcf.h" #include "xml.h" void printFsaMt1(Qseqs *header, Qseqs *qseq, CompDNA *compressor, FILE *out) { static int buff[8] = {0, 0, 1, 0, 0, 0, 0, 0}; if(header) { buff[1] = qseq->len; buff[6] = header->len; sfwrite(buff, sizeof(int), 8, out); sfwrite(qseq->seq, 1, qseq->len, out); sfwrite(header->seq + 1, 1, header->len, out); } else { buff[5] = qseq->len; } } void printFsa_pairMt1(Qseqs *header, Qseqs *qseq, Qseqs *header_r, Qseqs *qseq_r, CompDNA *compressor, FILE *out) { static int buff[8] = {0, 0, 1, 0, 0, 0, 0, 0}; if(header) { buff[1] = qseq->len; buff[6] = header->len; buff[7] = 97; sfwrite(buff, sizeof(int), 8, out); sfwrite(qseq->seq, 1, qseq->len, out); sfwrite(header->seq + 1, 1, header->len, out); buff[1] = qseq_r->len; buff[6] = header_r->len; buff[7] = 145; strrc(qseq_r->seq, qseq_r->len); sfwrite(buff, sizeof(int), 8, out); sfwrite(qseq_r->seq, 1, qseq_r->len, out); sfwrite(header_r->seq + 1, 1, header_r->len, out); } else { buff[5] = qseq->len; } } void runKMA_Mt1(char *templatefilename, char *outputfilename, char *exePrev, int kmersize, int minlen, Penalties *rewards, double ID_t, int mq, double scoreT, double mrc, double evalue, double support, int bcd, int Mt1, int ref_fsa, int print_matrix, int vcf, int xml, int sam, int nc, int nf, int thread_num) { int i, j, aln_len, t_len, coverScore, file_len, DB_size, delta, seq_in; int *template_lengths; long unsigned read_score, seeker; double p_value, id, q_id, cover, q_cover; long double depth; FILE *res_out, *alignment_out, *consensus_out, *template_fragments; FILE *DB_file, *xml_out; time_t t0, t1; FileBuff *frag_out, *matrix_out, *vcf_out; Aln *aligned, *gap_align; Assem *aligned_assem; Qseqs *qseq, *header, *template_name; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; Assemble_thread *threads, *thread; HashMapCCI *template_index; /* open pipe */ //template_fragments = popen(exePrev, "r"); template_fragments = kmaPipe("-s1", "rb", 0, 0); if(!template_fragments) { ERROR(); } else { setvbuf(template_fragments, NULL, _IOFBF, CHUNK); } file_len = strlen(outputfilename); delta = 1024; header = setQseqs(256); qseq = setQseqs(delta); points = seedPoint_init(delta, rewards); /* open outputfiles */ if(outputfilename) { strcat(outputfilename, ".res"); res_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; if(nf == 0) { strcat(outputfilename, ".frag.gz"); frag_out = gzInitFileBuff(CHUNK); openFileBuff(frag_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { frag_out = 0; } if(nc == 0) { strcat(outputfilename, ".aln"); alignment_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else if(nc == 2) { alignment_out = 0; strcat(outputfilename, ".fsa"); consensus_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } else { alignment_out = 0; consensus_out = 0; } if(print_matrix) { matrix_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".mat.gz"); openFileBuff(matrix_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { matrix_out = 0; } if(vcf) { vcf_out = gzInitFileBuff(CHUNK); strcat(outputfilename, ".vcf.gz"); openFileBuff(vcf_out, outputfilename, "wb"); outputfilename[file_len] = 0; } else { vcf_out = 0; } if(xml) { if(xml == 2) { xml_out = openInitXML("--", templatefilename, 1, 1, &exePrev); } else { strcat(outputfilename, ".xml"); xml_out = openInitXML(outputfilename, templatefilename, 1, 1, &exePrev); outputfilename[file_len] = 0; } } else { xml_out = 0; } } else { fprintf(stderr, " No output file specified!\n"); exit(1); } /* load indexing */ file_len = strlen(templatefilename); strcat(templatefilename, ".length.b"); DB_file = sfopen(templatefilename, "rb"); sfread(&DB_size, sizeof(int), 1, DB_file); /* load lengths */ template_lengths = smalloc(DB_size * sizeof(int)); sfread(template_lengths, sizeof(int), DB_size, DB_file); /*fseek(DB_file, (2 * DB_size) * sizeof(int), SEEK_CUR); if(fread(template_lengths, sizeof(int), DB_size, DB_file) == 0) { fseek(DB_file, sizeof(int), SEEK_SET); sfread(template_lengths, sizeof(int), DB_size, DB_file); }*/ templatefilename[file_len] = 0; fclose(DB_file); if(kmersize < 4) { kmersize = *template_lengths; if(32 < kmersize || kmersize < 4) { kmersize = 16; } } /* get seq / index */ seeker = 0; for(i = 2; i <= Mt1; ++i) { seeker += ((template_lengths[i - 1] >> 5) + 1) * sizeof(long unsigned); } /* make index */ *template_lengths = template_lengths[Mt1]; template_lengths = realloc(template_lengths, sizeof(int)); if(!template_lengths) { ERROR(); } strcat(templatefilename, ".seq.b"); seq_in = open(templatefilename, O_RDONLY); if(seq_in == -1) { ERROR(); } templatefilename[file_len] = 0; template_index = alignLoad_fly(0, seq_in, *template_lengths, kmersize, seeker); close(seq_in); /* get name */ strcat(templatefilename, ".name"); DB_file = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; template_name = setQseqs(256); i = 1; while(i != Mt1 && (j = fgetc(DB_file)) && j != EOF) { if(j == '\n') { ++i; } } nameLoad(template_name, DB_file); fclose(DB_file); if(sam) { fprintf(stdout, "@SQ\tSN:%s\tLN:%d\n", template_name->seq, *template_lengths); } fprintf(stderr, "#\n# Doing local assemblies of found templates, and output results\n"); t0 = clock(); /* print heading of resistance file: */ fprintf(res_out, "#Template\tScore\tExpected\tTemplate_length\tTemplate_Identity\tTemplate_Coverage\tQuery_Identity\tQuery_Coverage\tDepth\tq_value\tp_value\n"); if(vcf) { initialiseVcf(vcf_out, templatefilename); } /* preallocate assembly matrices */ matrix = smalloc(sizeof(AssemInfo)); aligned_assem = smalloc(sizeof(Assem)); if(alnToMatPtr == &alnToMat) { matrix->size = (*template_lengths) << 1; } else { matrix->size = (*template_lengths) + 1; } matrix->assmb = smalloc(matrix->size * sizeof(Assembly)); aligned_assem->size = matrix->size; aligned_assem->t = smalloc(aligned_assem->size); aligned_assem->s = smalloc(aligned_assem->size); aligned_assem->q = smalloc(aligned_assem->size); /* allocate matrcies for NW */ i = 1; threads = 0; while(i < thread_num) { /* allocate matrices */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); /* move it to the thread */ thread = smalloc(sizeof(Assemble_thread)); thread->num = i; thread->thread_num = thread_num; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = 0; thread->seq_in = 0; thread->kmersize = kmersize; thread->template = -2; thread->file_count = 1; thread->files = &template_fragments; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->aligned_assem = aligned_assem; thread->aligned = aligned; thread->gap_align = gap_align; thread->NWmatrices = NWmatrices; thread->matrix = matrix; thread->qseq = setQseqs(qseq->size); thread->header = setQseqs(header->size); thread->points = seedPoint_init(delta, rewards); thread->points->len = 0; thread->spin = 10; thread->next = threads; threads = thread; /* start thread */ if((errno = pthread_create(&thread->id, NULL, assembly_KMA_Ptr, thread))) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); fprintf(stderr, "Will continue with %d threads.\n", i); threads = thread->next; free(thread); i = thread_num; } else { ++i; } } /* start main thread */ NWmatrices = smalloc(sizeof(NWmat)); NWmatrices->NW_s = 1024 * 1024; NWmatrices->NW_q = 1024; NWmatrices->E = smalloc(NWmatrices->NW_s); NWmatrices->D[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->P[0] = smalloc((NWmatrices->NW_q << 1) * sizeof(int)); NWmatrices->D[1] = NWmatrices->D[0] + NWmatrices->NW_q; NWmatrices->P[1] = NWmatrices->P[0] + NWmatrices->NW_q; NWmatrices->rewards = rewards; aligned = smalloc(sizeof(Aln)); gap_align = smalloc(sizeof(Aln)); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); /* move it to the thread */ thread = smalloc(sizeof(Assemble_thread)); thread->num = 0; thread->thread_num = thread_num; thread->mq = mq; thread->minlen = minlen; thread->scoreT = scoreT; thread->mrc = mrc; thread->evalue = evalue; thread->bcd = bcd; thread->sam = sam; thread->ef = 0; thread->seq_in = 0; thread->kmersize = kmersize; thread->template = 0; thread->file_count = 1; thread->files = &template_fragments; thread->frag_out = frag_out; thread->xml_out = xml_out; thread->aligned_assem = aligned_assem; thread->aligned = aligned; thread->gap_align = gap_align; thread->NWmatrices = NWmatrices; thread->matrix = matrix; thread->qseq = qseq; thread->header = header; thread->points = points; thread->points->len = 0; thread->next = 0; thread->spin = 10; /* Do local assemblies of fragments mapping to the same template */ depth = 0; q_id = 0; cover = 0; q_cover = 0; /* Do assembly */ //assemblyPtr(aligned_assem, 0, &template_fragments, 1, frag_out, aligned, gap_align, qseq, header, matrix, points, NWmatrices); thread->template_name = (char *) template_name->seq; thread->template_index = template_index; if(xml) { newIterXML(xml_out, Mt1, *template_lengths, thread->template_name); } thread->t_len = *template_lengths; assembly_KMA_Ptr(thread); /* make p_value */ read_score = aligned_assem->score; t_len = *template_lengths; p_value = p_chisqr(read_score); aln_len = 0; if(cmp((p_value <= evalue && read_score > 0), read_score >= scoreT * t_len)) { /* Depth, ID and coverage */ if(aligned_assem->cover > 0) { coverScore = aligned_assem->cover; depth = aligned_assem->depth; depth /= t_len; id = 100.0 * coverScore / t_len; aln_len = aligned_assem->aln_len; q_id = 100.0 * coverScore / aln_len; cover = 100.0 * aln_len / t_len; q_cover = 100.0 * t_len / aln_len; } else { id = 0; } if(ID_t <= id && 0 < id) { /* Output result */ fprintf(res_out, "%-12s\t%8lu\t%8d\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, 0, t_len, id, cover, q_id, q_cover, (double) depth, (double) read_score, p_value); if(nc != 1) { printConsensus(aligned_assem, thread->template_name, alignment_out, consensus_out, ref_fsa); } /* print matrix */ if(matrix_out) { updateMatrix(matrix_out, thread->template_name, template_index->seq, matrix, t_len); } if(vcf) { updateVcf(thread->template_name, aligned_assem->t, evalue, support, bcd, t_len, matrix, vcf, vcf_out); } } /* destroy this DB index */ hashMapCCI_destroy(template_index); } else if(ID_t == 0.0) { fprintf(res_out, "%-12s\t%8ld\t%8u\t%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", thread->template_name, read_score, 0, t_len, 0.0, 0.0, 0.0, 0.0, (double) depth, (double) read_score, p_value); } if(xml) { capIterXML(xml_out, 1, t_len, t_len, read_score, p_value, read_score, aligned_assem->q, aln_len); closeCapXML(xml_out); } /* join threads */ thread->template = -1; assembly_KMA_Ptr(thread); for(thread = threads; thread != 0; thread = thread->next) { /* join thread */ if((errno = pthread_join(thread->id, NULL))) { ERROR(); } } /* Close files */ fclose(res_out); if(alignment_out) { fclose(alignment_out); fclose(consensus_out); } if(frag_out) { destroyGzFileBuff(frag_out); } if(matrix_out) { destroyGzFileBuff(matrix_out); } if(vcf) { destroyGzFileBuff(vcf_out); } t1 = clock(); fprintf(stderr, "# Total time used for local assembly: %.2f s.\n#\n", difftime(t1, t0) / 1000000); } genomicepidemiology-kma-091b8ffe66ac/hashmap.h0000644000175000017500000000420614157033525020705 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "hashtable.h" #ifndef STRUCTHASHMAP typedef struct hashMap HashMap; struct hashMap { /* open hash structure */ long unsigned size; // size of DB long unsigned n; // k-mers stored long unsigned mask; unsigned kmersize; // k unsigned prefix_len; // prefix length long unsigned prefix; // prefix HashTable **table; // org unsigned **values; // ME int DB_size; }; #define STRUCTHASHMAP 1 #endif extern int (*hashMap_add)(HashMap *, long unsigned, unsigned); extern unsigned * (*hashMapGet)(HashMap *, long unsigned); extern void (*addUniqueValues)(HashMap *, long unsigned, unsigned *); extern unsigned * (*updateValuePtr)(unsigned *, unsigned); HashMap * hashMap_initialize(long unsigned size, unsigned kmersize); int megaMap_addKMA(HashMap *templates, long unsigned key, unsigned value); unsigned * megaMap_getValue(HashMap *templates, long unsigned key); void hashMap2megaMap(HashMap *templates, HashTable *table); unsigned * updateValue(unsigned *values, unsigned value); unsigned * updateShortValue(unsigned *valuesOrg, unsigned value); int hashMap_addKMA(HashMap *templates, long unsigned key, unsigned value); unsigned * hashMapGetValue(HashMap *templates, long unsigned key); void hashMap_addUniqueValues(HashMap *dest, long unsigned key, unsigned *values); void megaMap_addUniqueValues(HashMap *dest, long unsigned key, unsigned *values); unsigned * HU2U(unsigned *values); void convertToU(HashMap *templates); genomicepidemiology-kma-091b8ffe66ac/sam.h0000644000175000017500000000200614157033525020040 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "nw.h" #include "qseqs.h" char * makeCigar(Qseqs *Cigar, const Aln *aligned); void saminit(Qseqs *template_name, FILE *name_file, int *template_lengths, int DB_size); int samwrite(const Qseqs *qseq, const Qseqs *header, const Qseqs *Qual, char *rname, const Aln *aligned, const int *stats); genomicepidemiology-kma-091b8ffe66ac/pherror.c0000644000175000017500000000346414157033525020745 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include "pherror.h" void * smalloc(const size_t size) { void *dest = malloc(size); if(!dest) { ERROR(); } return dest; } FILE * sfopen(const char *filename, const char *mode) { FILE *file = fopen(filename, mode); if(!file) { fprintf(stderr, "Filename:\t%s\n", filename); ERROR(); } return file; } void cfread(void *src, size_t size, size_t nmemb, FILE *stream) { unsigned char *ptr = src; nmemb = fread(ptr, 1, (size *= nmemb), stream); if((size -= nmemb)) { ptr += nmemb; while(size) { if(0 < (nmemb = read(fileno(stream), ptr, size))) { size -= nmemb; ptr += nmemb; } else if(nmemb == 0 || (nmemb == -1 && (errno & EAGAIN))) { usleep(1000); } else { ERROR(); } } } } void cfwrite(const void *src, size_t size, size_t nmemb, FILE *stream) { unsigned char *ptr; size *= nmemb; ptr = (unsigned char *)(src); while(size) { nmemb = fwrite(ptr, 1, size, stream); if(nmemb == 0) { ERROR(); } size -= nmemb; ptr += nmemb; } } genomicepidemiology-kma-091b8ffe66ac/sparse.h0000644000175000017500000000301514157033525020556 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "compkmers.h" #include "hashmapkma.h" #include "hashtable.h" int translateToKmersAndDump(long unsigned *Kmers, int n, int max, unsigned char *qseq, int seqlen, int kmersize, long unsigned mask, long unsigned prefix, int prefix_len, FILE *out); char ** load_DBs_Sparse(char *templatefilename, unsigned **template_lengths, unsigned **template_ulengths, unsigned shm); void save_kmers_sparse(const HashMapKMA *templates, HashMap_kmers *foundKmers, CompKmers *compressor); void run_input_sparse(const HashMapKMA *templates, char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int kmersize, char *trans, const double *prob, FILE *out); int save_kmers_sparse_batch(char *templatefilename, char *outputfilename, char *exePrev, int ID_t, double evalue, char ss, unsigned shm); genomicepidemiology-kma-091b8ffe66ac/savekmers.h0000644000175000017500000002003314157033525021260 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "compdna.h" #include "hashmapkma.h" #include "penalties.h" #include "qseqs.h" #ifndef SAVEKMERS typedef struct kmerScan_thread KmerScan_thread; struct kmerScan_thread { pthread_t id; int num; int exhaustive; int sam; int bestScore; int bestScore_r; int *bestTemplates; int *bestTemplates_r; FILE *inputfile; FILE *out; HashMapKMA *templates; Penalties *rewards; struct kmerScan_thread *next; }; #define SAVEKMERS 1; #endif /* pointers to combine functions */ extern void (*ankerPtr)(int*, int*, int*, char*, int*, unsigned**, unsigned**, int*, CompDNA*, int, int, int, int, Qseqs*, volatile int*, FILE*); extern int (*kmerScan)(const HashMapKMA *, const Penalties *, int*, int*, int*, int*, CompDNA*, CompDNA*, const Qseqs*, int*, const int, volatile int*, FILE*); extern int (*save_kmers_pair)(const HashMapKMA *, const Penalties *, int*, int*, int*, int*, int*, int*, CompDNA*, CompDNA*, const Qseqs*, const Qseqs*, int*, const int, volatile int*, FILE*); extern int (*get_kmers_for_pair_ptr)(const HashMapKMA *, const Penalties *, int *, int *, int *, int *, CompDNA *, int *, int); extern int (*getMatch)(int*, int*); extern int (*getMatchSparse)(int*, int*, int, int, int, int); extern int (*getSecondForce)(int*, int*, int*, int*, int*, int*); extern int (*getSecondPen)(int*, int*, int*, int*, int*, int*, int, int); extern int (*getF)(int*, int*, int*, int*, int*); extern int (*getR)(int*, int*, int*, int*, int*); int loadFsa(CompDNA *qseq, Qseqs *header, FILE *inputfile); void * save_kmers_threaded(void *arg); int getBestMatch(int *bestTemplates, int *Score); int getProxiMatch(int *bestTemplates, int *Score); int getBestMatchSparse(int *bestTemplates, int *Score, int kmersize, int n_kmers, int M, int MM); int getProxiMatchSparse(int *bestTemplates, int *Score, int kmersize, int n_kmers, int M, int MM); int get_kmers_for_pair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive); int get_kmers_for_pair_count(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive); int get_kmers_for_pair_Sparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive); int get_kmers_for_pair_pseoudoSparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive); void getFirstForce(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores); int getSecondBestForce(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores); int getSecondProxiForce(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores); int getFirstPen(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores); int getSecondBestPen(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, int bestScore, int PE); int getSecondProxiPen(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, int bestScore, int PE); int getF_Best(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates); int getR_Best(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates); int getF_Proxi(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates); int getR_Proxi(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates); int save_kmers_Sparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers_pseuodeSparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers_count(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers_unionPair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, const Qseqs *header_r, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers_penaltyPair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, const Qseqs *header_r, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers_forcePair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, const Qseqs *header_r, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers_HMM(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); void ankerAndClean(int *regionTemplates, int *Score, int *Score_r, char *include, int *template_lengths, unsigned **VF_scores, unsigned **VR_scores, int *tmpNs, CompDNA *qseq, int HIT, int bestScore, int start_cut, int end_cut, Qseqs *header, volatile int *excludeOut, FILE *out); void ankerAndClean_MEM(int *regionTemplates, int *Score, int *Score_r, char *include, int *template_lengths, unsigned **VF_scores, unsigned **VR_scores, int *tmpNs, CompDNA *qseq, int HIT, int bestScore, int start_cut, int end_cut, Qseqs *header, volatile int *excludeOut, FILE *out); int save_kmers_chain(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); int save_kmers_sparse_chain(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out); genomicepidemiology-kma-091b8ffe66ac/dist.c0000644000175000017500000006040714157033525020227 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2020 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include "dist.h" #include "hashmapkma.h" #include "matrix.h" #include "pherror.h" #include "runkma.h" #include "threader.h" #include "tmp.h" #define missArg(opt) fprintf(stderr, "Missing argument at %s.\n", opt); exit(1); #define invaArg(opt) fprintf(stderr, "Invalid value parsed at %s.\n", opt); exit(1); HashMapKMA * loadValues(const char *filename) { long unsigned check, size; FILE *file; HashMapKMA *dest; /* init */ file = sfopen(filename, "rb"); dest = smalloc(sizeof(HashMapKMA)); /* load sizes */ sfread(&dest->DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); sfread(&dest->n, sizeof(long unsigned), 1, file); sfread(&dest->v_index, sizeof(long unsigned), 1, file); sfread(&dest->null_index, sizeof(long unsigned), 1, file); dest->mask = 0; dest->mask = (~dest->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (dest->kmersize << 1)); dest->shmFlag = 0; /* simple check for old indexing */ if(dest->size < dest->n) { free(dest); fclose(file); return 0; } /* exist */ size = dest->size; if((dest->size - 1) == dest->mask) { /* mega */ if(dest->v_index <= UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } /* load */ dest->exist = smalloc(size); check = fread(dest->exist, 1, size, file); if(check != size) { free(dest); free(dest->exist); fclose(file); return 0; } dest->exist_l = (long unsigned *)(dest->exist); dest->shmFlag |= 1; } else { if(dest->n <= UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } /* skip */ dest->exist = 0; dest->exist_l = 0; fseek(file, size, SEEK_CUR); } /* values */ size = dest->v_index; if(dest->DB_size < USHRT_MAX) { size *= sizeof(short unsigned); } else { size *= sizeof(unsigned); } dest->values = smalloc(size); check = fread(dest->values, 1, size, file); if(check != size) { free(dest); free(dest->exist); free(dest->values); fclose(file); return 0; } dest->values_s = (short unsigned *)(dest->values); /* check for megaMap */ if(dest->exist) { fclose(file); return dest; } /* skip kmers */ size = dest->n + 1; if(dest->kmersize <= 16) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } dest->key_index = 0; dest->key_index_l = 0; fseek(file, size, SEEK_CUR); /* value indexes */ size = dest->n; if(dest->v_index < UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } dest->exist = smalloc(size); check = fread(dest->exist, 1, size, file); if(check != size) { free(dest); free(dest->exist); free(dest->values); fclose(file); return 0; } dest->exist_l = (long unsigned *)(dest->exist); fclose(file); return dest; } void destroyValues(HashMapKMA *src) { free(src->exist); free(src->values); free(src); } void kmerSimilarity(HashMapKMA *DB, Matrix *Dist, int *N) { int i, j, el, vs, v_i, **D, *Di; unsigned *exist, *values_i, *values_j; long unsigned n, pos, *exist_l; short unsigned *values_si, *values_sj; /* init */ el = DB->v_index < UINT_MAX; vs = DB->DB_size < USHRT_MAX; exist = DB->exist - 1; exist_l = DB->exist_l - 1; D = Dist->mat; /* get values */ n = DB->n; while(n) { pos = el ? *++exist : *++exist_l; if(pos != 1) { if(vs) { values_si = DB->values_s + pos; i = *values_si + 1; values_si += i; while(--i) { j = i; values_sj = --values_si; v_i = *values_si - 1; Di = D[v_i]; while(--j) { ++Di[*--values_sj - 1]; } ++N[v_i]; } } else { values_i = DB->values + pos; i = *values_i + 1; values_i += i; while(--i) { j = i; values_j = --values_i; v_i = *values_i - 1; Di = D[v_i]; while(--j) { ++Di[*--values_j - 1]; } ++N[v_i]; } } --n; } } Dist->n = DB->DB_size - 1; destroyValues(DB); } void kmerSimilarity_thread(HashMapKMA *DB, Matrix *Dist, int *N, int thread_num, volatile int *lock) { static volatile int thread_wait = 0; static volatile long unsigned next; static long unsigned n; int i, j, el, vs, v_i, chunk, chunkster, **D, *Di, *Dptr; unsigned *exist, *values_i, *values_j; long unsigned pos, size, *exist_l; short unsigned *values_si, *values_sj; /* init */ el = DB->v_index < UINT_MAX; vs = DB->DB_size < USHRT_MAX; D = Dist->mat; chunk = 131072; size = ((DB->size - 1) == DB->mask) ? DB->size : DB->n; /* static init */ lockTime(lock, 10); if(!thread_wait) { thread_wait = thread_num; next = 0; n = DB->n; Dist->n = DB->DB_size - 1; } unlock(lock); /* get values */ while(n && chunk) { /* get next chunk */ lockTime(lock, 10); pos = next; if(size < (next += chunk)) { next = size; } unlock(lock); /* update chunk */ exist = DB->exist + pos - 1; exist_l = DB->exist_l + pos - 1; if(size < pos + chunk) { chunkster = size - pos + 1; chunk = 0; } else { chunkster = (chunk + 1); } while(n && --chunkster) { pos = el ? *++exist : *++exist_l; if(pos != 1) { if(vs) { values_si = DB->values_s + pos; i = *values_si + 1; values_si += i; while(--i) { j = i; values_sj = --values_si; v_i = *values_si - 1; Di = D[v_i]; while(--j) { Dptr = Di + (*--values_sj - 1); __sync_add_and_fetch(Dptr, 1); } Dptr = N + v_i; __sync_add_and_fetch(Dptr, 1); } } else { values_i = DB->values + pos; i = *values_i + 1; values_i += i; while(--i) { j = i; values_j = --values_i; v_i = *values_i - 1; Di = D[v_i]; while(--j) { Dptr = Di + (*--values_j - 1); __sync_add_and_fetch(Dptr, 1); } Dptr = N + v_i; __sync_add_and_fetch(Dptr, 1); } } __sync_sub_and_fetch(&n, 1); } } } if(__sync_sub_and_fetch(&thread_wait, 1)) { wait_atomic(thread_wait); } else { destroyValues(DB); } } int kmerDist(int Ni, int Nj, int D) { return Ni + Nj - (D << 1); } int kmerShared(int Ni, int Nj, int D) { return D; } int chi2dist(int Ni, int Nj, int D) { D = (Ni + Nj - (D << 1)); return D * D / (Ni + Nj); } void printIntLtdPhy(char *outfile, Matrix *Dist, int *N, FILE *name_file, Qseqs *template_name, unsigned format, int thread_num, volatile int *lock, const char *method, int (*distPtr)(int, int, int)) { static volatile int thread_wait1 = 0, thread_wait2 = 0; static int next_i, next_j, entrance = 0; static long unsigned row_bias = 0; volatile int *thread_wait; int i, j, j_end, chunk, N_i, *Nj, **D, *Di; char *outfile_chunk, *name; /* init */ D = Dist->mat; chunk = 65536; lockTime(lock, 10); if(!row_bias) { if(format & 4) { row_bias += sprintf(outfile, "# %-35s\n", method); } row_bias += sprintf(outfile + row_bias, "%10d", Dist->n); next_i = -1; next_j = 0; if(++entrance & 1) { thread_wait1 = thread_num; thread_wait = &thread_wait1; } else { thread_wait2 = thread_num; thread_wait = &thread_wait2; } } else if(entrance & 1) { thread_wait = &thread_wait1; } else { thread_wait = &thread_wait2; } unlock(lock); while(next_i < Dist->n) { lockTime(lock, 10); /* check for new row */ if(Dist->n <= next_i) { chunk = 0; } else if(next_i <= next_j) { i = ++next_i; if(i) { row_bias += (i - 1) * 11; } j = 0; next_j = chunk; if(next_i < Dist->n) { name = nameLoad(template_name, name_file); if(format & 1) { row_bias += sprintf(outfile + row_bias, "\n%s", name); } else { row_bias += sprintf(outfile + row_bias, "\n%-10.10s", name); } } else { outfile[row_bias] = '\n'; ++row_bias; chunk = 0; } } else { i = next_i; j = next_j; next_j += chunk; } outfile_chunk = outfile + row_bias + j * 11; unlock(lock); if(chunk) { N_i = N[i]; j_end = (i < j + chunk) ? i : (j + chunk); Di = D[i] + --j; Nj = N + j; while(++j < j_end) { outfile_chunk += sprintf(outfile_chunk, "\t%10d", distPtr(N_i, *++Nj, *++Di)); } /* fix null character */ *outfile_chunk = (j == i) ? '\n' : '\t'; } } /* wait for matrix to finish */ lockTime(lock, 10); if(--*thread_wait) { unlock(lock); wait_atomic(*thread_wait); } else { fseek(name_file, 0, SEEK_SET); row_bias = 0; unlock(lock); } } double kmerQuery(int Ni, int Nj, int D) { return 100.0 * D / Ni; } double kmerTemplate(int Ni, int Nj, int D) { return 100.0 * D / Nj; } double kmerAvg(int Ni, int Nj, int D) { return 200.0 * D / (Ni + Nj); } double kmerInvAvg(int Ni, int Nj, int D) { return 100.0 - 200.0 * D / (Ni + Nj); } double kmerJaccardDist(int Ni, int Nj, int D) { return 1.0 - (double)(D) / (Ni + Nj - D); } double kmerJaccardSim(int Ni, int Nj, int D) { return (double)(D) / (Ni + Nj - D); } double kmerCosineDist(int Ni, int Nj, int D) { return 1.0 - (double)(D) / (Ni + Nj); } double kmerCosineSim(int Ni, int Nj, int D) { return (double)(D) / (Ni + Nj); } double kmerOverlapCoef(int Ni, int Nj, int D) { return (double)(D) / (Ni < Nj ? Ni : Nj); } double kmerInvOverlapCoef(int Ni, int Nj, int D) { return 1.0 - (double)(D) / (Ni < Nj ? Ni : Nj); } void printDoublePhy(char *outfile, Matrix *Dist, int *N, FILE *name_file, Qseqs *template_name, unsigned format, const char *formatString, int ltd, int thread_num, volatile int *lock, const char *method, double (*distPtr)(int, int, int)) { static volatile int thread_wait1 = 0, thread_wait2 = 0; static int next_i, next_j, entrance = 0; static long unsigned row_bias = 0; volatile int *thread_wait; int i, j, j_end, chunk, N_i, *Nj, **D, *Di; char endChar, *outfile_chunk, *name; /* init */ D = Dist->mat; chunk = 65536; lockTime(lock, 10); if(!row_bias) { if(format & 4) { row_bias += sprintf(outfile, "# %-35s\n", method); } row_bias += sprintf(outfile + row_bias, "%10d", Dist->n); next_i = -1; next_j = Dist->n; if(++entrance & 1) { thread_wait1 = thread_num; thread_wait = &thread_wait1; } else { thread_wait2 = thread_num; thread_wait = &thread_wait2; } } else if(entrance & 1) { thread_wait = &thread_wait1; } else { thread_wait = &thread_wait2; } unlock(lock); while(next_i < Dist->n) { lockTime(lock, 10); /* check for new row */ if(Dist->n <= next_i) { chunk = 0; } else if((ltd && next_i <= next_j) || (Dist->n <= next_j)) { i = ++next_i; if(i) { row_bias += (ltd ? (i - 1) : Dist->n) * 11; } j = 0; next_j = chunk; if(next_i < Dist->n) { name = nameLoad(template_name, name_file); if(format & 1) { row_bias += sprintf(outfile + row_bias, "\n%s", name); } else { row_bias += sprintf(outfile + row_bias, "\n%-10.10s", name); } } else { outfile[row_bias] = '\n'; ++row_bias; chunk = 0; } } else { i = next_i; j = next_j; next_j += chunk; } outfile_chunk = outfile + row_bias + j * 11; unlock(lock); if(chunk) { if(ltd) { j_end = (i < j + chunk) ? i : (j + chunk); endChar = (j_end == i) ? '\n' : '\t'; } else { j_end = (Dist->n < j + chunk) ? Dist->n : (j + chunk); endChar = (j_end == Dist->n) ? '\n' : '\t'; } N_i = N[i]; Di = D[i] + --j; Nj = N + j; if(j_end < i) { while(++j < j_end) { outfile_chunk += sprintf(outfile_chunk, formatString, distPtr(N_i, *++Nj, *++Di)); } } else if(i < j) { while(++j < j_end) { outfile_chunk += sprintf(outfile_chunk, formatString, distPtr(N_i, *++Nj, D[j][i])); } } else { while(++j < j_end) { if(j < i) { outfile_chunk += sprintf(outfile_chunk, formatString, distPtr(N_i, *++Nj, *++Di)); } else if(i < j) { outfile_chunk += sprintf(outfile_chunk, formatString, distPtr(N_i, *++Nj, D[j][i])); } else { outfile_chunk += sprintf(outfile_chunk, formatString, 100.0); ++Nj; } } } /* fix null character */ *outfile_chunk = endChar; } } /* wait for matrix to finish */ lockTime(lock, 10); if(--*thread_wait) { unlock(lock); wait_atomic(*thread_wait); } else { fseek(name_file, 0, SEEK_SET); row_bias = 0; unlock(lock); } } long unsigned getPhySize(int flag, int format, long unsigned n, long unsigned *ltdMat, long unsigned *covMat, FILE *name_file) { long unsigned size; /* get name name */ if(format & 1) { fseek(name_file, 0, SEEK_END); size = ftell(name_file); rewind(name_file); } else { size = n * 11; } if(format & 4) { size += 38; } /* phy size */ size += 11; /* ltd cell size */ *ltdMat = size + (((n - 1) * (n - 2)) >> 1) * 11; /* cov cell size */ *covMat = size + (n - 1) * (n - 1) * 11; /* get number of matrices to make */ size = 0; if(flag & 4) { size += *covMat; flag ^= 4; } if(flag & 8) { size += *covMat; flag ^= 8; } n = 0; while(flag) { n += flag & 1; flag >>= 1; } return size + n * *ltdMat; } char * mfile(FILE *outfile, long unsigned size) { char *outfileM; if(fseek(outfile, size - 1, SEEK_SET) || putc(0, outfile) == EOF) { ERROR(); } rewind(outfile); outfileM = mmap(0, size, PROT_WRITE, MAP_SHARED, fileno(outfile), 0); if(outfileM == MAP_FAILED) { ERROR(); } posix_madvise(outfileM, size, POSIX_MADV_SEQUENTIAL); return outfileM; } void * threadDist(void *arg) { static volatile int Lock = 0; volatile int *lock = &Lock; DistThread *thread = arg; int flag, format, thread_num, *N; long unsigned ltdMat, covMat; char *outfileM; FILE *name_file; HashMapKMA *DB; Matrix *Dist; Qseqs *template_name; /* init */ flag = thread->flag; format = thread->format; thread_num = thread->thread_num; N = thread->N; ltdMat = thread->ltdMat; covMat = thread->covMat; outfileM = thread->outfileM; name_file = thread->name_file; DB = thread->DB; Dist = thread->Dist; template_name = thread->template_name; /* get kmer similarities and lengths */ if(thread_num != 1) { kmerSimilarity_thread(DB, Dist, N, thread_num, lock); } else { kmerSimilarity(DB, Dist, N); } /* k-mer dist, lt */ if(flag & 1) { printIntLtdPhy(outfileM, Dist, N, name_file, template_name, format, thread_num, lock, "k-mer distance", &kmerDist); outfileM += ltdMat; } /* k-mer shared, lt */ if(flag & 2) { printIntLtdPhy(outfileM, Dist, N, name_file, template_name, format, thread_num, lock, "shared k-mers", &kmerShared); outfileM += ltdMat; } /* query cov, asym */ if(flag & 4) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%10.6f", 0, thread_num, lock, "Query k-mer coverage [%]", &kmerQuery); outfileM += covMat; } /* template cov, asym */ if(flag & 8) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%10.6f", 0, thread_num, lock, "Template k-mer coverage [%]", &kmerTemplate); outfileM += covMat; } /* avg. cov, lt */ if(flag & 16) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%10.6f", 1, thread_num, lock, "Avg. k-mer coverage [%]", &kmerAvg); outfileM += ltdMat; } /* inv. avg. cov, lt */ if(flag & 32) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%10.6f", 1, thread_num, lock, "Inverse Avg. k-mer coverage", &kmerInvAvg); outfileM += ltdMat; } /* Jaccard dist */ if(flag & 64) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%.8f", 1, thread_num, lock, "Jaccard Distance", &kmerJaccardDist); outfileM += ltdMat; } /* Jaccard similarity */ if(flag & 128) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%.8f", 1, thread_num, lock, "Jaccard Similarity", &kmerJaccardSim); outfileM += ltdMat; } /* Cosine dist */ if(flag & 256) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%.8f", 1, thread_num, lock, "Cosine distance", &kmerCosineDist); outfileM += ltdMat; } /* Cosine similarity */ if(flag & 512) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%.8f", 1, thread_num, lock, "Cosine similarity", &kmerCosineSim); outfileM += ltdMat; } /* Szymkiewicz–Simpson similarity */ if(flag & 1024) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%.8f", 1, thread_num, lock, "Szymkiewicz–Simpson similarity", &kmerOverlapCoef); outfileM += ltdMat; } /* Szymkiewicz–Simpson dissimilarity */ if(flag & 2048) { printDoublePhy(outfileM, Dist, N, name_file, template_name, format, "\t%.8f", 1, thread_num, lock, "Szymkiewicz–Simpson dissimilarity", &kmerInvOverlapCoef); outfileM += ltdMat; } /* Chi-square distance */ if(flag & 4096) { printIntLtdPhy(outfileM, Dist, N, name_file, template_name, format, thread_num, lock, "Chi-square distance", &chi2dist); outfileM += ltdMat; } return NULL; } void runDist(char *templatefilename, char *outputfilename, int flag, int format, int disk, int thread_num) { int i, file_len, *N; unsigned DB_size; long unsigned out_size, ltdMat, covMat; char *outfileM; FILE *outfile, *name_file; DistThread *thread, *threads; HashMapKMA *DB; Matrix *Dist; Qseqs *template_name; /* init */ outfile = sfopen(outputfilename, "wb+"); file_len = strlen(templatefilename); /* load k-mer links from KMA DB */ strcpy(templatefilename + file_len, ".comp.b"); if(!(DB = loadValues(templatefilename))) { fprintf(stderr, "Wrong format of DB.\n"); exit(1); } templatefilename[file_len] = 0; /* load names */ strcpy(templatefilename + file_len, ".name"); name_file = sfopen(templatefilename, "rb"); templatefilename[file_len] = 0; template_name = setQseqs(1024); /* allocate output file */ DB_size = DB->DB_size; out_size = getPhySize(flag, format, DB_size, <dMat, &covMat, name_file); outfileM = mfile(outfile, out_size); /* allocate matrices */ if(!(N = calloc(DB_size, sizeof(int)))) { ERROR(); } if(disk) { Dist = ltdMatrix_minit(DB_size); } else { Dist = ltdMatrix_init(DB_size); } /* thread out */ thread = 0; threads = 0; i = thread_num; while(i--) { /* init */ thread = smalloc(sizeof(DistThread)); thread->flag = flag; thread->format = format; thread->thread_num = thread_num; thread->N = N; thread->ltdMat = ltdMat; thread->covMat = covMat; thread->outfileM = outfileM; thread->name_file = name_file; thread->DB = DB; thread->Dist = Dist; thread->template_name = template_name; thread->next = threads; threads = thread; /* start */ if(i && (errno = pthread_create(&thread->id, NULL, &threadDist, thread))) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); fprintf(stderr, "Will continue with %d threads.\n", thread_num - i); i = 0; } } /* start main thread */ thread->id = 0; threadDist(thread); /* join threads */ while((thread = thread->next)) { /* join thread */ if((errno = pthread_join(thread->id, NULL))) { ERROR(); } } /* clean */ while(threads) { thread = threads->next; free(threads); threads = thread; } outfileM -= out_size; msync(outfileM, out_size, MS_SYNC); munmap(outfileM, out_size); fclose(outfile); fclose(name_file); free(N); if(disk) { Matrix_mdestroy(Dist); } else { Matrix_destroy(Dist); } destroyQseqs(template_name); } static int helpMessage(FILE *out) { fprintf(out, "#kma dist calculates distances between templates from a kma index\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "Options are:", "Desc:", "Default:"); fprintf(out, "# %16s\t%-32s\t%s\n", "-t_db", "Template DB", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-o", "Output file", "DB"); fprintf(out, "# %16s\t%-32s\t%s\n", "-f", "Output flags", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-fh", "Help on option \"-f\"", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-d", "Distance method", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-dh", "Help on option \"-d\"", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-m", "Allocate matrix on the disk", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-tmp", "Set directory for temporary files", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-t", "Number of threads", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-h", "Shows this helpmessage", ""); return (out == stderr); } /* main */ int dist_main(int argc, char *argv[]) { int args, flag, format, mmap, thread_num, file_len; char *arg, *errorMsg, *templatefilename, *outputfilename; /* init */ flag = 1; format = 1; mmap = 0; thread_num = 1; file_len = 0; templatefilename = 0; outputfilename = 0; /* parse cmd-line */ args = 1; while(args < argc) { arg = argv[args]; if(*arg++ == '-') { if(strcmp(arg, "t_db") == 0) { if(++args < argc) { file_len = strlen(argv[args]); templatefilename = smalloc(file_len + 64); strcpy(templatefilename, argv[args]); } else { missArg("\"-o\""); } } else if(strcmp(arg, "o") == 0) { if(++args < argc) { outputfilename = argv[args]; } else { missArg("\"-o\""); } } else if(strcmp(arg, "f") == 0) { if(++args < argc) { format = strtoul(argv[args], &errorMsg, 10); if(*errorMsg != 0) { invaArg("\"-f\""); } } else { missArg("\"-f\""); } } else if(strcmp(arg, "fh") == 0) { fprintf(stdout, "# Format flags output, add them to combine them.\n"); fprintf(stdout, "#\n"); fprintf(stdout, "#%9d\t%s\n", 1, "Relaxed Phylip"); fprintf(stdout, "#%9d\t%s\n", 4, "Include distance method(s) in phylip file"); return 0; } else if(strcmp(arg, "d") == 0) { if(++args < argc) { flag = strtoul(argv[args], &errorMsg, 10); if(*errorMsg != 0) { invaArg("\"-d\""); } } else { missArg("\"-d\""); } } else if(strcmp(arg, "dh") == 0) { fprintf(stdout, "# Distance / Similarity calculation methods, add them to combine them:\n"); fprintf(stdout, "#\n"); fprintf(stdout, "#%9d\t%s\n", 1, "k-mer hamming distance"); fprintf(stdout, "#%9d\t%s\n", 2, "Shared k-mers"); fprintf(stdout, "#%9d\t%s\n", 4, "k-mer query coverage"); fprintf(stdout, "#%9d\t%s\n", 8, "k-mer template coverage"); fprintf(stdout, "#%9d\t%s\n", 16, "k-mer avg. coverage"); fprintf(stdout, "#%9d\t%s\n", 32, "k-mer inv. avg. coverage"); fprintf(stdout, "#%9d\t%s\n", 64, "Jaccard distance"); fprintf(stdout, "#%9d\t%s\n", 128, "Jaccard similarity"); fprintf(stdout, "#%9d\t%s\n", 256, "Cosine distance"); fprintf(stdout, "#%9d\t%s\n", 512, "Cosine similarity"); fprintf(stdout, "#%9d\t%s\n", 1024, "Szymkiewicz–Simpson similarity"); fprintf(stdout, "#%9d\t%s\n", 2048, "Szymkiewicz–Simpson dissimilarity"); fprintf(stdout, "#%9d\t%s\n", 4096, "Chi-square distance"); fprintf(stdout, "#\n"); return 0; } else if(strcmp(arg, "m") == 0) { mmap = 1; } else if(strcmp(argv[args], "-tmp") == 0) { if(++args < argc) { if(argv[args][0] != '-') { tmpF(argv[args]); } else { invaArg("\"-tmp\""); } } } else if(strcmp(argv[args], "-t") == 0) { if(++args < argc) { thread_num = strtoul(argv[args], &errorMsg, 10); if(*errorMsg != 0) { invaArg("\"-t\""); } } else { missArg("\"-t\""); } } else if(strcmp(arg, "h") == 0) { return helpMessage(stdout); } else { fprintf(stderr, "Unknown option:%s\n", arg - 1); return helpMessage(stderr); } } else { fprintf(stderr, "Unknown argument:%s\n", arg - 1); return helpMessage(stderr); } ++args; } if(!templatefilename) { fprintf(stderr, "Too few arguments handed.\n"); exit(1); } if(!outputfilename) { outputfilename = smalloc(file_len + 64); sprintf(outputfilename, "%s.phy", templatefilename); } runDist(templatefilename, outputfilename, flag, format, mmap, thread_num); return 0; } genomicepidemiology-kma-091b8ffe66ac/kmerlink.h0000644000175000017500000000216714157033525021104 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "kmeranker.h" #ifndef KMERLINK #define KMERLINK 1; typedef struct kmerLink KmerLink; struct kmerLink { unsigned size; unsigned n; KmerAnker *list; }; #endif KmerLink * initKmerLink(unsigned size); void reallocKmerLink(KmerLink *src, unsigned newSize); KmerAnker * pushKmerLink(KmerLink *src, KmerAnker *node); KmerAnker * popKmerLink(KmerLink *src, int n); void destroyKmerLink(KmerLink *src); genomicepidemiology-kma-091b8ffe66ac/vcf.h0000644000175000017500000000202014157033525020032 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "assembly.h" #include "filebuff.h" char * noFolder(const char *src); void initialiseVcf(FileBuff *fileP, char *templateFilename); void updateVcf(char *template_name, unsigned char *template_seq, double evalue, double support, int bcd, int t_len, AssemInfo *matrix, int filter, FileBuff *fileP); genomicepidemiology-kma-091b8ffe66ac/assembly.c0000644000175000017500000015413414157033525021104 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include #include "align.h" #include "assembly.h" #include "chain.h" #include "ef.h" #include "filebuff.h" #include "hashmapcci.h" #include "kmapipe.h" #include "nw.h" #include "pherror.h" #include "qseqs.h" #include "sam.h" #include "stdnuc.h" #include "stdstat.h" #include "threader.h" #include "xml.h" #define mrcheck(mrc, Stat, q_len, t_len) ((mrc * q_len <= Stat.len - Stat.qGaps) || (mrc * t_len <= Stat.len - Stat.tGaps)) void * (*assembly_KMA_Ptr)(void *) = &assemble_KMA; int (*significantBase)(int, int, double) = &significantNuc; unsigned char (*baseCall)(unsigned char, unsigned char, int, int, double, Assembly*) = &baseCaller; void (*alnToMatPtr)(AssemInfo *, Assem *, Aln *, AlnScore, int, int) = &alnToMat; void updateFrags(FileBuff *dest, Qseqs *qseq, Qseqs *header, char *template_name, int *stats) { int check, avail; char *update; avail = dest->bytes; check = 47 + qseq->len + header->len + strlen(template_name); /* flush buffer */ if(avail < check) { writeGzFileBuff(dest); /* seq is too big, reallocate buffer */ if(dest->bytes < check) { resetGzFileBuff(dest, check << 1); } avail = dest->bytes; } /* update buffer with fragment */ memcpy(dest->next, qseq->seq, qseq->len); dest->next += qseq->len; avail -= qseq->len; /* stats */ update = (char *) dest->next; check = sprintf(update, "\t%d\t%d\t%d\t%d\t%s\t%s\n", stats[0], stats[1], stats[2], stats[3], template_name, header->seq); dest->next += check; avail -= check; dest->bytes = avail; /* equivalent with: fprintf(frag_out, "%s\t%d\t%d\t%d\t%d\t%s\t%s\n", qseq->seq, stats[0], stats[1], stats[2], stats[3], template_names[template], header->seq); */ } void updateMatrix(FileBuff *dest, char *template_name, long unsigned *template_seq, AssemInfo *matrix, int t_len) { unsigned i, pos, check, avail, asm_len; char *update; const char bases[6] = "ACGTN-"; Assembly *assembly; /* check buffer capacity */ check = strlen(template_name) + 2; if(dest->bytes < check) { writeGzFileBuff(dest); } update = (char *) dest->next; avail = dest->bytes - check; /* fill in header */ check -= 2; *update++ = '#'; memcpy(update, template_name, check); update += check; *update++ = '\n'; /* fill in rows */ asm_len = matrix->len; assembly = matrix->assmb; i = 0; for(pos = 0; asm_len != 0; --asm_len, pos = assembly[pos].next) { /* check buffer capacity */ if(avail < 38) { dest->bytes = avail; writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } /* update with row */ if(pos < t_len) { check = sprintf(update, "%c\t%hu\t%hu\t%hu\t%hu\t%hu\t%hu\n", bases[getNuc(template_seq, i)], assembly[pos].counts[0], assembly[pos].counts[1], assembly[pos].counts[2], assembly[pos].counts[3], assembly[pos].counts[4], assembly[pos].counts[5]); ++i; } else { check = sprintf(update, "-\t%hu\t%hu\t%hu\t%hu\t%hu\t%hu\n", assembly[pos].counts[0], assembly[pos].counts[1], assembly[pos].counts[2], assembly[pos].counts[3], assembly[pos].counts[4], assembly[pos].counts[5]); } avail -= check; update += check; } /* update with last newline */ if(avail == 0) { writeGzFileBuff(dest); avail = dest->bytes; update = (char *) dest->next; } *update++ = '\n'; dest->next = (unsigned char *) update; dest->bytes = avail - 1; } int significantNuc(int X, int Y, double evalue) { return (Y < X && p_chisqr(pow(X - Y, 2) / (X + Y)) <= evalue); } int significantAnd90Nuc(int X, int Y, double evalue) { return (Y < X && (9 * (X + Y) <= 10 * X) && p_chisqr(pow(X - Y, 2) / (X + Y)) <= evalue); } int significantAndSupport(int X, int Y, double evalue) { static double support = 0; if(support == 0) { support = evalue; } return (Y < X && (support * (X + Y) <= X) && p_chisqr(pow(X - Y, 2) / (X + Y)) <= evalue); } unsigned char baseCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls) { /* determine base at current position */ if(depthUpdate == 0) { bestNuc = '-'; } else { /* Use MnNemars test to test significance of the base call */ if(significantBase(bestScore, depthUpdate - bestScore, evalue) == 0) { if(bestNuc == '-' && tNuc != '-' && bestScore != depthUpdate) { bestNuc = 'n'; } else { bestNuc = tolower(bestNuc); } } } return bestNuc; } unsigned char orgBaseCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls) { /* determine base at current position */ if(depthUpdate == 0 || bestNuc == '-') { bestNuc = '-'; } else if(significantBase(bestScore, depthUpdate - bestScore, evalue) == 0) { /* McNemars test */ bestNuc = tolower(bestNuc); } return bestNuc; } unsigned char refCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls) { /* determine base at current position */ if(depthUpdate == 0 || (bestNuc == '-' && tNuc != '-')) { bestNuc = 'n'; } else if(significantBase(bestScore, depthUpdate - bestScore, evalue) == 0) { bestNuc = tolower(bestNuc); } return bestNuc; } unsigned char nanoCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls) { int j, bestBaseScore; const char bases[6] = "ACGTN-"; /* determine base at current position */ if(depthUpdate == 0) { bestNuc = '-'; } else { /* Use MC Neymars test to test significance of the base call */ if(significantBase(bestScore, depthUpdate - bestScore, evalue) == 0) { if(bestNuc == '-' && tNuc != '-' && bestScore != depthUpdate) { bestBaseScore = 0; for(j = 0; j < 5; ++j) { if(bestBaseScore < calls->counts[j]) { bestBaseScore = calls->counts[j]; bestNuc = j; } } if(bestBaseScore == 0) { bestNuc = '-'; } else { bestNuc = tolower(bases[bestNuc]); } } else { bestNuc = tolower(bestNuc); } } } return bestNuc; } unsigned char refNanoCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls) { int j, bestBaseScore; const char bases[6] = "ACGTN-"; /* determine base at current position */ if(depthUpdate == 0) { bestNuc = 'n'; } else { /* Use MC Neymars test to test significance of the base call */ if(significantBase(bestScore, depthUpdate - bestScore, evalue) == 0) { if(bestNuc == '-') { bestBaseScore = 0; for(j = 0; j < 5; ++j) { if(bestBaseScore < calls->counts[j]) { bestBaseScore = calls->counts[j]; bestNuc = j; } } if(bestBaseScore == 0) { bestNuc = 'n'; } else { bestNuc = tolower(bases[bestNuc]); } } else { bestNuc = tolower(bestNuc); } } else if(bestNuc == '-') { bestNuc = 'n'; } } return bestNuc; } void * assemble_KMA_threaded(void *arg) { static volatile int Lock[3] = {0, 0, 0}, mainTemplate = -2, thread_wait = 0; static char *template_name; static HashMapCCI *template_index; volatile int *excludeIn = &Lock[0], *excludeOut = &Lock[1], *excludeMatrix = &Lock[2]; Assemble_thread *thread = arg; int i, j, t_len, aln_len, start, end, bias, myBias, gaps, pos, spin, sam; int read_score, depthUpdate, bestBaseScore, bestScore, template, asm_len; int nextTemplate, file_i, file_count, delta, thread_num, mq, status, bcd; int minlen, q_start, q_end, stats[5], buffer[8], *qBoundPtr; unsigned coverScore; long unsigned depth, depthVar; short unsigned *counts; const char bases[6] = "ACGTN-"; double score, scoreT, mrc, evalue; unsigned char bestNuc; FILE **files, *file, *xml_out; AlnScore alnStat; Assembly *assembly; FileBuff *frag_out; Assem *aligned_assem; Aln *aligned, *gap_align; Qseqs *qseq, *header; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; /* get input */ template = thread->template; file_count = thread->file_count; files = thread->files; xml_out = thread->xml_out; frag_out = thread->frag_out; aligned_assem = thread->aligned_assem; aligned = thread->aligned; gap_align = thread->gap_align; qseq = thread->qseq; header = thread->header; matrix = thread->matrix; points = thread->points; NWmatrices = thread->NWmatrices; delta = qseq->size; mq = thread->mq; minlen = thread->minlen; scoreT = thread->scoreT; mrc = thread->mrc; evalue = thread->evalue; bcd = thread->bcd; sam = thread->sam; spin = thread->spin; thread_num = thread->thread_num; if(template != -2) { /* all assemblies done, signal threads to return */ if(template == -1) { lock(excludeMatrix); mainTemplate = template; unlock(excludeMatrix); return NULL; } /* Allocate assembly arrays */ lock(excludeMatrix); template_name = thread->template_name; template_index = thread->template_index; t_len = template_index->len; matrix->len = 0; /* start threads */ aligned_assem->score = 0; aligned_assem->fragmentCountAln = 0; aligned_assem->readCountAln = 0; mainTemplate = template; thread_wait = thread_num; unlock(excludeMatrix); template = -2; } do { while(template == mainTemplate) { usleep(100); } lock(excludeMatrix); template = mainTemplate; if(template != -1) { t_len = template_index->len; } unlock(excludeMatrix); if(template == -1) { return NULL; } /* load reads of this template */ file_i = 0; while(file_i < file_count) { lockTime(excludeIn, spin); file = files[file_i]; if(file != 0) { read_score = fread(buffer, sizeof(int), 8, file); if((nextTemplate = buffer[0]) == template) { /* load frag */ qseq->len = buffer[1]; stats[0] = buffer[2]; read_score = buffer[3]; stats[2] = buffer[4]; stats[3] = buffer[5]; header->len = buffer[6]; stats[4] = buffer[7]; if(qseq->size < qseq->len) { free(qseq->seq); qseq->size = qseq->len << 1; qseq->seq = smalloc(qseq->size); } if(header->size < header->len) { header->size = header->len + 1; free(header->seq); header->seq = smalloc(header->size); } sfread(qseq->seq, 1, qseq->len, file); sfread(header->seq, 1, header->len, file); unlock(excludeIn); if(delta < qseq->len) { delta = qseq->len << 1; free(aligned->t); free(aligned->s); free(aligned->q); free(gap_align->t); free(gap_align->s); free(gap_align->q); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); } /* q-bound */ if(2 * sizeof(int) + 1 < header->len && header->seq[header->len - 2 * sizeof(int) - 1] == 0) { qBoundPtr = (int*) (header->seq + (header->len - 2 * sizeof(int))); q_start = *qBoundPtr; q_end = *++qBoundPtr; } else { q_start = 0; q_end = qseq->len; } /* Update assembly with read */ if(read_score || anker_rc(template_index, qseq->seq, qseq->len, q_start, q_end, points)) { /* Start with alignment */ if(stats[3] <= stats[2]) { stats[2] = 0; stats[3] = t_len; } alnStat = KMA(template_index, qseq->seq, qseq->len, q_start, q_end, aligned, gap_align, stats[2], MIN(t_len, stats[3]), mq, scoreT, points, NWmatrices); /* get read score */ aln_len = alnStat.len; start = alnStat.pos; end = start + aln_len - alnStat.tGaps; /* Get normed score check read coverage */ read_score = alnStat.score; if(minlen <= aln_len && mrcheck(mrc, alnStat, qseq->len, t_len)) { score = 1.0 * read_score / aln_len; } else { read_score = 0; score = 0; } if(0 < read_score && scoreT <= score) { stats[1] = read_score; stats[2] = start; stats[3] = end; if(t_len < end) { stats[3] -= t_len; } /* Update backbone and counts */ //lock(excludeMatrix); lockTime(excludeMatrix, 10) aligned_assem->score += read_score; if(!(stats[4] & 2) || (stats[4] & 64)) { ++aligned_assem->fragmentCountAln; } ++aligned_assem->readCountAln; /* init matrix */ if(!matrix->len) { matrix->len = t_len; if(matrix->size < (t_len << 1)) { matrix->size = (t_len << 1); free(matrix->assmb); matrix->assmb = smalloc(matrix->size * sizeof(Assembly)); } /* cpy template seq */ assembly = matrix->assmb - 1; i = 0; while(i != t_len) { counts = (++assembly)->counts; *counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; assembly->next = ++i; } /* circularize */ assembly->next = 0; /* for(i = 0, j = 1; i < t_len; ++i, ++j) { assembly[i].counts[0] = 0; assembly[i].counts[1] = 0; assembly[i].counts[2] = 0; assembly[i].counts[3] = 0; assembly[i].counts[4] = 0; assembly[i].counts[5] = 0; assembly[i].next = j; } assembly[t_len - 1].next = 0; */ } /* diff */ i = 0; pos = start; assembly = matrix->assmb; while(i < aln_len) { if(aligned->t[i] == 5) { // Template gap, insertion if(t_len <= pos) { if(!++assembly[pos].counts[aligned->q[i]]) { assembly[pos].counts[aligned->q[i]] = USHRT_MAX; } ++i; pos = assembly[pos].next; } else { /* get estimate for non insertions */ myBias = 0; for(j = 0; j < 6; ++j) { myBias += assembly[pos].counts[j]; } if(myBias > 0) { --myBias; } /* find position of insertion */ gaps = pos; if(pos != 0) { --pos; } else { pos = t_len - 1; } while(assembly[pos].next != gaps) { pos = assembly[pos].next; } while(i < aln_len && aligned->t[i] == 5) { assembly[pos].next = matrix->len++; if(matrix->len == matrix->size) { matrix->size <<= 1; matrix->assmb = realloc(assembly, matrix->size * sizeof(Assembly)); if(!matrix->assmb) { matrix->size >>= 1; matrix->size += 1024; matrix->assmb = realloc(assembly, matrix->size * sizeof(Assembly)); if(!matrix->assmb) { ERROR(); } } assembly = matrix->assmb; } pos = assembly[pos].next; assembly[pos].next = gaps; assembly[pos].counts[0] = 0; assembly[pos].counts[1] = 0; assembly[pos].counts[2] = 0; assembly[pos].counts[3] = 0; assembly[pos].counts[4] = 0; assembly[pos].counts[5] = myBias < USHRT_MAX ? myBias : USHRT_MAX; assembly[pos].counts[aligned->q[i]] = 1; ++i; } pos = assembly[pos].next; } } else if(t_len <= pos) { // Old template gap, not present in this read if(!++assembly[pos].counts[5]) { assembly[pos].counts[5] = USHRT_MAX; } pos = assembly[pos].next; } else { if(!++assembly[pos].counts[aligned->q[i]]) { assembly[pos].counts[aligned->q[i]] = USHRT_MAX; } ++i; pos = assembly[pos].next; } } unlock(excludeMatrix); /* Convert fragment */ for(i = 0; i < qseq->len; ++i) { qseq->seq[i] = bases[qseq->seq[i]]; } qseq->seq[qseq->len] = 0; /* Save fragment */ if(frag_out) { lockTime(excludeOut, 10); updateFrags(frag_out, qseq, header, template_name, stats); unlock(excludeOut); } if(sam) { header->seq[header->len - 1] = 0; samwrite(qseq, header, 0, template_name, aligned, stats); } if(xml_out) { hitXML(xml_out, template, header->seq, aligned, &alnStat, NWmatrices->rewards, stats[4]); } } else if(sam && !(sam & 2096)) { stats[1] = read_score; stats[2] = start; stats[3] = end; header->seq[header->len - 1] = 0; nibble2base(qseq->seq, qseq->len); if(read_score) { samwrite(qseq, header, 0, template_name, aligned, stats); } else { stats[4] |= 4; stats[1] = stats[4]; samwrite(qseq, header, 0, template_name, 0, stats); } } } else if(sam && !(sam & 2096)) { stats[4] |= 4; stats[1] = stats[4]; header->seq[header->len - 1] = 0; nibble2base(qseq->seq, qseq->len); samwrite(qseq, header, 0, template_name, 0, stats); } } else if(nextTemplate == -1) { if(template) { fclose(file); } else { kmaPipe(0, 0, file, &status); errno |= status; } files[file_i] = 0; unlock(excludeIn); ++file_i; } else if(nextTemplate < template) { /* Move pointer forward */ fseek(file, buffer[1] + buffer[6], SEEK_CUR); unlock(excludeIn); } else { /* Move pointer back */ fseek(file, (-8) * sizeof(int), SEEK_CUR); unlock(excludeIn); ++file_i; } } else { unlock(excludeIn); ++file_i; } } lock(excludeIn); --thread_wait; unlock(excludeIn); } while(thread->num != 0); wait_atomic(thread_wait); if(aligned_assem->score == 0) { aligned_assem->cover = 0; aligned_assem->depth = 0; aligned_assem->depthVar = 0; aligned_assem->t[0] = 0; aligned_assem->s[0] = 0; aligned_assem->q[0] = 0; aligned_assem->len = 0; aligned_assem->aln_len = 0; return NULL; } /* diff */ /* pre on dense */ /* Pepare and make alignment on consensus */ asm_len = matrix->len; assembly = matrix->assmb; if(aligned_assem->size <= asm_len) { aligned_assem->size = (asm_len + 1) << 1; free(aligned_assem->t); free(aligned_assem->s); free(aligned_assem->q); aligned_assem->t = smalloc(aligned_assem->size); aligned_assem->s = smalloc(aligned_assem->size); aligned_assem->q = smalloc(aligned_assem->size); } /* Call nucleotides for the consensus */ /* diff */ i = 0; pos = 0; depth = 0; depthVar = 0; aln_len = 0; while(i < asm_len) { /* call template */ if(pos < t_len) { bestNuc = getNuc(template_index->seq, pos); } else { bestNuc = 5; } aligned_assem->t[i] = bases[bestNuc]; /* call query */ bestScore = assembly[pos].counts[bestNuc]; depthUpdate = 0; for(j = 0; j < 6; ++j) { if(bestScore < assembly[pos].counts[j]) { bestScore = assembly[pos].counts[j]; bestNuc = j; } depthUpdate += assembly[pos].counts[j]; } bestNuc = bases[bestNuc]; /* check for minor base call */ if(!depthUpdate) { bestNuc = '-'; } else if((bestScore << 1) < depthUpdate) { if(bestNuc == '-') { bestBaseScore = assembly[pos].counts[4]; bestNuc = 4; for(j = 0; j < 4; ++j) { if(bestBaseScore < assembly[pos].counts[j]) { bestBaseScore = assembly[pos].counts[j]; bestNuc = j; } } bestNuc = tolower(bases[bestNuc]); } else { bestNuc = tolower(bestNuc); } bestScore = depthUpdate - assembly[pos].counts[5]; } else if(depthUpdate < bcd) { /* too low depth */ bestNuc = tolower(bestNuc); } /* determine base at current position */ /* if(bcd <= depthUpdate) { bestNuc = baseCall(bestNuc, aligned_assem->t[i], bestScore, depthUpdate, evalue, &assembly[pos]); } else { bestNuc = baseCall('-', aligned_assem->t[i], 0, 0, evalue, &assembly[pos]); } */ bestNuc = baseCall(bestNuc, aligned_assem->t[i], bestScore, depthUpdate, evalue, &assembly[pos]); aligned_assem->q[i] = bestNuc; if(bestNuc != '-') { depth += depthUpdate; depthVar += (depthUpdate * depthUpdate); ++aln_len; } ++i; pos = assembly[pos].next; } /* Trim alignment on consensus */ coverScore = 0; bias = 0; for(i = 0; i < asm_len; ++i) { if(aligned_assem->t[i] == '-' && aligned_assem->q[i] == '-') { ++bias; } else { aligned_assem->t[i - bias] = aligned_assem->t[i]; aligned_assem->q[i - bias] = aligned_assem->q[i]; if(tolower(aligned_assem->t[i]) == tolower(aligned_assem->q[i])) { aligned_assem->s[i - bias] = '|'; ++coverScore; } else { aligned_assem->s[i - bias] = '_'; } } } asm_len -= bias; aligned_assem->t[asm_len] = 0; aligned_assem->s[asm_len] = 0; aligned_assem->q[asm_len] = 0; aligned_assem->cover = coverScore; aligned_assem->depth = depth; aligned_assem->depthVar = depthVar; aligned_assem->len = asm_len; aligned_assem->aln_len = aln_len; return NULL; } void * assemble_KMA_dense_threaded(void *arg) { static volatile int Lock[3] = {0, 0, 0}, mainTemplate = -2, thread_wait = 0; static char *template_name; static HashMapCCI *template_index; volatile int *excludeIn = &Lock[0], *excludeOut = &Lock[1], *excludeMatrix = &Lock[2]; Assemble_thread *thread = arg; int i, j, t_len, aln_len, start, end, file_i, file_count, template, spin; int pos, read_score, bestScore, depthUpdate, bestBaseScore, nextTemplate; int sam, thread_num, mq, status, bcd, minlen, q_start, q_end, *qBoundPtr; int stats[5], buffer[8]; unsigned coverScore, delta; long unsigned depth, depthVar; short unsigned *counts; const char bases[6] = "ACGTN-"; double score, scoreT, mrc, evalue; unsigned char bestNuc; FILE **files, *file, *xml_out; AlnScore alnStat; Assembly *assembly; FileBuff *frag_out; Assem *aligned_assem; Aln *aligned, *gap_align; Qseqs *qseq, *header; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; /* get input */ template = thread->template; file_count = thread->file_count; files = thread->files; xml_out = thread->xml_out; frag_out = thread->frag_out; aligned_assem = thread->aligned_assem; aligned = thread->aligned; gap_align = thread->gap_align; qseq = thread->qseq; header = thread->header; matrix = thread->matrix; points = thread->points; NWmatrices = thread->NWmatrices; delta = qseq->size; mq = thread->mq; minlen = thread->minlen; scoreT = thread->scoreT; mrc = thread->mrc; evalue = thread->evalue; bcd = thread->bcd; sam = thread->sam; spin = thread->spin; thread_num = thread->thread_num; if(template != -2) { /* all assemblies done, signal threads to return */ if(template == -1) { lock(excludeOut); mainTemplate = template; unlock(excludeOut); return NULL; } /* Allocate assembly arrays */ lock(excludeOut); template_name = thread->template_name; template_index = thread->template_index; t_len = template_index->len; matrix->len = t_len; /* diff */ if(aligned_assem->size <= t_len) { aligned_assem->size = t_len + 1; free(aligned_assem->t); free(aligned_assem->s); free(aligned_assem->q); aligned_assem->t = smalloc(t_len + 1); aligned_assem->s = smalloc(t_len + 1); aligned_assem->q = smalloc(t_len + 1); } if(matrix->size <= t_len) { matrix->size = t_len + 1; free(matrix->assmb); matrix->assmb = smalloc(matrix->size * sizeof(Assembly)); } /* cpy template seq */ assembly = matrix->assmb - 1; i = 0; while(i != t_len) { aligned_assem->t[i] = getNuc(template_index->seq, i); counts = (++assembly)->counts; *counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; assembly->next = ++i; } /* circularize */ assembly->next = 0; assembly = matrix->assmb; /* for(i = 0, j = 1; i < t_len; ++i, ++j) { assembly[i].counts[0] = 0; assembly[i].counts[1] = 0; assembly[i].counts[2] = 0; assembly[i].counts[3] = 0; assembly[i].counts[4] = 0; assembly[i].counts[5] = 0; assembly[i].next = j; } assembly[t_len - 1].next = 0; */ /* start threads */ aligned_assem->score = 0; aligned_assem->fragmentCountAln = 0; aligned_assem->readCountAln = 0; mainTemplate = template; thread_wait = thread_num; unlock(excludeOut); template = -2; } do { while(template == mainTemplate) { usleep(100); } lock(excludeOut); template = mainTemplate; if(template != -1) { t_len = template_index->len; assembly = matrix->assmb; } unlock(excludeOut); if(template == -1) { return NULL; } /* load reads of this template */ file_i = 0; while(file_i < file_count) { lockTime(excludeIn, spin); file = files[file_i]; if(file != 0) { read_score = fread(buffer, sizeof(int), 8, file); if((nextTemplate = buffer[0]) == template) { /* load frag */ qseq->len = buffer[1]; stats[0] = buffer[2]; read_score = buffer[3]; stats[2] = buffer[4]; stats[3] = buffer[5]; header->len = buffer[6]; stats[4] = buffer[7]; if(qseq->size < qseq->len) { free(qseq->seq); qseq->size = qseq->len << 1; qseq->seq = malloc(qseq->size); if(!qseq->seq) { ERROR(); } } if(header->size < header->len) { header->size = header->len + 1; free(header->seq); header->seq = malloc(header->size); if(!header->seq) { ERROR(); } } sfread(qseq->seq, 1, qseq->len, file); sfread(header->seq, 1, header->len, file); unlock(excludeIn); if(delta < qseq->size) { delta = qseq->size; free(aligned->t); free(aligned->s); free(aligned->q); free(gap_align->t); free(gap_align->s); free(gap_align->q); aligned->t = malloc((delta + 1) << 1); aligned->s = malloc((delta + 1) << 1); aligned->q = malloc((delta + 1) << 1); gap_align->t = malloc((delta + 1) << 1); gap_align->s = malloc((delta + 1) << 1); gap_align->q = malloc((delta + 1) << 1); if(!aligned->t || !aligned->s || !aligned->q || !gap_align->t || !gap_align->s || !gap_align->q) { ERROR(); } } /* q-bound */ if(2 * sizeof(int) + 1 < header->len && header->seq[header->len - 2 * sizeof(int) - 1] == 0) { qBoundPtr = (int*) (header->seq + (header->len - 2 * sizeof(int))); q_start = *qBoundPtr; q_end = *++qBoundPtr; } else { q_start = 0; q_end = qseq->len; } /* Update assembly with read */ if(read_score || anker_rc(template_index, qseq->seq, qseq->len, q_start, q_end, points)) { if(stats[3] <= stats[2]) { stats[2] = 0; stats[3] = t_len; } /* Start with alignment */ alnStat = KMA(template_index, qseq->seq, qseq->len, q_start, q_end, aligned, gap_align, stats[2], MIN(t_len, stats[3]), mq, scoreT, points, NWmatrices); /* get read score */ aln_len = alnStat.len; start = alnStat.pos; end = start + aln_len - alnStat.tGaps; /* Get normed score check read coverage */ read_score = alnStat.score; if(minlen <= aln_len && mrcheck(mrc, alnStat, qseq->len, t_len)) { score = 1.0 * read_score / aln_len; } else { read_score = 0; score = 0; } if(0 < read_score && scoreT <= score) { stats[1] = read_score; stats[2] = start; stats[3] = end; if(t_len < end) { stats[3] -= t_len; } /* Update backbone and counts */ //lock(excludeMatrix); lockTime(excludeMatrix, 10) aligned_assem->score += read_score; if(!(stats[4] & 2) || (stats[4] & 64)) { ++aligned_assem->fragmentCountAln; } ++aligned_assem->readCountAln; /* diff */ for(i = 0, pos = start; i < aln_len; ++i) { if(aligned->t[i] == aligned_assem->t[pos]) { if(!++assembly[pos].counts[aligned->q[i]]) { assembly[pos].counts[aligned->q[i]] = USHRT_MAX; } pos = assembly[pos].next; } } unlock(excludeMatrix); /* Convert fragment */ for(i = 0; i < qseq->len; ++i) { qseq->seq[i] = bases[qseq->seq[i]]; } qseq->seq[qseq->len] = 0; /* Save fragment */ if(frag_out) { lockTime(excludeOut, 10); updateFrags(frag_out, qseq, header, template_name, stats); unlock(excludeOut); } if(sam) { header->seq[header->len - 1] = 0; samwrite(qseq, header, 0, template_name, aligned, stats); } if(xml_out) { hitXML(xml_out, template, header->seq, aligned, &alnStat, NWmatrices->rewards, stats[4]); } } else if(sam && !(sam & 2096)) { stats[1] = read_score; stats[2] = start; stats[3] = end; /* flag */ header->seq[header->len - 1] = 0; nibble2base(qseq->seq, qseq->len); if(read_score) { samwrite(qseq, header, 0, template_name, aligned, stats); } else { stats[4] |= 4; stats[1] = stats[4]; samwrite(qseq, header, 0, template_name, 0, stats); } } } else if(sam && !(sam & 2096)) { stats[4] |= 4; stats[1] = stats[4]; header->seq[header->len - 1] = 0; nibble2base(qseq->seq, qseq->len); samwrite(qseq, header, 0, template_name, 0, stats); } } else if (nextTemplate == -1) { if(template) { fclose(file); } else { kmaPipe(0, 0, file, &status); errno |= status; } files[file_i] = 0; unlock(excludeIn); ++file_i; } else if(nextTemplate < template) { /* Move pointer forward */ fseek(file, buffer[1] + buffer[6], SEEK_CUR); unlock(excludeIn); } else { /* Move pointer back */ fseek(file, (-8) * sizeof(int), SEEK_CUR); unlock(excludeIn); ++file_i; } } else { unlock(excludeIn); ++file_i; } } lock(excludeIn); --thread_wait; unlock(excludeIn); } while(thread->num != 0); wait_atomic(thread_wait); if(aligned_assem->score == 0) { aligned_assem->cover = 0; aligned_assem->depth = 0; aligned_assem->depthVar = 0; aligned_assem->t[0] = 0; aligned_assem->s[0] = 0; aligned_assem->q[0] = 0; aligned_assem->len = 0; aligned_assem->aln_len = 0; return NULL; } /* Make consensus assembly by majority voting */ /* diff */ depth = 0; depthVar = 0; coverScore = 0; aln_len = 0; for(i = 0; i < t_len; ++i) { /* call template */ bestNuc = getNuc(template_index->seq, i); aligned_assem->t[i] = bases[bestNuc]; /* call query */ bestScore = assembly[i].counts[bestNuc]; depthUpdate = 0; for(j = 0; j < 6; ++j) { if(bestScore < assembly[i].counts[j]) { bestScore = assembly[i].counts[j]; bestNuc = j; } depthUpdate += assembly[i].counts[j]; } bestNuc = bases[bestNuc]; /* Check for minor base call */ if(!depthUpdate) { bestNuc = '-'; } else if((bestScore << 1) < depthUpdate) { if(bestNuc == '-') { bestBaseScore = 0; bestNuc = 4; for(j = 0; j < 5; ++j) { if(bestBaseScore < assembly[i].counts[j]) { bestBaseScore = assembly[i].counts[j]; bestNuc = j; } } bestNuc = tolower(bases[bestNuc]); } else { bestNuc = tolower(bestNuc); } bestScore = depthUpdate - assembly[i].counts[5]; } else if(depthUpdate < bcd) { /* too low depth */ bestNuc = tolower(bestNuc); } /* determine base at current position */ /* if(bcd <= depthUpdate) { bestNuc = baseCall(bestNuc, aligned_assem->t[i], bestScore, depthUpdate, evalue, &assembly[i]); } else { bestNuc = baseCall('-', aligned_assem->t[i], 0, 0, evalue, &assembly[i]); } */ bestNuc = baseCall(bestNuc, aligned_assem->t[i], bestScore, depthUpdate, evalue, &assembly[i]); aligned_assem->q[i] = bestNuc; if(bestNuc != '-') { depth += depthUpdate; depthVar += (depthUpdate * depthUpdate); ++aln_len; } if(tolower(aligned_assem->q[i]) == tolower(aligned_assem->t[i])) { aligned_assem->s[i] = '|'; ++coverScore; } else { aligned_assem->s[i] = '_'; } } aligned_assem->t[t_len] = 0; aligned_assem->s[t_len] = 0; aligned_assem->q[t_len] = 0; aligned_assem->cover = coverScore; aligned_assem->depth = depth; aligned_assem->depthVar = depthVar; aligned_assem->len = t_len; aligned_assem->aln_len = aln_len; return NULL; } void * skip_assemble_KMA(void *arg) { Assemble_thread *thread = arg; int template, t_len, sam, nextTemplate, file_count, file_i, status; int stats[5], buffer[8]; char *template_name; FILE *file, **files; Assem *aligned_assem; Qseqs *qseq, *header; if((template = thread->template) < 0) { return NULL; } /* get input */ sam = thread->sam; t_len = thread->template_index->len; template_name = thread->template_name; file_count = thread->file_count; files = thread->files; aligned_assem = thread->aligned_assem; qseq = thread->qseq; header = thread->header; aligned_assem->var = 0; aligned_assem->nucHighVar = 0; aligned_assem->maxDepth = 0; aligned_assem->snpSum = 0; aligned_assem->insertSum = 0; aligned_assem->deletionSum = 0; aligned_assem->score = 0; aligned_assem->cover = 0; aligned_assem->depth = 0; aligned_assem->depthVar = 0; aligned_assem->t[0] = 0; aligned_assem->s[0] = 0; aligned_assem->q[0] = 0; aligned_assem->len = t_len; aligned_assem->aln_len = t_len; aligned_assem->fragmentCountAln = 0; aligned_assem->readCountAln = 0; /* load reads of this template */ file_i = 0; while(file_i < file_count) { file = files[file_i]; if(file != 0) { nextTemplate = fread(buffer, sizeof(int), 8, file); if((nextTemplate = buffer[0]) == template) { /* load frag */ qseq->len = buffer[1]; stats[0] = buffer[2]; stats[2] = buffer[4]; stats[3] = buffer[5]; header->len = buffer[6]; stats[4] = buffer[7]; if(qseq->size < qseq->len) { free(qseq->seq); qseq->size = qseq->len << 1; qseq->seq = smalloc(qseq->size); } if(header->size < header->len) { header->size = header->len + 1; free(header->seq); header->seq = smalloc(header->size); } sfread(qseq->seq, 1, qseq->len, file); sfread(header->seq, 1, header->len, file); /* Update with read */ aligned_assem->depth += qseq->len; if(sam) { stats[4] |= 4; stats[1] = stats[4]; header->seq[header->len - 1] = 0; nibble2base(qseq->seq, qseq->len); samwrite(qseq, header, 0, template_name, 0, stats); } } else if (nextTemplate == -1) { if(template) { fclose(file); } else { kmaPipe(0, 0, file, &status); errno |= status; } files[file_i] = 0; ++file_i; } else if(nextTemplate < template) { /* Move pointer forward */ fseek(file, buffer[1] + buffer[6], SEEK_CUR); } else { /* Move pointer back */ fseek(file, (-8) * sizeof(int), SEEK_CUR); ++file_i; } } else { ++file_i; } } aligned_assem->cover = 0; aligned_assem->aln_len = 0;//(1 - exp((-1.0) * aligned_assem->depth / t_len)) * t_len; // expected coverage from depth return NULL; } void alnToMat(AssemInfo *matrix, Assem *aligned_assem, Aln *aligned, AlnScore alnStat, int t_len, int flag) { static volatile int Lock = 0; volatile int *excludeMatrix = &Lock; int i, j, pos, aln_len, start, read_score, myBias, gaps; Assembly *assembly; /* init */ aln_len = alnStat.len; start = alnStat.pos; read_score = alnStat.score; /* Update backbone and counts */ //lockTime(excludeMatrix, 10) lock(excludeMatrix); aligned_assem->score += read_score; if(!(flag & 2) || (flag & 64)) { ++aligned_assem->fragmentCountAln; } ++aligned_assem->readCountAln; /* diff */ i = 0; pos = start; assembly = matrix->assmb; while(i < aln_len) { if(aligned->t[i] == 5) { // Template gap, insertion if(t_len <= pos) { if(!++assembly[pos].counts[aligned->q[i]]) { assembly[pos].counts[aligned->q[i]] = USHRT_MAX; } ++i; pos = assembly[pos].next; } else { /* get estimate for non insertions */ myBias = 0; for(j = 0; j < 6; ++j) { myBias += assembly[pos].counts[j]; } if(myBias > 0) { --myBias; } /* find position of insertion */ gaps = pos; if(pos != 0) { --pos; } else { pos = t_len - 1; } while(assembly[pos].next != gaps) { pos = assembly[pos].next; } while(i < aln_len && aligned->t[i] == 5) { assembly[pos].next = matrix->len++; if(matrix->len == matrix->size) { matrix->size <<= 1; matrix->assmb = realloc(assembly, matrix->size * sizeof(Assembly)); if(!matrix->assmb) { matrix->size >>= 1; matrix->size += 1024; matrix->assmb = realloc(assembly, matrix->size * sizeof(Assembly)); if(!matrix->assmb) { ERROR(); } } assembly = matrix->assmb; } pos = assembly[pos].next; assembly[pos].next = gaps; assembly[pos].counts[0] = 0; assembly[pos].counts[1] = 0; assembly[pos].counts[2] = 0; assembly[pos].counts[3] = 0; assembly[pos].counts[4] = 0; assembly[pos].counts[5] = myBias < USHRT_MAX ? myBias : USHRT_MAX; assembly[pos].counts[aligned->q[i]] = 1; ++i; } pos = assembly[pos].next; } } else if(t_len <= pos) { // Old template gap, not present in this read if(!++assembly[pos].counts[5]) { assembly[pos].counts[5] = USHRT_MAX; } pos = assembly[pos].next; } else { if(!++assembly[pos].counts[aligned->q[i]]) { assembly[pos].counts[aligned->q[i]] = USHRT_MAX; } ++i; pos = assembly[pos].next; } } unlock(excludeMatrix); } void alnToMatDense(AssemInfo *matrix, Assem *aligned_assem, Aln *aligned, AlnScore alnStat, int t_len, int flag) { static volatile int Lock = 0; volatile int *excludeMatrix = &Lock; int i, pos, aln_len, start, read_score; Assembly *assembly; /* init */ aln_len = alnStat.len; start = alnStat.pos; read_score = alnStat.score; /* Update backbone and counts */ //lockTime(excludeMatrix, 10) lock(excludeMatrix); aligned_assem->score += read_score; if(!(flag & 2) || (flag & 64)) { ++aligned_assem->fragmentCountAln; } ++aligned_assem->readCountAln; /* diff */ assembly = matrix->assmb; for(i = 0, pos = start; i < aln_len; ++i) { if(aligned->t[i] != 5) { if(!++assembly[pos].counts[aligned->q[i]]) { assembly[pos].counts[aligned->q[i]] = USHRT_MAX; } pos = assembly[pos].next; } } unlock(excludeMatrix); } void callConsensus(AssemInfo *matrix, Assem *aligned_assem, long unsigned *seq, int t_len, int bcd, double evalue, int thread_num) { const char bases[6] = "ACGTN-"; static volatile int Lock = 0, next, thread_wait = 0; volatile int *excludeMatrix = &Lock; int i, j, pos, end ,asm_len, aln_len, bestScore, bestBaseScore, chunk; int coverScore; long unsigned depth, depthVar, depthUpdate; unsigned char bestNuc; Assembly *assembly; /* init */ lock(excludeMatrix); if(!thread_wait) { next = 0; thread_wait = thread_num; } unlock(excludeMatrix); asm_len = matrix->len; assembly = matrix->assmb; depth = 0; depthVar = 0; aln_len = 0; coverScore = 0; /* call in chunk of 8112 ~= 1 MB */ chunk = alnToMatPtr != &alnToMatDense ? asm_len : 8112; while(chunk) { lock(excludeMatrix); /* get next chunk */ i = next; if((next += chunk) < 0) { next = asm_len; } unlock(excludeMatrix); /* call chunk */ if(i < asm_len) { end = i + chunk; if(asm_len < end) { end = asm_len; chunk = 0; } pos = i; while(i < end) { /* call template */ if(pos < t_len) { bestNuc = getNuc(seq, pos); } else { bestNuc = 5; } aligned_assem->t[i] = bases[bestNuc]; /* call query */ bestScore = assembly[pos].counts[bestNuc]; depthUpdate = 0; for(j = 0; j < 6; ++j) { if(bestScore < assembly[pos].counts[j]) { bestScore = assembly[pos].counts[j]; bestNuc = j; } depthUpdate += assembly[pos].counts[j]; } bestNuc = bases[bestNuc]; /* check for minor base call */ if(!depthUpdate) { bestNuc = '-'; } else if((bestScore << 1) < depthUpdate) { if(bestNuc == '-') { bestBaseScore = assembly[pos].counts[4]; bestNuc = 4; for(j = 0; j < 4; ++j) { if(bestBaseScore < assembly[pos].counts[j]) { bestBaseScore = assembly[pos].counts[j]; bestNuc = j; } } bestNuc = tolower(bases[bestNuc]); } else { bestNuc = tolower(bestNuc); } bestScore = depthUpdate - assembly[pos].counts[5]; } else if(depthUpdate < bcd) { /* too low depth */ bestNuc = tolower(bestNuc); } /* determine base at current position */ /* if(bcd <= depthUpdate) { bestNuc = baseCall(bestNuc, aligned_assem->t[i], bestScore, depthUpdate, evalue, &assembly[pos]); } else { bestNuc = baseCall('-', aligned_assem->t[i], 0, 0, evalue, &assembly[pos]); } */ bestNuc = baseCall(bestNuc, aligned_assem->t[i], bestScore, depthUpdate, evalue, &assembly[pos]); aligned_assem->q[i] = bestNuc; if(bestNuc != '-') { depth += depthUpdate; depthVar += (depthUpdate * depthUpdate); ++aln_len; if(pos < t_len && aligned_assem->t[i] == toupper(bestNuc)) { ++coverScore; aligned_assem->s[i] = '|'; } else { aligned_assem->s[i] = '_'; } } else { aligned_assem->s[i] = '_'; } ++i; pos = assembly[pos].next; } } else { chunk = 0; } } /* update aligned_assem */ lock(excludeMatrix); aligned_assem->depth += depth; aligned_assem->depthVar += depthVar; aligned_assem->len = asm_len; aligned_assem->aln_len += aln_len; aligned_assem->cover += coverScore; --thread_wait; unlock(excludeMatrix); wait_atomic(thread_wait); } void fixVarOverflow(Assem *aligned_assem, Assembly *assembly, int t_len, int thread_num) { static volatile int Lock = 0, next, thread_wait = 0; volatile int *excludeMatrix = &Lock; int pos, end, chunk, depthUpdate; double var, depth, tmp; /* var(x) = E(x^2) - E(x)^2 = sum((x_i - E(x))^2) / n */ /* init */ var = 0; depth = (long double)(aligned_assem->depth) / t_len; chunk = 8112; lock(excludeMatrix); if(!thread_wait) { next = 0; thread_wait = thread_num; } unlock(excludeMatrix); /* get variance */ while(chunk) { lock(excludeMatrix); pos = next; if((next += chunk) < 0) { next = t_len; } unlock(excludeMatrix); /* call chunk */ if(pos < t_len) { end = pos + chunk; if(t_len < end) { end = t_len; chunk = 0; } while(pos < end) { depthUpdate = assembly[pos].counts[0] + assembly[pos].counts[1] + assembly[pos].counts[2] + assembly[pos].counts[3] + assembly[pos].counts[4] + assembly[pos].counts[5]; tmp = (depthUpdate - depth); var += tmp * tmp / t_len; ++pos; } } else { chunk = 0; } } lock(excludeMatrix); aligned_assem->var += var; --thread_wait; unlock(excludeMatrix); wait_atomic(thread_wait); } void * assemble_KMA(void *arg) { const char bases[6] = "ACGTN-"; static volatile int thread_wait = 0, thread_init = 0, thread_begin = 0; static volatile int mainTemplate = -2, next, Lock[3] = {0, 0, 0}; static int t_len, load, seq_in; static char *template_name; static HashMapCCI *template_index; volatile int *excludeIn = &Lock[0], *excludeOut = &Lock[1], *excludeMatrix = &Lock[2]; Assemble_thread *thread = arg; int i, minlen, aln_len, kmersize, sam, chunk, ef, template; int read_score, asm_len, nextTemplate, file_i, file_count, delta, status; int thread_num, mq, bcd, start, end, q_start, q_end; int stats[5], buffer[8], *qBoundPtr; short unsigned *counts; double score, scoreT, mrc, evalue; long double var, nucHighVar; char *s, *s_next; unsigned char *t, *q, *t_next, *q_next; FILE **files, *file, *xml_out; AlnScore alnStat; Assembly *assembly; FileBuff *frag_out; Assem *aligned_assem; Aln *aligned, *gap_align; Qseqs *qseq, *header; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; /* get input */ template = thread->template; file_count = thread->file_count; files = thread->files; xml_out = thread->xml_out; frag_out = thread->frag_out; aligned_assem = thread->aligned_assem; aligned = thread->aligned; gap_align = thread->gap_align; qseq = thread->qseq; header = thread->header; matrix = thread->matrix; points = thread->points; NWmatrices = thread->NWmatrices; delta = qseq->size; mq = thread->mq; minlen = thread->minlen; mrc = thread->mrc; scoreT = thread->scoreT; evalue = thread->evalue; bcd = thread->bcd; sam = thread->sam; ef = thread->ef; //spin = thread->spin; thread_num = thread->thread_num; seq_in = thread->seq_in; kmersize = thread->kmersize; if(template != -2) { wait_atomic(thread_begin); /* all assemblies done, signal threads to return */ if(template == -1) { lock(excludeMatrix); mainTemplate = template; unlock(excludeMatrix); return NULL; } /* Allocate assembly arrays */ lock(excludeMatrix); template_name = thread->template_name; template_index = thread->template_index; t_len = thread->t_len; load = (template_index->len != 0) ? 0 : 1; matrix->len = 0; seq_in = thread->seq_in; /* start threads */ aligned_assem->score = 0; aligned_assem->fragmentCountAln = 0; aligned_assem->readCountAln = 0; aligned_assem->cover = 0; aligned_assem->depth = 0; aligned_assem->depthVar = 0; aligned_assem->var = 0; aligned_assem->nucHighVar = 0; aligned_assem->maxDepth = 0; aligned_assem->snpSum = 0; aligned_assem->insertSum = 0; aligned_assem->deletionSum = 0; aligned_assem->t[0] = 0; aligned_assem->s[0] = 0; aligned_assem->q[0] = 0; aligned_assem->len = 0; aligned_assem->aln_len = 0; mainTemplate = template; thread_wait = thread_num; thread_init = thread_num; thread_begin = thread_num; unlock(excludeMatrix); template = -2; } do { while(template == mainTemplate) { usleep(100); } lock(excludeMatrix); template = mainTemplate; unlock(excludeMatrix); if(template == -1) { return NULL; } /* load index */ if(load) { hashMapCCI_load_thread(template_index, seq_in, t_len, kmersize, thread_num); } /* init matrix */ lock(excludeMatrix); if(matrix->len == 0) { matrix->len = t_len; if(matrix->size < (t_len << 1)) { matrix->size = (t_len << 1); free(matrix->assmb); matrix->assmb = smalloc(matrix->size * sizeof(Assembly)); } next = 0; } unlock(excludeMatrix); /* init in chunks of 8112 ~= 1 MB*/ chunk = 8112; while(chunk) { /* get next chunk */ lock(excludeMatrix); i = next; if((next += chunk) < 0) { next = t_len; } unlock(excludeMatrix); /* fill in chunk */ if(i < t_len) { end = i + chunk; if(t_len < end) { end = t_len; } assembly = matrix->assmb + i - 1; while(i != end) { counts = (++assembly)->counts; *counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; *++counts = 0; assembly->next = ++i; } if(t_len <= end) { /* circularize */ assembly->next = 0; chunk = 0; } } else { chunk = 0; } } /* wait for init to finish */ lock(excludeIn); --thread_init; unlock(excludeIn); wait_atomic(thread_init); /* load reads of this template */ file_i = 0; while(file_i < file_count) { //lockTime(excludeIn, spin); lock(excludeIn); file = files[file_i]; if(file != 0) { read_score = fread(buffer, sizeof(int), 8, file); if((nextTemplate = buffer[0]) == template) { /* load frag */ qseq->len = buffer[1]; stats[0] = buffer[2]; read_score = buffer[3]; stats[2] = buffer[4]; stats[3] = buffer[5]; header->len = buffer[6]; stats[4] = buffer[7]; if(qseq->size < qseq->len) { free(qseq->seq); qseq->size = qseq->len << 1; qseq->seq = smalloc(qseq->size); } if(header->size < header->len) { header->size = header->len + 1; free(header->seq); header->seq = smalloc(header->size); } sfread(qseq->seq, 1, qseq->len, file); sfread(header->seq, 1, header->len, file); unlock(excludeIn); if(delta < qseq->len) { delta = qseq->len << 1; free(aligned->t); free(aligned->s); free(aligned->q); free(gap_align->t); free(gap_align->s); free(gap_align->q); aligned->t = smalloc((delta + 1) << 1); aligned->s = smalloc((delta + 1) << 1); aligned->q = smalloc((delta + 1) << 1); gap_align->t = smalloc((delta + 1) << 1); gap_align->s = smalloc((delta + 1) << 1); gap_align->q = smalloc((delta + 1) << 1); } /* q-bound */ if(2 * sizeof(int) + 1 < header->len && header->seq[header->len - 2 * sizeof(int) - 1] == 0) { qBoundPtr = (int*) (header->seq + (header->len - 2 * sizeof(int))); q_start = *qBoundPtr; q_end = *++qBoundPtr; } else { q_start = 0; q_end = qseq->len; } /* Update assembly with read */ if(read_score || anker_rc(template_index, qseq->seq, qseq->len, q_start, q_end, points)) { /* Start with alignment */ if(stats[3] <= stats[2]) { stats[2] = 0; stats[3] = t_len; } alnStat = KMA(template_index, qseq->seq, qseq->len, q_start, q_end, aligned, gap_align, stats[2], MIN(t_len, stats[3]), mq, scoreT, points, NWmatrices); /* get read score */ aln_len = alnStat.len; start = alnStat.pos; end = start + aln_len - alnStat.tGaps; /* Get normed score check read coverage */ read_score = alnStat.score; if(minlen <= aln_len && mrcheck(mrc, alnStat, qseq->len, t_len)) { score = 1.0 * read_score / aln_len; } else { read_score = 0; score = 0; } if(0 < read_score && scoreT <= score) { stats[1] = read_score; stats[2] = start; stats[3] = end; if(t_len < end) { stats[3] -= t_len; } /* Update backbone and counts */ alnToMatPtr(matrix, aligned_assem, aligned, alnStat, t_len, stats[4]); /* Convert fragment */ q = qseq->seq; i = qseq->len + 1; while(--i) { *q = bases[*q]; ++q; } *q = 0; /* Save fragment */ if(frag_out) { lock(excludeOut); updateFrags(frag_out, qseq, header, template_name, stats); unlock(excludeOut); } if(sam) { header->seq[header->len - 1] = 0; samwrite(qseq, header, 0, template_name, aligned, stats); } if(xml_out) { hitXML(xml_out, template, header->seq, aligned, &alnStat, NWmatrices->rewards, stats[4]); } } else if(sam && !(sam & 2096)) { stats[1] = read_score; stats[2] = start; stats[3] = end; header->seq[header->len - 1] = 0; nibble2base(qseq->seq, qseq->len); if(read_score) { samwrite(qseq, header, 0, template_name, aligned, stats); } else { stats[4] |= 4; stats[1] = stats[4]; samwrite(qseq, header, 0, template_name, 0, stats); } } } else if(sam && !(sam & 2096)) { stats[4] |= 4; stats[1] = stats[4]; header->seq[header->len - 1] = 0; nibble2base(qseq->seq, qseq->len); samwrite(qseq, header, 0, template_name, 0, stats); } } else if(nextTemplate == -1) { if(template) { fclose(file); } else { kmaPipe(0, 0, file, &status); errno |= status; } files[file_i] = 0; unlock(excludeIn); ++file_i; } else if(nextTemplate < template) { /* Move pointer forward */ fseek(file, buffer[1] + buffer[6], SEEK_CUR); unlock(excludeIn); } else { /* Move pointer back */ fseek(file, (-8) * sizeof(int), SEEK_CUR); unlock(excludeIn); ++file_i; } } else { unlock(excludeIn); ++file_i; } } /* wait for last reads to align and update */ lock(excludeIn); --thread_wait; unlock(excludeIn); wait_atomic(thread_wait); /* collect consensus */ if(aligned_assem->score) { /* Pepare and make alignment on consensus */ asm_len = matrix->len; assembly = matrix->assmb; lock(excludeMatrix); if(aligned_assem->size <= asm_len) { aligned_assem->size = (asm_len + 1) << 1; free(aligned_assem->t); free(aligned_assem->s); free(aligned_assem->q); aligned_assem->t = smalloc(aligned_assem->size); aligned_assem->s = smalloc(aligned_assem->size); aligned_assem->q = smalloc(aligned_assem->size); } unlock(excludeMatrix); /* Call nucleotides for the consensus */ callConsensus(matrix, aligned_assem, template_index->seq, t_len, bcd, evalue, thread_num); if(ef) { /* overflow fix on variance */ lock(excludeMatrix); nucHighVar = aligned_assem->depth; nucHighVar /= t_len; var = aligned_assem->depthVar; var /= t_len; var -= (nucHighVar * nucHighVar); if(0 <= var) { aligned_assem->var = var; } unlock(excludeMatrix); if(var < 0) { fixVarOverflow(aligned_assem, assembly, t_len, thread_num); } /* get nucHighVar */ getExtendedFeatures(aligned_assem, matrix, template_index->seq, t_len, thread_num); } } else { asm_len = 0; } lock(excludeMatrix); --thread_begin; unlock(excludeMatrix); } while(thread->num != 0); /* Trim alignment on consensus */ if(aligned_assem->score && alnToMatPtr != &alnToMatDense) { t = aligned_assem->t; s = aligned_assem->s; q = aligned_assem->q; t_next = t; s_next = s; q_next = q; i = aligned_assem->len; asm_len = i++; while(--i) { if(*t_next == '-' && *q_next == '-') { --asm_len; ++t_next; ++s_next; ++q_next; } else { *t++ = *t_next++; *s++ = *s_next++; *q++ = *q_next++; } } *t = 0; *s = 0; *q = 0; aligned_assem->len = asm_len; } else { aligned_assem->t[asm_len] = 0; aligned_assem->s[asm_len] = 0; aligned_assem->q[asm_len] = 0; } return NULL; } genomicepidemiology-kma-091b8ffe66ac/index.c0000644000175000017500000004535514157033525020400 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include #include "compress.h" #include "decon.h" #include "hashmap.h" #include "hashmapkma.h" #include "index.h" #include "loadupdate.h" #include "makeindex.h" #include "pherror.h" #include "qualcheck.h" #include "stdstat.h" #include "updateindex.h" #include "valueshash.h" #include "version.h" static void helpMessage(int exeStatus) { FILE *helpOut; if(exeStatus == 0) { helpOut = stdout; } else { helpOut = stderr; } fprintf(helpOut, "# kma_index creates the databases needed to run KMA, from a list of fasta files given.\n"); fprintf(helpOut, "# Options are:\t\tDesc:\t\t\t\t\tDefault:\n"); fprintf(helpOut, "#\n"); fprintf(helpOut, "#\t-i\t\tInput/query file name (STDIN: \"--\")\tNone\n"); fprintf(helpOut, "#\t-o\t\tOutput file\t\t\t\tInput/template file\n"); fprintf(helpOut, "#\t-batch\t\tBatch input file\n"); fprintf(helpOut, "#\t-deCon\t\tFile with contamination (STDIN: \"--\")\tNone/False\n"); fprintf(helpOut, "#\t-batchD\t\tBatch decon file\n"); fprintf(helpOut, "#\t-t_db\t\tAdd to existing DB\t\t\tNone/False\n"); fprintf(helpOut, "#\t-k\t\tKmersize\t\t\t\t16\n"); fprintf(helpOut, "#\t-k_t\t\tKmersize for template identification\t16\n"); fprintf(helpOut, "#\t-k_i\t\tKmersize for indexing\t\t\t16\n"); fprintf(helpOut, "#\t-ML\t\tMinimum length of templates\t\tkmersize (16)\n"); fprintf(helpOut, "#\t-CS\t\tStart Chain size\t\t\t1 M\n"); fprintf(helpOut, "#\t-ME\t\tMega DB\t\t\t\t\tFalse\n"); fprintf(helpOut, "#\t-NI\t\tDo not dump *.index.b\t\t\tFalse\n"); fprintf(helpOut, "#\t-Sparse\t\tMake Sparse DB ('-' for no prefix)\tNone/False\n"); fprintf(helpOut, "#\t-ht\t\tHomology template\t\t\t1.0\n"); fprintf(helpOut, "#\t-hq\t\tHomology query\t\t\t\t1.0\n"); fprintf(helpOut, "#\t-and\t\tBoth homolgy thresholds\n#\t\t\thas to be reached\t\t\tor\n"); fprintf(helpOut, "#\t-nbp\t\tNo bias print\t\t\t\tFalse\n"); fprintf(helpOut, "#\t-v\t\tVersion\n"); fprintf(helpOut, "#\t-h\t\tShows this help message\n"); fprintf(helpOut, "#\n"); exit(exeStatus); } int index_main(int argc, char *argv[]) { int i, args, stop, filecount, deconcount, sparse_run, size, mapped_cont; int file_len, appender, prefix_len, MinLen, MinKlen; unsigned kmersize, kmerindex, megaDB, **Values; unsigned *template_lengths, *template_slengths, *template_ulengths; long unsigned initialSize, prefix, mask; double homQ, homT; char **inputfiles, *outputfilename, *templatefilename, **deconfiles; char *to2Bit, *line, *exeBasic; unsigned char *update; FILE *inputfile, *out; time_t t0, t1; HashMap *templates; HashMapKMA *finalDB; if (argc == 1) { fprintf(stderr, "# Too few arguments handed.\n"); helpMessage(-1); } else if(sizeof(long unsigned) != 8) { fprintf(stderr, "Need a 64-bit system.\n"); exit(1); } /* set defaults */ initialSize = 1048576; templates = 0; kmersize = 16; kmerindex = 16; sparse_run = 0; appender = 0; MinLen = 0; MinKlen = 1; prefix_len = 0; prefix = 0; homQ = 1; homT = 1; cmp = &cmp_or; template_ulengths = 0; template_slengths = 0; filecount = 0; deconcount = 0; outputfilename = 0; templatefilename = 0; megaDB = 0; inputfiles = smalloc(sizeof(char*)); deconfiles = smalloc(sizeof(char*)); to2Bit = smalloc(384); /* set to2Bit */ for(i = 0; i < 384; ++i) { to2Bit[i] = 8; } to2Bit += 128; to2Bit['\n'] = 16; to2Bit['A'] = 0; to2Bit['C'] = 1; to2Bit['G'] = 2; to2Bit['T'] = 3; to2Bit['N'] = 4; to2Bit['a'] = 0; to2Bit['c'] = 1; to2Bit['g'] = 2; to2Bit['t'] = 3; to2Bit['n'] = 4; to2Bit['R'] = 0; to2Bit['Y'] = 1; to2Bit['S'] = 2; to2Bit['W'] = 3; to2Bit['K'] = 2; to2Bit['M'] = 0; to2Bit['B'] = 1; to2Bit['D'] = 0; to2Bit['H'] = 3; to2Bit['V'] = 2; to2Bit['X'] = 4; to2Bit['r'] = 0; to2Bit['y'] = 1; to2Bit['s'] = 2; to2Bit['w'] = 3; to2Bit['k'] = 2; to2Bit['m'] = 0; to2Bit['b'] = 1; to2Bit['d'] = 0; to2Bit['h'] = 3; to2Bit['v'] = 2; to2Bit['x'] = 4; /* Future RNA encoding */ to2Bit['U'] = 3; to2Bit['u'] = 3; /* PARSE COMMAND LINE OPTIONS */ args = 1; while(args < argc) { if(strcmp(argv[args], "-i") == 0) { stop = 0; ++args; while(stop == 0 && args < argc) { if(strncmp(argv[args], "-", 1) != 0 || strcmp(argv[args], "--") == 0) { ++filecount; inputfiles = realloc(inputfiles, filecount * sizeof(char*)); if(inputfiles == NULL) { ERROR(); } inputfiles[filecount - 1] = argv[args]; ++args; } else { stop = 1; } } --args; } else if(strcmp(argv[args], "-o") == 0) { ++args; if(args < argc) { outputfilename = smalloc(strlen(argv[args]) + 64); strcpy(outputfilename, argv[args]); } } else if(strcmp(argv[args], "-deCon") == 0) { stop = 0; ++args; while(stop == 0 && args < argc) { if(strncmp(argv[args], "-", 1) != 0 || strcmp(argv[args], "--") == 0) { deconfiles = realloc(deconfiles, (deconcount + 1) * sizeof(char*)); if(deconfiles == NULL) { ERROR(); } deconfiles[deconcount] = argv[args]; ++deconcount; ++args; } else { stop = 1; } } if(deconcount == 0) { fprintf(stderr, "No deCon file specified.\n"); exit(1); } --args; } else if(strcmp(argv[args], "-t_db") == 0) { ++args; if(args < argc) { templatefilename = malloc(strlen(argv[args]) + 64); if(!templatefilename) { ERROR(); } strcpy(templatefilename, argv[args]); } } else if(strcmp(argv[args], "-k") == 0) { ++args; if(args < argc) { kmersize = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid kmersize parsed\n"); exit(1); } else if(kmersize == 0) { fprintf(stderr, "# Invalid kmersize parsed, using default\n"); kmersize = 16; } else if(kmersize > 31) { fprintf(stderr, "# Invalid kmersize parsed, max size is 31\n"); exit(1); } kmerindex = kmersize; } } else if(strcmp(argv[args], "-k_t") == 0) { ++args; if(args < argc) { kmersize = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid kmersize parsed\n"); exit(1); } else if(kmersize == 0) { fprintf(stderr, "# Invalid kmersize parsed, using default\n"); kmersize = 16; } else if(kmersize > 31) { fprintf(stderr, "# Invalid kmersize parsed, max size is 31\n"); exit(1); } } } else if(strcmp(argv[args], "-k_i") == 0) { ++args; if(args < argc) { kmerindex = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid kmersize parsed\n"); exit(1); } else if(kmerindex == 0) { fprintf(stderr, "# Invalid kmersize parsed, using default\n"); kmerindex = 16; } else if(kmerindex > 31) { fprintf(stderr, "# Invalid kmersize parsed, max size is 31\n"); exit(1); } } } else if(strcmp(argv[args], "-CS") == 0) { ++args; if(args < argc) { size = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid start size parsed\n"); exit(1); } initialSize = pow(2, ceil(log(size)/log(2))) + 0.5; initialSize *= 1048576; if(initialSize == 0) { fprintf(stderr, "# Invalid Chain Size parsed, using default\n"); initialSize = 1048576; } } } else if(strcmp(argv[args], "-and") == 0) { cmp = &cmp_and; } else if(strcmp(argv[args], "-ML") == 0) { ++args; if(args < argc) { MinLen = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid minimum length parsed\n"); exit(1); } else if(MinLen <= 0) { fprintf(stderr, "# Invalid minimum length parsed, using default\n"); MinLen = 0; } } } else if(strcmp(argv[args], "-hq") == 0) { ++args; if(args < argc) { homQ = strtod(argv[args], &exeBasic); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-hq\".\n"); exit(1); } else if(homQ < 0) { fprintf(stderr, "Invalid -hq\n"); homQ = 1.0; } } } else if(strcmp(argv[args], "-ht") == 0) { ++args; if(args < argc) { homT = strtod(argv[args], &exeBasic); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-ht\".\n"); exit(1); } else if(homT < 0) { fprintf(stderr, "Invalid -hq\n"); homT = 1.0; } } } else if(strcmp(argv[args], "-batch") == 0) { ++args; if(args < argc) { inputfile = sfopen(argv[args], "rb"); fseek(inputfile, 0, SEEK_END); size = ftell(inputfile) + 1; rewind(inputfile); ++filecount; inputfiles = realloc(inputfiles, filecount * sizeof(char*)); if(!inputfiles) { ERROR(); } inputfiles[filecount - 1] = malloc(size); if(!inputfiles[filecount - 1]) { ERROR(); } /* get number of file */ sfread(inputfiles[filecount - 1], 1, size - 1, inputfile); fclose(inputfile); i = size; size = 0; line = inputfiles[filecount - 1]; while(--i) { if(line[i] == '\n') { size++; while(isspace(line[i])) { line[i] = 0; --i; } } } --size; inputfiles = realloc(inputfiles, (filecount + size) * sizeof(char*)); if(!inputfiles) { ERROR(); } for(i = size; i; --i) { while(*line != 0) { ++line; } while(*line == 0) { ++line; } inputfiles[filecount] = line; ++filecount; } } } else if(strcmp(argv[args], "-batchD") == 0) { ++args; if(args < argc) { inputfile = sfopen(argv[args], "rb"); fseek(inputfile, 0, SEEK_END); size = ftell(inputfile) + 1; rewind(inputfile); ++deconcount; deconfiles = realloc(deconfiles, deconcount * sizeof(char*)); if(!inputfiles) { ERROR(); } deconfiles[deconcount - 1] = malloc(size); if(!deconfiles[deconcount - 1]) { ERROR(); } /* get number of file */ sfread(deconfiles[deconcount - 1], 1, size - 1, inputfile); fclose(inputfile); i = size; size = 0; line = deconfiles[deconcount - 1]; while(--i) { if(line[i] == '\n') { size++; while(isspace(line[i])) { line[i] = 0; --i; } } } --size; deconfiles = realloc(deconfiles, (deconcount + size) * sizeof(char*)); if(!inputfiles) { ERROR(); } for(i = size; i; --i) { while(*line != 0) { ++line; } while(*line == 0) { ++line; } deconfiles[deconcount] = line; ++deconcount; } } } else if(strcmp(argv[args], "-Sparse") == 0) { sparse_run = 1; ++args; if(args < argc) { if(strcmp(argv[args], "-") == 0) { prefix_len = 0; prefix = 1; } else { prefix_len = strlen(argv[args]); prefix = 0; update = (unsigned char *) argv[args]; for(i = 0; i < prefix_len; ++i) { prefix = (prefix << 2) | to2Bit[update[i]]; if(to2Bit[update[i]] > 3) { fprintf(stderr, "Invalid prefix.\n"); exit(1); } } if(prefix_len == 0) { fprintf(stderr, "Invalid prefix.\n"); exit(1); } } } } else if(strcmp(argv[args], "-ME") == 0) { megaDB = 1; } else if(strcmp(argv[args], "-NI") == 0) { } else if(strcmp(argv[args], "-nbp") == 0) { biasPrintPtr = &biasNoPrint; } else if(strcmp(argv[args], "-v") == 0) { fprintf(stdout, "KMA_index-%s\n", KMA_VERSION); exit(0); } else if(strcmp(argv[args], "-h") == 0) { helpMessage(0); } else { fprintf(stderr, "# Invalid option:\t%s\n", argv[args]); fprintf(stderr, "# Printing help message:\n"); helpMessage(1); } ++args; } /* check for sufficient input */ if(filecount == 0 && deconcount == 0) { fprintf(stderr, "No inputfiles defined.\n"); helpMessage(-1); } else if(filecount == 0 && deconcount != 0 && templatefilename == 0) { fprintf(stderr, "Nothing to update.\n"); exit(0); } else if(outputfilename == 0 && templatefilename != 0) { outputfilename = smalloc((strlen(templatefilename) + 64)); strcpy(outputfilename, templatefilename); } else if(outputfilename == 0 && filecount != 0) { outputfilename = smalloc((strlen(*inputfiles) + 64)); strcpy(outputfilename, *inputfiles); } else if(outputfilename == 0) { fprintf(stderr, "Output destination not defined.\n"); helpMessage(-1); } file_len = strlen(outputfilename); mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); if(megaDB) { initialSize = mask + 1; } else if(initialSize >= (mask + 1)) { initialSize = (mask + 1); megaDB = 1; } /* load DB */ if(templatefilename != 0) { /* load */ fprintf(stderr, "# Loading database: %s\n", outputfilename); finalDB = smalloc(sizeof(HashMapKMA)); kmerindex = load_DBs(templatefilename, outputfilename, &template_lengths, &template_ulengths, &template_slengths, finalDB); kmersize = finalDB->kmersize; mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); prefix = finalDB->prefix; prefix_len = finalDB->prefix_len; /* determine params based on loaded DB */ if(prefix_len == 0 && prefix == 0) { sparse_run = 0; } else { sparse_run = 1; } if(finalDB->mask == finalDB->size) { megaDB = 1; initialSize = finalDB->mask + 1; } else if(megaDB == 0) { initialSize = finalDB->size + 1; } appender = 1; } else { finalDB = 0; appender = 0; } /* function pointers */ hashMap_add = &hashMap_addKMA; hashMapGet = &hashMapGetValue; addCont = &hashMap_addCont; if(finalDB == 0 || finalDB->DB_size < USHRT_MAX) { updateValuePtr = &updateShortValue; valuesKeyPtr = &huValuesKey; cmpValuesPtr = &cmpHuValues; valuesSize = &huSize; } else { updateValuePtr = &updateValue; valuesKeyPtr = &valuesKey; cmpValuesPtr = &cmpValues; valuesSize = &uSize; } if(sparse_run) { update_DB = &updateDBs_sparse; updateAnnotsPtr = &updateAnnots_sparse; if(prefix_len == 0) { prefix = 1; } } else { update_DB = &updateDBs; updateAnnotsPtr = &updateAnnots; } if(prefix_len != 0) { deConNode_ptr = &deConNode_sparse; } else { deConNode_ptr = &deConNode; } if(megaDB) { hashMap_add = &megaMap_addKMA; hashMapGet = &megaMap_getValue; addCont = &megaMap_addCont; } /* set homology check */ if(MinLen > (kmersize + prefix_len + 1)) { MinKlen = 2 * (MinLen - kmersize - prefix_len + 1); for(i = 0; i < prefix_len; ++i) { MinKlen /= 4; } } else { MinLen = MAX(kmersize, kmerindex); } if(homT < 1) { QualCheck = &templateCheck; } else if(homQ < 1) { QualCheck = &queryCheck; } else { QualCheck = &lengthCheck; } /* update DBs */ if(filecount != 0) { if(finalDB) { /* convert */ templates = hashMapKMA_openChains(finalDB); } else { /* create */ templates = hashMap_initialize(initialSize, kmersize); template_lengths = smalloc(1024 * sizeof(unsigned));; if(sparse_run) { templates->prefix = prefix; templates->prefix_len = prefix_len; template_slengths = smalloc(1024 * sizeof(unsigned)); template_ulengths = smalloc(1024 * sizeof(unsigned)); *template_lengths = kmerindex; *template_slengths = 1024; *template_ulengths = 1024; } else { template_slengths = 0; template_ulengths = 0; *template_lengths = 1024; } } fprintf(stderr, "# Indexing databases.\n"); t0 = clock(); makeDB(templates, kmerindex, inputfiles, filecount, outputfilename, appender, to2Bit, MinLen, MinKlen, homQ, homT, &template_lengths, &template_ulengths, &template_slengths); t1 = clock(); fprintf(stderr, "#\n# Total time used for DB indexing: %.2f s.\n#\n", difftime(t1, t0) / 1000000); free(template_lengths); free(template_slengths); free(template_ulengths); /* compress db */ fprintf(stderr, "# Compressing templates\n"); t0 = clock(); if(templates->DB_size < USHRT_MAX) { valuesKeyPtr = &huValuesKey; cmpValuesPtr = &cmpHuValues; valuesSize = &huSize; } else { valuesKeyPtr = &valuesKey; cmpValuesPtr = &cmpValues; valuesSize = &uSize; } strcat(outputfilename, ".comp.b"); out = sfopen(outputfilename, "wb+"); if(templates->table != 0) { finalDB = compressKMA_DB(templates, out); } else { finalDB = compressKMA_megaDB(templates, out); } fclose(out); outputfilename[file_len] = 0; free(templates); fprintf(stderr, "# Template database created.\n"); t1 = clock(); fprintf(stderr, "#\n# Total time used for DB compression: %.2f s.\n#\n", difftime(t1, t0) / 1000000); } else { ++finalDB->size; } /* decontaminate */ if(deconcount != 0) { /* open values */ fprintf(stderr, "# Openning values\n"); if(!finalDB) { strcat(outputfilename, ".comp.b"); out = sfopen(outputfilename, "rb"); finalDB = smalloc(sizeof(HashMapKMA)); if(hashMapKMAload(finalDB, out)) { fprintf(stderr, "Wrong format of DB\n"); exit(1); } fclose(out); outputfilename[file_len] = 0; } Values = hashMapKMA_openValues(finalDB); /* get decontamination info */ fprintf(stderr, "# Adding decontamination information\n"); t0 = clock(); mapped_cont = deConDB(finalDB, deconfiles, deconcount, to2Bit, Values); fprintf(stderr, "# Contamination information added.\n"); fprintf(stderr, "# %d kmers mapped to the DB.\n", mapped_cont); fprintf(stderr, "# Contamination mapped to %f %% of the DB.\n", 100.0 * mapped_cont / finalDB->n); /* compress DB */ fprintf(stderr, "# Compressing templates\n"); if(finalDB->DB_size < USHRT_MAX) { valuesKeyPtr = &huValuesKey; cmpValuesPtr = &cmpHuValues; valuesSize = &huSize; } else { valuesKeyPtr = &valuesKey; cmpValuesPtr = &cmpValues; valuesSize = &uSize; } if((finalDB->size - 1) != finalDB->mask) { compressKMA_deconDB(finalDB, Values); } else { compressKMA_deconMegaDB(finalDB, Values); } t1 = clock(); fprintf(stderr, "#\n# Total time used for DB decontamination: %.2f s.\n#\n", difftime(t1, t0) / 1000000); /* dump DB */ fprintf(stderr, "# Dumping DB.\n"); strcat(outputfilename, ".decon.comp.b"); out = sfopen(outputfilename, "wb"); outputfilename[file_len] = 0; if((finalDB->size - 1) != mask) { hashMapKMA_dump(finalDB, out); } else { megaMapKMA_dump(finalDB, out); } fclose(out); outputfilename[file_len] = 0; } return 0; } genomicepidemiology-kma-091b8ffe66ac/sparse.c0000644000175000017500000005701014157033525020555 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "ankers.h" #include "compkmers.h" #include "filebuff.h" #include "hashmapkma.h" #include "hashtable.h" #include "kmapipe.h" #include "kmmap.h" #include "pherror.h" #include "runinput.h" #include "savekmers.h" #include "seqparse.h" #include "sparse.h" #include "stdnuc.h" #include "stdstat.h" #ifdef _WIN32 typedef int key_t; #define ftok(charPtr, integer) (0) #define shmget(key, size, permission) ((size != 0) ? (-1) : (-key)) #define shmat(shmid, NULL_Ptr, integer) (NULL) #else #include #include #endif int translateToKmersAndDump(long unsigned *Kmers, int n, int max, unsigned char *qseq, int seqlen, int kmersize, long unsigned mask, long unsigned prefix, int prefix_len, FILE *out) { int i, end, rc; long unsigned key; key = 0; if(prefix_len) { for(rc = 0; rc < 2; ++rc) { if(rc) { strrc(qseq, seqlen); } i = 0; while(i < seqlen) { end = charpos(qseq, 4, i, seqlen); if(end == -1) { end = seqlen; } if(i < end - kmersize - prefix_len) { key = makeKmer(qseq, i, prefix_len - 1); i += (prefix_len - 1); end -= kmersize; } else { i = end + 1; } while(i < end) { key = ((key << 2) | qseq[i]) & mask; ++i; if(key == prefix) { Kmers[n] = makeKmer(qseq, i, kmersize); ++n; if(n == max) { sfwrite(Kmers, sizeof(long unsigned), n, out); n = 0; } } } i = end + kmersize + 1; } } } else { for(rc = 0; rc < 2; ++rc) { if(rc) { strrc(qseq, seqlen); } i = 0; while(i < seqlen) { end = charpos(qseq, 4, i, seqlen); if(end == -1) { end = seqlen; } key = makeKmer(qseq, i, kmersize - 1); while(i < end) { key = ((key << 2) | qseq[i]) & mask; ++i; Kmers[n] = key; ++n; if(n == max) { sfwrite(Kmers, sizeof(long unsigned), n, out); n = 0; } } i = end + kmersize + 1; } } } return n; } char ** load_DBs_Sparse(char *templatefilename, unsigned **template_lengths, unsigned **template_ulengths, unsigned shm) { /* load DBs needed for KMA */ int file_len, shmid, DB_size; long unsigned i, j, file_size; char **template_names; FILE *DB_file; key_t key; /* Open DB */ file_len = strlen(templatefilename); strcat(templatefilename, ".length.b"); templatefilename[file_len + 9] = 0; DB_file = sfopen(templatefilename, "rb"); /* allocate DBs */ sfread(&DB_size, sizeof(int), 1, DB_file); if(shm & 4) { fseek(DB_file, 0, SEEK_END); file_size = ftell(DB_file) - sizeof(int); key = ftok(templatefilename, 'l'); shmid = shmget(key, file_size, 0666); if(shmid < 0) { fprintf(stderr, "No shared length\n"); exit(errno); } else { *template_lengths = shmat(shmid, NULL, 0); } *template_lengths += DB_size; *template_ulengths = *template_lengths + DB_size; } else { *template_lengths = smalloc(DB_size * sizeof(int)); *template_ulengths = smalloc(DB_size * sizeof(int)); /* load lengths */ fseek(DB_file, DB_size * sizeof(int), SEEK_CUR); i = fread(*template_lengths, sizeof(int), DB_size, DB_file); i += fread(*template_ulengths, sizeof(int), DB_size, DB_file); if(!i) { fprintf(stderr, "DB needs to sparse indexed, to run a sparse mapping.\n"); exit(1); } } templatefilename[file_len] = 0; fclose(DB_file); /* load names */ strcat(templatefilename, ".name"); templatefilename[file_len + 5] = 0; DB_file = sfopen(templatefilename, "rb"); /* get size of file */ fseek(DB_file, 0, SEEK_END); file_size = ftell(DB_file); template_names = malloc(DB_size * sizeof(char*)); if(!template_names) { ERROR(); } /* load file */ if(shm & 16) { key = ftok(templatefilename, 'n'); shmid = shmget(key, file_size, 0666); if(shmid < 0) { fprintf(stderr, "No shared name\n"); ERROR(); } else { template_names[0] = shmat(shmid, NULL, 0); } for(i = 0, j = 2; j < DB_size; ++i) { if(template_names[0][i] == 0) { template_names[j] = template_names[0] + i + 1; ++j; } } } else { rewind(DB_file); template_names[0] = malloc(file_size); if(!template_names[0]) { ERROR(); } sfread(template_names[0], 1, file_size, DB_file); template_names[0][file_size - 1] = 0; template_names[1] = template_names[0]; for(i = 0, j = 2; j < DB_size; ++i) { if(template_names[0][i] == '\n') { template_names[0][i] = 0; template_names[j] = template_names[0] + i + 1; ++j; } } } templatefilename[file_len] = 0; fclose(DB_file); return template_names; } void save_kmers_sparse(const HashMapKMA *templates, HashMap_kmers *foundKmers, CompKmers *compressor) { /* save_kmers find ankering k-mers the in query sequence, and is the time determining step */ int i; for(i = 0; i < compressor->n; ++i) { if(hashMap_get(templates, compressor->kmers[i])) { hashMap_kmers_CountIndex(foundKmers, compressor->kmers[i]); } } } void run_input_sparse(const HashMapKMA *templates, char **inputfiles, int fileCount, int minPhred, int minQ, int fiveClip, int threeClip, int kmersize, char *trans, const double *prob, FILE *out) { int FASTQ, fileCounter, phredScale, phredCut, start, end; char *filename; unsigned char *seq; Qseqs *qseq, *qual; FileBuff *inputfile; CompKmers *Kmers; Kmers = smalloc(sizeof(CompKmers)); allocCompKmers(Kmers, 1024); qseq = setQseqs(1024); qual = setQseqs(1024); inputfile = setFileBuff(CHUNK); for(fileCounter = 0; fileCounter < fileCount; ++fileCounter) { filename = (char*)(inputfiles[fileCounter]); /* determine filetype and open it */ if((FASTQ = openAndDetermine(inputfile, filename)) & 3) { fprintf(stderr, "%s\t%s\n", "# Reading inputfile: ", filename); } /* parse the file */ Kmers->n = 0; if(FASTQ & 1) { /* get phred scale */ phredScale = getPhredFileBuff(inputfile); fprintf(stderr, "# Phred scale:\t%d\n", phredScale); phredCut = phredScale + minPhred; /* parse reads */ while(FileBuffgetFqSeq(inputfile, qseq, qual, trans)) { /* trim */ seq = qual->seq; start = fiveClip; end = qseq->len - 1 - threeClip; end = end < 0 ? 0 : end; while(end >= 0 && seq[end] < phredCut) { --end; } ++end; while(start < end && seq[start] < phredCut) { ++start; } qseq->len = end - start; /* print */ if(qseq->len > kmersize && minQ <= eQual(seq + start, qseq->len, minQ, prob - phredScale)) { /* translate to kmers */ Kmers->n = translateToKmersAndDump(Kmers->kmers, Kmers->n, Kmers->size, qseq->seq + start, qseq->len, kmersize, templates->mask, templates->prefix, templates->prefix_len, out); } } if(Kmers->n) { sfwrite(Kmers->kmers, sizeof(long unsigned), Kmers->n, out); Kmers->n = 0; } } else if(FASTQ & 2) { while(FileBuffgetFsaSeq(inputfile, qseq, trans)) { if(qseq->len > kmersize) { /* translate to kmers */ Kmers->n = translateToKmersAndDump(Kmers->kmers, Kmers->n, Kmers->size, qseq->seq, qseq->len, kmersize, templates->mask, templates->prefix, templates->prefix_len, out); } } if(Kmers->n) { sfwrite(Kmers->kmers, sizeof(long unsigned), Kmers->n, out); Kmers->n = 0; } } if(FASTQ & 4) { gzcloseFileBuff(inputfile); } else { closeFileBuff(inputfile); } } free(Kmers->kmers); free(Kmers); destroyQseqs(qseq); destroyQseqs(qual); destroyFileBuff(inputfile); } int save_kmers_sparse_batch(char *templatefilename, char *outputfilename, char *exePrev, int ID_t, double evalue, char ss, unsigned shm) { int i, file_len, stop, template, status, contamination, score_add, deCon; unsigned *Scores, *w_Scores, *SearchList; unsigned *template_lengths, *template_ulengths; long unsigned Ntot, score, tmp_score, score_tot_add; long unsigned *Scores_tot, *w_Scores_tot; char **template_names; double expected, q_value, p_value, etta, depth, cover, query_cover; double tot_depth, tot_cover, tot_query_cover, tmp_depth, tmp_cover; double tmp_expected, tmp_q, tmp_p; FILE *inputfile, *templatefile, *sparse_out; time_t t0, t1; HashMapKMA *templates; HashMap_kmers *foundKmers; HashTable *kmerList, *deConTable, *node, *prev, **Collecter; Hit Nhits, w_Nhits; CompKmers *Kmers; /* here */ /* split input up */ /* open pipe */ //inputfile = popen(exePrev, "r"); status = 0; inputfile = kmaPipe(exePrev, "rb", 0, 0); if(!inputfile) { ERROR(); } /* Load hashMap */ t0 = clock(); file_len = strlen(templatefilename); if((deCon = deConPrintPtr == deConPrint)) { strcat(templatefilename, ".decon.comp.b"); } else { strcat(templatefilename, ".comp.b"); } templatefile = sfopen(templatefilename, "rb" ); templates = smalloc(sizeof(HashMapKMA)); hashMap_get = &hashMap_getGlobal; if((shm & 1) || (deCon && (shm & 2))) { hashMapKMA_load_shm(templates, templatefile, templatefilename); } else if(shm & 32) { hashMapKMAmmap(templates, templatefile); } else { if(hashMapKMA_load(templates, templatefile, templatefilename)) { fprintf(stderr, "Wrong format of DB.\n"); exit(1); } } fclose(templatefile); templatefilename[file_len] = 0; /* load template attributes */ template_names = load_DBs_Sparse(templatefilename, &template_lengths, &template_ulengths, shm); /* open output file */ if(strcmp(outputfilename, "--") == 0) { sparse_out = stdout; } else { file_len = strlen(outputfilename); strcat(outputfilename, ".spa"); sparse_out = sfopen(outputfilename, "w"); outputfilename[file_len] = 0; } if(!sparse_out) { ERROR(); } /* set hashMap for found kmers */ foundKmers = smalloc(sizeof(HashMap_kmers)); /* foundKmers->size = templates->n; */ foundKmers->size = 1024; i = templates->DB_size; while(--i) { if(foundKmers->size < template_lengths[i]) { foundKmers->size = template_lengths[i]; } } hashMap_kmers_initialize(foundKmers, foundKmers->size); t1 = clock(); fprintf(stderr, "#\n# Total time used for DB loading: %.2f s.\n#\n", difftime(t1, t0) / 1000000); t0 = clock(); fprintf(stderr, "# Finding k-mers\n"); Kmers = smalloc(sizeof(CompKmers)); allocCompKmers(Kmers, 1024); Ntot = 0; /* count kmers */ while((Kmers->n = fread(Kmers->kmers, sizeof(long unsigned), Kmers->size, inputfile))) { Ntot += Kmers->n; save_kmers_sparse(templates, foundKmers, Kmers); } kmaPipe(0, 0, inputfile, &status); if(kmaPipe == &kmaPipeFork) { t1 = clock(); fprintf(stderr, "#\n# Total time used to identify k-mers in query: %.2f s.\n#\n", difftime(t1, t0) / 1000000); } else { fprintf(stderr, "# k-mers in query identified\n#\n"); } t0 = clock(); fprintf(stderr, "# Finding best matches and output results.\n"); Scores = calloc(templates->DB_size, sizeof(unsigned)); Scores_tot = calloc(templates->DB_size, sizeof(long unsigned)); SearchList = malloc(templates->DB_size * sizeof(unsigned)); if(!Scores || !Scores_tot || !SearchList) { ERROR(); } etta = 1.0e-6; expected = 0; q_value = 0; p_value = 0; fprintf(sparse_out, "#Template\tNum\tScore\tExpected\tTemplate_length\tQuery_Coverage\tTemplate_Coverage\tDepth\ttot_query_Coverage\ttot_template_Coverage\ttot_depth\tq_value\tp_value\n"); stop = 0; if(deCon) { /* start by removing contamination and collect scores */ contamination = templates->DB_size; Collecter = collect_Kmers_deCon(templates, Scores, Scores_tot, foundKmers, &Nhits, contamination); kmerList = Collecter[0]; deConTable = Collecter[1]; free(Collecter); fprintf(stderr, "# Total number of matches: %lu of %lu kmers\n", Nhits.tot, Ntot); /* copy scores */ w_Scores = smalloc(templates->DB_size * sizeof(unsigned)); w_Scores_tot = smalloc(templates->DB_size * sizeof(long unsigned)); for(i = 0; i < templates->DB_size; ++i) { w_Scores[i] = Scores[i]; w_Scores_tot[i] = Scores_tot[i]; if(Scores[i] == 0) { SearchList[i] = 0; } else { SearchList[i] = 1; } } w_Nhits.n = Nhits.n; w_Nhits.tot = Nhits.tot; if(w_Scores[contamination] > 0 || w_Scores_tot[contamination] > 0) { fprintf(stderr, " Failed at removing contamination\n"); exit(1); } SearchList[contamination] = 0; /* get best matches */ while(! stop) { /* get best match, depth first then coverage */ depth = 0; cover = 0; score = 0; template = 0; if(ss == 'q') { for(i = 0; i < templates->DB_size; ++i) { if(SearchList[i] && w_Scores_tot[i] >= score) { tmp_cover = 100.0 * w_Scores[i] / template_ulengths[i]; if(tmp_cover >= ID_t) { tmp_score = w_Scores_tot[i]; tmp_depth = 1.0 * w_Scores_tot[i] / template_lengths[i]; if(tmp_score > score || (tmp_cover > cover || (tmp_cover == cover && (tmp_depth > depth || (tmp_depth == depth && template_ulengths[i] > template_ulengths[template]))))) { /* calculate p_value */ tmp_expected = 1.0 * (Nhits.tot - w_Scores_tot[i]) * template_ulengths[i] / (templates->n - template_ulengths[i] + etta); tmp_q = (tmp_score - tmp_expected) * (tmp_score - tmp_expected) / (tmp_score + tmp_expected); tmp_p = p_chisqr(tmp_q); if(tmp_p <= evalue && tmp_score > tmp_expected) { score = tmp_score; cover = tmp_cover; depth = tmp_depth; template = i; expected = tmp_expected; p_value = tmp_p; q_value = tmp_q; } else { SearchList[i] = 0; } } } else { SearchList[i] = 0; } } } } else if (ss == 'd') { for(i = 0; i < templates->DB_size; ++i) { if(SearchList[i]) { tmp_cover = 100.0 * w_Scores[i] / template_ulengths[i]; if(tmp_cover >= ID_t) { tmp_score = w_Scores_tot[i]; tmp_depth = 1.0 * w_Scores_tot[i] / template_lengths[i]; if(tmp_depth > depth || (tmp_depth == depth && (tmp_cover > cover || (tmp_cover == cover && (tmp_score > score || (tmp_score == score && template_ulengths[i] > template_ulengths[template])))))) { /* calculate p_value */ tmp_expected = 1.0 * (Nhits.tot - w_Scores_tot[i]) * template_ulengths[i] / (templates->n - template_ulengths[i] + etta); tmp_q = (tmp_score - tmp_expected) * (tmp_score - tmp_expected) / (tmp_score + tmp_expected); tmp_p = p_chisqr(tmp_q); if(tmp_p <= evalue && tmp_score > tmp_expected) { score = tmp_score; cover = tmp_cover; depth = tmp_depth; template = i; expected = tmp_expected; p_value = tmp_p; q_value = tmp_q; } else { SearchList[i] = 0; } } } else { SearchList[i] = 0; } } } } else { for(i = 0; i < templates->DB_size; ++i) { if(SearchList[i]) { tmp_cover = 100.0 * w_Scores[i] / template_ulengths[i]; if(tmp_cover >= ID_t) { tmp_score = w_Scores_tot[i]; tmp_depth = 1.0 * w_Scores_tot[i] / template_lengths[i]; if(tmp_cover > cover || (tmp_cover == cover && (tmp_depth > depth || (tmp_depth == depth && (tmp_score > score || (tmp_score == score && template_ulengths[i] > template_ulengths[template])))))) { /* calculate p_value */ tmp_expected = 1.0 * (Nhits.tot - w_Scores_tot[i]) * template_ulengths[i] / (templates->n - template_ulengths[i] + etta); tmp_q = (tmp_score - tmp_expected) * (tmp_score - tmp_expected) / (tmp_score + tmp_expected); tmp_p = p_chisqr(tmp_q); if(tmp_p <= evalue && tmp_score > tmp_expected) { score = tmp_score; cover = tmp_cover; depth = tmp_depth; template = i; expected = tmp_expected; p_value = tmp_p; q_value = tmp_q; } else { SearchList[i] = 0; } } } else { SearchList[i] = 0; } } } } /* validate best match */ if(cover && cover >= ID_t) { /* with draw contamination k-mers matching this template */ score_add = 0; score_tot_add = 0; if(deConTable != 0) { prev = 0; node = deConTable; while(node != 0) { if(intpos_bin(node->value, template) != -1) { ++score_add; score_tot_add += node->key; if(prev == 0) { deConTable = node->next; free(node); free(node->value); node = deConTable; } else { prev->next = node->next; free(node); free(node->value); node = prev->next; } } else { prev = node; node = node->next; } } } /* Calculate new attributes */ query_cover = 100.0 * (w_Scores_tot[template] + score_tot_add) / Ntot; cover = 100.0 * (w_Scores[template] + score_add) / template_ulengths[template]; depth = 1.0 * (w_Scores_tot[template] + score_tot_add) / template_lengths[template]; /* calc tot values */ tot_cover = 100.0 * (Scores[template] + score_add) / template_ulengths[template]; tot_depth = 1.0 * (Scores_tot[template] + score_tot_add) / template_lengths[template]; tot_query_cover = 100.0 * (Scores_tot[template] + score_tot_add) / Ntot; /* output results */ fprintf(sparse_out, "%s\t%d\t%lu\t%d\t%d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%f\t%e\n", template_names[template], template, score, (int) expected, template_lengths[template], query_cover, cover, depth, tot_query_cover, tot_cover, tot_depth, q_value, p_value); /* update scores */ kmerList = withDraw_Kmers(w_Scores, w_Scores_tot, kmerList, template, &w_Nhits); if(w_Scores[template] != 0 || w_Scores_tot[template] != 0) { fprintf(stderr, "# Failed updating the scores\n"); SearchList[template] = 0; } else { SearchList[template] = 0; } if(kmerList == 0) { stop = 1; } } else { stop = 1; } } } else { /* collect scores */ kmerList = collect_Kmers(templates, Scores, Scores_tot, foundKmers, &Nhits); fprintf(stderr, "# Total number of matches: %lu of %lu kmers\n", Nhits.tot, Ntot); /* copy scores */ w_Scores = smalloc(templates->DB_size * sizeof(int)); w_Scores_tot = smalloc(templates->DB_size * sizeof(long unsigned)); for(i = 0; i < templates->DB_size; ++i) { w_Scores[i] = Scores[i]; w_Scores_tot[i] = Scores_tot[i]; if(Scores[i] == 0) { SearchList[i] = 0; } else { SearchList[i] = 1; } } w_Nhits.n = Nhits.n; w_Nhits.tot = Nhits.tot; if(kmerList == 0) { stop = 1; } while(!stop) { /* get best match, depth first then coverage */ depth = 0; cover = 0; score = 0; template = 0; if(ss == 'q') { for(i = 0; i < templates->DB_size; ++i) { if(SearchList[i] && w_Scores_tot[i] >= score) { tmp_cover = 100.0 * w_Scores[i] / template_ulengths[i]; if(tmp_cover >= ID_t) { tmp_score = w_Scores_tot[i]; tmp_depth = 1.0 * w_Scores_tot[i] / template_lengths[i]; if(tmp_score > score || (tmp_cover > cover || (tmp_cover == cover && (tmp_depth > depth || (tmp_depth == depth && template_ulengths[i] > template_ulengths[template]))))) { /* calculate p_value */ tmp_expected = 1.0 * (Nhits.tot - w_Scores_tot[i]) * template_ulengths[i] / (templates->n - template_ulengths[i] + etta); tmp_q = (tmp_score - tmp_expected) * (tmp_score - tmp_expected) / (tmp_score + tmp_expected); tmp_p = p_chisqr(tmp_q); if(tmp_p <= evalue && tmp_score > tmp_expected) { score = tmp_score; cover = tmp_cover; depth = tmp_depth; template = i; expected = tmp_expected; p_value = tmp_p; q_value = tmp_q; } else { SearchList[i] = 0; } } } else { SearchList[i] = 0; } } } } else if (ss == 'd') { for(i = 0; i < templates->DB_size; ++i) { if(SearchList[i]) { tmp_cover = 100.0 * w_Scores[i] / template_ulengths[i]; if(tmp_cover >= ID_t) { tmp_score = w_Scores_tot[i]; tmp_depth = 1.0 * w_Scores_tot[i] / template_lengths[i]; if(tmp_depth > depth || (tmp_depth == depth && (tmp_cover > cover || (tmp_cover == cover && (tmp_score > score || (tmp_score == score && template_ulengths[i] > template_ulengths[template])))))) { /* calculate p_value */ tmp_expected = 1.0 * (Nhits.tot - w_Scores_tot[i]) * template_ulengths[i] / (templates->n - template_ulengths[i] + etta); tmp_q = (tmp_score - tmp_expected) * (tmp_score - tmp_expected) / (tmp_score + tmp_expected); tmp_p = p_chisqr(tmp_q); if(tmp_p <= evalue && tmp_score > tmp_expected) { score = tmp_score; cover = tmp_cover; depth = tmp_depth; template = i; expected = tmp_expected; p_value = tmp_p; q_value = tmp_q; } else { SearchList[i] = 0; } } } else { SearchList[i] = 0; } } } } else { for(i = 0; i < templates->DB_size; ++i) { if(SearchList[i]) { tmp_cover = 100.0 * w_Scores[i] / template_ulengths[i]; if(tmp_cover >= ID_t) { tmp_score = w_Scores_tot[i]; tmp_depth = 1.0 * w_Scores_tot[i] / template_lengths[i]; if(tmp_cover > cover || (tmp_cover == cover && (tmp_depth > depth || (tmp_depth == depth && (tmp_score > score || (tmp_score == score && template_ulengths[i] > template_ulengths[template])))))) { /* calculate p_value */ tmp_expected = 1.0 * (Nhits.tot - w_Scores_tot[i]) * template_ulengths[i] / (templates->n - template_ulengths[i] + etta); tmp_q = (tmp_score - tmp_expected) * (tmp_score - tmp_expected) / (tmp_score + tmp_expected); tmp_p = p_chisqr(tmp_q); if(tmp_p <= evalue && tmp_score > tmp_expected) { score = tmp_score; cover = tmp_cover; depth = tmp_depth; template = i; expected = tmp_expected; p_value = tmp_p; q_value = tmp_q; } else { SearchList[i] = 0; } } } else { SearchList[i] = 0; } } } } /* validate best match */ if(cover && cover >= ID_t) { /* output results */ query_cover = 100.0 * w_Scores_tot[template] / Ntot; /* calc tot values */ tot_cover = 100.0 * Scores[template] / template_ulengths[template]; tot_depth = 1.0 * Scores_tot[template] / template_lengths[template]; tot_query_cover = 100.0 * Scores_tot[template] / Ntot; fprintf(sparse_out, "%s\t%d\t%lu\t%d\t%d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%4.1e\n", template_names[template], template, score, (int) expected, template_lengths[template], query_cover, cover, depth, tot_query_cover, tot_cover, tot_depth, q_value, p_value); /* update scores */ kmerList = withDraw_Kmers(w_Scores, w_Scores_tot, kmerList, template, &w_Nhits); if(w_Scores[template] != 0 || w_Scores_tot[template] != 0) { fprintf(stderr, "# Failed updating the scores\n"); SearchList[template] = 0; } else { SearchList[template] = 0; } if(kmerList == 0) { stop = 1; } } else { stop = 1; } } } fclose(sparse_out); t1 = clock(); fprintf(stderr, "# Total for finding and outputting best matches: %.2f s.\n#\n", difftime(t1, t0) / 1000000); return status; } genomicepidemiology-kma-091b8ffe66ac/kma_update.c0000644000175000017500000000144314157033525021371 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "update.h" int main(int argc, char *argv[]) { return update_main(argc, argv); } genomicepidemiology-kma-091b8ffe66ac/shm.h0000644000175000017500000000252314157033525020053 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "hashmapkma.h" void hashMap_shm_detach(HashMapKMA *dest); int hashMapKMA_setupSHM(HashMapKMA *dest, FILE *file, const char *filename); void hashMapKMA_destroySHM(HashMapKMA *dest, FILE *file, const char *filename); int * length_setupSHM(FILE *file, const char *filename); void length_destroySHM(FILE *file, const char *filename); long unsigned * seq_setupSHM(FILE *file, const char *filename); void seq_destroySHM(FILE *file, const char *filename); char * name_setupSHM(FILE *file, const char *filename); void name_destroySHM(FILE *file, const char *filename); int shm_main(int argc, char *argv[]); genomicepidemiology-kma-091b8ffe66ac/threader.h0000644000175000017500000000305414157033525021062 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #if _POSIX_C_SOURCE >= 199309L #include #define sleepSpec(time)((const struct timespec[]){{0, time}}) #define lock(exclude) while(__sync_lock_test_and_set(exclude, 1)) {while(*exclude) {nanosleep(sleepSpec(100000),NULL);}} #define lockTime(exclude, time) while(__sync_lock_test_and_set(exclude, 1)) {while(*exclude) {nanosleep(sleepSpec(1000 * time),NULL);}} #define unlock(exclude) (__sync_lock_release(exclude)) #define wait_atomic(src) while(src) {nanosleep(sleepSpec(100000),NULL);} #else #include #define lock(exclude) while(__sync_lock_test_and_set(exclude, 1)) {while(*exclude) {usleep(100);}} #define lockTime(exclude, spin) while(__sync_lock_test_and_set(exclude, 1)) {while(*exclude) {usleep(spin);}} #define unlock(exclude) (__sync_lock_release(exclude)) #define wait_atomic(src) while(src) {usleep(100);} #endif genomicepidemiology-kma-091b8ffe66ac/.gitignore0000644000175000017500000000005114157033525021075 0ustar nileshnileshkma kma_index kma_shm kma_update *.o *.a genomicepidemiology-kma-091b8ffe66ac/stdnuc.c0000644000175000017500000000405714157033525020563 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "stdnuc.h" long unsigned getKmer(long unsigned *compressor, unsigned cPos, const unsigned shifter) { unsigned iPos = (cPos & 31) << 1; cPos >>= 5; return (iPos <= shifter) ? ((compressor[cPos] << iPos) >> shifter) : (((compressor[cPos] << iPos) | (compressor[cPos + 1] >> (64-iPos))) >> shifter); } long unsigned makeKmer(const unsigned char *qseq, unsigned pos, unsigned size) { long unsigned key = qseq[pos]; size += pos; for(++pos; pos < size; ++pos) { key = (key << 2) | qseq[pos]; } return key; } int charpos(const unsigned char *src, unsigned char target, int start, int len) { unsigned char *ptr; ptr = (unsigned char *) src + --start; while(++start < len) { if(*++ptr == target) { return start; } } return -1; } void strrc(unsigned char *qseq, int q_len) { int i, j, seqlen; unsigned char carry, comp[6] = {3, 2, 1, 0, 4, 5}; seqlen = q_len >> 1; for(i = 0, j = q_len - 1; i < seqlen; ++i, --j) { carry = comp[qseq[i]]; qseq[i] = comp[qseq[j]]; qseq[j] = carry; } if(q_len & 1) { qseq[seqlen] = comp[qseq[seqlen]]; } } void strtranslate(unsigned char *strp, char *trans) { --strp; while(*++strp) { *strp = trans[*strp]; } } void nibble2base(unsigned char *seq, int len) { const char bases[6] = "ACGTN-"; seq += len; *seq-- = 0; ++len; while(--len) { *seq = bases[*seq]; --seq; } } genomicepidemiology-kma-091b8ffe66ac/tmp.h0000644000175000017500000000137514157033525020070 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include FILE * tmpF(const char *location); genomicepidemiology-kma-091b8ffe66ac/savekmers.c0000644000175000017500000046211214157033525021263 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include "ankers.h" #include "compdna.h" #include "hashmapkma.h" #include "kmeranker.h" #include "penalties.h" #include "pherror.h" #include "qseqs.h" #include "sam.h" #include "savekmers.h" #include "seqmenttree.h" #include "stdnuc.h" #include "stdstat.h" #include "threader.h" void (*ankerPtr)(int*, int*, int*, char*, int*, unsigned**, unsigned**, int*, CompDNA*, int, int, int, int, Qseqs*, volatile int*, FILE*) = &ankerAndClean; int (*kmerScan)(const HashMapKMA *, const Penalties *, int*, int*, int*, int*, CompDNA*, CompDNA*, const Qseqs*, int*, const int, volatile int*, FILE*) = &save_kmers_HMM; /* here */ //&save_kmers_chain; int (*save_kmers_pair)(const HashMapKMA *, const Penalties *, int*, int*, int*, int*, int*, int*, CompDNA*, CompDNA*, const Qseqs*, const Qseqs*, int*, const int, volatile int*, FILE*) = &save_kmers_unionPair; int (*get_kmers_for_pair_ptr)(const HashMapKMA *, const Penalties *, int *, int *, int *, int *, CompDNA *, int *, int) = &get_kmers_for_pair; int (*getMatch)(int*, int*) = &getBestMatch; int (*getMatchSparse)(int*, int*, int, int, int, int) = &getBestMatchSparse; int (*getSecondForce)(int*, int*, int*, int*, int*, int*) = &getSecondBestForce; int (*getSecondPen)(int*, int*, int*, int*, int*, int*, int, int) = &getSecondBestPen; int (*getF)(int*, int*, int*, int*, int*) = &getF_Best; int (*getR)(int*, int*, int*, int*, int*) = &getR_Best; int loadFsa(CompDNA *qseq, Qseqs *header, FILE *inputfile) { int buffer[4]; if(fread(buffer, sizeof(int), 4, inputfile)) { qseq->seqlen = buffer[0]; qseq->complen = buffer[1]; /* if pair, header->len < 0 */ header->len = abs(buffer[3]); if(qseq->size <= qseq->seqlen) { free(qseq->N); free(qseq->seq); if(qseq->seqlen & 31) { qseq->size = (qseq->seqlen >> 5) + 1; qseq->size <<= 6; } else { qseq->size = qseq->seqlen << 1; } qseq->seq = calloc(qseq->size >> 5, sizeof(long unsigned)); qseq->N = malloc((qseq->size + 1) * sizeof(int)); if(!qseq->seq || !qseq->N) { ERROR(); } } qseq->N[0] = buffer[2]; if(header->size <= header->len) { header->size = header->len << 1; free(header->seq); header->seq = smalloc(header->size); } sfread(qseq->seq, sizeof(long unsigned), qseq->complen, inputfile); sfread(qseq->N + 1, sizeof(int), qseq->N[0], inputfile); sfread(header->seq, 1, header->len, inputfile); } else { qseq->seqlen = 0; return 0; } return buffer[3]; } void * save_kmers_threaded(void *arg) { static volatile int Lock[2] = {0, 0}; static unsigned readNum = 0; volatile int *excludeIn = &Lock[0], *excludeOut = &Lock[1]; KmerScan_thread *thread = arg; int *Score, *Score_r, *bestTemplates, *bestTemplates_r, *regionTemplates; int *regionScores, *extendScore, *p_readNum, *pr_readNum, *preg_readNum; int go, exhaustive, unmapped, sam, flag, cflag, stats[2];; FILE *inputfile, *out; HashMapKMA *templates; CompDNA *qseq, *qseq_r; Qseqs *header, *header_r, *samseq; Penalties *rewards; stats[0] = 0; templates = thread->templates; exhaustive = thread->exhaustive; bestTemplates = thread->bestTemplates; bestTemplates_r = thread->bestTemplates_r; rewards = thread->rewards; if(save_kmers_pair != &save_kmers_unionPair) { regionScores = calloc(templates->DB_size << 1, sizeof(int)); if(!regionScores) { ERROR(); } } else { regionScores = 0; } /* make constant part of flag */ if(save_kmers_pair == &save_kmers_forcePair) { cflag = 1; } else { cflag = 0; } if(templates->prefix && templates->prefix_len == 0) { cflag |= 2; } extendScore = calloc((templates->DB_size + 1) * sizeof(int) + templates->DB_size + 1, 1); if(!extendScore) { ERROR(); } qseq = smalloc(sizeof(CompDNA)); qseq_r = smalloc(sizeof(CompDNA)); header = setQseqs(256); header_r = setQseqs(256); allocComp(qseq, 1024); allocComp(qseq_r, 1024); regionTemplates = smalloc(((templates->DB_size << 1) + 4) * sizeof(int)); Score = calloc(templates->DB_size, sizeof(int)); Score_r = calloc(templates->DB_size, sizeof(int)); if(!Score || !Score_r) { ERROR(); } inputfile = thread->inputfile; *Score = thread->num; *bestTemplates++ = templates->DB_size; *bestTemplates_r++ = templates->DB_size; *regionTemplates++ = templates->DB_size; *bestTemplates++ = thread->num; *bestTemplates_r++ = thread->num; *regionTemplates++ = thread->num; *bestTemplates++ = 0; *bestTemplates_r++ = 0; *regionTemplates++ = 0; out = thread->out; if((sam = thread->sam)) { samseq = setQseqs(256); } else { samseq = 0; } p_readNum = (bestTemplates - 1); pr_readNum = (bestTemplates_r - 1); preg_readNum = (regionTemplates - 1); go = 1; while(go != 0) { /* load qseqs */ lock(excludeIn); if((go = loadFsa(qseq, header, inputfile)) < 0) { /* PE */ loadFsa(qseq_r, header_r, inputfile); } if(go != 0) { *p_readNum = ++readNum; } else { *p_readNum = readNum; } unlock(excludeIn); *pr_readNum = readNum; *preg_readNum = readNum; /* allocate memory */ if(qseq_r->size < qseq->size && 0 < go) { freeComp(qseq_r); allocComp(qseq_r, qseq->size); } /* find ankers */ if(0 < go) { unmapped = kmerScan(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq, qseq_r, header, extendScore, exhaustive, excludeOut, out); } else if(go < 0) { unmapped = save_kmers_pair(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates, regionScores, qseq, qseq_r, header, header_r, extendScore, exhaustive, excludeOut, out); } else { unmapped = 0; } if(sam && unmapped) { if(unmapped & 1) { /* set flag */ flag = 4; if(go < 0) { flag |= 65; if((unmapped & 2) || (cflag & 1)) { flag |= 8; } } if((cflag & 2) == 0) { flag |= 16; if((flag & 8) && (unmapped & 2)) { flag |= 32; } } qseqCompDNA(qseq, samseq); nibble2base(samseq->seq, samseq->len); stats[1] = flag; samwrite(samseq, header, 0, 0, 0, stats); } if(unmapped & 2 || ((cflag & 1) && (unmapped & 1))) { /* set flag */ flag = 4; if(go < 0) { flag |= 129; if(unmapped & 1) { flag |= 8; } } if((cflag & 2) == 0) { if(unmapped & 2) { flag |= 16; } if((flag & 8)) { flag |= 32; } } qseqCompDNA(qseq_r, samseq); nibble2base(samseq->seq, samseq->len); stats[1] = flag; samwrite(samseq, header_r, 0, 0, 0, stats); } } } /* clean up */ if(save_kmers_pair != &save_kmers_unionPair) { free(regionScores); } if(sam) { destroyQseqs(samseq); } free(extendScore); freeComp(qseq); free(qseq); freeComp(qseq_r); free(qseq_r); destroyQseqs(header); destroyQseqs(header_r); free(regionTemplates - 3); free(Score); free(Score_r); return NULL; } int getBestMatch(int *bestTemplates, int *Score) { int i, score, bestScore, bestHits, template; bestHits = 0; bestScore = 0; for(i = 1; i <= *bestTemplates; ++i) { score = Score[(template = bestTemplates[i])]; if(score > bestScore) { bestScore = score; bestHits = 1; bestTemplates[bestHits] = template; } else if(score == bestScore) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; } *bestTemplates = bestHits; return bestScore; } int getProxiMatch(int *bestTemplates, int *Score) { static double minFrac = 0.0; int i, score, bestScore, proxiScore, bestHits, template, *Templates; if(Score == 0) { minFrac = *((double *) bestTemplates); return 0; } /* get proximity score */ bestScore = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { if(bestScore < (score = Score[*Templates++])) { bestScore = score; } } /*proxiScore = (bestScore - proxi < 1) ? 1 : (bestScore - proxi);*/ proxiScore = minFrac * bestScore; /* get best matches within proximity */ bestHits = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { score = Score[(template = *Templates++)]; if(proxiScore <= score) { bestTemplates[++bestHits] = template; } Score[template] = 0; } *bestTemplates = bestHits; return bestScore; } int getBestMatchSparse(int *bestTemplates, int *Score, int kmersize, int n_kmers, int M, int MM) { int i, score, bestScore, bestHits, template; bestHits = 0; bestScore = 0; for(i = 1; i <= *bestTemplates; ++i) { score = Score[(template = bestTemplates[i])]; score = score * kmersize * M + (n_kmers - score) * MM; if(score > bestScore) { bestScore = score; bestHits = 1; bestTemplates[bestHits] = template; } else if(score == bestScore) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; } *bestTemplates = bestHits; return bestScore; } int getProxiMatchSparse(int *bestTemplates, int *Score, int kmersize, int n_kmers, int M, int MM) { static double minFrac = 0.0; int i, score, bestScore, proxiScore, bestHits, template, *Templates; if(Score == 0) { minFrac = *((double *) bestTemplates); return 0; } /* get proximity score */ bestScore = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { score = Score[*Templates++]; score = score * kmersize * M + (n_kmers - score) * MM; if(bestScore < score) { bestScore = score; } } /*proxiScore = (bestScore - proxi < 1) ? 1 : (bestScore - proxi);*/ proxiScore = minFrac * bestScore; /* get best matches within proximity */ bestHits = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { score = Score[(template = *Templates++)]; score = score * kmersize * M + (n_kmers - score) * MM; if(proxiScore <= score) { bestTemplates[++bestHits] = template; } Score[template] = 0; } *bestTemplates = bestHits; return bestScore; } static int clearScore(int *bestTemplates, int *Score) { int i; i = *bestTemplates + 1; while(--i) { Score[*++bestTemplates] = 0; } return 0; } int testVal(short unsigned *values_s, int template) { int i; i = *values_s; while(--i) { if(*++values_s == template) { return 1; } } return 0; } int get_kmers_for_pair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive) { /* save_kmers find ankering k-mers the in query sequence, and is the time determining step */ int i, j, l, rc, end, HIT, gaps, score, Ms, MMs, Us, W1s, template, SU; int hitCounter, bestSeqCount, kmersize, shifter, W1, U, M, MM, m, mm; int *bests, *Scores; unsigned *values, *last, n; short unsigned *values_s; char *include; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 0; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); W1 = rewards->W1; U = rewards->U; M = rewards->M; MM = rewards->MM; *extendScore = 0; *bestTemplates = 0; *bestTemplates_r = 0; bests = bestTemplates; Scores = Score; bestSeqCount = 0; kmersize = templates->kmersize; include = (char *) (extendScore + (templates->DB_size + 1)); for(rc = 0; rc < 2; ++rc) { if(rc) { bests = bestTemplates_r; Scores = Score_r; comp_rc(qseq); } /* Make quick check of the qseq */ HIT = exhaustive; hitCounter = 0; j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; } /* If deltamer qseq hits, then continue */ if(HIT) { /* Scan the deltamer exhaustively, and collect scores in Score*/ last = 0; gaps = 0; HIT = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { /* gaps == 0 -> Match gaps == kmersize -> 1 MM kmersize < gaps -> several mismatches or indel(s) gaps < kmersize -> deletion */ if(gaps == 0) { /* match */ ++Ms; } else if(gaps == kmersize) { /* snp */ Ms += kmersize; ++MMs; } else if(kmersize < gaps) { /* mismatch or insersion */ Ms += kmersize; gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { MMs += mm; Ms += m; } else { ++W1s; Us += (gaps -1); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ HIT = j; gaps = 0; } else { if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; values_s = (short unsigned *) last; l = SU ? (*values_s + 1) : (*last + 1); while(--l) { template = SU ? *++values_s : *++last; Scores[template] += score; extendScore[template] = HIT; } HIT = j - 1; last = values; score = kmersize * M; values_s = (short unsigned *) values; n = SU ? *values_s : *values; l = n + 1; while(--l) { template = SU ? *++values_s : *++values; if(Scores[template] != 0) { gaps = HIT - extendScore[template]; if(gaps == 0) { /* match */ Scores[template] += M; } else if(gaps == kmersize) { /* snp */ Scores[template] += score + MM; } else if(kmersize < gaps) { /* mismatch or insersion */ gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { Scores[template] += score + (mm * MM + m * M); } else { Scores[template] += score + (W1 + (gaps - 1) * U); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ } else { Scores[template] = score; if(include[template] == 0) { include[template] = 1; bests[++*bests] = template; } } } } else { last = values; values_s = (short unsigned *) values; n = SU ? *values_s : *values; Ms = kmersize * M; for(l = 1; l <= n; ++l) { template = SU ? *++values_s : *++values; Scores[template] = Ms; include[template] = 1; bests[l] = template; } *bests = n; } HIT = j; gaps = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; } ++hitCounter; } else { ++gaps; } } gaps += (qseq->N[i] + 1 - j); /* gap over N's */ j = qseq->N[i] + 1; } if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; if(SU) { values_s = (short unsigned *) last; l = (*values_s) + 1; while(--l) { Scores[*++values_s] += score; } } else { l = (*last) + 1; while(--l) { Scores[*++last] += score; } } for(l = *bests; l != 0; --l) { extendScore[(template = bests[l])] = 0; include[template] = 0; if(Scores[template] < 0) { Scores[template] = 0; } } } if(bestSeqCount < hitCounter) { bestSeqCount = hitCounter; } } qseq->N[0]--; } return bestSeqCount; } int get_kmers_for_pair_count(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive) { /* save_kmers find ankering k-mers the in query sequence, and is the time determining step */ int i, j, rc, end, HIT, hitCounter, bestSeqCount, reps, SU, kmersize; int shifter, *bests, *Scores; unsigned *values, *last, n; short unsigned *values_s; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 0; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); *extendScore = 0; *bestTemplates = 0; *bestTemplates_r = 0; bests = bestTemplates; Scores = Score; bestSeqCount = 0; kmersize = templates->kmersize; for(rc = 0; rc < 2; ++rc) { if(rc) { bests = bestTemplates_r; Scores = Score_r; comp_rc(qseq); } /* Make quick check of the qseq */ HIT = exhaustive; hitCounter = 0; j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; } /* If deltamer qseq hits, then continue */ if(HIT) { /* Scan the deltamer exhaustively, and collect scores in Score*/ last = 0; reps = 0; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { ++reps; } else { if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s + 1; while(--n) { if((Scores[*++values_s] += reps) == reps) { bests[++*bests] = *values_s; } } } else { n = *last + 1; while(--n) { if((Scores[*++last] += reps) == reps) { bests[++*bests] = *last; } } } hitCounter += reps; } reps = 1; last = values; } } } j = qseq->N[i] + 1; } if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s + 1; while(--n) { if((Scores[*++values_s] += reps) == reps) { bests[++*bests] = *values_s; } } } else { n = *last + 1; while(--n) { if((Scores[*++last] += reps) == reps) { bests[++*bests] = *last; } } } hitCounter += reps; } reps = 0; if(bestSeqCount < hitCounter) { bestSeqCount = hitCounter; } } qseq->N[0]--; } return bestSeqCount; } int get_kmers_for_pair_Sparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive) { int i, j, n, end, rc, prefix_len, hitCounter, reps, n_kmers, kmersize; int HIT, SU, *bests, *Scores; unsigned shifter, prefix_shifter, *values, *last; short unsigned *values_s; long unsigned prefix; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 0; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->prefix_len << 1); if(*extendScore) { bests = bestTemplates_r; Scores = Score_r; } else { bests = bestTemplates; Scores = Score; } *extendScore = 0; *bestTemplates = 0; *bestTemplates_r = 0; prefix = templates->prefix; prefix_len = templates->prefix_len; hitCounter = 0; n_kmers = 0; end = qseq->seqlen; if(prefix_len) { for(rc = 0; rc < 2; ++rc) { if(rc) { comp_rc(qseq); } j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize - prefix_len + 1; while(j < end) { if(getKmer(qseq->seq, j, prefix_shifter) == prefix) { if((values = hashMap_get(templates, getKmer(qseq->seq, j + prefix_len, shifter)))) { if(SU) { values_s = (short unsigned *) values; n = *values_s + 1; while(--n) { if(Scores[*++values_s]++ == 0) { bests[++*bests] = *values_s; } } } else { n = *values + 1; while(--n) { if(Scores[*++values]++ == 0) { bests[++*bests] = *values; } } } ++hitCounter; } ++n_kmers; } ++j; } j = qseq->N[i] + 1; } qseq->N[0]--; } if(hitCounter) { hitCounter *= (((qseq->seqlen - kmersize + 1) << 1) / n_kmers); } } else { HIT = exhaustive; j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; } if(HIT) { last = 0; reps = 0; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { ++reps; } else { if(last) { if(SU) { values_s = (short unsigned *) values; n = *values_s + 1; while(--n) { if((Scores[*++values_s] += reps) == reps) { bests[++*bests] = *values_s; } } } else { n = *values + 1; while(--n) { if((Scores[*++last] += reps) == reps) { bests[++*bests] = *last; } } } hitCounter += reps; } reps = 1; last = values; } } } j = qseq->N[i] + 1; } if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s + 1; while(--n) { if((Scores[*++values_s] += reps) == reps) { bests[++*bests] = *values_s; } } } else { n = *last + 1; while(--n) { if((Scores[*++last] += reps) == reps) { bests[++*bests] = *last; } } } hitCounter += reps; } } qseq->N[0]--; } return hitCounter; } int get_kmers_for_pair_pseoudoSparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, int *extendScore, const int exhaustive) { int i, j, l, n, end, template, hitCounter, gaps, Ms, MMs, Us, W1s; int W1, U, M, MM, HIT, SU, kmersize, score, m, mm, *bests, *Scores; unsigned shifter, *values, *last; short unsigned *values_s; char *include; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 0; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); W1 = rewards->W1; U = rewards->U; M = rewards->M; MM = rewards->MM; include = (char *) (extendScore + (templates->DB_size + 1)); if(*extendScore) { bests = bestTemplates_r; Scores = Score_r; } else { bests = bestTemplates; Scores = Score; } *extendScore = 0; *bestTemplates = 0; *bestTemplates_r = 0; hitCounter = 0; end = qseq->seqlen; HIT = exhaustive; j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; } if(HIT) { last = 0; gaps = 0; HIT = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { /* gaps == 0 -> Match gaps == kmersize -> 1 MM kmersize < gaps -> several mismatches or indel(s) gaps < kmersize -> deletion */ if(gaps == 0) { /* match */ ++Ms; } else if(gaps == kmersize) { /* snp */ Ms += kmersize; ++MMs; } else if(kmersize < gaps) { /* mismatch or insersion */ Ms += kmersize; gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { MMs += mm; Ms += m; } else { ++W1s; Us += (gaps -1); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ HIT = j; gaps = 0; } else { if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; values_s = (short unsigned *) last; l = SU ? (*values_s + 1) : (*last + 1); while(--l) { template = SU ? *++values_s : *++last; Scores[template] += score; extendScore[template] = HIT; } HIT = j - 1; last = values; score = kmersize * M; values_s = (short unsigned *) values; n = SU ? *values_s : *values; l = n + 1; while(--l) { template = SU ? *++values_s : *++values; if(Scores[template] != 0) { gaps = HIT - extendScore[template]; if(gaps == 0) { /* match */ Scores[template] += M; } else if(gaps == kmersize) { /* snp */ Scores[template] += score + MM; } else if(kmersize < gaps) { /* mismatch or insersion */ gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { Scores[template] += score + (mm * MM + m * M); } else { Scores[template] += score + (W1 + (gaps - 1) * U); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ } else { Scores[template] = score; if(include[template] == 0) { include[template] = 1; bests[++*bests] = template; } } } } else { last = values; values_s = (short unsigned *) values; n = SU ? *values_s : *values; Ms = kmersize * M; for(l = 1; l <= n; ++l) { template = SU ? *++values_s : *++values; Scores[template] = Ms; include[template] = 1; bests[l] = template; } *bests = n; } HIT = j; gaps = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; } ++hitCounter; } else { ++gaps; } } gaps += (qseq->N[i] + 1 - j); /* gap over N's */ j = qseq->N[i] + 1; } if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; if(SU) { values_s = (short unsigned *) last; l = *values_s + 1; while(--l) { Scores[*++values_s] += score; } } else { l = *last + 1; while(--l) { Scores[*++last] += score; } } for(l = *bests; l != 0; --l) { extendScore[(template = bests[l])] = 0; include[template] = 0; if(Scores[template] < 0) { Scores[template] = 0; } } } } qseq->N[0]--; return hitCounter; } void getFirstForce(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores) { int i, bestHits; bestHits = 0; for(i = 1; i <= *bestTemplates; ++i) { ++bestHits; regionTemplates[bestHits] = bestTemplates[i]; regionScores[bestHits] = Score[bestTemplates[i]]; Score[bestTemplates[i]] = 0; } for(i = 1; i <= *bestTemplates_r; ++i) { ++bestHits; regionTemplates[bestHits] = -bestTemplates_r[i]; regionScores[bestHits] = Score_r[bestTemplates_r[i]]; Score_r[bestTemplates_r[i]] = 0; } *regionTemplates = bestHits; } int getSecondBestForce(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores) { int i, score, bestHits, bestScore; bestHits = 0; bestScore = 0; for(i = 1; i <= *regionTemplates; ++i) { if(0 < regionTemplates[i]) { if((score = Score[regionTemplates[i]])) { score += regionScores[i]; if(bestScore < score) { bestScore = score; bestHits = 1; regionTemplates[bestHits] = regionTemplates[i]; } else if(bestScore == score) { ++bestHits; regionTemplates[bestHits] = regionTemplates[i]; } } } else { if((score = Score_r[-regionTemplates[i]])) { score += regionScores[i]; if(bestScore < score) { bestScore = score; bestHits = 1; regionTemplates[bestHits] = regionTemplates[i]; } else if(bestScore == score) { ++bestHits; regionTemplates[bestHits] = regionTemplates[i]; } } } } *regionTemplates = bestHits; for(i = *bestTemplates; i != 0; --i) { Score[bestTemplates[i]] = 0; } for(i = *bestTemplates_r; i != 0; --i) { Score_r[bestTemplates_r[i]] = 0; } return bestScore; } int getSecondProxiForce(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores) { static double minFrac = 0.0; int i, score, bestHits, bestScore, proxiScore, template, *Templates; if(Score == 0) { minFrac = *((double *) bestTemplates); return 0; } /* get proximity score */ bestScore = 0; Templates = regionTemplates; i = *Templates++ + 1; while(--i) { template = *Templates++; if(template < 0) { if(bestScore < (score = Score_r[-template])) { bestScore = score; } } else { if(bestScore < (score = Score[template])) { bestScore = score; } } } proxiScore = minFrac * bestScore; /* get best matches within proximity */ bestHits = 0; Templates = regionTemplates; i = *Templates++ + 1; while(--i) { template = *Templates++; if(template < 0) { if(proxiScore <= (score = Score_r[-template])) { regionTemplates[++bestHits] = template; } } else { if(proxiScore <= (score = Score[template])) { regionTemplates[++bestHits] = template; } } } for(i = *bestTemplates; i != 0; --i) { Score[bestTemplates[i]] = 0; } for(i = *bestTemplates_r; i != 0; --i) { Score_r[bestTemplates_r[i]] = 0; } return bestScore; } int getFirstPen(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores) { int i, score, bestScore, bestHits; bestScore = 0; bestHits = 0; /* save forward matches */ for(i = 1; i <= *bestTemplates; ++i) { if(bestScore < (score = Score[bestTemplates[i]])) { bestScore = score; } ++bestHits; regionTemplates[bestHits] = bestTemplates[i]; regionScores[bestHits] = score; Score[bestTemplates[i]] = 0; } /* save reverse matches */ for(i = 1; i <= *bestTemplates_r; ++i) { if(bestScore < (score = Score_r[bestTemplates_r[i]])) { bestScore = score; } ++bestHits; regionTemplates[bestHits] = -bestTemplates_r[i]; regionScores[bestHits] = score; Score_r[bestTemplates_r[i]] = 0; } *regionTemplates = bestHits; return bestScore; } int getSecondBestPen(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, int bestScore, int PE) { int i, score, bestScore_r, compScore, bestHits, template; /* get best scoring tempates */ bestScore_r = 0; for(i = 1; i <= *bestTemplates; ++i) { if(bestScore_r < Score[bestTemplates[i]]) { bestScore_r = Score[bestTemplates[i]]; } } bestHits = *bestTemplates; for(i = 1; i <= *bestTemplates_r; ++i) { if(bestScore_r < Score_r[bestTemplates_r[i]]) { bestScore_r = Score_r[bestTemplates_r[i]]; } ++bestHits; bestTemplates[bestHits] = -bestTemplates_r[i]; } *bestTemplates = bestHits; /* check union */ bestHits = 0; if(bestScore_r) { compScore = bestScore + bestScore_r - PE; compScore = MAX(0, compScore); for(i = 1; i <= *regionTemplates; ++i) { if(0 < regionTemplates[i]) { /* we got one */ if(0 < (score = Score_r[regionTemplates[i]])) { score += regionScores[i]; if(compScore < score) { compScore = score; bestHits = 1; regionTemplates[bestHits] = regionTemplates[i]; } else if(compScore == score) { ++bestHits; regionTemplates[bestHits] = regionTemplates[i]; } } } else { /* we got one */ if(0 < (score = Score[-regionTemplates[i]])) { score += regionScores[i]; if(compScore < score) { compScore = score; bestHits = 1; regionTemplates[bestHits] = regionTemplates[i]; } else if(compScore == score) { ++bestHits; regionTemplates[bestHits] = regionTemplates[i]; } } } } } /* mark as PE */ if(bestHits) { *regionTemplates = -bestHits; /* clear scores */ for(i = *bestTemplates; i != 0; --i) { if(0 < bestTemplates[i]) { Score[bestTemplates[i]] = 0; } else { Score_r[-bestTemplates[i]] = 0; } } } else { /* get bestHits from each as SE */ for(i = 1; i <= *regionTemplates; ++i) { if(bestScore == regionScores[i]) { regionTemplates[++bestHits] = regionTemplates[i]; } } *regionTemplates = bestHits; bestHits = 0; for(i = 1; i <= *bestTemplates; ++i) { if(0 < (template = bestTemplates[i])) { if(bestScore_r == Score[template]) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; } else { if(bestScore_r <= Score_r[-template]) { ++bestHits; bestTemplates[bestHits] = template; } Score_r[-template] = 0; } } *bestTemplates = bestHits; } return bestScore_r; } int getSecondProxiPen(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, int bestScore, int PE) { static double minFrac = 0.0; int i, score, bestScore_r, compScore, proxiScore, bestHits, template; if(Score == 0) { minFrac = *((double *) bestTemplates); return 0; } /* get best scoring tempates */ bestScore_r = 0; for(i = 1; i <= *bestTemplates; ++i) { if(bestScore_r < Score[bestTemplates[i]]) { bestScore_r = Score[bestTemplates[i]]; } } bestHits = *bestTemplates; for(i = 1; i <= *bestTemplates_r; ++i) { if(bestScore_r < Score_r[bestTemplates_r[i]]) { bestScore_r = Score_r[bestTemplates_r[i]]; } ++bestHits; bestTemplates[bestHits] = -bestTemplates_r[i]; } *bestTemplates = bestHits; /* check union */ bestHits = 0; if(bestScore_r) { compScore = 0; for(i = 1; i <= *regionTemplates; ++i) { if(0 < regionTemplates[i]) { /* we got one */ if(0 < (score = Score_r[regionTemplates[i]])) { score += regionScores[i]; if(compScore < score) { compScore = score; } } } else { /* we got one */ if(0 < (score = Score[-regionTemplates[i]])) { score += regionScores[i]; if(compScore < score) { compScore = score; } } } } /* union is better */ if((bestScore + bestScore_r - PE) <= compScore) { proxiScore = minFrac * compScore; for(i = 1; i <= *regionTemplates; ++i) { if(0 < regionTemplates[i]) { /* we got one */ if(0 < (score = Score_r[regionTemplates[i]])) { score += regionScores[i]; if(proxiScore <= score) { regionTemplates[++bestHits] = regionTemplates[i]; } } } else { /* we got one */ if(0 < (score = Score[-regionTemplates[i]])) { score += regionScores[i]; if(proxiScore <= score) { regionTemplates[++bestHits] = regionTemplates[i]; } } } } } } /* mark as PE */ if(bestHits) { *regionTemplates = -bestHits; /* clear scores */ for(i = *bestTemplates; i != 0; --i) { if(0 < bestTemplates[i]) { Score[bestTemplates[i]] = 0; } else { Score_r[-bestTemplates[i]] = 0; } } } else { /* get bestHits from each as SE */ proxiScore = minFrac * bestScore; for(i = 1; i <= *regionTemplates; ++i) { if(proxiScore <= regionScores[i]) { regionTemplates[++bestHits] = regionTemplates[i]; } } *regionTemplates = bestHits; bestHits = 0; proxiScore = minFrac * bestScore_r; for(i = 1; i <= *bestTemplates; ++i) { if(0 < (template = bestTemplates[i])) { if(proxiScore <= Score[template]) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; } else { if(proxiScore <= Score_r[-template]) { ++bestHits; bestTemplates[bestHits] = template; } Score_r[-template] = 0; } } *bestTemplates = bestHits; } return bestScore_r; } int getF_Best(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates) { int i, score, bestScore, bestHits; bestScore = 0; bestHits = 0; for(i = 1; i <= *bestTemplates; ++i) { if(bestScore < (score = Score[bestTemplates[i]])) { bestScore = score; bestHits = 1; regionTemplates[bestHits] = bestTemplates[i]; } else if(bestScore == score) { ++bestHits; regionTemplates[bestHits] = bestTemplates[i]; } Score[bestTemplates[i]] = 0; } for(i = 1; i <= *bestTemplates_r; ++i) { if(bestScore < (score = Score_r[bestTemplates_r[i]])) { bestScore = score; bestHits = 1; regionTemplates[bestHits] = -bestTemplates_r[i]; } else if(bestScore == score) { ++bestHits; regionTemplates[bestHits] = -bestTemplates_r[i]; } Score_r[bestTemplates_r[i]] = 0; } *regionTemplates = bestHits; return bestScore; } int getR_Best(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates) { int i, j, score, bestScore_r, bestHits; /* get best scoring tempates */ bestScore_r = 0; bestHits = 0; for(i = 1; i <= *bestTemplates; ++i) { if(bestScore_r < (score = Score[bestTemplates[i]])) { for(j = bestHits; j != 0; --j) { Score[bestTemplates[j]] = 0; } bestScore_r = score; bestHits = 1; bestTemplates[bestHits] = bestTemplates[i]; } else if(bestScore_r == score) { ++bestHits; bestTemplates[bestHits] = bestTemplates[i]; } else { Score[bestTemplates[i]] = 0; } } for(i = 1; i <= *bestTemplates_r; ++i) { if(bestScore_r < (score = Score_r[bestTemplates_r[i]])) { for(j = bestHits; j != 0; --j) { if(0 < bestTemplates[j]) { Score[bestTemplates[j]] = 0; } else { Score_r[-bestTemplates[j]] = 0; } } bestScore_r = score; bestHits = 1; bestTemplates[bestHits] = -bestTemplates_r[i]; } else if(bestScore_r == score) { ++bestHits; bestTemplates[bestHits] = -bestTemplates_r[i]; } else { Score_r[bestTemplates_r[i]] = 0; } } *bestTemplates = bestHits; /* check union */ bestHits = 0; for(i = 1; i <= *regionTemplates; ++i) { if(0 < regionTemplates[i]) { /* we got one */ if(Score_r[regionTemplates[i]]) { ++bestHits; score = regionTemplates[bestHits]; regionTemplates[bestHits] = regionTemplates[i]; regionTemplates[i] = score; } } else { /* we got one */ if(Score[-regionTemplates[i]]) { ++bestHits; score = regionTemplates[bestHits]; regionTemplates[bestHits] = regionTemplates[i]; regionTemplates[i] = score; } } } /* mark as PE */ if(bestHits) { *regionTemplates = -bestHits; } /* clear scores */ for(i = *bestTemplates; i != 0; --i) { if(0 < bestTemplates[i]) { Score[bestTemplates[i]] = 0; } else { Score_r[-bestTemplates[i]] = 0; } } return bestScore_r; } int getF_Proxi(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates) { static double minFrac = 0.0; int i, score, bestScore, proxiScore, bestHits, template, *Templates; if(Score == 0) { minFrac = *((double *) bestTemplates); return getR_Proxi(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates); } /* get proximity score */ bestScore = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { if(bestScore < (score = Score[*Templates++])) { bestScore = score; } } Templates = bestTemplates_r; i = *Templates++ + 1; while(--i) { if(bestScore < (score = Score_r[*Templates++])) { bestScore = score; } } proxiScore = minFrac * bestScore; /* get best matches within proximity */ bestHits = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { score = Score[(template = *Templates++)]; if(proxiScore <= score) { regionTemplates[++bestHits] = template; } Score[template] = 0; } Templates = bestTemplates_r; i = *Templates++ + 1; while(--i) { score = Score_r[(template = *Templates++)]; if(proxiScore <= score) { regionTemplates[++bestHits] = -template; } Score_r[template] = 0; } *regionTemplates = bestHits; return bestScore; } int getR_Proxi(int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates) { static double minFrac = 0.0; int i, score, proxiScore, bestScore, bestHits, template, *Templates; if(Score == 0) { minFrac = *((double *) bestTemplates); return 0; } /* get proximity score */ bestScore = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { if(bestScore < (score = Score[*Templates++])) { bestScore = score; } } Templates = bestTemplates_r; i = *Templates++ + 1; while(--i) { if(bestScore < (score = Score_r[*Templates++])) { bestScore = score; } } proxiScore = minFrac * bestScore; /* get best matches within proximity */ bestHits = 0; Templates = bestTemplates; i = *Templates++ + 1; while(--i) { score = Score[(template = *Templates++)]; if(proxiScore <= score) { bestTemplates[++bestHits] = template; } else { Score[template] = 0; } } Templates = bestTemplates_r; i = *Templates++ + 1; while(--i) { score = Score_r[(template = *Templates++)]; if(proxiScore <= score) { bestTemplates[++bestHits] = -template; } else { Score_r[template] = 0; } } *bestTemplates = bestHits; /* check union */ bestHits = 0; for(i = 1; i <= *regionTemplates; ++i) { if(0 < regionTemplates[i]) { /* we got one */ if(Score_r[regionTemplates[i]]) { ++bestHits; score = regionTemplates[bestHits]; regionTemplates[bestHits] = regionTemplates[i]; regionTemplates[i] = score; } } else { /* we got one */ if(Score[-regionTemplates[i]]) { ++bestHits; score = regionTemplates[bestHits]; regionTemplates[bestHits] = regionTemplates[i]; regionTemplates[i] = score; } } } /* mark as PE */ if(bestHits) { *regionTemplates = -bestHits; } /* clear scores */ for(i = *bestTemplates; i != 0; --i) { if(0 < bestTemplates[i]) { Score[bestTemplates[i]] = 0; } else { Score_r[-bestTemplates[i]] = 0; } } return bestScore; } int save_kmers_Sparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { int i, j, k, l, n, end, rc, prefix_len, template, hitCounter, HIT, SU; int M, MM, n_kmers, bestScore, reps, kmersize, flag; unsigned shifter, prefix_shifter, *values, *last; short unsigned *values_s; long unsigned prefix; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 1; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); M = rewards->M; MM = rewards->MM; *bestTemplates = 0; prefix = templates->prefix; prefix_len = templates->prefix_len; prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->prefix_len << 1); hitCounter = 0; n_kmers = 0; bestScore = 0; end = qseq->seqlen; if(prefix_len) { flag = 16; for(rc = 0; rc < 2; ++rc) { if(rc) { comp_rc(qseq); } j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize - prefix_len + 1; while(j < end) { if(getKmer(qseq->seq, j, prefix_shifter) == prefix) { if((values = hashMap_get(templates, getKmer(qseq->seq, j + prefix_len, shifter)))) { if(SU) { values_s = (short unsigned *) values; n = *values_s; for(k = 1; k <= n; ++k) { if(Score[(template = values_s[k])] == 0) { (*bestTemplates)++; bestTemplates[*bestTemplates] = template; } Score[template]++; } } else { n = *values; for(k = 1; k <= n; ++k) { if(Score[(template = values[k])] == 0) { (*bestTemplates)++; bestTemplates[*bestTemplates] = template; } Score[template]++; } } ++hitCounter; } ++n_kmers; } ++j; } j = qseq->N[i] + 1; } qseq->N[0]--; } /* get best match(es) */ /*if(hitCounter * kmersize > (n_kmers - hitCounter)) {*/ if(hitCounter) { bestScore = getMatchSparse(bestTemplates, Score, kmersize, n_kmers, M, MM); /* bestHits = 0; for(l = 1; l <= *bestTemplates; ++l) { score = Score[(template = bestTemplates[l])]; score = score * kmersize * M + (n_kmers - score) * MM; if(score > bestScore) { bestScore = score; bestHits = 1; bestTemplates[bestHits] = template; } else if(score == bestScore) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; } *bestTemplates = bestHits; */ } else { /* for(l = *bestTemplates; l != 0; --l) { Score[bestTemplates[l]] = 0; } *bestTemplates = 0; */ *bestTemplates = clearScore(bestTemplates, Score); } end = n_kmers - hitCounter - bestScore; } else { flag = 0; HIT = exhaustive; j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; } if(HIT) { last = 0; reps = 0; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { ++reps; } else { if(last) { if(SU) { values_s = (short unsigned *) values; n = *values_s; for(l = 1; l <= n; ++l) { if(Score[(template = values_s[l])]) { Score[template] += reps; } else { Score[template] = reps; bestTemplates[0]++; bestTemplates[*bestTemplates] = template; } } } else { n = *values; for(l = 1; l <= n; ++l) { if(Score[(template = last[l])]) { Score[template] += reps; } else { Score[template] = reps; bestTemplates[0]++; bestTemplates[*bestTemplates] = template; } } } hitCounter += reps; } reps = 1; last = values; } } } j = qseq->N[i] + 1; } if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s; for(l = 1; l <= n; ++l) { if(Score[(template = values_s[l])]) { Score[template] += reps; } else { Score[template] = reps; bestTemplates[0]++; bestTemplates[*bestTemplates] = template; } } } else { n = *last; for(l = 1; l <= n; ++l) { if(Score[(template = last[l])]) { Score[template] += reps; } else { Score[template] = reps; bestTemplates[0]++; bestTemplates[*bestTemplates] = template; } } } hitCounter += reps; } } qseq->N[0]--; /* get best match(es) */ /*if(hitCounter * kmersize > (end - hitCounter + kmersize)) {*/ if(hitCounter) { bestScore = getMatch(bestTemplates, Score); } else { *bestTemplates = clearScore(bestTemplates, Score); } end = qseq->seqlen + 1 - bestScore; } i = 0; if(kmersize <= bestScore || bestScore * kmersize > end) { lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, bestScore, header, flag, out); unlock(excludeOut); } return i; } int save_kmers_pseuodeSparse(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { int i, j, l, n, end, template, hitCounter, gaps, Ms, MMs, Us, W1s; int HIT, SU, score, bestScore, kmersize, W1, U, M, MM, m, mm; unsigned shifter, *values, *last; short unsigned *values_s; char *include; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 1; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); W1 = rewards->W1; U = rewards->U; M = rewards->M; MM = rewards->MM; *bestTemplates = 0; hitCounter = 0; bestScore = 0; end = qseq->seqlen; HIT = exhaustive; include = (char *) (extendScore + (templates->DB_size + 1)); j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; } if(HIT) { last = 0; gaps = 0; HIT = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; j = 0; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { /* gaps == 0 -> Match gaps == kmersize -> 1 MM kmersize < gaps -> several mismatches or indel(s) gaps < kmersize -> deletion */ if(gaps == 0) { /* match */ ++Ms; } else if(gaps == kmersize) { /* snp */ Ms += kmersize; ++MMs; } else if(kmersize < gaps) { /* mismatch or insersion */ Ms += kmersize; gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { MMs += mm; Ms += m; } else { ++W1s; Us += (gaps -1); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ HIT = j; gaps = 0; } else { if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; values_s = (short unsigned *) last; l = SU ? (*values_s + 1) : (*last + 1); while(--l) { template = SU ? *++values_s : *++last; Score[template] += score; extendScore[template] = HIT; } HIT = j - 1; last = values; score = kmersize * M; values_s = (short unsigned *) values; n = SU ? *values_s : *values; l = n + 1; while(--l) { template = SU ? *++values_s : *++values; if(Score[template] != 0) { gaps = HIT - extendScore[template]; if(gaps == 0) { /* match */ Score[template] += M; } else if(gaps == kmersize) { /* snp */ Score[template] += score + MM; } else if(kmersize < gaps) { /* mismatch or insersion */ gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { Score[template] += score + (mm * MM + m * M); } else { Score[template] += score + (W1 + (gaps - 1) * U); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ } else { Score[template] = score; if(include[template] == 0) { include[template] = 1; bestTemplates[++*bestTemplates] = template; } } } } else { last = values; values_s = (short unsigned *) values; n = SU ? *values_s : *values; Ms = kmersize * M; for(l = 1; l <= n; ++l) { template = SU ? *++values_s : *++values; Score[template] = Ms; include[template] = 1; bestTemplates[l] = template; } *bestTemplates = n; } HIT = j; gaps = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; } ++hitCounter; } else { ++gaps; } } gaps += (qseq->N[i] + 1 - j); /* gap over N's */ j = qseq->N[i] + 1; } if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; if(SU) { values_s = (short unsigned *) last; l = (*values_s) + 1; while(--l) { Score[values_s[l]] += score; } } else { l = (*last) + 1; while(--l) { Score[last[l]] += score; } } for(l = *bestTemplates; l != 0; --l) { extendScore[(template = bestTemplates[l])] = 0; include[template] = 0; if(Score[template] < 0) { Score[template] = 0; } } } } qseq->N[0]--; /* get best match(es) */ /*clearScore(bestTemplates, extendScore);*/ /*if(hitCounter * kmersize > (end - hitCounter + kmersize)) {*/ if(hitCounter) { bestScore = getMatch(bestTemplates, Score); /* bestHits = 0; for(l = 1; l <= *bestTemplates; ++l) { if(Score[(template = bestTemplates[l])] > bestScore) { bestScore = Score[template]; bestHits = 1; bestTemplates[bestHits] = template; } else if(Score[template] == bestScore) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; extendScore[template] = 0; } *bestTemplates = bestHits; */ } else { *bestTemplates = clearScore(bestTemplates, Score); /* for(l = *bestTemplates; l != 0; --l) { extendScore[(template = bestTemplates[l])] = 0; Score[template] = 0; } *bestTemplates = 0; */ } end = qseq->seqlen + 1 - bestScore; i = 0; if(kmersize <= bestScore || bestScore * kmersize > end) { lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, bestScore, header, 0, out); unlock(excludeOut); } return i; } int save_kmers(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { int i, j, l, end, HIT, gaps, score, Ms, MMs, Us, W1s, W1, U, M, MM; int template, hitCounter, bestScore, bestScore_r, kmersize, m, mm; unsigned *values, *last, n, SU, shifter; short unsigned *values_s; char *include; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 1; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } bestScore = 0; bestScore_r = 0; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); W1 = rewards->W1; U = rewards->U; M = rewards->M; MM = rewards->MM; include = (char *) (extendScore + (templates->DB_size + 1)); /* reverse complement qseq */ rc_comp(qseq, qseq_r); /* Search forward strand */ /* Make quick check of the qseq */ HIT = exhaustive; j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; while(j < end && hashMap_get(templates, getKmer(qseq->seq, j, shifter)) == 0) { j += kmersize; } if(j < end) { HIT = 1; } else { j = qseq->N[i] + 1; } /* end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; */ } /* If deltamer qseq hits, then continue */ if(HIT) { /* Scan the deltamer exhaustively, and collect scores in Score*/ hitCounter = 0; *bestTemplates = 0; last = 0; gaps = 0; HIT = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; j = 0; end = qseq->seqlen; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { /* gaps == 0 -> Match gaps == kmersize -> 1 MM kmersize < gaps -> several mismatches or indel(s) gaps < kmersize -> deletion */ if(gaps == 0) { /* match */ ++Ms; } else if(gaps == kmersize) { /* snp */ Ms += kmersize; ++MMs; } else if(kmersize < gaps) { /* mismatch or insersion */ Ms += kmersize; gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { MMs += mm; Ms += m; } else { ++W1s; Us += (gaps -1); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ HIT = j; gaps = 0; } else { if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; values_s = (short unsigned *) last; l = SU ? (*values_s + 1) : (*last + 1); while(--l) { template = SU ? *++values_s : *++last; Score[template] += score; extendScore[template] = HIT; } HIT = j - 1; last = values; score = kmersize * M; values_s = (short unsigned *) values; n = SU ? *values_s : *values; l = n + 1; while(--l) { template = SU ? *++values_s : *++values; if(Score[template] != 0) { gaps = HIT - extendScore[template]; if(gaps == 0) { /* match */ Score[template] += M; } else if(gaps == kmersize) { /* snp */ Score[template] += score + MM; } else if(kmersize < gaps) { /* mismatch or insersion */ gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { Score[template] += score + (mm * MM + m * M); } else { Score[template] += score + (W1 + (gaps - 1) * U); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ } else { Score[template] = score; if(include[template] == 0) { include[template] = 1; bestTemplates[++*bestTemplates] = template; } } } } else { last = values; values_s = (short unsigned *) values; n = SU ? *values_s : *values; Ms = kmersize * M; for(l = 1; l <= n; ++l) { template = SU ? *++values_s : *++values; Score[template] = Ms; include[template] = 1; bestTemplates[l] = template; } *bestTemplates = n; } HIT = j; gaps = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; } ++hitCounter; } else { ++gaps; } } gaps += (qseq->N[i] + 1 - j); /* gap over N's */ j = qseq->N[i] + 1; } if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; if(SU) { values_s = (short unsigned *) last; l = (*values_s) + 1; while(--l) { Score[values_s[l]] += score; } } else { l = (*last) + 1; while(--l) { Score[last[l]] += score; } } for(l = *bestTemplates; l != 0; --l) { extendScore[(template = bestTemplates[l])] = 0; include[template] = 0; if(Score[template] < 0) { Score[template] = 0; } } } /* get best match(es) */ /* clearScore(bestTemplates, extendScore); */ /* if(hitCounter * kmersize > (end - hitCounter - kmersize)) { */ if(hitCounter) { bestScore = getMatch(bestTemplates, Score); /* bestHits = 0; for(l = 1; l <= *bestTemplates; ++l) { if(Score[(template = bestTemplates[l])] > bestScore) { bestScore = Score[template]; bestHits = 1; bestTemplates[bestHits] = template; } else if(Score[template] == bestScore) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; extendScore[template] = 0; } *bestTemplates = bestHits; */ } else { /* for(l = *bestTemplates; l != 0; --l) { extendScore[(template = bestTemplates[l])] = 0; Score[template] = 0; } */ *bestTemplates = clearScore(bestTemplates, Score); } } qseq->N[0]--; /* search rc strand */ /* Make quick check of the qseq */ HIT = exhaustive; j = 0; qseq_r->N[0]++; qseq_r->N[qseq_r->N[0]] = qseq_r->seqlen; for(i = 1; i <= qseq_r->N[0] && !HIT; ++i) { end = qseq_r->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq_r->seq, j, shifter))) { HIT = 1; } } j = qseq_r->N[i] + 1; } /* If deltamer qseq hits, then continue */ if(HIT) { /* Scan the deltamer exhaustively, and collect scores in Score*/ hitCounter = 0; *bestTemplates_r = 0; last = 0; gaps = 0; HIT = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; j = 0; end = qseq_r->seqlen; for(i = 1; i <= qseq_r->N[0]; ++i) { end = qseq_r->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq_r->seq, j, shifter)))) { if(values == last) { /* gaps == 0 -> Match gaps == kmersize -> 1 MM kmersize < gaps -> several mismatches or indel(s) gaps < kmersize -> deletion */ if(gaps == 0) { /* match */ ++Ms; } else if(gaps == kmersize) { /* snp */ Ms += kmersize; ++MMs; } else if(kmersize < gaps) { /* mismatch or insersion */ Ms += kmersize; gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { MMs += mm; Ms += m; } else { ++W1s; Us += (gaps -1); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ HIT = j; gaps = 0; } else { if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; values_s = (short unsigned *) last; l = SU ? (*values_s + 1) : (*last + 1); while(--l) { template = SU ? *++values_s : *++last; Score_r[template] += score; extendScore[template] = HIT; } HIT = j - 1; last = values; score = kmersize * M; values_s = (short unsigned *) values; n = SU ? *values_s : *values; l = n + 1; while(--l) { template = SU ? *++values_s : *++values; if(Score_r[template] != 0) { gaps = HIT - extendScore[template]; if(gaps == 0) { /* match */ Score_r[template] += M; } else if(gaps == kmersize) { /* snp */ Score_r[template] += score + MM; } else if(kmersize < gaps) { /* mismatch or insersion */ gaps -= (kmersize - 1); /* adjust for consecutive k-mer mismatches */ if(gaps <= 2) { mm = gaps; m = 0; } else { mm = gaps / kmersize + (gaps % kmersize ? 1 : 0); mm = MAX(2, mm); m = MIN(gaps - mm, kmersize); m = MIN(m, mm); } /* evaluate best option */ if((W1 + (gaps - 1) * U) <= (mm * MM + m * M)) { Score_r[template] += score + (mm * MM + m * M); } else { Score_r[template] += score + (W1 + (gaps - 1) * U); } } /*else { // unlikely deletion or random k-mer mismatch, // assume better and go random zero score }*/ } else { Score_r[template] = score; if(include[template] == 0) { include[template] = 1; bestTemplates_r[++*bestTemplates_r] = template; } } } } else { last = values; values_s = (short unsigned *) values; n = SU ? *values_s : *values; Ms = kmersize * M; for(l = 1; l <= n; ++l) { template = SU ? *++values_s : *++values; Score_r[template] = Ms; include[template] = 1; bestTemplates_r[l] = template; } *bestTemplates_r = n; } HIT = j; gaps = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; } ++hitCounter; } else { ++gaps; } } gaps += (qseq->N[i] + 1 - j); /* gap over N's */ j = qseq_r->N[i] + 1; } if(last) { score = Ms * M + MMs * MM + Us * U + W1s * W1; if(SU) { values_s = (short unsigned *) last; l = (*values_s) + 1; while(--l) { Score_r[values_s[l]] += score; } } else { l = (*last) + 1; while(--l) { Score_r[last[l]] += score; } } for(l = *bestTemplates_r; l != 0; --l) { extendScore[(template = bestTemplates_r[l])] = 0; include[template] = 0; if(Score_r[template] < 0) { Score_r[template] = 0; } } } /* get best match(es) */ /*clearScore(bestTemplates_r, extendScore);*/ /*if(hitCounter * kmersize > (end - hitCounter + kmersize)) {*/ if(hitCounter) { bestScore_r = getMatch(bestTemplates_r, Score_r); /* bestHits = 0; for(l = 1; l <= *bestTemplates_r; ++l) { if(Score_r[(template = bestTemplates_r[l])] > bestScore_r) { bestScore_r = Score_r[template]; bestHits = 1; bestTemplates_r[bestHits] = template; } else if(Score_r[template] == bestScore_r) { ++bestHits; bestTemplates_r[bestHits] = template; } Score_r[template] = 0; extendScore[template] = 0; } *bestTemplates_r = bestHits; */ } else { /* for(l = *bestTemplates_r; l != 0; --l) { extendScore[(template = bestTemplates_r[l])] = 0; Score_r[template] = 0; } */ *bestTemplates_r = clearScore(bestTemplates_r, Score_r); } } qseq_r->N[0]--; /* Validate best match */ i = 0; if(bestScore > 0 || bestScore_r > 0) { end = qseq->seqlen + 1; //if((bestScore >= bestScore_r && bestScore * kmersize > (end - bestScore)) || (bestScore < bestScore_r && bestScore_r * kmersize > (end - bestScore_r))) { if(kmersize <= bestScore || kmersize <= bestScore_r) { if(bestScore > bestScore_r) { lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, bestScore, header, 0, out); unlock(excludeOut); } else if(bestScore < bestScore_r) { lock(excludeOut); i = deConPrintPtr(bestTemplates_r, qseq_r, bestScore_r, header, 16, out); unlock(excludeOut); } else { /* merge */ for(i = 1; i <= *bestTemplates_r; ++i) { bestTemplates[0]++; bestTemplates[*bestTemplates] = -bestTemplates_r[i]; } lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, -bestScore, header, 0, out); unlock(excludeOut); } } } return i; } int save_kmers_count(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { int i, j, end, HIT, hitCounter, bestScore, bestScore_r, reps, n, SU; unsigned kmersize, shifter, *values, *last; short unsigned *values_s; if(qseq->seqlen < (kmersize = templates->kmersize)) { return 1; } else if(templates->DB_size < USHRT_MAX) { SU = 1; } else { SU = 0; } bestScore = 0; bestScore_r = 0; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); /* reverse complement qseq */ rc_comp(qseq, qseq_r); /* Search forward strand */ /* Make quick check of the qseq */ HIT = exhaustive; j = 0; qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; for(i = 1; i <= qseq->N[0] && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq->seq, j, shifter))) { HIT = 1; } } j = qseq->N[i] + 1; } /* If deltamer qseq hits, then continue */ if(HIT) { /* Scan the deltamer exhaustively, and collect scores in Score*/ hitCounter = 0; *bestTemplates = 0; last = 0; reps = 0; j = 0; end = qseq->seqlen; for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { ++reps; } else { if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s + 1; while(--n) { if((Score[*++values_s] += reps) == reps) { bestTemplates[++*bestTemplates] = *values_s; } } } else { n = *last + 1; while(--n) { if((Score[*++last] += reps) == reps) { bestTemplates[++*bestTemplates] = *last; } } } hitCounter += reps; } reps = 1; last = values; } } } j = qseq->N[i] + 1; } if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s + 1; while(--n) { if((Score[*++values_s] += reps) == reps) { bestTemplates[++*bestTemplates] = *values_s; } } } else { n = *last + 1; while(--n) { if((Score[*++last] += reps) == reps) { bestTemplates[++*bestTemplates] = *last; } } } hitCounter += reps; } reps = 0; /* get best match(es) */ /*if(hitCounter * kmersize > (end - hitCounter + kmersize)) {*/ if(hitCounter) { bestScore = getMatch(bestTemplates, Score); /* bestHits = 0; for(l = 1; l <= *bestTemplates; ++l) { if(Score[(template = bestTemplates[l])] > bestScore) { bestScore = Score[template]; bestHits = 1; bestTemplates[bestHits] = template; } else if(Score[template] == bestScore) { ++bestHits; bestTemplates[bestHits] = template; } Score[template] = 0; } *bestTemplates = bestHits; */ } else { /* for(l = *bestTemplates; l != 0; --l) { Score[bestTemplates[l]] = 0; } */ *bestTemplates = clearScore(bestTemplates, Score); } } qseq->N[0]--; /* search rc strand */ /* Make quick check of the qseq */ HIT = exhaustive; j = 0; qseq_r->N[0]++; qseq_r->N[qseq_r->N[0]] = qseq_r->seqlen; for(i = 1; i <= qseq_r->N[0] && !HIT; ++i) { end = qseq_r->N[i] - kmersize + 1; for(;j < end && !HIT; j += kmersize) { if(hashMap_get(templates, getKmer(qseq_r->seq, j, shifter))) { HIT = 1; } } j = qseq_r->N[i] + 1; } /* If deltamer qseq hits, then continue */ if(HIT) { /* Scan the deltamer exhaustively, and collect scores in Score*/ hitCounter = 0; *bestTemplates_r = 0; last = 0; reps = 0; j = 0; end = qseq_r->seqlen; for(i = 1; i <= qseq_r->N[0]; ++i) { end = qseq_r->N[i] - kmersize + 1; for(;j < end; ++j) { if((values = hashMap_get(templates, getKmer(qseq_r->seq, j, shifter)))) { if(values == last) { ++reps; } else { if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s + 1; while(--n) { if((Score_r[*++values_s] += reps) == reps) { bestTemplates_r[++*bestTemplates_r] = *values_s; } } } else { n = *last + 1; while(--n) { if((Score_r[*++last] += reps) == reps) { bestTemplates_r[++*bestTemplates_r] = *last; } } } hitCounter += reps; } last = values; reps = 1; } } } j = qseq_r->N[i] + 1; } if(last) { if(SU) { values_s = (short unsigned *) last; n = *values_s + 1; while(--n) { if((Score_r[*++values_s] += reps) == reps) { bestTemplates_r[++*bestTemplates_r] = *values_s; } } } else { n = *last + 1; while(--n) { if((Score_r[*++last] += reps) == reps) { bestTemplates_r[++*bestTemplates_r] = *last; } } } hitCounter += reps; } reps = 0; /* get best match(es) */ /*if(hitCounter * kmersize > (end - hitCounter + kmersize)) {*/ if(hitCounter) { bestScore_r = getMatch(bestTemplates_r, Score_r); /* bestHits = 0; for(l = 1; l <= *bestTemplates_r; ++l) { if(Score_r[(template = bestTemplates_r[l])] > bestScore_r) { bestScore_r = Score_r[template]; bestHits = 1; bestTemplates_r[bestHits] = template; } else if(Score_r[template] == bestScore_r) { ++bestHits; bestTemplates_r[bestHits] = template; } Score_r[template] = 0; } *bestTemplates_r = bestHits; */ } else { /* for(l = *bestTemplates_r; l != 0; --l) { Score_r[bestTemplates_r[l]] = 0; } */ *bestTemplates_r = clearScore(bestTemplates_r, Score_r); } } qseq_r->N[0]--; /* Validate best match */ i = 0; if(bestScore > 0 || bestScore_r > 0) { end = qseq->seqlen + 1; //if((bestScore >= bestScore_r && bestScore * kmersize > (end - bestScore)) || (bestScore < bestScore_r && bestScore_r * kmersize > (end - bestScore_r))) { if(kmersize <= bestScore || kmersize <= bestScore_r) { if(bestScore > bestScore_r) { lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, bestScore, header, 0, out); unlock(excludeOut); } else if(bestScore < bestScore_r) { lock(excludeOut); i = deConPrintPtr(bestTemplates_r, qseq_r, bestScore_r, header, 16, out); unlock(excludeOut); } else { /* merge */ for(i = 1; i <= *bestTemplates_r; ++i) { bestTemplates[0]++; bestTemplates[*bestTemplates] = -bestTemplates_r[i]; } lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, -bestScore, header, 0, out); unlock(excludeOut); } } } return i; } int save_kmers_unionPair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, const Qseqs *header_r, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { int i, bestScore, bestScore_r, hitCounter, kmersize, flag, flag_r, rev; /* get_kmers_for_pair, returns a positive number if templates are found. zero otherwise */ kmersize = templates->kmersize; if(templates->prefix_len == 0 && templates->prefix != 0) { rev = 0; } else { rev = 1; } /* get forward */ /*if((hitCounter = get_kmers_for_pair_ptr(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq, extendScore, exhaustive)) && (qseq->seqlen - hitCounter - kmersize) < hitCounter * kmersize) {*/ if((hitCounter = get_kmers_for_pair_ptr(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq, extendScore, exhaustive))) { /* got hits */ bestScore = getF(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates); if(kmersize < bestScore && bestScore * kmersize < (qseq->seqlen - bestScore)) { bestScore = 0; } } else { bestScore = 0; if(hitCounter) { i = *bestTemplates + 1; while(--i) { Score[bestTemplates[i]] = 0; } *bestTemplates = 0; i = *bestTemplates_r + 1; while(--i) { Score_r[bestTemplates_r[i]] = 0; } *bestTemplates_r = 0; } } *extendScore = 1; /* get reverse */ /*if((hitCounter = get_kmers_for_pair_ptr(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq_r, extendScore, exhaustive)) && (qseq_r->seqlen - hitCounter - kmersize) < hitCounter * kmersize) {*/ if((hitCounter = get_kmers_for_pair_ptr(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq_r, extendScore, exhaustive))) { if(bestScore) { bestScore_r = getR(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates); } else { bestScore_r = getF(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates); } if(kmersize < bestScore_r && bestScore_r * kmersize < (qseq_r->seqlen - bestScore_r)) { bestScore_r = 0; *regionTemplates = abs(*regionTemplates); } } else { bestScore_r = 0; i = *bestTemplates + 1; while(--i) { Score[bestTemplates[i]] = 0; } *bestTemplates = 0; i = *bestTemplates_r + 1; while(--i) { Score_r[bestTemplates_r[i]] = 0; } *bestTemplates_r = 0; } flag = 65; flag_r = 129; if(0 < bestScore && 0 < bestScore_r) { if(*regionTemplates < 0) { flag |= 2; flag_r |= 2; *regionTemplates = -(*regionTemplates); if(0 < regionTemplates[1]) { if(rev) { flag |= 32; flag_r |= 16; comp_rc(qseq); } else { flag |= 16; flag_r |= 32; comp_rc(qseq_r); } if(regionTemplates[*regionTemplates] < 0) { bestScore = -bestScore; bestScore_r = -bestScore_r; } lock(excludeOut); i = printPairPtr(regionTemplates, qseq, bestScore, header, qseq_r, bestScore_r, header_r, flag, flag_r, out); unlock(excludeOut); } else { if(rev) { flag |= 16; flag_r |= 32; comp_rc(qseq_r); } else { flag |= 32; flag_r |= 16; comp_rc(qseq); } for(i = *regionTemplates; i != 0; --i) { regionTemplates[i] = -regionTemplates[i]; } lock(excludeOut); i = printPairPtr(regionTemplates, qseq_r, bestScore_r, header_r, qseq, bestScore, header, flag_r, flag, out); unlock(excludeOut); } if(i) { i = 3; } else { i = 0; } } else { if(0 < regionTemplates[1]) { if(rev) { comp_rc(qseq); } if(regionTemplates[*regionTemplates] < 0) { bestScore = -bestScore; } } else { if(rev) { flag |= 16; flag_r |= 32; } for(i = 1; i <= *regionTemplates; ++i) { regionTemplates[i] = -regionTemplates[i]; } } if(0 < bestTemplates[1]) { if(rev) { comp_rc(qseq_r); } if(bestTemplates[*bestTemplates] < 0) { bestScore_r = -bestScore_r; } } else { if(rev) { flag |= 32; flag_r |= 16; } for(i = 1; i <= *bestTemplates; ++i) { bestTemplates[i] = -bestTemplates[i]; } } lock(excludeOut); i = deConPrintPtr(regionTemplates, qseq, bestScore, header, flag, out); if(deConPrintPtr(bestTemplates, qseq_r, bestScore_r, header_r, flag_r, out)) { i += 2; } unlock(excludeOut); } return i; } else if(bestScore) { if(rev) { flag |= 8; flag |= 32; } if(0 < regionTemplates[1]) { if(rev) { comp_rc(qseq); } if(regionTemplates[*regionTemplates] < 0) { bestScore = -bestScore; } } else { if(rev) { flag |= 16; } for(i = 1; i <= *regionTemplates; ++i) { regionTemplates[i] = -regionTemplates[i]; } } lock(excludeOut); i = deConPrintPtr(regionTemplates, qseq, bestScore, header, flag, out); unlock(excludeOut); if(i == 0) { return 2; } } else if(bestScore_r) { if(rev) { flag_r |= 8; flag_r |= 32; } if(0 < regionTemplates[1]) { if(rev) { comp_rc(qseq_r); } if(regionTemplates[*regionTemplates] < 0) { bestScore_r = -bestScore_r; } } else { if(rev) { flag_r |= 16; } for(i = 1; i <= *regionTemplates; ++i) { regionTemplates[i] = -regionTemplates[i]; } } lock(excludeOut); i = deConPrintPtr(regionTemplates, qseq_r, bestScore_r, header_r, flag_r, out); unlock(excludeOut); if(i == 0) { return 1; } } return 3; } int save_kmers_penaltyPair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, const Qseqs *header_r, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { int i, bestScore, bestScore_r, compScore, hitCounter, hitCounter_r; int kmersize, flag, flag_r, rev; /* get_kmers_for_pair, returns a positive number if templates are found. zero otherwise */ kmersize = templates->kmersize; if(templates->prefix_len == 0 && templates->prefix != 0) { rev = 0; } else { rev = 1; } /* get forward */ if((hitCounter = get_kmers_for_pair_ptr(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq, extendScore, exhaustive))) { /* got hits */ bestScore = getFirstPen(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates, regionScores); } else { bestScore = 0; } *extendScore = 1; /* get reverse */ if((hitCounter_r = get_kmers_for_pair_ptr(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq_r, extendScore, exhaustive))) { if(0 < bestScore) { bestScore_r = getSecondPen(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates, regionScores, bestScore, rewards->PE); } else { bestScore_r = getF(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates); } } else { bestScore_r = 0; } flag = 65; flag_r = 129; if(0 < bestScore && 0 < bestScore_r) { if(*regionTemplates < 0) { flag |= 2; flag_r |= 2; compScore = MIN((hitCounter + hitCounter_r), (bestScore + bestScore_r)); if(kmersize <= compScore || (qseq->seqlen + qseq_r->seqlen - compScore - (kmersize << 1)) < compScore * kmersize) { *regionTemplates = -(*regionTemplates); if(0 < regionTemplates[1]) { if(rev) { flag |= 32; flag_r |= 16; comp_rc(qseq); } else { flag |= 16; flag_r |= 32; comp_rc(qseq_r); } if(regionTemplates[*regionTemplates] < 0) { bestScore = -bestScore; bestScore_r = -bestScore_r; } lock(excludeOut); i = printPairPtr(regionTemplates, qseq, bestScore, header, qseq_r, bestScore_r, header_r, flag, flag_r, out); unlock(excludeOut); } else { if(rev) { flag |= 16; flag_r |= 32; comp_rc(qseq_r); } else { flag |= 32; flag_r |= 16; comp_rc(qseq); } for(i = *regionTemplates; i != 0; --i) { regionTemplates[i] = -regionTemplates[i]; } lock(excludeOut); i = printPairPtr(regionTemplates, qseq_r, bestScore_r, header_r, qseq, bestScore, header, flag_r, flag, out); unlock(excludeOut); } if(i) { i = 3; } else { i = 0; } } else { i = 3; } } else { hitCounter = MIN(hitCounter, bestScore); hitCounter = kmersize <= hitCounter || (qseq->seqlen - hitCounter - kmersize) < hitCounter * kmersize; if(hitCounter) { if(0 < regionTemplates[1]) { if(rev) { comp_rc(qseq); } if(regionTemplates[*regionTemplates] < 0) { bestScore = -bestScore; } } else { if(rev) { flag |= 16; flag_r |= 32; } for(i = *regionTemplates; i != 0; --i) { regionTemplates[i] = -regionTemplates[i]; } } } hitCounter_r = MIN(hitCounter_r, bestScore_r); hitCounter_r = kmersize <= hitCounter_r || (qseq_r->seqlen - hitCounter_r - kmersize) < hitCounter_r * kmersize; if(hitCounter_r) { if(0 < bestTemplates[1]) { if(rev) { comp_rc(qseq_r); } if(bestTemplates[*bestTemplates] < 0) { bestScore_r = -bestScore_r; } } else { if(rev) { flag |= 32; flag_r |= 16; } for(i = *bestTemplates; i != 0; --i) { bestTemplates[i] = -bestTemplates[i]; } } } if(hitCounter) { lock(excludeOut); i = deConPrintPtr(regionTemplates, qseq, bestScore, header, flag, out); unlock(excludeOut); } else { i = 1; } if(hitCounter_r) { lock(excludeOut); if(deConPrintPtr(bestTemplates, qseq_r, bestScore_r, header_r, flag_r, out)) { i += 2; } unlock(excludeOut); } else { i += 2; } } return i; } else if(0 < bestScore) { hitCounter = MIN(hitCounter, bestScore); if(kmersize <= hitCounter || (qseq->seqlen - hitCounter - kmersize) < hitCounter * kmersize) { if(rev) { flag |= 8; flag |= 32; } if(0 < regionTemplates[1]) { if(rev) { comp_rc(qseq); } if(regionTemplates[*regionTemplates] < 0) { bestScore = -bestScore; } } else { if(rev) { flag |= 16; } for(i = *regionTemplates; i != 0; --i) { regionTemplates[i] = -regionTemplates[i]; } } lock(excludeOut); i = deConPrintPtr(regionTemplates, qseq, bestScore, header, flag, out); unlock(excludeOut); } else { i = 1; } if(i == 0) { return 2; } } else if(0 < bestScore_r) { hitCounter_r = MIN(hitCounter_r, bestScore_r); if(kmersize <= hitCounter_r || (qseq_r->seqlen - hitCounter_r - kmersize) < hitCounter_r * kmersize) { if(rev) { flag_r |= 8; flag_r |= 32; } if(0 < regionTemplates[1]) { if(rev) { comp_rc(qseq_r); } if(regionTemplates[*regionTemplates] < 0) { bestScore_r = -bestScore_r; } } else { if(rev) { flag_r |= 16; } for(i = 1; i <= *regionTemplates; ++i) { regionTemplates[i] = -regionTemplates[i]; } } lock(excludeOut); i = deConPrintPtr(regionTemplates, qseq_r, bestScore_r, header_r, flag_r, out); unlock(excludeOut); } else { i = 1; } if(i == 0) { return 1; } } return 3; } int save_kmers_forcePair(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, int *regionTemplates, int *regionScores, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, const Qseqs *header_r, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { int i, bestScore, hitCounter, hitCounter_r, kmersize, flag, flag_r, rev; /* get_kmers_for_pair, returns a positive number if templates are found. zero otherwise */ kmersize = templates->kmersize; if(templates->prefix_len == 0 && templates->prefix != 0) { rev = 0; } else { rev = 1; } /* get forward */ if((hitCounter = get_kmers_for_pair_ptr(templates, rewards, bestTemplates, bestTemplates_r, Score, Score_r, qseq, extendScore, exhaustive))) { /* got hits */ getFirstForce(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates, regionScores); } else { return 1; } *extendScore = 1; /* get reverse */ /*if((hitCounter_r = get_kmers_for_pair_ptr(templates, rewards, bestTemplates_r, bestTemplates, Score_r, Score, qseq_r, extendScore, exhaustive)) && (qseq->seqlen + qseq_r->seqlen - hitCounter - hitCounter_r - (kmersize << 1)) < (hitCounter + hitCounter_r) * kmersize && (bestScore = getSecondForce(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates, regionScores))) {*/ if((hitCounter_r = get_kmers_for_pair_ptr(templates, rewards, bestTemplates_r, bestTemplates, Score_r, Score, qseq_r, extendScore, exhaustive)) && (bestScore = getSecondForce(bestTemplates, bestTemplates_r, Score, Score_r, regionTemplates, regionScores))) { if(kmersize <= bestScore || (qseq->seqlen + qseq_r->seqlen - bestScore) < bestScore * kmersize) { flag = 67; flag_r = 131; if(regionTemplates[*regionTemplates] < 0) { bestScore = -bestScore; } if(0 < regionTemplates[1]) { if(rev) { flag |= 32; flag_r |= 16; comp_rc(qseq); } else { flag |= 16; flag_r |= 32; comp_rc(qseq_r); } lock(excludeOut); i = printPairPtr(regionTemplates, qseq, bestScore, header, qseq_r, bestScore, header_r, flag, flag_r, out); unlock(excludeOut); } else { if(rev) { flag |= 16; flag_r |= 32; comp_rc(qseq_r); } else { flag |= 32; flag_r |= 16; comp_rc(qseq); } for(i = *regionTemplates; i != 0; --i) { regionTemplates[i] = -regionTemplates[i]; } lock(excludeOut); i = printPairPtr(regionTemplates, qseq_r, bestScore, header_r, qseq, bestScore, header, flag_r, flag, out); unlock(excludeOut); } } else { i = 1; } if(i == 0) { return 0; } } else if(hitCounter || hitCounter_r) { i = *bestTemplates + 1; while(--i) { Score[bestTemplates[i]] = 0; } *bestTemplates = 0; i = *bestTemplates_r + 1; while(--i) { Score_r[bestTemplates_r[i]] = 0; } *bestTemplates_r = 0; } return 3; } int save_kmers_HMM(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *headerOrg, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { /* save_kmers find ankering k-mers the in query sequence, and is the time determining step */ static int **RegionTemplates, **TmpNs, *Sizes, *template_lengths, minLen = 0; static unsigned ***tVF_scores, ***tVR_scores; int i, j, k, l, N, n, i_r, j_r, seqlen, seqend, end, HIT, Ncheck, SU; int hitCounter, template, bestScore, bestHits, start, stop, kmersize; int start_cut, end_cut, DB_size, deCon, returner, *regionTemplates; unsigned *values, *last, *rlast, **VF_scores, **VR_scores, num, shifter; short unsigned *values_s; int *tmpNs, reps, rreps; double Ms, Ns, Ms_prev, Ns_prev, HMM_param[8]; char *include; Qseqs *header; if(qseq == 0 || qseq->seqlen < (kmersize = templates->kmersize)) { if(minLen == 0) { /* initial allocate */ template_lengths = bestTemplates_r; n = *bestTemplates; Sizes = smalloc(n * sizeof(int)); tVF_scores = smalloc(n * sizeof(int **)); tVR_scores = smalloc(n * sizeof(int **)); RegionTemplates = smalloc(n * sizeof(int*)); TmpNs = smalloc(n * sizeof(int *)); i = n; while(i--) { RegionTemplates[i] = smalloc(((templates->DB_size << 1) + 4) * sizeof(int)); Sizes[i] = 256; TmpNs[i] = smalloc(256 * sizeof(int)); tVF_scores[i] = calloc(256, sizeof(unsigned *)); tVR_scores[i] = calloc(256, sizeof(unsigned *)); if(!tVF_scores[i] || !tVR_scores[i]) { ERROR(); } } /* set minLen */ /* minLen = *template_lengths >> 1; i = templates->DB_size; while(--i) { if(minLen > ++*template_lengths >> 1)) { minLen = *template_lengths >> 1; } } minLen = exhaustive < minLen ? minLen : exhaustive; */ minLen = exhaustive; } return 1; } else if((DB_size = templates->DB_size) < USHRT_MAX) { SU = 1; } else { SU = 0; } returner = 1; deCon = deConPrintPtr == &deConPrint; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); header = (Qseqs *) headerOrg; include = (char *) (extendScore + (templates->DB_size + 1)); /* calculate HMM parameters */ HMM_param[0] = log(1 - pow(0.25, kmersize)); HMM_param[1] = log(pow(0.25, kmersize)); HMM_param[2] = log(1 - pow(0.25, kmersize - 1) * 0.75); HMM_param[3] = log(pow(0.25, kmersize - 1) * 0.75); HMM_param[4] = log(1 - 1.0 / kmersize * 0.75 * 0.25); HMM_param[5] = log(1.0 / kmersize * 0.75 * 0.25); HMM_param[6] = log(0.75); HMM_param[7] = log(0.25); if(Sizes[*Score] < qseq->size) { Sizes[*Score] = qseq->size; free(tVF_scores[*Score]); free(tVR_scores[*Score]); free(TmpNs[*Score]); TmpNs[*Score] = smalloc(qseq->size * sizeof(int)); tVF_scores[*Score] = calloc(qseq->size, sizeof(unsigned *)); tVR_scores[*Score] = calloc(qseq->size, sizeof(unsigned *)); if(!tVF_scores[*Score] || !tVR_scores[*Score]) { ERROR(); } } regionTemplates = RegionTemplates[*Score]; *regionTemplates++ = templates->DB_size; *regionTemplates++ = *Score; *regionTemplates++ = 0; VF_scores = tVF_scores[*Score]; VR_scores = tVR_scores[*Score]; tmpNs = TmpNs[*Score]; /* reverse complement qseq */ rc_comp(qseq, qseq_r); seqlen = qseq->seqlen; seqend = seqlen - kmersize + 1; i = 0; i_r = seqlen - kmersize; N = 1; qseq->N[0]++; qseq->N[qseq->N[0]] = seqlen; while(N <= qseq->N[0]) { /* find a seed */ HIT = 0; end = qseq->N[N] - kmersize + 1; if(exhaustive) { while(i < end && !HIT) { if(hashMap_get(templates, getKmer(qseq->seq, i, shifter)) || hashMap_get(templates, getKmer(qseq_r->seq, i_r, shifter))) { HIT = 1; } else { ++i; --i_r; } } } else { while(i < end && !HIT) { if(hashMap_get(templates, getKmer(qseq->seq, i, shifter)) || hashMap_get(templates, getKmer(qseq_r->seq, i_r, shifter))) { HIT = 1; } else { i += kmersize; i_r -= kmersize; } } } /* evaluate seed */ if(HIT) { /* set scores attr */ bestScore = 0; *bestTemplates = 0; hitCounter = 1; /* save seed */ VF_scores[i] = hashMap_get(templates, getKmer(qseq->seq, i, shifter)); VR_scores[i] = hashMap_get(templates, getKmer(qseq_r->seq, i_r, shifter)); /* init HMM */ Ms_prev = HMM_param[7] + HMM_param[2]; Ns_prev = HMM_param[5] + HMM_param[0]; Ms = 0; Ns = 0; /* extend backward */ j = i - 1; j_r = i_r + 1; n = N - 1; Ncheck = (n > 0) ? -1 : qseq->N[n]; while(j >= 0) { if(j == Ncheck) { k = j; while(k >= kmersize && k < (j - kmersize)) { /* update next N check */ if(k == Ncheck) { j = Ncheck; --n; Ncheck = (n > 0) ? -1 : qseq->N[n]; } /* Non match seq */ if(Ns_prev + HMM_param[0] + HMM_param[4] >= Ms_prev + HMM_param[3] + HMM_param[4]) { Ns = Ns_prev + HMM_param[0] + HMM_param[4]; } else { Ns = Ms_prev + HMM_param[3] + HMM_param[4]; } /* Match seq */ if(Ms_prev + HMM_param[2] + HMM_param[6] >= Ns_prev + HMM_param[1] + HMM_param[6]) { Ms = Ms_prev + HMM_param[2] + HMM_param[6]; } else { Ms = Ns_prev + HMM_param[1] + HMM_param[6]; break; } --k; Ns_prev = Ns; Ms_prev = Ms; } if(k >= kmersize && k < (j - kmersize)) { j = k - 1; break; } else { j = k; j_r = seqlen - kmersize - k; } } else { VF_scores[j] = hashMap_get(templates, getKmer(qseq->seq, j, shifter)); VR_scores[j] = hashMap_get(templates, getKmer(qseq_r->seq, j_r, shifter)); /* HMM */ if(VF_scores[j] || VR_scores[j]) { ++hitCounter; /* Non match seq */ if(Ns_prev + HMM_param[0] + HMM_param[5] >= Ms_prev + HMM_param[3] + HMM_param[5]) { Ns = Ns_prev + HMM_param[0] + HMM_param[5]; } else { Ns = Ms_prev + HMM_param[3] + HMM_param[5]; } /* Match seq */ if(Ms_prev + HMM_param[2] + HMM_param[7] >= Ns_prev + HMM_param[1] + HMM_param[7]) { Ms = Ms_prev + HMM_param[2] + HMM_param[7]; } else { Ms = Ns_prev + HMM_param[1] + HMM_param[7]; --j; break; } } else { /* Non match seq */ if(Ns_prev + HMM_param[0] + HMM_param[4] >= Ms_prev + HMM_param[3] + HMM_param[4]) { Ns = Ns_prev + HMM_param[0] + HMM_param[4]; } else { Ns = Ms_prev + HMM_param[3] + HMM_param[4]; } /* Match seq */ if(Ms_prev + HMM_param[2] + HMM_param[6] >= Ns_prev + HMM_param[1] + HMM_param[6]) { Ms = Ms_prev + HMM_param[2] + HMM_param[6]; } else { Ms = Ns_prev + HMM_param[1] + HMM_param[6]; --j; break; } } } --j; ++j_r; Ns_prev = Ns; Ms_prev = Ms; } start = j + 1; /* init HMM */ Ms_prev = HMM_param[7] + HMM_param[2]; Ns_prev = HMM_param[5] + HMM_param[0]; /* extend forward */ j = i + 1; j_r = i_r - 1; Ncheck = qseq->N[N] - kmersize + 1; while(j < seqend) { if(j == Ncheck) { k = j; while(k < seqend && k < (j + kmersize)) { /* update next N check */ if(k == Ncheck) { j = Ncheck; ++N; Ncheck = (N == qseq->N[0]) ? seqlen : qseq->N[N] - kmersize + 1; } /* Non match seq */ if(Ns_prev + HMM_param[0] + HMM_param[4] >= Ms_prev + HMM_param[3] + HMM_param[4]) { Ns = Ns_prev + HMM_param[0] + HMM_param[4]; } else { Ns = Ms_prev + HMM_param[3] + HMM_param[4]; } /* Match seq */ if(Ms_prev + HMM_param[2] + HMM_param[6] >= Ns_prev + HMM_param[1] + HMM_param[6]) { Ms = Ms_prev + HMM_param[2] + HMM_param[6]; } else { Ms = Ns_prev + HMM_param[1] + HMM_param[6]; break; } ++k; Ns_prev = Ns; Ms_prev = Ms; } if(k < seqend && k < (j + kmersize)) { j = k; break; } else { j = k; j_r = seqlen - kmersize - k; } } else { VF_scores[j] = hashMap_get(templates, getKmer(qseq->seq, j, shifter)); VR_scores[j] = hashMap_get(templates, getKmer(qseq_r->seq, j_r, shifter)); /* HMM */ if(VF_scores[j] || VR_scores[j]) { ++hitCounter; /* Non match seq */ if(Ns_prev + HMM_param[0] + HMM_param[5] >= Ms_prev + HMM_param[3] + HMM_param[5]) { Ns = Ns_prev + HMM_param[0] + HMM_param[5]; } else { Ns = Ms_prev + HMM_param[3] + HMM_param[5]; } /* Match seq */ if(Ms_prev + HMM_param[2] + HMM_param[7] >= Ns_prev + HMM_param[1] + HMM_param[7]) { Ms = Ms_prev + HMM_param[2] + HMM_param[7]; } else { Ms = Ns_prev + HMM_param[1] + HMM_param[7]; ++j; break; } } else { /* Non match seq */ if(Ns_prev + HMM_param[0] + HMM_param[4] >= Ms_prev + HMM_param[3] + HMM_param[4]) { Ns = Ns_prev + HMM_param[0] + HMM_param[4]; } else { Ns = Ms_prev + HMM_param[3] + HMM_param[4]; } /* Match seq */ if(Ms_prev + HMM_param[2] + HMM_param[6] >= Ns_prev + HMM_param[1] + HMM_param[6]) { Ms = Ms_prev + HMM_param[2] + HMM_param[6]; } else { Ms = Ns_prev + HMM_param[1] + HMM_param[6]; ++j; break; } } } ++j; --j_r; Ns_prev = Ns; Ms_prev = Ms; } stop = j + kmersize - 1; /* evaluate hit */ /*if(hitCounter > 0 && (hitCounter * kmersize > (stop - start - hitCounter + kmersize)) && ((stop - start) > minLen || start == 0 || stop == seqlen)) {*/ if(hitCounter > 0 && ((stop - start) > minLen || start == 0 || stop == seqlen)) { if(deCon) { if(SU) { for(k = start; k < j; ++k) { if(((values_s = (short unsigned *) VF_scores[k]) && values_s[*values_s] == DB_size) || ((values_s = (short unsigned *) VR_scores[k]) && values_s[*values_s] == DB_size)) { --hitCounter; } } } else { for(k = start; k < j; ++k) { if(((values = VF_scores[k]) && values[*values] == DB_size) || ((values = VR_scores[k]) && values[*values] == DB_size)) { --hitCounter; } } } } /* accept hit */ if(hitCounter > 0) { /* gain total scores and mapping templates for this region */ *bestTemplates = 0; *bestTemplates_r = 0; last = 0; reps = 0; rlast = 0; rreps = 0; for(k = start; k < j; ++k) { /* forward */ if(VF_scores[k]) { if(VF_scores[k] == last) { ++reps; } else { if(last) { if(SU) { values_s = (short unsigned *) last; num = *values_s + 1; while(--num) { if((Score[*++values_s] += reps) == reps) { bestTemplates[++*bestTemplates] = *values_s; } } } else { n = *last + 1; while(--n) { if((Score[*++last] += reps) == reps) { bestTemplates[++*bestTemplates] = *last; } } } } reps = 1; last = VF_scores[k]; } } /* rc */ if(VR_scores[k]) { if(VR_scores[k] == rlast) { ++rreps; } else { if(rlast) { if(SU) { values_s = (short unsigned *) rlast; num = *values_s + 1; while(--num) { if((Score_r[*++values_s] += rreps) == rreps) { bestTemplates_r[++*bestTemplates_r] = *values_s; } } } else { num = *rlast + 1; while(--num) { if((Score_r[*++rlast] += rreps) == rreps) { bestTemplates_r[++*bestTemplates_r] = *rlast; } } } } rreps = 1; rlast = VR_scores[k]; } } } if(last) { if(SU) { values_s = (short unsigned *) last; num = *values_s + 1; while(--num) { if((Score[*++values_s] += reps) == reps) { bestTemplates[++*bestTemplates] = *values_s; } } } else { num = *last + 1; while(--num) { if((Score[*++last] += reps) == reps) { bestTemplates[++*bestTemplates] = *last; } } } } if(rlast) { if(SU) { values_s = (short unsigned *) rlast; num = *values_s + 1; while(--num) { if((Score_r[*++values_s] += rreps) == rreps) { bestTemplates_r[++*bestTemplates_r] = *values_s; } } } else { num = *rlast + 1; while(--num) { if((Score_r[*++rlast] += rreps) == rreps) { bestTemplates_r[++*bestTemplates_r] = *rlast; } } } } /* cut out template hits */ while(HIT != 0) { /* get best score */ bestScore = 0; bestHits = 0; /* forward */ for(k = 1; k <= *bestTemplates; ++k) { template = bestTemplates[k]; if(Score[template] > bestScore) { bestScore = Score[template]; regionTemplates[(bestHits = 1)] = template; } else if(Score[template] == bestScore) { if(Score[template]) { regionTemplates[++bestHits] = template; } else { bestTemplates[k] = bestTemplates[(*bestTemplates)--]; --k; } } } /* rc */ for(k = 1; k <= *bestTemplates_r; ++k) { template = bestTemplates_r[k]; if(Score_r[template] > bestScore) { bestScore = Score_r[template]; regionTemplates[(bestHits = 1)] = -template; } else if(Score_r[template] == bestScore) { if(bestScore) { regionTemplates[++bestHits] = -template; } else { bestTemplates_r[k] = bestTemplates_r[(*bestTemplates_r)--]; --k; } } } *regionTemplates = bestHits; if(bestScore > 0) { bestHits = *regionTemplates; /* find limits of match */ start_cut = j; for(k = 1; k <= bestHits; ++k) { template = (regionTemplates[k] > 0) ? regionTemplates[k] : -regionTemplates[k]; for(l = start; l < start_cut; ++l) { if(VR_scores[l] && intpos_bin_contaminationPtr(VR_scores[l], template) != -1) { start_cut = l; } if(VF_scores[l] && intpos_bin_contaminationPtr(VF_scores[l], template) != -1) { start_cut = l; } } } end_cut = start_cut; for(k = 1; k <= bestHits; ++k) { template = (regionTemplates[k] > 0) ? regionTemplates[k] : -regionTemplates[k]; for(l = j; l > end_cut; --l) { if(VR_scores[l] && intpos_bin_contaminationPtr(VR_scores[l], template) != -1) { end_cut = l; } if(VF_scores[l] && intpos_bin_contaminationPtr(VF_scores[l], template) != -1) { end_cut = l; } } } /* evaluate best hit */ if(bestScore * kmersize > (end_cut - start_cut - bestScore + kmersize)) { /* check for hits on rc */ HIT = (regionTemplates[*regionTemplates] > 0) ? 1 : -1; /* print */ if(start != 0 && j != qseq->seqlen) { ankerAndClean(regionTemplates, Score, Score_r, include, template_lengths, VF_scores, VR_scores, tmpNs, qseq, HIT, bestScore, start_cut, end_cut, header, excludeOut, out); } else { ankerPtr(regionTemplates, Score, Score_r, include, template_lengths, VF_scores, VR_scores, tmpNs, qseq, HIT, bestScore, start_cut, end_cut, header, excludeOut, out); } returner = 0; } else { /* clear scores */ for(k = 1; k <= *bestTemplates; ++k) { Score[bestTemplates[k]] = 0; } for(k = 1; k <= *bestTemplates_r; ++k) { Score_r[bestTemplates_r[k]] = 0; } HIT = 0; } } else { /* clear scores */ for(k = 1; k <= *bestTemplates; ++k) { Score[bestTemplates[k]] = 0; } for(k = 1; k <= *bestTemplates_r; ++k) { Score_r[bestTemplates_r[k]] = 0; } HIT = 0; } } } } /* clear scores */ for(k = start; k < j; ++k) { VF_scores[k] = 0; VR_scores[k] = 0; } i = stop + 1; i_r = seqlen - kmersize - i; } else { ++N; } } return returner; } void ankerAndClean(int *regionTemplates, int *Score, int *Score_r, char *include, int *template_lengths, unsigned **VF_scores, unsigned **VR_scores, int *tmpNs, CompDNA *qseq, int HIT, int bestScore, int start_cut, int end_cut, Qseqs *header, volatile int *excludeOut, FILE *out) { static double minFrac = 0.0; int k, l, bestHits, bestHitsCov, DB_size, end, score, proxiScore; int template, *Templates; unsigned *values, n, SU; short unsigned *values_s; double thisCov, bestCov; CompDNA tmpQseq; if(Score == 0) { minFrac = *((double *) regionTemplates); return; } else if((DB_size = regionTemplates[-3]) < USHRT_MAX) { SU = 1; } else { SU = 0; } /* mark hits */ bestHits = *regionTemplates + 1; Templates = regionTemplates; while(--bestHits) { include[abs(*++Templates)] = 1; } /* get best cov */ bestHits = *regionTemplates; Templates = regionTemplates; bestHitsCov = template_lengths[abs(*++Templates)]; while(--bestHits) { if(template_lengths[abs(*++Templates)] < bestHitsCov) { bestHitsCov = template_lengths[abs(*Templates)]; } } /* make sure cuts isn't random seeds */ if(minFrac) { proxiScore = minFrac * bestScore; bestCov = 1.0 * proxiScore / bestHitsCov; bestHits = *regionTemplates; end = end_cut - 92; for(k = start_cut + 92; k <= end; ++k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; n = *values_s; for(l = 1; l <= n; ++l) { if(include[(template = values_s[l])] == 0 && template != DB_size && (proxiScore <= (score = Score[template]) || bestCov * template_lengths[template] <= score)) { include[template] = 1; regionTemplates[++bestHits] = template; } Score[template]--; } } else { values = VF_scores[k]; n = *values; for(l = 1; l <= n; ++l) { if(include[(template = values[l])] == 0 && template != DB_size && (proxiScore <= (score = Score[template]) || bestCov * template_lengths[template] <= score)) { include[template] = 1; regionTemplates[++bestHits] = template; } Score[template]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; n = *values_s; for(l = 1; l <= n; ++l) { if(include[(template = values_s[l])] == 0 && template != DB_size && (proxiScore <= (score = Score_r[template]) || bestCov * template_lengths[template] <= score)) { include[template] = 1; regionTemplates[bestHits] = -template; } Score_r[template]--; } } else { values = VR_scores[k]; n = *values; for(l = 1; l <= n; ++l) { if(include[(template = values[l])] == 0 && template != DB_size && (proxiScore <= (score = Score_r[template]) || bestCov * template_lengths[template] <= score)) { include[template] = 1; regionTemplates[bestHits] = -template; } Score_r[template]--; } } VR_scores[k] = 0; } } *regionTemplates = bestHits; } else { bestCov = 1.0 * bestScore / bestHitsCov; bestHits = *regionTemplates; end = end_cut - 92; for(k = start_cut + 92; k <= end; ++k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; n = *values_s; for(l = 1; l <= n; ++l) { template = values_s[l]; if(include[template] == 0 && template != DB_size) { thisCov = 1.0 * Score[template] / template_lengths[template]; if(thisCov > bestCov) { include[template] = 1; bestCov = thisCov; bestHits = *regionTemplates + 1; regionTemplates[bestHits] = template; } else if(thisCov == bestCov) { include[template] = 1; regionTemplates[++bestHits] = template; } } Score[template]--; } } else { values = VF_scores[k]; n = *values; for(l = 1; l <= n; ++l) { template = values[l]; if(include[template] == 0 && template != DB_size) { thisCov = 1.0 * Score[template] / template_lengths[template]; if(thisCov > bestCov) { include[template] = 1; bestCov = thisCov; bestHits = *regionTemplates + 1; regionTemplates[bestHits] = template; } else if(thisCov == bestCov) { include[template] = 1; regionTemplates[++bestHits] = template; } } Score[template]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; n = *values_s; for(l = 1; l <= n; ++l) { template = values_s[l]; if(include[template] == 0 && template != DB_size) { thisCov = 1.0 * Score_r[template] / template_lengths[template]; if(thisCov > bestCov) { include[template] = 1; HIT = -1; bestCov = thisCov; bestHits = *regionTemplates + 1; regionTemplates[bestHits] = -template; } else if(thisCov == bestCov) { include[template] = 1; HIT = -1; regionTemplates[++bestHits] = -template; } } Score_r[template]--; } } else { values = VR_scores[k]; n = *values; for(l = 1; l <= n; ++l) { template = values[l]; if(include[template] == 0 && template != DB_size) { thisCov = 1.0 * Score_r[template] / template_lengths[template]; if(thisCov > bestCov) { include[template] = 1; HIT = -1; bestCov = thisCov; bestHits = *regionTemplates + 1; regionTemplates[bestHits] = -template; } else if(thisCov == bestCov) { include[template] = 1; HIT = -1; regionTemplates[++bestHits] = -template; } } Score_r[template]--; } } VR_scores[k] = 0; } } *regionTemplates = bestHits; } /* clear nearest templates on both sides of match */ end = (qseq->seqlen < (start_cut + 92)) ? qseq->seqlen : (start_cut + 92); start_cut = ((start_cut - 92) < 0) ? 0 : (start_cut - 92); for(k = start_cut; k < end; ++k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; l = (*values_s) + 1; while(--l) { Score[values_s[l]]--; } } else { values = VF_scores[k]; l = (*values) + 1; while(--l) { Score[values[l]]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; l = (*values_s) + 1; while(--l) { Score_r[values_s[l]]--; } } else { values = VR_scores[k]; l = (*values) + 1; while(--l) { Score_r[values[l]]--; } } VR_scores[k] = 0; } } end = (end_cut - 92) < 0 ? 0 : (end_cut - 92); end_cut = ((end_cut + 92) > qseq->seqlen) ? qseq->seqlen : (end_cut + 92); for(k = end_cut; k > end; --k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; l = (*values_s) + 1; while(--l) { Score[values_s[l]]--; } } else { values = VF_scores[k]; l = (*values) + 1; while(--l) { Score[values[l]]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; l = (*values_s) + 1; while(--l) { Score_r[values_s[l]]--; } } else { values = VR_scores[k]; l = (*values) + 1; while(--l) { Score_r[values[l]]--; } } VR_scores[k] = 0; } } /* unmark hits */ bestHits = *regionTemplates + 1; Templates = regionTemplates; while(--bestHits) { include[abs(*++Templates)] = 0; } /* modify limits of match seq */ start_cut = ((start_cut - 92) < 0) ? 0 : (start_cut - 92); end_cut = ((end_cut + 92) > qseq->seqlen) ? qseq->seqlen : (end_cut + 92); start_cut = (start_cut >> 5) << 5; end_cut = ((end_cut >> 5) << 5) + 32; end_cut = (end_cut < qseq->seqlen) ? end_cut : qseq->seqlen; tmpQseq.seqlen = (end_cut - start_cut); tmpQseq.seq = qseq->seq + (start_cut >> 5); tmpQseq.N = tmpNs; for(k = 1, l = 0; k < qseq->N[0]; ++k) { if(start_cut <= qseq->N[k]) { ++l; tmpQseq.N[l] = qseq->N[k] - start_cut; if(tmpQseq.N[l] >= tmpQseq.seqlen) { --l; k = qseq->N[0]; } } } /* trim trailing gaps */ --tmpQseq.seqlen; while(tmpQseq.N[l] == tmpQseq.seqlen && l != 0) { --tmpQseq.seqlen; --l; } ++tmpQseq.seqlen; tmpQseq.complen = (tmpQseq.seqlen >> 5) + 1; tmpQseq.N[0] = l; /* modify header */ l = header->len; if(header->size <= l + 22) { header->size += 32; header->seq = realloc(header->seq, header->size); if(!header->seq) { ERROR(); } } header->len += sprintf((char *) header->seq + l - 1, "\t%d\t%d", start_cut, end_cut); lock(excludeOut); deConPrintPtr(regionTemplates, &tmpQseq, HIT * bestScore, header, 0, out); unlock(excludeOut); header->seq[l] = 0; header->len = l; } void ankerAndClean_MEM(int *regionTemplates, int *Score, int *Score_r, char *include, int *template_lengths, unsigned **VF_scores, unsigned **VR_scores, int *tmpNs, CompDNA *qseq, int HIT, int bestScore, int start_cut, int end_cut, Qseqs *header, volatile int *excludeOut, FILE *out) { static double minFrac = 0.0; int k, l, end, DB_size, SU, bestHits, proxiScore, template, *Templates; unsigned n, *values; short unsigned *values_s; CompDNA tmpQseq; if(Score == 0) { minFrac = *((double *) regionTemplates); return; } else if((DB_size = regionTemplates[-3]) < USHRT_MAX) { SU = 1; } else { SU = 0; } if(minFrac) { /* mark hits */ bestHits = *regionTemplates + 1; Templates = regionTemplates; while(--bestHits) { include[abs(*++Templates)] = 1; } proxiScore = minFrac * bestScore; bestHits = *regionTemplates; end = end_cut - 92; for(k = start_cut + 92; k <= end; ++k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; n = *values_s; for(l = 1; l <= n; ++l) { template = values_s[l]; if(include[template] == 0 && proxiScore <= Score[template] && template != DB_size) { include[template] = 1; regionTemplates[++bestHits] = template; } Score[template]--; } } else { values = VF_scores[k]; n = *values; for(l = 1; l <= n; ++l) { template = values[l]; if(include[template] == 0 && proxiScore <= Score[template] && template != DB_size) { include[template] = 1; regionTemplates[++bestHits] = template; } Score[template]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; n = *values_s; for(l = 1; l <= n; ++l) { template = values_s[l]; if(include[template] == 0 && proxiScore <= Score_r[template] && template != DB_size) { include[template] = 1; regionTemplates[++bestHits] = -template; } Score_r[template]--; } } else { values = VR_scores[k]; n = *values; for(l = 1; l <= n; ++l) { template = values[l]; if(include[template] == 0 && proxiScore <= Score_r[template] && template != DB_size) { include[template] = 1; regionTemplates[++bestHits] = -template; } Score_r[template]--; } } VR_scores[k] = 0; } } *regionTemplates = bestHits; /* clean up scores */ end = (qseq->seqlen < (start_cut + 92)) ? qseq->seqlen : (start_cut + 92); for(k = ((start_cut - 92) < 0) ? 0 : (start_cut - 92); k < end; ++k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; l = (*values_s) + 1; while(--l) { Score[*++values_s]--; } } else { values = VF_scores[k]; l = (*values) + 1; while(--l) { Score[*++values]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; l = (*values_s) + 1; while(--l) { Score_r[*++values_s]--; } } else { values = VR_scores[k]; l = (*values) + 1; while(--l) { Score_r[*++values]--; } } VR_scores[k] = 0; } } end = ((end_cut + 92) > qseq->seqlen) ? qseq->seqlen : (end_cut + 92); for(k = ((end_cut - 92) < 0) ? 0 : (end_cut - 92); k < end; ++k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; l = (*values_s) + 1; while(--l) { Score[*++values_s]--; } } else { values = VF_scores[k]; l = (*values) + 1; while(--l) { Score[*++values]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; l = (*values_s) + 1; while(--l) { Score_r[*++values_s]--; } } else { values = VR_scores[k]; l = (*values) + 1; while(--l) { Score_r[*++values]--; } } VR_scores[k] = 0; } } start_cut = ((start_cut - 92) < 0) ? 0 : (start_cut - 92); end_cut = ((end_cut + 92) > qseq->seqlen) ? qseq->seqlen : (end_cut + 92); /* unmark hits */ bestHits = *regionTemplates + 1; Templates = regionTemplates; while(--bestHits) { include[abs(*++Templates)] = 0; } } else { /* clean up scores */ start_cut = ((start_cut - 92) < 0) ? 0 : (start_cut - 92); end_cut = ((end_cut + 92) > qseq->seqlen) ? qseq->seqlen : (end_cut + 92); for(k = start_cut; k < end_cut; ++k) { if(VF_scores[k]) { if(SU) { values_s = (short unsigned *) VF_scores[k]; l = (*values_s) + 1; while(--l) { Score[*++values_s]--; } } else { values = VF_scores[k]; l = (*values) + 1; while(--l) { Score[*++values]--; } } VF_scores[k] = 0; } if(VR_scores[k]) { if(SU) { values_s = (short unsigned *) VR_scores[k]; l = (*values_s) + 1; while(--l) { Score_r[*++values_s]--; } } else { values = VR_scores[k]; l = (*values) + 1; while(--l) { Score_r[*++values]--; } } VR_scores[k] = 0; } } } /* modify limits of match seq */ start_cut = (start_cut >> 5) << 5; end_cut = ((end_cut >> 5) << 5) + 32; end_cut = (end_cut < qseq->seqlen) ? end_cut : qseq->seqlen; tmpQseq.seqlen = (end_cut - start_cut); tmpQseq.seq = qseq->seq + (start_cut >> 5); tmpQseq.N = tmpNs; for(k = 1, l = 0; k < qseq->N[0]; ++k) { if(start_cut <= qseq->N[k]) { ++l; tmpQseq.N[l] = qseq->N[k] - start_cut; if(tmpQseq.N[l] >= tmpQseq.seqlen) { --l; k = qseq->N[0]; } } } /* trim trailing gaps */ --tmpQseq.seqlen; while(tmpQseq.N[l] == tmpQseq.seqlen && l != 0) { --tmpQseq.seqlen; --l; } ++tmpQseq.seqlen; tmpQseq.complen = (tmpQseq.seqlen >> 5) + 1; tmpQseq.N[0] = l; /* modify header */ l = header->len; if(header->size <= l + 22) { header->size += 32; header->seq = realloc(header->seq, header->size); if(!header->seq) { ERROR(); } } header->len += sprintf((char *) header->seq + l - 1, "\t%d\t%d", start_cut, end_cut); lock(excludeOut); deConPrintPtr(regionTemplates, &tmpQseq, HIT * bestScore, header, 0, out); unlock(excludeOut); header->seq[l] = 0; header->len = l; } int save_kmers_chain(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { /* return 0 for match, 1 otherwise */ static int *Sizes = 0, minlen = 0; static double coverT = 0.5, mrs = 0.5; static KmerAnker **tVF_scores, **tVR_scores; static SeqmentTree **tSeqments; int i, j, rc, Wl, W1, U, M, MM, Ms, MMs, Us, W1s, score, gaps, SU, HIT; int start, end, pos, shifter, kmersize, cover, len, template, test; int cStart, cStart_r, *bests; unsigned DB_size, hitCounter, hitCounter_r, ties, *values, *last; short unsigned *values_s; char *include; KmerAnker *V_score, *V_scores, *VF_scores, *VR_scores, *tmp_score; KmerAnker *best_score, *best_score_r; SeqmentTree *chainSeqments; if(qseq == 0) { if(Sizes) { free(Sizes); Sizes = 0; i = *bestTemplates; while(i--) { free(tVF_scores[i]); } free(tVF_scores); } else { /* set coverT */ coverT = *((double *)(bestTemplates_r)); mrs = *((double *)(Score)); minlen = exhaustive; i = *bestTemplates; Sizes = smalloc(i * sizeof(int)); tVF_scores = smalloc(2 * i * sizeof(KmerAnker *)); tVR_scores = tVF_scores + i; tSeqments = calloc(i, sizeof(SeqmentTree *)); if(!tSeqments) { ERROR(); } while(i--) { Sizes[i] = 1024; tVF_scores[i] = calloc(2048, sizeof(KmerAnker)); if(!tVF_scores[i]) { ERROR(); } tVR_scores[i] = tVF_scores[i] + 1024; tSeqments[i] = initializeSeqmentTree(64); } } return 0; } else if(qseq->seqlen < (kmersize = templates->kmersize)) { return 1; } else if((DB_size = templates->DB_size) < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); M = rewards->M; MM = rewards->MM; U = rewards->U; W1 = rewards->W1; Wl = rewards->Wl; include = (char *) (extendScore + (templates->DB_size + 1)); values = 0; values_s = 0; rc_comp(qseq, qseq_r); if(Sizes[*Score] < qseq->size) { Sizes[*Score] = qseq->size; free(tVF_scores[*Score]); tVF_scores[*Score] = calloc(2 * qseq->size, sizeof(KmerAnker)); if(!tVF_scores[*Score]) { ERROR(); } else { tVR_scores[*Score] = tVF_scores[*Score] + qseq->size; } } VF_scores = tVF_scores[*Score]; VR_scores = tVR_scores[*Score]; chainSeqments = tSeqments[*Score]; chainSeqments->n = 0; /* get forward ankers */ hitCounter = 0; V_scores = VF_scores; HIT = exhaustive; j = 0; ++*(qseq->N); qseq->N[*(qseq->N)] = qseq->seqlen; for(i = 1; i <= *(qseq->N) && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; while(j < end && hashMap_get(templates, getKmer(qseq->seq, j, shifter)) == 0) { j += kmersize; } if(j < end) { HIT = 1; } else { j = qseq->N[i] + 1; } } if(HIT) { V_score = V_scores; V_score->start = 0; V_score->end = 0; V_score->values = 0; V_score->descend = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; gaps = 0; last = 0; j = 0; for(i = 1; i <= *(qseq->N); ++i) { end = qseq->N[i] - kmersize + 1; while(j < end) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { if(kmersize < gaps) { Ms += kmersize; gaps -= kmersize; if(gaps) { /* go for best scenario */ if(gaps == 1) { MMs += 2; } else if((2 * MM + (gaps - 2) * M) < 0) { Ms += (gaps - 2); MMs += 2; } else { if(last) { /* update and link between ankers */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = j - gaps + kmersize; V_score->descend = V_score + 1; ++V_score; } V_score->start = j; V_score->values = values; V_score->descend = 0; last = values; Ms = kmersize; MMs = 0; Us = 0; W1s = 0; ++hitCounter; } } else { ++MMs; } } else if(gaps) { --gaps; ++W1s; Us += gaps; } else { ++Ms; } } else { if(last) { /* update and link between ankers */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = j - gaps + kmersize; V_score->descend = V_score + 1; ++V_score; } V_score->start = j; V_score->values = values; V_score->descend = 0; last = values; Ms = kmersize; MMs = 0; Us = 0; W1s = 0; ++hitCounter; } gaps = 0; } else { ++gaps; } ++j; } j = qseq->N[i] + 1; } if(last) { /* update anker */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = qseq->seqlen - gaps; } } /* get rc ankers, in forward notation */ hitCounter_r = 0; V_scores = VR_scores; HIT = exhaustive; j = 0; rc = qseq->seqlen - kmersize; for(i = 1; i <= *(qseq->N) && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; while(j < end && hashMap_get(templates, getKmer(qseq_r->seq, rc, shifter)) == 0) { j += kmersize; rc -= kmersize; } if(j < end) { HIT = 1; } else { j = qseq->N[i] + 1; rc = qseq->seqlen - j; } } if(HIT) { V_score = V_scores; V_score->start = 0; V_score->end = 0; V_score->values = 0; V_score->descend = 0; Ms = 0; MMs = 0; Us = 0; W1s = 0; gaps = 0; last = 0; j = 0; rc = qseq->seqlen - kmersize; for(i = 1; i <= *(qseq->N); ++i) { end = qseq->N[i] - kmersize + 1; while(j < end) { if((values = hashMap_get(templates, getKmer(qseq_r->seq, rc, shifter)))) { if(values == last) { if(kmersize < gaps) { Ms += kmersize; gaps -= kmersize; if(gaps) { /* go for best scenario */ if(gaps == 1) { MMs += 2; } else if((2 * MM + (gaps - 2) * M) < 0) { Ms += (gaps - 2); MMs += 2; } else { if(last) { /* update and link between ankers */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = j - gaps + kmersize; V_score->descend = V_score + 1; ++V_score; } V_score->start = j; V_score->values = values; V_score->descend = 0; last = values; Ms = kmersize; MMs = 0; Us = 0; W1s = 0; ++hitCounter_r; } } else { ++MMs; } } else if(gaps) { --gaps; ++W1s; Us += gaps; } else { ++Ms; } } else { if(last) { /* update and link between ankers */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = j - gaps + kmersize; V_score->descend = V_score + 1; ++V_score; } V_score->start = j; V_score->values = values; V_score->descend = 0; last = values; Ms = kmersize; MMs = 0; Us = 0; W1s = 0; ++hitCounter_r; } gaps = 0; } else { ++gaps; } ++j; --rc; } j = qseq->N[i] + 1; rc = qseq->seqlen - j; } if(last) { /* update anker */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = qseq->seqlen - gaps; } } --*(qseq->N); /* no matches */ if(!hitCounter && !hitCounter_r) { return 1; } /* make chains */ V_score = VF_scores; V_score->score = 0; best_score = 0; best_score_r = V_score; HIT = hitCounter + 1; bests = bestTemplates; *bestTemplates = 0; *bestTemplates_r = 0; ties = 0; rc = 2; while(rc--) { if(rc == 0) { V_score = VR_scores; V_score->score = 0; HIT = hitCounter_r + 1; bests = bestTemplates_r; best_score = best_score_r; best_score_r = V_score; } *bests = 0; while(--HIT) { /* Save pos of best score, and chain it (0 if local). Score is always current / w.r.t. the anker you are on. extendScore contains endpos of last hit anker. */ start = V_score->start; end = V_score->end; /* chain anker */ V_score->score = 0; if(SU) { values_s = (short unsigned *) V_score->values; i = *values_s + 1; values_s += i; } else { values = V_score->values; i = *values + 1; values += i; } while(--i) { template = SU ? *--values_s : *--values; score = Score[template]; pos = extendScore[template]; gaps = start - pos; /* extend chain */ if(!include[template]) { include[template] = 1; bests[++*bests] = template; if(start) { score = W1 + (start - 1) * U; score = V_score->weight + MAX(Wl, score); } else { score = V_score->weight; } } else { if(gaps < 0) { if(gaps == -kmersize) { score += V_score->weight - (kmersize - 1) * M; } else { score += (W1 + (-gaps - 1) * U) + V_score->weight + gaps * M; } } else if(gaps == 0) { score += V_score->weight + W1; } else if(gaps <= 2) { score += V_score->weight + gaps * MM; } else if((MM * 2 + (gaps - 2) * M) < 0) { score += V_score->weight + (MM * 2 + (gaps - 2) * M); } else { MMs = gaps / kmersize + (gaps % kmersize ? 1 : 0); MMs = MAX(2, MMs); gaps -= MMs; Ms = MIN(gaps, kmersize); score += V_score->weight + Ms * M + MMs * MM; } /* verify extension */ if(score < 0) { test = start ? (W1 + (start - 1) * U) : 0; test = MAX(test, Wl); if(score < test + V_score->weight) { score = test + V_score->weight; } } } /* update Scores */ if(V_score->score < score) { V_score->score = score; } Score[template] = score; extendScore[template] = end; } /* Mark last best hit */ if(best_score_r->score < V_score->score) { best_score_r = V_score; ties = 0; } else if(best_score_r->score == V_score->score) { /* first hit on rc is likely last hit on forward */ best_score_r = V_score; ++ties; } ++V_score; } /* clear Score arrays */ clearScore(bests, Score); clearScore(bests, extendScore); i = *bests + 1; while(--i) { include[*++bests] = 0; } } /* no good hits */ if(best_score->score < kmersize && best_score_r->score < kmersize) { return 1; } /* prune hits */ VF_scores = pruneAnkers(VF_scores, kmersize); VR_scores = pruneAnkers(VR_scores, kmersize); /* get best chain, start/end, score, template(s) and zero out ankers */ *include = SU; *bestTemplates = 0; *bestTemplates_r = 0; if(best_score_r->score < best_score->score) { tmp_score = getChainTemplates(best_score, rewards, kmersize, bestTemplates, Score, extendScore, include); score = best_score->score; cStart = (start = tmp_score->start); cStart_r = -1; len = best_score->end - start; rc = 1; } else if(best_score->score < best_score_r->score) { tmp_score = getChainTemplates(best_score_r, rewards, kmersize, bestTemplates_r, Score, extendScore, include); score = best_score_r->score; cStart = -1; cStart_r = (start = tmp_score->start); len = best_score_r->end - start; rc = 2; } else if(best_score->end == best_score_r->end) { tmp_score = getChainTemplates(best_score, rewards, kmersize, bestTemplates, Score, extendScore, include); cStart = tmp_score->start; getChainTemplates(best_score_r, rewards, kmersize, bestTemplates_r, Score, extendScore, include); score = best_score->score; cStart_r = tmp_score->start; start = MAX(cStart, cStart_r); len = best_score->end - start; rc = 3; } else if(best_score->end < best_score_r->end) { tmp_score = getChainTemplates(best_score_r, rewards, kmersize, bestTemplates_r, Score, extendScore, include); score = best_score_r->score; cStart = -1; cStart_r = (start = tmp_score->start); len = best_score_r->end - start; rc = 2; } else { tmp_score = getChainTemplates(best_score, rewards, kmersize, bestTemplates, Score, extendScore, include); score = best_score->score; cStart = (start = tmp_score->start); cStart_r = -1; len = best_score->end - start; rc = 1; } if(len < minlen || score < mrs * len) { *include = 0; return 1; } /* get best chains */ while(best_score || best_score_r) { /* get equal ankers inside chain, that lies under the threshold */ if(0 && ties) { if(rc & 1) { score = best_score->score; V_score = best_score; while((V_score = getTieAnker(start, V_score, score))) { /* 1. tie anker -> tie_len == best_len 2. Best match is last on seq -> tie_start < best_start 1. && 2. -> cover = |tie_start - best_end| / len */ if((V_score->end - start) < coverT * len) { /* not a co-match / overlap is insufficient -> no more equal matches */ V_score = 0; } else { /* Anker is equal, update with templates */ /* Mark current templates to avoid double hitting */ i = *bestTemplates + 1; bests = bestTemplates; while(--i) { include[*++bests] = 1; } /* update best template candidates */ template = *bests; *bests = 0; getChainTemplates(V_score, rewards, kmersize, bests, Score, extendScore, include); *bestTemplates += *bests; *bests = template; } } } if(rc & 2) { score = best_score_r->score; V_score = best_score_r; while((V_score = getTieAnker(start, V_score, score))) { /* 1. tie anker -> tie_len == best_len 2. Best match is last on seq -> tie_start < best_start 1. && 2. -> cover = |tie_start - best_end| / len */ if((V_score->end - start) < coverT * len ) { /* not a co-match / overlap is insufficient -> no more equal matches */ V_score = 0; } else { /* Anker is equal, update with templates */ /* Mark current templates to avoid double hitting */ i = *bestTemplates_r + 1; bests = bestTemplates_r; while(--i) { include[*++bests] = 1; } /* update best template candidates */ template = *bests; *bests = 0; getChainTemplates(V_score, rewards, kmersize, bests, Score, extendScore, include); *bestTemplates_r += *bests; *bests = template; } } } } /* use segment trees to mark "used" regions of query. Allow for quick check of intersection with chosen chains. And insert anker-boundaries in header*/ if(rc & 1) { growSeqmentTree(chainSeqments, start, best_score->end); insertKmerBound((Qseqs *) header, start, best_score->end); } else { growSeqmentTree(chainSeqments, qseq->seqlen - best_score_r->end, qseq->seqlen - start); insertKmerBound((Qseqs *) header, qseq->seqlen - best_score_r->end, qseq->seqlen - start); } /* print match */ if(rc & 1) { if(rc & 2) { i = *bestTemplates_r; j = (*bestTemplates += i) + 1; while(--i) { bestTemplates[--j] = -bestTemplates_r[i]; } best_score->score = -best_score->score; best_score_r->score = 0; *bestTemplates_r = 0; } lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, best_score->score, header, 0, out); unlock(excludeOut); best_score->score = 0; *bestTemplates = 0; } else { lock(excludeOut); i = deConPrintPtr(bestTemplates_r, qseq_r, best_score_r->score, header, 0, out); unlock(excludeOut); best_score_r->score = 0; *bestTemplates_r = 0; } /* get next match */ ties = 0; rc = 0; if(best_score) { if(best_score->score) { tmp_score = getChainTemplates(best_score, rewards, kmersize, bestTemplates, Score, extendScore, include); cStart = tmp_score->start; cover = queSeqmentTree(chainSeqments->root, cStart, best_score->end); /* verify chain */ len = best_score->end - cStart; if(minlen <= len && cover <= coverT * len && mrs * len <= best_score->score) { /* get chain */ rc = 1; } else { /* silence anker */ best_score->score = 0; } } while(best_score && best_score->score == 0) { /* find best anker */ if((best_score = getBestAnker(&VF_scores, &ties))) { if(kmersize < best_score->score) { /* check chain */ tmp_score = getChainTemplates(best_score, rewards, kmersize, bestTemplates, Score, extendScore, include); cStart = tmp_score->start; cover = queSeqmentTree(chainSeqments->root, cStart, best_score->end); /* verify chain */ len = best_score->end - cStart; if(minlen <= len && cover <= coverT * len && mrs * len <= best_score->score) { /* get chain */ rc = 1; } else { /* silence anker */ best_score->score = 0; } } else { /* silence anker */ best_score->score = 0; } } } } if(best_score_r) { if(best_score_r->score) { tmp_score = getChainTemplates(best_score_r, rewards, kmersize, bestTemplates_r, Score, extendScore, include); cStart_r = tmp_score->start; //cover = queSeqmentTree(chainSeqments->root, cStart_r, best_score_r->end); cover = queSeqmentTree(chainSeqments->root, qseq->seqlen - best_score_r->end, qseq->seqlen - cStart_r); /* verify chain */ len = best_score_r->end - cStart_r; if(minlen <= len && cover <= coverT * len && mrs * len <= best_score_r->score) { /* get chain */ rc |= 2; } else { /* silence anker */ best_score_r->score = 0; } } while(best_score_r && best_score_r->score == 0) { /* find best anker */ if((best_score_r = getBestAnker(&VR_scores, &ties))) { if(kmersize < best_score_r->score) { /* check chain */ tmp_score = getChainTemplates(best_score_r, rewards, kmersize, bestTemplates_r, Score, extendScore, include); cStart_r = tmp_score->start; //cover = queSeqmentTree(chainSeqments->root, cStart_r, best_score_r->end); cover = queSeqmentTree(chainSeqments->root, qseq->seqlen - best_score_r->end, qseq->seqlen - cStart_r); /* verify chain */ len = best_score_r->end - cStart_r; if(minlen <= best_score_r->end - cStart_r && cover <= coverT * len && mrs * len <= best_score_r->score) { /* get chain */ rc |= 2; } else { /* silence anker */ best_score_r->score = 0; } } else { /* silence anker */ best_score_r->score = 0; } } } } if(!best_score && !best_score_r) { *include = 0; return 0; } else if(best_score && best_score_r) { if(best_score_r->score < best_score->score) { rc = 1; start = cStart; len = best_score->end - start; } else if(best_score->score < best_score_r->score) { rc = 2; start = cStart_r; len = best_score_r->end - start; } else if(best_score->end == best_score_r->end) { rc = 3; start = MAX(cStart, cStart_r); len = best_score->end - start; } else if(best_score->end < best_score_r->end) { rc = 2; start = cStart_r; len = best_score_r->end - start; } else { rc = 1; start = cStart; len = best_score->end - start; } } else if(best_score) { rc = 1; start = cStart; len = best_score->end - start; } else { rc = 2; start = cStart_r; len = best_score_r->end - start; } } *include = 0; return 1; } int save_kmers_sparse_chain(const HashMapKMA *templates, const Penalties *rewards, int *bestTemplates, int *bestTemplates_r, int *Score, int *Score_r, CompDNA *qseq, CompDNA *qseq_r, const Qseqs *header, int *extendScore, const int exhaustive, volatile int *excludeOut, FILE *out) { /* return 0 for match, 1 otherwise */ static int *Sizes = 0, minlen = 0; static double coverT = 0.5, mrs = 0.5; static KmerAnker **tVF_scores; static SeqmentTree **tSeqments; int i, j, shifter, prefix_shifter, kmersize, DB_size, pos, start, score; int Wl, W1, U, M, MM, Ms, MMs, Us, W1s, end, len, gaps, template, test; int *bests; unsigned SU, HIT, cover, hitCounter, ties, prefix_len, flag; unsigned *values, *last; short unsigned *values_s; long unsigned prefix; char *include; KmerAnker *V_score, *VF_scores, *tmp_score, *best_score; SeqmentTree *chainSeqments; if(qseq == 0) { if(Sizes) { free(Sizes); Sizes = 0; i = *bestTemplates; while(i--) { free(tVF_scores[i]); } free(tVF_scores); } else { /* set coverT */ coverT = *((double *)(bestTemplates_r)); mrs = *((double *)(Score)); minlen = exhaustive; i = *bestTemplates; Sizes = smalloc(i * sizeof(int)); tVF_scores = smalloc(i * sizeof(KmerAnker *)); tSeqments = calloc(i, sizeof(SeqmentTree *)); if(!tSeqments) { ERROR(); } while(i--) { Sizes[i] = 1024; tVF_scores[i] = calloc(1024, sizeof(KmerAnker)); if(!tVF_scores[i]) { ERROR(); } tSeqments[i] = initializeSeqmentTree(64); } } return 0; } else if(qseq->seqlen < (kmersize = templates->kmersize)) { return 1; } else if((DB_size = templates->DB_size) < USHRT_MAX) { SU = 1; } else { SU = 0; } shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->prefix_len << 1); M = rewards->M; MM = rewards->MM; U = rewards->U; W1 = rewards->W1; Wl = rewards->Wl; include = (char *) (extendScore + (templates->DB_size + 1)); hitCounter = 0; values = 0; values_s = 0; last = 0; start = 0; if(Sizes[*Score] < qseq->size) { Sizes[*Score] = qseq->size << 1; free(tVF_scores[*Score]); tVF_scores[*Score] = calloc(qseq->size, sizeof(KmerAnker)); if(!tVF_scores[*Score]) { ERROR(); } } VF_scores = tVF_scores[*Score]; chainSeqments = tSeqments[*Score]; chainSeqments->n = 0; V_score = VF_scores; V_score->start = 0; V_score->end = 0; V_score->values = 0; V_score->descend = 0; if((prefix_len = templates->prefix_len)) { prefix = templates->prefix; flag = 16; rc_comp(qseq, qseq_r); ++*(qseq->N); qseq->N[*(qseq->N)] = qseq->seqlen; i = 0; j = qseq->seqlen - kmersize - prefix_len; for(gaps = 1; gaps <= *(qseq->N); ++gaps) { V_score->end = i; end = qseq->N[gaps] - kmersize - prefix_len + 1; while(i < end) { if(getKmer(qseq->seq, i, prefix_shifter) == prefix) { if((values = hashMap_get(templates, getKmer(qseq->seq, i + prefix_len, shifter)))) { if(values == last) { /* update end */ V_score->end = i; } else if(last) { /* find mid point between ankers */ tmp_score = V_score++; tmp_score->end = (tmp_score->end + i) >> 1; /* start new anker */ V_score->start = tmp_score->end + 1; V_score->end = i; V_score->ties = 0; V_score->values = values; /* finish last anker */ tmp_score->end += kmersize + prefix_len; tmp_score->weight = (tmp_score->end - tmp_score->start) * M; tmp_score->descend = V_score; /* count hit */ ++hitCounter; last = values; } else { /* make hit anker */ V_score->start = V_score->end ? ((V_score->end + i) >> 1) : 0; V_score->end = i; V_score->ties = 0; V_score->values = values; last = values; } } else if(last) { /* finish last anker */ tmp_score = V_score++; tmp_score->end = ((tmp_score->end + i) >> 1) + kmersize + prefix_len; tmp_score->weight = (tmp_score->end - tmp_score->start) * M; tmp_score->descend = V_score; /* start new anker */ V_score->end = i; V_score->ties = 0; V_score->values = 0; ++hitCounter; last = 0; } else { V_score->end = i; } } else if(getKmer(qseq_r->seq, j, prefix_shifter) == prefix) { /* f-hit -> rc-hit -> else */ if((values = hashMap_get(templates, getKmer(qseq_r->seq, j + prefix_len, shifter)))) { if(values == last) { /* update end */ V_score->end = i; } else if(last) { /* find mid point between ankers */ tmp_score = V_score++; tmp_score->end = (tmp_score->end + i) >> 1; /* start new anker */ V_score->start = tmp_score->end + 1; V_score->end = i; V_score->ties = 0; V_score->values = values; /* finish last anker */ tmp_score->end += kmersize + prefix_len; tmp_score->weight = (tmp_score->end - tmp_score->start) * M; tmp_score->descend = V_score; /* count hit */ ++hitCounter; last = values; } else { /* make hit anker */ V_score->start = V_score->end ? ((V_score->end + i) >> 1) : 0; V_score->end = i; V_score->ties = 0; V_score->values = values; last = values; } } else if(last) { /* finish last anker */ tmp_score = V_score++; tmp_score->end = ((tmp_score->end + i) >> 1) + kmersize + prefix_len; tmp_score->weight = (tmp_score->end - tmp_score->start) * M; tmp_score->descend = V_score; /* start new anker */ V_score->end = i; V_score->ties = 0; V_score->values = 0; ++hitCounter; last = 0; } else { V_score->end = i; } } ++i; --j; } if(last) { /* finish last anker */ tmp_score = V_score++; tmp_score->end = i; tmp_score->weight = (tmp_score->end - tmp_score->start) * M; tmp_score->descend = V_score; /* start new anker */ V_score->ties = 0; V_score->values = 0; ++hitCounter; last = 0; } i = qseq->N[gaps] + 1; j = qseq->seqlen - kmersize - prefix_len - i; } if(hitCounter) { --V_score; V_score->descend = 0; } --*(qseq->N); /* adjust the kmersize for chaining */ kmersize += prefix_len - 1; } else { flag = 0; HIT = exhaustive; j = 0; ++*(qseq->N); qseq->N[*(qseq->N)] = qseq->seqlen; for(i = 1; i <= *(qseq->N) && !HIT; ++i) { end = qseq->N[i] - kmersize + 1; while(j < end && hashMap_get(templates, getKmer(qseq->seq, j, shifter)) == 0) { j += kmersize; } if(j < end) { HIT = 1; } else { j = qseq->N[i] + 1; } } if(HIT) { Ms = 0; MMs = 0; Us = 0; W1s = 0; gaps = 0; last = 0; j = 0; for(i = 1; i <= *(qseq->N); ++i) { end = qseq->N[i] - kmersize + 1; while(j < end) { if((values = hashMap_get(templates, getKmer(qseq->seq, j, shifter)))) { if(values == last) { if(kmersize < gaps) { Ms += kmersize; gaps -= kmersize; if(gaps) { /* go for best scenario */ if(gaps == 1) { MMs += 2; } else if((MM * 2 + (gaps - 2) * M) < 0) { Ms += (gaps - 2); MMs += 2; } else { if(last) { /* update and link between ankers */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = j - gaps + kmersize; V_score->descend = V_score + 1; ++V_score; } V_score->start = j; V_score->values = values; V_score->descend = 0; last = values; Ms = kmersize; MMs = 0; Us = 0; W1s = 0; ++hitCounter; } } else { ++MMs; } } else if(gaps) { --gaps; ++W1s; Us += gaps; } else { ++Ms; } gaps = 0; } else { if(last) { /* update and link between ankers */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = j - gaps + kmersize; V_score->descend = V_score + 1; ++V_score; } V_score->start = j; V_score->values = values; V_score->descend = 0; last = values; Ms = kmersize; MMs = 0; Us = 0; W1s = 0; ++hitCounter; } gaps = 0; } else { ++gaps; } ++j; } j = qseq->N[i] + 1; } if(last) { /* update anker */ V_score->weight = Ms * M + MMs * MM + Us * U + W1s * W1; V_score->end = qseq->seqlen - gaps; } } --*(qseq->N); } /* no matches */ if(!hitCounter) { return 1; } /* make chains */ V_score = VF_scores; V_score->score = 0; best_score = V_score; HIT = hitCounter + 1; bests = bestTemplates; *bests = 0; ties = 0; while(--HIT) { /* Save pos of best score, and chain it (0 if local). Score is always current / w.r.t. the anker you are on. extendScore contains endpos of last hit anker. */ start = V_score->start; end = V_score->end; /* chain anker */ V_score->score = 0; if(SU) { values_s = (short unsigned *) V_score->values; i = *values_s + 1; values_s += i; } else { values = V_score->values; i = *values + 1; values += i; } while(--i) { template = SU ? *--values_s : *--values; score = Score[template]; pos = extendScore[template]; gaps = start - pos; /* extend chain */ if(!include[template]) { include[template] = 1; bests[++*bests] = template; if(start) { score = W1 + (start - 1) * U; score = V_score->weight + MAX(Wl, score); } else { score = V_score->weight; } } else { if(gaps < 0) { if(gaps == -kmersize) { score += V_score->weight - (kmersize - 1) * M; } else { score += (W1 + (-gaps - 1) * U) + V_score->weight + gaps * M; } } else if(gaps == 0) { score += V_score->weight + W1; } else if(gaps <= 2) { score += V_score->weight + gaps * MM; } else if((MM * 2 + (gaps - 2) * M) < 0) { score += V_score->weight + (MM * 2 + (gaps - 2) * M); } else { MMs = gaps / kmersize + (gaps % kmersize ? 1 : 0); MMs = MAX(2, MMs); gaps -= MMs; Ms = MIN(gaps, kmersize); score += V_score->weight + Ms * M + MMs * MM; } /* verify extension */ if(score < 0) { test = start ? (W1 + (start - 1) * U) : 0; test = MAX(test, Wl); if(score <= test + V_score->weight) { score = test + V_score->weight; } } } /* update Scores */ if(V_score->score < score) { V_score->score = score; } Score[template] = score; extendScore[template] = end; } /* Mark last best hit */ if(best_score->score < V_score->score) { best_score = V_score; ties = 0; } else if(best_score->score == V_score->score) { /* first hit on rc is likely last hit on forward */ best_score = V_score; ++ties; } ++V_score; } /* clear Score arrays */ clearScore(bests, Score); clearScore(bests, extendScore); i = *bests + 1; while(--i) { include[*++bests] = 0; } /* no good hits */ if(best_score->score < kmersize) { return 1; } /* prune hits */ VF_scores = pruneAnkers(VF_scores, kmersize); /* get best chain, start/end, score, template(s) and zero out ankers */ *include = SU; *bestTemplates = 0; tmp_score = getChainTemplates(best_score, rewards, kmersize, bestTemplates, Score, extendScore, include); score = best_score->score; start = tmp_score->start; len = best_score->end - start; /* verify best anker */ if(len < minlen || score < mrs * len) { *include = 0; return 1; } /* get best chains */ while(best_score) { /* get equal ankers inside chain, that lies under the threshold */ if(ties) { score = best_score->score; V_score = best_score; while((V_score = getTieAnker(start, V_score, score))) { /* 1. tie anker -> tie_len == best_len 2. Best match is last on seq -> tie_start < best_start 1. && 2. -> cover = |tie_start - best_end| / len */ if((V_score->end - start) <= coverT * len ) { /* not a co-match / overlap is insufficient -> no more equal matches */ V_score = 0; } else { /* Anker is equal, update with templates */ /* Mark current templates to avoid double hitting */ i = *bestTemplates + 1; bests = bestTemplates; while(--i) { include[*++bests] = 1; } /* update best template candidates */ template = *bests; *bests = 0; getChainTemplates(V_score, rewards, kmersize, bests, Score, extendScore, include); *bestTemplates += *bests; *bests = template; } } } /* use segment trees to mark "used" regions of query. Allow for quick check of intersection with chosen chains. */ growSeqmentTree(chainSeqments, start, best_score->end); /* insert anker-boundaries */ insertKmerBound((Qseqs *) header, start, best_score->end); /* print match */ lock(excludeOut); i = deConPrintPtr(bestTemplates, qseq, best_score->score, header, flag, out); unlock(excludeOut); /* get next match */ ties = 0; best_score->score = 0; *bestTemplates = 0; while(best_score->score == 0) { /* find best anker */ if((best_score = getBestAnker(&VF_scores, &ties))) { if(kmersize < best_score->score) { /* check chain */ tmp_score = getChainTemplates(best_score, rewards, kmersize, bestTemplates, Score, extendScore, include); start = tmp_score->start; cover = queSeqmentTree(chainSeqments->root, start, best_score->end); len = best_score->end - start; /* verify chain */ if(len < minlen || coverT * len < cover || best_score->score < mrs * len) { /* silence anker */ best_score->score = 0; } } else { /* silence anker */ best_score->score = 0; } } else { *include = 0; return 0; } } } *include = 0; return 1; } genomicepidemiology-kma-091b8ffe66ac/kmeranker.c0000644000175000017500000001765514157033525021252 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "kmeranker.h" #include "penalties.h" KmerAnker * (*getChainTemplates)(KmerAnker*, const Penalties*, int, int*, int*, int*, char*) = &getBestChainTemplates; KmerAnker * getBestChainTemplates(KmerAnker *src, const Penalties *rewards, int kmersize, int *bests, int *Score, int *extendScore, char *include) { /* get set of best templates and silences the chain, except for the initial anker */ int i, j, template, score, tmpScore, bestScore, Wl, W1, U, M, MM, Ms, MMs; int gaps, start, end, pos, SU, nextAnker; unsigned *values; short unsigned *values_s; KmerAnker *node, *prev; /* mark template candidates */ if(!src) { return 0; } else if((SU = *include)) { values_s = (short unsigned *) src->values; i = *values_s; *bests = i; ++i; values_s += i; bests += i; while(--i) { include[(*--bests = *--values_s)] ^= 1; } } else { values = src->values; i = *values; *bests = i; ++i; values += i; bests += i; while(--i) { include[(*--bests = *--values)] ^= 1; } } --bests; M = rewards->M; MM = rewards->MM; U = rewards->U; W1 = rewards->W1; Wl = rewards->Wl; bestScore = src->score; values_s = 0; values = 0; nextAnker = 1; prev = src; /* get chaining scores */ for(node = src; nextAnker; --node) { if(SU) { values_s = (short unsigned *) node->values; i = *values_s + 1; values_s += i; } else { values = node->values; i = *values + 1; values += i; } start = node->start; end = node->end; while(--i) { template = SU ? *--values_s : *--values; if(include[template]) { score = Score[template]; pos = extendScore[template]; gaps = pos - end; /* extend chain */ if(pos == 0) { score = node->weight; } else { if(gaps < 0) { if(gaps == -kmersize) { score += node->weight - (kmersize - 1) * M; } else { score += (W1 + (-gaps - 1) * U) + node->weight + gaps * M; } } else if(gaps == 0) { score += node->weight + W1; } else if(gaps <= 2) { score += node->weight + gaps * MM; } else if((MM * 2 + (gaps - 2) * M) < 0) { score += node->weight + (MM * 2 + (gaps - 2) * M); } else { MMs = gaps / kmersize + ((gaps % kmersize) ? 1 : 0); MMs = 2 < MMs ? MMs : 2; gaps -= MMs; Ms = gaps < kmersize ? gaps : kmersize; score += node->weight + Ms * M + MMs * MM; } /* mark as used */ node->score = 0; } /* verify extension */ if(bestScore <= score) { /* test if anker is finalising the chain */ if(node->start) { tmpScore = W1 + (node->start - 1) * U; tmpScore = score + (Wl < tmpScore ? tmpScore : Wl); } else { tmpScore = score; } if(tmpScore == bestScore) { score = bestScore; nextAnker = 0; prev = node; } } extendScore[template] = start; Score[template] = score; } } } /* get best templates */ j = 0; for(i = 1; i <= *bests; ++i) { if(Score[(template = bests[i])] == bestScore) { bests[++j] = template; } /* clear Score arrays */ Score[template] = 0; extendScore[template] = 0; include[template] = 0; } *bests = j; return prev; } KmerAnker * getProxiChainTemplates(KmerAnker *src, const Penalties *rewards, int kmersize, int *bests, int *Score, int *extendScore, char *include) { /* get set of best templates and silences the chain, except for the initial anker */ static double minFrac = 0.0; int i, j, template, score, tmpScore, bestScore, Wl, W1, U, M, MM, Ms, MMs; int gaps, start, end, pos, SU, nextAnker, proxiScore; unsigned *values; short unsigned *values_s; KmerAnker *node, *prev; /* mark template candidates */ if(!src) { if(rewards) { minFrac = *((double *) rewards); } return 0; } SU = *include; *bests = 0; M = rewards->M; MM = rewards->MM; U = rewards->U; W1 = rewards->W1; Wl = rewards->Wl; bestScore = src->score; proxiScore = minFrac * bestScore; values_s = 0; values = 0; nextAnker = 1; prev = src; /* get chaining scores */ for(node = src; nextAnker; --node) { if(SU) { values_s = (short unsigned *) node->values; i = *values_s + 1; values_s += i; } else { values = node->values; i = *values + 1; values += i; } start = node->start; end = node->end; while(--i) { template = SU ? *--values_s : *--values; if(!include[template]) { score = Score[template]; pos = extendScore[template]; gaps = pos - end; /* extend chain */ if(pos == 0) { /* new template */ score = node->weight; bests[++*bests] = template; } else { if(gaps < 0) { if(gaps == -kmersize) { score += node->weight - (kmersize - 1) * M; } else { score += (W1 + (-gaps - 1) * U) + node->weight + gaps * M; } } else if(gaps == 0) { score += node->weight + W1; } else if(gaps <= 2) { score += node->weight + gaps * MM; } else if((MM * 2 + (gaps - 2) * M) < 0) { score += node->weight + (MM * 2 + (gaps - 2) * M); } else { MMs = gaps / kmersize + ((gaps % kmersize) ? 1 : 0); MMs = 2 < MMs ? MMs : 2; gaps -= MMs; Ms = gaps < kmersize ? gaps : kmersize; score += node->weight + Ms * M + MMs * MM; } /* mark as used */ node->score = 0; } /* verify extension */ if(bestScore <= score) { /* test if anker is finalising the chain */ if(node->start) { tmpScore = W1 + (node->start - 1) * U; tmpScore = score + (Wl < tmpScore ? tmpScore : Wl); } else { tmpScore = score; } if(tmpScore == bestScore) { score = bestScore; nextAnker = 0; prev = node; } } extendScore[template] = start; Score[template] = score; } } } /* get best templates */ j = 0; for(i = 1; i <= *bests; ++i) { if(proxiScore <= Score[(template = bests[i])]) { bests[++j] = template; } /* clear Score arrays */ Score[template] = 0; extendScore[template] = 0; include[template] = 0; } *bests = j; return prev; } KmerAnker * pruneAnkers(KmerAnker *V_score, int kmersize) { KmerAnker *node, *prev; if(!V_score || !V_score->score) { return 0; } while(V_score->score < kmersize && (V_score = V_score->descend)); if(!V_score) { return 0; } prev = V_score; node = V_score->descend; while(node) { if(kmersize <= node->score) { prev->descend = node; prev = node; } node = node->descend; } prev->descend = 0; return V_score; } KmerAnker * getBestAnker(KmerAnker **src, unsigned *ties) { KmerAnker *node, *prev, *best; *ties = 0; prev = *src; while(prev && prev->score == 0) { prev = prev->descend; } *src = prev; if(!prev) { return 0; } best = prev; node = prev->descend; while(node) { if(node->score) { if(best->score < node->score) { best = node; *ties = 0; } else if(best->score == node->score) { best = node; ++*ties; } prev->descend = node; prev = node; } node = node->descend; } prev->descend = 0; return best; } KmerAnker * getTieAnker(int stop, KmerAnker *src, int score) { if(!src || src->start == stop) { return 0; } /* search downwards */ while(stop < (--src)->start) { if(src->score == score) { return src; } } return 0; } genomicepidemiology-kma-091b8ffe66ac/frags.h0000644000175000017500000000221014157033525020357 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "filebuff.h" #include "qseqs.h" #ifndef FRAG typedef struct frag Frag; struct frag { int buffer[7]; unsigned char *qseq; unsigned char *header; struct frag *next; }; #define FRAG 1 #endif FILE * printFrags(Frag **alignFrags, int DB_size); void updateAllFrag(unsigned char *qseq, int q_len, int bestHits, int best_read_score, int *best_start_pos, int *best_end_pos, int *bestTemplates, Qseqs *header, FileBuff *dest); genomicepidemiology-kma-091b8ffe66ac/hashmapcci.c0000644000175000017500000003304114157033525021356 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "hashmapcci.h" #include "pherror.h" #include "stdnuc.h" #include "threader.h" #ifndef _WIN32 #include #include #include #else typedef int key_t; #define ftok(charPtr, integer) (0) #define shmget(key, size, permission) ((size != 0) ? (-1) : (-key)) #define shmat(shmid, NULL_Ptr, integer) (NULL) #endif HashMapCCI * (*alignLoadPtr)(HashMapCCI *, int, int, int, long unsigned) = &alignLoad_fly; long unsigned hashMapCCI_initialize(HashMapCCI *dest, int len, int kmerindex) { long unsigned size; dest->len = len; dest->cci_next = 1; dest->kmerindex = kmerindex; /* convert to 2 times nearest power of 2 */ size = (len << 1) - 1; size |= size >> 1; size |= size >> 2; size |= size >> 4; size |= size >> 8; size |= size >> 16; size |= size >> 32; dest->mask = size++; if(dest->size < size) { if(dest->size) { free(dest->index); free(dest->seq); } dest->size = size; /* add closed chains */ dest->cci_size = size + 1;//(size >> 1) + (size >> 2) + 2; dest->index = calloc(size + dest->cci_size, sizeof(int)); dest->seq = malloc(((len >> 5) + 1) * sizeof(long unsigned)); if(!dest->index || !dest->seq) { ERROR(); } size = 0; } else { dest->cci_size = size + 1;//(size >> 1) + (size >> 2) + 2; size += dest->cci_size; } dest->cci_avail = dest->cci_size - 1; dest->chain = dest->index + dest->mask; /* 1-indexed */ return size; } void hashMapCCI_destroy(HashMapCCI *dest) { if(dest) { if(dest->index) { free(dest->index); } if(dest->seq) { free(dest->seq); } free(dest); } } int hashMapCCI_get(const HashMapCCI *dest, long unsigned key, unsigned shifter) { long unsigned index; int pos, *chain; /* get hash */ murmur(index, key); index &= dest->mask; /* check index */ if((pos = dest->index[index]) == 0) { return 0; } else if(0 < pos) { return (getKmer(dest->seq, pos - 1, shifter) == key) ? pos : 0; } /* check chain */ chain = dest->chain - pos - 1; while((pos = *++chain)) { if(getKmer(dest->seq, abs(pos) - 1, shifter) == key) { return pos; } } return 0; } int hashMapCCI_get_bound(const HashMapCCI *dest, long unsigned key, int min, int max, unsigned shifter) { long unsigned index; int pos, apos, *chain; /* get hash */ murmur(index, key); index &= dest->mask; /* check index */ if((pos = dest->index[index]) == 0) { return 0; } else if(0 < pos) { return (min < pos && pos < max && getKmer(dest->seq, pos - 1, shifter) == key) ? pos : 0; } /* check chain */ chain = dest->chain - pos - 1; while((pos = *++chain)) { apos = abs(pos); if(min < apos && apos < max && getKmer(dest->seq, apos - 1, shifter) == key) { return pos; } } return 0; } int * hashMapCCI_getDubPos(const HashMapCCI *dest, long unsigned key, int value, unsigned shifter) { long unsigned index; int pos, *chain; /* check input */ if(0 < value) { return 0; } /* get hash */ murmur(index, key); index &= dest->mask; /* check index */ if(0 <= (pos = dest->index[index])) { return 0; } /* check chain */ chain = dest->chain - pos - 1; while((pos = *++chain)) { if(pos == value) { return chain; } } return 0; } int * hashMapCCI_getNextDubPos(const HashMapCCI *dest, int *chain, long unsigned key, int min, int max, unsigned shifter) { int pos; min = -min; max = -max; /* check chain */ while((pos = *++chain)) { if(pos < 0 && max < pos && pos < min && getKmer(dest->seq, -pos - 1, shifter) == key) { return chain; } } return 0; } int defragChain(HashMapCCI *dest, int size, int shifter) { /* defragmentize the chains to make space for new chain, return 0 on failure */ int newsize, cci_size, pos, newpos, index, fulldefrag; int *newchain, *chain, *next; long unsigned ipos, kmer; /* check if chain is available */ if(size <= dest->cci_avail) { dest->cci_avail -= size; pos = dest->cci_next; dest->cci_next += size; return pos; } dest->cci_avail = 0; fulldefrag = dest->cci_next == 1; /* sync cci_next / move to next available slot */ pos = dest->cci_next; chain = dest->chain + pos; next = chain--; cci_size = dest->cci_size - 1; while(pos < cci_size && *chain != *next) { ++pos; chain = next++; } /* end of chains, start over */ if(cci_size <= pos) { if(fulldefrag) { return 0; } dest->cci_next = 1; return defragChain(dest, size, shifter); } dest->cci_next = pos; /* defragmentize to make space */ newsize = 0; newpos = pos; /* index of newchain */ index = pos; /* index of chain */ newchain = chain++; /* newchain is one behind */ next = chain + 1; /* find new fragment of min size */ while(index < cci_size && newsize < size) { next = chain + 1; while(index < cci_size && *chain == *next && newsize < size) { ++newsize; ++index; chain = next++; } if(index < cci_size && newsize < size) { kmer = getKmer(dest->seq, abs(*next) - 1, shifter); murmur(ipos, kmer); ipos &= dest->mask; dest->index[ipos] = -newpos; chain = next; ++index; while(*chain) { *++newchain = *chain; *chain++ = 0; ++newpos; ++index; } *++newchain = 0; ++newpos; } } ++newchain; dest->cci_next = (index < cci_size) ? index : 1; /* check if defrag was succesfull */ if(newsize < size && !fulldefrag) { dest->cci_next = 1; return defragChain(dest, size, shifter); } return (newsize < size) ? 0 : newpos; } int newChain(HashMapCCI *dest, int pos, int newpos, long unsigned kmer, int shifter) { /* add new chain to hashmap */ int *chain; unsigned index; if(4 <= dest->cci_avail) { index = dest->cci_next; dest->cci_next += 4; dest->cci_avail -= 4; } else if(3 <= dest->cci_avail) { index = dest->cci_next; dest->cci_next += 3; dest->cci_avail -= 3; } else { /* no space left, defrag chains */ index = defragChain(dest, 3, shifter); } chain = dest->chain + index; /* check duplication */ if(getKmer(dest->seq, pos - 1, shifter) == kmer) { *chain = -pos; *++chain = -newpos; } else { *chain = pos; *++chain = newpos; } return -index; } int extendChain(HashMapCCI *dest, int chainpos, int newpos, long unsigned kmer, int shifter) { int pos, dup, size, *chain, *newchain; long unsigned index; pos = chainpos; chain = dest->chain + pos; dup = 1; while(*chain && dup) { if(getKmer(dest->seq, abs(*chain) - 1, shifter) == kmer) { dup = 0; if(0 < *chain) { *chain = -*chain; } } ++pos; ++chain; } if(dup == 0) { newpos = -newpos; while(*chain) { ++pos; ++chain; } } /* check if chain is sufficent */ size = pos - chainpos + 2; if(*++chain == 0) { *--chain = newpos; /* move next avail chain */ if(dest->cci_avail && pos + 1 == dest->cci_next) { ++dest->cci_next; --dest->cci_avail; } } else if(chainpos != 1 && (dest->chain[chainpos - 2] == 0 || chainpos == 2)) { /* check previous chain */ /* move chain one back */ newchain = dest->chain + chainpos; chain = newchain--; while(*chain) { *newchain++ = *chain++; } *newchain = newpos; --chainpos; /* threading -> unordered */ //dest->chain[--chainpos] = newpos; } else if((pos = defragChain(dest, size, shifter))) { /* mv to new pos */ murmur(index, kmer); index &= dest->mask; chainpos = -(dest->index[index]); chain = dest->chain + chainpos; newchain = dest->chain + pos; while(*chain) { *newchain++ = *chain; *chain++ = 0; } *newchain = newpos; chainpos = pos; } else { /* defrag failed -> bias chains by one to the end of chains */ /* get new chainpos */ murmur(index, kmer); index &= dest->mask; chainpos = -(dest->index[index]); /* go to end of chain */ chain = dest->chain + chainpos; while(*++chain); /* bias by one to end of chains */ newchain = chain++; while(*newchain != *chain) { if((dup = *newchain) == 0) { /* add new chain index */ kmer = getKmer(dest->seq, abs(newpos) - 1, shifter); murmur(index, kmer); index &= dest->mask; --(dest->index[index]); } *newchain = newpos; newpos = dup; newchain = chain++; } } return -chainpos; } void hashMapCCI_add(HashMapCCI *dest, long unsigned key, int newpos, unsigned shifter) { int pos, *index_ptr; long unsigned index; if(key == 0) { /* likely undefined region */ return; } /* get hash */ murmur(index, key); index_ptr = dest->index + (index & dest->mask); /* check index */ if((pos = *index_ptr) == 0) { *index_ptr = newpos; } else if(0 < pos) { /* new chain */ *index_ptr = newChain(dest, pos, newpos, key, shifter); } else { /* extend chain */ *index_ptr = extendChain(dest, -pos, newpos, key, shifter); } } void hashMapCCI_add_thread(HashMapCCI *dest, long unsigned key, int newpos, unsigned shifter) { static volatile int Lock[2] = {0, 0}; volatile int *indexLock = &Lock[0], *cciLock = &Lock[1]; int pos, *index_ptr; long unsigned index; if(key == 0) { /* likely undefined region */ return; } /* get hash */ murmur(index, key); index_ptr = dest->index + (index & dest->mask); /* check index */ lockTime(indexLock, 1); if((pos = *index_ptr) == 0) { *index_ptr = newpos; unlock(indexLock); } else { unlock(indexLock); /* check chain */ lockTime(cciLock, 5); if((pos = *index_ptr) < 0) { /* extend chain */ *index_ptr = extendChain(dest, -pos, newpos, key, shifter); } else { *index_ptr = newChain(dest, pos, newpos, key, shifter); } unlock(cciLock); } } HashMapCCI * hashMapCCI_load(HashMapCCI *src, int seq, int len, int kmersize) { int i, end, shifter; long size; /* init */ if(src == 0) { src = smalloc(sizeof(HashMapCCI)); src->size = 0; } if((size = hashMapCCI_initialize(src, len, kmersize))) { memset(src->index, 0, size * sizeof(int)); } /* get seq */ size = ((src->len >> 5) + 1) * sizeof(long unsigned); if(size != read(seq, src->seq, size)) { if(0 < size) { fprintf(stderr, "Corrupted *.seq.b\n"); exit(1); } else { ERROR(); } } /* add k-mers */ shifter = sizeof(long unsigned) * sizeof(long unsigned) - (src->kmerindex << 1); end = len - kmersize + 1; for(i = 0; i < end; ++i) { hashMapCCI_add(src, getKmer(src->seq, i, shifter), i + 1, shifter); } return src; } HashMapCCI * hashMapCCI_load_thread(HashMapCCI *src, int seq, int len, int kmersize, int thread_num) { static volatile int Lock = 0, next = 1, thread_wait = 0; static long unsigned size; volatile int *lock = &Lock; int i, end, shifter, chunk; long check; /* init */ lock(lock); if(src->len == 0) { size = hashMapCCI_initialize(src, len, kmersize); thread_wait = thread_num; next = 0; unlock(lock); /* get seq */ check = ((src->len >> 5) + 1) * sizeof(long unsigned); if(check != read(seq, src->seq, check)) { if(check < 0) { ERROR(); } else { fprintf(stderr, "Corrupted *.seq.b\n"); exit(1); } } } else { unlock(lock); } /* set in chunks of 16224 */ chunk = 16224; while(chunk) { lock(lock); i = next; if((next += chunk) < 0) { next = size; } unlock(lock); if(i < size) { if(size < i + chunk) { chunk = size - i; } memset(src->index + i, 0, chunk * sizeof(int)); } else { chunk = 0; } } /* this version slurps cpu in the locks of hashMapCCI_add_thread */ /* wait for init and seq to finish */ /* int stop; lock(lock); if(--thread_wait == 0) { next = 0; } unlock(lock); wait_atomic(thread_wait); */ /* add k-mers */ /* shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); end = len - kmersize + 1; chunk = 16224; while(chunk) { lock(lock); i = next; if((next += chunk) < 0) { next = end; } unlock(lock); if(i < end) { stop = (end <= i + chunk) ? end : (i + chunk); --i; while(++i < stop) { hashMapCCI_add_thread(src, getKmer(src->seq, i, shifter), i + 1, shifter); } } else { chunk = 0; } } */ lock(lock); if(--thread_wait == 0) { /* add k-mers */ shifter = sizeof(long unsigned) * sizeof(long unsigned) - (src->kmerindex << 1); end = len - kmersize + 1; i = -1; while(++i < end) { hashMapCCI_add(src, getKmer(src->seq, i, shifter), i + 1, shifter); } } unlock(lock); /* might not be completely loaded here, thus external thread_wait is required */ return src; } void hashMapCCI_dump(HashMapCCI *src, FILE *seq) { cfwrite(src->seq, sizeof(long unsigned), (src->len >> 5) + 1, seq); } HashMapCCI * alignLoad_fly(HashMapCCI *dest, int seq_in, int len, int kmersize, long unsigned seq_index) { /* move file pointer */ lseek(seq_in, seq_index, SEEK_SET); return hashMapCCI_load(dest, seq_in, len, kmersize); } HashMapCCI * alignLoad_fly_mem(HashMapCCI *dest, int seq_in, int len, int kmersize, long unsigned seq_index) { return hashMapCCI_load(dest, seq_in, len, kmersize); } HashMapCCI * alignLoad_skip(HashMapCCI *dest, int seq_in, int len, int kmersize, long unsigned seq_index) { dest->len = len; dest->kmerindex = kmersize; return dest; } genomicepidemiology-kma-091b8ffe66ac/kma.c0000644000175000017500000012764714157033525020046 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "ankers.h" #include "align.h" #include "alnfrags.h" #include "assembly.h" #include "chain.h" #include "hashmapkma.h" #include "kma.h" #include "kmapipe.h" #include "kmeranker.h" #include "kmers.h" #include "kmmap.h" #include "mt1.h" #include "penalties.h" #include "pherror.h" #include "qseqs.h" #include "runinput.h" #include "runkma.h" #include "savekmers.h" #include "sparse.h" #include "spltdb.h" #include "stdstat.h" #include "tmp.h" #include "vcf.h" #include "version.h" char * strjoin(char **strings, int len) { int i, new_len, escape; char *newStr, *stringPtr; new_len = len + 16; escape = 0; for(i = 0; i < len; ++i) { if(*strings[i] == '-') { escape = 0; } else if(escape) { new_len += 2; } new_len += strlen(strings[i]); if(strncmp(strings[i], "-i", 2) == 0) { escape = 1; } } newStr = smalloc(new_len); *newStr = 0; escape = 0; stringPtr = newStr; for(i = 0; i < len; ++i) { if(*strings[i] == '-') { escape = 0; } if(escape) { *stringPtr = '\"'; ++stringPtr; } new_len = strlen(strings[i]); strcpy(stringPtr, strings[i]); stringPtr += new_len; if(escape) { *stringPtr = '\"'; ++stringPtr; } *stringPtr = ' '; ++stringPtr; if(*strings[i] == '-' && (strings[i][1] == 'i' || strings[i][1] == 'o')) { escape = 1; } } return newStr; } static void helpMessage(int exitStatus) { FILE *out = exitStatus ? stderr : stdout; fprintf(out, "# KMA-%s maps and/or aligns raw reads to a template database.\n", KMA_VERSION); fprintf(out, "# %16s\t%-32s\t%s\n", "Options:", "Desc:", "Default:"); fprintf(out, "#\n# Input:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-i", "Single end input(s)", "stdin"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ipe", "Paired end input(s)", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-int", "Interleaved input(s)", ""); fprintf(out, "#\n# Output:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-o", "Output prefix", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-ef", "Output additional features", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-vcf", "Output vcf file, 2 to apply FT", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-sam", "Output sam, 4/2096 for mapped/aligned", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-nc", "No consensus file", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-nc", "No aln file", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-nf", "No frag file", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-matrix", "Output assembly matrix", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-a", "Output all template mappings", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-and", "Use both mrs and p-value on consensus", "or"); fprintf(out, "# %16s\t%-32s\t%s\n", "-oa", "Use neither mrs or p-value on consensus", "False"); fprintf(out, "#\n# Consensus:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-bc", "Minimum support to call bases", "0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-bcNano", "Altered indel calling for ONT data", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-bcd", "Minimum depth to cal bases", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-bcg", "Maintain insignificant gaps", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ID", "Minimum consensus ID", "1.0%"); fprintf(out, "# %16s\t%-32s\t%s\n", "-dense", "Skip insertion in consensus", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ref_fsa", "Use n's on indels", "False"); fprintf(out, "#\n# General:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-t_db", "Template DB", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-p", "P-value", "0.05"); fprintf(out, "# %16s\t%-32s\t%s\n", "-shm", "Use DB in shared memory", "0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mmap", "Memory map *.comp.b", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-tmp", "Set directory for temporary files", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-t", "Number of threads", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-status", "Extra status", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-verbose", "Extra verbose", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-c", "Citation", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-v", "Version", ""); fprintf(out, "# %16s\t%-32s\t%s\n", "-h", "Shows this help message", ""); fprintf(out, "#\n# Template mapping:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ConClave", "ConClave version", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mem_mode", "Base ConClave on template mappings", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-proxi", "Proximity scoring (negative for soft)", "False/1.0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ex_mode", "Searh kmers exhaustively", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-deCon", "Remove contamination", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-Sparse", "Only count kmers", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ss", "Sparse sorting (q,c,d)", "q"); fprintf(out, "# %16s\t%-32s\t%s\n", "-Mt1", "Map everything to one template", "False/0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-pm", "Pairing method (p,u,f)", "u"); fprintf(out, "# %16s\t%-32s\t%s\n", "-1t1", "One query to one template", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-hmm", "Use a HMM to assign template(s)", "True"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ck", "Count k-mers over pseudo alignment", "False"); fprintf(out, "#\n# Chaining:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-k", "K-mersize", "DB defined"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ts", "Trim front of seeds", "0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ssa", "Seeds soround alignments", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ex_mode", "Searh kmers exhaustively", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-fpm", "Pairing method (p,u,f)", "u"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mq", "Minimum mapping quality", "0"); fprintf(out, "#\n# Alignment:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ca", "Circular alignments", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mrs", "Minimum relative alignment score", "0.5"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mrc", "Minimum query coverage", "0.0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ml", "Minimum alignment length", "16"); fprintf(out, "# %16s\t%-32s\t%s\n", "-reward", "Score for match", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-penalty", "Penalty for mismatch", "2"); fprintf(out, "# %16s\t%-32s\t%s\n", "-gapopen", "Penalty for gap opening", "3"); fprintf(out, "# %16s\t%-32s\t%s\n", "-gapextend", "Penalty for gap extension", "1"); fprintf(out, "# %16s\t%-32s\t%s\n", "-per", "Reward for pairing reads", "7"); fprintf(out, "# %16s\t%-32s\t%s\n", "-Npenalty", "Penalty matching N", "0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-transition", "Penalty for transition", "2"); fprintf(out, "# %16s\t%-32s\t%s\n", "-transversion", "Penalty for transversion", "2"); fprintf(out, "# %16s\t%-32s\t%s\n", "-sasm", "Skip alignment", "False"); fprintf(out, "#\n# Trimming:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mp", "Minimum phred score", "20"); fprintf(out, "# %16s\t%-32s\t%s\n", "-eq", "Minimum avg. quality score", "0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-5p", "Trim 5 prime", "0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-3p", "Trim 3 prime", "0"); fprintf(out, "# %16s\t%-32s\t%s\n", "-ml", "Minimum length", "16"); fprintf(out, "# %16s\t%-32s\t%s\n", "-xl", "Maximum length on se", "2147483647"); fprintf(out, "# %16s\t%-32s\t%s\n", "-boot", "Bootstrap sub-sequence", "False"); fprintf(out, "#\n# Presets:\n"); fprintf(out, "# %16s\t%-32s\t%s\n", "-apm", "Sets both pm and fpm", "u"); fprintf(out, "# %16s\t%-32s\t%s\n", "-cge", "Set CGE penalties and rewards", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mint2", "Set 2ng gen Mintyper preset", "False"); fprintf(out, "# %16s\t%-32s\t%s\n", "-mint3", "Set 3rd gen Mintyper preset", "False"); fprintf(out, "#\n"); exit(exitStatus); } int kma_main(int argc, char *argv[]) { static const double prob[128] = { 1.0000000000000000, 0.7943282347242815, 0.6309573444801932, 0.5011872336272722, 0.3981071705534972, 0.3162277660168379, 0.2511886431509580, 0.1995262314968880, 0.1584893192461113, 0.1258925411794167, 0.1000000000000000, 0.0794328234724281, 0.0630957344480193, 0.0501187233627272, 0.0398107170553497, 0.0316227766016838, 0.0251188643150958, 0.0199526231496888, 0.0158489319246111, 0.0125892541179417, 0.0100000000000000, 0.0079432823472428, 0.0063095734448019, 0.0050118723362727, 0.0039810717055350, 0.0031622776601684, 0.0025118864315096, 0.0019952623149689, 0.0015848931924611, 0.0012589254117942, 0.0010000000000000, 0.0007943282347243, 0.0006309573444802, 0.0005011872336273, 0.0003981071705535, 0.0003162277660168, 0.0002511886431510, 0.0001995262314969, 0.0001584893192461, 0.0001258925411794, 0.0001000000000000, 0.0000794328234724, 0.0000630957344480, 0.0000501187233627, 0.0000398107170553, 0.0000316227766017, 0.0000251188643151, 0.0000199526231497, 0.0000158489319246, 0.0000125892541179, 0.0000100000000000, 0.0000079432823472, 0.0000063095734448, 0.0000050118723363, 0.0000039810717055, 0.0000031622776602, 0.0000025118864315, 0.0000019952623150, 0.0000015848931925, 0.0000012589254118, 0.0000010000000000, 0.0000007943282347, 0.0000006309573445, 0.0000005011872336, 0.0000003981071706, 0.0000003162277660, 0.0000002511886432, 0.0000001995262315, 0.0000001584893192, 0.0000001258925412, 0.0000001000000000, 0.0000000794328235, 0.0000000630957344, 0.0000000501187234, 0.0000000398107171, 0.0000000316227766, 0.0000000251188643, 0.0000000199526231, 0.0000000158489319, 0.0000000125892541, 0.0000000100000000, 0.0000000079432823, 0.0000000063095734, 0.0000000050118723, 0.0000000039810717, 0.0000000031622777, 0.0000000025118864, 0.0000000019952623, 0.0000000015848932, 0.0000000012589254, 0.0000000010000000, 0.0000000007943282, 0.0000000006309573, 0.0000000005011872, 0.0000000003981072, 0.0000000003162278, 0.0000000002511886, 0.0000000001995262, 0.0000000001584893, 0.0000000001258925, 0.0000000001000000, 0.0000000000794328, 0.0000000000630957, 0.0000000000501187, 0.0000000000398107, 0.0000000000316228, 0.0000000000251189, 0.0000000000199526, 0.0000000000158489, 0.0000000000125893, 0.0000000000100000, 0.0000000000079433, 0.0000000000063096, 0.0000000000050119, 0.0000000000039811, 0.0000000000031623, 0.0000000000025119, 0.0000000000019953, 0.0000000000015849, 0.0000000000012589, 0.0000000000010000, 0.0000000000007943, 0.0000000000006310, 0.0000000000005012, 0.0000000000003981, 0.0000000000003162, 0.0000000000002512, 0.0000000000001995}; static int minPhred, minQ, fiveClip, threeClip, ConClave, mem_mode; static int fileCounter, fileCounter_PE, fileCounter_INT, Ts, Tv, minlen; static int extendedFeatures, spltDB, thread_num, kmersize, targetNum, mq; static int ref_fsa, print_matrix, print_all, sam, vcf, Mt1, bcd, one2one; static int sparse_run, ts, maxlen, **d, status = 0; static unsigned xml, nc, nf, shm, exhaustive, verbose; static char *outputfilename, *templatefilename, **templatefilenames; static char **inputfiles, **inputfiles_PE, **inputfiles_INT, ss; static double ID_t, scoreT, coverT, mrc, evalue, minFrac, support; static Penalties *rewards; int i, j, args, exe_len, fileCount, size, escape, tmp, step1, step2; unsigned totFrags; char *to2Bit, *exeBasic, *myTemplatefilename; FILE *templatefile, *ioStream; time_t t0, t1; Qseqs qseq; HashMapKMA *templates; step1 = 0; step2 = 0; if(argc) { if(sizeof(long unsigned) != 8) { fprintf(stderr, "Need a 64-bit system.\n"); exit(1); } /* SET DEFAULTS */ ConClave = 1; verbose = 0; vcf = 0; xml = 0; sam = 0; nc = 0; nf = 0; targetNum = 0; spltDB = 0; extendedFeatures = 0; minPhred = 20; minQ = 0; fiveClip = 0; threeClip = 0; sparse_run = 0; fileCounter = 0; fileCounter_PE = 0; fileCounter_INT = 0; outputfilename = 0; templatefilename = 0; print_matrix = 0; print_all = 0; ref_fsa = 0; kmersize = 0; ts = 0; minlen = 16; maxlen = 2147483647; evalue = 0.05; support = 0.0; minFrac = 1.0; exhaustive = 0; shm = 0; mq = 0; bcd = 1; scoreT = 0.5; coverT = 0.1; mrc = 0.1; ID_t = 1.0; one2one = 0; ss = 'q'; mem_mode = 0; rewards = smalloc(sizeof(Penalties)); rewards->M = 1; rewards->MM = -2; rewards->U = -1; rewards->W1 = -3; rewards->Wl = -6; rewards->Mn = 0; rewards->PE = 7; Tv = -2; Ts = -2; thread_num = 1; inputfiles_PE = 0; inputfiles_INT = 0; inputfiles = 0; templatefilenames = 0; tmp = 0; Mt1 = 0; inputfiles = 0; deConPrintPtr = printPtr; /* PARSE COMMAND LINE OPTIONS */ args = 1; while(args < argc) { if(strcmp(argv[args], "-t_db") == 0) { if(++args < argc) { templatefilename = malloc(strlen(argv[args]) + 64); if(!templatefilename) { ERROR(); } strcpy(templatefilename, argv[args]); ++targetNum; templatefilenames = realloc(templatefilenames, targetNum * sizeof(char *)); templatefilenames[targetNum - 1] = templatefilename; } while(++args < argc && *argv[args] != '-') { templatefilename = malloc(strlen(argv[args]) + 64); if(!templatefilename) { ERROR(); } strcpy(templatefilename, argv[args]); ++targetNum; templatefilenames = realloc(templatefilenames, targetNum * sizeof(char *)); templatefilenames[targetNum - 1] = templatefilename; } --args; } else if(strcmp(argv[args], "-i") == 0) { ++args; fileCount = fileCounter; for(i = args; i < argc && (strncmp(argv[i], "-", 1) != 0 || strcmp(argv[i], "--") == 0); ++i) { ++fileCounter; } if(fileCounter == 0) { fprintf(stderr, "No files were specified.\n"); exit(1); } else { inputfiles = realloc(inputfiles, fileCounter * sizeof(char *)); if(!inputfiles) { ERROR(); } } for(i = fileCount; i < fileCounter; ++i, ++args) { inputfiles[i] = argv[args]; } --args; } else if(strcmp(argv[args], "-ipe") == 0) { ++args; fileCount = fileCounter_PE; for(i = args; i < argc && strncmp(argv[i], "-", 1) != 0; ++i) { ++fileCounter_PE; } if(fileCounter_PE % 2) { fprintf(stderr, "Uneven number of paired end files.\n"); exit(1); } else if(fileCounter_PE == 0) { fprintf(stderr, "No paired end files were specified.\n"); exit(1); } else { inputfiles_PE = realloc(inputfiles_PE, fileCounter_PE * sizeof(char *)); if(!inputfiles_PE) { ERROR(); } } for(i = fileCount; i < fileCounter_PE; ++i, ++args) { inputfiles_PE[i] = argv[args]; } --args; } else if(strcmp(argv[args], "-int") == 0) { ++args; fileCount = fileCounter_INT; for(i = args; i < argc && (strncmp(argv[i], "-", 1) != 0 || strcmp(argv[i], "--") == 0); ++i) { ++fileCounter_INT; } if(fileCounter_INT == 0) { fprintf(stderr, "No interleaved files were specified.\n"); exit(1); } inputfiles_INT = realloc(inputfiles_INT, fileCounter_INT * sizeof(char *)); if(!inputfiles_INT) { ERROR(); } for(i = fileCount; i < fileCounter_INT; ++i, ++args) { inputfiles_INT[i] = argv[args]; } --args; } else if(strcmp(argv[args], "-pm") == 0) { ++args; if(args < argc) { if(*(argv[args]) == 'p') { save_kmers_pair = &save_kmers_penaltyPair; } else if(*(argv[args]) == 'u') { save_kmers_pair = &save_kmers_unionPair; } else if(*(argv[args]) == 'f') { save_kmers_pair = &save_kmers_forcePair; } else { fprintf(stderr, "Invalid argument at pairing method: \"-pm\"\n"); fprintf(stderr, "Options are:\n"); fprintf(stderr, "p:\tReward for pairing.\n"); fprintf(stderr, "u:\tUnion of best hits.\n"); fprintf(stderr, "f:\tForce paring.\n"); exit(1); } } } else if(strcmp(argv[args], "-fpm") == 0) { ++args; if(args < argc) { if(*(argv[args]) == 'p') { alnFragsPE = &alnFragsPenaltyPE; } else if(*(argv[args]) == 'u') { alnFragsPE = &alnFragsUnionPE; } else if(*(argv[args]) == 'f') { alnFragsPE = &alnFragsForcePE; } else { fprintf(stderr, "Invalid argument at fine pairing method: \"-fpm\"\n"); fprintf(stderr, "Options are:\n"); fprintf(stderr, "p:\tReward for pairing.\n"); fprintf(stderr, "u:\tUnion of best hits.\n"); fprintf(stderr, "f:\tForce paring.\n"); exit(1); } } } else if(strcmp(argv[args], "-apm") == 0) { ++args; if(args < argc) { if(*(argv[args]) == 'p') { alnFragsPE = &alnFragsPenaltyPE; save_kmers_pair = &save_kmers_penaltyPair; } else if(*(argv[args]) == 'u') { alnFragsPE = &alnFragsUnionPE; save_kmers_pair = &save_kmers_unionPair; } else if(*(argv[args]) == 'f') { alnFragsPE = &alnFragsForcePE; save_kmers_pair = &save_kmers_forcePair; } else { fprintf(stderr, "Invalid argument at fine pairing method: \"-fpm\"\n"); fprintf(stderr, "Options are:\n"); fprintf(stderr, "p:\tReward for pairing.\n"); fprintf(stderr, "u:\tUnion of best hits.\n"); fprintf(stderr, "f:\tForce paring.\n"); exit(1); } } } else if(strcmp(argv[args], "-ConClave") == 0) { ++args; if(args < argc) { ConClave = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0 || ConClave < 0 || 2 < ConClave) { fprintf(stderr, " Invalid ConClave version specified.\n"); exit(1); } } } else if(strcmp(argv[args], "-o") == 0) { ++args; if(args < argc) { outputfilename = malloc(strlen(argv[args]) + 64); if(!outputfilename) { ERROR(); } strcpy(outputfilename, argv[args]); } } else if(strcmp(argv[args], "-deCon") == 0) { deConPrintPtr = &deConPrint; printPairPtr = &deConPrintPair; } else if(strcmp(argv[args], "-shm") == 0) { ++args; if(args < argc && argv[args][0] != '-') { shm = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid shm-lvl specified.\n"); exit(1); } } else { --args; shm = 3; } } else if(strcmp(argv[args], "-mmap") == 0 || strcmp(argv[args], "-swap") == 0) { shm |= 32; hashMapKMA_destroy = &hashMapKMA_munmap; } else if(strcmp(argv[args], "-t") == 0) { ++args; if(args < argc && argv[args][0] != '-') { thread_num = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid number of threads specified.\n"); exit(1); } } else { --args; } if(thread_num < 1) { thread_num = 1; } } else if(strcmp(argv[args], "-s1") == 0) { step1 = 1; } else if(strcmp(argv[args], "-s2") == 0) { step2 = 1; } else if(strcmp(argv[args], "-mem_mode") == 0) { mem_mode = 1; alignLoadPtr = &alignLoad_fly_mem; ankerPtr = &ankerAndClean_MEM; } else if(strcmp(argv[args], "-ex_mode") == 0) { exhaustive = 1; } else if(strcmp(argv[args], "-k") == 0) { ++args; if(args < argc) { kmersize = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid kmersize parsed\n"); exit(1); } else if(kmersize == 0) { fprintf(stderr, "# Invalid kmersize parsed, using default\n"); kmersize = 16; } else if(kmersize > 31) { fprintf(stderr, "# Invalid kmersize parsed, max size is 31\n"); exit(1); } } } else if(strcmp(argv[args], "-ts") == 0) { ++args; if(args < argc) { ts = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0 || ts < 0 || ts > 30) { fprintf(stderr, "# Invalid seed trim parsed\n"); exit(1); } } } else if(strcmp(argv[args], "-ssa") == 0) { trimSeedsPtr = &trimSeedsNoLead; leadTailAlnPtr = &skipLeadAln; trailTailAlnPtr = &skipTrailAln; } else if(strcmp(argv[args], "-ml") == 0) { ++args; if(args < argc) { minlen = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid kmersize parsed\n"); exit(1); } } } else if(strcmp(argv[args], "-xl") == 0) { ++args; if(args < argc) { maxlen = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid minimum length parsed\n"); exit(1); } } } else if(strcmp(argv[args], "-mp") == 0) { ++args; if(args < argc) { minPhred = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid minimum phred score parsed\n"); exit(1); } } } else if(strcmp(argv[args], "-eq") == 0) { ++args; if(args < argc) { minQ = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid average quality score parsed\n"); exit(1); } } } else if(strcmp(argv[args], "-mq") == 0) { ++args; if(args < argc) { mq = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "# Invalid minimum mapping quality parsed\n"); exit(1); } } } else if(strcmp(argv[args], "-5p") == 0) { ++args; if(args < argc) { fiveClip = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-5p\".\n"); exit(1); } } } else if(strcmp(argv[args], "-3p") == 0) { ++args; if(args < argc) { threeClip = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-3p\".\n"); exit(4); } } } else if(strcmp(argv[args], "-dense") == 0) { alnToMatPtr = alnToMatDense; } else if(strcmp(argv[args], "-sasm") == 0) { assembly_KMA_Ptr = &skip_assemble_KMA; ID_t = 0.0; } else if(strcmp(argv[args], "-matrix") == 0) { print_matrix = 1; } else if(strcmp(argv[args], "-a") == 0) { print_all = 1; } else if(strcmp(argv[args], "-ref_fsa") == 0) { ref_fsa = 1; if(++args < argc && *(argv[args]) != '-') { ref_fsa = strtoul(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-ref_fsa\".\n"); exit(4); } else if(ref_fsa == 0) { ref_fsa = 2; } } else { --args; } } else if(strcmp(argv[args], "-Sparse") == 0) { sparse_run = 1; } else if(strcmp(argv[args], "-1t1") == 0) { kmerScan = &save_kmers; one2one = 1; } else if(strcmp(argv[args], "-ck") == 0) { get_kmers_for_pair_ptr = &get_kmers_for_pair_count; } else if(strcmp(argv[args], "-hmm") == 0) { kmerScan = &save_kmers_HMM; one2one = 0; } else if(strcmp(argv[args], "-proxi") == 0) { if(++args < argc) { minFrac = strtod(argv[args], &exeBasic); if(*exeBasic != 0 || minFrac < 0 || 1 < minFrac) { fprintf(stderr, "Invalid argument at \"-proxi\".\n"); exit(1); } else { /* set proximity parameter */ getMatch = &getProxiMatch; getMatchSparse = &getProxiMatchSparse; getSecondForce = &getSecondProxiForce; getSecondPen = &getSecondProxiPen; getF = &getF_Proxi; getR = &getR_Proxi; getChainTemplates = &getProxiChainTemplates; getMatch((int *)(&minFrac), 0); getMatchSparse((int *)(&minFrac), 0, 0, 0, 0, 0); getSecondPen((int *)(&minFrac), 0, 0, 0, 0, 0, 0, 0); getF((int *)(&minFrac), 0, 0, 0, 0); ankerAndClean((int *)(&minFrac), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); ankerAndClean_MEM((int *)(&minFrac), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); getProxiChainTemplates(0, (const Penalties *)(&minFrac), 0, 0, 0, 0, 0); } } else { fprintf(stderr, "Need argument at: \"-proxi\".\n"); exit(1); } } else if(strcmp(argv[args], "-ca") == 0) { chainSeedsPtr = &chainSeeds_circular; } else if(strcmp(argv[args], "-ss") == 0) { if(++args < argc) { if(argv[args][0] == 'q') { ss = 'q'; } else if(argv[args][0] == 'c') { ss = 'c'; } else if(argv[args][0] == 'd') { ss = 'd'; } else { fprintf(stderr, "Invalid argument parsed to option: \"-ss\", using default.\n"); } } } else if(strcmp(argv[args], "-p") == 0 || strcmp(argv[args], "-e") == 0) { if(++args < argc) { evalue = strtod(argv[args], &exeBasic); if(*exeBasic != 0 || evalue < 0 || 1.0 < evalue) { fprintf(stderr, "Invalid argument at \"%s\".\n", argv[--args]); exit(1); } } } else if(strcmp(argv[args], "-bc") == 0) { if(++args < argc && argv[args][0] != '-') { significantBase = &significantAndSupport; support = strtod(argv[args], &exeBasic); if(*exeBasic != 0 || support < 0 || 1 < support) { fprintf(stderr, "Invalid argument at \"-bc\".\n"); exit(1); } else { significantAndSupport(0, 0, support); } } else { --args; significantBase = &significantNuc; } } else if(strcmp(argv[args], "-bc90") == 0) { significantBase = &significantAnd90Nuc; } else if(strcmp(argv[args], "-bcg") == 0) { baseCall = &orgBaseCaller; } else if(strcmp(argv[args], "-bcNano") == 0) { if(significantBase == &significantNuc) { significantBase = &significantAnd90Nuc; } baseCall = &nanoCaller; } else if(strcmp(argv[args], "-bcd") == 0) { ++args; if(args < argc) { bcd = strtol(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-bcd\".\n"); exit(1); } } } else if(strcmp(argv[args], "-ID") == 0) { ++args; if(args < argc) { ID_t = strtod(argv[args], &exeBasic); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-ID\".\n"); exit(1); } } } else if(strcmp(argv[args], "-mrs") == 0) { ++args; if(args < argc) { scoreT = strtod(argv[args], &exeBasic); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-mrs\".\n"); exit(1); } } } else if(strcmp(argv[args], "-mrc") == 0) { ++args; if(args < argc) { mrc = strtod(argv[args], &exeBasic); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-mrc\".\n"); exit(1); } } } else if(strcmp(argv[args], "-mct") == 0) { ++args; if(args < argc) { coverT = strtod(argv[args], &exeBasic); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-mct\".\n"); exit(1); } } } else if(strcmp(argv[args], "-reward") == 0) { ++args; if(args < argc) { rewards->M = strtol(argv[args], &exeBasic, 10); rewards->M = abs(rewards->M); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-reward\".\n"); exit(1); } } } else if(strcmp(argv[args], "-penalty") == 0) { ++args; if(args < argc) { rewards->MM = strtol(argv[args], &exeBasic, 10); rewards->MM = MIN(-rewards->MM, rewards->MM); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-penalty\".\n"); exit(1); } } } else if(strcmp(argv[args], "-gapopen") == 0) { ++args; if(args < argc) { rewards->W1 = strtol(argv[args], &exeBasic, 10); rewards->W1 = MIN(-rewards->W1, rewards->W1); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-gapopen\".\n"); exit(1); } } } else if(strcmp(argv[args], "-gapextend") == 0) { ++args; if(args < argc) { rewards->U = strtol(argv[args], &exeBasic, 10); rewards->U = MIN(-rewards->U, rewards->U); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-gapextend\".\n"); exit(1); } } } else if(strcmp(argv[args], "-localopen") == 0) { /* add to help */ ++args; if(args < argc) { rewards->Wl = strtol(argv[args], &exeBasic, 10); rewards->Wl = MIN(-rewards->Wl, rewards->Wl); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-localopen\".\n"); exit(1); } } } else if(strcmp(argv[args], "-Npenalty") == 0) { /* add to help */ ++args; if(args < argc) { rewards->Mn = strtol(argv[args], &exeBasic, 10); rewards->Mn = MIN(-rewards->Mn, rewards->Mn); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-localopen\".\n"); exit(1); } } } else if(strcmp(argv[args], "-per") == 0) { ++args; if(args < argc) { rewards->PE = strtol(argv[args], &exeBasic, 10); rewards->PE = abs(rewards->PE); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-per\".\n"); exit(1); } } } else if(strcmp(argv[args], "-transition") == 0) { /* add to help */ ++args; if(args < argc) { Ts = strtol(argv[args], &exeBasic, 10); Ts = MIN(-Ts, Ts); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-localopen\".\n"); exit(1); } } } else if(strcmp(argv[args], "-transversion") == 0) { /* add to help */ ++args; if(args < argc) { Tv = strtol(argv[args], &exeBasic, 10); Tv = MIN(-Tv, Tv); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-localopen\".\n"); exit(1); } } } else if(strcmp(argv[args], "-and") == 0) { cmp = &cmp_and; } else if(strcmp(argv[args], "-oa") == 0) { cmp = &cmp_true; ID_t = 0.0; } else if(strcmp(argv[args], "-boot") == 0) { printFsa_ptr = &bootFsa; } else if(strcmp(argv[args], "-Mt1") == 0) { ++args; if(args < argc) { Mt1 = strtol(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-Mt1\".\n"); exit(1); } } if(Mt1 < 1) { fprintf(stderr, "Invalid template specified at \"-Mt1\"\n"); exit(1); } printFsa_ptr = &printFsaMt1; printFsa_pair_ptr = &printFsa_pairMt1; } else if(strcmp(argv[args], "-ef") == 0) { if((args + 1) < argc && *(argv[args + 1]) != '-') { ++args; extendedFeatures = strtol(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-ef\".\n"); exit(1); } } else { extendedFeatures = 1; } } else if(strcmp(argv[args], "-vcf") == 0) { vcf = 1; if(++args < argc) { if(argv[args][0] != '-') { vcf = strtol(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-vcf\".\n"); exit(1); } } else { --args; } } } else if(strcmp(argv[args], "-xml") == 0) { xml = 1; if(++args < argc) { if(argv[args][0] == '-' && argv[args][1] == '-' && argv[args][2] == 0) { xml = 2; } else { --args; } } } else if(strcmp(argv[args], "-sam") == 0) { sam = 1; if(++args < argc) { if(argv[args][0] != '-') { sam = strtol(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-sam\".\n"); exit(1); } } else { --args; } } } else if(strcmp(argv[args], "-nc") == 0) { nc = 1; } else if(strcmp(argv[args], "-na") == 0) { nc = 2; } else if(strcmp(argv[args], "-nf") == 0) { nf = 1; } else if(strcmp(argv[args], "-cge") == 0) { scoreT = 0.75; rewards->M = 1; rewards->MM = -3; rewards->W1 = -5; rewards->U = -1; rewards->PE = 17; } else if(strcmp(argv[args], "-tmp") == 0) { tmp = 1; if(++args < argc) { if(argv[args][0] != '-') { if(argv[args][strlen(argv[args]) - 1] != '/') { fprintf(stderr, "Invalid output directory specified.\n"); exit(1); } tmpF(argv[args]); tmp = 0; } else { --args; } } } else if(strcmp(argv[args], "-spltDB") == 0) { spltDB = 1; } else if(strcmp(argv[args], "-status") == 0) { kmaPipe = &kmaPipeFork; } else if(strcmp(argv[args], "-verbose") == 0) { if(++args < argc && argv[args][0] != '-') { verbose = strtol(argv[args], &exeBasic, 10); if(*exeBasic != 0) { fprintf(stderr, "Invalid argument at \"-verbose\".\n"); exit(1); } } else { verbose = 1; --args; } } else if(strcmp(argv[args], "-mint2") == 0) { /* equivalent to: -1t1, -mem_mode, -ca, -cge, -mq 1, -ref_fsa 2, -dense, -bcg, -bcd 10, -bc 0.9 -vcf -ef */ kmerScan = &save_kmers; one2one = 1; mem_mode = 1; alignLoadPtr = &alignLoad_fly_mem; ankerPtr = &ankerAndClean_MEM; chainSeedsPtr = &chainSeeds_circular; scoreT = 0.75; rewards->M = 1; rewards->MM = -3; rewards->W1 = -5; rewards->U = -1; rewards->PE = 17; mq = 1; ref_fsa = 2; alnToMatPtr = alnToMatDense; baseCall = &orgBaseCaller; bcd = 10; significantBase = &significantAndSupport; significantAndSupport(0, 0, 0.9); vcf = 1; extendedFeatures = 1; } else if(strcmp(argv[args], "-mint3") == 0) { /* equivalent to: -1t1, -mem_mode, -ca, -mq 1, -ref_fsa, -dense, -bcNano, -bcd 10, -bc 0.7, -vcf -ef */ kmerScan = &save_kmers; one2one = 1; mem_mode = 1; alignLoadPtr = &alignLoad_fly_mem; ankerPtr = &ankerAndClean_MEM; chainSeedsPtr = &chainSeeds_circular; mq = 1; ref_fsa = 2; alnToMatPtr = alnToMatDense; baseCall = &nanoCaller; bcd = 10; significantBase = &significantAndSupport; significantAndSupport(0, 0, 0.7); vcf = 1; extendedFeatures = 1; } else if(strcmp(argv[args], "-v") == 0) { fprintf(stdout, "KMA-%s\n", KMA_VERSION); exit(0); } else if(strcmp(argv[args], "-c") == 0) { fprintf(stdout, "Philip T.L.C. Clausen, Frank M. Aarestrup & Ole Lund, \"Rapid and precise alignment of raw reads against redundant databases with KMA\", BMC Bioinformatics, 2018;19:307.\n"); exit(0); } else if(strcmp(argv[args], "-h") == 0) { helpMessage(0); } else { fprintf(stderr, " Invalid option:\t%s\n", argv[args]); fprintf(stderr, " Printing help message:\n"); helpMessage(1); } ++args; } preseed(0, 0, exhaustive); trimSeedsPtr(0, ts); if(sam && kmaPipe != &kmaPipeThread) { fprintf(stderr, "\"-sam\" and \"-status\" cannot coincide.\n"); kmaPipe = &kmaPipeThread; } if(spltDB || targetNum != 1) { printPtr = &print_ankers_spltDB; if(deConPrintPtr != &deConPrint) { deConPrintPtr = printPtr; } kmerScan = &save_kmers; one2one = 1; } if(get_kmers_for_pair_ptr == &get_kmers_for_pair_count) { if(one2one) { kmerScan = &save_kmers_count; } } if(ref_fsa == 1) { if(baseCall == nanoCaller) { baseCall = &refNanoCaller; } else { baseCall = &refCaller; } } if(outputfilename == 0 || templatefilename == 0) { fprintf(stderr, " Too few arguments handed\n"); fprintf(stderr, " Printing help message:\n"); helpMessage(1); } else if(tmp) { /* set tmp files */ tmpF(outputfilename); } if(fileCounter == 0 && fileCounter_PE == 0 && fileCounter_INT == 0) { inputfiles = smalloc(sizeof(char*)); inputfiles[0] = "--"; fileCounter = 1; } /* set scoring matrix */ rewards->MM = (Ts + Tv - 1) / 2; /* avg. of transition and transversion, rounded down */ d = smalloc(5 * sizeof(int *) + 25 * sizeof(int)); *d = (int *) (d + 5); i = 0; while(i < 4) { j = 4; d[i][j] = rewards->Mn; while(j--) { d[i][j] = Tv; } d[i][(i - 2) < 0 ? (i + 2) : (i - 2)] = Ts; d[i][i] = rewards->M; j = i++; d[i] = d[j] + 5; } i = 5; while(i--) { d[4][i] = rewards->Mn; } d[4][4] = 0; rewards->d = (int **) d; if(spltDB && targetNum != 1) { /* allocate space for commands */ escape = 0; size = argc + strlen(outputfilename) + 32; for(args = 0; args < argc; ++args) { if(*argv[args] == '-') { escape = 0; } else if(escape) { size += 2; } size += strlen(argv[args]); if(strncmp(argv[args], "-i", 2) == 0) { escape = 1; } } exeBasic = smalloc(size); fprintf(stderr, "# Map\n"); for(i = 0; i < targetNum; ++i) { to2Bit = exeBasic; *to2Bit = 0; args = -1; while(++args < argc) { if(strcmp(argv[args], "-t_db") == 0) { escape = 1; while(escape && ++args < argc) { if(*argv[args] == '-') { escape = 0; } } --args; } else { if(*argv[args] == '-') { escape = 0; } if(escape) { *to2Bit = '\"'; ++to2Bit; } exe_len = strlen(argv[args]); strcpy(to2Bit, argv[args]); to2Bit += exe_len; if(escape) { *to2Bit = '\"'; ++to2Bit; } *to2Bit = ' '; ++to2Bit; if(strncmp(argv[args], "-i", 2) == 0) { escape = 1; } } } fprintf(stdout, "%s-t_db %s -s2 > %s.%d &\n", exeBasic, templatefilenames[i], outputfilename, i); } fprintf(stderr, "# Reduce:\n"); to2Bit = exeBasic; *to2Bit = 0; args = -1; while(++args < argc) { if(strcmp(argv[args], "-spltDB") != 0) { if(*argv[args] == '-') { escape = 0; } if(escape) { *to2Bit = '\"'; ++to2Bit; } exe_len = strlen(argv[args]); strcpy(to2Bit, argv[args]); to2Bit += exe_len; if(escape) { *to2Bit = '\"'; ++to2Bit; } *to2Bit = ' '; ++to2Bit; if(strncmp(argv[args], "-i", 2) == 0) { escape = 1; } } } fprintf(stdout, "%s\n", exeBasic); return 0; } templatefilename = *templatefilenames; ioStream = stdout; anker_rc(0, 0, one2one, 0, 0, 0); anker_rc_comp(0, 0, (unsigned char *)(&one2one), 0, 0, 0, 0, 0); } else { if(strcmp(*argv, "-s1") == 0) { step1 = 1; } else if(strcmp(*argv, "-s2") == 0) { step2 = 1; } ioStream = (FILE *) argv[1]; } if(step1) { t0 = clock(); /* set to2Bit conversion */ to2Bit = smalloc(384); /* 128 * 3 = 384 -> OS independent */ for(i = 0; i < 384; ++i) { to2Bit[i] = 8; } to2Bit += 128; to2Bit['\n'] = 16; to2Bit['A'] = 0; to2Bit['C'] = 1; to2Bit['G'] = 2; to2Bit['T'] = 3; to2Bit['N'] = 4; to2Bit['a'] = 0; to2Bit['c'] = 1; to2Bit['g'] = 2; to2Bit['t'] = 3; to2Bit['n'] = 4; to2Bit['R'] = 0; to2Bit['Y'] = 1; to2Bit['S'] = 2; to2Bit['W'] = 3; to2Bit['K'] = 2; to2Bit['M'] = 0; to2Bit['B'] = 1; to2Bit['D'] = 0; to2Bit['H'] = 3; to2Bit['V'] = 2; to2Bit['X'] = 4; to2Bit['r'] = 0; to2Bit['y'] = 1; to2Bit['s'] = 2; to2Bit['w'] = 3; to2Bit['k'] = 2; to2Bit['m'] = 0; to2Bit['b'] = 1; to2Bit['d'] = 0; to2Bit['h'] = 3; to2Bit['v'] = 2; to2Bit['x'] = 4; to2Bit['U'] = 3; to2Bit['u'] = 3; if(sparse_run) { templates = smalloc(sizeof(HashMapKMA)); exe_len = strlen(templatefilename); myTemplatefilename = smalloc(exe_len + 64); strcpy(myTemplatefilename, templatefilename); if(deConPrintPtr == deConPrint) { strcat(myTemplatefilename, ".decon.comp.b"); } else { strcat(myTemplatefilename, ".comp.b"); } templatefile = sfopen(myTemplatefilename, "rb" ); loadPrefix(templates, templatefile); fclose(templatefile); myTemplatefilename[exe_len] = 0; kmersize = templates->kmersize; if(templates->prefix_len) { templates->mask = 0; templates->mask = (~templates->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (templates->prefix_len << 1)); } /* merge reads */ if(fileCounter_PE > 0) { inputfiles = realloc(inputfiles, (fileCounter + fileCounter_PE) * sizeof(char *)); if(!inputfiles) { ERROR(); } for(i = 0; i < fileCounter_PE; ++i, ++fileCounter) { inputfiles[fileCounter] = inputfiles_PE[i]; } free(inputfiles_PE); fprintf(stderr, "Paired end information is not considered in Sparse mode.\n"); } if(fileCounter_INT > 0) { inputfiles = realloc(inputfiles, (fileCounter + fileCounter_INT) * sizeof(char *)); if(!inputfiles) { ERROR(); } for(i = 0; i < fileCounter_INT; ++i, ++fileCounter) { inputfiles[fileCounter] = inputfiles_INT[i]; } free(inputfiles_INT); fprintf(stderr, "Interleaved information is not considered in Sparse mode.\n"); } run_input_sparse(templates, inputfiles, fileCounter, minPhred, minQ, fiveClip, threeClip, kmersize, to2Bit, prob, ioStream); hashMapKMA_destroy(templates); free(myTemplatefilename); } else { if(Mt1) { myTemplatefilename = smalloc(strlen(templatefilename) + 64); strcpy(myTemplatefilename, templatefilename); strcat(myTemplatefilename, ".length.b"); templatefile = sfopen(myTemplatefilename, "rb"); fseek(templatefile, (Mt1 + 1) * sizeof(int), SEEK_CUR); sfread(&qseq.len, sizeof(int), 1, templatefile); fclose(templatefile); printFsaMt1(0, &qseq, 0, ioStream); printFsa_pairMt1(0, &qseq, 0, 0, 0, ioStream); } else { myTemplatefilename = 0; } totFrags = 0; /* SE */ if(fileCounter > 0) { totFrags += run_input(inputfiles, fileCounter, minPhred, minQ, fiveClip, threeClip, minlen, maxlen, to2Bit, prob, ioStream); } /* PE */ if(fileCounter_PE > 0) { totFrags += run_input_PE(inputfiles_PE, fileCounter_PE, minPhred, minQ, fiveClip, threeClip, minlen, to2Bit, prob, ioStream); } /* INT */ if(fileCounter_INT > 0) { totFrags += run_input_INT(inputfiles_INT, fileCounter_INT, minPhred, minQ, fiveClip, threeClip, minlen, to2Bit, prob, ioStream); } status |= errno; if(Mt1) { Mt1 = -1; sfwrite(&Mt1, sizeof(int), 1, ioStream); free(myTemplatefilename); } } free((to2Bit - 128)); if(kmaPipe == &kmaPipeFork) { t1 = clock(); fprintf(stderr, "#\n# Total time used for converting query: %.2f s.\n#\n", difftime(t1, t0) / 1000000); } else { fprintf(stderr, "#\n# Query converted\n#\n"); } } else if(Mt1) { myTemplatefilename = smalloc(strlen(templatefilename) + 64); strcpy(myTemplatefilename, templatefilename); runKMA_Mt1(myTemplatefilename, outputfilename, strjoin(argv, argc), kmersize, minlen, rewards, ID_t, mq, scoreT, mrc, evalue, support, bcd, Mt1, ref_fsa, print_matrix, vcf, xml, sam, nc, nf, thread_num); free(myTemplatefilename); fprintf(stderr, "# Closing files\n"); } else if(step2) { myTemplatefilename = smalloc(strlen(templatefilename) + 64); strcpy(myTemplatefilename, templatefilename); status |= save_kmers_batch(myTemplatefilename, "-s1", shm, thread_num, exhaustive, rewards, ioStream, sam, minlen, scoreT, coverT); free(myTemplatefilename); } else if(sparse_run) { myTemplatefilename = smalloc(strlen(templatefilename) + 64); strcpy(myTemplatefilename, templatefilename); status |= save_kmers_sparse_batch(myTemplatefilename, outputfilename, "-s1", ID_t, evalue, ss, shm); free(myTemplatefilename); fprintf(stderr, "# Closing files\n"); } else { exeBasic = strjoin(argv, argc); myTemplatefilename = smalloc(strlen(templatefilename) + 64); strcpy(myTemplatefilename, templatefilename); if(spltDB == 0 && targetNum != 1) { status |= runKMA_spltDB(templatefilenames, targetNum, outputfilename, argc, argv, ConClave, kmersize, minlen, rewards, extendedFeatures, ID_t, mq, scoreT, mrc, evalue, support, bcd, ref_fsa, print_matrix, print_all, vcf, xml, sam, nc, nf, shm, thread_num, verbose); } else if(mem_mode) { status |= runKMA_MEM(myTemplatefilename, outputfilename, exeBasic, ConClave, kmersize, minlen, rewards, extendedFeatures, ID_t, mq, scoreT, mrc, evalue, support, bcd, ref_fsa, print_matrix, print_all, vcf, xml, sam, nc, nf, shm, thread_num, verbose); } else { status |= runKMA(myTemplatefilename, outputfilename, exeBasic, ConClave, kmersize, minlen, rewards, extendedFeatures, ID_t, mq, scoreT, mrc, evalue, support, bcd, ref_fsa, print_matrix, print_all, vcf, xml, sam, nc, nf, shm, thread_num, verbose); } free(myTemplatefilename); fprintf(stderr, "# Closing files\n"); } fflush(stderr); fflush(stdout); status |= errno; if(status < 0) { status = 1; } return status; } genomicepidemiology-kma-091b8ffe66ac/update.h0000644000175000017500000000157614157033525020555 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ unsigned convertLength_014to015(char *filename); int hashMapKMA_014to015(char *filename, unsigned prefix); int index_014to015(char *filename); int update_main(int argc, char *argv[]); genomicepidemiology-kma-091b8ffe66ac/xml.h0000644000175000017500000000304714157033525020066 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include void initXML(FILE *out, const char *templatefilename, const unsigned totFrags, int argc, char **argv); void capXML(FILE *out); FILE * openInitXML(const char *filename, const char *templatefilename, const unsigned totFrags, int argc, char **argv); void closeCapXML(FILE *out); void newIterXML(FILE *out, const int template, const int t_len, const char *template_name); double getEntropy(const unsigned char *aligned_assem_q, const int len); void capIterXML(FILE *out, const int DB_size, const long unsigned seqsize, const int t_len, const int readCounts, const double p_value, const long read_score, const unsigned char *aligned_assem_q, const int len); void hitXML(FILE *out, const int template, const unsigned char *template_name, const Aln *aligned, const AlnScore *alnStat, const Penalties *rewards, const int flag); genomicepidemiology-kma-091b8ffe66ac/ef.h0000644000175000017500000000213114157033525017651 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "assembly.h" void initExtendedFeatures(FILE *out, char *templatefilename, unsigned totFrags, char *cmd); void getExtendedFeatures(Assem *aligned_assem, AssemInfo *matrix, long unsigned *seq, int t_len, int thread_num); void printExtendedFeatures(char *template_name, Assem *aligned_assem, unsigned fragmentCount, unsigned readCount, FILE *outfile); genomicepidemiology-kma-091b8ffe66ac/assembly.h0000644000175000017500000000755314157033525021113 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "chain.h" #include "filebuff.h" #include "hashmapcci.h" #include "nw.h" #include "qseqs.h" #ifndef ASSEMBLY typedef struct assem Assem; typedef struct assembly Assembly; typedef struct assemInfo AssemInfo; typedef struct assemble_thread Assemble_thread; struct assem { unsigned char *t; /* template */ char *s; /* score */ unsigned char *q; /* query */ long unsigned depth; long unsigned depthVar; long unsigned score; long unsigned snpSum; long unsigned insertSum; long unsigned deletionSum; unsigned cover; unsigned len; unsigned aln_len; unsigned size; unsigned fragmentCountAln; unsigned readCountAln; unsigned nucHighVar; unsigned maxDepth; double var; }; struct assembly { short unsigned counts[6]; unsigned next; }; struct assemInfo { int len; int size; struct assembly *assmb; }; struct assemble_thread { pthread_t id; int num; int template; int file_count; int spin; int mq; int minlen; int bcd; int sam; int ef; int t_len; int seq_in; int kmersize; int thread_num; double scoreT; double mrc; double evalue; char *template_name; FILE **files; FILE *xml_out; FileBuff *frag_out; Assem *aligned_assem; Aln *aligned, *gap_align; Qseqs *qseq, *header; AssemInfo *matrix; AlnPoints *points; NWmat *NWmatrices; HashMapCCI *template_index; Assemble_thread *next; }; #define ASSEMBLY 1 #endif extern void * (*assembly_KMA_Ptr)(void *); extern int (*significantBase)(int, int, double); extern unsigned char (*baseCall)(unsigned char, unsigned char, int, int, double, Assembly*); extern void (*alnToMatPtr)(AssemInfo *, Assem *, Aln *, AlnScore, int, int); void updateMatrix(FileBuff *dest, char *template_name, long unsigned *template_seq, AssemInfo *matrix, int t_len); int significantNuc(int X, int Y, double evalue); int significantAnd90Nuc(int X, int Y, double evalue); int significantAndSupport(int X, int Y, double evalue); unsigned char baseCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls); unsigned char orgBaseCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls); unsigned char refCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls); unsigned char nanoCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls); unsigned char refNanoCaller(unsigned char bestNuc, unsigned char tNuc, int bestScore, int depthUpdate, double evalue, Assembly *calls); void * assemble_KMA_threaded(void *arg); void * assemble_KMA_dense_threaded(void *arg); void * skip_assemble_KMA(void *arg); void alnToMat(AssemInfo *matrix, Assem *aligned_assem, Aln *aligned, AlnScore alnStat, int t_len, int flag); void alnToMatDense(AssemInfo *matrix, Assem *aligned_assem, Aln *aligned, AlnScore alnStat, int t_len, int flag); void callConsensus(AssemInfo *matrix, Assem *aligned_assem, long unsigned *seq, int t_len, int bcd, double evalue, int thread_num); void fixVarOverflow(Assem *aligned_assem, Assembly *assembly, int t_len, int thread_num); void * assemble_KMA(void *arg); genomicepidemiology-kma-091b8ffe66ac/filebuff.h0000644000175000017500000000326114157033525021046 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #ifndef FILEBUFF typedef struct fileBuff FileBuff; struct fileBuff { int bytes; int buffSize; unsigned char *buffer; unsigned char *inBuffer; unsigned char *next; FILE *file; z_stream *strm; int z_err; }; #define FILEBUFF 1 #define CHUNK 1048576 #define GZIP_ENCODING 16 #define ENABLE_ZLIB_GZIP 32 #endif /* pointer to load buffer from a regular or gz file stream */ extern int (*buffFileBuff)(FileBuff *); int BuffgzFileBuff(FileBuff *dest); void init_gzFile(FileBuff *inputfile); FileBuff * setFileBuff(int buffSize); void openFileBuff(FileBuff *dest, char *filename, char *mode); void closeFileBuff(FileBuff *dest); void gzcloseFileBuff(FileBuff *dest); void destroyFileBuff(FileBuff *dest); int buff_FileBuff(FileBuff *dest); z_stream * strm_init(); FileBuff * gzInitFileBuff(int size); void resetGzFileBuff(FileBuff *dest, int size); void writeGzFileBuff(FileBuff *dest); void closeGzFileBuff(FileBuff *dest); void destroyGzFileBuff(FileBuff *dest); genomicepidemiology-kma-091b8ffe66ac/kmapipe.c0000644000175000017500000001331614157033525020707 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "kma.h" #include "kmapipe.h" #include "pherror.h" #include "threader.h" #ifdef _WIN32 #include #else #include #include #include #endif FILE * (*kmaPipe)(const char*, const char*, FILE*, int*) = &kmaPipeThread; void * pipeThreader(void *arg) { char *cmd[2]; Pid *pidPtr = arg; cmd[0] = pidPtr->cmd; cmd[1] = (char *) pidPtr->ioStream; /* start child work */ kma_main(0, cmd); /* close stream */ fclose(pidPtr->ioStream); return NULL; } FILE * kmaPipeThread(const char *cmd, const char *type, FILE *ioStream, int *status) { /* kmaPipe is a combination of popen and pclose, but allows for binary mode */ static volatile int Lock = 0; static Pid *pidlist = 0; volatile int *lock = &Lock; int pdes[2]; pthread_t id; Pid *src, *last, *dest; if(cmd && type) { /* check mode */ if((*type != 'r' && *type != 'w') || (type[1] != 0 && type[2] != 0)) { errno = EINVAL; ERROR(); } /* create pipe */ dest = malloc(sizeof(Pid)); if(!dest) { ERROR(); } else if(pipe(pdes) != 0) { ERROR(); } dest->cmd = (char *) cmd; /* convert pipe */ if (*type == 'r') { dest->fp = fdopen(pdes[0], type); dest->ioStream = fdopen(pdes[1], "wb"); } else { dest->fp = fdopen(pdes[1], type); dest->ioStream = fdopen(pdes[0], "rb"); } if(!dest->fp || !dest->ioStream) { ERROR(); } /* spawn process */ if((errno = pthread_create(&dest->id, NULL, &pipeThreader, dest))) { ERROR(); } /* Link into list of file descriptors. */ lock(lock); dest->next = pidlist; pidlist = dest; unlock(lock); return dest->fp; } else { *status = 0; /* Get file pointer. */ lock(lock); for (last = 0, src = pidlist; src->fp != ioStream; last = src, src = src->next) { if(!src) { *status = 1; return 0; } } unlock(lock); /* close stream and get exit status */ *status = 0; id = src->id; //if((errno = pthread_join(id, NULL))) { if((errno = pthread_join(id, (void *) &status))) { ERROR(); } fclose(ioStream); /* Remove the entry from the linked list. */ lock(lock); for (last = 0, src = pidlist; src->id != id; last = src, src = src->next) { if(!src) { *status = 1; return 0; } } if (!last) { pidlist = src->next; } else { last->next = src->next; } unlock(lock); free(src); return 0; } } FILE * kmaPipeFork(const char *cmd, const char *type, FILE *ioStream, int *status) { /* kmaPipe is a combination of popen and pclose, but allows for binary mode */ static volatile int Lock = 0; static Pid *pidlist = 0; volatile int *lock = &Lock; int exit_status, pdes[2]; char *argv[2]; pid_t id; volatile pid_t pid; Pid *src, *last, *dest; if(cmd && type) { /* check mode */ if((*type != 'r' && *type != 'w') || (type[1] != 0 && type[2] != 0)) { errno = EINVAL; ERROR(); } /* create pipe */ dest = malloc(sizeof(Pid)); if(!dest) { ERROR(); } else if(pipe(pdes) != 0) { ERROR(); } dest->cmd = (char *) cmd; /* spawn process */ pid = fork(); if(pid < 0) { ERROR(); } else if(pid == 0) { errno = 0; lock(lock); for(src = pidlist; src; src = src->next) { close(fileno(src->fp)); } unlock(lock); if(*type == 'r') { close(pdes[0]); dest->ioStream = fdopen(pdes[1], "wb"); } else { close(pdes[1]); dest->ioStream = fdopen(pdes[0], "rb"); } if(!dest->ioStream) { ERROR(); } /* start child work */ argv[0] = dest->cmd; argv[1] = (char *) dest->ioStream; exit_status = kma_main(0, argv); /* close stream */ fclose(dest->ioStream); /* kill child */ _exit(exit_status); } else if(*type == 'r') { close(pdes[1]); dest->fp = fdopen(pdes[0], type); } else { close(pdes[0]); dest->fp = fdopen(pdes[1], type); } if(!dest->fp) { ERROR(); } /* Link into list of file descriptors. */ lock(lock); dest->pid = pid; dest->next = pidlist; pidlist = dest; unlock(lock); return dest->fp; } else { *status = 0; /* Get file pointer. */ lock(lock); for (last = 0, src = pidlist; src->fp != ioStream; last = src, src = src->next) { if(!src) { *status = 1; unlock(lock); return 0; } } unlock(lock); /* close stream and get exit status */ *status = 0; #ifndef _WIN32 while ((pid = waitpid(src->pid, status, 0)) == -1 && errno == EINTR) { usleep(100); } if(WIFEXITED(*status)) { exit_status = WEXITSTATUS(*status); *status = exit_status; } else { *status = 1; } #else WaitForSingleObject(src->pid, INFINITE); #endif fclose(ioStream); /* Remove the entry from the linked list. */ lock(lock); id = src->pid; for (last = 0, src = pidlist; src->pid != id; last = src, src = src->next) { if(!src) { *status = 1; return 0; } } if (!last) { pidlist = src->next; } else { last->next = src->next; } unlock(lock); free(src); return 0; } } genomicepidemiology-kma-091b8ffe66ac/seqmenttree.h0000644000175000017500000000300114157033525021610 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 //cc -Wall -O3 -std=c99 -c -o seqmenttree seqmenttree.c #ifndef SEQMENTTREE #define SEQMENTTREE 1 typedef struct seqmentTree SeqmentTree; typedef struct seqmentTrees SeqmentTrees; struct seqmentTree { unsigned n; unsigned size; struct seqmentTrees *root; }; struct seqmentTrees { unsigned start; unsigned end; unsigned covered; struct seqmentTrees *branch[2]; }; #endif SeqmentTree * initializeSeqmentTree(long unsigned size); SeqmentTree * initSeqmentTree(SeqmentTree *src, const unsigned start, const unsigned end); void reallocSeqmentTree(SeqmentTree *src); unsigned addSeqmentTrees(SeqmentTrees *root, SeqmentTrees *node); int growSeqmentTree(SeqmentTree *src, const unsigned start, const unsigned end); unsigned queSeqmentTree(SeqmentTrees *src, const unsigned start, const unsigned end); genomicepidemiology-kma-091b8ffe66ac/performanceAndComparisonCMDs.tar.gz0000644000175000017500000102465614157033525025744 0ustar nileshnilesh‹xžZì½ízב-|þz_F9I¶Hàwç™JÙ®q&¶'öÎLæ8~ô@$$1¦Hš¤¬8gr/çZÞ+{{×Zµ{7~I²ãd¤Ä  »÷G­ªU«ªçÇûÏžÏξÑO?<ø¿~?ãñxgkkäÿnãßñtÿòÏh²1ÝÜÙÜÙ(O6Ç“Éÿmý0Ãþyq~1;ë†rzq´¿Åçº=yrÅûœGý÷ïäÏãÁþ?žä“<~z4»˜¯Ÿ½™k\³ÿ“éÖdaÿw&ãnÿÇoæòWÿù¾ÿ?û§‡/ÎÏ>><~x:?;­½LéÅù|t~qv¸ñ~J?½8Ÿ=ÿ¢ûá|öüâääè|t~rv1zwýñìùè¿GÍàÕ§óã“çóý“ïFk‡å­ó‹ƒÃãîëKf•ÒóïGÿûÙ|v0?}0º{÷}¡úÁh¼>ƯóÓ‹gÍ ÿrxüä¤ûýÞýnX‡OîÌŸÏî•Ïu?uoýòËüá'ŸýêþýÑÿMïì?;y~Š·ÞOïÄÑç§G‡÷îŒî<À[ÝÉÞé‡ò¿Ë§¾]^Äp&£5¾ºÙ½ú×ôòÙáÑü ^»›H\t4ÿ6VÅOò—à½×äëÑ»Í`Þùëh~ÔíUùèéÙáñEwòÏ“{w~~þÇ‹Ÿ?ñÿŽËÕp־Ƹ´÷GåÚe–¿ËPV¯C]ˆõñ`)êð¸Cïüµ[ׯèŸÿ¹F·ªw`SwºÑý­òúgÑÿw¿}ÊßÖ/þ|ñF®ÑùÃíÍÍËüÿdss‚ø¿±¹3ÝØØtÿ¿±ýÖÿÿ~¶ø§óóÎ.fן¤åw»·?:ß6ï¢Ã³ÃÙhÿäèpt>ÿöEg8óóÑËÃÎ\<›žœ¼<<~:šíwoœžŽ_<"¿=»¸8=ÿÅÇ/_¾\?Þ|¸~|ô|ýøðÙúӓÍÖËÊì?ýô·_æÑìèh~Ô­Æ““³ÑGë¾D+OüÑñÅüìäñ¬sá_—€ðuDÿòúËÙÙËÃýoÖgûë/¾Á º1Ì/ùÀÿ÷ÿº£¿_ðî“ÝÑofÇ/fgߦãÉî×>ÄÜmÎóó‹‹=èvÚ¯_v{4ëÆ8»¸˜uÛÛýr>ºS?¸þdÖÙÿr9»8|r¸8;u~úS¹X}ZŸö~÷¹‹îŒne•žœ>úð×£{q­ûFó?Ï÷_Ô -ètv6{>ï¦|ŽEî"ëáQyƒ'JO÷÷GkŸoŒÖNê¹ùïú~9bÒáññéè¼;æh>š`ä)>¼v8Z˜i9ÕÉ‹‹Ó›œÎϺ!Ö<ÀhgÇ£ÃãóyG‰Îÿ2<é–{ëf'­•s޶Æ)­ÀÚÏFÿö©¬Æ`9ÝŸËtW‹ÕîÆ³b º}œÿyÖQ¯yúæùì‘xÉ êKå ÅPû³táüdtþlVæÿ|þüäì{?Ûù³ç£µ‹G‡Ç^̾™÷dz/Xx><Áhö¤ÛÓ΀»¸ä\£µƒyGDO¾/'ýtvzêåé¬[î 7’³ùù“á|Ë©ÊôËúžûÄÿ°þäÛõ§iÖ¯/_Ï1ë6xmr1Yy®Gï¾êÙVÌãÊÁßâ‚LÃKŽÖº¥~ôüä`¾Ú¼¾üâË<}7^Ÿ¬ï®¶³/:×Þý¹{í’ <ÜZŸŽ×§Ýo³ãÙþÉñÁlúps½#€M~𰜰ó>÷N:/x|r1zyrö ÀrÒmÛÙè»Ì]H8¿ßõøäåÅá|úpº>]ßì~/ÞuíñQg”þÒt{tï £8=þ~¤®ýëáE9pÿ`íÙáEwõínô¯Š‰rž£Žtoƒª;“¯uæwXítŸÜ—Õ?è쯖ßZïR¡nëཎ¿+®¢\Ìß垎:|ퟗüµG'º_ÖO¿­­qxžtyÇŠSïu)×^똹ni°kÝ%†G¯—KS.[®ÞQíyçÏ¿+W/¿t¶å#¸·0ù2:^¨Ä“å«ï6Ë¥Îç/Nc³±WéüìübŠYºÉ?*‰ç²k\žEË_;:yê³æHW)"^wØ|tzv²??xÑE¤ÃóÎsœ"*• í›1„¢ÓÇe_žÍº«w¹ÈóÙ÷plç]FÒ}îûó²jû9<æé‹ÇDTGv–‚Í2×ÁÃÕòNëM8ˆø}zÍ Êpʰ®ÔÏFŸÑ^¸[îâò—®»¶v6/^a¾4‚r¥«æ†&przQ<ÎèÎÚÚóÃãGH]Ç%§õß»üs~6{:/iîÑËÎCÌ:¢ö Âgóãâ펾ÿKñ.ÅXf= *ÓÙöújû©=ï\~ç\¦ë;·ö°_Î:Wº³>Ùjëd½üªKñ‘Û÷í^ª>¯Ø· 4®Xø¯ÿSÖ>ýèÓâ¶KÔí}e™ÍéìâY7ßÎNŽ;œœÿÙúÂó²çÏN^u¸£Š§œÃcð´Î±übt'&ú¨UÒÇ;mÐ[‚D=æËÖOFkÿ>Z}–ÑÚ£5M‹'BÆ]îÐ*Ú+.!à5®X-µ»æŸ–a²<Œ•öÀ}(1ûz•I,ÄÀ.‰x©³¼±èŠËÏ/Û‹rTG–Ü÷p½ÿ»›}U¿;œ¿­}ùx´Öżáì‹4Ø^n™9/#¨aíô²Q\ê¥ÞܸæëÈicP§Ýõç£_Žî=}qü—ÃÓÎóß#|h ÿ»ßå—+>>½ìãÿ=êøÝ?^Üíþ:¾ës¹b)ÖºÜfª%ÿ>½(9i̺›å4ïÑhôæ¦>{ýÙ¯† )Èw$œ?q…µÇ/;—¹8…A¦ôÙI·N1Š—xåBÒ¨¡Žºmê6z~øôÙEqÇÇóyºsÝ›¯?-áíâóéî’YÏ»v6÷“Ö+ìwY+Ø O[ÍúÕ.‚ ·öç6Çùý’K¾}^ÅK.7YfÓ”áU0â‰Y“~³a«ÈCÇ-»Á¸©nÿ†ú<.°Ö˜é­ÂF†ÙŸGçͱ?Pà¸þ‚o,F âaJïE‹Òqv¢ÕÚg£¯&ãñøý"•?_;¥êœØWãõ­÷ ±üú5†ßÞÏ[N8^ß½ítV˜W=:¸äë˜Ø2#õWe¿Fñs%q)2QQ„ªV_üöÅìèðâûÑìqÇÑË?M»ÿ6ºå\X€nµ?mŽÖ¾|jÔ¬D>¼ŠYPzmsi"¿êÏ9½¸d.]ºYÖë"löû³×ŸÝ“ÂKì)®ÖfGÏ»D³#³{ë“KŠÐYz]ߨ1ºð¤ É>­ý;k³;Lä:—0{|4?èÉÇÐ-ãñÅP« c˜ gí¤"‹G®$ý-/ëU6£×¸ºþ7ÝžN§¨ÿM··ÇãÉh<Ùê~~[ÿû1þ<|wôïÏ:¾ž×»®ë#=š½8Ÿ—ÒQ)íŒÎ'Ó­Ýñ¿œ_¼8˜_¬\¼X?øfôîÔ¾›Fzrúý™“Ñ{û÷ýˆqFžêÁ(Ï÷ŸîwÁó÷LJ®ýv¯#"΋饑t~ÓOR„¹óùÙw󃎋Ž~{¸??.•©"‹ûÓ@â£ÿ€’<š®G÷Êîð­Ò30úþä…ëvEƒ.]-ÏÏ]±Íÿì»ó}¥žtt8;ÞoœϱžFÿÅ3œ<¾˜u.ÏÓïC!áÇF³ÎAŽÊèJ‘pæ]?9{úð;øÛOô£Ï¾ühmZ›n-Žæçe½¸Ý9ÁîÃűŽf/G]J0{zÖü¢4vWyvXɃί?¹x9;›§ÑÁaéÔyìµ³~•b`ÝlÛœktG¾}òåѯåËO¾|FÿùIþ×ÏŸGÿ)_|!ŸåO>úrôù#ýü³?ÉŸ|þY÷ÛÇ#ùì¿FÿöÉgvùÄ¡+øó?Ÿž•Ñ—¬¥¬_Ù°Ñ—óùàò¡­žŸÎ÷K¶ßMêøé‹¢²=-rÛ±‡ÉùÙóC/»•FG‡Ï/fë–f´žŠÝýìðxÿ¨³ÆÑ/Kø:Yö«æ¥ç³‹gÃWº>^|í¬»úðµ‹Ãçóá+ûߟ.¼tþýùÃòêùòË‹¸(¯¦ýg³³Ñ»Å°•WÚ•ºàä=A÷ð.ï]>ÏæÏKð¿8›¡°yÞÙΜŠÜüe) Ÿ¼½SÎòMé#º8;šß‹“¬&ï§wИ„×¾úæëÑ0©þïÎ üŒý›÷ï§wÞùfm­;ì›÷ÞëþnëŽßí^:›_¼8;}Sšž|üÝgNOΕÊ̽ý/_usy·¼>y0ZxeÊ6(þzú>Fø`Ô|âO»×Ò;å×Á”&¥©¼=xuÊ^)|üƒÑ¸Ì Ÿê)½ZþÚ/GctPqkïOzÇ'zZzÈ|d÷ýz£÷ÚcËu:»½wØ}ªyùýÑáèWÝ•º×Öpîn4ïâtø†bÊþz÷Ûñ~·Ùåíå­~ê>—…¯Ã:,]Tݰ|T¾Mí»…ÿîäðÕìóù·4žè¢Âoßvo<ùÍ¿=*î¯# 88<+¢nýÀþÉ‹ã þvø¾^êƒÑÇŸüö£2‘™‹|2¾ä8­¯s»¨-7õOJŽö>v<®]Nƒ‹¿[Èo÷..Ñ¿ëÐ ½óîhxL·úwžRFúÕèN·Gƒùt¿ß)«òá¯Ë[1¯òªÓ¾’1Ýñ³.ÿ™ŒÛßha÷ë Û+?8w'ë¸4Èçå?Ù¿wç ò~7žíû£w}©Ožøöݧ!/žéƒÑg¿ÿío±ÀOØ?×9®ùY·3w>ÿüÓ?ßñ½.‹¿¸çéV?í×»YºŸŸc~~Я̃тqÄ–Óöçê¦wÚå0Ç˧ygi×Ìàãò‘ý“³³NßñÇ‹ŸŸ{OàðÜËS,©ÿ4í‹Þbñž;¼@iÁd‡øb£Ã÷Þ •ã 8º;О,-V7®ùùãЯ\Nù'œòOÝ)ËźŸâœ«Ïðóýîðr¹¯þôõýôÊOþñø½ØÅW¾ÐÝOî^w‘;÷ÃÙîœÏ›÷ïàØ§Ùa‘¥ß¯Y½ÜA·GìßÄ^õþ£[ìÞú®k3°pIà‚ØÂÙmT½äþѼ#/Nq½ŽÕÜ[Þú%÷¨¸¦¿·wßûaߣ?ÿ@®ozµë›ýÛ»oÔÁ ORz¤oàrwW¹Ü…3M^ýLKsóaaz…ˆ¬¸ÒtîÝÅ.ñïE:¼‘‡¿äÄ“KO<}•бl+ÌãµMf±*Ta±­šÏO.ýüäëÕÑíÒ-¾~{oùº+\üêbv¶Yœ×}FÂêУ»¢àõá» A&"ärðÀbýËÚäá„ ~u”ºì §Š{f@üëåë#âk\Š!ñÊË &zäymÖÀuúù¯Ó+S‡f׳‡Ååz­Ë]Í!†KÖW4èÜÀ¸†ëx¯5Ù÷WnÓ$–têK:nMÂ.9n7S¤`Šì²3ù4kþý×÷ kœ¼¦5Nnf“×°ÆîsïVòK ëÄ~ÝÎ`&«í³ û&{ó*›s™IN^Ûú—6èšKá:—ñh:ëå×'_¿1Š=·~àÒæ›£Ùúªw&—½³âåû½:ñl~túéü¼Ü%x¯Lyþçù—Ý_œûn€ú–Ï|þâaµ~ !×ü€k>¥WvxwÛàÝ.¬Æw»ío.(½ ç£ÙE §EN+oŸ/ÐÐ~6{‰²Üzà~ùŒ—¿3ú-…]DÿãŇóó}ÿ¡üødöâè¢û¥Óçóã‹îS—_âbí°å·Ñ‡¿.¿ziîÊ£NÊÇ>GodGÈÊoŸÏË¿_|ô»ßòÅG^y|±¦òá/yß‚¯Eya2_y`ñ?~`‘Gçç/çCáñÏʾ=]}Žg~‚g'/Ï!Ë—wGÏaG×n‡³¤ÞЪFù|vxìF8;{º)a÷ów_}™Þ<àZäáñü£Gލ±oùü]fÞ]ÿ»“n£ŠQ¹°[@o«mÒ¿®\³LþZ.ÿ Ol=§­Ùb=Wsœ_¹ƒÜ½w‹!Yò㋳ûÈ»0Ûw=µþÜÿ9A«Ž„» ´„;Ù Ï‘ƒâ5÷E”®„â Ë},x½¸W8+ôaÿùÁšß2[TÙ‰rŽ÷C¿ö~éÛWUÖ.=+bªocy¿xèµÃ;÷÷á'r%ÛX:Ë;K³êNzð¢=©;|?zá£-»çêå–¿¿ƒãÑ—]6™“[Nfq;.™Ì ®\6ñ–ç¾Ï.NW.Ÿ¿ÿËþ„+–ì“ãïfGûGYšw¡îEi0À6‹:0µ[¬k±Ê[ÎŽ†|éìüý_ÞdríMa7˜cƒ [ÌðÙpzm,Æ=ÝM]êÏF1Ø“…ätqê+ý÷òJ™Kë¹QgÔemR)WÝ€¿6)vµä:“×Ë''£'ó—eh/<¤Žžu!}~PIám‡¸<Âf±ÇöÕj‘¨ã¾_þéƒÑ݇w¹‹Øì‚¢ !‹ºÉ%š]Ǫ¥iÝÐÕ^¨uB]ÔUSñ™¼ÃCšj¡_æù7Ý;‹ïìlUEº‹EvÁn e^جÖ=ô½%wÄ…¯—±nÜï&]©Öþ|¬ýB\¾ä¤ÝâOV ~×Å„+÷¢ÙŠ¿2s9ì+›Ã¬(2§ôUÉ'.w-¼þu\ÀK§ß/NùNߕݡ{ßÐFjÈa‹GÝY„EsÈ“«IƒU»F#ûìdtþbÿ™Dpq¬ÜÚdÉv‚ …å,ìâÿõE˜µf@)ò2È­Ú ¼\ëÝ‹“|xXõí^õ•Mä|!Qä%~þóóGÞbPn¬YÒa_eôí½Ý¢íýX³¾lÊ¡’‡5„=.œ Š¹ý_M®mÏ»¬ÔvÆy>¿hû•ý™/4QíÿTÝÔ%Üû“‹wª8ÒoÃdº{‰gj>üÚ^‰2Tw±F†ê‡Ó¹™âñ?«¿ç®Üõ÷òÝ÷‡¯g¼.‹¯+^·Å× ¯ëâë3¼~±øú^Ÿ-¾¾×Ÿ.¾þ¯ï/¾~Œ×ï6î Kõ5µÚ–V“Gg¦ÓM¾ÔïYÿå«OÚ¹Ág£éWý6.¹9ÞÛ.¿u°žæÛËÎQZg|p}#†Ð¿‚s½R5&ò·zR.[Îýò@Ÿ'Oçç÷ì6wÿ!\Ë3ðn*蓊ç#y›M ýî¯ Ë=|xÜñÀn°Å:>¬í1‘H£6 ü%«6£ïÑ x,ä×o켃|§’BºÈW«+à›÷ˆÅèÆR:ÂvËñå7]h?+7«ã`'Ø{ûÅ3v;а î¨Î}ôùÇewö¾þñøîRÎXÎÌEîFÀ!¼Çùß/Læœ4ŒïƒÑ4”¶, Ëw©‰â2Ë6øª9w¬'õóض~Y¹ï}ñ‡N μìÿ¨ÏrJoÜÎ~+Ø%á“Ö½)²Mõ»·ª!x²êí/·#®=oã¢ãý­;¢ÿgýöÿ/Ü<ñ†®qUÿÿÎÎÆæÎd»ïÿŸìŒÆ“íéÖÛþÿãϯf§ÏîMïÞ½¿öÉãG“GÿöñöÖt¼·›$›dÿ/›‰Z‘\þ§bê¯Kùt¿v¯Š¿‹ÿ’fͦÙ?Ô}¼aå\僦åoÍþ§{)ÇYÄË©|R¤ûIµœ´ûx…–÷ãÑrÂxË8’r¦œÔ '6N_®£#íþt§°2#N§\­{#©ŸÞ’}P˜o™’uÄ—!ûàËÛÝ*˜ß}ÀR†.w×é.–Ër æ/eYcôi–ñw æ3,«#±ì†9+&X>ï m¾¶~¡rÙ²Ú¾ü<¥JÝ:Rñab#1®2r_PKÝG|`æ‹ï“ôEñõåøaʵ*—È8:ùêtçW,¤ÏÕ¯“ýã°!ŸB9Jü“x­ŒöI+óÕˆ˜aCüD&Ô]£¬kŠsÆ|Ëá¾á~u‹‹ûƉ[H9cwšTÖ€ûê¦&]^Wó+”“¬ ‹V~.×á•ÍÍ­ÌÔ͹ ¬œLalfa@8¸|¢œ4a‘ýÒVæ“}“ÝP£VѸšX :5P}ÒCu§œÔ|£„ƒ!áÚRmÂ2/»w“éÖ‚ë\ ÜÇìF-X%‚¸—DhæÊ•µðùš>쑦O³áKÖےϹ³y·/Ú©ï øS%¿ãp@5'£+ÂòpðD+ÕÉ”E劖µIÈ öý ¿6¼ €ÉEÃÆ4³NÊ5UÎËMwá~ËÇv)ù…Šo£o¬” uj €:± Iz/î ÖÏ%#æÊ•¹.n©nL¾UFÛ`“fÑ›n&D- Y¶ÊˆMi°^Ù­Ÿ48‹SûÿÎja„˜*öÉ#­g«.W.³¡#æJpϸsᔄÀ¯‘ăré?`m+ô1ÃîMíLk5º§ÞhhÝ €6ð¢Õ•I·}Ö#t»"4ί²„Ð0"†%*¡þi«fUšã·•-Ûn— 4ü™!}Ô+||ji¨§hák\["biÉÉk,xYÄU>ÞS€vÉULìJ"F„¤`by‰iž+ˆXr€¯`b—±.fhõñÈD†Nþà#wì»Û›[[“ÄWy6“pfÂJtB„ÉXÉùµP°r5¸u ã1:F)Aõ¤}lHˆ|9–-²øÆ5»@öWùwg†=‹ ¤8Â,R9ØÈY%¼³8)Óü˜3ƒUøfñ¹Æ)ãn—ÿë2%°0†3µÐD’]´rƒý#ñª®ž(¹kY¤ð0\P$í š‰ùçzd’ó˜˜ÔM£ÅvO„  8ŒÙ }¼'ïåÌíýƒZÀMaÿÁ¾œÒè³}p%Z`-‡hctÄ ¯H{ ŽhE0)v]ì×i$&ÊK4”o°«ŒæE¿z§ Š0*!1× ±@ÙÉ›Áò ï–µçî$ßHá¯Âç¸; fW¢V9H /'•’RéÏš–\hÖñ·ãíÉ2!jØ/õ¯PÈÜ\¡ZÝÔ¬^ƒÕÔ>Àe»U.Š½Â¯Z$Ϊà§xEèÈn»Jlj¾¯tü Qnª\}Wö"{pÄo´(`PjIÛ¹I`4åê>[£dX[x}»Û[R¸D·Ãl¹-7n‡‚ü‘숃W¤F™Õ¸åØC† УpÇ5õƒÝxBÙ3Dù>høx…Khq.ÅùKè •±Í¾t6ÁšÝ¡ »FhC³)zôï7'›;“¢ ;ÇÖH#Š©¸Vç#3 Ç<›pmÆ/éXÒ(•à¢ê>[ùˆ¿ï©œñd~^=)éP]/Pƒi±3ÿ¤;<çŸ>_aâË?Ü@Å-C0|ÊçkJ b|Œ}G5aÝŒ“ñWñ—Ë«°ãòùXDÿ0¨k7'7/ø+œ%l^pYu‹ôƒq¼aØ€bæïJ×|ýTS¹/cQ·|?Þ±b\.+úQ\ßÌRA:|(Ùg©n6î}ÁC”‡ùàË ³âØÈC°‰á#=t~ß$,¤‹øjY—Lm¿˜ÚÎtg²é¦†Ñtll£zµ%£-e„n·¥RA€…*08bû1ä²3^÷#Ëø«1 Â-<|Ìö¥˜ ìØ>µÆ$4&ÎÞi Þƒ[´¥KðýÈaL8Ï`K±Fð¡‚@08Hj¡'Œ)7¶$0”v`\ɯƒ0à»kP¦aK˜6·Á·Œ;ñep È—ÛgŒаj´%Å“ãµ)??=ý(QFHÁÖaIÜ~Ò’Ѐ67Ü€2 H髲£ÅO…SWc2˜e’E_eÎNÜ»ª†+}• |•ò̾n]R]—j ‹ñ3’ .J÷½3ÚV7–¹“5¸²n‚õõ:™Òÿ»ðpAÈ–ë©S˜¢w:s„ÇêÖüð°DœÅâ ‡³àø{KÔêÖ( äX¿²Ú\x"Ö”Ž ÃhfÕ² RcоBêÌLáºü 0ñÁí&X#ËHôl0ôLu¢FÇ–Üû÷ž-+¡®ÏÆ0ça~¦Æ“Én/Dc ¢¬Ó©6þ-×W"Vâì^*Œk¹}¢LUý› À³€ÿO.îÙ•W”¢Cö’ ¬;£-MFàDÔb6V:àߤ÷oîÅèʘbXœü›Ò¿ÑßqëÃ6,¡QZdg2´*²+ç(Vý[‚c¯‘Ë"ñÍáN˜P’†VÿVnÄ_†÷¶ö '©¡¨õ𤲌!Ѥ+X4¥Wñ‘6þM°~Éò€‹mtVÔ‘üfwgg:ݪ^™ƒÄ p)¬“B¢c4)óIP5Š!en%Ö ㊗¢FîÙQuÐæÒ'ÍýT*šöw«[Ê ˆ0ÃDe ~)rø¡Z”÷8ÇžC%V½Dì¹m(’$øs« ð‡ï¦9JE)@yÒáë„æ–áJÀîX Á2ÂÁd!sp;ÀÅ‘ˆhŽºTŽKݧ‹Ež£Ô!aÉŠ-ÐÅK9ýn—|í“­Ý­i¢ÌiX`‡×ð%à ’>Áñ$º/’ÒKMÐÇx˜”·Sµ™0™|•ÉèÀdRµ™É°& y`ÙdŠ·¡ëÒÈ<‡&Cn“›@Zœ$®ŒÓ‡ÉäkMÆ­¥Ht.5™&£C“AßL†!Ór1óU&ã¤f6Ãì.ÛíLæq¤ø;4™lö&ô¡øGéÚbo/€?¼V%yˆ6XZåŠh ágt{a*VÖ^¹ãÒ–Òd¥ÌVY¾5ö¢tkÐ¥BàŒ„Z>Ô»ͱPRdn­‹TäûËÅBò«ÈK² W~ÔW(G­xÀ)s䇙ÆÊCQvÙÛË‚‹é/Þº?‹7„½´.¬ˆIªB«ìe-ªpn:òñÆÖVÇPÒ«í<6>½ÚÎcãÓ«í<6>]¾órÅÎcãÓ«í<6>½ÚÎ/—Ûí<6~9¸ vž²ªô.€±+{‰i^F‚J½ÎWòü¥/#jTØXwEHWQ ašJ¯¥ÁŒ(!g#Çåæ”\—»‹\ÜÛ‡cx>x ûÃIàÍè$r¦À§H8¡ÆD¤ ) y'Ljúr8fçY!\#ÉóË{Xð%E5 òì<94)A˜Ìr¦§²}1,Q€‚R”é\vk¹£O\@û# ÙM† ïÄBvU±Üö<È' ¤_Yæe˜ 0Ô ÝþέÉdºÍVT˜!N¦QiSš2Úc­™[)71Ԫ̸Ø%½Gý…ƽ’h(‚*´™?Ș ¥éž˜ž5$/ÂŒÞÄ…¾ÊÅW¥aF-›Bqq(g~vab²¤ÐÂBÚ†€.„Ï‹Öê•Æ„Ì<  šúªçðð ô òŸ¤Èa+‡ æÏíRJzƒM/Šüz2ÙÜÞ˜&£po¯ð)J„H%ÈóP.òiŠ—Éua¯C¼ÛOåÉ7•Ò¨º;F`üŠ..úòâÊUºÀâ'mK‘8Ö½f¿}­ Î+55NìufœÉ¤¢JÔF U)ù¢oGTTƒ~oÈî|·jA’KŠƒ=µ´í—Dì:©€W¥’F.^+`Œ\Œ8GQiiëK?«ü×îîæ8JµpðBJ¹EV+Q¬M0ƒ¨ÆîûBµÀr1Ï Z ÑUÌh‰EW_É„9€È% ÌePÌš-´@" SÒ%§ †³q/ãp×äPˆ—»¿š…ªP“ ÁrËò0Áì9€]ÆþžvÛ­ÿ^îÙõÓùKüL2+€èòÏ™w=Gðx9`Šâ1{žz¤c2å쉶ÙëÈ 3kÛ†áÿ ] _ˆê'}4J®¼_)HÑSxªHGÞ…oªp4Á ÅÓë3´2 ˜±h[ÛLØábtØî{ ¶þYlýæÞ8Ž™òg ™5£L1ŒÌQ¹XEšÎ$„‚‚cèΊ-°ªTa£&J8Ô!s1ÔæPt¢nf~0¤nhl~<] 8«Š"Ô‘ŒÜ¢ 4:’²ˆq9ªAµ^Äl9Pª(þʼn~ «¥!<QBášE)¦¢¼i-é‚BJìAãÞ«rM)×oRàFÆFo ì/»™ #›£„!R(÷ƒ{!¡T›-öƒÙ¶ â:·Þ 2\åRÒ­…è¬\}ÑØåbb2Øb–ýÇ!ÊÒ‚ók„YßáĆ€Ýu­ðA®ù)'ïWf •GpÚýkSÚòF)‰DëÉAY$Wìç4VÄ£B’f‹‘[bÅXƒð¡6ráÖdkc“G^ƒÐÅÏtg,2aÞ‰šs&re—±iþÅJŸC¼J( „â뜾NfÏj!BÌÕ?¬†Ê+\Žh€5ŒHÿ”ú6ý?Òár…¤F/ƒÝɹ×ÚPÉA%ù’‰ p–rÔ^„+nÍr[ 3¤Ã˜3Çä“ÍÂ` L}‘h„£¨º)?l•8Öo-, Ÿ2*<°A.ÓÑv±—Xqµ,…®¬š4Dȳ)Ø;å†L6g‘vf&Ì$¨Â%`ÝLlbFë)ÃP4š»h*ˆn‰ž Vj NQEw‰2Fè-µn”Èçé³Û6ˆ¦ûtf™D1B øLˆ%§ÎB¯¡Öˆê¿0ZaëS®É¹ÒçX´O÷v&;N¦ØÙì“d\… 6ǰ¬o¬W7œÅ"§¡Á¢òðá *l`±+³¾æ¶>Ÿ¦} ËÀ S°Bã€HŒébl†‚À£0È”‡‹„¸ÆÎk Ã91€PaãHÀbŒXÐŒ<FË -;À.¨~6d4«Õ¤`Ðáu!}ÓÅCèéÅ€ :FÎ&- eo©TÖ8œÈsÀ¨kk ?OiÂÕ–€±Ï »ŸÉ€ÊxA"žnÀ&♵¤¯¡‘²I‰=‚aî'd?ÖN}ŸƒÂ±ýdo]^@ü,çûÜ0í{4ÛÜ™n\ͬQVG3ùñ£™\Í Œ­Šfò¦¢™½‘h† ®Žf½—¾Y4Ëo6šér4ó3_͸z—E3#+ÿ»Œf”àK¢Yä6y)šÉR4+2àG¿O§“kåõÔŸ<¡Ô€ ­ ”y‚ò£ÊK!x¡”¿¯%”v%¡|-æŸ(A»ÈbG®'”ó‚[7ÍéòÛœîmN÷6§»$§‹á^’Ó-GAª*[Ûh‚%»ŸÉa‰™Íé°£Œ½”Þ€ñQÑÙ£´¼>ÿP ™™ïÇ —X_Rc¯²©Uƒ<8 6@s_|wLZb¡7%©E>ž+¾æÌ’2MÏ:ÊÅSÔ¯PKæBc1#ÍË¡mQK7t@gB D!Ì K›¾^’yrTRs`ÒŸK‚DÉ(ˆZ4R—ã¢Ù0o…æ ¡Äƒ§Ð)Zp ÄTÔ-ӛ ‹¹BF­#QcUÌ"œr©ã0ánh²øÓ(& SRîIù+¹cT´‘Z”Ì `†G¯E1ÇR̨͒TbïaÙ aãÿ4W^LÝë} ðJìi=0~äè°Êèaó2Jæ{ 8[®¼_uSÑ¥¶=NÊ«‰Þ4xòÐ`³µž€Ò@"’3çÊB ’fX ‚œ\¸A&ÐX¿ˆGJñ™š5âZ¼k 246ºÀ]Uvô!ŽÁ˜‰uïv'WaUn2d…¦£Dj_á4¥õ» eœ8 QX@…ØÐ€Ã"­û@B’p'@áù×î• &¼² ­ƒˆ’n@mÌWvø’ª2$átj.¤ã'x~«”Zk…H¸ ±Ô,Vx󑈂»TÇvÝ‹!Šz!£+b J]×Êî­ ¡W ¤kUÓb…H€,¨ "F Ck‹4Èw$Y´ˆg]Ö7\àpLЪ©Kj å Vå,ÌD[›ðZ¢A Å•Zƒ4­‘yk}õt6ÿ8Á-2–•BÁ•­Ò-X°Ç“`#Ëj°†¿7`ƒ·©`3J‡­¢ˆÛ•j¨[׌¨í±FûIK€hò¹Ö©©Ì@@v 6?–3Ö•`³êA3­-…)É%`Ó ¶e¬¥KÀ¦}'بµ¶XK1 #}¬.g lÆT"W¬¥l>Ü<›æ*;óÕ¥ &ò–ºÑ¢&ÀÆr©O‹5¬µ†+Ø,’r‹H‡·ˆ2a‹µÿp7žlìn±ÍX2B±ZÑE‰RÙ!•ÑsW˜&¤ºóÈüX˜\FÜ#WÃ’9{Kª¬àk]jÆ.œÌOgµq š;bh9¾ÀÀQ•àq­y‘ó\­YGƒç4Ø¿‘¡‰ƒÓÓè=8E ×Ïá›/h—ÉÑ{A«ôØàƒÂb=[NPÇN’M^ˆÉ]%]²( mÞo+dÃ= má ý¬Êª„JÜ>"‘ã:{tüitÍñ¤mŽ£LÆtØ]o9'[sHÕn)Hé )®댟îîŽ'L|0FE 5#+5ÊÖ‘tÄÏÅ* x]2·~“áÕqj¤á1jç±9ü¶ig±!'¿,NKéJ¬E\­¡ø.xVHŽpΘËÜ%Ó§°œG‹ã’à#ã¡sРw‘‘Ñ‚!‚›á„H:XD;ßàd|D…bYñ“YTõ þ°’´Š…â4f‚ÁiŽEâ@¨1ƒò£“jµ‹$Âû¸8±ˆÎžbh´ á,©¹¦°"%ñØ@N6vÄ¡—H^(Jåà[Š_ º}z± >&ܦÐÜãRÇ •Áƒ;hh¢±rÆ{®µ×KÊcÎðfÁĪ÷2ÞoÛðÚ™FÌC ÁƒbÜɸɞÑ/¸ùˆE6Aª€^<~HtˆSu:ÝÛÛÃ}¥J_ŠLÞ­¹Ÿ:—x 2© ihdÒ$?D¦§§$PвöjdƸ?SœÀ)úRàEœ¦ù‡ ò©†X)¤o÷áTp-ÿ5‘ŽIÈ„Âdi«iõf”-8XƒvÀ9‘n‰rÁƒ‚KbKvèœL”Õ•¹@x„[¥áûšðnÄœƒþJ%A íÚ#=G ¯K\¤OU2«¼DÜ<¦êDÈãÝBã=Ž‚(ñ›ò”’%™žÕûê®\ ÃwŽt‚‡!BWUÉØ¼fV}b†BÜF1¢QâcÉ>ŽøÐ>½‘H^Äâà ÒdÇųIÜDú‘)?e ºl_Ñ⊄ ´« \ˆ—âÖÖæt»Ïnûkbè²ðA9‚%^ͽlïåÑ´ßzp4¥† Ï³ˆ1@TëÅC¢Ãz?EÛŒ®^¤òL‰ŽŽx5°‰¥8‰ˆõ§ùŒõ[YˆLR¬•ú©VVâ¬pÎÁËÕ Ú f~&àöB/ çÉ;i–€(J¦×GÉTó‹sÒLsȃ±¢D¥wƒ0; ²:Iò¤ D ÏE jˆ„¸r8êˆHJèg©y]EClކ1…fe仡¤Ðâ1ó(„…L-5Š$H°³¨Çc{ª0ZíÜ̓%œÔ9| ÊÙºy5yÞ*ù0n´²c÷ÑžY ­°º¢‘’C¥ò‡¸Ã'µC>ˆ8&1lC›û3¹ Å‚‚¡ È;iHæ*QÁC÷-G$¤ôífS_ð'<,L.°z¥·DB–:„úV{rÂéÄSRèôÑÑkðH(}$TޤÚSXeY© »Q¬ÏeèïÌïÐp‘ÖŒ‘DN‚­OëÅI=ëRÜC¯o]é>³Rb 0#¤ÒPD$ gR=ògXÉÕ 3½#aÍÝ$Xë+‘%V”OpŒ_Å"&;ûôÞOî£M}„iR2Sn’0…î¹B‚/—Áœ3}?o²bQF"ͬ)oU(÷ ¥|œüºÜ>2Wò ˆ„ÿ³¶éÙªŠ5ƒKÁÕ’Ã5ää«y‹äSƒ|bÔ?úPÆ<­1ÉÁ™ÂÎ,D1ô²YȺ 1/Ë*ò™Ò¸%,Æ©a¹¤?‰;£ÖÄ<¨r5æEc@ó# !§^u­ ¹ ,O.kbä$†×Ǽ(/qõÉgK4ÒƒEòÉp¬±ÏÐm–cÞ€|êê˜ç³ic^U5#äµä%ظ,!ǃ5”ßž|2j5aÕ.­“&µç‘âyP‘| N%Á·€qú¨¨eDzh„º{$˜Rïb¨Xé¿mZ¶ü×ÖÖF÷'1ç:9 UÉÕ5ÔÃy£ ‚Sý“)žk€D3 B‚Ò®Ò‹Sïu×Ôw¡*lV$T\n•…PÆÊ>ÑŒOaŒÚ8丬}Y'ÚN#=ä=¸‰­¼Ã™kæAÇ-–>÷;ÛIVý£úNˆFç=I #.‡ÒSŸÃT]MìrufüV<ò |, GÖnªßj½=ÝÝÛņÂ!·”%p”ò=»f¦!¨RÜë$Á¯2Í4S«ô5Ÿ¦„%ƒÇ:߈@ޏ*¶æÕ$²2E©y(Jà*\Kaí%Ù¾E(l ö3„MBu‚ª¢–é+ñdˆº¾Z±å(Ø2Òe<¯@ ±,ÊDf)Ž—‚Ï@K’o·… _ůO ®3óei!òe†¿ÖsZ >Ãè eRPÅMjôˆq[›=Ñ=qãÏ0}ôáï6ÆS¶N =CÎx‚Ô*Ö÷„¥{ Úˆã¾*9õ¥>É\˜ž<·Ö<®ËñþôºmX] ®IYÔG¯åÍ„®·d¿Š°:W[Ç2Í¿ú¸Dò”ãè|!’CC¼È,a¼â ý°Q Ï ÜztÇóŽ{8Y:TÆ+|qU<=<Ê#æÄò€.nÖÆ£~¿7™nmìô¨G-_•Z0z„2Ìž:(“ós¯–¸Æuh“Μ!B6¨—ŠIÄõDšŽêŒÔg†Pÿœ¸Tv,Ì`ÄÎBx`­d"‘PèüDÌ;£þÀeÉú$"Pv×`Õ L°¢1HO©Eeʱ€]d>œMü¡°Æ#Êgu¨IcqlãÉÚû°(¢>´“Õ¨ÏàÈ÷X Ô“üPûÓê-.ù]þ/W¡ û´<^p°çã‰QIBƒ‹Ç¬ðŽ7‘ÈtüÛÄÂlÐNÌï2X!—€TàC6èËsœØ[r$:ÕkW>u(Á¨@`z0…o¸²L:¬‹O¯ Ù-‘ 0¹!0Õ•i°Sð$×E WFïeäQàØ”sðÿòÃpe,ךD¡ŒFª’r­_Åeg© NãÊX•¹ú©C‰a™Eº2J@Œ›~a51»êµèÊöýNÊÍñvsË:ÈH$&èÍ`FU%6ØVÔ¯`@JÁ/“·#šÓqC C „…IHR£Nw¿#‘ÉôÝà(Ö7HpÁS ©L…¢œ ©ÌTƒöcxöOÿô×:F^„SƒS™²Õæ¼ÁÙy_GšŠkÄ=íÂîU¡Ì‡sk‘qј$ï<ãAšÉ'¥K4ÉÛ0aŃ…þ0™nOâYR 0<”b©t2€Ò:kZñÔg%pa7‘H2v†,%IÊbÅ2emÜsÂU¯© ?äO)ö@¦rçŽV™™š•ûl¬·;ùƒü ®-ó–…ðZ‘¦öö "i5ØrÆD"%A+~CÇÜ\ [7%‡†pÅg¹Oc`Ư춰„/´°¸_`åÅ·ªÝÞ'è”ߨÚàó‘3dÆd¶5çPJ˜q³eŽA;óÁOÔÌ6%>|ƒK™½èpqøÊ$w%L¶¹ûˆüèˆ!×—Øã:i(M Ý?Ê$$ýøÄj½¶@,Àcº<S:Je†‚˜É BÝÎInöÊFP`4.Á‰ %qa`4òN ”7@H ñ!`µßRç£yÀ&œ`IÀ*Úý|ê ª{ÓÍmòI:ÒCt3?Æ9@=‘JýN>̇Fö:ZäoÞGC¡‰»š±H>°¯)ïÅi¸¥å©?¿î77›-%„IµÆRk³¥Ê-Åd{–B£kÀD‚p ý“~aBì_²Œñ6[ñjˆ4GGQP+Ç7wUvWŸX+kvÕê3õp^9ú*‘ó ¢“z‹gE1® Tx5¤ hçC\E¬ßdª¾ Ìüª¹ËûØÕ\wUa@>Vÿn? ãµ¶ô§ØÕ­…]å-;PÄ´/°Å®3\_Þî*ÓÎÅ]…FǸ€üßö‰0ŠBb‘ÀѰúž,‡8HÞž22&“ØÕˆá Z­¬z`²%C“•Òƒ#¨ÒçsW)7»ê5m°ŠÐP5#‰æ×~WYcõ]µðV¹ =0Èúe»š±«ct{.²¥o°«[¨¬5îW®v¿ˆ4pë^Ì&"…ï5?Øoë~­âÑ‚_g" V†ë!™­ È«›-ÍšÓPÁ“ p ÷ z†-¥t÷›ÃýJT…´y ’:°.‰–¡m±kƒÍ€ =¿†;ÒñÌ6¤{Üö Š‡\8$Qš¡Ÿ))­‡ÆÄL28ëe\<)˜nÉžQŸ‰ò«pjHâÃTÝÁ¹czÎtÕˆ ‘È»²ñ¦¡3‡ º Ú}ë†3ÞÜÙÚÚNpj9”FÖlê=¸^V OBX Ãh¯óOHH ³zÚ±àŸ@3ªB­à½Þ?éëû'ÃàP} þICmmý“ôþÉnäŸòmý“®ôO:ðOúCù§¡lƒj é †´1Ù˜2ûãvƒTRHRº(0U¯ÉA?*,J‡°FªÖ¤¬Ã¡ òžcí’•~ Ùc¥&ìÕÈ {û4¿-`™T2U ™»ÔRks™BCa•T2{"È\ŒoàyÔH }I¥Æ:1ºš*hJRãД"Uˆ©q¹ƒ G Nû‚¸å!©¬©BºAd9ï÷uç) 6) D ¸¼¯¹îkî÷Õ$¼Ièj ’~„[Y1¦&*3ˆ÷•ÉrÅ…}Í‘b_µÙ×Åda!”&Y Ê¬RS@´ IbÇAŸJ³¯ \ÝWaààYØ×Ê,- ìËÉ‚F ¨×¦€ý¾îÆ“bš}•+ö53 ÌWî+ƒíõ©}f¸˜Ú÷®¿¦ö¶˜Ú_†×IàöUš}Õ¥Ô ÷UÁøá….¹*µ‡ï }[t!µo÷›ÿº©ý‹~_÷z¼æ7„WY‘Üs_¯Å«.áU®Â+º$^k_/ë¾^óp_[¼jÅk^µ¯ð×áuÑc[öõ»º¯Lïí¦~ø:¼²Ø¹´¯ùvx½LŠÓ¯rY|eæ€"f#Å]»¯Ëxµ«ñª¯ô«=^u¸¯ Rœ÷uQŠ“›à5/áõe¿¯“Ê›°¯¹î+s¨¡×ð¦2ú¤õ~¤kâkÞÄÌAP VñZŸŠ×(h„ó‚WÊÙí¾êR|͵t¼i ÆaðÆé~_ÝТ´,ÆEJ)Ä«´x•%¼ éµãUWÄ×¾r ^uˆ×åæ/¾¯“Íñt:á7¼k¤V»4£ÊÝ=5edÕ¼‡T5G‹{¿Í<@j+°¡ZËJ9;9yä'ŽÇÈæy6T´‡Ì—}ȉgeQÛ¤YŬ{Œ >÷åéòuÒ(ªEõÀ„¥+‰%—Ù¿¤9þn‘xcá%Z§ $ó,å̉û„¼Çg.±V¥\èL]I˜T{Í•š%ºÚq!Ÿ š…ýüƒFªøœ½É’zÎ!ÔùørßN¡º¨ò:°=þ¸æ_Ì˜Ž¹H#T!UŒ[ᙩŸÉ”«<*è3ÊȤÍèµ2:Î j˜¨º¡k‚%‰ó_ôI˜=W4õêfsµ°$º¢°¤ê“/ |’ÀÕ1Âpi,6M.óI°.^“´gà¢6Æ~sØtwo{ìjÈ? âÒØ¤‹ Rò¸2+ÿfÚˆRøPf¸¨h·¢eè4<âBV¸¨ ‘©Ý±EǧàHaeT%àƒ2*Hy…a)CY ™!¼‡CÊb ¬CÓž ̉—‰±‹~º(œ.J«‹Ræˆa…/@/¿ö±³äó¥+ «F=–j2úÅ|† cUë]TV´,ûØ0m6@HDïeKÔŒ\·7¦ îKÛOövêp =¸šk³p$”И۴7Ÿøƒ †-Ûž°æpI¹ÏNÀÎ1 “D2ô£mÙ¯Pf}˜¼¼“±wŸ =¤|ß7¬Ã̆Œœu]Ú²MñÅ÷ˆ#0ÍýÍ'q{ »ÔØwHe°—q ïÁqãÿ*d“•-ÛŠË:а3qpËYb!Þ‡G*8*[¶©¸ùDÚŽíÄ6Ñ =±h™EÎ1ð9ÓË>ÞžlN7¶ø}rÑ\Î+”YæžÚ›ä;¶"ó9‡L˜‘¨3™$Wצû?WSò°Ï™p?;mɳ!‰™Ø Í&ƒ}i}Ö*aKAÄŒuhl±1%A_·Ki[Ê-Ñã",*k¼0¥Åqt@s¬Þ{¾½… KÔ­ÐlWÆÖàr¸¦™mÍaJºâF¦ªX E‚¶ûŸ¹X(p !åˆ ò72q%‡Ýÿ (ÆÛ ÑZŒgÖºÿ76:[²ßml쌷7¾,èY _¤&¸Â |Qk¸4|ÁýiD‡6|Eôña%äâÃð¥7 _™á+“~×𥯾òÕá+Ã×1W®á+ß$| x¬Šá íêÁ‹–—Öð¥}Ò¶*|/²›„/LÆ®_AG$›OGÛÛÞ ·dŒ_üã~¨]+Ü’U·Ô†8º%:óÆ-i ®üÔ»%“6ĵnIùY˜oáàŒ´šçÓˆƒÏm„[¾«nI›WÅÐáâ¬á–jˆËð­[äŠq?”Ö¸%2·nIÂ-!ŒéÐ-¡¬¦qr‚·? ·”#Ä!ÏtIÐ" 4n‰ˆÆ2hQº%g0nQpKðvqe^rKÍcËã+©èG¡ )œôGÃE¢ íšþ€Gt*J^ŠmÒ‘ËçÆ–S4FxM+“nÕõb(”†… ¡Ö“B&$Û‘þ(]Kc>9 ˜ÔÂmÕ$tV¸ÐØ{L •ÿg`Q`¾†à ?ÃI´öÏfj{xf ¨BpöúÛ\TeaY¤R둊'b®4ÐWÿâKÕJh>á®aÂ0¦lý0(çX2 Èü¾Œù죆°=ÝÙ™T_¤,y(S‹†<‹|ÝÀm¼v/|eR883•OxÐÊA@‘$|‘ 2* á=… ¶5€x ðû•¦ÞÁ‘,S$5­N “t­1Uº]}‘…1!%_”™`€n³Mï’hC‘ÀÔ¬õEβ ¸J½õš¡¡H¸@ù4oa%) ¼ é6xÔ¸jôuÄ! _¤¬S„1ÅÑ¥#°mx%P¤>;€~.Úb%²z;›>»7½ëχùt²AS?ÂH(Mf,äò\õ×|±Ñ}Êô7ç*Ç!>Q¡þ꣑¦‡41«È!?52Þ2¸ß&93wî}„‚ŒGig è!¥ â5"’?2 ?¾1€ ¶‘Ædú ©³0‰~vøg8­Ä $JR4è%™4ì E HØá­R/IS‘îe) ý9{F‰ûšÁi‘ü:ïtÏøÆgÖ@¬_¸HUVOs°HäZ‡à8Âu«–A.\aTf±Ž™jn %>¯Z£OÔ¿uˆ] q×D%YB¢À»b”‹ ™s{‚;gªÇ¡È‚øfÒBŸÂ¥Êõ hwgð݆eà¬Ðn…_[ A5¶í†Û‘ªs©:»v/ÅôƒïFJÐ䥜 ¤а);(ÁFJ È$utâ ¢†:Ìt> ªgÔ­@Q×­…ÃDŽH®"*¯†_--H08°„°j4nc­È·Û¢TM3÷×B`ϸ .†Æ7Hh“š@jE/9_/ƒŠÒ—OÊB\eÓCÀ+d!Ó’•¢i£D¢ÕÂWк¹È‘òÒ¼²·‹ð°> ¤' S(O׫w®Ž+FF¹Ž‹^͆ÙVSËyص9cAz{7c¢/ñ“´-#¬!QÞ£.‘-äø'7=uöß™¶D×!´&å[ž&Tê‘g°xÎ"K½‚2‰cíéL ²H†–Y=g«„°©K‘“>ch66Ô–È^ø O8Zyc.`<ÆÓ¨F"ƒ«Õ{ê£*¢dKhð¯d œI £@«‰… c‘4b]„‹¡‰±áI¤·XH²§lÍ ²Ùíù¿}:ÝÙìíñKlÜš(ýÞüy©>P£Qgå†ÏÓ¨ËìD‰ž2VV m2.)+19µŠZôäÀ‹1¶BAn¤ÃÜ#WºF> ‹pìaeKâlЦ(ª³Fº(¡Î2[mÄY ¥3ׂa à_`¦4ré@ÅÙ Ñ"q›çi u­êìíž§Šš´©«L÷¼4ÙØÛ¢EP¢m"é†b†ÁåJ·ÙOäJ8k¥‹†0œQB!ìàáV2\Òå³P…4êKp-P@sÜdéés²¨áEÎu¡‚Í$ƒŠ„»b8”´f¤ÐFh¶a¹;yµsõhI3&¦j¬„BbU~X˜&s}Éœ¡ã*Ú¢¨Œº‹Èù¯¿›nvøæCN2Yn®š àÒ7¤p,ýÖ9™ ¦†Ïùøˆa¡Éj®¨•CÌõ[Xûˆ‰ÞI'h>ž+Eä2dŒ0Sð4kˆ¢_ˆY3ÅïFä´*rJôÁ4wî”Lcº¨1Q:´ÄXüHyzœ)DÎLF›©´ErchHË`þK€÷”Ö“R.Íóš°I•®hHcE€ þ"'ø„W=šâoec!F/Šœ¼C–l8Üy1¨™øwM76Ç ‰b?›ó¬¶?B€ÉääP42û5ŠÒȈ”O:`J¢” …¸%‹8…Gr ëÃ?Œ’ÁÅ£}‚ "ów_”DªXÉbz!‚+Upd>3h~Pl‘³›Ô–Sò–üÐÔâ–Ä…ñI”ÿéhÐQ†a‘ÐÕ·lâY˜aòî‰@1ÑÐèä†}”n½)˜.EÓp—ì+tÍZ+»©÷}Þ ù¬Û˜ÁPùn×#Ük>„¼!Ê1ŠyVY¨ôCQ®q_È‹ý¼ ‚")-ƒ}8Î¥`N •¦JFb’I“iD¨â¯(± -#ÁD-âs¸hì3Åú„$Ú® ᦉX)ÚR¦ôçgÈõû*5çp8RIV4ØI8GHÕSAw1ƒYÆ û\Ip ˆn ÎÒ€}úèãßl•þÔÍÀM®ul†BDð›7a/nL-n"¤pc7Å —û-nÞâæ§Œ›G¿ùÝædsŒG0¼7oqóн7ùp³ùèÓ½­éîÎ?6jìÇC½2jò?:jì'm^5[%ÚìŽ'[Ûÿظym~ ¸ù¢]‚›4™Ï$%И÷¤,ƒæ“Ý­ÉÆô-hÞ‚æm°¹Y°) ØØÞNw¢Xtc ÕÒmE€(iYÈD õxtPT¤ÀŒÿê TÇ¢~……·Š”\ïÀnC/ãIn!=R\áäȤhEJ†ú2à 7ífHNÛ%ùÊ- E€¥Ò%5HáåŒõb E@)ç3Æ©òko€=R¤Eж@I7DŠRÚè’.GŠëº(4h®H©@Éxx,ŠE!RÌèS)R#ŒT $m*Al¹€‡]@J†´\ÑP¦+ÛØÞŒ/ÊhÌOE;»6©ÅÍ6ùZؤ7·…Mjqs[Ø,˜ÛÀæ²s#ؤ7·…Í«¹%+[ ›Ôâæ¶°I-nn ›´Œ›x¶àæÎÞOVs~eÜ\nÞâæ-näˆÙ¦?ôw¼;ötÆÐƇ¢3JøD L’;‰–&7U&>CÔ°êíñüDÐN…Fy°uœÁ·'¡9ÚQãmÔØÙ£‘È`ÊìYœ0›†Å˜²’d€¶ã€ý>Hn½ákÛQwö Óñ«!—á(a$4ÂN+j ÄÑ¢¡An%p\’3R¤Næ`Ô E‚¿ÉLl]^ªG:£±Ÿee“ç|ÊÅÉÈ…Ñw¤8{\À}œ;>ÃS³k×€Áѯï`¦Ä]A)¶ v–°8pB’¤/ˆ¿¨ÉX§Ð^Íí½Ïx5’W¤3ld1Z^NLm2NÁ îÃ|·éóqjf´åh¿#ÆÐL&ð”~Yc[¼;ió~)ck@FÊ[l;ã“j¶p§ÄÆÎÆö¤M¸dEãú6€F/ï• ‘4º4ò  ±4aqWƒF–@£è•½4y4ض›&¯½hüšõVGepô .‚Æ*hthòhìµA£šü†@ƒ}|# ÑWÍv<¢l›Š46ù G üŒ‹ßÜàB´Îòù™ãÑ!e~—Ø?[)œe‹ †s€'$!™ ”•ðK1ÁÒ7ÂÖ'㫪pq;g’ÓÊÏÐH’ø™báÌC0@ãë iø™¶ü ¨‚ÚÈ;ØB8cA?=%CØ}€ÆÍÙµ¸LKpúŒ»¦À±[¹;Šàg8µ \Lð³üŒ 1ÿBªÊÏlÈÏÀg—A3$?ƒš%•Ÿù"Ã\„3ì—Põ»ÀÏÐ×Gs _9ÎŒü,7ÂYà« gÀ@ÃîCC[YH¸žÊàkRá-,Ú‚o Â1c ø £7M>6ÂmÇá6nîà ¸q÷Úò–àf5BÀ"ܨSbæìÎàºtH›tÈ7]„Šö ¸j1áð)Q*H<½Y…›(=ܼqPB¸ù—Š .À͆pÃˆðŠ¬„›5pc nàæØŽu ÜÜäy‰n êô¡5BvPáAKöÉû¤ê¹éŠ,Ã;äê¯.§CJ£w0ØpË7f&~ÿÖj¸ÑÛѹWš{¸Á¶5à†t¢[ PŠå¬p³V§fÓ¯º²J+q¸YÀ QSàZ2xÖ š:7DyGa/&ìâ.¦ÛS~½Í[1á­˜ðfÅ„\«<Ò¢ç 1áo\呈 »åòéxs¼ƒG{½U¯ßço®ÂýèÀ¹}ç§ßõ›Íéx¼Ã¶E=ÚÍ—wì ò äúÎ{´¦s‚›YqO§o?ØCNz4¸!z¦‘þ7ÌŽÔwwš´T³#%Ð"˜7æ2gµõ“†¤€öEõ¹+°ë¦xZ»P’Pl„+ü”€d™ ’B¦¯CºÙpÂT€ãñ9q\6ÅÄÇ€Ýa¼y )Ð0x£Q¦€•„Œ’Aèƒl 7w6Mî2k†¯èF¾ïÎÈ3“-dGÂß))ÁRøsrEÉȰ‘ ¤# Vؤ„+teÜÿ—QÆîé‡-$K'2A,½§kU¥ó»‰ sPn RUdGH/3¶Y•ñìæŒ»ƒ…ºRÀ§Ð¸ ILß»S<ùûxl6r0]™ hb±AJ„=~!%’>6åFÐ+]©@€dËMJ”© ¶)öN¡d…FŒyâr™QcS›åeÙîZ¢¦D«ŠœC‹Ñ¦DZ•´ ½o( ýFCÀmá}JdK)âq«@h¦<²]ñÓÙî²”è¢M™Y—Pu« 1–‡)‘!…ºÚ®ô „£=©‹”hA¦D9æª|Jq{é6Áͼ››[{ã¿'‘OÞœÈgoE¾Ÿ˜È—‚"ŸÝPäj(òóˆ|“©ãm{{+¤ôSÔ)oo»Q¯K·Ë`?­nÔ¿ƒ¦ØÍBºuE³ÐÄ»…þkg²±5®w¨ ôTЮ8ZåqäoF‘ÞÇ .ØG{.˜¢÷-€si l€£+€ÃJ»›lØr«SÄâ PµÀ‘Eàh‡\éËpô–ÀY©SôÀÑ%àÔ|Ë€Ãô¢Ñ)VGà# THŠ+p~Â4J¸WgXòeh€C.èVs¨–u :—^§ðÜ ù#CB"PadQ§àÓYðÙt¹bwws‡ß¿Êì¸ Ú×) òêvZEIcsUˆDügËDt˜¿¾8ŸÏŠgل–9CíB5Ž¹Ñø¢Ž#¡²$ðÄäîÞ§Ñ”Z°#ßu+ ¨biL’…3è$ΚRCò œO;B8Ga¬÷uœÔx$föÈ¢‰‘Y€È/Òöà8 Û€G²ç† L7˜G[²ÄtŸG ý!²Ïv¡´„ !Ðû—R($‰º’¸m;N z’ê+“˜sf›¼¨g0qQÏà…aè¿‚’ µÃ5AFB$cæ ·$Xk¦RFÈ”¦¡·±·±³»ñÃÞ8¤78ziÄyKÕþæTíµ?õÖTmÛ¿†h{gk{w»—ÆírÙ.:VÊvUSX’í.ÑVÊvv5U[­)XM.C¶ã¸5T†…€µ¢q(ŒpISÈt<,»5Èk×Ëv×h ˲Ý*M¡‘ít(ÛµšÂ¢l Ùy°,Èv=Oèe;é5¥¦pµlw½¦ÐGT-U3‚ÆýÁ²TM!j ‚Vj ¹j ¾W”Æcôí4ÂÉ!©Z^!ÛQVì5xj ê Öj ¥sèãßln'»¯¥)¼½Ãõ*ú6¥5ÿ*áþª)ÅïÉtóíS¯~ZÀùI2¼èy ˆÔ¦`¨lp~½SW±?nOv7vÞç-pþDò#G–³n¼·9þi=Váj°´XI·K‹•t[°´XI·K‹•t[°´XIƒN¡€¥ÅJº-XZ¬Üô± ,-V®x¬Âj°´XI·K‹•t[°¬2.Yº3™L¦xÎxhnQåäwì–è«<+°bK©Ìj¬Èm°ÒA`E.Ê6X0ŒS€RÍ ä°P–A2¬ò\¹1VV>‚ä5°r“À¢KXQ`E†X¹:•¹+yEÇÏ«bEVb%³AàVXÁ.ºr°Œ•¼+¶ +Ìd~Ý!å7ŸM&{»[¸'œØ€ÔØC¼*!~‡¼Õ„å„©³2Y‹Á: #÷©ºÕùj–k¥Ð9ú¼5 yÌÃÒ…äU¼sËWP,5‹qæƒ%¢%¸Ý2IÜñ„iDVé“aâ%%£ ã}~±÷Ñ„Õ2Þœ¢µ&ÂÌš‰»Kxˆ² V&Ñ­ªÌ;!YBÊ9´8As•$e|†O‚>`èÏò’J3FùË- Cá4*æ dG'¡Ì DI©…_W€½|T¾ äãÍéd²EúÂÁœR”±F'å?«Tĺšæ_>®nµ  Š¡ÀèàgÜüoQè~pw¾„3å°Ÿw†SñH By‚/¨jé9\nø7ÃE$>CEïSšÊˆËÂÓÃc}®9Zaݼ3vzF\) ¢:UU¶Ùù58SØ‚ˆ3X2Å€G(ªàC^éDSƒwßfº ®B•ÅÚ°†ZE`Xt¦:Iÿ.Á̲ŷ~úä2¶«oQbsOލ–q†Þ“ öêƒw¦ãà¶As`l2¤Åüð=b¾¼~UË| Š7æÅ]‘ˆã"À PÇ3 o D4{Š3î:‹›ž]e…{E)´D¢dóFÔ _¼AUØ/îà×aÖF!Þ'âR¦æ4Áœªdû!î¬Þìm£¯9Wúq†!£¯ž›.±,˜¾8£¹Õ`—Ôas’Ã-ú– ¸;C_”Dªá/¹{³¨O»] Цpåqò+KhÊcdÃ!$J¢lFÉÂí‚«žhš¼_A¬šVì²AƒŽc2ŒÏ}ðçËmÑ••t›.–N¥ž€†êßyáÛînCXA ÃDÜ\Ág(Ãé% Qu‡ `À“=¾à–CjS¶‡ß{]Y ŠX?ï&HŽæŒºUªbQhöà½YjÝÉWFv‘¹)T0ÐS3®Š¯ r66Þ R‚º¾“ëÒšì~Ha¥ \¦™ëkð¤*,S%X¸:L vNSRŠÄ†ö„æßü;–·wñ`(…Õ (Ó‡'‘É ÜñÁ- ¾®[a8Ћi‡Oˆ·ˆ{ŽrEþ†‰+¿¨-“)W"‰p4øìßKÂH•Fx2¤mMx‚W•O>ƒQOth£zåG††Á †© Ó{:Ï\{¦”!JY: “ˆIaÁ„wÈàüžÀ13Ëa™a‚E-ª@‘àfaj†î ÿãGY[…ÃíC*dR6uSÉMRÄ&œÄ½‚Vf"À °î¾Iñ¨ú6²: pô°X)'[5|¨ÓD^”/Ézà<Ãc UkP¬Ä¸NÛg’ ‘Ï Mô÷‘5`>g/2H!³‚ëÃ+>¬¨©Âݧ™áÛÌTjÅÝ[Y‚a(U„WµúbqýÈI-6²ÝñŽ»å»Ÿ­õß0|àjskcoo÷íÝ?äÝru%ÿíÝ}:žiKˆZ0¥[Ü€l’,j±²hVu^…¦¢LÇéBE%,ÔáÊ»à•=3@ðƯ>sŸš%(¾X£šãõó ‹S@~Ùx{£!Ov– 3"kÊ´M˙Ɯ‘¢« *UÍ!Aï^F~‘‘øQé‰ÑyG$™º"i'é£Ô–é¨å€»:›¾…ƒ v®dÐÒÀÿÕ#+ý‹_05Œƒ¢µÏ%e¾À©@e ßq ‡¥F¡1Ÿ$UwªŽnž\|¤øÜÒÆ !&ƒ "N@mJ–˜,J7hBÜq s¼J(+°©Èà;_½Yü³ß»ÿ›­ñö„÷îKîÙwðE0ÒZPw’OöË]ÿÊ?þÌ„W)R¹€ŽýªppÌB\ÉD8MEŒõ¬I·YY¿¥–*‹¯9“h †“ÉTWD™bÒ½€®(VÃÞäHb1ae>ì*‚6Î’*•LeÊ=«]]ƼÂ^a] íB æiè34SX‹rµág•h"Á`Ö¦Hý-AÝ@xlÁøžD™(qaÑX›ýc¾á¢b÷ý´,I¡ëˆYR˜åvZ”&ȰHy õAž†ŠX³¥ 'E¹[PAa‹¤ù"`¼©„@¯‚‚•(ß¹ÓeŒ=Ry„Ê5˜|R¾íøÓ½ÝéŽgÛ!£i(5!vÂkŠB&tÔú.ã늃8)-)›«‚¦”ÿÐmuƒò7ÚÀ=×B(1`„Œˆ*Â_ŒÈ7 óQ?T#¼7 TZ? |˜ÑŸÔ¿”Cçe±RªÜà=‹ádûó\—>[*r9â9ʈ“ÂÑ÷$Ôk4Š™€_ f¥ôü$ n–ýAx¨FÖ¨ç.'Ó¯‡ºm9 ”?‹æ„\Îy ½ Šlu°Á_´nÊž‹äèugF¾[ÍT Žñ4Ðø]¿8›¬RW¶WšÔÃa³¾dÐâ#8Ü JsI¨e**´+ì>80ôwr1zHkABQRh‘ñP“ÍÉæ· êäpd ­.3ÃSL½ÌÚch‚ô žÜ`Ò$Vk568t’d(àfÜf@lhXŽf¶ØÀÿƒ6ò‚Olhƒ lD!é:‹OÙ50΋J£§^˜Ú$Qöþé lh`ñÅ0E75ªLŽØëß²«Á´•Å™PµPÉP‰hY(«ZEåŽ6Ø©´„¸ ÏtFÅ6,J—,—†ŒÄU®ËÊö?—Q¤\NUGéé$K†Ô´HŽ|‰®SX$b=Žô â Ýo€ƒØ(Ýdžª€ ò@`lw¸˜áibãí½½·’·öÃ@(ÈT0F¨©×¨39²1„VíIXÌDÔ²hüAû;õ+H˜?„öd¡bQÂ\‰ms4›Uu6³×‚ÕjÚi_ QÜɲ@BCS‰‰B°Š€ƒ”8R¬Bc3S„n®°T;SÖc<þ¯( C– ï]}»r˜¤è´ó([b¢ÚB¶D²?ÛÚÛìþ—8W¬½ ‡ÃñjfQ WBé¶¢ ´W m rS5«'£ÐÏIâàÌÏ´À ¥:Ó3;ü9Îâ¹PMç!ÄÓ>ñ?eù«JÇÚ^=kŸy;GÒÀ í—¹7ò¤DAê&p…s†ÙIH•V›ŒØçÿ-Dc!Ç ‹DÎÍ3&‹éË„ Σen¢àœÃ¬YD«n[.R©F4ƼŒt‰^Ð{àâmÁM䬣Äy[Ö½±Š ;8W‚kͼ˜IMC4–¨Þaç¢HAÑXrØ#&I<×ke‹—0¹@¶WRõ;E'ÒØ©„I£â@[ewÈZ|5Sh§ÏîMïV1¢‹™;{›;TóEBsƒ$ú\ÛåÊÃxbìm‚2ÀA*o‰0z¢—p {ÐÈœ .OD£¶h±bT$ø¥B29!y¤ô­]5è9æ]FS눆"‚…·a  3à*àx¯ÑA—b´åß=U"x1idé'‚jBH1Ó ”U efÖŽÀÀÁ’E'“E„6b7êH£‘븘f™‘fbƒê£Äž´aÌ^¨¾Eu>\â†s=ä%)x­\ èZô,0§åG,²uÊÐ$`3¥ž 9(RêœrfvJÃNµ¸é{hØFÉô%3Ö•$"‹§Óä^° &ŠHº…\‚ÐÉýÁTͽ4ëÁ4¨%"á9^¸šä`…nÐ-T÷ËSÕ¶&ñ½;5T£ðÉØHŸ!цÀ*ÕMØÐ'ൊ`¸¢CÙsïtPt£æ4¾o ^àûQÀ‚gp„º‚ QÕ6n}ÀŸI_^XOuö˜„·41ï3f§FðîáÓ”\V‚ P”É3±‚Kê(³>ˆÅå×”É#Q¯`¿&«”è&V®3¥@ÇOÓ_D‘6ÎîZß'6«‘¤ƒÂüPÑgn7Èšæ™ÙÂó²\Vk1KYZç¸$×bÁ”¨—åºüéÔ}ûvôåA© º-Pžä9Áò‡U"X%¯7–%)ë6™(‡ÁÜ>ÐñKœ»ƒ› î»½¨C> ±a¬·‡a!2JÇQ¯Šhþ/bØIjþ·tnñ@-‹a»Ho.ŠöØÈejV\Ý:#±,Cï,íüåd)üýÕÕÝ­ŸYû¡ upD%‚Bê²Õ`¨m `‚p­¦xOw/RÙ:)bá„“ó-»fa¤žî¤Þt÷¤p­•»ÜÒr±tp§Ûo*1ŒTiµ*TPðHñVP”_lq¾ª¶)åz `“0ëU“(c©Dò­m\g)/Ê2r½¦.sj1—Ö©UXI“~WÏâhI'SSS".iÏøo”,lˆú:ƒá¥#ôK-©V ÇqåÙ`8tR($ –“ã£m7¬Wñ—4¥m+W is‘_K·¯ªsI/>Mò˜h›’„}ÖöH^T q©€¡áÅ}†w« Ï\Éⵚè/ .Ü\óÅyHž3w´`Ä41ÎÂQÍÀûK0šµ ½OÖ »Î#x¶…žx =¹¢Âè)¿uù(¨k";—ÓBàÍú=Gðl®zü íHM‰ëv­¶À#ÓÆ•0Ÿ‚^î¶ûº5Üš¹·Í—3e.¢¨ýÞö˜[È™8Ýäg„Š>5=wèä.MÌ›SAŽÙgè¤ q*àCqal³½:ƒN`ÚÍÖë.¦,yôþÉ“4t´©²Ñr>úªÑ :‡Nxt?Œ”† £’ET2+$Â%…ÝÎö tNnÂ??^ßsŠš>f ¹òŒŽb†L„3èô £C°Ž‰§C’xLñ\Ò[µÝ]—©æÇ3è(¹ :‘+ñdì‚­ÔwhEhÕžéƒo C÷ :‹(cmó:CÈN<éÄ“ç‰ç‚z;¬í£ öݤNÊ~Í$Ÿîqö*ò)é¿¶[µ£'ìËÌ«äf$çc´ê-ÁÉ9GoÑzi“GÀϡljkÙ§l51Ê­ä•‘x”šE9;zj¡g{=ñ´O/™C /Y@ÿ"Ðv…Ïs@\}@Oѳ|í~†ÚBWŸ>Ýß*ó´\HÊ'Õ2’«¥.½J(|#:¼´Qí^¨ô)jC®GŽƒNgø|åøî¡><Dz51}% þf„2ž¤ûX# Ù]±†¡± B‡‹ÜY\½’â¹èÔ…8:§Mi9M:¿-Ö`úuÀÔ뀉X€ †¹‘ Àä`êËS/¦êó€ ¦Ïƒ÷ðuƒaÀä+€‰×ÓŸLcO,À,»ìÀpµõÅ€áÁh7OO$>H ÔÜÀ(†T6y0‡ý|º¢ +¡uºAÙß¶¼Yݘ ¾sâÖíA¥ràbUlŠ¥v ±ÍIn+#XAÀ‰UÎÐOÁÜ)Ó<Ì/Mˆ—£œÍî£}:&Úò.ƒo.kUå¡¶Í¿Ç܈ü-o'àØü†ú‹Õ/Á0[›Îà0.Çó´‹î´eʶG>t‹¥Ëžzb®{8cؤC+à#ÍM`‚[¨Ð7҄ݦ¹>[û^–Y±k•‹Óš_¢ÞÓ]5üÐ|$ `Þ¢ÌÙØÇÛòìJñ“r*Ã$ñ[¦âüé<¸SÆ;r#ŸûÍ¡_sz:ÿÍãÝýòÎhj’?1§DëUxŽqÎÒH8ÜGÂa Ý©0šùi¦šBr)R“ßÙšH°åšå§ÜóLigÉÒñÍÔQ ¬´OH3¤•Dr*Ì[´rHJüÒ”o˜ | yi½b&•s…´ ±¬uÆÒm!³~K•š-S (»,ûKbsc,SÿhEL֒ωÄLkª”`è‘r˜ÔjaSÖÇrÓJ esr-Mçâ¨îòU¹ôУa0×õŵÂo:f›®³U¯­%R€ž²]ƒnâÄØæ‘âq/$ð;h.Ó¬j+ÜÊü’wvv¸gÄÙé!7K¨€ #º–—$€gËäs6Éåþl'Y]qî¨ î–™r7Y‚I£x ˬ?âJÔvu×Bšý=;¹ñÌÔÞ»FüaŃ¡k]¡=\ÑZ{7˜s@\©‘¶tÜ©Œ­ */m]?w_NDš§ƒ=+ID¹V½I «$6uÙ2Þô²ÔCæöù×Éòô [ú¦Jö=mûÃòÒÒ׬ʎŽlDRÑêã—¨&S”!³E$_‚†‡Hb2V47AVÖu.3ß}Ÿ ˆö+'HPz“ó\9#¸kæiå&åßRóÔíCåµòlÛ†=Ú&;ÛƒZ0ÒØÒwwë`÷õÝÓzH`ªj<@–N}SÊúÌ£Ê 9–êõißV€sRT½ifê„!ó!õYf^nùÒNHòž4eî ¶*+¥0î)>[×£Û>Z…¥Æ€ôò¤½Õ2QUḟl‘º¯Ú…¶] «¬òµ„I…mĠϥú”’¸- ¼ Ö‚0 3u¤~¢¤Ö¡+VíÀ}pgjßO})w%é”|Ÿÿk"޵þ©÷µw‡ZÏÃÀ#B\Á5Ì ŽÙ(j q8²môAÎX@º ò¶ ¼œëZ Y Ôªì¤ÒS¬_+ ˆþkŸtXL’í¸—}Zp¯—×—§tk«,W¼ø‰¦M™¹ËÆ™è/V½ õ¿øyÂuÂñryµŽÀ„vU 'òœÀ^{æÇøÃù× “Íï¿©¥u¦eðJƒDuX,rO§œ~ELÉ3 ÊÛ8Z%}ë °ýǽ¢6ÖŒó9~Ó©´”:/R€;~ó¿&já7U +¿{² ×Ôö|ǘª× •Õ轄@’ªnú%ü¦ôqJr´öϾ© êÖ@Šð›/à73¤Å9~°|ºÒO‰ ã RŒ_à7_'x¹™éЭZÊÈ"båä‹#~moÇ®®ˆg« }’ˆýóÓÝãý<œŸszxJ©ƒŸèôÃê·èH†‚‡5°]Hš7É\Ýĉ,6 Þq;æ[óhc¨­œžaÀAÍïYÀpƒ™y‹5ì<Ȥ4“*¼'•¹‹¾&!rT2åÑßÿŽ€e“œ-J$O´d(àÃ¾Ü £,!ã=ôôí X‡sšªÐäæir÷/½s²ƒ[ gŒ*H=ERSíX¦Ú*Sìoúh–K]2LY¨óæZVG}^Œw2È Á«õCÁˆšî¦…gFø‚ ÍÅh30 ¶ ŒaÖµž„£©ªÒ¹!uîWLVï×=¬ÑfS°4¬ÂS=(»4«aol.MNá,À–‡qò-F¯ÂÐanàåqØ]g"c0TÌÓ$ã1º×Ò .étE[ú=§›™úüf¶ÇYšÃñlóºêÚ;¦‘ꉮZ¥'iá?ººýäã ê|µG8÷ʬòìõЬºµM-,­¡ T;ƒ3WÕ“76«ÐV.+õAÚÍœûë‰3££*kCÍÕ4Ñ/0kF\OœÄªt’掹Ìòfø¾]0—;mNK67å-ÅíL@euÙ\>ôé1v=6»×€SJHûŸ³­’q³'â) °p¾M§>„!Vñ¿4™8ÒK²Ü )£=h¥•¦ýG6jÈ4~± •»D·Ü<¶Â‘àš‹?Y¬Vùº¹ìĞ˱Ð%Âx2<œ0T0QkJŽJ"ËÝÔq°YF×CM2 éTn¶gž\,q¬êpÕœ,—Ƴ‘îõÙð@£çî$…"SC=®ÐÒÂ.TÞO€–:JóFá§%‘G°>Sn¸4ð7,ðïÿíþúæøý?>=|£ôµÁɘŒŸÖg.Oãyk|"“žÓFíŠY¥²˜¾4<™äËT¿R_Ä ÖI,kTÝ.Ô#3&ƒÇ40g€0²Ä¤]§2z†#4Žàñ  ÉÏЃf[‰/”B„#+Ó¬­Ü%b>´ýšVE‚[,/AámUØ—úmÓ^VQKÒâªô'E¶›ŒÎWH§¸½JÝK§Äf^œñ—\ZÏt”E¿®Ÿ8kG«E]ÐÝ(d³S›hi@ó{MH€!°4b“ªžN·µÑdƒ ƒŒ7ÝKWC–GÚusÄ k“ŸØÖÀ”<â7Ò &+”˜C¨ÒH3‚vM}*Û&€ÄÿuBį¯ožÈŠJä8+·”; IY”«Ë+ÎÞ4+HÚ »ìvOŽül*BFª­}Â$YWNÂF»H*'O² ƒà~"N)G° Ê’ªLöÜ™¸zzk[Ésh£¨:íº'1©ú-*õöžÏ¦Ö5ÉšS«+÷KXr•0›°ÚrT‚îÙ¼¬w“ˆ+õ ¸ŒÚ$LÛ¦0£˜A˜¯U¨½„)¶ù‚ÄË»2?SéŸ%#8S[C‘˜ªJìaæbÀ{Óžj=sQ‹ Zm"Ót‘ÙÜjJ9¤SžÝƒÄ[®} (ZTçBbîñÂÅèl:Ò¥µç=Âäç!ô²·‡J¤ÔéXùﯮîî($i-J€ve1©tQ¸WËÕÛT!¬–æ)žLr•ÐÕvçD(õR­è}õǦZ)¯õ¨¾zr½EÄGq¶ÙeJRAéÏ&åѬرê(o?é›Ðì{ɋѼ®5à3*EÅ@(ÙMg7Ê Ëè\¥ ©ò/[#Eøàã¶e/•1Ëý/ÓL!#fbdËBEÉ,‡Œì¢‚¹×*èvF Úù*ƒç JcÅn£r9ò7NÁ³ÐZ¦à2È8ȲI±Rrmncö²Ä!Æf[”¢N d<à¥üÀœ@ú¥G¨Æ×;”‚õ,¢ øêò ³ìú»ròþîîæ¾dêC]á;„Ú>S]šT~¦ºM¼&HV ¡có2_ %Mßj‰ÑÕ?°¿À#źšó)ŽÚj§*Yp¶×Ku•?W„{©ºT|Õ.¶ZS;¬©$C™T6UDz%›ž©.N¨„X¦ü–Ëí…ýGô~€òA¼Hˆ•‰œsQ’B%«‡z¢^Q]¾¶ª\æ ‘â–¶vª2~Ø^ ¼Yæ-V»TÙžÆV/äÍÒ£Ñ\ <OužHʃ8%}É|XWäR]rµÑUò'Sµ™ïy6Y¶ídæÑÖ™Dñ!?™½á:NŽÄ¿ÿ·˜ÖúÍÍÕýýãfIh4á¬c)-CÄ @™Ï=o¸[±|qoF‚Ì'î†m´© ަPVGÛÈZ9#PªcFÔó¨Uеhzý cSÛ:ʼóP/ ?YÅòLÃæÖµN°Yj'€±)PDa«a츖ýÖÍjò±tú44‚™©Õ?ñ?Cþk*UËûA-„·Ä¬F›Ë6Ö5^!Ól<°ªM/àg·2WÎŒãX…­%»_˜×M«É.vù¤‘ÖDhË—xâåHw}»u¸O]M§j=ŠBéðY=—‹vî¼k#±lhÇ ÞÃsŠ~ÃÀð 'ͪµÕ‘\ÿß#¿¾y¸¾º~Ø„‰Öà„j ™®-7ÔÚÅo·á†ŠZ§SXræ‰ì˜Éó~ .í“vrƒ¨LKJîÐYÞk¨È@š§Oê3ŵбV „l­9FNâÕjÚ§uìA¹|ȹÑ&(tsvrJ ¸ª^eønQˆ}±Ú,Pòᬓýî²—îKh|äÈÌv³¶’Þ‰X‡Ó¢<ý”Š¡qkiœÇ‚þ§ÎKX”†'v&®¦æ ä>˜{%Þlˆh6϶’®§å  µ$¬‘@k)\×am¶Ã ]"¯×7W·7—bu–½*)õ…ÐñÄÍ…Ðñ´„imõ*ÐÖ”(í釕üÚÀG{)•¼%øÝšñxa/)Íñ)Jrx:»ÐQ2_ö’ºm/•_’kCÚqn/ÍüÐ%xÇ`´w¡Ã5Ó²WšŠžNËĶzžô:Vi|:Þa$Й½ÄÉõ×k Šæp·éžbËàâ DùKÙ†SBWeñܲŽ'ô+WU1#83‰Ì ÛÑÏŒ†¦p÷¤eëúˆã!`[s›AÒËáÚOL9­5|kÂVþ jˆ ÒùÛ4uë‡ùÂu«Ê°ËÜsàU ëŠ3õHžmb´ýf¾&îéúîéáêðPw¹Z\²üÿÎUÿy¸Iä„á®Ý‚mB†e+2b¥c9¶0NnÇ–FÉÒJ©¥Š‰c«™\šS~̧ڱÕ{©E±ªNy#ökç—ÛKvm³ŸÂ.w«c2 ‰Í¾LJ_Sº¡„t0mUÌbõ—Gg °¶dcÛ‰ •è9Š©š(Jxw”” ÷YK¤KKµ6 SóØ«'¿š3»cëyâ´Ú§·3â|;h§ZÍ ²Ü·¼Ìêš9üöæV ³o»ýË$ìb«sAŸšOaÊrö­%ÆÃ=‚p׌-Ôú…P€¿ŽcËNÈ!² ûÍ©ïýw¼»º¾¸ÿQ`߃~; D&é ˆ/…A½ýý: êM0¨7Ã`…üaÐGáñí0˜}>‡A`Ðo‡Aü„`ðÛoPP¾¹:‰/¤—|=±ªl©N¢|aa‚fœ¶4›”Ä¥|Ý—Üa›r’sƒ[Érc¿õDtÊwd2s£[ù/§©>¤a´®äôÈÃ’7k;“Åßä}-×7v†×· ´”ú*®Fì[á„§$¤nH<®‘д˴©n>\Ú±0|aͺ€RD̆Î)[£aESöyB½£ÄöÔnk>iÚ*]'Ú-ÔÕ¯D•¨j™­$’1St¤gEô\%üT9%žh˜—MmKäÖqrºdj²97d7âNÑÝ9UAF9$Î6£.;e4LÔÒ ¹4¹Æ,eaµ•Úéž6jCe*BJ—·!d¾ÕÿøïœO¸¹\ç‹ðVGݨ8CóÚ²·Q\ë+>˜[–‡NËb"²ô[-iix¾K…S,”êñuWA©¢¢rse½™†fgrs‘ÚìÃZΠ•¯°Áûd 4[ v‹“Áó­\¦Oǘ‚˜m„k˜ì¨¨JÑ&»œœžxë¢ÒYòDZN-QÁã#\וFœ¯ª^)Ñï2–éGGz ÍÃó 6ÅK¯ «Håb™®„F‘EP2Fí5cÈ&s§­NáÜ,§¹´ 2XR "×Ã^rêÁJ“jfƒ·–ÁßônBâ$Õ¼SáD:pƒzéÙ*uºœ·R5Ìð¡L7`ÐÉÒž–g›Óÿã¿ÿ߈°›»»‡ëƒs¯9ŒÖ«Ó²·5l¯’Ç7Ï ŒV¦å²—ñ gª0âBÆj/Eî\ Éxœ8$çà@H%mâî£C$e—íô×ÊÌ“tíç¤Lú¦CÃò¨±Á2­è¹TêvŠ¡ BîÇjØ—F´Üv*ód‹¤óIpÛd_)¾É:oAb¨3§B Banzi†”ó¬œââ0ÍTž¨ÜDb¡©tȇ9'ŸÝ%†î}2Çé¶½I’ÂÊ?ëÈË%x€²ÐcxæJh†JBë;·µT«»wšh?ŽOâþP•JIñ¥WHJ°z»Õpšt‡ûüoÿö_ÿׇÿå?ü§ÿò«ÿúïã‹Ý^Ý>]ïÂ-¥1ñ››<Ãös¨À+|f^‚JXhnºk¥ßÐäÎd!T ÊfŽZ©„V4ù]«•ãÙÄŠ«kOós×hÝ ÞŠòÕM= Þ7ßGÝÒR¤^ „)42ý ˆ@nB¡æyûYh*¹°h=!UX’#p¶µ¨qÂAÈ­IV²å'|™5Р¼Ðf«ì‚ÿs±H9å—›¼âZ‡™tGÒ•U ˜Šž¢ÿ °¯~_YÅ“u:iI"ÉYËç¡wó×ßþîáöÁ2è òbœlo ”ãd{c ¼'Ûy'ÛåÅ8ÙÞ(/ÆÉöÆ@y1N¶7Ê‹q²}Y Ü~(7×WW·÷¿ü@é¿@©/ ¹ñÊÿøŸÿ~·ùÃÓÃíÓÍ8[j¦µ œ3Õü¼[û˜Mä`n’<ª4[^Іù¡„4žŠ<ÇyWY½ôS¸ëD ‘ ñ'+F5ýÑ"’%6¿R¡¬ídûW1EVXɨ 2|#ö§RjŒ‘¾ 4ééÃõ`9ZƒšÚ\ Jù‰¹°~&h‡¾…ÞWù>F¹”JwVPúJÏ÷•ý—L×xŠŸrTÓXM¸Nœm™o4*¼YB®tÖº’â‰Â¿ÔË•³ë‡Uk“5¸Ð®oZ¿) ò M÷6 J•g²ÝéñH Iµé-Ùè@ ñõ¢êê–¤°ÐJñAE€ýÌâÑB*L]HkN#Ô?&`Òm X‘Æ/“)|ÏCh¬,4Øxw'Ýüõ77O¿0å€ Uú~tû×øÝÕÍÝÏçùAè#}ä Bwß@èöæúþþú# }@èB_¡{Cèê«C¨>²Ð„~ñúõn%„&[ŠHUIâE÷2c$„¿Iæ\ÒsèåF£ ˜JÀh$¼£S Ì´I1c3 l Œð¢fa°Øé·VèöæDdáO5#èXUrœJ³KÁêW<~î˜b+©ƒ­±.û?êáÍPG­<;‰ Vj¿ÒA*¼'½uò¡¸RPÙèÒÒ-O9Jåï¨DΛ³~vØ ¯[ÓÑ]j‰hâoþ˜ž‚ÛymMsËxˆ``¤«ï”¹6[¢6Úi¿gž¨»™0CF«ÝÅ¿”¦ (¨‰žcbR=ETø«X2¤aT €B&š&4l°š¶óIs°‰ãômO/£¿?ŒP ¥Í1­Yò$ ÁÓÿÝÔ­œ\¥ÆC¡ú`¶‡‘Bîaõ»føá„°óRécûÀØÂX~ Œfñžnžî41;Åp™‡­fÄl¶zäàÄf‡ÆBºDƒy (fuJýŠ<ûÖp%#S̓NC“šz{¤æ/˜Ž(…[rxÞAóå¼ÑaÁslÓl¸j“Ïêñ§¡Üðð›/aú$<€ ÚºA§ó‡et§¥¡6M%òÿuŠ[Ë6Ó^Íê•$ô_¬×SBµ$ü$ÂkÇX朿ù«½˜j¯K×ñ¶ó™}öm¾ÍB2ߢ3Î…¢.‘jXdé´v$€v#§\'éö’2g0+ Y .ôôŒÒêÑVû¨]„wÍ;©™‚f-³ý#­ íÖ!WÞ*>í¯GêŠñä fíu€Y]sïwÊGÇÊA[UøÚ˜”æRÇ赇Uo†yÉzXšñ¯7ýÝ?ÞÝÞßÞ^ý ðSx˼}où3ÄÛ7òO·7÷7wà-Œ·æCÒ ð2Þti󬀅·xo¾¸#Þâ¼Å3¼ÞàÔè÷é=rÇ›‡®ßŽ·æÈîÞØ¬×ðæë÷ ÉÂ[½Œ·xÞêoñÞúE¼Õs¼¥ðÖ(u…ƒñÖlßWÃS&·ÿáW| |þÓÕÍíýýýÿ6ãHó¥Ñ^Ì\"ÖR)rÆ`bBù9£¾­E³C6Ã%sËÅ$%BÈÌ*&R’ožFÿÏFœöI&Z¯:…q™Y~)Ïmþ§¤7óä¼{¤`€‘¥w&dr¾vŒùsóØVa í9‰!`R»s ÙÁ6€ðbTCà‹¥<¨¹ÄQûSHÜ{a¼ÿ¨ôY YÄAå,Í}ŸcÒ[“>Éå­yæ©ff#uÁ³šë C”3Í3w§Ižô ÒÕ%8›ÙD”ªW˜p×Ý!î¹ Õ%§m˜”ÃAQBIU®0”w°É*³¬|e®((^©µ²=ºªP†ù“³¶½<:-iuéÜÜ]J¼X#žÚg M çVj&y€œŒMY4æ_JØÌ®ÌÖo½&†²U,Ÿñüÿsz@àŸŸnnžnAaQ몂Sv!ÒBµ~Š8Ïåä£g¨rœ»“ç=ÄoÔÒÊ"ð!:!5[w ¯ª\ôñ8I½¶Àç—š,op§ÔÇhй]ëb`0J<…Fr˜ SœªÂoˆ©ÒªÓ}ázøn¯¢‡àiµýW\p2Yjl=ýr"O´¹&ºåz“±‚öwb ¡š3uzT‘óÀ¬M-©3à¥R–ì#;“oØþYL’ûYA¯’&[«5!g/a–mÐZ{ó#Ö—1ÈBàÑXÚø¹Nbf01î\l)^ßRA—ávÒA¶›/cu´ŽRrÆœBBs–Ü ‘q쉞¿‹Z— lÿñ¿ü¿ÿöŸÿ%~uwó鄘y¼ùôp5bh¯³ÁvÆÔLOlü?ÎÐéç[ˆ u Æ]•‰Fm’îä?¹HCʪh9÷)˜R—£Ž0˜Ÿ¹¥2ôO€a{:Gjw1_ø´\¨K¹ä™å±—¾@F‰!áfe»ÊpÜø‘üçÑ/*ØR·J›¬˜| <ýMÊ9Tø(J›ÛGƒ¶kVÛm¥œÄ"&:p›¬¥Œ:9n¿ÕV%AÍ£GëÐé$ÃNï…ž)öf <–›Ü{k_Ó%0«Í‚©¶TwS½ïV.}ùU·‹õ}Ïé% …ñ‰Þq^’½¶4Ù~`Qí>Srˆ'UùOš@ÐûB4PóM±¼_Ë£jŸjµæœ…$×(„&Âsj~“)¨1Êë«"‰X-²•~=*UVà•ªæ’wͬk+„y`‘LÒþ@™;—é»EÒ±¢“Lµ'¢vÆês‡Ê2öÔh´2REÏ(c-WÅKɧy&>ÐoDŸ dRB]û»BqB™DÕ¦x )åù5š™· 3àTD±› í0b9¢ˆŠudº=3g ÎCâvÿ`ŽÓ žKyfý&}ãEüì7­ÿü§¬^XsýÓ²>dVÌM¹efêÞpÿGéülA¶w»8È6}¥+Da%1‰óÉsóÉŒ ÝBh Yk¡âJ± ƒ¬˜€){àb~¡‹[˜’O:ÏM[ᑱ$i¯N y¹š® §ÎF׳‘³¨ádi‡&$’Óƒ„§h„\YÞV˜œB5|Ë«qšäži¬áÞtX©ãVá%ΨSÒ"Ç/.ãR"À…uåj‹2ÏxÕf76•Hø€þÇßüáW×ÒÏ×7Ÿ®ï^¬7ñ+ªV•G*N©oOÄ3Uôë}*)“Òcèƒ^*ˆÜÈòÔnÉ º':Á‘i¬žÐSòe`’¿q †zÑ9g¦¦­]ýþîƒ{Õ]\îÈWSZv•œ«%-70Q°Ú’ªø,Ç;˂ߣc'Þò‘Ö€S£² _½&1:h•cLZŠL£Oꧦ+úò¬Ÿý§ œ7Õ í‚DzW]mv&:J„LAM°‹ˆÁ¥FÚåñ…êYê!DÚ÷éŽ;UNªúU!u ×´ìºÓ;nér0Š «¶ÅVš„ÐÓ¤ñ»–|Þ*TQ¥üºPL—†ÓNï¿á…šeCªÚ˜ßõxÔ¿Þ_Ý^Ñ ûiêMøÚ.ö.|m{_õ ¾¶ €½ _ÛÀÞ…¯í`oÄúm»ØgðUÏðµ]ì]øÚ.ö.|m{¾¶ €½ _ÛÀÞ¯ë¾þéæáþéö駇¯+a½¨Ÿ]ª÷&¬ç€úHXïJXw'@ýátºüñáP?@ÕWT|êÔýd¨O·÷w€úÉêG+©~ö€êP¨Ç‡›Ç›—{â€ú9ê#C}e@Åg•ø»_ÝŽçwýts­‡ ËüµôM %WL×Q=hyÕúnÃÐÁI\VÂhú'Mƒ8RO¾aXÈÒCГnºrýSS«ÏÉNçZs ‰Y[j¡%‹tÛx /Ó´PNo8O:œHîÔ†„~­æ¿VBx©/szÐ;v«3”0bš³Å­i…¤ó=4Ð¥À "{´hùGá™™+>•iÀÚt“S‡¾W‹I»5|¢yË´3 KæžÒ9ýáØ:XÂS.:Œ4k›î“¶&ce‚=ÿµ‹\5äšôµ6í¸Ühöšé†`z„]¥‹5±>xž³&3ÑÇ ÇtùåzÏjgøhÔ°!Ä>»¥¦ùF#ÇÜ>Kå>5—ÞfÂN ‡é ÎÌ-c] 7'S„4à—Ešóó,] ƒ1£~RˆÆÔ“1‹ƒg#hÒ&<Ì•E±Õô 'ßñ±ž•œÈ?ÝöÆDò (ÀÏŸ9‚Ô {Þ sTû‰UóÚ¥ôÈ{¨žPêþ•Og«ÔêÐØMièCoM³äôajøiƯ˜ÄÝ}‰®?üêÔ–øÇºº¿zP["EJf©ë¦~ŽÙ$-‚ÀS‡ÌéÇŒ™ž!ЖÂE–†Ôjš™¦ñn-tÊeã²5He&!Nøð­dþ9YƒSIUΔþwÄßn=b†Í*r{Ç`ÂLNSгY“-Öz<æñ ô¼×.K¬J‡Ï›Ë@Ò05Ô‹gÍ *B]G’n‚µeë^æÃ'<ù9'x¡’pè&— (24ÀdN+å§Óf)¬7ˆ ÿ7÷Œnœ›$2y÷²(t—}x³O=ÏÎvüi„¦WæŠÞej:Ã1ëÅŠ’»S“ÁZT¤·¿ Ì ?Y2͈'D¯Ý Îíi¦ïöêþëMÁãFm°Z<„°™@!=¯>õ§[Ù˜Ñòs8ؘú.i‚·×äzkžÐ«"A!T®“ ˜ Eþ[´`×RKœóp\;¦£…x©už|ÝĹî8&ÌŒî4ša&ç-‡†ÙâÖÔ¨6·Íg¶šû/lá¤OE2µ$h 'Ì%0 <,î‰ãi÷ÓןÐPª·ûôIÏù˜´ží&•AçCs ƒäBÄä[1¬ßº¶bÎ*IW4 ªŽH»PÍÌP̃Y””·S7¨ñþ}ÒHUDª8&.:µô§ß¨|Ñ(R¬­RÌ­¡!Û*>CÚ·•+&f6*ˆ y”'/Êã:V7ü’Ào'ÙÒnw¤]=½ˆ4ê×Ô„0¹¤5o=ØPíiL%èSšaHÝ•¯ÈúrØ—ñãôH£¥2_E#],|Ð`d,¤¢kÞÒuT†¾4B1"/ûiÒ¸ˆ‡ û8GZ…«HæáÎ u"ù€4rZB$ iõ:ÒÂHcü¾]„ÄæÇ&€´tN+ç44qHóì9mGÚlWí9m¤(!͵ψ‰Ê~ iaBZV¥ÿmÕÿ i¹rZ·ãeGÚp\¬œV<ô¸CûtÌiä›"‚ÄþR³mõ˜ñ§_ÿêîqÏiwk®½V kMA‹º g_d¨äæ<˜šðkOÝS¸¹¤”F¹{ºµÔ9ö,‡z®e76%° Â_DZB+E´Ž‡R©èËë!/OfÙúÄ=ø°ýT¥0™Ù5Õâ‚Ü‚)Ñ«†›JYË2ºg±çØEëao ©Â&PØ)•ØC%Ö!ßñÌ6)ëAý¥GI)$•ÐæV6¶?”´òC&³É¾£já™[‹ˆÿÔ©.o¹`ƒV*Fº˜?Ù‹æK:½!MpAÃvôé&7µBý !òd³HÁ7NÎÇlJµrÜ?s÷Oó…‚É0{!…'˜”›¶”+dã°ó9õ6R•,åV§ýZ*ÇUùª*›’ĵ#¨•;OÃbR vêµT§nëtIÛˆ›¸(>Ýe&r†j礼†ž¿VàåºÙ“¾Šƒ13C=\ÚR+|)e¹cúmÈuµgDñ=OÙã‰váJ‘StnöwgCeÚèiJ Ææ¹ßNg㤊ªµ¼•93ÉyŽöZŽM¶N„©Vêô…\\·¤ôwK^§2ƒp¶™9Îä]‹±i"s{Ùb Ãr(溱Ôö”l¹t)!»,{9†8 |G’ Ÿ¥–šœŒpÌ”–ʦ̪ùBA­ÇÆ1ÊÕšâ‰*(ä4ŽÆIqäaôÿå#`2inBÑ2ÙÊžƒî3eIæÄ޹òÍ·?is¬s„¾ÜIú‡¿ÞóGÌ÷‰ùúÛÀ|}`þ{Ä|ý,1ŸoÄ|æ×Ã< {¹F÷ ûE…ïVØõ…oUØù… »^VØ P¼Ia÷¬°û'¡°ó{QØù»ÿýW§Ñ÷øÝÍõ§ C6€lÚ!GJÏ4ós k†'·pò쀻Jyfph0irCòˆ;#—•îtâT”蔘^ÒKÜᡵ/rp×ÑTÔyÞR6J˜wµÓn°®êúwøR!ÜeɧQGDA­ŒçwÄ>UqG“OáFýàuL²ÖxÂdîq¨ß4ÛæëôÒÐóåÌ·n…S˜¯·3?½ 7-ù½†. ’ŠÒ ÁËeš›ÔiÇ=v‚Õ eÙë}ðÐ8ÌÍ1ÐSš:B¯ðtöæ,ÓXxH8÷‚—¦ÑdÐ ÁPí1qÃAm¹|–YQš"QAM•ÁÊé˜nüD=²ÒT‡~h0þÝ€q’àííÝwcl,Æ Xü[cœƒ1>Ƴ$èa)ZMÏÀxÅ& ‚„w#1*¶/FbÌþ/DâE|KO·ü"$^$Á÷!ñÄ!_ŠÄ" î@Üõoÿô«›ÓcK~óp{õtEÙ9±—êJ–$5êä:SµåЀ±4Ûº°¡£ìN T©„±*fNåI–„t¸ã¹ê©vgŒ­Õ…M9b%J# ªµ¡É—N‰L+°½~­gŸ¡jK…\³«C­ÊÉ#%*0Þè2 Dg—$=Uºd9T2´&6é_Ê^Ø‘H”mò…ï)®Bp§t 4œââ£ÓGDµŠ°v ֥ߪi% z?WñŒ3Ý9:½ñ†˜“&$¹ Ê’y=ÒJõ:4›f*ÒµÓº‡ÚÇñTêêæ]Öj|L~D©›1Qµ44aJèÁƒÁÍõKª*åN]á§+@X4˜l¥‰äÐ" ‹ìEkøŽÍåNJÁP[ÑØš°sÊ;Aïz‡Þõô~>ЋŸôâû‡^ü0ÐëzÿüÏMé÷ë««Ç»{}0~o™lº\¡^©rS6¿Ýv‡,jEiØþ”‹³ (]«F¿Ü,y+ò™fhÇpÄš2`ª½Ø.ÆkIV­Yz%š¿³é·Á#yüiI‹ôÙM þ§åËÂSÆ\úîÂ1ì S0¦|LLà í>ºFª qøeüv]³bþÈf«\WúóM¤•öÀ#ÿåøÎ'£o¹½–Ó Qˆ.pÆbßsÙŠ[./– î”ó´M‡x=Ø~£èåÔ ”= 'ÎÆÊõ]k%(³µtþBÖüÐzç«Ë”ñS³ÛtúiY&m‹G2”;œ5É×a—Ø.16šSŒÇžÁ‰âç)§½{±¤>³Ä{ìÓ”k¢î1ךÖË”øÞg6€”£Ëúi*WB{±äD 39þÃáqàªV¼`>Ma6HýÏŽR˜“^`S†÷lX£ÈÌ=ƒã’#>¦²Šx[ªlê¬)Äô§3bºû®Ää¿û"bŠŸ1õW!¦þ¾‰iYm~¦¬Öo!&O¿;1õ»ˆ©Äωi£·SŸSk¦ì]Ä„óõUˆ©ž“ÀP—ÄT_FL½ˆ‰¨21ah½‰˜òœ˜â]ÄäþWåsbŠsbŠÏS½HLyIL¡ K3¼¤ø91|‚ø×û›»›O¿dbª_1õw'¦þŠéG'¦<'¦þºŠIÄ$,þ<ˆé}Šé'HLÿôçQLõǧ맫»½q€ÃßvRZ'Ï17Z¿TïÖÝgžYJß!^úà5©¶ 1XÌŽ ùAã@‚V¯Tí‡á]ÐìEhQQ8lžè,3à›4YäÆ7/úaM÷´ää ÃǼùF+¿Ù”f±Y[V4覇Òzpó¤‹-´s…úTª¾Y ýy,ƒåŸêWuñv‚ J⽡\¨¹ÖBrQ²+¿Û1YŸ‡»Ÿ•yÀûr¾PÆÏàŽ‹Š '’eÕþ)Kƒïå7¹ÛþßËÉ[ÿ¯xñÜ9äzXï+\Iq•ßµKðÉ«»Iæ:hp’w«ü¾ÌÝ‹ýÛ½üv0îæßÎlÐÉÿ[xWš,=0|Ü$¢‡³çn=éWËP‡äÖà«XŸ%øVŸ+¿÷T¢2v¯õçž÷“wÈðDͶà.Ûr‡ÿFåvîÜ—$øØïùŸï¿ýÝÕÃí5ÏÚ³ƒ¢–¤,EUÌÎÚ¼ÂM {‚S>Q˜¼é¨ÈRãÀÆj4ÝAM,w¬çZ¼/2ë:}ëÙÄ^[ºe,¤ûˆ/ÂXÝ,c«j/Ú¡¥/«§Ç.°[Ý¥QéèWØæ=ô0¬ŸLŸ“L:äÞ«w6w•FЩF4¡Õ§šU¯q?Ø’¥^_èÄ ~è–‘˜ìîÔåAŽö€;5¨[\<`è¤æ[–V#*u3‚eIݶX³¨<ýj#j+—;0=øÖ3Æ(<á$n(Iæ¶7‰5:¿ô+I#Ü[ *Ū†7kO !õæRTž*ÖVR¢ßRj›@Á«RCJ¦j®(•û;ÃÊDÆFû›ê4ÒÊ—·«EÚ7©7Áô"ÕÐ᛽ýôOÿ¿zˆopø›?ÞÜ_ß}zÔÓÒ.…èGrä~¢ì‚¥{ÍÖ!A~%ë.­Pj,0Œ´Öl½WR³õr:fÓ*­¾ÔLõï¶t—œf߯=[¯æÀ jOÈß*t¹Ì€qp•å€èÔôc?ÐÒ$#±ÅC ‘‡ÙzX¸i!L„rÉÉÚ:˜ùyŽ<ð»ýX °ÖZQ`"¥ËfÊr1}´ŒÙz5Ù%EÊ]:2Õl}EJèfë!G5ˆz]'+5ÄH3˜ÈÄ5œ†}X(VqRÐ|SÔ{©;g3ª=[_r¸`|)+KÙdr/K”q*èþê‡®ÓˆÏØÕ¹fO+œFÎ-Y³™jÛ‡êqÑf륣 5îp>¹l‹³o*<uê¼xäm0?võéááöë2¾ ùÓdþ¢Y?4 µºß ëÇd~1 ‹FÝÛywäÝßn†üeòÏß ó€ìç€ìïš!ë{ä½$ëÝÓã§ë¿]@þÐ’µ™€Ì_p†ün’õ­€¼ù·I·WŸnï<~(ÖŸã§‘ ¿B ¹dýPx|O‚¼6o>ÝúÀ㿊`ÍŸp~ü΂õ{´t~û›ÿÌ÷ÎŒÿ§'R“Ó§Ï›2Ü¢ š%?íøÆT9 Ÿ×ÌéŠtGÌÇ"JCÒ2ç­z¾:¥Y.øF}ÈE\ K¢åÚÔYѸ¢¢J}ÃypŒ­†þ€Õ˜3@,“0B'“÷H6|§Ä*w‘|»hÑšõ€—'‚|é‰ö‘¯¯št¬wòÞQ%3ºŽœÄ Ÿ~ÈWV 4jTLÝ*cL­œÊ¨áèÖH ó >©j<'|ª€ÓVÀdÒõf8h©4“nŽ›LýÔ}a°Á¬é\1]3k¥×9öÑ0-ô·ƒˆ#j4<µŽx8l•^µ)ÚÑòÆðm0÷Ù,æôSáˆÒ†kä$ubŽÞQë>ùëÖÊOزÐjÙ@§ÞÊÒ ¹w‚ß~œìÓ'ïõæ|€ÓJÁÕ© éÒ'h¥õDÊ‚]IÈY†cœp}wõÛ‡zÏ¡Lt¿Ôm¡„‚µi©¡ÞÝá—à!LU$O†"Èé?šõN':í,I(ÔÊ–ÊÊP*?ÁO3 ~­}ˆâD”‹‘;­ž¼á—D†•ço’GmC5´«{.›—¦–{b©ž!­¤ßNcz1s£ŠX³ùdÑY“óß”9Àïôû¿ÙÈý:ÄL.®d•‚_-ø­O3Ž”|œwÛJ6$6¡¿’aÊÀŽô~΋L Hôfæp‡_¦ÎüŽl’ ”AZ)˜fßGû¥(G$D `F+­3ú ]>èB6ïq“úcŸk9}ãÖýõé{€þþÏŸnŸ®h]P°›ìåäúEIŽA)‚Пêc5ì3ÅÍ3±¢Ì†úÝX>~3/°x‚âæ Uºé)ÑÎE–Ç-`¦Ù ¥ÔÕ¬Å$1mœ‘qa”SŠyâTÈbkPóÉÓ)U9™ÇC‰Áor’ŠíÿF'ï*ÝFž'ÑY‹’ñàdžp*ÿO©N"WOAPYIb:ývóMʘìDœ 쥞HC„MçÀ{C Á0Þs1K*S‡Â&Eè5‡i:¬PUpb:¬³¼ôFf­T‚h2<{Ô¾2eq~ŠŽ¡ż2Dêðµ(’Üápu:lñ÷}{ÿ‰/ c5\Oá@AߵУA¦”iò5½“®È=ÒwÞ…Šq´x®2Û‡Á†£Nå^©P³#TÙB‹°¤²/ßJW§Àʘ•SÑö š@XI=ë¹ÌgÎË]Aa‘¥T,.~žBZô,%ço&4Ö*¹)¾‡oU@L:Pm¬Z,¦à+bb~:Dž þÂõÈIOÉzAhX[•FÖ’94\̈Ú'Q7Ò9ÃÇYLG.‚¤ö–ÿQZ‚Æ|H×˼±Ø9-:K›8Û;õ§¬)2_êvdQ°U Í%;"­u)mdü„dĤYV…’‚`%)MTNÄbÿ = “kóê)‡¢È†ŸY*§sùmß7ÿØ$÷0„jÇÏÝ|ãé°Ò§OŸ~Áé¤>ÒÉ›ÓIþí¦“»§SóûøOáœÀ£Š_ÏR° ãnÿ{/wˆBsnl4» †Šý×~·d Ñðì ê°æH¾Ï\ËAy@U0®?CÎŽ~MÕÆvðüqÒÂ% vœ#ät› «Áo™L.™qÇb Vù*6a_^DpOÚšVïJ-l,FÓw3ˆ( •Ö1[ŠÃ¶ccí 0 ù” Ó—’i¹˜𮈚jaù Z¯Ôß,Ô[êØ:]ß"½ðý‹«f o•ªƒÏ„o;>T˜‚¹l¶®pE„B[5Àß™š×â2 záëìÖ†z06A+üšêe+%Œ‡Ó3-þþOW×÷W×›wÉa¥ŠyôƒÆPØJ½'Œ´Ÿípà ïµ. ý€ç0.ä€iÒ ›~Á!Ép¨—áPoCÄ^QÌv¾ñêûCÿø "ß\Q\¡^JKD?ƒëv¨(ê},ý zÁ¡¾3ÊpˆÖ·¸jS=õ$Êù³'Š9WÓgRêaGÊýO )Nß3Rò»XQ_5qÔëHù+ê=H¹¬½_DÊ^ïý4‘ï@Ê{¤ÔíÕ£Ÿ:úpu{Vzÿ­®s»Žœ8V´p‹Ûš§œåŽÙÈ‚ô)…ÀÀu:â4>Yfw‹gKT=¶&ô¨ ùàiò¨^|²Êpˆk-ßdHFlK½ïùvòCÅ^b¦dÅ[#^ *IY&s§3Âö¼ˆÎ®‡…è^7Ï ¢%ìö\xêû™ ®Ž§¦{Šñ2¥µ…¨âÏ' ïF–@ä<écN<È»à2˜ò¢¿¼…F¦'²£×87¬ç­É\Œ4¤´̳-¶Ç,U²kîµ<Ú¦Á´©4¶]ÎÊý]³LZ2õÊÅG,qÍãåfíSèÐÆ Ì©€îž˜KñÁ„0†„|Œ$ÉÏjЙ\Óoç‹\4½±†JµžZf‚UQJ€û`{ØÁv³éÍ•9æ_85ÆÊö’ð·KÝâ qXܙָ}°\^O׉¬Æ–æŽbÐÃÈ!¤Ôn+` ‘œþƒ²VÒ,SîÁ3í§av°‚í4ÓÛ3‡lXúôJy¬4¶žÆGCr¬ª~ o"a¬˜éW†VŒ·Ó¢næ|œ.–­ÔÀEkºØx+Û Ãl,BÊX,ð›ç™hðÛHÞò¡ùLVÔY«e1Áyh-̤ȤïyƒéA³½©‘í´*ÌÊs¼ù UÞgM0 jºMjZH†‚ S”@“r®5zR*¤g’‰ÉZTçù•Ö<&Nf«@}k$z¶¨’–?ëáèy–#*à“Å‚ãD3 “«—£åèãÌãíÕ­‘vÿ4'\dßy t±½¦»¬´þ'ŸÎ÷¬Zˆ%¿3N Ú@€{RqÈ‹ƒ‘(„SãÒmm¼õàv!µðÖ oæp@μxkD‹æL8sŽ·4Þf»ÕÑo;"PœáMD0œˆÔ©"ˆ› ß”¡c&Ïf±VsKÒøo›¸Ù/Æ›ÆÌ^›¢¿‚OVæÊ•²ÕASß“[è]IJ™_¦ÀŠ8­ÞxWíoût&³éÇÔv³îñó€#D,3uf{ú!úâpúÜÅzáVÂ\ p&MJ•ÄàÊíÑÏNA¶.vÀí nŽKZ€ËsÀ­ÇŸÎ ®^œ¬¯Êc‚ã‹Ø.]$¸Jªþ ™\óE&šÿ/öfª¤àÊ Àå.( 8e¾”à8“!çUÅGr!g€‹n'(ÑF8Á1\ pÔÁ›jŒ=Áõ81—F5ÏœÇô'€KDïŠl7‡àò3€£ í•à^\ p¨Y†ÜJpaÀÅ9àN?8ÜÍÓÓ8a6ç¨UFj¶Ø¥Ähs˜*¥jߨÆ:}ZräJéŠàx`ÓµÎNÖ󓤖Qm@ù›ý3bŠ+'KðÌõXZ‚…6jþ(ËI›#(·Ã t=““p.r«<Á>mdN²Ñ~¹²œÁxRwÉIºxÉÆ0Œ `1Õ¡š¬ƒœtùvjõúáÏä^¾åd¡ÎöT?‹±ù}úyzãßU~ÚPR|7€#b—k͉z ¥·\L;ˆØv´y¹Òg©J±ÀñuåçtzÛ÷ù€6jO©Ü¢vó_¶JÐMw»Ð–Ë ‹2s$°æ¯O-ýå¦êäStã6jù7¥äk‡GŸ¨RYQÉ3qJ!8oåÝÝR¾µv«œÈ¤Cî»0OÉ[ë{gD±¢šç˜ð·á|Ø~\Òìȶ~'÷Eˆƒý‡_÷§OŸ®ïôà,Õ¢ ‘„x1j ò‘Õn³ŽA~ËÏbIK !T¹ª¯-åðÆñ¨uYÈ!gêýpM&¡* ·3°¶Zš€¬©ñÜEq†qSN¤ìN¬ª5|@’g_iò™tÏ¥&B•.Ê\!×Lñ´TœF(èýãI¯ ÃDI»Dêärµê(mY+:ÁCQZÒßÄ‹à_/pÖÕA¢·2H©›——šË,öjF¢Z$sB{Þü‘z±§M êÆÅqæz¥ÜA¥¼’ à¡^G‘„°ÕÈuµÌÄ’R¥̆[~ÐÒó¥Z¿þtÿxóéxò—ƒ˜2èæ¯ñ‡§Û§»Y²´Vñ¢Y‚‘zvz•Œ™ÄàÆL±Ü•-½N4„ªLÒ¼/ˆšð÷Ê®òn¹© CøŽÂÃkP%¯˜H£)NÉ"sSÖÎÊüAÔ¶Ÿvx²0we‘U¹°sÙÞ-©®¬ÛyxCÕáøjµh˜‡›5í)/ †¨ãqzŒ¡k´ÕòÑ_—†Rd‹sÔÜuuR2lÙËtöØ+=œ¬´H“BÇ-&¦6ÊôÒ„´CdkF€¥×.ÚàAéo¥¦%2]MMK¥*û€¥˜Éw’SªÞÔ:N÷•Zkf¸(+Þ`cÑ[#éÉ{ò‰I3¯UFR—¾”cNW…‘…øXè¿rÙ0A"ŸC^ Nq^êPá(°D )ãa´›k£’‹º´ß ˆ«7ÍêØý•уZf GŽˆÏ3…²IWb,"V[åLúx Ý—P²£'qZœ-°d€É]bÛ[ïØâ­D÷*T‰xb¢ØïÆ”D+‰¨™±u:zÞÁøcMÖþÝõãÕÓýªGRؽò-ìµ1²}UÚ¸Yqÿ*{%5y2’§¼‹½x¦æ$µ’Ér`¯ü<{mZ:aýÍìÕd°}%ýóØ«ÎÙ G¬im„Ðñ&öêÅ^›¼>Ôªgì˜ó‚½ènGú2{õÙ Š¾ÞË^›cÞ]ì5T {<2¬œÏØk;Ò×›ÙK–Àv¤¯÷²×v¤¯—Ù«Žì5bvøT·éë½ìµé+± ßÌ^Û‘¾ÎÙ+¿•½¶#}½—½¶#}}–½â9{mGúš~3UÀ ìu»³×ã·°W¼Ê^Ó àî’)D?méXno¹ùs©½¶¨]|½Î^òö[·Äר_ÆçÚ‹þe2ü¬,þ…Gâ`$ÁjöšWнÞ”K…ÿböR3_­æ³TpÁ⊥½ÎØ Ÿn±»ª¿®½ÝTîÊ´Æ( _9a/|=;wrÐ1ûB{±`Šk¤Z_Éçàh3µtd¯^ì¥úO¤C“U“5‰¿m®ÌKö"¤ØË+ÍÙDß_\õ´R3Žë:“5o³×Ÿ뻉´+î–°>Jì妤† ’âÜ—FÌ^d/ Á‹½( º˜¹Íͦ`¥3€7ô›ÔÉz‰½â‚½ Z±ªÙ'ÝÔ‘½b±W?c/;ÍJo‹½ÂìE‡€DÅ_šÛ!N/}X§m®sö*çØ«ګࢤÓ1ùúóÍýÃÃÝõG øQþJÀú(±%`Oóâϧöáý>ÊÙÖ-Y^e‚pŸ>🌜 Ñ3 /óL¨ÿØq%Å’ ´H8©KgI0Ù>ô?…Ñ‘i[<®’6W«¬Z;¦TW0‘ýl¸‡)¦j-~-Áƒè2ÑY–MMʲç]ÈÞtæÄ ƒØ’Ýäj†v:ÕTø-ZÚá]¢ŒY8˜RÁUˆ·@­i¼-uûiÇ=ÂSúÂBB”®šmÐ îr§¶ü”£š®§’b¹Zƒ^b'«µ‹ÁÉŒÙÊÓ;l!…œ°;=*`2wIWI,a<Ã÷VîÜeÒcônÇ¢õ]ô/½–$ŸØ–`’Ò¦ãÐ,­¤×TªèTÅ VŒ ·&¢wÕ#—¸ÕŠeu‘ß§ðœŸÀ³Ôt@”TùLj–Y‚‰–²3’âÕAø<Ô`mؽ,¢¬‹‚±­º ŠS;GO—f¯v ¾.¾9éEùÎf-nŒ X2i€–?@ï ÔKaÖî(h܃¼2WÈ7œj<ª?\}zxÒ£é?(êçJQù·KQõ·LQõFŠªŸ)EŒ¨ßþîúæþêúö¢¨ú%QT}PÔO¢âo˜¢¾PEõÏ…¢îN³ ¿¿½¾¾þt³}1?Õ̪ėI¨`ýü4{›‹Ÿ&pÌÞÄOyä§æÛ^á§>ðS=ç§œo7{/?• pÑ~?Á¶N§Îù©žñS¾ÂO™&GóS¿ÈO±óS.~R}–Ÿâ5~ _ÂO•ƒõ·I¨¼à§yñ—òÓiÁ>ÃOS`/ðÓ7?©Í°þ;ù©r9ÖïP9—4#sæ§¶„ꃄªÏðÓ¤¢ø)_á§<òSMñÈO‰ëùŒŸú9?ømêöXuzâòï~sûéöa= `þ3þEÍõÌïJP`î}²ëÄþ3Š*SÔ„ÖD%&ÞEÍËÇë[fвÁ­ím6ŽÆþ¶"tF… ,!…+Ôçú$3r+‡æ+j6ª¹:§¨\ÕîÜ)*]œË·•ý EõlÔ¢¨4E9ð¸šf/R”%’o§(¢;žQ”6óBB}Ž¢”Òv UGŠÊ×)*ßKQ8´GŠB¦h¤ý ¡š›Û)JáýE­T•b,ÿŠ*.Oñš4Ñš4$ê@Qu¤¨–ažq (4ŠÜiŠ‚µ ŠÊP‚N‰¢jQT]R} (¹÷ /QT™¢ú—*ŸSÔg%¢Nèé—õ°SÔÃwUQo4¢ú5噄oWQ{•÷•VQmŠºPQq¤¨ü¶*/Ÿ©¨ü_¦¢úXå}†¢Òèy‡Šz±ÊË«¼·¨¨W«¼¯FQGUo1¢^UQqTQ˯©¨ÚUTYE](®ñs*jÞùLEÅ×RQ¥*ï9E]Ty"ãw©¨×ª¼oQQßZå)Ꙋú´SÔz ­ÉW(êUåÄûoQQ„ùœŠŠÏ¨¨:WQGŠ:ª¨|£ŠÊï]EõK**¿LEIÍ-uAQý"Eõ®¢Î(êKTT=£¨¸ ¨|ƒŠÚ×òREÕ;TT¾OE™+¾'U/«¨Ø?–ëû騨|EÅ¢¨zYEž‰ów|xº}ä«=#œÿwŠê×UÔÀüPè-U‹¢yIE%'Z^TTÔ‘¢Þª¢bQ”&¡^ð¢\øÍPâ›T”)JCELŠ@QñLE1ÑË*V¯ ›ízQEAQ‰}fUŠ’vAQõ"EÅE5Ä;’`‰³¢B©àŒ¢š5;PTTÔiÎi.©Eüž&ˆ÷Ñ‹bfg©(Zq ¨xAE鿯ª(i`²F4]› =]Õµf£fîðŒ¢–äçú¥¢N·¸ Õ’º\„%íDsþ›TÔg(j¨fµŠ2k‰¢˜?". U×E±G#w\½³lVQq®¢È£óF‘ =¥y¤¨Ùô¥¢œ†¢0Äh¡-Š*­añ‚W~Z”íl$êêôeGÿøx÷x{{uáDe½¤¡~Ð2/¾K™·Ìò>'¨¯Væ}‰Y~NPñEͼoÕPï3Ë‚e^üe^½¡Ì«‹2Ï)±ß_æ}5³|/óúÍeÞ,륆Êo-óÖ€¯ÇEßc–i™w}‹úý¿ÜÝ]ÝÞß_rTêÁ$¯rÔüˆS¹éç‹£rqk›/qÔ¥ˆ*Žr[QhØAï+ ½5p°×yz"*—%åOô^ˆ¨` öy§àGõëuÞGå9GÅpTº†ØEÔ|ÂÎQyÎQˆ¥]D-Ž*¥„PѼÜr®Å"ªiÍõþ¶!Ž*!ú‚£Q}ÎQ„ëä"q âXçÕÑ-ÇÓÔ„I)튣š”ñZCO"AvÁQýR׎’üNÃ|x&^®óµê})×y™~œ<\X‡:¯uÞpjæ9Gí¥éŸûùvUç"*-¢KD½PçYè¦ÉJìQŸQ‰ˆºà(Érʷˆ¨xMDåQD]rÔÝÎQw¿˜Ž^¼¨~Å‹ºì车£ê+zQñKîèÕ¥Žú~:zoñ¢^ïè}/ª~T/êÇîè5iòëwôâBG=ó¢®ïwŽzx®£^ã¨þ2¿üMõá—ÿp~y Gýüò/ᨿ¼²~y¿Û/¿~àáj·Ÿž>=¾…£©ŸÓQñqTpÔ/¯§÷Ó×QùcrT|GÅwÔQýîáͯ¨£ÌQ'rúõoÿaÎÿæWOWO~ö·¥RÑêéM„ÍæÑ€»àüD5sàæÒ}-&­†nJ<àï{&8ð¨˜;)E$I(‰Ý±­}åí)PÖùé"Ô‡:ALØuºžõláG,}çƒûgöÞØÔévpÕM¸6y¾÷Ï42¾øi/æËzÙ *ÁÔ‚Ïþ è Ãm¾R{µ {®²Å4"ü‚ž+‡ü°%N5òNe’+ÔkÑÚBª!ÎÂáMav£Bv_Œäuñ@‹âÒ†èSÇrg›,ªi?„ŒCåŠÙ·ÚæD “|ÊA6N€QáuØ>é,§}©ùö➋ʴ»JÃA„L”ÌÖ±.8«§ £‡k—;^F^‰Å0¾l$T4Opiyëµãîfæ|®n?p÷KÄ]àî'ˆ»ÓYÏúãÍÕ̓¿Ðéw¿,Ü]ä»þÀÝ»Œ?ñ”ýøÝíõíݧkMé ©mTßMOÉ*'`ÖzâœõÆ+§rŠÒ¾ÆÌ‹Ñ;6žI&ÝeÁ·4@ µ5]lhpA왑IÔN®G—´®Ùºâ@AOÙÒëÅw{±ót›GŸàÌêÖ.ù‘ûIùMËvÖÆeÁ¬õ-×8íûÒgÒ;Alž]4èä²iLLP„Mµt‚üü–…§h„ióWäwhâÞ$¸¤o2}ärwi ½, ² g|X~>¦Ð`2 ˆÔ.n¡/£l×…%f&2R%`S+‘fg}6ö`8°©RK‘g2Ü6á<[5ñ»pÔ9q"à÷Y*b2è8⹸d·Ç|¡Ölàì^ÃøùØ/ž*åæÇsù¥oá–%u,œº¹†KÄ“óÉ)’=ýgÍ€œú¡”®ž„çž®ôÌM‘ïX-–"¦jÇGêöì;°½¶GÔnï…íµÛ{a{Díö^ØQ»½¶GÔnï…íµÛ{a{Díö^ØQ»½¶GÔnï…íµÛ{a{Díö^ØQ»½¶GÔn!kè­°=¢v{¶'ÝúÏw®?`ûÛ¶ùÛïÛÓÍŸ¯ï>ÝÉ\æXg(d O¨Q°œkÞ¹à…])‹Z(ôüMÓšiÞYºìKÍ› °^Gá)šÂ÷uÍÛ …ý’æetꜹZPHÀв^Ѽ0ÀsÍK¿!ÔŒ9C¡økiÞ:jÞ"Z.Pè¾ -´L¾’§Üa›v&½„€=2Ÿk^UQÍ«2û³(lk^À—»fÖÂ…@¤éñÌn=Ó¼qÔ¼ý" AÙQó†.«ÌËBa¿Qó&…ŸQ(µP˜aËã€Â’æ­]ó®†ÇBa\¢°Î4oÖæ¥KÔg(¼çIó·÷·Ÿd¶æø-˜OWŠl=t˜u"Ü'£ž|†DŽ6.p \­ÌÝ«B_²ÁA¤åM«LñQ¸,ôÑÆ Ù(D&;|€“T2 œö«P½«äEÒ¡öÿf(±édÈÓ{ AÓA1·ª¹w¢§Þ¡· %¾ *ŬrQªÄ— ÝL”6ÜÔînA«l“¥*È ÃÃ|Œm…P1³£¤šƒ'D'P×Ì@¬· 7 dŸú‰2w°…¸¢‚yUjŸ©çS œ¥"ÎQ^·Ä^b×™˜š­ËôÚyD„–omÖI~[(s'Ѝ&&úL¸Z~´í¡™I*“'OWºa©•†SÙÇIMïjÙ‚üäKëe,€–)vr©©“ã,úlW¡tÆ$~wu{õtwÿá}8DowˆR[m½w‘-¥Yaù7:D뺲e\fKBÈ9cØšuvh~¹²eœgK´årˆ¬£û?dwŸ;DyÈ–hÖ8׬ñíÙòsѧÁáÝÕÓÕÓq8 °­ZkÇát>ˆ‡¹p­&À‡H#fHZ0‘yCùùsíuŽCM°‡pK#'¿ùª5Îq˜/©Öjų´8TšûˆÃ~‡è ¾‘‘7¼Ä!xW­“$ýdÔká0œôæÏ¥ZSÔÓj5@¾ºíl}åFp8´²pØÆapH#!%ÚŒÃx‡u¦Zã‡ÃüJ8¬·ãð\µ>žpø¯×ŸŸžFµÖ‡jýP­¿0ÕÚ?eÕoQ­OƒÒ›»Ç«ÛÇ;[öO2[ÖWÏ–ý¥Ù²>²%ÆåËÙ²~ÆÙržúðÛ??Þ_Ý]ßœ¥Ëü)¥Ëü.é2ÿ&Òe}¤Ë_®És=s@ÿzuõxótõáò{þáò¼Áåù[žzOgòms@ó’ß\ßÞ\?‡á ­Éo…a}_0Ìo…ágZ“¿(³õÿgïM–]G’dÁ=þ%EH€à°´´ÌkùnUd½¨¶‰èÍ•®'½ïÿ_õª9Î8‡žÃsHÀánª¦6¸ÃçC9†!u£`8´4ù4ÚPþŸÿ÷ÿ“/þgÓ[òU³TTP,ôÌÍPRÐ!*UY³n¦ ]9ŠZŒZÑ#n‰ÐŒ•Ö’?îƒÈ§ô!“ üš¶QÒ<..Œá‹ø,7""6¥ZM‘,e`ëÙÑ¥L$ã´~"ÐÃ& [©ªAšÈs†Ù7 ró&"#6 c5°—Íø\i½8ž*£ÄÀ&ü>õLÄ}¬GdÂÙOÔ{Ô`±;̈ïX¬•ðïÚã×|+°Ü T)ýALÐý”ŒåÕShÁF ð††E0Ä5 §¯ô¦[í’C]?¨òF5ËÞìPïPePW ¨õ»xTÉÊ7{ÔÛ€j“€K­Ã€j“<ªœjÙzÔÕ»õ BTÿ ~ŒG•×JߦêòÛ_8áÏ]Y/¶T•È´;K,¬®›ÑPBgÆ?‡=+^- ¨0ùÔü­I'ém‹ñh”Æ9¬3Çm°g¬æ ³o,$séc¨\£€Õ“ÈŠ³ã$FËs-˜%£,Þ¬šñ( | ÿn}5BD¿ ƒ¡æ«P5Bv ñEEA+êÎ*¤eR¸E‹Š8±b¦îüÂk´ÆhŒÑ‘G½?µv`²hBá¨AKý³J5ÉQã–aöVz<Œ¬Ÿxnÿ¬R>[+igš¸"ÈúŽ´à‚Äï’úJSĶß@Úã¸ø<«Ô-¡µ6ŒUÓ &b+¬…‹C`TXEZƒ†;ƒèle2ïç ¬p -UqüÍÉk«Óz+¿ÂG±4ü^ IåÑl“”bâ(K%E,W öDwHça­E‡¤ÀÞ½ j[‚jŽÂøk¹Þl«LP™ æLPš êª9"°c§wO–‹z·Éü”ùiÎü$™Ÿ>€ŸŽT µÙ,ߘ“ jAù½ Ê3Aå/O‚ù¹X.Ë]Žñ²†š7Ey¦¨¤(’óWU®ªíá;½2EeŠ:¤(É**SÔ“)ª9?èŸ?ªm¹nw˜½s»i7€yr©çÑnà߯Ý@¢Ý@ì5ívµÝ ªägÚ 4áÑnj7Y´Ð>^ÔnÕ}Sj£Ú ¶¿Êæ„»UY/3K妨ÌR™¥æÇR8åíï‹õr³[e–B³sÖR™¥2KÍŠ¥pžü¨6U¹ÌæYLåsÉæ÷¥) ‹Âƒkšó‘4ïÝ.×å:ÓT¦©LSoKSöiªLæu®ðå °4Ó&ú˜\á{Ÿ ŸL¨ðí7š/+¶ T»u9‘ Â_DÙ£JMPp0®/"(¹•  k Ê.Tò­-Aù‹»¤dB ¾>… bÚ4”ì”·¥‰ lå·”]#(I%óiAX®ðR†õb±ÌœYDÍ»“3‹¨‘"J^-¢¦p”œà¨ò—ü¬ëz;UGeŽÊ•9*sÔãtÞ`NŽÊ:*sTæ¨ïÄQo™Œ:æ¨õ—Žúñs[׫*Ÿ|9jÖ sÉõfuÕì,þñÛnW—Ë]æ¨ÌQs樬£>“£¸µ¸^Vå:Ð’9jÖ±žgŽ:ÃQþ­9j ŽÚ¬ª¯ÿgŽÊ•9jö5XM¤ªiLUª¦1D¦1UAª:d*îÜ[îV+¾èZÉ1ïÚkžwîѶ°p¯ì5—¼sO4‹^sÚ‡½¦×<,ªû¦”5´×¼Äν¿vëE:òn’š{OUSùNVSÞà}ªšMMUS Y SSz¬¦àh“š’‘j ¼ÞWS:BM5²f²š¢;š¨¦¾~PLVSÍ„MVSNÔMSS^Ÿ¨¦¾¾VœRS>DMY,œŒøäzVêëVÅäˆïkTÅäˆOø¶®IŸÂ<{:ªlöìýã÷eµ«Ê|à]Žø®qÔ›x'ß9âû´ÌyY‚£Êz½Øäê^樜•Êõ,ŽrÈQ8jUmwu™9*sÔ7ä(Ë5Kެ£°kïÇjY¯ëüÐÌQïÊQžuÔ÷å¨;‹ëe]®r¬÷ŽJ)Å{sÔ˜œù\9jâé9Öûæ…÷Xý½Z,ªzbÎÜXe~ð -Ç%÷娗Ð"Sêzg9Jö8J/q”ís”ÜÀQŽÒke9ŠŒ9TG]8¡ÅÏsTL›&Ž’=Žò–£4q”̓£žtBË ŽòWqÔ¦ÕQ9Ö˱ÞÜc=?ëeõußdU¯—ëUî6ÏõMz>€£ôG}ŽÚ£ÖÛºÚ,3G½Gyæ¨Ïæ¨ï­£Z‚ªAåÆƒ7"¨Ï ô.”e‚ú†µD&ªª–«|g&¨·&¨¾‚²LPoMPý(¯*ÁQ«Ýz»Ì•9ê[p”dõ­8ªê8*Ÿ•9ê[pÔ§zÇìDr*¦±É©˜ÆN\µb;’[˫ݪÚävƒ×‘“ÜJNß¡m3“ÓxrJkôTÝqT.åeõ Ž’ÄQSZËòIå—8j^m›Ò㨉m›>Œ£$qÔŒ^¬W­»dyòp‘9ªå(¿»ŽB“ûë(yz÷Ýu2ÿ{¹]ìF¾lAGYlÁÜêÛrÔ#·¿øób=Ù㨓Û_|öÛ_ 9”£¦m9ä(¹ÆQO×Qv’£.é(¹ÆQ6XG=bû‹Lä(dþÛ®Z.ùX»ëÍ:¥#u”|@>jÞ:JšÖòýV¯ëe5¦é@¶ Ξ™Ž’KåOÔQ“sæÚç(ª‚+:j£ì"G…gí8ÊçrÔÜKGMæ¨y壆ê¨Û9êyù(O%×8jµè¶?%g®=Ž Y0„£ì2GùÓb=}Gù)Žº±®gDZ^3çtÔuŽ’S¥§b=Ûç(?ˆõìB>jT¬'7r”v%ä(Ù×Q-GÖQÒq”ÜŸ£ôùu=™]>jµD>jUîÊãÞé8ÊÎs”u%‡%×8J†p—78Ê’•4³Ó¾•£h,¯á(»š|È/p”<£ü\Î|`>jh¬·§£ä¡:ªÇQ§c½+eç9Ê8Ê_ë‰1ÖP £dB>JÎqTc§…¹/r”œâ¨±Þrµþ"©œÊù¨9ç£ÎpTä£)Π®—óQ÷ÖQMƒù¿~/×›ºÊ=œ™£.r”Κ£æÒ{9êÞÕô™ÿøÙt™ç—¨gŽzgõ¹Õç¥>-cy©OKÅX^êÓR1–—i©i-ÿñïzµ^nrx÷&´$¥%Ÿ+-m7øZz€tò9I§59ª^/·ã¤“<©mÓ§sÔ7k7P·óÒéµÈs¶¿\ä¨íòŽú.í#8jƒ4ùbµÞíŽÚ6G—òŽtÔƒJy©Îü Jy2¦”wš£ŽJyòÐRÿ`ž,Ts)ϵ|h)¯å(¨4Ù+åm£msWoÑûŽ¥£îÍQ—uÔ Žº £r»Á 9*·܉£šÖrû}µ(ëÕ¸¶ÍgÅz19-G=*5ËXoDÛ¦ŒŽõ&´m>%ÖÓÉirŒÚ‡qT|¡ÏQÎ Œõ^”"œç(¸þs±žÝ!Ö“gÇzuÓ¶ùó÷MUÕÇDZ¼XGiOGÉ#uÔýb½fxz‹Ž’7ÒQšuTŽõž £j¶DUÕz·Ê-Q¯«ëù­:êŽu½—é¨7o7¸ÆQïT×»½%ÊOè(¥=ÐQ~£VÌG­V‹*¿1ýMz2G 娎©ŠÐ\“˜ª U bª£ˆ¯˜ÄTEÄ?“˜ª UMcªâ¸Kj8S!Ú'E|ÅÉ.©ºn™êÍÕ”<‡©$3Õ1ÕSÕÔs²RZ3â+Ëõ²zkŽÊj*sÔ7ã(ÉŽÚp£Þ¶.W™£2G}Žò÷稬£ÈQè’ú}¹­×»¼#&sÔ÷á¨:Ê3G½%Gí~•¿äïõv³ØæW§gŽzgŽÒïëeŽG­Ý¡,ù¥U™£fÍQúaù¨ÌQä(trþX­›]wyŸŸdAºÍ'T¹Éõõñb2A5ë8™ ÌPÖžFP°Ý©õõ•b2A5L1™  šLP_?(&T3a“ ªqd“ êëÃÅd‚úúZ1™ ¬ñ¿S êëVÅd‚úU1™ ¾~^L&(˜gŸ ÊŽ ò©QYD]â(yµˆº5•EÔ{Š(¶š¯ëÅr±šó–½)%—8*Ï«í8Jnô¥7rÔ¤-{ð5S8Ê/q”·¥‰£ìu%=Žšx<‹ã(I5ôxyG¡Õü÷mU®7£ßª'Ïà(—ÌQOá(}ÏmÅÏæ(ÉõlU#ÖÛl»êÒñ,r>Ö³ ±žq”ö8J8Wu—78*Ïr•£¤å¨Gm+vÎ4Öà~:ªõyGɵX/o+ÀQbôãªç9JG5ãšðvâfÍýˆ£;å( ³r‘£äG5Mæ?ÿ½Y®VÇ:*sÔ{p”œÕQÊQöŽòÌQ/⨠gY.—Û£·÷8Ê^ÀQÚã(y$Gù]9Joá(™ÀQGGq>ž£”¦=WŽÊ:jþåÃ9jÛê¨í¥7¾BGiÊD=˜£ä¾õt• Îu޲G=à)æ£&è¨æ(Ο.V»e•›ÌsïÁKsæ¹÷`2Gé5ŽÂß×sæsì=Ø,ÀQÍ Rõˆ7¨û‘ŽÒi:ÊŽu”œâ¨6+­£Ì{%‡:ª1¨à(ê( {lŒ¿ÇQ2ˆ£p1 Eb‡uFG¬ë5Ÿ.ç…'êzøÙæZ]OGIÒQ~‘£4NÚç(=ÒQÍL¹ÆL'ŽBßé Ž²³å=Žâó aF®×ð ä(O%xIœYâ(;ÐQþò’޲‹¥û:*VåGÑbOs†i@¬³YZ˜Åɺ^ZYr”Ÿã¨dAƒ8*b=Ý×Q>Š£,Åz’8ªŸÒ :Êö8jÙ壯ôGé)ŽÂJžÓQú|•{rïÁDõ´þ(«£föúª'ôGmÊNGÅz/ΙçºÞl{´$ÏÈGéGùA>Êr>jþù(¨4ÙÊGm*¼¦ª—Õꨮw1%Oï3ׇ棧£ü˜£†ÆzÃóQ˜ëq:jJO壆qTâŠo˜:à¨Óù(™O>J_›²)ù(yë|”ß/Uw¯¯š[¬÷¬þ¨wï=¸s¬w£ÚXÏsïAŽõÆÆzS{6뎣Ž žm>J2G Ë™çÎÌQïÏQ›.g>æ0s¥Ë}B>Ês]/×õ¦ÖõüG=ý܃é%·×õÜS×»>꘣¶ŽšÛ^˜\×»®£,×õ4×õ¤§£Nï…¹œµf„ŽÚu•Ï=x?ŽÈkb=yV¬wÌQ‡±Þs9Êß’£ü]c½í¢ã¨q/…¹Ú{ ÷î=8ˆõ<Çzß+Ö9ÉQWb½óQOŒõîÓ{0³Î;Äz~%ÖÛ.;Žºt6Ë{Æzþ:Ê_ëy®ë½ŽºG¬w™£ëm«.g~ôR˜‹ýQvRGå(ÂQÞã¨Ü5£þ(×eÏ겓9óöGÒQ1Ò“5j¿žêGù9e×8 ÃÑ;õGéÅþ(ÚéYŽÚëÚ®:u©‡3ç£nÕQšóQß%•uÔå7먦÷@þ¾Þí–›K/×{E¬÷¬Nó»qdÍ-±žäþ¨뽊£œ3o9êÂ~½”j jÇ0õrU­G¿p%ê‘ óëÍQ£D½|xÔëæý@OF$Ìõ óŽ |0A邺OÂüA¥ßž0o½µ«;Ž: ô2GeŽz#ŽÒÌQß“£šÎÿÐuÓc89 ôü4Gùå„ùGᙸHG s~ç$GI?Ð;⨽@ÏŽ9Ê$ÈÈ‹v‚£ƒü[ÐeÒÁPÂÒ£HX–“f&Ðÿõ›" eÉÙEa1<ü˜AV3iÆ$ÒÀ&¦_SžˆLüî$cÎd$‘¸¦èU/‰˜2(Ïþ„ê ¶†\Ft= žÈ0ép'lJ€’E€Æ¶ñãÚDŒ’îò?Däê—ü\-×ժ̈̈̈|"­Èæüüþ±.ËŪíǃ$瘔í€Q·hqÉ$,æC §CO„NVi³Ö¬ÁhtqIZF‹ ."ñ ´´È6µˆÔPêȘ/& #l0ZÜ"=!²{&I,!Ò#Á²',$Ô!2ƒ@$…+ŒºC$“ãši4ï4ˆ SMˆL†i–Ôzmª6Í÷i¸K0—¹ÆÄðøbÎ]$Ç£ GÇlC”‘¾Á>¸`Zñ"¹†z€H•dœg>#ËWí!Ò" r¦€fCë’{%Dz ’“Ÿ “aP¯¸8¼yðÇ"SÞâ4"=!2%Ü…!'iHL[dŽ•N‰ñ§Hz¨@$ß* G ˆ„² Dê>"«_Û_ÿüQmËõfž>ÒNùHè#Wó‘zGÙCäY)wö‘6gi|¤ÞÅGÊ}}¤?×GÚiÕZý*¿¹ª6«ju‘úDêSTë}é‘ÏEä{«Ö3ˆljd-WËz=kÍ*4+s´ ÏЬ˜¦»jVÁ4Íj÷Ö¬öšU4«½»f­¿4«ü\,êE÷†£Y"rH9/DÚPDj‡H}"åňÔçD‘3B¤MDäú—ü(·ë宼?"5­Q‘ö0D~x^çî>òó:w@¤¾‘Í›!ÂG®ÞÞGêÓ}$ŸmæªU¿³jíøî>²Ù¢"?–Ûݦlk®iyPdÆŸ7Fél1‹í ó:Ú2T ‡}‘L¤¼NZ™xdIéÌ3§Û=Q^B¤í!R¹”4íh–î!’y=Êëô)D$÷¡@¶yqò HåxÌ}äu¼ Ñ9Í0qF‘’l3åuN  ²š&êò:´KKˆÔcDzÌ™ÚD’š¸B^ؘ¯áäu¼Íë0]Á v©"u‘œT‘‘änÉTŽ 5ƒ V̰'–O;Pˆ<Îë(M[÷ó:á$zý˜×Ñsy"Òi‹aÍô:ûˆ„ýµ†ìò:ÒC$ó:HÛ·4˜,Œ“yœ×Ñô¹ûµIýѱ x z´„H–Ú¿Ü" ˆ 'Âi)HMظ‚HÎHÌ8óV„Â,eZ…>’®Ÿ33zi°û‘dõi‰Kï#’î¿Mí®m¦Õ¢W‹ëy"ŽÔSˆ”>"±¨H³H#R{ˆlI‹H€Š!t MˆôÖGZôô‘ çð‘À`@DôUk‘BÊîûÈðIáì$dMÄÇ­ÔæÎ)¨Ä kò‘vä#µ‡Hk)"ƒ€p’=¾)”ôãb}D*2­Úó‘ÎôK²š@¤F“i/Óºï#=ùH~:’?ÓV›ÑGz GÄ(¯é9`ç‡ý;úÈÍjYî2"3"3"_€Èý:ôÞÿUï¶›z÷Ðr¤_-Gâ¯^ƒ@¬$–¨_ޤÒ{i9²ƒd.õ y\Žl!éçʑڇäíåÈñ÷*GÆÝuX9’¡“Ok¢ƒ¥ìÉÖHZšþË‘Isï’6­A@ï^Ž\.‘Û©–‹]ùXHêœ;t$$=w¼c‡€½C‡À²ilýÇïÛr¹YŒlÚ±Bò©mt–Ûèf É™·ÑÉ4H6}tò£¬ËuYÆ’2ÓX’söbIy|,)O‰%m±d(ãw%WHï’eNï|cH>'½“!yHþϯկþQnVñ‡ŒÉœr½“³H¹ú»¥\íÀMÖ©.¹ÌÌn2»É×Còà©ê]¹Ì½ÙMf7ùzéZÿ*«“‹r±Û|ndli2×Af‘tõoY©­W¿~üÜ.ër»Óy““‹ÉÍ"0¹9í'_„Iɘ̘üLLb{Ö_‹r·Xos8™ÃÉïNê¹pÒÞ"œÜ’UUó$ü Éœu½’6H¾IÖˆ< ɦ…gU¯ÖÕQ Ï8Hz†d†d†äíä­ª¬—étºì%?’ž!ùbáZb‡Û¾ÁQð0¦/öÒ;-$»G8†¤ðÉ-þI¾Ëá;ùPeÜÆó‡éKï<à¨ã1ö¨rÙAr`,Éÿq&/W?é%í¬—”c/éÙKfáú ^r’Í­ý¶Ú,Ê:«œ‹ ¦ß¹re‡!ù´"ˆœ.‚|A²úõÏ?ªÍz·ÎÌÌœ I¹$+¤wVÛm5³V}$ŸýʬùCRžIûv¼Ÿ—\áY»r¹-sÆ5Ç’9–¼9–´ñ±ä!$›WôÔ›æxå É É ÉÛ ©·AV|ÝfµØåî É É›½dš“ɬKÖËm½ÞtžÓYÄk'FÉ`#,“«ª]FßÅ’6ƒˆk(mІt’vKZ/–äãðÏ€$½à9ލKêùX²‰oŽ!)IJ3|Lu´¨KzuUæ¢ÒIíÕ%ûd(c„d˜VŠN;Æ;Š%¯Ô%5*S!T‚¤$H°Ý[HjŠ%­wày—Þuà¹ùþ籤¶±dÔÇɈø0ÎgðvØ<×»‹%5Å’'<çâÊ豤žŒ%Õ‚‹‰rKÔôZ0"áhÈÚ‡ä^,éð.m‹ ®‰\xà¹sä|c7{mç0š>$Ùv¾ªëmµøø$W¿ I9ð’v’öúXRÇÆ’r’z_Hú}!é£ i·xI;‚¤@Ò§@Ò»XÒÏ@rJ,©÷‡$ºwþ¾Ü¬ë*Ÿ*ðA±¤œ‰%=Ç’¯Ž%×ÉÍ—tý¼XòžÂ5Ç’³%¯d\gK6'Ôýø÷vY•é û WÉ¡ÂU. WyY,ùÖE=I™É ×[!9?áj}HnKn˲Þå7õä†:y‡†:™ÚP'ïÐPW±{gW¯âhex¡-æ¶s‘Üv.ól;Ÿ²$bÉy·¯Ø½³©»%Ó;Ƨ£x±ÖEjà‘<Ï@1ðèA®p?lñ8å"­AÕ9GqA ÉÌUìðȤ€4FrzmnGZáJ<êI¼ $‰ùŽ}óJ·ž)J®*@r¹(7‹2%sQò[7¸¦¤Þ)HÞ­(i7%WMëÎ?ªMï@ È Èo ȧt Ü È¦qçÛÝv]^«~¤Äÿ:[ýPMµ‡\ý˜Výð7ª~pÔ±šºWûد|4¿.ü°òï\)|¨ N¨{päÅ´º‡¦|JÝJ:e*Ô=Vƒ¢$Û÷s;¹çüq ®IOâê± ®cU«½…jíõ lsÏy†ä[A’ÖM/Ù}k–ܾ5ë ^’ít«EYíªo˜r½ɼ䣄«=P¸êhHÊiHnšÞ?·ËzU}Ç*È(/™!ù!é†äݼä¦ìúOz'Cò!iß’o“ÞÙ°W`¹Ú•î±»ôN‚¤¥} ’]û!‰ÏXä¥,BRÙ{ÕKïDÎEbG{ÏCHj‚$>ª–"ÍÀVú>oÿ xîIó¹ÉDS‡í;z°³Õf×$††«XZ¼ƒôŽŸ‚d›Þa,ÉÓ0Þ0Oï o?½c‘Þ‘x¨^z‡vY´«J»¾'ý2£ë«)xŒ|cÆã7Á£¶ ›ñø <â] ¿í¶e]>àMYšV¨GÙÇãì÷IÂDz’#ÂÍlŸ¤å}’ýЧð(gðHÉú€}’–ðèûxÔ‹û$7›’ˇm]>IyH¾ÃÖå·ƒ¤ÞI9Éi[—å´ÓÜv¼òt s&¡ÜÒ&ªVch?±ÓŒcI~<;ii’jMùÜÉí;æ' ©Ñ$@:ÚBHúùÄΡj%SbG#eÌ7(“Iµ6ðC1B@ÏÍɉk;$…I“Àå‘jm;W É9ƒ=Y’ÒB’²¬U­ÈPné;6\ ºp1€'$ž"—#ƒ^ƒ<¥ZsÐA’Ev² ¤¯Zû›@ú^²S­)A8g_ƒTK‰KŒ'ÑS¯A—£M ýÃ"7»îHå,äŠäÇ”?]‘¤ÉÞ¡"¹] I \”ëÍ#›˜™$sù㣠ùåí’­tÕzQ-?¾»5â‚=áÖrº»5þ[Ûtk?– e™Ò­ÚënÕ~,y½»Usw«}Lwë¶ä‹êõb·ü†ÂU³—Ì^r¦Âõœ—¬ÐJW.WÕz¾/±»è%uŽ{@®xIç%%{Éò’«’ø» ɹAÒ2$ë’y§äó!©’ÙK@rÝAr—!y_Hzö’’ã!‰óþ¨Wõjņ̃îAÒ3$_ É-wJnªMõ/±Ëלq}HÆUnȸîÉÝz½Ø}`÷N†äã!ióä{´ ì~• $7Ëínw¹ÇÕÆ÷¸Z(+Zwˆ_*/Ê­3ÂÕîØãªç!Ù˜ÉÕWh ' Cìõ¸êÙWíARz -$ °ò..8>ugpë^Û¹$á ù·ßãjêqµ€¤¶^rL+×»ƒ¤&HαÇÕuJ«õ¸ö!¹[üjOpýÀîKæôÎÜbÉÝû—·›Åªº²äž^Ò²—ü¾^Ò³—¼ÉK–±dSï¶ùU¯¤ ²Y€Pv{‡ý’þnû%ƒâ˜ Ø÷’.·0¿ý«^wMCÝ¿~_®×›O,‚¼¼U`®ÂU¾¥pµ·®MCÝ¿~[®7›õâóÒ;úrá*ßO¸Î7½co!\ÑP÷ïí²*Wõ£„+à8oáêßA¸ÚS…«ß.\[/9A¸Þ÷ ‡WÛ®2P¸â8¬ŸMvgl]’÷æÏŸ]—´$þöeZ—l!™ë’ñànû¶ „Γ{Õ%eR]r·pý’­›Åæ„—´œÞy/ù®éI^òû¦w¶„d]¯V¸$×%?ª.ùé ¹]Tåæ[rÆõ’þ!ù„V½’ËÚwþ{½-ëí{rÊõ÷ XN¹Þ’r].–¨LV»m¹\åÆó“ žg5ž{ç's‚gP‚Çg»$ìnJ‚g¹(;LÖY»fíú’pRr8ÙÇ$:xlUVËUÞ3ùZ?ÙÃdö“÷õ“òV~-<¿o«j]—ÙOf?ù­Ó®ÏØ"·ûɺÃäæ]s)d˜ÌÚu“k`r·¬êuŽ'3&¿—Ÿ´øÉȯÆd˦ òóG¹Y•«¬Z…FËhüÕ:ÖC"ÜVßå²e•Aùî.R2(ß ”DzuYv˜|Ó·|LZv”“ÀdÕa2¿†@âîoë'3&¿&W8‚§ª—ÕêsÎŽ j>žK“ŸPš|«žå~r·^oδ øk0 v|&=cò#1)³Â¤œÃd³qòç¿Ër³ØÖã'[Læža˜”ïÉ÷ð“%ò®ÿÞìÛu.†Ü?Ç#9žœQš†"$M{ßO&“„ 週Îùh¬&“ &L¾ß¡øMøIã÷àùNúIxè¿5öÐeY“›rUçFž÷ïÈ~òÕµä3nÑ®8¯îï›Eµ\ä>žŒI±ŒÉ±˜´{Ç“ÍQ5¨œUnBÂױŊ&ñÌd×½¶!ÔYØn¿æ`˜E0–×d1а'e»ŠK¿„^¨Æ†/d­ÝR³ItÏÄeãæ‚•Ó¸Iì’b!‰ðlQ"&„€ïù˜p猄)g7¥40Ì:¯Œb¼åÁe¸ á#Æ­ýhkäã³DyX5Y:Uø‰.º@ÛeEXЂ ýNì Ý`uˆÚš¶%ôæ¡;pÖ8«N» NNï3¨´§§Ü ÎX–8õ±à”G€ÓN=§§B³ìS8­U:É£^g¨œiàÔ3àTvÆ­ƒNëÓo§§žçªgyè9ÁX½ËàôyzÎCp^òœv 8eÖžSŽÁ©ƒÁ©Ißs89±'Gm£<§Ýâ9e8Qõy 8u,8uç¬:p.÷ÁégÁ)O‘µûžÓ38³¬ê9‡ÊZ?N?)k­NRÞYë7ÈÚ²çbºç pÊãÀ™=çS<§÷ÀiWsw±ûÉçmù 3ƒU 5æ «gç g6P¸Ç×-™º㲎÷ežô/ÜÖ|¢ß‚ãñz;eò¬„!š,ž„S«±çŒF†åâhéÌœ¼ cJ#ˆo)AP8ÍC|áêͼâVEXµÅ¨èYV%Mc'bX[1L”vÕ’aZa0±ÅÝ%¾ ¯ ÝfÀ µUbßעܖ'8J'p”Ì£ôGÙ38JGù1G9nÞr”Oà(¿ÄQÐm-G‰=£äGù)ŽÒSeC9JNp”\à(¹ÀQ˜’»Úç(½ÌQ„ªpÚNr”p”?—£tnU£–‹õöN:ªÇQÚç(™ÄQÒã(¹/GÝYGùewÐQrG`^¯£îÏQSu”é5ŽÂT¶%C8*õúGÙ>Gah Ó©ÔFŽò×QQ^ÜlêêT´·§¤ü¥¼c)½ Ké%å“YJïÂR½BgíÉJê‰,%`©xÚÙ>Kù–ò‹JjH´wVI‘=ü!,%Úæ“ÃR~™¥¼ÇRòx–B‡Ò_‹Å¦Zïú,eC´”‰÷|D¼w‰¥Žµ”\e)»]Kù)-¥wËIÝCK ÌIMŽ÷ô©ZJz,ÅRè­9)y€–‚Ü3Þó³ñ^×úŽç“”¹ËRö¾ZjM–ªVÛÕ6³Tf©ÌR7±”f–zKmñmÕf·Îõ½K_Ÿ¥FäÎs}ï¹õ½Ÿf©1õ½Z*×÷îÌRÛf7ëoõºÞ-79{~Kåìù]´ÔKÙP–úÜì¹~{–«jlwë-_=Š¥">½ÄR~köü&–­¥äLöœL,}–’1ZÊNj)»…¥dpÄç—µWÉèÔÙ¹˜ÜväÐÍlÇ£hBLb) KÙ9–’,u&{þм”ßÀR2<{îd)ÏR:Š¥ž=_ÆÛ{W»eµÌ‰©b*'¦0#91•Óç¯Sö_GÛù?T»ÕŠ;Ñçda¡þÁv 3å¶çôzìL¡m\4cï?w•´,ÎÞ~¡Å‚Ì(Všï6·Ã[âl¤(°…_Á§c£Áìæz蹇ìnŒƒä–|VÊI#øðKXW3Æàˆ(ÄŽHœ“CûÔãyøBÌpA¨q7'ûjúFÚVBÂd†!bb¸“…„I€4påhÐ_0ç FÖ\¥H„Ì1zl¹àð:ÞÜ­c6¸ ¡9R‡ÎSX‰Æâ‚—tá£µÌ o‹€àâü5¶…„´áV\ãémæP€îcçfRLX\âø´`­vës€¿Øéë¤|1sÙA¿“¶ÌLPР%Ϊ·>‘øŒ¹¡˜˜æK‹)''Ò^àCxÃlÂN%Ø ²³6^âçpüÚüÝcùK~,v‹%w6?ŒÖQ¾+&±F½ FŸFŸ FéÑÛ î-ÀÈEð„6{©÷÷ǘœà!;LNóĤž÷ÒäE9$ ç=é‰ ý:&W&/5¿bÒ2&3&3&ƒIž:·ÙÔõa^ç;úI̘͘œ=&›–ûc¹Ý®ø®ZÖ…sÄiw¬3ðÄ$Œ—3Cü Ý“Á V³„FçÆKL4÷8ö#Ië¡‘[çˆ& “O©)mƒ'¬\”ÈiYGh$ˆÙ’4Ûœc$³DûˆÐÈð/ú/ˆFc¹˜W;ˆ$cƉ¾@£÷†%Åfi³äQ$Ùü1,Ú.h–ÍBðcÑdâL žÉµÆÓZ‹FçÜ»ôr­¼¾¶hdRIJ/’l®XDºù‹Ç’ØÀH}4ø€1ÿb‘%$ø¤?pDIÚQ$$d]ÂTú¹Ö„F²plk÷KµÙh,8vj° ±Öà^Z]B#ŸÇÃw]0Î},8> x?”ôЈ­¢-‡¡±üòÛÝ®ª–WÑh§Ð(³@£e4^E£Ìh\#ËïŠFù4ÎË7jFã46 sÿø}±X­vëë5ñýš‡«yDµ 7¶h||W€?­æqªyPóð¼ƒzrWÀ~ܘ¦&Bÿ„F 4¾¾+ ¦(Hÿ\Üø¯þw¼oöGµ\V[¼ç$¾Â8¾±!<´§@˜s¦ŒÎS4žçꨑÆð8q¾‰Ñr›l Ô<¹0ØÏ’>Íépsér ß`AKQq4ˆ]:޾[2”Cuã‰LÍÅ ² ïDèÂ0¿X_KÞ¡»Æ@Ó)Fø늤2V'źŒÞ"Ö¥¡qºOX?îÖXWiaÇÖ¯lªO±®Ùa¬kýX7.£ g#Öóp™JÖïDZ.“ì¾µ°þæQ¯íY?s&Ž8¬‹u3­Wb]° X§u±ð‘ÎYˆƒˆu½ëÊXדõ+#ÿȺYJjíǺI&¥ðóó±®%ëÇ %`Cg߯ºéɱH±®žŒuñTÉúƒ^4²Ê&lI9°žÁ¯:ƒg‡NäC`R–òK±ì†ô‰ÅÕøw,06gÐU1S¶Çøx÷à_d8œY0‚dã31«=›—°µö›È)’…™!,RrPã“Y”xÁU=1~“8Œœžtùõ–¶˜m ÆgIaX?7gH²y˜møCm3 ÆDˆ”ÆÜi$::Æ×`ë`æd󀇥Lˆ¡p'²µä ›×ãsi§Èï žìˆçV WáÉæ%]´µyMù”kÌÓàÔ‹üaßæ™C"zùf¾#OÆçì5̽‚••HèYd‘ÀøÍ«C™NožâÀæé¥ÂñRŽ(óØ¥y¸ ¿^¬ÖûižË\Ÿ”„M²åz;R:Ìkz‚ö¸>F|5¯ #Øãz=Èk¦œp—×Ô6¯i$ñ\°ׇÝkÊkî+f—ý8¯é‰ë“Ò9פÝ{T>z\ŸÐ~–냔Ži ”yÍ(À$_ê=®·yÍÖ×{ÔzðÉ!yMéq½µv¯˜mÚ=qÇGkíž\o)¯i)¯)}®×žÒ‘^^Ó‚®q=jÜ¿-¶›UÝvcÚuƒ(¯ˆ|’²‰ùhð¾gð´·$íêÅõ žÊ/ ‰rÅYƒ·3¯ÇOq“To—È·Dô{=®ù)ƒ—#ƒwÕäßx¤*FÓ‚Ry¸“$n´—ȃ÷.‘ߊ›(Q%qshðzÑà)íSI¥§q£=ƒ×dðAGÉà!Ì÷Ä'ÿÆJN7’në¬Ò‘ب&΋›¶Ø¨)‘ïTFÒIû=ƒÇ¶Õ¿×å®.·T®lN•+=¨\©ù‡U®.0<ƒ5É•«×V®¶]òfu`ðA>=ƒO]7{`?Çð”4áꨃ´cxÅïüÙð5‚&oÄúwSFšôÇ}†ƒ÷! ßJy&oô²¤ñÄðz†áÛ¨ÓZIC^Û“4=)ïçÃWÕ}ƒG\#ç ^ ^JšÈëxÇð‡É›4Ýaðš ^$M'åÛð5 ·5x9 _ußàIä‡oç >åOIš]gðõÁ‹¦Z{kðéô#áÝ0,äI O†wš)ñs’æ _#GÏ8Ò£= ÝgxÆ®­ÁïKšÈõÃû¾ÁË)†O¶ Ò3xe›ÎA¶R÷%zDLÒcøƒØU ^z Ÿ¦‘ÝP¡ø9ïA¿_-âA(í]N|hx9ÌVja¡¡/KO¥mìÚ3xM®WeŸá51<çÔ÷4¼Ãciaž‰#Û¢¡á™ ц?ÈVj2xI’Fö ¾eø^3Î_.ÖU]M§øsÝ8™â[Š—Lñ³ x»ÿ¯ßÊU]mv¹"•+R=ŽQA6•?ü )œpOóß~b;N6ÿÙ™ÿ ý>ÚüW0ÿj½Ù,vã*²W“–¯«ÈRáß§"k÷¯Èös8Ô;S*²Iï< "ë½êT«wæ[‘•¸É Š,‡þ{½®–›ê­ ßrÿå „¯/íÀñÂÑã“õÎüoÝ&å®9½ ‰‡q·‘ó»¤mZ~ÓØA‡¿½92;LÄÚ}WX>ã>5êûxlîÒ5®PiP+¢/[š™H{Ãå0eMú2¢’´š öˆÓƒd=9†Ž?Ü„uŒòºñnQç@ؤ©„ÑæcÄc3RëZ<}ÎÃ~ T#õƒkÛÚ~3ØSÊÝGœì¨¤‰Ñ65~Ng3*¦ß‘¬ìÿ0F€¼<À+lÝ@2€Ø]ÄX >×%þë‚’ú÷7}Œ…§W­'´ÆŠ„ ƒ!ÿ¬œ0εµ ~)J³ôÐì –6–MÏÏ?ërµÜ-3,s²õûŠØI€$‹iò•n²Ȧç?tUU5Ï=È€œÈqÉ$™ï È„ƒ ÈoQýX® Ëu½ÜÍ<ªôùÂ2ûÉ¡°ô}Xêw‘¯wLöüç?ÿÝd`ÿ\¬ê%ò¯°;ýc-†;‹MÀ„]ÀÏé#šåB9³±1 à0L;÷ϪpCž„ñ;&‘‹ÛO×\L¸C4&J$,V‚8¬dÍŒà-t±ÝÛ¹msʽ̄ ðÇo¥ªdóGÜ™kc–XO¦Üü»yL¡¡°Œºy#[s_­µ“H+Bí$ÒŠP;‰´b S;‰´b ÔN"­µ“H+Bí$ÒŠP;‰´b ÔN"­Ø‡šAÍ,=BÂÕªÃÕæ®’ ˸ÚÇ•hÆUÆÕ>®øÆ‘uU-y–õ¢ŒÔ‹‹ÌÁfÑ‹‡h»ƒ^<6Md¦Y/ÎP/â}?×U½*ëb”#;€V1Ê‘@«åÈ U\tdWB±b”#;€V1Ê‘@«åÈ U pdvZÅ(Gv­b”#;€V1Ê‘@«åÈ UŒrdÐ*Zl%Øl;جŽ`s1®ºl®x¤)°iê'ÁƯÁF®è¿ ›)°Ñ °Ùµ°Y{›É°™‘·y:l’¼ÜÛdØ<ÎÛ`[q³Ü½Z¥ˆ€f‰›7Qi7çp£·ã¦ìüÍú4n²¿yµLûÜØûø›ªÃMõj“qóá¸y#ƒlöU].³ì3êë¶æ™ÍÎ}F-½s6ûŒS²™e³Ó2vý|xs÷_›UµZ®§7åÂшÂчAÍî µË~l6PX8ZâD¼墮wUîô{m }”·à}Þ€¨Aý¶­»Åö€þ!|¼Àì_ïõIp×p÷40ð;IÐrÑpùÁ›M23‡Ðï ÀeÀåçð(ôœïœ+í{yÀ²`ù¹|€Ìüì‚ÃPVoÈ‚¾mBrâÝ<à“$è“’0åªàj0%{Àì¿9ŸåkœÖºùÂßú†,hàEZà3èïè›N˜Ÿ¿/Ö›e9\‚vPž-AÀÇâ¯Pn þÞïÐ/Ð{ô3lŒ´ùÅ€vÂò,€–¦FÓmùäañÃöŒ?þã"“ÿü² ?ËͦdP¸2¡5§è5èâÓ—ió²‰:=Mº°XO‚&¬!-•Ä|7àyÂIıl¾ÀmË`¦pôž`ÿsdcL<~±y•8ÇT pÈI0< ƒ¦\ÀÓ$±læœjÞ·9Âm Â!rX –l½9äR8ìf*¼¨ó"aU–Nƒ ÁÖ17NÀB¿ÓƒI•´Œ8ÞG&¢ `G®>Ç©í)‚œQ%c˜ÞX2 S„i\”8&p"¢€í„çp`É ¥ø1–<ÅG¡7—å„ÂâbÉ ¢”¾Jh|Påä5ËeR—H ƒpv°ÆTÝñàç¤ÂO`¾1`¨Ó©,ƒiÄÜãǰ Ð|ª}ðëP§bm…* å/ ¨¾†wÐÃ@=ìÏéHÀœóÿea{X-› ‹]½Xƪf¬f¬f¬>«ÿë¿áW«6ÛŠ^ÕC¥CÇŠ„$Ô¤¯C0 ÚkØbA8 GIÓ†hJ¢µQÄL¨€æ+WœvS@Ú3ÂÖd¬Ô18®š‹K½…·YÇOIè]%KI­šôF Áù)Z„pÒqœ­ðrÂiw Ñ8•|¡°#o%%ŠO(CmÎ"Å ðÆÃ ‚zÌÒ -8=†À¤1+a“œ8ÁÑUa‘b¢Å§›Iæ‹ÓøH¨ªæ[EØ¿DŒ&Ô§°sÙ•d|²ÉÞ\2mO&é)×*1D(Üñi\AšDxÔæS‘"<6p@R™Z»YwX˜'bí[Zí¦,>ÆSŠãq¡æË´&§eònÆ“#òo5Ån`"Lxž–‚‡ˆI.Ä5¡Ó•d×ü§?c蜠dÈi5ÂGHÅ(‰¦V»8#Ü 4 «lpe;»äBͶ…û § Ü9dÆœ<¸2¹£(B6“5%® sr Ÿ!Š¥h@RÈX/I‘ ÒLȉ\XÓXËðp¤§yöŠ‡Ý–_Ê¿.ÇRîs¥™¢2E݉¢äie™¢žLQr@QrHQU»M®ªïKQYE}oŠÒoIQWU”N¦(ŸEÉ|(ꪊZa#áj¹©7wSQž)*ST¦¨O¡¨ôü¢¨¦ÇáÇϲÚTëÍhŠÊ¹¨S”>ƒ¢<z#(ê¦@O÷)Ê^CQ> Ðóù¨(v¬×«MU (ùþ¹(EMQQžsQ³¥¨=¥¯¢¨w ôþë¿¿ê¯å¢Ü’ž„ÜEE‹b ¡¤¢–,wáOpck^Óé .±D6Ö"i9é䦯ŸEóL…U]KÜDL¢  k4¡^Ǩš¹@ jM,eè8E=5&ÕIk(•^íLNè¸É£§*õ˜Æ¦-ã K8åøW¿w’8ÌŠ¦óv(ð0†^TŒnò#ùd}njŠöÁM‰Ûà?ÛÆ6Ì ±Àr,_P³Bn²èÄâ 8¹›_a·iœ1Jc<”iô'd-7©ìV#kj¹ÍRÛc´óyô$᢬N²‰á5møbˆs ಌmÑfaeî1;hKˆ/‡/ ™‰YãÃ{ç]ØT"䬘°¦ 2XC¤›äè?A‰Ô˜¥ÐÀMlL˜±÷¢õ¯7ñûè^°0Zá,CXÙÛXÂoœ^)xQø5!*ß«lÅcÝÙZeLÄd‰˜Hž0t¼§X5õÜh"&k££@BSp³Ä3G_£|š–Mƒ ʼnB˜ f´ÇK©ŒWÕÛŪè馘î#nÒÄM’¹©ÇMz7Ù>7é5n’ëÜ$Oà&y7éC¸IgÁMz¤›âûC¸ 4ÀÉ7ùL¸éOô@ýcYUd¦Dè·Š²¤°TFDrÈD¾8 †ŒûFæ†ýoä4Y•·C“ÒÖØ -4k]€ÇÙåÇšÿ.F'ºÑDTñé€ šà"øg\ !_„)EFŠžq–~Ë–uþ™WñæýäÁºL4ç[IJAó/´’–WPç°ãVŠŠÉwã&„XKTÔå˜[¶¹ý$sv˜ÆÄºRK#2r"Xif9‚:ãš°K/`€%µ>:» chÍ€‹˜ªV v-@(}8.•$ÁOÒ¦Òí¸¶ ,%@°ÃÉôbD´´F_©2ãÈiöœmŸd„î¸AŠE‰iL†q¶±Â)8i™æø)ÈK:ѽ¿¼A1NÆ|0hq;ÍÃÓ„ëXÊ#ºKé„:x‰=m¤O1‹ÅÂÓ¹‘6sÀ–ÖXTb õH*aªÄ,DP‡K@°ñ“†‰±›ÄR1:ˆ8—xŒ€1¿ÃXZ³–H&Âa2 §¸å¨2ö?¬Wuu™¥4ÅÖÃXJƱ”Ý“¥hƒ1±œGK^ å—YJû,¥ÉèKqx—XJγ”žb)½ÀR½PϘÇi.UxRªgX*ì-X*s¥û(Dh±”`)éXÊα”1åAÑ­NÛ¿7KuéIÕi,y»C–’ÄR:’¥ôK¡¸Ï©Kµ",•àžX†™v¶ ´,ż.[K`=ºÇRáb†±T——²}–²¨ i0hŸ¥x ô"4.,&3ê\Ø#–Ò¾–Ò3,•*+ÁR)áDcC§ˆUÈV-E¥rÀ‰$²QÉQ,8ymQY¨Š`Ê *ýƒEÓkЃ ªxYàQ­;¢Z^#ª(Ý•}œùÕ  Ï'•L$*ŸQ’S'‰JG•Õ 9u™¨ì QÅÈ÷‰Š ôQ=BN]&*= *KTçäÔ ¢²De-QùQ± |LT‡Šª`ŸÃp¢’³DÕVen!ªMGTåEåûDEåûqß<Õ»•Ü“¨ü5DÕWT²OTD¥Ó‰Ê¦•_&*Û¯ô#ªÑŠjQVTÞ•ŸTTÚ#*?GT}Eåw"*‚°%*eŽ\&ªÿÒ¥bß®®V‹t€¢l’•²›Á5Z…8ùšPâz6%Ìè4ÓWÌ.õ•DW’ë˜5-í´h(aC§“´”–‡ .Éâð]5æ†åŒF'L¢ÑšOt%Éž[h݆.˜ižÕØfqZ ÚÒ•{Ûþ· VBh,thOBbiþ–í5-ñ.mL•XØ9YwKtE Ì^®0{E€ fHÂq¶™ÑR¢MiKÎàº4]@…Ÿ7 ¿Ææ ì`€½„Y˜U€$È4³×HöÒQìeÉô÷ØË.³—öØË‚½¤Õ[ãÙKÅ^~‰½ÒãD…‚p™Ê^«Ž½Ê»²—̽ä${ùöò‹ìå„„Ÿc¯kÚˇi/{¤özöÒKì%ïÇ^óÕ^ø·Ïa¯Úk:{Õ{U·²×™ÈñÞìeÜ{s7íu޽.k/?©½ìÞìõÐÈ‘©§óì%sa¯ûh/¹{ùXöâÿí½µ×wd/{({­;öZ}ûÈ1k¯7Õ^ß-rœ¯öz`ÞËïÏ^›Ž½êÙËÎh¯{gí§k¯Ì^ÃØkvYû‹‘cf¯÷`¯h¯m³ ú÷ÕvW-6o’÷ú(öz|äØÕO²—Ͻ²öz×ÈñìõÿûoÂÄý¶¨—Ëj{ò ªqH,ÃU ÃŰŸ`"»y«ê¸Z’¦‹<‚áSHˆ”U° 6¶Ð ‚9,ò$ oõQžý¢©’!œW®¬,´¡iÝÝQˉ±¤Ñ{=Q$™4´ÆX.¾"U#ÁÎZ+Çræ Ê´v©d#¢ÖÒUÒ&œnOWNüËË‘Ë0oñÑÞ C²±Š;ƒsŒ¤K\Ktx¾¡‘† Ój† KÇ/ø > öÔ{C#þJ/”âd‚@°ë…óËIJ‘hà5üƒß ç]-5½”Eï{C£„çÃÇ1ÖæŠn¡y%ìfï ®=÷jé‰9ç¤//F"9xC#~¸Á²ƒàé·k,î !˜4Ätê5ÚgCÐ2 A¿A¿+åÞ¬Z²spV^0¦2Cð !Z’6;‚vwÞ× ^ Œ†àªƒ`y//ÈŹ³|[f/8‚uÁê^^°¢ÒAÐß‚–!˜½àS!¸î ¸š A}ÇXPÞ‚š!ø/D7ëA›|A,x‚úrNð‚>‚–!8 ‚von;nîåõ¼à9æXð>œQ,8s!ºë 8¿ºà¼ ff!:o!º\tÜ]R¢z+ßE‰f ¾ ƒ> ÊS1Èþ˜m½Ø-ë,E?ƒ‹GJÑ9`ðR†œõ!Ë`P^„A™;}Æ|œœ„A} Ê}0Xáð÷fβW”›Ëó÷‰³…A¿‚AýÌ”ŒÏÜ®: –ƒƒ#0(ŒA¹'k`pS×[žÒv¯6µ{`ðè0WŒÝæŠQ ;À\1 t˜+FîsÅ(Ð`®º¿WŒÝæŠQ ;À\1 t˜+FîsÅ(Çw€¹âtëtÓÚ³}>àìßK@y“$ÌýßÃÀ{8¾¿÷ö ÖwÛ!!}¿×| Ú°Q;„  ƒày7xêYÊuêÓ´§N†à錌 ]ÒžÞB…«)ÚÓör0>‚>‚vA¿Á@Õå }æ⇽ZÄß{ûëóÒs|´¼ ‚Ï ÿ2_ Ay»}‚õùMJ÷„à‘Í A¿ ‚þ`ê ô7`Ï úi!:‚Ý>ÁúÞ›”2³ü^Ђijî Aìü«^–õb!8ê›zAÿ¦^ð®Á:{Á™xÁs<ïe°ôzÁï >$Óí¬÷ z†àw¢Ù δ(Ñí¬Ï^ø,J†àp!ê#!øØXÐnò‚oÁû¥czû×Ï©Íg7ø"7x7 JV¢Ü Ç`׳–‘cPžŒAŸô›üࣥè]ü Ìƒ÷ȉÊ ¢AæçºªWå¢8‡¯!ð*Î5¿\‡§÷¤¯ÂÛçÝÇ×W lÃ> ¯â¾NÁËàUœÓ™.NNÁ«8‡¯!ð*ÎákH¤WœÃ×x ï ¾†À«8‡¯!ð*Îù¸äâü‚‹+Z|õ¡S±žPÖUÕ“’%d–Ot_$!OtX¯ð*©Ý®.·Ûb8âŽW GÜ1àŠáˆ;\1qÇ€+†#îpÅpÄ®ž89Ö‹ÅpÄ®ޏcÀÇí’Có=ÀÃw ¸b8âŽW CœôZ§‹³ˆ;Œ=lÕÝ“OÌþíiʱþ-W fT¬Ûóoëƒw;R0cpŽsÎ)’ykÌ·-7ŸS®;™FÉ|?x çíÐ=½‡Ám‹ÁrÞ[i3o,¼4×¢Ãü ÌƒwÕ¢'üà®Ãà¼÷Òú}0xXN˜#£Es¾s~ðƒå¢Ãà‹6ÓzöƒƒoA»;ÿ”¿ý_ÿú'Ê~‹õz±ÀëÆƒçk¾%ÆñÍý€QO“ˆÑð? çœ8¼Y}Á´ÓõÄÌs°ªÉbîyÖW CGoF»E$dq²Â|pqÅ×Ó8UBf¾¹pÓ_ã°LÌJó >~„F#¦[°BÄܵòy°ê(6ÿ"`c0GåCc!X2açqõ&’¡Àǽê`oT`gxX04‚ßi-àʦVK[ð ¯Æ¨hÍ:Ž€)ÈwFZâº4ëî{ðL Ø°V0VÁ4\`¯bp˜ãâ‹Ox9·÷ÑöICäQñ®4gp7™ xaiaÂ…QXbs_§æb¤B‹ããï6¦Sט'…‚Ïœ `œ6iY°¹¿ '¾i1Ôz¾ æ€ÙÊåÁÂGåš6´ÒÇ,е$¯tnÖa±éû¹(wë qH2oÖEù”MëðËsìPL±xQ2)$bN KùEá‚â,½*¾E‚GÛ  L5ÿÀüÓÔ­¹‚¾ñ¯VæÁ4ô¦J+öx‚„ ãÍ›©vVu8¬™ðÙðAPxך?¤eJN{oáCSvúXFª9JØ%)&qg^–"éˆ0vdzKAÇgˆ~¤Y*…Cµø[éø`N‚Ù¦?óP'ÀXÜÙcæÄȦ³nÂ¥\ƒÄ4Ì“C-„Y a€?7Wk,,ìEÚIãŒãGdW WæL^hCäìòÊ @~%ùSÚS¸ÓÄ+ ÙÀÄþ4¤ù£ž˜†fìÄOÁU¤c@±|60 0ƒ?8ïÝâ«Dq½Z.6‹ªh¹÷ °àgi¸\üÑCmò3ÚTl“©XHCaTêä¤fÑMHÛÞòŸ ñ7ñ5Lvr”Ù&Bó (ÚXª¿ƒ2–ÂA¥8NTÈ‚˜/xA•šóL¤¨îîÝ©xV®> Ô‹ðHt¨ørØœ$ør5覀ãfR ’p«’`1FIŒ‚‚ÈCÀH3ìxT>\rS¡½à“þ„tt…A±HäÚÀˆÑÕX˜¥‡×¢}âÞbÍ3›„ÎÁ”4*Ä©X¡WB—÷qEA†æáøh[¦Ï,IGr€` ÏT4÷±ô“ÔÉI çüpØ,Ü`l{¡B.U2X"](Î]c@€nKBJ²¶9THA…¡jÕ¤màe¿¯Öëåv5 ^’á•á•áu^åWœ¶Z­¶ËËðÒì½2¼2¼F«é~þÏÅfÇ>Sßó]Jአ}pI®¸Ï¸ôpIdz3×ÒK" GÄt®ˆX{àb4w\Ú –ÀåãÖ>¸g£ó‰¸”áˆöÀ¥—Á¥‘+8—X—MÂ$åzàÒ©àJ H!©µëG*9 .IàòAàÒàÒ3àRIIŠ+àÒaà².Mà’¸ä ¸´—]—ƒ öýµ\—å¶šcnÃsnã»ç6ì{ç6šææ?ëm¹)¾8!d|>H’ñÃRŒ)ef›Ù+RΓנ#iÅBÓ¸Júr®±…!¬Œâ\ô´°.\˜pmÀØ9ïq‚kw𮀯a&Å…»jž´0rïŠ 1Yâ·Î_¡JˆÖ*LºJk 4nJ8¡`'I\+Ä4êŽ×•$ÃÂí¶µ6‡Hx2ÊÙÈ"sX…ÇèÜO•ˆØCL:óÍNMÁêeóQj1Cá¹hø€%æÖðôªøJ‘Ê!4Ñ”ú£ËM~À)Åè§ׯëòwíÒA–*%5~£RB ã)pb5›Ú»ÈØ¢¡U’Xë%)4ðìÖ(*¦(†R‡3Ê0*çV]ˆ·)›ë×°5eGÂÐ7…$¡?7*e †Ë’ô!M‰ª–z ¢Éƒ ¨ñ0`”îãÛO "2JjÊ“`b:@ ]ƒfðU†pýãמ´–Ó>¸|Fá »jqÓ;õ¯ß–›z»©/ú+LtòWvà¯ì´¿ÒþJ/ú«}geûÎÊŽNtVçÎ8«#Ñwè¬öE_ë¬ô‚³òÖYõEßg¥ÉY1Önº¶"I1ÌY1WÙ‰¾aÎJÕAB>»†®9+Pjç¯ä.þ*ýþ žhŒ¿²ÁþJø«/•¿þùÇv»Þm—Dó‘dÍDMãÒÿ]–õn‘!ôv²Á’ ¡‡A¨ižøc¹(ùZ7o+¢N´ÐàBà «L…1uÉŸ5‹ÊîUm5/gF©ŸSÅ#‰¢Q:êP´>¯v¡)ס4Àr8Æ€¬AAöÔbA(­©+Y5²³lü,øÍ$ÒyøºÑJ4¶!ðñ2Ê"ûT»xˆŽÔi”H³1ŽøƒŸa Î55±³ˆI9vSs†ÚŠ`¤1Þ‚7eB=L”⩸ˆÄãMFçø=‹Õ\F]âˆË{TˆÚjo´º3ƒÍî}b–¥ñea^9N¶aŸ"mwPmkðnÖróÉÛZÃÇ6b£¶…;•˜%N žÈq'¢™ôõ_Eú¨¼XM“È—ÒN,ìv¶€¥Ò”åc§xœ\õc±ªêz{÷ÌÝPt9sw1m7ØÙý=œò@ÃÒv7z +âÌÚÛt”¶³.ý$}ÕùS2w#=Ð}3w8zê?«m]VÅu©v'Åu©v'Åu©v'Åu©v'Åu©v^©×¥Úyœ×¥Úyœ×¥Úyœ×¥Úy¥V\—jç•Zq(ç•Zq]ªWjÅu©v'³ù£Þ-»N†ìj¾¡«±ìjæjšf…?ÖÕ¶:Ñk§çûÄYà`›«çFVK#«åFÖ3½vB<=¯‘•g¬5ÑÐr±ÈRîRN²”{o)·ùU6§í.Êjµú֙눹d®sñGf¹nŽ2ûçõ¢ZÆ1JñôH4–hz™‘A=ÉçuÔ$rÅ£[oSB—9L d¶óG|HÓG‚kPšpî™M…Q?¥ÉÍóùÛýTd‘ç¸FÊaÀíÇœ‹–²é_?ä{4únžZ¤Û475X4Ñ$ãIø $«T¸D_2$%-…ÉÓæ\ÀJRR<$±jÑnÀ!0 ›RÜΖbÐz-?‰ýÈÒÒ5¥¸½Mq¼™kŒP<í2isÜÐXüå½?³Y—z/rÜX0<ƒ/$1¥%>vìA€³èµ±ôl{9neèhš¦€äUXJ°§ÕîRÛíŸiUQÀÀš# (Ð8ÕQD1~vE£ãj3/_÷"]ÏÕø+§òNfq’¥„yÚX‚÷¸ÐÕ¢Û&ÉR ÆYJM?T*bõ5ÅaaZÌakê‹,±Vë-žz¶Üc|­Am<ôÆm'|úB˜q~0Åá´FßÃÅ4+ýg¨ˆF*µx¸Š°Aþ*=X\MÙö_¿o‹*õ…ó E n3 WzH­ÕèÎÌCvh4‹©˜*º¸½`5*MvháËÞºI‹hN Ƨ<&48®ÇÂ`É)ÊÄЖz¤$Â;> ñâP#²˜HáXhK¡ çͨÏâËÞ sI‡LÞDóœõ³<$IÞ^æó :„š¡«`PJ–ÂÔÎ>¥cPIÔ9ÆÖ³k;Æ81$H’Ôï-§¯¡ Ä<3œoK3]ÍÁ#è$BJR÷Œ…©0 çRa ”Ľ»¸.=,ó?Ú(4dˆ¾Æÿxd¾aWÑ_ØEä8Z׆5–¤u¥=i–Q’F¤n•O¤ÒLÞ°)Œ1FøB‹ËC±¶~’†ß! ‡;ü,«Ý²Üµ‡;P§pç“©„{ÈΈe•a1BÂc4¼%S Á›)¬f&…i$f‚ÃÚo†6Ї0 ùÚŒ~|˜¥þ‚CÖXiÝÇW¸ÏÀ—´øŠ–Ìb?—a8C !“y;#ùÿÙ{·åV’\Iô=ÿeÌx¿¾ò|m|m'|MøšøKø²ûð×vÀ×Kd^Uûø†Ì+¦Ìë‡e^öÈÌ«o½øãÏåvµ]o¦Ò°ý´Ò°äl0üT~Tiý®f³Í\ò Þ˜ ~9VLlª:£2Lo•l—-JSD¡:  UÆW É+õÈ %ošôÇ´ØIQˆ`†EN†IW-WÞbHãQ¬O(f LlåÎ…õÛ*“ð#EU´”êY7n!MÊÊF|`²û7ô˜™ò–`EW|ÈøŽ¡‹í¼1‹OÕ¾IÝC71m¬ååÁ;TCÙfàmgE)E.çÍFh…˜cïJNå‚Ò‹¢"לÃ/Çh{­`§iú¥¥ŽÚÆM—rmÈ%ö¢ùdý%kÚ‚{\ø 5¹T">1þйd1—šâ¨¶qJjHkªÔþ m<ê_œç‚7V‡vÓÖÆ]±›hPU#ŽRIf¹¡ég ÃVíô²„Ž í%˜Ë ô—éÛ°Û3ÕÉ‘ÉÊï‘*Û6ÞŸA>'…7 3ÅDx¯@™©…)»G•L,êè´<ÛlÒ F¯)[hZNhºM>¡éëДï )¾MÐ þ\Ï÷ž•çÁ@J"·:mê¹B?c|“’ð«Ž3BûàÊ(ÛÕó5@q´jµ`¬ÐQ ¤¦Ll.†”Cy¨ &P×ð0J«CšÆb˜dlWÁZ'³j¼„|ŠÅP"œ*Zc¬N•¢Œ™ùî%æìz.Œ.” cîºRcjÇW4(ÉÕ>,ºK¤ÎÕ ”à%:TnËYpVYCšž«¾ðã}xG“WÊh ˾ '”¡ðˆäH0ú!ÔspBCMŽC5PÄ‹-¼ÀžÒ:¡•pååSüxSY ¹K§>;8se@J0½B¨Î|‘ÇJpÒè¨[£]5SHmƒ“àâ®T®S˜Jëø@%øs¿Ù/–ÛAZ" bΘ±väa=*§  ÒÈ&˜Ì¸¼+#sjh¼.Fìܜ定jHdçCÓ¨5ˆ¬"õ‘ ­,Àð&ÎKÄb¤[{ ™¹ÜÃ[AšKòF>‘Qö³ùÑ¡ŒbÊ¢ò£,!JGP5:½W~Ä -iýĆʪs²iZCÈù¥Iœp‰&QI151ò#Ñw‰™ÔéX‰uåGDÝ #š(H‹‚Gù‘—ŽàcÁ4?Þò#S¿i²ÇNUùQ¤•î¾#H“o")®Dâ à“­àã…¨–@D‘á/í–³/kL nœ—4&¸]Þ˜P±sÓ6&¨ûehL@V.Ù”–{ÿÆ“Úþ5 òÝbcÅ~ñ^cBª1A‚о&°ò“ yܘP½ª«>Ù˜×5&ðñ?nLXí~-±Íl«0ϘCGK%z½dt$­¬c‡ Q[ ”œ’Âr⇊k>Ö1ˆ»e&”5YŒñª ÉÍvt}FbPqWñV“µ“ào´'er]õ¶ñþT B ¢ZÐøý(}ÉÄf¦™z‘è˜9”8<-JÉõŒ¬÷¦šßLe8´¦Ú3L‘X%6FÕT´ ƒd{WPÔÏòµÁ*ùFxê¹±«hÔôiwå@²H—+ühôòºÿMƒRÞDD…:ËáÜT7Cª $W)ŠGš…&claÔ(“Kʪ^*Ì£ê9* R!˜+˜­TRî7„ =Õ¬4`·QCžœqq9>ÚЈ·'Iípø¾nɕΧÜ!QŒá¥¹O{ÓÛ’«Dgª¦y›‹(Úcê÷š;$OÕÃÈŠX”1Š36Iˆ[oÛžNõŸ*_¨ïóɣµÓÓGýg9ÛÌyÜ82¹d«¢—3wrÕ›3aü nèq]Å4&Uó‰–¦VœJ̺HY{˜2W<^¸ÀMªé£STÄÖ3LTÌKkfºg’*B©A i×YIí˜Õ:ÊJÊ6éˆpÊ@Þò $âTþaYM"P˜8e´JÒø>¯„›/ƒ]äÔÊb¬¾HŠ¡á´ó)+jåô„ Ùjëh¸ ¦Ü%J X§÷VÒäUX‡W’œFm”ñ&§çH5Öï(«y[ It ¶ˆªÿáR]ÓyÇISJîÐ/~z¶ßò_Î6]QSj#d6Q*„­H;á¥NÆ?11—IåÆdÌYBEXä^Nw œEgù8J†FÀñœxàä8ˆ2Ï'ߎÝ8ß]ûvàÄœk³,à,îœ8 „ÑSÀɧf{ p¾qbΧ3; œçÕòûóHÆùþPmΕÀÁö»?—³ýv©Y ™‘³"DÕN·ª^Ý*øJUë[‘Ø…Ê\,™”ÐfnHô›BwM(‰0ÙÖHåÓYLÉ€S“%>i¿Ÿ“’º ZŠÅÒ‡…”dV^Àû³ ÛȨôÒ=DÙqV$ V]©Gt¡ÑÊ8[-•i3í°¦ÚFi="Yû“Bñ³ˆÏÆ‘‘:—­ ½äl½¥uVT>ˬª#WR(K`RŒÛÎ/iÚôJ––\͉j7sHpœ(yD.5õ•‘† ½ÐRO$ûS°xYJ4J Ye¤ãæ%ŽÈt¡B´ÅÔ~«I}FZUTåTÒ¾É èÀØâ_j—I@†ß¥œ*ÁP4@UV§-”5òÙXû \Ë_û×b½^ì7àŠÇ‚+/—¿¸xg­Q^ .?.»\q?pÙÝÁegÁåï‚Ë/—]®¸?¸üp­ \ëûËîÃ\¸î.»„¹ìIÀõæz¸.b®ukõ…Ìe?\vÆ—†…ù5a¡Ý.ÿ&pÅ­àŠ{kSàZ>\ù†¹ü“àâ¤å®ËÀåß ®ïϹ¾‹¹¶®ÅÄ\?\“ ñ-àÚ¸æ_)h\®I-¼\“ZøàŠ+Áµ/pÍ>—}5¸Ž™Ë¿\v¸âcpù‹ëò°ð<¸¾XÐ8—}sÍçB×nw'êÊ‹’®[Ðõ4Ô•7R—=o\h_›t}]/¡Å/Õ†¾ßÌv£ ‡DAº¤Üþ{ŽZ;Ö"i·õWäËmÃ!®b?òõYáæÜ¥p £I6j´YøDúp '°ÑÎø¢ÑxØ Šúéš%Ø(ZСb|™ª3ÁÇðOž€Ç ‡0}nƒ0 –Úp¨÷{rË1¿ W‚ÙGS7¿§N Ù9'aü~Oâ(L® 6ÕÚ*R3ʆ€âºÃ÷{ʧ8' $ô&°nüJ–Án‚ Ÿ ïÀ‚sxnÕÇ碛ïÄ:OÀK5$À®”ròû¹àJD4Oª¶?ÅöF &Õ¯gjC§†XH €+C­xú¤oeKËÁ†Czx‚ôð<Ž?e¼›S% 6uÐæÑ€Ñ_åÜû="´ø2š_8aò?ëÙlÎ ½{WŸ$[ùx>¥|“Ü=M1„V6Ùšè¼BCù¶6Ȥá3Ô'aâG¸!ßœJc£ñ„Ú1î¬PŒqÅ@ìÀ/ËÏ$ýWÈ"ØA׃ê¯+~Õ#ðåAQdhD49 ë²¥ ÇA+^A¥ƒ±Ñ`°8¾áf8iÕÜ‡àˆ™N#»®¢äê”{«øDô8„„"ÚôD•$ˆT!ý¾3h#­·¸áË-ø€FŽmµÆ†Dgì-ÇiŒ‘:©š¡ßžY®Ãl—òmÖûhŽ7­1^ƒ"VŽÿuŽÁL߉H‘œŠæI¶/jÀôt€|6æª?¦H-(ôä™átŠÿl6³õðÖOúI’Ã^.­.ž-—©BÜɃ`‹’LÞÚc`>]¡¨ó ‚U(+cO¬V»õZ|ÝA°ämåªYÁ¦•ã7ú5ª.fk×…[óÊ~àA°ÌéA®`I1Œ72“L%ó´Šý²=ŒÚ‘Í%T”þÑA°kœNñçf9ßoê4ådϳ‘®‘®0,‘Ge ¸\}ÿ÷yc-ÎËÐ_É-¼åú@ùíg=oŒÒÚ0de’ár|ÓycÙf“f0BÓN”´Þ.†ÓûšTÇ WšœΠNÆ@‡v4YÚ† ƒt;$0+å€VRÚÌq¢ƒÒK`L $zU‚]qBjJÙgÀó$ðYsÝMHaöÄ0¿Fy’ÇÿÃԋæ‘àp+/GeÌ àž‹ƒTÂlFÿ“%·VhÛÛnWþ3 »pFü¯{ø)çÀ3ñÕ’ \B•IøH~H+¡§?~¦cÌHs ¡ä:å,pÀ”H+΀åCcÒ"’ËMm3öa~âTûìZäXrÄ*‰éô- s#<“ñs0$gtåJá›bUÒ•¥þLdÙÑ«ÈäÍ8ÈÚÜ4¡VÊ„òS”?Ó$hü̽D”âX“Îݰ×_xë›wç³ír³š7Ž30îQ€Û+\\,Vû)\œÂE{pÑŸ5\ÜÌ.®Ö3$_ù9$!ƒ !Ô58Õ‘JC±ä©êbÐü #eh®¯ê{Z},0¬v ANz†°Bsç=)«a1‚[•iæQˆÿ]¿²C4&=PxWHz —(Ø–FKÆ¡E$@(=SyQVÍ2Q‚Õ³‚Õ” õ(ІXJVUÁ‘Â3NyiÓGS•JPpÖPBP”J ¥dãå5Á•2ô è)“^³´1â†% 9?:$>6õ$ŽD‚waXyŽ—×¶,=PÕÄ -™æz`ió¥fVT`4“ tEú¸\“´»F‹ä¥TÖ¤îøbŽPyëIÇIà`jQ˜ZSùSª°N‚_aªÿ¡0¥y`ãÀ€)éÕǘÊLi*³FZRá€)»SÖ0å÷Å”¿‹)»SyS,Òò>£'‘–Ñì˜Rm†¼Ï‘bÊ>Ä”ŸÂTŒ0eŸÇ”ßSUïò7˜ò¦äM SýßÞÔbJÄ!¦ì<¦$1µ,L­>â)UeT IM9¡bç1åw”7Lå{˜ÊS<•_‚©xSöLqh˜"OÁÔˆ§²ööOå}1õå<ŇŠV¢]Ëyê-¦O­x„ó<µ¦›-Tô¥V!>¢¿&¦lÂÔë`Ên”?#¦æloÚm÷ëöjP«ÂkÕ>ÈÊ ûo³nÉŽpœèÊï•x¹'ñ5öÆÐ~ˆËféfh¯•*Æb¢µö®–Ú‹0ÙVj—è?ÕU¡TµRðª'PÚ;`P„ä#Rˆé8g¡Ÿ“Å_×ãάÑé)¸Á¤ª¢ÕQª>ÙTcpM„UÝD½¾FéOêW’Õ{"A)BÏ¥ÇÄÒÓ8«ü ̱ÞY :,zzT·Ž¢|º“Òª5é¨Á„0þ¬ø´\tS«À<^­Ìâ†UÚkhuº&È•êŠO!o.ù.ÚuCö(±•ÿ š¼£4ký=è0Q“äH ˦èjžyy¯& œü}Plu1mðζÿ¬ËÙvU]LX«ÈÎ¥EUNGÔñŸ¥†óµtê¿…E‰˜äB˜T ƒ.×Êëê…J‡I殬(cþ²TúŽŽÎ©:…5¥ö¯‘­œ '4ÔÕ8¢œOä@… K+„°'ƒÔÛq ³BèªÐ{¹}–äSŠºøªÓød’ø¢)%Û¢…€aTP;YooÕ#qòñ¬R9¾«ýK>çO/‹ÆÒEIêÊ;©ÌGM<'I%’' ·"Ô_Ò8¿é–VaƒEJL×™ÒÅÖG¿”´ÄÜ›‚´"a¿TVCJ©ÕÒÀ¨WO…M8wRKÓñÄ"«âs©‡Þ˜˜I¥ª:E 4ºšZoiÓ?/…Mð,ª0È9à)¶¹oæû_ò–åÆéÓTÊrK “× Èù†浚þ¯j<9‹×Rà •b½DûWB^&M«Ê6üØy-ÌqGÏÕ"%vq‹ƒ¦á۬ñtÓÕÌ*œ‘‡,G6ì0>íØÐ­EAǬ˜Œ_.®Ì¢5Ö~8©d»þè:i·Õ4Åé“iW‚üuˆÊøÌ˜Ú¨Z“Y5|±ŸXÄbo¸ »•¼ÚœYk)¼s`zNtýèÏ ö8M|_j¢v"˜?Ì•«Øœ$ÇIÿÇ/ó§bâ"3ò•l´¬z½z™ºò fÚ=¢+†©…&0Zh;´ôkŠ5œÙjö7c÷¤&9+˜ ½ÅöTôX5‚;Ú·ëÙ~¶ýúÄ!J~µíXêTžv¿ÊNâo9c³Àu¯½Ž§À•§Áå? \¼³Ö(/—Ÿ—]®xfpÙYp½¿×Ñ/—½¸6¿V¿þøs¹™­—nÓ¿'s«NàšÀõšàòÁÕ·µÿ¯®öóÅìpÙÍà²É\v®£°0>Wþä°0Ï‚ë‹ÃÂo9½i³kaáü^Ì•??,Ìs.;Å\÷W~\v¸®9#nb®ËÀõÌÕwØþýëÍj¹ÜO‡zÞÖ¢ D_®Ç„…~\Ïrõ÷ƒëcæÚÎæšõüTÎeׇ…ÏÄ\†…/uõwƒ‹Ý»õ~½8V ýñRü•àòï—4n‘âýÅr®éÜÁ+ÀÕwlÄ¿æûýl¹Z›ø1Ì0ÃÎä΢«sûa²Ç¡?¿ÆDgáÈÚ²VÈN!®˜× yJŲø´„ÅJ3ð…GI}lm2"ÏÕDXí@Î'•,S‹ƒdÃc7**‹G _¦¾ξ±L­qÊØÜ©G"Ã&råR]h 4NP—ªî ˜ààÌ„C+|Ä‚›ƒú3:\¥Ø,ô(ÉÁƒÆFäàÉùüD¦æó_t\>çZ$·8ö­ /«Nv]ØPoÅÜàGÕůCþ«6)x£š:7®ç0rÌ_d¹”á ‡]„0EÄÓõ Vudöö°¿¤Šà¸IW;ÐÍ!ªïñ_!|ß Ec[)?à‹ûÚÊ68Ï)KðÅ–Œíf±\¬‡s„DzZGjB02üWOjÁÙ(áZ.]“Ë&T–¿éQäÃM­<`•ܼ! ÿsöîYå¡Rˆkñ%™¯öœÈ³ßÏ$BðY\^­ÿ¡Þaüzuç1@WAï¬VMu}S«ÆG:@Í3[++æBBpG®¤øÐ|¢×ÈÙqT­¹XòœøÇ=xjy.0‡„ ‚ùÔ\Ð00í^ÞêMh‹eC [+”˜ `ÎþÎIR6ù3Ì­Û˜¹*6ÁÉ$— Kà4 1ÛE)¬¸¼»ÜÂ.ý¡AÉÀsй¢˜K]¼b.<§«¢Œ„ˆ€shÁ½:˜\(S«Œ“@ N¹u™fÖ÷ñØ´«¸4·_.ŸÀugp±Cc±ØÎÖ:#×dßÉ1„þî\…¬q¤ Á;wZ'«É ®’« úF- þ,péFZq´ŠµþS«NX5=a]ÔǤcå°Ä‚…¡ûãàrX´f•0š.붇šxpEç ÐîÂ…Æ_Ä(¾Îi[˜^.%™§-þ(5`ë¢L ¿Ò˜y±Ôš8­ÿïo‚ž^M˜F ËÂ%hÜ|RcG/Âqñª:ÇÊùÜ0Qº€ƒs9ÌGG3æ°ñ=ׂ¨iR*Ç›VMB´xuúáuÍXa, Û¾è/ø/¬?ÚòsHú öws=RèäJpDú[ã8§fh¶qy-]XÙdúš¸Ï|µ_¬#;;E>v3ùØùØ7ON;ò¿0²Ë³ä“ï’O^D>¯°#Çã.–«Ýl»žÀ5ëÞàòß\;‚k¿Øo¾²=о\¯“6}ëŽüoN›.×÷§M€kÿkÑÔ´ZovË™ë]pÙ“w0Ù«·~È\ù5à²zïä'ÁõYæzpíÙd±^mW«cæòG ~s=U© ]ÏÁ\— ~¯îç ×óýlw/5ý™ëÎàúÍ™ë ÂÂW8Kf¿`ε\¯7,U½—\œ´|æªEˆ¾ \ɹüÕs.p-æ:n²8Þ®Þ…¹ük™Ë® ¿õ ¦ßŒ¹¾?çòÁµÀ5:­4……“ZøzÌu ®ü.æZà:}8®O‚ÆMູžFÐx1p½DεiàÚëXwƒ}›±_BÙ´Œ/hg\åþ¹ÖÛëåÚir8DÍž€˜ègØ;Faý3Š6aá©p‡­Aá*ºgÁ@½’3Ke’}˲pÚTr1F# NR\’S©GÏ ¿œ°xØ$,'£f’Ã¥[0Zä\œ#”á3ýí3õ ˜DXª,M»ÿ™Î®2v3ÕpúyíŸÖ e .ÚµƒdÜ¢ðËš\üùía3ü ÎÃu`ò (K~…©1€„F#„…øŽ¬+’Ë-<ÑŽ]3¨ÇîŸvžlU@s œ¥¥=ýC8O‚#ñöA¹ ½¡,\SGè/‡?gêyð g =7áQ­PÌš5åèTâ§‘h<3ÂËøp1ÄD6H7ñÄ_¬3tDíû¦¿ý1Ÿ-«§Ç[Lx»ÞlÂÛ÷à ‡eüc±ÝoÖÓa“`<Æ${|FöØ#xÜívÛùî}ÉÌò}pÅff·hŠw×Óef~\y®|lfö-¥æùlFêZη‹éuvW£ËΡ+>DW>;ºž—º^A÷˜Ïðâ’¬æ‹mm:&¾úH‰X—PM^a(Ë9>yB5Nvo|&\YR§$j®8¡Z2ô¾=¡š•håU=LàHïBµ:¡ZÙ*Ò Œ×¹ pŽ+qÕ Õðsåúg./"øbÈCzñæ„j§‚™‹O¨ÎÊQ”{ôsÓÑUV*piÕ`è©‘ÿÀ(Ù)m794ãS#¥“êhL¬±öX 8<¡:õÌm,¸fÆ þü Õ•6}|B5ææƒªç3œóþÇz7_ìŽOt $E;˜0ò/Žâ_±Ð½e£…Ï!Í4zw~“>‡q8J-£¾㹂÷R–ÉEÒm ßyùel9Mz»9ÆÃd—üë‡ä¨,Ž  MÏ ´q‰šŠÅQÎ0dhR1DQ4Úꈣl”^E‹£8*Ú ƒ£‚Ø?Å™¿þÒi`ä{=°d.KŒç¢Þýžé9 ¦ —4æ(H\¬9±æd@ü™ôÔ.Ô;׎>²8*È/|„ÆQtS¡uÓ¶¹áh[¬´øÐ›:iT+L~@Šmx‰B”eÊN:6P#Äj»˜±q±„aÒæðez³”¬C*ÛàNk­  µYÏfw;æó7ÝbׇO¯\ ë‚¡.B×3öcØT2¾]>•Œï‰®Å€®ÝÄ]OÁ]ß¡jüvÜå_‚®¥Ðµ\ÍŽ2üÛÛŽÑåßwÙݹën[(ï§žå®ËùóÜõŪÆ¸ë’¼«/%ÿýËÍn©ƒªQ ä²÷­bÌŒµD¨¦«îÚ×ê%?ôô6…*þ̼{5 èâúþÔ±ô^ýêÛVS ª´¢Á¥`'d:ª(':ûˆàî†è°¿Aé¸C߫ݛ\fY0ÇØ€a‡«>šæ„WÅÇ:6Y—æD¨½¡7š,–Ä¢#ÙЫͩ3[½Œ³=¤j÷¸’«ÿ¥·ËþÃz&ªÎÇ“ù{¨j®QiP)xöåNmà*¤zfXŽÍê1äŒÚÞˆúÏw‘šÂ¨y M~Èû$YÅšü0ÞiöØ OÔz 8‚k\xŽ?µàÑßÙ9š Ï$L ÛRÃSÃGïRºZÖpU·«roéòͲô+”ö½Óò§œ).cý‰óÌoü5[ÀÖÀ^ `q°~¶òžs,/~ û6€•_g–‹ÇlùÀæ³ÕFU¯ `_°¼`v!ÀîÊ`W,^`d°Ulùb‹WØ• öü;Å`>ì/€­ÿØl½™­æÏ0ûñ öJóËìS9X¾^ˆhlS›=À.b° `ƒ=?ƒ­ùŠñÅ~¿dŒÖ3Òè§Þ¨§zÅøuú—TÀ¾F£Çž”-³íjÕ]Ž¥·­ÝåÕä·Pê.ÇÒ[(u—cé-”º °Ä¾X{[îêül½k\M.( å®îòz×›rWv—cé-”:¿Ko¡Ô]Ž¥¥ÖªÑ]^ïz[î¢S t>ÀÒ[(u—cé-”:úºl¶x{øj±Ü,îÕ°ûŒMOw&¥¼±p|ç¶Œ{nå²{Žo%¥O¶eØ3‘Òö×¢Hiý@R:ÀÒDJßNJ—bé>¤Ô t#)Ùˆ”.ÂÒÃI '£ý±ÜÎ÷T«ô¬ÕLY¡¬0ù?L%Ö1ÕéÚ)D /l×¢FÍìÍh{HT-hÃÅ ›šèh859sß>e F€“$p+‹¦Í 0V€ÑbD“>Ÿ•ÁQAÁc!]¥>À»¹Ö’YroBÆqá*L¼AÇ̱ñ_üÆôÈø³!ê'ŒJ1£ƒ0œZ9‡iE‹…ÑOÕª«À 5ÌH{q9 …˜M?Æ£ñKà2Ü$'œØí¿0:+ mAÌñ‰§¦Q)q`Éð€:î`q.xxEbt“ÄŒd º‘£FƘ åuFY‹J$T#¦˜)QHÈ! qJ žÄ)B$ ¹M´f’BAWâSw° i1”,r|Æ|7€Ï—û5õ† Eφ¢8BQüåÏAÑ¢ßsõ÷¿í7Ëífê[¿Zµ³s R|¨Úå¤Ï©v—+ Ïž }™j—'H ìÆÿ×r»^Ϙü“üðÍòCüht] ?,þc¿\l6ûv žUOZO¨µ`IÌAQ œnžŒ÷œ¯àBº›ª„ÌO“¨Á’1¾jQ¸##ÑÀb:ç!’Â̬«¤@·jÂD[¡FŽu.¨PÓ?i§ -ïj,ÚUðï·¯ÐRE¢$¨`6†õ”/¢$]N8ý\´ƒKR¤Ì†Ošÿ’&SP^ *ä£1ƒdF*ºrG4/‹è*ä3p?‹Ð©/ pGðà _s®Qê{ŸŒ…èTL͸%|B>FÇùaÙ¸4ªä–?a“¿É¹wÕdzMŒ$q|/"z³£Gòf¤tÓ­·ƒŸcTYÿã#lC¸ÖKaãŒÙa%‘zØÒ¢)‘õ_N†04l=ª9•|FßšBbö‚ÿšÌÎ ZN‹óÒoñóY\ÓÞÿ°“1Á ñMwA‹vÀSO¨Â)µ W«ùe(icÐ:Æ9ÖÇPðeµ³’5WsÄ“Óc\|;¾6ÐlY ÍÌLøƒ÷ksÑ"Ó€CëBIذˆJ<+né@-±)h1õêïœÔÞ•¢cnch•óT2N=‰K…%`µF¹×Ř´”7ann¬Î$3/Ô€LÆ]Њ‚ÖH¡—GdæÊ ÁH*sdúE3' YïÌàyQRJL'ëé©y 2F1P4=Ÿ†?‚vÝÿó/`íë\e½Vð¡+s–r(Hàî\'º‚Þ£„gäô \|ÐS’8Tˆª„Ý9ž0ಊžÊXk•Tî‚ÁW$¸‘¥\Íœ,jt>…¥T/rÕߊ¥ÜL¯#Œ8§VY+Ö†L¥Í¥¨;=¶U¶Ï–õC,t¨–¹Ð€dܹ¤ªÀMÁ<Ðá\4¥~ù”›èŠ×YXqâ„X"~¬ÊHœ*8"'”:~XJÊ8ª÷¹ì¥©zpX4ƒàup UÆõ"y®­Ä#.RM¡XªŸ¬³…ŠÛXØ×IzE5OPwHUÇ<Šo9Aé‡X¢–£L¶×Ë=\î"ñP¨ ÞU{ JÙ鋜ôî!šârkÂxCÆFÐb³ìl·ÙZ”}*>ËòÒ¬e›'üÐKÈë5ùvþ¢±V*ÈLÒLêZŒ$±HyQ<¼mc@£³›áÉzt×ìQa¡Æ}¨¶@ƒ·Õø{tÔ8GRÈ*î`(S3aú~°¾‹˜þS.¯“ò¶^ã­è÷‰t•ËkÕ¨S‡‡ Ü¬¢ªrñlðáì†ô¿ŠÌh,A"ÒSH,ƒA ”eƒV‹Á‚Õkß›HhŒ™LãRà,ÎR,åØPX 3ÒtèûShìLÑd*èKÊozD \Ë,CÓ›^&êò6ø×[@È#1 v†¶ư]ÑTûµÓŽé)40"D+]jgõ%MXå.4ªC8- N‹ N·Â)á¿5œâyà”_ §íÀN›+áäœ~$œÊ`~8œìpbÅf;Û¯ RMòú(^},Æ+ÊëOßc±TÅ~¾ßîºv~“EvñÒÒÔoA1°µJàeüµ¼¨€dmÕ±AÑJ×oß,G)c”ûœ –Y^TœÒÿ°3¡6‰ƒ`N€™—Ö*Â"©It#:“Øm4ø‡¨¸‰¤Ghý]ˆ+ÈÍGSÿ—„JGBê2ºOŠÀæˆê} À¬#_fWIȸÃum:XôЦ¦=.)hj>FÏéÂÅ‘À"Eg1>Ïðåæ17®^Þ’‚d¸ž€»ÈšéÉV+É‘S>Éò)9^ÖòUÙd§8YƒbØBYܤ#b!©Î°‹ö`ŠšRçТ;—öÀ('–mpž%üŽèkÅcÙ×ëÅj¶>hc·j ®`Âåš-ø]ç0{ÛÚØáçtïƒ6vzØó!ª 0Èå \f ¤ÚØ) EH䣰Ä.#jˆžŠg\ÎÐ)âzSKÙ!DOªþ{;lcOŠCì=b¤ ’­óÉß¶±;û•x•pÈyqOkc7j¹CúðŒ,Ç‘‡mì„E†FQiµFu£èGBZëiŠj–wWø Ó@¬Ó…B‡ ‚²®lC@XU¢`µ±ã™}뀒ê&r>#…bR†6vŠylcÏÃÍ QÒ­*€YmìÎ’ »ÚØë'Òå$ ŽÛØíý6vò›µ6vøhù8žÁRÈÖÆÎd…[#ª]Çg pz˜âe 0ˆ—ëݶ^”*‡Þº‹5œ'ÕX¹ò O¿nX¸æä‘•éú¬ú³¨¨û¯f®â¾~Q/{ÝpmN¨¸OÎõ3¯w ¢Ë/åÒµn¸!­œ>¥4àèª× §(ð¡K°JsnŠñÆ]‚åÎ…wÅ4¿n¸Ò]".ºa(^áá¨K°’?õ,£ RÛ#G]‚å(U[‰ÖñWª»,$_7 fX|}º]õ!“ZøºáQ— gsT®ˆÞ½".퇯^-±‘~·ùëOÛ÷âÀŠÛ8É­êãœXÆ>ÄÞâ@ùRÏYÕÿÊiãÀJî>Ž½ÅˆŸMq õŽqh¦ªã@RÓq ±DGš°7q`õýú‰8Ð+äf)Æ^q ŒżÑ—æ(—ƒ+L6(´Š¦´–Ô¦gTÝâ@S¸jX¥0Å2”/€™ÅY¼Ê°™q âÀ*R¾F‹³¼ª yzðì¥hLƒÕ­"Y‹UœËQ'n¶8P ªÀÒU`VZ^q Ê©#a-Ã$·Ö—ƒÿøs3ß.fÛ)üéq µ80¦8ðkâÀþö?þÜmëåñ;DnmÌ:aë„rL/ªæIpÚ‹u¨bD§uŠuN脳‚N¸Zƒ¾¶ûÙz¾9›eÉÍ0˲£,Ë>—eåY–ݘeÙý³,;•eÅ™,+î•eÙYÅTåC Îî¢+O¤Xœí/˜baáŠK]†7¦X=º•¤Xa¦X¤ìJ±ìâ‹sÓw3K±6€Ð|¿ZmfWôÚz=ø½¶þ5½¶Ì¬G";ú½½¶Œ‡*¹RÓóê^[œÿña¯-ÆH cl¦¹¨hÒª¿MÉÕ°ˆ ®F½¶y¾×Öå—oíµ¥‘¢…©*.‹49eœPk f×µÛvV®sM$ÓÒI‹Gí¶ yRçu1³—uf«÷²Žm*¢k tíV»ín9ÔÏ#(F‚‡u± xŠ£:²Ëm…¨õ2àÕu(^ÉQÊ€;Ê€ëåf»ÿ½Œ´ˆ—L¢âf »þ¸˜gJ¢âþI”½M¢ÊZã³IÔKì^íºv÷zÍéH9IgÐeO.?….¿º®”(¾çÝëÙ€®ù뀺ž]'¹k„®øùàèú×|¿Ÿ-§FA ÄÔ`¦FÁçņoÜÌA_‹Ùb³_Nâ/Çå‚S8›òùÈñf!Û®×Ⱦœ«œ}I©Ø¬)P\®ô¡Äùøe’VÀe UõÙ$*9ä„tnÔl³¡„ÿ§”s¥Ð±I*L:ÚΩ}Ó¢å0äÔò”nL> 4×oÔ& p:~.‚Ú{(ŠV ˜T± n¥SÔå:Ó‹D4qx ù³…¸ž‘~¡ReéNLR!ŽÐ×(Öë% Z‡ ˆ)ÐæfŠbŒ6`…ìÁêÍ”‹£[hТ”.J´ ûç<:ÒšjFX²3EÁJ&ZIÂ䑬 øŶܼb†ä’ŠÍÔâÄv¤–kÄ„‡*EY^Má Â`DÉÒ ãïh¦ì²WcJÃg‰®v´¡Ã p‰3-¶³Ùrµœ 4Aèáòó"Žlƨ鮅Í5ݵ°£¦{›˜g·œ¯·Õ¢^™I‘cHPæÎú®RdD5¸[ǪŽi‘³òS€á4[ëŒE&†A8+>żŠöÚҩΖª°eC1NBÁƒ3â5b«±+ÆdªL]¢F €“q¡àe ^\dÄ °òTÕeiv Qd«d¹ÔL’A(LCt¦J·êQ®BnNÐ% M µÈá˜W–¬Dƒ“‹?UàŠÙùÔi‚P1V½ò¬dAQ†1¥2¨dÖµ kÀåÎ&õ ±-ƒbaŠBêq¡4%¤§N"VõT9ÐêÍ ”7y%¤Š•ªâø<8ÍÅê£JV+M®¹i*QÕ íØ'@EÄèh4~ •³){‘ÈÖ†z}·Òßÿ±Úíö»ÍÔjAÏ&™}L­ö­u¬™žóš> »òX³ƒ> »ñX³Íf€Öö©¡å´&hq^ZÛZׯ9±Ö­ßZv´v´ö´&h½.´âÙXkß µ²¶ö˜ 5Aë©Xë:hmg´æÏ­‰µ~ hÙ…Ö|€Öb‚Ö­‰µFÐòOAkhÍçËõú‘¯>ÞC™fq£¡ƒ³Ê!>ïgIèÎfeœyÙW Û vQ9kŒ´k<ö©>Üõá²r…Y‹öá~÷Ùô÷èÃÝ.t}å­ ]º>®|zt­º6÷:DfB×çÐe߀®xt=Ý;‡®õ€®{íк]1¡kB×Ë¡ë,wmt-&îú$ºlBׄ®1º¶º–º&îzºâwD×n@×jB×ÓpWNªÆO@[4Öý¾­õºü‘è²[ÐåÏ®OÆ8‰®|‹®¸þdŒ§C—ŸEW¾‹®¼]qº¾çÜ™Ýl@׿+¹ë&t=9wÝŽ®r†Ÿ8wæéÐuž»~t±Qc¿_ìW››·Ûï¹å8‡-Ǹb?Tœ¦Á`Xe»FÙðÀgüpËqn9ÎòýÏ:,OÛrìœ*çÔ–c"ˆ§z [Ž1WÜ&?@oï‚) " "&‡Öqh×€çÁ¢ÑêñåŠ^ºå˜¡5Æè0Û|w×¾Ðr0ôÖð‹j)ÂóÞw×~Èáä›]û;6dlV³Åûïxtbó­ÐßñgÚC`®Î¼Û‡‡;â%L}%^7¼äè&v<é9,Ë'·£›Ln|à(¬›±¬uåhVóÒ£›´ 3‰;dM££›ø¥#õ‚×€R{jÉýU;I¤YàÀEû¬Ãt‹£œFl¸ªwûØ‰Ž§$WÈÒ²æ¢bxón‚Kr”k:Rn„tDŽ!©E½ÛG£KãWÊgÉ÷»|„½&t†{ÖÈû¨6(€õá°½y·OŒ9*‹£¬V%'ÜÁ»}HÃYô£ä§Éú2øvtÓ˜£.$#,Á†Ùÿn0‹1ŸÏWÛÕtö´1ÞK®}Ew&GÖ‡'={Ä@N–;}9£µéìi>RÈÆ³=Œ+Šq/‡ÊPëó§÷=MýùÇb»\mÑ{‘^n¶â¤—KÍjèe¶r<ýy^òF+¦¡¡ý„Ÿ¦OÔµ4ùŒòyÂTåp!°ÓƒòBt¨°Iü˜ÿÇÕì`ØÙàÊq¿“µ‹26à]ÝÞPn¾bu…gš Ó÷iéÆóèî‚q§›×øIL„0çεCNtUÂp*g!2pµŒrëÂ*>®ƒ`ó#.ª§ý!©Í!LȺ\ï²Ö^Ÿ(xûâæâW²ÉöÔ /Ð5…YA`ÒùâöÆKw…ðT¢”´Õ†(Ý*èdL´~žÃB§H©%Q®ˆˆÏSv&O +FÊ2CçJÛlTm¥Ë5à|Ž ¢L³SaÕ!œÐÊôÏÕb½Ú—ƒÉþ>IêSÁêþ²ÄO•ÔGÐZÐ:] ž 5AëJhùÕЊ7ЊׇÖf€Ö¨ì´^¹l´&Öú6hmh®O¬5Ak‚VA+®€Ú—þ¹Y®¶<à“R˜Ó(cRa/¨­À8ËÕO$NP䦢~°)hÆÁ“5•C @‰Ú„SžAÂJ‚àáVº›Ô‡týšž6 £ÂeLv]fñÉHYfUÄ88| eVj*O¨.†Ûaùø(M /Õ…jžÙŽjS¨^q± pu£t[X= s¬nah? É,ÔXÖ} ƒbjúZ–ªÌ¤Ø´¬žj±Ñ‹tVE%K)>%GIíz-ü +~q dj*ROã‚Iutù¨d]¿u ƒ½¾EI0¤¥ºp2 ÊQGv¦PƒåèTŠà¤8ý«&5fü)fôÞª_i=!‹„oÐb8—Em‚Q0ÙLÇ…8T)öBÎvµùÒæ‰‰”Î’R|1)MwŠ÷Æ•ßÅlÆóÚ—«ÝüxÃÕó5þý>èÊ/G—½ºò…Z“³ù€®iÃÕó Ë¦„ê'p×b@×´áêYÐ_.WL‘áCÐÅ–¥ý~·[ooCW>.2ÌF—ŸB—BWžãt›ÖóµÐ•ï¢+/B×g"Cû²È°ï½øóŸ»Ù^ªÆMMëù»5­K·{Á÷dõ>ùž,ÝBM~ÉG&è!Lçüaïɺ¢i݉¶ƒája ×´^'›Ö³5ºw³Ùf³=xªäUxf2N5«'–¦ ¬Sb^‡Š ÀÁIµ&“36ÌGM—I %Þ”-!Ê:P5¼4ì@ƒš¡£ Zð”¦M +"¥·ª†œ_)”Q§e&y jÔ$h†.88R+Å*U£å`v@\*h²xƒ¼MŽY½æ•Ô«N5J6Ë”º2ÆR5b$ÊóŽZh­h©+—5bÍoÊÛÓìYbQD4+ïgŠGØí&Ũ“}ø¬©žkaƒÀvªÔò¤¦TÓ ªZê¸.aú™±oCÔîj²aT@íäd}RØ/v޵ŽÀÊÓÀBF” pGª¼­zÑeÔáRDΘ»”ˆvT〻èJÕÌÒ9´eË¥±ö³"'ÍBåjEä!òp¡Æƒ£ÓÎxS®­x¡"WlV í_êˆ0Å QÕiAÊM褺µ¥SðA¾Èʨ$0ú§^,ï2Xœvfº¹Kùý¡:d”™RDp‰ò‘egYU%ugHž`XFòÈ¢|ÉM-¢ @‡=mRǶ¶œ6ì6€ÅóÓË –Æ|€mXõÚ¬ç›Ë_ Ú noÚ ±ý¬¦£ª—]^õâd|ªêEt´›X-¹ònU¯ŸÐ›ûeU¯9š6þk3[.V÷j‰Ê‹jÊ/®¤;¾]öºâóèÊO¢Ë¾¶¦ü~KÔeè²o¯)ûèBMù¿þ G;Ží± ‡¡+Ÿ]÷æ®; ësÜ÷ç.Ÿ¸kAÙp±Ú¿&kB×€®üñèºc?”_„®/æ®oB•Ãõ~³ßÏ[?ÛŒ 3߆«ädJ/B‚ m 3•[u”í“‚;Ë:ðoLÉ¥ƒjË ÄgHSÉ„=›D»RKæ£LJÑÀ5håT£Y©Ó‚O C¥,k’eû/qÀkq“9=õ6!뚥m(iï*ϦZ•¿§B0.nÀ1)îÉ%ëÛ=hY.pa ¨J´hÆÆp®ygKi/e”øˆ3]çh³ª<ªó§U1P=ò”JÇ@GþM3'ÛÑD³©LÍÓI(ÕŸB/¢ ¸êEêtïËz§•Z_#…Wf5ÈSmú «xXÆN³k*xe}Eª†ìI%DMeÃŽÅøVÌÊ¥M°AÆÁâ,—ÑÅKVê*ÔJÁa…Z$¨µˆ ÆÚÆ‚âáf¹Ûí´ïXC‘©G5|Óoy–î’Uî£V‡ƒ¿¼•Ö²œT£¢–U¢„#×ÓÃN:>MõÇ•;©â {îä¦JN”½ý% ƭدގSc7§˜ §ºÇ…/ÆY®òRç°œ2—R­Jì¾°[IΘ%졈­ð…U³*|…æR«W»àB$äèÓQÇ‘¼¼™JŽâ¸l²a4פ*ht%‹HýÍ+ó†.šaYÍX}d«¤Ëq³Y^ý¡ðE=”M¤#¡!‰°«*é±*§LãësÝ’ åuÜF5eÄUøJíðcßH”‘DɆáå¿J6ô}aA.‹öCëäßÊ4sˆò¢5`ÑðGÐÚa7Êj±˜­K—oƦI&΂H4uÄh­“¶ß±/‘NE[,À†Œ…d¨½drÒ 5ê= @fw]9Š›+FHN@'®> ‰+:°h hå…åA“›G¸ârTÏÑÿ),úiÇI¢0šSp¿žfÅm„+ Ü5mˆ,‡Mšü´úzU7€ÕU|Û ã¼aWŒKñyZ”]6C§å%÷J—牰йa#ª ¬ª J]…4U½7éÒîE¨äz‰?D—[éßÙ++rOnŽè«úÂ…+Lq×J!_V3¢$ý ÉÖX-6Åôa)Qð Ñpe6´Ë ÆS€¡Ï€X|iÕðbö`¿";¦ Gôµ0¶¸7Æü ÆìŒÅo±ªÍ©ê«0‡ËßcQ³{bl90¶zŒ=!Å9ŒÅŒå½0öü<#ŒYÃÏ6xEŒ=†Ç–èÿçr±YÌfÃÖ/NkØ¥ &©YT×PG]ãì+!¹‰…ù¿š0júuÃ.*°ÒTjý”t¹i‡b`™CP#2E” lÆöW×Îe?HÆ>عì6såìÉdYÉ‚K¡ y)!L}Lº“Sôt&²G`k;—“ÉXh¯Öû8h4a~¼s9ÕàÛ¸Vp0£ðš¶T¾ÛÃQ€Óæ“pVžEÉØñÎee5Æ´š_)´&]LÊ«rçJÆ$èD)*È÷²Ù`=XŸz807ÖJ¿"-QŽ,U™I)GÆcÓx‰ƒ–HHÊ"ÔMqrç² Q»ÃR}Áv¤s,Ñ>ÿïÕb¹[Χ×k‘Ô¶Cã:u”Ž3™^[lZ4ÊÈz|•u(ȳ@BÈrô$á'}mñb¹æé‹YkÔ0¹ü Ï, (Á¼Ñ÷³GžYApÄQãjÇ<æ ÑD[‰–Š**6€µÉ>üš3/àd$ûdH¸N°ÆE^òà —®:®]]fhÛ%(” fžs/GU_.TÉ {È`Css$Ò¼µ^]E 9ê-ôC‘Pª=%¥ù§éË^5.ÆÛ–Í´@`Ò.ûí —0SQm›Z-l‚@oO\¥è”‘ªø³*„b ?¨.U—1¥’aE†Ù°u´ñ$¢P€˜;ª·P k­ü³Õ¶. Ìl †)t-g©œ€s£RNƒ.Åÿ—‡6캡Wù3j·Œkc3£ÂGŒxLS›c‹ cƌ儱;al;`l>alÂØ·ðXülŒíuÛö¯?NeåiŸ,+§Ò©¬|ß²²½NYy9þß³Ý~³h§DIµt:<2\6ÃÃGQKðluÜ’Ì£Rzù æ£Ä6Jêâ¬Ö@­e‘ ÐÁd3‹><«3ЯWðñ¸ºQ-Y¥ÿ±‡IÛrL½„ªt¡:í3kk3b'p(Ð)n} ¶6Kµµœ QîXo‡;±’œŠ¥:Á„@çrëªewÅ«RÏnÑ”¦,±¸ ÓØž)y±¦Äµf%ms˜„ËSɆi¡ýq¥Rá’І¸j,-п¡Šm¹Ž}ù.ÿhBNA\‚ª3þ¨µbÂÆJF4añ©.Qﯞ7%ŸªÍš%¥ÞKZ[ÓÒ<@¸YÉy‡(šE‹õlq·7q‘Öìþ{º‰Úu»òˆ÷è‹gµäž»œRE?¢sWÃ}pçîgúâá^¾¢swµÐuø&.›úâߢ+|jtÅ èr¡Ë΢+?‰.»]öMç„®°ëäß‹Ùfµâ)¼zå‡2ÊJ½Aè˜?ä ÉäŒÅyÈ»¸Ÿ:¥¯…Ûõü©c–™Œ)H·>ÊÕ'1wÀ,| |dòˆº¬W~p}œñ1À–è¾Ç£õJ`ÞÕÊ;Îèž:IÍÿŽã¯†¤×+‡6S©(Jsà_‰s‚zcá7Пƒë—ãã±då4uÊÀhU³BòÇß±Ì/ìâ5(ÁÓ{gMБ¦W^j‘’9SdB"bêÄ®NJ;ZØ`žIEÅû­ÞË€°¯œH™QM0ÅŒG Žj©yº[s›’!“±hVåz„þcê„ø{‰2/AëêÍâø̶ɤø÷”±ÆOÃh‰ü¡z±Z±X¼ÜÍØqS±8Ïbñ+¾.Èã×…ÚØ ¦ÒSÂ,%ô?úìë‚òbqŽ‹ÅšÊwŠÅþ Åâbô·ÅâÕz€Ðíý„> !IŸ„ªßâ… „:Õ¿wûåz¾ 4±ÐÃ!ô^Ë£Qy“›1jºka3FMw-lƨéÞÀ¦ßvõ÷¿í7Ëíf?½£äVí¡râª2½§=ØeÚC\¨=ÄC´?§ì=þ[Ðâ»´‡}C×öŽ/°³ÇèæO®ìñÎZ¤<…®“ÊžŸPö´zwB—ÝO7t]©›ºÖ³]ÇU©‰»¾‹»T“¸ë-ºò•¸kÍ”Ì绵ts›:'.휈GtNT=Ž£yÓ9\çÙ:'ü7ïœX÷Õ§ÿí«í~¹X½·UÑiÆIÆ€%4—qRÎnULukrYðÕLéß%[ÙàǧKñhÿp@=‘}ЦLU‘ÏmU”³‚М$ƒ h”M8…Q4E²è÷Ù­Šô‘ÎÆ9ys“õyÛp”5~Ä[ÃKÇ‘4£võþã­ŠP`Ò‹¦$“nUdZTÔµÙ15øE­¤5¯*HÂ!7wõªQ™,¡?­†OE8ã²IbD ráSt\.•ö&—¬²!-ú½—¬¶A¹†yDS+¼#|»›oêH¦‡oR,iJ±N¦XRë¾'üæ‹kñü†_®úz÷á‡ôåïÓ—5ú²¾ÈõïЗ>p}Ùú¢·:¤¯Ô™,¦SåX½šVÑ© þö;`ö†&ZEò§šhÿzªNöÅg ¶¸Û3ª§–QXõê2uÊþÜaÌÉ;M´,»ºφ&Z„álH¥{lM´ŠàŽšh#›hûg ²uAZ…ƒ&ZO±‚šhÙLÒéâ¦6…šháÛÑ—Á+5ZjóÚ%sOkM´ÑšhQZ0´`»S¦ ç“©,(ÄhúW7hú¸‰V«ËÙ¶Ý0Ƚ¤‰¶ú^;„/å›hmÔDËUw?l¢eokgµq²2«qm M´šeËÑ5¸TYC ´{Ôz–©p ¢šh/°¥G+“hM´IC Ú$™i@×vÛnç‹áuàÉ ¤âSWšÒg'™ À2Ž·ÙsƒV I¯ç6h‰Ì¨H1×n³Ou¥ÀK^ºÍ^Ù‹Æ"ÝU´£ž)Ò!D*þÃ:T´]_®äJŽ^ ÂS‹E_T/Rç¸â%Ûì™a›=U•þæ—@ë’€ð‡BëBÖzhmhÍ»š3¬uq®u)´ì4´ÁZ÷ɵN„vM®•S®õ¨\냀ðnв´¼<ÿ´v´„îA “ã'¡åŸ„–[®õ €Ð®b-{±\ëBÖºs®õL¬µ µ¼«Bx[@øÐ\ëÐÊ'̵ÆÐú”øžŸ`­C‹#úl®%3<†Vÿ$lš¹Z’1NBk9 µú ´´ýàŒBx­¸”µâ^¹ÖCY˾0×:f­ƒ€ð6Öò;„‡¬çXËîÂZ~Ghå 5 µžêZ—@+ß͵>„V6hÙ;¹ÖyhÅIÖz/׺ˆµî–kÝ(cüܺÖr1@kó(ñý £A«:wŸZ /‘1ü%XëkëZ÷d­{„ËZÛÖLˆ…帹«*¹qÄ+×ðT«®kÑ›V]Óªë…7ÎüÙV]RÞe­º®#$>ߪk….ÎûÛV]¢‹í™jÕµCtÑvë\R´êªGk'tõ_·êR$²ü¸UWÁþBô¬Y‰±‹ó{Zu³Ô2äË|,*å\ö·­ºqÔªÕªKûµê >€£V]×Ъ{€.Ÿ”ÃjÕÍ“­º)Ë?ѪkŸhÕ]®t /Å¢ËÁP):@W¢ËnD—B—½ƒ®x]ýok„·èÂzŸC—ºìÒFx˜ªˆ®¸]S#ü 4Â/׺F[¹RáxÐ8€)xã #öveÌtÿ¸,Â)¶sÛbR{/é¢29ö¬0'Q»`GgÅz¥ç´ŠRغÌ&ª@@Å!ÜÁev´ƒ«Å9@ fÑñ~oÉBCa1Á8dBÉ;ELÂR*ö|ƒ%íà*(õg d茘¨\°š nrl›Jœ9]AÉy¼8£.`I!ã@:,}SÆE(1öìÅþ“Œ“a)–˜‘˜×.]T½"ÇŽ›ˆelº]ï»;¸²R‰NÞ"*¶l­2mÅ$ªV(Ž:H‡˜N· vpU†…m©c,¹BÑ4º©a—3ýÓù‹qb!‹4 ÅCÞÿk¶ÛÌ7³!,TnF•õå2–Ão‰¾~Õ:¦Y¦£IÈ)fõÔ¬f¥w0æý‹>‚9&cîJ’ž™±BâÚÊB¤Ö­]ÑTå7Å”!GaÄ íLYGrZ`à§+˜ÇÜS®&*ê±™auÆ K'x„.ñ¿Jéú‡î*)#ø“}„ÚîÀ,WÀ}ºÄ–PÞ…V©n ’®t9¥Â”¾=.ÓU¢%‹°šËr‡JšM¦/2‡¤»–PÄÚ*Öà / ¹3*ua èÙÈŠî~¶ŒO’n!”÷0µ¦adiÙ†Q'“h‰¢ˆR¤°Ö"Ó÷5o&Ž&°¾Æg±¬£èÄ£‰¡Kµãýv½½C üˆ7ïØ–‘w*p}¶ãÉß×3ìJ=ã÷• ãw‘ WûZ»w åïB+×ñt×fB÷“R¡½¦TxÜñ”GÐ*—ž´*Q{O*ü ´ò„Tè_-Ž¡eßÒ–ñZëÙ­÷[àícÖz³»Än*p}­üZö.k@+¥ÂÇãjÇCöõ>Ýx‘>Ý3ÐÊó¬uZþIh½Qá×ó­Ý›øƒ€0§€p §€ð ÖZ К?ª™ð Ö²SкWǓԨg®÷Óðm¬õ¨Ž§‹YëG5®—´[àíº€p`­·Ðâ0_w»ñ§Y«Öm ­[XË^Zq.ײ[YëZOØL¸^ ÐúT üÇ;ùoɵÞBëöŽ'{d@X¬e­ÓÐj2üíКZàïÊZëZ«³GX»!0Ý*x ‘kLGXsyžékâÊ8ÉH‚IÓÖtˆR/ª!†~•cÕïs„õr½0¶ž0v1ÆìÙ1VÝ_=&Þ&Œ]‚1îí_-æjÑ8"¾X¥ËÎ Ÿó–±5C]]éJÅW X†f¨~\ï…ˆƒú1 £8WéB”B'ü!¢R§·!¢Uˆh'4C­ðaˆè‡ˆÆþŒãì+>ξ. /¬tùU!â;{û×»ZÓ ¿½ˆüxaã;‹ÈüÜ lÈÖ†(±e_ïBëÞûMüâìëNEä„ ; -ndêÜ<úý‚c3ì´ö´Þ›‘ÇÐ"O5hå±°a|§Ç!´þ‹ ïTº®+"¿-‡‘¢~êK(dpg4CÆ®1ná½\Ø´Þ°–3=6Y+‹µ¸:~­(½e ­AËŽ4ë §„ãàðŠJ—]ÀZñ`ac3 µ<õf“líðÞÚámh‡GŒ »è Æ¢.èEG´nGDϧQ_úÌ›MìèÍ&˜úP_|¿~}ñÔ¶¬m1Q@PÆ}ñTâýÂÊ2ä[Ú›M<ÊüÂUíÖÜ4P‘¯rÜòÍ& T\eÌEYDŒúâõåê\&·v®/>\©Ž½Ù#²A³Ó}ñVWžz³ \и/žÀÆÍiþ¸X?|³ xÓب/Þi5 TŒóõf“(Pè‹·ÚÁEi€ÞˆtuÛMª«ë²7›Èdû ÃìÛÎñäÝv¾Y/øä2mÎ$¦“ð7¼9™±ö³r³ÄíHÞ *À›7a%ݪÀv§—  Ö¡˜ÈåšËKl çˆÁ|Ä`-ï"%ä]| ò(8”Ž¥ÐOýð— Ó®M{ÄF võKpÁêïÿäl °µà0FèB¯ÆŸÛÕfÅ·.`)š §™òìžå¸ÈntÈH{éEJô-ºD"Ñ¡é!8’N³_g¸ˆ '=>`I2Ó¨¤Èá¦LP°ë oP®Í®Œpãèè~ô;oˆ¤ˆêr%*¹· EzJ– ¤i;öþõÏ졨—vJ­¼Ù@K ¼~(´ñ "™ÙPA°öâ êSÅ‹àæ eƒ>ÄzÄÝ«‹ÀúC¬ëÄk2ŸB>¹3¥êëüOIðý}:†·å[nGA'Ð3¼I–%9LKGV–üÃÈ¡) %`` p²ÆÅ`ÐðvX\³A•§…1Ɇ6ê$…ZªÚ©×î¼tÆëéEI…`8Æí Y-!°ç~½×iÚJÉýŒt]¸ƒkEÍÜ**2æRŽM¶œŽ0ý1*„¶(ZºK²Y!8=c¸<ŽÖ0˜oKåಋ\c w^³¯Ôg(¤G…uQŒ\;–¤+a"–éθ~Ê¿è,F\Ãô®€NÞ]§a@OÒ—¸!¯<±1»AôÁt”.eP;‘É!Ü£’w&µï*/- ÁVާ-!æ]EòkT¼äÔ*y™2*Æ=ÜåŠIBµÅå'$^3š%‚Hÿ¼vCs™3° ŠD¦‡ä­l‰Á K8MS";Q=ªVÐSë`-†ƒm;#CA Šþ–Ñh2< …N„hhgXA(²ùÏÿ˜ÿ>”û¿ËÙ\[°TiIm½”dÇä‡̇zôÿtª ²"îZY€;I ô·Z'S¤Ë0¥+¿žŠV[,Ì*Î (Ì­4±3iS˜µ2VæˆB¡®KŒÑƒt´þÈŠéUB3^à›BÜ$çê…ä-/×–ÐP9 zøh¦ ãÎYÔLœsÆì—Õ-þãdG¸ m`˜ðÙœb%^ƽÔDÚ­WÚjŒ`‘h"ë ClXñ€¦"šmÓˆèv9¯`HþIñ,wŒkÖ™D(¾/ô5á…ªU5ùDÔ8˜„;Åͺ„yh=V%/t;²¨²8Znp+‹ÐÈé„e5 üñ‚,‡ñvDgU=ŽWî¡]‹V]YY˜—N…Y§aT²e#<.~-~ÙŸ¥V»ÍjBä„ÈoF¤}‘y ‘q"ý›¹üµüeÿ™m·+õ÷Nˆœùã8òD~7G®~­ ‘Ë+9‚#F}+QÛ¸ŽÈo…#y#þ Žöpœo…càª7ÂÑYô» ŽÁsgnƒc¯ ÞH˜˜îf8†Øæ&8–…] Çõ¯uÁq3äDSÈúÅ9Ââæ×æ×æÛí|=!qBâÏ UÏÊ9yý í-íÖPuûkûë‹íj½Ÿð8áqÂã÷¦Ž ”;$¯ª¶n'ÉÞK`êÃÔ±£tC8ÚÕn‰•b=·ÿZCMö†ql ÒØ3†£Y¶Þ3´– pä0NÀÑÞOí$Û¼â‹oSÇþËFoƒ6„G󎮫+u” CÑMY™†Oä¢ ¢Á±9ö9ô­epY›-™Ö›%EöwŽ\×ñ˧àXýrl)ˆº{?¯•:>J€ ŽYp´C8Ö'Þ¤ŽvGt@µë|”:FÁQ·ª~Iê˜#8採¶Ž¬Ô[r4<µ ¼G;:Ú!ã}8ŽªÛ Ž?ŽñåpŒŸGûJ8ŽJ»kàxˆÅ~¦oÆ"ƒ ±Ø7c1\o²¸‹Áž·Û°Hÿu#{8ÞŒEã.§Û°Ø»7S#žùV,"/¹‹˜ó~Ø7S#BÎ[±H#¹‹}‘JÎjBâ„ÄŸ†Dÿ$ÚmHÕ7® R',NXœ°x_VìëÂâú £ÝÇ)a¼ŽÏ0NúÍ­ c_Þø¿«ýlwU:©7'0ÞŒ»_»ž×ëÅlâÆ ŽSíuàhŸ†cÜ Çý¯ý¯?þÜîÖ›ÅUpœÒÆ)m|´Ñ^)mœÏ~ýõÐ8þ'rüy•Æür<«Ú€\²çÕ~¾ØîªÝª¿ì!9køm3dNEò‘zP …ÍŽÚâÄäÀ5mÍ‚MöÓ N0LKÆIç=“H ¶ÓŸ’[ÀѫŦªˆY@L.ʈíú/uï1ßkˆ“U¸Ž!Ñ]CÉ㈴O¼U@ÔxNÑ­ú#p^Ï›†8«†¸w€XýpÝ) &¼(†¬{ˆœWãŒX~D€hc f^Ì|1··ž;·bÿ°jËýFB£ì¢7 Â\ÃF@äohÒˆ&(JyÄÔ‡@\ˆTçï·¨@…xâE;âÅÓý©„Ï!1Gí¥ŠÇSý©Ú”䇼hö§Æ™½T¢„³p<¿—ꈹN Ž'öR¥Â 93pLòbžåÅqªóóto÷RaJ`;šíãþTLýŽöRÙ›þT„ãzÜŸºûæ­öa»x¾£½…#Œ©ÆçàhÖÚÅíc€£}ŽqG¿#ó<ý#8ú{p¼¢]ü8Âæj¦Ï‡©W´‹Ÿc¾ǯßÚ¸õ§nϰã—Àñ¦Ý?„cNp|‘Æ›;nÏlü?¬"ò>û© „fæýx5ÆˆäÆ¤¼-^=ÚO~M¼úá~ªsˆüêýTŒWûOuÀñåû©ìgï§ú‘°u"Çû©NÆ«1>>n3&È3;ŽO"òîy É47Âñˆ ¯ƒ£Ý=}¼œ ¯>Šc€ãI‚¼Ž¿+AÞ ÇÓÇ#8báxæ(Žç"Hûˆ s"È{ä¹ Ç9ä gU‘gNX}"m YŸ‘SÈú5ˆüìÿ°Ú±[®÷k^s-Çè¬ïP‰W±Ç®›«ÎÁïÚâ5p­`„~T°Ð˜˜.‹˜Hó*Üš>ÄQ ¯áš¯T¸îPUÐÛ#ä»h~>nÿ1Ú‰!b“/A$bŠg‚àHt%¨ÆÎ±`¥aóª®ã“ZbÜ„ž ëìpmxS'.‚‹gzpg9Ѝ‹ÐÂ&¿óñ¸›,Á¼îÜßœ%Tb—d°n«I‚¬Ì Fü­ù'ª¸°øF¤.ÇÇu.Ëç\¤Þ‚Ð;´Å¯?þÜl6³ÍäÐ^Ü¡ùïìÐrrhÏæÐü{ÚRm»üœC‹ßÜ¡ÅäÐ&‡69´ïwh«J9S„öÅ-~k‡–SÊù³Úw¤œûo´aÄ¿ö«ÕV;Û MÞØž"å9ëÐ0Ê>á~æØB¹¯KJХТ³Èa°l;¢@;>ämnQè_‰Må—J2‚éö§å6—öˆ»pX|wlâïTäéŒ1e”°¡Cšö¥´`øýÎ6Yh?OXƒA´Úú"qÆfï`{`s¦#± K£tjÀI‘3…ëâúot¤Xiî¢ ¹"<…”mì¦K¹Ô01«|f H¸ì¯Ä§zÍ£k˰¿ŒË+OŽE°8²:æ†MÞn‰‡1ÞUž‡Ïz²‚k5С†ì(ïs€ÉßÓakz"À™Ž'Ê¢ ¤Y>ÚäL³Ïþ0ªÚi£Çq)Û|Õ áXÃ'•é9ÈÄ΃…ðcÙ¯”É“A&œs7Æ@Ò¤ñc‘!´wpÓ^««Êïqã ¾UF¢¥)c“YbýM1h"È ÷/™ý÷~¹ÔñbB°s÷NÇG:æ•ø–™PAè/,ïâÔB°¦¸ÜÏIÇr‘!¸íç9ƒ`€Ð›CjjDPCpˆ~Œà~ÛaŽì…à(œtDrG‰aŠ a¾ˆ`€eY¶¥n2ödóDù(Uhä(yA„X"ع$“fM&èùcëHCpêÕÑ,ÂÑG;\CÚ!‚é“áäÁvˆàìŒI@gYe8!¸ŒN^Þq„`nƒô‚­œ'ìöBp6Ó°ðªMŒÖBšâ‚£!8ÚÇ0ž·Ö¶3Þ„AÀ²V2I´$½Ap"˜«E ÁÎèï ÁÜ/#.ãNK"¨!x‰ZÖv5ÛpçÎÄÂOÇÂ9±ðÄÂçXxõ†ÿö¯þ0³ÕjÂðSb˜S' O~Ãë¿0üÇŸ›Åv¾›}†cÂð” O¾†„7½ õÏå~³œ-Òae2J‡),2mÒa¬LŽÒa*¢ ß[:§h8Fé°µtx a&‹x0"˜7µÖ™œÀ. á–{A˜?!„™(ÆQ:a/ „µÒµd—¤Ãù&¶£tØ+½ŽJ‡GT:LçIKæA¸tÞ¶NJ‡a‹£t#F: oloÒa¥Ãya“ a>†„X,O4[AøÝt¸žèÂñq:ìC: PŠvìm:\=ÀÇépT:, ÃD!'Òá8›«²Å °ÜŸ05†0/éax{+Ÿû~:¬ªÄhxû†ÿþÏí|¹Ñ‰2S(ýpöJÃZ¥ç§á°s¡Ÿ€†ãÖPú¿íïÿ¥ÊÒf5a*°v\ûíášSu8Šh·ä×¾åìù‰ ‡VÊ*.”2!\ÒtÒr+…råMjB^Œ¢aR˜c…´?_IÅB9ÔJQm;'’®‹ŽÕk…;p• 5~\¸æLÐ¶é» Êìj‚ ãü¸&YåUZ]6H”eп֙EQL¬sA€±ÚåôB8),0n>hw&µðQ3TEU­Ý›Ì^ê4ü&Œp†¡àÁ¢u!"õK¹R ›ƒ¥û@]Y¤›y°s‚üËz¶V°bíÔ¹ ª´ ¾0ãq,…[‹Ì+ƒá’á% ½BY›‚ƒ'¹€sñËþX.w³åîÁ™8ΘÀ/ N»78ûøÿÇ|¾Z®ggÀ©k_ NÆÐ89cöpbBFàdø×ÇNF¼Qଵ?§‚ÓÇàt¦,Ì1P¥6ÅY¿ž¢ÒLšS7|)yIÓù£ÉœœYÁé‡à¬í œ ù­šŠêŸ8QÛ!8­œW%V C‘ô`䦶¬§LtÎ3³€™ ÀN,+Ç8i'˜ŠÈg?S8…Ĝƛ½Î~jÎ8'âzÚcHm3ª•ë8mÎ|Î$8 ÆY¾›IóÎ&ÏQàtmÌ,pª+âœ~ Îÿó?Õþ¯îV³õ\{€Þ˜?ˆ.¸U‰ám3Mý`ÁÐ~æ’ý.mkîÌÃåB hæW\³ÞjÙ&‡"=üž˜½€)ׇˆ=¬ú¨ÖÀê;ãGòKŒ2¥Šèï3Á ÙPqªqÑû™Ë"[ò½éöJŽ“öCaAýð°}šÖ²¯–ÂxW€Já>|ÓÏ%p6%Â`¼¼!ïEKØ”Y6ž-$áx'˜í FY;íL:•R2ç(ð̦† ¹þÔ5RîKÇ¡%¯ˆÅfóÃ%ìz@RÍ»Ø4èQø|Lz»ä5ü ”¿$`Í˶(Ï€xåì*mÍÒÒðtœHï¤w9‚¾«Ÿ°ÏkSÏO±¢“`ò¦Ô´’W`u’ M]3R£ãl„x sBŸÁ HFdÜ¥¬RfOßɬä R†@¯óL¤êRçtû˜w¶XÌÙ(õzÐõ º¿ tc‚.¡ûÿþýÿëÎ7›íN;ÉÅ)-Õªã[åmÇ Åè«@Œ ‘Mþ5Þ”qBxéըͮ;Î" e| [ù!…fŒI¨,ô9cDÞ•j1案$¿`Ä® @ßĤ¹Ò“VY‘0ªÎaÛŒ†v00œ¡N;3׎Ç»^ñ.½–Îüp†V6AS™‘Wr¬Ù¡ò‘NÍP˜‘ 0¨À¼r告­ȧz8U‰2ÑFˆPð<Ä»V{j¸ñB+Wi“WYBk†g`D¬(œ†Þ)$Í*^ •ç CóIõ=èöôv4:æHI¿•2Ó%ûAŸM–ÀàßI2É´ž3éU¢TfÂH¤Ý÷?dò¢›ÏoøÊÎØjò+ÁëJJP¶êqÀůïwóÙìÙà?~~ül‚ßÕð‹Ûàçß¿e¿Ù~7Áï9á7±ß—±ßwÀoõ+þ¹šmç‹íÀ;0'~7Àþ ®Àù~à”ÿý>€ÀͯøN¾ø€9p Ac>*ݧpàà … ;… Ë)üÍhŸ`>3ý‰pÿëïÿØ®çóÙbàï ÀÌ€Ï Àùì×ßþ˜-×ëÍD“ úÝ´ß0 œÏ ë “úS8ð…ú`æ‹þ¤®Ýv³zºN´ üÿÙ{»Ç‘$[ðÿ¥‘õñ2€•U¦Ugwõtu[.ªö%Ñ÷âÞ½ÜY °X`þís*" …¤ %¯©éÊŒH§»³cÇÌËòuµî–»uE`e¡×Gà JÌâÍbà'#PÏŽ@¯JÌÍ"Ð#pÒJLoÖÙn«i#°ÆÀ;@à”½v5°]'ë–ˆŠÀŠÀ—x±¸7÷ÇBk=prœ@x}nÛÚ“6QJEàíö¤uqÖql‹¨RèDXCà»(3àp¤L·ív][8MÖxÓ\ Û"Ö«å® ¡`€“ ]€ÿêñq4Ìe»²¥°FÀÓè· Àá•U¿÷ýzUË~“„ßûãŸÌ‡€öÿúñ¯ÿýÿú~ðï»8þsÛ­ú‰îQz‹a]§bñá ÍÉXôާbÑòðíc°XÌ“XÔøò‰Xô°®±(Ñbò‹jG`q°ë“±¨q ë‰X”á”ÐS±hqÐç‰X”8¡ýE,¯úÞ-ºÍ^(ô«aOî2ú»BaMß /Ðz™P¸^€¬ßwÝbUÅÐÊEŸPf@¢d&l‡c²å¾ÛnÚËnЭbÌÉüŒèó œçù °Ë­—m‰¹'Ö¶Ð[D %ýÌ\æùËnЭ¬œe\}Uˆ¹/Œ×nÌÞ;.»æ/#ðbyà:O ½l]þžXY詜òöÀ‹!pC..»=ðžxZèýÆÀkR³—ÛͲæ5V~w?¾~[m—» ŸYO¬1ðÓh3B`93»¯¼Z¬RÌ !x±Dðá_î¬[”j¬ü vìÚvÑVÖ‚ÄÍ@ðI*øŽC¯_l—?~þ­kw«ÍeÏŠ¹'V5æÓ!x(x9®‚õ°Š Á ÁÏ€`Ÿ¬Ý¡‚‚Wχ3 ùú–˾ÂìžXÕ˜ÏD `8s ‚Ýe]_XXxõ¸ŒØ®Wý¦+o Ž™ÄÀU °ëÖën¯ áõ°˜‹"Ð+/œΧ7m8·P¾-ÚvÕÝGw¨¼‚@©1ð8³äí^g¶Ý'k ü(õ]”Ë#1pÂyàzPb¾®Ö›ÝjSXx+1ÐfƒÀ /|@àÑ,Ô*Ï­…Úh@¿O^@‰y~*‡Îì/ßw›]ßW-tf1Ðk <7¯¯Ä¬¢'æk¿ìÛ;9¸é†XYè%”˜+÷…®Ú5^~Ί¼WÎ4”8bÏ·z~~aê<øyyà]#ðêyàÉ1=1ë~wü915¾@`á=ü õ« P®À)ïNÒË =1]¿kÛÊB?/¾Š@¹¡è“×Î{ä«Íº«çÄœ-NA‰‘I"ð ,Tì2{#.ÑÓµ‹í¶ž:Ñ8«€@¿>?½ø2["p×ßZ8%Æ/‡@½xzà…bàP‘ÿå·íªo?'ÆNA Tz}>¡xÓ”k"p¨FüüÛ¢_õc_¨×xá8z!ž£"«;W®È÷ëØÑo׋Õe{b®'€ÀÚ™}õhg‹W®È÷±C÷eßõ»×{b¤"ðÃô¯ÀBÅ.S¼7Pbºåv½¬JÌ4µÐËV#ìÖH˜ÌE‰A=p³[,/ÌBëÞˆ÷ Ðk œ`_¨_ë¨þ´\t»åe;³+ =9N©~B œn=põÀoÛõºÛ>ïJ³ŠÀŠÀyÆÀù °XO­?ýfµP™gS‘@`—on©¬¼Úl¸ŒzàrÕ-û‰+1³Aà„êò),T¦‡À ³ÐUôÄ´›Õò»“>-ê¨óŒWÌýtŠÍ©¸îGN|oÄMU#¤"°Æ@ p="p–oðÔy"°ÆÀË!pf1p3"ð²§Tœ>éX;³§'¬ÄìFÖ3³Ï¥"ð3xb5®7 ìNj—Ý…Ojº7^+ZEà•bà…ØÆ™ÙËÍr·©'5ͬxÉ7·øÌxŠüÅØ=ÄÀn·nw7Z¸ñXYè”›£+í×v³î÷ßàé5^ÓsC Í6\ŽL%æ„È•y ~þ*ü,ª5'Â/ êTø=|¡9~o«9~DàiðÓá˧ÂÏàN„Ÿ`©Nƒß`Ê'Ão0å“á÷0OÍÉðŒädø=üµy ~«~'mM’JAŸ#°–">= |BA§[Žßôý¢Ê0·‚Àã(¨~~1p³xt[¶Uæ´$Ð+_D LEÕ+#p3–"nuk’Ng–a.‰@Ÿy ´“xmºcàDi’Û‰•…Ö<ðw#k1ð¾c ß/ÀB/ƒÀíbDà­²Ð[E Ôx1pÛŽœåÖ¤I"ðM-ôc”ÊB?#¼Œ³bú½†;R8oZø)búm ™šSXxµ<ЮÏBqDŲëVë÷T䥲ЊÀDà'(1k"p»]t}uYEàµ"ðrÄ2Ÿ…^Ü ¿[ö˪Ä|^ ´ŠÀ;».¸]®w]w”9"ð¥èûôŠÀ+ Ðíª/ÐÝ-KWÚú^Û"7Q8ò!úÌ8º[}¡—Ý1 ž!ê}(1sGà‡bàUؼ, ­Õˆ=êý!ÐB Ü×#ëKä§—ÞߎzŸ1powÒD÷FÜ"ï0^•…Êùè—B v'íVívU*¬¼-Ô#ðœÙ~^îFNüµ-“C M[ ½oΦØ.#×mŠy_þÜA¤6GBõ R›#¡z©Í‘Áò R›# J,>Gjs$T"µ9ª‘Ú ÕƒHmŽ„êA¤6GJ6‘Ú ÕƒHmŽ„ªª6GBõ-¤ÆÉÚßÛ¾_´—}»ÄíËJWÏ,í‚Áòº*W –ÃË®¿|_t«Õ…_7_!x2å> x6¾ªÏ3Æ3íc’K@o»^,»õ…ßµ[!XSÆ©¶Ïر¼HŒþ™ïÝfÕo[¤‚S‹‚³‡ |:§{¢E»h¾~kw«Ý~é¯A¹K^# ~¬‰tÆQVwµO€ Î÷ÝuÝÞëv?[8=Dï( Ásô°a!NÎ_¬]\ŠˆnFÖ÷íV~6?m®Dt;Bðv3Í›ˆz…àÑ¹à‡ºØ®¹Ÿ°]ìBŽYµÛ]û¼‘Ô*«s$eZ<Ì›Ÿ‚íÐDóËoÛÍfÝÖ3~¯FD«seN÷|ö øíë¶ívëZšŸh¬¥ù÷BPæÁ¡AÍ~[uÛvw´cûôÏA›=?˜ ^UŽé†ã~ùuÓ?PÒËn*¬¼2} ‚:¼@z¡Ù)(ä:Ÿ†Âæ¥NícPØ`éNCaóR§ö1u‰FÙ©} Ïñ QÔ¾ï–]¿«Ì\…ðêïã¢5¾+Ê…¸èÑ,ö?x3î‚Ûn³©ŠÌTÓÁ ÁÉBÐcØâ¢ËQpÛnV—=bæJŠŒÏ‚ŸÉEo‚Iíúéà2ÞúòSß·›åæ X£àŒ!h“* ^iËàrŠLßïv>â¢ÑkAÐf ÁùÑs@°êüz¹é7gë„TÞl”éBð\QðZÜ‚ëv¹®‡^­AælÔ›"¢WÏuÕùU4ÈümÑ·íjyWoÕ÷APΫ3 NAŽY 2ß~[nþù”³+ä£`…à'炳‚`\t»]ô~%«rÌÝ炆à¹rÁ+)¢«%¢àª]¼ëEØó'¢3‚ày;µý. x6ÑKå‚«€à®[ï¶õ=¼3#¢^£à-ä‚CQâÛï‹v¹îë~¥«@Ð*½7Á¶kÛö†Žµ C°æ‚s… Ÿ ‚{øÛŽø«!°â¯âïò!ðQüÛø»l¸?ñ'çŸVüÍûñ¯_Œø«ÝÙ3Sajü{?þ|bøkGü]õ…Jz×ñ¯â¯Æ?à¯ñwÙ³CÏÿtêø»^ShÅßsüÉüM«¸‡¿eÁ_W ñÍÿÎ[ˆ¯ø; þü<ø[øû” ò÷É?kü»,þdÚUø=üõ#þºÚSñwøã<Ÿ=þüùùêýzÄ_=¬øÓùåRñw=ü·¦[`ºË¶À|e‚!p¦¨T¾‚r$Ç.˜nÄØ vŸø[]0Ýe»`vø«*ÌgÆ?Áp>‚™®ÇF˜îª0µQ!X__{aºOé…yA»V!æ²QðdjW®®Ç^˜å§ôÂÜgœ)þæ§Ž¿Gñ/ŽÉþ²Û¶ínâ{qõ†ðW)è ø“ó©0r"Õkgc;Ìòèv4ýÞR|k;è{CàE„˜óe{øC!p»Y,¶{ÔàÏ?9ÞþÎCAë¡Lg/D\'|7ƒ ó—¯ýCÜ\§Q!XYè xJôk…ÀÇ\޼l-âÝ”ùB°–ã§ÁimÊ} Ám@p³è»Åek5 žˆÞíî!¸!ø)ùK@P&Ák|€ ùõO­üXýøå×Íj·[G[h4½yÔ-ª­Œ;~Î…†= þëæñXpÁÃXXt,“€h:œ +CèAã`aìJ›4' Ùb© ¦<üf0µ±ì…BORVŒÙU\-&øÁ”‡'tã‡-Å„Т9¨„‰ ðx²°ú¾ŽÃCK{DJoˆðøÖð¹Áå*qN >,Cñ€|òp1anÀ`Á!¬Ê>Ë$}j ~XForÕcšˆ0:,˜×pqÈ\Z0øài1Ã|$<¨Ñá%8p:heAv!(S†àPü½_­WΥ¯¯¯ûñÿ¾u}»[]€^Xø¹ô)p¨Çÿ¾^õÝ•3ÀŸTøM~2“ø·ú¹ÙmH 7)Àœ·1'øí 0rã𛋳è×wý•áW£ßgF?©Ñoðk‡Ãaäëb·ìÛZœ\úç €7@bjò°Ά‘?¶›U¿ÜÔ85^0¼# :í8T ~ÝnÛÕ¤jð•ƒÞþ†}ñòëvµÛ.úÊA§–^ŽƒÞ“:mºNfUèÔðWèíGÀá-´«~seüM¸!w€¿9Å?ÿþ>ÿüÒ=0ƒ úå{ßmÚíîNx¿9àǨÎ&Î…vmDÀM¿­uÀÛa vSðƒø›Á×%øj Úí€ï¶èçûÁg3ßp0¯ýÖí–ýµ7 Uø}&ün»þ ó©ÀwCÚý¾Ü´»Z˜\öç—Ëþî@ÿœ‡Ó˜~þ­[ïV«Im­¬‚?t‚.ºÍ>´¹2Ð[Qa*þ>Ò#çß_.þm‰¿í©uŸ^ü«ø«ø› þv‰¿SùgÅ_Åß½àÏÎŽ¿¾ÓÝ/_ÛUÛnïåµ,3’`Î Á‹ ó‘`d&Lßý„3™ºM»«Yàä xA´Bp"\ÛÅjµª<ôŽx¨Ü:½¦ú!®FÖƒyow]‹÷‰"°GOöv½éêžøÉ!pr,ôº”;¨Å÷C-ðë·Õ¢ïÚIUã'@©¼8Q®y:öjÓn®Œ@9* Óšr œ“zö<0@v=šB Ì:\C‰Y.»¾=µ#ô¾•˜ûBà•µP»ƒ¸á"ÚödÊ%càä8'%æžjòOc OÛØ›Û-w‹E}GKEàí P.Òsþn¶Ûm­ÈO7©ÄHUböoIúÚ-–ÛvRmi•…Ö8¡xAvˆý¦ïë1¡Sbîk p·Xï¼'¢²Ðk#ÐnŸ…Özà#nFÞÐI¡:[ÞAø9”©"p;"pR'Ä|Œ…Ú ð¢,TïW`¡v:w#率óA`g‹6ѸE5b¹Ú,®ý¾ÎOc¡SD ]%Þ3§·¨F¬ºMÛ8-»"°"°"ð²1°¸½¾šN×É+/ƒ@ù—#'µ?ðcJŒW%æm%ÆceîWb>„ÀUAàrRoMªù+ ðNbवÐmÎìÍfÕžªÄxEàü(w€@9ýryàzDàŠ|E`Eà(3B zbº~±ÝìÕ¥²Ð[Þ¡vpçÓz]úFOÌ‹nÓïä7Y‘Ÿ}jZè;(ŸÞ™=‹jÄŽù¾íN>/tn¼v5Â&k5b‚ŒŠüO‹Õ®_Oª1›8§9¦B°Bðó Ø¡.Ø­&Z‰èC𞊳QD»¨ þ±\l–›ªˆÞ‘"zOrÌ”vÍ€`—l“z©ç‰èŒ¢ O”ˆN‚W&¢ò!¢.¸ì6ýrWO²¿ñ(xO|£.x<þ†Zè+ø‹§~>Øökø[ü­Ïñ7×í[ÁßäBà|êòo„À©à¯÷H¬¥ :ùø§xÜSñ'S¡ Íõ¦ãŸ½ÿΜÚ(èº@pWO©YàK”[ b°_~¹ÞvËQ°Bð& (w˜Î‚x±õ²ßuÛS[Ó&HDo‚µ"8"úåb¿üªïÖëS‹òsƒà³¾˜ Á!(‚‚Ëè‹ù¶]¯¶¦›ˆªŽ”Ûˆ‚s*GÜYQ~Dt‰¾˜Õr½\ŸúN3ŸY¬<‚3‘cfAôŬvíz{€ˆV9æ&ä˜CЍ¼A›´ç­iÓ… ÷ËwÛUwêfÝï' Î ‚3‰‚Ü/¿Yu›+¿\·æ‚Ÿ*Ǽo‚29f莱߶»õry/7U"zº":“\pVQÝ1Ûn½j'U¬¼,o›ˆÊ¥rA»£;æ×n»î®½SðFrÁ‹B°æ‚’clDÝ1Û~ÙOëÑÙ@p®¹à›ôyCp>¹àÐóóo‹M÷€Âë%Þc¤BpòÝ1‚g€à ¥ù]¿^./}‚¨Õ\p:¹àÍCp6r̪‹(¸Ü>üs/=¢5 ÞEÎý‚\’ˆöÝê†^kV£à[QÐo‚󉂫€`ׯÛú–ù;‚à<£ ‚~}‚ò ýÚì‚í¢ï»{9ÄwF” Áøþ9¢ œ- Êy!¸!xààŠ›„ ^‚:©\p®< =Ï7 ¢›Ý¶¯'ˆN. ^ˆÊ‡Ò|WüÚn—ËŹ{D}¢Qðš¹à´ x×¹àd!ØFÜ.W›iÉ1‹‚v#Dô‚¥ù™æ‚§@ð QÐ^‚ ½ Án„ऊ‚‚… L‚GDÁ¡;æ/úöí¤ 89fN¹àljè¼rÁsQ¿ºc¾~Û.6ëþèwJL‚ZsÁ7 x¢3«(8“\Ý1ëÍnwò!†'BPnC­œ,eŒƒ+~Ý­Ú¶Ÿ”SÑs@Pª":}¢;f·Ø-^€ Ü>å½´¹@ðRE ¯<‡î˜/_ûåjsKoVz5œõJDçÁ(¢»€`»\/ÅçúôŠÃóÞ/X”¨ŠèD¢àz1Bðʇ^RŽ©uÁ Ap–Qð uÁ@° ®ÖÛÕúÝ'¨ùk”W!(g&¢rý\ÐæÁš N‚CiþË÷í#]Þ‹":£(x¹\ðž¢àÅ!(ÇCПCpì6«þ®° Á Á€à~ÔwGÁutÇ´»Í²½!Et´ Á›†àû‰è& ¸\/¶ÛS7+ùÑ«APf” Þ€ãÇBPÎ*Çø!¸ îÂàÉE‰¹EÁ;ꎩQðLQð’Ü¡M{³Ü¬nèì.N.h‚ŸDDGümÚx¹`»Ú-W÷òf³W$j¬ø;[Ü ZŒ}ïûEÛ]ù.wªÅL'΂G'‚ó`h1[÷]·Û;Í^®¥j1Ÿ¨ÅÈiœIwZ‚ còóqm‚ú&ƒQÄ}. A™?W#'U—Ÿ.íúQPŽˆ‚‡!w;Á7‰èët-Ü‚ºA‚¸Ök´7!¨·Á~„à¤rÁ ÁwÑÓ¢àÉ£ ^8 ΂ˆ~‚Q‘øm»Ù¬“Š‚“c^…ày噯*ÇÌ "!s) „ü´Y,6‹ºOpr¹ O‚ó’c.A?£(ñû¢_´›msJôKä5ÇBOö —ÈkN! ‰¼æè%òšS —Á¯9z‰¼æ”è—Èk^‡žTByÍ)ÐKä5§@/‘ל½D^óÞèfÄEoN^"¯9%ú%òšÃÐëm@oÙ.–‡êŽ~V£_~7ýìì´[ôñVëÝbÑOk‡Òe˜g9 ÜKh#å4êlrÀKÐ@pëÀßf»\zŸ.C Ô°†À/¢Át‹M@pÛn»eÝQ!x[´Y@p ®ûõú‰àMCÐ+§ ÁyDÁAýË×nµØ.>g“®Ì‚5 V~‚mìÛe»ÙÕ£*& Å赘÷t¥½ªÅÌ‚O*“=°©k—Áõz¹nï¥7û¼-1†«ÏM­Qð³åÐÿãËOjc‹ür³XîÐ O¬HÌE<@I? ÂFi0½F+”byé`[4ÜQ`xçN—?~þí¤ýzw N¥â´â´âô 8]ý¯Ënµeeã„x*§§§ÅépR·ü±è6ÛÍâ|ñÔ*N+N+NψÓeà´_®ûö$Þû9ù©WœVœÞN‡íý_¾¶ËõrÓ×xz:N½â´âô‚8í§«nѲçà„xZóÓŠÓŠÓËâthRÿò½ëwÛíÉ:R§§§—Åi¼òôÛ¶ë×]WãiÍOï §2œÆQ俯7»®òÞO'ŠS»ãxú¯ÿü¯_­÷[·Y/ðÞ8ÏŽMF64]EFä_->‚>¶ágÚæTب…ňŽ)E'Õ0áè½BÓÕðLÑ0Ö cŸ@ƒ\Œ&ž=Æ?CG_Ìj3Ü-zµ¢c·MA´=ÃuÐü½Œ¸É°³ãe|ühJK‰¯+Ïùóèsl>Âýây°èƒAG—ÛÕ†‡³€¼Éð™¸óÐô˜Câ)`ÿhà‹+ÆOc H _ipSô\rÀ3®®ŽöB…Ý(º1íCKÝp9eÛ£gÏœ1YA]®w 1lp€ÀÐw l:¿œN…-zX'É{à)ÊR)}‚e Æ\žÜÊ,f·ß0S çó'¥sS`-á\a+,G“)+¾Œ:v(³³xƒ /V\ ûá[eñS·DN7¼ôt»ÞáE7WBŽ\9ž^{9¸~ôrÐÄ9|ozÈÑ©!Ç?9zUäì‚DÍáè-üPÃïz”bFŸBî3:^¥?~;;ö·¿ÿû¯5û¾XtÝ®obÝ€”Œ–ŽOÓúa¸´$²8BNBŒS‰À¢9F.;¸“  Àý+ƒ ­ðZ¸Š¤% X5iVF»¸-p……³T8w [†akyªðÀ±°UËÝ!€˜è(ÚÆc6*dñ1%ا2ŒÌ¸1at|‚0 o¸XNœ½`ôÈ­öOÛ0†âðlÃKÂTÉöie4wÎ*ŸSrÆñ„9‡yÂ2§‡Œ€vË?+ƒBD*} ÉF4PPI^CWŽq5ÎÌ BìÆå‘…"0³ã‡'z¸V“†‹¤3‡ãÄ$[ M{µ\ÝFòIè]$1AòA#-« ™iy]!˜Nߥةå#†é×/Œaíb³Ý¡OaL`"âéN ¨øô!$3ž¢IP‡‹K‰¾E踱f–P’0ÐÂQB׈¼†˜u8+G D ÊË@hKy)í‹€ô¼ ö8!> 6x9U†Œ±E&eE'_e0¢i;p„–4P¢MKŠ[1X»&(x.2À0OníI^¶,4!‡ÂÍé¯"AnŒZNüw£DC/ðQHÅcY4™Ö¡Dr¡Ã¹!¸IøðØ’E¢ê$¸!> Ô02ÓmÇh,M.“UŠû>@Ýÿ.£AÜ rìˆûä«È `MXúáÎúÁ¨´-‘ˆ}bÃCzXÈf º×+X­\Ò ÂRŠÅ%ú3<¬Àü,§ˆª˜ÀU¨ÑÒ ‹`yl™e@¥ ;¬Ê‘i[´–Üy¨Ðî`ÅŽ°êÅ/À˜&çNÚIÌ„‘”Ð Rˆk}à.FÚ¼á™âzM,Jòn”óàØ1R…;q>ŰT±xFÆ2¦c€SËLK‹»hÂpQõûfÛ¶›§ †ÎÔ9(<@<è ìU¥œÉ#S9 ÔáÆ“¦ƒÒ§ ©½ÆS5ÜÒAiáîÅAùè Ô“™ì;(?è dtPb)J“Û=qPúÔAʼn?vPIŽ)6 ¶ï „J:(£ƒBâ ÷¦ƒ²ƒ ¹ï9(¡ƒ 2–êÁ»©–¤2ÃK$òžZ¼ƒ‹A9¡&†;*giíp‰†%¤¯a¨1(jS&YÌ™£# J Ðå=j ]Ïù[gµFù‡aØT•Š™5£¶—]<*^‚$rÌ“¢*Èz!ñƒ”îN°àƒÜÉ€®ÿ@@ï×Ûñ"oá®ë-¼HÁ‹¼ØQx±Š—OÁ‹¼‚;'^ä^ìX¼ÈûðbÃK¦P/ûUÿ$Qßì—ëÅvƒ* œl2&„íŠc‚Å€uÀôP¦Fêîð  ¤+ ¾Áb~ Ÿ1…é¹ôšõï°µ {„bÆ47o¦AEÒŸ Âž„x cKAL7›'ŠæÐ"úÒ  ÁÁ¢° ‚¾ä!’µõá™CÐŒáoI8G%N¨T¾aõγ“ÿº³ñ€LG Ú\²!D)-‡“R)b(Gʉ¶Jã„;¨–p¶qÈH` 6¼F¬ ¨3gÅÊé@*ŸS™„ ‰KpTX°h5ÁïѲ@Γ%¯,ÍG"’ßaå&àÞ+¦„B-Ÿã6VÈ&y6~„£a9EV;}Nž(¢záHö¡•GþÃQ‘y:Ÿ?«pšƒá4àô–UFv€| 5‹„äWA“¯‹nµ^DË¥`œ2 .E9rüÄïâÊÓJ˜^%@eÝTébŒ¿ÕƲ e%„Œ)žRňSÚpÅFRW¤(¿™šP8=CÊ'9Åöî"Å­¼[‘ ÎÃ]Bî„¡:µlËÇÑ}Šp† …ðÉ̳BÅ”62C ¾–‡…-•² #Pü6qŠZ™fƒŽP‡²Æ U:î[f§Šn,b,ËŸœdÉ %OA|åÇ&9|N„ .;•k&F™È3–”–#D>mš³âC0+í(œ*+¢i;‚¬ê=̃Q>б¸٘ߴTÔK‚´HY§ 9àù­oHFy]“iÊ-,±(y•/ˆÜº÷´y5føVJN÷ýË/¿RØ^®W ¾1OSð¡zaÝœÍRà=(±„35øið©X8t0|Y¼A‚çc½œ¢%+É”Ú AH— Ç‹ÕzjßÑW šöM–ªH¿(§d±Â¨ee/¬ñ ÐÁçÐ…Ý'@’u+cߤF†¿3eøc¹j»ÏŒA÷¤“z"ÛâôQ¹Aâ ™“«MIÃR÷E’!$|ñ‚JS6­ }K#%Kò}G¼†”†< AÕ¨£Qq¢¯òŒ˜çL' ‚ÃrHÙ’ä;cñŒC *7¤°åx¦²Q}„žˆÈ©ô¥¸F:*êh!w–™4a6Iº6ÆÀì–|Ã2H6’*ü¨1¤‘tEȺ=—_ _ĉ”ŽÁYx¥è B)Jò+6{áe®ØËçf"çaŸj^z0…[tgÀdf:êE9’Œ„LO¢'öTžp¯, rÄÔ6\2e€IÐB˜“bÓcM )oaîÙÚ‘” }tÔ a^¸j0«H„qjðO_þIÙ¬[®vè6Cn‘éPföNú ¶¨K0ÃwNåŸñ!µ(ËR pëƒ'˯Pî`ŸùŽñB=kà5ù.þ½«.èÉ'’Ä©qºAzBÉ òÆïÀñSóT¶vǧBþ‚6×B¥GÐI (Ê4|€”±©êY»=ͫ̈ֆz'ÌÐQ¦cBO(+Ó | l¥aJažEvö•Z“˜…ƒÂ¤†Um`šé®ÉgúÔ,(P€î°³*p 7]Z*ÛD«#k˜EÁŸª8˜ªÛî©oB6¡@ÍPAJ(óɳФP+ Z1ßø è¾‡NÍ¢§C ¢tŶb<kÑ,7iÄ*’SÜÉÐ õ)õYjyþWa¸|æ‚ïZSa‚à¨t;3ßð_,c¦Q Á$˜nØÜy€îý/H«2£¤"Շ«2¦sRœŒPä¼Gl4l7sAʯü[.)Rd®Ë70;ÐÈ05Ôn•‚4½ÄM¶û¦65 ³qfdV|æ1å rOyyn$; ÛølHS Ð)«#Õrz3°IÌBC ³ô„ $~/ûÔA¾!ѪÍ …rHñ)VSƤŒ±IJ÷ÔÓ5úd‘©‰‚ "µgÐW”6©ËRó+ÃV&p"Ìæáà kgçAO¢IýˆAlÙMÌ exf…AŽcMšqz³Ñ"1Ïî\ Êg+’æ+åKx€ gƲ9¥JG"OÍÏœŸKJïïûF*ìGÒÈ—ÀýÑCh ˜1f]1QÍ¿ý¯ÿ÷ÿŠVŽá˜ïÕ:¢mê†B­J/ë¨2Ÿ æàºÖïbCmªÚ©È•‚Ä oÂ*#‰Q§Hz”XX¦ˆù†úM$6(H‡$NÏOe¦œ 1ߣÀ&Ôö<£"è/× pÆÄ Ïm¹ŽRFxEöZ³Ä_'hO€õ7>ÊV9tÚð)…còÀ hl°¹ú˜'áGÔÊî/‡Jíy“ˆ<1Œ¬ yªHB>lø$”ª! Pª¹5ÌQaçÙ3²ãXtQ?tdJ)hAñ1óHú|ØDÄÒ†K6ß 5a…T(CQP¢cR Ñœ‹ 6*{–aŒ°ø–R²ñ,…2Ä•~˜Š‰ÑJ-£P|¶aÒT¿aim¥H<„¤MJ…àç?ç^Ãe·\ðì`+b¸K®7æN“ÅBOqÖæð°ÑŸaH«…Ò‰$½µbÿ¥&—5ö{‡õ¢‚zþh@¸Rcj:Ä̰x”}¨ôÀ„Š:Ê“ ºœEÁ°v+ò|¬bN(z ‘ê(BL¦xh±è I3(@Ñ"JP D>…¬È›P)rv—&±f°Í‡j§Ž–Î,k:ʇJÔ ëÜ©ŽJö0$Z”Tc=SŠ•®Åd‹‹tup)R¦‹ 6²¦‡ŒÜƒb%µNV½ð},«§ÆvÒü&„ êÊ™ ˱E#ÉÔE TöLAŽANu´aj&a·ûê(ɨ|AËÓ÷vµAšˆõ ‹03RšP/“ä” zjFÙ €É¨ë©6£ì†ŒI³ V•½®Š×Ye™E“ÜÚ‡0EÅ$ÑX*„vk’ÈGq—šbÐ,òŒj6Ÿ ¼¡’Y•¬’ˆ¦2ïšÑ?,3œ7¥ ¦‰”œX£&iƒaîõ?5LT¸–¦ÌÀ¥{”åä“¥m aÈ—ÂC‘¤¤¾‹¤Z °y+ИtHYH€6Ç9bþ‰QÐŽ‘MšR§eí 3§9·^rGü -ùî0lR6‹&YtçƒÂ_M"[çiña„eô°dÄ6ŠD"4eÍ€j±¡½1 (ÅÝöm: Ë0I&âë0Éâ3eµ#¢ß`Ǩ‘ƒ2ü*À=LsŠP¬“Ñ)çc*©xÅ"ðŸTˆÍT‹&™™/ÉÄqøs8'eÛ„fU†¥]`^[A¢Ùš½Œ”‘)ßÒÉ*+:õ@‚â “,x6+͈DTÑ€!9s.ˆÄ|q/dœpåH[=$ÍXmª²í¥„%ÏHr¹„Ôu Éüò¿³Ø¸Øl6KƒÛ¦t›Ú c5A‹ýPÅÆ{‚’žÔhÅY˜@2àiv´CÇà3Fˆ±d›ÀuÔSqUŒÁÑ %ÙýI“ܠDG!<™Ý6ùTœ*Ò PXℵCwÿ‡ ÝpÔRYN-4›‹.£ξ˜ ·(„RÆTjb‹ûØD2¨šŠê B\wÊž0QYMæD ¦¯PSœ)U\•^ŒÈ4á;‘fq7›]‡C‚ôIÈLí]XJ%ThuêÀ@˜Y+i ¤öN`2;µŒ)P£Â_6àš½”’bíÜh&”Á˜Œ˜dÌ~¤Gìiq$AŸ]4 ™ž—êHF$I‚³U°?ÔÆQ,ÏÀL]µ >óBõ, •ÿÇaüò[¿jWx ›3¨„—EÕÝa%DIFzñ¬š! 5ã/F¼ÒÀLSODð×RÊ€ò*I]RTg+ý@†nƒË¤)qc•ø9´k—¼˜*jDlÈór•RÎdERX3¹fu_y:NPˆ›ù,ˆäL)tˆ\p®Ú@@¥šv™.Î’ïH±Þ%éÇ8Zª&`Îì:a …¢ˆF úÀq‰0yd·þ¤Á€n¤"ïW… š–~o\yè6|¼Æø<°E|”õ&&äÊ5CŸZ¹ôðfÔ¬lh pœ^ŒŽñS9¤ø ˜fûìÖÙ¤âù-¦Œ~‚]½L—óŠo²Ó?ŸjIP©à‘Ó‚çÒ–UFô–Μ­ð¬e«z–ËŠîåªßþý—¿etí¶«uà˜I¼“Á–:„#ÁPÍLO(j‡;ÓÈ‘©ÛÐWA ýº”K™Yd®É?(x .ç¬; åÏ͇tС9’I•j <‰RfÎ$£.š½{#Y²áÇ ˜K©@äE2yÔãÖ0†;ˆI6ëÉ£ì@€jg4ÌFrr¡Ý°6#hX`• •œv¤1TÂdᨑûAÌf=„MžKX’Ýÿâ,òB1+úla#…ìÅc§’j”z=»l8oYR%t ½Fy*”Y+Q¥´Ï ÕHgئk,3ï?<¥LJ[´ â*:6Œ€Tó×ïÙu³ZµÝvݰ0d,x‘Žxdf¯¨Ù4t&¹ pÃ…b2yvL>ºš Ò9•ïØÑH„!éC Á™‰•EVBźA”…“ý>O£U;u¤g„äÌá2Ã÷u/À@(«fÙQµ·4#:³’´, ´)*%)û§„åIˆ Ò›¬u¤*!àU,F(mÒ¤À¬å¹V@)uè¬!{bÂYò4FpA…¡)Ú8T,Éò «c„€Ç¡,ê½Rgcqܳ8_ U_Xš0dMÙؤæA ™æ™EKÊó¨hÅõ à˜—†« @ÊIÅfaÙ3Gݬ԰ SÊUN¶„1†ã:¿|]oºõ¶¼º“š‹3ñ¬© íUSæFn8fhY(†úÉÊUm”ý8r6F"gÇé)¡#8Ã#Šö‰â!€)M6/Â!Áߨ°Ø h ‡ kLôޔϘ1•è*,”°?7º¼ÁD ±Ÿ™É­³Ä‚<ƒ¶Ÿ„[§ZÀ„œá—_tå¨Ki–%â²¥qÃqEš5¥xJ˜|Ã~iÊ„aO)óSpñTù=Qxî©1ÿˆàÐ@c%„bÅ<ËN L3©ºX9d­( â)á:<'n ÏjHÀV=6û° Œ€ä)Úé`…P^9£¥LšbÃO¹]yÕ®7 š~N¯Ãe`ÝQŸ€*ÆzTœX†i²v&¬edð¬LÐŒ‚"]œ»ó¤wô†°> ȳ?7ƒ^ìiI,7{Vž`”,£Š-éÕ„FÂ2?à’&m,Å:¥oÍê²5|?»ô,ŽïB袕§ªZ\1Ýxæ`qI?ö­Ü$õWG±×£—edD€2!ü4¹ 8µÔÑ÷ã¢iäÞìÕ²\Y6ƒïMU>ù –]²+(ì¾P 8» ÉVS-ʘŸk@R„ÌVü± C¡‡ÆŒÕAE+ ’¾_$c¤#5Nh1rLs6,Q%q "4OPÔø‡¿Ï²FÒR .}z)fPFŒÿW§~I—Ã*@sÕC2ádûÆæ[c¢h’ˆ;õa𣔽ÍKe:hsÄ‘æ´Is8!‡hŽ‘æ°É‚lÊ÷IØApÒà=iv¿&Ù§&þˆædvâµÒ6ŒÙå'S Mc‡ÝÍA¡›3šczrœTTÇOÐÔAǧ>À÷Z–þⱑ»J/Œ¥Ð¨ÕÙw•U+®q”¦žî'Å!HzÉ–AñÅS÷tÖœ F •òn,>&˜±’ÕZý3Àðm±Ø,ûG?=Hq$Iøzhä,9 tgxæ" £j“¥?T„úE7Ïs†¼•=%µÒ|~Vfð[j¦˜&çæ}A½Ê¨$*ôI¡öÀ ¡4«, <Æ¹Æ¥ÅØ?ÁÊ» ›y*&‰R¡ÎA‡î¬?#é›"”¦%$îbéÎp):yÊÔh ÂI hˆbÇÅ~CTÖ¹A&AˆÀâËé˜Y'B´AP!^QÃÈÐEÜ0°Ó®xÓ@K!¿ä/–‘•¡ÎK«Ðù…ÝB‡%ý³’˜¸ñu®cKuec*/Ù¢·œÜWpÈci…2†@Mò JHF*)‰QLlRÒ%y¶DJ!j4HÌÁ€ñ²7+ /ŽîÅm¯Í#JØ!“{m<³6L<ȯ± [ö'Zœ5+ìnð¤ï¥,`ZÂ$‡N(JP¢t\OTBÁ¹¢ä"&™xr °0q.Š×ÉwÈ!È–„½µ\„xHœÓH9ÔÙƒñ×ïLƒÿXïú¶åΑŠsU¨jzVÔR@#¡¹  Oôì!÷qŽÒŒº£“Jê*( "ý~³›”L„½!°à8(‚æuÒ³5F˜€Ð'IÇÄvh¥Ê¤#Y“㯥RÄôFå`—dä Ö Å¥ PTÉÂ9MÓñîŽì=;„¹¹â1¸…Îäq›#2ņNĨCR ³‚´J­AYU¡Š,<ÁÙUBpƒ6À-ô²Ð‡0­ ‹±nZd*Ì>‚;+átÝìƒË—yö‚³à Œó,HÐ…ƒxázÈ¡Ssc¹À$¬Ž”™~ÚÊcÆ)§4L£ÜKÚl,z0bìµ9Z¶„yÃì›®Ô qBÊ6(dåС¨Ãư-»%`ˆU˜xF)ŠÿÅ¥ñ°£/?·ÜˆÚ®ñ^s/“;2û²äÍé•2dã9zœŒG*DmÁ4ÓEhÎ ¯<‘ò®-ùdJ«tA–}ôžÅF³”íR ÚhtôV%æÇOñ ²I?«ÃR‹>TD[*ðøraÖ È·©ï%Îp '•a^‰ž !›q–8mž5ZÚðpMzÔÂÒf1:ª–È€€qÆæÙÈ`$ÁXj/y­@ugtHX’Ö=é ¡W(6eô-œî¤º¡Û¶"µF1\4óZJ:–'L¦ô$äÈð_è(5ªñð| ò˜û Â ÖÔ„.Ï?Fx{>fÛY [G­FhØÈsÈÇ>°Eƒ†$u¦ç&ëèòýÿÄû¶_ô8!‰6O‹DŸÛžÉX4£ü•) ö4X<ãºf°èšå ¨ÐàÍóÕÜIÛ é¡ ¥øA+Žd{bŠSM‘H½œPæ!X4ö•Ñu¢#Q¯ÃO1™ÈŠ5… ¡œŠÑ†D±­³œSüŠn É® †¥ØYèà ݘnc¡ÃX\Q‘/ í ,{Åê4äwNU Äú\c9×YëyÏÖ$–邌½¦XÅB[‰e¡j&ìCöIVÏ2)¬‹wC¿Q!ÿPåFKai•ÆÇ6[#Áb¤ÌŒpø~¡¥ 8µ4N-$wsÖÀ±•dÀ%J¯`!,ÁCÕ‚­ÓÇAñP¤šEІ7-…„‘Œ]3( kQˆd°7¦“©â jeë$Ý®°BLö  ZY"Êo²£ü¢4w¶2aì 58/Gòè’é.[Å‚:5 °B4+±2 nÁYòà#†Ÿ5èiþí?þó?~ÁËnVÛÍnï}–èŽé÷,y`þXÈÉxÆ>ã×O/§´,I%…‹8‡æ)É ÊIqfûYÙ¶Ò ‚ä 2‹¾ICÃí)¼Y¬ˆÄ$ÇÐM4…¸‹ždDlP– ãôòq‰M³“*Â%30Æ&3ÖÙ5©þÛ§—Óàœq OKh=?½\ gRºø«h®Ò…ácN/WÊ;lźæ!òiæîhrxzz¹Jak¹åŒI k(£·$ùf¸†älp)”=ØbiZXi|ððéåtŒ ß(Y0+JzwC›4úµ•Y×ÖÈX‚‡þh oü£]¬Ú¾Ãé—,uL,Û`xÃ\þ`<ÃF´/ƒœ€ H\¯cÃ_®ö±!Gc#l›ôÛØÇØh¨Á¼† ÌÛSl(iåˆ Öà^ƆìaÝ$g°Á@o@.²‡Q÷)6˜+ûëØh å<„ l8;Ô|Ãýv½½ˆ¸?½–2ÃOþ+_¼ê©72ÊÃo1Y*ÕEXSMV²ZÖ JP.=vÌ…hè°Béì½xï‹‚úQ»Ú‹‚þ«è™yQ°ÞÊ‹‚5 hè#ÏÌMSérA¡á / f7ªú.©ââ‰à`Þ1>ts/ Vc.DqŠÙ¼/Ò†OxQ04Çó½(Xµ(ˆtë~»ëp¾dÄAM¼”æ JbLª’ PK2dsd9áŸéXc%…©HÎ=jTc©ãdVàÙb<×lÇ\¥@b%?ƺ¤ÔœÉXìbˆƒÁ4ÂÝ $~„@ì Ÿ9CqétppPðHÈ)ŠGBˆB™+‚$)K¦ÆRŒ¥¼å Æ#OÿŒðyuœ=ZâeµLy¤ÌêAL §æÀoìy$âlÊ))'µac'ÅaϸBMšÜس!#pLfGÖîy¤ mªŒÏéÚè_!‡=Q°Î¦öÒ®™=T–s©¼j:$ÂG©Q%É ! û¥GÎ3 Äø|•…Ð! Œ˜â' Ù\T~É„õ:K!pÏ#e¿Ÿ’MƈÌÀx¨\:s¤\’ŒÝdcÈBY€%jø'v·(D_cûsñH,$=qHM:?†ôÂ*Òð0ØäòïÃÆï‹ÕzÝ®Øä„94–0 ÌÄ‚ÙÀ$â=[b(Y‘ÂàÞ›,X“1x<Ú§$«5(ž@í©‡RŠM\HðÑÔ4»K!3f®AãĂĄ!Q„WA,÷t‚æ_Î|"–0çˆY#åpÖY#•ÌrP!"Á¦0d(154P&·c°ME‹N…¾·¡á4[Isҙΰ—À/—4ìR ÓJºžJ²©KYOéT$iÎðéFK5­TSé˜jª¯`t9’¹ Q;‹_¤sŠØç–̈Œx £NÇ€ò=DyÛFE–ÄßÓÿ¡a¦|?ŠŒîžRd2†ÜÔ¸,©"“0'¨YþS1$NmJšµ…×3M9 Fš:i)ÂG`V61å“@¥Ì`gL¦˜âK!ØôöYµU”¸à-×Ij±EF©àceâ±ÑR†,’=TªK56ulÃQ?àD4Lf`z”Íë"ᡵºâ bˆ{á£þÏ/ÆÎ :-y½£¥OêÂq jIZÂQ&S¬'K­0”ô2þ:uiö¸‹fÈ&sd.¬©<¡.R’)ptK>¡.( U N |¬æÞõp7.ý½d ÒÁÁd … pÏËŒ0v¥Ø¦àÉ”RnÄ`x´’úš¦œÿˆº4ºÇ]à+Š3tÖ6INS—“»€¨ÛSêBª…dÊàÓ ui’»¤¤ò”º€÷ÂMAx© ä¬ÜèE§˜yL]’bJ¦Hò“ºHR—b¥\á9¡¡y¦ Oúê#uÏèn uñ’L)›”Pñ  S˜Ü£.ú˜º ã,s›ÝkQÞv¤. 5”§‘EzÄFêâ{É”&uñ2ˆ’LaÎÝx€¤Rë`:åØ “ÉTóoÿúÏÿäËß·‹n³ÆKì‹Tàhf’T,É”PbY3²b*sˆâYW$Æaéôt¼z<»¡–7”´œ¤÷ĸÕh²@A‚_ÞÙÑ‘•EgC ­Kp…p*coC>¾A°9‘e /LU2*á~Ω!-]Qv¾ð3aãˆ1Ù–M8C€§ŽiTf {±5&ª¹` ©=ñk¸Y㨾BMóQKNqÐY÷‡T’^,pëlD¥I|…!Ã(Ç$½NC ,m“ëÇ,t^f—CcD“ L…m/³ KÈŠL˜à2«šòÑì}à a’ý–úŒ|ݧ’C¾ü³þ©ëãð’E»^ö}“™rv[;dÖA Î’5²5çø i¤pÉXoªådX¥û>CŽÅßøj]ÊM‰taKÆgð Hhð©<—ÂPã‡Çs– @Ýy¸A{JCjÌ^(¿hìè٠¡–9Ž´ÁòHé秇µX{G½J؃˵Rž?Ây2ôX€wÆ”0™AÃ:;b"@lER–ÌÀ¡7¡Š‰)–4BÔfD(u²E½8¬3¥È>teDJQ:Ì38/Ž:wÏ€Š)KÑq-‹Ú ]•mx²ðw²Kº~vpã5®¡¹<3S)æEoA=Y |x;-( Ò™1>ãq×èW`M+f€.C¹?†ñ .„8ÇLf.™C+:R»RE€éíçH¼PqË6•@ž°;¡ÄÒ$0O6=*kE¬NÄPÑ)æ K`0SÊ"èÿ¢Þ:j໬ÚG3¨ì“È ’ÓδÙQT.‹ÝNþþ±À…›2£+³ú |RÚDr÷óƒ“úù·U·Ú­û†ÏTyij #‹™w03Ø&í‰ÿ6))D²Á]NX2c /€öeEƒmY µÔJÃ(ȧ¥»ƒïA3&¹Ñ#‰=ø­¥Cê%î)‚¨ñÞ]q>m›µ$jI±,°8äLïÜY ‚“bòÁ0½¥øV6na °ÔºšÌ擞²£1ÃA-kfEv CøCU )unµ+z?° ™+ŽÒ …$ÃUU§W` ˆò•@ã°‹ Æ-^ðä6 Ãâ\Íb@š`¿Ër'Jº÷Ò/𩽠S‹#ŸÑ°Ã4ƒ‹”7"õfQ|˜^§e–-W f’RâÃn`‘¹à`ƒ<¦E€iúí,xHZUÅS§!zñ&Fdªˆ]„]÷oïúÕ¦Ûfé5x/á…¼Ž ÔC Ôf•éJY/$ãÀœeó:*_eó:*_eó:*_eó:*_eó:*_eó:*_eó:*‚R”Íë¨|”Íë¨|”Íë¨|”Íë¨|”Íë¨| J> ÄiÃ+œpMO‰9Y­³õ#‰F‚ò§?ux{ßv·Ä¡kÙv(¹E5ò’08Åâ²jº*{­MÑ ÅOPuÈZ9Ö…WâèɤáIb3|Ö»‚š:»" }W”¥˜{¹0«mCȈчa ÎØcÔØ1"tI í(uaK:õ9!ÝÕdÖÜ÷I* ‚Œ •“¬Â2¯de~õ)ˆÝ$÷Pî€Êþ Áä iŽqê•);ñ™Ù^À ™\̳³IÙD¼!#¡*VŽª[’ͤbH‹œüŠÛ’áéÜ"¬p¦Rsð’šA~&‰CN+I£É 'Ò•’(sgýT‘3A? p°zßÌ%£ƒ·PVý68,î„U7®&‚Ò‡—öœ?-G4´§ Á_EƒSÁ‹ïBƒ|ü†Ð¯i8 | –hÐàÇ£Á_Bƒ'€Ñ  ¦´Ÿ ²öh4t@C·ÛU4T4L /ƆK£¡cÃr Èp¿œ(õ/´X+&}DƒrIH ÷Ð%{ í/ì  É LÖ  –L‰±Xˆ†=(XBÁ/…ƒQáÝP86* ^êûï‰ GBa;B¡¹ä£P°óAAn ò&Ž"H¯D¿FT¸(vÑ_¸\m—ݱQA§®CÆÌù–Ò±¹ÂñÉæ…v1bá@X˜#.dnaÁßËü\ éXðÏÂB;ba}þ‚Û™EUÀ¡Ü>^p;¨zs·¶‹–Ñ~÷ðÛñÀ®”„kEÇÆ#8Ä­r¶ÃF£7>ŒpÍ-jÙ !á Ø–¯ôdtàüDtˆsïУ耺L´ Ä],»"ÌqCß‹n´•„zïâM³J¯$ep™RÃSUUËFƘ+pHØah¸«„ƒîÁÁŠÃ؃ƒÒ RUåItˆ5|%ëÏŽ•È ú„)ñ¢˜çŒOàÀè6™Ú¾»½Dy š¢…ßíÃá ªŠ~–cG‡#á°á°«p8 Rápò‰pðsÁaõ‡o[/û5ÏÙB˜NÃ3de®@€ƒ>àïN›nž1%=À”ìS*‰Ã)L ¦q"Szž8¼ƒ)1q8)É»‡'LéIâð>¦ôzýS’8°*±ð¦ä%qx‰)Ù«LÉX*<)“8üµý±| m·æ‘«Üñh´eÁöäÄÀâ>‰Ÿ7ì9Tva*}9² (1a™Øm’ý‘ ([¡ùͰ\.né{<1?+#ŠVR´¾Â;#fš`> ŽMsÓx'†·Ä/ɽwŒOS%hÍ4Ï®{”xœÛ¯†öYåšEüѼ8j¹©ß7ƒìoCH²ÜÇÇ~×XK´êb°Î®^c›¨r$`ì‹e(›~ð(ÎM‚¼ºr÷›8ç½Á³ƒ)Frz¢Õ?D߬çÓÄœÄy`ȹb˜8þ¯… ‚ÆQ€K1\ûâ9$‘á—jÙ3œ6cœž54±r› ÀÑC 3+ÝÞŽÉÊÖnîN#Á½•Rs—⌦ӵ4&ƒ“kÊÚÀèµY>KDbô53¼™{b!ùŽ' ç`¹c®Ç,»ò÷ÅbHß›LÝ-ÐŒ@%<•,ü0Ɖ_@Oh‹O·Jîþ>5ì\éº<:HâGñ9úkR†ð³ôíλ![G 1î&V0BJpR£, ü3œd~Y¸ε¬M¼çB`Þ\€œ Ñ=kñSÇ/-.Îæûx˜²Xyy>Zý€s7é0ÁM™­x°lT3¼\¨È?Aì P|œ<ù%x¸IΙ“Â0Ê&I'ñp¶a QÜÒÉïc’anˆ¿óèlš³Ü¡`ɘaÕØb²‚Ñ•ð/¹Z–»µùßÈI4)ãm˜„Û*à¶l—»×áænGÁÍg7©p».Üúòm¹èÖ»íËpÓ»›\nö¸ù§ÁMÃÍß·ø¯xn2 œÙd›Â0J2ºÇ-Àmý·Õb±éÞ “Ó‡›L0ºé|£ÛàvKÑí¿ÿÏÿ¨¼þ´Ø> ­¼|ŠGÊ4h=!ÓVÂG<\#ã.[HZNÓ3 ÷—Æiп²´Î]šqÜ $ÉcçR 2B©¬ÅH®qÐ+¶ú"³ç¢@ÆUµT•Ôò HaãmR‘BSÈœ.b£ß€Mj®—Bñm É0†"N­óLµa|a=XdA© °ž¹ €Ï/Y0JIyÐäð<–CëUÊçxæÔ‰°n°nÇ‚B!‡îKuÁ(é)ÛŒúW,«q1Ãñt d`õbTâ` ºæRcNBj‹#çܸƴ†°W#òÂÆ8NJÑ­b8Ô#ÛÁüP€1 Ëp!ÅHÊn*èëp9’ÒnéËÃ0t#Ö ×ƒ {X¬`8 Ë Û †§`ðn ú « »óƒA/;ý `W¢Iv=0ès0Ø™Á WƒË%"ú€aÙÖÈ0ҤF†í†eCÃ=ÁŸ‚a7‚a5o0xÍjÎð±È€^H6óFCÍ + z"=éë¯Ýb±Ù^ “N¡ýJ)´žBŸG\½B ý*d6±a5¢á‘ äBƒÞ­ 4_4øü˜Òÿ7>ÿ}¹íV‘@c „æ?…a²Õ#ö›»ŒÍÃ=Ö›{…Æmbõ9U‚¾¶ ¨b–ñÞqÞÏÆx‡‹i.¶G+73ܰa›<+ÜYýgAü\Ѐ_¡"O ç޶áGñÃh*(ŒËãQ¨á+Fˆv€&øì1ÆžÃÐÎÀ†‹¥ÆЊ¿ØÐð¡èd0We?‚¡:¾É¤ô¸x¼Rv¸…²›BñTa˜aü‚æôð3ù\‚{a›¡UKׇó¸ ÇòÄdà·ø`ƒ¾x«¡G^1ùho‰á!C hŸžÛ°ä1ÿabh¼ˆõ‹5²\¡†Æh´/Pý#ñx…ßÁsÑ”†a+UviHÜÛt<]-´˜TNXøx¶¡„ÙÇüé^c‰jŽñ k‹Ö W+ÌC ËUÁc&–X¾Áà¸| y‡ÆãÅßÂ8c6ðô!ñ41ƒ”ãTí~±Úá˜è¯Ý*ÐÏt­@ t»Ðq`øjÓ­»®½FôÑÝnèÑñÇf½Û-+u¯@¯@ t¹ ÷#Ð+u¯@¯@BÝíV€>´vÙoËU·Ûñ]Ï•1^>lÚªòyyb¶)®À¸x¼Ì<Ò4=]Їjé âþPpy‚&~W`{®À‹+Ø÷RQ¬Qx‰ø›W û®«ø‚'ˆƒ8Ãà»Ϙ¯ûž@ykÒÈ ®Àð·=OàÅ4oº~ô±'ÆÑž1‡‹ ŠâšèXðªS˜a ±#?*SaŸ(Óä 14E­& Åaf8Ï@©ãŠéØàE$§Eí¨ Þ…r LÊtTÀ†¡r‘¢òÅjŽG/6ÁÑ5ñ!Ã}òœ˜˜+ƒ‹æ¢ä5Œe(çy\, u1¥¸Š³^$ð Žúá´«ƒEΩÔpð²(jÅ%•kk\u’ÙÃF›ØO#  Ÿ ™‡ { ^¬j?ÆÆ€ã†Ö#¨êŽØÐÇØ°K`CžaC`Cž`c¸rc(Z¾ˆ ßÃF¬wŒ‚؈ ´½Œ =ˆ ߯Ãný#ØÐ7°¡¯cÃ_Ɔ¿‰ XÆsl€.ùõ>6”ˆ±a(ºØ°=lhÞí6ô68êgØX&6¶/bCôdž=ƬLúz 6^ЫįúlÈÓ¸QVÁžaCGlˆº‡ õÇqCKÜ•Û86jD“¤M—Èè~¬È/ß׋n·:'2ªW°¡Ï±áϰñJÔ‚=NbTR°¡ïÄÆñŒê¨¨ñ66ülèËØ°×°ñ8ÛðCŒÊ°Ð‡±ñ,j¼‡QÈ6LcƒéÀëÙÆ>6J¶©ôƒQÃŽÁÊÏ]·Yô‹—°lC>žmì«Tþ€ 9>Û`ºQ²c8•¾7nœ-ÛØËÄã~¯pª—âÆËØ8WÜ8˜mæTúB¶qP¥‚}>Ɔˆ¨{ë~ÜXØè^ªn¼C¥ÚÃÆ¸qP¥zªà~T¥ò÷bÃ>¨Rù Øpdg'cã¨ê†œ+nÄÆ™«þrDuã§z=ßxœnŒ {–‰oFl,r*¡ =ƃØðwaãp¾qLÜxz§òÉ(¸—ËÅŸÇĆŒù†ïaÃO‹gTpÅ^àT±ñÎÊß;rñØØŽ•¿þ‚ÕÌÅýEl¬n¼gË7äè\\NÈÅý"ù†7ö°q0n@+y6 §òk`ãYÜW±QrñCqãq¾ñ¤ò÷Ÿÿã¿Ëõ¯ÿØvífS¶3‡dŠ–¨T `êèÞ )r ¶Y¡ß‘MMðH ÿ!6 Oׂe[ª²C-^,Ä~7Ü]Р‡¿(,cqÄ9Õño˜à•ÂÆŽ/ž‰ìß³;‰]Ê`üxcìŸaïœñZa´yÂ'`.qÙ|i­D£ª2Aoü\1o˜)L»X6-5 V|0ìÑãËB[ê² mxfÍ)`ç±³s ¿Àˆ½,_Ï¢´ ’+Œ‚F»áéªÍÐINRó©549.¬^Ü®X/&ýXèQNAIh²òÅÀ„ƒåü"Äxö$ ùxAÃ4¼f¸ŠÞWeK¼¢+RÓ$àsÃt¨Óå´ÃBÏpV¨+šñ ®`Ê8ª¡q¶˜‡²” îéñŒôÙ%{‚Àa¯žGŽI̼$²àabíAhžRº7FŒˆ>ÃWD‹ l žÏ„®îˆûh?E³*›òé:Y#ÐàJFbu3\1¾¸Ñ—ÂÏä¬Å,6iØ‘„Ç’‘¬†³®–ËͺƒXâŸs—‡"†16qF£åˆ{— báMù$×B !NÀfHÄ‹$âKšÃï[iv0ˆOBMŒ/Ï@ê ®ZÆŸ“opòšs\\^tCÛË)úEÍk` ˆ¦rÛ‹µ±4xd3`¨Î€×Âû‡{†‘’L'05‹Äœ µ:7vK‡nÂ-ÐiŒL€ÌXŠ{&§jñ*Fæ: !¿Â¬xö±‹—AöèFâIùTêRkK;•Ôr—e$uˆÎ£bpáS¬p3¾ARèœéÕ0ÍéAßÙcÎóFq¡˜†^´¦ É"Sð«ÁIâyöÖ%Hµ,Ó¿=‚wæFVD8:#Gs¬Éq-iâYn 0Z2× FÀoò™Š«l¶à49)#É̈ԑ p4 g]Xaa¡ òëç‚„Éî-”ö¦$X4,Ef«ÊèÊLÊãæl9ÑR˜mNUX˜ºŽLÆbÉL‚*¿G7à´pañ&ù|²\€¤±Œt:(#'L ~é) ¯"âiÓ)I# c‚\î’L I*@âÜŠBº³ÊÐꃧ_îÑÀKú¦Îd•.QNe H2o,7á%N%nbhdžL L8ÞöÍÕ梑\›``X+ÉLÜ£¦Ò\Ÿ¨{FLr$¼ 96€SŠNd ­óöJý¢_/• HesbïбI[ªl ²Ê*89³žl ÛV6 • ܨڀT6PÙ@eUx`ÿíÿëÏ¿þýOùz?ÿÖw]·Ä™“–Pи²«g0v4yÛ‰cLjl®´ÆsÇ„edÊ@5ÐÜî6<ü¿ó`PƒUvÉ„tt\Ƥ‘zØáp–c³6z3=l(NìÐàü³Ç:B/¬.v> "Ç– tëøËGE!JaÕá\áîzcÇ8bÖbH oðœ´IDø&\έ¸; º3Söùâֱ݄sÔ Ú¨KÆK/«DÐs§ zΕ¾³ §%VfÔ± E# 3nXbkoÜfØ×ÖC·$N›„eVÆŠCgñ‚^|t釭âiá’ófð[ѶËÇÁ‹8è7žv…ÀÎÅ{dpyþ7üˆ%›ˆ¦ö¸½°îà ޒô­[-W;lÜOëåù‰´hŠqPâ¸;÷ýlˆçãâ\®\µ2)°óÜØ0 õjì ²&!z*8Ö—›[òÁp=y ݃ê ! Ã@²£þ Ò;¿ ?ƒðFäåúQ«?¹ÍàØ±u¢97 ‰Ï``¤²;ä) üea€…€'µÞƒ. ·a `1# ¤¦^`€ë€b; òƒ%ÞÜ.VígFƒÇ0810;o4(0x3Ø\£N.ØÇ¢¼;ÄG_»Õª]õGÂÀÃ@_„œ^``  >BŠä=0ð#H8ðÿÏÞÛ-Ǒٚ÷ñ.:†üÁOÞŒ™ËUtµÔêîR»ú¨ú¦llÌæîÌ˜ÍØ¼ÿ0ü[¾#H€ ’R©D™{ûòµ|¹Gä b}›C< ƒ^F'Ü*¯¿võNû|P†=› rƒ´—‰"eQ”ÀàO¿®n¯oo¹Á`ƒÁ×A®a0?Ôë/îvWWw÷`kÄCtmð Q4j> Îjƒ†AôQd-Š« ^6 žS"ÛsEÑÃÚÀ䔜Ã@¢¨“{0h«ô> °}m© E£6à2ØêGjƒ§aŸEù„(²—”Èó*¸{i‰|¿6¨çwýqwww·Û¿÷Ú`sŠ>¯6È­6ø4 î‹¢zTׇÃîîJ_ÒÓ’Ê„²¸ÔqŽëÒ_±‚7 â™là]"?d{¹†=pŠÖlà_ÂÝ{¡SôøÂy‰ ìŒ ülàglñä EQžÁ žbƒ' Ó|Ä)ZØ`8EKäš=Ÿbƒù©\¿üãê¸ßn>Ï05¦ ƒÍ0½ƒÍ0}Ô0E~ÃôT§»:n®?»6ˆ¯WØóØ W0° 08cƒìºÀ Ï`kƒË0@Á½rmpÆùP}^mŸ6L?]øKKd»Xp¬*Óï³ù êÿaƒ9Vê*2Û h`*ØÀ.Ÿ\½p?¯wWT§ë›ïÚC~‰O´U?|eð¼ù+ƒÝŽîÙíñØšˆs:ÓDýÒûš¨qÁ|ºh¢û8ðgk¢|ž&ºˆƒgi¢/&ƒš(/?ÀÁÓšèÅ~铚ȕBƧtu l”ÒDŽm½E$jž´ò‹_š¡úˆK8ð dÈ VšhváÔzg ØÏ_Fø—ãþêîæøXaસ¤‹8 5]8?4w ‚x¾€ ¨÷îvŸ ì v‚‡d ]ÀPDqVGƒ€÷(©˜q ÖdŸAý ­h‚à>ħ ƒU}쫦A~uH•—+p6È@§øDa ZŸÂ öäPD {@ŠÙ …Á®F)þr½Û_ëëÕž,Ÿ"ÅÐs ä¼\ Çyeç8h*®µ*íiŒÙÏqð8Äš T Û²}iœÍÁŒr~Feð *¶Ÿ(ï“_EGkøJÍO08p•_P ûÀç`ÿó¹"{-Š”çÏ d }Ó ƒsT¬Õû/ ‹º¾>ûE]ÀAºþ ü?MÕWe0ÿóQô¬âÀBr°âS~Q)ªŠ¢–EÑP!Çã¢Ä ¡&2|àÏ©md’OTÈÐg8P$‚Îø@1!åtŽƒ—ˆ¢Ì§"Œ¤ ÓO6‘?iÁQÙsàÀ#Šò1£è!Ä}£¨s|PCÿkÌ]ä_>ìîŽûŠƒ‹EòˆÞGøàÙNQ~¯ßE¶sf˜ú«é"\Ý ‹îŽ7×óTüópðø3‹ä‹õÁÂyÖ8°§ŠäXøÀÏq`uQ>Žƒ‡õÁü»u}`¦.òs\ªÈ”O4úÍëƒ(>ÈOòA\ârN<ƒ"NîÏR©;ŠäXÉ©"ù ñÜ"¹ns}´H~ŒÃÁ#ƒÝÝÂןÖE„zë"þÁ+ÈOãÀ^¤‹jdž­p`ç|¦o“ð\uÖºhÜ$z¿N^pÀyŠqÑ÷Í¢s]ä/ÐE¹àÀã|кè^œ}ék¥É ¼¯‹¼uQž ×½®.jˆ8ø]ôèHç|à•¸ÃAýÞÃA]çÀAœãàvw»Ûϼófk$oäÏÖEùL|íFò¾›h7§»»7ˆƒÜp°áà[à`ÿû~¾éàfwuwûâùõŸë"{ÎtQ6ü>H«EúD­µÎå:Ù?‰ƒ\5“?§‰fŸÄ —êäÇqâÀW8ð/¬ÎuÑ#õÁª‰–÷šh_VØkÖñŽè¢ÓÇòàÑ>Ú¦‹6>øJ|ðÜúàKø žÃ³oúç¿ín¯ïno¶ »¥N6»ì½¿ »|‡vñM'ìö³iÿ¸:^®ž;a'à9/vÛ˜Aàç ØîĬձ—MØ•÷•oHÞßr+æé¸?Þ=a𢆼q"ƒ„ æý¬¯f%)×{É*Ï*ìQÓôró ˆ³¬k¿$ŠòI2x–(j84}‘ 4\ôPšx@kÄÃᢇ8*Ø…á¢2p¹<år‹Þ¸ªh.Qäƒ à d�Fqc¨ÂŸE1pDÑœ»BÈ]‹¢X‹¢&ž¸èçnPPà=(ÔQYá ¦1qqÒt?7þòëñêöxuúJ·$³*/áƒ3|›[’k#ßv39žEù˜(z3Íä|Æ-É—ø /óAD|Prá>\2‹ê.sóàÏ¿wW×w—qà)Uô¹8˜WÅ?³8ˆ3]ôq`Ÿ‰{UôÔðSC/-¾"ì²Yd_Á,²¯ÛL>ÌwüõÃîxw}Z¾jÌ.SÄÀ/º¨ ~a¨ÂÎp`K‘¼SjdöƒI‹Ü]ýÙQ$Û3ø@E²]¨ì‘fr©Öô=Ð÷Ì¢G‡**¥ C—ú8làÀÎq+D›¦YÒyËb¥‹øü‹8¨ØCÓ´4ÂÙ]„žäú,ÓÔÏ냸oée•®Á‹ÀA6gfÑ£88²k³(VæÍÊeç8ˆK8˜ŸƒÝ0­@°/Qtuµ¿ÙŸ¶IÓ‡Žé削ü“¦4ëâ@“¦¼÷ÞDŽ"ù‹ÓóÎÁ9iz˜ï<øË¿Ýïnï¾à΃ìÛÐìS8XÊŒOvâñ"9VƒW¿óà 꼕;ì²(²GÌ¢lä}øE2ˆü¾ùxXçw<ÀVËÜ+’?uçÁ¡î<øãíîú¸÷,ʼ€ƒçÝ–üü"9Îqð~nKþÓ´ÂßÉöé"Ù¾úmÉ:Ù'ŠäûfÑ¡Ÿ_ws}<~ßâ º:ØŠƒ­8xíâà^‘lø šÿÜv‡ÛíŽLø Ö8x¯º¨ÈúuQóÁpG&?EÕÌÉo…†»²Nïn¯ßæÃ}/©£­¥ü÷”ã[·”Ì]ß^Ž×?ÞËüªv•pï§JÈ­Jx—ª„ãnÁÁÝ|x‘ˆþ²{j£JØ^ô >xÒ=õü¹^tÜ/ ¸y#d`Ÿk= ƒ—ˆ¢ ~j2à{ noo¯¯®ÞàC®W¢è)ËÈÛ:}H-#pkØ£svÕ¾ù’ù¢ÚÖ•et¡T¾„ƒÇç*Ü2ÈKs¶à ï“ÁÓsn빊‹dðƒ>äúx\p°ûáD‘o¢hEâƒGDÑýËßêbÛÝ]]°žÊH é8U© ‚wr™ÉÜõ÷ÕþTæö'pœNÒª¦•]P­NýLŽ^PIR©H"8Øü9ÅjsŒN ¨^Ä3Wp I8œzQWŸ>«ÄßÇŸM2-ëÖ!ø¯)®bTÏB‡­M˜´Â•«¼‚½Ö¹>¤.²Æ1xo²zc§Ú³’}å#+ò3W˜õÕ­yƒúÀ ´²¸HR"ss¶Î˜Ü&6›g½1œX¾êT ¼êËz“ ¤ÏÇÍ£ËÎðG‡¬U ²à»uùü¼A“÷º£øŒHò>ù‚ ½ à˜cjª/“fÁjR™£ŒÔR~&yu§ ü§ –˜UñÒ3E­½Ïuœ^ÿ”¯¶.èY…_ôǸkíùÊ«ù™¨“²ûpÃ+£­0T?l Yc¨â<¦6ÕjG*ßb†Öéú Å} Ec(¾CöÍ01”ßCù†üó0dÏÁç˜$Z0TË…™zÿ Cóyñã Rÿ< Ù9†ü†j`n`(†ÙóC ZêKíC E->þ‚!!cÁÐAº:r;ô{ÃmZa(6 } Õ#þq}·»½ºÙ´Ü¦å¾¡–ûL ½=-w]߉{µ?ì*ü, Í‹þšºÇCùy²×Å?‡‡¾C†Å#{áK1ô™<´Æ¿.†J³¼ ù³1T€ýmws}µ¿~ZÎcÓr›–û¾Zî–Ç(nîÂPª9ÕÜÈN7¡¦–Rª-®š’ž¥3}Çáƒ&A­­$3ÓH i‹mcÒ À|6.h>âœ%œ¦šÜë:#PnŠíò¿+t­i­6ÒÉŒTGÅø¯Ó»DBØþg²¾tE¡ä M¬~üÔ ›¹ä+‘a‹;m®2á«á@¸ïZ=OÄÊ C÷™LG¶D¬ä£Úóh­Hˆ÷CB›•¡*?àÿ Oå“9bh* @sHԦȟéÒ»Zû›ŠþùÖ2_z/PS ÷IÈõx¬ÚÃ霄4‡í꟠\ 9vŽÏä!BnZlí;¾—b<ñœÁwGB?›¡¯kÊÅDBöHè´`ènÃÐ;ÀPeýÍØ~KBŽoOD§ DïD[wè ²o ¢š^þíæêúê¸è݃h³¾ íËÛÞ§Ýaëmý¡·?ëóAt(n®ïîžl²æˆÚóˆžl•eÏa"»çÍ Dö4ˆêY@ ˆRÞÜ“ ò'@”„°­AÄ.¾¨A”ÏQ{sÜ"{ß›‹ˆê%+åc ÈΙ(Ö Êså7Q[bÍDÛ³ òû âÊâˆrí+l "ÿÜÑ€Ö}ùýQ}i쇿×Ç«ã×d"Û˜hc¢tRoœýÇqwº=¾Ï6ëV½]c!’šèfÑ;™ÝÎ DïD?‹±p[ š¿ãóøâ>QlL´h_m»½½»:íÞÝÑO>5÷\à¬q3½8kÜL/Î7ÓK³ÆÍôRà¬q3½8kÜL€sÂL8§ÛÍÖÞÌ„W1ìç2êë©ã×ãîx{x'uÐ&á6 wOÂÅ÷•pûChÜïn¶™Ó DßD?Lƒµ¾ûÏ»»¾Þ_m¶ö¢oÊDù£€ˆoÕ¾½¾Ú÷¼ÜgÔDON)|FMtDù"šÈ^DÛm¬Ï®‰üñš¨î×­‰¾=ˆæÞЇ¿ßïv×Û¼Üf,¼Ž±ð4ˆ¾PνAcá–ï!¸¾»¹º{_ Ê DïD_^½AÕ÷8]]]Ÿ>_ÎmL´èåLôµäÜ·Ñ©¾ê°ÛÞm z³ z^Ÿèõ˜(¾/ˆWõå³»ýéxý­§€hsç~.wîG±¸»Ñén8\m÷¢¯ ¢W˜X¸¢ïÜl=ì D7·7ûÃöäúw,çü"ˆÞ^Mô# ‡CÕDûë»Ýá«Þˆ·è'ª‰Dù“€èX ºÚn®·çn¿2ˆìgÑÏÂD×¢5ÑÍÆD}Ù{ÑÍ¢÷9;÷“ßCôÎŒ…Ó»]@ôÎäÜ6±ðΙè3Aô™hžXø«oN§ÛÝ'AtÆD+Í«¾  ¾ ˆ¶Ô·" DgLôoâ›Y?üÛátsw[DFîŸÉên^çô*zæs¬+¨@0S+<ñl]¼.°‚¨>¨"Ö <^Ë_œ¹qÈËS˜qS ŸüUû”¼ÙЊµ‰vfó71¸´TñSGŽz«èЮà—ñà;**Kªl.eÆP:„8¿B²ˆÍ?”z¨•ãú”Kæ÷Ì_¾6¢B²N¢^RK¢÷Ô•„‚¬â¯TÔüM½•´áóÖ×òÔŠWzªaGç*Pæ¾ê`]• cõIÔ+œí@«Ïy#*VÜ’]êßó§&àõYgQû^_çÌöHòC·YKÌú±kõÚµ’–ã»>€Ø¼ç„beS)°ú¯>]iêã5{j-jí>™´3¾×…˜b:XÆù*Š?͵& ;`¨m²§ê}¸½:쨎^O±áiÃÓÏ„§jýz{8Þð+?=Š'Ûð´áéSxª>Ò¯‡ãÝÝq·áé‡ã'ßðômñtͬêÕñú´ñÓÀSnxÚðôYxºalõæöæxÜðôÃñÓϧ÷òûâ‰FÓþfsÚðôfðd?½S~ª'¨þñöx¼ÝÝmxz+xŠØðô>ñtªîétºº»Úðôfðôåüd?©ÞûÎxª¯‚ýë‡ÃÍîúêk7tm (û€²s@ÙO¨·W@ùO¨})¾ÓþæxØóP?œâ³·¨¹¥û¯~µÛ_Ÿ¶‘£§õ[º? Þ2CÅ/ÿY#|þuw{u½+‚"êjÂÐ9×yÝ\¦‚!ÙkvÔČĊ¢Z2ú¼Ã k¼²0ɘn}P}bäĦâóÿéêØ$$Ù3×Xd}Bamªë. 8SŒµ¬ÑXBHáh>9DgÎ_p"€³Ú{Ý“ÂÖòÒ>AãÓ& 3/u½?u÷I]TíxApþEá<8ivb_ÀÀ‚J@0¯û¼’Îâ×2i¨ =¿9C¯lQîÜH dT›4¿¹2Ù’ùs&†“c`Ø5Y­¶¦ò‰u¼rãMVÒuÆs8ÔÜ´÷Âna6j ˜7ÿiÆÄÖP2§ò•Õ²‘LL@Qvž÷Ù9T]_呌^š Ñ$……’fo\OÌróŸ @÷°¨ŸO¦oJ]¹’ÅT¨3S„id·æ¸u[Š³Ú•>­ÇÈç5µ‰áã?ÙÓzŒvÆ`‰Ä‡ùž¨ë ƒ?! Ñ ƒßƒ‡*Ôv»Ã5Vâ»À  ú÷À ýHÜxð»cð( ÞÜîB Ú†ÁïÁy$ñO¿î7»Û­ü)µè†ÁïÁyŒÑ~;žzLäå´Ÿƒn|M Ö·‚üíx}8ì7OægÄàV~w ÞÉ=Ýð¥"~-úñ}7 ‚ÁSiÑÓþê´ÿL-úóñàU~9ý­bÐÞ k,óÃ_îöW»ýñ ô7Bÿ¾ÆèWa¾cnDø¥ ÜÂëãáf¿1áÆ„?ý€p_Oœ»¾>~„á „ï„ñNA8ÏÊÄ?v7§Û« Fo”ý1@ø^åè±@¸¿º½;>§&Ü@ø£1aùGá{aÂkðîævsG"æÏÂ÷„7ÕªßÝ|»Ù7al ܘðQÆOš—ùõîöxsØæFÆšðG2fÞ«½«ç3_íïn÷Ÿ90ón@h?ÆûgŸGŽžê!´×§›ý§ï$ô÷ ÂMŽnLø&A¸¿Ú@øsƒpcÂïÂ_¿s»?^rGóG’£(ßmá „õrÿ¼ÚŽÇ͘ùé@è›} <Ôsuw·§ÃõY³¾BËë¢êŸÚµŠ®ZÍŠ%íN_¼›qÂÚU0„ó_ Þ ôIãøsU”9 wJ¿ðâµÕÞÜ^OðKÅó8þŒAï3¯ ™7ÙÕ:R]Å„®JêØÚˆ5ç áj¦å¤úd8`í¥7=R×?.ûã¿§à}¨èmçÍ–ÅײÕRq:ŸÄǤcãulR86B/x¬&¬ë£ \µˆOZ}–«-DU {ƒÐ‰v„öj- ¬«U–ð0-΢~˜õàÁ \O¼ó„@Æõ1„Ç!×I$+ÎêBLÁ&ö&¹€·­Ã“ÕæOQ×ÅÖL\dƒÕÿò·©Çþãúj-‚ËâSfôE&ZVÎ^þXl1ñœÈÊ1E“zîc%“‚R­{*å°dPÒÌDVRÜ"ŠšWe©ƒTN ˆ3*‹p°ùq¥‚¦A­và|˜JkµæÉi( v\ÏìËéX}6™#ëÓ‹ˆêŠë¯Â^e½äº¦ÚzN/tH½@`ÊÜuuÆ|ËÄ&Qè͆u1ikVÌfÅ:Õ’Ó“®ÓÈÌRÙ3Àçë y>P%u‡88 ­v­iJxd‘Oý,뽤Øù€MŒ,í|äJ+ž"ÍW±GZéOX©¶×–ù>úåUâ¿d…+³zO­POY­í"ŸÕ‡¡ÞÄX|T]ˆ±(jâ3*A%ˆ–L-ÑLãJ&Åq@ 2Õæe±\m¼rÅÚhºbÕ ÂÚö¼g–hÁUY &ÉXAbûzÎÌîöp¤Uñõ i÷ i_É\A2Þ$óË éσd~;HÚ—C2ïA2¿$í@’±î«ÝGš<^‚¤=É\ ™Ïƒd¾’ñÕ é/‚¤?Iÿ*,ùbHæg@2^Î’öyÌG o’ù HÆ´¯Éÿüà%[í·Eã‘;-Ú´ÑFVAšòϦ,*˼ h\‚©ƒƒAõC:Ŧ±Ì¥¼‰¶¥•_L¢¥> <º9¬\êB›FÒ/£…½Ä"JSÕ_'íœ7Ø4Õî*òä‚D mÝPuXm.Š©L®¸ð‰ð‡ÿëðAL6 $µ-õçd| ç\Ù;Á)‡5l°w,UºÕ9êëêXïQ€&õX”·ÓÖU”Z—sœevp¤Fzéj1¬ VéxAó()Ïss@éQæ=ýýä縶6‡*C°_šCdÅœdž Œe.8+»CUÕ0 ÔfíÚL¯0¤…:H…ðö LÎhFt 'ÎRùÓ+4׿u[“º6§ó´66eq(ÇÕ¶¨îîWýnêÔŒé.±–6KÆ ð¬×¢ç>À¹ mÑæ(¬Jóÿw*ÌëãŽiWJ{_’Gæb·Áš¹¸!+†'Ážð©Øm÷7ôsW”§På#¿”5&¦fÇõA>öô u¥šúìà’qµN©(YŒPcbc^™©g`å 0rŠ)Yvèju¦¦G õ*„IÌŽ´áîUögͧ-’Àtä}sl)kú©+Ÿ„SYÉAæ/CÁ­‰ne0‰ŠÚ“b˜†ÉÎ0íD¸—®‰i¤)ÌkîíÕ=0ï3{ÁÕrU[+F%ܵĂ»Ø/E'óikÓ@C}F˜Œ¶ºæ²ÕC…Å£S‡”f‚jŸmäû\LIošÙsÞ›´Îýê%£`kÊ’ÓZ,H©s™LR9&Ê5E²\ô0ê@•Çzƒ5J½'#.”žazߘÞ}]LÇ#˜ö Ó?¦ímaÚߦã•0ýW:ý›»Óáx;5 ØÌ1†%!•üf¤ó×dà®fù4>˜¡ÆC¿ýâÖ¯ŸÎß=G×âC…ë>€é‡SPÿV~àИÞôJ ­Y]ážt²e º:j¡Ñ.5{ÂLê3S§U_k+Y^3¿/T?¥‚94‹ªò€‹S啎WßZnÉ ´b¯™H¦<™‘ÓH×”c?T7úh¢Q;UEÐÓ…îZÑZ…IÅ<‚ºôИéÜå8âµ ~ŠžDÕ»­‡)7Zm4JvsE¦7GOÖœ NC\!±Œc¦¶³ZIZmΊ·¶³VaŒ¸“kªäú!mí16q]5ñõétÚ]·YåÊ4¢:_®*ÇÛ¡š…çá…Šî"äJõe#áˆq”iº?ÕÓù]óu‹îÁØ„FÄ . GÓŠi¾ü¢M¥±‰<›ÈÕØD-(’#±ŒÀ#š¡¨ã|l‚Ê®•#k›Š’8¤%œ~ehiº4<›heÅ2‚‚öèØDÚjl"ÎÇ&z˜·Æ&Lk*›ªµ}9æD0(M•±ÊxŒM” ìªK‰–öSä@”W¤k“L.“Jyî{86!Ch=6óRNZ³$ ËÇÆ&ja^0É$ùTÕÆØD#“ʇ„W‘«± ÃB<›HÒ k¤ Ëþû?íûÓü8’‹«ãéú´Ÿ°”²•SE†ã­µÊп½fŒ$L²÷{Âñ¡i ®”}w A?ÜŽlaØ ý`RŽ ˜Ö>ÐNg˜S®†œÛ0!WqÕ¢GžŠ9sV›Ä>Ð+gØéW‚Є ð”ò)Ñsm ÊýßÔɧA’91BÊÙæWC2ß̤µ¹7@¯uÌï:ZG…Ø<¿…³Æ‰ÊŠúPŠs…2óï'M<…®œýÆŽvs-pA Ñ‹ˆÙ*E€ËBR(0°µNÑaC‚ ™ýÆm &% ª¦Èöj‘õ“!“ÄnêµhTi¨UÁ&¯TKŸL]¨Õ"USõÆ/µ$ÍÅž ñQ²XÄEGÚ­n”† y÷ÜËuŽ¿›ÜuVñ_Ê b¾{ B†Ú©Ä¦«µ83S:Á l?-uw‡òf‘S´7Ë6Ñ™siFÖ· _2Ëã“ÑÌ©”%ØÁíÂ|/»Q—Rg¢½œ%ÿîI4ìTŒ!+¤1H!FõJ[i–KÉ=è½G漩é8GÄ€)£Å¶¸¸Ýº6°±Á^wQ¨•Až¦l“á­øè Ç5é‚"¨@V}Ô—ÔÄÓ°ãµüÏGª q¾íÄZ>ŽmM€©”ÏÚ<’Eƒ±`*UöÚm¢Võ%Õ€š[²#¬¼^ENN³á502¦lAŠ$kµ³U¯kwÈí-;³‹GU£ì:‰\ÃZõÁ(^b“7(H¤¨@~…Õ•¥Èt ¾ë|W(Ò6-Ö<1¨¯˜¡’Íä?;¯Ì«lç,¦UwTç)ÒÛ:WyΛæTÛBsSó\7W¸Þ…ç ÙÊ5ˆ0ûRU¹p.×enÍs¡HùŸj´M+žËæ9Zæ-ä]:%¥…4©“L·XxŽ—©lÏa4­i.Êwº¸bB.ÏY_º5ÞÌiÜ›©³‘rÎs&z ÁÐôÌ!6¹}!ÈVÒlÔ™¢Œµ¢lAyiñ\¤ù«!Í>‰4_!mÊlAi÷–Ÿ4ÿ\¤í¤iˆ¶E¸DÄ Mu¿»Dä8Ò>gÑ›!óÊdæY{6b_4I¶abŠ Ÿoõæâdr¾’|D¾FÐCRT½šæ4!w©ÝrASçHCCÎY¤Å¥Ú†ˆü¡!"µ6~ÇehéÒd X—ÿCCÎö%í‚H³FZh=Ò 9µºUM‡³R3‚[­£FFår¨é²BþË9§•§®Í@Ížæ4—WË:t6Õïâ4Å:˜!yZŽ T:³Z…¶§¹åÄÚe»‡´\D¤ p[×ni–mn5ÒêÓ%"•˜Ù¸i¡hÀ”)¤ÍÂǘè¹ÄiÑ Fý¯¥·¢¥AÚnAÚ2|÷­æ‘fÏEZ>iþI¤ù§–oi±Bœ–f+¤åC¤yýïÒb´|M¤ÉÿÒ²‘FZð5§ù+ Í^‚4ú·ÏAZ`?Š´»»i×jñ¯™­£¯oxIŒXT¥žÔ¶Ä’Wõ[¯¦c"¼¥%]³FuÍ‹zÿcÙÒ»½ ®^Á‚·ùÚ¦v%ó o«l®†Û‚7x›L¾E ÜqÅ Vú¥+¼U‡©Ìs¹êv_Cªž÷PQ€Ã>ð6 Wr…·8Ç[œkHùÎAχ¾Ìlñ³1‘²8/áí)fë‰ä Ìf·x oÓÊ•|1³1ø8ìå´Æ›=·ie<o •§(uð¥x›Î·¸’wGç÷ç àdNÞ\,€ Lž3ÀåÀe.àZës¾º þø\ÀùkÎåGÞ+ÚìQÀ=(ÚࢠÇ׆3í´sÀ9FJ6x˜šî|¸\ܽ¢ÍÚ€sn‰pjP®‡Ð%»ê¼8ÆHæ_¬çÖ¼&8ö¿‹6ö‚Ø=À6ÀçÙt#1Ëqú³£hsŽsÎ8ŒS;·GZv0X¢¢ ?rä9;r-gcš”ÒSdŠn`îåÕð†˜­‡f¯ »ÏôÞ[Kú¢%SmÏB¡ŽÖ’Au¾´Ô(€»;Ü,•Ãù_;‘d¾hë?Õ ŠXq›tM¶–ô'¡–r˜{6ghIü‘'¸ÍZKæ9·å™–Ì ¶lƒúaÕ6tuɪ 7:n~¨%»š 5þNÇôÌI˜ o\w„@QˆÖ’mBg7&ÄmÝŒÃá —ü‘¡%Õ8‚0‡½sµB;‘u)®¸-·©Ô1uœ¸6æ1'’LªŽ[Ê7 6E²3°-¶ÿm=,À4Wî®äk²'SdíÒœ'”k)2;ãJFê΂èOºÔ`9‚7ê>píBjgs´Ú€Œµöñ¾*1õ¸}½¥QJ’ÎCYE$iÑQïNÛ¤4æ¹ö#Sµ›Ú­ÓWÒÈ­)£ÚAµ²©#éÁÖé´­%À¬ÿoLò‘ʺ´ø‘\'ÔfÃ̮ݦsjË–b²yƒ•b†¡[mœl¥6™LH.[SvqS[´–ô–V°[ߎ%¯µE®DŒŸ²Ï*å­"ê|€Š‡¼ú¶#§_¦\«Fx›VîáG›ÚÔ6dˆÒûQGÖ°ŠÚKK«Mx£UÙ ËÂY(Z¹¿¢ónUwí»¶€• ‰2‚)Ëш{˜[·»sf=XÚQüê˜ËÇ0—¯‚9ÿæb`.>söæòæòù˜ógb.ïaÎÌÙ9æò1ÌŹœ\û%±’“aÎÖ˜‹'1׊²ÛÛÍg˜ËsÌù=Ìù9æòÌ™J< •\À\žc.Ÿƒ¹|söÌÝ,Uܾ~X±’]‡¡®HFȩֲ6H¶<”˜úMÊ‚zJ·uKmÔk]Ô¦]Wõ¤†¢ ®Eé Y’ÉÅÆpË‚6×Y é†BÏê´éÚÆ«]¼¹µºmw²jŸÊ"S¨R•¢\1œ¦kâEY%`•pCQ’Oj§´äjš^5¬_”ñÔŠRq-µß‚°n´À,ÑlI<èŒa’uñ&Å3°<éªä–Œâ-{˜¤¶)•èâvÄfEšÃ¾xP¼…dy ÷ñX@œžDÛºxƒáL^\¥ýz(nÍÒqCÂ¥vØ16ï³äc„±y+ER”ÑŹ:nµ6‹M²»»®çöN7‡ÛӔЭƒ'D7?XRÁXÙª½{g3;äB“ŸIÎ&+×éµFTV²K)g‘j‡|(ƒ†<ŒÔí9êÍ?htâ¸.“ I"ˆfø"_*uw­áø¶L[‰¦*;»´" ¥Vs·1ºÝX®Ö%—…è¬/[h>:Ó½U dÿªó’©Œ\Ù÷ª¦Õ㨮¶É¨6à”MÍ;_©€lû @NÞ;D­ª É…8Xç:h²±«Õî¼ÝÊÕähôñ”„•C»ƒþHkN:8š›MAá]»uL™KΔµÓ¡1R‚ :í V›zå•¶º^;§ÚÝ8ÜmpØàðÞáà_‡ëSÝÂv{»;Ñ&Ê£¹Ä¤nªãßÁLÎí^ì¦×ŠË¬t<÷0é^*nvÍÓ¬éx}J9ZÜ—¥»ª¸àD¦-$°*æîí„ì6p±p½;ߦ€S5Á-GÜwÜ#$·Q탾»·¹´¹*¢\KÀ—G¯¦Ôdߦ¥3b5B“GÑ·º9æX0çk}ŸY7«©òÐ7u¸ $×ÿ&±D¥SÕÒºKrVMÔiwÒÈêa(Þ‹»}"ô©4`ÀšÏ×? -}áÑu ·ð÷Ôô•Œ1å\ÇRÍ€içTVš,XîPÓ0mÝÆ„ÐøósüéHmö:[ƒG¿þ²ó &¼Rަuðë¡îkÕ*ŽÐ7M.T ¡Õ-ü2Ã.7è!þnüϘZç2ó¥ÎÏVþ$óÕéªÓ¾f¾ÚÙjRÎÏöÐì º òjç{6GqOÌŠùÆ÷¥nB:G^œ3_ÑÁ ™óÁä ÍVÌ—ƒù8b" …ÚyòBÈó‡ÌgzöóéSMš“lòÔ~g‚æŒùŒ»Éï3_ó5òzY˜ïòÖÌ×kƒ±¹FÞÌgí ž1¡1Rãs˜O„ÓÌÍ|óE’ùˆ•Œ+æóÁ|2â?Å|î óÍE[¥ %#וš°+øô³‡Ìw y× òB^]ižkN±CxKŸ¢&ç¥^pW/+™ ŸJӂϤÝv@D“+ØÀiEDyÔÑ™fÐ!—¦“¾h.{þ”ÒÕó<î¡r‰¨(+èy²„â0‹ÎøÐTFƒ2û¯gr´:Ò}™}JÖŠ/hž4( uúMÐa}5CHÂyÔø~N‡­X;Ê 2kTÒ±ê|ÄI×¢Õ EÓ¡®fí†Fe4*SÝ”´îÉÑé\†vÙ×tÈûò”ó‰L x¿¯G Ë ôÊ ÏvqXâÊ%r4ÎA x<†õ3= w®èÈ[CR7#¥´gØ^Þctx\@¹¿ʾ×ë+ÒïÒÞ!(óÛƒÒ× ô·Ê.’Þ(ý[‚Ò?”‡”»•FíÙ€•F8Kš„D”¤´PÊVÎ<‚/ÛÀ ËèâÉâ{ü‚ZY‹®<ë tá±Âb.õbN—-©ŠÕ­¶è‘gÅðvÓÂ\Ö©º’j­Ì{~gW^ |¾¬wíלáÏ×ø[û5ÊiÜžÄy(¯ÙR5vf¿ì—ʯTûÔ.4…ÝYÕ8üšùžóSOì!þ˜3.uE…óNû¥Ê±öK¡Bq\SžNI¾–f°ªªÅÓÒK™hØž”‡Þ•`žv¡»"·+ºÄÔ@HTéèü•¨jGb‚z@†(º×d>J“Qãö©UMzfK 6½Å(†¯V'å¥Jü`ã ãS>]H·v×’ÚÄÔ«óv„ëB&-4ªvCã5 ]Õ,tØhËzj'ô&53—h¤=ðT±*³¶b2i>~;† ‚„Ô÷´»õ= s’ 2 Œ “lÐs©µ‚çÕêÐÄ4íKôm‡Áx“J®Íë -c}L‡d*&çQÙ§ÎÈ4&3¿›'^ëàËõkÇ™ÿìî]ôâ»’ñ$”³‹°’­¸ÿÀãÍþp:n|ƒŒ.47¾€ñ~xø=~=^Ýî§ €¯ÀܸðÙ<Î_\}ws¸Ù¸1à÷ ý„ôæ÷_>Ü\§ €¿7ß2úWàíü¶·W'Ý¥ª;‘7¾n&Ì À»€Wû««¯kÂØÀß5?O‚æ'xj~Ý6ÄÀ €_€öÐ^€»ý܇øm{¸»º½„@=bCàÏŒÀ5õÍ_ŸÁÉž‚à+Q xêPà£ôýÿ_ ùÛGèö|Vâjm8>¨y¸ÂŒKÓîÕ‚ÐʺoÏØîc½çO­S¯ŸÏk ûQ<³o2vµàn5OQ/ã’õhg&›Ù˜‰7ƒ3Á¾Öž2(X¯bœyE6_'ƒ‚êu÷ºñy)ܹQÑÜ%§x+ôÕ&+AU¸×Aˆ®º¼úÜùpíL8ο ]%“}ÎÆŠd…‰9—À¯ëL‘¨-¼ÕsêSë 6fBÈ{¤HrÓŒ>iAŠ#iâɈ»úCÔ ”ë²ÃêpuI 24ðb}$ýD›"~4ª«ð ÷ãÅ D’÷ÍhÉJ¹‘ ºÌ)¥/ë¡­¨øžÏ³'Šz®xþºÍnÒRN§’­Oo‰+¾æ ¯—˜~¤¯á4©* Í¿Ì\ˆ¡6¶®¶¦ö“S«ˆœ¸O2‚à&éºAÏÝ5UƒW0H*voߨ¥M%³fgaÉ(º+~š’äΙU¶Ä©Ñe‡÷+ìQ¢.!9+©U¦å«ZrcK¼…y]¡Õ,ŽÛ#ܬ4 À*µ$^ª¤àiPÝ­U¡;™!íês*ÿÔ[ꚇ.)~zð·Dâ8|ïm]dðx$ЪH¯×ÎgÃ3á/h™¸ç6”Z¯¬ ÐR@%b*R@œe3P1M2Ñ,@’MThh¯¦Ùº–\¡ÄÊ×é…°Eäºö¬ ±V[ ¥þkJTNWòøsÔNΑ’˜dôZ³–…C¢±³žŃ¥”‡xp¯%°êD…VEkŽ9 ä>v´0 =¤\‡z©£¤›1?u>t ço@Dèàš†6RÉŠƒ&"Ò«2FG¤ÅÇ™j†Æ+JY1A­Ðl£×Ã͘ArHŠJå¡Â˜ëE1µÃœ¾«VE"%í³dSéÈ'‚µJ%ªãuï™Û¸á&¬Ë†šO7Õ;’†(2ÕÚ¬ÍÀ¿÷Ã<æ\SOe£°Ô#ÈT½’˜„%V¤7ÚukS}Ãs=mr桺eî·ÓþxÚßñõè4Evÿ;¹ñÃV5“$2ïÌ=uIEöuÕAÁmb'ä»QátÐF7EA‹‚@j]Évľ* #òάÙ{™ÄÒ¡ì*O_I¶Î™Ì^³§2%ºÌÈ©®z™'Zô› „U6e0B?:G³º>ïË™©Ät“šRvÙäœnÄ׈ðœ8h¡›êÁ*´ƒÌÃö«ÐJô:x×5g§54†VµÎã‰Ot<$Âu‰ÔùD:H¾„댋tþl“´¡åK ÕãQC•]=Ó=VÄÃå&ÃäfTè [í¢…&'_Í”³(` î}œɲ÷‹Ø$7+~-[R%§“€ÐˆµS ¬TÕ’ûÞRØXJ°e…äD†@-‹‘»ž6­GØ `Åä|°ë±âíŒ2¨äq°/¨:¡R»P¶×„¯a¦bEÌ‚ÈÒšÕ©!?RtÉÂBb6è‰z‰s…ÖÐA/NÁAÒ¬'ਰ1=W¥D(…©Ôe­Üé·ùæ5!“L š ×Uðg›o³¦v-©§Ê?±-Ø$«/…#Õ{]Ô”ýIhsÔGÔÞt%T'cZ{[*¾ ŠÐ(üšTôÔ£‡9}ç1-}*b¢£·.¸wžEöx¯o —×lØ­•pTØeç6=Ç–¨¿F NYŒoø+Ö $RÅ€…ÕC»ÿQµüíæîúJÏñצ\²”àRý+O8q®à$ ZÁ‡A¬¼‰-+w›BÀšZ1)oMDEå¡òIU)f–=D;ÃUšt¥Å¾ ñ£V§` ü¡ ’дP2à“ì–!›S¦/ÅŸíè3©Þù«ÈÉ.­C–AµW\yUÅe×¹Él×CqåS¤ÎBÒP’‰Ksk)’eð;5Gšµk‡|E•qÑʸ» ÔZm†ð˜@2ŸËdm”xå—©ü YOµô…8*/…rYD¬3ù\EßTR‘©ê¦rF«zµR8i3Éç2CpŽCónÒX¨„ å4NÄdÌzqîâ |®”w*ëv0eàÈ.Cá˜uÝŒ|ì”$އ¡DÀôÊÈ óï§®“"M²¹¢Ë$W6â¯Þßz&u¥‹W8jè¬|zL’Æ>a´ØRqá‘,aý›…'\_è ¦ìv(ÕÖN [h¼¶ÊTõñrÌQ„ª7 ‘ßA¸ìb_v†­ÏöáÛ„ØVî,݂؆ígª6R»…™£èJ YØÚÑÉÚ³Q^¥»”ªmš·ÐëíŒMíá´DJŽÄiW¼š+6Äå€Ö¦.—åZ¶ý BC[YGõFNõf·>«±DªnDÌ ZjE(忢Ð%7­cŽÇ$¨é:¿B¾¸•¦¤·R‡;CA¤B~Ž›ïË™û}÷?îÄD‡»ã¾™(2‘oL´1ÑÆDmL´1ÑW`¢5Q=ôø·ãÝÝÇž¨‰6&Ú˜èÛ2QSÎÆDmLô0Q=þû·Ãõþxu³1ÑÆDo†‰¶šhc¢ïÀD¶1Ñ×c"{ЉêÉÛ¿]ww×mL´1ÑÆD?5}fMd}iMÄÝEû»Ãn½1ÑÆDmL´1Ñש‰rc¢'˜¨¦¸ÿq:÷Wß¼OÄgmL´1ÑÆDýøL´ÕDO0Q}éÈáx»ÛßnÑÆCm<´ñÐÆCß¾"ª¯¿úçþps¸:5åÆDmL´1ÑÆD}#&šyè_óútwsͽDœNý«âwIâ\?¶C*ÝM¸¸Ö ¿²u+r}´Hˆt#+¡;[¡õ©(­d —tnP~Œ>òÇ—L+ ù# äwçèg~èó` =¦R³+ ­ˆœŠòî3P•væ·Ô“–R©GöÁ@ZÌzôQ-‰Ä›ØMÀ™7ƒ¸ªï¹í-æJ¸€+zìÆg³þó æRÿ÷vk¶âiÙ Dúà)óSºê»uF„¸ÒVó_’÷æ ¹Ï@Î}þ y3Pa×Èr}Í|¬Àí«5æ÷š0PxË'<,ΈƒÌ/®ã(†ÎiÁ>öN b³ ’ÿôLBuÀnÑý™>Å@Ö $Ù7´Kð å—Èg j­Þ$…¹b Aù®S©‹Y1C@S3P“¨ˆ?ë´u‘Äh½ŸÅŸV äÍ@ö€êOZÔʵùMܶ0h3ëÁµ]dÚXíh–Þ—b:øÂü™TSBúcçÓ§ÖMl7T[a]©7L™°d+ī̑&HŒuM¦SY®(qâÓ# 54M+ÑÀ  •ž‹> \¶>”î†øw•'ÒµHµÓú™ß.¼¢”Xf“óüT…ÿóÿþÿ8ûqþWW»ÓÕa²:x Em²¡¶I:ð/©©6©êÑeÈ“¨Wðœˆ2 ËhôH I»Ô‘JÏ׺Î+P[L±Ž(ø:ϬHž)3)JêÃ$6²)ŸäjÚ”Pœ¢?昴ܜ-û¬œÐäÓç\*„ßòלÄ…¹”œ+ÙľUñ` €Ü]1%&¤cmNŠ¥4=K„'Óp"MÝu¢µsÿœ¿?ö?®vW'¾9Ð(I¨GD£UØò£^O_AŠÔUÕÓg”„ É^¢KJ¼hƧ!Xjqëˈ+3O Í>\¥¯HŠæs„að½Ñ: °RÏi“p²F¶£hséñâÇ 8׎ê¬ÅÈc“+̃O$Q¸J·Y½‰zð zF¼¤?¡XKªqk *áN€+Ô€Àª³c!Ɖ4sÔYD?s:úqê®J¢?Þmw7Úý¿>nõÇÿ|Ԉѯ–S'UI_qÉ£›¨3 E¥$gÍ« ª}1Ê‘3xÔ\É$­d7(­ê™ P+UÈg¿Ù˜~Nݲ¤B*ó¹¶ÑC˜L¼¡=–Œ‰.ím®e(†žÅ–ŒxU•M½¢ÞXp¤ª‘`ò–BY¼ë5 ] 3×uxòH3Ø#‚|@€“ÎU>hA(deÓ¹Ëþç_÷»Óíþ¦AIú{€}ȱTÂ3»ôäºúê”MuNΊ(]†È&WÙ”h{$çY ’ÁyPbȾª7ð€«³ljC,/›7böËÕîæîöÔ •Ù TH¥T¡D$Š´y*ÔXcÁÛÈñA¤E6ÚRÆsÁfmmÕÿÅÂ[,8+7´hŽÍ‹ŠTë͵–I ƒ3Ò]dz)š¸K­-Thƒ Gz6[Xªp’k7 þ*NÜÙ<§Xi*,‚¢ø.u,€^)JmžEûcM…ÊËd=6ïãÞýóú¸ï¦âW†] Øù'`¯»¼»|¿°û}ÿû?ïNw·×ß8a~jç¶„ù‰³yºù—ìN×Ç£f47R?´{–MËT7%þä ¥JŒ?°‚UôPl¡¥P%1TÉœn¦¤¼Âky)38Ãê6`:Ô6aãIÙSLVéÙ~4JÎr8Ð;ÄFk9ÇÈÑSUãªIc#Š¢?¨ÙTFˆ*OL›‘*ëݲ~‘Óeb͇£j‘Ú¥¼t$tfíbio™/:mT›7ß$e<]ÝNû©âÝ9ÝÔ'»tié.ª±:ªª=bª—´gã¹ZõXV½2¸V+‰A«Þ™Cc½ê9³:^mµðBëcŒoQq52én]=VaeÖûÎrÐaÑ‹¤½¥¡Ÿ¯º”}ÈBçu ”AýàòRúºT*jÕG»ÏÇ’jɯ÷ûÓíÕÔ¡ð»Éd 53ÔnTL×™Ë: ·3¼œïœ3áe윯ñ’ªñVx9Û9»°ss{cÙºeçSâÁÎYt ¢Š Ô)€×ÎôÎ|–ËÞ¹;7ÑEMUõí\¬vŽÒ¼Þ¼lݲsÞ;çì\ŽÛW¦;ÞÝîNwcçÚ¢j®NÈW;Ç^à=u|¢á2¾Ø¢Ûî"P +§«ê^¦©2ÔM¶yÈï©Ú5Up²sq¾sØI¶+zlKPÙ¤b¦â,²vNWµd:TZÓ,føT•Ò½ ÙëU¦£ˆse:D•.'Ú!å8Á_;çp 1áʲ‡ó×)Ü]d«ÏÞ@_o Œù¢ ô§70°Æ–MwasEU~¾KÒRƒ„Ë ó l‡_½Þë ô/ß@ £²b{¨ê± üçü=iÿz}úA=ý5!’T¿!­ Kšœ„±Äd[I”g²ðZ×Í ~Ò­6ÖÓd×WôÆ÷µZãíòD•_ºfÂlƒ«Š$G¢5zl‹ÍZé´2¨âBb-ÂúÞh5×u«àƈ®ÔeVOΪaEKhœÉ+U§V´eÓ¤oÞ¼…ÉÀÁ°IÕïP‹õcmMþi±»½:^±S”zÙž²KÖRF;¢\Xj ¡¶_…´Ì,š ­eš>àÇ7+OYJ1iÐØ0~Qž¸“å2Ò0Ë+LMrÝ:î3Ùh èŒC¶Y·&©Å@؇T±ÐÅþ³Uw#Ê1ô©™­‰®1To޽M(´œ™õU`@ ‘„œ·Pç2C^¯u(ëÿp}EíUéÁ$Ó» MkŒ> T jÚÚ³O2Ó6ª‰KïN=6fG|‰M˜S‘Ï.ÒÈ1ôTñ¢(ÅÍAG²áã.•D*°q9ŒÄî¥ó7™•Ö¬/}u=¤©¤¹À.à(›z†Yösoa™«´Î몡zh"uѵ Õ„õ”=Kó­Ô—:,­‹0cµYÇßÿôëá¸?Ëî²D*@™SêjבÉ=~"˜à™Œ=ªp#3ÑåZ¨£ÔAhdÃÔT«óz Íèaè@ëj•EG¶šïXg¾’Ü]ßxÇ…é¦1®•¯*Su9T¡®la8á—1<‰ Úh3,—ýR{Ñm˜ †8÷öÈÖªU;ý*WXÃ*>f¿?ýºÛí?þ‡Þ •‹‰Ž;û™ÖÒÔ€ªüÑŠ9UqWIoÝ<§a)¯¾GŸd/(ûyiÅjÜPH`T×òŽÚëÕMs›f}1Ž(‰…ζ1,[¸¢»sŽÁW“6Àz•ýLþ§²©©m_OÓ^½Øl¸-®R†Ä1æ$‹¾kÙ&øFž©I³6‚²õa&©ßö§ãápý3W\H ÑZ-’Ên>äŠË6¤Ôiwäa´#’²þq‘MR(BŠ@Úùó”Ã&˜ú>%‘T ’²v )%S:oN; yfLᔜTi™ªÕÎHÊIU³CS ¸q´TÊ­ÒZ`¨nn’1äÔI¹Ê<×ûÚ­ð¡c’úE6ÅîêXª/†âXõ8스ñ%Ò¥Q_±I œÝ$EÆË&©q8w}惤ÈG”Kx…7¾ D$_@û”µèp%=‘”«w Iaª—˜|/ñщZE:¥¶HªjuARšGªýtwºÞɇJWÃt~´)3eï§&mb¤¾¶\Áòké (¯(kk8 ¾Ò4­·×¶vsÅ•UÐ ¼ò•¸¹Nß.å>•ÃT: 7BŽk7W{Ѿ­±s£¹ tïfQæ¤þ¶9ŒZKýú2æaÙÇÖvÒÊÍUîu PDôÇ“bkï|?Ü©›3öâ­ÅЇµþÖ¸§r©X‘j'  1´¢¾ð–¬(|Å™=è¨=ðGÌK¸K£-K PèY}—£Æ}ŒÄ¨¤ <ðn9c«´/¡ÚuzäÄ5o ËÁ”Þä\|<­öÉÛu‡Â¼y ÙÒƒ¡Ý®9i‚¯ éRšâ­eŸ>nÓÇXK“nÌcAVÈ_朕 åÔO ÍS°À(XÇèúa»ù¨·œ8é±úûvÓqñõGÝ"^EjU#,%B¨à©ä‰‡¬AŒ8É`Y–»œ*ÍMGO€hRW„¦ ºRî@³·âSk×t©¤G¥Šþ9þ ®Ód•²å'³:.u@C±h@‹¡GítÌHår˜Àúü]2tJ"”n4qß1Š!»iÜN½j©Ð×C5þñcÍgþç_&¹½¡ÅBg¬w«Ûš›HÔ4s@N±³ÌH*)ÍЉ:½[Ý]U”ƤÍÚÛ‚u !‰šì)áS‘8ÑKVþ¶õÔňD=ÌÌÚŠy™'Ù+°Cg_µÝ¤#5Á+˜¨a’n»E·ÝF«9H#w¢¶©?Em7“K¨%¤†.ݤDÝ ìø?HøÞÉcUïWWûÓù.ÚûÞÅøÞ»˜¯³‹ñ¼]¼þÝþrsuý1£/Š©Ç0üÁâG§ÄCqרBh õ:kæÁÚŠÉÆÌI7¸±ÊFT´f a¤.®u^cæ¤ûßøÔ´gzæÄT‘¸†“+6»¤‘‚n«Œ¥³ž9‘ÆQŸQ½­ó™FPR_÷×uɈ£ÿͧéȽ…ÉÌ F¬JH_m!ц8@²Ž™“í„9‘þÏW"ýZýoï~Ö3ûßùFúߣÅtÎûßY~ÿÛžßÿþ˜>?îß?jÿvÇöÏaoo `µê;K¶ rºô€·àx ¢wì‹Þ?”ÇÒ¢lÆbðûû×£µtCMCµ?jÿضX·aGM.#Ìt*.©Kq\…8­BôZWĶ2F=`jÕ5Ÿ÷‚¼t’mkÛ„ÍA.¯šyä©U/È:üXpツÍÉòÃÁÜíñöýbο sùæâ9˜¿†޽Ç0—sñ2Ì™„ǼÿëUa^ínN| ~¾¬˜ü[ikW‹–|^êx²v4ŠŒˆÃ.¼ëk÷´Æ|ëåÇ,êþ«ØM;ô‘=hžÙEy†u«7£ýÇ2å?uŸª¹rTªê¬Nï­p™uÞ>Nªl£•Š*RŽA؇ $]y‰‘ûC:íÔ+\aH""MifÄU¡+ŨTNš, ‡j»Ðå2¤Û§ˆ‹Õ¹ÔçVÁf ö/uÆ`w³eg§Ö| Ù]Á©ÖûBÝi’í‡{‡µg³%Be¬eèòŒ3¦-ÑWÀþ“þk¦äÉ2t¼X(c¨kñ?<ºU6u<¹kójxƘ ³„‰Êb4+ê#}ê–IA¯TpŽ¡¢¼ÊdjFj^dWGUÜoÐõ¸B$¢ûîJeøi±³½8Ë5Æ zÝ6©Ôó-­=t{ynŲ́·{¨×„„ÑF÷(]nwêÒ+¸¸JSZ IÈÁ¨SÔ;ÁŸ4¥ÑMÕþ—ËD†U l {çèûñÚÉ0·¬ï 1nxŸçØË–§1ŒçP¿2”BØXvo/î!éj]èGƒ¨cÈÄõY¡fSadRæDÝ0u¸-—ÓÖ®\½¨WSb„, j2ÀÖhGãC‘ÝS[Eî‚©ÐÕË£€”P? ¶JÌÚ¤ÀÙ’­s‡ëàJ.íÔЋVÓÄZÍð6ëxîJÒ~ÞhMÙÒìȳ)Û²ITÞ…wG>³å>£~ÙtA,c£k ¨ÛäxB®¶Ô|ç‡×–ÙBžW0êÒ5¼PƒžÈ É åë$d®cò.bàx7„ÔCÓóê°ß_^ýž*õõ·{B蚺TÜ+ÜÍSßö÷»Û«Ãîø&nè±o½yùV6Ï^¼yÇeóvobó¾9ò¾ææùWEžý~û»ýòÏ?Šúë)÷¶Ps¬ ÊhsŽ“dzRqâh;ëè<üþ—···ËÝ7ß=:c‹Î-:§ÿí¿þ÷ÿëï˜Û6þrwss£ÇcWº×Zó>™¾Ú~m·ª¨¬ vïÝB×Ñåº>*¢o¬ ù~6×4ñ01 W +0y]ûòø¤-×§hÛI“#b Y“ÑXpëØÍÑ “K¦:6¸ ¦.R“˜L6¥(7T0ÏÿÌ[ùwTÝ ˵6Ò5 Š^È2~9Œ#5ôº.[T—ÖÙ. ]zÖΩÈê¦*Š]½4) ‘ N°7¥J©!—á/D´5©ªÜU#N’m¢8Ën’€Fù–%D˜ØÇ÷¥¢›h4ÐÊžCáJ5pXª¥¶€îj=C=BÄWåLúaË+¬ÿü0¬Ë 0ÍÌÔU7®ä£ASÒ§r!ÓŠu[XŽ)1¤Ä½dAq>ïÕYÙX„TMmeHTd*|+H( ; Mé¤ù‰† ×0ŸQ…¾^éÔë= °¡Â6ʤÐËk••¼'n…ÏÅøáŒ1& £À~ ê²2{’6Ç穳ÎXñnЄ8?œvÿèµi¸¥›L‰’dsV-arIWÊäëÔ¨%IÔnMÊ}p”€ÿ–+v¢¤cÏFDÊ V¯%ûÅ,A²óD—º¢”¢Áá}L.¨Â$Y¨“%‚g¦¹¤0“Ü´è9~¶ ¤â\ñ¡g]}5ªå®Ai¤åjÍSX¯˜žº¼nM 6N,1,T!—;Xnš††¦èxãf Óf8×Ý‚k®»¢µ´“æBØbh^dŽf”ˆxM”†W³» 'äP N¸‰.Tƒktþ Ï—ˆlCY1(Mê~j€z¬Ôr7QP s7@mÃYG[]3ùU㮡DI ÕeÓ¥iù5mÝnÀHkQÒkîXÅj/0•Ug@Zeæ$uïÔÈ h²ÞÀ¶xÆODüó.€@É3þ·þQ²LKØ2aR鯜W¯\2›v6G«Œ‹n/‹çŠªIßC7 )غDÒ&p‰bíJËStc<5EbmìÊ8¯lŒ­™"´61uëbwßGì¤Éâ"Õv Yû`* çA#<ƒóònjë'YIÞ;y¢ ê©ÝìPÓfJ"3@ '@s®ó$¼«Ñ*dB¥Hû2©S°¡OÁДá|Kd ‚Yï•â 2Ž ÙääSXº$) E>¹rnõÎM),ûLçŠ[–þv~¤ªþ·êfèµ£F)®/¥7ry@—rÀØ ÞÖÛÐum1mt©,¬øÔ¼ï›±®%5q`ÞS+®¸ÈÉÅQ’£oÖce}߈ôi¨W“Eêùqɸ×F’O…’8šŒŸ*+ªm§âNètÝÝ#Z½ÓV§]ŸÑ‘l½«a”°5*krÏûü+Jë©§aŠH™Ã¨&­\f*%Re]-ÝTúÚDÂ!t¤®]AKw¾Vo¾|$šˆ²Ó•ú'\J§Kò¹+˜ ¿“2º*½l@|§fˆ(¤êBœK(Pö£b´ÞOö¶ dˆ§^4dÜ„eÍeSE´p"ƒøØ "Ç\Ïø²²Úp]Rä Ê³ùÊTâˆÜQ+³Jyè!2®¶‡Öbƒó¿€s9_"VåD›æª»˜·é¬8ÐmÕr=èG÷G*drÉ‹h;¤š˜UF‚¢TíF‚pÖ)¦M1=A…« Á'`C‘`V w°zÑÚŽK©TGÂn!Þ‹'+ŠxA‰XÕ²®ˆ×´º T´ê¯”ÛVáÄk©”…ì kªXÚæó SeN™.ú-+ª!’ÖÕA!›ð¬øÏ?Ì]Ù¿n÷§Ûé{AŽ)—•_LËJmÓz׉D…#ˆ*–1õ2CÈÖUœZ¹s¶Žédm"Š$9[OM·£ÉÒ*ú\5Ù 4)£—¯ë~O’*9š&AÒÔîn®)gfÖI[¬¼F½’ÖV± êõ’#YwˆŠú™‰&ù,£‹?@ܸyösFвÃÉQ=ømT×WÎä£q-«Th÷›OvYf”C¹2䃼óxÂÙö”'Ö ,k‚uÅúâØýª<Ëk¡åU0V¯™r¿Öe~•N3¾ÓJ2›êT§M§$’ù”¢.¿bֹȻ"t½{¢èK·6àh,!Tº£lfÏC„Ú.õÎYYuBIÐèGŠ*Lmö·KåÍšBvd¨µÑY¼BBýÉ=Ä–Ru!™N‚Û-(&U¡v¢¨ªbhy/QV‡@è2H:‡J¿qö•ÛXçÔ(È|Í’¢iò¿%BK™a¯qûÄÓòöÕ©í¡)÷ÎS«,õEvG»t›Ý±Ù›ÝÑZï²;~ûÃýT¦ÓñÌtºXƒ>³ìR úÌtºXƒ>³.Ö Ï,A§‹5è3KÐéb úÌtºXƒ>³.Ö Ï,A§‹5è3KÐéb úÌtºXƒ>³.Ö Ï,A§‹5è3KÐéb úÌtzPƒþý5ÌôawÚxÜKJŽ˜©E“ºo“øR{0#Ÿ‚[¢)ÒÄ&êChÈl”—•Є&³¹}4ÏMU!©Bj™Æ˜ÈrÞÞ©'ÞºkÌù¢ êÍ´£ÉüãD :¨#3¬Å™“ ¹f$ËÜVj+T•’uë²§hÞpÉQPv÷5SÛ:¹r ÏÈ!î¤OÜbHÆ*ѽ”i5ü(iU¾wDÍlƒñgiÃù¯“°Æ º†(Sµxªž“ „†T Ï‹Æ÷1¹‚¦‡ äãˆ1¸†Z“ºM¬éY¼—h-.kEÙAøb³ÏH5M²sˆ¥<ïŠDh‚TD@®/æÓD+9!Dz£OÉX´VcDöWxF$ñêZŨ ÃCD©;&ÉiÝÇϾƆÁe,Œ·Ï`U¸Èਠñež¡ÇºµG¼l ªù{_è~‰-LÕªwµ#S9» <‘¹ÒëÆ RQêò£Í Ùµ–]ØäÚ!M£<Ùn\Œâ Eªm†$&ÝTÚTS©½NBxvÚ6xÞ&¶Ç¤9š–·L8YÈ¡DºQ‘R€ÖÚ4º8_n{i^\ªq?»ˆ:xКÆH\z!‡ò·‹™V€4—ZhéD z 7ÕÈ]SãÀ(z•íÊ×­·` qR!î8SkBj2¬-Wø‚8€n?ª”Eí…jåî©)OÅò šîò‘>k\¼‹ â>cÌP„@÷Ñ¿•Ö)¨*T•I‚•^\ÈQ¤ó†©¥á=¬ÀÈ‚„d#n ˆÁ„°‰a£”µÑ–dG”Õ†R§/ÀÅ;ª´N•šïï©Óˆ¡nFØâó`¬4~0…#c¤ [ê”Vˆ žù<|/‰ÃwSErôål±(RA]÷º±t¨|×cLî‚<â1ÈÖŸ^§[3>R&ÇË´Õï} šî­ã˪>›ÛëÜ…ñÿ¼€£vYN–/éž’(Â2Ý8Vï„å ½.)²MëʦQëi©H\,fåNÀÒ@R—ëF›,úâɺԮ¡5·`jHÚ¢n'ÉKΔ\‘ RI!åía#Ï':yÇëe<CÒGCªTB¡F~Ê-sÈ+ʶÇåOKáY÷ÒuXƈíê6“€–Æc6S}Qú4”Æ4'ÐÙ£’†Oª¨&—ˆŠØ5TZPy·`à|W™Íî‹Æ«¶ðÞŠIÆ)ÅÇÞZÛËšš°~ð"›]–»”õ°@Á$Ø×TuµËÌÑÎÖÙšn?uá)Çá%P9ó ›¥6×U',þ¥/9I¸Ððí}p …ñrå^Ö©vÏÖj/MË ˆw-çÖ%;ÎeíSûç²yÂõðOÝ_ÃU«øR–Ëå>¦2LBú…[±tq(ç‰)Ä5Y &Ó±ž#4¼â¡CLaCÀt$ —s*%3d|¶Ê ™ÈÑw¶»4þÍLœV¨ŒÃÃÉ+)kkæb=£MDž#Ôµ›c4™ÊK4½ÌB䥿òÁ:ÀvǸz© åÈͯªÂ›}'• £`'ÜÅͪ $ÇMXW〆K£"¼i–l᥸€$@$ÆœåjZ(ÇfÛŠ sÉ,'ÛŽ©+ó.܉Ycê^âó£WCåLc— <;‰YDÄRe»f• mØt>u“Ú©ÂÉ)(rÑ|Hì¤qTMê›àå yêCZ—ˆ}§MÆ’O­Ž¬¬Ãüí´Ûº!åÂÎYx7¤¤ð .L–ÑònH‘ ;A`—ùŸª7¨ËÁœ éq`„(J¥DùC£Ï@CJ99xD Ý(9w‹%‡e—bܘ¥7yuUÐÄÒ™Þ. ®OÆSÄŠ@ ¬äí½nTv7JfWÔcÞëF¹JX n”5æ¨v´@“„ÂJ"gåãg´( ]æê2Q µY–"AÇ‘ÝN×ß›õ¸%)í˦ÃÛf“´!â£É†ƒBœ¶{œÓL«nÉÿa7*ºÅ®Å$ËÅq…De›ÝÃi,Ýuw‘‘ij°£á~7jå:„QãÖÍFcÛÉ“&9n¦=ïF…ø²~;E[ïí{²Ç® üÖˆ%j¾êÝ8ö·Ew£¸Ï65â3êX5‹8 :|•ç(Ή&„pªrC‹uéÙA­S»h=|{±xÍvÕOkï†^6\è=|+3%:m-"Qʾx ;™Òô{U‚‰ÛjõnÍ º1gú÷0‹¢™Ò‚Tc´J§CxH<x’:^î&—1²J0t5ñ9ɰE|[ÛVØAð…£¢oDœd}A¥IÏGÎy™¶,afw4¢/‰€²aªßþð0[hìpäQ)\Isí ¤‰a:xu:˜¦¨RºÂ–ÓÒøPQ0‚IŠ ÑF"vf5…Åiò(ÊiKVX´ÞE!k*eJu&©®›ç¦Æ>ÏIQÈtïH «“„å²J5õ–3#‘ªÆ«©ìæˆns,£Ö&ÎÌd*O”HÌ0Š·Ë(uAN«´döYf©8Së~ô:’Ô›|WRz·Q*Á»ÒwDÂè¸ùa¥˜A¿½—¡üÝ¡•"ËL*[@¡êr‘KÇEª@À ¨r]…Eü$’VµÂ肌 i­7í¢$,¥"Ùu;Ô[W‰0É/F4à`,¹¸J¸#¿vÂ,UXcÉ:£c ü\­SF¨ÈU;TáS„'7B(¯ÓØn =$üÐkù­¦Àƒ«uÅäªTa”³b”Äž}=±´nЈ¢sÐ,k¥¼7¾E–é·@fxSáBJŒî½§zVó2×70HÞívšTœhç”3ÛXƒ~&Õ@ÙîÇ(ò•:¸Èf¥Ú¢"“’_Ù‘XeEË.½Ä=zA£ ¾µÅ(DøýÁÁì…šã:cGX—©í6J.—¶G®šê0Yci]y’ø Hªoc™W´åRHí ›±Ö]7‹Áé¢")Ãì.#Ã/>vX–½3³˜ØèŠxzÉt ͇Åêj+‡üå@¯jGhA«MÒó§¥d·†´Ö²¹Š²œÎÝlI„f=>€ªäèrŠ( ð{a)øÛ ç4Ô Ðõó}å!»’rM)ž‡qhl¸T»‰b -ݑǶ0ºFé-«GvD¾Ôµº¥ICÙкz&·IޤÆîLM[´´*JÓlÿ˜:Ñ´Ä¿rÔ@õfªï\"Aé2šÆåjxHͼ.“†å‘ÀЃk2¤¿Fž³P5R"†oþ~eˆ#¸!8…7«Ð|×·ŒLKËD=! (u`˜yŽ®õÀnà<ª{’*ÿL†RDz©Ã#E R6—Ú®)Á‰cªdC>»‘„ðþ.ê!bBódõ4Ce”‰"5ðr´wÑ$Ix€‚“™Ì««¹ÇGúaª©ø¨M¬œdjJµî,9=IFk{³^•6Þåöá߆ث¶ecF£àOMÅÕy:kî-,C×&OöïdFg[7À 5%̾Ö:„¾žº; 1 JhÅ–â¹™ ­+SqŒ²Å{ÕÕŒ·R€Êñq‰ÙÊ,жÚZv§]ÍÒ¤mÚå•jàIÕo˜|öì¬œíÆ³´â}LAÝã$‡RZIqe¨ªQ÷G™)eêýô¾âqÔfç&üž©Íeñg“ ‡QI’§ˆâÅ"d}¸`oÝ()²ÎÖÐbí )QreÓ&F—ïŠNYRºÝÒ';«Êå¡p¤Üî’“…¡¬–©‘¬«J´Ž,£¾šW±åRTuXÿçyX¯~m½K\ša‡/ÌÑœ‚é5Ú §…­’H®·(›×K(.,_FŒš ú9ŠV§^•ÿŠ3Éÿ%"&É3éøŒîqB ­sŒ ÷‡†iþÅe%õy´>†³U-š>±WžVö¦Zom®äÕV®FbXÒ@Á·ŒˆY]Í”ú]wÞâÑ•f k%)©™ÌA¨6ašÅdªUª'“pì$2F ¤[³{¿rµ’þKeÙIkk-D4ò€ÛÙµ<þ0=ªvÖ<ø’¹Ý’îßôÀˆKÊgJI[›bSûq„å(ndÖDËIM"Á´qÓÒÇbKHÁÊCëó~Ý~)dò•HízûjC-KS0ß'ŽWñ‰ã‚OœïÈ'Öyn>ñæ7Ù Ÿ8òÅ>±?Ç'öoçcæ=H›™÷¨™ç/3ó¤R63ïSf^¾I3ÏžoæÅ¹™7¼}™yñ½Í<‘™—?€™7Ü$èfæ}3Ï73ï;›yù̼ÙõXÕ$ù#¸ö ]»ïzÄÚõkøÍ\Ü\{ó®‡#×#¾¯ë+×ãðû/ÿØ]ïn¯÷k×C·Û B·g$ú×ðE\„,×$Z«"Ãï›èê1‚£’´álµ[Ûä«!›HjhÓz:)µ{SŽf¹ù%æ _ë!ɦGÕ„È ˜5Ø\1¼ÙõÀ°‚ä»›%© Å€-Û¬Gæxc˰ù%ÓÊ ±ÖršyT~¿^Y!dçÉåJŒX©¾-U΃^sƒx“‰û»å¹h ¬áúh¯'^Ö^HÎH\°BÚÔeMR§£é]$NÎ:)èÍL솨WJ¶­W~ŠÕÊ ™B“B(}%m{«Â‘¤FYŠL„ TÐ×%İBšR4»lZ]³¼—¼[aÞ¬k"îþ(FLZ ©XŒr¸ùBƒ)¶o+„‡¨¨/ såÀ\ÜÈJšÈ$œT²XëA›dÞ±¶ˆ;6,ˆÄÕÈÜý’>ôA‰×Qq$Á¡­»Q#s®¹õ[»x¡­éB~ÐÚó§ÉÚ1 ÁjœUÖ²¡sQ‚©jÜ5ÝMéN(›IvësSÚɺ<)mEÌ%á ó«®» (dÈÐ*”öðìpD ÙEa-ê„QŒìáSg)Ϙ°¾¤gä¾zŒ_kdΗGeõ¦YÎvM•T6‘d"#| wõ½ :†àòϾø)U}c› ‚©sîÌíïE–>ÉåÂwÑ–{ä:ë»00Úæm˜L®YûÔc¹^.£MiŒº'‚Íà†ï².P–€šK —ª¬í.ϳ¢z±f±P3½ÄFtUN®Ñ6Ðä¶mѦ ›Vu/G}TÈÏ×:ë²qfuŠ”¤öXŒ¶ùÚj‹ Á£ð$é¡/ –íSÀZ¥`ÑD*¹¹˜§¥~1ÉZkWô—×%WH9²>çEoÜ™”8Xµ(“δÅîP¾m´ù0Úhdmø>ÆÍê@äÙ‡•‚¢Ž§(јbÙ’]NQ/ð¾ì"“2m±Ô‡­èŸ¼• !Ε«œSY¼(rÙ$j´}ôúÉõRI.¢†Zhê°85§¡µXŒ6—”˨…«B¬Ó¡`lÉx°Qœ¦7îÌ2q]3äá½Côbc§nÀoŠà>$uvæWþÿì½K“Kr¥¹·_Ò½ x/•J–¶pHΰ©ÕÍê ìÙMˈ´Ìÿ—©ÐósÈÈD÷I‹·.‘îfú85%±Ÿf ÞJÎðÑ:¤/L§p¯¼”šU›öŠX]im¨óµ“Öª¡l€Ò>SZnµ3Ž…Î;ΠÏiˆ62ä •;(.iŽÜZÅÕR…œY]çCÇa@äNoM{ðt¸‰éY 5®T!¸3Ê3/˜ó™§Õ R&¸àõr 3ñyÔÞ´½L½ÄÌ©¯ÎÇÓSm°úp“¦ È£«ˆ*,‰©\²®[*[cú .¨Ùcrér‚©uäÅ_©<§oú)‚ÕÖ¦V˪gCèz§Ä8´¶Ð¦¡ÎmÍ&Š€^,¶l™· •²¶´üŠ“Ö[Z»ÄSׄ'Ó:ɦY‚Àü¦*ûÌÁ«¹)¶®´6R& õC¹—»@- á¨íœK_Í„§„=¨†žr¤”R¡LŒÁÚn¤´6ìSEÈ4\ü¥»|´•ÜÝ¢d‡fžf)€ Ëk)™Ÿ€Á…tM¨KgÑßJ1TRÇT¥y…ùNévf‹‰‹t×’mn½ªæu#«þ¬ Üé»ûš "÷Œ•X- øne:‘4)’›ÓU¢j„¯¯@fpìE5¿>à´BëŠôÓ@Ù½Iž†¼!Eb `4paÿjç”êæ!C¿,»ëÏʆVˆ-«ä¢oC¸c?í ^Ï1ý+h.`¤¾&ìÝŽEáœN½k^Š TDirSH¡«Í¾ÜÄԪ建 =j7ÕŠîUjëÚØÅß°æà Õ› ²VÕ-¤D"”%5€íi¨—ÏÔ…„h¼É"ÞÁÄ‹P1ù1%HÛŒZüÖµäÍËÕâ9‹øKªÅª`ù"µ8«Åq£×.ò·jqnµXw/U‹U5ŸT‹ûV-`w­§†B&½Ÿœ»§ÇתÅñbµxOä¸óÞ¨Åý´Z\V‹Óµ¸_¢Çjq|µ8^ ÷V‹uo[-6«¾£ׯ¬÷Õâˆ{jq~£Z|[B¾J-ÎÇjqþ–Ôâüj±{"ã_R‹C“‚Ф“Z,$qt«Åš(=ÉÁ.“Ï«Å}£c7…ZœwÔbuº³Z,–ÐW¤é!ï®i9$O¨Åon"«¬‡ êF-îoS‹ãIµ¸_®W›<5ž|O«Å#tº²ƒ¿õR专ZÜ/V‹Îjñ†xF-Î=–¹ö{·ß;j±øc>¡×Ï¡¬5¡‰æçÔ⸫Ãi2s#œx^-v©zN-6yFMé{jqŸæÞ]«g[åF-Þ;,µ˜_î ÷‹Õâ~¹Z,¿÷F-ÑÙ;j±å½¸NjqX-nÜð¹ÿgÔb#˵¸·Z\¨Å›²ÍÒj1ïò“Õâ¸V‹Sj± ¼ÔâÎÅí-Nj1qV¤m®=Ìq–p¥Ûûfµ8Ojq‹=lµ¸^¦ÇSjqžÔâ8:j±Õâ’ZV¾ ç Õâ`àê¬w?¥ƒq©Åý¬Z¬¯½D-îgÕâÚjqŸÔâY‘j«Å›{…¹ÈµX‹¸˜C-vÝM¡É†òŽZiØjq>V‹Ûó_ý„ZÜBAñSÕâ©Ùö„P‹ûëÕâr=V‹ƒ9°;jqÞªÅÓ‡ZLí“”8;~¥_ãØkµ¸¿A-.«Ånƒ¿†Zœ_¡æ“ZÜJÈ__-î/©ÅbÃ)¥çWªÅnÑÏ©Åûœõ·¨ÅùÔâë°ÖY™þijq}›ZÌ*žÔb• gÿjµXà±Z¬jÛWjqFOjñ¤ÌjqݨÅbH[-Þ­÷;«Åúá%üÔúø¯ò@}¨ÅùSÔbuÞ­÷·©Å(uõ¼Z¼ïå µ8©ÅaUµ) ®J[-Önµ¸oÔâÞÐÜÝõ¾Z7jq¢{{P‹Á¡×j1<ù®Zœj eðIÕ<±Õ¦zB-ÞÝÅÅå'ªÅS.ûIµxK%_R‹ß¹–¼ýåf‹ùçµ8î«ÅÙ?i¶øP‹Ãjq(¦ŸW‹U©µøÎlq³Å+x¬+V·ZÜư±­÷³j±Â ¨“úùì–nK¬;ïKf‹[)/v]nô¡ñà}c®¶§ö¼¾|Çcð=-Ì*Óv¬«é|I-p:©Å_˜-N—Ö›ÙbŒúVµ¸ú‘ZÜßW-þÖÙâ—©ÅýH-¾-!ϨŨÔâK¸-‰}5[,î(Ã!{‡Zì~ýH-®GjqÝS‹u!<9:ïªÅhxWjñ†„—ÃОS‹B¸û¢Z|Ì× |X-ž%üÊÙbQ¸/¨Å¢ßY-Î>©ÅyO-î'Ôâÿú7wy Ðß>¼}xóÚß^`þ&ùJ¼4OümVQú|¥Gß$o?8Ë–:ꤡü¢"詆âÂרï“UüQ¸bšœþoQEvp»–œ]+Í t#rù]f̬`Ï)mþ&Ã[ªk^&oÂî !Š!}!¼f)0±–hØìÁàÚùb¹H'×´+h¥n%Ög4Ôö²¤zF»Ã¸AÍÇKòQUAÚ➥„7…ÏZ xh‡”µ!”dzË.˜{.\uw÷àY©ŠS³HC—µ[ÒÒ¤¨è¼Ø`T=˜ò(ŠeHc@[Ð;i— A,¾ÒÅü¥œW‘}úkµºò€KóȉßMcPÇ´¸E5ú€‚¡{ZîÜa1T‹9sŸ‡eÙZsÜ@_vNZŸ Í’¸-Üh¼zÒ f€ ªÛ™ûó¼>œM‹*ÞhO¡ >™ŽE½˜v‡<šioM±H¹+qSkð»’Ï‹2*!÷¸Þl]ÐîB_®•$Æ9\€N–Ø *}’fáÛ jV‘9ÌwÒC¦¬Þtj†ŸE£:+9­}«Vs¨ÆPQË=å©0¹‹PHT>³ùP-@·êìˆñ£Ø"͕ǤhóE%ؤ;‡ba1÷3Æ/FðÚÓ¹ Îék©¿Ëòª@ñyˆ}¨_xó™ó)¼i‰›¯Bm…GonÕŒ°KK$O(ÀÖÁ?ù‰hˆ ³:X0Î’ÛšÅ_¢{ºÙ ÒôÛfrJ@ñC±½|üJ-F§ ¦k ŽŠ*°E*8júvlÃ¥@aÍ•ÿŒý ·±W©–ÊÃ148°sÍM>=7#e_ðd°ŠÜLuÅ‹V*-ñš©Lâk¹¥+,*¨yŸöØ’®ª^«óN:¡¬¨ŽJˆlñ#©sŸQö íP–$[ZÔ.ý9"è*^ ˆ*§i°{®fÂg…5•Î’ ¶X¾¥+u¾d懂èÛ¥T£Šv­i-­O[~¢/Ê/#&—ê6:‰"ßÈ|¡îe|JÈáGM:—|c\K5üÜM¨$8–žFèžÃ  üST„*+ ”RcË÷”!Gâ48,ÒG3Ì[X¤¦;÷Ž U‹`ݱ§º3Ú`ÁïxS\&t ‡½lŒläѺD°j£îÐH]ÍHøÏ4!jvµA˜@Ë87™óËÒ$@ñH‹ÐWÚŸõ¬¼bì<ÆŠT‡¿zð¶Xí¦‘94>DaW?L7Ì[&“BÈ!v7LM<ý~F¼óÍ«êS1Vz¦EõÞb `'‘ :?ŠqZXÖ€á +£mwgw•EÀäO¬zVd6A³zZc pÑ*!Éõ—§0¾Ô˜Tê+–̼«´åR^‰¾®ËÓ©áð4†” ÍСa"“Ä/i¹¼#úœ¢­¢–•m£Ø®§ò=« AºéñYÖdQaµÈ†KçX¸6{Jèï>?\[ÿáÝç7ϨÌÐ8ˆý†^‡ÊôٚϗTfå£í²%v[O«ÌVs3--ºTf@ù=•YMÀ }«2—ت‚R!{òˆÅEQ¤î«Ì¹Ufc ³Ê\_V™ë+Tæø²Ê¼ñÅIeö=K>BóÊ|Ve†™ÜU™ûZeÖo!í¬2÷Ê,A’c=­2oìÕ[eî“Ê\;ÈN*sm•ùÙ§¿´æ4¼,Þ½“°n²A½Yš¼vÝ¿)¥M¹Eé˜í6jPÍ/ · RƵHD3"¥;J=ª\ÇHÉ)–C¤Ô ¸jeé“RùÆè¬6¾Ø"%6þ@Æ[‘R•ÃÇ"e܈”K¯Þ*qqÓŒÜ)i1¨Eü 7ò¹G@ê‘H¹6¤(z»µ¹äüKŸŠ|å);-Õð$R*-”?ŒJœDÊØ"å¢Eú¯{¯­†7%¿&¯ ­Ky!ŒVq%RÖc‘2 !‰Wšƒâ=Ÿ)t¡U¢4YOˆ”i‘²O"%ù½„ú)53´Ì)‘2‘òº¦¸-«k¶È¶H™ `glu¢Çº ¨1ZÜ(Ú½Î|e¸)¶Ç}}‹Öê@l1ž–‰”qG¤d\íF¤L‹”õ‘²—KÖÁvß|Ž¿¼úøðêõëó8'ªûóÍã`õ.·Ð+®û’œM*N[g$Tý˜|ø3ù?&þè“×Ù>ócòá™|€Tü˜|0©ø1ùðu“ ¹_hòáb=¿ýk±xûñÓ«·ï¾ÖzÎß¿õ/´žÅ[!îZÏ _ø&ëÙ%+¹òè=bey¶NœÚ¯7 µõ¼ušÀ2¸µž‹fb™¶ï[Ï}ßzŽ“õ\Pz\àDwíNZÁå½ ±Œš”;Ïp‚½‡Í÷²ž…žâd=÷#ë¹ïZÏ/<à4 H€O7ø5œ(4:'ë96¡§–+`^`=O'~‘õÜqpЧ¬çøZë9~šõüEï¸â1—g8Q¦}½8ÕÍ'šäí§p‹“•Dÿ 81+F'¥ž'ö'9–9CI˜À÷V³¤xÈ= Ie—T.p;ø¬ßè§Së}± ’÷•Ú÷×+*+žPTꤨláX×nëÛœT¨áƒ¯ù‚9‰-5qô5æ$xÒO›“õrs²ü‰_aN ™Öö2lNjàá·iNæ#s²¾ #Ä7˜“*àgA#oÍÉ6c>Ìɶ9»Å\ëTµ¯2'õ¾Ýœì—›“y2')R:BXGÀœìo0'Fá:Û:B|Žà§Í<Öú·£#äÏ©#ÄIGëy­#Äw×òЬ ¿DGÈÇ:ÂÁô_lNv¿Ìœ4¹V‡h1ë“T7椰yÁ¼àÏ›“Ù‚®0âÞÕ:B^™“×:¯hNÞB·u#ÓöéW7'a}ßÛœŒŸ`NŠºY;‡ÚµïÌÉ|œ¼|ÚS§~¨#ŸÌɸoNÂnÌIV¸-ÓÔ6jk_4'g ë æd-*õ>Añ§Ëž?½~÷îõ›O;üÚ8zzøŠ›éÐÆë%K§ntr yІÝÚÕ ¥bXÎRËÓ>ÍÏÔUÚšžnÀX’E]Y€Øv2ç,Š:\ƒ™Ÿ³3ï¨ç0©@Wïö5ž˜¢b*`9-Öd;ÑZ|Ùò ñ]j£úÓ<¨°©? eδÀ" Ô“4ràÂå£WänÅ{sùr#ÛqÙŠ8Uïß—¨p© °ºÈ?‡t§™D@í¢HDSÔ‚“†Õ¸}º+ÆœP2•Ÿ˜‡ƒ¥š‘ˆÕ®(ˆ.Ô§AIdÒh€J2c€…jý ûP¥7*´½Äj}»ƒ×H…¯QXt¶NU>€›Œ^¨Yè ý°ü£þnHCPš4NIÖ»óIlxªª)2ÜØÔÉÎjKþi¹]>u(!Lqf+”T»– ŽAFèäÂË*x~14.^݋ޣŀçµ*U¿„ yH*Sc¨Šþé6\Soe&#ØÏW¢²Úc Ð:]Y'ޏWQº,=é9¬t"3ä %ÔðÁT—?8cx–„ÄG+ú3¡skºÝŽ þ’9Mcžj$u·"·§WÈp”¨ÉF$¦úNÛ]BÃ!À‰òºüÒtˆj;ö¼WFõ†æ*õ”Êþ²«”ý {v©ï¤†?»º•ÎlmM¥†4®ù,>9vE֥˂Â:ö +øK(¡séWkÇУܦD±æþÔGkv “šAw54|%•2š)ÑÎiÅ!³í–p¸ÀY‹9(Ö³ÅzóDÖFuX70[NSÃ^T¼*Ê!U²w×D/SV H'/CýD¢ µCû$^D«•v” óË8V€Å•“éÛ¦ ËÑÚÀA¥T™¡cO.ÑBð-ˆ×Б Í@„×xæ.jº ]í¶šF½³Â*<ûó%±»´Ê™ ñ xaÏ>†·þÇ£œTgÌ}¦YÞp3Ûàh¨X«:™nbíÿ°›}Ü0WÀ\Ê+ƒïÕjuì),ü.“Jd{4¬K5ґĈ’ad<ëî&;‰ê0]É5=¬[Ø” (DvÅ º›Û«þ^I@+ED-MÖ^t™÷Η÷€Õ·]r´ cm €¶Ã»Œù]å¤J]¥îº9ë®r6—#zîð+ç‰ØlÃ<·»¤ZpKÀÐÕcÞZ%À^<½ÐVWàÕ&SÉdõôÿ¿‚e¥IôÁŠl‰vl7[þQˆüÙxdx¡àWLZÍ!ÚÑ]q²UãUU›ÏÇb›ò¯ù< 昗ÏuÖŽ-”Ø K‹F‰¡¥õC6£õ^>J›.^AE)4ÖЩTÊõ(eÈDÒNâ?!Oÿ”²9`!6ÆNª…4sT¢rIWÒi8iº—TaÒTe»;IêSÃ’6¶…¿l@˜£9é‹Ð&v”ö, “oŒå?]¨=>£*$½S}Y, ™]&µ6Ñ*ۚ嶺G§ÔØ¥ðkv¡ñ?+¹0|Ö¿Ó_èaðXSÐó3ë~ô//N[’ Òµ³QÏPíÃæÓô]˜¤«_,ÕÜ“ó¹ Û¶+| Rä=øyYŸ±4Ye×ÓÍÆ£,páBï]i½h’ý*Õý7G­¬Ü(Š¢¦Ô¶øŸ¬‹l/ÁðÂó/Wäv ȸŠâ9†¾JEªÂ¤áÎн-2‚lj„2eÇx l,¿Š)úCü§ï)¼*­“M§„ïò0…’O»@ ô.3>+ÁdÚnlhOüKÒ“,«YÛ¢¨CüÇr²øÏ¥Œ°èÒ1­m¦˜^òœ¶ã³…!$:/ôT¤Eî‹l*϶úÜȬ$â¿çGNâpt9ì|¿½žÔQ0Ó!¿,Ìjž-ÑrJìYÿ•y{ˆP”#E˜©m€S¥Ò_µÉJêñ’Ú7+D,ð¬L’+Û~€9¶LâvðB)»ïøOxÅ ŒÉm£FKHÔˆËð–9˜^ôŒ†4û¸8×A}ùVüo?«@yAA—ç#3êÐD@Õ串,,ÌùÄÿ[\ÀÂ#R;O¹ir„pá·Gâ?oy-þ÷­å^ÜJnÚMYRQ϶et‰J›–“ue¶"W‹ñ2‹ÿ((­¬F.¯_I'ÂØâÙ®Õ‡†¹¥ÆÃŠØ·ÿM/µù˜ €1âƒ6NO’ø×J £²Å8QZü/M©-†ÿ6d›Û¶‰6© x+É× Á²úkv«­8 N@Îâ¿á|#+•Ò„®žšh›öæ´¡ FèÔP»Ù>Õ{žüpYˆBeÜ£züùoê¾yøðúÃÇÕ}AK©mZ±ºr“`™ËúŸí’Kiø'n£&%~W¶âm\^¿„h™g¢î â±€ÐRæ‹TxÉXêIU‚4Ô6…Mt¼U4ßäöÖ#Œöjå¶‚®[™D…9ÿ[Ò j‹)hµÛ'€bµa"l•FØ ¡^r\ƒÌVРƒ¾ß€ÃX(»!Z9R–㢠C€í'OyØÃ¸; 6á|2©GÏX¨yÉR¤Dñð d(uL“cÔrA§Ñï^ tÁØ{Y羓:RålKÙ%ñÜÓ˜ÁÝvž2¿Nl õÝ`šÙЂHñm¸y‚z  ]ª.¯ÌU/ÿ]8;VÁ’ÂwgΩJi"(Q@vOT2|]Ëšj¹ç€Æx(·!NQ=k[Rò9”µ,êW‹áh”·„ûÍ'ò¦A2.ßT2!räƒ(}q(Uɉ˧e+´³o3â« ëj)¨[PôöÍ•®$áõúWå*ÝE(Ó)¯ë£ZEinã/kšeç,ºüîVjÔD‡ýÙ¥Ôc‰Täz¦¢µÏr¡x#yÒ·¬9ѯa¿s}:«)y¬=+Ä,ºeq"D‚<¯âô´@áŠ]B:ʃÜ6,K‚]±¼é.¥¬0íê“a£(‚šˆêv9ݤ£HÈ÷jÿÙ´ZH$0¬© -`âÎÈvP3 ÇÛ“¾æÿþk}<ª’;W jhhÐ3[Ô‘¹þ$Ťs&×Ã\ÄÆVåãâηä™ó (½ÏRîÙ9ˆº‚JŽŠGJ À4„ Pº³Kó}¾cw@¸‰'TH¦Ù´D™@ÿe ÏßýËÃë‡Oß«·zf‘"ìÞÄ”oéX¡ú’”-7–®¹œèm4×{ºIT㣠•`^cWËhw1+oóqzþR3¹µSХǤ k—ðQËnC€V•#ZwÓ S´»EÀÇ3`º—è]³Q+ =ôÒp—þ¬yLã] ?ý»Dn5™4`Õ‡­cµ¸" EàÉ®ŽÅ‡! ž0OsEÃí«ð1«÷v`&-\\Å[zZIÿ6üš$Lœ½žïã+›‡½G” æŽÒ×¢ "%Ën+mÝÐîÅ[ ìfa—®®žÄPMYE®>ª(šk))Ýn{‚|­•§Àå7~ÿïמj/³à±ý;Ä—Ïh‰ ­oÂÞuÕ8ÒŒ¬¨b}t€'kolZ{I{&&$/²µ¤L„-/£àMwíæQÚ#7 ޼j¸) XßGol¯˜G¨o $È&g"݀ΰ¨Pçk]%T9¸5œIR%ðNpº ÷kV›On ×t )¾®OHÏ–µoªE+•p“ÒUÕƒ¦:iU¥³O­XE/;då”o§OR_ÁÝw#/FæoÛªv•Lí†_†X£ž—@¡чôœÆ*%³)œBŠYFX†ò©gÒñy„3Á˜¥D"ÑßøV¡jE{ˆH5¡¹ Ï/¯;ÃìŸÜ?åÛ#¶t¿)r€ .üÍõ›±¥ †Õx)%´¶ÖH²i aC7Ц!ª]KnE×ÞWQ;ü¿³Ô+öö*8ìV/™9ˆT…ªžl¾›PäJ¢M|• èÝžÓŽçXL‡€<ùÔO›™ 5ó2­û×^[Ê$#ÚsîŒ ¤°Â›Ç{‰­€`»8óÐo§'eSiYû­Úþy ‡ê‚ÚÀ{wY½"—Š tGrfFꂱZÂ[=°¤k(å‰CÚƒTßæF|9å’R¥Qôm¡ØX,À¡¦Âfš ýˆI«­j+š ÕE?1g!uMAT·Ü6$`êBÒ¡¹k$¥Û7Õi¡•ßžìQ ~¢"&A·ÔxFcûºQ((fý§£!~³TtÔVÔ;ïL²Ñ&j²|™Ââ/åC2 U䉴8þäÐñLõ r%yo¶¬?jóCPªû1QB‚ JNäºlR•PdÓ…ŠmhéPKÌRz½ õÄ4ýC¬ÓL£;àe¡@Ú@ª1üb^ÁÕºmT‰§ÏC(±Ùû´U¯<è¹Ò]ž®pzÈzöCÔQ”#iñe^\ ­švBM|áN°Fn2cþ4{j²[?Šë%ë(;ö„=9X`7Ô™Š-Ù¸ÅÆ’CR í‰t‡ Óþ×Öú ɈuMÖáWQ¥]À&k—z„¤=F'4z i k¸ëë(žF‰mXÓÔ¥µ8I‹mÒ£°&¿éüæ0 lý'µ¹Å”BKÄ.;‡Ø}‰(x f­Új» T©ð¯¢x45CßÇ0§_`%1ÖàÜÀUÿÖý˳œM§C²SêX_ƒáï„(Ðê‰2ÿ¯G1æeQR짦î×GXR£3LçùNDp÷í5Ø%¤ÔÑ)²üHOMŠ!ÀvØ¡Q&¶éyªãi;¶}1{3žc÷–fÒ.ºÛ8ð‘<…îRSB&•j$>Ñ?Ä™K)p]1SD w+/}[›Q•)ñïÞ7kø˜TNô͹ŒÚóZ £[0œ2Ý+}g¢¦ÁhÐÂZ~à”lšjs‰Â4M¥O!(!Íß0gP2^+z ûjy E¥¥#§Ûµ²ˆ(eg›Õ|¯Ž¨< S” É>áØèàÜÅ2É¡µêó¼öjêŒeLí§ó(Ò—du7# Æ;["<µ¢õÚÍoƒWá€&êÚjªêÌ hêíÀúíKÉ@s•Ö²ï=: b¬Gª;j¡/žÁÝí¥¥)sÅA +JjÅ$•aŠkKªÞ8}c³¾ÌBûㆄ)œÆo/ ()8”G-›Ât!Aä/ kÒ-xÜ_<¬h·ÆŒ=ñàËÔ^‚z.‚‹†‹ïåÃXíú½+¾xH&ž §ðcu•?¹Ä—«m4K²ÿ;p!h‚&Bdfwèd–Õ©LsÚ“)­#ÆMi—@172`Ã-aã"¼›Äò°”±]øXÐþ¯¹ \M#<­‰íØMD8‡–VT»M­]=¨g€7¶MçË´Ëmæ·ÕŽªÊ#âlDA[6/þ¯Q‡Å9ºÊü@)ºlô©ÖºŒÆvPðO-ÄlR©R1¿¬*" Ec{ 4ú¹‚‘x`=°X5û(ÍêP.”M¤fžAçÊ×äƒ]ºðÞÁDxƒ3Ü÷&§§Q38QN©Ò³>i¦ åøEJ@š-¨lr¸·ÑP~Ï'L¹f£f݆»c—, &íÍ,FÊTÅJEvYãGwk¬ÊcÕœø€HiË<&È9É#âÓ§k¨ ÚÇêlsÞ78…'sùÁÚ…]_ŠDøÂÈ1–O|Hìñr_S€Ð¶¢VξäIÅ&àð.ÿѳ˜Âö¶Q9Ú±MÒ-AÝrÕnî*Á€!'bW)õµA¥ÂhBH2£+’Ó©ôï2æš¶¬oûP™kÄS(ï‘# ª®®ÞÉÎ:«CÕ°˜ÆÚ’Í)ýù—0q¸@P“åd Jõ—õÌ“@zÒç¨/.5Ãg©äì÷cJô¦äî¦JfÒfqú3Æ=ôŸþZlþôoÞ~z÷NÒ`ØçÒTóÊ ËxÑ*¼ËŠL½@ø¨æå2V¸·íÑm»j!N[$­@ê…›¡ø% $Ð3פ‡â䩘[É)«üª† P®†|(ðGEL  T\–çO‹Åu¡×6é8aªÅ–6¦Þ/cnN‡ÛhÃ5¬gÇ4º³UÍ0Ý¨Ý©ÅØEaƒ«Àƒ £Â0Y¹CGÂýH"´ÑÛÈs´O›µ1z#|5Â}꤯˜?L"r“xK—?úŒÈ\ßð¡ô:í}iFaµGOñy0U6À܃Ë®)ÔбF<áÄ) ª 0êürÆnÌîJ_00駃=êŒ/È_â‰T‘<^[ýš>Z\üä]kâÇ ÜÝog™§ÁÈ òæ±Ì=‘*t‘pÉvЋv+í*8…Ô§'RYµLêQŸÖ1ø{Au´4“z?Ö¬ðm›çÂ9gqR Ÿ9ke3MV…wž'-§³y"åù'Rì|iC#Iã‰TA,Õ½vÓjEgžÔÅäë(„[4Ðqz"U*eÑ ¤e¶"ROP•¬¶œ“–Õ4þP¼“PˆÒù‰T R@†š ZIN*mž>­¥ wÏ7aÝ)êýDª–ääXµ#b‚ãÛ¾y"U‰´èÜhH%uµ3ë©`o•JAÎØÊ^î1·«'Ri%ŒÛ^˜€q·moŠ¿ŽBº¾nbÇ’¤6BVÂÌhÖû‰Tª*Ôýá‡pÕ2ÔE(aÆ`ZZ€÷©a„08mÆ!Úæj ¥¸‰&îÊ6žH¥*V>óy<"-]i@¸ëCŠô†2󞱂v›oja#ªÙèªÞx; ˆáZ-ÅF´`®½™Ýój)çŽÁP,±ýT¸iy^pí †¢…ç|áûðü&€+Pl¡’öóöjɀؔV½]Íã÷{2¯A,%9(¡—¦Á¡“ØÈ7HÃé“)ë‚ðÌ×xkYÎ¥ƒ&z#ÓQ&Êyøcøe’­ŦÆÀ 88[RœÙÐçê”ˆàžÆ=ç+…'{GÁÿL¹EìMȨ»\VnMáq´ ”ãð<†™ïHTQŽ¢&ô#* ê‘Ý:ᵚ[¶OµÓÞ.&‹5Â<°`[9 v€hÞk“Jþí²M÷ˆ lÃ\ì0Ãîêyú„š½’äÄ«éÒ ¹š›ðf%S@úçåø¡xMxNý?Ÿ›gU"g4S„Gêï¥3ýÏÿùÿÄÃ¥6<µaöÛK–Ðn ì)¸´“Tûı°u ) [zö€;õW_J·ÝÔÎ)ŸëÝ ùw4A…®|Æ‘K;§WëÎõÐȉ°¶„‚2¨€ Ë­¡Œ¥€¿ ˆJ_À¤ˆ™ÞŸw™Ga¥5C]&o×Å»ƒ§‡µ‰.ó]íS-Ƀ·²¸í I÷“,v{¢ ´nY,VNV”#R¸LuL( ;|ñ¤†i×÷íÞxÊL÷óýE¹lÿýÔ§©Jì0ÕÏóùé{“Vààk¨Áå­—H8•žáU⃯ªp¸Q§úKs4q–J@TéM«Ô.@–Ò• D£V¨² 7jiƒA—ಂµå!ˆÃ¨4¢²èBÄfÔ—»]^{Zp¹¼%s)I?ÇðÚ@öòÚýhÕiAa|iÏ!k—K]”:n÷¾ Efˆö¤(Ù´…4¨ ¥¢á°HÀÖ§I|Ò¿±>ÒÂ$ÉzžÉlå"`4æâÌQ‰E³‘ìpQ¹ÆivÜÅ Û¦Ñ$ ñ¼Ÿ¯BÎÄØ´º/ÍiùeƒÊòi‚°ì=Nònp#RLÃ-¨ SïÎUr—A© J‰@îöv&†Sº-ÐûòÉByžaS€JÌ59d¥±“24 tn‘¢ÃóÍ•ä¡Ú…í&á¥AñBýŒcDI—5ˆJõW€dáª.½zëD¹+÷äšïÃè«n¸·Áž' qÄZö½Þž'¦A⸟¤{bV…aÂnÙóD.µÈ¯L>U¬å€ª.›«±´ÉD:kœ<Ϧ( Ïÿ¬kÏóN®ë\¥¬ Ì®MÏMµiw^ÌNLÄmz‚ZUzÝJÖÕü‚o\°äR¦¶s«Äâ7§H`(œñýs‰úv¤¡Û³Åî¥ôEÚ+»±–´¼­ä–ø&@…V¤ÜÂô´ë†éÙé鳆+Ó›BVÔ6=¥)ëú¤‰ÌÛr—Ï™ž¸Úîÿ•é9¤šVW¦§¡b¯³é)“Jµ<ñˆènD[4ôŒû¦gŸMO>åK¦g"BÛô7!æ3ܪ6dž‹×é¦ÅŸ©±‘ê$eïÊ¥o6š$Ò©Hqo­bo)–¡Á¤!´VLÄãÓ»M‘ðNøË'ð R_ É2¸…²ãÿ¸#q•‰«olÏMI·'D¥zž¦.\A¥fÛÄÂÆÎåò©§]*o¸‚颥åLÆhxn;Åzd N¡gw„ zšœ¨ê}f¬˜F±¶8¬7ªñª%¦:Ò|²§ ‚»Ð‰¦‹­HI—W¼ÕƒM[lÐÚæír‹4D!¨[„øüösüåÓÃûï©ð ‰RexR…¿lî¶P½T…‡\©ð{–ù‹*|œTxRÂ¥N2ëc¾âV…ß \£mTø¾UáûV…?TÓZ…[Œ¤û*|*|ØÑ|© ÏÅe*|ÜUáY Ç*|¸H¼L…ßß²ðTø~‘ ¯Šñµ*üU`?ñâŠÍ»2¼$Ý+^áÔdp¾N2¼>úáû® ßweø|‰ __/Ã{Ùôš_M†“ ß÷dø~$ÃC½L†¯•áÃ2|„E.ûëeøNVžß~$ã;­´ ŸÈðu’á—²¡£âŽ oþü›”áû—“áû;ÈðZqôµß'¾¬¸Öáû‘¯ÒjÕ´Sœtx‰‘BWš´DY:Å=^,uä%:|_ëðùí:||w=ÓòÝ“:|?£ÃÇs:|=ÒáãJ‡ïG:üDö¡ÃGtx¦|R‡ï¡ÃǵŸ/ÓáóF‡gýÁ‚鿝ÔáãÖá›°©/éðtݯÔáï%û—…ø¼âë» ñùÛâA’IC£ g!^Ýç!,ôUB|¿@ˆïÞ§¾ Ä«NÇ÷â·D£ß³ï:ð¬/jdÙç+…ø|¹Ÿ_#Äß mž…x£¢“ŸÏ ñ©2#ÞYg!þq¹Eô7)ñý­J|~‹_ߪÄäê9%¾~~%^{õE%¾)ñõý”ø¾§Ä±šï"ÖWJ¼þ¡Ä?À²OùŸß&Åç!È£xÅA~I‘? ò¡1ÓÒÛ¤g™ôÏkA~˜¸;fo]ò ‚¼[ JyóRAž/[A QÕy± ï‡Ø“ ¿Ò7ð ‚<Ïù6A~•3òy¾úíÛù%EþÛyŒkA>Ÿä0çT¼æy‰äW ò3Ký΂üë?Ò,µTºÇ*n@8r«¸éâ/%üf©O*n]«¸*±æ;OÎR‡UÜüJWìA.I=7Kÿñf©OqýÄk ÿû})wÑ^"åæ­” óû6)w¹nÎbÞLT·¥'&ªùbžýÑ_5Q½lmÃáž—rãZÊÏV`š.ô”[m ¢r¹¥ÜeÅõ‹Rn“'.Ð!®RÞ’—H¹u’r—4˜k)·^8QÍÙèGRîã‰ê~$åÎ[˜Ë×OTëQ‚& WR®"’­;R®ž7‰Ì‰x¤‰ê°”‹Šv>s –r—4‚£æ”KÍ~”¥Ü¥ˆy™”›7Rî’–ûœ”[ñ””ë/…¼/å–ùù})wñyOJ¹ÿýR¶޲¥®Ö٘Ƃ˜ G™Œ’HÊ~/M€¹)´²¶'³{h¿A½WRÄøÆ'$s38TY2q¦´Y1zª1º„•RÌHÒU,)…¦ì™ýà…ËRÇX—LÌhDˆß‹UÚ JÁ¼ ž×V<9–§flq_D £LÒGç“‚G:Üõ)z@R%ìMÒ§;¿fò¤ÚîZzùóeŸÚÔ #¨„Ëê©ê£Æ^MiÐeÛž W£`F7k»×7qsÅ‚¦ja)¡T‹Å^MÁ"ç"83ê¬Ê“É=«¼•ÃR· ­J­¶šoR%$ ˆi„-,QùM·쿤°jd€EÞPB±~œQ¸¸^{# ñȇ(U#=5}{#éh¦u_M’ LòÞˆ}wõ }ñ×ÞHùŒ b¼‘ÀxÜÞ‚ ºkšu‹C4âl—Þ2Qå"¾•ŠTµäM³h}—x’ežÇÞˆÀöF Vgo ½Ê J¶šÅ‹Î($Þˆ*áЀçÕýþ•7§ÒöA˜ÓP¢Vå.O 'ð3ݯÉÈ„}±î8û¬XÉ^(´ütïN²hÏöFòðF ¤4"í ”ï´1äµ7b—âÊ©“7"ö¯ðA©ÍøoDý¶žóF^vFÁñŠØæð**T–Eâè3 × _ËT†ú“¢gk±,M’î7fSX(­á™0•tTÖHÈ£tŠz_k„æ*ÙµE(•Õ)Tá%ê¥ú¾Û²Y!YÜ×]¼ OóÖÈt¶}Fab³4ŒAÄ„­‘6Îj;ýqœQ¸ó`¶TžŽ‚¤òª²¶ dÖˆu™òct³w­‘:[#išõRkDÿþ…ú£X#´þç­‘ºo”ÿ‡JGw9[#lÔO¶Fòç;£PûŒÂ•5rƒ ”’4ŠFœ;9#urFÒÎÈ8aíGÎH”ö,ÔvFPhU—=~h&ø ™€HzuA”èkùvFšÖÝagD´¬k‹ĶPrô4t„jvFRLt—ušF™·½ÈÃõÍÎH¾üŒÂcgäþ“Ù´Þ&yìdÁ ôÁ/8£>·3ⱋ8#7ÖÈqဖý¶@SOº y¸ KíýÚÑ  *v´WÿàÌ ÀÀâ'Sh$ŠD¡‘Ò^.þîPÁ•´Žµ‘¹j_Þ!a#diŒñ’àîɺK`„L/ÝNÈT kŒqŒë˜Œpea&,WØ ±-xc„ÄÞ€Ù±+#„0Cña:û¥FÈ|M¡˜G|²¶RO!¦Œå$6¾Êñ7˜[/þ*#dm'äžRÏŸLXàIBçž’O! ÞkúüõFÈœLx{“¦ª³ao‹{Ui0G)M}hA5 »ƒÒ’8µ7‡âöÐÂzæÔ‚ês?}haAïZ­xæÐ‚€åcñšÉ°Îç-,ó¼´Â‚[Ò¨.• æjv5j¤B¹!ô¤p.©© sË“Éziæ_(”ÆDAñ|Ñ–úreÍXæ¤JÿDÅò˜Š“Þ]¶ö“ð¡Ò‹ÆOÔ£"I:jóéØò/"¶%}¶,¡6a.±ú®o+`Rn'e¶¡]¤|éá‰ûuÛ*J][ID=†B ”¾z;y}õOåÐóòHªDŸâ¼ÍÎZÄ,„lôQªÞ– <­Ù96EÚƒ”H6IÃj7l¡Ì¢ALæK?>Y’+UñluèË%¨ÌnF`Ö®53 ‚{vU$A̼x†CQ¶"™Å^! <ÈMï2÷Ìé½Ô£8eæL˜³ÈÀѵ:jyž ÑM>ºy‘`ë”Rd V"`Y¬…9R–Uˆy~X(÷YÍR £J‹E‚W0p=| ÁÃfNë¶ 2Òû·;ed³UP‘66˜ñÄ(z3ЉÛL3Š´—æµ¹šzšà¸bS™”‹ì´–ív+É³ðæŽ£Æ“¦FÂnyÖª(~) VòCN *«M2~òÐRÔY^Þ¦M]–¡…WÒt,Í(6j(ýAtwZLÊ.§(26>+¢³ú%Åsz¢ŒW**:½êûmI‹¬Ÿjé…öd£çÁ(¶¬Yˆ9ˆÃüÏÆ_õ ʆIëæ­@ &y0Þ¼e»ÙÃçŸã/ï_|ûþõ:—Üb|qÅõyO%÷åw=.¹/¯¸ëqÉ}yÅ]KîË+îz\r_^q×ã’ûòŠ»—Ü—WÜõ¸ä¾¬â¦Ð÷mÉ}yÅ]KîË+îz\r¿ªâ^…úŠû£â~MÅ•k?R¥óÿ}ýùãçøÓ«÷¯>|úä§åßÅü’,%¥Ê˲7e¤Ï˜¿s »7˜_òFÁrHì%9AãÆüz7Éöx‰ÞÌ=£'wÌ_µõºÉÕ² œÞ?€ücrjÇKW¯$ƒÆtBŽ–"È?¿|`~q–têSÒZ¸é´Ðåı× óç©åS H_Uå¦QÄíMBYO˪a²\üËt rêSŠG Hß@ZåD¡¥8jʽ4i[ãM8Ý ó«Fåv#&ÄwJ÷iû2h@òH¤¥„÷o+¼ü²š:AÞÅüU.Y»ùë è@°P5 ÷Šm;ªÙM¡V>ê@Ðn7såºç<·U¬<ÙŽùt÷Y§ö£wýl÷ 4ëªÿØ0?Éÿv¯z¨Á\u# úÉm7"rw7ª{ݨNÝ(5|𸠆 oïn´×̱®.fpîF¸ŠšÂS°šG7r¸Ûê¶)ô¦“ÜéFu§åýn”‡nõt7Jïý¹Õu7ÒcŸ»Ñ¼’nÔè6Å¿êî´l»ÍÿEn•i; E!O“5ÙyÙ£nt¨¾ªæÝè~ÉŒåH›'üÀ¡Kûzøüéóù—÷ ¿W¯~í+´¯íëGûúYÛWyXïÌž.ÅâýU±8š:ù%¤,Ä&Ù‚8œùlá6ƒÃmÃÍ:h6,`üí¯1,eÑ¡©Ø²qW0ÐL´‹Òöœ¿ý…ºåz•¤!íIò´˜…ÈBùÛ_TÕr_˜DÚÜ¿‰út~è]ôü)}øž–QU*ˆj_^OË g£nL‰¨¤ˆ1OžjÌ­¨µ›Z\v™ Q·Ë¡7ƾêÕÁš”M !p66!+œ.‰´”ÜéùÛ_¬i„[}󛀌I8ë,íÒÇÆ,IjhîêÉç`ö˜IÞö”¬'·¡Õ€÷°gzÃÞŒáuÞÑ4â …Õn] {jˆ-ª°X–”éuoسo†=%˜ö‹žƒéó°gK_g#TJ[q°ñ)]”É4™äÜÉ÷öL®ö4ì©¡˜Y1!Ȱ_òS†=ë¥ÃžšùåÍ—D»eœ†=Uì$ùyسäeñµÛ—ôÞ¹«£}Á¯Ÿƒ1ÃpòR5(æÄÚYc>O{þóçןÿáO_=¼úøöx†`žör6ðòßHg¡3ŠØo<­ù»l¶­AÈ\Tl“3š¼Ñ”âÏs„³"¤Aiž-®Q©™_Nnyþ8Oô:¶×y~_Ÿ‚ÏÍœ‰è*år•K~×´SʘαÎG‡û ƒR#mœÄÌú’íV§t©˜ÌŸëm—Åéµã=%5°K…ò\s€œËÔTÎØ¡GR´4ÅÑ]œðJ›Ø¡@„äTõN–‰Ã ¥˜T‰Éì=M¨UÐÊWê²÷±I¥9ÀN`P.µŽÿ¦ @¶$0´éׄþ”ÑÍY9ˆŸ¬¢Ú#œéã¨\µ±ëù¬:Eh_ ³r(-4#è¤v8u7T»TPछ¨SÇ„ºÆEç×v‰Ø…šƒ%îL %¼WPHxdWƒnan¨þ³4Vä`Ž£5ʃ—-9'ÊCmƒ T*ÔIÊŠŒ¶µæ5 ¨°å:U*¦ *1ÿò7·ÕBVžHSØiœ4+BÛ\z3{9F]Øf’Ã" }ÑÆÓãÜïJ+?(j©±Bd…†Gç›õ¸î—úì’%à‘€Ÿòþ’}‚ÁÈšæ‘3†¦}ሀjƒ‰9Wan@­Ï ¬iÔgXí@¦P Ì«´zR§OZ7˜ ?õ–4ÀQPd3@Î#4æ¾O”²þ$P[ePtœ_™Þ4—¥^…”Ò]ÌÙŒ½RAK_=ÖͪŠü–n“.Ô"K›Qljzò|ÖOèW{ÛÒ^´©³¿ó—éšî¡JSê#óέÖÈu÷‘TÕ¬±´˜tzv<]sÜ #- |¥qÂPáÑHUÂm·zmBÏ”1Ñr˜ÌvFæ4"†zåüD¼a1[ •ÀÔoÕÔäs&É‘ ¹?µ¨å’ |†K3NµiªQ»Ð2¦¬’õÓv´Î½hq$ÅQÜøGsD`1í*¼,!>"»e–ç`wÆé;Š6Å"IÉhy**›û/PzN××)µF¹jz’ËIP¦¡‚O[‚•·aµ6¼C¡5ÜI¨‚­lãEâRŸÔ·®8$lYË4‚dÓVn¯C•j;x„ ‡¤î4([Å*QqÀ"¹YVyýZg y²3Ï®à†©3!+L†’…æ¨Z®£ƒ0&ÁLAæá¢¤–&3sF— ÿõæÔ1#út’ »T(1¤ÌZBü£Ø¯ûÁžîØû½; E´ê©Ø_D3$ö#l îØ/Ç>° Þ-‘/|‰`kV§Ø‹ž÷Gôh‘Ô Câ“Qæ[‚Û±8*€.ž»Ë—ƒv¨ÙuŽý¤»Ãvìë*kÇ~pvˆØJ¦Ú$±ױ̭Lײø![’Lˆýyásì[–yêØ×¯ß}ôe¢zžcsC:§A½cŸ†%ÝV³OŽýRì³¶é6‰L½c¿1ÈîÄ~øgGì¿ùü÷~óöã‡wùæÌºŠN*s˜ ³‚“¼:\гSe.‚KÁ¬Â ÎP!\ƒºÞvaÖ{¶èøŒ)¨6ÇèÔ:sŠþ(Ì;8ý@àStRz–ƒ³OÁ)ŠÕÒh’7¤„21]$®ƒ“E`a0ÆR)ã’st> N™_Ga^ÏTæ£0? N èã=Q™O…9çeÃÖ3•ù™Â¬pûÛ Èø‡þøéÓ»ï–C6övkƒÕkõÉÎN¬äçKí>ØØ0y«e°±!ꪻœCÕá·×މVü*ö‹Sr *Îì›GÍÚ R¤«ŸUL€ŸdÏУêh“!ÓpEoÓ|DÞcøQ›Ê¿y?Í`QŽ ·ÝáéçÃ3R³-ŒAÜ”£ƒK‰²'á\ æ§Fñ4ÏTâ Hœæ¥‘E’‰4ú^ƒîó„1 Ä^c,pörnNF¬¤ %‘Cn9"ÜtX pHÐP'ìÖÆi_ëTg-0’ðjûš»\Ýr91áÊÎR•ï2Æh×YõEpUa&»àþílü¯^½{÷ú4ñ|üóºú Çß‹Ôéïÿõ+Åÿå~ÄÿwŒÿ÷Ûo>~xøÑ¾9âåP?:À÷É€øIÐ(®#>ü5Þ¼ÿøæÕTøEÀÐTøSaGù§KÁÿôéáÓ?ÊÿçG”gÈóúÕç?|ÿæÃŸó~ßøÁyÿ( ðúó?½þôðáÕ94Çõ[À9¿Í¨ÿÈ ððùϯ?~zóúœ?3çýÝ'ÀèðîóŸß~|ûæÝ~0Ý_(â7ÅtŸL€ùüÜgÞúìƒ}üüoïß¿}?ϬíP°¤¿ñ_'ë)à%y²žJ”—äÉz*Q^’'ë)®ð’½úÀ–Xéjq¿Uô ZE~K«ˆŸ+õM«¨Ÿ+=¼þüç7ï>~mü–-ârѲð¢ÈËÐ{õúáƒãŸ¯p8 d 4ýY1¯3P„jsÚsÂVA@è¯NbA'™ò˜ÆÌ=ð–;¼ éÔÚÜûL2ûñ º‘5§—›¨+®4ˆÿÖuOtõŒ{ñF³d:A:¡¦ Ɖ¥RêΫ´;9˜GU8M"ÇiY[ãiÈ>ÆXsK3‚9Ñä¢6Õç­¡ÓÞÓ˜;›ZÅizÌý—óü~G÷çêuGŠ*nÚQx­TØç&—_1¡çƒÊìJ'Q“ý3I×YàùêGý®ÞƒË äF;¼)?T®ÙÓ ’˹Ì‹&Dˆ'ý’">›"FZîiÌ]Mwð?\¤Ò÷ï~›ÁŸ¿Éàïç‚?^üõû þxQð×ï1øßü5ø/·ûµƒ¿þ(Áÿ²ÊÿÝ‚¿¿Oð×Èàÿôù/彯^1øëg®üõ3üþ•ÿ™àýJÑÿÅ=¿MÐÿ#úÿ(Ñÿ ès–|Žè¯ûÑ?„|B²žŽþ|6úû…À'îE?ýu7úã*úû»DíèÏg¢¿ŽèGÑ__Œ~½ÂQsÑmŽè¯Ÿ õ×K¢ß»ó=¢¿®£?®£¿¾ýå误Œþ ìóáý—‘ÏØÿ£öÿájÿÛ¿FÿÇ7?Hïï-úóGôÿôè÷ùÏÞ¿úðkGÿïV﬛èÿ¡wþŽ¢ÿròÕëO¯ßþ¨þ¿ÓøÿQý¿5þÿîâôþÓço}¶PØçÍ,~\úàä[˜æ“fümžÍ·˜(Šk®ZŸ§,œwì{}ÍËÚ72ˬ¹ @ /õ¥ w|ášó|äœ+Õ"ê›sB³ Š £háRqŠ‘Ë€†9iuyÍŒ Ì-(‹³¸úíÃkç[_ 3?”U¤j‘ZÖÓÝiQcœocKý¡õ sSÞÇÔó¥J_}â[›%‹yXËÄTë¡TI èBƒ‹cùõùJøÒøÄeçÅPÂ(Ÿ4'¢Ú"…£ØÔ˳Ýça.<ŒTk;|͹¢ùM•‚t(Í‹/Dó´«T•%î”›¹è ¨Ûà Gé‹h´÷ó ¢Ëoç<–°õ$Ê)Ç|±Q»r&êßÃ=Æ!~ÉŠYg®q'føF©¯kOÝÓÒ#Í]eTBç®UVf/ØV¡dÅbºBùݲöªžòïáó?¾úøæã§ù§ú‹å_?Ê¿ü‘_“]ûbþÅwÈ¿¾—ñòïÍçúðáÝ«wß”ñkä__å_|sþå³ù—?òïgÏ¿<òïòáuÊ¿¾Í¿YÍÁ“ý¯_˜ýóO¡žß’?Ï<}÷úã§×ó:q=~ùCjítS|QYÖ¢ÏÏèfú2RßÃ¥çö•¿ãÃéãß/}‹>ª–~sBd>‰×‰V%_û§eø¼ãòóUc—F|úX²0õ}•%j×,í„ñÄÌ|gRòþ:5ø^ŽÂP£¹½MóVänͳ·Cè_Ÿç/[Ô s¶4Ëw7wùÛ¥ÑwêKzrxuòÀñ ô$žßl¾ÎCßúzhnÎ kAU»´HUüq’bž™¬W.}”›ÚÍ;„öN/›‹›ßT€Å|ÐÒßñVŒÜëšg-ªÙ<-˜Ü-öe‚„Wì;‘©2;™º -Oòí3s‘óã5ù˜äˆ&¾}{ †ÉÇävô m—Ó›ËOâÓ¦·ÌòëC¹ }gJêFBŸ<ÓÂ5…Žëcµ=혊}öqÿK¡¯Çã‹¡N'PRÔTiå£ÐÅBÄOÒ)uŒþëùÛr2zI¯ÙùŠûÔšxîZoª_kňbbÍ uD¶âs>™K ®¥”JüÔšuñéÛieaª2„ÜËšöY»<]fA_?¼zõ-Oý£<ýÒåé©â³ž©>_,>ë™êóÅâ³nªOŸªÏ‹Ïz¦ú|±ø¬gªÏ‹Ïz¦ú|±ø¬gªÏ‹Ïz¦ú|±ø¬gªÏ¹øüIÅçÃë}kZNH²B°OçIŠ3IQÉk´»!pð×Ò'ŠÃ.ôÈcxeô™eYf"w¯4Í)ôßAQ _Òú¹¾G+ƒ+,=œb)ŠèÒeJºßhTð#­qÔŒ7 PZ¹m‹xò¥§Î ×ÜMòb U¦Å¸©Ü”Å~‰@9â­¾j+²µåÅ’fŠÔ#ݦᒠû$›‰ êÉç;u1$Ò£8u¡ŽJïD^ÅiÂiü:ôÛ¬ÜBÖ”É|(’vâítþW·¦] êÙçÂ)E‘æ]Ð]GŒÒÑS:ÓE6LÝJXõÆ ðJDÛ24¯å_K‹0A< @×=)=W7»&LËÞå-ÑWír}#›休$Q-Š«Þt–gHG!v¥šÇÔf˜dîPŸÛRŽþó8Ÿ>|x˜#/¬¢`h)e’ ”fi ŸW_žH–ŽTÅqyµ5u8ïIŽéÎÚ·¼:Woá95ÁÈBMí¶Æ**3éu©ôVm§’‹\Ÿš¨¸Àêɘ#/ qå¡{²‰ŠkM¥aNDzç¦*Pæû+Å=’KïèPø·ÕòT~ûKA‚5‘d+-*()Ùo"G"½be•<å;LhˆkÍ~O¥UK$ïå„ë²sàKô˜õ·pOöj6bdnלz;a™?ÉEãзªºDØj·Ux£lžä*§ ¹µCWŸŠN­ÂÌÊ$I8[UðI™,…·¤ER )ªg•¿«¦§ãyûc³†×¹øN¿üðöƒÀ"‘.œro'³)ßÛÛa*ìãP­.zŒ_¤"¨4-/¼&9&Òô廬…ª¾w…]$u¹?»dD¸ Ýúbþd;Q·qw±_RU‡ºqõ/¦Ó{h™/qI]Wù K­˜xW º»+z_n2‹ÆÅOܸêÔ¸Bï»h­g_Œ0—/ƇPTYݸÜ;(øU§%mj‚–_ ‡Kt8UÀ^?Ö f¹qòÛdžéæ@âdž)Õ.·wF¿R\ë¾pÊôYÇÚåѯ{“G³xzí¨+¹-ÌÀEÛQi è¥®È¬¼< ìÈ–‡Ïño>éiî÷ò¥^”/^  ðlåo¼Ô¥9³³ç|Iës_̗®|œ/ø”WùâH߸sÞGù2 ŒÁM¾ËïœS˜\ò¥ŸÌjŒÞM¾¨¥ èm¾wÜäK<“/}ʵåØÉfù²±VQgY]áÄ=¢];òEˆ‰|Ñ0ÛŽMWê#_h9ÒqéCžJ–x>Yæ—'¶ún²èˆ¼ƒSŒp|N–iõT²èЧO’+ÿré,ÿøððÞóÕaéG|ph\mù1À(>ËKúD BJâ†1šZŠzBÒ!ÀÃ+yú+b4ûîÏ4& c‹¶£6ˆ÷Ò\âèsñòMDÆ 1¤c.º]—Î$íkå—j±ù0­/lnG´}ÁG­Ñ—UòCÕæ³C2òîè¼ ]‰9Ö 9t£•ÐéÝ,fíù·¤`ŒÐ ÿÛ Êzßæ½wi8$4â2ÅB,GˆpJô|ä„QsVÉo^aæ ¤IŒZÒYX0y½_$i]Ëžº2éO’*ÖÖ*fd.(¸|ãÅg'ïâPg*Ë‘4Ò\r‹@'qƒ™_UŽü×é'yÿðæý» ½§Ø@*á#Æé¬[´±Ê£3¬•þ§`&õôÔ˜4þtUaÙË¥–1À‚W@Å…rs!ñ‚£Âé&Ü’"]s©ÒjIé$Mðc™Þ˜ë¹P¯´ŒºTky5Ú´{®ùêüÖROÊ=&¤šx=Ú4ûº%­S£¦“Ä®—)¤Q´¤ƒ£\H‹×nI‘.ÍG{kºP› ŠS/ÅH4Äiòr@‡¤€SS17haΛá'£´`¨i Ç„Œ—u ºE[~hÚ åB0f½;TL d£ÒV˜Ìõ£°yv´å°0d*Óf} ¡xÀ‘¹š}U¢,Öz  7”þ8I:àŽQ+]â¢y¢,¸×ÙWî à@C]ý| åÞm·ß3íM,x£ù¬µkÄ¿JÑüôðþÓ*çqë‡NpWÊ  µ/kVQ8,6¤œ0Ø„˜›kþûŸæIå)ërǦ=•纪MÎþÇ€˜:°!aà;wC,>¼p*U*ÊÉ›.’¹ùÏÚtW%'‚M3zÍ[æØ†‹"è|ÈB”d·ƒæ5x˜¥ ïâÚÕÇ+²w‰lÁv•…Ï‘TDQ>%BYùôõ$©°»ø,%ãr½ð0€P*ßÜ3€¸®ñ5TUW¯*£wÁÕ:qo@\èf%£6ÓJ±‹. @î®çåáRqÀwåÉöLøžî'·€¦Ò¹ë\i«Ùý2E ¨˜®|—ÌC¹´X°ää ;_lÀ䥊úép ¥,ü.øåžÿöÕ§«¯‡Ù€çì×åµ_§&6Yžû˜›%ÀÏi·lè¢i"ã‘_7í«å×mÐ^øuòíhЏ~«páü÷%gÐcÁ8VØ®ã/¹DÜgãid¿ ½ñzÙ¯‹ý ”l죈«SðÓbâÆ¯S·ë%àÿ„_×fµþ•…ÌÊøu [á¿„¢¦±°Œ¿ŒÖ)øôì¬RúÄYè|=öëTæW§£#uÈ„ÄÚž`¸G~Ý܇Œ+˜…Þ2Ó–ð” y¬óŽƒG_x ¾¾t ~¢cÿüôöõ›¿‘ðßCøÇðÿc„ÿ›Ë×`¿~õéÃÛßNøçðÿ£‡ýFÂÿíçø‡·?¾ýtþ_û3¬ô­±ó}/ßXúkìÜoŒý‹òÍÈ'JGÈ¿)öc¾8åc¿ù¾—oŠýÑêŽØoÂŽ— ˜Þ"›ú!ðú¾‚qvuÇPìï%ÑêJy|òû^þÛüÿùݧ·ï^‰cË]Å*A˜œ9óù&›£NÍÈ‘|™€ ²rŒ˜ÀÑGá°‡¶ÍˆåÍj¬¬­g„$†¶-<âÌL Åè}ÉÇh !,R6œg(¶R[ˆ˜ù-;ˆR¥5»ÂŽ`^/}ÁÖ,Ö¡á$#ĺòÔÿé‡\†FZDà{ÄCŒ§öŒŠjl”EYX¸þió¿Ä‹ü‚ÅÇ%›Ÿù¦d›¹¨­ X˜EÉÙ6 —3’{“QŠe0}!׎ø¬öañYçÓJn]· ÏV‹g´ÌІ®Þž£v4¥hÛ}å+U 8]Úâ:z‹J?Ï`û?’ óGé4\ˆÎž]Äâk#`…Uœ)û6˜/á™Ì '½#¸:ê.‘¹MÍɱ«¿´ûí BDTî©I•ÎÝäÍûïçkDS3Êdš¢ÍRܱ–“ïAÕR¨½½è  ”í4†¸|ÒÂN,+^ 2‰³hNã"bâD3-Z3ç&à˜ŠI×çÏ·ö¨¥ãË<µ~c<µ›+Þîœa9ÙQßúðf€Oí\ËJÊÏJ®P«Ê6W†iVEÝò @zÌd Ñå6Z¾®ZÑÜŠ ® _×@Wɇ=«…@k©Q²t„D· %&]oy²‘ásÊëÜ¿°³Z˜p¥VD[URÚƒ¯‹mVH™¯ pùý½(™JšâÒïÌ·ú n3åÍîüÿ³÷~ÍvdÇuç{}?Þÿ^‘L’)S¤bìI†)½ 8 yf"DÛAiüù•¿µvÕp4ØèFw‡Üpï9§jï̵V®Ì]'dój2 $ìÈ õE;·8ÁóëkLí¤bO½}Ÿ )@k:‘;…¸ö$.Õ{,šòa¥ÝÍþܘ»Ç›÷Ó./i÷­¦Pü N»ü´ûdÖ­¼¸}óÇ›ëÛ««K^ü¢ò"/yññ¼¸{óùæêêþæêJíœñÁÔ¨ÏHøR£_¤F|njäß–ýÉÔèSjôç¥F}Yjôßžù-SF¼—ïäÆÖÉx?7úœ[¾“õYJ?+µø~”Ú?íRüêêúîîéúEs¡l°vð(èÜ|ÅÑ\٥ɸ1œe°Öa°Nãa°¾xÀú,ŒÆ(ù…a{¬òÍ&qƒ£ ºRìðôÎÈ;mY“ãwVsÓ\*SRƒy¬I(²(•kI0^~½F«Þë8òˆí'ƒµabÓm”LBÜÀ‰åxÇ`ØÉwš -›mÍW2DÂG Öø@s¡d$ÍÞQ+B<€ƒ/š \6«w cö•æBÍp1À¶³Áª=Ss¡Õ\Ð÷µkiæSXÂѨÎDó6˳>š ë½£ ÿ<áÿ‡Ç«çǧÛy†ÜòíñÞ{i >1'äea2ÌôSØHÁÁ&—ï7ñÆmË+¼Çq”™¨íÔbŠ„À¢p3&5s7ü0¹4dd¯'dN ÅÅf2òæq«@æ>ýŠÔýU-žbæ‹OOàl¸DLªLXƒ|°—Á/˜•4˲e/ìõ4"ˆQ7ظߩL&>²AœšnLr¿ðYé–uÊ 0–{ÖØUt7†ñÒÃL,“H¹ÁLŒ\™Êsg³DÍ$>ë!õÓ‚éÃÅ´÷Œ+)—R¾Öò1e#ãŽæà6€”K›á“y£4¯È%És0CNaãuÈç€ÛŒ-u-R“­ŠüÂbÁÑ\!®µé­Ý– ïù§HO5qµZÕy‹Íæ»Rîöjrî·WÏç •‚„lµqØó5Š–nmJ‰À,›n[¦3T’%¿Q÷5Ñ¥0¿pÞ›ƒ´F*‹¤ ‰",èéiJw_àtÍÓúkåÓ¯n­hÏqÚØÍVÈ‹AŒRä#ä‚Ômu Â3c='CuMLJ3Y+Ñ”na¨ËbÅ‘< ÐöÿR("Út3 Íå+Šž²*¥é&ð"PA"R,åþ‡NƒštSØØ6܇œô} UWx>å°âÒíˆd~R³£ X¥u&ŒUY ìÀs{îì’oÑ®ЦЂãr"•Og‹El•¯ ¬s¹]RÈw6?é†08¯%'"…?JVAþ¾•Û’z£fÇLg¾r—ñÜØ 3íÀ¬#P©OÐʇµlºà­.xF5X¤°÷–jŽÏQ™Ýk†ùöú¸À‚$ËÄ-tž VŸ^Q„8¼ý‡r?Cp=˜¦`Cƒ]ÒNS§V{q@d«ð›K"ˆÌÅj£DERr-¸™bê¸2‘«D!; ²¤•lÎMú³†çþ<ÃvµÒ¦ )}Ì‘µZ‡‚jK÷N鿥hæH~ÅÜa¤Ñ¢6½ºgúq×Z»:r?Ô¤r ÈÐ8ì“ù2ùÅEó–«£=›§„„ê:is‘Ñð°©Y A†5t>¿Rªm'AV2°¥éÌÜ Ì¶˜ÑÓ«ÅŽÑ8–1»l ã[kCi«%Ô=1ÞÃÔû¨ÌNO´ðÉGviÁ¨­·Q[&¡ÉZk°³˜š´évÀJ3UY<ˆÿÒ¦EÊ]B¬l»åPúíõíýÍ—~ƒ¶FÙ›'ýâR¥.sVsty²yò}›‡¹4ÏÑÉHðÝ õd@¯9ºÏýmï…Lˆ™»ú’ïÑkÏÑõòWÇ™d<Ù<­UãNò°yB9ðj#"±­Úålž’á&££U6ïÓhóvå14lžS‘¡Í ð £Fç`fOÛÜÎê¬ñ ^Y1þÇ^q9x×Ï‹UØh–…!ι¸ÆüfDoÓÈÜ+ïÝz,2 =+Ô2ĸûyCø³76T,ÙæCÅ7§9ºGﻖܸ†%Ø_½Ñ¿Haã`HË·Ö¥¶Fä Õ2ŽãJ¨4‘\hµ»Jîm¨ú™† ¥cX…n¢ë¦‹œë¯°µ!øhµà|sÛybûöžJîöúùññùËî¾£–ÍꙪ¢ùÐìðt? q+OÎQè õ¦z-†ÎZ‚¹ÂóÉå&¶¦¬ég!a#ÇF°øs=œ¸dðcæ¸Âãu„ú 6µ[O ˆƒs†ƒhL4Î Q@ǧ¹>¥—Ì`!cK®FvØ$SÕLjêªýpâY-AzŠà;™ëCr€C,ŽoSóëš ÒïIIhÖŸ6†7]ß)ÞÄA.—nö‘¤9B}ó½Ús’!Õ¼Á(u–Ä)9‡Z”|٩èlµR“èöÊb×¶úqò c­y«¹‘\­M Ø—R òd >XwO77ÏV‹G_VÃ,ta±p`ÓÁ–2›.~ °"ík6¾`½¬T[©d>­^I¯hj‚R6*#㬰’ÝB¡¤_a¬!óq¹7 !IKá(îŽFSk<áŒHÛ©K’ëzŽVß”ñ }X/¡•ê ªü’Üø±ã¾zª ‘¶C’‰ Xˆ¤åÛJrfAÒߨ‰2tš3Z)£ž‚¾þNÍ—óŽà·{ªÀݽ%¬MÐ:£{%*Oµð?á-Èþ«ÛahF‚uQE­níš D•”°K'u‡‚ 5 ï&ø§ûÇ«û«}­‹m†Ž,È÷² ,XÏÏ•òâÎY@dzßÍ‚â1A‹Å?žyÊ‚¢:UК—Õ¯²(†hï¦/úÛÿúx{wÇ$¼<¯°}Þ‡e*›Bcxú±ðm£ÄfÔ3Ôf¡^š-š,Äö\$D?U Hö²¦5ä) gìh]L›þÕ†ŸüC¬q>±>/W$ñåäÔ„š¨ÖRàÔÅmNwªÛFžšÁ¥½ OìkFTÓ¿ûûo2›J’ Õ?¦?ÖÍ'Œ¤ô¿o¼!2©TȤ&6íVöiX8ìíÆW¨›=ba[½˜¶É¡ƒŒÂ¢»ÒëK¾êèV×îË&3˜ÊÝk[ˆÙÎþtBѵÇo·ˆ¹¬éR/(W‡Q}8û¿³‡1ûLy¶ÌÎÐà¸>Hñ ¯h s°7’yÛT˱ô‘UÎZWCàÎ5lØ„îVN„ÕqŸø¹xvºbÝF-Ìio¦¯ú«‡«ë'žÌVŠ‹ïœ³›ð‹rv+Ý~IÎnî7:góórvjMú²œ]Ý/ÉY$\_–³›¯çKr–ÖhYÎn$í—å즖éå¬ìóe9»ñÛ_–³Iûe9«ç\YÎnq̼ÍÙ¿üëÿOÁã´nnïùn¹ü¨ûh·HÛ×CÄFÛ •EÑsh–$騖â‡Í/Ä´·'³×¬Âþö[É~s¡­¬)yNoUëÕ«—³ïï¦I2]oK¥ÉTn a¨ Á$Dé7“oNSR`¥¨Kfqâ&œš^LÐK‹ ·³å´>I¿ß42èÓ¬/÷þƒ§]¨áÆFGjã!òX/¤Q:Ó·0©Y e)ªJ£´ÛrYžj1åÆ>ÒÀ¾_k!5›æ’i³lÛh^ua¹»ù(üoOVð&w§ûGm¥`¿é„çWèé¢@ÃO&aìó2ÄO9xGFu¼<ÑÞ~Æ?èȳ۪ßZ¼Ð¥äï|”oÓŠK-4[h˜A´…òøá••¹ˆh ½ˆ|(~„Ÿ€ þ¤†ˆh¼2-Ä…¦Z-†k½ØÝO]=A¾Ñ&ÔŒ…;ÌáZÍ­zd†† ÖåÜÓs]n¤Ò÷£íÃ4ƒªÔ²oDÝ{¾u•aÊÐ Á+‰~•ÍšDd†ž:qšòáh­Ð“[V‡ÉÈÁ†éT„fÊRi@Y¢ŸA»Ú‚¬ ‹¨MlO L¦Þú¹ŒtJ­cëÇ€ ÖG«—oêMR€ÎuµM)œ¬Ë_å}"4èÊП$úÀÑ ÄR'”?T3ªI™­ä¿1z Æ®ÌJ&(} YŒ56JBç‚LC¶–18>Â1*ÀRqËžxÚuÊì)1Ù”b]ÍZ¸(¦‰DóXjó°/¥èÀ'ç,«;Kí¾Íj÷Ÿ`N…ÀtKø^ÎN… µ›õûHÐ(˜rH/A`ê™O¼Ÿ©$¦ÌEÉ)w[>/}+øUXQJba­ÚC“]ðŠ':j€TZ§•×R4ÿWj®´ï¨]e–&/,$ø׫М§¬@Ì}xÙ¤[ÝHuj557¡±•Ê!)Í'Øcá‚yKd•an¿ÚM AîX< µ·s°¢A){yÿˆ7Ž!@…ǘÅù÷¿ŽÀ{ó§û›+0¯B•j¨ &RrJN§çë ‹ éMý“¶;¸u¦mÑ’ ˆ€­t0k°6S)Ó+»ÖhzêW¨ vÖgþÈ2%9É'rê£ •/‚­P!;?HøÍ"ÆOˆ¹bî™É6—B£ÀÌ$)§<.gö]z0Vת}{)ƒòOBÁÍÚÜ•°?Çϼ«* :í­v/öBKka ^°•š¿|…øG."öwà¹ÍÔb²w‰¬Uz5ÅÐ'x69üšæX‚¢ÏN5¤·Tü|ÖÖ:nѼ°•÷G0%˜®&¬#G” ®J–œr=M‰òEJaÕÊgá í\*E ¾<•í©‚‰Kíù†újW¡©c@Xb‰kT¦¤þ‰Ê‹BÆJ‰BdÕ,Î ‰’.ßU+«R­@é´’+Ãj´b©Qm‚kc'ë%ÃwðnüÍ<¡çöæùé\Äæ @$ƒQÀüʃ3Ì÷ë0ïÀ¼1\0_Ÿ óµ`¾¾E˜Ÿ,ü±a¾¿˜?ýÆ·óyùÏù¾ÀüóùU`þöÍž®Ÿ®n¶÷¢…˜ŒW‚%ÎÁ²½-Ÿ£ ¶×¢ås‚e{-Z>'X¶×¢ås‚e{-Z>'X¶×¢ås‚e{-Z>Gl¯EË'ƒ%™z¼ºº»½¿Zš ×‹ØR¨”QQß'Üœs'Øq-¬Ð¨²üù¤=š`7Ÿa/ZWnyp±ž¿„!¡#)+xpÜT°gµíuç7§âéC3Žß1!­¡„0¿a©Ïÿ"qŠ¥VxJ¨«@±&ÀØZŸÖÀkQ°‡DVaúˆ(1¼QJÛøÌµGyIC$* (_tp g¸Jˆ]QvX(ñ,§diÊÀ+1ðx¶þiýêÄŽÂuÕr työ^¶Æ×Á`¦ÿ*ÖÄŸµrÑ>ºG“!Ÿ7ݰØR ØŽ&õ4=eÈ{¥ìÄÐhA~_¯C~-È×!?CÃèï@~~ò{Ei0ùð)Èב„× ß²ï‡€üµ._òã;B¾LõïùR—«ÞÇøøþ0ÞIfŒG!|ãû5Œïãë³1>/ÿ ŒÏÄøþš__„ñ)ŒOa|ããÆÇׯøú8ÆÇ'0>ßÅxDR½ÀøürŒ¯ˆñý Æ÷wÂøüa|ã©­ÞÅøßìßnõ›?Þ<ßÝÜ®™<æ+UÛ§ÛÝ;Æ·P„ËŸJÐ!dŠ®éI;Ø÷WMî¿Àx5?<ÛšÐ/®–ÁJ-á–jº³ì¥&P¶îáäØÄ Œ'õ&†±ÔÀøêñQüK&ŒŸO&ôÊŸä‡Q„@@›¹¬ëã{Ú2FÉÐkItƒäÂçÒ‡ÃÏÑe÷BôeÙNaUž%âF ¨tB‘_/Mp¥¦ˆt·´D¤³Ï¶5Kg†¼¤eÂ’„³ÿÞ0ia¼z”kLûÝ·ã.uú¤/󪱄–©ž¹˲žÐòh`e0~ÂS-S˜^dk¦Òâ¾ ¸â“Àx,\Lá€I’BRåfÉpØÂ,¨%ýæu3l½9hª“Ò\ûâm3ü Ž8Kƒ‰FÝõIÊŽ’%Lït[›¡HÀ& 묙ª&d·Q‘û’1¾yk5[–Î ãñXÁûƒ…Ûò¢WÞ[ù-ÏÅ3@Æx ¥­ä¶¤Q*ËŸ¯1^€'#U£‡w¬[¢×Ù%ŸQ;ºýÝ¿üYc¹xºº½Ói èÄæ.‰_YlÊ‹ai:¿3æ´‡Þ–šýgñ1ôñ ©l>kg¨É—ÃÃ:z*Éi>¿ª÷P|ÎçŒ%6å@1R,YQ™šOš´Ö|JJ1Ìëè®ü¿lþ«£]¥—N²º¢ä½ôœ~¨ãY z‡öˆëÞ˜é/ùááÒPaϺ‚ržÿSÜØú@””R,­'ŸØ)­<«È=‡ Ã;°—½N¤â¦´y¤I髨ÕýM?|/%¼Vý¤Uƒ!“ó¥&Öô|¸³`ˆ&öJOsQøë›Oü#||<\ñ¸x-€oʳö.j#—œáÛ®äC;Í嚪ø ‡Eb…qo‹öz•¤’®NÏ´»ZL.[o¥¨b·WÅÊ0›7£k-ífMŸ¢}6=êExCdkim:uƒµ‰´ÖZMi’%,U¥MÂnµ„z ®‰¡‰–‰8»àiæ/%Û”;ˆÃU-bb«ÔKs”ÒìŠ %·×ÂC×íH,uþð4¢È¥3œÛ•fô½/~Âq›-bn¡'˜} Q¨»ðB!mJkIPü}`›(¯+]”:Jĉ?Cb¸{-¾r> Xo GHÄi9IšÁŒíT¾Xý(À×ÞEüé^TâÙfs£§¼Rª@Ù3Úù3¶°Ü•Hp¦Ô-lL_ã¦Yœ£h)VK‰ãwÑbtHðœ}ÃfSYßGɰt­ƒ"öÛÒ4eëžÛ SµAè_à±I‚˜HZCリÔu‹kíäÛykE%в¥–Ër{NÐC˜ó1‹"­.Â\¨)OXç#ø%·ãþ]?ëW5®ˆÃ×'hÚXaU2y8.W±«àgfq>qË“¯‚ä’ê„ȧºÅ•Ôüï޾—uËÀ纅¼ißËFLêɺDÝTc¥@77JPM7qêLYGí·Íq‡ß_=ÜÜ=o«>a—žäŠØ×p¦æ‰yp‹¢×êâ¹V[ØЕߪŠs[uÌ G6Âq)æioYÕ» ‘tÕI±d»k™x‹›wyÒöÊ&Z©Pþ¶¼éŒ"z•»Ì9ç²ÀGöÉ ³©J•3aùàw¡'›[M…ª÷ëã;RÚ‰ó…ñÿ[Ðà2úÀÁM\åR3Ò(ÆH@él~É¥UnÒþ„ebåê y@n‰áÑ@¾çÃ&Ôõ–‹.Úäe¯ äÍÏ>{£†‚¤’ƒ¤Øçf:Ÿ¿nV‰u¬G/’ö^#ÁVl™6§ãáÆ¤,;IoßêÒ•^0t*}chd*”“EK̯kÛùpŠ[Å“ÇÆR3‚Â)7U3ÒÀ19ÿïý zöO·w÷×6Ñ[FfKz1þ¢‹ œÕö4¯Á½Z ¡4ðš‰(Š0Ñû}=)`—r—ô)k9QÓvHlÕ-‡ú´‰n^:Lt-°.Ûòމn˜ÇY×Ბ6”Î)…kET¹‡h‘=Y,ÚyÝ[KdØAo=.-‚ÇŠká\ UºÖÚÔª%ÊÝŠH7e[§”öA¤6¨ÞÒ¨’JÞMLçLÖÖÕĶR¢0„\†Œp,̼Po ÅVPKð¨ŒÛÞñê§‹Løƒ¾ŒÚ ü×[ÔÇtV œalËCɪ¢Yzy¨ÐåÉZWnAmb´øÙAg „_¦ÛÖFð"ÖÀïP‚ëŠË%<9èÒ³EÆÊAW,¶Yzž6ØÜÚΆ)I™ïËu[šEÊb°]Ιedp.gÁÊlbûpÐÙ0ªKõÌ–môBþ®Íº[eieB˜¯Ë‘ðZaîú{í—ÙÏ)KŽ:¨Î¶$(]Å—TŸ1«Éˆªu €šW¯æym'|)•“š+hÑÃá  1`Å€ÏRMp“ʰ³]Ô8èÉ׳“óÙ.74EH …Œ')Q+@¿ú½ 씃¾”h®kŒôI޲ƒn/XëaIõ–¡þãßt÷÷w·|¹Oü*ý¡÷^ÝõhÕïµÔ—å¶üÒñ¬­¢Qm'T:Ïâ«]­˜q$SV öT ¤k¡ZÔÍ™‹üÌ…j¦ª>Q•X<ä{Pýd­ÄS¼0JÔïõˆŒ¾×Ò`aÜ'µÉ§C|F.Á¡%µ×añÒ¶>ä‚Cp+CI§¶4p›^†j}¤ÙFÃá䕨†81”˜UŸ,Ò*¾ð=T¡•Â#Íø¨ÊŽyb(ŸÔ©w*¥¢éÄPe¯ä`(ïß †?¤X„Ã6¤j™NUkšë`(TéB ,-ÉzÑã}—¡r•´£3¢|ˆ¡~>qsSEÔvDÒÚü† Ãîb¨v‰Öסq(’e³œê—æIR«nð/‰QÊ%µ%¤Ê%«\.Î ¿Ý¥C/ÛåCÙ®í­Ù>3ÔÙ+i3Õ‡â1ók±Ê­$UŽ\ {€ã²ú‹¡dO.b?ÌÅP‚¦X…'*Ír¥ZۡرmÙ‡ÂV”ŒÅ*85Y$B÷l†¢JH–Aóc uPÈ{ µ. *YnÅúåMŸyÊJ3” “ÅPZäz"²d‚r Ô&{w÷ßÿLõ¿»|¾}¸§iÈ|ÔT¿š±dZl&×—&CÛ#Q¹µ¯öùä`è¬lxr¼<¶Úk¦*8-Œ"ô|sêÈž~3Ò3ð|Lë¬q1—Ì:#…9*5(8mYk>P³Ý;1§‘9O2!Ij”²j+Öí¿¶ÍÙ¹@T4[£½aåWúÄqëääšµà†£4ªæ1gÐŒ1ýýK7Ö=&U5oÖ,.ÈOÎ{Jt6XóšµÎ&psæ`m:o:à²_Ú» Úu¶Ï©ÊPŒF ùÏ–3¿<‹¹:#Ûb_À~îP+R¾)UqCâìöÐxqlsV%×0p·Ó‹‘"Ÿx¶J³ˆTÐ,mS¨¶NŒ³Òóþ:b²Ÿ†Ðto­aU¶“I`¹jX¬í;b °ôátÍX–Ô‡ÍÖëX-,°‹QË.¾B„UÔB+f|¡Ëf^#ƒé>æÙ\hÖik¸•Aîö‚Ÿ±ß¦¿©ÄuÝïÍ R_£3œ¡£ Ú?`KÎI€—Nä æjW4oÞšH—Ý2ÓyLRVM–ï!ztx”¾€&Ýý%€vp3 XóÐ,ºBâXäÐÔð~|¤Sá:BwÐ~¥Š§NG”3;<—Î7‘~³þgO†’ƾrð"éá3½‚DpÂ^ùGqRuvmí•ÈþŸMƒÅöfs"Öä,?åÈßÿáùùêáñÚ¯@ Gc¦ˆ$ñÔX€;Û×±GZZøÓ€t ëÉãu$ŠZrLp.!¤R$5¢Qê3ä“bÅ‚hqƒ5ð¥ÞËQêϸ"df¦*|\H<šS Š1~é×¶ô=2È]~êBT› ’ˆ3äÃ…s<‰ÂÌ?{«šjnÂSiËçò·8Ž©¯d6äKè:TÉøS¦ʬX¿+±6úÎ/¥ˆ!¿ÙØ-bEŽiOC•íɡťIBâøûó«ê¾h6º[ØÊ×ٹ؜šÇQ‰â+ÕR@~é§çt¦'ÂZS~+˜y©TŽGmS7£öš½µ!¿ÑpÐ_ê÷÷`«´©_Õu˜#Íú\¿wÿü}±—Ep ”#B9ÏÒ§ å›Ö*Fçô‚|ÏÿÓÞÑ_K©=Ïx(ª´Ùý ÔPzr\ÅæÝE±s¥[Á ©7^‡V  %cèùvÈ7ÃÖÁ><µëOW­+_a”|#`D¤#Ò òRD0´áHgùì9…Ò$¢TŠ¥o/¸7äã#Ârtyóˆ—‘3-  °M­Ý ¢ AkÌ4¬-{=—‡[b…8DÉûém, Aݶ d“340E)x`™Æ_÷-”ÉÞë=yD©ny¤˜• pbOe†¢Y¥nôúñÙ„¿ŸmÏk_gE¥åƒãZ±Œ‘¸pðEÊ0“^ØjR@U™Å¾#9Û*å-<²³8¬ë>x=áo+ÄU9—ðǹ‰‹+ï÷ËÝ仜ÈäæÍoÿñþîáæáúU:ÉïF'ýGé›?œ°›ÕùW¡“ü¥Ñ ;WŸ¤“ø(¤é$¿.¬4znô5&q:‰Wè$\Ó¿O'õI:éïJ'Òï@'ùÄ×£“8%I,KíU:ño²8_“Nâ{ jÑŸÔ7L'¿Ï·ÕIý—§çë§§›ï‹PTŸô¥>ùQë“OÊO£>ÉK}ò Õ'gBɯ^Ÿô÷SŸôÏŠP¾™ú$Þ%”iiÿñÉ_vçJ·gëW˜B&©k‡æã· :N¥I0ÍÀÏÚ]Û«ã=/C2µB«SµC¢Œ–²ƒæ®‚Oë©àÕÏ›ö˜–‰ˆJÁiÍeku‡ê{*ýÔ~ux× ‰ð3” ¬z˜"R$C÷Äì+E7šx\qN/£-‚ûh_6[KÕö*Ñ›ËÕ¶Ùÿ_©ç¨æ´ðà`"îj ,ð33‘4”ƒóZŽO´™ˆ|Eç…4¢ÒH‰[$ö0‘R±mïó{-"]Läž¡q½œBøêÅY*ééYYªÈH<"°`µç§•ê-Æõ`›2› P(¤-ÔKRÄOý]&&‡}ACî÷h›ï»vìr«óú™ºRnQ®h¾sªQ? `ÕqÚ8ì=uXæó„á8„K¤ýʶ–œ`¶©áneÕUºuXè¨6'YjýÄÒP}kˆÆ³ãÔk(T© Ã2A2éEB¥–ÿÚœ;Ã4”ÆæÍuM—kIR[UÌ‹Œq¼AÅ÷š×Qׄç EëÆ›AGpÎ".ˆ uÓáFøò7HÍÚW›ÐÙ“nß‹|±Ä~œðN_–­è·pí¥U…ó¹þ¡…$K&šSVD[€Ñ0"tÕòß/@ß<®UxowÑ;.2‡ÑˆÍW¢›?¹á>ç¶¿û׿þ«¾¯ï·WÏÏ×wóD×ú½ØcQé¼23E1ÄÊ,CÎ\+غF¿Yr!{æ44n¾÷íÈ7$ý~†F€ÕÖΣG=š¼Pw¢Kõ#§°ÒºtN¢Ñ™KëfþQ›”ž§ÀK;h”+ÉJFígAæk™§­¬Yh%{Ï€‰¹ Í`#OÉãO°.§àújtÒŽT?è¬ë72–lÔÓ~DE2¯G®iÀ¯çˆžÆ Œ@l¡‡j‰`È)º”Q”Î.eªY% «ÎmjØŽR%Y<Ôc©|HÉ6ÊÑ{PbUDt®4ggéKÚ’Þ3ØN瘋òœœ¾2™D?ˆÚä.§T@25*œkÆDfl¨â˜§…fÐaݾœáF&ÅTf ¤k®èaVi¤¡&F]¥Ñ­ž¹õ„âT !û$MˆvP>)e¦uÜ:ÆÅC…ÂE¿R:õUtóáÓYaÌ[Ì÷•ÄÜì¬ÊS}à‚jŒ×9?`=(éSÿ †¼ÔMªæ+M•§Äñ Ú½jÑv"Äó|ò¬ºVnpÍ«%Ô ^2U òö‡XßÞ<Ü\=_ ïyÈû~ ¯¿È‹ ä½ywo!ïþúæþîáy_ òêy¿,È»¨¼oòö/½~º½»¿ý®—¯@žã(> y ¾¼yý ä¥!χ‘ yõ ¯¿7È«@^'ÈËÏTyy†< ˜Ï…¼t콄¼ZB9 :ßò²ãyõù—ïC^ž /Þƒ¼úrÈ C^üÍ%GñUÈ+™[¯@^¾yùWyùòºâ“`—;°n{ììã`Ömïƒ]|ìò»¬å×oÍtÿìò#`×ú‡¹°ívñQ°o2õJ°nûØýjwñþtuûü¤oì(y—D¸HšÄ#°&~ÈVh™£P›v|ÚxÖ[¥£Câð¹rÅg˜š$ßF|"îÚ²V¯[ž0m0J™ÐÞêÍÐf é™$‚ÝåJò/ľ 7nªðškMœÌžÉ,í`FË}R-Í4ÈnkñãâF•üÖqj‰éXîl¯´(a¼ãä!¡"–ŒsM^T:Öå¦<Åq[>ƒn/"³[î|ÀÝUëH@%Þjn$™¸ ”ܦœ{óº”ýi:êôÝèöÍyƒYI9¦\ˆ¢Œ$Y¸ùðííï¼ú¤ó ix  9Üá%“С?×tØÕà ²ñ|–¶ä!ô½5ɸÆźIÚ åµc»9í2è qž~¦@“.ç|’i= —Ö Ð¨J:ñ£‘8kT^•'+”ù­#+³Á ٜ뵅«õ;ÙÓìbÒ¢mM´¥Ö|#Q”¥äÆì¯-u.fóŠKÏE{—Ï,ä ýb¹ú¡F’Wrx8DGFÕ‹^h¡ÓÎ÷¥&kî;˜hML.iêc~wúïÿ—›Ü\]ß<¯ï©S§Ñ °IUÝSÒc–dFkø{¾¯‘î?øÉh‘tؼí¾ö+vÙñÍýÅЭøÀˆtzŠJÖ îGÖœy³½\PÆÀP¦¶AH;¿©’h÷¢CsœU%?“ûWN sú×7˜SŽ@ŠõñOC’s_ŠÍÃm‘z½Dž¦Üö}e§Ð¥>î|ÆÖRŠŠ±+—Ú:T÷¢EŸ?ë¼…~Ìç{\gå0kýÝle@`K`ÈpŒËdxÛSî Æ[r¤W'Ÿ@ƒÈ8d^y*-T2¨g¸z³¼ ´Jè·R_ªÂ…èþü-,÷G\y²ƒ^4j=‰L¨Á•ˬÿfœfýÂB_”ga²Ré-žÂF ÊBeùÎÉÕ¹óN\/ŽëRŽò؇ß^]ß?è›ÆB" ¹ g@ëp†€ß À­,EÖCÝÔÉ¢ÄYZ§,ÁÙèñ¢¢èãŸD éz£’*Ý'>²´…GlAn/²DB[(1Ÿ¿• 6ûÈÒ±¥ºÍ©,uå-%°‰26œù6®Ï_' ”ÀdiÌ–V©/<•×%‘2(²¹f•&=µd'«r¶ùÁcòYknH¦Ghž*G¦K™-`¬0ªs±¥x+K8Òª;™wr3„ý/}ŽÙRñ”H£-kØÉª¯U‘æÚçI’Ò9…Vn~;ìÅ!W¬û¢èôAæö+pƒ…Ÿ·+’(q Ÿož®Ÿø²l2ÍUö@±twû¹HµÆ°Í—€µ‚÷€ÎtÎŽÈ÷š =æ`󙀖/MY’¢¬PV”ÀÞ•z¢% ¸¤£4“²’lP±›ª½0ui}MH¥t&X<~ŒE³«²v=AYöÐXLYÛÏ·µaªO××Z¸Œo‚3nXÊ WùËåºä^ :…Ñóf›EI(üz…ßüöîþæúñ‘PˆpÑX«f e‡ €Ì#—ååÌWĶú„B›EÛ¡0¡XRP`c”’á±6!V(8Cm‹¯ãLs•­P 7¥NóXŽÀëíPA‹šÕ'Q¢/6 ÓåÀ¸ú4œ°'Üž”[øIƒ,‰ß7¸Ü$_-e#qØ>X”zqÊ”¸O6cã8+0Þ .5x ÷>yº´É‚÷ùïf'±².1`€JEd…h¦rYŒhoÙ®t-ê0ØÓw°`žD6ÖÝoâÍyûC(·ô^èg©8A†³¤ä,¨:d.ù¹¢¤žL•ëyMºt?®‘üi5µ;%£8i}÷¦Ijÿ¥”™2=Õ„Á LŒ(3–„ ¼}Ùì­ûs“rJMÚ'ûûmXñTóOhš´¨ü\¢l LÓ øäŽt *ö×C1Ùµt ÁÖß";B§Ÿ–)¸T9c>,ÛIZ?Ö¸gë[çªÜ Í[$?]*cùrb“Àz•wlÃa¤ÿrÖkÒpk³æ€VI€¯‘Žj§ÄÉô˜ö«Ø¸^- :=àÐ31©á^¤ÕÍ›_ÿ—§Û‡««#­ê’V—´º¤Õß”V·û“YÞ’Õã)­âeZÕ)­è‚¿žVò™¾ ­ú´B¦~fZõË´Š—iÕJ«úþÓ*?œVñÒª°iWZÅJ«øXZ…*ðO¤U¼–Vý¹iÕN+™Óú–•ò]Óª^M«<§c›m±Ð%‘V}¤U­´Š¦•­l ÷WÓª_¤U¼L+Ò"^O«ÿýçÿÀ_ûýÕãããÓ&ÝK9l¢àãËí³°¿–iozÄî¦ ›vŸ©UH»iJ…¡Ê¯Ê}ˆÝXÔ´%åá¤G®ª?*<¥D²ÍýÍCÚet«ÝE•N%¦PÆu.†“Â¥bo~—eˆ3ù ç²øÐ”ûK’áÿGqœªOµ† eí¬ˆÝƒbÔnþ²…\Ò³%Û@%y®f´jl¥ªôU Œ„ÈY>œ’kbàm,'®zÿß©O_ªöÌ¥UËQ"8ÛÓ²qÃpZ· I]$ÆœÐHK›¬Ûðn©\-yEúð‰’¹Xௌxå4óõóݽý`¬Ç(õ嵿 TUÊLŠ4ÅÒP]$ÐoA9¬¦¤lb¹õÝÍ­^‡•¼$®û¦³@3"BÞäÊÝ¢æ  ,Uˆªy“ö›„R†ãæ,¿+…š€”úû'»"·H9éìbºÕ[)Y("‚͑ʄ*’Œß›HUgPûP²gtjËHý ïò»(Ûectئß©‡©æ8¡°Ù¼ €„]Ê™ÔÖ rÖ¥§ûÑš¬Hw¯›ÅüÝOÕîÏšù~×1B¾˜@U”­°¤ÍÌvbË3´`KšÂÜïâcY/Sâ7 ¦6h¸AAQux[¢¨9iÊ •£Tɰšý]GÇÌ`Z LÃ`ªpj+Ónã.ó)¾ t|ÀùBK\ÖM,h%Dg%<…×nŒ÷‰ H)g£Á4±+Ã!:^LÌxŠªS'SÍyÊžÞæ’Õp·zü0'˜J•êÓsj)c7Ô•©ÒjÊË®êžso3Òáf^ËõqFFëÎñý~}su{+ÚJÍX.ÌÆÊZˆ ÀÄ Çá˜X™;áž58R ¨¯ÅëûÔ¡(©ä›6ùªy•>{*8BFá"X{Öú}ž”`_½Å Üè…˜‹y"v@Ï>$†¬ºû…n)b_w‹O¦…€×K4².P¼¾™ØÊõj½¥„žƒ¢”&¢ÜÊ“N‚b ‹`TyòÖt†Ð’§hÂ3´›òÁ)Ü|Á!WŸ_ÞbW‰d¹‰° ‰@· /}EHiü@±o&ÿ ‡¯ïoo¯yÌU‚…Su%º@P; AD¾jÒ²kî¤ó“{£¾J§KÒM´k¸àX²DÕΉ† øÐ\D>#¡éI¾…sGXR1fi0@’OP;uÏðÚ4éö†b«t‘Ç"ònMd€l[®æP fáZM   P‘{ ~Ìä, .u­ôQü¥“`8{esSûòÓB„jÆÏÆäœ2hõ8Dü(NžR¨/ϼ©"Óð;å^_L5H¥¥Èt8Ï'FÔ&¢0íº¡ùªÌ>ÔÂT,³btGoCôþMüîîééîùîS!š?½ï5Dû¢?Jˆ>¾‰ºº»½¹¾þN!*yq ÑKˆ~õ}Rˆú)ŸÑì Š^Bô‡ Ñg£èÕ%Dñ!Úßdˆ^_9F?Y/½#F/Lÿó‹ÑoF¯¯£·¯Æh½ÀÑi¡:FS㣗½Äè׉ÑßâÒ_?^=Þ^é@žLHÅV0Ô1F/›Í20¢ÆeOOŽdxŒ;õQ\º—Ë7cÅæO›{£:Ê• eD{Ž[]ÏÙ¯9nÞ˨Ï9çöˆ.^﫹IüB-´NgР¿|¸£íˆmÌ4y+z^Ë« !pIòêGþLZg‰éu؉„øFt¬}ÙNÊ^ÿ¢{){ºûÚcñgp'n“VA¿¾ÉJþR´ÆëOV[©‘'¯>™ÐÊÍÝ3>o˜1g£XáI†¤ßšöê_ø£¥¡NSñ–nŸ),¯~Þ^ÛÃ3 &+=_Û©oþÜ÷/ÿëÿ¡Sÿë뇛{Õù<;aú ™¥i¦#4Å[Ó¤)?CÉ\Z£A™Ùdæ ¦’‚ïâòkÖ@m…m f-ÔÜK-.k¨… E zMNpÆÃJóJ67…û½ž“À¨ËV,Ã<+gîTãn@¿5½Á¸ÆœFPöÎå…_ ÓSZ #|RzÖcž@>MlM—þìÑF+æjƒ+æ1 ´ŠÙ ¶øÅzuÁlEt¦Ïãò’í®”@òõ®¦D<$` Ý«-œ½ÿÌÚm¾’VßEõ|¨O„ÁZùk2§–¬ÿrsuÿp£óÅ¢½ªìÎÕz– ÝC;+• s$D}PÒíh¸yZíñ'ÀÛ=ªKö„»†¸'ƒº– C©»F]8÷¤[ŠN;—_PG‘l²1ç ­²9Ü÷òG“VîWaœ”ÚxûÏ75¨C~q¬n™P‡þ¦Ü£Ñ6,äþžœx•7€‰Áìõ§ï‰†S7]Kýé’.Ž—šXáNªI®—Ø“ÚX-Ôt¬»æòeÀJ±À™‚™ùµMñ“ÍÒ}˜˜Ê2©TÞt~g$l¢t+gRÖa ǹèyÜ åýž6TeáúûyÇ”FG÷—'x¿¢íÈC¬+ÝN¤Þ(žhÓ[†Å 5öSØŠE‹¤cÍDžwkf¦c¶¦íQ7p] ŠRJÁ’ÿNœ# à7é»z߆÷|§±˜iÄß|}±¿©2Æ5–²Yâ¤ÑPµø&v§Z1 ꨆœÑóŸq󳕃 ›û;´mPIZeúS(ØàÂSã|+&bkð Â{&æ†g„ -«´öÚBB¶>v[;=Ed-/V²¥€ß’¦ŽU JÏêõªÇÖF$MæaXi+Jd´~Ê'P,ƒ0åø `‹j¼Ä÷AäLüÔa_S…¹`@Á:*’°-ÉÅö”üú~Ïô¿ÙBŸ?'ÿÜË¿ ø@ðQ:`™—/^¹yóùæêúöêönoµò¯ráqL%#/VöHmÚ'và g%M,Èq&'ÂÄ¢S´¤ŠÂ„LXJ3¤&Z&HPU‡ÔzRS®²Kr•’£tE#„Ô>˜NÚÓŒ £`”TQIÎåм¢·:Ë´Ùù‡X¨µ©jB½3e´ŒøB‹¼Á ®#-`J-ž’¾5È1“IdlIgÐ1›‰C-jNö^OÜêv¼.bqkF”â ~;Ë >a³­½´Å±zSËþ[Ú%¥c0«”–°¥´Û{!S_ÐCXŸ¬?L¯?Ñ ^ܲ§@9Mäñ¿˜÷[¶V*¦C­)¾`~1e8e³°”p‹eP5,3ßF,ñeë/J^ pÔö‰Ùû*ñ%Ê)k'ÓžQ¿L˜#ÄU°d[b}L¥ѧ9ÜB†!©ö{h*¬±|Rž„a­·ðî@QÊL¯ô”`íÑ%™à1ï²?­–m´,M¶©Ìdþ‡5’Ø{`;¥ü¸3U,[Ùµ‘(5fn)%º ­ ö_¢<’‡‹Ë¯’"-‘W,gà×04×îDÛ¹ ÷Íø-lön ª6-sfA-°LÖ^iÚÚQ¦Ïçjô^¤Â].ǨžÒàuÏVª ÑSpºzg-V>+uæ“6ôúªSöÛ7¿ý¯o+•k=w•²U¢‚K†óôËz¦í”¯üu$µ²Jž¥‰iX%:Ù'-T§„Æy2aÛT+“0Tâ^e‰Ä7Ÿ£Bá0CB9Õ)±À7­éÐAðw%¤MÝŬæûÁšêv³›é}Q•f¼\vuOüSVÊP”½ÖZò.TÄ„m×)±è„…ĹÒý—.\ŽêS–ŽÑ^žÔ)²jõ!öOȳŒÅáu:þ¢Á”p‘C¤Oà—¹Ší0È€– Rî«aŒl ¹¢”¾©êÏt"g°ÁŹ/jÖvk5Ôûf™ŸYõª8Gõ^“ì"ùÅYX°/€æIb†nX=ª¥Y£)Å‘±­±[©t›-5‘¡±èDi«,JyO&8TOS3ú)Ÿ¤<Ÿ¦wŸärK¼L7¢Õ)¢TóýimCUëÏ"ÎÐP¡ÅöÜ´­1ºvUV_kz:‘@Ùe­š³:‰E'P€ƒ2‰_Öàz,ãªë”¡vPœ¶ [§ÀžÇt)hN9ßìXÝGm„™<²¡;Uâyåá$€K¹0§ŸÓT]Óà ÷c!QAG…ªÂP`Å>·¥ ã5ð{k§ÜˆÄz Ÿý&¶ÂÛJ¥t/ YtR«Ò:Ð ñº™á¨šö‡ëýûŸý…77÷ט_-†U±¦¸m^³{²h#–ÆN?¥NE.µ—ê#Y"ÚT¤Í3Ë¢ù;S‹\Znˆ!—°ÊS8Lu´ÚRé88$KªA*e#v’²Î-\i•zº¡>­ eźx*¤’Ôá®¶%’H‘êù»r_GMÍæ¨[AæÆBëïÖøx¸)ûG3uX«¢_DF¦•Zgò»¥¶phžÚÚÓ*";8NNPá"Ém[ÏK¸c°>ÔŒ+AÖþ’m¥‰« m²¼ ‡§üÖ(ÈP!5ØVy„yæjÛªiž,¡‹-“P«3Ðà¡@O>WÌD-Ö­º“Ó«,ù·ó‘i™ž«º¥¸ùŸ£Ó—~ÂXÂ.ÒØ«éRÉ%vTJž;ßQò,­£o+MþíFÜ Z‹@K“9_r›Nk˜Ø£µÿJŸÑÖHh‹13mú¼Ÿ­fl=šìz+®#"]· ˜RóSí€É°òR?>%ýgEËQ"ÿªÚMöªÛ@ë B‘4Õô\ívà±ò~¶W£†êö»)·vºSó¹ô‚ù3õؽ£LÖ³0viŽ)Ä(—©ô{.ÕqM‚'ål„ì~ç#¶BŒ ܼ%û§ç§›/âì †âG债pÀgr@9 ¾] Ë–iôýs@~›Äæ§8 OP¯s@œ8€,H3Ô‰rq@ÿПÇý#s@|6Ä—p@¼à›·ïpÀí[x¼}¼¿y¸ß, Ô…¾~!ßâ§ZÔ"Ogˆ×Ià;?, üì ¯@ÿú׿ü§ÿÆIó»û[Õt{f&„™ÖÐ9JbKCÙ™>ZB´àW#4‹µ† CNé+cìN&Ó×èçq$’É´™â_ƒY4/$æSÓ¥Ö¦NÎûù@!Nƒžs>°t«nEû©§òëóå_Æ÷ßùƒN\y†“£ÉñÉÐñMÝ»ÔÆ|ʼ£ÚìI\c´`¯X¨˜C×? <†Èf(¨$i&vÕÚÓòxWB€®t›|1¸6ŒÐˆa«ÝÂŒ¬‡piû±l>ï;ܯbÈ—}0hnFùÅ=îc*úë\aû<Æ$‡.f…‰NÌjé¥d6ïZïi+ø÷´(Á‚²ºûVåº1îÄüÌ s–¦æXBú¡º3º%HŽžÖä–f¦WJ”®›ÐÚ¸²dd#׌u–©K“Ä Y^ ý-•!UGjx—2ÛßýËÿëîéþáîêéþñöøNã·Œ2BP&ÏYƒüh¦ÖU(›VÂz9@½(Òo hí—‡¤-玠IqýtK‹_ÐÅa½ú+(¥¤!’é«\ºA=¨7mU|yJ%Ú—ELcšBâõ3ÛÀ³òKmJhØ4Knº–\§'mæ7k†¾ ·TdÝôÏ4Ý4¦C3,}'Èå£@ŽÖ~«‰¨¼ †V$ 4æ/‘w €Ó¯×ô=“]*iš [g F2 B £CGoÛ²­Õë+íRêÃÅW¬bÅz>ÔÓÚ‡V4‹§‹•ᆣÅÝZ3«¬¹N5ÍZ†ìgUγwôv¼Eé²ïsùsZ+ÄdåÇl u¹FÊ4V;ýÍV=\§w&Šž 7µ±è%ËùöFsDÈ ’_Ý!¨Ý‰°â0ô|hÕ¹å’êÐß9±9¿°qµ¬£7Qq3sk;vܼ‰ß==>ß?Ü_°ã‚¿xìˆ v|vüÛ_þÊS4þôpóôðˆ6Y®³UC”tä ƒÑB›‹ B§efz …á2¶-—ñ!F‰2‰n%UWc Ï%A©„:j‚ÑvÍ"O* ÌK*‘ ’Œ¡fÙ Åhà¢LR=!éß”«Œ`¸t/]8­æÝQÝ#Å^VŒ¼†÷K%qçËZ?æü‘‚¬\Ù¦K‚¤°(kñZIúd^%A«¤iç’`¦u’H·ô-)Xt7V»%ô6$Ô)÷ô`" ë)‰”´)†êÞØ5ê°ôëù¨åŽPûÌFq¢ƒ[›;T¬WÍA¾Ó¥J‚”ïÖ9Æ”/ÐŽ:KÊ”ÂWÙæ%}Ÿ*:&–øM½@3nÚª·Úþü¿‰=ïïîëÑëtw!G96‘?³ù¸Š§ Kiš­\ÑÍDº‡H‰…“Õ:ð9s3íJ^U2x*ÓÕÅùe̶ qK -«˜ò*W1T¯\锟—2i¤Ø¥fp‰`8˜h®÷ËÖAÐö¬:yk÷šêT“ÒµÌS‘üÖi{`@¤d^`ÜB9ò9UHC;›&[;÷ÃÊk‚nJ¸FO9°K_ƒ…ýÖŒ±â$>›…’j\žšPù•Cå–PéS¨x­4Ø-y… Ñ3À$ƒu– ³@"…Ê\Å„êp‡Š0¾ƒXõ’ íܾÎMí/âêû|,]@hÁ(!Fɦgœõ) PIü¿nwxÁÕ²"*HƒÖy9›E‚|µ:zyæËg_¡¢ì± ¯"ËM^!C!Ó¾P²›æçZC­h DCe^Ï­vÅ:Iâ'\‰ Œ9aðð|÷tB ÑŠ†—eíÑá@“D¹‚u¦BŸ+B®òNtÏn¼D œ©Ð ƒ‚Äœñ2&²8°­Dinâ=sBçý'x_b5©fkN` ¤3”2Zµ›äÃ&V?ò!€Ríý¿Î ¡@QAâ¡.ßânsãØB{|Ó-z¶lˆZzÁ tíBò!Ìf‘–oÿéØâ?\ÝÝÜ?ß¾¿ÅjŽþà[Ü?£-ŽÓ×—mq|r‹g/;éz}}wÿ‘t• ’]¦¸°‡ñR·õÇ\ÅKÜž ÿ ܦqzVû/p›%=ï¥ÕþÛÒRïá¶BMOlih´ÎÜÍ^¼›òSjŸ8ÚoK¸ñÂ".Ð Öþw»µ4ˆ´=z‹Înwœˆ»8ö%Uðñ\ýû·ûûº|¸»ÿÄþžyYö—ÂhÒn³8}G¢/^Î%Ñã^Î÷ö7œ«%Óì´¿¥ý­÷%ú¬d­\}‡—ßÕfm^nͦ¼èV§RKíý ´Y‡Ú¢¥jΩMõ+>(ѓݢ/Ç{½?ÀËÄ(¡\ÖfÞâÿ¼ÚûÝóÝÕÓÓàxmq:…ùyªò±Gé©`WuÏ¿›*ØË䝨ž-Nf½7z£§*,ÕÊ× îòÚbÂ+…1“>*E•,$Gö ŽmòÇ4G­dìœà§Å/KÁqêž±¨<Ç%÷oy,´T±²ÊÔy ØÄu€þì‰~)4ŽT¢v*œ]Þ¸9($?°Ëïîð‡-™×vXü­î0¦Zÿà;\ßãçË.ïpŸvøÌ~øQw¸¼Ã”Ðëk;Ü_?‡ó½®y‡ÿö~ü9åðW@éŸþ?_vøÛâá¿y‡G¢·~÷vŸÿñŸßüîïïž= aé §³ÚC©Å¶áemÍwzµœXJsœIÕLj«‡»*I¥Ì†oò¶Ö½ ´ó…çåöòÉþæ°n%-|o8Úš¥¯÷hyˆZ¾?ïØ…\c_úÆÃ¾§+ÕX/Cßî¶Ñìxª3M­18uÿ«²XclêÇ^{S*Ì0åá O÷ì2)4û>ýˬږ?ày6Û‹‰œ¸TŒ•̪Íe— ë‘ø±ýÝÿü_ÿñ×½]öÿÇíóóÃí#ƒ¹røƒ§´b0a¦,J•òðIà=l:z@û›Ò!51¿¨^?‘§@ÀîÏ/iYÐOÐ;—>¼5Ë©øœ²¨\Êðð“â†íÀRä}ÕÇ'ìJ0'±Q¿h*‡fHµð §¤t(tª#"Msë©­yŽv!?Q™ôõWWÒ ™UØ´áø¡¶ÂÐÖm––$´ï¡ª*7k€4¶Ü 1IMNcäé<YzēƖ˜—IzÎ?V‹»]‡¶úmMŸbÂcÕ¡~–Rk‚‰gò‚•F|ŽTxw¥Ùɬ즴a6«Sú 1Š˜¥aÿÕUs°Ï˜8^ì“ XùO´n¨’Õ6š®_£áÁ¸•ú‚¾TeݶӫÝ|.õ ÈÚ0Mð7.ÛׇgÕ±<¥ðg·$×)ÊÜìô j¦îé¡°"Zx£–µZã7¦º†~d hܦ×hм‡òy§Lßt¯Xeë}}ÃUêž¡Nï" Ã.€E¾¤F´À™{2yPHk=} ÁËJfwèlnÍ^ϰ7Ž-/œßŒpêï1ÿ­Ý®™/j9&vœ}z„NÒP9½»úÑ›·ÀjuVO³~E†Ì'oµBcžþÔ¡· ˜ÀY%cÚÃÊ ³Ä~+›y¿y%¶A<ú¸¹6æ¢JÍY6>|aµ@’Üæe䙀_*¦æeð¶¦Ó!œ0±¶3òÔKœÊ0qZÀðô„†ãÏV"ƒr„®¿†àA\"•°†(Ó¡Cé‰Y´C>ëš3…`ã¼î¯Ò£QKý²²ì“_¯ðÐö«o9‰aï½T¡.ÅH6.§ ŠgŠ¿yóýôpóøt-Н Å_(þ øºPü÷Cñ}¡ø Å_(þBñÚ?$Åßšâ¯.Uü…â/Uü¥Š¿Pü…âŠw>](þ{£øºŠ¿Å?^Œú¯@ññ“§øK¡ø Åÿr)>~±_FñýÍQü½«øÛ Å_ªøK¡ø Å_(þBñ?#Š0Åß]zñŠ¿Tñ—^üO‚âãBñŠ¿PügQü£úûK¡ø Å_ªøŸÅ_ªøƒâóBñ_ƒâ6½ø'Wñ7Š¿Pü…â/ÿ“ øK©â/ÿyÿ¼SüóÍÕÃí§úþ¹Q|üØŸEñz"ßßJñýƒR|¿Fñ}¡øOR|~c?Zä™ÿùF(ž§Šâó—Nññ’âëuŠOS|¾JñãS|}šâKÛû*Å ¼ý´ÎEñmŠgcÁöϤøþ¡(>?“âû øþ(Å×Ç(þúê-Ç?\]_?^ý9þRÆ_Êøo’ã/eü¥ŒÿÎ)ã/eü9~„øÃÍÕóíÝŪ¿pü…ãyFä…ã¿qŽ¿tã/áøÏäøsüÃe¨þÂñŽ¿ Õ_8þÂñŽÿ9qü­9þùèÕÿèýø ÇÿhŽÿ s|\8þÂñ?QޝšãïÄñwׯþûçø¸pü·Êñ?tñê/uü×áøËɹŸÇÿàuü½9þrtîoàøºÔñ?#Ž Ç_8þ§Ãñ—:þÂñåø‡7ñ‡_ýúêúêíÿ»y¾ðü÷_Ë_xþ§Èó¿þ›çù¸ðü…ç¿.ÏÇ—ñ|’çp¿þñMüþŸÿ3<ÿ£yöqáùo˜çÍØžÿyþRÏ_xþâÙÿ„xþçSÏ?½åù?ü=<õ£}‰ü…ç¿ež¿Ôó—zþÂóß4Ï_êù¯Âó_­žÿÁyþyçù”oÿ<ßßþÂóž¿Ôó?>Ï_úóž¿ÔóŸÇó7W;Ïÿ3<ÿøtñí/<áù Ïÿ$xþRÏ_xþÂóŸâùùóüêîÍõ›ßüñùöþñöy G>À ^Ù‘®9·=N„ÓÕ[‚üêdl"e8ωùIœ‰¸xfA®Üßzÿ·Iñœ™ÇRï\É/”fþwùÅñ€â+v Ù/<»ýyóù³”óÃùÕM諘0ßÙ¡f[€9Ú&*j–bãLûbÐùõ†Ýª!¤Ë wM¼½}1kXR9oÂCáýd…Ík!é¾#óbD9=,i_Ò€21u ÇÚÓ1h„ÂúìðpÂìÇM&«ö6‡.V½Ÿ?<ß^_ßnaêg¢0%´!6¹ªrmÒ 12NÎÂcBƒð‚FçczÇÇ0‚CZd¹€~¶?Ûä - ñíÛtïr A+uG µ`ªÖ ½–ÂÝ&ÑzH¦à#Â=Ä$Ç;¬4¢r ¢=É [4 fiÀÏoñQ›-˜è”²$ÕÒŠÙ ª¬–Z2M(>‘0tÈ6«ÎâÊ´ì’fCײkÚäYÛ¶.$SxW)iþ³±eó©W.‚䛵ˉ¬râR`”_,ý?û'”ûËKKFõñÉ+Z¯÷p½º{¼ÙÂUתÀL¶8 hàI²z` v°Óª¢qKŸ´ÀŽ7ðM'œØñGÂ7°Bú“¬ûÐA¥Š„ÏØ_HÇ?5(1˜00-¤«—H—S™åV*&­€,!/® Ug¤ÔñöïÛd ·…ßàÃc>@pœªP\¾Æ­PG¾Â¹ñùó¼’[Ôm¯»M½ÿ¦5Hˆx^0{5Îò|ls1#$¹Yîíj'´5Z~Þ#±³þ¬<÷©¸2yÔ^’ÌûÎëQóë¬%ÙP¦>|¿íùãþŽÛÔ4ŸŸúäá©" oÞdüöêîñîQü[KSQÏœøWª8ÄsHF+$—43ÿ¢jó½\ü»_á¦J¯XŠTp´ ƒ—üëb´Ed¾(T*À†;\îµù×ô†‰PL?©@ä–[W€©žÚ½d=ÄpQ‰çþ‚ˆiG¥J@t¹¢rkb]•àŠÊzÉ¿­Ýÿ¶øwn¬†igoöµ™˜Õ$¸]:¹E  2¾çh]_U‚äÿ‡ÑZ¸r¹®¨„r½‚0XΨe?P,L^4HV³8›pÂY2QÀ¥ä‚ÉÛ=*wuõütýtQ…?uUy°kµëâ˜[JU8MT9³·‹\üSh§ëTÖ“}ãbõ³¨p=쨄Dž/MU¨Ê~¢2Ãb¤„Æ“åú]¢ò¬¼}x¾µ Þ›¾ëˆJ6RQ™"àITJÃdí'•i¬$*…6{T¦£2•eeFÛq‹ÏQ©ŸU|ŸÁÍf!"б ŠÁ 23849{^ƒ¡¼×¼(%HHc%˜žÄ<3ø†ïC1ÑGTÊÄ,½ ¦Lç`.¬´ŠÑ§õ‰Áû%ƒã®–‚>§”ç±$ÆÊ”RTÉ•ÒÁSÐ+¬œ¨L½`•B|p**›d×›Î^Œá͇Þ=ÉðÍÎÆ›O›77÷WTB±“Âi¶¸ÂTwF̀ǭç)˜*O<þ>bæ 1Åã1±É¥’6ÁŽw3Œ˜½xâX¬™'ÄÌ!f «b±©÷“`‰/æŸb昇¼i«Ë…˜K]ˆY 1Q)Ö£ç&¥{‹Çû5Ä #fŸ‚o«KY¨ÂN³_ f1¥!^"æ›ËÒwÁ<ž/S%-ªÄì1ëÈùyí±O¤[¤b ±rÉž¹/ã¬2>'MnÌ—¥#2•ÒCyÆþIþaº•ìUöÚ­K©{¹FŦ÷oþx{ÿ¶<‡Õ¹©vÀàqp—J%-Yè7‰­­Ù´gÆji߼̆Ï&0M’KÙsÌ!É÷RÙQ LÔŠ×p wqõbVZÞII3¦ì‰”T/êÄMÙK,[ „BêB :º‘ÖoDšöäèÄB{¢e„ 3JF¡â[—ºAC¹:›§—8ßg1dž@7ÙR±l ˆvBPg®®e ½*dƒ²ÕçÐl5°´Ó\üÄAÖª“"NZ§Ð\Lºà‡}¥xÃZþ_”¶ÔÍŽv€>=¼EÒ¸ºº¿ã[ÞZù®—а&ÄC%h:Kåú½ýÅMàS–¢µ.ló  _È›¡*3ˆóØ{ùòåËýœÀÅm"F»S]êÕ@»!u†ÂábL ø(§§z©ºëè6Ûð³lö¨„Ì^ˊߘÒ@k[@L*ÊÚ$§{tVv)ÑZmÄ–—rƒ¥yMFŽ­õ¡Âèßýoßn7ÿ©*ùíõöþ¹…öUFÕ¡a¶r&ý<(óhœ®:´YXQ–”riêÐ8ò.”¼¤CCÒ‰8/ n-åêÞ㔵Ot¨ [Þ:´¢ïhêP{¬C;BU Ó |¬C­s¾V8ŽèP!ä©Ç:„*ùót¨·Ei.óî}qJõlI<ס½fÙ·ž°5Á«GÙðD‡®epjæmêP¥ä™¤”ç²uhLœîv Nío»ëëíÝõ©ŠÉNWL~X1峊©‹äµb²FªgO>ª˜âµŠ©%lR¼ÆZ1ÅDêaÅ+¦8Y1…ÈéÌŠ)UL>+&?^1YG[ÖÄþkSª˜ïP>ÐT¢ÈÅŽæ”6¾xʰ[S©w¡âœžB…­¢P‰ÉOd"”÷ÿçÿ°š5¿Ù__ß Z…)÷Î%z’ê 0æTRÿ].hЉiõ¢v­ÓuNÍÐÔ§Z‰¾Ò²PH´.²rn¥¹˜]¾r§ÿªMy‡>Z»N{+è‘ 4=PH¡ËŒƒÙ0Ï|Úe‚U£J*zCò÷’ Yî9{Þ:zJJcH™äç0 ËÔá ÐƒäØ›¦ÛQ Àá1W0 eZ<…&™UD3œ÷ ZÐód@§†9£:Ú.[˜É04^ò"g]_ öÚ[9´÷äÑjÖ Û9¢OU-5ÐT©±ëУ˜ŠµA¹¹º…¦§'•Â:VŒ @§žqMÒˆn·‡ójÕzS­uz]B[Öã^…b=¡¤8zU©ïý”"b>¢›Âpqhx¯þ6‚|àÓ•dfS&’¢¹XWÓ\ê rŽ®ùʸ@ôyë󤋊ËÛ½VìÁy'ëX2Øgfד8±j@óüŒ)4W£]/0c/=çÐD ܶb%–´v ”»WÁZ3–:Ž2[?x«Y#p[×N$¡)ÕX‰Ðì,£L,'âTñC›9Ù”®’Œµ`®« qûÉþ´Ýl—¯îëÑ›ÎÍ_ãB‰+%Æ…,J´c”h'(Ñ¿%úqJÌŸ—]}—7R"‘Ôó»Ï(qQˆÛíÍf?:ØÎ‰µ§¡6kï µ¡X{j ´s<iCÇ~W¤f½÷DÚ 0#í-¡&Õÿ²ø°âcè¯ïŠ4¤°ÇâãéQNR]ë‘0;#Äb¼b'#Œç ŽGXÃŒYìäk>¬äó^ÍÁøW˜?‰°ìoOˆŽ`šY̪Äìm>f(«häÑ”ç A檌[¡úO‹±pu¿én "¥r;³ $*Ϻëz¨¡V¨ž*©uå'à…‡FuzËTäuh`˲Å0¨HÞ‹åÒ RKµm°•ÑóÔ¥="KÒq³çylj¨ìGr Ÿƒßæ:ƒ;Ôtµ÷·˜':hôjÒX‰ zˆ“õ{µ ®6[DH^F!ôÐgA0z~A‡RºêÁ•/‚{VÇ•–jZ›m]£Gùùôrþ¡ánGöûù .>³•VÉÇÆLãª=«ËÓzJñ¡lçÞj*Q8Ï,Ï…e8­iÞ»í­'h¦fÁLã2ŽEØÉ€f‡WðŽ6°·*ûÞÒñ¿„š¢ä‚P¥;ªó×=GÌD¯÷þkyÝ^¨o´ëº@¢Ûúáȃó“«\k9xDH›‘ܘþ7µà¡üÕ5…‰‚W„¹Ï̾jBҵ܂4#4³VïQ¼ }…VµþÊ£ÁÜÓˆ©RBgIÒPýU|Z ›ðêÀÀlô7ô1”lÿ¦^×eôÚ…üÂè;äÿ˜·žqW"ã†RÖ5W,–cŒËWÆ.ç ‡þ?ÿã_þ+pÞn®¯¯ûÑJf.@‡®ØT}©zëçôhŒ”â©(&aÖšºŠƒ9¿!ŠÖ“5®'`†7~\íþè=ÅWÔl“)8­¤Â°ì âZe‡–1e#@º;Y‹Æ>Õc®º”ýê Jä#Ïh±è*;³æà\b!Ô×w>é3—›ì¿QI5VöO]‡xÞcý’‡†Bh²PR£à§°„mÐNÇ.›ØS3Är9’ç0di:„’d&-޲úɆMÝ[UŠÒÕ–eÙ¸ Òº·,… K1W…¼Øð&Ö²©7ôÕ¹J`lÊ-ÐRÕcšR¥ÄššaÒ¤bG›9°äbå¼å)Š*uëaî.Õ5æÞ’4[×,êi( É{pé§òïO%Q‘ªæe\û 8M;mP¨N`»ÀÖÔ$ñTÁ.8:l‹5NVAP©˜RFEœSJ5„¿‹¶È²5!)xkGy‘ƒKÞuŒ¨ qºÈêDQnÌ‹š–Ç­ï¶žhЦcà® íZ£»*ÕiKx[Ej9}8‰¹®aìûQÓErÛ’Ûlî6W·’‹ É]Hœ_HîC’Üÿ«‡x¯÷÷[¼+f¦B“K„a¨Jc!Þmø¨…­»·ª²Õ .ê1g-òœÚ¥Á÷^t[WMCûUóú%ÃI .Jj­`¨[ÛîJ…`*zê`»ÏP;§Ã .ejð^wÒò­'{\D‰÷ï%-æö¡¼å=.W"«‰¡€Ê»쓲Ò¯Õ€ì8n›UM¢w·âöí“dγötë2l¦¥Q1¥™‚¢& 5m²ÿN­+v$×ÞOâat¬MdŸÍÁÑAÉàŒ ¥ÈÚî˜þ”ûêèÓëºRO\…·ñ±Ä—vÛÈxùÀŸL‘`½nÍq”Êž¨«4Ý-©^E¶ES e?éöjŸžqšÒ‰(È&)îÅ5œ]{[ª$¬ŸSÂxž\ûiK˜W¶1…; œÞXºj|ž¼hוy”¤AÆ2â?†ð䫨‡¨è®ØNÂO~â߉[a¶ÎÞœžätnÓÝ2Í&+ºH+e¬h‚o{eµµ5B¢ Fhä“¥ì©Zá`/äI—É^'ș̌H9ºÑ£2¦kÉžŠ„£}Aÿ¬»ƒ¯C2ØäV†mŠU–‹ÒVé?µ)H4r‘t>Ú.q,“ñÚ(­U¿¢DkÓyÖôb »Z5eøÿ†¼ÿá·ëÝíç4&ìõ¸Y´>¥Q©°P–O|òz¬ß§²©¸D1’º5š"Ò&ˆzIo·ôê f=ÊU÷ËÀ‘œcTqåJzÅ#¤3„JØÊ»ÅÝÇvÝ5õ7­âÒuk¦I7=Ø‘=íEùÜt×-ç˜s«úYö—+S4^”MdÇT´ŒÀÞ†½¥¥RÎVŽdT‹ÀSÂÂÀ«4bÄ‚}ÈÕÂHþp„ѲðäÔ¡"ùnØ\—‚ -dAÊ͸ÂwƆ÷ÎE(<Ñ!/sÞ\ s´€ï=ãešXN]÷kJv:8ƒ¥]ñð:I+8Ô“ƒÄE9ë¢@.œGuÒï Í1¨T)•Ï2D‹aFÒØ·ÙqQîE=²—ŽðRr Í„0yˆ"½:„äAÐ÷Ð~¤"Ë0þ‹ó\Ó ê`ÕÉF«÷¤@"dRf ¶µ”ú‹dæPp"ó`бÔC¨_ÆŸ!™9n¯Î†rcOØ­ŒŠä3uF›et#õ 8e>äf×*ÆÂ†öB—EYWÚ¡1? ¢Þk¥Ni4oâýFÍçýÓÕÕÍVï‚•>5Ù=õê$PÍpªÓV°àœÃû¤h—€§N2% KÍÒÖá¼iz´¨eEÌl}N£ªK 4㬌—jÄ5j÷P>„¦-ùUä!Å]] g(i*ÔŒ4ÍÛc^#\L´ç E=1D97h ¢ËÔƒ› ÏÔÞ{‡+êÐ݆ðL5ʆŠ8ZÑ1JÄÐ4x©Ö¤v†ˆ¤ ¥yy…m"ƒfÄÊõÎþuðœåbëuPS-À.á)Õiwuo0ÚÆ©Å#_!aÕ3jï{'å܇\ƒ gD·Ûò¦Ø~HÚ÷7oÚV±\¦^ÿ™±‰WjÞ!éµíì>Ý*“42ÉW(š÷¶Å,zåÌ<ħ`Èå•2¤÷6ºtMo×–¼o|²<Ò·F?%„\JÃäy ’‘ð1I Ç(„ϬÅ ;ÂK{5ÜK­Ijv_ϵy÷¡{Â^· UÖíB#(ÖåƒÊü‘ ‹F¦$ŒY›têm©n>|C ÷ÌžkµLH節¤NUOËdž–?S•ô#ˆÎç”3'9eÖo¨;‰8¨SR[Õàü´ÿdÛîîîo7ý^픤C¡Ú|P€z-“’X`øŒ|œA‚=O=Áăܭâ¦é¹‘èZ$k¥®­ê¥å è¼OkÄ'­AvÂl}Î’"Ðõô‘~X¯ô¢œªí×~™Uï·GГ‡øçªºØ™¡§»‚å&¥%99%Ù•ehÜ_v¡®C+©©s· Þ²Ür´œÇ<@_MÛ¬±€Ù–Nj̽¾ˆeÞ.‰ÚX5¶¤ÔG{ J`Ö’»À)%I—ÐrîjÒ(•tƒä,ÊŒ<•jUHZ(qIu1S¢d®p’x1s%á’ å¿Ôâ¯o¶W£qVð¥R0¥!•y<í€0’!À•\³ ,.s>¤£ÇäLÆCñ8„  jä’k¥i¨ ŽqªÑ:|n™ !®#$µ@åÖ~²­ 4¿Ð9ýMÙÕ+ÓRâ·ì­µƒ/4Ð5z® á¦áS\ ™ÞkiõŽS,OÃ^i®ÑÐù«,\UV ¼ã8H“ÑÕ¤ÒdvÀXÏ'%Ϧ éÖ³Bà\d«§Þ–3§r$%ûdÚ‰â) ³J“Òè/4H‰Š\%W)uëGª^²mª&Þÿ¹|ë§ÿ¶Ù.ß·²‘ÏÓBˆv7“P,jÂé·l…HÇ^†‚–ŒÐãž}–Ž®úW¥DÍXr*tfú JÜñøZN£GK™žLCúhpÀ{¤Q⛞sˆ· êUCÍÁ›ã)¦ uUͯ¤þ¨þ…µ–ÑT7çr½8¿ZXÔ>©Y¢êÍçI•#Ír϶cõa¤qÏÑ¿0hÙCHºÛ¢µ*B½Žòº–­ªÅHn/\¡jŒ©è³R1&KEᰇəNMppñ>O®–£ èõ˜½pRuòçÔ‰s‘ŠöY$ùV5¡#qZ£'Å^ë$Q-~Õ~ø“*äá •ÞŒÅõBåzo>r.…£nòÔ›>­'U ªÆ"Û%ͧ-ZmÎ?d©b®“¯¼q¤'Œ½Ë(ù°ØúQ>Q¥CD_³š®Üh°‘í\¸w}¦u‚ƒL®kñÕ1“_‰µÉ/c˜{OQh);êÿÇÕà–鳂b¨®“0§¥7”ª(¯OàUÓÞT¶ÊÊt’hYþ:šñµ»1ªˆ­‰ËeVOÞSir÷é6™œF—:‘ïÃ9U¼«–§‹ï¨'>2Ç {9µ°+m¦˜Lù!jë …§!Õºù$E• uƒ ¯àÄZ”؜ۦ+Mj×—µkpÊþ¶G¡F€(x²¬®G£› ޹몺Lµ¶oEñr¸‘2ðî~‹*:Qv:’dé®d¸§/k$xÓ­EŠB¼¦»¹#èuz¨Ï´ÅKë<䢡ô¡dcÑÀj o'#»—ãĴƲ…WeWS2¬5áI¿)I¶Ü‚ù‘ûѼ”M×6·Ö?¥pX1¢ð¶F‘ØêL²¥Ä˜+ÑÍíýNÖx`®¿ü¯+çÐþvu{µÝ]S惘lˆœZÑT+p&i(&‚H´ó$?If [N÷BÞ jÓàçI!TŽ Ÿ…"UIñ¹¦‡]úpõê/çáà\¬ÙÓ™VŠ'ìAVjè¡ J«1€õ2\;;-áÔ4 eÆ`ÏFØTâd…DÝçMh:¶¬3—ÛÊt!ªê™/Ó¢<Õošœ VK¨ôHØqÏ¢}‘¹Ò_ÇÊXsÞÝM:“C´Úóàè2üØPqBË^Ã=4e4V­“Ôu“´(ÐpïC¯í†0çAëbþÃ_öûû››ûC´úc´Ú»Ñê/¢uü´úùhÍghÍóÑjg¢5¡Õ­4Ÿ¢ÕŸ ULr­ñ­y­ù ­³üx?Zã(ZåS:>F«:ñ¯ 5õêœôì¡5Ÿ uyûßÿåêúîæfó¹Üšgs«zQï@«¿­º–ÇÜšŸÃ­ù­yˆV;›[_@«ŸƒÖçÜê§¹õu´)Õ:­q€ÖçÜz­ñ"·ú)nݯhÝ~;%ð¡Ðê­öýЭ×+Zw?)Z>nÍ÷£5¿+Zo ­›ëÍÝÝýÇG«ýáКßE Ø—W§ª¬÷ õd•µ|9eüe³»½º}7Zý­´~ n]^•ùËo›Û»_;kw_ƒ)‡Ÿ}b²FV0Q£5õãé1­³@µk@ÝàG°QÖ³ýtùë÷ûašr¦OÈ€ ­¾:Y ]˜‚¡;pš´aÞ«`Z@15ï²g8 Ýjja0Ö9“JUqÆ/³Âúp5ÿhù‡þÞhÅàÏ4ŒAk6Zgqô"Õgë¡§fO’{è îQh ‘DȤօÑè¬ÝÔ’$½2¯K²ÔçlÃÞm©uÖ’Jº u…¼×T uÐÊ/Óàc½`NË)Ñj¦(«å‘˜ œ…C~~럿õÏ¿ÜÜm7|ñ/¬©ñ/Ëp1ͦζõ´öåÿkÊ?ؘÀÔg*«j°|?²‚Có¶£ÿE$G÷“X?ÈI# ý¬¥^äô\Ä»#-È65ËÃí5ú §µM5,’ÎQhuÛE·@þ¨‘Ž"&‚”ç^Ø”½]`N& L×K σ¶mèx7)Ìv<×!ìÒ£‚lvÄ»)Þ þ¥;>qí`Ýňî‹éÅÒ˜ªýT–,÷ æ…Ùë eåÿ©'žå‚iöÐ'€?BŒÇ™ÉZ°„Òª‘I+͈³ áh©–”gOsáÏU¬LÒýS±¿m¶×7÷wãDMs?¡þ¡ãDÏAè8Ñs:NAôe„–|t>‡hö#4Ê[îA´Pd_!”0˜eþp9Ï8Ñs::=LjžƒÐq ¢ç t…huÛ^GèxQÓ,L#Tú4|"óuwµ»×øÛ„híB´¶Ï Úø®DëO‰6žm¼B´ûÆž4g¬Hçxµ¤F ¤ÆÂN”öÄnúc®æ!Ha¬ÄùñÅ1…Ãì¥.[Ò_£GQêì.'g‡@iìP}ÐÒr¶Œ¬\Kç\z1ŸqíX¯ôJý1×êÅ R¤|Ë!JýàÂ] {R…5H— JÍ;þŵvR"œ!@:¥¦1©g\ÉÜÁܼ¤ƒ™·€…RÍs4H;9%ˆ† –™Ù'rÀq-#VÙÃK9Eív‘¿üz·¹ù|”ú›PZåhž‰ÒC*=‰Ò8¥Ñ(µ/ƒÒ£\z¥y&Jó5”Æ·@©½¥¡yÒ¯ÒëI¥›ûSŠ€Áeïùø‰b;DñEÏ…í×>Qþ&EàÇdûDض@=εQÄΤÎòFp\Þ¦ò|EàƒïýPÆ{ÁDq4ŠAW~‹ÒËŽ)‚„q|</½²?ÿõj¿Ûm6¯a/#ôMF˜­þòçaöeŒ°#=¡G0{f„=Ñ çaþ"BÇ)ˆžk„Ù—5Ââëaw+B·ã”¤}†ÐCE«"h"Ô©1ž!ô¹}ð:BŸf³;­½¡R´ƒ¥mU¡:ñQ«Ö’èkŠÖŸ#Ô¡Q]ëò×ÂÌrEhIýF¨=‘´Ðh„úBó‘U›<è „^-ïñ¬ú :ÏZ˜M„úB“Âì¡ B.8Ðl]ºÝ”}p³Ù,ßwxè¢_¢ñ½§m{½ÛÞ^½Éàª+®}ˆÖOçØ°Þ õ-Ï ®@úÜàÊómØip-»Ë#Xá/\3Óç9W¡ïi¦ÿ:6ì*Fƒ4žezzÙ™>§Áõ¤à‡ 9ÒGƒ†Á=!r¦Áeg\›«r¸nv›½¾†GC&ŸëpiÝþ°—BÿhM•Çk ÿÏs¸ÞSSÙ×v¸üë9\kMõÊpÁ$Ûµ¦zÀñݧøm¿»¿ÙïÏÔÇMØSE•ŸÑq £ ÑÚ¬Básˆ>×þLœ„è8…ÑsLØçEÕûõÀŠÑs :NaôÜ¢êhÝfQu£ç@ôyQ¥ºÿ%ˆÖ×_7»›ÍÝÑ9®&ÛwØWG¦d~dû*¿µ}e¯SíËæÀbø.l¼oŽKŠá¥fÂfW8ÞÞînû{l¾˜ ûSà8M{½Œc {½,ü,7Û±aóëâØß;xŽ·ËW•üv{»ßßîŸh/¹ï.Ð&JOhÏ]„¸hŸU =Aé‡-ЦjðV vÀ¶¿þ¾¹Ý]]_ß-øyÇf_ïäkÂö¼nÁËDúÖnA~Ia{œI¿V·à¢Û7/ »‚‹ øÀ‚`¿ ÛÛ÷ [?…ã<†ãü˜8ö¯6_çà˜göÞŽã3 ´ï3&/ÏÄY8ö3q|]8Þ]mïn¾tvÇEìÇ/ñ±}\?3Ì>ŽŸ _jNæŽoWéû†A™?‚ôͯ1(sª:;2Êõež;SúR½.}ã Ê<è8…Ñ Ñ#žî2)c¿Ýoîw÷ßd$ñƒJ†3¤ïG¤ÚY2œ/}ãIûìŽoË +ß]FkOðñçàø2Zû-Fk··õyµ7GÚÀöŠdP%ë›Qúí–Ç$C„¦”òeÉÛÀ/ºö‚dÈîA…¨O·ÌÛÐ=*¢.ü¹¡vð¹?ÆhsüeÉp0–å’®}jèúѱ°ðŽá¢vÑJë%†ö㤡ëï «`|Q5Q.ÿ ã´Å+/I†U{Ï{ö7·wyRá(‹ž„èù“ ¼¼çͪös'ò3Uí6©Ÿ1©°]†ÂìO»Ûû»Ýæe5àg©»ºT{®ªõ¯j ÄÇ0¾œ¡{Ç»õóí÷˜TÈ?"Ž¿Ycâç¨ÎÎ0t·{$ÃýözÿÛÃñI>¶ï„ãüqüC4ؾŽŸKßíu}Ãæv»¹zô °8-}ÿíä÷zh'^­ÎÞõÐN<–¾?êC;˯ ¢6 „mÇ}üÎB^ „ŸÞ@ØÞ­×îãAô«z\ùÓAÔÎè;Yô Cô ðº_!ú†¶Ø7¬ß«ðºÖR°Þ?¨M ð•!Ç0zD€ „cý°Ã·/Cô£ ß‚ÉW!úúðísˆî®&Õ^¿á¥µ?"ÕÚqªµs=®Ë‡ñ¸žK†Ý†ïiÜÜÝŸ˜¤‰c8–P8ŽS8γ¼Úå€plÇpql/àØâ¸pG%à ÒWí¯V¾å ªËB`­ÇIaJ”oN °Þ|'¢p\[Èe?Çq! &Žë¿$Žíçc+ðNK†å'gâ8ã8üÉ$MÍcÕ•ëËqÿ´Û®’aÿã¾Ýë8מÓNøo÷Ê·H†ãTûÙo÷ú¨’Ážµv”][Á¾·pñ¸~a·_!zó-^ž4‰Ôš¯¼<éË>›­:ª¤¹<›{܉ÍôlîîzEéí£\ŸÒ¯Ù ‡súYþúY«ûB?‹€û²ý¬gDš_ Ÿe?R?ë…\?!ºö³v7+DÏ}Ob>¯üãÛLÚc9ú,×Û#=„¨ájLEÙ½¼é›Lž–£Orý‘iÃÝÁc^÷¢ùZ¢gõC}5ѲhÑ™èí@޾èвï§b×¢ôÔK8+¦7'úç}C¢_Òõ»ýq9zf¢?Å¢6}œNô“E_Môö<Ñ?‚èýÝ„èÍÕ»ýãŠéÇ\9+Ñû·HôÏ*¦w ®uâSÞ',ÿ³òþx’ø‹šŸ“êñ¼?ž$þ7åýñ$ñ¿)ï'}SÞOÿ©¼oÇHuœiùÍûã™åÿ†¼?ž$þwäýýf"öþ³¾n1/Ï>Õ¯~Æ—!'8–8Xaüü™ÃÇŽÿÄñ² ޽^¶q¿¹Ýï÷#ÁKmža'v›çµËº™G¡z`Öñ°Ò´î‰?(h‘ò™åé/ šßv–=çÀ¦vN'1nîñ«Œ6 .Æ­C5~ª·YxãròåF­.:‹Kåëâ-ÅÞ6-Y3ÍŽòáŵ:ÈëÁ½U,"ðb}OnÌê»ÄçªÌ攎Õ1TWbÕo«3yU“ú]ê±îí¡d…3ö@8ÅЩ¬ÔödÝ}ôiëÖeO¿ÏØçÔO9=P-÷±öWjÚp—ƒ öZq;ç­?'Œ ‡ðôrÐÁölÿ¾Ùnï¶Û*ºX!ð§¼*ÉŠÐ1 â¨UjU ߊ³Zél ç¯ÆŒ½bÔE«Tÿ<9¸©82òG]ÑàW9VK)¢š>‰õ P÷±FNå“ÒÕ<…¸l»7±åX}WO) 6‘2 È*+±Bn&i2{" ‹WÍönSÑfñFk¡ˆ¥…©hxu*ZSŒ>¹ÌA'È’Þ¼*M<-‰ºiÌSe/+䢚ޭZûҭó‰¸>Üfª©*¶ ÓL¨æˆ@kˆRŠ’RƶV´ÿ¸©‡7w·×›ëF¨³Ð©Þ i™’·«Whw†ªTR•S®¢Lþ€“L›ã“Ìt3D¬ ’Já[·§|¬²‡Ké¦?QT¬œJÌt’{ÙD¢§>›·Ìl¶“†KÕºQú¬|ÖÄ:Wa1âáϺ’JFnx!©¦ÄYt=š}ÉvÊ$æÙõï-ˆ³€«I¨ª¶.º]•’VψÕCP–D7e 0ˆ¾g¢qqññÈKäÔ‚Jwù _tåj9]Ú°´²6H<…¿ ¦e„p’lÅùÖåëlýe{³ÙÜ=FkáÆ­&´FN´"|¢œ,‘Ð*VFNN>:‚ÖZ‹G^GkNMzˆV¾›ÕO 5ž¡5A«?C+¨@¢Bë#!ð ­„À¿þ÷ÿmUcmov· «–}XדõL k’ÑYz/V‡“ÿpµ¦ U–M‰Ùžü{¶—˜¡I+üöJk®"¶>so«˜tLJ¯kªJwÞ¥Î,3ð#.ÖõWŸ6>^j›ª#¸?.^e4ÒPÂú7ìBT±Ø\ü§ºNù­Üyõº1܇ÐA+ªÆòªc\I£ø¿6<’:„€w.Kÿu¨ÁN J+Aˆ` °º ««eC •šê«p‘¦+ÒA›3§¬ö£lÓvä¿Â»‚$ô—è%$+ÄèÀ/Ð1ÞÓz¯mç{ïBY‚“Ú®ø ¿7Ïß<¥_æÿŽèMæÍcÄÇA$y£z­}V¸Óýä € ±`Ù­­„µ+ªCd/¾v¢o]­}ÒŽ÷-jÕY ã%Ul«f¼Ûß^ïn/¹âü\ß,WØ%W\rÅ%W\rÅwÍÿë_þm)+~»¿ÝÜ0ÏY¥­æ’zÄr¶óðN»FO. >ªÔ"®jýºªîìGÔhyv³TxøkUƒ´ÓR4!åžtbÕ§vquÂoqÚkuоîuehý{_¹:¥QΤõØHP¨ŠFõÏ9?ct¿h8Ó‹×5à˜»þ²áRÝݪÕ å2ëäÃia«BÄSïj: MGY·G«¦´ &­>“êª Üä˜w)®æÑd•ÉÚCjg>oœ™^/ÝGò“»ZÈ[MR.ÉõÏAËwš æêˆ× +›Ó¸ ÃBSQÓ,:g7>eÛTùœÔóÞ×U0\5Hw&C]‡.%Ì[•SÁ¸ò;ÛóI•˜t_Ò£äNz[Ë(pѾԬv‚%6¾‡µž½$µ€B ÒÖg”–¼âÇääHö¨b®‡ˆðÈ¡JE…˘¿-‹s^1ÑroéŠýrŒ‡´“vWÍ#Ùõ‚+È„S.¥„©"…jk1• B¶;iĦV®p2êæQZH¬Õ£Eø/›cNª1£H>ZSsy*åf%,î«ÿÐk¸„¤)¥¿V´…Ryýé yÅlUá‹é­á¯2o•}©4$@^ÑyiÒ2£Múb®"4U¡eõEdÐN³ò²j:Ÿ5lUH 'Ú¥Á‘µ ‹B 3£’„Càð”Ùo´EX*É]‹Ýä©èŠn¨Êz,‹IF"y@ád µØAm‰ñ§Tµ¡½ïˆ¶PÝÙ—.—Gv[’¹Â¬€Vl_pV%fª 5 5d³×K°.«£KéP ¢™Ó¼ÆYõ¨ƒéÈžË'@I½Lµu#U.ÖKm=’4tÓd•þBA 7F•ÚUœu}êú˜”i›0Å÷Šˆ®9ÞIir&ÉŠ—’ #½¥†<vŸ»5ŸÅMEHý&…yèö®›`J ‰¦~ʦSùQ¬X£}vÄHß„žFÊ  uªQ‰Nð:ÓCδj›O)Ý„”»À¦ÜïâN`^ùWJu­øºØíRÓ¢h v\•îӲʶx¬K¨šÍUó¬8W'µ¨øU0 ¸ª+ûFã]:æBq[Ìåì+¯1c®­òŒÍƦf6ÛªI¥wí¸5f‹Ð¤'¢YrÖ…Ò3pe°çAgTz» ‹ù4Fçúßå·÷F´x]-êB|týÖ+TÐKŸpR•ïRb  ý€ZÝM„e ‡ÊTÀ ’8ϾÔÿGñ(i(H°~ˆ¦dÍ¢KíÅûAÇ%;Ó îJoÑÆÛ©cˆ›ÍªfÉ„Ü\9È›FC Qæz^–7=^Ñã¾:‚­!{å+B¤nݰc§ò £ᮄ <á$98-gõCT*#¬–¬Žó7¢†ö®¥5ãEÏ\O†¨§'ª«ÐNþ—ˆ™úLôL8Gñ¶MrãABBó­Èf¤Ö XÆ‘Ò9ƒ¸Ú-Í0N¤ø¥¬É–Ñx ”ðÍûTª¡*R e·Ã+¹‹ÇCDàÀ´ó¦xtRU‡Ñâñi°œd‘Y»à•Û’HÖ–Ð&NQª¦&³+B³©UßÂ:xsõLVŽt*/'Δ”(-ÞpC+BHŽÙÜåÂtPW{ݳúú)U]|K¾‚ÐÄ ©¥ý:&6À0vY(³µƒè] 4ñpÙ‘Úô6C:ãTà Ï®™2ä€h²½Û@ޮ˃ýåcš«ÒÎyÍÔ.D_C´ 4È2}ŠNzÎeOo¹®HœÖRBêý &f£R¬ÉRJJ²ÆT°®¢² ÒôW»é·¸—;)l…Чæ‹<ö6o£c(ë‡wÞA~*K¥þEQV«\…fîf†BWŠ~pšÌUÔÆRDb΄ì¡Õ™S¦Ú×Pôï7wW·ûÝÁcÓÓ• |< ›RÊÆ~r&Ÿïx}ªwEÌQŠd¾ü¸Šl01SOöχ÷”{ì‹|«–´–Ö„$³ü'êÞlÕCð¡Þ…††|\®¦œð~lz™„¶_ìz;_¦Î>›ª.9€,‚ÙɇP?þëSÃøÇþŠ Æ±Å1~ÞsŸ|5p| ÆßêMÕ¾ÂX ìð!T£;“ ãz_Ú_vû{ÍHA¡ã7Á·0?ÆöE`|„ŸDóÑïÑzÒî—ýÝ݃f}E°Ú‹‰þ#Xí\ÁúôÝlk¦?'Ѷ­çÐ6ó¯'X¯wõ–‹Û«ý~s¼ß-Xí±QK¾¯AŠ‚5p<‰øuÁZè}Šã8¬½¡'k]¸pìÇ[uÏŸVŒcŒc„ “À§¨]Y–øs¾­Í>óÛÚ| Öh×ö~Q£Ö^¬ùÇ ¼Ó‚uùÉþ¶¶eE…ã¥oö¾Û^ÝnoßYxÙ¥ðŠc’áã4>Fá_³ðªŽÃ?o¯ïw›“8öwXµGpü¬Ú'8>°jg_ŪÍ3¬Úüa­Ú8Çï°jãl«öŽoW¿Áû‘À??ÇñwÇùÂ|lŸÃÇþ6>¾[q|üÛŒßã<†ãüaqüæÖÙ Ý?ä C|K]q?q¼­ÞY&C;Ÿ«+VK;±®8ÝþfºâÕðëseXW|ÿðsß\Õ‹ow{}åq`ÔŽ»¾O$ëxù¯Ït}½1rYõ$”eù¢yèúZc4»¾Ñõˆæ#K­À21õø„iyþ`ý&D—úü/ð* ž°Ô²G×Iô›Í ÑÝ›‡,zé]¯²è{7õ<Ï?ßßÝn®6_ÒeXqüí\ûaÔ@| 5ÇpœQ ¬ ÑR‰ËÅô®@Ôê‘ç#]¶þ¸`)Xý@°:]Ö†h›‚ Þ§`}Q?)Xë`S°Þ¬½>LáÀ¢€§{¿<‹Æ;Y4N°¨?cÑxQ°ÆÁz»BôæHM•/ÖThØë^SÙw®©ò;ÖTw+DÏ™½@ôC–ýö¢/•K?XÙ¿BôîûhÑx¢Eí±ZÔ¥EÓOAt.ñq-Z×þŠÕ^¿¬EsüïÖ¢ön-jlô3-/hÑGæéDOiÑÕ<ÕÂ.×ЯE{¦Eó%-j/iÑ<Ô¢·W+Dï š°¨]Xô‡aÑljþâ·› Ñ›«×}\ úÃ@ôãïßn ¢·ûÍ~¬u)—Þ Ñüýðè?ެ߮ysùšmóè‡ JÕç&têÆïö5Ûö“~Íö?ù¦Þ̾ßÝÜ]_ÿŸÛ,ënÐW‘ÁÜãø}5`ÎÐÔ…'nµ®O;ŵ¯UOQ &oºÚ Þ€mð§ìѬí–6UçHµD_ºË¡ÔòÅ|倨}ïká-•ZÐÌlÀRÖª 'môË ÝÅ…Èdáj1CA™›<S«±lÕ¨¸ÓÔgú£žS\xêr°z õL`µeuÙ\˜– üp ‚ 3-}ÕÁ ØZRX†I–ì¨G>¬*ª›ÁO[—Ây—»FÖKΰóTXB[±s].KÖþ—[Ïuývµ¹¾ÙÞ\àú&¸úW\ó)\íǃëÒÈ¿ÜÝon¯õeÛut²kL)­àm ´XTÒhyo Ú}kV+QçÆ®5;ý×p56=t¥¹ÊÒ÷c’G‡põZôDC!ÒçµL"àÊ•.8æFÃ6ä¯0i½°)d¬ã¤!%¸Ö™u©ak 5ìR‹’Ð;þàÚwz`Q¡Ï«.ÒÁlÕ%eåqipõ†«ö9ÐìZ¹^ˆ[ä@ÔØˆ­r Z#k°<%º$¾Ú¢â˶³g©àêú6 ,AìGŠbÀ„k´¥Àµ.Ïé9\ëõ†¿ï¯îþsë[àš¸~{¸V÷ô·ëëk½óE¸æs¸æ»àªzçMpµóáê_®ñ®1oë}ìêGá ×>öÛá:×›ý{;\ýmpõ§põóájo‡ë¿þ¯ûóÖ¿]Ýî¶»;¦Q,a‡€å8N%[ÛZÞ•õ4Š&¢&‹˜Þ•êè2XBKF©®=>RÍRÐ.ñZ‡ ¦¯@(Cª²+ë_›;3K³IÈ/+O‚5ònR9C0Ù§ô6¼«Ð@`Ê»ò{µfؼ«,¨R®+«¡·vd¦/d:Í*âd“Ê4LW5ÔlRµ!ƒ+¤ ½«²ŽŸÞU¬=ÂþÞ²ÇÞÕÚ¤B›†\žè‚¾­u£8Y›TYÞU-¡è\çN¼«d;  ö_ÿëÿ±-ïj³ßlo«Gø‰Pãh˜sµ…x YŒb}Ô5°p.\Õ“6ä0­\¦Hêè%Ø) Ê ï°Zàîl"/û§ï® [· A¸Ê?6ï·Ø9z¨ J…“Ë×DÒèàz}½ ŽÀyëRÁ1°Zß‹[˜6Õ†°%ÂF‡„#ºÖXQÿ¡Á¤j"g,+ôv£w"”Kª”¨Iµ'|ÚìY¶w)ýåîêfÙÞs·7¾ÓöÆ;¶wÿé—ß¶W·7» OBjå ÁàŸ<&ÅÓ•¨às³|¤LEÔcÛ½\¢<…—‘3^†ÎËÈ/AGöÀI䌗¡ó2rÆËÐy9ãefx9ãe輌œñ23¼Œœ1¡³¯÷yÝÜ\]ßô[íÍ”¯´¿´êI¾&ûUÒžÌ@³lî/Fz)±u{먬$‰¼˜Á¥Ó „B­C0CµºJ[5Ê o»=¤ïÔœ˜èW­¤R°:Ôæ!ã—@ÂqÖŒo•,lýÇÊ/ª`kEji«áÊñô šOž^ÆÊ ØV®–Ct;Á¨´;MåB}WeH•:@ío´ð\¶÷zÝÞ~VíuÝk]ñAûKªŽ^Jtno“ãì[¸«ìw(Co Úåqo¯º"¶ ´ÌÂŽ^†¢o/òø•ЯE#zP’ŒuIuöÚ^[Ã×çý4ñë[¼]²Ñq%j{yNçYøÒjM4 [3£6ª4âr›£ë™Ð1½ÎëôŽš~J=\Õ%Äo¾6çöRh{—–ã/¿Ý?”Áw5æN¨íõÉÎrg¨n}’s]ßÉè%@Òã`{ƒbjæ÷¹½*ëØDâ9 ç< gúXbgJ‡¶éSÕIL#„ö(¯Wܵ¶÷0zæõ<Œ^{½*ž+zaĺž tò'Ñ ;7p«!W49‡š dʸÉÎΦ$µQ…M“óͧíÃöÞÝßn7ûËöþ8ÛkçnïîA•ßo·ww»‹*ÿàªüíE×bQþòûîþöf[ÛëG¤•wîµUZUV÷ÇÒÊG/¿ÎX‘=–V᲎K«2N≴ʖVö8÷®ÒŠ®eD¯­Ñk‡Ò*5Ve| î#iÏ¢×K«©œã0÷Ni¥Çä4¢èUß³„S‰ÒÅ9.­fôJ+ªÏ¥•·´êŸ¤ÕÃöþ¿ÿßÿ¨W"üm»ÝoH½!qUøÅúÂXåä&ÆNµ= ˜µËƒ˜@ŠzÈÖ~(«M3™m!¿‰ú ¡†Žv¯â¾®…)«ß1ÌXŽƒ³äèUìh)m½¾BÍgâ+‘er²µUíf-Ž0“ä&áÚ TûÍØô”]à\ãºjíë^(RËò­ð㪒“J_N£‹ Ð –ݘYc&²Â¢P丂³1´È櫫Ε Qj,k¢ÜûxÕË=‡¯—Sx×4ÅÕ™îÀZ56Ûõxk[©À9©Õ^1-J>œåÕX!l”8Ý×ôÌð*^qy·’äl©Є+qSG¬%í`áB–(© IÕ\2ÜQ}åšóE•k˜m?ù¹ºÚn®7#zäó›þîdG¶#å~g‘Sßg«õTEF Î_ ßñBü¾¾ã…ø}5|Ç ñûjøŽâ÷Õð/Äï«á;^ˆßWÃw¼¿¯†ïx!~_ ßñBü¾¾ã…ø}5|Ç ñûjøŽâ÷Õð/Äï«á;^ßݧ?ÿõîúúöîö¿—øý†ñ›—øýñ{ý¿·wWW›Ý%ÿ0!˜ß&/)ô‹„àí§_~½Ý\ßïnÎJÓÏ«4ãH˜]*ÍK¥yn¥y÷é×߯ï6÷ûíxwŒU˜½7Æ¢eî{blñ½Þc%°ßëæ}ð÷ŘՂ½3Æ9Þcõá÷Ƙ-`oŒ-1úî+jyoŒE=Húæ³Neãscìþ“ýíþfwwµO§RÞrãMòñIÈ7ÉÇ'!7Þ$Ÿ„Üx“||rãMòñIÈ7ÉÇ'!7ÞTÁ= ¹ñ&ùø$䯛äã“o’OBn¼I>> ¹ñ&ùø$䯛äã“Gbnsõéïÿ²Ùïî)áÞ‘Ò¯ñ¾”Fx÷¥43Þ—Ò¯ñ¾”FxóSš= ¯ñ¾”Fx÷¥4Âk¼/¥q5ã})ðïKi"×÷¥4Âk¼C6ÎðïOi›ÍCxÝoö÷¼;åç+ÏÞ˜Ç.åÙ¥<;gœRY§†$þe°?Цæœa…ƒáž ¼Éý'ûõzs{{¿ù°!™5ÓC Ó !o I»„ä%$¿¶c²¹®éâÛíýþ[ÇY^Rß%Î~š8»ýd¿Ýî"í2kv‰³¯gù³ÇÙÝ2Óysu½¿¹ÄÙ%ξ|œå%ŸUœÝ/Žäöz»ÿ¸õÙ%Î~à8ûº1>`œm¯>ýúËöf»¹ù.º1.qv‰³Ÿ!Ÿm7Ÿì×ûÛÍnÿÍ}K>ûxqgÄY\âìq¶}¨Ï6›ëýŹÄÙ%Ÿ=Ž3ûÌ8‹ƒ8Û=ä³Ù¸¹ûòÇùÇ‹3ûƒÄ™]âìç³ý§?ÿu³¹Ýðåe1ŸùгK>»ÄÙûâìúA7ÞÝÞÝn~Ò'h~®8³Kœ}§8»yˆ³ëí~¿¹Ôg?Lœù%Ÿýpqvû)þz}³Ý 'BãgÝøG‹³å‘ÐÛû«ûË<È—Š3!Îüg?iœÝ²_o÷7»›ÏŸ‰Kœ]òÙ%ÎŽ¿‹«çAn?¬ßøÑâ,/qv‰³7ÇÙæ“ývµ¿Úïï?TœÙdzK>»ÄÙÛãlûéÏ¿\ßo¯oߨý…8Ë?t>»ÄÙ+Îò›ÄÙ2r}³¿¿Ú}¨|v‰³sã,/qöáóÙò%ŒöËõ~{… bÆ÷´k½ky]ûõ€}ŸÁPßræ)°QAZ¢ºb%APízjù“H鯙¯0#9iÑXKd‰"âm¹¸Qàõí(\z?ÔÖ2úŒ©H¤Þ/Tk銷óo½†V{Ȫ DG,N(¨Þ&m VjÑtóËm§â­î¡–æáBG-ðrÔeky;Þà9É*X6f‚Sìq4¶ ÖÒRë´)‹Ó²v|Ï:…ök¹„€et—Ëÿ²àQ‡æ®–«¿Ô±ƒw¼hó+ÒHqAà¢ç̹7Y¡©Í¬« Ò@}o[} °³ôÄ“2Œ\耢M˜ºþËw‡)Òà’e ëõÖˆR¬º–½n¤Þ¿ÆŸT3î™ý©ÍÊúò³ §í§øË~»ÙßÜ\ÂéMá´¼ºê œâN—pÚ~Ú}ú‡¿Üí¯–÷£~ôpòóÂÉ.át §¯NöJ8]?š•zg8Å%œ~ŠpòÏ'G8ù[Ã)¾[8Ý|úå÷ûûëýõÇ{—púÞátÉN¯‰½ÛOÿðÛþîæþêöÇӥvú¹Ã)?p8%ð3 N<Ï‚ý8~ñ;æî>Ù¯w··WûobÿÙ%æ.1÷GLaoйûO¿üº¹¿½ÛÜ]òÜ%æ.1÷-bnsõÉ~ÛÜí¶Ûϱ>.A÷ÕƒîQÔÕW= »³ãn=A4¼/îqô¾¸Æ:¼+îF-â;ãnèµïg–k›ú6úÝöæöêR9¤>T³K;OÛOöËþþöþO‡ñä—xºèÂwÅÓ2A¸½»ßì.’ï’Ÿ¾b<-«ö3Äßp´¿Ûí/ñt‰§K~zk<ÕeÔÆÍºþô˯÷7w››‹ä{cHÙ%¤.!õ,EÝ~úëõíÍþÒ@þò Ê.Ñô³ES5‡wW·›‹à»¾â)/ñtV<-¯œÙmîï¶šýO—üô¥â)¾RmÂi}¿×\¿T+LTT|EV‘c¬lý9ô~ŽLõ¬qá:í²’Vûáµ:µŽ‘)_¤~V±¸ì]²Ì¡Û’Éâr\M},¿³ÜC­ ¢Èê>hÔ-!\µçœéçª|/ÿ;êb²@˜ú¤–=a YæJø¸.sùüX£ˆŸdá@\¿V?«k¨åXžÒ®,OÜ/·³ÜC1 Ι VHÅòŒx=e^Ëfõ³± j¹%¡ÜX-ÊØ¾Ô= ÏÉBDMÊ€•äéõ£:n]¯)*Ò V—ˇ.{Y:Ί]½?SkÅá–‹y,M±g²` O$kWwX›åzÜž£-7f<+2´eʶµ"°òÔŠTŠŒ85ÄJlYmÍhŸCF,W¤nÐØ…“g‘ÝB›^—tð¦Šý'ûÛÕþvw]¶Cg ¯gî+3:e­Eº¨ÆYUîÊ€<¤³ Ø¡¸Ú¡„s¥3¶3j$]ΘE6"«“ÓŽ¿µb¤ÎẄ>Œ¤$ yâ­£® dg½µbÁ¼¶¢§•ŽŠ™ú×:#— 4Êu ½µ†ä™rg"'|ꢓf­B-騋«M²¶I«ó)q©|P¿¥ô0vˆt ±uš»V¶®´ó/ bU‡](Œ#“j›ë ¿C¼§, J· ™Œ„Ùù¨HgYmpWÙÁYÞ³ßZ1ºâòN(/¼µ¿ˆæu&\É„D]bCÖ6e«–"\ÅDz›#Ð~øz˜ëOö§íÝfs·;;èòt— »Ý»‚î_þíßÿîOÿ©Þsu{u5ÈÕ* ´Ò®(ª•%*Ø(DÍ"ãuS!…TqТ¸nBb뺉ƒÁQ $5ºj¡‚5Q¹`*Æ\‡¤ƒj¤£MÁ\¿ª«ÂJJ«d¢ ¤R,"yêÓ*µê«R–]p-sÙÓµ»ÍÕñï¥k$öënÁY•k…呦iýZ¹ŠØ^ Š bbÔ깊 ¢'ôbÓ»¼¬«¨C (LØŽµrÓ½£¢…úíàÃõ«®G€;û #y-?ð¹çΙ¡8Ö6$#¹ÉZ4³YSrÓF­¼ÜR ‘F“¸¨œ]Mê%VÎ{jî¶vbÔiTF±1“ε–}ÛÞ…m¸öbÔêw¡VÛ¦¡ÇyI¦4øûþ—c ¶›ß³.|Jjc½ÉAAír %¼¦X‘øzç½½0w(¼9\ˆ5£sý±©êØrÈÃÄ}k`è‚ XŽ×ºß:ž+¼üÚ—Ú$0À?ªÒ ïP%ëµÜs¨&ÔI3zK¦÷Jž÷EÝ?ˆX‡8á—ʃèu ºlÍÙŸeŸ±Vs# š>­XÈfR…¡Ø:½šp•²P=½XŸž\â¹ÅˆÖ¦KæsC!0d<¸ÍÀ@·˜~¯,ˆæÔÝ*x!õ”ì÷QWÂiÖQNlC§I»cp¹çCZÇc©_%ÚÄ ¬5TWÿ…Ï(sõß&LG¹±1à§ &èÁ‡Q6êËkôB¹l·½ºÙì<'óM<ãÌÌs4ñŒ33ÏÑÄ3ÎÌ`MÀ™’üû‡°ÔºÚûýPW>ã©.©Î®¶S„áH¨ßYƒÙtéØ.lhïªóRy¶þ‡FŸÓÁP¢ì†8hÜ«."Ú•þÛöúúf{;ílR¹[¤ Äôr%xW«[¬[ÝÙö©o!‹f7äE‰§‚„K‡,‹8Ú`åסãNÅŸ1õR]SY½„o$í±Of´°a`.BYOYi”Ô ¤5x0Õ`’C³syCÇNµÈóR¡ z¥dŽêOqƒ$k—δά*ò©ôGf' …—”jE4— ²^$‰aŠè‚¼Ë ÏøÓí]üîn¦d¼mIètÎìjy»îdÊ©‡ÒÛ;& ¡r+Yg+ËÖ÷R4ºSݤªº~­çšµIö³T~” íJ$-¡E•3Ja·à1C+äꦪ? ½ rT#A%A@Ó÷d4Ð)µ`V¼/å—ÀŽL&CÚ©C«3P¤—€„ ÓPFÆÌáÝÕê}ÎUuú ^‚5 çYkÔ/iÖ\tRê5q0A_Gå7ƒ¬"Á¢Èb•dÊÎY+”N¤õï’ì@0w«ÃhŒÄ‚AÀI‹'%§ ëÊfµ}Hà‡„ƒëR§«ÚÂÛ}úû¿ìî¯ö×wƒL¥foýj'F×$OCHqœÃЧHqœÃЧHqœÃЧHqœÃЧHQvìˬxŠÇ9¬xŠÇ9¬xŠÇ9¬xŠÇ9¬xŠÇ9¬xŠÇ«¬X¿|œÇ9¬xŠÇ9¬xŠÇ9¬x”—i”sXñ).¿1³¢eÅS¤8ÎaÅǤ“‡ÁЧHqœÃЧHqœÃНâv)Gÿü×Ûív·Û1FI-C%yq]2Yþ@º;SQCnL5€F¬¦Âœ’ONWÍ.%D€±Xo=a´ª ÒÅ=y†Éƒu`-êùE¨qÌ€ZOEª´úF*â«ÀWq]ÕK•) #•”—-¨€žó„ÞE%£Sd…¥LÑ´Y9 T>&t…¯ §¸#”!éÑš³—o!¼ÙÞÜïäl@kŸáiζÎÙ|ƒ”DsœÎÙö,g/÷÷jÎF¿¾š³Ã¿eÎŽoŸ³¡o³ãÇÎÙ~hŽž¦¯¼üÖƒ„ìÝÐF÷p êˆbW›ë¦x@ Zûs}: Q³O­°³¾Lžkà†˜(ÀûÓÉêï+ó-O–n¯¯¶|—s3_\˜ïÂ|æûØÌæ{/óí÷‹æûý¿}²?ýý_¯6WÿïnóÄ® LÚ<ۮɶk4|Z‰ÙbQ§ºmµk ;¶ô.2”aÚç>ÖÊ9è)3O‡$wÂÇÙ5Úö,ñê;é©0¹jƪVÊ´ èÃncðkêæUuIÌ\×ܪ‚À£²¶kªQÉ­È®a>yÆA °‘ lÖ²kІ¥üå˜i7M˜½ïú¿]}§ ývŠ(âTä)´—Õf¬?N¹1?c¬<$^f5gyÌzF'LÑ55µ¬!þ…}8´kj=©¤ Øj‰ñƒjPv V«Nbµc®5ßOê„áÇ`«zÝ• BÕ`‹ÎźŸìâ­Ê¿å™@“!QN¹Î §É™4ÑK±Mˆ:†e/M›KìWd—Xs/ }ï]Œs±1(…¾«à$Ùä `æ½ØÓdcyCÂìy¢Âg!dÆÏ¾SP0u-[•C2˜"´*Wsƒ µ4˜wˆ›Gʶk « Ç®ÁG4eÉJkDœXJ—–ãj×8v a«ûnŒ»H1¹~f¢“épa»È@Nw¢0ˆÆ:G=²k”¼+ÙÚ¡]#"J…¾%1F¨u2Gµb±±ÍûŽex["ˆ¹ ~Û{^ÂZß2œ\¿$©Ë“·¡fvëR"ÝQEvÈÈ%r\–6=WI'EEâó3œæé;cå²ycE!¡N³·8&fÿ,¦§'PMZ°PΈæWòè¼Z,ËÊ#6¢]tá70c–?Ô ùƒ‡)ú7¤DbŸÐócÖUˆ~éTÇ(¬l·ý1Ø._b;»°Ý»Ø..l÷#±]\ØîsÙn÷É~Ûoîo¯7ší˜Þ¼h»‹¶ûyÙî¢í>‹íþº²½ÚÜoêÍÒuµ8ËI4iCåš$ÞM>XXåãR“—ñ¡½M™[œ Át³Óe­Â|DÛ%¦Aepe('~,ÜÞ± »¥¤gXCÞa|¾ÚM.kIþ`Œn}bnãù´¬Ý6Úò@9›Òúá.'h.êî–ט^ï¯îîîÇä‰2:ŠYqiˆ‘ 7K žF9Ö1¸Ǻ㗬]b›y»u!_…Í!_v#Dµ” œ´qË)ÓÏ? žjgt€‘É ‚“2ÕïPk?ß:²ýœ-“C#ïOF±rDNƒü Mùð^Þ]j¤¼õQ¡’){’´ž ÒêáaµÛ‚¡$ÁÔÿêÌ%)B¸ð~æ dƒ¨™¥Ú@r=¶53õ•ÊöE” ñ¾<8\Ê èéùn`‰8áÙv½Ô·T[Ü‹ÓT+‡d°~{€…´6­ó:‡ ¿ªß£s¦ƒ®Â’VT/ lþð©=LO t®vBÒ×ÈÒ#ëÑñµœÂ›µI ²#ü¹H–÷µ;™l’òxm uÁD|YÝzl‹$êdK™¶2ÐZ²ƒÔÀ‹…આðÖ`ìç¬íåÝ¥& ±r„bí ë§>‡ó¤ºYæ~x+HЫua“b¡ªZ‚JxEoµ.¿ßÝADuÌDj!¹‘ÁͱNÚ1žÇÐÚê …~GaV/)*êÑ &àÊ\»ÝÕ F£:ŠÅæ&+ft銇<@Zkò.V†‹dÁ,xb!®ŠËµ>ú®*±(žµ+´j)n·T6.5æ3\›&To© ôÆm:ÆÐû`6e°•³&KúEHµÄ–WÕm%«;!AñçÍg.˜“ÒM³ªC²Z0ÓƒÆ3-}gD+´7ªÓ¤ªè©(¦H"˜ÍU«pÁlMer/©O [¹Mr]d]çÛœXŒ. ©ëMÛb…*áûØ*— ò®W2ae¤°G",#ÙUDZ%6Ëûd“!¢Y¥¼œ`ÌE ت|ÌZ³V)ð¶#fÖô××Fk[µI1 ÄYkć;WtiÕ­ZI[íí ˜R ‰ÎÅŠõw#dq µ¡D[aï,?&‘r ónJç-_ ¿½æB52`s~¡e—uc¥lÖF0diá”R«ÕÒ75ü^ð¤ð4¬žeO†æY\”(I‹n¦¬®uC£s¨†kR­ëÙß§„ d­ÙÎÇ  Ê¾ëjçzNm¬kIPu=«päMl\ZdÓ[¢¢˜ÑöB_l²dÞg Ù.½ºì!Q•ÿ VyøÁtÅZ¬UˆgOì Ò³çc*ÃÉ©*Ç(“ÉL÷0ÜÁNc¶bÝÔ®ñzý…ê)·¥‡ê­Š¹ZUš|#E¶¦íâ¾{¡P*%Œ)†·I^µÛ:ɱNp1îÐ>¢«K®!ë*dG¹ EWµär€ð‡Ô–ž#2åCÖC¢¤ ÍyèáB›‹­PAk»f„ÞA)™\—TC&‰Í~Àv­¸n³ÁBEÒ]§ïŸÙ­{•ë J-˜ã8ýÿž]`SÎ4aDÔAT$Rì ê6ÛeüB5Áí ä†Öàr«!PòÛšO)Œ’ž4¿__Ħ+ï¹Ñ{j:Ã&±$öI¨lãÑk~%åpZÏuôt_‹&•Ú%§bÔ†XŸÂU–§¢ƒ87©f+x×ë®-»bâ>y.¬v¶‡†‹ÈàX]jÊ)ÚlkªªO¼Ý ¿úòËlSgkÆ[Å͘ה¯(Ô( —ní’¥r‰»2^Ή$Nr×hSr5IÈ‹ëØÈH9Dld-Ã$ØC/M3÷ÉÒaíàN•tèq£PǪ±¶€aÑ®{ÿ¨–!WlgMÖÊ€`dØÀ/r¨Œ“ ¹ØoNaòt!ö&s\¨:äèÙP£Ày`¹®TÇtYT›V‘·ÎÇä’¶ÿ¯%gïçPkv®S`Nrf­í-SŠNÚ"‘T-$.{>gF’ŒEÌ*£do÷RI[ƒRÊL¥ ` L¸5iË–Òd—&myvéšòöêÛõ d—‘ ¶ι… ˆõ€çú¾/›Y(Rȇ±Vç””b².jjuVL݃ƒ¡V\­ŠöQT¿<¥…!Mª^! +Eº8Ü:ic«.ÿ2'Ít)bT౬_îÖÛ¤p©lÔD.Kå­ù@ßrþ( ب,ßÑ®yx“©íæò5Èëú=ï|‰÷É$TåÅ"ÊA0wtgG•~jO.•[d¹&dÞæ¸Ö2ÏU¿ NȾHÈÂÿÐ=ª\“ë&qÐkƒ}ÜÆÜ§Ì‰—˜a"#3†dŒïÇÞP5æ°–ÐÖÂ)O¾jA@‹ÇÌçò—z‹sˆT{‡£¹œÒacÀÚ+ •8ë9`,ä¶,õ7ŸÙHiÄ´øL‡Š×xñ@í>Tv ]%„¢J=F¥(†é[ÀiíPêN]^oÊìHF÷­ù}ký*½æœÃ™””î:uÍgi\3®‹ å5ùl¡M´•t§¹Ôö¼Òa¹\¶z'\Œ²Y¶ŽB9dóÔ*zHã#:f6cÒ91õ’ZE[Fk°ž¢µº\ÂfÆ3ZA-?ÓšÃ!M+‘}c†"”ˆOuU€u¼z‘½uu@cKajbN)/ªhGU‰Í”6ÛQmþ·*Cœ÷ÖÑq~4ë>gJ4H¢Õ§4uE•’“D?ØnÉ­žM³¶Ñ,¦Ë¹œ¡‡ÔuZf°'îX³úò6÷››«ëÝÕ%¯_òú%¯ܼ/äuûióº}Á¼ž—¼~É넼¾¯‡Ùß¶7ûÛ»«ÑViÅý­Ôö@–뚥Z:´˜¢^”Ç0ƒk BmM(©é=AÑŠêoÑèÉT/û`HË5×ÖŠÂRÃ_t|—SÏnD+/§‡Lî¹õ¨”ñÉTƒ¬¿b>:ID³e¨æ(MLßâÎ}¥KÏú!êfÕ¢-{¯{U<;FŸ’–¨ÅÚ`ÒõwG¿;†Ý÷óÑÚ¦-©Á2[—ZyC½@·¿/PwN ¯ßt_×UÈìQ3¯Y Ëž(IÚAêѳV‚˜ƒìúˆ:ïbágË[½Øy†nÙZ-…úZÓöZi_²p€¬³šŸ@¨&fe  /j¶ F‚æ 'þRG ~A__‹D°ƒ§£NCžj7£Ä7RrA‰.ª¶T¦®DgÞ>}Sá þ*ì7À{Ÿ¸*¤î=”CXy%zꈮ½_‘^†¯I uÊ­qôuósü„¾‡ë#ˆ’g¥©KÙ MM$л¢A?'7¸"Mìê':£qHfBš‚è žåçÃÔ0¨+…šèqq¢tììù“,ŒYgô@Cö~U_€1èX´{>TMõº®0Ô=nºd!Ôûî¦Ñ`ûþ0±ß7,c¼2—à–Ô÷mªóžH§£ƒ:¥ç¯!¹èA&âÊÐIÞá€7ÍÍwçœ~ã0½Éú˜÷'Yd}ØBð§³Oš ¶jžÐ4t³­ñàêÏW^ÖÊÇòî²Ð?éc¡„cªR¼¹Pü#`Ÿ h¡ŠZµ‡îßQ®ûÏõ ¿¯óu1¢ûø¾6¡YˆÞdr&Ñ;¬5ÐPÍáEë+†®$ z‚ÇêK‰:éýŸ&'• ««‡Lf./…Ë%]y}­)¢R9:å ¢L —êÖ$œþðk¿ÏÐ3ûýá?Løeg€Jy¤¯ø½.ú#ARèÜœù»@Ʀ²t×´cþü{ª–ô¹&ÔJÊ¥ùï³núØÊÔÚ™ž¢kýØ‚&;jų-Óí@111®J­®Ž« G¯ #×’mn³š5q{›*”4=;‰¡¢tù_ž¢ë:PvDŸõâvE©IßNß51îšUw¦ï,âÞ«  }*ÝžUïŒqX‡·§_ÿ¨R"\’ˆãúE8[/“õöG-T­¥l¥ì4—.–èW„â]¿ÈGb¢P³Ê¶ÞêúÈDÓÊý _Óô]©ª[²ÅN2ïïs;zàw:XÃÛi‡1ú†{m¸½2~矽5õž€ü´`êi¤èÿýo ò÷»»íæzÈgÆS0-PÖ¡­µn—oWßGë}çªÎzØPÒY W‰¹Æ"Žƒ Ò„YQ…öúyѥς–1},]gª‘jìål‹C…)G3¹`—J]§`ET >½ÇÊ;Sø‘$Å&|M½¢©Ê(È;ÑŸGâOHVø,N¥Æ z²hÆ’ÊÏ©@-&ÈÉM)]/‰°.O4E6s«² %Éê5d0T¯Ç.o7CJecëˆeP‹ÐE)ÇÕ¯;5iAð VΔ¦ÐŸÉ+}ÎVæz ü7+’tsµ8ZÑ¦Ìæé t±Ñ’­ìµðWØ{I¼ÖjC#ˆc©¥Å-!1ä“"\)m1.’µ€RiÕWK5£ 4ÉGí¸\4T¿A`‚•†Ñˆ¬{^c°3n3Úªup5è0h@;5RK®ìÛ“fgñØ­®‹´ ÅCpÑ…)å·8T=ƒD$©Öô%Æívu„9ÍcE”zÿÊ~é‰1m¬[%#‹@é ¤“¾ êÑK=•LzÛ!òWö¬µ¾znýѼ×÷M‰¢KI•YÉ—Ík¬Ãó “v¥1õ5¿0¿ò}iÐÊÏV_ñlõÕýÕýÝíú@h0Øž¨yY£ˆû𮞜±eee5«8±œ- PõKd«PIAøì÷|IF†D…"YcÏͪ$»*PùãiÉVA4!£SçœB_(¬í zñÎo©ÃS]šf;?ppE§TðÝ” å&u,,»Y¥$ÎÓÎPöh ×VÍ9(dÚE“+®kï×fU[¸®ø8çÞ¸þIÍ;›m~•ÊáJ ¦4"ÎÆW’OV|¹ˆþBz¯¬,GæåmÐÒ×vWs"8³¤ªgOŒäš‰f£iîòäYmLõ컑$tÁ;º¢•ÅåO‹€¾¨µ«PÌÅ"æ vSVå¬Íª™I%\Ô‘)VÓÌ«»*yÏ ÐÚo¿•Aƒ¶/Úà6kv ²Mà‚F½É¢DûáoÐÑñ¼sq È”$IŽˆ$Q/·]}ù]˜r0§Ü}¡yíàÝí|í:‰µó:©€1½WW=R™‚s“´…Ѳ@ÉiÖu³Š–¤¬:计ŠÖ99ûU»kˆlw½»¾á­jõSû܂ɄÚÈB±XA?ã¨A„UÎA×á·Î: JÚÏB¨-!zþųík½ó €É$Pÿ‹P– öÔ×åp%&Qk‚in©øZÌ31’£e=4“>39YÄy`*zøªN¶\¼‚ZS+Œ¡1ôÁg²·Jw⤘¤Læ ‘ÚQ™U”^èV.žªNh™3Íö®Ì @F£€ÃuF,¤BŠ(‰,¡YJU¥:K|ì%PE§uôZo©Æí4÷§`"’Š‹\#E|,5#ZÙ/$B-][ðxþcJdë'\K”hïc¹‚ Iððå3€¨ €-8ò‰šKÖ5r–YNuoŒÉ3C¡ÞãjxJŽ3{=ñŠ~­·‹Êƒù./®w[ŠFj±EIí°V‹BŠÂTÖ1šfY0åýRgÖtÊÇ¡~zÔÆ­ÖH¯|èÐá”Eõ­pRžd_pHÑÚòJÎ`,@‚¢˜Žríò±e”÷Ÿ—¯‹¹•kXÅ\-6×,g¶fVjõ®Mªæž‰¥Zÿêi¸ä÷,@] «#t×hz¥>Œü+-{Æ´`MÓ™”k|ÃdëçyEZï<î=ߪB>œr(¿kÝ`>XU2)‚uš ‹jüX^¥OÂíúE•°Ù·˜k ›žUÄR±Z ÙÙLpòæ+Rò”,å³rÎYª‡Y%29KÙçáàÍ¥Œ9r@HPª©ûÙöwÁ’vJ[4ÐzêÏa*†R®'á³£\E*†ÔÚïD Í5A?UiÑ2º˜ }®T²dةߺ.u J6²ØÒmºH+“+©K¼¦f¤rA–¬w`ã`Ñê‚£K3- Xƒ3˜fÖm;™TcóéT \Z)¿É™T lx(ÂCC[Š™ÝfÙ&> ‡œ¼±R^‰!“¢- =PƒÖd{¥µl•ûœÖâBkZ»ÐÚEk×´¶_^=»¹ÐÚ…ÖÞNk˜ôZû"´–ZûB´vó@k»Ín·Û^híg¡µ¸¨µIk_G­åÏFkQïþøåÕ6»ûÁèBM¥dG6'æ7`æ=uQs€ÐÚ²ÙËÊè¹x/›Ðj'tÁ¦‡têr*ÐDhä,‘Œ÷B5¡…šð⬽·Þ¿îëi–©Ñ«®o‘RÖJi^¶bÔhŠ–¡§ðɆÅ)ŠE£  l©#Ób‰¹ÑîSTáÞÀ®M PÑêt²…ÚH"4ºdj~ë"hbù%K€‘q²!>É-uu®.Üïóå¼ÐÛ›jdžÂ*HOõzyn>g¸ÉŸYãÁà/iËMT¦¯ )’¬ÈâÐì=Í&9qpÎ*dÔ+Ã`ÔJ™­nÁšÐzÚ…©Õ&†Nø²i³AF¨tØTÓ·`g*ãúõœ„æëÄH-UØrtó+h«Ðà¨Cµ³õîŠ9,¡?¿×¤›‚ý_¸šéhBó& ¡.©G¼\»šÝ5ªîmt;½~¨ñ-Ýú­5}rÓЌ‹6jºc×mT!DhÄe-¯>É»†*²ùöSë¡siXÍ.…üÿí½É’$IŽ´9gy’ÿèûrD¡*Ñ”]Yó÷ü¨™¬¾8ÑÐÐ<À¼ÿaBñ1DÕ_,–¬ÈõNªÎŒp3S˜ ˆÚ _·/ÿëþæîöñ#àÒ5¯Nº/–ÐÏWnÀËNÁË6àå'àeÇàE¢×%^ÆXj¬Àæ¼ì¼–õý ð*®Ñ=‡ŽjnTàå'àe¯W4xå›à[𠎼|^~^ÞàåÖ¯€—€@½‚WLðbÁð²ð²sàã"°ÎW¾^öQð²yJô-ðŠ‚W¼ ^-òÏ€Wø/ébþë#à•gÀ+¿¼¤tzÈ/ŠBâ ð²ð²3à«Öîs_^v^Î둨6@)°»«ÄvÛA웃ØFí öY ¶U`÷ËØþãõý½Îy Ž.E£±…£KÑhláèR4[8ºÆŽ.E£±…£KÑhláèR4[8ºÆŽ.E£±…£KÑhláèR4[8ºÆŽ.E£±…£KÑhláèR4[8ºÆŽ.E£±…£KÑhláèãhô·ÅÎúÛ/w×ÏÏ÷ËäZF “7¦Å±vßS^·vÜÉØßM™j{¸ÆÚ” 'u¬\î{Á>¬ÄP@Kbøq<ƒÿ—Þ[rcK02V†ïåàîøó*.9t©Hд ·èò…4¯´Þw(­dœ ÊÊ7/šÂ$µîÖA²iòѵ¬ÙðÓ•BöÂWiáúµ!T5ÍCŽ„[ƒ¢`¯›"Šde¿aÜ µ`ôªM³>÷´(ƒ§ð&dŸe…÷¿» çz¹ãqÜT`¹ˆzÄMh«h‰á”¡ÛY>‚Ãõ@=â–“uÁÁî<äúÕâé¤FG[-[¥ÎF9ΆpqýƬ¬?‡l.(#$ÈÅé¬GMFc8ES£2,XÚÊÌÔ¦º(’7>q»|dâST?¦oôl „OAJ¸‹’#P¦p°VÕV”EœSà_ðß+Y0)kñëë3”ˆJÈä)¹nêö`¿ó˜Q¢˜3¤“zªiä!ó©ÁÙ¤ˆ¼¨wð:uª4¦õa }æ \·/¿zxÖמdÖfŠUwwh%ˆ°69ÒïÛ¸6Þ¶7pm¼ loàÚxØÞÀµñ.°½kã]`{×&æ½ loàÚxØÞÀµñ.°½kã]`{ׯ»Àö®wí \ïÛ¸6Þ¶7pm¼ loàÚxØÞÀµ1mE6ŸÈVG_¶A79úñ6Ö²¢6€ŠUˆbÛH (©!tS‚ÞŒC–ŒÆ³ªCYem11ƒ°âÜý‹ÿÏå€ÒÝý¥Hš¼Štöa¤‹?éì«!ÿ Î>Žtþ5‘ξ Òù‡‘.¿.Ò%5W#]^Žt:E[Ø2‘Îéú³ é|vk¤‹³HÇzL¤óC¤3£œQá{1Ò©Ṳ̈#F]S‡H×™xé–`Ð]³ÜJ B:` ‘.®.àéÒrŸˆ‰tÆÐ'^¼£¶=ªvŸçÀÿÊ1ð»‡Ç«G=Ï‚ïFdœfjml;M[¡ÒÃqøðõ5é³_àü¦‚ºÌ#|Š#Ù¿´iS=ä ÒñùÊÞlrã*ëØ~ôD…“jõz<­hôé(!=ê’¨é0IšNûÃÂPhÚŠtË«G3R]J„†¿¢í„—qdÖWÌœ G©prÈIÓd[ð.¤«Ç‘4ÓI ¥o®Û« J<’-„tÂEÇp¡6hgŠVvj=Åm ›ÅS­ìúη®ûÅâtHž¼ª{TG¡Y_ñnõ4ŸæÇºw«iŽçñô%ì4H­P¯4—£Õ 'a9ôjwöÌub:(éŠáY¢²ŒmÔ/=‹…ñ •ÈóK|Êâ䱺2™B·–ÑÖ‹RÞóÖBã{3#5·93t'B(ïëUœ1´ßü /qáBh°S„ˆt.-WX'á‚6©A§’p@O …7EçÍQ=1åóÖê²û@°Ž-¥qhçõ+Çî_~¸z|ØQlG±/G1ÅvûƒQÌ—ÆÀ?üåêêöúæV_rW º"˜Ѩïž*BŒ›2ž•®U„hël]IL·N­Bµ>MÃÿ*ž(?½‘G•p–]~f—å%T‘ÄøÓíÜ x|gQH´WÍ ÐÁ9¿O¥]¡íhoukë®5oŒ?Oµz:¿_wäêÖ)I¹™Zæ÷û·åVR5—Hló_åÙ«ÖÈ~fU[©‚±.2ºáE.†.¤À–"å–54©½Ù#!t—¨ÄjÅ–S¶h~¿žD¤–^²èµùË;Óå¤!Éâ׳1Ôóè§ó,´þ º´’…T…kÛùýòÚÐV=¢*QF;ßÃÌïCÁšßWÉ2J¢×BU«©÷½,óûêb*ÈûŠ1k›ò =Ñ)(ÛÜ$Yˆ К˦$N]]]ºÏù}jJ•×–Ý2ÓRzC•ŸT} !J‘JÝ:‘]{†wqͽ2¿/©î»ÚÊ:BÝÞŒÞ3X@©_íU­…ÛÚÞ켫Mb3p7Š@£ç÷}ÞFÏï§^ÙÔ]87Îîg7ׯÀ™}6œÅ g~œå œÙ)œi ÿ[Á™‡³ør8óogöåp‚3û8œÅûp§p_ Îü8‹7á,/†3ÿ‰à,¿w8{~±]Ý=Üt•¹£ÙŽf;šíhö}¡ÙyøúK= lijÞÞÝ´IVkH ÙˆÑe«èñvC…’Ÿœ«kŽÿ‘‚¡rØT½0T¦ #ëç´zb’ l¢‡ nà²6ÉdØ(¢GøyÂdö4™R(âÖÝ hÈ€ÛÁ¾ƒÅ©F ¡$#…z¿«Jà:“û4 ˆ:*t´äÒ¥¨ÄÕ Z›šùQä€,S´I&2 ÃMMÍ2ŒÊç1 >˜˜'MÍj¯a5•qcú^K +ÏÚÎPÇ×»cFû“ YÐqhÀ¬–»ú~5Id˜fåjß1T—o {Ǫõår…XJž§[‰WÀ²,ÛƒÁDÝÑ$)ÍÔ³éÂ~Sê*êS¹vY×r™Ü¿Þâ †ZEpøsåã9ÏiÕ…€˜‚®m³CW¡¸»¿Æ2å`ÕÐù“‡WŸƲ¹ó£®ß»£m&_*ð´à6²îš÷U³rDÛp–®ÉY Ó|BET¤^©éE)Ÿ±ˆ5ŽÁŒ‡A®(ú£·Ê€¶êKòÚäú¢,7Ÿ2o›·âÏ­E’•˵EŒ10Â[VÀJ¹²ek8|Pú ”no×FæŽn?5ºÅŽn;ºý(è¶<®ìæññáþvG·ÝvíöõÑmûÏ@7û6è_ Ýì;F·ÿX†Ðþuýp}u»o$“ÆúÇÖVªƒ±æ’²,ÄJ!.1yëðܱ £!´ qÁu3Q–+ŒkümÚ™@N{79¡¤lÝNT|‰£³.œûãÆë ¶ëÜ0¸¡€ù5A´‡Z1Š J eŒŸäaâ¡w¬&R)óy¹‰åI9 Ô11–‘{©?,t![W„ƒÃ›ØØ<ÜÂ;Rõvu£ ÀM ¦LvÆZ6¹N_}s1íÃë=¸…'é°Î&_!µlU­_u*\ÈĤ©UÿGÁqµU8ïÁI(Ú )¬×‚YÓY…!›1ƒ¢Hž.ƒ®¤þ¦‚H“–ÙÔ•Ñ=:(údÒÎe¦7[²Êp¿è(|^ lÅAÅ4 ÅÚkÞµÀas!é¶Ôû°è*XæYÏÒæî-# ²2…ÑOâCè½êP A¨j.‘“–‘T÷½U`"©“Ú¤W¤vqðfÖó­M¸Ú>سfî5(²RC¬X¤ÉX]± ¿„`-¹â‚­cA¸ñtZ³`g§Î,X‚ à`㎊ýXAç ÉPS3¢o+AX8ÖuÖ±Hk8솦y³Ê™¬Wº8Õc= é`Âj£ûf’=€ACj!H…¥ýæ|¸‰ÙhgF' ”£Ö±|^kð鞉zõÞr^j bkË8–Il{…7V‰v”Ò®ÚOR]¡Jõ¡\œçAIWŒiËL<€þ éPýR€÷`)«yÝ­Æhr2µ‡!§$Ô ‰—[¾yùíæêùæþK ;Þ'l? lû Û¿aÛW$l{ƒ°í»%ì<%ìøv|¿„í_‘°c'ì°wÂþl¾}ù×ÕããÓÕNØ.¶¯IØß}…ŸAØñ½¶}—„? aûŸœ°}'ìIØþ>aLJ Ûÿ„„ýÛb‰ÿþ|3‡°Lœd½ •TôŠŠ°³ »v¡ZNæ¦Kmx6Þ÷ÌQŸ¦`ÍÐtþ²Êõ-ôë°ŒaàÊ ïÉ¿„ÎS„]÷¼4  ›,™Q²Æ›°mKØôM¬ ›Ì0¸B7oÝJIºQµŸMØ A´KØ\Oa¹6<\º¸J³"*ý@"옄mäšÛ`Ââº:µæšµ`p\(ʲM›¥EÒš"‚ȦçB ‚í°Â.òÚv·LÛ¦®Ê2\¥9rÉòY7›ŠŽB'X½USC²V×Ûh®Ð:#…¢µ"uwvRaW(ÃMØåÐB`‘½ü„ ‰Ð3M{·¹ê ×Ô:JŠœVVw)–›´±Ò™$^«¶Üv̨ô¸« -}w¼23¸õügÁI]aÅ:‰V¼%ƒ.nCØ¢jÁZ60P‘ð‰»#!š°AXH†`‹r³î0«Ù9ôgµ[Sz6a“EðOãhë4‰dˆÖ¹Ñ¾oòØv³}v@ØM;yHØÙAdtò϶¢‰HKMIÔß ›€± a×¶ºúûMؾ©°mg½Hª$1zöh%Yó/JlG˜6‹’½Žå¼F6™¶±»žC¤UHñ‹o»…Ç膰s]WÂV$6a×Z‡©ÒñË&a ßCøž®ä%¿rCØ¤Û Û»±ß„Í;åJØ PÚrxˆLBµv´6$]\ôCÕVÌa/BÜX°ž]¾v2@Ø]½©xž„}ó‰°¯žoŸ?NرöAØöýv6a»oþßQ… ø›„M´Å{„m§„m‡„M"Gl;N;7„]!Ðö1aY|Ì–°gn¼KØUe!ÄEØL„v|œ°ãˆ°Å¸Âv—tªªŠ? l‡°kqÍzª¢¾S²ÅýÌä"ìb⊸&ì˜#a+aÇaû‡ÛUa¯WûaVØÇ„m‡„݅ﮈ|ù^ÛXÂö°›°o_þyõôt}³WØß€°·–øCØù§'ì½Â¶³ö!a‡Ëï ;÷ û{¯°}CØvްíOIØ{…= ûîå÷Çû«ÇÛ°÷ û§©°wÂ>OØö†%»%þ#v~Ÿ„m;a°ï_þyÿôüt¿öNØ{û2ÂÞZâo6‘…l {æÆgXâH…½÷°4ÂþsZâ;aOÂ~xùíæúúöa'ìÏ&ḭ̀JÂþ©*ì°Â>_a».ø açY¶-a‹€.àþ8a‡Û榦7„í[¶I³úI€ž6ÿLÂÎ&lÛvíWÁü†°sCء˞„Í|ƒâ©ÂØkÖ»î$yàÌaÛ$ìÎÊ#¶öãË/ÿ¸»½½Þ){¯±wÊÞ){§ì²wÊþž)ûéå÷«»Û§§?~N<¶„]

vöÓUرWØÿ† û€°÷ û¯°­‘öWØ“°ÿÐ {'ì°¯¯^þöÏë§›û}òìçãìïί”LpbÙªÕ'gû®œ½ìÝa‘m¯ÙÍagŠì,¼9àlÙq޳cÃÙz^^›Šì8àì¯RdçŠìΞþÛgÙqRdqöW(²ešÙ‡œ}q‘m¯qväf忸ȎM‘íg9;¿u‘½r¶}/Ev~6gãŠw²pö»âGœoq¶½ÃÙþgçÊÙ ý¤8;¿g_¿üú§»‡‡sì"½³wÎÞ9{çì³wÎÞ9û»àì›—_þ‡Çë»ë šÙ;gïœý½zãßU3ûÛžðÚ›Ù¯pö÷ØÌ¶½™½{ã_‰³o_ì·çç«ççý¹g;gÿœ]+ò]÷³mËÙ{?{Ÿß9{çìsöß—¯ùßnnïŸïž•¼pIÑ è „êÜ «ž@¯™ì“Æ—®€= $Õ£R·è!ÉVИ…j°­(—eûŽnÓ’LQv¦1B¬U³äna¦/ïÖ«LA@äÁOiî+É–?eÕÔfÁúcÞ­»J!)Dzƒ!¸üÄÅ¥äA‘{(±–-¬Ð .Ÿm~úëúÎÞ¦ú¸%iÊÜh’®Kw‚¶¤Y«0peõòj g}~BÏ@§¥Öÿdo±`\„T â$!âò6ƒü–ø³FK-ïìO¥0i§]ßé^9¢4êMWAœÊÍ*“aÖ0‚ˆH²sŠ3ѹޟQ±ð)<£ÄH½"—ÓZ5J¥² Ó&¨,(‡z2¤î Y7¯Â<‘ƒõí@)ú©[\01Z=áÉYï‡I殪²mZ·ï×ÎB‡1>…øº”*9øƒËVά\!4C®Ôr²"# Qòš±6ÃSDÐ×ê €GØL(bÖ%¦¥«áðjäU„õÛ×Âä\²P)€wšRéËûZÀòÉŽÒ(Üs%4ZJJ‘DÒÚ@0Á9„ÔAB†ö U1Ôä"Ù6>ýÚDäåëŸoî'›JxÂãNí¯„Çå(äŠÇö>O­^Ûy©âHˆ3xl‡xŒbˆsxìõáÙxlÂãÜàq¼Çv!ÛË+Tð ÃÐàqœâ1& Éûyã±5§©J9ƒÇ|~«ÜTqð6÷ à1 }ŒÇy€Ç¥š(ÈQ<„Z¼‰Ç~„ǹÁã…LÁ³ wyX1ɨeãqÌëÏp<®ð>Àã<Äc *6xLÍ«³J„ÚY<Îy€°Ó7x,Á½âqa•Æcôæ1çC ^ºz–½ Ü׆¢‘÷ÖxlSnÄ1Û {ãñ²ˆ[<Î<öÆc?Æc?Æc;ÄãRL§Ñ‘ˆ´Ÿxl ‰ª«Ì×"<îbÕsü^A"×@x¬·=Âãí×úÚ Äw/¿]__Ý>ì@¼ñÄ;5 öy³ß3ÛwÄ÷/½úô³ñÄ;ï@ü³)âïˆ^~¿zºº½;k÷U‹ozÇÕˆsZÅÖWxˆýu ƾˆ±Ã.ʈó,ûŸXÅÕ³‘ãÜ@ü <Õcª{ ©ºkNvÌé݈>XXÄ¥>BaÜ¡U¬|©+/0q€¸ú8«Uì瀘¦YåywEbÖª¨Œ-8ØZÅu©±±Š]@ŒEÖ@<­b%‹¢ÏÇÈÜ1.±µUlMZ X¡‰F{ÔÈuðBí3·iÉ×{Û >g«ÃÄÿl­âŠym‡7G·t§UìäŽo€ØéNn€XƒV©­) ÖK¤ µ¡Ã ÛY ös@\‘. ¶¶Š«+ØH∹³±ŠÕèž@L·zè è<Ûì§z`.™ÇjûU̪s‘м± *§UñìÐÙ!³`Ywú¡ÐÔZ…Ê‚sV±z~'@ˆ£Ø7@\áE‹µî¨š+!§Þ!óbZÚÞŒ®Ì2e€8¸Ù¨n¾VåÔ*^Ø©b¨¢"€øñå¯×7÷;ï@¼ñOÄÛ%û逨¿ûçqÐ!?½üþpõtó´[»5‘g¬ ÿJÖDX²íÖÄfMäœÇÌðoeM¬üùÇZ~ Ä—ZÎìp|{kÂ'Û[ÖÄó‹ýëêéúùúj‡âס8b(Þ]â?+ï.ñ\â?Š?âÿç27ñÏÛ§»OšX‘¢Q#*ɰ˜ Mà§âaš¦MíDÒpõ׿iƒO€Ø'»àQ!¿qÝ Xf+³(Ñû¹±j“.ˆ•iüpÏŠüàŠ©•Èìì¸Ë.ÿú7sÂ(cr] î>ˆ‚‰Tà2©2åX½z"Åž}¨†WëRëjë`/¨Þ¸cÏ• ÄÁ¿óI‚òbÓN€X1é‚É Äu!u;ƒ3¾ba à¨Ó½­ò \#Bb–Æ:šb”²7µIv €ÅG"éËÒ’×EúT üiô.X#Ïa•óŠ}oœ-qܰ՜°fš*Fk X×낽iNpñ¬üÜ‘Ä"*IzĘ  )ŒCªÆº™#>š@ì Äså2ú·o”ubž>;Ö µþó>YÚë?X)Ùë)$4LŽÀÒ±]Í|ÈËé‚°©ÊŠnØL ÄMì ‡ÎjoØÚœX¯öˆmÄÖ@\ùšbm{ô¶÷ îDhП æWÁSëG´ ÖµÀ€ã-/Úœ VS&ûxÇ.£¿^]?>ÜíX¼cñŽÅÀâ‹Àxä…`L^þº»2ÿûß®®k®IOí¥m¥g¨jÖ°|]Ÿ½€£÷gÖ¹ˆÊ/Lô^%á]r€쬊Íæµd"3µ W—•ÌAË2Cå²°¿³PÏRƒú E(‡¼›uºR¶91¨«t¢½\WYÿA2¼÷²“Ò.88kTn€~¥Ge¤Žjè8jW4æ:ø˜:9™\g¨ÿYÿ²ˆëÈ ¨ÔyFêYú³ÂG{èpØreNCô‡QîÅ\¤=ÞK†ë ]¨no‡>«d†Š:X–ÚTj)ZŸˆßx…–g¦™£“Òùµ®ëÖþ›(P©ÿ (ã–§Û¢`]ù¨ý,@*ô¡®ÒLë .šWÔ ª«ä®©ˆUÀ-7Q_ÈýบG(™òrªÒ…’8ºF»ލ±pý½¨çŒð3-æG„#ÁqnrµÐ´ôJcõ »÷EíL—­yCI(àXˆÌ<Õ,ªb™ÓZ@c6ÒS¹ÐVÐ1å™­;:«HBÚæõö²±j‘Ö‚ ÈÐE\S<(6¸vób¿\Ý>=?ßþ˜f'˜æo`šã¾Ži&ü,Lòašÿq˜–À´X1ÍÞÀ´¾å¯…iù=aš}6¦å7Å´8Á4ÿ÷`Z|Lû_‹VûëÝ>>ÞÞ]ñŒF3Ø7ˆ~Iîè-i¹©x·íSmPÙèÊày)™ŠZЧ‚w»”÷Ñתy+iŠùº¹*[‰4B¶ž°K3î&úkÕ@?*Wß<Õ†Ë`K4±¢ÊºvrûT &p߬ŸjÃÅÒWiÒö²-û.m5®e'üÚû¤T)ÏJ,ÅSm,´»Ä³µ/P¢œm®¿…<¢Nƒ7ì5/LWº×çàg#Zêrgl¿VM—¼õãÂ*E:¨y»šg0ŠJm78ž˜­c*¸Ú'¥£,wV[,©ˆ-å+F$ÂÕFÝh4ˆ³0ÑÑ猺ñÔ+_l¿µnÀ4´%  œAò;ôúj®´)ØF>¹¶F›í, ¤ õ¨ÝzôôX­“Ñ®#±FVkÓÛ)Š~z¬‰™#;ZB; ËgªB¿x#œ§Úæ½ñä8lš1MØŠ°F 6Oµ1!žñ¦ì "ºÉ5¿ÉÜ7/¿z~¼ø6¼/¼óöÎÛ;oï¼½óöÎÛ;oÞ¾}ùýùæùîAQŒ†”‹h|ñøEå÷8âñ‹h|ñøE4>Žxü"G<~#¿ˆÆÇ_DããˆÇ/¢ñqÄãÑø8âñ‹h|ñøE4>Žxü"G<~#¿ˆÆÇ_DããˆÇ/¢ñqÄãÑø8âñ‹h|ñøE4ÞÖ<~#¿ˆÆÇ_DããˆÇ/¢ñqÄãÑø8âñ‹h|ñøE4>Žxü"G<~#¿ˆÆÇ_DããˆÇ/¢ñqÄã[ÿ¯Å8ÿûííüÒ52H‹ 6:ˆª×”ß5¤±\ÎPª3-ŠI•ßœš£Ù¼ôÞRójÆ:ÖÑG %ºûWé!àQ¿Âé 'Ÿ òIÂÛÍ´!ÀÓÈ“wâ¦ìq\~±ˆBbÃV©Ë=•jÛÑöÔ×€‘Ü> Ø€Ó+D½ªÉ°ìó{οÐA‡nõ¦u_f ÈuKò… ³MZköÖS½“ð©–¯hsÙ°!ŽA‹8!Pßìyj}X=ï«SM«¹FÚG"·V–PU&å´©+<ÑC%šœÝ§)›jg£LŽæÌ9i¢ O×ɈÚeV£ÏÉX$MË OÔ©G.“ä_qŠò'éÊAŸâxCñ°(.Ѵضµ³©uV«Õd2gulÿhÌâ·âÒÊ¢Þ*¬›ƒ²Dz­}HVŒP‰îÁ°ɺJ[Jõìé ‹ùÀÔrÀŽ>:9ÀÔü€²³ù½Bâq5« ~«w˜J¨^ƒDµìi~Ee6P‰îQÝ)ׂû˜±îÑšZˆ¼&fk¹Ys Ò0…~èW'ˆ†Ð©ßðnÙ;ã B‚fˆ¥¦‘p³8©Mðh=4èÑV¥À¼dÅ„D@#]áÌÅØð„F7‘³¡ü#E]_ìPÔK™ !ï‹,G|és¡í>£eªcBp¯"¸nf¹ž1§™H]”iM5¨è«N¾™’–½`&"W¾uH‘ܪE@…ÐI•ËÓóMoÝt¯ 8ˆù²°Ž$Xf^j÷¡Þ£îÞG£‘u=€š-^™ý ZÝTDWö}K²é¬Çà}'oß¼ü~ÿôxýøGñv~1o综ßoÛäí¸ˆ·í-Þö oÇÊÛyž·íñ¶}·¼íoðvœò¶6•_…·í„·í[ð¶A#öÞöWx;¢]à<âíö ÄÛñ:oϱ³CÞöÞ.ÿ7ñ¶}]Þ¶cÞŽ÷y»&7¼çmûÖ¼íŒDðv~sÞöó¶½ÂÛ•§_ÂÛþ%¼m‡¼mäm?ÃÛñµxÛOxûö執wÏõT(Áãh>¬îŒiAëVÓäùq)Ñoy~\Z 7Ï0^Jô[ž—è[ž—ý–çdžèíu¢gÕÄË“çÇ!ÑÛZ Û–èmý–çép¼Gô›¤ U€®äù Ñoy~\Jô[ž+ÑÛÛDo>Ѫy~|„èsCôÍóËeŽK ô-ÏK‰Þ6‰~ËóãR¢ßòüx¯@o8m¢ßòü¸´@ßòüø0Ñ«@ßÖçãècCôq–è·‰ŒÏr5j¬À&ùWX×5â™ ô¬“7Ï#aG—gŸ“°<*,?/a™ŒÍ™°kß¾üýæêé곘Ý>Âì”Þaöøf÷ÙÿÌÌžÿFf·ïˆÙýBf/`v»„ÙóÙã3˜=.döüw2ûÝRò\]_=>ì%Ï Œ¶ãTòØ^ò|XA½Œ?QÉó?þ›°]ß,Ï•¬®~‘—ùTO6ÂoS=ƒG™ÎX•·ÿ¾m3~ª×ÕªÔx˜Óª({-ªqA£ÎŒ`šÕPµ?ØüzW#p.y€XýyÅj½%™¾ŒMѩ¼¯ ³:‚PÍ =3ËûInÎûò`®´ÌeÃó4&hepÖ/Ôûº\WÆw½‰2rËú-SºNqªûRÎ:7ŸtÜÕŒÞÏîâ¨|Ð×µð¸6ý¡óǦ÷ª«*g¼&¼¯’_ÕT"6¡'¿Å†­‹3¸E'ËƒË 1‰E–X­*iÕ9ݕӪA ¸ØÕ*<™µ¤›ƒ•¡§ô)N\Ÿ¤Jmxý{àäIÕ|ñjÐ…®˜˜ƒFé ”ëÑ=L¯aDšoÜv½‘áWë“ñq¦‰%.jIsö,t’…  ãÔ>»u©¥îe´©­þŸŽž9µ[h£çÛu"TnÔ‹™Ÿ´:ØUQHÑ ·ÒÛD˜š–†ÑOLiò×à‚Àv.X4,kez/¾Ç ’g5T^1C«ÃúJBD«m±±f5Ïverѧð@Af©­\kÈê&]>ê_‹iý·_îžï¯ŸŸƶÀ ¼÷Åe·+½°ô¶°¢í `H®¤!%Õ×è^ˆì}2ÕX*ãY|ê° “݇ 烂­snK?*²çùjjY»:Ÿð}¨#6_ÞlfÐѬ– \V/š’cÕË_~oï® 7Gæv:04 ú®‚§P¨Ý×ÝʲDzÎÏ­¤CDÖ›ŽÊŽ„b1'v L-?úÐÑÁÀ“­SçS”ù©ƒw¤Vž¼‰2„­®#ìîŠyúg—T Y¿Œ·¥é‰Pg7¤•­ä8ÚÝì8ðÞùA·KkÄ„¼"ý T*IºY9¤¶Xé±kë.T‘xkÏê´-J]1 Ø­5Ka€d(ìô¾{É…!H¢Ý”¡®”ô2Ÿßb_ äûòKõ%›´ÞZIsÁ6±UrG!Ð< ‘¢‹BÛGÊ¢Õv4- Æ =Pž˜$ H¥ÑŽ ©Åv5SYv-ó-†]ÕÛ) ›3­Á’ìÑJ”È,$‘8¡]éHÓ ÔÇLøº_ Ч燫‡¾> ¾ü‡ƒ¯|¾B'«'|ažÇ›ð•ÀW¾_ö1øòSøò/‡¯./?¾üøÊ#øÊ _~9|yÃW¾_9áË'|©<ªªì¾l_0Í|åF„}¾â]øÊ‘`ïÂWðy[øú}Q_ñÏ«ë»û[¾|€0–›ÓÃ3¶©Ž«ž52C9W ¥ª•Ù òÔ¿¤ÎNPf\?õ†¥éË[S0Ëà ŸLX,ÿ¸¨3ÐBã3Ë‹qCLžµ{a“PÒŽ±ò*/F¡@Ý‘Îà˜pJ.F†ÏMçzÁ5Óƒ R&y\€…½Wàå2 ™,³þ¼Aám ò“rÞ)X± ýEýöÀGÄÿ “UuD¥+)£}9¦xÊ"¢‰iÂǶʼ1»¼G'¼Û[ÈFæ:Y ›í<¸¦Æ€%ÓÈ£æþíòÛ–? :ù :·lV`ùùU•ÔÅhþ4Û?2 aø {²ý+ìD¹‚VOPìâ¤M+cº0ÓPQimñLs81U=kÇAÔ`»›¹È0Má@2¯SäM òËÌDÖ[ͧªÔ¿ƒAñz$ÖZ†Ê¬QµÿKünÒ@åöý€%©Wf[€sÉS›ÇCñ9!u6<€rë\Sè‡z±V"ú9)˜æZaìá˜/Ãg¨0 `S‰Ÿ´-jݼüvûøðü|ŒY±cÖÄ,Û1kǬƬø0fÙχYñ‡`ÖíR(>?>ßÝ %Í.©Ä¾<…ÁáªM’è«TB_qaÅ%åRªwY° KV¦:,$ëŠK!wYy¹ªa–F‹ßó¸´¥<…¥¡ ¸ßc‹Kæ~K±…¥å7ÆÛ¸d¡qmïZYw_oQ¥ vÑ9\Ò¶)×êÍ–ªk׸Ä+ÊÆ%`É–l…¥v^ª…ggqémXoàR}ü[°4Np)»Hna)XÚ Kãm\:KK•¹Å¥8Á¥†%?+¥Æ).á¹qÆÅ\nAÃRT´±”6—*¹â—Re÷,EÃ’ {©q)'.Ñ ¬ Ó¾Kµe‚lp)—b&AÃ’Á’õ£ÏàRP¹GwØ]ÊF°T›ÕãI”DwN’uÓÜ8`Ý™–þ/¾ÕäêáS øÐùýÚz±-ÝLõ'à”R:µ1±>ß—Ž,NFy9µ¢uÝê…š9à€ééè1unÙ~¨M)5ŸàêÉë/ø ošO8~j@ß°è™Jg\ìK¶NŸÃ8¨Ü5쉘®Eà!©Õ¤ ²€³ÝÄ ˜:[Rä[×EŸ(tʧvšGôVFd’áõ†ÝnuÞš¼‘ë5‰PÊ“÷2Ñ4ò‰Ö ¯^Nû5KÓÌ1Ö¢+2¥"NDYuQœŽPæñ:Áðæ„Ÿ81(LXÓtõßѱ®D+º­¬Œ|!«‚æ(Ë'Á¡Hp_SÛëÅ_~a´úà¯p”hZñ"bL°UïWÞÂ"Õ+ ‘ljGjW€`jÝ…¶š€«3„uWZ‹hѤl#^¹öŠ™e¥) êÀ’É| å?-ÃùËù jÀr•Æ‚e0Q¢ « ¨U@FÂÝ)6 Ð,å©¿–mæm›ì¥hÝQŠÏT^#:€„r c®`„UIR¤­h±P(%ÝÕÁ¶Ôy,æÚÝÔJÊ%s+UII  õH4šMÙÖÅØTý\ö:\þäôd¦bŽ’!éê¬äèKÓïPG’¡¼–ž.‘‹¯’{Þè)g³…B™˜œšg3düÊ!D\³&S»GMô »¢Ñ*!J™Ùu ±v*÷Húpšmì~QµÚ±tÐû|!0àš ÓL¨SmÑÁŒÒ²ƒ€¥Ažm®£65ìã}À@‰Ânôx£vE$Èëgé[ E)ƒÚF9 zqÀ‘éºòÂ4‡ fz÷X å1䩊oFŠBGVêm{=˃—ëžÞÍà"fC,ˆ°hÎD®Å–²o^ì_WwÏÏOúrEØ«¯'” yS6ù×_hÂÎl)ÛVÊŽ·)Ûš²óʶ-eÛ!eç!egS¶RvžR¶Ð_£PMÙ›N*Hu@Ù¾RvLʶCÊ®†Êe·²jÊvWĽNÙª¢ì ·VÏú ʶ³”ŸKÙñeÇeÇyÊŽ eáç);·”íÇ”'”§”íÝY1¶ºeêaQ6¦)¹¡lõcDÙAItBÙù5););uÙ—ÑF‚ oKÙ9ð¿&eK„“rP¶Iîz´Ô£9DæÙx*Êæ­¿s7º ÁçmO(Û^¡ìRù"Á#ʶϧìÖÇ'a“²‰¦ìµ˜·ìGuo);ãó(»¹Q”­wôQ¶ˆ²ó egSvG*Mã );ñrÏQv¾IÙJJkʾ³O¯P¶_DÙ1);_£l»„²1&ÎP6w¨Éâ.½'e=^½);N(Û/¡ìø(e߽دw7w77{•½WÙ{•½WÙoWÙ¶WÙ{•½WÙÿÎ*û¾)ûz§ì²wÊÞ){§ì²4ÊΉ²^~ùÇíóÃíÃÝNÙ;eG”0cSö·£ìc¼)Û¾œ²›)ûƒÆøCÙÖ”m¯Sö‘1Pv~eç·®²í e¿eŒáseç!eÛ!eÿŸõÈÒ_®n¯nïî†^˜õ¦ÅÊÜŽ‡x¦`¿öpY5Ùjg¬ß£ÎØéúkÈt"»’§~¨5ä™H1\Üâ7édB]RýNÍþÚ‹•Xƒú»¬ãZý8'¡ŒK+1 IXAD:º"¸Jš~Üoõd>8’õÑÍ‹¾™1dçP‹kEõM³\Rèꪳœ.Êrpû¼¶~_Çê¼âwÕ°õG6éYï%”¤U*‡‡è©þ;Èþݹœ&èEÐ^«Á“ØØzãà•’Dëï}Qld‰˜Ñy Š£ b„Ïú{ƒ½ >°æ4Ѽ7¶™x }`²µ›‹²Zm‚! Ú*ˆ¡˜jm%@\‡Ö+t=úÛ´U*¬û§¹¢”4þCq2w§wA' š¡…­"Œ|ª LíDqiiQË´…=º¿,@åÅ‘º|…qÎlš7•½ùµÏ­pzU guñxYX¼KÉHµÐ|‰ÏŠÐª*  aexÖ­5Nè+ʸY#OôÐŪk[×B’Eõ¼ìùiÞKÌ"³mîMÚ 0ñ/<ëñþru}õ|«ï^œµLMýö#ˆjÆÂ*ZÑ‹ÖòÔj"§Ž„ô*Mb:ÅðjÒuÍVsq)Qû)Á]p!M‘¤J"’¨«¨eŒËª*È›ùtœÁþÉ›®&CC>ë[ÂÞŸ@9°ƒšï÷®eªs¾¼ƒ¡_ëYþ¥x}¨ê )[?8éswï{y9_Ã…ÐÖ‚g¦Î¢Ô’…éT¥»K°ªÒ©ïYGPŽ”ºëôÌ2¤IýFíË@Ôµ ’:Ù2€¹Þ½’¬Þ8f¢ëðƒê¼"\ÉUÿ¨þƒ†‘9Ëúé[|™éŸm}yèMV¾¤‚¤13`øÒÆZ5”±1‰Ô"HBRÍX~0™Ö$QI‡FuO¹[ë¦W:PÔ«MsW¦—©,5kȶ©J|L=­ CÙ¼Iˆþ&”HË_ÎÇú­*…uÈVaÍüè4ú } »Ôþ²B\<±žÙÒ‹WYe9¯³oÀ˜è§~/fë¿TWé^ÇwÖæÅ.—F ©WÖÿz—èì8D~5Vw…Ýï«ÕöÆœ…n9쬑)]­í„쇴ÍåàIáªE\YÔºcÐÎÙ*6:Û‘Ø WÌr.„"Š«>°žXç²C.õ\énö%µ)lõÐDd ›£+œTXÇáo1£•)·›É YH‘§ÊÙÄ'M“ÈÀ³ §Ó»´ûô;ƒ†Ö=a#¸b0a£‚ ¦¢µ¾õQÂ`ÁPâ(qd•®Õ VøD?Û¢*Џ$ºq/)œ8ÀH$†º†JVÅä†uÒ¹2»é«J(Q‚K„È9¸d\.1ChðJ4ó¬L){)9K¨(,òõLJúœmXªàùþßÿÏn?<¿üzwÿüt]_ÏØ d›sZútm]Dƒ¶Ei0K}Kp¶H2±ê´”sæt™\L25I¨e à­ÒQH†çF¥hCª{U…Õj;y 4¤23”³CIPb!Bnb®X{¦íƒ@S 6% ÌTŒROÂΨöLʃÚ-¬ƒhî@$Ê)ÌÁ$ç^CP¥$+ìá™kaä+}iü¶"7ÖM¿½®/渹ºz¾¾_i"©AÓ½Vd£_´éUQƒ Cþ¿ê×®³µéraìBæ¹éɦgoz›d¶êñ5¸ rÞ¤2ÁÏì&@1oS$w^LÂ!' ÔªÐÆaÓî¨ÂFú:lzŽf_*]d¿~¦ í‚c4ß’Ý£ÞW£áU~`Æ;v ÔŽ”âÌ„QŸ˜ý‹Ö„‹RK‹¹ë>7ýú¦6ýþñúñYd.z»ðAz†º<»P«0¥ET 9:%Sš„Ò+±¥P@}l“å Ï-ÚמÅ®1‰çv缾ª¨åéŠÔ÷Ôi´*,)+²ðN$®æïèü&_(=éõ¥ìÅ^¡` ¾w® Ö)åH[• \‡ÏÚ°xyGA5jvDÊ™Ïäx£.?u1ã(#1Ú0ÜÑUêÔdˆ’ä©ã…¢2é ¬M·®–høíùùñæñy´¢5Õ3÷1lõjSm£D*ß*'‡Éµ…®Â_oÜ×°k%ŽÚI@@½#FuI>©§@`è Ô¶é ¯/Â[n5Oò6Rû6†”r™nÒ¬)Ó¨²JjC€Ç©WSÑ(û U®™¾€|}š?9q_Õ`ã>æ•®Ò¦a`k[TàR ™ªÅVÜïÆ‘mqÿ?ªÿÇíããÃUý†(Çl›ñ…TjætIaª²–5]Q¿þĽ« Ð"UT·®ö–NŠcÖýÑE›ÑúÓ–»*„žË€îxq¥“Ï)Ôå’ìk–7•þJQ½­kÙeG¶¥Í¤·À,Ê'C‡R Ø$›íßèr+UªX C õTºÍŽ Aн>ùè'eãòîõØ Ý?|›zI-²vœ¼ÝrW(àd}%ùn—ÔÿõñîáöáZ7,—®H#»ýc"ñs!Sˆ.™BQ=ªÂ†ûÁ(45ºõV³|Ý_¹gXv¸k!â%fð’Žkô/ÿà}z»ÊÖxÑN€t;R ÃX<<‹Ü\ãÞ=rišRà¸ãõêÑo‹W“=ixnºS©= ènX÷BÑ,9@ FDyðá¸tõ»u\VO¨&ûœòVV§‚ C̓%|#zH«‚· ¹VT²4áÊ4¹¾Æ'k}Uè’÷Ÿ¢é?~»»{¾ºn"ñƒB¶ PÖZ2•çf©&Gúûè&mÈ2€H\!d j;$:DðPç†H ³}’(qå(h¿Iµn@SÖ*X•m W™ªy’ý„ÈLMÁÄFÄ;:Õ’ŠẅwSú׬ŸÅ8C$Ô7>=«µ€ „qPõU²óà,éz¡ù, jü €8 »¹©M¿~¼½½×S4ô­Vo ¿[<›¯iÉêº4ûµ–ô–¬-7Õ‚óa³y†E…h¾ÅZ²\¡™w¥%KFñ«j]‡&¿¤%eŽØ¦yS~ÿy-!V³$ÔòèþýÔ’1»¾êÿµ•y %#׋zôhÉTs§íÖUKFkÉh-Ùaï*Ϥ%£µ$Q«?ïN÷¦²‡ðIVÜ>Üx2ï1_©ÑM9n`C­«‡@M²ñìPKc®l=T²˜d­œÔWùŒ¥É ʼå Å']\›f¸+šlÖ5ÛFX´í½Ó&צ]3iAÒÔ%$Pž™”ˆ« ¨Ì˜ SUU/›†‘éZþy£#2oFb›ë º¨­‡ Ë´“–´Í¦ÿ妞Óòtû|K5Z;Ä”HÕ$ƒ½©H¶‚tAé°ž4@]¤¦hRýõi=]ßpð=L#{k1Òp’óTšJŸ¥‰ hK$S±)¦V­âºàd’ OŸ@ZñÏ::¥ÛO³šêbjšhˆ:ëèGr«5¹¶|} Û¿¬>ãI15ºšš.½w©ibéãbŠY•ˆlô‰vRLõÄ—©^Q15f€Ï“ø?+¦ÆºýlÿõÃÃÕíhÉtdúÌO*JtH»°Såã­|¼a/»rpO`OÕ`Oá¢åFùøÖ:õÏÉcÖ%t÷9K­]6UW•ŽøMßñ͇[£ä„ÜÚ(¡+?zlô­*´Ö·áCïK­òvÙͱ!·èÜ¯”ÔÎmjóI•,A°ŠÜ ãÜ%ÙúíS¬µ;ëßת„)Ÿ¹€[Ó,Œ"ç6ò 5/Ñú–r´S{Ùä±5È­×3Ô—>Lmy4ºçs¹}^ß^/îØß¯P·Ù=ìb©X wЪ åvµM¹:äm ˜ŒQS•íÓ À.AN :ÁQËké~©óàj Ç, ±a!yo2XMõ“Š3®D”åˆgf©º^Ubv˜u”ò)õ·$vžBµèhSùbd ù²c‰R?á õøÊY¢Ý‘rÌ1ù¨?™ã?˜7® v¹­Þ*y¶Ù-zÝ÷ÂZN9Ø£4®¡ƒ‚(tZ;®â𮨠Цå,ç²Æ½y’˜(½Ð¾ÛÝË/ÿxx|¼}xþˆï–švüˆïfßÞw«X|ÅwËW|·|Ëw³é»Ù÷å»Å›¾[œ÷ݺæ^}7Ûøn6}·¿\¿Ü¼üóöáF_ 9]¾n4t̓é FÖ¥½kcŒÎFˆR£Ìœmô²Fó4~X%ßsHTÙiÞz™B‰2ýæs據sPtmô²©@˜.¡çX´£¯iðô) >iåçûë= ~ü4xÅ~¾ý¿ûù_OO×zð°uó”Wc0†ê*¸‘]9·÷ß¾6š]¡ÒUµàò÷CÃhìXÐalã#dë0Z!3LM¥åoU9ãçÕ´–lµ‰1¯¸6Eæ ê<åÌUp ìœ))wñð³` v^æúiy©œÀhÑjkúd惘r#5Þ)±Ô³<4¿cÁÔ*ëîHZ+$ ¥4ú _Ùј'ÙU>P—²©˜~ùÇýÃõÃÍÓÏ*‘Ž*¤qQ‰tT!‹J¤£ i\T"UHã¢é¨B•HGÒx»DŠÃé¨B:Ï'%’*$ǘ£ JÕ0õJ„QÊä©•÷è¡ßèÈu wSðËÚóø15Þ“VEÕ×ûo”œõ©m±¢‚ïÚù`ž‹WóËoOwO:‹)HÔ‡[{Ž.,‡ëâ±³á_;ä_áÏ©_òø¸ùUõeœçùו…¿jË¿ò«Žø×7üKÓ(7üò«Z€ÜÎ%x$û€5“ö°¹xœZ‚Õ²k âDUØ9 ’-AŽ-»³Dµä¡e·]‚˜Kàjù®Ä7–Ý*A—Ànž>‰0­ÁÃg»­VuJÈiÜÍÛ©‹­SD¦¬õµ[e=îæÛj^ý/w›J$×nÕḛ¨ quɸ”šêVwËÏwËòããnvH‡ÕüËÍòè”§»»›§Çs-J–.ÛÇ\7Ý£[ݳ?qڢ̶p\U,kš³EéÓ¨S-ÜdÍBMT«ìônQ²éšu¡›Ô––¼6fáOÕ«Þ›¾¬Ñ/#†xo¹’ŸÍBÒ;€(BkHªž´(}e!ëMÇìaÓ§Q‡¢V‹¯uËB³A|Ø¢ôm‹«è’åõËíÕ˯ÿõð|uwýÁM·?ï¦Ç¾é ¼_3Õv{óÐVK÷¥ý3ûÒÙ}éíŒ#ŒR AÖi_ÚÞêK[ËÏ7úÒöZ_:»“âŠ@€þ\_º›1é¯÷¥×G{¥/-fŒ5Toï½¾tKãÃǺÄ!8ߗΣÇx§/gûÒ7 wW·Œ9Ë;”»à!GÜt°Ž1üéµn£S”»Þ‡r%C^§$[‰p©·zU ˆC¾D2fCGÎñï ‚JKÂÁÈjK>g£%>kDBïbHjÒE§…Œ]¢º¸¿›Å.µ†Í_$$D†kÕæÖ£¸ªc\o”ZN]-z±4RŠ%Oå÷« Vü»FX0jÑtÔžËDie>V1¦ J-c&Í(.ýÐ?3\ú<„"¦¸ç Ô )ð©(­UXB‰–ˆÚóMåWüúôðxs{V=ìNM$X‹pªÿøÒ§xmÀ©—ˆ'¿L=,µÒß_=õ¤ìI#q ôÙe×þ¼M#õ?,¾½ýzwý|ýð´ Éw„¤[!Ù30ßXH†ÎGÝ?Üݵ*â•V…õ<¹€¿¤çPѪyH0±ñJ«‚Ðåë@»¢>„ŸkUÈÀ ó³­ŠØ´*ãg[][¿>)oݪà3j¥,Œï åãVEb”œiUx·*L‚§Sx¶*äž´*”XmÜ©i0x;úÊEÓòVK smU—êw·‡×³ùXTä?=\]mž”ž¸%bY,±f¿É0*¨¯í?TnF®Ž·Ô×ö¨œ²¿=9¥²õDÓéQ¹hÃȦa$ ¶²¿^ {ÉÁ>É-2qPÍi•‹îÈ1XF+û ÖZ="Ab&©ŸWYR‹3¼ZPÑ”tj¢Â‚¡Bi[]´/:*÷XŠoAüÇ«9ÏJzàN•Iè¯Ì³n_–)Þ²`F|ߊ¥‰ÃyV)>æY³;•óö^›g=ØsÓDM½rºgÛyÖTƒ5» 5Ó¿¨¾ÒJÔ>ß_–«$¨¬=÷ØÌ³äÙþ‹ ÔlD¯-Ò\ÝßÞÞhLºZ\†îÎõòáµÑæsV%J²2º_dÖ£ºü Ó€©]m 6©*QFfû ÄnŠi+ÇiÜŒF¢ŠŠŠ=DZH°1뵪¸†f°tñÆ~3ž,»¢g&ÿ– ³|Œ4LÌÚ¥‘¥+Ð=¬X(ŠÙ–qZ.º!®Å稠UOÒùÿE£©§=Åf±DŠ`C*Cà&«Á=î5[†Ð ¢…9Ñàúå÷««ç›‡ öŽÄûX°X ¿^ÝÞ^= iგÂ:±S‘jž%E)ƒÜì¸+è½±^Ò‘ê¸ã-"‡ jg]i¨ ›%”O†ÝI^á.Zªñšü:³Žer§WˆHqäZ³}ŠÀÖW1$I¯£#’Ëç Ì&†™ðwuÞ+qÙv· {†€y‘d{¬.›Ô¡ѨÈòæCˆU|¨š¢èsë5§;¿*Ðj°×îó2;þûõÍÓô¢ŠÌi´ð$Ö¢2{¼üQS·{{Hĺ’تJg*üÈGܺHtY­U¥ÉABáb|½uâžçðB(åì‰û4¦¹ðä­à<:$2ƒàôÄ=J"l‰4l–‰ bos~Öµj=Shf^%•EW®Ñ'îkIEAì³0 ¶„èiÎ/•į¿<]=Ü=?}Y%a{%ño®$úŠ_/%Øó§O{þÏë«ë'NÆÒ‚Àn{t ÌåÎʆñÖAA¯!GÈ5ÈÍ‘kP§ƒ›gFšãžÊ)¼-RÝ,âW²­æã˜áj»ÙVǸ2–Ûñ³²M)¡?·ÝŽ{ ¤ðQUH[xÄ3+¡mÅ]ˆô ¼"aá[ 6z¶¹WBx¬ßf[ÏBs!‡ä6ÔÉФ\e96²ßLïí&žzH¾¹|Ó ™^­°x^Àÿþññ¶ ÑüÒ[¬P6üṇD«YOpÓ]tõ&f÷€ÌöHI±‚XŽÐDÇ„\"i>çÀdH‰ÍngÔz<5y…ð.Ñ3Ròñ­Åä'Å2ù( NÌ–g/MuL§-]Gvba!¬Ê±—aº2tÇ;ufe·­µƒ ²CµN¼ôð[è²M†š,;²Ê ͺGA3}œBÕù?(µFT<À¤ý¨ÿMªäê³×vÅæpiu îE-èÖæÛ'JCà q(b#²‰£ÓF¶ã²uØŽ,wnÄBnÄBwQ`Ðsbá‚¥®fæÑãyLC ˆ…Ìó'J›8l}B—¯bÁÞ>Qª¦VÌ©ÅF,¼u¢ôœXP¾*ìD,Ôx´ýrõøxuõôõ”ªQ“LmC™ÓíÆkÎý@i·.fU¨Â²kÝn;|áÒë§rˆn¯?mû“Ž¿ OU†d¸ø>RNë&å Øè ‡Xwßð…àŸéRTÔ¬G; Éè¼j?Š2žùÜ¢ðþ—ºžP[Ǹ/(EºÑ5Âa®¿/ãUfaÕŠä´ –‘ëjn‡$^Õ+m°×«)!!¤p@>›\Š_›@êž…=½¯®F„T6ýcæ“%¯$9`jÁD[)MÚ¢>^´Ô' m– ‘§½ÕŒJHÙ¨¿Cƒ|ušG”æ"À‰ÙÓx¼«°z~¼y¸fŽBw¦uj® ö„%å—¢a·®ÁëK¼ÍÛÌ!ÄR3ý]…øìsÐL÷V©ƒI Cï™ ø½z›´é—¿Ü·p&*<`Bã¤ëõîí-./rWTž }£WLâ ~ê2…§ãw¯ÍmåˆèTª4‹\@½³¶©rMä ×kñCê¨ ®!l%£E¸K[Ð%l MI¦Ú‘5¥¥øÀ•U’ZpßóUÜAûjd ÝFËâJw_]‹›ç£»¹}üTÇn‹ØT;Orj±7’sÛEì!-mŠØØ±ÓºŠöÖŠØÚÏîzoŠØIKÈEJ¼--•uå¹–J³ˆÅþò–ou¡k? †¬wWJ&“{RbÒ”Å-¹h©A|±rökÅW-‚Èþ"¶ uC2Ól&wɼTezJKȃôµÚE줥i\ØY¹<ß%þyõðøpwóªsQºëœs!½¹:ÔqÖ¹pyši‚wªk?Ýô7œ ;t.t£qòLŸuÓCuÞÜtŸÅÿ¡s!‡zë\t÷¼‹X7‘©Mklòá^s.ô¦jÿçYç%DÍ€’Õß"c6ÎÅæ™>qì\d;[zà\ÜrBèùþñ©I}éÜ›ì+Ê©ÔÌ‹ÌËf F<š{‹·æÞ¢_ÒÀNæÞÔbš½£íÜ›IÞp `ýù¹7]“á†çéøtPZçåõj¶,€¾à±$JœÌ½9ö|ö¢"X¥Ô+sovnî­Ž‹ýþxsÿtÿãC¢QQQ*˜ûË}T~¾»½"X‚ˆu©Í£-zŠóÈ ¤þ݇–`ù°7Žì«bï%ˆœQ[D›#ûu¯'K@OÛÃZT­KÀ#Žnïî¯n·KpøÔ‚œKàÇKàvù%ð^‚sO-0-Aäq¼¿q²~KðXKðü|{ýDŸü “žQL%I,Ÿ$B„}#ìã‰à‡K`2”Ôx5°lK"ÝážóK€«%x*-pó|ÿpÿðjÄA"ÄÚ8U"l¢ 4{ÿFÄI"¼õìŠÏ‰‚³‰°.ÊÆRƒ èø+ÎÜõ]=Æ"å²û‰2Ö»3’¬a-’|P2›ŽLÃFo1{p¦¼åîls^5x ‘²e醸CžŽZ_tÛg˜D´"ŠÊ¶ãX'É9':Bñ\z—Yó°´š;Ñ¥A@õ;¢ç*ZQ) á¢çDUj©O¨J³ž¡J±ôPØœ5)v'/e;uwDªªªv$$@´9 ÉËzaœÙÍn›ðÑ¥”ÿ·ýgÿÙöŸýgÿÙöŸýgÿÙöŸýgÿÙöŸýgÿÙöŸýgÿÙöŸýgÿÙöŸýgÿÙ~ŸÿV¯[÷0 genomicepidemiology-kma-091b8ffe66ac/updateindex.c0000644000175000017500000001164614157033525021577 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include "compdna.h" #include "hashmap.h" #include "hashmapcci.h" #include "pherror.h" #include "qualcheck.h" #include "stdnuc.h" #include "updateindex.h" int (*update_DB)(HashMap *, CompDNA *, unsigned, int, double, double, unsigned *, unsigned *, Qseqs *) = &updateDBs; void (*updateAnnotsPtr)(CompDNA *, int, int, FILE *, unsigned **, unsigned **, unsigned **) = &updateAnnots; int updateDBs(HashMap *templates, CompDNA *qseq, unsigned template, int MinKlen, double homQ, double homT, unsigned *template_ulengths, unsigned *template_slengths, Qseqs *header) { int i, j, end, shifter; if(qseq->seqlen < templates->kmersize) { return 0; } /* set parameters */ qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); /* iterate sequence */ for(i = 1, j = 0; i <= qseq->N[0]; ++i) { end = qseq->N[i] - templates->kmersize + 1; for(;j < end; ++j) { /* update hashMap */ hashMap_add(templates, getKmer(qseq->seq, j, shifter), template); } j = qseq->N[i] + 1; } qseq->N[0]--; return 1; } int updateDBs_sparse(HashMap *templates, CompDNA *qseq, unsigned template, int MinKlen, double homQ, double homT, unsigned *template_ulengths, unsigned *template_slengths, Qseqs *header) { int i, j, end, rc, prefix_len, prefix_shifter, shifter; long unsigned prefix; if(qseq->seqlen < templates->kmersize) { return 0; } prefix = templates->prefix; prefix_len = templates->prefix_len; prefix_shifter = sizeof(long unsigned) * sizeof(long unsigned) - (prefix_len << 1); shifter = sizeof(long unsigned) * sizeof(long unsigned) - (templates->kmersize << 1); /* test homology and length */ if(QualCheck(templates, qseq, MinKlen, homQ, homT, template_ulengths, header)) { template_slengths[template] = 0; template_ulengths[template] = 0; for(rc = 0; rc < 2; ++rc) { /* reverse complement */ if(rc) { comp_rc(qseq); } /* iterate seq */ qseq->N[0]++; qseq->N[qseq->N[0]] = qseq->seqlen; j = 0; if(prefix_len) { for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - prefix_len - templates->kmersize + 1; for(;j < end; ++j) { if(getKmer(qseq->seq, j, prefix_shifter) == prefix) { /* add kmer */ if(hashMap_add(templates, getKmer(qseq->seq, j + prefix_len, shifter), template)) { template_ulengths[template]++; } template_slengths[template]++; } } j = qseq->N[i] + 1; } qseq->N[0]--; } else { for(i = 1; i <= qseq->N[0]; ++i) { end = qseq->N[i] - templates->kmersize + 1; for(;j < end; ++j) { /* add kmer */ if(hashMap_add(templates, getKmer(qseq->seq, j, shifter), template)) { template_ulengths[template]++; } template_slengths[template]++; } j = qseq->N[i] + 1; } qseq->N[0]--; } } if(prefix_len == 0 && !prefix) { comp_rc(qseq); } return 1; } return 0; } void updateAnnots(CompDNA *qseq, int DB_size, int kmerindex, FILE *seq_out, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths) { /* Dump annots */ cfwrite(qseq->seq, sizeof(long unsigned), (qseq->seqlen >> 5) + 1, seq_out); (*template_lengths)[DB_size] = qseq->seqlen; if((DB_size + 1) >= **template_lengths) { **template_lengths <<= 1; *template_lengths = realloc(*template_lengths, **template_lengths * sizeof(unsigned)); if(!*template_lengths) { ERROR(); } } } void updateAnnots_sparse(CompDNA *qseq, int DB_size, int kmerindex, FILE *seq_out, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths) { /* Dump annots */ cfwrite(qseq->seq, sizeof(long unsigned), (qseq->seqlen >> 5) + 1, seq_out); (*template_lengths)[DB_size] = qseq->seqlen; if((DB_size + 1) >= **template_ulengths) { **template_ulengths <<= 1; *template_slengths = realloc(*template_slengths, **template_ulengths * sizeof(unsigned)); *template_ulengths = realloc(*template_ulengths, **template_ulengths * sizeof(unsigned)); *template_lengths = realloc(*template_lengths, **template_ulengths * sizeof(unsigned)); if(!template_lengths || !template_slengths || !template_ulengths) { ERROR(); } } } genomicepidemiology-kma-091b8ffe66ac/compress.h0000644000175000017500000000211714157033525021116 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "hashmap.h" #include "hashmapkma.h" extern unsigned (*valuesSize)(unsigned *); HashMapKMA * compressKMA_DB(HashMap *templates, FILE *out); HashMapKMA * compressKMA_megaDB(HashMap *templates, FILE *out); void compressKMA_deconDB(HashMapKMA *finalDB, unsigned **Values); void compressKMA_deconMegaDB(HashMapKMA *finalDB, unsigned **Values); genomicepidemiology-kma-091b8ffe66ac/xml.c0000644000175000017500000001751714157033525020070 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "nw.h" #include "penalties.h" #include "pherror.h" #include "threader.h" #include "version.h" #include "xml.h" void initXML(FILE *out, const char *templatefilename, const unsigned totFrags, int argc, char **argv) { fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "\tkma\n"); fprintf(out, "\tKMA %s\n", KMA_VERSION); fprintf(out, "\tPhilip T.L.C. Clausen, Frank M. Aarestrup & Ole Lund, \"Rapid and precise alignment of raw reads against redundant databases with KMA\", BMC Bioinformatics, 2018;19:307.\n"); fprintf(out, "\t%s\n", templatefilename); fprintf(out, "\tkma-%s-%ld\n", templatefilename, time(NULL)); fprintf(out, "\t%s\n", "nucl"); fprintf(out, "\t%d\n", totFrags); fprintf(out, "\t\n"); fprintf(out, "\t\t\n"); fprintf(out, "\t\t\t%s", *argv); while(--argc) { fprintf(out, " %s", *++argv); } fprintf(out, "\n"); fprintf(out, "\t\t\n"); fprintf(out, "\t\n"); fprintf(out, "\n"); } void capXML(FILE *out) { fprintf(out, "\n"); fprintf(out, "\n"); } FILE * openInitXML(const char *filename, const char *templatefilename, const unsigned totFrags, int argc, char **argv) { FILE *fileP; if(*filename == '-' && filename[1] == '-' && filename[2] == 0) { fileP = stdout; } else { fileP = sfopen(filename, "wb"); } initXML(fileP, templatefilename, totFrags, argc, argv); return fileP; } void closeCapXML(FILE *out) { capXML(out); if(out && out != stdout) { fclose(out); } } void newIterXML(FILE *out, const int template, const int t_len, const char *template_name) { fprintf(out, "\n"); fprintf(out, "\t%d\n", template); fprintf(out, "\tQuery_%d\n", template); fprintf(out, "\t%s\n", template_name); fprintf(out, "\t%d\n", t_len); fprintf(out, "\n"); } double getEntropy(const unsigned char *aligned_assem_q, const int len) { unsigned i, *cPtr, counts[256]; unsigned char *qPtr; double p, h; if(len == 0) { return 0; } /* init counts */ cPtr = counts - 1; i = 257; while(--i) { *++cPtr = 0; } /* get counts */ qPtr = (unsigned char *) aligned_assem_q + len; i = len + 1; while(--i) { ++counts[*--qPtr]; } /* calculate entropy */ h = 0; i = 257; cPtr = counts - 1; while(--i) { if((p = *++cPtr)) { p /= len; h -= p * log2(p); } } return h; } void capIterXML(FILE *out, const int DB_size, const long unsigned seqsize, const int t_len, const int readCounts, const double p_value, const long read_score, const unsigned char *aligned_assem_q, const int len) { fprintf(out, "\n"); fprintf(out, "\t\n"); fprintf(out, "\t\t\n"); fprintf(out, "\t\t\t%d\n", DB_size); fprintf(out, "\t\t\t%ld\n", seqsize); fprintf(out, "\t\t\t%d\n", readCounts); fprintf(out, "\t\t\t%lu\n", seqsize * t_len); fprintf(out, "\t\t\t%4.1e\n", p_value * read_score); fprintf(out, "\t\t\t%4.1e\n", p_value); fprintf(out, "\t\t\t%f\n", getEntropy(aligned_assem_q, len)); fprintf(out, "\t\t\n"); fprintf(out, "\t\n"); fprintf(out, "\n"); } void hitXML(FILE *out, const int template, const unsigned char *template_name, const Aln *aligned, const AlnScore *alnStat, const Penalties *rewards, const int flag) { static volatile int Lock = 0; static int num = 0; volatile int *lock = &Lock; int i, Ms, MMs, W1s, Us, gap, pos, **d; unsigned char *t, *q; char *s, bases[6] = "ACGTN-"; /* get stats */ d = rewards->d; Ms = 0; MMs = 0; W1s = 0; Us = 0; gap = 0; pos = 0; t = aligned->t - 1; s = aligned->s - 1; q = aligned->q; i = aligned->len + 1; while(--i) { if(*++s == '_') { *s = ' '; if(*++t == 5 || *q == 5) { if(gap) { ++Us; } else { ++W1s; gap = 1; } } else { ++MMs; if(0 < d[*t][*q]) { ++pos; } gap = 1; } } else { ++Ms; ++t; if(0 < d[*t][*q]) { ++pos; } gap = 1; } *t = bases[*t]; *q = bases[*q]; ++q; } pos += W1s * (0 < rewards->W1) + Us * (0 < rewards->U); /* print stats */ lock(lock); fprintf(out, "\n"); fprintf(out, "\t%d\n", ++num); fprintf(out, "\tgnl|BL_ORD_ID|%d\n", template + 1); fprintf(out, "\t%s\n", template_name); fprintf(out, "\t%d\n", template); fprintf(out, "\t%d\n", aligned->len); fprintf(out, "\t\n"); fprintf(out, "\t\t\n"); fprintf(out, "\t\t\t1\n"); fprintf(out, "\t\t\t%d\n", aligned->score); fprintf(out, "\t\t\t%d\n", aligned->mapQ); fprintf(out, "\t\t\t%f\n", pow(10, aligned->mapQ / (-10.0))); fprintf(out, "\t\t\t%d\n", ((flag & 16) ? (aligned->end) : (aligned->start)) + 1); fprintf(out, "\t\t\t%d\n", ((flag & 16) ? (aligned->start) : (aligned->end)) + 1); fprintf(out, "\t\t\t%d\n", alnStat->pos + 1); fprintf(out, "\t\t\t%d\n", alnStat->pos + alnStat->len - alnStat->tGaps + 1); fprintf(out, "\t\t\t%d\n", aligned->start % 3); fprintf(out, "\t\t\t%d\n", alnStat->pos % 3); fprintf(out, "\t\t\t%d\n", Ms); fprintf(out, "\t\t\t%d\n", pos); fprintf(out, "\t\t\t%d\n", W1s + Us); fprintf(out, "\t\t\t%d\n", aligned->len); fprintf(out, "\t\t\t%s\n", aligned->q); fprintf(out, "\t\t\t%s\n", aligned->t); fprintf(out, "\t\t\t%s\n", aligned->s); fprintf(out, "\t\t\n"); fprintf(out, "\t\n"); fprintf(out, "\n"); unlock(lock); /* here */ /* fprintf(stdout, "%s\n", template_name); i = 0; for(i = 0; i < aligned->len; i += 60) { fprintf(stdout, "t:\t%.60s\n", aligned->t + i); fprintf(stdout, "s:\t%.60s\n", aligned->s + i); fprintf(stdout, "q:\t%.60s\n\n", aligned->q + i); } fprintf(stdout, "\n\n"); */ } genomicepidemiology-kma-091b8ffe66ac/chain.h0000644000175000017500000000304014157033525020341 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "penalties.h" #ifndef CHAIN typedef struct alnPoints AlnPoints; struct alnPoints { int size; int len; int *tStart; int *tEnd; int *qStart; int *qEnd; int *weight; int *score; int *next; Penalties *rewards; }; #define CHAIN 1 #endif /* pointer to chaining method */ extern int (*chainSeedsPtr)(AlnPoints *, int, int, int, unsigned *); extern void (*trimSeedsPtr)(AlnPoints *points, int start); /* FUNCTIONS */ AlnPoints * seedPoint_init(int size, Penalties *rewards); void seedPoint_realloc(AlnPoints *dest, int size); void seedPoint_free(AlnPoints *src); int chainSeeds(AlnPoints *points, int q_len, int t_len, int kmersize, unsigned *mapQ); int chainSeeds_circular(AlnPoints *points, int q_len, int t_len, int kmersize, unsigned *mapQ); void trimSeeds(AlnPoints *points, int start); void trimSeedsNoLead(AlnPoints *points, int start); genomicepidemiology-kma-091b8ffe66ac/qseqs.c0000644000175000017500000000261214157033525020412 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "pherror.h" #include "qseqs.h" Qseqs * setQseqs(unsigned size) { Qseqs *dest; dest = smalloc(sizeof(Qseqs)); dest->len = 0; dest->size = size; dest->seq = smalloc(size); return dest; } void destroyQseqs(Qseqs *dest) { free(dest->seq); free(dest); } void insertKmerBound(Qseqs *header, int start, int end) { int *seq; if((header->len + 2 * sizeof(int)) < header->size) { header->size = (header->len + 2 * sizeof(int)) << 1; if(!(header->seq = realloc(header->seq, header->size))) { ERROR(); } } header->seq[header->len] = 0; seq = (int *) (header->seq + header->len + 1); *seq = start; *++seq = end; header->len += (2 * sizeof(int) + 1); } genomicepidemiology-kma-091b8ffe66ac/kmeranker.h0000644000175000017500000000306114157033525021241 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "penalties.h" #ifndef KMERANKER #define KMERANKER 1; typedef struct kmerAnker KmerAnker; struct kmerAnker { int score; int weight; unsigned start; unsigned end; unsigned ties; unsigned *values; struct kmerAnker *descend; /* descending anker */ }; #endif extern KmerAnker * (*getChainTemplates)(KmerAnker*, const Penalties*, int, int*, int*, int*, char*); KmerAnker * getBestChainTemplates(KmerAnker *src, const Penalties *rewards, int kmersize, int *bests, int *Score, int *extendScore, char *include); KmerAnker * getProxiChainTemplates(KmerAnker *src, const Penalties *rewards, int kmersize, int *bests, int *Score, int *extendScore, char *include); KmerAnker * pruneAnkers(KmerAnker *V_score, int kmersize); KmerAnker * getBestAnker(KmerAnker **src, unsigned *ties); KmerAnker * getTieAnker(int stop, KmerAnker *src, int score); genomicepidemiology-kma-091b8ffe66ac/matrix.h0000644000175000017500000000221014157033525020561 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MATRIX typedef struct matrix Matrix; struct matrix { int n; int size; int **mat; }; #define MATRIX 1 #endif Matrix * matrix_init(unsigned size); Matrix * ltdMatrix_init(unsigned size); Matrix * ltdMatrix_minit(long unsigned size); void ltdMatrix_realloc(Matrix *src, unsigned size); void Matrix_destroy(Matrix *src); void Matrix_mdestroy(Matrix *src); void ltdMatrix_popArrange(Matrix *mat, unsigned pos); int ltdMatrix_add(Matrix *src); genomicepidemiology-kma-091b8ffe66ac/align.c0000644000175000017500000007621014157033525020355 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include "align.h" #include "chain.h" #include "compdna.h" #include "hashmapcci.h" #include "nw.h" #include "stdnuc.h" #include "stdstat.h" AlnScore (*leadTailAlnPtr)(Aln *, Aln *, const long unsigned*, const unsigned char*, int, int, int, const int, NWmat *) = &leadTailAln; void (*trailTailAlnPtr)(Aln *, Aln *, AlnScore *, const long unsigned *, const unsigned char *, int, int, int, int, const int, NWmat *) = &trailTailAln; AlnScore skipLeadAln(Aln *aligned, Aln *Frag_align, const long unsigned *tseq, const unsigned char *qseq, int t_e, int t_len, int q_e, const int bandwidth, NWmat *matrices) { AlnScore Stat; /* initialize */ Stat.len = 0; Stat.score = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.pos = t_e; return Stat; } AlnScore leadTailAln(Aln *aligned, Aln *Frag_align, const long unsigned *tseq, const unsigned char *qseq, int t_e, int t_len, int q_e, const int bandwidth, NWmat *matrices) { int bias, band, t_s, q_s; AlnScore Stat, NWstat; /* initialize */ Stat.len = 0; Stat.score = 0; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.pos = t_e; if(q_e) { /* get boundaries */ t_s = 0; q_s = 0; if((q_e << 1) < t_e || (q_e + bandwidth) < t_e) { // big leading template gap, cut down //t_s = t_e - MIN(bandwidth, (q_e << 1)); t_s = t_e - (q_e + (q_e < bandwidth ? q_e : bandwidth)); } else if((t_e << 1) < q_e || (t_e + bandwidth) < q_e) { // big leading query gap, cut down //q_s = q_e - MIN(bandwidth, (t_e << 1)); q_s = q_e - (t_e + (t_e < bandwidth ? t_e : bandwidth)); } /* align */ if(t_e - t_s > 0 && q_e - q_s > 0) { band = abs(t_e - t_s - q_e + q_s) + bandwidth; if(q_e - q_s <= band || t_e - t_s <= band) {// || abs(t_e - t_s - q_e - q_s) >= 32) { if(Frag_align) { NWstat = NW(tseq, qseq, -1 - (t_s == 0), t_s, t_e, q_s, q_e, Frag_align, matrices, t_len); } else { NWstat = NW_score(tseq, qseq, -1 - (t_s == 0), t_s, t_e, q_s, q_e, matrices, t_len); } } else if(Frag_align) { NWstat = NW_band(tseq, qseq, -1 - (t_s == 0), t_s, t_e, q_s, q_e, Frag_align, band, matrices, t_len); //NWstat = NW(tseq, qseq, -1 - (t_s == 0), t_s, t_e, q_s, q_e, Frag_align, matrices, t_len); } else { NWstat = NW_band_score(tseq, qseq, -1 - (t_s == 0), t_s, t_e, q_s, q_e, band, matrices, t_len); //NWstat = NW_score(tseq, qseq, -1 - (t_s == 0), t_s, t_e, q_s, q_e, matrices, t_len); } if(Frag_align) { /* trim leading gaps */ bias = 0; if(t_s == 0) { while(bias < NWstat.len && (Frag_align->t[bias] == 5 || Frag_align->q[bias] == 5)) { if(Frag_align->t[bias] == 5) { --NWstat.tGaps; ++(Frag_align->start); } else { --NWstat.qGaps; } ++bias; } NWstat.len -= bias; /*if(bias) { NWstat.score -= (W1 + (bias - 1) * U); }*/ } memcpy(aligned->t, Frag_align->t + bias, NWstat.len); memcpy(aligned->s, Frag_align->s + bias, NWstat.len); memcpy(aligned->q, Frag_align->q + bias, NWstat.len); aligned->start = q_s + Frag_align->start; } Stat.pos -= (NWstat.len - NWstat.tGaps); Stat.score = NWstat.score; Stat.len = NWstat.len; Stat.match = NWstat.match; Stat.tGaps = NWstat.tGaps; Stat.qGaps = NWstat.qGaps; } else if(aligned) { aligned->start = q_s; } } return Stat; } void skipTrailAln(Aln *aligned, Aln *Frag_align, AlnScore *Stat, const long unsigned *tseq, const unsigned char *qseq, int t_s, int t_len, int q_s, int q_len, const int bandwidth, NWmat *matrices) { if(aligned) { aligned->end = 0; Frag_align->end = 0; } } void trailTailAln(Aln *aligned, Aln *Frag_align, AlnScore *Stat, const long unsigned *tseq, const unsigned char *qseq, int t_s, int t_len, int q_s, int q_len, const int bandwidth, NWmat *matrices) { int band, bias, q_e, t_e; AlnScore NWstat; /* Get intervals in query and template to align */ q_e = q_len; t_e = t_len; if(((q_len - q_s) << 1) < (t_len - t_s) || (q_len - q_s + bandwidth) < (t_len - t_s)) { // big trailing template gap, cut down //t_e = t_s + MIN(bandwidth, ((q_len - q_s) << 1)); t_e = q_len - q_s; t_e = t_s + (t_e + (t_e < bandwidth ? t_e : bandwidth)); } else if(((t_len - t_s) << 1) < (q_len - q_s) || (t_len - t_s + bandwidth) < (q_len - q_s)) { // big leading query gap, cut down //q_e = q_s + MIN(bandwidth, ((t_len - t_s) << 1)); q_e = t_len - t_s; q_e = q_s + (q_e + (q_e < bandwidth ? q_e : bandwidth)); } /* align trailing gap */ if(t_e - t_s > 0 && q_e - q_s > 0) { band = abs(t_e - t_s - q_e + q_s) + bandwidth; if(q_e - q_s <= band || t_e - t_s <= band) {//|| abs(t_e - t_s - q_e - q_s) >= 32) { if(Frag_align) { NWstat = NW(tseq, qseq, 1 + (t_e == t_len), t_s, t_e, q_s, q_e, Frag_align, matrices, t_len); } else { NWstat = NW_score(tseq, qseq, 1 + (t_e == t_len), t_s, t_e, q_s, q_e, matrices, t_len); } } else if(Frag_align) { NWstat = NW_band(tseq, qseq, 1 + (t_e == t_len), t_s, t_e, q_s, q_e, Frag_align, band, matrices, t_len); //NWstat = NW(tseq, qseq, 1 + (t_e == t_len), t_s, t_e, q_s, q_e, Frag_align, matrices, t_len); } else { NWstat = NW_band_score(tseq, qseq, 1 + (t_e == t_len), t_s, t_e, q_s, q_e, band, matrices, t_len); } if(Frag_align) { /* trim trailing gaps */ if(t_e == t_len) { bias = NWstat.len - 1; while(bias && (Frag_align->t[bias] == 5 || Frag_align->q[bias] == 5)) { if(Frag_align->t[bias] == 5) { --NWstat.tGaps; ++(Frag_align->end); } else { --NWstat.qGaps; } --bias; } ++bias; if(bias != NWstat.len) { //NWstat.score -= (W1 + (NWstat.len - bias) * U); NWstat.len = bias; } } memcpy(aligned->t + Stat->len, Frag_align->t, NWstat.len); memcpy(aligned->s + Stat->len, Frag_align->s, NWstat.len); memcpy(aligned->q + Stat->len, Frag_align->q, NWstat.len); } Stat->score += NWstat.score; Stat->len += NWstat.len; Stat->match += NWstat.match; Stat->tGaps += NWstat.tGaps; Stat->qGaps += NWstat.qGaps; } else if(Frag_align) { Frag_align->end = 0; } if(aligned) { aligned->end = q_len - q_e + Frag_align->end; } } AlnScore KMA(const HashMapCCI *template_index, const unsigned char *qseq, int q_len, int q_start, int q_end, Aln *aligned, Aln *Frag_align, int min, int max, int mq, double scoreT, AlnPoints *points, NWmat *matrices) { const int bandwidth = 64; int i, j, k, bias, prev, start, stop, t_len, value, end, band, mem_count; int t_l, t_s, t_e, q_s, q_e, score, shifter, kmersize, U, M, *seeds, **d; long unsigned key, mask; unsigned char nuc; AlnScore Stat, NWstat; Penalties *rewards; /* Extract indexes and template sequence */ rewards = points->rewards; U = rewards->U; M = rewards->M; d = rewards->d; t_len = template_index->len; kmersize = template_index->kmerindex; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); key = 0; /* circular, skip boundaries */ if(min < max) { min = 0; max = t_len; } aligned->start = 0; aligned->end = 0; /* find seeds */ if(points->len) { mem_count = points->len; } else { mem_count = 0; i = q_start; while(i < q_end) { end = charpos(qseq, 4, i, q_len); if(end == -1) { end = q_end; } if(i < end - kmersize) { key = makeKmer(qseq, i, kmersize - 1); i += (kmersize - 1); } else { i = end + 1; } while(i < end) { key = ((key << 2) | qseq[i]) & mask; value = hashMapCCI_get_bound(template_index, key, min, max, shifter); if(value == 0) { ++i; } else if(0 < value) { i -= (kmersize - 1); /* backseed for overlapping seeds */ prev = value - 2; for(j = i - 1; 0 <= j && 0 <= prev && qseq[j] == getNuc(template_index->seq, prev); --j) { --prev; } /* get start positions */ points->qStart[mem_count] = j + 1; points->tStart[mem_count] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); i += kmersize; /* extend */ while(i < end && value < t_len && qseq[i] == getNuc(template_index->seq, value)) { ++i; ++value; } /* get end positions */ points->qEnd[mem_count] = i; points->tEnd[mem_count] = value + 1; /* calculate weight */ points->weight[mem_count] = (points->qEnd[mem_count] - points->qStart[mem_count]); ++mem_count; /* realloc seeding points */ if(mem_count == points->size) { seedPoint_realloc(points, points->size << 1); } /* update position */ if(i < end - kmersize) { key = makeKmer(qseq, i, kmersize - 1); i += (kmersize - 1); } else { i = end + 1; } } else { /* move counter back */ i -= (kmersize - 1); /* get position in hashmap */ seeds = hashMapCCI_getDubPos(template_index, key, value, shifter); /* get all mems */ bias = i; while(seeds) { /* get mem info */ k = i; /* backseed for overlapping seeds */ value = abs(*seeds); prev = value - 2; for(j = k - 1; 0 <= j && 0 <= prev && qseq[j] == getNuc(template_index->seq, prev); --j) { --prev; } /* get start positions */ points->qStart[mem_count] = j + 1; points->tStart[mem_count] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); k += kmersize; /* extend */ while(k < end && value < t_len && qseq[k] == getNuc(template_index->seq, value)) { ++k; ++value; } /* get end positions */ points->qEnd[mem_count] = k; points->tEnd[mem_count] = value + 1; /* calculate weight */ points->weight[mem_count] = (points->qEnd[mem_count] - points->qStart[mem_count]); ++mem_count; /* realloc seeding points */ if(mem_count == points->size) { seedPoint_realloc(points, points->size << 1); } if(bias < k) { bias = k; } seeds = hashMapCCI_getNextDubPos(template_index, seeds, key, min, max, shifter); } i = bias + 1; /* update position */ if(i < end - kmersize) { key = makeKmer(qseq, i, kmersize - 1); i += (kmersize - 1); } else { i = end + 1; } } } i = end + 1; } } aligned->mapQ = 0; if(mem_count) { points->len = mem_count; } else { Stat.score = 0; Stat.len = 1; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.pos = 0; aligned->s[0] = 0; aligned->len = 0; points->len = 0; return Stat; } /* get best seed chain, returns best starting point */ start = chainSeedsPtr(points, q_len, t_len, kmersize, &aligned->mapQ); score = points->score[start]; if(aligned->mapQ < mq || score < kmersize) { Stat.score = 0; Stat.len = 1; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.pos = 0; aligned->s[0] = 0; aligned->len = 0; points->len = 0; return Stat; } /* trim seeds */ trimSeedsPtr(points, start); /* align leading tail */ Stat = leadTailAlnPtr(aligned, Frag_align, template_index->seq, qseq, points->tStart[start] - 1, t_len, points->qStart[start], bandwidth, matrices); /* piece seeds together */ stop = 1; while(stop) { /* MEM */ q_s = points->qStart[start]; end = points->qEnd[start] - q_s; memcpy(aligned->t + Stat.len, qseq + q_s, end); memset(aligned->s + Stat.len, '|', end); memcpy(aligned->q + Stat.len, qseq + q_s, end); Stat.len += end; Stat.match += end; end = points->qEnd[start]; for(i = points->qStart[start]; i < end; ++i) { nuc = qseq[i]; Stat.score += d[nuc][nuc]; } /* join MEMs */ if(points->next[start]) { /* get positions between seed-extends */ q_s = points->qEnd[start]; t_s = points->tEnd[start] - 1; start = points->next[start]; /* check if next MEM is a semi match */ if(points->qStart[start] < q_s) { points->tStart[start] += (q_s - points->qStart[start]); points->qStart[start] = q_s; } t_e = points->tStart[start] - 1; if(t_e < t_s) { if(t_s <= points->tEnd[start]) { points->qStart[start] += (t_s - t_e); t_e = t_s; t_l = t_e - t_s; } else { /* circular joining */ Frag_align->pos = t_len; t_l = t_len - t_s + t_e; } } else { t_l = t_e - t_s; } q_e = points->qStart[start]; /* piece seed-extends together */ if(abs(t_l - q_e + q_s) * U > q_len * M || t_l > q_len || q_e - q_s > (q_len >> 1)) { /* gap is too big to give a positive score */ Stat.score = 0; Stat.len = 1; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; aligned->s[0] = 0; aligned->len = 0; points->len = 0; return Stat; } if((t_l > 0 || q_e - q_s > 0)) { band = abs(t_l - q_e + q_s) + bandwidth; if(q_e - q_s <= band || t_l <= band) {// || abs(t_e - t_s - q_e - q_s) >= 32) { NWstat = NW(template_index->seq, qseq, 0, t_s, t_e, q_s, q_e, Frag_align, matrices, t_len); } else { NWstat = NW_band(template_index->seq, qseq, 0, t_s, t_e, q_s, q_e, Frag_align, band, matrices, t_len); //NWstat = NW(template_index->seq, qseq, 0, t_s, t_e, q_s, q_e, Frag_align, matrices); } memcpy(aligned->t + Stat.len, Frag_align->t, NWstat.len); memcpy(aligned->s + Stat.len, Frag_align->s, NWstat.len); memcpy(aligned->q + Stat.len, Frag_align->q, NWstat.len); Stat.score += NWstat.score; Stat.len += NWstat.len; Stat.match += NWstat.match; Stat.tGaps += NWstat.tGaps; Stat.qGaps += NWstat.qGaps; } } else { stop = 0; } } /* align trailing tail */ trailTailAlnPtr(aligned, Frag_align, &Stat, template_index->seq, qseq, points->tEnd[start] - 1, t_len, points->qEnd[start], q_len, bandwidth, matrices); aligned->s[Stat.len] = 0; aligned->len = Stat.len; points->len = 0; return Stat; } AlnScore KMA_score(const HashMapCCI *template_index, const unsigned char *qseq, int q_len, int q_start, int q_end, const CompDNA *qseq_comp, int mq, double scoreT, AlnPoints *points, NWmat *matrices) { const int bandwidth = 64; int i, j, k, l, bias, prev, start, stop, t_len, value, end, band, U, M; int t_l, t_s, t_e, q_s, q_e, mem_count, score, kmersize, *seeds, **d; unsigned mapQ, shifter, cPos, iPos; long unsigned key; unsigned char nuc; AlnScore Stat, NWstat; Penalties *rewards; /* Extract indexes and template sequence */ rewards = points->rewards; U = rewards->U; M = rewards->M; d = rewards->d; t_len = template_index->len; kmersize = template_index->kmerindex; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); /* find seeds */ if(points->len) { mem_count = points->len; } else { mem_count = 0; j = q_start; for(i = 1; i <= qseq_comp->N[0]; ++i) { if(i != qseq_comp->N[0]) { end = qseq_comp->N[i] - kmersize + 1; } else { end = q_end - kmersize + 1; } while(j < end) { getKmer_macro(key, qseq_comp->seq, j, cPos, iPos, shifter); value = hashMapCCI_get(template_index, key, shifter); if(value == 0) { ++j; } else if(0 < value) { /* backseed for ambiguos seeds */ prev = value - 2; for(k = j - 1; 0 <= k && 0 <= prev && qseq[k] == getNuc(template_index->seq, prev); --k) { --prev; } /* get start positions */ points->qStart[mem_count] = k + 1; points->tStart[mem_count] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); j += kmersize; /* extend */ end += (kmersize - 1); while(j < end && value < t_len && qseq[j] == getNuc(template_index->seq, value)) { ++j; ++value; } end -= (kmersize - 1); /* get end positions */ points->qEnd[mem_count] = j; points->tEnd[mem_count] = value + 1; /* calculate weight */ points->weight[mem_count] = (points->qEnd[mem_count] - points->qStart[mem_count]); ++mem_count; /* realloc seeding points */ if(mem_count == points->size) { seedPoint_realloc(points, points->size << 1); } } else { /* get position in hashmap */ seeds = hashMapCCI_getDubPos(template_index, key, value, shifter); /* get all mems */ bias = j; while(seeds) { /* get mem info */ l = j; /* backseed for overlapping seeds */ value = abs(*seeds); prev = value - 2; for(k = l - 1; 0 <= k && 0 <= prev && qseq[k] == getNuc(template_index->seq, prev); --k) { --prev; } /* get start positions */ points->qStart[mem_count] = k + 1; points->tStart[mem_count] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); l += kmersize; /* extend */ end += (kmersize - 1); while(l < end && value < t_len && qseq[l] == getNuc(template_index->seq, value)) { ++l; ++value; } end -= (kmersize - 1); /* get end positions */ points->qEnd[mem_count] = l; points->tEnd[mem_count] = value + 1; /* calculate weight */ points->weight[mem_count] = (points->qEnd[mem_count] - points->qStart[mem_count]); ++mem_count; /* realloc seeding points */ if(mem_count == points->size) { seedPoint_realloc(points, points->size << 1); } if(bias < l) { bias = l; } seeds = hashMapCCI_getNextDubPos(template_index, seeds, key, 0, t_len, shifter); } j = bias + 1; } } j = qseq_comp->N[i] + 1; } } mapQ = 0; if(mem_count) { points->len = mem_count; } else { Stat.score = 0; Stat.len = 1; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.pos = 0; points->len = 0; return Stat; } /* get best seed chain, returns best starting point */ start = chainSeedsPtr(points, q_len, t_len, kmersize, &mapQ); score = points->score[start]; if(mapQ < mq || score < kmersize) { Stat.score = 0; Stat.len = 1; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; Stat.pos = 0; points->len = 0; return Stat; } /* align leading tail */ Stat = leadTailAlnPtr(0, 0, template_index->seq, qseq, points->tStart[start] - 1, t_len, points->qStart[start], bandwidth, matrices); /* piece seeds together */ stop = 1; while(stop) { /* MEM */ q_s = points->qStart[start]; end = points->qEnd[start] - q_s; Stat.len += end; Stat.match += end; end = points->qEnd[start]; for(i = points->qStart[start]; i < end; ++i) { nuc = qseq[i]; Stat.score += d[nuc][nuc]; } /* join MEMs */ if(points->next[start]) { /* get positions between seed-extends */ q_s = points->qEnd[start]; t_s = points->tEnd[start] - 1; start = points->next[start]; /* check if next MEM is a semi match, or a circular joining */ if(points->qStart[start] < q_s) { points->tStart[start] += (q_s - points->qStart[start]); points->qStart[start] = q_s; } t_e = points->tStart[start] - 1; if(t_e < t_s) { if(t_s <= points->tEnd[start]) { points->qStart[start] += (t_s - t_e); t_e = t_s; t_l = t_e - t_s; } else { /* circular joining */ t_l = t_len - t_s + t_e; } } else { t_l = t_e - t_s; } q_e = points->qStart[start]; /* piece seed-extends together */ if(abs(t_l - q_e + q_s) * U > q_len * M || t_l > q_len || q_e - q_s > (q_len >> 1)) { /* gap is too big to give a positive score */ Stat.score = 0; Stat.len = 1; Stat.match = 0; Stat.tGaps = 0; Stat.qGaps = 0; points->len = 0; return Stat; } if((t_l > 0 || q_e - q_s > 0)) { band = abs(t_l - q_e + q_s) + bandwidth; if(q_e - q_s <= band || t_l <= band) { NWstat = NW_score(template_index->seq, qseq, 0, t_s, t_e, q_s, q_e, matrices, t_len); } else { NWstat = NW_band_score(template_index->seq, qseq, 0, t_s, t_e, q_s, q_e, band, matrices, t_len); } Stat.score += NWstat.score; Stat.len += NWstat.len; Stat.match += NWstat.match; Stat.tGaps += NWstat.tGaps; Stat.qGaps += NWstat.qGaps; } } else { stop = 0; } } /* align trailing tail */ trailTailAlnPtr(0, 0, &Stat, template_index->seq, qseq, points->tEnd[start] - 1, t_len, points->qEnd[start], q_len, bandwidth, matrices); points->len = 0; return Stat; } int preseed(const HashMapCCI *template_index, unsigned char *qseq, int q_len) { static int exhaustive = 1; int i, shifter, kmersize, len; if(exhaustive) { exhaustive = q_len; return 0; } kmersize = template_index->kmerindex; len = template_index->len; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); for(i = 0; i < q_len; i += kmersize) { if(hashMapCCI_get_bound(template_index, makeKmer(qseq, i, kmersize), 0, len, shifter)) { return 0; } } return i; } void intcpy(int *dest, int *src, int size) { *dest = *src; while(--size) { *++dest = *++src; } } int anker_rc(const HashMapCCI *template_index, unsigned char *qseq, int q_len, int q_start, int q_end, AlnPoints *points) { static int one2one = 0; int i, j, k, rc, end, score, score_r, value, t_len, prev, bias; int bestScore, mem_count, totMems, shifter, kmersize, *seeds; long unsigned key, mask; if(!template_index) { one2one = q_len; return 0; } t_len = template_index->len; kmersize = template_index->kmerindex; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); key = 0; /* find seeds */ bestScore = 0; score = 0; score_r = 0; mem_count = 0; totMems = 0; points->len = 0; for(rc = 0; rc < 2; ++rc) { if(rc) { strrc(qseq, q_len); score = score_r; points->len = mem_count; i = q_len - q_start; q_start = q_len - q_end; q_end = i; i = q_start ? q_start : preseed(template_index, qseq, q_end - q_start); } else if(q_start) { i = q_start; } else { i = preseed(template_index, qseq, q_end - q_start); } score_r = 0; mem_count = 0; while(i < q_end) { end = charpos(qseq, 4, i, q_len); if(end == -1) { end = q_end; } if(i < end - kmersize) { key = makeKmer(qseq, i, kmersize - 1); i += (kmersize - 1); } else { i = end + 1; } while(i < end) { key = ((key << 2) | qseq[i]) & mask; value = hashMapCCI_get(template_index, key, shifter); if(value == 0) { ++i; } else if(0 < value) { i -= (kmersize - 1); /* backseed for ambiguos seeds */ prev = value - 2; for(j = i - 1; 0 <= j && 0 <= prev && qseq[j] == getNuc(template_index->seq, prev); --j) { --prev; ++score_r; } /* get start positions */ points->qStart[totMems] = j + 1; points->tStart[totMems] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); i += kmersize; score_r += kmersize; /* extend */ while(i < end && value < t_len && qseq[i] == getNuc(template_index->seq, value)) { ++i; ++value; ++score_r; } /* get end positions */ points->qEnd[totMems] = i; points->tEnd[totMems] = value + 1; /* calculate weight */ points->weight[totMems] = (points->tEnd[totMems] - points->tStart[totMems]); ++mem_count; ++totMems; /* realloc seeding points */ if(totMems == points->size) { seedPoint_realloc(points, points->size << 1); } /* update position */ if(i < end - kmersize) { key = makeKmer(qseq, i, kmersize - 1); i += (kmersize - 1); } else { i = end + 1; } } else { /* move counter back */ i -= (kmersize - 1); score_r += kmersize; /* get position in hashmap */ seeds = hashMapCCI_getDubPos(template_index, key, value, shifter); /* get all mems */ bias = i; while(seeds) { /* get mem info */ k = i; /* backseed for overlapping seeds */ value = abs(*seeds); prev = value - 2; for(j = k - 1; 0 <= j && 0 <= prev && qseq[j] == getNuc(template_index->seq, prev); --j) { --prev; } /* get start positions */ points->qStart[totMems] = j + 1; points->tStart[totMems] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); k += kmersize; /* extend */ while(k < end && value < t_len && qseq[k] == getNuc(template_index->seq, value)) { ++k; ++value; } /* get end positions */ points->qEnd[totMems] = k; points->tEnd[totMems] = value + 1; /* calculate weight */ points->weight[totMems] = (points->qEnd[totMems] - points->qStart[totMems]); ++mem_count; ++totMems; /* realloc seeding points */ if(totMems == points->size) { seedPoint_realloc(points, points->size << 1); } if(bias < k) { bias = k; } seeds = hashMapCCI_getNextDubPos(template_index, seeds, key, 0, t_len, shifter); } /* add best anker score */ score_r += (bias - i); i = bias + 1; /* update position */ if(i < end - kmersize) { key = makeKmer(qseq, i, kmersize - 1); i += (kmersize - 1); } else { i = end + 1; } } } i = end + 1; } if(bestScore < score_r) { bestScore = score_r; } } if(one2one && bestScore < kmersize && bestScore * kmersize < (q_len - kmersize - bestScore)) { bestScore = 0; points->len = 0; } else if(bestScore == score) { strrc(qseq, q_len); } else { /* move mems down */ if(points->len) { intcpy(points->tStart, points->tStart + points->len, mem_count); intcpy(points->tEnd, points->tEnd + points->len, mem_count); intcpy(points->qStart, points->qStart + points->len, mem_count); intcpy(points->qEnd, points->qEnd + points->len, mem_count); intcpy(points->weight, points->weight + points->len, mem_count); } points->len = mem_count; } return bestScore; } int anker_rc_comp(const HashMapCCI *template_index, unsigned char *qseq, unsigned char *qseq_r, CompDNA *qseq_comp, CompDNA *qseq_r_comp, int q_start, int q_end, AlnPoints *points) { static int one2one = 0; int i, j, k, rc, end, score, score_r, value, t_len, q_len, prev; int bestScore, mem_count, totMems, shifter, kmersize, bias, *Ns, *seeds; unsigned cPos, iPos; long unsigned key, mask, *seq; if(!template_index) { one2one = *((int *)(qseq_r)); return 0; } q_len = qseq_comp->seqlen; t_len = template_index->len; kmersize = template_index->kmerindex; shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); key = 0; /* find seeds */ bestScore = 0; score = 0; score_r = 0; mem_count = 0; totMems = 0; points->len = 0; seq = qseq_comp->seq; Ns = qseq_comp->N; Ns[*Ns] = q_len; for(rc = 0; rc < 2; ++rc) { if(rc) { qseq = qseq_r; seq = qseq_r_comp->seq; score = score_r; points->len = mem_count; Ns = qseq_r_comp->N; Ns[*Ns] = q_len; i = q_len - q_start; q_start = q_len - q_end; q_end = i; i = q_start; } else if(q_start) { i = q_start; } else { i = preseed(template_index, qseq, q_end - q_start); } score_r = 0; mem_count = 0; while(i < q_end) { end = *++Ns - kmersize + 1; while(i < end) { getKmer_macro(key, seq, i, cPos, iPos, shifter); value = hashMapCCI_get(template_index, key, shifter); if(value == 0) { ++i; } else if(0 < value) { /* backseed for ambiguos seeds */ prev = value - 2; for(j = i - 1; 0 <= j && 0 <= prev && qseq[j] == getNuc(template_index->seq, prev); --j) { --prev; ++score_r; } /* get start positions */ points->qStart[totMems] = j + 1; points->tStart[totMems] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); i += kmersize; score_r += kmersize; /* extend */ while(i < end && value < t_len && qseq[i] == getNuc(template_index->seq, value)) { ++i; ++value; ++score_r; } /* get end positions */ points->qEnd[totMems] = i; points->tEnd[totMems] = value + 1; /* calculate weight */ points->weight[totMems] = (points->tEnd[totMems] - points->tStart[totMems]); ++mem_count; ++totMems; /* realloc seeding points */ if(totMems == points->size) { seedPoint_realloc(points, points->size << 1); } /* update position */ ++i; } else { score_r += kmersize; /* get position in hashmap */ seeds = hashMapCCI_getDubPos(template_index, key, value, shifter); /* get all mems */ bias = i; while(seeds) { /* get mem info */ k = i; /* backseed for overlapping seeds */ value = abs(*seeds); prev = value - 2; for(j = k - 1; 0 <= j && 0 <= prev && qseq[j] == getNuc(template_index->seq, prev); --j) { --prev; } /* get start positions */ points->qStart[totMems] = j + 1; points->tStart[totMems] = prev + 2; /* skip k-mer bases */ value += (kmersize - 1); k += kmersize; /* extend */ while(k < end && value < t_len && qseq[k] == getNuc(template_index->seq, value)) { ++k; ++value; } /* get end positions */ points->qEnd[totMems] = k; points->tEnd[totMems] = value + 1; /* calculate weight */ points->weight[totMems] = (points->qEnd[totMems] - points->qStart[totMems]); ++mem_count; ++totMems; /* realloc seeding points */ if(totMems == points->size) { seedPoint_realloc(points, points->size << 1); } if(bias < k) { bias = k; } seeds = hashMapCCI_getNextDubPos(template_index, seeds, key, 0, t_len, shifter); } /* add best anker score */ score_r += (bias - i); i = bias + 1; } } i = end + kmersize; } if(bestScore < score_r) { bestScore = score_r; } } if(one2one && bestScore < kmersize && bestScore * kmersize < (q_len - kmersize - bestScore)) { bestScore = 0; points->len = 0; } else if(bestScore == score) { return bestScore; } else { /* move mems down */ if(points->len) { intcpy(points->tStart, points->tStart + points->len, mem_count); intcpy(points->tEnd, points->tEnd + points->len, mem_count); intcpy(points->qStart, points->qStart + points->len, mem_count); intcpy(points->qEnd, points->qEnd + points->len, mem_count); intcpy(points->weight, points->weight + points->len, mem_count); } points->len = mem_count; return -bestScore; } return bestScore; } genomicepidemiology-kma-091b8ffe66ac/db.c0000644000175000017500000001250314157033525017643 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "db.h" #include "hashmapkma.h" #include "pherror.h" #include "stdstat.h" void dbInfo(char *filename) { const char bases[6] = "ACGTN-"; int i, filename_len, min, max, index; unsigned *values, *value_index; short unsigned *values_s; long unsigned ntcount, prefix, ntax, v_index, n, size; long unsigned *value_index_l; double mean, var, tmp; char Prefix[33]; FILE *dbfile; HashMapKMA *templates; /* print DB name */ fprintf(stdout, "DB:\t%s\n", filename); /* get # nucleotides */ filename_len = strlen(filename); strcpy(filename + filename_len, ".seq.b"); dbfile = sfopen(filename, "rb"); fseek(dbfile, 0, SEEK_END); ntcount = 4 * ftell(dbfile); fclose(dbfile); filename[filename_len] = 0; fprintf(stdout, "# nucleotides:\t%lu\n", ntcount); /* load database */ strcpy(filename + filename_len, ".comp.b"); dbfile = sfopen(filename, "rb" ); templates = smalloc(sizeof(HashMapKMA)); if(hashMapKMA_load(templates, dbfile, filename) == 1) { fprintf(stderr, "Wrong format of DB.\n"); exit(1); } fclose(dbfile); filename[filename_len] = 0; /* get basic statistics */ fprintf(stdout, "# templates:\t%d\n", templates->DB_size); fprintf(stdout, "k:\t%d\n", templates->kmersize); /* get prefix */ if(templates->prefix_len) { prefix = templates->prefix; i = templates->prefix_len; Prefix[i] = 0; while(i--) { Prefix[i] = bases[prefix & 3]; prefix >>= 2; } fprintf(stderr, "prefix:\t%s\n", Prefix); } else if(templates->prefix != 0) { fprintf(stderr, "prefix:\t-\n"); } fprintf(stdout, "# uniq k-mers:\t%lu\n", templates->n); fprintf(stdout, "k-mer fraqtion covered:\t%f\n", templates->n / power(4, templates->kmersize)); fprintf(stdout, "inferred tax size:\t%lu\n", templates->v_index); /* get number of unique inferred tax */ ntax = 0; v_index = templates->v_index; if(templates->DB_size < USHRT_MAX) { values_s = templates->values_s; while(v_index) { ++ntax; i = *values_s + 1; v_index -= i; values_s += i; } } else { values = templates->values; while(v_index) { ++ntax; i = *values + 1; v_index -= i; values += i; } } fprintf(stderr, "# inferred taxids:\t%lu\n", ntax); /* get min, max, mean and variance of k-mer uniqueness */ if((templates->size - 1) == templates->mask) { if(templates->v_index <= UINT_MAX) { value_index = templates->exist; value_index_l = 0; } else { value_index = 0; value_index_l = templates->exist_l; } } else { if(templates->n <= UINT_MAX) { value_index = templates->value_index; value_index_l = 0; } else { value_index = 0; value_index_l = templates->value_index_l; } } if(templates->DB_size < USHRT_MAX) { values = 0; values_s = templates->values_s; } else { values = templates->values; values_s = 0; } n = templates->n; size = n; min = templates->DB_size; max = 1; mean = 0; var = 0; while(size) { index = value_index ? *value_index++ : *value_index_l++; if(index != 1) { index = values ? values[index] : values_s[index]; if(index < min) { min = index; } if(max < index) { max = index; } mean += index; /* avoid overflow on var */ tmp = index * index; tmp /= n; var += tmp; --size; } } mean /= n; var -= mean * mean; fprintf(stderr, "k-mer co-occurence var:\t%f\n", var); fprintf(stderr, "k-mer co-occurence mean:\t%f\n", mean); fprintf(stderr, "k-mer co-occurence min:\t%d\n", min); fprintf(stderr, "k-mer co-occurence max:\t%d\n", max); } static void helpMessage(int exeStatus) { FILE *helpOut; if(exeStatus == 0) { helpOut = stdout; } else { helpOut = stderr; } fprintf(helpOut, "# KMA db gives statistics on a KMA database\n"); fprintf(helpOut, "# Options are:\t\tDesc:\t\t\t\t\tRequirements:\n"); fprintf(helpOut, "#\n"); fprintf(helpOut, "#\t-t_db\t\tTemplate DB\t\t\t\tREQUIRED\n"); fprintf(helpOut, "#\t-h\t\tShows this help message\n"); fprintf(helpOut, "#\n"); exit(exeStatus); } int db_main(int argc, char *argv[]) { unsigned args; char *filename; /* set defaults */ filename = 0; args = 1; while(args < argc) { if(strcmp(argv[args], "-t_db") == 0) { if(++args < argc) { filename = smalloc(strlen(argv[args]) + 64); strcpy(filename, argv[args]); } } else if(strcmp(argv[args], "-h") == 0) { helpMessage(0); } else { fprintf(stderr, " Invalid option:\t%s\n", argv[args]); fprintf(stderr, " Printing help message:\n"); helpMessage(1); } ++args; } if(!filename) { fprintf(stderr, "Insuffient amount of arguments handed!!!\n"); helpMessage(1); } dbInfo(filename); return 0; } genomicepidemiology-kma-091b8ffe66ac/kma_shm.c0000644000175000017500000000146514157033525020702 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "shm.h" int main(int argc, char *argv[]) { return shm_main(argc, argv); } genomicepidemiology-kma-091b8ffe66ac/update.c0000644000175000017500000002005714157033525020543 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "hashmapkma.h" #include "pherror.h" #include "stdnuc.h" #include "update.h" unsigned convertLength_014to015(char *filename) { unsigned size, file_len; int *lengths; FILE *file; file_len = strlen(filename); strcat(filename, ".length.b"); file = sfopen(filename, "rb+"); filename[file_len] = 0; sfread(&size, sizeof(unsigned), 1, file); lengths = smalloc(3 * size * sizeof(unsigned)); file_len = fread(lengths, sizeof(unsigned), 3 * size, file); fseek(file, sizeof(unsigned), SEEK_SET); if(file_len == size) { file_len = 0; } else if(file_len == 2 * size) { fprintf(stderr, "DB is old.\n"); fprintf(stderr, "It will only work for \"-Sparse\" mapping!!!\n"); fwrite(lengths, sizeof(unsigned), size, file); fwrite(lengths, sizeof(unsigned), 2 * size, file); file_len = 0; } else if(file_len == 3 * size) { fwrite(lengths + 2 * size, sizeof(unsigned), size, file); fwrite(lengths, sizeof(unsigned), 2 * size, file); file_len = 1; } else { fprintf(stderr, "DB is malformed.\n"); exit(1); } fclose(file); return file_len; } int hashMapKMA_014to015(char *filename, unsigned prefix) { unsigned i, tmp, size, kmersize, seqsize, file_len, shifter, DB_size; long unsigned mask, *seq; FILE *file; HashMapKMA *dest; /* rm filename.b */ file_len = strlen(filename); strcat(filename, ".b"); remove(filename); filename[file_len] = 0; /* load DB */ strcat(filename, ".comp.b"); file = sfopen(filename, "rb"); filename[file_len] = 0; /* load sizes */ dest = smalloc(sizeof(HashMapKMA)); dest->n = 0; dest->size = 0; sfread(&DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); kmersize = dest->kmersize; mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); shifter = sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1); /* load changed size */ sfread(&tmp, sizeof(unsigned), 1, file); dest->n = tmp; sfread(&seqsize, sizeof(unsigned), 1, file); //seq size sfread(&tmp, sizeof(unsigned), 1, file); dest->v_index = tmp; sfread(&tmp, sizeof(unsigned), 1, file); dest->null_index = tmp; /* make checks */ if(dest->size < dest->n || dest->n == 0) { fprintf(stderr, "DB is not of version 0.14\n"); exit(1); } /* load arrays */ dest->exist = smalloc(dest->size * sizeof(unsigned)); if(dest->size != fread(dest->exist, sizeof(unsigned), dest->size, file)) { return 1; } if(mask != (dest->size - 1)) { seq = smalloc(seqsize * sizeof(long unsigned)); if(seqsize != fread(seq, sizeof(long unsigned), seqsize, file)) { return 1; } } else { seq = 0; } dest->values = smalloc(dest->v_index * sizeof(int)); if(dest->v_index != fread(dest->values, sizeof(int), dest->v_index, file)) { return 1; } if(mask != (dest->size - 1)) { dest->key_index = smalloc((dest->n + 1) * sizeof(unsigned)); if((dest->n + 1) != fread(dest->key_index, sizeof(unsigned), dest->n + 1, file)) { return 1; } dest->value_index = smalloc(dest->n * sizeof(unsigned)); if(dest->n != fread(dest->value_index, sizeof(unsigned), dest->n, file)) { return 1; } } /* convert to new format */ /* change prefix if sparse - */ if(prefix && dest->prefix_len == 0) { dest->prefix = 1; } strcat(filename, ".comp.b"); file = sfopen(filename, "wb"); filename[file_len] = 0; sfwrite(&DB_size, sizeof(unsigned), 1, file); sfwrite(&dest->kmersize, sizeof(unsigned), 1, file); sfwrite(&dest->prefix_len, sizeof(unsigned), 1, file); sfwrite(&dest->prefix, sizeof(long unsigned), 1, file); sfwrite(&dest->size, sizeof(long unsigned), 1, file); sfwrite(&dest->n, sizeof(long unsigned), 1, file); sfwrite(&dest->v_index, sizeof(long unsigned), 1, file); sfwrite(&dest->null_index, sizeof(long unsigned), 1, file); /* exist */ cfwrite(dest->exist, sizeof(unsigned), dest->size, file); /* values */ if(DB_size < USHRT_MAX) { dest->values_s = (short unsigned *)(dest->values); for(i = 0; i < dest->v_index; ++i) { dest->values_s[i] = dest->values[i]; } size = sizeof(short unsigned); } else { size = sizeof(unsigned); } cfwrite(dest->values, size, dest->v_index, file); free(dest->values); if(mask == (dest->size - 1)) { return 0; } if(dest->kmersize <= 16) { cfwrite(dest->key_index, sizeof(unsigned), dest->n + 1, file); } else { dest->key_index_l = realloc(dest->key_index, (dest->n + 1) * sizeof(long unsigned)); if(dest->key_index_l) { dest->key_index = (unsigned *)(dest->key_index_l); } else { ERROR(); } i = dest->n + 1; while(i--) { dest->key_index_l[i] = getKmer(seq, dest->key_index[i], shifter); } cfwrite(dest->key_index_l, sizeof(long unsigned), dest->n + 1, file); free(seq); } free(dest->key_index); /* value_index */ cfwrite(dest->value_index, sizeof(unsigned), dest->n, file); return 0; } int index_014to015(char *filename) { unsigned prefix, file_len, returner; FILE *file; file_len = strlen(filename); /* change prefix if sparse - */ prefix = convertLength_014to015(filename); returner = hashMapKMA_014to015(filename, prefix); /* check for deCon */ strcat(filename, ".decon.b"); file = fopen(filename, "rb"); if(file) { fclose(file); /* change filename to: "filename.decon" */ filename[file_len + 6] = 0; returner += hashMapKMA_014to015(filename, prefix); } filename[file_len] = 0; return returner; } static void helpMessage(int exeStatus) { FILE *helpOut; if(exeStatus == 0) { helpOut = stdout; } else { helpOut = stderr; } fprintf(helpOut, "# KMA_update syncronises kma-indexes to the needed version.\n"); fprintf(helpOut, "# Options are:\t\tDesc:\t\t\t\t\tRequirements:\n"); fprintf(helpOut, "#\n"); fprintf(helpOut, "#\t-t_db\t\tTemplate DB\t\t\t\tREQUIRED\n"); fprintf(helpOut, "#\t-v\t\t[XXYY], from version major version XX\n#\t\t\tto major version YY. Use minor version,\n#\t\t\tif major version is 0.\t\t\tREQUIRED\n"); fprintf(helpOut, "#\t-h\t\tShows this help message\n"); fprintf(helpOut, "#\n"); exit(exeStatus); } int update_main(int argc, char *argv[]) { unsigned args, version; char *filename, *error; /* set defaults */ filename = 0; version = 0; args = 1; while(args < argc) { if(strcmp(argv[args], "-t_db") == 0) { if(++args < argc) { filename = smalloc(strlen(argv[args]) + 64); strcpy(filename, argv[args]); } } else if(strcmp(argv[args], "-v") == 0) { if(++args < argc) { version = strtoul(argv[args], &error, 10); if(*error != 0) { fprintf(stderr, " Invalid version specified.\n"); exit(1); } } } else if(strcmp(argv[args], "-h") == 0) { helpMessage(0); } else { fprintf(stderr, " Invalid option:\t%s\n", argv[args]); fprintf(stderr, " Printing help message:\n"); helpMessage(1); } ++args; } if(!filename || !version) { fprintf(stderr, "Insuffient amount of arguments handed!!!\n"); } else if(version == 1415) { if(index_014to015(filename)) { fprintf(stderr, "Conversion error.\n"); exit(1); } } else { fprintf(stderr, "Invalid version swifting specified.\n"); fprintf(stderr, "Valid conversions:\n"); fprintf(stderr, "\t%d\t%.2f -> %.2f\n", 1415, 0.14, 0.15); return 2; } return 0; } genomicepidemiology-kma-091b8ffe66ac/hashmap.c0000644000175000017500000001516214157033525020703 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "hashmap.h" #include "hashtable.h" #include "pherror.h" int (*hashMap_add)(HashMap *, long unsigned, unsigned); unsigned * (*hashMapGet)(HashMap *, long unsigned); void (*addUniqueValues)(HashMap *, long unsigned, unsigned *); unsigned * (*updateValuePtr)(unsigned *, unsigned); HashMap * hashMap_initialize(long unsigned size, unsigned kmersize) { HashMap *src; src = smalloc(sizeof(HashMap)); src->size = size; src->n = 0; src->mask = 0; src->mask = (~src->mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); src->kmersize = kmersize; src->prefix_len = 0; src->prefix = 0; src->DB_size = 1; if((size - 1) == src->mask) { src->table = 0; src->values = calloc(src->size, sizeof(unsigned *)); if(!src->values) { ERROR(); } } else { src->values = 0; src->table = calloc(src->size, sizeof(HashTable *)); if(!src->table) { ERROR(); } } /* masking */ --src->size; return src; } int megaMap_addKMA(HashMap *templates, long unsigned key, unsigned value) { unsigned *values; values = templates->values[key]; if(values == 0) { templates->values[key] = updateValuePtr(0, value); ++templates->n; return 1; } else if((values = updateValuePtr(values, value))) { templates->values[key] = values; return 1; } return 0; } unsigned * megaMap_getValue(HashMap *templates, long unsigned key) { return templates->values[key]; } void hashMap2megaMap(HashMap *templates, HashTable *table) { HashTable *node, *next; templates->table = 0; templates->values = calloc(templates->size, sizeof(unsigned *)); if(!templates->values) { ERROR(); } --templates->size; /* convert table */ for(node = table; node != 0; node = next) { next = node->next; /* move values */ templates->values[node->key] = node->value; /* clean */ free(node); } /* clean */ templates->table = 0; /* set pointers */ hashMap_add = &megaMap_addKMA; hashMapGet = &megaMap_getValue; } unsigned * updateValue(unsigned *values, unsigned value) { if(!values) { values = smalloc(2 * sizeof(unsigned)); values[0] = 1; values[1] = value; } else if(values[*values] == value) { return 0; } else { values[0]++; values = realloc(values, (values[0] + 1) * sizeof(unsigned)); if(!values) { ERROR(); } values[*values] = value; } return values; } unsigned * updateShortValue(unsigned *valuesOrg, unsigned value) { short unsigned *values; values = (short unsigned *)(valuesOrg); if(!values) { values = smalloc(2 * sizeof(short unsigned)); values[0] = 1; values[1] = value; } else if(values[*values] == value) { return 0; } else { values[0]++; values = realloc(values, (values[0] + 1) * sizeof(short unsigned)); if(!values) { ERROR(); } values[*values] = value; } valuesOrg = (unsigned *)(values); return valuesOrg; } int hashMap_addKMA(HashMap *templates, long unsigned key, unsigned value) { unsigned *values; long unsigned index; HashTable *node, *next, *table; index = key & templates->size; /* check if key exists */ for(node = templates->table[index]; node != 0; node = node->next) { if(key == node->key) { if((values = updateValuePtr(node->value, value))) { node->value = values; return 1; } else { return 0; } } } /* new value check if there is space */ if(templates->n == templates->size) { ++templates->size; /* link table */ table = 0; index = templates->size; while(index--) { for(node = templates->table[index]; node != 0; node = next) { next = node->next; node->next = table; table = node; } } free(templates->table); /* check for megamap */ templates->size <<= 1; if((templates->size - 1) == templates->mask) { hashMap2megaMap(templates, table); return megaMap_addKMA(templates, key, value); } /* reallocate */ templates->table = calloc(templates->size, sizeof(HashTable)); if(!templates->table) { ERROR(); } --templates->size; for(node = table; node != 0; node = next) { next = node->next; index = node->key & templates->size; node->next = templates->table[index]; templates->table[index] = node; } index = key & templates->size; } /* add new value */ node = smalloc(sizeof(HashTable)); /* key */ node->key = key; /* value */ node->value = updateValuePtr(0, value); /* push it */ node->next = templates->table[index]; templates->table[index] = node; ++templates->n; return 1; } unsigned * hashMapGetValue(HashMap *templates, long unsigned key) { HashTable *node; for(node = templates->table[key & templates->size]; node != 0; node = node->next) { if(key == node->key) { return node->value; } } return 0; } void hashMap_addUniqueValues(HashMap *dest, long unsigned key, unsigned *values) { long unsigned index; HashTable *node; node = smalloc(sizeof(HashTable)); node->key = key; node->value = values; index = key & dest->size; node->next = dest->table[index]; dest->table[index] = node; dest->n++; } void megaMap_addUniqueValues(HashMap *dest, long unsigned key, unsigned *values) { dest->values[key] = values; dest->n++; } unsigned * HU2U(unsigned *values) { int i; short unsigned *hu_values; hu_values = (short unsigned *)(values); values = realloc(values, (hu_values[0] + 1) * sizeof(unsigned)); if(!values) { ERROR(); } else { hu_values = (short unsigned *)(values); } i = *hu_values + 1; while(i--) { values[i] = hu_values[i]; } return values; } void convertToU(HashMap *templates) { long unsigned index; HashTable *node; /* convert values */ index = templates->size + 1; if(templates->table) { while(index--) { for(node = templates->table[index]; node != 0; node = node->next) { node->value = HU2U(node->value); } } } else { while(index--) { if(templates->values[index]) { templates->values[index] = HU2U(templates->values[index]); } } } /* set pointers */ updateValuePtr = &updateValue; } genomicepidemiology-kma-091b8ffe66ac/valueshash.c0000644000175000017500000000637514157033525021433 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "pherror.h" #include "valueshash.h" long unsigned (*valuesKeyPtr)(unsigned *, int); int (*cmpValuesPtr)(unsigned *, unsigned *, unsigned); ValuesHash * initialize_hashValues(long unsigned size, int DB_size) { ValuesHash *dest; dest = smalloc(sizeof(ValuesHash)); dest->n = 0; dest->size = size; dest->DB_size = DB_size; dest->table = calloc(size, sizeof(ValuesTable *)); if(!dest->table) { ERROR(); } return dest; } void valuesHash_destroy(ValuesHash *src) { long unsigned i; ValuesTable *node, *next; i = src->size; while(i--) { for(node = src->table[i]; node != 0; node = next) { next = node->next; free(node); } } free(src->table); free(src); } long unsigned valuesKey(unsigned *values, int DB_size) { unsigned i; long unsigned key; key = 0; for(i = 0; i <= *values; ++i) { key = key * DB_size + values[i]; } return key; } long unsigned huValuesKey(unsigned *valuesOrg, int DB_size) { unsigned i; long unsigned key; short unsigned *values; values = (short unsigned *)(valuesOrg); key = 0; for(i = 0; i <= *values; ++i) { key = key * DB_size + values[i]; } return key; } unsigned uSize(unsigned *values) { return *values + 1; } unsigned huSize(unsigned *valuesOrg) { short unsigned *values; values = (short unsigned *)(valuesOrg); return *values + 1; } int cmpValues(unsigned *s1, unsigned *s2, unsigned len) { if(len == 0) { return 1; } while(len--) { if(s1[len] != s2[len]) { return 0; } } return 1; } int cmpHuValues(unsigned *s1_org, unsigned *s2_org, unsigned len_org) { short unsigned *s1, *s2, len; len = len_org; --len; if(len == 0) { return 1; } s1 = (short unsigned *)(s1_org); s2 = (short unsigned *)(s2_org); while(len--) { if(s1[len] != s2[len]) { return 0; } } return 1; } long unsigned valuesHash_add(ValuesHash *src, unsigned *newValues, long unsigned v_index) { /* return 0 if values are new, else return first index of seen value */ unsigned *values; long unsigned index; ValuesTable *node; /* get index */ index = valuesKeyPtr(newValues, src->DB_size) % src->size; /* search for values */ for(node = src->table[index]; node != 0; node = node->next) { values = node->values; if(*values == *newValues && cmpValuesPtr(values + 1, newValues + 1, newValues[0])) { // Value exists return node->v_index; } } /* new values */ ++src->n; node = smalloc(sizeof(ValuesTable)); node->v_index = v_index; node->values = newValues; node->next = src->table[index]; src->table[index] = node; return v_index; } genomicepidemiology-kma-091b8ffe66ac/hashmapkmers.h0000644000175000017500000000245414157033525021752 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HASHMAPKMERS typedef struct hashTable_kmers HashTable_kmers; typedef struct hashMap_kmers HashMap_kmers; struct hashTable_kmers { long unsigned key; int value; struct hashTable_kmers *next; }; struct hashMap_kmers { unsigned size; unsigned n; struct hashTable_kmers **table; }; #define HASHMAPKMERS 1 #endif void hashMap_kmers_initialize(HashMap_kmers *dest, unsigned newSize); void reallocHashMap_kmers(HashMap_kmers *dest); void hashMap_kmers_CountIndex(HashMap_kmers *dest, long unsigned key); int hashMap_CountKmer(HashMap_kmers *dest, long unsigned key); void emptyHash(HashMap_kmers *dest); genomicepidemiology-kma-091b8ffe66ac/seqparse.h0000644000175000017500000000235514157033525021112 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "filebuff.h" #include "qseqs.h" /* determine format */ int openAndDetermine(FileBuff *inputfile, char *filename); /* get entry from fastafile */ int FileBuffgetFsa(FileBuff *src, Qseqs *header, Qseqs *qseq, char *trans); int FileBuffgetFsaSeq(FileBuff *src, Qseqs *qseq, char *trans); /* get entry from fastq file */ int FileBuffgetFq(FileBuff *src, Qseqs *header, Qseqs *qseq, Qseqs *qual, char *trans); int FileBuffgetFqSeq(FileBuff *src, Qseqs *qseq, Qseqs *qual, char *trans); /* get phred scale */ int getPhredFileBuff(FileBuff *dest); genomicepidemiology-kma-091b8ffe66ac/kmers.c0000644000175000017500000001743114157033525020404 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include "ankers.h" #include "compdna.h" #include "hashmapkma.h" #include "kmapipe.h" #include "kmers.h" #include "kmmap.h" #include "penalties.h" #include "pherror.h" #include "qseqs.h" #include "savekmers.h" #include "spltdb.h" #ifndef _WIN32 #include #include #include #else typedef int key_t; #define ftok(charPtr, integer) (0) #define shmget(key, size, permission) ((size != 0) ? (-1) : (-key)) #define shmat(shmid, NULL_Ptr, integer) (NULL) #define shmdt(dest) fprintf(stderr, "sysV not available on Windows.\n") #define shmctl(shmid, cmd, buf) fprintf(stderr, "sysV not available on Windows.\n") #endif int save_kmers_batch(char *templatefilename, char *exePrev, unsigned shm, int thread_num, const int exhaustive, Penalties *rewards, FILE *out, int sam, int minlen, double mrs, double coverT) { int i, file_len, shmid, deCon, *bestTemplates, *template_lengths; FILE *inputfile, *templatefile; time_t t0, t1; key_t key; HashMapKMA *templates; KmerScan_thread *threads, *thread; /* open pipe */ //inputfile = popen(exePrev, "r"); inputfile = kmaPipe(exePrev, "rb", 0, 0); if(!inputfile) { ERROR(); } t0 = clock(); /* do not output unmapped sam reads */ if(sam != 1 || out == stdout) { sam = 0; } /* load hashMap */ file_len = strlen(templatefilename); if((deCon = deConPrintPtr == deConPrint)) { strcat(templatefilename, ".decon.comp.b"); } else { strcat(templatefilename, ".comp.b"); } templatefile = sfopen(templatefilename, "rb" ); templates = smalloc(sizeof(HashMapKMA)); hashMap_get = &hashMap_getGlobal; if((shm & 1) || (deCon && (shm & 2))) { hashMapKMA_load_shm(templates, templatefile, templatefilename); } else if(shm & 32) { hashMapKMAmmap(templates, templatefile); } else { if(hashMapKMA_load(templates, templatefile, templatefilename) == 1) { fprintf(stderr, "Wrong format of DB.\n"); exit(1); } } templatefilename[file_len] = 0; fclose(templatefile); /* check if DB is sparse */ if(templates->prefix_len != 0 || templates->prefix != 0) { /* set pointers to sparse detection */ if(printPtr != &print_ankers_spltDB) { printPtr = &print_ankers_Sparse; } else { printPtr = &print_ankers_Sparse_spltDB; } if(deConPrintPtr != &deConPrint) { deConPrintPtr = printPtr; } if(templates->prefix_len == 0 && get_kmers_for_pair_ptr != &get_kmers_for_pair_count) { /* here */ /* if(kmerScan == &save_kmers) { kmerScan = &save_kmers_pseuodeSparse; } else { kmerScan = &save_kmers_sparse_chain; } */ kmerScan = &save_kmers_pseuodeSparse; get_kmers_for_pair_ptr = &get_kmers_for_pair_pseoudoSparse; } else { /* here */ /* if(kmerScan == &save_kmers) { kmerScan = &save_kmers_Sparse; } else { kmerScan = &save_kmers_sparse_chain; } */ kmerScan = &save_kmers_Sparse; get_kmers_for_pair_ptr = &get_kmers_for_pair_Sparse; } } /* allocate scoring arrays */ if(printPtr == &print_ankers_spltDB || printPtr == &print_ankers_Sparse_spltDB) { printPtr(0, 0, thread_num, 0, 0, 0); } template_lengths = 0; if(kmerScan == &save_kmers_HMM) { /* load lengths */ strcat(templatefilename, ".length.b"); templatefile = sfopen(templatefilename, "rb"); sfread(&templates->DB_size, sizeof(int), 1, templatefile); if(shm & 4) { key = ftok(templatefilename, 'l'); shmid = shmget(key, templates->DB_size * sizeof(int), 0666); if(shmid < 0) { fprintf(stderr, "No shared length\n"); exit(1); } else { template_lengths = shmat(shmid, NULL, 0); } } else { template_lengths = smalloc(templates->DB_size * sizeof(int)); sfread(template_lengths, sizeof(int), templates->DB_size, templatefile); } templatefilename[file_len] = 0; fclose(templatefile); save_kmers_HMM(templates, 0, &(int){thread_num}, template_lengths, 0, 0, 0, 0, 0, 0, minlen, 0, 0); } else if(kmerScan == &save_kmers_chain || kmerScan == &save_kmers_sparse_chain) { kmerScan(0, 0, &(int){thread_num}, (int *)(&coverT), (int *)(&mrs), 0, 0, 0, 0, 0, minlen, 0, 0); } t1 = clock(); fprintf(stderr, "#\n# Total time used for DB loading: %.2f s.\n#\n", difftime(t1, t0) / 1000000); t0 = clock(); fprintf(stderr, "# Finding k-mer ankers\n"); /* initialize threads */ i = 1; threads = 0; while(i < thread_num) { thread = smalloc(sizeof(KmerScan_thread)); thread->num = i; thread->exhaustive = exhaustive; thread->sam = sam; thread->bestScore = 0; thread->bestScore_r = 0; thread->bestTemplates = calloc((templates->DB_size << 1) + 4, sizeof(int)); thread->bestTemplates_r = calloc((templates->DB_size << 1) + 4, sizeof(int)); if(!thread->bestTemplates || !thread->bestTemplates_r) { ERROR(); } thread->templates = templates; thread->inputfile = inputfile; thread->rewards = rewards; thread->out = out; thread->next = threads; threads = thread; /* start thread */ if((errno = pthread_create(&thread->id, NULL, &save_kmers_threaded, thread))) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); fprintf(stderr, "Will continue with %d threads.\n", i); threads = thread->next; free(thread); i = thread_num; } else { ++i; } } /* start main thread */ thread = smalloc(sizeof(KmerScan_thread)); thread->num = 0; thread->bestScore = 0; thread->bestScore_r = 0; bestTemplates = calloc((templates->DB_size << 1) + 4, sizeof(int)); thread->bestTemplates = bestTemplates; thread->bestTemplates_r = calloc(templates->DB_size + 4, sizeof(int)); if(!bestTemplates || !thread->bestTemplates_r) { ERROR(); } thread->templates = templates; thread->inputfile = inputfile; thread->rewards = rewards; thread->exhaustive = exhaustive; thread->sam = sam; thread->out = out; /* start k-mer search */ save_kmers_threaded(thread); /* join threads */ for(thread = threads; thread; thread = thread->next) { /* join thread */ if((errno = pthread_join(thread->id, NULL))) { ERROR(); } else if(bestTemplates[2] < thread->bestTemplates[2]) { bestTemplates[2] = thread->bestTemplates[2]; } } /* print remaining buffer */ if(printPtr == &print_ankers_spltDB || printPtr == &print_ankers_Sparse_spltDB) { printPtr(bestTemplates, 0, 0, 0, 0, out); } else { /* print number of fragments */ sfwrite(&(int){bestTemplates[2]}, sizeof(int), 1, out); } kmaPipe(0, 0, inputfile, &i); if(kmaPipe == &kmaPipeFork) { t1 = clock(); fprintf(stderr, "#\n# Total time used ankering query: %.2f s.\n#\n", difftime(t1, t0) / 1000000); } else { fprintf(stderr, "# Query ankered\n#\n"); } /* clean up */ if(!((shm & 1) || (deCon && (shm & 2)))) { hashMapKMA_destroy(templates); } if(kmerScan == &save_kmers_HMM && (shm & 4) == 0) { free(template_lengths); } else if(kmerScan == &save_kmers_chain || kmerScan == &save_kmers_sparse_chain) { kmerScan(0, 0, &(int){thread_num}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } for(thread = threads; thread; thread = threads) { threads = thread->next; free(thread->bestTemplates); free(thread->bestTemplates_r); free(thread); } return i; } genomicepidemiology-kma-091b8ffe66ac/loadupdate.h0000644000175000017500000000220614157033525021404 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "hashmap.h" #include "hashmapkma.h" void * memdup(const void * src, size_t size); int CP(char *templatefilename, char *outputfilename); HashMap * hashMapKMA_openChains(HashMapKMA *src); unsigned ** hashMapKMA_openValues(HashMapKMA *src); unsigned load_DBs(char *templatefilename, char *outputfilename, unsigned **template_lengths, unsigned **template_ulengths, unsigned **template_slengths, HashMapKMA *finalDB); genomicepidemiology-kma-091b8ffe66ac/hashmapkma.h0000644000175000017500000001036214157033525021376 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #ifndef HASHMAPKMA #ifdef _WIN32 typedef int key_t; #endif typedef struct hashMapKMA HashMapKMA; struct hashMapKMA { long unsigned size; // size of DB long unsigned n; // k-mers stored long unsigned mask; long unsigned null_index; // null value long unsigned v_index; // size of values unsigned kmersize; // k unsigned prefix_len; // prefix length long unsigned prefix; // prefix int DB_size; unsigned shmFlag; unsigned *exist; // size long long unsigned *exist_l; // size long, big DBs unsigned *values; // compressed values short unsigned *values_s; // compressed values, few templates unsigned *key_index; // Relative long unsigned *key_index_l; // Relative, 16 < k unsigned *value_index; // Relative long unsigned *value_index_l; // Relative, big DBs }; #define HASHMAPKMA 1 #endif /* DB size dependent pointers */ extern void (*hashMapKMA_destroy)(HashMapKMA *); extern long unsigned (*getExistPtr)(const unsigned *, const long unsigned); extern long unsigned (*getKeyPtr)(const unsigned *, const long unsigned); extern long unsigned (*getValueIndexPtr)(const unsigned *, const long unsigned); extern unsigned * (*getValuePtr)(const HashMapKMA *, const long unsigned); extern unsigned * (*hashMap_get)(const HashMapKMA *, const long unsigned); extern int (*intpos_bin_contaminationPtr)(const unsigned *, const int); extern int (*getSizePtr)(const unsigned *); extern void (*hashMapKMA_addKey_ptr)(HashMapKMA *, long unsigned, long unsigned); extern void (*hashMapKMA_addValue_ptr)(HashMapKMA *, long unsigned, long unsigned); extern void (*hashMapKMA_addExist_ptr)(HashMapKMA *, long unsigned, long unsigned); /* HASHMAP FUNCTIONS */ long unsigned getExist(const unsigned *exist, const long unsigned pos); long unsigned getExistL(const unsigned *exist, const long unsigned pos); long unsigned getKey(const unsigned *key_index, const long unsigned pos); long unsigned getKeyL(const unsigned *key_index, const long unsigned pos); long unsigned getValueIndex(const unsigned *value_index, const long unsigned pos); long unsigned getValueIndexL(const unsigned *value_index, const long unsigned pos); unsigned * getValue(const HashMapKMA *dest, const long unsigned pos); unsigned * getValueS(const HashMapKMA *dest, const long unsigned pos); int getSize(const unsigned *values); int getSizeS(const unsigned *values); int intpos_bin_contamination(const unsigned *str1, const int str2); int intpos_bin_contamination_s(const unsigned *Str1, const int str2); unsigned * hashMap_getGlobal(const HashMapKMA *templates, const long unsigned key); void loadPrefix(HashMapKMA *dest, FILE *file); unsigned * megaMap_getGlobal(const HashMapKMA *templates, const long unsigned key); int hashMapKMA_load(HashMapKMA *dest, FILE *file, const char *filename); void hashMapKMA_load_shm(HashMapKMA *dest, FILE *file, const char *filename); int hashMapKMAload(HashMapKMA *dest, FILE *file); void hashMapKMA_dump(HashMapKMA *dest, FILE *out); void megaMapKMA_dump(HashMapKMA *dest, FILE *out); void hashMapKMA_addKey(HashMapKMA *dest, long unsigned index, long unsigned key); void hashMapKMA_addKeyL(HashMapKMA *dest, long unsigned index, long unsigned key); void hashMapKMA_addValue(HashMapKMA *dest, long unsigned index, long unsigned v_index); void hashMapKMA_addValueL(HashMapKMA *dest, long unsigned index, long unsigned v_index); void hashMapKMA_addExist(HashMapKMA *dest, long unsigned index, long unsigned relative); void hashMapKMA_addExistL(HashMapKMA *dest, long unsigned index, long unsigned relative); void hashMapKMA_free(HashMapKMA *dest); genomicepidemiology-kma-091b8ffe66ac/kmmap.h0000644000175000017500000000154714157033525020376 0ustar nileshnilesh/* Philip T.L.C. Clausen May 2019 plan@dtu.dk */ /* * Copyright (c) 2019, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include #include "hashmapkma.h" int hashMapKMAmmap(HashMapKMA *dest, FILE *file); void hashMapKMA_munmap(HashMapKMA *dest); genomicepidemiology-kma-091b8ffe66ac/shm.c0000644000175000017500000003743014157033525020053 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #ifndef _WIN32 #include #include #include #else typedef int key_t; #define ftok(charPtr, integer) (0) #define shmget(key, size, permission) ((size != 0) ? (-1) : (-key)) #define shmat(shmid, NULL_Ptr, integer) (NULL) #define shmdt(dest) fprintf(stderr, "sysV not available on Windows.\n") #define shmctl(shmid, cmd, buf) fprintf(stderr, "sysV not available on Windows.\n") #endif #include #include #include #include #include #include #include "pherror.h" #include "hashmapkma.h" #include "shm.h" #include "version.h" void hashMap_shm_detach(HashMapKMA *dest) { shmdt(dest->exist); shmdt(dest->values); shmdt(dest->key_index); shmdt(dest->value_index); } int hashMapKMA_setupSHM(HashMapKMA *dest, FILE *file, const char *filename) { int shmid, kmersize, status; unsigned DB_size; long unsigned mask, size; key_t key; /* load sizes */ sfread(&DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); sfread(&dest->n, sizeof(long unsigned), 1, file); sfread(&dest->v_index, sizeof(long unsigned), 1, file); sfread(&dest->null_index, sizeof(long unsigned), 1, file); kmersize = dest->kmersize; mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); status = 0; /* check shared memory, else load */ size = dest->size; if((dest->size - 1) == mask) { if(dest->v_index <= UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } } else { if(dest->n <= UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } } key = ftok(filename, 'e'); shmid = shmget(key, size, IPC_CREAT | 0666); if(shmid < 0) { fprintf(stderr, "Could not setup the shared hashMap e\n"); fseek(file, size, SEEK_CUR); dest->exist = 0; status = 1; } else { dest->exist = shmat(shmid, NULL, 0); sfread(dest->exist, 1, size, file); } /* values */ size = dest->v_index; if(DB_size < USHRT_MAX) { size *= sizeof(short unsigned); } else { size *= sizeof(unsigned); } key = ftok(filename, 'v'); shmid = shmget(key, size, IPC_CREAT | 0666); if(shmid < 0) { fprintf(stderr, "Could not setup the shared hashMap v\n"); fseek(file, size, SEEK_CUR); dest->values = 0; status = 1; } else { /* found */ dest->values = shmat(shmid, NULL, 0); sfread(dest->values, 1, size, file); } if((dest->size - 1) == mask) { return status; } /* kmers */ size = dest->n + 1; if(dest->kmersize <= 16) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } key = ftok(filename, 'k'); shmid = shmget(key, size, IPC_CREAT | 0666); if(shmid < 0) { fprintf(stderr, "Could not setup the shared hashMap k\n"); fseek(file, size, SEEK_CUR); dest->values = 0; status = 1; } else { /* found */ dest->key_index = shmat(shmid, NULL, 0); sfread(dest->key_index, 1, size, file); } /* value indexes */ size = dest->n; if(dest->v_index < UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } key = ftok(filename, 'i'); shmid = shmget(key, size, IPC_CREAT | 0666); if(shmid < 0) { fprintf(stderr, "Could not setup the shared hashMap i\n"); fseek(file, size, SEEK_CUR); dest->value_index = 0; status = 1; } else { /* found */ dest->value_index = shmat(shmid, NULL, 0); sfread(dest->value_index, 1, size, file); } return status; } void hashMapKMA_destroySHM(HashMapKMA *dest, FILE *file, const char *filename) { int shmid, kmersize; unsigned DB_size; long unsigned mask, size; key_t key; /* load sizes */ sfread(&DB_size, sizeof(unsigned), 1, file); sfread(&dest->kmersize, sizeof(unsigned), 1, file); sfread(&dest->prefix_len, sizeof(unsigned), 1, file); sfread(&dest->prefix, sizeof(long unsigned), 1, file); sfread(&dest->size, sizeof(long unsigned), 1, file); sfread(&dest->n, sizeof(long unsigned), 1, file); sfread(&dest->v_index, sizeof(long unsigned), 1, file); sfread(&dest->null_index, sizeof(long unsigned), 1, file); kmersize = dest->kmersize; mask = 0; mask = (~mask) >> (sizeof(long unsigned) * sizeof(long unsigned) - (kmersize << 1)); /* check shared memory, and destroy */ size = dest->size; if((dest->size - 1) == mask) { if(dest->v_index <= UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } } else { if(dest->n <= UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } } key = ftok(filename, 'e'); shmid = shmget(key, size, 0666); if(shmid >= 0) { shmctl(shmid, IPC_RMID, NULL); } /* values */ size = dest->v_index; if(DB_size < USHRT_MAX) { size *= sizeof(short unsigned); } else { size *= sizeof(unsigned); } key = ftok(filename, 'v'); shmid = shmget(key, size, 0666); if(shmid >= 0) { shmctl(shmid, IPC_RMID, NULL); } /* kmers */ size = dest->n + 1; if(dest->kmersize <= 16) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } key = ftok(filename, 'k'); shmid = shmget(key, size, 0666); if(shmid >= 0) { shmctl(shmid, IPC_RMID, NULL); } /* value indexes */ size = dest->n; if(dest->v_index < UINT_MAX) { size *= sizeof(unsigned); } else { size *= sizeof(long unsigned); } key = ftok(filename, 'i'); shmid = shmget(key, size, 0666); if(shmid >= 0) { shmctl(shmid, IPC_RMID, NULL); } } int * length_setupSHM(FILE *file, const char *filename) { int shmid, *template_lengths; long unsigned size; key_t key; /* load size */ fseek(file, 0, SEEK_END); size = ftell(file) - sizeof(int); fseek(file, sizeof(int), SEEK_SET); key = ftok(filename, 'l'); shmid = shmget(key, size, IPC_CREAT | 0666); if(shmid < 0) { fprintf(stderr, "Could not setup the shared length\n"); template_lengths = 0; } else { template_lengths = shmat(shmid, NULL, 0); sfread(template_lengths, sizeof(unsigned), size / sizeof(unsigned), file); } return template_lengths; } void length_destroySHM(FILE *file, const char *filename) { int shmid; long unsigned size; key_t key; /* load size */ fseek(file, 0, SEEK_END); size = ftell(file) - sizeof(int); key = ftok(filename, 'l'); shmid = shmget(key, size, 0666); if(shmid >= 0) { shmctl(shmid, IPC_RMID, NULL); } } long unsigned * seq_setupSHM(FILE *file, const char *filename) { int shmid; long unsigned size, *seq; key_t key; /* load size */ fseek(file, 0, SEEK_END); size = ftell(file); rewind(file); key = ftok(filename, 's'); shmid = shmget(key, size, IPC_CREAT | 0666); if(shmid < 0) { fprintf(stderr, "Could not setup the shared length\n"); seq = 0; } else { seq = shmat(shmid, NULL, 0); sfread(seq, sizeof(long unsigned), size / sizeof(long unsigned), file); } return seq; } void seq_destroySHM(FILE *file, const char *filename) { int shmid; long unsigned size; key_t key; /* load size */ fseek(file, 0, SEEK_END); size = ftell(file); key = ftok(filename, 's'); shmid = shmget(key, size, 0666); if(shmid >= 0) { shmctl(shmid, IPC_RMID, NULL); } } char * name_setupSHM(FILE *file, const char *filename) { int i, shmid; long unsigned size; char *template_names; key_t key; /* load size */ fseek(file, 0, SEEK_END); size = ftell(file); rewind(file); key = ftok(filename, 'n'); shmid = shmget(key, size, IPC_CREAT | 0666); if(shmid < 0) { fprintf(stderr, "Could not setup the shared length\n"); template_names = 0; } else { template_names = shmat(shmid, NULL, 0); sfread(template_names, 1, size, file); for(i = 0; i < size; ++i) { if(template_names[i] == '\n') { template_names[i] = 0; } } } return template_names; } void name_destroySHM(FILE *file, const char *filename) { int shmid; long unsigned size; key_t key; /* load size */ fseek(file, 0, SEEK_END); size = ftell(file); key = ftok(filename, 'n'); shmid = shmget(key, size, 0666); if(shmid >= 0) { shmctl(shmid, IPC_RMID, NULL); } } static void helpMessage(int exeStatus) { FILE *helpOut; if(exeStatus == 0) { helpOut = stdout; } else { helpOut = stderr; } fprintf(helpOut, "# kma_shm sets up a shared database (sysV) for mapping with KMA.\n"); fprintf(helpOut, "# Options are:\t\tDesc:\t\t\t\tDefault:\tRequirements:\n"); fprintf(helpOut, "#\n"); fprintf(helpOut, "#\t-t_db\t\tTemplate DB\t\t\tNone\t\tREQUIRED\n"); fprintf(helpOut, "#\t-destroy\tDestroy shared DB\t\tFalse\n"); fprintf(helpOut, "#\t-shmLvl\t\tLevel of shared memory\t\t1\n"); fprintf(helpOut, "#\t-shm-h\t\tExplain shm levels\n"); fprintf(helpOut, "#\t-v\t\tVersion\n"); fprintf(helpOut, "#\t-h\t\tShows this help message\n"); fprintf(helpOut, "#\n"); exit(exeStatus); } int shm_main(int argc, char *argv[]) { int args, file_len, destroy, status, *template_lengths; unsigned shmLvl; long unsigned *seq; char *templatefilename, *template_names; HashMapKMA *templates; FILE *file; #ifdef _WIN32 fprintf(stderr, "sysV not available on Windows.\n"); return 1; #endif /* SET DEFAULTS */ templatefilename = 0; destroy = 0; shmLvl = 1; status = 0; /* PARSE COMMAND LINE OPTIONS */ args = 1; while(args < argc) { if(strcmp(argv[args], "-t_db") == 0) { ++args; if(args < argc) { templatefilename = malloc(strlen(argv[args]) + 64); if(!templatefilename) { fprintf(stderr, "OOM\n"); exit(1); } strcpy(templatefilename, argv[args]); } } else if(strcmp(argv[args], "-destroy") == 0) { destroy = 1; } else if(strcmp(argv[args], "-shmLvl") == 0) { ++args; if(args < argc) { shmLvl = atoi(argv[args]); if(!shmLvl) { fprintf(stderr, "Invalid shmLvl\n"); exit(0); } } } else if(strcmp(argv[args], "-v") == 0) { fprintf(stdout, "KMA_SHM-%s\n", KMA_VERSION); exit(0); } else if(strcmp(argv[args], "-h") == 0) { helpMessage(0); } else if(strcmp(argv[args], "-shm-h") == 0) { fprintf(stderr, "# Flags for shared memory, add them to combine them\n"); fprintf(stderr, "# After shm is setup, the DB-files should not be changed.\n"); fprintf(stderr, "#\n"); fprintf(stderr, "#\tDB piece\t\tFlag\n"); fprintf(stderr, "#\t*.comp.b\t\t1\n"); fprintf(stderr, "#\t*.decon.comp.b\t\t2\n"); fprintf(stderr, "#\t*.length.b\t\t4\n"); fprintf(stderr, "#\t*.seq.b\t\t\t8\n"); fprintf(stderr, "#\t*.name\t\t\t16\n"); //fprintf(stderr, "#\tall\t\t\t31\n"); exit(0); } else { fprintf(stderr, "# Invalid option:\t%s\n", argv[args]); fprintf(stderr, "# Printing help message:\n"); helpMessage(-1); } ++args; } if(templatefilename == 0) { fprintf(stderr, "# Too few arguments handed\n"); fprintf(stderr, "# Printing help message:\n"); helpMessage(-1); } file_len = strlen(templatefilename); templates = malloc(sizeof(HashMapKMA)); if(!templates) { fprintf(stderr, "OOM\n"); exit(1); } /* setup or destroy shm */ if(destroy) { /* *comp.b */ if(shmLvl & 1) { strcat(templatefilename, ".comp.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { hashMapKMA_destroySHM(templates, file, templatefilename); fclose(file); } templatefilename[file_len] = 0; } /* *decon.comp.b */ if(shmLvl & 2) { strcat(templatefilename, ".decon.comp.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { hashMapKMA_destroySHM(templates, file, templatefilename); fclose(file); } templatefilename[file_len] = 0; } /* *.length.b */ if(shmLvl & 4) { strcat(templatefilename, ".length.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { length_destroySHM(file, templatefilename); fclose(file); } templatefilename[file_len] = 0; } /* *.seq.b */ if(shmLvl & 8) { /* *.seq.b */ strcat(templatefilename, ".seq.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { seq_destroySHM(file, templatefilename); fclose(file); } templatefilename[file_len] = 0; } /* *.name */ if(shmLvl & 16) { strcat(templatefilename, ".name"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { name_destroySHM(file, templatefilename); fclose(file); } templatefilename[file_len] = 0; } } else { /* *.comp.b */ if(shmLvl & 1) { strcat(templatefilename, ".comp.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { status |= hashMapKMA_setupSHM(templates, file, templatefilename); hashMap_shm_detach(templates); fclose(file); } templatefilename[file_len] = 0; } /* *.decon.comp.b */ if(shmLvl & 2) { strcat(templatefilename, ".decon.comp.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { status |= hashMapKMA_setupSHM(templates, file, templatefilename); hashMap_shm_detach(templates); fclose(file); } templatefilename[file_len] = 0; } /* *.length.b */ if(shmLvl & 4) { strcat(templatefilename, ".length.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { template_lengths = length_setupSHM(file, templatefilename); if(template_lengths) { shmdt(template_lengths); } else { status |= 1; } fclose(file); } templatefilename[file_len] = 0; } /* *.seq.b*/ if(shmLvl & 8) { /* *.seq.b */ strcat(templatefilename, ".seq.b"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { seq = seq_setupSHM(file, templatefilename); if(seq) { shmdt(seq); } else { status |= 1; } fclose(file); } templatefilename[file_len] = 0; } /* *.name */ if(shmLvl & 16) { strcat(templatefilename, ".name"); file = fopen(templatefilename, "rb"); if(!file) { fprintf(stderr, "Error: %d (%s)\n", errno, strerror(errno)); status |= errno; } else { template_names = name_setupSHM(file, templatefilename); if(template_names) { shmdt(template_names); } else { status |= 1; } fclose(file); } templatefilename[file_len] = 0; } } /* Set sys shm to 1 GB * sudo sysctl -w kern.sysv.shmmax=1073741824 * sudo sysctl -w kern.sysv.shmall=1073741824 * * Set sys shm to 2 GB * sudo sysctl -w kern.sysv.shmmax=2147483648 * sudo sysctl -w kern.sysv.shmall=2147483648 * * Set sys shm to 3 GB * sudo sysctl -w kern.sysv.shmmax=3221225472 * sudo sysctl -w kern.sysv.shmall=3221225472 * * check status: * ipcs -a */ return status; } genomicepidemiology-kma-091b8ffe66ac/kma_index.c0000644000175000017500000000147214157033525021220 0ustar nileshnilesh/* Philip T.L.C. Clausen Jan 2017 plan@dtu.dk */ /* * Copyright (c) 2017, Philip Clausen, Technical University of Denmark * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _XOPEN_SOURCE 600 #include "index.h" int main(int argc, char *argv[]) { return index_main(argc, argv); }