Bio-SamTools-1.39000755001750001750 012207676767 13721 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/MANIFEST000444001750001750 134712207676767 15214 0ustar00lsteinlstein000000000000bin/bamToGBrowse.pl bin/chrom_sizes.pl bin/genomeCoverageBed.pl Build.PL c_bin/bam2bedgraph.c c_bin/makefile Changes DISCLAIMER lib/Bio/DB/Bam/Alignment.pm lib/Bio/DB/Bam/AlignWrapper.pm lib/Bio/DB/Bam/FetchIterator.pm lib/Bio/DB/Bam/Pileup.pm lib/Bio/DB/Bam/PileupWrapper.pm lib/Bio/DB/Bam/Query.pm lib/Bio/DB/Bam/ReadIterator.pm lib/Bio/DB/Bam/Target.pm lib/Bio/DB/Sam.pm lib/Bio/DB/Sam.xs lib/Bio/DB/Sam/Constants.pm lib/Bio/DB/Sam/SamToGBrowse.pm lib/Bio/DB/Sam/Segment.pm LICENSE MANIFEST This list of files META.json META.yml README t/01sam.t t/data/00README.txt t/data/dm3_3R_4766911_4767130.sam t/data/dm3_3R_4766911_4767130.sam.bam t/data/dm3_3R_4766911_4767130.sam.sorted.bam t/data/ex1.bam t/data/ex1.fa t/data/ex1.sam.gz typemap Bio-SamTools-1.39/Build.PL000444001750001750 1007512207676767 15375 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use Module::Build; my $HeaderFile = "bam.h"; my $LibFile = "libbam.a"; my $ReadLine; my ($sam_include,$sam_lib) = find_sam(); # may exit with error here my $class = Module::Build->subclass(code=><; \$self->copy_if_modified(from =>\$_, to_dir => "./blib/bin/", flatten=>1, ) foreach \@exec; } sub ACTION_clean { my \$self = shift; \$self->SUPER::ACTION_clean(); system "cd c_bin; make -s clean"; } EOF my $build = $class->new( module_name => 'Bio::SamTools', dist_version_from => 'lib/Bio/DB/Sam.pm', dist_author => 'Lincoln Stein ', dist_abstract => 'Perl interface to SamTools library for DNA sequencing', license => 'perl', include_dirs => [$sam_include], extra_linker_flags => ["-L$sam_lib",'-lbam','-lpthread','-lz'], extra_compiler_flags=>[ # must match DFLAGS in Samtools Makefile '-D_IOLIB=2','-D_FILE_OFFSET_BITS=64', # turn off warnings originating in Perl's Newx* calls '-Wformat=0' ], c_source => 'c_bin', c_bin_files => {'./bin/bam2bedgraph' => 'bin/bam2bedgraph'}, build_requires => { 'ExtUtils::CBuilder' => 0, }, requires => { 'perl' => '5.008', 'Bio::Root::Version' => '1.006009001', }, # create_makefile_pl => 'passthrough', ); $build->add_build_element('c_bin'); $build->create_build_script; exit 0; sub find_sam { my ($sam_include,$sam_lib); if (my $samtools = $ENV{SAMTOOLS}) { $sam_include = $samtools if -e "$samtools/$HeaderFile"; $sam_include = "$samtools/include" if -e "$samtools/include/$HeaderFile"; $sam_lib = $samtools if -e "$samtools/$LibFile"; $sam_lib = "$samtools/lib" if -e "$samtools/lib/$LibFile"; } my @search_path = qw(/ /usr /usr/share /usr/local); unless ($sam_include) { for my $p (@search_path) { $sam_include ||= "$p/include" if -e "$p/include/$HeaderFile"; } } unless ($sam_lib) { for my $p (@search_path) { $sam_lib ||= "$p/lib" if -e "$p/lib/$LibFile"; } } unless ($sam_include && $sam_lib) { print STDOUT "This module requires samtools 0.1.10 or higher (samtools.sourceforge.net).\n"; my $prompt = "Please enter the location of the bam.h and compiled libbam.a files: "; my $found; while (!$found) { my $path = prompt($prompt); print STDOUT "\n"; last unless $path; $sam_include = $path if -e "$path/$HeaderFile"; $sam_include = "$path/include" if -e "$path/include/$HeaderFile"; $sam_lib = $path if -e "$path/$LibFile"; $sam_lib = "$path/lib" if -e "$path/lib/$LibFile"; $found = $sam_include && $sam_lib; unless ($found) { print STDOUT "That didn't seem to be right.\n"; $prompt = "Try again, or hit to cancel: "; } } } unless ($sam_include && $sam_lib) { die <can('new') || 0; $ReadLine &&= Term::ReadLine->new(\*STDOUT); eval {readline::rl_set('TcshCompleteMode','On')}; } unless ($ReadLine) { print STDOUT $msg; chomp (my $in = <>); return $in; } my $in = $ReadLine->readline($msg); chomp $in; $in=~ s/\s+//; $ReadLine->addhistory($in) if $in =~ /\S/; return $in; } Bio-SamTools-1.39/Changes000444001750001750 1713212207676767 15375 0ustar00lsteinlstein000000000000Version 1.39 * Bio::DB::Bam::Alinment->strand() performance patch from: https://rt.cpan.org/Ticket/Display.html?id=88203. Version 1.38 * Add -lpthread to linker flags to allow to run with samtools 0.1.19. Version 1.37 * Fix incorrect calculation of mate_len and mate_end when CIGAR string contains insertions and deletions. Thanks to Ian Sealy for the patch! Version 1.36 * Added C binary bam2bedgraph for quick coverage calculations (2-5x faster than BEDTools' genomeCoverageBed) * Speed up bamToGrowse.pl using bam2bedgraph. Version 1.35 * Add patch from John Marshall to fix several problems in the tam line generator when reads are unmapped. Version 1.34 * Add patch from Florian Finkernagel to accomodate paired end data that are encoded as CIGAR strings. Version 1.33 * Fix compile error on perl 5.8.7 and lower. * Fix "substr outside of string" errors when processing split alignments with a hard clip at beginning of CIGAR string. Version 1.32 * Fix loss of strand information when joining split alignments. * Give read_pair objects a primary_id that will allow them to be retrieved intact using get_feature_by_id(). Version 1.31 * Added Bio::DB::Sam->max_pileup_cnt() and Bio::DB::Bam->max_pileup_cnt() method to allow users to adjust Samtools cap on pileup depth. Version 1.30 * Apply patch from Jason Walker to return full arrays across 0-depth coverage and to max the count at a certain coverage. Version 1.29 * Apply patch from Hongwen Qiu to fix memory allocation error in bam header generation. Version 1.28 *Fixed coverage calculations so that sections of reads that cover the reference genome which are marked in the CIGAR string as 'N' (skip) or 'D' (delete) do not contribute to coverage. *The bamToGBrowse.pl script now takes advantage of genomeCoveragetoBed from the BedTools package. If this executable is installed, BigWig generation will speed up noticeably. Version 1.27 *Support for SAM/BAM files in which the sequence is given as "*". This will return a completely ambiguous read (NNNNNNNN) of the proper length. *SamToGBrowse functions will now work properly under a fastCGI environment. Version 1.26 * Added support for samtools >= 0.1.9 is_refskip field in pileups. Version 1.25 * Removed debugging warning in get_feature_by_id(). * Identify version-specific samtools installs where the prefix is xyz and the include/lib files are in xyz/include and xyz/lib (Contributed by John Marshall). Version 1.24 * More revisions needed to run tests succssfully. Sorry! Version 1.23 * added missing files needed for the multi-gaps test introduced in 1.22. Version 1.22 * fix/test for 'incomplete cigar/split alignments processing of multi-gaps' (https://sourceforge.net/tracker/?func=detail&aid=3083769&group_id=27707&atid=391291)" Version 1.21 * Fixed the AlignWrapper->can() method, which was causing crashes with GBrowse2. Version 1.20 * Added Bio::DB::Tam->header_read() method. Version 1.19 * Added Bio::DB::Bam::Alignment->mate_seq_id() method. * Added Bio::DB::Bam::Alignment->aux() method. * Added Bio::DB::Bam::Alignment->tam_line() method. * Fixed Bio::DB::Bam::Alignment->cigar_str() method to return fields in correct order! (bad bug) Version 1.18 * Made the BAMfile $header->text() method read/write, allowing limited modification of header fields. * Fixed MD processing again to correctly handle insertions into the reference sequence. Version 1.17 * Fixed bug in processing of MD tag that returned incorrect reference sequence when alignment contains soft clips. * Fixed processing of "A" tags so that they return the appropriate 1 character string rather than undef. Version 1.16 * No longer attempt to build BAM index automatically if the .bai file is either missing or out of date. Pass -autoindex=>1 to Bio::DB::Sam to restore original behavior. Version 1.15 * If -fasta argument is not provided at new() time, methods will attempt to use the MD tags to reconstruct reference sequence. Version 1.14 * A last minute typo broke the regression tests. This is now fixed. Don't use version 1.13. Version 1.13 * Fixed another bug in padded_alignments(), which caused the source dna sequence to be reported incorrectly for mismatches. Thanks to David Gacquer for identifying all these bugs. Version 1.12 * Fixed the padded_alignments() method to correct "method not found" bug introduced in version 1.11. Version 1.11 * Fixed the padded alignments returned for hard-clipped alignments. Version 1.10 * Added a new Bio::DB::Bam method for caching remote files' indices in the temp directory. This is used by default by high-level API. * Fixed bug in soft and hard clipping code; query endpoints should be correct now. * Fixed bug in get_all_tags() which was choking on "Z" style tags and giving scrambled results. * $feature->query now reports the DNA query in canonical (ref) coordinates; only $feature->target reverse complements the query DNA to give the data actually read; cigar string is always in canonical coordinates Version 1.09 * Disabled checks for file readability when path is a remote BAM index. This allows transparent access to BAM databases on http/ftp servers. Version 1.08 * Implemented a clone() method for use immediately before or after a fork() attempt. Version 1.07 * IMPORTANT API CHANGE 1: The feature strand now returns +1 or -1 to indicate whether the query was reverse complemented in the SAM file. * IMPORTANT API CHANGE 2: The $feature->query object's dna() and seq() methods now return the sequence as it was read, rather than the reverse complemented version as represented in the SAM file. $feature->qseq() returns the reverse complemented version as before. Version 1.06 * Updated README to be more explicit about how to troubleshoot compile errors. * Modifed so that Bio::DB::Sam will work with GBrowse 1. Version 1.05 * Bio::DB::Sam->seq_id() method no longer lower-cases reference names. * Quashed enormous memory leak in the pileup() function. Version 1.04 * Updated example BAM file (ex1.bam) to be compatible with 1.06 version of samtools. Version 1.03 * Fixed documentation on running with GBrowse. * Fixed alignwrapper behavior so that GBrowse searches don't crash. Version 1.02 * Fixed bug in parsing of unsigned integer tags that caused some tags to be treated as signed integer. Version 1.01 * Fixed Build.PL to pick up correct location of bam header files. * Eliminated several memory leaks that manifested when reading BAM files with lots of targets. * Made -fasta argument optional when using high-level interface. Version 1.00 * initial release Tue Jun 23 23:47:28 BST 2009 * Many documentation improvements * Improved performance of high-level interface for fetch() and pileup() functions. * Added information to README about how to compile with samtools 0.1.4 Thu May 7 09:47:02 EDT 2009 * See t/01sam.t for a demonstration of the API. * Essentially all of the API is fleshed out, with the exception of the ability to generate padded alignment itself. * The $alignment->query() interface is the one to use for retrieving start, end and sequence of the query sequence. The $alignment->target() interface flips the meaning of start and end when the alignment is reversed, to accomodate old AceDB/GFF2 scripts. Bio-SamTools-1.39/META.yml000444001750001750 354012207676767 15331 0ustar00lsteinlstein000000000000--- abstract: 'Perl interface to SamTools library for DNA sequencing' author: - 'Lincoln Stein ' build_requires: ExtUtils::CBuilder: 0 configure_requires: Module::Build: 0.38 dynamic_config: 1 generated_by: 'Module::Build version 0.38, CPAN::Meta::Converter version 2.110440' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Bio-SamTools provides: Bio::DB::Bam: file: lib/Bio/DB/Sam.pm version: 0 Bio::DB::Bam::AlignWrapper: file: lib/Bio/DB/Bam/AlignWrapper.pm version: 0 Bio::DB::Bam::Alignment: file: lib/Bio/DB/Bam/Alignment.pm version: 0 Bio::DB::Bam::FetchIterator: file: lib/Bio/DB/Bam/FetchIterator.pm version: 0 Bio::DB::Bam::Pileup: file: lib/Bio/DB/Bam/Pileup.pm version: 0 Bio::DB::Bam::PileupWrapper: file: lib/Bio/DB/Bam/PileupWrapper.pm version: 0 Bio::DB::Bam::Query: file: lib/Bio/DB/Bam/Query.pm version: 0 Bio::DB::Bam::ReadIterator: file: lib/Bio/DB/Bam/ReadIterator.pm version: 0 Bio::DB::Bam::SplitAlignmentPart: file: lib/Bio/DB/Bam/AlignWrapper.pm version: 0 Bio::DB::Bam::Target: file: lib/Bio/DB/Bam/Target.pm version: 0 Bio::DB::Sam: file: lib/Bio/DB/Sam.pm version: 1.39 Bio::DB::Sam::Constants: file: lib/Bio/DB/Sam/Constants.pm version: 0 Bio::DB::Sam::Fai: file: lib/Bio/DB/Sam.pm version: 0 Bio::DB::Sam::SamToGBrowse: file: lib/Bio/DB/Sam/SamToGBrowse.pm version: 0 Bio::DB::Sam::Segment: file: lib/Bio/DB/Sam/Segment.pm version: 0 Bio::DB::Sam::Segment::Iterator: file: lib/Bio/DB/Sam/Segment.pm version: 0 Bio::SeqFeature::Coverage: file: lib/Bio/DB/Sam.pm version: 0 requires: Bio::Root::Version: 1.006009001 perl: 5.008 resources: license: http://dev.perl.org/licenses/ version: 1.39 Bio-SamTools-1.39/README000444001750001750 363212207676767 14742 0ustar00lsteinlstein000000000000This is a Perl interface to the SAMtools sequence alignment interface. See http://samtools.sourceforge.net/. To compile this module, you must first download, unpack and compile SAMtools 0.1.4 or higher in some accessible directory. FOR SAMTOOLS VERSION 0.1.4, YOU MUST RUN "make -f makefile.generic" IN THE DISTRIBUTION DIRECTORY IN ORDER TO CREATE THE REQUIRED libbam.a LIBRARY FILE. For other versions, just "make" will usually work. Then set the environment variable SAMTOOLS to point to this directory. You will also need to install Bio::Perl from CPAN. Now run: perl Build.PL ./Build ./Build test (sudo) ./Build install TROUBLESHOOTING: If you encounter problems during compiling, you may need to edit Build.PL so that extra_compiler_flags matches the CFLAGS and DFLAGS settings in the Samtools Makefile. Here are some common problems: 1. When building this module, you get an error like the following: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC To fix this, edit the Makefile in the Samtools distribution by adding "-fPIC" to the CFLAGS line. It should look like this: CFLAGS= -g -Wall -O2 -fPIC #-m64 #-arch ppc Then do "make clean; make" in the Samtools directory to recompile the library. After this you should be able to build this module without errors. 2. When building this module, you get an error about a missing math library. To fix this, follow the recipe in (1) except add -m64 to CFLAGS so it looks like this: CFLAGS= -g -Wall -O2 -fPIC #-m64 #-arch ppc AUTHOR: Lincoln D. Stein Copyright (c) 2009 Ontario Institute for Cancer Research This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. Bio-SamTools-1.39/META.json000444001750001750 556612207676767 15513 0ustar00lsteinlstein000000000000{ "abstract" : "Perl interface to SamTools library for DNA sequencing", "author" : [ "Lincoln Stein " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.38, CPAN::Meta::Converter version 2.110440", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Bio-SamTools", "prereqs" : { "build" : { "requires" : { "ExtUtils::CBuilder" : 0 } }, "configure" : { "requires" : { "Module::Build" : "0.38" } }, "runtime" : { "requires" : { "Bio::Root::Version" : "1.006009001", "perl" : "5.008" } } }, "provides" : { "Bio::DB::Bam" : { "file" : "lib/Bio/DB/Sam.pm", "version" : 0 }, "Bio::DB::Bam::AlignWrapper" : { "file" : "lib/Bio/DB/Bam/AlignWrapper.pm", "version" : 0 }, "Bio::DB::Bam::Alignment" : { "file" : "lib/Bio/DB/Bam/Alignment.pm", "version" : 0 }, "Bio::DB::Bam::FetchIterator" : { "file" : "lib/Bio/DB/Bam/FetchIterator.pm", "version" : 0 }, "Bio::DB::Bam::Pileup" : { "file" : "lib/Bio/DB/Bam/Pileup.pm", "version" : 0 }, "Bio::DB::Bam::PileupWrapper" : { "file" : "lib/Bio/DB/Bam/PileupWrapper.pm", "version" : 0 }, "Bio::DB::Bam::Query" : { "file" : "lib/Bio/DB/Bam/Query.pm", "version" : 0 }, "Bio::DB::Bam::ReadIterator" : { "file" : "lib/Bio/DB/Bam/ReadIterator.pm", "version" : 0 }, "Bio::DB::Bam::SplitAlignmentPart" : { "file" : "lib/Bio/DB/Bam/AlignWrapper.pm", "version" : 0 }, "Bio::DB::Bam::Target" : { "file" : "lib/Bio/DB/Bam/Target.pm", "version" : 0 }, "Bio::DB::Sam" : { "file" : "lib/Bio/DB/Sam.pm", "version" : "1.39" }, "Bio::DB::Sam::Constants" : { "file" : "lib/Bio/DB/Sam/Constants.pm", "version" : 0 }, "Bio::DB::Sam::Fai" : { "file" : "lib/Bio/DB/Sam.pm", "version" : 0 }, "Bio::DB::Sam::SamToGBrowse" : { "file" : "lib/Bio/DB/Sam/SamToGBrowse.pm", "version" : 0 }, "Bio::DB::Sam::Segment" : { "file" : "lib/Bio/DB/Sam/Segment.pm", "version" : 0 }, "Bio::DB::Sam::Segment::Iterator" : { "file" : "lib/Bio/DB/Sam/Segment.pm", "version" : 0 }, "Bio::SeqFeature::Coverage" : { "file" : "lib/Bio/DB/Sam.pm", "version" : 0 } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ] }, "version" : "1.39" } Bio-SamTools-1.39/LICENSE000444001750001750 5660112207676767 15113 0ustar00lsteinlstein000000000000a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License 2.0" ---------------------------------------------------------------------------- The General Public License (GPL) Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ---------------------------------------------------------------------------- Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Bio-SamTools-1.39/DISCLAIMER000444001750001750 220412207676767 15413 0ustar00lsteinlstein000000000000The Bio::SamTools package and all associated files are Copyright (c) 2009 Ontario Institute for Cancer Research (OICR). This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See the Artistic License file in the main Perl distribution for specific terms and conditions of use. In addition, the following disclaimers apply: OICR makes no representations whatsoever as to the SOFTWARE contained herein. It is experimental in nature and is provided WITHOUT WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTY, EXPRESS OR IMPLIED. OICR MAKES NO REPRESENTATION OR WARRANTY THAT THE USE OF THIS SOFTWARE WILL NOT INFRINGE ANY PATENT OR OTHER PROPRIETARY RIGHT. By downloading this SOFTWARE, your Institution hereby indemnifies OICR against any loss, claim, damage or liability, of whatsoever kind or nature, which may arise from your Institution's respective use, handling or storage of the SOFTWARE. If publications result from research using this SOFTWARE, we ask that OICR be acknowledged and/or credit be given to OICR scientists, as scientifically appropriate. Bio-SamTools-1.39/typemap000444001750001750 34012207676767 15435 0ustar00lsteinlstein000000000000TYPEMAP Bio::DB::Bam T_PTROBJ Bio::DB::Bam::Header T_PTROBJ Bio::DB::Bam::Alignment T_PTROBJ Bio::DB::Bam::Index T_PTROBJ Bio::DB::Sam::Fai T_PTROBJ Bio::DB::Tam T_PTROBJ Bio::DB::Bam::Pileup T_PTROBJ Bio-SamTools-1.39/lib000755001750001750 012207676767 14467 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/lib/Bio000755001750001750 012207676767 15200 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/lib/Bio/DB000755001750001750 012207676767 15465 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/lib/Bio/DB/Sam.xs000444001750001750 5330512207676767 16744 0ustar00lsteinlstein000000000000#ifdef PERL_CAPI #define WIN32IO_IS_STDIO #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef FCGI #include #else #ifdef USE_SFIO #include #else #include #endif #include #endif #ifndef Newx # define Newx(v,n,t) New(0,v,n,t) #endif #ifndef Newxz # define Newxz(v,n,t) Newz(0,v,n,t) #endif #include #include #include "bam.h" #include "khash.h" #include "faidx.h" /* stolen from bam_aux.c */ #define MAX_REGION 1<<29 typedef tamFile Bio__DB__Tam; typedef faidx_t* Bio__DB__Sam__Fai; typedef bamFile Bio__DB__Bam; typedef bam_header_t* Bio__DB__Bam__Header; typedef bam1_t* Bio__DB__Bam__Alignment; typedef bam_index_t* Bio__DB__Bam__Index; typedef bam_pileup1_t* Bio__DB__Bam__Pileup; typedef struct { SV* callback; SV* data; } fetch_callback_data; typedef fetch_callback_data *fetch_callback_dataptr; typedef struct { int start; int end; double width; int reads; int* bin; } coverage_graph; typedef coverage_graph *coverage_graph_ptr; static int MaxPileupCnt=8000; void XS_pack_charPtrPtr( SV * arg, char ** array, int count) { int i; AV * avref; avref = (AV*)sv_2mortal((SV*)newAV()); for (i=0; icallback; callbackdata = fcp->data; /* turn the bam1_t into an appropriate object */ /* need to dup it here so that the C layer doesn't reuse the address under Perl */ b2 = bam_dup1(b); alignment_obj = sv_setref_pv(newSV(sizeof(bam1_t)),"Bio::DB::Bam::Alignment",(void*) b2); /* set up subroutine stack for the call */ ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(alignment_obj)); XPUSHs(callbackdata); PUTBACK; /* execute the call */ count = call_sv(callback,G_SCALAR|G_DISCARD); FREETMPS; LEAVE; return 1; } int invoke_pileup_callback_fun(uint32_t tid, uint32_t pos, int n, const bam_pileup1_t *pl, void *data) { dSP; int count,i; fetch_callback_dataptr fcp; SV* callback; SV* callbackdata; SV* pileup_obj; SV* p; SV** pileups; AV* pileup; fcp = (fetch_callback_dataptr) data; callback = fcp->callback; callbackdata = fcp->data; /* turn the bam_pileup1_t into the appropriate object */ /* this causes a compiler warning -- ignore it */ pileup = newAV(); av_extend(pileup,n); for (i=0;ireads += n; valid = 0; for (i=0;i= cgp->start && pos <= cgp->end) { bin = (pos-cgp->start)/cgp->width; cgp->bin[bin] += valid; } return 0; } MODULE = Bio::DB::Sam PACKAGE = Bio::DB::Tam PREFIX=tam_ Bio::DB::Tam tam_open(packname="Bio::DB::Tam", filename) char * packname char * filename PROTOTYPE: $$ CODE: RETVAL = sam_open(filename); OUTPUT: RETVAL void tam_DESTROY(tam) Bio::DB::Tam tam PROTOTYPE: $ CODE: sam_close(tam); Bio::DB::Bam::Header tam_header_read2(packname="Bio::DB::Tam", filename) char * packname char * filename PROTOTYPE: $$ CODE: RETVAL = sam_header_read2(filename); OUTPUT: RETVAL Bio::DB::Bam::Header tam_header_read(tam) Bio::DB::Tam tam PROTOTYPE: $$ CODE: RETVAL = sam_header_read(tam); OUTPUT: RETVAL int tam_read1(tam,header,alignment) Bio::DB::Tam tam Bio::DB::Bam::Header header Bio::DB::Bam::Alignment alignment CODE: RETVAL = sam_read1(tam,header,alignment); OUTPUT: RETVAL MODULE = Bio::DB::Sam PACKAGE = Bio::DB::Sam::Fai PREFIX=fai_ Bio::DB::Sam::Fai fai_load(packname="Bio::DB::Sam::Fai", filename) char * packname char * filename PROTOTYPE: $$ CODE: RETVAL = fai_load(filename); OUTPUT: RETVAL void fai_destroy(fai) Bio::DB::Sam::Fai fai PROTOTYPE: $ CODE: fai_destroy(fai); SV* fai_fetch(fai,reg) Bio::DB::Sam::Fai fai const char *reg PROTOTYPE: $$$ PREINIT: char *seq; int len; CODE: seq = fai_fetch(fai,reg,&len); if (seq == NULL) XSRETURN_EMPTY; RETVAL = newSVpv(seq,len); free((void*)seq); OUTPUT: RETVAL MODULE = Bio::DB::Sam PACKAGE = Bio::DB::Bam PREFIX=bam_ int max_pileup_cnt(packname,...) CODE: if (items > 1) MaxPileupCnt = SvIV(ST(1)); RETVAL = MaxPileupCnt; OUTPUT: RETVAL Bio::DB::Bam bam_open(packname, filename, mode="r") char * packname char * filename char * mode PROTOTYPE: $$$ CODE: RETVAL = bam_open(filename,mode); OUTPUT: RETVAL void bam_DESTROY(bam) Bio::DB::Bam bam PROTOTYPE: $ CODE: bam_close(bam); int bam_index_build(packname, filename) char * packname const char * filename CODE: RETVAL = bam_index_build(filename); OUTPUT: RETVAL void bam_sort_core(packname, is_by_qname=0, filename, prefix, max_mem=500000000) char * packname int is_by_qname char * filename char * prefix int max_mem PROTOTYPE: $$$$$ CODE: bam_sort_core(is_by_qname,filename,prefix,max_mem); Bio::DB::Bam::Index bam_index_open(packname="Bio::DB::Bam", filename) char * packname char * filename PROTOTYPE: $$ CODE: RETVAL = bam_index_load(filename); OUTPUT: RETVAL Bio::DB::Bam::Header bam_header(bam) Bio::DB::Bam bam PROTOTYPE: $ PREINIT: bam_header_t *bh; int64_t result; CODE: result = bgzf_seek(bam,0,0); bh = bam_header_read(bam); RETVAL = bh; OUTPUT: RETVAL int bam_header_write(bam,header) Bio::DB::Bam bam Bio::DB::Bam::Header header PROTOTYPE: $$ CODE: bgzf_seek(bam,0,0); RETVAL= bam_header_write(bam,header); OUTPUT: RETVAL char* bam_tell(bam) Bio::DB::Bam bam PROTOTYPE: $ CODE: int64_t t = bam_tell(bam); char string[128]; sprintf(string,"%llu",t); RETVAL = string; OUTPUT: RETVAL void bam_seek(bam,pos,dir) Bio::DB::Bam bam int pos int dir PROTOTYPE: $$$ CODE: bam_seek(bam,pos,dir); Bio::DB::Bam::Alignment bam_read1(bam) Bio::DB::Bam bam PROTOTYPE: $ PREINIT: bam1_t *b; CODE: b = bam_init1(); if (bam_read1(bam,b) >= 0) { RETVAL = b; } else XSRETURN_EMPTY; OUTPUT: RETVAL int bam_write1(bam,align) Bio::DB::Bam bam Bio::DB::Bam::Alignment align PROTOTYPE: $$ CODE: RETVAL = bam_write1(bam,align); OUTPUT: RETVAL MODULE = Bio::DB::Sam PACKAGE = Bio::DB::Bam::Alignment PREFIX=bama_ Bio::DB::Bam::Alignment bama_new(package="Bio::DB::Bam::Alignment") char * package PROTOTYPE: $ CODE: RETVAL = bam_init1(); OUTPUT: RETVAL void bama_DESTROY(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: bam_destroy1(b); int bama_tid(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.tid = SvIV(ST(1)); RETVAL=b->core.tid; OUTPUT: RETVAL int bama_pos(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.pos = SvIV(ST(1)); RETVAL=b->core.pos; OUTPUT: RETVAL int bama_calend(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=bam_calend(&b->core,bam1_cigar(b)); OUTPUT: RETVAL int bama_cigar2qlen(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=bam_cigar2qlen(&b->core,bam1_cigar(b)); OUTPUT: RETVAL int bama_qual(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.qual = SvIV(ST(1)); RETVAL=b->core.qual; OUTPUT: RETVAL int bama_flag(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.flag = SvIV(ST(1)); RETVAL=b->core.flag; OUTPUT: RETVAL int bama_n_cigar(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.n_cigar = SvIV(ST(1)); RETVAL=b->core.n_cigar; OUTPUT: RETVAL int bama_l_qseq(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.l_qseq = SvIV(ST(1)); RETVAL=b->core.l_qseq; OUTPUT: RETVAL SV* bama_qseq(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ PREINIT: char* seq; int i; CODE: seq = Newxz(seq,b->core.l_qseq+1,char); for (i=0;icore.l_qseq;i++) { seq[i]=bam_nt16_rev_table[bam1_seqi(bam1_seq(b),i)]; } RETVAL = newSVpv(seq,b->core.l_qseq); Safefree(seq); OUTPUT: RETVAL SV* bama__qscore(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL = newSVpv(bam1_qual(b),b->core.l_qseq); OUTPUT: RETVAL int bama_mtid(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.mtid = SvIV(ST(1)); RETVAL=b->core.mtid; OUTPUT: RETVAL int bama_mpos(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.mpos = SvIV(ST(1)); RETVAL=b->core.mpos; OUTPUT: RETVAL int bama_isize(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->core.isize = SvIV(ST(1)); RETVAL=b->core.isize; OUTPUT: RETVAL int bama_l_aux(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->l_aux = SvIV(ST(1)); RETVAL=b->l_aux; OUTPUT: RETVAL char* bama_aux(b) Bio::DB::Bam::Alignment b PREINIT: uint8_t *s; uint8_t type, key[2]; char str[8192]; CODE: s = bam1_aux(b); str[0] = '\0'; int left = sizeof(str) - strlen(str); while (left > 0 && (s < b->data + b->data_len)) { char* d = str+strlen(str); key[0] = s[0]; key[1] = s[1]; left -= snprintf(d, left, "%c%c:", key[0], key[1]); d += 3; s += 2; type = *s++; if (left <= 0) continue; if (type == 'A') { left -= snprintf(d, left, "A:%c", *s); s++; } else if (type == 'C') { left -= snprintf(d, left, "i:%u", *s); s++; } else if (type == 'c') { left -= snprintf(d, left, "i:%d", *s); s++; } else if (type == 'S') { left -= snprintf(d, left, "i:%u", *(uint16_t*)s);s += 2; } else if (type == 's') { left -= snprintf(d, left, "i:%d", *(int16_t*)s); s += 2; } else if (type == 'I') { left -= snprintf(d, left, "i:%u", *(uint32_t*)s);s += 4; } else if (type == 'i') { left -= snprintf(d, left, "i:%d", *(int32_t*)s); s += 4; } else if (type == 'f') { left -= snprintf(d, left, "f:%g", *(float*)s); s += 4; } else if (type == 'd') { left -= snprintf(d, left, "d:%lg", *(double*)s); s += 8; } else if (type == 'Z' || type == 'H') { left -= snprintf(d, left, "%c:", type); strncat(d,s,left); while (*s++) {} left = sizeof(str) - strlen(str); } if (left <= 0) continue; strncat(d,"\t",left); left--; } str[strlen(str)-1] = '\0'; RETVAL = str; OUTPUT: RETVAL SV* bama_aux_get(b,tag) Bio::DB::Bam::Alignment b char* tag PROTOTYPE: $$ PREINIT: int type; uint8_t *s; CODE: s = bam_aux_get_core(b,tag); if (s==0) XSRETURN_EMPTY; type = *s++; switch (type) { case 'c': RETVAL = newSViv((int32_t)*(int8_t*)s); break; case 'C': RETVAL = newSViv((int32_t)*(uint8_t*)s); break; case 's': RETVAL = newSViv((int32_t)*(int16_t*)s); break; case 'S': RETVAL = newSViv((int32_t)*(uint16_t*)s); break; case 'i': RETVAL = newSViv(*(int32_t*)s); break; case 'I': RETVAL = newSViv((int32_t)*(uint32_t*)s); break; case 'f': RETVAL = newSVnv(*(float*)s); break; case 'Z': case 'H': RETVAL = newSVpv((char*)s,0); break; case 'A': RETVAL = newSVpv((char*)s,1); break; default: XSRETURN_EMPTY; } OUTPUT: RETVAL void bama_aux_keys(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ PREINIT: uint8_t *s; uint8_t type; PPCODE: { s = bam1_aux(b); /* s is a khash macro */ while (s < b->data + b->data_len) { XPUSHs(sv_2mortal(newSVpv(s,2))); s += 2; type = *s++; if (type == 'A') { ++s; } else if (type == 'C') { ++s; } else if (type == 'c') { ++s; } else if (type == 'S') { s += 2; } else if (type == 's') { s += 2; } else if (type == 'I') { s += 4; } else if (type == 'i') { s += 4; } else if (type == 'f') { s += 4; } else if (type == 'Z' || type == 'H') { while (*s) ++(s); ++(s); } } } SV* bama_data(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ PREINIT: STRLEN len; CODE: if (items > 1) { b->data = SvPV(ST(1),len); b->data_len = len; } RETVAL=newSVpv(b->data,b->data_len); OUTPUT: RETVAL int bama_data_len(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) b->data_len = SvIV(ST(1)); RETVAL=b->data_len; OUTPUT: RETVAL int bama_m_data(b,...) Bio::DB::Bam::Alignment b PROTOTYPE: $;$ CODE: if (items > 1) { b->m_data = SvIV(ST(1)); } RETVAL=b->m_data; OUTPUT: RETVAL SV* bama_qname(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=newSVpv(bam1_qname(b),0); OUTPUT: RETVAL int bama_paired(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=(b->core.flag&BAM_FPAIRED) != 0; OUTPUT: RETVAL int bama_proper_pair(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=(b->core.flag&BAM_FPROPER_PAIR) != 0; OUTPUT: RETVAL int bama_unmapped(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=(b->core.flag&BAM_FUNMAP) != 0; OUTPUT: RETVAL int bama_munmapped(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=(b->core.flag&BAM_FMUNMAP) != 0; OUTPUT: RETVAL int bama_reversed(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=bam1_strand(b); OUTPUT: RETVAL int bama_mreversed(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ CODE: RETVAL=bam1_mstrand(b); OUTPUT: RETVAL SV* bama_cigar(b) Bio::DB::Bam::Alignment b PROTOTYPE: $ PREINIT: int i; uint32_t *c; AV *avref; CODE: avref = (AV*) sv_2mortal((SV*)newAV()); c = bam1_cigar(b); for (i=0;icore.n_cigar;i++) av_push(avref, newSViv(c[i])); RETVAL = (SV*) newRV((SV*)avref); OUTPUT: RETVAL MODULE = Bio::DB::Sam PACKAGE = Bio::DB::Bam::Header PREFIX=bam_ Bio::DB::Bam::Header bam_new(packname=Bio::DB::Bam::Header) PROTOTYPE: $ CODE: RETVAL = bam_header_init(); OUTPUT: RETVAL int bam_n_targets(bamh) Bio::DB::Bam::Header bamh PROTOTYPE: $ CODE: RETVAL = bamh->n_targets; OUTPUT: RETVAL SV* bam_target_name(bamh) Bio::DB::Bam::Header bamh PROTOTYPE: $ PREINIT: int i; AV * avref; CODE: avref = (AV*) sv_2mortal((SV*)newAV()); for (i=0;in_targets;i++) av_push(avref, newSVpv(bamh->target_name[i],0)); RETVAL = (SV*) newRV((SV*)avref); OUTPUT: RETVAL SV* bam_target_len(bamh) Bio::DB::Bam::Header bamh PROTOTYPE: $ PREINIT: int i; AV * avref; CODE: avref = (AV*) sv_2mortal((SV*)newAV()); for (i=0;in_targets;i++) av_push(avref, newSViv(bamh->target_len[i])); RETVAL = (SV*) newRV((SV*)avref); OUTPUT: RETVAL SV* bam_text(bamh, ...) Bio::DB::Bam::Header bamh PREINIT: char *newtext; STRLEN n; CODE: /* in case text is not null terminated, we copy it */ RETVAL = newSVpv(bamh->text,bamh->l_text); if (items > 1) { newtext = (char*) SvPV(ST(1),n); strcpy(bamh->text,newtext); bamh->l_text = n; } OUTPUT: RETVAL void bam_parse_region(bamh,region) Bio::DB::Bam::Header bamh char* region PROTOTYPE: $ PREINIT: int seqid,start,end; PPCODE: { bam_parse_region(bamh, region, &seqid, &start, &end); if (seqid < 0) XSRETURN_EMPTY; else { EXTEND(sp,3); PUSHs(sv_2mortal(newSViv(seqid))); PUSHs(sv_2mortal(newSViv(start))); PUSHs(sv_2mortal(newSViv(end))); } } void bam_view1(bamh,alignment) Bio::DB::Bam::Header bamh Bio::DB::Bam::Alignment alignment PROTOTYPE: $$ CODE: bam_view1(bamh,alignment); void bam_DESTROY(bamh) Bio::DB::Bam::Header bamh PROTOTYPE: $ CODE: bam_header_destroy(bamh); MODULE = Bio::DB::Sam PACKAGE = Bio::DB::Bam::Index PREFIX=bami_ int bami_fetch(bai,bfp,ref,start,end,callback,callbackdata=&PL_sv_undef) Bio::DB::Bam::Index bai Bio::DB::Bam bfp int ref int start int end CV* callback SV* callbackdata PREINIT: fetch_callback_data fcd; CODE: { fcd.callback = (SV*) callback; fcd.data = callbackdata; RETVAL = bam_fetch(bfp,bai,ref,start,end,&fcd,bam_fetch_fun); } OUTPUT: RETVAL void bami_lpileup(bai,bfp,ref,start,end,callback,callbackdata=&PL_sv_undef) Bio::DB::Bam::Index bai Bio::DB::Bam bfp int ref int start int end CV* callback SV* callbackdata PREINIT: fetch_callback_data fcd; bam_lplbuf_t *pileup; CODE: fcd.callback = (SV*) callback; fcd.data = callbackdata; pileup = bam_lplbuf_init(invoke_pileup_callback_fun,(void*)&fcd); bam_fetch(bfp,bai,ref,start,end,(void*)pileup,add_lpileup_line); bam_lplbuf_push(NULL,pileup); bam_lplbuf_destroy(pileup); void bami_pileup(bai,bfp,ref,start,end,callback,callbackdata=&PL_sv_undef) Bio::DB::Bam::Index bai Bio::DB::Bam bfp int ref int start int end CV* callback SV* callbackdata PREINIT: fetch_callback_data fcd; bam_plbuf_t *pileup; CODE: fcd.callback = (SV*) callback; fcd.data = callbackdata; pileup = bam_plbuf_init(invoke_pileup_callback_fun,(void*)&fcd); bam_plp_set_maxcnt(pileup->iter,MaxPileupCnt); bam_fetch(bfp,bai,ref,start,end,(void*)pileup,add_pileup_line); bam_plbuf_push(NULL,pileup); bam_plbuf_destroy(pileup); AV* bami_coverage(bai,bfp,ref,start,end,bins=0,maxcnt=8000) Bio::DB::Bam::Index bai Bio::DB::Bam bfp int ref int start int end int bins int maxcnt PREINIT: coverage_graph cg; bam_plbuf_t *pileup; AV* array; SV* cov; int i; bam_header_t *bh; CODE: { if (end >= MAX_REGION) { bgzf_seek(bfp,0,0); bh = bam_header_read(bfp); end = bh->target_len[ref]; bam_header_destroy(bh); } if ((bins==0) || (bins > (end-start))) bins = end-start; /* coverage graph used to communicate to our callback the region we are sampling */ cg.start = start; cg.end = end; cg.reads = 0; cg.width = ((double)(end-start))/bins; Newxz(cg.bin,bins+1,int); /* accumulate coverage into the coverage graph */ pileup = bam_plbuf_init(coverage_from_pileup_fun,(void*)&cg); if (items >= 7) bam_plp_set_maxcnt(pileup->iter,maxcnt); else bam_plp_set_maxcnt(pileup->iter,MaxPileupCnt); bam_fetch(bfp,bai,ref,start,end,(void*)pileup,add_pileup_line); bam_plbuf_push(NULL,pileup); bam_plbuf_destroy(pileup); /* now normalize to coverage/bp and convert into an array */ array = newAV(); av_extend(array,bins); for (i=0;iqpos; OUTPUT: RETVAL int pl_pos(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = pl->qpos+1; OUTPUT: RETVAL int pl_indel(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = pl->indel; OUTPUT: RETVAL int pl_level(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = pl->level; OUTPUT: RETVAL int pl_is_del(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = pl->is_del; OUTPUT: RETVAL int pl_is_refskip(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = pl->is_refskip; OUTPUT: RETVAL int pl_is_head(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = pl->is_head; OUTPUT: RETVAL int pl_is_tail(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = pl->is_tail; OUTPUT: RETVAL Bio::DB::Bam::Alignment pl_b(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = bam_dup1(pl->b); OUTPUT: RETVAL Bio::DB::Bam::Alignment pl_alignment(pl) Bio::DB::Bam::Pileup pl CODE: RETVAL = bam_dup1(pl->b); OUTPUT: RETVAL Bio-SamTools-1.39/lib/Bio/DB/Sam.pm000444001750001750 22641112207676767 16746 0ustar00lsteinlstein000000000000package Bio::DB::Sam; our $VERSION = '1.39'; =head1 NAME Bio::DB::Sam -- Read SAM/BAM database files =head1 SYNOPSIS use Bio::DB::Sam; # high level API my $sam = Bio::DB::Sam->new(-bam =>"data/ex1.bam", -fasta=>"data/ex1.fa", ); my @targets = $sam->seq_ids; my @alignments = $sam->get_features_by_location(-seq_id => 'seq2', -start => 500, -end => 800); for my $a (@alignments) { # where does the alignment start in the reference sequence my $seqid = $a->seq_id; my $start = $a->start; my $end = $a->end; my $strand = $a->strand; my $cigar = $a->cigar_str; my $paired = $a->get_tag_values('PAIRED'); # where does the alignment start in the query sequence my $query_start = $a->query->start; my $query_end = $a->query->end; my $ref_dna = $a->dna; # reference sequence bases my $query_dna = $a->query->dna; # query sequence bases my @scores = $a->qscore; # per-base quality scores my $match_qual= $a->qual; # quality of the match } my @pairs = $sam->get_features_by_location(-type => 'read_pair', -seq_id => 'seq2', -start => 500, -end => 800); for my $pair (@pairs) { my $length = $pair->length; # insert length my ($first_mate,$second_mate) = $pair->get_SeqFeatures; my $f_start = $first_mate->start; my $s_start = $second_mate->start; } # low level API my $bam = Bio::DB::Bam->open('/path/to/bamfile'); my $header = $bam->header; my $target_count = $header->n_targets; my $target_names = $header->target_name; while (my $align = $bam->read1) { my $seqid = $target_names->[$align->tid]; my $start = $align->pos+1; my $end = $align->calend; my $cigar = $align->cigar_str; } my $index = Bio::DB::Bam->index_open('/path/to/bamfile'); my $index = Bio::DB::Bam->index_open_in_safewd('/path/to/bamfile'); my $callback = sub { my $alignment = shift; my $start = $alignment->start; my $end = $alignment->end; my $seqid = $target_names->[$alignment->tid]; print $alignment->qname," aligns to $seqid:$start..$end\n"; } my $header = $index->header; $index->fetch($bam,$header->parse_region('seq2'),$callback); =head1 DESCRIPTION This module provides a Perl interface to the libbam library for indexed and unindexed SAM/BAM sequence alignment databases. It provides support for retrieving information on individual alignments, read pairs, and alignment coverage information across large regions. It also provides callback functionality for calling SNPs and performing other base-by-base functions. Most operations are compatible with the BioPerl Bio::SeqFeatureI interface, allowing BAM files to be used as a backend to the GBrowse genome browser application (gmod.sourceforge.net). =head2 The high-level API The high-level API provides a BioPerl-compatible interface to indexed BAM files. The BAM database is treated as a collection of Bio::SeqFeatureI features, and can be searched for features by name, location, type and combinations of feature tags such as whether the alignment is part of a mate-pair. When opening a BAM database using the high-level API, you provide the pathnames of two files: the FASTA file that contains the reference genome sequence, and the BAM file that contains the query sequences and their alignments. If either of the two files needs to be indexed, the indexing will happen automatically. You can then query the database for alignment features by combinations of name, position, type, and feature tag. The high-level API provides access to up to four feature "types": * "match": The "raw" unpaired alignment between a read and the reference sequence. * "read_pair": Paired alignments; a single composite feature that contains two subfeatures for the alignments of each of the mates in a mate pair. * "coverage": A feature that spans a region of interest that contains numeric information on the coverage of reads across the region. * "region": A way of retrieving information about the reference sequence. Searching for features of type "region" will return a list of chromosomes or contigs in the reference sequence, rather than read alignments. * "chromosome": A synonym for "region". B can be en masse in a single call, retrieved in a memory-efficient streaming basis using an iterator, or interrogated using a filehandle that return a series of TAM-format lines. B can be retrieved using BioPerl's feature "tag" mechanism. For example, to interrogate the FIRST_MATE flag, one fetches the "FIRST_MATE" tag: warn "aye aye captain!" if $alignment->get_tag_values('FIRST_MATE'); The Bio::SeqFeatureI interface has been extended to retrieve all flags as a compact human-readable string, and to return the CIGAR alignment in a variety of formats. B, such as reads that cover introns, are dealt with in one of two ways. The default is to leave split alignments alone: they can be detected by one or more "N" operations in the CIGAR string. Optionally, you can choose to have the API split these alignments across two or more subfeatures; the CIGAR strings of these split alignments will be adjusted accordingly. B The API provides you with access to the samtools "pileup" API. This gives you the ability to write a callback that will be invoked on every column of the alignment for the purpose of calculating coverage, quality score metrics, or SNP calling. B When you create the Bio::DB::Sam object, you can pass the path to a FASTA file containing the reference sequence. Alternatively, you may pass an object that knows how to retrieve DNA sequences across a range via the seq() of fetch_seq() methods, as described under new(). If the SAM/BAM file has MD tags, then these tags will be used to reconstruct the reference sequence when necessary, in which case you can completely omit the -fasta argument. Note that not all SAM/BAM files have MD tags, and those that do may not use them correctly due to the newness of this part of the SAM spec. You may wish to populate these tags using samtools' "calmd" command. If the -fasta argument is omitted and no MD tags are present, then the reference sequence will be returned as 'N'. The B
that you will be dealing with in the high-level API are as follows: * Bio::DB::Sam -- A collection of alignments and reference sequences. * Bio::DB::Bam::Alignment -- The alignment between a query and the reference. * Bio::DB::Bam::Query -- An object corresponding to the query sequence in which both (+) and (-) strand alignments are shown in the reference (+) strand. * Bio::DB::Bam::Target -- An interface to the query sequence in which (-) strand alignments are shown in reverse complement You may encounter other classes as well. These include: * Bio::DB::Sam::Segment -- This corresponds to a region on the reference sequence. * Bio::DB::Sam::Constants -- This defines CIGAR symbol constants and flags. * Bio::DB::Bam::AlignWrapper -- An alignment helper object that adds split alignment functionality. See Bio::DB::Bam::Alignment for the documentation on using it. * Bio::DB::Bam::ReadIterator -- An iterator that mediates the one-feature-at-a-time retrieval mechanism. * Bio::DB::Bam::FetchIterator -- Another iterator for feature-at-a-time retrieval. =head2 The low-level API The low-level API closely mirrors that of the libbam library. It provides the ability to open TAM and BAM files, read and write to them, build indexes, and perform searches across them. There is less overhead to using the API because there is very little Perl memory management, but the functions are less convenient to use. Some operations, such as writing BAM files, are only available through the low-level API. The classes you will be interacting with in the low-level API are as follows: * Bio::DB::Tam -- Methods that read and write TAM (text SAM) files. * Bio::DB::Bam -- Methods that read and write BAM (binary SAM) files. * Bio::DB::Bam::Header -- Methods for manipulating the BAM file header. * Bio::DB::Bam::Index -- Methods for retrieving data from indexed BAM files. * Bio::DB::Bam::Alignment -- Methods for manipulating alignment data. * Bio::DB::Bam::Pileup -- Methods for manipulating the pileup data structure. * Bio::DB::Sam::Fai -- Methods for creating and reading from indexed Fasta files. =head1 METHODS We cover the high-level API first. The high-level API code can be found in the files Bio/DB/Sam.pm, Bio/DB/Sam/*.pm, and Bio/DB/Bam/*.pm. =head2 Bio::DB::Sam Constructor and basic accessors =over 4 =item $sam = Bio::DB::Sam->new(%options) The Bio::DB::Sam object combines a Fasta file of the reference sequences with a BAM file to allow for convenient retrieval of human-readable sequence IDs and reference sequences. The new() constructor accepts a -name=>value style list of options as follows: Option Description ------ ------------- -bam Path to the BAM file that contains the alignments (required). When using samtools 0.1.6 or higher, an http: or ftp: URL is accepted. -fasta Path to the Fasta file that contains the reference sequences (optional). Alternatively, you may pass any object that supports a seq() or fetch_seq() method and takes the three arguments ($seq_id,$start,$end). -expand_flags A boolean value. If true then the standard alignment flags will be broken out as individual tags such as 'M_UNMAPPED' (default false). -split_splices A boolean value. If true, then alignments that are split across splices will be broken out into a single alignment containing two sub- alignments (default false). -split The same as -split_splices. -autoindex Create a BAM index file if one does not exist or the current one has a modification date earlier than the BAM file. An example of a typical new() constructor invocation is: $sam = Bio::DB::Sam->new(-fasta => '/home/projects/genomes/hu17.fa', -bam => '/home/projects/alignments/ej88.bam', -expand_flags => 1, -split_splices => 1); If the B<-fasta> argument is present, then you will be able to use the interface to fetch the reference sequence's bases. Otherwise, calls that return the reference sequence will return sequences consisting entirely of "N". B<-expand_flags> option, if true, has the effect of turning each of the standard SAM flags into a separately retrievable B in the Bio::SeqFeatureI interface. Otherwise, the standard flags will be concatenated in easily parseable form as a tag named "FLAGS". See get_all_tags() and get_tag_values() for more information. Any two-letter extension flags, such as H0 or H1, will always appear as separate tags regardless of the setting. B<-split_splices> has the effect of breaking up alignments that contain an "N" operation into subparts for more convenient manipulation. For example, if you have both paired reads and spliced alignments in the BAM file, the following code shows the subpart relationships: $pair = $sam->get_feature_by_name('E113:01:01:23'); @mates = $pair->get_SeqFeatures; @mate1_parts = $mates[0]->get_SeqFeatures; @mate2_parts = $mates[1]->get_SeqFeatures; Because there is some overhead to splitting up the spliced alignments, this option is false by default. B to BAM files located on an HTTP or FTP server is possible when using the Samtools library version 0.1.6 or higher. Simply replace the path to the BAM file with the appropriate URL. Note that incorrect URLs may lead to a core dump. It is not currently possible to refer to a remote FASTA file. These will have to be downloaded locally and indexed before using. =item $flag = $sam->expand_flags([$new_value]) Get or set the expand_flags option. This can be done after object creation and will have an immediate effect on all alignments fetched from the BAM file. =item $flag = $sam->split_splices([$new_value]) Get or set the split_splices option. This can be done after object creation and will affect all alignments fetched from the BAM file B =item $header = $sam->header Return the Bio::DB::Bam::Header object associated with the BAM file. You can manipulate the header using the low-level API. =item $bam = $sam->bam Returns the low-level Bio::DB::Bam object associated with the opened file. =item $fai = $sam->fai Returns the Bio::DB::Sam::Fai object associated with the Fasta file. You can then manipuate this object with the low-level API. B If index building is necessarily, the process will need write privileges to the same directory in which the Fasta file resides.> If the process does not have write permission, then the call will fail. Unfortunately, the BAM library does not do great error recovery for this condition, and you may experience a core dump. This is not trappable via an eval {}. =item $bai = $sam->bam_index Return the Bio::DB::Bam::Index object associated with the BAM file. B In addition, if the BAM file is not already sorted by chromosome and coordinate, it will be sorted automatically, an operation that consumes significant time and disk space. The current process must have write permission to the directory in which the BAM file resides in order for this to work.> In case of a permissions problem, the Perl library will catch the error and die. You can trap it with an eval {}. =item $sam->clone Bio::DB::SAM objects are not stable across fork() operations. If you fork, you must call clone() either in the parent or the child process before attempting to call any methods. =back =head2 Getting information about reference sequences The Bio::DB::Sam object provides the following methods for getting information about the reference sequence(s) contained in the associated Fasta file. =over 4 =item @seq_ids = $sam->seq_ids Returns an unsorted list of the IDs of the reference sequences (known elsewhere in this document as seq_ids). This is the same as the identifier following the ">" sign in the Fasta file (e.g. "chr1"). =item $num_targets = $sam->n_targets Return the number of reference sequences. =item $length = $sam->length('seqid') Returns the length of the reference sequence named "seqid". =item $seq_id = $sam->target_name($tid) Translates a numeric target ID (TID) returned by the low-level API into a seq_id used by the high-level API. =item $length = $sam->target_len($tid) Translates a numeric target ID (TID) from the low-level API to a sequence length. =item $dna = $sam->seq($seqid,$start,$end) Returns the DNA across the region from start to end on reference seqid. Note that this is a string, not a Bio::PrimarySeq object. If no -fasta path was passed when the sam object was created, then you will receive a series of N nucleotides of the requested length. =back =head2 Creating and querying segments Bio::DB::Sam::Segment objects refer regions on the reference sequence. They can be used to retrieve the sequence of the reference, as well as alignments that overlap with the region. =over 4 =item $segment = $sam->segment($seqid,$start,$end); =item $segment = $sam->segment(-seq_id=>'chr1',-start=>5000,-end=>6000); Segments are created using the Bio:DB::Sam->segment() method. It can be called using one to three positional arguments corresponding to the seq_id of the reference sequence, and optionally the start and end positions of a subregion on the sequence. If the start and/or end are undefined, they will be replaced with the beginning and end of the sequence respectively. Alternatively, you may call segment() with named -seq_id, -start and -end arguments. All coordinates are 1-based. =item $seqid = $segment->seq_id Return the segment's sequence ID. =item $start = $segment->start Return the segment's start position. =item $end = $segment->end Return the segment's end position. =item $strand = $segment->strand Return the strand of the segment (always 0). =item $length = $segment->length Return the length of the segment. =item $dna = $segment->dna Return the DNA string for the reference sequence under this segment. =item $seq = $segment->seq Return a Bio::PrimarySeq object corresponding to the sequence of the reference under this segment. You can get the actual DNA string in this redundant-looking way: $dna = $segment->seq->seq The advantage of working with a Bio::PrimarySeq object is that you can perform operations on it, including taking its reverse complement and subsequences. =item @alignments = $segment->features(%args) Return alignments that overlap the segment in the associated BAM file. The optional %args list allows you to filter features by name, tag or other attributes. See the documentation of the Bio::DB::Sam->features() method for the full list of options. Here are some typical examples: # get all the overlapping alignments @all_alignments = $segment->features; # get an iterator across the alignments my $iterator = $segment->features(-iterator=>1); while (my $align = $iterator->next_seq) { do something } # get a TAM filehandle across the alignments my $fh = $segment->features(-fh=>1); while (<$fh>) { print } # get only the alignments with unmapped mates my @unmapped = $segment->features(-flags=>{M_UNMAPPED=>1}); # get coverage across this region my ($coverage) = $segment->features('coverage'); my @data_points = $coverage->coverage; # grep through features using a coderef my @reverse_alignments = $segment->features( -filter => sub { my $a = shift; return $a->strand < 0; }); =item $tag = $segment->primary_tag =item $tag = $segment->source_tag Return the strings "region" and "sam/bam" respectively. These methods allow the segment to be passed to BioPerl methods that expect Bio::SeqFeatureI objects. =item $segment->name, $segment->display_name, $segment->get_SeqFeatures, $segment->get_tag_values These methods are provided for Bio::SeqFeatureI compatibility and don't do anything of interest. =back =head2 Retrieving alignments, mate pairs and coverage information The features() method is an all-purpose tool for retrieving alignment information from the SAM/BAM database. In addition, the methods get_features_by_name(), get_features_by_location() and others provide convenient shortcuts to features(). These methods either return a list of features, an iterator across a list of features, or a filehandle opened on a pseudo-TAM file. =over 4 =item @features = $sam->features(%options) =item $iterator = $sam->features(-iterator=>1,%more_options) =item $filehandle = $sam->features(-fh=>1,%more_options) =item @features = $sam->features('type1','type2'...) This is the all-purpose interface for fetching alignments and other types of features from the database. Arguments are a -name=>value option list selected from the following list of options: Option Description ------ ------------- -type Filter on features of a given type. You may provide either a scalar typename, or a reference to an array of desired feature types. Valid types are "match", "read_pair", "coverage" and "chromosome." See below for a full explanation of feature types. -name Filter on reads with the designated name. Note that this can be a slow operation unless accompanied by the feature location as well. -seq_id Filter on features that align to seq_id between start -start and end. -start and -end must be used in conjunction -end with -seq_id. If -start and/or -end are absent, they will default to 1 and the end of the reference sequence, respectively. -flags Filter features that match a list of one or more flags. See below for the format. -attributes The same as -flags, for compatibility with other -tags APIs. -filter Filter on features with a coderef. The coderef will receive a single argument consisting of the feature and should return true to keep the feature, or false to discard it. -iterator Instead of returning a list of features, return an iterator across the results. To retrieve the results, call the iterator's next_seq() method repeatedly until it returns undef to indicate that no more matching features remain. -fh Instead of returning a list of features, return a filehandle. Read from the filehandle to retrieve each of the results in TAM format, one alignment per line read. This only works for features of type "match." The high-level API introduces the concept of a B in order to provide several convenience functions. You specify types by using the optional B<-type> argument. The following types are currently supported: B. The "match" type corresponds to the unprocessed SAM alignment. It will retrieve single reads, either mapped or unmapped. Each match feature's primary_tag() method will return the string "match." The features returned by this call are of type Bio::DB::Bam::AlignWrapper. B. The "paired_end" type causes the sam interface to find and merge together mate pairs. Fetching this type of feature will yield a series of Bio::SeqFeatureI objects, each as long as the total distance on the reference sequence spanned by the mate pairs. The top-level feature is of type Bio::SeqFeature::Lite; it contains two Bio::DB::Bam::AlignWrapper subparts. Call get_SeqFeatures() to get the two individual reads. Example: my @pairs = $sam->features(-type=>'read_pair'); my $p = $pairs[0]; my $i_length = $p->length; my @ends = $p->get_SeqFeatures; my $left = $ends[0]->start; my $right = $ends[1]->end; B. The "coverage" type causes the sam interface to calculate coverage across the designated region. It only works properly if accompanied by the desired location of the coverage graph; -seq_id is a mandatory argument for coverage calculation, and -start and -end are optional. The call will return a single Bio::SeqFeatureI object whose primary_tag() is "coverage." To recover the coverage data, call the object's coverage() method to obtain an array (list context) or arrayref (scalar context) of coverage counts across the region of interest: my ($coverage) = $sam->features(-type=>'coverage',-seq_id=>'seq1'); my @data = $coverage->coverage; my $total; for (@data) { $total += $_ } my $average_coverage = $total/@data; By default the coverage graph will be at the base pair level. So for a region 5000 bp wide, coverage() will return an array or arrayref with exactly 5000 elements. However, you also have the option of calculating the coverage across larger bins. Simply append the number of intervals you are interested to the "coverage" typename. For example, fetching "coverage:500" will return a feature whose coverage() method will return the coverage across 500 intervals. B or B. The "chromosome" or "region" type are interchangeable. They ask the sam interface to construct Bio::DB::Sam::Segment representing the reference sequences. These two calls give similar results: my $segment = $sam->segment('seq2',1=>500); my ($seg) = $sam->features(-type=>'chromosome', -seq_id=>'seq2',-start=>1,-end=>500); Due to an unresolved bug, you cannot fetch chromosome features in the same call with matches and other feature types call. Specifically, this works as expected: my @chromosomes = $sam->features (-type=>'chromosome'); But this doesn't (as of 18 June 2009): my @chromosomes_and_matches = $sam->features(-type=>['match','chromosome']); If no -type argument is provided, then features() defaults to finding features of type "match." You may call features() with a plain list of strings (positional arguments, not -type=>value arguments). This will be interpreted as a list of feature types to return: my ($coverage) = $sam->features('coverage') For a description of the methods available in the features returned from this call, please see L and L. You can B "match" and "read_pair" features by name, location and/or flags. The name and flag filters are not very efficient. Unless they are combined with a location filter, they will initiate an exhaustive search of the BAM database. Name filters are case-insensitive, and allow you to use shell-style "*" and "?" wildcards. Flag filters created with the B<-flag>, B<-attribute> or B<-tag> options have the following syntax: -flag => { FLAG_NAME_1 => ['list','of','possible','values'], FLAG_NAME_2 => ['list','of','possible','values'], ... } The value of B<-flag> is a hash reference in which the keys are flag names and the values are array references containing lists of acceptable values. The list of values are OR'd with each other, and the flag names are AND'd with each other. The B<-filter> option provides a completely generic filtering interface. Provide a reference to a subroutine. It will be called once for each potential feature. Return true to keep the feature, or false to discard it. Here is an example of how to find all matches whose alignment quality scores are greater than 80. @features = $sam->features(-filter=>sub {shift->qual > 80} ); By default, features() returns a list of all matching features. You may instead request an iterator across the results list by passing -iterator=>1. This will give you an object that has a single method, next_seq(): my $high_qual = $sam->features(-filter => sub {shift->qual > 80}, -iterator=> 1 ); while (my $feature = $high_qual->next_seq) { # do something with the alignment } Similarly, by passing a true value to the argument B<-fh>, you can obtain a filehandle to a virtual TAM file. This only works with the "match" feature type: my $high_qual = $sam->features(-filter => sub {shift->qual > 80}, -fh => 1 ); while (my $tam_line = <$high_qual>) { chomp($tam_line); # do something with it } =item @features = $sam->get_features_by_name($name) Convenience method. The same as calling $sam->features(-name=>$name); =item $feature = $sam->get_feature_by_name($name) Convenience method. The same as ($sam->features(-name=>$name))[0]. =item @features = $sam->get_features_by_location($seqid,$start,$end) Convenience method. The same as calling $sam->features(-seq_id=>$seqid,-start=>$start,-end=>$end). =item @features = $sam->get_features_by_flag(%flags) Convenience method. The same as calling $sam->features(-flags=>\%flags). This method is also called get_features_by_attribute() and get_features_by_tag(). Example: @features = $sam->get_features_by_flag(H0=>1) =item $feature = $sam->get_feature_by_id($id) The high-level API assigns each feature a unique ID composed of its read name, position and strand and returns it when you call the feature's primary_id() method. Given that ID, this method returns the feature. =item $iterator = $sam->get_seq_stream(%options) Convenience method. This is the same as calling $sam->features(%options,-iterator=>1). =item $fh = $sam->get_seq_fh(%options) Convenience method. This is the same as calling $sam->features(%options,-fh=>1). =item $fh = $sam->tam_fh Convenience method. It is the same as calling $sam->features(-fh=>1). =item @types = $sam->types This method returns the list of feature types (e.g. "read_pair") returned by the current version of the interface. =back =head2 The generic fetch() and pileup() methods Lastly, the high-level API supports two methods for rapidly traversing indexed BAM databases. =over 4 =item $sam->fetch($region,$callback) This method, which is named after the native bam_fetch() function in the C interface, traverses the indicated region and invokes a callback code reference on each match. Specify a region using the BAM syntax "seqid:start-end", or either of the alternative syntaxes "seqid:start..end" and "seqid:start,end". If start and end are absent, then the entire reference sequence is traversed. If end is absent, then the end of the reference sequence is assumed. The callback will be called repeatedly with a Bio::DB::Bam::AlignWrapper on the argument list. Example: $sam->fetch('seq1:600-700', sub { my $a = shift; print $a->display_name,' ',$a->cigar_str,"\n"; }); Note that the fetch() operation works on reads that B the indicated region. Therefore the callback may be called for reads that align to the reference at positions that start before or end after the indicated region. =item $sam->pileup($region,$callback [,$keep_level]) This method, which is named after the native bam_lpileupfile() function in the C interfaces, traverses the indicated region and generates a "pileup" of all the mapped reads that cover it. The user-provided callback function is then invoked on each position of the alignment along with a data structure that provides access to the individual aligned reads. As with fetch(), the region is specified as a string in the format "seqid:start-end", "seqid:start..end" or "seqid:start,end". The callback is a coderef that will be invoked with three arguments: the seq_id of the reference sequence, the current position on the reference (in 1-based coordinates!), and a reference to an array of Bio::DB::Bam::Pileup objects. Here is the typical call signature: sub { my ($seqid,$pos,$pileup) = @_; # do something } For example, if you call pileup on the region "seq1:501-600", then the callback will be invoked for all reads that overlap the indicated region. The first invocation of the callback will typically have a $pos argument somewhat to the left of the desired region and the last call will be somewhat to the right. You may wish to ignore positions that are outside of the requested region. Also be aware that the reference sequence position uses 1-based coordinates, which is different from the low-level interface, which use 0-based coordinates. The optional $keep_level argument, if true, asks the BAM library to keep track of the level of the read in the multiple alignment, an operation that generates some overhead. This is mostly useful for text alignment viewers, and so is off by default. The size of the $pileup array reference indicates the read coverage at that position. Here is a simple average coverage calculator: my $depth = 0; my $positions = 0; my $callback = sub { my ($seqid,$pos,$pileup) = @_; next unless $pos >= 501 && $pos <= 600; $positions++; $depth += @$pileup; } $sam->pileup('seq1:501-600',$callback); print "coverage = ",$depth/$positions; Each Bio::DB::Bam::Pileup object describes the position of a read in the alignment. Briefly, Bio::DB::Bam::Pileup has the following methods: $pileup->alignment The alignment at this level (a Bio::DB::Bam::AlignWrapper object). $pileup->qpos The position of the read base at the pileup site, in 0-based coordinates. $pileup->pos The position of the read base at the pileup site, in 1-based coordinates; $pileup->level The level of the read in the multiple alignment view. Note that this field is only valid when $keep_level is true. $pileup->indel Length of the indel at this position: 0 for no indel, positive for an insertion (relative to the reference), negative for a deletion (relative to the reference.) $pileup->is_del True if the base on the padded read is a deletion. $pileup->is_refskip True if the base on the padded read is a gap relative to the reference (denoted as < or > in the pileup) $pileup->is_head Undocumented field in the bam.h header file. $pileup->is_tail Undocumented field in the bam.h header file. See L for a very simple SNP caller. =item $sam->fast_pileup($region,$callback [,$keep_level]) This is identical to pileup() except that the pileup object returns low-level Bio::DB::Bam::Alignment objects rather than the higher-level Bio::DB::Bam::AlignWrapper objects. This makes it roughly 50% faster, but you lose the align objects' seq_id() and get_tag_values() methods. As a compensation, the callback receives an additional argument corresponding to the Bio::DB::Sam object. You can use this to create AlignWrapper objects on an as needed basis: my $callback = sub { my($seqid,$pos,$pileup,$sam) = @_; for my $p (@$pileup) { my $alignment = $p->alignment; my $wrapper = Bio::DB::Bam::AlignWrapper->new($alignment,$sam); my $has_mate = $wrapper->get_tag_values('PAIRED'); } }; =item Bio::DB::Sam->max_pileup_cnt([$new_cnt]) =item $sam->max_pileup_cnt([$new_cnt]) The Samtools library caps pileups at a set level, defaulting to 8000. The callback will not be invoked on a single position more than the level set by the cap, even if there are more reads. Called with no arguments, this method returns the current cap value. Called with a numeric argument, it changes the cap. There is currently no way to specify an unlimited cap. This method can be called as an instance method or a class method. =item $sam->coverage2BedGraph([$fh]) This special-purpose method will compute a four-column BED graph of the coverage across the entire SAM/BAM file and print it to STDOUT. You may provide a filehandle to redirect output to a file or pipe. =back The next sections correspond to the low-level API, which let you create and manipulate Perl objects that correspond directly to data structures in the C interface. A major difference between the high and low level APIs is that in the high-level API, the reference sequence is identified using a human-readable seq_id. However, in the low-level API, the reference is identified using a numeric target ID ("tid"). The target ID is established during the creation of the BAM file and is a small 0-based integer index. The Bio::DB::Bam::Header object provides methods for converting from seq_ids to tids. =head2 Indexed Fasta Files These methods relate to the BAM library's indexed Fasta (".fai") files. =over 4 =item $fai = Bio::DB::Sam::Fai->load('/path/to/file.fa') Load an indexed Fasta file and return the object corresponding to it. If the index does not exist, it will be created automatically. Note that you pass the path to the Fasta file, not the index. For consistency with Bio::DB::Bam->open() this method is also called open(). =item $dna_string = $fai->fetch("seqid:start-end") Given a sequence ID contained in the Fasta file and optionally a subrange in the form "start-end", finds the indicated subsequence and returns it as a string. =back =head2 TAM Files These methods provide interfaces to the "TAM" text version of SAM files; they often have a .sam extension. =over 4 =item $tam = Bio::DB::Tam->open('/path/to/file.sam') Given the path to a SAM file, opens it for reading. The file can be compressed with gzip if desired. =item $header = $tam->header_read() Create and return a Bio::DB::Bam::Header object from the information contained within @SQ header lines of the Sam file. If there are no @SQ lines, then the header will not be useful, and you should call header_read2() to generate the missing information from the appropriate indexed Fasta file. Here is some code to illustrate the suggested logic: my $header = $tam->header_read; unless ($header->n_targets > 0) { $header = $tam->header_read2('/path/to/file.fa.fai'); } =item $header = $tam->header_read2('/path/to/file.fa.fai') Create and return a Bio::DB::Bam::Header object from the information contained within the indexed Fasta file of the reference sequences. Note that you have to pass the path to the .fai file, and not the .fa file. The header object contains information on the reference sequence names and lengths. =item $bytes = $tam->read1($header,$alignment) Given a Bio::DB::Bam::Header object, such as the one created by header_read2(), and a Bio::DB::Bam::Alignment object created by Bio::DB::Bam::Alignment->new(), reads one line of alignment information into the alignment object from the TAM file and returns a status code. The result code will be the number of bytes read. =back =head2 BAM Files These methods provide interfaces to the "BAM" binary version of SAM. They usually have a .bam extension. =over 4 =item $bam = Bio::DB::Bam->open('/path/to/file.bam' [,$mode]) Open up the BAM file at the indicated path. Mode, if present, must be one of the file stream open flags ("r", "w", "a", "r+", etc.). If absent, mode defaults to "r". Note that Bio::DB::Bam objects are not stable across fork() operations. If you fork, and intend to use the object in both parent and child, you must reopen the Bio::DB::Bam in either the child or the parent (but not both) before attempting to call any of the object's methods. The path may be an http: or ftp: URL, in which case a copy of the index file will be downloaded to the current working directory (see below) and all accesses will be performed on the remote BAM file. Example: $bam = Bio::DB::Bam->open('http://some.site.com/nextgen/chr1_bowtie.bam'); =item $header = $bam->header() Given an open BAM file, return a Bio::DB::Bam::Header object containing information about the reference sequence(s). Note that you must invoke header() at least once before calling read1(). =item $status_code = $bam->header_write($header) Given a Bio::DB::Bam::Header object and a BAM file opened in write mode, write the header to the file. If the write fails the process will be terminated at the C layer. The result code is (currently) always zero. =item $integer = $bam->tell() Return the current position of the BAM file read/write pointer. =item $bam->seek($integer,$pos) Set the current position of the BAM file read/write pointer. $pos is one of SEEK_SET, SEEK_CUR, SEEK_END. These constants can be obtained from the Fcntl module by importing the ":seek" group: use Fcntl ':seek'; =item $alignment = $bam->read1() Read one alignment from the BAM file and return it as a Bio::DB::Bam::Alignment object. Note that you must invoke header() at least once before calling read1(). =item $bytes = $bam->write1($alignment) Given a BAM file that has been opened in write mode and a Bio::DB::Bam::Alignment object, write the alignment to the BAM file and return the number of bytes successfully written. =item Bio::DB::Bam->sort_core($by_qname,$path,$prefix,$max_mem) Attempt to sort a BAM file by chromosomal location or name and create a new sorted BAM file. Arguments are as follows: Argument Description -------- ----------- $by_qname If true, sort by read name rather than chromosomal location. $path Path to the BAM file $prefix Prefix to use for the new sorted file. For example, passing "foo" will result in a BAM file named "foo.bam". $max_mem Maximum core memory to use for the sort. If the sort requires more than this amount of memory, intermediate sort files will be written to disk. The default, if not provided is 500M. =back =head2 BAM index methods The Bio::DB::Bam::Index object provides access to BAM index (.bai) files. =over 4 =item $status_code = Bio::DB::Bam->index_build('/path/to/file.bam') Given the path to a .bam file, this function attempts to build a ".bai" index. The process in which the .bam file exists must be writable by the current process and there must be sufficient disk space for the operation or the process will be terminated in the C library layer. The result code is currently always zero, but in the future may return a negative value to indicate failure. =item $index = Bio::DB::Bam->index('/path/to/file.bam',$reindex) Attempt to open the index for the indicated BAM file. If $reindex is true, and the index either does not exist or is out of date with respect to the BAM file (by checking modification dates), then attempt to rebuild the index. Will throw an exception if the index does not exist or if attempting to rebuild the index was unsuccessful. =item $index = Bio::DB::Bam->index_open('/path/to/file.bam') Attempt to open the index file for a BAM file, returning a Bio::DB::Bam::Index object. The filename path to use is the .bam file, not the .bai file. =item $index = Bio::DB::Bam->index_open_in_safewd('/path/to/file.bam' [,$mode]) When opening a remote BAM file, you may not wish for the index to be downloaded to the current working directory. This version of index_open copies the index into the directory indicated by the TMPDIR environment variable or the system-defined /tmp directory if not present. You may change the environment variable just before the call to change its behavior. =item $code = $index->fetch($bam,$tid,$start,$end,$callback [,$callback_data]) This is the low-level equivalent of the $sam->fetch() function described for the high-level API. Given a open BAM file object, the numeric ID of the reference sequence, start and end ranges on the reference, and a coderef, this function will traverse the region and repeatedly invoke the coderef with each Bio::DB::Bam::Alignment object that overlaps the region. Arguments: Argument Description -------- ----------- $bam The Bio::DB::Bam object that corresponds to the index object. $tid The target ID of the reference sequence. This can be obtained by calling $header->parse_region() with an appropriate opened Bio::DB::Bam::Header object. $start The start and end positions of the desired range on the reference sequence given by $tid, in 0-based $end coordinates. Like the $tid, these can be obtained from $header->parse_region(). $callback A coderef that will be called for each read overlapping the designated region. $callback_data Any arbitrary Perl data that you wish to pass to the $callback (optional). The coderef's call signature should look like this: my $callback = sub { my ($alignment,$data) = @_; ... } The first argument is a Bio::DB::Bam::Alignment object. The second is the callback data (if any) passed to fetch(). Fetch() returns an integer code, but its meaning is not described in the SAM/BAM C library documentation. =item $index->pileup($bam,$tid,$start,$end,$callback [,$callback_data]) This is the low-level version of the pileup() method, which allows you to invoke a coderef for every position in a BAM alignment. Arguments are: Argument Description -------- ----------- $bam The Bio::DB::Bam object that corresponds to the index object. $tid The target ID of the reference sequence. This can be obtained by calling $header->parse_region() with an appropriate opened Bio::DB::Bam::Header object. $start The start and end positions of the desired range on the reference sequence given by $tid, in 0-based $end coordinates. Like the $tid, these can be obtained from $header->parse_region(). $callback A coderef that will be called for each position of the alignment across the designated region. $callback_data Any arbitrary Perl data that you wish to pass to the $callback (optional). The callback will be invoked with four arguments corresponding to the numeric sequence ID of the reference sequence, the B position on the alignment, an arrayref of Bio::DB::Bam::Pileup objects, and the callback data, if any. A typical call signature will be this: $callback = sub { my ($tid,$pos,$pileups,$callback_data) = @_; for my $pileup (@$pileups) { # do something }; Note that the position argument is zero-based rather than 1-based, as it is in the high-level API. The Bio::DB::Bam::Pileup object was described earlier in the description of the high-level pileup() method. =item $coverage = $index->coverage($bam,$tid,$start,$end [,$bins [,maxcnt]]) Calculate coverage for the region on the target sequence given by $tid between positions $start and $end (zero-based coordinates). This method will return an array reference equal to the size of the region (by default). Each element of the array will be an integer indicating the number of reads aligning over that position. If you provide an option binsize in $bins, the array will be $bins elements in length, and each element will contain the average coverage over that region as a floating point number. By default, the underlying Samtools library caps coverage counting at a fixed value of 8000. You may change this default by providing an optional numeric sixth value, which changes the cap for the duration of the call, or by invoking Bio::DB::Sam->max_pileup_cnt($new_value), which changes the cap permanently. Unfortunately there is no way of specifying that you want an unlimited cap. =back =head2 BAM header methods The Bio::DB::Bam::Header object contains information regarding the reference sequence(s) used to construct the corresponding TAM or BAM file. It is most frequently used to translate between numeric target IDs and human-readable seq_ids. Headers can be created either from reading from a .fai file with the Bio::DB::Tam->header_read2() method, or by reading from a BAM file using Bio::DB::Bam->header(). You can also create header objects from scratch, although there is not much that you can do with such objects at this point. =over 4 =item $header = Bio::DB::Bam::Header->new() Return a new, empty, header object. =item $n_targets = $header->n_targets Return the number of reference sequences in the database. =item $name_arrayref = $header->target_name Return a reference to an array of reference sequence names, corresponding to the high-level API's seq_ids. To convert from a target ID to a seq_id, simply index into this array: $seq_id = $header->target_name->[$tid]; =item $length_arrayref = $header->target_len Return a reference to an array of reference sequence lengths. To get the length of the sequence corresponding to $tid, just index into the array returned by target_len(): $length = $header->target_len->[$tid]; =item $text = $header->text =item $header->text("new value") Read the text portion of the BAM header. The text can be replaced by providing the replacement string as an argument. Note that you should follow the header conventions when replacing the header text. No parsing or other error-checking is performed. =item ($tid,$start,$end) = $header->parse_region("seq_id:start-end") Given a string in the format "seqid:start-end" (using a human-readable seq_id and 1-based start and end coordinates), parse the string and return the target ID and start and end positions in 0-based coordinates. If the range is omitted, then the start and end coordinates of the entire sequence is returned. If only the end position is omitted, then the end of the sequence is assumed. =item $header->view1($alignment) This method will accept a Bio::DB::Bam::Alignment object, convert it to a line of TAM output, and write the output to STDOUT. In the low-level API there is currently no way to send the output to a different filehandle or capture it as a string. =back =head2 Bio::DB::Bam::Pileup methods An array of Bio::DB::Bam::Pileup object is passed to the pileup() callback for each position of a multi-read alignment. Each pileup object contains information about the alignment of a single read at a single position. =over 4 =item $alignment = $pileup->alignment Return the Bio::DB::Bam::Alignment object at this level. This provides you with access to the aligning read. =item $alignment = $pileup->b An alias for alignment(), provided for compatibility with the C API. =item $pos = $pileup->qpos The position of the aligning base in the read in zero-based coordinates. =item $pos = $pileup->pos The position of the aligning base in 1-based coordinates. =item $level = $pileup->level The "level" of the read in the BAM-generated text display of the alignment. =item $indel = $pileup->indel Length of the indel at this position: 0 for no indel, positive for an insertion (relative to the reference), negative for a deletion (relative to the reference sequence.) =item $flag = $pileup->is_del True if the base on the padded read is a deletion. =item $flag = $pileup->is_refskip True if the base on the padded read is a gap relative to the reference (denoted as < or > in the pileup) =item $flag = $pileup->is_head =item $flag = $pileup->is_del These fields are undocumented in the BAM documentation, but are exported to the Perl API just in case. =back =head2 The alignment objects Please see L for documentation of the Bio::DB::Bam::Alignment and Bio::DB::Bam::AlignWrapper objects. =cut use strict; use warnings; use Carp 'croak'; use Bio::SeqFeature::Lite; use Bio::PrimarySeq; use base 'DynaLoader'; bootstrap Bio::DB::Sam; use Bio::DB::Bam::Alignment; use Bio::DB::Sam::Segment; use Bio::DB::Bam::AlignWrapper; use Bio::DB::Bam::PileupWrapper; use Bio::DB::Bam::FetchIterator; use Bio::DB::Bam::ReadIterator; use constant DUMP_INTERVAL => 1_000_000; sub new { my $class = shift; my %args = $_[0] =~ /^-/ ? @_ : (-bam=>shift); my $bam_path = $args{-bam} or croak "-bam argument required"; my $fa_path = $args{-fasta}; my $expand_flags = $args{-expand_flags}; my $split_splices = $args{-split} || $args{-split_splices}; my $autoindex = $args{-autoindex}; # file existence checks unless ($class->is_remote($bam_path)) { -e $bam_path or croak "$bam_path does not exist"; -r _ or croak "is not readable"; } my $bam = Bio::DB::Bam->open($bam_path) or croak "$bam_path open: $!"; my $fai = $class->new_dna_accessor($fa_path) if $fa_path; my $self = bless { fai => $fai, bam => $bam, bam_path => $bam_path, fa_path => $fa_path, expand_flags => $expand_flags, split_splices => $split_splices, autoindex => $autoindex, },ref $class || $class; $self->header; # catch it return $self; } sub bam { shift->{bam} } sub is_remote { my $self = shift; my $path = shift; return $path =~ /^(http|ftp):/; } sub clone { my $self = shift; $self->{bam} = Bio::DB::Bam->open($self->{bam_path}) if $self->{bam_path}; $self->{fai} = $self->new_dna_accessor($self->{fa_path}) if $self->{fa_path}; } sub header { my $self = shift; return $self->{header} ||= $self->{bam}->header; } sub fai { shift->{fai} } sub new_dna_accessor { my $self = shift; my $accessor = shift; return unless $accessor; if (-e $accessor) { # a file, assume it is a fasta file -r _ or croak "$accessor is not readable"; my $a = Bio::DB::Sam::Fai->open($accessor) or croak "$accessor open: $!" or croak "Can't open FASTA file $accessor: $!"; return $a; } if (ref $accessor && $self->can_do_seq($accessor)) { return $accessor; # already built } return; } sub can_do_seq { my $self = shift; my $obj = shift; return UNIVERSAL::can($obj,'seq') || UNIVERSAL::can($obj,'fetch_sequence'); } sub seq { my $self = shift; my ($seqid,$start,$end) = @_; my $fai = $self->fai or return 'N' x ($end-$start+1); return $fai->can('seq') ? $fai->seq($seqid,$start,$end) :$fai->can('fetch_sequence') ? $fai->fetch_sequence($seqid,$start,$end) :'N' x ($end-$start+1); } sub expand_flags { my $self = shift; my $d = $self->{expand_flags}; $self->{expand_flags} = shift if @_; $d; } sub split_splices { my $self = shift; my $d = $self->{split_splices}; $self->{split_splices} = shift if @_; $d; } sub autoindex { my $self = shift; my $d = $self->{autoindex}; $self->{autoindex} = shift if @_; $d; } sub reset_read { my $self = shift; $self->{bam}->header; } sub n_targets { shift->header->n_targets; } sub target_name { my $self = shift; my $tid = shift; $self->{target_name} ||= $self->header->target_name; return $self->{target_name}->[$tid]; } sub target_len { my $self = shift; my $tid = shift; $self->{target_len} ||= $self->header->target_len; return $self->{target_len}->[$tid]; } sub seq_ids { my $self = shift; return @{$self->header->target_name}; } sub _cache_targets { my $self = shift; return $self->{targets} if exists $self->{targets}; my @targets = map {lc $_} @{$self->header->target_name}; my @lengths = @{$self->header->target_len}; my %targets; @targets{@targets} = @lengths; # just you try to figure out what this is doing! return $self->{targets} = \%targets; } sub length { my $self = shift; my $target_name = shift; return $self->_cache_targets->{lc $target_name}; } sub _fetch { my $self = shift; my $region = shift; my $callback = shift; my $header = $self->{bam}->header; $region =~ s/\.\.|,/-/; my ($seqid,$start,$end) = $header->parse_region($region); return unless defined $seqid; my $index = $self->bam_index; $index->fetch($self->{bam},$seqid,$start,$end,$callback,$self); } sub fetch { my $self = shift; my $region = shift; my $callback = shift; my $code = sub { my ($align,$self) = @_; $callback->(Bio::DB::Bam::AlignWrapper->new($align,$self)); }; $self->_fetch($region,$code); } sub pileup { my $self = shift; my ($region,$callback,$keep_level) = @_; my $header = $self->header; $region =~ s/\.\.|,/-/; my ($seqid,$start,$end) = $header->parse_region($region); return unless defined $seqid; my $refnames = $self->header->target_name; my $code = sub { my ($tid,$pos,$pileup) = @_; my $seqid = $refnames->[$tid]; my @p = map { Bio::DB::Bam::PileupWrapper->new($_,$self) } @$pileup; $callback->($seqid,$pos+1,\@p); }; my $index = $self->bam_index; if ($keep_level) { $index->lpileup($self->{bam},$seqid,$start,$end,$code); } else { $index->pileup($self->{bam},$seqid,$start,$end,$code); } } sub fast_pileup { my $self = shift; my ($region,$callback,$keep_level) = @_; my $header = $self->header; $region =~ s/\.\.|,/-/; my ($seqid,$start,$end) = $header->parse_region($region); return unless defined $seqid; my $refnames = $self->header->target_name; my $code = sub { my ($tid,$pos,$pileup) = @_; my $seqid = $refnames->[$tid]; $callback->($seqid,$pos+1,$pileup,$self); }; my $index = $self->bam_index; if ($keep_level) { $index->lpileup($self->{bam},$seqid,$start,$end,$code); } else { $index->pileup($self->{bam},$seqid,$start,$end,$code); } } # segment returns a segment across the reference # it will not work on a arbitrary aligned feature sub segment { my $self = shift; my ($seqid,$start,$end) = @_; if ($_[0] =~ /^-/) { my %args = @_; $seqid = $args{-seq_id} || $args{-name}; $start = $args{-start}; $end = $args{-stop} || $args{-end}; } else { ($seqid,$start,$end) = @_; } my $targets = $self->_cache_targets; return unless exists $targets->{lc $seqid}; $start = 1 unless defined $start; $end = $targets->{lc $seqid} unless defined $end; $start = 1 if $start < 1; $end = $targets->{lc $seqid} if $end > $targets->{lc $seqid}; return Bio::DB::Sam::Segment->new($self,$seqid,$start,$end); } sub get_features_by_location { my $self = shift; my %args; if ($_[0] =~ /^-/) { # named args %args = @_; } else { # positional args $args{-seq_id} = shift; $args{-start} = shift; $args{-end} = shift; } $self->features(%args); } sub get_features_by_attribute { my $self = shift; my %attributes = ref($_[0]) ? %{$_[0]} : @_; $self->features(-attributes=>\%attributes); } sub get_features_by_tag { shift->get_features_by_attribute(@_); } sub get_features_by_flag { shift->get_features_by_attribute(@_); } sub get_feature_by_name { my $self = shift; my %args; if ($_[0] =~ /^-/) { %args = @_; } else { $args{-name} = shift; } $self->features(%args); } sub get_features_by_name { shift->get_feature_by_name(@_) } sub get_feature_by_id { my $self = shift; my $id = shift; my ($name,$tid,$start,$end,$strand,$type) = map {s/%3B/;/ig;$_} split ';',$id; return unless $name && defined $tid; $type ||= 'match'; my $seqid = $self->target_name($tid); my @features = $self->features(-name=>$name, -type => $type, -seq_id=>$seqid, -start=>$start, -end=>$end, -strand=>$strand); return unless @features; return $features[0]; } sub get_seq_stream { my $self = shift; $self->features(@_,-iterator=>1); } sub get_seq_fh { my $self = shift; $self->features(@_,-fh=>1); } sub types { return qw(match read_pair coverage region chromosome); } sub features { my $self = shift; my %args; if (defined $_[0] && $_[0] !~ /^-/) { $args{-type} = \@_; } else { %args = @_; } my $seqid = $args{-seq_id} || $args{-seqid}; my $start = $args{-start}; my $end = $args{-end} || $args{-stop}; my $types = $args{-type} || $args{-types} || []; my $attributes = $args{-attributes} || $args{-tags} || $args{-flags}; my $iterator = $args{-iterator}; my $fh = $args{-fh}; my $filter = $args{-filter}; my $max = $args{-max_features}; $types = [$types] unless ref $types; $types = [$args{-class}] if !@$types && defined $args{-class}; my $use_index = defined $seqid; # we do some special casing to retrieve target (reference) sequences # if they are requested if (defined($args{-name}) && (!@$types || $types->[0]=~/region|chromosome/) && !defined $seqid) { my @results = $self->_segment_search(lc $args{-name}); return @results if @results; } elsif (@$types && $types->[0] =~ /region|chromosome/) { return map {$self->segment($_)} $self->seq_ids; } my %seenit; my @types = grep {!$seenit{$_}++} ref $types ? @$types : $types; @types = 'match' unless @types; # the filter is intended to be inserted into a closure # it will return undef from the closure unless the filter # criteria are satisfied if (!$filter) { $filter = ''; $filter .= $self->_filter_by_name(lc $args{-name}) if defined $args{-name}; $filter .= $self->_filter_by_attribute($attributes) if defined $attributes; } # Special cases for unmunged data if (@types == 1 && $types[0] =~ /^match/) { # if iterator is requested, and no indexing is possible, # then we directly iterate through the database using read1() if ($iterator && !$use_index) { $self->reset_read; my $code = eval "sub {my \$a=shift;$filter;1}"; die $@ if $@; return Bio::DB::Bam::ReadIterator->new($self,$self->{bam},$code); } # TAM filehandle retrieval is requested elsif ($fh) { return $self->_features_fh($seqid,$start,$end,$filter); } } # otherwise we're going to do a little magic my ($features,@result); for my $t (@types) { if ($t =~ /^(match|read_pair)/) { # fetch the features if type is 'match' or 'read_pair' $features = $self->_filter_features($seqid,$start,$end,$filter,undef,$max); # for "match" just return the alignments if ($t =~ /^(match)/) { push @result,@$features; } # otherwise aggregate mate pairs into two-level features elsif ($t =~ /^read_pair/) { $self->_build_mates($features,\@result); } next; } # create a coverage graph if type is 'coverage' # specify coverage:N, to create a map of N bins # units are coverage per bp # resulting array will be stored in the "coverage" attribute if ($t =~ /^coverage:?(\d*)/) { my $bins = $1; push @result,$self->_coverage($seqid,$start,$end,$bins,$filter); } } return $iterator ? Bio::DB::Bam::FetchIterator->new(\@result,$self->last_feature_count) : @result; } sub coverage2BedGraph { my $self = shift; my $fh = shift; $fh ||= \*STDOUT; my $header = $self->header; my $index = $self->bam_index; my $seqids = $header->target_name; my $lengths = $header->target_len; my $b = $self->bam; for my $tid (0..$header->n_targets-1) { my $seqid = $seqids->[$tid]; my $len = $lengths->[$tid]; my $sec_start = -1; my $last_val = -1; for (my $start=0;$start <= $len;$start += DUMP_INTERVAL) { my $end = $start+DUMP_INTERVAL; $end = $len if $end > $len; my $coverage = $index->coverage($b,$tid,$start,$end); for (my $i=0; $i<@$coverage; $i++) { if($last_val == -1) { $sec_start = 0; $last_val = $coverage->[$i]; } if($last_val != $coverage->[$i]) { print $fh $seqid,"\t",$sec_start,"\t",$start+$i,"\t",$last_val,"\n" unless $last_val == 0; $sec_start = $start+$i; $last_val = $coverage->[$i]; } elsif($start+$i == $len-1) { print $fh $seqid,"\t",$sec_start,"\t",$start+$i,"\t",$last_val,"\n" unless $last_val == 0; } } } } } sub _filter_features { my $self = shift; my ($seqid,$start,$end,$filter,$do_tam_fh,$max_features) = @_; my @result; my $action = $do_tam_fh ? '\$self->header->view1($a)' : $self->_push_features($max_features); my $user_code; if (ref ($filter) eq 'CODE') { $user_code = $filter; $filter = ''; } my $callback = defined($seqid) ? <start; $action; } INDEXED sub { my \$a = shift; $filter $action; } NONINDEXED ; my $code = eval $callback; die $@ if $@; if ($user_code) { my $new_callback = sub { my $a = shift; $code->($a) if $user_code->($a); }; $self->_features($seqid,$start,$end,$new_callback); } else { $self->_features($seqid,$start,$end,$code); } return \@result; } sub _push_features { my $self = shift; my $max = shift; # simple case -- no max specified. Will push onto an array called # @result. return 'push @result,Bio::DB::Bam::AlignWrapper->new($a,$self)' unless $max; $self->{_result_count} = 0; # otherwise we implement a simple subsampling my $code=<{_result_count}; if (\@result < $max) { push \@result,Bio::DB::Bam::AlignWrapper->new(\$a,\$self); } else { \$result[rand \@result] = Bio::DB::Bam::AlignWrapper->new(\$a,\$self) if rand() < $max/\$count; } END return $code; } sub last_feature_count { shift->{_result_count}||0 } sub _features { my $self = shift; my ($seqid,$start,$end,$callback) = @_; if (defined $seqid) { my $region = $seqid; if (defined $start) { $region .= ":$start"; $region .= "-$end" if defined $end; } $self->_fetch($region,$callback); } else { $self->reset_read; while (my $b = $self->{bam}->read1) { $callback->($b); } } } # build mate pairs sub _build_mates { my $self = shift; my ($src,$dest) = @_; my %read_pairs; for my $a (@$src) { my $name = $a->display_name; unless ($read_pairs{$name}) { my $isize = $a->isize; my $start = $isize >= 0 ? $a->start : $a->end+$isize+1; my $end = $isize <= 0 ? $a->end : $a->start+$isize-1; $read_pairs{$name} = Bio::SeqFeature::Lite->new( -display_name => $name, -seq_id => $a->seq_id, -start => $start, -end => $end, -type => 'read_pair', -class => 'read_pair', ); } my $d = $self->{split_splices}; if ($d) { my @parts = $a->get_SeqFeatures; if (!@parts) { $read_pairs{$name}->add_SeqFeature($a); } else { for my $x (@parts){ $read_pairs{$name}->add_SeqFeature($x); } } } else { $read_pairs{$name}->add_SeqFeature($a); } } for my $name (keys %read_pairs) { my $f = $read_pairs{$name}; my $primary_id = join(';', map {s/;/%3B/g; $_} ($f->display_name, ($f->get_SeqFeatures)[0]->tid, $f->start, $f->end, $f->strand, $f->type, ) ); $read_pairs{$name}->primary_id($primary_id); } push @$dest,values %read_pairs; } sub _coverage { my $self = shift; my ($seqid,$start,$end,$bins,$filter) = @_; # Currently filter is ignored. In reality, we should # turn filter into a callback and invoke it on each # position in the pileup. croak "cannot calculate coverage unless a -seq_id is provided" unless defined $seqid; my $region = $seqid; if (defined $start) { $region .= ":$start"; $region .= "-$end" if defined $end; } my $header = $self->{bam}->header; my ($id,$s,$e) = $header->parse_region($region); return unless defined $id; # parse_region may return a very high value if no end specified $end = $e >= 1<<29 ? $header->target_len->[$id] : $e; $start = $s+1; $bins ||= $end-$start+1; my $index = $self->bam_index; my $coverage = $index->coverage($self->{bam}, $id,$s,$e, $bins); return Bio::SeqFeature::Coverage->new( -display_name => "$seqid coverage", -seq_id => $seqid, -start => $start, -end => $end, -strand => 0, -type => "coverage:$bins", -class => "coverage:$bins", -attributes => { coverage => [$coverage] } ); } sub _segment_search { my $self = shift; my $name = shift; my $targets = $self->_cache_targets; return $self->segment($name) if $targets->{$name}; if (my $regexp = $self->_glob_match($name)) { my @results = grep {/^$regexp$/i} keys %$targets; return map {$self->segment($_)} @results; } return; } sub bam_index { my $self = shift; return $self->{bai} ||= Bio::DB::Bam->index($self->{bam_path},$self->autoindex); } sub _features_fh { my $self = shift; my ($seqid,$start,$end,$filter) = @_; my $result = open my $fh,"-|"; if (!$result) { # in child $self->_filter_features($seqid,$start,$end,$filter,'do_fh'); # will print TAM to stdout exit 0; } return $fh; } sub tam_fh { my $self = shift; return $self->features(-fh=>1); } sub max_pileup_cnt { my $self = shift; return Bio::DB::Bam->max_pileup_cnt(@_); } # return a fragment of code that will be placed in the eval "" filter # to eliminate alignments that don't match by name sub _filter_by_name { my $self = shift; my $name = shift; my $frag = "my \$name=\$a->qname; defined \$name or return; "; if (my $regexp = $self->_glob_match($name)) { $frag .= "return unless \$name =~ /^$regexp\$/i;\n"; } else { $frag .= "return unless lc \$name eq '$name';\n"; } } # return a fragment of code that will be placed in the eval "" filter # to eliminate alignments that don't match by attribute sub _filter_by_attribute { my $self = shift; my $attributes = shift; my $result; for my $tag (keys %$attributes) { $result .= "my \$value = lc \$a->get_tag_values('$tag');\n"; $result .= "return unless defined \$value;\n"; my @comps = ref $attributes->{$tag} eq 'ARRAY' ? @{$attributes->{$tag}} : $attributes->{$tag}; my @matches; for my $c (@comps) { if ($c =~ /^[+-]?[\deE.]+$/) { # numeric-looking argument push @matches,"CORE::length \$value && \$value == $c"; } elsif (my $regexp = $self->_glob_match($c)) { push @matches,"\$value =~ /^$regexp\$/i"; } else { push @matches,"\$value eq lc '$c'"; } } $result .= "return unless " . join (' OR ',@matches) . ";\n"; } return $result; } # turn a glob expression into a regexp sub _glob_match { my $self = shift; my $term = shift; return unless $term =~ /(?:^|[^\\])[*?]/; $term =~ s/(^|[^\\])([+\[\]^{}\$|\(\).])/$1\\$2/g; $term =~ s/(^|[^\\])\*/$1.*/g; $term =~ s/(^|[^\\])\?/$1./g; return $term; } package Bio::DB::Sam::Fai; sub open { shift->load(@_) } sub seq { my $self = shift; my ($seqid,$start,$end) = @_; my $region = $seqid; $region .= ":$start" if defined $start; $region .= "-$end" if defined $end; return $self->fetch($region) } package Bio::SeqFeature::Coverage; use base 'Bio::SeqFeature::Lite'; sub coverage { my $self = shift; my ($coverage) = $self->get_tag_values('coverage'); return wantarray ? @$coverage : $coverage; } sub source { my $self = shift; my $type = $self->type; my ($base,$width) = split ':',$type; return $width; } sub method { my $self = shift; my $type = $self->type; my ($base,$width) = split ':',$type; return $base; } sub gff3_string { my $self = shift; my $gff3 = $self->SUPER::gff3_string; my $coverage = $self->escape(join(',',$self->coverage)); $gff3 =~ s/coverage=[^;]+/coverage=$coverage/g; return $gff3; } package Bio::DB::Bam; use File::Spec; use Cwd; use Carp 'croak'; sub index { my $self = shift; my $path = shift; my $autoindex = shift; return $self->index_open_in_safewd($path) if Bio::DB::Sam->is_remote($path); if ($autoindex) { $self->reindex($path) unless -e "${path}.bai" && mtime($path) <= mtime("${path}.bai"); } croak "No index file for $path; try opening file with -autoindex" unless -e "${path}.bai"; return $self->index_open($path); } sub reindex { my $self = shift; my $path = shift; # if bam file is not sorted, then index_build will exit. # we spawn a shell to intercept this eventuality print STDERR "[bam_index_build] creating index for $path\n" if -t STDOUT; my $result = open my $fh,"-|"; die "Couldn't fork $!" unless defined $result; if ($result == 0) { # in child # dup stderr to stdout so that we can intercept messages from library open STDERR,">&STDOUT"; $self->index_build($path); exit 0; } my $mesg = <$fh>; $mesg ||= ''; close $fh; if ($mesg =~ /not sorted/i) { print STDERR "[bam_index_build] sorting by coordinate...\n" if -t STDOUT; $self->sort_core(0,$path,"$path.sorted"); rename "$path.sorted.bam",$path; $self->index_build($path); } elsif ($mesg) { die $mesg; } } # same as index_open(), but changes current wd to TMPDIR to accomodate # the C library when it tries to download the index file from remote # locations. sub index_open_in_safewd { my $self = shift; my $dir = getcwd; my $tmpdir = File::Spec->tmpdir; chdir($tmpdir); my $result = $self->index_open(@_); chdir $dir; $result; } sub mtime { my $path = shift; (stat($path))[9]; } 1; __END__ =head1 EXAMPLES For illustrative purposes only, here is an extremely stupid SNP caller that tallies up bases that are q>20 and calls a SNP if there are at least 4 non-N/non-indel bases at the position and at least 25% of them are a non-reference base. my @SNPs; # this will be list of SNPs my $snp_caller = sub { my ($seqid,$pos,$p) = @_; my $refbase = $sam->segment($seqid,$pos,$pos)->dna; my ($total,$different); for my $pileup (@$p) { my $b = $pileup->alignment; next if $pileup->indel or $pileup->is_refskip; # don't deal with these ;-) my $qbase = substr($b->qseq,$pileup->qpos,1); next if $qbase =~ /[nN]/; my $qscore = $b->qscore->[$pileup->qpos]; next unless $qscore > 25; $total++; $different++ if $refbase ne $qbase; } if ($total >= 4 && $different/$total >= 0.25) { push @SNPs,"$seqid:$pos"; } }; $sam->pileup('seq1',$snp_caller); print "Found SNPs: @SNPs\n"; =head1 GBrowse Compatibility The Bio::DB::Sam interface can be used as a backend to GBrowse (gmod.sourceforge.net/gbrowse). GBrowse can calculate and display coverage graphs across large regions, alignment cartoons across intermediate size regions, and detailed base-pair level alignments across small regions. Here is a typical configuration for a BAM database that contains information from a shotgun genomic sequencing project. Some notes: * It is important to set "search options = none" in order to avoid GBrowse trying to scan through the BAM database to match read names. This is a time-consuming operation. * The callback to "bgcolor" renders pairs whose mates are unmapped in red. * The callback to "balloon hover" causes a balloon to pop up with the read name when the user hovers over each paired read. Otherwise the default behavior would be to provide information about the pair as a whole. * When the user zooms out to 1001 bp or greaterp, the track switches to a coverage graph. [bamtest:database] db_adaptor = Bio::DB::Sam db_args = -bam /var/www/gbrowse2/databases/bamtest/ex1.bam search options= default [Pair] feature = read_pair glyph = segments database = bamtest draw_target = 1 show_mismatch = 1 bgcolor = sub { my $f = shift; return $f->get_tag_values('M_UNMAPPED') ? 'red' : 'green'; } fgcolor = green height = 3 label = sub {shift->display_name} label density = 50 bump = fast connector = dashed balloon hover = sub { my $f = shift; return '' unless $f->type eq 'match'; return 'Read: '.$f->display_name.' : '.$f->flag_str; } key = Read Pairs [Pair:1000] feature = coverage:1001 glyph = wiggle_xyplot height = 50 min_score = 0 autoscale = local To show alignment data correctly when the user is zoomed in, you should also provide a pointer to the FASTA file containing the reference genome. In this case, modify the db_args line to read: db_args = -bam /var/www/gbrowse2/databases/bamtest/ex1.bam -fasta /var/www/gbrowse2/databases/bamtest/ex1.fa =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Elincoln.stein@bmail.comE Copyright (c) 2009 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut Bio-SamTools-1.39/lib/Bio/DB/Bam000755001750001750 012207676767 16164 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/lib/Bio/DB/Bam/Query.pm000444001750001750 1070712207676767 20011 0ustar00lsteinlstein000000000000package Bio::DB::Bam::Query; # $Id$ =head1 NAME Bio::DB::Bam::Query -- Object representing the query portion of a BAM/SAM alignment =head1 SYNOPSIS Given an alignment retrieved from a Bio::DB::Sam database, my $query = $alignment->query; my $name = $query->display_name; my $start = $query->start; my $end = $query->end; my $dna = $query->dna; # dna string my $seq = $query->seq; # Bio::PrimarySeq object my @scores = $query->qscore; # quality score =head1 DESCRIPTION This is a simple Bio::SeqFeatureI object that represents the query part of a SAM alignment. =head2 Methods =over 4 =cut use strict; use Bio::DB::Sam; use Bio::DB::Sam::Constants qw(CIGAR_SYMBOLS BAM_CREF_SKIP BAM_CSOFT_CLIP BAM_CHARD_CLIP); use constant CIGAR_SKIP => {CIGAR_SYMBOLS->[BAM_CREF_SKIP] => 1, CIGAR_SYMBOLS->[BAM_CSOFT_CLIP] => 1, CIGAR_SYMBOLS->[BAM_CHARD_CLIP] => 1}; sub new { my $self = shift; my $alignment = shift; bless \$alignment,ref $self || $self; } =item $seqid = $query->seq_id The name of the read. =cut sub seq_id { my $self = shift; $$self->qname; } =item $name = $query->name The read name (same as seq_id in this case). =cut sub name { my $self = shift; $$self->qname; } =item $name = $query->display_name The read display_name (same as seq_id in this case). =cut sub display_name {shift->name} =item $tag = $query->primary_tag The string "match". =cut sub primary_tag { ${shift()}->primary_tag } =item $tag = $query->source_tag The string "sam/bam". =cut sub source_tag { ${shift()}->source_tag } =item $start = $query->start The start of the match in read coordinates. =cut sub start { my $self = shift; return $self->low; } =item $end = $query->end The end of the match in read coordinates; =cut sub end { my $self = shift; return $self->high; } sub low { my $self = shift; my $cigar_arry = $$self->cigar_array; my $start = 1; for my $c (@$cigar_arry) { last unless CIGAR_SKIP->{$c->[0]}; $start += $c->[1]; } $start; } sub high { my $self = shift; my $len = $$self->cigar2qlen; my $cigar_arry = $$self->cigar_array; # alignment stops at first non-clip CIGAR position my $i = $len - 1; for my $c (reverse @$cigar_arry) { last unless CIGAR_SKIP->{$c->[0]}; $len -= $c->[1]; } return $len; } =item $len = $query->length The length of the read. =cut sub length { my $self = shift; $self->high-$self->low+1; # $$self->cigar2qlen; } =item $seq = $query->seq A Bio::PrimarySeq representing the read sequence in REFERENCE orientation. =cut sub seq { my $self = shift; my $dna = $self->dna; return Bio::PrimarySeq->new(-seq => $dna, -id => $$self->qname); } =item $scores = $query->qscore The read quality scores. In a list context, a list of integers equal in length to the read sequence length. In a scalar context, an array ref. The qscores are in REFERENCE sequence orientation. =cut sub qscore { my $self = shift; my @qscore = $$self->qscore; return wantarray ? @qscore : \@qscore; } =item $dna = $query->dna The DNA string in reference sequence orientation. =cut sub dna { my $self = shift; return $$self->qseq || ('N' x $self->length); } =item $strand = $query->strand If the query was reversed to align it, -1. Otherwise +1. =cut sub strand { my $self = shift; return $$self->reversed ? -1 : 1; } =item $seq = $query->subseq($start,$end) Return a Bio::PrimarySeq object representing the requested subsequence on the read. =cut sub subseq { my $self = shift; my ($start,$end) = @_; $start = 1 if $start < 1; $end = $self->high if $end > $self->high; ($end,$start) = ($start,$end) if $start > $end; return Bio::PrimarySeq->new(-seq=>substr($self->dna, $start-1, $end-$start+1) ); } 1; =back =head1 SEE ALSO L, L, L, L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Elincoln.stein@bmail.comE Copyright (c) 2009 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut Bio-SamTools-1.39/lib/Bio/DB/Bam/Alignment.pm000444001750001750 4202712207676767 20622 0ustar00lsteinlstein000000000000package Bio::DB::Bam::Alignment; # $Id$ =head1 NAME Bio::DB::Bam::Alignment -- The SAM/BAM alignment object =head1 SYNOPSIS use Bio::DB::Sam; my $sam = Bio::DB::Sam->new(-fasta=>"data/ex1.fa", -bam =>"data/ex1.bam"); my @alignments = $sam->get_features_by_location(-seq_id => 'seq2', -start => 500, -end => 800); for my $a (@alignments) { my $seqid = $a->seq_id; my $start = $a->start; my $end = $a->end; my $strand = $a->strand; my $ref_dna= $a->dna; my $query_start = $a->query->start; my $query_end = $a->query->end; my $query_strand = $a->query->strand; my $query_dna = $a->query->dna; my $cigar = $a->cigar_str; my @scores = $a->qscore; # per-base quality scores my $match_qual= $a->qual; # quality of the match my $paired = $a->get_tag_values('PAIRED'); } =head1 DESCRIPTION The Bio::DB::Bam::Alignment and Bio::DB::Bam::AlignWrapper classes together represent an alignment between a sequence read (the "query") and a reference sequence (the "target"). Bio::DB::Bam::Alignment adheres strictly to the C-level BAM library's definition of a bam1_t* and is used in the Bio::DB::Sam low-level API The latter adds convenience methods that make it similar to a BioPerl Bio::SeqFeatureI object. This manual page describes both. =head1 High-level Bio::DB::Bam::Alignment methods These methods are provided by Bio::DB::Bam::Alignment, and are intended to be compatible with the Bio::SeqFeatureI interfaces. Note that these objects are B compatible with Bio::Align::AlignI, as the BAM API is fundamentally incompatible with the BioPerl API for alignments (the first deals with the alignment of a single read against the reference sequence, while the second deals with a multiple alignment). Note that the high-level API return Bio::DB::Bam::AlignWrapper objects B in the case of the callback to the fast_pileup() method. In this case only, the object returned by calling $pileup->b() is a Bio::DB::Bam::Alignment object for performance reasons. =over 4 =item $seq_id = $align->seq_id Return the seq_id of the reference (target) sequence. This method is only available in the Bio::DB::Bam::AlignWrapper extension. =item $start = $align->start Return the start of the alignment in 1-based reference sequence coordinates. =item $end = $align->end Return the end of the alignment in 1-based reference sequence coordinates. =item $len = $align->length Return the length of the alignment on the reference sequence. =item $mseqid = $align->mate_seq_id Return the seq_id of the mate's reference (target) sequence. This method is only available in the Bio::DB::AlignWrapper extension. =item $mstart = $align->mate_start For paired reads, return the start of the mate's alignment in 1-based reference sequence coordinates. =item $mend = $align->mate_end For paired reads, return the end position of the mate's alignment in 1-based reference sequence coordinates. =item $mlen = $align->mate_len For mate-pairs, retrieve the length of the mate's alignment on the reference sequence. =item $strand = $align->strand Return the strand of the alignment as -1 for reversed, +1 for forward. NOTE: In versions 1.00-1.06, this method always returned +1. As of version 1.07, this behavior is fixed. =item $mstrand = $align->mstrand If the read has a mate pair, return the strand of the mate in the format -1 or +1. =item $ref_dna = $align->dna Returns the B sequence's DNA across the aligned region. If an MD tag is present in the alignment, it will be used preferentially to reconstruct the reference sequence. Otherwise the reference DNA access object passed to Bio::DB::Sam->new() will be used. =item $ref_dna = $align->seq The B sequence's DNA as a Bio::PrimarySeqI object (useful for passing to BioPerl functions and for calculating subsequences and reverse complements). =item $query = $align->query This method returns a Bio::DB::Alignment::Query object that can be used to retrieve information about the query sequence. The next few entries show how to use this object. =item $read_name = $align->query->name The name of the read. =item $q_start = $align->query->start This returns the start position of the query (read) sequence in 1-based coordinates. It acts via a transient Bio::DB::Bam::Query object that is provided for Bio::Graphics compatibility (see L). =item $q_end = $align->query->end This returns the end position of the query sequence in 1-based coordinates. =item $q_len = $align->query->length Return the length of the alignment on the read. =item $scores = $align->query->score Return an array reference containing the unpacked quality scores for each base of the query sequence. The length of this array reference will be equal to the length of the read. =item $read_dna = $align->query->dna The read's DNA string. =item $read_seq = $align->query->seq The read's DNA as a Bio::PrimarySeqI object. =item $target = $align->target; The target() method is similar to query(), except that it follows Bio::AlignIO conventions for how to represent minus strand alignments. The object returned has start(), end(), qscore(), dna() and seq() methods, but for minus strand alignments the sequence will be represented as it appears on the reverse strand, rather than on the forward strand. This has the advantage of giving you the read as it came off the machine, before being reverse complemented for use in the SAM file. =item $query = $align->hit The hit() method is identical to target() and returns information about the read. It is present for compatibility with some of the Bio::Graphics glyphs, which use hit() to represent the non-reference sequence in aligned sequences. =item $primary_id = $align->primary_id This method synthesizes a unique ID for the alignment which can be passed to $sam->get_feature_by_id() to retrieve the alignment at a later date. =item @tags = $align->get_all_tags Return all tag names known to this alignment. This includes SAM flags such as M_UNMAPPED, as well as auxiliary flags such as H0. The behavior of this method depends on the value of -expand_flags when the SAM object was created. If false (the default), then the standard SAM flags will be concatenated together into a single string and stored in a tag named 'FLAGS'. The format of this tag value is the list of one or more flag constants separated by the "|" character, as in: "PAIRED|MAP_PAIR|REVERSED|SECOND_MATE". If -expand_flags was true, then each flag becomes its own named tag, such as "MAP_PAIR". =item @values = $align->get_tag_values($tag) Given a tag name, such as 'PAIRED' or 'H0', return its value(s). -expand_flags must be true in order to use the standard SAM flag constants as tags. Otherwise, they can be fetched by asking for the "FLAGS" tag, or by using the low-level methods described below. =item $is_true = $align->has_tag($tag) Return true if the alignment has the indicated tag. =item $string = $align->cigar_str Return the CIGAR string for this alignment in conventional human readable format (e.g. "M34D1M1"). =item $arrayref = $align->cigar_array Return a reference to an array representing the CIGAR string. This is an array of arrays, in which each subarray consists of a CIGAR operation and a count. Example: [ ['M',34], ['D',1], ['M1',1] ] =item ($ref,$matches,$query) = $align->padded_alignment Return three strings that show the alignment between the reference sequence (the target) and the query. It will look like this: $ref AGTGCCTTTGTTCA-----ACCCCCTTGCAACAACC $matches |||||||||||||| ||||||||||||||||| $query AGTGCCTTTGTTCACATAGACCCCCTTGCAACAACC =item $str = $align->aux Returns the text version of the SAM tags, e.g. "XT:A:M NM:i:2 SM:i:37 AM:i:37 XM:i:1 XO:i:1 XG:i:1 MD:Z:6^C0A47" =item $str = $align->tam_line Returns the TAM (text) representation of the alignment (available in the high-level "AlignWrapper" interface only). =item $tag = $align->primary_tag This is provided for Bio::SeqFeatureI compatibility. Return the string "match". =item $tag = $align->source_tag This is provided for Bio::SeqFeatureI compatibility. Return the string "sam/bam". =item @parts = $align->get_SeqFeatures Return subfeatures of this alignment. If you have fetched a "read_pair" feature, this will be the two mate pair objects (both of type Bio::DB::Bam::AlignWrapper). If you have -split_splices set to true in the Bio::DB::Sam database, calling get_SeqFeatures() will return the components of split alignments. See L for an example of how to use this. =back =head1 Low-level Bio::DB::Bam::Alignment methods These methods are available to objects of type Bio::DB::Bam::Alignment as well as Bio::DB::Bam::AlignWrapper and closely mirror the native C API. =over 4 =item $align = Bio::DB::Bam::Alignment->new Create a new, empty alignment object. This is usually only needed when iterating through a TAM file using Bio::DB::Tam->read1(). =item $tid = $align->tid( [$new_tid] ) Return the target ID of the alignment. Optionally you may change the tid by providing it as an argument (currently this is the only field that you can change; the functionality was implemented as a proof of principle). =item $read_name = $align->qname Returns the name of the read. =item $pos = $align->pos 0-based leftmost coordinate of the aligned sequence on the reference sequence. =item $end = $align->calend The 0-based rightmost coordinate of the aligned sequence on the reference sequence after taking alignment gaps into account. =item $len = $align->cigar2qlen The length of the query sequence calculated from the CIGAR string. =item $quality = $align->qual The quality score for the alignment as a whole. =item $flag = $align->flag The bitwise flag field (see the SAM documentation). =item $mtid = $align->mtid For paired reads, the target ID of the mate's alignemnt. =item $mpos = $align->mpos For paired reads, the 0-based leftmost coordinate of the mate's alignment on the reference sequence. =item $n_cigar = $align->n_cigar Number of CIGAR operations in this alignment. =item $length = $align->l_qseq The length of the query sequence (the read). =item $dna = $align->qseq The actual DNA sequence of the query. As in the SAM file, reads that are aligned to the minus strand of the reference are returned in reverse complemented form. =item $score_str = $align->_qscore A packed binary string containing the quality scores for each base of the read. It will be the same length as the DNA. You may unpack it using unpack('C*',$score_str), or use the high-level qscore() method. =item $score_arry = $align->qscore =item @score_arry = $align->qscore In a scalar context return an array reference containing the unpacked quality scores for each base of the query sequence. In a list context return a list of the scores. This array is in the same orientation as the reference sequence. =item $length = $align->isize The calculated insert size for mapped paired reads. =item $length = $align->l_aux The length of the align "auxiliary" data. =item $value = $align->aux_get("tag") Given an auxiliary tag, such as "H0", return its value. =item @keys = $align->aux_keys Return the list of auxiliary tags known to this alignment. =item $data = $align->data Return a packed string containing the alignment data (sequence, quality scores and cigar string). =item $length = $align->data_len Return the current length of the alignment data. =item $length = $align->m_data Return the maximum length of the alignment data. =item $is_paired = $align->paired Return true if the aligned read is part of a mate/read pair (regardless of whether the mate mapped). =item $is_proper = $align->proper_pair Return true if the aligned read is part of a mate/read pair and both partners mapped to the reference sequence. =item $is_unmapped = $align->unmapped Return true if the read failed to align. =item $mate_is_unmapped = $align->munmapped Return true if the read's mate failed to align. =item $reversed = $align->reversed Return true if the aligned read was reverse complemented prior to aligning. =item $mate_reversed = $align->mreversed Return true if the aligned read's mate was reverse complemented prior to aligning. =item $isize = $align->isize For mate-pairs, return the computed insert size. =item $arrayref = $align->cigar This returns the CIGAR data in its native BAM format. You will receive an arrayref in which each operation and count are packed together into an 8-bit structure. To decode each element you must use the following operations: use Bio::DB::Sam::Constants; my $c = $align->cigar; my $op = $c->[0] & BAM_CIGAR_MASK; my $len = $c->[0] >> BAM_CIGAR_SHIFT; =back =cut use strict; use warnings; use Bio::DB::Bam::Query; use Bio::DB::Bam::Target; use Bio::DB::Sam::Constants; sub each_tag_value { shift->get_tag_values(@_) } sub get_tag_values { my $self = shift; my $tag = shift; defined $tag or return; if (my $mask = RFLAGS->{uc $tag}) { # special tag # to avoid warnings when making numeric comps return ($self->flag & $mask) == 0 ? 0 : 1; } elsif ($tag eq 'FLAGS') { $self->flag_str; } else { $self->aux_get($tag); } } sub has_tag { my $self = shift; my $tag = shift; defined $tag or return; if (my $mask = RFLAGS->{uc $tag}) { # special tag return 1; } elsif ($tag eq 'FLAGS') { return 1; } else { my %keys = map {$_=>1} $self->aux_keys; return exists $keys{uc $tag}; } } sub get_all_tags { my $self = shift; my @aux_tags = $self->aux_keys; my @flag_tags = keys %{RFLAGS()}; return (@aux_tags,@flag_tags); } sub start { my $self = shift; return if $self->pos < 0 || $self->unmapped; return $self->pos+1; } sub end { my $self = shift; return if $self->unmapped; return $self->calend; } sub stop { shift->end } # in SAM format, alignment is always to the forward strand sub strand { return shift->reversed ? -1 : 1; } sub abs_strand { shift->strand } sub mstrand { my $self = shift; return $self->mreversed ? -1 : 1; } sub display_name { return shift->qname; } sub qscore { my $self = shift; my $scores = $self->_qscore; my @scores = unpack('C*',$scores); return wantarray ? @scores : \@scores; } sub primary_id { my $self = shift; return join ';', map {s/;/%3B/g; $_} ($self->display_name, $self->tid, $self->start, $self->end, $self->strand); } sub cigar_str { my $self = shift; my $cigar = $self->cigar; my $result = ''; for my $c (@$cigar) { my $op = $c & BAM_CIGAR_MASK; my $l = $c >> BAM_CIGAR_SHIFT(); my $symbol = CIGAR_SYMBOLS()->[$op]; $result .= "${l}${symbol}"; } return $result; } sub cigar_array { my $self = shift; my $cigar = $self->cigar; my @result; for my $c (@$cigar) { my $op = $c & BAM_CIGAR_MASK(); my $l = $c >> BAM_CIGAR_SHIFT(); my $symbol = CIGAR_SYMBOLS()->[$op]; push @result,[$symbol,$l]; } return \@result; } sub flag_str { my $self = shift; my $flag = $self->flag; my $flags = FLAGS; return join '|',map {$flags->{$_}} grep {$flag & $_} sort {$a<=>$b} keys %{$flags}; } sub length { my $self = shift; my $end = $self->end || 0; my $start = $self->start || 0; return $end-$start+1; } sub mate_start { my $self = shift; return if $self->mpos < 0 || $self->munmapped; return $self->mpos+1; } sub mate_len { my $self = shift; my $ins_len = $self->isize or return; my $len = $self->length; my $adjust = 0; my @cigar = $self->cigar_str =~ /(\d+)(\w)/g; while (@cigar) { my ($len,$op) = splice(@cigar,0,2); $adjust += $len if $op eq 'I'; $adjust -= $len if $op eq 'D'; } return $adjust + $ins_len + ($self->start-$self->mate_start) if $ins_len > 0; return $adjust + $self->mate_start-($self->start+$ins_len) if $ins_len < 0; } sub mate_end { my $self = shift; return unless $self->mate_len; return $self->mate_start+$self->mate_len-1; } sub query { my $self = shift; return Bio::DB::Bam::Query->new($self); } sub get_SeqFeatures { return; } # Target is the same as Query, but with meaning of start() and end() reversed # for compatibility with Bio::DB::GFF and its ilk. Please use Query if you can! sub target { my $self = shift; return Bio::DB::Bam::Target->new($self); } sub primary_tag { 'match' } sub source_tag { 'sam/bam' } sub hit { shift->target(@_); } 1; =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Elincoln.stein@bmail.comE Copyright (c) 2009 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut Bio-SamTools-1.39/lib/Bio/DB/Bam/Pileup.pm000444001750001750 462512207676767 20124 0ustar00lsteinlstein000000000000package Bio::DB::Bam::Pileup; # $Id$ # documentation only 1; =head1 NAME Bio::DB::Bam::Pileup -- Object passed to pileup() callback =head1 SYNOPSIS See L for how this object is passed to pileup callbacks. =head1 DESCRIPTION A Bio::DB::Bam::Pileup object (or a Bio::DB::Bam::PileupWrapper object) is passed to the callback passed to the Bio::DB::Sam->pileup() method for each column in a sequence alignment. The only difference between the two is that the latter returns the more convenient Bio::DB::Bam::AlignWrapper objects in response to the alignment() method, at the cost of some performance loss. =head2 Methods =over 4 =item $alignment = $pileup->alignment Return the Bio::DB::Bam::Alignment or Bio::DB::Bam::AlignWrapper object representing the aligned read. =item $alignment = $pileup->b This method is an alias for alignment(). It is available for compatibility with the C API. =item $qpos = $pileup->qpos Return the position of this aligned column in read coordinates, using zero-based coordinates. =item $pos = $pileup->pos Return the position of this aligned column in read coordinates, using 1-based coordinates. =item $indel = $pileup->indel If this column is an indel, return a positive integer for an insertion relative to the reference, a negative integer for a deletion relative to the reference, or 0 for no indel at this column. =item $is_del = $pileup->is_del True if the base on the padded read is a deletion. =item $level = $pileup->level If pileup() or fast_pileup() was invoked with the "keep_level" flag, then this method will return a positive integer indicating the level of the read in a printed multiple alignment. =item $pileup->is_head =item $pileup->is_tail These fields are defined in bam.h but their interpretation is obscure. =back =head1 SEE ALSO L, L, L, L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Elincoln.stein@bmail.comE Copyright (c) 2009 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut Bio-SamTools-1.39/lib/Bio/DB/Bam/PileupWrapper.pm000444001750001750 362412207676767 21463 0ustar00lsteinlstein000000000000package Bio::DB::Bam::PileupWrapper; #$Id$ =head1 NAME Bio::DB::Bam::PileupWrapper -- Add high-level methods to Bio::DB::Bam::Pileup =head1 SYNOPSIS See L for usage of the pileup() method. =head1 DESCRIPTION See L for documentation of this object's methods. This class is used by the high-level API to return Bio::DB::Bam::AlignWrapper objects from the call to alignment() rather than Bio::DB::Bam::Alignment. =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Elincoln.stein@bmail.comE Copyright (c) 2009 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut use strict; use Bio::DB::Bam::AlignWrapper; our $AUTOLOAD; use Carp 'croak'; sub new { my $package = shift; my ($align,$sam) = @_; return bless {sam => $sam, pileup => $align},ref $package || $package; } sub AUTOLOAD { my($pack,$func_name) = $AUTOLOAD=~/(.+)::([^:]+)$/; return if $func_name eq 'DESTROY'; no strict 'refs'; $_[0] or die "autoload called for non-object symbol $func_name"; croak qq(Can't locate object method "$func_name" via package "$pack") unless $_[0]->{pileup}->can($func_name); *{"${pack}::${func_name}"} = sub { shift->{pileup}->$func_name(@_) }; shift->$func_name(@_); } sub can { my $self = shift; return 1 if $self->SUPER::can(@_); return $self->{pileup}->can(@_); } sub alignment { my $self = shift; return Bio::DB::Bam::AlignWrapper->new($self->{pileup}->b,$self->{sam}); } 1; Bio-SamTools-1.39/lib/Bio/DB/Bam/AlignWrapper.pm000444001750001750 2624612207676767 21304 0ustar00lsteinlstein000000000000package Bio::DB::Bam::AlignWrapper; # $Id$ =head1 NAME Bio::DB::Bam::AlignWrapper -- Add high-level methods to Bio::DB::Bam::Alignment =head1 SYNOPSIS See L. =head1 DESCRIPTION This is a wrapper around Bio::DB::Bam::Alignment that adds the following high-level methods. These are described in detail in L. add_segment() add a new subfeature to split alignments get_SeqFeatures() fetch subfeatures from split alignments split_splices() process cigar strings to produce split alignments expand_flags() return true if flags should be expanded into tags seq_id() return human-readable reference sequence name seq() return Bio::PrimarySeq object for reference sequence subseq() return a subsequence across the indicated range mate_seq_id() return human-readable mate reference sequence name dna() return the DNA of the reference sequence tam_line() return the text representation of the alignment attributes() synonym for get_tag_values() get_all_tags() return all tag names get_tag_values() return the values of the given tag has_tag() return true if the given tag is defined =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Elincoln.stein@bmail.comE Copyright (c) 2009 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut use strict; use Bio::DB::Sam::Constants; our $AUTOLOAD; use Carp 'croak'; sub new { my $package = shift; my ($align,$sam) = @_; my $self = bless {sam => $sam, align => $align},ref $package || $package; $self->add_segment($self->split_splices) if $sam->split_splices && $align->cigar_str =~ /N/; return $self; } sub AUTOLOAD { my($pack,$func_name) = $AUTOLOAD=~/(.+)::([^:]+)$/; return if $func_name eq 'DESTROY'; no strict 'refs'; $_[0] or die "autoload called for non-object symbol $func_name"; croak qq(Can't locate object method "$func_name" via package "$pack") unless $_[0]->{align}->can($func_name); *{"${pack}::${func_name}"} = sub { shift->{align}->$func_name(@_) }; shift->$func_name(@_); } sub score {shift->{align}->qual} sub can { my $self = shift; return 1 if $self->SUPER::can(@_); return ref $self && $self->{align}->can(@_); } sub add_segment { my $self = shift; my @subfeat = @_; $self->{segments} ||= []; push @{$self->{segments}},@subfeat; } sub get_SeqFeatures { my $self = shift; return unless $self->{segments}; return @{$self->{segments}}; } sub split_splices { my $self = shift; my $cigar = $self->cigar_array; my @results; my $start = 0; my $end = 0; my $skip = 0; my $partial_cigar = ''; # in case sequence is missing? my $qseq = $self->qseq; $qseq ||= 'N' x $self->length; for my $op (@$cigar,['N',0]) { my ($operation,$count) = @$op; if ($operation eq 'N') { my $s = $self->start + $start + $skip; my $e = $self->start + $end - 1 + $skip; my $f = Bio::DB::Bam::SplitAlignmentPart->new(-name => $self->display_name, -start => $s, -end => $e, -seq_id => $self->seq_id, -strand => $self->strand, -seq => [$self,$start+$skip,$end-$start], # deferred rendering -type => $self->type); $f->hit(-name => $self->display_name, -seq_id => $self->display_name, -start => $start+1, -end => $end, -strand => $self->strand, -seq => substr($qseq,$start,$end-$start), ); $f->cigar_str($partial_cigar); $partial_cigar = ''; push @results,$f; $start += $end-$start; } else { $partial_cigar .= "$operation$count"; } $end += $count if $operation =~ /^[MDSHP]/i; $skip += $count if $operation eq 'N'; if ($operation eq 'H' and $start == 0) { $qseq = 'N' x $count . $qseq; } } return @results; } sub expand_flags { shift->{sam}->expand_flags(@_); } sub query { my $self = shift; return Bio::DB::Bam::Query->new($self); } sub target { my $self = shift; return Bio::DB::Bam::Target->new($self); } sub hit { shift->target(@_); } sub seq_id { my $self = shift; my $tid = $self->tid; return if $tid < 0 || $self->unmapped; $self->{sam}->target_name($tid); } sub mate_seq_id { my $self = shift; my $tid = $self->mtid; return if $tid < 0 || $self->munmapped; $self->{sam}->target_name($tid); } sub abs_ref { shift->seq_id } sub abs_start { shift->start } sub abs_end { shift->end } sub low { shift->start } sub high { shift->end } sub type { shift->primary_tag } sub method { shift->primary_tag } sub source { return shift->source_tag; } sub name { shift->qname } sub class { shift->primary_tag } sub seq { my $self = shift; my $dna = $self->dna; return Bio::PrimarySeq->new(-seq => $dna, -id => $self->seq_id); } sub subseq { my $self = shift; my ($start,$end) = @_; $start = 1 if $start < 1; $end = $self->high if $end > $self->high; my $dna = $self->dna; return Bio::PrimarySeq->new(-seq=>substr($dna, $start-1, $end-$start+1) ); } sub padded_alignment { my $self = shift; my $cigar = $self->cigar_array; my $sdna = $self->dna; my $tdna = $self->query->dna; my ($pad_source,$pad_target,$pad_match); for my $event (@$cigar) { my ($op,$count) = @$event; if ($op eq 'I' || $op eq 'S') { $pad_source .= '-' x $count; $pad_target .= substr($tdna,0,$count,''); $pad_match .= ' ' x $count; } elsif ($op eq 'D' || $op eq 'N') { $pad_source .= substr($sdna,0,$count,''); $pad_target .= '-' x $count; $pad_match .= ' ' x $count; } elsif ($op eq 'P') { $pad_source .= '*' x $count; $pad_target .= '*' x $count; $pad_match .= ' ' x $count; } elsif ($op eq 'H') { # nothing needs to be done in this case } else { # everything else is assumed to be a match -- revisit $pad_source .= substr($sdna,0,$count,''); $pad_target .= substr($tdna,0,$count,''); $pad_match .= '|' x $count; } } return ($pad_source,$pad_match,$pad_target); } sub dna { my $self = shift; my $sam = $self->{sam}; if (my $md = $self->get_tag_values('MD')) { # try to use MD string my $qseq = $self->qseq; #preprocess qseq using cigar array my $cigar = $self->cigar_array; my $seq = ''; for my $op (@$cigar) { my ($operation,$count) = @$op; if ($operation eq 'M') { $seq .= substr($qseq,0,$count,''); # include these residues } elsif ($operation eq 'S' or $operation eq 'I') { substr($qseq,0,$count,''); # skip soft clipped and inserted residues } } my $start = 0; my $result; while ($md =~ /(\d+)|\^([gatcn]+)|([gatcn]+)/ig) { if (defined $1) { $result .= substr($seq,$start,$1); $start += $1; } elsif ($2) { $result .= $2; } elsif ($3) { $result .= $3; $start += length $3; } } return $result; } else { return $self->{sam}->seq($self->seq_id,$self->start,$self->end); } } sub tseq { shift->dna(@_); } sub attributes { my $self = shift; my $tag = shift; if (defined $tag) { return $self->get_tag_values($tag); } else { return map {$_=>$self->get_tag_values($_)} $self->get_all_tags; } } sub get_all_tags { my $self = shift; return $self->{align}->get_all_tags(@_) if $self->expand_flags; return ($self->aux_keys,'FLAGS'); } sub get_tag_values { my $self = shift; my $tag = shift; defined $tag or return; return $self->{align}->get_tag_values($tag) if $self->expand_flags; if ($tag eq 'FLAGS') { $self->flag_str; } else { $self->aux_get($tag); } } sub has_tag { my $self = shift; my $tag = shift; defined $tag or return; $self->{align}->get_tag_values($tag) if $self->expand_flags; if ($tag eq 'FLAGS') { return 1; } else { my %keys = map {$_=>1} $self->aux_keys; return exists $keys{uc $tag}; } } sub gff_string { shift->gff3_string(@_) } sub gff3_string { my $self = shift; my $recurse = shift; my $parent_id = shift; my $group = $self->format_attributes($parent_id); my $name = $self->name; my $id = $self->primary_id; my $class = $self->class; my $strand = ('-','.','+')[$self->strand+1]; my $p = join("\t", $self->seq_id||'.', $self->source||'.', $self->method||'.', $self->start||'.', $self->stop||'.', defined($self->score) ? $self->score : '.', $strand||'.', defined($self->phase) ? $self->phase : '.', $group||''); my @rsf = $self->get_SeqFeatures; return join("\n", $p, map {$_->gff3_string($id)} @rsf); } sub phase { return } sub escape { my $self = shift; my $toencode = shift; $toencode =~ s/([^a-zA-Z0-9_.:?^*\(\)\[\]@!+-])/uc sprintf("%%%02x",ord($1))/eg; $toencode; } sub format_attributes { my $self = shift; my $parent_id = shift; my @tags = $self->get_all_tags; my @result; for my $t (@tags) { my @values = $self->each_tag_value($t); push @result,join '=',$self->escape($t),join(',', map {$self->escape($_)} @values) if @values; } my $id = $self->escape($self->primary_id); my $name = $self->display_name; unshift @result,"ID=".$id if defined $id; unshift @result,"Parent=".$parent_id if defined $parent_id; unshift @result,"Name=".$self->escape($name) if defined $name; return join ';',@result; } sub tam_line { my $self = shift; return join ("\t", $self->qname, $self->flag, $self->tid >= 0 ? $self->{sam}->target_name($self->tid) : '*', $self->pos+1, $self->qual, $self->cigar_str || '*', $self->mtid >= 0 ? ($self->mtid == $self->tid ? '=' : $self->{sam}->target_name($self->mtid)) : '*', $self->mpos+1, $self->isize, $self->qseq, join('',map{chr($_+33)} $self->qscore), $self->aux || () ); } package Bio::DB::Bam::SplitAlignmentPart; use base 'Bio::SeqFeature::Lite'; sub hit { my $self = shift; my $d = $self->{hit}; $self->{hit} = Bio::SeqFeature::Lite->new(@_) if @_; return $d; } sub seq { my $self = shift; my $seq = $self->{seq}; return $self->SUPER::seq() unless ref $seq; return substr($seq->[0]->dna,$seq->[1],$seq->[2]); } sub Bio::SeqFeature::Lite::subseq { my $self = shift; my ($start,$end) = @_; $start = 1 if $start < 1; $end = $self->high if $end > $self->high; return Bio::PrimarySeq->new(-seq=>substr($self->dna, $start-1, $end-$start+1) ); } sub cigar_str { my $self = shift; my $d = $self->{cigar_str}; $self->{cigar_str} = shift if @_; $d; } 1; Bio-SamTools-1.39/lib/Bio/DB/Bam/Target.pm000444001750001750 202612207676767 20105 0ustar00lsteinlstein000000000000package Bio::DB::Bam::Target; use strict; use base 'Bio::DB::Bam::Query'; =head1 NAME Bio::DB::Bam::Target -- Object representing the query portion of a BAM/SAM alignment in NATIVE alignment =head1 SYNOPSIS This is identical to Bio::DB::Bam::Query, except that the dna, qscores and start and end positions are all given in the orientation in which the read was sequenced, not in the oreintation in which it was aligned. =cut sub dna { my $self = shift; my $qseq = $self->SUPER::dna; return $$self->strand > 0 ? $qseq : reversec($qseq); } sub qscore { my $self = shift; my @qscore = $$self->qscore; @qscore = reverse @qscore if $$self->strand < 0; return wantarray ? @qscore : \@qscore; } sub start { my $self = shift; return $self->strand > 0 ? $self->low : $self->high; } sub end { my $self = shift; return $self->strand > 0 ? $self->high : $self->low; } # sub strand { 1 } sub reversec { my $dna = shift; $dna =~ tr/gatcGATC/ctagCTAG/; return scalar reverse $dna; } 1; Bio-SamTools-1.39/lib/Bio/DB/Bam/FetchIterator.pm000444001750001750 51712207676767 21405 0ustar00lsteinlstein000000000000package Bio::DB::Bam::FetchIterator; use strict; sub new { my $self = shift; my $list = shift; my $total= shift; $total ||= @$list; return bless {list=>$list, total=>$total},ref $self || $self; } sub next_seq { my $self = shift; return shift @{$self->{list}}; } sub total { shift->{total}; } 1; Bio-SamTools-1.39/lib/Bio/DB/Bam/ReadIterator.pm000444001750001750 62212207676767 21224 0ustar00lsteinlstein000000000000package Bio::DB::Bam::ReadIterator; use strict; sub new { my $self = shift; my ($sam,$bam,$filter) = @_; return bless {sam => $sam, bam => $bam, filter=> $filter},ref $self || $self; } sub next_seq { my $self = shift; while (my $b = $self->{bam}->read1) { return Bio::DB::Bam::AlignWrapper->new($b,$self->{sam}) if $self->{filter}->($b); } return; } 1; Bio-SamTools-1.39/lib/Bio/DB/Sam000755001750001750 012207676767 16205 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/lib/Bio/DB/Sam/SamToGBrowse.pm000444001750001750 2737212207676767 21247 0ustar00lsteinlstein000000000000package Bio::DB::Sam::SamToGBrowse; use Carp 'croak'; use Bio::DB::Sam; use File::Spec; use File::Basename 'basename'; use File::Temp 'tempfile','tmpnam'; use constant FORCE_TEMPFILES=>0; sub new { my $class = shift; my ($dir,$fasta,$debug) = @_; $dir or croak "Usage: $class->new(\$dir_to_index,[\$fasta_path])"; $fasta ||= $class->find_fasta($dir) or croak "Cannot find a suitable fasta file in $dir"; return bless { dir => $dir, fasta => $fasta, debug => $debug||0 },ref $class || $class; } sub run { my $self = shift; $self->sam_to_bam; $self->index_bam; $self->bam_to_wig; $self->make_conf; } sub dir {shift->{dir} } sub fasta {shift->{fasta} } sub debug {shift->{debug} } sub msg { my $self = shift; return unless $self->debug; print STDERR @_,"\n"; } sub err { my $self = shift; $self->{error} = "@_"; print STDERR @_,"\n"; } sub last_error { shift->{error} } sub files { my $self = shift; my @extensions = @_; # e.g. '.sam','.sam.gz'; my $dir = $self->dir; return map {glob($self->dir_path("*$_"))} @extensions; } sub mtime { my $self = shift; my $file = shift; my $mtime = (stat($file))[9]; return $mtime; } sub up_to_date { my $self = shift; my ($source,$target) = @_; return unless -e $target; return unless $self->mtime($target) >= $self->mtime($source); return 1; } sub find_fasta { my $self = shift; my $dir = shift; my @files = (glob(File::Spec->catfile($dir,"*.fa")),glob(File::Spec->catfile($dir,"*.fasta"))); return unless @files == 1; return $files[0]; } sub sam_to_bam { my $self = shift; $self->msg('Searching for SAM files'); my @sam = $self->files($self->sam_extensions); $self->msg("\t",'Found ',@sam+0,' sam files'); $self->convert_one_sam($_) foreach @sam; } sub sam_extensions { return qw(.sam .sam.gz) } sub index_bam { my $self = shift; $self->msg('Searching for BAM files'); my @bam = $self->files('.bam'); $self->msg("\t",'Found ',@bam+0,' bam files'); $self->index_one_bam($_) foreach @bam; } sub convert_one_sam { my $self = shift; my $sam = shift; my $base = basename($sam,$self->sam_extensions); my $bam = $self->dir_path("$base.bam"); my $sorted = $self->dir_path("${base}_sorted.bam"); if ($self->up_to_date($sam,$bam) or $self->up_to_date($sam,$sorted)) { $self->msg("\t","$sam: bam file is up to date"); return; } $self->msg("\t","$bam: creating"); my $fai = $self->make_fai; my $tam = Bio::DB::Tam->open($sam) or die "Could not open SAM file for reading: $!"; my $header = $tam->header_read2($fai); my $out = Bio::DB::Bam->open($bam,'w') or die "Could not open BAM file for writing: $!"; $out->header_write($header); my $alignment = Bio::DB::Bam::Alignment->new(); my $lines = 0; while ($tam->read1($header,$alignment) > 0) { $out->write1($alignment); $self->msg("\tConverted $lines lines...") if ++$lines%100000 == 0; } undef $tam; undef $out; $self->msg("\tConverted $lines lines"); $self->sort_bam($bam); } sub make_chrom_sizes { my $self = shift; my @files = $self->files('.bam'); my $sizes = $self->dir_path('chrom_sizes.txt'); open my $fh,'>',$sizes or die "$sizes: $!"; for my $f (@files) { my $b = Bio::DB::Sam->new(-bam=>$f) or die "Couldn't open $f"; for my $s (sort $b->seq_ids) { print $fh join("\t",$s,$b->length($s)),"\n"; } } close $fh; return $sizes; } sub make_fai { my $self = shift; # This is to create the .fai file. Do this in a block so that handle # goes out of scope when not needed. my $fasta = $self->fasta; -r $fasta or croak "FASTA file '$fasta' is not readable"; my $fai = $fasta.".fai"; unless ($self->up_to_date($fasta,$fai)) { my $fai = Bio::DB::Sam::Fai->load($fasta) or die "Could not load reference FASTA file for indexing this SAM file: $!"; } return $fai; } sub sort_bam { my $self = shift; my $bam = shift; $self->msg("Sorting $bam"); my $basename = basename($bam,'.bam'); my $sorted = $self->dir_path($basename.'_sorted'); Bio::DB::Bam->sort_core(0,$bam,$sorted); unlink $bam; # we don't want the unsorted version! return $sorted.'.bam'; } # This guy is a little tricky because unsorted BAM files # will terminate the process. We try to get around this by # forking and reading STDERR to see what happened (the Samtools # library is not great at returning status codes. sub index_one_bam { my $self = shift; my $bam = shift; my $idx = $bam . ".bai"; if ($self->up_to_date($bam,$idx)) { $self->msg("\t$bam: index is up to date"); return; } $self->msg("\tIndexing $bam"); my $err = $self->_fork_and_index_bam($bam); if ($err =~ /alignment is not sorted/) { $self->msg("$bam needs sorting"); $bam = $self->sort_bam($bam); $err = $self->_fork_and_index_bam($bam); } if ($err) { $self->err("\t","Could not index $bam: $err"); } else { $self->msg("\t","$bam indexed successfully"); } } sub _fork_and_index_bam { my $self = shift; my $bam = shift; my $pid = open my $pipe,"-|"; die "Couldn't fork: $!" unless defined $pid; if ($pid) { # I am the parent my $output = join '',<$pipe>; return $output; } # Otherwise, I am the child open STDERR,">&STDOUT"; # get stderr to go to the pipe Bio::DB::Bam->index_build($bam); exit 0; } sub dir_path { my $self = shift; my $filename = shift; return File::Spec->catfile($self->dir,$filename); } sub bam_to_wig { my $self = shift; my $chrom_sizes = shift; $self->msg('Searching for .bai files'); my @files = map {$self->dir_path(basename($_,'.bai'))} $self->files('.bai'); $self->msg("\t",'Found ', @files+0,' files'); $chrom_sizes ||= $self->make_chrom_sizes; $self->wiggle_one_bam($_,$chrom_sizes) foreach @files; } sub wiggle_one_bam { my $self = shift; my ($bam,$chrom_sizes) = @_; $chrom_sizes ||= $self->fasta.".fai"; die "$bam does not exist or is not readable" unless -r $bam; die "$chrom_sizes does not exist or is not readable" unless -r $chrom_sizes; my $base = basename($bam,'.bam'); my $bigwig = $self->dir_path($base.'.bw'); if ($self->up_to_date($bam,$bigwig)) { $self->msg("\t","$bam: bigwig is up to date"); return; } if (!$self->bedgraph_path && -r '/dev/stdin' && -c _) { # only works with linux, I think $self->_wiggle_one_bam_pipe($bam,$bigwig,$chrom_sizes); } else { $self->_wiggle_one_bam_tempfile($bam,$bigwig,$chrom_sizes); } } sub _wiggle_one_bam_pipe { my $self = shift; my ($bam,$bigwig,$chrom_sizes) = @_; my $pid = open my $pipe,"|-"; defined $pid or die "Couldn't fork: $!"; if ($pid) { # I'm the parent; my job is to write the coverage data to stdout $self->write_coverage($bam,$pipe); close $pipe; return; } else { # I'm the child; my job is to create the BigWig file from /dev/stdin $self->msg("Writing bigwig file"); $self->make_bigwig_file('/dev/stdin',$chrom_sizes,$bigwig); exit 0; } } # we are using the low-level interface here in order to eke # out all possible performance. sub write_coverage { my $self = shift; my ($bamfile,$fh) = @_; $self->msg("Calculating coverage for $bamfile"); if (my $bam2bedgraph = $self->bam2bedgraph) { $self->msg("\t",'bam2bedgraph found in path; will use it to calculate coverage graph.'); open my $gcb,"$bam2bedgraph '$bamfile' |" or die "Couldn't open $bam2bedgraph pipe: $!"; while (<$gcb>) { print $fh $_; } close $gcb; return; } else { # if we get here we are doing it ourselves my $bam = Bio::DB::Sam->new(-bam=>$bamfile) or die "Couldn't open $bamfile: $!"; $bam->coverage2BedGraph($fh); } } sub _wiggle_one_bam_tempfile { my $self = shift; my ($bam,$bigwig,$chrom_sizes) = @_; my $tmpfh = File::Temp->new(TEMPLATE => 'wigfileXXXXX', UNLINK => 1, DIR => $self->dir, SUFFIX => '.wig'); my $time = time(); $self->write_coverage($bam,$tmpfh); print STDERR time()-$time," seconds\n"; close $tmpfh; $self->msg("Writing bigwig file"); $self->make_bigwig_file($tmpfh,$chrom_sizes,$bigwig); } sub make_conf { my $self = shift; my $conf = $self->dir_path('gbrowse.conf'); my $existing_config = -e $conf ? $self->parse_conf($conf) : {}; my %tracks = map { basename($_,'.bw')=>1 } $self->files('.bw'); my @new = grep { !$existing_config->{$_} } keys %tracks; my $newfile = "$conf.new"; open my $f,">",$newfile or die "$newfile: $!"; for my $track (sort keys %tracks) { if ($existing_config->{$track}) { print $f $existing_config->{$track}; } else { print $f $self->make_gbrowse_conf($track); } } close $f; rename $newfile,$conf; } sub parse_conf { my $self = shift; my $conf = shift; open my $f,$conf or die "$conf: $!"; my ($current,%data); while (<$f>) { if (/^\[([^:]+)/) { $current = $1; $data{$current} = $_; } elsif ($current) { $data{$current} .= $_; } } return \%data; } sub bedgraph_path { my $self = shift; return $self->{_bedgraph_path} ||= $self->search_for_binary('bedGraphToBigWig'); } sub bam2bedgraph { my $self = shift; return $self->{_genomeCoverageBed} ||= $self->search_for_binary('bam2bedgraph'); } sub search_for_binary { my $self = shift; my $target = shift; my @path = split ':',$ENV{PATH}; for my $d (@path) { my $tgt = File::Spec->catfile($d,$target); return $tgt if -e $tgt && -x _; } return; } sub make_bigwig_file { my $self = shift; my ($infile,$chrom_sizes,$outfile) = @_; my $bedpath = $self->bedgraph_path; if ($bedpath) { $self->msg("\t",'Found bedGraphToBigWig in path. Will use it to create BigWig index.'); # BUG: potential race condition here, but fastCGI prevents us from # redirecting STDERR my $error_file = tmpnam(); system("$bedpath '$infile' '$chrom_sizes' '$outfile' 2>$error_file"); if (-s $error_file) { open (F,'<',$error_file); my $err = ; $self->err("bedGraphToBigWig exited with an error: \"$err\". $outfile will be removed."); unlink $outfile; } unlink $error_file; } else { $self->err('WARNING: No bedGraphToBigWig found in path. Will use memory-intensive library function to create BigWig index.'); Bio::DB::BigFile->createBigWig($infile,$chrom_sizes,$outfile); } } sub make_gbrowse_conf { my $self = shift; my $track = shift; $self->msg("Creating gbrowse stanza for $track"); my $fasta = File::Spec->rel2abs($self->fasta); my $bam = File::Spec->rel2abs($self->dir_path("$track.bam")); my $bw = File::Spec->rel2abs($self->dir_path("$track.bw")); (my $key = $track) =~ s/_sorted//; my $result = < '$bw', -fasta => Bio::DB::Sam::Fai->open('$fasta'), ); } [$track] database = $track feature = read_pair glyph = segments draw_target = 1 show_mismatch= 1 mismatch_only = 1 mismatch_color = orange indel_color = yellow bgcolor = black fgcolor = black height = 4 label = 1 label_position = left label density = 50 bump = fast connector = sub { my \$glyph = pop; return \$glyph->level == 0 ? 'dashed' : 'solid'; } maxdepth = 2 box_subparts = 2 key = Reads from $key [$track:2000] database = ${track}_bw feature = summary glyph = wiggle_whiskers height = 20 END } 1; Bio-SamTools-1.39/lib/Bio/DB/Sam/Constants.pm000444001750001750 440512207676767 20657 0ustar00lsteinlstein000000000000package Bio::DB::Sam::Constants; # $Id$ =head1 NAME Bio::DB::Sam::Constants -- Constants for use with SAM/BAM =head1 SYNOPSIS use Bio::DB::Sam::Constants; my $pad_flag = BAM_CPAD; =head1 DESCRIPTION This module exports several constants for use with the SAM/BAM module. See the SAM documentation for their interpretation. =over 4 =item Cigar operations BAM_CIGAR_SHIFT BAM_CIGAR_MASK BAM_CMATCH BAM_CINS BAM_CDEL BAM_CREF_SKIP BAM_CSOFT_CLIP BAM_CHARD_CLIP BAM_CPAD =item FLAGS A hashref that maps flag values to human-readable names. For example: FLAGS->{0x0008} == 'M_UNMAPPED' =item RFLAGS The reverse of FLAGS: FLAGS->{M_UNMAPPED} == 0x0008 =back =head1 SEE ALSO L, L, L =head1 AUTHOR Lincoln Stein Elincoln.stein@oicr.on.caE. Elincoln.stein@bmail.comE Copyright (c) 2009 Ontario Institute for Cancer Research. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. In addition, please see DISCLAIMER.txt for disclaimers of warranty. =cut use strict; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(CIGAR_SYMBOLS BAM_CIGAR_SHIFT BAM_CIGAR_MASK BAM_CMATCH BAM_CINS BAM_CDEL BAM_CREF_SKIP BAM_CSOFT_CLIP BAM_CHARD_CLIP BAM_CPAD FLAGS RFLAGS); our @EXPORT_OK = @EXPORT; use constant CIGAR_SYMBOLS => [qw(M I D N S H P)]; use constant BAM_CIGAR_SHIFT => 4; use constant BAM_CIGAR_MASK => (1 << BAM_CIGAR_SHIFT) - 1; use constant BAM_CMATCH => 0; use constant BAM_CINS => 1; use constant BAM_CDEL => 2; use constant BAM_CREF_SKIP => 3; use constant BAM_CSOFT_CLIP => 4; use constant BAM_CHARD_CLIP => 5; use constant BAM_CPAD => 6; use constant FLAGS => { 0x0001 => 'PAIRED', 0x0002 => 'MAP_PAIR', 0x0004 => 'UNMAPPED', 0x0008 => 'M_UNMAPPED', 0x0010 => 'REVERSED', 0x0020 => 'M_REVERSED', 0x0040 => 'FIRST_MATE', 0x0080 => 'SECOND_MATE', 0x0100 => 'NOT_PRIMARY', 0x0200 => 'QC_FAILED', 0x0400 => 'DUPLICATE' }; use constant RFLAGS => {reverse %{FLAGS()}}; 1; Bio-SamTools-1.39/lib/Bio/DB/Sam/Segment.pm000444001750001750 435412207676767 20310 0ustar00lsteinlstein000000000000package Bio::DB::Sam::Segment; use strict; sub new { my $class = shift; my ($db,$seqid,$start,$end) = @_; return bless { db => $db, seqid => $seqid, start => $start, end => $end},ref $class || $class; } sub db { shift->{db} }; sub features { my $self = shift; my $db = $self->db; my @args; if (@_ && $_[0] !~ /^-/) { # type list @args = (-types=>\@_); } else { @args = @_; } return $db->features(-seq_id => $self->seq_id, -start => $self->start, -end => $self->end, @args); } #required by GBrowse1 sub get_feature_stream { my $self = shift; my @args = @_; my @features = $self->features(@args); return Bio::DB::Sam::Segment::Iterator->new(\@features); } # required by api sub seq_id { shift->{seqid} }; # required by GBrowse1 *ref = *abs_ref = *sourceseq = \&seq_id; # required by api sub start { shift->{start} }; # required by api sub end { shift->{end} }; # required by api sub strand { 0 }; # required by api sub length { my $self = shift; return $self->end - $self->start + 1; } # required by api sub seq { my $self = shift; return Bio::PrimarySeq->new(-seq => $self->dna, -id => $self->seq_id); } sub primary_id { shift->seq_id; } # required by api sub primary_tag { my $self = shift; return 'region'; } sub dna { my $self = shift; my $db = $self->db; $db->seq($self->seq_id,$self->start,$self->end); } # required by api sub source_tag { return 'sam/bam' } # required by api sub name { shift->seq_id } # required by api sub display_name { shift->seq_id } # required by api sub factory { shift->db } # required by api sub get_SeqFeatures { return; } # required by api sub method { shift->primary_tag } # required by GBrowse1 sub type { shift->primary_tag } # required by api sub get_tag_values { return; } # required by api sub score { return; } # required by api sub class { 'sequence' } package Bio::DB::Sam::Segment::Iterator; sub new { my $package = shift; my $features = shift; return bless $features,$package; } sub next_seq { my $self = shift; return unless @$self; my $next_feature = shift @$self; return $next_feature; } 1; Bio-SamTools-1.39/bin000755001750001750 012207676767 14471 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/bin/chrom_sizes.pl000555001750001750 51212207676767 17471 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use Bio::DB::Sam; my $bamfile = shift or die "Usage: $0 \nOutput a chrom_sizes file.\n"; my $bam = Bio::DB::Sam->new(-bam=>$bamfile) or die "Couldn't open $bamfile"; my @seqids = $bam->seq_ids; for my $s (sort @seqids) { my $len = $bam->length($s); print join("\t",$s,$len),"\n"; } Bio-SamTools-1.39/bin/bamToGBrowse.pl000555001750001750 404612207676767 17525 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use Bio::DB::Sam; use Bio::DB::Sam::SamToGBrowse; my $has_bigwig = eval {require Bio::DB::BigFile;1}; @ARGV >= 1 or die < [] Given the path to a directory and the fasta file for the reference sequence, do the following: 1. Find all SAM files in the indicated directory and convert them into BAM. These must end in one of the extensions ".sam" or ".sam.gz". A series of .bam files will be created. This step will be skipped if SAM files are absent or the corresponding BAM files are already present. 2. Sort the newly created BAM files, creating a series of files named _sorted.bam. 3. Index BAM files that need indexing. This step will look for files named _sorted.bam 4. Create a set of BigWig files representing the coverage graph. These will be named .bw. 5. Create a skeletal GBrowse config file named "gbrowse.conf" that serves as a starting point for viewing these files. Previous versions of this file will be appended to. You can prepopulate the directory with sorted and indexed BAM files, in which case the script will not attempt to resort or reindex them. Unless the Fasta file is explicitly provided, this script will look in the designated directory for ONE .fa file to use. Note that you will need temporary space in the directory equivalent to the size of the largest SAM file being processed. This script takes a long time to run and uses significant amounts of RAM when generating the coverage graphs. To improve both performance and memory consumption, you can install the following C binaries: bedGraphToBigWig -- download from http://hgdownload.cse.ucsc.edu/admin/exe or build from source downloadable from http;//hgdownload.cse.ucsc.edu/admin/jksrc.zip Place these executables into your path, e.g. /usr/local/bin or ~/bin. USAGE ; my($dir,$fasta) = @ARGV; my $converter = Bio::DB::Sam::SamToGBrowse->new($dir,$fasta,'verbose'); $converter->run(); exit 0; Bio-SamTools-1.39/bin/genomeCoverageBed.pl000555001750001750 43212207676767 20506 0ustar00lsteinlstein000000000000#!/usr/bin/perl use strict; use FindBin '$Bin'; use lib "$Bin/../blib/lib","$Bin/../blib/arch"; use Bio::DB::Sam; my $bamfile = shift or die "Usage $0 \n"; my $bam = Bio::DB::Sam->new(-bam=>$bamfile) or die "Couldn't open $bamfile: $!"; $bam->coverage2BedGraph(); Bio-SamTools-1.39/t000755001750001750 012207676767 14164 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/t/01sam.t000444001750001750 2664512207676767 15464 0ustar00lsteinlstein000000000000#-*-Perl-*- # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.t' use strict; use ExtUtils::MakeMaker; use File::Temp qw(tempfile); use FindBin '$Bin'; use constant TEST_COUNT => 104 + 8; # malcolm_cook@stowers.org added spliced alignment tests use lib "$Bin/../lib","$Bin/../blib/lib","$Bin/../blib/arch"; BEGIN { # to handle systems with no installed Test module # we include the t dir (where a copy of Test.pm is located) # as a fallback eval { require Test; }; if( $@ ) { use lib 't'; } use Test; plan test => TEST_COUNT; } use Bio::DB::Sam; { ## Following tests added by malcolm_cook@stowers.org while ## diagnosing, patching "incomplete cigar/split alignments ## processing of multi-gaps" ## (https://sourceforge.net/tracker/?func=detail&aid=3083769&group_id=27707&atid=391291) my $bamfile = "$Bin/data/dm3_3R_4766911_4767130.sam.sorted.bam"; my $sam = Bio::DB::Sam->new( -bam => $bamfile, -split_splices => 1, -autoindex => 1, ); ok($sam); ok($sam->split_splices); my @alignments = $sam->get_features_by_location("3R"); ok (75,@alignments,"count of alignments in $bamfile"); my @e3 = grep {my $c = $_->cigar_str; $c =~ /^\d+M124N3M91N\d+M$/} @alignments; ok (9, @e3, "count of spliced alignments which 'take' the 3bp exon according to CIGAR string"); my @e3_parts=map {[$_->get_SeqFeatures]} @e3; ok($#e3,$#e3_parts,"all have split splices"); ok((grep {grep {$_->start == 4767036 && $_->end == 4767038 && $_->hit->seq eq "GCT" } @$_} @e3_parts),@e3_parts, "split alignments harboring the 3bp exon"); ok((grep {grep {$_->end == 4766911 && do {my $h = $_->hit->seq; $h =~ m/GCT$/; }} @$_} @e3_parts),@e3_parts, "split alignments having a part (exon) that ends at 4766911 (the donor of the upstream exon)" ); ok((grep {grep {$_->start == 4767130 && do {my $h = $_->hit->seq; $h =~ m/^TCTTC/; }} @$_} @e3_parts), @e3_parts, # This is the test that fails without the patch that motivated # these tests. Prior to patch, 4767006 was the incorrectly computed value # for the start of the downstream exon, due to incorrect cigar processing when # an alignment spanned multiple introns. "split alignments having a part (exon) that starts at 4767130 (the acceptor of the downstream exon)" ); } # low level tests (defined in lib/Bio/DB/Sam.xs) { my $bamfile = "$Bin/data/ex1.bam"; my $bam = Bio::DB::Bam->open($bamfile); ok($bam); my $header = $bam->header; my $targets = $header->n_targets; ok($targets,2); my $target_names = $header->target_name; ok($target_names); ok(scalar @$target_names,2); ok($target_names->[0],'seq1'); my $target_lens = $header->target_len; ok($target_lens); ok(scalar @$target_lens,2); ok($target_lens->[0],1575); my $text = $header->text; ok(length $text > 0); my $c = "\@CO\tThis is a comment\n"; $header->text($c); ok($header->text,$c); my $fai = Bio::DB::Sam::Fai->open("$Bin/data/ex1.fa"); my $seq = $fai->fetch('seq2:51-1000'); ok(length $seq,950); my $count; while (my $b = $bam->read1) { $count++; } ok($count,3307); my @result = $header->parse_region('seq2:51-1000'); ok($result[0],1); ok($result[1],50); @result = $header->parse_region('seq_invalid:51-1000'); ok(scalar @result,0); my $index = Bio::DB::Bam->index($bamfile,1); ok($index); my @a; my $print_region = sub { my($alignment,$data) = @_; push @a,$alignment; return; }; $index->fetch($bam,$header->parse_region('seq2'),$print_region,"foobar"); ok(scalar @a > 1); my %matches; my $fetch_back = sub { my ($tid,$pos,$p) = @_; my $p1 = $pos+1; my $r = $fai->fetch($header->target_name->[$tid].":$p1-$p1"); for my $pileup (@$p) { my $b = $pileup->b; my $qpos = $pileup->qpos; my $base = $pileup->indel == 0 ? substr($b->qseq,$qpos,1) :$pileup->indel > 0 ? '*' : '-'; $matches{matched}++ if $r eq $base; $matches{total}++; } }; $index->pileup($bam,$header->parse_region('seq2:1-100'),$fetch_back); ok($matches{matched}/$matches{total} > 0.99); # try to get coverage my $coverage = $index->coverage($bam, $header->parse_region('seq2'), 100, 9000 ); ok(scalar @$coverage,100); my @c = sort {$a<=>$b} @$coverage; ok($c[0] >= 0); ok($c[-1] < 1000); # try reading from a TAM (text sam) file my $sam = Bio::DB::Tam->open("$Bin/data/ex1.sam.gz"); ok($sam); my $align = Bio::DB::Bam::Alignment->new(); ok($align); # quench annoying stderr message from library here open my $saverr,">&STDERR"; open STDERR,">/dev/null"; my $head = Bio::DB::Tam->header_read2("$Bin/data/ex1.fa.fai"); open STDERR,">&",$saverr; ok($head); my $result = $sam->read1($head,$align); ok($result>0); ok($align->qseq,'CACTAGTGGCTCATTGTAAATGTGTGGTTTAACTCG'); ok($align->start,1); ok($sam->read1($head,$align)>0); ok($align->start,3); ok($header->target_name->[$align->tid],'seq1'); # test ability to write a BAM file my (undef,$filename) = tempfile('BAM_TEST_XXXXXXX',UNLINK=>1); $sam = Bio::DB::Tam->open("$Bin/data/ex1.sam.gz"); $bam = Bio::DB::Bam->open($filename,'w'); ok($bam); ok($bam->header_write($head),0); $count = 0; while ($sam->read1($head,$align) > 0) { $count++; $bam->write1($align); } ok($count,3307); undef $bam; $bam = Bio::DB::Bam->open($filename); ok($bam); $header = $bam->header; $targets = $header->n_targets; ok($targets,2); $target_names = $header->target_name; ok($target_names); ok(scalar @$target_names,2); ok($target_names->[0],'seq1'); $target_lens = $header->target_len; ok($target_lens); ok(scalar @$target_lens,2); ok($target_lens->[0],1575); # try removing and regenerating index unlink "$Bin/data/ex1.bam.bai"; ok(Bio::DB::Bam->index($bamfile,1)); ok(-e "$Bin/data/ex1.bam.bai"); Bio::DB::Bam->sort_core(1,"$Bin/data/ex1.bam","$Bin/data/ex1.sorted"); ok(-e "$Bin/data/ex1.sorted.bam"); ok(Bio::DB::Bam->index("$Bin/data/ex1.sorted.bam",1)); ok(-e "$Bin/data/ex1.sorted.bam.bai"); unlink ("$Bin/data/ex1.sorted.bam","$Bin/data/ex1.sorted.bam.bai"); } # high level tests (defined in lib/Bio/DB/Sam.pm) { my $sam = Bio::DB::Sam->new(-fasta=>"$Bin/data/ex1.fa", -bam =>"$Bin/data/ex1.bam", -expand_flags => 1, -autoindex => 1, ); ok($sam); ok($sam->n_targets,2); ok($sam->length('seq1'),1575); ok(join $sam->seq_ids,'seq1 seq2'); my $seg = $sam->segment('seq1'); ok($seg); ok($seg->length,1575); my $seq = $seg->seq; ok($seq->isa('Bio::PrimarySeq')); ok(length $seq->seq,1575); my $fh = $sam->tam_fh; ok($fh); my $samline = <$fh>; ok($samline =~ /^B7_591:4:96:693:509/); $fh->close; my ($readname) = $samline =~ /^(\S+)/; my ($f) = $sam->get_features_by_name($readname); ok($f); chomp($samline); ok($f->tam_line,$samline); my $dummy = eval {Bio::DB::Sam->new(-fasta=>"invalid_path.txt", -bam =>"invalid_path.txt")}; ok($dummy,undef); ok($@ =~ /does not exist/); my @alignments = $sam->get_features_by_location( -seq_id => 'seq2', -start => 500, -end => 800 ); ok(scalar @alignments,442); ok($alignments[0]->seq_id,'seq2'); ok(scalar @{$alignments[0]->qscore},length $alignments[0]->dna); my @keys = $alignments[0]->get_all_tags; ok(scalar @keys,17); ok($alignments[0]->get_tag_values('MF'),18); my %att = $alignments[0]->attributes; ok(scalar(keys %att),17); ok($alignments[0]->cigar_str,'35M'); $sam->expand_flags(0); @keys = $alignments[0]->get_all_tags; ok(scalar @keys,7); my $query = $alignments[0]->query; ok($query); ok($query->start,1); ok($query->end,35); ok($query->length,35); ok($query->dna,$alignments[0]->dna); ok($alignments[0]->strand,-1); ok($query->strand,-1); my $target = $alignments[0]->target; ok($target); ok($target->start,35); ok($target->end,1); ok($target->length,35); ok($target->dna,reversec($alignments[0]->dna)); ok($alignments[0]->get_tag_values('FLAGS'),$alignments[0]->flag_str); my @pads = $alignments[0]->padded_alignment; ok(@pads,3); ok($pads[0],$pads[2]); ok($pads[1]=~tr/|/|/,length($pads[0])); my @f = $sam->features(-name=>'EAS114_45:2:1:1140:1206'); ok(scalar @f,2); @f = $sam->features(-filter=> sub { my $a = shift; return 1 if $a->display_name eq 'EAS114_45:2:1:1140:1206'; }); ok(scalar @f,2); @f = $sam->features(-seq_id => 'seq2', -filter => sub { my $a = shift; return 1 if $a->display_name =~ /^EAS114/; }); ok(scalar @f,306); @f = $sam->features(-filter => sub { my $a = shift; return 1 if $a->display_name =~ /^EAS114/; }); ok(scalar @f,534); @f = $sam->features(-name=>'EAS114_45:2:1:1140:1206', -tags=>{FIRST_MATE=>1}); ok(scalar @f,1); # try iteration my $i = $sam->get_seq_stream( -seq_id => 'seq2', -start => 500, -end => 800 ); ok($i); my $count = 0; while ($i->next_seq) { $count++ } ok($count,442); # try tam fh retrieval $fh = $sam->get_seq_fh( -seq_id => 'seq2', -start => 500, -end => 800, ); $count = 0; $count++ while <$fh>; ok($count,442); $fh->close; $i = $sam->get_seq_stream(); # all features! ok($i); $count = 0; while ($i->next_seq) { $count++ } ok($count,3307); $i = $sam->get_seq_stream(-max_features=>200,-seq_id=>'seq1'); ok ($i); $count = 0; while ($i->next_seq) { $count++ } ok($count,200); ok($sam->last_feature_count,1482); # try the read_pair aggregation my @pairs = $sam->features(-type=>'read_pair', -seq_id => 'seq2'); ok(scalar @pairs,939); # try coverage my @coverage = $sam->features(-type => 'coverage', -seq_id => 'seq2'); ok(scalar @coverage,1); my ($c) = $coverage[0]->get_tag_values('coverage'); ok($c); ok($c->[0],3); ok($c->[1],4); ok($coverage[0]->type,"coverage:1584"); # test high level API version of pileup my %matches; my $fetch_back = sub { my ($seqid,$pos,$p) = @_; my $r = $sam->segment($seqid,$pos,$pos)->dna; for my $pileup (@$p) { my $a = $pileup->alignment; my $qpos = $pileup->qpos; my $dna = $a->query->dna; my $base = $pileup->indel == 0 ? substr($dna,$qpos,1) :$pileup->indel > 0 ? '*' : '-'; $matches{matched}++ if $r eq $base; $matches{total}++; } }; $sam->pileup('seq2:1-100',$fetch_back); ok($matches{matched}/$matches{total} > 0.99); exit 0; # this is not a unit test, but a piece of demo to show cigar string # processing for my $a (@alignments) { warn $a->display_name,' :: ',$a->flag_str,' :: ', $a->start,'..',$a->end,' ',' mpos=',$a->mate_start,' ins=',$a->isize, ' qlen=',$a->cigar2qlen, ' [',$a->strand,'/',$a->mstrand,']', ' ', $a->cigar_str, ' ', $a->mate_start,'..',$a->mate_end, "\n"; } } sub reversec { my $dna = shift; $dna =~ tr/gatcGATC/ctagCTAG/; return scalar reverse $dna; } Bio-SamTools-1.39/t/data000755001750001750 012207676767 15075 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/t/data/dm3_3R_4766911_4767130.sam.sorted.bam000444001750001750 617712207676767 22667 0ustar00lsteinlstein000000000000BCsred~ fHyެ R@NJnjN|nfI~rF~^JQf~^|zj^~n*3P xF& 3A[5$hX4aظ@2!dD>AJFv 34(`.F6";<V0KU2g1 e vH8@BC MNjBao^V{u佀C s#K@ 6&JL/G}[K2:Ylq2f-/Q:_SʭUZS,}DVQ&EFraQx}E^Ńj{3 B(dP_W7v)njZZ}%<*+v@[yoxqsz鋤HxA,AF _o'' p|DBLm}a$\/E{o'KL+?"pt$M[TRBҭXdNl)텹ύDnO'[:i2?!>q06r-ۻcc2LfWY*we[=#uae{S 7}B$ź-sa}K3:iZ.f6jG۽_ UHb1<$*7hZ4WyIv W<T(%\"%>_Py-vɤ$yH==u}oͦM-ڣ*YQ j uXHQhQ,,V r= SDTSA0ѭE+΍[CG2Ó @`ש5dk\cnY!Ҭ]]w'|oO˰v`ggG߶V*1\*!"ݽHfM2ه?.m[0!! !eԛ"aSsON5)u]Q]rQdIh,N;f:,UCIRg`ħ+l=Kp$"*bf3ߟ|_'fO0#\{}7ʋ8'iP_{ .`;+8F)N&^ ku[&aS<1XgΪ7ۣwK<PaΚfﶂ/jLqGU;<"{͛쾼]vK]` r=<2)GvV@GӵZ#ԮϬq&˺ 'C8K2y.zõS=9mɰo@{dc6ދ==.yO8[zj`l/jP<_=p)J)3o #OJ`I*36:ځ3fg>xAk[OKGq )!*bDm{^E؎ax}]̗C !9P&{R B82b 8Ҍ˕mۧ4ȘfWPV1>N:>Cs0ƙ2 XO7a1(+6+Q _I },-걶^45^* O+V+K$O-,ÛuVt߀{aRߣTBU7&|889m8.XcMӄBq}C=#%+v, -C7v>qeE26uZzFwQ <_m_F'A3wGb,;$+6*F2u:.peI!kwW#EVmj\]ޏ/$c:/ub-D5Wq0:_4}{!找)Ec;̾1N>6bҥTu-BCBio-SamTools-1.39/t/data/dm3_3R_4766911_4767130.sam000444001750001750 3116212207676767 20642 0ustar00lsteinlstein000000000000SNPSTER1_0624:1:76:3859:1170#0/1 0 3R 4766872 255 40M * 0 0 GTTGAGATCAACCCCTATGCCGAGGATGCCATGTCCGGCT GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGFGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:19:3314:1450#0/1 16 3R 4766872 255 40M * 0 0 GTTGAGATCAACCCCTATGCCGAGGATGCCATGTCCGGCA EFDGGDGFGGDGGFGFGFFBGFGFGGFFGGGBGDGGGGGG XA:i:1 MD:Z:39T0 NM:i:1 SNPSTER1_0624:1:24:11178:5138#0/1 16 3R 4766872 255 40M * 0 0 GTTGAGATCAACCCCTATGCCGAGGATGCCATGTCCGGCA GDGGGEGGGGFGEGGFDDE:GFFGGFGGGGFGFFGFGGFG XA:i:1 MD:Z:39T0 NM:i:1 SNPSTER1_0624:1:59:18561:8672#0/1 16 3R 4766872 255 40M * 0 0 GTTGAGATCAGCCCCTATGCCGAGGATGCCATGTCCGGCT ADDDDAA:CC,C5:C>;>C=C8?@@DDD:D5BBDBDDDDD XA:i:1 MD:Z:10A29 NM:i:1 SNPSTER1_0624:1:13:15204:6475#0/1 0 3R 4766873 255 40M * 0 0 TTGAGATCAACCCCTATGCCGAGGATGCCATGTCCGGCTT EEEEEEGFGFGGGGGGGGFEFEFGEGGEDFGGEGEEEDDF XA:i:0 MD:Z:39G0 NM:i:1 SNPSTER1_0624:1:108:12715:2571#0/1 0 3R 4766873 255 40M * 0 0 TTGAGATCAACCCCTATGCCGAGGATGCCATGTCCGGCTT GGGFGEGGDAFFFFDEB?EAAA?:AEDEEEEDEBEA:EEE XA:i:0 MD:Z:39G0 NM:i:1 SNPSTER1_0624:1:75:18585:17302#0/1 16 3R 4766873 255 40M * 0 0 TTGAGATCAACCCCTATGCCGAGGATGCCATGGCCGGCTG GFGGGGGGEFGGGDGGGGGGGGEGGFGGGFFF-?FGFFGG XA:i:1 MD:Z:32T7 NM:i:1 SNPSTER1_0624:1:76:11608:14484#0/1 16 3R 4766873 255 40M * 0 0 TTGAGATCAACCCCTATGCCGAGGATGCCATGTCCGGCTG GFGGGFGGGDGGEGGGGDGFGGGGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:78:18342:13460#0/1 16 3R 4766877 255 35M218N5M * 0 0 GATCAACCCCTATGCCGAGGATGCCATGTCCGGCTTCTTC GGGGGEGGGGFGGGFGFGFGGGGGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:50:18992:5646#0/1 0 3R 4766879 255 33M218N7M * 0 0 TCAACCCCTATGCCGAGGATGCCATGTCCGGCTTCTTCGC =FDFFFDFFDFDFF=EE=D?EBEEDD?DDA:CC?CE?EAD XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:54:12705:7226#0/1 0 3R 4766879 255 33M218N7M * 0 0 TCAACCCCTATGCCGAGGATGCCATGTCCGGCTTCTTCGC GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:76:18795:9315#0/1 0 3R 4766879 255 33M218N7M * 0 0 TCAACCCCTATGCCGAGGATGCCATGTCCGGCTTCTTCGC DCDDAADE?EAEEDE=DDADEEE==C?@@6?7@####### XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:33:17716:8124#0/1 16 3R 4766879 255 33M218N7M * 0 0 TCAACCCCTATGCCGAGGATGCCATGTCCGGCTTCTTCGC 5EEDEBEEEE==EDDE=EEEAEEEEFFFFFEE=EDDEE=D XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:62:14097:13695#0/1 16 3R 4766880 255 32M218N8M * 0 0 CAACCCCTATGCCGAGGATGCCATGTCCGGCTTCTTCGCA EEB=E=BE?BFFFFFFFAFFEEEEDD=EEDBDDBDADDDD XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:118:10624:10461#0/1 16 3R 4766882 255 30M124N3M91N7M * 0 0 ACCCCTATGCCGAGGATGCCATGTCCGGCTGCTTCTTCGC GGGEEGGGGGGGGGGGGGGGFGGDGGGGGGGGGEGGGGEG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:29:8470:6899#0/1 0 3R 4766883 255 29M218N11M * 0 0 CCGCTATGCCGAGGATGCCATGTCCGGCTTCTTCGCATTG CC,CCEEEEEGGGGGGGGGGGGGGGGGFGGGGGFGGFGGG XA:i:1 MD:Z:2C37 NM:i:1 SNPSTER1_0624:1:55:16577:6603#0/1 0 3R 4766883 255 29M218N11M * 0 0 CCCCTATGCCGAGGATGCCATGTCCGGCTTCTTCGCATTG GGGGGGGGGGGFGGDGGGGGGGGGGAFFFFGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:12:11906:12096#0/1 16 3R 4766884 255 28M218N12M * 0 0 CCCTATGCCGAGGATGCCATGTCCGGCTTCTTCGCATTGG :C=CA:EEEEABEDECAC::ADDEDDFDBFFFDAFADFDD XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:50:4068:2579#0/1 0 3R 4766885 255 27M218N13M * 0 0 CCTATGCCGAGGATGCCATGTCCGGCTTCTTCGCATTGGA GGGDGGGGGEGGGGFGGGGGGGGGGGGGGGGGGGGGGGGF XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:55:19295:11289#0/1 0 3R 4766885 255 27M218N13M * 0 0 CCTATGCCGAGGATGCCATGTCCGGCTTCTTCGCATTGGA GGGGGGGGGGGGGGGGGGGGGGGGGEGGGGGEGGGGGGGE XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:107:17204:14904#0/1 0 3R 4766886 255 26M218N14M * 0 0 CTATGCCGAGGATGCCATGTCCGGCTTCTTCGCATTGGAT GGGGGGGGFGGGGGGGFGEEDFDFFGGFGGGFEEGGGFB= XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:5:5444:15694#0/1 0 3R 4766890 255 22M218N18M * 0 0 GCCGAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTA D5DDAA-ACADDDD=DDDC=ADDDADDDDDDDDDDDABCB XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:44:6102:19956#0/1 0 3R 4766890 255 22M218N18M * 0 0 GCCGAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTA GGFGGGGGGGGCGGGFGGEFGEFGGGGGEGGGEGEGGE?B XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:26:10801:9184#0/1 16 3R 4766890 255 22M218N18M * 0 0 GCCGAGGATGCCATGTCCGGCTTCTTCGCATTGGATGGCA GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGEEEFFDD;DD XA:i:2 MD:Z:37C0T1 NM:i:2 SNPSTER1_0624:1:31:14362:11262#0/1 0 3R 4766890 255 22M124N3M91N15M * 0 0 GGCGAGGATGCCATGTCCGGCTGCTTCTTCGCATTGGATG GGGGGGGGGGGGGGGGGGGGGGGFGGGGGGGGGGGFGGGG XA:i:1 MD:Z:1C38 NM:i:1 SNPSTER1_0624:1:117:4789:17961#0/1 0 3R 4766891 255 21M218N19M * 0 0 CCGAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTAA GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGFGGFFGC XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:28:5089:1640#0/1 16 3R 4766891 255 21M218N19M * 0 0 CCGAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTAA GFGGGGGGGFGGGGGGGGGGGGFGGGDGGFGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:32:3686:2052#0/1 16 3R 4766891 255 21M218N19M * 0 0 CCGAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTAA CBEDGGFGGEGGGGFDGGGEGGFGEGGGFGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:66:9908:5425#0/1 16 3R 4766892 255 20M124N3M91N17M * 0 0 CGAGGATGCCATGTCCGGCTGCTTCTTCGCATTGGATGCA GGGGGGGGFGBGGGGGGGGGGGGGGGGGGGGGGGGGGGGG XA:i:1 MD:Z:39T0 NM:i:1 SNPSTER1_0624:1:2:14689:9538#0/1 16 3R 4766893 255 19M218N21M * 0 0 GAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGC FDGGGGFDGFEEEEDGDGFGBGGGAGBFEFFFFADFDEDF XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:65:12780:3711#0/1 16 3R 4766893 255 19M218N21M * 0 0 GAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGC GGGGGGGGGGGGFGGGGGGGGGGGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:97:4809:2026#0/1 16 3R 4766893 255 19M218N21M * 0 0 GAGGATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGC GGGGDGGGGGGGEGGGGGGGGEGGFGGGGGGGGGFGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:39:17671:15065#0/1 16 3R 4766895 255 17M218N23M * 0 0 GGATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGCTG GGGGGGGGGGFGGGGGGGGGGGGGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:4:4797:14319#0/1 16 3R 4766896 255 16M218N24M * 0 0 GATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGCTGC GGEGGFGGFFGGGGGGFGGGGGFGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:9:6910:12235#0/1 16 3R 4766896 255 16M218N24M * 0 0 GATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGCTGC D=DDBDDDDABDDCDADD?DDDDD?BDBDB;@<>;?@?@> XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:48:9427:5673#0/1 0 3R 4766897 255 15M124N3M91N22M * 0 0 ATGCCATGTCCGGCTGCTTCTTCGCATTGGATGCTAAGCT GGGGGGGGGGGGFGDGGGGGGGGEGEGGGFEFDEEFGEGB XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:6:19065:6983#0/1 16 3R 4766897 255 15M218N25M * 0 0 ATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGCTGCG FFGBGGGGFGGGFGGGGGGGGGGDGGGGGGGFGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:8:18794:13099#0/1 16 3R 4766897 255 15M218N25M * 0 0 ATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGCTGCG GGGGGGFGGGGGGEGFGGDGEGGGGGGGGGGFGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:16:19857:14078#0/1 16 3R 4766897 255 15M218N25M * 0 0 ATGCCATGTCCGGCTTCTTCGCATTGGATGCTAAGCTGCN <=?>>;C@9;=ADBAD5?A5C?5A?EF=DBF XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:17:14419:10033#0/1 16 3R 4766902 255 10M218N30M * 0 0 ATGTCGAGCTTCTTCGCATTGGATGCTAAGCTGCGATTTG ?>>?@-?ADDDDADDA=EEEBEFEFFFFFEDA XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:2:13119:7887#0/1 0 3R 4766906 255 6M124N3M91N31M * 0 0 CCGGCTGCTTCTTCGCATTGGATGCCAAGCTGCGATTTGA GGGDEGGFGGGGGEGFGEGB70?93*7?<:7:6>3FFFB: XA:i:1 MD:Z:25T14 NM:i:1 SNPSTER1_0624:1:34:9549:7584#0/1 0 3R 4766906 255 6M218N34M * 0 0 CCGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGA GGGGFGGGGGFGAGGA7CAACCCCCFFFGFDEEEEFDFFE XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:52:11586:13990#0/1 0 3R 4766906 255 6M218N34M * 0 0 CCGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGA GGGGGGGGGGGGGGGGGGGGECCEE7CBDCD@BDDGEEGF XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:55:6314:16719#0/1 0 3R 4766906 255 6M218N34M * 0 0 CCGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGA GGGGGGGGGGEGFFGGGGBGEEEDD@DDDDEAEEEE=EEE XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:56:17930:20920#0/1 0 3R 4766906 255 6M218N34M * 0 0 CCGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGA EFGGGGGBGGEEEEEEAEEAB5DBDDDDDDE==EEEBBB: XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:71:9666:15267#0/1 0 3R 4766906 255 6M218N34M * 0 0 CCGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGA GGGGGGGGGGGGGGGGGGGGGFGGGFDGGGGGGGGGFGGF XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:101:16533:16033#0/1 0 3R 4766906 255 6M218N34M * 0 0 CCGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGA FFBFFFGGGGGGGGEGGDGGFFGFGBAEGAFACFFEEDFF XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:104:10705:2422#0/1 0 3R 4766906 255 6M124N3M91N31M * 0 0 CCGGCTGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGA GGGGGGGGFGGGGGGGGFGFGGGGFGGGFGGGGGFGGGF= XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:102:9041:19142#0/1 0 3R 4766907 255 5M218N35M * 0 0 CGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGAC GGGFGGGFGFBDFFFFF=FFBFFF=FDEDFDEFFB?FEED XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:13:3079:20441#0/1 16 3R 4766907 255 5M124N3M91N32M * 0 0 CGGCTGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGAT BBBDDBBC5D@@>.>?>>C75AACA>=>C==:AC5CAAAC XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:14:17663:12890#0/1 0 3R 4766907 255 5M218N35M * 0 0 CGGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGAC GFGGGGGGGFFGGGGFGGGFEEBGEFGGDGFGGGGFFFFC XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:51:18119:20479#0/1 16 3R 4766907 255 5M124N3M91N32M * 0 0 CGGCTGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGAT GGGFGGGGEGDGGGGGGEGGGGGGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:68:4735:5439#0/1 0 3R 4766908 255 4M218N36M * 0 0 GGCTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGACA FDFFFFGGGEGGGGDFGGFGGDGGGGEGDGGGGEFDDEFE XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:32:14039:13606#0/1 0 3R 4766975 255 40M * 0 0 ATCCTAACGAACTAACTCATTTGTGATTGTCATTGTACTG GGGGGGGGGGGGGGGEGGEGGEECEEEGEEEDF-ECCCCC XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:29:4268:14563#0/1 16 3R 4767128 255 40M * 0 0 CTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGACAAC DFEGEGGGEGEGGGGGGGFGGGGGGGGGGGGGGGGGGFGG XA:i:0 MD:Z:0A0G38 NM:i:2 SNPSTER1_0624:1:43:18168:12378#0/1 16 3R 4767128 255 40M * 0 0 CTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGACAAC GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG XA:i:0 MD:Z:0A0G38 NM:i:2 SNPSTER1_0624:1:72:14305:19119#0/1 16 3R 4767128 255 40M * 0 0 CTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGACAAC EECE=AGGFGGGEFGFGAEGEFFBGFGGGFGFGFGFGGGG XA:i:0 MD:Z:0A0G38 NM:i:2 SNPSTER1_0624:1:86:16050:7108#0/1 16 3R 4767128 255 40M * 0 0 CTTCTTCGCATTGGATGCTAAGCTGCGATTTGATGACAAC GAFBGGGGGGEGFFGGGGGGGGGGDGGGGFFGGEGFGGGG XA:i:0 MD:Z:0A0G38 NM:i:2 SNPSTER1_0624:1:68:13841:15470#0/1 16 3R 4767129 255 40M * 0 0 TTCTTCGCATTGGATGCTAAGCTGCGATTTGATGACAACG GFGGFGGGGGGGGGGGGGGGGGFGGGGGGGGGGGGGGGFG XA:i:0 MD:Z:0G39 NM:i:1 SNPSTER1_0624:1:25:9762:4966#0/1 0 3R 4767130 255 40M * 0 0 TCTTCGCATTGGATGCTAAGCTGCGATTTGATGACAACGC CC5CCEEEEEGGGGGGGGGGGGGGGGGGGFE:EEEGGGGG XA:i:0 MD:Z:40 NM:i:0 SNPSTER1_0624:1:113:19575:18309#0/1 16 3R 4767130 255 40M * 0 0 TCTTCGCATTGGATGCTAAGCTGCGATTTGATGACAACGC ?ECDAF?G?GGGDGGDGFEFFFFFBEEFFDEE=E=DBBDD XA:i:0 MD:Z:40 NM:i:0 Bio-SamTools-1.39/t/data/ex1.fa000444001750001750 623112207676767 16241 0ustar00lsteinlstein000000000000>seq1 CACTAGTGGCTCATTGTAAATGTGTGGTTTAACTCGTCCATGGCCCAGCATTAGGGAGCT GTGGACCCTGCAGCCTGGCTGTGGGGGCCGCAGTGGCTGAGGGGTGCAGAGCCGAGTCAC GGGGTTGCCAGCACAGGGGCTTAACCTCTGGTGACTGCCAGAGCTGCTGGCAAGCTAGAG TCCCATTTGGAGCCCCTCTAAGCCGTTCTATTTGTAATGAAAACTATATTTATGCTATTC AGTTCTAAATATAGAAATTGAAACAGCTGTGTTTAGTGCCTTTGTTCAACCCCCTTGCAA CAACCTTGAGAACCCCAGGGAATTTGTCAATGTCAGGGAAGGAGCATTTTGTCAGTTACC AAATGTGTTTATTACCAGAGGGATGGAGGGAAGAGGGACGCTGAAGAACTTTGATGCCCT CTTCTTCCAAAGATGAAACGCGTAACTGCGCTCTCATTCACTCCAGCTCCCTGTCACCCA ATGGACCTGTGATATCTGGATTCTGGGAAATTCTTCATCCTGGACCCTGAGAGATTCTGC AGCCCAGCTCCAGATTGCTTGTGGTCTGACAGGCTGCAACTGTGAGCCATCACAATGAAC AACAGGAAGAAAAGGTCTTTCAAAAGGTGATGTGTGTTCTCATCAACCTCATACACACAC ATGGTTTAGGGGTATAATACCTCTACATGGCTGATTATGAAAACAATGTTCCCCAGATAC CATCCCTGTCTTACTTCCAGCTCCCCAGAGGGAAAGCTTTCAACGCTTCTAGCCATTTCT TTTGGCATTTGCCTTCAGACCCTACACGAATGCGTCTCTACCACAGGGGGCTGCGCGGTT TCCCATCATGAAGCACTGAACTTCCACGTCTCATCTAGGGGAACAGGGAGGTGCACTAAT GCGCTCCACGCCCAAGCCCTTCTCACAGTTTCTGCCCCCAGCATGGTTGTACTGGGCAAT ACATGAGATTATTAGGAAATGCTTTACTGTCATAACTATGAAGAGACTATTGCCAGATGA ACCACACATTAATACTATGTTTCTTATCTGCACATTACTACCCTGCAATTAATATAATTG TGTCCATGTACACACGCTGTCCTATGTACTTATCATGACTCTATCCCAAATTCCCAATTA CGTCCTATCTTCTTCTTAGGGAAGAACAGCTTAGGTATCAATTTGGTGTTCTGTGTAAAG TCTCAGGGAGCCGTCCGTGTCCTCCCATCTGGCCTCGTCCACACTGGTTCTCTTGAAAGC TTGGGCTGTAATGATGCCCCTTGGCCATCACCCAGTCCCTGCCCCATCTCTTGTAATCTC TCTCCTTTTTGCTGCATCCCTGTCTTCCTCTGTCTTGATTTACTTGTTGTTGGTTTTCTG TTTCTTTGTTTGATTTGGTGGAAGACATAATCCCACGCTTCCTATGGAAAGGTTGTTGGG AGATTTTTAATGATTCCTCAATGTTAAAATGTCTATTTTTGTCTTGACACCCAACTAATA TTTGTCTGAGCAAAACAGTCTAGATGAGAGAGAACTTCCCTGGAGGTCTGATGGCGTTTC TCCCTCGTCTTCTTA >seq2 TTCAAATGAACTTCTGTAATTGAAAAATTCATTTAAGAAATTACAAAATATAGTTGAAAG CTCTAACAATAGACTAAACCAAGCAGAAGAAAGAGGTTCAGAACTTGAAGACAAGTCTCT TATGAATTAACCCAGTCAGACAAAAATAAAGAAAAAAATTTTAAAAATGAACAGAGCTTT CAAGAAGTATGAGATTATGTAAAGTAACTGAACCTATGAGTCACAGGTATTCCTGAGGAA AAAGAAAAAGTGAGAAGTTTGGAAAAACTATTTGAGGAAGTAATTGGGGAAAACCTCTTT AGTCTTGCTAGAGATTTAGACATCTAAATGAAAGAGGCTCAAAGAATGCCAGGAAGATAC ATTGCAAGACAGACTTCATCAAGATATGTAGTCATCAGACTATCTAAAGTCAACATGAAG GAAAAAAATTCTAAAATCAGCAAGAGAAAAGCATACAGTCATCTATAAAGGAAATCCCAT CAGAATAACAATGGGCTTCTCAGCAGAAACCTTACAAGCCAGAAGAGATTGGATCTAATT TTTGGACTTCTTAAAGAAAAAAAAACCTGTCAAACACGAATGTTATGCCCTGCTAAACTA AGCATCATAAATGAAGGGGAAATAAAGTCAAGTCTTTCCTGACAAGCAAATGCTAAGATA ATTCATCATCACTAAACCAGTCCTATAAGAAATGCTCAAAAGAATTGTAAAAGTCAAAAT TAAAGTTCAATACTCACCATCATAAATACACACAAAAGTACAAAACTCACAGGTTTTATA AAACAATTGAGACTACAGAGCAACTAGGTAAAAAATTAACATTACAACAGGAACAAAACC TCATATATCAATATTAACTTTGAATAAAAAGGGATTAAATTCCCCCACTTAAGAGATATA GATTGGCAGAACAGATTTAAAAACATGAACTAACTATATGCTGTTTACAAGAAACTCATT AATAAAGACATGAGTTCAGGTAAAGGGGTGGAAAAAGATGTTCTACGCAAACAGAAACCA AATGAGAGAAGGAGTAGCTATACTTATATCAGATAAAGCACACTTTAAATCAACAACAGT AAAATAAAACAAAGGAGGTCATCATACAATGATAAAAAGATCAATTCAGCAAGAAGATAT AACCATCCTACTAAATACATATGCACCTAACACAAGACTACCCAGATTCATAAAACAAAT ACTACTAGACCTAAGAGGGATGAGAAATTACCTAATTGGTACAATGTACAATATTCTGAT GATGGTTACACTAAAAGCCCATACTTTACTGCTACTCAATATATCCATGTAACAAATCTG CGCTTGTACTTCTAAATCTATAAAAAAATTAAAATTTAACAAAAGTAAATAAAACACATA GCTAAAACTAAAAAAGCAAAAACAAAAACTATGCTAAGTATTGGTAAAGATGTGGGGAAA AAAGTAAACTCTCAAATATTGCTAGTGGGAGTATAAATTGTTTTCCACTTTGGAAAACAA TTTGGTAATTTCGTTTTTTTTTTTTTCTTTTCTCTTTTTTTTTTTTTTTTTTTTGCATGC CAGAAAAAAATATTTACAGTAACT Bio-SamTools-1.39/t/data/dm3_3R_4766911_4767130.sam.bam000444001750001750 617712207676767 21370 0ustar00lsteinlstein000000000000BCsred~ fHyެ R@NJnjN|nfI~rF~^JQf~^|zj^~n*3P xF& 3A[5$hX4aظ@2!dD>AJFv 34(`.F6";<V0KU2g1 e vH8@BC MNjBao^V{u佀C s#K@ 6&JL/G}[K2:Ylq2f-/Q:_SʭUZS,}DVQ&EFraQx}E^Ńj{3 B(dP_W7v)njZZ}%<*+v@[yoxqsz鋤HxA,AF _o'' p|DBLm}a$\/E{o'KL+?"pt$M[TRBҭXdNl)텹ύDnO'[:i2?!>q06r-ۻcc2LfWY*we[=#uae{S 7}B$ź-sa}K3:iZ.f6jG۽_ UHb1<$*7hZ4WyIv W<T(%\"%>_Py-vɤ$yH==u}oͦM-ڣ*YQ j uXHQhQ,,V r= SDTSA0ѭE+΍[CG2Ó @`ש5dk\cnY!Ҭ]]w'|oO˰v`ggG߶V*1\*!"ݽHfM2ه?.m[0!! !eԛ"aSsON5)u]Q]rQdIh,N;f:,UCIRg`ħ+l=Kp$"*bf3ߟ|_'fO0#\{}7ʋ8'iP_{ .`;+8F)N&^ ku[&aS<1XgΪ7ۣwK<PaΚfﶂ/jLqGU;<"{͛쾼]vK]` r=<2)GvV@GӵZ#ԮϬq&˺ 'C8K2y.zõS=9mɰo@{dc6ދ==.yO8[zj`l/jP<_=p)J)3o #OJ`I*36:ځ3fg>xAk[OKGq )!*bDm{^E؎ax}]̗C !9P&{R B82b 8Ҍ˕mۧ4ȘfWPV1>N:>Cs0ƙ2 XO7a1(+6+Q _I },-걶^45^* O+V+K$O-,ÛuVt߀{aRߣTBU7&|889m8.XcMӄBq}C=#%+v, -C7v>qeE26uZzFwQ <_m_F'A3wGb,;$+6*F2u:.peI!kwW#EVmj\]ޏ/$c:/ub-D5Wq0:_4}{!找)Ec;̾1N>6bҥTu-BCBio-SamTools-1.39/t/data/ex1.bam000444001750001750 36721212207676767 16463 0ustar00lsteinlstein000000000000BChH iYX]՗Kw}ÿm@k q $zppǍ >%SXb4+99&1Lz!D"$Y`9&Ywy޻f{t粸xjkPT/o}z{M~̗?w~5zjv.ފ|*OT/&ώfp>dz|ԝU?DMV:Cw9/H /O?X˾ec5GxSe7\<3>;'t *]\I |#<+8/⽜cYXc.rωx8`8M(]" IHB- {$O#9< xzt6M'YwLri/z}o֝a|vA~?(7P^P**=JnMxқOFSJ&չ+$)DY%TQ射f|Fv2ޅad H$&\ ea|? $J#y˾8ID'\GԛNE cl„9./ȳȮNNINrB|O?9@D  aJ"1p1wTiBSd~$,``ohY".Xgtz8L\SVs&ғD''QrԣATb2RU,і rk#%"F}4ΠxT.b49+s)'PYHE8jr,_啥)X>_cy&0A*L)g8ڋr^iJPDq8L9/P(,|Ow<;̗`,;+R|OBjPkuE5E'^EO*~C-|gSHgu^1%WC0ݧ|'~w`s Ki\lWrggSv>&Q(Rr- LFV+l+ҴGءB|>)-5!=&_UyvX&On1Q|Qߛ=9pΐ{*a˳S]T^1Ar cT]J<:MvrWhAעHquRhC`u{ e{ aA4Mw0HbVTr@&`Y[5ԟ0 I̓uʿ,,(Y :&Ԋ5L׼UۤXMX,-Eg `LA}vFQKE(DG*)X<X2X~~F* t[А)^MH.SN.ҧāPv>ct _:ENDh!y("hT? `vvpg:xC:\{*XW+1CE72A:s(nb)r$`KhGȫSdߔ| pqqf)\|(NJ_:~?8Iҝz]Q-HsYv2 E?O6aV틅暾hSr(B;>~b2X 觓|8q+x켐HV.8SnooK"|%bYH[RQ|n@ dR, ˵A) <u*ax>,/;ED:hjLR ~ k$QT .7$B 责z,g7-kJ^-RTG>!ImE^\\Cx\ٔEꁗC*PD P(0uo/rOBM ?X~J pD{|1($i/~zBS$[*B#:$/(G~&) $Td7*]"~q|=0~ROgѾM".K|7K7 ,sDgNgB>S&ŕ2[8̳īх*@^R4RI"`^e"ay]}3C `@ez@q߭'/aB{_Ms'kʾ{5ڷ)|v*`Tu4ІU@y?cYLsin^#%G7cfTGECA3^:#,V&M=B<uHP~ ioD]Gf<2TT"dfHɎ99h(gR' v&Uo`hFA7|ul/.O+(; ikFN7m=!!x>jBiYFw iuhR; vkA"\49k-s4K)OgҦ auLbpY#XG8`M-$Pgu8ܵ[4^#j:K7d#b# T1I,T›Mߪ3[2 dl81MyЄ3:Ӹ5#H ,ہR]#;Ljw:atʲyFR€KL㌞,?]QR'm6`ZDN/3bJA+KabA],.L`|DZeN8[ߥAH ]^XCfN"LK p.AcX]qfKjfJvquP,]vdsn^s&8|X~́2$8A2@Yw7dE'zutӊC|mXZeR>ؤa>JׁMd-3`1*/5`X .];!BLd ~K9/̏+"-nQ -#XA-2. >1ћu_@N] Kʩ)2L6YF,`*_|_ܑ΃ 4[4L[(,g< O%ѩMsV9[, ³v{}nֱ1aWyQyш>ywWNK),9Gݽ^#CG8nfMS ˁ#>^u[K>(kpҝ?7/TlAair(jP@eEY#×PښU-qʫZ0ZuܝZr0?(FX1]`f'X0·3نǷ\i+Ç8M(l=Ů{KN `)ZA'MdDk6U7 y 7X4 5|L 4l+DIMPLm[K1^r9LNd*ԧVjO \K,%IV8)ZacE)KnXu\5&* Rg"DA ),Ê=`c 1GG4eź0b!}ѡ2/jz*|;ކtJ%h>0z`lO];1a[̽sKVxgq>m [N%Q11R%bKDp4,CoB /s;F58s*QN3'hlh*ѼdeuEEdᎇG*yi+ߩxos[z؇zRZWPߡ`ɟdJEԠv{LκVhVk,}Ȱ`_ej1ޭ⩄uʟY,ٛNh^#kZ+iGu#jph<"5܈vF}Ƶ&Ӗיv+# Sj!m?ew _7(yB"JR?:Ud1}xQi"! qs:q fp NpxBYI=oy4Έ4?+,ALlk 3{"&_~q|DˑҖ;`lįU\g+L+(t ){zdv$)Č[_F>9-|2dZt0t%4XJF̛m0c{9OyF!`a_\?ߣz-}ts'423- -_zaIߪEl piܦ|mFitPjf]5b70.o;Yd7vkd/}DÊmC!=,RzMS5 HnM״ݖ$&vWexX5)Cx^uamQelvVq$?htlJKZ.@v,j-FRK@$ɰ{kP`2e[+Va8a,Ldߧ}싍!a]=͔&UߌR,CnFM{GyԴw{`BtvP iKF!f9rO~159fAL*"S(8=ap.}$`hQ&`~U}ˎpBK9T$OpHDc)_v9m{ؓ&eXڨ\I`4i6c-[,eoly3h!LUH]F~I$[s񀢗IJ} 70¹hHRG2ТmWr P0˚hacZ&nUq"f*ba t>Z`υmUJDlzJ8Z3 OY8c%,M 7&geJ fqЋ6e-Y|Wי,'@0JkVi3 I8<(RFLc|r],d!0[ ɓ˽W[N,kRӤTH%EƤ]*sU~CzQ(F=viu'c`LrKMrey0`8Ǔ|-6xʼ"gcM#I]+94W8;4xg{~<z,InRp`!共sPA cW[e zPsWO3Oj, >P(A8pXӰo%_o9&8ń]4 r,}.9"wN=2s;'&,k~:؏\Jc" hB#T7Ew"Wi!}|b%TbYWF_x)BooZ9zn]ҷi>^另 -ssy}-`Rps`(SM ʗd9r` 6QtG˶KdҬԏv9^V$"#V2Xo1G!%툈g~}WʓłoH-ۘPP$̂,s`1ި\:rXXVtv0ޞg>UQr @;ڧMԡ8g`DLmOb\qF+ l=@CnS p+&5<%\1*N4o9F4B K}-{,^U:@ym/93җ#?e𮜈gq{(,勲Dd-qcLxܧyK OzWi-$pXuYf^cy>GT7oSfez6l gFvX+=m L+,8j*U^.u%].[L'w`3k]+FX0&nS#҄\E)ҋvs xAKU0t[U*cMq:QC2JhV|xWȌ!M,T%Kvqvq du?-1&i#N"O1Yt/iL8jdY+^+'uy߹ewg?RpLd ?dr. Q'zw9rQxBUt:UTT mvzGr%Uҭs bds,r,i5(_QP-o\p<N$ʅZf ܆ ҫye6bMt$\(L8beй (f5r8o{qՔ8]IE 1ItFL7 )BIOAS;@TIv8=5,Ejӂ2Ҩ>C|Hs? 1/Wѡ6ĀM0%~D1ej +H~y՘ Zogth®$g 0,|H07)Bf-. 8+st0uEfHŲ(֛W&GJwQ#r #n4,mgBYw/k"F'.3\qˉ"A߅q:y`_.!S0KUA""4q!EղIxSt*އ s~AeL׭Q&0Ob"E6LB)?wpY&آ fM^7mB9$8Ƒ TYCxN;*V^Ybi0=krNc|E"k?@$XڒY)R9XUɟ (w㈐*XIHXuUޅj-y/=`۹#m#- Stt{Ce7^ xŧ|8R"Ysq@A?n,3L@dzinͺc-q4lJ=HeռVAyhC7iV-?мWe0=F|c18YCnjӽiTBvܘEaQ5ƻ=BDn9yh~Mò,v@6 OWˍUFo˛6cs-dMP}:NHM 9/ҵ)XdX1.0%-p>Lrld.-W;BLv :7q)dzZKa+2wk IolE-+q7LiUEg .EhME4=[5:;%LB źâԼZ9"5Ja20؛.kjBEI] cXtqt$kIys }?p0 zT4*ѩrE"1`}txK>ҨmO3zTzh2o$-lK("}Mu}U&MV̈́8}SGw:ى1dVrs{-1^vMN Xӻ4b.x%laAM!҇U&; xlc00(=Gpsk$ ;`xOw0۝'A齌|DxG*XwM$sY%le[1 Ga1S͍`&&"2F@uN13Sc(.8sJ{ waGЙtiF<~ ĵ "X./;ED:hߕM>nG˪lR_=|m[\BٌM~1\~pG@=,k35#C\x 7悗˖ kKcE'Us)5njG ;\囫r wP!W==rׅEPGY[qNSGR>4arpx2x9ڂrF,tXh4>O Sxs>>"$8VpAUW9coI*BQFvd6Uu}m<`ͼDbqUxS4-ǧߧ@1_["<biKm4RԧȰ" &1Z&!D#b/ēOt<);&WLyM qdQd5|>\ (5{xwجсfCpἀ2Ujl4['!]χ<ݣsmMgy Y;W:[T Y>x64K7e _ f-{t*UlJI|94Q=&4E1Òl  z\cxK>, WB?Zʳd+ju:/v R8|M:waE69ַ`44²rXa}"X>8"C{IfzQxCO`F$mlJ0Kg'xXixHK[ p~++u]֋`QҸG]!whW?e>?̆BHmQd_$,TaPnrՎ˛*h ;WͶS&'I'a9Nl4|&]g^Ꜹ3}$FD ~+r\O8oc ?l,02(&Φy\I}ǃýj=TUc IX 3ޛc)"J$y+̮P܃品C{[ǷZNڥ(XK:rB,K<(]BS rxT>s Lxdm;-F蠌e\S,0"gq&E 4zfye7#Ź+="8zM\OZ*Zr4rrC]PS^pmpJLSL,ْ6b}5zL:p͘&]1IwꓤY$j-̸$~R4OBcTAHGNxӎ`އ>r̔&@h{:07#\ȊBDft)K[E(ol$ɊFV.?`{h#NT!V=:DŽ47T,N# -vn iL '%}7]('؏,c򀡣9s Nn]vi2M3ݹƁz1d+_nP Rë]PpD0lPp~y 46,Cg m>S9ӹբ8Ȥ@v =ߵjEaaO UV.mcAժْ#SK솵F,'>-KiآҹJbMЏ}brwD(#xwS kjƜ8&YVFʧV9cE ;yH,&.,ir}smzS̙&UDqwZ~BcD5k4aQ٭6_+}Qpj`7(V+DЯ8<^\[ ](!E<5ZfWxe}zbpG9y&+3 ^ez&kG xDijJoO9"\Zj5Q's߼[fلz|`NչH%0f!G Lx$i2bp`)y%uvpNo8*?g7hy^sOZhPssԧWʪ?@lr–I#gS~!ona#e!{OXŧ `&Q^y&e |2:{هqFU܈3\9M6}F9%a'pUM̧x2eM3G(m¢Φ 5__(P69έ9&U=8G/1'gW+Y+|Ƶp].lsޫ11lq%TZ=q8;v$"f34k:e|lK0j4$y쎖3ut^8LcOs l2;c;WR#esݏcS:]q I鿷E_:2z1_9X?!VC~䐐(?'$WeR 9߱ҾjmiJ) z86Fe Y|N:,Qg01x-υ*ߥe صG'HmSqc&>^4wlk {̻;r,)BحQKS?ewnvGe^adm ԝln\.Qj8oe8e0&*8GRQyͱ}#".L2R[ǛG  Ia`'r`hͦ?8ߩ!I[ftytuŻEbZqLx0KB P -'{/JY]QCN&FmM}3_QaR*4,oE"eP^}Ӎr-:r\G) 떖j+;nj.?Q-7!x8!hC+7*rd0)`goU ͒,&Nsm.Vl_q`DB|7TѠCژKwzTX`:}$Y[t :QTm[%/Yhn@*ꥏBqE[&OoM3 7$t5I:: ̫ncG]^z}g}`ngW9Rǚ՘gԹJ2Pe@1E'i=oX@G#ӺRJ3d:6w7!#@-9ZS튥4e}n누#ӨIQόXqyfl%sٱ?\7j,;45v1(n΁ql 6synBk(q[A"=g!K+~+sH$ءC&*o/=*gZ0`>+ ?0Aegy;دgRO о 䛯ҍӧjo5f˨pi a!2:jV֋)PTe#`fDc(نQ}6wܹS?z=\\4QoArR ~jFȧk%/1)yoԉC\Un݄PN2V ӮIYqjw:󜔵7D[\}a qEܢ`:n| ^1w*yI F'Z+ms;K# Y休\#'=xOҟNɵxo1^2ZE,CVAHuq@`0s"(wvw'yAAٟF]1̂}qWm8W\ǻ"sZ%IٖvN7@"S0]%e!Fu%hX3)\R9s=η" 62t`Olc492/T˱Wbf)88pmBKRN{_倜AG=ZڟB'-sc^I ;7Bi?Ok,X| h M( XrXSe#KKhp,odQ >,|FE>Cz,=a5X$m¯Ln#E)I{]A\JSK R7VՎkI:FVHCC5nXF*n :/cu=]ШXI!ZAQ jMq,meߴ;_ d~w R F 97:ڊS߅,2 A`u}#r={4IvNsѢiacUFJ~U8<\P6n^Fhn- !BS{ҷ;UZtF2ТsӦ4YA q obf mE,$&aqSe[/i߄"= 0㽓zݧUL&{8a3j|oe K}f縨׹DJg掲PYHϑ[kc'$l0K8~6d雷 =y[K麏cS ղZx Llp>Fߐ@ΰ{zB D ʊIQ#59u@$Lߡp@ZdQvkx6*{OqJRE@r  S_NHS?{ ߺ~wu0gp2(IMrIsc'NÈ"DQh|uL2ܝ~p砵s= [gny^yMG(`gXzp>&yo0LPR FX#᥵",HR(2`Y, `y2:a&#d>Lg!I@:i~HI:'.(A}Y4S0zp2QEXhݖVPv)YH8CG8De# h8G5[9`ȁ#YTXGPu\Z=O_uB DrN'/A1 ,-E~(A_9g 8$˩.DK{]KaZnw? {_?" O{7q^$G&)eZP: E`028 9g\_)SxL)H}IjH2zL'̳h|TCEo9ػϸƁfG?RР@$! *.4ݖIV4"~C U}·=N(oRmhi@P|cKwWBiV+O7`pSCAZ E=M}9 ?)$}y3peLp,N]XCX+nm  6cx(]Di\Y&iG> (Op8SU* Y4 2w©boYjC_PF [L"˞A"XZ+KI,UQf Ot4/NH$s.r.o viz\?N&uKx nT]x( ŲXvfc!7oX Vy4.Ot1p3S0@2>$f Ő4>}dYqL1 [)`c*yxȚbo(ؓN/MQ xO"8]_9VcL4iYD94})w%7Fܔ/g!bJd1v2uDğ zjdJ~#Whiވ{޺Ȟe{f$,,Oug%Qסe`.^].Qd˺X$Q0{RXd>菨G^,%GEE2:'}- uQ9sj\bUuFWП1þ 5ʳүI( k`1?>fz /ӘaRtEta".D`fvY#!$_/ Ûc /2^Jb =tF/(7TYe2US&#2NЪ^+ %$kU!@)iAe‘R/HڛxCRR^ =^?Q~>ӑ X>ɥl|đ@N/93,$f5Co4xX?M}B3<Y%ip џqwLV|g+cE,G9!4R J-QXe0fIe*d#Y(-~$_Fa{2,!S8v6Jz,`o<$Mէr_n[CNN( ]Avpf  eQ;S&R@ٕ+U@ފQc&Y)GMRU??|aWBnbv4p(t6[FɈp\GFSQ9Mc2H݄[)˨ot!2Ѭ ˴<㮂I-0- {ѠdH%Q8_fYB *! `4 A)Qȷ8cy.Q<`lh̼(ݓ`,"o-d)=7ൌiHԃl]9&aWB.z|+NŕcK#{{ny}[i랬lИg,I PZ;6V:Y'c">|ElEҽ_"tTh0gG3&IlS¼R>@p*ޔ{ȣ)$f<&-RSDX`QV #5 Zo<פVq8He!:qBZ27|2Qhy{N_B}`Ap~G''h%k[MMT+H@O,S7f}Jԃš:C<^ٽK" k5 r q|⥋1U Cem{]rֵ ]ъY<6p%7,p /yѤi gcۮ(  N|24#I I]T ȋ4~eK:p84Y4oE#П]P H2}k(rJ)rxxrҤfZE.Iz Q׻CAbf?Héһ /4<3uuV_Īf-y6`(;N`9((I,-V9}!Clzwͥ7ٜ&ܹM<&*vaO+r,]p/ jG`&I3tw(XN ck؛B;^j@fC,w8r+@+UpѲK#a G$9ޢsYip<cWhOW6^gT]XH.ꥰ!.w:X2V4( I67-xzU;rYJ.ڤ5@]OP$F*YLxڴb5=PTa;97ȡ!P{!-1/[,@3Ed+kϋU=@R10 BK2II夞9&Q|"LL0x CK|%,0ݳTBEГ$Vewd.+Hf8n{ j5ä:"! z>=Æ)VFf,6%VԔaobU2ưJM{-`<騕{ȫ}C7We;}4yAd&O989¡-%&`gV%US'=L\%uT&ٔ-0٥K~[z ]]]+M7ŬtPɨS.d^.r{M{F,:O+]CpBND3=Z*'YR//z}_7F}cr+ft#}&*Z7d)p[(پ,$`_2c+*OEQ33t(ɬ.,'gV7#y7L/P~lmtl>f2ɃS`m7sWzt|B Xr|RVEPg{m,RuWW ;ޟkciTΓ9JϢ ` Db4YQN +_Et9|)Y!49tԱ?ZQyfTqgU>KR|WaO8<ּ&DDӒ['mr|Qq1W/p9mvBjY.("QBv"!+Ywt켻}A':IѩG+y5JU[-7eLKoKy\旁 "@IN`ϏyΐiN?Օ|pOM3B?:;Hި` k~B`5H6?%܀Dm{iz^d>'E<?x+kfqCK|{)dtI!QS8}n5 }A/4q@u>=`6i;me4d2XvL79JdOT&Aφ8v%E3m7ڄ }G'1ϼ4m1lu~`J 0{:D`y &m6 "|zä~Fd@N] 4i;8 id/D-(*DGe1J .'IɝH&'yQԘBHPWTU9Ws?YҬ88·;k H#<+?ON[4ACwwI =84(қ> qϣ]ynlw1dw0;\"FDQ#ߓ4y;pjsٻ>,Y,v1*/w/m.⢡Nǔwr \mj`ۦh8,#wÔܕ2+ 8 q6e4+u%= {D@؄͌pLG.3 y$kjrIPml7+W[AVSm!Q$}ۖy(}G^p*Z:_'>#&_KxcdԤ+Kwr7@~ؙ:Ru(3~BC)r}}e/oDyA rdyygZ^WW9:@Yvow8tkK, Q^Ao: _B,$I߉FTܻK+\pK'Bm,[p{_O ɑd%1,ΔՇiһ8΃:e6<*2n,.JCRPh }[1: vsMB Eʶ7s| $"VG-SL5GKr^G@*g 2(7R/DLԢf;.GUuҘzr&@$T`Gcf SKף"cvB]$[|ߒ/KD \({{n+Jl`2@@/-hʊ~E/3q|*=(:UmP xH6!/ϓntB{YhZE|QgI*c-âPt{i$MqH€HF鯐%{yFW9 38 (Y ߃FQsJE/ 8 8JA#JEMsI=Ne77U˫>ZcR]`jEBRGiDHB|!ѹX>Q=9׽-,+-c Ot:N'1:UVL,x]Q]ߝFBaPpG '3ќؚvd-\]q,3o\Hॲ[nD% *Wh8mh}+m, \)֔tNHܙ-..ٝh8`_L[D>GKrL@) gq҂{XSAUrcGdMUKټ:lk4+z$i$ yz?9AW S CpHbRŹ K2M ChndҥG=G2bV ._R&yyRYXǬdL8AЩFNEŸ9n_DAm~Iog{ut$IIJ MpdSA[kc{WU.%6a,2~7Ò)XTl\H8ܡH X~Rv<7u0KER9=xZ[ ioq3ind+͕c)܏WpedJC|qEG'WBUZZ[ZY_iǝvRKMZDcu+mx5};,RQn'tlbJKh.r,V ﮲]2!3 [ K5 ݏ9ƱT#ϥqGQNpaatqb ;+ږ\48t1ݴ8s.%\e5R+#FK8=9z)W)0$r`Q6^p(<1աdS$>\b>Fx{``Pw,0[i\`H*ޫծ)niOD(|'Ύ8ڛ08ljq\~M8V v",0~/b@ =ehUbceI+͊ 6ѳ.]\8t;-cz Vc"H/P$YnU"kJL i$?2?$k@r?_p^e=t Agth.[$$)#1`rQ4J%2JM=ݮm{Redo2gp"ᡤKtaw%̢ yQ*jQVVW)Yh]?[W^|~ɞ,YJ簋{[5bU.u ~sg\>sdL2>fumm-k ܏]jC3]y"|ajlfﹶi?<\e(srC}֬錉.)G;Rm}]U&$:w*z9nRR{~-K2[(Xġ&Gl|#O mEp {!(˓Uq\oV\eBbSf/d}5:KFJi9oX$Iì ~bcǠ;,Eȸ')I8^;ˊWˊ{0l蠶&ٸTD. `Lҝ(JuI,ڗeߑ$uu/iDn=%{[.Υɫe& Y&oymG# !LpwBmhwOQBzzsAQEţ#3!HR_䇬G MŢlaz^]0v^GXҋ" ]c:JOscƆe_6x;oӅ%&2 4MA io3LpqͬMq|m0D] &,zBqɸ/Zm5nh\P oJ6pPM&=g򄴬V융Ε֙ 6:Vv%>帓'$4&J:ρ_ 1"[گk{PQ2 ^K^e XA­UŸe*87M]P2gh6<&H^Z< O\K,Y\fxU;O%scHrӎߨ・*-BAG2ņ;y[~'$T~9GX[\2ͰS6?lLc[mT {iaoqԂJD&%{k:lܳU'HdN}u8ai:t_+ҵu]lŏf iggEw"!tms#n,NenDM"j)KfDPKgw6nQ 2ci vjVDZ%Jg->Ì*Q0% E#jw)mM`H>)PL )':6${A\rz3<# Vej[^$0 R}|,adZҖv[W83XTIhM\fX9gIeruTSoEʷ,  "ݭ=^Sz!Z/EG.RƽkD eGax>$ {"WT57Ya:$ck29WWv[TmQlqB):n,4o4vȒqZq;,|ZnwRpX7rx,]U!&@BˌJ g{C=| =}bnj54rVaɽDFGż,bv8/b~\b>KXV6Xb'j&^,v$>UU'G-RiуtxTecܡy ^)/+Mr0AQa}Gc6-$Qw;h<}>}=Yl7+@`{tI4^FI$|(C/Ә`2;Ǽ@JK==9vTe blM(Op wioAC^sg^7dǛԮ:ǖn~@OVPsϘ5]Yf##ꪎ]AV|Lʃgj';wQZ;قe1=TLa{EeR!nqi wQ[ zDQڦq4 M,jxbnSU@@x1&9Lb{#zu^6JAEsi_KXZ.{++Yktt6=fO(siw?;&!ޅ3UM8ƣU^!q&L(K˛H(7,+'&5Z:{Ϝ*Sm(\xM}" _]X]rAkeQQ_VEG[!ړ)4;QM\ŖkPVBdyHlvF S§\_fK{?1U9 $ Zs .A`&Op|P2qh`>=Ɍ, m/72n͖Ѡ{ +?#C=).ǍKF(!)ȺSVwp>J6uI;DZ[eFov۔:jCV[+xSM72cϢ>n[ޮ@1 7B '[AW!1XmlaՆ;NSߟD4 =l/R7'*$])4Ž,VVd*y+թr} nҼ 6}]BТӧZ~חowT21ފZюiKCҐK9xBtܭ8ʲ^ك]\Y.49J|5gB?qch,ޱ:J։^~|%Y KY)pr_-81o)ah(nBs@vCױ乹Mj{C$qH}q&K8tZ_lvW2&}Pڃ習^tiVR>>R?ޢ/p47PηؕX^ܛe:ărI\h OB"gn]=R01Hx]E\OlHKE%;+& ׋u k5#l_Q."l6L'qm paAܼpmڲlNw+o:zOgÍO`DCNJxLVBi-2F KliInbcYQ21j.6P(<]E/EޮE hܗEl,j;g;ҵQ?kk=~K`XF< 8uё+]^=UȍF7>|2-Jjd{U{'x˧ɡsd*#b3o0ĉ#<wNhJ0j%U(-x荄6YGf-ǻzdl[{y-]rKO(@1Iv6XwW%SMJٺc#b 鮃Y;!PYʇdw@ÄrM7F{LVpr9u{m&'R>,q^̖VaDe/2VJs+شi#(zm&7/;G?ħz'l!a)LJ2-s#_XtPno@uzl~]_g5s ]kBrWI 3C4) V[}@̀9TQeĂ0 0TgY !,Yda?K[yYag= }pvA]>19bp әC\/-ޠW;hE&MpgEQn|ȭ$"57J a9;:;<(+ikED+PLݳ.qHʎRcDަ؇l,a,c;8*u$ ֬004,`_fc̺f />rHq"3lU7j|]P2.(LCE~,i[BF,S\,EQÑ^._܏º՗!g 4 ЧܷU{'| PU$K@??Io "##2m)oP$%!ll"J65J/cKW1t5·!~5`izEv3+#yRy^0_#slm7+P:B8^:'a$Ǩqf] ޺k_-9YDmUjϢ֣78=DD,,AFS9z:(Eɧ78GI 'ky!J|:(s\Vripɥ HC<2sut$!Mab~sɠǚ 0 |8W9NodZ_<$FG{{>eK g*\qjxV 86Itي+OU9\{f8Źd{q?(pRIJMZHVسͿ]<0;jpCRxZZX?״ !(dLL@2;X7r>8oO.+tMJoD B XP,Xw[>{snNƻ";9ټ}&;9Kd#]qGɢ}R%SPН#;lxDvd"~&c2IE6 AM]X y{)kL)B*$·TeCtE?ώF;!MB Cn#[vFj|[S0_Qޟ^PU Lz-,{xnRťr tcQdy)F?Q8ߛ˥ʈfk)XLY݇%qݼ7z&)/fQ'xޯ[.wdj}za`a ;;7pA",ݫTW=wUtDN裚oW_yNVvp.gDvGeјN<@ty.قbI r.XWPUn8l1ǹs^O8HKwC,#z} .`"k$[#!k~ڙka<=,f7Kr͆W{1apLӑ4XDAS<(uӕ7ftsIiA{Q)nGƦr]"] Z%ڃp'hFEwLYN+Kj9*ّBf=(Y%^wA䝎y*6$9; rE5: VbQ=李軖{.ЗmޔeqJ|u]pűQ2Ms⧆6*.MsP!|WQb 4?cDTL -}Wn>,dNv曅 p$ 8x.:'yw,t| `7&|gN'WL*qP|\ > %$,Y{Clq]؍u@YY@$£@[m^ e?5CeEypΕPsUs;1ë~?ʠ DD!^fڶakl&hՍ%ZDӆI9rFy_9DEJD粨2ߴ{|_Νl? tSF/;cU ҊPooYic։r߳e-Rud7O8a/^#nWLDi -9rctdU شOT6ϵwXylAfᐭQAoo͕c9fgo6W XW(PivZG xz"1?3S(ap`\׉+)oMڋ)IvZ$v܎EU^ɲ&x>EiPKU@8NDZZt_?:uE"eR0C R;UNt ]\΃4)ڗ< yq!EHp }v^vm{;>0v/qyDj /v]m-ݛ`qX1vBtO!+*#M6c:(BW0[6~%6bd)U1NAsͼd2xnJDk}ŒyiF'i$ne30euBVv=PGsFFVPȹb0= 9$s6I& wD `^>YkekRJ_#qG{dDOw35L{^0A®fϱrҒEW=, f[Bڞ Y_*,[/)»vNߡ`1W|Uy0Ta=X1 _9|WISǒ% Y8J(rʏVrԲEO_;L/6*zsLnwzN.kZvv[+D)/LP8 \rx;_tHV X[ م: ^S*}&U<ɉ|`_Kov?eu}SM& Bkpf3יJӆm01n(Jnp\~Z.Nn»̼dЙqrNؖ{r7UԦOtZ(Lϼ(< ÅA3=#Iss ?̥ v[8Qdu p(3dFJn;rFn=~.SWZ&a!}lyl)4XQ0ȻKI68ڧB A)r!r$֒*L-^8+#|_ߛx^Sp_&~0D$ɲ$Y!/_vxhܙĀ %yPw*Xr`iBCwF} |WYgaR]v_;LR ݝ&t@@QgpQ. Mo6u'Yۇ)stY\?;_.q I ̋ 50R\vlН ƃYoҧPt$5+"V2P" q ϦzY@P,ѨthR'd1q07`;|qt>/C8`6F],3r@8uKGk|ppq|;^h3vaiiK3nUZ-7>Irb,1^wz 2F4/:,[2fp{]C?+Q$iyhL#t$?˿?$2P :l F= D~DPM0T}_e <>Aޟh2 *ވ~800!&࿿9E\_>" r(Szk03+sx_=^*Ht}/|e~:#XƓٰBץT1WBҤCNp}2Ȼ&c*c=l8d@6E!H rD'+"Hhl4ӎ $Oj%&PN)o4A g!c G<Ǒ{GH&u+C]MQF U(R&3Xa'dkJP<$/ < xXmla֠^JB@ʽ8Ү6ʦVζDPsq g}&WWLwxF%r"FYJ}U+,݋q( ȸ"2"<#&&#P@'+0:`Q^&\.nAU"+$`\aKeRQDoE` B %rD?I ibt2 P)Qt(I# L"]$ !ʤ4':߁a0d%{3.=\&H]\mE@8dppQM։`ˣ\\[b\;D'g.AZi$d]f_$KɂF -CkQE\% H]=%uP#mxԷbX}?! Z! U\SV`rv2Mf'ٜZjԈّCK X,iPcwpiLq}1lqB n$| 0g)x%nߝ`O";s,J{5"msKܠ)J~PDh;yLbYzjRU݄Fy ♁,3r*9G}H"{>͉ѲD]}8i9ByDIxTtg/ Gm@PPXn7tIP)y cAtF,$%+.-Y`y*z})y(jH]Bc`޺;qvJ9o("[(xgSIrV"}T80>R.6Xȹ#vB߀/eq)K (Bϓƒq iABdyz nyԽ ¦f;F'z5s=xN3M-< <6u,UjQ(f4+KC_48;,j=LMwkk(#34"K<|>+~bLrd9@(u ʓJ 8]RJI58|@dEBC쏹ufN;dIS#,6g }y,x8 Èud LJ^G7bˤ೿┚hxl[r*E SR[ˮ]|{?.T^A@ .e]L?gq\8i]pbh&?œ;g{IZOʱvVYuxE `Qh7p:I$h(V΂i/X|g(.P D#Wn[u4MoWc\D[>}D[ha؃E<%j:St^D9=0+VwxyA ˣQȉF0:drq@s`\[&: EֆLwB[eGs\cBϑZn )3+u؞B49+a}\; ^#.\YBԞA{O"NMIi^%$+pJ k-bHU 8co?؋k8F{۵8ڬDu]8c~  VyE!,@8T `Ro1*E;>MvQ'px_ $ӠCzXnM*kPL<G<>rDg9Aa;sD"~T|+aD,(z9V3~Ytf8rbItq$#+\gj9`[^@7iۖ#yDT3b俋L̐䉲jjP]"z |>L)o5ꀤGBb}2T[iE? I5LU&9w}xuұg?XR. zS͈ܲ8+G<& ?F#MJ(tď7/gKW\z?Ctz̉ʺL #4BlzX_W|h)T`.wE^DAR="7*A8];e ʹ=ݦZ<;eǴf7s!-Paz\*M [ ݳxh(]3Oe4o3ኈ3K^GLci=e+,(:Y>(# Y.QV9ҪǢֈb^/[v2u/)Xt-y:]1'L*LwZY祹! #P7곖i} O #T?}LHtqi}.xA ,@9h̢?4;$yEhC^G9<y]'ɲ8lC|9)Yh%)=tI$N.] N@@Yy9E Q_d2v:iuĆA@g[I0E֜-hdYX-N&1$ ]R!'೿,9 ',a`-P6Q% F9ej; ׺$~D-ƳXL( sˢ*,)p{7XטpY'iD?5-u<E;ֿۛIBH@BBW8u{/Aa#t,/+Cwf:^.-OMކ51vWIlAbQ#QYxB1wwEU@9) N&CYgv|PPyBpK[p{Jkss{)J}ʾXKX$Y^(rs{4:X0n! T`<]QL.-+Kր]'\g_ k0I,Fɚ3p aC8 `A 'Fyu?h'aay`5"a(]0(~H~crqKZ jE-g0jbKfנjP9bx*\,E—Ee#72Fp J&wT:7\W: @a\el ~ +,]>b/>2 Yuq*;Hj|˯J(E0aF숖ٍF=`E[-LJ"fAΦ`O&< +7%P8[-2'?A8}˃X2XE.XV>L;Ut7r5cҦ\/SS] Ƞ˱آ; NNufej[z (LJK:[*y*ƕ*ucE 9Qc )p/rj.pXħ*< HuQZ&E\uy9NΙ c{P<\'J}ySnV-=W:H\i` 508,K#RsŲkhEi0!1Usb5UX2yLepbjl6 &8hwZŊ8ls669J$G"r9Ug LW )uS # ¼zTΙ/8iVJD)>^k@y(ΛAK%%Rף&C p¢ D=BE0m/uwXI$iWr?/6 `H~xaqEsfZO^bEZX6"(Y m*(7+}TNXWJ|9LY+,|rx.HY7yϢBbYiIB9U3X> LQZF :-ϝTh9ӌ/`+| 'Ow)%-DVX8#Q䒂EFiH:D] 918yeiړQig 3IslӶ[ZIcЏ萎`"MT@X_/2.RbpC5~QѢpe⏒tFQlN¾cx̀0e469? CzҼ*)_"4a H{qv#ܨlg\-c]E)'@ICQL觃UˊODdYFaJY: p;o[v7B␚Rq(wL6i!/CQVNge%!$40KU@*n+}M@C\0itVNnOՐԶѺ$ qLEzˆFFSꀂ s+͛9p@&HJ5N9?:ξ0,uv !ɡW,W}ūCAA=>!x~j۲Ȳgy@LhvX{Mk t,;,n@i:F]#0OMI';vt(Β;,א͕c&t'%E/!Qju0\~w%X#eb$UNo򫖘˓NJ_;Єun&C~JHqvUo!WTY;xZ cQ#-<˧Ac G\8'[?voXfWzGޯO2#wɺGDz߮v%MjtP- d]6YYBHfV$^7LūKj6^.AqerK3z:&fn`co (Ґ9'AaVjU)&`4/os~jti/ۉJkQJ*qJa޽R[(:c|z!+ﴸx:jF[}! 25$i8&UC3 0m)Tqr-XzҨs Rgyr!Vt!Q'+E\tIp/^B*cC]Eܦ28f2Ѹl,xÛK#,[;vHEnyjh9fs|f-+aEUvB^I&^8[2WˌI9JCmk㈏9h_~<, ƼIP+?z"Sӛs9$g+b̬G,˕h LMB!܀7IN Jph壖4政>Saz;IJ}>Z:ñP>fpݵ5wiDqozcaKI)vZ@El9gއϷIh9uhƗJ^.0T|{zhll@A??╗&'ӆqL Mʲ>t_?96(9c'- VJo*!}B]@)X;#ĵپڸp~A b94!4߬Sr% 'q!AF6Oܪ;TѦ:|l6܈f O7El~@p`Odnpe1qQO[mPҙxl1sx. <,;-Phg)upwY/E÷I3Y 9+dXgwC Sw[ܙl^#op/Y= ka x[tI- X qau3Tv[W OUEpCeP1s_G<&&#9]d=}"nq`sT=h_.]s^YȂ"u닙u5Z5 @ѳhcEV`*6C1[=Ig.4aKNgϥ%'N3:]7< wEQyI)Zp^JIa/(+- 9eVB`tP6ۤqlޣrd3($fKVO8B|¿ae2)-.q3 )&Iglkߣxcga VBہ?Ѝ]tH^{,=0kIˣPH_($\Qm-ԩrdlHE@"wˤE%ptBu睁SǞIwnϱKЁVKl> WI1E#Eֿdkqwh2pGQ;E>Kh,­@m~{y8rB9\.v SKB _EP8LXv:2ŹrE3HC\E 6XRi:>=9h/3,5occ.|60f$L$JE@9z55_EJt ]lH:\=C<H陦ܣd͂cWNg 刜nHم6Z.g.^ZKAF$~Ɯ+ &>Ogт j 'aAjL e a*iNJ_qQ԰ՋEG4S$n,\_(g!ie,j_8jIC{Ke:Q(O O)kC'\\`P.Jc7 F#xU6ōQ7dۻ{ %ZoSy] 0EYc9(ݩvd'p{E "O/Үg6=8Q-RdoYjJ DCiylyJWDbb?6|T6qOF⥦QBKu0='>8vU$xro5FI)lY4˪1*{H{958XW~M0QŮ{=|m lWs!G̐Y,}FvnK*?\gN{F`=5Lv B?`a}Ґ0+*c8B@BuvTaý婬o>2nWY dkiI"qھZ,(44Zr^톤 I7:D%E2H8 Y06A M6C*om㛕f]..vLE9pY;JXO$s4_|RDvڬ $L5s/«-/g_()8UWs"o E>N"xwVJMA- Qa%5#wyO,`=wu[ Xd,}={gO=P1]>v^'aP>')XSQ]4&zQW[T8dC\={%8JRWjay/U&@A0<$5[wbl;Wq6+pgȼټ^#T+Dll{f] dkiތ#VIL}EC3M^w DzI}lBX݊9,$5߮T63ui dتx]~K$:|}Q;MD{"siD#% n&1`D1~}HjnYN r|pm66l%|2 >|ŐA_Oca" b~X:YIW$ٰԚ5&:%nWz!͚'R9y|-TT.+\E}9Շa_RwEAD E]R#Qnjf%]Љ}ٍmP MNBtޞ%# Ogs{GECR%![)х]UE=-?po۰g$qt;uf$jK7n#߷hz%fC˸ hR E{gsZ(K+zX+xηM\dH$RieXf"iһbqrH$M)  ]< 4Q&Qh,2@+B{{iy$(-A4rs{ R;T(123v۰he1 %9WʽXVg%W M@+{tCcr!]Y"^7TM^FZDj|Eq8ې{E&'-Va¾wi0 QÕ;HԆO+Yf|QZxjcA Jr~hZ G Y%߷ .^x>,O6@J.toX-_ͦby€gMn;2u>JHq8jQr +46b o%ISrYɣˁr| Up J2~НO'iQ[*P"2WX7-,'vaa8!(dM::t,Rn/Ky⟞-'NH7mk)νܮN(J;Q҈;k __NBT"BpZܞOz(j@c <0PaQ2B3̦c' &JE(0B$RXMd°gt`{@-&`} ],Uy@ NiHdhm+xJjm̐V kd UWA0x*%IXeķ(匲E)X\X!87'6(y3!63\5bt+-O{X:|*N J0ˎϟK^۝pp!I79Y3q p-Z*w(7Q͞9(2cN2FRAbv؃Bc)SEy0sS*씐(%x"DxYw2f`0e6'Dq"ƄC+op-aiwp &Ei@rWn eYoGudkɶ'H]kڸX+9cb*T"\DFz2VK+w۹qIk? X*;ZTjV[R*öרٮf:VvrTJ$o>mܠ!W+SwtxEܿI&A ^*OKrX}ʠ4s 4Jm318i13]4jlF8n*1a=bkBn*8dG5h,y$'5?%8рLpAkJAؖjBpަ*mє"bօRGoBۓ<y΄Xii8fa)5elfm/L6(q˅Z.G>2B 9YvZtkoW2Ywj4)h/7LYclA"",M9+S4 Ί4$ 0gw^S+{7Ӕ$VHN2w++hr<9:Gh P!H,MhgYҏ۔F*cs $$"I Ừ3,<\G[C\Ň Ҭ_bb*۳Ȝr,+rҌ`ąK +eeӣm~ Lacs7]۩6„ϴւd* r(7\~ZJ>K>w4G˃~!ciUmg;^fE'yֹ">~ o Xuj#^nERL4.\ς{^5ۗ=PM1#H\˚5`9%ŇaRB\98WZ.=U̡y g~jnU]YEE- FrXb4+VK2*x ]>}coϗ?sϗwrX?`B}֚X*6JC96@KSEj}SBp ֐,IV._oΰm|ѡ,Dԫt7oѯ8z,59 [,QtK^R-P'=\.YM{3Ȕ|_e?BCC} dY_4~Yif%Kcx3+{$Y, Z EPgؚU[I%J HBScm| l̵}l׿(]⃏<|⯻:\ ʋ'ZvnzS&Y=rڵˣy5x?LWvw҃0=MON& L(c_t(sպ\^&dSax{pDtχٵ^/vo,r+6r \,9`iGK \U|Mh<h^p2a`T 8cxEo ?3A&al0 0m.f|y4C*t4OL]QE9ِX$Ve:Y9wp )jL񕣓+';w<ϐA?qidLˌ/Od^NF Q5- ,aVe=#g27H.F4dcc)>.y`8kX$9`U,3u5z4> >\&w<Np@rt(y7F7-ϗ=s00{>¼qHd8A (M2 $ fi],[ $,6"B$Qsa6೻U}WGռkPCH5.!Kms4gR΀wAhP #%DkP-#T3Uk X0,,wL;4:Kɠж ^R!&H@W ]*e]_`t^1b ɋdd!i'ٷb]J󰞏!Xu>W;04hrUPwg`:\aZK lP.at/?_qU>tAƔk,8HKY*|kf YnR1=mN<ȱm4<@s|6h>)F$}3ᰒ{zDG9gI&gZƲoKbD@C)Ygtt_JOCy3k _$28TACC','$ 7Jbq|P.6K>P~18 *9KnS2Ԕ[*+A1PF4N@qynnjCy^@}Db2]}_Ua( n~U1Va4ܠy0(cjMVr؉;/onny;x y'ۊt$8 >_Z)t-e#pX7ϡlJ^L1gӍLE@Hu.v)ENIu φφZ63_@ 49\949ڋhÑXf]^.ezYNWHF)d>! 33sh?Hz'z#29 #LעsJg+ B9CoZ] `0 &V-H{y B?K1.yas:xh*M V\CFe +)o[IPnW9R0gd dSG別`s`ܘr-"(w(!>*] gY]͇CQ#hMwxs"MoYs"2O(HLGzsp>94K(*p);#x7Y3"Hp 3N82t[S%u$"9n :O)K}&A'ʇD)-EW#1Q6ebY=P-$^!jb0d0iH( %̓ͭd{Mɺ)' ӕCwGgl3X1 l Hd䋝?([nv$gzJmeHͼYBYŶF[xÎs೛ HX"^\g$brnn>rc]OTS@q$Pݢ M1~edge|: ѻ%#(X鐥9 lCY  pJ@E1P0,ܰ"N+ϮK!j=bX;9.ixűw8E,:aY7:~N?v+%*`"zH&^iIL(9haP:NV)9:Y, T DLS8&(txy@N-cySG2*fqM#F V]1u ^IEg;dlS &V`S| |vIdj_:d_@, ɱ" ɷ^(OS9ӎB֝mÃX ! Y5;I Z &,V)V@,ϵEW2K07{Q|9t!MpTP'C&xF7o| UJ JKՠvXV:y?Ń2_䐤ڢ;+$t8 Tg]ԊYMP?SJnur(DjX,UF ˛D =ZXbS!қX\9Ɉhk"}c_yܭgsl!C,42G*J3C|3]˔k3Vp!ߎbDhVMž+[Eq*Nliڛߓ"M:|[(hMp{R+SpG6 i"`12̅avAٓ1u@ o̒Ž[)y)oL@!f E طDÜ4O>Ijm7b~!tL5rR5߽2Nq{-E>( wi+oRfRסƨP ˉŗ8Ts~kM$BBxze#u^gXxo2.i a1ra>1I8W{oD2DoIxϴ:tHx=Dh*v@c h>u'<3:>J0!a>+ϧZ' " @,=2Y AQY1,q-_@,ocXPVqUceq=c60 PZ>(d!HT ;;l%LAw“0<99㣅lk r : h'SXۀ+2ME"MNC_P.ccx 44&(7$ºG. 1F!k^澬t치媂%Ha'iL9`0)1q?̹Ie u-,#X2jJT+HQq~djaXClƆ|ފjiGB4M"89W$ 'g}X=b!G4XX fޫ ?[<D7&Qq4a$mH<]Hyi aip^sYt 2@ә]V-d ++Kd9Q"2E&>ϒc\ED"#p^uib@ntbc- 8RiGiuAӸE(b%h$l4="*' x݅#Ɓl2xNu(̟LnpskP+랑1:qIs6)82~°c8NI&Y='[hK{=>ebGtnGGoG8 Vȅ+^M%Rmul7k1.@2LE;hw73'/S ̎f&h zTI,.GMsϲ,N||s&ϞׯJYBxaIu?DFͺOTPd$q,0ґHyzu]AJ48%p2_bFX. 'tÔV~J:hbQYj4#2 4cwxLbexlKD'A6D$I gk+bp&'U#@8 2j"|Xӡ>&:c\ G+2W$0^cLFMqZlK]H*vUc]p9js-u|@Wr8b33V5"6'mAץgT=+OHn3*y J.鳠N8{F”14~D1 g@͍=X֍e&ch1Udr8YFΞ!9$I/Di G*E ИDI#6nC7nJ#%1?!kN[⇉(&GNߪ&("a2jIe¥r*!qT_GŊԓ(k=TB2qq,]>3];34ޢ1C&K(Eø3E7ӿfp D#fPSZHM>dѡ4p=p ځ:MSd,-~g"ײCߓ mdIw`.5d鹊gCz_>X(xV,7G\EP̃)Xwؕ.iuEA@UTT++] =xT-2{4+eS)N%$ȳT9o`<,&P-˪8I_hMZx0ϕ&-|Y.:Ȳojɸ" ēb@ %u^. HVAT2"1hK}?C,z:wHg,$Fpudp0R7T|-`( CY bv̩vg{"`^в#gaR I }!`f/pn; 1N &P*"sCyDxP*"|KGh GhҤ{tB8|< wVˇH'%cH4f15Eqq> auR!jL$q,ePF-vK[j6$ ,fT*|D-9 B24AEMo aP jXnEV';TyPm!{_к4\%ldu{,Zj\|CBUh%WPZqtٽ["k%(%&K&~|EZiKX ew1]Nxo(򒖌ϸvAWZJxw2ˆ$t GǎoOƶE.]._n NVV=x¢(]3/XX~XcݏkR2_ Xf,Cʳ&,/u`9Qa=̄HPC6w7yI`>-`&Ou"Ƶ,ۑh^ :vKtIOM~,dMuo(4)ceL"PL<܂'1Y6UG z]3 jrs(]iSc1 IS{@}g/+`;h`Hv@6Vj6"䗣n!W_Pvth hJuR̘IgDo)νg8X0P{^2$6E1GnM)OZ2ɱ hHӀnf[ a{8a$JA7P OK s~? P& K*'t~`ǎԇml~ wgG&[yN1,z1I,M8lN϶jIW9`d6kOڷ r&!6-ٖyE@g\d4![xٰi_Eɸ-|,SԹ# TSb4;{ycS1l[mifM,Vav`;8#|z?Ip=KYno?݈V6ݍ67+/43Ty@NZ-=WVO8(o(sȡ{_DQdKn )G0I;h%^LZ;vӨ[oWw!XPwiQJ7:HsWXKdTpŽ(Ʀ&pf n7a3,0Wss6sOv>"#_*! W['5e?5fA&9Kq ˴HO>n{Z< $7kC>-?K& ur|BpQ5=%V">f%6 8m$,omV{m$o-$W`’ پCq cAP?nA+_X8Nn<~kǛ8!B/ӱ\ V "&Qr'pK "3aÍ)rg6?6?b,f̸5-"G NKI 689O*@?qrs@4;rś;w7cGIJ"g,0pSż=[ *|jxsmB (Q9ěN4na 3DG\i0 2n!JU-\ۤa Z!kiɨ+*G}ygiV-۵~m`t>UZ'+@fŹ?Ja`8}RH_玟iQ]prwϰ}!LXtS܌Q"Oh)fI9 0d&ECr|@J> kl[`HvlɠJ疈f$ti/SL.ߩdlkJg&D-c7:K|&,Rѱibb<t<:5j~N,PsBE#b Xp]䋽Lk-n]]6onwQڲ3v+Ʒ0gri] aXpyTE6$x}P8 PpzۅH|?[TRSl4l!,1Gkӝ\&];<)N9v%0r閵5v071)5{ϖI |쩐|܁W 9to'?-ODEZlCq ׹DĂ_d+S+PePVq˧Z-Q #\{ $f=㢖2LMN׌*+E,0UCcjt>HFRBCP.CN|hsQ_=q6$32UF]Z2.g)nG9CVz1ulX~//&皍,ƹI~qDë3XxY*X7t( rH.OGEHVS SgP gc'٥j49sx#9x1HUڜ,Ck'{ScfjVp@x"+Y{[di]Px/u\īZ>!l|Ծ VYQD(X,NXPs:?< Sd>m@r]„X4 YYAXN=:>Z6, ˏd*M#PxeX%YcWw]5b?J}k53e{_ıh>JcLHqߜ}OyNvຫt\{4 7flSN8 (&'0UĨ_YiA!㩤˹_nٹ )~p˴ɹRYe?"j/;|KHÊM8,rt:+8Y8!_tٻEOH]UbN(#yO-Bʹj${y d{񋿪gp=<'@z}[Ai/M_uF7]SFvrZX(*p;\nRѹ>E-;&#b ,hzAQ]@0[8[I7gHnc#p7:rYN,^DSmӸ_u-*. 8 ʂg&/جי`ҡQgZy^f\QS84UKxtHƒ{|[vη딁Xq<#v>eDx7wٚD'+$W1C8 &e4^DY]FVK F6n!i]i*q3*WHȸ[Op)_~V[8oR[QԬ=; <6T H"*>+kT C<\xP 4$v&u|zaX c5 Gw1m׿\[Ix ?t~ZSJ83>d~VKTpZ| k˳ɞW]C1׃px,=x8'_GD|&I1 Z;8˱Z<x;xD5x͇e%D{36Uv*FM.r7C q+\espD NWqW:5q'^N{Ь|0^!Os-vNvrx2Zx[*yWVvﯽv$ͅ |8Rywٍ4[^β;8r/b!24P4@rֱ6mP$%GXi=YV@=M}#7!otJ0hJEpUpC6hXCԅ^fG$8.Z$I$je!m2StptӨpql5iyo-PUM:ν{h\ fV{`K'(Jo-irLc~ 6a4kbpAJfHbnӁ %H, 3GV-Imth?>QzJbN"aͲʔp:Y IQ?xYjϘ;< v9RaE"Yym%يX$lK7cgzsys)mT4 pN+YWѸf J3z7o='&KgNC#n5Ew8A0|J/}  D0uerN/4M])^Z"ZZq 2H.e^Df魖Z~`oO ,֗49{qvms-:tz{qX%4?:4DI=ׅ$+DiVȜRH5DqG@V+W:Cdjaqw ޿rsV\Xn%X^cCG%%k.~ޗgiy-dn5P*>ACvCs?-V 7(>3[s7".ҪAб.١[ x;krKD_q',1~K cĚj Jn 5|jVY~QFռ_{CkK[1ybcwќ7ɸwqjm&ejZ" /q2gu()7~³o HA7=Id"Y ,8NT vvL4űx Mk=Z/*2EfP HxB6@Wk8p> >n("90]D7Q&g 4)u%n򬢻ayfB޼|F]B/XBۍ,u >"j 6˵LN_Ovqߤp i70`ClA3GxIח+M$I1J]KbD0xJN| eEJp[>]mxt Ʋ&mEW`s|,tfStPWTR 9O~ b@^f͎)WX}+O)Hu(~_ h<#W& Lot|'5t? yzLB$Mׂ f)#G@CNT CY?5eUG]d n7dO qY}z0U/*],0'}c V&PgC&q4T/|0)x%$L8XpܓB9X:)n6I޻CzpMɀvڢT`SS OG {\Jk& I#IfX׫ 1= nPt\`x7Q7˒ZfqR0o'Rԍ80Sxμ@{Go7N-H[Dra;2{gt`'ui {y%.gݤ}aޫ]4 5_^/I23Trµ/ ͘5my6*!Q,xح̀L 08$D5m Ysުe{bLRQ!8jr콎[Cy:IH‘\𥹹^Sry:'1nԓ2DXMcRlf8\#AI_"N%Ǐ肃ij{~˫ Q F{6B^b ƪ WHNb rӌrMS&;~.[o "/sJ&za8H4sL,jf]JsPaN:*t9oDb^~WW@!u87 $QGYsr)gϜ۳l)UPT .) 3jsmXudm{{N!+6ub>O3Z] gu(.^cLhMI|;KYb[*njVY֔ gis.Zj G$ X9LMR/EY,gqʙa~I Uq{ {@]hN.y9H4Pk,/<e.gdf{ü8P>[:\ :d~B _*к9ߕJ0p(x_l|B#=&/8aǴomnDs N[9uK|Ty%zH7x-o0u?y-ddʃ(H酫/t\b6Xdy8; Of6 dr.1؟-y`/(ѩRpa<[ט0p!I1V *Y_u>xa ׺x&)VfsHq7׆?mւr%#j {D7eOK2,ꤱo׋"X>ȫby 'ґukYiD>`[&]aybyX]:5ȝIN5AC4 Xi'hZ:WwBrߟ?V'5Kc‡{38+ihH۴FSh-q_ kEvº:{$o?)ܶ]z+= ?<%X͓~h7?}m`g7Ψ'zEjR;L$Ƥzog. @B; 1.B.?k0e_2ܤ^ȫ`@s85hu01.zx`l]_rbyXg/J9 Y&:5p糰?`IKgL.4dtuXcGi*.qy\*F&a O{;U&o@4w:Rb!v ыZAlsܖazfyDC8$짓Q8$ y<9y@Y>Ag%*d4FFYX!-Ru"?x\Up/y/9; (AE܆V$6%~>Prן<q9fLꌲ%jnp$`_Ze쐔Sƈ-w7vIV/Hg(!բ=WQ-}㌾o6dJ6 %aA7cqV7*P3_RY(~2IG,,@#M\X,c/ rdtaa3@k}qNgDT$0,}2=XOic %sef!b]G`+ L8 ݺ8,Z%K8!=حkr!#t3;$Q'{Iꭕ= 11~L1|W8Ѥq;xUl',Ӂ8@'=λ Z{8L̿y^- g w%Ͳ[b7)9nzWxd#)ȝ(3 Yh˴I`8Z7XtyE`ᲃHm8xwA˺IS &נئGt  \K Mف Ԑ{Gwck0<`PA7y0*qY1^ W"vv- vh;q\bh_dY$$9w1mq-5 4ɕ#$ir=`1Dtzv@b(&Q DN-;0%6A$0׮X ǒ{6W  w6p=O^?%E7 ҇eH{tmք, ͺd*r,tWn+i3Es2~ la6V,ã Pn&kQ$xEɪfK3G7*n0NOھݔv<7Kd'։i4 ֖i~br-2Ivr)MWG@y-i i3EBLu}/'ʷ;--9KҶ0Ğ(&Cה|2X:3t.%kz^Co6,ϛ^ȩ%Oltfa %ڥ=K `Eu'^p~dO{ҍݗx֧ظ7676GF _/y7wk<-o5_7VWl2ˇYQMghu݃ {ۇ~%_{eM4aXFMl4 Fi9 #e{w0^ħ2Ǔà<߅?Η,dVS%,eai(@PH@!A(K }8 ();dd'2g*'X: ߺ& ˓}rpGnAF'YQT, q boW&_]K4 Z_7#߲(gӂ@1h'hK45|dy,|2$r6q@S@4fXL,aAXN>ϖY>c@L"${4/rof$\ ɬ+' a;#9x8&8pdek\VXg! ;o1,y*#+p $NGrv'^I+"S6N9}eZg}"줈<x6R c=1fXEה< hVUTiKY!Ȱw(}(% f%Hp0aoOZxrV siLw>T!%OةP³> bOd3h`ioO*ourDt(Hp(9 9j,։@Y&A%LK"/w 5=j`Svl#zm)-fhU^f19OWVg EpHYW9-%PJ%6Z/eGhg4~Tb؈ʹK,, #)e yK^LEf#&?qx#h_~Fx# AT% KK]Tq nr@hp{>|$*;%z;c`]T&av{A!?Yg+2]] y8: ;*"e@΀n6Ωk!:CE[-lX߭`ߡcuB abgʉIƀC]H&*U{͵ ^RȀ q8eJsr;U]GLϸM̫QݡD Ul4sħݭ 7)`gg҆׀ 1d%q$JrIDF"`Y,*X_>+PMɅS`sޛSt4Su #ʿ˴; ~ɬPK4eJ[/ 'yy4WeCy By-?{m ry@A[W SL*_˘8#ͅ n.@@tf_UHfA5wzJi6a!^"?LQ`tEI tC=e҄\8M0B.2ݍn;| 53O 7+-~z s :o׭R!M?)KƚH!wcaF[['5)̠ cx9Y. M7#@ -͢b.v@9"iL*VnhecQEyD,98U5(~t&^&>SbO ~lQU Prt/88P'8a^2[ y zgH$ 1;y f Xu72b?`T>cWE =@2o8C1RNe؇Eu0u|]Ϣeyu-|d^V4& Ӌ qJ*ͼNw?ô4lbV`a4^hG*/N)̴'%ԅn/-/ubE80N ʼnH:i F@fݔXu4*ed%ZP=_p:3ܵwV !PD`Qs:oFKEZh]ΘŀB1cYð |=b tx~D1 0J}d:ƂֳR6'Y8tVZ.0g 3uĮ*Sxl;Dy$T}TP$U(6`<dC}P~e#??%SNAԂ nxz,]%RC7K+ۜZ 4FEdG#yve#Ap>c9gK0i <.?D tv4(gcc b+kfoC1.j!Pni U-142[PΤx&:T z3?79 R 1;B#ڌyOja$ ;B ۸6.15gXayqѮLظ 9x#f1ȒXI4m,R=G)cAC4-Y@Ձ%# Oo6>˖eOf%?GL n4馳j 8;A0#Dy'9M(4 kabȻU0»*nB >1z Ta!_v<=Rd YoByf2+ˮ( =DOq,N˗w%`A1_D?3H'DNjA1CB9/L 8E921l/RYǠ03a>ni Ș,Oo"$"nm OGjJ]eT>`˺. &Aڕs5lڗ#g8] _+K?*~FS8 `ӎ{kaHxK-<dj4>K-9eC$^'l H :DBD.5a0*HviCGhejB)&97 b feSP63E#y/F!M,z!5Loay={ۛ4꾠ݔ>=K儤rLJ:LoA*b<6Tݡ[1R5pACbzb]ʾĮ\+W' G)Y+G,IWL ^dv9l?2u$.{rp`i+`c!}E",`FNtN*t zTm4B.%YRu'!x)Rc'tRXS7 z8rHA 3,;?ѣI@\K;Bb^ Nˡ.FZ4Df,*NVDT<%+MYc ϕ' rLEφcL I$KpwBԲ>va8l'hLԀehBŜIޙVAu%vں.] BYoRž.ӴKc^Yg$#[?Eg*~>XTB,rY֡Ipx*[cӛ"pk}D {&C[kl,Q(â`60HNU"FqVy#oAfWWyb#tNxq4CPw G!7x:۰hbCĽEä;$Qk4jALx:!K[i,s157Qb‚@N{1[׳T&C*.rݏ91M'A |SB KdiWS}ԭzB4 Ƃs|S]旱fǛvdYqˋ 5 lUm#ޱ&9(3Zŀ%hT N,waba~ӯѫ4]O>$5 ~։Tq4бأ-,bf %zI>m(.Z$;b X2n 6XX. Sb|V~9!s렬HN,'bxbL42|=I`Rx[-}4NBPJ֖]ܙlscQj,qw#yFi3\݆IO:t>P8 aHӏ;^^"(#Gn N|0FbS^`#±<;MS'8E%aE3Z.Xb}}KY@Ve/~W c"0Ҩp`=ZH&-G[rpIPt\ǘ6&'ʧv 7NXS/XU׳G;OxU*-y҃[0eE-0c|Nh]輎JXz|(C0*?*w㰊(!-aj c3_D|P` 0%ugq(*T'1I%5L>`hir:3-DZV@zF&Yz6@դ'(cv_Sɸ5VaCz>F,zS)BBxI;sF]̃+J_iTt8Ÿ5 wIޙMhѦ!\EnjjO`MXsyBHBARc-^%%>-' aJۼ>괳BkNO^xy(e%J]H Ŋu嗅/So}CWKGty<ۗY7' Z9=tf3¨}{1Ė0,]\^{PQmw*qMc& *wy>m?&"rd8'9!#y@k (L|7HbZ ?e'tvn]*UEJ$)."oij>Rc2~mWv N PwD޴CˣhJtup@QkP Edត[NCs([^$F enE}B/U.*PLTJCR36vuZyQ.I*۬0IsoC9E`MMs*q#0zQ+b{,RDOӹki %SC|xε@.,W+?ϡ=[4J)=yBq{)I #/ -ͅzS֋qHfiB!ՍӶ kV5D2: du6#{l"zQzovv,,Vwza)p#t8Hٷb^]'DG$ztI,F 89mfAL`B$꼭[Wh@Th\ΚsL< 2M.jE͕z|NMefLZAm'I2qחE46b{6 { 3tT}W)J k 6V*T~FIӟKo:l_hQ8Jwŀs2e j]wq+^>/&C0yQ5肪,@QRnD#z(Ψa s<6U2%-mAAIT[/@ 1ѡpIT1OB(/ e>aűM׫HT8@3;mX! lJ/wv50@t)]YԅSZk9\]tۤ˷Gn~É6mTGwv緵aSAN\ʑP,~QyiGTߤ$H^zBc8O 5H@t\XP+~F?ޢ1aɈh M$y_vRE5e Œj#BJlPŇnI09^~?x̜p^lJ|tָ͒c:qˉrege#Eԅ2ˈ ذ8|ߘ'yட$a[9BuO#¼m)9#눂 rA;.M)gUC>DY(XLYq#CKJ# YR'JZK2!y*z; v?k3Q*%aIX|,3&-Sj],q%JdGoy5ED?׉]cL%KH`Eۀ!iS%8 ZBs,;-JD7It&$PN,OS4N?ښ#aq1&Qom<쭐X_o9XlC:VnƂ3Q- pQb> 5̉F” z,l񩣭8RDpIi%@M6f|_ ]pQ@ؖb03 g<#ϭpCuC9ҙ%(E)"3֍[4֝D#Nⅆ5`LyCIn@2Fa`!lB ԹI.)V)Z ?aO;!%u\S.XV` SdQ:KJFe)G1Xh;$bЖwNP3^=#VFM2( ȵPO={(ٔ| S3E/N0ʝUoI!m9 6Պ-Z@c`jgZMFFjo-LSōt7tqew"Ub*"tQ 0-(PLۯgo|Ak2MbG QÀ4yTЮͼ6l3D͞欧pb̡2ejM(3˵GKqlGW/TnHfaܮT$#mٍ_V&*>SRL MmL 7iQsO  Gf`EUM"4Z$Q!Z^go;-,R);M$x̜VLDG.\m{[V2޽ mCubor\]M~%V!-qxY_s00hie2/qXd,x D1VztU(s{t2k>%z>ؒz U'q%@XΞ8ӑ0dg֎!+0U&%&eASR&\1|kt4\8<֋OGuQbf_Ք k%'vnH` ;+YwC&rHb`5\amy[yqoF(%l+o^?w#W˄P%/^k>7@dI.1d`rR,@anif! }9Q"dtRAVU%K' K֮<4,WeclLrc{µ#Ř%qrCə/':-JلP="#.XrώnFۛmŚùeвhiF_bDYCߠ6qMYo扭Loށb>;]рn " U+ gݎ8pЫdanj,Ĩ9X|s xBO6,pt< ɢJ}\ͮRJeJ7XRr0N$tUu1*E:IR4sr„MҀ̉ ǹ܅vo\X8zVa79%P" I;4 ?u×3tE;Cz 2$ϠGb/L u&cmP6ь\Cѻ+_(\p-YʧÕx>i߅eGk(W%y.TA햮04ݔ@:06ӌ$IثSc+%WAʕ0<=^53qYsnjc~ӤŻt[TccDr&9sYQ.(]7ݳUѣC4sc,- '+' &/sEZjW?Lxt “8C3̲] 9Pv[viß T4&Ŭ n'] Ey9\=Sɬ=1HCH#n9RfjJ᝞:6WQX{k.Xn :\>`;4 : .dawd:rmFGdMiei&^Gګ1VFxEp4:8f;hmMS1-u.8ىqSɸd>f{Ӥ -ϒ }q \>}Zl6.hCۗ4$LB4lБ$Rm{tQ osf9wc>An b&ֆ"7-1["V%ˡ83Z唺a~۟:-|r6olǵStU6{m{gh l1YdpP]8p"B4t зWS\{x3.%*.v|_8:14udO,FOF:bI)AlZ`͈ zR&UH' }z4Lɢ? hE#0k<~kşSlF"9GXp~Ԑ$\Ke ~eZf lh:6plUlo?yC'bYL)NXIvAA",1cN>,inɽ+ &t^["iAySyj·R`No0$Mml`=( YMiL{*N"{G,0f/GhRLFv9dY,_*b銝]2X< 7o;Ʊl(@IRdG;s_w9_yu r~MgAf1s1rcnC$]hغuS\6` )*53"}dKbP:; oXeg p}ߪU G/ < :[b[Fھ[vj?^1cx 23 NPc m#+%_e1ĕ]p9:0N0SC'b\TpLc$33 -#6 < DQSj-@E/` ˥fsfYgAҪ!EBE٣ÝNVgEޝ:7=a b3(ӏˤ b@9D#=#O_]SY,xt>tƽ1BIqt6wt G_^M"Gi1Prϝ{gSBqƳ`x #o;[v;8nEnmrA1Vy<(aJ,,s/T/S:!c{xW }Nyp:d@ ܲ];mHAc)ɗ)h ҸUYV8@m1]$ WFhާ\ʋ.Ry"d\#ђ!.^GN^_'N3P1Ӆtú#jd+(ƂXEH:Sldi ;$UlaNr.㖥 gLi~&#'4UF栟0<ߑTz*Kq`'#regn]MM]#j5wH4En9f_P$%.,zlH1@ԇPj|byκ13tX+倊a},c޼^}Aa͙lAB9ӤIet9g8 amAObRQ+iì)AaAU hKӏduCKuNyM% $eߦ<)pŘ5];g`1]KJn71FDU$=6\?nbê.c; w/31p z+{v8ڔy g M^9v;t)s=d`%r@%ƦXAɻ1wW1 Ƞt#u^4,hlrRYG`>1Ց/r%Z!ATG7锓Uȓ$[E| G}5u٠FMqkVlklݭ'9zegQSPN@'a$TǑ{HDj ]S5م,'Y$Q.':rق:Do d=bPxY{d]OP#{oX0q$R Ҷ+&!׮D29fk-{doR2*Ic|\s53Cm+;"S om #B̆1G)=Tr2+Foŋ.2 Ŕsq ,su sfj8%&0!r0e5]]J1;<~2G;5t.m( 3.0qJ'}+ƉԨG\K8(MYH1i7G[ \ԮKg Z_K\4?&<#)Eۢ e5ɇ7'b`\H4s.\~ÕtS8M$~(JwGVC~lW Zv-)MbG؅ϺqAuÐ|S[#0t\oq>ob8$CzYX8"Wtp ,.;FMv, %Pg }>Уєc6_ڠa{x6)Ь(lta5D##DT8A1ħdfs@^ٲ+1 1JPN;uI8WkRGAb2Ǜo2d g*0rP2u+#:Ⱥ܃(Q^C&RÖ:b4 =#*z.Ǻ]29:b>]8 eO pK7hG1cSI|\Vq̕,iOUPEN{F)Ӟ,K&Q:iJ=̓VGP(.-XbxȄ͗6S&>v-8,; m<6ք"|0^]IJ;JxӁ6u js4`1%8 |r7m G[ddxv0{X'RQeW;h wRQe8z<"VZSSD0(%ۑEûcE`$!O;SXYv׵J9ʘi&̄@UV܋5KxGG[}h+1u@>g2"$cB ᆚ *טe{xo: $ o"#=t7J%2(Mmd+TJ8ztJÄArcrrў(P ׶qr)ehDS!iQ{c6ƚM}e>QNKw@`$xvCM˜=c5K7mmP^/ +>UI@fnD"P C^p-!E1B&QzmF_ sץS]2le@(׮eLIz~y oxqf _h0jF $Fqf;yj:F(:.r5R 8 ~cN{ȡ3£4{45fDƖ.8+춰*a6L(\Qg &2ePIXǹ?}E zO1Yw>G7t< l dÕ _cXХԒ.z߱F0kރѺԿSSFݭ ڞa#@ʔO|$)3D|#/J$ӳ$K>kb1=s ¼I$5$Ý7ܷbl,Lv,[{Ėv":qjʰo PvƢF׵[$ast,gl<1hϓʹnLʜ|qHE,:o4b"j4cI)=6rsG#v_+#dҰEX"2B2u r˺:˷/#i ^x%psZbxK5xk+^K/p'2IJ7dM9a.cA\7/erي.FٮG8 q `1䡬mtJ&)v ڑſu߄C &̔u_gzN{/A("0,hE&& $}Lҡmsw&ZY{qsEDo/:N[/ i_L1O(Gǎtm<ф?]$%,yip*[-D>*tHL~Kˎ8-t0$&%z&KL^,DV<\1 )7iO3b[ :\Tʯ7~H2Bߚf5?` aV9as NbZ2u-ou{ MKz,#k]}Vt_jBa$7hJuF;3j"^xGڥ os\nuyZN)g1HVX\ޥl^`1w=,u3"'}bjщ]\C0_nҵDʪvx8gU`$VVh-I@bգyx-K/ɤx؆l倭N2Ŭ7ieT 1^7r<'OG*zC5!`8ldԺfEtHΏ|A)%(Pl=ޟ9羫e/W7Q7i,|hr[I~w98DK84OG4=CaM)kPۑ.J,nuaYˎumA]a~!{K0fvF&i;jN/ +r}qqzլ&U0H#wQoF'# GG4m9(F[`F2̷dj-j3ٺl0 |˗kdjVl̼i[jJgW,wwZ";w>gzg*l*%auǝMg9{,e]#&]5 GH@|R˙셒]+ /6hwדOCE U{{JI ǸoQ1Xܲ,qαX6^x%q,zxk p_`:Eg>C9C;-&5kٕ5p,\('nLyũnTO;Ud7?UV]?T%/}IE+gj7<=/g|6Y^,/'ymOAl݃}u-~L4w+h"qG4Y5h4 =8I f{ mgGy U3|6LfBDɳ8s_ , ,-1 K~fj6dz|HXiekkG(x,]e?fid`ч— Tȩn pJbM )fa7X+XB&6K@l 2+Y 3&sh|K5(OIp .(Ygl2  ~{6?u,$Iㄾ90ֲғ͇tRs`vQdfe>1ȃ , %)'9V-;L9^MWy6:Na"uLlgFl2+6R6bˍ^&A<: `jM٨TL"ӢrB\mYg /Q>8wAYq)}=$8NGΩ8>;*>l\N@L ŗji&AjI<W೫INA f#&46~OINȒ*1M1.gT5`4ӸI.,)"{r RUPxYֵl<*`_PĆ}0+|`&ep ̋jW~ x(YQ 8Oۨft(n;kぁ_i.Uzl._<ާg>3% PLxN@ L fӕ$NSY~I@m*8CլR(M\lJ~K{APcC#Tyxp{0~N3;4e0\gڒ;ً?=Ag9%0+@ Sd] R @Bڴ,< 3tEw>J ĥ;iQoc!$Rּ~Kb4!SH! I\Hjn9`ʅ34d2U*UKk\n?5_ X>ccBqѫZfa%M0)PhO;Ldx02aXN%b/eKT"Gz`hn݋`egr jdWQ[ܠ}-dy/H&,KӔ:L9&M@ ŤfnM(A)}c0<0C+GŸcE]HQ "D?#>DŽ97%4C=P53⏅ȟJlSpG쨪HaOnd;cυA!!:Pd9 =I&Ag6s %_p7Hs2EUNp pє!"}qn4Oؖpz/EoF߆-"2=*EiEǥ'/EDgnp6ͩe2"! 䰠^X*wXʝf.H/ ,{i$ $~ {!Q )߉~ s~NHHnb3O7ͤe'qk`o;iv XiZ.;R8pXOQJ.`jj\#;EZtEײ-`+]nvdUtG 1Bcxwhg~alʎ3@hsfԃ$VɆP#~Xq)(C%@,!>yY~ͽE8Q({5%W&OMY I~AϹro87H%QxૂY90LIp:|2C4|zɧAm&8p_sPc+jA(.4tS1wS ObthJ0 HU |G雊(s$10&6MEm#쭫u5Tߎt>:p1һ$M)fFDn$1Ć fh@4NSgǧcy&= %0 N7!nu4eøk@nLj`= ,u0BOm$@z %^/"̈&k/"(7L?gJ(,III8inX ˈ[-T,PpXmY;XX0+pA)fB?E03uay2|vB3$sH[ZYnK0raviK1'Mhꀦh_nt@L5E,z|_PxC{"p.3 m;aGGoG SL$\veW_D 9F:-q5rst ˮ傂%MUM-h$YIJ6='B΢L0 s;N+j4' ?vvϳcJyzGPlCLuwfC20XWk1DP0R3(T/@Ԝ0`8"P"qRguu5ݪEz "F)կ1L߄?&纭L]AyֹnBL¢.¤?ޔt\LS?W0 dhGI/Vu.Hh R(ja:54#JM"Uxfzdݻ᳿]axE%$uGy O-q$/e>ClTS %Pp/Ksg(3DY(*2CYb:dUΚ^IH=KD ,":o⚐ҜtCؐxZRO;JCu/᳇)FNX.VsA'j PYA Q T+2ЦEA]fԾEX0k\Q5lyxzzsrq |ZW-g]IyL} Cu;LR7K S V*`VtݜE e#z : !u~36X)cbu;kDą[ !WL[QknĪ=  ΐ ,c%4(˫`EeMbPK؂Š\L׬j킋I#KK˱, Eb(luBE08 #6oaJGʋ4&%`Lv'Tq3RJ:ħ]bDd^]gH@04I̞'xQ/):M}0W=ZOA颲?Sɵo\q \$o<҇h (xaX2ku+@+r@1;g7LtI愨㊧#d>wם W r6f/hGY2K%oqUeS$5S udiF+)I-s!-=e z9`wH.W-8W/L`7`WG!FMV[o}RzAe^G^\pKҢ.:"2Pd:\,\>!./E1tuma-T#%QVUT(jj\Ӽri<+COHOr(9}=2E[8|z]%-t :X];pn33]X\iEze,S8ST3S^oE %rTPPCtmaXGSźİ1 SX1`OɣC<`76ΣIuWrv~qQ>]N:O(4G`vO+6Tu˔'勉cy೯\0V1]]N=X4O%J3>Tt15 ;5I&7Q/*@K9CR}JJJ1z2EUGoHYi1#Sd+@kum{/lƫ&inBPRlw~L+Pep:45 .GJ{kC,,! s*2qk8(`a9hjbx?L|,vyHM_XJ1&f jf ,o. ӃJ]THqa򵱜eBQ~L$I,$\Vfȟg555«¹سz~ccy|׫G#Dk*2) 48"B9b()# Zx#If!VF%. Ww[c8a>LGhE64Ċl,$!)#Y,0 .|fgﮩ/8Cr0s' r.л@SLPL+XL Y改)s._%qĕqYlRA,#h zRuByͣomG< +sq!8cF*[D:]Wq$2 ot2$cڦk$Wx{錅 y9ui71(otϳ>dD>`y=,DNj̏zF&i@bxzS<$<[-i[l:u)ZK94fKM}n=~/ n^:cE sț !8,b.V#X q)zn/}F.(XiֿTbQTWwd`z<)7n`C%DY3prM|`dovϢi0PH 3f%Q[t(g7?>%z9ާkRXYq}ʻ|rGn&5LvZ-Y $i(IDm&uW<* q, kMf+`8g9UfxC8O<#1ر^t\Fi\~-Y'.K|^:ȌLJThm@ J2Gws A߱ZUX6:oCmv$HdW}/B2:7 BlF+ x̔IHL3+Py5@̒#&860qRF[iJVS$m -qwL 6>l'ap%iN+Iޅ|%/7%E>-tYf&Gveݙ]fNǓ2)Ω[|ոs'mP0m #c%4Qspڤsŝ;ȋUBCH 0:yNVi"8VǴ(-]l|4%epcr1 ?NWυh_٠} E@˔Sutn'颿vhPDڷBT9 IF1/M"ayCXfJ tYö4 $h/iɀP>?4^HԠUAiKܤC? X OvdcKv5:%#](\gQXvz$ z#Ye;&,h)edOWqUΝleR$u1iQpՆ(a18;?j6z^ ۔.!˘.Pz`iVZM=^ZjV*,ߍ/wp̮6{cE[;rɠE^$?0D K~aDKn7[[sue#mih;dDDy)7szl=]W/1_ v||&O6-MUەcAk=ɭw9 2d>:l4Aj5,g5|4]OazB4$[հx H[;A5{@+/_W8LkqVg85s9oo y"л$_TW*B{&lvEQ["V[JS?۠AHiB1W2ӂ;Ujϭ c0*.O agOpA*XS1S~ͤlʙdAo4:+\\~negUkL11s>b<쒳R[^3cmunq*EوC$P[ #[T2;ؖK%*̅a*u"M~W;5 ul>?i8>òM0V~+Y+n>OI>yy"^I;xB2 ,;<*1Y IѶw)HCrWJۼ}h$g:mH:'rRO :G6mx9E'-مdJU?Sb*:@jM))p#эt.PM31AFӅ;a㎼އga51_1c*|As)o_kAm V3u[?Ѽ"^Otc}YtT^  RS1GΔ)ٶ̢w82eslge ,ψK7 ,w(1q^_:*>4GbZ+ RECx47k pG+zSMC Ǯ@CٓD+Ztx^jqY/R+ayEݥ>9IF.w:Jܳ8:^/YID޴E`ypZ0>2{E6"2oI8rA/#|,0 LC*RM>'N\[Mu.SbI.pA-ҩ~X_Xcr乃d qYt#\JGaXQ6\X@6uƸ R{#i=󬬵׏r)omS kb YkbwnW%ViDlmiZFvv)&]cv͓$yE`Ly)0}Ի"[d/,}c^P(0ىw;.&zuZvE ')L%ѯ;,oEL 85Й4[0j#BoaQnw 咺@4ɹ`EEo!!yo3JPp`/u1`)aC .i١X$\eթK8}Qt̃ujwʰEߨP+4f=,AbE WRJGsS`Ãu4" bPű/2Ո#bvMVNF CLq,ҟ{[wێmY@;6V/6TZl=YlVjZUr,0J[W+&]ε:q'VLO=L).]EtFI&a3&=7]X䁉?]h-1>æCyQ/M b&v߾SvC 'h,"8b9yRb!@>: XzC+ TѨ+v=Cp^, DcGK69ݣ350e "a̻N8?`>SSLL$m8X4%*i4U[H`8;.^]\l+JGҌK6]DrzfFośç5h^1"%Ztl*ezbegc#Z䣽q_\R[)eBUk~/ID=Ѕ"2M:G^ ,n]z~4xxjؕ˒4;/$+b0ւ/F*g9-0MQX4/ lJ'?` 3Tſ{e[ڷ>ķ:/eLɑᓳp:@J$Nk6pLN8$8zz[Xp']) \&yBMvZ=Ļ\RNowf.//5%2Z5*%;?v5^71lJC|!kH]i3 raSbspyri" 6 dEz9ި+sPY\f=aޒ5Ts̞4`%1n>\#yi޺]4J9C6oR .QlmS8A(8qt>1+˲BqݮR̲,`$vM+QҶz IU$ac׹p~J_]TS|kmh(bx 1Uz\GZuX\0X6s>|jF.2|^b\wtTXmḍ#Pi' 4觱`>*83C.#k"yi'NdR n]7vq˕,!@$ʕnы,^m s+)UT ߿!^g=iwݴ>,l([?H4e("feKB"͖\Y 53A BGTE{qk߆@b*Þ3wXXbr-āZTCrR7^y(ǭ]F(?(+vzv,Yvò)N]c$$tɯ4b.+ղL,s.F) ʺ #s#eBgL,h'i׻7킂ì'#w5->2)i\`ځe I-5Bn|_ry˦CF±:8 qGh`X_,M57 $KM,ǎd)`gI:-1~S>p+Bה 1n:ĎdJ ,-P .eJ .ϧIȣc 2ELi m꾢O;? 1mTNYNpQ rA?A?o,-I1S'i XȲ$^mrWW%R; yn n>G\<npib0hۼ'kyr.xҳƒFo^(\N1i]wۙiS;7]L'[!Pγx Yګ-(41s-I{r8hm2iKCdYub}ܾE'K\EF.SNs6T7uYdnCŽ^E'Kݴde[AfԾMb):s,zT(JmĀc,3Hݺ2- ^ bBSY=Vw)X=)-xZ՜dO208+dI72{M2S93Pjj*>Ot$|-<5c.5ZLi"+څSfQƻdd@XM\WM WjjCx܀2lP&]Eg;% JLy3²MoIih?$$LÎpCg{.wNyvI[lX%o5wؼ5Ţ#*r*t/M貝؇=%EQ?R5oACţe**&!.sK}2B! h8 !tR Ҹ=r$qKoڗN@M/ȱH>Jhr\,7& W-UR,q㞜/j:efz75KIt`-<6 s|/;딬dr<<ϐ|I$^q+ucZ&MjzߎN:R"Uo浚4mA$dI3QxP4S2dv{C9fպ=?Ծ,@KtV rJkɔ1!d2?/GPŚlؼ90Dބ+ݯ91̍AT1wˑR`PDIV5鏐TĐ Q \NFr _Wc?PS*cn2Q3e>} e^MQ(dZ[S~asc|~ikm0iѳV{kLL*XT#ؽ%aD#&*YKGܺ<pX*!.@1DS]X"L~9 ZWpDgn`,Va"q/,SDD7)Pr` }+sp-*'$ϮKzgzU;ϐ7+Ean`Ľi{EMPfj$vM$#lWlA5pw[7dt:LxCľiZJ)#xMfV Řun̡F, WP1r=gORT(ƽ&eHa |xa,f!.%ieE]*ssWa w,{v;.duD˟Jv9(1}ŋT풙2QfVF4dKj,>@b7ْlj4tE5X |ۮb\볧]-KdEzi`(X.-{!z])qR NX`N֦ʛѼqy583.鴒TGMXAL')/;U(ƈV4Z%#2n c HYP)"HꀤkgeZ·T$hAdmDE5bO>yW+ f~B o8~Ԍ.Oq`>vAzT.E9$ʊ5SC\V4,K1H5]^qMq.%bO yJVJ!7KiL($HL;0]LSd61X\af[1:&2s(J}GDSu'mF0xq[(su(oͻ!ɒXl0gG=i`ڜ.͆#}tݽORH)sV.7KUN00'6ZTΒ`Rj 8Xq7Ts;V ( {$Y2T X%ST."Mz>OYh(uq: Y{0CKEr 4P,VѢТvÎYWf1Nq 6h\7Filң(:gGCǩǪQ.ʯ1 J1G9!5pxZ s܎Hy-ޒҕlZTu DK2{z/bPV3͝ap5dVKufi Ё$2ZlT1.bm,Nn_va!/hdd:\m5e:kK:lZ*hOX6wMf ^OΘM3e%0DDRśzw 2CKFԍIAagX^c#5%T' WEXO&Y jyǂ0bꞅZ8FK贖N$D-i( 'v9c;rC?!&sy6 s5Ҧ3=W>ӷ9Y.(X!?Z|M{}ޘ:q$&C0 :F#IY$㳤86 R yπ…@_C$^B/6v6>,\x/s8ϾT12 Cs١pC!vВ@Kf-,.1YMEYMY4clܘu͚L$^3V- n9|4)8|!+pKU[m+,ݏ7Ib/hO$5p ^!+ 4h<,81W#tW8B8ܝ5UI ,HhGB8dA[7+ g8lu, X/; y]mB%榭dO{e.gqB5zm!ˬ`#3wX{{Vl٥d)!}aN/s?J$1E f]6~צaw$3#DJ0 MjQw)X&5 @nS8u hBe2BnZGV&sio.)wk".¹1pxU6B.l˰Ke"lZPT$|Њa+L %QXd+XJR/ -OAQA󹒩pGBCD} wU#W޷V'UM+K:"ITBԈg:00sd9+ ƈGETp9# 8a ʄAAaw8r2} _kyx~}oҺ*o"t޴nOC>nXrSRui& Cxoz bK` Uzt0dAF;tCsTL0b/t0g)h2Oi; 4IC*yZd Oo ȍB MyñJe ONӟ&m9%o KXXR,Oа\/0tge:L2{R"kY2E,7뜋X\F^7IaYe桋/9'{|>~ftv 2vHo@p$qǥ&{;tS쳟^P^n<9uƤIG^ïYEéryD1Niݧk9$"^Cqy!# |d]3U:FoOdž<|!MFt4}Q7ON48jm2(=]uf.!pNtνQ]KpHa^yyVs.:)~!x8@F]bBDnږAR 4\@ `\G#vtT/ZYL Rsź+HbC,ӆ;qA}P>Mrp/$(0ZBA:!-&p.8o)N|:ay@gA|p+)茲Ǩ|@XTGϥ40tQ˜XRL"'@a`nq[~Z+6\D}T[,(-KEie"_IiF%L6G=?qkňP2CxJpQw ^C*/ErḼ q43:̖)Td@/ESvJmO;}R@g۶U`yO#̳R&D>,6vC!j@ݎ}ι3dHLjsw? ;&RvrfIz2Vvꈃң߃M|!pD43,QfR Q{:jSEgh'zG /.eKyH|N_ Ci)tmFZԀS8W8('M{f|BɁ57Np^Goe[ɷɵ7;>&4q;hvt=XӨb Z S˱HQIlno4폆>,y/m.n" qt0P0zyUnV@тqfr'XR`J pT8taIÓ2Y!tϾcty)2 to#fŚ.:9R-3P. 5D Q̀ i C",)) HvV4AyyՋjA׋z~an}i$f5ފ=5gi_ԦZDJZ nF~fp/$)`E vt}PC=fI粬./q(/UnыH5Ϟ<Oq\Q;2GObYRDž@,c0kO%.?ֈf]5X_ ,k#_Lad"'CxvzP=V&ѯhrZ?}B.iнeIjBiFe'|@E"om҃Cr=*G:#(A:`vor-U[(~((DGuKCJ0)Zj1f183u7l$&Uր*WQ  (^ovBσe,C"w0ڠl;Z~X,qwKSa`[,3XЕwtw`l-/sp˟TK:^5ݭW0Zú+Ay͊Z^0p[~5|#=mm--)k)/㕟pT* A^,9Z، 3bhw"`i|l0MXsVs|f]F='F#&y%J|'CҲq Rl6.,djb)V|东*.vaɄidz7.hIXhȼ%?-rls;y6 5ƒ]P])tA^뺇01HI37d4(JD`T1Y@A`؇kY-Epa\X@:! "+5ɲuBjآCHKVbQ'O4KL U.w;$ t-puW\b>O")#w8M7f7e ]+wa9r.WZe7mv5q]XbIXm8ǘ[zym $=ZVk%|QBy#1n_{}XxCGb#d%bՎoSl8iKwϴYi187`IcѺùWp"gilgemPH.^㸌%0p AVkR#j-Z$zB 43tS5JʗC1ge W4$n^[GSLӹ%%M ' 1kojj5w.}ZO ./(5%WbFcLQR|E]~(R wtFp-ٵh2n9w&pZYy=r6/S'vAO :Z&uѿX嵎Zr'>BMd.+MR>r@ R]9hܙN:.2[RkNA&d(FFKt!]z}M.5ET ;V^)bI Xd?OpJ5ȂA1pBOIBu)>>U?tғAUHU\\PNt B>(и^(KHuUr[bW೛dĐ4co XPe.I#.Q9ſS?İtOۄR̐VMcJwioDs;VQ0n`Xj[Cpİ;sK#b+|9^^v\C(P Hh>p]thwi,~k1i%E~őy* `2!-})2hߣ]XYeԛt};u=R>r&Iܲsް[Pʴ/Q,(6Rv: gYEsA>E' "ŅF# [05fӈl¤ RMdӅ'3pyly2̘N0y%K7q(=#k-H9"(ԘTuIۅt'3~U t^oqؕ_>+ud߼P67L8CP|z8%I,Ҫ +" Wk^Y:a_ :nh*VıTz茀?򄧣mĽ`1;dCTdFШzA5}Mr^1#1DuBsyF8"%ǽ DGm,~Ebyr) ˕>-k`gKapB it0\d #tѯ;xU!x\'[L-GF0=o VG:X 0GC2h&YϮ\cy'dxOVELWyrn1)9ɨ% HuWVbJt. $x>]ty\)s->h!L xD,u:KXv`i;-8/3Dx%]cc~V -x\ GpJF isS2Ÿ'ys<vERX7,ŬjѼ!,)G%EV%W0p:T !6/28IG\oj Vbb;/X ݨ O\Sr >C^ "Zx$tAU32_}Dy%.u q׏z$gM!qDNPY;w*~b/Xv8|BǮReN> +}T20R-+dEH | s[dXvYx7  l* _2t.D-$YU+6`w G]^aӖe!ǵڍEԾX\ªm,qFMsDqÔZ_!!`3P83 \P&f*@GLLhqL-zA+j2_~HR쌪Y?7h~PD ' aen[{S2* aL; l(d`Z>yC$Y#!!tXQQ%"dmνGwY!Ǻa ²5Co{e%*LaGR3޵)ށl "xHO}=+Bz3E6ÕpeD#\=NOA<1VnѢD@p 3ኺt$ ÷ F[( #Kjk!Z, Œ6`!>!b0²H\m6AsџoY"ISzUTuˡxB~&$N(nK~PnЏ.Fފfo6:c[Q" #@l2f|CϡpZB݈|=ʸ/FB)٦0r4?8G,fd\^g?D E ‰pK(l sahJrVcSnE!)XՀBhA#S֮YQ ~@2FUY]>dބ|&Qac_}^b:"/|DZsVZ=ŴZVZ(-`U.:'ـccpY$ɹzj8ViAߊ63anAqNR.AR/D ,nLY%æONi Ǡ"uoHj+(3+8dڛ=S!W89ϓ!x:&;#(Ӛr4T?q]O'?U<δ*/N ƖiD2[#YBLl) 7 %M%ˢ;{(q[Ot|I= 1]wu =乗"2'a y ʅCvՈnp4Lw#K~#r Qdc 4q8/g 0 R9yI6 g!. $'NN7YF {V>S*ɢȽ#RÆXߕiX&(Q#;}"s:6&\(/k0vW!OdermӶ#Lk bu.@aABZ{6+ qVZꘔ`c ]dQf\kb>0~\i$=JUhr i$&QKE2-BI.ODUE`8VtX~pDzՊb%_A~euK~FG,\DfЉT+{<9}?te.$X&˳, <^wрX8ݻΫ?ުHM\na_Fv=Y >BKc_'!,QHth21u_PKe~\t0x3GTWiG^12]~1`wJ\?ퟓ<؟L'"a׀uG:6*%$IV䍆+P^joupHR,ed^.=㴪r.=^h,%˵:]&UEZocI4IXݓ~w;I ](-2粫4`G:jsQ #ZY7+{uU5$# V1 RSnBUu(u ̵2%m[E>/#GbȧffՑʎF fR.Fɧ|%/V;8Xr<;k(=d~,Uʔ_ݢKћd#p&MN.Tt4cAW0}UhHqO\#Iu:kͨrkxc RB57JHL aFTBX!8^*!Y KK '5de}Y ] ^Xy<*^9QpBXl3Ҙ6╸4R G\-њ,O3~aDݫ=,@!lL')?; ?݃:v"E5me؋%t|@#q9MRey;?(݀ (Vk>s- їj:\nY*]1N)8ltVg ++%)7"O<ܭ@1SV$0&8D0 YXR\ʒɾιWVE-0Qd $;"||Tњxr3e%Sk IGRz#2|lje1U y :#fA@A?vxWdHUԪG>`/.*che=[^L]JpǪ4^ W4!䴏xn>FZi-d炂G\Wio(44,GYBDh1b4Cm_9a"fu, pXU{y|uNSE|6-} tSpJ7Hp9[| zmpZ{qYXLug>~Y#.aQO,)Iwz}lxПbxȉP?6i07ᛇu(CbeI`nOMr.s90n]_V@btXF#[cEL؅KTviV^[.X܊vΔo0oSvn@C:`P@X,EFH[ytcU-J#0idːYP4Y[o19{@0iz(}Hkg_ZfI8f0 d:N,7j"iY@6j8:L@zc9mCdyqݯec$0 !(iReR8>OyPT,oT|2UƾvG@AEm3]V8-ny+]TM7:X \Q=!ަO'8kPK; bG}԰3IsOKY{J[qCwEHƎ "j42r9L,Ҳ쀂;:{-Zu=4(7pn5PpߍJjZHhy ^f+ jXEZRb"-'be JX[ - [!3VD1{bDyĽ9zDe|2n#Y<%cc5YQX@ek KÇeM< W`/n `ASCH3JbX߰`k=_8Go&q!Aϒ=wY7}$jey|eɻZ`'neaSp2ǀOSMka ,l\گvE nI5[y&sT\4Yϯ*[[FVo p䎪2ݒĀPvz>&Ifۘ -bn ,Z?,gՐǬ*̄{FLȭgV-u>ҭ&?$іi6cNsf.v K=["",KH,Ҹ1պ j(ʢ@z٬m|msXȽ%mA,t5dȂ& [8T% p9/JI^Lbn{o:[uNx˖#AɾBIe}tY; &cc(D9/R`.|+۹2!41ƾ cIh8ދ8J1/v߫ iOw vkVkW.V%yPgP>}AX&ƝeNPr4( g ʽݭbaGu} tc#2 em]ZL.ᰄ`Ɛ\S4XC0]VneСY6ǀ 4e]nC6)qUl׵>g̰+7ɥT9 ݛ!<*J*YoRx(偽,š8d=V rtHx;$wH k6-#1,A+Ѩee0vْN#,XdY9I-g>+@$.Γ'm"crP⭖aҸ3Dz:mpm/Y44^Bu35- ؅q.j6`$ϲT|F+@L2Y<+-=Wurůc&|vfܕj|cZ W\߬eo#45GaBK8ZJP-v uQN9">#T =f*oBZ{c[ڧX]GCG i2WqadcLRN,ӂr_'Q,(sJ:QxJFlҝrXz9 .Nڒ?ٖ;GjjH`v7BM]C]vikP8ObۘsIwޮC߾*ڎN<L0M[)i.V E)& o0=Vk5䚦;1&qT*Jorf,hZ?ѩyQX%*\]SF)wc͎@mֿH'9̆ M y,q]+]*藕0 РIXϖkiR5F_.4:3P Y~mUALŔ`(egē~kص]6Jй`sl4nQpy(﬊x@&:{I fϸ䒌;.7aKvPe0;Fmo v۸o4Oȡ橑i>A\r0%*dMS|,C {i $ASŊxY->>P  }N*ax; Mf'Ŕebz,0\^RN1-TYO*(zzֱ89>sg]Py*g+,X(k'Z3!O[jR޳ncQ!wsA|Uf|<ZovDX7oA"c`/o$Ϛ ]U$1<:♍ 3([=qF*ƷIswړdqtSQ\Ǽ|8HeTPL6ve<$sEYWTЈB^Ĥ>*Fr錊ؚYv"YJv"K(= 3*f_Q:K~Ti=D zdzw'Lщ! h"i;84,o$]p]O$|@|#etQ4R鉆 K^*)4-|\)p7ecqrJSk.8rŹp8=2*F/Dm]\q!➠+U;T yIDirۋrY@2 1NtoHx@AWnoO 1PCllc?<FA=Hk`$f+U͹ļqeh2ia⌱Zλ-*ޝ3.0OaRy0IiźR-n #."V GXpPjr[m:p2{9fBZPbNZCv8U=𡪶U (tŰ5yW;/+֭sȨA#ܧ쵎yX(}{2t1YudqR"k%L5$L.н ~ lǕev Kzn7̜l:5qX_3:,:!Oj6?sXYghMmR)Pmb{,f#UmV{ .'0@t/u]yTDyƭٔibYe-,"b9_}7g7:i0sF5bi2 Nd%RI;0 X_ŻӅ北jc1˂cW!ӏ(NZsfP6 V.6ȯ79+z9ˤ 1MN [异&$Bι yŲ8Qp! n c~8Lֵπ+9QG%zFJ$ICt݊E툌k8+5[+~JӸ@pggpήeOZ;"+'G9dm\vCֵ$u*77h6J'Y+#-\7PN%~C=Lu43?l)$9ei;4SL(G۹[2ham>& c"fcP^XNDžr4{c;^]98o(ؠM1 $ 8ՇcEd #I뉢|ݤ)Q$E2+STi6rؐZ˕$3Ɖr(k&k#W+s{a#dwQ=w#K+:{"ّHaZVr,_1c&|A\-yg|ӂ71*dց>m0:krO8?:8l$dV:`2;$m3xMyr((8JbӲ[6Y~,WP36@ UWct| /HGPf=gOIDIlyO{|I.seW!w钷4nHj$Bb^:j봋]ٙhf=4;XdjBt  +;.^1Y7:k,ΏlՌv~-?P$:(I t"ݓC;S;HWf^35ʠlPdaAnKQysDj;[T (ViAA*nVcpn@' Bq5dqA$Yd6Te~*4MfRuNVgwn$O66@WjZ?l67s m7L;(R9D\| qSAI@Gǜs;*;N%}ʴ+uI <̃b I$ I^`T^gK[N(=A`<BCOoDƧ&Mu۱=Y)åt+T$XSn([\ y@HpkSq)ϳˉpB(&•/rYvcGy޻D =BJNn%g:5ȳ7@DGJ%ݰV Ua_u 7crT-n1‘cfqY=bخy|#NTV-#3%U QR x4&6NTUzݿYힱlWTzV:'r|SvS6O{ *#<j,*[XʤwdxgYHU,ciʣ"Ea 3^ysrp󞺐}/awUV9֞ʋGϙq"V_=V,vv :yC5ij9ֲʉk72 bv<.ۉ1Jm(M9]e_#P.#ndאַ!F,p yMd|7N3llKёl?g^2qItyJ8Nj5cX?dBF yChuKL1xs=?wmAhuA8>P7n{\e)gƲsc M! pB<9SUIH.D>L B"[t{+`̠ROmeDGQ>ݶu HzQp:p2Jim<9zgֲ {H~Rײ?LY 0_j\LE#0*BR)D{)LnGXm ⟅Zz9r1 W1W-ZSpQhHD^Vg }ç cŻⵆߩ/r4$ks8zfr1JFIb:3^EMtPUKr1l7"Y5!EcL2O~16#,b48PR0SisA ފ^K5Vgw>rR%au Vπ2 Q0rwWz 'f +[rDQltw@dL_Dr .^dgݳ ῀jf'n q'B7;%z x=ĴibL>!xz,/QG@pzQ1vD(-^kOФv.dyj]WR6m^9aj7uHsj2Jls5Rzt[=)LJwJWd2 i%HAشQv%D`DU2#R,-z6oHIj T=-O;}[VS&mk?~ӽ+w_^_uߜP0}Fێ| utB:$4$/M$t㎍; Ln/7Q{rFy&!K-᫛R=гT3˺3w00S _,ڡhInQm`m5x10PvԠ9hq%w{6W7QN2G.!_糟5)je'0=`j!}0/{){7"9?ϕ6rJ#CJ yL;gPРj!5N1Lnⷷv9J 41!bOx$}DWX-Sp"QJA)iϹ)b:~>?s M@n Ixҋܪx. ־J^L%T mC8n|Xd0'+rr%|rbZXx>iJ=ԓa|Sfv sޜ*fs⤮ :,J7 iy$%DGk*U"o] XE6嵠~dM6$mRayܭvOLPƶpܒtգ.ɒQ/)9QzGˠ299nLE/@H`P_4~PuciUL.* HR6ͧh,6<>M OiOsΙ-šC. CFPEvGLi4SeckmkO}N64 cZR=PD]f@QR̞H MCJ/x^.b24cI,0y646̧|\d-FQ& ^~v-׌r2%i:|V<Rm]~.SVg">ccl՟v>=*+= whl$<#΢LyEh ^I`xϮWKSeDHX8]/8PnB!1 ch4c0Gcl17±:Amy!9$:)M/OidG(ctSsP\~zRV9RH'hf}Bܠ~I=AIC$%reu\1zڂBG 隗X;"hXU.;shdQЛ&z54G2WFC&OR]h@JU^$&N;@Vn=_~^ċ+3#/]rG9;7yt 0aKi cݰ}x뗫CK[\(5wk@N{z _ r&nhryuEغH>B4D Vy0ܟ`r_涊c gՍo|+Ot;O{Few&FDP\K@?x\v]<OGLRZ*1re:NDі=0C*U;2^-Z#m3,Ey(m۵l3 "oԦxlXe=27(mI r(xʅ̷tmibE/ed `#ab-srb:bYc|`ܡyEiQ wp6TXeQL8Wټ y'f07JBm暯.@փNՓנoMhI9xpB0~.7sAC :ҶsTgxhýO}\qy܆Cw}''4)aNg^%ri|IJrʍ"`\]ʕe\x(6 %WjAhDԲլSP%00H:a3D\odkP6 ;w wul_/ -̝4`aG[̛/=H$=@T5|*mXz:X'tn]u;Zp6 2޺&Af"&Dۜ`YIX؄b$^YmTX[6i g6io6ke~: UuFƘF}pZ=Q:&NQ-J;p> \\wNF p09u s&Zg>劬|R}urX;S-y[%MuuO )/uIS=HTfR9_-z0 SV 4%(dy>8W6`Ngz_8 |d#hE~"Gڐc]y ]yvޙ<7 Os$/Aw"O[?02"{&=M!uP)RyC9NbIrOuߕgNr|m(P}ZU6ҢS;RNzuyXܧЊ9PƖgw%5wKyHOI0&eD=B 7yѽ@{B?S|Kܫ'=Cm~ur R^NmcxlBSǃA6C}ͬT'pwp͗YT;0)K,כֿpu[͉ӫ$ɧ󋿤so6IzlCl&1cRs2y[rUVrZTZBi?ֺv|tT.*J:DA>ժ~iSG!{ t'Rݾ-ۂ'*woxt RX&QnI뮢]{"ON}Hk6mTVnh4HyA1VMf-nզlenyY.~/}3u:CTvڅD9LA$3zIuPߐ3I?Ps^+qNm-]8 c υ& 'y yHضᬖ$.6AB#ҡLyj2ܖA¤}vEm܅s/[i{{LSiʑr'J'fﴁsej@0?SN iL9Ҳr'#Sf4!q4id^7,>QZ`YH=L) t$IwpJ.&ߞ勅S;>|U~FD &|m/k架/owɹrLthKiGZ5W_xI#qOx )ˍԕsw:N&ǔxAA;TɌTfBiʜ>l%t6R:}V5m^&KɍZhꎎ\\STxE~uدXA1Xv!7y0%O:\;,ba0]>X?Ϳ Z KN^6npW ;xϖ#בa𚏱8`$&/닮+ݟr 0|3%e9UkcpV6=3.Eu[j v_ӯ9jnw5+@݃߹KV:Gx}l^l޳ H$CU$rsdš`ˎn,Ai!l};%\<1ˏ8W.g]وi~yhJ7GImKHD.6`:z91.! )95'GmuN>hEAO="# 8p# JoU /~b_zyb+2 6+9F@1*|d&*9Ƭ[{1f`#jY):azBxv#\ƯZ} x`ˉJw"?ᛍZ h&gooԣ])X\ |EǓyϮe <"-Hf9Lɭ`(\iza@I,Z'Lӕaw}iO@m89,|'pF7.= @( vŜ~0:v.:-yL&8j7^kjE,qYfXfwaSzo痗g%Gn g%`=<ͨx Cd!4P9v.e8Fp( އ]d#D3?`E-ObS%5-P5ZMZoKfA;m@E!C]@3L_ǃ17d~se.NjYgܥAɿɹo.<.CjGxYa̻Kf$'h`vuuTh \F.BsTVy\=Vȿ'۽l5#~u ow*עN~=CclJqxc8;zRI`A'ףГu(%f;C0"Jzz6!R)9dF w4.]RG@>si1wl[Lj4GU y |B\o0e\,~RFeKŧV5EVߗ ughA7=.Zzm0}N^T.f!R;:$FK@RoFki\0⽲L|h= ӻέG1<<gjecք8Z:-$AOG ~W:/ϟ#QY )x~֟l9:1(O_|p~6?8OSpiޅ;$b~}G@N_B4HxG4)L^q&~~P~(%rWVF[zKcPOd۶u3&BOq=>U*DXJEB3瞏 ImRrڷyWN|XSJ=huK|swP-इi̕,^9I#]!UAkc k9);.ӲR7x"<2dݵJ)*&ֶ8~92FJix )}SeM3VHWG*#Ca{C~`8Ҩ;[((9ii.idڵe wLo?MɺR6c(@#]9D~T3(sr];o/}MSzvͭSъmʒ@'_!ZeƉ%d}t 3{?R}ч,|tnD^P<\f \$CڅzysyԬ. ݧ1d|4Am$lTI"Eݒ~4+wD:vFhEߍ3r,4@V[/IW_%Ծkp%#Bl*,z63֣I{hΊ.??Ǽž"{ 'T.cV|D3ۭf+\&qhHxp.i$"/yeNt Mk.3|M{I;.Miԩ 3rqJV|϶XKײaAl-iY,.츭MOEd@p 6 E^2=s&uж} |f-􎡤*JR#OMR|M"oY` 69̾1w.KV.EsRAF%7`Z(8*ݥӹ`yw6F ;#^rV?sUOyo9Gyʇɭ(?(m_=H'*BH b\"q4>ݻ4SDGn5qJ5(O'Kqs!ՌֈEٻQ Y2QT.({يBIOs{9yN0ּ!3V—ΊrjQfD˽WTlSX~_b)></ ѩT2|v[fF}Jm&U{vN/.jTº*̢*5NZ6мe3ZD)aコS;'eE0(|hgmeMf-IlHjDv3V{涝0^6 Vb3er2Exͻ;{VNqs|dM+[r"uE5Oې /tCOt:^1-mB¸ް*p2^5{4)kM5Q` _&Өby=W;:WO"wgI~[ڀY+gbe%gB<OZ>un90kZgM)BL휗*+bf TS^m8fwoLV|֝M|+Y 0{CT%*1ۤ7:<yx Ȗ&VׯxC+u&/̌oR Tӆ4B0I$~󛿬ջNӚZ'R{h+=鞩-ɧLmY?M>ΘO%FU"yrӔד,pPF>Z~ Oi |_TgqMh6ā"t^p 4Ji3نa~ԯEhx09IRTJ.G Ui*xOUy2Ch1u\YbhmN~/Hil;m:LƊD{$Cwz>>V:91ьEr7YIyۏr'ʈcrSp/MY%#jv @O5m1_NXi{GN~ ;lFAUN'](cV[Q,ǔ";߷Hb_.z:2pcυ8TI&iV "KM኿OęF7ѩTV񷾕~|D Tg0T~<p oB~Ъ >48+`gtLQG5)zh#hd|>b{۔s]OpHv-(|CMqJ-k`eyuh(icyuzI?QΗ x~"u^.rŦqg@ihltBRG >r(DEVq;z72q7jXpW@/Az4v}댜L9#[RXш]R|Fd2[<)T1pCs4ZXg$}{% wsȖ wJqࡺH='[.éG[\N$6iESƙM~쎤*SH- 5$kO0\d ʒ_.g5|4CEzSC^ ω:dw%Uc[4dys_XB7 ]_&N( 1D"@~5 oPcxz^SΧW)[R*azKMK#a>Ͷ:`%!ȃ/"rlSDq[|Kp : P%m%ɦm׹/εm􅐹h["N+rK%{G!xsqb|1ݓGyF,v9DRD W^ͣp0%FY4i-UgԍZIF ]^d\a0b |?@W -;DD˯~専-md; 6,8tu:9a-U[H&Iv;sb' 2`wҹJUT0]me$`hBTEE˯ |Dsy@)% 6*rT-5;ag q@cI_C8M*O{&Q C2%0 e4vxv_4 e VC&bT\@tQy%e\<)L"w*t928s9ZJ^B OkY[[t zlgF jC*!$}Rn)F?uY4A-:DϕZM"ίT[6FQr.{D PrK"o1M3j#)ڞM0pIO\8#Uff{1zM^ː&^7*ܦ"Tl9g\˓Fb.0cux\DF>B\ʘYuAoXm ^dc^~HBlh꠲6X#`{?;{˴pN,*i]X' rf`!$0trHaҀ Gpͻ(:]~:NA;?,V%rn0vƯI,c6<7}JK:]6]Ь~% ?mj&bAcv3E 5Nkm-X"Ӓzh}{ߤ2 ?R}#m_[o‘L@ACk(cnPǐ}oz3IO8ΡjtCxcB+֌؄W,hroQHfF[g"07%|GH8zev JCcL9sMW9_WSjQNX ^ ;ʫ=1H@.g?%V/r#k&)jX3GD|& stsC69sCqzb9svyD%˲]njʉvW552q6y}g贯=VQtjIBzhhM@_܎;%'cC [+`svMmSm◷sv|o]F|P cʇwH3z1|t"SW!c6%69uH3v\^ZY3kFy~SqFs:ɒOK%|)n{Sy!QXΏE-@ܬͼC vtHDNKB *,\mK>4ȂNC" E:NDPӏ6V&`uz^%V%+ţJ#\G&YKܷTbqR "FO@ZZZ#ZJ=C"Su+GmD0i;~9#<_'HЎa w"ѥFioL?hcQ(/7Zke+:Ac )/.weg0W9Ve$d2|1ieO.hPl l-Cg/Amm(# L`Z(Y*К14Ĥl:sbKdpy7p91uSP*=ߗY0(I-. oh`yUAQYXNFlwp?MIjZ{nJdIŻ7_RE,mL1) '=!YJnpfp:NG XՋ!sXGجiQJ^&|!J =[(Mp8 $L剎R|sGaFrtV&DzP©nEohF'v^XS^ %=CpdY1*RmYxL2e$%/u|7&yU*t@O29M% YP{ƥjOPVqm!<|]]!} _Թ/UҤ\~3ޮ<'?= e 8=x9Tqr_UN- vq4K\Kϐu،'[~wH: 5y]?zyIŽ * .uh-VuEI=\PBAH2e(D(V oC} S(r+Y i!:<[7H_*Ra&^#`e.96?zYۨV UcfG:{CmA)er}` yFsԅ%yBgf&A|V跛݊Ӧ^/7qoKIIзC$N֣"HDu!<6"Pk߲i،٬k%>o`prNFECM-We1-G v`CіC+YJOfŃzPUbd"Ix2N!d ' @HzlCpWѣGz٦{Q䷽OMYq~/4 }@4ɁPfM8]M':H"D9Hgşݘoox}v&}L ֟0wY]n_4?e۩lU@л͒qruG6m`[]gO ,Os}1TbLGFs@m)'_ʽv󓠍I( '8Z{iI̜ۖ f?-=[C_AuR#Jw~mJR5[{ *A8{"p y<尓"m/3)#긺)> 3T:#1;yd0K% =KƙyMs~wAn]dWY!tKl'ni8]J[@$zﺦ#iPq&`ҳHlATh9>Ӛ wpRi:*^OJ4k/˪ `_nv)MlE<7ύJOTXa,> #ٛh;A-M%5(v栂Kb,һ,S{ڏg|Oӭ@ gT_>LP*bM7Mi(8@b@W~i5K ZoGa;˔dj{X'7LZE3AYb_KygoPt)UC+4EQ5(s̤LULm?*Q!6M΢C_luEg1|B6RQ: 7b4[DKdc{YPttHu[Fc qA-+f+t[9P&]GZ= PhMT "7j,ޭbw [F6 Uԍ]?w%Iwn9N[(s);vx_'z $I>;ê GQg fj٤gbv' RI|9UiY mqiIHsc{fqf5#Pm[Y2^mUmr~1XڏѨrc @ĩ*-ZuU(1GUwbQi\)ЏڊqLVtBLE]t3cއY.j4Ls1t*M96 šKr"ڴX-N4*.F _Ur,cmiF٦,ı2TX ])fY`w>8؏/G2/|.=b'.Ĵ9_tr9Ee Y].zsM{9nGI n1io_?P HpCX4zHXаQaZmЄ+̳fOZ!A7;Ro zJ6 X;CwT\ P V}*{ZUs䫱b=ү3h{ڪ t9ߦ?&šddwϩU}vQش}i *3QS'Ɖnnw4a߬ŊN^U~uk4~fPFlA%7POh$0" ?;$I^[(RQ?%`($[boJL$H# *OPk&Hw]ɬ5i$ցejKa1fUN Z#8\F_Hu,Zюsz3CzNꥉo8'A?=߻oWiQ%v>9U$F@΀oL!3RtE=HH6֭TZ^5%,k`%D(M-&Z@{(|>Z)2 y/<ܭiy ̟ ӷqЃsqj_ƳLJkcG'?&ɀZrNO~[{kPC:+g+j9PgKBז~| =k:?Zx ױk )dh7yn?ݟV" ew^<\{yֽK4ˑWisMLJ jdb Q@R.O#Ʒ[[C {z]K\i PAHu^,Sv]Bdl rruu66 _Ooy_2JJ1Gm(, aj3=Mwۧve.\ =x0‰4Q! Gaz` $;1!itu}qO3S7}işnD}})QU{*wBV0H=Mi0AzlһNN/}74eQd8 ɇ2PU{eKf)AЁؓ~)Zv}n1H1p:-Ūq+hQ'k{Tr[/G.nӇGyRy+:gڥ˛X ԻVqRoA_͟RtW;I&&7|㣜]|ڽnT;A >#';WB *tWÔ;8e (>+ NNGhlWAKTB U5&I` S0oy }Bް"#Rho?omIb/2Qt7E4өѽ($kAHP Z~5GҪ7/zՄflٕg/m`fg/Nh@ANJak*FfZe} R@ C}L)ʮ"(NZRR[~>|D 7[#ols aUڷ%yGrOw0- TU@)FƯu,o|OY*Z~ &H0sF@`y 8MRbV'$<;jL̃PN 399ydrl8WE0K;/('^g[D c  8JPҵg5䱐 _1ˋs:MK)<0Nj+:&UIIGTBlq(׷=`dA@;Kƙ ZFH]$>I#PgAߦ)LJ\g2LhQ-w? 7-ݎȖ.F9{}2L*0WD5IÔhɊl=fK>(y:^9:p=+^h9p)PM"VN+=ě.ҫEBO߹޾lMe?Md$A՛(pH5QJl:.82Ȍ0 ID6-2Cnuܭ#D |Ji֦ yњi))EDlm/9Pz!ٻNcژH9H#%P;D42!4E" KG%aU˫v."e';ʙT<$bxo{T2 W 5%ipFAQiVbO|}C<窵+ dLw]Q 3$M}'ʃ׫^Nɰx5mO-Df))}pcdƥ U/Tgl uRɁamzj@J]Z 3YWTˮhP;hͮVL\zX\8xv e|>uIH4?L"ԔS(gISW{݃A׽#ӄv65: ?%g}dҢezڭ UT-_(:3LZ{`MJZ HֵM W)}x㱔C]Kk~WU4AQw(,uvkTķK8ڻ/$/D1[ r Y-[ȩ^ןi˂r֊_t\TL)G7q>bm-RTMq:/@~,pڠ!G*qNPG_! K`5Uj-_~k(R[O)skiPS4~{9ՠg]4#]x ο#aȲX!W`n&9M7^VJ >fJ;êvZKۨ7cd&R(*kDKJOqNCur;Cjs*!;^+NA |]^r*|pVՙV+n7  T*_McAIo:.`C V QI[ KI';үj1g`1Lt};>1 =Vuf۫s$X[jbPZ*,Nk%aH龋h&J$:_neODh:T)ǫ{$U&hgç,+)L& ަړ*X6յHF,1.ad?PӅg3iڣ`׻Zȓ"ZbpnXWҤ"9~|N'Mj@P''L2-5ƼD(޴ {%k6g3PfW~^z՘zպ;RD0e^@;fKUw[~) )iqFLvȡn )`(xƹyJHsArJ3TbP)g2)\.f^eV9Ref9g}[{W󧛍(hC>unk%YVikʀ;/%d*tK%2iwDOKT9J|Š8%U +ӎٻ~{Sमћ[M6"Mu,=Q^Qp>G)`df.LV| Jʓ+gE_aHeJ4aєeWi*N36MGyGo;K& 'K0&I[0$HdrQ꼆(5A~~f{9HXWrXl*/VƜHK buh#q+:}Qmjvݸ2  {JxA;al 盚5qGW \,HGah[b*~vם'X (Tt zW9X:;;a$NG;2'І:Bp 1ta!&2dbLuq8FuE9,S4DuyW逻'''eA]!luYP㿽}~y~=??_/ b3G,>l(ʢLRn4KQ?Hэ}_)\)o_*gh?rw_^_^_^om!j]Ý20Gg Vqr$zOy?ct mΠaQNj}U^Rbjœiͨʋy7Ȗ?5qCLJ5s`kNaJ!Dz|`qOk!x]Rֵ">XqoKGP Cڛl3H_H^g1)94 Wp!Nq[j _;:fU3]^ATXӪKE1(\ B%W&xtd$ ܮ} ? GqZz[\xH݀%.hWhZLBO7M&f-Mxcr 1KjpGCF|/w> >mϻ|ŧmmߞnZ} זZ*EĹq>$vh~}bKύ8G;Hֲ&eaMflHDl:n_$g8x)^M6w3LHRV7P_< r#ɀk ȁbW x7N ӝ56QUjB ߼4M"vqPJqg\hNŧ̰x/ ߧx:C?ԡKmGL0vTI6OvVճt7j]vyPcfco6^3؜fxa஧1ޗ)iCҖg#]j~U9Ј)sJ >O*R^JYΓT?9Y >JmR|[+z;ZMuZTHP+&uj2o# XZ;k]HƅNH4-oDxAXϵ9( OFtZN,٦3VSyKC{$V܀#:m_'b+3v5Fog9(~Jv~"5E}9)s}y5Urvk8P4`S p:yfs`U} t/C^lSÔ=7H.K[b&tt忙,6X}l9ISʀ"fY G/ CYRƄ<ˉf_Ց%CE"jN6S's C^䏓K ߓ|n/F)ٶ{ 7g-m>F_`CP]Q~tê&sM;yYIJ'I|$(GʶnΌ(5O7֯Tk J80{ԏ#tSo 32J+W4IJ! U@iq>TU?1+Rq/J Pͧs̻sjT]%C RMsZs^ntTxiKmHW{y~_PHZ!rrd.TǓP.Z o:B_үo4W4#OXYQ؏;HM"G84A8qm;F;Er7(y=pg侈6>?VsT_"\-]ΐ{.wYF-.gяm, >18#V FncXl6%X\D.]w@jD:,. ѳo)Bj~CvЈnSxPWM)%잛|^jeS K5o,n4+RuqRwF'/M"OZqm$i|Tr~=πVz _kN rƦ LO: oS'= _Noinexs[bbѧh$sH\,Pl?qSїRwq᡽>`TzMyaB "D=bp0FV%0%ȯDkI4T`r*"H5aP os(oipQG뢝jfg |`D逾پ }h7^';I(SXr:m~i%6WiɊ.!xYjzA|X\SiI)0; 9#?R  ~lBl=$$!Hӽ, #Xr[s ҉ӃoѴXc-) Dex>hq%t4swd,gE.&ίEMz=@~A_7ړ6TV4gW@Yɲ͞s ݧdAk&?(d<͘YS]#?\hZ&CeFf uno^ lfӟq GA^#Np.,t0)+$Љw "}rW&Fu"Zk]r"%l;@%q @ܞ2ҘS_٬='VRx׊wH^`j^fi3kOUiL"Nw贈?U;r= UHMwHG(/(KКyTD- EPODaCH뭺jΨ2]p~gqR{CH?6oI\&n qkN Ximђ} UU ^>c47y@[)ПP 4j^D*<~`m'}^rE9D7p'>tqHs5p 逇 qhH}b*͡^u֌ض`dU@5C}՝  1`9g-XRY'b4+>d=[q9潹o;x6(SavZ;NDCDd0}{{"ðt{ϗ&eG'zMOAZw|/pd2̟ƽzl)L 'מ4?iCw^$f^uޞ]Sph&4u̅zCJ;yW(s8]v;|-jD zp#V49[S"-;Ҵ91L[0PƳ`i(+T镲&}2-3HNp~3osnmi, J{tڢ.),;_R{vHI8ʏɢpsQ[r/R t34_}IʜͿƼIbϵГP#@pK"f4`(yR„毉H4z[7xMEc%1Py*N)e_L2n=safjRm:yC7y` F:z4Nl3#؂Ib<|`:M8j&ڛ)T0Ȧ.S'gf6?M{T'Jj4*oJ[KLy0nژaKS fBR濅(+=Jl빗/[=~5sF@}z^Q:$^ cdˡ5fz2L46d0J#߶MX.BtF2OgG{CL+VhA g@ &D ղe\6c ?{ غ mI=SYTz 2$z|u i5HjP4, ڱ\z e%+wh{aAw{N1Q@@G0=Ll4;wgL<.~tf<)zRvWWh3>WҶtt2AB^mV4U醦 I,%쪪eD`ȩw2~gÉ׉zћ{aYO\ה(7/Ѫ6%3Qb/#z,)'BY,,nxzМFjs͠#[?)ő`J0^D3^ZSIu ]"]wX i={/ BfIJf(OZ?s*e;"yvo=M] up;z`OCbNeG[ N7r(wn>}{\t&͎:atEQ= Uzέ :oY]sv6d,gޥ`>]##ZEGrpƉqҢ눿Jq>аGJH abt̨aUN 'Vr1pY=ݔq]{U;@BYR熰, " i[G{_ŵbش [ԟ<ԟf4EENɀ?g˹y'NkRB( p_u̮g q!$"Ĝvk"V[ߌo {Os"UШ&"xly7 ))D~492鶎xiFN igv>#Q(HE,"QHDn gZ-IS|zjⓥ}2uF۶.0K(ݕ7,(&IS#D ]ODXݕ74Z~DψAu]tT˛U;A$'6@'kF* JPi% A ^{}G~/6!]gguJ^Ǜ|?UTTyљ 󤉜޿D~}8NEPI wp'd ËjHq(ŝrۤrl6?9?ɐcFSUHwc?8+ r|AuLz7fQ³}fm밴Ia1ӡhQ=Lٔ&\Ĕ^uC -r9$E>xuFH,!ܫd5 (Д'Ѽ %ߥ))Zwcɗ,PB֝8zSmWt9Ccw{\I2IH|H3MTrHŒ& TENe0qH7.oocB>\ s\Cr=d G`c"Nt!1z}dp@Zm9t()I‘zȨ@* #mglvBa |NrR>n I*aGt_/ &I+ɫj3MjiIk6? /g))-))nFAE8حpbg/ؖt&|pJ@{ڌX\^ih盜{2; j&Jh8|o7F|m* '7+0nnPۋi3P4{ }dYW=e6Srw! |W j.yK>כۥ'4y4QMJbÑv`KT!9^Ldd p*StD0y}W|OXGgr]#8z(.{ᕙ/YM?B\(nqgdi4d_diyȒup]RfL)ʖudOOUz$z*t@fm[t<|ؓS2O~z3T7T (eLr]xΩT5N9`D҉0$~B4w-@r|'Yusy˷m*= ,l8Q.H~LEM]>- rWSڷID:E#.]T2TIn[qjlj*(*KޫWɽ*GY]Ŕ9}fvާ'N'̘:ځ{}Zǣ"?@MCPF^|<03ଽIr_@7,fNy#LːQiu=KLmFY^Oj,B^˴\K2^O=Ia6J8L7f^za ϘǂdkF3ጎ$iFX{zh Gg<)+S (T8ÊjL~ͭzn&@W4&Q[iR4^=q{#l) }ا 8uoRizB?4!WS~m0g)vHFc!#M9ՈeJooQckl0W's Xُ>a?GMGl)"߻R};v[o'gҁ"9/H`6wz3!@’FT:o0;H w`z ]-4,HK-{^=2z59}7H4M"9ubd'7&P+uV]詝&9v<},ƗSw(ҭ`P[U4-%0;ڞOcYӛeRFr>݁|9`qO0Q}wYߓ[\]Ⱦy)O֯<=lʣ%??K8 8m;Q 4k6f*{sJ0Y|1=ͩˑĚ%>Sbi;f߇he^S箓?"):ߝW>B=1-.WjM}ȸ3ڍ=W2:Gک+.{mkÀ֚5׃: e/wuAmr-"*Udh h*_4&'=.#"-MD9zjI]Q]A AILFC*6KsI+7l9u/`YgC)X._JwcwcM;}KAāB2ίfK(w۫ rG=B;BelKWBTQUIؒrva /K{̹%%@( D)UmPGvnI㝗t^F4@;*6mUBLG#n SW (Il4 t \rPwc onnq^KfOwj GGHe@DU@_#|?n35h'+=Xݑ]puT/*QSI0Ey0w5y~}LfzI֑R#|#.rB%kcz:,hח)b蔟 >:Eߙ!Y>RWMrH'W"؞ ¾9:lxC ܣXTGfTI2eTrz=-H0* 2e_ !gn3TFԘcW-MBxD,ёyR?ET q%HZd3mF^xW$+S&&BDfR"4hwZx ۂB]K,cWa 提b=uȁR_Х=k|{sq>b8N-&Aɮ鴵!W;HswѺeߙu /hAMrs { $7J{FEur"g莙tsԿiLϝ&a$kSM=m&lM mBȄvk/z;?/8n۫noݽHV4e攖s'OL:۷qe|q zL}p##Ήq1_)~K-e{ss܏&N‰L-8sa ܤOӟԇd7zcxF6ıS\L/ԝ~ث2loC!,T҄hɄC*d릌0e`v׾V vuQׂLo"$8GoC\'`̽O/YXb_Ek !21da҂:OD_ҲZX`#C&gEK;&w ^-)%_Šd +|DuKn/izj9q7/iYBt'ɺ$UohMa~.vsVӹhoRVI$kf=3h (O@UZbJIoޔU&¯G i䗠Evs0/@| TNdjO*3R2ꪑ{i4`W-QjE!Х@WpjL_Ψ'Ջ1iFZ?B JWwꪈ1==Pd`*䥲iיַT =Sti@ĵUv;g,M%2>Ԝ0Ҥ "RFtъ4Rm"ߴOQX(FO)ؿ|U"j6r׉HoKc|CVsL')]|o^ Ro>I2rz ぷiXJT×UefZH'*DWTw_w 'yPTHDHJF5# XVx(^ 2T}=U4Eq.8Ky9JP^$ 4"qW;ɀЗ`+8 t/(R#ƪi)B;mMdN[a%y]ݏ Wө$7ĵVMaӃ* s:;cy ؒeQ.̎2BG1qk~z /BNx%rIW I8RKDݢ~fhѽm`^k$DP^%%*`Ob]SٶyE)2u꘼#$e63@e½jbf\Gy>.[7^u`F(4Q^Hq)U$[ ${gI.68(h@cZ6jѓ0ݦ2b-ϲgTE~Ä.S7̕2nH9E1!v}A;rS+"@8*AӴxRmJ5Θv{Kd*gRH.@paYK5sHӰ{yQA'1iUIى %HHR>zP|MȄHDS=mѥSY>*iJHZ?܋ԋmr!Dvge9G@Et Zb-Ѥw E}22$07Al{jRke\+OFp=tAݛoFCM#7&1U.h+DldI|m\%2\lu{%4Q*jk?[Ĺ%מLfca]EPGGuJVo7a6^0oےZzO?*MREuA(>qxm^B #gM. rʸkW֘(R9J)}RnyQZr_j2ӆKGFzjbe!^UwT1D/Z<↪7DPx4cL(٦Yr&V;&5)eT2TU bA&%{$IH;C:5Hеk ϣjO|2fֈ$S̗TNSC0SDy2}ʿSSEQU%K Q<@ []z>h&2T$wxD7=Q U@ch&7p9:o)Ju>p+g$8e]<` ՘Gy"C i͛OD+"}tNS\tFٛU^}/P7_Jj38O5~N0(ZS:SvDK}݇H@Z /)I9 3H? ?,鷻~Vֽ߬XY1ۛiտ6 )X5yT @٪zwlQtn8^'@Ю~jB;+/>~@qK .8=F% պsB(&:J uGY=S/+U}EJ%Tb˨*#%3߻,%N`Գ.j,@W"'X- XNV5`/+\mi`ROzxV <\_[ѭD&Rx9JPNA &wau$X]}K@?Y-J2#upH˭ F;-(4Ȧioa30 U5u(ϣ壝&IϋTFOx6=4 *Bk~>Q+~8--<"Û٢,REI_6G^}bó5Hߑ+28tM4րw)q2Dےmjkwݟ ɔC:TnTUmCۿ'׼wZQ3=TE*D @o/pHQʃH9)ufN9$Zңv6Eѩy~H?"m/Qp !{*U gbg%ʳ8H2?IEy)J7@|'뻞_k+s_E }VMGJ܍1]umJTaIZYꄉsWzK˙>_iNU3zT|0p]8gCJ|fBכq+32ݾ 7Lpݭ_?, );(u&9p*|-w3H<@ґFuUQŤEP5 K2;V_ރ =Qz{F$A'BB]*Px̷p|b7MD˄ǒ7Ȓ2 S?\ У)sZǴ|$(s^D{hLBo+zn:51eN:3s#ZˑJf~E@dCܬpZ䤏hNˏ"JyYؾ(S5>Ѥ_7( ztm˯UFgHw9*gw0/N]׍G@ywz#ά*_zxqx'?_Ai_j'U)ijKz}@ݍ]եoHzf^HP]ʫ }[^Q}WXJT(ӮivdV T&yggt~^ZpRHG0=_R"~@ tTwUM=UMo'Bn݇+k {~esaE^aY#t_Uo"A4ROPMrzg$`%^6/R?dVܫYtoZϋ[Ԩҧ|2nIoȫ{>ռ Ba**(G4r?D=%&˿Jau¹P[dSx615o U;}tezT⮉l+ *蠍MTICd)g+M0~jݠԙ 3V -\^`7ĞwQ;gEDeu0X!{<к!$4N`™oČiE7T/KGicHS.5YԾv̾;Λ/U+m<  O|#J^b@E+ʏ !YIM|$u9|pbw),iF_~f^tQ9!>aC/v@ h=4Uy40݁$vb(cu o@.;Ҋt7 !*4WF%M{P͝P 09/']ΧTRLQ1叿hd5sZ3V?wN;HRXk aR !x@$d=iA+}C*8.0Q,a+IGPU}|~(5AMHu*nߨ] {QA) >![D nː' N4x9b7.b--xZz+0봜:=АGrb%@B%hdRinaO>H\/R+lilF˭ J &ti:)U~MA֔z?:%&aU- 8U-)rI/'#OIaxh@ÒjN^BZ5幒xv3Pg{Nr$oA:vWcU}d'QR!!hN 'k :)<@ܮ#ކ=tD5 K򛟖Щ l+8Qr~IB[h7K>-8]4u9~ 'Ej" Hy`rV h'wS[E ӻ.aHu>DSf;| REQ4(l š:,53tk;aUrr },dj^r)1LxRL.7eEu^&81A_usSͳ]Pйi4[|:i hE~C*D {= 췑%x4~ }`C=J/;Gk4MWM0aEhhy$-tD-!B,iI"J`w@KaUdPyohKHO}au*[7ڑ*1Ïc{}"xf ]UM,U|xG읥rg֚)Ϥx./4Opo/lSXɳ"ڐ)oBb|𤜘XD )GҕT>I9UB߱"YOЂ,nyY|"}ηm$ ”4KJ:F+<=ڙؓG7wT=LJYii}v*Rv_dY"tܼJ,=Jgq}aCRȘ.:JQfjʎڊ<'$yz@ ;(kGw+Bw (#=_vޑ֎Oy}seZ*ۀrڽѕk_~RyJRpq@ZC9ԘTTvf٦lUyZz+*FS¥(tܢfi 62MzhH)*О>BT!9%e>:׿DI!j1ͣ+V}L+_OݗLMMF#4 Vo V0zGgٳC ky*]q;a*w2<Мj!ET.2ԍ>ifRXKOJ)>vިAޔrjGSS:*|:D/REe'm*Ӱ~v" T5>P@@ h3+1K{s~|ʸ,YZts"1;b! u-Ϗ(OT{uKʢik8MUD<@]Z&N*zK=}ySPd5V/ivzM>Jc˅&{ՙҷL\ۖV5}g@~_'ݳeYUB迀 Ǣs$;/ dgִvdZ71{Ԟt~Ih+Z~TS{㜪Hx(=neΫ?)Ro%AghWXe"rSejejkR j{_ D4IϨZs=nIzt?Xo|L/mrXcGHs}zNAE~V:‚`$uKzZcA`TPݭzB*\:Z~QEiʈۯ:='ϣqۭ{ϔIijH/k SAv1O5MFdoF4ԡ*e]H@l8/-cс+WzG;DR:1_ճꫫNs5 ʃيUO(UD |:I { >P qQ+:BHYb_20tk2D }.^ 4h{eaERaMiG)゙h{q{zTI aHChYctQ2 WXuyN\@?*HzT`}s?G؈瓦mΪVeU-zp8 m()ʃU-g+h!voQ4̭AL}J$agl@jJPia;0~|픒R)rYɆ"b&k6"T8+<>S;ݩLCMa$hkY-u/0juMprrHkUEIO*wS,>(a4Tp^ ~wq_%ψݱ<%Q(4~5u3ETOTgÒrqRIo).c_ j;zS^x EO)1 ֭io缭7F ܞm&{{uWln{%|GxaQ5Y.k7PMo4oAI@Վh$ eK >J%ǝ GMԺ>iE mA*hv|cFNS'447Xn\@S&8,B#^6ѻ9.6tcFB%|a,0,%?@KPHA_1]r =%Rflͬ}̭tu:TZܣ`e-t@s YuU,Ltʵ Py2f+7 YF35֓BnKPlѝoh{_ȪXe-,!FW@PG@RsL"l%nSTg꽻[HߵWineT+ K@ḺZcM 驠?iCtNOWx 'V ޚE@\APsV7~4Z쾥EJGA2eV*B3 fW^ 7W%~d~Qє4&&/Jp*Ө2CyeJ1FmE)&Bý'."B2C'둞Ҧl0!%tIB*R;nwa^)I`ҝWC_ߜϲ%&hGӒTQR} CyE(U4\{e֊672ukXEܿ,NzٯiRmhghzLjf>sSwZp=)Q u\:o0~4fS5;UZ g+é2F9gR/:%sVRWiis\L;h@19֭͛!v4K8d̶-+![ƭԏJ qb:UAD=_W> Lު/ E[7j5WO8o$PFX{bS7xhewj|iyZk,/ h8Am ieLb )H+||I,eXL 2o,YX+TD/S8/b@xUY=[RQx j[s?+1>y~X6&VBesicZTmE0`n0s, 'Ӈ`/LC)At\Sy([UDPiIH 5cvv- Cl)n~.}+x <(nx۝2F^'Q&0OrZjC88K݀:@rvKGk:r$2+$9ŭDt!z[绿@1{KBPFƨx1p5hg*.~Y`AI ͫ߻Sۿ37Az 5.tR0TIVH< 4n(ԓe?ҦWf:113KC`zls{~~noooPxV/jw< t9V%"e5.L1 Xb\X=iJ>Y:Ӗѷ&%)qZwmw%8@o&p>ϋm Ơ :b !gқסq/rVں'Ub8 oh+b=+W"}V;Xiy`6L1HqsRw%MdY5 ~tP:v5N%seTx.>T })cҢ=VBU AWƷI[e9 =- Uϛ-MxY6txg աy )kCW`qI⴯j^Á>;42eΌȨ^"2Á~7~q<=ݥe o_1*I&rVAlh"hlEH\)?3/H9?<>Hb{eWWcPi~yFO~[L-T s!-Y01r-ڷ+ _qM]B7 Āp@S::q PmbˮU&S>uk8a%H.`^-TB|3Q b1.u 젌prg{@лVP5 j q*6}R,A 4 =-k, om=;y2&,ccƣS{!$Ɋ7az?WqFjrSPlB hoqƶW7M +"wODH"[Lw+$wF(hm݊)RJuUmoW6(?Z`X/"'z›r5vIfbt1T::ps~ ZXgu݃n szm͍ԻM~aZLS ~rr;" Z/g"c;ѬsՁ&9ÊTFj#Fq;w^a:*{`K//0kqF{ 5@EvX$ipEIBHqvͯ/q9 WucŽB"Cޕ^+ge!:ۇ!Ɓ8K0*S&/;>Vp@*x)h = @xwtG;;wJBm}b]Ou=[te(xخi+M@Y鍪վa\nm9FyO*}|,6؍0V^X~&8ohҺ 6na*[6;~rg(2,0hA;hc,G<"L?ƞ{"N:ƚw:/_K*Bc|t.d6DS[98'Ec!&OkL oz!v?X4^ Oə- yJ#UWA=\JPQQ^CtOk hGWM*<@U,]@"#R#Pf3ڽ9}/„Jo?q6>rN\U.àf+%(^7Crsxh^YcoJe+_8ǚR1<ρA G}hћrǬ]l:=/Hz)Zp cVL4#rpjN)]!&R5]Ҕj TQtםlkȒP|iy;C٣̯a1mB MuWZ6QER.k}O=,CYD3?"DŽ֐p]>h.huT@_$n!vOe qW-I *ީ!T`L?hDr|*vmdcgΆdn \|P 9E'1t~HBcKdУkE뻰O l2k|…ۣbA=i29]baXQX?x2P_`O@&.犏x ;?0_Һ\AQ)bsX yhNw[Ί^iXI{/4oh@nT2`S%6G$ϊvZz"gZs'ַm?たэaߟ Mr@ur RXh jVgOc /'B-D DO% !~,32Dtp&C&r^4!UrTI+:ͽ%g.\l(s@]t ~.M,CKjz!MA9t= XOLDwsG =yz8h)4c)$Z 'A}2cU<C>s~@14-!{== R(ѓB{fG7[̴SiK.:paZl4J.RpdoWny ,=`?}:a'SO~5#n$H^I:Q HڍF'D״UJ gz8y|ͷ|̱2!lFT9I߶Yv?Lǎ;}8C-/)ҝIuOq]S7D%eyжpzDC4m$_-)K|{1]׍ia2*sV HM =Q=_$8/5&ƧA2*VWtЫ8sh捲SEDv8 ToVs=ܔ_HG)uVJ[𩑚նs1S{7 0OyF5oxMiuX"=jGRUP+pdjA?4p>kƝ5LY5Y6EJA'dDO[YFCa{r(rQumz#P"rzOS۸Ӂb rQ+5*h^5sn@m, ΪF#'FJ{s_@񷃖Yu\T~\tI<'4 ,CD)1VZ~ɀtG˭;ENIfKN?`K`s8y+N$RR~7_uo uQiGM-zz:ڈN+R~OW݇FT<o3U,"x Ba{8#FWv~<#2A]QTωcSg{%..nD1h  &l \_#t琀j (ijߍOjx݉iMUA5Eq, NoW<;jwL<A*UPx)HXx!7;߯jA"e EUD㆔#9~x9)f8OY࣒$ F`i¢W=\f@{ E~jJNu(f)vj'A}Z, RչWK[Qa[˳$ ,w"c5x!Prh^+ *;jB3cĘ$:%.--2*hg0t5NK};]D ^OQ:g ?8wp;U4.H?FJ}]38}[|"S kgJ`@dxX"C l$j;v 8<dS~ﻶ)Ē^CUH+pz@)iёC4$<_ZߏwO ~*EB:En0d|vTI=(TRtE7hfLꕝ/ê#Ve_ZcvrZ|;͙ ۦ JGfHl1BWK.$t`P鳕[Dߟ7Me_p|{YS9,cF7e.jvtPߌ~f]cæ:y `)yw_)OKݪzT 8V.Rg^d:r*v/P|z`uQaF#,u]JEy^jNkm%{!AkjiRZ^p%y-"tv[K6ڝISUH}A"<2'X 2,[e7? +@*ȐV%V9I,9|]+SmuHm+MHg&H2uV`.霢̤0vb?GH9jL 9p Ӿ^8fZ5+<7H޳j:)6@%WM7K~(Lti0ѹTP/' (GW wXNq{xPICK1ʅ2$S^1̾1vv=oXƊ0c Mgg/1%T>\aQf=a'x;[_` s?"=+]DUVHUaC%Ѩrl֥"y[` '-a`#a\|`E5Ӛm5yC#D1^zĢܹ}!Rn^5gqaEZCHԋ6n=3Miuj_}`U+1jlU.i9xo^/" Te~pL]0+lE 1Vx|!;Sxw?nh5dUٵ^'>ǭq$&QYNd8Rsܗ2ߦK۾t֟𫞦n\60j~­(5Tebj3.kF_錿~~Im#+3S2#]R~EWw^^f۾@.{\bjC+R".OaA#g:Cjw?!=GRR3N+k\_Soynܴ>;X t#ܡrfpf T#I&.Pj{Hv"՚P1 8֖e^޶zòVy/kn,ZsMY9.'1z/۔ҲAYq:h"y2RZ_Кz8%~ᯪ6џ̒R1MwtvuYK%gk*{e.hG*N#R/j{=DCxJNij??=\M A9?W?KQjẘܭk .`<^.Zbh(/E^ N [[Xi*@7K@Pw#-D1O=?EݹTC:z}WgV9r kv #[ϫz:Sa'@IS"/` .:IU4)*p@΁bP[ٷ[V5Fꇟ*.~~z^@kک %D&4ws,ekGO.iV!dOiwPE06xYEN7($r ed1 _s7IC RUHR=55J_է}f N| $5v;.U'TK`E*9eZJXwR֭lPP")T8wx+)vPY2MCcm~Y޹g6eΑF*L{v~Kib6/RgkȍآF{5S{UQ:hr^/;p40~@aW)@&m'y@g0P{?Y-1`qdCci%~HP#r)rs} L,7z2Y[,!_m+.`XC-+vVvW B֭4  z_=HrY{Oʗ6*Sc_ˉn [v~/xrՓbj0 s1QX`>ꌖ&}{|e[-w1rnҺ⼖fH8aS a;WKw?CF.e %.1-Έ͗5 Д~7n6Ta=׬cᬊ4Ar=^K%ȉ`-)Mfhs4B?U0p61<ǓB|IXE<"yPR=XyFƢ yZx?{͖®+'+xaKM[\P)fQlbzi56--p"pq[8-hv^Na:yfmǖ>Cc!0yz}16K/|EC, jǴ)f^Ѹ(vt=5C]+)"a) # ѤTMg堥Va1 AE.=u5FW oA #v!fg? ctBRȕ`5<˟$D q=pAju.{~me@;KP$Yo q&~ >$4ǩK//ITks).a84bE\{koar-B<H ]^`i zOl}'eWqz#Ϟ;A~'-Vi]D*Z+Bs h(`" g*˻^]b3Crh }]{ L`@պKoF]0,* Я+~L YBƇk\- :ώip[6ܥ cP%> emR=Ah"݅ò{lilE  ֙);4*rY5<1d׫vy^#/]GN4j3zwQ˵p~So\ FPU4^^qn6]9@T%In^z9J+QzN]9`J=$RK?O xI#ٱ}NK8#rL3C xƹmCmnXe+pֵn*oF8)0 9l:x*6Y&bPk 4ѕTDJj/l)t19}R,vSlhnk((}Sw>e!}ަ+lei4"x"SE# cJj,,qW%Cͻ[[PEGY/}Og3C'9 a$*`RrwRG+Kע{fާ߆o`]>mnA\$Z8yBI)2eAAj/ˮm1s:(<u D8BL;`X`D0Ux= ܝ%u@'ѣ\uә !۶)dw`)f1] NcŜK֟Ͷ)f d%͊1uZM,z3rEYM$$Qf($\Qwq981otsk?]Yt d\8LmV 1?:3?}8W]F8ݻkk-Ϲ.{w^\_:"?@nBPn!`;V@ɬф}sZ4M2G4s {%W! ~%2 2tqꦈ+}0U4WM2Q4{!6YAq0;`F8qz}Oi\&@ƖNnmGfe%zw,mNH iiPqji6zZ*a1r'qhCYoGFR * g`[S>-[P#3Ԯ$:cEPJ تzeI-(CjQYfZ7Gk<1@Jm0Z8*`VaYK|U+4br2{ _w3ۑF֝8 $s xLSœ|iJfO[Q(C1*'pI\M <UR~jl|}K]nrHPҊ^ 3fo.R ʷzZ S^@ع.RuZZ˖6S+R=\<ǽcriC=NkSnq{C@źX[a.&{+|}y@c(Ku5P3 3< =v#bhG{z|%$B ǻ)13UF4^Mw`~̻^ZH_9 %~KIi#zfL:Su Sy봬M_CR>+((F!"5C5FFHI"&ógxY\oދk Kżgܭ}L/).YE' Lnz1 hEhWzW TjupZ:'%sjk/Zi݋Qt k ưϊqg/HMeۈ0[߻XJ܃%mhNi!e'{砶_4j(*Y~%J)|wd8ƓDz(mM2CPfPP{*xg8&P!{lg}v|BGRMJuh)īCwP/hHA|L3{R]ޡ#vg"op/!% cV)l`‘/>Ҟ߼~?+Y\<vȌĒ?.jMҲ&mmGoU0/Gn 99y{Ӗʟp]z88t>zh:CI ^'_?P\R{JY؀>l{㉳OVCk{|5YF@G_P[e0<׹ʹ|{pYĘ#e~[˃I @K< Q`C1#H>PCsRS2{Apl ^Iin>fz}{~))>h^S~yX~\eyyڟϲ! &d:5I&!6~'EAzg?QSө|lSvXUmc:ꅴG?sAvt>K8(lz@_UTQ.lRU5'_=9x+}cɧ"NM?xuR8gkdzp|"|d==#RcҙI^기ѩ![mMDh"_b2Fxu‡xK]x݃LȐ")q3?+UyV?7ۜ#G5K9_ˁt熲m^V?>%J?DtDS.+4_,Aro33#؛ }.z&S;JHj6 .JzAӿ"8=ϟ9=Շ5%)[?%J"]E} Gi}%9z$T-J0+eXqFjf.&P{ݶ@Z7Jw/f1iOGdaT%& _(ԵZ7i&bjEbc/Hb=)@PEi羚F .$CgX6^S}ؗ5 _]υ~MoQ-Q7tpmVj;SV蛧lQ*]ցlDaw`=+k(m$ZWr vGlY--9ZlQSqmɥKIPŗ^Kн&WhY~3? {J~cF?IZ2ɉ)ѶblQRp@IUG]g#^kdk]=4U,}=mw@w~1M v|ڣrDiMաwuEL􈶄D'{&푂$GНmu_Q?;zh:t鶴2|vܦy`$2Fy) hN@j=ϽRJRb3ź*bh*i"k)yRT:9bJgW?0ç[;d:¼v+- Ep[RWٖ:^aPs1Λ1UKlU[4YI潲n0)۱KeOŀu4cB'2t8TNXʭnFl|CU2@ Z; j֯DMeHR|F8D mj#Ka(YM!1j kޠ_ݡ١ĥ}ϚmK)oF1Ǻ7 LhNmOQ_Pr;Q]_ Erp;/[w G;x opwDɧB;d?g ,c^H0*\~Zf1SfPbXAblAP\tD~ ,Z^,ɪUwxWCc7?Sd%w$'LSџr&)a`.q,%䆒2ARVΙi1W)!=XúQ+wJ8Y*ݒ/y,ٮZ$ssF?t2r(ب!2 ۶̭' z2J⾽BY%Y$UtV&9T†pweQ&(w|Ĕ)!050e<ϫ &^"<=GJӼMp8ϋ7$b:_tԉr>[sNS8wM #;Feo~ REj4[Q\k"nGVZfx>&i yKG <#  ͕Pnsw_Q{g逖aP]zbs&e}g8ywo|ܷcP Kqh#v .:`*3R.!Hɫ rwN:^ sE,{7 OӪմp'mi"mxsK a`,$eN>7ZL.gK1L|簻Z=Fφlʳ6QbCeH&'1%Z ɦ2+!¼ H"]{3!sZ"ƃ;hqRW${!i+ c^KzݭiKUZa@c<+"xU qT|P4гG6To"1'D|Σ. ͯ/^N]FzdsB8Nʇu8)r+gKFƙzp'YՑU.<Ӧr]s̖U {pa!TkQn=MV{2L%ѶNs @g ˷ԥJwgev[8TCNfa!KP& B%?žMtFd(nꤻH̹ܹC~4S?^7s@߅,[cgInҵͿN-;M!nhwNes'u-wJ'v_~㗧"82<8  9g{7\ ?:VuS(n!2 %˗ЛebVT݌qZq~{6AHcςKztR2:5x.lABi~/;,)7)߈vez-K(~֌i3}\(EHokzuMv@ԕVW>.<Tp[^f_kmN*!&Z$57$Pzi eWNԆf:K}|VLl0?e zHU9H:maQgژ2aM EZ\&)?dų+Z[>\:CyZ2YԹj蹸 -p0fҵ "WF8;g> >OK]RL$A skgisQ0 8yKs6ޓ^M)*gl#6RA?WSUb?LoO5JC+ C@|??wHĒ;WʪJsU\&Km-KNДQ6ӬoE%TAzF%h=dn SխmAĥAfܝV3:+C Nٔa&N͸/n+.`81:ϨI!+߽ϥ;:CKj*~5E"e5˲B6eq!Dm|`XDG4ݚ/A})H\~e5/ϋ,0&L,ZZGi d[IH6(ks N?(z!" PeiaXsʵPL;{a6DS糊er/J1ژu~ U$wWO^'B,5N|D7$"I=/-*ߨۍU\'&*J"0QN).ewpS1B0Jsk*hA]qSjFC{>XjsL%}YtnQl9j#_TUU9N뵗 )ws|9J+ 2d$NԨPZj۟ZHZR]W\c/^l=eGO9hn+7M +WjVYM1m/{ԟ\mHҚWJ!soag~y]zJ2M.,ַVZ2 Z -,ӈL N眴iPQ=h/)]`? bv%+ǥPAAw>0kinH]4Q~f̯ sFϦ=g,gkpRly~jw2Y~5@uW@ߋF], gT-^ޅ?/h7;ف}(Д@Z||!57iQ4Cc00[eRT~>IbXѢ$i΅{JJ*YP@"}l-yMIj=` .4&.ߣeܭWͨǪңWL_ kO9 m =7/T:hdcSHSv(]xfH4./hFv>]rHڂ]e:Y:P~I> ̫vEeb0꽺 gcv~3n=5@-J@@޳>n{q5ȉh-6$߂v`<|~$%x*D#&P Ϛ ]GI+˹HvMt΁ 8P #Lj|a192vӎ  ͗% YXΜl:;zMQg2JPvb,}-YAXw^M`urȅTTT3~A]eGXT5}ur&<߼"{IS #uBOvN]| FJ4juA/h(P:Y(u-8K8˹A14޳bah_Q dťaMAJٮ!.ִK ڐ%jIEOJP"Xsw2a<9ާ&ZC>tS|@\o|#*iYY0ݱ٠O@J c:EPj r_OuoVdl9U')ndv\TzCK2k #U%PGG]MێMSA??j߅??Pg 86$%v^2~"ey!.UZߑ_-2V߮]tz8nx@*ۨ٤xPOR, r3%"YC]7VSOxsp;b6TP\XJH1ڏr8Qw9пXtOz:$ѵ`=IDyᩀy(֍rȖr !tXC 1f WeׇrN) 5I)vPYcQ =D=}2IuSg=סtb v~$|8SMUqBδqYF$^ 0=4gO:.; }wK1t:f>t\N|/ FTb,|{5 syJa_ )vӋq`trHyF w G2ܸߣnǃ )ɷژ iC;2ja5vjy7K ce^{2:pRu,:YFeK[ړ$-o} 1-|gj4Tt"E ׭۲z411cE` .dDž7'_5?u?5Wq)][4u KN,<ч m+&< yg+b,F)3n\n=}8[i:jt ݓABBЬ,|XQf(gEOO9gkE(!ѧW!R|#%#SQɚ5N0T;9|.]d_\܆2qցtkR3h9q~m-pbmo;d >gZu< 諥{~hlH8TTyDHʪɆmK-u*zV_EǪdhl05|_!^kމ];P'545G[`;<2 Hr*Zmji љ4NƗбGhq@ v'˫3Q7M| 1/= M\L1ՃnKm Db`&~LԭY eVĖF`;۠|HLU upanHZ/~7ּ,1=)Gcr*FbU'$`kleY N ^u|{ßkNqE{(b1ᬎ9eoFDjtoF[K?klaO}]0`q/0aI=()yn/N*fzKx*iD___0ob1\;K9ZuiKjVϔ$tWfWD# 3v߫l^%Hæ^_O[ji>sWlOﴈlCgIJc~9^;1f[6(W^lJs)'grOBdm:rFagpb?{ 4V?xDW4%ßH{(4)ku)iJ,5Zr̀GEU5Д;Rvr\ *%M( ]"cm ܾxLd0cڪ 0,嵍%!S OR e} -I~k[ByY+qcruMհQo3<=).R@ }LZ1 b\BDm%H‰2;'&~1c4_FKBU뮬uM/zIKMeÂz%HO1:CPYVSO8S֋|"aj24\ƃ&@N|OqYaSN'=Bmh+Z+;fLPs٧6%%+%/xIsX&ӵPEݸqʲUiMMŚepϴ]~)&/ _/a|~gw6tq ì%t* 5_^+zK 5ğMs( .)O XMo~2|߈Ձ2A N.m,^p<YZH|Ae1Sa_NUO@*"E~-IsĪˮH?VP]n%?uh).9uvVܼ)Qv /${:E<"A~טڝ^)QgiİTN: >hc4|]xSOsd|?JAC-I껊q_r"L{?Er0d%tHnli03$x8'.{tSI \~-OreiAQJU ll4;ؕ9VAx`<떮"*ߩy<<㺘CҳA1ɒVL[K= әZ;%";%uig$鬺*zŻ@S*W6 ?rGQ31hAq'ϩ6sn\i{z!]K{*DV qn)E  pJ8='ߩs4š'w \'Ad01&kZۂ0羔x?:L>f&Ъ=DKC7WDž5$PrybL+gT&ӓKc7hG7RC-qiSv~3Ht&hj}*dsS1M~k=k#W9K6:KN~"z)C* TpnMQ_+?u{P@/JwKهJߪ6ǔxq>,\ ǥh;ߴ-… zi Z0ԅ)+=Io=8[ .ᓥTgKjޯ*E}h =WIBǨe:&OpAİ#]5 /F56/@%@>?BzvHC3 zr^|[z%~ԳZ0͕|YBz-3m}۴c+&g\=ץhݳ^H/,R BƇ zCՙ[˵_#N-N{jނzriS/,{@۫8ʈD6|I2SHäGYHl=)tsj:Ziӹ%~E=]H=$fFD&BqMIyX<RIՁB؆wQ&Sg6:>H0?qJc69bh?g۴ŕ?y-ȵeIo D[-<{7jmM2qYv`9O<)@*"w1B 5&JNBڟw@tPk&͉9h ࿑@3aNn:yݞSm Y=iѯ@w :RQ}xB? Wpi:]ey^ߐ{^iId'ߞxwCJtbiTɓT|';/+\4 O<=wg+>mP~~aF˱fIoH] Ht7oct| |Q5yl 2ܸ4ЧVm {5ש䶁*LhFG'D49-  i\d5/u};<~攵gI!AqߪX ٶn .pyt%#xBNfts5]mH^$_y AЗZF O#hx/y0BS?`d^}~|򝣛R Y&iO&gG4M&ш^7࿩K5?I Og()}z]Iٸw>_.k*Ռ|c@us(`T>~\x{^  evXEx2Ā; JZ-S,a:M?NݞUc4BP- Ia;;w[ JNt@x_.68g:]hRhUB\&T(߇OfQFg_`YT-a>&4MH.cɸ/=C7s5>R;f~Bed t`SaPC,=hPڌu KO욡ecRJ=< =xNCeܡ X4B7%%-ׄ.yPBMQ]V%J}M-F`r9L1lJg82q'S^)/MtF GT"s(_mpyB&{ īKHQ-D:УOZzCg&6$:Gm#-@Ci3KW&_T ]:s%Z*ʥ >|sǜwT!ɾ\y$qYMiRKƬfx#<,  m(2q0OgDof3,z.?A9!ӊW@X}7hK\oRUU.`U1x%AD-T~D'=o9EMGՊ7*^`١\ȹ}ǃCUKR -bH"uA^u'AzhEjxfPǘ+׈sΓ\D@'YXݱkʱ3EU-@  {uդS!%Ž}k/iZO݀)ZJY!Ã*-<}uqg>S1XgT,:~ef0^\eFQHπތtcp׉^! ke[蓉pœJfG_Ո6߫_@k(VI̺@|ng?ScF_j^'K35@05gЂs_%b&JT[qd4̟0Y9?H@9f!_{<6C*c  vUbɤKzJ3<E=uc~1xzo~BBhe:Sup6Q=# (^a`x=ou1|R;iBg>5;)`zğM"lBI>' 9ü([8"8ΰht~k{]ʧ lAP1o1j }oڂ^ TL|(թL\h/p5Zn}h˜z ܚ4ؖ&tjL_W/0?5f\)jUw|kɋ6mc$㢛4o@yHS+N c= imDa(0"SRvќ;YQI"YJߐ[9/hStK;~#\yUtM,ojTq?çt:e=A\&0  qB=,LSu{ۧä1yzn{ |$r*E9N _{o/'x;PQiW!Nu]o˅A33oZ5-_I 4u6= Xuwtqv:/5埃1ˡң֧0  ;4Df?Ԁ~:W,VwTsF&-n0XcXb=-Bo8yefT m`I}7 _M9홀wj>?iW4eϓtO,1S;` xn/R;( IH;1j ŝvnX'&ccph_&̛tn#=8|v~7j[p7s#vL>~G@l;[3rD|G~fKPcK 5k1QΡEKVQX-b悶,Bhuq2y;&m ! #@}J۟JVѮ⩏[>rI'WIs:tReClJoo_ |0厘Gaw1rF1詃(ޝRӿFoXY~)Eq:!Ƨw)#:DU%+V5MDܥXsb!*6i<-wUftjRK@3{qT\S?^,9?RXy6;<8ВGS;OP7 \Ŋ+jfXx|,U$rX:br)FH<"i}v7Oq bKϩMnSV& EP,=4 s 4-|hAC:&03t0ΰxϠ\!5HZtH"=a溤y3t+qxV\E8X szRwgjWM9%$tuύAȞě>8V1h_D^lp@eIMc3Jszz+P,rsC%t0GT0Ec916kx"JF)MCI+ XK˯'] ]8vԣ@ZݡÜD =锍[@ DN$JPMЛqmʣPҋ4"fD#H }wGz%m,E%Ab !2Ĉ.SnSr.g̍P7(:Է:J3Ղ]͒2 @gu$l1U;rfs_~D9M?s(9v }4UD[cјm [t{@y}_7NO(Fwq(U$n2VbMd 1dHnRNRSPբORL#)?ڱSSY,<) R5kosEܻ(?q01G |Ml0v\d`&i% m4=Q~-\k>zB.']H:ȼKZ0+g~[}h{YNNQY;4^PMB.ziW>ɧ~I63gG&z5Up4k8n KP$O]gFK308eр鷭 )"xZTx ң#T%]ǠM=. xTu VTucLܺNwY͵?dR ub{G)՗<&hg.A *oue\Y:E$P`NXQYn.NuyP_ ƦíwBj x]L+v(xS+^ yu)+uE9}=<P+F/)A3{.]ÞEs \gt8>A򛃄5nf % stC$kڐNpxuwkWINR feCТzH]A[pFogX啼5WqA W1\93<7i?8&n>gRNE&OC\xBG'_7 ju^?f]ENL/C8uXxc@U&սK EH'(q(uK/VŢԢ˅Ds0Ϝ_N\[9gVlk?t uE \wC .dPt[E *j7d4O+C(4==^&=EX(#%E' :R)5Oc>MPhS"lP dץx+#ɺ[Uwh" !cST˩")[? A,1A9R-@gH7YIdAZ~$p>=>[} EW`)/Hj"dNNC\˜}tB\jtP˷  LyQ|oɒZ=#G1u(t7 Stozdt7t )rdH=WIN;aFtDAO “XlL A7W[RL)$@ȑbKϐ:=mz~RmE[sRF<r]_r%RC' mXK%Nk*C]x}w_oaE:݈S y\MA{E3熭NQ%8)2htB Eh Хxm0TRRWwT z(nN3y&v17dK0RD*KDqR'-s% nש&rG@scu%E5\c @*driBX6\NKj6_Y֯C}%nu%ec_#/V/e RKuE#Vk.:k rIT6!hcdʓ#͇ /=֒6mT.'M3ci#Ko4Deҷ5?lƛWK7v}$mbP7h2s8'[1/L=uO=#nrL*=8lp~bRoqO-#{qg_|-pZuJ!.jQjO&ub7S3)+Σ.bp:supDfɝ'e5 ]] 3OnnGT3hڧS>{ N6I!ң[4v& Z\ GsV3pCqes<-ZJd.h$J @ }kx)^ҫYT=ehQ%xn2(65%I^>Q?=u4ws Mn^c1Pa!WbJLJ{d/^OZ(`$⧺wi ~|{|\$|gliug湳G2cob {UM={Ι rVY]Jԑ5hP{ZTo^T8Ҧ-J"Q_O>.C}iS<RꙚ3@D{©;J$[0͸17A$*,JM䳸^ \nPW\Qz2pO}`߸=OTI $POcOh~謹;@)Jmfu5%;AObP 28ϤvnNAx_٤l5Hfw@z1IFmjC!Gn\BܷaX{J9h}b@)䩝OSOk01m:pjB/ B$ǩIkù] tAJA2v:z hQ{j)ns]"&F聋igϩfj 2=;:t(j?$IsKZ>Ó[W[zvte/n{ratPTbzehaP)ޠWA[4 T@pL \Qфs54M_=/ R U-~Ix?|_^M-f8v~>}RIZߤW销R&*Oλ<UW}A0?Ɂ ?}x~1:i[[7.!V)1((4b)>#]n^M&9 آ>OykٿSU3W>e#PĴ/dfD!S ꍬ+#M Yfn Lk.\(.uW!o+H5*@S a cIyp/OBanRBBċi60{RVc Z;B-$($2Ӯ<g~xj>)0ȣ,n&˞k;>5]sp>dz5' =1Y pȴa/4 8_jW5uzB 8ayFi1nx܄k{BñH_7%@?,'(>Ǭ>| ~2ms-Pw+Ԣst<+4ZI>${M[dfa:?f3ӷ+(L=V,y$QAk`]'UPVDLFT'I+*>.$ͳ,$srO].|v8놶#V!~ah,G&;. ĬtHRR9Llaxg{؜9HL@d)%wNF ^-;Y]1lQ5:ZNbOw @R³uw|) m@&P@4c(ubm=N M }RZ?_=$3-E㶜$Hfau{)N@:m;8e]TЃ^᭸I$,d`(_5.FAx %R+ڀ^+wg߁h8q4SUmT1Ukg;bao8[-7NJ|iPBo w-M~4~_F xsm`۔@'!qwoHUMMm1dʎ';tXkg*/Cvj0u7||KԿ| RSBc_+bkH*eFqu,OŢ/J Y9եo\^ ίrw/t]x$>M6k(FaN%=J T>~{UeaPd~q{NC:@:Yu^ /"{t0I(zxY\1VҢ%pDyPُV]ERuF<#7o٥v<з ?+ۚ6.{b|ywYa"& @6[Mp*KUm7NDmoTDtSdŻϩ@%TC|)#<M ]j[6o;DW| N| mIV9VzZ7;amG' YQHZ4;4(ƞүsЀvWʔnՒ^TM#2r͢xQ90W}SK>oB!T%I b Ev[Иy/;B:+A޲ y׉*q;) 30"𷟓 I2-PCtG~HǏ?{uZ;0==TݑIΗM8Rڳe癔ٜRf(͜MSj%M"q"iC}̢|ZC4s$7t2 qiB9τ]BOC|,bB;$oRertpMՠ{b8~l$J[{h ˝S>}O _ǧy:]y% Y̥QSì5Mvs}a0kz4Fo:pRpZǩKH8NjQA7]kfߢu_6Un~ߚYni9OԬI2#YP3B0 5$nڀ wuq-@}0Rp٪I:E{4rtM:R&er][ {TQ1MH1kPUz֚$2 k pF 1ds_#z;>:ơآb<\fYؘ/n:&<a :i<,gQ6Q?z208t?UzPn `&oE5_5o` L%" 'K@ur^% 8tfBh>̪"_KV __+<˷(&PG-rJ )RJw˳_u&,^ ƥG|Qvcd9f!,,J#Msw8|<YƖ;W%2y\|Õ VSbŨ&] =͋ܛ.Ҹu_>p[.v=do iyC8\ꖵ]*(󽤕JP8225>H̹wNz>Ǹ5 bOfE}(e8* GհW]T]U'nU~9FLb`4A[9]ӆ2Sz:9RkVH*qZj`_"mrICs } K4"keI,lZ!y @ !dR~y"$28iֿVj[rK-MML4wGh]4\i ?2TI@gt>-5K@Fn+rN0X/ְ\F)]/|W|H{(\^ƻAGY5u#0[ P7<İ\/tH=Fw^C {ٞ|(.Q~Gv.;w.H);ɤ<*} BG!>M3 E+9Ɯ =O/m_|VEtm| O ʳ2هF Mip)1mu8sW;qSA 3 KI Kb$%)(M 7e}kg*K}2WtxM8SJ(e|yƐJG4ho mǣ._Q_QLC>=8lo|z[{уv\+ H]/_jH}ao^U7@inHӰA ICؓJ\=J֊q1ᔵqGѴR}k>)F5Vj5a^(t8StFO+WP~xkؔU~/f G~y9LVs$=6Fō|↦v#9MsI 9'6Qk4R p!ȭI &y3rZLh>32nUY" :T!iA#\M!P̀w7M8ki>zN@!B$4y&|:-J~ǶbSZ?ќԬWKJD=>` ;kˬ1*y溏k|Mi.5J5U/!] &_blUHPjev{t潭(h瑊d-hm g!Gn)K:a{.sIԔ= iϐ{ɢ'9dDTIv"Kюeo mǦ:1B7kzEz|pEMCvo+X37#MYUH҄r嚀p~U-Z~~ήZRCz֨Eςa & ̽_qvmGČY٫4~dsWoH:3oR9Dȏi>H2p٥lIP~~=vRkpoPptq1~9IRR$!}!7ӖQAYL1??p $UJioEشJNTqWާ:OwW(=sdҊ_MQfuOz'g>¦taI?N .|Ǥg<0iq:_CCKG /rדdui!eY웺,T\x"x{cԈn`r~t8m]Dž^ +u&گUZ1XeV'}q_E,47se 5 }pʆ}lGXWr/HƢ&Wn%;m.Iuy ^&h)alz [Re)9z48l4ij[۴+B)Z4s>b/2ƈi:W%|y~i[6d fLʫ(L}P?IyX"?RGQVSE_AF0DcF8m/N=z! /W'NEҐIm<(n-b مS|`U1GgHbK\)WP6`/ =s_D rxŕ ֙[߫鲕ϑQP.iL./PAf)g%` G*ͺX<7y+`$kBu#k틵WKGIA3ƪ k-{#T @]#]m@!ܢ)aѢ* Iar)m|K )T>B@/|x̛^P6mJ P9{\EYNx.-fkx~kŞه?W[IOUҜL% {GlUr=(篝EpF*kSS/NPG-θl|OIy ގUJejR[Ժ^V>nytJ0I Bݐjι__1^Oƹ7!=JB=$T 8U"h^~0ϣB85z/>kĦqlGyg%AtŞ FLgݥ.\^tuScd#>g]ڸhNPw{~yhzH@8IռD]W~p~rVX.Cy~eRKCx!a4mS2&UuMt[wGzer^}~}_4>cfT03ݻft$su֧9룄bTE5׆+Tr22U`t@9^}԰ӣTe]_\FJ"4--Cr\I d.1A>wަf(3 O8_4+^{W:rNBCe 6er6s>MCtl5_|ej0PD"9)@Ji*[onw;XCyEuhe!((N_#I!vR3]L-1un (Ҭ$8@42O]9Ky'rMh1k4pi$q84ר VvM\ 7AV O8\*;ρަhǍ2 f1aZ`X/U՜ɞ}Z}R6F}c`u)z"kF~?l$vLZo+} 82 y1SI dJ)|=J, Q˄/v577GKǻfd9Bn.t7 P 8i|A~Y>FjTa6LH ?g:z-$OC7"ͭ 0um ăX>n,E֍qESɠ68$Bu&[BPj,CV7̙+y?AKr\*YZ7&]<q{`֖ͻUed.4b˖Ov͡MnTY齦nyY UA˞Sr&D1sw[3ul.M3]d l]ǒ֚e i|_gN\cZˉˉ/xF:睥J2ulwFFܘFG >*A_ JJS5_Om Eǟ*o1`C 4g=X2Q: pmx!׳! ﮟ=`2:5bf\ڻSjUq7^ryw;זFױ !@ :'&[Жu-yTΏZȊ2 'h珛5ZSh纷1lE܍4%.Jhma^խ0N@8ψn/k|VpFMAukwM0Ac]Öm]Wq N b݃0ݹHoK+1}%/66кtqpsXe32P{O`۸%x' YyUnyxhUX|ޯuoojvTrOZ/ 6eD4#$+:M$_$2I%l%Ea_ z{};`^\ʦ8}i\IU /u07i{>Rfyxڐ;U'"ܽook2Ⱦqۊ£H쉻4c1/Dtd`=f]0.P$ \>o֯v2`\1 2@mëQk %_qh[&A=a9W mp ¤I aܹv wX^T׀Y !P_:܏f}޵n SBt}҃Zl>) [d~;Hoݍ co;OI< 7Z]jĎÐH6 +̶lXt M"Ԛ )da$o+k?R* n>;\z ,Bb9̫:ӄts4Bga }2*nÁFGlHT8ڭ4r_9`߱bM+6iZ8FZb?rB:vʜO[gg=$`xFj VZ0d5M2<2x2Kxx#%ߛ2v C1dxSbLoKA,=z\۪G={I)gcis3'Rbu*-I xEj֠yxgPCTR<oi&nP{]j.N;a@3bW=Er\3ZD 1:+uu-3}D6aU`h`W !tɷT+cxK!+-6G$;Ӷg]绿{w9ǠgH M85 O7ո>2+hq1 rZMvL-}Al=@ m_|?}~>q>F/z|4䣟,qN:ZZdl[48~ L pH{g)pZC.diG*4 si됧t[ߚ#ǤYM;BPrpn0pjMk{r!LY璺VN ?]iFIj8ˢ@M-@鶜$~'b 49vILIM2:((ёdf2 tɓ:E9>p`@c{nO|&ݣISG0iY?4eakUڰmwO"u*|2.;qOӅ+(bGewi(n^ІMwŋ$R:Αo5Swb4( _7n}Hi腾'{/E*:Ac7@i+Npic2"-OW?˖Pq@nTm ShƟ_jO:t2y)Hq'&n{9QUr}<\*z^_f#ֶmpc/}G:#=ȗH쩅T Mڀ¿eu6> S̕gOTDPh9pz^C SSz͊wS ΧG0y 6)N=S]H :\wO@)E]*?_DP]@ gKL=I'0% H_$(rݭnu4o*RƑ#Hfytʌuwaiunoǵ.&߁|G+6AHԞ:e<.%@) fZ1̢[Tn[uaLÔ=Afjf !=m?q bK},Ѩ곢@6qxVPksv*N׿0i{ArJ@s~:RRЃt9||~ T'ӈ<.&oxt~`qTdW?& qSǥj$ 44;}i%;Rzs[d=3l:!ϑߥ>&{0?(W\{P$b[H5N?UqIUn> MǙFewMC4>?=4Cϳ5yrnS4*Wx^wji5lT.ǁ+}*>/~fΒT|(>l@/{liBZq̤?UP1|b>b' 4 qWo(b\ Kk nk=T{1er#g7sSgs[3=39J"&߄sx%`i4֮4 vϑʕ;_N/a;nRS&IRggM/=IA6TuI BJrY @gs?SzALr|BZ dk5o{geMOʏ[DwuQïs}oYǙ^p$MguvInwK+؛t쿦Z!?؃G2hpDEi :挀A[ 4ҙjIMuNEso_g,ppE vlӤ.oU4ƭŦgࢸP6͊EهW9/$ (c=}y%`JSԑOhI7pq$g^,jZc'7(.LAVGU85dw`8SI7П:1X+lŒiæa|]bR)FTo_=<}5cRfUo"P*5 ~jֆRG/h͘H}}}ɖ }4q'B̄6luy߀`R3-Q-wխZk*|){{D*6"yLl !]zGGW E_ӫxFĶl鏚[~ hV)$T(!C4he X4M @;8¹1տ9JyﭢdZgXzkvo^yX;N`)(Ah+ꋔ#>~x?M8PkƊk${~& Bu |yyy~~y>O[b袭u%}iuK=6 X75zkjؓ񑓌o K/:?o '_WG!W[A6 ZOCgef_R}IdxP jtFg*:0aoُѰh8#!YTe1;|DMDv GQyPm{K'n, 5)A%=mrD+V D|UA/F0 @#f|(択"KJTz@vKj|H ojF*څܹR' Mb!PQ_m-ݭ&7~{uRMi'^ n)6ͫnʼnh@|JMXM#_P2>㤯7QPݡiroexL+g+ nΜѯ۰IZ&[:a)&ӡ&s\M,?Wi$NH9\hpM>տ[0}69=Jl̪$XA2b2i[_)"gm  ?d/Z. ;']%:f'qO%SmLaж *D%6ϤUÊfF rՔd1lљ⩻49(tR .TcƗObx(Ƌ ,YDFF3PM7H壝!Vl/咾5>#s#:LKaŭw M0+Mp,KXR+xz5 Vݽ^)Px{FIR0۶ s}h )hW;T;ˡS;-9w;DY1rGDMu>a>>aK%E3'zKp ڈ3OV H@P9:F[&Fˋ-Rbܽ~4[7"kxi(eB"k5zj՟4K<(A$d]M}Oe޲kOM6»Kc_H=7$Տ4%43/$&%*mlF_}Ih =OCK#W\1"s_q~:w/(.kQBInRܿxŰWq/?qA|F\ ~u:-?6I_/6;whxpj8Yl`Mcw0-_i.֛`8-eJa~}}9?ٙ9Fb?cxgSN8bIkWсeu|֮-gt)evggb5VK)-:3{̧*;QOe*_IP_{M@Ll~'%OEHR_7ڽOF1 niKs"e&yo}6m*RӮ_|xPRLSьn$GѻKAy5QYL-&>H0R0Kr4?)*lK0+ԀېYz o|/ɼ(*韣<1a#_x>k_n|^'*sNooSJMw%/ u?ad0㫿fG uw4ѫӈ_7@S$ȍ*(WPw-~S3?L8zH*ibU'avo(D3*kAVQFtG9)MTS96Bi^0;Y16M@ך|S8B_:{L΃FMPsܡR2VFЅ+qTIᔚ)oUY}ԏHLх_NfRnAzH=ۢ ˛M'utHaf·*b "f]Q61)x\Cd!pC3,K)'coY}[1[,ۜ] Tn7pިe]2w!#x d&-jE)2QM:HYRhY!=Xg<&n[$M$zSsn*3PNmm xoٔiVqr6lTN~)Q=H1/|I6dsdOP6D+%~>;{&MWj֞,ݥܨ.ԩӼGgE6nW>!pHt@Sel?x$tI"e=+58&i|#Z 8G0~ kf<wǨ'J9iMޤ%;f*zQE<[I 1hSV61s2/2_Aly궃pL6Is{h*@G_BєzjH4Wq5WEED`P(`sw0CD\C'I jc ƼΪv-8kѫTG닊x)\ݟ!-0" u:` bq~d|4,Ę{zJrDgAxҮq<#̓M&M{cSYSJ6* v!`7`/՟=kXNWR3q2.oz%o tKja ײ%' פ %#s Y@OvAO |cJɃBGv {nko:Ljp.툸4{9PW [&m)Ґ^E>q٠ΧDN*Lv9|r˴X"Е|J`U͡^IG8Z>#IǦ j56t]&U0RE84;d8/˗Y?_܂M6u8zMi&v͜eC1ϫoK@8$6,eKҫ_.{M}2-@yMLMSA9%Gꨭؕ>7LJXΡ GAnp])ߎtߍv(0k׋7(AD $c4iTLb5tah#H|'^2;z8#3HIQ2IDbԖ+sK6L Qj^Mth7-HOsVgAXxZ`(6UHA ͩZaʯ⒒5 r-HM r7arAm#1cN>NMM&O94O|w 1(4=_p^˴zZKwX%[!u6GtlхZTF5s,GєQɈšYY3[Lfu>/QJC%i~Ɛ u7+ ?;T8!cPp|B0(XW:4;y茔xX)GH?_|mOԒjR>נ^_}&NSQm)aK/xg{û#2_Vp$& U7`?Snn=ģd*[jrh:x#&9\*A==)KpO CI$'w۩K3H< rd HohfX],+P/wlfm Cz:k285KzhgKv^wgP"$Ԁa,4a;5qzER19dgR!sOΓ҂55#NҬ@׸ >#%hrnF2#?MP,UcHU~ro&Ă-MʴURI+0L9=C<~z']]7?>U E0Itu&E5-k~nk٢MP{<$ k ^&4u7s Nf*JAn9R:@$8:ƥX"e}qnsο?K92# ʝSP(ţGv8ɢΔCз01JxG@Ḧr?3m/{?ُ@ԓ1م0@0eqDA,ye<ʣfϳ4rMѭOw֩Qjeq~?LMC2Sx@C$OTA]ԣU6E >~d(EW\vW Ru:Ѓs3y՟s>kO:@fSLZ!=綬-Mjv6^f0GI! Qysn-I w6T#. 4&IP*" r@M~3"8 5WsMZu;uk:FVO \M[ulXP}a8|19 Fk sN"LmJoP_*m,^]b,{ճT[>Xe$_:}^K%(qcPHʝAaIn(u' ? W)SJTЃV M)sn̶Q7 &(c^X՛٪.!oAr6@yHm\T~яw*:ծ UH2M_ !44 u#IZ"CZ / f߾W e:TyhN^N,B@MtR]e*tVXw6;F(HTXqh8QUo "Wqh͊ҒSJW[X1@A6Kti{ÖMbjr5J=S OA ⳊjzcMj8\_¨~{Bll4 xW0=?u_4 fS&φـ63^Ij>y9l 2BfuK9!. Ϥ}ޟEr0vzdI{7+A+ȃw@(v@\V뾗=5H\i8YcsjEza ;:_CnL]l쁸}iD[bAMwj q66㘭]U/X5O`G\X qYs-?QZbQ\ӉU ,2Ի&lKu`\_S!Y u# 4UY h.ߩE&es=vϦfb,kQZ#dRv{W}Z.*FuhHpBy9msꩺVyOT -:h8^CMaV OꃢIsHKٮhd|*Oj:ZTa!;tH}^tk4矛e_(*?&'JTVH/AC)LU4|[!u|L-S:}qr>*P⹏զ =Չ؀:jB8n:zzzE∦j?c${q6? )஢O]ɵ}g Y-}#R=1?q`xyt?6qW\3J 'mMZ'uWܛ8g<2[ ]b]*Wɳq֧mα灂zVH[ ̆tө Sx;g{ j@$;XjN펯%שQ/1EpSVHVFs4͍ŇKQC"jMaO&?DHuc]>W& sWWno>wٯVMbbhI G$,^Y<_ٔ\ZRzhk ]؛&wzBEoǎ|碹#e%s¢z2q!?N jIhE}|{1K>no"M4XRB[[?x~u{+@1қez;9.J۴ƌ5۠G`3MԴj[\0dXOj U06^+g-̕EoRNޢI)Ϲ\p2B>?_^Ms="kU{JW惘Ŧ1PRG^v Yg\oRAj5?fAZ$a UH&-?[?^]w>uiSԩULMClHmIAK\|.^P3< ee%Z)^'Mk%zss=:Zx~=eORC`yCW6Ց%9S1bB&n 6.j{#oiWU" ?O~TZBmԲR% zl}S O{%] n(cM ) ci Qҍӹ/+Q*e RTUkjU HOi2h/ZQ ֵ4P@5t…~*>+Nxӏr[ۓ}3ƥ%=ZfG}I_frj_ |lQd HO0?IYE`-etuV7 LFti8t&򪹶A2&ЀQ/i .Od~YGJcXS?OT+E3F eX!(](4"|Ӧ)BX`sXc[͟?|ҮdyLfOcHJݭq-]- J7bȠЂt$S)*Ȟ^($O@ڿw|{6 PBhйtfwp~nq~dK?w=O*q'˩MJcO ?>x/gis_JPKHEM-TAԗD^JI}GKvKO3Fw8N rSR՞E>KޙG3 ը< Y}k@|Ꞣ)Ijh\U i48 =c'OU%ŦO([3 <{*kM4X^[P MPOr?X~Ceg0DzHR ĩ:x>KgHGI~@lr&:Lab]OMj0 $BeZiC_qVv -7T{@bku~]e+i拀l &XT1 ;?:z҆V$Mʅ@EiԹ:eu1CG!/?Xs߿ds "RbǷ7lx軄~m6 )yzEA6کm+jEHҺej Ms;egp@OQH #p~M8W8nhWH JRufM(jKOQ *)G͔ %ԫ&S؇p 9V DPS44*@C.6ʆxHBIïZ$WG*"PU+x\y !θzRPuܛz*~ĞX4WFb<5GXKժM11_TX'DqT۫ ˎ d,TNɊU%蓯1BEe8:y6+1H@Bz94zhMp6e,;@SJYIGjM.;`;UӴQ%5pY qoAKooG9{m+1 >PO(."ҸYBjUշGv7,#MEjP{V"R`"wy5`^9)&Uϥc$4h*a=%$Qi*x)=ڠTӰ"O$qxJjDOHu Nzr%Qt)gS %l]Ŋf`Vmȴ:CلDd晴Som? Pc9+V;ɨ/^Iun[{bA*0/8|n4Xpk @" zOd#*5MPeZ˔Z4 oEU˯k}>I hLJWMj_-@IT(_AWVa:`)R~ҐgMsCQ VjDG|/'4Ƒw>*ZBj_Qcƞ1#r۪J֤HLhe'5a=D5dTS@aъ*)HdRj)h *L\SZ}f WtuZrjjJ VʃO;@o̪=iec|(ܓWR%_%4[ H#&ڦJb仔s驖@'_xK -dE{0$jsb.UD>!IR@>!)T!i–Lb+~UL B- x|XaX_(/"jM a~zrg/G8&CuᏀ\KQ]SdZtS }[}Q )oS#t}(}T[/x눚ԓj@h*f"mlGHhLI:(Op~߆Y}'?}t#P}Es*=>HB a: HO /~['U Ȓ'ԺY;_M?)H) ^D& EmLɓՔJS4G })|r~ /*-i͊OBV!.*~u),ZNC⿚z>g۴䗀"+z"Y)~AňӖ$BQ2+`$gDJH țT7A-2ghMt5т!:]tx^”ICH@GpQ(])NH 2U͚-cmݭR5c^}h0嵸 çRBT [tLP'6-?$zm:񯿴B TuA@Йr }%mn=̈́$\ZJQ6VSijB it"M7Mnս OkJ6R IѕRJ)4s͍}4"_׾MFӁ;UB9kPEiSӄY[`I1 . I-͢d{b 4>/U_)Zާs\ܰ38zuy8}{<4y=(i!PKּ>LKZ(s#n$ie۲?m h\iCRv(?BY?F}z{%Z}?oHW~ew;dC&lT`:u"-EhmQCB@ɨI->iSZ ߢ'n7L9E&[:cH+)I;>^0u#5!hHyjwE/zhDI.?(=9kRDyKLq; T9's7hc{Ɨ MP]Pi5ҡ.|JOy+4z& y *?]^R3Tt:^%_jL.'đWiʤZR(Dsi ķ?f`x( CI)*^ԩ/GP9rJ5* )*NFi\4ɩլgr{[l\ISW^3vʳPɮ9x!VYt#5!=ߓ}eПJ6OK.T(4 AB+C\?mRcUJIsVƠ==<6S~Ns "*_UMmL2k$GeQNE$HQytG s(%]=ޱrJԋ^G},}x$l!麸 VwfR[?37djL7 B2mkxq@x-c`6#ϓYW, hGo]"e˷bg-Hd[’>Oy *;29e|OP6|V.kӥ PF~Vj]XVMOԨR0>d.$RI5ǽڝUK)렟\a$YȞ?fAlͪoU)Os]m *K}P kZ:\"XCD!x ä:S{pgWU$ZLPD7Ao'I5m}•[=  r.scگIZSsRUQV eRN5߷MMhÖ xfj h,bJ};M546{}JACJ=+Ԟ|ύڦ7WX[I?9j{O{`:º* $ċY.]9REͦ gC6ztjuUAT E2yYu&j6RLmiAU8Cĉ{zXtgzX_?T |'Y䥛ԎWԐdFruKPA=$KKY uEU7Ҡl# MZ$b:|lQ4][Lv]Qm(׏2Y@4H YK\u@@ܮԖLmS l䁠'R$`þNQ }uƬVD]D`A]*vIC]5@ID P5QUjlXpuq*F:}4(֓Ч@E]8WT 0[tieD^ _/s[HhƲZ#\)S[ xNL_<$Y_W,K/@ T{W(G+ V~PtBI}z?=5Ff*ުRDF Hy\J4zqq䭾 Q!o-Г̍Z.AUyO$d 㿕. P"iIrU7o~=*Ru5]2+2څBq6H"z|LJ=Fz MXTB+G{KqzHV&?s]\z6i oŖyBwE zU#Z &nK+X4)& @bOYtЃݫJJvGS*W {ac_C`Sj~%ܠM jR s&Nm@y{8ϣLLoҨeZBpꆪg((*GئMV-[?lʒ>^3v/DҸԆcr)J ĬgoDJ})9̕_"qr+dISG":U|rgԭ\*"{,(A'*B`/i4÷Ot@V_"Bmw|u Vu jø/O_3,nS^ln\o7Qpd"эN`1teɚO?^':(rh+j +mVe s{|Wo-bةdVJ! iinxv7U$ՎtJd%lEW ub- ^ ŕ$UX41_ЅhB[OT's0 HwMXJtu?۞ʓ P ,@}2MVq_r8=)FPq)Rm~:WW04DkwVCY׼"xc$Sڕx5EWv~1D`})q]- aUTpT c-@\CMܨ_:{Ĭ}Q7/U8T^ \SI|Fu )3o }io^B+J]ӻ|ZZ݈0DD_MaRܦJ ZY50U;pz FIUJ䕂c;|?C+AlU* (8]a?\gF=iӮGEL]*"<d:֯[}O;{(%Zs٪-:pfg RX7Uǣk%ŻIݭ %s! UXN\'ѥ0뷳۽:}.gY1T3#JY{*V09 ӓSo 4*jZJ~ajUC c `%HE[n3*~Z/ʱ HW@s1]>}w /)d H 1\jjUݨ;S)U2Ẍq 4*m>[`xzd[ I0A\ c8ݨ;PK<(.ީ[2~hA9itr=C?{c]gq{5R1|^ ~!/O󌿾VR/a-OoO}َAZOьj&, VIaЙ=(!!A#%؎IЄQr NIwh_Lc1~2sEqG+zF]N/p#f\W~JY"BihcwMP|Ss޷ӈl*$*J2j%: wGt{P)*){5#'Pqޞs|@C_̨T{uN=| / h٧jU ;mNޙ{CY%(ӑ\GE* vUj åDU-ׁ.!ۧ^%b OHTVDA(hTARƓ<ߪDS֑BU;M]FgoGxEQ _P%_틋u͚if-%`%6ϧ`$QQjP =V&Q*RzU7k$z jI]ZE( )*ׁ,4aaCPohKI!iP ;VAzSQIӦg&N]ޣ5cDicVS귕]۔ԩxUB% O/ah:GɈ %ܶZ3S7t_T<)MZ)OpZ*P]诼 dٯ%K/K'̀nR~_!YA@o@l ҆16t {*+pw!ɘG_5/5nUU$=byZ.pfu)d Z*}P?zq'TȮu/T:B gE5~IʍtJ$6^NjW-QL3a˦_ %~-S4kRU ėo۰ED(((]6eZx njmOJJCtE&PTNhw0o!KGţWMC:EOWh GUUXE }=;j`S5u|!)BV$=e{k(YÔ,s]4ї_z:5=uS]PlRG$:PIO3ns~Ojӧ!V^t"Hc?`5z"w[Ԧ{5'?`d]eJ+!Smc/'Nǻ#nQ*{r%FHFW1*zy9tOxX:*~*}ީާ[vCR\tS;jz5eO4~,'^(B>biRl:cj3 A2~eBXc҄痽hR%74|yӉxq!u 5lEyEOf4XЬI?Uc\ƨt۟*( 1ޝTVMٿ +f=&\K.+S~X_\PzJ4ju1MkxH4VVȢ(7a,pFܱJP]aUheBFSѕSſgzN`?c%x}(2&J9 6K/xi(U'h:1mZĪ$sN'_u=Sy9n@tS.:ZϤgV&MfK?BH|lnXSskL bj})% LcrV0<7LO:$F*iQbJe|ďqJcJ:孯wAYVIWګHV ԱU<+ju \U8J҄&Q*%VQU*MiX!qYGzWI$zPƯue'Rb{sd"n Qk((-يCnŏ)piү# V_QXr! viZ;* k ZR% `S1&_tpߏA_>>rGϤ?")PZu+UIﳺS^S;UTttܱXC:Oo[2?q..*oyc$<UKZD9Tq*PU` Pzʫ ZZ$}ݾ2^4MA TWpV]GR[5BQ)`w_Kj^<ْR_ܧ \&z0k@Myui,|m[_A?Eǟ^Fʫv{7UrFPbQPFvn֯ϬRʂ?}KYc i \1j _| Tt=zO >jJLC@TʕpY\,ɱjH GhT%H.]U 15iSː"Y2e uoS䓨 )gCeH @O~AӨ &{er9œob|DT:ĭT!j/|8aRHuJm:.&4?O]/r u 59JLjWҞ5̮<:&T2L[;qA|IeI߆)~(\QN5Νwuҭ[=t_fPT&*NQtudϷ[5U-4F|Mq]iR|iC}oj6jYtJ^S[=񨶛`Ϯciz*٪}DlBݳ@?WM$E1arV1+ԑ>g}6kCteatK=MtLvU#V.H̠*Fw5+бxgU$w-/T˞_v_U8^^K/OX&ЮDeT+yWRΏ!Ĩ8ǂ:9)9#)TE⋔*]1*%T y R<Ÿ B.GO[|Ɠ?,.PvZD*zМpѾ 厰^cG|V ULXCsr^g_I43 :I@k=9Ç˾E3-jP'S}}uIZ_6>M)8MK8J)e"qJ)1:"X;<1wci J:h+[0Q+%*T96h7ӲDOcO@tRI j>vCm5]MGK67kW6M022_UnS^a6-*cd*ДxS eJ5PIESw)[xOaS]|p GygͼŢ+,&s4/A,;ӓ"XQ9XECśKM7Y8+& c_SIQSe`o$k$ uߔaOKց׽l;UDiq_cƼS% V3Wd6pA6X,hPWvݎ]Zp1Ub<|[{S5jZu`n6\{^(VTunTMj+C?̺+Q)(\kY6M{,ќ2榕7YrKzWv-^47Bm0]xmšo$)l T `jNmZ'9jMJ`@]ws |bH}tR:e<82G r9ZLL .ַKȰҬ:[vV{;^>Bq J`{s#ƉQk-oC?quXuC#OO'vC7^;#B]QPĥTwo:P( jm{:l`VUw0jcVw]!OWض5v ܪg]?DŪB.jlA~ SR>'!#jD5˰ȠKM ,@*<{-{\mű;V&rvh:0r3&di1 3C^ȩ?0/5\3Dl`~ğ5^qYbGTiғA1c?_ߟ.pX4L%KuV .?E0Mx3]`ߒ```2̳Y| tc/ Xs]@C5yۛqZ-3HNIȷGQϠ&fx&kV9$ )/Ҙ?>s;uNʝ`$ԱС8CYvv;Mh|_R2j%]٦s q|-Ͳo^[%9u낻y Wo,?Y+itGbI95][)D/1'0y4/<f"8}yA ^C+&M Of 2z_GxheLCT0)pwԜ,LI0xIbW*eq $|i"sG750.I_A(JB:S_3ۙ삌{9"]}8 4(uu>NDׯ =ɾ NniGaxY*IcP?gq>hl^^ǟuLǯ-Œbx[0GO,BfT]yM;@rU.5y;4aWq߼?{ ٙz'z70?"qPJMHoL[zRxRu`̭8:LSC[RߖfZoڢ |ϓ*z:PagzTg_ϳ^U_ů-$# b;k1|O=20( \0sv7>'׾ #xE`ώŴcG\'Oz^B|oz= TO6Gr2u5*4BA{!N(M$ck5tQO_"q]j?o6"k>N_`0SeԍXeܲA}Of ro{\d)v5!˕dp$4X̳8]6{{zQ/mK JOYrdœg~&Xj˂Mڳ&B|17y~7Ѽ r_!'6$.i0O~ktlOMrH!%J5?!"\J;pUn Ndl"N;Mh7L]DOVrWw\4!7ҲpKrޖs0r}U?t xlF~34nJ`!?{rvjㅳ4:PS9Or'gT:rKD9E}(UU&6܍1)BOƦlo_J_K;dNHveG29ȝN򟯙fI!A:98u?}M4nF"Ůԥ38IyyޞusjW/ҹ>ä6I$Ot~;;>Q!8KCA2^փEdO[i+|WwJ< &Q]?<3d~Wm_Z_IK/Fnڢ,l27 (Gz\fUWB>Bio-SamTools-1.39/t/data/00README.txt000444001750001750 276212207676767 17077 0ustar00lsteinlstein000000000000The files dm3_3R_4766911_4767130.* are a spliced alignments from an RNASeq experiment (40bp Illumina single end) measuring alternative splicing in fly. They align with chromosome 3R (genome build: dm3) spanning a region holding a small (3nt) exon on the gene 'skap' (CG11963). Some of the spliced alignments join three exons, and cross two introns; the CIGAR lines match /\d+M124N3M91N\d+M/, where the internal 3M is the 3bp exon. and the flanking 124N and 91N are the introns. NOTE: These files were copied from the examples directory in the Samtools distribution version 0.1.3. The original README follows. ORIGINAL 00README.txt File ex1.fa contains two sequences cut from the human genome build36. They were extracted with command: samtools faidx human_b36.fa 2:2043966-2045540 20:67967-69550 Sequence names were changed manually for simplicity. File ex1.sam.gz contains MAQ alignments exatracted with: (samtools view NA18507_maq.bam 2:2044001-2045500; samtools view NA18507_maq.bam 20:68001-69500) and processed with `samtools fixmate' to make it self-consistent as a standalone alignment. To try samtools, you may run the following commands: samtools faidx ex1.fa # index the reference FASTA samtools import ex1.fa.fai ex1.sam.gz ex1.bam # SAM->BAM samtools index ex1.bam # index BAM samtools tview ex1.bam ex1.fa # view alignment samtools pileup -cf ex1.fa ex1.bam # pileup and consensus samtools pileup -cf ex1.fa -t ex1.fa.fai ex1.sam.gz Bio-SamTools-1.39/c_bin000755001750001750 012207676767 14773 5ustar00lsteinlstein000000000000Bio-SamTools-1.39/c_bin/bam2bedgraph.c000444001750001750 436112207676767 17616 0ustar00lsteinlstein000000000000#include #include "sam.h" typedef struct { uint32_t ltid; int lstart,lcoverage,lpos,beg,end; samfile_t *in; } tmpstruct_t; // callback for bam_fetch() static int fetch_func(const bam1_t *b, void *data) { bam_plbuf_t *buf = (bam_plbuf_t*)data; bam_plbuf_push(b, buf); return 0; } // callback for bam_plbuf_init() static int pileup_func(uint32_t tid, uint32_t position, int n, const bam_pileup1_t *pl, void *data) { tmpstruct_t *tmp = (tmpstruct_t*)data; int pos = (int)position; int coverage = n; int i; for (i=0;iltid != tid || tmp->lcoverage != coverage || pos > tmp->lpos+1) { if (tmp->lpos > 0 && tmp->lcoverage > 0) printf("%s\t%d\t%d\t%d\n", tmp->in->header->target_name[tmp->ltid], tmp->lstart,tmp->lpos+1, tmp->lcoverage); tmp->ltid = tid; tmp->lstart = pos; tmp->lcoverage = coverage; } tmp->lpos = pos; return 0; } int main(int argc, char *argv[]) { tmpstruct_t tmp; if (argc == 1) { fprintf(stderr, "Usage: bam2bedgraph [region]\n\nCreate a BEDGraph file of genomic coverage. BAM file must be sorted.\n"); return 1; } tmp.beg = 0; tmp.end = 0x7fffffff; tmp.lstart = 0; tmp.lcoverage = 0; tmp.ltid = 0; tmp.lpos = 0; tmp.in = samopen(argv[1], "rb", 0); if (tmp.in == 0) { fprintf(stderr, "Fail to open BAM file %s\n", argv[1]); return 1; } if (argc == 2) { // if a region is not specified sampileup(tmp.in, -1, pileup_func, &tmp); } else { int ref; bam_index_t *idx; bam_plbuf_t *buf; idx = bam_index_load(argv[1]); // load BAM index if (idx == 0) { fprintf(stderr, "BAM indexing file is not available.\n"); return 1; } bam_parse_region(tmp.in->header, argv[2], &ref, &tmp.beg, &tmp.end); // parse the region if (ref < 0) { fprintf(stderr, "Invalid region %s\n", argv[2]); return 1; } buf = bam_plbuf_init(pileup_func, &tmp); // initialize pileup bam_fetch(tmp.in->x.bam, idx, ref, tmp.beg, tmp.end, buf, fetch_func); bam_plbuf_push(0, buf); // finalize pileup bam_index_destroy(idx); bam_plbuf_destroy(buf); } printf("%s\t%d\t%d\t%d\n", tmp.in->header->target_name[tmp.ltid], tmp.lstart,tmp.lpos+1, tmp.lcoverage); samclose(tmp.in); return 0; } Bio-SamTools-1.39/c_bin/makefile000444001750001750 61512207676767 16612 0ustar00lsteinlstein000000000000CC= gcc CFLAGS= -g -Wall -O2 -fPIC DFLAGS= -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_USE_KNETFILE -D_CURSES_LIB=1 INCLUDES= LIBPATH= PROG= bam2bedgraph .SUFFIXES:.c .o .PHONY: all lib .c.o: $(CC) -c $(CFLAGS) $(DFLAGS) $(INCLUDES) $< -o $@ all:$(PROG) bam2bedgraph: bam2bedgraph.o $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBPATH) -lbam -lpthread -lm -lz clean: rm -f *.o $(PROG)